diff --git a/.config/ast-grep/rule-tests/no-context-test.yml b/.config/ast-grep/rule-tests/no-context-test.yml new file mode 100644 index 0000000000000..ed8ebf148087b --- /dev/null +++ b/.config/ast-grep/rule-tests/no-context-test.yml @@ -0,0 +1,11 @@ +id: no-context +valid: + - "let chunking_context = ChunkingContext::new();" + - "struct Foo { chunking_context: Context };" + - "foo(|chunking_context| context)" + - "fn foo(chunking_context: ChunkingContext) -> u32 { 5 };" +invalid: + - "let context = ChunkingContext::new();" + - "struct Foo { context: Context };" + - "foo(|context| context)" + - "fn foo(context: ChunkingContext) -> u32 { 5 };" diff --git a/examples/with-angular/apps/docs/src/assets/.gitkeep b/.config/ast-grep/rule-utils/.gitkeep similarity index 100% rename from examples/with-angular/apps/docs/src/assets/.gitkeep rename to .config/ast-grep/rule-utils/.gitkeep diff --git a/.config/ast-grep/rules/no-context.yml b/.config/ast-grep/rules/no-context.yml new file mode 100644 index 0000000000000..92df0364b2721 --- /dev/null +++ b/.config/ast-grep/rules/no-context.yml @@ -0,0 +1,35 @@ +id: no-context +message: Don't name variables `context`. +note: Use a more specific name, such as chunking_context, asset_context, etc. +severity: error +language: Rust +rule: + regex: \bcontext\b + any: + - all: + - inside: + any: + - kind: closure_parameters + - kind: parameter + - kind: function_item + - kind: let_declaration + - kind: identifier + - all: + - kind: field_identifier + - inside: + kind: field_declaration +ignores: + - "./crates/turbopack-css/**" + - "./crates/turbopack-dev-server/**" + - "./crates/turbopack-browser/**" + - "./crates/turbopack-ecmascript-hmr-protocol/**" + - "./crates/turbopack-ecmascript-plugins/**" + - "./crates/turbopack-ecmascript-runtime/**" + - "./crates/turbopack-json/**" + - "./crates/turbopack-mdx/**" + - "./crates/turbopack-node/**" + - "./crates/turbopack-static/**" + - "./crates/turbopack-tests/**" + - "./crates/turbopack/**" + - "./crates/turborepo-cache/**" + - "./crates/turborepo-scm/**" diff --git a/.config/nextest.toml b/.config/nextest.toml new file mode 100644 index 0000000000000..f0ce903755ccf --- /dev/null +++ b/.config/nextest.toml @@ -0,0 +1,17 @@ +[profile.tp-test-linux.junit] +path = "junit.xml" +report-name = "Turbopack tests (Linux)" +store-success-output = true +store-failure-output = true + +[profile.tp-test-mac.junit] +path = "junit.xml" +report-name = "Turbopack tests (Mac)" +store-success-output = true +store-failure-output = true + +[profile.tp-test-win.junit] +path = "junit.xml" +report-name = "Turbopack tests (Windows)" +store-success-output = true +store-failure-output = true \ No newline at end of file diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 3c0db6643ee3c..0000000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/go/.devcontainer/base.Dockerfile - -# [Choice] Go version (use -bullseye variants on local arm64/Apple Silicon): 1, 1.16, 1.17, 1-bullseye, 1.16-bullseye, 1.17-bullseye, 1-buster, 1.16-buster, 1.17-buster -ARG VARIANT="1.18-bullseye" -FROM mcr.microsoft.com/vscode/devcontainers/go:0-${VARIANT} - -RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends \ - # Chromium for running Turbopack benchmarks - chromium \ - # Used for plotters graph visualizations in turbopack benchmarks - libfontconfig1-dev - -# Add hyperfine, a useful benchmarking tool -RUN dpkgArch="$(dpkg --print-architecture)"; \ - wget "https://github.com/sharkdp/hyperfine/releases/download/v1.12.0/hyperfine_1.12.0_${dpkgArch}.deb" && dpkg -i "hyperfine_1.12.0_${dpkgArch}.deb" - -# -# Everything below is run as the vscode user. If superuser permissions are necessary, -# run it before this. Otherwise, prefer running as the vscode user. -# -USER vscode - -# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 -ARG NODE_VERSION="none" -RUN if [ "${NODE_VERSION}" != "none" ]; then umask 0002 && sh -c ". /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION}" 2>&1; fi - -RUN sh -c ". /usr/local/share/nvm/nvm.sh && npm install -g vercel yarn yalc pnpm nodemon" 2>&1 - -# The installer from https://rustup.rs/ homepage, with the following changes: -# * `-y` to accept without interactivity -# * `--default-toolchain none` to avoid installing stable rust. Our specific toolchain is installed post-create. -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index b829f934fbb3c..0000000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,52 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/go -{ - "name": "turbo (go, node, rust)", - "build": { - "dockerfile": "Dockerfile", - "args": { - // Update the VARIANT arg to pick a version of Go: 1, 1.18, 1.17 - // Append -bullseye or -buster to pin to an OS version. - // Use -bullseye variants on local arm64/Apple Silicon. - "VARIANT": "1.18-bullseye", - // Options - "NODE_VERSION": "lts/*" - } - }, - "runArgs": [ - "--cap-add=SYS_PTRACE", - "--security-opt", - "seccomp=unconfined" - ], - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "bradlc.vscode-tailwindcss", - "christian-kohler.npm-intellisense", - "dbaeumer.vscode-eslint", - "eamodio.gitlens", - "EditorConfig.EditorConfig", - "esbenp.prettier-vscode", - "github.copilot", - "github.vscode-pull-request-github", - "golang.go", - "heybourn.headwind", - "rust-lang.rust-analyzer", - "silvenon.mdx", - "windmilleng.vscode-go-autotest", - "yzhang.markdown-all-in-one" - ], - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "cargo --version", - // Invoking `cargo` will eagerly install the toolchain specified in rust-toolchain file - - // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode", - "features": { - "docker-in-docker": "latest", - "git": "latest", - "github-cli": "latest" - } -} diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 6b84715c4a3a6..0000000000000 --- a/.editorconfig +++ /dev/null @@ -1,24 +0,0 @@ -# http://editorconfig.org -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_size = 2 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true - -[*.t] -trim_trailing_whitespace = false - -[Makefile] -indent_style = tab - -[{go.mod,go.sum,*.go}] -indent_style = tab - -[*.rs] -# Keep in sync with rustfmt -max_line_length = 100 -indent_size = 4 diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index ae34fcb7810d7..0000000000000 --- a/.eslintignore +++ /dev/null @@ -1,12 +0,0 @@ -node_modules/ -target/ -.next/ -build/ -dist/ - -/examples/ - -packages/eslint-plugin-turbo/__fixtures__ -packages/create-turbo/templates -crates/*/tests/** -crates/*/js/src/compiled diff --git a/.github/.kodiak.toml b/.github/.kodiak.toml deleted file mode 100644 index 2b2959eaee4a8..0000000000000 --- a/.github/.kodiak.toml +++ /dev/null @@ -1,39 +0,0 @@ -# .kodiak.toml -version = 1 - -[merge] -automerge_label = "pr: automerge" -require_automerge_label = true -blocking_labels = ["pr: fixship", "pr: on hold", "pr: work in progress"] -method = "squash" -delete_branch_on_merge = true -optimistic_updates = true -prioritize_ready_to_merge = true -notify_on_conflict = false - -[update] -# https://kodiakhq.com/docs/config-reference#updatealways -# always "update" (i.e. merge main branch into PR), if it has the automerge_label. -# Without this, only branches that are passing CI will get updated. -# The benefit of this config is that PRs that we want to automerge, but -# have failed because the test suite is flaky will get stuck, unless someone -# presses the Update Branch button manually, or re-triggers the GitHub workflow -# for tests again. This causes delays in getting easy PRs in. -always = true - -# https://kodiakhq.com/docs/config-reference#updateautoupdate_label -# PRs will get updates from the base branch (i.e. usually `main`) -# when this label is applied. This is different from "update=always" -# config, which only applies to PRs that have been tagged with for auto_merging_ -# (i.e. PRs with the "pr: automerge" label, which is configured above). -# This label allows PR authors to keep their PR branch up-to-date without -# opting into Kodiak's automerge feature. This is useful if you want to use -# GitHub's AutoMerge feature instead. -autoupdate_label = "pr: autoupdate" - -[merge.message] -title = "pull_request_title" -include_coauthors= true -include_pr_number = true -body_type = "markdown" -strip_html_comments = true diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index a72a74286e30d..0000000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,7 +0,0 @@ -# Learn how to add code owners here: -# https://help.github.com/en/articles/about-code-owners - -* @vercel/turbo-oss - -# Shared docs (team specific overrides below) -/docs @vercel/turbo-oss @anthonyshew diff --git a/.github/DISCUSSION_TEMPLATE/help.yml b/.github/DISCUSSION_TEMPLATE/help.yml deleted file mode 100644 index 6d32d10a4601c..0000000000000 --- a/.github/DISCUSSION_TEMPLATE/help.yml +++ /dev/null @@ -1,20 +0,0 @@ -body: - - type: textarea - attributes: - label: Summary - description: What do you need help with? - validations: - required: true - - type: textarea - attributes: - label: Additional information - description: Any code snippets, error messages, or dependency details that may be related? - render: js - validations: - required: false - - type: input - attributes: - label: Example - description: A link to a minimal reproduction is helpful for collaborative debugging! - validations: - required: false diff --git a/.github/DISCUSSION_TEMPLATE/ideas.yml b/.github/DISCUSSION_TEMPLATE/ideas.yml deleted file mode 100644 index 9beccc6d519b4..0000000000000 --- a/.github/DISCUSSION_TEMPLATE/ideas.yml +++ /dev/null @@ -1,33 +0,0 @@ -body: - - type: textarea - attributes: - label: Goals - description: Short list of the problems that the feature request aims to address. - value: | - 1. - 2. - 3. - validations: - required: true - - type: textarea - attributes: - label: Non-goals - description: Short list of what the feature request _does not_ aim to address. - value: | - 1. - 2. - 3. - validations: - required: false - - type: textarea - attributes: - label: Background - description: Discuss prior art and provide context around your idea. Why do you think this feature is needed? Are there current alternatives? - validations: - required: true - - type: textarea - attributes: - label: Proposal - description: How should this feature be implemented? Are you interested in contributing? - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/0-turborepo-bug-report.yml b/.github/ISSUE_TEMPLATE/0-turborepo-bug-report.yml deleted file mode 100644 index a70caf7a46d25..0000000000000 --- a/.github/ISSUE_TEMPLATE/0-turborepo-bug-report.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: Turborepo bug report -description: Create a bug report -labels: ["kind: bug", "needs: triage"] - -body: - - type: markdown - attributes: - value: | - This template is to report bugs. Before opening a new issue, please do a [search](https://github.com/vercel/turborepo/issues) of existing issues and :+1: upvote the existing issue instead. This will result in a quicker resolution. - - If you need help with your own project, you can: - - Start a discussion in the ["Help" section](https://github.com/vercel/turborepo/discussions/categories/help). - - Ask a question in [the Turbo Discord server](https://turbo.build/discord). - - - type: checkboxes - attributes: - label: Verify canary release - description: "Please install the canary version of `turbo` (e.g. `npm install turbo@canary`) to try the canary version of Turborepo. It includes all features and fixes that have not been released to the stable version yet. Some issues may already be fixed in the canary version, so please verify that your issue reproduces before opening a new issue." - options: - - label: I verified that the issue exists in the latest Turborepo canary release. - required: true - - - type: input - attributes: - label: Link to code that reproduces this issue - description: | - A link to a **public** GitHub repository with a minimal reproduction. Ideally, minimal reproductions should be created using [`npx create-turbo@canary -e with-shell-commands`](https://github.com/vercel/turborepo/tree/main/examples/with-shell-commands) and should include only changes that contribute to the issue. You may also use [`npx create-turbo@canary -e `](https://github.com/vercel/turborepo/tree/main/examples) to create a reproduction that includes frameworks if you believe your bug requires a specific framework to reproduce. - validations: - required: true - - - type: input - attributes: - label: Which canary version will you have in your reproduction? - description: | - To find the exact version installed in your reproduction, you can use `npm list turbo`, `yarn why turbo`, or `pnpm why turbo`. - validations: - required: true - - - type: textarea - attributes: - label: Enviroment information - render: block - description: | - Run the command `turbo info` and paste its output here. Please review it in case there is sensitive information you don't want to share. - - - type: textarea - attributes: - label: Expected behavior - description: | - A clear and concise description of what you expected to happen. - validations: - required: true - - - type: textarea - attributes: - label: Actual behavior - description: | - A clear and concise description of the bug. - validations: - required: true - - - type: textarea - attributes: - label: To Reproduce - description: | - Steps to reproduce the unexpected behavior. Please provide clear code snippets that always reproduces the issue or a GitHub repository. Screenshots can be provided in "Additional context" below. - validations: - required: true - - - type: markdown - attributes: - value: | - Another way you can help the maintainers is to pinpoint the `canary` version of `turbo` that introduced the issue. Check out our [releases](https://github.com/vercel/turborepo/releases), and try to find the first `canary` release that introduced the issue. While not required, this will help us narrow down the scope of the issue, and possibly point to the PR/code change that introduced it. You can install a specific version of `turbo` by running `npm install turbo@`. - - type: textarea - attributes: - label: Additional context - description: | - Any extra information that might help us investigate. For example, where are you deploying your application (Vercel, Docker, other platform)? Is it only reproducible on that platform, or locally too? Is the issue only happening in a specific browser? etc. - placeholder: | - I tested my reproduction against different canary releases, and the first one that introduced the bug was "2.2.4-canary.2", since reverting to "2.3.4-canary.1" works. - or - I am using GitHub Actions but running my tasks locally does not have the same issue. diff --git a/.github/ISSUE_TEMPLATE/1-docs.yml b/.github/ISSUE_TEMPLATE/1-docs.yml deleted file mode 100644 index 4d145e2ceb5ae..0000000000000 --- a/.github/ISSUE_TEMPLATE/1-docs.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: "Documentation update or improvement" -description: A request to update or improve documentation -title: "📚 Docs: " -labels: - - "area: docs" -body: - - type: markdown - attributes: - value: Before opening this issue to request a docs improvement, is this something you can help us with? Your contributions are welcomed and appreciated. - - type: markdown - attributes: - value: Thank you for helping us improve the docs! - - type: textarea - attributes: - label: What is the improvement or update you wish to see? - description: "Example: I would like to see more examples of how to use `turbo run`. Or, the `turbo run` docs are missing information." - validations: - required: true - - type: textarea - attributes: - label: Is there any context that might help us understand? - description: A clear description of any added context that might help us understand. - validations: - required: true - - type: input - attributes: - label: Does the docs page already exist? Please link to it. - description: "Example: https://turbo.build/repo/docs/reference/command-line-reference/run" - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 92e9ccf5bfc91..0000000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,11 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Turbopack in Next.js Bug Report - url: https://github.com/vercel/next.js/issues/new?assignees=&labels=template%3A+bug&projects=&template=1.bug_report.yml - about: Create a Next.js bug report for the Turbopack team - - name: Ask for help - url: https://github.com/vercel/turborepo/discussions/new?category=help - about: Need to ask a question? Get help from the community. - - name: Submit an idea - url: https://github.com/vercel/turborepo/discussions/new?category=ideas - about: Make feature requests and suggest improvements. diff --git a/.github/actions/cargo-sweep/.eslintignore b/.github/actions/cargo-sweep/.eslintignore deleted file mode 100644 index 06c5e16854a00..0000000000000 --- a/.github/actions/cargo-sweep/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist/** diff --git a/.github/actions/cargo-sweep/.eslintrc.js b/.github/actions/cargo-sweep/.eslintrc.js deleted file mode 100644 index 4ca761e2f8eb5..0000000000000 --- a/.github/actions/cargo-sweep/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], -}; diff --git a/.github/actions/cargo-sweep/.gitignore b/.github/actions/cargo-sweep/.gitignore deleted file mode 100644 index af18ca9559d21..0000000000000 --- a/.github/actions/cargo-sweep/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!dist/ diff --git a/.github/actions/cargo-sweep/action.yml b/.github/actions/cargo-sweep/action.yml deleted file mode 100644 index 53b624b466a1d..0000000000000 --- a/.github/actions/cargo-sweep/action.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: "cargo-sweep" -description: "Runs cargo-sweep to clean old build artifacts" -runs: - using: "node20" - main: "dist/main/index.js" - post: "dist/post/index.js" diff --git a/.github/actions/cargo-sweep/dist/main/index.js b/.github/actions/cargo-sweep/dist/main/index.js deleted file mode 100644 index 125b5e61434e7..0000000000000 --- a/.github/actions/cargo-sweep/dist/main/index.js +++ /dev/null @@ -1,4157 +0,0 @@ -require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ 925: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const core = __nccwpck_require__(363); -const exec = __nccwpck_require__(141); - -async function runSweep(...args) { - // TODO(alexkirsz) A cargo change introduced a regression where cargo can't - // find the sweep binary. This is a temporary workaround until the fix is - // released. See: - // https://github.com/rust-lang/cargo/pull/11814 - await exec.exec("cargo-sweep", ["sweep", ...args]); -} - -async function storeTimestamp() { - await core.group("Storing timestamp to compare later", () => - runSweep("--stamp") - ); - - core.info("Timestamp stored in `sweep.timestamp`"); -} - -async function sweep() { - await core.group("Cleaning old build artifacts", () => runSweep("--file")); - - core.info("Removed old build artifacts."); -} - -module.exports = { - storeTimestamp, - sweep, -}; - - -/***/ }), - -/***/ 255: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.issue = exports.issueCommand = void 0; -const os = __importStar(__nccwpck_require__(37)); -const utils_1 = __nccwpck_require__(393); -/** - * Commands - * - * Command Format: - * ::name key=value,key=value::message - * - * Examples: - * ::warning::This is the message - * ::set-env name=MY_VAR::some value - */ -function issueCommand(command, properties, message) { - const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os.EOL); -} -exports.issueCommand = issueCommand; -function issue(name, message = '') { - issueCommand(name, {}, message); -} -exports.issue = issue; -const CMD_STRING = '::'; -class Command { - constructor(command, properties, message) { - if (!command) { - command = 'missing.command'; - } - this.command = command; - this.properties = properties; - this.message = message; - } - toString() { - let cmdStr = CMD_STRING + this.command; - if (this.properties && Object.keys(this.properties).length > 0) { - cmdStr += ' '; - let first = true; - for (const key in this.properties) { - if (this.properties.hasOwnProperty(key)) { - const val = this.properties[key]; - if (val) { - if (first) { - first = false; - } - else { - cmdStr += ','; - } - cmdStr += `${key}=${escapeProperty(val)}`; - } - } - } - } - cmdStr += `${CMD_STRING}${escapeData(this.message)}`; - return cmdStr; - } -} -function escapeData(s) { - return utils_1.toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A'); -} -function escapeProperty(s) { - return utils_1.toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A') - .replace(/:/g, '%3A') - .replace(/,/g, '%2C'); -} -//# sourceMappingURL=command.js.map - -/***/ }), - -/***/ 363: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(255); -const file_command_1 = __nccwpck_require__(189); -const utils_1 = __nccwpck_require__(393); -const os = __importStar(__nccwpck_require__(37)); -const path = __importStar(__nccwpck_require__(17)); -const oidc_utils_1 = __nccwpck_require__(226); -/** - * The code to exit an action - */ -var ExitCode; -(function (ExitCode) { - /** - * A code indicating that the action was successful - */ - ExitCode[ExitCode["Success"] = 0] = "Success"; - /** - * A code indicating that the action was a failure - */ - ExitCode[ExitCode["Failure"] = 1] = "Failure"; -})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); -//----------------------------------------------------------------------- -// Variables -//----------------------------------------------------------------------- -/** - * Sets env variable for this action and future actions in the job - * @param name the name of the variable to set - * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function exportVariable(name, val) { - const convertedVal = utils_1.toCommandValue(val); - process.env[name] = convertedVal; - const filePath = process.env['GITHUB_ENV'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); - } - command_1.issueCommand('set-env', { name }, convertedVal); -} -exports.exportVariable = exportVariable; -/** - * Registers a secret which will get masked from logs - * @param secret value of the secret - */ -function setSecret(secret) { - command_1.issueCommand('add-mask', {}, secret); -} -exports.setSecret = setSecret; -/** - * Prepends inputPath to the PATH (for this action and future actions) - * @param inputPath - */ -function addPath(inputPath) { - const filePath = process.env['GITHUB_PATH'] || ''; - if (filePath) { - file_command_1.issueFileCommand('PATH', inputPath); - } - else { - command_1.issueCommand('add-path', {}, inputPath); - } - process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; -} -exports.addPath = addPath; -/** - * Gets the value of an input. - * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. - * Returns an empty string if the value is not defined. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string - */ -function getInput(name, options) { - const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; - if (options && options.required && !val) { - throw new Error(`Input required and not supplied: ${name}`); - } - if (options && options.trimWhitespace === false) { - return val; - } - return val.trim(); -} -exports.getInput = getInput; -/** - * Gets the values of an multiline input. Each value is also trimmed. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string[] - * - */ -function getMultilineInput(name, options) { - const inputs = getInput(name, options) - .split('\n') - .filter(x => x !== ''); - if (options && options.trimWhitespace === false) { - return inputs; - } - return inputs.map(input => input.trim()); -} -exports.getMultilineInput = getMultilineInput; -/** - * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. - * Support boolean input list: `true | True | TRUE | false | False | FALSE` . - * The return value is also in boolean type. - * ref: https://yaml.org/spec/1.2/spec.html#id2804923 - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns boolean - */ -function getBooleanInput(name, options) { - const trueValue = ['true', 'True', 'TRUE']; - const falseValue = ['false', 'False', 'FALSE']; - const val = getInput(name, options); - if (trueValue.includes(val)) - return true; - if (falseValue.includes(val)) - return false; - throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + - `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); -} -exports.getBooleanInput = getBooleanInput; -/** - * Sets the value of an output. - * - * @param name name of the output to set - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function setOutput(name, value) { - const filePath = process.env['GITHUB_OUTPUT'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); - } - process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); -} -exports.setOutput = setOutput; -/** - * Enables or disables the echoing of commands into stdout for the rest of the step. - * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. - * - */ -function setCommandEcho(enabled) { - command_1.issue('echo', enabled ? 'on' : 'off'); -} -exports.setCommandEcho = setCommandEcho; -//----------------------------------------------------------------------- -// Results -//----------------------------------------------------------------------- -/** - * Sets the action status to failed. - * When the action exits it will be with an exit code of 1 - * @param message add error issue message - */ -function setFailed(message) { - process.exitCode = ExitCode.Failure; - error(message); -} -exports.setFailed = setFailed; -//----------------------------------------------------------------------- -// Logging Commands -//----------------------------------------------------------------------- -/** - * Gets whether Actions Step Debug is on or not - */ -function isDebug() { - return process.env['RUNNER_DEBUG'] === '1'; -} -exports.isDebug = isDebug; -/** - * Writes debug message to user log - * @param message debug message - */ -function debug(message) { - command_1.issueCommand('debug', {}, message); -} -exports.debug = debug; -/** - * Adds an error issue - * @param message error issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function error(message, properties = {}) { - command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); -} -exports.error = error; -/** - * Adds a warning issue - * @param message warning issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function warning(message, properties = {}) { - command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); -} -exports.warning = warning; -/** - * Adds a notice issue - * @param message notice issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function notice(message, properties = {}) { - command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); -} -exports.notice = notice; -/** - * Writes info to log with console.log. - * @param message info message - */ -function info(message) { - process.stdout.write(message + os.EOL); -} -exports.info = info; -/** - * Begin an output group. - * - * Output until the next `groupEnd` will be foldable in this group - * - * @param name The name of the output group - */ -function startGroup(name) { - command_1.issue('group', name); -} -exports.startGroup = startGroup; -/** - * End an output group. - */ -function endGroup() { - command_1.issue('endgroup'); -} -exports.endGroup = endGroup; -/** - * Wrap an asynchronous function call in a group. - * - * Returns the same type as the function itself. - * - * @param name The name of the group - * @param fn The function to wrap in the group - */ -function group(name, fn) { - return __awaiter(this, void 0, void 0, function* () { - startGroup(name); - let result; - try { - result = yield fn(); - } - finally { - endGroup(); - } - return result; - }); -} -exports.group = group; -//----------------------------------------------------------------------- -// Wrapper action state -//----------------------------------------------------------------------- -/** - * Saves state for current action, the state can only be retrieved by this action's post job execution. - * - * @param name name of the state to store - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function saveState(name, value) { - const filePath = process.env['GITHUB_STATE'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); - } - command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); -} -exports.saveState = saveState; -/** - * Gets the value of an state set by this action's main execution. - * - * @param name name of the state to get - * @returns string - */ -function getState(name) { - return process.env[`STATE_${name}`] || ''; -} -exports.getState = getState; -function getIDToken(aud) { - return __awaiter(this, void 0, void 0, function* () { - return yield oidc_utils_1.OidcClient.getIDToken(aud); - }); -} -exports.getIDToken = getIDToken; -/** - * Summary exports - */ -var summary_1 = __nccwpck_require__(874); -Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); -/** - * @deprecated use core.summary - */ -var summary_2 = __nccwpck_require__(874); -Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); -/** - * Path exports - */ -var path_utils_1 = __nccwpck_require__(88); -Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); -Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); -Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); -//# sourceMappingURL=core.js.map - -/***/ }), - -/***/ 189: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -// For internal use, subject to change. -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__nccwpck_require__(147)); -const os = __importStar(__nccwpck_require__(37)); -const uuid_1 = __nccwpck_require__(503); -const utils_1 = __nccwpck_require__(393); -function issueFileCommand(command, message) { - const filePath = process.env[`GITHUB_${command}`]; - if (!filePath) { - throw new Error(`Unable to find environment variable for file command ${command}`); - } - if (!fs.existsSync(filePath)) { - throw new Error(`Missing file at path: ${filePath}`); - } - fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { - encoding: 'utf8' - }); -} -exports.issueFileCommand = issueFileCommand; -function prepareKeyValueMessage(key, value) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - const convertedValue = utils_1.toCommandValue(value); - // These should realistically never happen, but just in case someone finds a - // way to exploit uuid generation let's not allow keys or values that contain - // the delimiter. - if (key.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedValue.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; -} -exports.prepareKeyValueMessage = prepareKeyValueMessage; -//# sourceMappingURL=file-command.js.map - -/***/ }), - -/***/ 226: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(882); -const auth_1 = __nccwpck_require__(362); -const core_1 = __nccwpck_require__(363); -class OidcClient { - static createHttpClient(allowRetry = true, maxRetry = 10) { - const requestOptions = { - allowRetries: allowRetry, - maxRetries: maxRetry - }; - return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); - } - static getRequestToken() { - const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; - if (!token) { - throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); - } - return token; - } - static getIDTokenUrl() { - const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; - if (!runtimeUrl) { - throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); - } - return runtimeUrl; - } - static getCall(id_token_url) { - var _a; - return __awaiter(this, void 0, void 0, function* () { - const httpclient = OidcClient.createHttpClient(); - const res = yield httpclient - .getJson(id_token_url) - .catch(error => { - throw new Error(`Failed to get ID Token. \n - Error Code : ${error.statusCode}\n - Error Message: ${error.result.message}`); - }); - const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; - if (!id_token) { - throw new Error('Response json body do not have ID Token field'); - } - return id_token; - }); - } - static getIDToken(audience) { - return __awaiter(this, void 0, void 0, function* () { - try { - // New ID Token is requested from action service - let id_token_url = OidcClient.getIDTokenUrl(); - if (audience) { - const encodedAudience = encodeURIComponent(audience); - id_token_url = `${id_token_url}&audience=${encodedAudience}`; - } - core_1.debug(`ID token url is ${id_token_url}`); - const id_token = yield OidcClient.getCall(id_token_url); - core_1.setSecret(id_token); - return id_token; - } - catch (error) { - throw new Error(`Error message: ${error.message}`); - } - }); - } -} -exports.OidcClient = OidcClient; -//# sourceMappingURL=oidc-utils.js.map - -/***/ }), - -/***/ 88: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; -const path = __importStar(__nccwpck_require__(17)); -/** - * toPosixPath converts the given path to the posix form. On Windows, \\ will be - * replaced with /. - * - * @param pth. Path to transform. - * @return string Posix path. - */ -function toPosixPath(pth) { - return pth.replace(/[\\]/g, '/'); -} -exports.toPosixPath = toPosixPath; -/** - * toWin32Path converts the given path to the win32 form. On Linux, / will be - * replaced with \\. - * - * @param pth. Path to transform. - * @return string Win32 path. - */ -function toWin32Path(pth) { - return pth.replace(/[/]/g, '\\'); -} -exports.toWin32Path = toWin32Path; -/** - * toPlatformPath converts the given path to a platform-specific path. It does - * this by replacing instances of / and \ with the platform-specific path - * separator. - * - * @param pth The path to platformize. - * @return string The platform-specific path. - */ -function toPlatformPath(pth) { - return pth.replace(/[/\\]/g, path.sep); -} -exports.toPlatformPath = toPlatformPath; -//# sourceMappingURL=path-utils.js.map - -/***/ }), - -/***/ 874: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; -const os_1 = __nccwpck_require__(37); -const fs_1 = __nccwpck_require__(147); -const { access, appendFile, writeFile } = fs_1.promises; -exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; -exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; -class Summary { - constructor() { - this._buffer = ''; - } - /** - * Finds the summary file path from the environment, rejects if env var is not found or file does not exist - * Also checks r/w permissions. - * - * @returns step summary file path - */ - filePath() { - return __awaiter(this, void 0, void 0, function* () { - if (this._filePath) { - return this._filePath; - } - const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; - if (!pathFromEnv) { - throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); - } - try { - yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); - } - catch (_a) { - throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); - } - this._filePath = pathFromEnv; - return this._filePath; - }); - } - /** - * Wraps content in an HTML tag, adding any HTML attributes - * - * @param {string} tag HTML tag to wrap - * @param {string | null} content content within the tag - * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add - * - * @returns {string} content wrapped in HTML element - */ - wrap(tag, content, attrs = {}) { - const htmlAttrs = Object.entries(attrs) - .map(([key, value]) => ` ${key}="${value}"`) - .join(''); - if (!content) { - return `<${tag}${htmlAttrs}>`; - } - return `<${tag}${htmlAttrs}>${content}`; - } - /** - * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. - * - * @param {SummaryWriteOptions} [options] (optional) options for write operation - * - * @returns {Promise} summary instance - */ - write(options) { - return __awaiter(this, void 0, void 0, function* () { - const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); - const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; - yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); - return this.emptyBuffer(); - }); - } - /** - * Clears the summary buffer and wipes the summary file - * - * @returns {Summary} summary instance - */ - clear() { - return __awaiter(this, void 0, void 0, function* () { - return this.emptyBuffer().write({ overwrite: true }); - }); - } - /** - * Returns the current summary buffer as a string - * - * @returns {string} string of summary buffer - */ - stringify() { - return this._buffer; - } - /** - * If the summary buffer is empty - * - * @returns {boolen} true if the buffer is empty - */ - isEmptyBuffer() { - return this._buffer.length === 0; - } - /** - * Resets the summary buffer without writing to summary file - * - * @returns {Summary} summary instance - */ - emptyBuffer() { - this._buffer = ''; - return this; - } - /** - * Adds raw text to the summary buffer - * - * @param {string} text content to add - * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) - * - * @returns {Summary} summary instance - */ - addRaw(text, addEOL = false) { - this._buffer += text; - return addEOL ? this.addEOL() : this; - } - /** - * Adds the operating system-specific end-of-line marker to the buffer - * - * @returns {Summary} summary instance - */ - addEOL() { - return this.addRaw(os_1.EOL); - } - /** - * Adds an HTML codeblock to the summary buffer - * - * @param {string} code content to render within fenced code block - * @param {string} lang (optional) language to syntax highlight code - * - * @returns {Summary} summary instance - */ - addCodeBlock(code, lang) { - const attrs = Object.assign({}, (lang && { lang })); - const element = this.wrap('pre', this.wrap('code', code), attrs); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML list to the summary buffer - * - * @param {string[]} items list of items to render - * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) - * - * @returns {Summary} summary instance - */ - addList(items, ordered = false) { - const tag = ordered ? 'ol' : 'ul'; - const listItems = items.map(item => this.wrap('li', item)).join(''); - const element = this.wrap(tag, listItems); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML table to the summary buffer - * - * @param {SummaryTableCell[]} rows table rows - * - * @returns {Summary} summary instance - */ - addTable(rows) { - const tableBody = rows - .map(row => { - const cells = row - .map(cell => { - if (typeof cell === 'string') { - return this.wrap('td', cell); - } - const { header, data, colspan, rowspan } = cell; - const tag = header ? 'th' : 'td'; - const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); - return this.wrap(tag, data, attrs); - }) - .join(''); - return this.wrap('tr', cells); - }) - .join(''); - const element = this.wrap('table', tableBody); - return this.addRaw(element).addEOL(); - } - /** - * Adds a collapsable HTML details element to the summary buffer - * - * @param {string} label text for the closed state - * @param {string} content collapsable content - * - * @returns {Summary} summary instance - */ - addDetails(label, content) { - const element = this.wrap('details', this.wrap('summary', label) + content); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML image tag to the summary buffer - * - * @param {string} src path to the image you to embed - * @param {string} alt text description of the image - * @param {SummaryImageOptions} options (optional) addition image attributes - * - * @returns {Summary} summary instance - */ - addImage(src, alt, options) { - const { width, height } = options || {}; - const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); - const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML section heading element - * - * @param {string} text heading text - * @param {number | string} [level=1] (optional) the heading level, default: 1 - * - * @returns {Summary} summary instance - */ - addHeading(text, level) { - const tag = `h${level}`; - const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) - ? tag - : 'h1'; - const element = this.wrap(allowedTag, text); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML thematic break (
) to the summary buffer - * - * @returns {Summary} summary instance - */ - addSeparator() { - const element = this.wrap('hr', null); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML line break (
) to the summary buffer - * - * @returns {Summary} summary instance - */ - addBreak() { - const element = this.wrap('br', null); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML blockquote to the summary buffer - * - * @param {string} text quote text - * @param {string} cite (optional) citation url - * - * @returns {Summary} summary instance - */ - addQuote(text, cite) { - const attrs = Object.assign({}, (cite && { cite })); - const element = this.wrap('blockquote', text, attrs); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML anchor tag to the summary buffer - * - * @param {string} text link text/content - * @param {string} href hyperlink - * - * @returns {Summary} summary instance - */ - addLink(text, href) { - const element = this.wrap('a', text, { href }); - return this.addRaw(element).addEOL(); - } -} -const _summary = new Summary(); -/** - * @deprecated use `core.summary` - */ -exports.markdownSummary = _summary; -exports.summary = _summary; -//# sourceMappingURL=summary.js.map - -/***/ }), - -/***/ 393: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toCommandProperties = exports.toCommandValue = void 0; -/** - * Sanitizes an input into a string so it can be passed into issueCommand safely - * @param input input to sanitize into a string - */ -function toCommandValue(input) { - if (input === null || input === undefined) { - return ''; - } - else if (typeof input === 'string' || input instanceof String) { - return input; - } - return JSON.stringify(input); -} -exports.toCommandValue = toCommandValue; -/** - * - * @param annotationProperties - * @returns The command properties to send with the actual annotation command - * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 - */ -function toCommandProperties(annotationProperties) { - if (!Object.keys(annotationProperties).length) { - return {}; - } - return { - title: annotationProperties.title, - file: annotationProperties.file, - line: annotationProperties.startLine, - endLine: annotationProperties.endLine, - col: annotationProperties.startColumn, - endColumn: annotationProperties.endColumn - }; -} -exports.toCommandProperties = toCommandProperties; -//# sourceMappingURL=utils.js.map - -/***/ }), - -/***/ 141: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getExecOutput = exports.exec = void 0; -const string_decoder_1 = __nccwpck_require__(576); -const tr = __importStar(__nccwpck_require__(624)); -/** - * Exec a command. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param commandLine command to execute (can include additional args). Must be correctly escaped. - * @param args optional arguments for tool. Escaping is handled by the lib. - * @param options optional exec options. See ExecOptions - * @returns Promise exit code - */ -function exec(commandLine, args, options) { - return __awaiter(this, void 0, void 0, function* () { - const commandArgs = tr.argStringToArray(commandLine); - if (commandArgs.length === 0) { - throw new Error(`Parameter 'commandLine' cannot be null or empty.`); - } - // Path to tool to execute should be first arg - const toolPath = commandArgs[0]; - args = commandArgs.slice(1).concat(args || []); - const runner = new tr.ToolRunner(toolPath, args, options); - return runner.exec(); - }); -} -exports.exec = exec; -/** - * Exec a command and get the output. - * Output will be streamed to the live console. - * Returns promise with the exit code and collected stdout and stderr - * - * @param commandLine command to execute (can include additional args). Must be correctly escaped. - * @param args optional arguments for tool. Escaping is handled by the lib. - * @param options optional exec options. See ExecOptions - * @returns Promise exit code, stdout, and stderr - */ -function getExecOutput(commandLine, args, options) { - var _a, _b; - return __awaiter(this, void 0, void 0, function* () { - let stdout = ''; - let stderr = ''; - //Using string decoder covers the case where a mult-byte character is split - const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); - const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); - const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; - const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; - const stdErrListener = (data) => { - stderr += stderrDecoder.write(data); - if (originalStdErrListener) { - originalStdErrListener(data); - } - }; - const stdOutListener = (data) => { - stdout += stdoutDecoder.write(data); - if (originalStdoutListener) { - originalStdoutListener(data); - } - }; - const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); - const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); - //flush any remaining characters - stdout += stdoutDecoder.end(); - stderr += stderrDecoder.end(); - return { - exitCode, - stdout, - stderr - }; - }); -} -exports.getExecOutput = getExecOutput; -//# sourceMappingURL=exec.js.map - -/***/ }), - -/***/ 624: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.argStringToArray = exports.ToolRunner = void 0; -const os = __importStar(__nccwpck_require__(37)); -const events = __importStar(__nccwpck_require__(361)); -const child = __importStar(__nccwpck_require__(81)); -const path = __importStar(__nccwpck_require__(17)); -const io = __importStar(__nccwpck_require__(59)); -const ioUtil = __importStar(__nccwpck_require__(152)); -const timers_1 = __nccwpck_require__(512); -/* eslint-disable @typescript-eslint/unbound-method */ -const IS_WINDOWS = process.platform === 'win32'; -/* - * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. - */ -class ToolRunner extends events.EventEmitter { - constructor(toolPath, args, options) { - super(); - if (!toolPath) { - throw new Error("Parameter 'toolPath' cannot be null or empty."); - } - this.toolPath = toolPath; - this.args = args || []; - this.options = options || {}; - } - _debug(message) { - if (this.options.listeners && this.options.listeners.debug) { - this.options.listeners.debug(message); - } - } - _getCommandString(options, noPrefix) { - const toolPath = this._getSpawnFileName(); - const args = this._getSpawnArgs(options); - let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool - if (IS_WINDOWS) { - // Windows + cmd file - if (this._isCmdFile()) { - cmd += toolPath; - for (const a of args) { - cmd += ` ${a}`; - } - } - // Windows + verbatim - else if (options.windowsVerbatimArguments) { - cmd += `"${toolPath}"`; - for (const a of args) { - cmd += ` ${a}`; - } - } - // Windows (regular) - else { - cmd += this._windowsQuoteCmdArg(toolPath); - for (const a of args) { - cmd += ` ${this._windowsQuoteCmdArg(a)}`; - } - } - } - else { - // OSX/Linux - this can likely be improved with some form of quoting. - // creating processes on Unix is fundamentally different than Windows. - // on Unix, execvp() takes an arg array. - cmd += toolPath; - for (const a of args) { - cmd += ` ${a}`; - } - } - return cmd; - } - _processLineBuffer(data, strBuffer, onLine) { - try { - let s = strBuffer + data.toString(); - let n = s.indexOf(os.EOL); - while (n > -1) { - const line = s.substring(0, n); - onLine(line); - // the rest of the string ... - s = s.substring(n + os.EOL.length); - n = s.indexOf(os.EOL); - } - return s; - } - catch (err) { - // streaming lines to console is best effort. Don't fail a build. - this._debug(`error processing line. Failed with error ${err}`); - return ''; - } - } - _getSpawnFileName() { - if (IS_WINDOWS) { - if (this._isCmdFile()) { - return process.env['COMSPEC'] || 'cmd.exe'; - } - } - return this.toolPath; - } - _getSpawnArgs(options) { - if (IS_WINDOWS) { - if (this._isCmdFile()) { - let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; - for (const a of this.args) { - argline += ' '; - argline += options.windowsVerbatimArguments - ? a - : this._windowsQuoteCmdArg(a); - } - argline += '"'; - return [argline]; - } - } - return this.args; - } - _endsWith(str, end) { - return str.endsWith(end); - } - _isCmdFile() { - const upperToolPath = this.toolPath.toUpperCase(); - return (this._endsWith(upperToolPath, '.CMD') || - this._endsWith(upperToolPath, '.BAT')); - } - _windowsQuoteCmdArg(arg) { - // for .exe, apply the normal quoting rules that libuv applies - if (!this._isCmdFile()) { - return this._uvQuoteCmdArg(arg); - } - // otherwise apply quoting rules specific to the cmd.exe command line parser. - // the libuv rules are generic and are not designed specifically for cmd.exe - // command line parser. - // - // for a detailed description of the cmd.exe command line parser, refer to - // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 - // need quotes for empty arg - if (!arg) { - return '""'; - } - // determine whether the arg needs to be quoted - const cmdSpecialChars = [ - ' ', - '\t', - '&', - '(', - ')', - '[', - ']', - '{', - '}', - '^', - '=', - ';', - '!', - "'", - '+', - ',', - '`', - '~', - '|', - '<', - '>', - '"' - ]; - let needsQuotes = false; - for (const char of arg) { - if (cmdSpecialChars.some(x => x === char)) { - needsQuotes = true; - break; - } - } - // short-circuit if quotes not needed - if (!needsQuotes) { - return arg; - } - // the following quoting rules are very similar to the rules that by libuv applies. - // - // 1) wrap the string in quotes - // - // 2) double-up quotes - i.e. " => "" - // - // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately - // doesn't work well with a cmd.exe command line. - // - // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. - // for example, the command line: - // foo.exe "myarg:""my val""" - // is parsed by a .NET console app into an arg array: - // [ "myarg:\"my val\"" ] - // which is the same end result when applying libuv quoting rules. although the actual - // command line from libuv quoting rules would look like: - // foo.exe "myarg:\"my val\"" - // - // 3) double-up slashes that precede a quote, - // e.g. hello \world => "hello \world" - // hello\"world => "hello\\""world" - // hello\\"world => "hello\\\\""world" - // hello world\ => "hello world\\" - // - // technically this is not required for a cmd.exe command line, or the batch argument parser. - // the reasons for including this as a .cmd quoting rule are: - // - // a) this is optimized for the scenario where the argument is passed from the .cmd file to an - // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. - // - // b) it's what we've been doing previously (by deferring to node default behavior) and we - // haven't heard any complaints about that aspect. - // - // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be - // escaped when used on the command line directly - even though within a .cmd file % can be escaped - // by using %%. - // - // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts - // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. - // - // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would - // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the - // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args - // to an external program. - // - // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. - // % can be escaped within a .cmd file. - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { - // walk the string in reverse - reverse += arg[i - 1]; - if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; // double the slash - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '"'; // double the quote - } - else { - quoteHit = false; - } - } - reverse += '"'; - return reverse - .split('') - .reverse() - .join(''); - } - _uvQuoteCmdArg(arg) { - // Tool runner wraps child_process.spawn() and needs to apply the same quoting as - // Node in certain cases where the undocumented spawn option windowsVerbatimArguments - // is used. - // - // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, - // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), - // pasting copyright notice from Node within this function: - // - // Copyright Joyent, Inc. and other Node contributors. All rights reserved. - // - // Permission is hereby granted, free of charge, to any person obtaining a copy - // of this software and associated documentation files (the "Software"), to - // deal in the Software without restriction, including without limitation the - // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - // sell copies of the Software, and to permit persons to whom the Software is - // furnished to do so, subject to the following conditions: - // - // The above copyright notice and this permission notice shall be included in - // all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - // IN THE SOFTWARE. - if (!arg) { - // Need double quotation for empty argument - return '""'; - } - if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { - // No quotation needed - return arg; - } - if (!arg.includes('"') && !arg.includes('\\')) { - // No embedded double quotes or backslashes, so I can just wrap - // quote marks around the whole thing. - return `"${arg}"`; - } - // Expected input/output: - // input : hello"world - // output: "hello\"world" - // input : hello""world - // output: "hello\"\"world" - // input : hello\world - // output: hello\world - // input : hello\\world - // output: hello\\world - // input : hello\"world - // output: "hello\\\"world" - // input : hello\\"world - // output: "hello\\\\\"world" - // input : hello world\ - // output: "hello world\\" - note the comment in libuv actually reads "hello world\" - // but it appears the comment is wrong, it should be "hello world\\" - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { - // walk the string in reverse - reverse += arg[i - 1]; - if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '\\'; - } - else { - quoteHit = false; - } - } - reverse += '"'; - return reverse - .split('') - .reverse() - .join(''); - } - _cloneExecOptions(options) { - options = options || {}; - const result = { - cwd: options.cwd || process.cwd(), - env: options.env || process.env, - silent: options.silent || false, - windowsVerbatimArguments: options.windowsVerbatimArguments || false, - failOnStdErr: options.failOnStdErr || false, - ignoreReturnCode: options.ignoreReturnCode || false, - delay: options.delay || 10000 - }; - result.outStream = options.outStream || process.stdout; - result.errStream = options.errStream || process.stderr; - return result; - } - _getSpawnOptions(options, toolPath) { - options = options || {}; - const result = {}; - result.cwd = options.cwd; - result.env = options.env; - result['windowsVerbatimArguments'] = - options.windowsVerbatimArguments || this._isCmdFile(); - if (options.windowsVerbatimArguments) { - result.argv0 = `"${toolPath}"`; - } - return result; - } - /** - * Exec a tool. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param tool path to tool to exec - * @param options optional exec options. See ExecOptions - * @returns number - */ - exec() { - return __awaiter(this, void 0, void 0, function* () { - // root the tool path if it is unrooted and contains relative pathing - if (!ioUtil.isRooted(this.toolPath) && - (this.toolPath.includes('/') || - (IS_WINDOWS && this.toolPath.includes('\\')))) { - // prefer options.cwd if it is specified, however options.cwd may also need to be rooted - this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); - } - // if the tool is only a file name, then resolve it from the PATH - // otherwise verify it exists (add extension on Windows if necessary) - this.toolPath = yield io.which(this.toolPath, true); - return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { - this._debug(`exec tool: ${this.toolPath}`); - this._debug('arguments:'); - for (const arg of this.args) { - this._debug(` ${arg}`); - } - const optionsNonNull = this._cloneExecOptions(this.options); - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); - } - const state = new ExecState(optionsNonNull, this.toolPath); - state.on('debug', (message) => { - this._debug(message); - }); - if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { - return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); - } - const fileName = this._getSpawnFileName(); - const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); - let stdbuffer = ''; - if (cp.stdout) { - cp.stdout.on('data', (data) => { - if (this.options.listeners && this.options.listeners.stdout) { - this.options.listeners.stdout(data); - } - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(data); - } - stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { - if (this.options.listeners && this.options.listeners.stdline) { - this.options.listeners.stdline(line); - } - }); - }); - } - let errbuffer = ''; - if (cp.stderr) { - cp.stderr.on('data', (data) => { - state.processStderr = true; - if (this.options.listeners && this.options.listeners.stderr) { - this.options.listeners.stderr(data); - } - if (!optionsNonNull.silent && - optionsNonNull.errStream && - optionsNonNull.outStream) { - const s = optionsNonNull.failOnStdErr - ? optionsNonNull.errStream - : optionsNonNull.outStream; - s.write(data); - } - errbuffer = this._processLineBuffer(data, errbuffer, (line) => { - if (this.options.listeners && this.options.listeners.errline) { - this.options.listeners.errline(line); - } - }); - }); - } - cp.on('error', (err) => { - state.processError = err.message; - state.processExited = true; - state.processClosed = true; - state.CheckComplete(); - }); - cp.on('exit', (code) => { - state.processExitCode = code; - state.processExited = true; - this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); - state.CheckComplete(); - }); - cp.on('close', (code) => { - state.processExitCode = code; - state.processExited = true; - state.processClosed = true; - this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); - state.CheckComplete(); - }); - state.on('done', (error, exitCode) => { - if (stdbuffer.length > 0) { - this.emit('stdline', stdbuffer); - } - if (errbuffer.length > 0) { - this.emit('errline', errbuffer); - } - cp.removeAllListeners(); - if (error) { - reject(error); - } - else { - resolve(exitCode); - } - }); - if (this.options.input) { - if (!cp.stdin) { - throw new Error('child process missing stdin'); - } - cp.stdin.end(this.options.input); - } - })); - }); - } -} -exports.ToolRunner = ToolRunner; -/** - * Convert an arg string to an array of args. Handles escaping - * - * @param argString string of arguments - * @returns string[] array of arguments - */ -function argStringToArray(argString) { - const args = []; - let inQuotes = false; - let escaped = false; - let arg = ''; - function append(c) { - // we only escape double quotes. - if (escaped && c !== '"') { - arg += '\\'; - } - arg += c; - escaped = false; - } - for (let i = 0; i < argString.length; i++) { - const c = argString.charAt(i); - if (c === '"') { - if (!escaped) { - inQuotes = !inQuotes; - } - else { - append(c); - } - continue; - } - if (c === '\\' && escaped) { - append(c); - continue; - } - if (c === '\\' && inQuotes) { - escaped = true; - continue; - } - if (c === ' ' && !inQuotes) { - if (arg.length > 0) { - args.push(arg); - arg = ''; - } - continue; - } - append(c); - } - if (arg.length > 0) { - args.push(arg.trim()); - } - return args; -} -exports.argStringToArray = argStringToArray; -class ExecState extends events.EventEmitter { - constructor(options, toolPath) { - super(); - this.processClosed = false; // tracks whether the process has exited and stdio is closed - this.processError = ''; - this.processExitCode = 0; - this.processExited = false; // tracks whether the process has exited - this.processStderr = false; // tracks whether stderr was written to - this.delay = 10000; // 10 seconds - this.done = false; - this.timeout = null; - if (!toolPath) { - throw new Error('toolPath must not be empty'); - } - this.options = options; - this.toolPath = toolPath; - if (options.delay) { - this.delay = options.delay; - } - } - CheckComplete() { - if (this.done) { - return; - } - if (this.processClosed) { - this._setResult(); - } - else if (this.processExited) { - this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); - } - } - _debug(message) { - this.emit('debug', message); - } - _setResult() { - // determine whether there is an error - let error; - if (this.processExited) { - if (this.processError) { - error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); - } - else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { - error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); - } - else if (this.processStderr && this.options.failOnStdErr) { - error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); - } - } - // clear the timeout - if (this.timeout) { - clearTimeout(this.timeout); - this.timeout = null; - } - this.done = true; - this.emit('done', error, this.processExitCode); - } - static HandleTimeout(state) { - if (state.done) { - return; - } - if (!state.processClosed && state.processExited) { - const message = `The STDIO streams did not close within ${state.delay / - 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; - state._debug(message); - } - state._setResult(); - } -} -//# sourceMappingURL=toolrunner.js.map - -/***/ }), - -/***/ 362: -/***/ (function(__unused_webpack_module, exports) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; -class BasicCredentialHandler { - constructor(username, password) { - this.username = username; - this.password = password; - } - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } -} -exports.BasicCredentialHandler = BasicCredentialHandler; -class BearerCredentialHandler { - constructor(token) { - this.token = token; - } - // currently implements pre-authorization - // TODO: support preAuth = false where it hooks on 401 - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Bearer ${this.token}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } -} -exports.BearerCredentialHandler = BearerCredentialHandler; -class PersonalAccessTokenCredentialHandler { - constructor(token) { - this.token = token; - } - // currently implements pre-authorization - // TODO: support preAuth = false where it hooks on 401 - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } -} -exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; -//# sourceMappingURL=auth.js.map - -/***/ }), - -/***/ 882: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -/* eslint-disable @typescript-eslint/no-explicit-any */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; -const http = __importStar(__nccwpck_require__(685)); -const https = __importStar(__nccwpck_require__(687)); -const pm = __importStar(__nccwpck_require__(668)); -const tunnel = __importStar(__nccwpck_require__(457)); -var HttpCodes; -(function (HttpCodes) { - HttpCodes[HttpCodes["OK"] = 200] = "OK"; - HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; - HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; - HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; - HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; - HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; - HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; - HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; - HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; - HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; - HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; - HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; - HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; - HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; - HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; - HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; - HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; - HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; - HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; - HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; - HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; - HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; - HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; - HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; - HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; - HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; - HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; -})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); -var Headers; -(function (Headers) { - Headers["Accept"] = "accept"; - Headers["ContentType"] = "content-type"; -})(Headers = exports.Headers || (exports.Headers = {})); -var MediaTypes; -(function (MediaTypes) { - MediaTypes["ApplicationJson"] = "application/json"; -})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); -/** - * Returns the proxy URL, depending upon the supplied url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ -function getProxyUrl(serverUrl) { - const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); - return proxyUrl ? proxyUrl.href : ''; -} -exports.getProxyUrl = getProxyUrl; -const HttpRedirectCodes = [ - HttpCodes.MovedPermanently, - HttpCodes.ResourceMoved, - HttpCodes.SeeOther, - HttpCodes.TemporaryRedirect, - HttpCodes.PermanentRedirect -]; -const HttpResponseRetryCodes = [ - HttpCodes.BadGateway, - HttpCodes.ServiceUnavailable, - HttpCodes.GatewayTimeout -]; -const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; -const ExponentialBackoffCeiling = 10; -const ExponentialBackoffTimeSlice = 5; -class HttpClientError extends Error { - constructor(message, statusCode) { - super(message); - this.name = 'HttpClientError'; - this.statusCode = statusCode; - Object.setPrototypeOf(this, HttpClientError.prototype); - } -} -exports.HttpClientError = HttpClientError; -class HttpClientResponse { - constructor(message) { - this.message = message; - } - readBody() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { - let output = Buffer.alloc(0); - this.message.on('data', (chunk) => { - output = Buffer.concat([output, chunk]); - }); - this.message.on('end', () => { - resolve(output.toString()); - }); - })); - }); - } -} -exports.HttpClientResponse = HttpClientResponse; -function isHttps(requestUrl) { - const parsedUrl = new URL(requestUrl); - return parsedUrl.protocol === 'https:'; -} -exports.isHttps = isHttps; -class HttpClient { - constructor(userAgent, handlers, requestOptions) { - this._ignoreSslError = false; - this._allowRedirects = true; - this._allowRedirectDowngrade = false; - this._maxRedirects = 50; - this._allowRetries = false; - this._maxRetries = 1; - this._keepAlive = false; - this._disposed = false; - this.userAgent = userAgent; - this.handlers = handlers || []; - this.requestOptions = requestOptions; - if (requestOptions) { - if (requestOptions.ignoreSslError != null) { - this._ignoreSslError = requestOptions.ignoreSslError; - } - this._socketTimeout = requestOptions.socketTimeout; - if (requestOptions.allowRedirects != null) { - this._allowRedirects = requestOptions.allowRedirects; - } - if (requestOptions.allowRedirectDowngrade != null) { - this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; - } - if (requestOptions.maxRedirects != null) { - this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); - } - if (requestOptions.keepAlive != null) { - this._keepAlive = requestOptions.keepAlive; - } - if (requestOptions.allowRetries != null) { - this._allowRetries = requestOptions.allowRetries; - } - if (requestOptions.maxRetries != null) { - this._maxRetries = requestOptions.maxRetries; - } - } - } - options(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); - }); - } - get(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('GET', requestUrl, null, additionalHeaders || {}); - }); - } - del(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('DELETE', requestUrl, null, additionalHeaders || {}); - }); - } - post(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('POST', requestUrl, data, additionalHeaders || {}); - }); - } - patch(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('PATCH', requestUrl, data, additionalHeaders || {}); - }); - } - put(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('PUT', requestUrl, data, additionalHeaders || {}); - }); - } - head(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('HEAD', requestUrl, null, additionalHeaders || {}); - }); - } - sendStream(verb, requestUrl, stream, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request(verb, requestUrl, stream, additionalHeaders); - }); - } - /** - * Gets a typed object from an endpoint - * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise - */ - getJson(requestUrl, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - const res = yield this.get(requestUrl, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - postJson(requestUrl, obj, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - const res = yield this.post(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - putJson(requestUrl, obj, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - const res = yield this.put(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - patchJson(requestUrl, obj, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - const res = yield this.patch(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - /** - * Makes a raw http request. - * All other methods such as get, post, patch, and request ultimately call this. - * Prefer get, del, post and patch - */ - request(verb, requestUrl, data, headers) { - return __awaiter(this, void 0, void 0, function* () { - if (this._disposed) { - throw new Error('Client has already been disposed.'); - } - const parsedUrl = new URL(requestUrl); - let info = this._prepareRequest(verb, parsedUrl, headers); - // Only perform retries on reads since writes may not be idempotent. - const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) - ? this._maxRetries + 1 - : 1; - let numTries = 0; - let response; - do { - response = yield this.requestRaw(info, data); - // Check if it's an authentication challenge - if (response && - response.message && - response.message.statusCode === HttpCodes.Unauthorized) { - let authenticationHandler; - for (const handler of this.handlers) { - if (handler.canHandleAuthentication(response)) { - authenticationHandler = handler; - break; - } - } - if (authenticationHandler) { - return authenticationHandler.handleAuthentication(this, info, data); - } - else { - // We have received an unauthorized response but have no handlers to handle it. - // Let the response return to the caller. - return response; - } - } - let redirectsRemaining = this._maxRedirects; - while (response.message.statusCode && - HttpRedirectCodes.includes(response.message.statusCode) && - this._allowRedirects && - redirectsRemaining > 0) { - const redirectUrl = response.message.headers['location']; - if (!redirectUrl) { - // if there's no location to redirect to, we won't - break; - } - const parsedRedirectUrl = new URL(redirectUrl); - if (parsedUrl.protocol === 'https:' && - parsedUrl.protocol !== parsedRedirectUrl.protocol && - !this._allowRedirectDowngrade) { - throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); - } - // we need to finish reading the response before reassigning response - // which will leak the open socket. - yield response.readBody(); - // strip authorization header if redirected to a different hostname - if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { - for (const header in headers) { - // header names are case insensitive - if (header.toLowerCase() === 'authorization') { - delete headers[header]; - } - } - } - // let's make the request with the new redirectUrl - info = this._prepareRequest(verb, parsedRedirectUrl, headers); - response = yield this.requestRaw(info, data); - redirectsRemaining--; - } - if (!response.message.statusCode || - !HttpResponseRetryCodes.includes(response.message.statusCode)) { - // If not a retry code, return immediately instead of retrying - return response; - } - numTries += 1; - if (numTries < maxTries) { - yield response.readBody(); - yield this._performExponentialBackoff(numTries); - } - } while (numTries < maxTries); - return response; - }); - } - /** - * Needs to be called if keepAlive is set to true in request options. - */ - dispose() { - if (this._agent) { - this._agent.destroy(); - } - this._disposed = true; - } - /** - * Raw request. - * @param info - * @param data - */ - requestRaw(info, data) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - function callbackForResult(err, res) { - if (err) { - reject(err); - } - else if (!res) { - // If `err` is not passed, then `res` must be passed. - reject(new Error('Unknown error')); - } - else { - resolve(res); - } - } - this.requestRawWithCallback(info, data, callbackForResult); - }); - }); - } - /** - * Raw request with callback. - * @param info - * @param data - * @param onResult - */ - requestRawWithCallback(info, data, onResult) { - if (typeof data === 'string') { - if (!info.options.headers) { - info.options.headers = {}; - } - info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); - } - let callbackCalled = false; - function handleResult(err, res) { - if (!callbackCalled) { - callbackCalled = true; - onResult(err, res); - } - } - const req = info.httpModule.request(info.options, (msg) => { - const res = new HttpClientResponse(msg); - handleResult(undefined, res); - }); - let socket; - req.on('socket', sock => { - socket = sock; - }); - // If we ever get disconnected, we want the socket to timeout eventually - req.setTimeout(this._socketTimeout || 3 * 60000, () => { - if (socket) { - socket.end(); - } - handleResult(new Error(`Request timeout: ${info.options.path}`)); - }); - req.on('error', function (err) { - // err has statusCode property - // res should have headers - handleResult(err); - }); - if (data && typeof data === 'string') { - req.write(data, 'utf8'); - } - if (data && typeof data !== 'string') { - data.on('close', function () { - req.end(); - }); - data.pipe(req); - } - else { - req.end(); - } - } - /** - * Gets an http agent. This function is useful when you need an http agent that handles - * routing through a proxy server - depending upon the url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ - getAgent(serverUrl) { - const parsedUrl = new URL(serverUrl); - return this._getAgent(parsedUrl); - } - _prepareRequest(method, requestUrl, headers) { - const info = {}; - info.parsedUrl = requestUrl; - const usingSsl = info.parsedUrl.protocol === 'https:'; - info.httpModule = usingSsl ? https : http; - const defaultPort = usingSsl ? 443 : 80; - info.options = {}; - info.options.host = info.parsedUrl.hostname; - info.options.port = info.parsedUrl.port - ? parseInt(info.parsedUrl.port) - : defaultPort; - info.options.path = - (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); - info.options.method = method; - info.options.headers = this._mergeHeaders(headers); - if (this.userAgent != null) { - info.options.headers['user-agent'] = this.userAgent; - } - info.options.agent = this._getAgent(info.parsedUrl); - // gives handlers an opportunity to participate - if (this.handlers) { - for (const handler of this.handlers) { - handler.prepareRequest(info.options); - } - } - return info; - } - _mergeHeaders(headers) { - if (this.requestOptions && this.requestOptions.headers) { - return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); - } - return lowercaseKeys(headers || {}); - } - _getExistingOrDefaultHeader(additionalHeaders, header, _default) { - let clientHeader; - if (this.requestOptions && this.requestOptions.headers) { - clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; - } - return additionalHeaders[header] || clientHeader || _default; - } - _getAgent(parsedUrl) { - let agent; - const proxyUrl = pm.getProxyUrl(parsedUrl); - const useProxy = proxyUrl && proxyUrl.hostname; - if (this._keepAlive && useProxy) { - agent = this._proxyAgent; - } - if (this._keepAlive && !useProxy) { - agent = this._agent; - } - // if agent is already assigned use that agent. - if (agent) { - return agent; - } - const usingSsl = parsedUrl.protocol === 'https:'; - let maxSockets = 100; - if (this.requestOptions) { - maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; - } - // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. - if (proxyUrl && proxyUrl.hostname) { - const agentOptions = { - maxSockets, - keepAlive: this._keepAlive, - proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { - proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` - })), { host: proxyUrl.hostname, port: proxyUrl.port }) - }; - let tunnelAgent; - const overHttps = proxyUrl.protocol === 'https:'; - if (usingSsl) { - tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; - } - else { - tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; - } - agent = tunnelAgent(agentOptions); - this._proxyAgent = agent; - } - // if reusing agent across request and tunneling agent isn't assigned create a new agent - if (this._keepAlive && !agent) { - const options = { keepAlive: this._keepAlive, maxSockets }; - agent = usingSsl ? new https.Agent(options) : new http.Agent(options); - this._agent = agent; - } - // if not using private agent and tunnel agent isn't setup then use global agent - if (!agent) { - agent = usingSsl ? https.globalAgent : http.globalAgent; - } - if (usingSsl && this._ignoreSslError) { - // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process - // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options - // we have to cast it to any and change it directly - agent.options = Object.assign(agent.options || {}, { - rejectUnauthorized: false - }); - } - return agent; - } - _performExponentialBackoff(retryNumber) { - return __awaiter(this, void 0, void 0, function* () { - retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); - const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); - return new Promise(resolve => setTimeout(() => resolve(), ms)); - }); - } - _processResponse(res, options) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { - const statusCode = res.message.statusCode || 0; - const response = { - statusCode, - result: null, - headers: {} - }; - // not found leads to null obj returned - if (statusCode === HttpCodes.NotFound) { - resolve(response); - } - // get the result from the body - function dateTimeDeserializer(key, value) { - if (typeof value === 'string') { - const a = new Date(value); - if (!isNaN(a.valueOf())) { - return a; - } - } - return value; - } - let obj; - let contents; - try { - contents = yield res.readBody(); - if (contents && contents.length > 0) { - if (options && options.deserializeDates) { - obj = JSON.parse(contents, dateTimeDeserializer); - } - else { - obj = JSON.parse(contents); - } - response.result = obj; - } - response.headers = res.message.headers; - } - catch (err) { - // Invalid resource (contents not json); leaving result obj null - } - // note that 3xx redirects are handled by the http layer. - if (statusCode > 299) { - let msg; - // if exception/error in body, attempt to get better error - if (obj && obj.message) { - msg = obj.message; - } - else if (contents && contents.length > 0) { - // it may be the case that the exception is in the body message as string - msg = contents; - } - else { - msg = `Failed request: (${statusCode})`; - } - const err = new HttpClientError(msg, statusCode); - err.result = response.result; - reject(err); - } - else { - resolve(response); - } - })); - }); - } -} -exports.HttpClient = HttpClient; -const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); -//# sourceMappingURL=index.js.map - -/***/ }), - -/***/ 668: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.checkBypass = exports.getProxyUrl = void 0; -function getProxyUrl(reqUrl) { - const usingSsl = reqUrl.protocol === 'https:'; - if (checkBypass(reqUrl)) { - return undefined; - } - const proxyVar = (() => { - if (usingSsl) { - return process.env['https_proxy'] || process.env['HTTPS_PROXY']; - } - else { - return process.env['http_proxy'] || process.env['HTTP_PROXY']; - } - })(); - if (proxyVar) { - return new URL(proxyVar); - } - else { - return undefined; - } -} -exports.getProxyUrl = getProxyUrl; -function checkBypass(reqUrl) { - if (!reqUrl.hostname) { - return false; - } - const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; - if (!noProxy) { - return false; - } - // Determine the request port - let reqPort; - if (reqUrl.port) { - reqPort = Number(reqUrl.port); - } - else if (reqUrl.protocol === 'http:') { - reqPort = 80; - } - else if (reqUrl.protocol === 'https:') { - reqPort = 443; - } - // Format the request hostname and hostname with port - const upperReqHosts = [reqUrl.hostname.toUpperCase()]; - if (typeof reqPort === 'number') { - upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); - } - // Compare request host against noproxy - for (const upperNoProxyItem of noProxy - .split(',') - .map(x => x.trim().toUpperCase()) - .filter(x => x)) { - if (upperReqHosts.some(x => x === upperNoProxyItem)) { - return true; - } - } - return false; -} -exports.checkBypass = checkBypass; -//# sourceMappingURL=proxy.js.map - -/***/ }), - -/***/ 152: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var _a; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rename = exports.readlink = exports.readdir = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; -const fs = __importStar(__nccwpck_require__(147)); -const path = __importStar(__nccwpck_require__(17)); -_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; -exports.IS_WINDOWS = process.platform === 'win32'; -function exists(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - try { - yield exports.stat(fsPath); - } - catch (err) { - if (err.code === 'ENOENT') { - return false; - } - throw err; - } - return true; - }); -} -exports.exists = exists; -function isDirectory(fsPath, useStat = false) { - return __awaiter(this, void 0, void 0, function* () { - const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); - return stats.isDirectory(); - }); -} -exports.isDirectory = isDirectory; -/** - * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: - * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). - */ -function isRooted(p) { - p = normalizeSeparators(p); - if (!p) { - throw new Error('isRooted() parameter "p" cannot be empty'); - } - if (exports.IS_WINDOWS) { - return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello - ); // e.g. C: or C:\hello - } - return p.startsWith('/'); -} -exports.isRooted = isRooted; -/** - * Best effort attempt to determine whether a file exists and is executable. - * @param filePath file path to check - * @param extensions additional file extensions to try - * @return if file exists and is executable, returns the file path. otherwise empty string. - */ -function tryGetExecutablePath(filePath, extensions) { - return __awaiter(this, void 0, void 0, function* () { - let stats = undefined; - try { - // test file exists - stats = yield exports.stat(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // on Windows, test for valid extension - const upperExt = path.extname(filePath).toUpperCase(); - if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { - return filePath; - } - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - // try each extension - const originalFilePath = filePath; - for (const extension of extensions) { - filePath = originalFilePath + extension; - stats = undefined; - try { - stats = yield exports.stat(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // preserve the case of the actual file (since an extension was appended) - try { - const directory = path.dirname(filePath); - const upperName = path.basename(filePath).toUpperCase(); - for (const actualName of yield exports.readdir(directory)) { - if (upperName === actualName.toUpperCase()) { - filePath = path.join(directory, actualName); - break; - } - } - } - catch (err) { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); - } - return filePath; - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - } - return ''; - }); -} -exports.tryGetExecutablePath = tryGetExecutablePath; -function normalizeSeparators(p) { - p = p || ''; - if (exports.IS_WINDOWS) { - // convert slashes on Windows - p = p.replace(/\//g, '\\'); - // remove redundant slashes - return p.replace(/\\\\+/g, '\\'); - } - // remove redundant slashes - return p.replace(/\/\/+/g, '/'); -} -// on Mac/Linux, test the execute bit -// R W X R W X R W X -// 256 128 64 32 16 8 4 2 1 -function isUnixExecutable(stats) { - return ((stats.mode & 1) > 0 || - ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || - ((stats.mode & 64) > 0 && stats.uid === process.getuid())); -} -// Get the path of cmd.exe in windows -function getCmdPath() { - var _a; - return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; -} -exports.getCmdPath = getCmdPath; -//# sourceMappingURL=io-util.js.map - -/***/ }), - -/***/ 59: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; -const assert_1 = __nccwpck_require__(491); -const childProcess = __importStar(__nccwpck_require__(81)); -const path = __importStar(__nccwpck_require__(17)); -const util_1 = __nccwpck_require__(837); -const ioUtil = __importStar(__nccwpck_require__(152)); -const exec = util_1.promisify(childProcess.exec); -const execFile = util_1.promisify(childProcess.execFile); -/** - * Copies a file or folder. - * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js - * - * @param source source path - * @param dest destination path - * @param options optional. See CopyOptions. - */ -function cp(source, dest, options = {}) { - return __awaiter(this, void 0, void 0, function* () { - const { force, recursive, copySourceDirectory } = readCopyOptions(options); - const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; - // Dest is an existing file, but not forcing - if (destStat && destStat.isFile() && !force) { - return; - } - // If dest is an existing directory, should copy inside. - const newDest = destStat && destStat.isDirectory() && copySourceDirectory - ? path.join(dest, path.basename(source)) - : dest; - if (!(yield ioUtil.exists(source))) { - throw new Error(`no such file or directory: ${source}`); - } - const sourceStat = yield ioUtil.stat(source); - if (sourceStat.isDirectory()) { - if (!recursive) { - throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); - } - else { - yield cpDirRecursive(source, newDest, 0, force); - } - } - else { - if (path.relative(source, newDest) === '') { - // a file cannot be copied to itself - throw new Error(`'${newDest}' and '${source}' are the same file`); - } - yield copyFile(source, newDest, force); - } - }); -} -exports.cp = cp; -/** - * Moves a path. - * - * @param source source path - * @param dest destination path - * @param options optional. See MoveOptions. - */ -function mv(source, dest, options = {}) { - return __awaiter(this, void 0, void 0, function* () { - if (yield ioUtil.exists(dest)) { - let destExists = true; - if (yield ioUtil.isDirectory(dest)) { - // If dest is directory copy src into dest - dest = path.join(dest, path.basename(source)); - destExists = yield ioUtil.exists(dest); - } - if (destExists) { - if (options.force == null || options.force) { - yield rmRF(dest); - } - else { - throw new Error('Destination already exists'); - } - } - } - yield mkdirP(path.dirname(dest)); - yield ioUtil.rename(source, dest); - }); -} -exports.mv = mv; -/** - * Remove a path recursively with force - * - * @param inputPath path to remove - */ -function rmRF(inputPath) { - return __awaiter(this, void 0, void 0, function* () { - if (ioUtil.IS_WINDOWS) { - // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another - // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del. - // Check for invalid characters - // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file - if (/[*"<>|]/.test(inputPath)) { - throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); - } - try { - const cmdPath = ioUtil.getCmdPath(); - if (yield ioUtil.isDirectory(inputPath, true)) { - yield exec(`${cmdPath} /s /c "rd /s /q "%inputPath%""`, { - env: { inputPath } - }); - } - else { - yield exec(`${cmdPath} /s /c "del /f /a "%inputPath%""`, { - env: { inputPath } - }); - } - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; - } - // Shelling out fails to remove a symlink folder with missing source, this unlink catches that - try { - yield ioUtil.unlink(inputPath); - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; - } - } - else { - let isDir = false; - try { - isDir = yield ioUtil.isDirectory(inputPath); - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; - return; - } - if (isDir) { - yield execFile(`rm`, [`-rf`, `${inputPath}`]); - } - else { - yield ioUtil.unlink(inputPath); - } - } - }); -} -exports.rmRF = rmRF; -/** - * Make a directory. Creates the full path with folders in between - * Will throw if it fails - * - * @param fsPath path to create - * @returns Promise - */ -function mkdirP(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - assert_1.ok(fsPath, 'a path argument must be provided'); - yield ioUtil.mkdir(fsPath, { recursive: true }); - }); -} -exports.mkdirP = mkdirP; -/** - * Returns path of a tool had the tool actually been invoked. Resolves via paths. - * If you check and the tool does not exist, it will throw. - * - * @param tool name of the tool - * @param check whether to check if tool exists - * @returns Promise path to tool - */ -function which(tool, check) { - return __awaiter(this, void 0, void 0, function* () { - if (!tool) { - throw new Error("parameter 'tool' is required"); - } - // recursive when check=true - if (check) { - const result = yield which(tool, false); - if (!result) { - if (ioUtil.IS_WINDOWS) { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); - } - else { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); - } - } - return result; - } - const matches = yield findInPath(tool); - if (matches && matches.length > 0) { - return matches[0]; - } - return ''; - }); -} -exports.which = which; -/** - * Returns a list of all occurrences of the given tool on the system path. - * - * @returns Promise the paths of the tool - */ -function findInPath(tool) { - return __awaiter(this, void 0, void 0, function* () { - if (!tool) { - throw new Error("parameter 'tool' is required"); - } - // build the list of extensions to try - const extensions = []; - if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { - for (const extension of process.env['PATHEXT'].split(path.delimiter)) { - if (extension) { - extensions.push(extension); - } - } - } - // if it's rooted, return it if exists. otherwise return empty. - if (ioUtil.isRooted(tool)) { - const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); - if (filePath) { - return [filePath]; - } - return []; - } - // if any path separators, return empty - if (tool.includes(path.sep)) { - return []; - } - // build the list of directories - // - // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, - // it feels like we should not do this. Checking the current directory seems like more of a use - // case of a shell, and the which() function exposed by the toolkit should strive for consistency - // across platforms. - const directories = []; - if (process.env.PATH) { - for (const p of process.env.PATH.split(path.delimiter)) { - if (p) { - directories.push(p); - } - } - } - // find all matches - const matches = []; - for (const directory of directories) { - const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); - if (filePath) { - matches.push(filePath); - } - } - return matches; - }); -} -exports.findInPath = findInPath; -function readCopyOptions(options) { - const force = options.force == null ? true : options.force; - const recursive = Boolean(options.recursive); - const copySourceDirectory = options.copySourceDirectory == null - ? true - : Boolean(options.copySourceDirectory); - return { force, recursive, copySourceDirectory }; -} -function cpDirRecursive(sourceDir, destDir, currentDepth, force) { - return __awaiter(this, void 0, void 0, function* () { - // Ensure there is not a run away recursive copy - if (currentDepth >= 255) - return; - currentDepth++; - yield mkdirP(destDir); - const files = yield ioUtil.readdir(sourceDir); - for (const fileName of files) { - const srcFile = `${sourceDir}/${fileName}`; - const destFile = `${destDir}/${fileName}`; - const srcFileStat = yield ioUtil.lstat(srcFile); - if (srcFileStat.isDirectory()) { - // Recurse - yield cpDirRecursive(srcFile, destFile, currentDepth, force); - } - else { - yield copyFile(srcFile, destFile, force); - } - } - // Change the mode for the newly created directory - yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); - }); -} -// Buffered file copy -function copyFile(srcFile, destFile, force) { - return __awaiter(this, void 0, void 0, function* () { - if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { - // unlink/re-link it - try { - yield ioUtil.lstat(destFile); - yield ioUtil.unlink(destFile); - } - catch (e) { - // Try to override file permission - if (e.code === 'EPERM') { - yield ioUtil.chmod(destFile, '0666'); - yield ioUtil.unlink(destFile); - } - // other errors = it doesn't exist, no work to do - } - // Copy over symlink - const symlinkFull = yield ioUtil.readlink(srcFile); - yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); - } - else if (!(yield ioUtil.exists(destFile)) || force) { - yield ioUtil.copyFile(srcFile, destFile); - } - }); -} -//# sourceMappingURL=io.js.map - -/***/ }), - -/***/ 457: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -module.exports = __nccwpck_require__(531); - - -/***/ }), - -/***/ 531: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -var net = __nccwpck_require__(808); -var tls = __nccwpck_require__(404); -var http = __nccwpck_require__(685); -var https = __nccwpck_require__(687); -var events = __nccwpck_require__(361); -var assert = __nccwpck_require__(491); -var util = __nccwpck_require__(837); - - -exports.httpOverHttp = httpOverHttp; -exports.httpsOverHttp = httpsOverHttp; -exports.httpOverHttps = httpOverHttps; -exports.httpsOverHttps = httpsOverHttps; - - -function httpOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - return agent; -} - -function httpsOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} - -function httpOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - return agent; -} - -function httpsOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} - - -function TunnelingAgent(options) { - var self = this; - self.options = options || {}; - self.proxyOptions = self.options.proxy || {}; - self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; - self.requests = []; - self.sockets = []; - - self.on('free', function onFree(socket, host, port, localAddress) { - var options = toOptions(host, port, localAddress); - for (var i = 0, len = self.requests.length; i < len; ++i) { - var pending = self.requests[i]; - if (pending.host === options.host && pending.port === options.port) { - // Detect the request to connect same origin server, - // reuse the connection. - self.requests.splice(i, 1); - pending.request.onSocket(socket); - return; - } - } - socket.destroy(); - self.removeSocket(socket); - }); -} -util.inherits(TunnelingAgent, events.EventEmitter); - -TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { - var self = this; - var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); - - if (self.sockets.length >= this.maxSockets) { - // We are over limit so we'll add it to the queue. - self.requests.push(options); - return; - } - - // If we are under maxSockets create a new one. - self.createSocket(options, function(socket) { - socket.on('free', onFree); - socket.on('close', onCloseOrRemove); - socket.on('agentRemove', onCloseOrRemove); - req.onSocket(socket); - - function onFree() { - self.emit('free', socket, options); - } - - function onCloseOrRemove(err) { - self.removeSocket(socket); - socket.removeListener('free', onFree); - socket.removeListener('close', onCloseOrRemove); - socket.removeListener('agentRemove', onCloseOrRemove); - } - }); -}; - -TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { - var self = this; - var placeholder = {}; - self.sockets.push(placeholder); - - var connectOptions = mergeOptions({}, self.proxyOptions, { - method: 'CONNECT', - path: options.host + ':' + options.port, - agent: false, - headers: { - host: options.host + ':' + options.port - } - }); - if (options.localAddress) { - connectOptions.localAddress = options.localAddress; - } - if (connectOptions.proxyAuth) { - connectOptions.headers = connectOptions.headers || {}; - connectOptions.headers['Proxy-Authorization'] = 'Basic ' + - new Buffer(connectOptions.proxyAuth).toString('base64'); - } - - debug('making CONNECT request'); - var connectReq = self.request(connectOptions); - connectReq.useChunkedEncodingByDefault = false; // for v0.6 - connectReq.once('response', onResponse); // for v0.6 - connectReq.once('upgrade', onUpgrade); // for v0.6 - connectReq.once('connect', onConnect); // for v0.7 or later - connectReq.once('error', onError); - connectReq.end(); - - function onResponse(res) { - // Very hacky. This is necessary to avoid http-parser leaks. - res.upgrade = true; - } - - function onUpgrade(res, socket, head) { - // Hacky. - process.nextTick(function() { - onConnect(res, socket, head); - }); - } - - function onConnect(res, socket, head) { - connectReq.removeAllListeners(); - socket.removeAllListeners(); - - if (res.statusCode !== 200) { - debug('tunneling socket could not be established, statusCode=%d', - res.statusCode); - socket.destroy(); - var error = new Error('tunneling socket could not be established, ' + - 'statusCode=' + res.statusCode); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - if (head.length > 0) { - debug('got illegal response body from proxy'); - socket.destroy(); - var error = new Error('got illegal response body from proxy'); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - debug('tunneling connection has established'); - self.sockets[self.sockets.indexOf(placeholder)] = socket; - return cb(socket); - } - - function onError(cause) { - connectReq.removeAllListeners(); - - debug('tunneling socket could not be established, cause=%s\n', - cause.message, cause.stack); - var error = new Error('tunneling socket could not be established, ' + - 'cause=' + cause.message); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - } -}; - -TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { - var pos = this.sockets.indexOf(socket) - if (pos === -1) { - return; - } - this.sockets.splice(pos, 1); - - var pending = this.requests.shift(); - if (pending) { - // If we have pending requests and a socket gets closed a new one - // needs to be created to take over in the pool for the one that closed. - this.createSocket(pending, function(socket) { - pending.request.onSocket(socket); - }); - } -}; - -function createSecureSocket(options, cb) { - var self = this; - TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { - var hostHeader = options.request.getHeader('host'); - var tlsOptions = mergeOptions({}, self.options, { - socket: socket, - servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host - }); - - // 0 is dummy port for v0.6 - var secureSocket = tls.connect(0, tlsOptions); - self.sockets[self.sockets.indexOf(socket)] = secureSocket; - cb(secureSocket); - }); -} - - -function toOptions(host, port, localAddress) { - if (typeof host === 'string') { // since v0.10 - return { - host: host, - port: port, - localAddress: localAddress - }; - } - return host; // for v0.11 or later -} - -function mergeOptions(target) { - for (var i = 1, len = arguments.length; i < len; ++i) { - var overrides = arguments[i]; - if (typeof overrides === 'object') { - var keys = Object.keys(overrides); - for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { - var k = keys[j]; - if (overrides[k] !== undefined) { - target[k] = overrides[k]; - } - } - } - } - return target; -} - - -var debug; -if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { - debug = function() { - var args = Array.prototype.slice.call(arguments); - if (typeof args[0] === 'string') { - args[0] = 'TUNNEL: ' + args[0]; - } else { - args.unshift('TUNNEL:'); - } - console.error.apply(console, args); - } -} else { - debug = function() {}; -} -exports.debug = debug; // for test - - -/***/ }), - -/***/ 503: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -Object.defineProperty(exports, "v1", ({ - enumerable: true, - get: function () { - return _v.default; - } -})); -Object.defineProperty(exports, "v3", ({ - enumerable: true, - get: function () { - return _v2.default; - } -})); -Object.defineProperty(exports, "v4", ({ - enumerable: true, - get: function () { - return _v3.default; - } -})); -Object.defineProperty(exports, "v5", ({ - enumerable: true, - get: function () { - return _v4.default; - } -})); -Object.defineProperty(exports, "NIL", ({ - enumerable: true, - get: function () { - return _nil.default; - } -})); -Object.defineProperty(exports, "version", ({ - enumerable: true, - get: function () { - return _version.default; - } -})); -Object.defineProperty(exports, "validate", ({ - enumerable: true, - get: function () { - return _validate.default; - } -})); -Object.defineProperty(exports, "stringify", ({ - enumerable: true, - get: function () { - return _stringify.default; - } -})); -Object.defineProperty(exports, "parse", ({ - enumerable: true, - get: function () { - return _parse.default; - } -})); - -var _v = _interopRequireDefault(__nccwpck_require__(42)); - -var _v2 = _interopRequireDefault(__nccwpck_require__(377)); - -var _v3 = _interopRequireDefault(__nccwpck_require__(452)); - -var _v4 = _interopRequireDefault(__nccwpck_require__(390)); - -var _nil = _interopRequireDefault(__nccwpck_require__(691)); - -var _version = _interopRequireDefault(__nccwpck_require__(430)); - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -var _parse = _interopRequireDefault(__nccwpck_require__(590)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/***/ }), - -/***/ 940: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function md5(bytes) { - if (Array.isArray(bytes)) { - bytes = Buffer.from(bytes); - } else if (typeof bytes === 'string') { - bytes = Buffer.from(bytes, 'utf8'); - } - - return _crypto.default.createHash('md5').update(bytes).digest(); -} - -var _default = md5; -exports["default"] = _default; - -/***/ }), - -/***/ 691: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; -var _default = '00000000-0000-0000-0000-000000000000'; -exports["default"] = _default; - -/***/ }), - -/***/ 590: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function parse(uuid) { - if (!(0, _validate.default)(uuid)) { - throw TypeError('Invalid UUID'); - } - - let v; - const arr = new Uint8Array(16); // Parse ########-....-....-....-............ - - arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; - arr[1] = v >>> 16 & 0xff; - arr[2] = v >>> 8 & 0xff; - arr[3] = v & 0xff; // Parse ........-####-....-....-............ - - arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; - arr[5] = v & 0xff; // Parse ........-....-####-....-............ - - arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; - arr[7] = v & 0xff; // Parse ........-....-....-####-............ - - arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; - arr[9] = v & 0xff; // Parse ........-....-....-....-############ - // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) - - arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; - arr[11] = v / 0x100000000 & 0xff; - arr[12] = v >>> 24 & 0xff; - arr[13] = v >>> 16 & 0xff; - arr[14] = v >>> 8 & 0xff; - arr[15] = v & 0xff; - return arr; -} - -var _default = parse; -exports["default"] = _default; - -/***/ }), - -/***/ 346: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; -var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; -exports["default"] = _default; - -/***/ }), - -/***/ 720: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = rng; - -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate - -let poolPtr = rnds8Pool.length; - -function rng() { - if (poolPtr > rnds8Pool.length - 16) { - _crypto.default.randomFillSync(rnds8Pool); - - poolPtr = 0; - } - - return rnds8Pool.slice(poolPtr, poolPtr += 16); -} - -/***/ }), - -/***/ 922: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function sha1(bytes) { - if (Array.isArray(bytes)) { - bytes = Buffer.from(bytes); - } else if (typeof bytes === 'string') { - bytes = Buffer.from(bytes, 'utf8'); - } - - return _crypto.default.createHash('sha1').update(bytes).digest(); -} - -var _default = sha1; -exports["default"] = _default; - -/***/ }), - -/***/ 636: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -const byteToHex = []; - -for (let i = 0; i < 256; ++i) { - byteToHex.push((i + 0x100).toString(16).substr(1)); -} - -function stringify(arr, offset = 0) { - // Note: Be careful editing this code! It's been tuned for performance - // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 - const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one - // of the following: - // - One or more input array values don't map to a hex octet (leading to - // "undefined" in the uuid) - // - Invalid input values for the RFC `version` or `variant` fields - - if (!(0, _validate.default)(uuid)) { - throw TypeError('Stringified UUID is invalid'); - } - - return uuid; -} - -var _default = stringify; -exports["default"] = _default; - -/***/ }), - -/***/ 42: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _rng = _interopRequireDefault(__nccwpck_require__(720)); - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html -let _nodeId; - -let _clockseq; // Previous uuid creation time - - -let _lastMSecs = 0; -let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details - -function v1(options, buf, offset) { - let i = buf && offset || 0; - const b = buf || new Array(16); - options = options || {}; - let node = options.node || _nodeId; - let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - - if (node == null || clockseq == null) { - const seedBytes = options.random || (options.rng || _rng.default)(); - - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; - } - - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; - } - } // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - - - let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - - let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) - - const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression - - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - - - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } // Per 4.2.1.2 Throw error if too many uuids are requested - - - if (nsecs >= 10000) { - throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - - msecs += 12219292800000; // `time_low` - - const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; // `time_mid` - - const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; // `time_high_and_version` - - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - - b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - - b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` - - b[i++] = clockseq & 0xff; // `node` - - for (let n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } - - return buf || (0, _stringify.default)(b); -} - -var _default = v1; -exports["default"] = _default; - -/***/ }), - -/***/ 377: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _v = _interopRequireDefault(__nccwpck_require__(852)); - -var _md = _interopRequireDefault(__nccwpck_require__(940)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const v3 = (0, _v.default)('v3', 0x30, _md.default); -var _default = v3; -exports["default"] = _default; - -/***/ }), - -/***/ 852: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = _default; -exports.URL = exports.DNS = void 0; - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -var _parse = _interopRequireDefault(__nccwpck_require__(590)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function stringToBytes(str) { - str = unescape(encodeURIComponent(str)); // UTF8 escape - - const bytes = []; - - for (let i = 0; i < str.length; ++i) { - bytes.push(str.charCodeAt(i)); - } - - return bytes; -} - -const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; -exports.DNS = DNS; -const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; -exports.URL = URL; - -function _default(name, version, hashfunc) { - function generateUUID(value, namespace, buf, offset) { - if (typeof value === 'string') { - value = stringToBytes(value); - } - - if (typeof namespace === 'string') { - namespace = (0, _parse.default)(namespace); - } - - if (namespace.length !== 16) { - throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); - } // Compute hash of namespace and value, Per 4.3 - // Future: Use spread syntax when supported on all platforms, e.g. `bytes = - // hashfunc([...namespace, ... value])` - - - let bytes = new Uint8Array(16 + value.length); - bytes.set(namespace); - bytes.set(value, namespace.length); - bytes = hashfunc(bytes); - bytes[6] = bytes[6] & 0x0f | version; - bytes[8] = bytes[8] & 0x3f | 0x80; - - if (buf) { - offset = offset || 0; - - for (let i = 0; i < 16; ++i) { - buf[offset + i] = bytes[i]; - } - - return buf; - } - - return (0, _stringify.default)(bytes); - } // Function#name is not settable on some platforms (#270) - - - try { - generateUUID.name = name; // eslint-disable-next-line no-empty - } catch (err) {} // For CommonJS default export support - - - generateUUID.DNS = DNS; - generateUUID.URL = URL; - return generateUUID; -} - -/***/ }), - -/***/ 452: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _rng = _interopRequireDefault(__nccwpck_require__(720)); - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function v4(options, buf, offset) { - options = options || {}; - - const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - - - rnds[6] = rnds[6] & 0x0f | 0x40; - rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided - - if (buf) { - offset = offset || 0; - - for (let i = 0; i < 16; ++i) { - buf[offset + i] = rnds[i]; - } - - return buf; - } - - return (0, _stringify.default)(rnds); -} - -var _default = v4; -exports["default"] = _default; - -/***/ }), - -/***/ 390: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _v = _interopRequireDefault(__nccwpck_require__(852)); - -var _sha = _interopRequireDefault(__nccwpck_require__(922)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const v5 = (0, _v.default)('v5', 0x50, _sha.default); -var _default = v5; -exports["default"] = _default; - -/***/ }), - -/***/ 911: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _regex = _interopRequireDefault(__nccwpck_require__(346)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function validate(uuid) { - return typeof uuid === 'string' && _regex.default.test(uuid); -} - -var _default = validate; -exports["default"] = _default; - -/***/ }), - -/***/ 430: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function version(uuid) { - if (!(0, _validate.default)(uuid)) { - throw TypeError('Invalid UUID'); - } - - return parseInt(uuid.substr(14, 1), 16); -} - -var _default = version; -exports["default"] = _default; - -/***/ }), - -/***/ 491: -/***/ ((module) => { - -"use strict"; -module.exports = require("assert"); - -/***/ }), - -/***/ 81: -/***/ ((module) => { - -"use strict"; -module.exports = require("child_process"); - -/***/ }), - -/***/ 113: -/***/ ((module) => { - -"use strict"; -module.exports = require("crypto"); - -/***/ }), - -/***/ 361: -/***/ ((module) => { - -"use strict"; -module.exports = require("events"); - -/***/ }), - -/***/ 147: -/***/ ((module) => { - -"use strict"; -module.exports = require("fs"); - -/***/ }), - -/***/ 685: -/***/ ((module) => { - -"use strict"; -module.exports = require("http"); - -/***/ }), - -/***/ 687: -/***/ ((module) => { - -"use strict"; -module.exports = require("https"); - -/***/ }), - -/***/ 808: -/***/ ((module) => { - -"use strict"; -module.exports = require("net"); - -/***/ }), - -/***/ 37: -/***/ ((module) => { - -"use strict"; -module.exports = require("os"); - -/***/ }), - -/***/ 17: -/***/ ((module) => { - -"use strict"; -module.exports = require("path"); - -/***/ }), - -/***/ 576: -/***/ ((module) => { - -"use strict"; -module.exports = require("string_decoder"); - -/***/ }), - -/***/ 512: -/***/ ((module) => { - -"use strict"; -module.exports = require("timers"); - -/***/ }), - -/***/ 404: -/***/ ((module) => { - -"use strict"; -module.exports = require("tls"); - -/***/ }), - -/***/ 837: -/***/ ((module) => { - -"use strict"; -module.exports = require("util"); - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __nccwpck_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ var threw = true; -/******/ try { -/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); -/******/ threw = false; -/******/ } finally { -/******/ if(threw) delete __webpack_module_cache__[moduleId]; -/******/ } -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/compat */ -/******/ -/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; -/******/ -/************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { -const core = __nccwpck_require__(363); -const sweep = __nccwpck_require__(925); - -sweep.storeTimestamp().catch(core.setFailed); - -})(); - -module.exports = __webpack_exports__; -/******/ })() -; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/.github/actions/cargo-sweep/dist/main/index.js.map b/.github/actions/cargo-sweep/dist/main/index.js.map deleted file mode 100644 index 7e6adfdbb054b..0000000000000 --- a/.github/actions/cargo-sweep/dist/main/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC/UA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC1RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACzmBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5lBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AChLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACpVA;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACvQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC1GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACpBA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC7BA;AACA;;;;;;ACDA;AACA;AACA;AACA","sources":["../webpack://cargo-sweep-action/./src/sweep.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/command.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/core.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/file-command.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/oidc-utils.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/path-utils.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/summary.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/utils.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/exec.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/toolrunner.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+http-client@2.0.1/node_modules/@actions/http-client/lib/auth.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+http-client@2.0.1/node_modules/@actions/http-client/lib/index.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+http-client@2.0.1/node_modules/@actions/http-client/lib/proxy.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+io@1.1.2/node_modules/@actions/io/lib/io-util.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+io@1.1.2/node_modules/@actions/io/lib/io.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/index.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/lib/tunnel.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/index.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/md5.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/nil.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/parse.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/regex.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/rng.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/sha1.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/stringify.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v1.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v3.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v35.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v4.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v5.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/validate.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/version.js","../webpack://cargo-sweep-action/external node-commonjs \"assert\"","../webpack://cargo-sweep-action/external node-commonjs \"child_process\"","../webpack://cargo-sweep-action/external node-commonjs \"crypto\"","../webpack://cargo-sweep-action/external node-commonjs \"events\"","../webpack://cargo-sweep-action/external node-commonjs \"fs\"","../webpack://cargo-sweep-action/external node-commonjs \"http\"","../webpack://cargo-sweep-action/external node-commonjs \"https\"","../webpack://cargo-sweep-action/external node-commonjs \"net\"","../webpack://cargo-sweep-action/external node-commonjs \"os\"","../webpack://cargo-sweep-action/external node-commonjs \"path\"","../webpack://cargo-sweep-action/external node-commonjs \"string_decoder\"","../webpack://cargo-sweep-action/external node-commonjs \"timers\"","../webpack://cargo-sweep-action/external node-commonjs \"tls\"","../webpack://cargo-sweep-action/external node-commonjs \"util\"","../webpack://cargo-sweep-action/webpack/bootstrap","../webpack://cargo-sweep-action/webpack/runtime/compat","../webpack://cargo-sweep-action/./src/main.js"],"sourcesContent":["const core = require(\"@actions/core\");\nconst exec = require(\"@actions/exec\");\n\nasync function runSweep(...args) {\n // TODO(alexkirsz) A cargo change introduced a regression where cargo can't\n // find the sweep binary. This is a temporary workaround until the fix is\n // released. See:\n // https://github.com/rust-lang/cargo/pull/11814\n await exec.exec(\"cargo-sweep\", [\"sweep\", ...args]);\n}\n\nasync function storeTimestamp() {\n await core.group(\"Storing timestamp to compare later\", () =>\n runSweep(\"--stamp\")\n );\n\n core.info(\"Timestamp stored in `sweep.timestamp`\");\n}\n\nasync function sweep() {\n await core.group(\"Cleaning old build artifacts\", () => runSweep(\"--file\"));\n\n core.info(\"Removed old build artifacts.\");\n}\n\nmodule.exports = {\n storeTimestamp,\n sweep,\n};\n","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.issue = exports.issueCommand = void 0;\nconst os = __importStar(require(\"os\"));\nconst utils_1 = require(\"./utils\");\n/**\n * Commands\n *\n * Command Format:\n * ::name key=value,key=value::message\n *\n * Examples:\n * ::warning::This is the message\n * ::set-env name=MY_VAR::some value\n */\nfunction issueCommand(command, properties, message) {\n const cmd = new Command(command, properties, message);\n process.stdout.write(cmd.toString() + os.EOL);\n}\nexports.issueCommand = issueCommand;\nfunction issue(name, message = '') {\n issueCommand(name, {}, message);\n}\nexports.issue = issue;\nconst CMD_STRING = '::';\nclass Command {\n constructor(command, properties, message) {\n if (!command) {\n command = 'missing.command';\n }\n this.command = command;\n this.properties = properties;\n this.message = message;\n }\n toString() {\n let cmdStr = CMD_STRING + this.command;\n if (this.properties && Object.keys(this.properties).length > 0) {\n cmdStr += ' ';\n let first = true;\n for (const key in this.properties) {\n if (this.properties.hasOwnProperty(key)) {\n const val = this.properties[key];\n if (val) {\n if (first) {\n first = false;\n }\n else {\n cmdStr += ',';\n }\n cmdStr += `${key}=${escapeProperty(val)}`;\n }\n }\n }\n }\n cmdStr += `${CMD_STRING}${escapeData(this.message)}`;\n return cmdStr;\n }\n}\nfunction escapeData(s) {\n return utils_1.toCommandValue(s)\n .replace(/%/g, '%25')\n .replace(/\\r/g, '%0D')\n .replace(/\\n/g, '%0A');\n}\nfunction escapeProperty(s) {\n return utils_1.toCommandValue(s)\n .replace(/%/g, '%25')\n .replace(/\\r/g, '%0D')\n .replace(/\\n/g, '%0A')\n .replace(/:/g, '%3A')\n .replace(/,/g, '%2C');\n}\n//# sourceMappingURL=command.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0;\nconst command_1 = require(\"./command\");\nconst file_command_1 = require(\"./file-command\");\nconst utils_1 = require(\"./utils\");\nconst os = __importStar(require(\"os\"));\nconst path = __importStar(require(\"path\"));\nconst oidc_utils_1 = require(\"./oidc-utils\");\n/**\n * The code to exit an action\n */\nvar ExitCode;\n(function (ExitCode) {\n /**\n * A code indicating that the action was successful\n */\n ExitCode[ExitCode[\"Success\"] = 0] = \"Success\";\n /**\n * A code indicating that the action was a failure\n */\n ExitCode[ExitCode[\"Failure\"] = 1] = \"Failure\";\n})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));\n//-----------------------------------------------------------------------\n// Variables\n//-----------------------------------------------------------------------\n/**\n * Sets env variable for this action and future actions in the job\n * @param name the name of the variable to set\n * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction exportVariable(name, val) {\n const convertedVal = utils_1.toCommandValue(val);\n process.env[name] = convertedVal;\n const filePath = process.env['GITHUB_ENV'] || '';\n if (filePath) {\n return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val));\n }\n command_1.issueCommand('set-env', { name }, convertedVal);\n}\nexports.exportVariable = exportVariable;\n/**\n * Registers a secret which will get masked from logs\n * @param secret value of the secret\n */\nfunction setSecret(secret) {\n command_1.issueCommand('add-mask', {}, secret);\n}\nexports.setSecret = setSecret;\n/**\n * Prepends inputPath to the PATH (for this action and future actions)\n * @param inputPath\n */\nfunction addPath(inputPath) {\n const filePath = process.env['GITHUB_PATH'] || '';\n if (filePath) {\n file_command_1.issueFileCommand('PATH', inputPath);\n }\n else {\n command_1.issueCommand('add-path', {}, inputPath);\n }\n process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;\n}\nexports.addPath = addPath;\n/**\n * Gets the value of an input.\n * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed.\n * Returns an empty string if the value is not defined.\n *\n * @param name name of the input to get\n * @param options optional. See InputOptions.\n * @returns string\n */\nfunction getInput(name, options) {\n const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';\n if (options && options.required && !val) {\n throw new Error(`Input required and not supplied: ${name}`);\n }\n if (options && options.trimWhitespace === false) {\n return val;\n }\n return val.trim();\n}\nexports.getInput = getInput;\n/**\n * Gets the values of an multiline input. Each value is also trimmed.\n *\n * @param name name of the input to get\n * @param options optional. See InputOptions.\n * @returns string[]\n *\n */\nfunction getMultilineInput(name, options) {\n const inputs = getInput(name, options)\n .split('\\n')\n .filter(x => x !== '');\n if (options && options.trimWhitespace === false) {\n return inputs;\n }\n return inputs.map(input => input.trim());\n}\nexports.getMultilineInput = getMultilineInput;\n/**\n * Gets the input value of the boolean type in the YAML 1.2 \"core schema\" specification.\n * Support boolean input list: `true | True | TRUE | false | False | FALSE` .\n * The return value is also in boolean type.\n * ref: https://yaml.org/spec/1.2/spec.html#id2804923\n *\n * @param name name of the input to get\n * @param options optional. See InputOptions.\n * @returns boolean\n */\nfunction getBooleanInput(name, options) {\n const trueValue = ['true', 'True', 'TRUE'];\n const falseValue = ['false', 'False', 'FALSE'];\n const val = getInput(name, options);\n if (trueValue.includes(val))\n return true;\n if (falseValue.includes(val))\n return false;\n throw new TypeError(`Input does not meet YAML 1.2 \"Core Schema\" specification: ${name}\\n` +\n `Support boolean input list: \\`true | True | TRUE | false | False | FALSE\\``);\n}\nexports.getBooleanInput = getBooleanInput;\n/**\n * Sets the value of an output.\n *\n * @param name name of the output to set\n * @param value value to store. Non-string values will be converted to a string via JSON.stringify\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction setOutput(name, value) {\n const filePath = process.env['GITHUB_OUTPUT'] || '';\n if (filePath) {\n return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value));\n }\n process.stdout.write(os.EOL);\n command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value));\n}\nexports.setOutput = setOutput;\n/**\n * Enables or disables the echoing of commands into stdout for the rest of the step.\n * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.\n *\n */\nfunction setCommandEcho(enabled) {\n command_1.issue('echo', enabled ? 'on' : 'off');\n}\nexports.setCommandEcho = setCommandEcho;\n//-----------------------------------------------------------------------\n// Results\n//-----------------------------------------------------------------------\n/**\n * Sets the action status to failed.\n * When the action exits it will be with an exit code of 1\n * @param message add error issue message\n */\nfunction setFailed(message) {\n process.exitCode = ExitCode.Failure;\n error(message);\n}\nexports.setFailed = setFailed;\n//-----------------------------------------------------------------------\n// Logging Commands\n//-----------------------------------------------------------------------\n/**\n * Gets whether Actions Step Debug is on or not\n */\nfunction isDebug() {\n return process.env['RUNNER_DEBUG'] === '1';\n}\nexports.isDebug = isDebug;\n/**\n * Writes debug message to user log\n * @param message debug message\n */\nfunction debug(message) {\n command_1.issueCommand('debug', {}, message);\n}\nexports.debug = debug;\n/**\n * Adds an error issue\n * @param message error issue message. Errors will be converted to string via toString()\n * @param properties optional properties to add to the annotation.\n */\nfunction error(message, properties = {}) {\n command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message);\n}\nexports.error = error;\n/**\n * Adds a warning issue\n * @param message warning issue message. Errors will be converted to string via toString()\n * @param properties optional properties to add to the annotation.\n */\nfunction warning(message, properties = {}) {\n command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message);\n}\nexports.warning = warning;\n/**\n * Adds a notice issue\n * @param message notice issue message. Errors will be converted to string via toString()\n * @param properties optional properties to add to the annotation.\n */\nfunction notice(message, properties = {}) {\n command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message);\n}\nexports.notice = notice;\n/**\n * Writes info to log with console.log.\n * @param message info message\n */\nfunction info(message) {\n process.stdout.write(message + os.EOL);\n}\nexports.info = info;\n/**\n * Begin an output group.\n *\n * Output until the next `groupEnd` will be foldable in this group\n *\n * @param name The name of the output group\n */\nfunction startGroup(name) {\n command_1.issue('group', name);\n}\nexports.startGroup = startGroup;\n/**\n * End an output group.\n */\nfunction endGroup() {\n command_1.issue('endgroup');\n}\nexports.endGroup = endGroup;\n/**\n * Wrap an asynchronous function call in a group.\n *\n * Returns the same type as the function itself.\n *\n * @param name The name of the group\n * @param fn The function to wrap in the group\n */\nfunction group(name, fn) {\n return __awaiter(this, void 0, void 0, function* () {\n startGroup(name);\n let result;\n try {\n result = yield fn();\n }\n finally {\n endGroup();\n }\n return result;\n });\n}\nexports.group = group;\n//-----------------------------------------------------------------------\n// Wrapper action state\n//-----------------------------------------------------------------------\n/**\n * Saves state for current action, the state can only be retrieved by this action's post job execution.\n *\n * @param name name of the state to store\n * @param value value to store. Non-string values will be converted to a string via JSON.stringify\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction saveState(name, value) {\n const filePath = process.env['GITHUB_STATE'] || '';\n if (filePath) {\n return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value));\n }\n command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value));\n}\nexports.saveState = saveState;\n/**\n * Gets the value of an state set by this action's main execution.\n *\n * @param name name of the state to get\n * @returns string\n */\nfunction getState(name) {\n return process.env[`STATE_${name}`] || '';\n}\nexports.getState = getState;\nfunction getIDToken(aud) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield oidc_utils_1.OidcClient.getIDToken(aud);\n });\n}\nexports.getIDToken = getIDToken;\n/**\n * Summary exports\n */\nvar summary_1 = require(\"./summary\");\nObject.defineProperty(exports, \"summary\", { enumerable: true, get: function () { return summary_1.summary; } });\n/**\n * @deprecated use core.summary\n */\nvar summary_2 = require(\"./summary\");\nObject.defineProperty(exports, \"markdownSummary\", { enumerable: true, get: function () { return summary_2.markdownSummary; } });\n/**\n * Path exports\n */\nvar path_utils_1 = require(\"./path-utils\");\nObject.defineProperty(exports, \"toPosixPath\", { enumerable: true, get: function () { return path_utils_1.toPosixPath; } });\nObject.defineProperty(exports, \"toWin32Path\", { enumerable: true, get: function () { return path_utils_1.toWin32Path; } });\nObject.defineProperty(exports, \"toPlatformPath\", { enumerable: true, get: function () { return path_utils_1.toPlatformPath; } });\n//# sourceMappingURL=core.js.map","\"use strict\";\n// For internal use, subject to change.\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.prepareKeyValueMessage = exports.issueFileCommand = void 0;\n// We use any as a valid input type\n/* eslint-disable @typescript-eslint/no-explicit-any */\nconst fs = __importStar(require(\"fs\"));\nconst os = __importStar(require(\"os\"));\nconst uuid_1 = require(\"uuid\");\nconst utils_1 = require(\"./utils\");\nfunction issueFileCommand(command, message) {\n const filePath = process.env[`GITHUB_${command}`];\n if (!filePath) {\n throw new Error(`Unable to find environment variable for file command ${command}`);\n }\n if (!fs.existsSync(filePath)) {\n throw new Error(`Missing file at path: ${filePath}`);\n }\n fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, {\n encoding: 'utf8'\n });\n}\nexports.issueFileCommand = issueFileCommand;\nfunction prepareKeyValueMessage(key, value) {\n const delimiter = `ghadelimiter_${uuid_1.v4()}`;\n const convertedValue = utils_1.toCommandValue(value);\n // These should realistically never happen, but just in case someone finds a\n // way to exploit uuid generation let's not allow keys or values that contain\n // the delimiter.\n if (key.includes(delimiter)) {\n throw new Error(`Unexpected input: name should not contain the delimiter \"${delimiter}\"`);\n }\n if (convertedValue.includes(delimiter)) {\n throw new Error(`Unexpected input: value should not contain the delimiter \"${delimiter}\"`);\n }\n return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`;\n}\nexports.prepareKeyValueMessage = prepareKeyValueMessage;\n//# sourceMappingURL=file-command.js.map","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.OidcClient = void 0;\nconst http_client_1 = require(\"@actions/http-client\");\nconst auth_1 = require(\"@actions/http-client/lib/auth\");\nconst core_1 = require(\"./core\");\nclass OidcClient {\n static createHttpClient(allowRetry = true, maxRetry = 10) {\n const requestOptions = {\n allowRetries: allowRetry,\n maxRetries: maxRetry\n };\n return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions);\n }\n static getRequestToken() {\n const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'];\n if (!token) {\n throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable');\n }\n return token;\n }\n static getIDTokenUrl() {\n const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL'];\n if (!runtimeUrl) {\n throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable');\n }\n return runtimeUrl;\n }\n static getCall(id_token_url) {\n var _a;\n return __awaiter(this, void 0, void 0, function* () {\n const httpclient = OidcClient.createHttpClient();\n const res = yield httpclient\n .getJson(id_token_url)\n .catch(error => {\n throw new Error(`Failed to get ID Token. \\n \n Error Code : ${error.statusCode}\\n \n Error Message: ${error.result.message}`);\n });\n const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value;\n if (!id_token) {\n throw new Error('Response json body do not have ID Token field');\n }\n return id_token;\n });\n }\n static getIDToken(audience) {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n // New ID Token is requested from action service\n let id_token_url = OidcClient.getIDTokenUrl();\n if (audience) {\n const encodedAudience = encodeURIComponent(audience);\n id_token_url = `${id_token_url}&audience=${encodedAudience}`;\n }\n core_1.debug(`ID token url is ${id_token_url}`);\n const id_token = yield OidcClient.getCall(id_token_url);\n core_1.setSecret(id_token);\n return id_token;\n }\n catch (error) {\n throw new Error(`Error message: ${error.message}`);\n }\n });\n }\n}\nexports.OidcClient = OidcClient;\n//# sourceMappingURL=oidc-utils.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0;\nconst path = __importStar(require(\"path\"));\n/**\n * toPosixPath converts the given path to the posix form. On Windows, \\\\ will be\n * replaced with /.\n *\n * @param pth. Path to transform.\n * @return string Posix path.\n */\nfunction toPosixPath(pth) {\n return pth.replace(/[\\\\]/g, '/');\n}\nexports.toPosixPath = toPosixPath;\n/**\n * toWin32Path converts the given path to the win32 form. On Linux, / will be\n * replaced with \\\\.\n *\n * @param pth. Path to transform.\n * @return string Win32 path.\n */\nfunction toWin32Path(pth) {\n return pth.replace(/[/]/g, '\\\\');\n}\nexports.toWin32Path = toWin32Path;\n/**\n * toPlatformPath converts the given path to a platform-specific path. It does\n * this by replacing instances of / and \\ with the platform-specific path\n * separator.\n *\n * @param pth The path to platformize.\n * @return string The platform-specific path.\n */\nfunction toPlatformPath(pth) {\n return pth.replace(/[/\\\\]/g, path.sep);\n}\nexports.toPlatformPath = toPlatformPath;\n//# sourceMappingURL=path-utils.js.map","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0;\nconst os_1 = require(\"os\");\nconst fs_1 = require(\"fs\");\nconst { access, appendFile, writeFile } = fs_1.promises;\nexports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY';\nexports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary';\nclass Summary {\n constructor() {\n this._buffer = '';\n }\n /**\n * Finds the summary file path from the environment, rejects if env var is not found or file does not exist\n * Also checks r/w permissions.\n *\n * @returns step summary file path\n */\n filePath() {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._filePath) {\n return this._filePath;\n }\n const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR];\n if (!pathFromEnv) {\n throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`);\n }\n try {\n yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK);\n }\n catch (_a) {\n throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`);\n }\n this._filePath = pathFromEnv;\n return this._filePath;\n });\n }\n /**\n * Wraps content in an HTML tag, adding any HTML attributes\n *\n * @param {string} tag HTML tag to wrap\n * @param {string | null} content content within the tag\n * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add\n *\n * @returns {string} content wrapped in HTML element\n */\n wrap(tag, content, attrs = {}) {\n const htmlAttrs = Object.entries(attrs)\n .map(([key, value]) => ` ${key}=\"${value}\"`)\n .join('');\n if (!content) {\n return `<${tag}${htmlAttrs}>`;\n }\n return `<${tag}${htmlAttrs}>${content}`;\n }\n /**\n * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default.\n *\n * @param {SummaryWriteOptions} [options] (optional) options for write operation\n *\n * @returns {Promise} summary instance\n */\n write(options) {\n return __awaiter(this, void 0, void 0, function* () {\n const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite);\n const filePath = yield this.filePath();\n const writeFunc = overwrite ? writeFile : appendFile;\n yield writeFunc(filePath, this._buffer, { encoding: 'utf8' });\n return this.emptyBuffer();\n });\n }\n /**\n * Clears the summary buffer and wipes the summary file\n *\n * @returns {Summary} summary instance\n */\n clear() {\n return __awaiter(this, void 0, void 0, function* () {\n return this.emptyBuffer().write({ overwrite: true });\n });\n }\n /**\n * Returns the current summary buffer as a string\n *\n * @returns {string} string of summary buffer\n */\n stringify() {\n return this._buffer;\n }\n /**\n * If the summary buffer is empty\n *\n * @returns {boolen} true if the buffer is empty\n */\n isEmptyBuffer() {\n return this._buffer.length === 0;\n }\n /**\n * Resets the summary buffer without writing to summary file\n *\n * @returns {Summary} summary instance\n */\n emptyBuffer() {\n this._buffer = '';\n return this;\n }\n /**\n * Adds raw text to the summary buffer\n *\n * @param {string} text content to add\n * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false)\n *\n * @returns {Summary} summary instance\n */\n addRaw(text, addEOL = false) {\n this._buffer += text;\n return addEOL ? this.addEOL() : this;\n }\n /**\n * Adds the operating system-specific end-of-line marker to the buffer\n *\n * @returns {Summary} summary instance\n */\n addEOL() {\n return this.addRaw(os_1.EOL);\n }\n /**\n * Adds an HTML codeblock to the summary buffer\n *\n * @param {string} code content to render within fenced code block\n * @param {string} lang (optional) language to syntax highlight code\n *\n * @returns {Summary} summary instance\n */\n addCodeBlock(code, lang) {\n const attrs = Object.assign({}, (lang && { lang }));\n const element = this.wrap('pre', this.wrap('code', code), attrs);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML list to the summary buffer\n *\n * @param {string[]} items list of items to render\n * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false)\n *\n * @returns {Summary} summary instance\n */\n addList(items, ordered = false) {\n const tag = ordered ? 'ol' : 'ul';\n const listItems = items.map(item => this.wrap('li', item)).join('');\n const element = this.wrap(tag, listItems);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML table to the summary buffer\n *\n * @param {SummaryTableCell[]} rows table rows\n *\n * @returns {Summary} summary instance\n */\n addTable(rows) {\n const tableBody = rows\n .map(row => {\n const cells = row\n .map(cell => {\n if (typeof cell === 'string') {\n return this.wrap('td', cell);\n }\n const { header, data, colspan, rowspan } = cell;\n const tag = header ? 'th' : 'td';\n const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan }));\n return this.wrap(tag, data, attrs);\n })\n .join('');\n return this.wrap('tr', cells);\n })\n .join('');\n const element = this.wrap('table', tableBody);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds a collapsable HTML details element to the summary buffer\n *\n * @param {string} label text for the closed state\n * @param {string} content collapsable content\n *\n * @returns {Summary} summary instance\n */\n addDetails(label, content) {\n const element = this.wrap('details', this.wrap('summary', label) + content);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML image tag to the summary buffer\n *\n * @param {string} src path to the image you to embed\n * @param {string} alt text description of the image\n * @param {SummaryImageOptions} options (optional) addition image attributes\n *\n * @returns {Summary} summary instance\n */\n addImage(src, alt, options) {\n const { width, height } = options || {};\n const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height }));\n const element = this.wrap('img', null, Object.assign({ src, alt }, attrs));\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML section heading element\n *\n * @param {string} text heading text\n * @param {number | string} [level=1] (optional) the heading level, default: 1\n *\n * @returns {Summary} summary instance\n */\n addHeading(text, level) {\n const tag = `h${level}`;\n const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag)\n ? tag\n : 'h1';\n const element = this.wrap(allowedTag, text);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML thematic break (
) to the summary buffer\n *\n * @returns {Summary} summary instance\n */\n addSeparator() {\n const element = this.wrap('hr', null);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML line break (
) to the summary buffer\n *\n * @returns {Summary} summary instance\n */\n addBreak() {\n const element = this.wrap('br', null);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML blockquote to the summary buffer\n *\n * @param {string} text quote text\n * @param {string} cite (optional) citation url\n *\n * @returns {Summary} summary instance\n */\n addQuote(text, cite) {\n const attrs = Object.assign({}, (cite && { cite }));\n const element = this.wrap('blockquote', text, attrs);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML anchor tag to the summary buffer\n *\n * @param {string} text link text/content\n * @param {string} href hyperlink\n *\n * @returns {Summary} summary instance\n */\n addLink(text, href) {\n const element = this.wrap('a', text, { href });\n return this.addRaw(element).addEOL();\n }\n}\nconst _summary = new Summary();\n/**\n * @deprecated use `core.summary`\n */\nexports.markdownSummary = _summary;\nexports.summary = _summary;\n//# sourceMappingURL=summary.js.map","\"use strict\";\n// We use any as a valid input type\n/* eslint-disable @typescript-eslint/no-explicit-any */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.toCommandProperties = exports.toCommandValue = void 0;\n/**\n * Sanitizes an input into a string so it can be passed into issueCommand safely\n * @param input input to sanitize into a string\n */\nfunction toCommandValue(input) {\n if (input === null || input === undefined) {\n return '';\n }\n else if (typeof input === 'string' || input instanceof String) {\n return input;\n }\n return JSON.stringify(input);\n}\nexports.toCommandValue = toCommandValue;\n/**\n *\n * @param annotationProperties\n * @returns The command properties to send with the actual annotation command\n * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646\n */\nfunction toCommandProperties(annotationProperties) {\n if (!Object.keys(annotationProperties).length) {\n return {};\n }\n return {\n title: annotationProperties.title,\n file: annotationProperties.file,\n line: annotationProperties.startLine,\n endLine: annotationProperties.endLine,\n col: annotationProperties.startColumn,\n endColumn: annotationProperties.endColumn\n };\n}\nexports.toCommandProperties = toCommandProperties;\n//# sourceMappingURL=utils.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getExecOutput = exports.exec = void 0;\nconst string_decoder_1 = require(\"string_decoder\");\nconst tr = __importStar(require(\"./toolrunner\"));\n/**\n * Exec a command.\n * Output will be streamed to the live console.\n * Returns promise with return code\n *\n * @param commandLine command to execute (can include additional args). Must be correctly escaped.\n * @param args optional arguments for tool. Escaping is handled by the lib.\n * @param options optional exec options. See ExecOptions\n * @returns Promise exit code\n */\nfunction exec(commandLine, args, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const commandArgs = tr.argStringToArray(commandLine);\n if (commandArgs.length === 0) {\n throw new Error(`Parameter 'commandLine' cannot be null or empty.`);\n }\n // Path to tool to execute should be first arg\n const toolPath = commandArgs[0];\n args = commandArgs.slice(1).concat(args || []);\n const runner = new tr.ToolRunner(toolPath, args, options);\n return runner.exec();\n });\n}\nexports.exec = exec;\n/**\n * Exec a command and get the output.\n * Output will be streamed to the live console.\n * Returns promise with the exit code and collected stdout and stderr\n *\n * @param commandLine command to execute (can include additional args). Must be correctly escaped.\n * @param args optional arguments for tool. Escaping is handled by the lib.\n * @param options optional exec options. See ExecOptions\n * @returns Promise exit code, stdout, and stderr\n */\nfunction getExecOutput(commandLine, args, options) {\n var _a, _b;\n return __awaiter(this, void 0, void 0, function* () {\n let stdout = '';\n let stderr = '';\n //Using string decoder covers the case where a mult-byte character is split\n const stdoutDecoder = new string_decoder_1.StringDecoder('utf8');\n const stderrDecoder = new string_decoder_1.StringDecoder('utf8');\n const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout;\n const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr;\n const stdErrListener = (data) => {\n stderr += stderrDecoder.write(data);\n if (originalStdErrListener) {\n originalStdErrListener(data);\n }\n };\n const stdOutListener = (data) => {\n stdout += stdoutDecoder.write(data);\n if (originalStdoutListener) {\n originalStdoutListener(data);\n }\n };\n const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener });\n const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners }));\n //flush any remaining characters\n stdout += stdoutDecoder.end();\n stderr += stderrDecoder.end();\n return {\n exitCode,\n stdout,\n stderr\n };\n });\n}\nexports.getExecOutput = getExecOutput;\n//# sourceMappingURL=exec.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.argStringToArray = exports.ToolRunner = void 0;\nconst os = __importStar(require(\"os\"));\nconst events = __importStar(require(\"events\"));\nconst child = __importStar(require(\"child_process\"));\nconst path = __importStar(require(\"path\"));\nconst io = __importStar(require(\"@actions/io\"));\nconst ioUtil = __importStar(require(\"@actions/io/lib/io-util\"));\nconst timers_1 = require(\"timers\");\n/* eslint-disable @typescript-eslint/unbound-method */\nconst IS_WINDOWS = process.platform === 'win32';\n/*\n * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way.\n */\nclass ToolRunner extends events.EventEmitter {\n constructor(toolPath, args, options) {\n super();\n if (!toolPath) {\n throw new Error(\"Parameter 'toolPath' cannot be null or empty.\");\n }\n this.toolPath = toolPath;\n this.args = args || [];\n this.options = options || {};\n }\n _debug(message) {\n if (this.options.listeners && this.options.listeners.debug) {\n this.options.listeners.debug(message);\n }\n }\n _getCommandString(options, noPrefix) {\n const toolPath = this._getSpawnFileName();\n const args = this._getSpawnArgs(options);\n let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool\n if (IS_WINDOWS) {\n // Windows + cmd file\n if (this._isCmdFile()) {\n cmd += toolPath;\n for (const a of args) {\n cmd += ` ${a}`;\n }\n }\n // Windows + verbatim\n else if (options.windowsVerbatimArguments) {\n cmd += `\"${toolPath}\"`;\n for (const a of args) {\n cmd += ` ${a}`;\n }\n }\n // Windows (regular)\n else {\n cmd += this._windowsQuoteCmdArg(toolPath);\n for (const a of args) {\n cmd += ` ${this._windowsQuoteCmdArg(a)}`;\n }\n }\n }\n else {\n // OSX/Linux - this can likely be improved with some form of quoting.\n // creating processes on Unix is fundamentally different than Windows.\n // on Unix, execvp() takes an arg array.\n cmd += toolPath;\n for (const a of args) {\n cmd += ` ${a}`;\n }\n }\n return cmd;\n }\n _processLineBuffer(data, strBuffer, onLine) {\n try {\n let s = strBuffer + data.toString();\n let n = s.indexOf(os.EOL);\n while (n > -1) {\n const line = s.substring(0, n);\n onLine(line);\n // the rest of the string ...\n s = s.substring(n + os.EOL.length);\n n = s.indexOf(os.EOL);\n }\n return s;\n }\n catch (err) {\n // streaming lines to console is best effort. Don't fail a build.\n this._debug(`error processing line. Failed with error ${err}`);\n return '';\n }\n }\n _getSpawnFileName() {\n if (IS_WINDOWS) {\n if (this._isCmdFile()) {\n return process.env['COMSPEC'] || 'cmd.exe';\n }\n }\n return this.toolPath;\n }\n _getSpawnArgs(options) {\n if (IS_WINDOWS) {\n if (this._isCmdFile()) {\n let argline = `/D /S /C \"${this._windowsQuoteCmdArg(this.toolPath)}`;\n for (const a of this.args) {\n argline += ' ';\n argline += options.windowsVerbatimArguments\n ? a\n : this._windowsQuoteCmdArg(a);\n }\n argline += '\"';\n return [argline];\n }\n }\n return this.args;\n }\n _endsWith(str, end) {\n return str.endsWith(end);\n }\n _isCmdFile() {\n const upperToolPath = this.toolPath.toUpperCase();\n return (this._endsWith(upperToolPath, '.CMD') ||\n this._endsWith(upperToolPath, '.BAT'));\n }\n _windowsQuoteCmdArg(arg) {\n // for .exe, apply the normal quoting rules that libuv applies\n if (!this._isCmdFile()) {\n return this._uvQuoteCmdArg(arg);\n }\n // otherwise apply quoting rules specific to the cmd.exe command line parser.\n // the libuv rules are generic and are not designed specifically for cmd.exe\n // command line parser.\n //\n // for a detailed description of the cmd.exe command line parser, refer to\n // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912\n // need quotes for empty arg\n if (!arg) {\n return '\"\"';\n }\n // determine whether the arg needs to be quoted\n const cmdSpecialChars = [\n ' ',\n '\\t',\n '&',\n '(',\n ')',\n '[',\n ']',\n '{',\n '}',\n '^',\n '=',\n ';',\n '!',\n \"'\",\n '+',\n ',',\n '`',\n '~',\n '|',\n '<',\n '>',\n '\"'\n ];\n let needsQuotes = false;\n for (const char of arg) {\n if (cmdSpecialChars.some(x => x === char)) {\n needsQuotes = true;\n break;\n }\n }\n // short-circuit if quotes not needed\n if (!needsQuotes) {\n return arg;\n }\n // the following quoting rules are very similar to the rules that by libuv applies.\n //\n // 1) wrap the string in quotes\n //\n // 2) double-up quotes - i.e. \" => \"\"\n //\n // this is different from the libuv quoting rules. libuv replaces \" with \\\", which unfortunately\n // doesn't work well with a cmd.exe command line.\n //\n // note, replacing \" with \"\" also works well if the arg is passed to a downstream .NET console app.\n // for example, the command line:\n // foo.exe \"myarg:\"\"my val\"\"\"\n // is parsed by a .NET console app into an arg array:\n // [ \"myarg:\\\"my val\\\"\" ]\n // which is the same end result when applying libuv quoting rules. although the actual\n // command line from libuv quoting rules would look like:\n // foo.exe \"myarg:\\\"my val\\\"\"\n //\n // 3) double-up slashes that precede a quote,\n // e.g. hello \\world => \"hello \\world\"\n // hello\\\"world => \"hello\\\\\"\"world\"\n // hello\\\\\"world => \"hello\\\\\\\\\"\"world\"\n // hello world\\ => \"hello world\\\\\"\n //\n // technically this is not required for a cmd.exe command line, or the batch argument parser.\n // the reasons for including this as a .cmd quoting rule are:\n //\n // a) this is optimized for the scenario where the argument is passed from the .cmd file to an\n // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.\n //\n // b) it's what we've been doing previously (by deferring to node default behavior) and we\n // haven't heard any complaints about that aspect.\n //\n // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be\n // escaped when used on the command line directly - even though within a .cmd file % can be escaped\n // by using %%.\n //\n // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts\n // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.\n //\n // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would\n // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the\n // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args\n // to an external program.\n //\n // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.\n // % can be escaped within a .cmd file.\n let reverse = '\"';\n let quoteHit = true;\n for (let i = arg.length; i > 0; i--) {\n // walk the string in reverse\n reverse += arg[i - 1];\n if (quoteHit && arg[i - 1] === '\\\\') {\n reverse += '\\\\'; // double the slash\n }\n else if (arg[i - 1] === '\"') {\n quoteHit = true;\n reverse += '\"'; // double the quote\n }\n else {\n quoteHit = false;\n }\n }\n reverse += '\"';\n return reverse\n .split('')\n .reverse()\n .join('');\n }\n _uvQuoteCmdArg(arg) {\n // Tool runner wraps child_process.spawn() and needs to apply the same quoting as\n // Node in certain cases where the undocumented spawn option windowsVerbatimArguments\n // is used.\n //\n // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,\n // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),\n // pasting copyright notice from Node within this function:\n //\n // Copyright Joyent, Inc. and other Node contributors. All rights reserved.\n //\n // Permission is hereby granted, free of charge, to any person obtaining a copy\n // of this software and associated documentation files (the \"Software\"), to\n // deal in the Software without restriction, including without limitation the\n // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n // sell copies of the Software, and to permit persons to whom the Software is\n // furnished to do so, subject to the following conditions:\n //\n // The above copyright notice and this permission notice shall be included in\n // all copies or substantial portions of the Software.\n //\n // THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n // IN THE SOFTWARE.\n if (!arg) {\n // Need double quotation for empty argument\n return '\"\"';\n }\n if (!arg.includes(' ') && !arg.includes('\\t') && !arg.includes('\"')) {\n // No quotation needed\n return arg;\n }\n if (!arg.includes('\"') && !arg.includes('\\\\')) {\n // No embedded double quotes or backslashes, so I can just wrap\n // quote marks around the whole thing.\n return `\"${arg}\"`;\n }\n // Expected input/output:\n // input : hello\"world\n // output: \"hello\\\"world\"\n // input : hello\"\"world\n // output: \"hello\\\"\\\"world\"\n // input : hello\\world\n // output: hello\\world\n // input : hello\\\\world\n // output: hello\\\\world\n // input : hello\\\"world\n // output: \"hello\\\\\\\"world\"\n // input : hello\\\\\"world\n // output: \"hello\\\\\\\\\\\"world\"\n // input : hello world\\\n // output: \"hello world\\\\\" - note the comment in libuv actually reads \"hello world\\\"\n // but it appears the comment is wrong, it should be \"hello world\\\\\"\n let reverse = '\"';\n let quoteHit = true;\n for (let i = arg.length; i > 0; i--) {\n // walk the string in reverse\n reverse += arg[i - 1];\n if (quoteHit && arg[i - 1] === '\\\\') {\n reverse += '\\\\';\n }\n else if (arg[i - 1] === '\"') {\n quoteHit = true;\n reverse += '\\\\';\n }\n else {\n quoteHit = false;\n }\n }\n reverse += '\"';\n return reverse\n .split('')\n .reverse()\n .join('');\n }\n _cloneExecOptions(options) {\n options = options || {};\n const result = {\n cwd: options.cwd || process.cwd(),\n env: options.env || process.env,\n silent: options.silent || false,\n windowsVerbatimArguments: options.windowsVerbatimArguments || false,\n failOnStdErr: options.failOnStdErr || false,\n ignoreReturnCode: options.ignoreReturnCode || false,\n delay: options.delay || 10000\n };\n result.outStream = options.outStream || process.stdout;\n result.errStream = options.errStream || process.stderr;\n return result;\n }\n _getSpawnOptions(options, toolPath) {\n options = options || {};\n const result = {};\n result.cwd = options.cwd;\n result.env = options.env;\n result['windowsVerbatimArguments'] =\n options.windowsVerbatimArguments || this._isCmdFile();\n if (options.windowsVerbatimArguments) {\n result.argv0 = `\"${toolPath}\"`;\n }\n return result;\n }\n /**\n * Exec a tool.\n * Output will be streamed to the live console.\n * Returns promise with return code\n *\n * @param tool path to tool to exec\n * @param options optional exec options. See ExecOptions\n * @returns number\n */\n exec() {\n return __awaiter(this, void 0, void 0, function* () {\n // root the tool path if it is unrooted and contains relative pathing\n if (!ioUtil.isRooted(this.toolPath) &&\n (this.toolPath.includes('/') ||\n (IS_WINDOWS && this.toolPath.includes('\\\\')))) {\n // prefer options.cwd if it is specified, however options.cwd may also need to be rooted\n this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath);\n }\n // if the tool is only a file name, then resolve it from the PATH\n // otherwise verify it exists (add extension on Windows if necessary)\n this.toolPath = yield io.which(this.toolPath, true);\n return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {\n this._debug(`exec tool: ${this.toolPath}`);\n this._debug('arguments:');\n for (const arg of this.args) {\n this._debug(` ${arg}`);\n }\n const optionsNonNull = this._cloneExecOptions(this.options);\n if (!optionsNonNull.silent && optionsNonNull.outStream) {\n optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);\n }\n const state = new ExecState(optionsNonNull, this.toolPath);\n state.on('debug', (message) => {\n this._debug(message);\n });\n if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) {\n return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`));\n }\n const fileName = this._getSpawnFileName();\n const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName));\n let stdbuffer = '';\n if (cp.stdout) {\n cp.stdout.on('data', (data) => {\n if (this.options.listeners && this.options.listeners.stdout) {\n this.options.listeners.stdout(data);\n }\n if (!optionsNonNull.silent && optionsNonNull.outStream) {\n optionsNonNull.outStream.write(data);\n }\n stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => {\n if (this.options.listeners && this.options.listeners.stdline) {\n this.options.listeners.stdline(line);\n }\n });\n });\n }\n let errbuffer = '';\n if (cp.stderr) {\n cp.stderr.on('data', (data) => {\n state.processStderr = true;\n if (this.options.listeners && this.options.listeners.stderr) {\n this.options.listeners.stderr(data);\n }\n if (!optionsNonNull.silent &&\n optionsNonNull.errStream &&\n optionsNonNull.outStream) {\n const s = optionsNonNull.failOnStdErr\n ? optionsNonNull.errStream\n : optionsNonNull.outStream;\n s.write(data);\n }\n errbuffer = this._processLineBuffer(data, errbuffer, (line) => {\n if (this.options.listeners && this.options.listeners.errline) {\n this.options.listeners.errline(line);\n }\n });\n });\n }\n cp.on('error', (err) => {\n state.processError = err.message;\n state.processExited = true;\n state.processClosed = true;\n state.CheckComplete();\n });\n cp.on('exit', (code) => {\n state.processExitCode = code;\n state.processExited = true;\n this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);\n state.CheckComplete();\n });\n cp.on('close', (code) => {\n state.processExitCode = code;\n state.processExited = true;\n state.processClosed = true;\n this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);\n state.CheckComplete();\n });\n state.on('done', (error, exitCode) => {\n if (stdbuffer.length > 0) {\n this.emit('stdline', stdbuffer);\n }\n if (errbuffer.length > 0) {\n this.emit('errline', errbuffer);\n }\n cp.removeAllListeners();\n if (error) {\n reject(error);\n }\n else {\n resolve(exitCode);\n }\n });\n if (this.options.input) {\n if (!cp.stdin) {\n throw new Error('child process missing stdin');\n }\n cp.stdin.end(this.options.input);\n }\n }));\n });\n }\n}\nexports.ToolRunner = ToolRunner;\n/**\n * Convert an arg string to an array of args. Handles escaping\n *\n * @param argString string of arguments\n * @returns string[] array of arguments\n */\nfunction argStringToArray(argString) {\n const args = [];\n let inQuotes = false;\n let escaped = false;\n let arg = '';\n function append(c) {\n // we only escape double quotes.\n if (escaped && c !== '\"') {\n arg += '\\\\';\n }\n arg += c;\n escaped = false;\n }\n for (let i = 0; i < argString.length; i++) {\n const c = argString.charAt(i);\n if (c === '\"') {\n if (!escaped) {\n inQuotes = !inQuotes;\n }\n else {\n append(c);\n }\n continue;\n }\n if (c === '\\\\' && escaped) {\n append(c);\n continue;\n }\n if (c === '\\\\' && inQuotes) {\n escaped = true;\n continue;\n }\n if (c === ' ' && !inQuotes) {\n if (arg.length > 0) {\n args.push(arg);\n arg = '';\n }\n continue;\n }\n append(c);\n }\n if (arg.length > 0) {\n args.push(arg.trim());\n }\n return args;\n}\nexports.argStringToArray = argStringToArray;\nclass ExecState extends events.EventEmitter {\n constructor(options, toolPath) {\n super();\n this.processClosed = false; // tracks whether the process has exited and stdio is closed\n this.processError = '';\n this.processExitCode = 0;\n this.processExited = false; // tracks whether the process has exited\n this.processStderr = false; // tracks whether stderr was written to\n this.delay = 10000; // 10 seconds\n this.done = false;\n this.timeout = null;\n if (!toolPath) {\n throw new Error('toolPath must not be empty');\n }\n this.options = options;\n this.toolPath = toolPath;\n if (options.delay) {\n this.delay = options.delay;\n }\n }\n CheckComplete() {\n if (this.done) {\n return;\n }\n if (this.processClosed) {\n this._setResult();\n }\n else if (this.processExited) {\n this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this);\n }\n }\n _debug(message) {\n this.emit('debug', message);\n }\n _setResult() {\n // determine whether there is an error\n let error;\n if (this.processExited) {\n if (this.processError) {\n error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`);\n }\n else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) {\n error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`);\n }\n else if (this.processStderr && this.options.failOnStdErr) {\n error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`);\n }\n }\n // clear the timeout\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n this.done = true;\n this.emit('done', error, this.processExitCode);\n }\n static HandleTimeout(state) {\n if (state.done) {\n return;\n }\n if (!state.processClosed && state.processExited) {\n const message = `The STDIO streams did not close within ${state.delay /\n 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;\n state._debug(message);\n }\n state._setResult();\n }\n}\n//# sourceMappingURL=toolrunner.js.map","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0;\nclass BasicCredentialHandler {\n constructor(username, password) {\n this.username = username;\n this.password = password;\n }\n prepareRequest(options) {\n if (!options.headers) {\n throw Error('The request has no headers');\n }\n options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`;\n }\n // This handler cannot handle 401\n canHandleAuthentication() {\n return false;\n }\n handleAuthentication() {\n return __awaiter(this, void 0, void 0, function* () {\n throw new Error('not implemented');\n });\n }\n}\nexports.BasicCredentialHandler = BasicCredentialHandler;\nclass BearerCredentialHandler {\n constructor(token) {\n this.token = token;\n }\n // currently implements pre-authorization\n // TODO: support preAuth = false where it hooks on 401\n prepareRequest(options) {\n if (!options.headers) {\n throw Error('The request has no headers');\n }\n options.headers['Authorization'] = `Bearer ${this.token}`;\n }\n // This handler cannot handle 401\n canHandleAuthentication() {\n return false;\n }\n handleAuthentication() {\n return __awaiter(this, void 0, void 0, function* () {\n throw new Error('not implemented');\n });\n }\n}\nexports.BearerCredentialHandler = BearerCredentialHandler;\nclass PersonalAccessTokenCredentialHandler {\n constructor(token) {\n this.token = token;\n }\n // currently implements pre-authorization\n // TODO: support preAuth = false where it hooks on 401\n prepareRequest(options) {\n if (!options.headers) {\n throw Error('The request has no headers');\n }\n options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`;\n }\n // This handler cannot handle 401\n canHandleAuthentication() {\n return false;\n }\n handleAuthentication() {\n return __awaiter(this, void 0, void 0, function* () {\n throw new Error('not implemented');\n });\n }\n}\nexports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler;\n//# sourceMappingURL=auth.js.map","\"use strict\";\n/* eslint-disable @typescript-eslint/no-explicit-any */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0;\nconst http = __importStar(require(\"http\"));\nconst https = __importStar(require(\"https\"));\nconst pm = __importStar(require(\"./proxy\"));\nconst tunnel = __importStar(require(\"tunnel\"));\nvar HttpCodes;\n(function (HttpCodes) {\n HttpCodes[HttpCodes[\"OK\"] = 200] = \"OK\";\n HttpCodes[HttpCodes[\"MultipleChoices\"] = 300] = \"MultipleChoices\";\n HttpCodes[HttpCodes[\"MovedPermanently\"] = 301] = \"MovedPermanently\";\n HttpCodes[HttpCodes[\"ResourceMoved\"] = 302] = \"ResourceMoved\";\n HttpCodes[HttpCodes[\"SeeOther\"] = 303] = \"SeeOther\";\n HttpCodes[HttpCodes[\"NotModified\"] = 304] = \"NotModified\";\n HttpCodes[HttpCodes[\"UseProxy\"] = 305] = \"UseProxy\";\n HttpCodes[HttpCodes[\"SwitchProxy\"] = 306] = \"SwitchProxy\";\n HttpCodes[HttpCodes[\"TemporaryRedirect\"] = 307] = \"TemporaryRedirect\";\n HttpCodes[HttpCodes[\"PermanentRedirect\"] = 308] = \"PermanentRedirect\";\n HttpCodes[HttpCodes[\"BadRequest\"] = 400] = \"BadRequest\";\n HttpCodes[HttpCodes[\"Unauthorized\"] = 401] = \"Unauthorized\";\n HttpCodes[HttpCodes[\"PaymentRequired\"] = 402] = \"PaymentRequired\";\n HttpCodes[HttpCodes[\"Forbidden\"] = 403] = \"Forbidden\";\n HttpCodes[HttpCodes[\"NotFound\"] = 404] = \"NotFound\";\n HttpCodes[HttpCodes[\"MethodNotAllowed\"] = 405] = \"MethodNotAllowed\";\n HttpCodes[HttpCodes[\"NotAcceptable\"] = 406] = \"NotAcceptable\";\n HttpCodes[HttpCodes[\"ProxyAuthenticationRequired\"] = 407] = \"ProxyAuthenticationRequired\";\n HttpCodes[HttpCodes[\"RequestTimeout\"] = 408] = \"RequestTimeout\";\n HttpCodes[HttpCodes[\"Conflict\"] = 409] = \"Conflict\";\n HttpCodes[HttpCodes[\"Gone\"] = 410] = \"Gone\";\n HttpCodes[HttpCodes[\"TooManyRequests\"] = 429] = \"TooManyRequests\";\n HttpCodes[HttpCodes[\"InternalServerError\"] = 500] = \"InternalServerError\";\n HttpCodes[HttpCodes[\"NotImplemented\"] = 501] = \"NotImplemented\";\n HttpCodes[HttpCodes[\"BadGateway\"] = 502] = \"BadGateway\";\n HttpCodes[HttpCodes[\"ServiceUnavailable\"] = 503] = \"ServiceUnavailable\";\n HttpCodes[HttpCodes[\"GatewayTimeout\"] = 504] = \"GatewayTimeout\";\n})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {}));\nvar Headers;\n(function (Headers) {\n Headers[\"Accept\"] = \"accept\";\n Headers[\"ContentType\"] = \"content-type\";\n})(Headers = exports.Headers || (exports.Headers = {}));\nvar MediaTypes;\n(function (MediaTypes) {\n MediaTypes[\"ApplicationJson\"] = \"application/json\";\n})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {}));\n/**\n * Returns the proxy URL, depending upon the supplied url and proxy environment variables.\n * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com\n */\nfunction getProxyUrl(serverUrl) {\n const proxyUrl = pm.getProxyUrl(new URL(serverUrl));\n return proxyUrl ? proxyUrl.href : '';\n}\nexports.getProxyUrl = getProxyUrl;\nconst HttpRedirectCodes = [\n HttpCodes.MovedPermanently,\n HttpCodes.ResourceMoved,\n HttpCodes.SeeOther,\n HttpCodes.TemporaryRedirect,\n HttpCodes.PermanentRedirect\n];\nconst HttpResponseRetryCodes = [\n HttpCodes.BadGateway,\n HttpCodes.ServiceUnavailable,\n HttpCodes.GatewayTimeout\n];\nconst RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD'];\nconst ExponentialBackoffCeiling = 10;\nconst ExponentialBackoffTimeSlice = 5;\nclass HttpClientError extends Error {\n constructor(message, statusCode) {\n super(message);\n this.name = 'HttpClientError';\n this.statusCode = statusCode;\n Object.setPrototypeOf(this, HttpClientError.prototype);\n }\n}\nexports.HttpClientError = HttpClientError;\nclass HttpClientResponse {\n constructor(message) {\n this.message = message;\n }\n readBody() {\n return __awaiter(this, void 0, void 0, function* () {\n return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {\n let output = Buffer.alloc(0);\n this.message.on('data', (chunk) => {\n output = Buffer.concat([output, chunk]);\n });\n this.message.on('end', () => {\n resolve(output.toString());\n });\n }));\n });\n }\n}\nexports.HttpClientResponse = HttpClientResponse;\nfunction isHttps(requestUrl) {\n const parsedUrl = new URL(requestUrl);\n return parsedUrl.protocol === 'https:';\n}\nexports.isHttps = isHttps;\nclass HttpClient {\n constructor(userAgent, handlers, requestOptions) {\n this._ignoreSslError = false;\n this._allowRedirects = true;\n this._allowRedirectDowngrade = false;\n this._maxRedirects = 50;\n this._allowRetries = false;\n this._maxRetries = 1;\n this._keepAlive = false;\n this._disposed = false;\n this.userAgent = userAgent;\n this.handlers = handlers || [];\n this.requestOptions = requestOptions;\n if (requestOptions) {\n if (requestOptions.ignoreSslError != null) {\n this._ignoreSslError = requestOptions.ignoreSslError;\n }\n this._socketTimeout = requestOptions.socketTimeout;\n if (requestOptions.allowRedirects != null) {\n this._allowRedirects = requestOptions.allowRedirects;\n }\n if (requestOptions.allowRedirectDowngrade != null) {\n this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade;\n }\n if (requestOptions.maxRedirects != null) {\n this._maxRedirects = Math.max(requestOptions.maxRedirects, 0);\n }\n if (requestOptions.keepAlive != null) {\n this._keepAlive = requestOptions.keepAlive;\n }\n if (requestOptions.allowRetries != null) {\n this._allowRetries = requestOptions.allowRetries;\n }\n if (requestOptions.maxRetries != null) {\n this._maxRetries = requestOptions.maxRetries;\n }\n }\n }\n options(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('OPTIONS', requestUrl, null, additionalHeaders || {});\n });\n }\n get(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('GET', requestUrl, null, additionalHeaders || {});\n });\n }\n del(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('DELETE', requestUrl, null, additionalHeaders || {});\n });\n }\n post(requestUrl, data, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('POST', requestUrl, data, additionalHeaders || {});\n });\n }\n patch(requestUrl, data, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('PATCH', requestUrl, data, additionalHeaders || {});\n });\n }\n put(requestUrl, data, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('PUT', requestUrl, data, additionalHeaders || {});\n });\n }\n head(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('HEAD', requestUrl, null, additionalHeaders || {});\n });\n }\n sendStream(verb, requestUrl, stream, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request(verb, requestUrl, stream, additionalHeaders);\n });\n }\n /**\n * Gets a typed object from an endpoint\n * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise\n */\n getJson(requestUrl, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n const res = yield this.get(requestUrl, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n postJson(requestUrl, obj, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const data = JSON.stringify(obj, null, 2);\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);\n const res = yield this.post(requestUrl, data, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n putJson(requestUrl, obj, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const data = JSON.stringify(obj, null, 2);\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);\n const res = yield this.put(requestUrl, data, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n patchJson(requestUrl, obj, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const data = JSON.stringify(obj, null, 2);\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);\n const res = yield this.patch(requestUrl, data, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n /**\n * Makes a raw http request.\n * All other methods such as get, post, patch, and request ultimately call this.\n * Prefer get, del, post and patch\n */\n request(verb, requestUrl, data, headers) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._disposed) {\n throw new Error('Client has already been disposed.');\n }\n const parsedUrl = new URL(requestUrl);\n let info = this._prepareRequest(verb, parsedUrl, headers);\n // Only perform retries on reads since writes may not be idempotent.\n const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb)\n ? this._maxRetries + 1\n : 1;\n let numTries = 0;\n let response;\n do {\n response = yield this.requestRaw(info, data);\n // Check if it's an authentication challenge\n if (response &&\n response.message &&\n response.message.statusCode === HttpCodes.Unauthorized) {\n let authenticationHandler;\n for (const handler of this.handlers) {\n if (handler.canHandleAuthentication(response)) {\n authenticationHandler = handler;\n break;\n }\n }\n if (authenticationHandler) {\n return authenticationHandler.handleAuthentication(this, info, data);\n }\n else {\n // We have received an unauthorized response but have no handlers to handle it.\n // Let the response return to the caller.\n return response;\n }\n }\n let redirectsRemaining = this._maxRedirects;\n while (response.message.statusCode &&\n HttpRedirectCodes.includes(response.message.statusCode) &&\n this._allowRedirects &&\n redirectsRemaining > 0) {\n const redirectUrl = response.message.headers['location'];\n if (!redirectUrl) {\n // if there's no location to redirect to, we won't\n break;\n }\n const parsedRedirectUrl = new URL(redirectUrl);\n if (parsedUrl.protocol === 'https:' &&\n parsedUrl.protocol !== parsedRedirectUrl.protocol &&\n !this._allowRedirectDowngrade) {\n throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.');\n }\n // we need to finish reading the response before reassigning response\n // which will leak the open socket.\n yield response.readBody();\n // strip authorization header if redirected to a different hostname\n if (parsedRedirectUrl.hostname !== parsedUrl.hostname) {\n for (const header in headers) {\n // header names are case insensitive\n if (header.toLowerCase() === 'authorization') {\n delete headers[header];\n }\n }\n }\n // let's make the request with the new redirectUrl\n info = this._prepareRequest(verb, parsedRedirectUrl, headers);\n response = yield this.requestRaw(info, data);\n redirectsRemaining--;\n }\n if (!response.message.statusCode ||\n !HttpResponseRetryCodes.includes(response.message.statusCode)) {\n // If not a retry code, return immediately instead of retrying\n return response;\n }\n numTries += 1;\n if (numTries < maxTries) {\n yield response.readBody();\n yield this._performExponentialBackoff(numTries);\n }\n } while (numTries < maxTries);\n return response;\n });\n }\n /**\n * Needs to be called if keepAlive is set to true in request options.\n */\n dispose() {\n if (this._agent) {\n this._agent.destroy();\n }\n this._disposed = true;\n }\n /**\n * Raw request.\n * @param info\n * @param data\n */\n requestRaw(info, data) {\n return __awaiter(this, void 0, void 0, function* () {\n return new Promise((resolve, reject) => {\n function callbackForResult(err, res) {\n if (err) {\n reject(err);\n }\n else if (!res) {\n // If `err` is not passed, then `res` must be passed.\n reject(new Error('Unknown error'));\n }\n else {\n resolve(res);\n }\n }\n this.requestRawWithCallback(info, data, callbackForResult);\n });\n });\n }\n /**\n * Raw request with callback.\n * @param info\n * @param data\n * @param onResult\n */\n requestRawWithCallback(info, data, onResult) {\n if (typeof data === 'string') {\n if (!info.options.headers) {\n info.options.headers = {};\n }\n info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8');\n }\n let callbackCalled = false;\n function handleResult(err, res) {\n if (!callbackCalled) {\n callbackCalled = true;\n onResult(err, res);\n }\n }\n const req = info.httpModule.request(info.options, (msg) => {\n const res = new HttpClientResponse(msg);\n handleResult(undefined, res);\n });\n let socket;\n req.on('socket', sock => {\n socket = sock;\n });\n // If we ever get disconnected, we want the socket to timeout eventually\n req.setTimeout(this._socketTimeout || 3 * 60000, () => {\n if (socket) {\n socket.end();\n }\n handleResult(new Error(`Request timeout: ${info.options.path}`));\n });\n req.on('error', function (err) {\n // err has statusCode property\n // res should have headers\n handleResult(err);\n });\n if (data && typeof data === 'string') {\n req.write(data, 'utf8');\n }\n if (data && typeof data !== 'string') {\n data.on('close', function () {\n req.end();\n });\n data.pipe(req);\n }\n else {\n req.end();\n }\n }\n /**\n * Gets an http agent. This function is useful when you need an http agent that handles\n * routing through a proxy server - depending upon the url and proxy environment variables.\n * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com\n */\n getAgent(serverUrl) {\n const parsedUrl = new URL(serverUrl);\n return this._getAgent(parsedUrl);\n }\n _prepareRequest(method, requestUrl, headers) {\n const info = {};\n info.parsedUrl = requestUrl;\n const usingSsl = info.parsedUrl.protocol === 'https:';\n info.httpModule = usingSsl ? https : http;\n const defaultPort = usingSsl ? 443 : 80;\n info.options = {};\n info.options.host = info.parsedUrl.hostname;\n info.options.port = info.parsedUrl.port\n ? parseInt(info.parsedUrl.port)\n : defaultPort;\n info.options.path =\n (info.parsedUrl.pathname || '') + (info.parsedUrl.search || '');\n info.options.method = method;\n info.options.headers = this._mergeHeaders(headers);\n if (this.userAgent != null) {\n info.options.headers['user-agent'] = this.userAgent;\n }\n info.options.agent = this._getAgent(info.parsedUrl);\n // gives handlers an opportunity to participate\n if (this.handlers) {\n for (const handler of this.handlers) {\n handler.prepareRequest(info.options);\n }\n }\n return info;\n }\n _mergeHeaders(headers) {\n if (this.requestOptions && this.requestOptions.headers) {\n return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {}));\n }\n return lowercaseKeys(headers || {});\n }\n _getExistingOrDefaultHeader(additionalHeaders, header, _default) {\n let clientHeader;\n if (this.requestOptions && this.requestOptions.headers) {\n clientHeader = lowercaseKeys(this.requestOptions.headers)[header];\n }\n return additionalHeaders[header] || clientHeader || _default;\n }\n _getAgent(parsedUrl) {\n let agent;\n const proxyUrl = pm.getProxyUrl(parsedUrl);\n const useProxy = proxyUrl && proxyUrl.hostname;\n if (this._keepAlive && useProxy) {\n agent = this._proxyAgent;\n }\n if (this._keepAlive && !useProxy) {\n agent = this._agent;\n }\n // if agent is already assigned use that agent.\n if (agent) {\n return agent;\n }\n const usingSsl = parsedUrl.protocol === 'https:';\n let maxSockets = 100;\n if (this.requestOptions) {\n maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets;\n }\n // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis.\n if (proxyUrl && proxyUrl.hostname) {\n const agentOptions = {\n maxSockets,\n keepAlive: this._keepAlive,\n proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && {\n proxyAuth: `${proxyUrl.username}:${proxyUrl.password}`\n })), { host: proxyUrl.hostname, port: proxyUrl.port })\n };\n let tunnelAgent;\n const overHttps = proxyUrl.protocol === 'https:';\n if (usingSsl) {\n tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp;\n }\n else {\n tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp;\n }\n agent = tunnelAgent(agentOptions);\n this._proxyAgent = agent;\n }\n // if reusing agent across request and tunneling agent isn't assigned create a new agent\n if (this._keepAlive && !agent) {\n const options = { keepAlive: this._keepAlive, maxSockets };\n agent = usingSsl ? new https.Agent(options) : new http.Agent(options);\n this._agent = agent;\n }\n // if not using private agent and tunnel agent isn't setup then use global agent\n if (!agent) {\n agent = usingSsl ? https.globalAgent : http.globalAgent;\n }\n if (usingSsl && this._ignoreSslError) {\n // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process\n // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options\n // we have to cast it to any and change it directly\n agent.options = Object.assign(agent.options || {}, {\n rejectUnauthorized: false\n });\n }\n return agent;\n }\n _performExponentialBackoff(retryNumber) {\n return __awaiter(this, void 0, void 0, function* () {\n retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber);\n const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber);\n return new Promise(resolve => setTimeout(() => resolve(), ms));\n });\n }\n _processResponse(res, options) {\n return __awaiter(this, void 0, void 0, function* () {\n return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {\n const statusCode = res.message.statusCode || 0;\n const response = {\n statusCode,\n result: null,\n headers: {}\n };\n // not found leads to null obj returned\n if (statusCode === HttpCodes.NotFound) {\n resolve(response);\n }\n // get the result from the body\n function dateTimeDeserializer(key, value) {\n if (typeof value === 'string') {\n const a = new Date(value);\n if (!isNaN(a.valueOf())) {\n return a;\n }\n }\n return value;\n }\n let obj;\n let contents;\n try {\n contents = yield res.readBody();\n if (contents && contents.length > 0) {\n if (options && options.deserializeDates) {\n obj = JSON.parse(contents, dateTimeDeserializer);\n }\n else {\n obj = JSON.parse(contents);\n }\n response.result = obj;\n }\n response.headers = res.message.headers;\n }\n catch (err) {\n // Invalid resource (contents not json); leaving result obj null\n }\n // note that 3xx redirects are handled by the http layer.\n if (statusCode > 299) {\n let msg;\n // if exception/error in body, attempt to get better error\n if (obj && obj.message) {\n msg = obj.message;\n }\n else if (contents && contents.length > 0) {\n // it may be the case that the exception is in the body message as string\n msg = contents;\n }\n else {\n msg = `Failed request: (${statusCode})`;\n }\n const err = new HttpClientError(msg, statusCode);\n err.result = response.result;\n reject(err);\n }\n else {\n resolve(response);\n }\n }));\n });\n }\n}\nexports.HttpClient = HttpClient;\nconst lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {});\n//# sourceMappingURL=index.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.checkBypass = exports.getProxyUrl = void 0;\nfunction getProxyUrl(reqUrl) {\n const usingSsl = reqUrl.protocol === 'https:';\n if (checkBypass(reqUrl)) {\n return undefined;\n }\n const proxyVar = (() => {\n if (usingSsl) {\n return process.env['https_proxy'] || process.env['HTTPS_PROXY'];\n }\n else {\n return process.env['http_proxy'] || process.env['HTTP_PROXY'];\n }\n })();\n if (proxyVar) {\n return new URL(proxyVar);\n }\n else {\n return undefined;\n }\n}\nexports.getProxyUrl = getProxyUrl;\nfunction checkBypass(reqUrl) {\n if (!reqUrl.hostname) {\n return false;\n }\n const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';\n if (!noProxy) {\n return false;\n }\n // Determine the request port\n let reqPort;\n if (reqUrl.port) {\n reqPort = Number(reqUrl.port);\n }\n else if (reqUrl.protocol === 'http:') {\n reqPort = 80;\n }\n else if (reqUrl.protocol === 'https:') {\n reqPort = 443;\n }\n // Format the request hostname and hostname with port\n const upperReqHosts = [reqUrl.hostname.toUpperCase()];\n if (typeof reqPort === 'number') {\n upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`);\n }\n // Compare request host against noproxy\n for (const upperNoProxyItem of noProxy\n .split(',')\n .map(x => x.trim().toUpperCase())\n .filter(x => x)) {\n if (upperReqHosts.some(x => x === upperNoProxyItem)) {\n return true;\n }\n }\n return false;\n}\nexports.checkBypass = checkBypass;\n//# sourceMappingURL=proxy.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar _a;\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rename = exports.readlink = exports.readdir = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0;\nconst fs = __importStar(require(\"fs\"));\nconst path = __importStar(require(\"path\"));\n_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink;\nexports.IS_WINDOWS = process.platform === 'win32';\nfunction exists(fsPath) {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n yield exports.stat(fsPath);\n }\n catch (err) {\n if (err.code === 'ENOENT') {\n return false;\n }\n throw err;\n }\n return true;\n });\n}\nexports.exists = exists;\nfunction isDirectory(fsPath, useStat = false) {\n return __awaiter(this, void 0, void 0, function* () {\n const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath);\n return stats.isDirectory();\n });\n}\nexports.isDirectory = isDirectory;\n/**\n * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:\n * \\, \\hello, \\\\hello\\share, C:, and C:\\hello (and corresponding alternate separator cases).\n */\nfunction isRooted(p) {\n p = normalizeSeparators(p);\n if (!p) {\n throw new Error('isRooted() parameter \"p\" cannot be empty');\n }\n if (exports.IS_WINDOWS) {\n return (p.startsWith('\\\\') || /^[A-Z]:/i.test(p) // e.g. \\ or \\hello or \\\\hello\n ); // e.g. C: or C:\\hello\n }\n return p.startsWith('/');\n}\nexports.isRooted = isRooted;\n/**\n * Best effort attempt to determine whether a file exists and is executable.\n * @param filePath file path to check\n * @param extensions additional file extensions to try\n * @return if file exists and is executable, returns the file path. otherwise empty string.\n */\nfunction tryGetExecutablePath(filePath, extensions) {\n return __awaiter(this, void 0, void 0, function* () {\n let stats = undefined;\n try {\n // test file exists\n stats = yield exports.stat(filePath);\n }\n catch (err) {\n if (err.code !== 'ENOENT') {\n // eslint-disable-next-line no-console\n console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);\n }\n }\n if (stats && stats.isFile()) {\n if (exports.IS_WINDOWS) {\n // on Windows, test for valid extension\n const upperExt = path.extname(filePath).toUpperCase();\n if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) {\n return filePath;\n }\n }\n else {\n if (isUnixExecutable(stats)) {\n return filePath;\n }\n }\n }\n // try each extension\n const originalFilePath = filePath;\n for (const extension of extensions) {\n filePath = originalFilePath + extension;\n stats = undefined;\n try {\n stats = yield exports.stat(filePath);\n }\n catch (err) {\n if (err.code !== 'ENOENT') {\n // eslint-disable-next-line no-console\n console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);\n }\n }\n if (stats && stats.isFile()) {\n if (exports.IS_WINDOWS) {\n // preserve the case of the actual file (since an extension was appended)\n try {\n const directory = path.dirname(filePath);\n const upperName = path.basename(filePath).toUpperCase();\n for (const actualName of yield exports.readdir(directory)) {\n if (upperName === actualName.toUpperCase()) {\n filePath = path.join(directory, actualName);\n break;\n }\n }\n }\n catch (err) {\n // eslint-disable-next-line no-console\n console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`);\n }\n return filePath;\n }\n else {\n if (isUnixExecutable(stats)) {\n return filePath;\n }\n }\n }\n }\n return '';\n });\n}\nexports.tryGetExecutablePath = tryGetExecutablePath;\nfunction normalizeSeparators(p) {\n p = p || '';\n if (exports.IS_WINDOWS) {\n // convert slashes on Windows\n p = p.replace(/\\//g, '\\\\');\n // remove redundant slashes\n return p.replace(/\\\\\\\\+/g, '\\\\');\n }\n // remove redundant slashes\n return p.replace(/\\/\\/+/g, '/');\n}\n// on Mac/Linux, test the execute bit\n// R W X R W X R W X\n// 256 128 64 32 16 8 4 2 1\nfunction isUnixExecutable(stats) {\n return ((stats.mode & 1) > 0 ||\n ((stats.mode & 8) > 0 && stats.gid === process.getgid()) ||\n ((stats.mode & 64) > 0 && stats.uid === process.getuid()));\n}\n// Get the path of cmd.exe in windows\nfunction getCmdPath() {\n var _a;\n return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`;\n}\nexports.getCmdPath = getCmdPath;\n//# sourceMappingURL=io-util.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0;\nconst assert_1 = require(\"assert\");\nconst childProcess = __importStar(require(\"child_process\"));\nconst path = __importStar(require(\"path\"));\nconst util_1 = require(\"util\");\nconst ioUtil = __importStar(require(\"./io-util\"));\nconst exec = util_1.promisify(childProcess.exec);\nconst execFile = util_1.promisify(childProcess.execFile);\n/**\n * Copies a file or folder.\n * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js\n *\n * @param source source path\n * @param dest destination path\n * @param options optional. See CopyOptions.\n */\nfunction cp(source, dest, options = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const { force, recursive, copySourceDirectory } = readCopyOptions(options);\n const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null;\n // Dest is an existing file, but not forcing\n if (destStat && destStat.isFile() && !force) {\n return;\n }\n // If dest is an existing directory, should copy inside.\n const newDest = destStat && destStat.isDirectory() && copySourceDirectory\n ? path.join(dest, path.basename(source))\n : dest;\n if (!(yield ioUtil.exists(source))) {\n throw new Error(`no such file or directory: ${source}`);\n }\n const sourceStat = yield ioUtil.stat(source);\n if (sourceStat.isDirectory()) {\n if (!recursive) {\n throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`);\n }\n else {\n yield cpDirRecursive(source, newDest, 0, force);\n }\n }\n else {\n if (path.relative(source, newDest) === '') {\n // a file cannot be copied to itself\n throw new Error(`'${newDest}' and '${source}' are the same file`);\n }\n yield copyFile(source, newDest, force);\n }\n });\n}\nexports.cp = cp;\n/**\n * Moves a path.\n *\n * @param source source path\n * @param dest destination path\n * @param options optional. See MoveOptions.\n */\nfunction mv(source, dest, options = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n if (yield ioUtil.exists(dest)) {\n let destExists = true;\n if (yield ioUtil.isDirectory(dest)) {\n // If dest is directory copy src into dest\n dest = path.join(dest, path.basename(source));\n destExists = yield ioUtil.exists(dest);\n }\n if (destExists) {\n if (options.force == null || options.force) {\n yield rmRF(dest);\n }\n else {\n throw new Error('Destination already exists');\n }\n }\n }\n yield mkdirP(path.dirname(dest));\n yield ioUtil.rename(source, dest);\n });\n}\nexports.mv = mv;\n/**\n * Remove a path recursively with force\n *\n * @param inputPath path to remove\n */\nfunction rmRF(inputPath) {\n return __awaiter(this, void 0, void 0, function* () {\n if (ioUtil.IS_WINDOWS) {\n // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another\n // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.\n // Check for invalid characters\n // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file\n if (/[*\"<>|]/.test(inputPath)) {\n throw new Error('File path must not contain `*`, `\"`, `<`, `>` or `|` on Windows');\n }\n try {\n const cmdPath = ioUtil.getCmdPath();\n if (yield ioUtil.isDirectory(inputPath, true)) {\n yield exec(`${cmdPath} /s /c \"rd /s /q \"%inputPath%\"\"`, {\n env: { inputPath }\n });\n }\n else {\n yield exec(`${cmdPath} /s /c \"del /f /a \"%inputPath%\"\"`, {\n env: { inputPath }\n });\n }\n }\n catch (err) {\n // if you try to delete a file that doesn't exist, desired result is achieved\n // other errors are valid\n if (err.code !== 'ENOENT')\n throw err;\n }\n // Shelling out fails to remove a symlink folder with missing source, this unlink catches that\n try {\n yield ioUtil.unlink(inputPath);\n }\n catch (err) {\n // if you try to delete a file that doesn't exist, desired result is achieved\n // other errors are valid\n if (err.code !== 'ENOENT')\n throw err;\n }\n }\n else {\n let isDir = false;\n try {\n isDir = yield ioUtil.isDirectory(inputPath);\n }\n catch (err) {\n // if you try to delete a file that doesn't exist, desired result is achieved\n // other errors are valid\n if (err.code !== 'ENOENT')\n throw err;\n return;\n }\n if (isDir) {\n yield execFile(`rm`, [`-rf`, `${inputPath}`]);\n }\n else {\n yield ioUtil.unlink(inputPath);\n }\n }\n });\n}\nexports.rmRF = rmRF;\n/**\n * Make a directory. Creates the full path with folders in between\n * Will throw if it fails\n *\n * @param fsPath path to create\n * @returns Promise\n */\nfunction mkdirP(fsPath) {\n return __awaiter(this, void 0, void 0, function* () {\n assert_1.ok(fsPath, 'a path argument must be provided');\n yield ioUtil.mkdir(fsPath, { recursive: true });\n });\n}\nexports.mkdirP = mkdirP;\n/**\n * Returns path of a tool had the tool actually been invoked. Resolves via paths.\n * If you check and the tool does not exist, it will throw.\n *\n * @param tool name of the tool\n * @param check whether to check if tool exists\n * @returns Promise path to tool\n */\nfunction which(tool, check) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!tool) {\n throw new Error(\"parameter 'tool' is required\");\n }\n // recursive when check=true\n if (check) {\n const result = yield which(tool, false);\n if (!result) {\n if (ioUtil.IS_WINDOWS) {\n throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);\n }\n else {\n throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`);\n }\n }\n return result;\n }\n const matches = yield findInPath(tool);\n if (matches && matches.length > 0) {\n return matches[0];\n }\n return '';\n });\n}\nexports.which = which;\n/**\n * Returns a list of all occurrences of the given tool on the system path.\n *\n * @returns Promise the paths of the tool\n */\nfunction findInPath(tool) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!tool) {\n throw new Error(\"parameter 'tool' is required\");\n }\n // build the list of extensions to try\n const extensions = [];\n if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) {\n for (const extension of process.env['PATHEXT'].split(path.delimiter)) {\n if (extension) {\n extensions.push(extension);\n }\n }\n }\n // if it's rooted, return it if exists. otherwise return empty.\n if (ioUtil.isRooted(tool)) {\n const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions);\n if (filePath) {\n return [filePath];\n }\n return [];\n }\n // if any path separators, return empty\n if (tool.includes(path.sep)) {\n return [];\n }\n // build the list of directories\n //\n // Note, technically \"where\" checks the current directory on Windows. From a toolkit perspective,\n // it feels like we should not do this. Checking the current directory seems like more of a use\n // case of a shell, and the which() function exposed by the toolkit should strive for consistency\n // across platforms.\n const directories = [];\n if (process.env.PATH) {\n for (const p of process.env.PATH.split(path.delimiter)) {\n if (p) {\n directories.push(p);\n }\n }\n }\n // find all matches\n const matches = [];\n for (const directory of directories) {\n const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions);\n if (filePath) {\n matches.push(filePath);\n }\n }\n return matches;\n });\n}\nexports.findInPath = findInPath;\nfunction readCopyOptions(options) {\n const force = options.force == null ? true : options.force;\n const recursive = Boolean(options.recursive);\n const copySourceDirectory = options.copySourceDirectory == null\n ? true\n : Boolean(options.copySourceDirectory);\n return { force, recursive, copySourceDirectory };\n}\nfunction cpDirRecursive(sourceDir, destDir, currentDepth, force) {\n return __awaiter(this, void 0, void 0, function* () {\n // Ensure there is not a run away recursive copy\n if (currentDepth >= 255)\n return;\n currentDepth++;\n yield mkdirP(destDir);\n const files = yield ioUtil.readdir(sourceDir);\n for (const fileName of files) {\n const srcFile = `${sourceDir}/${fileName}`;\n const destFile = `${destDir}/${fileName}`;\n const srcFileStat = yield ioUtil.lstat(srcFile);\n if (srcFileStat.isDirectory()) {\n // Recurse\n yield cpDirRecursive(srcFile, destFile, currentDepth, force);\n }\n else {\n yield copyFile(srcFile, destFile, force);\n }\n }\n // Change the mode for the newly created directory\n yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode);\n });\n}\n// Buffered file copy\nfunction copyFile(srcFile, destFile, force) {\n return __awaiter(this, void 0, void 0, function* () {\n if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) {\n // unlink/re-link it\n try {\n yield ioUtil.lstat(destFile);\n yield ioUtil.unlink(destFile);\n }\n catch (e) {\n // Try to override file permission\n if (e.code === 'EPERM') {\n yield ioUtil.chmod(destFile, '0666');\n yield ioUtil.unlink(destFile);\n }\n // other errors = it doesn't exist, no work to do\n }\n // Copy over symlink\n const symlinkFull = yield ioUtil.readlink(srcFile);\n yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null);\n }\n else if (!(yield ioUtil.exists(destFile)) || force) {\n yield ioUtil.copyFile(srcFile, destFile);\n }\n });\n}\n//# sourceMappingURL=io.js.map","module.exports = require('./lib/tunnel');\n","'use strict';\n\nvar net = require('net');\nvar tls = require('tls');\nvar http = require('http');\nvar https = require('https');\nvar events = require('events');\nvar assert = require('assert');\nvar util = require('util');\n\n\nexports.httpOverHttp = httpOverHttp;\nexports.httpsOverHttp = httpsOverHttp;\nexports.httpOverHttps = httpOverHttps;\nexports.httpsOverHttps = httpsOverHttps;\n\n\nfunction httpOverHttp(options) {\n var agent = new TunnelingAgent(options);\n agent.request = http.request;\n return agent;\n}\n\nfunction httpsOverHttp(options) {\n var agent = new TunnelingAgent(options);\n agent.request = http.request;\n agent.createSocket = createSecureSocket;\n agent.defaultPort = 443;\n return agent;\n}\n\nfunction httpOverHttps(options) {\n var agent = new TunnelingAgent(options);\n agent.request = https.request;\n return agent;\n}\n\nfunction httpsOverHttps(options) {\n var agent = new TunnelingAgent(options);\n agent.request = https.request;\n agent.createSocket = createSecureSocket;\n agent.defaultPort = 443;\n return agent;\n}\n\n\nfunction TunnelingAgent(options) {\n var self = this;\n self.options = options || {};\n self.proxyOptions = self.options.proxy || {};\n self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets;\n self.requests = [];\n self.sockets = [];\n\n self.on('free', function onFree(socket, host, port, localAddress) {\n var options = toOptions(host, port, localAddress);\n for (var i = 0, len = self.requests.length; i < len; ++i) {\n var pending = self.requests[i];\n if (pending.host === options.host && pending.port === options.port) {\n // Detect the request to connect same origin server,\n // reuse the connection.\n self.requests.splice(i, 1);\n pending.request.onSocket(socket);\n return;\n }\n }\n socket.destroy();\n self.removeSocket(socket);\n });\n}\nutil.inherits(TunnelingAgent, events.EventEmitter);\n\nTunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) {\n var self = this;\n var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress));\n\n if (self.sockets.length >= this.maxSockets) {\n // We are over limit so we'll add it to the queue.\n self.requests.push(options);\n return;\n }\n\n // If we are under maxSockets create a new one.\n self.createSocket(options, function(socket) {\n socket.on('free', onFree);\n socket.on('close', onCloseOrRemove);\n socket.on('agentRemove', onCloseOrRemove);\n req.onSocket(socket);\n\n function onFree() {\n self.emit('free', socket, options);\n }\n\n function onCloseOrRemove(err) {\n self.removeSocket(socket);\n socket.removeListener('free', onFree);\n socket.removeListener('close', onCloseOrRemove);\n socket.removeListener('agentRemove', onCloseOrRemove);\n }\n });\n};\n\nTunnelingAgent.prototype.createSocket = function createSocket(options, cb) {\n var self = this;\n var placeholder = {};\n self.sockets.push(placeholder);\n\n var connectOptions = mergeOptions({}, self.proxyOptions, {\n method: 'CONNECT',\n path: options.host + ':' + options.port,\n agent: false,\n headers: {\n host: options.host + ':' + options.port\n }\n });\n if (options.localAddress) {\n connectOptions.localAddress = options.localAddress;\n }\n if (connectOptions.proxyAuth) {\n connectOptions.headers = connectOptions.headers || {};\n connectOptions.headers['Proxy-Authorization'] = 'Basic ' +\n new Buffer(connectOptions.proxyAuth).toString('base64');\n }\n\n debug('making CONNECT request');\n var connectReq = self.request(connectOptions);\n connectReq.useChunkedEncodingByDefault = false; // for v0.6\n connectReq.once('response', onResponse); // for v0.6\n connectReq.once('upgrade', onUpgrade); // for v0.6\n connectReq.once('connect', onConnect); // for v0.7 or later\n connectReq.once('error', onError);\n connectReq.end();\n\n function onResponse(res) {\n // Very hacky. This is necessary to avoid http-parser leaks.\n res.upgrade = true;\n }\n\n function onUpgrade(res, socket, head) {\n // Hacky.\n process.nextTick(function() {\n onConnect(res, socket, head);\n });\n }\n\n function onConnect(res, socket, head) {\n connectReq.removeAllListeners();\n socket.removeAllListeners();\n\n if (res.statusCode !== 200) {\n debug('tunneling socket could not be established, statusCode=%d',\n res.statusCode);\n socket.destroy();\n var error = new Error('tunneling socket could not be established, ' +\n 'statusCode=' + res.statusCode);\n error.code = 'ECONNRESET';\n options.request.emit('error', error);\n self.removeSocket(placeholder);\n return;\n }\n if (head.length > 0) {\n debug('got illegal response body from proxy');\n socket.destroy();\n var error = new Error('got illegal response body from proxy');\n error.code = 'ECONNRESET';\n options.request.emit('error', error);\n self.removeSocket(placeholder);\n return;\n }\n debug('tunneling connection has established');\n self.sockets[self.sockets.indexOf(placeholder)] = socket;\n return cb(socket);\n }\n\n function onError(cause) {\n connectReq.removeAllListeners();\n\n debug('tunneling socket could not be established, cause=%s\\n',\n cause.message, cause.stack);\n var error = new Error('tunneling socket could not be established, ' +\n 'cause=' + cause.message);\n error.code = 'ECONNRESET';\n options.request.emit('error', error);\n self.removeSocket(placeholder);\n }\n};\n\nTunnelingAgent.prototype.removeSocket = function removeSocket(socket) {\n var pos = this.sockets.indexOf(socket)\n if (pos === -1) {\n return;\n }\n this.sockets.splice(pos, 1);\n\n var pending = this.requests.shift();\n if (pending) {\n // If we have pending requests and a socket gets closed a new one\n // needs to be created to take over in the pool for the one that closed.\n this.createSocket(pending, function(socket) {\n pending.request.onSocket(socket);\n });\n }\n};\n\nfunction createSecureSocket(options, cb) {\n var self = this;\n TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {\n var hostHeader = options.request.getHeader('host');\n var tlsOptions = mergeOptions({}, self.options, {\n socket: socket,\n servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host\n });\n\n // 0 is dummy port for v0.6\n var secureSocket = tls.connect(0, tlsOptions);\n self.sockets[self.sockets.indexOf(socket)] = secureSocket;\n cb(secureSocket);\n });\n}\n\n\nfunction toOptions(host, port, localAddress) {\n if (typeof host === 'string') { // since v0.10\n return {\n host: host,\n port: port,\n localAddress: localAddress\n };\n }\n return host; // for v0.11 or later\n}\n\nfunction mergeOptions(target) {\n for (var i = 1, len = arguments.length; i < len; ++i) {\n var overrides = arguments[i];\n if (typeof overrides === 'object') {\n var keys = Object.keys(overrides);\n for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {\n var k = keys[j];\n if (overrides[k] !== undefined) {\n target[k] = overrides[k];\n }\n }\n }\n }\n return target;\n}\n\n\nvar debug;\nif (process.env.NODE_DEBUG && /\\btunnel\\b/.test(process.env.NODE_DEBUG)) {\n debug = function() {\n var args = Array.prototype.slice.call(arguments);\n if (typeof args[0] === 'string') {\n args[0] = 'TUNNEL: ' + args[0];\n } else {\n args.unshift('TUNNEL:');\n }\n console.error.apply(console, args);\n }\n} else {\n debug = function() {};\n}\nexports.debug = debug; // for test\n","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"v1\", {\n enumerable: true,\n get: function () {\n return _v.default;\n }\n});\nObject.defineProperty(exports, \"v3\", {\n enumerable: true,\n get: function () {\n return _v2.default;\n }\n});\nObject.defineProperty(exports, \"v4\", {\n enumerable: true,\n get: function () {\n return _v3.default;\n }\n});\nObject.defineProperty(exports, \"v5\", {\n enumerable: true,\n get: function () {\n return _v4.default;\n }\n});\nObject.defineProperty(exports, \"NIL\", {\n enumerable: true,\n get: function () {\n return _nil.default;\n }\n});\nObject.defineProperty(exports, \"version\", {\n enumerable: true,\n get: function () {\n return _version.default;\n }\n});\nObject.defineProperty(exports, \"validate\", {\n enumerable: true,\n get: function () {\n return _validate.default;\n }\n});\nObject.defineProperty(exports, \"stringify\", {\n enumerable: true,\n get: function () {\n return _stringify.default;\n }\n});\nObject.defineProperty(exports, \"parse\", {\n enumerable: true,\n get: function () {\n return _parse.default;\n }\n});\n\nvar _v = _interopRequireDefault(require(\"./v1.js\"));\n\nvar _v2 = _interopRequireDefault(require(\"./v3.js\"));\n\nvar _v3 = _interopRequireDefault(require(\"./v4.js\"));\n\nvar _v4 = _interopRequireDefault(require(\"./v5.js\"));\n\nvar _nil = _interopRequireDefault(require(\"./nil.js\"));\n\nvar _version = _interopRequireDefault(require(\"./version.js\"));\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nvar _parse = _interopRequireDefault(require(\"./parse.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _crypto = _interopRequireDefault(require(\"crypto\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction md5(bytes) {\n if (Array.isArray(bytes)) {\n bytes = Buffer.from(bytes);\n } else if (typeof bytes === 'string') {\n bytes = Buffer.from(bytes, 'utf8');\n }\n\n return _crypto.default.createHash('md5').update(bytes).digest();\n}\n\nvar _default = md5;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\nvar _default = '00000000-0000-0000-0000-000000000000';\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction parse(uuid) {\n if (!(0, _validate.default)(uuid)) {\n throw TypeError('Invalid UUID');\n }\n\n let v;\n const arr = new Uint8Array(16); // Parse ########-....-....-....-............\n\n arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24;\n arr[1] = v >>> 16 & 0xff;\n arr[2] = v >>> 8 & 0xff;\n arr[3] = v & 0xff; // Parse ........-####-....-....-............\n\n arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8;\n arr[5] = v & 0xff; // Parse ........-....-####-....-............\n\n arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8;\n arr[7] = v & 0xff; // Parse ........-....-....-####-............\n\n arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8;\n arr[9] = v & 0xff; // Parse ........-....-....-....-############\n // (Use \"/\" to avoid 32-bit truncation when bit-shifting high-order bytes)\n\n arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff;\n arr[11] = v / 0x100000000 & 0xff;\n arr[12] = v >>> 24 & 0xff;\n arr[13] = v >>> 16 & 0xff;\n arr[14] = v >>> 8 & 0xff;\n arr[15] = v & 0xff;\n return arr;\n}\n\nvar _default = parse;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\nvar _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = rng;\n\nvar _crypto = _interopRequireDefault(require(\"crypto\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate\n\nlet poolPtr = rnds8Pool.length;\n\nfunction rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n _crypto.default.randomFillSync(rnds8Pool);\n\n poolPtr = 0;\n }\n\n return rnds8Pool.slice(poolPtr, poolPtr += 16);\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _crypto = _interopRequireDefault(require(\"crypto\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction sha1(bytes) {\n if (Array.isArray(bytes)) {\n bytes = Buffer.from(bytes);\n } else if (typeof bytes === 'string') {\n bytes = Buffer.from(bytes, 'utf8');\n }\n\n return _crypto.default.createHash('sha1').update(bytes).digest();\n}\n\nvar _default = sha1;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nconst byteToHex = [];\n\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).substr(1));\n}\n\nfunction stringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n\n if (!(0, _validate.default)(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n\n return uuid;\n}\n\nvar _default = stringify;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _rng = _interopRequireDefault(require(\"./rng.js\"));\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// **`v1()` - Generate time-based UUID**\n//\n// Inspired by https://github.com/LiosK/UUID.js\n// and http://docs.python.org/library/uuid.html\nlet _nodeId;\n\nlet _clockseq; // Previous uuid creation time\n\n\nlet _lastMSecs = 0;\nlet _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details\n\nfunction v1(options, buf, offset) {\n let i = buf && offset || 0;\n const b = buf || new Array(16);\n options = options || {};\n let node = options.node || _nodeId;\n let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not\n // specified. We do this lazily to minimize issues related to insufficient\n // system entropy. See #189\n\n if (node == null || clockseq == null) {\n const seedBytes = options.random || (options.rng || _rng.default)();\n\n if (node == null) {\n // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];\n }\n\n if (clockseq == null) {\n // Per 4.2.2, randomize (14 bit) clockseq\n clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;\n }\n } // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n\n\n let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock\n // cycle to simulate higher resolution clock\n\n let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)\n\n const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression\n\n if (dt < 0 && options.clockseq === undefined) {\n clockseq = clockseq + 1 & 0x3fff;\n } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n // time interval\n\n\n if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n nsecs = 0;\n } // Per 4.2.1.2 Throw error if too many uuids are requested\n\n\n if (nsecs >= 10000) {\n throw new Error(\"uuid.v1(): Can't create more than 10M uuids/sec\");\n }\n\n _lastMSecs = msecs;\n _lastNSecs = nsecs;\n _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n\n msecs += 12219292800000; // `time_low`\n\n const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n b[i++] = tl >>> 24 & 0xff;\n b[i++] = tl >>> 16 & 0xff;\n b[i++] = tl >>> 8 & 0xff;\n b[i++] = tl & 0xff; // `time_mid`\n\n const tmh = msecs / 0x100000000 * 10000 & 0xfffffff;\n b[i++] = tmh >>> 8 & 0xff;\n b[i++] = tmh & 0xff; // `time_high_and_version`\n\n b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n\n b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n\n b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low`\n\n b[i++] = clockseq & 0xff; // `node`\n\n for (let n = 0; n < 6; ++n) {\n b[i + n] = node[n];\n }\n\n return buf || (0, _stringify.default)(b);\n}\n\nvar _default = v1;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _v = _interopRequireDefault(require(\"./v35.js\"));\n\nvar _md = _interopRequireDefault(require(\"./md5.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst v3 = (0, _v.default)('v3', 0x30, _md.default);\nvar _default = v3;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = _default;\nexports.URL = exports.DNS = void 0;\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nvar _parse = _interopRequireDefault(require(\"./parse.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction stringToBytes(str) {\n str = unescape(encodeURIComponent(str)); // UTF8 escape\n\n const bytes = [];\n\n for (let i = 0; i < str.length; ++i) {\n bytes.push(str.charCodeAt(i));\n }\n\n return bytes;\n}\n\nconst DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';\nexports.DNS = DNS;\nconst URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';\nexports.URL = URL;\n\nfunction _default(name, version, hashfunc) {\n function generateUUID(value, namespace, buf, offset) {\n if (typeof value === 'string') {\n value = stringToBytes(value);\n }\n\n if (typeof namespace === 'string') {\n namespace = (0, _parse.default)(namespace);\n }\n\n if (namespace.length !== 16) {\n throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');\n } // Compute hash of namespace and value, Per 4.3\n // Future: Use spread syntax when supported on all platforms, e.g. `bytes =\n // hashfunc([...namespace, ... value])`\n\n\n let bytes = new Uint8Array(16 + value.length);\n bytes.set(namespace);\n bytes.set(value, namespace.length);\n bytes = hashfunc(bytes);\n bytes[6] = bytes[6] & 0x0f | version;\n bytes[8] = bytes[8] & 0x3f | 0x80;\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = bytes[i];\n }\n\n return buf;\n }\n\n return (0, _stringify.default)(bytes);\n } // Function#name is not settable on some platforms (#270)\n\n\n try {\n generateUUID.name = name; // eslint-disable-next-line no-empty\n } catch (err) {} // For CommonJS default export support\n\n\n generateUUID.DNS = DNS;\n generateUUID.URL = URL;\n return generateUUID;\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _rng = _interopRequireDefault(require(\"./rng.js\"));\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction v4(options, buf, offset) {\n options = options || {};\n\n const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\n\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n\n return buf;\n }\n\n return (0, _stringify.default)(rnds);\n}\n\nvar _default = v4;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _v = _interopRequireDefault(require(\"./v35.js\"));\n\nvar _sha = _interopRequireDefault(require(\"./sha1.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst v5 = (0, _v.default)('v5', 0x50, _sha.default);\nvar _default = v5;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _regex = _interopRequireDefault(require(\"./regex.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction validate(uuid) {\n return typeof uuid === 'string' && _regex.default.test(uuid);\n}\n\nvar _default = validate;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction version(uuid) {\n if (!(0, _validate.default)(uuid)) {\n throw TypeError('Invalid UUID');\n }\n\n return parseInt(uuid.substr(14, 1), 16);\n}\n\nvar _default = version;\nexports.default = _default;","module.exports = require(\"assert\");","module.exports = require(\"child_process\");","module.exports = require(\"crypto\");","module.exports = require(\"events\");","module.exports = require(\"fs\");","module.exports = require(\"http\");","module.exports = require(\"https\");","module.exports = require(\"net\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"string_decoder\");","module.exports = require(\"timers\");","module.exports = require(\"tls\");","module.exports = require(\"util\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tvar threw = true;\n\ttry {\n\t\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\t\tthrew = false;\n\t} finally {\n\t\tif(threw) delete __webpack_module_cache__[moduleId];\n\t}\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","\nif (typeof __webpack_require__ !== 'undefined') __webpack_require__.ab = __dirname + \"/\";","const core = require(\"@actions/core\");\nconst sweep = require(\"./sweep\");\n\nsweep.storeTimestamp().catch(core.setFailed);\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/.github/actions/cargo-sweep/dist/main/sourcemap-register.js b/.github/actions/cargo-sweep/dist/main/sourcemap-register.js deleted file mode 100644 index 466141d4069ca..0000000000000 --- a/.github/actions/cargo-sweep/dist/main/sourcemap-register.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var e={650:e=>{var r=Object.prototype.toString;var n=typeof Buffer.alloc==="function"&&typeof Buffer.allocUnsafe==="function"&&typeof Buffer.from==="function";function isArrayBuffer(e){return r.call(e).slice(8,-1)==="ArrayBuffer"}function fromArrayBuffer(e,r,t){r>>>=0;var o=e.byteLength-r;if(o<0){throw new RangeError("'offset' is out of bounds")}if(t===undefined){t=o}else{t>>>=0;if(t>o){throw new RangeError("'length' is out of bounds")}}return n?Buffer.from(e.slice(r,r+t)):new Buffer(new Uint8Array(e.slice(r,r+t)))}function fromString(e,r){if(typeof r!=="string"||r===""){r="utf8"}if(!Buffer.isEncoding(r)){throw new TypeError('"encoding" must be a valid string encoding')}return n?Buffer.from(e,r):new Buffer(e,r)}function bufferFrom(e,r,t){if(typeof e==="number"){throw new TypeError('"value" argument must not be a number')}if(isArrayBuffer(e)){return fromArrayBuffer(e,r,t)}if(typeof e==="string"){return fromString(e,r)}return n?Buffer.from(e):new Buffer(e)}e.exports=bufferFrom},274:(e,r,n)=>{var t=n(339);var o=Object.prototype.hasOwnProperty;var i=typeof Map!=="undefined";function ArraySet(){this._array=[];this._set=i?new Map:Object.create(null)}ArraySet.fromArray=function ArraySet_fromArray(e,r){var n=new ArraySet;for(var t=0,o=e.length;t=0){return r}}else{var n=t.toSetString(e);if(o.call(this._set,n)){return this._set[n]}}throw new Error('"'+e+'" is not in the set.')};ArraySet.prototype.at=function ArraySet_at(e){if(e>=0&&e{var t=n(190);var o=5;var i=1<>1;return r?-n:n}r.encode=function base64VLQ_encode(e){var r="";var n;var i=toVLQSigned(e);do{n=i&a;i>>>=o;if(i>0){n|=u}r+=t.encode(n)}while(i>0);return r};r.decode=function base64VLQ_decode(e,r,n){var i=e.length;var s=0;var l=0;var c,p;do{if(r>=i){throw new Error("Expected more digits in base 64 VLQ value.")}p=t.decode(e.charCodeAt(r++));if(p===-1){throw new Error("Invalid base64 digit: "+e.charAt(r-1))}c=!!(p&u);p&=a;s=s+(p<{var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");r.encode=function(e){if(0<=e&&e{r.GREATEST_LOWER_BOUND=1;r.LEAST_UPPER_BOUND=2;function recursiveSearch(e,n,t,o,i,a){var u=Math.floor((n-e)/2)+e;var s=i(t,o[u],true);if(s===0){return u}else if(s>0){if(n-u>1){return recursiveSearch(u,n,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return n1){return recursiveSearch(e,u,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return u}else{return e<0?-1:e}}}r.search=function search(e,n,t,o){if(n.length===0){return-1}var i=recursiveSearch(-1,n.length,e,n,t,o||r.GREATEST_LOWER_BOUND);if(i<0){return-1}while(i-1>=0){if(t(n[i],n[i-1],true)!==0){break}--i}return i}},680:(e,r,n)=>{var t=n(339);function generatedPositionAfter(e,r){var n=e.generatedLine;var o=r.generatedLine;var i=e.generatedColumn;var a=r.generatedColumn;return o>n||o==n&&a>=i||t.compareByGeneratedPositionsInflated(e,r)<=0}function MappingList(){this._array=[];this._sorted=true;this._last={generatedLine:-1,generatedColumn:0}}MappingList.prototype.unsortedForEach=function MappingList_forEach(e,r){this._array.forEach(e,r)};MappingList.prototype.add=function MappingList_add(e){if(generatedPositionAfter(this._last,e)){this._last=e;this._array.push(e)}else{this._sorted=false;this._array.push(e)}};MappingList.prototype.toArray=function MappingList_toArray(){if(!this._sorted){this._array.sort(t.compareByGeneratedPositionsInflated);this._sorted=true}return this._array};r.H=MappingList},758:(e,r)=>{function swap(e,r,n){var t=e[r];e[r]=e[n];e[n]=t}function randomIntInRange(e,r){return Math.round(e+Math.random()*(r-e))}function doQuickSort(e,r,n,t){if(n{var t;var o=n(339);var i=n(345);var a=n(274).I;var u=n(449);var s=n(758).U;function SourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}return n.sections!=null?new IndexedSourceMapConsumer(n,r):new BasicSourceMapConsumer(n,r)}SourceMapConsumer.fromSourceMap=function(e,r){return BasicSourceMapConsumer.fromSourceMap(e,r)};SourceMapConsumer.prototype._version=3;SourceMapConsumer.prototype.__generatedMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_generatedMappings",{configurable:true,enumerable:true,get:function(){if(!this.__generatedMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__generatedMappings}});SourceMapConsumer.prototype.__originalMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_originalMappings",{configurable:true,enumerable:true,get:function(){if(!this.__originalMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__originalMappings}});SourceMapConsumer.prototype._charIsMappingSeparator=function SourceMapConsumer_charIsMappingSeparator(e,r){var n=e.charAt(r);return n===";"||n===","};SourceMapConsumer.prototype._parseMappings=function SourceMapConsumer_parseMappings(e,r){throw new Error("Subclasses must implement _parseMappings")};SourceMapConsumer.GENERATED_ORDER=1;SourceMapConsumer.ORIGINAL_ORDER=2;SourceMapConsumer.GREATEST_LOWER_BOUND=1;SourceMapConsumer.LEAST_UPPER_BOUND=2;SourceMapConsumer.prototype.eachMapping=function SourceMapConsumer_eachMapping(e,r,n){var t=r||null;var i=n||SourceMapConsumer.GENERATED_ORDER;var a;switch(i){case SourceMapConsumer.GENERATED_ORDER:a=this._generatedMappings;break;case SourceMapConsumer.ORIGINAL_ORDER:a=this._originalMappings;break;default:throw new Error("Unknown order of iteration.")}var u=this.sourceRoot;a.map((function(e){var r=e.source===null?null:this._sources.at(e.source);r=o.computeSourceURL(u,r,this._sourceMapURL);return{source:r,generatedLine:e.generatedLine,generatedColumn:e.generatedColumn,originalLine:e.originalLine,originalColumn:e.originalColumn,name:e.name===null?null:this._names.at(e.name)}}),this).forEach(e,t)};SourceMapConsumer.prototype.allGeneratedPositionsFor=function SourceMapConsumer_allGeneratedPositionsFor(e){var r=o.getArg(e,"line");var n={source:o.getArg(e,"source"),originalLine:r,originalColumn:o.getArg(e,"column",0)};n.source=this._findSourceIndex(n.source);if(n.source<0){return[]}var t=[];var a=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,i.LEAST_UPPER_BOUND);if(a>=0){var u=this._originalMappings[a];if(e.column===undefined){var s=u.originalLine;while(u&&u.originalLine===s){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}else{var l=u.originalColumn;while(u&&u.originalLine===r&&u.originalColumn==l){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}}return t};r.SourceMapConsumer=SourceMapConsumer;function BasicSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sources");var u=o.getArg(n,"names",[]);var s=o.getArg(n,"sourceRoot",null);var l=o.getArg(n,"sourcesContent",null);var c=o.getArg(n,"mappings");var p=o.getArg(n,"file",null);if(t!=this._version){throw new Error("Unsupported version: "+t)}if(s){s=o.normalize(s)}i=i.map(String).map(o.normalize).map((function(e){return s&&o.isAbsolute(s)&&o.isAbsolute(e)?o.relative(s,e):e}));this._names=a.fromArray(u.map(String),true);this._sources=a.fromArray(i,true);this._absoluteSources=this._sources.toArray().map((function(e){return o.computeSourceURL(s,e,r)}));this.sourceRoot=s;this.sourcesContent=l;this._mappings=c;this._sourceMapURL=r;this.file=p}BasicSourceMapConsumer.prototype=Object.create(SourceMapConsumer.prototype);BasicSourceMapConsumer.prototype.consumer=SourceMapConsumer;BasicSourceMapConsumer.prototype._findSourceIndex=function(e){var r=e;if(this.sourceRoot!=null){r=o.relative(this.sourceRoot,r)}if(this._sources.has(r)){return this._sources.indexOf(r)}var n;for(n=0;n1){v.source=l+_[1];l+=_[1];v.originalLine=i+_[2];i=v.originalLine;v.originalLine+=1;v.originalColumn=a+_[3];a=v.originalColumn;if(_.length>4){v.name=c+_[4];c+=_[4]}}m.push(v);if(typeof v.originalLine==="number"){d.push(v)}}}s(m,o.compareByGeneratedPositionsDeflated);this.__generatedMappings=m;s(d,o.compareByOriginalPositions);this.__originalMappings=d};BasicSourceMapConsumer.prototype._findMapping=function SourceMapConsumer_findMapping(e,r,n,t,o,a){if(e[n]<=0){throw new TypeError("Line must be greater than or equal to 1, got "+e[n])}if(e[t]<0){throw new TypeError("Column must be greater than or equal to 0, got "+e[t])}return i.search(e,r,o,a)};BasicSourceMapConsumer.prototype.computeColumnSpans=function SourceMapConsumer_computeColumnSpans(){for(var e=0;e=0){var t=this._generatedMappings[n];if(t.generatedLine===r.generatedLine){var i=o.getArg(t,"source",null);if(i!==null){i=this._sources.at(i);i=o.computeSourceURL(this.sourceRoot,i,this._sourceMapURL)}var a=o.getArg(t,"name",null);if(a!==null){a=this._names.at(a)}return{source:i,line:o.getArg(t,"originalLine",null),column:o.getArg(t,"originalColumn",null),name:a}}}return{source:null,line:null,column:null,name:null}};BasicSourceMapConsumer.prototype.hasContentsOfAllSources=function BasicSourceMapConsumer_hasContentsOfAllSources(){if(!this.sourcesContent){return false}return this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some((function(e){return e==null}))};BasicSourceMapConsumer.prototype.sourceContentFor=function SourceMapConsumer_sourceContentFor(e,r){if(!this.sourcesContent){return null}var n=this._findSourceIndex(e);if(n>=0){return this.sourcesContent[n]}var t=e;if(this.sourceRoot!=null){t=o.relative(this.sourceRoot,t)}var i;if(this.sourceRoot!=null&&(i=o.urlParse(this.sourceRoot))){var a=t.replace(/^file:\/\//,"");if(i.scheme=="file"&&this._sources.has(a)){return this.sourcesContent[this._sources.indexOf(a)]}if((!i.path||i.path=="/")&&this._sources.has("/"+t)){return this.sourcesContent[this._sources.indexOf("/"+t)]}}if(r){return null}else{throw new Error('"'+t+'" is not in the SourceMap.')}};BasicSourceMapConsumer.prototype.generatedPositionFor=function SourceMapConsumer_generatedPositionFor(e){var r=o.getArg(e,"source");r=this._findSourceIndex(r);if(r<0){return{line:null,column:null,lastColumn:null}}var n={source:r,originalLine:o.getArg(e,"line"),originalColumn:o.getArg(e,"column")};var t=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,o.getArg(e,"bias",SourceMapConsumer.GREATEST_LOWER_BOUND));if(t>=0){var i=this._originalMappings[t];if(i.source===n.source){return{line:o.getArg(i,"generatedLine",null),column:o.getArg(i,"generatedColumn",null),lastColumn:o.getArg(i,"lastGeneratedColumn",null)}}}return{line:null,column:null,lastColumn:null}};t=BasicSourceMapConsumer;function IndexedSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sections");if(t!=this._version){throw new Error("Unsupported version: "+t)}this._sources=new a;this._names=new a;var u={line:-1,column:0};this._sections=i.map((function(e){if(e.url){throw new Error("Support for url field in sections not implemented.")}var n=o.getArg(e,"offset");var t=o.getArg(n,"line");var i=o.getArg(n,"column");if(t{var t=n(449);var o=n(339);var i=n(274).I;var a=n(680).H;function SourceMapGenerator(e){if(!e){e={}}this._file=o.getArg(e,"file",null);this._sourceRoot=o.getArg(e,"sourceRoot",null);this._skipValidation=o.getArg(e,"skipValidation",false);this._sources=new i;this._names=new i;this._mappings=new a;this._sourcesContents=null}SourceMapGenerator.prototype._version=3;SourceMapGenerator.fromSourceMap=function SourceMapGenerator_fromSourceMap(e){var r=e.sourceRoot;var n=new SourceMapGenerator({file:e.file,sourceRoot:r});e.eachMapping((function(e){var t={generated:{line:e.generatedLine,column:e.generatedColumn}};if(e.source!=null){t.source=e.source;if(r!=null){t.source=o.relative(r,t.source)}t.original={line:e.originalLine,column:e.originalColumn};if(e.name!=null){t.name=e.name}}n.addMapping(t)}));e.sources.forEach((function(t){var i=t;if(r!==null){i=o.relative(r,t)}if(!n._sources.has(i)){n._sources.add(i)}var a=e.sourceContentFor(t);if(a!=null){n.setSourceContent(t,a)}}));return n};SourceMapGenerator.prototype.addMapping=function SourceMapGenerator_addMapping(e){var r=o.getArg(e,"generated");var n=o.getArg(e,"original",null);var t=o.getArg(e,"source",null);var i=o.getArg(e,"name",null);if(!this._skipValidation){this._validateMapping(r,n,t,i)}if(t!=null){t=String(t);if(!this._sources.has(t)){this._sources.add(t)}}if(i!=null){i=String(i);if(!this._names.has(i)){this._names.add(i)}}this._mappings.add({generatedLine:r.line,generatedColumn:r.column,originalLine:n!=null&&n.line,originalColumn:n!=null&&n.column,source:t,name:i})};SourceMapGenerator.prototype.setSourceContent=function SourceMapGenerator_setSourceContent(e,r){var n=e;if(this._sourceRoot!=null){n=o.relative(this._sourceRoot,n)}if(r!=null){if(!this._sourcesContents){this._sourcesContents=Object.create(null)}this._sourcesContents[o.toSetString(n)]=r}else if(this._sourcesContents){delete this._sourcesContents[o.toSetString(n)];if(Object.keys(this._sourcesContents).length===0){this._sourcesContents=null}}};SourceMapGenerator.prototype.applySourceMap=function SourceMapGenerator_applySourceMap(e,r,n){var t=r;if(r==null){if(e.file==null){throw new Error("SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, "+'or the source map\'s "file" property. Both were omitted.')}t=e.file}var a=this._sourceRoot;if(a!=null){t=o.relative(a,t)}var u=new i;var s=new i;this._mappings.unsortedForEach((function(r){if(r.source===t&&r.originalLine!=null){var i=e.originalPositionFor({line:r.originalLine,column:r.originalColumn});if(i.source!=null){r.source=i.source;if(n!=null){r.source=o.join(n,r.source)}if(a!=null){r.source=o.relative(a,r.source)}r.originalLine=i.line;r.originalColumn=i.column;if(i.name!=null){r.name=i.name}}}var l=r.source;if(l!=null&&!u.has(l)){u.add(l)}var c=r.name;if(c!=null&&!s.has(c)){s.add(c)}}),this);this._sources=u;this._names=s;e.sources.forEach((function(r){var t=e.sourceContentFor(r);if(t!=null){if(n!=null){r=o.join(n,r)}if(a!=null){r=o.relative(a,r)}this.setSourceContent(r,t)}}),this)};SourceMapGenerator.prototype._validateMapping=function SourceMapGenerator_validateMapping(e,r,n,t){if(r&&typeof r.line!=="number"&&typeof r.column!=="number"){throw new Error("original.line and original.column are not numbers -- you probably meant to omit "+"the original mapping entirely and only map the generated position. If so, pass "+"null for the original mapping instead of an object with empty or null values.")}if(e&&"line"in e&&"column"in e&&e.line>0&&e.column>=0&&!r&&!n&&!t){return}else if(e&&"line"in e&&"column"in e&&r&&"line"in r&&"column"in r&&e.line>0&&e.column>=0&&r.line>0&&r.column>=0&&n){return}else{throw new Error("Invalid mapping: "+JSON.stringify({generated:e,source:n,original:r,name:t}))}};SourceMapGenerator.prototype._serializeMappings=function SourceMapGenerator_serializeMappings(){var e=0;var r=1;var n=0;var i=0;var a=0;var u=0;var s="";var l;var c;var p;var f;var g=this._mappings.toArray();for(var h=0,d=g.length;h0){if(!o.compareByGeneratedPositionsInflated(c,g[h-1])){continue}l+=","}}l+=t.encode(c.generatedColumn-e);e=c.generatedColumn;if(c.source!=null){f=this._sources.indexOf(c.source);l+=t.encode(f-u);u=f;l+=t.encode(c.originalLine-1-i);i=c.originalLine-1;l+=t.encode(c.originalColumn-n);n=c.originalColumn;if(c.name!=null){p=this._names.indexOf(c.name);l+=t.encode(p-a);a=p}}s+=l}return s};SourceMapGenerator.prototype._generateSourcesContent=function SourceMapGenerator_generateSourcesContent(e,r){return e.map((function(e){if(!this._sourcesContents){return null}if(r!=null){e=o.relative(r,e)}var n=o.toSetString(e);return Object.prototype.hasOwnProperty.call(this._sourcesContents,n)?this._sourcesContents[n]:null}),this)};SourceMapGenerator.prototype.toJSON=function SourceMapGenerator_toJSON(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};if(this._file!=null){e.file=this._file}if(this._sourceRoot!=null){e.sourceRoot=this._sourceRoot}if(this._sourcesContents){e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)}return e};SourceMapGenerator.prototype.toString=function SourceMapGenerator_toString(){return JSON.stringify(this.toJSON())};r.h=SourceMapGenerator},351:(e,r,n)=>{var t;var o=n(591).h;var i=n(339);var a=/(\r?\n)/;var u=10;var s="$$$isSourceNode$$$";function SourceNode(e,r,n,t,o){this.children=[];this.sourceContents={};this.line=e==null?null:e;this.column=r==null?null:r;this.source=n==null?null:n;this.name=o==null?null:o;this[s]=true;if(t!=null)this.add(t)}SourceNode.fromStringWithSourceMap=function SourceNode_fromStringWithSourceMap(e,r,n){var t=new SourceNode;var o=e.split(a);var u=0;var shiftNextLine=function(){var e=getNextLine();var r=getNextLine()||"";return e+r;function getNextLine(){return u=0;r--){this.prepend(e[r])}}else if(e[s]||typeof e==="string"){this.children.unshift(e)}else{throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e)}return this};SourceNode.prototype.walk=function SourceNode_walk(e){var r;for(var n=0,t=this.children.length;n0){r=[];for(n=0;n{function getArg(e,r,n){if(r in e){return e[r]}else if(arguments.length===3){return n}else{throw new Error('"'+r+'" is a required argument.')}}r.getArg=getArg;var n=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;var t=/^data:.+\,.+$/;function urlParse(e){var r=e.match(n);if(!r){return null}return{scheme:r[1],auth:r[2],host:r[3],port:r[4],path:r[5]}}r.urlParse=urlParse;function urlGenerate(e){var r="";if(e.scheme){r+=e.scheme+":"}r+="//";if(e.auth){r+=e.auth+"@"}if(e.host){r+=e.host}if(e.port){r+=":"+e.port}if(e.path){r+=e.path}return r}r.urlGenerate=urlGenerate;function normalize(e){var n=e;var t=urlParse(e);if(t){if(!t.path){return e}n=t.path}var o=r.isAbsolute(n);var i=n.split(/\/+/);for(var a,u=0,s=i.length-1;s>=0;s--){a=i[s];if(a==="."){i.splice(s,1)}else if(a===".."){u++}else if(u>0){if(a===""){i.splice(s+1,u);u=0}else{i.splice(s,2);u--}}}n=i.join("/");if(n===""){n=o?"/":"."}if(t){t.path=n;return urlGenerate(t)}return n}r.normalize=normalize;function join(e,r){if(e===""){e="."}if(r===""){r="."}var n=urlParse(r);var o=urlParse(e);if(o){e=o.path||"/"}if(n&&!n.scheme){if(o){n.scheme=o.scheme}return urlGenerate(n)}if(n||r.match(t)){return r}if(o&&!o.host&&!o.path){o.host=r;return urlGenerate(o)}var i=r.charAt(0)==="/"?r:normalize(e.replace(/\/+$/,"")+"/"+r);if(o){o.path=i;return urlGenerate(o)}return i}r.join=join;r.isAbsolute=function(e){return e.charAt(0)==="/"||n.test(e)};function relative(e,r){if(e===""){e="."}e=e.replace(/\/$/,"");var n=0;while(r.indexOf(e+"/")!==0){var t=e.lastIndexOf("/");if(t<0){return r}e=e.slice(0,t);if(e.match(/^([^\/]+:\/)?\/*$/)){return r}++n}return Array(n+1).join("../")+r.substr(e.length+1)}r.relative=relative;var o=function(){var e=Object.create(null);return!("__proto__"in e)}();function identity(e){return e}function toSetString(e){if(isProtoString(e)){return"$"+e}return e}r.toSetString=o?identity:toSetString;function fromSetString(e){if(isProtoString(e)){return e.slice(1)}return e}r.fromSetString=o?identity:fromSetString;function isProtoString(e){if(!e){return false}var r=e.length;if(r<9){return false}if(e.charCodeAt(r-1)!==95||e.charCodeAt(r-2)!==95||e.charCodeAt(r-3)!==111||e.charCodeAt(r-4)!==116||e.charCodeAt(r-5)!==111||e.charCodeAt(r-6)!==114||e.charCodeAt(r-7)!==112||e.charCodeAt(r-8)!==95||e.charCodeAt(r-9)!==95){return false}for(var n=r-10;n>=0;n--){if(e.charCodeAt(n)!==36){return false}}return true}function compareByOriginalPositions(e,r,n){var t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0||n){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0){return t}t=e.generatedLine-r.generatedLine;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByOriginalPositions=compareByOriginalPositions;function compareByGeneratedPositionsDeflated(e,r,n){var t=e.generatedLine-r.generatedLine;if(t!==0){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0||n){return t}t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsDeflated=compareByGeneratedPositionsDeflated;function strcmp(e,r){if(e===r){return 0}if(e===null){return 1}if(r===null){return-1}if(e>r){return 1}return-1}function compareByGeneratedPositionsInflated(e,r){var n=e.generatedLine-r.generatedLine;if(n!==0){return n}n=e.generatedColumn-r.generatedColumn;if(n!==0){return n}n=strcmp(e.source,r.source);if(n!==0){return n}n=e.originalLine-r.originalLine;if(n!==0){return n}n=e.originalColumn-r.originalColumn;if(n!==0){return n}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsInflated=compareByGeneratedPositionsInflated;function parseSourceMapInput(e){return JSON.parse(e.replace(/^\)]}'[^\n]*\n/,""))}r.parseSourceMapInput=parseSourceMapInput;function computeSourceURL(e,r,n){r=r||"";if(e){if(e[e.length-1]!=="/"&&r[0]!=="/"){e+="/"}r=e+r}if(n){var t=urlParse(n);if(!t){throw new Error("sourceMapURL could not be parsed")}if(t.path){var o=t.path.lastIndexOf("/");if(o>=0){t.path=t.path.substring(0,o+1)}}r=join(urlGenerate(t),r)}return normalize(r)}r.computeSourceURL=computeSourceURL},997:(e,r,n)=>{n(591).h;r.SourceMapConsumer=n(952).SourceMapConsumer;n(351)},284:(e,r,n)=>{e=n.nmd(e);var t=n(997).SourceMapConsumer;var o=n(17);var i;try{i=n(147);if(!i.existsSync||!i.readFileSync){i=null}}catch(e){}var a=n(650);function dynamicRequire(e,r){return e.require(r)}var u=false;var s=false;var l=false;var c="auto";var p={};var f={};var g=/^data:application\/json[^,]+base64,/;var h=[];var d=[];function isInBrowser(){if(c==="browser")return true;if(c==="node")return false;return typeof window!=="undefined"&&typeof XMLHttpRequest==="function"&&!(window.require&&window.module&&window.process&&window.process.type==="renderer")}function hasGlobalProcessEventEmitter(){return typeof process==="object"&&process!==null&&typeof process.on==="function"}function globalProcessVersion(){if(typeof process==="object"&&process!==null){return process.version}else{return""}}function globalProcessStderr(){if(typeof process==="object"&&process!==null){return process.stderr}}function globalProcessExit(e){if(typeof process==="object"&&process!==null&&typeof process.exit==="function"){return process.exit(e)}}function handlerExec(e){return function(r){for(var n=0;n"}var n=this.getLineNumber();if(n!=null){r+=":"+n;var t=this.getColumnNumber();if(t){r+=":"+t}}}var o="";var i=this.getFunctionName();var a=true;var u=this.isConstructor();var s=!(this.isToplevel()||u);if(s){var l=this.getTypeName();if(l==="[object Object]"){l="null"}var c=this.getMethodName();if(i){if(l&&i.indexOf(l)!=0){o+=l+"."}o+=i;if(c&&i.indexOf("."+c)!=i.length-c.length-1){o+=" [as "+c+"]"}}else{o+=l+"."+(c||"")}}else if(u){o+="new "+(i||"")}else if(i){o+=i}else{o+=r;a=false}if(a){o+=" ("+r+")"}return o}function cloneCallSite(e){var r={};Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach((function(n){r[n]=/^(?:is|get)/.test(n)?function(){return e[n].call(e)}:e[n]}));r.toString=CallSiteToString;return r}function wrapCallSite(e,r){if(r===undefined){r={nextPosition:null,curPosition:null}}if(e.isNative()){r.curPosition=null;return e}var n=e.getFileName()||e.getScriptNameOrSourceURL();if(n){var t=e.getLineNumber();var o=e.getColumnNumber()-1;var i=/^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;var a=i.test(globalProcessVersion())?0:62;if(t===1&&o>a&&!isInBrowser()&&!e.isEval()){o-=a}var u=mapSourcePosition({source:n,line:t,column:o});r.curPosition=u;e=cloneCallSite(e);var s=e.getFunctionName;e.getFunctionName=function(){if(r.nextPosition==null){return s()}return r.nextPosition.name||s()};e.getFileName=function(){return u.source};e.getLineNumber=function(){return u.line};e.getColumnNumber=function(){return u.column+1};e.getScriptNameOrSourceURL=function(){return u.source};return e}var l=e.isEval()&&e.getEvalOrigin();if(l){l=mapEvalOrigin(l);e=cloneCallSite(e);e.getEvalOrigin=function(){return l};return e}return e}function prepareStackTrace(e,r){if(l){p={};f={}}var n=e.name||"Error";var t=e.message||"";var o=n+": "+t;var i={nextPosition:null,curPosition:null};var a=[];for(var u=r.length-1;u>=0;u--){a.push("\n at "+wrapCallSite(r[u],i));i.nextPosition=i.curPosition}i.curPosition=i.nextPosition=null;return o+a.reverse().join("")}function getErrorSource(e){var r=/\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(e.stack);if(r){var n=r[1];var t=+r[2];var o=+r[3];var a=p[n];if(!a&&i&&i.existsSync(n)){try{a=i.readFileSync(n,"utf8")}catch(e){a=""}}if(a){var u=a.split(/(?:\r\n|\r|\n)/)[t-1];if(u){return n+":"+t+"\n"+u+"\n"+new Array(o).join(" ")+"^"}}}return null}function printErrorAndExit(e){var r=getErrorSource(e);var n=globalProcessStderr();if(n&&n._handle&&n._handle.setBlocking){n._handle.setBlocking(true)}if(r){console.error();console.error(r)}console.error(e.stack);globalProcessExit(1)}function shimEmitUncaughtException(){var e=process.emit;process.emit=function(r){if(r==="uncaughtException"){var n=arguments[1]&&arguments[1].stack;var t=this.listeners(r).length>0;if(n&&!t){return printErrorAndExit(arguments[1])}}return e.apply(this,arguments)}}var S=h.slice(0);var _=d.slice(0);r.wrapCallSite=wrapCallSite;r.getErrorSource=getErrorSource;r.mapSourcePosition=mapSourcePosition;r.retrieveSourceMap=v;r.install=function(r){r=r||{};if(r.environment){c=r.environment;if(["node","browser","auto"].indexOf(c)===-1){throw new Error("environment "+c+" was unknown. Available options are {auto, browser, node}")}}if(r.retrieveFile){if(r.overrideRetrieveFile){h.length=0}h.unshift(r.retrieveFile)}if(r.retrieveSourceMap){if(r.overrideRetrieveSourceMap){d.length=0}d.unshift(r.retrieveSourceMap)}if(r.hookRequire&&!isInBrowser()){var n=dynamicRequire(e,"module");var t=n.prototype._compile;if(!t.__sourceMapSupport){n.prototype._compile=function(e,r){p[r]=e;f[r]=undefined;return t.call(this,e,r)};n.prototype._compile.__sourceMapSupport=true}}if(!l){l="emptyCacheBetweenOperations"in r?r.emptyCacheBetweenOperations:false}if(!u){u=true;Error.prepareStackTrace=prepareStackTrace}if(!s){var o="handleUncaughtExceptions"in r?r.handleUncaughtExceptions:true;try{var i=dynamicRequire(e,"worker_threads");if(i.isMainThread===false){o=false}}catch(e){}if(o&&hasGlobalProcessEventEmitter()){s=true;shimEmitUncaughtException()}}};r.resetRetrieveHandlers=function(){h.length=0;d.length=0;h=S.slice(0);d=_.slice(0);v=handlerExec(d);m=handlerExec(h)}},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")}};var r={};function __webpack_require__(n){var t=r[n];if(t!==undefined){return t.exports}var o=r[n]={id:n,loaded:false,exports:{}};var i=true;try{e[n](o,o.exports,__webpack_require__);i=false}finally{if(i)delete r[n]}o.loaded=true;return o.exports}(()=>{__webpack_require__.nmd=e=>{e.paths=[];if(!e.children)e.children=[];return e}})();if(typeof __webpack_require__!=="undefined")__webpack_require__.ab=__dirname+"/";var n={};(()=>{__webpack_require__(284).install()})();module.exports=n})(); \ No newline at end of file diff --git a/.github/actions/cargo-sweep/dist/post/index.js b/.github/actions/cargo-sweep/dist/post/index.js deleted file mode 100644 index 795eb438bd6ba..0000000000000 --- a/.github/actions/cargo-sweep/dist/post/index.js +++ /dev/null @@ -1,4157 +0,0 @@ -require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ 925: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const core = __nccwpck_require__(363); -const exec = __nccwpck_require__(141); - -async function runSweep(...args) { - // TODO(alexkirsz) A cargo change introduced a regression where cargo can't - // find the sweep binary. This is a temporary workaround until the fix is - // released. See: - // https://github.com/rust-lang/cargo/pull/11814 - await exec.exec("cargo-sweep", ["sweep", ...args]); -} - -async function storeTimestamp() { - await core.group("Storing timestamp to compare later", () => - runSweep("--stamp") - ); - - core.info("Timestamp stored in `sweep.timestamp`"); -} - -async function sweep() { - await core.group("Cleaning old build artifacts", () => runSweep("--file")); - - core.info("Removed old build artifacts."); -} - -module.exports = { - storeTimestamp, - sweep, -}; - - -/***/ }), - -/***/ 255: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.issue = exports.issueCommand = void 0; -const os = __importStar(__nccwpck_require__(37)); -const utils_1 = __nccwpck_require__(393); -/** - * Commands - * - * Command Format: - * ::name key=value,key=value::message - * - * Examples: - * ::warning::This is the message - * ::set-env name=MY_VAR::some value - */ -function issueCommand(command, properties, message) { - const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os.EOL); -} -exports.issueCommand = issueCommand; -function issue(name, message = '') { - issueCommand(name, {}, message); -} -exports.issue = issue; -const CMD_STRING = '::'; -class Command { - constructor(command, properties, message) { - if (!command) { - command = 'missing.command'; - } - this.command = command; - this.properties = properties; - this.message = message; - } - toString() { - let cmdStr = CMD_STRING + this.command; - if (this.properties && Object.keys(this.properties).length > 0) { - cmdStr += ' '; - let first = true; - for (const key in this.properties) { - if (this.properties.hasOwnProperty(key)) { - const val = this.properties[key]; - if (val) { - if (first) { - first = false; - } - else { - cmdStr += ','; - } - cmdStr += `${key}=${escapeProperty(val)}`; - } - } - } - } - cmdStr += `${CMD_STRING}${escapeData(this.message)}`; - return cmdStr; - } -} -function escapeData(s) { - return utils_1.toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A'); -} -function escapeProperty(s) { - return utils_1.toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A') - .replace(/:/g, '%3A') - .replace(/,/g, '%2C'); -} -//# sourceMappingURL=command.js.map - -/***/ }), - -/***/ 363: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(255); -const file_command_1 = __nccwpck_require__(189); -const utils_1 = __nccwpck_require__(393); -const os = __importStar(__nccwpck_require__(37)); -const path = __importStar(__nccwpck_require__(17)); -const oidc_utils_1 = __nccwpck_require__(226); -/** - * The code to exit an action - */ -var ExitCode; -(function (ExitCode) { - /** - * A code indicating that the action was successful - */ - ExitCode[ExitCode["Success"] = 0] = "Success"; - /** - * A code indicating that the action was a failure - */ - ExitCode[ExitCode["Failure"] = 1] = "Failure"; -})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); -//----------------------------------------------------------------------- -// Variables -//----------------------------------------------------------------------- -/** - * Sets env variable for this action and future actions in the job - * @param name the name of the variable to set - * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function exportVariable(name, val) { - const convertedVal = utils_1.toCommandValue(val); - process.env[name] = convertedVal; - const filePath = process.env['GITHUB_ENV'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); - } - command_1.issueCommand('set-env', { name }, convertedVal); -} -exports.exportVariable = exportVariable; -/** - * Registers a secret which will get masked from logs - * @param secret value of the secret - */ -function setSecret(secret) { - command_1.issueCommand('add-mask', {}, secret); -} -exports.setSecret = setSecret; -/** - * Prepends inputPath to the PATH (for this action and future actions) - * @param inputPath - */ -function addPath(inputPath) { - const filePath = process.env['GITHUB_PATH'] || ''; - if (filePath) { - file_command_1.issueFileCommand('PATH', inputPath); - } - else { - command_1.issueCommand('add-path', {}, inputPath); - } - process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; -} -exports.addPath = addPath; -/** - * Gets the value of an input. - * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. - * Returns an empty string if the value is not defined. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string - */ -function getInput(name, options) { - const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; - if (options && options.required && !val) { - throw new Error(`Input required and not supplied: ${name}`); - } - if (options && options.trimWhitespace === false) { - return val; - } - return val.trim(); -} -exports.getInput = getInput; -/** - * Gets the values of an multiline input. Each value is also trimmed. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string[] - * - */ -function getMultilineInput(name, options) { - const inputs = getInput(name, options) - .split('\n') - .filter(x => x !== ''); - if (options && options.trimWhitespace === false) { - return inputs; - } - return inputs.map(input => input.trim()); -} -exports.getMultilineInput = getMultilineInput; -/** - * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. - * Support boolean input list: `true | True | TRUE | false | False | FALSE` . - * The return value is also in boolean type. - * ref: https://yaml.org/spec/1.2/spec.html#id2804923 - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns boolean - */ -function getBooleanInput(name, options) { - const trueValue = ['true', 'True', 'TRUE']; - const falseValue = ['false', 'False', 'FALSE']; - const val = getInput(name, options); - if (trueValue.includes(val)) - return true; - if (falseValue.includes(val)) - return false; - throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + - `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); -} -exports.getBooleanInput = getBooleanInput; -/** - * Sets the value of an output. - * - * @param name name of the output to set - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function setOutput(name, value) { - const filePath = process.env['GITHUB_OUTPUT'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); - } - process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); -} -exports.setOutput = setOutput; -/** - * Enables or disables the echoing of commands into stdout for the rest of the step. - * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. - * - */ -function setCommandEcho(enabled) { - command_1.issue('echo', enabled ? 'on' : 'off'); -} -exports.setCommandEcho = setCommandEcho; -//----------------------------------------------------------------------- -// Results -//----------------------------------------------------------------------- -/** - * Sets the action status to failed. - * When the action exits it will be with an exit code of 1 - * @param message add error issue message - */ -function setFailed(message) { - process.exitCode = ExitCode.Failure; - error(message); -} -exports.setFailed = setFailed; -//----------------------------------------------------------------------- -// Logging Commands -//----------------------------------------------------------------------- -/** - * Gets whether Actions Step Debug is on or not - */ -function isDebug() { - return process.env['RUNNER_DEBUG'] === '1'; -} -exports.isDebug = isDebug; -/** - * Writes debug message to user log - * @param message debug message - */ -function debug(message) { - command_1.issueCommand('debug', {}, message); -} -exports.debug = debug; -/** - * Adds an error issue - * @param message error issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function error(message, properties = {}) { - command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); -} -exports.error = error; -/** - * Adds a warning issue - * @param message warning issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function warning(message, properties = {}) { - command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); -} -exports.warning = warning; -/** - * Adds a notice issue - * @param message notice issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function notice(message, properties = {}) { - command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); -} -exports.notice = notice; -/** - * Writes info to log with console.log. - * @param message info message - */ -function info(message) { - process.stdout.write(message + os.EOL); -} -exports.info = info; -/** - * Begin an output group. - * - * Output until the next `groupEnd` will be foldable in this group - * - * @param name The name of the output group - */ -function startGroup(name) { - command_1.issue('group', name); -} -exports.startGroup = startGroup; -/** - * End an output group. - */ -function endGroup() { - command_1.issue('endgroup'); -} -exports.endGroup = endGroup; -/** - * Wrap an asynchronous function call in a group. - * - * Returns the same type as the function itself. - * - * @param name The name of the group - * @param fn The function to wrap in the group - */ -function group(name, fn) { - return __awaiter(this, void 0, void 0, function* () { - startGroup(name); - let result; - try { - result = yield fn(); - } - finally { - endGroup(); - } - return result; - }); -} -exports.group = group; -//----------------------------------------------------------------------- -// Wrapper action state -//----------------------------------------------------------------------- -/** - * Saves state for current action, the state can only be retrieved by this action's post job execution. - * - * @param name name of the state to store - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function saveState(name, value) { - const filePath = process.env['GITHUB_STATE'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); - } - command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); -} -exports.saveState = saveState; -/** - * Gets the value of an state set by this action's main execution. - * - * @param name name of the state to get - * @returns string - */ -function getState(name) { - return process.env[`STATE_${name}`] || ''; -} -exports.getState = getState; -function getIDToken(aud) { - return __awaiter(this, void 0, void 0, function* () { - return yield oidc_utils_1.OidcClient.getIDToken(aud); - }); -} -exports.getIDToken = getIDToken; -/** - * Summary exports - */ -var summary_1 = __nccwpck_require__(874); -Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); -/** - * @deprecated use core.summary - */ -var summary_2 = __nccwpck_require__(874); -Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); -/** - * Path exports - */ -var path_utils_1 = __nccwpck_require__(88); -Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); -Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); -Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); -//# sourceMappingURL=core.js.map - -/***/ }), - -/***/ 189: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -// For internal use, subject to change. -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__nccwpck_require__(147)); -const os = __importStar(__nccwpck_require__(37)); -const uuid_1 = __nccwpck_require__(503); -const utils_1 = __nccwpck_require__(393); -function issueFileCommand(command, message) { - const filePath = process.env[`GITHUB_${command}`]; - if (!filePath) { - throw new Error(`Unable to find environment variable for file command ${command}`); - } - if (!fs.existsSync(filePath)) { - throw new Error(`Missing file at path: ${filePath}`); - } - fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { - encoding: 'utf8' - }); -} -exports.issueFileCommand = issueFileCommand; -function prepareKeyValueMessage(key, value) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - const convertedValue = utils_1.toCommandValue(value); - // These should realistically never happen, but just in case someone finds a - // way to exploit uuid generation let's not allow keys or values that contain - // the delimiter. - if (key.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedValue.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; -} -exports.prepareKeyValueMessage = prepareKeyValueMessage; -//# sourceMappingURL=file-command.js.map - -/***/ }), - -/***/ 226: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(882); -const auth_1 = __nccwpck_require__(362); -const core_1 = __nccwpck_require__(363); -class OidcClient { - static createHttpClient(allowRetry = true, maxRetry = 10) { - const requestOptions = { - allowRetries: allowRetry, - maxRetries: maxRetry - }; - return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); - } - static getRequestToken() { - const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; - if (!token) { - throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); - } - return token; - } - static getIDTokenUrl() { - const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; - if (!runtimeUrl) { - throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); - } - return runtimeUrl; - } - static getCall(id_token_url) { - var _a; - return __awaiter(this, void 0, void 0, function* () { - const httpclient = OidcClient.createHttpClient(); - const res = yield httpclient - .getJson(id_token_url) - .catch(error => { - throw new Error(`Failed to get ID Token. \n - Error Code : ${error.statusCode}\n - Error Message: ${error.result.message}`); - }); - const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; - if (!id_token) { - throw new Error('Response json body do not have ID Token field'); - } - return id_token; - }); - } - static getIDToken(audience) { - return __awaiter(this, void 0, void 0, function* () { - try { - // New ID Token is requested from action service - let id_token_url = OidcClient.getIDTokenUrl(); - if (audience) { - const encodedAudience = encodeURIComponent(audience); - id_token_url = `${id_token_url}&audience=${encodedAudience}`; - } - core_1.debug(`ID token url is ${id_token_url}`); - const id_token = yield OidcClient.getCall(id_token_url); - core_1.setSecret(id_token); - return id_token; - } - catch (error) { - throw new Error(`Error message: ${error.message}`); - } - }); - } -} -exports.OidcClient = OidcClient; -//# sourceMappingURL=oidc-utils.js.map - -/***/ }), - -/***/ 88: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; -const path = __importStar(__nccwpck_require__(17)); -/** - * toPosixPath converts the given path to the posix form. On Windows, \\ will be - * replaced with /. - * - * @param pth. Path to transform. - * @return string Posix path. - */ -function toPosixPath(pth) { - return pth.replace(/[\\]/g, '/'); -} -exports.toPosixPath = toPosixPath; -/** - * toWin32Path converts the given path to the win32 form. On Linux, / will be - * replaced with \\. - * - * @param pth. Path to transform. - * @return string Win32 path. - */ -function toWin32Path(pth) { - return pth.replace(/[/]/g, '\\'); -} -exports.toWin32Path = toWin32Path; -/** - * toPlatformPath converts the given path to a platform-specific path. It does - * this by replacing instances of / and \ with the platform-specific path - * separator. - * - * @param pth The path to platformize. - * @return string The platform-specific path. - */ -function toPlatformPath(pth) { - return pth.replace(/[/\\]/g, path.sep); -} -exports.toPlatformPath = toPlatformPath; -//# sourceMappingURL=path-utils.js.map - -/***/ }), - -/***/ 874: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; -const os_1 = __nccwpck_require__(37); -const fs_1 = __nccwpck_require__(147); -const { access, appendFile, writeFile } = fs_1.promises; -exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; -exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; -class Summary { - constructor() { - this._buffer = ''; - } - /** - * Finds the summary file path from the environment, rejects if env var is not found or file does not exist - * Also checks r/w permissions. - * - * @returns step summary file path - */ - filePath() { - return __awaiter(this, void 0, void 0, function* () { - if (this._filePath) { - return this._filePath; - } - const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; - if (!pathFromEnv) { - throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); - } - try { - yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); - } - catch (_a) { - throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); - } - this._filePath = pathFromEnv; - return this._filePath; - }); - } - /** - * Wraps content in an HTML tag, adding any HTML attributes - * - * @param {string} tag HTML tag to wrap - * @param {string | null} content content within the tag - * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add - * - * @returns {string} content wrapped in HTML element - */ - wrap(tag, content, attrs = {}) { - const htmlAttrs = Object.entries(attrs) - .map(([key, value]) => ` ${key}="${value}"`) - .join(''); - if (!content) { - return `<${tag}${htmlAttrs}>`; - } - return `<${tag}${htmlAttrs}>${content}`; - } - /** - * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. - * - * @param {SummaryWriteOptions} [options] (optional) options for write operation - * - * @returns {Promise} summary instance - */ - write(options) { - return __awaiter(this, void 0, void 0, function* () { - const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); - const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; - yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); - return this.emptyBuffer(); - }); - } - /** - * Clears the summary buffer and wipes the summary file - * - * @returns {Summary} summary instance - */ - clear() { - return __awaiter(this, void 0, void 0, function* () { - return this.emptyBuffer().write({ overwrite: true }); - }); - } - /** - * Returns the current summary buffer as a string - * - * @returns {string} string of summary buffer - */ - stringify() { - return this._buffer; - } - /** - * If the summary buffer is empty - * - * @returns {boolen} true if the buffer is empty - */ - isEmptyBuffer() { - return this._buffer.length === 0; - } - /** - * Resets the summary buffer without writing to summary file - * - * @returns {Summary} summary instance - */ - emptyBuffer() { - this._buffer = ''; - return this; - } - /** - * Adds raw text to the summary buffer - * - * @param {string} text content to add - * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) - * - * @returns {Summary} summary instance - */ - addRaw(text, addEOL = false) { - this._buffer += text; - return addEOL ? this.addEOL() : this; - } - /** - * Adds the operating system-specific end-of-line marker to the buffer - * - * @returns {Summary} summary instance - */ - addEOL() { - return this.addRaw(os_1.EOL); - } - /** - * Adds an HTML codeblock to the summary buffer - * - * @param {string} code content to render within fenced code block - * @param {string} lang (optional) language to syntax highlight code - * - * @returns {Summary} summary instance - */ - addCodeBlock(code, lang) { - const attrs = Object.assign({}, (lang && { lang })); - const element = this.wrap('pre', this.wrap('code', code), attrs); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML list to the summary buffer - * - * @param {string[]} items list of items to render - * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) - * - * @returns {Summary} summary instance - */ - addList(items, ordered = false) { - const tag = ordered ? 'ol' : 'ul'; - const listItems = items.map(item => this.wrap('li', item)).join(''); - const element = this.wrap(tag, listItems); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML table to the summary buffer - * - * @param {SummaryTableCell[]} rows table rows - * - * @returns {Summary} summary instance - */ - addTable(rows) { - const tableBody = rows - .map(row => { - const cells = row - .map(cell => { - if (typeof cell === 'string') { - return this.wrap('td', cell); - } - const { header, data, colspan, rowspan } = cell; - const tag = header ? 'th' : 'td'; - const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); - return this.wrap(tag, data, attrs); - }) - .join(''); - return this.wrap('tr', cells); - }) - .join(''); - const element = this.wrap('table', tableBody); - return this.addRaw(element).addEOL(); - } - /** - * Adds a collapsable HTML details element to the summary buffer - * - * @param {string} label text for the closed state - * @param {string} content collapsable content - * - * @returns {Summary} summary instance - */ - addDetails(label, content) { - const element = this.wrap('details', this.wrap('summary', label) + content); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML image tag to the summary buffer - * - * @param {string} src path to the image you to embed - * @param {string} alt text description of the image - * @param {SummaryImageOptions} options (optional) addition image attributes - * - * @returns {Summary} summary instance - */ - addImage(src, alt, options) { - const { width, height } = options || {}; - const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); - const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML section heading element - * - * @param {string} text heading text - * @param {number | string} [level=1] (optional) the heading level, default: 1 - * - * @returns {Summary} summary instance - */ - addHeading(text, level) { - const tag = `h${level}`; - const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) - ? tag - : 'h1'; - const element = this.wrap(allowedTag, text); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML thematic break (
) to the summary buffer - * - * @returns {Summary} summary instance - */ - addSeparator() { - const element = this.wrap('hr', null); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML line break (
) to the summary buffer - * - * @returns {Summary} summary instance - */ - addBreak() { - const element = this.wrap('br', null); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML blockquote to the summary buffer - * - * @param {string} text quote text - * @param {string} cite (optional) citation url - * - * @returns {Summary} summary instance - */ - addQuote(text, cite) { - const attrs = Object.assign({}, (cite && { cite })); - const element = this.wrap('blockquote', text, attrs); - return this.addRaw(element).addEOL(); - } - /** - * Adds an HTML anchor tag to the summary buffer - * - * @param {string} text link text/content - * @param {string} href hyperlink - * - * @returns {Summary} summary instance - */ - addLink(text, href) { - const element = this.wrap('a', text, { href }); - return this.addRaw(element).addEOL(); - } -} -const _summary = new Summary(); -/** - * @deprecated use `core.summary` - */ -exports.markdownSummary = _summary; -exports.summary = _summary; -//# sourceMappingURL=summary.js.map - -/***/ }), - -/***/ 393: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toCommandProperties = exports.toCommandValue = void 0; -/** - * Sanitizes an input into a string so it can be passed into issueCommand safely - * @param input input to sanitize into a string - */ -function toCommandValue(input) { - if (input === null || input === undefined) { - return ''; - } - else if (typeof input === 'string' || input instanceof String) { - return input; - } - return JSON.stringify(input); -} -exports.toCommandValue = toCommandValue; -/** - * - * @param annotationProperties - * @returns The command properties to send with the actual annotation command - * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 - */ -function toCommandProperties(annotationProperties) { - if (!Object.keys(annotationProperties).length) { - return {}; - } - return { - title: annotationProperties.title, - file: annotationProperties.file, - line: annotationProperties.startLine, - endLine: annotationProperties.endLine, - col: annotationProperties.startColumn, - endColumn: annotationProperties.endColumn - }; -} -exports.toCommandProperties = toCommandProperties; -//# sourceMappingURL=utils.js.map - -/***/ }), - -/***/ 141: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getExecOutput = exports.exec = void 0; -const string_decoder_1 = __nccwpck_require__(576); -const tr = __importStar(__nccwpck_require__(624)); -/** - * Exec a command. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param commandLine command to execute (can include additional args). Must be correctly escaped. - * @param args optional arguments for tool. Escaping is handled by the lib. - * @param options optional exec options. See ExecOptions - * @returns Promise exit code - */ -function exec(commandLine, args, options) { - return __awaiter(this, void 0, void 0, function* () { - const commandArgs = tr.argStringToArray(commandLine); - if (commandArgs.length === 0) { - throw new Error(`Parameter 'commandLine' cannot be null or empty.`); - } - // Path to tool to execute should be first arg - const toolPath = commandArgs[0]; - args = commandArgs.slice(1).concat(args || []); - const runner = new tr.ToolRunner(toolPath, args, options); - return runner.exec(); - }); -} -exports.exec = exec; -/** - * Exec a command and get the output. - * Output will be streamed to the live console. - * Returns promise with the exit code and collected stdout and stderr - * - * @param commandLine command to execute (can include additional args). Must be correctly escaped. - * @param args optional arguments for tool. Escaping is handled by the lib. - * @param options optional exec options. See ExecOptions - * @returns Promise exit code, stdout, and stderr - */ -function getExecOutput(commandLine, args, options) { - var _a, _b; - return __awaiter(this, void 0, void 0, function* () { - let stdout = ''; - let stderr = ''; - //Using string decoder covers the case where a mult-byte character is split - const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); - const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); - const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; - const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; - const stdErrListener = (data) => { - stderr += stderrDecoder.write(data); - if (originalStdErrListener) { - originalStdErrListener(data); - } - }; - const stdOutListener = (data) => { - stdout += stdoutDecoder.write(data); - if (originalStdoutListener) { - originalStdoutListener(data); - } - }; - const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); - const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); - //flush any remaining characters - stdout += stdoutDecoder.end(); - stderr += stderrDecoder.end(); - return { - exitCode, - stdout, - stderr - }; - }); -} -exports.getExecOutput = getExecOutput; -//# sourceMappingURL=exec.js.map - -/***/ }), - -/***/ 624: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.argStringToArray = exports.ToolRunner = void 0; -const os = __importStar(__nccwpck_require__(37)); -const events = __importStar(__nccwpck_require__(361)); -const child = __importStar(__nccwpck_require__(81)); -const path = __importStar(__nccwpck_require__(17)); -const io = __importStar(__nccwpck_require__(59)); -const ioUtil = __importStar(__nccwpck_require__(152)); -const timers_1 = __nccwpck_require__(512); -/* eslint-disable @typescript-eslint/unbound-method */ -const IS_WINDOWS = process.platform === 'win32'; -/* - * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. - */ -class ToolRunner extends events.EventEmitter { - constructor(toolPath, args, options) { - super(); - if (!toolPath) { - throw new Error("Parameter 'toolPath' cannot be null or empty."); - } - this.toolPath = toolPath; - this.args = args || []; - this.options = options || {}; - } - _debug(message) { - if (this.options.listeners && this.options.listeners.debug) { - this.options.listeners.debug(message); - } - } - _getCommandString(options, noPrefix) { - const toolPath = this._getSpawnFileName(); - const args = this._getSpawnArgs(options); - let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool - if (IS_WINDOWS) { - // Windows + cmd file - if (this._isCmdFile()) { - cmd += toolPath; - for (const a of args) { - cmd += ` ${a}`; - } - } - // Windows + verbatim - else if (options.windowsVerbatimArguments) { - cmd += `"${toolPath}"`; - for (const a of args) { - cmd += ` ${a}`; - } - } - // Windows (regular) - else { - cmd += this._windowsQuoteCmdArg(toolPath); - for (const a of args) { - cmd += ` ${this._windowsQuoteCmdArg(a)}`; - } - } - } - else { - // OSX/Linux - this can likely be improved with some form of quoting. - // creating processes on Unix is fundamentally different than Windows. - // on Unix, execvp() takes an arg array. - cmd += toolPath; - for (const a of args) { - cmd += ` ${a}`; - } - } - return cmd; - } - _processLineBuffer(data, strBuffer, onLine) { - try { - let s = strBuffer + data.toString(); - let n = s.indexOf(os.EOL); - while (n > -1) { - const line = s.substring(0, n); - onLine(line); - // the rest of the string ... - s = s.substring(n + os.EOL.length); - n = s.indexOf(os.EOL); - } - return s; - } - catch (err) { - // streaming lines to console is best effort. Don't fail a build. - this._debug(`error processing line. Failed with error ${err}`); - return ''; - } - } - _getSpawnFileName() { - if (IS_WINDOWS) { - if (this._isCmdFile()) { - return process.env['COMSPEC'] || 'cmd.exe'; - } - } - return this.toolPath; - } - _getSpawnArgs(options) { - if (IS_WINDOWS) { - if (this._isCmdFile()) { - let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; - for (const a of this.args) { - argline += ' '; - argline += options.windowsVerbatimArguments - ? a - : this._windowsQuoteCmdArg(a); - } - argline += '"'; - return [argline]; - } - } - return this.args; - } - _endsWith(str, end) { - return str.endsWith(end); - } - _isCmdFile() { - const upperToolPath = this.toolPath.toUpperCase(); - return (this._endsWith(upperToolPath, '.CMD') || - this._endsWith(upperToolPath, '.BAT')); - } - _windowsQuoteCmdArg(arg) { - // for .exe, apply the normal quoting rules that libuv applies - if (!this._isCmdFile()) { - return this._uvQuoteCmdArg(arg); - } - // otherwise apply quoting rules specific to the cmd.exe command line parser. - // the libuv rules are generic and are not designed specifically for cmd.exe - // command line parser. - // - // for a detailed description of the cmd.exe command line parser, refer to - // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 - // need quotes for empty arg - if (!arg) { - return '""'; - } - // determine whether the arg needs to be quoted - const cmdSpecialChars = [ - ' ', - '\t', - '&', - '(', - ')', - '[', - ']', - '{', - '}', - '^', - '=', - ';', - '!', - "'", - '+', - ',', - '`', - '~', - '|', - '<', - '>', - '"' - ]; - let needsQuotes = false; - for (const char of arg) { - if (cmdSpecialChars.some(x => x === char)) { - needsQuotes = true; - break; - } - } - // short-circuit if quotes not needed - if (!needsQuotes) { - return arg; - } - // the following quoting rules are very similar to the rules that by libuv applies. - // - // 1) wrap the string in quotes - // - // 2) double-up quotes - i.e. " => "" - // - // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately - // doesn't work well with a cmd.exe command line. - // - // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. - // for example, the command line: - // foo.exe "myarg:""my val""" - // is parsed by a .NET console app into an arg array: - // [ "myarg:\"my val\"" ] - // which is the same end result when applying libuv quoting rules. although the actual - // command line from libuv quoting rules would look like: - // foo.exe "myarg:\"my val\"" - // - // 3) double-up slashes that precede a quote, - // e.g. hello \world => "hello \world" - // hello\"world => "hello\\""world" - // hello\\"world => "hello\\\\""world" - // hello world\ => "hello world\\" - // - // technically this is not required for a cmd.exe command line, or the batch argument parser. - // the reasons for including this as a .cmd quoting rule are: - // - // a) this is optimized for the scenario where the argument is passed from the .cmd file to an - // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. - // - // b) it's what we've been doing previously (by deferring to node default behavior) and we - // haven't heard any complaints about that aspect. - // - // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be - // escaped when used on the command line directly - even though within a .cmd file % can be escaped - // by using %%. - // - // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts - // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. - // - // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would - // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the - // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args - // to an external program. - // - // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. - // % can be escaped within a .cmd file. - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { - // walk the string in reverse - reverse += arg[i - 1]; - if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; // double the slash - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '"'; // double the quote - } - else { - quoteHit = false; - } - } - reverse += '"'; - return reverse - .split('') - .reverse() - .join(''); - } - _uvQuoteCmdArg(arg) { - // Tool runner wraps child_process.spawn() and needs to apply the same quoting as - // Node in certain cases where the undocumented spawn option windowsVerbatimArguments - // is used. - // - // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, - // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), - // pasting copyright notice from Node within this function: - // - // Copyright Joyent, Inc. and other Node contributors. All rights reserved. - // - // Permission is hereby granted, free of charge, to any person obtaining a copy - // of this software and associated documentation files (the "Software"), to - // deal in the Software without restriction, including without limitation the - // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - // sell copies of the Software, and to permit persons to whom the Software is - // furnished to do so, subject to the following conditions: - // - // The above copyright notice and this permission notice shall be included in - // all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - // IN THE SOFTWARE. - if (!arg) { - // Need double quotation for empty argument - return '""'; - } - if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { - // No quotation needed - return arg; - } - if (!arg.includes('"') && !arg.includes('\\')) { - // No embedded double quotes or backslashes, so I can just wrap - // quote marks around the whole thing. - return `"${arg}"`; - } - // Expected input/output: - // input : hello"world - // output: "hello\"world" - // input : hello""world - // output: "hello\"\"world" - // input : hello\world - // output: hello\world - // input : hello\\world - // output: hello\\world - // input : hello\"world - // output: "hello\\\"world" - // input : hello\\"world - // output: "hello\\\\\"world" - // input : hello world\ - // output: "hello world\\" - note the comment in libuv actually reads "hello world\" - // but it appears the comment is wrong, it should be "hello world\\" - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { - // walk the string in reverse - reverse += arg[i - 1]; - if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '\\'; - } - else { - quoteHit = false; - } - } - reverse += '"'; - return reverse - .split('') - .reverse() - .join(''); - } - _cloneExecOptions(options) { - options = options || {}; - const result = { - cwd: options.cwd || process.cwd(), - env: options.env || process.env, - silent: options.silent || false, - windowsVerbatimArguments: options.windowsVerbatimArguments || false, - failOnStdErr: options.failOnStdErr || false, - ignoreReturnCode: options.ignoreReturnCode || false, - delay: options.delay || 10000 - }; - result.outStream = options.outStream || process.stdout; - result.errStream = options.errStream || process.stderr; - return result; - } - _getSpawnOptions(options, toolPath) { - options = options || {}; - const result = {}; - result.cwd = options.cwd; - result.env = options.env; - result['windowsVerbatimArguments'] = - options.windowsVerbatimArguments || this._isCmdFile(); - if (options.windowsVerbatimArguments) { - result.argv0 = `"${toolPath}"`; - } - return result; - } - /** - * Exec a tool. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param tool path to tool to exec - * @param options optional exec options. See ExecOptions - * @returns number - */ - exec() { - return __awaiter(this, void 0, void 0, function* () { - // root the tool path if it is unrooted and contains relative pathing - if (!ioUtil.isRooted(this.toolPath) && - (this.toolPath.includes('/') || - (IS_WINDOWS && this.toolPath.includes('\\')))) { - // prefer options.cwd if it is specified, however options.cwd may also need to be rooted - this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); - } - // if the tool is only a file name, then resolve it from the PATH - // otherwise verify it exists (add extension on Windows if necessary) - this.toolPath = yield io.which(this.toolPath, true); - return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { - this._debug(`exec tool: ${this.toolPath}`); - this._debug('arguments:'); - for (const arg of this.args) { - this._debug(` ${arg}`); - } - const optionsNonNull = this._cloneExecOptions(this.options); - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); - } - const state = new ExecState(optionsNonNull, this.toolPath); - state.on('debug', (message) => { - this._debug(message); - }); - if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { - return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); - } - const fileName = this._getSpawnFileName(); - const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); - let stdbuffer = ''; - if (cp.stdout) { - cp.stdout.on('data', (data) => { - if (this.options.listeners && this.options.listeners.stdout) { - this.options.listeners.stdout(data); - } - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(data); - } - stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { - if (this.options.listeners && this.options.listeners.stdline) { - this.options.listeners.stdline(line); - } - }); - }); - } - let errbuffer = ''; - if (cp.stderr) { - cp.stderr.on('data', (data) => { - state.processStderr = true; - if (this.options.listeners && this.options.listeners.stderr) { - this.options.listeners.stderr(data); - } - if (!optionsNonNull.silent && - optionsNonNull.errStream && - optionsNonNull.outStream) { - const s = optionsNonNull.failOnStdErr - ? optionsNonNull.errStream - : optionsNonNull.outStream; - s.write(data); - } - errbuffer = this._processLineBuffer(data, errbuffer, (line) => { - if (this.options.listeners && this.options.listeners.errline) { - this.options.listeners.errline(line); - } - }); - }); - } - cp.on('error', (err) => { - state.processError = err.message; - state.processExited = true; - state.processClosed = true; - state.CheckComplete(); - }); - cp.on('exit', (code) => { - state.processExitCode = code; - state.processExited = true; - this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); - state.CheckComplete(); - }); - cp.on('close', (code) => { - state.processExitCode = code; - state.processExited = true; - state.processClosed = true; - this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); - state.CheckComplete(); - }); - state.on('done', (error, exitCode) => { - if (stdbuffer.length > 0) { - this.emit('stdline', stdbuffer); - } - if (errbuffer.length > 0) { - this.emit('errline', errbuffer); - } - cp.removeAllListeners(); - if (error) { - reject(error); - } - else { - resolve(exitCode); - } - }); - if (this.options.input) { - if (!cp.stdin) { - throw new Error('child process missing stdin'); - } - cp.stdin.end(this.options.input); - } - })); - }); - } -} -exports.ToolRunner = ToolRunner; -/** - * Convert an arg string to an array of args. Handles escaping - * - * @param argString string of arguments - * @returns string[] array of arguments - */ -function argStringToArray(argString) { - const args = []; - let inQuotes = false; - let escaped = false; - let arg = ''; - function append(c) { - // we only escape double quotes. - if (escaped && c !== '"') { - arg += '\\'; - } - arg += c; - escaped = false; - } - for (let i = 0; i < argString.length; i++) { - const c = argString.charAt(i); - if (c === '"') { - if (!escaped) { - inQuotes = !inQuotes; - } - else { - append(c); - } - continue; - } - if (c === '\\' && escaped) { - append(c); - continue; - } - if (c === '\\' && inQuotes) { - escaped = true; - continue; - } - if (c === ' ' && !inQuotes) { - if (arg.length > 0) { - args.push(arg); - arg = ''; - } - continue; - } - append(c); - } - if (arg.length > 0) { - args.push(arg.trim()); - } - return args; -} -exports.argStringToArray = argStringToArray; -class ExecState extends events.EventEmitter { - constructor(options, toolPath) { - super(); - this.processClosed = false; // tracks whether the process has exited and stdio is closed - this.processError = ''; - this.processExitCode = 0; - this.processExited = false; // tracks whether the process has exited - this.processStderr = false; // tracks whether stderr was written to - this.delay = 10000; // 10 seconds - this.done = false; - this.timeout = null; - if (!toolPath) { - throw new Error('toolPath must not be empty'); - } - this.options = options; - this.toolPath = toolPath; - if (options.delay) { - this.delay = options.delay; - } - } - CheckComplete() { - if (this.done) { - return; - } - if (this.processClosed) { - this._setResult(); - } - else if (this.processExited) { - this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); - } - } - _debug(message) { - this.emit('debug', message); - } - _setResult() { - // determine whether there is an error - let error; - if (this.processExited) { - if (this.processError) { - error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); - } - else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { - error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); - } - else if (this.processStderr && this.options.failOnStdErr) { - error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); - } - } - // clear the timeout - if (this.timeout) { - clearTimeout(this.timeout); - this.timeout = null; - } - this.done = true; - this.emit('done', error, this.processExitCode); - } - static HandleTimeout(state) { - if (state.done) { - return; - } - if (!state.processClosed && state.processExited) { - const message = `The STDIO streams did not close within ${state.delay / - 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; - state._debug(message); - } - state._setResult(); - } -} -//# sourceMappingURL=toolrunner.js.map - -/***/ }), - -/***/ 362: -/***/ (function(__unused_webpack_module, exports) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; -class BasicCredentialHandler { - constructor(username, password) { - this.username = username; - this.password = password; - } - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } -} -exports.BasicCredentialHandler = BasicCredentialHandler; -class BearerCredentialHandler { - constructor(token) { - this.token = token; - } - // currently implements pre-authorization - // TODO: support preAuth = false where it hooks on 401 - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Bearer ${this.token}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } -} -exports.BearerCredentialHandler = BearerCredentialHandler; -class PersonalAccessTokenCredentialHandler { - constructor(token) { - this.token = token; - } - // currently implements pre-authorization - // TODO: support preAuth = false where it hooks on 401 - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } -} -exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; -//# sourceMappingURL=auth.js.map - -/***/ }), - -/***/ 882: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -/* eslint-disable @typescript-eslint/no-explicit-any */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; -const http = __importStar(__nccwpck_require__(685)); -const https = __importStar(__nccwpck_require__(687)); -const pm = __importStar(__nccwpck_require__(668)); -const tunnel = __importStar(__nccwpck_require__(457)); -var HttpCodes; -(function (HttpCodes) { - HttpCodes[HttpCodes["OK"] = 200] = "OK"; - HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; - HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; - HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; - HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; - HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; - HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; - HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; - HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; - HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; - HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; - HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; - HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; - HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; - HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; - HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; - HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; - HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; - HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; - HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; - HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; - HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; - HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; - HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; - HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; - HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; - HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; -})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); -var Headers; -(function (Headers) { - Headers["Accept"] = "accept"; - Headers["ContentType"] = "content-type"; -})(Headers = exports.Headers || (exports.Headers = {})); -var MediaTypes; -(function (MediaTypes) { - MediaTypes["ApplicationJson"] = "application/json"; -})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); -/** - * Returns the proxy URL, depending upon the supplied url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ -function getProxyUrl(serverUrl) { - const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); - return proxyUrl ? proxyUrl.href : ''; -} -exports.getProxyUrl = getProxyUrl; -const HttpRedirectCodes = [ - HttpCodes.MovedPermanently, - HttpCodes.ResourceMoved, - HttpCodes.SeeOther, - HttpCodes.TemporaryRedirect, - HttpCodes.PermanentRedirect -]; -const HttpResponseRetryCodes = [ - HttpCodes.BadGateway, - HttpCodes.ServiceUnavailable, - HttpCodes.GatewayTimeout -]; -const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; -const ExponentialBackoffCeiling = 10; -const ExponentialBackoffTimeSlice = 5; -class HttpClientError extends Error { - constructor(message, statusCode) { - super(message); - this.name = 'HttpClientError'; - this.statusCode = statusCode; - Object.setPrototypeOf(this, HttpClientError.prototype); - } -} -exports.HttpClientError = HttpClientError; -class HttpClientResponse { - constructor(message) { - this.message = message; - } - readBody() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { - let output = Buffer.alloc(0); - this.message.on('data', (chunk) => { - output = Buffer.concat([output, chunk]); - }); - this.message.on('end', () => { - resolve(output.toString()); - }); - })); - }); - } -} -exports.HttpClientResponse = HttpClientResponse; -function isHttps(requestUrl) { - const parsedUrl = new URL(requestUrl); - return parsedUrl.protocol === 'https:'; -} -exports.isHttps = isHttps; -class HttpClient { - constructor(userAgent, handlers, requestOptions) { - this._ignoreSslError = false; - this._allowRedirects = true; - this._allowRedirectDowngrade = false; - this._maxRedirects = 50; - this._allowRetries = false; - this._maxRetries = 1; - this._keepAlive = false; - this._disposed = false; - this.userAgent = userAgent; - this.handlers = handlers || []; - this.requestOptions = requestOptions; - if (requestOptions) { - if (requestOptions.ignoreSslError != null) { - this._ignoreSslError = requestOptions.ignoreSslError; - } - this._socketTimeout = requestOptions.socketTimeout; - if (requestOptions.allowRedirects != null) { - this._allowRedirects = requestOptions.allowRedirects; - } - if (requestOptions.allowRedirectDowngrade != null) { - this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; - } - if (requestOptions.maxRedirects != null) { - this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); - } - if (requestOptions.keepAlive != null) { - this._keepAlive = requestOptions.keepAlive; - } - if (requestOptions.allowRetries != null) { - this._allowRetries = requestOptions.allowRetries; - } - if (requestOptions.maxRetries != null) { - this._maxRetries = requestOptions.maxRetries; - } - } - } - options(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); - }); - } - get(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('GET', requestUrl, null, additionalHeaders || {}); - }); - } - del(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('DELETE', requestUrl, null, additionalHeaders || {}); - }); - } - post(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('POST', requestUrl, data, additionalHeaders || {}); - }); - } - patch(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('PATCH', requestUrl, data, additionalHeaders || {}); - }); - } - put(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('PUT', requestUrl, data, additionalHeaders || {}); - }); - } - head(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('HEAD', requestUrl, null, additionalHeaders || {}); - }); - } - sendStream(verb, requestUrl, stream, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request(verb, requestUrl, stream, additionalHeaders); - }); - } - /** - * Gets a typed object from an endpoint - * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise - */ - getJson(requestUrl, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - const res = yield this.get(requestUrl, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - postJson(requestUrl, obj, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - const res = yield this.post(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - putJson(requestUrl, obj, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - const res = yield this.put(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - patchJson(requestUrl, obj, additionalHeaders = {}) { - return __awaiter(this, void 0, void 0, function* () { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - const res = yield this.patch(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - /** - * Makes a raw http request. - * All other methods such as get, post, patch, and request ultimately call this. - * Prefer get, del, post and patch - */ - request(verb, requestUrl, data, headers) { - return __awaiter(this, void 0, void 0, function* () { - if (this._disposed) { - throw new Error('Client has already been disposed.'); - } - const parsedUrl = new URL(requestUrl); - let info = this._prepareRequest(verb, parsedUrl, headers); - // Only perform retries on reads since writes may not be idempotent. - const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) - ? this._maxRetries + 1 - : 1; - let numTries = 0; - let response; - do { - response = yield this.requestRaw(info, data); - // Check if it's an authentication challenge - if (response && - response.message && - response.message.statusCode === HttpCodes.Unauthorized) { - let authenticationHandler; - for (const handler of this.handlers) { - if (handler.canHandleAuthentication(response)) { - authenticationHandler = handler; - break; - } - } - if (authenticationHandler) { - return authenticationHandler.handleAuthentication(this, info, data); - } - else { - // We have received an unauthorized response but have no handlers to handle it. - // Let the response return to the caller. - return response; - } - } - let redirectsRemaining = this._maxRedirects; - while (response.message.statusCode && - HttpRedirectCodes.includes(response.message.statusCode) && - this._allowRedirects && - redirectsRemaining > 0) { - const redirectUrl = response.message.headers['location']; - if (!redirectUrl) { - // if there's no location to redirect to, we won't - break; - } - const parsedRedirectUrl = new URL(redirectUrl); - if (parsedUrl.protocol === 'https:' && - parsedUrl.protocol !== parsedRedirectUrl.protocol && - !this._allowRedirectDowngrade) { - throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); - } - // we need to finish reading the response before reassigning response - // which will leak the open socket. - yield response.readBody(); - // strip authorization header if redirected to a different hostname - if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { - for (const header in headers) { - // header names are case insensitive - if (header.toLowerCase() === 'authorization') { - delete headers[header]; - } - } - } - // let's make the request with the new redirectUrl - info = this._prepareRequest(verb, parsedRedirectUrl, headers); - response = yield this.requestRaw(info, data); - redirectsRemaining--; - } - if (!response.message.statusCode || - !HttpResponseRetryCodes.includes(response.message.statusCode)) { - // If not a retry code, return immediately instead of retrying - return response; - } - numTries += 1; - if (numTries < maxTries) { - yield response.readBody(); - yield this._performExponentialBackoff(numTries); - } - } while (numTries < maxTries); - return response; - }); - } - /** - * Needs to be called if keepAlive is set to true in request options. - */ - dispose() { - if (this._agent) { - this._agent.destroy(); - } - this._disposed = true; - } - /** - * Raw request. - * @param info - * @param data - */ - requestRaw(info, data) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - function callbackForResult(err, res) { - if (err) { - reject(err); - } - else if (!res) { - // If `err` is not passed, then `res` must be passed. - reject(new Error('Unknown error')); - } - else { - resolve(res); - } - } - this.requestRawWithCallback(info, data, callbackForResult); - }); - }); - } - /** - * Raw request with callback. - * @param info - * @param data - * @param onResult - */ - requestRawWithCallback(info, data, onResult) { - if (typeof data === 'string') { - if (!info.options.headers) { - info.options.headers = {}; - } - info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); - } - let callbackCalled = false; - function handleResult(err, res) { - if (!callbackCalled) { - callbackCalled = true; - onResult(err, res); - } - } - const req = info.httpModule.request(info.options, (msg) => { - const res = new HttpClientResponse(msg); - handleResult(undefined, res); - }); - let socket; - req.on('socket', sock => { - socket = sock; - }); - // If we ever get disconnected, we want the socket to timeout eventually - req.setTimeout(this._socketTimeout || 3 * 60000, () => { - if (socket) { - socket.end(); - } - handleResult(new Error(`Request timeout: ${info.options.path}`)); - }); - req.on('error', function (err) { - // err has statusCode property - // res should have headers - handleResult(err); - }); - if (data && typeof data === 'string') { - req.write(data, 'utf8'); - } - if (data && typeof data !== 'string') { - data.on('close', function () { - req.end(); - }); - data.pipe(req); - } - else { - req.end(); - } - } - /** - * Gets an http agent. This function is useful when you need an http agent that handles - * routing through a proxy server - depending upon the url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ - getAgent(serverUrl) { - const parsedUrl = new URL(serverUrl); - return this._getAgent(parsedUrl); - } - _prepareRequest(method, requestUrl, headers) { - const info = {}; - info.parsedUrl = requestUrl; - const usingSsl = info.parsedUrl.protocol === 'https:'; - info.httpModule = usingSsl ? https : http; - const defaultPort = usingSsl ? 443 : 80; - info.options = {}; - info.options.host = info.parsedUrl.hostname; - info.options.port = info.parsedUrl.port - ? parseInt(info.parsedUrl.port) - : defaultPort; - info.options.path = - (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); - info.options.method = method; - info.options.headers = this._mergeHeaders(headers); - if (this.userAgent != null) { - info.options.headers['user-agent'] = this.userAgent; - } - info.options.agent = this._getAgent(info.parsedUrl); - // gives handlers an opportunity to participate - if (this.handlers) { - for (const handler of this.handlers) { - handler.prepareRequest(info.options); - } - } - return info; - } - _mergeHeaders(headers) { - if (this.requestOptions && this.requestOptions.headers) { - return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); - } - return lowercaseKeys(headers || {}); - } - _getExistingOrDefaultHeader(additionalHeaders, header, _default) { - let clientHeader; - if (this.requestOptions && this.requestOptions.headers) { - clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; - } - return additionalHeaders[header] || clientHeader || _default; - } - _getAgent(parsedUrl) { - let agent; - const proxyUrl = pm.getProxyUrl(parsedUrl); - const useProxy = proxyUrl && proxyUrl.hostname; - if (this._keepAlive && useProxy) { - agent = this._proxyAgent; - } - if (this._keepAlive && !useProxy) { - agent = this._agent; - } - // if agent is already assigned use that agent. - if (agent) { - return agent; - } - const usingSsl = parsedUrl.protocol === 'https:'; - let maxSockets = 100; - if (this.requestOptions) { - maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; - } - // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. - if (proxyUrl && proxyUrl.hostname) { - const agentOptions = { - maxSockets, - keepAlive: this._keepAlive, - proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { - proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` - })), { host: proxyUrl.hostname, port: proxyUrl.port }) - }; - let tunnelAgent; - const overHttps = proxyUrl.protocol === 'https:'; - if (usingSsl) { - tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; - } - else { - tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; - } - agent = tunnelAgent(agentOptions); - this._proxyAgent = agent; - } - // if reusing agent across request and tunneling agent isn't assigned create a new agent - if (this._keepAlive && !agent) { - const options = { keepAlive: this._keepAlive, maxSockets }; - agent = usingSsl ? new https.Agent(options) : new http.Agent(options); - this._agent = agent; - } - // if not using private agent and tunnel agent isn't setup then use global agent - if (!agent) { - agent = usingSsl ? https.globalAgent : http.globalAgent; - } - if (usingSsl && this._ignoreSslError) { - // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process - // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options - // we have to cast it to any and change it directly - agent.options = Object.assign(agent.options || {}, { - rejectUnauthorized: false - }); - } - return agent; - } - _performExponentialBackoff(retryNumber) { - return __awaiter(this, void 0, void 0, function* () { - retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); - const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); - return new Promise(resolve => setTimeout(() => resolve(), ms)); - }); - } - _processResponse(res, options) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { - const statusCode = res.message.statusCode || 0; - const response = { - statusCode, - result: null, - headers: {} - }; - // not found leads to null obj returned - if (statusCode === HttpCodes.NotFound) { - resolve(response); - } - // get the result from the body - function dateTimeDeserializer(key, value) { - if (typeof value === 'string') { - const a = new Date(value); - if (!isNaN(a.valueOf())) { - return a; - } - } - return value; - } - let obj; - let contents; - try { - contents = yield res.readBody(); - if (contents && contents.length > 0) { - if (options && options.deserializeDates) { - obj = JSON.parse(contents, dateTimeDeserializer); - } - else { - obj = JSON.parse(contents); - } - response.result = obj; - } - response.headers = res.message.headers; - } - catch (err) { - // Invalid resource (contents not json); leaving result obj null - } - // note that 3xx redirects are handled by the http layer. - if (statusCode > 299) { - let msg; - // if exception/error in body, attempt to get better error - if (obj && obj.message) { - msg = obj.message; - } - else if (contents && contents.length > 0) { - // it may be the case that the exception is in the body message as string - msg = contents; - } - else { - msg = `Failed request: (${statusCode})`; - } - const err = new HttpClientError(msg, statusCode); - err.result = response.result; - reject(err); - } - else { - resolve(response); - } - })); - }); - } -} -exports.HttpClient = HttpClient; -const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); -//# sourceMappingURL=index.js.map - -/***/ }), - -/***/ 668: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.checkBypass = exports.getProxyUrl = void 0; -function getProxyUrl(reqUrl) { - const usingSsl = reqUrl.protocol === 'https:'; - if (checkBypass(reqUrl)) { - return undefined; - } - const proxyVar = (() => { - if (usingSsl) { - return process.env['https_proxy'] || process.env['HTTPS_PROXY']; - } - else { - return process.env['http_proxy'] || process.env['HTTP_PROXY']; - } - })(); - if (proxyVar) { - return new URL(proxyVar); - } - else { - return undefined; - } -} -exports.getProxyUrl = getProxyUrl; -function checkBypass(reqUrl) { - if (!reqUrl.hostname) { - return false; - } - const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; - if (!noProxy) { - return false; - } - // Determine the request port - let reqPort; - if (reqUrl.port) { - reqPort = Number(reqUrl.port); - } - else if (reqUrl.protocol === 'http:') { - reqPort = 80; - } - else if (reqUrl.protocol === 'https:') { - reqPort = 443; - } - // Format the request hostname and hostname with port - const upperReqHosts = [reqUrl.hostname.toUpperCase()]; - if (typeof reqPort === 'number') { - upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); - } - // Compare request host against noproxy - for (const upperNoProxyItem of noProxy - .split(',') - .map(x => x.trim().toUpperCase()) - .filter(x => x)) { - if (upperReqHosts.some(x => x === upperNoProxyItem)) { - return true; - } - } - return false; -} -exports.checkBypass = checkBypass; -//# sourceMappingURL=proxy.js.map - -/***/ }), - -/***/ 152: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var _a; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rename = exports.readlink = exports.readdir = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; -const fs = __importStar(__nccwpck_require__(147)); -const path = __importStar(__nccwpck_require__(17)); -_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; -exports.IS_WINDOWS = process.platform === 'win32'; -function exists(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - try { - yield exports.stat(fsPath); - } - catch (err) { - if (err.code === 'ENOENT') { - return false; - } - throw err; - } - return true; - }); -} -exports.exists = exists; -function isDirectory(fsPath, useStat = false) { - return __awaiter(this, void 0, void 0, function* () { - const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); - return stats.isDirectory(); - }); -} -exports.isDirectory = isDirectory; -/** - * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: - * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). - */ -function isRooted(p) { - p = normalizeSeparators(p); - if (!p) { - throw new Error('isRooted() parameter "p" cannot be empty'); - } - if (exports.IS_WINDOWS) { - return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello - ); // e.g. C: or C:\hello - } - return p.startsWith('/'); -} -exports.isRooted = isRooted; -/** - * Best effort attempt to determine whether a file exists and is executable. - * @param filePath file path to check - * @param extensions additional file extensions to try - * @return if file exists and is executable, returns the file path. otherwise empty string. - */ -function tryGetExecutablePath(filePath, extensions) { - return __awaiter(this, void 0, void 0, function* () { - let stats = undefined; - try { - // test file exists - stats = yield exports.stat(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // on Windows, test for valid extension - const upperExt = path.extname(filePath).toUpperCase(); - if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { - return filePath; - } - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - // try each extension - const originalFilePath = filePath; - for (const extension of extensions) { - filePath = originalFilePath + extension; - stats = undefined; - try { - stats = yield exports.stat(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // preserve the case of the actual file (since an extension was appended) - try { - const directory = path.dirname(filePath); - const upperName = path.basename(filePath).toUpperCase(); - for (const actualName of yield exports.readdir(directory)) { - if (upperName === actualName.toUpperCase()) { - filePath = path.join(directory, actualName); - break; - } - } - } - catch (err) { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); - } - return filePath; - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - } - return ''; - }); -} -exports.tryGetExecutablePath = tryGetExecutablePath; -function normalizeSeparators(p) { - p = p || ''; - if (exports.IS_WINDOWS) { - // convert slashes on Windows - p = p.replace(/\//g, '\\'); - // remove redundant slashes - return p.replace(/\\\\+/g, '\\'); - } - // remove redundant slashes - return p.replace(/\/\/+/g, '/'); -} -// on Mac/Linux, test the execute bit -// R W X R W X R W X -// 256 128 64 32 16 8 4 2 1 -function isUnixExecutable(stats) { - return ((stats.mode & 1) > 0 || - ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || - ((stats.mode & 64) > 0 && stats.uid === process.getuid())); -} -// Get the path of cmd.exe in windows -function getCmdPath() { - var _a; - return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; -} -exports.getCmdPath = getCmdPath; -//# sourceMappingURL=io-util.js.map - -/***/ }), - -/***/ 59: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; -const assert_1 = __nccwpck_require__(491); -const childProcess = __importStar(__nccwpck_require__(81)); -const path = __importStar(__nccwpck_require__(17)); -const util_1 = __nccwpck_require__(837); -const ioUtil = __importStar(__nccwpck_require__(152)); -const exec = util_1.promisify(childProcess.exec); -const execFile = util_1.promisify(childProcess.execFile); -/** - * Copies a file or folder. - * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js - * - * @param source source path - * @param dest destination path - * @param options optional. See CopyOptions. - */ -function cp(source, dest, options = {}) { - return __awaiter(this, void 0, void 0, function* () { - const { force, recursive, copySourceDirectory } = readCopyOptions(options); - const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; - // Dest is an existing file, but not forcing - if (destStat && destStat.isFile() && !force) { - return; - } - // If dest is an existing directory, should copy inside. - const newDest = destStat && destStat.isDirectory() && copySourceDirectory - ? path.join(dest, path.basename(source)) - : dest; - if (!(yield ioUtil.exists(source))) { - throw new Error(`no such file or directory: ${source}`); - } - const sourceStat = yield ioUtil.stat(source); - if (sourceStat.isDirectory()) { - if (!recursive) { - throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); - } - else { - yield cpDirRecursive(source, newDest, 0, force); - } - } - else { - if (path.relative(source, newDest) === '') { - // a file cannot be copied to itself - throw new Error(`'${newDest}' and '${source}' are the same file`); - } - yield copyFile(source, newDest, force); - } - }); -} -exports.cp = cp; -/** - * Moves a path. - * - * @param source source path - * @param dest destination path - * @param options optional. See MoveOptions. - */ -function mv(source, dest, options = {}) { - return __awaiter(this, void 0, void 0, function* () { - if (yield ioUtil.exists(dest)) { - let destExists = true; - if (yield ioUtil.isDirectory(dest)) { - // If dest is directory copy src into dest - dest = path.join(dest, path.basename(source)); - destExists = yield ioUtil.exists(dest); - } - if (destExists) { - if (options.force == null || options.force) { - yield rmRF(dest); - } - else { - throw new Error('Destination already exists'); - } - } - } - yield mkdirP(path.dirname(dest)); - yield ioUtil.rename(source, dest); - }); -} -exports.mv = mv; -/** - * Remove a path recursively with force - * - * @param inputPath path to remove - */ -function rmRF(inputPath) { - return __awaiter(this, void 0, void 0, function* () { - if (ioUtil.IS_WINDOWS) { - // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another - // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del. - // Check for invalid characters - // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file - if (/[*"<>|]/.test(inputPath)) { - throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); - } - try { - const cmdPath = ioUtil.getCmdPath(); - if (yield ioUtil.isDirectory(inputPath, true)) { - yield exec(`${cmdPath} /s /c "rd /s /q "%inputPath%""`, { - env: { inputPath } - }); - } - else { - yield exec(`${cmdPath} /s /c "del /f /a "%inputPath%""`, { - env: { inputPath } - }); - } - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; - } - // Shelling out fails to remove a symlink folder with missing source, this unlink catches that - try { - yield ioUtil.unlink(inputPath); - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; - } - } - else { - let isDir = false; - try { - isDir = yield ioUtil.isDirectory(inputPath); - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; - return; - } - if (isDir) { - yield execFile(`rm`, [`-rf`, `${inputPath}`]); - } - else { - yield ioUtil.unlink(inputPath); - } - } - }); -} -exports.rmRF = rmRF; -/** - * Make a directory. Creates the full path with folders in between - * Will throw if it fails - * - * @param fsPath path to create - * @returns Promise - */ -function mkdirP(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - assert_1.ok(fsPath, 'a path argument must be provided'); - yield ioUtil.mkdir(fsPath, { recursive: true }); - }); -} -exports.mkdirP = mkdirP; -/** - * Returns path of a tool had the tool actually been invoked. Resolves via paths. - * If you check and the tool does not exist, it will throw. - * - * @param tool name of the tool - * @param check whether to check if tool exists - * @returns Promise path to tool - */ -function which(tool, check) { - return __awaiter(this, void 0, void 0, function* () { - if (!tool) { - throw new Error("parameter 'tool' is required"); - } - // recursive when check=true - if (check) { - const result = yield which(tool, false); - if (!result) { - if (ioUtil.IS_WINDOWS) { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); - } - else { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); - } - } - return result; - } - const matches = yield findInPath(tool); - if (matches && matches.length > 0) { - return matches[0]; - } - return ''; - }); -} -exports.which = which; -/** - * Returns a list of all occurrences of the given tool on the system path. - * - * @returns Promise the paths of the tool - */ -function findInPath(tool) { - return __awaiter(this, void 0, void 0, function* () { - if (!tool) { - throw new Error("parameter 'tool' is required"); - } - // build the list of extensions to try - const extensions = []; - if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { - for (const extension of process.env['PATHEXT'].split(path.delimiter)) { - if (extension) { - extensions.push(extension); - } - } - } - // if it's rooted, return it if exists. otherwise return empty. - if (ioUtil.isRooted(tool)) { - const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); - if (filePath) { - return [filePath]; - } - return []; - } - // if any path separators, return empty - if (tool.includes(path.sep)) { - return []; - } - // build the list of directories - // - // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, - // it feels like we should not do this. Checking the current directory seems like more of a use - // case of a shell, and the which() function exposed by the toolkit should strive for consistency - // across platforms. - const directories = []; - if (process.env.PATH) { - for (const p of process.env.PATH.split(path.delimiter)) { - if (p) { - directories.push(p); - } - } - } - // find all matches - const matches = []; - for (const directory of directories) { - const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); - if (filePath) { - matches.push(filePath); - } - } - return matches; - }); -} -exports.findInPath = findInPath; -function readCopyOptions(options) { - const force = options.force == null ? true : options.force; - const recursive = Boolean(options.recursive); - const copySourceDirectory = options.copySourceDirectory == null - ? true - : Boolean(options.copySourceDirectory); - return { force, recursive, copySourceDirectory }; -} -function cpDirRecursive(sourceDir, destDir, currentDepth, force) { - return __awaiter(this, void 0, void 0, function* () { - // Ensure there is not a run away recursive copy - if (currentDepth >= 255) - return; - currentDepth++; - yield mkdirP(destDir); - const files = yield ioUtil.readdir(sourceDir); - for (const fileName of files) { - const srcFile = `${sourceDir}/${fileName}`; - const destFile = `${destDir}/${fileName}`; - const srcFileStat = yield ioUtil.lstat(srcFile); - if (srcFileStat.isDirectory()) { - // Recurse - yield cpDirRecursive(srcFile, destFile, currentDepth, force); - } - else { - yield copyFile(srcFile, destFile, force); - } - } - // Change the mode for the newly created directory - yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); - }); -} -// Buffered file copy -function copyFile(srcFile, destFile, force) { - return __awaiter(this, void 0, void 0, function* () { - if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { - // unlink/re-link it - try { - yield ioUtil.lstat(destFile); - yield ioUtil.unlink(destFile); - } - catch (e) { - // Try to override file permission - if (e.code === 'EPERM') { - yield ioUtil.chmod(destFile, '0666'); - yield ioUtil.unlink(destFile); - } - // other errors = it doesn't exist, no work to do - } - // Copy over symlink - const symlinkFull = yield ioUtil.readlink(srcFile); - yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); - } - else if (!(yield ioUtil.exists(destFile)) || force) { - yield ioUtil.copyFile(srcFile, destFile); - } - }); -} -//# sourceMappingURL=io.js.map - -/***/ }), - -/***/ 457: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -module.exports = __nccwpck_require__(531); - - -/***/ }), - -/***/ 531: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -var net = __nccwpck_require__(808); -var tls = __nccwpck_require__(404); -var http = __nccwpck_require__(685); -var https = __nccwpck_require__(687); -var events = __nccwpck_require__(361); -var assert = __nccwpck_require__(491); -var util = __nccwpck_require__(837); - - -exports.httpOverHttp = httpOverHttp; -exports.httpsOverHttp = httpsOverHttp; -exports.httpOverHttps = httpOverHttps; -exports.httpsOverHttps = httpsOverHttps; - - -function httpOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - return agent; -} - -function httpsOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} - -function httpOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - return agent; -} - -function httpsOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} - - -function TunnelingAgent(options) { - var self = this; - self.options = options || {}; - self.proxyOptions = self.options.proxy || {}; - self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; - self.requests = []; - self.sockets = []; - - self.on('free', function onFree(socket, host, port, localAddress) { - var options = toOptions(host, port, localAddress); - for (var i = 0, len = self.requests.length; i < len; ++i) { - var pending = self.requests[i]; - if (pending.host === options.host && pending.port === options.port) { - // Detect the request to connect same origin server, - // reuse the connection. - self.requests.splice(i, 1); - pending.request.onSocket(socket); - return; - } - } - socket.destroy(); - self.removeSocket(socket); - }); -} -util.inherits(TunnelingAgent, events.EventEmitter); - -TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { - var self = this; - var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); - - if (self.sockets.length >= this.maxSockets) { - // We are over limit so we'll add it to the queue. - self.requests.push(options); - return; - } - - // If we are under maxSockets create a new one. - self.createSocket(options, function(socket) { - socket.on('free', onFree); - socket.on('close', onCloseOrRemove); - socket.on('agentRemove', onCloseOrRemove); - req.onSocket(socket); - - function onFree() { - self.emit('free', socket, options); - } - - function onCloseOrRemove(err) { - self.removeSocket(socket); - socket.removeListener('free', onFree); - socket.removeListener('close', onCloseOrRemove); - socket.removeListener('agentRemove', onCloseOrRemove); - } - }); -}; - -TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { - var self = this; - var placeholder = {}; - self.sockets.push(placeholder); - - var connectOptions = mergeOptions({}, self.proxyOptions, { - method: 'CONNECT', - path: options.host + ':' + options.port, - agent: false, - headers: { - host: options.host + ':' + options.port - } - }); - if (options.localAddress) { - connectOptions.localAddress = options.localAddress; - } - if (connectOptions.proxyAuth) { - connectOptions.headers = connectOptions.headers || {}; - connectOptions.headers['Proxy-Authorization'] = 'Basic ' + - new Buffer(connectOptions.proxyAuth).toString('base64'); - } - - debug('making CONNECT request'); - var connectReq = self.request(connectOptions); - connectReq.useChunkedEncodingByDefault = false; // for v0.6 - connectReq.once('response', onResponse); // for v0.6 - connectReq.once('upgrade', onUpgrade); // for v0.6 - connectReq.once('connect', onConnect); // for v0.7 or later - connectReq.once('error', onError); - connectReq.end(); - - function onResponse(res) { - // Very hacky. This is necessary to avoid http-parser leaks. - res.upgrade = true; - } - - function onUpgrade(res, socket, head) { - // Hacky. - process.nextTick(function() { - onConnect(res, socket, head); - }); - } - - function onConnect(res, socket, head) { - connectReq.removeAllListeners(); - socket.removeAllListeners(); - - if (res.statusCode !== 200) { - debug('tunneling socket could not be established, statusCode=%d', - res.statusCode); - socket.destroy(); - var error = new Error('tunneling socket could not be established, ' + - 'statusCode=' + res.statusCode); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - if (head.length > 0) { - debug('got illegal response body from proxy'); - socket.destroy(); - var error = new Error('got illegal response body from proxy'); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - debug('tunneling connection has established'); - self.sockets[self.sockets.indexOf(placeholder)] = socket; - return cb(socket); - } - - function onError(cause) { - connectReq.removeAllListeners(); - - debug('tunneling socket could not be established, cause=%s\n', - cause.message, cause.stack); - var error = new Error('tunneling socket could not be established, ' + - 'cause=' + cause.message); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - } -}; - -TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { - var pos = this.sockets.indexOf(socket) - if (pos === -1) { - return; - } - this.sockets.splice(pos, 1); - - var pending = this.requests.shift(); - if (pending) { - // If we have pending requests and a socket gets closed a new one - // needs to be created to take over in the pool for the one that closed. - this.createSocket(pending, function(socket) { - pending.request.onSocket(socket); - }); - } -}; - -function createSecureSocket(options, cb) { - var self = this; - TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { - var hostHeader = options.request.getHeader('host'); - var tlsOptions = mergeOptions({}, self.options, { - socket: socket, - servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host - }); - - // 0 is dummy port for v0.6 - var secureSocket = tls.connect(0, tlsOptions); - self.sockets[self.sockets.indexOf(socket)] = secureSocket; - cb(secureSocket); - }); -} - - -function toOptions(host, port, localAddress) { - if (typeof host === 'string') { // since v0.10 - return { - host: host, - port: port, - localAddress: localAddress - }; - } - return host; // for v0.11 or later -} - -function mergeOptions(target) { - for (var i = 1, len = arguments.length; i < len; ++i) { - var overrides = arguments[i]; - if (typeof overrides === 'object') { - var keys = Object.keys(overrides); - for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { - var k = keys[j]; - if (overrides[k] !== undefined) { - target[k] = overrides[k]; - } - } - } - } - return target; -} - - -var debug; -if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { - debug = function() { - var args = Array.prototype.slice.call(arguments); - if (typeof args[0] === 'string') { - args[0] = 'TUNNEL: ' + args[0]; - } else { - args.unshift('TUNNEL:'); - } - console.error.apply(console, args); - } -} else { - debug = function() {}; -} -exports.debug = debug; // for test - - -/***/ }), - -/***/ 503: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -Object.defineProperty(exports, "v1", ({ - enumerable: true, - get: function () { - return _v.default; - } -})); -Object.defineProperty(exports, "v3", ({ - enumerable: true, - get: function () { - return _v2.default; - } -})); -Object.defineProperty(exports, "v4", ({ - enumerable: true, - get: function () { - return _v3.default; - } -})); -Object.defineProperty(exports, "v5", ({ - enumerable: true, - get: function () { - return _v4.default; - } -})); -Object.defineProperty(exports, "NIL", ({ - enumerable: true, - get: function () { - return _nil.default; - } -})); -Object.defineProperty(exports, "version", ({ - enumerable: true, - get: function () { - return _version.default; - } -})); -Object.defineProperty(exports, "validate", ({ - enumerable: true, - get: function () { - return _validate.default; - } -})); -Object.defineProperty(exports, "stringify", ({ - enumerable: true, - get: function () { - return _stringify.default; - } -})); -Object.defineProperty(exports, "parse", ({ - enumerable: true, - get: function () { - return _parse.default; - } -})); - -var _v = _interopRequireDefault(__nccwpck_require__(42)); - -var _v2 = _interopRequireDefault(__nccwpck_require__(377)); - -var _v3 = _interopRequireDefault(__nccwpck_require__(452)); - -var _v4 = _interopRequireDefault(__nccwpck_require__(390)); - -var _nil = _interopRequireDefault(__nccwpck_require__(691)); - -var _version = _interopRequireDefault(__nccwpck_require__(430)); - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -var _parse = _interopRequireDefault(__nccwpck_require__(590)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/***/ }), - -/***/ 940: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function md5(bytes) { - if (Array.isArray(bytes)) { - bytes = Buffer.from(bytes); - } else if (typeof bytes === 'string') { - bytes = Buffer.from(bytes, 'utf8'); - } - - return _crypto.default.createHash('md5').update(bytes).digest(); -} - -var _default = md5; -exports["default"] = _default; - -/***/ }), - -/***/ 691: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; -var _default = '00000000-0000-0000-0000-000000000000'; -exports["default"] = _default; - -/***/ }), - -/***/ 590: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function parse(uuid) { - if (!(0, _validate.default)(uuid)) { - throw TypeError('Invalid UUID'); - } - - let v; - const arr = new Uint8Array(16); // Parse ########-....-....-....-............ - - arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; - arr[1] = v >>> 16 & 0xff; - arr[2] = v >>> 8 & 0xff; - arr[3] = v & 0xff; // Parse ........-####-....-....-............ - - arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; - arr[5] = v & 0xff; // Parse ........-....-####-....-............ - - arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; - arr[7] = v & 0xff; // Parse ........-....-....-####-............ - - arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; - arr[9] = v & 0xff; // Parse ........-....-....-....-############ - // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) - - arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; - arr[11] = v / 0x100000000 & 0xff; - arr[12] = v >>> 24 & 0xff; - arr[13] = v >>> 16 & 0xff; - arr[14] = v >>> 8 & 0xff; - arr[15] = v & 0xff; - return arr; -} - -var _default = parse; -exports["default"] = _default; - -/***/ }), - -/***/ 346: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; -var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; -exports["default"] = _default; - -/***/ }), - -/***/ 720: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = rng; - -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate - -let poolPtr = rnds8Pool.length; - -function rng() { - if (poolPtr > rnds8Pool.length - 16) { - _crypto.default.randomFillSync(rnds8Pool); - - poolPtr = 0; - } - - return rnds8Pool.slice(poolPtr, poolPtr += 16); -} - -/***/ }), - -/***/ 922: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function sha1(bytes) { - if (Array.isArray(bytes)) { - bytes = Buffer.from(bytes); - } else if (typeof bytes === 'string') { - bytes = Buffer.from(bytes, 'utf8'); - } - - return _crypto.default.createHash('sha1').update(bytes).digest(); -} - -var _default = sha1; -exports["default"] = _default; - -/***/ }), - -/***/ 636: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -const byteToHex = []; - -for (let i = 0; i < 256; ++i) { - byteToHex.push((i + 0x100).toString(16).substr(1)); -} - -function stringify(arr, offset = 0) { - // Note: Be careful editing this code! It's been tuned for performance - // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 - const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one - // of the following: - // - One or more input array values don't map to a hex octet (leading to - // "undefined" in the uuid) - // - Invalid input values for the RFC `version` or `variant` fields - - if (!(0, _validate.default)(uuid)) { - throw TypeError('Stringified UUID is invalid'); - } - - return uuid; -} - -var _default = stringify; -exports["default"] = _default; - -/***/ }), - -/***/ 42: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _rng = _interopRequireDefault(__nccwpck_require__(720)); - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html -let _nodeId; - -let _clockseq; // Previous uuid creation time - - -let _lastMSecs = 0; -let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details - -function v1(options, buf, offset) { - let i = buf && offset || 0; - const b = buf || new Array(16); - options = options || {}; - let node = options.node || _nodeId; - let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - - if (node == null || clockseq == null) { - const seedBytes = options.random || (options.rng || _rng.default)(); - - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; - } - - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; - } - } // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - - - let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - - let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) - - const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression - - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - - - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } // Per 4.2.1.2 Throw error if too many uuids are requested - - - if (nsecs >= 10000) { - throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - - msecs += 12219292800000; // `time_low` - - const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; // `time_mid` - - const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; // `time_high_and_version` - - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - - b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - - b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` - - b[i++] = clockseq & 0xff; // `node` - - for (let n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } - - return buf || (0, _stringify.default)(b); -} - -var _default = v1; -exports["default"] = _default; - -/***/ }), - -/***/ 377: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _v = _interopRequireDefault(__nccwpck_require__(852)); - -var _md = _interopRequireDefault(__nccwpck_require__(940)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const v3 = (0, _v.default)('v3', 0x30, _md.default); -var _default = v3; -exports["default"] = _default; - -/***/ }), - -/***/ 852: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = _default; -exports.URL = exports.DNS = void 0; - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -var _parse = _interopRequireDefault(__nccwpck_require__(590)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function stringToBytes(str) { - str = unescape(encodeURIComponent(str)); // UTF8 escape - - const bytes = []; - - for (let i = 0; i < str.length; ++i) { - bytes.push(str.charCodeAt(i)); - } - - return bytes; -} - -const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; -exports.DNS = DNS; -const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; -exports.URL = URL; - -function _default(name, version, hashfunc) { - function generateUUID(value, namespace, buf, offset) { - if (typeof value === 'string') { - value = stringToBytes(value); - } - - if (typeof namespace === 'string') { - namespace = (0, _parse.default)(namespace); - } - - if (namespace.length !== 16) { - throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); - } // Compute hash of namespace and value, Per 4.3 - // Future: Use spread syntax when supported on all platforms, e.g. `bytes = - // hashfunc([...namespace, ... value])` - - - let bytes = new Uint8Array(16 + value.length); - bytes.set(namespace); - bytes.set(value, namespace.length); - bytes = hashfunc(bytes); - bytes[6] = bytes[6] & 0x0f | version; - bytes[8] = bytes[8] & 0x3f | 0x80; - - if (buf) { - offset = offset || 0; - - for (let i = 0; i < 16; ++i) { - buf[offset + i] = bytes[i]; - } - - return buf; - } - - return (0, _stringify.default)(bytes); - } // Function#name is not settable on some platforms (#270) - - - try { - generateUUID.name = name; // eslint-disable-next-line no-empty - } catch (err) {} // For CommonJS default export support - - - generateUUID.DNS = DNS; - generateUUID.URL = URL; - return generateUUID; -} - -/***/ }), - -/***/ 452: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _rng = _interopRequireDefault(__nccwpck_require__(720)); - -var _stringify = _interopRequireDefault(__nccwpck_require__(636)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function v4(options, buf, offset) { - options = options || {}; - - const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - - - rnds[6] = rnds[6] & 0x0f | 0x40; - rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided - - if (buf) { - offset = offset || 0; - - for (let i = 0; i < 16; ++i) { - buf[offset + i] = rnds[i]; - } - - return buf; - } - - return (0, _stringify.default)(rnds); -} - -var _default = v4; -exports["default"] = _default; - -/***/ }), - -/***/ 390: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _v = _interopRequireDefault(__nccwpck_require__(852)); - -var _sha = _interopRequireDefault(__nccwpck_require__(922)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const v5 = (0, _v.default)('v5', 0x50, _sha.default); -var _default = v5; -exports["default"] = _default; - -/***/ }), - -/***/ 911: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _regex = _interopRequireDefault(__nccwpck_require__(346)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function validate(uuid) { - return typeof uuid === 'string' && _regex.default.test(uuid); -} - -var _default = validate; -exports["default"] = _default; - -/***/ }), - -/***/ 430: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports["default"] = void 0; - -var _validate = _interopRequireDefault(__nccwpck_require__(911)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function version(uuid) { - if (!(0, _validate.default)(uuid)) { - throw TypeError('Invalid UUID'); - } - - return parseInt(uuid.substr(14, 1), 16); -} - -var _default = version; -exports["default"] = _default; - -/***/ }), - -/***/ 491: -/***/ ((module) => { - -"use strict"; -module.exports = require("assert"); - -/***/ }), - -/***/ 81: -/***/ ((module) => { - -"use strict"; -module.exports = require("child_process"); - -/***/ }), - -/***/ 113: -/***/ ((module) => { - -"use strict"; -module.exports = require("crypto"); - -/***/ }), - -/***/ 361: -/***/ ((module) => { - -"use strict"; -module.exports = require("events"); - -/***/ }), - -/***/ 147: -/***/ ((module) => { - -"use strict"; -module.exports = require("fs"); - -/***/ }), - -/***/ 685: -/***/ ((module) => { - -"use strict"; -module.exports = require("http"); - -/***/ }), - -/***/ 687: -/***/ ((module) => { - -"use strict"; -module.exports = require("https"); - -/***/ }), - -/***/ 808: -/***/ ((module) => { - -"use strict"; -module.exports = require("net"); - -/***/ }), - -/***/ 37: -/***/ ((module) => { - -"use strict"; -module.exports = require("os"); - -/***/ }), - -/***/ 17: -/***/ ((module) => { - -"use strict"; -module.exports = require("path"); - -/***/ }), - -/***/ 576: -/***/ ((module) => { - -"use strict"; -module.exports = require("string_decoder"); - -/***/ }), - -/***/ 512: -/***/ ((module) => { - -"use strict"; -module.exports = require("timers"); - -/***/ }), - -/***/ 404: -/***/ ((module) => { - -"use strict"; -module.exports = require("tls"); - -/***/ }), - -/***/ 837: -/***/ ((module) => { - -"use strict"; -module.exports = require("util"); - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __nccwpck_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ var threw = true; -/******/ try { -/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); -/******/ threw = false; -/******/ } finally { -/******/ if(threw) delete __webpack_module_cache__[moduleId]; -/******/ } -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/compat */ -/******/ -/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; -/******/ -/************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { -const core = __nccwpck_require__(363); -const sweep = __nccwpck_require__(925); - -sweep.sweep().catch(core.setFailed); - -})(); - -module.exports = __webpack_exports__; -/******/ })() -; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/.github/actions/cargo-sweep/dist/post/index.js.map b/.github/actions/cargo-sweep/dist/post/index.js.map deleted file mode 100644 index 5d5c5afd80205..0000000000000 --- a/.github/actions/cargo-sweep/dist/post/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC/UA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC1RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACzmBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5lBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AChLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACpVA;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACvQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC1GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACpBA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC7BA;AACA;;;;;;ACDA;AACA;AACA;AACA","sources":["../webpack://cargo-sweep-action/./src/sweep.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/command.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/core.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/file-command.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/oidc-utils.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/path-utils.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/summary.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+core@1.10.0/node_modules/@actions/core/lib/utils.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/exec.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/toolrunner.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+http-client@2.0.1/node_modules/@actions/http-client/lib/auth.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+http-client@2.0.1/node_modules/@actions/http-client/lib/index.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+http-client@2.0.1/node_modules/@actions/http-client/lib/proxy.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+io@1.1.2/node_modules/@actions/io/lib/io-util.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/@actions+io@1.1.2/node_modules/@actions/io/lib/io.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/index.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/lib/tunnel.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/index.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/md5.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/nil.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/parse.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/regex.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/rng.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/sha1.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/stringify.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v1.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v3.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v35.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v4.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/v5.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/validate.js","../webpack://cargo-sweep-action/../../../node_modules/.pnpm/uuid@8.3.2/node_modules/uuid/dist/version.js","../webpack://cargo-sweep-action/external node-commonjs \"assert\"","../webpack://cargo-sweep-action/external node-commonjs \"child_process\"","../webpack://cargo-sweep-action/external node-commonjs \"crypto\"","../webpack://cargo-sweep-action/external node-commonjs \"events\"","../webpack://cargo-sweep-action/external node-commonjs \"fs\"","../webpack://cargo-sweep-action/external node-commonjs \"http\"","../webpack://cargo-sweep-action/external node-commonjs \"https\"","../webpack://cargo-sweep-action/external node-commonjs \"net\"","../webpack://cargo-sweep-action/external node-commonjs \"os\"","../webpack://cargo-sweep-action/external node-commonjs \"path\"","../webpack://cargo-sweep-action/external node-commonjs \"string_decoder\"","../webpack://cargo-sweep-action/external node-commonjs \"timers\"","../webpack://cargo-sweep-action/external node-commonjs \"tls\"","../webpack://cargo-sweep-action/external node-commonjs \"util\"","../webpack://cargo-sweep-action/webpack/bootstrap","../webpack://cargo-sweep-action/webpack/runtime/compat","../webpack://cargo-sweep-action/./src/post.js"],"sourcesContent":["const core = require(\"@actions/core\");\nconst exec = require(\"@actions/exec\");\n\nasync function runSweep(...args) {\n // TODO(alexkirsz) A cargo change introduced a regression where cargo can't\n // find the sweep binary. This is a temporary workaround until the fix is\n // released. See:\n // https://github.com/rust-lang/cargo/pull/11814\n await exec.exec(\"cargo-sweep\", [\"sweep\", ...args]);\n}\n\nasync function storeTimestamp() {\n await core.group(\"Storing timestamp to compare later\", () =>\n runSweep(\"--stamp\")\n );\n\n core.info(\"Timestamp stored in `sweep.timestamp`\");\n}\n\nasync function sweep() {\n await core.group(\"Cleaning old build artifacts\", () => runSweep(\"--file\"));\n\n core.info(\"Removed old build artifacts.\");\n}\n\nmodule.exports = {\n storeTimestamp,\n sweep,\n};\n","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.issue = exports.issueCommand = void 0;\nconst os = __importStar(require(\"os\"));\nconst utils_1 = require(\"./utils\");\n/**\n * Commands\n *\n * Command Format:\n * ::name key=value,key=value::message\n *\n * Examples:\n * ::warning::This is the message\n * ::set-env name=MY_VAR::some value\n */\nfunction issueCommand(command, properties, message) {\n const cmd = new Command(command, properties, message);\n process.stdout.write(cmd.toString() + os.EOL);\n}\nexports.issueCommand = issueCommand;\nfunction issue(name, message = '') {\n issueCommand(name, {}, message);\n}\nexports.issue = issue;\nconst CMD_STRING = '::';\nclass Command {\n constructor(command, properties, message) {\n if (!command) {\n command = 'missing.command';\n }\n this.command = command;\n this.properties = properties;\n this.message = message;\n }\n toString() {\n let cmdStr = CMD_STRING + this.command;\n if (this.properties && Object.keys(this.properties).length > 0) {\n cmdStr += ' ';\n let first = true;\n for (const key in this.properties) {\n if (this.properties.hasOwnProperty(key)) {\n const val = this.properties[key];\n if (val) {\n if (first) {\n first = false;\n }\n else {\n cmdStr += ',';\n }\n cmdStr += `${key}=${escapeProperty(val)}`;\n }\n }\n }\n }\n cmdStr += `${CMD_STRING}${escapeData(this.message)}`;\n return cmdStr;\n }\n}\nfunction escapeData(s) {\n return utils_1.toCommandValue(s)\n .replace(/%/g, '%25')\n .replace(/\\r/g, '%0D')\n .replace(/\\n/g, '%0A');\n}\nfunction escapeProperty(s) {\n return utils_1.toCommandValue(s)\n .replace(/%/g, '%25')\n .replace(/\\r/g, '%0D')\n .replace(/\\n/g, '%0A')\n .replace(/:/g, '%3A')\n .replace(/,/g, '%2C');\n}\n//# sourceMappingURL=command.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0;\nconst command_1 = require(\"./command\");\nconst file_command_1 = require(\"./file-command\");\nconst utils_1 = require(\"./utils\");\nconst os = __importStar(require(\"os\"));\nconst path = __importStar(require(\"path\"));\nconst oidc_utils_1 = require(\"./oidc-utils\");\n/**\n * The code to exit an action\n */\nvar ExitCode;\n(function (ExitCode) {\n /**\n * A code indicating that the action was successful\n */\n ExitCode[ExitCode[\"Success\"] = 0] = \"Success\";\n /**\n * A code indicating that the action was a failure\n */\n ExitCode[ExitCode[\"Failure\"] = 1] = \"Failure\";\n})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));\n//-----------------------------------------------------------------------\n// Variables\n//-----------------------------------------------------------------------\n/**\n * Sets env variable for this action and future actions in the job\n * @param name the name of the variable to set\n * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction exportVariable(name, val) {\n const convertedVal = utils_1.toCommandValue(val);\n process.env[name] = convertedVal;\n const filePath = process.env['GITHUB_ENV'] || '';\n if (filePath) {\n return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val));\n }\n command_1.issueCommand('set-env', { name }, convertedVal);\n}\nexports.exportVariable = exportVariable;\n/**\n * Registers a secret which will get masked from logs\n * @param secret value of the secret\n */\nfunction setSecret(secret) {\n command_1.issueCommand('add-mask', {}, secret);\n}\nexports.setSecret = setSecret;\n/**\n * Prepends inputPath to the PATH (for this action and future actions)\n * @param inputPath\n */\nfunction addPath(inputPath) {\n const filePath = process.env['GITHUB_PATH'] || '';\n if (filePath) {\n file_command_1.issueFileCommand('PATH', inputPath);\n }\n else {\n command_1.issueCommand('add-path', {}, inputPath);\n }\n process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;\n}\nexports.addPath = addPath;\n/**\n * Gets the value of an input.\n * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed.\n * Returns an empty string if the value is not defined.\n *\n * @param name name of the input to get\n * @param options optional. See InputOptions.\n * @returns string\n */\nfunction getInput(name, options) {\n const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';\n if (options && options.required && !val) {\n throw new Error(`Input required and not supplied: ${name}`);\n }\n if (options && options.trimWhitespace === false) {\n return val;\n }\n return val.trim();\n}\nexports.getInput = getInput;\n/**\n * Gets the values of an multiline input. Each value is also trimmed.\n *\n * @param name name of the input to get\n * @param options optional. See InputOptions.\n * @returns string[]\n *\n */\nfunction getMultilineInput(name, options) {\n const inputs = getInput(name, options)\n .split('\\n')\n .filter(x => x !== '');\n if (options && options.trimWhitespace === false) {\n return inputs;\n }\n return inputs.map(input => input.trim());\n}\nexports.getMultilineInput = getMultilineInput;\n/**\n * Gets the input value of the boolean type in the YAML 1.2 \"core schema\" specification.\n * Support boolean input list: `true | True | TRUE | false | False | FALSE` .\n * The return value is also in boolean type.\n * ref: https://yaml.org/spec/1.2/spec.html#id2804923\n *\n * @param name name of the input to get\n * @param options optional. See InputOptions.\n * @returns boolean\n */\nfunction getBooleanInput(name, options) {\n const trueValue = ['true', 'True', 'TRUE'];\n const falseValue = ['false', 'False', 'FALSE'];\n const val = getInput(name, options);\n if (trueValue.includes(val))\n return true;\n if (falseValue.includes(val))\n return false;\n throw new TypeError(`Input does not meet YAML 1.2 \"Core Schema\" specification: ${name}\\n` +\n `Support boolean input list: \\`true | True | TRUE | false | False | FALSE\\``);\n}\nexports.getBooleanInput = getBooleanInput;\n/**\n * Sets the value of an output.\n *\n * @param name name of the output to set\n * @param value value to store. Non-string values will be converted to a string via JSON.stringify\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction setOutput(name, value) {\n const filePath = process.env['GITHUB_OUTPUT'] || '';\n if (filePath) {\n return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value));\n }\n process.stdout.write(os.EOL);\n command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value));\n}\nexports.setOutput = setOutput;\n/**\n * Enables or disables the echoing of commands into stdout for the rest of the step.\n * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.\n *\n */\nfunction setCommandEcho(enabled) {\n command_1.issue('echo', enabled ? 'on' : 'off');\n}\nexports.setCommandEcho = setCommandEcho;\n//-----------------------------------------------------------------------\n// Results\n//-----------------------------------------------------------------------\n/**\n * Sets the action status to failed.\n * When the action exits it will be with an exit code of 1\n * @param message add error issue message\n */\nfunction setFailed(message) {\n process.exitCode = ExitCode.Failure;\n error(message);\n}\nexports.setFailed = setFailed;\n//-----------------------------------------------------------------------\n// Logging Commands\n//-----------------------------------------------------------------------\n/**\n * Gets whether Actions Step Debug is on or not\n */\nfunction isDebug() {\n return process.env['RUNNER_DEBUG'] === '1';\n}\nexports.isDebug = isDebug;\n/**\n * Writes debug message to user log\n * @param message debug message\n */\nfunction debug(message) {\n command_1.issueCommand('debug', {}, message);\n}\nexports.debug = debug;\n/**\n * Adds an error issue\n * @param message error issue message. Errors will be converted to string via toString()\n * @param properties optional properties to add to the annotation.\n */\nfunction error(message, properties = {}) {\n command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message);\n}\nexports.error = error;\n/**\n * Adds a warning issue\n * @param message warning issue message. Errors will be converted to string via toString()\n * @param properties optional properties to add to the annotation.\n */\nfunction warning(message, properties = {}) {\n command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message);\n}\nexports.warning = warning;\n/**\n * Adds a notice issue\n * @param message notice issue message. Errors will be converted to string via toString()\n * @param properties optional properties to add to the annotation.\n */\nfunction notice(message, properties = {}) {\n command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message);\n}\nexports.notice = notice;\n/**\n * Writes info to log with console.log.\n * @param message info message\n */\nfunction info(message) {\n process.stdout.write(message + os.EOL);\n}\nexports.info = info;\n/**\n * Begin an output group.\n *\n * Output until the next `groupEnd` will be foldable in this group\n *\n * @param name The name of the output group\n */\nfunction startGroup(name) {\n command_1.issue('group', name);\n}\nexports.startGroup = startGroup;\n/**\n * End an output group.\n */\nfunction endGroup() {\n command_1.issue('endgroup');\n}\nexports.endGroup = endGroup;\n/**\n * Wrap an asynchronous function call in a group.\n *\n * Returns the same type as the function itself.\n *\n * @param name The name of the group\n * @param fn The function to wrap in the group\n */\nfunction group(name, fn) {\n return __awaiter(this, void 0, void 0, function* () {\n startGroup(name);\n let result;\n try {\n result = yield fn();\n }\n finally {\n endGroup();\n }\n return result;\n });\n}\nexports.group = group;\n//-----------------------------------------------------------------------\n// Wrapper action state\n//-----------------------------------------------------------------------\n/**\n * Saves state for current action, the state can only be retrieved by this action's post job execution.\n *\n * @param name name of the state to store\n * @param value value to store. Non-string values will be converted to a string via JSON.stringify\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction saveState(name, value) {\n const filePath = process.env['GITHUB_STATE'] || '';\n if (filePath) {\n return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value));\n }\n command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value));\n}\nexports.saveState = saveState;\n/**\n * Gets the value of an state set by this action's main execution.\n *\n * @param name name of the state to get\n * @returns string\n */\nfunction getState(name) {\n return process.env[`STATE_${name}`] || '';\n}\nexports.getState = getState;\nfunction getIDToken(aud) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield oidc_utils_1.OidcClient.getIDToken(aud);\n });\n}\nexports.getIDToken = getIDToken;\n/**\n * Summary exports\n */\nvar summary_1 = require(\"./summary\");\nObject.defineProperty(exports, \"summary\", { enumerable: true, get: function () { return summary_1.summary; } });\n/**\n * @deprecated use core.summary\n */\nvar summary_2 = require(\"./summary\");\nObject.defineProperty(exports, \"markdownSummary\", { enumerable: true, get: function () { return summary_2.markdownSummary; } });\n/**\n * Path exports\n */\nvar path_utils_1 = require(\"./path-utils\");\nObject.defineProperty(exports, \"toPosixPath\", { enumerable: true, get: function () { return path_utils_1.toPosixPath; } });\nObject.defineProperty(exports, \"toWin32Path\", { enumerable: true, get: function () { return path_utils_1.toWin32Path; } });\nObject.defineProperty(exports, \"toPlatformPath\", { enumerable: true, get: function () { return path_utils_1.toPlatformPath; } });\n//# sourceMappingURL=core.js.map","\"use strict\";\n// For internal use, subject to change.\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.prepareKeyValueMessage = exports.issueFileCommand = void 0;\n// We use any as a valid input type\n/* eslint-disable @typescript-eslint/no-explicit-any */\nconst fs = __importStar(require(\"fs\"));\nconst os = __importStar(require(\"os\"));\nconst uuid_1 = require(\"uuid\");\nconst utils_1 = require(\"./utils\");\nfunction issueFileCommand(command, message) {\n const filePath = process.env[`GITHUB_${command}`];\n if (!filePath) {\n throw new Error(`Unable to find environment variable for file command ${command}`);\n }\n if (!fs.existsSync(filePath)) {\n throw new Error(`Missing file at path: ${filePath}`);\n }\n fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, {\n encoding: 'utf8'\n });\n}\nexports.issueFileCommand = issueFileCommand;\nfunction prepareKeyValueMessage(key, value) {\n const delimiter = `ghadelimiter_${uuid_1.v4()}`;\n const convertedValue = utils_1.toCommandValue(value);\n // These should realistically never happen, but just in case someone finds a\n // way to exploit uuid generation let's not allow keys or values that contain\n // the delimiter.\n if (key.includes(delimiter)) {\n throw new Error(`Unexpected input: name should not contain the delimiter \"${delimiter}\"`);\n }\n if (convertedValue.includes(delimiter)) {\n throw new Error(`Unexpected input: value should not contain the delimiter \"${delimiter}\"`);\n }\n return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`;\n}\nexports.prepareKeyValueMessage = prepareKeyValueMessage;\n//# sourceMappingURL=file-command.js.map","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.OidcClient = void 0;\nconst http_client_1 = require(\"@actions/http-client\");\nconst auth_1 = require(\"@actions/http-client/lib/auth\");\nconst core_1 = require(\"./core\");\nclass OidcClient {\n static createHttpClient(allowRetry = true, maxRetry = 10) {\n const requestOptions = {\n allowRetries: allowRetry,\n maxRetries: maxRetry\n };\n return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions);\n }\n static getRequestToken() {\n const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'];\n if (!token) {\n throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable');\n }\n return token;\n }\n static getIDTokenUrl() {\n const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL'];\n if (!runtimeUrl) {\n throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable');\n }\n return runtimeUrl;\n }\n static getCall(id_token_url) {\n var _a;\n return __awaiter(this, void 0, void 0, function* () {\n const httpclient = OidcClient.createHttpClient();\n const res = yield httpclient\n .getJson(id_token_url)\n .catch(error => {\n throw new Error(`Failed to get ID Token. \\n \n Error Code : ${error.statusCode}\\n \n Error Message: ${error.result.message}`);\n });\n const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value;\n if (!id_token) {\n throw new Error('Response json body do not have ID Token field');\n }\n return id_token;\n });\n }\n static getIDToken(audience) {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n // New ID Token is requested from action service\n let id_token_url = OidcClient.getIDTokenUrl();\n if (audience) {\n const encodedAudience = encodeURIComponent(audience);\n id_token_url = `${id_token_url}&audience=${encodedAudience}`;\n }\n core_1.debug(`ID token url is ${id_token_url}`);\n const id_token = yield OidcClient.getCall(id_token_url);\n core_1.setSecret(id_token);\n return id_token;\n }\n catch (error) {\n throw new Error(`Error message: ${error.message}`);\n }\n });\n }\n}\nexports.OidcClient = OidcClient;\n//# sourceMappingURL=oidc-utils.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0;\nconst path = __importStar(require(\"path\"));\n/**\n * toPosixPath converts the given path to the posix form. On Windows, \\\\ will be\n * replaced with /.\n *\n * @param pth. Path to transform.\n * @return string Posix path.\n */\nfunction toPosixPath(pth) {\n return pth.replace(/[\\\\]/g, '/');\n}\nexports.toPosixPath = toPosixPath;\n/**\n * toWin32Path converts the given path to the win32 form. On Linux, / will be\n * replaced with \\\\.\n *\n * @param pth. Path to transform.\n * @return string Win32 path.\n */\nfunction toWin32Path(pth) {\n return pth.replace(/[/]/g, '\\\\');\n}\nexports.toWin32Path = toWin32Path;\n/**\n * toPlatformPath converts the given path to a platform-specific path. It does\n * this by replacing instances of / and \\ with the platform-specific path\n * separator.\n *\n * @param pth The path to platformize.\n * @return string The platform-specific path.\n */\nfunction toPlatformPath(pth) {\n return pth.replace(/[/\\\\]/g, path.sep);\n}\nexports.toPlatformPath = toPlatformPath;\n//# sourceMappingURL=path-utils.js.map","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0;\nconst os_1 = require(\"os\");\nconst fs_1 = require(\"fs\");\nconst { access, appendFile, writeFile } = fs_1.promises;\nexports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY';\nexports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary';\nclass Summary {\n constructor() {\n this._buffer = '';\n }\n /**\n * Finds the summary file path from the environment, rejects if env var is not found or file does not exist\n * Also checks r/w permissions.\n *\n * @returns step summary file path\n */\n filePath() {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._filePath) {\n return this._filePath;\n }\n const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR];\n if (!pathFromEnv) {\n throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`);\n }\n try {\n yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK);\n }\n catch (_a) {\n throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`);\n }\n this._filePath = pathFromEnv;\n return this._filePath;\n });\n }\n /**\n * Wraps content in an HTML tag, adding any HTML attributes\n *\n * @param {string} tag HTML tag to wrap\n * @param {string | null} content content within the tag\n * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add\n *\n * @returns {string} content wrapped in HTML element\n */\n wrap(tag, content, attrs = {}) {\n const htmlAttrs = Object.entries(attrs)\n .map(([key, value]) => ` ${key}=\"${value}\"`)\n .join('');\n if (!content) {\n return `<${tag}${htmlAttrs}>`;\n }\n return `<${tag}${htmlAttrs}>${content}`;\n }\n /**\n * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default.\n *\n * @param {SummaryWriteOptions} [options] (optional) options for write operation\n *\n * @returns {Promise} summary instance\n */\n write(options) {\n return __awaiter(this, void 0, void 0, function* () {\n const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite);\n const filePath = yield this.filePath();\n const writeFunc = overwrite ? writeFile : appendFile;\n yield writeFunc(filePath, this._buffer, { encoding: 'utf8' });\n return this.emptyBuffer();\n });\n }\n /**\n * Clears the summary buffer and wipes the summary file\n *\n * @returns {Summary} summary instance\n */\n clear() {\n return __awaiter(this, void 0, void 0, function* () {\n return this.emptyBuffer().write({ overwrite: true });\n });\n }\n /**\n * Returns the current summary buffer as a string\n *\n * @returns {string} string of summary buffer\n */\n stringify() {\n return this._buffer;\n }\n /**\n * If the summary buffer is empty\n *\n * @returns {boolen} true if the buffer is empty\n */\n isEmptyBuffer() {\n return this._buffer.length === 0;\n }\n /**\n * Resets the summary buffer without writing to summary file\n *\n * @returns {Summary} summary instance\n */\n emptyBuffer() {\n this._buffer = '';\n return this;\n }\n /**\n * Adds raw text to the summary buffer\n *\n * @param {string} text content to add\n * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false)\n *\n * @returns {Summary} summary instance\n */\n addRaw(text, addEOL = false) {\n this._buffer += text;\n return addEOL ? this.addEOL() : this;\n }\n /**\n * Adds the operating system-specific end-of-line marker to the buffer\n *\n * @returns {Summary} summary instance\n */\n addEOL() {\n return this.addRaw(os_1.EOL);\n }\n /**\n * Adds an HTML codeblock to the summary buffer\n *\n * @param {string} code content to render within fenced code block\n * @param {string} lang (optional) language to syntax highlight code\n *\n * @returns {Summary} summary instance\n */\n addCodeBlock(code, lang) {\n const attrs = Object.assign({}, (lang && { lang }));\n const element = this.wrap('pre', this.wrap('code', code), attrs);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML list to the summary buffer\n *\n * @param {string[]} items list of items to render\n * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false)\n *\n * @returns {Summary} summary instance\n */\n addList(items, ordered = false) {\n const tag = ordered ? 'ol' : 'ul';\n const listItems = items.map(item => this.wrap('li', item)).join('');\n const element = this.wrap(tag, listItems);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML table to the summary buffer\n *\n * @param {SummaryTableCell[]} rows table rows\n *\n * @returns {Summary} summary instance\n */\n addTable(rows) {\n const tableBody = rows\n .map(row => {\n const cells = row\n .map(cell => {\n if (typeof cell === 'string') {\n return this.wrap('td', cell);\n }\n const { header, data, colspan, rowspan } = cell;\n const tag = header ? 'th' : 'td';\n const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan }));\n return this.wrap(tag, data, attrs);\n })\n .join('');\n return this.wrap('tr', cells);\n })\n .join('');\n const element = this.wrap('table', tableBody);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds a collapsable HTML details element to the summary buffer\n *\n * @param {string} label text for the closed state\n * @param {string} content collapsable content\n *\n * @returns {Summary} summary instance\n */\n addDetails(label, content) {\n const element = this.wrap('details', this.wrap('summary', label) + content);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML image tag to the summary buffer\n *\n * @param {string} src path to the image you to embed\n * @param {string} alt text description of the image\n * @param {SummaryImageOptions} options (optional) addition image attributes\n *\n * @returns {Summary} summary instance\n */\n addImage(src, alt, options) {\n const { width, height } = options || {};\n const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height }));\n const element = this.wrap('img', null, Object.assign({ src, alt }, attrs));\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML section heading element\n *\n * @param {string} text heading text\n * @param {number | string} [level=1] (optional) the heading level, default: 1\n *\n * @returns {Summary} summary instance\n */\n addHeading(text, level) {\n const tag = `h${level}`;\n const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag)\n ? tag\n : 'h1';\n const element = this.wrap(allowedTag, text);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML thematic break (
) to the summary buffer\n *\n * @returns {Summary} summary instance\n */\n addSeparator() {\n const element = this.wrap('hr', null);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML line break (
) to the summary buffer\n *\n * @returns {Summary} summary instance\n */\n addBreak() {\n const element = this.wrap('br', null);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML blockquote to the summary buffer\n *\n * @param {string} text quote text\n * @param {string} cite (optional) citation url\n *\n * @returns {Summary} summary instance\n */\n addQuote(text, cite) {\n const attrs = Object.assign({}, (cite && { cite }));\n const element = this.wrap('blockquote', text, attrs);\n return this.addRaw(element).addEOL();\n }\n /**\n * Adds an HTML anchor tag to the summary buffer\n *\n * @param {string} text link text/content\n * @param {string} href hyperlink\n *\n * @returns {Summary} summary instance\n */\n addLink(text, href) {\n const element = this.wrap('a', text, { href });\n return this.addRaw(element).addEOL();\n }\n}\nconst _summary = new Summary();\n/**\n * @deprecated use `core.summary`\n */\nexports.markdownSummary = _summary;\nexports.summary = _summary;\n//# sourceMappingURL=summary.js.map","\"use strict\";\n// We use any as a valid input type\n/* eslint-disable @typescript-eslint/no-explicit-any */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.toCommandProperties = exports.toCommandValue = void 0;\n/**\n * Sanitizes an input into a string so it can be passed into issueCommand safely\n * @param input input to sanitize into a string\n */\nfunction toCommandValue(input) {\n if (input === null || input === undefined) {\n return '';\n }\n else if (typeof input === 'string' || input instanceof String) {\n return input;\n }\n return JSON.stringify(input);\n}\nexports.toCommandValue = toCommandValue;\n/**\n *\n * @param annotationProperties\n * @returns The command properties to send with the actual annotation command\n * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646\n */\nfunction toCommandProperties(annotationProperties) {\n if (!Object.keys(annotationProperties).length) {\n return {};\n }\n return {\n title: annotationProperties.title,\n file: annotationProperties.file,\n line: annotationProperties.startLine,\n endLine: annotationProperties.endLine,\n col: annotationProperties.startColumn,\n endColumn: annotationProperties.endColumn\n };\n}\nexports.toCommandProperties = toCommandProperties;\n//# sourceMappingURL=utils.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getExecOutput = exports.exec = void 0;\nconst string_decoder_1 = require(\"string_decoder\");\nconst tr = __importStar(require(\"./toolrunner\"));\n/**\n * Exec a command.\n * Output will be streamed to the live console.\n * Returns promise with return code\n *\n * @param commandLine command to execute (can include additional args). Must be correctly escaped.\n * @param args optional arguments for tool. Escaping is handled by the lib.\n * @param options optional exec options. See ExecOptions\n * @returns Promise exit code\n */\nfunction exec(commandLine, args, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const commandArgs = tr.argStringToArray(commandLine);\n if (commandArgs.length === 0) {\n throw new Error(`Parameter 'commandLine' cannot be null or empty.`);\n }\n // Path to tool to execute should be first arg\n const toolPath = commandArgs[0];\n args = commandArgs.slice(1).concat(args || []);\n const runner = new tr.ToolRunner(toolPath, args, options);\n return runner.exec();\n });\n}\nexports.exec = exec;\n/**\n * Exec a command and get the output.\n * Output will be streamed to the live console.\n * Returns promise with the exit code and collected stdout and stderr\n *\n * @param commandLine command to execute (can include additional args). Must be correctly escaped.\n * @param args optional arguments for tool. Escaping is handled by the lib.\n * @param options optional exec options. See ExecOptions\n * @returns Promise exit code, stdout, and stderr\n */\nfunction getExecOutput(commandLine, args, options) {\n var _a, _b;\n return __awaiter(this, void 0, void 0, function* () {\n let stdout = '';\n let stderr = '';\n //Using string decoder covers the case where a mult-byte character is split\n const stdoutDecoder = new string_decoder_1.StringDecoder('utf8');\n const stderrDecoder = new string_decoder_1.StringDecoder('utf8');\n const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout;\n const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr;\n const stdErrListener = (data) => {\n stderr += stderrDecoder.write(data);\n if (originalStdErrListener) {\n originalStdErrListener(data);\n }\n };\n const stdOutListener = (data) => {\n stdout += stdoutDecoder.write(data);\n if (originalStdoutListener) {\n originalStdoutListener(data);\n }\n };\n const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener });\n const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners }));\n //flush any remaining characters\n stdout += stdoutDecoder.end();\n stderr += stderrDecoder.end();\n return {\n exitCode,\n stdout,\n stderr\n };\n });\n}\nexports.getExecOutput = getExecOutput;\n//# sourceMappingURL=exec.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.argStringToArray = exports.ToolRunner = void 0;\nconst os = __importStar(require(\"os\"));\nconst events = __importStar(require(\"events\"));\nconst child = __importStar(require(\"child_process\"));\nconst path = __importStar(require(\"path\"));\nconst io = __importStar(require(\"@actions/io\"));\nconst ioUtil = __importStar(require(\"@actions/io/lib/io-util\"));\nconst timers_1 = require(\"timers\");\n/* eslint-disable @typescript-eslint/unbound-method */\nconst IS_WINDOWS = process.platform === 'win32';\n/*\n * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way.\n */\nclass ToolRunner extends events.EventEmitter {\n constructor(toolPath, args, options) {\n super();\n if (!toolPath) {\n throw new Error(\"Parameter 'toolPath' cannot be null or empty.\");\n }\n this.toolPath = toolPath;\n this.args = args || [];\n this.options = options || {};\n }\n _debug(message) {\n if (this.options.listeners && this.options.listeners.debug) {\n this.options.listeners.debug(message);\n }\n }\n _getCommandString(options, noPrefix) {\n const toolPath = this._getSpawnFileName();\n const args = this._getSpawnArgs(options);\n let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool\n if (IS_WINDOWS) {\n // Windows + cmd file\n if (this._isCmdFile()) {\n cmd += toolPath;\n for (const a of args) {\n cmd += ` ${a}`;\n }\n }\n // Windows + verbatim\n else if (options.windowsVerbatimArguments) {\n cmd += `\"${toolPath}\"`;\n for (const a of args) {\n cmd += ` ${a}`;\n }\n }\n // Windows (regular)\n else {\n cmd += this._windowsQuoteCmdArg(toolPath);\n for (const a of args) {\n cmd += ` ${this._windowsQuoteCmdArg(a)}`;\n }\n }\n }\n else {\n // OSX/Linux - this can likely be improved with some form of quoting.\n // creating processes on Unix is fundamentally different than Windows.\n // on Unix, execvp() takes an arg array.\n cmd += toolPath;\n for (const a of args) {\n cmd += ` ${a}`;\n }\n }\n return cmd;\n }\n _processLineBuffer(data, strBuffer, onLine) {\n try {\n let s = strBuffer + data.toString();\n let n = s.indexOf(os.EOL);\n while (n > -1) {\n const line = s.substring(0, n);\n onLine(line);\n // the rest of the string ...\n s = s.substring(n + os.EOL.length);\n n = s.indexOf(os.EOL);\n }\n return s;\n }\n catch (err) {\n // streaming lines to console is best effort. Don't fail a build.\n this._debug(`error processing line. Failed with error ${err}`);\n return '';\n }\n }\n _getSpawnFileName() {\n if (IS_WINDOWS) {\n if (this._isCmdFile()) {\n return process.env['COMSPEC'] || 'cmd.exe';\n }\n }\n return this.toolPath;\n }\n _getSpawnArgs(options) {\n if (IS_WINDOWS) {\n if (this._isCmdFile()) {\n let argline = `/D /S /C \"${this._windowsQuoteCmdArg(this.toolPath)}`;\n for (const a of this.args) {\n argline += ' ';\n argline += options.windowsVerbatimArguments\n ? a\n : this._windowsQuoteCmdArg(a);\n }\n argline += '\"';\n return [argline];\n }\n }\n return this.args;\n }\n _endsWith(str, end) {\n return str.endsWith(end);\n }\n _isCmdFile() {\n const upperToolPath = this.toolPath.toUpperCase();\n return (this._endsWith(upperToolPath, '.CMD') ||\n this._endsWith(upperToolPath, '.BAT'));\n }\n _windowsQuoteCmdArg(arg) {\n // for .exe, apply the normal quoting rules that libuv applies\n if (!this._isCmdFile()) {\n return this._uvQuoteCmdArg(arg);\n }\n // otherwise apply quoting rules specific to the cmd.exe command line parser.\n // the libuv rules are generic and are not designed specifically for cmd.exe\n // command line parser.\n //\n // for a detailed description of the cmd.exe command line parser, refer to\n // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912\n // need quotes for empty arg\n if (!arg) {\n return '\"\"';\n }\n // determine whether the arg needs to be quoted\n const cmdSpecialChars = [\n ' ',\n '\\t',\n '&',\n '(',\n ')',\n '[',\n ']',\n '{',\n '}',\n '^',\n '=',\n ';',\n '!',\n \"'\",\n '+',\n ',',\n '`',\n '~',\n '|',\n '<',\n '>',\n '\"'\n ];\n let needsQuotes = false;\n for (const char of arg) {\n if (cmdSpecialChars.some(x => x === char)) {\n needsQuotes = true;\n break;\n }\n }\n // short-circuit if quotes not needed\n if (!needsQuotes) {\n return arg;\n }\n // the following quoting rules are very similar to the rules that by libuv applies.\n //\n // 1) wrap the string in quotes\n //\n // 2) double-up quotes - i.e. \" => \"\"\n //\n // this is different from the libuv quoting rules. libuv replaces \" with \\\", which unfortunately\n // doesn't work well with a cmd.exe command line.\n //\n // note, replacing \" with \"\" also works well if the arg is passed to a downstream .NET console app.\n // for example, the command line:\n // foo.exe \"myarg:\"\"my val\"\"\"\n // is parsed by a .NET console app into an arg array:\n // [ \"myarg:\\\"my val\\\"\" ]\n // which is the same end result when applying libuv quoting rules. although the actual\n // command line from libuv quoting rules would look like:\n // foo.exe \"myarg:\\\"my val\\\"\"\n //\n // 3) double-up slashes that precede a quote,\n // e.g. hello \\world => \"hello \\world\"\n // hello\\\"world => \"hello\\\\\"\"world\"\n // hello\\\\\"world => \"hello\\\\\\\\\"\"world\"\n // hello world\\ => \"hello world\\\\\"\n //\n // technically this is not required for a cmd.exe command line, or the batch argument parser.\n // the reasons for including this as a .cmd quoting rule are:\n //\n // a) this is optimized for the scenario where the argument is passed from the .cmd file to an\n // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.\n //\n // b) it's what we've been doing previously (by deferring to node default behavior) and we\n // haven't heard any complaints about that aspect.\n //\n // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be\n // escaped when used on the command line directly - even though within a .cmd file % can be escaped\n // by using %%.\n //\n // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts\n // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.\n //\n // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would\n // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the\n // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args\n // to an external program.\n //\n // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.\n // % can be escaped within a .cmd file.\n let reverse = '\"';\n let quoteHit = true;\n for (let i = arg.length; i > 0; i--) {\n // walk the string in reverse\n reverse += arg[i - 1];\n if (quoteHit && arg[i - 1] === '\\\\') {\n reverse += '\\\\'; // double the slash\n }\n else if (arg[i - 1] === '\"') {\n quoteHit = true;\n reverse += '\"'; // double the quote\n }\n else {\n quoteHit = false;\n }\n }\n reverse += '\"';\n return reverse\n .split('')\n .reverse()\n .join('');\n }\n _uvQuoteCmdArg(arg) {\n // Tool runner wraps child_process.spawn() and needs to apply the same quoting as\n // Node in certain cases where the undocumented spawn option windowsVerbatimArguments\n // is used.\n //\n // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,\n // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),\n // pasting copyright notice from Node within this function:\n //\n // Copyright Joyent, Inc. and other Node contributors. All rights reserved.\n //\n // Permission is hereby granted, free of charge, to any person obtaining a copy\n // of this software and associated documentation files (the \"Software\"), to\n // deal in the Software without restriction, including without limitation the\n // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n // sell copies of the Software, and to permit persons to whom the Software is\n // furnished to do so, subject to the following conditions:\n //\n // The above copyright notice and this permission notice shall be included in\n // all copies or substantial portions of the Software.\n //\n // THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n // IN THE SOFTWARE.\n if (!arg) {\n // Need double quotation for empty argument\n return '\"\"';\n }\n if (!arg.includes(' ') && !arg.includes('\\t') && !arg.includes('\"')) {\n // No quotation needed\n return arg;\n }\n if (!arg.includes('\"') && !arg.includes('\\\\')) {\n // No embedded double quotes or backslashes, so I can just wrap\n // quote marks around the whole thing.\n return `\"${arg}\"`;\n }\n // Expected input/output:\n // input : hello\"world\n // output: \"hello\\\"world\"\n // input : hello\"\"world\n // output: \"hello\\\"\\\"world\"\n // input : hello\\world\n // output: hello\\world\n // input : hello\\\\world\n // output: hello\\\\world\n // input : hello\\\"world\n // output: \"hello\\\\\\\"world\"\n // input : hello\\\\\"world\n // output: \"hello\\\\\\\\\\\"world\"\n // input : hello world\\\n // output: \"hello world\\\\\" - note the comment in libuv actually reads \"hello world\\\"\n // but it appears the comment is wrong, it should be \"hello world\\\\\"\n let reverse = '\"';\n let quoteHit = true;\n for (let i = arg.length; i > 0; i--) {\n // walk the string in reverse\n reverse += arg[i - 1];\n if (quoteHit && arg[i - 1] === '\\\\') {\n reverse += '\\\\';\n }\n else if (arg[i - 1] === '\"') {\n quoteHit = true;\n reverse += '\\\\';\n }\n else {\n quoteHit = false;\n }\n }\n reverse += '\"';\n return reverse\n .split('')\n .reverse()\n .join('');\n }\n _cloneExecOptions(options) {\n options = options || {};\n const result = {\n cwd: options.cwd || process.cwd(),\n env: options.env || process.env,\n silent: options.silent || false,\n windowsVerbatimArguments: options.windowsVerbatimArguments || false,\n failOnStdErr: options.failOnStdErr || false,\n ignoreReturnCode: options.ignoreReturnCode || false,\n delay: options.delay || 10000\n };\n result.outStream = options.outStream || process.stdout;\n result.errStream = options.errStream || process.stderr;\n return result;\n }\n _getSpawnOptions(options, toolPath) {\n options = options || {};\n const result = {};\n result.cwd = options.cwd;\n result.env = options.env;\n result['windowsVerbatimArguments'] =\n options.windowsVerbatimArguments || this._isCmdFile();\n if (options.windowsVerbatimArguments) {\n result.argv0 = `\"${toolPath}\"`;\n }\n return result;\n }\n /**\n * Exec a tool.\n * Output will be streamed to the live console.\n * Returns promise with return code\n *\n * @param tool path to tool to exec\n * @param options optional exec options. See ExecOptions\n * @returns number\n */\n exec() {\n return __awaiter(this, void 0, void 0, function* () {\n // root the tool path if it is unrooted and contains relative pathing\n if (!ioUtil.isRooted(this.toolPath) &&\n (this.toolPath.includes('/') ||\n (IS_WINDOWS && this.toolPath.includes('\\\\')))) {\n // prefer options.cwd if it is specified, however options.cwd may also need to be rooted\n this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath);\n }\n // if the tool is only a file name, then resolve it from the PATH\n // otherwise verify it exists (add extension on Windows if necessary)\n this.toolPath = yield io.which(this.toolPath, true);\n return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {\n this._debug(`exec tool: ${this.toolPath}`);\n this._debug('arguments:');\n for (const arg of this.args) {\n this._debug(` ${arg}`);\n }\n const optionsNonNull = this._cloneExecOptions(this.options);\n if (!optionsNonNull.silent && optionsNonNull.outStream) {\n optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);\n }\n const state = new ExecState(optionsNonNull, this.toolPath);\n state.on('debug', (message) => {\n this._debug(message);\n });\n if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) {\n return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`));\n }\n const fileName = this._getSpawnFileName();\n const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName));\n let stdbuffer = '';\n if (cp.stdout) {\n cp.stdout.on('data', (data) => {\n if (this.options.listeners && this.options.listeners.stdout) {\n this.options.listeners.stdout(data);\n }\n if (!optionsNonNull.silent && optionsNonNull.outStream) {\n optionsNonNull.outStream.write(data);\n }\n stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => {\n if (this.options.listeners && this.options.listeners.stdline) {\n this.options.listeners.stdline(line);\n }\n });\n });\n }\n let errbuffer = '';\n if (cp.stderr) {\n cp.stderr.on('data', (data) => {\n state.processStderr = true;\n if (this.options.listeners && this.options.listeners.stderr) {\n this.options.listeners.stderr(data);\n }\n if (!optionsNonNull.silent &&\n optionsNonNull.errStream &&\n optionsNonNull.outStream) {\n const s = optionsNonNull.failOnStdErr\n ? optionsNonNull.errStream\n : optionsNonNull.outStream;\n s.write(data);\n }\n errbuffer = this._processLineBuffer(data, errbuffer, (line) => {\n if (this.options.listeners && this.options.listeners.errline) {\n this.options.listeners.errline(line);\n }\n });\n });\n }\n cp.on('error', (err) => {\n state.processError = err.message;\n state.processExited = true;\n state.processClosed = true;\n state.CheckComplete();\n });\n cp.on('exit', (code) => {\n state.processExitCode = code;\n state.processExited = true;\n this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);\n state.CheckComplete();\n });\n cp.on('close', (code) => {\n state.processExitCode = code;\n state.processExited = true;\n state.processClosed = true;\n this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);\n state.CheckComplete();\n });\n state.on('done', (error, exitCode) => {\n if (stdbuffer.length > 0) {\n this.emit('stdline', stdbuffer);\n }\n if (errbuffer.length > 0) {\n this.emit('errline', errbuffer);\n }\n cp.removeAllListeners();\n if (error) {\n reject(error);\n }\n else {\n resolve(exitCode);\n }\n });\n if (this.options.input) {\n if (!cp.stdin) {\n throw new Error('child process missing stdin');\n }\n cp.stdin.end(this.options.input);\n }\n }));\n });\n }\n}\nexports.ToolRunner = ToolRunner;\n/**\n * Convert an arg string to an array of args. Handles escaping\n *\n * @param argString string of arguments\n * @returns string[] array of arguments\n */\nfunction argStringToArray(argString) {\n const args = [];\n let inQuotes = false;\n let escaped = false;\n let arg = '';\n function append(c) {\n // we only escape double quotes.\n if (escaped && c !== '\"') {\n arg += '\\\\';\n }\n arg += c;\n escaped = false;\n }\n for (let i = 0; i < argString.length; i++) {\n const c = argString.charAt(i);\n if (c === '\"') {\n if (!escaped) {\n inQuotes = !inQuotes;\n }\n else {\n append(c);\n }\n continue;\n }\n if (c === '\\\\' && escaped) {\n append(c);\n continue;\n }\n if (c === '\\\\' && inQuotes) {\n escaped = true;\n continue;\n }\n if (c === ' ' && !inQuotes) {\n if (arg.length > 0) {\n args.push(arg);\n arg = '';\n }\n continue;\n }\n append(c);\n }\n if (arg.length > 0) {\n args.push(arg.trim());\n }\n return args;\n}\nexports.argStringToArray = argStringToArray;\nclass ExecState extends events.EventEmitter {\n constructor(options, toolPath) {\n super();\n this.processClosed = false; // tracks whether the process has exited and stdio is closed\n this.processError = '';\n this.processExitCode = 0;\n this.processExited = false; // tracks whether the process has exited\n this.processStderr = false; // tracks whether stderr was written to\n this.delay = 10000; // 10 seconds\n this.done = false;\n this.timeout = null;\n if (!toolPath) {\n throw new Error('toolPath must not be empty');\n }\n this.options = options;\n this.toolPath = toolPath;\n if (options.delay) {\n this.delay = options.delay;\n }\n }\n CheckComplete() {\n if (this.done) {\n return;\n }\n if (this.processClosed) {\n this._setResult();\n }\n else if (this.processExited) {\n this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this);\n }\n }\n _debug(message) {\n this.emit('debug', message);\n }\n _setResult() {\n // determine whether there is an error\n let error;\n if (this.processExited) {\n if (this.processError) {\n error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`);\n }\n else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) {\n error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`);\n }\n else if (this.processStderr && this.options.failOnStdErr) {\n error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`);\n }\n }\n // clear the timeout\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n this.done = true;\n this.emit('done', error, this.processExitCode);\n }\n static HandleTimeout(state) {\n if (state.done) {\n return;\n }\n if (!state.processClosed && state.processExited) {\n const message = `The STDIO streams did not close within ${state.delay /\n 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;\n state._debug(message);\n }\n state._setResult();\n }\n}\n//# sourceMappingURL=toolrunner.js.map","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0;\nclass BasicCredentialHandler {\n constructor(username, password) {\n this.username = username;\n this.password = password;\n }\n prepareRequest(options) {\n if (!options.headers) {\n throw Error('The request has no headers');\n }\n options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`;\n }\n // This handler cannot handle 401\n canHandleAuthentication() {\n return false;\n }\n handleAuthentication() {\n return __awaiter(this, void 0, void 0, function* () {\n throw new Error('not implemented');\n });\n }\n}\nexports.BasicCredentialHandler = BasicCredentialHandler;\nclass BearerCredentialHandler {\n constructor(token) {\n this.token = token;\n }\n // currently implements pre-authorization\n // TODO: support preAuth = false where it hooks on 401\n prepareRequest(options) {\n if (!options.headers) {\n throw Error('The request has no headers');\n }\n options.headers['Authorization'] = `Bearer ${this.token}`;\n }\n // This handler cannot handle 401\n canHandleAuthentication() {\n return false;\n }\n handleAuthentication() {\n return __awaiter(this, void 0, void 0, function* () {\n throw new Error('not implemented');\n });\n }\n}\nexports.BearerCredentialHandler = BearerCredentialHandler;\nclass PersonalAccessTokenCredentialHandler {\n constructor(token) {\n this.token = token;\n }\n // currently implements pre-authorization\n // TODO: support preAuth = false where it hooks on 401\n prepareRequest(options) {\n if (!options.headers) {\n throw Error('The request has no headers');\n }\n options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`;\n }\n // This handler cannot handle 401\n canHandleAuthentication() {\n return false;\n }\n handleAuthentication() {\n return __awaiter(this, void 0, void 0, function* () {\n throw new Error('not implemented');\n });\n }\n}\nexports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler;\n//# sourceMappingURL=auth.js.map","\"use strict\";\n/* eslint-disable @typescript-eslint/no-explicit-any */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0;\nconst http = __importStar(require(\"http\"));\nconst https = __importStar(require(\"https\"));\nconst pm = __importStar(require(\"./proxy\"));\nconst tunnel = __importStar(require(\"tunnel\"));\nvar HttpCodes;\n(function (HttpCodes) {\n HttpCodes[HttpCodes[\"OK\"] = 200] = \"OK\";\n HttpCodes[HttpCodes[\"MultipleChoices\"] = 300] = \"MultipleChoices\";\n HttpCodes[HttpCodes[\"MovedPermanently\"] = 301] = \"MovedPermanently\";\n HttpCodes[HttpCodes[\"ResourceMoved\"] = 302] = \"ResourceMoved\";\n HttpCodes[HttpCodes[\"SeeOther\"] = 303] = \"SeeOther\";\n HttpCodes[HttpCodes[\"NotModified\"] = 304] = \"NotModified\";\n HttpCodes[HttpCodes[\"UseProxy\"] = 305] = \"UseProxy\";\n HttpCodes[HttpCodes[\"SwitchProxy\"] = 306] = \"SwitchProxy\";\n HttpCodes[HttpCodes[\"TemporaryRedirect\"] = 307] = \"TemporaryRedirect\";\n HttpCodes[HttpCodes[\"PermanentRedirect\"] = 308] = \"PermanentRedirect\";\n HttpCodes[HttpCodes[\"BadRequest\"] = 400] = \"BadRequest\";\n HttpCodes[HttpCodes[\"Unauthorized\"] = 401] = \"Unauthorized\";\n HttpCodes[HttpCodes[\"PaymentRequired\"] = 402] = \"PaymentRequired\";\n HttpCodes[HttpCodes[\"Forbidden\"] = 403] = \"Forbidden\";\n HttpCodes[HttpCodes[\"NotFound\"] = 404] = \"NotFound\";\n HttpCodes[HttpCodes[\"MethodNotAllowed\"] = 405] = \"MethodNotAllowed\";\n HttpCodes[HttpCodes[\"NotAcceptable\"] = 406] = \"NotAcceptable\";\n HttpCodes[HttpCodes[\"ProxyAuthenticationRequired\"] = 407] = \"ProxyAuthenticationRequired\";\n HttpCodes[HttpCodes[\"RequestTimeout\"] = 408] = \"RequestTimeout\";\n HttpCodes[HttpCodes[\"Conflict\"] = 409] = \"Conflict\";\n HttpCodes[HttpCodes[\"Gone\"] = 410] = \"Gone\";\n HttpCodes[HttpCodes[\"TooManyRequests\"] = 429] = \"TooManyRequests\";\n HttpCodes[HttpCodes[\"InternalServerError\"] = 500] = \"InternalServerError\";\n HttpCodes[HttpCodes[\"NotImplemented\"] = 501] = \"NotImplemented\";\n HttpCodes[HttpCodes[\"BadGateway\"] = 502] = \"BadGateway\";\n HttpCodes[HttpCodes[\"ServiceUnavailable\"] = 503] = \"ServiceUnavailable\";\n HttpCodes[HttpCodes[\"GatewayTimeout\"] = 504] = \"GatewayTimeout\";\n})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {}));\nvar Headers;\n(function (Headers) {\n Headers[\"Accept\"] = \"accept\";\n Headers[\"ContentType\"] = \"content-type\";\n})(Headers = exports.Headers || (exports.Headers = {}));\nvar MediaTypes;\n(function (MediaTypes) {\n MediaTypes[\"ApplicationJson\"] = \"application/json\";\n})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {}));\n/**\n * Returns the proxy URL, depending upon the supplied url and proxy environment variables.\n * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com\n */\nfunction getProxyUrl(serverUrl) {\n const proxyUrl = pm.getProxyUrl(new URL(serverUrl));\n return proxyUrl ? proxyUrl.href : '';\n}\nexports.getProxyUrl = getProxyUrl;\nconst HttpRedirectCodes = [\n HttpCodes.MovedPermanently,\n HttpCodes.ResourceMoved,\n HttpCodes.SeeOther,\n HttpCodes.TemporaryRedirect,\n HttpCodes.PermanentRedirect\n];\nconst HttpResponseRetryCodes = [\n HttpCodes.BadGateway,\n HttpCodes.ServiceUnavailable,\n HttpCodes.GatewayTimeout\n];\nconst RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD'];\nconst ExponentialBackoffCeiling = 10;\nconst ExponentialBackoffTimeSlice = 5;\nclass HttpClientError extends Error {\n constructor(message, statusCode) {\n super(message);\n this.name = 'HttpClientError';\n this.statusCode = statusCode;\n Object.setPrototypeOf(this, HttpClientError.prototype);\n }\n}\nexports.HttpClientError = HttpClientError;\nclass HttpClientResponse {\n constructor(message) {\n this.message = message;\n }\n readBody() {\n return __awaiter(this, void 0, void 0, function* () {\n return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {\n let output = Buffer.alloc(0);\n this.message.on('data', (chunk) => {\n output = Buffer.concat([output, chunk]);\n });\n this.message.on('end', () => {\n resolve(output.toString());\n });\n }));\n });\n }\n}\nexports.HttpClientResponse = HttpClientResponse;\nfunction isHttps(requestUrl) {\n const parsedUrl = new URL(requestUrl);\n return parsedUrl.protocol === 'https:';\n}\nexports.isHttps = isHttps;\nclass HttpClient {\n constructor(userAgent, handlers, requestOptions) {\n this._ignoreSslError = false;\n this._allowRedirects = true;\n this._allowRedirectDowngrade = false;\n this._maxRedirects = 50;\n this._allowRetries = false;\n this._maxRetries = 1;\n this._keepAlive = false;\n this._disposed = false;\n this.userAgent = userAgent;\n this.handlers = handlers || [];\n this.requestOptions = requestOptions;\n if (requestOptions) {\n if (requestOptions.ignoreSslError != null) {\n this._ignoreSslError = requestOptions.ignoreSslError;\n }\n this._socketTimeout = requestOptions.socketTimeout;\n if (requestOptions.allowRedirects != null) {\n this._allowRedirects = requestOptions.allowRedirects;\n }\n if (requestOptions.allowRedirectDowngrade != null) {\n this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade;\n }\n if (requestOptions.maxRedirects != null) {\n this._maxRedirects = Math.max(requestOptions.maxRedirects, 0);\n }\n if (requestOptions.keepAlive != null) {\n this._keepAlive = requestOptions.keepAlive;\n }\n if (requestOptions.allowRetries != null) {\n this._allowRetries = requestOptions.allowRetries;\n }\n if (requestOptions.maxRetries != null) {\n this._maxRetries = requestOptions.maxRetries;\n }\n }\n }\n options(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('OPTIONS', requestUrl, null, additionalHeaders || {});\n });\n }\n get(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('GET', requestUrl, null, additionalHeaders || {});\n });\n }\n del(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('DELETE', requestUrl, null, additionalHeaders || {});\n });\n }\n post(requestUrl, data, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('POST', requestUrl, data, additionalHeaders || {});\n });\n }\n patch(requestUrl, data, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('PATCH', requestUrl, data, additionalHeaders || {});\n });\n }\n put(requestUrl, data, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('PUT', requestUrl, data, additionalHeaders || {});\n });\n }\n head(requestUrl, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request('HEAD', requestUrl, null, additionalHeaders || {});\n });\n }\n sendStream(verb, requestUrl, stream, additionalHeaders) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.request(verb, requestUrl, stream, additionalHeaders);\n });\n }\n /**\n * Gets a typed object from an endpoint\n * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise\n */\n getJson(requestUrl, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n const res = yield this.get(requestUrl, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n postJson(requestUrl, obj, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const data = JSON.stringify(obj, null, 2);\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);\n const res = yield this.post(requestUrl, data, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n putJson(requestUrl, obj, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const data = JSON.stringify(obj, null, 2);\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);\n const res = yield this.put(requestUrl, data, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n patchJson(requestUrl, obj, additionalHeaders = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const data = JSON.stringify(obj, null, 2);\n additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);\n additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);\n const res = yield this.patch(requestUrl, data, additionalHeaders);\n return this._processResponse(res, this.requestOptions);\n });\n }\n /**\n * Makes a raw http request.\n * All other methods such as get, post, patch, and request ultimately call this.\n * Prefer get, del, post and patch\n */\n request(verb, requestUrl, data, headers) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._disposed) {\n throw new Error('Client has already been disposed.');\n }\n const parsedUrl = new URL(requestUrl);\n let info = this._prepareRequest(verb, parsedUrl, headers);\n // Only perform retries on reads since writes may not be idempotent.\n const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb)\n ? this._maxRetries + 1\n : 1;\n let numTries = 0;\n let response;\n do {\n response = yield this.requestRaw(info, data);\n // Check if it's an authentication challenge\n if (response &&\n response.message &&\n response.message.statusCode === HttpCodes.Unauthorized) {\n let authenticationHandler;\n for (const handler of this.handlers) {\n if (handler.canHandleAuthentication(response)) {\n authenticationHandler = handler;\n break;\n }\n }\n if (authenticationHandler) {\n return authenticationHandler.handleAuthentication(this, info, data);\n }\n else {\n // We have received an unauthorized response but have no handlers to handle it.\n // Let the response return to the caller.\n return response;\n }\n }\n let redirectsRemaining = this._maxRedirects;\n while (response.message.statusCode &&\n HttpRedirectCodes.includes(response.message.statusCode) &&\n this._allowRedirects &&\n redirectsRemaining > 0) {\n const redirectUrl = response.message.headers['location'];\n if (!redirectUrl) {\n // if there's no location to redirect to, we won't\n break;\n }\n const parsedRedirectUrl = new URL(redirectUrl);\n if (parsedUrl.protocol === 'https:' &&\n parsedUrl.protocol !== parsedRedirectUrl.protocol &&\n !this._allowRedirectDowngrade) {\n throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.');\n }\n // we need to finish reading the response before reassigning response\n // which will leak the open socket.\n yield response.readBody();\n // strip authorization header if redirected to a different hostname\n if (parsedRedirectUrl.hostname !== parsedUrl.hostname) {\n for (const header in headers) {\n // header names are case insensitive\n if (header.toLowerCase() === 'authorization') {\n delete headers[header];\n }\n }\n }\n // let's make the request with the new redirectUrl\n info = this._prepareRequest(verb, parsedRedirectUrl, headers);\n response = yield this.requestRaw(info, data);\n redirectsRemaining--;\n }\n if (!response.message.statusCode ||\n !HttpResponseRetryCodes.includes(response.message.statusCode)) {\n // If not a retry code, return immediately instead of retrying\n return response;\n }\n numTries += 1;\n if (numTries < maxTries) {\n yield response.readBody();\n yield this._performExponentialBackoff(numTries);\n }\n } while (numTries < maxTries);\n return response;\n });\n }\n /**\n * Needs to be called if keepAlive is set to true in request options.\n */\n dispose() {\n if (this._agent) {\n this._agent.destroy();\n }\n this._disposed = true;\n }\n /**\n * Raw request.\n * @param info\n * @param data\n */\n requestRaw(info, data) {\n return __awaiter(this, void 0, void 0, function* () {\n return new Promise((resolve, reject) => {\n function callbackForResult(err, res) {\n if (err) {\n reject(err);\n }\n else if (!res) {\n // If `err` is not passed, then `res` must be passed.\n reject(new Error('Unknown error'));\n }\n else {\n resolve(res);\n }\n }\n this.requestRawWithCallback(info, data, callbackForResult);\n });\n });\n }\n /**\n * Raw request with callback.\n * @param info\n * @param data\n * @param onResult\n */\n requestRawWithCallback(info, data, onResult) {\n if (typeof data === 'string') {\n if (!info.options.headers) {\n info.options.headers = {};\n }\n info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8');\n }\n let callbackCalled = false;\n function handleResult(err, res) {\n if (!callbackCalled) {\n callbackCalled = true;\n onResult(err, res);\n }\n }\n const req = info.httpModule.request(info.options, (msg) => {\n const res = new HttpClientResponse(msg);\n handleResult(undefined, res);\n });\n let socket;\n req.on('socket', sock => {\n socket = sock;\n });\n // If we ever get disconnected, we want the socket to timeout eventually\n req.setTimeout(this._socketTimeout || 3 * 60000, () => {\n if (socket) {\n socket.end();\n }\n handleResult(new Error(`Request timeout: ${info.options.path}`));\n });\n req.on('error', function (err) {\n // err has statusCode property\n // res should have headers\n handleResult(err);\n });\n if (data && typeof data === 'string') {\n req.write(data, 'utf8');\n }\n if (data && typeof data !== 'string') {\n data.on('close', function () {\n req.end();\n });\n data.pipe(req);\n }\n else {\n req.end();\n }\n }\n /**\n * Gets an http agent. This function is useful when you need an http agent that handles\n * routing through a proxy server - depending upon the url and proxy environment variables.\n * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com\n */\n getAgent(serverUrl) {\n const parsedUrl = new URL(serverUrl);\n return this._getAgent(parsedUrl);\n }\n _prepareRequest(method, requestUrl, headers) {\n const info = {};\n info.parsedUrl = requestUrl;\n const usingSsl = info.parsedUrl.protocol === 'https:';\n info.httpModule = usingSsl ? https : http;\n const defaultPort = usingSsl ? 443 : 80;\n info.options = {};\n info.options.host = info.parsedUrl.hostname;\n info.options.port = info.parsedUrl.port\n ? parseInt(info.parsedUrl.port)\n : defaultPort;\n info.options.path =\n (info.parsedUrl.pathname || '') + (info.parsedUrl.search || '');\n info.options.method = method;\n info.options.headers = this._mergeHeaders(headers);\n if (this.userAgent != null) {\n info.options.headers['user-agent'] = this.userAgent;\n }\n info.options.agent = this._getAgent(info.parsedUrl);\n // gives handlers an opportunity to participate\n if (this.handlers) {\n for (const handler of this.handlers) {\n handler.prepareRequest(info.options);\n }\n }\n return info;\n }\n _mergeHeaders(headers) {\n if (this.requestOptions && this.requestOptions.headers) {\n return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {}));\n }\n return lowercaseKeys(headers || {});\n }\n _getExistingOrDefaultHeader(additionalHeaders, header, _default) {\n let clientHeader;\n if (this.requestOptions && this.requestOptions.headers) {\n clientHeader = lowercaseKeys(this.requestOptions.headers)[header];\n }\n return additionalHeaders[header] || clientHeader || _default;\n }\n _getAgent(parsedUrl) {\n let agent;\n const proxyUrl = pm.getProxyUrl(parsedUrl);\n const useProxy = proxyUrl && proxyUrl.hostname;\n if (this._keepAlive && useProxy) {\n agent = this._proxyAgent;\n }\n if (this._keepAlive && !useProxy) {\n agent = this._agent;\n }\n // if agent is already assigned use that agent.\n if (agent) {\n return agent;\n }\n const usingSsl = parsedUrl.protocol === 'https:';\n let maxSockets = 100;\n if (this.requestOptions) {\n maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets;\n }\n // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis.\n if (proxyUrl && proxyUrl.hostname) {\n const agentOptions = {\n maxSockets,\n keepAlive: this._keepAlive,\n proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && {\n proxyAuth: `${proxyUrl.username}:${proxyUrl.password}`\n })), { host: proxyUrl.hostname, port: proxyUrl.port })\n };\n let tunnelAgent;\n const overHttps = proxyUrl.protocol === 'https:';\n if (usingSsl) {\n tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp;\n }\n else {\n tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp;\n }\n agent = tunnelAgent(agentOptions);\n this._proxyAgent = agent;\n }\n // if reusing agent across request and tunneling agent isn't assigned create a new agent\n if (this._keepAlive && !agent) {\n const options = { keepAlive: this._keepAlive, maxSockets };\n agent = usingSsl ? new https.Agent(options) : new http.Agent(options);\n this._agent = agent;\n }\n // if not using private agent and tunnel agent isn't setup then use global agent\n if (!agent) {\n agent = usingSsl ? https.globalAgent : http.globalAgent;\n }\n if (usingSsl && this._ignoreSslError) {\n // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process\n // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options\n // we have to cast it to any and change it directly\n agent.options = Object.assign(agent.options || {}, {\n rejectUnauthorized: false\n });\n }\n return agent;\n }\n _performExponentialBackoff(retryNumber) {\n return __awaiter(this, void 0, void 0, function* () {\n retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber);\n const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber);\n return new Promise(resolve => setTimeout(() => resolve(), ms));\n });\n }\n _processResponse(res, options) {\n return __awaiter(this, void 0, void 0, function* () {\n return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {\n const statusCode = res.message.statusCode || 0;\n const response = {\n statusCode,\n result: null,\n headers: {}\n };\n // not found leads to null obj returned\n if (statusCode === HttpCodes.NotFound) {\n resolve(response);\n }\n // get the result from the body\n function dateTimeDeserializer(key, value) {\n if (typeof value === 'string') {\n const a = new Date(value);\n if (!isNaN(a.valueOf())) {\n return a;\n }\n }\n return value;\n }\n let obj;\n let contents;\n try {\n contents = yield res.readBody();\n if (contents && contents.length > 0) {\n if (options && options.deserializeDates) {\n obj = JSON.parse(contents, dateTimeDeserializer);\n }\n else {\n obj = JSON.parse(contents);\n }\n response.result = obj;\n }\n response.headers = res.message.headers;\n }\n catch (err) {\n // Invalid resource (contents not json); leaving result obj null\n }\n // note that 3xx redirects are handled by the http layer.\n if (statusCode > 299) {\n let msg;\n // if exception/error in body, attempt to get better error\n if (obj && obj.message) {\n msg = obj.message;\n }\n else if (contents && contents.length > 0) {\n // it may be the case that the exception is in the body message as string\n msg = contents;\n }\n else {\n msg = `Failed request: (${statusCode})`;\n }\n const err = new HttpClientError(msg, statusCode);\n err.result = response.result;\n reject(err);\n }\n else {\n resolve(response);\n }\n }));\n });\n }\n}\nexports.HttpClient = HttpClient;\nconst lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {});\n//# sourceMappingURL=index.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.checkBypass = exports.getProxyUrl = void 0;\nfunction getProxyUrl(reqUrl) {\n const usingSsl = reqUrl.protocol === 'https:';\n if (checkBypass(reqUrl)) {\n return undefined;\n }\n const proxyVar = (() => {\n if (usingSsl) {\n return process.env['https_proxy'] || process.env['HTTPS_PROXY'];\n }\n else {\n return process.env['http_proxy'] || process.env['HTTP_PROXY'];\n }\n })();\n if (proxyVar) {\n return new URL(proxyVar);\n }\n else {\n return undefined;\n }\n}\nexports.getProxyUrl = getProxyUrl;\nfunction checkBypass(reqUrl) {\n if (!reqUrl.hostname) {\n return false;\n }\n const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';\n if (!noProxy) {\n return false;\n }\n // Determine the request port\n let reqPort;\n if (reqUrl.port) {\n reqPort = Number(reqUrl.port);\n }\n else if (reqUrl.protocol === 'http:') {\n reqPort = 80;\n }\n else if (reqUrl.protocol === 'https:') {\n reqPort = 443;\n }\n // Format the request hostname and hostname with port\n const upperReqHosts = [reqUrl.hostname.toUpperCase()];\n if (typeof reqPort === 'number') {\n upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`);\n }\n // Compare request host against noproxy\n for (const upperNoProxyItem of noProxy\n .split(',')\n .map(x => x.trim().toUpperCase())\n .filter(x => x)) {\n if (upperReqHosts.some(x => x === upperNoProxyItem)) {\n return true;\n }\n }\n return false;\n}\nexports.checkBypass = checkBypass;\n//# sourceMappingURL=proxy.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar _a;\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rename = exports.readlink = exports.readdir = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0;\nconst fs = __importStar(require(\"fs\"));\nconst path = __importStar(require(\"path\"));\n_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink;\nexports.IS_WINDOWS = process.platform === 'win32';\nfunction exists(fsPath) {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n yield exports.stat(fsPath);\n }\n catch (err) {\n if (err.code === 'ENOENT') {\n return false;\n }\n throw err;\n }\n return true;\n });\n}\nexports.exists = exists;\nfunction isDirectory(fsPath, useStat = false) {\n return __awaiter(this, void 0, void 0, function* () {\n const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath);\n return stats.isDirectory();\n });\n}\nexports.isDirectory = isDirectory;\n/**\n * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:\n * \\, \\hello, \\\\hello\\share, C:, and C:\\hello (and corresponding alternate separator cases).\n */\nfunction isRooted(p) {\n p = normalizeSeparators(p);\n if (!p) {\n throw new Error('isRooted() parameter \"p\" cannot be empty');\n }\n if (exports.IS_WINDOWS) {\n return (p.startsWith('\\\\') || /^[A-Z]:/i.test(p) // e.g. \\ or \\hello or \\\\hello\n ); // e.g. C: or C:\\hello\n }\n return p.startsWith('/');\n}\nexports.isRooted = isRooted;\n/**\n * Best effort attempt to determine whether a file exists and is executable.\n * @param filePath file path to check\n * @param extensions additional file extensions to try\n * @return if file exists and is executable, returns the file path. otherwise empty string.\n */\nfunction tryGetExecutablePath(filePath, extensions) {\n return __awaiter(this, void 0, void 0, function* () {\n let stats = undefined;\n try {\n // test file exists\n stats = yield exports.stat(filePath);\n }\n catch (err) {\n if (err.code !== 'ENOENT') {\n // eslint-disable-next-line no-console\n console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);\n }\n }\n if (stats && stats.isFile()) {\n if (exports.IS_WINDOWS) {\n // on Windows, test for valid extension\n const upperExt = path.extname(filePath).toUpperCase();\n if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) {\n return filePath;\n }\n }\n else {\n if (isUnixExecutable(stats)) {\n return filePath;\n }\n }\n }\n // try each extension\n const originalFilePath = filePath;\n for (const extension of extensions) {\n filePath = originalFilePath + extension;\n stats = undefined;\n try {\n stats = yield exports.stat(filePath);\n }\n catch (err) {\n if (err.code !== 'ENOENT') {\n // eslint-disable-next-line no-console\n console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);\n }\n }\n if (stats && stats.isFile()) {\n if (exports.IS_WINDOWS) {\n // preserve the case of the actual file (since an extension was appended)\n try {\n const directory = path.dirname(filePath);\n const upperName = path.basename(filePath).toUpperCase();\n for (const actualName of yield exports.readdir(directory)) {\n if (upperName === actualName.toUpperCase()) {\n filePath = path.join(directory, actualName);\n break;\n }\n }\n }\n catch (err) {\n // eslint-disable-next-line no-console\n console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`);\n }\n return filePath;\n }\n else {\n if (isUnixExecutable(stats)) {\n return filePath;\n }\n }\n }\n }\n return '';\n });\n}\nexports.tryGetExecutablePath = tryGetExecutablePath;\nfunction normalizeSeparators(p) {\n p = p || '';\n if (exports.IS_WINDOWS) {\n // convert slashes on Windows\n p = p.replace(/\\//g, '\\\\');\n // remove redundant slashes\n return p.replace(/\\\\\\\\+/g, '\\\\');\n }\n // remove redundant slashes\n return p.replace(/\\/\\/+/g, '/');\n}\n// on Mac/Linux, test the execute bit\n// R W X R W X R W X\n// 256 128 64 32 16 8 4 2 1\nfunction isUnixExecutable(stats) {\n return ((stats.mode & 1) > 0 ||\n ((stats.mode & 8) > 0 && stats.gid === process.getgid()) ||\n ((stats.mode & 64) > 0 && stats.uid === process.getuid()));\n}\n// Get the path of cmd.exe in windows\nfunction getCmdPath() {\n var _a;\n return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`;\n}\nexports.getCmdPath = getCmdPath;\n//# sourceMappingURL=io-util.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0;\nconst assert_1 = require(\"assert\");\nconst childProcess = __importStar(require(\"child_process\"));\nconst path = __importStar(require(\"path\"));\nconst util_1 = require(\"util\");\nconst ioUtil = __importStar(require(\"./io-util\"));\nconst exec = util_1.promisify(childProcess.exec);\nconst execFile = util_1.promisify(childProcess.execFile);\n/**\n * Copies a file or folder.\n * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js\n *\n * @param source source path\n * @param dest destination path\n * @param options optional. See CopyOptions.\n */\nfunction cp(source, dest, options = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n const { force, recursive, copySourceDirectory } = readCopyOptions(options);\n const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null;\n // Dest is an existing file, but not forcing\n if (destStat && destStat.isFile() && !force) {\n return;\n }\n // If dest is an existing directory, should copy inside.\n const newDest = destStat && destStat.isDirectory() && copySourceDirectory\n ? path.join(dest, path.basename(source))\n : dest;\n if (!(yield ioUtil.exists(source))) {\n throw new Error(`no such file or directory: ${source}`);\n }\n const sourceStat = yield ioUtil.stat(source);\n if (sourceStat.isDirectory()) {\n if (!recursive) {\n throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`);\n }\n else {\n yield cpDirRecursive(source, newDest, 0, force);\n }\n }\n else {\n if (path.relative(source, newDest) === '') {\n // a file cannot be copied to itself\n throw new Error(`'${newDest}' and '${source}' are the same file`);\n }\n yield copyFile(source, newDest, force);\n }\n });\n}\nexports.cp = cp;\n/**\n * Moves a path.\n *\n * @param source source path\n * @param dest destination path\n * @param options optional. See MoveOptions.\n */\nfunction mv(source, dest, options = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n if (yield ioUtil.exists(dest)) {\n let destExists = true;\n if (yield ioUtil.isDirectory(dest)) {\n // If dest is directory copy src into dest\n dest = path.join(dest, path.basename(source));\n destExists = yield ioUtil.exists(dest);\n }\n if (destExists) {\n if (options.force == null || options.force) {\n yield rmRF(dest);\n }\n else {\n throw new Error('Destination already exists');\n }\n }\n }\n yield mkdirP(path.dirname(dest));\n yield ioUtil.rename(source, dest);\n });\n}\nexports.mv = mv;\n/**\n * Remove a path recursively with force\n *\n * @param inputPath path to remove\n */\nfunction rmRF(inputPath) {\n return __awaiter(this, void 0, void 0, function* () {\n if (ioUtil.IS_WINDOWS) {\n // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another\n // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.\n // Check for invalid characters\n // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file\n if (/[*\"<>|]/.test(inputPath)) {\n throw new Error('File path must not contain `*`, `\"`, `<`, `>` or `|` on Windows');\n }\n try {\n const cmdPath = ioUtil.getCmdPath();\n if (yield ioUtil.isDirectory(inputPath, true)) {\n yield exec(`${cmdPath} /s /c \"rd /s /q \"%inputPath%\"\"`, {\n env: { inputPath }\n });\n }\n else {\n yield exec(`${cmdPath} /s /c \"del /f /a \"%inputPath%\"\"`, {\n env: { inputPath }\n });\n }\n }\n catch (err) {\n // if you try to delete a file that doesn't exist, desired result is achieved\n // other errors are valid\n if (err.code !== 'ENOENT')\n throw err;\n }\n // Shelling out fails to remove a symlink folder with missing source, this unlink catches that\n try {\n yield ioUtil.unlink(inputPath);\n }\n catch (err) {\n // if you try to delete a file that doesn't exist, desired result is achieved\n // other errors are valid\n if (err.code !== 'ENOENT')\n throw err;\n }\n }\n else {\n let isDir = false;\n try {\n isDir = yield ioUtil.isDirectory(inputPath);\n }\n catch (err) {\n // if you try to delete a file that doesn't exist, desired result is achieved\n // other errors are valid\n if (err.code !== 'ENOENT')\n throw err;\n return;\n }\n if (isDir) {\n yield execFile(`rm`, [`-rf`, `${inputPath}`]);\n }\n else {\n yield ioUtil.unlink(inputPath);\n }\n }\n });\n}\nexports.rmRF = rmRF;\n/**\n * Make a directory. Creates the full path with folders in between\n * Will throw if it fails\n *\n * @param fsPath path to create\n * @returns Promise\n */\nfunction mkdirP(fsPath) {\n return __awaiter(this, void 0, void 0, function* () {\n assert_1.ok(fsPath, 'a path argument must be provided');\n yield ioUtil.mkdir(fsPath, { recursive: true });\n });\n}\nexports.mkdirP = mkdirP;\n/**\n * Returns path of a tool had the tool actually been invoked. Resolves via paths.\n * If you check and the tool does not exist, it will throw.\n *\n * @param tool name of the tool\n * @param check whether to check if tool exists\n * @returns Promise path to tool\n */\nfunction which(tool, check) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!tool) {\n throw new Error(\"parameter 'tool' is required\");\n }\n // recursive when check=true\n if (check) {\n const result = yield which(tool, false);\n if (!result) {\n if (ioUtil.IS_WINDOWS) {\n throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);\n }\n else {\n throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`);\n }\n }\n return result;\n }\n const matches = yield findInPath(tool);\n if (matches && matches.length > 0) {\n return matches[0];\n }\n return '';\n });\n}\nexports.which = which;\n/**\n * Returns a list of all occurrences of the given tool on the system path.\n *\n * @returns Promise the paths of the tool\n */\nfunction findInPath(tool) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!tool) {\n throw new Error(\"parameter 'tool' is required\");\n }\n // build the list of extensions to try\n const extensions = [];\n if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) {\n for (const extension of process.env['PATHEXT'].split(path.delimiter)) {\n if (extension) {\n extensions.push(extension);\n }\n }\n }\n // if it's rooted, return it if exists. otherwise return empty.\n if (ioUtil.isRooted(tool)) {\n const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions);\n if (filePath) {\n return [filePath];\n }\n return [];\n }\n // if any path separators, return empty\n if (tool.includes(path.sep)) {\n return [];\n }\n // build the list of directories\n //\n // Note, technically \"where\" checks the current directory on Windows. From a toolkit perspective,\n // it feels like we should not do this. Checking the current directory seems like more of a use\n // case of a shell, and the which() function exposed by the toolkit should strive for consistency\n // across platforms.\n const directories = [];\n if (process.env.PATH) {\n for (const p of process.env.PATH.split(path.delimiter)) {\n if (p) {\n directories.push(p);\n }\n }\n }\n // find all matches\n const matches = [];\n for (const directory of directories) {\n const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions);\n if (filePath) {\n matches.push(filePath);\n }\n }\n return matches;\n });\n}\nexports.findInPath = findInPath;\nfunction readCopyOptions(options) {\n const force = options.force == null ? true : options.force;\n const recursive = Boolean(options.recursive);\n const copySourceDirectory = options.copySourceDirectory == null\n ? true\n : Boolean(options.copySourceDirectory);\n return { force, recursive, copySourceDirectory };\n}\nfunction cpDirRecursive(sourceDir, destDir, currentDepth, force) {\n return __awaiter(this, void 0, void 0, function* () {\n // Ensure there is not a run away recursive copy\n if (currentDepth >= 255)\n return;\n currentDepth++;\n yield mkdirP(destDir);\n const files = yield ioUtil.readdir(sourceDir);\n for (const fileName of files) {\n const srcFile = `${sourceDir}/${fileName}`;\n const destFile = `${destDir}/${fileName}`;\n const srcFileStat = yield ioUtil.lstat(srcFile);\n if (srcFileStat.isDirectory()) {\n // Recurse\n yield cpDirRecursive(srcFile, destFile, currentDepth, force);\n }\n else {\n yield copyFile(srcFile, destFile, force);\n }\n }\n // Change the mode for the newly created directory\n yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode);\n });\n}\n// Buffered file copy\nfunction copyFile(srcFile, destFile, force) {\n return __awaiter(this, void 0, void 0, function* () {\n if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) {\n // unlink/re-link it\n try {\n yield ioUtil.lstat(destFile);\n yield ioUtil.unlink(destFile);\n }\n catch (e) {\n // Try to override file permission\n if (e.code === 'EPERM') {\n yield ioUtil.chmod(destFile, '0666');\n yield ioUtil.unlink(destFile);\n }\n // other errors = it doesn't exist, no work to do\n }\n // Copy over symlink\n const symlinkFull = yield ioUtil.readlink(srcFile);\n yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null);\n }\n else if (!(yield ioUtil.exists(destFile)) || force) {\n yield ioUtil.copyFile(srcFile, destFile);\n }\n });\n}\n//# sourceMappingURL=io.js.map","module.exports = require('./lib/tunnel');\n","'use strict';\n\nvar net = require('net');\nvar tls = require('tls');\nvar http = require('http');\nvar https = require('https');\nvar events = require('events');\nvar assert = require('assert');\nvar util = require('util');\n\n\nexports.httpOverHttp = httpOverHttp;\nexports.httpsOverHttp = httpsOverHttp;\nexports.httpOverHttps = httpOverHttps;\nexports.httpsOverHttps = httpsOverHttps;\n\n\nfunction httpOverHttp(options) {\n var agent = new TunnelingAgent(options);\n agent.request = http.request;\n return agent;\n}\n\nfunction httpsOverHttp(options) {\n var agent = new TunnelingAgent(options);\n agent.request = http.request;\n agent.createSocket = createSecureSocket;\n agent.defaultPort = 443;\n return agent;\n}\n\nfunction httpOverHttps(options) {\n var agent = new TunnelingAgent(options);\n agent.request = https.request;\n return agent;\n}\n\nfunction httpsOverHttps(options) {\n var agent = new TunnelingAgent(options);\n agent.request = https.request;\n agent.createSocket = createSecureSocket;\n agent.defaultPort = 443;\n return agent;\n}\n\n\nfunction TunnelingAgent(options) {\n var self = this;\n self.options = options || {};\n self.proxyOptions = self.options.proxy || {};\n self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets;\n self.requests = [];\n self.sockets = [];\n\n self.on('free', function onFree(socket, host, port, localAddress) {\n var options = toOptions(host, port, localAddress);\n for (var i = 0, len = self.requests.length; i < len; ++i) {\n var pending = self.requests[i];\n if (pending.host === options.host && pending.port === options.port) {\n // Detect the request to connect same origin server,\n // reuse the connection.\n self.requests.splice(i, 1);\n pending.request.onSocket(socket);\n return;\n }\n }\n socket.destroy();\n self.removeSocket(socket);\n });\n}\nutil.inherits(TunnelingAgent, events.EventEmitter);\n\nTunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) {\n var self = this;\n var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress));\n\n if (self.sockets.length >= this.maxSockets) {\n // We are over limit so we'll add it to the queue.\n self.requests.push(options);\n return;\n }\n\n // If we are under maxSockets create a new one.\n self.createSocket(options, function(socket) {\n socket.on('free', onFree);\n socket.on('close', onCloseOrRemove);\n socket.on('agentRemove', onCloseOrRemove);\n req.onSocket(socket);\n\n function onFree() {\n self.emit('free', socket, options);\n }\n\n function onCloseOrRemove(err) {\n self.removeSocket(socket);\n socket.removeListener('free', onFree);\n socket.removeListener('close', onCloseOrRemove);\n socket.removeListener('agentRemove', onCloseOrRemove);\n }\n });\n};\n\nTunnelingAgent.prototype.createSocket = function createSocket(options, cb) {\n var self = this;\n var placeholder = {};\n self.sockets.push(placeholder);\n\n var connectOptions = mergeOptions({}, self.proxyOptions, {\n method: 'CONNECT',\n path: options.host + ':' + options.port,\n agent: false,\n headers: {\n host: options.host + ':' + options.port\n }\n });\n if (options.localAddress) {\n connectOptions.localAddress = options.localAddress;\n }\n if (connectOptions.proxyAuth) {\n connectOptions.headers = connectOptions.headers || {};\n connectOptions.headers['Proxy-Authorization'] = 'Basic ' +\n new Buffer(connectOptions.proxyAuth).toString('base64');\n }\n\n debug('making CONNECT request');\n var connectReq = self.request(connectOptions);\n connectReq.useChunkedEncodingByDefault = false; // for v0.6\n connectReq.once('response', onResponse); // for v0.6\n connectReq.once('upgrade', onUpgrade); // for v0.6\n connectReq.once('connect', onConnect); // for v0.7 or later\n connectReq.once('error', onError);\n connectReq.end();\n\n function onResponse(res) {\n // Very hacky. This is necessary to avoid http-parser leaks.\n res.upgrade = true;\n }\n\n function onUpgrade(res, socket, head) {\n // Hacky.\n process.nextTick(function() {\n onConnect(res, socket, head);\n });\n }\n\n function onConnect(res, socket, head) {\n connectReq.removeAllListeners();\n socket.removeAllListeners();\n\n if (res.statusCode !== 200) {\n debug('tunneling socket could not be established, statusCode=%d',\n res.statusCode);\n socket.destroy();\n var error = new Error('tunneling socket could not be established, ' +\n 'statusCode=' + res.statusCode);\n error.code = 'ECONNRESET';\n options.request.emit('error', error);\n self.removeSocket(placeholder);\n return;\n }\n if (head.length > 0) {\n debug('got illegal response body from proxy');\n socket.destroy();\n var error = new Error('got illegal response body from proxy');\n error.code = 'ECONNRESET';\n options.request.emit('error', error);\n self.removeSocket(placeholder);\n return;\n }\n debug('tunneling connection has established');\n self.sockets[self.sockets.indexOf(placeholder)] = socket;\n return cb(socket);\n }\n\n function onError(cause) {\n connectReq.removeAllListeners();\n\n debug('tunneling socket could not be established, cause=%s\\n',\n cause.message, cause.stack);\n var error = new Error('tunneling socket could not be established, ' +\n 'cause=' + cause.message);\n error.code = 'ECONNRESET';\n options.request.emit('error', error);\n self.removeSocket(placeholder);\n }\n};\n\nTunnelingAgent.prototype.removeSocket = function removeSocket(socket) {\n var pos = this.sockets.indexOf(socket)\n if (pos === -1) {\n return;\n }\n this.sockets.splice(pos, 1);\n\n var pending = this.requests.shift();\n if (pending) {\n // If we have pending requests and a socket gets closed a new one\n // needs to be created to take over in the pool for the one that closed.\n this.createSocket(pending, function(socket) {\n pending.request.onSocket(socket);\n });\n }\n};\n\nfunction createSecureSocket(options, cb) {\n var self = this;\n TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {\n var hostHeader = options.request.getHeader('host');\n var tlsOptions = mergeOptions({}, self.options, {\n socket: socket,\n servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host\n });\n\n // 0 is dummy port for v0.6\n var secureSocket = tls.connect(0, tlsOptions);\n self.sockets[self.sockets.indexOf(socket)] = secureSocket;\n cb(secureSocket);\n });\n}\n\n\nfunction toOptions(host, port, localAddress) {\n if (typeof host === 'string') { // since v0.10\n return {\n host: host,\n port: port,\n localAddress: localAddress\n };\n }\n return host; // for v0.11 or later\n}\n\nfunction mergeOptions(target) {\n for (var i = 1, len = arguments.length; i < len; ++i) {\n var overrides = arguments[i];\n if (typeof overrides === 'object') {\n var keys = Object.keys(overrides);\n for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {\n var k = keys[j];\n if (overrides[k] !== undefined) {\n target[k] = overrides[k];\n }\n }\n }\n }\n return target;\n}\n\n\nvar debug;\nif (process.env.NODE_DEBUG && /\\btunnel\\b/.test(process.env.NODE_DEBUG)) {\n debug = function() {\n var args = Array.prototype.slice.call(arguments);\n if (typeof args[0] === 'string') {\n args[0] = 'TUNNEL: ' + args[0];\n } else {\n args.unshift('TUNNEL:');\n }\n console.error.apply(console, args);\n }\n} else {\n debug = function() {};\n}\nexports.debug = debug; // for test\n","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"v1\", {\n enumerable: true,\n get: function () {\n return _v.default;\n }\n});\nObject.defineProperty(exports, \"v3\", {\n enumerable: true,\n get: function () {\n return _v2.default;\n }\n});\nObject.defineProperty(exports, \"v4\", {\n enumerable: true,\n get: function () {\n return _v3.default;\n }\n});\nObject.defineProperty(exports, \"v5\", {\n enumerable: true,\n get: function () {\n return _v4.default;\n }\n});\nObject.defineProperty(exports, \"NIL\", {\n enumerable: true,\n get: function () {\n return _nil.default;\n }\n});\nObject.defineProperty(exports, \"version\", {\n enumerable: true,\n get: function () {\n return _version.default;\n }\n});\nObject.defineProperty(exports, \"validate\", {\n enumerable: true,\n get: function () {\n return _validate.default;\n }\n});\nObject.defineProperty(exports, \"stringify\", {\n enumerable: true,\n get: function () {\n return _stringify.default;\n }\n});\nObject.defineProperty(exports, \"parse\", {\n enumerable: true,\n get: function () {\n return _parse.default;\n }\n});\n\nvar _v = _interopRequireDefault(require(\"./v1.js\"));\n\nvar _v2 = _interopRequireDefault(require(\"./v3.js\"));\n\nvar _v3 = _interopRequireDefault(require(\"./v4.js\"));\n\nvar _v4 = _interopRequireDefault(require(\"./v5.js\"));\n\nvar _nil = _interopRequireDefault(require(\"./nil.js\"));\n\nvar _version = _interopRequireDefault(require(\"./version.js\"));\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nvar _parse = _interopRequireDefault(require(\"./parse.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _crypto = _interopRequireDefault(require(\"crypto\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction md5(bytes) {\n if (Array.isArray(bytes)) {\n bytes = Buffer.from(bytes);\n } else if (typeof bytes === 'string') {\n bytes = Buffer.from(bytes, 'utf8');\n }\n\n return _crypto.default.createHash('md5').update(bytes).digest();\n}\n\nvar _default = md5;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\nvar _default = '00000000-0000-0000-0000-000000000000';\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction parse(uuid) {\n if (!(0, _validate.default)(uuid)) {\n throw TypeError('Invalid UUID');\n }\n\n let v;\n const arr = new Uint8Array(16); // Parse ########-....-....-....-............\n\n arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24;\n arr[1] = v >>> 16 & 0xff;\n arr[2] = v >>> 8 & 0xff;\n arr[3] = v & 0xff; // Parse ........-####-....-....-............\n\n arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8;\n arr[5] = v & 0xff; // Parse ........-....-####-....-............\n\n arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8;\n arr[7] = v & 0xff; // Parse ........-....-....-####-............\n\n arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8;\n arr[9] = v & 0xff; // Parse ........-....-....-....-############\n // (Use \"/\" to avoid 32-bit truncation when bit-shifting high-order bytes)\n\n arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff;\n arr[11] = v / 0x100000000 & 0xff;\n arr[12] = v >>> 24 & 0xff;\n arr[13] = v >>> 16 & 0xff;\n arr[14] = v >>> 8 & 0xff;\n arr[15] = v & 0xff;\n return arr;\n}\n\nvar _default = parse;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\nvar _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = rng;\n\nvar _crypto = _interopRequireDefault(require(\"crypto\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate\n\nlet poolPtr = rnds8Pool.length;\n\nfunction rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n _crypto.default.randomFillSync(rnds8Pool);\n\n poolPtr = 0;\n }\n\n return rnds8Pool.slice(poolPtr, poolPtr += 16);\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _crypto = _interopRequireDefault(require(\"crypto\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction sha1(bytes) {\n if (Array.isArray(bytes)) {\n bytes = Buffer.from(bytes);\n } else if (typeof bytes === 'string') {\n bytes = Buffer.from(bytes, 'utf8');\n }\n\n return _crypto.default.createHash('sha1').update(bytes).digest();\n}\n\nvar _default = sha1;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nconst byteToHex = [];\n\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).substr(1));\n}\n\nfunction stringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n\n if (!(0, _validate.default)(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n\n return uuid;\n}\n\nvar _default = stringify;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _rng = _interopRequireDefault(require(\"./rng.js\"));\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// **`v1()` - Generate time-based UUID**\n//\n// Inspired by https://github.com/LiosK/UUID.js\n// and http://docs.python.org/library/uuid.html\nlet _nodeId;\n\nlet _clockseq; // Previous uuid creation time\n\n\nlet _lastMSecs = 0;\nlet _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details\n\nfunction v1(options, buf, offset) {\n let i = buf && offset || 0;\n const b = buf || new Array(16);\n options = options || {};\n let node = options.node || _nodeId;\n let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not\n // specified. We do this lazily to minimize issues related to insufficient\n // system entropy. See #189\n\n if (node == null || clockseq == null) {\n const seedBytes = options.random || (options.rng || _rng.default)();\n\n if (node == null) {\n // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];\n }\n\n if (clockseq == null) {\n // Per 4.2.2, randomize (14 bit) clockseq\n clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;\n }\n } // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n\n\n let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock\n // cycle to simulate higher resolution clock\n\n let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)\n\n const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression\n\n if (dt < 0 && options.clockseq === undefined) {\n clockseq = clockseq + 1 & 0x3fff;\n } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n // time interval\n\n\n if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n nsecs = 0;\n } // Per 4.2.1.2 Throw error if too many uuids are requested\n\n\n if (nsecs >= 10000) {\n throw new Error(\"uuid.v1(): Can't create more than 10M uuids/sec\");\n }\n\n _lastMSecs = msecs;\n _lastNSecs = nsecs;\n _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n\n msecs += 12219292800000; // `time_low`\n\n const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n b[i++] = tl >>> 24 & 0xff;\n b[i++] = tl >>> 16 & 0xff;\n b[i++] = tl >>> 8 & 0xff;\n b[i++] = tl & 0xff; // `time_mid`\n\n const tmh = msecs / 0x100000000 * 10000 & 0xfffffff;\n b[i++] = tmh >>> 8 & 0xff;\n b[i++] = tmh & 0xff; // `time_high_and_version`\n\n b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n\n b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n\n b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low`\n\n b[i++] = clockseq & 0xff; // `node`\n\n for (let n = 0; n < 6; ++n) {\n b[i + n] = node[n];\n }\n\n return buf || (0, _stringify.default)(b);\n}\n\nvar _default = v1;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _v = _interopRequireDefault(require(\"./v35.js\"));\n\nvar _md = _interopRequireDefault(require(\"./md5.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst v3 = (0, _v.default)('v3', 0x30, _md.default);\nvar _default = v3;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = _default;\nexports.URL = exports.DNS = void 0;\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nvar _parse = _interopRequireDefault(require(\"./parse.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction stringToBytes(str) {\n str = unescape(encodeURIComponent(str)); // UTF8 escape\n\n const bytes = [];\n\n for (let i = 0; i < str.length; ++i) {\n bytes.push(str.charCodeAt(i));\n }\n\n return bytes;\n}\n\nconst DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';\nexports.DNS = DNS;\nconst URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';\nexports.URL = URL;\n\nfunction _default(name, version, hashfunc) {\n function generateUUID(value, namespace, buf, offset) {\n if (typeof value === 'string') {\n value = stringToBytes(value);\n }\n\n if (typeof namespace === 'string') {\n namespace = (0, _parse.default)(namespace);\n }\n\n if (namespace.length !== 16) {\n throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');\n } // Compute hash of namespace and value, Per 4.3\n // Future: Use spread syntax when supported on all platforms, e.g. `bytes =\n // hashfunc([...namespace, ... value])`\n\n\n let bytes = new Uint8Array(16 + value.length);\n bytes.set(namespace);\n bytes.set(value, namespace.length);\n bytes = hashfunc(bytes);\n bytes[6] = bytes[6] & 0x0f | version;\n bytes[8] = bytes[8] & 0x3f | 0x80;\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = bytes[i];\n }\n\n return buf;\n }\n\n return (0, _stringify.default)(bytes);\n } // Function#name is not settable on some platforms (#270)\n\n\n try {\n generateUUID.name = name; // eslint-disable-next-line no-empty\n } catch (err) {} // For CommonJS default export support\n\n\n generateUUID.DNS = DNS;\n generateUUID.URL = URL;\n return generateUUID;\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _rng = _interopRequireDefault(require(\"./rng.js\"));\n\nvar _stringify = _interopRequireDefault(require(\"./stringify.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction v4(options, buf, offset) {\n options = options || {};\n\n const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\n\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n\n return buf;\n }\n\n return (0, _stringify.default)(rnds);\n}\n\nvar _default = v4;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _v = _interopRequireDefault(require(\"./v35.js\"));\n\nvar _sha = _interopRequireDefault(require(\"./sha1.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst v5 = (0, _v.default)('v5', 0x50, _sha.default);\nvar _default = v5;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _regex = _interopRequireDefault(require(\"./regex.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction validate(uuid) {\n return typeof uuid === 'string' && _regex.default.test(uuid);\n}\n\nvar _default = validate;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _validate = _interopRequireDefault(require(\"./validate.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction version(uuid) {\n if (!(0, _validate.default)(uuid)) {\n throw TypeError('Invalid UUID');\n }\n\n return parseInt(uuid.substr(14, 1), 16);\n}\n\nvar _default = version;\nexports.default = _default;","module.exports = require(\"assert\");","module.exports = require(\"child_process\");","module.exports = require(\"crypto\");","module.exports = require(\"events\");","module.exports = require(\"fs\");","module.exports = require(\"http\");","module.exports = require(\"https\");","module.exports = require(\"net\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"string_decoder\");","module.exports = require(\"timers\");","module.exports = require(\"tls\");","module.exports = require(\"util\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tvar threw = true;\n\ttry {\n\t\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\t\tthrew = false;\n\t} finally {\n\t\tif(threw) delete __webpack_module_cache__[moduleId];\n\t}\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","\nif (typeof __webpack_require__ !== 'undefined') __webpack_require__.ab = __dirname + \"/\";","const core = require(\"@actions/core\");\nconst sweep = require(\"./sweep\");\n\nsweep.sweep().catch(core.setFailed);\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/.github/actions/cargo-sweep/dist/post/sourcemap-register.js b/.github/actions/cargo-sweep/dist/post/sourcemap-register.js deleted file mode 100644 index 466141d4069ca..0000000000000 --- a/.github/actions/cargo-sweep/dist/post/sourcemap-register.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var e={650:e=>{var r=Object.prototype.toString;var n=typeof Buffer.alloc==="function"&&typeof Buffer.allocUnsafe==="function"&&typeof Buffer.from==="function";function isArrayBuffer(e){return r.call(e).slice(8,-1)==="ArrayBuffer"}function fromArrayBuffer(e,r,t){r>>>=0;var o=e.byteLength-r;if(o<0){throw new RangeError("'offset' is out of bounds")}if(t===undefined){t=o}else{t>>>=0;if(t>o){throw new RangeError("'length' is out of bounds")}}return n?Buffer.from(e.slice(r,r+t)):new Buffer(new Uint8Array(e.slice(r,r+t)))}function fromString(e,r){if(typeof r!=="string"||r===""){r="utf8"}if(!Buffer.isEncoding(r)){throw new TypeError('"encoding" must be a valid string encoding')}return n?Buffer.from(e,r):new Buffer(e,r)}function bufferFrom(e,r,t){if(typeof e==="number"){throw new TypeError('"value" argument must not be a number')}if(isArrayBuffer(e)){return fromArrayBuffer(e,r,t)}if(typeof e==="string"){return fromString(e,r)}return n?Buffer.from(e):new Buffer(e)}e.exports=bufferFrom},274:(e,r,n)=>{var t=n(339);var o=Object.prototype.hasOwnProperty;var i=typeof Map!=="undefined";function ArraySet(){this._array=[];this._set=i?new Map:Object.create(null)}ArraySet.fromArray=function ArraySet_fromArray(e,r){var n=new ArraySet;for(var t=0,o=e.length;t=0){return r}}else{var n=t.toSetString(e);if(o.call(this._set,n)){return this._set[n]}}throw new Error('"'+e+'" is not in the set.')};ArraySet.prototype.at=function ArraySet_at(e){if(e>=0&&e{var t=n(190);var o=5;var i=1<>1;return r?-n:n}r.encode=function base64VLQ_encode(e){var r="";var n;var i=toVLQSigned(e);do{n=i&a;i>>>=o;if(i>0){n|=u}r+=t.encode(n)}while(i>0);return r};r.decode=function base64VLQ_decode(e,r,n){var i=e.length;var s=0;var l=0;var c,p;do{if(r>=i){throw new Error("Expected more digits in base 64 VLQ value.")}p=t.decode(e.charCodeAt(r++));if(p===-1){throw new Error("Invalid base64 digit: "+e.charAt(r-1))}c=!!(p&u);p&=a;s=s+(p<{var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");r.encode=function(e){if(0<=e&&e{r.GREATEST_LOWER_BOUND=1;r.LEAST_UPPER_BOUND=2;function recursiveSearch(e,n,t,o,i,a){var u=Math.floor((n-e)/2)+e;var s=i(t,o[u],true);if(s===0){return u}else if(s>0){if(n-u>1){return recursiveSearch(u,n,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return n1){return recursiveSearch(e,u,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return u}else{return e<0?-1:e}}}r.search=function search(e,n,t,o){if(n.length===0){return-1}var i=recursiveSearch(-1,n.length,e,n,t,o||r.GREATEST_LOWER_BOUND);if(i<0){return-1}while(i-1>=0){if(t(n[i],n[i-1],true)!==0){break}--i}return i}},680:(e,r,n)=>{var t=n(339);function generatedPositionAfter(e,r){var n=e.generatedLine;var o=r.generatedLine;var i=e.generatedColumn;var a=r.generatedColumn;return o>n||o==n&&a>=i||t.compareByGeneratedPositionsInflated(e,r)<=0}function MappingList(){this._array=[];this._sorted=true;this._last={generatedLine:-1,generatedColumn:0}}MappingList.prototype.unsortedForEach=function MappingList_forEach(e,r){this._array.forEach(e,r)};MappingList.prototype.add=function MappingList_add(e){if(generatedPositionAfter(this._last,e)){this._last=e;this._array.push(e)}else{this._sorted=false;this._array.push(e)}};MappingList.prototype.toArray=function MappingList_toArray(){if(!this._sorted){this._array.sort(t.compareByGeneratedPositionsInflated);this._sorted=true}return this._array};r.H=MappingList},758:(e,r)=>{function swap(e,r,n){var t=e[r];e[r]=e[n];e[n]=t}function randomIntInRange(e,r){return Math.round(e+Math.random()*(r-e))}function doQuickSort(e,r,n,t){if(n{var t;var o=n(339);var i=n(345);var a=n(274).I;var u=n(449);var s=n(758).U;function SourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}return n.sections!=null?new IndexedSourceMapConsumer(n,r):new BasicSourceMapConsumer(n,r)}SourceMapConsumer.fromSourceMap=function(e,r){return BasicSourceMapConsumer.fromSourceMap(e,r)};SourceMapConsumer.prototype._version=3;SourceMapConsumer.prototype.__generatedMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_generatedMappings",{configurable:true,enumerable:true,get:function(){if(!this.__generatedMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__generatedMappings}});SourceMapConsumer.prototype.__originalMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_originalMappings",{configurable:true,enumerable:true,get:function(){if(!this.__originalMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__originalMappings}});SourceMapConsumer.prototype._charIsMappingSeparator=function SourceMapConsumer_charIsMappingSeparator(e,r){var n=e.charAt(r);return n===";"||n===","};SourceMapConsumer.prototype._parseMappings=function SourceMapConsumer_parseMappings(e,r){throw new Error("Subclasses must implement _parseMappings")};SourceMapConsumer.GENERATED_ORDER=1;SourceMapConsumer.ORIGINAL_ORDER=2;SourceMapConsumer.GREATEST_LOWER_BOUND=1;SourceMapConsumer.LEAST_UPPER_BOUND=2;SourceMapConsumer.prototype.eachMapping=function SourceMapConsumer_eachMapping(e,r,n){var t=r||null;var i=n||SourceMapConsumer.GENERATED_ORDER;var a;switch(i){case SourceMapConsumer.GENERATED_ORDER:a=this._generatedMappings;break;case SourceMapConsumer.ORIGINAL_ORDER:a=this._originalMappings;break;default:throw new Error("Unknown order of iteration.")}var u=this.sourceRoot;a.map((function(e){var r=e.source===null?null:this._sources.at(e.source);r=o.computeSourceURL(u,r,this._sourceMapURL);return{source:r,generatedLine:e.generatedLine,generatedColumn:e.generatedColumn,originalLine:e.originalLine,originalColumn:e.originalColumn,name:e.name===null?null:this._names.at(e.name)}}),this).forEach(e,t)};SourceMapConsumer.prototype.allGeneratedPositionsFor=function SourceMapConsumer_allGeneratedPositionsFor(e){var r=o.getArg(e,"line");var n={source:o.getArg(e,"source"),originalLine:r,originalColumn:o.getArg(e,"column",0)};n.source=this._findSourceIndex(n.source);if(n.source<0){return[]}var t=[];var a=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,i.LEAST_UPPER_BOUND);if(a>=0){var u=this._originalMappings[a];if(e.column===undefined){var s=u.originalLine;while(u&&u.originalLine===s){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}else{var l=u.originalColumn;while(u&&u.originalLine===r&&u.originalColumn==l){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}}return t};r.SourceMapConsumer=SourceMapConsumer;function BasicSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sources");var u=o.getArg(n,"names",[]);var s=o.getArg(n,"sourceRoot",null);var l=o.getArg(n,"sourcesContent",null);var c=o.getArg(n,"mappings");var p=o.getArg(n,"file",null);if(t!=this._version){throw new Error("Unsupported version: "+t)}if(s){s=o.normalize(s)}i=i.map(String).map(o.normalize).map((function(e){return s&&o.isAbsolute(s)&&o.isAbsolute(e)?o.relative(s,e):e}));this._names=a.fromArray(u.map(String),true);this._sources=a.fromArray(i,true);this._absoluteSources=this._sources.toArray().map((function(e){return o.computeSourceURL(s,e,r)}));this.sourceRoot=s;this.sourcesContent=l;this._mappings=c;this._sourceMapURL=r;this.file=p}BasicSourceMapConsumer.prototype=Object.create(SourceMapConsumer.prototype);BasicSourceMapConsumer.prototype.consumer=SourceMapConsumer;BasicSourceMapConsumer.prototype._findSourceIndex=function(e){var r=e;if(this.sourceRoot!=null){r=o.relative(this.sourceRoot,r)}if(this._sources.has(r)){return this._sources.indexOf(r)}var n;for(n=0;n1){v.source=l+_[1];l+=_[1];v.originalLine=i+_[2];i=v.originalLine;v.originalLine+=1;v.originalColumn=a+_[3];a=v.originalColumn;if(_.length>4){v.name=c+_[4];c+=_[4]}}m.push(v);if(typeof v.originalLine==="number"){d.push(v)}}}s(m,o.compareByGeneratedPositionsDeflated);this.__generatedMappings=m;s(d,o.compareByOriginalPositions);this.__originalMappings=d};BasicSourceMapConsumer.prototype._findMapping=function SourceMapConsumer_findMapping(e,r,n,t,o,a){if(e[n]<=0){throw new TypeError("Line must be greater than or equal to 1, got "+e[n])}if(e[t]<0){throw new TypeError("Column must be greater than or equal to 0, got "+e[t])}return i.search(e,r,o,a)};BasicSourceMapConsumer.prototype.computeColumnSpans=function SourceMapConsumer_computeColumnSpans(){for(var e=0;e=0){var t=this._generatedMappings[n];if(t.generatedLine===r.generatedLine){var i=o.getArg(t,"source",null);if(i!==null){i=this._sources.at(i);i=o.computeSourceURL(this.sourceRoot,i,this._sourceMapURL)}var a=o.getArg(t,"name",null);if(a!==null){a=this._names.at(a)}return{source:i,line:o.getArg(t,"originalLine",null),column:o.getArg(t,"originalColumn",null),name:a}}}return{source:null,line:null,column:null,name:null}};BasicSourceMapConsumer.prototype.hasContentsOfAllSources=function BasicSourceMapConsumer_hasContentsOfAllSources(){if(!this.sourcesContent){return false}return this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some((function(e){return e==null}))};BasicSourceMapConsumer.prototype.sourceContentFor=function SourceMapConsumer_sourceContentFor(e,r){if(!this.sourcesContent){return null}var n=this._findSourceIndex(e);if(n>=0){return this.sourcesContent[n]}var t=e;if(this.sourceRoot!=null){t=o.relative(this.sourceRoot,t)}var i;if(this.sourceRoot!=null&&(i=o.urlParse(this.sourceRoot))){var a=t.replace(/^file:\/\//,"");if(i.scheme=="file"&&this._sources.has(a)){return this.sourcesContent[this._sources.indexOf(a)]}if((!i.path||i.path=="/")&&this._sources.has("/"+t)){return this.sourcesContent[this._sources.indexOf("/"+t)]}}if(r){return null}else{throw new Error('"'+t+'" is not in the SourceMap.')}};BasicSourceMapConsumer.prototype.generatedPositionFor=function SourceMapConsumer_generatedPositionFor(e){var r=o.getArg(e,"source");r=this._findSourceIndex(r);if(r<0){return{line:null,column:null,lastColumn:null}}var n={source:r,originalLine:o.getArg(e,"line"),originalColumn:o.getArg(e,"column")};var t=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,o.getArg(e,"bias",SourceMapConsumer.GREATEST_LOWER_BOUND));if(t>=0){var i=this._originalMappings[t];if(i.source===n.source){return{line:o.getArg(i,"generatedLine",null),column:o.getArg(i,"generatedColumn",null),lastColumn:o.getArg(i,"lastGeneratedColumn",null)}}}return{line:null,column:null,lastColumn:null}};t=BasicSourceMapConsumer;function IndexedSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sections");if(t!=this._version){throw new Error("Unsupported version: "+t)}this._sources=new a;this._names=new a;var u={line:-1,column:0};this._sections=i.map((function(e){if(e.url){throw new Error("Support for url field in sections not implemented.")}var n=o.getArg(e,"offset");var t=o.getArg(n,"line");var i=o.getArg(n,"column");if(t{var t=n(449);var o=n(339);var i=n(274).I;var a=n(680).H;function SourceMapGenerator(e){if(!e){e={}}this._file=o.getArg(e,"file",null);this._sourceRoot=o.getArg(e,"sourceRoot",null);this._skipValidation=o.getArg(e,"skipValidation",false);this._sources=new i;this._names=new i;this._mappings=new a;this._sourcesContents=null}SourceMapGenerator.prototype._version=3;SourceMapGenerator.fromSourceMap=function SourceMapGenerator_fromSourceMap(e){var r=e.sourceRoot;var n=new SourceMapGenerator({file:e.file,sourceRoot:r});e.eachMapping((function(e){var t={generated:{line:e.generatedLine,column:e.generatedColumn}};if(e.source!=null){t.source=e.source;if(r!=null){t.source=o.relative(r,t.source)}t.original={line:e.originalLine,column:e.originalColumn};if(e.name!=null){t.name=e.name}}n.addMapping(t)}));e.sources.forEach((function(t){var i=t;if(r!==null){i=o.relative(r,t)}if(!n._sources.has(i)){n._sources.add(i)}var a=e.sourceContentFor(t);if(a!=null){n.setSourceContent(t,a)}}));return n};SourceMapGenerator.prototype.addMapping=function SourceMapGenerator_addMapping(e){var r=o.getArg(e,"generated");var n=o.getArg(e,"original",null);var t=o.getArg(e,"source",null);var i=o.getArg(e,"name",null);if(!this._skipValidation){this._validateMapping(r,n,t,i)}if(t!=null){t=String(t);if(!this._sources.has(t)){this._sources.add(t)}}if(i!=null){i=String(i);if(!this._names.has(i)){this._names.add(i)}}this._mappings.add({generatedLine:r.line,generatedColumn:r.column,originalLine:n!=null&&n.line,originalColumn:n!=null&&n.column,source:t,name:i})};SourceMapGenerator.prototype.setSourceContent=function SourceMapGenerator_setSourceContent(e,r){var n=e;if(this._sourceRoot!=null){n=o.relative(this._sourceRoot,n)}if(r!=null){if(!this._sourcesContents){this._sourcesContents=Object.create(null)}this._sourcesContents[o.toSetString(n)]=r}else if(this._sourcesContents){delete this._sourcesContents[o.toSetString(n)];if(Object.keys(this._sourcesContents).length===0){this._sourcesContents=null}}};SourceMapGenerator.prototype.applySourceMap=function SourceMapGenerator_applySourceMap(e,r,n){var t=r;if(r==null){if(e.file==null){throw new Error("SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, "+'or the source map\'s "file" property. Both were omitted.')}t=e.file}var a=this._sourceRoot;if(a!=null){t=o.relative(a,t)}var u=new i;var s=new i;this._mappings.unsortedForEach((function(r){if(r.source===t&&r.originalLine!=null){var i=e.originalPositionFor({line:r.originalLine,column:r.originalColumn});if(i.source!=null){r.source=i.source;if(n!=null){r.source=o.join(n,r.source)}if(a!=null){r.source=o.relative(a,r.source)}r.originalLine=i.line;r.originalColumn=i.column;if(i.name!=null){r.name=i.name}}}var l=r.source;if(l!=null&&!u.has(l)){u.add(l)}var c=r.name;if(c!=null&&!s.has(c)){s.add(c)}}),this);this._sources=u;this._names=s;e.sources.forEach((function(r){var t=e.sourceContentFor(r);if(t!=null){if(n!=null){r=o.join(n,r)}if(a!=null){r=o.relative(a,r)}this.setSourceContent(r,t)}}),this)};SourceMapGenerator.prototype._validateMapping=function SourceMapGenerator_validateMapping(e,r,n,t){if(r&&typeof r.line!=="number"&&typeof r.column!=="number"){throw new Error("original.line and original.column are not numbers -- you probably meant to omit "+"the original mapping entirely and only map the generated position. If so, pass "+"null for the original mapping instead of an object with empty or null values.")}if(e&&"line"in e&&"column"in e&&e.line>0&&e.column>=0&&!r&&!n&&!t){return}else if(e&&"line"in e&&"column"in e&&r&&"line"in r&&"column"in r&&e.line>0&&e.column>=0&&r.line>0&&r.column>=0&&n){return}else{throw new Error("Invalid mapping: "+JSON.stringify({generated:e,source:n,original:r,name:t}))}};SourceMapGenerator.prototype._serializeMappings=function SourceMapGenerator_serializeMappings(){var e=0;var r=1;var n=0;var i=0;var a=0;var u=0;var s="";var l;var c;var p;var f;var g=this._mappings.toArray();for(var h=0,d=g.length;h0){if(!o.compareByGeneratedPositionsInflated(c,g[h-1])){continue}l+=","}}l+=t.encode(c.generatedColumn-e);e=c.generatedColumn;if(c.source!=null){f=this._sources.indexOf(c.source);l+=t.encode(f-u);u=f;l+=t.encode(c.originalLine-1-i);i=c.originalLine-1;l+=t.encode(c.originalColumn-n);n=c.originalColumn;if(c.name!=null){p=this._names.indexOf(c.name);l+=t.encode(p-a);a=p}}s+=l}return s};SourceMapGenerator.prototype._generateSourcesContent=function SourceMapGenerator_generateSourcesContent(e,r){return e.map((function(e){if(!this._sourcesContents){return null}if(r!=null){e=o.relative(r,e)}var n=o.toSetString(e);return Object.prototype.hasOwnProperty.call(this._sourcesContents,n)?this._sourcesContents[n]:null}),this)};SourceMapGenerator.prototype.toJSON=function SourceMapGenerator_toJSON(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};if(this._file!=null){e.file=this._file}if(this._sourceRoot!=null){e.sourceRoot=this._sourceRoot}if(this._sourcesContents){e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)}return e};SourceMapGenerator.prototype.toString=function SourceMapGenerator_toString(){return JSON.stringify(this.toJSON())};r.h=SourceMapGenerator},351:(e,r,n)=>{var t;var o=n(591).h;var i=n(339);var a=/(\r?\n)/;var u=10;var s="$$$isSourceNode$$$";function SourceNode(e,r,n,t,o){this.children=[];this.sourceContents={};this.line=e==null?null:e;this.column=r==null?null:r;this.source=n==null?null:n;this.name=o==null?null:o;this[s]=true;if(t!=null)this.add(t)}SourceNode.fromStringWithSourceMap=function SourceNode_fromStringWithSourceMap(e,r,n){var t=new SourceNode;var o=e.split(a);var u=0;var shiftNextLine=function(){var e=getNextLine();var r=getNextLine()||"";return e+r;function getNextLine(){return u=0;r--){this.prepend(e[r])}}else if(e[s]||typeof e==="string"){this.children.unshift(e)}else{throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e)}return this};SourceNode.prototype.walk=function SourceNode_walk(e){var r;for(var n=0,t=this.children.length;n0){r=[];for(n=0;n{function getArg(e,r,n){if(r in e){return e[r]}else if(arguments.length===3){return n}else{throw new Error('"'+r+'" is a required argument.')}}r.getArg=getArg;var n=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;var t=/^data:.+\,.+$/;function urlParse(e){var r=e.match(n);if(!r){return null}return{scheme:r[1],auth:r[2],host:r[3],port:r[4],path:r[5]}}r.urlParse=urlParse;function urlGenerate(e){var r="";if(e.scheme){r+=e.scheme+":"}r+="//";if(e.auth){r+=e.auth+"@"}if(e.host){r+=e.host}if(e.port){r+=":"+e.port}if(e.path){r+=e.path}return r}r.urlGenerate=urlGenerate;function normalize(e){var n=e;var t=urlParse(e);if(t){if(!t.path){return e}n=t.path}var o=r.isAbsolute(n);var i=n.split(/\/+/);for(var a,u=0,s=i.length-1;s>=0;s--){a=i[s];if(a==="."){i.splice(s,1)}else if(a===".."){u++}else if(u>0){if(a===""){i.splice(s+1,u);u=0}else{i.splice(s,2);u--}}}n=i.join("/");if(n===""){n=o?"/":"."}if(t){t.path=n;return urlGenerate(t)}return n}r.normalize=normalize;function join(e,r){if(e===""){e="."}if(r===""){r="."}var n=urlParse(r);var o=urlParse(e);if(o){e=o.path||"/"}if(n&&!n.scheme){if(o){n.scheme=o.scheme}return urlGenerate(n)}if(n||r.match(t)){return r}if(o&&!o.host&&!o.path){o.host=r;return urlGenerate(o)}var i=r.charAt(0)==="/"?r:normalize(e.replace(/\/+$/,"")+"/"+r);if(o){o.path=i;return urlGenerate(o)}return i}r.join=join;r.isAbsolute=function(e){return e.charAt(0)==="/"||n.test(e)};function relative(e,r){if(e===""){e="."}e=e.replace(/\/$/,"");var n=0;while(r.indexOf(e+"/")!==0){var t=e.lastIndexOf("/");if(t<0){return r}e=e.slice(0,t);if(e.match(/^([^\/]+:\/)?\/*$/)){return r}++n}return Array(n+1).join("../")+r.substr(e.length+1)}r.relative=relative;var o=function(){var e=Object.create(null);return!("__proto__"in e)}();function identity(e){return e}function toSetString(e){if(isProtoString(e)){return"$"+e}return e}r.toSetString=o?identity:toSetString;function fromSetString(e){if(isProtoString(e)){return e.slice(1)}return e}r.fromSetString=o?identity:fromSetString;function isProtoString(e){if(!e){return false}var r=e.length;if(r<9){return false}if(e.charCodeAt(r-1)!==95||e.charCodeAt(r-2)!==95||e.charCodeAt(r-3)!==111||e.charCodeAt(r-4)!==116||e.charCodeAt(r-5)!==111||e.charCodeAt(r-6)!==114||e.charCodeAt(r-7)!==112||e.charCodeAt(r-8)!==95||e.charCodeAt(r-9)!==95){return false}for(var n=r-10;n>=0;n--){if(e.charCodeAt(n)!==36){return false}}return true}function compareByOriginalPositions(e,r,n){var t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0||n){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0){return t}t=e.generatedLine-r.generatedLine;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByOriginalPositions=compareByOriginalPositions;function compareByGeneratedPositionsDeflated(e,r,n){var t=e.generatedLine-r.generatedLine;if(t!==0){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0||n){return t}t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsDeflated=compareByGeneratedPositionsDeflated;function strcmp(e,r){if(e===r){return 0}if(e===null){return 1}if(r===null){return-1}if(e>r){return 1}return-1}function compareByGeneratedPositionsInflated(e,r){var n=e.generatedLine-r.generatedLine;if(n!==0){return n}n=e.generatedColumn-r.generatedColumn;if(n!==0){return n}n=strcmp(e.source,r.source);if(n!==0){return n}n=e.originalLine-r.originalLine;if(n!==0){return n}n=e.originalColumn-r.originalColumn;if(n!==0){return n}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsInflated=compareByGeneratedPositionsInflated;function parseSourceMapInput(e){return JSON.parse(e.replace(/^\)]}'[^\n]*\n/,""))}r.parseSourceMapInput=parseSourceMapInput;function computeSourceURL(e,r,n){r=r||"";if(e){if(e[e.length-1]!=="/"&&r[0]!=="/"){e+="/"}r=e+r}if(n){var t=urlParse(n);if(!t){throw new Error("sourceMapURL could not be parsed")}if(t.path){var o=t.path.lastIndexOf("/");if(o>=0){t.path=t.path.substring(0,o+1)}}r=join(urlGenerate(t),r)}return normalize(r)}r.computeSourceURL=computeSourceURL},997:(e,r,n)=>{n(591).h;r.SourceMapConsumer=n(952).SourceMapConsumer;n(351)},284:(e,r,n)=>{e=n.nmd(e);var t=n(997).SourceMapConsumer;var o=n(17);var i;try{i=n(147);if(!i.existsSync||!i.readFileSync){i=null}}catch(e){}var a=n(650);function dynamicRequire(e,r){return e.require(r)}var u=false;var s=false;var l=false;var c="auto";var p={};var f={};var g=/^data:application\/json[^,]+base64,/;var h=[];var d=[];function isInBrowser(){if(c==="browser")return true;if(c==="node")return false;return typeof window!=="undefined"&&typeof XMLHttpRequest==="function"&&!(window.require&&window.module&&window.process&&window.process.type==="renderer")}function hasGlobalProcessEventEmitter(){return typeof process==="object"&&process!==null&&typeof process.on==="function"}function globalProcessVersion(){if(typeof process==="object"&&process!==null){return process.version}else{return""}}function globalProcessStderr(){if(typeof process==="object"&&process!==null){return process.stderr}}function globalProcessExit(e){if(typeof process==="object"&&process!==null&&typeof process.exit==="function"){return process.exit(e)}}function handlerExec(e){return function(r){for(var n=0;n"}var n=this.getLineNumber();if(n!=null){r+=":"+n;var t=this.getColumnNumber();if(t){r+=":"+t}}}var o="";var i=this.getFunctionName();var a=true;var u=this.isConstructor();var s=!(this.isToplevel()||u);if(s){var l=this.getTypeName();if(l==="[object Object]"){l="null"}var c=this.getMethodName();if(i){if(l&&i.indexOf(l)!=0){o+=l+"."}o+=i;if(c&&i.indexOf("."+c)!=i.length-c.length-1){o+=" [as "+c+"]"}}else{o+=l+"."+(c||"")}}else if(u){o+="new "+(i||"")}else if(i){o+=i}else{o+=r;a=false}if(a){o+=" ("+r+")"}return o}function cloneCallSite(e){var r={};Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach((function(n){r[n]=/^(?:is|get)/.test(n)?function(){return e[n].call(e)}:e[n]}));r.toString=CallSiteToString;return r}function wrapCallSite(e,r){if(r===undefined){r={nextPosition:null,curPosition:null}}if(e.isNative()){r.curPosition=null;return e}var n=e.getFileName()||e.getScriptNameOrSourceURL();if(n){var t=e.getLineNumber();var o=e.getColumnNumber()-1;var i=/^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;var a=i.test(globalProcessVersion())?0:62;if(t===1&&o>a&&!isInBrowser()&&!e.isEval()){o-=a}var u=mapSourcePosition({source:n,line:t,column:o});r.curPosition=u;e=cloneCallSite(e);var s=e.getFunctionName;e.getFunctionName=function(){if(r.nextPosition==null){return s()}return r.nextPosition.name||s()};e.getFileName=function(){return u.source};e.getLineNumber=function(){return u.line};e.getColumnNumber=function(){return u.column+1};e.getScriptNameOrSourceURL=function(){return u.source};return e}var l=e.isEval()&&e.getEvalOrigin();if(l){l=mapEvalOrigin(l);e=cloneCallSite(e);e.getEvalOrigin=function(){return l};return e}return e}function prepareStackTrace(e,r){if(l){p={};f={}}var n=e.name||"Error";var t=e.message||"";var o=n+": "+t;var i={nextPosition:null,curPosition:null};var a=[];for(var u=r.length-1;u>=0;u--){a.push("\n at "+wrapCallSite(r[u],i));i.nextPosition=i.curPosition}i.curPosition=i.nextPosition=null;return o+a.reverse().join("")}function getErrorSource(e){var r=/\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(e.stack);if(r){var n=r[1];var t=+r[2];var o=+r[3];var a=p[n];if(!a&&i&&i.existsSync(n)){try{a=i.readFileSync(n,"utf8")}catch(e){a=""}}if(a){var u=a.split(/(?:\r\n|\r|\n)/)[t-1];if(u){return n+":"+t+"\n"+u+"\n"+new Array(o).join(" ")+"^"}}}return null}function printErrorAndExit(e){var r=getErrorSource(e);var n=globalProcessStderr();if(n&&n._handle&&n._handle.setBlocking){n._handle.setBlocking(true)}if(r){console.error();console.error(r)}console.error(e.stack);globalProcessExit(1)}function shimEmitUncaughtException(){var e=process.emit;process.emit=function(r){if(r==="uncaughtException"){var n=arguments[1]&&arguments[1].stack;var t=this.listeners(r).length>0;if(n&&!t){return printErrorAndExit(arguments[1])}}return e.apply(this,arguments)}}var S=h.slice(0);var _=d.slice(0);r.wrapCallSite=wrapCallSite;r.getErrorSource=getErrorSource;r.mapSourcePosition=mapSourcePosition;r.retrieveSourceMap=v;r.install=function(r){r=r||{};if(r.environment){c=r.environment;if(["node","browser","auto"].indexOf(c)===-1){throw new Error("environment "+c+" was unknown. Available options are {auto, browser, node}")}}if(r.retrieveFile){if(r.overrideRetrieveFile){h.length=0}h.unshift(r.retrieveFile)}if(r.retrieveSourceMap){if(r.overrideRetrieveSourceMap){d.length=0}d.unshift(r.retrieveSourceMap)}if(r.hookRequire&&!isInBrowser()){var n=dynamicRequire(e,"module");var t=n.prototype._compile;if(!t.__sourceMapSupport){n.prototype._compile=function(e,r){p[r]=e;f[r]=undefined;return t.call(this,e,r)};n.prototype._compile.__sourceMapSupport=true}}if(!l){l="emptyCacheBetweenOperations"in r?r.emptyCacheBetweenOperations:false}if(!u){u=true;Error.prepareStackTrace=prepareStackTrace}if(!s){var o="handleUncaughtExceptions"in r?r.handleUncaughtExceptions:true;try{var i=dynamicRequire(e,"worker_threads");if(i.isMainThread===false){o=false}}catch(e){}if(o&&hasGlobalProcessEventEmitter()){s=true;shimEmitUncaughtException()}}};r.resetRetrieveHandlers=function(){h.length=0;d.length=0;h=S.slice(0);d=_.slice(0);v=handlerExec(d);m=handlerExec(h)}},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")}};var r={};function __webpack_require__(n){var t=r[n];if(t!==undefined){return t.exports}var o=r[n]={id:n,loaded:false,exports:{}};var i=true;try{e[n](o,o.exports,__webpack_require__);i=false}finally{if(i)delete r[n]}o.loaded=true;return o.exports}(()=>{__webpack_require__.nmd=e=>{e.paths=[];if(!e.children)e.children=[];return e}})();if(typeof __webpack_require__!=="undefined")__webpack_require__.ab=__dirname+"/";var n={};(()=>{__webpack_require__(284).install()})();module.exports=n})(); \ No newline at end of file diff --git a/.github/actions/cargo-sweep/package.json b/.github/actions/cargo-sweep/package.json deleted file mode 100644 index e1c0cb5d220c1..0000000000000 --- a/.github/actions/cargo-sweep/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "cargo-sweep-action", - "private": true, - "version": "1.0.0", - "scripts": { - "build:main": "ncc build src/main.js -o dist/main --source-map", - "build:post": "ncc build src/post.js -o dist/post --source-map", - "prepare": "pnpm run build:main && pnpm run build:post", - "lint": "eslint src/", - "lint:prettier": "prettier -c . --cache --ignore-path=../../../.prettierignore" - }, - "dependencies": { - "@actions/core": "^1.10.0", - "@actions/exec": "^1.1.1" - }, - "devDependencies": { - "@turbo/eslint-config": "workspace:*", - "@vercel/ncc": "^0.36.0" - } -} diff --git a/.github/actions/cargo-sweep/src/main.js b/.github/actions/cargo-sweep/src/main.js deleted file mode 100644 index 436442c9d6cd2..0000000000000 --- a/.github/actions/cargo-sweep/src/main.js +++ /dev/null @@ -1,4 +0,0 @@ -const core = require("@actions/core"); -const sweep = require("./sweep"); - -sweep.storeTimestamp().catch(core.setFailed); diff --git a/.github/actions/cargo-sweep/src/post.js b/.github/actions/cargo-sweep/src/post.js deleted file mode 100644 index fe9fdb4835b00..0000000000000 --- a/.github/actions/cargo-sweep/src/post.js +++ /dev/null @@ -1,4 +0,0 @@ -const core = require("@actions/core"); -const sweep = require("./sweep"); - -sweep.sweep().catch(core.setFailed); diff --git a/.github/actions/cargo-sweep/src/sweep.js b/.github/actions/cargo-sweep/src/sweep.js deleted file mode 100644 index dd5850364c9e7..0000000000000 --- a/.github/actions/cargo-sweep/src/sweep.js +++ /dev/null @@ -1,29 +0,0 @@ -const core = require("@actions/core"); -const exec = require("@actions/exec"); - -async function runSweep(...args) { - // TODO(alexkirsz) A cargo change introduced a regression where cargo can't - // find the sweep binary. This is a temporary workaround until the fix is - // released. See: - // https://github.com/rust-lang/cargo/pull/11814 - await exec.exec("cargo-sweep", ["sweep", ...args]); -} - -async function storeTimestamp() { - await core.group("Storing timestamp to compare later", () => - runSweep("--stamp") - ); - - core.info("Timestamp stored in `sweep.timestamp`"); -} - -async function sweep() { - await core.group("Cleaning old build artifacts", () => runSweep("--file")); - - core.info("Removed old build artifacts."); -} - -module.exports = { - storeTimestamp, - sweep, -}; diff --git a/.github/actions/examples-tests/action.yml b/.github/actions/examples-tests/action.yml deleted file mode 100644 index 5f5a3690f580f..0000000000000 --- a/.github/actions/examples-tests/action.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: "Run Turbo Tests" -description: "Setup the environment and run Turbo tests" -inputs: - github-token: - description: "GitHub token for GitHub" - required: true - turbo-token: - description: "Turbo token for authentication" - required: true - turbo-team: - description: "Turbo team for authentication" - required: true - test-filter: - description: "Filter for the turbo run command" - required: true -runs: - using: "composite" - steps: - - name: Disable corepack - shell: bash - run: corepack disable - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ inputs.github-token }}" - node-version: "22" - - - name: Install Global Turbo - uses: ./.github/actions/install-global-turbo - - - name: Run Turbo Tests - shell: bash - run: | - turbo run test \ - --filter="${{ inputs.test-filter }}" \ - --continue \ - --token=${{ inputs.turbo-token }} \ - --team=${{ inputs.turbo-team }} \ - --env-mode=strict \ - --concurrency=1 diff --git a/.github/actions/install-global-turbo/action.yml b/.github/actions/install-global-turbo/action.yml deleted file mode 100644 index 43dd99a8324a9..0000000000000 --- a/.github/actions/install-global-turbo/action.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: "Install Global Turbo" -description: "Installs turbo globally. Expects Node and npm to already be installed" - -runs: - using: "composite" - steps: - - name: Install Turbo globally - shell: bash - run: | - VERSION=$(npm view turbo --json | jq -r '.versions | map(select(test("2."))) | last') - echo "Latest published version: $VERSION" - npm i -g turbo@$VERSION diff --git a/.github/actions/setup-capnproto/action.yml b/.github/actions/setup-capnproto/action.yml deleted file mode 100644 index 8bbd7ab85d8e7..0000000000000 --- a/.github/actions/setup-capnproto/action.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: "Setup Capnproto" -description: "Sets up capnproto for the current platform" - -runs: - using: "composite" - steps: - - name: "Setup capnproto for Linux" - if: runner.os == 'Linux' - shell: bash - run: sudo apt-get -y update && sudo apt-get install -y capnproto - - - name: "Setup capnproto for macos" - if: runner.os == 'macOS' - shell: bash - run: brew install capnp - - - name: "Setup capnproto for Windows" - if: runner.os == 'Windows' - shell: bash - run: choco install capnproto diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml deleted file mode 100644 index b117d02b0ea53..0000000000000 --- a/.github/actions/setup-node/action.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: "Turborepo Node.js Setup" -description: "Sets Node.js up for CI" -inputs: - enable-corepack: - description: "Control turning on corepack." - required: false - default: "true" - extra-flags: - description: "Extra flags to pass to the pnpm install." - required: false - default: "" - package-install: - description: "Don't run the install step." - required: false - default: "true" - node-version: - description: "Node version to install" - required: false - default: "18" - -runs: - using: "composite" - steps: - - name: Setup pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - cache: pnpm - - - name: Upgrade corepack - if: ${{ inputs.enable-corepack == 'true' && inputs.node-version == '16' }} - shell: bash - # Forcibly upgrade our available version of corepack. - # The bundled version in node 16 has known issues. - # Prepends the npm bin dir so that it is always first. - run: | - npm install --force --global corepack@latest - npm config get prefix >> $GITHUB_PATH - - - name: Configure corepack - if: ${{ inputs.enable-corepack == 'true' }} - shell: bash - run: corepack enable - - - name: pnpm install - id: install - if: ${{ inputs.package-install == 'true' }} - continue-on-error: true - shell: bash - run: pnpm install ${{ inputs.extra-flags }} - - - name: pnpm install (second try) - if: ${{ steps.install.outcome == 'failure' }} - shell: bash - run: pnpm install ${{ inputs.extra-flags }} diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml deleted file mode 100644 index 91b926b0daabe..0000000000000 --- a/.github/actions/setup-rust/action.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: "Turbo Rust Setup" -description: "Sets up the Rust toolchain for CI" -inputs: - targets: - description: "Comma-separated list of target triples to install for this toolchain" - required: false - github-token: - description: "GitHub token. You can pass secrets.GITHUB_TOKEN" - required: true - shared-cache-key: - description: "A cache key that is used instead of the automatic `job`-based key, and is stable over multiple jobs." - required: false - cache-key: - description: "An additional cache key that is added alongside the automatic `job`-based cache key and can be used to further differentiate jobs." - required: false - save-cache: - description: "Determiners whether the cache should be saved. If `false`, the cache is only restored." - required: false - default: "false" - -runs: - using: "composite" - steps: - - name: "Setup Rust toolchain" - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - target: ${{ inputs.targets }} - # needed to not make it override the defaults - rustflags: "" - # we want more specific settings - cache: false - - - name: "Install LLD (LLVM Linker) for Linux" - if: runner.os == 'Linux' - shell: bash - run: sudo apt-get -y update && sudo apt-get install -y lld - - - name: Set Up Protoc - id: set-up-protoc - continue-on-error: true - uses: arduino/setup-protoc@v3 - with: - version: "26.x" - repo-token: ${{ inputs.github-token }} - - - name: Set Up Protoc (second try) - if: steps.set-up-protoc.outcome == 'failure' - uses: arduino/setup-protoc@v3 - with: - version: "26.x" - repo-token: ${{ inputs.github-token }} - - - name: "Add cargo problem matchers" - shell: bash - run: echo "::add-matcher::${{ github.action_path }}/matchers.json" - - - uses: rui314/setup-mold@v1 - - - name: "Setup Rust Cache" - uses: Swatinem/rust-cache@v2 - with: - shared-key: ${{ inputs.shared-cache-key }} - key: ${{ inputs.cache-key }} - # the cache is huge and we only get 10gb max, so we only save on master - save-if: ${{ github.ref == 'refs/heads/main' && inputs.save-cache || 'false' }} - - - name: "Install cargo-sweep" - uses: taiki-e/install-action@v2 - env: - GITHUB_TOKEN: ${{ inputs.github-token }} - with: - tool: cargo-sweep@0.6.2,cargo-groups@0.1.9 - - - name: "Run cargo-sweep" - uses: ./.github/actions/cargo-sweep diff --git a/.github/actions/setup-rust/matchers.json b/.github/actions/setup-rust/matchers.json deleted file mode 100644 index ba9a4730e7d0c..0000000000000 --- a/.github/actions/setup-rust/matchers.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "problemMatcher": [ - { - "owner": "cargo-test", - "pattern": [ - { - "regexp": "^.*panicked\\s+at\\s+'(.*)',\\s+(.*):(\\d+):(\\d+)$", - "message": 1, - "file": 2, - "line": 3, - "column": 4 - } - ] - } - ] -} diff --git a/.github/actions/setup-turborepo-environment/action.yml b/.github/actions/setup-turborepo-environment/action.yml deleted file mode 100644 index d27fe0f42dd44..0000000000000 --- a/.github/actions/setup-turborepo-environment/action.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: "Setup Turborepo Environment" -description: "Sets up development environment for turborepo" -inputs: - github-token: - description: "GitHub token. You can pass secrets.GITHUB_TOKEN" - required: true - node-version: - description: Node version - required: false - default: "18" - -runs: - using: "composite" - steps: - - name: "Setup Node" - uses: ./.github/actions/setup-node - with: - extra-flags: --no-optional - node-version: ${{ inputs.node-version }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - - - name: "Setup Rust" - uses: ./.github/actions/setup-rust - with: - shared-cache-key: turborepo-debug-build - cache-key: ${{ inputs.target }} - save-cache: true - github-token: ${{ inputs.github-token }} - - - name: "Setup capnproto" - uses: ./.github/actions/setup-capnproto diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 6ead4ba303abb..0000000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,129 +0,0 @@ -# This file will create many PRs, one for each example. -# From what I can tell, we are forced into approaching it this way -# because of the many workspace roots. - -version: 2 -updates: - - package-ecosystem: "npm" - directory: "/examples/basic" - schedule: - interval: "weekly" - labels: - - "area: examples" - open-pull-requests-limit: 1 - versioning-strategy: "increase" - allow: - - dependency-type: "direct" - assignees: - - "anthonyshew" - groups: - basic: - patterns: - - "*" - update-types: - - "minor" - - - package-ecosystem: "npm" - directory: "/examples/kitchen-sink" - schedule: - interval: "weekly" - labels: - - "area: examples" - open-pull-requests-limit: 1 - versioning-strategy: "increase" - allow: - - dependency-type: "direct" - assignees: - - "anthonyshew" - groups: - kitchen-sink: - patterns: - - "*" - update-types: - - "minor" - ignore: - # Types are just...broken? - - dependency-name: "@types/express" - # Remix is behind on updating these peer deps and npm doesn't like it - - dependency-name: "react" - - dependency-name: "react-dom" - - dependency-name: "@types/react" - - dependency-name: "@types/react-dom" - # We can't upgrade versions of this due to npm - - dependency-name: "vite" - - - package-ecosystem: "npm" - directory: "/examples/non-monorepo" - schedule: - interval: "weekly" - labels: - - "area: examples" - open-pull-requests-limit: 1 - versioning-strategy: "increase" - allow: - - dependency-type: "direct" - assignees: - - "anthonyshew" - groups: - non-monorepo: - patterns: - - "*" - update-types: - - "minor" - - - package-ecosystem: "npm" - directory: "/examples/with-shell-commands" - schedule: - interval: "weekly" - labels: - - "area: examples" - open-pull-requests-limit: 1 - versioning-strategy: "increase" - allow: - - dependency-type: "direct" - assignees: - - "anthonyshew" - groups: - with-shell-commands: - patterns: - - "*" - update-types: - - "minor" - - - package-ecosystem: "npm" - directory: "/examples/with-svelte" - schedule: - interval: "weekly" - labels: - - "area: examples" - open-pull-requests-limit: 1 - versioning-strategy: "increase" - allow: - - dependency-type: "direct" - assignees: - - "anthonyshew" - groups: - with-svelte: - patterns: - - "*" - update-types: - - "minor" - - - package-ecosystem: "npm" - directory: "/examples/with-tailwind" - schedule: - interval: "weekly" - labels: - - "area: examples" - open-pull-requests-limit: 1 - versioning-strategy: "increase" - allow: - - dependency-type: "direct" - assignees: - - "anthonyshew" - groups: - with-tailwind: - patterns: - - "*" - update-types: - - "minor" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 8ca42ee13d13a..0000000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,12 +0,0 @@ -### Description - - - -### Testing Instructions - - diff --git a/.github/turbo-orchestrator.yml b/.github/turbo-orchestrator.yml deleted file mode 100644 index eba9f77a2cd0b..0000000000000 --- a/.github/turbo-orchestrator.yml +++ /dev/null @@ -1,89 +0,0 @@ -# Docs - -# Label Config - -# labeler: -# - settings: -# - codeOwnersPath: {PATH TO CODEOWNERS FILE (defaults to .github/CODEOWNERS)} -# - labels: -# - label: {YOUR LABEL NAME} -# condition: {AND (default) | OR} -# when: -# {TEST_FUNCTION}: {REGEX} -# ... -# ... - -#| Function Name | Description | -#| --------------------------- | -------------------------------------------------------------------------- | -#| `isAnyFilePathMatch` | Returns true if any filename in the PR diff matches the given regex | -#| `isPRBodyMatch` | Returns true if the PR description matches the given regex | -#| `isPRTitleMatch` | Returns true if the PR title matches the given regex | -#| `isPRAuthorMatch` | Returns true if the PR author matches the given regex | -#| `isPRAuthorCompanyMatch` | Returns true if the PR author's company matches the given regex | -#| `isAnyFileOwnedByMatch` | Returns true if any owner of a file in the PR diff matches the given regex | -#| `isNotAnyFilePathMatch` | The negation of `isAnyFilePathMatch` | -#| `isNotPRBodyMatch` | The negation of `isPRBodyMatch` | -#| `isNotPRTitleMatch` | The negation of `isPRTitleMatch` | -#| `isNotPRAuthorMatch` | The negation of `isPRAuthorMatch` | -#| `isNotPRAuthorCompanyMatch` | The negation of `isPRAuthorCompanyMatch` | -#| `isNotAnyFileOwnerByMatch` | The negation of `isAnyFileOwnedByMatch` | - -labeler: - labels: - # needs: triage when not any of the turborepo team - - label: "needs: triage" - when: - isNotPRAuthorMatch: "^(padmaia|anthonyshew|dimitropoulos|tknickman|chris-olszewski|NicholasLYang)$" - - # areas - - label: "area: ci" - when: - isAnyFilePathMatch: '^\.github\/(workflows|actions).*$' - - label: "area: examples" - when: - isAnyFilePathMatch: '^examples\/.*$' - - label: "area: docs" - when: - isAnyFilePathMatch: '^docs\/.*\.mdx$' - - label: "area: site" - when: - isAnyFilePathMatch: '^docs\/.*\.(?!mdx).*$' - - # packages - - label: "pkg: turbo-eslint" - when: - isAnyFilePathMatch: '^packages\/eslint-(plugin|config)-turbo\/.*$' - - label: "pkg: turbo-ignore" - when: - isAnyFilePathMatch: '^packages\/turbo-ignore\/.*$' - - label: "pkg: turbo-codemod" - when: - isAnyFilePathMatch: '^packages\/turbo-codemod\/.*$' - - label: "pkg: create-turbo" - when: - isAnyFilePathMatch: '^packages\/create-turbo\/.*$' - - label: "pkg: turbo-gen" - when: - isAnyFilePathMatch: '^packages\/turbo-gen\/.*$' - - label: "pkg: turbo-workspaces" - when: - isAnyFilePathMatch: '^packages\/turbo-workspaces\/.*$' - - label: "pkg: turbo-repository" - when: - isAnyFilePathMatch: '^packages\/turbo-repository\/.*$' - - label: "pkg: turbo-telemetry" - when: - isAnyFilePathMatch: '^packages\/turbo-telemetry\/.*$' - - # release - - label: "release: turborepo" - when: - isAnyFilePathMatch: '^version\.txt$' - isPRTitleMatch: '^release\(turborepo\):.*$' -events: - onPublish: - turbo: - - runWorkflow: bench-turborepo.yml - when: any - - runWorkflow: update-examples-on-release.yml - when: latest diff --git a/.github/turborepo-release.yml b/.github/turborepo-release.yml deleted file mode 100644 index 1b4a25a6987e4..0000000000000 --- a/.github/turborepo-release.yml +++ /dev/null @@ -1,36 +0,0 @@ -# Used to auto generate turborepo release notes - -changelog: - exclude: - labels: - - "area: ci" - - "release: turborepo" - categories: - - title: Docs - labels: - - "area: docs" - - "area: site" - - title: create-turbo - labels: - - "pkg: create-turbo" - - title: turbo-ignore - labels: - - "pkg: turbo-ignore" - - title: "@turbo/codemod" - labels: - - "pkg: turbo-codemod" - - title: "eslint" - labels: - - "pkg: turbo-eslint" - - title: "@turbo/repository" - labels: - - "pkg: turbo-repository" - - title: "@turbo/telemetry" - labels: - - "pkg: turbo-telemetry" - - title: Examples - labels: - - "area: examples" - - title: Changelog - labels: - - "*" diff --git a/.github/workflows/README.md b/.github/workflows/README.md deleted file mode 100644 index adba5244caadb..0000000000000 --- a/.github/workflows/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Rust workflows - -### cargo-install - -- [taiki-e/install-action](https://github.com/taiki-e/install-action) can only be used when pre built binaries are available. -- [baptiste0928/cargo-install](https://github.com/baptiste0928/cargo-install) will compile the binary and cache it. diff --git a/.github/workflows/bench-turborepo.yml b/.github/workflows/bench-turborepo.yml deleted file mode 100644 index c200b9041070a..0000000000000 --- a/.github/workflows/bench-turborepo.yml +++ /dev/null @@ -1,183 +0,0 @@ -name: Benchmark Turborepo - -on: - workflow_dispatch: - workflow_run: - # Make sure this matches the name of the workflow in ./github/workflows/turborepo-release.yml. - workflows: [Turborepo Release] - types: - - completed - push: - branches: - - main - paths: - - "cli/**" - - crates/turborepo*/** - # - "benchmark/**" (we don't need to run benchmarks when the benchmark changes, next push will capture it) - -jobs: - benchmark: - name: Benchmark turbo run - timeout-minutes: 60 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/setup-node - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - - name: Build - run: pnpm -F cli build:release - - - name: Run benchmarks - run: pnpm -F @turbo/benchmark benchmark - - - name: Save to Tinybird - run: | - curl \ - -i \ - -F "ndjson=@./packages/turbo-benchmark/tinybird.ndjson" \ - -X POST \ - -H 'Authorization: Bearer ${{ secrets.TINYBIRD_TOKEN }}' \ - 'https://api.us-east.tinybird.co/v0/datasources?format=ndjson&name=turbo_benchmarks&mode=append' - - time-to-first-task: - name: Benchmark TTFT - timeout-minutes: 60 - runs-on: ${{ matrix.os.runner }} - strategy: - fail-fast: false - matrix: - os: - - name: ubuntu - runner: ubuntu-latest - - name: macos - runner: macos-latest - - name: windows - runner: windows-latest - - steps: - - uses: actions/checkout@v4 - - name: Set filename for profile - id: filename - shell: bash - run: | - echo 'file_basename=${{ matrix.os.name }}' >> "$GITHUB_OUTPUT" - echo 'filename=${{ matrix.os.name }}.json' >> "$GITHUB_OUTPUT" - - - name: Display filename - shell: bash - run: echo "${{ steps.filename.outputs.filename }}" - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - - name: Build Turborepo from source - run: pnpm -F cli build:release - - - name: Run benchmarks - shell: bash - # ttft script will normalize filepath and place the profile in the benchmark directory. - run: pnpm -F @turbo/benchmark ttft "${{ steps.filename.outputs.filename }}" - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: profiles-${{ matrix.os.name }} # This name will be the folder each file gets downloaded to - if-no-files-found: error - # cwd is root of the repository, so we need the benchmark/ prefixed path - path: | - packages/turbo-benchmark/profiles/${{ steps.filename.outputs.filename }} - packages/turbo-benchmark/profiles/${{ steps.filename.outputs.file_basename }}-ttft.json - - # Send each of the profiles generated from the previous job to TinyBird - # We'll wait for all profiles to complete before sending. - send-to-tinybird: - name: Send to Tinybird - needs: [time-to-first-task] - runs-on: ubuntu-latest - env: - TINYBIRD_TOKEN: ${{secrets.TINYBIRD_TOKEN}} - - steps: - - uses: actions/checkout@v4 - - - name: Setup Node - uses: ./.github/actions/setup-node - - - name: Download profiles - uses: actions/download-artifact@v4 - with: - path: packages/turbo-benchmark/profiles/ - pattern: profiles-* - merge-multiple: true - - - name: Display TTFT Data - shell: bash - run: | - ls -al packages/turbo-benchmark/profiles - cat packages/turbo-benchmark/profiles/ubuntu-ttft.json - cat packages/turbo-benchmark/profiles/macos-ttft.json - cat packages/turbo-benchmark/profiles/windows-ttft.json - - - name: Send data to TinyBird - shell: bash - run: | - cd packages/turbo-benchmark - node -r esbuild-register ./src/ttft/tinybird.ts profiles/ubuntu-ttft.json ${{github.run_id}} - node -r esbuild-register ./src/ttft/tinybird.ts profiles/macos-ttft.json ${{github.run_id}} - node -r esbuild-register ./src/ttft/tinybird.ts profiles/windows-ttft.json ${{github.run_id}} - - send-to-slack: - name: Send to Slack - # Wait for send-to-tinybird so we can get aggregate data points - # before sending to slack. - needs: [send-to-tinybird] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup Node - uses: ./.github/actions/setup-node - - - name: Download profiles - uses: actions/download-artifact@v4 - with: - path: packages/turbo-benchmark/profiles/ - pattern: profiles-* - merge-multiple: true - - - name: Display TTFT Data - shell: bash - run: | - ls -al packages/turbo-benchmark/profiles - cat packages/turbo-benchmark/profiles/ubuntu-ttft.json - cat packages/turbo-benchmark/profiles/macos-ttft.json - cat packages/turbo-benchmark/profiles/windows-ttft.json - - # TODO: compare results to previous data and only post regressions - - name: Create Slack payload - shell: bash - env: - BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }} - TINYBIRD_TOKEN: ${{ secrets.TINYBIRD_TOKEN }} - run: | - cd packages/turbo-benchmark - node -r esbuild-register ./src/ttft/slack.ts ${{github.run_id}} - - - name: Debug Slack payload - shell: bash - run: cat packages/turbo-benchmark/slack-payload.json | jq - - - name: Send payload to slack - uses: slackapi/slack-github-action@v1.23.0 - with: - payload-file-path: "packages/turbo-benchmark/slack-payload.json" - env: - SLACK_WEBHOOK_URL: "${{ secrets.TURBOREPO_PERF_BENCHMARK_SLACK_WEBHOOK_URL }}" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index c920db365822d..0000000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Docs checks - -on: - pull_request: - paths: - - "docs/**" - - ".github/actions/validate-docs-links/**" - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - validate-docs-links: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - uses: ./.github/actions/setup-node - with: - node-version: 20 - - - name: Run link checker - run: cd docs && pnpm run check-links - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lint-pr-title.yml b/.github/workflows/lint-pr-title.yml deleted file mode 100644 index 1610f71bde4c9..0000000000000 --- a/.github/workflows/lint-pr-title.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Lint pull request title - -on: - pull_request_target: - types: - - opened - - edited - - synchronize - - reopened - -permissions: - pull-requests: read - -jobs: - main: - name: Validate PR title - runs-on: ubuntu-latest - steps: - - uses: amannn/action-semantic-pull-request@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - # Configure that a scope must always be provided. - requireScope: false - # Configure additional validation for the subject based on a regex. - # Ensures that the subject doesn't start with an uppercase character. - subjectPattern: ^[^A-Z].*$ - # If `subjectPattern` is configured, you can use this property to override - # the default error message that is shown when the pattern doesn't match. - # The variables `subject` and `title` can be used within the message. - subjectPatternError: | - The subject "{subject}" found in the pull request title "{title}" doesn't match the configured pattern. - Please ensure that the subject doesn't start with an uppercase character. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 99d9c4e19ec95..0000000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Lint -on: - push: - branches: [main] - pull_request: - paths: - - ".github/actions/**" - - .github/workflows/lint.yml - - "**/*.{yml,yaml,md,mdx,js,jsx,ts,tsx,json,toml,css}" - - pnpm-lock.yaml - - package.json - - "Cargo.**" - - "crates/**" - - ".cargo/**" - - rust-toolchain - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -permissions: - actions: write - contents: read - pull-requests: read - -jobs: - rust_lint: - name: Rust lints - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup Rust - uses: ./.github/actions/setup-rust - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - - name: Run cargo fmt check - run: | - cargo fmt --check - - - name: Check Cargo.toml formatting (taplo) - run: npx @taplo/cli@0.5.2 format --check - - - name: Check licenses - uses: EmbarkStudios/cargo-deny-action@v1 - with: - command: check licenses - - format_lint: - name: Formatting - runs-on: ubuntu-latest - env: - TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ vars.TURBO_TEAM }} - TURBO_REMOTE_ONLY: true - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: "Setup Node" - uses: ./.github/actions/setup-node - with: - extra-flags: --no-optional - node-version: "20" - - - name: Install Global Turbo - uses: ./.github/actions/install-global-turbo - - - name: Lint - # Manually set TURBO_API to an empty string to override Hetzner env - run: | - TURBO_API= turbo run lint --env-mode=strict - - cleanup: - name: Cleanup - needs: - - rust_lint - - format_lint - if: always() - uses: ./.github/workflows/pr-clean-caches.yml - secrets: inherit diff --git a/.github/workflows/lsp.yml b/.github/workflows/lsp.yml deleted file mode 100644 index d58abcf1ef177..0000000000000 --- a/.github/workflows/lsp.yml +++ /dev/null @@ -1,80 +0,0 @@ -# Turborepo LSP Pipeline -# -# Currently this just dumps the LSP binaries into the artifacts, but in the future -# we will want to do the entire packaging process here. - -name: Turborepo LSP - -on: - workflow_dispatch: - -jobs: - build-rust: - name: "Build Rust" - strategy: - fail-fast: false - matrix: - settings: - - host: macos-13 - target: "x86_64-apple-darwin" - container-options: "--rm" - - host: macos-13 - target: "aarch64-apple-darwin" - container-options: "--rm" - - host: ubuntu-latest - container-options: "--platform=linux/amd64 --rm" - container-setup: "sudo apt-get update && sudo apt-get install -y curl musl-tools" - target: "x86_64-unknown-linux-musl" - setup: "sudo apt-get install -y build-essential" - - host: ubuntu-latest - container-options: "--rm" - target: "aarch64-unknown-linux-musl" - rust-build-env: 'CC_aarch64_unknown_linux_musl=clang AR_aarch64_unknown_linux_musl=llvm-ar RUSTFLAGS="-Clink-self-contained=yes -Clinker=rust-lld"' - setup: "sudo apt-get update && sudo apt-get install -y build-essential musl-tools clang llvm gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu" - - host: windows-latest - target: x86_64-pc-windows-msvc - setup: "rustup set default-host x86_64-pc-windows-msvc" - container-options: "--rm" - - host: windows-latest - target: aarch64-pc-windows-msvc - setup: "rustup set default-host aarch64-pc-windows-msvc" - container-options: "--rm" - runs-on: ${{ matrix.settings.host }} - container: - image: ${{ matrix.settings.container }} - options: ${{ matrix.settings.container-options }} - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - name: Setup Container - if: ${{ matrix.settings.container-setup }} - run: ${{ matrix.settings.container-setup }} - - - name: Setup Protoc - uses: arduino/setup-protoc@v3 - with: - version: "26.x" - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Setup capnproto - uses: ./.github/actions/setup-capnproto - - - name: Rust Setup - uses: ./.github/actions/setup-rust - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - targets: ${{ matrix.settings.target }} - - - name: Build Setup - shell: bash - if: ${{ matrix.settings.setup }} - run: ${{ matrix.settings.setup }} - - - name: Build - run: ${{ matrix.settings.rust-build-env }} cargo build --profile release-turborepo-lsp -p turborepo-lsp --target ${{ matrix.settings.target }} - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: turborepo-lsp-${{ matrix.settings.target }} - path: target/${{ matrix.settings.target }}/release-turborepo-lsp/turborepo-lsp* diff --git a/.github/workflows/pr-clean-caches.yml b/.github/workflows/pr-clean-caches.yml deleted file mode 100644 index 800013e41bab7..0000000000000 --- a/.github/workflows/pr-clean-caches.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Cleanup branch caches -on: - pull_request: - types: [opened, closed, reopened, synchronize] - push: - workflow_dispatch: - workflow_call: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - actions: write - -jobs: - cleanup: - runs-on: ubuntu-latest - if: ${{ github.ref != 'refs/heads/main' }} - steps: - - name: Cleanup - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh extension install actions/gh-actions-cache - - REPO=${{ github.repository }} - BRANCH=${{ github.ref }} - - echo "Fetching list of cache key" - cacheKeysForPR=$(gh actions-cache list -R "$REPO" -B "$BRANCH" --limit 100 | cut -f 1) - - ## Setting this to not fail the workflow while deleting cache keys. - set +e - echo "Deleting caches..." - for cacheKey in $cacheKeysForPR - do - gh actions-cache delete "$cacheKey" -R "$REPO" -B "$BRANCH" --confirm - done - echo "Done" diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml deleted file mode 100644 index a1e1f747aae2d..0000000000000 --- a/.github/workflows/test-js-packages.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: JS Package Tests -on: - push: - branches: [main] - pull_request: - paths: - - package.json - - pnpm-workspace.yaml - - pnpm-lock.yaml - - "packages/**" - - ".github/actions/**" - - ".github/workflows/test-js-packages.yml" - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -permissions: - actions: write - contents: read - pull-requests: read - -jobs: - js_packages: - name: "JS Package Tests (${{matrix.os.name}}, Node ${{matrix.node-version}})" - timeout-minutes: 30 - runs-on: ${{ matrix.os.runner }} - strategy: - fail-fast: false - matrix: - os: - - name: ubuntu - runner: ubuntu-latest - - name: macos - runner: macos-13 - node-version: - - 18 - - 20 - env: - TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ vars.TURBO_TEAM }} - TURBO_REMOTE_ONLY: true - - steps: - # on main -> current + prev commit - # pr -> pr commits + base commit - - name: Determine fetch depth - id: fetch-depth - run: | - echo "depth=$(( ${{ github.event.pull_request.commits || 1 }} + 1 ))" >> $GITHUB_OUTPUT - - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ github.ref }} - fetch-depth: ${{ steps.fetch-depth.outputs.depth }} - - - name: "Setup Node" - uses: ./.github/actions/setup-node - with: - extra-flags: --no-optional - node-version: ${{ matrix.node-version }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - - - name: Install Global Turbo - uses: ./.github/actions/install-global-turbo - - - name: Run tests - # We manually set TURBO_API to an empty string to override Hetzner env - # We filter out turborepo-repository because it's a native package and needs - # to run when turbo core changes. This job (`js_packages`) does not run on turborpeo core - # changes, and we don't want to enable that beahvior for _all_ our JS packages. - run: | - TURBO_API= turbo run check-types test --filter="!turborepo-repository" --filter={./packages/*}...[${{ github.event.pull_request.base.sha || 'HEAD^1' }}] --color --env-mode=strict - env: - NODE_VERSION: ${{ matrix.node-version }} - - summary: - name: Turborepo JS Test Summary - runs-on: ubuntu-latest - if: always() - needs: - - js_packages - steps: - - name: Compute info - run: | - cancelled=false - failure=false - - subjob () { - local result=$1 - if [ "$result" = "cancelled" ]; then - cancelled=true - elif [ "$result" != "success" ] && [ "$result" != "skipped" ]; then - failure=true - fi - } - - subjob ${{needs.js_packages.result}} - - if [ "$cancelled" = "true" ]; then - echo "Job was cancelled." - exit 0 - elif [ "$failure" = "true" ]; then - echo "Job failed." - exit 1 - else - echo "Job succeeded." - exit 0 - fi diff --git a/.github/workflows/turborepo-compare-cache-item.yml b/.github/workflows/turborepo-compare-cache-item.yml deleted file mode 100644 index 11bc540d5ab71..0000000000000 --- a/.github/workflows/turborepo-compare-cache-item.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Turborepo Compare Cache Item - -on: - workflow_dispatch: - inputs: - version: - description: Turborepo release to test. - type: string - default: "canary" - -jobs: - generate_cache_artifact: - strategy: - matrix: - os: [macos-latest, ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - - steps: - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - name: create-turbo - run: | - npm install -g pnpm turbo@${{ inputs.version }} - pnpm dlx create-turbo@${{ inputs.version }} my-turborepo pnpm - - - name: Run build - run: | - cd my-turborepo - turbo run build --filter=docs --filter=web --summarize --skip-infer -vvv - - - name: Grab Turborepo artifacts - uses: actions/upload-artifact@v4 - with: - name: cache-item-${{ matrix.os }}-${{ inputs.version }} - path: | - my-turborepo/node_modules/.cache/turbo - my-turborepo/.turbo/runs - retention-days: 1 - - use_cache_artifact: - needs: generate_cache_artifact - strategy: - fail-fast: false - matrix: - os: [macos-latest, ubuntu-latest, windows-latest] - cache_os: [macos-latest, ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - - steps: - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - name: create-turbo - run: | - npm install -g pnpm turbo@${{ inputs.version }} - pnpm dlx create-turbo@${{ inputs.version }} my-turborepo pnpm - - - name: Download cache artifacts - uses: actions/download-artifact@v4 - with: - name: cache-item-${{ matrix.cache_os }}-${{ inputs.version }} - path: my-turborepo - - - name: Check for cache hit - run: | - cd my-turborepo - rm .turbo/runs/*.json - turbo run build --filter=docs --filter=web --summarize --skip-infer -vvv - cat .turbo/runs/*.json | jq -e '.execution.cached == 2' - - - name: Check for functional server - run: | - curl https://raw.githubusercontent.com/vercel/turbo/main/scripts/server.js -O - node server.js my-turborepo/apps/docs diff --git a/.github/workflows/turborepo-library-release.yml b/.github/workflows/turborepo-library-release.yml deleted file mode 100644 index c1ad8a771123d..0000000000000 --- a/.github/workflows/turborepo-library-release.yml +++ /dev/null @@ -1,199 +0,0 @@ -name: Turborepo Library Release - -on: - workflow_dispatch: - inputs: - dry_run: - description: "Do a dry run, skipping the final publish step." - type: boolean - -jobs: - build: - defaults: - run: - shell: bash -leo pipefail {0} - - strategy: - fail-fast: false - matrix: - settings: - - host: macos-latest - target: "aarch64-apple-darwin" - - host: macos-latest - target: "x86_64-apple-darwin" - - - host: ubuntu-latest - target: "aarch64-unknown-linux-gnu" - setup: | - sudo apt update - sudo apt install -y g++-aarch64-linux-gnu libc6-dev-arm64-cross - echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV - - - host: ubuntu-latest - target: "x86_64-unknown-linux-gnu" - container: amazon/aws-lambda-nodejs:20 - install: | - microdnf install -y gcc gcc-c++ git - curl https://sh.rustup.rs -sSf | bash -s -- -y - npm i -g pnpm@8.9.0 - setup: | - pnpm install - - - host: ubuntu-latest - target: "x86_64-unknown-linux-musl" - container: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-alpine - install: | - apk update && apk upgrade - apk add libc6-compat curl - echo /root/.cargo/bin >> ${GITHUB_PATH} - echo /usr/local/cargo/bin/rustup >> ${GITHUB_PATH} - setup: | - export PATH=/usr/local/cargo/bin/rustup:/root/.cargo/bin:${PATH} - rustup show active-toolchain - dirname $(rustup which cargo) >> ${GITHUB_PATH} - pnpm install - - - host: ubuntu-latest - target: "aarch64-unknown-linux-musl" - container: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-alpine - install: | - apk update && apk upgrade - apk add libc6-compat curl - echo /root/.cargo/bin >> ${GITHUB_PATH} - echo /usr/local/cargo/bin/rustup >> ${GITHUB_PATH} - echo /aarch64-linux-musl-cross/bin >> ${GITHUB_PATH} - setup: | - export PATH=/aarch64-linux-musl-cross/bin:/usr/local/cargo/bin/rustup:/root/.cargo/bin:${PATH} - rustup show active-toolchain - rustup target add aarch64-unknown-linux-musl - dirname $(rustup which cargo) >> ${GITHUB_PATH} - pnpm install - rust_env: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc RUSTFLAGS="-Ctarget-feature=-crt-static" - - - host: windows-latest - target: "aarch64-pc-windows-msvc" - - - host: windows-latest - target: "x86_64-pc-windows-msvc" - - runs-on: ${{ matrix.settings.host }} - container: - image: ${{ matrix.settings.container }} - steps: - - name: Install Packages - run: ${{ matrix.settings.install }} - if: ${{ matrix.settings.install }} - - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Setup Rust - uses: ./.github/actions/setup-rust - with: - targets: ${{ matrix.settings.target }} - github-token: ${{ github.token }} - if: ${{ !matrix.settings.install }} - - - name: Setup Node - uses: ./.github/actions/setup-node - with: - enable-corepack: false - if: ${{ !matrix.settings.install }} - - - name: Setup toolchain - run: ${{ matrix.settings.setup }} - if: ${{ matrix.settings.setup }} - - - name: Build native library - # For some reason PATH modifications from Setup toolchain aren't populated - # when using the nodejs-rust alpine container. - run: | - export PATH=/usr/local/cargo/bin/rustup:/root/.cargo/bin:${PATH} - cd packages/turbo-repository - ${{ matrix.settings.rust_env }} pnpm build:release --target=${{ matrix.settings.target }} - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: turbo-library-${{ matrix.settings.target }} - path: packages/turbo-repository/native - - package: - name: "Publish to NPM" - runs-on: ubuntu-latest - needs: [build] - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Configure git - run: | - git config --global user.name 'Turbobot' - git config --global user.email 'turbobot@vercel.com' - - - name: Download Artifacts - uses: actions/download-artifact@v4 - with: - path: native-packages - - - name: Move artifacts into place - run: | - mv native-packages/turbo-library-aarch64-apple-darwin/@turbo/repository.darwin-arm64.node packages/turbo-repository/npm/darwin-arm64/ - mv native-packages/turbo-library-x86_64-apple-darwin/@turbo/repository.darwin-x64.node packages/turbo-repository/npm/darwin-x64/ - mv native-packages/turbo-library-aarch64-unknown-linux-gnu/@turbo/repository.linux-arm64-gnu.node packages/turbo-repository/npm/linux-arm64-gnu/ - mv native-packages/turbo-library-aarch64-unknown-linux-musl/@turbo/repository.linux-arm64-musl.node packages/turbo-repository/npm/linux-arm64-musl/ - mv native-packages/turbo-library-x86_64-unknown-linux-gnu/@turbo/repository.linux-x64-gnu.node packages/turbo-repository/npm/linux-x64-gnu/ - mv native-packages/turbo-library-x86_64-unknown-linux-musl/@turbo/repository.linux-x64-musl.node packages/turbo-repository/npm/linux-x64-musl/ - mv native-packages/turbo-library-aarch64-pc-windows-msvc/@turbo/repository.win32-arm64-msvc.node packages/turbo-repository/npm/win32-arm64-msvc/ - mv native-packages/turbo-library-x86_64-pc-windows-msvc/@turbo/repository.win32-x64-msvc.node packages/turbo-repository/npm/win32-x64-msvc/ - - - name: Build Meta Package - run: | - cd packages/turbo-repository/js - npm run build - - - name: Package Artifacts - run: | - mkdir tarballs - npm pack packages/turbo-repository/npm/darwin-arm64 - npm pack packages/turbo-repository/npm/darwin-x64 - npm pack packages/turbo-repository/npm/linux-arm64-gnu - npm pack packages/turbo-repository/npm/linux-arm64-musl - npm pack packages/turbo-repository/npm/linux-x64-gnu - npm pack packages/turbo-repository/npm/linux-x64-musl - npm pack packages/turbo-repository/npm/win32-arm64-msvc - npm pack packages/turbo-repository/npm/win32-x64-msvc - npm pack packages/turbo-repository/js - mv *.tgz tarballs/ - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: Upload Tarballs - path: tarballs - - - name: Publish Artifacts - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - if: ${{ !inputs.dry_run }} - run: | - npm config set --location=project "//registry.npmjs.org/:_authToken" ${NPM_TOKEN} - VERSION=$(jq -r .version packages/turbo-repository/js/package.json) - cd tarballs - ls - TAG="canary" - npm publish -ddd --tag ${TAG} --access public turbo-repository-darwin-arm64-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-darwin-x64-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-arm64-gnu-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-arm64-musl-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-x64-gnu-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-x64-musl-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-win32-arm64-msvc-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-win32-x64-msvc-${VERSION}.tgz - npm publish -ddd --tag ${TAG} --access public turbo-repository-${VERSION}.tgz diff --git a/.github/workflows/turborepo-native-lib-test.yml b/.github/workflows/turborepo-native-lib-test.yml deleted file mode 100644 index 9ac95e12f6c42..0000000000000 --- a/.github/workflows/turborepo-native-lib-test.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Turborepo Native Library Tests -on: - push: - branches: [main] - paths-ignore: - - "docs/**" - pull_request: - -permissions: - actions: write - contents: read - pull-requests: read - -jobs: - js_native_packages: - name: "@turbo/repository (${{matrix.os.name}}, Node ${{matrix.node-version}})" - timeout-minutes: 30 - runs-on: ${{ matrix.os.runner }} - strategy: - fail-fast: false - matrix: - os: - - name: ubuntu - runner: ubuntu-latest - - name: macos - runner: macos-latest - node-version: - - 18 - - 20 - env: - TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ vars.TURBO_TEAM }} - TURBO_REMOTE_ONLY: true - - steps: - - name: Determine fetch depth - id: fetch-depth - run: | - echo "depth=$(( ${{ github.event.pull_request.commits || 1 }} + 1 ))" >> $GITHUB_OUTPUT - - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ github.ref }} - fetch-depth: ${{ steps.fetch-depth.outputs.depth }} - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - node-version: ${{ matrix.node-version }} - - - name: Install Global Turbo - uses: ./.github/actions/install-global-turbo - - - name: Run tests - # Manually set TURBO_API to an empty string to override Hetzner env - run: | - TURBO_API= turbo run test --filter "turborepo-repository" --color --env-mode=strict - env: - NODE_VERSION: ${{ matrix.node-version }} diff --git a/.github/workflows/turborepo-release.yml b/.github/workflows/turborepo-release.yml deleted file mode 100644 index 2b7a2098e868b..0000000000000 --- a/.github/workflows/turborepo-release.yml +++ /dev/null @@ -1,269 +0,0 @@ -# Turborepo Release Pipeline -# -# This release consists of a few steps -# -# 1. Create a staging branch -# 2. Run some smoke tests on that branch -# 3. Build the Rust binary -# 4. Publish JS packages npm (including turbo itself) -# 5. Create a release branch and open a PR. - -# You can opt into a dry run, which will skip publishing to npm and opening the release branch - -name: Turborepo Release - -env: - CARGO_PROFILE_RELEASE_LTO: true - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - RELEASE_TURBO_CLI: true # TODO: do we need this? - -on: - workflow_dispatch: - inputs: - increment: - description: "SemVer Increment (prerelease = bump canary)" - required: true - default: "prerelease" - type: choice - options: - # Bump the canary version of the existing semver release - - prerelease - # Bump to the next patch version, creating its first canary release - - prepatch - # Bump to the next minor version, creating its first canary release - - preminor - # Bump to the next major version, creating its first canary release - - premajor - # Bump to the next patch version - - patch - # Bump to the next minor version - - minor - # Bump to the next major version - - major - dry_run: - description: "Do a dry run, skipping the final publish step." - type: boolean - -jobs: - stage: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/setup-node - with: - enable-corepack: false - - name: Configure git - run: | - git config --global user.name 'Turbobot' - git config --global user.email 'turbobot@vercel.com' - - name: Version - run: | - ./scripts/version.js ${{ inputs.increment }} - cat version.txt - - name: Stage Commit - id: stage - run: cd cli && make stage-release && echo "STAGE_BRANCH=$(git branch --show-current)" >> $GITHUB_OUTPUT - - name: Show Stage Commit - run: echo "${{ steps.stage.outputs.STAGE_BRANCH }}" - outputs: - stage-branch: "${{ steps.stage.outputs.STAGE_BRANCH }}" - - rust-smoke-test: - name: Rust Unit Tests - runs-on: ubuntu-latest - needs: [stage] - steps: - - name: Show Stage Commit - run: echo "${{ needs.stage.outputs.stage-branch }}" - - uses: actions/checkout@v4 - with: - ref: ${{ needs.stage.outputs.stage-branch }} - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - - name: Run Rust Unit Tests - run: cargo groups test turborepo - - js-smoke-test: - name: JS Package Tests - runs-on: ubuntu-latest - needs: [stage] - steps: - - name: Show Stage Commit - run: echo "${{ needs.stage.outputs.stage-branch }}" - - uses: actions/checkout@v4 - with: - ref: ${{ needs.stage.outputs.stage-branch }} - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - node-version: "20" - - name: Install Global Turbo - uses: ./.github/actions/install-global-turbo - - name: Run JS Package Tests - run: turbo run check-types test --filter="./packages/*" --color - - build-rust: - name: "Build Rust" - needs: [stage, rust-smoke-test, js-smoke-test] - strategy: - fail-fast: false - matrix: - settings: - - host: macos-latest - target: "x86_64-apple-darwin" - container-options: "--rm" - - host: macos-latest - target: "aarch64-apple-darwin" - container-options: "--rm" - - host: ubuntu-latest - container-options: "--platform=linux/amd64 --rm" - target: "x86_64-unknown-linux-musl" - setup: "sudo apt-get update && sudo apt-get install -y build-essential clang lldb llvm libclang-dev curl musl-tools sudo unzip" - - host: ubuntu-latest - container-options: "--rm" - target: "aarch64-unknown-linux-musl" - rust-build-env: 'CC_aarch64_unknown_linux_musl=clang AR_aarch64_unknown_linux_musl=llvm-ar RUSTFLAGS="-Clink-self-contained=yes -Clinker=rust-lld"' - setup: "sudo apt-get update && sudo apt-get install -y build-essential musl-tools clang llvm gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu" - - host: windows-latest - target: x86_64-pc-windows-msvc - container-options: "--rm" - runs-on: ${{ matrix.settings.host }} - container: - image: ${{ matrix.settings.container }} - options: ${{ matrix.settings.container-options }} - steps: - - name: Show Stage Commit - run: echo "${{ needs.stage.outputs.stage-branch }}" - - name: Checkout repo - uses: actions/checkout@v4 - with: - ref: "${{ needs.stage.outputs.stage-branch }}" - - - name: Setup Container - if: ${{ matrix.settings.container-setup }} - run: ${{ matrix.settings.container-setup }} - - - name: Setup Protoc - uses: arduino/setup-protoc@v3 - with: - version: "26.x" - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Setup capnproto - uses: ./.github/actions/setup-capnproto - - - name: Setup Rust Up - if: ${{ matrix.settings.container-setup }} - # setup-rust-toolchain uses the --retry-connrefused flag with curl to install rustup - # this flag was added in curl 7.52.0, but the Ubuntu version we use only has 7.47.0 - run: | - curl --proto '=https' --tlsv1.2 --retry 10 --location --silent --show-error --fail "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y - echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH - - - name: Rust Setup - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - target: ${{ matrix.settings.target }} - # needed to not make it override the defaults - rustflags: "" - # we want more specific settings - cache: false - - - name: Build Setup - shell: bash - if: ${{ matrix.settings.setup }} - run: ${{ matrix.settings.setup }} - - - name: Build - run: ${{ matrix.settings.rust-build-env }} cargo build --profile release-turborepo -p turbo --target ${{ matrix.settings.target }} - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: turbo-${{ matrix.settings.target }} - path: target/${{ matrix.settings.target }}/release-turborepo/turbo* - - npm-publish: - name: "Publish To NPM" - runs-on: ubuntu-latest - needs: [stage, build-rust] - steps: - - name: Show Stage Commit - run: echo "${{ needs.stage.outputs.stage-branch }}" - - uses: actions/checkout@v4 - with: - ref: "${{ needs.stage.outputs.stage-branch }}" - - run: git fetch origin --tags - - uses: ./.github/actions/setup-node - with: - enable-corepack: false - - - name: Install Global Turbo - uses: ./.github/actions/install-global-turbo - - - name: Configure git - run: | - git config --global user.name 'Turbobot' - git config --global user.email 'turbobot@vercel.com' - - - name: Install GoReleaser - uses: goreleaser/goreleaser-action@v6 - with: - distribution: goreleaser-pro - version: v1.18.2 - install-only: true - env: - GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} - - - name: Download Rust artifacts - uses: actions/download-artifact@v4 - with: - path: rust-artifacts - - - name: Move Rust artifacts into place - run: | - mv rust-artifacts/turbo-aarch64-apple-darwin cli/dist-darwin-arm64 - mv rust-artifacts/turbo-aarch64-unknown-linux-musl cli/dist-linux-arm64 - cp -r rust-artifacts/turbo-x86_64-pc-windows-msvc cli/dist-windows-arm64 - mv rust-artifacts/turbo-x86_64-unknown-linux-musl cli/dist-linux-amd64 - mv rust-artifacts/turbo-x86_64-apple-darwin cli/dist-darwin-amd64 - mv rust-artifacts/turbo-x86_64-pc-windows-msvc cli/dist-windows-amd64 - - - name: Perform Release - run: cd cli && make publish-turbo SKIP_PUBLISH=${{ inputs.dry_run && '--skip-publish' || '' }} - env: - GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - # Upload published artifacts in case they are needed for debugging later - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: turbo-combined - path: cli/dist - - create-release-pr: - name: "Open Release Branch PR" - needs: [stage, npm-publish] - runs-on: ubuntu-latest - steps: - - name: Show Stage Commit - run: echo "${{ needs.stage.outputs.stage-branch }}" - - uses: actions/checkout@v4 - with: - ref: ${{ needs.stage.outputs.stage-branch }} - - name: Get version - id: getVersion - run: echo "version=$(head -n 1 version.txt)" >> $GITHUB_OUTPUT - - name: Create pull request - uses: thomaseizinger/create-pull-request@master - if: ${{ !inputs.dry_run }} - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - head: ${{ needs.stage.outputs.stage-branch }} - base: main - title: "release(turborepo): ${{ steps.getVersion.outputs.version }}" diff --git a/.github/workflows/turborepo-test.yml b/.github/workflows/turborepo-test.yml deleted file mode 100644 index 06377ec606bb8..0000000000000 --- a/.github/workflows/turborepo-test.yml +++ /dev/null @@ -1,394 +0,0 @@ -name: Turborepo Test -on: - push: - branches: [main] - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -permissions: - actions: write - contents: read - pull-requests: read - -jobs: - find-changes: - name: Find path changes - runs-on: ubuntu-latest - outputs: - docs: ${{ steps.filter.outputs.docs }} - basic-example: ${{ steps.filter.outputs.basic-example }} - kitchen-sink-example: ${{ steps.filter.outputs.kitchen-sink-example }} - non-monorepo-example: ${{ steps.filter.outputs.non-monorepo-example }} - with-svelte-example: ${{ steps.filter.outputs.with-svelte-example }} - with-tailwind-example: ${{ steps.filter.outputs.with-tailwind-example }} - rest: ${{ steps.filter.outputs.rest }} - steps: - - uses: dorny/paths-filter@v3 - id: filter - with: - filters: | - docs: - - "docs/**" - basic-example: - - "examples/basic/**" - - "turborepo-tests/example-basic-*/**" - - "turborepo-tests/helpers/**" - kitchen-sink-example: - - "examples/kitchen-sink/**" - - "turborepo-tests/example-kitchen-sink-*/**" - - "turborepo-tests/helpers/**" - non-monorepo-example: - - "examples/non-monorepo/**" - - "turborepo-tests/example-non-monorepo-*/**" - - "turborepo-tests/helpers/**" - with-svelte-example: - - "examples/with-svelte/**" - - "turborepo-tests/example-with-svelte-*/**" - - "turborepo-tests/helpers/**" - with-tailwind-example: - - "examples/with-tailwind/**" - - "turborepo-tests/example-with-svelte-*/**" - - "turborepo-tests/helpers/**" - rest: - - "!(docs/**|examples/**)**" - - integration: - name: Turborepo Integration - needs: - - find-changes - runs-on: ${{ matrix.os.runner }} - timeout-minutes: 45 - if: ${{ needs.find-changes.outputs.rest == 'true' }} - strategy: - fail-fast: false - matrix: - os: - - runner: ubuntu-latest - - runner: macos-13 - - runner: windows-latest - steps: - # On Windows, set autocrlf to input so that when the repo is cloned down - # the fixtures retain their line endings and don't get updated to CRLF. - # We want this because this repo also contains the fixtures for our test cases - # and these fixtures have files that need stable file hashes. If we let git update - # the line endings on checkout, the file hashes will change. - # https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_core_autocrlf - - name: set crlf - if: matrix.os.runner == 'windows-latest' - shell: bash - run: git config --global core.autocrlf input - - uses: actions/checkout@v4 - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - node-version: "18.20.2" - - - name: Install Global Turbo - uses: ./.github/actions/install-global-turbo - - - name: Setup Graphviz - uses: ts-graphviz/setup-graphviz@v2 - with: - macos-skip-brew-update: "true" - env: - HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: true - - - name: Cache Prysk - id: cache-prysk - uses: actions/cache@v4 - with: - path: cli/.cram_env - key: prysk-venv-${{ matrix.os.runner }} - - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.6 - - - name: Integration Tests - run: | - if [ -z "${RUSTC_WRAPPER}" ]; then - unset RUSTC_WRAPPER - fi - turbo run test --filter=turborepo-tests-integration --color --env-mode=strict --token=${{ secrets.TURBO_TOKEN }} --team=${{ vars.TURBO_TEAM }} - shell: bash - env: - SCCACHE_BUCKET: turborepo-sccache - SCCACHE_REGION: us-east-2 - # Only use sccache if we're in the Vercel repo. - RUSTC_WRAPPER: ${{ !github.event.pull_request.head.repo.fork && 'sccache' || '' }} - CARGO_INCREMENTAL: 0 - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - - rust_lint: - name: Rust lints - needs: - - find-changes - if: ${{ needs.find-changes.outputs.rest == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - node-version: "18.20.2" - - - name: Run cargo fmt check - run: | - cargo fmt --check - - - name: Check Cargo.toml formatting (taplo) - run: npx @taplo/cli@0.5.2 format --check - - - name: Check licenses - uses: EmbarkStudios/cargo-deny-action@v1 - with: - command: check licenses - - - name: Run cargo clippy - run: | - cargo clippy --workspace --features rustls-tls -- --deny clippy::all - - rust_check: - # We test dependency changes only on main - name: Turborepo rust check - needs: - - find-changes - if: ${{ needs.find-changes.outputs.rest == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - node-version: "18.20.2" - - - name: Run cargo check - run: | - cargo check --workspace - - rust_test: - strategy: - fail-fast: false - matrix: - os: - - name: ubuntu - runner: ubuntu-latest - - name: macos - runner: macos-13 - - name: windows - runner: windows-latest - runs-on: ${{ matrix.os.runner }} - needs: - - find-changes - if: ${{ needs.find-changes.outputs.rest == 'true' }} - name: Turborepo Rust testing on ${{ matrix.os.name }} - steps: - - name: Set git to use LF line endings - run: | - git config --global core.autocrlf false - git config --global core.eol lf - if: matrix.os.name == 'windows' - - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Turborepo Environment - uses: ./.github/actions/setup-turborepo-environment - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - node-version: "18.20.2" - - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.6 - - - name: Run tests - timeout-minutes: 120 - # We explicitly unset RUSTC_WRAPPER if it is an empty string as causes build issues - run: | - if [ -z "${RUSTC_WRAPPER}" ]; then - unset RUSTC_WRAPPER - fi - if [ "$RUNNER_OS" == "Windows" ]; then - cargo test --workspace --exclude turborepo-napi - else - cargo test --workspace - fi - shell: bash - env: - SCCACHE_BUCKET: turborepo-sccache - SCCACHE_REGION: us-east-2 - # Only use sccache if we're in the Vercel repo. - RUSTC_WRAPPER: ${{ !github.event.pull_request.head.repo.fork && 'sccache' || '' }} - CARGO_INCREMENTAL: 0 - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - - basic-example: - name: "`basic` example" - timeout-minutes: 40 - needs: - - find-changes - if: ${{ needs.find-changes.outputs.basic-example == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: "Run `basic` example tests" - uses: ./.github/actions/examples-tests - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - turbo-token: "${{ secrets.TURBO_TOKEN }}" - turbo-team: "${{ vars.TURBO_TEAM }}" - test-filter: "@turborepo-examples-tests/kitchen-sink-*" - - kitchen-sink-example: - name: "`kitchen-sink` example" - needs: - - find-changes - timeout-minutes: 40 - if: ${{ needs.find-changes.outputs.kitchen-sink-example == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: "Run `kitchen-sink` example tests" - uses: ./.github/actions/examples-tests - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - turbo-token: "${{ secrets.TURBO_TOKEN }}" - turbo-team: "${{ vars.TURBO_TEAM }}" - test-filter: "@turborepo-examples-tests/kitchen-sink-*" - - non-monorepo-example: - name: "`non-monorepo` example" - timeout-minutes: 40 - needs: - - find-changes - if: ${{ needs.find-changes.outputs.non-monorepo-example == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: "Run `non-monorepo` example tests" - uses: ./.github/actions/examples-tests - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - turbo-token: "${{ secrets.TURBO_TOKEN }}" - turbo-team: "${{ vars.TURBO_TEAM }}" - test-filter: "@turborepo-examples-tests/non-monorepo-*" - - with-svelte-example: - name: "`with-svelte` example" - timeout-minutes: 40 - needs: - - find-changes - if: ${{ needs.find-changes.outputs.with-svelte-example == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: "Run `with-svelte` example tests" - uses: ./.github/actions/examples-tests - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - turbo-token: "${{ secrets.TURBO_TOKEN }}" - turbo-team: "${{ vars.TURBO_TEAM }}" - test-filter: "@turborepo-examples-tests/with-svelte-*" - - with-tailwind-example: - name: "`with-tailwind` example" - timeout-minutes: 40 - needs: - - find-changes - if: ${{ needs.find-changes.outputs.with-tailwind-example == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: "Run `with-tailwind` example tests" - uses: ./.github/actions/examples-tests - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - turbo-token: "${{ secrets.TURBO_TOKEN }}" - turbo-team: "${{ vars.TURBO_TEAM }}" - test-filter: "@turborepo-examples-tests/with-tailwind-*" - - summary: - name: Turborepo Test Summary - runs-on: ubuntu-latest - if: always() - needs: - - integration - - rust_lint - - rust_check - - rust_test - - basic-example - - kitchen-sink-example - - non-monorepo-example - - with-svelte-example - - with-tailwind-example - steps: - - name: Compute info - id: info - if: always() - run: | - cancelled=false - failure=false - - subjob () { - local result=$1 - if [ "$result" = "cancelled" ]; then - cancelled=true - elif [ "$result" != "success" ] && [ "$result" != "skipped" ]; then - failure=true - fi - } - - subjob ${{needs.integration.result}} - subjob ${{needs.rust_lint.result}} - subjob ${{needs.rust_check.result}} - subjob ${{needs.rust_test.result}} - subjob ${{needs.basic-example.result}} - subjob ${{needs.kitchen-sink-example.result}} - subjob ${{needs.non-monorepo-example.result}} - subjob ${{needs.with-svelte-example.result}} - subjob ${{needs.with-tailwind-example.result}} - - if [ "$cancelled" = "true" ]; then - echo "cancelled=true" >> $GITHUB_OUTPUT - elif [ "$failure" = "true" ]; then - echo "failure=true" >> $GITHUB_OUTPUT - else - echo "success=true" >> $GITHUB_OUTPUT - fi - - - name: Failed - if: steps.info.outputs.failure == 'true' - run: exit 1 - - - name: Succeeded - if: steps.info.outputs.success == 'true' - run: echo Ok - - cleanup: - name: Cleanup - needs: summary - if: always() - uses: ./.github/workflows/pr-clean-caches.yml - secrets: inherit diff --git a/.github/workflows/turborepo-top-issues.yml b/.github/workflows/turborepo-top-issues.yml deleted file mode 100644 index d9337f8786019..0000000000000 --- a/.github/workflows/turborepo-top-issues.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Turborepo Top Issues - -on: - schedule: - - cron: "0 13 * * 1" # Every Monday at 1PM UTC (9AM EST) - workflow_dispatch: - -jobs: - run: - # if: github.repository_owner == 'vercel' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - run: corepack enable - - run: pnpm install - - name: "Get Top Issues" - run: node ./packages/top-issues/src/index.mjs packages/top-issues - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: "Show slack payload" - run: cat packages/top-issues/slack-payload.json - - name: Send payload to slack - uses: slackapi/slack-github-action@v1.23.0 - with: - payload-file-path: "packages/top-issues/slack-payload.json" - env: - SLACK_WEBHOOK_URL: "${{ secrets.TURBOREPO_REPO_STATS_SLACK_WEBHOOK_URL }}" diff --git a/.github/workflows/update-examples-on-release.yml b/.github/workflows/update-examples-on-release.yml deleted file mode 100644 index 6fb77b8856cc3..0000000000000 --- a/.github/workflows/update-examples-on-release.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Update examples to latest - -on: - workflow_dispatch: - -jobs: - update-examples-pr: - name: "Update examples PR" - needs: [stage, npm-publish] - runs-on: ubuntu-latest - steps: - - name: Run upgrade script - run: bash ./scripts/update-examples-dep.sh - - name: Create pull request - uses: thomaseizinger/create-pull-request@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - head: ${{ needs.stage.outputs.stage-branch }} - base: main - title: "release(turborepo): update examples to latest(${{ steps.getVersion.outputs.version }})" diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 58b1861ccc498..0000000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -pnpm exec lint-staged diff --git a/.node-version b/.node-version deleted file mode 100644 index 9a2a0e219c9b2..0000000000000 --- a/.node-version +++ /dev/null @@ -1 +0,0 @@ -v20 diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index bb208140e1ece..0000000000000 --- a/.prettierignore +++ /dev/null @@ -1,24 +0,0 @@ -.next/ -build/ -dist - -node_modules/ -target/ -coverage/ -snapshot/ -generated/ -pnpm-lock.yaml - -__generated__/ -/benchmark/large-monorepo -/cli/dist-cross* -/docs/public/schema.json -/packages/eslint-plugin-turbo/__tests__/fixtures/ -/packages/turbo-codemod/templates/ -/docs/components/pages/pack-home/benchmark-data/data.json -/examples/with-svelte - - -# crates -# generators -*.hbs diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 5c39c68bf8c2a..0000000000000 --- a/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "overrides": [ - { - "files": ["./docs/**/*.mdx"], - "options": { - "singleQuote": true - } - } - ] -} diff --git a/.rustfmt.toml b/.rustfmt.toml deleted file mode 100644 index c4e4d348c3510..0000000000000 --- a/.rustfmt.toml +++ /dev/null @@ -1,11 +0,0 @@ -# Keep in sync with .editorconfig -max_width = 100 - -tab_spaces = 4 -hard_tabs = false - -format_strings = true -wrap_comments = true - -imports_granularity = "Crate" -group_imports = "StdExternalCrate" diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 9ad18d0cc48a0..0000000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "recommendations": [ - "bradlc.vscode-tailwindcss", - "christian-kohler.npm-intellisense", - "dbaeumer.vscode-eslint", - "eamodio.gitlens", - "EditorConfig.EditorConfig", - "esbenp.prettier-vscode", - "github.copilot", - "github.vscode-pull-request-github", - "heybourn.headwind", - "ms-azuretools.vscode-docker", - "ms-vscode-remote.remote-containers", - "rust-lang.rust-analyzer", - "unifiedjs.vscode-mdx", - "yzhang.markdown-all-in-one", - "zxh404.vscode-proto3", - "mihaipopescu.Cram" - ] -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 0b0425636cbb5..0000000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "2.0.0", - "configurations": [ - { - "name": "turbo build (example)", - "type": "lldb", - "request": "launch", - "preLaunchTask": "prepare turbo", - "program": "${workspaceRoot}/target/debug/turbo", - "args": ["build", "--skip-infer"], - "cwd": "${workspaceRoot}/${input:pickExample}", - "presentation": { - "group": "commands", - "order": 1 - } - }, - { - "name": "turbo gen", - "type": "lldb", - "request": "launch", - "preLaunchTask": "prepare turbo", - "program": "${workspaceRoot}/target/debug/turbo", - "args": [ - "gen", - "blog - release post", - "--args", - "1.11.0", - "1.10.0", - "_", - "tagline about my really cool release" - ], - "cwd": "${workspaceRoot}", - "presentation": { - "group": "commands", - "order": 1 - } - }, - { - "name": "turbo daemon", - "type": "lldb", - "request": "launch", - "preLaunchTask": "prepare turbo", - "program": "${workspaceRoot}/target/debug/turbo", - "args": ["--skip-infer", "daemon"], - "cwd": "${workspaceRoot}", - "presentation": { - "group": "commands", - "order": 1 - } - }, - { - "type": "extensionHost", - "request": "launch", - "name": "Turbo VSC", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceRoot}/packages/turbo-vsc" - ], - "outFiles": ["${workspaceRoot}/packages/turbo-vsc/out/**/*.js"] - } - ], - "inputs": [ - { - "id": "pickExample", - "description": "Select the example to use", - "type": "pickString", - "options": [ - "examples/basic", - "examples/kitchen-sink", - "examples/design-system", - "examples/non-monorepo", - "examples/non-shell-commands" - ], - "default": "examples/basic" - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 72f8e97302afa..0000000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "eslint.validate": [ - "javascript", - "javascriptreact", - "typescript", - "typescriptreact" - ], - "eslint.workingDirectories": [{ "mode": "auto" }], - "debug.javascript.unmapMissingSources": true, - "files.associations": { - "libturbo.h": "c", - "turbo.json": "jsonc", - "*.t.err": "cram" - }, - "[cram]": { - "editor.trimAutoWhitespace": false, - "files.trimFinalNewlines": false, - "files.insertFinalNewline": false, - "files.trimTrailingWhitespace": false - }, - "typescript.tsdk": "node_modules/typescript/lib", - "json.schemas": [ - { - "fileMatch": ["turbo.json"], - "url": "./packages/turbo-types/schemas/schema.json" - } - ] -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 77c0a921b1352..0000000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "shell", - "label": "prepare turbo", - "command": "cargo build --package turbo" - } - ] -} diff --git a/.vscode/turborepo.code-workspace b/.vscode/turborepo.code-workspace deleted file mode 100644 index c32d6a13ff1ad..0000000000000 --- a/.vscode/turborepo.code-workspace +++ /dev/null @@ -1,11 +0,0 @@ -{ - "folders": [ - { - "name": "turbo", - "path": "../" - }, - { - "path": "../packages/eslint-plugin-turbo" - } - ] -} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index ddccaea475a34..0000000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,50 +0,0 @@ -# Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our community include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -- Focusing on what is best not just for us as individuals, but for the overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or advances of any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a professional setting - -## Enforcement Responsibilities - -Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project team responsible for enforcement at [coc@vercel.com](mailto:coc@vercel.com). All complaints will be reviewed and investigated promptly and fairly. - -All project maintainers are obligated to respect the privacy and security of the reporter of any incident. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct/][version]. - -[homepage]: http://contributor-covenant.org -[version]: https://www.contributor-covenant.org/version/2/1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 27821afd97778..0000000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,239 +0,0 @@ -Thank you for your interest in contributing to Turborepo! - -- [General dependencies](#general-dependencies) -- [Optional dependencies](#optional-dependencies) -- [Structure of the repository](#structure-of-the-repository) -- [Building Turborepo](#building-turborepo) - - [TLS implementation](#tls-implementation) -- [Running tests](#running-tests) -- [Manually testing `turbo`](#manually-testing-turbo) - - [Repositories to test with](#repositories-to-test-with) -- [Debugging tips](#debugging-tips) - - [Verbose logging](#verbose-logging) - - [Crash logs](#crash-logs) - - [Terminal UI debugging](#terminal-ui-debugging) -- [Publishing `turbo` to the npm registry](#publishing-turbo-to-the-npm-registry) -- [Contributing to examples](#contributing-to-examples) - - [Contributing to an existing example](#contributing-to-an-existing-example) - - [Philosophy for new examples](#philosophy-for-new-examples) - - [Designing a new example](#designing-a-new-example) - - [Testing examples](#testing-examples) - -## General dependencies - -You will need to have these dependences installed on your machine to work on this repository: - -- [Rust](https://www.rust-lang.org/tools/install) ([Repository toolchain](https://github.com/vercel/turborepo/blob/main/rust-toolchain.toml)) -- [NodeJS](https://nodejs.org/en) v20 -- [pnpm](https://pnpm.io/) v8 -- [protoc](https://grpc.io/docs/protoc-installation/) -- [capnp](https://capnproto.org) - -### Optional dependencies - -- For running tests locally, `jq` and `zstd` are also required. - - macOS: `brew install jq zstd` - - Linux: `sudo apt update && sudo apt install jq zstd` - - Windows: `choco install jq zstandard` -- On Linux, ensure LLD (LLVM Linker) is installed, as it's not installed by default on many Linux distributions (e.g. `apt install lld`). - -## Structure of the repository - -In general, there are two major areas in the repository: - -- The `crates` directory with the Rust code for the `turbo` binary -- The `packages` directory with JavaScript packages -- the `examples` directory with examples of how to use Turborepo with other tools and frameworks -- The `docs` directory with the documentation for Turborepo - -## Building Turborepo - -1. Run `pnpm install` at the root of the repository -2. Run `cargo build` - -### TLS Implementation - -Turborepo uses [`reqwest`](https://docs.rs/reqwest/latest/reqwest/) to make requests to the Remote Cache. - -`reqwest` supports two TLS -implementations: `rustls` and `native-tls`. `rustls` is a pure Rust implementation of TLS, while `native-tls` -is a wrapper around OpenSSL. You may select which implementation you want with the `native-tls` -and `rustls-tls` features. - -By default, the `rustls-tls` feature is selected so that `cargo build` works -out of the box. If you wish to select `native-tls`, you may do so by running `cargo build --no-default-features --features native-tls`. - -## Running tests - -> [!IMPORTANT] -> You will need to have `jq` and `zstd` installed on your system in order to run tests. See [General dependencies](#general-dependencies) for instructions on how to install these tools. - -First, install Turborepo globally with your package manager of choice. For instance, with npm, `npm install -g turbo`. This will install the `turbo` binary in your system's `PATH`, making it globally available. - -Now, from the root directory, you can run: - -- Unit tests - -```bash - cargo test -``` - -- A module's unit tests - -```bash -cargo test -p -``` - -- Integration tests - ```bash - pnpm test -- --filter=turborepo-tests-integration - ``` -- A single integration test - e.g to run everything in `turborepo-tests/integration/tests/run-summary`: - - ```bash - # Build `turbo` first because the next command doesn't run through `turbo` - pnpm -- turbo run build --filter=cli - pnpm test -F turborepo-tests-integration -- "run-summary" - ``` - -- Updating integration tests - - ```bash - turbo run build --filter=cli - pnpm --filter turborepo-tests-integration test:interactive - ``` - - You can pass a test name to run a single test, or a directory to run all tests in that directory. - - ```bash - pnpm --filter turborepo-tests-integration test:interactive tests/turbo-help.t - ``` - -## Manually testing `turbo` - -After [building `turbo`](#building-turborepo), you can manually test `turbo` for the behaviors you're affecting with your changes. We recommend setting an alias to the built binary so you can call it with your alias. - -```bash -alias devturbo='~/projects/turbo/target/debug/turbo' -devturbo run build --skip-infer -``` - -> [!IMPORTANT] -> The `--skip-infer` flag is required so that `turbo` doesn't try to use a locally installed binary of `turbo`. Forgetting to use this flag will cause `devturbo` to defer to the binary installed into the repository. - -A non-exhaustive list of things to check on: - -- Features related to your changes -- Test with and without daemon -- Installation scenarios - - Global only. `turbo` is installed as global binary without a local `turbo` in repository. - - Local only. `turbo` is installed as local binary without global `turbo` in PATH. turbo` is invoked via a root package - script. - - Global and local. `turbo` is installed as global binary, and local `turbo` in repository. Global `turbo` delegates to - local `turbo` - -### Repositories to test with - -There are many open-source Turborepos out in the community that you can test with. A few are listed below: - -- [Next.js](https://github.com/vercel/next.js) -- [tldraw](https://github.com/tldraw/tldraw) -- [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss) -- [Vercel CLI](https://github.com/vercel/vercel) -- This repository! Keep in mind that you'll be building and running `turbo` in the same repository, which can be confusing at times. - -## Debugging tips - -### Links in error messages - -Many of Turborepo's error messages include links to information or documentation to help end users. - -The base URL for the links can be set to a value of your choosing by providing a `TURBO_SITE` environment variable at compilation time. - -```bash -TURBO_SITE="http://localhost:3000" cargo build -``` - -### Verbose logging - -Verbose logging can be enabled by using the `-v`, `-vv`, or `-vvv` flag on your `turbo` command, depending on the level of logging you're looking for. - -```bash -turbo build --vvv -``` - -### Crash logs - -In the event of a crash, Rust's crash logs will be written to your temp directory. When `turbo` crashes, the location of the crash log will be printed to the console. - -### Terminal UI debugging - -The architecture of the Terminal UI makes for a tricky debugging experience. Because the UI writes to the console through `stdout` in a specific way, using `println!()` statements won't work as expected. - -Instead, use `eprintln!()` to print to `stdout` and output `stdout` to a file: - -```bash -# devturbo is an alias to the debug binary of `turbo` in this case -devturbo run build --ui=tui --skip-infer 2&> ~/tmp/logs.txt -``` - -> [!IMPORTANT] -> The `--skip-infer` flag is required so that `turbo` doesn't try to use a locally installed binary of `turbo`. Forgetting to use this flag will cause `devturbo` to defer to the binary installed into the repository rather than the one you're developing. - -## Publishing `turbo` to the npm registry - -See [the publishing guide](./release.md). - -## Contributing to examples - -Contributing to examples helps the Turborepo community by showcasing how to use Turborepo in real-world scenarios with other tools and frameworks. They can be found in [the examples directory](https://github.com/vercel/turborepo/tree/main/examples) of this repository. - -> [!IMPORTANT] -> As Turborepo usage has grown, the community has contributed more and more examples to the repository. While this is exciting for us on the core team, we're unable to maintain the full surface area of every example, given the constant updates across the breadth of tooling that Turborepo works with in the examples. -> -> Because of this, a handful of the examples are explictly marked as maintained by the core team. For the rest, we work with the community to keep them as up to date and correct as possible. If you find a problem with a community-supported template, we ask that you do not open a GitHub Issue for it. Instead, please open a pull request with the needed fixes. - -The `basic` example is the default used by `create-turbo`. - -For simplicity, each example is treated as a standalone "repository", separate from the rest of the repository, with its own dependencies, lockfile, `turbo` version, etc. You are able to run code and make code updates in an example without needing to install the dependencies of the rest of the repository. - -> [!NOTE] -> You may find that opening your code editor directly in the example's directory that you're working on can give you a better sense of how the example will feel to community members who download the example. - -### Contributing to an existing example - -To contribute to an existing example, create your code updates and submit a pull request to the repository. No special steps are required to contribute to an example. - -### Philosophy for new examples - -Turborepo works with any framework, tool, or even language. Because of this, the community often expresses interest in creating new examples to showcase Turborepo working with other tooling. - -However, we aim to have as few examples in the repository while still showcasing Turborepo's flexibility. By having fewer examples, the core team has a better chance to maintain the collection of examples, keeping them at a higher quality. The ecosystem evolves quickly, and keeping every example up-to-date for every tool requires a wealth of attention. Our goal is to balance the needs of the core team and the community together to keep the Turboverse in a healthy state. - -Due to these considerations, we ask that you first [open a Discussion](https://github.com/vercel/turborepo/discussions/categories/ideas) before working on a new example for the repository. It's best to make sure ahead of time that the example you'd like to propose will be accepted. Once you have received approval, you can work on and create a pull request for your example. - -#### Designing a new example - -Each example should have a specific focus when compared to the `basic` example. The goal is for an example to show how to use a singular, distinct technology's usage in a Turborepo. - -You're encouraged to start with the [`basic` example](https://github.com/vercel/turborepo/tree/main/examples/basic) and add your specific tool of interest to it. Each example should have as few modifications to the `basic` example as possible required to showcase the tool or framework. - -Key characteristics of a great example include: - -- One technology added to the `basic` example -- An updated README at the root of the example directory. Make sure to include any steps required to run the example -- All tasks in `turbo.json` in the example run successfully without any code changes needed -- Works with every package manager listed in our [Support Policy](https://turbo.build/repo/docs/getting-started/support-policy#package-managers) - -Once you've created your example (with prior approval, as discussed above), you can submit a pull request to the repository. - -### Testing examples - -To test out the experience of your example with `create-turbo`, run `create-turbo` with the `--example` flag pointed to a URL to your example's source code: - -```bash -npx create-turbo@latest --example https://github.com/your-org/your-repo/tree/your-branch/... -``` - -This will allow you to use the example as a user would. diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index c72920436ca3e..0000000000000 --- a/Cargo.lock +++ /dev/null @@ -1,7610 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "addr2line" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" -dependencies = [ - "backtrace", -] - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "ascii_utils" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" - -[[package]] -name = "assert-json-diff" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "assert_cmd" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d6b683edf8d1119fe420a94f8a7e389239666aa72e65495d91c00462510151" -dependencies = [ - "anstyle", - "bstr 1.8.0", - "doc-comment", - "predicates", - "predicates-core", - "predicates-tree", - "wait-timeout", -] - -[[package]] -name = "ast_node" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9184f2b369b3e8625712493c89b785881f27eedc6cde480a81883cef78868b2" -dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.58", -] - -[[package]] -name = "async-channel" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand 1.9.0", - "futures-lite", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-graphql" -version = "7.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b76aba2f176af685c2229633881a3adeae51f87ae1811781e73910b7001c93e" -dependencies = [ - "async-graphql-derive", - "async-graphql-parser", - "async-graphql-value", - "async-stream", - "async-trait", - "base64 0.22.1", - "bytes", - "fast_chemail", - "fnv", - "futures-util", - "handlebars", - "http 1.1.0", - "indexmap 2.2.6", - "mime", - "multer", - "num-traits", - "once_cell", - "pin-project-lite", - "regex", - "serde", - "serde_json", - "serde_urlencoded", - "static_assertions_next", - "tempfile", - "thiserror", -] - -[[package]] -name = "async-graphql-axum" -version = "7.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686e48ce7820a1cf404b5c8e9b90ae24d03c867a408d8d651183945c7a554982" -dependencies = [ - "async-graphql", - "async-trait", - "axum 0.7.5", - "bytes", - "futures-util", - "serde_json", - "tokio", - "tokio-stream", - "tokio-util", - "tower-service", -] - -[[package]] -name = "async-graphql-derive" -version = "7.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e2e26a6b44bc61df3ca8546402cf9204c28e30c06084cc8e75cd5e34d4f150" -dependencies = [ - "Inflector", - "async-graphql-parser", - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "strum", - "syn 2.0.58", - "thiserror", -] - -[[package]] -name = "async-graphql-parser" -version = "7.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f801451484b4977d6fe67b29030f81353cabdcbb754e5a064f39493582dac0cf" -dependencies = [ - "async-graphql-value", - "pest", - "serde", - "serde_json", -] - -[[package]] -name = "async-graphql-value" -version = "7.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69117c43c01d81a69890a9f5dd6235f2f027ca8d1ec62d6d3c5e01ca0edb4f2b" -dependencies = [ - "bytes", - "indexmap 2.2.6", - "serde", - "serde_json", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite", - "log", - "parking", - "polling", - "rustix 0.37.23", - "slab", - "socket2 0.4.9", - "waker-fn", -] - -[[package]] -name = "async-lock" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-object-pool" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb901c30ebc2fc4ab46395bbfbdba9542c16559d853645d75190c3056caf3bc" -dependencies = [ - "async-std", -] - -[[package]] -name = "async-once-cell" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9338790e78aa95a416786ec8389546c4b6a1dfc3dc36071ed9518a9413a542eb" - -[[package]] -name = "async-process" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" -dependencies = [ - "async-io", - "async-lock", - "autocfg", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "libc", - "signal-hook", - "windows-sys 0.42.0", -] - -[[package]] -name = "async-std" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "async-task" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" - -[[package]] -name = "async-trait" -version = "0.1.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "atomic-waker" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "axum" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f8ccfd9221ee7d1f3d4b33e1f8319b3a81ed8f61f2ea40b37b859794b4491" -dependencies = [ - "async-trait", - "axum-core 0.3.3", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.11", - "http-body 0.4.5", - "hyper 0.14.28", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" -dependencies = [ - "async-trait", - "axum-core 0.4.3", - "base64 0.21.4", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.4.1", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sha1", - "sync_wrapper 1.0.1", - "tokio", - "tokio-tungstenite", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.11", - "http-body 0.4.5", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 0.1.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-server" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bace45b270e36e3c27a190c65883de6dfc9f1d18c829907c127464815dc67b24" -dependencies = [ - "bytes", - "futures-util", - "http 0.2.11", - "http-body 0.4.5", - "hyper 0.14.28", - "tokio", - "tower-service", -] - -[[package]] -name = "axum-server" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56bac90848f6a9393ac03c63c640925c4b7c8ca21654de40d53f55964667c7d8" -dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.4.1", - "hyper-util", - "pin-project-lite", - "tokio", - "tower", - "tower-service", -] - -[[package]] -name = "backtrace" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "backtrace-ext" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" -dependencies = [ - "backtrace", -] - -[[package]] -name = "base-encode" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17bd29f7c70f32e9387f4d4acfa5ea7b7749ef784fb78cf382df97069337b8c" - -[[package]] -name = "base64" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "better_scoped_tls" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794edcc9b3fb07bb4aecaa11f093fd45663b4feadb782d68303a2268bc2701de" -dependencies = [ - "scoped-tls", -] - -[[package]] -name = "biome_console" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c672a9e31e47f8df74549a570ea3245a93ce3404115c724bb16762fcbbfe17e1" -dependencies = [ - "biome_markup", - "biome_text_size", - "schemars", - "serde", - "termcolor", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "biome_deserialize" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f619dc8ca0595ed8850d729ebc71722d4233aba68c5aec7d9993a53e59f3fe" -dependencies = [ - "biome_console", - "biome_deserialize_macros", - "biome_diagnostics", - "biome_json_parser", - "biome_json_syntax", - "biome_rowan", - "bitflags 2.5.0", - "indexmap 2.2.6", - "serde", - "serde_json", -] - -[[package]] -name = "biome_deserialize_macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c12826fff87ac09f63bbacf8bdf5225dfdf890da04d426f758cbcacf068e3e" -dependencies = [ - "biome_string_case", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "biome_diagnostics" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe1317b6d610541c4e6a0e1f803a946f153ace3468bbc77a8f273dcb04ee526f" -dependencies = [ - "backtrace", - "biome_console", - "biome_diagnostics_categories", - "biome_diagnostics_macros", - "biome_rowan", - "biome_text_edit", - "biome_text_size", - "bitflags 2.5.0", - "bpaf", - "oxc_resolver 1.12.0", - "serde", - "termcolor", - "unicode-width", -] - -[[package]] -name = "biome_diagnostics_categories" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832080d68a2ee2f198d98ff5d26fc0f5c2566907f773d105a4a049ee07664d19" -dependencies = [ - "quote", - "serde", -] - -[[package]] -name = "biome_diagnostics_macros" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540fec04d2e789fb992128c63d111b650733274afffff1cb3f26c8dff5167d3b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "biome_json_factory" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e409eb289040f3660689dad178b00b6ac8cfa9a7fffd8225f35cb6b3d36437cf" -dependencies = [ - "biome_json_syntax", - "biome_rowan", -] - -[[package]] -name = "biome_json_parser" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6d23fb9b683e6356c094b4a0cb38f8aa0acee60ce9c3ef24628d21a204de4d" -dependencies = [ - "biome_console", - "biome_diagnostics", - "biome_json_factory", - "biome_json_syntax", - "biome_parser", - "biome_rowan", - "biome_unicode_table", - "tracing", - "unicode-bom", -] - -[[package]] -name = "biome_json_syntax" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2645ca57f75680d3d390b2482c35db5850b1d849e1f96151a12f15f4abdb097" -dependencies = [ - "biome_rowan", - "serde", -] - -[[package]] -name = "biome_markup" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a7f11cf91599594528e97d216044ef4e410a103327212d909f215cbafe2fd9c" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", -] - -[[package]] -name = "biome_parser" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955dd999f32c086371d5c0e64b4ea1a50f50c98f1f31a3b9fe17ef47198de19b" -dependencies = [ - "biome_console", - "biome_diagnostics", - "biome_rowan", - "bitflags 2.5.0", - "drop_bomb", -] - -[[package]] -name = "biome_rowan" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c2dc25a7ba6ae89526340034abed6c89fac35b79060786771e32ed4aac77e7" -dependencies = [ - "biome_text_edit", - "biome_text_size", - "countme", - "hashbrown 0.12.3", - "memoffset 0.8.0", - "rustc-hash 1.1.0", - "tracing", -] - -[[package]] -name = "biome_string_case" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28b4d0e08c2f13f1c9e0df4e7a8f9bfa03ef3803713d1bcd5110578cc5c67be" - -[[package]] -name = "biome_text_edit" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d486fdd96d5dad6428213ce64e6b9eb5bfb2fce6387fe901e844d386283de509" -dependencies = [ - "biome_text_size", - "serde", - "similar", -] - -[[package]] -name = "biome_text_size" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec604d15cefdced636255400359aeacfdea5d1e79445efc7aa32a0de7f0319b" -dependencies = [ - "serde", -] - -[[package]] -name = "biome_unicode_table" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e8604d34b02180a58af1dbdaac166f1805f27f5370934142a3246f83870952" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blocking" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "atomic-waker", - "fastrand 1.9.0", - "futures-lite", -] - -[[package]] -name = "bpaf" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19232d7d855392d993f6dabd8dea40a457a6d24ef679fe98f5edca811bb11e21" -dependencies = [ - "bpaf_derive", -] - -[[package]] -name = "bpaf_derive" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efeab2975f8102de445dcf898856a638332403c50216144653a89aec22fd79e0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata 0.1.10", -] - -[[package]] -name = "bstr" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" -dependencies = [ - "memchr", - "regex-automata 0.4.6", - "serde", -] - -[[package]] -name = "build-fs-tree" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c68339add1d0c864575cd425203adee58c8b64ea1709b35bb90fc0fc07e4286" -dependencies = [ - "derive_more", - "pipe-trait", - "serde", - "serde_yaml", - "text-block-macros", -] - -[[package]] -name = "build-target" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -dependencies = [ - "allocator-api2", -] - -[[package]] -name = "bytecount" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" -dependencies = [ - "serde", -] - -[[package]] -name = "camino" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" -dependencies = [ - "serde", -] - -[[package]] -name = "capnp" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e65021d89250bbfe7c2791789ced2c4bdc21b0e8bb59c64f3fd6145a5fd678" - -[[package]] -name = "capnp" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eddbd729bd9742aa22d29e871a42ffea7f216a4ddbfdaf09ea88150ef2e7f76" -dependencies = [ - "embedded-io", -] - -[[package]] -name = "capnpc" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f3c8ee94d993d03150153e9a57a6ff330127b1c1ad76475051e1cef79c2d" -dependencies = [ - "capnp 0.18.1", -] - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - -[[package]] -name = "castaway" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" - -[[package]] -name = "castaway" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" -dependencies = [ - "rustversion", -] - -[[package]] -name = "cc" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.6", -] - -[[package]] -name = "clap" -version = "4.5.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_complete" -version = "4.5.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7db6eca8c205649e8d3ccd05aa5042b1800a784e56bc7c43524fde8abbfa9b" -dependencies = [ - "clap", -] - -[[package]] -name = "clap_derive" -version = "4.5.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "clipboard-win" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" -dependencies = [ - "error-code", -] - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "combine" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "command-group" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916" -dependencies = [ - "async-trait", - "nix 0.26.2", - "tokio", - "winapi", -] - -[[package]] -name = "compact_str" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" -dependencies = [ - "castaway 0.2.2", - "cfg-if", - "itoa", - "ryu", - "static_assertions", -] - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "config" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" -dependencies = [ - "async-trait", - "lazy_static", - "nom", - "pathdiff", - "serde", - "serde_json", -] - -[[package]] -name = "console" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.45.0", -] - -[[package]] -name = "const-random" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a" -dependencies = [ - "const-random-macro", -] - -[[package]] -name = "const-random-macro" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom", - "once_cell", - "tiny-keccak", -] - -[[package]] -name = "const_format" -version = "0.2.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "countme" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" - -[[package]] -name = "cpp_demangle" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crop" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7cba78cdac608a5e2e645de47e566c0f63e1b6110318736581ec97d5669767" -dependencies = [ - "str_indices", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset 0.9.0", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crossterm" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" -dependencies = [ - "bitflags 1.3.2", - "crossterm_winapi", - "libc", - "mio 0.8.11", - "parking_lot", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" -dependencies = [ - "bitflags 2.5.0", - "crossterm_winapi", - "futures-core", - "libc", - "mio 0.8.11", - "parking_lot", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "ctor" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4056f63fce3b82d852c3da92b08ea59959890813a7f4ce9c0ff85b10cf301b" -dependencies = [ - "quote", - "syn 2.0.58", -] - -[[package]] -name = "ctrlc" -version = "3.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" -dependencies = [ - "nix 0.28.0", - "windows-sys 0.52.0", -] - -[[package]] -name = "curl" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" -dependencies = [ - "curl-sys", - "libc", - "openssl-probe", - "openssl-sys", - "schannel", - "socket2 0.4.9", - "winapi", -] - -[[package]] -name = "curl-sys" -version = "0.4.60+curl-7.88.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "717abe2cb465a5da6ce06617388a3980c9a2844196734bec8ccb8e575250f13f" -dependencies = [ - "cc", - "libc", - "libnghttp2-sys", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "winapi", -] - -[[package]] -name = "darling" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.58", -] - -[[package]] -name = "darling_macro" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "debugid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" -dependencies = [ - "uuid", -] - -[[package]] -name = "deranged" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 1.0.109", -] - -[[package]] -name = "derive_setters" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8ef033054e131169b8f0f9a7af8f5533a9436fadf3c500ed547f730f07090d" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "dialoguer" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" -dependencies = [ - "console", - "fuzzy-matcher", - "shell-words", - "tempfile", - "thiserror", - "zeroize", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "difflib" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "directories" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" -dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys 0.3.7", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dlv-list" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" -dependencies = [ - "const-random", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "drop_bomb" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" - -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] -name = "dyn-clone" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "embedded-io" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bbadc628dc286b9ae02f0cb0f5411c056eb7487b72f0083203f115de94060" - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding_rs" -version = "0.8.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "erased-serde" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" -dependencies = [ - "serde", -] - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "error-code" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fast_chemail" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4" -dependencies = [ - "ascii_utils", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "filedescriptor" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" -dependencies = [ - "libc", - "thiserror", - "winapi", -] - -[[package]] -name = "filetime" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", -] - -[[package]] -name = "findshlibs" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" -dependencies = [ - "cc", - "lazy_static", - "libc", - "winapi", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "from_variant" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4" -dependencies = [ - "proc-macro2", - "swc_macros_common", - "syn 2.0.58", -] - -[[package]] -name = "fs-err" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fuzzy-matcher" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" -dependencies = [ - "thread_local", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "git2" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" -dependencies = [ - "bitflags 2.5.0", - "libc", - "libgit2-sys", - "log", - "url", -] - -[[package]] -name = "globset" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" -dependencies = [ - "aho-corasick", - "bstr 1.8.0", - "log", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", -] - -[[package]] -name = "globwalk" -version = "0.1.0" -dependencies = [ - "camino", - "itertools 0.10.5", - "path-clean", - "path-slash", - "rayon", - "regex", - "tempfile", - "test-case", - "thiserror", - "tracing", - "turbopath", - "walkdir", - "wax", -] - -[[package]] -name = "globwatch" -version = "0.1.0" -dependencies = [ - "futures", - "itertools 0.10.5", - "merge-streams", - "notify", - "stop-token", - "test-case", - "thiserror", - "tokio", - "tokio-stream", - "tracing", - "tracing-subscriber", - "tracing-test", - "turbopath", - "unic-segment", -] - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "go-parse-duration" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558b88954871f5e5b2af0e62e2e176c8bde7a6c2c4ed41b13d138d96da2e2cbd" - -[[package]] -name = "h2" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.11", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.1.0", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "handlebars" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" -dependencies = [ - "log", - "pest", - "pest_derive", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - -[[package]] -name = "hstr" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412" -dependencies = [ - "hashbrown 0.14.5", - "new_debug_unreachable", - "once_cell", - "phf", - "rustc-hash 1.1.0", - "triomphe", -] - -[[package]] -name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http 0.2.11", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.1.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "httpmock" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b02e044d3b4c2f94936fb05f9649efa658ca788f44eb6b87554e2033fc8ce93" -dependencies = [ - "assert-json-diff", - "async-object-pool", - "async-trait", - "base64 0.21.4", - "crossbeam-utils", - "form_urlencoded", - "futures-util", - "hyper 0.14.28", - "isahc", - "lazy_static", - "levenshtein", - "log", - "regex", - "serde", - "serde_json", - "serde_regex", - "similar", - "tokio", - "url", -] - -[[package]] -name = "human-panic" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f016c89920bbb30951a8405ecacbb4540db5524313b9445736e7e1855cf370" -dependencies = [ - "anstream", - "anstyle", - "backtrace", - "os_info", - "serde", - "serde_derive", - "toml", - "uuid", -] - -[[package]] -name = "human_format" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3b1f728c459d27b12448862017b96ad4767b1ec2ec5e6434e99f1577f085b8" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.5", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.6", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.1", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.4.1", - "hyper-util", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper 0.14.28", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.4.1", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", - "pin-project-lite", - "socket2 0.5.6", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "ignore" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata 0.4.6", - "same-file", - "walkdir", - "winapi-util", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", - "serde", -] - -[[package]] -name = "indicatif" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" -dependencies = [ - "console", - "number_prefix", - "portable-atomic", - "unicode-width", -] - -[[package]] -name = "indoc" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f2cb48b81b1dc9f39676bf99f5499babfec7cd8fe14307f7b3d747208fb5690" - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "insta" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" -dependencies = [ - "console", - "lazy_static", - "linked-hash-map", - "regex", - "serde", - "similar", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "ioctl-rs" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7970510895cee30b3e9128319f2cefd4bde883a39f38baa279567ba3a7eb97d" -dependencies = [ - "libc", -] - -[[package]] -name = "ipnet" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" - -[[package]] -name = "is-macro" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2069faacbe981460232f880d26bf3c7634e322d49053aa48c27e3ae642f728f1" -dependencies = [ - "Inflector", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi 0.3.9", - "rustix 0.38.31", - "windows-sys 0.48.0", -] - -[[package]] -name = "is_ci" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" - -[[package]] -name = "isahc" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" -dependencies = [ - "async-channel", - "castaway 0.1.2", - "crossbeam-utils", - "curl", - "curl-sys", - "encoding_rs", - "event-listener", - "futures-lite", - "http 0.2.11", - "log", - "mime", - "once_cell", - "polling", - "slab", - "sluice", - "tracing", - "tracing-futures", - "url", - "waker-fn", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "json-strip-comments" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d129799327c8f80861e467c59b825ba24c277dba6ad0d71a141dc98f9e04ee" - -[[package]] -name = "jsonc-parser" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1853e40333206f9a685358046d13ab200169e3ee573019bddf0ede0dc29307" - -[[package]] -name = "jsonc-parser" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7725c320caac8c21d8228c1d055af27a995d371f78cc763073d3e068323641b5" - -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lazy-regex" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff63c423c68ea6814b7da9e88ce585f793c87ddd9e78f646970891769c8235d4" -dependencies = [ - "lazy-regex-proc_macros", - "once_cell", - "regex", -] - -[[package]] -name = "lazy-regex-proc_macros" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8edfc11b8f56ce85e207e62ea21557cfa09bb24a8f6b04ae181b086ff8611c22" -dependencies = [ - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "levenshtein" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" - -[[package]] -name = "libc" -version = "0.2.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" - -[[package]] -name = "libgit2-sys" -version = "0.17.0+1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" -dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libloading" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "libm" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" - -[[package]] -name = "libnghttp2-sys" -version = "0.1.10+1.61.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "959c25552127d2e1fa72f0e52548ec04fc386e827ba71a7bd01db46a447dc135" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "libz-sys" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -dependencies = [ - "value-bag", -] - -[[package]] -name = "lru" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2c024b41519440580066ba82aab04092b333e09066a5eb86c7c4890df31f22" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "lsp-types" -version = "0.94.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" -dependencies = [ - "bitflags 1.3.2", - "serde", - "serde_json", - "serde_repr", - "url", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matchit" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" - -[[package]] -name = "memchr" -version = "2.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "merge" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9" -dependencies = [ - "merge_derive", - "num-traits", -] - -[[package]] -name = "merge-streams" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f84f6452969abd246e7ac1fe4fe75906c76e8ec88d898df9aef37e0f3b6a7c2" -dependencies = [ - "futures-core", - "pin-project", -] - -[[package]] -name = "merge_derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "miette" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" -dependencies = [ - "backtrace", - "backtrace-ext", - "is-terminal", - "miette-derive", - "once_cell", - "owo-colors", - "supports-color", - "supports-hyperlinks", - "supports-unicode", - "terminal_size 0.1.17", - "textwrap", - "thiserror", - "unicode-width", -] - -[[package]] -name = "miette-derive" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "mio" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "multer" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 1.1.0", - "httparse", - "memchr", - "mime", - "spin", - "version_check", -] - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "napi" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbf98e1bcb85cc441bbf7cdfb11070d2537a100e2697d75397b2584c32492d1" -dependencies = [ - "bitflags 2.5.0", - "ctor", - "napi-derive", - "napi-sys", - "once_cell", - "tokio", -] - -[[package]] -name = "napi-build" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" - -[[package]] -name = "napi-derive" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7622f0dbe0968af2dacdd64870eee6dee94f93c989c841f1ad8f300cf1abd514" -dependencies = [ - "cfg-if", - "convert_case 0.6.0", - "napi-derive-backend", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "napi-derive-backend" -version = "1.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cf2d74ac66fd1cccb646be75fdd1c1dce8acfe20a68f61566a31da0d3eb9786" -dependencies = [ - "convert_case 0.6.0", - "once_cell", - "proc-macro2", - "quote", - "regex", - "semver 1.0.23", - "syn 2.0.58", -] - -[[package]] -name = "napi-sys" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b" -dependencies = [ - "libloading", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.6.5", - "pin-utils", -] - -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", - "pin-utils", - "static_assertions", -] - -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "node-semver" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f390c1756333538f2aed01cf280a56bc683e199b9804a504df6e7320d40116" -dependencies = [ - "bytecount", - "miette", - "nom", - "serde", - "thiserror", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "notify" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" -dependencies = [ - "bitflags 2.5.0", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio 0.8.11", - "walkdir", - "windows-sys 0.48.0", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] -name = "object" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "openssl" -version = "0.10.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b277f87dacc05a6b709965d1cbafac4649d6ce9f3ce9ceb88508b5666dfec9" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a95792af3c4e0153c3914df2261bedd30a98476f94dc892b67dfe1d89d433a04" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-multimap" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d6a8c22fc714f0c2373e6091bf6f5e9b37b1bc0b1184874b7e0a4e303d318f" -dependencies = [ - "dlv-list", - "hashbrown 0.14.5", -] - -[[package]] -name = "os_info" -version = "3.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" -dependencies = [ - "log", - "serde", - "windows-sys 0.52.0", -] - -[[package]] -name = "os_str_bytes" -version = "6.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" -dependencies = [ - "memchr", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "owo-colors" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" - -[[package]] -name = "oxc_resolver" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c20bb345f290c46058ba650fef7ca2b579612cf2786b927ebad7b8bec0845a7" -dependencies = [ - "cfg-if", - "dashmap 6.1.0", - "dunce", - "indexmap 2.2.6", - "json-strip-comments", - "once_cell", - "rustc-hash 2.0.0", - "serde", - "serde_json", - "simdutf8", - "thiserror", - "tracing", -] - -[[package]] -name = "oxc_resolver" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da33ec82d0f4770f4b5c120d6a1d8e45de2d99ae2672a7ee6bd29092ada945f2" -dependencies = [ - "cfg-if", - "dashmap 6.1.0", - "indexmap 2.2.6", - "json-strip-comments", - "once_cell", - "rustc-hash 2.0.0", - "serde", - "serde_json", - "simdutf8", - "thiserror", - "tracing", -] - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.3.5", - "smallvec", - "windows-targets 0.48.1", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "path-clean" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" - -[[package]] -name = "path-slash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" - -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "pest" -version = "2.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "pest_meta" -version = "2.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - -[[package]] -name = "petgraph" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" -dependencies = [ - "fixedbitset", - "indexmap 1.9.3", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pidlock" -version = "0.1.4" -dependencies = [ - "libc", - "log", - "rand", - "tempfile", - "thiserror", - "windows-sys 0.45.0", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pipe-trait" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1be1ec9e59f0360aefe84efa6f699198b685ab0d5718081e9f72aa2344289e2" - -[[package]] -name = "pkg-config" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" - -[[package]] -name = "polling" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e1f879b2998099c2d69ab9605d145d5b661195627eccc680002c4918a7fb6fa" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.45.0", -] - -[[package]] -name = "pori" -version = "0.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a63d338dec139f56dacc692ca63ad35a6be6a797442479b55acd611d79e906" -dependencies = [ - "nom", -] - -[[package]] -name = "port_scanner" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325a6d2ac5dee293c3b2612d4993b98aec1dff096b0a2dae70ed7d95784a05da" - -[[package]] -name = "portable-atomic" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b" - -[[package]] -name = "portable-pty" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806ee80c2a03dbe1a9fb9534f8d19e4c0546b790cde8fd1fea9d6390644cb0be" -dependencies = [ - "anyhow", - "bitflags 1.3.2", - "downcast-rs", - "filedescriptor", - "lazy_static", - "libc", - "log", - "nix 0.25.1", - "serial", - "shared_library", - "shell-words", - "winapi", - "winreg", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "pprof" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978385d59daf9269189d052ca8a84c1acfd0715c0599a5d5188d4acc078ca46a" -dependencies = [ - "backtrace", - "cfg-if", - "findshlibs", - "libc", - "log", - "nix 0.26.2", - "once_cell", - "parking_lot", - "prost 0.11.8", - "prost-build", - "prost-derive 0.11.8", - "sha2", - "smallvec", - "symbolic-demangle", - "tempfile", - "thiserror", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "predicates" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" -dependencies = [ - "anstyle", - "difflib", - "itertools 0.10.5", - "predicates-core", -] - -[[package]] -name = "predicates-core" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" - -[[package]] -name = "predicates-tree" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" -dependencies = [ - "predicates-core", - "termtree", -] - -[[package]] -name = "pretty_assertions" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" -dependencies = [ - "diff", - "yansi", -] - -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" -dependencies = [ - "bytes", - "prost-derive 0.11.8", -] - -[[package]] -name = "prost" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" -dependencies = [ - "bytes", - "prost-derive 0.12.3", -] - -[[package]] -name = "prost-build" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c828f93f5ca4826f97fedcbd3f9a536c16b12cff3dbbb4a007f932bbad95b12" -dependencies = [ - "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap", - "petgraph", - "prettyplease", - "prost 0.11.8", - "prost-types", - "regex", - "syn 1.0.109", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-derive" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" -dependencies = [ - "anyhow", - "itertools 0.11.0", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "prost-types" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" -dependencies = [ - "prost 0.11.8", -] - -[[package]] -name = "psm" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" -dependencies = [ - "cc", -] - -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "quickcheck" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" -dependencies = [ - "env_logger", - "log", - "rand", -] - -[[package]] -name = "quinn" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.0.0", - "rustls", - "socket2 0.5.6", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" -dependencies = [ - "bytes", - "rand", - "ring", - "rustc-hash 2.0.0", - "rustls", - "slab", - "thiserror", - "tinyvec", - "tracing", -] - -[[package]] -name = "quinn-udp" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" -dependencies = [ - "libc", - "once_cell", - "socket2 0.5.6", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "ratatui" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb12f8fbf6c62614b0d56eb352af54f6a22410c3b079eb53ee93c7b97dd31d8" -dependencies = [ - "bitflags 2.5.0", - "cassowary", - "compact_str", - "crossterm 0.27.0", - "indoc", - "itertools 0.12.0", - "lru", - "paste", - "stability", - "strum", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "raw-window-handle" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f851a03551ceefd30132e447f07f96cb7011d6b658374f3aed847333adb5559" - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.3", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - -[[package]] -name = "reqwest" -version = "0.12.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.4.1", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-native-certs", - "rustls-pemfile", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots", - "windows-registry", -] - -[[package]] -name = "ring" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.48.0", -] - -[[package]] -name = "rust-ini" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.23", -] - -[[package]] -name = "rustc_version_runtime" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d31b7153270ebf48bf91c65ae5b0c00e749c4cfad505f66530ac74950249582f" -dependencies = [ - "rustc_version 0.2.3", - "semver 0.9.0", -] - -[[package]] -name = "rustix" -version = "0.37.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" -dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys 0.4.13", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.23.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" -dependencies = [ - "windows-sys 0.42.0", -] - -[[package]] -name = "schemars" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 1.0.109", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "serde_json" -version = "1.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" -dependencies = [ - "indexmap 2.2.6", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa", - "serde", -] - -[[package]] -name = "serde_regex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" -dependencies = [ - "regex", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "serde_spanned" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.9.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" -dependencies = [ - "indexmap 2.2.6", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "serial" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1237a96570fc377c13baa1b88c7589ab66edced652e43ffb17088f003db3e86" -dependencies = [ - "serial-core", - "serial-unix", - "serial-windows", -] - -[[package]] -name = "serial-core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f46209b345401737ae2125fe5b19a77acce90cd53e1658cda928e4fe9a64581" -dependencies = [ - "libc", -] - -[[package]] -name = "serial-unix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03fbca4c9d866e24a459cbca71283f545a37f8e3e002ad8c70593871453cab7" -dependencies = [ - "ioctl-rs", - "libc", - "serial-core", - "termios", -] - -[[package]] -name = "serial-windows" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c6d3b776267a75d31bbdfd5d36c0ca051251caafc285827052bc53bcdc8162" -dependencies = [ - "libc", - "serial-core", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shared_child" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "shared_library" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" -dependencies = [ - "lazy_static", - "libc", -] - -[[package]] -name = "shell-words" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio 0.8.11", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - -[[package]] -name = "similar" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" -dependencies = [ - "bstr 0.2.17", - "unicode-segmentation", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "sluice" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" -dependencies = [ - "async-channel", - "futures-core", - "futures-io", -] - -[[package]] -name = "smallvec" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" - -[[package]] -name = "smartstring" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" -dependencies = [ - "autocfg", - "static_assertions", - "version_check", -] - -[[package]] -name = "smawk" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "stability" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd1b177894da2a2d9120208c3386066af06a488255caabc5de8ddca22dbc3ce" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "stacker" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.59.0", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "static_assertions_next" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7beae5182595e9a8b683fa98c4317f956c9a2dec3b9716990d20023cc60c766" - -[[package]] -name = "stop-token" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af91f480ee899ab2d9f8435bfdfc14d08a5754bd9d3fef1f1a1c23336aad6c8b" -dependencies = [ - "async-channel", - "cfg-if", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "str_indices" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9557cb6521e8d009c51a8666f09356f4b817ba9ba0981a305bd86aee47bd35c" - -[[package]] -name = "string_enum" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e383308aebc257e7d7920224fa055c632478d92744eca77f99be8fa1545b90" -dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.58", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "struct_iterable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "849a064c6470a650b72e41fa6c057879b68f804d113af92900f27574828e7712" -dependencies = [ - "struct_iterable_derive", - "struct_iterable_internal", -] - -[[package]] -name = "struct_iterable_derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb939ce88a43ea4e9d012f2f6b4cc789deb2db9d47bad697952a85d6978662c" -dependencies = [ - "erased-serde", - "proc-macro2", - "quote", - "struct_iterable_internal", - "syn 2.0.58", -] - -[[package]] -name = "struct_iterable_internal" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9426b2a0c03e6cc2ea8dbc0168dbbf943f88755e409fb91bcb8f6a268305f4a" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.58", -] - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "supports-color" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" -dependencies = [ - "is-terminal", - "is_ci", -] - -[[package]] -name = "supports-hyperlinks" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" -dependencies = [ - "is-terminal", -] - -[[package]] -name = "supports-unicode" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" -dependencies = [ - "is-terminal", -] - -[[package]] -name = "svix-ksuid" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75d773122e48817eb6eb74605cf799574a855bf4c7eb0c1bb06c005067123b13" -dependencies = [ - "base-encode", - "byteorder", - "getrandom", - "serde", - "time", -] - -[[package]] -name = "swc_allocator" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc8bd3075d1c6964010333fae9ddcd91ad422a4f8eb8b3206a9b2b6afb4209e" -dependencies = [ - "bumpalo", - "hashbrown 0.14.5", - "ptr_meta", - "rustc-hash 1.1.0", - "triomphe", -] - -[[package]] -name = "swc_atoms" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125" -dependencies = [ - "hstr", - "once_cell", - "rustc-hash 1.1.0", - "serde", -] - -[[package]] -name = "swc_common" -version = "0.37.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12d0a8eaaf1606c9207077d75828008cb2dfb51b095a766bd2b72ef893576e31" -dependencies = [ - "ast_node", - "better_scoped_tls", - "cfg-if", - "either", - "from_variant", - "new_debug_unreachable", - "num-bigint", - "once_cell", - "parking_lot", - "rustc-hash 1.1.0", - "serde", - "siphasher", - "swc_allocator", - "swc_atoms", - "swc_eq_ignore_macros", - "swc_visit", - "termcolor", - "tracing", - "unicode-width", - "url", -] - -[[package]] -name = "swc_ecma_ast" -version = "0.118.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f866d12e4d519052b92a0a86d1ac7ff17570da1272ca0c89b3d6f802cd79df" -dependencies = [ - "bitflags 2.5.0", - "is-macro", - "num-bigint", - "phf", - "scoped-tls", - "serde", - "string_enum", - "swc_atoms", - "swc_common", - "unicode-id-start", -] - -[[package]] -name = "swc_ecma_parser" -version = "0.149.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683dada14722714588b56481399c699378b35b2ba4deb5c4db2fb627a97fb54b" -dependencies = [ - "either", - "new_debug_unreachable", - "num-bigint", - "num-traits", - "phf", - "serde", - "smallvec", - "smartstring", - "stacker", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "tracing", - "typed-arena", -] - -[[package]] -name = "swc_ecma_visit" -version = "0.104.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1c6802e68e51f336e8bc9644e9ff9da75d7da9c1a6247d532f2e908aa33e81" -dependencies = [ - "new_debug_unreachable", - "num-bigint", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_visit", - "tracing", -] - -[[package]] -name = "swc_eq_ignore_macros" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "swc_macros_common" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "swc_visit" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ceb044142ba2719ef9eb3b6b454fce61ab849eb696c34d190f04651955c613d" -dependencies = [ - "either", - "new_debug_unreachable", -] - -[[package]] -name = "symbolic-common" -version = "12.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac08504d60cf5bdffeb8a6a028f1a4868a5da1098bb19eb46239440039163fb" -dependencies = [ - "debugid", - "memmap2", - "stable_deref_trait", - "uuid", -] - -[[package]] -name = "symbolic-demangle" -version = "12.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b212728d4f6c527c1d50d6169e715f6e02d849811843c13e366d8ca6d0cf5c4" -dependencies = [ - "cpp_demangle", - "rustc-demangle", - "symbolic-common", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] - -[[package]] -name = "sysinfo" -version = "0.27.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a902e9050fca0a5d6877550b769abd2bd1ce8c04634b941dbe2809735e1a1e33" -dependencies = [ - "cfg-if", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi", -] - -[[package]] -name = "tabwriter" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08e1173ee641651a3095fe95d86ae314cd1f959888097debce3e0f9ca532eef1" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "tar" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "tardar" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900c942f83b6a8b9998cc8f74ad3ffa24b7ff3c4279ea1c1c52d95dced9f3516" -dependencies = [ - "miette", - "vec1", -] - -[[package]] -name = "tempfile" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" -dependencies = [ - "cfg-if", - "fastrand 2.1.0", - "once_cell", - "rustix 0.38.31", - "windows-sys 0.59.0", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "terminal_size" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" -dependencies = [ - "rustix 0.37.23", - "windows-sys 0.48.0", -] - -[[package]] -name = "termios" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a" -dependencies = [ - "libc", -] - -[[package]] -name = "termtree" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" - -[[package]] -name = "test-case" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1d6e7bde536b0412f20765b76e921028059adfd1b90d8974d33fd3c91b25df" -dependencies = [ - "test-case-macros", -] - -[[package]] -name = "test-case-core" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dc21b5887f4032c4656502d085dc28f2afbb686f25f216472bb0526f4b1b88" -dependencies = [ - "cfg-if", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "test-case-macros" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3786898e0be151a96f730fd529b0e8a10f5990fa2a7ea14e37ca27613c05190" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", - "test-case-core", -] - -[[package]] -name = "text-block-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8b59b4da1c1717deaf1de80f0179a9d8b4ac91c986d5fd9f4a8ff177b84049" - -[[package]] -name = "textwrap" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" -dependencies = [ - "smawk", - "unicode-linebreak", - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-gradient" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8063c572fcc935676f1e01615f201f355a053e88525ec41c1b0c4884ce104847" -dependencies = [ - "libm", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.39.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio 1.0.1", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.6", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-retry" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" -dependencies = [ - "pin-project", - "rand", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-scoped" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4beb8ba13bc53ac53ce1d52b42f02e5d8060f0f42138862869beb769722b256" -dependencies = [ - "tokio", - "tokio-stream", -] - -[[package]] -name = "tokio-stream" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite", -] - -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-io", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.15", -] - -[[package]] -name = "toml_datetime" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.22.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" -dependencies = [ - "indexmap 2.2.6", - "serde", - "serde_spanned", - "toml_datetime", -] - -[[package]] -name = "tonic" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" -dependencies = [ - "async-stream", - "async-trait", - "axum 0.6.12", - "base64 0.21.4", - "bytes", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.5", - "hyper 0.14.28", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost 0.12.3", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic-build" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", - "rand", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" -dependencies = [ - "bitflags 2.5.0", - "bytes", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "pin-project-lite", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-lsp" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" -dependencies = [ - "async-trait", - "auto_impl", - "bytes", - "dashmap 5.5.3", - "futures", - "httparse", - "lsp-types", - "memchr", - "serde", - "serde_json", - "tokio", - "tokio-util", - "tower", - "tower-lsp-macros", - "tracing", -] - -[[package]] -name = "tower-lsp-macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tower-uds" -version = "0.1.0" -dependencies = [ - "async-io", - "tokio", - "tokio-util", - "tower", - "uds_windows", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-appender" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" -dependencies = [ - "crossbeam-channel", - "time", - "tracing-subscriber", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "tracing-chrome" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496b3cd5447f7ff527bbbf19b071ad542a000adf297d4127078b4dfdb931f41a" -dependencies = [ - "serde_json", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "tracing-test" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a2c0ff408fe918a94c428a3f2ad04e4afd5c95bbc08fcf868eff750c15728a4" -dependencies = [ - "lazy_static", - "tracing-core", - "tracing-subscriber", - "tracing-test-macro", -] - -[[package]] -name = "tracing-test-macro" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bc1c4f8e2e73a977812ab339d503e6feeb92700f6d07a6de4d321522d5c08" -dependencies = [ - "lazy_static", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "triomphe" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" -dependencies = [ - "serde", - "stable_deref_trait", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "tui-term" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4612d4537b4c9f69192596f5b48516b2faf5442fafab885e999e6195cd19463f" -dependencies = [ - "ratatui", -] - -[[package]] -name = "tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand", - "sha1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "turbo" -version = "0.1.0" -dependencies = [ - "anyhow", - "assert_cmd", - "build-target", - "camino", - "insta", - "itertools 0.10.5", - "miette", - "pretty_assertions", - "serde_json", - "tempfile", - "turbopath", - "turborepo-lib", - "which", -] - -[[package]] -name = "turbo-trace" -version = "0.1.0" -dependencies = [ - "camino", - "clap", - "futures", - "globwalk", - "miette", - "oxc_resolver 2.1.1", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_visit", - "thiserror", - "tokio", - "tracing", - "tracing-subscriber", - "turbopath", -] - -[[package]] -name = "turbo-updater" -version = "0.1.0" -dependencies = [ - "atty", - "console", - "reqwest", - "semver 1.0.23", - "serde", - "thiserror", - "update-informer", -] - -[[package]] -name = "turbopath" -version = "0.1.0" -dependencies = [ - "anyhow", - "biome_deserialize", - "biome_deserialize_macros", - "biome_diagnostics", - "biome_json_parser", - "camino", - "dunce", - "fs-err", - "miette", - "path-clean", - "serde", - "serde_json", - "tempfile", - "test-case", - "thiserror", - "turborepo-unescape", - "wax", -] - -[[package]] -name = "turborepo-analytics" -version = "0.1.0" -dependencies = [ - "futures", - "thiserror", - "tokio", - "tracing", - "turborepo-api-client", - "turborepo-vercel-api", - "uuid", -] - -[[package]] -name = "turborepo-api-client" -version = "0.1.0" -dependencies = [ - "anyhow", - "bytes", - "chrono", - "http 1.1.0", - "httpmock", - "insta", - "lazy_static", - "port_scanner", - "regex", - "reqwest", - "rustc_version_runtime", - "serde", - "serde_json", - "test-case", - "thiserror", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", - "turbopath", - "turborepo-ci", - "turborepo-vercel-api", - "turborepo-vercel-api-mock", - "url", -] - -[[package]] -name = "turborepo-auth" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "axum 0.7.5", - "axum-server 0.7.1", - "chrono", - "hostname", - "lazy_static", - "port_scanner", - "reqwest", - "serde", - "serde_json", - "tempfile", - "thiserror", - "tokio", - "tracing", - "turbopath", - "turborepo-api-client", - "turborepo-dirs", - "turborepo-ui", - "turborepo-vercel-api", - "turborepo-vercel-api-mock", - "url", - "webbrowser", -] - -[[package]] -name = "turborepo-cache" -version = "0.1.0" -dependencies = [ - "anyhow", - "base64 0.21.4", - "bytes", - "camino", - "futures", - "hmac", - "insta", - "libc", - "miette", - "os_str_bytes", - "path-clean", - "petgraph", - "pin-project", - "port_scanner", - "reqwest", - "serde", - "serde_json", - "sha2", - "tar", - "tempfile", - "test-case", - "thiserror", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", - "turbopath", - "turborepo-analytics", - "turborepo-api-client", - "turborepo-vercel-api", - "turborepo-vercel-api-mock", - "zstd", -] - -[[package]] -name = "turborepo-ci" -version = "0.1.0" -dependencies = [ - "chrono", - "test-case", - "tracing", -] - -[[package]] -name = "turborepo-dirs" -version = "0.1.0" -dependencies = [ - "dirs-next", - "thiserror", - "turbopath", -] - -[[package]] -name = "turborepo-env" -version = "0.1.0" -dependencies = [ - "hex", - "regex", - "serde", - "sha2", - "test-case", - "thiserror", - "turborepo-ci", - "turborepo-ui", -] - -[[package]] -name = "turborepo-errors" -version = "0.1.0" -dependencies = [ - "biome_deserialize", - "biome_diagnostics", - "miette", - "serde", - "serde_json", - "test-case", - "thiserror", -] - -[[package]] -name = "turborepo-filewatch" -version = "0.1.0" -dependencies = [ - "bitflags 1.3.2", - "fsevent-sys", - "futures", - "git2", - "itertools 0.10.5", - "libc", - "nibble_vec", - "notify", - "num_cpus", - "radix_trie", - "tempfile", - "thiserror", - "tokio", - "tokio-scoped", - "tracing", - "tracing-test", - "turbopath", - "turborepo-repository", - "turborepo-scm", - "walkdir", - "wax", -] - -[[package]] -name = "turborepo-fs" -version = "0.1.0" -dependencies = [ - "fs-err", - "ignore", - "tempfile", - "test-case", - "thiserror", - "turbopath", -] - -[[package]] -name = "turborepo-graph-utils" -version = "0.1.0" -dependencies = [ - "fixedbitset", - "futures", - "insta", - "itertools 0.10.5", - "log", - "petgraph", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "turborepo-lib" -version = "0.1.0" -dependencies = [ - "anyhow", - "assert_cmd", - "async-graphql", - "async-graphql-axum", - "async-io", - "async-stream", - "atty", - "axum 0.7.5", - "biome_deserialize", - "biome_deserialize_macros", - "biome_diagnostics", - "biome_json_parser", - "biome_json_syntax", - "camino", - "capnp 0.17.2", - "capnpc", - "chrono", - "clap", - "clap_complete", - "command-group", - "console", - "const_format", - "convert_case 0.6.0", - "crossterm 0.26.1", - "ctrlc", - "derive_setters", - "dialoguer", - "dirs-next", - "dunce", - "either", - "futures", - "futures-core", - "git2", - "globwalk", - "globwatch", - "go-parse-duration", - "hex", - "human-panic", - "human_format", - "humantime", - "ignore", - "insta", - "itertools 0.10.5", - "jsonc-parser 0.21.0", - "lazy_static", - "libc", - "merge", - "miette", - "nix 0.26.2", - "notify", - "num_cpus", - "owo-colors", - "oxc_resolver 2.1.1", - "path-clean", - "petgraph", - "pidlock", - "port_scanner", - "portable-pty", - "pprof", - "pretty_assertions", - "prost 0.12.3", - "radix_trie", - "rand", - "rayon", - "regex", - "reqwest", - "semver 1.0.23", - "serde", - "serde_json", - "serde_yaml", - "sha2", - "shared_child", - "struct_iterable", - "svix-ksuid", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_visit", - "sysinfo", - "tabwriter", - "tempfile", - "test-case", - "thiserror", - "time", - "tiny-gradient", - "tokio", - "tokio-stream", - "tokio-util", - "tonic", - "tonic-build", - "tower", - "tower-http", - "tracing", - "tracing-appender", - "tracing-chrome", - "tracing-subscriber", - "tracing-test", - "turbo-trace", - "turbo-updater", - "turbopath", - "turborepo-analytics", - "turborepo-api-client", - "turborepo-auth", - "turborepo-cache", - "turborepo-ci", - "turborepo-dirs", - "turborepo-env", - "turborepo-errors", - "turborepo-filewatch", - "turborepo-fs", - "turborepo-graph-utils", - "turborepo-lockfiles", - "turborepo-microfrontends", - "turborepo-repository", - "turborepo-scm", - "turborepo-telemetry", - "turborepo-ui", - "turborepo-unescape", - "turborepo-vercel-api", - "turborepo-vercel-api-mock", - "twox-hash", - "uds_windows", - "wax", - "webbrowser", - "which", - "windows-sys 0.59.0", -] - -[[package]] -name = "turborepo-lockfiles" -version = "0.1.0" -dependencies = [ - "itertools 0.10.5", - "nom", - "pest", - "pest_derive", - "pretty_assertions", - "rayon", - "regex", - "semver 1.0.23", - "serde", - "serde_json", - "serde_yaml", - "test-case", - "thiserror", - "tracing", - "turbopath", -] - -[[package]] -name = "turborepo-lsp" -version = "0.1.0" -dependencies = [ - "crop", - "itertools 0.10.5", - "jsonc-parser 0.23.0", - "pidlock", - "serde_json", - "tokio", - "tokio-retry", - "tower-lsp", - "turbopath", - "turborepo-lib", - "turborepo-repository", - "wax", -] - -[[package]] -name = "turborepo-microfrontends" -version = "0.1.0" -dependencies = [ - "biome_deserialize", - "biome_deserialize_macros", - "biome_diagnostics", - "biome_json_parser", - "biome_json_syntax", - "insta", - "pretty_assertions", - "serde", - "serde_json", - "tempfile", - "test-case", - "thiserror", - "turbopath", - "turborepo-errors", -] - -[[package]] -name = "turborepo-napi" -version = "0.1.0" -dependencies = [ - "napi", - "napi-build", - "napi-derive", - "pretty_assertions", - "thiserror", - "tokio", - "turbopath", - "turborepo-repository", -] - -[[package]] -name = "turborepo-repository" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-once-cell", - "biome_deserialize", - "biome_deserialize_macros", - "biome_diagnostics", - "biome_json_parser", - "biome_json_syntax", - "globwalk", - "itertools 0.10.5", - "lazy-regex", - "miette", - "node-semver", - "petgraph", - "pretty_assertions", - "regex", - "rust-ini", - "serde", - "serde_json", - "serde_yaml", - "tempfile", - "test-case", - "thiserror", - "tokio", - "tokio-stream", - "tracing", - "turbopath", - "turborepo-errors", - "turborepo-graph-utils", - "turborepo-lockfiles", - "turborepo-unescape", - "wax", - "which", -] - -[[package]] -name = "turborepo-scm" -version = "0.1.0" -dependencies = [ - "bstr 1.8.0", - "git2", - "globwalk", - "hex", - "ignore", - "nom", - "serde", - "serde_json", - "sha1", - "tempfile", - "test-case", - "thiserror", - "tracing", - "turbopath", - "turborepo-ci", - "turborepo-telemetry", - "wax", - "which", -] - -[[package]] -name = "turborepo-telemetry" -version = "0.1.0" -dependencies = [ - "chrono", - "config", - "futures", - "hex", - "once_cell", - "reqwest", - "serde", - "serde_json", - "sha2", - "tempfile", - "test-case", - "thiserror", - "tokio", - "tracing", - "turbopath", - "turborepo-api-client", - "turborepo-ci", - "turborepo-dirs", - "turborepo-ui", - "turborepo-vercel-api", - "turborepo-vercel-api-mock", - "url", - "uuid", -] - -[[package]] -name = "turborepo-ui" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-graphql", - "async-graphql-axum", - "async-stream", - "atty", - "axum 0.7.5", - "axum-server 0.7.1", - "base64 0.22.1", - "chrono", - "clipboard-win", - "console", - "crossterm 0.27.0", - "dialoguer", - "futures", - "indicatif", - "indoc", - "itertools 0.10.5", - "lazy_static", - "nix 0.26.2", - "ratatui", - "serde", - "serde_json", - "tempfile", - "test-case", - "thiserror", - "tokio", - "tracing", - "tui-term", - "turbopath", - "turborepo-ci", - "turborepo-vt100", - "which", - "windows-sys 0.59.0", -] - -[[package]] -name = "turborepo-unescape" -version = "0.1.0" -dependencies = [ - "biome_deserialize", - "biome_diagnostics", - "serde", - "serde_json", -] - -[[package]] -name = "turborepo-vercel-api" -version = "0.1.0" -dependencies = [ - "chrono", - "insta", - "serde", - "serde_json", - "test-case", - "url", -] - -[[package]] -name = "turborepo-vercel-api-mock" -version = "0.1.0" -dependencies = [ - "anyhow", - "axum 0.7.5", - "axum-server 0.4.7", - "futures-util", - "port_scanner", - "tempfile", - "tokio", - "turborepo-vercel-api", -] - -[[package]] -name = "turborepo-vt100" -version = "0.15.2" -dependencies = [ - "itoa", - "log", - "quickcheck", - "rand", - "ratatui", - "serde", - "serde_json", - "terminal_size 0.2.6", - "tui-term", - "unicode-width", - "vte", -] - -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "rand", - "static_assertions", -] - -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "uds_windows" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" -dependencies = [ - "tempfile", - "winapi", -] - -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" -dependencies = [ - "unic-ucd-segment", -] - -[[package]] -name = "unic-ucd-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-bom" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" - -[[package]] -name = "unicode-id-start" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3882f69607a2ac8cc4de3ee7993d8f68bb06f2974271195065b3bd07f2edea" - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-linebreak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "update-informer" -version = "1.1.0" -source = "git+https://github.com/nicholaslyang/update-informer.git#7a78e90e62479e022bae77ada824c9df53036f96" -dependencies = [ - "directories", - "reqwest", - "semver 1.0.23", - "serde", - "serde_json", - "ureq", -] - -[[package]] -name = "ureq" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" -dependencies = [ - "base64 0.22.1", - "flate2", - "log", - "native-tls", - "once_cell", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "url", - "webpki-roots", -] - -[[package]] -name = "url" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "uuid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" -dependencies = [ - "getrandom", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "value-bag" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d330786735ea358f3bc09eea4caa098569c1c93f342d9aca0514915022fe7e" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vec1" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bda7c41ca331fe9a1c278a9e7ee055f4be7f5eb1c2b72f079b4ff8b5fce9d5c" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "vte" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" -dependencies = [ - "arrayvec", - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.58", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" - -[[package]] -name = "wasm-streams" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wax" -version = "0.6.0" -dependencies = [ - "build-fs-tree", - "const_format", - "dunce", - "itertools 0.11.0", - "miette", - "nom", - "path-slash", - "pori", - "regex", - "tardar", - "tempfile", - "thiserror", - "walkdir", -] - -[[package]] -name = "web-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579cc485bd5ce5bfa0d738e4921dd0b956eca9800be1fd2e5257ebe95bc4617e" -dependencies = [ - "core-foundation", - "dirs", - "jni", - "log", - "ndk-context", - "objc", - "raw-window-handle", - "url", - "web-sys", -] - -[[package]] -name = "webpki-roots" -version = "0.26.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "which" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" -dependencies = [ - "either", - "libc", - "once_cell", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.1", -] - -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.1", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[package]] -name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys 0.4.13", - "rustix 0.38.31", -] - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" - -[[package]] -name = "zstd" -version = "0.12.3+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "6.0.5+zstd.1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56d9e60b4b1758206c238a10165fbcae3ca37b01744e394c463463f6529d23b" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/Cargo.toml b/Cargo.toml index 713d65441300f..786f85532d7ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,77 +1,37 @@ -[workspace] -resolver = "2" - -members = [ - "crates/tower-uds", - "crates/turbo-trace", - "crates/turborepo*", - "packages/turbo-repository/rust", -] +[profile] -[workspace.metadata.groups] -# Only the libraries, does not include the turborepo binary. -# That way we don't have to build the Go code -turborepo-libraries = ["path:crates/turborepo-*"] -turborepo = ["path:crates/turborepo*"] +[profile.dev] -[workspace.lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(debug_assert)'] } +[profile.dev.build-override] +opt-level = 3 -[workspace.lints.clippy] -too_many_arguments = "allow" +[profile.dev.package] -# Set the options for dependencies (not crates in the workspace), this mostly impacts cold builds [profile.dev.package."*"] opt-level = 1 -# Set the settings for build scripts and proc-macros. -[profile.dev.build-override] -opt-level = 3 - [profile.release] lto = "off" -[profile.release-turborepo-lsp] +[profile.release-turborepo] inherits = "release" strip = true -opt-level = "z" -[profile.release-turborepo] +[profile.release-turborepo-lsp] inherits = "release" +opt-level = "z" strip = true -# Declare dependencies used across workspace packages requires single version bump. -# ref: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#inheriting-a-dependency-from-a-workspace -[workspace.dependencies] -async-recursion = "1.0.2" -miette = { version = "5.10.0", features = ["fancy"] } -markdown = "1.0.0-alpha.18" - -turbo-trace = { path = "crates/turbo-trace" } -turbo-updater = { path = "crates/turborepo-updater" } -turbopath = { path = "crates/turborepo-paths" } -turborepo = { path = "crates/turborepo" } -turborepo-analytics = { path = "crates/turborepo-analytics" } -turborepo-api-client = { path = "crates/turborepo-api-client" } -turborepo-cache = { path = "crates/turborepo-cache" } -turborepo-ci = { path = "crates/turborepo-ci" } -turborepo-env = { path = "crates/turborepo-env" } -turborepo-errors = { path = "crates/turborepo-errors" } -turborepo-fs = { path = "crates/turborepo-fs" } -turborepo-lib = { path = "crates/turborepo-lib", default-features = false } -turborepo-lockfiles = { path = "crates/turborepo-lockfiles" } -turborepo-microfrontends = { path = "crates/turborepo-microfrontends" } -turborepo-repository = { path = "crates/turborepo-repository" } -turborepo-ui = { path = "crates/turborepo-ui" } -turborepo-unescape = { path = "crates/turborepo-unescape" } -turborepo-scm = { path = "crates/turborepo-scm" } -wax = { path = "crates/turborepo-wax" } -turborepo-vercel-api = { path = "crates/turborepo-vercel-api" } -turborepo-vercel-api-mock = { path = "crates/turborepo-vercel-api-mock" } -turborepo-vt100 = { path = "crates/turborepo-vt100" } - -reqwest = { version = "0.12.9", default-features = false } +[workspace] +members = [ + "crates/tower-uds", + "crates/turbo-trace", + "crates/turborepo*", + "packages/turbo-repository/rust", +] +resolver = "2" +[workspace.dependencies] anyhow = "1.0.69" assert_cmd = "2.0.8" async-compression = { version = "0.3.13", default-features = false, features = [ @@ -80,6 +40,7 @@ async-compression = { version = "0.3.13", default-features = false, features = [ ] } async-graphql = "7.0.7" async-graphql-axum = "7.0.7" +async-recursion = "1.0.2" async-trait = "0.1.64" atty = "0.2.14" axum = "0.7.5" @@ -115,7 +76,9 @@ indoc = "2.0.0" insta = { version = "1.34.0", features = ["json"] } itertools = "0.10.5" lazy_static = "1.4.0" +markdown = "1.0.0-alpha.18" merge = "0.1.0" +miette = { version = "5.10.0", features = ["fancy"] } mime = "0.3.16" notify = "6.1.1" num_cpus = "1.15.0" @@ -136,6 +99,7 @@ radix_trie = "0.2.1" rand = "0.8.5" ratatui = "0.26.1" regex = "1.7.0" +reqwest = { version = "0.12.9", default-features = false } rustc-hash = "1.1.0" semver = "1.0.16" serde = { version = "1.0.152", features = ["derive"] } @@ -165,8 +129,44 @@ tracing = "0.1.37" tracing-appender = "0.2.2" tracing-subscriber = "0.3.16" tui-term = { version = "=0.1.9", default-features = false } +turbo-trace = { path = "crates/turbo-trace" } +turbo-updater = { path = "crates/turborepo-updater" } +turbopath = { path = "crates/turborepo-paths" } +turborepo = { path = "crates/turborepo" } +turborepo-analytics = { path = "crates/turborepo-analytics" } +turborepo-api-client = { path = "crates/turborepo-api-client" } +turborepo-cache = { path = "crates/turborepo-cache" } +turborepo-ci = { path = "crates/turborepo-ci" } +turborepo-env = { path = "crates/turborepo-env" } +turborepo-errors = { path = "crates/turborepo-errors" } +turborepo-fs = { path = "crates/turborepo-fs" } +turborepo-lib = { path = "crates/turborepo-lib", default-features = false } +turborepo-lockfiles = { path = "crates/turborepo-lockfiles" } +turborepo-microfrontends = { path = "crates/turborepo-microfrontends" } +turborepo-repository = { path = "crates/turborepo-repository" } +turborepo-scm = { path = "crates/turborepo-scm" } +turborepo-ui = { path = "crates/turborepo-ui" } +turborepo-unescape = { path = "crates/turborepo-unescape" } +turborepo-vercel-api = { path = "crates/turborepo-vercel-api" } +turborepo-vercel-api-mock = { path = "crates/turborepo-vercel-api-mock" } +turborepo-vt100 = { path = "crates/turborepo-vt100" } +unicode-segmentation = "1.10.1" url = "2.2.2" urlencoding = "2.1.2" +wax = { path = "crates/turborepo-wax" } webbrowser = "0.8.7" which = "4.4.0" -unicode-segmentation = "1.10.1" + +[workspace.lints] + +[workspace.lints.clippy] +too_many_arguments = "allow" + +[workspace.lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(debug_assert)'] } + +[workspace.metadata] + +[workspace.metadata.groups] +turborepo = ["path:crates/turborepo*"] +turborepo-libraries = ["path:crates/turborepo-*"] diff --git a/NOTICES.md b/NOTICES.md new file mode 100644 index 0000000000000..cbbf7ccbb80fe --- /dev/null +++ b/NOTICES.md @@ -0,0 +1,36 @@ +THIRD-PARTY SOFTWARE NOTICES + +This project incorporates components from the projects listed below. The original copyright notices and the licenses under which those components are redistributed are set forth below. + +--- + +- https://cs.opensource.google/go/go/+/refs/tags/go1.18.2:src/encoding/csv/reader.go +- https://cs.opensource.google/go/go/+/refs/tags/go1.18.2:src/encoding/csv/reader_test.go + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +- Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. +- Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md deleted file mode 100644 index 3979d4ad13641..0000000000000 --- a/README.md +++ /dev/null @@ -1,54 +0,0 @@ -

- - - - - -

Turborepo

- -

- -

- - - - -

- -Turborepo is a high-performance build system for JavaScript and TypeScript codebases, written in Rust. - -## Getting Started - -Visit https://turbo.build/repo to get started with Turborepo. - -## Contributing - -See [CONTRIBUTING.md](./CONTRIBUTING.md) for more information. - -## Community - -The Turborepo community can be found on [GitHub Discussions](https://github.com/vercel/turborepo/discussions), where you can ask questions, voice ideas, and share your projects. - -To chat with other community members, you can join [Vercel Community's `#turborepo` tag](https://vercel.community/tag/turborepo). - -Our [Code of Conduct](https://github.com/vercel/turborepo/blob/main/CODE_OF_CONDUCT.md) applies to all Turborepo community channels. - -## Who is using Turborepo? - -Turborepo is used by the world's leading companies. Check out the [Turborepo Showcase](https://turbo.build/showcase) to learn more. - -## Updates - -Follow [@turborepo](https://x.com/turborepo) on X for project updates. - -## Authors - -**Turborepo** - -- Jared Palmer ([@jaredpalmer](https://x.com/jaredpalmer)) - -## Security - -If you believe you have found a security vulnerability in Turborepo, we encourage you to responsibly disclose this and not open a public issue. We will investigate all legitimate reports. Email `security@vercel.com` to disclose any security vulnerabilities. - -https://vercel.com/security diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 294bff136eef4..0000000000000 --- a/SECURITY.md +++ /dev/null @@ -1 +0,0 @@ -Visit https://vercel.com/security to view the disclosure policy. diff --git a/buildcontainer/README.md b/buildcontainer/README.md deleted file mode 100644 index 1c68d591e1937..0000000000000 --- a/buildcontainer/README.md +++ /dev/null @@ -1,104 +0,0 @@ -### Provenance - -This directory has been forked from https://github.com/goreleaser/goreleaser-cross, and modified to fit Turborepo's needs. - -The License has been preserved from the source, and OSX SDKs have been removed. - -Original README follows: - -# goreleaser-cross - -Docker container to turn CGO cross-compilation pain into a pleasure. It tested on [variety of platforms](#supported-toolchains/platforms). -[Custom sysroots](#Sysroot) also can be used. - -**Tip!** -Should you wish to see working [examples](#examples) instead of reading - -## Credits - -This project is rather cookbook combing various projects into one. Special to [osxcross](https://github.com/tpoechtrager/osxcross) for amazing cross-compile environment for OSX. - -## Docker - -Docker images are available on both [GitHub](https://ghcr.io/goreleaser/goreleaser-cross) and [Docker hub](https://hub.docker.com/r/goreleaser/goreleaser-cross). - -Images from version v1.17.4 are multi-arch. Supported host are listed in the table below - -| Host | Supported | -| ------------------- | :-------: | -| amd64 | ✅ | -| arm64 (aka aarch64) | ✅ | - -To run build with CGO each entry requires some environment variables - -| Env variable | value | required | Notes | -| ---------------------- | ---------------------------------------------- | :----------------------------: | -------------------------------------------------------------------------------------------------- | -| CGO_ENABLED | 1 | Yes | instead of specifying it in each build it can be set globally during docker run `-e CGO_ENABLED=1` | -| CC | [see targets](#supported-toolchains/platforms) | Optional | -| CXX | [see targets](#supported-toolchains/platforms) | Optional | -| PKG_CONFIG_SYSROOT_DIR | | Required if sysroot is present | -| PKG_CONFIG_PATH | | Optional | List of directories containing pkg-config files | - -- **PKG_CONFIG_SYSROOT_DIR** modifies `-I` and `-L` to use the directories located in target's sysroot. -- The value of `PKG_CONFIG_SYSROOT_DIR` is prefixed to `-I` and `-L`. For instance `-I/usr/include/libfoo` becomes `-I/var/target/usr/include/libfoo` - with a `PKG_CONFIG_SYSROOT_DIR` set to `/var/target` (same rule apply to `-L`) -- **PKG_CONFIG_PATH** - A colon-separated list of directories to search for `.pc` files. - -## Supported toolchains/platforms - -| Platform | Arch | CC | CXX | Verified | -| ----------- | --------------- | -------------------------------------------------- | -------------------------------------------------- | :-------------------: | -| Darwin | amd64 | o64-clang | o64-clang++ | ✅ | -| Darwin (M1) | arm64 | oa64-clang | oa64-clang++ | ✅ | -| Linux | amd64 | gcc | g++ | ✅ | -| Linux | arm64 | aarch64-linux-gnu-gcc | aarch64-linux-gnu-g++ | ✅ | -| Linux | armhf (GOARM=5) | arm-linux-gnueabihf-gcc | arm-linux-gnueabihf-g++ | Verification required | -| Linux | armhf (GOARM=6) | arm-linux-gnueabihf-gcc | arm-linux-gnueabihf-g++ | Verification required | -| Linux | armhf (GOARM=7) | arm-linux-gnueabihf-gcc | arm-linux-gnueabihf-g++ | ✅ | -| Windows | amd64 | x86_64-w64-mingw32-gcc | x86_64-w64-mingw32-g++ | ✅ | -| Windows | arm64 | /llvm-mingw/llvm-mingw/bin/aarch64-w64-mingw32-gcc | /llvm-mingw/llvm-mingw/bin/aarch64-w64-mingw32-g++ | ✅ | - -## Docker - -### Environment variables - -- GPG_KEY - defaults to /secrets/key.gpg. ignored if file not found -- DOCKER_USERNAME -- DOCKER_PASSWORD -- DOCKER_HOST - defaults to `hub.docker.io`. ignored if `DOCKER_USERNAME` and `DOCKER_PASSWORD` are empty or `DOCKER_CREDS_FILE` is present -- DOCKER_CREDS_FILE - path to file with docker login credentials in colon separated format `user:password:`. useful when push to multiple docker registries required - ``` - user1:password1:hub.docker.io - user2:password2:registry.gitlab.com - ``` -- DOCKER_FAIL_ON_LOGIN_ERROR - fail on docker login error -- GITHUB_TOKEN - github auth token to deploy release - -## Sysroot howto - -Most reasonable way to make a sysroot seem to be rsync and [the example](https://github.com/goreleaser/goreleaser-cross-example) is using it. You may want to -use [the script](https://github.com/goreleaser/goreleaser-cross/blob/master/scripts/sysroot-rsync.sh) to create sysroot for your desired setup. Lets consider creating sysroot for Raspberry Pi 4 -running Debian Buster. - -- install all required dev packages. for this example we will install libftdi1-dev, libusb-1.0-0-dev and opencv4 - ```bash - ./sysroot-rsync.sh pi@ - ``` - -### sshfs - -Though `sshfs` is a good way to test sysroot before running rsync it introduces cons. Some packages are creating absolute links and thus pointing to wrong files when mounted ( -or appear as broken). For example RPI4 running Debian Buster the library `/usr/lib/x86_x64-gnu-linux/libpthread.so` is symlink to `/lib/x86_x64-gnu-linux/libpthread.so` instead -of `../../../lib/x86_x64-gnu-linux/libpthread.so`. - -## Contributing - -Any contribution helping to make this project is welcome - -## Examples - -- [Example described in this tutorial](https://github.com/goreleaser/goreleaser-cross-example) - -## Projects using - -- [Akash](https://github.com/ovrclk/akash) diff --git a/cli/README.md b/cli/README.md deleted file mode 100644 index 0cc7a7b113fe9..0000000000000 --- a/cli/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `turbo` CLI - -Visit https://turbo.build/repo to view the full documentation. diff --git a/cli/package.json b/cli/package.json index deff9108f9185..11cc87e7e334a 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,10 +1,10 @@ { - "name": "cli", - "private": true, - "version": "0.0.0", - "scripts": { - "clean": "cargo clean --package turbo", - "build": "cargo build --package turbo", - "build:release": "cargo build --package turbo --profile release-turborepo" - } + "name": "cli", + "scripts": { + "build": "cargo build --package turbo", + "build:release": "cargo build --package turbo --profile release-turborepo", + "clean": "cargo clean --package turbo" + }, + "dependencies": {}, + "devDependencies": {} } diff --git a/cli/scripts/npm-native-packages/template/README.md b/cli/scripts/npm-native-packages/template/README.md deleted file mode 100644 index 27416bc7b03fd..0000000000000 --- a/cli/scripts/npm-native-packages/template/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `turbo` - -This is a platform-specific binary for Turborepo, a monorepo build system. See https://github.com/vercel/turborepo for details. diff --git a/cli/scripts/npm-native-packages/template/template.package.json b/cli/scripts/npm-native-packages/template/template.package.json index c6f9700b183e7..fec8931842246 100644 --- a/cli/scripts/npm-native-packages/template/template.package.json +++ b/cli/scripts/npm-native-packages/template/template.package.json @@ -4,7 +4,7 @@ "description": "The {{Os}}-{{Arch}} binary for turbo, a monorepo build system.", "repository": "https://github.com/vercel/turborepo", "bugs": "https://github.com/vercel/turborepo/issues", - "homepage": "https://turbo.build/repo", + "homepage": "HTTPS://turbo.build/repo", "license": "MIT", "os": ["{{Os}}"], "cpu": ["{{Arch}}"], diff --git a/crates/node-file-trace/Source/lib.rs b/crates/node-file-trace/Source/lib.rs new file mode 100644 index 0000000000000..0b715717437d3 --- /dev/null +++ b/crates/node-file-trace/Source/lib.rs @@ -0,0 +1,639 @@ +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +mod nft_json; + +use std::{ + collections::{BTreeSet, HashMap}, + env::current_dir, + future::Future, + path::{Path, PathBuf}, + pin::Pin, + sync::Arc, + time::{Duration, Instant}, +}; + +use anyhow::{Context, Result, anyhow}; +#[cfg(feature = "cli")] +use clap::Parser; +#[cfg(feature = "node-api")] +use serde::Deserialize; +#[cfg(feature = "node-api")] +use serde::Serialize; +use tokio::sync::mpsc::channel; +use turbo_tasks::{ + RcStr, + TaskId, + TransientInstance, + TransientValue, + TurboTasks, + UpdateInfo, + Value, + Vc, + backend::Backend, + util::FormatDuration, +}; +use turbo_tasks_fs::{ + DirectoryEntry, + DiskFileSystem, + FileSystem, + FileSystemPath, + ReadGlobResult, + glob::Glob, +}; +use turbo_tasks_memory::MemoryBackend; +use turbopack::{ + ModuleAssetContext, + emit_asset, + emit_with_completion, + module_options::ModuleOptionsContext, + rebase::RebasedAsset, +}; +use turbopack_cli_utils::issue::{ConsoleUi, IssueSeverityCliOption, LogOptions}; +use turbopack_core::{ + compile_time_info::CompileTimeInfo, + context::AssetContext, + environment::{Environment, ExecutionEnvironment, NodeJsEnvironment}, + file_source::FileSource, + issue::{IssueDescriptionExt, IssueReporter, IssueSeverity}, + module::{Module, Modules}, + output::OutputAsset, + reference::all_modules_and_affecting_sources, + resolve::options::{ImportMapping, ResolvedMap}, +}; +use turbopack_resolve::resolve_options_context::ResolveOptionsContext; + +use crate::nft_json::NftJsonAsset; + +#[cfg(feature = "persistent_cache")] +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[cfg_attr( + feature = "node-api", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] +#[derive(Debug, Clone)] +struct CacheArgs { + #[clap(long)] + cache:Option, + + #[clap(long)] + cache_fully:bool, +} + +#[cfg(not(feature = "persistent_cache"))] +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[cfg_attr( + feature = "node-api", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] +#[derive(Debug, Clone, Default)] +pub struct CacheArgs {} + +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[cfg_attr( + feature = "node-api", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] +#[derive(Debug, Clone)] +pub struct CommonArgs { + input:Vec, + + #[cfg_attr(feature = "cli", clap(short, long))] + #[cfg_attr(feature = "node-api", serde(default))] + context_directory:Option, + + #[cfg_attr(feature = "cli", clap(long))] + #[cfg_attr(feature = "node-api", serde(default))] + process_cwd:Option, + + #[cfg_attr(feature = "cli", clap(flatten))] + #[cfg_attr(feature = "node-api", serde(default))] + cache:CacheArgs, + + #[cfg_attr(feature = "cli", clap(short, long))] + #[cfg_attr(feature = "node-api", serde(default))] + watch:bool, + + #[cfg_attr(feature = "cli", clap(short, long))] + #[cfg_attr(feature = "node-api", serde(default))] + /// Filter by issue severity. + log_level:Option, + + #[cfg_attr(feature = "cli", clap(long))] + #[cfg_attr(feature = "node-api", serde(default))] + /// Show all log messages without limit. + show_all:bool, + + #[cfg_attr(feature = "cli", clap(long))] + #[cfg_attr(feature = "node-api", serde(default))] + /// Expand the log details. + log_detail:bool, + + /// Whether to skip the glob logic + /// assume the provided input is not glob even if it contains `*` and `[]` + #[cfg_attr(feature = "cli", clap(short, long))] + #[cfg_attr(feature = "node-api", serde(default))] + exact:bool, + + /// Enable experimental garbage collection with the provided memory limit in + /// MB. + #[cfg_attr(feature = "cli", clap(long))] + #[cfg_attr(feature = "serializable", serde(default))] + pub memory_limit:Option, +} + +#[cfg_attr(feature = "cli", derive(Parser))] +#[cfg_attr(feature = "cli", clap(author, version, about, long_about = None))] +#[cfg_attr( + feature = "node-api", + derive(Serialize, Deserialize), + serde(tag = "action", rename_all = "camelCase") +)] +#[derive(Debug)] +pub enum Args { + // Print all files that the input files reference + Print { + #[cfg_attr(feature = "cli", clap(flatten))] + #[cfg_attr(feature = "node-api", serde(flatten))] + common:CommonArgs, + }, + + // Adds a *.nft.json file next to each input file which lists the referenced files + Annotate { + #[cfg_attr(feature = "cli", clap(flatten))] + #[cfg_attr(feature = "node-api", serde(flatten))] + common:CommonArgs, + }, + + // Copy input files and all referenced files to the output directory + Build { + #[cfg_attr(feature = "cli", clap(flatten))] + #[cfg_attr(feature = "node-api", serde(flatten))] + common:CommonArgs, + + #[cfg_attr(feature = "cli", clap(short, long, default_value_t = String::from("dist")))] + #[cfg_attr(feature = "node-api", serde(default = "default_output_directory"))] + output_directory:String, + }, + + // Print total size of input and referenced files + Size { + #[cfg_attr(feature = "cli", clap(flatten))] + #[cfg_attr(feature = "node-api", serde(flatten))] + common:CommonArgs, + }, +} + +#[cfg(feature = "node-api")] +fn default_output_directory() -> String { "dist".to_string() } + +impl Args { + fn common(&self) -> &CommonArgs { + match self { + Args::Print { common, .. } + | Args::Annotate { common, .. } + | Args::Build { common, .. } + | Args::Size { common, .. } => common, + } + } +} + +async fn create_fs(name:&str, root:&str, watch:bool) -> Result>> { + let fs = DiskFileSystem::new(name.into(), root.into(), vec![]); + if watch { + fs.await?.start_watching()?; + } else { + fs.await?.invalidate(); + } + Ok(Vc::upcast(fs)) +} + +async fn add_glob_results( + asset_context:Vc>, + result:Vc, + list:&mut Vec>>, +) -> Result<()> { + let result = result.await?; + for entry in result.results.values() { + if let DirectoryEntry::File(path) = entry { + let source = Vc::upcast(FileSource::new(*path)); + let module = asset_context + .process( + source, + Value::new(turbopack_core::reference_type::ReferenceType::Undefined), + ) + .module(); + list.push(module); + } + } + for result in result.inner.values() { + fn recurse<'a>( + asset_context:Vc>, + result:Vc, + list:&'a mut Vec>>, + ) -> Pin> + Send + 'a>> { + Box::pin(add_glob_results(asset_context, result, list)) + } + // Boxing for async recursion + recurse(asset_context, *result, list).await?; + } + Ok(()) +} + +#[turbo_tasks::function] +async fn input_to_modules( + fs:Vc>, + input:Vec, + exact:bool, + process_cwd:Option, + context_directory:RcStr, + module_options:TransientInstance, + resolve_options:TransientInstance, +) -> Result> { + let root = fs.root(); + let process_cwd = process_cwd + .clone() + .map(|p| format!("/ROOT{}", p.trim_start_matches(&*context_directory)).into()); + + let asset_context:Vc> = + Vc::upcast(create_module_asset(root, process_cwd, module_options, resolve_options)); + + let mut list = Vec::new(); + for input in input { + if exact { + let source = Vc::upcast(FileSource::new(root.join(input))); + let module = asset_context + .process( + source, + Value::new(turbopack_core::reference_type::ReferenceType::Undefined), + ) + .module(); + list.push(module); + } else { + let glob = Glob::new(input); + add_glob_results(asset_context, root.read_glob(glob, false), &mut list).await?; + }; + } + Ok(Vc::cell(list)) +} + +fn process_context(dir:&Path, context_directory:Option<&String>) -> Result { + let mut context_directory = PathBuf::from(context_directory.map_or(".", |s| s)); + if !context_directory.is_absolute() { + context_directory = dir.join(context_directory); + } + // context = context.canonicalize().unwrap(); + Ok(context_directory + .to_str() + .ok_or_else(|| anyhow!("context directory contains invalid characters")) + .unwrap() + .to_string()) +} + +fn make_relative_path(dir:&Path, context_directory:&str, input:&str) -> Result { + let mut input = PathBuf::from(input); + if !input.is_absolute() { + input = dir.join(input); + } + // input = input.canonicalize()?; + let input = input.strip_prefix(context_directory).with_context(|| { + anyhow!("{} is not part of the context directory {}", input.display(), context_directory) + })?; + Ok(input + .to_str() + .ok_or_else(|| anyhow!("input contains invalid characters"))? + .replace('\\', "/") + .into()) +} + +fn process_input(dir:&Path, context_directory:&str, input:&[String]) -> Result> { + input + .iter() + .map(|input| make_relative_path(dir, context_directory, input)) + .collect() +} + +pub async fn start( + args:Arc, + turbo_tasks:Option<&Arc>>, + module_options:Option, + resolve_options:Option, +) -> Result> { + register(); + let &CommonArgs { + memory_limit, + #[cfg(feature = "persistent_cache")] + cache: CacheArgs { ref cache, ref cache_fully }, + .. + } = args.common(); + #[cfg(feature = "persistent_cache")] + if let Some(cache) = cache { + use tokio::time::timeout; + use turbo_tasks_memory::MemoryBackendWithPersistedGraph; + use turbo_tasks_rocksdb::RocksDbPersistedGraph; + + run( + &args, + || { + let start = Instant::now(); + let backend = MemoryBackendWithPersistedGraph::new( + RocksDbPersistedGraph::new(cache).unwrap(), + ); + let tt = TurboTasks::new(backend); + let elapsed = start.elapsed(); + println!("restored cache {}", FormatDuration(elapsed)); + tt + }, + |tt, _, duration| { + async move { + let mut start = Instant::now(); + if *cache_fully { + tt.wait_background_done().await; + tt.stop_and_wait().await; + let elapsed = start.elapsed(); + println!("flushed cache {}", FormatDuration(elapsed)); + } else { + let background_timeout = + std::cmp::max(duration / 5, Duration::from_millis(100)); + let timed_out = + timeout(background_timeout, tt.wait_background_done()).await.is_err(); + tt.stop_and_wait().await; + let elapsed = start.elapsed(); + if timed_out { + println!("flushed cache partially {}", FormatDuration(elapsed)); + } else { + println!("flushed cache completely {}", FormatDuration(elapsed)); + } + } + start = Instant::now(); + drop(tt); + let elapsed = start.elapsed(); + println!("writing cache {}", FormatDuration(elapsed)); + } + }, + ) + .await; + return; + } + + run( + args.clone(), + || { + turbo_tasks.cloned().unwrap_or_else(|| { + TurboTasks::new(MemoryBackend::new(memory_limit.unwrap_or(usize::MAX))) + }) + }, + |_, _, _| async move {}, + module_options, + resolve_options, + ) + .await +} + +async fn run>( + args:Arc, + create_tt:impl Fn() -> Arc>, + final_finish:impl FnOnce(Arc>, TaskId, Duration) -> F, + module_options:Option, + resolve_options:Option, +) -> Result> { + let &CommonArgs { watch, show_all, log_detail, log_level, .. } = args.common(); + + let start = Instant::now(); + let finish = |tt:Arc>, root_task:TaskId| { + async move { + if watch { + if let Err(e) = tt.wait_task_completion(root_task, true).await { + println!("{}", e); + } + let UpdateInfo { duration, tasks, .. } = + tt.get_or_wait_aggregated_update_info(Duration::from_millis(100)).await; + println!( + "done in {} ({} task execution, {} tasks)", + FormatDuration(start.elapsed()), + FormatDuration(duration), + tasks + ); + + loop { + let UpdateInfo { duration, tasks, .. } = + tt.get_or_wait_aggregated_update_info(Duration::from_millis(100)).await; + println!("updated {} tasks in {}", tasks, FormatDuration(duration)); + } + } else { + let result = tt.wait_task_completion(root_task, true).await; + let dur = start.elapsed(); + let UpdateInfo { duration, tasks, .. } = + tt.get_or_wait_aggregated_update_info(Duration::from_millis(100)).await; + final_finish(tt, root_task, dur).await; + let dur2 = start.elapsed(); + println!( + "done in {} ({} compilation, {} task execution, {} tasks)", + FormatDuration(dur2), + FormatDuration(dur), + FormatDuration(duration), + tasks + ); + result + } + } + }; + let has_return_value = + matches!(&*args, Args::Annotate { .. }) || matches!(&*args, Args::Print { .. }); + let (sender, mut receiver) = channel(1); + let dir = current_dir().unwrap(); + let tt = create_tt(); + let module_options = TransientInstance::new(module_options.unwrap_or_default()); + let resolve_options = TransientInstance::new(resolve_options.unwrap_or_default()); + let log_options = TransientInstance::new(LogOptions { + current_dir:dir.clone(), + project_dir:dir.clone(), + show_all, + log_detail, + log_level:log_level.map_or_else(|| IssueSeverity::Error, |l| l.0), + }); + let task = tt.spawn_root_task(move || { + let dir = dir.clone(); + let args = args.clone(); + let sender = sender.clone(); + let module_options = module_options.clone(); + let resolve_options = resolve_options.clone(); + let log_options = log_options.clone(); + Box::pin(async move { + let output = main_operation( + TransientValue::new(dir.clone()), + args.clone().into(), + module_options, + resolve_options, + ); + let _ = output.resolve_strongly_consistent().await?; + + let source = TransientValue::new(Vc::into_raw(output)); + let issues = output.peek_issues_with_path().await?; + + let console_ui = ConsoleUi::new(log_options); + Vc::upcast::>(console_ui) + .report_issues(TransientInstance::new(issues), source, IssueSeverity::Error.cell()) + .await?; + + if has_return_value { + let output_read_ref = output.await?; + let output_iter = output_read_ref.iter().cloned(); + sender.send(output_iter.collect::>()).await?; + drop(sender); + } + Ok::, _>(Default::default()) + }) + }); + finish(tt, task).await?; + let output = if has_return_value { receiver.try_recv()? } else { Vec::new() }; + Ok(output) +} + +#[turbo_tasks::function] +async fn main_operation( + current_dir:TransientValue, + args:TransientInstance, + module_options:TransientInstance, + resolve_options:TransientInstance, +) -> Result>> { + let dir = current_dir.into_value(); + let args = &*args; + let &CommonArgs { ref input, watch, exact, ref context_directory, ref process_cwd, .. } = + args.common(); + let context_directory:RcStr = process_context(&dir, context_directory.as_ref()).unwrap().into(); + let fs = create_fs("context directory", &context_directory, watch).await?; + let process_cwd = process_cwd.clone().map(RcStr::from); + + match *args { + Args::Print { common: _ } => { + let input = process_input(&dir, &context_directory, input).unwrap(); + let mut result = BTreeSet::new(); + let modules = input_to_modules( + fs, + input, + exact, + process_cwd.clone(), + context_directory, + module_options, + resolve_options, + ) + .await?; + for module in modules.iter() { + let set = all_modules_and_affecting_sources(*module) + .issue_file_path(module.ident().path(), "gathering list of assets") + .await?; + for asset in set.await?.iter() { + let path = asset.ident().path().await?; + result.insert(RcStr::from(&*path.path)); + } + } + + return Ok(Vc::cell(result.into_iter().collect::>())); + }, + Args::Annotate { common: _ } => { + let input = process_input(&dir, &context_directory, input).unwrap(); + let mut output_nft_assets = Vec::new(); + let mut emits = Vec::new(); + for module in input_to_modules( + fs, + input, + exact, + process_cwd.clone(), + context_directory, + module_options, + resolve_options, + ) + .await? + .iter() + { + let nft_asset = NftJsonAsset::new(*module); + let path = nft_asset.ident().path().await?.path.clone(); + output_nft_assets.push(path); + emits.push(emit_asset(Vc::upcast(nft_asset))); + } + // Wait for all files to be emitted + for emit in emits { + emit.await?; + } + return Ok(Vc::cell(output_nft_assets)); + }, + Args::Build { ref output_directory, common: _ } => { + let output = process_context(&dir, Some(output_directory)).unwrap(); + let input = process_input(&dir, &context_directory, input).unwrap(); + let out_fs = create_fs("output directory", &output, watch).await?; + let input_dir = fs.root(); + let output_dir = out_fs.root(); + let mut emits = Vec::new(); + for module in input_to_modules( + fs, + input, + exact, + process_cwd.clone(), + context_directory, + module_options, + resolve_options, + ) + .await? + .iter() + { + let rebased = Vc::upcast(RebasedAsset::new(*module, input_dir, output_dir)); + emits.push(emit_with_completion(rebased, output_dir)); + } + // Wait for all files to be emitted + for emit in emits { + emit.await?; + } + }, + Args::Size { common: _ } => todo!(), + } + Ok(Vc::cell(Vec::new())) +} + +#[turbo_tasks::function] +async fn create_module_asset( + root:Vc, + process_cwd:Option, + module_options:TransientInstance, + resolve_options:TransientInstance, +) -> Result> { + let env = Environment::new(Value::new(ExecutionEnvironment::NodeJsLambda( + NodeJsEnvironment { cwd:Vc::cell(process_cwd), ..Default::default() }.into(), + ))); + let compile_time_info = CompileTimeInfo::builder(env).cell(); + let glob_mappings = vec![ + ( + root, + Glob::new("**/*/next/dist/server/next.js".into()), + ImportMapping::Ignore.into(), + ), + (root, Glob::new("**/*/next/dist/bin/next".into()), ImportMapping::Ignore.into()), + ]; + let mut resolve_options = ResolveOptionsContext::clone(&*resolve_options); + if resolve_options.emulate_environment.is_none() { + resolve_options.emulate_environment = Some(env); + } + if resolve_options.resolved_map.is_none() { + resolve_options.resolved_map = Some(ResolvedMap { by_glob:glob_mappings }.cell()); + } + + Ok(ModuleAssetContext::new( + Vc::cell(HashMap::new()), + compile_time_info, + ModuleOptionsContext::clone(&*module_options).cell(), + resolve_options.cell(), + Vc::cell("node_file_trace".into()), + )) +} + +fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack::register(); + turbopack_cli_utils::register(); + turbopack_resolve::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/node-file-trace/Source/main.rs b/crates/node-file-trace/Source/main.rs new file mode 100644 index 0000000000000..c3600fa4a350f --- /dev/null +++ b/crates/node-file-trace/Source/main.rs @@ -0,0 +1,25 @@ +#![feature(min_specialization)] + +use std::sync::Arc; + +use anyhow::Result; +use clap::Parser; +use node_file_trace::{Args, start}; + +#[global_allocator] +static ALLOC:turbo_tasks_malloc::TurboMalloc = turbo_tasks_malloc::TurboMalloc; + +#[tokio::main] +async fn main() -> Result<()> { + #[cfg(feature = "tokio_console")] + console_subscriber::init(); + let args = Arc::new(Args::parse()); + let should_print = matches!(&*args, Args::Print { .. }); + let result = start(args, None, None, None).await?; + if should_print { + for file in result.iter() { + println!("{}", file); + } + } + Ok(()) +} diff --git a/crates/node-file-trace/Source/nft_json.rs b/crates/node-file-trace/Source/nft_json.rs new file mode 100644 index 0000000000000..fd1712f7986bd --- /dev/null +++ b/crates/node-file-trace/Source/nft_json.rs @@ -0,0 +1,63 @@ +use anyhow::Result; +use serde_json::json; +use turbo_tasks::Vc; +use turbo_tasks_fs::{File, FileSystem}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + ident::AssetIdent, + module::Module, + output::OutputAsset, + reference::all_modules_and_affecting_sources, +}; + +#[turbo_tasks::value(shared)] +pub struct NftJsonAsset { + entry:Vc>, +} + +#[turbo_tasks::value_impl] +impl NftJsonAsset { + #[turbo_tasks::function] + pub fn new(entry:Vc>) -> Vc { NftJsonAsset { entry }.cell() } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for NftJsonAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let path = self.entry.ident().path().await?; + Ok(AssetIdent::from_path( + path.fs.root().join(format!("{}.nft.json", path.path).into()), + )) + } +} + +#[turbo_tasks::value_impl] +impl Asset for NftJsonAsset { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let parent_dir = self.entry.ident().path().parent().await?; + // For clippy -- This explicit deref is necessary + let entry_path = &*self.entry.ident().path().await?; + let mut result = Vec::new(); + if let Some(self_path) = parent_dir.get_relative_path_to(entry_path) { + let set = all_modules_and_affecting_sources(self.entry); + for asset in set.await?.iter() { + let path = asset.ident().path().await?; + if let Some(rel_path) = parent_dir.get_relative_path_to(&path) { + if rel_path != self_path { + result.push(rel_path); + } + } + } + result.sort(); + result.dedup(); + } + let json = json!({ + "version": 1, + "files": result + }); + + Ok(AssetContent::file(File::from(json.to_string()).into())) + } +} diff --git a/crates/node-file-trace/build.rs b/crates/node-file-trace/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/node-file-trace/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/tower-uds/Cargo.toml b/crates/tower-uds/Cargo.toml index 451fea5c71a18..4f43faa02c9fb 100644 --- a/crates/tower-uds/Cargo.toml +++ b/crates/tower-uds/Cargo.toml @@ -1,17 +1,21 @@ +[dependencies] +tokio = { workspace = true, features = ["net"] } +tower = { version = "0.4.13", features = ["util"] } + +[lib] +path = "Source/lib.rs" + [package] +edition = "2021" +license-file = "LICENSE" name = "tower-uds" version = "0.1.0" -edition = "2021" -license = "MPL-2.0" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -tokio = { workspace = true, features = ["net"] } -tower = { version = "0.4.13", features = ["util"] } +[target] +[target.'cfg(target_os = "windows")'] [target.'cfg(target_os = "windows")'.dependencies] +async-io = "1.12.0" tokio-util = { workspace = true, features = ["compat"] } uds_windows = "1.0.2" -async-io = "1.12.0" diff --git a/crates/tower-uds/Source/lib.rs b/crates/tower-uds/Source/lib.rs new file mode 100644 index 0000000000000..f9ed6141798d2 --- /dev/null +++ b/crates/tower-uds/Source/lib.rs @@ -0,0 +1,55 @@ +//! tower-uds +//! +//! A unix domain socket server for the `tower` ecosystem. + +#![feature(impl_trait_in_assoc_type)] + +use std::{future::Future, path::Path}; + +use tower::Service; + +pub struct UDSConnector<'a> { + path:&'a Path, +} + +impl<'a> UDSConnector<'a> { + pub fn new(path:&'a Path) -> Self { Self { path } } +} + +impl<'a, T> Service for UDSConnector<'a> { + type Error = std::io::Error; + #[cfg(not(target_os = "windows"))] + type Response = tokio::net::UnixStream; + // tokio does not support UDS on windows, so we need to use async-io + // with a tokio compat layer instead + #[cfg(target_os = "windows")] + type Response = tokio_util::compat::Compat>; + + type Future = impl Future> + 'a; + + fn poll_ready( + &mut self, + _cx:&mut std::task::Context<'_>, + ) -> std::task::Poll> { + Ok(()).into() + } + + fn call(&mut self, _req:T) -> Self::Future { + // we need to make sure our ref is immutable so that the closure has a lifetime + // of 'a, not the anonymous lifetime of the call method + let path = self.path; + + #[cfg(not(target_os = "windows"))] + { + async move { tokio::net::UnixStream::connect(path).await } + } + #[cfg(target_os = "windows")] + { + async move { + use tokio_util::compat::FuturesAsyncReadCompatExt; + let stream = uds_windows::UnixStream::connect(path)?; + Ok(FuturesAsyncReadCompatExt::compat(async_io::Async::new(stream)?)) + } + } + } +} diff --git a/crates/tower-uds/src/lib.rs b/crates/tower-uds/src/lib.rs deleted file mode 100644 index a4cab89194730..0000000000000 --- a/crates/tower-uds/src/lib.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! tower-uds -//! -//! A unix domain socket server for the `tower` ecosystem. - -#![feature(impl_trait_in_assoc_type)] - -use std::{future::Future, path::Path}; - -use tower::Service; - -pub struct UDSConnector<'a> { - path: &'a Path, -} - -impl<'a> UDSConnector<'a> { - pub fn new(path: &'a Path) -> Self { - Self { path } - } -} - -impl<'a, T> Service for UDSConnector<'a> { - #[cfg(not(target_os = "windows"))] - type Response = tokio::net::UnixStream; - - // tokio does not support UDS on windows, so we need to use async-io - // with a tokio compat layer instead - #[cfg(target_os = "windows")] - type Response = tokio_util::compat::Compat>; - - type Error = std::io::Error; - - type Future = impl Future> + 'a; - - fn poll_ready( - &mut self, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - Ok(()).into() - } - - fn call(&mut self, _req: T) -> Self::Future { - // we need to make sure our ref is immutable so that the closure has a lifetime - // of 'a, not the anonymous lifetime of the call method - let path = self.path; - - #[cfg(not(target_os = "windows"))] - { - async move { tokio::net::UnixStream::connect(path).await } - } - #[cfg(target_os = "windows")] - { - async move { - use tokio_util::compat::FuturesAsyncReadCompatExt; - let stream = uds_windows::UnixStream::connect(path)?; - Ok(FuturesAsyncReadCompatExt::compat(async_io::Async::new( - stream, - )?)) - } - } - } -} diff --git a/crates/turbo-prehash/Source/lib.rs b/crates/turbo-prehash/Source/lib.rs new file mode 100644 index 0000000000000..8548e7b70ca4f --- /dev/null +++ b/crates/turbo-prehash/Source/lib.rs @@ -0,0 +1,122 @@ +//! turbo-prehash +//! +//! A small wrapper around `std::hash::Hasher` that allows you to pre-hash a +//! value before hashing it. +//! +//! This is useful for when you want to hash a value that is expensive to +//! compute (e.g. a large string) but you want to avoid re-hashing it every +//! time. +//! +//! # Example +//! +//! ``` +//! use std::{ +//! collections::HashMap, +//! hash::{BuildHasherDefault, Hash, RandomState}, +//! }; +//! +//! use turbo_prehash::{BuildHasherExt, PreHashed}; +//! +//! /// hash a key, returning a prehashed value +//! fn hash_key(key:T) -> PreHashed { RandomState::new().prehash(key) } +//! +//! // create hashmap to hold pre-hashed values +//! let mut map:HashMap, String> = Default::default(); +//! +//! // insert a prehashed value +//! let hashed_key = hash_key("hello".to_string()); +//! map.insert(hashed_key.clone(), "world".to_string()); +//! +//! // get the value +//! assert_eq!(map.get(&hashed_key), Some(&"world".to_string())); +//! ``` + +use std::{ + fmt, + hash::{BuildHasher, Hash, Hasher}, + ops::Deref, +}; + +/// A wrapper type that hashes some `inner` on creation, implementing [Hash] +/// by simply returning the pre-computed hash. +#[derive(Copy, Debug, Clone)] +pub struct PreHashed { + hash:H, + inner:I, +} + +impl PreHashed { + /// Create a new [PreHashed] value with the given hash and inner value. + /// + /// SAFETY: The hash must be a valid hash of the inner value. + pub fn new(hash:H, inner:I) -> Self { Self { hash, inner } } + + /// Split the [PreHashed] value into its hash and inner value. + pub fn into_parts(self) -> (H, I) { (self.hash, self.inner) } + + fn inner(&self) -> &I { &self.inner } +} + +impl PreHashed { + /// Create a new [PreHashed] value from a [BuildHasher]. + fn new_from_builder(hasher:&B, inner:I) -> Self { + Self::new(hasher.hash_one(&inner), inner) + } +} + +impl Deref for PreHashed { + type Target = I; + + fn deref(&self) -> &Self::Target { self.inner() } +} + +impl AsRef for PreHashed { + fn as_ref(&self) -> &I { self.inner() } +} + +impl Hash for PreHashed { + fn hash(&self, state:&mut S) { self.hash.hash(state) } +} + +impl Eq for PreHashed {} + +impl PartialEq for PreHashed { + // note: we compare the values, not the hashes + fn eq(&self, other:&Self) -> bool { self.inner.eq(&other.inner) } +} + +impl fmt::Display for PreHashed { + fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result { self.inner.fmt(f) } +} + +/// An implementer of [Hash] that simply returns the pre-computed hash. +#[derive(Copy, Clone, Debug, Default)] +pub struct PassThroughHash(u64); + +impl PassThroughHash { + pub fn new() -> Self { Default::default() } +} + +impl Hasher for PassThroughHash { + fn write(&mut self, _bytes:&[u8]) { unimplemented!("do not use") } + + fn write_u64(&mut self, i:u64) { self.0 = i; } + + fn finish(&self) -> u64 { self.0 } +} + +/// An extension trait for [BuildHasher] that provides the +/// [BuildHasherExt::prehash] method. +pub trait BuildHasherExt: BuildHasher { + type Hash; + + fn prehash(&self, value:T) -> PreHashed; +} + +impl BuildHasherExt for B { + type Hash = u64; + + fn prehash(&self, value:T) -> PreHashed { + PreHashed::new_from_builder(self, value) + } +} diff --git a/crates/turbo-static/.gitignore b/crates/turbo-static/.gitignore new file mode 100644 index 0000000000000..32d96908cdc6b --- /dev/null +++ b/crates/turbo-static/.gitignore @@ -0,0 +1,2 @@ +call_resolver.bincode +graph.cypherl diff --git a/crates/turbo-static/Source/call_resolver.rs b/crates/turbo-static/Source/call_resolver.rs new file mode 100644 index 0000000000000..5adc90aec2cc2 --- /dev/null +++ b/crates/turbo-static/Source/call_resolver.rs @@ -0,0 +1,159 @@ +use std::{collections::HashMap, fs::OpenOptions, path::PathBuf}; + +use crate::{Identifier, IdentifierReference, lsp_client::RAClient}; + +/// A wrapper around a rust-analyzer client that can resolve call references. +/// This is quite expensive so we cache the results in an on-disk key-value +/// store. +pub struct CallResolver<'a> { + client:&'a mut RAClient, + state:HashMap>, + path:Option, +} + +/// On drop, serialize the state to disk +impl<'a> Drop for CallResolver<'a> { + fn drop(&mut self) { + let file = OpenOptions::new() + .create(true) + .truncate(false) + .write(true) + .open(self.path.as_ref().unwrap()) + .unwrap(); + bincode::serialize_into(file, &self.state).unwrap(); + } +} + +impl<'a> CallResolver<'a> { + pub fn new(client:&'a mut RAClient, path:Option) -> Self { + // load bincode-encoded HashMap from path + let state = path + .as_ref() + .and_then(|path| { + let file = OpenOptions::new() + .create(true) + .truncate(false) + .read(true) + .write(true) + .open(path) + .unwrap(); + let reader = std::io::BufReader::new(file); + bincode::deserialize_from::<_, HashMap>>( + reader, + ) + .map_err(|e| { + tracing::warn!("failed to load existing cache, restarting"); + e + }) + .ok() + }) + .unwrap_or_default(); + Self { client, state, path } + } + + pub fn cached_count(&self) -> usize { self.state.len() } + + pub fn cleared(mut self) -> Self { + // delete file if exists and clear state + self.state = Default::default(); + if let Some(path) = self.path.as_ref() { + std::fs::remove_file(path).unwrap(); + } + self + } + + pub fn resolve(&mut self, ident:&Identifier) -> Vec { + if let Some(data) = self.state.get(ident) { + tracing::info!("skipping {}", ident); + return data.to_owned(); + }; + + tracing::info!("checking {}", ident); + + let mut count = 0; + let _response = loop { + let Some(response) = self.client.request(lsp_server::Request { + id:1.into(), + method:"textDocument/prepareCallHierarchy".to_string(), + params:serde_json::to_value(&lsp_types::CallHierarchyPrepareParams { + text_document_position_params:lsp_types::TextDocumentPositionParams { + position:ident.range.start, + text_document:lsp_types::TextDocumentIdentifier { + uri:lsp_types::Url::from_file_path(&ident.path).unwrap(), + }, + }, + work_done_progress_params:lsp_types::WorkDoneProgressParams { + work_done_token:Some(lsp_types::ProgressToken::String( + "prepare".to_string(), + )), + }, + }) + .unwrap(), + }) else { + tracing::warn!("RA server shut down"); + return vec![]; + }; + + if let Some(Some(value)) = response.result.as_ref().map(|r| r.as_array()) { + if !value.is_empty() { + break value.to_owned(); + } + count += 1; + } + + // textDocument/prepareCallHierarchy will sometimes return an empty array so try + // at most 5 times + if count > 5 { + tracing::warn!("discovered isolated task {}", ident); + break vec![]; + } + + std::thread::sleep(std::time::Duration::from_secs(1)); + }; + + // callHierarchy/incomingCalls + let Some(response) = self.client.request(lsp_server::Request { + id:1.into(), + method:"callHierarchy/incomingCalls".to_string(), + params:serde_json::to_value(lsp_types::CallHierarchyIncomingCallsParams { + partial_result_params:lsp_types::PartialResultParams::default(), + item:lsp_types::CallHierarchyItem { + name:ident.name.to_owned(), + kind:lsp_types::SymbolKind::FUNCTION, + data:None, + tags:None, + detail:None, + uri:lsp_types::Url::from_file_path(&ident.path).unwrap(), + range:ident.range, + selection_range:ident.range, + }, + work_done_progress_params:lsp_types::WorkDoneProgressParams { + work_done_token:Some(lsp_types::ProgressToken::String("prepare".to_string())), + }, + }) + .unwrap(), + }) else { + tracing::warn!("RA server shut down"); + return vec![]; + }; + + let links = if let Some(e) = response.error { + tracing::warn!("unable to resolve {}: {:?}", ident, e); + vec![] + } else { + let response:Result, _> = + serde_path_to_error::deserialize(response.result.unwrap()); + + response + .unwrap() + .into_iter() + .map(|i| i.into()) + .collect::>() + }; + + tracing::debug!("links: {:?}", links); + + self.state.insert(ident.to_owned(), links.clone()); + links + } +} diff --git a/crates/turbo-static/Source/identifier.rs b/crates/turbo-static/Source/identifier.rs new file mode 100644 index 0000000000000..c1b68bd2a95fb --- /dev/null +++ b/crates/turbo-static/Source/identifier.rs @@ -0,0 +1,95 @@ +use std::{fs, path::PathBuf}; + +use lsp_types::{CallHierarchyIncomingCall, CallHierarchyItem, Range}; + +/// A task that references another, with the range of the reference +#[derive(Hash, PartialEq, Eq, serde::Deserialize, serde::Serialize, Clone, Debug)] +pub struct IdentifierReference { + pub identifier:Identifier, + pub references:Vec, // the places where this identifier is used +} + +/// identifies a task by its file, and range in the file +#[derive(Hash, PartialEq, Eq, serde::Deserialize, serde::Serialize, Clone)] +pub struct Identifier { + pub path:String, + // technically you can derive this from the name and range but it's easier to just store it + pub name:String, + // post_transform_name: Option, + pub range:lsp_types::Range, +} + +impl Identifier { + /// check the span matches and the text matches + /// + /// `same_location` is used to check if the location of the identifier is + /// the same as the other + pub fn equals_ident(&self, other:&syn::Ident, match_location:bool) -> bool { + *other == self.name + && (!match_location + || (self.range.start.line == other.span().start().line as u32 + && self.range.start.character == other.span().start().column as u32)) + } + + /// We cannot use `item.name` here in all cases as, during testing, the name + /// does not always align with the exact text in the range. + fn get_name(item:&CallHierarchyItem) -> String { + // open file, find range inside, extract text + let file = fs::read_to_string(item.uri.path()).unwrap(); + let start = item.selection_range.start; + let end = item.selection_range.end; + file.lines() + .nth(start.line as usize) + .unwrap() + .chars() + .skip(start.character as usize) + .take(end.character as usize - start.character as usize) + .collect() + } +} + +impl From<(PathBuf, syn::Ident)> for Identifier { + fn from((path, ident):(PathBuf, syn::Ident)) -> Self { + Self { + path:path.display().to_string(), + name:ident.to_string(), + // post_transform_name: None, + range:Range { + start:lsp_types::Position { + line:ident.span().start().line as u32 - 1, + character:ident.span().start().column as u32, + }, + end:lsp_types::Position { + line:ident.span().end().line as u32 - 1, + character:ident.span().end().column as u32, + }, + }, + } + } +} + +impl From for IdentifierReference { + fn from(item:CallHierarchyIncomingCall) -> Self { + Self { + identifier:Identifier { + name:Identifier::get_name(&item.from), + // post_transform_name: Some(item.from.name), + path:item.from.uri.path().to_owned(), + range:item.from.selection_range, + }, + references:item.from_ranges, + } + } +} + +impl std::fmt::Debug for Identifier { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + +impl std::fmt::Display for Identifier { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}:{}#{}", self.path, self.range.start.line, self.name,) + } +} diff --git a/crates/turbo-static/Source/lsp_client.rs b/crates/turbo-static/Source/lsp_client.rs new file mode 100644 index 0000000000000..108db0f372e6e --- /dev/null +++ b/crates/turbo-static/Source/lsp_client.rs @@ -0,0 +1,149 @@ +use std::{path::PathBuf, process, sync::mpsc}; + +use lsp_server::Message; + +/// An LSP client for Rust Analyzer (RA) that launches it as a subprocess. +pub struct RAClient { + /// Handle to the client + handle:process::Child, + sender:Option>, + receiver:Option>, +} + +impl RAClient { + /// Create a new LSP client for Rust Analyzer. + pub fn new() -> Self { + let stdin = process::Stdio::piped(); + let stdout = process::Stdio::piped(); + let stderr = process::Stdio::inherit(); + + let child = process::Command::new("rust-analyzer") + .stdin(stdin) + .stdout(stdout) + .stderr(stderr) + // .env("RA_LOG", "info") + .env("RUST_BACKTRACE", "1") + .spawn() + .expect("Failed to start RA LSP server"); + Self { handle:child, sender:None, receiver:None } + } + + pub fn start(&mut self, folders:&[PathBuf]) { + let stdout = self.handle.stdout.take().unwrap(); + let mut stdin = self.handle.stdin.take().unwrap(); + + let (writer_sender, writer_receiver) = mpsc::sync_channel::(0); + _ = std::thread::spawn(move || { + writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdin)) + }); + + let (reader_sender, reader_receiver) = mpsc::sync_channel::(0); + _ = std::thread::spawn(move || { + let mut reader = std::io::BufReader::new(stdout); + while let Ok(Some(msg)) = Message::read(&mut reader) { + reader_sender.send(msg).expect("receiver was dropped, failed to send a message"); + } + }); + + self.sender = Some(writer_sender); + self.receiver = Some(reader_receiver); + + let workspace_paths = folders + .iter() + .map(|p| std::fs::canonicalize(p).unwrap()) + .map(|p| { + lsp_types::WorkspaceFolder { + name:p.file_name().unwrap().to_string_lossy().to_string(), + uri:lsp_types::Url::from_file_path(p).unwrap(), + } + }) + .collect::>(); + + _ = self.request(lsp_server::Request { + id:1.into(), + method:"initialize".to_string(), + params:serde_json::to_value(lsp_types::InitializeParams { + workspace_folders:Some(workspace_paths), + process_id:Some(std::process::id()), + capabilities:lsp_types::ClientCapabilities { + workspace:Some(lsp_types::WorkspaceClientCapabilities { + workspace_folders:Some(true), + ..Default::default() + }), + ..Default::default() + }, + work_done_progress_params:lsp_types::WorkDoneProgressParams { + work_done_token:Some(lsp_types::ProgressToken::String("prepare".to_string())), + }, + // we use workspace_folders so root_path and root_uri can be + // empty + ..Default::default() + }) + .unwrap(), + }); + + self.notify(lsp_server::Notification { + method:"initialized".to_string(), + params:serde_json::to_value(lsp_types::InitializedParams {}).unwrap(), + }); + } + + /// Send an LSP request to the server. This returns an option + /// in the case of an error such as the server being shut down + /// from pressing `Ctrl+C`. + pub fn request(&mut self, message:lsp_server::Request) -> Option { + tracing::debug!("sending {:?}", message); + self.sender.as_mut().unwrap().send(Message::Request(message)).ok()?; + + loop { + match self.receiver.as_mut().unwrap().recv() { + Ok(lsp_server::Message::Response(response)) => { + tracing::debug!("received {:?}", response); + return Some(response); + }, + Ok(m) => tracing::trace!("unexpected message: {:?}", m), + Err(_) => { + tracing::trace!("error receiving message"); + return None; + }, + } + } + } + + pub fn notify(&mut self, message:lsp_server::Notification) { + self.sender + .as_mut() + .unwrap() + .send(Message::Notification(message)) + .expect("failed to send message"); + } +} + +impl Drop for RAClient { + fn drop(&mut self) { + if self.sender.is_some() { + let Some(resp) = self.request(lsp_server::Request { + id:1.into(), + method:"shutdown".to_string(), + params:serde_json::to_value(()).unwrap(), + }) else { + return; + }; + + if resp.error.is_none() { + tracing::info!("shutting down RA LSP server"); + self.notify(lsp_server::Notification { + method:"exit".to_string(), + params:serde_json::to_value(()).unwrap(), + }); + self.handle.wait().expect("failed to wait for RA LSP server"); + tracing::info!("shut down RA LSP server"); + } else { + tracing::error!("failed to shutdown RA LSP server: {:#?}", resp); + } + } + + self.sender = None; + self.receiver = None; + } +} diff --git a/crates/turbo-static/Source/main.rs b/crates/turbo-static/Source/main.rs new file mode 100644 index 0000000000000..a0fffd8032580 --- /dev/null +++ b/crates/turbo-static/Source/main.rs @@ -0,0 +1,295 @@ +#![feature(entry_insert)] + +use std::{ + collections::{HashMap, HashSet}, + error::Error, + fs, + path::PathBuf, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, +}; + +use call_resolver::CallResolver; +use clap::Parser; +use identifier::{Identifier, IdentifierReference}; +use itertools::Itertools; +use syn::visit::Visit; +use visitor::CallingStyleVisitor; + +use crate::visitor::CallingStyle; + +mod call_resolver; +mod identifier; +mod lsp_client; +mod visitor; + +#[derive(Parser)] +struct Opt { + #[clap(required = true)] + paths:Vec, + + /// reparse all files + #[clap(long)] + reparse:bool, + + /// reindex all files + #[clap(long)] + reindex:bool, +} + +fn main() -> Result<(), Box> { + tracing_subscriber::fmt::init(); + let opt = Opt::parse(); + + let mut connection = lsp_client::RAClient::new(); + connection.start(&opt.paths); + + let call_resolver = CallResolver::new(&mut connection, Some("call_resolver.bincode".into())); + let mut call_resolver = if opt.reindex { call_resolver.cleared() } else { call_resolver }; + + let halt = Arc::new(AtomicBool::new(false)); + let halt_clone = halt.clone(); + ctrlc::set_handler({ + move || { + halt_clone.store(true, Ordering::SeqCst); + } + })?; + + tracing::info!("getting tasks"); + let mut tasks = get_all_tasks(&opt.paths); + let dep_tree = resolve_tasks(&mut tasks, &mut call_resolver, halt.clone()); + let concurrency = resolve_concurrency(&tasks, &dep_tree, halt.clone()); + + write_dep_tree(&tasks, concurrency, std::path::Path::new("graph.cypherl")); + + if halt.load(Ordering::Relaxed) { + tracing::info!("ctrl-c detected, exiting"); + } + + Ok(()) +} + +/// search the given folders recursively and attempt to find all tasks inside +#[tracing::instrument(skip_all)] +fn get_all_tasks(folders:&[PathBuf]) -> HashMap> { + let mut out = HashMap::new(); + + for folder in folders { + let walker = ignore::Walk::new(folder); + for entry in walker { + let entry = entry.unwrap(); + let rs_file = if let Some(true) = entry.file_type().map(|t| t.is_file()) { + let path = entry.path(); + let ext = path.extension().unwrap_or_default(); + if ext == "rs" { + std::fs::canonicalize(path).unwrap() + } else { + continue; + } + } else { + continue; + }; + + let file = fs::read_to_string(&rs_file).unwrap(); + let lines = file.lines(); + let mut occurences = vec![]; + + tracing::debug!("processing {}", rs_file.display()); + + for ((_, line), (line_no, _)) in lines.enumerate().tuple_windows() { + if line.contains("turbo_tasks::function") { + tracing::debug!("found at {:?}:L{}", rs_file, line_no); + occurences.push(line_no + 1); + } + } + + if occurences.is_empty() { + continue; + } + + // parse the file using syn and get the span of the functions + let file = syn::parse_file(&file).unwrap(); + let occurences_count = occurences.len(); + let mut visitor = visitor::TaskVisitor::new(); + syn::visit::visit_file(&mut visitor, &file); + if visitor.results.len() != occurences_count { + tracing::warn!( + "file {:?} passed the heuristic with {:?} but the visitor found {:?}", + rs_file, + occurences_count, + visitor.results.len() + ); + } + + out.extend( + visitor + .results + .into_iter() + .map(move |(ident, tags)| ((rs_file.clone(), ident).into(), tags)), + ) + } + } + + out +} + +/// Given a list of tasks, get all the tasks that call that one +fn resolve_tasks( + tasks:&mut HashMap>, + client:&mut CallResolver, + halt:Arc, +) -> HashMap> { + tracing::info!("found {} tasks, of which {} cached", tasks.len(), client.cached_count()); + + let mut unresolved = tasks.keys().cloned().collect::>(); + let mut resolved = HashMap::new(); + + while let Some(top) = unresolved.iter().next().cloned() { + unresolved.remove(&top); + + let callers = client.resolve(&top); + + // add all non-task callers to the unresolved list if they are not in the + // resolved list + for caller in callers.iter() { + if !resolved.contains_key(&caller.identifier) + && !unresolved.contains(&caller.identifier) + { + tracing::debug!("adding {} to unresolved", caller.identifier); + unresolved.insert(caller.identifier.to_owned()); + } + } + resolved.insert(top.to_owned(), callers); + + if halt.load(Ordering::Relaxed) { + break; + } + } + + resolved +} + +/// given a map of tasks and functions that call it, produce a map of tasks and +/// those tasks that it calls +/// +/// returns a list of pairs with a task, the task that calls it, and the calling +/// style +fn resolve_concurrency( + task_list:&HashMap>, + dep_tree:&HashMap>, // pairs of tasks and call trees + halt:Arc, +) -> Vec<(Identifier, Identifier, CallingStyle)> { + // println!("{:?}", dep_tree); + // println!("{:#?}", task_list); + + let mut edges = vec![]; + + for (ident, references) in dep_tree { + for reference in references { + if !dep_tree.contains_key(&reference.identifier) { + // this is a task that is not in the task list + // so we can't resolve it + tracing::error!("missing task for {}: {}", ident, reference.identifier); + for task in task_list.keys() { + if task.name == reference.identifier.name { + // we found a task that is not in the task list + // so we can't resolve it + tracing::trace!("- found {}", task); + continue; + } + } + continue; + } else { + // load the source file and get the calling style + let target = IdentifierReference { + identifier:ident.clone(), + references:reference.references.clone(), + }; + let mut visitor = CallingStyleVisitor::new(target); + tracing::info!("looking for {} from {}", ident, reference.identifier); + let file = + syn::parse_file(&fs::read_to_string(&reference.identifier.path).unwrap()) + .unwrap(); + visitor.visit_file(&file); + + edges.push(( + ident.clone(), + reference.identifier.clone(), + visitor.result().unwrap_or(CallingStyle::Once), + )); + } + + if halt.load(Ordering::Relaxed) { + break; + } + } + } + + // parse each fn between parent and child and get the max calling style + + edges +} + +/// Write the dep tree into the given file using cypher syntax +fn write_dep_tree( + task_list:&HashMap>, + dep_tree:Vec<(Identifier, Identifier, CallingStyle)>, + out:&std::path::Path, +) { + use std::io::Write; + + let mut node_ids = HashMap::new(); + let mut counter = 0; + + let mut file = std::fs::File::create(out).unwrap(); + + let empty = vec![]; + + // collect all tasks as well as all intermediate nodes + // tasks come last to ensure the tags are preserved + let node_list = dep_tree + .iter() + .flat_map(|(dest, src, _)| [(src, &empty), (dest, &empty)]) + .chain(task_list) + .collect::>(); + + for (ident, tags) in node_list { + counter += 1; + + let label = if !task_list.contains_key(ident) { + "Function" + } else if tags.contains(&"fs".to_string()) || tags.contains(&"network".to_string()) { + "ImpureTask" + } else { + "Task" + }; + + _ = writeln!( + file, + "CREATE (n_{}:{} {{name: '{}', file: '{}', line: {}, tags: [{}]}})", + counter, + label, + ident.name, + ident.path, + ident.range.start.line, + tags.iter().map(|t| format!("\"{}\"", t)).join(",") + ); + node_ids.insert(ident, counter); + } + + for (dest, src, style) in &dep_tree { + let style = match style { + CallingStyle::Once => "ONCE", + CallingStyle::ZeroOrOnce => "ZERO_OR_ONCE", + CallingStyle::ZeroOrMore => "ZERO_OR_MORE", + CallingStyle::OneOrMore => "ONE_OR_MORE", + }; + + let src_id = *node_ids.get(src).unwrap(); + let dst_id = *node_ids.get(dest).unwrap(); + + _ = writeln!(file, "CREATE (n_{})-[:{}]->(n_{})", src_id, style, dst_id,); + } +} diff --git a/crates/turbo-static/Source/visitor.rs b/crates/turbo-static/Source/visitor.rs new file mode 100644 index 0000000000000..02677b39d4db2 --- /dev/null +++ b/crates/turbo-static/Source/visitor.rs @@ -0,0 +1,262 @@ +//! A visitor that traverses the AST and collects all functions or methods that +//! are annotated with `#[turbo_tasks::function]`. + +use std::{collections::VecDeque, ops::Add}; + +use lsp_types::Range; +use syn::{Expr, Meta, visit::Visit}; + +use crate::identifier::Identifier; + +pub struct TaskVisitor { + /// the list of results as pairs of an identifier and its tags + pub results:Vec<(syn::Ident, Vec)>, +} + +impl TaskVisitor { + pub fn new() -> Self { Self { results:Default::default() } } +} + +impl Visit<'_> for TaskVisitor { + #[tracing::instrument(skip_all)] + fn visit_item_fn(&mut self, i:&syn::ItemFn) { + if let Some(tags) = extract_tags(i.attrs.iter()) { + tracing::trace!("L{}: {}", i.sig.ident.span().start().line, i.sig.ident,); + self.results.push((i.sig.ident.clone(), tags)); + } + } + + #[tracing::instrument(skip_all)] + fn visit_impl_item_fn(&mut self, i:&syn::ImplItemFn) { + if let Some(tags) = extract_tags(i.attrs.iter()) { + tracing::trace!("L{}: {}", i.sig.ident.span().start().line, i.sig.ident,); + self.results.push((i.sig.ident.clone(), tags)); + } + } +} + +fn extract_tags<'a>(mut meta:impl Iterator) -> Option> { + meta.find_map(|a| { + match &a.meta { + // path has two segments, turbo_tasks and function + Meta::Path(path) if path.segments.len() == 2 => { + let first = &path.segments[0]; + let second = &path.segments[1]; + (first.ident == "turbo_tasks" && second.ident == "function") + .then(std::vec::Vec::new) + }, + Meta::List(list) if list.path.segments.len() == 2 => { + let first = &list.path.segments[0]; + let second = &list.path.segments[1]; + if first.ident != "turbo_tasks" || second.ident != "function" { + return None; + } + + // collect ident tokens as args + let tags:Vec<_> = list + .tokens + .clone() + .into_iter() + .filter_map(|t| { + if let proc_macro2::TokenTree::Ident(ident) = t { + Some(ident.to_string()) + } else { + None + } + }) + .collect(); + + Some(tags) + }, + _ => { + tracing::trace!("skipping unknown annotation"); + None + }, + } + }) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)] +pub enum CallingStyle { + Once = 0b0010, + ZeroOrOnce = 0b0011, + ZeroOrMore = 0b0111, + OneOrMore = 0b0110, +} + +impl CallingStyle { + fn bitset(self) -> u8 { self as u8 } +} + +impl Add for CallingStyle { + type Output = Self; + + /// Add two calling styles together to determine the calling style of the + /// target function within the source function. + /// + /// Consider it as a bitset over properties. + /// - 0b000: Nothing + /// - 0b001: Zero + /// - 0b010: Once + /// - 0b011: Zero Or Once + /// - 0b100: More Than Once + /// - 0b101: Zero Or More Than Once (?) + /// - 0b110: Once Or More + /// - 0b111: Zero Or More + /// + /// Note that zero is not a valid calling style. + fn add(self, rhs:Self) -> Self { + let left = self.bitset(); + let right = rhs.bitset(); + + // we treat this as a bitset under addition + #[allow(clippy::suspicious_arithmetic_impl)] + match left | right { + 0b0010 => CallingStyle::Once, + 0b011 => CallingStyle::ZeroOrOnce, + 0b0111 => CallingStyle::ZeroOrMore, + 0b0110 => CallingStyle::OneOrMore, + // the remaining 4 (null, zero, more than once, zero or more than once) + // are unreachable because we don't detect 'zero' or 'more than once' + _ => unreachable!(), + } + } +} + +pub struct CallingStyleVisitor { + pub reference:crate::IdentifierReference, + state:VecDeque, + halt:bool, +} + +impl CallingStyleVisitor { + /// Create a new visitor that will traverse the AST and determine the + /// calling style of the target function within the source function. + pub fn new(reference:crate::IdentifierReference) -> Self { + Self { reference, state:Default::default(), halt:false } + } + + pub fn result(self) -> Option { + self.state + .into_iter() + .map(|b| { + match b { + CallingStyleVisitorState::Block => CallingStyle::Once, + CallingStyleVisitorState::Loop => CallingStyle::ZeroOrMore, + CallingStyleVisitorState::If => CallingStyle::ZeroOrOnce, + CallingStyleVisitorState::Closure => CallingStyle::ZeroOrMore, + } + }) + .reduce(|a, b| a + b) + } +} + +#[derive(Debug, Clone, Copy)] +enum CallingStyleVisitorState { + Block, + Loop, + If, + Closure, +} + +impl Visit<'_> for CallingStyleVisitor { + fn visit_item_fn(&mut self, i:&'_ syn::ItemFn) { + self.state.push_back(CallingStyleVisitorState::Block); + syn::visit::visit_item_fn(self, i); + if !self.halt { + self.state.pop_back(); + } + } + + fn visit_impl_item_fn(&mut self, i:&'_ syn::ImplItemFn) { + self.state.push_back(CallingStyleVisitorState::Block); + syn::visit::visit_impl_item_fn(self, i); + if !self.halt { + self.state.pop_back(); + } + } + + fn visit_expr_loop(&mut self, i:&'_ syn::ExprLoop) { + self.state.push_back(CallingStyleVisitorState::Loop); + syn::visit::visit_expr_loop(self, i); + if !self.halt { + self.state.pop_back(); + } + } + + fn visit_expr_for_loop(&mut self, i:&'_ syn::ExprForLoop) { + self.state.push_back(CallingStyleVisitorState::Loop); + syn::visit::visit_expr_for_loop(self, i); + if !self.halt { + self.state.pop_back(); + } + } + + fn visit_expr_if(&mut self, i:&'_ syn::ExprIf) { + self.state.push_back(CallingStyleVisitorState::If); + syn::visit::visit_expr_if(self, i); + if !self.halt { + self.state.pop_back(); + } + } + + fn visit_expr_closure(&mut self, i:&'_ syn::ExprClosure) { + self.state.push_back(CallingStyleVisitorState::Closure); + syn::visit::visit_expr_closure(self, i); + if !self.halt { + self.state.pop_back(); + } + } + + fn visit_expr_call(&mut self, i:&'_ syn::ExprCall) { + syn::visit::visit_expr_call(self, i); + if let Expr::Path(p) = i.func.as_ref() { + if let Some(last) = p.path.segments.last() { + if is_match(&self.reference.identifier, &last.ident, &self.reference.references) { + self.halt = true; + } + } + } + } + + // to validate this, we first check if the name is the same and then compare it + // against any of the references we are holding + fn visit_expr_method_call(&mut self, i:&'_ syn::ExprMethodCall) { + if is_match(&self.reference.identifier, &i.method, &self.reference.references) { + self.halt = true; + } + + syn::visit::visit_expr_method_call(self, i); + } +} + +/// Check if some ident referenced by `check` is calling the `target` by +/// looking it up in the list of known `ranges`. +fn is_match(target:&Identifier, check:&syn::Ident, ranges:&[Range]) -> bool { + if target.equals_ident(check, false) { + let span = check.span(); + // syn is 1-indexed, range is not + for reference in ranges { + if reference.start.line != span.start().line as u32 - 1 { + continue; + } + + if reference.start.character != span.start().column as u32 { + continue; + } + + if reference.end.line != span.end().line as u32 - 1 { + continue; + } + + if reference.end.character != span.end().column as u32 { + continue; + } + + // match, just exit the visitor + return true; + } + } + + false +} diff --git a/crates/turbo-tasks-auto-hash-map/Source/lib.rs b/crates/turbo-tasks-auto-hash-map/Source/lib.rs new file mode 100644 index 0000000000000..262ce6b8ae1ef --- /dev/null +++ b/crates/turbo-tasks-auto-hash-map/Source/lib.rs @@ -0,0 +1,14 @@ +#![feature(hash_raw_entry)] + +pub mod map; +pub mod set; + +pub use map::AutoMap; +pub use set::AutoSet; + +// Values based on data from https://github.com/yegor256/micromap#benchmark + +/// Maximum size of list variant. Must convert to HashMap when bigger. +pub const MAX_LIST_SIZE:usize = 32; +/// Minimum size of HashMap variant. Must convert to List when smaller. +pub const MIN_HASH_SIZE:usize = 16; diff --git a/crates/turbo-tasks-auto-hash-map/Source/map.rs b/crates/turbo-tasks-auto-hash-map/Source/map.rs new file mode 100644 index 0000000000000..0b362feb5bcaf --- /dev/null +++ b/crates/turbo-tasks-auto-hash-map/Source/map.rs @@ -0,0 +1,804 @@ +use std::{ + borrow::Borrow, + collections::{HashMap, hash_map::RandomState}, + fmt::{Debug, Formatter}, + hash::{BuildHasher, Hash}, + marker::PhantomData, +}; + +use serde::{ + Deserialize, + Deserializer, + Serialize, + Serializer, + de::{MapAccess, Visitor}, + ser::SerializeMap, +}; +use smallvec::SmallVec; + +use crate::{MAX_LIST_SIZE, MIN_HASH_SIZE}; + +#[derive(Clone)] +pub enum AutoMap { + List(SmallVec<[(K, V); I]>), + Map(Box>), +} + +impl Default for AutoMap { + fn default() -> Self { Self::List(Default::default()) } +} + +impl Debug for AutoMap { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_map().entries(self.iter()).finish() + } +} + +impl AutoMap { + /// see [HashMap::new](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.new) + pub const fn new() -> Self { AutoMap::List(SmallVec::new_const()) } + + /// see [HashMap::with_capacity](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.with_capacity) + pub fn with_capacity(capacity:usize) -> Self { + if capacity < MAX_LIST_SIZE { + AutoMap::List(SmallVec::with_capacity(capacity)) + } else { + AutoMap::Map(Box::new(HashMap::with_capacity_and_hasher(capacity, Default::default()))) + } + } +} + +impl AutoMap { + /// see [HashMap::with_hasher](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.with_hasher) + pub const fn with_hasher() -> Self { AutoMap::List(SmallVec::new_const()) } + + /// see [HashMap::with_capacity_and_hasher](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.with_capacity_and_hasher) + pub fn with_capacity_and_hasher(capacity:usize, hasher:H) -> Self { + if capacity <= MAX_LIST_SIZE { + AutoMap::List(SmallVec::with_capacity(capacity)) + } else { + AutoMap::Map(Box::new(HashMap::with_capacity_and_hasher(capacity, hasher))) + } + } + + /// see [HashMap::clear](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.clear) + pub fn clear(&mut self) { + match self { + AutoMap::List(list) => list.clear(), + AutoMap::Map(map) => map.clear(), + } + } +} + +impl AutoMap { + fn convert_to_map(&mut self) -> &mut HashMap { + if let AutoMap::List(list) = self { + let mut map = HashMap::with_capacity_and_hasher(MAX_LIST_SIZE * 2, Default::default()); + map.extend(list.drain(..)); + *self = AutoMap::Map(Box::new(map)); + } + if let AutoMap::Map(map) = self { map } else { unreachable!() } + } + + fn convert_to_list(&mut self) -> &mut SmallVec<[(K, V); I]> { + if let AutoMap::Map(map) = self { + let mut list = SmallVec::with_capacity(MAX_LIST_SIZE); + list.extend(map.drain()); + *self = AutoMap::List(list); + } + if let AutoMap::List(list) = self { list } else { unreachable!() } + } + + /// see [HashMap::insert](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.insert) + pub fn insert(&mut self, key:K, value:V) -> Option { + match self { + AutoMap::List(list) => { + for (k, v) in list.iter_mut() { + if *k == key { + return Some(std::mem::replace(v, value)); + } + } + if list.len() >= MAX_LIST_SIZE { + let map = self.convert_to_map(); + map.insert(key, value); + } else { + list.push((key, value)); + } + None + }, + AutoMap::Map(map) => map.insert(key, value), + } + } + + /// see [HashMap::remove](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.remove) + pub fn remove(&mut self, key:&K) -> Option { + match self { + AutoMap::List(list) => { + for i in 0..list.len() { + if list[i].0 == *key { + return Some(list.swap_remove(i).1); + } + } + None + }, + AutoMap::Map(map) => { + let result = map.remove(key); + if result.is_some() && map.len() < MIN_HASH_SIZE { + self.convert_to_list(); + } + result + }, + } + } + + /// see [HashMap::extend](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.extend) + pub fn extend(&mut self, iter:impl IntoIterator) { + let iter = iter.into_iter(); + match self { + AutoMap::List(list) => { + let (lower, _) = iter.size_hint(); + if list.len() + lower > MAX_LIST_SIZE { + let map = self.convert_to_map(); + map.extend(iter); + // The hint is not enforced + if map.len() < MIN_HASH_SIZE { + self.convert_to_list(); + } + return; + } + for (k, v) in iter { + self.insert(k, v); + } + }, + AutoMap::Map(map) => { + map.extend(iter); + }, + } + } + + /// see [HashMap::entry](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.entry) + pub fn entry(&mut self, key:K) -> Entry<'_, K, V, H, I> { + let this = self as *mut Self; + match self { + AutoMap::List(list) => { + match list.iter().position(|(k, _)| *k == key) { + Some(index) => Entry::Occupied(OccupiedEntry::List { list, index }), + None => Entry::Vacant(VacantEntry::List { this, list, key }), + } + }, + AutoMap::Map(map) => { + match map.entry(key) { + std::collections::hash_map::Entry::Occupied(entry) => { + Entry::Occupied(OccupiedEntry::Map { this, entry }) + }, + std::collections::hash_map::Entry::Vacant(entry) => { + Entry::Vacant(VacantEntry::Map(entry)) + }, + } + }, + } + } + + pub fn raw_entry_mut(&mut self, key:&Q) -> RawEntry<'_, K, V, H, I> + where + K: Borrow, + Q: Hash + Eq + ?Sized, { + let this = self as *mut Self; + match self { + AutoMap::List(list) => { + match list.iter().position(|(k, _)| k.borrow() == key) { + Some(index) => RawEntry::Occupied(OccupiedRawEntry::List { list, index }), + None => RawEntry::Vacant(VacantRawEntry::List { this, list }), + } + }, + AutoMap::Map(map) => { + match map.raw_entry_mut().from_key(key) { + std::collections::hash_map::RawEntryMut::Occupied(entry) => { + RawEntry::Occupied(OccupiedRawEntry::Map { this, entry }) + }, + std::collections::hash_map::RawEntryMut::Vacant(entry) => { + RawEntry::Vacant(VacantRawEntry::Map(entry)) + }, + } + }, + } + } + + /// see [HashMap::shrink_to_fit](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.shrink_to_fit) + pub fn shrink_to_fit(&mut self) { + match self { + AutoMap::List(list) => list.shrink_to_fit(), + AutoMap::Map(map) => { + if map.len() <= MAX_LIST_SIZE { + let mut list = SmallVec::with_capacity(map.len()); + list.extend(map.drain()); + *self = AutoMap::List(list); + } else { + map.shrink_to_fit(); + } + }, + } + } +} + +impl AutoMap { + /// see [HashMap::get](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get) + pub fn get(&self, key:&Q) -> Option<&V> + where + K: Borrow, + Q: Hash + Eq + ?Sized, { + match self { + AutoMap::List(list) => { + list.iter().find_map(|(k, v)| if *k.borrow() == *key { Some(v) } else { None }) + }, + AutoMap::Map(map) => map.get(key), + } + } + + /// see [HashMap::get_mut](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get_mut) + pub fn get_mut(&mut self, key:&K) -> Option<&mut V> { + match self { + AutoMap::List(list) => { + list.iter_mut().find_map(|(k, v)| if *k == *key { Some(v) } else { None }) + }, + AutoMap::Map(map) => map.get_mut(key), + } + } + + /// see [HashMap::contains_key](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.contains_key) + pub fn contains_key(&self, key:&K) -> bool { + match self { + AutoMap::List(list) => list.iter().any(|(k, _)| *k == *key), + AutoMap::Map(map) => map.contains_key(key), + } + } +} + +impl AutoMap { + /// see [HashMap::iter](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.iter) + pub fn iter(&self) -> Iter<'_, K, V> { + match self { + AutoMap::List(list) => Iter::List(list.iter()), + AutoMap::Map(map) => Iter::Map(map.iter()), + } + } + + /// see [HashMap::iter_mut](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.iter_mut) + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + match self { + AutoMap::List(list) => IterMut::List(list.iter_mut()), + AutoMap::Map(map) => IterMut::Map(map.iter_mut()), + } + } + + /// see [HashMap::is_empty](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.is_empty) + pub fn is_empty(&self) -> bool { + match self { + AutoMap::List(list) => list.is_empty(), + AutoMap::Map(map) => map.is_empty(), + } + } + + /// see [HashMap::len](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.len) + pub fn len(&self) -> usize { + match self { + AutoMap::List(list) => list.len(), + AutoMap::Map(map) => map.len(), + } + } + + /// see [HashMap::values_mut](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.values_mut) + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + match self { + AutoMap::List(list) => ValuesMut::List(list.iter_mut()), + AutoMap::Map(map) => ValuesMut::Map(map.values_mut()), + } + } + + /// see [HashMap::values](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.values) + pub fn values(&self) -> Values<'_, K, V> { + match self { + AutoMap::List(list) => Values::List(list.iter()), + AutoMap::Map(map) => Values::Map(map.values()), + } + } + + /// see [HashMap::into_values](https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.into_values) + pub fn into_values(self) -> IntoValues { + match self { + AutoMap::List(list) => IntoValues::List(list.into_iter()), + AutoMap::Map(map) => IntoValues::Map(map.into_values()), + } + } +} + +impl IntoIterator for AutoMap { + type IntoIter = IntoIter; + type Item = (K, V); + + fn into_iter(self) -> Self::IntoIter { + match self { + AutoMap::List(list) => IntoIter::List(list.into_iter()), + AutoMap::Map(map) => IntoIter::Map(map.into_iter()), + } + } +} + +impl<'a, K, V, H, const I: usize> IntoIterator for &'a AutoMap { + type IntoIter = Iter<'a, K, V>; + type Item = (&'a K, &'a V); + + fn into_iter(self) -> Self::IntoIter { self.iter() } +} + +pub enum Iter<'a, K, V> { + List(std::slice::Iter<'a, (K, V)>), + Map(std::collections::hash_map::Iter<'a, K, V>), +} + +impl<'a, K, V> Iterator for Iter<'a, K, V> { + type Item = (&'a K, &'a V); + + // This clippy lint doesn't account for lifetimes + #[allow(clippy::map_identity)] + fn next(&mut self) -> Option { + match self { + Iter::List(iter) => iter.next().map(|(k, v)| (k, v)), + Iter::Map(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + Iter::List(iter) => iter.size_hint(), + Iter::Map(iter) => iter.size_hint(), + } + } +} + +impl<'a, K, V> Clone for Iter<'a, K, V> { + fn clone(&self) -> Self { + match self { + Iter::List(iter) => Iter::List(iter.clone()), + Iter::Map(iter) => Iter::Map(iter.clone()), + } + } +} + +pub enum IterMut<'a, K, V> { + List(std::slice::IterMut<'a, (K, V)>), + Map(std::collections::hash_map::IterMut<'a, K, V>), +} + +impl<'a, K, V> Iterator for IterMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn next(&mut self) -> Option { + match self { + IterMut::List(iter) => iter.next().map(|(k, v)| (&*k, v)), + IterMut::Map(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + IterMut::List(iter) => iter.size_hint(), + IterMut::Map(iter) => iter.size_hint(), + } + } +} + +pub enum IntoIter { + List(smallvec::IntoIter<[(K, V); I]>), + Map(std::collections::hash_map::IntoIter), +} + +impl Iterator for IntoIter { + type Item = (K, V); + + fn next(&mut self) -> Option { + match self { + IntoIter::List(iter) => iter.next(), + IntoIter::Map(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + IntoIter::List(iter) => iter.size_hint(), + IntoIter::Map(iter) => iter.size_hint(), + } + } +} + +pub enum Values<'a, K, V> { + List(std::slice::Iter<'a, (K, V)>), + Map(std::collections::hash_map::Values<'a, K, V>), +} + +impl<'a, K, V> Iterator for Values<'a, K, V> { + type Item = &'a V; + + fn next(&mut self) -> Option { + match self { + Values::List(iter) => iter.next().map(|(_, v)| v), + Values::Map(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + Values::List(iter) => iter.size_hint(), + Values::Map(iter) => iter.size_hint(), + } + } +} + +pub enum ValuesMut<'a, K, V> { + List(std::slice::IterMut<'a, (K, V)>), + Map(std::collections::hash_map::ValuesMut<'a, K, V>), +} + +impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { + type Item = &'a mut V; + + fn next(&mut self) -> Option { + match self { + ValuesMut::List(iter) => iter.next().map(|(_, v)| v), + ValuesMut::Map(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + ValuesMut::List(iter) => iter.size_hint(), + ValuesMut::Map(iter) => iter.size_hint(), + } + } +} + +pub enum IntoValues { + List(smallvec::IntoIter<[(K, V); I]>), + Map(std::collections::hash_map::IntoValues), +} + +impl Iterator for IntoValues { + type Item = V; + + fn next(&mut self) -> Option { + match self { + IntoValues::List(iter) => iter.next().map(|(_, v)| v), + IntoValues::Map(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + IntoValues::List(iter) => iter.size_hint(), + IntoValues::Map(iter) => iter.size_hint(), + } + } +} + +pub enum Entry<'a, K, V, H, const I: usize> { + Occupied(OccupiedEntry<'a, K, V, H, I>), + Vacant(VacantEntry<'a, K, V, H, I>), +} + +impl<'a, K:Eq + Hash, V, H:BuildHasher + Default + 'a, const I: usize> Entry<'a, K, V, H, I> { + /// see [HashMap::Entry::or_insert](https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_insert) + pub fn or_insert_with(self, default:impl FnOnce() -> V) -> &'a mut V { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(default()), + } + } +} + +impl<'a, K:Eq + Hash, V:Default, H:BuildHasher + Default + 'a, const I: usize> + Entry<'a, K, V, H, I> +{ + /// see [HashMap::Entry::or_default](https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_default) + pub fn or_default(self) -> &'a mut V { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(Default::default()), + } + } +} + +pub enum OccupiedEntry<'a, K, V, H, const I: usize> { + List { + list:&'a mut SmallVec<[(K, V); I]>, + index:usize, + }, + Map { + this:*mut AutoMap, + entry:std::collections::hash_map::OccupiedEntry<'a, K, V>, + }, +} + +impl<'a, K:Eq + Hash, V, H:BuildHasher, const I: usize> OccupiedEntry<'a, K, V, H, I> { + /// see [HashMap::OccupiedEntry::get_mut](https://doc.rust-lang.org/std/collections/hash_map/enum.OccupiedEntry.html#method.get_mut) + pub fn get_mut(&mut self) -> &mut V { + match self { + OccupiedEntry::List { list, index } => &mut list[*index].1, + OccupiedEntry::Map { entry, .. } => entry.get_mut(), + } + } + + /// see [HashMap::OccupiedEntry::into_mut](https://doc.rust-lang.org/std/collections/hash_map/enum.OccupiedEntry.html#method.into_mut) + pub fn into_mut(self) -> &'a mut V { + match self { + OccupiedEntry::List { list, index } => &mut list[index].1, + OccupiedEntry::Map { entry, .. } => entry.into_mut(), + } + } +} + +impl<'a, K:Eq + Hash, V, H:BuildHasher + Default, const I: usize> OccupiedEntry<'a, K, V, H, I> { + /// see [HashMap::OccupiedEntry::remove](https://doc.rust-lang.org/std/collections/hash_map/enum.OccupiedEntry.html#method.remove) + pub fn remove(self) -> V { + match self { + OccupiedEntry::List { list, index } => list.swap_remove(index).1, + OccupiedEntry::Map { entry, this } => { + let v = entry.remove(); + let this = unsafe { &mut *this }; + if this.len() < MIN_HASH_SIZE { + this.convert_to_list(); + } + v + }, + } + } +} + +pub enum VacantEntry<'a, K, V, H, const I: usize> { + List { this:*mut AutoMap, list:&'a mut SmallVec<[(K, V); I]>, key:K }, + Map(std::collections::hash_map::VacantEntry<'a, K, V>), +} + +impl<'a, K:Eq + Hash, V, H:BuildHasher + Default + 'a, const I: usize> VacantEntry<'a, K, V, H, I> { + /// see [HashMap::VacantEntry::insert](https://doc.rust-lang.org/std/collections/hash_map/enum.VacantEntry.html#method.insert) + pub fn insert(self, value:V) -> &'a mut V { + match self { + VacantEntry::List { this, list, key } => { + if list.len() >= MAX_LIST_SIZE { + let this = unsafe { &mut *this }; + this.convert_to_map().entry(key).or_insert(value) + } else { + list.push((key, value)); + &mut list.last_mut().unwrap().1 + } + }, + VacantEntry::Map(entry) => entry.insert(value), + } + } +} + +pub enum RawEntry<'a, K, V, H, const I: usize> { + Occupied(OccupiedRawEntry<'a, K, V, H, I>), + Vacant(VacantRawEntry<'a, K, V, H, I>), +} + +pub enum OccupiedRawEntry<'a, K, V, H, const I: usize> { + List { + list:&'a mut SmallVec<[(K, V); I]>, + index:usize, + }, + Map { + this:*mut AutoMap, + entry:std::collections::hash_map::RawOccupiedEntryMut<'a, K, V, H>, + }, +} + +impl<'a, K:Eq + Hash, V, H:BuildHasher, const I: usize> OccupiedRawEntry<'a, K, V, H, I> { + /// see [HashMap::RawOccupiedEntryMut::get_mut](https://doc.rust-lang.org/std/collections/hash_map/struct.RawOccupiedEntryMut.html#method.get_mut) + pub fn get_mut(&mut self) -> &mut V { + match self { + OccupiedRawEntry::List { list, index } => &mut list[*index].1, + OccupiedRawEntry::Map { entry, .. } => entry.get_mut(), + } + } + + /// see [HashMap::RawOccupiedEntryMut::into_mut](https://doc.rust-lang.org/std/collections/hash_map/struct.RawOccupiedEntryMut.html#method.into_mut) + pub fn into_mut(self) -> &'a mut V { + match self { + OccupiedRawEntry::List { list, index } => &mut list[index].1, + OccupiedRawEntry::Map { entry, .. } => entry.into_mut(), + } + } +} + +impl<'a, K:Eq + Hash, V, H:BuildHasher + Default, const I: usize> OccupiedRawEntry<'a, K, V, H, I> { + /// see [HashMap::OccupiedEntry::remove](https://doc.rust-lang.org/std/collections/hash_map/enum.OccupiedEntry.html#method.remove) + pub fn remove(self) -> V { + match self { + OccupiedRawEntry::List { list, index } => list.swap_remove(index).1, + OccupiedRawEntry::Map { entry, this } => { + let v = entry.remove(); + let this = unsafe { &mut *this }; + if this.len() < MIN_HASH_SIZE { + this.convert_to_list(); + } + v + }, + } + } +} + +pub enum VacantRawEntry<'a, K, V, H, const I: usize> { + List { this:*mut AutoMap, list:&'a mut SmallVec<[(K, V); I]> }, + Map(std::collections::hash_map::RawVacantEntryMut<'a, K, V, H>), +} + +impl<'a, K:Eq + Hash, V, H:BuildHasher + Default + 'a, const I: usize> + VacantRawEntry<'a, K, V, H, I> +{ + /// see [HashMap::RawVacantEntryMut::insert](https://doc.rust-lang.org/std/collections/hash_map/struct.RawVacantEntryMut.html#method.insert) + pub fn insert(self, key:K, value:V) -> &'a mut V { + match self { + VacantRawEntry::List { this, list } => { + if list.len() >= MAX_LIST_SIZE { + let this = unsafe { &mut *this }; + this.convert_to_map().entry(key).or_insert(value) + } else { + list.push((key, value)); + &mut list.last_mut().unwrap().1 + } + }, + VacantRawEntry::Map(entry) => entry.insert(key, value).1, + } + } +} + +impl Serialize for AutoMap +where + K: Eq + Hash + Serialize, + V: Serialize, + H: BuildHasher, +{ + fn serialize(&self, serializer:S) -> Result + where + S: Serializer, { + match self { + AutoMap::List(list) => { + let mut map = serializer.serialize_map(Some(list.len()))?; + for (k, v) in list { + map.serialize_entry(k, v)?; + } + map.end() + }, + AutoMap::Map(map) => (**map).serialize(serializer), + } + } +} + +impl<'de, K, V, H, const I: usize> Deserialize<'de> for AutoMap +where + K: Eq + Hash + Deserialize<'de>, + V: Deserialize<'de>, + H: BuildHasher + Default, +{ + fn deserialize(deserializer:D) -> Result + where + D: Deserializer<'de>, { + struct AutoMapVisitor { + phantom:PhantomData>, + } + + impl<'de, K, V, H, const I: usize> Visitor<'de> for AutoMapVisitor + where + K: Eq + Hash + Deserialize<'de>, + V: Deserialize<'de>, + H: BuildHasher + Default, + { + type Value = AutoMap; + + fn expecting(&self, formatter:&mut Formatter) -> std::fmt::Result { + formatter.write_str("a map") + } + + fn visit_map(self, mut m:M) -> Result + where + M: MapAccess<'de>, { + if let Some(size) = m.size_hint() { + if size < MAX_LIST_SIZE { + let mut list = SmallVec::with_capacity(size); + while let Some((k, v)) = m.next_entry()? { + list.push((k, v)); + } + return Ok(AutoMap::List(list)); + } else { + let mut map = + Box::new(HashMap::with_capacity_and_hasher(size, H::default())); + while let Some((k, v)) = m.next_entry()? { + map.insert(k, v); + } + return Ok(AutoMap::Map(map)); + } + } + let mut map = AutoMap::with_hasher(); + while let Some((k, v)) = m.next_entry()? { + map.insert(k, v); + } + Ok(map) + } + } + + deserializer.deserialize_map(AutoMapVisitor { phantom:PhantomData::> }) + } +} + +impl PartialEq for AutoMap { + fn eq(&self, other:&Self) -> bool { + match (self, other) { + (AutoMap::Map(a), AutoMap::Map(b)) => a == b, + (AutoMap::List(a), b) => { + if a.len() != b.len() { + return false; + } + a.iter().all(|(k, v)| b.get(k) == Some(v)) + }, + (a, AutoMap::List(b)) => { + if a.len() != b.len() { + return false; + } + b.iter().all(|(k, v)| a.get(k) == Some(v)) + }, + } + } +} + +impl Eq for AutoMap +where + K: Eq, + V: Eq, +{ +} + +impl FromIterator<(K, V)> for AutoMap +where + K: Eq + Hash, + H: BuildHasher + Default, +{ + fn from_iter>(iter:T) -> Self { + let iter = iter.into_iter(); + let (lower, _) = iter.size_hint(); + if lower > MAX_LIST_SIZE { + let map = iter.collect::>(); + // The hint is not enforced + if map.len() < MIN_HASH_SIZE { + return AutoMap::List(map.into_iter().collect()); + } + return AutoMap::Map(Box::new(map)); + } + let mut map = AutoMap::with_hasher(); + for (k, v) in iter { + map.insert(k, v); + } + map + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_auto_map() { + let mut map = AutoMap::new(); + for i in 0..MAX_LIST_SIZE * 2 { + map.insert(i, i); + } + for i in 0..MAX_LIST_SIZE * 2 { + assert_eq!(map.get(&i), Some(&i)); + } + assert_eq!(map.get(&(MAX_LIST_SIZE * 2)), None); + for i in 0..MAX_LIST_SIZE * 2 { + assert_eq!(map.remove(&(MAX_LIST_SIZE * 2)), None); + assert_eq!(map.remove(&i), Some(i)); + } + assert_eq!(map.remove(&(MAX_LIST_SIZE * 2)), None); + } +} diff --git a/crates/turbo-tasks-auto-hash-map/Source/set.rs b/crates/turbo-tasks-auto-hash-map/Source/set.rs new file mode 100644 index 0000000000000..d56ce2a5fc132 --- /dev/null +++ b/crates/turbo-tasks-auto-hash-map/Source/set.rs @@ -0,0 +1,210 @@ +use std::{ + collections::hash_map::RandomState, + fmt::Debug, + hash::{BuildHasher, Hash}, + marker::PhantomData, +}; + +use serde::{Deserialize, Serialize}; + +use crate::AutoMap; + +#[derive(Clone)] +pub struct AutoSet { + map:AutoMap, +} + +impl Default for AutoSet { + fn default() -> Self { Self { map:Default::default() } } +} + +impl Debug for AutoSet { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_set().entries(self.iter()).finish() + } +} + +impl AutoSet { + /// see [HashSet::new](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.new) + pub const fn new() -> Self { Self { map:AutoMap::new() } } + + /// see [HashSet::with_capacity](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.with_capacity) + pub fn with_capacity(capacity:usize) -> Self { Self { map:AutoMap::with_capacity(capacity) } } +} + +impl AutoSet { + /// see [HashSet::with_hasher](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.with_hasher) + pub const fn with_hasher() -> Self { Self { map:AutoMap::with_hasher() } } + + /// see [HashSet::with_capacity_and_hasher](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.with_capacity_and_hasher) + pub fn with_capacity_and_hasher(capacity:usize, hasher:H) -> Self { + Self { map:AutoMap::with_capacity_and_hasher(capacity, hasher) } + } + + /// see [HashSet::clear](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.clear) + pub fn clear(&mut self) { self.map.clear(); } +} + +impl AutoSet { + /// see [HashSet::insert](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.insert) + pub fn insert(&mut self, key:K) -> bool { self.map.insert(key, ()).is_none() } + + /// see [HashSet::remove](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.remove) + pub fn remove(&mut self, key:&K) -> bool { self.map.remove(key).is_some() } + + /// see [HashSet::extend](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.extend) + pub fn extend(&mut self, iter:impl IntoIterator) { + self.map.extend(iter.into_iter().map(|item| (item, ()))) + } + + /// see [HashSet::shrink_to_fit](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.shrink_to_fit) + pub fn shrink_to_fit(&mut self) { self.map.shrink_to_fit(); } + + /// see [HashSet::contains](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.contains) + pub fn contains(&self, key:&K) -> bool { self.map.contains_key(key) } +} + +impl AutoSet { + /// see [HashSet::len](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.len) + pub fn len(&self) -> usize { self.map.len() } + + /// see [HashSet::is_empty](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.is_empty) + pub fn is_empty(&self) -> bool { self.map.is_empty() } + + /// see [HashSet::iter](https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.iter) + pub fn iter(&self) -> Iter<'_, K> { Iter(self.map.iter()) } +} + +impl IntoIterator for AutoSet { + type IntoIter = IntoIter; + type Item = K; + + fn into_iter(self) -> Self::IntoIter { IntoIter(self.map.into_iter()) } +} + +impl<'a, K, H, const I: usize> IntoIterator for &'a AutoSet { + type IntoIter = Iter<'a, K>; + type Item = &'a K; + + fn into_iter(self) -> Self::IntoIter { self.iter() } +} + +pub struct Iter<'a, K>(super::map::Iter<'a, K, ()>); + +impl<'a, K> Iterator for Iter<'a, K> { + type Item = &'a K; + + fn next(&mut self) -> Option { self.0.next().map(|(k, _)| k) } + + fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } +} + +impl<'a, K> Clone for Iter<'a, K> { + fn clone(&self) -> Self { Self(self.0.clone()) } +} + +pub struct IntoIter(super::map::IntoIter); + +impl Iterator for IntoIter { + type Item = K; + + fn next(&mut self) -> Option { self.0.next().map(|(k, _)| k) } + + fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } +} + +impl Serialize for AutoSet +where + K: Serialize, + H: BuildHasher, +{ + fn serialize(&self, serializer:S) -> Result { + serializer.collect_seq(self.iter()) + } +} + +impl<'de, K, H, const I: usize> Deserialize<'de> for AutoSet +where + K: Deserialize<'de> + Hash + Eq, + H: BuildHasher + Default, +{ + fn deserialize>(deserializer:D) -> Result { + struct AutoSetVisitor(PhantomData>); + + impl<'de, K, H, const I: usize> serde::de::Visitor<'de> for AutoSetVisitor + where + K: Deserialize<'de> + Hash + Eq, + H: BuildHasher + Default, + { + type Value = AutoSet; + + fn expecting(&self, formatter:&mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a set") + } + + fn visit_seq>( + self, + mut seq:A, + ) -> Result { + let mut set = if let Some(size) = seq.size_hint() { + AutoSet::with_capacity_and_hasher(size, H::default()) + } else { + AutoSet::with_hasher() + }; + while let Some(item) = seq.next_element()? { + set.insert(item); + } + Ok(set) + } + } + + deserializer.deserialize_seq(AutoSetVisitor(std::marker::PhantomData)) + } +} + +impl PartialEq for AutoSet { + fn eq(&self, other:&Self) -> bool { self.map == other.map } +} + +impl Eq for AutoSet {} + +impl FromIterator for AutoSet +where + K: Hash + Eq, + H: BuildHasher + Default, +{ + fn from_iter>(iter:T) -> Self { + Self { map:AutoMap::from_iter(iter.into_iter().map(|item| (item, ()))) } + } +} + +impl From<[K; N]> for AutoSet +where + K: Hash + Eq, + H: BuildHasher + Default, +{ + fn from(array:[K; N]) -> Self { Self::from_iter(array) } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::MAX_LIST_SIZE; + + #[test] + fn test_auto_set() { + let mut set = AutoSet::new(); + for i in 0..MAX_LIST_SIZE * 2 { + set.insert(i); + } + for i in 0..MAX_LIST_SIZE * 2 { + assert!(set.contains(&i)); + } + assert!(!set.contains(&(MAX_LIST_SIZE * 2))); + for i in 0..MAX_LIST_SIZE * 2 { + assert!(!set.remove(&(MAX_LIST_SIZE * 2))); + assert!(set.remove(&i)); + } + assert!(!set.remove(&(MAX_LIST_SIZE * 2))); + } +} diff --git a/crates/turbo-tasks-build/Source/lib.rs b/crates/turbo-tasks-build/Source/lib.rs new file mode 100644 index 0000000000000..062e8850c0e5c --- /dev/null +++ b/crates/turbo-tasks-build/Source/lib.rs @@ -0,0 +1,518 @@ +use std::{ + collections::{HashMap, HashSet}, + env::{ + current_dir, + {self}, + }, + fmt::{Display, Write}, + fs::read_dir, + path::{MAIN_SEPARATOR as PATH_SEP, PathBuf}, +}; + +use anyhow::{Context, Result}; +use glob::glob; +use syn::{ + Attribute, + Ident, + Item, + ItemEnum, + ItemFn, + ItemImpl, + ItemMacro, + ItemMod, + ItemStruct, + ItemTrait, + TraitItem, + TraitItemMethod, + parse_quote, +}; +use turbo_tasks_macros_shared::{ + GenericTypeInput, + PrimitiveInput, + ValueTraitArguments, + get_impl_function_ident, + get_native_function_ident, + get_path_ident, + get_register_trait_methods_ident, + get_register_value_type_ident, + get_trait_default_impl_function_ident, + get_trait_impl_function_ident, + get_trait_type_ident, + get_type_ident, +}; + +pub fn generate_register() { + println!("cargo:rerun-if-changed=build.rs"); + + let crate_dir = current_dir().unwrap(); + let workspace_dir = env::var_os("CARGO_WORKSPACE_DIR") + .map(PathBuf::from) + .unwrap_or_else(|| crate_dir.clone()); + let crate_name = env::var("CARGO_PKG_NAME").unwrap(); + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + + let src_dir = crate_dir.join("src"); + let examples_dir = crate_dir.join("examples"); + let tests_dir = crate_dir.join("tests"); + let benches_dir = crate_dir.join("benches"); + let cargo_lock_path = workspace_dir.join("Cargo.lock"); + + // TODO: use (ask @sokra) + let _lock = cargo_lock::Lockfile::load(cargo_lock_path).ok(); + + let mut entries = Vec::new(); + + let lib_entry = src_dir.join("lib.rs"); + if lib_entry.exists() { + entries.push(("register.rs".to_string(), lib_entry)); + } else { + let bin_entry = src_dir.join("main.rs"); + if bin_entry.exists() { + entries.push(("register.rs".to_string(), bin_entry)); + } + } + + if examples_dir.exists() { + for item in read_dir(examples_dir).unwrap() { + let item = item.unwrap(); + if item.file_type().unwrap().is_file() { + let name = item.file_name(); + let name = name.to_string_lossy(); + if name.ends_with(".rs") { + entries.push((format!("register_example_{name}"), item.path())); + } + } + } + } + + if tests_dir.exists() { + for item in read_dir(tests_dir).unwrap() { + let item = item.unwrap(); + if item.file_type().unwrap().is_file() { + let name = item.file_name(); + let name = name.to_string_lossy(); + if name.ends_with(".rs") { + entries.push((format!("register_test_{name}"), item.path())); + } + } + } + } + + if benches_dir.exists() { + let bench_mod = benches_dir.join("mod.rs"); + if bench_mod.is_file() { + let name = bench_mod.file_name().unwrap(); + let name = name.to_string_lossy(); + if name.ends_with(".rs") { + entries.push(("register_benches.rs".to_string(), bench_mod)); + } + } + } + + for (filename, entry) in entries { + // TODO hash src dir + let hash = "TODO"; + + let prefix = format!("{crate_name}@{hash}::"); + + let mut register_code = String::new(); + let mut values = HashMap::new(); + + let out_file = out_dir.join(filename); + + let mut queue = vec![("".to_string(), entry)]; + + while let Some((mod_path, file_path)) = queue.pop() { + println!("cargo:rerun-if-changed={}", file_path.to_string_lossy()); + let src = std::fs::read_to_string(&file_path).unwrap(); + + let mut ctx = RegisterContext { + queue:&mut queue, + + file_path:&file_path, + prefix:&prefix, + mod_path:&mod_path, + + register:&mut register_code, + values:&mut values, + }; + + match syn::parse_file(&src) + .with_context(|| format!("failed to parse {}", file_path.display())) + { + Ok(file) => { + for item in file.items { + ctx.process_item(item).unwrap(); + } + }, + Err(err) => println!("{}", err), + } + } + + let mut values_code = String::new(); + for ((mod_path, ident), (global_name, trait_idents)) in values { + writeln!( + values_code, + "crate{}::{}({}, #[allow(unused_variables)] |value| {{", + mod_path, + get_register_value_type_ident(&ident), + global_name + ) + .unwrap(); + for trait_ident in trait_idents { + writeln!( + values_code, + " crate{}::{}(value);", + mod_path, + get_register_trait_methods_ident(&trait_ident, &ident), + ) + .unwrap(); + } + writeln!(values_code, "}});").unwrap(); + } + + let code = format!( + "{{\nstatic ONCE: std::sync::Once = std::sync::Once::new();\nONCE.call_once(|| \ + {{\n{register_code}{values_code}}});\n}}\n" + ); + std::fs::write(out_file, code).unwrap(); + + // println!("cargo:warning={}", out_file.display()); + // for line in code.lines() { + // println!("cargo:warning={line}"); + // } + } +} + +pub fn rerun_if_glob(globs:&str, root:&str) { + let cwd = env::current_dir().unwrap(); + let globs = cwd.join(globs.replace('/', PATH_SEP.to_string().as_str())); + let root = cwd.join(root.replace('/', PATH_SEP.to_string().as_str())); + println!("cargo:rerun-if-changed={}", root.display()); + let mut seen = HashSet::from([root]); + for entry in glob(globs.to_str().unwrap()).unwrap() { + let path = entry.unwrap(); + for ancestor in path.ancestors() { + if seen.insert(ancestor.to_owned()) { + println!("cargo:rerun-if-changed={}", ancestor.display()); + } else { + break; + } + } + } +} + +/// (mod_path, type_ident) +type ValueKey = (String, Ident); +/// (global_name, trait_register_fns) +type ValueEntry = (String, Vec); + +struct RegisterContext<'a> { + queue:&'a mut Vec<(String, PathBuf)>, + + file_path:&'a PathBuf, + mod_path:&'a str, + prefix:&'a str, + + register:&'a mut String, + values:&'a mut HashMap, +} + +impl<'a> RegisterContext<'a> { + fn process_item(&mut self, item:Item) -> Result<()> { + match item { + Item::Enum(enum_item) => self.process_enum(enum_item), + Item::Fn(fn_item) => self.process_fn(fn_item), + Item::Impl(impl_item) => self.process_impl(impl_item), + Item::Mod(mod_item) => self.process_mod(mod_item), + Item::Struct(struct_item) => self.process_struct(struct_item), + Item::Trait(trait_item) => self.process_trait(trait_item), + Item::Macro(macro_item) => self.process_macro(macro_item), + _ => Ok(()), + } + } + + fn process_enum(&mut self, enum_item:ItemEnum) -> Result<()> { + if has_attribute(&enum_item.attrs, "value") { + self.add_value(&enum_item.ident); + self.add_value_debug_impl(&enum_item.ident); + } + Ok(()) + } + + fn process_fn(&mut self, fn_item:ItemFn) -> Result<()> { + if has_attribute(&fn_item.attrs, "function") { + let ident = &fn_item.sig.ident; + let type_ident = get_native_function_ident(ident); + + self.register(type_ident, self.get_global_name(&[ident]))?; + } + Ok(()) + } + + fn process_impl(&mut self, impl_item:ItemImpl) -> Result<()> { + if has_attribute(&impl_item.attrs, "value_impl") { + let struct_ident = get_type_ident(&impl_item.self_ty).unwrap(); + + let trait_ident = + impl_item.trait_.as_ref().map(|(_, trait_path, _)| get_path_ident(trait_path)); + + if let Some(trait_ident) = &trait_ident { + self.add_value_trait(&struct_ident, trait_ident); + } + + for item in impl_item.items { + if let syn::ImplItem::Method(method_item) = item { + // TODO: if method_item.attrs.iter().any(|a| + // is_attribute(a, + // "function")) { + let method_ident = &method_item.sig.ident; + let function_type_ident = if let Some(trait_ident) = &trait_ident { + get_trait_impl_function_ident(&struct_ident, trait_ident, method_ident) + } else { + get_impl_function_ident(&struct_ident, method_ident) + }; + + let global_name = if let Some(trait_ident) = &trait_ident { + self.get_global_name(&[&struct_ident, trait_ident, method_ident]) + } else { + self.get_global_name(&[&struct_ident, method_ident]) + }; + + self.register(function_type_ident, global_name)?; + } + } + } + Ok(()) + } + + fn process_mod(&mut self, mod_item:ItemMod) -> Result<()> { + if mod_item.content.is_none() { + let name = mod_item.ident.to_string(); + let parent_path = self.file_path.parent().unwrap(); + let direct = parent_path.join(format!("{name}.rs")); + if direct.exists() { + self.queue.push((format!("{}::{name}", self.mod_path), direct)); + } else { + let nested = parent_path.join(&name).join("mod.rs"); + if nested.exists() { + self.queue.push((format!("{}::{name}", self.mod_path), nested)); + } + } + } + Ok(()) + } + + fn process_struct(&mut self, struct_item:ItemStruct) -> Result<()> { + if has_attribute(&struct_item.attrs, "value") { + self.add_value(&struct_item.ident); + self.add_value_debug_impl(&struct_item.ident); + } + Ok(()) + } + + fn process_trait(&mut self, trait_item:ItemTrait) -> Result<()> { + if let Some(attr) = trait_item.attrs.iter().find(|a| is_attribute(a, "value_trait")) { + let trait_ident = &trait_item.ident; + + for item in &trait_item.items { + if let TraitItem::Method(TraitItemMethod { default: Some(_), sig, .. }) = item { + let method_ident = &sig.ident; + let function_type_ident = + get_trait_default_impl_function_ident(trait_ident, method_ident); + + self.register( + function_type_ident, + self.get_global_name(&[trait_ident, method_ident]), + )?; + } + } + + let trait_type_ident = get_trait_type_ident(trait_ident); + self.register(trait_type_ident, self.get_global_name(&[trait_ident]))?; + + let trait_args:ValueTraitArguments = parse_attr_args(attr)?.unwrap_or_default(); + if trait_args.debug { + self.register_debug_impl( + &get_type_ident(&parse_quote! { + Box + }) + .unwrap(), + )?; + } + } + Ok(()) + } + + fn process_macro(&mut self, macro_item:ItemMacro) -> Result<()> { + if macro_item.mac.path.is_ident("__turbo_tasks_internal_primitive") { + let input = macro_item.mac.tokens; + let input = syn::parse2::(input).unwrap(); + + let ty = input.ty; + let Some(ident) = get_type_ident(&ty) else { + return Ok(()); + }; + + self.add_value(&ident); + self.add_value_debug_impl(&ident); + self.add_value_default_impl(&ident); + } else if macro_item.mac.path.is_ident("__turbo_tasks_internal_generic_type") { + let input = macro_item.mac.tokens; + let input = syn::parse2::(input).unwrap(); + + let ty = input.ty; + let Some(ident) = get_type_ident(&ty) else { + return Ok(()); + }; + + // Generic types must implement `ValueDebug` manually, as there's currently no + // easy way to automate the process. + self.add_value(&ident); + } + + Ok(()) + } +} + +impl<'a> RegisterContext<'a> { + fn get_global_name(&self, parts:&[&Ident]) -> String { + format!( + "r##\"{}{}::{}\"##", + self.prefix, + self.mod_path, + parts.iter().map(ToString::to_string).collect::>().join("::") + ) + } + + fn add_value(&mut self, ident:&Ident) { + let key:ValueKey = (self.mod_path.to_owned(), ident.clone()); + let value:ValueEntry = (self.get_global_name(&[ident]), Vec::new()); + + assert!(self.values.insert(key, value).is_none(), "{} is declared more than once", ident); + } + + fn add_value_debug_impl(&mut self, ident:&Ident) { + // register default debug impl generated by proc macro + self.register_debug_impl(ident).unwrap(); + self.add_value_trait( + ident, + &get_type_ident(&parse_quote! { + turbo_tasks::debug::ValueDebug + }) + .unwrap(), + ); + } + + fn add_value_default_impl(&mut self, ident:&Ident) { + // register default ValueDefault impl generated by proc macro + self.register_default_impl(ident).unwrap(); + self.add_value_trait( + ident, + &get_type_ident(&parse_quote! { + turbo_tasks::ValueDefault + }) + .unwrap(), + ); + } + + fn add_value_trait(&mut self, ident:&Ident, trait_ident:&Ident) { + let key:ValueKey = (self.mod_path.to_owned(), ident.clone()); + + let entry = self.values.get_mut(&key); + if entry.is_none() { + panic!( + "failed to add value trait {} to {} in {}. Did you try to implement a trait on a \ + Vc instead of its value?", + trait_ident, + ident, + self.file_path.display() + ); + } + entry.unwrap().1.push(trait_ident.clone()); + } + + fn register(&mut self, type_ident:impl Display, global_name:impl Display) -> std::fmt::Result { + writeln!( + self.register, + "crate{}::{}.register({});", + self.mod_path, type_ident, global_name + ) + } + + /// Declares a derive of the given trait and its methods. + fn register_impl( + &mut self, + ident:&Ident, + trait_ident:&Ident, + fn_names:&[&'static str], + ) -> std::fmt::Result { + for fn_name in fn_names { + let fn_ident = Ident::new(fn_name, ident.span()); + + let (impl_fn_ident, global_name) = ( + get_trait_impl_function_ident(ident, trait_ident, &fn_ident), + self.get_global_name(&[ident, trait_ident, &fn_ident]), + ); + + self.register(impl_fn_ident, global_name)?; + } + + Ok(()) + } + + /// Declares the default derive of the `ValueDebug` trait. + fn register_debug_impl(&mut self, ident:&Ident) -> std::fmt::Result { + self.register_impl( + ident, + &get_type_ident(&parse_quote! { + turbo_tasks::debug::ValueDebug + }) + .unwrap(), + &["dbg", "dbg_depth"], + ) + } + + /// Declares the default derive of the `ValueDefault` trait. + fn register_default_impl(&mut self, ident:&Ident) -> std::fmt::Result { + self.register_impl( + ident, + &get_type_ident(&parse_quote! { + turbo_tasks::ValueDefault + }) + .unwrap(), + &["value_default"], + ) + } +} + +fn has_attribute(attrs:&[Attribute], name:&str) -> bool { + attrs.iter().any(|a| is_attribute(a, name)) +} + +fn is_attribute(attr:&Attribute, name:&str) -> bool { + let path = &attr.path; + if path.leading_colon.is_some() { + return false; + } + let mut iter = path.segments.iter(); + match iter.next() { + Some(seg) if seg.arguments.is_empty() && seg.ident == "turbo_tasks" => { + match iter.next() { + Some(seg) if seg.arguments.is_empty() && seg.ident == name => iter.next().is_none(), + _ => false, + } + }, + _ => false, + } +} + +fn parse_attr_args(attr:&Attribute) -> syn::Result> +where + T: syn::parse::Parse, { + if attr.tokens.is_empty() { + Ok(None) + } else { + Ok(Some(attr.parse_args_with(T::parse)?)) + } +} diff --git a/crates/turbo-tasks-bytes/Source/bytes.rs b/crates/turbo-tasks-bytes/Source/bytes.rs new file mode 100644 index 0000000000000..42742ab992b4d --- /dev/null +++ b/crates/turbo-tasks-bytes/Source/bytes.rs @@ -0,0 +1,109 @@ +use std::{ + ops::Deref, + str::{Utf8Error, from_utf8}, +}; + +use anyhow::Result; +use bytes::Bytes as CBytes; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +/// Bytes is a thin wrapper around [bytes::Bytes], implementing easy +/// conversion to/from, ser/de support, and Vc containers. +#[derive(Clone, Debug, Default)] +#[turbo_tasks::value(transparent, serialization = "custom")] +pub struct Bytes(#[turbo_tasks(trace_ignore)] CBytes); + +impl Bytes { + pub fn to_str(&self) -> Result<&'_ str, Utf8Error> { from_utf8(&self.0) } +} + +impl Serialize for Bytes { + fn serialize(&self, serializer:S) -> Result { + serde_bytes::Bytes::new(&self.0).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Bytes { + fn deserialize>(deserializer:D) -> Result { + let bytes = serde_bytes::ByteBuf::deserialize(deserializer)?; + Ok(Bytes(bytes.into_vec().into())) + } +} + +impl Deref for Bytes { + type Target = CBytes; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +/// Types that implement From for Bytes {} +/// Unfortunately, we cannot just use the more generic `Into` without +/// running afoul of the `From for X` base case, causing conflicting impls. +pub trait IntoBytes: Into {} +impl IntoBytes for &'static [u8] {} +impl IntoBytes for &'static str {} +impl IntoBytes for Vec {} +impl IntoBytes for Box<[u8]> {} +impl IntoBytes for String {} + +impl From for Bytes { + fn from(value:T) -> Self { Bytes(value.into()) } +} + +impl From for Bytes { + fn from(value:CBytes) -> Self { Bytes(value) } +} + +impl From for CBytes { + fn from(value:Bytes) -> Self { value.0 } +} + +#[cfg(test)] +mod tests { + use bytes::Bytes as CBytes; + use serde_test::{Token, assert_tokens}; + + use super::Bytes; + impl PartialEq<&str> for Bytes { + fn eq(&self, other:&&str) -> bool { self.0 == other } + } + + #[test] + fn into_bytes() { + let s = "foo".to_string(); + assert_eq!(Bytes::from(b"foo" as &'static [u8]), "foo"); + assert_eq!(Bytes::from("foo"), "foo"); + assert_eq!(Bytes::from(s.as_bytes().to_vec()), "foo"); + assert_eq!(Bytes::from(s.as_bytes().to_vec().into_boxed_slice()), "foo"); + assert_eq!(Bytes::from(s), "foo"); + } + + #[test] + fn serde() { + let s = Bytes::from("test"); + assert_tokens(&s, &[Token::Bytes(b"test")]) + } + + #[test] + fn from_into() { + let b = Bytes::from("foo"); + let cb = CBytes::from("foo"); + assert_eq!(Bytes::from(cb), "foo"); + assert_eq!(CBytes::from(b), "foo"); + } + + #[test] + fn deref() { + let b = Bytes::from("foo"); + assert_eq!(*b, CBytes::from("foo")); + } + + #[test] + fn to_str() { + let cb = Bytes::from("foo"); + assert_eq!(cb.to_str(), Ok("foo")); + + let b = Bytes::from("💩".as_bytes()[0..3].to_vec()); + assert!(b.to_str().is_err()); + } +} diff --git a/crates/turbo-tasks-bytes/Source/lib.rs b/crates/turbo-tasks-bytes/Source/lib.rs new file mode 100644 index 0000000000000..69995a0b43092 --- /dev/null +++ b/crates/turbo-tasks-bytes/Source/lib.rs @@ -0,0 +1,14 @@ +#![feature(arbitrary_self_types)] + +pub mod bytes; +pub mod stream; + +pub use crate::{ + bytes::Bytes, + stream::{Stream, StreamRead}, +}; + +pub fn register() { + turbo_tasks::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbo-tasks-bytes/Source/stream.rs b/crates/turbo-tasks-bytes/Source/stream.rs new file mode 100644 index 0000000000000..092406badb671 --- /dev/null +++ b/crates/turbo-tasks-bytes/Source/stream.rs @@ -0,0 +1,195 @@ +use std::{ + fmt, + pin::Pin, + sync::{Arc, Mutex}, + task::{Context as TaskContext, Poll}, +}; + +use anyhow::Result; +use futures::{Stream as StreamTrait, StreamExt, TryStreamExt}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +/// Streams allow for streaming values from source to sink. +/// +/// A Stream implements both a reader (which implements the Stream trait), and a +/// writer (which can be sent to another thread). As new values are written, any +/// pending readers will be woken up to receive the new value. +#[derive(Clone, Debug)] +pub struct Stream { + inner:Arc>>, +} + +/// The StreamState actually holds the data of a Stream. +struct StreamState { + source:Option + Send>>>, + pulled:Vec, +} + +impl Stream { + /// Constructs a new Stream, and immediately closes it with only the passed + /// values. + pub fn new_closed(pulled:Vec) -> Self { + Self { inner:Arc::new(Mutex::new(StreamState { source:None, pulled })) } + } + + /// Creates a new Stream, which will lazily pull from the source stream. + pub fn new_open(pulled:Vec, source:Box + Send + 'static>) -> Self { + Self { + inner:Arc::new(Mutex::new(StreamState { source:Some(Box::into_pin(source)), pulled })), + } + } + + /// Returns a [StreamTrait] implementation to poll values out of our Stream. + pub fn read(&self) -> StreamRead { StreamRead { source:self.clone(), index:0 } } + + pub async fn into_single(&self) -> SingleValue { + let mut stream = self.read(); + let Some(first) = stream.next().await else { + return SingleValue::None; + }; + + if stream.next().await.is_some() { + return SingleValue::Multiple; + } + + SingleValue::Single(first) + } +} + +impl Stream> { + /// Converts a TryStream into a single value when possible. + pub async fn try_into_single(&self) -> Result, E> { + let mut stream = self.read(); + let Some(first) = stream.try_next().await? else { + return Ok(SingleValue::None); + }; + + if stream.try_next().await?.is_some() { + return Ok(SingleValue::Multiple); + } + + Ok(SingleValue::Single(first)) + } +} + +pub enum SingleValue { + /// The Stream did not hold a value. + None, + + /// The Stream held multiple values. + Multiple, + + /// The held only a single value. + Single(T), +} + +impl fmt::Debug for SingleValue { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SingleValue::None => f.debug_struct("SingleValue::None").finish(), + SingleValue::Multiple => f.debug_struct("SingleValue::Multiple").finish(), + SingleValue::Single(v) => f.debug_tuple("SingleValue::Single").field(v).finish(), + } + } +} + +impl + Send + Unpin + 'static> From for Stream { + fn from(source:S) -> Self { Self::new_open(vec![], Box::new(source)) } +} + +impl Default for Stream { + fn default() -> Self { Self::new_closed(vec![]) } +} + +impl PartialEq for Stream { + // A Stream is equal if it's the same internal pointer, or both streams are + // closed with equivalent values. + fn eq(&self, other:&Self) -> bool { + Arc::ptr_eq(&self.inner, &other.inner) || { + let left = self.inner.lock().unwrap(); + let right = other.inner.lock().unwrap(); + + match (&*left, &*right) { + ( + StreamState { pulled: a, source: None }, + StreamState { pulled: b, source: None }, + ) => a == b, + _ => false, + } + } + } +} +impl Eq for Stream {} + +impl Serialize for Stream { + fn serialize(&self, serializer:S) -> Result { + use serde::ser::Error; + let lock = self.inner.lock().map_err(Error::custom)?; + match &*lock { + StreamState { pulled, source: None } => pulled.serialize(serializer), + _ => Err(Error::custom("cannot serialize open stream")), + } + } +} + +impl<'de, T:Clone + Send + Deserialize<'de>> Deserialize<'de> for Stream { + fn deserialize>(deserializer:D) -> Result { + let data = >::deserialize(deserializer)?; + Ok(Stream::new_closed(data)) + } +} + +impl fmt::Debug for StreamState { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("StreamState").field("pulled", &self.pulled).finish() + } +} + +/// Implements [StreamTrait] over our Stream. +#[derive(Debug)] +pub struct StreamRead { + index:usize, + source:Stream, +} + +impl StreamTrait for StreamRead { + type Item = T; + + fn poll_next(self: Pin<&mut Self>, cx:&mut TaskContext<'_>) -> Poll> { + let this = self.get_mut(); + let index = this.index; + let mut inner = this.source.inner.lock().unwrap(); + + if let Some(v) = inner.pulled.get(index) { + // If the current reader can be satisfied by a value we've already pulled, then + // just do that. + this.index += 1; + return Poll::Ready(Some(v.clone())); + }; + + let Some(source) = &mut inner.source else { + // If the source has been closed, there's nothing left to pull. + return Poll::Ready(None); + }; + + match source.poll_next_unpin(cx) { + // If the source stream is ready to give us a new value, we can immediately store that + // and return it to the caller. Any other readers will be able to read the value from + // the already-pulled data. + Poll::Ready(Some(v)) => { + this.index += 1; + inner.pulled.push(v.clone()); + Poll::Ready(Some(v)) + }, + // If the source stream is finished, then we can transition to the closed state + // to drop the source stream. + Poll::Ready(None) => { + inner.source.take(); + Poll::Ready(None) + }, + // Else, we need to wait for the source stream to give us a new value. The + // source stream will be responsible for waking the TaskContext. + Poll::Pending => Poll::Pending, + } + } +} diff --git a/crates/turbo-tasks-bytes/build.rs b/crates/turbo-tasks-bytes/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbo-tasks-bytes/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbo-tasks-env/Source/command_line.rs b/crates/turbo-tasks-env/Source/command_line.rs new file mode 100644 index 0000000000000..58f9a77496965 --- /dev/null +++ b/crates/turbo-tasks-env/Source/command_line.rs @@ -0,0 +1,26 @@ +use indexmap::IndexMap; +use turbo_tasks::{RcStr, Vc}; + +use crate::{EnvMap, GLOBAL_ENV_LOCK, ProcessEnv, sorted_env_vars}; + +/// Load the environment variables defined via command line. +#[turbo_tasks::value] +pub struct CommandLineProcessEnv; + +#[turbo_tasks::value_impl] +impl CommandLineProcessEnv { + #[turbo_tasks::function] + pub fn new() -> Vc { CommandLineProcessEnv.cell() } +} + +/// Clones the current env vars into a IndexMap. +fn env_snapshot() -> IndexMap { + let _lock = GLOBAL_ENV_LOCK.lock().unwrap(); + sorted_env_vars() +} + +#[turbo_tasks::value_impl] +impl ProcessEnv for CommandLineProcessEnv { + #[turbo_tasks::function] + fn read_all(&self) -> Vc { Vc::cell(env_snapshot()) } +} diff --git a/crates/turbo-tasks-env/Source/custom.rs b/crates/turbo-tasks-env/Source/custom.rs new file mode 100644 index 0000000000000..f324905fdc171 --- /dev/null +++ b/crates/turbo-tasks-env/Source/custom.rs @@ -0,0 +1,42 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; + +use crate::{EnvMap, ProcessEnv, case_insensitive_read}; + +/// Allows providing any custom env values that you'd like, deferring the prior +/// envs if a key is not overridden. +#[turbo_tasks::value] +pub struct CustomProcessEnv { + prior:Vc>, + custom:Vc, +} + +#[turbo_tasks::value_impl] +impl CustomProcessEnv { + #[turbo_tasks::function] + pub fn new(prior:Vc>, custom:Vc) -> Vc { + CustomProcessEnv { prior, custom }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ProcessEnv for CustomProcessEnv { + #[turbo_tasks::function] + async fn read_all(&self) -> Result> { + let prior = self.prior.read_all().await?; + let custom = self.custom.await?; + + let mut extended = prior.clone_value(); + extended.extend(custom.clone_value()); + Ok(Vc::cell(extended)) + } + + #[turbo_tasks::function] + async fn read(&self, name:RcStr) -> Result>> { + let custom = case_insensitive_read(self.custom, name.clone()); + match &*custom.await? { + Some(_) => Ok(custom), + None => Ok(self.prior.read(name)), + } + } +} diff --git a/crates/turbo-tasks-env/Source/dotenv.rs b/crates/turbo-tasks-env/Source/dotenv.rs new file mode 100644 index 0000000000000..9403086fa5663 --- /dev/null +++ b/crates/turbo-tasks-env/Source/dotenv.rs @@ -0,0 +1,99 @@ +use std::{env, sync::MutexGuard}; + +use anyhow::{Context, Result, anyhow}; +use indexmap::IndexMap; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbo_tasks_fs::{FileContent, FileSystemPath}; + +use crate::{EnvMap, GLOBAL_ENV_LOCK, ProcessEnv, sorted_env_vars}; + +/// Load the environment variables defined via a dotenv file, with an +/// optional prior state that we can lookup already defined variables +/// from. +#[turbo_tasks::value] +pub struct DotenvProcessEnv { + prior:Option>>, + path:Vc, +} + +#[turbo_tasks::value_impl] +impl DotenvProcessEnv { + #[turbo_tasks::function] + pub fn new(prior:Option>>, path:Vc) -> Vc { + DotenvProcessEnv { prior, path }.cell() + } + + #[turbo_tasks::function] + pub async fn read_prior(self: Vc) -> Result> { + let this = self.await?; + match this.prior { + None => Ok(EnvMap::empty()), + Some(p) => Ok(p.read_all()), + } + } + + #[turbo_tasks::function] + pub async fn read_all_with_prior(self: Vc, prior:Vc) -> Result> { + let this = self.await?; + let prior = prior.await?; + + let file = this.path.read().await?; + if let FileContent::Content(f) = &*file { + let res; + let vars; + { + let lock = GLOBAL_ENV_LOCK.lock().unwrap(); + + // Unfortunately, dotenvy only looks up variable references from the global env. + // So we must mutate while we process. Afterwards, we can restore the initial + // state. + let initial = sorted_env_vars(); + + restore_env(&initial, &prior, &lock); + + // from_read will load parse and evalute the Read, and set variables + // into the global env. If a later dotenv defines an already defined + // var, it'll be ignored. + res = dotenv::from_read(f.read()).map(|e| e.load()); + + vars = sorted_env_vars(); + restore_env(&vars, &initial, &lock); + } + + if let Err(e) = res { + return Err(e).context(anyhow!( + "unable to read {} for env vars", + this.path.to_string().await? + )); + } + + Ok(Vc::cell(vars)) + } else { + Ok(Vc::cell(prior.clone_value())) + } + } +} + +#[turbo_tasks::value_impl] +impl ProcessEnv for DotenvProcessEnv { + #[turbo_tasks::function] + async fn read_all(self: Vc) -> Result> { + let prior = self.read_prior(); + Ok(self.read_all_with_prior(prior)) + } +} + +/// Restores the global env variables to mirror `to`. +fn restore_env(from:&IndexMap, to:&IndexMap, _lock:&MutexGuard<()>) { + for key in from.keys() { + if !to.contains_key(key) { + env::remove_var(key); + } + } + for (key, value) in to { + match from.get(key) { + Some(v) if v == value => {}, + _ => env::set_var(key, value), + } + } +} diff --git a/crates/turbo-tasks-env/Source/filter.rs b/crates/turbo-tasks-env/Source/filter.rs new file mode 100644 index 0000000000000..b9cce8f9847af --- /dev/null +++ b/crates/turbo-tasks-env/Source/filter.rs @@ -0,0 +1,54 @@ +use anyhow::Result; +use indexmap::IndexMap; +use turbo_tasks::{RcStr, Vc}; + +use crate::{EnvMap, ProcessEnv}; + +/// Filters env variables by some prefix. Casing of the env vars is ignored for +/// filtering. +#[turbo_tasks::value] +pub struct FilterProcessEnv { + prior:Vc>, + filters:Vec, +} + +#[turbo_tasks::value_impl] +impl FilterProcessEnv { + #[turbo_tasks::function] + pub fn new(prior:Vc>, filters:Vec) -> Vc { + FilterProcessEnv { + prior, + filters:filters.into_iter().map(|f| f.to_uppercase().into()).collect(), + } + .cell() + } +} + +#[turbo_tasks::value_impl] +impl ProcessEnv for FilterProcessEnv { + #[turbo_tasks::function] + async fn read_all(&self) -> Result> { + let prior = self.prior.read_all().await?; + let mut filtered = IndexMap::new(); + for (key, value) in &*prior { + let uppercase = key.to_uppercase(); + for filter in &self.filters { + if uppercase.starts_with(&**filter) { + filtered.insert(key.clone(), value.clone()); + break; + } + } + } + Ok(Vc::cell(filtered)) + } + + #[turbo_tasks::function] + fn read(&self, name:RcStr) -> Vc> { + for filter in &self.filters { + if name.to_uppercase().starts_with(&**filter) { + return self.prior.read(name); + } + } + Vc::cell(None) + } +} diff --git a/crates/turbo-tasks-env/Source/lib.rs b/crates/turbo-tasks-env/Source/lib.rs new file mode 100644 index 0000000000000..da48234497c75 --- /dev/null +++ b/crates/turbo-tasks-env/Source/lib.rs @@ -0,0 +1,85 @@ +#![feature(arbitrary_self_types)] + +mod command_line; +mod custom; +mod dotenv; +mod filter; + +use std::{env, sync::Mutex}; + +use anyhow::Result; +use indexmap::IndexMap; +use turbo_tasks::{RcStr, Vc}; + +pub use self::{ + command_line::CommandLineProcessEnv, + custom::CustomProcessEnv, + dotenv::DotenvProcessEnv, + filter::FilterProcessEnv, +}; + +#[turbo_tasks::value(transparent)] +pub struct EnvMap(#[turbo_tasks(trace_ignore)] IndexMap); + +#[turbo_tasks::value_impl] +impl EnvMap { + #[turbo_tasks::function] + pub fn empty() -> Vc { EnvMap(IndexMap::new()).cell() } +} + +#[turbo_tasks::value_impl] +impl ProcessEnv for EnvMap { + #[turbo_tasks::function] + async fn read_all(self: Vc) -> Result> { Ok(self) } + + #[turbo_tasks::function] + async fn read(self: Vc, name:RcStr) -> Vc> { + case_insensitive_read(self, name) + } +} + +#[turbo_tasks::value_trait] +pub trait ProcessEnv { + // TODO SECURITY: From security perspective it's not good that we read *all* env + // vars into the cache. This might store secrects into the persistent cache + // which we want to avoid. + // Instead we should use only `read_prefix` to read all env vars with a specific + // prefix. + /// Reads all env variables into a Map + fn read_all(self: Vc) -> Vc; + + /// Reads a single env variable. Ignores casing. + fn read(self: Vc, name:RcStr) -> Vc> { + case_insensitive_read(self.read_all(), name) + } +} + +pub fn sorted_env_vars() -> IndexMap { + let mut vars = env::vars().map(|(k, v)| (k.into(), v.into())).collect::>(); + vars.sort_keys(); + vars +} + +#[turbo_tasks::function] +pub async fn case_insensitive_read(map:Vc, name:RcStr) -> Result>> { + Ok(Vc::cell( + to_uppercase_map(map).await?.get(&RcStr::from(name.to_uppercase())).cloned(), + )) +} + +#[turbo_tasks::function] +async fn to_uppercase_map(map:Vc) -> Result> { + let map = &*map.await?; + let mut new = IndexMap::with_capacity(map.len()); + for (k, v) in map { + new.insert(k.to_uppercase().into(), v.clone()); + } + Ok(Vc::cell(new)) +} + +pub static GLOBAL_ENV_LOCK:Mutex<()> = Mutex::new(()); + +pub fn register() { + turbo_tasks::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbo-tasks-env/build.rs b/crates/turbo-tasks-env/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbo-tasks-env/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbo-tasks-fetch/Source/lib.rs b/crates/turbo-tasks-fetch/Source/lib.rs new file mode 100644 index 0000000000000..1e87ba10b82c7 --- /dev/null +++ b/crates/turbo-tasks-fetch/Source/lib.rs @@ -0,0 +1,201 @@ +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueSeverity, IssueStage, OptionStyledString, StyledString}; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} + +#[turbo_tasks::value(transparent)] +pub struct FetchResult(Result, Vc>); + +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub struct HttpResponse { + pub status:u16, + pub body:Vc, +} + +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub struct HttpResponseBody(pub Vec); + +#[turbo_tasks::value_impl] +impl HttpResponseBody { + #[turbo_tasks::function] + pub async fn to_string(self: Vc) -> Result> { + let this = &*self.await?; + Ok(Vc::cell(std::str::from_utf8(&this.0)?.into())) + } +} + +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub enum ProxyConfig { + Http(String), + Https(String), +} + +#[turbo_tasks::value(transparent)] +pub struct OptionProxyConfig(Option); + +#[turbo_tasks::function] +pub async fn fetch( + url:Vc, + user_agent:Vc>, + proxy_option:Vc, +) -> Result> { + let url = &*url.await?; + let user_agent = &*user_agent.await?; + let proxy_option = &*proxy_option.await?; + + let client_builder = reqwest::Client::builder(); + let client_builder = match proxy_option { + Some(ProxyConfig::Http(proxy)) => client_builder.proxy(reqwest::Proxy::http(proxy)?), + Some(ProxyConfig::Https(proxy)) => client_builder.proxy(reqwest::Proxy::https(proxy)?), + _ => client_builder, + }; + + let client = client_builder.build()?; + + let mut builder = client.get(url.as_str()); + if let Some(user_agent) = user_agent { + builder = builder.header("User-Agent", user_agent.as_str()); + } + + let response = builder.send().await.and_then(|r| r.error_for_status()); + match response { + Ok(response) => { + let status = response.status().as_u16(); + let body = response.bytes().await?.to_vec(); + + Ok(Vc::cell(Ok(HttpResponse { + status, + body:HttpResponseBody::cell(HttpResponseBody(body)), + } + .cell()))) + }, + Err(err) => Ok(Vc::cell(Err(FetchError::from_reqwest_error(&err, url).cell()))), + } +} + +#[derive(Debug)] +#[turbo_tasks::value(shared)] +pub enum FetchErrorKind { + Connect, + Timeout, + Status(u16), + Other, +} + +#[turbo_tasks::value(shared)] +pub struct FetchError { + pub url:Vc, + pub kind:Vc, + pub detail:Vc, +} + +impl FetchError { + fn from_reqwest_error(error:&reqwest::Error, url:&str) -> FetchError { + let kind = if error.is_connect() { + FetchErrorKind::Connect + } else if error.is_timeout() { + FetchErrorKind::Timeout + } else if let Some(status) = error.status() { + FetchErrorKind::Status(status.as_u16()) + } else { + FetchErrorKind::Other + }; + + FetchError { + detail:StyledString::Text(error.to_string().into()).cell(), + url:Vc::cell(url.into()), + kind:kind.into(), + } + } +} + +#[turbo_tasks::value_impl] +impl FetchError { + #[turbo_tasks::function] + pub async fn to_issue( + self: Vc, + severity:Vc, + issue_context:Vc, + ) -> Result> { + let this = &*self.await?; + Ok( + FetchIssue { + issue_context, + severity, + url:this.url, + kind:this.kind, + detail:this.detail, + } + .into(), + ) + } +} + +#[turbo_tasks::value(shared)] +pub struct FetchIssue { + pub issue_context:Vc, + pub severity:Vc, + pub url:Vc, + pub kind:Vc, + pub detail:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for FetchIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.issue_context } + + #[turbo_tasks::function] + fn severity(&self) -> Vc { self.severity } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Error while requesting resource".into()).cell() + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Load.into() } + + #[turbo_tasks::function] + async fn description(&self) -> Result> { + let url = &*self.url.await?; + let kind = &*self.kind.await?; + + Ok(Vc::cell(Some( + StyledString::Text(match kind { + FetchErrorKind::Connect => { + format!( + "There was an issue establishing a connection while requesting {}.", + url + ) + .into() + }, + FetchErrorKind::Status(status) => { + format!("Received response with status {} when requesting {}", status, url) + .into() + }, + FetchErrorKind::Timeout => { + format!("Connection timed out when requesting {}", url).into() + }, + FetchErrorKind::Other => format!("There was an issue requesting {}", url).into(), + }) + .cell(), + ))) + } + + #[turbo_tasks::function] + fn detail(&self) -> Vc { Vc::cell(Some(self.detail)) } +} diff --git a/crates/turbo-tasks-fetch/build.rs b/crates/turbo-tasks-fetch/build.rs new file mode 100644 index 0000000000000..bd92278a4e872 --- /dev/null +++ b/crates/turbo-tasks-fetch/build.rs @@ -0,0 +1,19 @@ +use turbo_tasks_build::generate_register; + +#[cfg(any(feature = "native-tls", feature = "rustls-tls"))] +fn check_tls_config() { + // do nothing +} +#[cfg(not(any(feature = "native-tls", feature = "rustls-tls")))] +fn check_tls_config() { + panic!("You must enable one of the TLS features: native-tls or rustls-tls"); +} + +fn main() { + generate_register(); + + // Check if tls feature for reqwest is properly configured. + // Technically reqwest falls back to non-tls http request if none of the tls + // features are enabled, But we won't allow it. + check_tls_config(); +} diff --git a/crates/turbo-tasks-fs/Source/attach.rs b/crates/turbo-tasks-fs/Source/attach.rs new file mode 100644 index 0000000000000..550bc0c7139ae --- /dev/null +++ b/crates/turbo-tasks-fs/Source/attach.rs @@ -0,0 +1,184 @@ +use anyhow::{Result, bail}; +use auto_hash_map::AutoMap; +use turbo_tasks::{Completion, RcStr, ValueToString, Vc}; + +use crate::{ + DirectoryContent, + DirectoryEntry, + FileContent, + FileMeta, + FileSystem, + FileSystemPath, + LinkContent, +}; + +/// A wrapper [FileSystem] which attaches a child [FileSystem] as a +/// "subdirectory" in the given root [FileSystem]. +/// +/// Caveat: The `child_path` itself is not visible as a directory entry. +#[turbo_tasks::value] +pub struct AttachedFileSystem { + root_fs:Vc>, + // we turn this into a string because creating a FileSystemPath requires the filesystem which + // we are creating (circular reference) + child_path:RcStr, + child_fs:Vc>, +} + +#[turbo_tasks::value_impl] +impl AttachedFileSystem { + /// Create a new [AttachedFileSystem] which will have the `child_fs` as + /// an invisible subdirectory of the `child_path` + #[turbo_tasks::function] + pub async fn new( + child_path:Vc, + child_fs:Vc>, + ) -> Result> { + let child_path = child_path.await?; + + Ok(AttachedFileSystem { + root_fs:child_path.fs, + child_path:child_path.path.clone(), + child_fs, + } + .cell()) + } + + /// Converts the given [Vc] to a path in this [FileSystem]. + /// + /// The given path has to be inside of the root [FileSystem], the child + /// [FileSystem] or this [AttachedFileSystem]. + #[turbo_tasks::function] + pub async fn convert_path( + self: Vc, + contained_path_vc:Vc, + ) -> Result> { + let contained_path = contained_path_vc.await?; + let self_fs:Vc> = Vc::upcast(self); + let this = self.await?; + + match contained_path.fs { + // already on this filesystem + fs if fs == self_fs => Ok(contained_path_vc), + // in the root filesystem, just need to rebase on this filesystem + fs if fs == this.root_fs => { + Ok(self.root().resolve().await?.join(contained_path.path.clone())) + }, + // in the child filesystem, so we expand to the full path by appending to child_path + fs if fs == this.child_fs => { + Ok(self.child_path().resolve().await?.join(contained_path.path.clone())) + }, + _ => { + bail!( + "path {} not part of self, the root fs or the child fs", + contained_path_vc.to_string().await? + ) + }, + } + } + + /// Constructs a [Vc] of the attachment point referencing + /// this [AttachedFileSystem] + #[turbo_tasks::function] + async fn child_path(self: Vc) -> Result> { + Ok(self.root().resolve().await?.join(self.await?.child_path.clone())) + } + + /// Resolves the local path of the root or child filesystem from a path + /// on the [AttachedFileSystem] + #[turbo_tasks::function] + pub async fn get_inner_fs_path( + self: Vc, + path:Vc, + ) -> Result> { + let this = self.await?; + let path = path.await?; + let self_fs:Vc> = Vc::upcast(self); + + if path.fs != self_fs { + let self_fs_str = self_fs.to_string().await?; + let path_fs_str = path.fs.to_string().await?; + bail!("path fs does not match (expected {}, got {})", self_fs_str, path_fs_str) + } + + let child_path = self.child_path().await?; + Ok(if let Some(inner_path) = child_path.get_path_to(&path) { + this.child_fs.root().resolve().await?.join(inner_path.into()) + } else { + this.root_fs.root().resolve().await?.join(path.path.clone()) + }) + } +} + +#[turbo_tasks::value_impl] +impl FileSystem for AttachedFileSystem { + #[turbo_tasks::function] + fn read(self: Vc, path:Vc) -> Vc { + self.get_inner_fs_path(path).read() + } + + #[turbo_tasks::function] + fn read_link(self: Vc, path:Vc) -> Vc { + self.get_inner_fs_path(path).read_link() + } + + #[turbo_tasks::function] + async fn read_dir(self: Vc, path:Vc) -> Result> { + let dir_content = self.get_inner_fs_path(path).read_dir().await?; + let entries = match &*dir_content { + DirectoryContent::Entries(e) => e, + DirectoryContent::NotFound => return Ok(DirectoryContent::not_found()), + }; + + let mut converted_entries = AutoMap::with_capacity(entries.len()); + for (name, entry) in entries { + use DirectoryEntry::*; + + let entry = match *entry { + File(path) => File(self.convert_path(path)), + Directory(path) => Directory(self.convert_path(path)), + Symlink(path) => Symlink(self.convert_path(path)), + Other(path) => Other(self.convert_path(path)), + Error => Error, + }; + + converted_entries.insert(name.clone(), entry); + } + + Ok(DirectoryContent::new(converted_entries)) + } + + #[turbo_tasks::function] + fn track(self: Vc, path:Vc) -> Vc { + self.get_inner_fs_path(path).track() + } + + #[turbo_tasks::function] + fn write(self: Vc, path:Vc, content:Vc) -> Vc { + self.get_inner_fs_path(path).write(content) + } + + #[turbo_tasks::function] + fn write_link( + self: Vc, + path:Vc, + target:Vc, + ) -> Vc { + self.get_inner_fs_path(path).write_link(target) + } + + #[turbo_tasks::function] + fn metadata(self: Vc, path:Vc) -> Vc { + self.get_inner_fs_path(path).metadata() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for AttachedFileSystem { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + let root_fs_str = self.root_fs.to_string().await?; + let child_fs_str = self.child_fs.to_string().await?; + Ok(Vc::cell(format!("{}-with-{}", root_fs_str, child_fs_str).into())) + } +} diff --git a/crates/turbo-tasks-fs/Source/embed/dir.rs b/crates/turbo-tasks-fs/Source/embed/dir.rs new file mode 100644 index 0000000000000..0446e45e095b1 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/embed/dir.rs @@ -0,0 +1,80 @@ +pub use ::include_dir::{ + include_dir, + {self}, +}; +use anyhow::Result; +use turbo_tasks::{RcStr, TransientInstance, Vc}; + +use crate::{DiskFileSystem, FileSystem, embed::EmbeddedFileSystem}; + +#[turbo_tasks::function] +pub async fn directory_from_relative_path( + name:RcStr, + path:RcStr, +) -> Result>> { + let disk_fs = DiskFileSystem::new(name, path, vec![]); + disk_fs.await?.start_watching()?; + + Ok(Vc::upcast(disk_fs)) +} + +#[turbo_tasks::function] +pub async fn directory_from_include_dir( + name:RcStr, + dir:TransientInstance<&'static include_dir::Dir<'static>>, +) -> Result>> { + Ok(Vc::upcast(EmbeddedFileSystem::new(name, dir))) +} + +/// Returns an embedded [Vc>] for the given path. +/// +/// This will embed a directory's content into the binary and +/// create an [Vc]. +/// +/// If you enable the `dynamic_embed_contents` feature, calling +/// the macro will return a [Vc]. +/// +/// This enables dynamic linking (and hot reloading) of embedded files/dirs. +/// A binary built with `dynamic_embed_contents` enabled is **is not portable**, +/// only the directory path will be embedded into the binary. +#[macro_export] +macro_rules! embed_directory { + ($name:tt, $path:tt) => {{ // make sure the path contains `$CARGO_MANIFEST_DIR` + assert!($path.contains("$CARGO_MANIFEST_DIR")); + // make sure `CARGO_MANIFEST_DIR` is the only env variable in the path + assert!(!$path.replace("$CARGO_MANIFEST_DIR", "").contains('$')); + + turbo_tasks_fs::embed_directory_internal!($name, $path) + }}; +} + +#[cfg(feature = "dynamic_embed_contents")] +#[macro_export] +#[doc(hidden)] +macro_rules! embed_directory_internal { + ($name:tt, $path:tt) => {{ + // make sure the types the `include_dir!` proc macro refers to are in scope + use turbo_tasks_fs::embed::include_dir; + + let path = $path.replace("$CARGO_MANIFEST_DIR", env!("CARGO_MANIFEST_DIR")); + + turbo_tasks_fs::embed::directory_from_relative_path($name.to_string(), path) + }}; +} + +#[cfg(not(feature = "dynamic_embed_contents"))] +#[macro_export] +#[doc(hidden)] +macro_rules! embed_directory_internal { + ($name:tt, $path:tt) => {{ + // make sure the types the `include_dir!` proc macro refers to are in scope + use turbo_tasks_fs::embed::include_dir; + + static dir:include_dir::Dir<'static> = turbo_tasks_fs::embed::include_dir!($path); + + turbo_tasks_fs::embed::directory_from_include_dir( + $name.into(), + turbo_tasks::TransientInstance::new(&dir), + ) + }}; +} diff --git a/crates/turbo-tasks-fs/Source/embed/file.rs b/crates/turbo-tasks-fs/Source/embed/file.rs new file mode 100644 index 0000000000000..5e09f2415e415 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/embed/file.rs @@ -0,0 +1,60 @@ +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use dunce::canonicalize; +use turbo_tasks::{RcStr, Vc}; + +use crate::{DiskFileSystem, File, FileContent, FileSystem}; + +#[turbo_tasks::function] +pub async fn content_from_relative_path(package_path:RcStr, path:RcStr) -> Result> { + let package_path = PathBuf::from(package_path); + let resolved_path = package_path.join(path); + let resolved_path = + canonicalize(&resolved_path).context("failed to canonicalize embedded file path")?; + let root_path = resolved_path.parent().unwrap(); + let path = resolved_path.file_name().unwrap().to_str().unwrap(); + + let disk_fs = DiskFileSystem::new( + root_path.to_string_lossy().into(), + root_path.to_string_lossy().into(), + vec![], + ); + disk_fs.await?.start_watching()?; + + let fs_path = disk_fs.root().join(path.into()); + Ok(fs_path.read()) +} + +#[turbo_tasks::function] +pub async fn content_from_str(string:RcStr) -> Result> { + Ok(File::from(string).into()) +} + +/// Loads a file's content from disk and invalidates on change (debug builds). +/// +/// In production, this will embed a file's content into the binary directly. +#[cfg(feature = "dynamic_embed_contents")] +#[macro_export] +macro_rules! embed_file { + ($path:expr) => {{ + // check that the file exists at compile time + let _ = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/", $path)); + + turbo_tasks_fs::embed::content_from_relative_path( + env!("CARGO_MANIFEST_DIR").to_string(), + $path.to_string(), + ) + }}; +} + +/// Embeds a file's content into the binary (production). +#[cfg(not(feature = "dynamic_embed_contents"))] +#[macro_export] +macro_rules! embed_file { + ($path:expr) => { + turbo_tasks_fs::embed::content_from_str( + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/", $path)).into(), + ) + }; +} diff --git a/crates/turbo-tasks-fs/Source/embed/fs.rs b/crates/turbo-tasks-fs/Source/embed/fs.rs new file mode 100644 index 0000000000000..3a641c96066c0 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/embed/fs.rs @@ -0,0 +1,112 @@ +use anyhow::{Result, bail}; +use include_dir::{Dir, DirEntry}; +use turbo_tasks::{Completion, RcStr, TransientInstance, ValueToString, Vc}; + +use crate::{ + DirectoryContent, + DirectoryEntry, + File, + FileContent, + FileMeta, + FileSystem, + FileSystemPath, + LinkContent, +}; + +#[turbo_tasks::value(serialization = "none")] +pub struct EmbeddedFileSystem { + name:RcStr, + #[turbo_tasks(trace_ignore)] + dir:TransientInstance<&'static Dir<'static>>, +} + +#[turbo_tasks::value_impl] +impl EmbeddedFileSystem { + #[turbo_tasks::function] + pub(super) fn new( + name:RcStr, + dir:TransientInstance<&'static Dir<'static>>, + ) -> Vc { + EmbeddedFileSystem { name, dir }.cell() + } +} + +#[turbo_tasks::value_impl] +impl FileSystem for EmbeddedFileSystem { + #[turbo_tasks::function] + async fn read(&self, path:Vc) -> Result> { + let file = match self.dir.get_file(&path.await?.path) { + Some(file) => file, + None => return Ok(FileContent::NotFound.cell()), + }; + + Ok(File::from(file.contents()).into()) + } + + #[turbo_tasks::function] + fn read_link(&self, _path:Vc) -> Vc { + LinkContent::NotFound.cell() + } + + #[turbo_tasks::function] + async fn read_dir(&self, path:Vc) -> Result> { + let path_str = &path.await?.path; + let dir = match (path_str.as_str(), self.dir.get_dir(path_str)) { + ("", _) => *self.dir, + (_, Some(dir)) => dir, + (_, None) => return Ok(DirectoryContent::NotFound.cell()), + }; + + let entries = dir + .entries() + .iter() + .map(|e| { + let entry_name:RcStr = + e.path().file_name().unwrap_or_default().to_string_lossy().into(); + let entry_path = path.join(entry_name.clone()); + + ( + entry_name, + match e { + DirEntry::Dir(_) => DirectoryEntry::Directory(entry_path), + DirEntry::File(_) => DirectoryEntry::File(entry_path), + }, + ) + }) + .collect(); + + Ok(DirectoryContent::new(entries)) + } + + #[turbo_tasks::function] + fn track(&self, _path:Vc) -> Vc { Completion::immutable() } + + #[turbo_tasks::function] + fn write(&self, _path:Vc, _content:Vc) -> Result> { + bail!("Writing is not possible to the embedded filesystem") + } + + #[turbo_tasks::function] + fn write_link( + &self, + _path:Vc, + _target:Vc, + ) -> Result> { + bail!("Writing is not possible to the embedded filesystem") + } + + #[turbo_tasks::function] + async fn metadata(&self, path:Vc) -> Result> { + if self.dir.get_entry(&path.await?.path).is_none() { + bail!("path not found, can't read metadata"); + } + + Ok(FileMeta::default().cell()) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EmbeddedFileSystem { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { Vc::cell(self.name.clone()) } +} diff --git a/crates/turbo-tasks-fs/Source/embed/mod.rs b/crates/turbo-tasks-fs/Source/embed/mod.rs new file mode 100644 index 0000000000000..d388918c78b2f --- /dev/null +++ b/crates/turbo-tasks-fs/Source/embed/mod.rs @@ -0,0 +1,5 @@ +pub(crate) mod dir; +pub(crate) mod file; +pub(crate) mod fs; + +pub use self::{dir::*, file::*, fs::*}; diff --git a/crates/turbo-tasks-fs/Source/glob.rs b/crates/turbo-tasks-fs/Source/glob.rs new file mode 100644 index 0000000000000..c29d3b9f54b90 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/glob.rs @@ -0,0 +1,506 @@ +use std::mem::take; + +use anyhow::{Context, Result, anyhow, bail}; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{RcStr, TryJoinIterExt, Vc, trace::TraceRawVcs}; +use unicode_segmentation::GraphemeCursor; + +#[derive(PartialEq, Eq, Debug, Clone, TraceRawVcs, Serialize, Deserialize)] +enum GlobPart { + /// `/**/`: Matches any path of directories + AnyDirectories, + + /// `*`: Matches any filename (no path separator) + AnyFile, + + /// `?`: Matches a single filename character (no path separator) + AnyFileChar, + + /// `/`: Matches the path separator + PathSeparator, + + /// `[abc]`: Matches any char of the list + FileChar(Vec), + + /// `abc`: Matches literal filename + File(String), + + /// `{a,b,c}`: Matches any of the globs in the list + Alternatives(Vec), +} + +// Examples: +// - file.js = File(file.js) +// - *.js = AnyFile, File(.js) +// - file*.js = File(file), AnyFile, File(.js) +// - dir/file.js = File(dir), PathSeparator, File(file.js) +// - **/*.js = AnyDirectories, PathSeparator, AnyFile, File(.js) +// - {a/**,*}/file = Alternatives([File(a), PathSeparator, AnyDirectories], +// [AnyFile]), PathSeparator, File(file) + +// Note: a/**/b does match a/b, so we need some special logic about path +// separators + +#[turbo_tasks::value] +#[derive(Debug, Clone)] +pub struct Glob { + expression:Vec, +} + +impl Glob { + pub fn execute(&self, path:&str) -> bool { + let match_partial = path.ends_with('/'); + self.iter_matches(path, true, match_partial) + .any(|result| matches!(result, ("", _))) + } + + fn iter_matches<'a>( + &'a self, + path:&'a str, + previous_part_is_path_separator_equivalent:bool, + match_partial:bool, + ) -> GlobMatchesIterator<'a> { + GlobMatchesIterator { + current:path, + glob:self, + match_partial, + is_path_separator_equivalent:previous_part_is_path_separator_equivalent, + stack:Vec::new(), + index:0, + } + } + + pub fn parse(input:&str) -> Result { + let mut current = input; + let mut expression = Vec::new(); + + while !current.is_empty() { + let (part, remainder) = GlobPart::parse(current, false) + .with_context(|| anyhow!("Failed to parse glob {input}"))?; + expression.push(part); + current = remainder; + } + + Ok(Glob { expression }) + } +} + +struct GlobMatchesIterator<'a> { + current:&'a str, + glob:&'a Glob, + match_partial:bool, + is_path_separator_equivalent:bool, + stack:Vec>, + index:usize, +} + +impl<'a> Iterator for GlobMatchesIterator<'a> { + type Item = (&'a str, bool); + + fn next(&mut self) -> Option { + loop { + if let Some(part) = self.glob.expression.get(self.index) { + let iter = if let Some(iter) = self.stack.get_mut(self.index) { + iter + } else { + let iter = part.iter_matches( + self.current, + self.is_path_separator_equivalent, + self.match_partial, + ); + self.stack.push(iter); + self.stack.last_mut().unwrap() + }; + if let Some((new_path, new_is_path_separator_equivalent)) = iter.next() { + self.current = new_path; + self.is_path_separator_equivalent = new_is_path_separator_equivalent; + + self.index += 1; + + if self.match_partial && self.current.is_empty() { + return Some(("", self.is_path_separator_equivalent)); + } + } else { + if self.index == 0 { + // failed to match + return None; + } + // backtrack + self.stack.pop(); + self.index -= 1; + } + } else { + // end of expression, matched successfully + + // backtrack for the next iteration + self.index -= 1; + + return Some((self.current, self.is_path_separator_equivalent)); + } + } + } +} + +impl GlobPart { + /// Iterates over all possible matches of this part with the provided path. + /// The least greedy match is returned first. This is usually used for + /// backtracking. The string slice returned is the remaining part or the + /// path. The boolean flag returned specifies if the matched part should + /// be considered as path-separator equivalent. + fn iter_matches<'a>( + &'a self, + path:&'a str, + previous_part_is_path_separator_equivalent:bool, + match_partial:bool, + ) -> GlobPartMatchesIterator<'a> { + GlobPartMatchesIterator { + path, + part:self, + match_partial, + previous_part_is_path_separator_equivalent, + cursor:GraphemeCursor::new(0, path.len(), true), + index:0, + glob_iterator:None, + } + } + + fn parse(input:&str, inside_of_braces:bool) -> Result<(GlobPart, &str)> { + debug_assert!(!input.is_empty()); + let two_chars = { + let mut chars = input.chars(); + (chars.next().unwrap(), chars.next()) + }; + match two_chars { + ('/', _) => Ok((GlobPart::PathSeparator, &input[1..])), + ('*', Some('*')) => Ok((GlobPart::AnyDirectories, &input[2..])), + ('*', _) => Ok((GlobPart::AnyFile, &input[1..])), + ('?', _) => Ok((GlobPart::AnyFileChar, &input[1..])), + ('[', Some('[')) => todo!("glob char classes are not implemented yet"), + ('[', _) => todo!("glob char sequences are not implemented yet"), + ('{', Some(_)) => { + let mut current = &input[1..]; + let mut alternatives = Vec::new(); + let mut expression = Vec::new(); + + loop { + let (part, remainder) = GlobPart::parse(current, true)?; + expression.push(part); + current = remainder; + match current.chars().next() { + Some(',') => { + alternatives.push(Glob { expression:take(&mut expression) }); + current = ¤t[1..]; + }, + Some('}') => { + alternatives.push(Glob { expression:take(&mut expression) }); + current = ¤t[1..]; + break; + }, + None => bail!("Unterminated glob braces"), + _ => { + // next part of the glob + }, + } + } + + Ok((GlobPart::Alternatives(alternatives), current)) + }, + ('{', None) => { + bail!("Unterminated glob braces") + }, + _ => { + let mut is_escaped = false; + let mut literal = String::new(); + + let mut cursor = GraphemeCursor::new(0, input.len(), true); + + let mut start = cursor.cur_cursor(); + let mut end_cursor = + cursor.next_boundary(input, 0).map_err(|e| anyhow!("{:?}", e))?; + + while let Some(end) = end_cursor { + let c = &input[start..end]; + if is_escaped { + is_escaped = false; + } else if c == "\\" { + is_escaped = true; + } else if c == "/" + || c == "*" || c == "?" + || c == "[" || c == "{" + || (inside_of_braces && (c == "," || c == "}")) + { + break; + } + literal.push_str(c); + + start = cursor.cur_cursor(); + end_cursor = + cursor.next_boundary(input, end).map_err(|e| anyhow!("{:?}", e))?; + } + + Ok((GlobPart::File(literal), &input[start..])) + }, + } + } +} + +struct GlobPartMatchesIterator<'a> { + path:&'a str, + part:&'a GlobPart, + match_partial:bool, + previous_part_is_path_separator_equivalent:bool, + cursor:GraphemeCursor, + index:usize, + glob_iterator:Option>>, +} + +impl<'a> Iterator for GlobPartMatchesIterator<'a> { + type Item = (&'a str, bool); + + fn next(&mut self) -> Option { + match self.part { + GlobPart::AnyDirectories => { + if self.cursor.cur_cursor() == 0 { + let Ok(Some(_)) = self.cursor.next_boundary(self.path, 0) else { + return None; + }; + return Some((self.path, true)); + } + + if self.cursor.cur_cursor() == self.path.len() { + return None; + } + + loop { + let start = self.cursor.cur_cursor(); + // next_boundary does not set cursor offset to the end of the string + // if there is no next boundary - manually set cursor to the end + let end = match self.cursor.next_boundary(self.path, 0) { + Ok(end) => { + if let Some(end) = end { + end + } else { + self.cursor.set_cursor(self.path.len()); + self.cursor.cur_cursor() + } + }, + _ => return None, + }; + + if &self.path[start..end] == "/" { + return Some((&self.path[end..], true)); + } else if start == end { + return Some((&self.path[start..], false)); + } + } + }, + GlobPart::AnyFile => { + let Ok(Some(c)) = self.cursor.next_boundary(self.path, 0) else { + return None; + }; + + let idx = self.path[0..c].len(); + + // TODO verify if `*` does match zero chars? + if let Some(slice) = self.path.get(0..c) { + if slice.ends_with('/') { + None + } else { + Some(( + &self.path[c..], + self.previous_part_is_path_separator_equivalent && idx == 1, + )) + } + } else { + None + } + }, + GlobPart::AnyFileChar => todo!(), + GlobPart::PathSeparator => { + if self.cursor.cur_cursor() == 0 { + let Ok(Some(b)) = self.cursor.next_boundary(self.path, 0) else { + return None; + }; + if self.path.starts_with('/') { + Some((&self.path[b..], true)) + } else if self.previous_part_is_path_separator_equivalent { + Some((self.path, true)) + } else { + None + } + } else { + None + } + }, + GlobPart::FileChar(chars) => { + let start = self.cursor.cur_cursor(); + let Ok(Some(end)) = self.cursor.next_boundary(self.path, 0) else { + return None; + }; + let mut chars_in_path = self.path[start..end].chars(); + let c = chars_in_path.next()?; + if chars_in_path.next().is_some() { + return None; + } + chars.contains(&c).then(|| (&self.path[end..], false)) + }, + GlobPart::File(name) => { + if self.cursor.cur_cursor() == 0 && self.path.starts_with(name) { + let Ok(Some(_)) = self.cursor.next_boundary(self.path, 0) else { + return None; + }; + Some((&self.path[name.len()..], false)) + } else { + None + } + }, + GlobPart::Alternatives(alternatives) => { + loop { + if let Some(glob_iterator) = &mut self.glob_iterator { + if let Some((path, is_path_separator_equivalent)) = glob_iterator.next() { + return Some((path, is_path_separator_equivalent)); + } else { + self.index += 1; + self.glob_iterator = None; + } + } else if let Some(alternative) = alternatives.get(self.index) { + self.glob_iterator = Some(Box::new(alternative.iter_matches( + self.path, + self.previous_part_is_path_separator_equivalent, + self.match_partial, + ))); + } else { + return None; + } + } + }, + } + } +} + +impl TryFrom<&str> for Glob { + type Error = anyhow::Error; + + fn try_from(value:&str) -> Result { Glob::parse(value) } +} + +#[turbo_tasks::value_impl] +impl Glob { + #[turbo_tasks::function] + pub fn new(glob:RcStr) -> Result> { Ok(Self::cell(Glob::try_from(glob.as_str())?)) } + + #[turbo_tasks::function] + pub async fn alternatives(globs:Vec>) -> Result> { + if globs.len() == 1 { + return Ok(globs.into_iter().next().unwrap()); + } + Ok(Self::cell(Glob { + expression:vec![GlobPart::Alternatives( + globs + .into_iter() + .try_join() + .await? + .into_iter() + .map(|g| g.clone_value()) + .collect(), + )], + })) + } +} + +#[cfg(test)] +mod tests { + use rstest::*; + + use super::Glob; + + #[rstest] + #[case::file("file.js", "file.js")] + #[case::dir_and_file("../public/äöüšÄří.png", "../public/äöüšÄří.png")] + #[case::dir_and_file("dir/file.js", "dir/file.js")] + #[case::dir_and_file_partial("dir/file.js", "dir/")] + #[case::file_braces("file.{ts,js}", "file.js")] + #[case::dir_and_file_braces("dir/file.{ts,js}", "dir/file.js")] + #[case::dir_and_file_dir_braces("{dir,other}/file.{ts,js}", "dir/file.js")] + #[case::star("*.js", "file.js")] + #[case::dir_star("dir/*.js", "dir/file.js")] + #[case::dir_star_partial("dir/*.js", "dir/")] + #[case::globstar("**/*.js", "file.js")] + #[case::globstar("**/*.js", "dir/file.js")] + #[case::globstar("**/*.js", "dir/sub/file.js")] + #[case::globstar("**/**/*.js", "file.js")] + #[case::globstar("**/**/*.js", "dir/sub/file.js")] + #[case::globstar_partial("**/**/*.js", "dir/sub/")] + #[case::globstar_partial("**/**/*.js", "dir/")] + #[case::globstar_in_dir("dir/**/sub/file.js", "dir/sub/file.js")] + #[case::globstar_in_dir("dir/**/sub/file.js", "dir/a/sub/file.js")] + #[case::globstar_in_dir("dir/**/sub/file.js", "dir/a/b/sub/file.js")] + #[case::globstar_in_dir( + "**/next/dist/**/*.shared-runtime.js", + "next/dist/shared/lib/app-router-context.shared-runtime.js" + )] + #[case::globstar_in_dir_partial("dir/**/sub/file.js", "dir/a/b/sub/")] + #[case::globstar_in_dir_partial("dir/**/sub/file.js", "dir/a/b/")] + #[case::globstar_in_dir_partial("dir/**/sub/file.js", "dir/a/")] + #[case::globstar_in_dir_partial("dir/**/sub/file.js", "dir/")] + #[case::star_dir("**/*/next/dist/server/next.js", "node_modules/next/dist/server/next.js")] + #[case::node_modules_root("**/node_modules/**", "node_modules/next/dist/server/next.js")] + #[case::node_modules_root_package( + "**/node_modules/next/**", + "node_modules/next/dist/server/next.js" + )] + #[case::node_modules_nested( + "**/node_modules/**", + "apps/some-app/node_modules/regenerate-unicode-properties/Script_Extensions/Osage.js" + )] + #[case::node_modules_nested_package( + "**/node_modules/regenerate-unicode-properties/**", + "apps/some-app/node_modules/regenerate-unicode-properties/Script_Extensions/Osage.js" + )] + #[case::node_modules_pnpm( + "**/node_modules/**", + "node_modules/.pnpm/regenerate-unicode-properties@9.0.0/node_modules/\ + regenerate-unicode-properties/Script_Extensions/Osage.js" + )] + #[case::node_modules_pnpm_package( + "**/node_modules/{regenerate,regenerate-unicode-properties}/**", + "node_modules/.pnpm/regenerate-unicode-properties@9.0.0/node_modules/\ + regenerate-unicode-properties/Script_Extensions/Osage.js" + )] + #[case::node_modules_pnpm_prefixed_package( + "**/node_modules/{@blockfrost/blockfrost-js,@highlight-run/node,@libsql/client,@jpg-store/\ + lucid-cardano,@mikro-orm/core,@mikro-orm/knex,@prisma/client,@sentry/nextjs,@sentry/node,\ + @swc/core,argon2,autoprefixer,bcrypt,better-sqlite3,canvas,cpu-features,cypress,eslint,\ + express,next-seo,node-pty,payload,pg,playwright,postcss,prettier,prisma,puppeteer,rimraf,\ + sharp,shiki,sqlite3,tailwindcss,ts-node,typescript,vscode-oniguruma,webpack,websocket,@\ + aws-sdk/client-dynamodb,@aws-sdk/lib-dynamodb}/**", + "node_modules/.pnpm/@aws-sdk+lib-dynamodb@3.445.0_@aws-sdk+client-dynamodb@3.445.0/\ + node_modules/@aws-sdk/lib-dynamodb/dist-es/index.js" + )] + #[case::alternatives_nested1("{a,b/c,d/e/{f,g/h}}", "a")] + #[case::alternatives_nested2("{a,b/c,d/e/{f,g/h}}", "b/c")] + #[case::alternatives_nested3("{a,b/c,d/e/{f,g/h}}", "d/e/f")] + #[case::alternatives_nested4("{a,b/c,d/e/{f,g/h}}", "d/e/g/h")] + // #[case::alternatives_chars("[abc]", "b")] + fn glob_match(#[case] glob:&str, #[case] path:&str) { + let glob = Glob::parse(glob).unwrap(); + + println!("{glob:?} {path}"); + + assert!(glob.execute(path)); + } + + #[rstest] + #[case::early_end("*.raw", "hello.raw.js")] + #[case::early_end( + "**/next/dist/esm/*.shared-runtime.js", + "next/dist/shared/lib/app-router-context.shared-runtime.js" + )] + fn glob_not_matching(#[case] glob:&str, #[case] path:&str) { + let glob = Glob::parse(glob).unwrap(); + + println!("{glob:?} {path}"); + + assert!(!glob.execute(path)); + } +} diff --git a/crates/turbo-tasks-fs/Source/invalidation.rs b/crates/turbo-tasks-fs/Source/invalidation.rs new file mode 100644 index 0000000000000..7674fe1b30e4f --- /dev/null +++ b/crates/turbo-tasks-fs/Source/invalidation.rs @@ -0,0 +1,118 @@ +use std::fmt::{Display, Formatter}; + +use indexmap::IndexSet; +use turbo_tasks::{InvalidationReason, InvalidationReasonKind, RcStr, util::StaticOrArc}; + +/// Invalidation was caused by a file change detected by the file watcher +#[derive(PartialEq, Eq, Hash)] +pub struct WatchChange { + pub path:String, +} + +impl InvalidationReason for WatchChange { + fn kind(&self) -> Option> { + Some(StaticOrArc::Static(&WATCH_CHANGE_KIND)) + } +} + +impl Display for WatchChange { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { write!(f, "{} changed", self.path) } +} + +/// Invalidation kind for [WatchChange] +#[derive(PartialEq, Eq, Hash)] +struct WatchChangeKind; + +static WATCH_CHANGE_KIND:WatchChangeKind = WatchChangeKind; + +impl InvalidationReasonKind for WatchChangeKind { + fn fmt( + &self, + reasons:&IndexSet>, + f:&mut Formatter<'_>, + ) -> std::fmt::Result { + write!( + f, + "{} files changed ({}, ...)", + reasons.len(), + reasons[0].as_any().downcast_ref::().unwrap().path + ) + } +} + +/// Invalidation was caused by a directory starting to watch from which was read +/// before. +#[derive(PartialEq, Eq, Hash)] +pub struct WatchStart { + pub name:RcStr, +} + +impl InvalidationReason for WatchStart { + fn kind(&self) -> Option> { + Some(StaticOrArc::Static(&WATCH_START_KIND)) + } +} + +impl Display for WatchStart { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{} started watching", self.name) + } +} + +/// Invalidation kind for [WatchStart] +#[derive(PartialEq, Eq, Hash)] +struct WatchStartKind; + +static WATCH_START_KIND:WatchStartKind = WatchStartKind; + +impl InvalidationReasonKind for WatchStartKind { + fn fmt( + &self, + reasons:&IndexSet>, + f:&mut Formatter<'_>, + ) -> std::fmt::Result { + write!( + f, + "{} directories started watching (e. g. {})", + reasons.len(), + reasons[0].as_any().downcast_ref::().unwrap().name + ) + } +} + +/// Invalidation was caused by a write operation on the filesystem +#[derive(PartialEq, Eq, Hash)] +pub struct Write { + pub path:String, +} + +impl InvalidationReason for Write { + fn kind(&self) -> Option> { + Some(StaticOrArc::Static(&WRITE_KIND)) + } +} + +impl Display for Write { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { write!(f, "{} written", self.path) } +} + +/// Invalidation kind for [Write] +#[derive(PartialEq, Eq, Hash)] +struct WriteKind; + +static WRITE_KIND:WriteKind = WriteKind; + +impl InvalidationReasonKind for WriteKind { + fn fmt( + &self, + reasons:&IndexSet>, + f:&mut Formatter<'_>, + ) -> std::fmt::Result { + write!( + f, + "{} files written ({}, ...)", + reasons.len(), + reasons[0].as_any().downcast_ref::().unwrap().path + ) + } +} diff --git a/crates/turbo-tasks-fs/Source/invalidator_map.rs b/crates/turbo-tasks-fs/Source/invalidator_map.rs new file mode 100644 index 0000000000000..14f0ffbdbf3e2 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/invalidator_map.rs @@ -0,0 +1,78 @@ +use std::{ + collections::{HashMap, HashSet}, + sync::{LockResult, Mutex, MutexGuard}, +}; + +use concurrent_queue::ConcurrentQueue; +use serde::{Deserialize, Serialize, de::Visitor}; +use turbo_tasks::Invalidator; + +pub struct InvalidatorMap { + queue:ConcurrentQueue<(String, Invalidator)>, + map:Mutex>>, +} + +impl InvalidatorMap { + pub fn new() -> Self { Self { queue:ConcurrentQueue::unbounded(), map:Default::default() } } + + pub fn lock(&self) -> LockResult>>> { + let mut guard = self.map.lock()?; + while let Ok((key, value)) = self.queue.pop() { + guard.entry(key).or_default().insert(value); + } + Ok(guard) + } + + #[allow(unused_must_use)] + pub fn insert(&self, key:String, invalidator:Invalidator) { + self.queue.push((key, invalidator)); + } +} + +impl Serialize for InvalidatorMap { + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + serializer.serialize_newtype_struct("InvalidatorMap", &*self.lock().unwrap()) + } +} + +impl<'de> Deserialize<'de> for InvalidatorMap { + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + struct V; + + impl<'de> Visitor<'de> for V { + type Value = InvalidatorMap; + + fn expecting(&self, f:&mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "an InvalidatorMap") + } + + fn visit_newtype_struct(self, deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + Ok(InvalidatorMap { + queue:ConcurrentQueue::unbounded(), + map:Mutex::new(Deserialize::deserialize(deserializer)?), + }) + } + } + + deserializer.deserialize_newtype_struct("InvalidatorMap", V) + } +} + +impl Drop for InvalidatorMap { + fn drop(&mut self) { + while let Ok((_, value)) = self.queue.pop() { + value.invalidate(); + } + for (_, invalidators) in self.map.lock().unwrap().drain() { + for invalidator in invalidators { + invalidator.invalidate(); + } + } + } +} diff --git a/crates/turbo-tasks-fs/Source/json.rs b/crates/turbo-tasks-fs/Source/json.rs new file mode 100644 index 0000000000000..a033e5ee8238e --- /dev/null +++ b/crates/turbo-tasks-fs/Source/json.rs @@ -0,0 +1,118 @@ +use std::{ + borrow::Cow, + fmt::{Display, Formatter, Write}, +}; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use turbo_tasks::trace::TraceRawVcs; + +use crate::{rope::Rope, source_context::get_source_context}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, TraceRawVcs)] +pub struct UnparseableJson { + #[turbo_tasks(trace_ignore)] + pub message:Cow<'static, str>, + pub path:Option, + /// The start line and column of the error. + /// Line and column is 0-based. + pub start_location:Option<(usize, usize)>, + /// The end line and column of the error. + /// Line and column is 0-based. + pub end_location:Option<(usize, usize)>, +} + +/// Converts a byte position to a 0-based line and column. +fn byte_to_location(pos:usize, text:&str) -> (usize, usize) { + let text = &text[..pos]; + let mut lines = text.lines().rev(); + let last = lines.next().unwrap_or(""); + let column = last.len(); + let line = lines.count(); + (line, column) +} + +impl UnparseableJson { + pub fn from_jsonc_error(e:jsonc_parser::errors::ParseError, text:&str) -> Self { + Self { + message:e.message.clone().into(), + path:None, + start_location:Some(byte_to_location(e.range.start, text)), + end_location:Some(byte_to_location(e.range.end, text)), + } + } + + pub fn from_serde_path_to_error(e:serde_path_to_error::Error) -> Self { + let inner = e.inner(); + Self { + message:inner.to_string().into(), + path:Some(e.path().to_string()), + start_location:Some((inner.line().saturating_sub(1), inner.column().saturating_sub(1))), + end_location:None, + } + } + + pub fn write_with_content(&self, writer:&mut impl Write, text:&str) -> std::fmt::Result { + writeln!(writer, "{}", self.message)?; + if let Some(path) = &self.path { + writeln!(writer, " at {}", path)?; + } + match (self.start_location, self.end_location) { + (Some((line, column)), Some((end_line, end_column))) => { + write!( + writer, + "{}", + get_source_context(text.lines(), line, column, end_line, end_column,) + )?; + }, + (Some((line, column)), None) | (None, Some((line, column))) => { + write!(writer, "{}", get_source_context(text.lines(), line, column, line, column))?; + }, + (None, None) => { + write!(writer, "{}", get_source_context(text.lines(), 0, 0, 0, 0))?; + }, + } + Ok(()) + } + + pub fn to_string_with_content(&self, text:&str) -> String { + let mut result = String::new(); + self.write_with_content(&mut result, text).unwrap(); + result + } +} + +impl Display for UnparseableJson { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.message)?; + if let Some(path) = &self.path { + write!(f, " at {}", path)?; + } + Ok(()) + } +} + +pub fn parse_json_with_source_context<'de, T:Deserialize<'de>>(text:&'de str) -> Result { + let de = &mut serde_json::Deserializer::from_str(text); + match serde_path_to_error::deserialize(de) { + Ok(data) => Ok(data), + Err(e) => { + Err(anyhow::Error::msg( + UnparseableJson::from_serde_path_to_error(e).to_string_with_content(text), + )) + }, + } +} + +pub fn parse_json_rope_with_source_context<'de, T:Deserialize<'de>>(rope:&'de Rope) -> Result { + let de = &mut serde_json::Deserializer::from_reader(rope.read()); + match serde_path_to_error::deserialize(de) { + Ok(data) => Ok(data), + Err(e) => { + let cow = rope.to_str()?; + Err(anyhow::Error::msg( + UnparseableJson::from_serde_path_to_error(e).to_string_with_content(&cow), + )) + }, + } +} diff --git a/crates/turbo-tasks-fs/Source/lib.rs b/crates/turbo-tasks-fs/Source/lib.rs new file mode 100644 index 0000000000000..81e4433b8e565 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/lib.rs @@ -0,0 +1,1866 @@ +#![feature(trivial_bounds)] +#![feature(hash_extract_if)] +#![feature(min_specialization)] +#![feature(iter_advance_by)] +#![feature(io_error_more)] +#![feature(round_char_boundary)] +#![feature(arbitrary_self_types)] +#![feature(lint_reasons)] +#![allow(clippy::mutable_key_type)] + +pub mod attach; +pub mod embed; +pub mod glob; +mod invalidation; +mod invalidator_map; +pub mod json; +mod mutex_map; +mod read_glob; +mod retry; +pub mod rope; +pub mod source_context; +pub mod util; +pub(crate) mod virtual_fs; +mod watcher; + +use std::{ + borrow::Cow, + cmp::min, + collections::HashSet, + fmt::{ + Debug, + Display, + Formatter, + {self}, + }, + fs::FileType, + io::{ + BufRead, + ErrorKind, + {self}, + }, + mem::take, + path::{MAIN_SEPARATOR, Path, PathBuf}, + sync::Arc, +}; + +use anyhow::{Context, Result, anyhow, bail}; +use auto_hash_map::AutoMap; +use bitflags::bitflags; +use dunce::simplified; +use glob::Glob; +use invalidator_map::InvalidatorMap; +use jsonc_parser::{ParseOptions, parse_to_serde_value}; +use mime::Mime; +pub use read_glob::ReadGlobResult; +use read_glob::read_glob; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use tokio::{ + fs, + io::{AsyncBufReadExt, AsyncReadExt, BufReader}, + sync::{RwLock, RwLockReadGuard}, +}; +use tracing::Instrument; +use turbo_tasks::{ + Completion, + InvalidationReason, + Invalidator, + RcStr, + ReadRef, + ValueToString, + Vc, + mark_stateful, + trace::TraceRawVcs, +}; +use turbo_tasks_hash::{DeterministicHash, DeterministicHasher, hash_xxh3_hash64}; +use util::{extract_disk_access, join_path, normalize_path, sys_to_unix, unix_to_sys}; +pub use virtual_fs::VirtualFileSystem; +use watcher::DiskWatcher; + +use self::{invalidation::Write, json::UnparseableJson, mutex_map::MutexMap}; +use crate::{ + attach::AttachedFileSystem, + retry::{retry_blocking, retry_future}, + rope::{Rope, RopeReader}, +}; + +#[turbo_tasks::value_trait] +pub trait FileSystem: ValueToString { + /// Returns the path to the root of the file system. + fn root(self: Vc) -> Vc { + FileSystemPath::new_normalized(self, RcStr::default()) + } + fn read(self: Vc, fs_path:Vc) -> Vc; + fn read_link(self: Vc, fs_path:Vc) -> Vc; + fn read_dir(self: Vc, fs_path:Vc) -> Vc; + fn track(self: Vc, fs_path:Vc) -> Vc; + fn write(self: Vc, fs_path:Vc, content:Vc) + -> Vc; + fn write_link( + self: Vc, + fs_path:Vc, + target:Vc, + ) -> Vc; + fn metadata(self: Vc, fs_path:Vc) -> Vc; +} + +#[turbo_tasks::value(cell = "new", eq = "manual")] +pub struct DiskFileSystem { + pub name:RcStr, + pub root:RcStr, + #[turbo_tasks(debug_ignore, trace_ignore)] + #[serde(skip)] + mutex_map:MutexMap, + #[turbo_tasks(debug_ignore, trace_ignore)] + invalidator_map:Arc, + #[turbo_tasks(debug_ignore, trace_ignore)] + dir_invalidator_map:Arc, + /// Lock that makes invalidation atomic. It will keep a write lock during + /// watcher invalidation and a read lock during other operations. + #[turbo_tasks(debug_ignore, trace_ignore)] + #[serde(skip)] + invalidation_lock:Arc>, + #[turbo_tasks(debug_ignore, trace_ignore)] + watcher:Arc, +} + +impl DiskFileSystem { + /// Returns the root as Path + fn root_path(&self) -> &Path { simplified(Path::new(&*self.root)) } + + /// registers the path as an invalidator for the current task, + /// has to be called within a turbo-tasks function + fn register_invalidator(&self, path:&Path) -> Result<()> { + let invalidator = turbo_tasks::get_invalidator(); + self.invalidator_map.insert(path_to_key(path), invalidator); + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + if let Some(dir) = path.parent() { + self.watcher.ensure_watching(dir, self.root_path())?; + } + Ok(()) + } + + /// registers the path as an invalidator for the current task, + /// has to be called within a turbo-tasks function. It removes and returns + /// the current list of invalidators. + fn register_sole_invalidator(&self, path:&Path) -> Result> { + let invalidator = turbo_tasks::get_invalidator(); + let mut invalidator_map = self.invalidator_map.lock().unwrap(); + let old_invalidators = invalidator_map.insert(path_to_key(path), [invalidator].into()); + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + if let Some(dir) = path.parent() { + self.watcher.ensure_watching(dir, self.root_path())?; + } + Ok(old_invalidators.unwrap_or_default()) + } + + /// registers the path as an invalidator for the current task, + /// has to be called within a turbo-tasks function + fn register_dir_invalidator(&self, path:&Path) -> Result<()> { + let invalidator = turbo_tasks::get_invalidator(); + self.dir_invalidator_map.insert(path_to_key(path), invalidator); + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + self.watcher.ensure_watching(path, self.root_path())?; + Ok(()) + } + + async fn lock_path(&self, full_path:&Path) -> PathLockGuard<'_> { + let lock1 = self.invalidation_lock.read().await; + let lock2 = self.mutex_map.lock(full_path.to_path_buf()).await; + PathLockGuard(lock1, lock2) + } + + pub fn invalidate(&self) { + for (_, invalidators) in take(&mut *self.invalidator_map.lock().unwrap()).into_iter() { + invalidators.into_iter().for_each(|i| i.invalidate()); + } + for (_, invalidators) in take(&mut *self.dir_invalidator_map.lock().unwrap()).into_iter() { + invalidators.into_iter().for_each(|i| i.invalidate()); + } + } + + pub fn invalidate_with_reason(&self, reason:T) { + for (_, invalidators) in take(&mut *self.invalidator_map.lock().unwrap()).into_iter() { + invalidators.into_iter().for_each(|i| i.invalidate_with_reason(reason.clone())); + } + for (_, invalidators) in take(&mut *self.dir_invalidator_map.lock().unwrap()).into_iter() { + invalidators.into_iter().for_each(|i| i.invalidate_with_reason(reason.clone())); + } + } + + pub fn start_watching(&self) -> Result<()> { self.start_watching_internal(false) } + + pub fn start_watching_with_invalidation_reason(&self) -> Result<()> { + self.start_watching_internal(true) + } + + fn start_watching_internal(&self, report_invalidation_reason:bool) -> Result<()> { + let invalidator_map = self.invalidator_map.clone(); + let dir_invalidator_map = self.dir_invalidator_map.clone(); + let root_path = self.root_path().to_path_buf(); + + let report_invalidation_reason = + report_invalidation_reason.then(|| (self.name.clone(), root_path.clone())); + let invalidation_lock = self.invalidation_lock.clone(); + + self.watcher.clone().start_watching( + self.name.clone(), + root_path, + report_invalidation_reason, + invalidation_lock, + invalidator_map, + dir_invalidator_map, + )?; + + Ok(()) + } + + pub fn stop_watching(&self) { self.watcher.stop_watching(); } + + pub async fn to_sys_path(&self, fs_path:Vc) -> Result { + // just in case there's a windows unc path prefix we remove it with `dunce` + let path = self.root_path(); + let fs_path = fs_path.await?; + Ok(if fs_path.path.is_empty() { + path.to_path_buf() + } else { + path.join(&*unix_to_sys(&fs_path.path)) + }) + } + + fn invalidate_from_write(&self, full_path:&Path, invalidators:HashSet) { + if !invalidators.is_empty() { + if let Some(path) = format_absolute_fs_path(full_path, &self.name, self.root_path()) { + if invalidators.len() == 1 { + let invalidator = invalidators.into_iter().next().unwrap(); + invalidator.invalidate_with_reason(Write { path }); + } else { + invalidators.into_iter().for_each(|invalidator| { + invalidator.invalidate_with_reason(Write { path:path.clone() }); + }); + } + } else { + invalidators.into_iter().for_each(|invalidator| { + invalidator.invalidate(); + }); + } + } + } +} + +#[allow(dead_code, reason = "we need to hold onto the locks")] +struct PathLockGuard<'a>( + #[allow(dead_code)] RwLockReadGuard<'a, ()>, + #[allow(dead_code)] mutex_map::MutexMapGuard<'a, PathBuf>, +); + +fn format_absolute_fs_path(path:&Path, name:&str, root_path:&Path) -> Option { + let path = if let Ok(rel_path) = path.strip_prefix(root_path) { + let path = if MAIN_SEPARATOR != '/' { + let rel_path = rel_path.to_string_lossy().replace(MAIN_SEPARATOR, "/"); + format!("[{name}]/{}", rel_path) + } else { + format!("[{name}]/{}", rel_path.display()) + }; + Some(path) + } else { + None + }; + path +} + +pub fn path_to_key(path:impl AsRef) -> String { path.as_ref().to_string_lossy().to_string() } + +#[turbo_tasks::value_impl] +impl DiskFileSystem { + /// Create a new instance of `DiskFileSystem`. + /// # Arguments + /// + /// * `name` - Name of the filesystem. + /// * `root` - Path to the given filesystem's root. + /// * `ignored_subpaths` - A list of subpaths that should not trigger + /// invalidation. This should be a full path, since it is possible that + /// root & project dir is different and requires to ignore specific + /// subpaths from each. + #[turbo_tasks::function] + pub async fn new(name:RcStr, root:RcStr, ignored_subpaths:Vec) -> Result> { + mark_stateful(); + // create the directory for the filesystem on disk, if it doesn't exist + fs::create_dir_all(&root).await?; + + let instance = DiskFileSystem { + name, + root, + mutex_map:Default::default(), + invalidation_lock:Default::default(), + invalidator_map:Arc::new(InvalidatorMap::new()), + dir_invalidator_map:Arc::new(InvalidatorMap::new()), + watcher:Arc::new(DiskWatcher::new( + ignored_subpaths.into_iter().map(PathBuf::from).collect(), + )), + }; + + Ok(Self::cell(instance)) + } +} + +impl Debug for DiskFileSystem { + fn fmt(&self, f:&mut Formatter) -> fmt::Result { + write!(f, "name: {}, root: {}", self.name, self.root) + } +} + +#[turbo_tasks::value_impl] +impl FileSystem for DiskFileSystem { + #[turbo_tasks::function] + async fn read(&self, fs_path:Vc) -> Result> { + let full_path = self.to_sys_path(fs_path).await?; + self.register_invalidator(&full_path)?; + + let _lock = self.lock_path(&full_path).await; + let content = match retry_future(|| File::from_path(full_path.clone())) + .instrument(tracing::info_span!("read file", path = display(full_path.display()))) + .await + { + Ok(file) => FileContent::new(file), + Err(e) if e.kind() == ErrorKind::NotFound || e.kind() == ErrorKind::InvalidFilename => { + FileContent::NotFound + }, + Err(e) => { + bail!(anyhow!(e).context(format!("reading file {}", full_path.display()))) + }, + }; + Ok(content.cell()) + } + + #[turbo_tasks::function] + async fn read_dir(&self, fs_path:Vc) -> Result> { + let full_path = self.to_sys_path(fs_path).await?; + self.register_dir_invalidator(&full_path)?; + let fs_path = fs_path.await?; + + // we use the sync std function here as it's a lot faster (600%) in + // node-file-trace + let read_dir = match retry_blocking( + &full_path, + tracing::info_span!("read directory", path = display(full_path.display())), + |path| std::fs::read_dir(path), + ) + .await + { + Ok(dir) => dir, + Err(e) + if e.kind() == ErrorKind::NotFound + || e.kind() == ErrorKind::NotADirectory + || e.kind() == ErrorKind::InvalidFilename => + { + return Ok(DirectoryContent::not_found()); + }, + Err(e) => { + bail!(anyhow!(e).context(format!("reading dir {}", full_path.display()))) + }, + }; + + let entries = read_dir + .filter_map(|r| { + let e = match r { + Ok(e) => e, + Err(err) => return Some(Err(err.into())), + }; + + let path = e.path(); + + // we filter out any non unicode names and paths without the same root here + let file_name:RcStr = path.file_name()?.to_str()?.into(); + let path_to_root = sys_to_unix(path.strip_prefix(&self.root).ok()?.to_str()?); + + let fs_path = FileSystemPath::new_normalized(fs_path.fs, path_to_root.into()); + + let entry = match e.file_type() { + Ok(t) if t.is_file() => DirectoryEntry::File(fs_path), + Ok(t) if t.is_dir() => DirectoryEntry::Directory(fs_path), + Ok(t) if t.is_symlink() => DirectoryEntry::Symlink(fs_path), + Ok(_) => DirectoryEntry::Other(fs_path), + Err(err) => return Some(Err(err.into())), + }; + + Some(anyhow::Ok((file_name, entry))) + }) + .collect::>() + .with_context(|| format!("reading directory item in {}", full_path.display()))?; + + Ok(DirectoryContent::new(entries)) + } + + #[turbo_tasks::function] + async fn read_link(&self, fs_path:Vc) -> Result> { + let full_path = self.to_sys_path(fs_path).await?; + self.register_invalidator(&full_path)?; + + let _lock = self.lock_path(&full_path).await; + let link_path = match retry_future(|| fs::read_link(&full_path)) + .instrument(tracing::info_span!("read symlink", path = display(full_path.display()))) + .await + { + Ok(res) => res, + Err(_) => return Ok(LinkContent::NotFound.cell()), + }; + let is_link_absolute = link_path.is_absolute(); + + let mut file = link_path.clone(); + if !is_link_absolute { + if let Some(normalized_linked_path) = full_path.parent().and_then(|p| { + normalize_path(&sys_to_unix(p.join(&file).to_string_lossy().as_ref())) + }) { + #[cfg(target_family = "windows")] + { + file = PathBuf::from(normalized_linked_path); + } + // `normalize_path` stripped the leading `/` of the path + // add it back here or the `strip_prefix` will return `Err` + #[cfg(not(target_family = "windows"))] + { + file = PathBuf::from(format!("/{normalized_linked_path}")); + } + } else { + return Ok(LinkContent::Invalid.cell()); + } + } + + // strip the root from the path, it serves two purpose + // 1. ensure the linked path is under the root + // 2. strip the root path if the linked path is absolute + // + // we use `dunce::simplify` to strip a potential UNC prefix on windows, on any + // other OS this gets compiled away + let result = simplified(&file).strip_prefix(simplified(Path::new(&self.root))); + + let relative_to_root_path = match result { + Ok(file) => PathBuf::from(sys_to_unix(&file.to_string_lossy()).as_ref()), + Err(_) => return Ok(LinkContent::Invalid.cell()), + }; + + let (target, file_type) = if is_link_absolute { + let target_string:RcStr = relative_to_root_path.to_string_lossy().into(); + ( + target_string.clone(), + FileSystemPath::new_normalized(fs_path.fs(), target_string).get_type().await?, + ) + } else { + let link_path_string_cow = link_path.to_string_lossy(); + let link_path_unix:RcStr = sys_to_unix(&link_path_string_cow).into(); + (link_path_unix.clone(), fs_path.parent().join(link_path_unix).get_type().await?) + }; + + Ok(LinkContent::Link { + target, + link_type:{ + let mut link_type = Default::default(); + if link_path.is_absolute() { + link_type |= LinkType::ABSOLUTE; + } + if matches!(&*file_type, FileSystemEntryType::Directory) { + link_type |= LinkType::DIRECTORY; + } + link_type + }, + } + .cell()) + } + + #[turbo_tasks::function] + async fn track(&self, fs_path:Vc) -> Result> { + let full_path = self.to_sys_path(fs_path).await?; + self.register_invalidator(&full_path)?; + Ok(Completion::new()) + } + + #[turbo_tasks::function] + async fn write( + &self, + fs_path:Vc, + content:Vc, + ) -> Result> { + let full_path = self.to_sys_path(fs_path).await?; + let content = content.await?; + + let _lock = self.lock_path(&full_path).await; + + // Track the file, so that we will rewrite it if it ever changes. + let old_invalidators = self.register_sole_invalidator(&full_path)?; + + // We perform an untracked comparison here, so that this write is not dependent + // on a read's Vc (and the memory it holds). Our untracked read can + // be freed immediately. Given this is an output file, it's unlikely any Turbo + // code will need to read the file from disk into a Vc, so we're + // not wasting cycles. + let compare = content + .streaming_compare(full_path.clone()) + .instrument(tracing::info_span!( + "read file before write", + path = display(full_path.display()) + )) + .await?; + if compare == FileComparison::Equal { + if !old_invalidators.is_empty() { + let key = path_to_key(&full_path); + for i in old_invalidators { + self.invalidator_map.insert(key.clone(), i); + } + } + return Ok(Completion::unchanged()); + } + + let create_directory = compare == FileComparison::Create; + + match &*content { + FileContent::Content(file) => { + if create_directory { + if let Some(parent) = full_path.parent() { + retry_future(move || fs::create_dir_all(parent)) + .instrument(tracing::info_span!( + "create directory", + path = display(parent.display()) + )) + .await + .with_context(|| { + format!( + "failed to create directory {} for write to {}", + parent.display(), + full_path.display() + ) + })?; + } + } + let full_path_to_write = full_path.clone(); + retry_future(move || { + let full_path = full_path_to_write.clone(); + async move { + let mut f = fs::File::create(&full_path).await?; + tokio::io::copy(&mut file.read(), &mut f).await?; + #[cfg(target_family = "unix")] + f.set_permissions(file.meta.permissions.into()).await?; + #[cfg(feature = "write_version")] + { + let mut full_path = full_path; + let hash = hash_xxh3_hash64(file); + let ext = full_path.extension(); + let ext = if let Some(ext) = ext { + format!("{:016x}.{}", hash, ext.to_string_lossy()) + } else { + format!("{:016x}", hash) + }; + full_path.set_extension(ext); + let mut f = fs::File::create(&full_path).await?; + tokio::io::copy(&mut file.read(), &mut f).await?; + #[cfg(target_family = "unix")] + f.set_permissions(file.meta.permissions.into()).await?; + } + Ok::<(), io::Error>(()) + } + }) + .instrument(tracing::info_span!("write file", path = display(full_path.display()))) + .await + .with_context(|| format!("failed to write to {}", full_path.display()))?; + }, + FileContent::NotFound => { + retry_future(|| fs::remove_file(full_path.clone())) + .instrument(tracing::info_span!( + "remove file", + path = display(full_path.display()) + )) + .await + .or_else( + |err| { + if err.kind() == ErrorKind::NotFound { Ok(()) } else { Err(err) } + }, + ) + .with_context(|| anyhow!("removing {} failed", full_path.display()))?; + }, + } + + self.invalidate_from_write(&full_path, old_invalidators); + + Ok(Completion::new()) + } + + #[turbo_tasks::function] + async fn write_link( + &self, + fs_path:Vc, + target:Vc, + ) -> Result> { + let full_path = self.to_sys_path(fs_path).await?; + // TODO(sokra) preform a untracked read here, register an invalidator and get + // all existing invalidators + let old_content = fs_path + .read_link() + .await + .with_context(|| format!("reading old symlink target of {}", full_path.display()))?; + let target_link = target.await?; + if target_link == old_content { + return Ok(Completion::unchanged()); + } + let file_type = &*fs_path.get_type().await?; + let create_directory = file_type == &FileSystemEntryType::NotFound; + if create_directory { + if let Some(parent) = full_path.parent() { + retry_future(move || fs::create_dir_all(parent)) + .instrument(tracing::info_span!( + "create directory", + path = display(parent.display()) + )) + .await + .with_context(|| { + format!( + "failed to create directory {} for write to {}", + parent.display(), + full_path.display() + ) + })?; + } + } + let _lock = self.lock_path(&full_path).await; + match &*target_link { + LinkContent::Link { target, link_type } => { + let link_type = *link_type; + let target_path = if link_type.contains(LinkType::ABSOLUTE) { + Path::new(&self.root).join(unix_to_sys(target).as_ref()) + } else { + PathBuf::from(unix_to_sys(target).as_ref()) + }; + retry_blocking( + &target_path, + tracing::info_span!("write symlink", path = display(full_path.display())), + move |target_path| { + // we use the sync std method here because `symlink` is fast + // if we put it into a task, it will be slower + #[cfg(not(target_family = "windows"))] + { + std::os::unix::fs::symlink(target_path, &full_path) + } + #[cfg(target_family = "windows")] + { + if link_type.contains(LinkType::DIRECTORY) { + std::os::windows::fs::symlink_dir(target_path, &full_path) + } else { + std::os::windows::fs::symlink_file(target_path, &full_path) + } + } + }, + ) + .await + .with_context(|| format!("create symlink to {}", target))?; + }, + LinkContent::Invalid => { + return Err(anyhow!("invalid symlink target: {}", full_path.display())); + }, + LinkContent::NotFound => { + retry_future(|| fs::remove_file(&full_path)) + .await + .or_else( + |err| { + if err.kind() == ErrorKind::NotFound { Ok(()) } else { Err(err) } + }, + ) + .with_context(|| anyhow!("removing {} failed", full_path.display()))?; + }, + } + Ok(Completion::new()) + } + + #[turbo_tasks::function] + async fn metadata(&self, fs_path:Vc) -> Result> { + let full_path = self.to_sys_path(fs_path).await?; + self.register_invalidator(&full_path)?; + + let _lock = self.lock_path(&full_path).await; + let meta = retry_future(|| fs::metadata(full_path.clone())) + .instrument(tracing::info_span!("read metadata", path = display(full_path.display()))) + .await + .with_context(|| format!("reading metadata for {}", full_path.display()))?; + + Ok(FileMeta::cell(meta.into())) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for DiskFileSystem { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { Vc::cell(self.name.clone()) } +} + +#[turbo_tasks::value] +#[derive(Debug, Clone)] +pub struct FileSystemPath { + pub fs:Vc>, + pub path:RcStr, +} + +impl FileSystemPath { + pub fn is_inside_ref(&self, other:&FileSystemPath) -> bool { + if self.fs == other.fs && self.path.starts_with(&*other.path) { + if other.path.is_empty() { + true + } else { + self.path.as_bytes().get(other.path.len()) == Some(&b'/') + } + } else { + false + } + } + + pub fn is_inside_or_equal_ref(&self, other:&FileSystemPath) -> bool { + if self.fs == other.fs && self.path.starts_with(&*other.path) { + if other.path.is_empty() { + true + } else { + matches!(self.path.as_bytes().get(other.path.len()), Some(&b'/') | None) + } + } else { + false + } + } + + pub fn is_root(&self) -> bool { self.path.is_empty() } + + /// Returns the path of `inner` relative to `self`. + /// + /// Note: this method always strips the leading `/` from the result. + pub fn get_path_to<'a>(&self, inner:&'a FileSystemPath) -> Option<&'a str> { + if self.fs != inner.fs { + return None; + } + let path = inner.path.strip_prefix(&*self.path)?; + if self.path.is_empty() { + Some(path) + } else if let Some(stripped) = path.strip_prefix('/') { + Some(stripped) + } else { + None + } + } + + pub fn get_relative_path_to(&self, other:&FileSystemPath) -> Option { + if self.fs != other.fs { + return None; + } + fn split(s:&str) -> impl Iterator { + let empty = s.is_empty(); + let mut iterator = s.split('/'); + if empty { + iterator.next(); + } + iterator + } + let mut self_segments = split(&self.path).peekable(); + let mut other_segments = split(&other.path).peekable(); + while self_segments.peek() == other_segments.peek() { + self_segments.next(); + if other_segments.next().is_none() { + return Some(".".into()); + } + } + let mut result = Vec::new(); + if self_segments.peek().is_none() { + result.push("."); + } else { + while self_segments.next().is_some() { + result.push(".."); + } + } + for segment in other_segments { + result.push(segment); + } + Some(result.join("/").into()) + } + + /// Returns the final component of the FileSystemPath, or an empty string + /// for the root path. + pub fn file_name(&self) -> &str { + let (_, file_name) = self.split_file_name(); + file_name + } + + pub fn extension_ref(&self) -> Option<&str> { + let (_, extension) = self.split_extension(); + extension + } + + /// Splits the path into two components: + /// 1. The path without the extension; + /// 2. The extension, if any. + fn split_extension(&self) -> (&str, Option<&str>) { + if let Some((path_before_extension, extension)) = self.path.rsplit_once('.') { + if extension.contains('/') || + // The file name begins with a `.` and has no other `.`s within. + path_before_extension.ends_with('/') || path_before_extension.is_empty() + { + (self.path.as_str(), None) + } else { + (path_before_extension, Some(extension)) + } + } else { + (self.path.as_str(), None) + } + } + + /// Splits the path into two components: + /// 1. The parent directory, if any; + /// 2. The file name; + fn split_file_name(&self) -> (Option<&str>, &str) { + // Since the path is normalized, we know `parent`, if any, must not be empty. + if let Some((parent, file_name)) = self.path.rsplit_once('/') { + (Some(parent), file_name) + } else { + (None, self.path.as_str()) + } + } + + /// Splits the path into three components: + /// 1. The parent directory, if any; + /// 2. The file stem; + /// 3. The extension, if any. + fn split_file_stem_extension(&self) -> (Option<&str>, &str, Option<&str>) { + let (path_before_extension, extension) = self.split_extension(); + + if let Some((parent, file_stem)) = path_before_extension.rsplit_once('/') { + (Some(parent), file_stem, extension) + } else { + (None, path_before_extension, extension) + } + } +} + +#[turbo_tasks::value(transparent)] +pub struct FileSystemPathOption(Option>); + +#[turbo_tasks::value_impl] +impl FileSystemPathOption { + #[turbo_tasks::function] + pub fn none() -> Vc { Vc::cell(None) } +} + +#[turbo_tasks::value_impl] +impl FileSystemPath { + /// Create a new Vc from a path withing a FileSystem. The + /// /-separated path is expected to be already normalized (this is asserted + /// in dev mode). + #[turbo_tasks::function] + fn new_normalized(fs:Vc>, path:RcStr) -> Vc { + // On Windows, the path must be converted to a unix path before creating. But on + // Unix, backslashes are a valid char in file names, and the path can be + // provided by the user, so we allow it. + debug_assert!( + MAIN_SEPARATOR != '\\' || !path.contains('\\'), + "path {} must not contain a Windows directory '\\', it must be normalized to Unix '/'", + path, + ); + debug_assert!( + normalize_path(&path).as_deref() == Some(&*path), + "path {} must be normalized", + path, + ); + Self::cell(FileSystemPath { fs, path }) + } + + /// Adds a subpath to the current path. The /-separate path argument might + /// contain ".." or "." seqments, but it must not leave the root of the + /// filesystem. + #[turbo_tasks::function] + pub async fn join(self: Vc, path:RcStr) -> Result> { + let this = self.await?; + if let Some(path) = join_path(&this.path, &path) { + Ok(Self::new_normalized(this.fs, path.into())) + } else { + bail!( + "Vc(\"{}\").join(\"{}\") leaves the filesystem root", + this.path, + path + ); + } + } + + /// Adds a suffix to the filename. [path] must not contain `/`. + #[turbo_tasks::function] + pub async fn append(self: Vc, path:RcStr) -> Result> { + let this = self.await?; + if path.contains('/') { + bail!("Vc(\"{}\").append(\"{}\") must not append '/'", this.path, path) + } + Ok(Self::new_normalized(this.fs, format!("{}{}", this.path, path).into())) + } + + /// Adds a suffix to the basename of the filename. [appending] must not + /// contain `/`. Extension will stay intact. + #[turbo_tasks::function] + pub async fn append_to_stem(self: Vc, appending:RcStr) -> Result> { + let this = self.await?; + if appending.contains('/') { + bail!( + "Vc(\"{}\").append_to_stem(\"{}\") must not append '/'", + this.path, + appending + ) + } + if let (path, Some(ext)) = this.split_extension() { + return Ok(Self::new_normalized( + this.fs, + format!("{}{}.{}", path, appending, ext).into(), + )); + } + Ok(Self::new_normalized(this.fs, format!("{}{}", this.path, appending).into())) + } + + /// Similar to [FileSystemPath::join], but returns an Option that will be + /// None when the joined path would leave the filesystem root. + #[turbo_tasks::function] + pub async fn try_join(self: Vc, path:RcStr) -> Result> { + let this = self.await?; + if let Some(path) = join_path(&this.path, &path) { + Ok(Vc::cell(Some(Self::new_normalized(this.fs, path.into()).resolve().await?))) + } else { + Ok(FileSystemPathOption::none()) + } + } + + /// Similar to [FileSystemPath::join], but returns an Option that will be + /// None when the joined path would leave the current path. + #[turbo_tasks::function] + pub async fn try_join_inside(self: Vc, path:RcStr) -> Result> { + let this = self.await?; + if let Some(path) = join_path(&this.path, &path) { + if path.starts_with(&*this.path) { + return Ok(Vc::cell(Some( + Self::new_normalized(this.fs, path.into()).resolve().await?, + ))); + } + } + Ok(FileSystemPathOption::none()) + } + + #[turbo_tasks::function] + pub async fn read_glob( + self: Vc, + glob:Vc, + include_dot_files:bool, + ) -> Vc { + read_glob(self, glob, include_dot_files) + } + + #[turbo_tasks::function] + pub fn root(self: Vc) -> Vc { self.fs().root() } + + #[turbo_tasks::function] + pub async fn fs(self: Vc) -> Result>> { Ok(self.await?.fs) } + + #[turbo_tasks::function] + pub async fn extension(self: Vc) -> Result> { + let this = self.await?; + Ok(Vc::cell(this.extension_ref().unwrap_or("").into())) + } + + #[turbo_tasks::function] + pub async fn is_inside(self: Vc, other:Vc) -> Result> { + Ok(Vc::cell(self.await?.is_inside_ref(&*other.await?))) + } + + #[turbo_tasks::function] + pub async fn is_inside_or_equal(self: Vc, other:Vc) -> Result> { + Ok(Vc::cell(self.await?.is_inside_or_equal_ref(&*other.await?))) + } + + /// Creates a new [`Vc`] like `self` but with the given + /// extension. + #[turbo_tasks::function] + pub async fn with_extension(self: Vc, extension:RcStr) -> Result> { + let this = self.await?; + let (path_without_extension, _) = this.split_extension(); + Ok(Self::new_normalized( + this.fs, + // Like `Path::with_extension` and `PathBuf::set_extension`, if the extension is empty, + // we remove the extension altogether. + match extension.is_empty() { + true => path_without_extension.into(), + false => format!("{path_without_extension}.{extension}").into(), + }, + )) + } + + /// Extracts the stem (non-extension) portion of self.file_name. + /// + /// The stem is: + /// + /// * [`None`], if there is no file name; + /// * The entire file name if there is no embedded `.`; + /// * The entire file name if the file name begins with `.` and has no other + /// `.`s within; + /// * Otherwise, the portion of the file name before the final `.` + #[turbo_tasks::function] + pub async fn file_stem(self: Vc) -> Result>> { + let this = self.await?; + let (_, file_stem, _) = this.split_file_stem_extension(); + if file_stem.is_empty() { + return Ok(Vc::cell(None)); + } + Ok(Vc::cell(Some(file_stem.into()))) + } +} + +impl Display for FileSystemPath { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.path) } +} + +#[turbo_tasks::function] +pub async fn rebase( + fs_path:Vc, + old_base:Vc, + new_base:Vc, +) -> Result> { + let fs_path = &*fs_path.await?; + let old_base = &*old_base.await?; + let new_base = &*new_base.await?; + let new_path; + if old_base.path.is_empty() { + if new_base.path.is_empty() { + new_path = fs_path.path.clone(); + } else { + new_path = [new_base.path.as_str(), "/", &fs_path.path].concat().into(); + } + } else { + let base_path = [&old_base.path, "/"].concat(); + if !fs_path.path.starts_with(&base_path) { + bail!( + "rebasing {} from {} onto {} doesn't work because it's not part of the source path", + fs_path.to_string(), + old_base.to_string(), + new_base.to_string() + ); + } + if new_base.path.is_empty() { + new_path = [&fs_path.path[base_path.len()..]].concat().into(); + } else { + new_path = + [new_base.path.as_str(), &fs_path.path[old_base.path.len()..]].concat().into(); + } + } + Ok(new_base.fs.root().join(new_path)) +} + +// Not turbo-tasks functions, only delegating +impl FileSystemPath { + pub fn read(self: Vc) -> Vc { self.fs().read(self) } + + pub fn read_link(self: Vc) -> Vc { self.fs().read_link(self) } + + pub fn read_json(self: Vc) -> Vc { self.fs().read(self).parse_json() } + + /// Reads content of a directory. + /// + /// DETERMINISM: Result is in random order. Either sort result or do not + /// depend on the order. + pub fn read_dir(self: Vc) -> Vc { self.fs().read_dir(self) } + + pub fn track(self: Vc) -> Vc { self.fs().track(self) } + + pub fn write(self: Vc, content:Vc) -> Vc { + self.fs().write(self, content) + } + + pub fn write_link(self: Vc, target:Vc) -> Vc { + self.fs().write_link(self, target) + } + + pub fn metadata(self: Vc) -> Vc { self.fs().metadata(self) } + + pub fn realpath(self: Vc) -> Vc { self.realpath_with_links().path() } + + pub fn rebase( + fs_path:Vc, + old_base:Vc, + new_base:Vc, + ) -> Vc { + rebase(fs_path, old_base, new_base) + } +} + +#[turbo_tasks::value_impl] +impl FileSystemPath { + #[turbo_tasks::function] + pub async fn parent(self: Vc) -> Result> { + let this = self.await?; + let path = &this.path; + if path.is_empty() { + return Ok(self); + } + let p = match str::rfind(path, '/') { + Some(index) => path[..index].to_string(), + None => "".to_string(), + }; + Ok(FileSystemPath::new_normalized(this.fs, p.into())) + } + + #[turbo_tasks::function] + // It is important that get_type uses read_dir and not stat/metadata. + // - `get_type` is called very very often during resolving and stat would + // make it 1 syscall per call, whereas read_dir would make it 1 syscall per + // directory. + // - `metadata` allows you to use the "wrong" casing on + // case-insenstive filesystems, while read_dir gives you the "correct" + // casing. We want to enforce "correct" casing to avoid broken builds on + // Vercel deployments (case-sensitive). + pub async fn get_type(self: Vc) -> Result> { + let this = self.await?; + if this.is_root() { + return Ok(FileSystemEntryType::cell(FileSystemEntryType::Directory)); + } + let parent = self.parent().resolve().await?; + let dir_content = parent.read_dir().await?; + match &*dir_content { + DirectoryContent::NotFound => { + Ok(FileSystemEntryType::cell(FileSystemEntryType::NotFound)) + }, + DirectoryContent::Entries(entries) => { + let (_, file_name) = this.split_file_name(); + if let Some(entry) = entries.get(file_name) { + Ok(FileSystemEntryType::cell(entry.into())) + } else { + Ok(FileSystemEntryType::cell(FileSystemEntryType::NotFound)) + } + }, + } + } + + #[turbo_tasks::function] + pub async fn realpath_with_links(self: Vc) -> Result> { + let this = self.await?; + if this.is_root() { + return Ok(RealPathResult { path:self, symlinks:Vec::new() }.cell()); + } + let parent = self.parent().resolve().await?; + let parent_result = parent.realpath_with_links().await?; + let basename = this.path.rsplit_once('/').map_or(this.path.as_str(), |(_, name)| name); + let real_self = if parent_result.path != parent { + parent_result.path.join(basename.into()).resolve().await? + } else { + self + }; + let mut result = parent_result.clone_value(); + if matches!(*real_self.get_type().await?, FileSystemEntryType::Symlink) { + if let LinkContent::Link { target, link_type } = &*real_self.read_link().await? { + result.symlinks.push(real_self); + result.path = if link_type.contains(LinkType::ABSOLUTE) { + real_self.root().resolve().await? + } else { + result.path + } + .join(target.clone()) + .resolve() + .await?; + return Ok(result.cell()); + } + } + result.path = real_self; + Ok(result.cell()) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for FileSystemPath { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("[{}]/{}", self.fs.to_string().await?, self.path).into())) + } +} + +#[derive(Clone, Debug)] +#[turbo_tasks::value(shared)] +pub struct RealPathResult { + pub path:Vc, + pub symlinks:Vec>, +} + +#[turbo_tasks::value_impl] +impl RealPathResult { + #[turbo_tasks::function] + pub async fn path(self: Vc) -> Result> { Ok(self.await?.path) } +} + +#[derive(Clone, Copy, Debug, DeterministicHash)] +#[turbo_tasks::value(shared)] +pub enum Permissions { + Readable, + Writable, + Executable, +} + +impl Default for Permissions { + fn default() -> Self { Self::Writable } +} + +// Only handle the permissions on unix platform for now + +#[cfg(target_family = "unix")] +impl From for std::fs::Permissions { + fn from(perm:Permissions) -> Self { + use std::os::unix::fs::PermissionsExt; + match perm { + Permissions::Readable => std::fs::Permissions::from_mode(0o444), + Permissions::Writable => std::fs::Permissions::from_mode(0o664), + Permissions::Executable => std::fs::Permissions::from_mode(0o755), + } + } +} + +#[cfg(target_family = "unix")] +impl From for Permissions { + fn from(perm:std::fs::Permissions) -> Self { + use std::os::unix::fs::PermissionsExt; + if perm.readonly() { + Permissions::Readable + } else { + // https://github.com/fitzgen/is_executable/blob/master/src/lib.rs#L96 + if perm.mode() & 0o111 != 0 { + Permissions::Executable + } else { + Permissions::Writable + } + } + } +} + +#[cfg(not(target_family = "unix"))] +impl From for Permissions { + fn from(_:std::fs::Permissions) -> Self { Permissions::default() } +} + +#[turbo_tasks::value(shared)] +#[derive(Clone, Debug, DeterministicHash)] +pub enum FileContent { + Content(File), + NotFound, +} + +impl From for FileContent { + fn from(file:File) -> Self { FileContent::Content(file) } +} + +impl From for Vc { + fn from(file:File) -> Self { FileContent::Content(file).cell() } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +enum FileComparison { + Create, + Equal, + NotEqual, +} + +impl FileContent { + /// Performs a comparison of self's data against a disk file's streamed + /// read. + async fn streaming_compare(&self, path:PathBuf) -> Result { + let old_file = extract_disk_access(retry_future(|| fs::File::open(&path)).await, &path)?; + let Some(mut old_file) = old_file else { + return Ok(match self { + FileContent::NotFound => FileComparison::Equal, + _ => FileComparison::Create, + }); + }; + // We know old file exists, does the new file? + let FileContent::Content(new_file) = self else { + return Ok(FileComparison::NotEqual); + }; + + let old_meta = extract_disk_access(retry_future(|| old_file.metadata()).await, &path)?; + let Some(old_meta) = old_meta else { + // If we failed to get meta, then the old file has been deleted between the + // handle open. In which case, we just pretend the file never + // existed. + return Ok(FileComparison::Create); + }; + // If the meta is different, we need to rewrite the file to update it. + if new_file.meta != old_meta.into() { + return Ok(FileComparison::NotEqual); + } + + // So meta matches, and we have a file handle. Let's stream the contents to see + // if they match. + let mut new_contents = new_file.read(); + let mut old_contents = BufReader::new(&mut old_file); + Ok(loop { + let new_chunk = new_contents.fill_buf()?; + let Ok(old_chunk) = old_contents.fill_buf().await else { + break FileComparison::NotEqual; + }; + + let len = min(new_chunk.len(), old_chunk.len()); + if len == 0 { + if new_chunk.len() == old_chunk.len() { + break FileComparison::Equal; + } else { + break FileComparison::NotEqual; + } + } + + if new_chunk[0..len] != old_chunk[0..len] { + break FileComparison::NotEqual; + } + + new_contents.consume(len); + old_contents.consume(len); + }) + } +} + +bitflags! { + #[derive(Default, Serialize, Deserialize, TraceRawVcs)] + pub struct LinkType: u8 { + const DIRECTORY = 0b00000001; + const ABSOLUTE = 0b00000010; + } +} + +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub enum LinkContent { + // for the relative link, the target is raw value read from the link + // for the absolute link, the target is stripped of the root path while reading + // We don't use the `Vc` here for now, because the `FileSystemPath` is always + // normalized, which means in `fn write_link` we couldn't restore the raw value of the file + // link because there is only **dist** path in `fn write_link`, and we need the raw path if + // we want to restore the link value in `fn write_link` + Link { target:RcStr, link_type:LinkType }, + Invalid, + NotFound, +} + +#[turbo_tasks::value(shared)] +#[derive(Clone, DeterministicHash)] +pub struct File { + meta:FileMeta, + #[turbo_tasks(debug_ignore)] + content:Rope, +} + +impl File { + /// Reads a [File] from the given path + async fn from_path(p:PathBuf) -> io::Result { + let mut file = fs::File::open(p).await?; + let metadata = file.metadata().await?; + + let mut output = Vec::with_capacity(metadata.len() as usize); + file.read_to_end(&mut output).await?; + + Ok(File { meta:metadata.into(), content:Rope::from(output) }) + } + + /// Creates a [File] from raw bytes. + fn from_bytes(content:Vec) -> Self { + File { meta:FileMeta::default(), content:Rope::from(content) } + } + + /// Creates a [File] from a rope. + fn from_rope(content:Rope) -> Self { File { meta:FileMeta::default(), content } } + + /// Returns the content type associated with this file. + pub fn content_type(&self) -> Option<&Mime> { self.meta.content_type.as_ref() } + + /// Sets the content type associated with this file. + pub fn with_content_type(mut self, content_type:Mime) -> Self { + self.meta.content_type = Some(content_type); + self + } + + /// Returns a Read/AsyncRead/Stream/Iterator to access the File's contents. + pub fn read(&self) -> RopeReader { self.content.read() } +} + +impl Debug for File { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { + f.debug_struct("File") + .field("meta", &self.meta) + .field("content (hash)", &hash_xxh3_hash64(&self.content)) + .finish() + } +} + +impl From for File { + fn from(s:RcStr) -> Self { s.into_owned().into() } +} + +impl From for File { + fn from(s:String) -> Self { File::from_bytes(s.into_bytes()) } +} + +impl From> for File { + fn from(s:ReadRef) -> Self { File::from_bytes(s.as_bytes().to_vec()) } +} + +impl From<&str> for File { + fn from(s:&str) -> Self { File::from_bytes(s.as_bytes().to_vec()) } +} + +impl From> for File { + fn from(bytes:Vec) -> Self { File::from_bytes(bytes) } +} + +impl From<&[u8]> for File { + fn from(bytes:&[u8]) -> Self { File::from_bytes(bytes.to_vec()) } +} + +impl From> for File { + fn from(rope:ReadRef) -> Self { File::from_rope(rope.clone_value()) } +} + +impl From for File { + fn from(rope:Rope) -> Self { File::from_rope(rope) } +} + +impl File { + pub fn new(meta:FileMeta, content:Vec) -> Self { + Self { meta, content:Rope::from(content) } + } + + /// Returns the associated [FileMeta] of this file. + pub fn meta(&self) -> &FileMeta { &self.meta } + + /// Returns the immutable contents of this file. + pub fn content(&self) -> &Rope { &self.content } +} + +mod mime_option_serde { + use std::{fmt, str::FromStr}; + + use mime::Mime; + use serde::{Deserializer, Serializer, de}; + + pub fn serialize(mime:&Option, serializer:S) -> Result + where + S: Serializer, { + if let Some(mime) = mime { + serializer.serialize_str(mime.as_ref()) + } else { + serializer.serialize_str("") + } + } + + pub fn deserialize<'de, D>(deserializer:D) -> Result, D::Error> + where + D: Deserializer<'de>, { + struct Visitor; + + impl<'de> de::Visitor<'de> for Visitor { + type Value = Option; + + fn expecting(&self, formatter:&mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a valid MIME type or empty string") + } + + fn visit_str(self, value:&str) -> Result, E> + where + E: de::Error, { + if value.is_empty() { + Ok(None) + } else { + Mime::from_str(value).map(Some).map_err(|e| E::custom(format!("{}", e))) + } + } + } + + deserializer.deserialize_str(Visitor) + } +} + +#[turbo_tasks::value(shared)] +#[derive(Debug, Clone, Default)] +pub struct FileMeta { + permissions:Permissions, + #[serde(with = "mime_option_serde")] + #[turbo_tasks(trace_ignore)] + content_type:Option, +} + +impl From for FileMeta { + fn from(meta:std::fs::Metadata) -> Self { + let permissions = meta.permissions().into(); + + Self { permissions, content_type:None } + } +} + +impl DeterministicHash for FileMeta { + fn deterministic_hash(&self, state:&mut H) { + self.permissions.deterministic_hash(state); + if let Some(content_type) = &self.content_type { + content_type.to_string().deterministic_hash(state); + } + } +} + +impl FileContent { + pub fn new(file:File) -> Self { FileContent::Content(file) } + + pub fn is_content(&self) -> bool { matches!(self, FileContent::Content(_)) } + + pub fn as_content(&self) -> Option<&File> { + match self { + FileContent::Content(file) => Some(file), + FileContent::NotFound => None, + } + } + + pub fn parse_json_ref(&self) -> FileJsonContent { + match self { + FileContent::Content(file) => { + let de = &mut serde_json::Deserializer::from_reader(file.read()); + match serde_path_to_error::deserialize(de) { + Ok(data) => FileJsonContent::Content(data), + Err(e) => { + FileJsonContent::Unparseable(Box::new( + UnparseableJson::from_serde_path_to_error(e), + )) + }, + } + }, + FileContent::NotFound => FileJsonContent::NotFound, + } + } + + pub fn parse_json_with_comments_ref(&self) -> FileJsonContent { + match self { + FileContent::Content(file) => { + match file.content.to_str() { + Ok(string) => { + match parse_to_serde_value( + &string, + &ParseOptions { + allow_comments:true, + allow_trailing_commas:true, + allow_loose_object_property_names:false, + }, + ) { + Ok(data) => { + match data { + Some(value) => FileJsonContent::Content(value), + None => { + FileJsonContent::unparseable( + "text content doesn't contain any json data", + ) + }, + } + }, + Err(e) => { + FileJsonContent::Unparseable(Box::new( + UnparseableJson::from_jsonc_error(e, string.as_ref()), + )) + }, + } + }, + Err(_) => FileJsonContent::unparseable("binary is not valid utf-8 text"), + } + }, + FileContent::NotFound => FileJsonContent::NotFound, + } + } + + pub fn lines_ref(&self) -> FileLinesContent { + match self { + FileContent::Content(file) => { + match file.content.to_str() { + Ok(string) => { + let mut bytes_offset = 0; + FileLinesContent::Lines( + string + .split('\n') + .map(|l| { + let line = FileLine { content:l.to_string(), bytes_offset }; + bytes_offset += l.len() + 1; + line + }) + .collect(), + ) + }, + Err(_) => FileLinesContent::Unparseable, + } + }, + FileContent::NotFound => FileLinesContent::NotFound, + } + } +} + +#[turbo_tasks::value_impl] +impl FileContent { + #[turbo_tasks::function] + pub async fn parse_json(self: Vc) -> Result> { + let this = self.await?; + Ok(this.parse_json_ref().into()) + } + + #[turbo_tasks::function] + pub async fn parse_json_with_comments(self: Vc) -> Result> { + let this = self.await?; + Ok(this.parse_json_with_comments_ref().into()) + } + + #[turbo_tasks::function] + pub async fn lines(self: Vc) -> Result> { + let this = self.await?; + Ok(this.lines_ref().into()) + } + + #[turbo_tasks::function] + pub async fn hash(self: Vc) -> Result> { + Ok(Vc::cell(hash_xxh3_hash64(&self.await?))) + } +} + +/// A file's content interpreted as a JSON value. +#[turbo_tasks::value(shared, serialization = "none")] +pub enum FileJsonContent { + Content(Value), + Unparseable(Box), + NotFound, +} + +#[turbo_tasks::value_impl] +impl ValueToString for FileJsonContent { + /// Returns the JSON file content as a UTF-8 string. + /// + /// This operation will only succeed if the file contents are a valid JSON + /// value. + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + match self { + FileJsonContent::Content(json) => Ok(Vc::cell(json.to_string().into())), + FileJsonContent::Unparseable(e) => Err(anyhow!("File is not valid JSON: {}", e)), + FileJsonContent::NotFound => Err(anyhow!("File not found")), + } + } +} + +impl FileJsonContent { + pub fn unparseable(message:&'static str) -> Self { + FileJsonContent::Unparseable(Box::new(UnparseableJson { + message:Cow::Borrowed(message), + path:None, + start_location:None, + end_location:None, + })) + } + + pub fn unparseable_with_message(message:Cow<'static, str>) -> Self { + FileJsonContent::Unparseable(Box::new(UnparseableJson { + message, + path:None, + start_location:None, + end_location:None, + })) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct FileLine { + pub content:String, + pub bytes_offset:usize, +} + +#[turbo_tasks::value(shared, serialization = "none")] +pub enum FileLinesContent { + Lines(#[turbo_tasks(trace_ignore)] Vec), + Unparseable, + NotFound, +} + +#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, TraceRawVcs, Serialize, Deserialize)] +pub enum DirectoryEntry { + File(Vc), + Directory(Vc), + Symlink(Vc), + Other(Vc), + Error, +} + +#[turbo_tasks::value] +#[derive(Hash, Clone, Copy, Debug)] +pub enum FileSystemEntryType { + NotFound, + File, + Directory, + Symlink, + Other, + Error, +} + +impl From for FileSystemEntryType { + fn from(file_type:FileType) -> Self { + match file_type { + t if t.is_dir() => FileSystemEntryType::Directory, + t if t.is_file() => FileSystemEntryType::File, + t if t.is_symlink() => FileSystemEntryType::Symlink, + _ => FileSystemEntryType::Other, + } + } +} + +impl From for FileSystemEntryType { + fn from(entry:DirectoryEntry) -> Self { FileSystemEntryType::from(&entry) } +} + +impl From<&DirectoryEntry> for FileSystemEntryType { + fn from(entry:&DirectoryEntry) -> Self { + match entry { + DirectoryEntry::File(_) => FileSystemEntryType::File, + DirectoryEntry::Directory(_) => FileSystemEntryType::Directory, + DirectoryEntry::Symlink(_) => FileSystemEntryType::Symlink, + DirectoryEntry::Other(_) => FileSystemEntryType::Other, + DirectoryEntry::Error => FileSystemEntryType::Error, + } + } +} + +#[turbo_tasks::value] +#[derive(Debug)] +pub enum DirectoryContent { + Entries(AutoMap), + NotFound, +} + +impl DirectoryContent { + pub fn new(entries:AutoMap) -> Vc { + Self::cell(DirectoryContent::Entries(entries)) + } + + pub fn not_found() -> Vc { Self::cell(DirectoryContent::NotFound) } +} + +#[turbo_tasks::value(shared)] +pub struct NullFileSystem; + +#[turbo_tasks::value_impl] +impl FileSystem for NullFileSystem { + #[turbo_tasks::function] + fn read(&self, _fs_path:Vc) -> Vc { FileContent::NotFound.cell() } + + #[turbo_tasks::function] + fn read_link(&self, _fs_path:Vc) -> Vc { + LinkContent::NotFound.into() + } + + #[turbo_tasks::function] + fn read_dir(&self, _fs_path:Vc) -> Vc { + DirectoryContent::not_found() + } + + #[turbo_tasks::function] + fn track(&self, _fs_path:Vc) -> Vc { Completion::immutable() } + + #[turbo_tasks::function] + fn write(&self, _fs_path:Vc, _content:Vc) -> Vc { + Completion::new() + } + + #[turbo_tasks::function] + fn write_link(&self, _fs_path:Vc, _target:Vc) -> Vc { + Completion::new() + } + + #[turbo_tasks::function] + fn metadata(&self, _fs_path:Vc) -> Vc { FileMeta::default().cell() } +} + +#[turbo_tasks::value_impl] +impl ValueToString for NullFileSystem { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { Vc::cell(RcStr::from("null")) } +} + +pub async fn to_sys_path(mut path:Vc) -> Result> { + loop { + if let Some(fs) = Vc::try_resolve_downcast_type::(path.fs()).await? { + path = fs.get_inner_fs_path(path); + continue; + } + + if let Some(fs) = Vc::try_resolve_downcast_type::(path.fs()).await? { + let sys_path = fs.await?.to_sys_path(path).await?; + return Ok(Some(sys_path)); + } + + return Ok(None); + } +} + +pub fn register() { + turbo_tasks::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn with_extension() { + crate::register(); + + turbo_tasks_testing::VcStorage::with(async { + let fs = Vc::upcast(VirtualFileSystem::new()); + + let path_txt = FileSystemPath::new_normalized(fs, "foo/bar.txt".into()); + + let path_json = path_txt.with_extension("json".into()); + assert_eq!(&*path_json.await.unwrap().path, "foo/bar.json"); + + let path_no_ext = path_txt.with_extension("".into()); + assert_eq!(&*path_no_ext.await.unwrap().path, "foo/bar"); + + let path_new_ext = path_no_ext.with_extension("json".into()); + assert_eq!(&*path_new_ext.await.unwrap().path, "foo/bar.json"); + + let path_no_slash_txt = FileSystemPath::new_normalized(fs, "bar.txt".into()); + + let path_no_slash_json = path_no_slash_txt.with_extension("json".into()); + assert_eq!(path_no_slash_json.await.unwrap().path.as_str(), "bar.json"); + + let path_no_slash_no_ext = path_no_slash_txt.with_extension("".into()); + assert_eq!(path_no_slash_no_ext.await.unwrap().path.as_str(), "bar"); + + let path_no_slash_new_ext = path_no_slash_no_ext.with_extension("json".into()); + assert_eq!(path_no_slash_new_ext.await.unwrap().path.as_str(), "bar.json"); + + anyhow::Ok(()) + }) + .await + .unwrap() + } + + #[tokio::test] + async fn file_stem() { + crate::register(); + + turbo_tasks_testing::VcStorage::with(async { + let fs = Vc::upcast::>(VirtualFileSystem::new()); + + let path = FileSystemPath::new_normalized(fs, "".into()); + assert_eq!(path.file_stem().await.unwrap().as_deref(), None); + + let path = FileSystemPath::new_normalized(fs, "foo/bar.txt".into()); + assert_eq!(path.file_stem().await.unwrap().as_deref(), Some("bar")); + + let path = FileSystemPath::new_normalized(fs, "bar.txt".into()); + assert_eq!(path.file_stem().await.unwrap().as_deref(), Some("bar")); + + let path = FileSystemPath::new_normalized(fs, "foo/bar".into()); + assert_eq!(path.file_stem().await.unwrap().as_deref(), Some("bar")); + + let path = FileSystemPath::new_normalized(fs, "foo/.bar".into()); + assert_eq!(path.file_stem().await.unwrap().as_deref(), Some(".bar")); + + anyhow::Ok(()) + }) + .await + .unwrap() + } +} diff --git a/crates/turbo-tasks-fs/Source/mutex_map.rs b/crates/turbo-tasks-fs/Source/mutex_map.rs new file mode 100644 index 0000000000000..d02b6b31fab80 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/mutex_map.rs @@ -0,0 +1,103 @@ +use std::{ + collections::{HashMap, hash_map::Entry}, + hash::Hash, + marker::PhantomData, +}; + +use parking_lot::Mutex; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use turbo_tasks::event::Event; + +pub struct MutexMap { + map:Mutex>>, +} + +impl Default for MutexMap { + fn default() -> Self { Self { map:Mutex::new(HashMap::new()) } } +} + +impl<'a, K:Eq + Hash + Clone> MutexMap { + pub async fn lock(&'a self, key:K) -> MutexMapGuard<'a, K> { + let listener = { + let mut map = self.map.lock(); + match map.entry(key.clone()) { + Entry::Occupied(mut e) => { + let state = e.get_mut(); + Some(match state { + Some((event, count)) => { + *count += 1; + event.listen() + }, + None => { + let event = Event::new(|| "MutexMap".to_string()); + let listener = event.listen(); + *state = Some((event, 0)); + listener + }, + }) + }, + Entry::Vacant(e) => { + e.insert(None); + None + }, + } + }; + if let Some(listener) = listener { + listener.await; + } + MutexMapGuard { map:self, key:Some(key) } + } +} + +pub struct MutexMapGuard<'a, K:Eq + Hash> { + map:&'a MutexMap, + key:Option, +} + +impl<'a, K:Eq + Hash> Drop for MutexMapGuard<'a, K> { + fn drop(&mut self) { + if let Some(key) = self.key.take() { + let mut map = self.map.map.lock(); + if let Entry::Occupied(mut e) = map.entry(key) { + let value = e.get_mut(); + match value { + Some((event, count)) => { + event.notify(1); + if *count == 0 { + *value = None; + } else { + *count -= 1; + } + }, + None => { + e.remove(); + }, + } + } + } + } +} + +impl Serialize for MutexMap { + fn serialize(&self, serializer:S) -> Result { + serializer.serialize_unit() + } +} + +impl<'de, K> Deserialize<'de> for MutexMap { + fn deserialize>(deserializer:D) -> Result { + struct Visitor(PhantomData>); + impl<'de, K> serde::de::Visitor<'de> for Visitor { + type Value = MutexMap; + + fn expecting(&self, formatter:&mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a unit") + } + + fn visit_unit(self) -> Result { + Ok(MutexMap::default()) + } + } + deserializer.deserialize_unit(Visitor(std::marker::PhantomData)) + } +} diff --git a/crates/turbo-tasks-fs/Source/read_glob.rs b/crates/turbo-tasks-fs/Source/read_glob.rs new file mode 100644 index 0000000000000..ef2066eea45d8 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/read_glob.rs @@ -0,0 +1,78 @@ +use std::collections::HashMap; + +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; + +use crate::{DirectoryContent, DirectoryEntry, FileSystemPath, glob::Glob}; + +#[turbo_tasks::value] +#[derive(Default, Debug)] +pub struct ReadGlobResult { + pub results:HashMap, + pub inner:HashMap>, +} + +/// Reads matches of a glob pattern. +/// +/// DETERMINISM: Result is in random order. Either sort result or do not depend +/// on the order. +#[turbo_tasks::function] +pub async fn read_glob( + directory:Vc, + glob:Vc, + include_dot_files:bool, +) -> Result> { + read_glob_internal("", directory, glob, include_dot_files).await +} + +#[turbo_tasks::function] +async fn read_glob_inner( + prefix:RcStr, + directory:Vc, + glob:Vc, + include_dot_files:bool, +) -> Result> { + read_glob_internal(&prefix, directory, glob, include_dot_files).await +} + +async fn read_glob_internal( + prefix:&str, + directory:Vc, + glob:Vc, + include_dot_files:bool, +) -> Result> { + let dir = directory.read_dir().await?; + let mut result = ReadGlobResult::default(); + let glob_value = glob.await?; + match &*dir { + DirectoryContent::Entries(entries) => { + for item in entries.iter() { + match item { + (segment, DirectoryEntry::Directory(path)) => { + let full_path = format!("{prefix}{segment}"); + let full_path_prefix:RcStr = format!("{full_path}/").into(); + if glob_value.execute(&full_path) { + result + .results + .insert(full_path.clone(), DirectoryEntry::Directory(*path)); + } + if glob_value.execute(&full_path_prefix) { + result.inner.insert( + full_path, + read_glob_inner(full_path_prefix, *path, glob, include_dot_files), + ); + } + }, + (segment, entry) => { + let full_path = format!("{prefix}{segment}"); + if glob_value.execute(&full_path) { + result.results.insert(full_path, *entry); + } + }, + } + } + }, + DirectoryContent::NotFound => {}, + } + Ok(ReadGlobResult::cell(result)) +} diff --git a/crates/turbo-tasks-fs/Source/retry.rs b/crates/turbo-tasks-fs/Source/retry.rs new file mode 100644 index 0000000000000..93c12ca890dc2 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/retry.rs @@ -0,0 +1,83 @@ +use std::{future::Future, io, io::ErrorKind, path::Path, thread::sleep, time::Duration}; + +use futures_retry::{ErrorHandler, FutureRetry, RetryPolicy}; +use tokio::task::spawn_blocking; + +const MAX_RETRY_ATTEMPTS:usize = 10; + +pub(crate) async fn retry_future<'a, R, F, Fut>(func:F) -> io::Result +where + F: FnMut() -> Fut + Unpin, + Fut: Future> + 'a, { + match FutureRetry::new(func, FsRetryHandler { max_attempts:MAX_RETRY_ATTEMPTS }).await { + Ok((r, _attempts)) => Ok(r), + Err((err, _attempts)) => Err(err), + } +} + +pub(crate) async fn retry_blocking( + path:impl AsRef, + span:tracing::Span, + func:F, +) -> io::Result +where + F: Fn(&Path) -> io::Result + Send + 'static, + R: Send + 'static, { + let path = path.as_ref().to_owned(); + + let current_span = tracing::Span::current(); + asyncify(move || { + let _entered = current_span.entered(); + let _entered = span.entered(); + let mut attempt = 1; + + loop { + return match func(&path) { + Ok(r) => Ok(r), + Err(err) => { + if attempt < MAX_RETRY_ATTEMPTS && can_retry(&err) { + sleep(get_retry_wait_time(attempt)); + attempt += 1; + continue; + } + + Err(err) + }, + }; + } + }) + .await +} + +fn can_retry(err:&io::Error) -> bool { + matches!(err.kind(), ErrorKind::PermissionDenied | ErrorKind::WouldBlock) +} + +fn get_retry_wait_time(attempt:usize) -> Duration { Duration::from_millis((attempt as u64) * 100) } + +struct FsRetryHandler { + max_attempts:usize, +} + +impl ErrorHandler for FsRetryHandler { + type OutError = io::Error; + + fn handle(&mut self, attempt:usize, e:io::Error) -> RetryPolicy { + if attempt == self.max_attempts || !can_retry(&e) { + RetryPolicy::ForwardError(e) + } else { + RetryPolicy::WaitRetry(get_retry_wait_time(attempt)) + } + } +} + +// stolen from tokio::fs +async fn asyncify(f:F) -> io::Result +where + F: FnOnce() -> io::Result + Send + 'static, + T: Send + 'static, { + match spawn_blocking(f).await { + Ok(res) => res, + Err(_) => Err(io::Error::new(ErrorKind::Other, "background task failed")), + } +} diff --git a/crates/turbo-tasks-fs/Source/rope.rs b/crates/turbo-tasks-fs/Source/rope.rs new file mode 100644 index 0000000000000..cdd7ad651661a --- /dev/null +++ b/crates/turbo-tasks-fs/Source/rope.rs @@ -0,0 +1,935 @@ +use std::{ + borrow::Cow, + cmp::min, + fmt, + io::{BufRead, Read, Result as IoResult, Write}, + mem, + ops::{AddAssign, Deref}, + pin::Pin, + sync::Arc, + task::{Context as TaskContext, Poll}, +}; + +use RopeElem::{Local, Shared}; +use anyhow::{Context, Result}; +use bytes::{Buf, Bytes}; +use futures::Stream; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use tokio::io::{AsyncRead, ReadBuf}; +use turbo_tasks_hash::{DeterministicHash, DeterministicHasher}; + +static EMPTY_BUF:&[u8] = &[]; + +/// A Rope provides an efficient structure for sharing bytes/strings between +/// multiple sources. Cloning a Rope is extremely cheap (Arc and usize), and +/// sharing the contents of one Rope can be done by just cloning an Arc. +/// +/// Ropes are immutable, in order to construct one see [RopeBuilder]. +#[turbo_tasks::value(shared, serialization = "custom", eq = "manual")] +#[derive(Clone, Debug, Default)] +pub struct Rope { + /// Total length of all held bytes. + length:usize, + + /// A shareable container holding the rope's bytes. + #[turbo_tasks(debug_ignore, trace_ignore)] + data:InnerRope, +} + +/// An Arc container for ropes. This indirection allows for easily sharing the +/// contents between Ropes (and also RopeBuilders/RopeReaders). +#[derive(Clone, Debug)] +struct InnerRope(Arc<[RopeElem]>); + +/// Differentiates the types of stored bytes in a rope. +#[derive(Clone, Debug)] +enum RopeElem { + /// Local bytes are owned directly by this rope. + Local(Bytes), + + /// Shared holds the Arc container of another rope. + Shared(InnerRope), +} + +/// RopeBuilder provides a mutable container to append bytes/strings. This can +/// also append _other_ Rope instances cheaply, allowing efficient sharing of +/// the contents without a full clone of the bytes. +#[derive(Default, Debug)] +pub struct RopeBuilder { + /// Total length of all previously committed bytes. + length:usize, + + /// Immutable bytes references that have been appended to this builder. The + /// rope is the combination of all these committed bytes. + committed:Vec, + + /// Stores bytes that have been pushed, but are not yet committed. This is + /// either an attempt to push a static lifetime, or a push of owned bytes. + /// When the builder is flushed, we will commit these bytes into a real + /// Bytes instance. + uncommitted:Uncommitted, +} + +/// Stores any bytes which have been pushed, but we haven't decided to commit +/// yet. Uncommitted bytes allow us to build larger buffers out of possibly +/// small pushes. +#[derive(Default)] +enum Uncommitted { + #[default] + None, + + /// Stores our attempt to push static lifetime bytes into the rope. If we + /// build the Rope or concatenate another Rope, we can commit a static + /// Bytes reference and save memory. If not, we'll concatenate this into + /// writable bytes to be committed later. + Static(&'static [u8]), + + /// Mutable bytes collection where non-static/non-shared bytes are written. + /// This builds until the next time a static or shared bytes is + /// appended, in which case we split the buffer and commit. Finishing + /// the builder also commits these bytes. + Owned(Vec), +} + +impl Rope { + pub fn len(&self) -> usize { self.length } + + pub fn is_empty(&self) -> bool { self.length == 0 } + + /// Returns a [Read]/[AsyncRead]/[Iterator] instance over all bytes. + pub fn read(&self) -> RopeReader { RopeReader::new(&self.data, 0) } + + /// Returns a String instance of all bytes. + pub fn to_str(&self) -> Result> { self.data.to_str(self.length) } + + /// Returns a slice of all bytes + pub fn to_bytes(&self) -> Result> { self.data.to_bytes(self.length) } +} + +impl> From for Rope { + fn from(bytes:T) -> Self { + let bytes = bytes.into(); + // We can't have an InnerRope which contains an empty Local section. + if bytes.is_empty() { + Default::default() + } else { + Rope { length:bytes.len(), data:InnerRope(Arc::from([Local(bytes)])) } + } + } +} + +impl RopeBuilder { + /// Push owned bytes into the Rope. + /// + /// If possible use [push_static_bytes] or `+=` operation instead, as they + /// will create a reference to shared memory instead of cloning the bytes. + pub fn push_bytes(&mut self, bytes:&[u8]) { + if bytes.is_empty() { + return; + } + + self.uncommitted.push_bytes(bytes); + } + + /// Push static lifetime bytes into the Rope. + /// + /// This is more efficient than pushing owned bytes, because the internal + /// data does not need to be copied when the rope is read. + pub fn push_static_bytes(&mut self, bytes:&'static [u8]) { + if bytes.is_empty() { + return; + } + + // If the string is smaller than the cost of a Bytes reference (4 usizes), then + // it's more efficient to own the bytes in a new buffer. We may be able to reuse + // that buffer when more bytes are pushed. + if bytes.len() < mem::size_of::() { + return self.uncommitted.push_static_bytes(bytes); + } + + // We may have pending bytes from a prior push. + self.finish(); + + self.length += bytes.len(); + self.committed.push(Local(bytes.into())); + } + + /// Concatenate another Rope instance into our builder. + /// + /// This is much more efficient than pushing actual bytes, since we can + /// share the other Rope's references without copying the underlying data. + pub fn concat(&mut self, other:&Rope) { + if other.is_empty() { + return; + } + + // We may have pending bytes from a prior push. + self.finish(); + + self.length += other.len(); + self.committed.push(Shared(other.data.clone())); + } + + /// Writes any pending bytes into our committed queue. + /// + /// This may be called multiple times without issue. + pub fn finish(&mut self) { + if let Some(b) = self.uncommitted.finish() { + debug_assert!(!b.is_empty(), "must not have empty uncommitted bytes"); + self.length += b.len(); + self.committed.push(Local(b)); + } + } + + pub fn len(&self) -> usize { self.length + self.uncommitted.len() } + + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Constructs our final, immutable Rope instance. + pub fn build(mut self) -> Rope { + self.finish(); + Rope { length:self.length, data:InnerRope::from(self.committed) } + } +} + +impl From<&'static str> for RopeBuilder { + default fn from(bytes:&'static str) -> Self { + let mut r = RopeBuilder::default(); + r += bytes; + r + } +} + +impl From> for RopeBuilder { + fn from(bytes:Vec) -> Self { + RopeBuilder { + // Directly constructing the Uncommitted allows us to skip copying the bytes. + uncommitted:Uncommitted::from(bytes), + ..Default::default() + } + } +} + +impl Write for RopeBuilder { + fn write(&mut self, bytes:&[u8]) -> IoResult { + self.push_bytes(bytes); + Ok(bytes.len()) + } + + fn flush(&mut self) -> IoResult<()> { + self.finish(); + Ok(()) + } +} + +impl AddAssign<&'static str> for RopeBuilder { + /// Pushes a reference to static memory onto the rope. + /// + /// This is more efficient than pushing owned bytes, because the internal + /// data does not need to be copied when the rope is read. + fn add_assign(&mut self, rhs:&'static str) { self.push_static_bytes(rhs.as_bytes()); } +} + +impl AddAssign<&Rope> for RopeBuilder { + fn add_assign(&mut self, rhs:&Rope) { self.concat(rhs); } +} + +impl Uncommitted { + fn len(&self) -> usize { + match self { + Uncommitted::None => 0, + Uncommitted::Static(s) => s.len(), + Uncommitted::Owned(v) => v.len(), + } + } + + /// Pushes owned bytes, converting the current representation to an Owned if + /// it's not already. + fn push_bytes(&mut self, bytes:&[u8]) { + debug_assert!(!bytes.is_empty(), "must not push empty uncommitted bytes"); + match self { + Self::None => *self = Self::Owned(bytes.to_vec()), + Self::Static(s) => { + // If we'd previously pushed static bytes, we instead concatenate those bytes + // with the new bytes in an attempt to use less memory rather than committing 2 + // Bytes references (2 * 4 usizes). + let v = [s, bytes].concat(); + *self = Self::Owned(v); + }, + Self::Owned(v) => v.extend(bytes), + } + } + + /// Pushes static lifetime bytes, but only if the current representation is + /// None. Else, it coverts to an Owned. + fn push_static_bytes(&mut self, bytes:&'static [u8]) { + debug_assert!(!bytes.is_empty(), "must not push empty uncommitted bytes"); + match self { + // If we've not already pushed static bytes, we attempt to store the bytes for later. If + // we push owned bytes or another static bytes, then this attempt will fail and we'll + // instead concatenate into a single owned Bytes. But if we don't push anything (build + // the Rope), or concatenate another Rope (we can't join our bytes with the InnerRope of + // another Rope), we'll be able to commit a static Bytes reference and save overall + // memory (a small static Bytes reference is better than a small owned Bytes reference). + Self::None => *self = Self::Static(bytes), + _ => self.push_bytes(bytes), + } + } + + /// Converts the current uncommitted bytes into a Bytes, resetting our + /// representation to None. + fn finish(&mut self) -> Option { + match mem::take(self) { + Self::None => None, + Self::Static(s) => Some(s.into()), + Self::Owned(v) => Some(v.into()), + } + } +} + +impl fmt::Debug for Uncommitted { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Uncommitted::None => f.write_str("None"), + Uncommitted::Static(s) => { + f.debug_tuple("Static").field(&Bytes::from_static(s)).finish() + }, + Uncommitted::Owned(v) => f.debug_tuple("Owned").field(&Bytes::from(v.clone())).finish(), + } + } +} + +impl DeterministicHash for Rope { + /// Ropes with similar contents hash the same, regardless of their + /// structure. + fn deterministic_hash(&self, state:&mut H) { + state.write_usize(self.len()); + self.data.deterministic_hash(state); + } +} + +impl Serialize for Rope { + /// Ropes are always serialized into contiguous strings, because + /// deserialization won't deduplicate and share the Arcs (being the only + /// possible owner of a individual "shared" data doesn't make sense). + fn serialize(&self, serializer:S) -> Result { + use serde::ser::Error; + let s = self.to_str().map_err(Error::custom)?; + serializer.serialize_str(&s) + } +} + +impl<'de> Deserialize<'de> for Rope { + /// Deserializes strings into a contiguous, immutable Rope. + fn deserialize>(deserializer:D) -> Result { + let bytes = >::deserialize(deserializer)?; + Ok(Rope::from(bytes)) + } +} + +impl PartialEq for Rope { + // Ropes with similar contents are equals, regardless of their structure. + fn eq(&self, other:&Self) -> bool { + if Arc::ptr_eq(&self.data, &other.data) { + return true; + } + if self.len() != other.len() { + return false; + } + + // Fast path for structurally equal Ropes. With this, we can do memory reference + // checks and skip some contents equality. + let left = &self.data; + let right = &other.data; + let len = min(left.len(), right.len()); + let mut index = 0; + while index < len { + let a = &left[index]; + let b = &right[index]; + + match a.maybe_eq(b) { + // Bytes or InnerRope point to the same memory, or Bytes are contents equal. + Some(true) => index += 1, + // Bytes are not contents equal. + Some(false) => return false, + // InnerRopes point to different memory, or the Ropes weren't structurally equal. + None => break, + } + } + // If we reach the end of iteration without finding a mismatch (or early + // breaking), then we know the ropes are either equal or not equal. + if index == len { + // We know that any remaining RopeElem in the InnerRope must contain content, so + // if either one contains more RopeElem than they cannot be equal. + return left.len() == right.len(); + } + + // At this point, we need to do slower contents equality. It's possible we'll + // still get some memory reference equality for Bytes. + let mut left = RopeReader::new(left, index); + let mut right = RopeReader::new(right, index); + loop { + match (left.fill_buf(), right.fill_buf()) { + // fill_buf should always return Ok, with either some number of bytes or 0 bytes + // when consumed. + (Ok(a), Ok(b)) => { + let len = min(a.len(), b.len()); + + // When one buffer is consumed, both must be consumed. + if len == 0 { + return a.len() == b.len(); + } + + if a[0..len] != b[0..len] { + return false; + } + + left.consume(len); + right.consume(len); + }, + + // If an error is ever returned (which shouldn't happen for us) for either/both, + // then we can't prove equality. + _ => return false, + } + } + } +} + +impl Eq for Rope {} + +impl From> for Uncommitted { + fn from(bytes:Vec) -> Self { + if bytes.is_empty() { Uncommitted::None } else { Uncommitted::Owned(bytes) } + } +} + +impl InnerRope { + /// Returns a String instance of all bytes. + fn to_str(&self, len:usize) -> Result> { + match &self[..] { + [] => Ok(Cow::Borrowed("")), + [Shared(inner)] => inner.to_str(len), + [Local(bytes)] => { + let utf8 = std::str::from_utf8(bytes); + utf8.context("failed to convert rope into string").map(Cow::Borrowed) + }, + _ => { + let mut read = RopeReader::new(self, 0); + let mut string = String::with_capacity(len); + let res = read.read_to_string(&mut string); + res.context("failed to convert rope into string")?; + Ok(Cow::Owned(string)) + }, + } + } + + /// Returns a slice of all bytes. + fn to_bytes(&self, len:usize) -> Result> { + match &self[..] { + [] => Ok(Cow::Borrowed(EMPTY_BUF)), + [Shared(inner)] => inner.to_bytes(len), + [Local(bytes)] => Ok(Cow::Borrowed(bytes)), + _ => { + let mut read = RopeReader::new(self, 0); + let mut buf = Vec::with_capacity(len); + read.read_to_end(&mut buf)?; + Ok(Cow::Owned(buf)) + }, + } + } +} + +impl Default for InnerRope { + fn default() -> Self { InnerRope(Arc::from([])) } +} + +impl DeterministicHash for InnerRope { + /// Ropes with similar contents hash the same, regardless of their + /// structure. Notice the InnerRope does not contain a length (and any + /// shared InnerRopes won't either), so the exact structure isn't + /// relevant at this point. + fn deterministic_hash(&self, state:&mut H) { + for v in self.0.iter() { + v.deterministic_hash(state); + } + } +} + +impl From> for InnerRope { + fn from(els:Vec) -> Self { + if cfg!(debug_assertions) { + // It's important that an InnerRope never contain an empty Bytes section. + for el in els.iter() { + match el { + Local(b) => debug_assert!(!b.is_empty(), "must not have empty Bytes"), + Shared(s) => { + // We check whether the shared slice is empty, and not its elements. The + // only way to construct the Shared's InnerRope is + // in this mod, and we have already checked that + // none of its elements are empty. + debug_assert!(!s.is_empty(), "must not have empty InnerRope"); + }, + } + } + } + InnerRope(Arc::from(els)) + } +} + +impl Deref for InnerRope { + type Target = Arc<[RopeElem]>; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +impl RopeElem { + fn maybe_eq(&self, other:&Self) -> Option { + match (self, other) { + (Local(a), Local(b)) => { + if a.len() == b.len() { + return Some(a == b); + } + + // But if not, the rope may still be contents equal if a following section + // contains the missing bytes. + None + }, + (Shared(a), Shared(b)) => { + if Arc::ptr_eq(&a.0, &b.0) { + return Some(true); + } + + // But if not, they might still be equal and we need to fallback to slower + // equality. + None + }, + _ => None, + } + } +} + +impl DeterministicHash for RopeElem { + /// Ropes with similar contents hash the same, regardless of their + /// structure. Notice the Bytes length is not hashed, and shared InnerRopes + /// do not contain a length. + fn deterministic_hash(&self, state:&mut H) { + match self { + Local(bytes) => state.write_bytes(bytes), + Shared(inner) => inner.deterministic_hash(state), + } + } +} + +#[derive(Debug, Default)] +/// Implements the [Read]/[AsyncRead]/[Iterator] trait over a [Rope]. +pub struct RopeReader { + /// The Rope's tree is kept as a cloned stack, allowing us to accomplish + /// incremental yielding. + stack:Vec, +} + +/// A StackElem holds the current index into either a Bytes or a shared Rope. +/// When the index reaches the end of the associated data, it is removed and we +/// continue onto the next item in the stack. +#[derive(Debug)] +enum StackElem { + Local(Bytes), + Shared(InnerRope, usize), +} + +impl RopeReader { + fn new(inner:&InnerRope, index:usize) -> Self { + if index >= inner.len() { + Default::default() + } else { + RopeReader { stack:vec![StackElem::Shared(inner.clone(), index)] } + } + } + + /// A shared implementation for reading bytes. This takes the basic + /// operations needed for both Read and AsyncRead. + fn read_internal(&mut self, want:usize, buf:&mut ReadBuf<'_>) -> usize { + let mut remaining = want; + + while remaining > 0 { + let mut bytes = match self.next() { + None => break, + Some(b) => b, + }; + + let amount = min(bytes.len(), remaining); + + buf.put_slice(&bytes[0..amount]); + + if amount < bytes.len() { + bytes.advance(amount); + self.stack.push(StackElem::Local(bytes)) + } + remaining -= amount; + } + + want - remaining + } +} + +impl Iterator for RopeReader { + type Item = Bytes; + + fn next(&mut self) -> Option { + // Iterates the rope's elements recursively until we find the next Local + // section, returning its Bytes. + loop { + let (inner, mut index) = match self.stack.pop() { + None => return None, + Some(StackElem::Local(b)) => { + debug_assert!(!b.is_empty(), "must not have empty Bytes section"); + return Some(b); + }, + Some(StackElem::Shared(r, i)) => (r, i), + }; + + let el = inner[index].clone(); + index += 1; + if index < inner.len() { + self.stack.push(StackElem::Shared(inner, index)); + } + + self.stack.push(StackElem::from(el)); + } + } +} + +impl Read for RopeReader { + fn read(&mut self, buf:&mut [u8]) -> IoResult { + Ok(self.read_internal(buf.len(), &mut ReadBuf::new(buf))) + } +} + +impl AsyncRead for RopeReader { + fn poll_read( + self: Pin<&mut Self>, + _cx:&mut TaskContext<'_>, + buf:&mut ReadBuf<'_>, + ) -> Poll> { + let this = self.get_mut(); + this.read_internal(buf.remaining(), buf); + Poll::Ready(Ok(())) + } +} + +impl BufRead for RopeReader { + fn fill_buf(&mut self) -> IoResult<&[u8]> { + // Returns the full buffer without coping any data. The same bytes will + // continue to be returned until [consume] is called. + let bytes = match self.next() { + None => return Ok(EMPTY_BUF), + Some(b) => b, + }; + + // This is just so we can get a reference to the asset that is kept alive by the + // RopeReader itself. We can then auto-convert that reference into the needed u8 + // slice reference. + self.stack.push(StackElem::Local(bytes)); + let Some(StackElem::Local(bytes)) = self.stack.last() else { + unreachable!() + }; + + Ok(bytes) + } + + fn consume(&mut self, amt:usize) { + if let Some(StackElem::Local(b)) = self.stack.last_mut() { + if amt == b.len() { + self.stack.pop(); + } else { + // Consume some amount of bytes from the current Bytes instance, ensuring + // those bytes are not returned on the next call to [fill_buf]. + b.advance(amt); + } + } + } +} + +impl Stream for RopeReader { + // The Result item type is required for this to be streamable into a + // [Hyper::Body]. + type Item = Result; + + // Returns a "result" of reading the next shared bytes reference. This + // differs from [Read::read] by not copying any memory. + fn poll_next(self: Pin<&mut Self>, _cx:&mut TaskContext<'_>) -> Poll> { + let this = self.get_mut(); + Poll::Ready(this.next().map(Ok)) + } +} + +impl From for StackElem { + fn from(el:RopeElem) -> Self { + match el { + Local(bytes) => Self::Local(bytes), + Shared(inner) => Self::Shared(inner, 0), + } + } +} + +#[cfg(test)] +mod test { + use std::{ + borrow::Cow, + cmp::min, + io::{BufRead, Read}, + }; + + use anyhow::Result; + + use super::{InnerRope, Rope, RopeBuilder, RopeElem}; + + // These are intentionally not exposed, because they do inefficient conversions + // in order to fully test cases. + impl From<&str> for RopeElem { + fn from(value:&str) -> Self { RopeElem::Local(value.to_string().into()) } + } + impl From> for RopeElem { + fn from(value:Vec) -> Self { RopeElem::Shared(InnerRope::from(value)) } + } + impl From for RopeElem { + fn from(value:Rope) -> Self { RopeElem::Shared(value.data) } + } + impl Rope { + fn new(value:Vec) -> Self { + let data = InnerRope::from(value); + Rope { length:data.len(), data } + } + } + impl InnerRope { + fn len(&self) -> usize { self.iter().map(|v| v.len()).sum() } + } + impl RopeElem { + fn len(&self) -> usize { + match self { + RopeElem::Local(b) => b.len(), + RopeElem::Shared(r) => r.len(), + } + } + } + + #[test] + fn empty_build_without_pushes() { + let empty = RopeBuilder::default().build(); + let mut reader = empty.read(); + assert!(reader.next().is_none()); + } + + #[test] + fn empty_build_with_empty_static_push() { + let mut builder = RopeBuilder::default(); + builder += ""; + + let empty = builder.build(); + let mut reader = empty.read(); + assert!(reader.next().is_none()); + } + + #[test] + fn empty_build_with_empty_bytes_push() { + let mut builder = RopeBuilder::default(); + builder.push_bytes(&[]); + + let empty = builder.build(); + let mut reader = empty.read(); + assert!(reader.next().is_none()); + } + + #[test] + fn empty_build_with_empty_concat() { + let mut builder = RopeBuilder::default(); + builder += &RopeBuilder::default().build(); + + let empty = builder.build(); + let mut reader = empty.read(); + assert!(reader.next().is_none()); + } + + #[test] + fn empty_from_empty_static_str() { + let empty = Rope::from(""); + let mut reader = empty.read(); + assert!(reader.next().is_none()); + } + + #[test] + fn empty_from_empty_string() { + let empty = Rope::from("".to_string()); + let mut reader = empty.read(); + assert!(reader.next().is_none()); + } + + #[test] + fn empty_equality() { + let a = Rope::from(""); + let b = Rope::from(""); + + assert_eq!(a, b); + } + + #[test] + fn cloned_equality() { + let a = Rope::from("abc"); + let b = a.clone(); + + assert_eq!(a, b); + } + + #[test] + fn value_equality() { + let a = Rope::from("abc".to_string()); + let b = Rope::from("abc".to_string()); + + assert_eq!(a, b); + } + + #[test] + fn value_inequality() { + let a = Rope::from("abc".to_string()); + let b = Rope::from("def".to_string()); + + assert_ne!(a, b); + } + + #[test] + fn value_equality_shared_1() { + let shared = Rope::from("def"); + let a = Rope::new(vec!["abc".into(), shared.clone().into(), "ghi".into()]); + let b = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]); + + assert_eq!(a, b); + } + + #[test] + fn value_equality_shared_2() { + let a = Rope::new(vec!["abc".into(), vec!["def".into()].into(), "ghi".into()]); + let b = Rope::new(vec!["abc".into(), vec!["def".into()].into(), "ghi".into()]); + + assert_eq!(a, b); + } + + #[test] + fn value_equality_splits_1() { + let a = Rope::new(vec!["a".into(), "aa".into()]); + let b = Rope::new(vec!["aa".into(), "a".into()]); + + assert_eq!(a, b); + } + + #[test] + fn value_equality_splits_2() { + let a = Rope::new(vec![vec!["a".into()].into(), "aa".into()]); + let b = Rope::new(vec![vec!["aa".into()].into(), "a".into()]); + + assert_eq!(a, b); + } + + #[test] + fn value_inequality_shared_1() { + let shared = Rope::from("def"); + let a = Rope::new(vec!["aaa".into(), shared.clone().into(), "ghi".into()]); + let b = Rope::new(vec!["bbb".into(), shared.into(), "ghi".into()]); + + assert_ne!(a, b); + } + + #[test] + fn value_inequality_shared_2() { + let a = Rope::new(vec!["abc".into(), vec!["ddd".into()].into(), "ghi".into()]); + let b = Rope::new(vec!["abc".into(), vec!["eee".into()].into(), "ghi".into()]); + + assert_ne!(a, b); + } + + #[test] + fn value_inequality_shared_3() { + let shared = Rope::from("def"); + let a = Rope::new(vec!["abc".into(), shared.clone().into(), "ggg".into()]); + let b = Rope::new(vec!["abc".into(), shared.into(), "hhh".into()]); + + assert_ne!(a, b); + } + + #[test] + fn iteration() { + let shared = Rope::from("def"); + let rope = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]); + + let chunks = rope.read().collect::>(); + + assert_eq!(chunks, vec!["abc", "def", "ghi"]); + } + + #[test] + fn read() { + let shared = Rope::from("def"); + let rope = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]); + + let mut chunks = vec![]; + let mut buf = [0_u8; 2]; + let mut reader = rope.read(); + loop { + let amt = reader.read(&mut buf).unwrap(); + if amt == 0 { + break; + } + chunks.push(Vec::from(&buf[0..amt])); + } + + assert_eq!( + chunks, + vec![ + Vec::from(*b"ab"), + Vec::from(*b"cd"), + Vec::from(*b"ef"), + Vec::from(*b"gh"), + Vec::from(*b"i") + ] + ); + } + + #[test] + fn fill_buf() { + let shared = Rope::from("def"); + let rope = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]); + + let mut chunks = vec![]; + let mut reader = rope.read(); + loop { + let buf = reader.fill_buf().unwrap(); + if buf.is_empty() { + break; + } + let c = min(2, buf.len()); + chunks.push(Vec::from(buf)); + reader.consume(c); + } + + assert_eq!( + chunks, + // We're receiving a full buf, then only consuming 2 bytes, so we'll still get the + // third. + vec![ + Vec::from(*b"abc"), + Vec::from(*b"c"), + Vec::from(*b"def"), + Vec::from(*b"f"), + Vec::from(*b"ghi"), + Vec::from(*b"i") + ] + ); + } + + #[test] + fn test_to_bytes() -> Result<()> { + let rope = Rope::from("abc"); + assert_eq!(rope.to_bytes()?, Cow::Borrowed::<[u8]>(&[0x61, 0x62, 0x63])); + Ok(()) + } +} diff --git a/crates/turbo-tasks-fs/Source/source_context.rs b/crates/turbo-tasks-fs/Source/source_context.rs new file mode 100644 index 0000000000000..4ed78de629a14 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/source_context.rs @@ -0,0 +1,127 @@ +use std::{borrow::Cow, cmp::Ordering, fmt::Display}; + +pub enum SourceContextLine<'a> { + Context { line:usize, outside:Cow<'a, str> }, + Start { line:usize, before:Cow<'a, str>, inside:Cow<'a, str> }, + End { line:usize, inside:Cow<'a, str>, after:Cow<'a, str> }, + StartAndEnd { line:usize, before:Cow<'a, str>, inside:Cow<'a, str>, after:Cow<'a, str> }, + Inside { line:usize, inside:Cow<'a, str> }, +} + +impl<'a> Display for SourceContextLine<'a> { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SourceContextLine::Context { line, outside } => { + writeln!(f, "{line:>6} | {outside}") + }, + SourceContextLine::Start { line, before, inside } => { + writeln!(f, " | {}v{}", " ".repeat(before.len()), "-".repeat(inside.len()),)?; + writeln!(f, "{line:>6} + {before}{inside}") + }, + SourceContextLine::End { line, inside, after } => { + writeln!(f, "{line:>6} + {inside}{after}")?; + writeln!(f, " +{}^", "-".repeat(inside.len())) + }, + SourceContextLine::StartAndEnd { line, before, inside, after } => { + if inside.len() >= 2 { + writeln!( + f, + " | {}v{}v", + " ".repeat(before.len()), + "-".repeat(inside.len() - 2) + )?; + } else { + writeln!(f, " | {}v", " ".repeat(before.len()))?; + } + writeln!(f, "{line:>6} + {before}{inside}{after}")?; + if inside.len() >= 2 { + writeln!( + f, + " | {}^{}^", + " ".repeat(before.len()), + "-".repeat(inside.len() - 2), + ) + } else { + writeln!(f, " | {}^", " ".repeat(before.len())) + } + }, + SourceContextLine::Inside { line, inside } => { + writeln!(f, "{line:>6} + {inside}") + }, + } + } +} + +pub struct SourceContextLines<'a>(pub Vec>); + +impl<'a> Display for SourceContextLines<'a> { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for line in &self.0 { + write!(f, "{}", line)?; + } + Ok(()) + } +} + +/// Compute the source context for a given range of lines, including selected +/// ranges in these lines. (Lines are 0-indexed) +pub fn get_source_context<'a>( + lines:impl Iterator, + start_line:usize, + start_column:usize, + end_line:usize, + end_column:usize, +) -> SourceContextLines<'a> { + let mut result = Vec::new(); + let context_start = start_line.saturating_sub(4); + let context_end = end_line + 4; + for (i, l) in lines.enumerate().take(context_end + 1).skip(context_start) { + let n = i + 1; + fn safe_split_at(s:&str, i:usize) -> (&str, &str) { + if i < s.len() { s.split_at(s.floor_char_boundary(i)) } else { (s, "") } + } + fn limit_len(s:&str) -> Cow<'_, str> { + if s.len() < 200 { + return Cow::Borrowed(s); + } + let (a, b) = s.split_at(s.floor_char_boundary(98)); + let (_, c) = b.split_at(b.ceil_char_boundary(b.len() - 99)); + Cow::Owned(format!("{}...{}", a, c)) + } + match (i.cmp(&start_line), i.cmp(&end_line)) { + // outside + (Ordering::Less, _) | (_, Ordering::Greater) => { + result.push(SourceContextLine::Context { line:n, outside:limit_len(l) }); + }, + // start line + (Ordering::Equal, Ordering::Less) => { + let (before, inside) = safe_split_at(l, start_column); + let before = limit_len(before); + let inside = limit_len(inside); + result.push(SourceContextLine::Start { line:n, before, inside }); + }, + // start and end line + (Ordering::Equal, Ordering::Equal) => { + let real_start = l.floor_char_boundary(start_column); + let (before, temp) = safe_split_at(l, real_start); + let (inside, after) = safe_split_at(temp, end_column - real_start); + let before = limit_len(before); + let inside = limit_len(inside); + let after = limit_len(after); + result.push(SourceContextLine::StartAndEnd { line:n, before, inside, after }); + }, + // end line + (Ordering::Greater, Ordering::Equal) => { + let (inside, after) = safe_split_at(l, end_column); + let inside = limit_len(inside); + let after = limit_len(after); + result.push(SourceContextLine::End { line:n, inside, after }); + }, + // middle line + (Ordering::Greater, Ordering::Less) => { + result.push(SourceContextLine::Inside { line:n, inside:limit_len(l) }); + }, + } + } + SourceContextLines(result) +} diff --git a/crates/turbo-tasks-fs/Source/util.rs b/crates/turbo-tasks-fs/Source/util.rs new file mode 100644 index 0000000000000..d43cd1880a31c --- /dev/null +++ b/crates/turbo-tasks-fs/Source/util.rs @@ -0,0 +1,135 @@ +use std::{ + borrow::Cow, + io::{self, ErrorKind}, + path::Path, +}; + +use anyhow::{Result, anyhow}; + +/// Joins two /-separated paths into a normalized path. +/// Paths are concatenated with /. +/// +/// see also [normalize_path] for normalization. +pub fn join_path(fs_path:&str, join:&str) -> Option { + // Paths that we join are written as source code (eg, `join_path(fs_path, + // "foo/bar.js")`) and it's expected that they will never contain a + // backslash. + debug_assert!( + !join.contains('\\'), + "joined path {} must not contain a Windows directory '\\', it must be normalized to Unix \ + '/'", + join + ); + + // TODO: figure out why this freezes the benchmarks. + // // an absolute path would leave the file system root + // if Path::new(join).is_absolute() { + // return None; + // } + + if fs_path.is_empty() { + normalize_path(join) + } else if join.is_empty() { + normalize_path(fs_path) + } else { + normalize_path(&[fs_path, "/", join].concat()) + } +} + +/// Converts System paths into Unix paths. This is a noop on Unix systems, and +/// replaces backslash directory separators with forward slashes on Windows. +#[inline] +pub fn sys_to_unix(path:&str) -> Cow<'_, str> { + #[cfg(not(target_family = "windows"))] + { + Cow::from(path) + } + #[cfg(target_family = "windows")] + { + Cow::Owned(path.replace(std::path::MAIN_SEPARATOR_STR, "/")) + } +} + +/// Converts Unix paths into System paths. This is a noop on Unix systems, and +/// replaces forward slash directory separators with backslashes on Windows. +#[inline] +pub fn unix_to_sys(path:&str) -> Cow<'_, str> { + #[cfg(not(target_family = "windows"))] + { + Cow::from(path) + } + #[cfg(target_family = "windows")] + { + Cow::Owned(path.replace('/', std::path::MAIN_SEPARATOR_STR)) + } +} + +/// Normalizes a /-separated path into a form that contains no leading /, no +/// double /, no "." seqment, no ".." seqment. +/// +/// Returns None if the path would need to start with ".." to be equal. +pub fn normalize_path(str:&str) -> Option { + let mut seqments = Vec::new(); + for seqment in str.split('/') { + match seqment { + "." | "" => {}, + ".." => { + seqments.pop()?; + }, + seqment => { + seqments.push(seqment); + }, + } + } + Some(seqments.join("/")) +} + +/// Normalizes a /-separated request into a form that contains no leading /, no +/// double /, and no "." or ".." seqments in the middle of the request. A +/// request might only start with a single "." seqment and no ".." segements, or +/// any positive number of ".." seqments but no "." seqment. +pub fn normalize_request(str:&str) -> String { + let mut seqments = vec!["."]; + // Keeps track of our directory depth so that we can pop directories when + // encountering a "..". If this is positive, then we're inside a directory + // and we can pop that. If it's 0, then we can't pop the directory and we must + // keep the ".." in our seqments. This is not the same as the seqments.len(), + // because we cannot pop a kept ".." when encountering another "..". + let mut depth = 0; + let mut popped_dot = false; + for seqment in str.split('/') { + match seqment { + "." => {}, + ".." => { + if depth > 0 { + depth -= 1; + seqments.pop(); + } else { + // The first time we push a "..", we need to remove the "." we include by + // default. + if !popped_dot { + popped_dot = true; + seqments.pop(); + } + seqments.push(seqment); + } + }, + seqment => { + seqments.push(seqment); + depth += 1; + }, + } + } + seqments.join("/") +} + +/// Converts a disk access Result into a Result>, where a NotFound +/// error results in a None value. This is purely to reduce boilerplate code +/// comparing NotFound errors against all other errors. +pub fn extract_disk_access(value:io::Result, path:&Path) -> Result> { + match value { + Ok(v) => Ok(Some(v)), + Err(e) if matches!(e.kind(), ErrorKind::NotFound | ErrorKind::InvalidFilename) => Ok(None), + Err(e) => Err(anyhow!(e).context(format!("reading file {}", path.display()))), + } +} diff --git a/crates/turbo-tasks-fs/Source/virtual_fs.rs b/crates/turbo-tasks-fs/Source/virtual_fs.rs new file mode 100644 index 0000000000000..9ac4d53f627a1 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/virtual_fs.rs @@ -0,0 +1,87 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{Completion, RcStr, ValueDefault, ValueToString, Vc}; + +use super::{DirectoryContent, FileContent, FileMeta, FileSystem, FileSystemPath, LinkContent}; + +#[turbo_tasks::value] +pub struct VirtualFileSystem { + name:RcStr, +} + +impl VirtualFileSystem { + /// Creates a new [`Vc`]. + /// + /// NOTE: This function is not a `turbo_tasks::function` to avoid instances + /// being equivalent identity-wise. This ensures that a + /// [`Vc`] created from this [`Vc`] + /// will never be equivalent, nor be interoperable, with a + /// [`Vc`] created from another + /// [`Vc`]. + pub fn new() -> Vc { Self::cell(VirtualFileSystem { name:"virtual file system".into() }) } + + /// Creates a new [`Vc`] with a name. + /// + /// NOTE: This function is not a `turbo_tasks::function` to avoid instances + /// being equivalent identity-wise. This ensures that a + /// [`Vc`] created from this [`Vc`] + /// will never be equivalent, nor be interoperable, with a + /// [`Vc`] created from another + /// [`Vc`]. + pub fn new_with_name(name:RcStr) -> Vc { Self::cell(VirtualFileSystem { name }) } +} + +impl ValueDefault for VirtualFileSystem { + fn value_default() -> Vc { Self::new() } +} + +#[turbo_tasks::value_impl] +impl FileSystem for VirtualFileSystem { + #[turbo_tasks::function] + fn read(&self, _fs_path:Vc) -> Result> { + bail!("Reading is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn read_link(&self, _fs_path:Vc) -> Result> { + bail!("Reading is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn read_dir(&self, _fs_path:Vc) -> Result> { + bail!("Reading is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn track(&self, _fs_path:Vc) -> Result> { + bail!("Tracking is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn write( + &self, + _fs_path:Vc, + _content:Vc, + ) -> Result> { + bail!("Writing is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn write_link( + &self, + _fs_path:Vc, + _target:Vc, + ) -> Result> { + bail!("Writing is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn metadata(&self, _fs_path:Vc) -> Result> { + bail!("Reading is not possible on the virtual file system") + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for VirtualFileSystem { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { Vc::cell(self.name.clone()) } +} diff --git a/crates/turbo-tasks-fs/Source/watcher.rs b/crates/turbo-tasks-fs/Source/watcher.rs new file mode 100644 index 0000000000000..729be3dd29c04 --- /dev/null +++ b/crates/turbo-tasks-fs/Source/watcher.rs @@ -0,0 +1,470 @@ +use std::{ + collections::{HashMap, HashSet}, + mem::take, + path::{Path, PathBuf}, + sync::{ + Arc, + Mutex, + mpsc::{Receiver, RecvError, TryRecvError, channel}, + }, + time::Duration, +}; + +use anyhow::Result; +use notify::{ + EventKind, + RecommendedWatcher, + RecursiveMode, + Watcher, + event::{MetadataKind, ModifyKind, RenameMode}, +}; +use notify_debouncer_full::{DebounceEventResult, DebouncedEvent, Debouncer, FileIdMap}; +use serde::{Deserialize, Serialize}; +use tokio::sync::RwLock; +use tracing::instrument; +use turbo_tasks::{Invalidator, RcStr, spawn_thread}; + +use crate::{ + format_absolute_fs_path, + invalidation::{WatchChange, WatchStart}, + invalidator_map::InvalidatorMap, + path_to_key, +}; + +#[derive(Default, Serialize, Deserialize)] +pub(crate) struct DiskWatcher { + #[serde(skip)] + watcher:Mutex>>, + + /// Array of paths that should not notify invalidations. + /// `notify` currently doesn't support unwatching subpaths from the root, + /// so underlying we still watches filesystem event but only skips to + /// invalidate. + ignored_subpaths:Vec, + + /// Keeps track of which directories are currently watched. This is only + /// used on OSs that doesn't support recursive watching. + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + #[serde(skip)] + watching:dashmap::DashSet, +} + +impl DiskWatcher { + pub(crate) fn new(ignored_subpaths:Vec) -> Self { + Self { ignored_subpaths, ..Default::default() } + } + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + pub(crate) fn restore_if_watching(&self, dir_path:&Path, root_path:&Path) -> Result<()> { + if self.watching.contains(dir_path) { + let mut watcher = self.watcher.lock().unwrap(); + self.start_watching_dir(&mut watcher, dir_path, root_path)?; + } + Ok(()) + } + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + pub(crate) fn ensure_watching(&self, dir_path:&Path, root_path:&Path) -> Result<()> { + if self.watching.contains(dir_path) { + return Ok(()); + } + let mut watcher = self.watcher.lock().unwrap(); + if self.watching.insert(dir_path.to_path_buf()) { + self.start_watching_dir(&mut watcher, dir_path, root_path)?; + } + Ok(()) + } + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + fn start_watching_dir( + &self, + watcher:&mut std::sync::MutexGuard>>, + dir_path:&Path, + root_path:&Path, + ) -> Result<()> { + use anyhow::Context; + + if let Some(watcher) = watcher.as_mut() { + let mut path = dir_path; + while let Err(err) = watcher.watcher().watch(path, RecursiveMode::NonRecursive) { + if path == root_path { + return Err(err).context(format!( + "Unable to watch {} (tried up to {})", + dir_path.display(), + path.display() + )); + } + let Some(parent_path) = path.parent() else { + return Err(err).context(format!( + "Unable to watch {} (tried up to {})", + dir_path.display(), + path.display() + )); + }; + path = parent_path; + } + } + Ok(()) + } + + /// Create a watcher and start watching by creating `debounced` watcher + /// via `full debouncer` + /// + /// `notify` provides 2 different debouncer implementations, `-full` + /// provides below differences for the easy of use: + /// + /// - Only emits a single Rename event if the rename From and To events can + /// be matched + /// - Merges multiple Rename events + /// - Takes Rename events into account and updates paths for events that + /// occurred before the rename event, but which haven't been emitted, yet + /// - Optionally keeps track of the file system IDs all files and stitches + /// rename events together (FSevents, Windows) + /// - Emits only one Remove event when deleting a directory (inotify) + /// - Doesn't emit duplicate create events + /// - Doesn't emit Modify events after a Create event + pub(crate) fn start_watching( + self: Arc, + name:RcStr, + root_path:PathBuf, + report_invalidation_reason:Option<(RcStr, PathBuf)>, + invalidation_lock:Arc>, + invalidator_map:Arc, + dir_invalidator_map:Arc, + ) -> Result<()> { + let mut watcher_guard = self.watcher.lock().unwrap(); + if watcher_guard.is_some() { + return Ok(()); + } + + // Create a channel to receive the events. + let (tx, rx) = channel(); + // Linux watching is too fast, so we need to throttle it a bit to avoid reading + // wip files + #[cfg(target_os = "linux")] + let delay = Duration::from_millis(10); + #[cfg(not(target_os = "linux"))] + let delay = Duration::from_millis(1); + // Create a watcher object, delivering debounced events. + // The notification back-end is selected based on the platform. + let mut debounced_watcher = notify_debouncer_full::new_debouncer(delay, None, tx)?; + // Add a path to be watched. All files and directories at that path and + // below will be monitored for changes. + #[cfg(any(target_os = "macos", target_os = "windows"))] + { + debounced_watcher.watcher().watch(&root_path, RecursiveMode::Recursive)?; + } + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + for dir_path in self.watching.iter() { + debounced_watcher.watcher().watch(&dir_path, RecursiveMode::NonRecursive)?; + } + + // We need to invalidate all reads that happened before watching + // Best is to start_watching before starting to read + for invalidator in take(&mut *invalidator_map.lock().unwrap()) + .into_iter() + .chain(take(&mut *dir_invalidator_map.lock().unwrap()).into_iter()) + .flat_map(|(_, invalidators)| invalidators.into_iter()) + { + if report_invalidation_reason.is_some() { + invalidator.invalidate_with_reason(WatchStart { name:name.clone() }) + } else { + invalidator.invalidate(); + } + } + + watcher_guard.replace(debounced_watcher); + drop(watcher_guard); + + spawn_thread(move || { + self.watch_thread( + rx, + root_path, + report_invalidation_reason, + invalidation_lock, + invalidator_map, + dir_invalidator_map, + ) + }); + + Ok(()) + } + + pub(crate) fn stop_watching(&self) { + if let Some(watcher) = self.watcher.lock().unwrap().take() { + drop(watcher); + // thread will detect the stop because the channel is disconnected + } + } + + /// Internal thread that processes the events from the watcher + /// and invalidates the cache. + /// + /// Should only be called once from `start_watching`. + fn watch_thread( + &self, + rx:Receiver, + root_path:PathBuf, + report_invalidation_reason:Option<(RcStr, PathBuf)>, + invalidation_lock:Arc>, + invalidator_map:Arc, + dir_invalidator_map:Arc, + ) { + let mut batched_invalidate_path = HashSet::new(); + let mut batched_invalidate_path_dir = HashSet::new(); + let mut batched_invalidate_path_and_children = HashSet::new(); + let mut batched_invalidate_path_and_children_dir = HashSet::new(); + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + let mut batched_new_paths = HashSet::new(); + + 'outer: loop { + let mut event = rx.recv().map_err(|e| { + match e { + RecvError => TryRecvError::Disconnected, + } + }); + loop { + match event { + Ok(Ok(events)) => { + events.iter().for_each( + |DebouncedEvent { + event: notify::Event { kind, paths, .. }, .. + }| { + let paths:Vec = paths + .iter() + .filter(|p| { + !self + .ignored_subpaths + .iter() + .any(|ignored| p.starts_with(ignored)) + }) + .cloned() + .collect(); + + if paths.is_empty() { + return; + } + + // [NOTE] there is attrs in the `Event` struct, which contains few + // more metadata like process_id who triggered the event, + // or the source we may able to utilize later. + match kind { + // [NOTE] Observing `ModifyKind::Metadata(MetadataKind::Any)` is + // not a mistake, fix for PACK-2437. + // In here explicitly subscribes to the `ModifyKind::Data` which + // indicates file content changes - in case of fsevents backend, + // this is `kFSEventStreamEventFlagItemModified`. + // Also meanwhile we subscribe to ModifyKind::Metadata as well. + // This is due to in some cases fsevents does not emit explicit + // kFSEventStreamEventFlagItemModified kernel events, + // but only emits kFSEventStreamEventFlagItemInodeMetaMod. While + // this could cause redundant invalidation, + // it's the way to reliably detect file content changes. + // ref other implementation, i.e libuv does same thing to + // trigger UV_CHANEGS https://github.com/libuv/libuv/commit/73cf3600d75a5884b890a1a94048b8f3f9c66876#diff-e12fdb1f404f1c97bbdcc0956ac90d7db0d811d9fa9ca83a3deef90c937a486cR95-R99 + EventKind::Modify( + ModifyKind::Data(_) + | ModifyKind::Metadata(MetadataKind::Any), + ) => { + batched_invalidate_path.extend(paths.clone()); + }, + EventKind::Create(_) => { + batched_invalidate_path_and_children.extend(paths.clone()); + batched_invalidate_path_and_children_dir + .extend(paths.clone()); + paths.iter().for_each(|path| { + if let Some(parent) = path.parent() { + batched_invalidate_path_dir + .insert(PathBuf::from(parent)); + } + }); + + #[cfg(not(any( + target_os = "macos", + target_os = "windows" + )))] + batched_new_paths.extend(paths.clone()); + }, + EventKind::Remove(_) => { + batched_invalidate_path_and_children.extend(paths.clone()); + batched_invalidate_path_and_children_dir + .extend(paths.clone()); + paths.iter().for_each(|path| { + if let Some(parent) = path.parent() { + batched_invalidate_path_dir + .insert(PathBuf::from(parent)); + } + }); + }, + // A single event emitted with both the `From` and `To` paths. + EventKind::Modify(ModifyKind::Name(RenameMode::Both)) => { + // For the rename::both, notify provides an array of paths + // in given order + if let [source, destination, ..] = &paths[..] { + batched_invalidate_path_and_children + .insert(source.clone()); + if let Some(parent) = source.parent() { + batched_invalidate_path_dir + .insert(PathBuf::from(parent)); + } + batched_invalidate_path_and_children + .insert(destination.clone()); + if let Some(parent) = destination.parent() { + batched_invalidate_path_dir + .insert(PathBuf::from(parent)); + } + #[cfg(not(any( + target_os = "macos", + target_os = "windows" + )))] + batched_new_paths.insert(destination.clone()); + } else { + // If we hit here, we expect this as a bug either in + // notify or system weirdness. + panic!( + "Rename event does not contain source and \ + destination paths {:#?}", + paths + ); + } + }, + // We expect `RenameMode::Both` to cover most of the cases we + // need to invalidate, + // but we also check other RenameModes + // to cover cases where notify couldn't match the two rename + // events. + EventKind::Any + | EventKind::Modify(ModifyKind::Any | ModifyKind::Name(..)) => { + batched_invalidate_path.extend(paths.clone()); + batched_invalidate_path_and_children.extend(paths.clone()); + batched_invalidate_path_and_children_dir + .extend(paths.clone()); + for parent in paths.iter().filter_map(|path| path.parent()) + { + batched_invalidate_path_dir + .insert(PathBuf::from(parent)); + } + }, + EventKind::Modify( + ModifyKind::Metadata(..) | ModifyKind::Other, + ) + | EventKind::Access(_) + | EventKind::Other => { + // ignored + }, + } + }, + ); + }, + // Error raised by notify watcher itself + Ok(Err(errors)) => { + errors.iter().for_each(|notify::Error { kind, paths }| { + println!("watch error ({:?}): {:?} ", paths, kind); + + if paths.is_empty() { + batched_invalidate_path_and_children.insert(root_path.clone()); + batched_invalidate_path_and_children_dir.insert(root_path.clone()); + } else { + batched_invalidate_path_and_children.extend(paths.clone()); + batched_invalidate_path_and_children_dir.extend(paths.clone()); + } + }); + }, + Err(TryRecvError::Disconnected) => { + // Sender has been disconnected + // which means DiskFileSystem has been dropped + // exit thread + break 'outer; + }, + Err(TryRecvError::Empty) => { + break; + }, + } + event = rx.try_recv(); + } + + // We need to start watching first before invalidating the changed paths + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + { + for path in batched_new_paths.drain() { + let _ = self.restore_if_watching(&path, &root_path); + } + } + + let _lock = invalidation_lock.blocking_write(); + { + let mut invalidator_map = invalidator_map.lock().unwrap(); + invalidate_path( + &report_invalidation_reason, + &mut invalidator_map, + batched_invalidate_path.drain(), + ); + invalidate_path_and_children_execute( + &report_invalidation_reason, + &mut invalidator_map, + batched_invalidate_path_and_children.drain(), + ); + } + { + let mut dir_invalidator_map = dir_invalidator_map.lock().unwrap(); + invalidate_path( + &report_invalidation_reason, + &mut dir_invalidator_map, + batched_invalidate_path_dir.drain(), + ); + invalidate_path_and_children_execute( + &report_invalidation_reason, + &mut dir_invalidator_map, + batched_invalidate_path_and_children_dir.drain(), + ); + } + } + } +} + +#[instrument(parent = None, level = "info", name = "DiskFileSystem file change", skip_all, fields(name = display(path.display())))] +fn invalidate( + report_invalidation_reason:&Option<(RcStr, PathBuf)>, + path:&Path, + invalidator:Invalidator, +) { + if let Some((name, root_path)) = report_invalidation_reason { + if let Some(path) = format_absolute_fs_path(path, name, root_path) { + invalidator.invalidate_with_reason(WatchChange { path }); + return; + } + } + invalidator.invalidate(); +} + +fn invalidate_path( + report_invalidation_reason:&Option<(RcStr, PathBuf)>, + invalidator_map:&mut HashMap>, + paths:impl Iterator, +) { + for path in paths { + let key = path_to_key(&path); + if let Some(invalidators) = invalidator_map.remove(&key) { + invalidators + .into_iter() + .for_each(|i| invalidate(report_invalidation_reason, &path, i)); + } + } +} + +fn invalidate_path_and_children_execute( + report_invalidation_reason:&Option<(RcStr, PathBuf)>, + invalidator_map:&mut HashMap>, + paths:impl Iterator, +) { + for path in paths { + let path_key = path_to_key(&path); + for (_, invalidators) in invalidator_map.extract_if(|key, _| key.starts_with(&path_key)) { + invalidators + .into_iter() + .for_each(|i| invalidate(report_invalidation_reason, &path, i)); + } + } +} diff --git a/crates/turbo-tasks-fs/benches/mod.rs b/crates/turbo-tasks-fs/benches/mod.rs new file mode 100644 index 0000000000000..83194b96d8ac4 --- /dev/null +++ b/crates/turbo-tasks-fs/benches/mod.rs @@ -0,0 +1,105 @@ +use std::{ + fs, + sync::{Arc, mpsc::channel}, + thread, + time::{Duration, Instant}, +}; + +use criterion::{ + BenchmarkId, + Criterion, + criterion_group, + criterion_main, + measurement::{Measurement, WallTime}, +}; +use notify_debouncer_full::{ + new_debouncer, + notify::{RecursiveMode, Watcher}, +}; +use tokio::runtime::Runtime; +use turbo_tasks::event::Event; +use turbo_tasks_fs::rope::{Rope, RopeBuilder}; + +fn bench_file_watching(c:&mut Criterion) { + let mut g = c.benchmark_group("turbo-tasks-fs"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(10)); + + let temp = tempfile::TempDir::new().unwrap(); + let start = Instant::now(); + let temp_path = temp.path(); + fs::write(temp_path.join("file.txt"), start.elapsed().as_micros().to_string()).unwrap(); + + g.bench_function(BenchmarkId::new("bench_file_watching", "change file"), move |b| { + let (tx, rx) = channel(); + let event = Arc::new(Event::new(|| "test event".to_string())); + + let mut watcher = new_debouncer(Duration::from_micros(1), None, tx).unwrap(); + watcher.watcher().watch(temp_path, RecursiveMode::Recursive).unwrap(); + + let t = thread::spawn({ + let event = event.clone(); + move || { + loop { + match rx.recv() { + Ok(_) => event.notify(usize::MAX), + Err(_) => return, + } + } + } + }); + + b.to_async(Runtime::new().unwrap()).iter_custom(move |iters| { + let event = event.clone(); + async move { + let m = WallTime; + let mut value = m.zero(); + for _ in 0..iters { + std::thread::sleep(Duration::from_millis(1)); + let l = event.listen(); + let path = temp_path.join("file.txt"); + let content = start.elapsed().as_micros().to_string(); + let s = m.start(); + fs::write(path, content).unwrap(); + l.await; + let duration = m.end(s); + value = m.add(&value, &duration); + } + value + } + }); + + drop(watcher); + t.join().unwrap(); + }); +} + +fn bench_rope_iteration(c:&mut Criterion) { + let mut g = c.benchmark_group("turbo-tasks-fs"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(10)); + + g.bench_function(BenchmarkId::new("bench_rope_iteration", "next collect"), move |b| { + b.iter(|| { + let mut root = RopeBuilder::default(); + for _ in 0..5 { + let mut inner = RopeBuilder::default(); + for _ in 0..5 { + let r = Rope::from("abc".to_string().into_bytes()); + inner += &r; + } + root += &inner.build(); + } + + let rope = root.build(); + let _v = rope.read().collect::>(); + }) + }); +} + +criterion_group!( + name = benches; + config = Criterion::default(); + targets = bench_file_watching, bench_rope_iteration +); +criterion_main!(benches); diff --git a/crates/turbo-tasks-fs/build.rs b/crates/turbo-tasks-fs/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbo-tasks-fs/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbo-tasks-fs/examples/hash_directory.rs b/crates/turbo-tasks-fs/examples/hash_directory.rs new file mode 100644 index 0000000000000..50c8580b5dca0 --- /dev/null +++ b/crates/turbo-tasks-fs/examples/hash_directory.rs @@ -0,0 +1,117 @@ +#![feature(trivial_bounds)] + +use std::{ + collections::BTreeMap, + env::current_dir, + io::Read, + time::{Duration, Instant}, +}; + +use anyhow::Result; +use sha2::{Digest, Sha256}; +use turbo_tasks::{RcStr, TurboTasks, UpdateInfo, Vc, util::FormatDuration}; +use turbo_tasks_fs::{ + DirectoryContent, + DirectoryEntry, + DiskFileSystem, + FileContent, + FileSystem, + FileSystemPath, + register, +}; +use turbo_tasks_memory::MemoryBackend; + +#[tokio::main] +async fn main() -> Result<()> { + register(); + include!(concat!(env!("OUT_DIR"), "/register_example_hash_directory.rs")); + + let tt = TurboTasks::new(MemoryBackend::default()); + let start = Instant::now(); + + let task = tt.spawn_root_task(|| { + Box::pin(async { + let root = current_dir().unwrap().to_str().unwrap().into(); + let disk_fs = DiskFileSystem::new("project".into(), root, vec![]); + disk_fs.await?.start_watching()?; + + // Smart Pointer cast + let fs:Vc> = Vc::upcast(disk_fs); + let input = fs.root().join("demo".into()); + let dir_hash = hash_directory(input); + print_hash(dir_hash).await?; + Ok::, _>(Default::default()) + }) + }); + tt.wait_task_completion(task, true).await.unwrap(); + println!("done in {}", FormatDuration(start.elapsed())); + + loop { + let UpdateInfo { duration, tasks, .. } = + tt.get_or_wait_aggregated_update_info(Duration::from_millis(100)).await; + println!("updated {} tasks in {}", tasks, FormatDuration(duration)); + } +} + +#[turbo_tasks::function] +async fn print_hash(dir_hash:Vc) -> Result> { + println!("DIR HASH: {}", dir_hash.await?.as_str()); + Ok(Default::default()) +} + +async fn filename(path:Vc) -> Result { + Ok(path.await?.path.split('/').last().unwrap().to_string()) +} + +#[turbo_tasks::function] +async fn hash_directory(directory:Vc) -> Result> { + let dir_path = &directory.await?.path; + let content = directory.read_dir(); + let mut hashes = BTreeMap::new(); + match &*content.await? { + DirectoryContent::Entries(entries) => { + for entry in entries.values() { + match entry { + DirectoryEntry::File(path) => { + let name = filename(*path).await?; + hashes.insert(name, hash_file(*path).await?.clone_value()); + }, + DirectoryEntry::Directory(path) => { + let name = filename(*path).await?; + hashes.insert(name, hash_directory(*path).await?.clone_value()); + }, + _ => {}, + } + } + }, + DirectoryContent::NotFound => { + println!("{}: not found", directory.await?.path); + }, + }; + let hash = hash_content(&mut hashes.into_values().collect::>().join(",").as_bytes()); + println!("hash_directory({})", dir_path); + Ok(hash) +} + +#[turbo_tasks::function] +async fn hash_file(file_path:Vc) -> Result> { + let content = file_path.read().await?; + Ok(match &*content { + FileContent::Content(file) => hash_content(&mut file.read()), + FileContent::NotFound => { + // report error + Vc::cell(Default::default()) + }, + }) +} + +fn hash_content(content:&mut R) -> Vc { + let mut hasher = Sha256::new(); + let mut buf = [0; 1024]; + while let Ok(size) = content.read(&mut buf) { + hasher.update(&buf[0..size]); + } + let result = format!("{:x}", hasher.finalize()); + + Vc::cell(result.into()) +} diff --git a/crates/turbo-tasks-fs/examples/hash_glob.rs b/crates/turbo-tasks-fs/examples/hash_glob.rs new file mode 100644 index 0000000000000..4fcc4972826b5 --- /dev/null +++ b/crates/turbo-tasks-fs/examples/hash_glob.rs @@ -0,0 +1,111 @@ +#![feature(trivial_bounds)] + +use std::{ + collections::BTreeMap, + env::current_dir, + io::Read, + time::{Duration, Instant}, +}; + +use anyhow::Result; +use sha2::{Digest, Sha256}; +use turbo_tasks::{RcStr, TurboTasks, UpdateInfo, Vc, util::FormatDuration}; +use turbo_tasks_fs::{ + DirectoryEntry, + DiskFileSystem, + FileContent, + FileSystem, + FileSystemPath, + ReadGlobResult, + glob::Glob, + register, +}; +use turbo_tasks_memory::MemoryBackend; + +#[tokio::main] +async fn main() -> Result<()> { + register(); + include!(concat!(env!("OUT_DIR"), "/register_example_hash_glob.rs")); + + let tt = TurboTasks::new(MemoryBackend::default()); + let start = Instant::now(); + + let task = tt.spawn_root_task(|| { + Box::pin(async { + let root = current_dir().unwrap().to_str().unwrap().into(); + let disk_fs = DiskFileSystem::new("project".into(), root, vec![]); + disk_fs.await?.start_watching()?; + + // Smart Pointer cast + let fs:Vc> = Vc::upcast(disk_fs); + let input = fs.root().join("crates".into()); + let glob = Glob::new("**/*.rs".into()); + let glob_result = input.read_glob(glob, true); + let dir_hash = hash_glob_result(glob_result); + print_hash(dir_hash).await?; + Ok::, _>(Default::default()) + }) + }); + tt.wait_task_completion(task, true).await.unwrap(); + println!("done in {}", FormatDuration(start.elapsed())); + + loop { + let UpdateInfo { duration, tasks, .. } = + tt.get_or_wait_aggregated_update_info(Duration::from_millis(100)).await; + println!("updated {} tasks in {}", tasks, FormatDuration(duration)); + } +} + +#[turbo_tasks::function] +pub fn empty_string() -> Vc { Vc::cell(Default::default()) } + +#[turbo_tasks::function] +async fn print_hash(dir_hash:Vc) -> Result> { + println!("DIR HASH: {}", dir_hash.await?.as_str()); + Ok(Default::default()) +} + +#[turbo_tasks::function] +async fn hash_glob_result(result:Vc) -> Result> { + let result = result.await?; + let mut hashes = BTreeMap::new(); + for (name, entry) in result.results.iter() { + if let DirectoryEntry::File(path) = entry { + hashes.insert(name, hash_file(*path).await?.clone_value()); + } + } + for (name, result) in result.inner.iter() { + let hash = hash_glob_result(*result).await?; + if !hash.is_empty() { + hashes.insert(name, hash.clone_value()); + } + } + if hashes.is_empty() { + return Ok(empty_string()); + } + let hash = hash_content(&mut hashes.into_values().collect::>().join(",").as_bytes()); + Ok(hash) +} + +#[turbo_tasks::function] +async fn hash_file(file_path:Vc) -> Result> { + let content = file_path.read().await?; + Ok(match &*content { + FileContent::Content(file) => hash_content(&mut file.read()), + FileContent::NotFound => { + // report error + Vc::cell(Default::default()) + }, + }) +} + +fn hash_content(content:&mut R) -> Vc { + let mut hasher = Sha256::new(); + let mut buf = [0; 1024]; + while let Ok(size) = content.read(&mut buf) { + hasher.update(&buf[0..size]); + } + let result = format!("{:x}", hasher.finalize()); + + Vc::cell(result.into()) +} diff --git a/crates/turbo-tasks-hash/Source/deterministic_hash.rs b/crates/turbo-tasks-hash/Source/deterministic_hash.rs new file mode 100644 index 0000000000000..2295155bbf543 --- /dev/null +++ b/crates/turbo-tasks-hash/Source/deterministic_hash.rs @@ -0,0 +1,196 @@ +use std::mem::Discriminant; + +pub use turbo_tasks_macros::DeterministicHash; + +macro_rules! deterministic_hash_number { + ($(($ty:ident, $meth:ident),)*) => {$( + impl DeterministicHash for $ty { + fn deterministic_hash(&self, state: &mut H) { + state.$meth(*self); + } + } + )*} +} + +macro_rules! impl_write_number { + ($(($ty:ident, $meth:ident),)*) => {$( + /// Writes a single `$ty` to this hasher + #[inline] + fn $meth(&mut self, i: $ty) { + // Apple silicon and Intel chips both use little endian, so this should be fast. + let little_endian = i.to_le_bytes(); + self.write_bytes(&little_endian); + } + )*} +} + +/// DeterministicHash is a custom trait that signals the implementor can safely +/// be hashed in a replicatable way across platforms and process runs. Note that +/// the default Hash trait used by Rust is not deterministic for our purposes. +/// +/// It's very important that Vcs never implement this, since they cannot be +/// deterministic. The value that they wrap, however, can implement the trait. +pub trait DeterministicHash { + /// Adds self's bytes to the [Hasher] state, in a way that is replicatable + /// on any platform or process run. + fn deterministic_hash(&self, state:&mut H); +} + +/// DeterministicHasher is a custom trait that signals the implementor can +/// safely hash in a replicatable way across platforms and process runs. Note +/// that the default Hasher trait used by Rust allows for non-deterministic +/// hashing, so it is not suitable for our purposes. +pub trait DeterministicHasher { + fn finish(&self) -> u64; + fn write_bytes(&mut self, bytes:&[u8]); + + /// Writes a single `u8` to this hasher + #[inline] + fn write_u8(&mut self, i:u8) { self.write_bytes(&[i]); } + + /// Writes a single `usize` to this hasher + #[inline] + fn write_usize(&mut self, i:usize) { + // usize can be 4 or 8 bytes, standardize on the larger. + // As long as the original value is smaller than 4 bytes, the two will hash + // equivalently. + self.write_u64(i as u64); + } + + /// Writes a single `isize` to this hasher + #[inline] + fn write_isize(&mut self, i:isize) { + // isize can be 4 or 8 bytes, standardize on the larger. + // As long as the original value is smaller than 4 bytes, the two will hash + // equivalently. + self.write_i64(i as i64); + } + + impl_write_number! { + (u16, write_u16), + (u32, write_u32), + (u64, write_u64), + (i8, write_i8), + (i16, write_i16), + (i32, write_i32), + (i64, write_i64), + (u128, write_u128), + (i128, write_i128), + } +} + +deterministic_hash_number! { + (u8, write_u8), + (u16, write_u16), + (u32, write_u32), + (u64, write_u64), + (usize, write_usize), + (i8, write_i8), + (i16, write_i16), + (i32, write_i32), + (i64, write_i64), + (isize, write_isize), + (u128, write_u128), + (i128, write_i128), +} + +impl DeterministicHash for &T { + fn deterministic_hash(&self, state:&mut H) { + (**self).deterministic_hash(state); + } +} + +impl DeterministicHash for [u8] { + fn deterministic_hash(&self, state:&mut H) { + state.write_usize(self.len()); + state.write_bytes(self); + } +} + +impl DeterministicHash for String { + fn deterministic_hash(&self, state:&mut H) { + state.write_usize(self.len()); + state.write_bytes(self.as_bytes()); + } +} + +impl DeterministicHash for &str { + fn deterministic_hash(&self, state:&mut H) { + state.write_usize(self.len()); + state.write_bytes(self.as_bytes()); + } +} + +impl DeterministicHash for bool { + fn deterministic_hash(&self, state:&mut H) { + state.write_u8(*self as u8); + } +} + +impl DeterministicHash for Option { + fn deterministic_hash(&self, state:&mut H) { + match self { + None => state.write_u8(0), + Some(v) => { + state.write_u8(1); + v.deterministic_hash(state); + }, + } + } +} + +impl DeterministicHash for Vec { + fn deterministic_hash(&self, state:&mut H) { + state.write_usize(self.len()); + for v in self { + v.deterministic_hash(state); + } + } +} + +macro_rules! tuple_impls { + ( $( $name:ident )+ ) => { + impl<$($name: DeterministicHash),+> DeterministicHash for ($($name,)+) + { + #[allow(non_snake_case)] + fn deterministic_hash(&self, state: &mut Hasher) { + let ($(ref $name,)+) = *self; + $($name.deterministic_hash(state);)+ + } + } + }; +} + +// Implement `DeterministicHash` for all tuples of 1 to 12 elements. +tuple_impls! { A } +tuple_impls! { A B } +tuple_impls! { A B C } +tuple_impls! { A B C D } +tuple_impls! { A B C D E } +tuple_impls! { A B C D E F } +tuple_impls! { A B C D E F G } +tuple_impls! { A B C D E F G H } +tuple_impls! { A B C D E F G H I } +tuple_impls! { A B C D E F G H I J } +tuple_impls! { A B C D E F G H I J K } +tuple_impls! { A B C D E F G H I J K L } + +/// HasherWrapper allows the DeterministicHasher to be used as a Hasher, for +/// standard types that do not allow us to directly access their internals. +struct HasherWrapper<'a, D:DeterministicHasher>(&'a mut D); +impl<'a, D:DeterministicHasher> std::hash::Hasher for HasherWrapper<'a, D> { + fn write(&mut self, bytes:&[u8]) { self.0.write_bytes(bytes); } + + fn finish(&self) -> u64 { + unimplemented!(); + } +} + +impl DeterministicHash for Discriminant { + fn deterministic_hash(&self, state:&mut H) { + // The Discriminant does not allow us to access its internal state, but does + // allow us to Hash it. + let mut wrapper = HasherWrapper(state); + std::hash::Hash::hash(self, &mut wrapper); + } +} diff --git a/crates/turbo-tasks-hash/Source/hex.rs b/crates/turbo-tasks-hash/Source/hex.rs new file mode 100644 index 0000000000000..6dd37ed5e56a1 --- /dev/null +++ b/crates/turbo-tasks-hash/Source/hex.rs @@ -0,0 +1,2 @@ +/// Encodes a 64-bit unsigned integer into a hex string. +pub fn encode_hex(n:u64) -> String { format!("{:01$x}", n, std::mem::size_of::() * 2) } diff --git a/crates/turbo-tasks-hash/Source/lib.rs b/crates/turbo-tasks-hash/Source/lib.rs new file mode 100644 index 0000000000000..4dc7a088aca2d --- /dev/null +++ b/crates/turbo-tasks-hash/Source/lib.rs @@ -0,0 +1,17 @@ +//! Hashing and encoding functions for turbopack. +//! +//! An example use of this module is hashing a file's content for cache +//! invalidation, and encoding the hash to an hexadecimal string for use in a +//! file name. + +mod deterministic_hash; +mod hex; +mod md4; +mod xxh3_hash64; + +pub use crate::{ + deterministic_hash::{DeterministicHash, DeterministicHasher}, + hex::encode_hex, + md4::hash_md4, + xxh3_hash64::{Xxh3Hash64Hasher, hash_xxh3_hash64}, +}; diff --git a/crates/turbo-tasks-hash/Source/md4.rs b/crates/turbo-tasks-hash/Source/md4.rs new file mode 100644 index 0000000000000..f66b4c74be03f --- /dev/null +++ b/crates/turbo-tasks-hash/Source/md4.rs @@ -0,0 +1,6 @@ +use md4::Digest; + +/// Hash some content with the MD4 cryptographic hash function. +/// +/// Returns a 16-byte hash digest. +pub fn hash_md4(content:&[u8]) -> [u8; 16] { md4::Md4::digest(content).into() } diff --git a/crates/turbo-tasks-hash/Source/xxh3_hash64.rs b/crates/turbo-tasks-hash/Source/xxh3_hash64.rs new file mode 100644 index 0000000000000..7bfa3f8e6040b --- /dev/null +++ b/crates/turbo-tasks-hash/Source/xxh3_hash64.rs @@ -0,0 +1,41 @@ +use std::hash::Hasher; + +use twox_hash::xxh3; + +use crate::{DeterministicHash, DeterministicHasher}; + +/// Hash some content with the Xxh3Hash64 non-cryptographic hash function. +pub fn hash_xxh3_hash64(input:T) -> u64 { + let mut hasher = Xxh3Hash64Hasher::new(); + input.deterministic_hash(&mut hasher); + hasher.finish() +} + +/// Xxh3Hash64 hasher. +pub struct Xxh3Hash64Hasher(xxh3::Hash64); + +impl Xxh3Hash64Hasher { + /// Create a new hasher. + pub fn new() -> Self { Self(xxh3::Hash64::with_seed(0)) } + + /// Uses the DeterministicHash trait to hash the input in a + /// cross-platform way. + pub fn write_value(&mut self, input:T) { input.deterministic_hash(self); } + + /// Uses the DeterministicHash trait to hash the input in a + /// cross-platform way. + pub fn write_ref(&mut self, input:&T) { input.deterministic_hash(self); } + + /// Finish the hash computation and return the digest. + pub fn finish(&self) -> u64 { self.0.finish() } +} + +impl DeterministicHasher for Xxh3Hash64Hasher { + fn finish(&self) -> u64 { self.0.finish() } + + fn write_bytes(&mut self, bytes:&[u8]) { self.0.write(bytes); } +} + +impl Default for Xxh3Hash64Hasher { + fn default() -> Self { Self::new() } +} diff --git a/crates/turbo-tasks-macros-shared/Source/expand.rs b/crates/turbo-tasks-macros-shared/Source/expand.rs new file mode 100644 index 0000000000000..c6808a4407ed6 --- /dev/null +++ b/crates/turbo-tasks-macros-shared/Source/expand.rs @@ -0,0 +1,182 @@ +use proc_macro2::{Ident, TokenStream}; +use quote::quote; +use syn::{ + Data, + DataEnum, + DataStruct, + DeriveInput, + Field, + Fields, + FieldsNamed, + FieldsUnnamed, + spanned::Spanned, +}; + +/// Handles the expansion of a struct/enum into a match statement that accesses +/// every field for procedural code generation. +/// +/// Requires several Fn helpers which perform expand different structures: +/// +/// - [expand_named] handles the expansion of a struct or enum variant with +/// named fields (e.g. `struct Foo { bar: u32 }`, `Foo::Bar { baz: u32 }`). +/// - [expand_unnamed] handles the expansion of a struct or enum variant with +/// unnamed fields (e.g. `struct Foo(u32)`, `Foo::Bar(u32)`). +/// - [expand_unit] handles the expansion of a unit struct or enum (e.g. `struct +/// Foo;`, `Foo::Bar`). +/// +/// These helpers should themselves call [generate_destructuring] to generate +/// the destructure necessary to access the fields of the value. +pub fn match_expansion< + EN:Fn(&Ident, &FieldsNamed) -> (TokenStream, TokenStream), + EU:Fn(&Ident, &FieldsUnnamed) -> (TokenStream, TokenStream), + U:Fn(&Ident) -> TokenStream, +>( + derive_input:&DeriveInput, + expand_named:&EN, + expand_unnamed:&EU, + expand_unit:&U, +) -> TokenStream { + let ident = &derive_input.ident; + let expand_unit = move |ident| (TokenStream::new(), expand_unit(ident)); + match &derive_input.data { + Data::Enum(DataEnum { variants, .. }) => { + let (variants_idents, (variants_fields_capture, expansion)):(Vec<_>, (Vec<_>, Vec<_>)) = + variants + .iter() + .map(|variant| { + ( + &variant.ident, + expand_fields( + &variant.ident, + &variant.fields, + expand_named, + expand_unnamed, + expand_unit, + ), + ) + }) + .unzip(); + + quote! { + match self { + #( + #ident::#variants_idents #variants_fields_capture => #expansion, + )* + } + } + }, + Data::Struct(DataStruct { fields, .. }) => { + let (captures, expansion) = + expand_fields(ident, fields, expand_named, expand_unnamed, expand_unit); + + if fields.is_empty() { + assert!(captures.is_empty()); + // a match expression here doesn't make sense as there's no fields to capture, + // just pass through the inner expression. + expansion + } else { + match fields { + Fields::Named(_) | Fields::Unnamed(_) => { + quote! { + match self { + #ident #captures => #expansion + } + } + }, + Fields::Unit => unreachable!(), + } + } + }, + _ => { + derive_input.span().unwrap().error("unsupported syntax").emit(); + + quote! {} + }, + } +} + +/// Formats the fields of any structure or enum variant. +/// +/// Empty lists of named or unnamed fields are treated as unit structs, as they +/// are semantically identical, and the `expand_unit` codepath can usually +/// generate better code. +pub fn expand_fields< + 'ident, + 'fields, + EN:Fn(&'ident Ident, &'fields FieldsNamed) -> R, + EU:Fn(&'ident Ident, &'fields FieldsUnnamed) -> R, + U:Fn(&'ident Ident) -> R, + R, +>( + ident:&'ident Ident, + fields:&'fields Fields, + expand_named:EN, + expand_unnamed:EU, + expand_unit:U, +) -> R { + if fields.is_empty() { + // any empty struct (regardless of the syntax used during declaration) is + // equivalent to a unit struct + return expand_unit(ident); + } + match fields { + Fields::Named(named) => expand_named(ident, named), + Fields::Unnamed(unnamed) => expand_unnamed(ident, unnamed), + Fields::Unit => unreachable!(), + } +} + +/// Generates a match arm destructuring pattern for the given fields. +/// +/// If no `filter_field` function is provided, all fields are included in the +/// pattern. If a `filter_field` function is provided, only fields for which +/// the function returns `true` are included in the pattern. If any field is +/// ignored, a wildcard pattern is added to the end of the pattern, making it +/// non-exhaustive. +/// +/// Returns both the capture pattern token stream and the name of the bound +/// identifiers corresponding to the input fields. +pub fn generate_destructuring<'a, I:Fn(&Field) -> bool>( + fields:impl ExactSizeIterator, + filter_field:&I, +) -> (TokenStream, Vec) { + let fields_len = fields.len(); + let (captures, fields_idents):(Vec<_>, Vec<_>) = fields + // We need to enumerate first to capture the indexes of the fields before filtering has + // changed them. + .enumerate() + .filter(|(_i, field)| filter_field(field)) + .map(|(i, field)| match &field.ident { + Some(ident) => (quote! { #ident }, quote! { #ident }), + None => { + let ident = Ident::new(&format!("field_{}", i), field.span()); + let index = syn::Index::from(i); + (quote! { #index: #ident }, quote! { #ident }) + } + }) + .unzip(); + // Only add the wildcard pattern if we're ignoring some fields. + let wildcard = if fields_idents.len() != fields_len { + quote! { .. } + } else { + quote! {} + }; + ( + quote! { + { #(#captures,)* #wildcard } + }, + fields_idents, + ) +} + +/// Generates an exhaustive match arm destructuring pattern for the given +/// fields. This is equivalent to calling [`generate_destructuring`] with a +/// `filter_field` function that always returns `true`. +/// +/// Returns both the capture pattern token stream and the name of the bound +/// identifiers corresponding to the input fields. +pub fn generate_exhaustive_destructuring<'a>( + fields:impl ExactSizeIterator, +) -> (TokenStream, Vec) { + generate_destructuring(fields, &|_| true) +} diff --git a/crates/turbo-tasks-macros-shared/Source/generic_type_input.rs b/crates/turbo-tasks-macros-shared/Source/generic_type_input.rs new file mode 100644 index 0000000000000..7783bd432d73c --- /dev/null +++ b/crates/turbo-tasks-macros-shared/Source/generic_type_input.rs @@ -0,0 +1,24 @@ +use syn::{ + Generics, + Result, + Token, + Type, + parse::{Parse, ParseStream}, +}; + +/// The input of the `generic_type` macro. +#[derive(Debug)] +pub struct GenericTypeInput { + pub generics:Generics, + pub ty:Type, +} + +impl Parse for GenericTypeInput { + fn parse(input:ParseStream) -> Result { + let generics:Generics = input.parse()?; + let _comma:Token![,] = input.parse()?; + let ty:Type = input.parse()?; + + Ok(GenericTypeInput { generics, ty }) + } +} diff --git a/crates/turbo-tasks-macros-shared/Source/ident.rs b/crates/turbo-tasks-macros-shared/Source/ident.rs new file mode 100644 index 0000000000000..dd437bc26c128 --- /dev/null +++ b/crates/turbo-tasks-macros-shared/Source/ident.rs @@ -0,0 +1,223 @@ +use quote::ToTokens; +use syn::{GenericArgument, Ident, Path, PathArguments, Type, TypeParamBound, spanned::Spanned}; + +pub fn get_register_value_type_ident(struct_ident:&Ident) -> Ident { + Ident::new(&format!("__register_{struct_ident}_value_type"), struct_ident.span()) +} + +pub fn get_register_trait_methods_ident(trait_ident:&Ident, struct_ident:&Ident) -> Ident { + Ident::new( + &format!("__register_{struct_ident}_{trait_ident}_trait_methods"), + trait_ident.span(), + ) +} + +pub fn get_native_function_ident(ident:&Ident) -> Ident { + Ident::new(&format!("{}_FUNCTION", ident.to_string().to_uppercase()), ident.span()) +} + +pub fn get_native_function_id_ident(ident:&Ident) -> Ident { + Ident::new(&format!("{}_FUNCTION_ID", ident.to_string().to_uppercase()), ident.span()) +} + +pub fn get_trait_type_ident(ident:&Ident) -> Ident { + Ident::new(&format!("{}_TRAIT_TYPE", ident.to_string().to_uppercase()), ident.span()) +} + +pub fn get_impl_function_ident(struct_ident:&Ident, ident:&Ident) -> Ident { + Ident::new( + &format!( + "{}_IMPL_{}_FUNCTION", + struct_ident.to_string().to_uppercase(), + ident.to_string().to_uppercase() + ), + ident.span(), + ) +} + +pub fn get_inherent_impl_function_ident(ty_ident:&Ident, fn_ident:&Ident) -> Ident { + Ident::new( + &format!( + "{}_IMPL_{}_FUNCTION", + ty_ident.to_string().to_uppercase(), + fn_ident.to_string().to_uppercase() + ), + fn_ident.span(), + ) +} + +pub fn get_inherent_impl_function_id_ident(ty_ident:&Ident, fn_ident:&Ident) -> Ident { + Ident::new( + &format!( + "{}_IMPL_{}_FUNCTION_ID", + ty_ident.to_string().to_uppercase(), + fn_ident.to_string().to_uppercase() + ), + fn_ident.span(), + ) +} + +pub fn get_trait_impl_function_ident( + struct_ident:&Ident, + trait_ident:&Ident, + ident:&Ident, +) -> Ident { + Ident::new( + &format!( + "{}_IMPL_TRAIT_{}_{}_FUNCTION", + struct_ident.to_string().to_uppercase(), + trait_ident.to_string().to_uppercase(), + ident.to_string().to_uppercase() + ), + ident.span(), + ) +} + +pub fn get_trait_impl_function_id_ident( + struct_ident:&Ident, + trait_ident:&Ident, + ident:&Ident, +) -> Ident { + Ident::new( + &format!( + "{}_IMPL_TRAIT_{}_{}_FUNCTION_ID", + struct_ident.to_string().to_uppercase(), + trait_ident.to_string().to_uppercase(), + ident.to_string().to_uppercase() + ), + ident.span(), + ) +} + +pub fn get_internal_trait_impl_function_ident(trait_ident:&Ident, ident:&Ident) -> Ident { + Ident::new(&format!("__trait_call_{trait_ident}_{ident}"), trait_ident.span()) +} + +pub fn get_path_ident(path:&Path) -> Ident { + let mut result = String::new(); + + for (i, segment) in path.segments.iter().enumerate() { + let ident = segment.ident.to_string(); + + if i > 0 { + result.push('_'); + } + + result.push_str(&ident); + + match &segment.arguments { + PathArguments::AngleBracketed(args) => { + for arg in &args.args { + match arg { + GenericArgument::Type(ty) => { + if let Type::Path(type_path) = ty { + let type_ident = get_path_ident(&type_path.path); + result.push('_'); + result.push_str(&type_ident.to_string()); + } else if let Type::TraitObject(trait_obj) = ty { + for bound in &trait_obj.bounds { + if let TypeParamBound::Trait(bound_trait) = bound { + let bound_ident = get_path_ident(&bound_trait.path); + result.push_str("_dyn_"); + result.push_str(&bound_ident.to_string()); + } + } + } else { + arg.span() + .unwrap() + .error( + "#[turbo_tasks::value_impl] does not support this type \ + argument", + ) + .emit(); + } + }, + _ => { + arg.span() + .unwrap() + .error( + "#[turbo_tasks::value_impl] does not support this type \ + argument", + ) + .emit() + }, + } + } + }, + PathArguments::None => {}, + _ => { + segment + .span() + .unwrap() + .error("#[turbo_tasks::value_impl] does not support this type argument") + .emit(); + }, + } + } + + Ident::new(&result, path.span()) +} + +pub fn get_type_ident(ty:&Type) -> Option { + match ty { + Type::Path(path) => Some(get_path_ident(&path.path)), + Type::Tuple(tuple) => Some(Ident::new("unit", tuple.span())), + _ => { + ty.span() + .unwrap() + .error(format!( + "#[turbo_tasks::value_impl] does not support the type {}, expected T or \ + Box", + ty.to_token_stream() + )) + .emit(); + None + }, + } +} + +pub fn get_read_ref_ident(ident:&Ident) -> Ident { + Ident::new(&(ident.to_string() + "ReadRef"), ident.span()) +} + +pub fn get_trait_ref_ident(ident:&Ident) -> Ident { + Ident::new(&(ident.to_string() + "TraitRef"), ident.span()) +} + +pub fn get_trait_default_impl_function_ident(trait_ident:&Ident, ident:&Ident) -> Ident { + Ident::new( + &format!( + "{}_DEFAULT_IMPL_{}_FUNCTION", + trait_ident.to_string().to_uppercase(), + ident.to_string().to_uppercase() + ), + ident.span(), + ) +} + +pub fn get_trait_type_id_ident(ident:&Ident) -> Ident { + Ident::new(&format!("{}_TRAIT_TYPE_ID", ident.to_string().to_uppercase()), ident.span()) +} + +pub fn get_trait_default_impl_function_id_ident(trait_ident:&Ident, ident:&Ident) -> Ident { + Ident::new( + &format!( + "{}_DEFAULT_IMPL_{}_FUNCTION_ID", + trait_ident.to_string().to_uppercase(), + ident.to_string().to_uppercase() + ), + ident.span(), + ) +} + +pub fn get_value_type_ident(ident:&Ident) -> Ident { + Ident::new(&format!("{}_VALUE_TYPE", ident.to_string().to_uppercase()), ident.span()) +} + +pub fn get_value_type_id_ident(ident:&Ident) -> Ident { + Ident::new(&format!("{}_VALUE_TYPE_ID", ident.to_string().to_uppercase()), ident.span()) +} + +pub fn get_value_type_init_ident(ident:&Ident) -> Ident { + Ident::new(&format!("{}_VALUE_TYPE_INIT", ident.to_string().to_uppercase()), ident.span()) +} diff --git a/crates/turbo-tasks-macros-shared/Source/lib.rs b/crates/turbo-tasks-macros-shared/Source/lib.rs new file mode 100644 index 0000000000000..cbeb9aa2d3399 --- /dev/null +++ b/crates/turbo-tasks-macros-shared/Source/lib.rs @@ -0,0 +1,14 @@ +#![feature(proc_macro_diagnostic)] +#![feature(box_patterns)] + +mod expand; +mod generic_type_input; +mod ident; +mod primitive_input; +mod value_trait_arguments; + +pub use expand::*; +pub use generic_type_input::GenericTypeInput; +pub use ident::*; +pub use primitive_input::PrimitiveInput; +pub use value_trait_arguments::ValueTraitArguments; diff --git a/crates/turbo-tasks-macros-shared/Source/primitive_input.rs b/crates/turbo-tasks-macros-shared/Source/primitive_input.rs new file mode 100644 index 0000000000000..52aa37d322fa1 --- /dev/null +++ b/crates/turbo-tasks-macros-shared/Source/primitive_input.rs @@ -0,0 +1,17 @@ +use syn::{ + Result, + Type, + parse::{Parse, ParseStream}, +}; + +#[derive(Debug)] +pub struct PrimitiveInput { + pub ty:Type, +} + +impl Parse for PrimitiveInput { + fn parse(input:ParseStream) -> Result { + let ty:Type = input.parse()?; + Ok(PrimitiveInput { ty }) + } +} diff --git a/crates/turbo-tasks-macros-shared/Source/value_trait_arguments.rs b/crates/turbo-tasks-macros-shared/Source/value_trait_arguments.rs new file mode 100644 index 0000000000000..7b916758b5fc2 --- /dev/null +++ b/crates/turbo-tasks-macros-shared/Source/value_trait_arguments.rs @@ -0,0 +1,41 @@ +use syn::{ + Meta, + Token, + parse::{Parse, ParseStream}, + punctuated::Punctuated, +}; + +/// Arguments to the `#[turbo_tasks::value_trait]` attribute macro. +#[derive(Debug)] +pub struct ValueTraitArguments { + /// Whether the macro should generate a `ValueDebug`-like `dbg()` + /// implementation on the trait's `Vc`. + pub debug:bool, +} + +impl Default for ValueTraitArguments { + fn default() -> Self { Self { debug:true } } +} + +impl Parse for ValueTraitArguments { + fn parse(input:ParseStream) -> syn::Result { + let mut result = Self::default(); + if input.is_empty() { + return Ok(result); + } + + let punctuated:Punctuated = input.parse_terminated(Meta::parse)?; + for meta in punctuated { + match meta.path().get_ident().map(ToString::to_string).as_deref() { + Some("no_debug") => { + result.debug = false; + }, + _ => { + return Err(syn::Error::new_spanned(meta, "unknown parameter")); + }, + } + } + + Ok(result) + } +} diff --git a/crates/turbo-tasks-macros-tests/build.rs b/crates/turbo-tasks-macros-tests/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbo-tasks-macros-tests/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turborepo-lib/src/query/boundaries.rs b/crates/turbo-tasks-macros/Source/derive/boundaries.rs similarity index 100% rename from crates/turborepo-lib/src/query/boundaries.rs rename to crates/turbo-tasks-macros/Source/derive/boundaries.rs diff --git a/crates/turbo-tasks-macros/Source/derive/deterministic_hash_macro.rs b/crates/turbo-tasks-macros/Source/derive/deterministic_hash_macro.rs new file mode 100644 index 0000000000000..00597ae7b03ef --- /dev/null +++ b/crates/turbo-tasks-macros/Source/derive/deterministic_hash_macro.rs @@ -0,0 +1,67 @@ +use proc_macro::TokenStream; +use proc_macro2::{Ident, TokenStream as TokenStream2}; +use quote::quote; +use syn::{Data, DeriveInput, FieldsNamed, FieldsUnnamed, parse_macro_input}; +use turbo_tasks_macros_shared::{generate_exhaustive_destructuring, match_expansion}; + +/// This macro generates the implementation of the `DeterministicHash` trait for +/// a given type. +/// +/// This requires that every contained value also implement `DeterministicHash`. +pub fn derive_deterministic_hash(input:TokenStream) -> TokenStream { + let derive_input = parse_macro_input!(input as DeriveInput); + + let ident = &derive_input.ident; + let match_hash = match_expansion(&derive_input, &hash_named, &hash_unnamed, &hash_unit); + let discriminant = match derive_input.data { + Data::Enum(_) => { + quote! { + turbo_tasks_hash::DeterministicHash::deterministic_hash(&std::mem::discriminant(self), __state__); + } + }, + _ => quote! {}, + }; + + quote! { + impl turbo_tasks_hash::DeterministicHash for #ident { + fn deterministic_hash(&self, __state__: &mut H) { + #discriminant + #match_hash + } + } + } + .into() +} + +/// Hashes a struct or enum variant with named fields (e.g. `struct Foo { +/// bar: u32 }`, `Foo::Bar { baz: u32 }`). +fn hash_named(_ident:&Ident, fields:&FieldsNamed) -> (TokenStream2, TokenStream2) { + let (captures, fields_idents) = generate_exhaustive_destructuring(fields.named.iter()); + ( + captures, + quote! { + {#( + #fields_idents.deterministic_hash(__state__); + )*} + }, + ) +} + +/// Hashes a struct or enum variant with unnamed fields (e.g. `struct +/// Foo(u32)`, `Foo::Bar(u32)`). +fn hash_unnamed(_ident:&Ident, fields:&FieldsUnnamed) -> (TokenStream2, TokenStream2) { + let (captures, fields_idents) = generate_exhaustive_destructuring(fields.unnamed.iter()); + ( + captures, + quote! { + {#( + #fields_idents.deterministic_hash(__state__); + )*} + }, + ) +} + +/// Hashes a unit struct or enum variant (e.g. `struct Foo;`, `Foo::Bar`). +fn hash_unit(_ident:&Ident) -> TokenStream2 { + quote! { { } } +} diff --git a/crates/turborepo-lib/src/query/external_package.rs b/crates/turbo-tasks-macros/Source/derive/external_package.rs similarity index 100% rename from crates/turborepo-lib/src/query/external_package.rs rename to crates/turbo-tasks-macros/Source/derive/external_package.rs diff --git a/crates/turbo-tasks-macros/Source/derive/mod.rs b/crates/turbo-tasks-macros/Source/derive/mod.rs new file mode 100644 index 0000000000000..e2f68f08b95c0 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/derive/mod.rs @@ -0,0 +1,55 @@ +mod deterministic_hash_macro; +mod task_input_macro; +mod trace_raw_vcs_macro; +mod value_debug_format_macro; +mod value_debug_macro; + +pub use deterministic_hash_macro::derive_deterministic_hash; +use syn::{Attribute, Meta, MetaList, NestedMeta, spanned::Spanned}; +pub use task_input_macro::derive_task_input; +pub use trace_raw_vcs_macro::derive_trace_raw_vcs; +pub use value_debug_format_macro::derive_value_debug_format; +pub use value_debug_macro::derive_value_debug; + +struct FieldAttributes { + trace_ignore:bool, + debug_ignore:bool, +} + +impl From<&[Attribute]> for FieldAttributes { + fn from(attrs:&[Attribute]) -> Self { + let mut result = Self { trace_ignore:false, debug_ignore:false }; + + for attr in attrs { + if !attr.path.get_ident().map(|ident| *ident == "turbo_tasks").unwrap_or_default() { + continue; + } + if let Ok(Meta::List(MetaList { nested, .. })) = attr + .parse_meta() + .map_err(|err| err.span().unwrap().error(err.to_string()).emit()) + { + for meta in nested { + if let NestedMeta::Meta(Meta::Path(path)) = &meta { + match path.get_ident().map(|ident| ident.to_string()).as_deref() { + Some("trace_ignore") => result.trace_ignore = true, + Some("debug_ignore") => result.debug_ignore = true, + _ => { + path.span() + .unwrap() + .error("expected `trace_ignore` or `debug_ignore`") + .emit() + }, + } + } else { + meta.span() + .unwrap() + .error("expected `trace_ignore` or `debug_ignore`") + .emit(); + } + } + } + } + + result + } +} diff --git a/crates/turbo-tasks-macros/Source/derive/task_input_macro.rs b/crates/turbo-tasks-macros/Source/derive/task_input_macro.rs new file mode 100644 index 0000000000000..f4f47138fbbee --- /dev/null +++ b/crates/turbo-tasks-macros/Source/derive/task_input_macro.rs @@ -0,0 +1,262 @@ +use proc_macro::TokenStream; +use proc_macro2::{Ident, Literal, TokenStream as TokenStream2}; +use quote::quote; +use syn::{ + Data, + DataEnum, + DataStruct, + DeriveInput, + FieldsNamed, + FieldsUnnamed, + parse_macro_input, + spanned::Spanned, +}; +use turbo_tasks_macros_shared::{expand_fields, generate_exhaustive_destructuring}; + +pub fn derive_task_input(input:TokenStream) -> TokenStream { + let derive_input = parse_macro_input!(input as DeriveInput); + let ident = &derive_input.ident; + let generics = &derive_input.generics; + + if let Some(where_clause) = &generics.where_clause { + // NOTE(alexkirsz) We could support where clauses and generic parameters bounds + // in the future, but for simplicity's sake, we don't support them yet. + where_clause + .span() + .unwrap() + .error("the TaskInput derive macro does not support where clauses yet") + .emit(); + } + + for param in &generics.params { + match param { + syn::GenericParam::Type(param) => { + if !param.bounds.is_empty() { + // NOTE(alexkirsz) See where clause above. + param + .span() + .unwrap() + .error( + "the TaskInput derive macro does not support generic parameters \ + bounds yet", + ) + .emit(); + } + }, + syn::GenericParam::Lifetime(param) => { + param + .span() + .unwrap() + .error("the TaskInput derive macro does not support generic lifetimes") + .emit(); + }, + syn::GenericParam::Const(param) => { + // NOTE(alexkirsz) Ditto: not supported yet for simplicity's sake. + param + .span() + .unwrap() + .error("the TaskInput derive macro does not support const generics yet") + .emit(); + }, + } + } + + let inputs_list_ident = + Ident::new(&format!("__{}_inputs_list", ident), derive_input.ident.span()); + + let expand_named = |ident, fields| expand_named(ident, fields, &inputs_list_ident); + let expand_unnamed = |ident, fields| expand_unnamed(ident, fields, &inputs_list_ident); + + let (try_from_impl, from_impl) = match &derive_input.data { + Data::Enum(DataEnum { variants, .. }) => { + let mut variants_idents = vec![]; + let mut variants_fields_len = vec![]; + let mut variants_fields_destructuring = vec![]; + let mut variants_try_from_expansion = vec![]; + let mut variants_from_expansion = vec![]; + + for variant in variants { + let variant_ident = &variant.ident; + let (fields_destructuring, try_from_expansion, from_expansion) = expand_fields( + &variant.ident, + &variant.fields, + expand_named, + expand_unnamed, + expand_unit, + ); + variants_idents.push(variant_ident); + variants_fields_len.push(variant.fields.len()); + variants_fields_destructuring.push(fields_destructuring); + variants_try_from_expansion.push(try_from_expansion); + variants_from_expansion.push(from_expansion); + } + + // This is similar to what Rust does for enums (configurable via the `repr` + // attribute). We use the smallest possible integer type that can + // represent all the variants. However, for now, this is not + // configurable for TaskInput enums. + let repr_bits = usize::BITS - variants.len().leading_zeros(); + let repr = match repr_bits { + 0..=8 => quote! { u8 }, + 9..=16 => quote! { u16 }, + 17..=32 => quote! { u32 }, + 33..=64 => quote! { u64 }, + _ => panic!("too many variants"), + }; + + let variants_discriminants:Vec<_> = + (0..variants_idents.len()).map(Literal::usize_unsuffixed).collect(); + + ( + quote! { + match value { + turbo_tasks::ConcreteTaskInput::List(value) => { + let mut #inputs_list_ident = value.iter(); + + let discriminant = #inputs_list_ident.next().ok_or_else(|| anyhow::anyhow!(concat!("missing discriminant for ", stringify!(#ident))))?; + let discriminant: #repr = turbo_tasks::TaskInput::try_from_concrete(discriminant)?; + + Ok(match discriminant { + #( + #variants_discriminants => { + #variants_try_from_expansion + #ident::#variants_idents #variants_fields_destructuring + }, + )* + _ => return Err(anyhow::anyhow!("invalid discriminant for {}", stringify!(#ident))), + }) + }, + _ => Err(anyhow::anyhow!("invalid task input type, expected list")), + } + }, + quote! { + match self { + #( + #ident::#variants_idents #variants_fields_destructuring => { + let mut #inputs_list_ident = Vec::with_capacity(1 + #variants_fields_len); + let discriminant: #repr = #variants_discriminants; + let discriminant = discriminant.into_concrete(); + #inputs_list_ident.push(discriminant); + #variants_from_expansion + turbo_tasks::ConcreteTaskInput::List(#inputs_list_ident) + } + )* + } + }, + ) + }, + Data::Struct(DataStruct { fields, .. }) => { + let (destructuring, try_from_expansion, from_expansion) = + expand_fields(ident, fields, expand_named, expand_unnamed, expand_unit); + let fields_len = fields.len(); + + ( + quote! { + match value { + turbo_tasks::ConcreteTaskInput::List(value) => { + let mut #inputs_list_ident = value.iter(); + #try_from_expansion + Ok(#ident #destructuring) + }, + _ => Err(anyhow::anyhow!("invalid task input type, expected list")), + } + }, + quote! { + let mut #inputs_list_ident = Vec::with_capacity(#fields_len); + let #ident #destructuring = self; + #from_expansion + turbo_tasks::ConcreteTaskInput::List(#inputs_list_ident) + }, + ) + }, + _ => { + derive_input.span().unwrap().error("unsupported syntax").emit(); + + (quote! {}, quote! {}) + }, + }; + + let generic_params:Vec<_> = generics + .params + .iter() + .filter_map(|param| { + match param { + syn::GenericParam::Type(param) => Some(param), + _ => { + // We already report an error for this above. + None + }, + } + }) + .collect(); + + quote! { + impl #generics turbo_tasks::TaskInput for #ident #generics + where + #(#generic_params: turbo_tasks::TaskInput,)* + { + #[allow(non_snake_case)] + #[allow(unreachable_code)] // This can occur for enums with no variants. + fn try_from_concrete(value: &turbo_tasks::ConcreteTaskInput) -> turbo_tasks::Result { + #try_from_impl + } + + #[allow(non_snake_case)] + #[allow(unreachable_code)] // This can occur for enums with no variants. + fn into_concrete(self) -> turbo_tasks::ConcreteTaskInput { + #from_impl + } + } + } + .into() +} + +fn expand_named( + _ident:&Ident, + fields:&FieldsNamed, + inputs_list_ident:&Ident, +) -> (TokenStream2, TokenStream2, TokenStream2) { + let (destructuring, fields_idents) = generate_exhaustive_destructuring(fields.named.iter()); + ( + destructuring, + quote! { + #( + let #fields_idents = #inputs_list_ident.next().ok_or_else(|| anyhow::anyhow!(concat!("missing element for ", stringify!(#fields_idents))))?; + let #fields_idents = turbo_tasks::TaskInput::try_from_concrete(#fields_idents)?; + )* + }, + quote! { + #( + let #fields_idents = #fields_idents.into_concrete(); + #inputs_list_ident.push(#fields_idents); + )* + }, + ) +} + +fn expand_unnamed( + _ident:&Ident, + fields:&FieldsUnnamed, + inputs_list_ident:&Ident, +) -> (TokenStream2, TokenStream2, TokenStream2) { + let (destructuring, fields_idents) = generate_exhaustive_destructuring(fields.unnamed.iter()); + ( + destructuring, + quote! { + #( + let #fields_idents = #inputs_list_ident.next().ok_or_else(|| anyhow::anyhow!(concat!("missing element for ", stringify!(#fields_idents))))?; + let #fields_idents = turbo_tasks::TaskInput::try_from_concrete(#fields_idents)?; + )* + }, + quote! { + #( + let #fields_idents = #fields_idents.into_concrete(); + #inputs_list_ident.push(#fields_idents); + )* + }, + ) +} + +fn expand_unit(_ident:&Ident) -> (TokenStream2, TokenStream2, TokenStream2) { + (quote! {}, quote! {}, quote! {}) +} diff --git a/crates/turbo-tasks-macros/Source/derive/trace_raw_vcs_macro.rs b/crates/turbo-tasks-macros/Source/derive/trace_raw_vcs_macro.rs new file mode 100644 index 0000000000000..031b6cfb0d608 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/derive/trace_raw_vcs_macro.rs @@ -0,0 +1,59 @@ +use proc_macro::TokenStream; +use proc_macro2::{Ident, TokenStream as TokenStream2}; +use quote::quote; +use syn::{DeriveInput, Field, FieldsNamed, FieldsUnnamed, parse_macro_input}; +use turbo_tasks_macros_shared::{generate_destructuring, match_expansion}; + +use super::FieldAttributes; + +fn filter_field(field:&Field) -> bool { + !FieldAttributes::from(field.attrs.as_slice()).trace_ignore +} + +pub fn derive_trace_raw_vcs(input:TokenStream) -> TokenStream { + let mut derive_input = parse_macro_input!(input as DeriveInput); + let ident = &derive_input.ident; + + for type_param in derive_input.generics.type_params_mut() { + type_param.bounds.push(syn::parse_quote!(turbo_tasks::trace::TraceRawVcs)); + } + let (impl_generics, ty_generics, where_clause) = derive_input.generics.split_for_impl(); + + let trace_items = match_expansion(&derive_input, &trace_named, &trace_unnamed, &trace_unit); + quote! { + impl #impl_generics turbo_tasks::trace::TraceRawVcs for #ident #ty_generics #where_clause { + fn trace_raw_vcs(&self, __context__: &mut turbo_tasks::trace::TraceRawVcsContext) { + #trace_items + } + } + } + .into() +} + +fn trace_named(_ident:&Ident, fields:&FieldsNamed) -> (TokenStream2, TokenStream2) { + let (captures, fields_idents) = generate_destructuring(fields.named.iter(), &filter_field); + ( + captures, + quote! { + {#( + turbo_tasks::trace::TraceRawVcs::trace_raw_vcs(#fields_idents, __context__); + )*} + }, + ) +} + +fn trace_unnamed(_ident:&Ident, fields:&FieldsUnnamed) -> (TokenStream2, TokenStream2) { + let (captures, fields_idents) = generate_destructuring(fields.unnamed.iter(), &filter_field); + ( + captures, + quote! { + {#( + turbo_tasks::trace::TraceRawVcs::trace_raw_vcs(#fields_idents, __context__); + )*} + }, + ) +} + +fn trace_unit(_ident:&Ident) -> TokenStream2 { + quote! { { } } +} diff --git a/crates/turbo-tasks-macros/Source/derive/value_debug_format_macro.rs b/crates/turbo-tasks-macros/Source/derive/value_debug_format_macro.rs new file mode 100644 index 0000000000000..fe06910ef7419 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/derive/value_debug_format_macro.rs @@ -0,0 +1,124 @@ +use proc_macro::TokenStream; +use proc_macro2::{Ident, TokenStream as TokenStream2}; +use quote::quote; +use syn::{DeriveInput, Field, FieldsNamed, FieldsUnnamed, parse_macro_input}; +use turbo_tasks_macros_shared::{generate_destructuring, match_expansion}; + +use super::FieldAttributes; + +fn filter_field(field:&Field) -> bool { + !FieldAttributes::from(field.attrs.as_slice()).debug_ignore +} + +/// This macro generates the implementation of the `ValueDebugFormat` trait for +/// a given type. +/// +/// Fields annotated with `#[debug_ignore]` will not appear in the +/// `ValueDebugFormat` representation of the type. +pub fn derive_value_debug_format(input:TokenStream) -> TokenStream { + let mut derive_input = parse_macro_input!(input as DeriveInput); + + let ident = &derive_input.ident; + + for type_param in derive_input.generics.type_params_mut() { + type_param.bounds.push(syn::parse_quote!(turbo_tasks::debug::ValueDebugFormat)); + type_param.bounds.push(syn::parse_quote!(std::fmt::Debug)); + type_param.bounds.push(syn::parse_quote!(std::marker::Send)); + type_param.bounds.push(syn::parse_quote!(std::marker::Sync)); + } + let (impl_generics, ty_generics, where_clause) = derive_input.generics.split_for_impl(); + + let formatting_logic = + match_expansion(&derive_input, &format_named, &format_unnamed, &format_unit); + + quote! { + impl #impl_generics turbo_tasks::debug::ValueDebugFormat for #ident #ty_generics #where_clause { + fn value_debug_format<'a>(&'a self, depth: usize) -> turbo_tasks::debug::ValueDebugFormatString<'a> { + turbo_tasks::debug::ValueDebugFormatString::Async( + Box::pin(async move { + if depth == 0 { + return Ok(stringify!(#ident).to_string()); + } + + use turbo_tasks::debug::internal::*; + use turbo_tasks::debug::ValueDebugFormat; + Ok(format!("{:#?}", #formatting_logic)) + }) + ) + } + } + } + .into() +} + +/// Formats a single field nested inside named or unnamed fields. +fn format_field(value:TokenStream2) -> TokenStream2 { + quote! { + turbo_tasks::macro_helpers::value_debug_format_field(#value.value_debug_format(depth.saturating_sub(1))) + } +} + +/// Formats a struct or enum variant with named fields (e.g. `struct Foo { +/// bar: u32 }`, `Foo::Bar { baz: u32 }`). +fn format_named(ident:&Ident, fields:&FieldsNamed) -> (TokenStream2, TokenStream2) { + let (captures, fields_idents) = generate_destructuring(fields.named.iter(), &filter_field); + ( + captures, + if fields_idents.is_empty() { + // this can happen if all fields are ignored, we must special-case this to avoid + // rustc being unable to infer the type of an empty vec of futures + quote! { + FormattingStruct::new_named(stringify!(#ident), vec![]) + } + } else { + let fields_values = fields_idents.iter().cloned().map(format_field); + quote! { + FormattingStruct::new_named_async( + stringify!(#ident), + vec![#( + AsyncFormattingField::new( + stringify!(#fields_idents), + #fields_values, + ), + )*], + ).await + } + }, + ) +} + +/// Formats a struct or enum variant with unnamed fields (e.g. `struct +/// Foo(u32)`, `Foo::Bar(u32)`). +fn format_unnamed(ident:&Ident, fields:&FieldsUnnamed) -> (TokenStream2, TokenStream2) { + let (captures, fields_idents) = generate_destructuring(fields.unnamed.iter(), &filter_field); + ( + captures, + if fields_idents.is_empty() { + // this can happen if all fields are ignored, we must special-case this to avoid + // rustc being unable to infer the type of an empty vec of futures + quote! { + FormattingStruct::new_unnamed(stringify!(#ident), vec![]) + } + } else { + let fields_values = fields_idents.into_iter().map(format_field); + quote! { + FormattingStruct::new_unnamed_async( + stringify!(#ident), + vec![#( + #fields_values, + )*], + ).await + } + }, + ) +} + +/// Formats a unit struct or enum variant (e.g. `struct Foo;`, `Foo::Bar`). +fn format_unit(ident:&Ident) -> TokenStream2 { + quote! { + FormattingStruct::new_unnamed( + stringify!(#ident), + vec![], + ) + } +} diff --git a/crates/turbo-tasks-macros/Source/derive/value_debug_macro.rs b/crates/turbo-tasks-macros/Source/derive/value_debug_macro.rs new file mode 100644 index 0000000000000..c45b011a4e74a --- /dev/null +++ b/crates/turbo-tasks-macros/Source/derive/value_debug_macro.rs @@ -0,0 +1,27 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{DeriveInput, parse_macro_input}; + +/// This macro generates the implementation of the `ValueDebug` trait for a +/// given type. +/// +/// This requires the type to implement the `ValueDebugFormat` trait. +pub fn derive_value_debug(input:TokenStream) -> TokenStream { + let derive_input = parse_macro_input!(input as DeriveInput); + let ident = &derive_input.ident; + quote! { + #[turbo_tasks::value_impl] + impl turbo_tasks::debug::ValueDebug for #ident { + #[turbo_tasks::function] + async fn dbg(&self) -> anyhow::Result> { + turbo_tasks::debug::ValueDebugFormat::value_debug_format(self, usize::MAX).try_to_value_debug_string().await + } + + #[turbo_tasks::function] + async fn dbg_depth(&self, depth: usize) -> anyhow::Result> { + turbo_tasks::debug::ValueDebugFormat::value_debug_format(self, depth).try_to_value_debug_string().await + } + } + } + .into() +} diff --git a/crates/turborepo-lib/src/query/package_graph.rs b/crates/turbo-tasks-macros/Source/derive/value_macro.rs similarity index 100% rename from crates/turborepo-lib/src/query/package_graph.rs rename to crates/turbo-tasks-macros/Source/derive/value_macro.rs diff --git a/crates/turbo-tasks-macros/Source/func.rs b/crates/turbo-tasks-macros/Source/func.rs new file mode 100644 index 0000000000000..43e71176f4925 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/func.rs @@ -0,0 +1,488 @@ +use proc_macro2::Ident; +use syn::{ + AngleBracketedGenericArguments, + Block, + Expr, + ExprPath, + FnArg, + GenericArgument, + Pat, + PatIdent, + PatType, + Path, + PathArguments, + PathSegment, + Receiver, + ReturnType, + Signature, + Token, + Type, + TypeGroup, + TypePath, + TypeTuple, + parse_quote, + punctuated::{Pair, Punctuated}, + spanned::Spanned, +}; + +#[derive(Debug)] +pub struct TurboFn { + // signature: Signature, + // block: Block, + ident:Ident, + output:Type, + inputs:Vec, +} + +#[derive(Debug)] +pub struct Input { + pub ident:Ident, + pub ty:Type, +} + +impl TurboFn { + pub fn new( + original_signature:&Signature, + definition_context:DefinitionContext, + ) -> Option { + if !original_signature.generics.params.is_empty() { + original_signature + .generics + .span() + .unwrap() + .error(format!( + "{} do not support generic parameters", + definition_context.function_type(), + )) + .emit(); + return None; + } + + if original_signature.generics.where_clause.is_some() { + original_signature + .generics + .where_clause + .span() + .unwrap() + .error(format!( + "{} do not support where clauses", + definition_context.function_type(), + )) + .emit(); + return None; + } + + let mut raw_inputs = original_signature.inputs.iter(); + let mut inputs = Vec::with_capacity(raw_inputs.len()); + + if let Some(possibly_receiver) = raw_inputs.next() { + match possibly_receiver { + FnArg::Receiver( + receiver @ Receiver { attrs, self_token, reference, mutability }, + ) => { + if !attrs.is_empty() { + receiver + .span() + .unwrap() + .error(format!( + "{} do not support attributes on arguments", + definition_context.function_type(), + )) + .emit(); + return None; + } + + // tt::functions in tt::value_impl can either take self as a typed `self: + // Vc`, or as immutable references `&self`. We must validate against any + // other forms of self. + + let definition_context = match &definition_context { + DefinitionContext::NakedFn { .. } => return None, + _ => &definition_context, + }; + + if !attrs.is_empty() { + receiver + .span() + .unwrap() + .error(format!( + "{} do not support attributes on self", + definition_context.function_type(), + )) + .emit(); + return None; + } + + if mutability.is_some() { + receiver + .span() + .unwrap() + .error(format!( + "{} cannot take self by mutable reference, use &self or self: \ + Vc instead", + definition_context.function_type(), + )) + .emit(); + return None; + } + + match &reference { + None => { + receiver + .span() + .unwrap() + .error(format!( + "{} cannot take self by value, use &self or self: Vc \ + instead", + definition_context.function_type(), + )) + .emit(); + return None; + }, + Some((_, Some(lifetime))) => { + lifetime + .span() + .unwrap() + .error(format!( + "{} cannot take self by reference with a custom lifetime, use \ + &self or self: Vc instead", + definition_context.function_type(), + )) + .emit(); + return None; + }, + _ => {}, + } + + inputs.push(Input { + ident:Ident::new("self", self_token.span()), + ty:parse_quote! { turbo_tasks::Vc }, + }); + }, + FnArg::Typed(typed) => { + if !typed.attrs.is_empty() { + typed + .span() + .unwrap() + .error(format!( + "{} does not support attributes on arguments", + definition_context.function_type(), + )) + .emit(); + return None; + } + + let ident = if let Pat::Ident(ident) = &*typed.pat { + if ident.ident == "self" { + if let DefinitionContext::NakedFn { .. } = definition_context { + // The function is not associated. The compiler will emit an error + // on its own. + return None; + }; + + // We don't validate that the user provided a valid + // `turbo_tasks::Vc` here. + // We'll rely on the compiler to emit an error + // if the user provided an invalid receiver type + // when + // calling `into_concrete`. + } else { + match definition_context { + DefinitionContext::NakedFn { .. } + | DefinitionContext::ValueInherentImpl { .. } => {}, + DefinitionContext::ValueTraitImpl { .. } + | DefinitionContext::ValueTrait { .. } => { + typed + .span() + .unwrap() + .error(format!( + "{} must accept &self or self: Vc as the first \ + argument", + definition_context.function_type(), + )) + .emit(); + return None; + }, + } + } + + ident.ident.clone() + } else { + // We can't support destructuring patterns (or other kinds of patterns). + Ident::new("arg1", typed.pat.span()) + }; + + inputs.push(Input { ident, ty:(*typed.ty).clone() }); + }, + } + } + + for (i, input) in raw_inputs.enumerate() { + match input { + FnArg::Receiver(_) => { + // The compiler will emit an error on its own. + return None; + }, + FnArg::Typed(typed) => { + let ident = if let Pat::Ident(ident) = &*typed.pat { + ident.ident.clone() + } else { + Ident::new(&format!("arg{}", i + 2), typed.pat.span()) + }; + + inputs.push(Input { ident, ty:(*typed.ty).clone() }); + }, + } + } + + let output = return_type_to_type(&original_signature.output); + + Some(TurboFn { ident:original_signature.ident.clone(), output, inputs }) + } + + /// The signature of the exposed function. This is the original signature + /// converted to a standard turbo_tasks function signature. + pub fn signature(&self) -> Signature { + let exposed_inputs:Punctuated<_, Token![,]> = self + .inputs + .iter() + .map(|input| { + FnArg::Typed(PatType { + attrs:Default::default(), + ty:Box::new(input.ty.clone()), + pat:Box::new(Pat::Ident(PatIdent { + attrs:Default::default(), + by_ref:None, + mutability:None, + ident:input.ident.clone(), + subpat:None, + })), + colon_token:Default::default(), + }) + }) + .collect(); + + let ident = &self.ident; + let orig_output = &self.output; + let new_output = expand_vc_return_type(orig_output); + + parse_quote! { + fn #ident(#exposed_inputs) -> #new_output + } + } + + pub fn trait_signature(&self) -> Signature { + let signature = self.signature(); + + parse_quote! { + #signature where Self: Sized + } + } + + fn converted_inputs(&self) -> Punctuated { + self.inputs + .iter() + .map(|Input { ty, ident }| -> Expr { + parse_quote! { + <#ty as turbo_tasks::task::TaskInput>::into_concrete(#ident) + } + }) + .collect() + } + + /// The block of the exposed function for a dynamic dispatch call to the + /// given trait. + pub fn dynamic_block(&self, trait_type_id_ident:&Ident) -> Block { + let ident = &self.ident; + let output = &self.output; + let converted_inputs = self.converted_inputs(); + parse_quote! { + { + <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( + turbo_tasks::trait_call( + *#trait_type_id_ident, + std::borrow::Cow::Borrowed(stringify!(#ident)), + vec![#converted_inputs], + ) + ) + } + } + } + + /// The block of the exposed function for a static dispatch call to the + /// given native function. + pub fn static_block(&self, native_function_id_ident:&Ident) -> Block { + let output = &self.output; + let converted_inputs = self.converted_inputs(); + parse_quote! { + { + <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( + turbo_tasks::dynamic_call( + *#native_function_id_ident, + vec![#converted_inputs], + ) + ) + } + } + } +} + +fn return_type_to_type(return_type:&ReturnType) -> Type { + match return_type { + ReturnType::Default => parse_quote! { () }, + ReturnType::Type(_, ref return_type) => (**return_type).clone(), + } +} + +fn expand_vc_return_type(orig_output:&Type) -> Type { + // HACK: Approximate the expansion that we'd otherwise get from + // `::Return`, so that the return type shown in the rustdocs + // is as simple as possible. Break out as soon as we see something we don't + // recognize. + let mut new_output = orig_output.clone(); + let mut found_vc = false; + loop { + new_output = match new_output { + Type::Group(TypeGroup { elem, .. }) => *elem, + Type::Tuple(TypeTuple { elems, .. }) if elems.is_empty() => { + Type::Path(parse_quote!(::turbo_tasks::Vc<()>)) + }, + Type::Path(TypePath { qself: None, path: Path { leading_colon, ref segments } }) => { + let mut pairs = segments.pairs(); + let mut cur_pair = pairs.next(); + + enum PathPrefix { + Anyhow, + TurboTasks, + } + + // try to strip a `turbo_tasks::` or `anyhow::` prefix + let prefix = if let Some(first) = cur_pair.as_ref().map(|p| p.value()) { + if first.arguments.is_none() { + if first.ident == "turbo_tasks" { + Some(PathPrefix::TurboTasks) + } else if first.ident == "anyhow" { + Some(PathPrefix::Anyhow) + } else { + None + } + } else { + None + } + } else { + None + }; + + if prefix.is_some() { + cur_pair = pairs.next(); // strip the matched prefix + } else if leading_colon.is_some() { + break; // something like `::Vc` isn't valid + } + + // Look for a `Vc<...>` or `Result<...>` generic + let Some(Pair::End(PathSegment { + ident, + arguments: + PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }), + })) = cur_pair + else { + break; + }; + if ident == "Vc" { + found_vc = true; + break; // Vc is the bottom-most level + } + if ident == "Result" && args.len() == 1 { + let GenericArgument::Type(ty) = + args.first().expect("Result<...> type has an argument") + else { + break; + }; + ty.clone() + } else { + break; // we only support expanding Result<...> + } + }, + _ => break, + } + } + + if !found_vc { + orig_output + .span() + .unwrap() + .error( + "Expected return type to be `turbo_tasks::Vc` or `anyhow::Result>`. \ + Unable to process type.", + ) + .emit(); + } + + new_output +} + +/// The context in which the function is being defined. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum DefinitionContext { + // The function is defined as a naked #[turbo_tasks::function]. + NakedFn, + // The function is defined as a #[turbo_tasks::value_impl] inherent implementation method. + ValueInherentImpl, + // The function is defined as a #[turbo_tasks::value_impl] trait implementation method. + ValueTraitImpl, + // The function is defined as a #[turbo_tasks::value_trait] default method. + ValueTrait, +} + +impl DefinitionContext { + pub fn function_type(&self) -> &'static str { + match self { + DefinitionContext::NakedFn => "#[turbo_tasks::function] naked functions", + DefinitionContext::ValueInherentImpl => "#[turbo_tasks::value_impl] inherent methods", + DefinitionContext::ValueTraitImpl => "#[turbo_tasks::value_impl] trait methods", + DefinitionContext::ValueTrait => "#[turbo_tasks::value_trait] methods", + } + } +} + +#[derive(Debug)] +pub struct NativeFn { + function_path_string:String, + function_path:ExprPath, +} + +impl NativeFn { + pub fn new(function_path_string:&str, function_path:&ExprPath) -> NativeFn { + NativeFn { + function_path_string:function_path_string.to_owned(), + function_path:function_path.clone(), + } + } + + pub fn ty(&self) -> Type { + parse_quote! { turbo_tasks::macro_helpers::Lazy } + } + + pub fn definition(&self) -> Expr { + let Self { function_path_string, function_path } = self; + + parse_quote! { + turbo_tasks::macro_helpers::Lazy::new(|| { + #[allow(deprecated)] + turbo_tasks::NativeFunction::new(#function_path_string.to_owned(), #function_path) + }) + } + } + + pub fn id_ty(&self) -> Type { + parse_quote! { turbo_tasks::macro_helpers::Lazy } + } + + pub fn id_definition(&self, native_function_id_path:&Path) -> Expr { + parse_quote! { + turbo_tasks::macro_helpers::Lazy::new(|| { + turbo_tasks::registry::get_function_id(&*#native_function_id_path) + }) + } + } +} diff --git a/crates/turbo-tasks-macros/Source/function_macro.rs b/crates/turbo-tasks-macros/Source/function_macro.rs new file mode 100644 index 0000000000000..1b7fd73ac9237 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/function_macro.rs @@ -0,0 +1,55 @@ +use proc_macro::TokenStream; +use proc_macro2::Ident; +use quote::quote; +use syn::{ExprPath, ItemFn, parse_macro_input, parse_quote}; +use turbo_tasks_macros_shared::{get_native_function_id_ident, get_native_function_ident}; + +use crate::func::{DefinitionContext, NativeFn, TurboFn}; + +pub fn function(_args:TokenStream, input:TokenStream) -> TokenStream { + let item = parse_macro_input!(input as ItemFn); + + let ItemFn { attrs, vis, sig, block } = &item; + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::NakedFn) else { + return quote! { + // An error occurred while parsing the function signature. + } + .into(); + }; + + let ident = &sig.ident; + + let inline_function_ident = Ident::new(&format!("{ident}_inline_function"), ident.span()); + let inline_function_path:ExprPath = parse_quote! { #inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let native_fn = NativeFn::new(&ident.to_string(), &inline_function_path); + let native_function_ident = get_native_function_ident(ident); + let native_function_ty = native_fn.ty(); + let native_function_def = native_fn.definition(); + + let native_function_id_ident = get_native_function_id_ident(ident); + let native_function_id_ty = native_fn.id_ty(); + let native_function_id_def = native_fn.id_definition(&native_function_ident.clone().into()); + + let exposed_signature = turbo_fn.signature(); + let exposed_block = turbo_fn.static_block(&native_function_id_ident); + + quote! { + #(#attrs)* + #vis #exposed_signature #exposed_block + + #(#attrs)* + #[doc(hidden)] + #inline_signature #block + + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = #native_function_def; + + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = #native_function_id_def; + } + .into() +} diff --git a/crates/turbo-tasks-macros/Source/generic_type_macro.rs b/crates/turbo-tasks-macros/Source/generic_type_macro.rs new file mode 100644 index 0000000000000..118424c381893 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/generic_type_macro.rs @@ -0,0 +1,148 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{GenericParam, Lifetime, Type, parse_macro_input, spanned::Spanned, visit_mut::VisitMut}; +use turbo_tasks_macros_shared::{GenericTypeInput, get_type_ident}; + +use crate::value_macro::value_type_and_register; + +pub fn generic_type(input:TokenStream) -> TokenStream { + let mut input = parse_macro_input!(input as GenericTypeInput); + + for param in &input.generics.params { + match param { + syn::GenericParam::Type(ty) => { + if ty.ident == "Vc" { + ty.span().unwrap().error("Vc is a reserved name in generic_type").emit(); + } + }, + syn::GenericParam::Lifetime(lt) => { + lt.span() + .unwrap() + .error("lifetime parameters are not supported in generic_type") + .emit(); + }, + syn::GenericParam::Const(c) => { + c.span() + .unwrap() + .error("const parameters are not supported in generic_type") + .emit(); + }, + } + } + + // Add Send bound to input generics. + + for param in &mut input.generics.params { + if let GenericParam::Type(param) = param { + param.bounds.push(syn::parse_quote! { std::marker::Send }); + } + } + + let (impl_generics, _, where_clause) = input.generics.split_for_impl(); + + let repr = replace_generics_with_unit(input.generics.params.iter(), &input.ty); + + let ty = input.ty; + let Some(ident) = get_type_ident(&ty) else { + return quote! { + // An error occurred while parsing the ident. + } + .into(); + }; + + let mut generics_with_static = input.generics.clone(); + for param in &mut generics_with_static.params { + if let GenericParam::Type(param) = param { + param.bounds.push(syn::TypeParamBound::Lifetime(Lifetime { + ident:syn::Ident::new("static", param.ident.span()), + apostrophe:param.ident.span(), + })) + } + } + + let value_type_and_register = value_type_and_register( + &ident, + quote! { #ty }, + Some(&generics_with_static), + quote! { + turbo_tasks::VcTransparentRead<#ty, #ty, #repr> + }, + quote! { + turbo_tasks::VcCellSharedMode<#ty> + }, + quote! { + turbo_tasks::ValueType::new_with_any_serialization::<#repr>() + }, + ); + + quote! { + #value_type_and_register + + impl #impl_generics Vc<#ty> #where_clause { + /// Converts this `Vc` to a generic representation. + fn to_repr(vc: Self) -> Vc<#repr> { + unsafe { + turbo_tasks::Vc::from_raw(Vc::into_raw(vc)) + } + } + + /// Converts a generic representation of this `Vc` to the proper `Vc` type. + /// + /// # Safety + /// + /// The caller must ensure that the `repr` is a valid representation of this `Vc`. + unsafe fn from_repr(vc: Vc<#repr>) -> Self { + unsafe { + turbo_tasks::Vc::from_raw(Vc::into_raw(vc)) + } + } + } + } + .into() +} + +struct ReplaceGenericsVisitor<'a> { + generics:&'a std::collections::HashSet, +} + +impl<'a> VisitMut for ReplaceGenericsVisitor<'a> { + fn visit_type_mut(&mut self, node:&mut Type) { + if let Type::Path(type_path) = node { + if type_path.qself.is_none() + && type_path.path.segments.len() == 1 + && type_path.path.segments[0].arguments.is_none() + && self.generics.contains(&type_path.path.segments[0].ident.to_string()) + { + // Replace the whole path with () + *node = syn::parse_quote! { () }; + return; + } + } + + syn::visit_mut::visit_type_mut(self, node); + } +} + +/// Replaces all instances of `params` generic types in `ty` with the unit type +/// `()`. +fn replace_generics_with_unit<'a, P>(params:P, ty:&Type) -> Type +where + P: IntoIterator, { + let generics_set:std::collections::HashSet<_> = params + .into_iter() + .filter_map(|param| { + if let GenericParam::Type(type_param) = param { + Some(type_param.ident.to_string()) + } else { + None + } + }) + .collect(); + + let mut new_ty = ty.clone(); + let mut visitor = ReplaceGenericsVisitor { generics:&generics_set }; + + syn::visit_mut::visit_type_mut(&mut visitor, &mut new_ty); + + new_ty +} diff --git a/crates/turbo-tasks-macros/Source/lib.rs b/crates/turbo-tasks-macros/Source/lib.rs new file mode 100644 index 0000000000000..8a11cef4b92b1 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/lib.rs @@ -0,0 +1,168 @@ +#![allow(internal_features)] +#![feature(proc_macro_diagnostic)] +#![feature(allow_internal_unstable)] +#![feature(box_patterns)] + +mod derive; +mod func; +mod function_macro; +mod generic_type_macro; +mod primitive_macro; +mod value_impl_macro; +mod value_macro; +mod value_trait_macro; + +extern crate proc_macro; + +use proc_macro::TokenStream; +use proc_macro_error::proc_macro_error; + +#[proc_macro_derive(TraceRawVcs, attributes(turbo_tasks))] +pub fn derive_trace_raw_vcs_attr(input:TokenStream) -> TokenStream { + derive::derive_trace_raw_vcs(input) +} + +#[proc_macro_derive(ValueDebug, attributes(turbo_tasks))] +pub fn derive_value_debug_attr(input:TokenStream) -> TokenStream { + derive::derive_value_debug(input) +} + +#[proc_macro_derive(ValueDebugFormat, attributes(turbo_tasks))] +pub fn derive_value_debug_format_attr(input:TokenStream) -> TokenStream { + derive::derive_value_debug_format(input) +} + +#[proc_macro_derive(DeterministicHash, attributes(turbo_tasks))] +pub fn derive_deterministic_hash(input:TokenStream) -> TokenStream { + derive::derive_deterministic_hash(input) +} + +#[proc_macro_derive(TaskInput, attributes(turbo_tasks))] +pub fn derive_task_input(input:TokenStream) -> TokenStream { derive::derive_task_input(input) } + +/// Creates a Vc struct for a `struct` or `enum` that represent +/// that type placed into a cell in a Task. +/// +/// That Vc object can be `await`ed to get a readonly reference +/// to the value contained in the cell. +/// +/// ## Arguments +/// +/// Example: `#[turbo_tasks::value(into = "new", eq = "manual")]` +/// +/// ### `cell` +/// +/// Possible values: +/// +/// - "new": Always overrides the value in the cell. Invalidating all +/// dependent tasks. +/// - "shared" (default): Compares with the existing value in the cell, before +/// overriding it. Requires Value to implement [Eq]. +/// +/// ### `eq` +/// +/// Possible values: +/// +/// - "manual": Prevents deriving [Eq] so you can do it manually. +/// +/// ### `into` +/// +/// When provided the Vc implement `From` to allow to convert +/// a Value to a Vc by placing it into a cell in a Task. +/// +/// Possible values: +/// +/// - "new": Always overrides the value in the cell. Invalidating all +/// dependent tasks. +/// - "shared": Compares with the existing value in the cell, before +/// overriding it. Requires Value to implement [Eq]. +/// - "none" (default): Prevents implementing `From`. +/// +/// ### `serialization` +/// +/// Affects serialization via [serde::Serialize] and [serde::Deserialize]. +/// +/// Possible values: +/// +/// - "auto" (default): Derives the serialization traits and enabled +/// serialization. +/// - "auto_for_input": Same as "auto", but also adds the marker trait +/// [turbo_tasks::TypedForInput]. +/// - "custom": Prevents deriving the serialization traits, but still enables +/// serialization (you need to manually implement [serde::Serialize] and +/// [serde::Deserialize]). +/// - "custom_for_input":Same as "auto", but also adds the marker trait +/// [turbo_tasks::TypedForInput]. +/// - "none": Disables serialization and prevents deriving the traits. +/// +/// ### `shared` +/// +/// Sets both `cell = "shared"` and `into = "shared"` +/// +/// No value. +/// +/// Example: `#[turbo_tasks::value(shared)]` +/// +/// ### `transparent` +/// +/// If applied to a unit struct (e.g. `struct Wrapper(Value)`) the outer struct +/// is skipped for all operations (cell, into, reading). +/// +/// No value. +/// +/// Example: `#[turbo_tasks::value(transparent)]` +/// +/// TODO: add more documentation: presets, traits +#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)] +#[proc_macro_error] +#[proc_macro_attribute] +pub fn value(args:TokenStream, input:TokenStream) -> TokenStream { value_macro::value(args, input) } + +#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)] +#[proc_macro_error] +#[proc_macro_attribute] +pub fn value_trait(args:TokenStream, input:TokenStream) -> TokenStream { + value_trait_macro::value_trait(args, input) +} + +#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)] +#[proc_macro_error] +#[proc_macro_attribute] +pub fn function(args:TokenStream, input:TokenStream) -> TokenStream { + function_macro::function(args, input) +} + +#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)] +#[proc_macro_error] +#[proc_macro_attribute] +pub fn value_impl(args:TokenStream, input:TokenStream) -> TokenStream { + value_impl_macro::value_impl(args, input) +} + +#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)] +#[proc_macro_error] +#[proc_macro] +pub fn primitive(input:TokenStream) -> TokenStream { primitive_macro::primitive(input) } + +/// Registers a value type that is generic over the `Vc` it contains. +/// +/// # Example +/// +/// ``` +/// use crate::generic_type as __turbo_tasks_internal_generic_type; +/// +/// __turbo_tasks_internal_generic_type!(, GenericType, Vc>); +/// +/// // Now you can do the following, for any `A` and `B` value types: +/// +/// let vc: Vc, Vc>> = Vc::cell( +/// GenericType::new( +/// Vc::cell(42), +/// Vc::cell("hello".to_string()) +/// ) +/// ); +/// ``` +#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)] +#[proc_macro_error] +#[proc_macro] +pub fn generic_type(input:TokenStream) -> TokenStream { generic_type_macro::generic_type(input) } diff --git a/crates/turbo-tasks-macros/Source/primitive_macro.rs b/crates/turbo-tasks-macros/Source/primitive_macro.rs new file mode 100644 index 0000000000000..026a8c0bec55e --- /dev/null +++ b/crates/turbo-tasks-macros/Source/primitive_macro.rs @@ -0,0 +1,69 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::parse_macro_input; +use turbo_tasks_macros_shared::{PrimitiveInput, get_type_ident}; + +use crate::value_macro::value_type_and_register; + +pub fn primitive(input:TokenStream) -> TokenStream { + let input = parse_macro_input!(input as PrimitiveInput); + + let ty = input.ty; + let Some(ident) = get_type_ident(&ty) else { + return quote! { + // An error occurred while parsing the ident. + } + .into(); + }; + + let value_debug_impl = quote! { + #[turbo_tasks::value_impl] + impl turbo_tasks::debug::ValueDebug for #ty { + #[turbo_tasks::function] + async fn dbg(&self) -> anyhow::Result> { + use turbo_tasks::debug::ValueDebugFormat; + self.value_debug_format(usize::MAX).try_to_value_debug_string().await + } + + #[turbo_tasks::function] + async fn dbg_depth(&self, depth: usize) -> anyhow::Result> { + use turbo_tasks::debug::ValueDebugFormat; + self.value_debug_format(depth).try_to_value_debug_string().await + } + } + }; + + let value_type_and_register = value_type_and_register( + &ident, + quote! { #ty }, + None, + quote! { + turbo_tasks::VcTransparentRead<#ty, #ty, #ty> + }, + quote! { + turbo_tasks::VcCellSharedMode<#ty> + }, + quote! { + turbo_tasks::ValueType::new_with_any_serialization::<#ty>() + }, + ); + + let value_default_impl = quote! { + #[turbo_tasks::value_impl] + impl turbo_tasks::ValueDefault for #ty { + #[turbo_tasks::function] + fn value_default() -> Vc { + Vc::cell(Default::default()) + } + } + }; + + quote! { + #value_type_and_register + + #value_debug_impl + + #value_default_impl + } + .into() +} diff --git a/crates/turbo-tasks-macros/Source/value_impl_macro.rs b/crates/turbo-tasks-macros/Source/value_impl_macro.rs new file mode 100644 index 0000000000000..b976b73d871c4 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/value_impl_macro.rs @@ -0,0 +1,335 @@ +use proc_macro::TokenStream; +use proc_macro2::{Ident, TokenStream as TokenStream2}; +use quote::{ToTokens, quote}; +use syn::{ + Attribute, + Error, + ExprPath, + Generics, + ImplItem, + ImplItemMethod, + ItemImpl, + Lit, + LitStr, + Meta, + MetaNameValue, + Path, + Result, + Token, + Type, + parse::{Parse, ParseStream}, + parse_macro_input, + parse_quote, + punctuated::Punctuated, + spanned::Spanned, +}; +use turbo_tasks_macros_shared::{ + get_inherent_impl_function_id_ident, + get_inherent_impl_function_ident, + get_path_ident, + get_register_trait_methods_ident, + get_trait_impl_function_id_ident, + get_trait_impl_function_ident, + get_type_ident, +}; + +use crate::func::{DefinitionContext, NativeFn, TurboFn}; + +fn is_attribute(attr:&Attribute, name:&str) -> bool { + let path = &attr.path; + if path.leading_colon.is_some() { + return false; + } + let mut iter = path.segments.iter(); + match iter.next() { + Some(seg) if seg.arguments.is_empty() && seg.ident == "turbo_tasks" => { + match iter.next() { + Some(seg) if seg.arguments.is_empty() && seg.ident == name => iter.next().is_none(), + _ => false, + } + }, + _ => false, + } +} + +fn strip_function_attribute<'a>(item:&'a ImplItem, attrs:&'a [Attribute]) -> Vec<&'a Attribute> { + let (function_attrs, attrs):(Vec<_>, Vec<_>) = attrs + .iter() + // TODO(alexkirsz) Replace this with function + .partition(|attr| is_attribute(attr, "function")); + if function_attrs.is_empty() { + item.span().unwrap().error("#[turbo_tasks::function] attribute missing").emit(); + } + attrs +} + +struct ValueImplArguments { + ident:Option, +} + +impl Parse for ValueImplArguments { + fn parse(input:ParseStream) -> Result { + let mut result = ValueImplArguments { ident:None }; + let punctuated:Punctuated = input.parse_terminated(Meta::parse)?; + for meta in punctuated { + match ( + meta.path().get_ident().map(ToString::to_string).as_deref().unwrap_or_default(), + meta, + ) { + ("ident", Meta::NameValue(MetaNameValue { lit: Lit::Str(lit), .. })) => { + result.ident = Some(lit); + }, + (_, meta) => { + return Err(Error::new_spanned( + &meta, + format!("unexpected {:?}, expected \"ident\"", meta), + )); + }, + } + } + + Ok(result) + } +} + +pub fn value_impl(args:TokenStream, input:TokenStream) -> TokenStream { + let ValueImplArguments { ident } = parse_macro_input!(args as ValueImplArguments); + + fn inherent_value_impl(ty:&Type, ty_ident:&Ident, items:&[ImplItem]) -> TokenStream2 { + let mut all_definitions = Vec::new(); + let mut exposed_impl_items = Vec::new(); + + for item in items.iter() { + if let ImplItem::Method(ImplItemMethod { attrs, vis, defaultness: _, sig, block }) = + item + { + let attrs = strip_function_attribute(item, attrs); + + let ident = &sig.ident; + + // TODO(alexkirsz) These should go into their own utilities. + let inline_function_ident:Ident = + Ident::new(&format!("{}_inline", ident), ident.span()); + let inline_function_path:ExprPath = parse_quote! { <#ty>::#inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::ValueInherentImpl) else { + return quote! { + // An error occurred while parsing the function signature. + }; + }; + + let native_fn = NativeFn::new( + &format!("{ty}::{ident}", ty = ty.to_token_stream()), + &inline_function_path, + ); + + let native_function_ident = get_inherent_impl_function_ident(ty_ident, ident); + let native_function_ty = native_fn.ty(); + let native_function_def = native_fn.definition(); + let native_function_id_ident = get_inherent_impl_function_id_ident(ty_ident, ident); + let native_function_id_ty = native_fn.id_ty(); + let native_function_id_def = native_fn.id_definition(&parse_quote! { + #native_function_ident + }); + + let turbo_signature = turbo_fn.signature(); + let turbo_block = turbo_fn.static_block(&native_function_id_ident); + exposed_impl_items.push(quote! { + #(#attrs)* + #vis #turbo_signature #turbo_block + }); + + all_definitions.push(quote! { + #[doc(hidden)] + impl #ty { + // By declaring the native function's body within an `impl` block, we ensure that `Self` refers + // to `#ty`. This is necessary because the function's body is originally declared within an + // `impl` block already. + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_ident: #native_function_ty = #native_function_def; + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_id_ident: #native_function_id_ty = #native_function_id_def; + + #(#attrs)* + #[doc(hidden)] + #[deprecated(note = "This function is only exposed for use in macros. Do not call it directly.")] + pub(self) #inline_signature #block + } + + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = <#ty>::#native_function_ident; + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = <#ty>::#native_function_id_ident; + }) + } + } + + quote! { + impl #ty { + #(#exposed_impl_items)* + } + + #(#all_definitions)* + } + } + + fn trait_value_impl( + ty:&Type, + generics:&Generics, + ty_ident:&Ident, + trait_path:&Path, + items:&[ImplItem], + ) -> TokenStream2 { + let trait_ident = get_path_ident(trait_path); + + let (impl_generics, _, where_clause) = generics.split_for_impl(); + + let register = get_register_trait_methods_ident(&trait_ident, ty_ident); + + let mut trait_registers = Vec::new(); + let mut trait_functions = Vec::with_capacity(items.len()); + let mut all_definitions = Vec::with_capacity(items.len()); + + for item in items.iter() { + if let ImplItem::Method(ImplItemMethod { sig, attrs, block, .. }) = item { + let ident = &sig.ident; + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::ValueTraitImpl) else { + return quote! { + // An error occurred while parsing the function signature. + }; + }; + + let attrs = strip_function_attribute(item, attrs); + + // TODO(alexkirsz) These should go into their own utilities. + let inline_function_ident:Ident = + Ident::new(&format!("{}_inline", ident), ident.span()); + let inline_extension_trait_ident = Ident::new( + &format!("{}_{}_{}_inline", ty_ident, trait_ident, ident), + ident.span(), + ); + let inline_function_path:ExprPath = + parse_quote! { <#ty as #inline_extension_trait_ident>::#inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let native_fn = NativeFn::new( + &format!( + "<{ty} as {trait_path}>::{ident}", + ty = ty.to_token_stream(), + trait_path = trait_path.to_token_stream() + ), + &inline_function_path, + ); + + let native_function_ident = + get_trait_impl_function_ident(ty_ident, &trait_ident, ident); + + let native_function_ty = native_fn.ty(); + let native_function_def = native_fn.definition(); + let native_function_id_ident = + get_trait_impl_function_id_ident(ty_ident, &trait_ident, ident); + let native_function_id_ty = native_fn.id_ty(); + let native_function_id_def = native_fn.id_definition(&parse_quote! { + #native_function_ident + }); + + let turbo_signature = turbo_fn.signature(); + let turbo_block = turbo_fn.static_block(&native_function_id_ident); + + trait_functions.push(quote! { + #(#attrs)* + #turbo_signature #turbo_block + }); + + all_definitions.push(quote! { + #[doc(hidden)] + #[allow(non_camel_case_types)] + // #[turbo_tasks::async_trait] + trait #inline_extension_trait_ident: std::marker::Send { + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_ident: #native_function_ty; + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_id_ident: #native_function_id_ty; + + #(#attrs)* + #[doc(hidden)] + #inline_signature; + } + + #[doc(hidden)] + // #[turbo_tasks::async_trait] + impl #impl_generics #inline_extension_trait_ident for #ty #where_clause { + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_ident: #native_function_ty = #native_function_def; + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_id_ident: #native_function_id_ty = #native_function_id_def; + + #(#attrs)* + #[doc(hidden)] + #[deprecated(note = "This function is only exposed for use in macros. Do not call it directly.")] + #inline_signature #block + } + + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = <#ty as #inline_extension_trait_ident>::#native_function_ident; + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = <#ty as #inline_extension_trait_ident>::#native_function_id_ident; + }); + + trait_registers.push(quote! { + value.register_trait_method( as turbo_tasks::VcValueTrait>::get_trait_type_id(), stringify!(#ident).into(), *#native_function_id_ident); + }); + } + } + + quote! { + #[doc(hidden)] + #[allow(non_snake_case)] + pub(crate) fn #register(value: &mut turbo_tasks::ValueType) { + value.register_trait( as turbo_tasks::VcValueTrait>::get_trait_type_id()); + #(#trait_registers)* + } + + // NOTE(alexkirsz) We can't have a general `turbo_tasks::Upcast> for T where T: Trait` because + // rustc complains: error[E0210]: type parameter `T` must be covered by another type when it appears before + // the first local type (`dyn Trait`). + unsafe impl #impl_generics turbo_tasks::Upcast> for #ty #where_clause {} + + impl #impl_generics #trait_path for #ty #where_clause { + #(#trait_functions)* + } + + #(#all_definitions)* + } + } + + let item = parse_macro_input!(input as ItemImpl); + + let Some(ty_ident) = ident + .map(|ident| Ident::new(&ident.value(), ident.span())) + .or_else(|| get_type_ident(&item.self_ty)) + else { + return quote! { + // An error occurred while parsing the type. + } + .into(); + }; + + match &item.trait_ { + None => inherent_value_impl(&item.self_ty, &ty_ident, &item.items).into(), + Some((_, trait_path, _)) => { + trait_value_impl(&item.self_ty, &item.generics, &ty_ident, trait_path, &item.items) + .into() + }, + } +} diff --git a/crates/turbo-tasks-macros/Source/value_macro.rs b/crates/turbo-tasks-macros/Source/value_macro.rs new file mode 100644 index 0000000000000..024e41d1c6e01 --- /dev/null +++ b/crates/turbo-tasks-macros/Source/value_macro.rs @@ -0,0 +1,483 @@ +use std::sync::OnceLock; + +use proc_macro::TokenStream; +use proc_macro2::Ident; +use quote::{ToTokens, quote}; +use regex::Regex; +use syn::{ + Error, + Fields, + FieldsUnnamed, + Generics, + Item, + ItemEnum, + ItemStruct, + Lit, + LitStr, + Meta, + MetaNameValue, + Result, + Token, + parse::{Parse, ParseStream}, + parse_macro_input, + parse_quote, + punctuated::Punctuated, + spanned::Spanned, +}; +use turbo_tasks_macros_shared::{ + get_register_value_type_ident, + get_value_type_id_ident, + get_value_type_ident, + get_value_type_init_ident, +}; + +enum IntoMode { + None, + New, + Shared, +} + +impl Parse for IntoMode { + fn parse(input:ParseStream) -> Result { + let ident = input.parse::()?; + Self::try_from(ident) + } +} + +impl TryFrom for IntoMode { + type Error = Error; + + fn try_from(lit:LitStr) -> std::result::Result { + match lit.value().as_str() { + "none" => Ok(IntoMode::None), + "new" => Ok(IntoMode::New), + "shared" => Ok(IntoMode::Shared), + _ => Err(Error::new_spanned(&lit, "expected \"none\", \"new\" or \"shared\"")), + } + } +} + +enum CellMode { + New, + Shared, +} + +impl Parse for CellMode { + fn parse(input:ParseStream) -> Result { + let ident = input.parse::()?; + Self::try_from(ident) + } +} + +impl TryFrom for CellMode { + type Error = Error; + + fn try_from(lit:LitStr) -> std::result::Result { + match lit.value().as_str() { + "new" => Ok(CellMode::New), + "shared" => Ok(CellMode::Shared), + _ => Err(Error::new_spanned(&lit, "expected \"new\" or \"shared\"")), + } + } +} + +enum SerializationMode { + None, + Auto, + AutoForInput, + Custom, + CustomForInput, +} + +impl Parse for SerializationMode { + fn parse(input:ParseStream) -> Result { + let ident = input.parse::()?; + Self::try_from(ident) + } +} + +impl TryFrom for SerializationMode { + type Error = Error; + + fn try_from(lit:LitStr) -> std::result::Result { + match lit.value().as_str() { + "none" => Ok(SerializationMode::None), + "auto" => Ok(SerializationMode::Auto), + "auto_for_input" => Ok(SerializationMode::AutoForInput), + "custom" => Ok(SerializationMode::Custom), + "custom_for_input" => Ok(SerializationMode::CustomForInput), + _ => { + Err(Error::new_spanned( + &lit, + "expected \"none\", \"auto\", \"auto_for_input\", \"custom\" or \ + \"custom_for_input\"", + )) + }, + } + } +} + +struct ValueArguments { + serialization_mode:SerializationMode, + into_mode:IntoMode, + cell_mode:CellMode, + manual_eq:bool, + transparent:bool, +} + +impl Parse for ValueArguments { + fn parse(input:ParseStream) -> Result { + let mut result = ValueArguments { + serialization_mode:SerializationMode::Auto, + into_mode:IntoMode::None, + cell_mode:CellMode::Shared, + manual_eq:false, + transparent:false, + }; + let punctuated:Punctuated = input.parse_terminated(Meta::parse)?; + for meta in punctuated { + match ( + meta.path().get_ident().map(ToString::to_string).as_deref().unwrap_or_default(), + meta, + ) { + ("shared", Meta::Path(_)) => { + result.into_mode = IntoMode::Shared; + result.cell_mode = CellMode::Shared; + }, + ("into", Meta::NameValue(MetaNameValue { lit: Lit::Str(str), .. })) => { + result.into_mode = IntoMode::try_from(str)?; + }, + ("serialization", Meta::NameValue(MetaNameValue { lit: Lit::Str(str), .. })) => { + result.serialization_mode = SerializationMode::try_from(str)?; + }, + ("cell", Meta::NameValue(MetaNameValue { lit: Lit::Str(str), .. })) => { + result.cell_mode = CellMode::try_from(str)?; + }, + ("eq", Meta::NameValue(MetaNameValue { lit: Lit::Str(str), .. })) => { + result.manual_eq = if str.value() == "manual" { + true + } else { + return Err(Error::new_spanned(&str, "expected \"manual\"")); + }; + }, + ("transparent", Meta::Path(_)) => { + result.transparent = true; + }, + (_, meta) => { + return Err(Error::new_spanned( + &meta, + format!( + "unexpected {:?}, expected \"shared\", \"into\", \"serialization\", \ + \"cell\", \"eq\", \"transparent\"", + meta + ), + )); + }, + } + } + + Ok(result) + } +} + +pub fn value(args:TokenStream, input:TokenStream) -> TokenStream { + let mut item = parse_macro_input!(input as Item); + let ValueArguments { serialization_mode, into_mode, cell_mode, manual_eq, transparent } = + parse_macro_input!(args as ValueArguments); + + let mut inner_type = None; + if transparent { + if let Item::Struct(ItemStruct { + attrs, + fields: Fields::Unnamed(FieldsUnnamed { unnamed, .. }), + .. + }) = &mut item + { + if unnamed.len() == 1 { + let field = unnamed.iter().next().unwrap(); + inner_type = Some(field.ty.clone()); + + // generate a type string to add to the docs + let inner_type_string = inner_type.to_token_stream().to_string(); + + // HACK: proc_macro2 inserts whitespace between every token. It's ugly, so + // remove it, assuming these whitespace aren't syntatically important. Using + // prettyplease (or similar) would be more correct, but slower and add another + // dependency. + static WHITESPACE_RE:OnceLock = OnceLock::new(); + // Remove whitespace, as long as there is a non-word character (e.g. `>` or `,`) + // on either side. Try not to remove whitespace between `dyn Trait`. + let whitespace_re = WHITESPACE_RE.get_or_init(|| { + Regex::new(r"\b \B|\B \b|\B \B").expect("WHITESPACE_RE is valid") + }); + let inner_type_string = whitespace_re.replace_all(&inner_type_string, ""); + + // Add a couple blank lines in case there's already a doc comment we're + // effectively appending to. If there's not, rustdoc will strip + // the leading whitespace. + let doc_str = format!( + "\n\nThis is a [transparent value type][::turbo_tasks::value#transparent] \ + wrapping [`{}`].", + inner_type_string, + ); + + attrs.push(parse_quote! { + #[doc = #doc_str] + }); + } + } + if inner_type.is_none() { + item.span() + .unwrap() + .error( + "#[turbo_tasks::value(transparent)] is only valid with single-item unit \ + structs", + ) + .emit(); + } + } + + let ident = match &item { + Item::Enum(ItemEnum { ident, .. }) => ident, + Item::Struct(ItemStruct { ident, .. }) => ident, + _ => { + item.span().unwrap().error("unsupported syntax").emit(); + + return quote! { + #item + } + .into(); + }, + }; + + let cell_mode = match cell_mode { + CellMode::New => { + quote! { + turbo_tasks::VcCellNewMode<#ident> + } + }, + CellMode::Shared => { + quote! { + turbo_tasks::VcCellSharedMode<#ident> + } + }, + }; + + let (cell_prefix, cell_access_content, read) = if let Some(inner_type) = &inner_type { + ( + quote! { pub }, + quote! { + content.0 + }, + quote! { + turbo_tasks::VcTransparentRead::<#ident, #inner_type, #ident> + }, + ) + } else { + ( + if let IntoMode::New | IntoMode::Shared = into_mode { + quote! { pub } + } else { + quote! {} + }, + quote! { content }, + quote! { + turbo_tasks::VcDefaultRead::<#ident> + }, + ) + }; + + let cell_struct = quote! { + /// Places a value in a cell of the current task. + /// + /// Cell is selected based on the value type and call order of `cell`. + #cell_prefix fn cell(self) -> turbo_tasks::Vc { + let content = self; + turbo_tasks::Vc::cell_private(#cell_access_content) + } + }; + + let into = if let IntoMode::New | IntoMode::Shared = into_mode { + quote! { + impl Into> for #ident { + fn into(self) -> turbo_tasks::Vc<#ident> { + self.cell() + } + } + } + } else { + quote! {} + }; + + let derive = match serialization_mode { + SerializationMode::None | SerializationMode::Custom | SerializationMode::CustomForInput => { + quote! { + #[derive(turbo_tasks::trace::TraceRawVcs)] + } + }, + SerializationMode::Auto | SerializationMode::AutoForInput => { + quote! { + #[derive(turbo_tasks::trace::TraceRawVcs, serde::Serialize, serde::Deserialize)] + } + }, + }; + let debug_derive = if inner_type.is_some() { + // Transparent structs have their own manual `ValueDebug` implementation. + quote! { + #[repr(transparent)] + } + } else { + quote! { + #[derive(turbo_tasks::debug::ValueDebugFormat, turbo_tasks::debug::internal::ValueDebug)] + } + }; + let eq_derive = if manual_eq { + quote!() + } else { + quote!( + #[derive(PartialEq, Eq)] + ) + }; + + let new_value_type = match serialization_mode { + SerializationMode::None => { + quote! { + turbo_tasks::ValueType::new::<#ident>() + } + }, + SerializationMode::Auto | SerializationMode::Custom => { + quote! { + turbo_tasks::ValueType::new_with_any_serialization::<#ident>() + } + }, + SerializationMode::AutoForInput | SerializationMode::CustomForInput => { + quote! { + turbo_tasks::ValueType::new_with_magic_serialization::<#ident>() + } + }, + }; + + let for_input_marker = match serialization_mode { + SerializationMode::None | SerializationMode::Auto | SerializationMode::Custom => quote! {}, + SerializationMode::AutoForInput | SerializationMode::CustomForInput => { + quote! { + impl turbo_tasks::TypedForInput for #ident {} + } + }, + }; + + let value_debug_impl = if inner_type.is_some() { + // For transparent values, we defer directly to the inner type's `ValueDebug` + // implementation. + quote! { + #[turbo_tasks::value_impl] + impl turbo_tasks::debug::ValueDebug for #ident { + #[turbo_tasks::function] + async fn dbg(&self) -> anyhow::Result> { + use turbo_tasks::debug::ValueDebugFormat; + (&self.0).value_debug_format(usize::MAX).try_to_value_debug_string().await + } + + #[turbo_tasks::function] + async fn dbg_depth(&self, depth: usize) -> anyhow::Result> { + use turbo_tasks::debug::ValueDebugFormat; + (&self.0).value_debug_format(depth).try_to_value_debug_string().await + } + } + } + } else { + quote! {} + }; + + let value_type_and_register_code = + value_type_and_register(ident, quote! { #ident }, None, read, cell_mode, new_value_type); + + let expanded = quote! { + #derive + #eq_derive + #debug_derive + #item + + impl #ident { + #cell_struct + } + + #into + + #value_type_and_register_code + + #for_input_marker + + #value_debug_impl + }; + + expanded.into() +} + +pub fn value_type_and_register( + ident:&Ident, + ty:proc_macro2::TokenStream, + generics:Option<&Generics>, + read:proc_macro2::TokenStream, + cell_mode:proc_macro2::TokenStream, + new_value_type:proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + let value_type_init_ident = get_value_type_init_ident(ident); + let value_type_ident = get_value_type_ident(ident); + let value_type_id_ident = get_value_type_id_ident(ident); + let register_value_type_ident = get_register_value_type_ident(ident); + + let (impl_generics, where_clause) = if let Some(generics) = generics { + let (impl_generics, _, where_clause) = generics.split_for_impl(); + (quote! { #impl_generics }, quote! { #where_clause }) + } else { + (quote!(), quote!()) + }; + + quote! { + #[doc(hidden)] + static #value_type_init_ident: turbo_tasks::macro_helpers::OnceCell< + turbo_tasks::ValueType, + > = turbo_tasks::macro_helpers::OnceCell::new(); + #[doc(hidden)] + pub(crate) static #value_type_ident: turbo_tasks::macro_helpers::Lazy<&turbo_tasks::ValueType> = + turbo_tasks::macro_helpers::Lazy::new(|| { + #value_type_init_ident.get_or_init(|| { + panic!( + concat!( + stringify!(#value_type_ident), + " has not been initialized (this should happen via the generated register function)" + ) + ) + }) + }); + #[doc(hidden)] + static #value_type_id_ident: turbo_tasks::macro_helpers::Lazy = + turbo_tasks::macro_helpers::Lazy::new(|| { + turbo_tasks::registry::get_value_type_id(*#value_type_ident) + }); + + + #[doc(hidden)] + #[allow(non_snake_case)] + pub(crate) fn #register_value_type_ident( + global_name: &'static str, + f: impl FnOnce(&mut turbo_tasks::ValueType), + ) { + #value_type_init_ident.get_or_init(|| { + let mut value = #new_value_type; + f(&mut value); + value + }).register(global_name); + } + + unsafe impl #impl_generics turbo_tasks::VcValueType for #ty #where_clause { + type Read = #read; + type CellMode = #cell_mode; + + fn get_value_type_id() -> turbo_tasks::ValueTypeId { + *#value_type_id_ident + } + } + } +} diff --git a/crates/turbo-tasks-macros/Source/value_trait_macro.rs b/crates/turbo-tasks-macros/Source/value_trait_macro.rs new file mode 100644 index 0000000000000..2865ae580c29e --- /dev/null +++ b/crates/turbo-tasks-macros/Source/value_trait_macro.rs @@ -0,0 +1,248 @@ +use proc_macro::TokenStream; +use proc_macro2::{Ident, TokenStream as TokenStream2}; +use quote::quote; +use syn::{ + ExprPath, + ItemTrait, + TraitItem, + TraitItemMethod, + parse_macro_input, + parse_quote, + spanned::Spanned, +}; +use turbo_tasks_macros_shared::{ + ValueTraitArguments, + get_trait_default_impl_function_id_ident, + get_trait_default_impl_function_ident, + get_trait_type_id_ident, + get_trait_type_ident, +}; + +use crate::func::{DefinitionContext, NativeFn, TurboFn}; + +pub fn value_trait(args:TokenStream, input:TokenStream) -> TokenStream { + let ValueTraitArguments { debug } = parse_macro_input!(args as ValueTraitArguments); + + let item = parse_macro_input!(input as ItemTrait); + + let ItemTrait { + vis, + ident: trait_ident, + items: raw_items, + supertraits, + attrs, + trait_token, + colon_token: _, + unsafety, + auto_token, + generics, + brace_token: _, + } = &item; + + if unsafety.is_some() { + item.span() + .unwrap() + .error("unsafe traits are not supported in #[turbo_tasks::value_trait]") + .emit(); + } + + if auto_token.is_some() { + item.span() + .unwrap() + .error("auto traits are not supported in #[turbo_tasks::value_trait]") + .emit(); + } + + if !generics.params.is_empty() { + item.span() + .unwrap() + .error("generic traits are not supported in #[turbo_tasks::value_trait]") + .emit(); + } + + if generics.where_clause.is_some() { + item.span() + .unwrap() + .error("where clauses are not supported in #[turbo_tasks::value_trait]") + .emit(); + } + + let supertraits = supertraits.into_iter().collect::>(); + + let trait_type_ident = get_trait_type_ident(trait_ident); + let trait_type_id_ident = get_trait_type_id_ident(trait_ident); + let mut dynamic_trait_fns = Vec::new(); + let mut default_method_registers:Vec = Vec::new(); + let mut native_functions = Vec::new(); + let mut items = Vec::with_capacity(raw_items.len()); + + for item in raw_items.iter() { + let TraitItem::Method(TraitItemMethod { sig, default, attrs, semi_token: _ }) = item else { + item.span() + .unwrap() + .error("only methods are allowed in a #[turbo_tasks::value_trait] trait") + .emit(); + continue; + }; + + let ident = &sig.ident; + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::ValueTrait) else { + return quote! { + // An error occurred while parsing the function signature. + } + .into(); + }; + + let turbo_signature = turbo_fn.signature(); + let dynamic_block = turbo_fn.dynamic_block(&trait_type_id_ident); + dynamic_trait_fns.push(quote! { + #turbo_signature #dynamic_block + }); + + let default = if let Some(block) = default { + // TODO(alexkirsz) These should go into their own utilities. + let inline_function_ident:Ident = + Ident::new(&format!("{}_inline", ident), ident.span()); + let inline_extension_trait_ident = + Ident::new(&format!("{}_{}_inline", trait_ident, ident), ident.span()); + let inline_function_path:ExprPath = parse_quote! { as #inline_extension_trait_ident>::#inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let native_function = + NativeFn::new(&format!("{trait_ident}::{ident}"), &inline_function_path); + + let native_function_ident = get_trait_default_impl_function_ident(trait_ident, ident); + let native_function_ty = native_function.ty(); + let native_function_def = native_function.definition(); + let native_function_id_ident = + get_trait_default_impl_function_id_ident(trait_ident, ident); + let native_function_id_ty = native_function.id_ty(); + let native_function_id_def = native_function.id_definition(&parse_quote! { + #native_function_ident + }); + + default_method_registers.push(quote! { + trait_type.register_default_trait_method(stringify!(#ident).into(), *#native_function_id_ident); + }); + + native_functions.push(quote! { + #[doc(hidden)] + #[allow(non_camel_case_types)] + // #[turbo_tasks::async_trait] + trait #inline_extension_trait_ident: std::marker::Send { + #[allow(declare_interior_mutable_const)] + const #native_function_ident: #native_function_ty; + #[allow(declare_interior_mutable_const)] + const #native_function_id_ident: #native_function_id_ty; + + #(#attrs)* + #inline_signature; + } + + #[doc(hidden)] + // #[turbo_tasks::async_trait] + // Needs to be explicit 'static here, otherwise we can get a lifetime error + // in the inline signature. + impl #inline_extension_trait_ident for Box { + #[allow(declare_interior_mutable_const)] + const #native_function_ident: #native_function_ty = #native_function_def; + #[allow(declare_interior_mutable_const)] + const #native_function_id_ident: #native_function_id_ty = #native_function_id_def; + + #(#attrs)* + #inline_signature #block + } + + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = as #inline_extension_trait_ident>::#native_function_ident; + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = as #inline_extension_trait_ident>::#native_function_id_ident; + }); + + Some(turbo_fn.static_block(&native_function_id_ident)) + } else { + None + }; + + items.push(TraitItem::Method(TraitItemMethod { + sig:turbo_fn.trait_signature(), + default, + attrs:attrs.clone(), + semi_token:Default::default(), + })); + } + + let value_debug_impl = if debug { + quote! { + #[turbo_tasks::value_impl] + impl turbo_tasks::debug::ValueDebug for Box { + #[turbo_tasks::function] + pub fn dbg(self: turbo_tasks::Vc) -> turbo_tasks::Vc { + use turbo_tasks::debug::ValueDebug; + self.dbg_depth(usize::MAX) + } + + #[turbo_tasks::function] + pub async fn dbg_depth(self: turbo_tasks::Vc, depth: usize) -> anyhow::Result> { + use turbo_tasks::debug::ValueDebugFormat; + let string = self.value_debug_format(depth).try_to_value_debug_string().await?.await?; + Ok(turbo_tasks::debug::ValueDebugString::new(format!(concat!(stringify!(#trait_ident), "({})"), string))) + } + } + } + } else { + quote! {} + }; + + let expanded = quote! { + #[must_use] + #(#attrs)* + #vis #trait_token #trait_ident: std::marker::Send + #(#supertraits)+* + { + #(#items)* + } + + #(#native_functions)* + + #[doc(hidden)] + pub(crate) static #trait_type_ident: turbo_tasks::macro_helpers::Lazy = + turbo_tasks::macro_helpers::Lazy::new(|| { + let mut trait_type = turbo_tasks::TraitType::new(stringify!(#trait_ident).to_string());; + #(#default_method_registers)* + trait_type + }); + #[doc(hidden)] + static #trait_type_id_ident: turbo_tasks::macro_helpers::Lazy = + turbo_tasks::macro_helpers::Lazy::new(|| { + turbo_tasks::registry::get_trait_type_id(&#trait_type_ident) + }); + + impl turbo_tasks::VcValueTrait for Box { + fn get_trait_type_id() -> turbo_tasks::TraitTypeId { + *#trait_type_id_ident + } + } + + unsafe impl turbo_tasks::Dynamic> for Box {} + // TODO(alexkirsz) It would be great to have the following identity. However, I run into an ICE when I attempt this, + // so tabling it for now. + unsafe impl turbo_tasks::Upcast> for Box {} + + impl #trait_ident for T + where + T: turbo_tasks::Dynamic> #(+ #supertraits)*, + { + #(#dynamic_trait_fns)* + } + + #( + unsafe impl turbo_tasks::Dynamic> for Box {} + unsafe impl turbo_tasks::Upcast> for Box {} + )* + + #value_debug_impl + }; + expanded.into() +} diff --git a/crates/turbo-tasks-malloc/Source/counter.rs b/crates/turbo-tasks-malloc/Source/counter.rs new file mode 100644 index 0000000000000..34cfc91c038be --- /dev/null +++ b/crates/turbo-tasks-malloc/Source/counter.rs @@ -0,0 +1,158 @@ +use std::{ + cell::UnsafeCell, + ptr::NonNull, + sync::atomic::{AtomicUsize, Ordering}, +}; + +use crate::AllocationCounters; + +static ALLOCATED:AtomicUsize = AtomicUsize::new(0); +const KB:usize = 1024; +/// When global counter is updates we will keep a thread-local buffer of this +/// size. +const TARGET_BUFFER:usize = 100 * KB; +/// When the thread-local buffer would exceed this size, we will update the +/// global counter. +const MAX_BUFFER:usize = 200 * KB; + +#[derive(Default)] +struct ThreadLocalCounter { + /// Thread-local buffer of allocated bytes that have been added to the + /// global counter desprite not being allocated yet. It is unsigned so that + /// means the global counter is always equal or greater than the real + /// value. + buffer:usize, + allocation_counters:AllocationCounters, +} + +impl ThreadLocalCounter { + fn add(&mut self, size:usize) { + self.allocation_counters.allocations += size; + self.allocation_counters.allocation_count += 1; + if self.buffer >= size { + self.buffer -= size; + } else { + let offset = size - self.buffer + TARGET_BUFFER; + self.buffer = TARGET_BUFFER; + ALLOCATED.fetch_add(offset, Ordering::Relaxed); + } + } + + fn remove(&mut self, size:usize) { + self.allocation_counters.deallocations += size; + self.allocation_counters.deallocation_count += 1; + self.buffer += size; + if self.buffer > MAX_BUFFER { + let offset = self.buffer - TARGET_BUFFER; + self.buffer = TARGET_BUFFER; + ALLOCATED.fetch_sub(offset, Ordering::Relaxed); + } + } + + fn update(&mut self, old_size:usize, new_size:usize) { + self.allocation_counters.deallocations += old_size; + self.allocation_counters.deallocation_count += 1; + self.allocation_counters.allocations += new_size; + self.allocation_counters.allocation_count += 1; + match old_size.cmp(&new_size) { + std::cmp::Ordering::Equal => {}, + std::cmp::Ordering::Less => { + let size = new_size - old_size; + if self.buffer >= size { + self.buffer -= size; + } else { + let offset = size - self.buffer + TARGET_BUFFER; + self.buffer = TARGET_BUFFER; + ALLOCATED.fetch_add(offset, Ordering::Relaxed); + } + }, + std::cmp::Ordering::Greater => { + let size = old_size - new_size; + self.buffer += size; + if self.buffer > MAX_BUFFER { + let offset = self.buffer - TARGET_BUFFER; + self.buffer = TARGET_BUFFER; + ALLOCATED.fetch_sub(offset, Ordering::Relaxed); + } + }, + } + } + + fn unload(&mut self) { + if self.buffer > 0 { + ALLOCATED.fetch_sub(self.buffer, Ordering::Relaxed); + self.buffer = 0; + } + self.allocation_counters = AllocationCounters::default(); + } +} + +thread_local! { + static LOCAL_COUNTER: UnsafeCell = UnsafeCell::new(ThreadLocalCounter::default()); +} + +pub fn get() -> usize { ALLOCATED.load(Ordering::Relaxed) } + +pub fn allocation_counters() -> AllocationCounters { + with_local_counter(|local| local.allocation_counters.clone()) +} + +pub fn reset_allocation_counters(start:AllocationCounters) { + with_local_counter(|local| local.allocation_counters = start); +} + +fn with_local_counter(f:impl FnOnce(&mut ThreadLocalCounter) -> T) -> T { + LOCAL_COUNTER.with(|local| { + let ptr = local.get(); + // SAFETY: This is a thread local. + let mut local = unsafe { NonNull::new_unchecked(ptr) }; + f(unsafe { local.as_mut() }) + }) +} + +/// Adds some `size` to the global counter in a thread-local buffered way. +pub fn add(size:usize) { with_local_counter(|local| local.add(size)); } + +/// Removes some `size` to the global counter in a thread-local buffered way. +pub fn remove(size:usize) { with_local_counter(|local| local.remove(size)); } + +/// Adds some `size` to the global counter in a thread-local buffered way. +pub fn update(old_size:usize, new_size:usize) { + with_local_counter(|local| local.update(old_size, new_size)); +} + +/// Flushes the thread-local buffer to the global counter. This should be called +/// e. g. when a thread is stopped or goes to sleep for a long time. +pub fn flush() { with_local_counter(|local| local.unload()); } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn counting() { + let mut expected = get(); + add(100); + // Initial change should fill up the buffer + expected += TARGET_BUFFER + 100; + assert_eq!(get(), expected); + add(100); + // Further changes should use the buffer + assert_eq!(get(), expected); + add(MAX_BUFFER); + // Large changes should require more buffer space + expected += 100 + MAX_BUFFER; + assert_eq!(get(), expected); + remove(100); + // Small changes should use the buffer + // buffer size is now TARGET_BUFFER + 100 + assert_eq!(get(), expected); + remove(MAX_BUFFER); + // The buffer should not grow over MAX_BUFFER + // buffer size would be TARGET_BUFFER + 100 + MAX_BUFFER + // but it will be reduce to TARGET_BUFFER + // this means the global counter should reduce by 100 + MAX_BUFFER + expected -= MAX_BUFFER + 100; + assert_eq!(get(), expected); + } +} diff --git a/crates/turbo-tasks-malloc/Source/lib.rs b/crates/turbo-tasks-malloc/Source/lib.rs new file mode 100644 index 0000000000000..d86c5762b56d6 --- /dev/null +++ b/crates/turbo-tasks-malloc/Source/lib.rs @@ -0,0 +1,109 @@ +mod counter; + +use std::{ + alloc::{GlobalAlloc, Layout}, + marker::PhantomData, +}; + +use self::counter::{add, flush, get, remove, update}; + +#[derive(Default, Clone, Debug)] +pub struct AllocationInfo { + pub allocations:usize, + pub deallocations:usize, + pub allocation_count:usize, + pub deallocation_count:usize, +} + +impl AllocationInfo { + pub fn is_empty(&self) -> bool { + self.allocations == 0 + && self.deallocations == 0 + && self.allocation_count == 0 + && self.deallocation_count == 0 + } +} + +#[derive(Default, Clone, Debug)] +pub struct AllocationCounters { + pub allocations:usize, + pub deallocations:usize, + pub allocation_count:usize, + pub deallocation_count:usize, + _not_send:PhantomData<*mut ()>, +} + +impl AllocationCounters { + pub fn until_now(&self) -> AllocationInfo { + let new = TurboMalloc::allocation_counters(); + AllocationInfo { + allocations:new.allocations - self.allocations, + deallocations:new.deallocations - self.deallocations, + allocation_count:new.allocation_count - self.allocation_count, + deallocation_count:new.deallocation_count - self.deallocation_count, + } + } +} + +/// Turbo's preferred global allocator. This is a new type instead of a type +/// alias because you can't use type aliases to instantiate unit types (E0423). +pub struct TurboMalloc; + +impl TurboMalloc { + pub fn memory_usage() -> usize { get() } + + pub fn thread_stop() { flush(); } + + pub fn allocation_counters() -> AllocationCounters { self::counter::allocation_counters() } + + pub fn reset_allocation_counters(start:AllocationCounters) { + self::counter::reset_allocation_counters(start); + } +} + +/// Get the allocator for this platform that we should wrap with TurboMalloc. +#[inline] +fn base_alloc() -> &'static impl GlobalAlloc { + #[cfg(all( + feature = "custom_allocator", + not(any(target_family = "wasm", target_env = "musl")) + ))] + return &mimalloc::MiMalloc; + #[cfg(any( + not(feature = "custom_allocator"), + any(target_family = "wasm", target_env = "musl") + ))] + return &std::alloc::System; +} + +unsafe impl GlobalAlloc for TurboMalloc { + unsafe fn alloc(&self, layout:Layout) -> *mut u8 { + let ret = base_alloc().alloc(layout); + if !ret.is_null() { + add(layout.size()); + } + ret + } + + unsafe fn dealloc(&self, ptr:*mut u8, layout:Layout) { + base_alloc().dealloc(ptr, layout); + remove(layout.size()); + } + + unsafe fn alloc_zeroed(&self, layout:Layout) -> *mut u8 { + let ret = base_alloc().alloc_zeroed(layout); + if !ret.is_null() { + add(layout.size()); + } + ret + } + + unsafe fn realloc(&self, ptr:*mut u8, layout:Layout, new_size:usize) -> *mut u8 { + let ret = base_alloc().realloc(ptr, layout, new_size); + if !ret.is_null() { + let old_size = layout.size(); + update(old_size, new_size); + } + ret + } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/aggregation_data.rs b/crates/turbo-tasks-memory/Source/aggregation/aggregation_data.rs new file mode 100644 index 0000000000000..da0a2b4806f9b --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/aggregation_data.rs @@ -0,0 +1,83 @@ +use std::ops::{Deref, DerefMut}; + +use super::{ + AggregationContext, + AggregationNode, + AggregationNodeGuard, + increase_aggregation_number_internal, +}; +use crate::aggregation::{balance_queue::BalanceQueue, increase::IncreaseReason}; + +/// Gives an reference to the aggregated data for a given item. This will +/// convert the item to a fully aggregated node. +pub fn aggregation_data<'l, C>( + ctx:&'l C, + node_id:&C::NodeRef, +) -> AggregationDataGuard> +where + C: AggregationContext + 'l, { + let guard = ctx.node(node_id); + if guard.aggregation_number() == u32::MAX { + AggregationDataGuard { guard } + } else { + let mut balance_queue = BalanceQueue::new(); + increase_aggregation_number_internal( + ctx, + &mut balance_queue, + guard, + node_id, + u32::MAX, + u32::MAX, + IncreaseReason::AggregationData, + ); + balance_queue.process(ctx); + let guard = ctx.node(node_id); + debug_assert!(guard.aggregation_number() == u32::MAX); + AggregationDataGuard { guard } + } +} + +/// Converted the given node to a fully aggregated node. To make the next call +/// to `aggregation_data` instant. +pub fn prepare_aggregation_data(ctx:&C, node_id:&C::NodeRef) { + let mut balance_queue = BalanceQueue::new(); + increase_aggregation_number_internal( + ctx, + &mut balance_queue, + ctx.node(node_id), + node_id, + u32::MAX, + u32::MAX, + IncreaseReason::AggregationData, + ); + balance_queue.process(ctx); +} + +/// A reference to the aggregated data of a node. This holds a lock to the node. +pub struct AggregationDataGuard { + guard:G, +} + +impl AggregationDataGuard { + pub fn into_inner(self) -> G { self.guard } +} + +impl Deref for AggregationDataGuard { + type Target = G::Data; + + fn deref(&self) -> &Self::Target { + match &*self.guard { + AggregationNode::Leaf { .. } => unreachable!(), + AggregationNode::Aggegating(aggregating) => &aggregating.data, + } + } +} + +impl DerefMut for AggregationDataGuard { + fn deref_mut(&mut self) -> &mut Self::Target { + match &mut *self.guard { + AggregationNode::Leaf { .. } => unreachable!(), + AggregationNode::Aggegating(aggregating) => &mut aggregating.data, + } + } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/balance_edge.rs b/crates/turbo-tasks-memory/Source/aggregation/balance_edge.rs new file mode 100644 index 0000000000000..68e04e1579c89 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/balance_edge.rs @@ -0,0 +1,209 @@ +use std::cmp::Ordering; + +use super::{ + AggregationContext, + AggregationNode, + balance_queue::BalanceQueue, + followers::{ + RemovePositveFollowerCountResult, + add_follower_count, + remove_follower_count, + remove_positive_follower_count, + }, + in_progress::is_in_progress, + increase::IncreaseReason, + increase_aggregation_number_internal, + uppers::{ + RemovePositiveUpperCountResult, + add_upper_count, + remove_positive_upper_count, + remove_upper_count, + }, +}; + +// Migrated followers to uppers or uppers to followers depending on the +// aggregation numbers of the nodes involved in the edge. Might increase targets +// aggregation number if they are equal. +pub(super) fn balance_edge( + ctx:&C, + balance_queue:&mut BalanceQueue, + upper_id:&C::NodeRef, + mut upper_aggregation_number:u32, + target_id:&C::NodeRef, + mut target_aggregation_number:u32, +) -> (u32, u32) { + // too many uppers on target + let mut extra_uppers = 0; + // too many followers on upper + let mut extra_followers = 0; + // The last info about uppers + let mut uppers_count:Option = None; + // The last info about followers + let mut followers_count = None; + + loop { + let root = upper_aggregation_number == u32::MAX || target_aggregation_number == u32::MAX; + let order = if root { + Ordering::Greater + } else { + upper_aggregation_number.cmp(&target_aggregation_number) + }; + match order { + Ordering::Equal => { + // we probably want to increase the aggregation number of target + let upper = ctx.node(upper_id); + upper_aggregation_number = upper.aggregation_number(); + drop(upper); + if upper_aggregation_number != u32::MAX + && upper_aggregation_number == target_aggregation_number + { + let target = ctx.node(target_id); + target_aggregation_number = target.aggregation_number(); + if upper_aggregation_number == target_aggregation_number { + // increase target aggregation number + increase_aggregation_number_internal( + ctx, + balance_queue, + target, + target_id, + target_aggregation_number + 1, + target_aggregation_number + 1, + IncreaseReason::EqualAggregationNumberOnBalance, + ); + } + } + }, + Ordering::Less => { + // target should probably be a follower of upper + if uppers_count.map_or(false, |count| count <= 0) { + // We already removed all uppers, maybe too many + break; + } else if extra_followers == 0 { + let upper = ctx.node(upper_id); + upper_aggregation_number = upper.aggregation_number(); + if upper_aggregation_number < target_aggregation_number { + // target should be a follower of upper + // add some extra followers + let count = uppers_count.unwrap_or(1) as usize; + extra_followers += count; + followers_count = Some(add_follower_count( + ctx, + balance_queue, + upper, + upper_id, + target_id, + count, + true, + )); + } + } else { + // we already have extra followers, remove some uppers to balance + let count = extra_followers + extra_uppers; + let target = ctx.node(target_id); + if is_in_progress(ctx, upper_id) { + drop(target); + let mut upper = ctx.node(upper_id); + if is_in_progress(ctx, upper_id) { + let AggregationNode::Aggegating(aggregating) = &mut *upper else { + unreachable!(); + }; + aggregating.enqueued_balancing.push(( + upper_id.clone(), + upper_aggregation_number, + target_id.clone(), + target_aggregation_number, + )); + drop(upper); + // Somebody else will balance this edge + return (upper_aggregation_number, target_aggregation_number); + } + } else { + let RemovePositiveUpperCountResult { removed_count, remaining_count } = + remove_positive_upper_count( + ctx, + balance_queue, + target, + upper_id, + count, + ); + decrease_numbers(removed_count, &mut extra_uppers, &mut extra_followers); + uppers_count = Some(remaining_count); + } + } + }, + Ordering::Greater => { + // target should probably be an inner node of upper + if followers_count.map_or(false, |count| count <= 0) { + // We already removed all followers, maybe too many + break; + } else if extra_uppers == 0 { + let target = ctx.node(target_id); + target_aggregation_number = target.aggregation_number(); + if root || target_aggregation_number < upper_aggregation_number { + // target should be a inner node of upper + if is_in_progress(ctx, upper_id) { + drop(target); + let mut upper = ctx.node(upper_id); + if is_in_progress(ctx, upper_id) { + let AggregationNode::Aggegating(aggregating) = &mut *upper else { + unreachable!(); + }; + aggregating.enqueued_balancing.push(( + upper_id.clone(), + upper_aggregation_number, + target_id.clone(), + target_aggregation_number, + )); + drop(upper); + // Somebody else will balance this edge + return (upper_aggregation_number, target_aggregation_number); + } + } else { + // add some extra uppers + let count = followers_count.unwrap_or(1) as usize; + extra_uppers += count; + uppers_count = Some( + add_upper_count( + ctx, + balance_queue, + target, + target_id, + upper_id, + count, + true, + ) + .new_count, + ); + } + } + } else { + // we already have extra uppers, try to remove some followers to balance + let count = extra_followers + extra_uppers; + let upper = ctx.node(upper_id); + let RemovePositveFollowerCountResult { removed_count, remaining_count } = + remove_positive_follower_count(ctx, balance_queue, upper, target_id, count); + decrease_numbers(removed_count, &mut extra_followers, &mut extra_uppers); + followers_count = Some(remaining_count); + } + }, + } + } + if extra_followers > 0 { + let upper = ctx.node(upper_id); + remove_follower_count(ctx, balance_queue, upper, target_id, extra_followers); + } + if extra_uppers > 0 { + let target = ctx.node(target_id); + remove_upper_count(ctx, balance_queue, target, upper_id, extra_uppers); + } + (upper_aggregation_number, target_aggregation_number) +} + +fn decrease_numbers(amount:usize, a:&mut usize, b:&mut usize) { + if *a >= amount { + *a -= amount; + } else { + *b -= amount - *a; + *a = 0; + } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/balance_queue.rs b/crates/turbo-tasks-memory/Source/aggregation/balance_queue.rs new file mode 100644 index 0000000000000..71864395cb93a --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/balance_queue.rs @@ -0,0 +1,76 @@ +use std::{cmp::max, collections::HashMap, hash::Hash, mem::take}; + +use indexmap::IndexSet; + +use super::{AggregationContext, balance_edge}; + +/// Enqueued edges that need to be balanced. Deduplicates edges and keeps track +/// of aggregation numbers read during balancing. +pub struct BalanceQueue { + queue:IndexSet<(I, I)>, + aggregation_numbers:HashMap, +} + +impl BalanceQueue { + pub fn new() -> Self { + Self { queue:IndexSet::default(), aggregation_numbers:HashMap::default() } + } + + fn add_number(&mut self, id:I, number:u32) { + self.aggregation_numbers + .entry(id) + .and_modify(|n| *n = max(*n, number)) + .or_insert(number); + } + + /// Add an edge to the queue. The edge will be balanced during the next + /// call. + pub fn balance( + &mut self, + upper_id:I, + upper_aggregation_number:u32, + target_id:I, + target_aggregation_number:u32, + ) { + debug_assert!(upper_id != target_id); + self.add_number(upper_id.clone(), upper_aggregation_number); + self.add_number(target_id.clone(), target_aggregation_number); + self.queue.insert((upper_id.clone(), target_id.clone())); + } + + /// Add multiple edges to the queue. The edges will be balanced during the + /// next call. + pub fn balance_all(&mut self, edges:Vec<(I, u32, I, u32)>) { + for (upper_id, upper_aggregation_number, target_id, target_aggregation_number) in edges { + self.balance(upper_id, upper_aggregation_number, target_id, target_aggregation_number); + } + } + + /// Process the queue and balance all enqueued edges. + pub fn process>(mut self, ctx:&C) { + while !self.queue.is_empty() { + let queue = take(&mut self.queue); + for (upper_id, target_id) in queue { + let upper_aggregation_number = + self.aggregation_numbers.get(&upper_id).copied().unwrap_or_default(); + let target_aggregation_number = + self.aggregation_numbers.get(&target_id).copied().unwrap_or_default(); + + let (u, t) = balance_edge( + ctx, + &mut self, + &upper_id, + upper_aggregation_number, + &target_id, + target_aggregation_number, + ); + if u != upper_aggregation_number { + self.add_number(upper_id, u); + } + if t != target_aggregation_number { + self.add_number(target_id, t); + } + } + } + } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/change.rs b/crates/turbo-tasks-memory/Source/aggregation/change.rs new file mode 100644 index 0000000000000..a5c0721a5c21f --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/change.rs @@ -0,0 +1,114 @@ +use std::hash::Hash; + +use super::{AggegatingNode, AggregationContext, AggregationNode, PreparedOperation, StackVec}; + +impl AggregationNode { + /// Prepares to apply a change to a node. Changes will be propagated to all + /// upper nodes. + #[must_use] + pub fn apply_change>( + &mut self, + ctx:&C, + change:C::DataChange, + ) -> Option> { + match self { + AggregationNode::Leaf { uppers, .. } => { + (!uppers.is_empty()).then(|| { + PreparedChange { + uppers:uppers.iter().cloned().collect::>(), + change, + } + }) + }, + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { data, uppers, .. } = &mut **aggegating; + let change = ctx.apply_change(data, &change); + if uppers.is_empty() { + None + } else { + change.map(|change| { + PreparedChange { + uppers:uppers.iter().cloned().collect::>(), + change, + } + }) + } + }, + } + } + + /// Prepares to apply a change to a node. Changes will be propagated to all + /// upper nodes. + #[must_use] + pub fn apply_change_ref<'l, C:AggregationContext>( + &mut self, + ctx:&C, + change:&'l C::DataChange, + ) -> Option> { + match self { + AggregationNode::Leaf { uppers, .. } => { + (!uppers.is_empty()).then(|| { + PreparedChangeRef::Borrowed { + uppers:uppers.iter().cloned().collect::>(), + change, + } + }) + }, + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { data, uppers, .. } = &mut **aggegating; + let change = ctx.apply_change(data, change); + if uppers.is_empty() { + None + } else { + change.map(|change| { + PreparedChangeRef::Owned { + uppers:uppers.iter().cloned().collect::>(), + change, + } + }) + } + }, + } + } +} + +/// A prepared `apply_change` operation. +pub struct PreparedChange { + uppers:StackVec, + change:C::DataChange, +} + +impl PreparedOperation for PreparedChange { + type Result = (); + + fn apply(self, ctx:&C) { + let prepared = self + .uppers + .into_iter() + .filter_map(|upper_id| ctx.node(&upper_id).apply_change_ref(ctx, &self.change)) + .collect::>(); + prepared.apply(ctx); + } +} + +/// A prepared `apply_change_ref` operation. +pub enum PreparedChangeRef<'l, C:AggregationContext> { + Borrowed { uppers:StackVec, change:&'l C::DataChange }, + Owned { uppers:StackVec, change:C::DataChange }, +} + +impl<'l, C:AggregationContext> PreparedOperation for PreparedChangeRef<'l, C> { + type Result = (); + + fn apply(self, ctx:&C) { + let (uppers, change) = match self { + PreparedChangeRef::Borrowed { uppers, change } => (uppers, change), + PreparedChangeRef::Owned { uppers, ref change } => (uppers, change), + }; + let prepared = uppers + .into_iter() + .filter_map(|upper_id| ctx.node(&upper_id).apply_change_ref(ctx, change)) + .collect::>(); + prepared.apply(ctx); + } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/followers.rs b/crates/turbo-tasks-memory/Source/aggregation/followers.rs new file mode 100644 index 0000000000000..7e3833f9c8545 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/followers.rs @@ -0,0 +1,159 @@ +use super::{ + AggregationContext, + AggregationNode, + StackVec, + balance_queue::BalanceQueue, + in_progress::start_in_progress_all, + notify_lost_follower, + notify_new_follower, + optimize::{MAX_FOLLOWERS, optimize_aggregation_number_for_followers}, +}; +use crate::count_hash_set::RemovePositiveCountResult; + +/// Add a follower to a node. Followers will be propagated to the uppers of the +/// node. +pub fn add_follower( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + node_id:&C::NodeRef, + follower_id:&C::NodeRef, + already_optimizing_for_node:bool, +) -> usize { + let AggregationNode::Aggegating(aggregating) = &mut *node else { + unreachable!(); + }; + if aggregating.followers.add_clonable(follower_id) { + on_added(ctx, balance_queue, node, node_id, follower_id, already_optimizing_for_node) + } else { + 0 + } +} + +/// Handle the addition of a follower to a node. This function is called after +/// the follower has been added to the node. +pub fn on_added( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + node_id:&C::NodeRef, + follower_id:&C::NodeRef, + already_optimizing_for_node:bool, +) -> usize { + let AggregationNode::Aggegating(aggregating) = &mut *node else { + unreachable!(); + }; + let followers_len = aggregating.followers.len(); + let optimize = (!already_optimizing_for_node + && followers_len > MAX_FOLLOWERS + && (followers_len - MAX_FOLLOWERS).count_ones() == 1) + .then(|| aggregating.followers.iter().cloned().collect::>()); + let uppers = aggregating.uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + drop(node); + + let mut optimizing = false; + + if let Some(followers) = optimize { + optimizing = optimize_aggregation_number_for_followers( + ctx, + balance_queue, + node_id, + followers, + false, + ); + } + + let mut affected_nodes = uppers.len(); + for upper_id in uppers { + affected_nodes += notify_new_follower( + ctx, + balance_queue, + ctx.node(&upper_id), + &upper_id, + follower_id, + optimizing, + ); + } + affected_nodes +} + +/// Add a follower to a node with a count. Followers will be propagated to the +/// uppers of the node. +pub fn add_follower_count( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + node_id:&C::NodeRef, + follower_id:&C::NodeRef, + follower_count:usize, + already_optimizing_for_node:bool, +) -> isize { + let AggregationNode::Aggegating(aggregating) = &mut *node else { + unreachable!(); + }; + if aggregating.followers.add_clonable_count(follower_id, follower_count) { + let count = aggregating.followers.get_count(follower_id); + on_added(ctx, balance_queue, node, node_id, follower_id, already_optimizing_for_node); + count + } else { + aggregating.followers.get_count(follower_id) + } +} + +/// Remove a follower from a node. Followers will be propagated to the uppers of +/// the node. +pub fn remove_follower_count( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + follower_id:&C::NodeRef, + follower_count:usize, +) { + let AggregationNode::Aggegating(aggregating) = &mut *node else { + unreachable!(); + }; + if aggregating.followers.remove_clonable_count(follower_id, follower_count) { + let uppers = aggregating.uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + drop(node); + for upper_id in uppers { + notify_lost_follower(ctx, balance_queue, ctx.node(&upper_id), &upper_id, follower_id); + } + } +} + +pub struct RemovePositveFollowerCountResult { + /// The amount of followers that have been removed. + pub removed_count:usize, + /// The amount of followers that are remaining. Might be negative. + pub remaining_count:isize, +} + +/// Remove a positive count of a follower from a node. Negative counts will not +/// be increased. The function returns how much of the count has been removed +/// and whats remaining. Followers will be propagated to the uppers of the node. +pub fn remove_positive_follower_count( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + follower_id:&C::NodeRef, + follower_count:usize, +) -> RemovePositveFollowerCountResult { + let AggregationNode::Aggegating(aggregating) = &mut *node else { + unreachable!(); + }; + let RemovePositiveCountResult { removed, removed_count, count } = aggregating + .followers + .remove_positive_clonable_count(follower_id, follower_count); + + if removed { + let uppers = aggregating.uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + drop(node); + for upper_id in uppers { + notify_lost_follower(ctx, balance_queue, ctx.node(&upper_id), &upper_id, follower_id); + } + } + RemovePositveFollowerCountResult { removed_count, remaining_count:count } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/in_progress.rs b/crates/turbo-tasks-memory/Source/aggregation/in_progress.rs new file mode 100644 index 0000000000000..b3ee29330c789 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/in_progress.rs @@ -0,0 +1,75 @@ +use std::{hash::Hash, mem::take}; + +use super::{AggregationContext, AggregationNode, StackVec, balance_queue::BalanceQueue}; + +impl AggregationNode { + /// Finishes an in progress operation. This might enqueue balancing + /// operations when they weren't possible due to the in progress operation. + pub(super) fn finish_in_progress>( + &mut self, + ctx:&C, + balance_queue:&mut BalanceQueue, + node_id:&I, + ) { + let value = ctx + .atomic_in_progress_counter(node_id) + .fetch_sub(1, std::sync::atomic::Ordering::AcqRel); + debug_assert!(value > 0); + if value == 1 { + if let AggregationNode::Aggegating(aggegating) = &mut *self { + balance_queue.balance_all(take(&mut aggegating.enqueued_balancing)) + } + } + } +} + +/// Finishes an in progress operation. This might enqueue balancing +/// operations when they weren't possible due to the in progress operation. +/// This version doesn't require a node guard. +pub fn finish_in_progress_without_node( + ctx:&C, + balance_queue:&mut BalanceQueue, + node_id:&C::NodeRef, +) { + let value = ctx + .atomic_in_progress_counter(node_id) + .fetch_sub(1, std::sync::atomic::Ordering::AcqRel); + debug_assert!(value > 0); + if value == 1 { + let mut node = ctx.node(node_id); + if let AggregationNode::Aggegating(aggegating) = &mut *node { + balance_queue.balance_all(take(&mut aggegating.enqueued_balancing)) + } + } +} + +/// Starts an in progress operation for all nodes in the list. +pub fn start_in_progress_all(ctx:&C, node_ids:&StackVec) { + for node_id in node_ids { + start_in_progress(ctx, node_id); + } +} + +/// Starts an in progress operation for a node. +pub fn start_in_progress(ctx:&C, node_id:&C::NodeRef) { + start_in_progress_count(ctx, node_id, 1); +} + +/// Starts multiple in progress operations for a node. +pub fn start_in_progress_count(ctx:&C, node_id:&C::NodeRef, count:u32) { + if count == 0 { + return; + } + ctx.atomic_in_progress_counter(node_id) + .fetch_add(count, std::sync::atomic::Ordering::Release); +} + +/// Checks if there is an in progress operation for a node. +/// It doesn't require a lock, but should run under a lock of the node or a +/// follower/inner node. +pub fn is_in_progress(ctx:&C, node_id:&C::NodeRef) -> bool { + let counter = ctx + .atomic_in_progress_counter(node_id) + .load(std::sync::atomic::Ordering::Acquire); + counter > 0 +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/increase.rs b/crates/turbo-tasks-memory/Source/aggregation/increase.rs new file mode 100644 index 0000000000000..7766125be8292 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/increase.rs @@ -0,0 +1,335 @@ +use std::{hash::Hash, mem::take}; + +use super::{ + AggegatingNode, + AggregationContext, + AggregationNode, + AggregationNodeGuard, + PreparedInternalOperation, + PreparedOperation, + StackVec, + balance_queue::BalanceQueue, +}; +pub(super) const LEAF_NUMBER:u32 = 64; + +#[derive(Debug)] +pub enum IncreaseReason { + Upgraded, + AggregationData, + EqualAggregationNumberOnBalance, + EqualAggregationNumberOnNewFollower, + OptimizeForUppers, + OptimizeForFollowers, + LeafEdge, + LeafEdgeAfterIncrease, + #[cfg(test)] + Test, +} + +impl AggregationNode { + /// Increase the aggregation number of a node. This might temporarily + /// violate the graph invariants between uppers and followers of that node. + /// Therefore a balancing operation is enqueued to restore the invariants. + /// The actual change to the aggregation number is applied in the prepared + /// operation after checking all upper nodes aggregation numbers. + #[must_use] + pub(super) fn increase_aggregation_number_internal< + C:AggregationContext, + >( + &mut self, + _ctx:&C, + node_id:&C::NodeRef, + min_aggregation_number:u32, + target_aggregation_number:u32, + reason:IncreaseReason, + ) -> Option> { + if self.aggregation_number() >= min_aggregation_number { + return None; + } + Some(PreparedInternalIncreaseAggregationNumber::Lazy { + node_id:node_id.clone(), + uppers:self.uppers_mut().iter().cloned().collect(), + min_aggregation_number, + target_aggregation_number, + reason, + }) + } + + /// Increase the aggregation number of a node. This is only for testing + /// proposes. + #[cfg(test)] + pub fn increase_aggregation_number>( + &mut self, + _ctx:&C, + node_id:&C::NodeRef, + new_aggregation_number:u32, + ) -> Option> { + self.increase_aggregation_number_internal( + _ctx, + node_id, + new_aggregation_number, + new_aggregation_number, + IncreaseReason::Test, + ) + .map(PreparedIncreaseAggregationNumber) + } +} + +/// Increase the aggregation number of a node directly. This might temporarily +/// violate the graph invariants between uppers and followers of that node. +/// Therefore a balancing operation is enqueued to restore the invariants. +/// The actual change to the aggregation number is applied directly without +/// checking the upper nodes. +#[must_use] +pub(super) fn increase_aggregation_number_immediately( + _ctx:&C, + node:&mut C::Guard<'_>, + node_id:C::NodeRef, + min_aggregation_number:u32, + target_aggregation_number:u32, + reason:IncreaseReason, +) -> Option> { + if node.aggregation_number() >= min_aggregation_number { + return None; + } + + let _span = + tracing::trace_span!("increase_aggregation_number_immediately", reason = debug(&reason)) + .entered(); + let children = matches!(**node, AggregationNode::Leaf { .. }) + .then(|| node.children().collect::>()); + match &mut **node { + AggregationNode::Leaf { aggregation_number, uppers } => { + let children = children.unwrap(); + if target_aggregation_number < LEAF_NUMBER { + *aggregation_number = target_aggregation_number as u8; + Some(PreparedInternalIncreaseAggregationNumber::Leaf { + target_aggregation_number, + children, + }) + } else { + let uppers_copy = uppers.iter().cloned().collect::>(); + // Convert to Aggregating + **node = AggregationNode::Aggegating(Box::new(AggegatingNode { + aggregation_number:target_aggregation_number, + uppers:take(uppers), + followers:children.iter().cloned().collect(), + data:node.get_initial_data(), + enqueued_balancing:Vec::new(), + })); + let followers = children; + Some(PreparedInternalIncreaseAggregationNumber::Aggregating { + node_id, + uppers:uppers_copy, + followers, + target_aggregation_number, + }) + } + }, + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { followers, uppers, aggregation_number, .. } = &mut **aggegating; + let uppers = uppers.iter().cloned().collect::>(); + let followers = followers.iter().cloned().collect(); + *aggregation_number = target_aggregation_number; + Some(PreparedInternalIncreaseAggregationNumber::Aggregating { + node_id, + uppers, + followers, + target_aggregation_number, + }) + }, + } +} + +/// A prepared `increase_aggregation_number` operation. +pub enum PreparedInternalIncreaseAggregationNumber { + Lazy { + node_id:C::NodeRef, + uppers:StackVec, + min_aggregation_number:u32, + target_aggregation_number:u32, + reason:IncreaseReason, + }, + Leaf { + children:StackVec, + target_aggregation_number:u32, + }, + Aggregating { + node_id:C::NodeRef, + uppers:StackVec, + followers:StackVec, + target_aggregation_number:u32, + }, +} + +impl PreparedInternalOperation + for PreparedInternalIncreaseAggregationNumber +{ + type Result = (); + + fn apply(self, ctx:&C, balance_queue:&mut BalanceQueue) { + match self { + PreparedInternalIncreaseAggregationNumber::Lazy { + min_aggregation_number, + mut target_aggregation_number, + node_id, + uppers, + reason, + } => { + let mut need_to_run = true; + while need_to_run { + need_to_run = false; + let mut max = 0; + for upper_id in &uppers { + let upper = ctx.node(upper_id); + let aggregation_number = upper.aggregation_number(); + if aggregation_number != u32::MAX { + if aggregation_number > max { + max = aggregation_number; + } + if aggregation_number == target_aggregation_number { + target_aggregation_number += 1; + if max >= target_aggregation_number { + need_to_run = true; + } + } + } + } + } + drop(uppers); + let mut node = ctx.node(&node_id); + if node.aggregation_number() >= min_aggregation_number { + return; + } + let _span = + tracing::trace_span!("increase_aggregation_number", reason = debug(&reason)) + .entered(); + let children = matches!(*node, AggregationNode::Leaf { .. }) + .then(|| node.children().collect::>()); + let (uppers, followers) = match &mut *node { + AggregationNode::Leaf { aggregation_number, uppers } => { + let children = children.unwrap(); + if target_aggregation_number < LEAF_NUMBER { + *aggregation_number = target_aggregation_number as u8; + drop(node); + for child_id in children { + increase_aggregation_number_internal( + ctx, + balance_queue, + ctx.node(&child_id), + &child_id, + target_aggregation_number + 1, + target_aggregation_number + 1, + IncreaseReason::LeafEdgeAfterIncrease, + ); + } + return; + } else { + let uppers_copy = uppers.iter().cloned().collect::>(); + // Convert to Aggregating + *node = AggregationNode::Aggegating(Box::new(AggegatingNode { + aggregation_number:target_aggregation_number, + uppers:take(uppers), + followers:children.iter().cloned().collect(), + data:node.get_initial_data(), + enqueued_balancing:Vec::new(), + })); + let followers = children; + drop(node); + (uppers_copy, followers) + } + }, + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { followers, uppers, aggregation_number, .. } = + &mut **aggegating; + let uppers = uppers.iter().cloned().collect::>(); + let followers = followers.iter().cloned().collect(); + *aggregation_number = target_aggregation_number; + drop(node); + (uppers, followers) + }, + }; + for follower_id in followers { + balance_queue.balance( + node_id.clone(), + target_aggregation_number, + follower_id, + 0, + ); + } + for upper_id in uppers { + balance_queue.balance(upper_id, 0, node_id.clone(), target_aggregation_number); + } + }, + PreparedInternalIncreaseAggregationNumber::Leaf { + children, + target_aggregation_number, + } => { + for child_id in children { + increase_aggregation_number_internal( + ctx, + balance_queue, + ctx.node(&child_id), + &child_id, + target_aggregation_number + 1, + target_aggregation_number + 1, + IncreaseReason::LeafEdgeAfterIncrease, + ); + } + }, + PreparedInternalIncreaseAggregationNumber::Aggregating { + node_id, + uppers, + followers, + target_aggregation_number, + } => { + for follower_id in followers { + balance_queue.balance( + node_id.clone(), + target_aggregation_number, + follower_id, + 0, + ); + } + for upper_id in uppers { + balance_queue.balance(upper_id, 0, node_id.clone(), target_aggregation_number); + } + }, + } + } +} + +pub fn increase_aggregation_number_internal( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + node_id:&C::NodeRef, + min_aggregation_number:u32, + target_aggregation_number:u32, + reason:IncreaseReason, +) { + let prepared = node.increase_aggregation_number_internal( + ctx, + node_id, + min_aggregation_number, + target_aggregation_number, + reason, + ); + drop(node); + prepared.apply(ctx, balance_queue); +} + +/// A prepared `increase_aggregation_number` operation. +pub struct PreparedIncreaseAggregationNumber( + PreparedInternalIncreaseAggregationNumber, +); + +impl PreparedOperation for PreparedIncreaseAggregationNumber { + type Result = (); + + fn apply(self, ctx:&C) { + let mut balance_queue = BalanceQueue::new(); + self.0.apply(ctx, &mut balance_queue); + balance_queue.process(ctx); + } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/loom_tests.rs b/crates/turbo-tasks-memory/Source/aggregation/loom_tests.rs new file mode 100644 index 0000000000000..1b5e29f4e843f --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/loom_tests.rs @@ -0,0 +1,249 @@ +use std::{ + fmt::Debug, + hash::Hash, + ops::{Deref, DerefMut}, + sync::{Arc, atomic::AtomicU32}, +}; + +use loom::{ + sync::{Mutex, MutexGuard}, + thread, +}; +use nohash_hasher::IsEnabled; +use rand::{Rng, SeedableRng, rngs::SmallRng}; +use ref_cast::RefCast; +use rstest::*; + +use super::{ + AggregationContext, + AggregationNode, + AggregationNodeGuard, + PreparedOperation, + aggregation_data, + handle_new_edge, +}; + +struct Node { + atomic:AtomicU32, + inner:Mutex, +} + +impl Node { + fn new(value:u32) -> Arc { + Arc::new(Node { + atomic:AtomicU32::new(0), + inner:Mutex::new(NodeInner { + children:Vec::new(), + aggregation_node:AggregationNode::new(), + value, + }), + }) + } + + fn add_child(self: &Arc, aggregation_context:&NodeAggregationContext, child:Arc) { + let mut guard = self.inner.lock().unwrap(); + guard.children.push(child.clone()); + let number_of_children = guard.children.len(); + let mut guard = unsafe { NodeGuard::new(guard, self.clone()) }; + let prepared = handle_new_edge( + aggregation_context, + &mut guard, + &NodeRef(self.clone()), + &NodeRef(child), + number_of_children, + ); + drop(guard); + prepared.apply(aggregation_context); + } +} + +#[derive(Copy, Clone)] +struct Change {} + +struct NodeInner { + children:Vec>, + aggregation_node:AggregationNode, + value:u32, +} + +struct NodeAggregationContext {} + +#[derive(Clone, RefCast)] +#[repr(transparent)] +struct NodeRef(Arc); + +impl Debug for NodeRef { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "NodeRef({})", self.0.inner.lock().unwrap().value) + } +} + +impl Hash for NodeRef { + fn hash(&self, state:&mut H) { Arc::as_ptr(&self.0).hash(state); } +} + +impl IsEnabled for NodeRef {} + +impl PartialEq for NodeRef { + fn eq(&self, other:&Self) -> bool { Arc::ptr_eq(&self.0, &other.0) } +} + +impl Eq for NodeRef {} + +struct NodeGuard { + guard:MutexGuard<'static, NodeInner>, + // This field is important to keep the node alive + #[allow(dead_code)] + node:Arc, +} + +impl NodeGuard { + unsafe fn new(guard:MutexGuard<'_, NodeInner>, node:Arc) -> Self { + NodeGuard { guard:unsafe { std::mem::transmute(guard) }, node } + } +} + +impl Deref for NodeGuard { + type Target = AggregationNode; + + fn deref(&self) -> &Self::Target { &self.guard.aggregation_node } +} + +impl DerefMut for NodeGuard { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.guard.aggregation_node } +} + +impl AggregationNodeGuard for NodeGuard { + type Data = Aggregated; + type DataChange = Change; + type NodeRef = NodeRef; + + type ChildrenIter<'a> = impl Iterator + 'a; + + fn children(&self) -> Self::ChildrenIter<'_> { + self.guard.children.iter().map(|child| NodeRef(child.clone())) + } + + fn get_remove_change(&self) -> Option { None } + + fn get_add_change(&self) -> Option { None } + + fn get_initial_data(&self) -> Self::Data { Aggregated {} } +} + +impl AggregationContext for NodeAggregationContext { + type Data = Aggregated; + type DataChange = Change; + type Guard<'l> + = NodeGuard + where + Self: 'l; + type NodeRef = NodeRef; + + fn node<'b>(&'b self, reference:&Self::NodeRef) -> Self::Guard<'b> { + let r = reference.0.clone(); + let guard = reference.0.inner.lock().unwrap(); + unsafe { NodeGuard::new(guard, r) } + } + + fn atomic_in_progress_counter<'l>(&self, id:&'l NodeRef) -> &'l AtomicU32 + where + Self: 'l, { + &id.0.atomic + } + + fn apply_change(&self, _data:&mut Aggregated, _change:&Change) -> Option { None } + + fn data_to_add_change(&self, _data:&Self::Data) -> Option { None } + + fn data_to_remove_change(&self, _data:&Self::Data) -> Option { None } +} + +#[derive(Default)] +struct Aggregated {} + +// #[test] +#[allow(dead_code)] +fn fuzzy_loom_new() { + for size in [10, 20] { + for _ in 0..1000 { + let seed = rand::random(); + println!("Seed {} Size {}", seed, size); + fuzzy_loom(seed, size); + } + } +} + +#[rstest] +#[case::a(3302552607, 10)] +// #[case::b(3629477471, 50)] +// #[case::c(1006976052, 20)] +// #[case::d(2174645157, 10)] +fn fuzzy_loom(#[case] seed:u32, #[case] count:u32) { + let mut builder = loom::model::Builder::new(); + builder.max_branches = 100000; + builder.check(move || { + loom::stop_exploring(); + thread::Builder::new() + .stack_size(80000) + .spawn(move || { + let ctx = NodeAggregationContext {}; + + let mut seed_buffer = [0; 32]; + seed_buffer[0..4].copy_from_slice(&seed.to_be_bytes()); + let mut r = SmallRng::from_seed(seed_buffer); + let mut nodes = Vec::new(); + for i in 0..count { + nodes.push(Node::new(i)); + } + aggregation_data(&ctx, &NodeRef(nodes[0].clone())); + aggregation_data(&ctx, &NodeRef(nodes[1].clone())); + + // setup graph + for _ in 0..20 { + let parent = r.gen_range(0..nodes.len() - 1); + let child = r.gen_range(parent + 1..nodes.len()); + let parent_node = nodes[parent].clone(); + let child_node = nodes[child].clone(); + parent_node.add_child(&ctx, child_node); + } + + let mut edges = Vec::new(); + for _ in 0..2 { + let parent = r.gen_range(0..nodes.len() - 1); + let child = r.gen_range(parent + 1..nodes.len()); + let parent_node = nodes[parent].clone(); + let child_node = nodes[child].clone(); + edges.push((parent_node, child_node)); + } + + let ctx = Arc::new(ctx); + + loom::explore(); + + let mut threads = Vec::new(); + + // Fancy testing + for (parent_node, child_node) in edges.iter() { + let parent_node = parent_node.clone(); + let child_node = child_node.clone(); + let ctx = ctx.clone(); + threads.push( + thread::Builder::new() + .stack_size(80000) + .spawn(move || { + parent_node.add_child(&ctx, child_node); + }) + .unwrap(), + ); + } + + for thread in threads { + thread.join().unwrap(); + } + }) + .unwrap() + .join() + .unwrap(); + }); +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/lost_edge.rs b/crates/turbo-tasks-memory/Source/aggregation/lost_edge.rs new file mode 100644 index 0000000000000..c57f075474f29 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/lost_edge.rs @@ -0,0 +1,112 @@ +use std::hash::Hash; + +use super::{ + AggregationContext, + AggregationNode, + PreparedInternalOperation, + PreparedOperation, + StackVec, + balance_queue::BalanceQueue, + in_progress::start_in_progress_count, + notify_lost_follower::PreparedNotifyLostFollower, +}; + +impl AggregationNode { + /// Handles the loss of edges to a node. This will notify all upper nodes + /// about the new follower or add the new node as inner node. + #[must_use] + pub fn handle_lost_edges>( + &mut self, + ctx:&C, + origin_id:&C::NodeRef, + target_ids:impl IntoIterator, + ) -> Option> { + match self { + AggregationNode::Leaf { uppers, .. } => { + let uppers = uppers.iter().cloned().collect::>(); + let target_ids:StackVec<_> = target_ids.into_iter().collect(); + for upper_id in &uppers { + start_in_progress_count(ctx, upper_id, target_ids.len() as u32); + } + Some(PreparedLostEdgesInner::Leaf { uppers, target_ids }.into()) + }, + AggregationNode::Aggegating(_) => { + let notify = target_ids + .into_iter() + .filter_map(|target_id| { + self.notify_lost_follower_not_in_progress(ctx, origin_id, &target_id) + }) + .collect::>(); + (!notify.is_empty()).then(|| notify.into()) + }, + } + } +} + +/// A prepared `handle_lost_edges` operation. +pub struct PreparedLostEdges { + inner:PreparedLostEdgesInner, +} + +impl From> for PreparedLostEdges { + fn from(inner:PreparedLostEdgesInner) -> Self { Self { inner } } +} + +impl From>> for PreparedLostEdges { + fn from(notify:StackVec>) -> Self { + Self { inner:PreparedLostEdgesInner::Aggregating { notify } } + } +} + +#[allow(clippy::large_enum_variant)] +enum PreparedLostEdgesInner { + Leaf { uppers:StackVec, target_ids:StackVec }, + Aggregating { notify:StackVec> }, +} + +impl PreparedOperation for PreparedLostEdges { + type Result = (); + + fn apply(self, ctx:&C) { + let mut balance_queue = BalanceQueue::new(); + match self.inner { + PreparedLostEdgesInner::Leaf { uppers, target_ids } => { + // TODO This could be more efficient + for upper_id in uppers { + let mut upper = ctx.node(&upper_id); + let prepared = target_ids + .iter() + .filter_map(|target_id| { + upper.notify_lost_follower( + ctx, + &mut balance_queue, + &upper_id, + target_id, + ) + }) + .collect::>(); + drop(upper); + prepared.apply(ctx, &mut balance_queue); + } + }, + PreparedLostEdgesInner::Aggregating { notify } => { + notify.apply(ctx, &mut balance_queue); + }, + } + balance_queue.process(ctx); + } +} + +/// Handles the loss of edges to a node. This will notify all upper nodes +/// about the new follower or add the new node as inner node. +#[cfg(test)] +pub fn handle_lost_edges( + ctx:&C, + mut origin:C::Guard<'_>, + origin_id:&C::NodeRef, + target_ids:impl IntoIterator, +) { + let p = origin.handle_lost_edges(ctx, origin_id, target_ids); + drop(origin); + p.apply(ctx); +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/mod.rs b/crates/turbo-tasks-memory/Source/aggregation/mod.rs new file mode 100644 index 0000000000000..10474d4eab01b --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/mod.rs @@ -0,0 +1,224 @@ +use std::{fmt::Debug, hash::Hash, ops::DerefMut, sync::atomic::AtomicU32}; + +use smallvec::SmallVec; + +use crate::count_hash_set::CountHashSet; + +mod aggregation_data; +mod balance_edge; +mod balance_queue; +mod change; +mod followers; +mod in_progress; +mod increase; +#[cfg(test)] +mod loom_tests; +mod lost_edge; +mod new_edge; +mod notify_lost_follower; +mod notify_new_follower; +mod optimize; +mod root_query; +#[cfg(test)] +mod tests; +mod uppers; + +pub use aggregation_data::{AggregationDataGuard, aggregation_data, prepare_aggregation_data}; +use balance_edge::balance_edge; +use increase::increase_aggregation_number_internal; +pub use new_edge::handle_new_edge; +use notify_lost_follower::notify_lost_follower; +use notify_new_follower::notify_new_follower; +pub use root_query::{RootQuery, query_root_info}; + +use self::balance_queue::BalanceQueue; + +type StackVec = SmallVec<[I; 16]>; + +/// The aggregation node structure. This stores the aggregation number, the +/// aggregation edges to uppers and followers and the aggregated data. +pub enum AggregationNode { + Leaf { aggregation_number:u8, uppers:CountHashSet }, + Aggegating(Box>), +} + +impl AggregationNode { + pub fn new() -> Self { Self::Leaf { aggregation_number:0, uppers:CountHashSet::new() } } +} + +/// The aggregation node structure for aggregating nodes. +pub struct AggegatingNode { + aggregation_number:u32, + uppers:CountHashSet, + followers:CountHashSet, + data:D, + enqueued_balancing:Vec<(I, u32, I, u32)>, +} + +impl AggregationNode { + /// Returns the aggregation number of the node. + pub fn aggregation_number(&self) -> u32 { + match self { + AggregationNode::Leaf { aggregation_number, .. } => *aggregation_number as u32, + AggregationNode::Aggegating(aggegating) => aggegating.aggregation_number, + } + } + + fn is_leaf(&self) -> bool { matches!(self, AggregationNode::Leaf { .. }) } + + fn uppers(&self) -> &CountHashSet { + match self { + AggregationNode::Leaf { uppers, .. } => uppers, + AggregationNode::Aggegating(aggegating) => &aggegating.uppers, + } + } + + fn uppers_mut(&mut self) -> &mut CountHashSet { + match self { + AggregationNode::Leaf { uppers, .. } => uppers, + AggregationNode::Aggegating(aggegating) => &mut aggegating.uppers, + } + } + + fn followers(&self) -> Option<&CountHashSet> { + match self { + AggregationNode::Leaf { .. } => None, + AggregationNode::Aggegating(aggegating) => Some(&aggegating.followers), + } + } +} + +/// A prepared operation. Must be applied outside of node locks. +#[must_use] +pub trait PreparedOperation { + type Result; + fn apply(self, ctx:&C) -> Self::Result; +} + +impl> PreparedOperation for Option { + type Result = Option; + + fn apply(self, ctx:&C) -> Self::Result { self.map(|prepared| prepared.apply(ctx)) } +} + +impl> PreparedOperation for Vec { + type Result = (); + + fn apply(self, ctx:&C) -> Self::Result { + for prepared in self { + prepared.apply(ctx); + } + } +} + +impl, const N: usize> PreparedOperation + for SmallVec<[T; N]> +{ + type Result = (); + + fn apply(self, ctx:&C) -> Self::Result { + for prepared in self { + prepared.apply(ctx); + } + } +} + +/// A prepared internal operation. Must be applied inside of node locks and with +/// a balance queue. +#[must_use] +trait PreparedInternalOperation { + type Result; + fn apply(self, ctx:&C, balance_queue:&mut BalanceQueue) -> Self::Result; +} + +impl> PreparedInternalOperation + for Option +{ + type Result = Option; + + fn apply(self, ctx:&C, balance_queue:&mut BalanceQueue) -> Self::Result { + self.map(|prepared| prepared.apply(ctx, balance_queue)) + } +} + +impl> PreparedInternalOperation for Vec { + type Result = (); + + fn apply(self, ctx:&C, balance_queue:&mut BalanceQueue) -> Self::Result { + for prepared in self { + prepared.apply(ctx, balance_queue); + } + } +} + +impl, const N: usize> + PreparedInternalOperation for SmallVec<[T; N]> +{ + type Result = (); + + fn apply(self, ctx:&C, balance_queue:&mut BalanceQueue) -> Self::Result { + for prepared in self { + prepared.apply(ctx, balance_queue); + } + } +} + +/// Context for aggregation operations. +pub trait AggregationContext { + type NodeRef: Clone + Eq + Hash + Debug; + type Guard<'l>: AggregationNodeGuard< + NodeRef = Self::NodeRef, + Data = Self::Data, + DataChange = Self::DataChange, + > + where + Self: 'l; + type Data; + type DataChange; + + /// Gets mutable access to an item. + fn node<'l>(&'l self, id:&Self::NodeRef) -> Self::Guard<'l>; + + /// Get the atomic in progress counter for a node. + fn atomic_in_progress_counter<'l>(&self, id:&'l Self::NodeRef) -> &'l AtomicU32 + where + Self: 'l; + + /// Apply a changeset to an aggregated data object. Returns a new changeset + /// that should be applied to the next aggregation level. Might return None, + /// if no change should be applied to the next level. + fn apply_change( + &self, + data:&mut Self::Data, + change:&Self::DataChange, + ) -> Option; + + /// Creates a changeset from an aggregated data object, that represents + /// adding the aggregated node to an aggregated node of the next level. + fn data_to_add_change(&self, data:&Self::Data) -> Option; + /// Creates a changeset from an aggregated data object, that represents + /// removing the aggregated node from an aggregated node of the next level. + fn data_to_remove_change(&self, data:&Self::Data) -> Option; +} + +/// A guard for a node that allows to access the aggregation node, children and +/// data. +pub trait AggregationNodeGuard: + DerefMut> { + type NodeRef: Clone + Eq + Hash; + type Data; + type DataChange; + + type ChildrenIter<'a>: Iterator + 'a + where + Self: 'a; + + /// Returns an iterator over the children. + fn children(&self) -> Self::ChildrenIter<'_>; + /// Returns a changeset that represents the addition of the node. + fn get_add_change(&self) -> Option; + /// Returns a changeset that represents the removal of the node. + fn get_remove_change(&self) -> Option; + /// Returns the aggregated data which contains only that node + fn get_initial_data(&self) -> Self::Data; +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/new_edge.rs b/crates/turbo-tasks-memory/Source/aggregation/new_edge.rs new file mode 100644 index 0000000000000..e82a5cb435a71 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/new_edge.rs @@ -0,0 +1,169 @@ +use super::{ + AggregationContext, + AggregationNode, + PreparedInternalOperation, + PreparedOperation, + StackVec, + balance_queue::BalanceQueue, + in_progress::start_in_progress_all, + increase::{ + IncreaseReason, + LEAF_NUMBER, + PreparedInternalIncreaseAggregationNumber, + increase_aggregation_number_immediately, + }, + increase_aggregation_number_internal, + notify_new_follower, + notify_new_follower::PreparedNotifyNewFollower, + optimize::optimize_aggregation_number_for_uppers, +}; + +const BUFFER_SPACE:u32 = 2; + +const MAX_UPPERS_TIMES_CHILDREN:usize = 32; + +const MAX_AFFECTED_NODES:usize = 4096; + +/// Handle the addition of a new edge to a node. The the edge is propagated to +/// the uppers of that node or added a inner node. +pub fn handle_new_edge( + ctx:&C, + origin:&mut C::Guard<'_>, + origin_id:&C::NodeRef, + target_id:&C::NodeRef, + number_of_children:usize, +) -> impl PreparedOperation { + match **origin { + AggregationNode::Leaf { ref mut aggregation_number, ref uppers } => { + if number_of_children.count_ones() == 1 + && (uppers.len() + 1) * number_of_children >= MAX_UPPERS_TIMES_CHILDREN + { + let uppers = uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + let increase = increase_aggregation_number_immediately( + ctx, + origin, + origin_id.clone(), + LEAF_NUMBER, + LEAF_NUMBER, + IncreaseReason::Upgraded, + ) + .unwrap(); + Some(PreparedNewEdge::Upgraded { uppers, target_id:target_id.clone(), increase }) + } else { + let min_aggregation_number = *aggregation_number as u32 + 1; + let target_aggregation_number = *aggregation_number as u32 + 1 + BUFFER_SPACE; + let uppers = uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + Some(PreparedNewEdge::Leaf { + min_aggregation_number, + target_aggregation_number, + uppers, + target_id:target_id.clone(), + }) + } + }, + AggregationNode::Aggegating(_) => { + origin + .notify_new_follower_not_in_progress(ctx, origin_id, target_id) + .map(|notify| PreparedNewEdge::Aggegating { target_id:target_id.clone(), notify }) + }, + } +} + +/// A prepared `handle_new_edge` operation. +enum PreparedNewEdge { + Leaf { + min_aggregation_number:u32, + target_aggregation_number:u32, + uppers:StackVec, + target_id:C::NodeRef, + }, + Upgraded { + uppers:StackVec, + target_id:C::NodeRef, + increase:PreparedInternalIncreaseAggregationNumber, + }, + Aggegating { + notify:PreparedNotifyNewFollower, + target_id:C::NodeRef, + }, +} + +impl PreparedOperation for PreparedNewEdge { + type Result = (); + + fn apply(self, ctx:&C) { + let mut balance_queue = BalanceQueue::new(); + match self { + PreparedNewEdge::Leaf { + min_aggregation_number, + target_aggregation_number, + uppers, + target_id, + } => { + increase_aggregation_number_internal( + ctx, + &mut balance_queue, + ctx.node(&target_id), + &target_id, + min_aggregation_number, + target_aggregation_number, + IncreaseReason::LeafEdge, + ); + let mut affected_nodes = 0; + for upper_id in uppers { + affected_nodes += notify_new_follower( + ctx, + &mut balance_queue, + ctx.node(&upper_id), + &upper_id, + &target_id, + false, + ); + if affected_nodes > MAX_AFFECTED_NODES { + handle_expensive_node(ctx, &mut balance_queue, &target_id); + } + } + }, + PreparedNewEdge::Upgraded { uppers, target_id, increase } => { + // Since it was added to a leaf node, we would add it to the uppers + for upper_id in uppers { + notify_new_follower( + ctx, + &mut balance_queue, + ctx.node(&upper_id), + &upper_id, + &target_id, + true, + ); + } + // The balancing will attach it to the aggregated node later + increase.apply(ctx, &mut balance_queue); + }, + PreparedNewEdge::Aggegating { target_id, notify } => { + let affected_nodes = notify.apply(ctx, &mut balance_queue); + if affected_nodes > MAX_AFFECTED_NODES { + handle_expensive_node(ctx, &mut balance_queue, &target_id); + } + }, + } + balance_queue.process(ctx); + } +} + +/// Called in the case when we detect that adding this node was expensive. It +/// optimizes the aggregation number of the node so it can be cheaper on the +/// next call. +fn handle_expensive_node( + ctx:&C, + balance_queue:&mut BalanceQueue, + node_id:&C::NodeRef, +) { + let _span = tracing::trace_span!("handle_expensive_node").entered(); + let node = ctx.node(node_id); + let uppers = node.uppers().iter().cloned().collect::>(); + let leaf = matches!(*node, AggregationNode::Leaf { .. }); + drop(node); + optimize_aggregation_number_for_uppers(ctx, balance_queue, node_id, leaf, uppers); +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/notify_lost_follower.rs b/crates/turbo-tasks-memory/Source/aggregation/notify_lost_follower.rs new file mode 100644 index 0000000000000..97796b881f89c --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/notify_lost_follower.rs @@ -0,0 +1,213 @@ +use std::{hash::Hash, thread::yield_now}; + +use super::{ + AggegatingNode, + AggregationContext, + AggregationNode, + AggregationNodeGuard, + PreparedInternalOperation, + PreparedOperation, + StackVec, + balance_queue::BalanceQueue, + in_progress::{finish_in_progress_without_node, start_in_progress, start_in_progress_all}, +}; +use crate::count_hash_set::RemoveIfEntryResult; + +impl AggregationNode { + /// Called when a inner node of the upper node has lost a follower + /// It's expected that the upper node is flagged as "in progress". + pub(super) fn notify_lost_follower>( + &mut self, + ctx:&C, + balance_queue:&mut BalanceQueue, + upper_id:&C::NodeRef, + follower_id:&C::NodeRef, + ) -> Option> { + let AggregationNode::Aggegating(aggregating) = self else { + unreachable!(); + }; + match aggregating.followers.remove_if_entry(follower_id) { + RemoveIfEntryResult::PartiallyRemoved => { + self.finish_in_progress(ctx, balance_queue, upper_id); + None + }, + RemoveIfEntryResult::Removed => { + let uppers = aggregating.uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + self.finish_in_progress(ctx, balance_queue, upper_id); + Some(PreparedNotifyLostFollower::RemovedFollower { + uppers, + follower_id:follower_id.clone(), + }) + }, + RemoveIfEntryResult::NotPresent => { + Some(PreparedNotifyLostFollower::NotFollower { + upper_id:upper_id.clone(), + follower_id:follower_id.clone(), + }) + }, + } + } + + /// Called when a inner node of the upper node has lost a follower. + /// It's expected that the upper node is NOT flagged as "in progress". + pub(super) fn notify_lost_follower_not_in_progress< + C:AggregationContext, + >( + &mut self, + ctx:&C, + upper_id:&C::NodeRef, + follower_id:&C::NodeRef, + ) -> Option> { + let AggregationNode::Aggegating(aggregating) = self else { + unreachable!(); + }; + match aggregating.followers.remove_if_entry(follower_id) { + RemoveIfEntryResult::PartiallyRemoved => None, + RemoveIfEntryResult::Removed => { + let uppers = aggregating.uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + Some(PreparedNotifyLostFollower::RemovedFollower { + uppers, + follower_id:follower_id.clone(), + }) + }, + RemoveIfEntryResult::NotPresent => { + start_in_progress(ctx, upper_id); + Some(PreparedNotifyLostFollower::NotFollower { + upper_id:upper_id.clone(), + follower_id:follower_id.clone(), + }) + }, + } + } +} + +/// A prepared `notify_lost_follower` operation. +pub(super) enum PreparedNotifyLostFollower { + RemovedFollower { uppers:StackVec, follower_id:C::NodeRef }, + NotFollower { upper_id:C::NodeRef, follower_id:C::NodeRef }, +} + +impl PreparedInternalOperation for PreparedNotifyLostFollower { + type Result = (); + + fn apply(self, ctx:&C, balance_queue:&mut BalanceQueue) { + match self { + PreparedNotifyLostFollower::RemovedFollower { uppers, follower_id } => { + for upper_id in uppers { + notify_lost_follower( + ctx, + balance_queue, + ctx.node(&upper_id), + &upper_id, + &follower_id, + ); + } + }, + PreparedNotifyLostFollower::NotFollower { upper_id, follower_id } => { + loop { + let mut follower = ctx.node(&follower_id); + match follower.uppers_mut().remove_if_entry(&upper_id) { + RemoveIfEntryResult::PartiallyRemoved => { + finish_in_progress_without_node(ctx, balance_queue, &upper_id); + drop(follower); + return; + }, + RemoveIfEntryResult::Removed => { + let remove_change = get_aggregated_remove_change(ctx, &follower); + let followers = match &*follower { + AggregationNode::Leaf { .. } => { + follower.children().collect::>() + }, + AggregationNode::Aggegating(aggregating) => { + let AggegatingNode { ref followers, .. } = **aggregating; + followers.iter().cloned().collect::>() + }, + }; + drop(follower); + + let mut upper = ctx.node(&upper_id); + let remove_change = remove_change + .map(|remove_change| upper.apply_change(ctx, remove_change)); + let prepared = followers + .into_iter() + .filter_map(|follower_id| { + upper.notify_lost_follower_not_in_progress( + ctx, + &upper_id, + &follower_id, + ) + }) + .collect::>(); + upper.finish_in_progress(ctx, balance_queue, &upper_id); + drop(upper); + prepared.apply(ctx, balance_queue); + remove_change.apply(ctx); + return; + }, + RemoveIfEntryResult::NotPresent => { + drop(follower); + let mut upper = ctx.node(&upper_id); + let AggregationNode::Aggegating(aggregating) = &mut *upper else { + unreachable!(); + }; + match aggregating.followers.remove_if_entry(&follower_id) { + RemoveIfEntryResult::PartiallyRemoved => { + upper.finish_in_progress(ctx, balance_queue, &upper_id); + return; + }, + RemoveIfEntryResult::Removed => { + let uppers = + aggregating.uppers.iter().cloned().collect::>(); + start_in_progress_all(ctx, &uppers); + upper.finish_in_progress(ctx, balance_queue, &upper_id); + drop(upper); + for upper_id in uppers { + notify_lost_follower( + ctx, + balance_queue, + ctx.node(&upper_id), + &upper_id, + &follower_id, + ); + } + return; + }, + RemoveIfEntryResult::NotPresent => { + drop(upper); + yield_now() + // Retry, concurrency + }, + } + }, + } + } + }, + } + } +} + +/// Notifies the upper node that a follower has been lost. +/// It's expected that the upper node is flagged as "in progress". +pub fn notify_lost_follower( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut upper:C::Guard<'_>, + upper_id:&C::NodeRef, + follower_id:&C::NodeRef, +) { + let p = upper.notify_lost_follower(ctx, balance_queue, upper_id, follower_id); + drop(upper); + p.apply(ctx, balance_queue); +} + +fn get_aggregated_remove_change( + ctx:&C, + guard:&C::Guard<'_>, +) -> Option { + match &**guard { + AggregationNode::Leaf { .. } => guard.get_remove_change(), + AggregationNode::Aggegating(aggegating) => ctx.data_to_remove_change(&aggegating.data), + } +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/notify_new_follower.rs b/crates/turbo-tasks-memory/Source/aggregation/notify_new_follower.rs new file mode 100644 index 0000000000000..02a9a8dcb5107 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/notify_new_follower.rs @@ -0,0 +1,251 @@ +use std::{cmp::Ordering, hash::Hash}; + +use super::{ + AggregationContext, + AggregationNode, + PreparedInternalOperation, + StackVec, + balance_queue::BalanceQueue, + followers::add_follower, + in_progress::{finish_in_progress_without_node, start_in_progress}, + increase::IncreaseReason, + increase_aggregation_number_internal, + optimize::optimize_aggregation_number_for_uppers, + uppers::add_upper, +}; + +const MAX_AFFECTED_NODES:usize = 4096; + +impl AggregationNode { + // Called when a inner node of the upper node has a new follower. + // It's expected that the upper node is flagged as "in progress". + pub(super) fn notify_new_follower>( + &mut self, + ctx:&C, + balance_queue:&mut BalanceQueue, + upper_id:&C::NodeRef, + follower_id:&C::NodeRef, + already_optimizing_for_upper:bool, + ) -> Option> { + let AggregationNode::Aggegating(aggregating) = self else { + unreachable!(); + }; + if aggregating.followers.add_if_entry(follower_id) { + self.finish_in_progress(ctx, balance_queue, upper_id); + None + } else { + let upper_aggregation_number = aggregating.aggregation_number; + if upper_aggregation_number == u32::MAX { + Some(PreparedNotifyNewFollower::Inner { + upper_id:upper_id.clone(), + follower_id:follower_id.clone(), + already_optimizing_for_upper, + }) + } else { + Some(PreparedNotifyNewFollower::FollowerOrInner { + upper_aggregation_number, + upper_id:upper_id.clone(), + follower_id:follower_id.clone(), + already_optimizing_for_upper, + }) + } + } + } + + // Called when a inner node of the upper node has a new follower. + // It's expected that the upper node is NOT flagged as "in progress". + pub(super) fn notify_new_follower_not_in_progress< + C:AggregationContext, + >( + &mut self, + ctx:&C, + upper_id:&C::NodeRef, + follower_id:&C::NodeRef, + ) -> Option> { + let AggregationNode::Aggegating(aggregating) = self else { + unreachable!(); + }; + if aggregating.followers.add_if_entry(follower_id) { + None + } else { + start_in_progress(ctx, upper_id); + let upper_aggregation_number = aggregating.aggregation_number; + if upper_aggregation_number == u32::MAX { + Some(PreparedNotifyNewFollower::Inner { + upper_id:upper_id.clone(), + follower_id:follower_id.clone(), + already_optimizing_for_upper:false, + }) + } else { + Some(PreparedNotifyNewFollower::FollowerOrInner { + upper_aggregation_number, + upper_id:upper_id.clone(), + follower_id:follower_id.clone(), + already_optimizing_for_upper:false, + }) + } + } + } +} + +/// A prepared `notify_new_follower` operation. +pub(super) enum PreparedNotifyNewFollower { + Inner { + upper_id:C::NodeRef, + follower_id:C::NodeRef, + already_optimizing_for_upper:bool, + }, + FollowerOrInner { + upper_aggregation_number:u32, + upper_id:C::NodeRef, + follower_id:C::NodeRef, + already_optimizing_for_upper:bool, + }, +} + +impl PreparedInternalOperation for PreparedNotifyNewFollower { + type Result = usize; + + fn apply(self, ctx:&C, balance_queue:&mut BalanceQueue) -> Self::Result { + match self { + PreparedNotifyNewFollower::Inner { + upper_id, + follower_id, + already_optimizing_for_upper, + } => { + let follower = ctx.node(&follower_id); + let affected_nodes = add_upper( + ctx, + balance_queue, + follower, + &follower_id, + &upper_id, + already_optimizing_for_upper, + ); + finish_in_progress_without_node(ctx, balance_queue, &upper_id); + if !already_optimizing_for_upper && affected_nodes > MAX_AFFECTED_NODES { + let follower = ctx.node(&follower_id); + let uppers = follower.uppers().iter().cloned().collect::>(); + let leaf:bool = follower.is_leaf(); + drop(follower); + if optimize_aggregation_number_for_uppers( + ctx, + balance_queue, + &follower_id, + leaf, + uppers, + ) { + return 1; + } + } + affected_nodes + }, + PreparedNotifyNewFollower::FollowerOrInner { + mut upper_aggregation_number, + upper_id, + follower_id, + already_optimizing_for_upper, + } => { + loop { + let follower = ctx.node(&follower_id); + let follower_aggregation_number = follower.aggregation_number(); + if follower_aggregation_number < upper_aggregation_number { + let affected_nodes = add_upper( + ctx, + balance_queue, + follower, + &follower_id, + &upper_id, + already_optimizing_for_upper, + ); + finish_in_progress_without_node(ctx, balance_queue, &upper_id); + if !already_optimizing_for_upper && affected_nodes > MAX_AFFECTED_NODES { + let follower = ctx.node(&follower_id); + let uppers = follower.uppers().iter().cloned().collect::>(); + let leaf = follower.is_leaf(); + drop(follower); + if optimize_aggregation_number_for_uppers( + ctx, + balance_queue, + &follower_id, + leaf, + uppers, + ) { + return 1; + } + } + return affected_nodes; + } else { + drop(follower); + let mut upper = ctx.node(&upper_id); + let AggregationNode::Aggegating(aggregating) = &mut *upper else { + unreachable!(); + }; + upper_aggregation_number = aggregating.aggregation_number; + if upper_aggregation_number == u32::MAX { + // retry, concurrency + } else { + match follower_aggregation_number.cmp(&upper_aggregation_number) { + Ordering::Less => { + // retry, concurrency + }, + Ordering::Equal => { + drop(upper); + let follower = ctx.node(&follower_id); + let follower_aggregation_number = follower.aggregation_number(); + if follower_aggregation_number == upper_aggregation_number { + increase_aggregation_number_internal( + ctx, + balance_queue, + follower, + &follower_id, + upper_aggregation_number + 1, + upper_aggregation_number + 1, + IncreaseReason::EqualAggregationNumberOnNewFollower, + ); + // retry + } else { + // retry, concurrency + } + }, + Ordering::Greater => { + upper.finish_in_progress(ctx, balance_queue, &upper_id); + return add_follower( + ctx, + balance_queue, + upper, + &upper_id, + &follower_id, + already_optimizing_for_upper, + ); + }, + } + } + } + } + }, + } + } +} + +/// Notifies the upper node that it has a new follower. +/// Returns the number of affected nodes. +/// The upper node is expected to be flagged as "in progress". +pub fn notify_new_follower( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut upper:C::Guard<'_>, + upper_id:&C::NodeRef, + follower_id:&C::NodeRef, + already_optimizing_for_upper:bool, +) -> usize { + let p = upper.notify_new_follower( + ctx, + balance_queue, + upper_id, + follower_id, + already_optimizing_for_upper, + ); + drop(upper); + p.apply(ctx, balance_queue).unwrap_or_default() +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/optimize.rs b/crates/turbo-tasks-memory/Source/aggregation/optimize.rs new file mode 100644 index 0000000000000..0405a2bdff433 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/optimize.rs @@ -0,0 +1,147 @@ +use tracing::Level; + +use super::{ + AggregationContext, + StackVec, + balance_queue::BalanceQueue, + increase::{IncreaseReason, LEAF_NUMBER, increase_aggregation_number_internal}, +}; + +pub const MAX_UPPERS:usize = 512; + +pub const MAX_FOLLOWERS:usize = 128; + +/// Optimize the aggregation number for a node based on a list of upper nodes. +/// The goal is to reduce the number of upper nodes, so we try to find a +/// aggregation number that is higher than some of the upper nodes. +/// Returns true if the aggregation number was increased. +#[tracing::instrument(level = Level::TRACE, skip(ctx, balance_queue, node_id, uppers))] +pub fn optimize_aggregation_number_for_uppers( + ctx:&C, + balance_queue:&mut BalanceQueue, + node_id:&C::NodeRef, + leaf:bool, + uppers:StackVec, +) -> bool { + let count = uppers.len(); + let mut root_count = 0; + let mut min = u32::MAX; + let mut max = 0; + let mut uppers_uppers = 0; + for upper_id in uppers.into_iter() { + let upper = ctx.node(&upper_id); + let aggregation_number = upper.aggregation_number(); + if aggregation_number == u32::MAX { + root_count += 1; + } else { + let upper_uppers = upper.uppers().len(); + uppers_uppers += upper_uppers; + if aggregation_number < min { + min = aggregation_number; + } + if aggregation_number > max { + max = aggregation_number; + } + } + } + if min == u32::MAX { + min = LEAF_NUMBER - 1; + } + if max < LEAF_NUMBER { + max = LEAF_NUMBER - 1; + } + let aggregation_number = (min + max) / 2 + 1; + if leaf { + increase_aggregation_number_internal( + ctx, + balance_queue, + ctx.node(node_id), + node_id, + aggregation_number, + aggregation_number, + IncreaseReason::OptimizeForUppers, + ); + return true; + } else { + let normal_count = count - root_count; + if normal_count > 0 { + let avg_uppers_uppers = uppers_uppers / normal_count; + if count > avg_uppers_uppers && root_count * 2 < count { + increase_aggregation_number_internal( + ctx, + balance_queue, + ctx.node(node_id), + node_id, + aggregation_number, + aggregation_number, + IncreaseReason::OptimizeForUppers, + ); + return true; + } + } + } + false +} + +/// Optimize the aggregation number for a node based on a list of followers. +/// The goal is to reduce the number of followers, so we try to find a +/// aggregation number that is higher than some of the followers. +/// Returns true if the aggregation number was increased. +#[tracing::instrument(level = Level::TRACE, skip(ctx, balance_queue, node_id, followers))] +pub fn optimize_aggregation_number_for_followers( + ctx:&C, + balance_queue:&mut BalanceQueue, + node_id:&C::NodeRef, + followers:StackVec, + force:bool, +) -> bool { + let count = followers.len(); + let mut root_count = 0; + let mut min = u32::MAX; + let mut max = 0; + let mut followers_followers = 0; + for follower_id in followers.into_iter() { + let follower = ctx.node(&follower_id); + let aggregation_number = follower.aggregation_number(); + if aggregation_number == u32::MAX { + root_count += 1; + } else { + let follower_followers = follower.followers().map_or(0, |f| f.len()); + followers_followers += follower_followers; + if aggregation_number < min { + min = aggregation_number; + } + if aggregation_number > max { + max = aggregation_number; + } + } + } + if min == u32::MAX { + min = LEAF_NUMBER - 1; + } + if min < LEAF_NUMBER { + min = LEAF_NUMBER - 1; + } + if max < min { + max = min; + } + let normal_count = count - root_count; + if normal_count > 0 { + let avg_followers_followers = followers_followers / normal_count; + let makes_sense = count > avg_followers_followers || force; + if makes_sense && root_count * 2 < count { + let aggregation_number = (min + max) / 2 + 1; + increase_aggregation_number_internal( + ctx, + balance_queue, + ctx.node(node_id), + node_id, + aggregation_number, + aggregation_number, + IncreaseReason::OptimizeForFollowers, + ); + return true; + } + } + false +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/root_query.rs b/crates/turbo-tasks-memory/Source/aggregation/root_query.rs new file mode 100644 index 0000000000000..76979af1a5153 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/root_query.rs @@ -0,0 +1,51 @@ +use std::ops::ControlFlow; + +use auto_hash_map::AutoSet; + +use super::{AggregationContext, AggregationNode, StackVec}; + +/// A query about aggregation data in a root node. +pub trait RootQuery { + type Data; + type Result; + + /// Processes the aggregated data of a root node. Can decide to stop the + /// query. + fn query(&mut self, data:&Self::Data) -> ControlFlow<()>; + /// Returns the result of the query. + fn result(self) -> Self::Result; +} + +/// Queries the root node of an aggregation tree. +pub fn query_root_info>( + ctx:&C, + mut query:Q, + node_id:C::NodeRef, +) -> Q::Result { + let mut queue = StackVec::new(); + queue.push(node_id); + let mut visited = AutoSet::new(); + while let Some(node_id) = queue.pop() { + let node = ctx.node(&node_id); + match &*node { + AggregationNode::Leaf { uppers, .. } => { + for upper_id in uppers.iter() { + if visited.insert(upper_id.clone()) { + queue.push(upper_id.clone()); + } + } + }, + AggregationNode::Aggegating(aggegrating) => { + if let ControlFlow::Break(_) = query.query(&aggegrating.data) { + return query.result(); + } + for upper_id in aggegrating.uppers.iter() { + if visited.insert(upper_id.clone()) { + queue.push(upper_id.clone()); + } + } + }, + } + } + query.result() +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/tests.rs b/crates/turbo-tasks-memory/Source/aggregation/tests.rs new file mode 100644 index 0000000000000..c23e57fca6d57 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/tests.rs @@ -0,0 +1,1015 @@ +use std::{ + collections::HashSet, + fmt::Debug, + hash::Hash, + iter::once, + ops::{ControlFlow, Deref, DerefMut}, + sync::{ + Arc, + atomic::{AtomicU32, Ordering}, + }, + time::Instant, +}; + +use indexmap::IndexSet; +use nohash_hasher::IsEnabled; +use parking_lot::{Mutex, MutexGuard}; +use rand::{Rng, SeedableRng, rngs::SmallRng}; +use ref_cast::RefCast; +use rstest::*; + +use self::aggregation_data::prepare_aggregation_data; +use super::{ + AggregationContext, + AggregationNode, + AggregationNodeGuard, + RootQuery, + aggregation_data, + handle_new_edge, + lost_edge::handle_lost_edges, +}; +use crate::aggregation::{PreparedOperation, StackVec, query_root_info}; + +fn find_root(mut node:NodeRef) -> NodeRef { + loop { + let lock = node.0.inner.lock(); + let uppers = lock.aggregation_node.uppers(); + if uppers.is_empty() { + drop(lock); + return node; + } + let upper = uppers.iter().next().unwrap().clone(); + drop(lock); + node = upper; + } +} + +fn check_invariants<'a>( + ctx:&NodeAggregationContext<'a>, + node_ids:impl IntoIterator, +) { + let mut queue = node_ids.into_iter().collect::>(); + // print(ctx, &queue[0], true); + let mut visited = HashSet::new(); + while let Some(node_id) = queue.pop() { + assert_eq!(node_id.0.atomic.load(Ordering::SeqCst), 0); + let node = ctx.node(&node_id); + for child_id in node.children() { + if visited.insert(child_id.clone()) { + queue.push(child_id.clone()); + } + } + + let aggregation_number = node.aggregation_number(); + let node_value = node.guard.value; + let uppers = match &*node { + AggregationNode::Leaf { uppers, .. } => { + let uppers = uppers.iter().cloned().collect::>(); + drop(node); + uppers + }, + AggregationNode::Aggegating(aggegrating) => { + let uppers = aggegrating.uppers.iter().cloned().collect::>(); + let followers = aggegrating.followers.iter().cloned().collect::>(); + drop(node); + for follower_id in followers { + let follower_aggregation_number; + let follower_uppers; + let follower_value; + { + let follower = ctx.node(&follower_id); + + follower_aggregation_number = follower.aggregation_number(); + follower_uppers = + follower.uppers().iter().cloned().collect::>(); + follower_value = follower.guard.value; + } + + // A follower should have a bigger aggregation number + let condition = follower_aggregation_number > aggregation_number + || aggregation_number == u32::MAX; + if !condition { + let msg = format!( + "follower #{} {} -> #{} {}", + node_value, + aggregation_number, + follower_value, + follower_aggregation_number + ); + print(ctx, &find_root(node_id.clone()), true); + panic!("{msg}"); + } + + // All followers should also be connected to all uppers + let missing_uppers = uppers.iter().filter(|&upper_id| { + if follower_uppers + .iter() + .any(|follower_upper_id| follower_upper_id == upper_id) + { + return false; + } + let upper = ctx.node(upper_id); + if let Some(followers) = upper.followers() { + !followers + .iter() + .any(|follower_upper_id| follower_upper_id == &follower_id) + } else { + false + } + }); + #[allow(clippy::never_loop)] + for missing_upper in missing_uppers { + let upper_value = { + let upper = ctx.node(missing_upper); + upper.guard.value + }; + let msg = format!( + "follower #{} -> #{} is not connected to upper #{}", + node_value, follower_value, upper_value, + ); + print(ctx, &find_root(node_id.clone()), true); + panic!("{msg}"); + } + + // And visit them too + if visited.insert(follower_id.clone()) { + queue.push(follower_id); + } + } + uppers + }, + }; + for upper_id in uppers { + { + let upper = ctx.node(&upper_id); + let upper_aggregation_number = upper.aggregation_number(); + let condition = + upper_aggregation_number > aggregation_number || aggregation_number == u32::MAX; + if !condition { + let msg = format!( + "upper #{} {} -> #{} {}", + node_value, aggregation_number, upper.guard.value, upper_aggregation_number + ); + drop(upper); + print(ctx, &find_root(upper_id.clone()), true); + panic!("{msg}"); + } + } + if visited.insert(upper_id.clone()) { + queue.push(upper_id); + } + } + } +} + +fn print_graph( + ctx:&C, + entries:impl IntoIterator, + show_internal:bool, + name_fn:impl Fn(&C::NodeRef) -> String, +) { + let mut queue = entries.into_iter().collect::>(); + let mut visited = queue.iter().cloned().collect::>(); + while let Some(node_id) = queue.pop() { + let name = name_fn(&node_id); + let node = ctx.node(&node_id); + let n = node.aggregation_number(); + let n = if n == u32::MAX { "♾".to_string() } else { n.to_string() }; + let color = if matches!(*node, AggregationNode::Leaf { .. }) { "gray" } else { "#99ff99" }; + let children = node.children().collect::>(); + let uppers = node.uppers().iter().cloned().collect::>(); + let followers = match &*node { + AggregationNode::Aggegating(aggegrating) => { + aggegrating.followers.iter().cloned().collect::>() + }, + AggregationNode::Leaf { .. } => StackVec::new(), + }; + drop(node); + + if show_internal { + println!( + "\"{}\" [label=\"{}\\n{}\", style=filled, fillcolor=\"{}\"];", + name, name, n, color + ); + } else { + println!( + "\"{}\" [label=\"{}\\n{}\\n{}U {}F\", style=filled, fillcolor=\"{}\"];", + name, + name, + n, + uppers.len(), + followers.len(), + color, + ); + } + + for child_id in children { + let child_name = name_fn(&child_id); + println!("\"{}\" -> \"{}\";", name, child_name); + if visited.insert(child_id.clone()) { + queue.push(child_id); + } + } + if show_internal { + for upper_id in uppers { + let upper_name = name_fn(&upper_id); + println!("\"{}\" -> \"{}\" [style=dashed, color=green];", name, upper_name); + if visited.insert(upper_id.clone()) { + queue.push(upper_id); + } + } + for follower_id in followers { + let follower_name = name_fn(&follower_id); + println!("\"{}\" -> \"{}\" [style=dashed, color=red];", name, follower_name); + if visited.insert(follower_id.clone()) { + queue.push(follower_id); + } + } + } + } +} + +struct Node { + atomic:AtomicU32, + inner:Mutex, +} + +impl Node { + fn new(value:u32) -> Arc { + Arc::new(Node { + atomic:AtomicU32::new(0), + inner:Mutex::new(NodeInner { + children:Vec::new(), + aggregation_node:AggregationNode::new(), + value, + }), + }) + } + + fn new_with_children( + aggregation_context:&NodeAggregationContext, + value:u32, + children:Vec>, + ) -> Arc { + let node = Self::new(value); + for child in children { + node.add_child(aggregation_context, child); + } + node + } + + fn add_child(self: &Arc, aggregation_context:&NodeAggregationContext, child:Arc) { + self.add_child_unchecked(aggregation_context, child); + check_invariants(aggregation_context, once(find_root(NodeRef(self.clone())))); + } + + fn add_child_unchecked( + self: &Arc, + aggregation_context:&NodeAggregationContext, + child:Arc, + ) { + let mut guard = self.inner.lock(); + guard.children.push(child.clone()); + let number_of_children = guard.children.len(); + let mut guard = unsafe { NodeGuard::new(guard, self.clone()) }; + let prepared = handle_new_edge( + aggregation_context, + &mut guard, + &NodeRef(self.clone()), + &NodeRef(child), + number_of_children, + ); + drop(guard); + prepared.apply(aggregation_context); + } + + fn prepare_add_child<'c>( + self: &Arc, + aggregation_context:&'c NodeAggregationContext<'c>, + child:Arc, + ) -> impl PreparedOperation> { + let mut guard = self.inner.lock(); + guard.children.push(child.clone()); + let number_of_children = guard.children.len(); + let mut guard = unsafe { NodeGuard::new(guard, self.clone()) }; + handle_new_edge( + aggregation_context, + &mut guard, + &NodeRef(self.clone()), + &NodeRef(child), + number_of_children, + ) + } + + fn prepare_aggregation_number<'c>( + self: &Arc, + aggregation_context:&'c NodeAggregationContext<'c>, + aggregation_number:u32, + ) -> impl PreparedOperation> { + let mut guard = self.inner.lock(); + guard.aggregation_node.increase_aggregation_number( + aggregation_context, + &NodeRef(self.clone()), + aggregation_number, + ) + } + + fn remove_child( + self: &Arc, + aggregation_context:&NodeAggregationContext, + child:&Arc, + ) { + self.remove_child_unchecked(aggregation_context, child); + check_invariants(aggregation_context, once(NodeRef(self.clone()))); + } + + fn remove_child_unchecked( + self: &Arc, + aggregation_context:&NodeAggregationContext, + child:&Arc, + ) { + let mut guard = self.inner.lock(); + if let Some(idx) = guard.children.iter().position(|item| Arc::ptr_eq(item, child)) { + guard.children.swap_remove(idx); + handle_lost_edges( + aggregation_context, + unsafe { NodeGuard::new(guard, self.clone()) }, + &NodeRef(self.clone()), + [NodeRef(child.clone())], + ); + } + } + + fn incr(self: &Arc, aggregation_context:&NodeAggregationContext) { + let mut guard = self.inner.lock(); + guard.value += 10000; + let prepared = + guard.aggregation_node.apply_change(aggregation_context, Change { value:10000 }); + drop(guard); + prepared.apply(aggregation_context); + check_invariants(aggregation_context, once(NodeRef(self.clone()))); + } +} + +#[derive(Copy, Clone)] +struct Change { + value:i32, +} + +impl Change { + fn is_empty(&self) -> bool { self.value == 0 } +} + +struct NodeInner { + children:Vec>, + aggregation_node:AggregationNode, + value:u32, +} + +struct NodeAggregationContext<'a> { + additions:AtomicU32, + #[allow(dead_code)] + something_with_lifetime:&'a u32, + add_value:bool, +} + +#[derive(Clone, RefCast)] +#[repr(transparent)] +struct NodeRef(Arc); + +impl Debug for NodeRef { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "NodeRef({})", self.0.inner.lock().value) + } +} + +impl Hash for NodeRef { + fn hash(&self, state:&mut H) { Arc::as_ptr(&self.0).hash(state); } +} + +impl IsEnabled for NodeRef {} + +impl PartialEq for NodeRef { + fn eq(&self, other:&Self) -> bool { Arc::ptr_eq(&self.0, &other.0) } +} + +impl Eq for NodeRef {} + +struct NodeGuard { + guard:MutexGuard<'static, NodeInner>, + // This field is important to keep the node alive + #[allow(dead_code)] + node:Arc, +} + +impl NodeGuard { + unsafe fn new(guard:MutexGuard<'_, NodeInner>, node:Arc) -> Self { + NodeGuard { guard:unsafe { std::mem::transmute(guard) }, node } + } +} + +impl Deref for NodeGuard { + type Target = AggregationNode; + + fn deref(&self) -> &Self::Target { &self.guard.aggregation_node } +} + +impl DerefMut for NodeGuard { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.guard.aggregation_node } +} + +impl AggregationNodeGuard for NodeGuard { + type Data = Aggregated; + type DataChange = Change; + type NodeRef = NodeRef; + + type ChildrenIter<'a> = impl Iterator + 'a; + + fn children(&self) -> Self::ChildrenIter<'_> { + self.guard.children.iter().map(|child| NodeRef(child.clone())) + } + + fn get_remove_change(&self) -> Option { + let change = Change { value:-(self.guard.value as i32) }; + if change.is_empty() { None } else { Some(change) } + } + + fn get_add_change(&self) -> Option { + let change = Change { value:self.guard.value as i32 }; + if change.is_empty() { None } else { Some(change) } + } + + fn get_initial_data(&self) -> Self::Data { + Aggregated { value:self.guard.value as i32, active:false } + } +} + +impl<'a> AggregationContext for NodeAggregationContext<'a> { + type Data = Aggregated; + type DataChange = Change; + type Guard<'l> + = NodeGuard + where + Self: 'l; + type NodeRef = NodeRef; + + fn node<'b>(&'b self, reference:&Self::NodeRef) -> Self::Guard<'b> { + let r = reference.0.clone(); + let guard = reference.0.inner.lock(); + unsafe { NodeGuard::new(guard, r) } + } + + fn atomic_in_progress_counter<'l>(&self, id:&'l Self::NodeRef) -> &'l AtomicU32 + where + Self: 'l, { + &id.0.atomic + } + + fn apply_change(&self, data:&mut Aggregated, change:&Change) -> Option { + if data.value != 0 { + self.additions.fetch_add(1, Ordering::SeqCst); + } + if self.add_value { + data.value += change.value; + Some(*change) + } else { + None + } + } + + fn data_to_add_change(&self, data:&Self::Data) -> Option { + let change = Change { value:data.value }; + if change.is_empty() { None } else { Some(change) } + } + + fn data_to_remove_change(&self, data:&Self::Data) -> Option { + let change = Change { value:-data.value }; + if change.is_empty() { None } else { Some(change) } + } +} + +#[derive(Default)] +struct ActiveQuery { + active:bool, +} + +impl RootQuery for ActiveQuery { + type Data = Aggregated; + type Result = bool; + + fn query(&mut self, data:&Self::Data) -> ControlFlow<()> { + if data.active { + self.active = true; + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } + + fn result(self) -> Self::Result { self.active } +} + +#[derive(Default)] +struct Aggregated { + value:i32, + active:bool, +} + +#[test] +fn chain() { + let something_with_lifetime = 0; + let ctx = NodeAggregationContext { + additions:AtomicU32::new(0), + something_with_lifetime:&something_with_lifetime, + add_value:true, + }; + let root = Node::new(1); + let mut current = root.clone(); + for i in 2..=100 { + let node = Node::new(i); + current.add_child(&ctx, node.clone()); + current = node; + } + let leaf = Node::new(10000); + current.add_child(&ctx, leaf.clone()); + let current = NodeRef(root); + + { + let root_info = query_root_info(&ctx, ActiveQuery::default(), NodeRef(leaf.clone())); + assert!(!root_info); + } + + { + let aggregated = aggregation_data(&ctx, ¤t); + assert_eq!(aggregated.value, 15050); + } + assert_eq!(ctx.additions.load(Ordering::SeqCst), 122); + ctx.additions.store(0, Ordering::SeqCst); + check_invariants(&ctx, once(current.clone())); + + { + let root_info = query_root_info(&ctx, ActiveQuery::default(), NodeRef(leaf.clone())); + assert!(!root_info); + } + check_invariants(&ctx, once(current.clone())); + + leaf.incr(&ctx); + // The change need to propagate through 2 aggregated nodes + assert_eq!(ctx.additions.load(Ordering::SeqCst), 2); + ctx.additions.store(0, Ordering::SeqCst); + + { + let mut aggregated = aggregation_data(&ctx, ¤t); + assert_eq!(aggregated.value, 25050); + aggregated.active = true; + } + assert_eq!(ctx.additions.load(Ordering::SeqCst), 0); + ctx.additions.store(0, Ordering::SeqCst); + + { + let root_info = query_root_info(&ctx, ActiveQuery::default(), NodeRef(leaf.clone())); + assert!(root_info); + } + + let i = 101; + let current = Node::new_with_children(&ctx, i, vec![current.0]); + let current = NodeRef(current); + + { + let aggregated = aggregation_data(&ctx, ¤t); + assert_eq!(aggregated.value, 25151); + } + // This should be way less the 100 to prove that we are reusing trees + assert_eq!(ctx.additions.load(Ordering::SeqCst), 1); + ctx.additions.store(0, Ordering::SeqCst); + + leaf.incr(&ctx); + // This should be less the 20 to prove that we are reusing trees + assert_eq!(ctx.additions.load(Ordering::SeqCst), 3); + ctx.additions.store(0, Ordering::SeqCst); + + { + let root_info = query_root_info(&ctx, ActiveQuery::default(), NodeRef(leaf.clone())); + assert!(root_info); + } + + print(&ctx, ¤t, true); + check_invariants(&ctx, once(current.clone())); +} + +#[test] +fn chain_double_connected() { + let something_with_lifetime = 0; + let ctx = NodeAggregationContext { + additions:AtomicU32::new(0), + something_with_lifetime:&something_with_lifetime, + add_value:true, + }; + let root = Node::new(1); + let mut nodes = vec![root.clone()]; + let mut current = root.clone(); + let mut current2 = Node::new(2); + current.add_child(&ctx, current2.clone()); + nodes.push(current2.clone()); + for i in 3..=100 { + let node = Node::new(i); + nodes.push(node.clone()); + current.add_child(&ctx, node.clone()); + current2.add_child(&ctx, node.clone()); + current = current2; + current2 = node; + } + let current = NodeRef(root); + + { + let aggregated = aggregation_data(&ctx, ¤t); + assert_eq!(aggregated.value, 13188); + } + check_invariants(&ctx, once(current.clone())); + assert_eq!(ctx.additions.load(Ordering::SeqCst), 285); + ctx.additions.store(0, Ordering::SeqCst); + + print(&ctx, ¤t, true); + + for i in 2..nodes.len() { + nodes[i - 2].remove_child(&ctx, &nodes[i]); + nodes[i - 1].remove_child(&ctx, &nodes[i]); + } + nodes[0].remove_child(&ctx, &nodes[1]); + + { + let aggregated = aggregation_data(&ctx, ¤t); + assert_eq!(aggregated.value, 1); + } +} + +const RECT_SIZE:usize = 30; +const RECT_MULT:usize = 100; + +#[test] +fn rectangle_tree() { + let something_with_lifetime = 0; + let ctx = NodeAggregationContext { + additions:AtomicU32::new(0), + something_with_lifetime:&something_with_lifetime, + add_value:false, + }; + let mut nodes:Vec>> = Vec::new(); + let mut extra_nodes = Vec::new(); + for y in 0..RECT_SIZE { + let mut line:Vec> = Vec::new(); + for x in 0..RECT_SIZE { + let mut parents = Vec::new(); + if x > 0 { + parents.push(line[x - 1].clone()); + } + if y > 0 { + parents.push(nodes[y - 1][x].clone()); + } + let value = (x + y * RECT_MULT) as u32; + let node = Node::new(value); + if x == 0 || y == 0 { + let extra_node = Node::new(value + 100000); + prepare_aggregation_data(&ctx, &NodeRef(extra_node.clone())); + extra_node.add_child(&ctx, node.clone()); + extra_nodes.push(extra_node); + prepare_aggregation_data(&ctx, &NodeRef(node.clone())); + } + for parent in parents { + parent.add_child_unchecked(&ctx, node.clone()); + } + if x == 0 || y == 0 { + prepare_aggregation_data(&ctx, &NodeRef(node.clone())); + } + line.push(node); + } + nodes.push(line); + } + + check_invariants(&ctx, extra_nodes.iter().cloned().map(NodeRef)); + + let root = NodeRef(extra_nodes[0].clone()); + print(&ctx, &root, false); +} + +#[rstest] +#[case::many_roots_initial(100000, 0, 2, 1)] +#[case::many_roots_later(1, 100000, 2, 1)] +#[case::many_roots_later2(0, 100000, 2, 1)] +#[case::many_roots(50000, 50000, 2, 1)] +#[case::many_children(2, 0, 100000, 1)] +#[case::many_roots_and_children(5000, 5000, 10000, 1)] +#[case::many_roots_and_subgraph(5000, 5000, 100, 2)] +#[case::large_subgraph_a(9, 1, 10, 5)] +#[case::large_subgraph_b(5, 5, 10, 5)] +#[case::large_subgraph_c(1, 9, 10, 5)] +#[case::large_subgraph_d(6, 0, 10, 5)] +#[case::large_subgraph_e(0, 10, 10, 5)] +#[case::many_roots_large_subgraph(5000, 5000, 10, 5)] +fn performance( + #[case] initial_root_count:u32, + #[case] additional_root_count:u32, + #[case] children_count:u32, + #[case] children_layers_count:u32, +) { + fn print_aggregation_numbers(node:Arc) { + print!("Aggregation numbers "); + let mut current = node.clone(); + loop { + let guard = current.inner.lock(); + let n = guard.aggregation_node.aggregation_number(); + let f = guard.aggregation_node.followers().map_or(0, |f| f.len()); + let u = guard.aggregation_node.uppers().len(); + print!(" -> {} [{}U {}F]", n, u, f); + if guard.children.is_empty() { + break; + } + let child = guard.children[guard.children.len() / 2].clone(); + drop(guard); + current = child; + } + println!(); + } + + let something_with_lifetime = 0; + let ctx = NodeAggregationContext { + additions:AtomicU32::new(0), + something_with_lifetime:&something_with_lifetime, + add_value:false, + }; + let mut roots:Vec> = Vec::new(); + let inner_node = Node::new(0); + // Setup + for i in 0..initial_root_count { + let node = Node::new(2 + i); + roots.push(node.clone()); + aggregation_data(&ctx, &NodeRef(node.clone())).active = true; + node.add_child_unchecked(&ctx, inner_node.clone()); + } + let start = Instant::now(); + let mut children = vec![inner_node.clone()]; + for j in 0..children_layers_count { + let mut new_children = Vec::new(); + for child in children { + for i in 0..children_count { + let node = Node::new(1000000 * (j + 1) + i); + new_children.push(node.clone()); + child.add_child_unchecked(&ctx, node.clone()); + } + } + children = new_children; + } + println!("Setup children: {:?}", start.elapsed()); + + print_aggregation_numbers(inner_node.clone()); + + let start = Instant::now(); + for i in 0..additional_root_count { + let node = Node::new(2 + i); + roots.push(node.clone()); + aggregation_data(&ctx, &NodeRef(node.clone())).active = true; + node.add_child_unchecked(&ctx, inner_node.clone()); + } + println!("Setup additional roots: {:?}", start.elapsed()); + + print_aggregation_numbers(inner_node.clone()); + + // Add another root + let start = Instant::now(); + { + let node = Node::new(1); + roots.push(node.clone()); + aggregation_data(&ctx, &NodeRef(node.clone())).active = true; + node.add_child_unchecked(&ctx, inner_node.clone()); + } + let root_duration = start.elapsed(); + println!("Root: {:?}", root_duration); + + // Add another child + let start = Instant::now(); + { + let node = Node::new(999999); + inner_node.add_child_unchecked(&ctx, node.clone()); + } + let child_duration = start.elapsed(); + println!("Child: {:?}", child_duration); + + print_aggregation_numbers(inner_node.clone()); + + assert!(root_duration.as_micros() < 10000); + assert!(child_duration.as_micros() < 10000); + + // check_invariants(&ctx, roots.iter().cloned().map(NodeRef)); +} + +#[test] +fn many_children() { + let something_with_lifetime = 0; + let ctx = NodeAggregationContext { + additions:AtomicU32::new(0), + something_with_lifetime:&something_with_lifetime, + add_value:false, + }; + let mut roots:Vec> = Vec::new(); + let mut children:Vec> = Vec::new(); + const CHILDREN:u32 = 100000; + const ROOTS:u32 = 3; + let inner_node = Node::new(0); + let start = Instant::now(); + for i in 0..ROOTS { + let node = Node::new(10000 + i); + roots.push(node.clone()); + aggregation_data(&ctx, &NodeRef(node.clone())).active = true; + node.add_child_unchecked(&ctx, inner_node.clone()); + } + println!("Roots: {:?}", start.elapsed()); + let start = Instant::now(); + for i in 0..CHILDREN { + let node = Node::new(20000 + i); + children.push(node.clone()); + inner_node.add_child_unchecked(&ctx, node.clone()); + } + println!("Children: {:?}", start.elapsed()); + let start = Instant::now(); + for i in 0..CHILDREN { + let node = Node::new(40000 + i); + children.push(node.clone()); + inner_node.add_child_unchecked(&ctx, node.clone()); + } + let children_duration = start.elapsed(); + println!("Children: {:?}", children_duration); + for j in 0.. { + let start = Instant::now(); + for i in 0..CHILDREN { + let node = Node::new(50000 + j * 10000 + i); + children.push(node.clone()); + inner_node.add_child_unchecked(&ctx, node.clone()); + } + let dur = start.elapsed(); + println!("Children: {:?}", dur); + let is_slow = dur > children_duration * 2; + if j > 10 && !is_slow { + break; + } + if j > 20 { + panic!("Adding children has become slower over time"); + } + } + + let start = Instant::now(); + for i in 0..ROOTS { + let node = Node::new(30000 + i); + roots.push(node.clone()); + aggregation_data(&ctx, &NodeRef(node.clone())).active = true; + node.add_child_unchecked(&ctx, inner_node.clone()); + } + println!("Roots: {:?}", start.elapsed()); + + check_invariants(&ctx, roots.iter().cloned().map(NodeRef)); + + // let root = NodeRef(roots[0].clone()); + // print(&ctx, &root, false); +} + +#[test] +fn concurrent_modification() { + let something_with_lifetime = 0; + let ctx = NodeAggregationContext { + additions:AtomicU32::new(0), + something_with_lifetime:&something_with_lifetime, + add_value:true, + }; + let root1 = Node::new(1); + let root2 = Node::new(2); + let helper = Node::new(3); + let inner_node = Node::new(10); + let outer_node1 = Node::new(11); + let outer_node2 = Node::new(12); + let outer_node3 = Node::new(13); + let outer_node4 = Node::new(14); + inner_node.add_child(&ctx, outer_node1.clone()); + inner_node.add_child(&ctx, outer_node2.clone()); + root2.add_child(&ctx, helper.clone()); + outer_node1.prepare_aggregation_number(&ctx, 7).apply(&ctx); + outer_node3.prepare_aggregation_number(&ctx, 7).apply(&ctx); + root1.prepare_aggregation_number(&ctx, 8).apply(&ctx); + root2.prepare_aggregation_number(&ctx, 4).apply(&ctx); + helper.prepare_aggregation_number(&ctx, 3).apply(&ctx); + + let add_job1 = root1.prepare_add_child(&ctx, inner_node.clone()); + let add_job2 = inner_node.prepare_add_child(&ctx, outer_node3.clone()); + let add_job3 = inner_node.prepare_add_child(&ctx, outer_node4.clone()); + let add_job4 = helper.prepare_add_child(&ctx, inner_node.clone()); + + add_job4.apply(&ctx); + print_all(&ctx, [root1.clone(), root2.clone()].map(NodeRef), true); + add_job3.apply(&ctx); + print_all(&ctx, [root1.clone(), root2.clone()].map(NodeRef), true); + add_job2.apply(&ctx); + print_all(&ctx, [root1.clone(), root2.clone()].map(NodeRef), true); + add_job1.apply(&ctx); + + print_all(&ctx, [root1.clone(), root2.clone()].map(NodeRef), true); + + check_invariants(&ctx, [root1, root2].map(NodeRef)); +} + +#[test] +fn fuzzy_new() { + for size in [10, 50, 100, 200, 1000] { + for _ in 0..100 { + let seed = rand::random(); + println!("Seed {} Size {}", seed, size); + fuzzy(seed, size); + } + } +} + +#[rstest] +#[case::a(4059591975, 10)] +#[case::b(603692396, 100)] +#[case::c(3317876847, 10)] +#[case::d(4012518846, 50)] +fn fuzzy(#[case] seed:u32, #[case] count:u32) { + let something_with_lifetime = 0; + let ctx = NodeAggregationContext { + additions:AtomicU32::new(0), + something_with_lifetime:&something_with_lifetime, + add_value:true, + }; + + let mut seed_buffer = [0; 32]; + seed_buffer[0..4].copy_from_slice(&seed.to_be_bytes()); + let mut r = SmallRng::from_seed(seed_buffer); + let mut nodes = Vec::new(); + for i in 0..count { + nodes.push(Node::new(i)); + } + prepare_aggregation_data(&ctx, &NodeRef(nodes[0].clone())); + + let mut edges = IndexSet::new(); + + for _ in 0..1000 { + match r.gen_range(0..=2) { + 0 | 1 => { + // if x == 47 { + // print_all(&ctx, nodes.iter().cloned().map(NodeRef), true); + // } + // add edge + let parent = r.gen_range(0..nodes.len() - 1); + let child = r.gen_range(parent + 1..nodes.len()); + // println!("add edge {} -> {}", parent, child); + if edges.insert((parent, child)) { + nodes[parent].add_child(&ctx, nodes[child].clone()); + } + }, + 2 => { + // remove edge + if edges.is_empty() { + continue; + } + let i = r.gen_range(0..edges.len()); + let (parent, child) = edges.swap_remove_index(i).unwrap(); + // println!("remove edge {} -> {}", parent, child); + nodes[parent].remove_child(&ctx, &nodes[child]); + }, + _ => unreachable!(), + } + } + + for (parent, child) in edges { + nodes[parent].remove_child(&ctx, &nodes[child]); + } + + assert_eq!(aggregation_data(&ctx, &NodeRef(nodes[0].clone())).value, 0); + + check_invariants(&ctx, nodes.iter().cloned().map(NodeRef)); + + for node in nodes { + let lock = node.inner.lock(); + if let AggregationNode::Aggegating(a) = &lock.aggregation_node { + assert_eq!(a.data.value, lock.value as i32); + } + } +} + +fn print(aggregation_context:&NodeAggregationContext<'_>, root:&NodeRef, show_internal:bool) { + print_all(aggregation_context, once(root.clone()), show_internal); +} + +fn print_all( + aggregation_context:&NodeAggregationContext<'_>, + nodes:impl IntoIterator, + show_internal:bool, +) { + println!("digraph {{"); + print_graph(aggregation_context, nodes, show_internal, |item| { + let lock = item.0.inner.lock(); + if let AggregationNode::Aggegating(a) = &lock.aggregation_node { + format!("#{} [{}]", lock.value, a.data.value) + } else { + format!("#{}", lock.value) + } + }); + println!("\n}}"); +} diff --git a/crates/turbo-tasks-memory/Source/aggregation/uppers.rs b/crates/turbo-tasks-memory/Source/aggregation/uppers.rs new file mode 100644 index 0000000000000..0e8595fb874d6 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/aggregation/uppers.rs @@ -0,0 +1,233 @@ +use super::{ + AggegatingNode, + AggregationContext, + AggregationNode, + AggregationNodeGuard, + PreparedInternalOperation, + PreparedOperation, + StackVec, + balance_queue::BalanceQueue, + in_progress::start_in_progress_count, + optimize::{MAX_UPPERS, optimize_aggregation_number_for_uppers}, +}; +use crate::count_hash_set::RemovePositiveCountResult; + +/// Adds an upper node to a node. Returns the number of affected nodes by this +/// operation. This will also propagate the followers to the new upper node. +pub fn add_upper( + ctx:&C, + balance_queue:&mut BalanceQueue, + node:C::Guard<'_>, + node_id:&C::NodeRef, + upper_id:&C::NodeRef, + already_optimizing_for_upper:bool, +) -> usize { + add_upper_count(ctx, balance_queue, node, node_id, upper_id, 1, already_optimizing_for_upper) + .affected_nodes +} + +pub struct AddUpperCountResult { + pub new_count:isize, + pub affected_nodes:usize, +} + +/// Adds an upper node to a node with a given count. Returns the new count of +/// the upper node and the number of affected nodes by this operation. This will +/// also propagate the followers to the new upper node. +pub fn add_upper_count( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + node_id:&C::NodeRef, + upper_id:&C::NodeRef, + count:usize, + already_optimizing_for_upper:bool, +) -> AddUpperCountResult { + // TODO add_clonable_count could return the current count for better performance + let (added, count) = match &mut *node { + AggregationNode::Leaf { uppers, .. } => { + if uppers.add_clonable_count(upper_id, count) { + let count = uppers.get_count(upper_id); + (true, count) + } else { + (false, uppers.get_count(upper_id)) + } + }, + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { ref mut uppers, .. } = **aggegating; + if uppers.add_clonable_count(upper_id, count) { + let count = uppers.get_count(upper_id); + (true, count) + } else { + (false, uppers.get_count(upper_id)) + } + }, + }; + let mut affected_nodes = 0; + if added { + affected_nodes = + on_added(ctx, balance_queue, node, node_id, upper_id, already_optimizing_for_upper); + } else { + drop(node); + } + AddUpperCountResult { new_count:count, affected_nodes } +} + +/// Called when an upper node was added to a node. This will propagate the +/// followers to the new upper node. +pub fn on_added( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + node_id:&C::NodeRef, + upper_id:&C::NodeRef, + already_optimizing_for_upper:bool, +) -> usize { + let uppers = node.uppers(); + let uppers_len = uppers.len(); + let optimize = (!already_optimizing_for_upper + && uppers_len > MAX_UPPERS + && (uppers_len - MAX_UPPERS).count_ones() == 1) + .then(|| (true, uppers.iter().cloned().collect::>())); + let (add_change, followers) = match &mut *node { + AggregationNode::Leaf { .. } => { + let add_change = node.get_add_change(); + let children = node.children().collect::>(); + start_in_progress_count(ctx, upper_id, children.len() as u32); + drop(node); + (add_change, children) + }, + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { ref followers, .. } = **aggegating; + let add_change = ctx.data_to_add_change(&aggegating.data); + let followers = followers.iter().cloned().collect::>(); + start_in_progress_count(ctx, upper_id, followers.len() as u32); + drop(node); + + (add_change, followers) + }, + }; + + let mut optimizing = false; + + // This heuristic ensures that we don’t have too many upper edges, which would + // degrade update performance + if let Some((leaf, uppers)) = optimize { + optimizing = + optimize_aggregation_number_for_uppers(ctx, balance_queue, node_id, leaf, uppers); + } + + let mut affected_nodes = 0; + + // Make sure to propagate the change to the upper node + let mut upper = ctx.node(upper_id); + let add_prepared = add_change.and_then(|add_change| upper.apply_change(ctx, add_change)); + affected_nodes += followers.len(); + let prepared = followers + .into_iter() + .filter_map(|child_id| { + upper.notify_new_follower(ctx, balance_queue, upper_id, &child_id, optimizing) + }) + .collect::>(); + drop(upper); + add_prepared.apply(ctx); + for prepared in prepared { + affected_nodes += prepared.apply(ctx, balance_queue); + } + + affected_nodes +} + +/// Removes an upper node from a node with a count. +pub fn remove_upper_count( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + upper_id:&C::NodeRef, + count:usize, +) { + let removed = match &mut *node { + AggregationNode::Leaf { uppers, .. } => uppers.remove_clonable_count(upper_id, count), + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { ref mut uppers, .. } = **aggegating; + uppers.remove_clonable_count(upper_id, count) + }, + }; + if removed { + on_removed(ctx, balance_queue, node, upper_id); + } +} + +pub struct RemovePositiveUpperCountResult { + pub removed_count:usize, + pub remaining_count:isize, +} + +/// Removes a positive count of an upper node from a node. +/// Returns the removed count and the remaining count of the upper node. +/// This will also propagate the followers to the removed upper node. +pub fn remove_positive_upper_count( + ctx:&C, + balance_queue:&mut BalanceQueue, + mut node:C::Guard<'_>, + upper_id:&C::NodeRef, + count:usize, +) -> RemovePositiveUpperCountResult { + let RemovePositiveCountResult { removed, removed_count, count } = match &mut *node { + AggregationNode::Leaf { uppers, .. } => { + uppers.remove_positive_clonable_count(upper_id, count) + }, + AggregationNode::Aggegating(aggegating) => { + let AggegatingNode { ref mut uppers, .. } = **aggegating; + uppers.remove_positive_clonable_count(upper_id, count) + }, + }; + if removed { + on_removed(ctx, balance_queue, node, upper_id); + } + RemovePositiveUpperCountResult { removed_count, remaining_count:count } +} + +/// Called when an upper node was removed from a node. This will propagate the +/// followers to the removed upper node. +pub fn on_removed( + ctx:&C, + balance_queue:&mut BalanceQueue, + node:C::Guard<'_>, + upper_id:&C::NodeRef, +) { + match &*node { + AggregationNode::Leaf { .. } => { + let remove_change = node.get_remove_change(); + let children = node.children().collect::>(); + drop(node); + let mut upper = ctx.node(upper_id); + let remove_prepared = + remove_change.and_then(|remove_change| upper.apply_change(ctx, remove_change)); + start_in_progress_count(ctx, upper_id, children.len() as u32); + let prepared = children + .into_iter() + .map(|child_id| upper.notify_lost_follower(ctx, balance_queue, upper_id, &child_id)) + .collect::>(); + drop(upper); + remove_prepared.apply(ctx); + prepared.apply(ctx, balance_queue); + }, + AggregationNode::Aggegating(aggegating) => { + let remove_change = ctx.data_to_remove_change(&aggegating.data); + let followers = aggegating.followers.iter().cloned().collect::>(); + drop(node); + let mut upper = ctx.node(upper_id); + let remove_prepared = + remove_change.and_then(|remove_change| upper.apply_change(ctx, remove_change)); + start_in_progress_count(ctx, upper_id, followers.len() as u32); + let prepared = followers + .into_iter() + .map(|child_id| upper.notify_lost_follower(ctx, balance_queue, upper_id, &child_id)) + .collect::>(); + drop(upper); + remove_prepared.apply(ctx); + prepared.apply(ctx, balance_queue); + }, + } +} diff --git a/crates/turbo-tasks-memory/Source/cell.rs b/crates/turbo-tasks-memory/Source/cell.rs new file mode 100644 index 0000000000000..ec518c564e5c7 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/cell.rs @@ -0,0 +1,231 @@ +use std::{ + fmt::Debug, + mem::{replace, take}, +}; + +use auto_hash_map::AutoSet; +use turbo_tasks::{ + TaskId, + TaskIdSet, + TurboTasksBackendApi, + backend::CellContent, + event::{Event, EventListener}, +}; + +use crate::MemoryBackend; + +#[derive(Default, Debug)] +pub(crate) enum Cell { + /// No content has been set yet, or it was removed for memory pressure + /// reasons. + /// Assigning a value will transition to the Value state. + /// Reading this cell will transition to the Recomputing state. + #[default] + Empty, + /// The content has been removed for memory pressure reasons, but the + /// tracking is still active. Any update will invalidate dependent tasks. + /// Assigning a value will transition to the Value state. + /// Reading this cell will transition to the Recomputing state. + TrackedValueless { dependent_tasks:TaskIdSet }, + /// Someone wanted to read the content and it was not available. The content + /// is now being recomputed. + /// Assigning a value will transition to the Value state. + Recomputing { dependent_tasks:TaskIdSet, event:Event }, + /// The content was set only once and is tracked. + /// GC operation will transition to the TrackedValueless state. + Value { dependent_tasks:TaskIdSet, content:CellContent }, +} + +#[derive(Debug)] +pub struct RecomputingCell { + pub listener:EventListener, + pub schedule:bool, +} + +impl Cell { + /// Returns true if the cell has a value. + pub fn has_value(&self) -> bool { + match self { + Cell::Empty => false, + Cell::Recomputing { .. } => false, + Cell::TrackedValueless { .. } => false, + Cell::Value { .. } => true, + } + } + + /// Removes a task from the list of dependent tasks. + pub fn remove_dependent_task(&mut self, task:TaskId) { + match self { + Cell::Empty => {}, + Cell::Value { dependent_tasks, .. } + | Cell::TrackedValueless { dependent_tasks, .. } + | Cell::Recomputing { dependent_tasks, .. } => { + dependent_tasks.remove(&task); + }, + } + } + + /// Switch the cell to recomputing state. + fn recompute( + &mut self, + dependent_tasks:TaskIdSet, + description:impl Fn() -> String + Sync + Send + 'static, + note:impl Fn() -> String + Sync + Send + 'static, + ) -> EventListener { + let event = Event::new(move || (description)() + " -> Cell::Recomputing::event"); + let listener = event.listen_with_note(note); + *self = Cell::Recomputing { event, dependent_tasks }; + listener + } + + /// Read the content of the cell when avaiable. Registers the reader as + /// dependent task. Will trigger recomputation is no content is + /// available. + pub fn read_content( + &mut self, + reader:TaskId, + description:impl Fn() -> String + Sync + Send + 'static, + note:impl Fn() -> String + Sync + Send + 'static, + ) -> Result { + if let Cell::Value { content, dependent_tasks, .. } = self { + dependent_tasks.insert(reader); + return Ok(content.clone()); + } + // Same behavior for all other states, so we reuse the same code. + self.read_content_untracked(description, note) + } + + /// Read the content of the cell when avaiable. Does not register the reader + /// as dependent task. Will trigger recomputation is no content is + /// available. + /// + /// INVALIDATION: Be careful with this, it will not + /// track dependencies, so using it could break cache invalidation. + pub fn read_content_untracked( + &mut self, + description:impl Fn() -> String + Sync + Send + 'static, + note:impl Fn() -> String + Sync + Send + 'static, + ) -> Result { + match self { + Cell::Empty => { + let listener = self.recompute(AutoSet::default(), description, note); + Err(RecomputingCell { listener, schedule:true }) + }, + Cell::Recomputing { event, .. } => { + let listener = event.listen_with_note(note); + Err(RecomputingCell { listener, schedule:false }) + }, + &mut Cell::TrackedValueless { ref mut dependent_tasks } => { + let dependent_tasks = take(dependent_tasks); + let listener = self.recompute(dependent_tasks, description, note); + Err(RecomputingCell { listener, schedule:true }) + }, + Cell::Value { content, .. } => Ok(content.clone()), + } + } + + /// Read the content of the cell when avaiable. Does not register the reader + /// as dependent task. Will not start recomputing when content is not + /// available. + /// + /// INVALIDATION: Be careful with this, it will not track + /// dependencies, so using it could break cache invalidation. + pub fn read_own_content_untracked(&self) -> CellContent { + match self { + Cell::Empty | Cell::Recomputing { .. } | Cell::TrackedValueless { .. } => { + CellContent(None) + }, + Cell::Value { content, .. } => content.clone(), + } + } + + pub fn assign( + &mut self, + content:CellContent, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + match self { + Cell::Empty => { + *self = Cell::Value { content, dependent_tasks:AutoSet::default() }; + }, + &mut Cell::Recomputing { ref mut event, ref mut dependent_tasks } => { + event.notify(usize::MAX); + // Assigning to a cell will invalidate all dependent tasks as the content might + // have changed. + if !dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(dependent_tasks); + } + *self = Cell::Value { content, dependent_tasks:AutoSet::default() }; + }, + &mut Cell::TrackedValueless { ref mut dependent_tasks } => { + // Assigning to a cell will invalidate all dependent tasks as the content might + // have changed. + // TODO this leads to flagging task unnecessarily dirty when a GC'ed task is + // recomputed. We need to use the notification of changed cells for the current + // task to check if it's valid to skip the invalidation here + if !dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(dependent_tasks); + } + *self = Cell::Value { content, dependent_tasks:AutoSet::default() }; + }, + Cell::Value { content: ref mut cell_content, dependent_tasks } => { + if content != *cell_content { + if !dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(dependent_tasks); + dependent_tasks.clear(); + } + *cell_content = content; + } + }, + } + } + + /// Reduces memory needs to the minimum. + pub fn shrink_to_fit(&mut self) { + match self { + Cell::Empty => {}, + Cell::TrackedValueless { dependent_tasks, .. } + | Cell::Recomputing { dependent_tasks, .. } + | Cell::Value { dependent_tasks, .. } => { + dependent_tasks.shrink_to_fit(); + }, + } + } + + /// Takes the content out of the cell. Make sure to drop the content outside + /// of the task state lock. + #[must_use] + pub fn gc_content(&mut self) -> Option { + match self { + Cell::Empty | Cell::Recomputing { .. } | Cell::TrackedValueless { .. } => None, + Cell::Value { dependent_tasks, .. } => { + let dependent_tasks = take(dependent_tasks); + let Cell::Value { content, .. } = + replace(self, Cell::TrackedValueless { dependent_tasks }) + else { + unreachable!() + }; + Some(content) + }, + } + } + + /// Drops the cell after GC. Will notify all dependent tasks and events. + pub fn gc_drop(self, turbo_tasks:&dyn TurboTasksBackendApi) { + match self { + Cell::Empty => {}, + Cell::Recomputing { event, dependent_tasks, .. } => { + event.notify(usize::MAX); + if !dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(&dependent_tasks); + } + }, + Cell::TrackedValueless { dependent_tasks, .. } + | Cell::Value { dependent_tasks, .. } => { + if !dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(&dependent_tasks); + } + }, + } + } +} diff --git a/crates/turbo-tasks-memory/Source/count_hash_set.rs b/crates/turbo-tasks-memory/Source/count_hash_set.rs new file mode 100644 index 0000000000000..89a88d83c42af --- /dev/null +++ b/crates/turbo-tasks-memory/Source/count_hash_set.rs @@ -0,0 +1,469 @@ +use std::{ + borrow::Borrow, + cmp::Ordering, + collections::hash_map::RandomState, + fmt::{Debug, Formatter}, + hash::{BuildHasher, Hash}, + iter::FilterMap, +}; + +use auto_hash_map::{ + AutoMap, + map::{Entry, Iter, RawEntry}, +}; + +#[derive(Clone)] +pub struct CountHashSet { + inner:AutoMap, + negative_entries:usize, +} + +impl Debug for CountHashSet { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CountHashSet") + .field("inner", &self.inner) + .field("negative_entries", &self.negative_entries) + .finish() + } +} + +impl From<[T; N]> for CountHashSet { + fn from(list:[T; N]) -> Self { + let mut set = CountHashSet::default(); + for item in list { + set.add(item); + } + set + } +} + +impl Default for CountHashSet { + fn default() -> Self { Self { inner:Default::default(), negative_entries:0 } } +} + +impl FromIterator for CountHashSet { + fn from_iter>(iter:I) -> Self { + let mut set = CountHashSet::default(); + for item in iter { + set.add(item); + } + set + } +} + +impl CountHashSet { + pub fn new() -> Self { Self::default() } +} + +impl CountHashSet { + /// Get the number of positive entries + pub fn len(&self) -> usize { self.inner.len() - self.negative_entries } + + /// Checks if the set looks empty from outside. It might still have negative + /// entries, but they should be treated as not existing. + pub fn is_empty(&self) -> bool { self.len() == 0 } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum RemoveIfEntryResult { + PartiallyRemoved, + Removed, + NotPresent, +} + +pub struct RemovePositiveCountResult { + pub removed:bool, + pub removed_count:usize, + pub count:isize, +} + +impl CountHashSet { + /// Returns true, when the value has become visible from outside + pub fn add_count(&mut self, item:T, count:usize) -> bool { + if count == 0 { + return false; + } + match self.inner.entry(item) { + Entry::Occupied(mut e) => { + let value = e.get_mut(); + let old = *value; + *value += count as isize; + if old > 0 { + // it was positive before + false + } else if *value > 0 { + // it was negative and has become positive + self.negative_entries -= 1; + true + } else if *value == 0 { + // it was negative and has become zero + self.negative_entries -= 1; + e.remove(); + false + } else { + // it was and still is negative + false + } + }, + Entry::Vacant(e) => { + // it was zero and is now positive + e.insert(count as isize); + true + }, + } + } + + /// Returns true when the value has become visible from outside + pub fn add(&mut self, item:T) -> bool { self.add_count(item, 1) } + + /// Returns true, when the value has been added. Returns false, when the + /// value was not part of the set before (positive or negative). The + /// visibility from outside will never change due to this method. + pub fn add_if_entry(&mut self, item:&Q) -> bool + where + T: Borrow, + Q: Hash + Eq + ?Sized, { + match self.inner.raw_entry_mut(item) { + RawEntry::Occupied(mut e) => { + let value = e.get_mut(); + *value += 1; + if *value == 0 { + // it was negative and has become zero + self.negative_entries -= 1; + e.remove(); + } + true + }, + RawEntry::Vacant(_) => false, + } + } + + /// Removes an item if it is present. + pub fn remove_if_entry(&mut self, item:&T) -> RemoveIfEntryResult { + match self.inner.raw_entry_mut(item) { + RawEntry::Occupied(mut e) => { + let value = e.get_mut(); + if *value < 0 { + return RemoveIfEntryResult::NotPresent; + } + *value -= 1; + if *value == 0 { + // It was positive and has become zero + e.remove(); + RemoveIfEntryResult::Removed + } else { + RemoveIfEntryResult::PartiallyRemoved + } + }, + RawEntry::Vacant(_) => RemoveIfEntryResult::NotPresent, + } + } + + pub fn iter(&self) -> CountHashSetIter<'_, T> { + CountHashSetIter { + inner:self.inner.iter().filter_map(filter), + count:self.inner.len() - self.negative_entries, + } + } + + pub fn get_count(&self, item:&T) -> isize { + match self.inner.get(item) { + Some(value) => *value, + None => 0, + } + } +} + +impl CountHashSet { + /// Returns true, when the value has become visible from outside + pub fn add_clonable_count(&mut self, item:&T, count:usize) -> bool { + if count == 0 { + return false; + } + match self.inner.raw_entry_mut(item) { + RawEntry::Occupied(mut e) => { + let value = e.get_mut(); + let old = *value; + *value += count as isize; + if old > 0 { + // it was positive before + false + } else if *value > 0 { + // it was negative and has become positive + self.negative_entries -= 1; + true + } else if *value == 0 { + // it was negative and has become zero + self.negative_entries -= 1; + e.remove(); + false + } else { + // it was and still is negative + false + } + }, + RawEntry::Vacant(e) => { + // it was zero and is now positive + e.insert(item.clone(), count as isize); + true + }, + } + } + + /// Returns true when the value has become visible from outside + pub fn add_clonable(&mut self, item:&T) -> bool { self.add_clonable_count(item, 1) } + + /// Returns true when the value is no longer visible from outside + pub fn remove_clonable_count(&mut self, item:&T, count:usize) -> bool { + if count == 0 { + return false; + } + match self.inner.raw_entry_mut(item) { + RawEntry::Occupied(mut e) => { + let value = e.get_mut(); + let old = *value; + *value -= count as isize; + if *value > 0 { + // It was and still is positive + false + } else if *value == 0 { + // It was positive and has become zero + e.remove(); + true + } else if old > 0 { + // It was positive and is negative now + self.negative_entries += 1; + true + } else { + // It was and still is negative + false + } + }, + RawEntry::Vacant(e) => { + // It was zero and is negative now + e.insert(item.clone(), -(count as isize)); + self.negative_entries += 1; + false + }, + } + } + + /// Returns true when the value is no longer visible from outside + pub fn remove_positive_clonable_count( + &mut self, + item:&T, + count:usize, + ) -> RemovePositiveCountResult { + if count == 0 { + return RemovePositiveCountResult { + removed:false, + removed_count:0, + count:self.inner.get(item).copied().unwrap_or(0), + }; + } + match self.inner.raw_entry_mut(item) { + RawEntry::Occupied(mut e) => { + let value = e.get_mut(); + let old = *value; + match old.cmp(&(count as isize)) { + Ordering::Less => { + if old < 0 { + // It's already negative, can't remove anything + RemovePositiveCountResult { removed:false, removed_count:0, count:old } + } else { + // It's removed completely with count remaining + e.remove(); + RemovePositiveCountResult { + removed:true, + removed_count:old as usize, + count:0, + } + } + }, + Ordering::Equal => { + // It's perfectly removed + e.remove(); + RemovePositiveCountResult { removed:true, removed_count:count, count:0 } + }, + Ordering::Greater => { + // It's partially removed + *value -= count as isize; + RemovePositiveCountResult { + removed:false, + removed_count:count, + count:*value, + } + }, + } + }, + RawEntry::Vacant(_) => { + // It's not present + RemovePositiveCountResult { removed:false, removed_count:0, count:0 } + }, + } + } +} + +fn filter<'a, T>((k, v):(&'a T, &'a isize)) -> Option<&'a T> { if *v > 0 { Some(k) } else { None } } + +type InnerIter<'a, T> = + FilterMap, for<'b> fn((&'b T, &'b isize)) -> Option<&'b T>>; + +pub struct CountHashSetIter<'a, T> { + inner:InnerIter<'a, T>, + count:usize, +} + +impl<'a, T> Iterator for CountHashSetIter<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + self.count = self.count.saturating_sub(1); + self.inner.next() + } + + fn size_hint(&self) -> (usize, Option) { (self.count, Some(self.count)) } +} + +#[cfg(test)] +mod tests { + use nohash_hasher::BuildNoHashHasher; + + use super::*; + + #[test] + fn test_add_remove() { + let mut set:CountHashSet> = CountHashSet::new(); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(set.add(1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(!set.add(1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(set.add(2)); + assert_eq!(set.len(), 2); + assert!(!set.is_empty()); + + assert!(set.remove_clonable_count(&2, 2)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(!set.remove_clonable_count(&2, 1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(!set.remove_clonable_count(&1, 1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(set.remove_clonable_count(&1, 1)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(!set.add_count(2, 2)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert_eq!(format!("{:?}", set), "CountHashSet { inner: {}, negative_entries: 0 }"); + } + + #[test] + fn test_add_remove_cloneable() { + let mut set:CountHashSet> = CountHashSet::new(); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(set.add_clonable_count(&1, 1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(!set.add_clonable_count(&1, 1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(set.add_clonable_count(&2, 1)); + assert_eq!(set.len(), 2); + assert!(!set.is_empty()); + + assert!(set.remove_clonable_count(&2, 2)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(!set.remove_clonable_count(&2, 1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(!set.remove_clonable_count(&1, 1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert!(set.remove_clonable_count(&1, 1)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(!set.add_clonable_count(&2, 2)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert_eq!(format!("{:?}", set), "CountHashSet { inner: {}, negative_entries: 0 }"); + } + + #[test] + fn test_add_remove_if_entry() { + let mut set:CountHashSet> = CountHashSet::new(); + + assert!(!set.add_if_entry(&1)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(set.add(1)); + + assert!(set.add_if_entry(&1)); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert_eq!(set.remove_if_entry(&1), RemoveIfEntryResult::PartiallyRemoved); + assert_eq!(set.len(), 1); + assert!(!set.is_empty()); + + assert_eq!(set.remove_if_entry(&1), RemoveIfEntryResult::Removed); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert_eq!(set.remove_if_entry(&1), RemoveIfEntryResult::NotPresent); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + } + + #[test] + fn test_zero() { + let mut set:CountHashSet> = CountHashSet::new(); + + assert!(!set.add_count(1, 0)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(!set.remove_clonable_count(&1, 0)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(!set.add_clonable_count(&1, 0)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(!set.remove_clonable_count(&1, 0)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert!(!set.remove_clonable_count(&1, 1)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + + assert_eq!(set.remove_if_entry(&1), RemoveIfEntryResult::NotPresent); + } +} diff --git a/crates/turbo-tasks-memory/Source/gc.rs b/crates/turbo-tasks-memory/Source/gc.rs new file mode 100644 index 0000000000000..00ee37d298a3b --- /dev/null +++ b/crates/turbo-tasks-memory/Source/gc.rs @@ -0,0 +1,240 @@ +use std::{ + cmp::{Reverse, max}, + collections::VecDeque, + fmt::Debug, + mem::take, + sync::atomic::{AtomicU32, AtomicUsize, Ordering}, + time::Duration, +}; + +use concurrent_queue::ConcurrentQueue; +use parking_lot::Mutex; +use tracing::field::{Empty, debug}; +use turbo_tasks::TaskId; + +use crate::MemoryBackend; + +/// The priority of a task for garbage collection. +/// Any action will shrink the internal memory structures of the task in a +/// transparent way. +#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] +pub struct GcPriority { + // Memory usage divided by compute duration. Specifies how efficient garbage collection would + // be with this task. Higher memory usage and lower compute duration makes it more likely to be + // garbage collected. + memory_per_time:u16, +} + +/// State about garbage collection for a task. +#[derive(Clone, Copy, Debug, Default)] +pub struct GcTaskState { + pub priority:GcPriority, + /// The generation where the task was last accessed. + pub generation:u32, +} + +impl GcTaskState { + pub(crate) fn execution_completed( + &mut self, + duration:Duration, + memory_usage:usize, + generation:u32, + ) { + self.generation = generation; + self.priority = GcPriority { + memory_per_time:((memory_usage + TASK_BASE_MEMORY_USAGE) as u64 + / (duration.as_micros() as u64 + TASK_BASE_COMPUTE_DURATION_IN_MICROS)) + .try_into() + .unwrap_or(u16::MAX), + }; + } + + pub(crate) fn on_read(&mut self, generation:u32) -> bool { + if self.generation < generation { + self.generation = generation; + true + } else { + false + } + } +} + +const TASKS_PER_NEW_GENERATION:usize = 100_000; +const MAX_TASKS_PER_OLD_GENERATION:usize = 200_000; +const PERCENTAGE_TO_COLLECT:usize = 30; +const TASK_BASE_MEMORY_USAGE:usize = 1_000; +const TASK_BASE_COMPUTE_DURATION_IN_MICROS:u64 = 1_000; +pub const PERCENTAGE_TARGET_MEMORY:usize = 88; +pub const PERCENTAGE_IDLE_TARGET_MEMORY:usize = 75; + +struct OldGeneration { + tasks:Vec, + generation:u32, +} + +struct ProcessGenerationResult { + priority:Option, + count:usize, +} + +/// The queue of actions that garbage collection should perform. +pub struct GcQueue { + /// The current generation number. + generation:AtomicU32, + /// Fresh or read tasks that should added to the queue. + incoming_tasks:ConcurrentQueue, + /// Number of tasks in `incoming_tasks`. + incoming_tasks_count:AtomicUsize, + /// Tasks from old generations. The oldest generation will be garbage + /// collected next. + generations:Mutex>, +} + +impl GcQueue { + pub fn new() -> Self { + Self { + generation:AtomicU32::new(0), + incoming_tasks:ConcurrentQueue::unbounded(), + incoming_tasks_count:AtomicUsize::new(0), + generations:Mutex::new(VecDeque::with_capacity(128)), + } + } + + /// Get the current generation number. + pub fn generation(&self) -> u32 { self.generation.load(Ordering::Relaxed) } + + /// Notify the GC queue that a task has been executed. + pub fn task_executed(&self, task:TaskId) -> u32 { self.add_task(task) } + + /// Notify the GC queue that a task has been accessed. + pub fn task_accessed(&self, task:TaskId) -> u32 { self.add_task(task) } + + fn add_task(&self, task:TaskId) -> u32 { + let _ = self.incoming_tasks.push(task); + if self.incoming_tasks_count.fetch_add(1, Ordering::Acquire) % TASKS_PER_NEW_GENERATION + == TASKS_PER_NEW_GENERATION - 1 + { + self.incoming_tasks_count.fetch_sub(TASKS_PER_NEW_GENERATION, Ordering::Release); + // We are selected to move TASKS_PER_NEW_GENERATION tasks into a generation + let gen = self.generation.fetch_add(1, Ordering::Relaxed); + let mut tasks = Vec::with_capacity(TASKS_PER_NEW_GENERATION); + for _ in 0..TASKS_PER_NEW_GENERATION { + match self.incoming_tasks.pop() { + Ok(task) => { + tasks.push(task); + }, + Err(_) => { + // That will not happen, since we only pop the same amount as we have + // pushed. + unreachable!(); + }, + } + } + self.generations.lock().push_front(OldGeneration { tasks, generation:gen }); + gen + } else { + self.generation.load(Ordering::Relaxed) + } + } + + fn process_old_generation(&self, backend:&MemoryBackend) -> ProcessGenerationResult { + let old_generation = { + let guard = &mut self.generations.lock(); + guard.pop_back() + }; + let Some(OldGeneration { mut tasks, generation }) = old_generation else { + // No old generation to process + return ProcessGenerationResult { priority:None, count:0 }; + }; + // Check all tasks for the correct generation + let mut indices = Vec::with_capacity(tasks.len()); + assert!(tasks.len() <= MAX_TASKS_PER_OLD_GENERATION); + for (i, task) in tasks.iter().enumerate() { + backend.with_task(*task, |task| { + if let Some(state) = task.gc_state() { + if state.generation <= generation { + indices.push((Reverse(state.priority), i as u32)); + } + } + }); + } + + if indices.is_empty() { + // No valid tasks in old generation to process + return ProcessGenerationResult { priority:None, count:0 }; + } + + // Sorting based on sort_by_cached_key from std lib + indices.sort_unstable(); + for i in 0..indices.len() { + let mut index = indices[i].1; + while (index as usize) < i { + index = indices[index as usize].1; + } + indices[i].1 = index; + tasks.swap(i, index as usize); + } + tasks.truncate(indices.len()); + + let tasks_to_collect = max(1, tasks.len() * PERCENTAGE_TO_COLLECT / 100); + let (Reverse(max_priority), _) = indices[0]; + drop(indices); + + // Put back remaining tasks into the queue + let remaining_tasks = &tasks[tasks_to_collect..]; + { + let mut guard = self.generations.lock(); + if !remaining_tasks.is_empty() { + if let Some(first) = guard.front_mut() { + first.tasks.extend(remaining_tasks); + if first.tasks.len() > MAX_TASKS_PER_OLD_GENERATION { + // Need to split the tasks into two generations + let mut gen_b = Vec::with_capacity(first.tasks.len() / 2); + let mut gen_a = Vec::with_capacity(first.tasks.len() - gen_b.capacity()); + for (i, task) in take(&mut first.tasks).into_iter().enumerate() { + if i % 2 == 0 { + gen_a.push(task); + } else { + gen_b.push(task); + } + } + let generation = first.generation; + first.tasks = gen_a; + guard.push_front(OldGeneration { tasks:gen_b, generation }); + } + } else { + guard.push_front(OldGeneration { tasks:remaining_tasks.to_vec(), generation }); + } + } + } + + // GC the tasks + let mut count = 0; + for task in tasks[..tasks_to_collect].iter() { + backend.with_task(*task, |task| { + if task.run_gc(generation) { + count += 1; + } + }); + } + + ProcessGenerationResult { priority:Some(max_priority), count } + } + + /// Run garbage collection on the queue. + pub fn run_gc(&self, backend:&MemoryBackend) -> Option<(GcPriority, usize)> { + let span = + tracing::trace_span!("garbage collection", priority = Empty, count = Empty).entered(); + + let ProcessGenerationResult { priority, count } = self.process_old_generation(backend); + + span.record("count", count); + if let Some(priority) = &priority { + span.record("priority", debug(priority)); + } else { + span.record("priority", ""); + } + + priority.map(|p| (p, count)) + } +} diff --git a/crates/turbo-tasks-memory/Source/lib.rs b/crates/turbo-tasks-memory/Source/lib.rs new file mode 100644 index 0000000000000..25a0536212132 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/lib.rs @@ -0,0 +1,21 @@ +#![feature(hash_extract_if)] +#![feature(option_get_or_insert_default)] +#![feature(type_alias_impl_trait)] +#![feature(lint_reasons)] +#![feature(box_patterns)] +#![feature(int_roundings)] +#![feature(impl_trait_in_assoc_type)] +#![deny(unsafe_op_in_unsafe_fn)] + +mod aggregation; +mod cell; +mod count_hash_set; +mod gc; +mod map_guard; +mod memory_backend; +mod memory_backend_with_pg; +mod output; +mod task; + +pub use memory_backend::MemoryBackend; +pub use memory_backend_with_pg::MemoryBackendWithPersistedGraph; diff --git a/crates/turbo-tasks-memory/Source/map_guard.rs b/crates/turbo-tasks-memory/Source/map_guard.rs new file mode 100644 index 0000000000000..da6e989565e54 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/map_guard.rs @@ -0,0 +1,54 @@ +use std::ops::{Deref, DerefMut}; + +use parking_lot::{RwLockReadGuard, RwLockWriteGuard}; + +pub struct ReadGuard<'a, T:'a, U:'a, M:'a + Fn(&T) -> Option<&U>> { + inner:RwLockReadGuard<'a, T>, + map:M, +} + +impl<'a, T:'a, U:'a, M:'a + Fn(&T) -> Option<&U>> ReadGuard<'a, T, U, M> { + pub fn new(guard:RwLockReadGuard<'a, T>, map:M) -> Self { Self { inner:guard, map } } +} + +impl<'a, T:'a, U:'a, M:'a + Fn(&T) -> Option<&U>> Deref for ReadGuard<'a, T, U, M> { + type Target = U; + + fn deref(&self) -> &Self::Target { (self.map)(&self.inner).unwrap() } +} + +pub struct WriteGuard< + 'a, + T:'a, + U:'a, + M:'a + Fn(&T) -> Option<&U>, + MM:'a + Fn(&mut T) -> Option<&mut U>, +> { + inner:RwLockWriteGuard<'a, T>, + map:M, + map_mut:MM, +} + +impl<'a, T:'a, U:'a, M:'a + Fn(&T) -> Option<&U>, MM:'a + Fn(&mut T) -> Option<&mut U>> + WriteGuard<'a, T, U, M, MM> +{ + pub fn new(guard:RwLockWriteGuard<'a, T>, map:M, map_mut:MM) -> Self { + Self { inner:guard, map, map_mut } + } + + pub fn into_inner(self) -> RwLockWriteGuard<'a, T> { self.inner } +} + +impl<'a, T:'a, U:'a, M:'a + Fn(&T) -> Option<&U>, MM:'a + Fn(&mut T) -> Option<&mut U>> Deref + for WriteGuard<'a, T, U, M, MM> +{ + type Target = U; + + fn deref(&self) -> &Self::Target { (self.map)(&self.inner).unwrap() } +} + +impl<'a, T:'a, U:'a, M:'a + Fn(&T) -> Option<&U>, MM:'a + Fn(&mut T) -> Option<&mut U>> DerefMut + for WriteGuard<'a, T, U, M, MM> +{ + fn deref_mut(&mut self) -> &mut Self::Target { (self.map_mut)(&mut self.inner).unwrap() } +} diff --git a/crates/turbo-tasks-memory/Source/memory_backend.rs b/crates/turbo-tasks-memory/Source/memory_backend.rs new file mode 100644 index 0000000000000..6460f106a86b2 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/memory_backend.rs @@ -0,0 +1,623 @@ +use std::{ + borrow::{Borrow, Cow}, + cell::RefCell, + future::Future, + hash::{BuildHasher, BuildHasherDefault, Hash}, + pin::Pin, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, + time::Duration, +}; + +use anyhow::{Result, bail}; +use auto_hash_map::AutoMap; +use dashmap::{DashMap, mapref::entry::Entry}; +use rustc_hash::FxHasher; +use tokio::task::futures::TaskLocalFuture; +use tracing::trace_span; +use turbo_prehash::{BuildHasherExt, PassThroughHash, PreHashed}; +use turbo_tasks::{ + CellId, + RawVc, + TaskId, + TaskIdSet, + TraitTypeId, + TurboTasksBackendApi, + Unused, + backend::{ + Backend, + BackendJobId, + CellContent, + PersistentTaskType, + TaskExecutionSpec, + TransientTaskType, + }, + event::EventListener, + util::{IdFactory, NoMoveVec}, +}; + +use crate::{ + cell::RecomputingCell, + gc::{GcQueue, PERCENTAGE_IDLE_TARGET_MEMORY, PERCENTAGE_TARGET_MEMORY}, + output::Output, + task::{DEPENDENCIES_TO_TRACK, Task, TaskDependency, TaskDependencySet}, +}; + +fn prehash_task_type(task_type:PersistentTaskType) -> PreHashed { + BuildHasherDefault::::prehash(&Default::default(), task_type) +} + +pub struct MemoryBackend { + memory_tasks:NoMoveVec, + backend_jobs:NoMoveVec, + backend_job_id_factory:IdFactory, + task_cache: + DashMap>, TaskId, BuildHasherDefault>, + memory_limit:usize, + gc_queue:Option, + idle_gc_active:AtomicBool, +} + +impl Default for MemoryBackend { + fn default() -> Self { Self::new(usize::MAX) } +} + +impl MemoryBackend { + pub fn new(memory_limit:usize) -> Self { + Self { + memory_tasks:NoMoveVec::new(), + backend_jobs:NoMoveVec::new(), + backend_job_id_factory:IdFactory::new(), + task_cache:DashMap::with_hasher_and_shard_amount( + Default::default(), + (std::thread::available_parallelism().map_or(1, usize::from) * 32) + .next_power_of_two(), + ), + memory_limit, + gc_queue:(memory_limit != usize::MAX).then(GcQueue::new), + idle_gc_active:AtomicBool::new(false), + } + } + + fn connect_task_child( + &self, + parent:TaskId, + child:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.with_task(parent, |parent| parent.connect_child(child, self, turbo_tasks)); + } + + pub(crate) fn create_backend_job(&self, job:Job) -> BackendJobId { + job.before_schedule(self); + let id = self.backend_job_id_factory.get(); + // SAFETY: This is a fresh id + unsafe { + self.backend_jobs.insert(*id as usize, job); + } + id + } + + pub(crate) fn has_gc(&self) -> bool { self.gc_queue.is_some() } + + fn try_get_output Result>( + &self, + id:TaskId, + strongly_consistent:bool, + note:impl Fn() -> String + Sync + Send + 'static, + turbo_tasks:&dyn TurboTasksBackendApi, + func:F, + ) -> Result> { + self.with_task(id, |task| { + task.get_or_wait_output(strongly_consistent, func, note, self, turbo_tasks) + }) + } + + pub fn with_all_cached_tasks(&self, mut func:impl FnMut(TaskId)) { + for id in self.task_cache.clone().into_read_only().values() { + func(*id); + } + } + + #[inline(always)] + pub fn with_task(&self, id:TaskId, func:impl FnOnce(&Task) -> T) -> T { + func(self.memory_tasks.get(*id as usize).unwrap()) + } + + #[inline(always)] + pub fn task(&self, id:TaskId) -> &Task { self.memory_tasks.get(*id as usize).unwrap() } + + /// Runs the garbage collection until reaching the target memory. An `idle` + /// garbage collection has a lower target memory. Returns true, when + /// memory was collected. + pub fn run_gc(&self, idle:bool, _turbo_tasks:&dyn TurboTasksBackendApi) -> bool { + if let Some(gc_queue) = &self.gc_queue { + let mut did_something = false; + loop { + let mem_limit = self.memory_limit; + + let usage = turbo_tasks_malloc::TurboMalloc::memory_usage(); + let target = if idle { + mem_limit * PERCENTAGE_IDLE_TARGET_MEMORY / 100 + } else { + mem_limit * PERCENTAGE_TARGET_MEMORY / 100 + }; + if usage < target { + return did_something; + } + + let collected = gc_queue.run_gc(self); + + // Collecting less than 100 tasks is not worth it + if !collected.map_or(false, |(_, count)| count > 100) { + return true; + } + + did_something = true; + } + } + false + } + + fn insert_and_connect_fresh_task( + &self, + parent_task:TaskId, + task_cache:&DashMap, + key:K, + new_id:Unused, + task:Task, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> TaskId { + let new_id = new_id.into(); + // Safety: We have a fresh task id that nobody knows about yet + unsafe { self.memory_tasks.insert(*new_id as usize, task) }; + let result_task = match task_cache.entry(key) { + Entry::Vacant(entry) => { + // This is the most likely case + entry.insert(new_id); + new_id + }, + Entry::Occupied(entry) => { + // Safety: We have a fresh task id that nobody knows about yet + let task_id = *entry.get(); + drop(entry); + unsafe { + self.memory_tasks.remove(*new_id as usize); + let new_id = Unused::new_unchecked(new_id); + turbo_tasks.reuse_task_id(new_id); + } + task_id + }, + }; + self.connect_task_child(parent_task, result_task, turbo_tasks); + result_task + } + + fn lookup_and_connect_task( + &self, + parent_task:TaskId, + task_cache:&DashMap, + key:&Q, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Option + where + K: Borrow + Hash + Eq, + Q: Hash + Eq + ?Sized, { + task_cache + .get(key) + // Avoid holding the lock for too long + .map(|task_ref| *task_ref) + .map(|task_id| { + self.connect_task_child(parent_task, task_id, turbo_tasks); + + task_id + }) + } + + pub(crate) fn schedule_when_dirty_from_aggregation( + &self, + set:TaskIdSet, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + for task in set { + self.with_task(task, |task| { + task.schedule_when_dirty_from_aggregation(self, turbo_tasks) + }); + } + } +} + +impl Backend for MemoryBackend { + type ExecutionScopeFuture> + Send + 'static> = + TaskLocalFuture, T>; + + fn idle_start(&self, turbo_tasks:&dyn TurboTasksBackendApi) { + if self + .idle_gc_active + .compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire) + .is_ok() + { + let job = self.create_backend_job(Job::GarbageCollection); + turbo_tasks.schedule_backend_background_job(job); + } + } + + fn invalidate_task(&self, task:TaskId, turbo_tasks:&dyn TurboTasksBackendApi) { + self.with_task(task, |task| task.invalidate(self, turbo_tasks)); + } + + fn invalidate_tasks( + &self, + tasks:&[TaskId], + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + for &task in tasks { + self.with_task(task, |task| { + task.invalidate(self, turbo_tasks); + }); + } + } + + fn invalidate_tasks_set( + &self, + tasks:&TaskIdSet, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + for &task in tasks { + self.with_task(task, |task| { + task.invalidate(self, turbo_tasks); + }); + } + } + + fn get_task_description(&self, task:TaskId) -> String { + self.with_task(task, |task| task.get_description()) + } + + fn execution_scope> + Send + 'static>( + &self, + _task:TaskId, + future:T, + ) -> Self::ExecutionScopeFuture { + DEPENDENCIES_TO_TRACK.scope(RefCell::new(TaskDependencySet::with_hasher()), future) + } + + fn try_start_task_execution( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Option { + self.with_task(task, |task| task.execute(self, turbo_tasks)) + } + + fn task_execution_result( + &self, + task_id:TaskId, + result:Result, Option>>, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.with_task(task_id, |task| { + #[cfg(debug_assertions)] + if let Ok(Ok(RawVc::TaskOutput(result))) = result.as_ref() { + if *result == task_id { + panic!("Task {} returned itself as output", task.get_description()); + } + } + task.execution_result(result, self, turbo_tasks); + }) + } + + fn task_execution_completed( + &self, + task_id:TaskId, + duration:Duration, + memory_usage:usize, + stateful:bool, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> bool { + let generation = + if let Some(gc_queue) = &self.gc_queue { gc_queue.generation() } else { 0 }; + let reexecute = self.with_task(task_id, |task| { + task.execution_completed( + duration, + memory_usage, + generation, + stateful, + self, + turbo_tasks, + ) + }); + if !reexecute { + if let Some(gc_queue) = &self.gc_queue { + gc_queue.task_executed(task_id); + self.run_gc(false, turbo_tasks); + } + } + reexecute + } + + fn try_read_task_output( + &self, + task:TaskId, + reader:TaskId, + strongly_consistent:bool, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result> { + if task == reader { + bail!("reading it's own output is not possible"); + } + self.try_get_output( + task, + strongly_consistent, + move || format!("reading task output from {reader}"), + turbo_tasks, + |output| { + Task::add_dependency_to_current(TaskDependency::Output(task)); + output.read(reader) + }, + ) + } + + fn try_read_task_output_untracked( + &self, + task:TaskId, + strongly_consistent:bool, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result> { + self.try_get_output( + task, + strongly_consistent, + || "reading task output untracked".to_string(), + turbo_tasks, + |output| output.read_untracked(), + ) + } + + fn try_read_task_cell( + &self, + task_id:TaskId, + index:CellId, + reader:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result> { + if task_id == reader { + Ok(Ok(self.with_task(task_id, |task| { + task.with_cell(index, |cell| cell.read_own_content_untracked()) + }))) + } else { + Task::add_dependency_to_current(TaskDependency::Cell(task_id, index)); + self.with_task(task_id, |task| { + match task.with_cell_mut(index, self.gc_queue.as_ref(), |cell| { + cell.read_content( + reader, + move || format!("{task_id} {index}"), + move || format!("reading {} {} from {}", task_id, index, reader), + ) + }) { + Ok(content) => Ok(Ok(content)), + Err(RecomputingCell { listener, schedule }) => { + if schedule { + task.recompute(self, turbo_tasks); + } + Ok(Err(listener)) + }, + } + }) + } + } + + fn try_read_own_task_cell_untracked( + &self, + current_task:TaskId, + index:CellId, + _turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result { + Ok(self.with_task(current_task, |task| { + task.with_cell(index, |cell| cell.read_own_content_untracked()) + })) + } + + fn try_read_task_cell_untracked( + &self, + task_id:TaskId, + index:CellId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result> { + self.with_task(task_id, |task| { + match task.with_cell_mut(index, self.gc_queue.as_ref(), |cell| { + cell.read_content_untracked( + move || format!("{task_id}"), + move || format!("reading {} {} untracked", task_id, index), + ) + }) { + Ok(content) => Ok(Ok(content)), + Err(RecomputingCell { listener, schedule }) => { + if schedule { + task.recompute(self, turbo_tasks); + } + Ok(Err(listener)) + }, + } + }) + } + + fn read_task_collectibles( + &self, + id:TaskId, + trait_id:TraitTypeId, + reader:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> AutoMap { + Task::read_collectibles(id, trait_id, reader, self, turbo_tasks) + } + + fn emit_collectible( + &self, + trait_type:TraitTypeId, + collectible:RawVc, + id:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.with_task(id, |task| { + task.emit_collectible(trait_type, collectible, self, turbo_tasks) + }); + } + + fn unemit_collectible( + &self, + trait_type:TraitTypeId, + collectible:RawVc, + count:u32, + id:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.with_task(id, |task| { + task.unemit_collectible(trait_type, collectible, count, self, turbo_tasks); + }); + } + + fn update_task_cell( + &self, + task:TaskId, + index:CellId, + content:CellContent, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.with_task(task, |task| { + task.with_cell_mut(index, self.gc_queue.as_ref(), |cell| { + cell.assign(content, turbo_tasks) + }) + }) + } + + /// SAFETY: Must only called once with the same id + fn run_backend_job<'a>( + &'a self, + id:BackendJobId, + turbo_tasks:&'a dyn TurboTasksBackendApi, + ) -> Pin + Send + 'a>> { + // SAFETY: id will not be reused until with job is done + if let Some(job) = unsafe { self.backend_jobs.take(*id as usize) } { + Box::pin(async move { + job.run(self, turbo_tasks).await; + // SAFETY: This id will no longer be used + unsafe { + self.backend_job_id_factory.reuse(id); + } + }) + } else { + Box::pin(async {}) + } + } + + fn get_or_create_persistent_task( + &self, + task_type:PersistentTaskType, + parent_task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> TaskId { + let task_type = prehash_task_type(task_type); + if let Some(task) = + self.lookup_and_connect_task(parent_task, &self.task_cache, &task_type, turbo_tasks) + { + // fast pass without creating a new task + task + } else { + // It's important to avoid overallocating memory as this will go into the task + // cache and stay there forever. We can to be as small as possible. + let (task_type_hash, mut task_type) = PreHashed::into_parts(task_type); + task_type.shrink_to_fit(); + let task_type = Arc::new(PreHashed::new(task_type_hash, task_type)); + // slow pass with key lock + let id = turbo_tasks.get_fresh_task_id(); + let task = Task::new_persistent( + // Safety: That task will hold the value, but we are still in + // control of the task + *unsafe { id.get_unchecked() }, + task_type.clone(), + ); + self.insert_and_connect_fresh_task( + parent_task, + &self.task_cache, + task_type, + id, + task, + turbo_tasks, + ) + } + } + + fn connect_task( + &self, + task:TaskId, + parent_task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.connect_task_child(parent_task, task, turbo_tasks); + } + + fn mark_own_task_as_finished( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.with_task(task, |task| task.mark_as_finished(self, turbo_tasks)) + } + + fn create_transient_task( + &self, + task_type:TransientTaskType, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> TaskId { + let id = turbo_tasks.get_fresh_task_id(); + let id = id.into(); + match task_type { + TransientTaskType::Root(f) => { + let task = Task::new_root(id, move || f() as _); + // SAFETY: We have a fresh task id where nobody knows about yet + unsafe { self.memory_tasks.insert(*id as usize, task) }; + Task::set_root(id, self, turbo_tasks); + }, + TransientTaskType::Once(f) => { + let task = Task::new_once(id, f); + // SAFETY: We have a fresh task id where nobody knows about yet + unsafe { self.memory_tasks.insert(*id as usize, task) }; + Task::set_once(id, self, turbo_tasks); + }, + }; + id + } + + fn dispose_root_task(&self, task:TaskId, turbo_tasks:&dyn TurboTasksBackendApi) { + Task::unset_root(task, self, turbo_tasks); + } +} + +pub(crate) enum Job { + GarbageCollection, +} + +impl Job { + // TODO remove this method + fn before_schedule(&self, _backend:&MemoryBackend) {} + + async fn run( + self, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + match self { + Job::GarbageCollection => { + let _guard = trace_span!("Job::GarbageCollection").entered(); + if backend.run_gc(true, turbo_tasks) { + let job = backend.create_backend_job(Job::GarbageCollection); + turbo_tasks.schedule_backend_background_job(job); + } else { + backend.idle_gc_active.store(false, Ordering::Release); + } + }, + } + } +} diff --git a/crates/turbo-tasks-memory/Source/memory_backend_with_pg.rs b/crates/turbo-tasks-memory/Source/memory_backend_with_pg.rs new file mode 100644 index 0000000000000..4468611cf0584 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/memory_backend_with_pg.rs @@ -0,0 +1,1818 @@ +use std::{ + borrow::Cow, + collections::{BinaryHeap, HashMap}, + fmt::Debug, + future::Future, + mem::{replace, take}, + pin::Pin, + sync::{ + Mutex, + MutexGuard, + atomic::{AtomicU32, AtomicUsize, Ordering}, + }, + time::Duration, +}; + +use anyhow::{Result, anyhow}; +use auto_hash_map::{AutoMap, AutoSet}; +use concurrent_queue::ConcurrentQueue; +use dashmap::{DashMap, DashSet, mapref::entry::Entry}; +use turbo_tasks::{ + CellId, + RawVc, + TaskId, + TaskIdSet, + TraitTypeId, + TurboTasksBackendApi, + Unused, + backend::{ + Backend, + BackendJobId, + CellContent, + PersistentTaskType, + TaskExecutionSpec, + TransientTaskType, + }, + event::{Event, EventListener}, + persisted_graph::{ + ActivateResult, + DeactivateResult, + PersistResult, + PersistTaskState, + PersistedGraph, + PersistedGraphApi, + ReadTaskState, + TaskCell, + TaskData, + }, + util::{IdFactory, NoMoveVec, SharedError}, +}; + +type RootTaskFn = + Box Pin> + Send>> + Send + Sync>; + +enum TaskType { + Persistent(PersistentTaskType), + Root(RootTaskFn), + Once(Mutex> + Send + 'static>>>), +} + +impl Debug for TaskType { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Persistent(ty) => f.debug_tuple("Persistent").field(ty).finish(), + Self::Root(_) => f.debug_tuple("Root").finish(), + Self::Once(_) => f.debug_tuple("Once").finish(), + } + } +} + +// dirty+active+scheduled -> clean+active+done -> dirty+active+done+scheduled + +#[derive(PartialEq, Eq, Copy, Clone, Debug, Default)] +enum TaskFreshness { + #[default] + NeverExecuted, + Dirty, + Done, +} + +#[derive(Debug)] +struct MemoryTaskState { + need_persist:bool, + has_changes:bool, + freshness:TaskFreshness, + cells:HashMap, + output:Option>, + output_dependent:TaskIdSet, + dependencies:AutoSet, + children:TaskIdSet, + event:Event, + event_cells:Event, +} + +impl MemoryTaskState { + fn new(task:TaskId, freshness:TaskFreshness) -> Self { + Self { + freshness, + need_persist:Default::default(), + has_changes:Default::default(), + cells:HashMap::default(), + output:Default::default(), + output_dependent:Default::default(), + dependencies:Default::default(), + children:Default::default(), + event:Event::new(move || format!("MemoryTaskState({task})::event")), + event_cells:Event::new(move || format!("MemoryTaskState({task})::event_cells")), + } + } +} + +#[derive(Default, Debug)] +struct PersistedTaskState { + clean:Option, +} + +#[derive(Default, Debug)] +struct TaskState { + memory:Option, + persisted:Option, + + /// the memory version is considered as active + active:bool, + + // cross activeness: + /// There are active parents in memory graph + /// that keep the persisted version active too + mem_to_persisted_active:bool, + + /// There are active parents in persisted graph + /// that keep the memory version active + persisted_to_mem_active:bool, + + scheduled:bool, +} + +struct Task { + task_type:TaskType, + task_state:Mutex, + active_parents:AtomicU32, +} + +enum BackgroundJob { + DeactivateTasks(Vec), + ActivatePersisted(TaskId), + DeactivatePersisted(TaskId), +} + +pub struct MemoryBackendWithPersistedGraph { + pub pg:P, + tasks:NoMoveVec, + cache:DashMap, + background_job_id_factory:IdFactory, + background_jobs:NoMoveVec, + only_known_to_memory_tasks:DashSet, + /// Tasks that were selected to persist + persist_queue1:ConcurrentQueue, + persist_queue1_queued:DashSet, + need_persisting:DashSet, + /// Task sorted by importance, sharded to avoid lock contention + persist_queue_by_duration:[Mutex>; 64], + persist_capacity:AtomicUsize, + persist_job:BackendJobId, + partial_lookups:DashMap, + #[cfg(feature = "unsafe_once_map")] + partial_lookup:turbo_tasks::util::OnceConcurrentlyMap, + #[cfg(not(feature = "unsafe_once_map"))] + partial_lookup:turbo_tasks::util::SafeOnceConcurrentlyMap, + + #[cfg(feature = "log_running_tasks")] + in_progress_tasks:Mutex>, +} + +impl MemoryBackendWithPersistedGraph

{ + pub fn new(pg:P) -> Self { + let background_job_id_factory = IdFactory::new(); + let persist_job = background_job_id_factory.get(); + Self { + pg, + tasks:NoMoveVec::new(), + cache:DashMap::new(), + background_job_id_factory, + background_jobs:NoMoveVec::new(), + only_known_to_memory_tasks:DashSet::new(), + persist_queue1:ConcurrentQueue::unbounded(), + persist_queue1_queued:DashSet::new(), + need_persisting:DashSet::new(), + persist_queue_by_duration:[(); 64].map(|_| Mutex::new(BinaryHeap::new())), + persist_capacity:AtomicUsize::new(num_cpus::get()), + persist_job, + partial_lookups:DashMap::new(), + #[cfg(feature = "unsafe_once_map")] + partial_lookup:turbo_tasks::util::OnceConcurrentlyMap::new(), + #[cfg(not(feature = "unsafe_once_map"))] + partial_lookup:turbo_tasks::util::SafeOnceConcurrentlyMap::new(), + #[cfg(feature = "log_running_tasks")] + in_progress_tasks:Mutex::new(HashSet::new()), + } + } + + fn state_mut( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> (MutexGuard<'_, TaskState>, &Task) { + let task_info = self.tasks.get(*task as usize).unwrap(); + let mut state = task_info.task_state.lock().unwrap(); + self.ensure_task_initialized(task, task_info, &mut state, turbo_tasks); + (state, task_info) + } + + fn mem_state_mut( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> (MutexGuard<'_, TaskState>, &Task) { + let task_info = self.tasks.get(*task as usize).unwrap(); + loop { + let mut delayed_activate = Vec::new(); + let mut state = task_info.task_state.lock().unwrap(); + self.ensure_task_in_memory(task, &mut state, &mut delayed_activate, turbo_tasks); + if delayed_activate.is_empty() { + return (state, task_info); + } + drop(state); + loop { + for task in take(&mut delayed_activate) { + let (state, task_info) = self.state_mut(task, turbo_tasks); + self.activate_task_inner( + task, + state, + task_info, + &mut delayed_activate, + turbo_tasks, + ); + } + if delayed_activate.is_empty() { + break; + } + } + } + } + + fn ensure_task_initialized( + &self, + task:TaskId, + task_info:&Task, + task_state:&mut TaskState, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + if task_state.memory.is_none() && task_state.persisted.is_none() { + if let TaskType::Persistent(_) = &task_info.task_type { + if self.pg_is_persisted(task, turbo_tasks) { + task_state.persisted = Some(PersistedTaskState { clean:None }); + } else { + task_state.memory = + Some(MemoryTaskState::new(task, TaskFreshness::NeverExecuted)); + } + } else { + // We must never have not initizalized transient task in the cache + // This is ensured by initializing the task when creating it + unreachable!(); + } + } + } + + fn ensure_task_in_memory( + &self, + task:TaskId, + task_state:&mut TaskState, + delayed_activate:&mut Vec, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + if task_state.memory.is_none() { + if let Some((data, state)) = self.pg_read(task, turbo_tasks) { + task_state.persisted = Some(PersistedTaskState { clean:Some(state.clean) }); + let mem_state = MemoryTaskState { + freshness:if state.clean { TaskFreshness::Done } else { TaskFreshness::Dirty }, + cells:data + .cells + .into_iter() + .map(|(k, s)| (k, (s, AutoSet::default()))) + .collect(), + output:Some(Ok(data.output)), + output_dependent:AutoSet::default(), + dependencies:data.dependencies.into_iter().collect(), + children:data.children.into_iter().collect(), + need_persist:Default::default(), + has_changes:Default::default(), + event:Event::new(move || format!("MemoryTaskState({task})::event")), + event_cells:Event::new(move || format!("MemoryTaskState({task})::event_cells")), + }; + if task_state.active { + for &child in mem_state.children.iter() { + self.try_increment_active_parents( + child, + false, + 1, + delayed_activate, + turbo_tasks, + ); + } + } + if !task_state.persisted_to_mem_active && state.keeps_external_active { + delayed_activate.push(task); + } + task_state.persisted_to_mem_active = state.keeps_external_active; + task_state.memory = Some(mem_state); + if !state.clean && task_state.active && !task_state.scheduled { + task_state.scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in ensure_task_in_memory"); + turbo_tasks.schedule(task); + } + } else { + task_state.memory = Some(MemoryTaskState::new(task, TaskFreshness::NeverExecuted)); + } + } + } + + fn lookup( + &self, + task_type:&PersistentTaskType, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Option { + for i in 0..task_type.len() { + let partial = task_type.partial(i); + let complete_cached = self.partial_lookups.get(&partial).map(|x| *x); + let complete = complete_cached.unwrap_or_else(|| { + self.partial_lookup.action(&partial, || { + let complete = self.pg_lookup(&partial, turbo_tasks); + self.partial_lookups.insert(partial.clone(), complete); + complete + }) + }); + if complete { + return self.cache.get(task_type).map(|x| *x); + } + } + self.pg_lookup_one(task_type, turbo_tasks) + } + + fn connect( + &self, + parent_task:TaskId, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + // connect() will never be called concurrently for the same parent_task + // therefore it's safe to add the task into children before incrementing + // active_parents. + // An active_parents underflow can't happen because of that. + + let (mut state, _) = self.mem_state_mut(parent_task, turbo_tasks); + let mem_state = state.memory.as_mut().unwrap(); + if !mem_state.children.insert(task) { + return; + } + let memory_active = state.active; + drop(state); + + #[cfg(feature = "log_connect_tasks")] + println!("connect({parent_task} -> {task}) (memory_active={memory_active})"); + if memory_active { + self.increment_active_parents(task, 1, turbo_tasks); + } + } + + fn connect_already_counted( + &self, + parent_task:TaskId, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + // The active_parents count was already initialized with 1 + // When this was incorrect, we need to revert that. + let (mut state, _) = self.mem_state_mut(parent_task, turbo_tasks); + let mem_state = state.memory.as_mut().unwrap(); + if !mem_state.children.insert(task) { + // revert already increased count as it has already been added a child before + drop(state); + self.decrement_active_parents(task, 1, turbo_tasks); + return; + } + #[cfg(feature = "log_connect_tasks")] + println!( + "connect_already_counted({parent_task} -> {task}) (memory_active={})", + state.active + ); + if !state.active { + // revert already increased count as the parent task is not active + drop(state); + self.decrement_active_parents(task, 1, turbo_tasks); + } + } + + fn schedule_background_job( + &self, + job:BackgroundJob, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let id = self.background_job_id_factory.get(); + // SAFETY: It's a fresh id + unsafe { + self.background_jobs.insert(*id as usize, job); + } + turbo_tasks.schedule_backend_background_job(id); + } + + fn activate_persisted( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + if let Some(ActivateResult { + keeps_external_active, + external, + dirty, + more_tasks_to_activate, + }) = self.pg_activate_when_needed(task, turbo_tasks) + { + for task in more_tasks_to_activate { + self.schedule_background_job(BackgroundJob::ActivatePersisted(task), turbo_tasks); + } + let (mut state, task_info) = self.state_mut(task, turbo_tasks); + if dirty && state.memory.is_none() && !state.scheduled { + state.scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in activate_persisted"); + turbo_tasks.schedule(task); + } + if (external || state.memory.is_some()) + && state.persisted_to_mem_active != keeps_external_active + { + state.persisted_to_mem_active = keeps_external_active; + if keeps_external_active { + self.activate_task(task, state, task_info, turbo_tasks) + } else { + self.deactivate_task(task, state, task_info, turbo_tasks) + } + } + } + } + + fn deactivate_persisted( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + if let Some(DeactivateResult { more_tasks_to_deactivate }) = + self.pg_deactivate_when_needed(task, turbo_tasks) + { + for task in more_tasks_to_deactivate { + self.schedule_background_job(BackgroundJob::DeactivatePersisted(task), turbo_tasks); + } + let (mut state, task_info) = self.state_mut(task, turbo_tasks); + if state.persisted_to_mem_active { + state.persisted_to_mem_active = false; + self.deactivate_task(task, state, task_info, turbo_tasks); + } + } + } + + fn increment_active_parents( + &self, + task:TaskId, + by:u32, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let mut delayed_activate = Vec::new(); + self.try_increment_active_parents(task, true, by, &mut delayed_activate, turbo_tasks); + while !delayed_activate.is_empty() { + for task in take(&mut delayed_activate) { + let (state, task_info) = self.state_mut(task, turbo_tasks); + self.activate_task_inner( + task, + state, + task_info, + &mut delayed_activate, + turbo_tasks, + ); + } + } + } + + fn try_increment_active_parents( + &self, + task:TaskId, + force:bool, + by:u32, + delayed_activate:&mut Vec, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let task_info = self.tasks.get(*task as usize).unwrap(); + let prev = task_info.active_parents.fetch_add(by, Ordering::Relaxed); + if prev == 0 { + // only the connect() call that increases from 0 is responsible for activating + let mut state = if force { + task_info.task_state.lock().unwrap() + } else { + match task_info.task_state.try_lock() { + Ok(state) => state, + Err(_) => { + delayed_activate.push(task); + return; + }, + } + }; + self.ensure_task_initialized(task, task_info, &mut state, turbo_tasks); + self.activate_task_inner(task, state, task_info, delayed_activate, turbo_tasks); + } + } + + fn activate_task( + &self, + task:TaskId, + state:MutexGuard, + task_info:&Task, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let mut delayed_activate = Vec::new(); + self.activate_task_inner(task, state, task_info, &mut delayed_activate, turbo_tasks); + while !delayed_activate.is_empty() { + for task in take(&mut delayed_activate) { + let (state, task_info) = self.state_mut(task, turbo_tasks); + self.activate_task_inner( + task, + state, + task_info, + &mut delayed_activate, + turbo_tasks, + ); + } + } + } + + fn activate_task_inner( + &self, + task:TaskId, + mut state:MutexGuard, + task_info:&Task, + delayed_activate:&mut Vec, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let TaskState { + ref mut active, + ref persisted_to_mem_active, + ref persisted, + ref mut mem_to_persisted_active, + ref mut scheduled, + ref memory, + .. + } = *state; + let mut activate_persisted = false; + let mut deactivate_persisted = false; + let has_active_parents = task_info.active_parents.load(Ordering::Acquire) > 0; + if persisted.is_some() && !*mem_to_persisted_active && has_active_parents { + *mem_to_persisted_active = true; + if self.pg_set_externally_active(task, turbo_tasks) { + activate_persisted = true; + } + } + if *mem_to_persisted_active && !has_active_parents { + *mem_to_persisted_active = false; + if self.pg_unset_externally_active(task, turbo_tasks) { + deactivate_persisted = true; + } + } + if !*active && (has_active_parents || *persisted_to_mem_active) { + *active = true; + #[cfg(feature = "log_activate_tasks")] + println!("activate {task}"); + if let Some(MemoryTaskState { freshness, children, .. }) = memory { + if !*scheduled && *freshness != TaskFreshness::Done { + *scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in activate_task_inner"); + turbo_tasks.schedule(task); + } + for child in children.iter() { + self.try_increment_active_parents( + *child, + false, + 1, + delayed_activate, + turbo_tasks, + ); + } + } + } + drop(state); + if activate_persisted { + self.activate_persisted(task, turbo_tasks); + } + if deactivate_persisted { + self.deactivate_persisted(task, turbo_tasks); + } + } + + fn decrement_active_parents( + &self, + task:TaskId, + by:u32, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + self.decrement_active_parents_limited(&[(task, by)], 0, turbo_tasks); + } + + fn decrement_active_parents_limited( + &self, + tasks:&[(TaskId, u32)], + remaining_depth:u8, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let mut delayed_deactivate = Vec::new(); + for (task, by) in tasks { + self.try_decrement_active_parents( + *task, + *by, + remaining_depth, + &mut delayed_deactivate, + turbo_tasks, + ); + } + if !delayed_deactivate.is_empty() { + self.schedule_background_job( + BackgroundJob::DeactivateTasks(delayed_deactivate), + turbo_tasks, + ); + } + } + + fn try_decrement_active_parents( + &self, + task:TaskId, + by:u32, + remaining_depth:u8, + delayed_deactivate:&mut Vec, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let task_info = self.tasks.get(*task as usize).unwrap(); + let prev = task_info.active_parents.fetch_sub(by, Ordering::Relaxed); + if prev == by { + // count reached zero + let mut state = if remaining_depth > 0 { + match task_info.task_state.try_lock() { + Ok(state) => state, + Err(_) => { + delayed_deactivate.push(task); + return; + }, + } + } else { + delayed_deactivate.push(task); + return; + }; + self.ensure_task_initialized(task, task_info, &mut state, turbo_tasks); + self.deactivate_task_inner( + task, + state, + task_info, + remaining_depth - 1, + delayed_deactivate, + turbo_tasks, + ); + } + } + + fn deactivate_task( + &self, + task:TaskId, + state:MutexGuard, + task_info:&Task, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let mut delayed_deactivate = Vec::new(); + self.deactivate_task_inner(task, state, task_info, 2, &mut delayed_deactivate, turbo_tasks); + if !delayed_deactivate.is_empty() { + self.schedule_background_job( + BackgroundJob::DeactivateTasks(delayed_deactivate), + turbo_tasks, + ); + } + } + + fn deactivate_tasks( + &self, + tasks:&[TaskId], + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let mut delayed_deactivate = Vec::new(); + for task in tasks { + let (state, task_info) = self.state_mut(*task, turbo_tasks); + self.deactivate_task_inner( + *task, + state, + task_info, + 2, + &mut delayed_deactivate, + turbo_tasks, + ); + } + if !delayed_deactivate.is_empty() { + self.schedule_background_job( + BackgroundJob::DeactivateTasks(delayed_deactivate), + turbo_tasks, + ); + } + } + + fn deactivate_task_inner( + &self, + task:TaskId, + mut state:MutexGuard, + task_info:&Task, + remaining_depth:u8, + delayed_deactivate:&mut Vec, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let mut deactivate_persisted = false; + let TaskState { ref mut active, ref mut mem_to_persisted_active, ref memory, .. } = *state; + if *active && task_info.active_parents.load(Ordering::Acquire) == 0 { + *active = false; + if *mem_to_persisted_active { + *mem_to_persisted_active = false; + if self.pg_unset_externally_active(task, turbo_tasks) { + deactivate_persisted = true; + } + } + if let Some(MemoryTaskState { ref children, .. }) = memory { + for child in children.iter() { + self.try_decrement_active_parents( + *child, + 1, + remaining_depth, + delayed_deactivate, + turbo_tasks, + ); + } + } + } + drop(state); + if deactivate_persisted { + self.deactivate_persisted(task, turbo_tasks); + } + } + + fn persist( + &self, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> bool { + loop { + if let Ok(mut task) = self.persist_queue1.pop() { + self.persist_queue1_queued.remove(&task); + 'outer: loop { + self.need_persisting.remove(&task); + let (mut state, task_info) = self.state_mut(task, turbo_tasks); + if let TaskState { + ref mut persisted, + ref mut mem_to_persisted_active, + memory: + Some(MemoryTaskState { + freshness: TaskFreshness::Done, + ref mut need_persist, + ref output, + ref mut has_changes, + ref children, + ref dependencies, + ref cells, + .. + }), + .. + } = *state + { + if *need_persist || persisted.is_none() { + *need_persist = false; + if let TaskType::Persistent(_task_type) = &task_info.task_type { + if let &Some(Ok(output)) = &output { + if *has_changes || persisted.is_none() { + for higher_prio_task in dependencies + .iter() + .map(|vc| vc.get_task_id()) + .chain(children.iter().copied()) + { + if self.need_persisting.contains(&higher_prio_task) { + if self.persist_queue1_queued.insert(task) { + self.persist_queue1.push(task).unwrap(); + } + task = higher_prio_task; + continue 'outer; + } + } + if !dependencies.is_empty() { + for dep in dependencies.iter() { + let task = dep.get_task_id(); + self.only_known_to_memory_tasks.remove(&task); + } + } + let data = TaskData { + children:children.iter().cloned().collect(), + dependencies:dependencies.iter().cloned().collect(), + cells:cells + .iter() + .map(|(k, (s, _))| (*k, s.clone())) + .collect(), + output:*output, + }; + let externally_active = + task_info.active_parents.load(Ordering::Acquire) > 0; + let task_state = + turbo_tasks::persisted_graph::PersistTaskState { + externally_active, + }; + if let Some(PersistResult { + tasks_to_activate, + tasks_to_deactivate, + }) = self.pg_persist(task, data, task_state, turbo_tasks) + { + *persisted = + Some(PersistedTaskState { clean:Some(true) }); + *has_changes = false; + *mem_to_persisted_active = externally_active; + drop(state); + for task in tasks_to_activate { + self.activate_persisted(task, turbo_tasks); + } + for task in tasks_to_deactivate { + self.schedule_background_job( + BackgroundJob::DeactivatePersisted(task), + turbo_tasks, + ) + } + return true; + } else { + println!( + "task {task} failed to persist: {:?}", + task_info.task_type + ); + } + } else { + self.pg_make_clean(task, turbo_tasks); + return true; + } + } + } + } + } + break; + } + continue; + } + + let mut did_something = false; + for queue in self.persist_queue_by_duration.iter() { + let mut queue = queue.lock().unwrap(); + if let Some((_dur, task)) = queue.pop() { + let (state, _) = self.state_mut(task, turbo_tasks); + if let Some(MemoryTaskState { dependencies: _, .. }) = &state.memory { + // let dependencies = dependencies + // .iter() + // .map(|d| d.get_task_id()) + // .collect::>(); + // for dep in dependencies { + // if self.persist_queue1_queued.insert(dep) { + // self.persist_queue1.push(dep).unwrap(); + // did_something = true; + // } + // } + if self.persist_queue1_queued.insert(task) { + self.persist_queue1.push(task).unwrap(); + did_something = true; + } + } + } + } + + return did_something; + } + } + + fn has_persist_work(&self) -> bool { + !self.persist_queue1.is_empty() + || self.persist_queue_by_duration.iter().any(|q| !q.lock().unwrap().is_empty()) + } + + fn increase_persist_workers( + &self, + n:usize, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + loop { + let capacity = self.persist_capacity.load(Ordering::Acquire); + if capacity == 0 { + break; + } + let can_start = std::cmp::min(capacity, n); + if self + .persist_capacity + .compare_exchange( + capacity, + capacity - can_start, + Ordering::Release, + Ordering::Relaxed, + ) + .is_ok() + { + for _ in 0..can_start { + turbo_tasks.schedule_backend_background_job(self.persist_job); + } + } + } + } +} + +impl Backend for MemoryBackendWithPersistedGraph

{ + type ExecutionScopeFuture> + Send + 'static> = T; + + fn startup(&self, turbo_tasks:&dyn TurboTasksBackendApi>) { + let (tasks_to_activate, tasks_to_deactivate) = + self.pg_get_pending_active_update(turbo_tasks); + let tasks = self.pg_get_active_external_tasks(turbo_tasks); + let dirty_tasks = self.pg_get_dirty_active_tasks(turbo_tasks); + + for task in tasks.iter() { + #[allow(unused_variables)] + let (mut state, task_info) = self.state_mut(*task, turbo_tasks); + state.persisted_to_mem_active = true; + state.memory = Some(MemoryTaskState::new(*task, TaskFreshness::NeverExecuted)); + #[cfg(feature = "log_running_tasks")] + { + println!("restored external active task {} {:?}", task, task_info.task_type); + } + } + for task in dirty_tasks.iter() { + #[allow(unused_variables)] + let (mut state, task_info) = self.state_mut(*task, turbo_tasks); + state.persisted_to_mem_active = true; + state.persisted = Some(PersistedTaskState { clean:Some(false) }); + #[cfg(feature = "log_running_tasks")] + { + println!("restored dirty active task {} {:?}", task, task_info.task_type); + } + + // On startup this is never scheduled yet + state.scheduled = true; + } + for task in tasks.into_iter() { + let (state, task_info) = self.state_mut(task, turbo_tasks); + self.activate_task(task, state, task_info, turbo_tasks); + } + + for task in dirty_tasks.into_iter() { + let (state, task_info) = self.state_mut(task, turbo_tasks); + self.activate_task(task, state, task_info, turbo_tasks); + // Activate would not schedule it since it's not in memory + turbo_tasks.schedule(task); + } + for task in tasks_to_activate { + #[cfg(feature = "log_running_tasks")] + { + let (state, task_info) = self.state_mut(task, turbo_tasks); + println!("continue pending activate {} {:?}", task, task_info.task_type); + } + self.activate_persisted(task, turbo_tasks); + } + for task in tasks_to_deactivate { + #[cfg(feature = "log_running_tasks")] + { + let (state, task_info) = self.state_mut(task, turbo_tasks); + println!("continue pending deactivate {} {:?}", task, task_info.task_type); + } + self.schedule_background_job(BackgroundJob::DeactivatePersisted(task), turbo_tasks); + } + } + + fn stop(&self, turbo_tasks:&dyn TurboTasksBackendApi>) { + self.pg_stop(turbo_tasks); + } + + fn invalidate_task( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let (mut state, _) = self.state_mut(task, turbo_tasks); + + if let Some(MemoryTaskState { freshness, .. }) = &mut state.memory { + if *freshness != TaskFreshness::Dirty { + *freshness = TaskFreshness::Dirty; + if state.active && !state.scheduled { + state.scheduled = true; + turbo_tasks.schedule(task); + } + } + } + if let Some(PersistedTaskState { clean, .. }) = &mut state.persisted { + if *clean != Some(false) && self.pg_make_dirty(task, turbo_tasks) { + *clean = Some(false); + if !state.scheduled { + state.scheduled = true; + turbo_tasks.schedule(task); + } + } + } + } + + fn invalidate_tasks( + &self, + tasks:&[TaskId], + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + for &task in tasks { + self.invalidate_task(task, turbo_tasks); + } + } + + fn invalidate_tasks_set( + &self, + tasks:&TaskIdSet, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + for &task in tasks { + self.invalidate_task(task, turbo_tasks); + } + } + + fn get_task_description(&self, task:TaskId) -> String { + let task_info = self.tasks.get(*task as usize).unwrap(); + format!("{:?}", task_info.task_type) + } + + fn execution_scope> + Send + 'static>( + &self, + _task:TaskId, + future:T, + ) -> Self::ExecutionScopeFuture { + future + } + + fn try_start_task_execution( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Option { + let (mut state, task_info) = self.mem_state_mut(task, turbo_tasks); + let mem_state = state.memory.as_mut().unwrap(); + if mem_state.freshness == TaskFreshness::Done { + state.scheduled = false; + return None; + } + #[cfg(feature = "log_running_tasks")] + { + let mut t = self.in_progress_tasks.lock().unwrap(); + t.insert(task); + println!("start {} {:?}", task, task_info.task_type); + } + mem_state.freshness = TaskFreshness::NeverExecuted; + let deps = take(&mut mem_state.dependencies); + let children = take(&mut mem_state.children); + drop(state); + for dep in deps { + let (mut state, _) = self.mem_state_mut(dep.get_task_id(), turbo_tasks); + let mem_state = state.memory.as_mut().unwrap(); + match dep { + RawVc::TaskOutput(_) => { + mem_state.output_dependent.remove(&task); + }, + RawVc::TaskCell(_, i) => { + if let Some((_, dependent)) = mem_state.cells.get_mut(&i) { + dependent.remove(&task); + } + }, + } + } + for child in children { + self.decrement_active_parents(child, 1, turbo_tasks); + } + let future = match &task_info.task_type { + TaskType::Persistent(t) => t.clone().run(turbo_tasks.pin()), + TaskType::Root(root) => root(), + TaskType::Once(once) => { + let mut m = once.lock().unwrap(); + replace( + &mut *m, + Box::pin(async { Err(anyhow::anyhow!("Once task can only be executed once")) }), + ) + }, + }; + Some(TaskExecutionSpec { future, span:tracing::Span::none() }) + } + + fn task_execution_result( + &self, + task:TaskId, + result:Result, Option>>, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let (mut state, _task_info) = self.mem_state_mut(task, turbo_tasks); + let TaskState { ref mut memory, .. } = *state; + let mem_state = memory.as_mut().unwrap(); + let result = result.unwrap_or_else(|panic| { + match panic { + Some(message) => Err(anyhow!("A task panicked: {message}")), + None => Err(anyhow!("A task panicked")), + } + }); + let output_change = if let (Some(Ok(old)), Ok(new)) = (&mem_state.output, &result) { + old != new + } else { + true + }; + let dependent = if output_change { + mem_state.has_changes = true; + mem_state.output = Some(result.map_err(SharedError::new)); + take(&mut mem_state.output_dependent) + } else { + AutoSet::default() + }; + + drop(state); + + if !dependent.is_empty() { + turbo_tasks.schedule_notify_tasks_set(&dependent); + } + } + + fn task_execution_completed( + &self, + task:TaskId, + duration:Duration, + _memory_usage:usize, + _stateful:bool, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> bool { + #[cfg(feature = "log_running_tasks")] + { + println!("done {}", task); + let mut t = self.in_progress_tasks.lock().unwrap(); + t.remove(&task); + println!("running {:?}", t.iter().take(10).collect::>()); + } + let (mut state, task_info) = self.mem_state_mut(task, turbo_tasks); + let TaskState { ref mut scheduled, ref mut memory, ref mut persisted, .. } = *state; + let mem_state = memory.as_mut().unwrap(); + if mem_state.freshness == TaskFreshness::Dirty { + return true; + } + mem_state.freshness = TaskFreshness::Done; + *scheduled = false; + mem_state.event.notify(usize::MAX); + mem_state.event_cells.notify(usize::MAX); + mem_state.need_persist = true; + let has_changes = mem_state.has_changes; + let is_persisted = persisted.is_some(); + let is_dirty_persisted = + persisted.as_ref().map(|p| p.clean != Some(true)).unwrap_or_default(); + drop(state); + + if let TaskType::Persistent(_) = task_info.task_type { + if has_changes && (is_persisted || !self.only_known_to_memory_tasks.contains(&task)) { + for task in self.pg_make_dependent_dirty(RawVc::TaskOutput(task), turbo_tasks) { + let (mut state, _) = self.state_mut(task, turbo_tasks); + if !state.scheduled { + state.scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in task_execution_completed"); + turbo_tasks.schedule(task); + } + } + } + if has_changes || is_dirty_persisted { + self.need_persisting.insert(task); + self.persist_queue_by_duration + [*task as usize % self.persist_queue_by_duration.len()] + .lock() + .unwrap() + .push((duration, task)); + self.increase_persist_workers(1, turbo_tasks); + } + } + + false + } + + fn run_backend_job<'a>( + &'a self, + id:BackendJobId, + turbo_tasks:&'a dyn TurboTasksBackendApi>, + ) -> Pin + Send + 'a>> { + if id == self.persist_job { + return Box::pin(async { + if self.persist(turbo_tasks) { + turbo_tasks.schedule_backend_background_job(self.persist_job); + } else { + self.persist_capacity.fetch_add(1, Ordering::Relaxed); + if self.has_persist_work() { + // Might be a race condition, work was just added before + // we reduced persist_capacity. To avoid a stall we will + // increase the workers again in this situation. + self.increase_persist_workers(1, turbo_tasks) + } + } + }); + } + // SAFETY: We are the only owner of this id + let job = unsafe { self.background_jobs.take(*id as usize) }; + unsafe { + self.background_job_id_factory.reuse(id); + } + if let Some(job) = job { + match job { + BackgroundJob::DeactivateTasks(tasks) => { + Box::pin(async move { + for chunk in tasks.chunks(10) { + self.deactivate_tasks(chunk, turbo_tasks) + } + }) + }, + BackgroundJob::ActivatePersisted(task) => { + Box::pin(async move { self.activate_persisted(task, turbo_tasks) }) + }, + BackgroundJob::DeactivatePersisted(task) => { + Box::pin(async move { self.deactivate_persisted(task, turbo_tasks) }) + }, + } + } else { + Box::pin(async {}) + } + } + + fn try_read_task_output( + &self, + task:TaskId, + reader:TaskId, + _strongly_consistent:bool, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Result> { + let (mut state, _task_info) = self.mem_state_mut(task, turbo_tasks); + let TaskState { ref mut scheduled, ref mut memory, .. } = *state; + let mem_state = memory.as_mut().unwrap(); + if mem_state.freshness != TaskFreshness::Done { + let listener = mem_state.event.listen(); + if !*scheduled { + *scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in try_read_task_output[{:?}]", mem_state.freshness); + turbo_tasks.schedule(task); + } + #[cfg(feature = "log_running_tasks")] + println!("waiting {} waits on {}: {:?}", reader, task, state); + return Ok(Err(listener)); + } + let need_dependency = mem_state.output_dependent.insert(reader); + let result = Ok(Ok(mem_state.output.as_ref().unwrap().clone()?)); + drop(state); + if need_dependency { + let (mut state, _) = self.mem_state_mut(reader, turbo_tasks); + let mem_state = state.memory.as_mut().unwrap(); + mem_state.dependencies.insert(RawVc::TaskOutput(task)); + } + result + } + + fn try_read_task_output_untracked( + &self, + task:TaskId, + _strongly_consistent:bool, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Result> { + let (state, task_info) = self.mem_state_mut(task, turbo_tasks); + let mem_state = state.memory.as_ref().unwrap(); + if mem_state.freshness != TaskFreshness::Done { + let listener = mem_state.event.listen(); + if !state.active { + self.activate_task(task, state, task_info, turbo_tasks); + } + #[cfg(feature = "log_running_tasks")] + println!("waiting ?? waits on {}", task); + return Ok(Err(listener)); + } + Ok(Ok(mem_state.output.as_ref().unwrap().clone()?)) + } + + fn try_read_task_cell( + &self, + task:TaskId, + index:CellId, + reader:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Result> { + let (mut state, _task_info) = self.mem_state_mut(task, turbo_tasks); + let TaskState { ref mut scheduled, ref mut memory, .. } = *state; + let mem_state = memory.as_mut().unwrap(); + if mem_state.freshness == TaskFreshness::NeverExecuted { + if !*scheduled { + *scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in try_read_task_cell[NeverExecuted]"); + turbo_tasks.schedule(task); + } + #[cfg(feature = "log_running_tasks")] + println!("waiting (fresh task) {} waits on {}", reader, task); + return Ok(Err(mem_state.event_cells.listen())); + } + if let Some((cell, dependent)) = mem_state.cells.get_mut(&index) { + match cell { + TaskCell::Content(content) => { + let content = content.clone(); + let need_dependency = dependent.insert(reader); + drop(state); + if need_dependency { + let (mut state, _) = self.mem_state_mut(reader, turbo_tasks); + let mem_state = state.memory.as_mut().unwrap(); + mem_state.dependencies.insert(RawVc::TaskCell(task, index)); + } + Ok(Ok(content)) + }, + TaskCell::NeedComputation => { + if mem_state.freshness != TaskFreshness::Dirty { + mem_state.freshness = TaskFreshness::Dirty; + if !*scheduled { + *scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in try_read_task_cell[NeedComputation]"); + turbo_tasks.schedule(task); + } + } + #[cfg(feature = "log_running_tasks")] + println!("waiting (need computation) {} waits on {}", reader, task); + Ok(Err(mem_state.event.listen())) + }, + } + } else { + if !*scheduled { + *scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in try_read_task_cell[Cell missing]"); + turbo_tasks.schedule(task); + } + #[cfg(feature = "log_running_tasks")] + println!("waiting (incomplete task) {} waits on {}", reader, task); + Ok(Err(mem_state.event_cells.listen())) + } + } + + fn try_read_task_cell_untracked( + &self, + task:TaskId, + index:CellId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Result> { + let (mut state, _) = self.mem_state_mut(task, turbo_tasks); + let TaskState { ref mut scheduled, ref mut memory, .. } = *state; + let mem_state = memory.as_mut().unwrap(); + let (cell, _) = mem_state + .cells + .get(&index) + .ok_or_else(|| anyhow!("Cannot read non-existing cell"))?; + match cell { + TaskCell::Content(content) => { + let content = content.clone(); + drop(state); + Ok(Ok(content)) + }, + TaskCell::NeedComputation => { + if mem_state.freshness != TaskFreshness::Dirty { + mem_state.freshness = TaskFreshness::Dirty; + if !*scheduled { + *scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in try_read_task_cell_untracked"); + turbo_tasks.schedule(task); + } + } + Ok(Err(mem_state.event.listen())) + }, + } + } + + fn try_read_own_task_cell_untracked( + &self, + task:TaskId, + index:CellId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Result { + let (state, _) = self.mem_state_mut(task, turbo_tasks); + let mem_state = state.memory.as_ref().unwrap(); + if let Some((cell, _)) = mem_state.cells.get(&index) { + match cell { + TaskCell::Content(content) => Ok(content.clone()), + TaskCell::NeedComputation => Ok(CellContent(None)), + } + } else { + Ok(CellContent(None)) + } + } + + fn read_task_collectibles( + &self, + _task:TaskId, + _trait_id:TraitTypeId, + _reader:TaskId, + _turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> AutoMap { + todo!() + } + + fn emit_collectible( + &self, + _trait_id:TraitTypeId, + _collectible:RawVc, + _task:TaskId, + _turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + todo!() + } + + fn unemit_collectible( + &self, + _trait_id:TraitTypeId, + _collectible:RawVc, + _count:u32, + _task:TaskId, + _turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + todo!() + } + + fn update_task_cell( + &self, + task:TaskId, + index:CellId, + content:CellContent, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + let (mut state, task_info) = self.mem_state_mut(task, turbo_tasks); + let TaskState { ref mut memory, ref mut persisted, .. } = *state; + let mem_state = memory.as_mut().unwrap(); + mem_state.has_changes = true; + let (cell, dependent) = mem_state.cells.entry(index).or_default(); + *cell = TaskCell::Content(content); + mem_state.event_cells.notify(usize::MAX); + let is_persisted = persisted.is_some(); + if !dependent.is_empty() { + let dependent = take(dependent); + drop(state); + turbo_tasks.schedule_notify_tasks_set(&dependent); + } else { + drop(state); + } + if let TaskType::Persistent(_) = task_info.task_type { + if is_persisted || !self.only_known_to_memory_tasks.contains(&task) { + for task in self.pg_make_dependent_dirty(RawVc::TaskCell(task, index), turbo_tasks) + { + let (mut state, _) = self.state_mut(task, turbo_tasks); + if !state.scheduled { + state.scheduled = true; + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in update_task_cell"); + turbo_tasks.schedule(task); + } + } + } + } + } + + fn get_or_create_persistent_task( + &self, + task_type:PersistentTaskType, + parent_task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> TaskId { + if let Some(task) = self.cache.get(&task_type) { + self.connect(parent_task, *task, turbo_tasks); + return *task; + } + if let Some(task) = self.lookup(&task_type, turbo_tasks) { + // a return value from lookup was already added to the cache by the id mapping + self.connect(parent_task, task, turbo_tasks); + return task; + } + + let task = turbo_tasks.get_fresh_task_id(); + let task = task.into(); + let new_task = Task { + active_parents:AtomicU32::new(1), + task_state:Mutex::new(TaskState { + scheduled:true, + memory:Some(MemoryTaskState::new(task, TaskFreshness::NeverExecuted)), + persisted:None, + active:true, + ..Default::default() + }), + task_type:TaskType::Persistent(task_type.clone()), + }; + // SAFETY: It's a fresh task id + unsafe { + self.tasks.insert(*task as usize, new_task); + } + match self.cache.entry(task_type) { + Entry::Occupied(e) => { + let existing_task = *e.into_ref(); + // SAFETY: We are still the only owner of this task and id + unsafe { + self.tasks.remove(*task as usize); + let task = Unused::new_unchecked(task); + turbo_tasks.reuse_task_id(task); + } + self.connect(parent_task, existing_task, turbo_tasks); + existing_task + }, + Entry::Vacant(e) => { + e.insert(task); + self.only_known_to_memory_tasks.insert(task); + #[cfg(feature = "log_scheduled_tasks")] + println!("schedule({task}) in get_or_create_persistent_task"); + turbo_tasks.schedule(task); + self.connect_already_counted(parent_task, task, turbo_tasks); + task + }, + } + } + + fn connect_task( + &self, + _task:TaskId, + _parent_task:TaskId, + _turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + todo!() + } + + fn create_transient_task( + &self, + task_type:TransientTaskType, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> TaskId { + let task = turbo_tasks.get_fresh_task_id(); + let task = task.into(); + let new_task = Task { + active_parents:AtomicU32::new(1), + task_state:Mutex::new(TaskState { + scheduled:true, + memory:Some(MemoryTaskState::new(task, TaskFreshness::NeverExecuted)), + persisted:None, + active:true, + ..Default::default() + }), + task_type:match task_type { + TransientTaskType::Root(r) => TaskType::Root(r), + TransientTaskType::Once(o) => TaskType::Once(Mutex::new(o)), + }, + }; + // SAFETY: It's a fresh task id + unsafe { + self.tasks.insert(*task as usize, new_task); + } + self.only_known_to_memory_tasks.insert(task); + task + } + + fn dispose_root_task(&self, _task:TaskId, _turbo_tasks:&dyn TurboTasksBackendApi) { + todo!() + } +} + +struct MemoryBackendPersistedGraphApi<'a, P:PersistedGraph + 'static> { + backend:&'a MemoryBackendWithPersistedGraph

, + turbo_tasks:&'a dyn TurboTasksBackendApi>, +} + +impl<'a, P:PersistedGraph> PersistedGraphApi for MemoryBackendPersistedGraphApi<'a, P> { + fn get_or_create_task_type(&self, task_type:PersistentTaskType) -> TaskId { + let cache = &self.backend.cache; + // We could try a cache.get first to avoid insert and remove + // but it seems very unlikely that we actually already know the task type + let new_task = Task { + active_parents:AtomicU32::new(0), + task_state:Mutex::new(Default::default()), + task_type:TaskType::Persistent(task_type.clone()), + }; + let task = self.turbo_tasks.get_fresh_task_id(); + let task = task.into(); + // SAFETY: It's a fresh task id + unsafe { + self.backend.tasks.insert(*task as usize, new_task); + } + match cache.entry(task_type) { + Entry::Occupied(e) => { + let value = *e.into_ref(); + // Safety: We didn't store the task id in the cache, we it's still unused + unsafe { + let task = Unused::new_unchecked(task); + self.turbo_tasks.reuse_task_id(task); + } + value + }, + Entry::Vacant(e) => { + e.insert(task); + task + }, + } + } + + fn lookup_task_type(&self, id:TaskId) -> &PersistentTaskType { + let task = self.backend.tasks.get(*id as usize).unwrap(); + match &task.task_type { + TaskType::Persistent(ty) => ty, + _ => panic!("lookup_task_type should only be used for PersistentTaskType"), + } + } +} + +impl MemoryBackendWithPersistedGraph

{ + fn pg_read( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Option<(TaskData, ReadTaskState)> { + self.pg + .read(task, &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } + + fn pg_lookup_one( + &self, + task_type:&PersistentTaskType, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Option { + self.pg + .lookup_one(task_type, &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } + + fn pg_lookup( + &self, + partial_task_type:&PersistentTaskType, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> bool { + self.pg + .lookup( + partial_task_type, + &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }, + ) + .unwrap() + } + + fn pg_is_persisted( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> bool { + self.pg + .is_persisted(task, &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } + + fn pg_persist( + &self, + task:TaskId, + data:TaskData, + state:PersistTaskState, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Option { + self.pg + .persist( + task, + data, + state, + &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }, + ) + .unwrap() + } + + #[must_use] + fn pg_activate_when_needed( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Option { + self.pg + .activate_when_needed( + task, + &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }, + ) + .unwrap() + } + + #[must_use] + fn pg_deactivate_when_needed( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Option { + self.pg + .deactivate_when_needed( + task, + &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }, + ) + .unwrap() + } + + #[must_use] + fn pg_set_externally_active( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> bool { + self.pg + .set_externally_active( + task, + &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }, + ) + .unwrap() + } + + #[must_use] + fn pg_unset_externally_active( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> bool { + self.pg + .unset_externally_active( + task, + &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }, + ) + .unwrap() + } + + #[must_use] + fn pg_make_dirty( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> bool { + self.pg + .make_dirty(task, &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } + + #[must_use] + fn pg_make_dependent_dirty( + &self, + vc:RawVc, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Vec { + self.pg + .make_dependent_dirty(vc, &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } + + fn pg_make_clean( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) { + self.pg + .make_clean(task, &MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } + + // FIXME + #[allow(dead_code)] + #[must_use] + fn pg_remove_outdated_externally_active( + &self, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Vec { + self.pg + .remove_outdated_externally_active(&MemoryBackendPersistedGraphApi { + backend:self, + turbo_tasks, + }) + .unwrap() + } + + #[must_use] + fn pg_get_active_external_tasks( + &self, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Vec { + self.pg + .get_active_external_tasks(&MemoryBackendPersistedGraphApi { + backend:self, + turbo_tasks, + }) + .unwrap() + } + + #[must_use] + fn pg_get_dirty_active_tasks( + &self, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> Vec { + self.pg + .get_dirty_active_tasks(&MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } + + #[must_use] + fn pg_get_pending_active_update( + &self, + turbo_tasks:&dyn TurboTasksBackendApi>, + ) -> (Vec, Vec) { + self.pg + .get_pending_active_update(&MemoryBackendPersistedGraphApi { + backend:self, + turbo_tasks, + }) + .unwrap() + } + + fn pg_stop(&self, turbo_tasks:&dyn TurboTasksBackendApi>) { + self.pg + .stop(&MemoryBackendPersistedGraphApi { backend:self, turbo_tasks }) + .unwrap() + } +} diff --git a/crates/turbo-tasks-memory/Source/output.rs b/crates/turbo-tasks-memory/Source/output.rs new file mode 100644 index 0000000000000..8c06fa393a788 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/output.rs @@ -0,0 +1,113 @@ +use std::{ + borrow::Cow, + fmt::{Debug, Display}, + mem::take, +}; + +use anyhow::{Error, Result, anyhow}; +use turbo_tasks::{RawVc, TaskId, TaskIdSet, TurboTasksBackendApi, util::SharedError}; + +use crate::MemoryBackend; + +#[derive(Default, Debug)] +pub struct Output { + pub(crate) content:OutputContent, + updates:u32, + pub(crate) dependent_tasks:TaskIdSet, +} + +#[derive(Clone, Debug, Default)] +pub enum OutputContent { + #[default] + Empty, + Link(RawVc), + Error(SharedError), + Panic(Option>), +} + +impl Display for OutputContent { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + OutputContent::Empty => write!(f, "empty"), + OutputContent::Link(raw_vc) => write!(f, "link {}", raw_vc), + OutputContent::Error(err) => write!(f, "error {}", err), + OutputContent::Panic(Some(message)) => write!(f, "panic {}", message), + OutputContent::Panic(None) => write!(f, "panic"), + } + } +} + +impl Output { + pub fn read(&mut self, reader:TaskId) -> Result { + self.dependent_tasks.insert(reader); + self.read_untracked() + } + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + pub fn read_untracked(&mut self) -> Result { + match &self.content { + OutputContent::Empty => Err(anyhow!("Output is empty")), + OutputContent::Error(err) => Err(anyhow::Error::new(err.clone())), + OutputContent::Link(raw_vc) => Ok(*raw_vc), + OutputContent::Panic(Some(message)) => Err(anyhow!("A task panicked: {message}")), + OutputContent::Panic(None) => Err(anyhow!("A task panicked")), + } + } + + pub fn link(&mut self, target:RawVc, turbo_tasks:&dyn TurboTasksBackendApi) { + debug_assert!(*self != target); + self.assign(OutputContent::Link(target), turbo_tasks) + } + + pub fn error(&mut self, error:Error, turbo_tasks:&dyn TurboTasksBackendApi) { + self.content = OutputContent::Error(SharedError::new(error)); + self.updates += 1; + // notify + if !self.dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(&take(&mut self.dependent_tasks)); + } + } + + pub fn panic( + &mut self, + message:Option>, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.content = OutputContent::Panic(message); + self.updates += 1; + // notify + if !self.dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(&take(&mut self.dependent_tasks)); + } + } + + pub fn assign( + &mut self, + content:OutputContent, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.content = content; + self.updates += 1; + // notify + if !self.dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(&take(&mut self.dependent_tasks)); + } + } + + pub fn gc_drop(self, turbo_tasks:&dyn TurboTasksBackendApi) { + // notify + if !self.dependent_tasks.is_empty() { + turbo_tasks.schedule_notify_tasks_set(&self.dependent_tasks); + } + } +} + +impl PartialEq for Output { + fn eq(&self, rhs:&RawVc) -> bool { + match &self.content { + OutputContent::Link(old_target) => old_target == rhs, + OutputContent::Empty | OutputContent::Error(_) | OutputContent::Panic(_) => false, + } + } +} diff --git a/crates/turbo-tasks-memory/Source/task.rs b/crates/turbo-tasks-memory/Source/task.rs new file mode 100644 index 0000000000000..f4efdc2ef9812 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/task.rs @@ -0,0 +1,1665 @@ +use std::{ + borrow::Cow, + cell::RefCell, + fmt::{self, Debug, Display, Formatter}, + future::Future, + hash::{BuildHasherDefault, Hash}, + mem::{replace, take}, + pin::Pin, + sync::{Arc, atomic::AtomicU32}, + time::Duration, +}; + +use anyhow::Result; +use auto_hash_map::{AutoMap, AutoSet}; +use nohash_hasher::BuildNoHashHasher; +use parking_lot::{Mutex, RwLock}; +use rustc_hash::FxHasher; +use smallvec::SmallVec; +use tokio::task_local; +use tracing::Span; +use turbo_prehash::PreHashed; +use turbo_tasks::{ + CellId, + Invalidator, + NativeFunction, + RawVc, + TaskId, + TaskIdSet, + TraitType, + TraitTypeId, + TurboTasksBackendApi, + ValueTypeId, + backend::{PersistentTaskType, TaskExecutionSpec}, + event::{Event, EventListener}, + get_invalidator, + registry, +}; + +use crate::{ + MemoryBackend, + aggregation::{ + AggregationDataGuard, + PreparedOperation, + aggregation_data, + handle_new_edge, + prepare_aggregation_data, + query_root_info, + }, + cell::Cell, + gc::{GcQueue, GcTaskState}, + output::{Output, OutputContent}, + task::aggregation::{TaskAggregationContext, TaskChange}, +}; + +pub type NativeTaskFuture = Pin> + Send>>; +pub type NativeTaskFn = Box NativeTaskFuture + Send + Sync>; + +mod aggregation; +mod meta_state; + +#[derive(Hash, Copy, Clone, PartialEq, Eq)] +pub enum TaskDependency { + Output(TaskId), + Cell(TaskId, CellId), + Collectibles(TaskId, TraitTypeId), +} +pub type TaskDependencySet = AutoSet>; + +task_local! { + /// Cells/Outputs/Collectibles that are read during task execution + /// These will be stored as dependencies when the execution has finished + pub(crate) static DEPENDENCIES_TO_TRACK: RefCell; +} + +type OnceTaskFn = Mutex> + Send + 'static>>>>; + +/// Different Task types +enum TaskType { + // Note: double boxed to reduce TaskType size + /// A root task that will track dependencies and re-execute when + /// dependencies change. Task will eventually settle to the correct + /// execution. + Root(Box), + + // Note: double boxed to reduce TaskType size + /// A single root task execution. It won't track dependencies. + /// Task will definitely include all invalidations that happened before the + /// start of the task. It may or may not include invalidations that + /// happened after that. It may see these invalidations partially + /// applied. + Once(Box), + + /// A normal persistent task + Persistent { ty:Arc> }, +} + +enum TaskTypeForDescription { + Root, + Once, + Persistent(Arc>), +} + +impl TaskTypeForDescription { + fn from(task_type:&TaskType) -> Self { + match task_type { + TaskType::Root(..) => Self::Root, + TaskType::Once(..) => Self::Once, + TaskType::Persistent { ty, .. } => Self::Persistent(ty.clone()), + } + } +} + +impl Debug for TaskType { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { + match self { + Self::Root(..) => f.debug_tuple("Root").finish(), + Self::Once(..) => f.debug_tuple("Once").finish(), + Self::Persistent { ty, .. } => Debug::fmt(ty, f), + } + } +} + +impl Display for TaskType { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { + match self { + Self::Root(..) => f.debug_tuple("Root").finish(), + Self::Once(..) => f.debug_tuple("Once").finish(), + Self::Persistent { ty, .. } => Display::fmt(ty, f), + } + } +} + +#[derive(Default)] +enum PrepareTaskType { + #[default] + None, + Resolve(&'static NativeFunction), + ResolveTrait(&'static TraitType), + Native(&'static NativeFunction, NativeTaskFn), +} + +/// A Task is an instantiation of an Function with some arguments. +/// The same combinations of Function and arguments usually results in the same +/// Task instance. +pub struct Task { + id:TaskId, + /// The type of the task + ty:TaskType, + /// The mutable state of the task + /// Unset state is equal to a Dirty task that has not been executed yet + state:RwLock, + /// Atomic in progress counter for graph modification + graph_modification_in_progress_counter:AtomicU32, +} + +impl Debug for Task { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { + let mut result = f.debug_struct("Task"); + result.field("id", &self.id); + result.field("ty", &self.ty); + if let Some(state) = self.try_state() { + match state { + TaskMetaStateReadGuard::Full(state) => { + result.field("state", &Task::state_string(&state)); + }, + TaskMetaStateReadGuard::Partial(_) => { + result.field("state", &"partial"); + }, + TaskMetaStateReadGuard::Unloaded => { + result.field("state", &"unloaded"); + }, + } + } + result.finish() + } +} + +/// The full state of a [Task], it includes all information. +struct TaskState { + aggregation_node:TaskAggregationNode, + + // TODO using a Atomic might be possible here + /// More flags of task state, where not all combinations are possible. + /// dirty, scheduled, in progress + state_type:TaskStateType, + + /// true, when the task has state and that can't be dropped + stateful:bool, + + /// Children are only modified from execution + children:TaskIdSet, + + /// Collectibles are only modified from execution + collectibles:MaybeCollectibles, + + /// Preparations done for the task type with the bound arguments, e. g. + /// argument validation + prepared_type:PrepareTaskType, + + output:Output, + cells:AutoMap, BuildNoHashHasher>, + + // GC state: + gc:GcTaskState, +} + +impl TaskState { + fn new(description:impl Fn() -> String + Send + Sync + 'static) -> Self { + Self { + aggregation_node:TaskAggregationNode::new(), + state_type:Dirty { + event:Event::new(move || format!("TaskState({})::event", description())), + outdated_dependencies:Default::default(), + }, + stateful:false, + children:Default::default(), + collectibles:Default::default(), + output:Default::default(), + prepared_type:PrepareTaskType::None, + cells:Default::default(), + gc:Default::default(), + #[cfg(feature = "track_wait_dependencies")] + last_waiting_task:Default::default(), + } + } + + fn new_scheduled(description:impl Fn() -> String + Send + Sync + 'static) -> Self { + Self { + aggregation_node:TaskAggregationNode::new(), + state_type:Scheduled { + event:Event::new(move || format!("TaskState({})::event", description())), + outdated_dependencies:Default::default(), + }, + stateful:false, + children:Default::default(), + collectibles:Default::default(), + output:Default::default(), + prepared_type:PrepareTaskType::None, + cells:Default::default(), + gc:Default::default(), + #[cfg(feature = "track_wait_dependencies")] + last_waiting_task:Default::default(), + } + } +} + +/// The partial task state. It's equal to a full TaskState with state = Dirty +/// and all other fields empty. It looks like a dirty task that has not been +/// executed yet. The task might still referenced by some parents tasks. +/// A Task can get into this state when it is unloaded by garbage collection, +/// but is still attached to parents and aggregated. +struct PartialTaskState { + aggregation_node:TaskAggregationNode, +} + +impl PartialTaskState { + fn into_full(self, description:impl Fn() -> String + Send + Sync + 'static) -> TaskState { + TaskState { + aggregation_node:self.aggregation_node, + state_type:Dirty { + event:Event::new(move || format!("TaskState({})::event", description())), + outdated_dependencies:Default::default(), + }, + stateful:false, + children:Default::default(), + collectibles:Default::default(), + prepared_type:PrepareTaskType::None, + output:Default::default(), + cells:Default::default(), + gc:Default::default(), + } + } +} + +/// A fully unloaded task state. It's equal to a partial task state without +/// being referenced by any parent. This state is stored inlined instead of in a +/// [Box] to reduce the memory consumption. Make sure to not add more fields +/// than the size of a [Box]. +struct UnloadedTaskState {} + +#[cfg(test)] +#[test] +fn test_unloaded_task_state_size() { + assert!(std::mem::size_of::() <= std::mem::size_of::>()); +} + +impl UnloadedTaskState { + fn into_full(self, description:impl Fn() -> String + Send + Sync + 'static) -> TaskState { + TaskState { + aggregation_node:TaskAggregationNode::new(), + state_type:Dirty { + event:Event::new(move || format!("TaskState({})::event", description())), + outdated_dependencies:Default::default(), + }, + stateful:false, + children:Default::default(), + collectibles:Default::default(), + prepared_type:PrepareTaskType::None, + output:Default::default(), + cells:Default::default(), + gc:Default::default(), + } + } + + fn into_partial(self) -> PartialTaskState { + PartialTaskState { aggregation_node:TaskAggregationNode::new() } + } +} + +/// The collectibles of a task. +type Collectibles = AutoMap<(TraitTypeId, RawVc), i32>; + +/// Keeps track of emitted and unemitted collectibles and the +/// read_collectibles tasks. Defaults to None to avoid allocating memory when no +/// collectibles are emitted or read. +#[derive(Default)] +struct MaybeCollectibles { + inner:Option>, +} + +impl MaybeCollectibles { + /// Consumes the collectibles (if any) and return them. + fn take_collectibles(&mut self) -> Option { + self.inner.as_mut().map(|boxed| take(&mut **boxed)) + } + + /// Consumes the collectibles (if any) and return them. + fn into_inner(self) -> Option> { self.inner } + + /// Returns a reference to the collectibles (if any). + fn as_ref(&self) -> Option<&Collectibles> { + if let Some(inner) = &self.inner { Some(&**inner) } else { None } + } + + /// Emits a collectible. + fn emit(&mut self, trait_type:TraitTypeId, value:RawVc) { + let value = self.inner.get_or_insert_default().entry((trait_type, value)).or_default(); + *value += 1; + } + + /// Unemits a collectible. + fn unemit(&mut self, trait_type:TraitTypeId, value:RawVc, count:u32) { + let value = self.inner.get_or_insert_default().entry((trait_type, value)).or_default(); + *value -= count as i32; + } +} + +enum TaskStateType { + /// Ready + /// + /// on invalidation this will move to Dirty or Scheduled depending on active + /// flag + Done { + /// Cells/Outputs/Collectibles that the task has read during execution. + /// The Task will keep these tasks alive as invalidations that happen + /// there might affect this task. + /// + /// This back-edge is [Cell] `dependent_tasks`, which is a weak edge. + dependencies:TaskDependencySet, + }, + + /// Execution is invalid, but not yet scheduled + /// + /// on activation this will move to Scheduled + Dirty { event:Event, outdated_dependencies:TaskDependencySet }, + + /// Execution is invalid and scheduled + /// + /// on start this will move to InProgress or Dirty depending on active flag + Scheduled { event:Event, outdated_dependencies:TaskDependencySet }, + + /// Execution is happening + /// + /// on finish this will move to Done + /// + /// on invalidation this will move to InProgressDirty + InProgress { + event:Event, + count_as_finished:bool, + /// Children that need to be disconnected once leaving this state + #[cfg(feature = "lazy_remove_children")] + outdated_children:TaskIdSet, + outdated_collectibles:MaybeCollectibles, + }, + + /// Invalid execution is happening + /// + /// on finish this will move to Scheduled + InProgressDirty { event:Event }, +} + +use TaskStateType::*; + +use self::{ + aggregation::{ActiveQuery, RootType, TaskAggregationNode, TaskGuard}, + meta_state::{ + FullTaskWriteGuard, + TaskMetaState, + TaskMetaStateReadGuard, + TaskMetaStateWriteGuard, + }, +}; + +impl Task { + pub(crate) fn new_persistent(id:TaskId, task_type:Arc>) -> Self { + let ty = TaskType::Persistent { ty:task_type }; + let description = Self::get_event_description_static(id, &ty); + Self { + id, + ty, + state:RwLock::new(TaskMetaState::Full(Box::new(TaskState::new(description)))), + graph_modification_in_progress_counter:AtomicU32::new(0), + } + } + + pub(crate) fn new_root( + id:TaskId, + functor:impl Fn() -> NativeTaskFuture + Sync + Send + 'static, + ) -> Self { + let ty = TaskType::Root(Box::new(Box::new(functor))); + let description = Self::get_event_description_static(id, &ty); + Self { + id, + ty, + state:RwLock::new(TaskMetaState::Full(Box::new(TaskState::new_scheduled(description)))), + graph_modification_in_progress_counter:AtomicU32::new(0), + } + } + + pub(crate) fn new_once( + id:TaskId, + functor:impl Future> + Send + 'static, + ) -> Self { + let ty = TaskType::Once(Box::new(Mutex::new(Some(Box::pin(functor))))); + let description = Self::get_event_description_static(id, &ty); + Self { + id, + ty, + state:RwLock::new(TaskMetaState::Full(Box::new(TaskState::new_scheduled(description)))), + graph_modification_in_progress_counter:AtomicU32::new(0), + } + } + + pub(crate) fn is_pure(&self) -> bool { + match &self.ty { + TaskType::Persistent { .. } => true, + TaskType::Root(_) => false, + TaskType::Once(_) => false, + } + } + + pub(crate) fn set_root( + id:TaskId, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + { + Self::set_root_type( + &aggregation_context, + &mut aggregation_context.aggregation_data(id), + RootType::Root, + ); + } + aggregation_context.apply_queued_updates(); + } + + pub(crate) fn set_once( + id:TaskId, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + { + let mut aggregation_guard = aggregation_context.aggregation_data(id); + Self::set_root_type(&aggregation_context, &mut aggregation_guard, RootType::Once); + } + aggregation_context.apply_queued_updates(); + } + + fn set_root_type( + aggregation_context:&TaskAggregationContext, + aggregation:&mut AggregationDataGuard>, + root_type:RootType, + ) { + aggregation.root_type = Some(root_type); + let dirty_tasks = aggregation + .dirty_tasks + .iter() + .filter_map(|(&id, &count)| (count > 0).then_some(id)); + let mut tasks_to_schedule = aggregation_context.dirty_tasks_to_schedule.lock(); + tasks_to_schedule.get_or_insert_default().extend(dirty_tasks); + } + + pub(crate) fn unset_root( + id:TaskId, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + { + aggregation_context.aggregation_data(id).root_type = None; + } + aggregation_context.apply_queued_updates(); + } + + pub(crate) fn get_function_name(&self) -> Option> { + if let TaskType::Persistent { ty, .. } = &self.ty { + match &***ty { + PersistentTaskType::Native(native_fn, _) + | PersistentTaskType::ResolveNative(native_fn, _) => { + return Some(Cow::Borrowed(®istry::get_function(*native_fn).name)); + }, + PersistentTaskType::ResolveTrait(trait_id, fn_name, _) => { + return Some( + format!("{}::{}", registry::get_trait(*trait_id).name, fn_name).into(), + ); + }, + } + } + None + } + + pub(crate) fn get_description(&self) -> String { + Self::format_description(&TaskTypeForDescription::from(&self.ty), self.id) + } + + fn format_description(ty:&TaskTypeForDescription, id:TaskId) -> String { + match ty { + TaskTypeForDescription::Root => format!("[{}] root", id), + TaskTypeForDescription::Once => format!("[{}] once", id), + TaskTypeForDescription::Persistent(ty) => { + match &***ty { + PersistentTaskType::Native(native_fn, _) => { + format!("[{}] {}", id, registry::get_function(*native_fn).name) + }, + PersistentTaskType::ResolveNative(native_fn, _) => { + format!("[{}] [resolve] {}", id, registry::get_function(*native_fn).name) + }, + PersistentTaskType::ResolveTrait(trait_type, fn_name, _) => { + format!( + "[{}] [resolve trait] {} in trait {}", + id, + fn_name, + registry::get_trait(*trait_type).name + ) + }, + } + }, + } + } + + fn get_event_description_static(id:TaskId, ty:&TaskType) -> impl Fn() -> String + Send + Sync { + let ty = TaskTypeForDescription::from(ty); + move || Self::format_description(&ty, id) + } + + fn get_event_description(&self) -> impl Fn() -> String + Send + Sync { + Self::get_event_description_static(self.id, &self.ty) + } + + pub(crate) fn remove_dependency( + dep:TaskDependency, + reader:TaskId, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + match dep { + TaskDependency::Output(task) => { + backend.with_task(task, |task| { + task.with_output_mut_if_available(|output| { + output.dependent_tasks.remove(&reader); + }); + }); + }, + TaskDependency::Cell(task, index) => { + backend.with_task(task, |task| { + task.with_cell_mut_if_available(index, |cell| { + cell.remove_dependent_task(reader); + }); + }); + }, + TaskDependency::Collectibles(task, trait_type) => { + let aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let mut aggregation = aggregation_context.aggregation_data(task); + aggregation.remove_collectible_dependent_task(trait_type, reader); + }, + } + } + + #[cfg(not(feature = "report_expensive"))] + fn clear_dependencies( + &self, + dependencies:TaskDependencySet, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + for dep in dependencies.into_iter() { + Task::remove_dependency(dep, self.id, backend, turbo_tasks); + } + } + + #[cfg(feature = "report_expensive")] + fn clear_dependencies( + &self, + dependencies:TaskDependencySet, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + use std::time::Instant; + + use turbo_tasks::util::FormatDuration; + let start = Instant::now(); + + let count = dependencies.len(); + + for dep in dependencies.into_iter() { + Task::remove_dependency(dep, self.id, backend, turbo_tasks); + } + let elapsed = start.elapsed(); + if elapsed.as_millis() >= 10 || count > 10000 { + println!("clear_dependencies({}) took {}: {:?}", count, FormatDuration(elapsed), self); + } + } + + fn state(&self) -> TaskMetaStateReadGuard<'_> { self.state.read().into() } + + fn try_state(&self) -> Option> { + self.state.try_read().map(|guard| guard.into()) + } + + fn state_mut(&self) -> TaskMetaStateWriteGuard<'_> { self.state.write().into() } + + fn full_state_mut(&self) -> FullTaskWriteGuard<'_> { + TaskMetaStateWriteGuard::full_from(self.state.write(), self) + } + + #[allow(dead_code, reason = "We need this in future")] + fn partial_state_mut(&self) -> TaskMetaStateWriteGuard<'_> { + TaskMetaStateWriteGuard::partial_from(self.state.write()) + } + + pub(crate) fn execute( + self: &Task, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Option { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let dependencies; + let (future, span) = { + let mut state = self.full_state_mut(); + #[cfg(not(feature = "lazy_remove_children"))] + let remove_job; + match state.state_type { + Done { .. } | InProgress { .. } | InProgressDirty { .. } => { + // should not start in this state + return None; + }, + Scheduled { ref mut event, ref mut outdated_dependencies } => { + let event = event.take(); + dependencies = take(outdated_dependencies); + let outdated_children = take(&mut state.children); + let outdated_collectibles = take(&mut state.collectibles); + #[cfg(not(feature = "lazy_remove_children"))] + { + remove_job = state + .aggregation_node + .remove_children_job(&aggregation_context, outdated_children); + } + state.state_type = InProgress { + event, + count_as_finished:false, + #[cfg(feature = "lazy_remove_children")] + outdated_children, + outdated_collectibles, + }; + }, + Dirty { .. } => { + let state_type = Task::state_string(&state); + panic!("{:?} execution started in unexpected state {}", self, state_type) + }, + }; + let result = self.make_execution_future(state, backend, turbo_tasks); + #[cfg(not(feature = "lazy_remove_children"))] + { + remove_job(); + } + #[allow(clippy::let_and_return)] + result + }; + aggregation_context.apply_queued_updates(); + self.clear_dependencies(dependencies, backend, turbo_tasks); + Some(TaskExecutionSpec { future, span }) + } + + /// Prepares task execution and returns a future that will execute the task. + fn make_execution_future( + self: &Task, + mut state:FullTaskWriteGuard<'_>, + _backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> (Pin> + Send>>, Span) { + match &self.ty { + TaskType::Root(bound_fn) => { + drop(state); + (bound_fn(), tracing::trace_span!("turbo_tasks::root_task")) + }, + TaskType::Once(mutex) => { + drop(state); + ( + mutex.lock().take().expect("Task can only be executed once"), + tracing::trace_span!("turbo_tasks::once_task"), + ) + }, + TaskType::Persistent { ty, .. } => { + match &***ty { + PersistentTaskType::Native(native_fn, inputs) => { + let result = + if let PrepareTaskType::Native(func, bound_fn) = &state.prepared_type { + let span = func.span(); + let entered = span.enter(); + let future = bound_fn(); + drop(entered); + (future, span) + } else { + let func = registry::get_function(*native_fn); + let span = func.span(); + let entered = span.enter(); + let bound_fn = func.bind(inputs); + let future = bound_fn(); + drop(entered); + state.prepared_type = PrepareTaskType::Native(func, bound_fn); + (future, span) + }; + drop(state); + result + }, + PersistentTaskType::ResolveNative(ref native_fn_id, inputs) => { + let native_fn_id = *native_fn_id; + let span = if let &PrepareTaskType::Resolve(func) = &state.prepared_type { + func.resolve_span() + } else { + let func = registry::get_function(native_fn_id); + state.prepared_type = PrepareTaskType::Resolve(func); + func.resolve_span() + }; + drop(state); + let entered = span.enter(); + let inputs = inputs.clone(); + let turbo_tasks = turbo_tasks.pin(); + let future = Box::pin(PersistentTaskType::run_resolve_native( + native_fn_id, + inputs, + turbo_tasks, + )); + drop(entered); + (future, span) + }, + PersistentTaskType::ResolveTrait(trait_type_id, name, inputs) => { + let trait_type_id = *trait_type_id; + let span = if let PrepareTaskType::ResolveTrait(trait_type) = + &state.prepared_type + { + trait_type.resolve_span(name) + } else { + let trait_type = registry::get_trait(trait_type_id); + state.prepared_type = PrepareTaskType::ResolveTrait(trait_type); + trait_type.resolve_span(name) + }; + drop(state); + let entered = span.enter(); + let name = name.clone(); + let inputs = inputs.clone(); + let turbo_tasks = turbo_tasks.pin(); + let future = Box::pin(PersistentTaskType::run_resolve_trait( + trait_type_id, + name, + inputs, + turbo_tasks, + )); + drop(entered); + (future, span) + }, + } + }, + } + } + + pub(crate) fn mark_as_finished( + &self, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let TaskMetaStateWriteGuard::Full(mut state) = self.state_mut() else { + return; + }; + let TaskStateType::InProgress { + ref mut count_as_finished, + #[cfg(feature = "lazy_remove_children")] + ref mut outdated_children, + ref mut outdated_collectibles, + .. + } = state.state_type + else { + return; + }; + if *count_as_finished { + return; + } + *count_as_finished = true; + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + { + #[cfg(feature = "lazy_remove_children")] + let outdated_children = take(outdated_children); + let outdated_collectibles = outdated_collectibles.take_collectibles(); + + let mut change = TaskChange { + unfinished:-1, + #[cfg(feature = "track_unfinished")] + unfinished_tasks_update:vec![(self.id, -1)], + ..Default::default() + }; + if let Some(collectibles) = outdated_collectibles { + for ((trait_type, value), count) in collectibles.into_iter() { + change.collectibles.push((trait_type, value, -count)); + } + } + let change_job = state.aggregation_node.apply_change(&aggregation_context, change); + #[cfg(feature = "lazy_remove_children")] + let remove_job = if outdated_children.is_empty() { + None + } else { + Some(state.aggregation_node.handle_lost_edges( + &aggregation_context, + &self.id, + outdated_children, + )) + }; + drop(state); + change_job.apply(&aggregation_context); + #[cfg(feature = "lazy_remove_children")] + remove_job.apply(&aggregation_context); + } + aggregation_context.apply_queued_updates(); + } + + pub(crate) fn execution_result( + &self, + result:Result, Option>>, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut state = self.full_state_mut(); + match state.state_type { + InProgress { .. } => { + match result { + Ok(Ok(result)) => { + if state.output != result { + if cfg!(feature = "print_task_invalidation") + && !matches!(state.output.content, OutputContent::Empty) + { + println!( + "Task {{ id: {}, name: {} }} invalidates:", + *self.id, self.ty + ); + for dep in state.output.dependent_tasks.iter() { + backend.with_task(*dep, |task| { + println!( + "\tTask {{ id: {}, name: {} }}", + *task.id, task.ty + ); + }); + } + } + state.output.link(result, turbo_tasks) + } + }, + Ok(Err(mut err)) => { + if let Some(name) = self.get_function_name() { + err = err.context(format!("Execution of {} failed", name)); + } + state.output.error(err, turbo_tasks) + }, + Err(message) => state.output.panic(message, turbo_tasks), + } + }, + InProgressDirty { .. } => { + // We don't want to assign the output cell here + // as we want to avoid unnecessary updates + // TODO maybe this should be controlled by a heuristic + }, + Dirty { .. } | Scheduled { .. } | Done { .. } => { + panic!( + "Task execution completed in unexpected state {}", + Task::state_string(&state) + ) + }, + }; + } + + #[must_use] + pub(crate) fn execution_completed( + &self, + duration:Duration, + memory_usage:usize, + generation:u32, + stateful:bool, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> bool { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let mut schedule_task = false; + { + let mut change_job = None; + #[cfg(feature = "lazy_remove_children")] + let mut remove_job = None; + let mut dependencies = DEPENDENCIES_TO_TRACK.with(|deps| deps.take()); + { + let mut state = self.full_state_mut(); + + state.gc.execution_completed(duration, memory_usage, generation); + match state.state_type { + InProgress { + ref mut event, + count_as_finished, + #[cfg(feature = "lazy_remove_children")] + ref mut outdated_children, + ref mut outdated_collectibles, + } => { + let event = event.take(); + #[cfg(feature = "lazy_remove_children")] + let outdated_children = take(outdated_children); + let outdated_collectibles = outdated_collectibles.take_collectibles(); + let mut dependencies = take(&mut dependencies); + if !backend.has_gc() { + // This will stay here for longer, so make sure to not consume too much + // memory + dependencies.shrink_to_fit(); + for cells in state.cells.values_mut() { + cells.shrink_to_fit(); + } + state.cells.shrink_to_fit(); + } + state.stateful = stateful; + state.state_type = Done { dependencies }; + if !count_as_finished { + let mut change = TaskChange { + unfinished:-1, + #[cfg(feature = "track_unfinished")] + unfinished_tasks_update:vec![(self.id, -1)], + ..Default::default() + }; + if let Some(collectibles) = outdated_collectibles { + for ((trait_type, value), count) in collectibles.into_iter() { + change.collectibles.push((trait_type, value, -count)); + } + } + change_job = + state.aggregation_node.apply_change(&aggregation_context, change); + } + #[cfg(feature = "lazy_remove_children")] + if !outdated_children.is_empty() { + remove_job = state.aggregation_node.handle_lost_edges( + &aggregation_context, + &self.id, + outdated_children, + ); + } + event.notify(usize::MAX); + }, + InProgressDirty { ref mut event } => { + let event = event.take(); + state.state_type = + Scheduled { event, outdated_dependencies:Default::default() }; + schedule_task = true; + }, + Dirty { .. } | Scheduled { .. } | Done { .. } => { + panic!( + "Task execution completed in unexpected state {}", + Task::state_string(&state) + ) + }, + }; + } + if !dependencies.is_empty() { + self.clear_dependencies(dependencies, backend, turbo_tasks); + } + change_job.apply(&aggregation_context); + #[cfg(feature = "lazy_remove_children")] + remove_job.apply(&aggregation_context); + } + if let TaskType::Once(_) = self.ty { + // unset the root type, so tasks below are no longer active + aggregation_context.aggregation_data(self.id).root_type = None; + } + aggregation_context.apply_queued_updates(); + + schedule_task + } + + fn make_dirty( + &self, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.make_dirty_internal(false, backend, turbo_tasks); + } + + fn make_dirty_internal( + &self, + force_schedule:bool, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + if let TaskType::Once(_) = self.ty { + // once task won't become dirty + return; + } + + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let active = query_root_info(&aggregation_context, ActiveQuery::default(), self.id); + + let state = if force_schedule { + TaskMetaStateWriteGuard::Full(self.full_state_mut()) + } else { + self.state_mut() + }; + if let TaskMetaStateWriteGuard::Full(mut state) = state { + match state.state_type { + Scheduled { .. } | InProgressDirty { .. } => { + // already dirty + drop(state); + }, + Dirty { ref mut outdated_dependencies, .. } => { + if force_schedule { + let description = self.get_event_description(); + state.state_type = Scheduled { + event:Event::new(move || { + format!("TaskState({})::event", description()) + }), + outdated_dependencies:take(outdated_dependencies), + }; + let change_job = state.aggregation_node.apply_change( + &aggregation_context, + TaskChange { + dirty_tasks_update:vec![(self.id, -1)], + ..Default::default() + }, + ); + drop(state); + change_job.apply(&aggregation_context); + turbo_tasks.schedule(self.id); + } else { + // already dirty + drop(state); + } + }, + Done { ref mut dependencies } => { + let outdated_dependencies = take(dependencies); + // add to dirty lists and potentially schedule + let description = self.get_event_description(); + let should_schedule = force_schedule || active; + if should_schedule { + let change_job = state.aggregation_node.apply_change( + &aggregation_context, + TaskChange { + unfinished:1, + #[cfg(feature = "track_unfinished")] + unfinished_tasks_update:vec![(self.id, 1)], + ..Default::default() + }, + ); + state.state_type = Scheduled { + event:Event::new(move || { + format!("TaskState({})::event", description()) + }), + outdated_dependencies, + }; + drop(state); + change_job.apply(&aggregation_context); + + if cfg!(feature = "print_task_invalidation") { + println!("invalidated Task {{ id: {}, name: {} }}", *self.id, self.ty); + } + turbo_tasks.schedule(self.id); + } else { + let change_job = state.aggregation_node.apply_change( + &aggregation_context, + TaskChange { + unfinished:1, + #[cfg(feature = "track_unfinished")] + unfinished_tasks_update:vec![(self.id, 1)], + dirty_tasks_update:vec![(self.id, 1)], + ..Default::default() + }, + ); + state.state_type = Dirty { + event:Event::new(move || { + format!("TaskState({})::event", description()) + }), + outdated_dependencies, + }; + drop(state); + change_job.apply(&aggregation_context); + } + }, + InProgress { + ref mut event, + count_as_finished, + #[cfg(feature = "lazy_remove_children")] + ref mut outdated_children, + ref mut outdated_collectibles, + } => { + let event = event.take(); + #[cfg(feature = "lazy_remove_children")] + let outdated_children = take(outdated_children); + let outdated_collectibles = outdated_collectibles.take_collectibles(); + let change = if count_as_finished { + let mut change = TaskChange { + unfinished:1, + #[cfg(feature = "track_unfinished")] + unfinished_tasks_update:vec![(self.id, 1)], + ..Default::default() + }; + if let Some(collectibles) = outdated_collectibles { + for ((trait_type, value), count) in collectibles.into_iter() { + change.collectibles.push((trait_type, value, -count)); + } + } + Some(change) + } else if let Some(collectibles) = outdated_collectibles { + let mut change = TaskChange::default(); + for ((trait_type, value), count) in collectibles.into_iter() { + change.collectibles.push((trait_type, value, -count)); + } + Some(change) + } else { + None + }; + let change_job = change.and_then(|change| { + state.aggregation_node.apply_change(&aggregation_context, change) + }); + #[cfg(feature = "lazy_remove_children")] + let remove_job = state.aggregation_node.handle_lost_edges( + &aggregation_context, + &self.id, + outdated_children, + ); + state.state_type = InProgressDirty { event }; + drop(state); + change_job.apply(&aggregation_context); + #[cfg(feature = "lazy_remove_children")] + remove_job.apply(&aggregation_context); + }, + } + } + aggregation_context.apply_queued_updates(); + } + + pub(crate) fn schedule_when_dirty_from_aggregation( + &self, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut state = self.full_state_mut(); + if let TaskStateType::Dirty { ref mut event, ref mut outdated_dependencies } = + state.state_type + { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + state.state_type = + Scheduled { event:event.take(), outdated_dependencies:take(outdated_dependencies) }; + let job = state.aggregation_node.apply_change( + &aggregation_context, + TaskChange { dirty_tasks_update:vec![(self.id, -1)], ..Default::default() }, + ); + drop(state); + turbo_tasks.schedule(self.id); + job.apply(&aggregation_context); + aggregation_context.apply_queued_updates(); + } + } + + pub(crate) fn add_dependency_to_current(dep:TaskDependency) { + DEPENDENCIES_TO_TRACK.with(|list| { + let mut list = list.borrow_mut(); + list.insert(dep); + }) + } + + /// Get an [Invalidator] that can be used to invalidate the current [Task] + /// based on external events. + pub fn get_invalidator() -> Invalidator { get_invalidator() } + + /// Called by the [Invalidator]. Invalidate the [Task]. When the task is + /// active it will be scheduled for execution. + pub(crate) fn invalidate( + &self, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + self.make_dirty(backend, turbo_tasks) + } + + /// Called when the task need to be recomputed because a gc'ed cell was + /// read. + pub(crate) fn recompute( + &self, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let _span = tracing::trace_span!("turbo_tasks::recompute", id = *self.id).entered(); + self.make_dirty_internal(true, backend, turbo_tasks) + } + + /// Access to the output cell. + pub(crate) fn with_output_mut_if_available( + &self, + func:impl FnOnce(&mut Output) -> T, + ) -> Option { + if let TaskMetaStateWriteGuard::Full(mut state) = self.state_mut() { + Some(func(&mut state.output)) + } else { + None + } + } + + /// Access to a cell. + pub(crate) fn with_cell_mut( + &self, + index:CellId, + gc_queue:Option<&GcQueue>, + func:impl FnOnce(&mut Cell) -> T, + ) -> T { + let mut state = self.full_state_mut(); + if let Some(gc_queue) = gc_queue { + let generation = gc_queue.generation(); + if state.gc.on_read(generation) { + gc_queue.task_accessed(self.id); + } + } + let list = state.cells.entry(index.type_id).or_default(); + let i = index.index as usize; + if list.len() <= i { + list.resize_with(i + 1, Default::default); + } + func(&mut list[i]) + } + + /// Access to a cell. + pub(crate) fn with_cell_mut_if_available( + &self, + index:CellId, + func:impl FnOnce(&mut Cell) -> T, + ) -> Option { + self.state_mut() + .as_full_mut() + .and_then(|state| state.cells.get_mut(&index.type_id)) + .and_then(|list| list.get_mut(index.index as usize).map(func)) + } + + /// Access to a cell. + pub(crate) fn with_cell(&self, index:CellId, func:impl FnOnce(&Cell) -> T) -> T { + if let Some(cell) = self + .state() + .as_full() + .and_then(|state| state.cells.get(&index.type_id)) + .and_then(|list| list.get(index.index as usize)) + { + func(cell) + } else { + func(&Default::default()) + } + } + + pub fn is_pending(&self) -> bool { + if let TaskMetaStateReadGuard::Full(state) = self.state() { + !matches!(state.state_type, TaskStateType::Done { .. }) + } else { + true + } + } + + pub fn is_dirty(&self) -> bool { + if let TaskMetaStateReadGuard::Full(state) = self.state() { + matches!(state.state_type, TaskStateType::Dirty { .. }) + } else { + false + } + } + + fn state_string(state:&TaskState) -> &'static str { + match state.state_type { + Scheduled { .. } => "scheduled", + InProgress { count_as_finished: false, .. } => "in progress", + InProgress { count_as_finished: true, .. } => "in progress (marked as finished)", + InProgressDirty { .. } => "in progress (dirty)", + Done { .. } => "done", + Dirty { .. } => "dirty", + } + } + + pub(crate) fn connect_child( + &self, + child_id:TaskId, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + { + let mut add_job = None; + { + let mut state = self.full_state_mut(); + if state.children.insert(child_id) { + #[cfg(feature = "lazy_remove_children")] + if let TaskStateType::InProgress { outdated_children, .. } = + &mut state.state_type + { + if outdated_children.remove(&child_id) { + drop(state); + aggregation_context.apply_queued_updates(); + return; + } + } + let number_of_children = state.children.len(); + let mut guard = TaskGuard::from_full(self.id, state); + add_job = Some(handle_new_edge( + &aggregation_context, + &mut guard, + &self.id, + &child_id, + number_of_children, + )); + } + } + if let Some(job) = add_job { + // To avoid bubbling up the dirty tasks into the new parent tree, we make a + // quick check for activeness of the parent when the child is dirty. This is + // purely an optimization and not required for correctness. + // So it's fine to ignore the race condition existing here. + backend.with_task(child_id, |child| { + if child.is_dirty() { + let active = + query_root_info(&aggregation_context, ActiveQuery::default(), self.id); + if active { + child.schedule_when_dirty_from_aggregation(backend, turbo_tasks); + } + } + }); + job.apply(&aggregation_context); + } + } + aggregation_context.apply_queued_updates(); + } + + pub(crate) fn get_or_wait_output Result>( + &self, + strongly_consistent:bool, + func:F, + note:impl Fn() -> String + Sync + Send + 'static, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result> { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + if strongly_consistent { + prepare_aggregation_data(&aggregation_context, &self.id); + } + let mut state = if strongly_consistent { + let mut aggregation = aggregation_data(&aggregation_context, &self.id); + if aggregation.unfinished > 0 { + if aggregation.root_type.is_none() { + Self::set_root_type( + &aggregation_context, + &mut aggregation, + RootType::ReadingStronglyConsistent, + ); + } + let listener = aggregation.unfinished_event.listen_with_note(note); + drop(aggregation); + aggregation_context.apply_queued_updates(); + + return Ok(Err(listener)); + } else if matches!(aggregation.root_type, Some(RootType::ReadingStronglyConsistent)) { + aggregation.root_type = None; + } + let state = aggregation.into_inner().into_inner().into_inner(); + TaskMetaStateWriteGuard::full_from(state, self) + } else { + self.full_state_mut() + }; + let result = match state.state_type { + Done { .. } => { + let result = func(&mut state.output)?; + drop(state); + + Ok(Ok(result)) + }, + Dirty { ref mut event, ref mut outdated_dependencies } => { + turbo_tasks.schedule(self.id); + let event = event.take(); + let listener = event.listen_with_note(note); + state.state_type = + Scheduled { event, outdated_dependencies:take(outdated_dependencies) }; + let change_job = state.aggregation_node.apply_change( + &aggregation_context, + TaskChange { dirty_tasks_update:vec![(self.id, -1)], ..Default::default() }, + ); + drop(state); + change_job.apply(&aggregation_context); + Ok(Err(listener)) + }, + Scheduled { ref event, .. } + | InProgress { ref event, .. } + | InProgressDirty { ref event } => { + let listener = event.listen_with_note(note); + drop(state); + Ok(Err(listener)) + }, + }; + aggregation_context.apply_queued_updates(); + result + } + + pub(crate) fn read_collectibles( + id:TaskId, + trait_type:TraitTypeId, + reader:TaskId, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> AutoMap { + let aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let mut aggregation_data = aggregation_context.aggregation_data(id); + aggregation_data.read_collectibles(trait_type, reader) + } + + pub(crate) fn emit_collectible( + &self, + trait_type:TraitTypeId, + collectible:RawVc, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let mut state = self.full_state_mut(); + state.collectibles.emit(trait_type, collectible); + let change_job = state.aggregation_node.apply_change( + &aggregation_context, + TaskChange { collectibles:vec![(trait_type, collectible, 1)], ..Default::default() }, + ); + drop(state); + change_job.apply(&aggregation_context); + aggregation_context.apply_queued_updates(); + } + + pub(crate) fn unemit_collectible( + &self, + trait_type:TraitTypeId, + collectible:RawVc, + count:u32, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let mut state = self.full_state_mut(); + state.collectibles.unemit(trait_type, collectible, count); + let change_job = state.aggregation_node.apply_change( + &aggregation_context, + TaskChange { + collectibles:vec![(trait_type, collectible, -(count as i32))], + ..Default::default() + }, + ); + drop(state); + change_job.apply(&aggregation_context); + aggregation_context.apply_queued_updates(); + } + + pub(crate) fn run_gc(&self, generation:u32) -> bool { + if !self.is_pure() { + return false; + } + + let mut cells_to_drop = Vec::new(); + + let result = if let TaskMetaStateWriteGuard::Full(mut state) = self.state_mut() { + if state.gc.generation > generation || state.stateful { + return false; + } + + match &mut state.state_type { + TaskStateType::Done { dependencies } => { + dependencies.shrink_to_fit(); + }, + TaskStateType::Dirty { .. } => {}, + _ => { + // GC can't run in this state. We will reschedule it when the execution + // completes. + return false; + }, + } + + // shrinking memory and dropping cells + state.output.dependent_tasks.shrink_to_fit(); + state.cells.shrink_to_fit(); + for cells in state.cells.values_mut() { + cells.shrink_to_fit(); + for cell in cells.iter_mut() { + if cell.has_value() { + cells_to_drop.extend(cell.gc_content()); + } + cell.shrink_to_fit(); + } + } + true + } else { + false + }; + + drop(cells_to_drop); + + result + } + + pub(crate) fn gc_state(&self) -> Option { + if let TaskMetaStateReadGuard::Full(state) = self.state() { + Some(state.gc) + } else { + None + } + } + + // TODO not used yet, but planned + #[allow(dead_code)] + fn unload( + &self, + mut full_state:FullTaskWriteGuard<'_>, + backend:&MemoryBackend, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> bool { + let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); + let mut clear_dependencies = None; + let mut change_job = None; + let TaskState { ref mut aggregation_node, ref mut state_type, .. } = *full_state; + match state_type { + Done { ref mut dependencies } => { + change_job = aggregation_node.apply_change( + &aggregation_context, + TaskChange { + unfinished:1, + dirty_tasks_update:vec![(self.id, 1)], + ..Default::default() + }, + ); + clear_dependencies = Some(take(dependencies)); + }, + Dirty { ref event, ref mut outdated_dependencies } => { + // We want to get rid of this Event, so notify it to make sure it's empty. + event.notify(usize::MAX); + if !outdated_dependencies.is_empty() { + clear_dependencies = Some(take(outdated_dependencies)); + } + }, + _ => { + // Any other state is not unloadable. + return false; + }, + } + // Task is now dirty, so we can safely unload it + + let mut state = full_state.into_inner(); + let old_state = replace( + &mut *state, + // placeholder + TaskMetaState::Unloaded(UnloadedTaskState {}), + ); + let TaskState { + children, + cells, + output, + collectibles, + mut aggregation_node, + // can be dropped as it will be recomputed on next execution + stateful: _, + // can be dropped as it can be recomputed + prepared_type: _, + // can be dropped as always Dirty, event has been notified above + state_type: _, + // can be dropped as only gc meta info + gc: _, + } = old_state.into_full().unwrap(); + + // Remove all children, as they will be added again when this task is executed + // again + let remove_job = (!children.is_empty()) + .then(|| aggregation_node.handle_lost_edges(&aggregation_context, &self.id, children)); + + // Remove all collectibles, as they will be added again when this task is + // executed again. + let collectibles_job = if let Some(collectibles) = collectibles.into_inner() { + aggregation_node.apply_change( + &aggregation_context, + TaskChange { + collectibles:collectibles.into_iter().map(|((t, r), c)| (t, r, -c)).collect(), + ..Default::default() + }, + ) + } else { + None + }; + + // TODO aggregation_node + let unset = false; + + if unset { + *state = TaskMetaState::Unloaded(UnloadedTaskState {}); + } else { + *state = TaskMetaState::Partial(Box::new(PartialTaskState { aggregation_node })); + } + drop(state); + + change_job.apply(&aggregation_context); + remove_job.apply(&aggregation_context); + collectibles_job.apply(&aggregation_context); + + // Notify everyone that is listening on our output or cells. + // This will mark everyone as dirty and will trigger a new execution when they + // become active again. + for cells in cells.into_values() { + for cell in cells { + cell.gc_drop(turbo_tasks); + } + } + output.gc_drop(turbo_tasks); + + // TODO This is a race condition, the task might be executed again while + // removing dependencies We can clear the dependencies as we are already + // marked as dirty + if let Some(dependencies) = clear_dependencies { + self.clear_dependencies(dependencies, backend, turbo_tasks); + } + + aggregation_context.apply_queued_updates(); + + true + } +} + +impl Display for Task { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { + if let TaskMetaStateReadGuard::Full(state) = self.state() { + write!(f, "Task({}, {})", self.get_description(), Task::state_string(&state)) + } else { + write!(f, "Task({}, unloaded)", self.get_description()) + } + } +} + +impl Hash for Task { + fn hash(&self, state:&mut H) { Hash::hash(&(self as *const Task), state) } +} + +impl PartialEq for Task { + fn eq(&self, other:&Self) -> bool { std::ptr::eq(self, other) } +} + +impl Eq for Task {} diff --git a/crates/turbo-tasks-memory/Source/task/aggregation.rs b/crates/turbo-tasks-memory/Source/task/aggregation.rs new file mode 100644 index 0000000000000..7dc9bb158d01a --- /dev/null +++ b/crates/turbo-tasks-memory/Source/task/aggregation.rs @@ -0,0 +1,620 @@ +use std::{ + cmp::Ordering, + hash::{BuildHasher, Hash}, + mem::take, + ops::{ControlFlow, Deref, DerefMut}, + sync::atomic::AtomicU32, +}; + +use auto_hash_map::{AutoMap, map::Entry}; +use nohash_hasher::BuildNoHashHasher; +use parking_lot::Mutex; +use turbo_tasks::{RawVc, TaskId, TaskIdSet, TraitTypeId, TurboTasksBackendApi, event::Event}; + +use super::{ + TaskStateType, + meta_state::{FullTaskWriteGuard, TaskMetaStateWriteGuard}, +}; +use crate::{ + MemoryBackend, + aggregation::{ + AggregationContext, + AggregationDataGuard, + AggregationNode, + AggregationNodeGuard, + RootQuery, + aggregation_data, + }, +}; + +pub enum RootType { + Once, + Root, + ReadingStronglyConsistent, +} + +#[derive(Debug, Default)] +pub struct CollectiblesInfo { + collectibles:AutoMap, + dependent_tasks:TaskIdSet, +} + +impl CollectiblesInfo { + fn is_unset(&self) -> bool { self.collectibles.is_empty() && self.dependent_tasks.is_empty() } +} + +pub struct Aggregated { + /// The number of unfinished items in the lower aggregation level. + /// Unfinished means not "Done". + // TODO determine if this can go negative in concurrent situations. + pub unfinished: i32, + /// Event that will be notified when all unfinished tasks are done. + pub unfinished_event:Event, + /// A list of all tasks that are unfinished. Only for debugging. + #[cfg(feature = "track_unfinished")] + pub unfinished_tasks:AutoMap>, + /// A list of all tasks that are dirty. + /// When the it becomes active, these need to be scheduled. + // TODO evaluate a more efficient data structure for this since we are copying the list on + // every level. + pub dirty_tasks: AutoMap>, + /// Emitted collectibles with count and dependent_tasks by trait type + pub collectibles:AutoMap>, + + /// Only used for the aggregation root. Which kind of root is this? + /// [RootType::Once] for OnceTasks or [RootType::Root] for Root Tasks. + /// [RootType::ReadingStronglyConsistent] while currently reading a task + /// strongly consistent. It's set to None for other tasks, when the once + /// task is done or when the root task is disposed. + pub root_type:Option, +} + +impl Default for Aggregated { + fn default() -> Self { + Self { + unfinished:0, + unfinished_event:Event::new(|| "Aggregated::unfinished_event".to_string()), + #[cfg(feature = "track_unfinished")] + unfinished_tasks:AutoMap::with_hasher(), + dirty_tasks:AutoMap::with_hasher(), + collectibles:AutoMap::with_hasher(), + root_type:None, + } + } +} + +impl Aggregated { + pub(crate) fn remove_collectible_dependent_task( + &mut self, + trait_type:TraitTypeId, + reader:TaskId, + ) { + if let Entry::Occupied(mut entry) = self.collectibles.entry(trait_type) { + let info = entry.get_mut(); + info.dependent_tasks.remove(&reader); + if info.is_unset() { + entry.remove(); + } + } + } + + pub(crate) fn read_collectibles( + &mut self, + trait_type:TraitTypeId, + reader:TaskId, + ) -> AutoMap { + match self.collectibles.entry(trait_type) { + Entry::Occupied(mut e) => { + let info = e.get_mut(); + info.dependent_tasks.insert(reader); + info.collectibles.clone() + }, + Entry::Vacant(e) => { + e.insert(CollectiblesInfo::default()).dependent_tasks.insert(reader); + AutoMap::default() + }, + } + } +} + +#[derive(Default, Debug)] +pub struct TaskChange { + pub unfinished:i32, + #[cfg(feature = "track_unfinished")] + pub unfinished_tasks_update:Vec<(TaskId, i32)>, + pub dirty_tasks_update:Vec<(TaskId, i32)>, + pub collectibles:Vec<(TraitTypeId, RawVc, i32)>, +} + +impl TaskChange { + pub fn is_empty(&self) -> bool { + #[allow(unused_mut, reason = "feature flag")] + let mut empty = self.unfinished == 0 + && self.dirty_tasks_update.is_empty() + && self.collectibles.is_empty(); + #[cfg(feature = "track_unfinished")] + if !self.unfinished_tasks_update.is_empty() { + empty = false; + } + empty + } +} + +pub struct TaskAggregationContext<'a> { + pub turbo_tasks:&'a dyn TurboTasksBackendApi, + pub backend:&'a MemoryBackend, + pub dirty_tasks_to_schedule:Mutex>, + pub tasks_to_notify:Mutex>, +} + +impl<'a> TaskAggregationContext<'a> { + pub fn new( + turbo_tasks:&'a dyn TurboTasksBackendApi, + backend:&'a MemoryBackend, + ) -> Self { + Self { + turbo_tasks, + backend, + dirty_tasks_to_schedule:Mutex::new(None), + tasks_to_notify:Mutex::new(None), + } + } + + pub fn apply_queued_updates(&mut self) { + { + let mut _span = None; + let tasks = self.dirty_tasks_to_schedule.get_mut(); + if let Some(tasks) = tasks.as_mut() { + let tasks = take(tasks); + if !tasks.is_empty() { + _span.get_or_insert_with(|| { + tracing::trace_span!("task aggregation apply_queued_updates").entered() + }); + self.backend.schedule_when_dirty_from_aggregation(tasks, self.turbo_tasks); + } + } + } + let tasks = self.tasks_to_notify.get_mut(); + if let Some(tasks) = tasks.as_mut() { + let tasks = take(tasks); + if !tasks.is_empty() { + self.turbo_tasks.schedule_notify_tasks_set(&tasks); + } + } + } + + pub fn aggregation_data(&self, id:TaskId) -> AggregationDataGuard> { + aggregation_data(self, &id) + } +} + +#[cfg(debug_assertions)] +impl<'a> Drop for TaskAggregationContext<'a> { + fn drop(&mut self) { + let tasks_to_schedule = self.dirty_tasks_to_schedule.get_mut(); + if let Some(tasks_to_schedule) = tasks_to_schedule.as_ref() { + if !tasks_to_schedule.is_empty() { + panic!("TaskAggregationContext dropped without scheduling all tasks"); + } + } + let tasks_to_notify = self.tasks_to_notify.get_mut(); + if let Some(tasks_to_notify) = tasks_to_notify.as_ref() { + if !tasks_to_notify.is_empty() { + panic!("TaskAggregationContext dropped without notifying all tasks"); + } + } + } +} + +impl<'a> AggregationContext for TaskAggregationContext<'a> { + type Data = Aggregated; + type DataChange = TaskChange; + type Guard<'l> + = TaskGuard<'l> + where + Self: 'l; + type NodeRef = TaskId; + + fn node<'b>(&'b self, reference:&TaskId) -> Self::Guard<'b> { + let task = self.backend.task(*reference); + TaskGuard::new(*reference, task.state_mut()) + } + + fn atomic_in_progress_counter<'l>(&self, id:&'l TaskId) -> &'l AtomicU32 + where + Self: 'l, { + &self.backend.task(*id).graph_modification_in_progress_counter + } + + fn apply_change( + &self, + info:&mut Aggregated, + change:&Self::DataChange, + ) -> Option { + let mut unfinished = 0; + if info.unfinished > 0 { + info.unfinished += change.unfinished; + if info.unfinished <= 0 { + info.unfinished_event.notify(usize::MAX); + unfinished = -1; + } + } else { + info.unfinished += change.unfinished; + if info.unfinished > 0 { + unfinished = 1; + } + } + #[cfg(feature = "track_unfinished")] + let mut unfinished_tasks_update = Vec::new(); + #[cfg(feature = "track_unfinished")] + for &(task, count) in change.unfinished_tasks_update.iter() { + match update_count_entry(info.unfinished_tasks.entry(task), count) { + (_, UpdateCountEntryChange::Removed) => unfinished_tasks_update.push((task, -1)), + (_, UpdateCountEntryChange::Inserted) => unfinished_tasks_update.push((task, 1)), + _ => {}, + } + } + let mut dirty_tasks_update = Vec::new(); + let is_root = info.root_type.is_some(); + for &(task, count) in change.dirty_tasks_update.iter() { + match update_count_entry(info.dirty_tasks.entry(task), count) { + (_, UpdateCountEntryChange::Removed) => dirty_tasks_update.push((task, -1)), + (_, UpdateCountEntryChange::Inserted) => { + if is_root { + let mut tasks_to_schedule = self.dirty_tasks_to_schedule.lock(); + tasks_to_schedule.get_or_insert_default().insert(task); + } + dirty_tasks_update.push((task, 1)) + }, + _ => {}, + } + } + for &(trait_type_id, collectible, count) in change.collectibles.iter() { + let collectibles_info_entry = info.collectibles.entry(trait_type_id); + match collectibles_info_entry { + Entry::Occupied(mut e) => { + let collectibles_info = e.get_mut(); + let (value, _) = update_count_entry( + collectibles_info.collectibles.entry(collectible), + count, + ); + if !collectibles_info.dependent_tasks.is_empty() { + self.tasks_to_notify + .lock() + .get_or_insert_default() + .extend(take(&mut collectibles_info.dependent_tasks).into_iter()); + } + if value == 0 && collectibles_info.is_unset() { + e.remove(); + } + }, + Entry::Vacant(e) => { + let mut collectibles_info = CollectiblesInfo::default(); + update_count_entry(collectibles_info.collectibles.entry(collectible), count); + e.insert(collectibles_info); + }, + } + } + #[cfg(feature = "track_unfinished")] + if info.unfinished > 0 && info.unfinished_tasks.is_empty() + || info.unfinished == 0 && !info.unfinished_tasks.is_empty() + { + panic!( + "inconsistent state: unfinished {}, unfinished_tasks {:?}, change {:?}", + info.unfinished, info.unfinished_tasks, change + ); + } + let new_change = TaskChange { + unfinished, + #[cfg(feature = "track_unfinished")] + unfinished_tasks_update, + dirty_tasks_update, + collectibles:change.collectibles.clone(), + }; + if new_change.is_empty() { None } else { Some(new_change) } + } + + fn data_to_add_change(&self, data:&Aggregated) -> Option { + let mut change = TaskChange::default(); + if data.unfinished > 0 { + change.unfinished = 1; + } + #[cfg(feature = "track_unfinished")] + for (&task, &count) in data.unfinished_tasks.iter() { + if count > 0 { + change.unfinished_tasks_update.push((task, 1)); + } + } + for (&task, &count) in data.dirty_tasks.iter() { + if count > 0 { + change.dirty_tasks_update.push((task, 1)); + } + } + for (trait_type_id, collectibles_info) in data.collectibles.iter() { + for (collectible, count) in collectibles_info.collectibles.iter() { + change.collectibles.push((*trait_type_id, *collectible, *count)); + } + } + if change.is_empty() { None } else { Some(change) } + } + + fn data_to_remove_change(&self, data:&Aggregated) -> Option { + let mut change = TaskChange::default(); + if data.unfinished > 0 { + change.unfinished = -1; + } + #[cfg(feature = "track_unfinished")] + for (&task, &count) in data.unfinished_tasks.iter() { + change.unfinished_tasks_update.push((task, -count)); + } + for (&task, &count) in data.dirty_tasks.iter() { + change.dirty_tasks_update.push((task, -count)); + } + for (trait_type_id, collectibles_info) in data.collectibles.iter() { + for (collectible, count) in collectibles_info.collectibles.iter() { + change.collectibles.push((*trait_type_id, *collectible, -*count)); + } + } + if change.is_empty() { None } else { Some(change) } + } +} + +#[derive(Default)] +pub struct ActiveQuery { + active:bool, +} + +impl RootQuery for ActiveQuery { + type Data = Aggregated; + type Result = bool; + + fn query(&mut self, data:&Self::Data) -> ControlFlow<()> { + if data.root_type.is_some() { + self.active = true; + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } + + fn result(self) -> Self::Result { self.active } +} + +pub struct TaskGuard<'l> { + id:TaskId, + guard:TaskMetaStateWriteGuard<'l>, +} + +impl<'l> TaskGuard<'l> { + pub fn new(id:TaskId, mut guard:TaskMetaStateWriteGuard<'l>) -> Self { + guard.ensure_at_least_partial(); + Self { id, guard } + } + + pub fn from_full(id:TaskId, guard:FullTaskWriteGuard<'l>) -> Self { + Self { id, guard:TaskMetaStateWriteGuard::Full(guard) } + } + + pub fn into_inner(self) -> TaskMetaStateWriteGuard<'l> { self.guard } +} + +impl<'l> Deref for TaskGuard<'l> { + type Target = AggregationNode< + ::NodeRef, + ::Data, + >; + + fn deref(&self) -> &Self::Target { + match self.guard { + TaskMetaStateWriteGuard::Full(ref guard) => &guard.aggregation_node, + TaskMetaStateWriteGuard::Partial(ref guard) => &guard.aggregation_node, + TaskMetaStateWriteGuard::Unloaded(_) => unreachable!(), + TaskMetaStateWriteGuard::TemporaryFiller => unreachable!(), + } + } +} + +impl<'l> DerefMut for TaskGuard<'l> { + fn deref_mut(&mut self) -> &mut Self::Target { + match self.guard { + TaskMetaStateWriteGuard::Full(ref mut guard) => &mut guard.aggregation_node, + TaskMetaStateWriteGuard::Partial(ref mut guard) => &mut guard.aggregation_node, + TaskMetaStateWriteGuard::Unloaded(_) => unreachable!(), + TaskMetaStateWriteGuard::TemporaryFiller => unreachable!(), + } + } +} + +impl<'l> AggregationNodeGuard for TaskGuard<'l> { + type Data = Aggregated; + type DataChange = TaskChange; + type NodeRef = TaskId; + + type ChildrenIter<'a> + = impl Iterator + 'a + where + Self: 'a; + + fn children(&self) -> Self::ChildrenIter<'_> { + match self.guard { + TaskMetaStateWriteGuard::Full(ref guard) => { + #[cfg(feature = "lazy_remove_children")] + { + let outdated_children = match &guard.state_type { + TaskStateType::InProgress { outdated_children, .. } => { + Some(outdated_children.iter().copied()) + }, + _ => None, + }; + Some( + guard + .children + .iter() + .copied() + .chain(outdated_children.into_iter().flatten()), + ) + .into_iter() + .flatten() + } + #[cfg(not(feature = "lazy_remove_children"))] + { + Some(guard.children.iter().copied()).into_iter().flatten() + } + }, + TaskMetaStateWriteGuard::Partial(_) | TaskMetaStateWriteGuard::Unloaded(_) => { + None.into_iter().flatten() + }, + TaskMetaStateWriteGuard::TemporaryFiller => unreachable!(), + } + } + + fn get_add_change(&self) -> Option { + match self.guard { + TaskMetaStateWriteGuard::Full(ref guard) => { + let mut change = TaskChange::default(); + if !matches!( + guard.state_type, + TaskStateType::Done { .. } + | TaskStateType::InProgress { count_as_finished:true, .. } + ) { + change.unfinished = 1; + #[cfg(feature = "track_unfinished")] + change.unfinished_tasks_update.push((self.id, 1)); + } + if matches!(guard.state_type, TaskStateType::Dirty { .. }) { + change.dirty_tasks_update.push((self.id, 1)); + } + if let Some(collectibles) = guard.collectibles.as_ref() { + for (&(trait_type_id, collectible), _) in collectibles.iter() { + change.collectibles.push((trait_type_id, collectible, 1)); + } + } + if let TaskStateType::InProgress { outdated_collectibles, .. } = &guard.state_type { + if let Some(collectibles) = outdated_collectibles.as_ref() { + for (&(trait_type_id, collectible), _) in collectibles.iter() { + change.collectibles.push((trait_type_id, collectible, 1)); + } + } + } + if change.is_empty() { None } else { Some(change) } + }, + TaskMetaStateWriteGuard::Partial(_) | TaskMetaStateWriteGuard::Unloaded(_) => None, + TaskMetaStateWriteGuard::TemporaryFiller => unreachable!(), + } + } + + fn get_remove_change(&self) -> Option { + match self.guard { + TaskMetaStateWriteGuard::Full(ref guard) => { + let mut change = TaskChange::default(); + if !matches!( + guard.state_type, + TaskStateType::Done { .. } + | TaskStateType::InProgress { count_as_finished:true, .. } + ) { + change.unfinished = -1; + #[cfg(feature = "track_unfinished")] + change.unfinished_tasks_update.push((self.id, -1)); + } + if matches!(guard.state_type, TaskStateType::Dirty { .. }) { + change.dirty_tasks_update.push((self.id, -1)); + } + if let Some(collectibles) = guard.collectibles.as_ref() { + for (&(trait_type_id, collectible), _) in collectibles.iter() { + change.collectibles.push((trait_type_id, collectible, -1)); + } + } + if let TaskStateType::InProgress { outdated_collectibles, .. } = &guard.state_type { + if let Some(collectibles) = outdated_collectibles.as_ref() { + for (&(trait_type_id, collectible), _) in collectibles.iter() { + change.collectibles.push((trait_type_id, collectible, -1)); + } + } + } + if change.is_empty() { None } else { Some(change) } + }, + TaskMetaStateWriteGuard::Partial(_) | TaskMetaStateWriteGuard::Unloaded(_) => None, + TaskMetaStateWriteGuard::TemporaryFiller => unreachable!(), + } + } + + fn get_initial_data(&self) -> Self::Data { + let mut data = Aggregated::default(); + if let Some(TaskChange { + unfinished, + #[cfg(feature = "track_unfinished")] + unfinished_tasks_update, + dirty_tasks_update, + collectibles, + }) = self.get_add_change() + { + data.unfinished = unfinished; + #[cfg(feature = "track_unfinished")] + { + data.unfinished_tasks = unfinished_tasks_update.into_iter().collect(); + } + data.dirty_tasks = dirty_tasks_update.into_iter().collect(); + data.collectibles = collectibles + .into_iter() + .map(|(trait_type_id, collectible, count)| { + ( + trait_type_id, + CollectiblesInfo { + collectibles:[(collectible, count)].iter().cloned().collect(), + dependent_tasks:TaskIdSet::default(), + }, + ) + }) + .collect(); + } + data + } +} + +pub type TaskAggregationNode = AggregationNode; + +enum UpdateCountEntryChange { + Removed, + Inserted, + Updated, +} + +fn update_count_entry( + entry:Entry<'_, K, i32, H, I>, + update:i32, +) -> (i32, UpdateCountEntryChange) { + match entry { + Entry::Occupied(mut e) => { + let value = e.get_mut(); + if *value < 0 { + *value += update; + match (*value).cmp(&0) { + Ordering::Less => (*value, UpdateCountEntryChange::Updated), + Ordering::Equal => { + e.remove(); + (0, UpdateCountEntryChange::Updated) + }, + Ordering::Greater => (*value, UpdateCountEntryChange::Inserted), + } + } else { + *value += update; + match (*value).cmp(&0) { + Ordering::Less => (*value, UpdateCountEntryChange::Removed), + Ordering::Equal => { + e.remove(); + (0, UpdateCountEntryChange::Removed) + }, + Ordering::Greater => (*value, UpdateCountEntryChange::Updated), + } + } + }, + Entry::Vacant(e) => { + if update == 0 { + (0, UpdateCountEntryChange::Updated) + } else { + e.insert(update); + (update, UpdateCountEntryChange::Inserted) + } + }, + } +} diff --git a/crates/turbo-tasks-memory/Source/task/meta_state.rs b/crates/turbo-tasks-memory/Source/task/meta_state.rs new file mode 100644 index 0000000000000..352bc34c875e3 --- /dev/null +++ b/crates/turbo-tasks-memory/Source/task/meta_state.rs @@ -0,0 +1,279 @@ +use std::mem::replace; + +use parking_lot::{RwLockReadGuard, RwLockWriteGuard}; + +use super::{PartialTaskState, Task, TaskState, UnloadedTaskState}; +use crate::{ + aggregation::AggregationNode, + map_guard::{ReadGuard, WriteGuard}, +}; + +pub(super) enum TaskMetaState { + Full(Box), + Partial(Box), + Unloaded(UnloadedTaskState), +} + +impl TaskMetaState { + pub(super) fn into_full(self) -> Option { + match self { + Self::Full(state) => Some(*state), + _ => None, + } + } + + pub(super) fn into_partial(self) -> Option { + match self { + Self::Partial(state) => Some(*state), + _ => None, + } + } + + pub(super) fn into_unloaded(self) -> Option { + match self { + Self::Unloaded(state) => Some(state), + _ => None, + } + } + + pub(super) fn as_full(&self) -> Option<&TaskState> { + match self { + Self::Full(state) => Some(state), + _ => None, + } + } + + pub(super) fn as_partial(&self) -> Option<&PartialTaskState> { + match self { + Self::Partial(state) => Some(state), + _ => None, + } + } + + pub(super) fn as_unloaded(&self) -> Option<&UnloadedTaskState> { + match self { + Self::Unloaded(state) => Some(state), + _ => None, + } + } + + pub(super) fn as_full_mut(&mut self) -> Option<&mut TaskState> { + match self { + Self::Full(state) => Some(state), + _ => None, + } + } + + pub(super) fn as_partial_mut(&mut self) -> Option<&mut PartialTaskState> { + match self { + Self::Partial(state) => Some(state), + _ => None, + } + } + + pub(super) fn as_unloaded_mut(&mut self) -> Option<&mut UnloadedTaskState> { + match self { + Self::Unloaded(state) => Some(state), + _ => None, + } + } +} + +pub(super) type TaskMetaStateAsFull = for<'a> fn(&'a TaskMetaState) -> Option<&'a TaskState>; +pub(super) type TaskMetaStateAsPartial = for<'a> fn(&'a TaskMetaState) -> Option<&PartialTaskState>; +pub(super) type TaskMetaStateAsUnloaded = + for<'a> fn(&'a TaskMetaState) -> Option<&'a UnloadedTaskState>; +pub(super) type TaskMetaStateAsFullMut = + for<'a> fn(&'a mut TaskMetaState) -> Option<&'a mut TaskState>; +pub(super) type TaskMetaStateAsPartialMut = + for<'a> fn(&'a mut TaskMetaState) -> Option<&'a mut PartialTaskState>; +pub(super) type TaskMetaStateAsUnloadedMut = + for<'a> fn(&'a mut TaskMetaState) -> Option<&'a mut UnloadedTaskState>; + +#[allow(dead_code, reason = "test")] +pub(super) enum TaskMetaStateReadGuard<'a> { + Full(ReadGuard<'a, TaskMetaState, TaskState, TaskMetaStateAsFull>), + Partial(ReadGuard<'a, TaskMetaState, PartialTaskState, TaskMetaStateAsPartial>), + Unloaded, +} + +pub(super) type FullTaskWriteGuard<'a> = + WriteGuard<'a, TaskMetaState, TaskState, TaskMetaStateAsFull, TaskMetaStateAsFullMut>; + +pub(super) enum TaskMetaStateWriteGuard<'a> { + Full(FullTaskWriteGuard<'a>), + Partial( + WriteGuard< + 'a, + TaskMetaState, + PartialTaskState, + TaskMetaStateAsPartial, + TaskMetaStateAsPartialMut, + >, + ), + Unloaded( + WriteGuard< + 'a, + TaskMetaState, + UnloadedTaskState, + TaskMetaStateAsUnloaded, + TaskMetaStateAsUnloadedMut, + >, + ), + TemporaryFiller, +} + +impl<'a> From> for TaskMetaStateReadGuard<'a> { + fn from(guard:RwLockReadGuard<'a, TaskMetaState>) -> Self { + match &*guard { + TaskMetaState::Full(_) => { + TaskMetaStateReadGuard::Full(ReadGuard::new(guard, TaskMetaState::as_full)) + }, + TaskMetaState::Partial(_) => { + TaskMetaStateReadGuard::Partial(ReadGuard::new(guard, TaskMetaState::as_partial)) + }, + TaskMetaState::Unloaded(_) => TaskMetaStateReadGuard::Unloaded, + } + } +} + +impl<'a> From> for TaskMetaStateWriteGuard<'a> { + fn from(guard:RwLockWriteGuard<'a, TaskMetaState>) -> Self { + match &*guard { + TaskMetaState::Full(_) => { + TaskMetaStateWriteGuard::Full(WriteGuard::new( + guard, + TaskMetaState::as_full, + TaskMetaState::as_full_mut, + )) + }, + TaskMetaState::Partial(_) => { + TaskMetaStateWriteGuard::Partial(WriteGuard::new( + guard, + TaskMetaState::as_partial, + TaskMetaState::as_partial_mut, + )) + }, + TaskMetaState::Unloaded(_) => { + TaskMetaStateWriteGuard::Unloaded(WriteGuard::new( + guard, + TaskMetaState::as_unloaded, + TaskMetaState::as_unloaded_mut, + )) + }, + } + } +} + +impl<'a> TaskMetaStateReadGuard<'a> { + pub(super) fn as_full(&mut self) -> Option<&TaskState> { + match self { + TaskMetaStateReadGuard::Full(state) => Some(&**state), + _ => None, + } + } +} + +impl<'a> TaskMetaStateWriteGuard<'a> { + pub(super) fn full_from( + mut guard:RwLockWriteGuard<'a, TaskMetaState>, + task:&Task, + ) -> FullTaskWriteGuard<'a> { + match &*guard { + TaskMetaState::Full(_) => {}, + TaskMetaState::Partial(_) => { + let partial = replace( + &mut *guard, + // placeholder + TaskMetaState::Unloaded(UnloadedTaskState {}), + ) + .into_partial() + .unwrap(); + *guard = + TaskMetaState::Full(Box::new(partial.into_full(task.get_event_description()))); + }, + TaskMetaState::Unloaded(_) => { + let unloaded = replace( + &mut *guard, + // placeholder + TaskMetaState::Unloaded(UnloadedTaskState {}), + ) + .into_unloaded() + .unwrap(); + *guard = + TaskMetaState::Full(Box::new(unloaded.into_full(task.get_event_description()))); + }, + } + WriteGuard::new(guard, TaskMetaState::as_full, TaskMetaState::as_full_mut) + } + + #[allow(dead_code, reason = "We need this in future")] + pub(super) fn partial_from(mut guard:RwLockWriteGuard<'a, TaskMetaState>) -> Self { + match &*guard { + TaskMetaState::Full(_) => { + TaskMetaStateWriteGuard::Full(WriteGuard::new( + guard, + TaskMetaState::as_full, + TaskMetaState::as_full_mut, + )) + }, + TaskMetaState::Partial(_) => { + TaskMetaStateWriteGuard::Partial(WriteGuard::new( + guard, + TaskMetaState::as_partial, + TaskMetaState::as_partial_mut, + )) + }, + TaskMetaState::Unloaded(_) => { + let unloaded = replace( + &mut *guard, + // placeholder + TaskMetaState::Unloaded(UnloadedTaskState {}), + ) + .into_unloaded() + .unwrap(); + *guard = TaskMetaState::Partial(Box::new(unloaded.into_partial())); + TaskMetaStateWriteGuard::Partial(WriteGuard::new( + guard, + TaskMetaState::as_partial, + TaskMetaState::as_partial_mut, + )) + }, + } + } + + pub(super) fn as_full_mut(&mut self) -> Option<&mut TaskState> { + match self { + TaskMetaStateWriteGuard::Full(state) => Some(&mut **state), + _ => None, + } + } + + pub(super) fn into_inner(self) -> RwLockWriteGuard<'a, TaskMetaState> { + match self { + TaskMetaStateWriteGuard::Full(state) => state.into_inner(), + TaskMetaStateWriteGuard::Partial(state) => state.into_inner(), + TaskMetaStateWriteGuard::Unloaded(state) => state.into_inner(), + TaskMetaStateWriteGuard::TemporaryFiller => unreachable!(), + } + } + + pub(super) fn ensure_at_least_partial(&mut self) { + if matches!(self, TaskMetaStateWriteGuard::Unloaded(..)) { + let TaskMetaStateWriteGuard::Unloaded(state) = + replace(self, TaskMetaStateWriteGuard::TemporaryFiller) + else { + unreachable!(); + }; + let mut state = state.into_inner(); + *state = TaskMetaState::Partial(Box::new(PartialTaskState { + aggregation_node:AggregationNode::new(), + })); + *self = TaskMetaStateWriteGuard::Partial(WriteGuard::new( + state, + TaskMetaState::as_partial, + TaskMetaState::as_partial_mut, + )); + } + } +} diff --git a/crates/turbo-tasks-memory/benches/mod.rs b/crates/turbo-tasks-memory/benches/mod.rs new file mode 100644 index 0000000000000..0502ba162e3fd --- /dev/null +++ b/crates/turbo-tasks-memory/benches/mod.rs @@ -0,0 +1,18 @@ +#![feature(arbitrary_self_types)] + +use criterion::{Criterion, criterion_group, criterion_main}; + +pub(crate) mod scope_stress; +pub(crate) mod stress; + +criterion_group!( + name = turbo_tasks_memory_stress; + config = Criterion::default(); + targets = stress::fibonacci, scope_stress::scope_stress +); +criterion_main!(turbo_tasks_memory_stress); + +pub fn register() { + turbo_tasks::register(); + include!(concat!(env!("OUT_DIR"), "/register_benches.rs")); +} diff --git a/crates/turbo-tasks-memory/benches/scope_stress.rs b/crates/turbo-tasks-memory/benches/scope_stress.rs new file mode 100644 index 0000000000000..93987b5c372a4 --- /dev/null +++ b/crates/turbo-tasks-memory/benches/scope_stress.rs @@ -0,0 +1,75 @@ +use anyhow::Result; +use criterion::{BenchmarkId, Criterion}; +use turbo_tasks::{Completion, TryJoinIterExt, TurboTasks, Vc}; +use turbo_tasks_memory::MemoryBackend; + +use super::register; + +pub fn scope_stress(c:&mut Criterion) { + if matches!( + std::env::var("TURBOPACK_BENCH_STRESS").ok().as_deref(), + None | Some("") | Some("no") | Some("false") + ) { + return; + } + + register(); + + let mut group = c.benchmark_group("turbo_tasks_memory_scope_stress"); + group.sample_size(20); + + for size in [5, 10, 15, 20, 25, 30, 100, 200, 300] { + group.throughput(criterion::Throughput::Elements( + // tasks for fib from 0 to size - 1 = + (size as u64) * (size as u64) + + /* root tasks = */ + (2 * size as u64) + - 1, + )); + group.bench_with_input( + BenchmarkId::new("rectangle", format_args!("{size} x {size}")), + &size, + |b, size| { + let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap(); + let size = *size; + + b.to_async(rt).iter_with_large_drop(move || { + let tt = TurboTasks::new(MemoryBackend::default()); + async move { + (0..size) + .map(|a| (a, size - 1)) + .chain((0..size - 1).map(|b| (size - 1, b))) + .map(|(a, b)| { + let tt = &tt; + async move { + let task = tt.spawn_once_task(async move { + rectangle(a, b).strongly_consistent().await?; + Ok::, _>(Default::default()) + }); + tt.wait_task_completion(task, false).await + } + }) + .try_join() + .await + .unwrap(); + + tt + } + }) + }, + ); + } +} + +/// This fills a rectagle from (0, 0) to (a, b) by +/// first filling (0, 0) to (a - 1, b) and then (0, 0) to (a, b - 1) recursively +#[turbo_tasks::function] +async fn rectangle(a:u32, b:u32) -> Result> { + if a > 0 { + rectangle(a - 1, b).await?; + } + if b > 0 { + rectangle(a, b - 1).await?; + } + Ok(Completion::new()) +} diff --git a/crates/turbo-tasks-memory/benches/stress.rs b/crates/turbo-tasks-memory/benches/stress.rs new file mode 100644 index 0000000000000..99032e26a934c --- /dev/null +++ b/crates/turbo-tasks-memory/benches/stress.rs @@ -0,0 +1,75 @@ +use anyhow::Result; +use criterion::{BenchmarkId, Criterion}; +use turbo_tasks::{TryJoinIterExt, TurboTasks, Vc}; +use turbo_tasks_memory::MemoryBackend; + +use super::register; + +pub fn fibonacci(c:&mut Criterion) { + if matches!( + std::env::var("TURBOPACK_BENCH_STRESS").ok().as_deref(), + None | Some("") | Some("no") | Some("false") + ) { + return; + } + + register(); + + let mut group = c.benchmark_group("turbo_tasks_memory_stress"); + group.sample_size(20); + + for size in [100, 200, 500, 1000, 1414] { + group.throughput(criterion::Throughput::Elements( + // tasks for fib from 0 to size - 1 = + size as u64 * (size as u64 + 1) / 2 + + /* root task = */ + 1, + )); + group.bench_with_input(BenchmarkId::new("fibonacci", size), &size, |b, size| { + let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap(); + let size = *size; + + b.to_async(rt).iter_with_large_drop(move || { + let tt = TurboTasks::new(MemoryBackend::default()); + async move { + let task = tt.spawn_once_task(async move { + // Number of tasks: + // 1 root task + // size >= 1 => + fib(0) = 1 + // size >= 2 => + fib(1) = 2 + (0..size).map(|i| fib(i, i)).try_join().await?; + Ok::, _>(Default::default()) + }); + tt.wait_task_completion(task, false).await.unwrap(); + tt + } + }) + }); + } +} + +#[turbo_tasks::value(transparent)] +struct FibResult(u64); + +// Number of tasks: +// fib(0) = 1 tasks +// fib(1) = 2 tasks +// fib(n) = n + 1 tasks + +/// Computes a fibonacci number in a recursive matter. Due to turbo-tasks this +/// will result in a lot of cached tasks, so its performance is only O(n) +/// (compared to non-turbo-tasks O(1.6^N)). +/// This function also has a `key` parameter to allow forcing it to separate +/// cache entries by using different keys. +#[turbo_tasks::function] +async fn fib(i:u32, key:u32) -> Result> { + Ok(match i { + 0 => FibResult(1).cell(), + 1 => fib(0, key), + _ => { + let a = fib(i - 1, key); + let b = fib(i - 2, key); + FibResult(a.await?.wrapping_add(*b.await?)).cell() + }, + }) +} diff --git a/crates/turbo-tasks-memory/build.rs b/crates/turbo-tasks-memory/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbo-tasks-memory/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbo-tasks-signposter-sys/Source/lib.rs b/crates/turbo-tasks-signposter-sys/Source/lib.rs new file mode 100644 index 0000000000000..385eefb391259 --- /dev/null +++ b/crates/turbo-tasks-signposter-sys/Source/lib.rs @@ -0,0 +1,9 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(clippy::unnecessary_cast)] +#![allow(clippy::useless_transmute)] +#![allow(clippy::missing_safety_doc)] + +#[cfg(target_os = "macos")] +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/crates/turbo-tasks-signposter-sys/Source/wrapper.h b/crates/turbo-tasks-signposter-sys/Source/wrapper.h new file mode 100644 index 0000000000000..4e0b46fe48627 --- /dev/null +++ b/crates/turbo-tasks-signposter-sys/Source/wrapper.h @@ -0,0 +1 @@ +#include diff --git a/crates/turbo-tasks-signposter-sys/build.rs b/crates/turbo-tasks-signposter-sys/build.rs new file mode 100644 index 0000000000000..0c60eabd3510a --- /dev/null +++ b/crates/turbo-tasks-signposter-sys/build.rs @@ -0,0 +1,31 @@ +use std::{env, path::PathBuf}; + +fn main() { + if env::var("CARGO_CFG_TARGET_OS").unwrap() != "macos" { + return; + } + + let sdk_path = std::process::Command::new("xcrun") + .arg("--show-sdk-path") + .output() + .expect("Failed to execute xcrun") + .stdout; + let sdk_path = std::str::from_utf8(&sdk_path).expect("Failed to parse xcrun output"); + let sdk_path = sdk_path.trim(); + println!("cargo:rustc-link-search={}/usr/lib/log", sdk_path); + + println!("cargo:rustc-link-lib=log_signpost"); + + println!("cargo:rerun-if-changed=src/wrapper.h"); + + let bindings = bindgen::Builder::default() + .header("src/wrapper.h") + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/crates/turbo-tasks-signposter/Source/global.rs b/crates/turbo-tasks-signposter/Source/global.rs new file mode 100644 index 0000000000000..1dabf1e795eb0 --- /dev/null +++ b/crates/turbo-tasks-signposter/Source/global.rs @@ -0,0 +1,46 @@ +use once_cell::sync::OnceCell; + +use crate::{Log, LogCategory}; + +static LOG_INSTANCE:OnceCell = OnceCell::new(); + +#[doc(hidden)] +pub fn global_log() -> &'static Log { + LOG_INSTANCE.get_or_init(|| { + Log::new_with_subsystem_and_category("com.global.Global", LogCategory::PointsOfInterest) + }) +} + +#[macro_export] +macro_rules! event { + ($name:expr) => { + $crate::global_log().signpost().event($name) + }; + ($name:expr, $message:expr) => { + $crate::global_log() + .signpost() + .event_with_message($name, $message) + }; + ($name:expr, $message:expr, $($arg:tt)+) => { + $crate::global_log() + .signpost() + .event_with_message($name, &format!($message, $($arg)+)) + }; +} + +#[macro_export] +macro_rules! interval { + ($name:expr) => { + $crate::global_log().signpost().interval($name) + }; + ($name:expr, $message:expr) => { + $crate::global_log() + .signpost() + .interval_with_message($name, $message) + }; + ($name:expr, $message:expr, $($arg:tt)+) => { + $crate::global_log() + .signpost() + .interval_with_message($name, &format!($message, $($arg)+)) + }; +} diff --git a/crates/turbo-tasks-signposter/Source/lib.rs b/crates/turbo-tasks-signposter/Source/lib.rs new file mode 100644 index 0000000000000..5f7db7460965f --- /dev/null +++ b/crates/turbo-tasks-signposter/Source/lib.rs @@ -0,0 +1,9 @@ +#[cfg(all(target_os = "macos", feature = "global"))] +mod global; +#[cfg(target_os = "macos")] +mod log; + +#[cfg(all(target_os = "macos", feature = "global"))] +pub use global::*; +#[cfg(target_os = "macos")] +pub use log::*; diff --git a/crates/turbo-tasks-signposter/Source/log.rs b/crates/turbo-tasks-signposter/Source/log.rs new file mode 100644 index 0000000000000..1cc48609be673 --- /dev/null +++ b/crates/turbo-tasks-signposter/Source/log.rs @@ -0,0 +1,179 @@ +use std::{ + ffi::{CStr, CString}, + ptr::{addr_of, null}, +}; + +use signposter_sys::*; + +pub enum LogCategory { + /// Signposts provide high-level events that can be used to orient a + /// developer looking at performance data. These will be displayed by + /// default by performance tools like Instruments.app. + PointsOfInterest, + /// Signposts should be disabled by default, reducing the runtime overhead. + /// [`Log::signpost_enabled`] calls will only return 'true' when a + /// performance tool like Instruments.app is recording. + DynamicTracing, + /// Signposts should capture user backtraces. This behavior is more + /// expensive, so [`Log::signpost_enabled`] will only return 'true' when + /// a performance tool like Instruments.app is recording. + DynamicStackTracing, +} + +impl LogCategory { + fn as_c_str(&self) -> &CStr { + match self { + LogCategory::PointsOfInterest => { + CStr::from_bytes_with_nul(b"PointsOfInterest\0").unwrap() + }, + LogCategory::DynamicTracing => CStr::from_bytes_with_nul(b"DynamicTracing\0").unwrap(), + LogCategory::DynamicStackTracing => { + CStr::from_bytes_with_nul(b"DynamicStackTracing\0").unwrap() + }, + } + } +} + +/// A log is a collection of signposts. +#[derive(Debug, Clone, Copy)] +pub struct Log { + os_log:*mut os_log_s, +} + +// Safety: unclear +unsafe impl Sync for Log {} + +// Safety: unclear +unsafe impl Send for Log {} + +impl Default for Log { + fn default() -> Self { + Log { os_log:unsafe { addr_of!(_os_log_default) as *const _ as *mut _ } } + } +} + +impl Log { + /// Create a new log with the given subsystem and category. + pub fn new_with_subsystem_and_category(subsystem:&str, category:LogCategory) -> Self { + let subsystem = CString::new(subsystem).unwrap(); + let category = category.as_c_str(); + let os_log = unsafe { os_log_create(subsystem.as_ptr(), category.as_ptr()) }; + Log { os_log } + } + + /// Create a new [`Signpost`] for this log. + pub fn signpost(&self) -> Signpost { + let id = unsafe { os_signpost_id_generate(self.os_log) }; + Signpost { id, log:self.os_log } + } +} + +/// A signpost is a marker that can be used to annotate a log with +/// information about the execution of a program. +#[derive(Debug, Clone, Copy)] +pub struct Signpost { + id:os_signpost_id_t, + log:*mut os_log_s, +} + +// Safety: unclear +unsafe impl Sync for Signpost {} + +// Safety: unclear +unsafe impl Send for Signpost {} + +// NOTE(alexkirsz) Not sure that's correct, but it's what the Dart SDK does and +// it seems to work. +// See https://github.com/dart-lang/sdk/blob/3e2d3bc77fa8bb5139b869e9b3a5357b5487df18/runtime/vm/timeline_macos.cc#L34-L35 +const FORMAT_BUFFER_LEN:usize = 64; +static FORMAT_BUFFER:[u8; 64] = [0; FORMAT_BUFFER_LEN]; + +#[repr(u8)] +enum SignpostType { + Event = os_signpost_type_t_OS_SIGNPOST_EVENT, + IntervalBegin = os_signpost_type_t_OS_SIGNPOST_INTERVAL_BEGIN, + IntervalEnd = os_signpost_type_t_OS_SIGNPOST_INTERVAL_END, +} + +impl Signpost { + /// Emits a signpost event with the given name. + pub fn event(&self, name:&str) { + let name = CString::new(name).unwrap(); + self.emit(name.as_c_str(), None, SignpostType::Event) + } + + /// Emits a signpost event with the given name and message. + pub fn event_with_message(&self, name:&str, message:&str) { + let name = CString::new(name).unwrap(); + let message = CString::new(escape_message(message)).unwrap(); + self.emit(name.as_c_str(), Some(message.as_c_str()), SignpostType::Event) + } + + /// Starts a new interval signpost with the given name. + pub fn interval(&self, name:&str) -> SignpostInterval { + let name = CString::new(name).unwrap(); + + self.emit(name.as_c_str(), None, SignpostType::IntervalBegin); + + SignpostInterval { signpost:*self, name } + } + + /// Starts a new interval signpost with the given name and message. + pub fn interval_with_message(&self, name:&str, message:&str) -> SignpostInterval { + let name = CString::new(name).unwrap(); + let message = CString::new(escape_message(message)).unwrap(); + + self.emit(name.as_c_str(), Some(message.as_c_str()), SignpostType::IntervalBegin); + + SignpostInterval { signpost:*self, name } + } + + fn emit(&self, name:&CStr, message:Option<&CStr>, signpost_type:SignpostType) { + unsafe { + _os_signpost_emit_with_name_impl( + addr_of!(__dso_handle) as *const _ as *mut _, + self.log, + signpost_type as _, + self.id, + name.as_ptr(), + message.map(|message| message.as_ptr()).unwrap_or(null()), + &FORMAT_BUFFER as *const _ as *mut _, + FORMAT_BUFFER_LEN as _, + ) + } + } +} + +/// A signpost interval. +pub struct SignpostInterval { + signpost:Signpost, + name:CString, +} + +impl SignpostInterval { + /// Ends the interval signpost. Calling this is equivalent to dropping the + /// interval. + pub fn end(self) {} + + /// Ends the interval signpost with the given message. + pub fn end_with_message(self, message:&str) { + let message = CString::new(escape_message(message)).unwrap(); + + self.signpost.emit( + self.name.as_c_str(), + Some(message.as_c_str()), + SignpostType::IntervalEnd, + ) + } +} + +impl Drop for SignpostInterval { + fn drop(&mut self) { + self.signpost.emit(self.name.as_c_str(), None, SignpostType::IntervalEnd); + } +} + +// TODO(alexkirsz) This should likely return a Cow instead. +/// Escapes a message for use with signposts, which will try to parse it as a +/// format string. +fn escape_message(message:&str) -> String { message.replace('%', "%%") } diff --git a/crates/turbo-tasks-signposter/examples/simple_signposter.rs b/crates/turbo-tasks-signposter/examples/simple_signposter.rs new file mode 100644 index 0000000000000..f4a7b19bc5d8a --- /dev/null +++ b/crates/turbo-tasks-signposter/examples/simple_signposter.rs @@ -0,0 +1,16 @@ +#[cfg(target_os = "macos")] +fn main() { + signposter::event!("Event"); + signposter::event!("Event with message", "Event message"); + + let _interval = signposter::interval!("Interval"); + let _interval_with_message = signposter::interval!("Interval with message", "Interval message"); + let interval_with_end_message = + signposter::interval!("Interval with end message", "Interval start message"); + interval_with_end_message.end_with_message("Interval end message"); +} + +#[cfg(not(target_os = "macos"))] +fn main() { + println!("This example only works on macOS."); +} diff --git a/crates/turbo-tasks-testing/Source/lib.rs b/crates/turbo-tasks-testing/Source/lib.rs new file mode 100644 index 0000000000000..ac1036a32d928 --- /dev/null +++ b/crates/turbo-tasks-testing/Source/lib.rs @@ -0,0 +1,271 @@ +//! Testing utilities and macros for turbo-tasks and applications based on it. + +mod macros; +pub mod retry; + +use std::{ + borrow::Cow, + collections::HashMap, + future::Future, + mem::replace, + panic::AssertUnwindSafe, + sync::{Arc, Mutex, Weak}, +}; + +use anyhow::{Result, anyhow}; +use auto_hash_map::AutoMap; +use futures::FutureExt; +use turbo_tasks::{ + CellId, + InvalidationReason, + RawVc, + TaskId, + TraitTypeId, + TurboTasksApi, + TurboTasksCallApi, + backend::CellContent, + event::{Event, EventListener}, + registry, + test_helpers::with_turbo_tasks_for_testing, + util::{SharedError, StaticOrArc}, +}; + +enum Task { + Spawned(Event), + Finished(Result), +} + +#[derive(Default)] +pub struct VcStorage { + this:Weak, + cells:Mutex>, + tasks:Mutex>, +} + +impl TurboTasksCallApi for VcStorage { + fn dynamic_call( + &self, + func:turbo_tasks::FunctionId, + inputs:Vec, + ) -> RawVc { + let this = self.this.upgrade().unwrap(); + let func = registry::get_function(func).bind(&inputs); + let handle = tokio::runtime::Handle::current(); + let future = func(); + let i = { + let mut tasks = self.tasks.lock().unwrap(); + let i = tasks.len(); + tasks.push(Task::Spawned(Event::new(move || format!("Task({i})::event")))); + i + }; + let id = TaskId::from(i as u32 + 1); + handle.spawn(with_turbo_tasks_for_testing(this.clone(), id, async move { + let result = AssertUnwindSafe(future).catch_unwind().await; + + // Convert the unwind panic to an anyhow error that can be cloned. + let result = result + .map_err(|any| { + match any.downcast::() { + Ok(owned) => anyhow!(owned), + Err(any) => { + match any.downcast::<&'static str>() { + Ok(str) => anyhow!(str), + Err(_) => anyhow!("unknown panic"), + } + }, + } + }) + .and_then(|r| r) + .map_err(SharedError::new); + + let mut tasks = this.tasks.lock().unwrap(); + if let Task::Spawned(event) = replace(&mut tasks[i], Task::Finished(result)) { + event.notify(usize::MAX); + } + })); + RawVc::TaskOutput(id) + } + + fn native_call( + &self, + _func:turbo_tasks::FunctionId, + _inputs:Vec, + ) -> RawVc { + unreachable!() + } + + fn trait_call( + &self, + _trait_type:turbo_tasks::TraitTypeId, + _trait_fn_name:Cow<'static, str>, + _inputs:Vec, + ) -> RawVc { + unreachable!() + } + + fn run_once( + &self, + _future:std::pin::Pin> + Send + 'static>>, + ) -> TaskId { + unreachable!() + } + + fn run_once_with_reason( + &self, + _reason:StaticOrArc, + _future:std::pin::Pin> + Send + 'static>>, + ) -> TaskId { + unreachable!() + } + + fn run_once_process( + &self, + _future:std::pin::Pin> + Send + 'static>>, + ) -> TaskId { + unreachable!() + } +} + +impl TurboTasksApi for VcStorage { + fn pin(&self) -> Arc { self.this.upgrade().unwrap() } + + fn invalidate(&self, _task:TaskId) { unreachable!() } + + fn invalidate_with_reason( + &self, + _task:TaskId, + _reason:turbo_tasks::util::StaticOrArc, + ) { + unreachable!() + } + + fn notify_scheduled_tasks(&self) { + // ignore + } + + fn try_read_task_output( + &self, + id:TaskId, + _strongly_consistent:bool, + ) -> Result> { + let tasks = self.tasks.lock().unwrap(); + let i = *id - 1; + let task = tasks.get(i as usize).unwrap(); + match task { + Task::Spawned(event) => Ok(Err(event.listen())), + Task::Finished(result) => { + match result { + Ok(vc) => Ok(Ok(*vc)), + Err(err) => Err(anyhow!(err.clone())), + } + }, + } + } + + fn try_read_task_output_untracked( + &self, + task:TaskId, + strongly_consistent:bool, + ) -> Result> { + self.try_read_task_output(task, strongly_consistent) + } + + fn try_read_task_cell( + &self, + task:TaskId, + index:CellId, + ) -> Result> { + let map = self.cells.lock().unwrap(); + if let Some(cell) = map.get(&(task, index)) { + Ok(Ok(cell.clone())) + } else { + Ok(Ok(CellContent::default())) + } + } + + fn try_read_task_cell_untracked( + &self, + task:TaskId, + index:CellId, + ) -> Result> { + let map = self.cells.lock().unwrap(); + if let Some(cell) = map.get(&(task, index)) { + Ok(Ok(cell.clone())) + } else { + Ok(Ok(CellContent::default())) + } + } + + fn try_read_own_task_cell_untracked( + &self, + current_task:TaskId, + index:CellId, + ) -> Result { + self.read_own_task_cell(current_task, index) + } + + fn emit_collectible(&self, _trait_type:turbo_tasks::TraitTypeId, _collectible:RawVc) { + unimplemented!() + } + + fn unemit_collectible( + &self, + _trait_type:turbo_tasks::TraitTypeId, + _collectible:RawVc, + _count:u32, + ) { + unimplemented!() + } + + fn unemit_collectibles( + &self, + _trait_type:turbo_tasks::TraitTypeId, + _collectibles:&AutoMap, + ) { + unimplemented!() + } + + fn read_task_collectibles(&self, _task:TaskId, _trait_id:TraitTypeId) -> AutoMap { + unimplemented!() + } + + fn read_own_task_cell(&self, task:TaskId, index:CellId) -> Result { + let map = self.cells.lock().unwrap(); + if let Some(cell) = map.get(&(task, index)) { + Ok(cell.clone()) + } else { + Ok(CellContent::default()) + } + } + + fn update_own_task_cell(&self, task:TaskId, index:CellId, content:CellContent) { + let mut map = self.cells.lock().unwrap(); + let cell = map.entry((task, index)).or_default(); + *cell = content; + } + + fn connect_task(&self, _task:TaskId) { + // no-op + } + + fn mark_own_task_as_finished(&self, _task:TaskId) { + // no-op + } + + fn detached( + &self, + _f:std::pin::Pin> + Send + 'static>>, + ) -> std::pin::Pin> + Send + 'static>> { + unimplemented!() + } +} + +impl VcStorage { + pub fn with(f:impl Future) -> impl Future { + with_turbo_tasks_for_testing( + Arc::new_cyclic(|weak| VcStorage { this:weak.clone(), ..Default::default() }), + TaskId::from(u32::MAX), + f, + ) + } +} diff --git a/crates/turbo-tasks-testing/Source/macros.rs b/crates/turbo-tasks-testing/Source/macros.rs new file mode 100644 index 0000000000000..b0e87fcb031e6 --- /dev/null +++ b/crates/turbo-tasks-testing/Source/macros.rs @@ -0,0 +1,26 @@ +#[macro_export] +macro_rules! register { + () => { + lazy_static::lazy_static! { + static ref REGISTER: () = { + turbo_tasks::register(); + include!(concat!(env!("OUT_DIR"), "/register_test_", module_path!(), ".rs")); + }; + } + }; +} + +#[macro_export] +macro_rules! run { + ($($stmt:tt)+) => {{ + use turbo_tasks::TurboTasks; + use turbo_tasks_memory::MemoryBackend; + *REGISTER; + let tt = TurboTasks::new(MemoryBackend::default()); + tt.run_once(async { + $($stmt)+ + Ok(()) + }) + .await.unwrap(); + }}; +} diff --git a/crates/turbo-tasks-testing/Source/retry.rs b/crates/turbo-tasks-testing/Source/retry.rs new file mode 100644 index 0000000000000..396a6292e1227 --- /dev/null +++ b/crates/turbo-tasks-testing/Source/retry.rs @@ -0,0 +1,45 @@ +use std::{future::Future, time::Duration}; + +pub fn retry(mut args:A, f:F, max_retries:usize, mut timeout:Duration) -> Result +where + F: Fn(&mut A) -> Result, { + let mut retries = 0usize; + loop { + match f(&mut args) { + Ok(value) => return Ok(value), + Err(e) => { + if retries >= max_retries { + return Err(e); + } + retries += 1; + std::thread::sleep(timeout); + timeout += timeout; + }, + } + } +} + +pub async fn retry_async( + mut args:A, + f:F, + max_retries:usize, + mut timeout:Duration, +) -> Result +where + F: Fn(&mut A) -> Fut, + Fut: Future>, { + let mut retries = 0usize; + loop { + match f(&mut args).await { + Ok(value) => return Ok(value), + Err(e) => { + if retries >= max_retries { + return Err(e); + } + retries += 1; + tokio::time::sleep(timeout).await; + timeout += timeout; + }, + } + } +} diff --git a/crates/turbo-tasks-tracing-signpost/Source/layer.rs b/crates/turbo-tasks-tracing-signpost/Source/layer.rs new file mode 100644 index 0000000000000..6a209053e3f79 --- /dev/null +++ b/crates/turbo-tasks-tracing-signpost/Source/layer.rs @@ -0,0 +1,116 @@ +use dashmap::DashMap; +use signposter::{Log, LogCategory, Signpost, SignpostInterval}; +use tracing::{Event, Id, span, subscriber::Subscriber}; +use tracing_subscriber::{Layer, layer::Context}; + +/// A [`tracing::Layer`] implementation that emits signposts for each span and +/// event. +pub struct SignpostLayer { + signposts:DashMap, + current_intervals:DashMap, + log:Log, +} + +impl Default for SignpostLayer { + /// Create a new `SignpostLayer`. + fn default() -> SignpostLayer { + SignpostLayer { + signposts:Default::default(), + current_intervals:Default::default(), + log:Log::new_with_subsystem_and_category( + "com.global.Global", + LogCategory::PointsOfInterest, + ), + } + } +} + +impl Layer for SignpostLayer +where + S: Subscriber, +{ + fn on_event(&self, event:&Event<'_>, _ctx:Context<'_, S>) { + let mut visitor:KeyValueVisitor = KeyValueVisitor::new(); + + event.record(&mut visitor); + + self.log.signpost().event_with_message(event.metadata().name(), &visitor.output); + } + + fn on_new_span(&self, attrs:&span::Attributes<'_>, id:&span::Id, _ctx:Context<'_, S>) { + let mut visitor:KeyValueVisitor = KeyValueVisitor::new(); + + attrs.record(&mut visitor); + + self.signposts.insert( + id.clone(), + SignpostDescriptor { + name:attrs.metadata().name().to_string(), + description:visitor.output, + signpost:self.log.signpost(), + }, + ); + } + + fn on_enter(&self, id:&span::Id, _ctx:Context<'_, S>) { + let signpost = self.signposts.get(id).unwrap(); + self.current_intervals.insert( + id.clone(), + signpost.signpost.interval_with_message(&signpost.name, &signpost.description), + ); + } + + fn on_exit(&self, id:&span::Id, _ctx:Context<'_, S>) { + let (_, interval) = self.current_intervals.remove(id).unwrap(); + interval.end(); + } +} + +struct SignpostDescriptor { + name:String, + description:String, + signpost:Signpost, +} + +use std::fmt; + +use tracing::field::{Field, Visit}; + +struct KeyValueVisitor { + output:String, + first:bool, +} + +impl KeyValueVisitor { + fn new() -> Self { KeyValueVisitor { output:String::new(), first:true } } +} + +impl Visit for KeyValueVisitor { + fn record_debug(&mut self, field:&Field, value:&dyn fmt::Debug) { + self.record_any(field, format!("{:?}", value)); + } + + fn record_i64(&mut self, field:&Field, value:i64) { self.record_any(field, value.to_string()); } + + fn record_u64(&mut self, field:&Field, value:u64) { self.record_any(field, value.to_string()); } + + fn record_bool(&mut self, field:&Field, value:bool) { + self.record_any(field, value.to_string()); + } + + fn record_str(&mut self, field:&Field, value:&str) { + self.record_any(field, value.to_string()); + } +} + +impl KeyValueVisitor { + fn record_any(&mut self, field:&Field, value:T) { + if !self.first { + self.output.push_str(", "); + } else { + self.first = false; + } + + self.output.push_str(&format!("{}: {}", field.name(), value)); + } +} diff --git a/crates/turbo-tasks-tracing-signpost/Source/lib.rs b/crates/turbo-tasks-tracing-signpost/Source/lib.rs new file mode 100644 index 0000000000000..3d96f58f259df --- /dev/null +++ b/crates/turbo-tasks-tracing-signpost/Source/lib.rs @@ -0,0 +1,5 @@ +#[cfg(target_os = "macos")] +mod layer; + +#[cfg(target_os = "macos")] +pub use layer::SignpostLayer; diff --git a/crates/turbo-tasks/Source/backend.rs b/crates/turbo-tasks/Source/backend.rs new file mode 100644 index 0000000000000..3f6d7730d6bf0 --- /dev/null +++ b/crates/turbo-tasks/Source/backend.rs @@ -0,0 +1,443 @@ +use std::{ + any::Any, + borrow::Cow, + fmt, + fmt::{Debug, Display, Write}, + future::Future, + mem::take, + pin::Pin, + sync::Arc, + time::Duration, +}; + +use anyhow::{Result, anyhow, bail}; +use auto_hash_map::AutoMap; +use serde::{Deserialize, Serialize}; +use tracing::Span; + +pub use crate::id::BackendJobId; +use crate::{ + ConcreteTaskInput, + FunctionId, + RawVc, + ReadRef, + SharedReference, + TaskId, + TaskIdProvider, + TaskIdSet, + TraitRef, + TraitTypeId, + VcValueTrait, + VcValueType, + event::EventListener, + manager::TurboTasksBackendApi, + raw_vc::CellId, + registry, +}; + +pub enum TaskType { + /// Tasks that only exist for a certain operation and + /// won't persist between sessions + Transient(TransientTaskType), + + /// Tasks that can persist between sessions and potentially + /// shared globally + Persistent(PersistentTaskType), +} + +type TransientTaskRoot = + Box Pin> + Send>> + Send + Sync>; + +pub enum TransientTaskType { + /// A root task that will track dependencies and re-execute when + /// dependencies change. Task will eventually settle to the correct + /// execution. + /// Always active. Automatically scheduled. + Root(TransientTaskRoot), + + // TODO implement these strongly consistency + /// A single root task execution. It won't track dependencies. + /// Task will definitely include all invalidations that happened before the + /// start of the task. It may or may not include invalidations that + /// happened after that. It may see these invalidations partially + /// applied. + /// Active until done. Automatically scheduled. + Once(Pin> + Send + 'static>>), +} + +impl Debug for TransientTaskType { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Root(_) => f.debug_tuple("Root").finish(), + Self::Once(_) => f.debug_tuple("Once").finish(), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub enum PersistentTaskType { + /// A normal task execution a native (rust) function + Native(FunctionId, Vec), + + /// A resolve task, which resolves arguments and calls the function with + /// resolve arguments. The inner function call will do a cache lookup. + ResolveNative(FunctionId, Vec), + + /// A trait method resolve task. It resolves the first (`self`) argument and + /// looks up the trait method on that value. Then it calls that method. + /// The method call will do a cache lookup and might resolve arguments + /// before. + ResolveTrait(TraitTypeId, Cow<'static, str>, Vec), +} + +impl Display for PersistentTaskType { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Native(fid, _) | Self::ResolveNative(fid, _) => { + Display::fmt(®istry::get_function(*fid).name, f) + }, + Self::ResolveTrait(tid, n, _) => { + write!(f, "{}::{n}", registry::get_trait(*tid).name) + }, + } + } +} + +impl PersistentTaskType { + pub fn shrink_to_fit(&mut self) { + match self { + Self::Native(_, inputs) => inputs.shrink_to_fit(), + Self::ResolveNative(_, inputs) => inputs.shrink_to_fit(), + Self::ResolveTrait(_, _, inputs) => inputs.shrink_to_fit(), + } + } + + pub fn len(&self) -> usize { + match self { + PersistentTaskType::Native(_, v) + | PersistentTaskType::ResolveNative(_, v) + | PersistentTaskType::ResolveTrait(_, _, v) => v.len(), + } + } + + pub fn is_empty(&self) -> bool { + match self { + PersistentTaskType::Native(_, v) + | PersistentTaskType::ResolveNative(_, v) + | PersistentTaskType::ResolveTrait(_, _, v) => v.is_empty(), + } + } + + pub fn partial(&self, len:usize) -> Self { + match self { + PersistentTaskType::Native(f, v) => PersistentTaskType::Native(*f, v[..len].to_vec()), + PersistentTaskType::ResolveNative(f, v) => { + PersistentTaskType::ResolveNative(*f, v[..len].to_vec()) + }, + PersistentTaskType::ResolveTrait(f, n, v) => { + PersistentTaskType::ResolveTrait(*f, n.clone(), v[..len].to_vec()) + }, + } + } +} + +pub struct TaskExecutionSpec { + pub future:Pin> + Send>>, + pub span:Span, +} + +// TODO technically CellContent is already indexed by the ValueTypeId, so we +// don't need to store it here +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct CellContent(pub Option); + +impl Display for CellContent { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.0 { + None => write!(f, "empty"), + Some(content) => Display::fmt(content, f), + } + } +} + +impl CellContent { + pub fn cast(self) -> Result> { + let data = self.0.ok_or_else(|| anyhow!("Cell is empty"))?; + let data = data.downcast().ok_or_else(|| anyhow!("Unexpected type in cell"))?; + Ok(ReadRef::new(data)) + } + + /// # Safety + /// + /// The caller must ensure that the CellContent contains a vc that + /// implements T. + pub fn cast_trait(self) -> Result> + where + T: VcValueTrait + ?Sized, { + let shared_reference = self.0.ok_or_else(|| anyhow!("Cell is empty"))?; + if shared_reference.0.is_none() { + bail!("Cell content is untyped"); + } + Ok( + // Safety: We just checked that the content is typed. + TraitRef::new(shared_reference), + ) + } + + pub fn try_cast(self) -> Option> { + self.0.and_then(|data| data.downcast().map(|data| ReadRef::new(data))) + } +} + +pub trait Backend: Sync + Send { + #[allow(unused_variables)] + fn initialize(&mut self, task_id_provider:&dyn TaskIdProvider) {} + + #[allow(unused_variables)] + fn startup(&self, turbo_tasks:&dyn TurboTasksBackendApi) {} + + #[allow(unused_variables)] + fn stop(&self, turbo_tasks:&dyn TurboTasksBackendApi) {} + + #[allow(unused_variables)] + fn idle_start(&self, turbo_tasks:&dyn TurboTasksBackendApi) {} + + fn invalidate_task(&self, task:TaskId, turbo_tasks:&dyn TurboTasksBackendApi); + + fn invalidate_tasks(&self, tasks:&[TaskId], turbo_tasks:&dyn TurboTasksBackendApi); + fn invalidate_tasks_set(&self, tasks:&TaskIdSet, turbo_tasks:&dyn TurboTasksBackendApi); + + fn get_task_description(&self, task:TaskId) -> String; + + type ExecutionScopeFuture> + Send + 'static>: Future> + + Send + + 'static; + + fn execution_scope> + Send + 'static>( + &self, + task:TaskId, + future:T, + ) -> Self::ExecutionScopeFuture; + + fn try_start_task_execution( + &self, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Option; + + fn task_execution_result( + &self, + task:TaskId, + result:Result, Option>>, + turbo_tasks:&dyn TurboTasksBackendApi, + ); + + fn task_execution_completed( + &self, + task:TaskId, + duration:Duration, + memory_usage:usize, + stateful:bool, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> bool; + + fn run_backend_job<'a>( + &'a self, + id:BackendJobId, + turbo_tasks:&'a dyn TurboTasksBackendApi, + ) -> Pin + Send + 'a>>; + + fn try_read_task_output( + &self, + task:TaskId, + reader:TaskId, + strongly_consistent:bool, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result>; + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + fn try_read_task_output_untracked( + &self, + task:TaskId, + strongly_consistent:bool, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result>; + + fn try_read_task_cell( + &self, + task:TaskId, + index:CellId, + reader:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result>; + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + fn try_read_task_cell_untracked( + &self, + task:TaskId, + index:CellId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result>; + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + fn try_read_own_task_cell_untracked( + &self, + current_task:TaskId, + index:CellId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> Result { + match self.try_read_task_cell_untracked(current_task, index, turbo_tasks)? { + Ok(content) => Ok(content), + Err(_) => Ok(CellContent(None)), + } + } + + fn read_task_collectibles( + &self, + task:TaskId, + trait_id:TraitTypeId, + reader:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> AutoMap; + + fn emit_collectible( + &self, + trait_type:TraitTypeId, + collectible:RawVc, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ); + + fn unemit_collectible( + &self, + trait_type:TraitTypeId, + collectible:RawVc, + count:u32, + task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ); + + fn update_task_cell( + &self, + task:TaskId, + index:CellId, + content:CellContent, + turbo_tasks:&dyn TurboTasksBackendApi, + ); + + fn get_or_create_persistent_task( + &self, + task_type:PersistentTaskType, + parent_task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> TaskId; + + fn connect_task( + &self, + task:TaskId, + parent_task:TaskId, + turbo_tasks:&dyn TurboTasksBackendApi, + ); + + fn mark_own_task_as_finished( + &self, + _task:TaskId, + _turbo_tasks:&dyn TurboTasksBackendApi, + ) { + // Do nothing by default + } + + fn create_transient_task( + &self, + task_type:TransientTaskType, + turbo_tasks:&dyn TurboTasksBackendApi, + ) -> TaskId; + + fn dispose_root_task(&self, task:TaskId, turbo_tasks:&dyn TurboTasksBackendApi); +} + +impl PersistentTaskType { + pub async fn run_resolve_native( + fn_id:FunctionId, + mut inputs:Vec, + turbo_tasks:Arc>, + ) -> Result { + for i in 0..inputs.len() { + let input = unsafe { take(inputs.get_unchecked_mut(i)) }; + let input = input.resolve().await?; + unsafe { + *inputs.get_unchecked_mut(i) = input; + } + } + Ok(turbo_tasks.native_call(fn_id, inputs)) + } + + pub async fn run_resolve_trait( + trait_type:TraitTypeId, + name:Cow<'static, str>, + inputs:Vec, + turbo_tasks:Arc>, + ) -> Result { + let mut resolved_inputs = Vec::with_capacity(inputs.len()); + let mut iter = inputs.into_iter(); + if let Some(this) = iter.next() { + let this = this.resolve().await?; + let this_value = this.clone().resolve_to_value().await?; + match this_value.get_trait_method(trait_type, name) { + Ok(native_fn) => { + resolved_inputs.push(this); + for input in iter { + resolved_inputs.push(input) + } + Ok(turbo_tasks.dynamic_call(native_fn, resolved_inputs)) + }, + Err(name) => { + if !this_value.has_trait(trait_type) { + let traits = + this_value.traits().iter().fold(String::new(), |mut out, t| { + let _ = write!(out, " {}", t); + out + }); + Err(anyhow!( + "{} doesn't implement {} (only{})", + this_value, + registry::get_trait(trait_type), + traits, + )) + } else { + Err(anyhow!( + "{} implements trait {}, but method {} is missing", + this_value, + registry::get_trait(trait_type), + name + )) + } + }, + } + } else { + panic!("No arguments for trait call"); + } + } + + pub fn run( + self, + turbo_tasks:Arc>, + ) -> Pin> + Send>> { + match self { + PersistentTaskType::Native(fn_id, inputs) => { + let native_fn = registry::get_function(fn_id); + let bound = native_fn.bind(&inputs); + (bound)() + }, + PersistentTaskType::ResolveNative(fn_id, inputs) => { + Box::pin(Self::run_resolve_native(fn_id, inputs, turbo_tasks)) + }, + PersistentTaskType::ResolveTrait(trait_type, name, inputs) => { + Box::pin(Self::run_resolve_trait(trait_type, name, inputs, turbo_tasks)) + }, + } + } +} diff --git a/crates/turbo-tasks/Source/capture_future.rs b/crates/turbo-tasks/Source/capture_future.rs new file mode 100644 index 0000000000000..9088ad8604489 --- /dev/null +++ b/crates/turbo-tasks/Source/capture_future.rs @@ -0,0 +1,74 @@ +use std::{ + future::Future, + pin::Pin, + sync::{Arc, Mutex}, + task::{Context, Poll}, + time::{Duration, Instant}, +}; + +use pin_project_lite::pin_project; +use tokio::{task::futures::TaskLocalFuture, task_local}; +use turbo_tasks_malloc::{AllocationInfo, TurboMalloc}; + +task_local! { + static EXTRA: Arc>; +} + +pin_project! { + pub struct CaptureFuture> { + cell: Arc>, + #[pin] + future: TaskLocalFuture>, F>, + duration: Duration, + allocations: usize, + deallocations: usize, + } +} + +impl> CaptureFuture { + pub fn new(future:F) -> Self { + let cell = Arc::new(Mutex::new((Duration::ZERO, 0, 0))); + Self { + future:EXTRA.scope(cell.clone(), future), + cell, + duration:Duration::ZERO, + allocations:0, + deallocations:0, + } + } +} + +pub fn add_duration(duration:Duration) { EXTRA.with(|cell| cell.lock().unwrap().0 += duration); } + +pub fn add_allocation_info(alloc_info:AllocationInfo) { + EXTRA.with(|cell| { + let mut guard = cell.lock().unwrap(); + guard.1 += alloc_info.allocations; + guard.2 += alloc_info.deallocations; + }); +} + +impl> Future for CaptureFuture { + type Output = (T, Duration, Instant, usize); + + fn poll(self: Pin<&mut Self>, cx:&mut Context<'_>) -> Poll { + let this = self.project(); + let start = Instant::now(); + let start_allocations = TurboMalloc::allocation_counters(); + let result = this.future.poll(cx); + let elapsed = start.elapsed(); + let allocations = start_allocations.until_now(); + *this.duration += elapsed; + *this.allocations += allocations.allocations; + *this.deallocations += allocations.deallocations; + match result { + Poll::Ready(r) => { + let (duration, allocations, deallocations) = *this.cell.lock().unwrap(); + let memory_usage = (*this.allocations + allocations) + .saturating_sub(*this.deallocations + deallocations); + Poll::Ready((r, *this.duration + duration, start + elapsed, memory_usage)) + }, + Poll::Pending => Poll::Pending, + } + } +} diff --git a/crates/turbo-tasks/Source/collectibles.rs b/crates/turbo-tasks/Source/collectibles.rs new file mode 100644 index 0000000000000..55183c1dc638f --- /dev/null +++ b/crates/turbo-tasks/Source/collectibles.rs @@ -0,0 +1,8 @@ +use auto_hash_map::AutoSet; + +use crate::{Vc, VcValueTrait}; + +pub trait CollectiblesSource { + fn take_collectibles(self) -> AutoSet>; + fn peek_collectibles(self) -> AutoSet>; +} diff --git a/crates/turbo-tasks/Source/completion.rs b/crates/turbo-tasks/Source/completion.rs new file mode 100644 index 0000000000000..4303cf107e41a --- /dev/null +++ b/crates/turbo-tasks/Source/completion.rs @@ -0,0 +1,66 @@ +use crate::{self as turbo_tasks, RawVc, TryJoinIterExt, Vc}; +/// Just an empty type, but it's never equal to itself. +/// [Vc] can be used as return value instead of `()` +/// to have a concrete reference that can be awaited. +/// It will invalidate the awaiting task everytime the referenced +/// task has been executed. +#[turbo_tasks::value(cell = "new")] +pub struct Completion; + +#[turbo_tasks::value_impl] +impl Completion { + /// This will always be the same and never invalidates the reading task. + #[turbo_tasks::function] + pub fn immutable() -> Vc { Completion::cell(Completion) } +} + +// no #[turbo_tasks::value_impl] to inline new into the caller task +// this ensures it's re-created on each execution +impl Completion { + /// This will always be a new completion and invalidates the reading task. + pub fn new() -> Vc { Completion::cell(Completion) } + + /// Uses the previous completion. Can be used to cancel without triggering a + /// new invalidation. + pub fn unchanged() -> Vc { + // This is the same code that Completion::cell uses except that it + // only updates the cell when it is empty (Completion::cell opted-out of + // that via `#[turbo_tasks::value(cell = "new")]`) + let cell = turbo_tasks::macro_helpers::find_cell_by_type(*COMPLETION_VALUE_TYPE_ID); + cell.conditional_update_shared(|old| old.is_none().then_some(Completion)); + let raw:RawVc = cell.into(); + raw.into() + } +} + +#[turbo_tasks::value(transparent)] +pub struct Completions(Vec>); + +#[turbo_tasks::value_impl] +impl Completions { + /// Merges multiple completions into one. The passed list will be part of + /// the cache key, so this function should not be used with varying lists. + /// + /// Varying lists should use `Vc::cell(list).completed()` + /// instead. + #[turbo_tasks::function] + pub fn all(completions:Vec>) -> Vc { + Vc::::cell(completions).completed() + } + + /// Merges the list of completions into one. + #[turbo_tasks::function] + pub async fn completed(self: Vc) -> anyhow::Result> { + self.await? + .iter() + .map(|&c| { + async move { + c.await?; + Ok(()) + } + }) + .try_join() + .await?; + Ok(Completion::new()) + } +} diff --git a/crates/turbo-tasks/Source/debug/internal.rs b/crates/turbo-tasks/Source/debug/internal.rs new file mode 100644 index 0000000000000..7ba0c902c926f --- /dev/null +++ b/crates/turbo-tasks/Source/debug/internal.rs @@ -0,0 +1,106 @@ +use std::{borrow::Cow, future::Future}; + +use futures::future::join_all; +pub use turbo_tasks_macros::ValueDebug; + +/// Representation of a named field of a structure for formatting purposes of +/// `ValueDebug` implementations. +#[derive(Debug)] +pub struct FormattingField<'a> { + name:&'a str, + contents:String, +} + +impl<'a> FormattingField<'a> { + pub fn new(name:&'a str, contents:String) -> Self { Self { name, contents } } +} + +/// Representation of a named field of a structure for formatting purposes of +/// `ValueDebug` implementations. +#[derive(Debug)] +pub struct AsyncFormattingField<'a, Fut> +where + Fut: Future, { + name:&'a str, + contents:Fut, +} + +impl<'a, Fut:Future> AsyncFormattingField<'a, Fut> +where + Fut: Future, +{ + pub fn new(name:&'a str, contents:Fut) -> Self { Self { name, contents } } + + pub async fn resolve(self) -> FormattingField<'a> { + let Self { name, contents } = self; + FormattingField { name, contents:contents.await } + } +} + +/// Representation of a structure for formatting purposes of `ValueDebug` +/// implementations. +pub enum FormattingStruct<'a> { + /// Structure with named fields (e.g. `struct Foo { bar: u32 }`). + Named { name:&'a str, fields:Vec> }, + /// Structure with unnamed fields (e.g. `struct Foo(u32)`, `Foo::Bar(u32)`). + Unnamed { name:&'a str, fields:Vec }, +} + +impl<'a> FormattingStruct<'a> { + pub fn new_named(name:&'a str, fields:Vec>) -> Self { + Self::Named { name, fields } + } + + pub fn new_unnamed(name:&'a str, fields:Vec) -> Self { Self::Unnamed { name, fields } } + + pub async fn new_named_async( + name:&'a str, + fields:Vec>>, + ) -> Self { + Self::Named { + name, + fields:join_all(fields.into_iter().map(AsyncFormattingField::resolve)).await, + } + } + + pub async fn new_unnamed_async(name:&'a str, fields:Vec>) -> Self { + Self::Unnamed { name, fields:join_all(fields).await } + } +} + +impl<'a> std::fmt::Debug for FormattingStruct<'a> { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + FormattingStruct::Named { name, fields } => { + let mut debug_struct = f.debug_struct(name); + for field in fields { + debug_struct.field(field.name, &PassthroughDebug::new_str(&field.contents)); + } + debug_struct.finish() + }, + FormattingStruct::Unnamed { name, fields } => { + let mut debug_tuple = f.debug_tuple(name); + for field in fields { + debug_tuple.field(&PassthroughDebug::new_str(field)); + } + debug_tuple.finish() + }, + } + } +} + +/// Debug implementation that prints an unquoted, unescaped string. +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PassthroughDebug<'a>(Cow<'a, str>); + +impl<'a> PassthroughDebug<'a> { + pub fn new_str(s:&'a str) -> Self { Self(Cow::Borrowed(s)) } + + pub fn new_string(s:String) -> Self { Self(Cow::Owned(s)) } +} + +impl<'a> std::fmt::Debug for PassthroughDebug<'a> { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.0.as_ref()) + } +} diff --git a/crates/turbo-tasks/Source/debug/mod.rs b/crates/turbo-tasks/Source/debug/mod.rs new file mode 100644 index 0000000000000..e7ce9105cf794 --- /dev/null +++ b/crates/turbo-tasks/Source/debug/mod.rs @@ -0,0 +1,381 @@ +use std::fmt::{Debug, Display}; + +use auto_hash_map::{AutoMap, AutoSet}; +use indexmap::{IndexMap, IndexSet}; +use turbo_tasks::Vc; +pub use turbo_tasks_macros::ValueDebugFormat; + +use crate::{self as turbo_tasks}; + +#[doc(hidden)] +pub mod internal; +mod vdbg; + +use internal::PassthroughDebug; + +/// The return type of `ValueDebug::dbg`. +/// +/// We don't use `Vc` directly because we don't want the +/// `Debug`/`Display` representations to be escaped. +#[turbo_tasks::value] +pub struct ValueDebugString(String); + +impl Debug for ValueDebugString { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&self.0) } +} + +impl Display for ValueDebugString { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&self.0) } +} + +impl ValueDebugString { + /// Returns the underlying string. + pub fn as_str(&self) -> &str { &self.0 } +} + +impl ValueDebugString { + /// Create a new `ValueDebugString` from a string. + pub fn new(s:String) -> Vc { ValueDebugString::cell(ValueDebugString(s)) } +} + +/// `Debug`-like trait for `Vc` types, automatically derived when using +/// `turbo_tasks::value` and `turbo_tasks::value_trait`. +/// +/// # Usage +/// +/// ```ignore +/// dbg!(any_vc.dbg().await?); +/// ``` +#[turbo_tasks::value_trait(no_debug)] +pub trait ValueDebug { + fn dbg(self: Vc) -> Vc; + + /// Like `dbg`, but with a depth limit. + fn dbg_depth(self: Vc, depth:usize) -> Vc; +} + +/// Use [autoref specialization] to implement `ValueDebug` for `T: Debug`. +/// +/// [autoref specialization] https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md +pub trait ValueDebugFormat { + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString; +} + +impl ValueDebugFormat for String { + fn value_debug_format(&self, _depth:usize) -> ValueDebugFormatString { + ValueDebugFormatString::Sync(format!("{:#?}", self)) + } +} + +// Use autoref specialization [1] to implement `ValueDebugFormat` for `T: +// Debug` as a fallback if `T` does not implement it directly, hence the `for +// &T` clause. +// +// [1] https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md +impl ValueDebugFormat for &T +where + T: Debug, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + ValueDebugFormatString::Sync(format!("{:#?}", self)) + } +} + +impl ValueDebugFormat for Option +where + T: ValueDebugFormat, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + match self { + None => ValueDebugFormatString::Sync(format!("{:#?}", Option::<()>::None)), + Some(value) => { + match value.value_debug_format(depth.saturating_sub(1)) { + ValueDebugFormatString::Sync(string) => { + ValueDebugFormatString::Sync(format!( + "{:#?}", + Some(PassthroughDebug::new_string(string)) + )) + }, + ValueDebugFormatString::Async(future) => { + ValueDebugFormatString::Async(Box::pin(async move { + let string = future.await?; + Ok(format!("{:#?}", Some(PassthroughDebug::new_string(string)))) + })) + }, + } + }, + } + } +} + +impl ValueDebugFormat for Vec +where + T: ValueDebugFormat, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + let values = self + .iter() + .map(|value| value.value_debug_format(depth.saturating_sub(1))) + .collect::>(); + + ValueDebugFormatString::Async(Box::pin(async move { + let mut values_string = vec![]; + for value in values { + match value { + ValueDebugFormatString::Sync(string) => { + values_string.push(PassthroughDebug::new_string(string)); + }, + ValueDebugFormatString::Async(future) => { + values_string.push(PassthroughDebug::new_string(future.await?)); + }, + } + } + Ok(format!("{:#?}", values_string)) + })) + } +} + +impl ValueDebugFormat for AutoSet +where + K: ValueDebugFormat, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + let values = self + .iter() + .map(|item| item.value_debug_format(depth.saturating_sub(1))) + .collect::>(); + + ValueDebugFormatString::Async(Box::pin(async move { + let mut values_string = Vec::with_capacity(values.len()); + for item in values { + match item { + ValueDebugFormatString::Sync(string) => { + values_string.push(PassthroughDebug::new_string(string)); + }, + ValueDebugFormatString::Async(future) => { + values_string.push(PassthroughDebug::new_string(future.await?)); + }, + } + } + Ok(format!("{:#?}", values_string)) + })) + } +} + +impl ValueDebugFormat for std::collections::HashMap +where + K: Debug, + V: ValueDebugFormat, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + let values = self + .iter() + .map(|(key, value)| { + (format!("{:#?}", key), value.value_debug_format(depth.saturating_sub(1))) + }) + .collect::>(); + + ValueDebugFormatString::Async(Box::pin(async move { + let mut values_string = std::collections::HashMap::new(); + for (key, value) in values { + match value { + ValueDebugFormatString::Sync(string) => { + values_string.insert(key, PassthroughDebug::new_string(string)); + }, + ValueDebugFormatString::Async(future) => { + values_string.insert(key, PassthroughDebug::new_string(future.await?)); + }, + } + } + Ok(format!("{:#?}", values_string)) + })) + } +} + +impl ValueDebugFormat for AutoMap +where + K: Debug, + V: ValueDebugFormat, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + let values = self + .iter() + .map(|(key, value)| { + (format!("{:#?}", key), value.value_debug_format(depth.saturating_sub(1))) + }) + .collect::>(); + + ValueDebugFormatString::Async(Box::pin(async move { + let mut values_string = AutoMap::new(); + for (key, value) in values { + match value { + ValueDebugFormatString::Sync(string) => { + values_string.insert(key, PassthroughDebug::new_string(string)); + }, + ValueDebugFormatString::Async(future) => { + values_string.insert(key, PassthroughDebug::new_string(future.await?)); + }, + } + } + Ok(format!("{:#?}", values_string)) + })) + } +} + +impl ValueDebugFormat for IndexSet +where + T: ValueDebugFormat, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + let values = self + .iter() + .map(|value| value.value_debug_format(depth.saturating_sub(1))) + .collect::>(); + + ValueDebugFormatString::Async(Box::pin(async move { + let mut values_string = IndexSet::new(); + for value in values { + let value = match value { + ValueDebugFormatString::Sync(string) => string, + ValueDebugFormatString::Async(future) => future.await?, + }; + values_string.insert(PassthroughDebug::new_string(value)); + } + Ok(format!("{:#?}", values_string)) + })) + } +} + +impl ValueDebugFormat for IndexMap +where + K: ValueDebugFormat, + V: ValueDebugFormat, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + let values = self + .iter() + .map(|(key, value)| { + ( + key.value_debug_format(depth.saturating_sub(1)), + value.value_debug_format(depth.saturating_sub(1)), + ) + }) + .collect::>(); + + ValueDebugFormatString::Async(Box::pin(async move { + let mut values_string = IndexMap::new(); + for (key, value) in values { + let key = match key { + ValueDebugFormatString::Sync(string) => string, + ValueDebugFormatString::Async(future) => future.await?, + }; + let value = match value { + ValueDebugFormatString::Sync(string) => string, + ValueDebugFormatString::Async(future) => future.await?, + }; + values_string + .insert(PassthroughDebug::new_string(key), PassthroughDebug::new_string(value)); + } + Ok(format!("{:#?}", values_string)) + })) + } +} + +macro_rules! tuple_impls { + ( $( $name:ident )+ ) => { + impl<$($name: ValueDebugFormat),+> ValueDebugFormat for ($($name,)+) + { + #[allow(non_snake_case)] + fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString { + if depth == 0 { + return ValueDebugFormatString::Sync(std::any::type_name::().to_string()); + } + + let ($($name,)+) = self; + let ($($name,)+) = ($($name.value_debug_format(depth.saturating_sub(1)),)+); + + ValueDebugFormatString::Async(Box::pin(async move { + let values = ($(PassthroughDebug::new_string($name.try_to_string().await?),)+); + Ok(format!("{:#?}", values)) + })) + } + } + }; +} + +tuple_impls! { A } +tuple_impls! { A B } +tuple_impls! { A B C } +tuple_impls! { A B C D } +tuple_impls! { A B C D E } +tuple_impls! { A B C D E F } +tuple_impls! { A B C D E F G } +tuple_impls! { A B C D E F G H } +tuple_impls! { A B C D E F G H I } +tuple_impls! { A B C D E F G H I J } +tuple_impls! { A B C D E F G H I J K } +tuple_impls! { A B C D E F G H I J K L } + +/// Output of `ValueDebugFormat::value_debug_format`. +pub enum ValueDebugFormatString<'a> { + /// For the `T: Debug` fallback implementation, we can output a string + /// directly as the result of `format!("{:?}", t)`. + Sync(String), + /// For the `Vc` types and `Vc`-containing types implementations, we need to + /// resolve types asynchronously before we can format them, hence the need + /// for a future. + Async( + core::pin::Pin> + Send + 'a>>, + ), +} + +impl<'a> ValueDebugFormatString<'a> { + /// Convert the `ValueDebugFormatString` into a `String`. + /// + /// This can fail when resolving `Vc` types. + pub async fn try_to_string(self) -> anyhow::Result { + Ok(match self { + ValueDebugFormatString::Sync(value) => value, + ValueDebugFormatString::Async(future) => future.await?, + }) + } + + /// Convert the `ValueDebugFormatString` into a `Vc`. + /// + /// This can fail when resolving `Vc` types. + pub async fn try_to_value_debug_string(self) -> anyhow::Result> { + Ok(ValueDebugString::new(self.try_to_string().await?)) + } +} diff --git a/crates/turbo-tasks/Source/debug/vdbg.rs b/crates/turbo-tasks/Source/debug/vdbg.rs new file mode 100644 index 0000000000000..8b7407c54910e --- /dev/null +++ b/crates/turbo-tasks/Source/debug/vdbg.rs @@ -0,0 +1,74 @@ +// NOTE(alexkirsz) Implementation and comments are based on the `dbg!` macro +// from the Rust standard library. +/// This macro supports the same syntax as `dbg!`, but also supports +/// pretty-printing `Vc` types. +/// +/// Beware: this macro should only be used for debugging purposes. Its behavior +/// around dependency tracking is not well-defined and could lead to unexpected +/// results. +#[macro_export] +macro_rules! vdbg { + // NOTE: We cannot use `concat!` to make a static string as a format argument + // of `eprintln!` because `file!` could contain a `{` or + // `$val` expression could be a block (`{ .. }`), in which case the `eprintln!` + // will be malformed. + () => { + eprintln!("[{}:{}]", file!(), line!()) + }; + + (__init $depth:expr ; [ $val:expr $(, $rest:expr)* ] [ $($tt:tt)* ] ) => { + { + let valstr = stringify!($val); + // We move the value into a new binding so we may refer to it multiple + // times without re-evaluating the expression. + let valmove = $val; + // We convert the value to an owned value which will be moved into the + // spawned thread. This is necessary in order to ensure a 'static lifetime + // for the value, but it may require a clone. + let valowned = valmove.to_owned(); + $crate::vdbg!(__init $depth ; [ $($rest),* ] [ $($tt)* valstr valmove valowned ]) + } + }; + (__init $depth:expr ; [ ] [ $($valstr:ident $valmove:ident $valowned:ident)* ] ) => { + { + use $crate::debug::ValueDebugFormat; + let depth = $depth; + $crate::macro_helpers::spawn_detached(async move { + $crate::vdbg!(__expand depth ; [ $($valstr $valowned)* ] []); + Ok(()) + }); + ($($valmove),*) + } + }; + + (__expand $depth:ident ; [ $valstr:ident $val:ident $($rest:tt)* ] [ $($tt:tt)* ]) => { + let valdbg = (&$val).value_debug_format($depth).try_to_string().await?; + $crate::vdbg!(__expand $depth ; [ $($rest)* ] [ $($tt)* $valstr valdbg ]); + }; + (__expand $depth:ident ; [] [ $( $valstr:ident $valdbg:ident )* ]) => { + // By pre-awaiting, then printing everything at once, we ensure that the + // output won't be interleaved with output from other threads, and that + // it will always appear in the order that the macro was invoked. + eprint!( + $crate::vdbg!(__repeat "[{file}:{line}] {} = {}\n" $($valstr)*), + $( + $valstr, + $valdbg, + )* + file = file!(), + line = line!(), + ); + }; + + // Sub-macro for repeating a string N times, where N is controlled by the number of identifiers + // passed to the macro. + (__repeat $str:literal $x:ident $($rest:ident)*) => { concat!($str, $crate::vdbg!(__repeat $str $($rest)*)) }; + (__repeat $str:literal) => { "" }; + + ($($val:expr),* ; depth = $depth:expr) => { + $crate::vdbg!(__init $depth ; [ $($val),* ] []) + }; + ($($val:expr),+ $(,)?) => { + $crate::vdbg!(__init usize::MAX ; [ $($val),* ] []) + }; +} diff --git a/crates/turbo-tasks/Source/display.rs b/crates/turbo-tasks/Source/display.rs new file mode 100644 index 0000000000000..a73f642c1aa6f --- /dev/null +++ b/crates/turbo-tasks/Source/display.rs @@ -0,0 +1,8 @@ +use turbo_tasks::Vc; + +use crate::{self as turbo_tasks, RcStr}; + +#[turbo_tasks::value_trait] +pub trait ValueToString { + fn to_string(self: Vc) -> Vc; +} diff --git a/crates/turbo-tasks/Source/duration_span.rs b/crates/turbo-tasks/Source/duration_span.rs new file mode 100644 index 0000000000000..816f978dfbba3 --- /dev/null +++ b/crates/turbo-tasks/Source/duration_span.rs @@ -0,0 +1,39 @@ +use std::time::Instant; + +/// Guard that emits a tracing event when dropped with the duration of the +/// lifetime of the guard. +pub struct DurationSpanGuard { + start:Instant, + f:Option, +} + +impl DurationSpanGuard { + pub fn new(f:F) -> Self { Self { start:Instant::now(), f:Some(f) } } +} + +impl Drop for DurationSpanGuard { + fn drop(&mut self) { + if let Some(f) = self.f.take() { + f(self.start.elapsed().as_micros() as u64); + } + } +} + +/// Creates a event-based span that traces a certain duration (lifetime of the +/// guard). It's not a real span, which means it can be used across threads. It +/// will trace a duration and not the time the cpu is doing actual work. This +/// way it can be used to trace non-cpu-time or time that is spend in other +/// processes. +#[macro_export] +macro_rules! duration_span { + ($name:literal) => { + turbo_tasks::duration_span::DurationSpanGuard::new(|duration| { + turbo_tasks::macro_helpers::tracing::info!(name = $name, duration = duration); + }) + }; + ($name:literal, $($arg:tt)+) => { + turbo_tasks::duration_span::DurationSpanGuard::new(|duration| { + turbo_tasks::macro_helpers::tracing::info!(name = $name, $($arg)+, duration = duration); + }) + }; +} diff --git a/crates/turbo-tasks/Source/event.rs b/crates/turbo-tasks/Source/event.rs new file mode 100644 index 0000000000000..a65976617f296 --- /dev/null +++ b/crates/turbo-tasks/Source/event.rs @@ -0,0 +1,190 @@ +#[cfg(feature = "hanging_detection")] +use std::sync::Arc; +#[cfg(feature = "hanging_detection")] +use std::task::Poll; +#[cfg(feature = "hanging_detection")] +use std::task::ready; +#[cfg(feature = "hanging_detection")] +use std::time::Duration; +use std::{ + fmt::{Debug, Formatter}, + future::Future, + mem::replace, + pin::Pin, +}; + +#[cfg(feature = "hanging_detection")] +use tokio::time::Timeout; +#[cfg(feature = "hanging_detection")] +use tokio::time::timeout; + +pub struct Event { + #[cfg(feature = "hanging_detection")] + description:Arc String + Sync + Send>, + event:event_listener::Event, +} + +#[cfg(not(feature = "hanging_detection"))] +impl Event { + /// see [event_listener::Event]::new + #[inline(always)] + pub fn new(_description:impl Fn() -> String + Sync + Send + 'static) -> Self { + Self { event:event_listener::Event::new() } + } + + /// see [event_listener::Event]::listen + pub fn listen(&self) -> EventListener { EventListener { listener:self.event.listen() } } + + /// see [event_listener::Event]::listen + pub fn listen_with_note( + &self, + _note:impl Fn() -> String + Sync + Send + 'static, + ) -> EventListener { + EventListener { listener:self.event.listen() } + } + + /// pulls out the event listener, leaving a new, empty event in its place. + pub fn take(&mut self) -> Self { + Self { event:replace(&mut self.event, event_listener::Event::new()) } + } +} + +#[cfg(feature = "hanging_detection")] +impl Event { + /// see [event_listener::Event]::new + #[inline(always)] + pub fn new(description:impl Fn() -> String + Sync + Send + 'static) -> Self { + Self { description:Arc::new(description), event:event_listener::Event::new() } + } + + /// see [event_listener::Event]::listen + pub fn listen(&self) -> EventListener { + EventListener { + description:self.description.clone(), + note:Arc::new(|| String::new()), + future:Some(Box::pin(timeout(Duration::from_secs(10), self.event.listen()))), + duration:Duration::from_secs(10), + } + } + + /// see [event_listener::Event]::listen + pub fn listen_with_note( + &self, + note:impl Fn() -> String + Sync + Send + 'static, + ) -> EventListener { + EventListener { + description:self.description.clone(), + note:Arc::new(note), + future:Some(Box::pin(timeout(Duration::from_secs(10), self.event.listen()))), + duration:Duration::from_secs(10), + } + } + + /// pulls out the event listener, leaving a new, empty event in its place. + pub fn take(&mut self) -> Event { + Self { + description:self.description.clone(), + event:replace(&mut self.event, event_listener::Event::new()), + } + } +} + +impl Event { + /// see [event_listener::Event]::notify + pub fn notify(&self, n:usize) { self.event.notify(n); } +} + +impl Debug for Event { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + let mut t = f.debug_tuple("Event"); + #[cfg(feature = "hanging_detection")] + t.field(&(self.description)()); + t.finish() + } +} + +#[cfg(not(feature = "hanging_detection"))] +pub struct EventListener { + listener:event_listener::EventListener, +} + +#[cfg(not(feature = "hanging_detection"))] +impl Debug for EventListener { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("EventListener").finish() + } +} + +#[cfg(not(feature = "hanging_detection"))] +impl Future for EventListener { + type Output = (); + + fn poll( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll { + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().listener) }.poll(cx) + } +} + +#[cfg(feature = "hanging_detection")] +pub struct EventListener { + description:Arc String + Sync + Send>, + note:Arc String + Sync + Send>, + // Timeout need to stay pinned while polling and also while it's dropped. + // So it's important to put it into a pinned Box to be able to take it out of the Option. + future:Option>>>, + duration:Duration, +} + +#[cfg(feature = "hanging_detection")] +impl Debug for EventListener { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + let mut t = f.debug_tuple("EventListener"); + t.field(&(self.description)()); + let note = (self.note)(); + if !note.is_empty() { + t.field(¬e); + } + t.finish() + } +} + +#[cfg(feature = "hanging_detection")] +impl Future for EventListener { + type Output = (); + + fn poll( + mut self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll { + while let Some(future) = self.future.as_mut() { + match ready!(future.as_mut().poll(cx)) { + Ok(_) => { + self.future = None; + return Poll::Ready(()); + }, + Err(_) => { + use crate::util::FormatDuration; + eprintln!( + "{:?} is potentially hanging (waiting for {})", + self, + FormatDuration(self.duration) + ); + self.duration *= 2; + // SAFETY: Taking from Option is safe because the value is inside of a pinned + // Box. Pinning must continue until dropped. + let future = self.future.take().unwrap(); + self.future = Some(Box::pin(timeout( + self.duration, + // SAFETY: We can move the inner future since it's an EventListener and + // that is Unpin. + unsafe { Pin::into_inner_unchecked(future) }.into_inner(), + ))); + }, + } + } + // EventListener was awaited again after completion + Poll::Ready(()) + } +} diff --git a/crates/turbo-tasks/Source/generics/index_map.rs b/crates/turbo-tasks/Source/generics/index_map.rs new file mode 100644 index 0000000000000..04b72ede80f65 --- /dev/null +++ b/crates/turbo-tasks/Source/generics/index_map.rs @@ -0,0 +1,74 @@ +use anyhow::Result; +use indexmap::IndexMap; +// This specific macro identifier is detected by turbo-tasks-build. +use turbo_tasks_macros::generic_type as __turbo_tasks_internal_generic_type; + +use crate::{ + self as turbo_tasks, + ValueDefault, + Vc, + debug::{ValueDebug, ValueDebugFormat, ValueDebugString}, +}; + +__turbo_tasks_internal_generic_type!(, IndexMap, Vc>); + +#[turbo_tasks::function] +async fn index_map_len(index_map:Vc, Vc<()>>>) -> Result> { + let index_map = index_map.await?; + Ok(Vc::cell(index_map.len())) +} + +#[turbo_tasks::function] +async fn index_map_is_empty(index_map:Vc, Vc<()>>>) -> Result> { + let index_map = index_map.await?; + Ok(Vc::cell(index_map.is_empty())) +} + +impl Vc, Vc>> +where + K: Send, + V: Send, +{ + /// See [`IndexMap::len`]. + pub fn len(self) -> Vc { index_map_len(Self::to_repr(self)) } + + /// See [`IndexMap::is_empty`]. + pub fn is_empty(self) -> Vc { index_map_is_empty(Self::to_repr(self)) } +} + +#[turbo_tasks::function] +fn index_map_default() -> Vc, Vc<()>>> { Vc::cell(Default::default()) } + +impl ValueDefault for IndexMap, Vc> +where + K: Send, + V: Send, +{ + fn value_default() -> Vc { + // Safety: `index_map_default` creates an empty map, which is a valid + // representation of any index set of `Vc`. + unsafe { Vc::::from_repr(index_map_default()) } + } +} + +#[turbo_tasks::function] +async fn index_map_dbg_depth( + index_map:Vc, Vc<()>>>, + depth:usize, +) -> Result> { + index_map.await?.value_debug_format(depth).try_to_value_debug_string().await +} + +impl ValueDebug for IndexMap, Vc> +where + K: Send, + V: Send, +{ + fn dbg(self: Vc) -> Vc { + index_map_dbg_depth(Vc::::to_repr(self), usize::MAX) + } + + fn dbg_depth(self: Vc, depth:usize) -> Vc { + index_map_dbg_depth(Vc::::to_repr(self), depth) + } +} diff --git a/crates/turbo-tasks/Source/generics/index_set.rs b/crates/turbo-tasks/Source/generics/index_set.rs new file mode 100644 index 0000000000000..9ebf18eaef0be --- /dev/null +++ b/crates/turbo-tasks/Source/generics/index_set.rs @@ -0,0 +1,71 @@ +use anyhow::Result; +use indexmap::IndexSet; +// This specific macro identifier is detected by turbo-tasks-build. +use turbo_tasks_macros::generic_type as __turbo_tasks_internal_generic_type; + +use crate::{ + self as turbo_tasks, + ValueDefault, + Vc, + debug::{ValueDebug, ValueDebugFormat, ValueDebugString}, +}; + +__turbo_tasks_internal_generic_type!(, IndexSet>); + +#[turbo_tasks::function] +async fn index_set_len(index_set:Vc>>) -> Result> { + let index_set = index_set.await?; + Ok(Vc::cell(index_set.len())) +} + +#[turbo_tasks::function] +async fn index_set_is_empty(index_set:Vc>>) -> Result> { + let index_set = index_set.await?; + Ok(Vc::cell(index_set.is_empty())) +} + +impl Vc>> +where + T: Send, +{ + /// See [`IndexSet::len`]. + pub fn len(self) -> Vc { index_set_len(Self::to_repr(self)) } + + /// See [`IndexSet::is_empty`]. + pub fn is_empty(self) -> Vc { index_set_is_empty(Self::to_repr(self)) } +} + +#[turbo_tasks::function] +fn index_set_default() -> Vc>> { Vc::cell(Default::default()) } + +impl ValueDefault for IndexSet> +where + T: Send, +{ + fn value_default() -> Vc { + // Safety: `index_set_default` creates an empty set, which is a valid + // representation of any index set of `Vc`. + unsafe { Vc::::from_repr(index_set_default()) } + } +} + +#[turbo_tasks::function] +async fn index_set_dbg_depth( + index_set:Vc>>, + depth:usize, +) -> Result> { + index_set.await?.value_debug_format(depth).try_to_value_debug_string().await +} + +impl ValueDebug for IndexSet> +where + T: Send, +{ + fn dbg(self: Vc) -> Vc { + index_set_dbg_depth(Vc::::to_repr(self), usize::MAX) + } + + fn dbg_depth(self: Vc, depth:usize) -> Vc { + index_set_dbg_depth(Vc::::to_repr(self), depth) + } +} diff --git a/crates/turbo-tasks/Source/generics/mod.rs b/crates/turbo-tasks/Source/generics/mod.rs new file mode 100644 index 0000000000000..9bbc961eb1b69 --- /dev/null +++ b/crates/turbo-tasks/Source/generics/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod index_map; +pub(crate) mod index_set; +pub(crate) mod option; +pub(crate) mod vec; diff --git a/crates/turbo-tasks/Source/generics/option.rs b/crates/turbo-tasks/Source/generics/option.rs new file mode 100644 index 0000000000000..2eefafd631a50 --- /dev/null +++ b/crates/turbo-tasks/Source/generics/option.rs @@ -0,0 +1,67 @@ +use anyhow::Result; +// This specific macro identifier is detected by turbo-tasks-build. +use turbo_tasks_macros::generic_type as __turbo_tasks_internal_generic_type; + +use crate::{ + self as turbo_tasks, + ValueDefault, + Vc, + debug::{ValueDebug, ValueDebugFormat, ValueDebugString}, +}; + +__turbo_tasks_internal_generic_type!(, Option>); + +#[turbo_tasks::function] +async fn option_is_none(option:Vc>>) -> Result> { + let option = option.await?; + Ok(Vc::cell(option.is_none())) +} + +#[turbo_tasks::function] +async fn option_is_some(option:Vc>>) -> Result> { + let option = option.await?; + Ok(Vc::cell(option.is_some())) +} + +impl Vc>> +where + T: Send, +{ + /// See [`Option::is_none`]. + pub fn is_none(self) -> Vc { option_is_none(Self::to_repr(self)) } + + /// See [`Option::is_some`]. + pub fn is_some(self) -> Vc { option_is_some(Self::to_repr(self)) } +} + +#[turbo_tasks::function] +fn option_default() -> Vc>> { Vc::cell(Default::default()) } + +impl ValueDefault for Option> +where + T: Send, +{ + fn value_default() -> Vc { + // Safety: `option_default` creates a None variant, which is a valid + // representation of any option of `Vc`. + unsafe { Vc::::from_repr(option_default()) } + } +} + +#[turbo_tasks::function] +async fn option_dbg_depth(option:Vc>>, depth:usize) -> Result> { + option.await?.value_debug_format(depth).try_to_value_debug_string().await +} + +impl ValueDebug for Option> +where + T: Send, +{ + fn dbg(self: Vc) -> Vc { + option_dbg_depth(Vc::::to_repr(self), usize::MAX) + } + + fn dbg_depth(self: Vc, depth:usize) -> Vc { + option_dbg_depth(Vc::::to_repr(self), depth) + } +} diff --git a/crates/turbo-tasks/Source/generics/vec.rs b/crates/turbo-tasks/Source/generics/vec.rs new file mode 100644 index 0000000000000..94fd3d9f2b8a7 --- /dev/null +++ b/crates/turbo-tasks/Source/generics/vec.rs @@ -0,0 +1,67 @@ +use anyhow::Result; +// This specific macro identifier is detected by turbo-tasks-build. +use turbo_tasks_macros::generic_type as __turbo_tasks_internal_generic_type; + +use crate::{ + self as turbo_tasks, + ValueDefault, + Vc, + debug::{ValueDebug, ValueDebugFormat, ValueDebugString}, +}; + +__turbo_tasks_internal_generic_type!(, Vec>); + +#[turbo_tasks::function] +async fn vec_len(vec:Vc>>) -> Result> { + let vec = vec.await?; + Ok(Vc::cell(vec.len())) +} + +#[turbo_tasks::function] +async fn vec_is_empty(vec:Vc>>) -> Result> { + let vec = vec.await?; + Ok(Vc::cell(vec.is_empty())) +} + +impl Vc>> +where + T: Send, +{ + /// See [`Vec::len`]. + pub fn len(self) -> Vc { vec_len(Self::to_repr(self)) } + + /// See [`Vec::is_empty`]. + pub fn is_empty(self) -> Vc { vec_is_empty(Self::to_repr(self)) } +} + +#[turbo_tasks::function] +fn vec_default() -> Vc>> { Vc::cell(Default::default()) } + +impl ValueDefault for Vec> +where + T: Send, +{ + fn value_default() -> Vc { + // Safety: `vec_default` creates an empty vector, which is a valid + // representation of any vector of `Vc`s. + unsafe { Vc::::from_repr(vec_default()) } + } +} + +#[turbo_tasks::function] +async fn vec_dbg_depth(vec:Vc>>, depth:usize) -> Result> { + vec.await?.value_debug_format(depth).try_to_value_debug_string().await +} + +impl ValueDebug for Vec> +where + T: Send, +{ + fn dbg(self: Vc) -> Vc { + vec_dbg_depth(Vc::::to_repr(self), usize::MAX) + } + + fn dbg_depth(self: Vc, depth:usize) -> Vc { + vec_dbg_depth(Vc::::to_repr(self), depth) + } +} diff --git a/crates/turbo-tasks/Source/graph/adjacency_map.rs b/crates/turbo-tasks/Source/graph/adjacency_map.rs new file mode 100644 index 0000000000000..9acc2bc64ccc6 --- /dev/null +++ b/crates/turbo-tasks/Source/graph/adjacency_map.rs @@ -0,0 +1,212 @@ +use std::collections::{HashMap, HashSet}; + +use serde::{Deserialize, Serialize}; +use turbo_tasks_macros::{TraceRawVcs, ValueDebugFormat}; + +use super::graph_store::{GraphNode, GraphStore}; +use crate as turbo_tasks; + +/// A graph traversal that builds an adjacency map +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat)] +pub struct AdjacencyMap +where + T: Eq + std::hash::Hash + Clone, { + adjacency_map:HashMap>, + roots:Vec, +} + +impl Default for AdjacencyMap +where + T: Eq + std::hash::Hash + Clone, +{ + fn default() -> Self { Self::new() } +} + +impl AdjacencyMap +where + T: Eq + std::hash::Hash + Clone, +{ + /// Creates a new adjacency map + pub fn new() -> Self { Self { adjacency_map:HashMap::new(), roots:Vec::new() } } + + /// Returns an iterator over the root nodes of the graph + pub fn roots(&self) -> impl Iterator { self.roots.iter() } + + /// Returns an iterator over the children of the given node + pub fn get(&self, node:&T) -> Option> { + self.adjacency_map.get(node).map(|vec| vec.iter()) + } +} + +impl GraphStore for AdjacencyMap +where + T: Eq + std::hash::Hash + Clone, +{ + type Handle = T; + type Node = T; + + fn insert(&mut self, from_handle:Option, node:GraphNode) -> Option<(Self::Handle, &T)> { + let vec = if let Some(from_handle) = from_handle { + self.adjacency_map.entry(from_handle).or_insert_with(|| Vec::with_capacity(1)) + } else { + &mut self.roots + }; + + vec.push(node.node().clone()); + Some((node.into_node(), vec.last().unwrap())) + } +} + +impl AdjacencyMap +where + T: Eq + std::hash::Hash + Clone, +{ + /// Returns an owned iterator over the nodes in reverse topological order, + /// starting from the roots. + pub fn into_reverse_topological(self) -> IntoReverseTopologicalIter { + IntoReverseTopologicalIter { + adjacency_map:self.adjacency_map, + stack:self + .roots + .into_iter() + .rev() + .map(|root| (ReverseTopologicalPass::Pre, root)) + .collect(), + visited:HashSet::new(), + } + } + + /// Returns an iterator over the nodes in reverse topological order, + /// starting from the roots. + pub fn reverse_topological(&self) -> ReverseTopologicalIter { + ReverseTopologicalIter { + adjacency_map:&self.adjacency_map, + stack:self + .roots + .iter() + .rev() + .map(|root| (ReverseTopologicalPass::Pre, root)) + .collect(), + visited:HashSet::new(), + } + } + + /// Returns an iterator over the nodes in reverse topological order, + /// starting from the given node. + pub fn reverse_topological_from_node<'graph>( + &'graph self, + node:&'graph T, + ) -> ReverseTopologicalIter<'graph, T> { + ReverseTopologicalIter { + adjacency_map:&self.adjacency_map, + stack:vec![(ReverseTopologicalPass::Pre, node)], + visited:HashSet::new(), + } + } +} + +#[derive(Debug)] +enum ReverseTopologicalPass { + Pre, + Post, +} + +/// An iterator over the nodes of a graph in reverse topological order, starting +/// from the roots. +pub struct IntoReverseTopologicalIter +where + T: Eq + std::hash::Hash + Clone, { + adjacency_map:HashMap>, + stack:Vec<(ReverseTopologicalPass, T)>, + visited:HashSet, +} + +impl Iterator for IntoReverseTopologicalIter +where + T: Eq + std::hash::Hash + Clone, +{ + type Item = T; + + fn next(&mut self) -> Option { + let current = loop { + let (pass, current) = self.stack.pop()?; + + match pass { + ReverseTopologicalPass::Post => { + break current; + }, + ReverseTopologicalPass::Pre => { + if self.visited.contains(¤t) { + continue; + } + + self.visited.insert(current.clone()); + + let Some(neighbors) = self.adjacency_map.get(¤t) else { + break current; + }; + + self.stack.push((ReverseTopologicalPass::Post, current)); + self.stack.extend( + neighbors + .iter() + .rev() + .map(|neighbor| (ReverseTopologicalPass::Pre, neighbor.clone())), + ); + }, + } + }; + + Some(current) + } +} + +/// An iterator over the nodes of a graph in reverse topological order, starting +/// from the roots. +pub struct ReverseTopologicalIter<'graph, T> +where + T: Eq + std::hash::Hash + Clone, { + adjacency_map:&'graph HashMap>, + stack:Vec<(ReverseTopologicalPass, &'graph T)>, + visited:HashSet<&'graph T>, +} + +impl<'graph, T> Iterator for ReverseTopologicalIter<'graph, T> +where + T: Eq + std::hash::Hash + Clone, +{ + type Item = &'graph T; + + fn next(&mut self) -> Option { + let current = loop { + let (pass, current) = self.stack.pop()?; + + match pass { + ReverseTopologicalPass::Post => { + break current; + }, + ReverseTopologicalPass::Pre => { + if self.visited.contains(current) { + continue; + } + + self.visited.insert(current); + + let Some(neighbors) = self.adjacency_map.get(current) else { + break current; + }; + + self.stack.push((ReverseTopologicalPass::Post, current)); + self.stack.extend( + neighbors + .iter() + .rev() + .map(|neighbor| (ReverseTopologicalPass::Pre, neighbor)), + ); + }, + } + }; + + Some(current) + } +} diff --git a/crates/turbo-tasks/Source/graph/control_flow.rs b/crates/turbo-tasks/Source/graph/control_flow.rs new file mode 100644 index 0000000000000..9bc6f5415d0ec --- /dev/null +++ b/crates/turbo-tasks/Source/graph/control_flow.rs @@ -0,0 +1,33 @@ +/// The control flow of visiting an edge during a graph traversal. +pub enum VisitControlFlow { + /// The traversal should continue on the outgoing edges of the given node. + Continue(Node), + /// The traversal should skip visiting the edges the given node. + Skip(Node), + /// The traversal should abort and return immediately. + Abort(Abort), +} + +impl VisitControlFlow { + /// Map the continue and skip values of this control flow. + pub fn map_node(self, mut map:Map) -> VisitControlFlow + where + Map: FnMut(Node) -> Mapped, { + match self { + VisitControlFlow::Continue(node) => VisitControlFlow::Continue(map(node)), + VisitControlFlow::Skip(node) => VisitControlFlow::Skip(map(node)), + VisitControlFlow::Abort(abort) => VisitControlFlow::Abort(abort), + } + } + + /// Map the abort value of this control flow. + pub fn map_abort(self, mut map:Map) -> VisitControlFlow + where + Map: FnMut(Abort) -> Mapped, { + match self { + VisitControlFlow::Continue(node) => VisitControlFlow::Continue(node), + VisitControlFlow::Skip(node) => VisitControlFlow::Skip(node), + VisitControlFlow::Abort(abort) => VisitControlFlow::Abort(map(abort)), + } + } +} diff --git a/crates/turbo-tasks/Source/graph/graph_store.rs b/crates/turbo-tasks/Source/graph/graph_store.rs new file mode 100644 index 0000000000000..3ed6c1e743311 --- /dev/null +++ b/crates/turbo-tasks/Source/graph/graph_store.rs @@ -0,0 +1,87 @@ +use std::collections::HashSet; + +/// A graph store is a data structure that will be built up during a graph +/// traversal. It is used to store the results of the traversal. +pub trait GraphStore { + type Node; + type Handle: Clone; + + // TODO(alexkirsz) An `entry(from_handle) -> Entry` API would be more + // efficient, as right now we're getting the same key multiple times. + /// Inserts a node into the graph store, and returns a handle to it. + /// + /// If this method returns `None`, the node edges will not be visited. + fn insert( + &mut self, + from_handle:Option, + node:GraphNode, + ) -> Option<(Self::Handle, &Self::Node)>; +} + +/// Utility type to ensure that GraphStore::insert can only ever be called from +/// within this module, as a GraphNode can't be constructed outside of it. +#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash, Ord, PartialOrd)] +pub struct GraphNode(pub(super) Node); + +impl GraphNode { + /// Consumes this `GraphNode` and returns the underlying node. + pub fn into_node(self) -> Node { self.0 } + + /// Returns a reference the underlying node. + pub fn node(&self) -> &Node { &self.0 } + + /// Returns a mutable reference the underlying node. + pub fn node_mut(&mut self) -> &mut Node { &mut self.0 } +} + +/// A [`GraphStore`] wrapper that skips nodes that have already been +/// visited. This is necessary to avoid repeated work when traversing non-tree +/// graphs (i.e. where a node can have more than one incoming edge). +#[derive(Debug)] +pub struct SkipDuplicates +where + StoreImpl: GraphStore, { + store:StoreImpl, + visited:HashSet, +} + +impl SkipDuplicates +where + StoreImpl: GraphStore, +{ + pub fn new(store:StoreImpl) -> Self { Self { store, visited:Default::default() } } +} + +impl GraphStore for SkipDuplicates +where + StoreImpl: GraphStore, + StoreImpl::Node: Eq + std::hash::Hash + Clone, +{ + type Handle = StoreImpl::Handle; + type Node = StoreImpl::Node; + + fn insert( + &mut self, + from_handle:Option, + node:GraphNode, + ) -> Option<(Self::Handle, &StoreImpl::Node)> { + if !self.visited.contains(node.node()) { + self.visited.insert(node.node().clone()); + self.store.insert(from_handle, node) + } else { + // Always insert the node into the store, even if we've already + // visited it. This is necessary to ensure that the store sees all + // edges. + self.store.insert(from_handle, node); + None + } + } +} + +impl SkipDuplicates +where + StoreImpl: GraphStore, +{ + /// Consumes the wrapper and returns the underlying store. + pub fn into_inner(self) -> StoreImpl { self.store } +} diff --git a/crates/turbo-tasks/Source/graph/graph_traversal.rs b/crates/turbo-tasks/Source/graph/graph_traversal.rs new file mode 100644 index 0000000000000..b3e56e367ff1e --- /dev/null +++ b/crates/turbo-tasks/Source/graph/graph_traversal.rs @@ -0,0 +1,219 @@ +use std::{future::Future, pin::Pin}; + +use anyhow::Result; +use futures::{Stream, stream::FuturesUnordered}; + +use super::{ + SkipDuplicates, + Visit, + VisitControlFlow, + graph_store::{GraphNode, GraphStore}, + with_future::With, +}; + +/// [`GraphTraversal`] is a utility type that can be used to traverse a graph of +/// nodes, where each node can have a variable number of outgoing edges. The +/// traversal is done in parallel, and the order of the nodes in the traversal +/// result is determined by the [`GraphStore`] parameter. +pub trait GraphTraversal: GraphStore + Sized { + fn visit( + self, + root_edges:RootEdgesIt, + visit:VisitImpl, + ) -> GraphTraversalFuture + where + VisitImpl: Visit, + RootEdgesIt: IntoIterator; + + fn skip_duplicates(self) -> SkipDuplicates; +} + +impl GraphTraversal for Store +where + Store: GraphStore, +{ + /// Visits the graph starting from the given `roots`, and returns a future + /// that will resolve to the traversal result. + fn visit( + mut self, + root_edges:RootEdgesIt, + mut visit:VisitImpl, + ) -> GraphTraversalFuture + where + VisitImpl: Visit, + RootEdgesIt: IntoIterator, { + let futures = FuturesUnordered::new(); + for edge in root_edges { + match visit.visit(edge) { + VisitControlFlow::Continue(node) => { + if let Some((parent_handle, node_ref)) = self.insert(None, GraphNode(node)) { + let span = visit.span(node_ref); + futures.push(With::new(visit.edges(node_ref), span, parent_handle)); + } + }, + VisitControlFlow::Skip(node) => { + self.insert(None, GraphNode(node)); + }, + VisitControlFlow::Abort(abort) => { + return GraphTraversalFuture { state:GraphTraversalState::Aborted { abort } }; + }, + } + } + GraphTraversalFuture { + state:GraphTraversalState::Running(GraphTraversalRunningState { + store:self, + futures, + visit, + _phantom:std::marker::PhantomData, + }), + } + } + + fn skip_duplicates(self) -> SkipDuplicates { SkipDuplicates::new(self) } +} + +/// A future that resolves to a [`GraphStore`] containing the result of a graph +/// traversal. +pub struct GraphTraversalFuture +where + Store: GraphStore, + VisitImpl: Visit, + EdgesFuture: Future, { + state:GraphTraversalState, +} + +#[derive(Default)] +enum GraphTraversalState +where + Store: GraphStore, + VisitImpl: Visit, + EdgesFuture: Future, { + #[default] + Completed, + Aborted { + abort:Abort, + }, + Running(GraphTraversalRunningState), +} + +struct GraphTraversalRunningState +where + Store: GraphStore, + VisitImpl: Visit, + EdgesFuture: Future, { + store:Store, + // This should be VisitImpl::EdgesFuture, but this causes a bug in the Rust + // compiler (see https://github.com/rust-lang/rust/issues/102211). + // Instead, we pass the associated type as an additional generic parameter. + futures:FuturesUnordered>, + visit:VisitImpl, + _phantom:std::marker::PhantomData<(Abort, Impl)>, +} + +pub enum GraphTraversalResult { + Completed(Completed), + Aborted(Aborted), +} + +impl GraphTraversalResult { + pub fn completed(self) -> Completed { + match self { + GraphTraversalResult::Completed(completed) => completed, + GraphTraversalResult::Aborted(_) => unreachable!("the type parameter `Aborted` is `!`"), + } + } +} + +impl Future + for GraphTraversalFuture +where + Store: GraphStore, + // The EdgesFuture bound is necessary to avoid the compiler bug mentioned + // above. + VisitImpl: Visit, + EdgesFuture: Future>, +{ + type Output = GraphTraversalResult, Abort>; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = unsafe { self.get_unchecked_mut() }; + + let result; + (this.state, result) = match std::mem::take(&mut this.state) { + GraphTraversalState::Completed => { + panic!("polled after completion") + }, + GraphTraversalState::Aborted { abort } => { + ( + GraphTraversalState::Completed, + std::task::Poll::Ready(GraphTraversalResult::Aborted(abort)), + ) + }, + GraphTraversalState::Running(mut running) => { + 'outer: loop { + let futures_pin = unsafe { Pin::new_unchecked(&mut running.futures) }; + match futures_pin.poll_next(cx) { + std::task::Poll::Ready(Some((parent_handle, span, Ok(edges)))) => { + let _guard = span.enter(); + for edge in edges { + match running.visit.visit(edge) { + VisitControlFlow::Continue(node) => { + if let Some((node_handle, node_ref)) = running + .store + .insert(Some(parent_handle.clone()), GraphNode(node)) + { + let span = running.visit.span(node_ref); + running.futures.push(With::new( + running.visit.edges(node_ref), + span, + node_handle, + )); + } + }, + VisitControlFlow::Skip(node) => { + running + .store + .insert(Some(parent_handle.clone()), GraphNode(node)); + }, + VisitControlFlow::Abort(abort) => { + break 'outer ( + GraphTraversalState::Completed, + std::task::Poll::Ready(GraphTraversalResult::Aborted( + abort, + )), + ); + }, + } + } + }, + std::task::Poll::Ready(Some((_, _, Err(err)))) => { + break ( + GraphTraversalState::Completed, + std::task::Poll::Ready(GraphTraversalResult::Completed(Err(err))), + ); + }, + std::task::Poll::Ready(None) => { + break ( + GraphTraversalState::Completed, + std::task::Poll::Ready(GraphTraversalResult::Completed(Ok( + running.store, + ))), + ); + }, + std::task::Poll::Pending => { + break ( + GraphTraversalState::Running(running), + std::task::Poll::Pending, + ); + }, + } + } + }, + }; + + result + } +} diff --git a/crates/turbo-tasks/Source/graph/mod.rs b/crates/turbo-tasks/Source/graph/mod.rs new file mode 100644 index 0000000000000..e2c0754485387 --- /dev/null +++ b/crates/turbo-tasks/Source/graph/mod.rs @@ -0,0 +1,14 @@ +mod adjacency_map; +mod control_flow; +mod graph_store; +mod graph_traversal; +mod non_deterministic; +mod visit; +mod with_future; + +pub use adjacency_map::AdjacencyMap; +pub use control_flow::VisitControlFlow; +pub use graph_store::{GraphStore, SkipDuplicates}; +pub use graph_traversal::{GraphTraversal, GraphTraversalResult}; +pub use non_deterministic::NonDeterministic; +pub use visit::Visit; diff --git a/crates/turbo-tasks/Source/graph/non_deterministic.rs b/crates/turbo-tasks/Source/graph/non_deterministic.rs new file mode 100644 index 0000000000000..a185f006bf2a6 --- /dev/null +++ b/crates/turbo-tasks/Source/graph/non_deterministic.rs @@ -0,0 +1,36 @@ +use super::graph_store::{GraphNode, GraphStore}; + +/// A graph traversal that does not guarantee any particular order, and may not +/// return the same order every time it is run. +pub struct NonDeterministic { + output:Vec, +} + +impl Default for NonDeterministic { + fn default() -> Self { Self::new() } +} + +impl NonDeterministic { + pub fn new() -> Self { Self { output:Vec::new() } } +} + +impl GraphStore for NonDeterministic { + type Handle = (); + type Node = T; + + fn insert( + &mut self, + _from_handle:Option, + node:GraphNode, + ) -> Option<(Self::Handle, &T)> { + self.output.push(node.into_node()); + Some(((), self.output.last().unwrap())) + } +} + +impl IntoIterator for NonDeterministic { + type IntoIter = as IntoIterator>::IntoIter; + type Item = T; + + fn into_iter(self) -> Self::IntoIter { self.output.into_iter() } +} diff --git a/crates/turbo-tasks/Source/graph/visit.rs b/crates/turbo-tasks/Source/graph/visit.rs new file mode 100644 index 0000000000000..8ed5c0b40cb30 --- /dev/null +++ b/crates/turbo-tasks/Source/graph/visit.rs @@ -0,0 +1,76 @@ +use std::future::Future; + +use anyhow::Result; +use tracing::Span; + +use super::VisitControlFlow; + +/// A trait that allows a graph traversal to visit the edges of a node +/// transitively. +pub trait Visit { + type Edge; + type EdgesIntoIter: IntoIterator; + type EdgesFuture: Future>; + + /// Visits an edge to get to the neighbor node. Should return a + /// [`VisitControlFlow`] that indicates whether to: + /// * continue visiting the neighbor node edges; + /// * skip visiting the neighbor node's edges; + /// * abort the traversal entirely. + fn visit(&mut self, edge:Self::Edge) -> VisitControlFlow; + + /// Returns a future that resolves to the outgoing edges of the given + /// `node`. + fn edges(&mut self, node:&Node) -> Self::EdgesFuture; + + /// Returns a [Span] for the given `node`, under which all edges are + /// processed. + fn span(&mut self, node:&Node) -> Span { + let _ = node; + Span::current() + } +} + +// The different `Impl*` here are necessary in order to avoid the `Conflicting +// implementations of trait` error when implementing `Visit` on different +// kinds of `FnMut`. +// See https://users.rust-lang.org/t/conflicting-implementation-when-implementing-traits-for-fn/53359/3 + +pub struct ImplRef; + +impl Visit for VisitFn +where + VisitFn: FnMut(&Node) -> NeighFut, + NeighFut: Future>, + NeighIt: IntoIterator, +{ + type Edge = Node; + type EdgesFuture = NeighFut; + type EdgesIntoIter = NeighIt; + + fn visit(&mut self, edge:Self::Edge) -> VisitControlFlow { + VisitControlFlow::Continue(edge) + } + + fn edges(&mut self, node:&Node) -> Self::EdgesFuture { (self)(node) } +} + +pub struct ImplValue; + +impl Visit for VisitFn +where + Node: Clone, + VisitFn: FnMut(Node) -> NeighFut, + NeighFut: Future>, + NeighIt: IntoIterator, +{ + type Edge = Node; + type EdgesFuture = NeighFut; + type EdgesIntoIter = NeighIt; + + fn visit(&mut self, edge:Self::Edge) -> VisitControlFlow { + VisitControlFlow::Continue(edge) + } + + fn edges(&mut self, node:&Node) -> Self::EdgesFuture { (self)(node.clone()) } +} diff --git a/crates/turbo-tasks/Source/graph/with_future.rs b/crates/turbo-tasks/Source/graph/with_future.rs new file mode 100644 index 0000000000000..875af211b57c6 --- /dev/null +++ b/crates/turbo-tasks/Source/graph/with_future.rs @@ -0,0 +1,49 @@ +use std::{future::Future, mem::replace}; + +use pin_project_lite::pin_project; +use tracing::Span; + +pin_project! { + pub struct With + where + T: Future, + { + #[pin] + future: T, + span: Span, + handle: Option, + } +} + +impl With +where + T: Future, +{ + pub fn new(future:T, span:Span, handle:H) -> Self { Self { future, span, handle:Some(handle) } } +} + +impl Future for With +where + T: Future, +{ + type Output = (H, Span, T::Output); + + fn poll( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + let guard = this.span.enter(); + match this.future.poll(cx) { + std::task::Poll::Ready(result) => { + drop(guard); + std::task::Poll::Ready(( + this.handle.take().expect("polled after completion"), + replace(this.span, Span::none()), + result, + )) + }, + std::task::Poll::Pending => std::task::Poll::Pending, + } + } +} diff --git a/crates/turbo-tasks/Source/id.rs b/crates/turbo-tasks/Source/id.rs new file mode 100644 index 0000000000000..413611776db78 --- /dev/null +++ b/crates/turbo-tasks/Source/id.rs @@ -0,0 +1,233 @@ +use std::{ + cell::RefCell, + fmt::{Debug, Display}, + mem::{ManuallyDrop, transmute_copy}, + num::NonZeroU32, + ops::Deref, +}; + +use serde::{Deserialize, Serialize, de::Visitor}; + +use crate::registry; + +macro_rules! define_id { + (internal $name:ident $(,$derive:ty)*) => { + #[derive(Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord $(,$derive)*)] + pub struct $name { + id: NonZeroU32, + } + + impl $name { + /// # Safety + /// + /// The passed `id` must not be zero. + pub unsafe fn new_unchecked(id: u32) -> Self { + Self { id: unsafe { NonZeroU32::new_unchecked(id) } } + } + } + + impl Display for $name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, concat!(stringify!($name), " {}"), self.id) + } + } + + impl Deref for $name { + type Target = u32; + + fn deref(&self) -> &Self::Target { + unsafe { transmute_copy(&&self.id) } + } + } + + impl From for $name { + fn from(id: u32) -> Self { + Self { id: NonZeroU32::new(id).expect("Ids can only be created from non zero values") } + } + } + + impl nohash_hasher::IsEnabled for $name {} + }; + ($name:ident) => { + define_id!(internal $name); + }; + ($name:ident, derive($($derive:ty),*)) => { + define_id!(internal $name $(,$derive)*); + }; +} + +define_id!(TaskId); +define_id!(FunctionId); +define_id!(ValueTypeId); +define_id!(TraitTypeId); +define_id!(BackendJobId); + +impl Debug for TaskId { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TaskId").field("id", &self.id).finish() + } +} + +macro_rules! make_serializable { + ($ty:ty, $get_global_name:path, $get_id:path, $visitor_name:ident) => { + impl Serialize for $ty { + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + serializer.serialize_str($get_global_name(*self)) + } + } + + impl<'de> Deserialize<'de> for $ty { + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + deserializer.deserialize_str($visitor_name) + } + } + + struct $visitor_name; + + impl<'de> Visitor<'de> for $visitor_name { + type Value = $ty; + + fn expecting(&self, formatter:&mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str(concat!("a name of a registered ", stringify!($ty))) + } + + fn visit_str(self, v:&str) -> Result + where + E: serde::de::Error, { + $get_id(v).ok_or_else(|| E::unknown_variant(v, &[])) + } + } + + impl Debug for $ty { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct(stringify!($ty)) + .field("id", &self.id) + .field("name", &$get_global_name(*self)) + .finish() + } + } + }; +} + +make_serializable!( + FunctionId, + registry::get_function_global_name, + registry::get_function_id_by_global_name, + FunctionIdVisitor +); +make_serializable!( + ValueTypeId, + registry::get_value_type_global_name, + registry::get_value_type_id_by_global_name, + ValueTypeVisitor +); +make_serializable!( + TraitTypeId, + registry::get_trait_type_global_name, + registry::get_trait_type_id_by_global_name, + TraitTypeVisitor +); + +pub trait IdMapping { + fn forward(&self, id:T) -> u32; + fn backward(&self, id:u32) -> T; +} + +impl IdMapping for &U +where + U: IdMapping, +{ + fn forward(&self, id:T) -> u32 { (**self).forward(id) } + + fn backward(&self, id:u32) -> T { (**self).backward(id) } +} + +struct TemporarySwapGuard<'c, T>(&'c RefCell, ManuallyDrop); + +impl<'c, T> Drop for TemporarySwapGuard<'c, T> { + fn drop(&mut self) { + // Safety: T is "taken out" only once here before dropping the whole object. + let old = unsafe { ManuallyDrop::take(&mut self.1) }; + *self.0.borrow_mut() = old; + } +} + +pub fn with_task_id_mapping<'a, T, M>(mapping:M, func:impl FnOnce() -> T) -> T +where + M: IdMapping + 'a, { + TASK_ID_MAPPING.with(|cell| { + let dyn_box:Box + 'a> = Box::new(mapping); + // SAFETY: We cast to 'static lifetime, but it's still safe since we remove the + // value again before the lifetime ends. So as long nobody copies the + // value it's safe. The thread_local is private, so nobody can use it + // except for this module. + let static_box:Box + 'static> = + unsafe { std::mem::transmute(dyn_box) }; + let old = std::mem::replace(&mut *cell.borrow_mut(), Some(static_box)); + let _swap_guard = TemporarySwapGuard(cell, ManuallyDrop::new(old)); + func() + }) +} + +pub fn without_task_id_mapping(func:impl FnOnce() -> T) -> T { + TASK_ID_MAPPING.with(|cell| { + let old = cell.borrow_mut().take(); + let _swap_guard = TemporarySwapGuard(cell, ManuallyDrop::new(old)); + func() + }) +} + +thread_local! { + static TASK_ID_MAPPING: RefCell>>> = RefCell::new(None); +} + +impl Serialize for TaskId { + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + TASK_ID_MAPPING.with(|cell| { + let mapped_id = if let Some(mapping) = cell.borrow().as_ref() { + mapping.forward(*self) + } else { + **self + }; + serializer.serialize_u64(mapped_id as u64) + }) + } +} + +impl<'de> Deserialize<'de> for TaskId { + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + struct V; + + impl Visitor<'_> for V { + type Value = TaskId; + + fn expecting(&self, f:&mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "task id") + } + + fn visit_u64(self, v:u64) -> Result + where + E: serde::de::Error, { + TASK_ID_MAPPING.with(|cell| { + let id = v as u32; + let mapped_id = if let Some(mapping) = cell.borrow().as_ref() { + mapping.backward(id) + } else { + TaskId::from(id) + }; + Ok(mapped_id) + }) + } + } + + deserializer.deserialize_u64(V) + } +} diff --git a/crates/turbo-tasks/Source/id_factory.rs b/crates/turbo-tasks/Source/id_factory.rs new file mode 100644 index 0000000000000..b4d7eabbeceff --- /dev/null +++ b/crates/turbo-tasks/Source/id_factory.rs @@ -0,0 +1,40 @@ +use std::{ + marker::PhantomData, + ops::Deref, + sync::atomic::{AtomicU32, Ordering}, +}; + +use concurrent_queue::ConcurrentQueue; +use once_cell::sync::Lazy; + +pub struct IdFactory { + next_id:AtomicU32, + free_ids:Lazy>, + phantom_data:PhantomData, +} + +impl + Deref> Default for IdFactory { + fn default() -> Self { Self::new() } +} + +impl + Deref> IdFactory { + pub const fn new() -> Self { + Self { + next_id:AtomicU32::new(1), + free_ids:Lazy::new(|| ConcurrentQueue::unbounded()), + phantom_data:PhantomData, + } + } + + pub fn get(&self) -> T { + if let Ok(id) = self.free_ids.pop() { + return id; + } + self.next_id.fetch_add(1, Ordering::Relaxed).into() + } + + /// # Safety + /// + /// It must be ensured that the id is no longer used + pub unsafe fn reuse(&self, id:T) { let _ = self.free_ids.push(id); } +} diff --git a/crates/turbo-tasks/Source/invalidation.rs b/crates/turbo-tasks/Source/invalidation.rs new file mode 100644 index 0000000000000..8f9ca9c4fba7d --- /dev/null +++ b/crates/turbo-tasks/Source/invalidation.rs @@ -0,0 +1,158 @@ +use std::{ + any::{Any, TypeId}, + fmt::Display, + hash::{Hash, Hasher}, + mem::replace, +}; + +use indexmap::{IndexMap, IndexSet, map::Entry}; + +use crate::{magic_any::HasherMut, util::StaticOrArc}; + +pub trait DynamicEqHash { + fn as_any(&self) -> &dyn Any; + fn dyn_eq(&self, other:&dyn Any) -> bool; + fn dyn_hash(&self, state:&mut dyn Hasher); +} + +impl DynamicEqHash for T { + fn as_any(&self) -> &dyn Any { self } + + fn dyn_eq(&self, other:&dyn Any) -> bool { + other.downcast_ref::().map(|other| self.eq(other)).unwrap_or(false) + } + + fn dyn_hash(&self, state:&mut dyn Hasher) { + Hash::hash(&(TypeId::of::(), self), &mut HasherMut(state)); + } +} + +/// A user-facing reason why a task was invalidated. This should only be used +/// for invalidation that were triggered by the user. +/// +/// Reasons are deduplicated, so this need to implement [Eq] and [Hash] +pub trait InvalidationReason: DynamicEqHash + Display + Send + Sync + 'static { + fn kind(&self) -> Option> { None } +} + +/// Invalidation reason kind. This is used to merge multiple reasons of the same +/// kind into a combined description. +/// +/// Reason kinds are used a hash map key, so this need to implement [Eq] and +/// [Hash] +pub trait InvalidationReasonKind: DynamicEqHash + Send + Sync + 'static { + /// Displays a description of multiple invalidation reasons of the same + /// kind. It is only called with two or more reasons. + fn fmt( + &self, + data:&IndexSet>, + f:&mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result; +} + +macro_rules! impl_eq_hash { + ($ty:ty) => { + impl PartialEq for $ty { + fn eq(&self, other:&Self) -> bool { DynamicEqHash::dyn_eq(self, other.as_any()) } + } + + impl Eq for $ty {} + + impl Hash for $ty { + fn hash(&self, state:&mut H) { + self.as_any().type_id().hash(state); + DynamicEqHash::dyn_hash(self, state as &mut dyn Hasher) + } + } + }; +} + +impl_eq_hash!(dyn InvalidationReason); +impl_eq_hash!(dyn InvalidationReasonKind); + +#[derive(PartialEq, Eq, Hash)] +enum MapKey { + Untyped { unique_tag:usize }, + Typed { kind:StaticOrArc }, +} + +enum MapEntry { + Single { reason:StaticOrArc }, + Multiple { reasons:IndexSet> }, +} + +/// A set of [InvalidationReason]s. They are automatically deduplicated and +/// merged by kind during insertion. It implements [Display] to get a readable +/// representation. +#[derive(Default)] +pub struct InvalidationReasonSet { + next_unique_tag:usize, + // We track typed and untyped entries in the same map to keep the occurence order of entries. + map:IndexMap, +} + +impl InvalidationReasonSet { + pub(crate) fn insert(&mut self, reason:StaticOrArc) { + if let Some(kind) = reason.kind() { + let key = MapKey::Typed { kind }; + match self.map.entry(key) { + Entry::Occupied(mut entry) => { + let entry = &mut *entry.get_mut(); + match replace(entry, MapEntry::Multiple { reasons:IndexSet::new() }) { + MapEntry::Single { reason: existing_reason } => { + if reason == existing_reason { + *entry = MapEntry::Single { reason:existing_reason }; + return; + } + let mut reasons = IndexSet::new(); + reasons.insert(existing_reason); + reasons.insert(reason); + *entry = MapEntry::Multiple { reasons }; + }, + MapEntry::Multiple { mut reasons } => { + reasons.insert(reason); + *entry = MapEntry::Multiple { reasons }; + }, + } + }, + Entry::Vacant(entry) => { + entry.insert(MapEntry::Single { reason }); + }, + } + } else { + let key = MapKey::Untyped { unique_tag:self.next_unique_tag }; + self.next_unique_tag += 1; + self.map.insert(key, MapEntry::Single { reason }); + } + } + + pub fn is_empty(&self) -> bool { self.map.is_empty() } + + pub fn len(&self) -> usize { self.map.len() } +} + +impl Display for InvalidationReasonSet { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let count = self.map.len(); + for (i, (key, entry)) in self.map.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + if i == count - 1 { + write!(f, "and ")?; + } + } + match entry { + MapEntry::Single { reason } => { + write!(f, "{}", reason)?; + }, + MapEntry::Multiple { reasons } => { + let MapKey::Typed { kind } = key else { + unreachable!("An untyped reason can't collect more than one reason"); + }; + kind.fmt(reasons, f)? + }, + } + } + Ok(()) + } +} diff --git a/crates/turbo-tasks/Source/join_iter_ext.rs b/crates/turbo-tasks/Source/join_iter_ext.rs new file mode 100644 index 0000000000000..9c61ac033b6a6 --- /dev/null +++ b/crates/turbo-tasks/Source/join_iter_ext.rs @@ -0,0 +1,167 @@ +use std::{ + future::{Future, IntoFuture}, + pin::Pin, + task::Poll, +}; + +use anyhow::Result; +use futures::{ + FutureExt, + future::{JoinAll, join_all}, +}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [JoinIterExt::join] method. + pub struct Join + where + F: Future, + { + #[pin] + inner: JoinAll, + } +} + +impl Future for Join +where + F: Future, +{ + type Output = Vec; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll { + self.project().inner.poll(cx) + } +} + +pub trait JoinIterExt: Iterator +where + F: Future, { + /// Returns a future that resolves to a vector of the outputs of the futures + /// in the iterator. + fn join(self) -> Join; +} + +pin_project! { + /// Future for the [TryJoinIterExt::try_join] method. + #[must_use] + pub struct TryJoin + where + F: Future, + { + #[pin] + inner: JoinAll, + } +} + +impl Future for TryJoin +where + F: Future>, +{ + type Output = Result>; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll { + match self.project().inner.poll_unpin(cx) { + std::task::Poll::Ready(res) => { + std::task::Poll::Ready(res.into_iter().collect::>>()) + }, + std::task::Poll::Pending => std::task::Poll::Pending, + } + } +} + +pub trait TryJoinIterExt: Iterator +where + F: Future>, { + /// Returns a future that resolves to a vector of the outputs of the futures + /// in the iterator, or to an error if one of the futures fail. + /// + /// Unlike `Futures::future::try_join_all`, this returns the Error that + /// occurs first in the list of futures, not the first to fail in time. + fn try_join(self) -> TryJoin; +} + +impl JoinIterExt for It +where + F: Future, + IF: IntoFuture, + It: Iterator, +{ + fn join(self) -> Join { Join { inner:join_all(self.map(|f| f.into_future())) } } +} + +impl TryJoinIterExt for It +where + F: Future>, + IF: IntoFuture, IntoFuture = F>, + It: Iterator, +{ + fn try_join(self) -> TryJoin { TryJoin { inner:join_all(self.map(|f| f.into_future())) } } +} + +pin_project! { + /// Future for the [TryFlatJoinIterExt::try_flat_join] method. + pub struct TryFlatJoin + where + F: Future, + { + #[pin] + inner: JoinAll, + } +} + +impl Future for TryFlatJoin +where + F: Future>, + I: IntoIterator, + U: Iterator, +{ + type Output = Result>; + + fn poll(self: Pin<&mut Self>, cx:&mut std::task::Context<'_>) -> Poll { + match self.project().inner.poll_unpin(cx) { + Poll::Ready(res) => { + let mut v = Vec::new(); + for r in res { + v.extend(r?); + } + + Poll::Ready(Ok(v)) + }, + Poll::Pending => Poll::Pending, + } + } +} + +pub trait TryFlatJoinIterExt: Iterator +where + F: Future>, + I: IntoIterator, + U: Iterator, { + /// Returns a future that resolves to a vector of the outputs of the futures + /// in the iterator, or to an error if one of the futures fail. + /// + /// It also flattens the result. + /// + /// Unlike `Futures::future::try_join_all`, this returns the Error that + /// occurs first in the list of futures, not the first to fail in time. + fn try_flat_join(self) -> TryFlatJoin; +} + +impl TryFlatJoinIterExt for It +where + F: Future>, + IF: IntoFuture, IntoFuture = F>, + It: Iterator, + I: IntoIterator, + U: Iterator, +{ + fn try_flat_join(self) -> TryFlatJoin { + TryFlatJoin { inner:join_all(self.map(|f| f.into_future())) } + } +} diff --git a/crates/turbo-tasks/Source/keyed_cell.rs b/crates/turbo-tasks/Source/keyed_cell.rs new file mode 100644 index 0000000000000..1665f63d3e514 --- /dev/null +++ b/crates/turbo-tasks/Source/keyed_cell.rs @@ -0,0 +1,78 @@ +use anyhow::Result; + +use crate::{ + self as turbo_tasks, + ConcreteTaskInput, + CurrentCellRef, + RawVc, + TaskId, + TaskInput, + ValueTypeId, + Vc, + VcValueType, + macro_helpers::find_cell_by_type, + manager::current_task, +}; + +#[turbo_tasks::value] +struct KeyedCell { + cell:RawVc, + #[turbo_tasks(trace_ignore, debug_ignore)] + cell_ref:CurrentCellRef, +} + +#[turbo_tasks::value_impl] +impl KeyedCell { + #[turbo_tasks::function] + fn new_local(_task:TaskId, _key:ConcreteTaskInput, value_type_id:ValueTypeId) -> Vc { + let cell_ref = find_cell_by_type(value_type_id); + KeyedCell { cell:cell_ref.into(), cell_ref }.cell() + } + + #[turbo_tasks::function] + fn new_global(_key:ConcreteTaskInput, value_type_id:ValueTypeId) -> Vc { + let cell_ref = find_cell_by_type(value_type_id); + KeyedCell { cell:cell_ref.into(), cell_ref }.cell() + } +} + +/// Cells a value in a cell with a given key. A key MUST only be used once per +/// function. +/// +/// Usually calling [Vc::cell] will create cells for a give type based on the +/// call order of [Vc::cell]. But this can yield to over-invalidation when the +/// number of cells changes. e. g. not doing the first [Vc::cell] call will move +/// all remaining values into different cells, causing invalidation of all of +/// them. +/// +/// A keyed cell avoids this problem by not using call order, but a key instead. +/// +/// Internally it creates a new Task based on the key and cells the value into +/// that task. This is a implementation detail and might change in the future. +pub async fn keyed_cell( + key:K, + content:T, +) -> Result> { + let cell = KeyedCell::new_local( + current_task("keyed_cell"), + key.into_concrete(), + T::get_value_type_id(), + ) + .await?; + cell.cell_ref.compare_and_update_shared(content); + Ok(cell.cell.into()) +} + +/// Cells a value in a cell with a given key. A key MUST only be used once for +/// the whole application. +/// +/// This allows to create singleton Vcs for values while avoiding to pass the +/// whole value as argument and creating a large task key. +pub async fn global_keyed_cell( + key:K, + content:T, +) -> Result> { + let cell = KeyedCell::new_global(key.into_concrete(), T::get_value_type_id()).await?; + cell.cell_ref.compare_and_update_shared(content); + Ok(cell.cell.into()) +} diff --git a/crates/turbo-tasks/Source/lib.rs b/crates/turbo-tasks/Source/lib.rs new file mode 100644 index 0000000000000..5b03b4cb16df0 --- /dev/null +++ b/crates/turbo-tasks/Source/lib.rs @@ -0,0 +1,159 @@ +//! A task scheduling and caching system that is focused on incremental +//! execution. +//! +//! It defines 4 primitives: +//! - functions: Unit of execution, invalidation and reexecution. +//! - values: Data created, stored and returned by functions. +//! - traits: Traits that define a set of functions on values. +//! - collectibles: Values emitted in functions that bubble up the call graph +//! and can be collected in parent functions. +//! +//! It also defines some derived elements from that: +//! - cells: The locations in functions where values are stored. The content of +//! a cell can change after the reexecution of a function. +//! - Vcs: A reference to a cell in a function or a return value of a function. +//! - task: An instance of a function together with its arguments. +//! +//! A Vc can be read to get a read-only reference to the stored data. +//! +//! On execution of functions, turbo-tasks will track which Vcs are read. Once +//! any of these change, turbo-tasks will invalidate the task created from the +//! function's execution and it will eventually be scheduled and reexecuted. +//! +//! Collectibles go through a similar process. + +#![feature(trivial_bounds)] +#![feature(min_specialization)] +#![feature(try_trait_v2)] +#![feature(hash_extract_if)] +#![deny(unsafe_op_in_unsafe_fn)] +#![feature(result_flattening)] +#![feature(error_generic_member_access)] +#![feature(new_uninit)] +#![feature(arbitrary_self_types)] +#![feature(type_alias_impl_trait)] +#![feature(never_type)] + +pub mod backend; +mod capture_future; +mod collectibles; +mod completion; +pub mod debug; +mod display; +pub mod duration_span; +pub mod event; +mod generics; +pub mod graph; +mod id; +mod id_factory; +mod invalidation; +mod join_iter_ext; +mod keyed_cell; +#[doc(hidden)] +pub mod macro_helpers; +mod magic_any; +mod manager; +mod native_function; +mod no_move_vec; +mod once_map; +pub mod persisted_graph; +pub mod primitives; +mod raw_vc; +mod raw_vc_set; +mod rcstr; +mod read_ref; +pub mod registry; +pub mod small_duration; +mod state; +pub mod task; +pub mod trace; +mod trait_ref; +pub mod util; +mod value; +mod value_type; +mod vc; + +pub use anyhow::{Error, Result}; +use auto_hash_map::AutoSet; +pub use collectibles::CollectiblesSource; +pub use completion::{Completion, Completions}; +pub use display::ValueToString; +pub use id::{ + FunctionId, + IdMapping, + TaskId, + TraitTypeId, + ValueTypeId, + with_task_id_mapping, + without_task_id_mapping, +}; +pub use invalidation::{ + DynamicEqHash, + InvalidationReason, + InvalidationReasonKind, + InvalidationReasonSet, +}; +pub use join_iter_ext::{JoinIterExt, TryFlatJoinIterExt, TryJoinIterExt}; +pub use keyed_cell::{global_keyed_cell, keyed_cell}; +pub use manager::{ + CurrentCellRef, + Invalidator, + TaskIdProvider, + TurboTasks, + TurboTasksApi, + TurboTasksBackendApi, + TurboTasksCallApi, + Unused, + UpdateInfo, + dynamic_call, + emit, + get_invalidator, + mark_finished, + mark_stateful, + prevent_gc, + run_once, + run_once_with_reason, + spawn_blocking, + spawn_thread, + trait_call, + turbo_tasks, +}; +pub use native_function::NativeFunction; +use nohash_hasher::BuildNoHashHasher; +pub use raw_vc::{CellId, RawVc, ReadRawVcFuture, ResolveTypeError}; +pub use read_ref::ReadRef; +pub use state::State; +pub use task::{ + concrete_task_input::{ConcreteTaskInput, SharedReference, SharedValue}, + task_input::TaskInput, +}; +pub use trait_ref::{IntoTraitRef, TraitRef}; +pub use turbo_tasks_macros::{TaskInput, function, value, value_impl, value_trait}; +pub use value::{TransientInstance, TransientValue, Value}; +pub use value_type::{TraitMethod, TraitType, ValueType}; +pub use vc::{ + Dynamic, + TypedForInput, + Upcast, + ValueDefault, + Vc, + VcCellNewMode, + VcCellSharedMode, + VcDefaultRead, + VcRead, + VcTransparentRead, + VcValueTrait, + VcValueType, +}; + +pub use crate::rcstr::RcStr; + +pub type TaskIdSet = AutoSet, 2>; + +pub mod test_helpers { + pub use super::manager::{current_task_for_testing, with_turbo_tasks_for_testing}; +} + +pub fn register() { + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbo-tasks/Source/macro_helpers.rs b/crates/turbo-tasks/Source/macro_helpers.rs new file mode 100644 index 0000000000000..9d4fea002a9fd --- /dev/null +++ b/crates/turbo-tasks/Source/macro_helpers.rs @@ -0,0 +1,19 @@ +//! Runtime helpers for [turbo-tasks-macro]. +pub use once_cell::sync::{Lazy, OnceCell}; +pub use tracing; + +pub use super::manager::{find_cell_by_type, notify_scheduled_tasks, spawn_detached}; +use crate::debug::ValueDebugFormatString; + +#[inline(never)] +pub async fn value_debug_format_field(value:ValueDebugFormatString<'_>) -> String { + match value.try_to_value_debug_string().await { + Ok(result) => { + match result.await { + Ok(result) => result.to_string(), + Err(err) => format!("{0:?}", err), + } + }, + Err(err) => format!("{0:?}", err), + } +} diff --git a/crates/turbo-tasks/Source/magic_any.rs b/crates/turbo-tasks/Source/magic_any.rs new file mode 100644 index 0000000000000..dc5411721b905 --- /dev/null +++ b/crates/turbo-tasks/Source/magic_any.rs @@ -0,0 +1,192 @@ +use core::fmt; +use std::{ + any::{Any, TypeId}, + cmp::Ordering, + fmt::Debug, + hash::{Hash, Hasher}, + ops::DerefMut, + sync::Arc, +}; + +use serde::{Deserialize, Serialize, de::DeserializeSeed}; + +pub trait MagicAny: mopa::Any + Send + Sync { + fn magic_any_arc(self: Arc) -> Arc; + + fn magic_debug(&self, f:&mut fmt::Formatter) -> fmt::Result; + + fn magic_eq(&self, other:&dyn MagicAny) -> bool; + + fn magic_hash(&self, hasher:&mut dyn Hasher); + + fn magic_cmp(&self, other:&dyn MagicAny) -> Ordering; + + #[cfg(debug_assertions)] + fn magic_type_name(&self) -> &'static str; +} + +#[allow(clippy::transmute_ptr_to_ref)] // can't fix as it's in the macro +mod clippy { + use mopa::mopafy; + + use super::MagicAny; + + mopafy!(MagicAny); +} + +impl MagicAny for T { + fn magic_any_arc(self: Arc) -> Arc { self } + + fn magic_debug(&self, f:&mut fmt::Formatter) -> fmt::Result { + let mut d = f.debug_tuple("MagicAny"); + d.field(&TypeId::of::()); + + #[cfg(debug_assertions)] + d.field(&std::any::type_name::()); + + d.field(&(self as &Self)); + d.finish() + } + + fn magic_eq(&self, other:&dyn MagicAny) -> bool { + match other.downcast_ref::() { + None => false, + Some(other) => self == other, + } + } + + fn magic_hash(&self, hasher:&mut dyn Hasher) { + Hash::hash(&(TypeId::of::(), self), &mut HasherMut(hasher)) + } + + fn magic_cmp(&self, other:&dyn MagicAny) -> Ordering { + match other.downcast_ref::() { + None => Ord::cmp(&TypeId::of::(), &other.type_id()), + Some(other) => self.cmp(other), + } + } + + #[cfg(debug_assertions)] + fn magic_type_name(&self) -> &'static str { std::any::type_name::() } +} + +impl fmt::Debug for dyn MagicAny { + fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result { self.magic_debug(f) } +} + +impl PartialEq for dyn MagicAny { + fn eq(&self, other:&Self) -> bool { self.magic_eq(other) } +} + +impl Eq for dyn MagicAny {} + +impl PartialOrd for dyn MagicAny { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for dyn MagicAny { + fn cmp(&self, other:&Self) -> Ordering { self.magic_cmp(other) } +} + +impl Hash for dyn MagicAny { + fn hash(&self, hasher:&mut H) { self.magic_hash(hasher) } +} + +pub struct HasherMut(pub H); + +impl Hasher for HasherMut +where + H::Target: Hasher, +{ + fn finish(&self) -> u64 { self.0.finish() } + + fn write(&mut self, bytes:&[u8]) { self.0.write(bytes) } +} + +impl dyn MagicAny { + pub fn as_serialize( + &self, + ) -> &dyn erased_serde::Serialize { + if let Some(r) = self.downcast_ref::() { + r + } else { + #[cfg(debug_assertions)] + panic!( + "MagicAny::as_serializable broken: got {} but expected {}", + self.magic_type_name(), + std::any::type_name::() + ); + #[cfg(not(debug_assertions))] + panic!("MagicAny::as_serializable bug"); + } + } +} + +type MagicAnyDeserializeSeedFunctor = + fn(&mut dyn erased_serde::Deserializer<'_>) -> Result, erased_serde::Error>; + +#[derive(Clone, Copy)] +pub struct MagicAnyDeserializeSeed { + functor:MagicAnyDeserializeSeedFunctor, +} + +impl MagicAnyDeserializeSeed { + pub fn new() -> Self + where + T: for<'de> Deserialize<'de> + Debug + Eq + Ord + Hash + Send + Sync + 'static, { + fn deserialize< + T:Debug + Eq + Ord + Hash + for<'de> Deserialize<'de> + Send + Sync + 'static, + >( + deserializer:&mut dyn erased_serde::Deserializer<'_>, + ) -> Result, erased_serde::Error> { + let value:T = erased_serde::deserialize(deserializer)?; + Ok(Box::new(value)) + } + Self { functor:deserialize:: } + } +} + +impl<'de> DeserializeSeed<'de> for MagicAnyDeserializeSeed { + type Value = Box; + + fn deserialize(self, deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + let mut deserializer = ::erase(deserializer); + (self.functor)(&mut deserializer).map_err(serde::de::Error::custom) + } +} + +type AnyDeserializeSeedFunctor = fn( + &mut dyn erased_serde::Deserializer<'_>, +) -> Result, erased_serde::Error>; + +#[derive(Clone, Copy)] +pub struct AnyDeserializeSeed { + functor:AnyDeserializeSeedFunctor, +} + +impl AnyDeserializeSeed { + pub fn new() -> Self + where + T: for<'de> Deserialize<'de> + Any + Send + Sync + 'static, { + fn deserialize Deserialize<'de> + Send + Sync + 'static>( + deserializer:&mut dyn erased_serde::Deserializer<'_>, + ) -> Result, erased_serde::Error> { + let value:T = erased_serde::deserialize(deserializer)?; + Ok(Box::new(value)) + } + Self { functor:deserialize:: } + } +} + +impl<'de> DeserializeSeed<'de> for AnyDeserializeSeed { + type Value = Box; + + fn deserialize(self, deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + let mut deserializer = ::erase(deserializer); + (self.functor)(&mut deserializer).map_err(serde::de::Error::custom) + } +} diff --git a/crates/turbo-tasks/Source/manager.rs b/crates/turbo-tasks/Source/manager.rs new file mode 100644 index 0000000000000..ea651a0721483 --- /dev/null +++ b/crates/turbo-tasks/Source/manager.rs @@ -0,0 +1,1400 @@ +use std::{ + borrow::Cow, + cell::RefCell, + future::Future, + hash::Hash, + mem::take, + panic::AssertUnwindSafe, + pin::Pin, + sync::{ + Arc, + Mutex, + Weak, + atomic::{AtomicBool, AtomicUsize, Ordering}, + }, + thread, + time::{Duration, Instant}, +}; + +use anyhow::{Result, anyhow}; +use auto_hash_map::AutoMap; +use futures::FutureExt; +use nohash_hasher::BuildNoHashHasher; +use serde::{Deserialize, Serialize, de::Visitor}; +use tokio::{runtime::Handle, select, task_local}; +use tracing::{Instrument, Level, info_span, instrument, trace_span}; +use turbo_tasks_malloc::TurboMalloc; + +use crate::{ + Completion, + ConcreteTaskInput, + InvalidationReason, + InvalidationReasonSet, + SharedReference, + TaskId, + TaskIdSet, + ValueTypeId, + Vc, + VcRead, + VcValueTrait, + VcValueType, + backend::{Backend, CellContent, PersistentTaskType, TaskExecutionSpec, TransientTaskType}, + capture_future::{ + CaptureFuture, + {self}, + }, + event::{Event, EventListener}, + id::{BackendJobId, FunctionId, TraitTypeId}, + id_factory::IdFactory, + raw_vc::{CellId, RawVc}, + registry, + trace::TraceRawVcs, + util::StaticOrArc, +}; + +pub trait TurboTasksCallApi: Sync + Send { + fn dynamic_call(&self, func:FunctionId, inputs:Vec) -> RawVc; + fn native_call(&self, func:FunctionId, inputs:Vec) -> RawVc; + fn trait_call( + &self, + trait_type:TraitTypeId, + trait_fn_name:Cow<'static, str>, + inputs:Vec, + ) -> RawVc; + + fn run_once(&self, future:Pin> + Send + 'static>>) + -> TaskId; + fn run_once_with_reason( + &self, + reason:StaticOrArc, + future:Pin> + Send + 'static>>, + ) -> TaskId; + fn run_once_process( + &self, + future:Pin> + Send + 'static>>, + ) -> TaskId; +} + +pub trait TurboTasksApi: TurboTasksCallApi + Sync + Send { + fn pin(&self) -> Arc; + + fn invalidate(&self, task:TaskId); + fn invalidate_with_reason(&self, task:TaskId, reason:StaticOrArc); + + /// Eagerly notifies all tasks that were scheduled for notifications via + /// `schedule_notify_tasks_set()` + fn notify_scheduled_tasks(&self); + + fn try_read_task_output( + &self, + task:TaskId, + strongly_consistent:bool, + ) -> Result>; + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + fn try_read_task_output_untracked( + &self, + task:TaskId, + strongly_consistent:bool, + ) -> Result>; + + fn try_read_task_cell( + &self, + task:TaskId, + index:CellId, + ) -> Result>; + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + fn try_read_task_cell_untracked( + &self, + task:TaskId, + index:CellId, + ) -> Result>; + + fn read_task_collectibles(&self, task:TaskId, trait_id:TraitTypeId) -> AutoMap; + + fn emit_collectible(&self, trait_type:TraitTypeId, collectible:RawVc); + fn unemit_collectible(&self, trait_type:TraitTypeId, collectible:RawVc, count:u32); + fn unemit_collectibles(&self, trait_type:TraitTypeId, collectibles:&AutoMap); + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + fn try_read_own_task_cell_untracked( + &self, + current_task:TaskId, + index:CellId, + ) -> Result; + + fn read_own_task_cell(&self, task:TaskId, index:CellId) -> Result; + fn update_own_task_cell(&self, task:TaskId, index:CellId, content:CellContent); + fn mark_own_task_as_finished(&self, task:TaskId); + + fn connect_task(&self, task:TaskId); + + /// Wraps the given future in the current task. + fn detached( + &self, + f:Pin> + Send + 'static>>, + ) -> Pin> + Send + 'static>>; +} + +pub trait TaskIdProvider { + fn get_fresh_task_id(&self) -> Unused; + fn reuse_task_id(&self, id:Unused); +} + +impl TaskIdProvider for IdFactory { + fn get_fresh_task_id(&self) -> Unused { + // Safety: This is a fresh id from the factory + unsafe { Unused::new_unchecked(self.get()) } + } + + fn reuse_task_id(&self, id:Unused) { unsafe { self.reuse(id.into()) } } +} + +/// A wrapper around a value that is unused. +pub struct Unused { + inner:T, +} + +impl Unused { + /// Creates a new unused value. + /// + /// # Safety + /// + /// The wrapped value must not be used. + pub unsafe fn new_unchecked(inner:T) -> Self { Self { inner } } + + /// Get the inner value, without consuming the `Unused` wrapper. + /// + /// # Safety + /// + /// The user need to make sure that the value stays unused. + pub unsafe fn get_unchecked(&self) -> &T { &self.inner } + + /// Unwraps the value, consuming the `Unused` wrapper. + pub fn into(self) -> T { self.inner } +} + +pub trait TurboTasksBackendApi: + TaskIdProvider + TurboTasksCallApi + Sync + Send { + fn pin(&self) -> Arc>; + + fn schedule(&self, task:TaskId); + fn schedule_backend_background_job(&self, id:BackendJobId); + fn schedule_backend_foreground_job(&self, id:BackendJobId); + + fn try_foreground_done(&self) -> Result<(), EventListener>; + fn wait_foreground_done_excluding_own<'a>( + &'a self, + ) -> Option + Send + 'a>>>; + + /// Enqueues tasks for notification of changed dependencies. This will + /// eventually call `invalidate_tasks()` on all tasks. + fn schedule_notify_tasks(&self, tasks:&[TaskId]); + + /// Enqueues tasks for notification of changed dependencies. This will + /// eventually call `invalidate_tasks()` on all tasks. + fn schedule_notify_tasks_set(&self, tasks:&TaskIdSet); + + /// Returns the duration from the start of the program to the given instant. + fn program_duration_until(&self, instant:Instant) -> Duration; + /// Returns a reference to the backend. + fn backend(&self) -> &B; +} + +impl TaskIdProvider for &dyn TurboTasksBackendApi { + fn get_fresh_task_id(&self) -> Unused { (*self).get_fresh_task_id() } + + fn reuse_task_id(&self, id:Unused) { (*self).reuse_task_id(id) } +} + +impl TaskIdProvider for &dyn TaskIdProvider { + fn get_fresh_task_id(&self) -> Unused { (*self).get_fresh_task_id() } + + fn reuse_task_id(&self, id:Unused) { (*self).reuse_task_id(id) } +} + +#[allow(clippy::manual_non_exhaustive)] +pub struct UpdateInfo { + pub duration:Duration, + pub tasks:usize, + pub reasons:InvalidationReasonSet, + #[allow(dead_code)] + placeholder_for_future_fields:(), +} + +pub struct TurboTasks { + this:Weak, + backend:B, + task_id_factory:IdFactory, + stopped:AtomicBool, + currently_scheduled_tasks:AtomicUsize, + currently_scheduled_foreground_jobs:AtomicUsize, + currently_scheduled_background_jobs:AtomicUsize, + scheduled_tasks:AtomicUsize, + start:Mutex>, + aggregated_update:Mutex<(Option<(Duration, usize)>, InvalidationReasonSet)>, + event:Event, + event_start:Event, + event_foreground:Event, + event_background:Event, + program_start:Instant, +} + +#[derive(Default)] +struct CurrentTaskState { + /// Affected [Task]s, that are tracked during task execution + /// These tasks will be invalidated when the execution finishes + /// or before reading a cell value + tasks_to_notify:Vec, + + // true, if the current task has state in cells + stateful:bool, +} + +// TODO implement our own thread pool and make these thread locals instead +task_local! { + /// The current TurboTasks instance + static TURBO_TASKS: Arc; + + static CELL_COUNTERS: RefCell, 8>>; + + static CURRENT_TASK_ID: TaskId; + + static CURRENT_TASK_STATE: RefCell; +} + +impl TurboTasks { + // TODO better lifetime management for turbo tasks + // consider using unsafe for the task_local turbo tasks + // that should be safe as long tasks can't outlife turbo task + // so we probably want to make sure that all tasks are joined + // when trying to drop turbo tasks + pub fn new(mut backend:B) -> Arc { + let task_id_factory = IdFactory::new(); + backend.initialize(&task_id_factory); + let this = Arc::new_cyclic(|this| { + Self { + this:this.clone(), + backend, + task_id_factory, + stopped:AtomicBool::new(false), + currently_scheduled_tasks:AtomicUsize::new(0), + currently_scheduled_background_jobs:AtomicUsize::new(0), + currently_scheduled_foreground_jobs:AtomicUsize::new(0), + scheduled_tasks:AtomicUsize::new(0), + start:Default::default(), + aggregated_update:Default::default(), + event:Event::new(|| "TurboTasks::event".to_string()), + event_start:Event::new(|| "TurboTasks::event_start".to_string()), + event_foreground:Event::new(|| "TurboTasks::event_foreground".to_string()), + event_background:Event::new(|| "TurboTasks::event_background".to_string()), + program_start:Instant::now(), + } + }); + this.backend.startup(&*this); + this + } + + pub fn pin(&self) -> Arc { self.this.upgrade().unwrap() } + + /// Creates a new root task + pub fn spawn_root_task(&self, functor:F) -> TaskId + where + T: Send, + F: Fn() -> Fut + Send + Sync + Clone + 'static, + Fut: Future>> + Send, { + let id = self.backend.create_transient_task( + TransientTaskType::Root(Box::new(move || { + let functor = functor.clone(); + Box::pin(async move { Ok(functor().await?.node) }) + })), + self, + ); + self.schedule(id); + id + } + + pub fn dispose_root_task(&self, task_id:TaskId) { + self.backend.dispose_root_task(task_id, self); + } + + // TODO make sure that all dependencies settle before reading them + /// Creates a new root task, that is only executed once. + /// Dependencies will not invalidate the task. + #[track_caller] + pub fn spawn_once_task(&self, future:Fut) -> TaskId + where + T: Send, + Fut: Future>> + Send + 'static, { + let id = self.backend.create_transient_task( + TransientTaskType::Once(Box::pin(async move { Ok(future.await?.node) })), + self, + ); + self.schedule(id); + id + } + + pub async fn run_once( + &self, + future:impl Future> + Send + 'static, + ) -> Result { + let (tx, rx) = tokio::sync::oneshot::channel(); + let task_id = self.spawn_once_task(async move { + let result = future.await?; + tx.send(result).map_err(|_| anyhow!("unable to send result"))?; + Ok(Completion::new()) + }); + // INVALIDATION: A Once task will never invalidate, therefore we don't need to + // track a dependency + let raw_result = read_task_output_untracked(self, task_id, false).await?; + raw_result.into_read_untracked_with_turbo_tasks::(self).await?; + + Ok(rx.await?) + } + + /// Call a native function with arguments. + /// All inputs must be resolved. + pub(crate) fn native_call(&self, func:FunctionId, inputs:Vec) -> RawVc { + RawVc::TaskOutput(self.backend.get_or_create_persistent_task( + PersistentTaskType::Native(func, inputs), + current_task("turbo_function calls"), + self, + )) + } + + /// Calls a native function with arguments. Resolves arguments when needed + /// with a wrapper [Task]. + pub fn dynamic_call(&self, func:FunctionId, inputs:Vec) -> RawVc { + if inputs.iter().all(|i| i.is_resolved()) { + self.native_call(func, inputs) + } else { + RawVc::TaskOutput(self.backend.get_or_create_persistent_task( + PersistentTaskType::ResolveNative(func, inputs), + current_task("turbo_function calls"), + self, + )) + } + } + + /// Calls a trait method with arguments. First input is the `self` object. + /// Uses a wrapper task to resolve + pub fn trait_call( + &self, + trait_type:TraitTypeId, + mut trait_fn_name:Cow<'static, str>, + inputs:Vec, + ) -> RawVc { + // avoid creating a wrapper task if self is already resolved + // for resolved cells we already know the value type so we can lookup the + // function + let first_input = inputs.first().expect("trait call without self argument"); + if let &ConcreteTaskInput::TaskCell(_, CellId { type_id, .. }) = first_input { + let value_type = registry::get_value_type(type_id); + let key = (trait_type, trait_fn_name); + if let Some(native_fn) = value_type.get_trait_method(&key) { + return self.dynamic_call(*native_fn, inputs); + } + trait_fn_name = key.1; + } + + // create a wrapper task to resolve all inputs + RawVc::TaskOutput(self.backend.get_or_create_persistent_task( + PersistentTaskType::ResolveTrait(trait_type, trait_fn_name, inputs), + current_task("turbo_function calls"), + self, + )) + } + + #[track_caller] + pub(crate) fn schedule(&self, task_id:TaskId) { + self.begin_primary_job(); + self.scheduled_tasks.fetch_add(1, Ordering::AcqRel); + + #[cfg(feature = "tokio_tracing")] + let description = self.backend.get_task_description(task_id); + + let this = self.pin(); + let future = async move { + #[allow(clippy::blocks_in_conditions)] + while CURRENT_TASK_STATE + .scope(Default::default(), async { + if this.stopped.load(Ordering::Acquire) { + return false; + } + + // Setup thread locals + CELL_COUNTERS + .scope(Default::default(), async { + let Some(TaskExecutionSpec { future, span }) = + this.backend.try_start_task_execution(task_id, &*this) + else { + return false; + }; + + async { + let (result, duration, _instant, memory_usage) = + CaptureFuture::new(AssertUnwindSafe(future).catch_unwind()) + .await; + + let result = result.map_err(|any| { + match any.downcast::() { + Ok(owned) => Some(Cow::Owned(*owned)), + Err(any) => { + match any.downcast::<&'static str>() { + Ok(str) => Some(Cow::Borrowed(*str)), + Err(_) => None, + } + }, + } + }); + this.backend.task_execution_result(task_id, result, &*this); + let stateful = this.finish_current_task_state(); + this.backend.task_execution_completed( + task_id, + duration, + memory_usage, + stateful, + &*this, + ) + } + .instrument(span) + .await + }) + .await + }) + .await + {} + this.finish_primary_job(); + anyhow::Ok(()) + }; + + let future = TURBO_TASKS + .scope( + self.pin(), + CURRENT_TASK_ID.scope(task_id, self.backend.execution_scope(task_id, future)), + ) + .in_current_span(); + + #[cfg(feature = "tokio_tracing")] + tokio::task::Builder::new().name(&description).spawn(future).unwrap(); + #[cfg(not(feature = "tokio_tracing"))] + tokio::task::spawn(future); + } + + fn begin_primary_job(&self) { + if self.currently_scheduled_tasks.fetch_add(1, Ordering::AcqRel) == 0 { + *self.start.lock().unwrap() = Some(Instant::now()); + self.event_start.notify(usize::MAX); + } + } + + fn begin_foreground_job(&self) { + self.begin_primary_job(); + self.currently_scheduled_foreground_jobs.fetch_add(1, Ordering::AcqRel); + } + + fn finish_primary_job(&self) { + if self.currently_scheduled_tasks.fetch_sub(1, Ordering::AcqRel) == 1 { + self.backend.idle_start(self); + // That's not super race-condition-safe, but it's only for + // statistical reasons + let total = self.scheduled_tasks.load(Ordering::Acquire); + self.scheduled_tasks.store(0, Ordering::Release); + if let Some(start) = *self.start.lock().unwrap() { + let (update, _) = &mut *self.aggregated_update.lock().unwrap(); + if let Some(update) = update.as_mut() { + update.0 += start.elapsed(); + update.1 += total; + } else { + *update = Some((start.elapsed(), total)); + } + } + self.event.notify(usize::MAX); + } + } + + fn finish_foreground_job(&self) { + if self.currently_scheduled_foreground_jobs.fetch_sub(1, Ordering::AcqRel) == 1 { + self.event_foreground.notify(usize::MAX); + } + self.finish_primary_job(); + } + + pub async fn wait_foreground_done(&self) { + if self.currently_scheduled_foreground_jobs.load(Ordering::Acquire) == 0 { + return; + } + let listener = self.event_foreground.listen(); + if self.currently_scheduled_foreground_jobs.load(Ordering::Acquire) == 0 { + return; + } + listener.instrument(trace_span!("wait_foreground_done")).await; + } + + pub fn get_in_progress_count(&self) -> usize { + self.currently_scheduled_tasks.load(Ordering::Acquire) + } + + pub async fn wait_task_completion(&self, id:TaskId, fully_settled:bool) -> Result<()> { + // INVALIDATION: This doesn't return a value, only waits for it to be ready. + let result = read_task_output_untracked(self, id, fully_settled).await; + result.map(|_| ()) + } + + #[deprecated(note = "Use get_or_wait_aggregated_update_info instead")] + pub async fn get_or_wait_update_info(&self, aggregation:Duration) -> (Duration, usize) { + let UpdateInfo { duration, tasks, .. } = + self.get_or_wait_aggregated_update_info(aggregation).await; + (duration, tasks) + } + + #[deprecated(note = "Use aggregated_update_info instead")] + pub async fn update_info( + &self, + aggregation:Duration, + timeout:Duration, + ) -> Option<(Duration, usize)> { + self.aggregated_update_info(aggregation, timeout) + .await + .map(|UpdateInfo { duration, tasks, .. }| (duration, tasks)) + } + + /// Returns [UpdateInfo] with all updates aggregated over a given duration + /// (`aggregation`). Will wait until an update happens. + pub async fn get_or_wait_aggregated_update_info(&self, aggregation:Duration) -> UpdateInfo { + self.aggregated_update_info(aggregation, Duration::MAX).await.unwrap() + } + + /// Returns [UpdateInfo] with all updates aggregated over a given duration + /// (`aggregation`). Will only return None when the timeout is reached while + /// waiting for the first update. + pub async fn aggregated_update_info( + &self, + aggregation:Duration, + timeout:Duration, + ) -> Option { + let listener = self.event.listen_with_note(|| "wait for update info".to_string()); + let wait_for_finish = { + let (update, reason_set) = &mut *self.aggregated_update.lock().unwrap(); + if aggregation.is_zero() { + if let Some((duration, tasks)) = update.take() { + return Some(UpdateInfo { + duration, + tasks, + reasons:take(reason_set), + placeholder_for_future_fields:(), + }); + } else { + true + } + } else { + update.is_none() + } + }; + if wait_for_finish { + if timeout == Duration::MAX { + // wait for finish + listener.await; + } else { + // wait for start, then wait for finish or timeout + let start_listener = + self.event_start.listen_with_note(|| "wait for update info".to_string()); + if self.currently_scheduled_tasks.load(Ordering::Acquire) == 0 { + start_listener.await; + } else { + drop(start_listener); + } + if timeout.is_zero() || tokio::time::timeout(timeout, listener).await.is_err() { + // Timeout + return None; + } + } + } + if !aggregation.is_zero() { + loop { + select! { + () = tokio::time::sleep(aggregation) => { + break; + } + () = self.event.listen_with_note(|| "wait for update info".to_string()) => { + // Resets the sleep + } + } + } + } + let (update, reason_set) = &mut *self.aggregated_update.lock().unwrap(); + if let Some((duration, tasks)) = update.take() { + Some(UpdateInfo { + duration, + tasks, + reasons:take(reason_set), + placeholder_for_future_fields:(), + }) + } else { + panic!("aggregated_update_info must not called concurrently") + } + } + + pub async fn wait_background_done(&self) { + let listener = self.event_background.listen(); + if self.currently_scheduled_background_jobs.load(Ordering::Acquire) != 0 { + listener.await; + } + } + + pub async fn stop_and_wait(&self) { + self.stopped.store(true, Ordering::Release); + { + let listener = self.event.listen_with_note(|| "wait for stop".to_string()); + if self.currently_scheduled_tasks.load(Ordering::Acquire) != 0 { + listener.await; + } + } + { + let listener = self.event_background.listen(); + if self.currently_scheduled_background_jobs.load(Ordering::Acquire) != 0 { + listener.await; + } + } + self.backend.stop(self); + } + + #[track_caller] + pub(crate) fn schedule_background_job< + T:FnOnce(Arc>) -> F + Send + 'static, + F:Future + Send + 'static, + >( + &self, + func:T, + ) { + let this = self.pin(); + self.currently_scheduled_background_jobs.fetch_add(1, Ordering::AcqRel); + tokio::spawn( + TURBO_TASKS + .scope(this.clone(), async move { + while this.currently_scheduled_tasks.load(Ordering::Acquire) != 0 { + let listener = this.event.listen_with_note(|| { + "background job waiting for execution".to_string() + }); + if this.currently_scheduled_tasks.load(Ordering::Acquire) != 0 { + listener.await; + } + } + let this2 = this.clone(); + if !this.stopped.load(Ordering::Acquire) { + func(this).await; + } + if this2.currently_scheduled_background_jobs.fetch_sub(1, Ordering::AcqRel) == 1 + { + this2.event_background.notify(usize::MAX); + } + }) + .in_current_span(), + ); + } + + #[track_caller] + pub(crate) fn schedule_foreground_job< + T:FnOnce(Arc>) -> F + Send + 'static, + F:Future + Send + 'static, + >( + &self, + func:T, + ) { + let this = self.pin(); + this.begin_foreground_job(); + tokio::spawn( + TURBO_TASKS + .scope(this.clone(), async move { + if !this.stopped.load(Ordering::Acquire) { + func(this.clone()).await; + } + this.finish_foreground_job(); + }) + .in_current_span(), + ); + } + + fn finish_current_task_state(&self) -> bool { + let (stateful, tasks) = CURRENT_TASK_STATE.with(|cell| { + let CurrentTaskState { tasks_to_notify, stateful } = &mut *cell.borrow_mut(); + (*stateful, take(tasks_to_notify)) + }); + + if !tasks.is_empty() { + self.backend.invalidate_tasks(&tasks, self); + } + stateful + } + + pub fn backend(&self) -> &B { &self.backend } +} + +impl TurboTasksCallApi for TurboTasks { + fn dynamic_call(&self, func:FunctionId, inputs:Vec) -> RawVc { + self.dynamic_call(func, inputs) + } + + fn native_call(&self, func:FunctionId, inputs:Vec) -> RawVc { + self.native_call(func, inputs) + } + + fn trait_call( + &self, + trait_type:TraitTypeId, + trait_fn_name:Cow<'static, str>, + inputs:Vec, + ) -> RawVc { + self.trait_call(trait_type, trait_fn_name, inputs) + } + + #[track_caller] + fn run_once( + &self, + future:Pin> + Send + 'static>>, + ) -> TaskId { + self.spawn_once_task(async move { + future.await?; + Ok(Completion::new()) + }) + } + + #[track_caller] + fn run_once_with_reason( + &self, + reason:StaticOrArc, + future:Pin> + Send + 'static>>, + ) -> TaskId { + { + let (_, reason_set) = &mut *self.aggregated_update.lock().unwrap(); + reason_set.insert(reason); + } + self.spawn_once_task(async move { + future.await?; + Ok(Completion::new()) + }) + } + + #[track_caller] + fn run_once_process( + &self, + future:Pin> + Send + 'static>>, + ) -> TaskId { + let this = self.pin(); + self.spawn_once_task(async move { + this.finish_primary_job(); + future.await?; + this.begin_primary_job(); + Ok(Completion::new()) + }) + } +} + +impl TurboTasksApi for TurboTasks { + fn pin(&self) -> Arc { self.pin() } + + #[instrument(level = Level::INFO, skip_all, name = "invalidate")] + fn invalidate(&self, task:TaskId) { self.backend.invalidate_task(task, self); } + + #[instrument(level = Level::INFO, skip_all, name = "invalidate", fields(name = display(&reason)))] + fn invalidate_with_reason(&self, task:TaskId, reason:StaticOrArc) { + { + let (_, reason_set) = &mut *self.aggregated_update.lock().unwrap(); + reason_set.insert(reason); + } + self.backend.invalidate_task(task, self); + } + + fn notify_scheduled_tasks(&self) { + let _ = CURRENT_TASK_STATE.try_with(|cell| { + let tasks = { + let CurrentTaskState { tasks_to_notify, .. } = &mut *cell.borrow_mut(); + take(tasks_to_notify) + }; + if tasks.is_empty() { + return; + } + self.backend.invalidate_tasks(&tasks, self); + }); + } + + fn try_read_task_output( + &self, + task:TaskId, + strongly_consistent:bool, + ) -> Result> { + self.backend.try_read_task_output( + task, + current_task("reading Vcs"), + strongly_consistent, + self, + ) + } + + fn try_read_task_output_untracked( + &self, + task:TaskId, + strongly_consistent:bool, + ) -> Result> { + self.backend.try_read_task_output_untracked(task, strongly_consistent, self) + } + + fn try_read_task_cell( + &self, + task:TaskId, + index:CellId, + ) -> Result> { + self.backend.try_read_task_cell(task, index, current_task("reading Vcs"), self) + } + + fn try_read_task_cell_untracked( + &self, + task:TaskId, + index:CellId, + ) -> Result> { + self.backend.try_read_task_cell_untracked(task, index, self) + } + + fn try_read_own_task_cell_untracked( + &self, + current_task:TaskId, + index:CellId, + ) -> Result { + self.backend.try_read_own_task_cell_untracked(current_task, index, self) + } + + fn read_task_collectibles(&self, task:TaskId, trait_id:TraitTypeId) -> AutoMap { + self.backend.read_task_collectibles( + task, + trait_id, + current_task("reading collectibles"), + self, + ) + } + + fn emit_collectible(&self, trait_type:TraitTypeId, collectible:RawVc) { + self.backend.emit_collectible( + trait_type, + collectible, + current_task("emitting collectible"), + self, + ); + } + + fn unemit_collectible(&self, trait_type:TraitTypeId, collectible:RawVc, count:u32) { + self.backend.unemit_collectible( + trait_type, + collectible, + count, + current_task("emitting collectible"), + self, + ); + } + + fn unemit_collectibles(&self, trait_type:TraitTypeId, collectibles:&AutoMap) { + for (&collectible, &count) in collectibles { + if count > 0 { + self.backend.unemit_collectible( + trait_type, + collectible, + count as u32, + current_task("emitting collectible"), + self, + ); + } + } + } + + fn read_own_task_cell(&self, task:TaskId, index:CellId) -> Result { + // INVALIDATION: don't need to track a dependency to itself + self.try_read_own_task_cell_untracked(task, index) + } + + fn update_own_task_cell(&self, task:TaskId, index:CellId, content:CellContent) { + self.backend.update_task_cell(task, index, content, self); + } + + fn connect_task(&self, task:TaskId) { + self.backend.connect_task(task, current_task("connecting task"), self); + } + + fn mark_own_task_as_finished(&self, task:TaskId) { + self.backend.mark_own_task_as_finished(task, self); + } + + fn detached( + &self, + f:Pin> + Send + 'static>>, + ) -> Pin> + Send + 'static>> { + let current_task_id = CURRENT_TASK_ID.get(); + Box::pin( + TURBO_TASKS.scope( + turbo_tasks(), + CURRENT_TASK_ID.scope( + current_task_id, + CELL_COUNTERS.scope( + Default::default(), + self.backend.execution_scope(current_task_id, f), + ), + ), + ), + ) + } +} + +impl TurboTasksBackendApi for TurboTasks { + fn pin(&self) -> Arc> { self.pin() } + + fn backend(&self) -> &B { &self.backend } + + #[track_caller] + fn schedule_backend_background_job(&self, id:BackendJobId) { + self.schedule_background_job(move |this| { + async move { + this.backend.run_backend_job(id, &*this).await; + } + }) + } + + #[track_caller] + fn schedule_backend_foreground_job(&self, id:BackendJobId) { + self.schedule_foreground_job(move |this| { + async move { + this.backend.run_backend_job(id, &*this).await; + } + }) + } + + fn try_foreground_done(&self) -> Result<(), EventListener> { + if self.currently_scheduled_foreground_jobs.load(Ordering::Acquire) == 0 { + return Ok(()); + } + let listener = self.event_foreground.listen(); + if self.currently_scheduled_foreground_jobs.load(Ordering::Acquire) == 0 { + return Ok(()); + } + Err(listener) + } + + fn wait_foreground_done_excluding_own<'a>( + &'a self, + ) -> Option + Send + 'a>>> { + if self.currently_scheduled_foreground_jobs.load(Ordering::Acquire) == 0 { + return None; + } + Some(Box::pin(async { + self.finish_foreground_job(); + self.wait_foreground_done().await; + self.begin_foreground_job(); + })) + } + + /// Enqueues tasks for notification of changed dependencies. This will + /// eventually call `dependent_cell_updated()` on all tasks. + fn schedule_notify_tasks(&self, tasks:&[TaskId]) { + let result = CURRENT_TASK_STATE.try_with(|cell| { + let CurrentTaskState { tasks_to_notify, .. } = &mut *cell.borrow_mut(); + tasks_to_notify.extend(tasks.iter()); + }); + if result.is_err() { + let _guard = trace_span!("schedule_notify_tasks", count = tasks.len()).entered(); + self.backend.invalidate_tasks(tasks, self); + } + } + + /// Enqueues tasks for notification of changed dependencies. This will + /// eventually call `dependent_cell_updated()` on all tasks. + fn schedule_notify_tasks_set(&self, tasks:&TaskIdSet) { + let result = CURRENT_TASK_STATE.try_with(|cell| { + let CurrentTaskState { tasks_to_notify, .. } = &mut *cell.borrow_mut(); + tasks_to_notify.extend(tasks.iter()); + }); + if result.is_err() { + let _guard = trace_span!("schedule_notify_tasks_set", count = tasks.len()).entered(); + self.backend.invalidate_tasks_set(tasks, self); + }; + } + + #[track_caller] + fn schedule(&self, task:TaskId) { self.schedule(task) } + + fn program_duration_until(&self, instant:Instant) -> Duration { instant - self.program_start } +} + +impl TaskIdProvider for TurboTasks { + fn get_fresh_task_id(&self) -> Unused { + // Safety: This is a fresh id from the factory + unsafe { Unused::new_unchecked(self.task_id_factory.get()) } + } + + fn reuse_task_id(&self, id:Unused) { unsafe { self.task_id_factory.reuse(id.into()) } } +} + +pub(crate) fn current_task(from:&str) -> TaskId { + match CURRENT_TASK_ID.try_with(|id| *id) { + Ok(id) => id, + Err(_) => panic!("{} can only be used in the context of turbo_tasks task execution", from), + } +} + +pub struct Invalidator { + task:TaskId, + turbo_tasks:Weak, + handle:Handle, +} + +impl Hash for Invalidator { + fn hash(&self, state:&mut H) { self.task.hash(state); } +} + +impl PartialEq for Invalidator { + fn eq(&self, other:&Self) -> bool { self.task == other.task } +} + +impl Eq for Invalidator {} + +impl Invalidator { + pub fn invalidate(self) { + let Invalidator { task, turbo_tasks, handle } = self; + let _ = handle.enter(); + if let Some(turbo_tasks) = turbo_tasks.upgrade() { + turbo_tasks.invalidate(task); + } + } + + pub fn invalidate_with_reason(self, reason:T) { + let Invalidator { task, turbo_tasks, handle } = self; + let _ = handle.enter(); + if let Some(turbo_tasks) = turbo_tasks.upgrade() { + turbo_tasks.invalidate_with_reason( + task, + (Arc::new(reason) as Arc).into(), + ); + } + } + + pub fn invalidate_with_static_reason(self, reason:&'static T) { + let Invalidator { task, turbo_tasks, handle } = self; + let _ = handle.enter(); + if let Some(turbo_tasks) = turbo_tasks.upgrade() { + turbo_tasks + .invalidate_with_reason(task, (reason as &'static dyn InvalidationReason).into()); + } + } +} + +impl TraceRawVcs for Invalidator { + fn trace_raw_vcs(&self, _context:&mut crate::trace::TraceRawVcsContext) { + // nothing here + } +} + +impl Serialize for Invalidator { + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + serializer.serialize_newtype_struct("Invalidator", &self.task) + } +} + +impl<'de> Deserialize<'de> for Invalidator { + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + struct V; + + impl<'de> Visitor<'de> for V { + type Value = Invalidator; + + fn expecting(&self, f:&mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "an Invalidator") + } + + fn visit_newtype_struct(self, deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + Ok(Invalidator { + task:TaskId::deserialize(deserializer)?, + turbo_tasks:weak_turbo_tasks(), + handle:tokio::runtime::Handle::current(), + }) + } + } + deserializer.deserialize_newtype_struct("Invalidator", V) + } +} + +pub async fn run_once( + tt:Arc, + future:impl Future> + Send + 'static, +) -> Result { + let (tx, rx) = tokio::sync::oneshot::channel(); + + let task_id = tt.run_once(Box::pin(async move { + let result = future.await?; + tx.send(result).map_err(|_| anyhow!("unable to send result"))?; + Ok(()) + })); + + // INVALIDATION: A Once task will never invalidate, therefore we don't need to + // track a dependency + let raw_result = read_task_output_untracked(&*tt, task_id, false).await?; + raw_result.into_read_untracked_with_turbo_tasks::(&*tt).await?; + + Ok(rx.await?) +} + +pub async fn run_once_with_reason( + tt:Arc, + reason:impl InvalidationReason, + future:impl Future> + Send + 'static, +) -> Result { + let (tx, rx) = tokio::sync::oneshot::channel(); + + let task_id = tt.run_once_with_reason( + (Arc::new(reason) as Arc).into(), + Box::pin(async move { + let result = future.await?; + tx.send(result).map_err(|_| anyhow!("unable to send result"))?; + Ok(()) + }), + ); + + // INVALIDATION: A Once task will never invalidate, therefore we don't need to + // track a dependency + let raw_result = read_task_output_untracked(&*tt, task_id, false).await?; + raw_result.into_read_untracked_with_turbo_tasks::(&*tt).await?; + + Ok(rx.await?) +} + +/// see [TurboTasks] `dynamic_call` +pub fn dynamic_call(func:FunctionId, inputs:Vec) -> RawVc { + with_turbo_tasks(|tt| tt.dynamic_call(func, inputs)) +} + +/// see [TurboTasks] `trait_call` +pub fn trait_call( + trait_type:TraitTypeId, + trait_fn_name:Cow<'static, str>, + inputs:Vec, +) -> RawVc { + with_turbo_tasks(|tt| tt.trait_call(trait_type, trait_fn_name, inputs)) +} + +pub fn turbo_tasks() -> Arc { TURBO_TASKS.with(|arc| arc.clone()) } + +pub fn with_turbo_tasks(func:impl FnOnce(&Arc) -> T) -> T { + TURBO_TASKS.with(|arc| func(arc)) +} + +pub fn weak_turbo_tasks() -> Weak { TURBO_TASKS.with(Arc::downgrade) } + +pub fn with_turbo_tasks_for_testing( + tt:Arc, + current_task:TaskId, + f:impl Future, +) -> impl Future { + TURBO_TASKS.scope( + tt, + CURRENT_TASK_ID.scope(current_task, CELL_COUNTERS.scope(Default::default(), f)), + ) +} + +/// Spawns the given future within the context of the current task. +/// +/// Beware: this method is not safe to use in production code. It is only +/// intended for use in tests and for debugging purposes. +pub fn spawn_detached(f:impl Future> + Send + 'static) { + tokio::spawn(turbo_tasks().detached(Box::pin(f.in_current_span()))); +} + +pub fn current_task_for_testing() -> TaskId { CURRENT_TASK_ID.with(|id| *id) } + +/// Get an [Invalidator] that can be used to invalidate the current [Task] +/// based on external events. +pub fn get_invalidator() -> Invalidator { + let handle = Handle::current(); + Invalidator { + task:current_task("turbo_tasks::get_invalidator()"), + turbo_tasks:weak_turbo_tasks(), + handle, + } +} + +/// Marks the current task as finished. This excludes it from waiting for +/// strongly consistency. +pub fn mark_finished() { + with_turbo_tasks(|tt| { + tt.mark_own_task_as_finished(current_task("turbo_tasks::mark_finished()")) + }); +} + +/// Marks the current task as stateful. This prevents the tasks from being +/// dropped without persisting the state. +pub fn mark_stateful() { + CURRENT_TASK_STATE.with(|cell| { + let CurrentTaskState { stateful, .. } = &mut *cell.borrow_mut(); + *stateful = true; + }) +} + +pub fn prevent_gc() { mark_stateful(); } + +/// Notifies scheduled tasks for execution. +pub fn notify_scheduled_tasks() { with_turbo_tasks(|tt| tt.notify_scheduled_tasks()) } + +pub fn emit(collectible:Vc) { + with_turbo_tasks(|tt| tt.emit_collectible(T::get_trait_type_id(), collectible.node)) +} + +pub async fn spawn_blocking(func:impl FnOnce() -> T + Send + 'static) -> T { + let span = trace_span!("blocking operation").or_current(); + let (result, duration, alloc_info) = tokio::task::spawn_blocking(|| { + let _guard = span.entered(); + let start = Instant::now(); + let start_allocations = TurboMalloc::allocation_counters(); + let r = func(); + (r, start.elapsed(), start_allocations.until_now()) + }) + .await + .unwrap(); + capture_future::add_duration(duration); + capture_future::add_allocation_info(alloc_info); + result +} + +pub fn spawn_thread(func:impl FnOnce() + Send + 'static) { + let handle = Handle::current(); + let span = info_span!("thread").or_current(); + thread::spawn(move || { + let span = span.entered(); + let guard = handle.enter(); + func(); + drop(guard); + drop(span); + }); +} + +pub(crate) async fn read_task_output( + this:&dyn TurboTasksApi, + id:TaskId, + strongly_consistent:bool, +) -> Result { + loop { + match this.try_read_task_output(id, strongly_consistent)? { + Ok(result) => return Ok(result), + Err(listener) => listener.await, + } + } +} + +/// INVALIDATION: Be careful with this, it will not track dependencies, so +/// using it could break cache invalidation. +pub(crate) async fn read_task_output_untracked( + this:&dyn TurboTasksApi, + id:TaskId, + strongly_consistent:bool, +) -> Result { + loop { + match this.try_read_task_output_untracked(id, strongly_consistent)? { + Ok(result) => return Ok(result), + Err(listener) => listener.await, + } + } +} + +pub(crate) async fn read_task_cell( + this:&dyn TurboTasksApi, + id:TaskId, + index:CellId, +) -> Result { + loop { + match this.try_read_task_cell(id, index)? { + Ok(result) => return Ok(result), + Err(listener) => listener.await, + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub struct CurrentCellRef { + current_task:TaskId, + index:CellId, +} + +impl CurrentCellRef { + pub fn conditional_update_shared) -> Option>( + &self, + functor:F, + ) { + let tt = turbo_tasks(); + let content = tt + .read_own_task_cell(self.current_task, self.index) + .ok() + .and_then(|v| v.try_cast::()); + let update = + functor(content.as_deref().map(|content| { + <::Read as VcRead>::target_to_value_ref(content) + })); + if let Some(update) = update { + tt.update_own_task_cell( + self.current_task, + self.index, + CellContent(Some(SharedReference(Some(self.index.type_id), Arc::new(update)))), + ) + } + } + + pub fn compare_and_update_shared(&self, new_content:T) { + self.conditional_update_shared(|old_content| { + if let Some(old_content) = old_content { + if PartialEq::eq(&new_content, old_content) { + return None; + } + } + Some(new_content) + }); + } + + pub fn update_shared(&self, new_content:T) { + let tt = turbo_tasks(); + tt.update_own_task_cell( + self.current_task, + self.index, + CellContent(Some(SharedReference(Some(self.index.type_id), Arc::new(new_content)))), + ) + } + + pub fn update_shared_reference(&self, shared_ref:SharedReference) { + let tt = turbo_tasks(); + let content = tt.read_own_task_cell(self.current_task, self.index).ok(); + let update = if let Some(CellContent(Some(content))) = content { + content != shared_ref + } else { + true + }; + if update { + tt.update_own_task_cell(self.current_task, self.index, CellContent(Some(shared_ref))) + } + } +} + +impl From for RawVc { + fn from(cell:CurrentCellRef) -> Self { RawVc::TaskCell(cell.current_task, cell.index) } +} + +pub fn find_cell_by_type(ty:ValueTypeId) -> CurrentCellRef { + CELL_COUNTERS.with(|cell| { + let current_task = current_task("celling turbo_tasks values"); + let mut map = cell.borrow_mut(); + let current_index = map.entry(ty).or_default(); + let index = *current_index; + *current_index += 1; + CurrentCellRef { current_task, index:CellId { type_id:ty, index } } + }) +} diff --git a/crates/turbo-tasks/Source/native_function.rs b/crates/turbo-tasks/Source/native_function.rs new file mode 100644 index 0000000000000..305a6e94de880 --- /dev/null +++ b/crates/turbo-tasks/Source/native_function.rs @@ -0,0 +1,87 @@ +use std::{fmt::Debug, hash::Hash}; + +use tracing::Span; + +use crate::{ + ConcreteTaskInput, + registry::register_function, + task::{IntoTaskFn, TaskFn, function::NativeTaskFn}, + util::SharedError, + {self as turbo_tasks}, +}; + +/// A native (rust) turbo-tasks function. It's used internally by +/// `#[turbo_tasks::function]`. +#[turbo_tasks::value(cell = "new", serialization = "none", eq = "manual")] +pub struct NativeFunction { + /// A readable name of the function that is used to reporting purposes. + pub name:String, + /// The functor that creates a functor from inputs. The inner functor + /// handles the task execution. + #[turbo_tasks(debug_ignore, trace_ignore)] + pub implementation:Box, +} + +impl Debug for NativeFunction { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("NativeFunction") + .field("name", &self.name) + .finish_non_exhaustive() + } +} + +impl NativeFunction { + pub fn new(name:String, implementation:I) -> Self + where + I: IntoTaskFn, { + Self { name, implementation:Box::new(implementation.into_task_fn()) } + } + + /// Creates a functor for execution from a fixed set of inputs. + pub fn bind(&'static self, inputs:&[ConcreteTaskInput]) -> NativeTaskFn { + match (self.implementation).functor(inputs) { + Ok(functor) => functor, + Err(err) => { + let err = SharedError::new(err); + Box::new(move || { + let err = err.clone(); + Box::pin(async { Err(err.into()) }) + }) + }, + } + } + + pub fn span(&'static self) -> Span { + tracing::trace_span!("turbo_tasks::function", name = self.name.as_str()) + } + + pub fn resolve_span(&'static self) -> Span { + tracing::trace_span!("turbo_tasks::resolve_call", name = self.name.as_str()) + } + + pub fn register(&'static self, global_name:&'static str) { + register_function(global_name, self); + } +} + +impl PartialEq for &'static NativeFunction { + fn eq(&self, other:&Self) -> bool { std::ptr::eq(*self, *other) } +} + +impl Eq for &'static NativeFunction {} + +impl Hash for &'static NativeFunction { + fn hash(&self, state:&mut H) { + Hash::hash(&(*self as *const NativeFunction), state); + } +} + +impl PartialOrd for &'static NativeFunction { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for &'static NativeFunction { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + Ord::cmp(&(*self as *const NativeFunction), &(*other as *const NativeFunction)) + } +} diff --git a/crates/turbo-tasks/Source/no_move_vec.rs b/crates/turbo-tasks/Source/no_move_vec.rs new file mode 100644 index 0000000000000..4f1e8b7e46153 --- /dev/null +++ b/crates/turbo-tasks/Source/no_move_vec.rs @@ -0,0 +1,301 @@ +use std::{ + ptr::null_mut, + slice::from_raw_parts_mut, + sync::{ + Mutex, + atomic::{AtomicPtr, Ordering}, + }, +}; + +const BUCKETS:usize = (usize::BITS + 1) as usize; + +/// An `Option`-like type that guarantees that a fully zeroed value is a valid +/// `None` variant. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(u8)] +enum COption { + // TODO(alexkirsz) We need a way to guarantee that a fully zeroed value is a + // valid `None` variant. This is theoretically possible when the wrapped + // type has no valid value that can be represented by all zeros, but there + // is no way to enforce this at the type level. For now, we just use a custom + // option type with explicit discriminant for the `None` variant. + // The issue with this implementation is that it disables niche optimization. + None = 0, + Some(T), +} + +impl Default for COption { + fn default() -> Self { Self::None } +} + +impl COption { + /// Returns a slice of the given size filled with the `None` variant. + fn new_none_slice(size:usize) -> Box<[Self]> { + let slice = Box::<[COption]>::new_zeroed_slice(size); + // Safety: + // We know that a zeroed COption is a valid COption::None value. + unsafe { slice.assume_init() } + } + + /// Returns a reference to the contained value, or `None` if it is `None`. + fn as_option_ref(&self) -> Option<&T> { + match self { + COption::None => None, + COption::Some(t) => Some(t), + } + } + + /// Takes the value out of the option, leaving a `None` in its place. + fn take(&mut self) -> Option { + match std::mem::take(self) { + COption::None => None, + COption::Some(t) => Some(t), + } + } +} + +impl COption { + /// Returns a slice of the given size filled with the `Some` variant and + /// filled with default values. + fn new_default_slice(size:usize) -> Box<[Self]> { + (0..size) + .map(|_| COption::Some(Default::default())) + .collect::>() + .into_boxed_slice() + } +} + +pub struct NoMoveVec { + buckets:[(AtomicPtr>, Mutex<()>); BUCKETS], +} + +fn get_bucket_index(idx:usize) -> u32 { + (usize::BITS - idx.leading_zeros()).saturating_sub(INITIAL_CAPACITY_BITS) +} + +fn get_bucket_size(bucket_index:u32) -> usize { + if bucket_index != 0 { + 1 << (bucket_index + INITIAL_CAPACITY_BITS - 1) + } else { + 1 << INITIAL_CAPACITY_BITS + } +} + +fn get_index_in_bucket(idx:usize, bucket_index:u32) -> usize { + if bucket_index != 0 { + idx ^ (1 << (bucket_index + INITIAL_CAPACITY_BITS - 1)) + } else { + idx + } +} + +/// Allocates a new bucket of `COption`s, all initialized to `None`. +fn allocate_bucket(bucket_index:u32) -> *mut COption { + let size = get_bucket_size::(bucket_index); + let slice = COption::::new_none_slice(size); + Box::into_raw(slice) as *mut COption +} + +/// Allocates a new bucket of `COption`s, all initialized to `None`. +fn allocate_default_bucket( + bucket_index:u32, +) -> *mut COption { + let size = get_bucket_size::(bucket_index); + let slice = COption::::new_default_slice(size); + Box::into_raw(slice) as *mut COption +} + +impl Default for NoMoveVec { + fn default() -> Self { Self::new() } +} + +impl NoMoveVec { + pub fn new() -> Self { + let mut buckets = [null_mut(); BUCKETS]; + buckets[0] = allocate_bucket::(0); + let buckets = buckets.map(|p| (AtomicPtr::new(p), Mutex::new(()))); + NoMoveVec { buckets } + } + + pub fn get(&self, idx:usize) -> Option<&T> { + let bucket_idx = get_bucket_index::(idx); + let bucket_ptr = unsafe { self.buckets.get_unchecked(bucket_idx as usize) } + .0 + .load(Ordering::Acquire); + if bucket_ptr.is_null() { + return None; + } + let index = get_index_in_bucket::(idx, bucket_idx); + unsafe { &*bucket_ptr.add(index) }.as_option_ref() + } + + /// # Safety + /// There must not be a concurrent operation to this idx + pub unsafe fn take(&self, idx:usize) -> Option { + let bucket_idx = get_bucket_index::(idx); + let bucket = unsafe { self.buckets.get_unchecked(bucket_idx as usize) }; + let bucket_ptr = bucket.0.load(Ordering::Acquire); + if bucket_ptr.is_null() { + return None; + } + let index = get_index_in_bucket::(idx, bucket_idx); + let item = unsafe { &mut *bucket_ptr.add(index) }; + let item = item.take(); + // To sync with any acquire load of the bucket ptr + bucket.0.store(bucket_ptr, Ordering::Release); + item + } + + /// # Safety + /// There must not be a concurrent operation to this idx + pub unsafe fn insert(&self, idx:usize, value:T) -> &T { + let bucket_idx = get_bucket_index::(idx); + let bucket = unsafe { self.buckets.get_unchecked(bucket_idx as usize) }; + // SAFETY: This is safe to be relaxed as the bucket will never become null + // again. We perform a acquire load when it's null. + let mut bucket_ptr = bucket.0.load(Ordering::Relaxed); + if bucket_ptr.is_null() { + bucket_ptr = bucket.0.load(Ordering::Acquire); + if bucket_ptr.is_null() { + let lock = bucket.1.lock(); + let guarded_bucket_ptr = bucket.0.load(Ordering::Acquire); + if guarded_bucket_ptr.is_null() { + let new_bucket = allocate_bucket::(bucket_idx); + bucket_ptr = match bucket.0.compare_exchange( + null_mut(), + new_bucket, + Ordering::AcqRel, + Ordering::Relaxed, + ) { + Ok(_) => new_bucket, + Err(current_bucket) => { + drop(unsafe { Box::from_raw(new_bucket) }); + current_bucket + }, + }; + drop(lock); + } else { + bucket_ptr = guarded_bucket_ptr; + } + } + } + let index = get_index_in_bucket::(idx, bucket_idx); + let item = unsafe { &mut *bucket_ptr.add(index) }; + *item = COption::Some(value); + // To sync with any acquire load of the bucket ptr + bucket.0.store(bucket_ptr, Ordering::Release); + item.as_option_ref().unwrap() + } + + /// # Safety + /// There must not be a concurrent operation to this idx + pub unsafe fn remove(&self, idx:usize) { + let bucket_idx = get_bucket_index::(idx); + let bucket = unsafe { self.buckets.get_unchecked(bucket_idx as usize) }; + let bucket_ptr = bucket.0.load(Ordering::Acquire); + if bucket_ptr.is_null() { + return; + } + let index = get_index_in_bucket::(idx, bucket_idx); + let item = unsafe { &mut *bucket_ptr.add(index) }; + *item = COption::None; + // To sync with any acquire load of the bucket ptr + bucket.0.store(bucket_ptr, Ordering::Release); + } +} + +impl NoMoveVec { + pub fn new_init_default() -> Self { + let mut buckets = [null_mut(); BUCKETS]; + buckets[0] = allocate_default_bucket::(0); + let buckets = buckets.map(|p| (AtomicPtr::new(p), Mutex::new(()))); + NoMoveVec { buckets } + } + + pub fn get_init_default(&self, idx:usize) -> &T { + let bucket_idx = get_bucket_index::(idx); + let bucket = unsafe { self.buckets.get_unchecked(bucket_idx as usize) }; + // SAFETY: This is safe to be relaxed as the bucket will never become null + // again. We perform a acquire load when it's null. + let mut bucket_ptr = bucket.0.load(Ordering::Relaxed); + if bucket_ptr.is_null() { + bucket_ptr = bucket.0.load(Ordering::Acquire); + if bucket_ptr.is_null() { + let lock = bucket.1.lock(); + let guarded_bucket_ptr = bucket.0.load(Ordering::Acquire); + if guarded_bucket_ptr.is_null() { + let new_bucket = + allocate_default_bucket::(bucket_idx); + bucket_ptr = match bucket.0.compare_exchange( + null_mut(), + new_bucket, + Ordering::AcqRel, + Ordering::Relaxed, + ) { + Ok(_) => new_bucket, + Err(current_bucket) => { + drop(unsafe { Box::from_raw(new_bucket) }); + current_bucket + }, + }; + drop(lock); + } else { + bucket_ptr = guarded_bucket_ptr; + } + } + } + let index = get_index_in_bucket::(idx, bucket_idx); + let value = unsafe { &*bucket_ptr.add(index) }.as_option_ref(); + value.expect("get_init_default must not be combined with normal insert") + } +} + +impl Drop for NoMoveVec { + fn drop(&mut self) { + for (bucket_index, (bucket, _)) in self.buckets.iter_mut().enumerate() { + if bucket_index < (usize::BITS + 1 - INITIAL_CAPACITY_BITS) as usize { + let bucket_size = get_bucket_size::(bucket_index as u32); + let bucket_ptr = *bucket.get_mut(); + + if !bucket_ptr.is_null() { + drop(unsafe { Box::from_raw(from_raw_parts_mut(bucket_ptr, bucket_size)) }); + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::NoMoveVec; + + #[test] + fn basic_operations() { + let v = NoMoveVec::<(usize, usize)>::new(); + assert_eq!(v.get(0), None); + assert_eq!(v.get(1), None); + assert_eq!(v.get(8), None); + assert_eq!(v.get(9), None); + assert_eq!(v.get(15), None); + assert_eq!(v.get(16), None); + assert_eq!(v.get(100), None); + assert_eq!(v.get(1000), None); + + for i in 0..1000 { + unsafe { + v.insert(i, (i, i)); + } + assert_eq!(v.get(i), Some(&(i, i))); + } + for i in 0..1000 { + assert_eq!(v.get(i), Some(&(i, i))); + } + assert_eq!(v.get(1001), None); + + unsafe { + v.insert(1000000, (0, 0)); + } + assert_eq!(v.get(1000000), Some(&(0, 0))); + assert_eq!(v.get(10000), None); + } +} diff --git a/crates/turbo-tasks/Source/once_map.rs b/crates/turbo-tasks/Source/once_map.rs new file mode 100644 index 0000000000000..ebdf478ac2ef5 --- /dev/null +++ b/crates/turbo-tasks/Source/once_map.rs @@ -0,0 +1,112 @@ +use std::{ + hash::Hash, + sync::{Arc, Mutex}, +}; + +use dashmap::{DashMap, mapref::entry::Entry}; + +pub struct OnceConcurrentlyMap { + inner:DashMap<&'static K, Arc>>>, +} + +impl Default for OnceConcurrentlyMap { + fn default() -> Self { Self::new() } +} + +impl OnceConcurrentlyMap { + pub fn new() -> Self { Self { inner:DashMap::new() } } + + pub fn action(&self, key:&K, func:impl FnOnce() -> V) -> V { + let temp = TemporarilyInserted { inner:&self.inner, key }; + let mutex = match temp.entry() { + Entry::Occupied(e) => e.get().clone(), + Entry::Vacant(e) => e.insert(Arc::new(Mutex::new(None))).clone(), + }; + let mut guard = mutex.lock().unwrap(); + if let Some(value) = &*guard { + // Yeah, somebody else already did it for us + return value.clone(); + } + // We are the one responsible for computing + let value = func(); + *guard = Some(value.clone()); + drop(guard); + drop(temp); + value + } +} + +struct TemporarilyInserted<'a, K:'static + Hash + Eq + Ord + Send + Sync, V:Send + Sync> { + inner:&'a DashMap<&'static K, V>, + key:&'a K, +} + +impl<'a, K:Hash + Eq + Ord + Send + Sync, V:Send + Sync> TemporarilyInserted<'a, K, V> { + fn entry(&self) -> Entry<'a, &'static K, V> { + // SAFETY: We remove the value again after this function is done + let static_key:&'static K = unsafe { std::mem::transmute(self.key) }; + self.inner.entry(static_key) + } +} + +impl<'a, K:Hash + Eq + Ord + Send + Sync, V:Send + Sync> Drop for TemporarilyInserted<'a, K, V> { + fn drop(&mut self) { + let static_key:&'static K = unsafe { std::mem::transmute(self.key) }; + self.inner.remove(&static_key); + } +} + +pub struct SafeOnceConcurrentlyMap< + K:Clone + Hash + Eq + Ord + Send + Sync + 'static, + V:Clone + Send + Sync, +> { + inner:DashMap>>>, +} + +impl Default + for SafeOnceConcurrentlyMap +{ + fn default() -> Self { Self::new() } +} + +impl SafeOnceConcurrentlyMap { + pub fn new() -> Self { Self { inner:DashMap::new() } } + + pub fn action(&self, key:&K, func:impl FnOnce() -> V) -> V { + let temp = SafeTemporarilyInserted { inner:&self.inner, key }; + let mutex = match temp.entry() { + Entry::Occupied(e) => e.get().clone(), + Entry::Vacant(e) => e.insert(Arc::new(Mutex::new(None))).clone(), + }; + let mut guard = mutex.lock().unwrap(); + if let Some(value) = &*guard { + // Yeah, somebody else already did it for us + return value.clone(); + } + // We are the one responsible for computing + let value = func(); + *guard = Some(value.clone()); + drop(guard); + drop(temp); + value + } +} + +struct SafeTemporarilyInserted<'a, K:'static + Clone + Hash + Eq + Ord + Send + Sync, V:Send + Sync> +{ + inner:&'a DashMap, + key:&'a K, +} + +impl<'a, K:Clone + Hash + Eq + Ord + Send + Sync, V:Send + Sync> SafeTemporarilyInserted<'a, K, V> { + fn entry(&self) -> Entry<'_, K, V> { + // SAFETY: We remove the value again after this function is done + self.inner.entry(self.key.clone()) + } +} + +impl<'a, K:Clone + Hash + Eq + Ord + Send + Sync, V:Send + Sync> Drop + for SafeTemporarilyInserted<'a, K, V> +{ + fn drop(&mut self) { self.inner.remove(self.key); } +} diff --git a/crates/turbo-tasks/Source/persisted_graph.rs b/crates/turbo-tasks/Source/persisted_graph.rs new file mode 100644 index 0000000000000..a79ef7d0c33fa --- /dev/null +++ b/crates/turbo-tasks/Source/persisted_graph.rs @@ -0,0 +1,314 @@ +use anyhow::Result; +use serde::{Deserialize, Serialize}; + +use crate::{ + CellId, + RawVc, + TaskId, + backend::{CellContent, PersistentTaskType}, +}; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum TaskCell { + Content(CellContent), + NeedComputation, +} + +impl Default for TaskCell { + fn default() -> Self { TaskCell::Content(CellContent(None)) } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct TaskData { + pub children:Vec, + pub dependencies:Vec, + pub cells:Vec<(CellId, TaskCell)>, + pub output:RawVc, +} +pub struct ReadTaskState { + pub clean:bool, + pub keeps_external_active:bool, +} + +pub struct PersistTaskState { + pub externally_active:bool, +} + +// There are 4 kinds of task: +// +// (A) A task that exists only in memory. +// (B) A task that exists in persistent graph and in memory (either "store" or +// "read" has been called) (C) A task that exists only in persistent graph. +// +// Parent-child relationships: +// +// (A) as child: active_parents is tracked only in memory. +// (B) as child: active_parents is tracked in memory and either as +// internal_active_parents or external_active_parents in the persisted graph. +// (C) as child: either as internal_active_parents or external_active_parents in +// the persisted graph. +// +// (A) as parent: It will use external_active_parents for (B) or (C) as child. +// update_active_parents() is used to modify the external_active_parents count. +// (B) as parent: It will use internal_active_parents for (B) or (C) as child. +// compute_active() returns the changes needed for (A) or (C) as child +// (C) as parent: It will use internal_active_parents for (B) or (C) as child. +// compute_active() returns the changes needed for (A) or (C) as child +// +// (A) as child of (B) or (C): active count tracked as external_active_children, +// have task ids assigned in persistent graph +// + +#[derive(Debug)] +pub struct ActivateResult { + /// Keeps the external version of the task active + pub keeps_external_active:bool, + + /// Task doesn't live in the persisted graph but + /// should be track externally + pub external:bool, + + /// Task is dirty and need to be scheduled for execution + pub dirty:bool, + + /// Further tasks that need to be activated that + /// didn't fit into that batch + pub more_tasks_to_activate:Vec, +} + +#[derive(Debug)] +pub struct PersistResult { + /// Tasks that need to be activated + pub tasks_to_activate:Vec, + + /// Tasks that need to be deactivated + pub tasks_to_deactivate:Vec, +} + +#[derive(Debug)] +pub struct DeactivateResult { + /// Further tasks that need to be deactivated that + /// didn't fit into that batch + pub more_tasks_to_deactivate:Vec, +} + +pub trait PersistedGraph: Sync + Send { + /// read task data and state for a specific task. + fn read( + &self, + task:TaskId, + api:&dyn PersistedGraphApi, + ) -> Result>; + + /// lookup all cache entries for a partial task type + /// returns true if all cache entries has been initialized + /// returns false if that were too many + fn lookup( + &self, + partial_task_type:&PersistentTaskType, + api:&dyn PersistedGraphApi, + ) -> Result; + + /// lookup one cache entry + fn lookup_one( + &self, + task_type:&PersistentTaskType, + api:&dyn PersistedGraphApi, + ) -> Result>; + + /// checks if a task is persisted + fn is_persisted(&self, task:TaskId, api:&dyn PersistedGraphApi) -> Result; + + /// store a completed task into the persisted graph + /// together with dependencies, children and cells. + /// Returns false, if the task failed to persist. + fn persist( + &self, + task:TaskId, + data:TaskData, + state:PersistTaskState, + api:&dyn PersistedGraphApi, + ) -> Result>; + + /// Activate a task in the persisted graph when active_parents > 0 or it's + /// externally kept alive. + fn activate_when_needed( + &self, + task:TaskId, + api:&dyn PersistedGraphApi, + ) -> Result>; + + /// Deactivate a task in the persisted graph when active_parents == 0 and + /// it's not externally kept alive. + fn deactivate_when_needed( + &self, + task:TaskId, + api:&dyn PersistedGraphApi, + ) -> Result>; + + /// Marks a task as kept alive by the consumer graph + /// (usually from memory to persisted graph) + /// Returns true when activate_when_needed should be called soonish + fn set_externally_active(&self, task:TaskId, api:&dyn PersistedGraphApi) -> Result; + + /// No longer marks a task as kept alive by the consumer graph + /// (usually from memory to persisted graph) + /// Returns true when deactivate_when_needed should be called soonish + fn unset_externally_active(&self, task:TaskId, api:&dyn PersistedGraphApi) -> Result; + + /// Removes all external keep alives that were not renewed this round. + /// This is usually called after the initial build has finished and all + /// external keep alives has been renewed. + fn remove_outdated_externally_active(&self, api:&dyn PersistedGraphApi) -> Result>; + + /// update the dirty flag for a stored task + /// Returns true, when the task is active and should be scheduled + fn make_dirty(&self, task:TaskId, api:&dyn PersistedGraphApi) -> Result; + + /// update the dirty flag for a stored task + fn make_clean(&self, task:TaskId, api:&dyn PersistedGraphApi) -> Result<()>; + + /// make all tasks that depend on that vc dirty and + /// return a list of active tasks that should be scheduled + fn make_dependent_dirty(&self, vc:RawVc, api:&dyn PersistedGraphApi) -> Result>; + + /// Get all tasks that are active, but not persisted. + /// This is usually called at beginning to create and schedule + /// tasks that are missing in the persisted graph + fn get_active_external_tasks(&self, api:&dyn PersistedGraphApi) -> Result>; + + /// Get all tasks that are dirty and active. + /// This is usually called at the beginning to schedule these tasks. + fn get_dirty_active_tasks(&self, api:&dyn PersistedGraphApi) -> Result>; + + /// Get tasks that have active update pending that need to be continued + /// returns (tasks_to_activate, tasks_to_deactivate) + fn get_pending_active_update( + &self, + api:&dyn PersistedGraphApi, + ) -> Result<(Vec, Vec)>; + + /// Stop operations + #[allow(unused_variables)] + fn stop(&self, api:&dyn PersistedGraphApi) -> Result<()> { Ok(()) } +} + +pub trait PersistedGraphApi { + fn get_or_create_task_type(&self, ty:PersistentTaskType) -> TaskId; + + fn lookup_task_type(&self, id:TaskId) -> &PersistentTaskType; +} + +// read: +// +// data: (TaskId) => (TaskData) +// cache: (PersistentTaskType) => (TaskId) +// type: (TaskId) => (PersistentTaskType) +// +// read_dependents: +// +// dependents: (RawVc) => [TaskId] +// +// store: +// +// external_active_parents: (TaskId) -> (usize) +// internal_active_parents: (TaskId) -> (usize) +// inactive_tasks: [TaskId] +// +// B+C? +// +// +// +// + +impl PersistedGraph for () { + fn read( + &self, + _task:TaskId, + _api:&dyn PersistedGraphApi, + ) -> Result> { + Ok(None) + } + + fn lookup( + &self, + _partial_task_type:&PersistentTaskType, + _api:&dyn PersistedGraphApi, + ) -> Result { + Ok(false) + } + + fn lookup_one( + &self, + _task_type:&PersistentTaskType, + _api:&dyn PersistedGraphApi, + ) -> Result> { + Ok(None) + } + + fn is_persisted(&self, _task:TaskId, _api:&dyn PersistedGraphApi) -> Result { Ok(false) } + + fn persist( + &self, + _task:TaskId, + _data:TaskData, + _state:PersistTaskState, + _api:&dyn PersistedGraphApi, + ) -> Result> { + Ok(None) + } + + fn activate_when_needed( + &self, + _task:TaskId, + _api:&dyn PersistedGraphApi, + ) -> Result> { + Ok(None) + } + + fn deactivate_when_needed( + &self, + _task:TaskId, + _api:&dyn PersistedGraphApi, + ) -> Result> { + Ok(None) + } + + fn set_externally_active(&self, _task:TaskId, _api:&dyn PersistedGraphApi) -> Result { + Ok(false) + } + + fn unset_externally_active(&self, _task:TaskId, _api:&dyn PersistedGraphApi) -> Result { + Ok(false) + } + + fn remove_outdated_externally_active( + &self, + _api:&dyn PersistedGraphApi, + ) -> Result> { + Ok(Vec::new()) + } + + fn make_dirty(&self, _task:TaskId, _api:&dyn PersistedGraphApi) -> Result { Ok(false) } + + fn make_clean(&self, _task:TaskId, _api:&dyn PersistedGraphApi) -> Result<()> { Ok(()) } + + fn make_dependent_dirty(&self, _vc:RawVc, _api:&dyn PersistedGraphApi) -> Result> { + Ok(Vec::new()) + } + + fn get_active_external_tasks(&self, _api:&dyn PersistedGraphApi) -> Result> { + Ok(Vec::new()) + } + + fn get_dirty_active_tasks(&self, _api:&dyn PersistedGraphApi) -> Result> { + Ok(Vec::new()) + } + + fn get_pending_active_update( + &self, + _api:&dyn PersistedGraphApi, + ) -> Result<(Vec, Vec)> { + Ok((Vec::new(), Vec::new())) + } +} diff --git a/crates/turbo-tasks/Source/primitives.rs b/crates/turbo-tasks/Source/primitives.rs new file mode 100644 index 0000000000000..25949bce2dfcd --- /dev/null +++ b/crates/turbo-tasks/Source/primitives.rs @@ -0,0 +1,121 @@ +use std::{future::IntoFuture, ops::Deref}; + +use anyhow::Result; +use futures::TryFutureExt; +// This specific macro identifier is detected by turbo-tasks-build. +use turbo_tasks_macros::primitive as __turbo_tasks_internal_primitive; + +use crate::{ + RcStr, + TryJoinIterExt, + Vc, + {self as turbo_tasks}, +}; + +__turbo_tasks_internal_primitive!(()); +__turbo_tasks_internal_primitive!(String); +__turbo_tasks_internal_primitive!(RcStr); + +#[turbo_tasks::function] +fn empty_string() -> Vc { Vc::cell(RcStr::default()) } + +impl Vc { + #[deprecated(note = "use Default::default() instead")] + #[inline(always)] + pub fn empty() -> Vc { empty_string() } +} + +__turbo_tasks_internal_primitive!(Option); +__turbo_tasks_internal_primitive!(Option); +__turbo_tasks_internal_primitive!(Vec); + +#[turbo_tasks::function] +fn empty_string_vec() -> Vc> { Vc::cell(Vec::new()) } + +impl Vc> { + #[deprecated(note = "use Default::default() instead")] + #[inline(always)] + pub fn empty() -> Vc> { empty_string_vec() } +} + +__turbo_tasks_internal_primitive!(Option); + +#[turbo_tasks::function] +fn option_string_none() -> Vc> { Vc::cell(None) } + +impl Vc> { + #[deprecated(note = "use Default::default() instead")] + pub fn none() -> Self { option_string_none() } +} + +__turbo_tasks_internal_primitive!(bool); +__turbo_tasks_internal_primitive!(u8); +__turbo_tasks_internal_primitive!(u16); +__turbo_tasks_internal_primitive!(u32); +__turbo_tasks_internal_primitive!(u64); +__turbo_tasks_internal_primitive!(u128); +__turbo_tasks_internal_primitive!(i8); +__turbo_tasks_internal_primitive!(i16); +__turbo_tasks_internal_primitive!(i32); +__turbo_tasks_internal_primitive!(i64); +__turbo_tasks_internal_primitive!(i128); +__turbo_tasks_internal_primitive!(usize); +__turbo_tasks_internal_primitive!(isize); +__turbo_tasks_internal_primitive!(serde_json::Value); +__turbo_tasks_internal_primitive!(Vec); + +__turbo_tasks_internal_primitive!(Vec); + +#[turbo_tasks::value(transparent)] +pub struct Bools(Vec>); + +#[turbo_tasks::value_impl] +impl Bools { + #[turbo_tasks::function] + pub fn empty() -> Vc { Vc::cell(Vec::new()) } + + #[turbo_tasks::function] + async fn into_bools(self: Vc) -> Result>> { + let this = self.await?; + + let bools = this.iter().map(|b| b.into_future().map_ok(|b| *b)).try_join().await?; + + Ok(Vc::cell(bools)) + } + + #[turbo_tasks::function] + pub async fn all(self: Vc) -> Result> { + let bools = self.into_bools().await?; + + Ok(Vc::cell(bools.iter().all(|b| *b))) + } + + #[turbo_tasks::function] + pub async fn any(self: Vc) -> Result> { + let bools = self.into_bools().await?; + + Ok(Vc::cell(bools.iter().any(|b| *b))) + } +} + +#[turbo_tasks::value(transparent, eq = "manual")] +#[derive(Debug, Clone)] +pub struct Regex( + #[turbo_tasks(trace_ignore)] + #[serde(with = "serde_regex")] + pub regex::Regex, +); + +impl Deref for Regex { + type Target = regex::Regex; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +impl PartialEq for Regex { + fn eq(&self, other:&Regex) -> bool { + // Context: https://github.com/rust-lang/regex/issues/313#issuecomment-269898900 + self.0.as_str() == other.0.as_str() + } +} +impl Eq for Regex {} diff --git a/crates/turbo-tasks/Source/raw_vc.rs b/crates/turbo-tasks/Source/raw_vc.rs new file mode 100644 index 0000000000000..bc841468f562a --- /dev/null +++ b/crates/turbo-tasks/Source/raw_vc.rs @@ -0,0 +1,416 @@ +use std::{ + any::Any, + fmt::{Debug, Display}, + future::Future, + hash::Hash, + marker::PhantomData, + pin::Pin, + sync::Arc, + task::Poll, +}; + +use anyhow::Result; +use auto_hash_map::AutoSet; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use crate::{ + CollectiblesSource, + SharedReference, + TaskId, + TraitTypeId, + ValueTypeId, + Vc, + VcValueTrait, + VcValueType, + backend::CellContent, + event::EventListener, + manager::{TurboTasksApi, read_task_cell, read_task_output}, + registry::{ + get_value_type, + {self}, + }, + turbo_tasks, + vc::{VcValueTraitCast, VcValueTypeCast, cast::VcCast}, +}; + +#[derive(Error, Debug)] +pub enum ResolveTypeError { + #[error("no content in the cell")] + NoContent, + #[error("the content in the cell has no type")] + UntypedContent, + #[error("content is not available as task execution failed")] + TaskError { source:anyhow::Error }, + #[error("reading the cell content failed")] + ReadError { source:anyhow::Error }, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub struct CellId { + pub type_id:ValueTypeId, + pub index:u32, +} + +impl Display for CellId { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}#{}", registry::get_value_type(self.type_id).name, self.index) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub enum RawVc { + TaskOutput(TaskId), + TaskCell(TaskId, CellId), +} + +impl RawVc { + pub(crate) fn into_read(self) -> ReadRawVcFuture> { + // returns a custom future to have something concrete and sized + // this avoids boxing in IntoFuture + ReadRawVcFuture::new(self) + } + + pub(crate) fn into_strongly_consistent_read( + self, + ) -> ReadRawVcFuture> { + // returns a custom future to have something concrete and sized + // this avoids boxing in IntoFuture + ReadRawVcFuture::new_strongly_consistent(self) + } + + pub(crate) fn into_trait_read( + self, + ) -> ReadRawVcFuture> { + // returns a custom future to have something concrete and sized + // this avoids boxing in IntoFuture + ReadRawVcFuture::new(self) + } + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + pub(crate) fn into_read_untracked_with_turbo_tasks( + self, + turbo_tasks:&dyn TurboTasksApi, + ) -> ReadRawVcFuture> { + ReadRawVcFuture::new_untracked_with_turbo_tasks(self, turbo_tasks) + } + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + pub(crate) fn into_trait_read_untracked( + self, + ) -> ReadRawVcFuture> { + ReadRawVcFuture::new_untracked(self) + } + + /// INVALIDATION: Be careful with this, it will not track dependencies, so + /// using it could break cache invalidation. + pub(crate) fn into_strongly_consistent_trait_read_untracked( + self, + ) -> ReadRawVcFuture> { + ReadRawVcFuture::new_strongly_consistent_untracked(self) + } + + pub(crate) async fn resolve_trait( + self, + trait_type:TraitTypeId, + ) -> Result, ResolveTypeError> { + let tt = turbo_tasks(); + tt.notify_scheduled_tasks(); + let mut current = self; + loop { + match current { + RawVc::TaskOutput(task) => { + current = read_task_output(&*tt, task, false) + .await + .map_err(|source| ResolveTypeError::TaskError { source })?; + }, + RawVc::TaskCell(task, index) => { + let content = read_task_cell(&*tt, task, index) + .await + .map_err(|source| ResolveTypeError::ReadError { source })?; + if let CellContent(Some(shared_reference)) = content { + if let SharedReference(Some(value_type), _) = shared_reference { + if get_value_type(value_type).has_trait(&trait_type) { + return Ok(Some(RawVc::TaskCell(task, index))); + } else { + return Ok(None); + } + } else { + return Err(ResolveTypeError::UntypedContent); + } + } else { + return Err(ResolveTypeError::NoContent); + } + }, + } + } + } + + pub(crate) async fn resolve_value( + self, + value_type:ValueTypeId, + ) -> Result, ResolveTypeError> { + let tt = turbo_tasks(); + tt.notify_scheduled_tasks(); + let mut current = self; + loop { + match current { + RawVc::TaskOutput(task) => { + current = read_task_output(&*tt, task, false) + .await + .map_err(|source| ResolveTypeError::TaskError { source })?; + }, + RawVc::TaskCell(task, index) => { + let content = read_task_cell(&*tt, task, index) + .await + .map_err(|source| ResolveTypeError::ReadError { source })?; + if let CellContent(Some(shared_reference)) = content { + if let SharedReference(Some(cell_value_type), _) = shared_reference { + if cell_value_type == value_type { + return Ok(Some(RawVc::TaskCell(task, index))); + } else { + return Ok(None); + } + } else { + return Err(ResolveTypeError::UntypedContent); + } + } else { + return Err(ResolveTypeError::NoContent); + } + }, + } + } + } + + /// See [`crate::Vc::resolve`]. + pub(crate) async fn resolve(self) -> Result { + let tt = turbo_tasks(); + let mut current = self; + let mut notified = false; + loop { + match current { + RawVc::TaskOutput(task) => { + if !notified { + tt.notify_scheduled_tasks(); + notified = true; + } + current = read_task_output(&*tt, task, false).await?; + }, + RawVc::TaskCell(..) => return Ok(current), + } + } + } + + /// See [`crate::Vc::resolve_strongly_consistent`]. + pub(crate) async fn resolve_strongly_consistent(self) -> Result { + let tt = turbo_tasks(); + let mut current = self; + let mut notified = false; + loop { + match current { + RawVc::TaskOutput(task) => { + if !notified { + tt.notify_scheduled_tasks(); + notified = true; + } + current = read_task_output(&*tt, task, true).await?; + }, + RawVc::TaskCell(..) => return Ok(current), + } + } + } + + pub(crate) fn connect(&self) { + let tt = turbo_tasks(); + tt.connect_task(self.get_task_id()); + } + + pub fn get_task_id(&self) -> TaskId { + match self { + RawVc::TaskOutput(t) | RawVc::TaskCell(t, _) => *t, + } + } +} + +impl CollectiblesSource for RawVc { + fn peek_collectibles(self) -> AutoSet> { + let tt = turbo_tasks(); + tt.notify_scheduled_tasks(); + let map = tt.read_task_collectibles(self.get_task_id(), T::get_trait_type_id()); + map.into_iter() + .filter_map(|(raw, count)| (count > 0).then_some(raw.into())) + .collect() + } + + fn take_collectibles(self) -> AutoSet> { + let tt = turbo_tasks(); + tt.notify_scheduled_tasks(); + let map = tt.read_task_collectibles(self.get_task_id(), T::get_trait_type_id()); + tt.unemit_collectibles(T::get_trait_type_id(), &map); + map.into_iter() + .filter_map(|(raw, count)| (count > 0).then_some(raw.into())) + .collect() + } +} + +impl Display for RawVc { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RawVc::TaskOutput(task) => { + write!(f, "output of {}", task) + }, + RawVc::TaskCell(task, index) => { + write!(f, "value {} of {}", index, task) + }, + } + } +} + +pub struct ReadRawVcFuture> { + turbo_tasks:Arc, + strongly_consistent:bool, + current:RawVc, + untracked:bool, + listener:Option, + phantom_data:PhantomData>>, + _cast:PhantomData, +} + +impl ReadRawVcFuture { + pub(crate) fn new(vc:RawVc) -> Self { + let tt = turbo_tasks(); + ReadRawVcFuture { + turbo_tasks:tt, + strongly_consistent:false, + current:vc, + untracked:false, + listener:None, + phantom_data:PhantomData, + _cast:PhantomData, + } + } + + fn new_untracked_with_turbo_tasks(vc:RawVc, turbo_tasks:&dyn TurboTasksApi) -> Self { + let tt = turbo_tasks.pin(); + ReadRawVcFuture { + turbo_tasks:tt, + strongly_consistent:false, + current:vc, + untracked:true, + listener:None, + phantom_data:PhantomData, + _cast:PhantomData, + } + } + + fn new_untracked(vc:RawVc) -> Self { + let tt = turbo_tasks(); + ReadRawVcFuture { + turbo_tasks:tt, + strongly_consistent:false, + current:vc, + untracked:true, + listener:None, + phantom_data:PhantomData, + _cast:PhantomData, + } + } + + fn new_strongly_consistent(vc:RawVc) -> Self { + let tt = turbo_tasks(); + ReadRawVcFuture { + turbo_tasks:tt, + strongly_consistent:true, + current:vc, + untracked:false, + listener:None, + phantom_data:PhantomData, + _cast:PhantomData, + } + } + + fn new_strongly_consistent_untracked(vc:RawVc) -> Self { + let tt = turbo_tasks(); + ReadRawVcFuture { + turbo_tasks:tt, + strongly_consistent:true, + current:vc, + untracked:true, + listener:None, + phantom_data:PhantomData, + _cast:PhantomData, + } + } +} + +impl Future for ReadRawVcFuture { + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx:&mut std::task::Context<'_>) -> Poll { + self.turbo_tasks.notify_scheduled_tasks(); + // SAFETY: we are not moving this + let this = unsafe { self.get_unchecked_mut() }; + 'outer: loop { + if let Some(listener) = &mut this.listener { + // SAFETY: listener is from previous pinned this + let listener = unsafe { Pin::new_unchecked(listener) }; + if listener.poll(cx).is_pending() { + return Poll::Pending; + } + this.listener = None; + } + let mut listener = match this.current { + RawVc::TaskOutput(task) => { + let read_result = if this.untracked { + this.turbo_tasks + .try_read_task_output_untracked(task, this.strongly_consistent) + } else { + this.turbo_tasks.try_read_task_output(task, this.strongly_consistent) + }; + match read_result { + Ok(Ok(vc)) => { + // We no longer need to read strongly consistent, as any Vc returned + // from the first task will be inside of the scope of the first task. So + // it's already strongly consistent. + this.strongly_consistent = false; + this.current = vc; + continue 'outer; + }, + Ok(Err(listener)) => listener, + Err(err) => return Poll::Ready(Err(err)), + } + }, + RawVc::TaskCell(task, index) => { + let read_result = if this.untracked { + this.turbo_tasks.try_read_task_cell_untracked(task, index) + } else { + this.turbo_tasks.try_read_task_cell(task, index) + }; + match read_result { + Ok(Ok(content)) => { + // SAFETY: Constructor ensures that T and U are binary identical + return Poll::Ready(Cast::cast(content)); + }, + Ok(Err(listener)) => listener, + Err(err) => return Poll::Ready(Err(err)), + } + }, + }; + // SAFETY: listener is from previous pinned this + match unsafe { Pin::new_unchecked(&mut listener) }.poll(cx) { + Poll::Ready(_) => continue, + Poll::Pending => { + this.listener = Some(listener); + return Poll::Pending; + }, + }; + } + } +} + +unsafe impl Send for ReadRawVcFuture where T: ?Sized {} +unsafe impl Sync for ReadRawVcFuture where T: ?Sized {} + +impl Unpin for ReadRawVcFuture where T: ?Sized {} diff --git a/crates/turbo-tasks/Source/raw_vc_set.rs b/crates/turbo-tasks/Source/raw_vc_set.rs new file mode 100644 index 0000000000000..787eaff85cc7f --- /dev/null +++ b/crates/turbo-tasks/Source/raw_vc_set.rs @@ -0,0 +1,21 @@ +use std::marker::PhantomData; + +use auto_hash_map::AutoSet; +// This specific macro identifier is detected by turbo-tasks-build. +use turbo_tasks_macros::primitive as __turbo_tasks_internal_primitive; + +use crate as turbo_tasks; +use crate::{RawVc, TaskId, Vc}; + +__turbo_tasks_internal_primitive!(AutoSet); + +impl Vc> { + /// Casts a `TaskId` to a `Vc>`. + /// + /// # Safety + /// + /// The `TaskId` must be point to a valid `AutoSet`. + pub unsafe fn from_task_id(task_id:TaskId) -> Self { + Vc { node:RawVc::TaskOutput(task_id), _t:PhantomData } + } +} diff --git a/crates/turbo-tasks/Source/rcstr.rs b/crates/turbo-tasks/Source/rcstr.rs new file mode 100644 index 0000000000000..912c23facdd15 --- /dev/null +++ b/crates/turbo-tasks/Source/rcstr.rs @@ -0,0 +1,119 @@ +use std::{ + borrow::{Borrow, Cow}, + ffi::OsStr, + fmt::{Debug, Display}, + ops::Deref, + path::{Path, PathBuf}, + sync::Arc, +}; + +use serde::{Deserialize, Serialize}; +use turbo_tasks_hash::{DeterministicHash, DeterministicHasher}; + +use crate::debug::{ValueDebugFormat, ValueDebugFormatString}; + +/// This type exists to allow swapping out the underlying string type easily. +// If you want to change the underlying string type to `Arc`, please ensure that you profile +// perforamnce. The current implementation offers very cheap `String -> RcStr -> String`, meaning we +// only pay for the allocation for `Arc` when we pass `format!("").into()` to a function. +#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[serde(transparent)] +pub struct RcStr(Arc); + +impl RcStr { + pub fn as_str(&self) -> &str { self.0.as_str() } + + /// This implementation is more efficient than `.to_string()` + pub fn into_owned(self) -> String { + match Arc::try_unwrap(self.0) { + Ok(v) => v, + Err(arc) => arc.to_string(), + } + } + + pub fn map(self, f:impl FnOnce(String) -> String) -> Self { + RcStr(Arc::new(f(self.into_owned()))) + } +} + +impl DeterministicHash for RcStr { + fn deterministic_hash(&self, state:&mut H) { + state.write_usize(self.len()); + state.write_bytes(self.as_bytes()); + } +} + +impl Deref for RcStr { + type Target = str; + + fn deref(&self) -> &Self::Target { self.0.as_str() } +} + +impl Borrow for RcStr { + fn borrow(&self) -> &str { self.0.as_str() } +} + +impl From> for RcStr { + fn from(s:Arc) -> Self { RcStr(s) } +} + +impl From for RcStr { + fn from(s:String) -> Self { RcStr(Arc::new(s)) } +} + +impl From<&'_ str> for RcStr { + fn from(s:&str) -> Self { RcStr(Arc::new(s.to_string())) } +} + +impl From> for RcStr { + fn from(s:Cow) -> Self { RcStr(Arc::new(s.into_owned())) } +} + +/// Mimic `&str` +impl AsRef for RcStr { + fn as_ref(&self) -> &Path { (*self.0).as_ref() } +} + +/// Mimic `&str` +impl AsRef for RcStr { + fn as_ref(&self) -> &OsStr { (*self.0).as_ref() } +} + +/// Mimic `&str` +impl AsRef<[u8]> for RcStr { + fn as_ref(&self) -> &[u8] { (*self.0).as_ref() } +} + +impl PartialEq for RcStr { + fn eq(&self, other:&str) -> bool { self.0.as_str() == other } +} + +impl PartialEq<&'_ str> for RcStr { + fn eq(&self, other:&&str) -> bool { self.0.as_str() == *other } +} + +impl PartialEq for RcStr { + fn eq(&self, other:&String) -> bool { self.as_str() == other.as_str() } +} + +impl Debug for RcStr { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&self.0, f) } +} + +impl Display for RcStr { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&self.0, f) } +} + +impl From for String { + fn from(s:RcStr) -> Self { s.into_owned() } +} + +impl From for PathBuf { + fn from(s:RcStr) -> Self { String::from(s).into() } +} + +impl ValueDebugFormat for RcStr { + fn value_debug_format(&self, _:usize) -> ValueDebugFormatString { + ValueDebugFormatString::Sync(self.to_string()) + } +} diff --git a/crates/turbo-tasks/Source/read_ref.rs b/crates/turbo-tasks/Source/read_ref.rs new file mode 100644 index 0000000000000..0913e7d182d8e --- /dev/null +++ b/crates/turbo-tasks/Source/read_ref.rs @@ -0,0 +1,238 @@ +use std::{ + cmp::Ordering, + fmt::{Debug, Display}, + hash::Hash, + marker::PhantomData, + mem::transmute_copy, + sync::Arc, +}; + +use serde::{Deserialize, Serialize}; +use turbo_tasks_hash::DeterministicHash; + +use crate::{ + SharedReference, + Vc, + VcRead, + VcValueType, + debug::{ValueDebugFormat, ValueDebugFormatString}, + macro_helpers::find_cell_by_type, + trace::{TraceRawVcs, TraceRawVcsContext}, +}; + +/// The read value of a value cell. The read value is immutable, while the cell +/// itself might change over time. It's basically a snapshot of a value at a +/// certain point in time. +/// +/// Internally it stores a reference counted reference to a value on the heap. +pub struct ReadRef(Arc); + +impl Clone for ReadRef { + fn clone(&self) -> Self { Self(self.0.clone()) } +} + +impl std::ops::Deref for ReadRef +where + T: VcValueType, +{ + type Target = >::Target; + + fn deref(&self) -> &Self::Target { T::Read::value_to_target_ref(&self.0) } +} + +impl Display for ReadRef +where + T: VcValueType, + >::Target: Display, +{ + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) } +} + +impl Debug for ReadRef +where + T: VcValueType, + >::Target: Debug, +{ + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&**self, f) } +} + +impl TraceRawVcs for ReadRef +where + T: VcValueType, + >::Target: TraceRawVcs, +{ + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + (**self).trace_raw_vcs(trace_context); + } +} + +impl ValueDebugFormat for ReadRef +where + T: VcValueType, + >::Target: ValueDebugFormat + 'static, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + let value = &**self; + value.value_debug_format(depth) + } +} + +impl PartialEq for ReadRef +where + T: VcValueType, + >::Target: PartialEq, +{ + fn eq(&self, other:&Self) -> bool { PartialEq::eq(&**self, &**other) } +} + +impl Eq for ReadRef +where + T: VcValueType, + >::Target: Eq, +{ +} + +impl PartialOrd for ReadRef +where + T: VcValueType, + >::Target: PartialOrd, +{ + fn partial_cmp(&self, other:&Self) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +impl Ord for ReadRef +where + T: VcValueType, + >::Target: Ord, +{ + fn cmp(&self, other:&Self) -> std::cmp::Ordering { Ord::cmp(&**self, &**other) } +} + +impl Hash for ReadRef +where + T: VcValueType, + >::Target: Hash, +{ + fn hash(&self, state:&mut H) { Hash::hash(&**self, state) } +} + +impl DeterministicHash for ReadRef +where + T: VcValueType, + >::Target: DeterministicHash, +{ + fn deterministic_hash(&self, state:&mut H) { + let p = &**self; + p.deterministic_hash(state); + } +} + +impl<'a, T, I, J:Iterator> IntoIterator for &'a ReadRef +where + T: VcValueType, + &'a >::Target: IntoIterator, +{ + type IntoIter = J; + type Item = I; + + fn into_iter(self) -> Self::IntoIter { (&**self).into_iter() } +} + +impl> IntoIterator for ReadRef +where + T: VcValueType, + &'static >::Target: IntoIterator, +{ + type IntoIter = ReadRefIter; + type Item = I; + + fn into_iter(self) -> Self::IntoIter { + let r = &*self; + // # Safety + // The reference will we valid as long as the ReadRef is valid. + let r = unsafe { + transmute_copy::< + &'_ >::Target, + &'static >::Target, + >(&r) + }; + ReadRefIter { read_ref:self, iter:r.into_iter() } + } +} + +pub struct ReadRefIter> +where + T: VcValueType, { + iter:J, + #[allow(dead_code)] + read_ref:ReadRef, +} + +impl> Iterator for ReadRefIter +where + T: VcValueType, +{ + type Item = I; + + fn next(&mut self) -> Option { self.iter.next() } +} + +impl Serialize for ReadRef +where + T: VcValueType, + >::Target: Serialize, +{ + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + (**self).serialize(serializer) + } +} + +impl<'de, T> Deserialize<'de> for ReadRef +where + T: Deserialize<'de>, +{ + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + let value = T::deserialize(deserializer)?; + Ok(Self(Arc::new(value))) + } +} + +impl ReadRef { + pub fn new(arc:Arc) -> Self { Self(arc) } + + pub fn ptr_eq(&self, other:&ReadRef) -> bool { Arc::ptr_eq(&self.0, &other.0) } + + pub fn ptr_cmp(&self, other:&ReadRef) -> Ordering { + Arc::as_ptr(&self.0).cmp(&Arc::as_ptr(&other.0)) + } +} + +impl ReadRef +where + T: VcValueType, +{ + /// Returns a new cell that points to the same value as the given + /// reference. + pub fn cell(read_ref:ReadRef) -> Vc { + let local_cell = find_cell_by_type(T::get_value_type_id()); + local_cell + .update_shared_reference(SharedReference(Some(T::get_value_type_id()), read_ref.0)); + Vc { node:local_cell.into(), _t:PhantomData } + } +} + +impl ReadRef +where + T: VcValueType, + >::Target: Clone, +{ + /// This will clone the contained value instead of cloning the ReadRef. + /// This clone is more expensive, but allows to get an mutable owned value. + pub fn clone_value(&self) -> >::Target { (**self).clone() } +} diff --git a/crates/turbo-tasks/Source/registry.rs b/crates/turbo-tasks/Source/registry.rs new file mode 100644 index 0000000000000..fde61507785db --- /dev/null +++ b/crates/turbo-tasks/Source/registry.rs @@ -0,0 +1,148 @@ +use std::{fmt::Debug, hash::Hash, ops::Deref}; + +use dashmap::{DashMap, mapref::entry::Entry}; +use once_cell::sync::Lazy; + +use crate::{ + NativeFunction, + TraitType, + ValueType, + id::{FunctionId, TraitTypeId, ValueTypeId}, + id_factory::IdFactory, + no_move_vec::NoMoveVec, +}; + +static FUNCTION_ID_FACTORY:IdFactory = IdFactory::new(); +static FUNCTIONS_BY_NAME:Lazy> = Lazy::new(DashMap::new); +static FUNCTIONS_BY_VALUE:Lazy> = + Lazy::new(DashMap::new); +static FUNCTIONS:Lazy> = + Lazy::new(NoMoveVec::new); + +static VALUE_TYPE_ID_FACTORY:IdFactory = IdFactory::new(); +static VALUE_TYPES_BY_NAME:Lazy> = Lazy::new(DashMap::new); +static VALUE_TYPES_BY_VALUE:Lazy> = + Lazy::new(DashMap::new); +static VALUE_TYPES:Lazy> = Lazy::new(NoMoveVec::new); + +static TRAIT_TYPE_ID_FACTORY:IdFactory = IdFactory::new(); +static TRAIT_TYPES_BY_NAME:Lazy> = Lazy::new(DashMap::new); +static TRAIT_TYPES_BY_VALUE:Lazy> = + Lazy::new(DashMap::new); +static TRAIT_TYPES:Lazy> = Lazy::new(NoMoveVec::new); + +fn register_thing< + K:From + Deref + Sync + Send + Copy, + V:Clone + Hash + Ord + Eq + Sync + Send + Copy, + const INITIAL_CAPACITY_BITS: u32, +>( + global_name:&'static str, + value:V, + id_factory:&IdFactory, + store:&NoMoveVec<(V, &'static str), INITIAL_CAPACITY_BITS>, + map_by_name:&DashMap<&'static str, K>, + map_by_value:&DashMap, +) { + if let Entry::Vacant(e) = map_by_value.entry(value) { + let new_id = id_factory.get(); + // SAFETY: this is a fresh id + unsafe { + store.insert(*new_id as usize, (value, global_name)); + } + map_by_name.insert(global_name, new_id); + e.insert(new_id); + } +} + +fn get_thing_id< + K:From + Deref + Sync + Send + Copy + Debug, + V:Clone + Hash + Ord + Eq + Debug + Sync + Send + Debug, +>( + value:V, + map_by_value:&DashMap, +) -> K { + if let Some(id) = map_by_value.get(&value) { + *id + } else { + panic!("Use of unregistered {:?}", value); + } +} + +pub fn register_function(global_name:&'static str, func:&'static NativeFunction) { + register_thing( + global_name, + func, + &FUNCTION_ID_FACTORY, + &FUNCTIONS, + &FUNCTIONS_BY_NAME, + &FUNCTIONS_BY_VALUE, + ) +} + +pub fn get_function_id(func:&'static NativeFunction) -> FunctionId { + get_thing_id(func, &FUNCTIONS_BY_VALUE) +} + +pub fn get_function_id_by_global_name(global_name:&str) -> Option { + FUNCTIONS_BY_NAME.get(global_name).map(|x| *x) +} + +pub fn get_function(id:FunctionId) -> &'static NativeFunction { + FUNCTIONS.get(*id as usize).unwrap().0 +} + +pub fn get_function_global_name(id:FunctionId) -> &'static str { + FUNCTIONS.get(*id as usize).unwrap().1 +} + +pub fn register_value_type(global_name:&'static str, ty:&'static ValueType) { + register_thing( + global_name, + ty, + &VALUE_TYPE_ID_FACTORY, + &VALUE_TYPES, + &VALUE_TYPES_BY_NAME, + &VALUE_TYPES_BY_VALUE, + ) +} + +pub fn get_value_type_id(func:&'static ValueType) -> ValueTypeId { + get_thing_id(func, &VALUE_TYPES_BY_VALUE) +} + +pub fn get_value_type_id_by_global_name(global_name:&str) -> Option { + VALUE_TYPES_BY_NAME.get(global_name).map(|x| *x) +} + +pub fn get_value_type(id:ValueTypeId) -> &'static ValueType { + VALUE_TYPES.get(*id as usize).unwrap().0 +} + +pub fn get_value_type_global_name(id:ValueTypeId) -> &'static str { + VALUE_TYPES.get(*id as usize).unwrap().1 +} + +pub fn register_trait_type(global_name:&'static str, ty:&'static TraitType) { + register_thing( + global_name, + ty, + &TRAIT_TYPE_ID_FACTORY, + &TRAIT_TYPES, + &TRAIT_TYPES_BY_NAME, + &TRAIT_TYPES_BY_VALUE, + ) +} + +pub fn get_trait_type_id(func:&'static TraitType) -> TraitTypeId { + get_thing_id(func, &TRAIT_TYPES_BY_VALUE) +} + +pub fn get_trait_type_id_by_global_name(global_name:&str) -> Option { + TRAIT_TYPES_BY_NAME.get(global_name).map(|x| *x) +} + +pub fn get_trait(id:TraitTypeId) -> &'static TraitType { TRAIT_TYPES.get(*id as usize).unwrap().0 } + +pub fn get_trait_type_global_name(id:TraitTypeId) -> &'static str { + TRAIT_TYPES.get(*id as usize).unwrap().1 +} diff --git a/crates/turbo-tasks/Source/small_duration.rs b/crates/turbo-tasks/Source/small_duration.rs new file mode 100644 index 0000000000000..809f0c94b7f8f --- /dev/null +++ b/crates/turbo-tasks/Source/small_duration.rs @@ -0,0 +1,205 @@ +use std::{ + fmt::{Debug, Display}, + time::Duration, +}; + +/// Stores a [`Duration`] in a given precision (in nanoseconds) in 4 bytes. +/// +/// For instance, for `P = 10_000` (10 microseconds), this allows a for a total +/// duration of 11.9 hours. Values smaller than 10 microseconds are stored as 10 +/// microseconds. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] +pub struct SmallDuration(u32); + +impl SmallDuration

{ + pub const MAX:SmallDuration

= SmallDuration(u32::MAX); + // TODO(alexkirsz) Figure out if MIN should be 0 or 1. + pub const MIN:SmallDuration

= SmallDuration(1); + pub const ZERO:SmallDuration

= SmallDuration(0); + + pub const fn from_nanos(nanos:u64) -> Self { + if nanos == 0 { + return SmallDuration::ZERO; + } + if nanos <= P { + return SmallDuration::MIN; + } + let value = nanos / P; + if value > u32::MAX as u64 { + return SmallDuration::MAX; + } + SmallDuration(value as u32) + } + + pub const fn from_micros(micros:u64) -> Self { + if micros == 0 { + return SmallDuration::ZERO; + } + let micros_precision = P / 1_000; + if micros <= micros_precision { + return SmallDuration::MIN; + } + let value = micros * 1_000 / P; + if value > u32::MAX as u64 { + return SmallDuration::MAX; + } + SmallDuration(value as u32) + } + + pub const fn from_millis(millis:u64) -> Self { + if millis == 0 { + return SmallDuration::ZERO; + } + let millis_precision = P / 1_000_000; + if millis <= millis_precision { + return SmallDuration::MIN; + } + let value = millis * 1_000_000 / P; + if value > u32::MAX as u64 { + return SmallDuration::MAX; + } + SmallDuration(value as u32) + } + + pub const fn from_secs(secs:u64) -> Self { + if secs == 0 { + return SmallDuration::ZERO; + } + let secs_precision = P / 1_000_000_000; + if secs <= secs_precision { + return SmallDuration::MIN; + } + let value = secs * 1_000_000_000 / P; + if value > u32::MAX as u64 { + return SmallDuration::MAX; + } + SmallDuration(value as u32) + } + + pub(self) fn to_duration(self) -> Duration { Duration::from_nanos(self.0 as u64 * P) } +} + +impl From for SmallDuration

{ + fn from(duration:Duration) -> Self { + if duration.is_zero() { + return SmallDuration::ZERO; + } + let nanos = duration.as_nanos(); + if nanos <= P as u128 { + return SmallDuration::MIN; + } + (nanos / P as u128).try_into().map_or(SmallDuration::MAX, SmallDuration) + } +} + +impl From> for Duration { + fn from(duration:SmallDuration

) -> Self { duration.to_duration() } +} + +impl Display for SmallDuration

{ + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let duration = Duration::from(*self); + duration.fmt(f) + } +} + +impl Debug for SmallDuration

{ + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let duration = Duration::from(*self); + duration.fmt(f) + } +} + +impl PartialEq for SmallDuration

{ + fn eq(&self, other:&Duration) -> bool { self.to_duration() == *other } +} + +#[cfg(test)] +mod tests { + use std::time::Duration; + + use super::SmallDuration; + + #[test] + fn test_1_nano() { + type Sd = SmallDuration<1>; + + assert_eq!(Sd::from_nanos(1), Duration::from_nanos(1)); + assert_eq!(Sd::from_nanos(42), Duration::from_nanos(42)); + + assert_eq!(Sd::from_micros(1), Duration::from_micros(1)); + assert_eq!(Sd::from_micros(42), Duration::from_micros(42)); + + assert_eq!(Sd::from_millis(1), Duration::from_millis(1)); + assert_eq!(Sd::from_millis(42), Duration::from_millis(42)); + + assert_eq!(Sd::from_secs(1), Duration::from_secs(1)); + + // 1ns precision can only store up to ~4.29s. + assert_eq!(Sd::from_secs(4), Duration::from_secs(4)); + assert_eq!(Sd::from_secs(5), Sd::MAX); + } + + #[test] + fn test_1_micro() { + type Sd = SmallDuration<1_000>; + + // 1µs precision can't store ns-level variations. + assert_eq!(Sd::from_nanos(1), Sd::MIN); + assert_eq!(Sd::from_nanos(42), Sd::MIN); + + assert_eq!(Sd::from_micros(1), Duration::from_micros(1)); + assert_eq!(Sd::from_micros(42), Duration::from_micros(42)); + + assert_eq!(Sd::from_millis(1), Duration::from_millis(1)); + assert_eq!(Sd::from_millis(42), Duration::from_millis(42)); + + assert_eq!(Sd::from_secs(1), Duration::from_secs(1)); + assert_eq!(Sd::from_secs(42), Duration::from_secs(42)); + + // 1µs precision can only store up to ~4,294s. + assert_eq!(Sd::from_secs(4_000), Duration::from_secs(4_000)); + assert_eq!(Sd::from_secs(5_000), Sd::MAX); + } + + #[test] + fn test_1_milli() { + type Sd = SmallDuration<1_000_000>; + + // 1ms precision can't store ns-or-µs-level variations. + assert_eq!(Sd::from_nanos(1), Sd::MIN); + assert_eq!(Sd::from_nanos(42), Sd::MIN); + assert_eq!(Sd::from_micros(1), Sd::MIN); + assert_eq!(Sd::from_micros(42), Sd::MIN); + + assert_eq!(Sd::from_millis(1), Duration::from_millis(1)); + assert_eq!(Sd::from_millis(42), Duration::from_millis(42)); + + assert_eq!(Sd::from_secs(1), Duration::from_secs(1)); + assert_eq!(Sd::from_secs(42), Duration::from_secs(42)); + + // 1ms precision can only store up to ~4,294,000s. + assert_eq!(Sd::from_secs(4_000_000), Duration::from_secs(4_000_000)); + assert_eq!(Sd::from_secs(5_000_000), Sd::MAX); + } + + #[test] + fn test_1_sec() { + type Sd = SmallDuration<1_000_000_000>; + + // 1ms precision can't store ns/µs/ms-level variations. + assert_eq!(Sd::from_nanos(1), Sd::MIN); + assert_eq!(Sd::from_nanos(42), Sd::MIN); + assert_eq!(Sd::from_micros(1), Sd::MIN); + assert_eq!(Sd::from_micros(42), Sd::MIN); + assert_eq!(Sd::from_millis(1), Sd::MIN); + assert_eq!(Sd::from_millis(42), Sd::MIN); + + assert_eq!(Sd::from_secs(1), Duration::from_secs(1)); + assert_eq!(Sd::from_secs(42), Duration::from_secs(42)); + + // 1s precision can only store up to ~4,294,000,000s. + assert_eq!(Sd::from_secs(4_000_000_000), Duration::from_secs(4_000_000_000)); + assert_eq!(Sd::from_secs(5_000_000_000), Sd::MAX); + } +} diff --git a/crates/turbo-tasks/Source/state.rs b/crates/turbo-tasks/Source/state.rs new file mode 100644 index 0000000000000..c39ec2010bfb0 --- /dev/null +++ b/crates/turbo-tasks/Source/state.rs @@ -0,0 +1,159 @@ +use std::{ + fmt::Debug, + mem::take, + ops::{Deref, DerefMut}, +}; + +use auto_hash_map::AutoSet; +use parking_lot::{Mutex, MutexGuard}; +use serde::{Deserialize, Deserializer, Serialize}; + +use crate::{Invalidator, get_invalidator, mark_stateful, trace::TraceRawVcs}; + +pub struct State { + inner:Mutex>, +} + +struct StateInner { + value:T, + invalidators:AutoSet, +} + +pub struct StateRef<'a, T> { + inner:MutexGuard<'a, StateInner>, + mutated:bool, +} + +impl Debug for State { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("State").field("value", &self.inner.lock().value).finish() + } +} + +impl TraceRawVcs for State { + fn trace_raw_vcs(&self, trace_context:&mut crate::trace::TraceRawVcsContext) { + self.inner.lock().value.trace_raw_vcs(trace_context); + } +} + +impl Default for State { + fn default() -> Self { + // Need to be explicit to ensure marking as stateful. + Self::new(Default::default()) + } +} + +impl PartialEq for State { + fn eq(&self, _other:&Self) -> bool { false } +} +impl Eq for State {} + +impl Serialize for State { + fn serialize(&self, _serializer:S) -> Result { + // For this to work at all we need to do more. Changing the state need to + // invalidate the serialization of the task that contains the state. So we + // probably need to store the state outside of the task to be able to serialize + // it independent from the creating task. + panic!("State serialization is not implemented yet"); + } +} + +impl<'de, T> Deserialize<'de> for State { + fn deserialize>(_deserializer:D) -> Result { + panic!("State serialization is not implemented yet"); + } +} + +impl Drop for State { + fn drop(&mut self) { + let mut inner = self.inner.lock(); + for invalidator in take(&mut inner.invalidators) { + invalidator.invalidate(); + } + } +} + +impl State { + pub fn new(value:T) -> Self { + mark_stateful(); + Self { inner:Mutex::new(StateInner { value, invalidators:AutoSet::new() }) } + } + + /// Gets the current value of the state. The current task will be registered + /// as dependency of the state and will be invalidated when the state + /// changes. + pub fn get(&self) -> StateRef<'_, T> { + let invalidator = get_invalidator(); + let mut inner = self.inner.lock(); + inner.invalidators.insert(invalidator); + StateRef { inner, mutated:false } + } + + /// Gets the current value of the state. Untracked. + pub fn get_untracked(&self) -> StateRef<'_, T> { + let inner = self.inner.lock(); + StateRef { inner, mutated:false } + } + + /// Sets the current state without comparing it with the old value. This + /// should only be used if one is sure that the value has changed. + pub fn set_unconditionally(&self, value:T) { + let mut inner = self.inner.lock(); + inner.value = value; + for invalidator in take(&mut inner.invalidators) { + invalidator.invalidate(); + } + } + + /// Updates the current state with the `update` function. The `update` + /// function need to return `true` when the value was modified. Exposing + /// the current value from the `update` function is not allowed and will + /// result in incorrect cache invalidation. + pub fn update_conditionally(&self, update:impl FnOnce(&mut T) -> bool) { + let mut inner = self.inner.lock(); + if !update(&mut inner.value) { + return; + } + for invalidator in take(&mut inner.invalidators) { + invalidator.invalidate(); + } + } +} + +impl State { + /// Update the current state when the `value` is different from the current + /// value. `T` must implement [PartialEq] for this to work. + pub fn set(&self, value:T) { + let mut inner = self.inner.lock(); + if inner.value == value { + return; + } + inner.value = value; + for invalidator in take(&mut inner.invalidators) { + invalidator.invalidate(); + } + } +} + +impl<'a, T> Deref for StateRef<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { &self.inner.value } +} + +impl<'a, T> DerefMut for StateRef<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.mutated = true; + &mut self.inner.value + } +} + +impl<'a, T> Drop for StateRef<'a, T> { + fn drop(&mut self) { + if self.mutated { + for invalidator in take(&mut self.inner.invalidators) { + invalidator.invalidate(); + } + } + } +} diff --git a/crates/turbo-tasks/Source/task/concrete_task_input.rs b/crates/turbo-tasks/Source/task/concrete_task_input.rs new file mode 100644 index 0000000000000..13dc9cc1fe57f --- /dev/null +++ b/crates/turbo-tasks/Source/task/concrete_task_input.rs @@ -0,0 +1,488 @@ +use std::{ + any::Any, + borrow::Cow, + fmt::{Debug, Display}, + future::Future, + hash::Hash, + pin::Pin, + sync::Arc, +}; + +use anyhow::Result; +use serde::{Deserialize, Serialize, ser::SerializeTuple}; + +use crate::{ + CellId, + RawVc, + RcStr, + TaskId, + TraitType, + ValueTypeId, + backend::CellContent, + id::{FunctionId, TraitTypeId}, + magic_any::MagicAny, + manager::{read_task_cell, read_task_output}, + registry, + turbo_tasks, +}; + +#[derive(Clone)] +pub struct SharedReference(pub Option, pub Arc); + +impl SharedReference { + pub fn downcast(self) -> Option> { + match Arc::downcast(self.1) { + Ok(data) => Some(data), + Err(_) => None, + } + } +} + +impl Hash for SharedReference { + fn hash(&self, state:&mut H) { + Hash::hash(&(&*self.1 as *const (dyn Any + Send + Sync)), state) + } +} +impl PartialEq for SharedReference { + // Must compare with PartialEq rather than std::ptr::addr_eq since the latter + // only compares their addresses. + #[allow(ambiguous_wide_pointer_comparisons)] + fn eq(&self, other:&Self) -> bool { + std::ptr::addr_eq( + &*self.1 as *const (dyn Any + Send + Sync), + &*other.1 as *const (dyn Any + Send + Sync), + ) + } +} +impl Eq for SharedReference {} +impl PartialOrd for SharedReference { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} +impl Ord for SharedReference { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + Ord::cmp( + &(&*self.1 as *const (dyn Any + Send + Sync)).cast::<()>(), + &(&*other.1 as *const (dyn Any + Send + Sync)).cast::<()>(), + ) + } +} +impl Debug for SharedReference { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("SharedReference").field(&self.0).field(&self.1).finish() + } +} + +impl Serialize for SharedReference { + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + if let SharedReference(Some(ty), arc) = self { + let value_type = registry::get_value_type(*ty); + if let Some(serializable) = value_type.any_as_serializable(arc) { + let mut t = serializer.serialize_tuple(2)?; + t.serialize_element(registry::get_value_type_global_name(*ty))?; + t.serialize_element(serializable)?; + t.end() + } else { + Err(serde::ser::Error::custom(format!("{:?} is not serializable", arc))) + } + } else { + Err(serde::ser::Error::custom("untyped values are not serializable")) + } + } +} + +impl Display for SharedReference { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(ty) = self.0 { + write!(f, "value of type {}", registry::get_value_type(ty).name) + } else { + write!(f, "untyped value") + } + } +} + +impl<'de> Deserialize<'de> for SharedReference { + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = SharedReference; + + fn expecting(&self, formatter:&mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a serializable shared reference") + } + + fn visit_seq(self, mut seq:A) -> Result + where + A: serde::de::SeqAccess<'de>, { + if let Some(global_name) = seq.next_element()? { + if let Some(ty) = registry::get_value_type_id_by_global_name(global_name) { + if let Some(seed) = registry::get_value_type(ty).get_any_deserialize_seed() + { + if let Some(value) = seq.next_element_seed(seed)? { + Ok(SharedReference(Some(ty), value.into())) + } else { + Err(serde::de::Error::invalid_length( + 1, + &"tuple with type and value", + )) + } + } else { + Err(serde::de::Error::custom(format!("{ty} is not deserializable"))) + } + } else { + Err(serde::de::Error::unknown_variant(global_name, &[])) + } + } else { + Err(serde::de::Error::invalid_length(0, &"tuple with type and value")) + } + } + } + + deserializer.deserialize_tuple(2, Visitor) + } +} + +#[derive(Debug, Clone, PartialOrd, Ord)] +pub struct TransientSharedValue(pub Arc); + +impl TransientSharedValue { + pub fn downcast(self) -> Option> { + match Arc::downcast(self.0.magic_any_arc()) { + Ok(data) => Some(data), + Err(_) => None, + } + } +} + +impl Hash for TransientSharedValue { + fn hash(&self, state:&mut H) { self.0.hash(state); } +} + +impl PartialEq for TransientSharedValue { + #[allow(clippy::op_ref)] + fn eq(&self, other:&Self) -> bool { &self.0 == &other.0 } +} +impl Eq for TransientSharedValue {} +impl Serialize for TransientSharedValue { + fn serialize(&self, _serializer:S) -> Result + where + S: serde::Serializer, { + Err(serde::ser::Error::custom("Transient values can't be serialized")) + } +} +impl<'de> Deserialize<'de> for TransientSharedValue { + fn deserialize(_deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + unreachable!("Transient values can't be serialized") + } +} + +#[derive(Debug, Clone, PartialOrd, Ord)] +pub struct SharedValue(pub Option, pub Arc); + +impl SharedValue { + pub fn downcast(self) -> Option> { + match Arc::downcast(self.1.magic_any_arc()) { + Ok(data) => Some(data), + Err(_) => None, + } + } +} + +impl PartialEq for SharedValue { + // this breaks without the ref + #[allow(clippy::op_ref)] + fn eq(&self, other:&Self) -> bool { self.0 == other.0 && &self.1 == &other.1 } +} + +impl Eq for SharedValue {} + +impl Hash for SharedValue { + fn hash(&self, state:&mut H) { + self.0.hash(state); + self.1.hash(state); + } +} + +impl Display for SharedValue { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(ty) = self.0 { + write!(f, "value of type {}", registry::get_value_type(ty).name) + } else { + write!(f, "untyped value") + } + } +} + +impl Serialize for SharedValue { + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + if let SharedValue(Some(ty), arc) = self { + let value_type = registry::get_value_type(*ty); + if let Some(serializable) = value_type.magic_as_serializable(arc) { + let mut t = serializer.serialize_tuple(2)?; + t.serialize_element(registry::get_value_type_global_name(*ty))?; + t.serialize_element(serializable)?; + t.end() + } else { + Err(serde::ser::Error::custom(format!("{:?} is not serializable", arc))) + } + } else { + Err(serde::ser::Error::custom("untyped values are not serializable")) + } + } +} + +impl<'de> Deserialize<'de> for SharedValue { + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = SharedValue; + + fn expecting(&self, formatter:&mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a serializable shared value") + } + + fn visit_seq(self, mut seq:A) -> Result + where + A: serde::de::SeqAccess<'de>, { + if let Some(global_name) = seq.next_element()? { + if let Some(ty) = registry::get_value_type_id_by_global_name(global_name) { + if let Some(seed) = + registry::get_value_type(ty).get_magic_deserialize_seed() + { + if let Some(value) = seq.next_element_seed(seed)? { + Ok(SharedValue(Some(ty), value.into())) + } else { + Err(serde::de::Error::invalid_length( + 1, + &"tuple with type and value", + )) + } + } else { + Err(serde::de::Error::custom(format!("{ty} is not deserializable"))) + } + } else { + Err(serde::de::Error::unknown_variant(global_name, &[])) + } + } else { + Err(serde::de::Error::invalid_length(0, &"tuple with type and value")) + } + } + } + + deserializer.deserialize_tuple(2, Visitor) + } +} + +/// Intermediate representation of task inputs. +/// +/// When a task is called, all its arguments will be converted and stored as +/// [`ConcreteTaskInput`]s. When the task is actually run, these inputs will be +/// converted back into the argument types. This is handled by the [`TaskInput`] +/// trait. +#[allow(clippy::derived_hash_with_manual_eq)] +#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default)] +pub enum ConcreteTaskInput { + TaskOutput(TaskId), + TaskCell(TaskId, CellId), + List(Vec), + String(RcStr), + Bool(bool), + Usize(usize), + I8(i8), + U8(u8), + I16(i16), + U16(u16), + I32(i32), + U32(u32), + U64(u64), + #[default] + Nothing, + SharedValue(SharedValue), + TransientSharedValue(TransientSharedValue), + SharedReference(SharedReference), +} + +impl ConcreteTaskInput { + pub async fn resolve_to_value(self) -> Result { + let tt = turbo_tasks(); + let mut current = self; + loop { + current = match current { + ConcreteTaskInput::TaskOutput(task_id) => { + read_task_output(&*tt, task_id, false).await?.into() + }, + ConcreteTaskInput::TaskCell(task_id, index) => { + read_task_cell(&*tt, task_id, index).await?.into() + }, + _ => return Ok(current), + } + } + } + + pub async fn resolve(self) -> Result { + let tt = turbo_tasks(); + let mut current = self; + loop { + current = match current { + ConcreteTaskInput::TaskOutput(task_id) => { + read_task_output(&*tt, task_id, false).await?.into() + }, + ConcreteTaskInput::List(list) => { + if list.iter().all(|i| i.is_resolved()) { + return Ok(ConcreteTaskInput::List(list)); + } + fn resolve_all( + list:Vec, + ) -> Pin>> + Send>> { + use crate::TryJoinIterExt; + Box::pin(list.into_iter().map(|i| i.resolve()).try_join()) + } + return Ok(ConcreteTaskInput::List(resolve_all(list).await?)); + }, + _ => return Ok(current), + } + } + } + + pub fn get_task_id(&self) -> Option { + match self { + ConcreteTaskInput::TaskOutput(t) | ConcreteTaskInput::TaskCell(t, _) => Some(*t), + _ => None, + } + } + + pub fn get_trait_method( + &self, + trait_type:TraitTypeId, + name:Cow<'static, str>, + ) -> Result> { + match self { + ConcreteTaskInput::TaskOutput(_) | ConcreteTaskInput::TaskCell(..) => { + panic!("get_trait_method must be called on a resolved TaskInput") + }, + ConcreteTaskInput::SharedValue(SharedValue(ty, _)) + | ConcreteTaskInput::SharedReference(SharedReference(ty, _)) => { + if let Some(ty) = *ty { + let key = (trait_type, name); + if let Some(func) = registry::get_value_type(ty).get_trait_method(&key) { + Ok(*func) + } else if let Some(func) = + registry::get_trait(trait_type).default_trait_methods.get(&key.1) + { + Ok(*func) + } else { + Err(key.1) + } + } else { + Err(name) + } + }, + _ => Err(name), + } + } + + pub fn has_trait(&self, trait_type:TraitTypeId) -> bool { + match self { + ConcreteTaskInput::TaskOutput(_) | ConcreteTaskInput::TaskCell(..) => { + panic!("has_trait() must be called on a resolved TaskInput") + }, + ConcreteTaskInput::SharedValue(SharedValue(ty, _)) + | ConcreteTaskInput::SharedReference(SharedReference(ty, _)) => { + if let Some(ty) = *ty { + registry::get_value_type(ty).has_trait(&trait_type) + } else { + false + } + }, + _ => false, + } + } + + pub fn traits(&self) -> Vec<&'static TraitType> { + match self { + ConcreteTaskInput::TaskOutput(_) | ConcreteTaskInput::TaskCell(..) => { + panic!("traits() must be called on a resolved TaskInput") + }, + ConcreteTaskInput::SharedValue(SharedValue(ty, _)) + | ConcreteTaskInput::SharedReference(SharedReference(ty, _)) => { + if let Some(ty) = *ty { + registry::get_value_type(ty).traits_iter().map(registry::get_trait).collect() + } else { + Vec::new() + } + }, + _ => Vec::new(), + } + } + + pub fn is_resolved(&self) -> bool { + match self { + ConcreteTaskInput::TaskOutput(_) => false, + ConcreteTaskInput::List(list) => list.iter().all(|i| i.is_resolved()), + _ => true, + } + } + + pub fn is_nothing(&self) -> bool { matches!(self, ConcreteTaskInput::Nothing) } +} + +impl From for ConcreteTaskInput { + fn from(raw_vc:RawVc) -> Self { + match raw_vc { + RawVc::TaskOutput(task) => ConcreteTaskInput::TaskOutput(task), + RawVc::TaskCell(task, i) => ConcreteTaskInput::TaskCell(task, i), + } + } +} + +impl From for ConcreteTaskInput { + fn from(content:CellContent) -> Self { + match content { + CellContent(None) => ConcreteTaskInput::Nothing, + CellContent(Some(shared_ref)) => ConcreteTaskInput::SharedReference(shared_ref), + } + } +} + +impl Display for ConcreteTaskInput { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConcreteTaskInput::TaskOutput(task) => write!(f, "task output {}", task), + ConcreteTaskInput::TaskCell(task, index) => write!(f, "cell {} in {}", index, task), + ConcreteTaskInput::List(list) => { + write!( + f, + "list {}", + list.iter().map(|i| i.to_string()).collect::>().join(", ") + ) + }, + ConcreteTaskInput::String(s) => write!(f, "string {:?}", s), + ConcreteTaskInput::Bool(b) => write!(f, "bool {:?}", b), + ConcreteTaskInput::Usize(v) => write!(f, "usize {}", v), + ConcreteTaskInput::I8(v) => write!(f, "i8 {}", v), + ConcreteTaskInput::U8(v) => write!(f, "u8 {}", v), + ConcreteTaskInput::I16(v) => write!(f, "i16 {}", v), + ConcreteTaskInput::U16(v) => write!(f, "u16 {}", v), + ConcreteTaskInput::I32(v) => write!(f, "i32 {}", v), + ConcreteTaskInput::U32(v) => write!(f, "u32 {}", v), + ConcreteTaskInput::U64(v) => write!(f, "u64 {}", v), + ConcreteTaskInput::Nothing => write!(f, "nothing"), + ConcreteTaskInput::SharedValue(_) => write!(f, "any value"), + ConcreteTaskInput::TransientSharedValue(_) => write!(f, "any transient value"), + ConcreteTaskInput::SharedReference(data) => { + write!(f, "shared reference with {}", data) + }, + } + } +} diff --git a/crates/turbo-tasks/Source/task/function.rs b/crates/turbo-tasks/Source/task/function.rs new file mode 100644 index 0000000000000..1f5b813394ecc --- /dev/null +++ b/crates/turbo-tasks/Source/task/function.rs @@ -0,0 +1,437 @@ +//! # Function tasks +//! +//! This module contains the trait definitions and implementations that are +//! necessary for accepting functions as tasks when using the +//! `turbo_tasks::function` macro. +//! +//! This system is inspired by Bevy's Systems and Axum's Handlers. +//! +//! The original principle is somewhat simple: a function is accepted if all +//! of its arguments implement `TaskInput` and its return type implements +//! `TaskOutput`. There are a few hoops one needs to jump through to make this +//! work, but they are described in this blog post: +//! https://blog.logrocket.com/rust-bevy-entity-component-system/ +//! +//! However, there is an additional complication in our case: async methods +//! that accept a reference to the receiver as their first argument. +//! +//! This complication handled through our own version of the `async_trait` +//! crate, which allows us to target `async fn` as trait bounds. The naive +//! approach runs into many issues with lifetimes, hence the need for an +//! intermediate trait. However, this implementation doesn't support all async +//! methods (see commented out tests). + +use std::{future::Future, marker::PhantomData, pin::Pin}; + +use anyhow::{Context, Result, bail}; + +use super::{TaskInput, TaskOutput}; +use crate::{ConcreteTaskInput, RawVc, Vc, VcRead, VcValueType}; + +pub type NativeTaskFuture = Pin> + Send>>; +pub type NativeTaskFn = Box NativeTaskFuture + Send + Sync>; + +pub trait TaskFn: Send + Sync + 'static { + fn functor(&self, inputs:&[ConcreteTaskInput]) -> Result; +} + +pub trait IntoTaskFn { + type TaskFn: TaskFn; + + fn into_task_fn(self) -> Self::TaskFn; +} + +impl IntoTaskFn for F +where + F: TaskFnInputFunction, + Mode: TaskFnMode, + Inputs: TaskInputs, +{ + type TaskFn = FunctionTaskFn; + + fn into_task_fn(self) -> Self::TaskFn { + FunctionTaskFn { task_fn:self, mode:PhantomData, inputs:PhantomData } + } +} + +pub struct FunctionTaskFn { + task_fn:F, + mode:PhantomData, + inputs:PhantomData, +} + +impl TaskFn for FunctionTaskFn +where + F: TaskFnInputFunction, + Mode: TaskFnMode, + Inputs: TaskInputs, +{ + fn functor(&self, inputs:&[ConcreteTaskInput]) -> Result { + TaskFnInputFunction::functor(&self.task_fn, inputs) + } +} + +trait TaskFnInputFunction: Send + Sync + Clone + 'static { + fn functor(&self, inputs:&[ConcreteTaskInput]) -> Result; +} + +pub trait TaskInputs: Send + Sync + 'static {} + +/// Modes to allow multiple `TaskFnInputFunction` blanket implementations on +/// `Fn`s. Even though the implementations are non-conflicting in practice, they +/// could be in theory (at least from with the compiler's current limitations). +/// Despite this, the compiler is still able to infer the correct mode from a +/// function. +pub trait TaskFnMode: Send + Sync + 'static {} + +pub struct FunctionMode; +impl TaskFnMode for FunctionMode {} + +pub struct MethodMode; +impl TaskFnMode for MethodMode {} + +pub struct AsyncFunctionMode; +impl TaskFnMode for AsyncFunctionMode {} + +pub struct AsyncMethodMode; +impl TaskFnMode for AsyncMethodMode {} + +macro_rules! task_inputs_impl { + ( $( $arg:ident )* ) => { + impl<$($arg,)*> TaskInputs for ($($arg,)*) + where + $($arg: TaskInput + 'static,)* + {} + } +} + +macro_rules! as_concrete_task_input { + ($arg:ident) => { + ConcreteTaskInput + }; +} + +macro_rules! task_fn_impl { + ( $helper_module:ident $async_fn_trait:ident $arg_len:literal $( $arg:ident )* ) => { + mod $helper_module { + use super::*; + + // this is a non-generic helper method to allow code-sharing across monomorphized + // instances of this function + pub fn get_args( + inputs: &[ConcreteTaskInput], + ) -> Result<($(&as_concrete_task_input!($arg),)*)> { + get_args_iter(inputs.iter()) + } + + pub fn get_method_args( + inputs: &[ConcreteTaskInput], + ) -> Result<(&ConcreteTaskInput, ($(&as_concrete_task_input!($arg),)*))> { + let mut iter = inputs.iter(); + let recv = iter.next().context("task is missing receiver")?; + Ok((recv, get_args_iter(iter)?)) + } + + fn get_args_iter( + mut iter: std::slice::Iter<'_, ConcreteTaskInput>, + ) -> Result<($(&as_concrete_task_input!($arg),)*)> { + let args = ($(next_arg(&mut iter, stringify!($arg))?,)*); + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + Ok(args) + } + } + + impl TaskFnInputFunction for F + where + $($arg: TaskInput + 'static,)* + F: Fn($($arg,)*) -> Output + Send + Sync + Clone + 'static, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let ($($arg,)*) = $helper_module::get_args(inputs)?; + + let task_fn = self.clone(); + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(async move { + Output::try_into_raw_vc((task_fn)($($arg),*)) + }) + })) + } + } + + impl TaskFnInputFunction for F + where + $($arg: TaskInput + 'static,)* + F: Fn($($arg,)*) -> FutureOutput + Send + Sync + Clone + 'static, + FutureOutput: Future + Send, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let ($($arg,)*) = $helper_module::get_args(inputs)?; + + let task_fn = self.clone(); + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(async move { + Output::try_into_raw_vc((task_fn)($($arg),*).await) + }) + })) + } + } + + impl TaskFnInputFunction, $($arg,)*)> for F + where + Recv: VcValueType, + $($arg: TaskInput + 'static,)* + F: Fn(&Recv, $($arg,)*) -> Output + Send + Sync + Clone + 'static, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let (recv, ($($arg,)*)) = $helper_module::get_method_args(inputs)?; + + let task_fn = self.clone(); + let recv = Vc::::try_from_concrete(recv)?; + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + let recv = recv.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(async move { + let recv = recv.await?; + let recv = <::Read as VcRead>::target_to_value_ref(&*recv); + Output::try_into_raw_vc((task_fn)(recv, $($arg),*)) + }) + })) + } + } + + pub trait $async_fn_trait: Fn(A0, $($arg,)*) -> Self::OutputFuture { + type OutputFuture: Future>::Output> + Send; + type Output: TaskOutput; + } + + impl $async_fn_trait for F + where + F: Fn(A0, $($arg,)*) -> Fut, + Fut: Future + Send, + Fut::Output: TaskOutput + { + type OutputFuture = Fut; + type Output = Fut::Output; + } + + impl TaskFnInputFunction, $($arg,)*)> for F + where + Recv: VcValueType, + $($arg: TaskInput + 'static,)* + F: for<'a> $async_fn_trait<&'a Recv, $($arg,)*> + Clone + Send + Sync + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let task_fn = self.clone(); + let mut iter = inputs.iter(); + + let recv = iter.next().context("task is missing receiver")?; + $( + let $arg = next_arg(&mut iter, stringify!($arg))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + let recv = Vc::::try_from_concrete(recv)?; + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + let recv = recv.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(async move { + let recv = recv.await?; + let recv = <::Read as VcRead>::target_to_value_ref(&*recv); + >::Output::try_into_raw_vc((task_fn)(recv, $($arg),*).await) + }) + })) + } + } + }; +} + +task_fn_impl! { async_fn_0 AsyncFn0 0 } +task_fn_impl! { async_fn_1 AsyncFn1 1 A1 } +task_fn_impl! { async_fn_2 AsyncFn2 2 A1 A2 } +task_fn_impl! { async_fn_3 AsyncFn3 3 A1 A2 A3 } +task_fn_impl! { async_fn_4 AsyncFn4 4 A1 A2 A3 A4 } +task_fn_impl! { async_fn_5 AsyncFn5 5 A1 A2 A3 A4 A5 } +task_fn_impl! { async_fn_6 AsyncFn6 6 A1 A2 A3 A4 A5 A6 } +task_fn_impl! { async_fn_7 AsyncFn7 7 A1 A2 A3 A4 A5 A6 A7 } +task_fn_impl! { async_fn_8 AsyncFn8 8 A1 A2 A3 A4 A5 A6 A7 A8 } +task_fn_impl! { async_fn_9 AsyncFn9 9 A1 A2 A3 A4 A5 A6 A7 A8 A9 } +task_fn_impl! { async_fn_10 AsyncFn10 10 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 } +task_fn_impl! { async_fn_11 AsyncFn11 11 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 } +task_fn_impl! { async_fn_12 AsyncFn12 12 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 } +task_fn_impl! { async_fn_13 AsyncFn13 13 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 } +task_fn_impl! { async_fn_14 AsyncFn14 14 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 } +task_fn_impl! { async_fn_15 AsyncFn15 15 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 } +task_fn_impl! { async_fn_16 AsyncFn16 16 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 } + +// There needs to be one more implementation than task_fn_impl to account for +// the receiver. +task_inputs_impl! {} +task_inputs_impl! { A1 } +task_inputs_impl! { A1 A2 } +task_inputs_impl! { A1 A2 A3 } +task_inputs_impl! { A1 A2 A3 A4 } +task_inputs_impl! { A1 A2 A3 A4 A5 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 } + +fn next_arg<'a>( + iter:&mut std::slice::Iter<'a, ConcreteTaskInput>, + arg_name:&'static str, +) -> Result<&'a ConcreteTaskInput> { + iter.next() + .with_context(move || format!("task is missing argument {}", arg_name)) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{RcStr, VcCellNewMode, VcDefaultRead}; + + #[test] + fn test_task_fn() { + fn no_args() -> crate::Vc { todo!() } + + fn one_arg(_a:i32) -> crate::Vc { todo!() } + + async fn async_one_arg(_a:i32) -> crate::Vc { todo!() } + + fn with_recv(_a:&i32) -> crate::Vc { todo!() } + + async fn async_with_recv(_a:&i32) -> crate::Vc { todo!() } + + fn with_recv_and_str(_a:&i32, _s:RcStr) -> crate::Vc { todo!() } + + async fn async_with_recv_and_str(_a:&i32, _s:RcStr) -> crate::Vc { todo!() } + + async fn async_with_recv_and_str_and_result(_a:&i32, _s:RcStr) -> Result> { + todo!() + } + + fn accepts_task_fn(_task_fn:F) + where + F: TaskFn, { + } + + struct Struct; + impl Struct { + async fn inherent_method(&self) {} + } + + unsafe impl VcValueType for Struct { + type CellMode = VcCellNewMode; + type Read = VcDefaultRead; + + fn get_value_type_id() -> crate::ValueTypeId { todo!() } + } + + trait AsyncTrait { + async fn async_method(&self); + } + + impl AsyncTrait for Struct { + async fn async_method(&self) { todo!() } + } + + // async fn async_with_recv_and_str_and_lf( + // _a: &i32, + // _s: String, + // ) -> Result, crate::Vc> { + // todo!() + // } + // + // #[async_trait::async_trait] + // trait BoxAsyncTrait { + // async fn box_async_method(&self); + // } + // + // #[async_trait::async_trait] + // impl BoxAsyncTrait for Struct { + // async fn box_async_method(&self) { + // todo!() + // } + // } + + let _task_fn = no_args.into_task_fn(); + accepts_task_fn(no_args.into_task_fn()); + let _task_fn = one_arg.into_task_fn(); + accepts_task_fn(one_arg.into_task_fn()); + let _task_fn = async_one_arg.into_task_fn(); + accepts_task_fn(async_one_arg.into_task_fn()); + let task_fn = with_recv.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = async_with_recv.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = with_recv_and_str.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = async_with_recv_and_str.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = async_with_recv_and_str_and_result.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = ::async_method.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = Struct::inherent_method.into_task_fn(); + accepts_task_fn(task_fn); + + // let task_fn = ::box_async_method.into_task_fn(); + // accepts_task_fn(task_fn); + // let task_fn = async_with_recv_and_str_and_lf.into_task_fn(); + // accepts_task_fn(task_fn); + } +} diff --git a/crates/turbo-tasks/Source/task/mod.rs b/crates/turbo-tasks/Source/task/mod.rs new file mode 100644 index 0000000000000..42a8f42e16704 --- /dev/null +++ b/crates/turbo-tasks/Source/task/mod.rs @@ -0,0 +1,17 @@ +pub(crate) mod concrete_task_input; +pub(crate) mod function; +pub(crate) mod task_input; +pub(crate) mod task_output; + +pub use concrete_task_input::ConcreteTaskInput; +pub use function::{ + AsyncFunctionMode, + AsyncMethodMode, + FunctionMode, + IntoTaskFn, + MethodMode, + NativeTaskFn, + TaskFn, +}; +pub use task_input::TaskInput; +pub use task_output::TaskOutput; diff --git a/crates/turbo-tasks/Source/task/task_input.rs b/crates/turbo-tasks/Source/task/task_input.rs new file mode 100644 index 0000000000000..5750286039fa6 --- /dev/null +++ b/crates/turbo-tasks/Source/task/task_input.rs @@ -0,0 +1,497 @@ +use std::{ + any::{Any, type_name}, + marker::PhantomData, + sync::Arc, +}; + +use anyhow::{Result, anyhow, bail}; + +use super::concrete_task_input::TransientSharedValue; +use crate::{ + ConcreteTaskInput, + RawVc, + RcStr, + SharedValue, + TaskId, + TransientInstance, + TransientValue, + TypedForInput, + Value, + ValueTypeId, + Vc, + VcValueType, + magic_any::MagicAny, +}; + +/// Trait to implement in order for a type to be accepted as a +/// `turbo_tasks::function` argument. +/// +/// See also [`ConcreteTaskInput`]. +pub trait TaskInput: Send + Sync + Clone { + fn try_from_concrete(input:&ConcreteTaskInput) -> Result; + fn into_concrete(self) -> ConcreteTaskInput; +} + +impl TaskInput for ConcreteTaskInput { + fn try_from_concrete(input:&ConcreteTaskInput) -> Result { Ok(input.clone()) } + + fn into_concrete(self) -> ConcreteTaskInput { self } +} + +impl TaskInput for RcStr { + fn try_from_concrete(input:&ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::String(s) => Ok(s.clone()), + _ => bail!("invalid task input type, expected String"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::String(self) } +} + +impl TaskInput for bool { + fn try_from_concrete(input:&ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::Bool(b) => Ok(*b), + _ => bail!("invalid task input type, expected Bool"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::Bool(self) } +} + +impl TaskInput for Vec +where + T: TaskInput, +{ + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::List(list) => { + Ok(list + .iter() + .map(|i| ::try_from_concrete(i)) + .collect::, _>>()?) + }, + _ => bail!("invalid task input type, expected List"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::List( + self.into_iter().map(|i| ::into_concrete(i)).collect::>(), + ) + } +} + +impl TaskInput for u8 { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U8(value) => Ok(*value), + _ => bail!("invalid task input type, expected U8"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::U8(self) } +} + +impl TaskInput for u16 { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U16(value) => Ok(*value), + _ => bail!("invalid task input type, expected U16"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::U16(self) } +} + +impl TaskInput for u32 { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U32(value) => Ok(*value), + _ => bail!("invalid task input type, expected U32"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::U32(self) } +} + +impl TaskInput for i32 { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::I32(value) => Ok(*value), + _ => bail!("invalid task input type, expected I32"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::I32(self) } +} + +impl TaskInput for u64 { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U64(value) => Ok(*value), + _ => bail!("invalid task input type, expected U64"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::U64(self) } +} + +impl TaskInput for usize { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::Usize(value) => Ok(*value), + _ => bail!("invalid task input type, expected Usize"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::Usize(self) } +} + +impl TaskInput for ValueTypeId { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U32(value) => Ok(ValueTypeId::from(*value)), + _ => bail!("invalid task input type, expected ValueTypeId"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::U32(*self) } +} + +impl TaskInput for TaskId { + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U32(value) => Ok(TaskId::from(*value)), + _ => bail!("invalid task input type, expected TaskId"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::U32(*self) } +} + +impl TaskInput for Option +where + T: TaskInput, +{ + fn try_from_concrete(value:&ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::Nothing => Ok(None), + _ => Ok(Some(::try_from_concrete(value)?)), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + match self { + None => ConcreteTaskInput::Nothing, + Some(value) => ::into_concrete(value), + } + } +} + +impl TaskInput for Vc +where + T: Send, +{ + fn try_from_concrete(input:&ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::TaskCell(task, index) => { + Ok(Vc { node:RawVc::TaskCell(*task, *index), _t:PhantomData }) + }, + ConcreteTaskInput::TaskOutput(task) => { + Ok(Vc { node:RawVc::TaskOutput(*task), _t:PhantomData }) + }, + _ => bail!("invalid task input type, expected RawVc"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + match self.node { + RawVc::TaskCell(task, index) => ConcreteTaskInput::TaskCell(task, index), + RawVc::TaskOutput(task) => ConcreteTaskInput::TaskOutput(task), + } + } +} + +impl TaskInput for Value +where + T: Any + + std::fmt::Debug + + Clone + + std::hash::Hash + + Eq + + Ord + + Send + + Sync + + VcValueType + + TypedForInput + + 'static, +{ + fn try_from_concrete(input:&ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::SharedValue(value) => { + let v = value.1.downcast_ref::().ok_or_else(|| { + anyhow!( + "invalid task input type, expected {} got {:?}", + type_name::(), + value.1, + ) + })?; + Ok(Value::new(v.clone())) + }, + _ => bail!("invalid task input type, expected {}", type_name::()), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + let raw_value:T = self.into_value(); + ConcreteTaskInput::SharedValue(SharedValue( + Some(T::get_value_type_id()), + Arc::new(raw_value), + )) + } +} + +impl TaskInput for TransientValue +where + T: MagicAny + Clone + 'static, +{ + fn try_from_concrete(input:&ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::TransientSharedValue(value) => { + let v = value.0.downcast_ref::().ok_or_else(|| { + anyhow!( + "invalid task input type, expected {} got {:?}", + type_name::(), + value.0, + ) + })?; + Ok(TransientValue::new(v.clone())) + }, + _ => bail!("invalid task input type, expected {}", type_name::()), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + let raw_value:T = self.into_value(); + ConcreteTaskInput::TransientSharedValue(TransientSharedValue(Arc::new(raw_value))) + } +} + +impl TaskInput for TransientInstance +where + T: Send + Sync + 'static, +{ + fn try_from_concrete(input:&ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::SharedReference(reference) => { + if let Ok(i) = reference.clone().try_into() { + Ok(i) + } else { + bail!( + "invalid task input type, expected {} got {:?}", + type_name::(), + reference.0, + ) + } + }, + _ => bail!("invalid task input type, expected {}", type_name::()), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { ConcreteTaskInput::SharedReference(self.into()) } +} + +macro_rules! tuple_impls { + ( $( $name:ident )+ ) => { + impl<$($name: TaskInput),+> TaskInput for ($($name,)+) + { + #[allow(non_snake_case)] + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::List(value) => { + let mut iter = value.iter(); + $( + let $name = iter.next().ok_or_else(|| anyhow!("missing tuple element"))?; + let $name = TaskInput::try_from_concrete($name)?; + )+ + Ok(($($name,)+)) + } + _ => bail!("invalid task input type, expected list"), + } + } + + #[allow(non_snake_case)] + fn into_concrete(self) -> ConcreteTaskInput { + let ($($name,)+) = self; + let ($($name,)+) = ($($name.into_concrete(),)+); + ConcreteTaskInput::List(vec![ $($name,)+ ]) + } + } + }; +} + +// Implement `TaskInput` for all tuples of 1 to 12 elements. +tuple_impls! { A } +tuple_impls! { A B } +tuple_impls! { A B C } +tuple_impls! { A B C D } +tuple_impls! { A B C D E } +tuple_impls! { A B C D E F } +tuple_impls! { A B C D E F G } +tuple_impls! { A B C D E F G H } +tuple_impls! { A B C D E F G H I } +tuple_impls! { A B C D E F G H I J } +tuple_impls! { A B C D E F G H I J K } +tuple_impls! { A B C D E F G H I J K L } + +#[cfg(test)] +mod tests { + use turbo_tasks_macros::TaskInput; + + use super::*; + // This is necessary for the derive macro to work, as its expansion refers to + // the crate name directly. + use crate as turbo_tasks; + + fn conversion(t:T) -> Result + where + T: TaskInput, { + TaskInput::try_from_concrete(&TaskInput::into_concrete(t)) + } + + macro_rules! test_conversion { + ($input:expr) => { + assert_eq!(conversion($input)?, $input); + }; + } + + #[test] + fn test_no_fields() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct NoFields; + + test_conversion!(NoFields); + Ok(()) + } + + #[test] + fn test_one_unnamed_field() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct OneUnnamedField(u32); + + test_conversion!(OneUnnamedField(42)); + Ok(()) + } + + #[test] + fn test_multiple_unnamed_fields() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct MultipleUnnamedFields(u32, RcStr); + + test_conversion!(MultipleUnnamedFields(42, "42".into())); + Ok(()) + } + + #[test] + fn test_one_named_field() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct OneNamedField { + named:u32, + } + + test_conversion!(OneNamedField { named:42 }); + Ok(()) + } + + #[test] + fn test_multiple_named_fields() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct MultipleNamedFields { + named:u32, + other:RcStr, + } + + test_conversion!(MultipleNamedFields { named:42, other:"42".into() }); + Ok(()) + } + + #[test] + fn test_generic_field() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct GenericField(T); + + test_conversion!(GenericField(42)); + test_conversion!(GenericField(RcStr::from("42"))); + Ok(()) + } + + #[test] + fn test_no_variant() -> Result<()> { + // This can't actually be tested at runtime because such an enum can't be + // constructed. However, the macro expansion is tested. + #[derive(Clone, TaskInput)] + enum NoVariants {} + Ok(()) + } + + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + enum OneVariant { + Variant, + } + + #[test] + fn test_one_variant() -> Result<()> { + test_conversion!(OneVariant::Variant); + Ok(()) + } + + #[test] + fn test_multiple_variants() -> Result<()> { + #[derive(Clone, TaskInput, PartialEq, Eq, Debug)] + enum MultipleVariants { + Variant1, + Variant2, + } + + test_conversion!(MultipleVariants::Variant2); + Ok(()) + } + + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + enum MultipleVariantsAndHeterogeneousFields { + Variant1, + Variant2(u32), + Variant3 { named:u32 }, + Variant4(u32, RcStr), + Variant5 { named:u32, other:RcStr }, + } + + #[test] + fn test_multiple_variants_and_heterogeneous_fields() -> Result<()> { + test_conversion!(MultipleVariantsAndHeterogeneousFields::Variant5 { + named:42, + other:"42".into() + }); + Ok(()) + } + + #[test] + fn test_nested_variants() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + enum NestedVariants { + Variant1, + Variant2(MultipleVariantsAndHeterogeneousFields), + Variant3 { named:OneVariant }, + Variant4(OneVariant, RcStr), + Variant5 { named:OneVariant, other:RcStr }, + } + + test_conversion!(NestedVariants::Variant5 { named:OneVariant::Variant, other:"42".into() }); + test_conversion!(NestedVariants::Variant2( + MultipleVariantsAndHeterogeneousFields::Variant5 { named:42, other:"42".into() } + )); + Ok(()) + } +} diff --git a/crates/turbo-tasks/Source/task/task_output.rs b/crates/turbo-tasks/Source/task/task_output.rs new file mode 100644 index 0000000000000..e4905e469d949 --- /dev/null +++ b/crates/turbo-tasks/Source/task/task_output.rs @@ -0,0 +1,47 @@ +use std::marker::PhantomData; + +use anyhow::Result; + +use crate::{RawVc, Vc}; + +/// Trait to implement in order for a type to be accepted as a +/// `turbo_tasks::function` return type. +pub trait TaskOutput { + type Return; + + fn try_from_raw_vc(raw_vc:RawVc) -> Self::Return; + fn try_into_raw_vc(self) -> Result; +} + +impl TaskOutput for Vc +where + T: ?Sized + Send, +{ + type Return = Vc; + + fn try_from_raw_vc(raw_vc:RawVc) -> Self::Return { Vc { node:raw_vc, _t:PhantomData } } + + fn try_into_raw_vc(self) -> Result { Ok(self.node) } +} + +impl TaskOutput for () { + type Return = Vc<()>; + + fn try_from_raw_vc(raw_vc:RawVc) -> Self::Return { raw_vc.into() } + + fn try_into_raw_vc(self) -> Result { + let unit = Vc::<()>::default(); + Ok(unit.node) + } +} + +impl TaskOutput for Result +where + T: TaskOutput, +{ + type Return = T::Return; + + fn try_from_raw_vc(raw_vc:RawVc) -> Self::Return { T::try_from_raw_vc(raw_vc) } + + fn try_into_raw_vc(self) -> Result { self?.try_into_raw_vc() } +} diff --git a/crates/turbo-tasks/Source/trace.rs b/crates/turbo-tasks/Source/trace.rs new file mode 100644 index 0000000000000..59c31c547f47c --- /dev/null +++ b/crates/turbo-tasks/Source/trace.rs @@ -0,0 +1,221 @@ +use std::{ + cell::RefCell, + collections::{BTreeMap, BTreeSet, HashMap, HashSet}, + path::{Path, PathBuf}, + sync::{Arc, Mutex, atomic::*}, + time::Duration, +}; + +use auto_hash_map::{AutoMap, AutoSet}; +use indexmap::{IndexMap, IndexSet}; + +use crate::{RawVc, RcStr}; + +pub struct TraceRawVcsContext { + list:Vec, +} + +impl TraceRawVcsContext { + pub(crate) fn new() -> Self { Self { list:Vec::new() } } + + pub(crate) fn into_vec(self) -> Vec { self.list } +} + +/// Trait that allows to walk data to find all [RawVc]s contained. +/// +/// This is important for Garbage Collection to mark all Cells and therefore +/// Tasks that are still in use. +/// +/// It can also be used to optimize transferring of Tasks, where knowning the +/// referenced Cells/Tasks allows pushing them earlier. +/// +/// `#[derive(TraceRawVcs)]` is available. +/// `#[trace_ignore]` can be used on fields to skip tracing for them. +pub trait TraceRawVcs { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext); + fn get_raw_vcs(&self) -> Vec { + let mut trace_context = TraceRawVcsContext::new(); + self.trace_raw_vcs(&mut trace_context); + trace_context.into_vec() + } +} + +macro_rules! ignore { + ($ty:ty) => { + impl TraceRawVcs for $ty { + fn trace_raw_vcs(&self, _context: &mut TraceRawVcsContext) {} + } + }; + + ($ty:ty, $($tys:ty),+) => { + ignore!($ty); + ignore!($($tys),+); + } +} + +ignore!(i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, char, bool, usize); +ignore!( + AtomicI8, + AtomicU8, + AtomicI16, + AtomicU16, + AtomicI32, + AtomicU32, + AtomicI64, + AtomicU64, + AtomicBool, + AtomicUsize +); +ignore!((), String, Duration, anyhow::Error, RcStr); +ignore!(Path, PathBuf); +ignore!(serde_json::Value); + +impl<'a> TraceRawVcs for &'a str { + fn trace_raw_vcs(&self, _trace_context:&mut TraceRawVcsContext) {} +} + +impl TraceRawVcs for (A,) { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + TraceRawVcs::trace_raw_vcs(&self.0, trace_context); + } +} + +impl TraceRawVcs for (A, B) { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + TraceRawVcs::trace_raw_vcs(&self.0, trace_context); + TraceRawVcs::trace_raw_vcs(&self.1, trace_context); + } +} + +impl TraceRawVcs for (A, B, C) { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + TraceRawVcs::trace_raw_vcs(&self.0, trace_context); + TraceRawVcs::trace_raw_vcs(&self.1, trace_context); + TraceRawVcs::trace_raw_vcs(&self.2, trace_context); + } +} + +impl TraceRawVcs for Option { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + if let Some(item) = self { + TraceRawVcs::trace_raw_vcs(item, trace_context); + } + } +} + +impl TraceRawVcs for Vec { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for item in self.iter() { + TraceRawVcs::trace_raw_vcs(item, trace_context); + } + } +} + +impl TraceRawVcs for HashSet { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for item in self.iter() { + TraceRawVcs::trace_raw_vcs(item, trace_context); + } + } +} + +impl TraceRawVcs for AutoSet { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for item in self.iter() { + TraceRawVcs::trace_raw_vcs(item, trace_context); + } + } +} + +impl TraceRawVcs for BTreeSet { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for item in self.iter() { + TraceRawVcs::trace_raw_vcs(item, trace_context); + } + } +} + +impl TraceRawVcs for IndexSet { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for item in self.iter() { + TraceRawVcs::trace_raw_vcs(item, trace_context); + } + } +} + +impl TraceRawVcs for HashMap { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for (key, value) in self.iter() { + TraceRawVcs::trace_raw_vcs(key, trace_context); + TraceRawVcs::trace_raw_vcs(value, trace_context); + } + } +} + +impl TraceRawVcs for AutoMap { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for (key, value) in self.iter() { + TraceRawVcs::trace_raw_vcs(key, trace_context); + TraceRawVcs::trace_raw_vcs(value, trace_context); + } + } +} + +impl TraceRawVcs for BTreeMap { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for (key, value) in self.iter() { + TraceRawVcs::trace_raw_vcs(key, trace_context); + TraceRawVcs::trace_raw_vcs(value, trace_context); + } + } +} + +impl TraceRawVcs for IndexMap { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + for (key, value) in self.iter() { + TraceRawVcs::trace_raw_vcs(key, trace_context); + TraceRawVcs::trace_raw_vcs(value, trace_context); + } + } +} + +impl TraceRawVcs for Box { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + TraceRawVcs::trace_raw_vcs(&**self, trace_context); + } +} + +impl TraceRawVcs for Arc { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + TraceRawVcs::trace_raw_vcs(&**self, trace_context); + } +} + +impl TraceRawVcs for RawVc { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + trace_context.list.push(*self); + } +} + +impl TraceRawVcs for Result { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + match self { + Ok(o) => o.trace_raw_vcs(trace_context), + Err(e) => e.trace_raw_vcs(trace_context), + } + } +} + +impl TraceRawVcs for Mutex { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + self.lock().unwrap().trace_raw_vcs(trace_context); + } +} + +impl TraceRawVcs for RefCell { + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + self.borrow().trace_raw_vcs(trace_context); + } +} + +pub use turbo_tasks_macros::TraceRawVcs; diff --git a/crates/turbo-tasks/Source/trait_ref.rs b/crates/turbo-tasks/Source/trait_ref.rs new file mode 100644 index 0000000000000..1abfa9318591b --- /dev/null +++ b/crates/turbo-tasks/Source/trait_ref.rs @@ -0,0 +1,139 @@ +use std::{fmt::Debug, future::Future, marker::PhantomData}; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; + +use crate::{ + RawVc, + ReadRawVcFuture, + SharedReference, + Vc, + VcValueTrait, + manager::find_cell_by_type, + vc::{VcValueTraitCast, cast::VcCast}, +}; + +/// Similar to a [`ReadRef`], but contains a value trait object instead. The +/// only way to interact with a `TraitRef` is by passing it around or turning +/// it back into a value trait vc by calling [`ReadRef::cell`]. +/// +/// Internally it stores a reference counted reference to a value on the heap. +pub struct TraitRef +where + T: ?Sized, { + shared_reference:SharedReference, + _t:PhantomData, +} + +impl Debug for TraitRef { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TraitRef") + .field("shared_reference", &self.shared_reference) + .finish() + } +} + +impl Clone for TraitRef { + fn clone(&self) -> Self { + Self { shared_reference:self.shared_reference.clone(), _t:PhantomData } + } +} + +impl PartialEq for TraitRef { + fn eq(&self, other:&Self) -> bool { self.shared_reference == other.shared_reference } +} + +impl Eq for TraitRef {} + +impl PartialOrd for TraitRef { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for TraitRef { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + self.shared_reference.cmp(&other.shared_reference) + } +} + +impl std::hash::Hash for TraitRef { + fn hash(&self, state:&mut H) { self.shared_reference.hash(state) } +} + +impl Serialize for TraitRef { + fn serialize(&self, serializer:S) -> Result { + self.shared_reference.serialize(serializer) + } +} + +impl<'de, T> Deserialize<'de> for TraitRef { + fn deserialize>(deserializer:D) -> Result { + Ok(Self { shared_reference:SharedReference::deserialize(deserializer)?, _t:PhantomData }) + } +} + +// Otherwise, TraitRef> would not be Sync. +// SAFETY: TraitRef doesn't actually contain a T. +unsafe impl Sync for TraitRef where T: ?Sized {} + +// Otherwise, TraitRef> would not be Send. +// SAFETY: TraitRef doesn't actually contain a T. +unsafe impl Send for TraitRef where T: ?Sized {} + +impl Unpin for TraitRef where T: ?Sized {} + +impl TraitRef +where + T: ?Sized, +{ + pub(crate) fn new(shared_reference:SharedReference) -> Self { + Self { shared_reference, _t:PhantomData } + } +} + +impl TraitRef +where + T: VcValueTrait + ?Sized + Send, +{ + /// Returns a new cell that points to a value that implements the value + /// trait `T`. + pub fn cell(trait_ref:TraitRef) -> Vc { + // See Safety clause above. + let SharedReference(ty, _) = trait_ref.shared_reference; + let ty = ty.unwrap(); + let local_cell = find_cell_by_type(ty); + local_cell.update_shared_reference(trait_ref.shared_reference); + let raw_vc:RawVc = local_cell.into(); + raw_vc.into() + } +} + +/// A trait that allows a value trait vc to be converted into a trait reference. +/// +/// The signature is similar to `IntoFuture`, but we don't want trait vcs to +/// have the same future-like semantics as value vcs when it comes to producing +/// refs. This behavior is rarely needed, so in most cases, `.await`ing a trait +/// vc is a mistake. +pub trait IntoTraitRef { + type ValueTrait: VcValueTrait + ?Sized; + type Future: Future as VcCast>::Output>>; + + fn into_trait_ref(self) -> Self::Future; + fn into_trait_ref_untracked(self) -> Self::Future; + fn into_trait_ref_strongly_consistent_untracked(self) -> Self::Future; +} + +impl IntoTraitRef for Vc +where + T: VcValueTrait + ?Sized + Send, +{ + type Future = ReadRawVcFuture>; + type ValueTrait = T; + + fn into_trait_ref(self) -> Self::Future { self.node.into_trait_read::() } + + fn into_trait_ref_untracked(self) -> Self::Future { self.node.into_trait_read_untracked::() } + + fn into_trait_ref_strongly_consistent_untracked(self) -> Self::Future { + self.node.into_strongly_consistent_trait_read_untracked::() + } +} diff --git a/crates/turbo-tasks/Source/util.rs b/crates/turbo-tasks/Source/util.rs new file mode 100644 index 0000000000000..cacd9c6726a88 --- /dev/null +++ b/crates/turbo-tasks/Source/util.rs @@ -0,0 +1,220 @@ +use std::{ + error::Error as StdError, + fmt::{Debug, Display}, + future::Future, + hash::{Hash, Hasher}, + ops::Deref, + pin::Pin, + sync::Arc, + task::{Context, Poll}, + time::Duration, +}; + +use anyhow::{Error, anyhow}; +use pin_project_lite::pin_project; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +pub use super::{id_factory::IdFactory, no_move_vec::NoMoveVec, once_map::*}; + +/// A error struct that is backed by an Arc to allow cloning errors +#[derive(Debug, Clone)] +pub struct SharedError { + inner:Arc, +} + +impl SharedError { + pub fn new(err:Error) -> Self { Self { inner:Arc::new(err) } } +} + +impl StdError for SharedError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { self.inner.source() } + + fn provide<'a>(&'a self, req:&mut std::error::Request<'a>) { self.inner.provide(req); } +} + +impl Display for SharedError { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Display::fmt(&*self.inner, f) + } +} + +impl From for SharedError { + fn from(e:Error) -> Self { Self::new(e) } +} + +impl PartialEq for SharedError { + fn eq(&self, other:&Self) -> bool { Arc::ptr_eq(&self.inner, &other.inner) } +} + +impl Eq for SharedError {} + +impl Serialize for SharedError { + fn serialize(&self, serializer:S) -> Result { + let mut v = vec![self.to_string()]; + let mut source = self.source(); + while let Some(s) = source { + v.push(s.to_string()); + source = s.source(); + } + Serialize::serialize(&v, serializer) + } +} + +impl<'de> Deserialize<'de> for SharedError { + fn deserialize>(deserializer:D) -> Result { + use serde::de::Error; + let mut messages = >::deserialize(deserializer)?; + let mut e = match messages.pop() { + Some(e) => anyhow!(e), + None => return Err(Error::custom("expected at least 1 error message")), + }; + while let Some(message) = messages.pop() { + e = e.context(message); + } + Ok(SharedError::new(e)) + } +} + +impl Deref for SharedError { + type Target = Arc; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +pub struct FormatDuration(pub Duration); + +impl Display for FormatDuration { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = self.0.as_secs(); + if s > 10 { + return write!(f, "{}s", s); + } + let ms = self.0.as_millis(); + if ms > 10 { + return write!(f, "{}ms", ms); + } + write!(f, "{}ms", (self.0.as_micros() as f32) / 1000.0) + } +} + +impl Debug for FormatDuration { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = self.0.as_secs(); + if s > 100 { + return write!(f, "{}s", s); + } + let ms = self.0.as_millis(); + if ms > 10000 { + return write!(f, "{:.2}s", (ms as f32) / 1000.0); + } + if ms > 100 { + return write!(f, "{}ms", ms); + } + write!(f, "{}ms", (self.0.as_micros() as f32) / 1000.0) + } +} + +pub struct FormatBytes(pub usize); + +impl Display for FormatBytes { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let b = self.0; + const KB:usize = 1_024; + const MB:usize = 1_024 * KB; + const GB:usize = 1_024 * MB; + if b > GB { + return write!(f, "{:.2}GiB", ((b / MB) as f32) / 1_024.0); + } + if b > MB { + return write!(f, "{:.2}MiB", ((b / KB) as f32) / 1_024.0); + } + if b > KB { + return write!(f, "{:.2}KiB", (b as f32) / 1_024.0); + } + write!(f, "{}B", b) + } +} + +/// Smart pointer that stores data either in an [Arc] or as a static reference. +pub enum StaticOrArc { + Static(&'static T), + Shared(Arc), +} + +impl AsRef for StaticOrArc { + fn as_ref(&self) -> &T { + match self { + Self::Static(s) => s, + Self::Shared(b) => b, + } + } +} + +impl From<&'static T> for StaticOrArc { + fn from(s:&'static T) -> Self { Self::Static(s) } +} + +impl From> for StaticOrArc { + fn from(b:Arc) -> Self { Self::Shared(b) } +} + +impl From for StaticOrArc { + fn from(b:T) -> Self { Self::Shared(Arc::new(b)) } +} + +impl Deref for StaticOrArc { + type Target = T; + + fn deref(&self) -> &Self::Target { self.as_ref() } +} + +impl Clone for StaticOrArc { + fn clone(&self) -> Self { + match self { + Self::Static(s) => Self::Static(s), + Self::Shared(b) => Self::Shared(b.clone()), + } + } +} + +impl PartialEq for StaticOrArc { + fn eq(&self, other:&Self) -> bool { **self == **other } +} + +impl Eq for StaticOrArc {} + +impl Hash for StaticOrArc { + fn hash(&self, state:&mut H) { (**self).hash(state); } +} + +impl Display for StaticOrArc { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { (**self).fmt(f) } +} + +impl Debug for StaticOrArc { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { (**self).fmt(f) } +} + +pin_project! { + /// A future that wraps another future and applies a function on every poll call. + pub struct WrapFuture { + wrapper: W, + #[pin] + future: F, + } +} + +impl Fn(Pin<&mut F>, &mut Context<'a>) -> Poll> WrapFuture { + pub fn new(future:F, wrapper:W) -> Self { Self { wrapper, future } } +} + +impl Fn(Pin<&mut F>, &mut Context<'a>) -> Poll> Future + for WrapFuture +{ + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx:&mut Context<'_>) -> Poll { + let this = self.project(); + (this.wrapper)(this.future, cx) + } +} diff --git a/crates/turbo-tasks/Source/value.rs b/crates/turbo-tasks/Source/value.rs new file mode 100644 index 0000000000000..399cc5667b412 --- /dev/null +++ b/crates/turbo-tasks/Source/value.rs @@ -0,0 +1,122 @@ +use std::{fmt::Debug, marker::PhantomData, ops::Deref, sync::Arc}; + +use crate::SharedReference; + +/// Pass a value by value (`Value`) instead of by reference (`Vc`). +/// +/// Persistent, requires serialization. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] +pub struct Value { + inner:T, +} + +impl Value { + pub fn new(value:T) -> Self { Self { inner:value } } + + pub fn into_value(self) -> T { self.inner } +} + +impl Deref for Value { + type Target = T; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl Copy for Value {} + +impl Default for Value { + fn default() -> Self { Value::new(Default::default()) } +} + +/// Pass a value by value (`Value`) instead of by reference (`Vc`). +/// +/// Doesn't require serialization, and won't be stored in the persistent cache +/// in the future. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] +pub struct TransientValue { + inner:T, +} + +impl TransientValue { + pub fn new(value:T) -> Self { Self { inner:value } } + + pub fn into_value(self) -> T { self.inner } +} + +impl Deref for TransientValue { + type Target = T; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +/// Pass a reference to an instance to a turbo-tasks function. +/// +/// Equality and hash is implemented as pointer comparison. +/// +/// Doesn't require serialization, and won't be stored in the persistent cache +/// in the future. +#[derive(Debug)] +pub struct TransientInstance { + inner:SharedReference, + phantom:PhantomData, +} + +impl Clone for TransientInstance { + fn clone(&self) -> Self { Self { inner:self.inner.clone(), phantom:self.phantom } } +} + +impl Eq for TransientInstance {} + +impl PartialEq for TransientInstance { + fn eq(&self, other:&Self) -> bool { self.inner == other.inner } +} + +impl std::hash::Hash for TransientInstance { + fn hash(&self, state:&mut H) { self.inner.hash(state); } +} + +impl PartialOrd for TransientInstance { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for TransientInstance { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { self.inner.cmp(&other.inner) } +} + +impl From> for Arc { + fn from(instance:TransientInstance) -> Self { + Arc::downcast(instance.inner.1.clone()).unwrap() + } +} + +impl From> for SharedReference { + fn from(instance:TransientInstance) -> Self { instance.inner } +} + +impl From> for TransientInstance { + fn from(arc:Arc) -> Self { Self { inner:SharedReference(None, arc), phantom:PhantomData } } +} + +impl TryFrom for TransientInstance { + type Error = (); + + fn try_from(inner:SharedReference) -> Result { + if inner.1.downcast_ref::().is_some() { + Ok(Self { inner, phantom:PhantomData }) + } else { + Err(()) + } + } +} + +impl TransientInstance { + pub fn new(value:T) -> Self { + Self { inner:SharedReference(None, Arc::new(value)), phantom:PhantomData } + } +} + +impl Deref for TransientInstance { + type Target = T; + + fn deref(&self) -> &Self::Target { self.inner.1.downcast_ref().unwrap() } +} diff --git a/crates/turbo-tasks/Source/value_type.rs b/crates/turbo-tasks/Source/value_type.rs new file mode 100644 index 0000000000000..9d4f23bb8f88a --- /dev/null +++ b/crates/turbo-tasks/Source/value_type.rs @@ -0,0 +1,236 @@ +use std::{ + any::{Any, type_name}, + borrow::Cow, + fmt::{ + Debug, + Display, + Formatter, + {self}, + }, + hash::Hash, + sync::Arc, +}; + +use auto_hash_map::{AutoMap, AutoSet}; +use serde::{Deserialize, Serialize}; +use tracing::Span; + +use crate::{ + id::{FunctionId, TraitTypeId}, + magic_any::{AnyDeserializeSeed, MagicAny, MagicAnyDeserializeSeed}, + registry::{register_trait_type, register_value_type}, +}; + +type MagicSerializationFn = fn(&dyn MagicAny) -> &dyn erased_serde::Serialize; +type AnySerializationFn = fn(&(dyn Any + Sync + Send)) -> &dyn erased_serde::Serialize; + +// TODO this type need some refactoring when multiple languages are added to +// turbo-task In this case a trait_method might be of a different function type. +// It probably need to be a Vc. +// That's also needed in a distributed world, where the function might be only +// available on a remote instance. + +/// A definition of a type of data. +/// +/// Contains a list of traits and trait methods that are available on that type. +pub struct ValueType { + /// A readable name of the type + pub name:String, + /// List of traits available + pub traits:AutoSet, + /// List of trait methods available + pub trait_methods:AutoMap<(TraitTypeId, Cow<'static, str>), FunctionId>, + + /// Functors for serialization + magic_serialization:Option<(MagicSerializationFn, MagicAnyDeserializeSeed)>, + any_serialization:Option<(AnySerializationFn, AnyDeserializeSeed)>, +} + +impl Hash for ValueType { + fn hash(&self, state:&mut H) { (self as *const ValueType).hash(state); } +} + +impl Eq for ValueType {} + +impl PartialEq for ValueType { + fn eq(&self, other:&Self) -> bool { std::ptr::eq(self, other) } +} + +impl PartialOrd for ValueType { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} +impl Ord for ValueType { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + (self as *const ValueType).cmp(&(other as *const ValueType)) + } +} + +impl Debug for ValueType { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { + let mut d = f.debug_struct("ValueType"); + d.field("name", &self.name); + for ((_trait_type, name), _value) in self.trait_methods.iter() { + d.field(name, &"(trait fn)"); + } + d.finish() + } +} + +pub fn any_as_serialize( + this:&(dyn Any + Send + Sync), +) -> &dyn erased_serde::Serialize { + if let Some(r) = this.downcast_ref::() { + return r; + } + panic!("any_as_serialize::<{}> called with invalid type", type_name::()); +} + +impl ValueType { + /// This is internally used by `#[turbo_tasks::value]` + pub fn new() -> Self { + Self { + name:std::any::type_name::().to_string(), + traits:AutoSet::new(), + trait_methods:AutoMap::new(), + magic_serialization:None, + any_serialization:None, + } + } + + /// This is internally used by `#[turbo_tasks::value]` + pub fn new_with_magic_serialization< + T:Debug + Eq + Ord + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static, + >() -> Self { + Self { + name:std::any::type_name::().to_string(), + traits:AutoSet::new(), + trait_methods:AutoMap::new(), + magic_serialization:Some(( + ::as_serialize::, + MagicAnyDeserializeSeed::new::(), + )), + any_serialization:Some((any_as_serialize::, AnyDeserializeSeed::new::())), + } + } + + /// This is internally used by `#[turbo_tasks::value]` + pub fn new_with_any_serialization< + T:Any + Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static, + >() -> Self { + Self { + name:std::any::type_name::().to_string(), + traits:AutoSet::new(), + trait_methods:AutoMap::new(), + magic_serialization:None, + any_serialization:Some((any_as_serialize::, AnyDeserializeSeed::new::())), + } + } + + pub fn magic_as_serializable<'a>( + &self, + arc:&'a Arc, + ) -> Option<&'a dyn erased_serde::Serialize> { + if let Some(s) = self.magic_serialization { + let r:&dyn MagicAny = arc; + Some((s.0)(r)) + } else { + None + } + } + + pub fn any_as_serializable<'a>( + &self, + arc:&'a Arc, + ) -> Option<&'a dyn erased_serde::Serialize> { + if let Some(s) = self.any_serialization { Some((s.0)(&**arc)) } else { None } + } + + pub fn get_magic_deserialize_seed(&self) -> Option { + self.magic_serialization.map(|s| s.1) + } + + pub fn get_any_deserialize_seed(&self) -> Option { + self.any_serialization.map(|s| s.1) + } + + /// This is internally used by `#[turbo_tasks::value_impl]` + pub fn register_trait_method( + &mut self, + trait_type:TraitTypeId, + name:Cow<'static, str>, + native_fn:FunctionId, + ) { + self.trait_methods.insert((trait_type, name), native_fn); + } + + pub fn get_trait_method( + &self, + trait_method_key:&(TraitTypeId, Cow<'static, str>), + ) -> Option<&FunctionId> { + self.trait_methods.get(trait_method_key) + } + + /// This is internally used by `#[turbo_tasks::value_impl]` + pub fn register_trait(&mut self, trait_type:TraitTypeId) { self.traits.insert(trait_type); } + + pub fn has_trait(&self, trait_type:&TraitTypeId) -> bool { self.traits.contains(trait_type) } + + pub fn traits_iter(&self) -> impl Iterator + '_ { + self.traits.iter().copied() + } + + pub fn register(&'static self, global_name:&'static str) { + register_value_type(global_name, self) + } +} + +#[derive(Debug)] +pub struct TraitType { + pub name:String, + pub(crate) default_trait_methods:AutoMap, FunctionId>, +} + +impl Hash for TraitType { + fn hash(&self, state:&mut H) { (self as *const TraitType).hash(state); } +} + +impl Display for TraitType { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { write!(f, "trait {}", self.name) } +} + +impl Eq for TraitType {} + +impl PartialEq for TraitType { + fn eq(&self, other:&Self) -> bool { std::ptr::eq(self, other) } +} + +impl PartialOrd for TraitType { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for TraitType { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + (self as *const TraitType).cmp(&(other as *const TraitType)) + } +} + +impl TraitType { + pub fn new(name:String) -> Self { Self { name, default_trait_methods:AutoMap::new() } } + + pub fn register_default_trait_method(&mut self, name:Cow<'static, str>, native_fn:FunctionId) { + self.default_trait_methods.insert(name, native_fn); + } + + pub fn register(&'static self, global_name:&'static str) { + register_trait_type(global_name, self); + } + + pub fn resolve_span(&'static self, name:&str) -> Span { + tracing::trace_span!( + "turbo_tasks::resolve_trait_call", + name = format_args!("{}::{name}", &self.name), + ) + } +} + +pub trait TraitMethod: Any {} diff --git a/crates/turbo-tasks/Source/vc/cast.rs b/crates/turbo-tasks/Source/vc/cast.rs new file mode 100644 index 0000000000000..95f1f219aa82e --- /dev/null +++ b/crates/turbo-tasks/Source/vc/cast.rs @@ -0,0 +1,63 @@ +use std::{marker::PhantomData, mem::ManuallyDrop}; + +use anyhow::Result; + +use crate::{ReadRef, TraitRef, VcRead, VcValueTrait, VcValueType, backend::CellContent}; + +/// Trait defined to share behavior between values and traits within +/// [`ReadRawVcFuture`]. See [`ValueCast`] and [`TraitCast`]. +/// +/// This should not be implemented by users. +pub trait VcCast { + type Output; + + fn cast(content:CellContent) -> Result; +} + +/// Casts an arbitrary cell content into a [`ReadRef`]. +pub struct VcValueTypeCast { + _phantom:PhantomData, +} + +impl VcCast for VcValueTypeCast +where + T: VcValueType, +{ + type Output = ReadRef; + + fn cast(content:CellContent) -> Result { + Ok( + // Safety: the `VcValueType` implementor must guarantee that both `T` and + // `Repr` are #[repr(transparent)]. + unsafe { + // Downcast the cell content to the expected representation type, then + // transmute it to the expected type. + // See https://users.rust-lang.org/t/transmute-doesnt-work-on-generic-types/87272/9 + std::mem::transmute_copy::< + ManuallyDrop>::Repr>>, + Self::Output, + >(&ManuallyDrop::new(content.cast::<>::Repr>()?)) + }, + ) + } +} + +/// Casts an arbitrary cell content into a [`TraitRef`]. +pub struct VcValueTraitCast +where + T: ?Sized, { + _phantom:PhantomData, +} + +impl VcCast for VcValueTraitCast +where + T: VcValueTrait + ?Sized, +{ + type Output = TraitRef; + + fn cast(content:CellContent) -> Result { + // Safety: Constructor ensures the cell content points to a value that + // implements T + content.cast_trait::() + } +} diff --git a/crates/turbo-tasks/Source/vc/cell_mode.rs b/crates/turbo-tasks/Source/vc/cell_mode.rs new file mode 100644 index 0000000000000..86cff5cc56004 --- /dev/null +++ b/crates/turbo-tasks/Source/vc/cell_mode.rs @@ -0,0 +1,47 @@ +use std::marker::PhantomData; + +use super::{read::VcRead, traits::VcValueType}; +use crate::{Vc, manager::find_cell_by_type}; + +/// Trait that controls the behavior of `Vc::cell` on a value type basis. +/// +/// This trait must remain sealed within this crate. +pub trait VcCellMode +where + T: VcValueType, { + fn cell(value:>::Target) -> Vc; +} + +/// Mode that always updates the cell's content. +pub struct VcCellNewMode { + _phantom:PhantomData, +} + +impl VcCellMode for VcCellNewMode +where + T: VcValueType, +{ + fn cell(inner:>::Target) -> Vc { + let cell = find_cell_by_type(T::get_value_type_id()); + cell.update_shared(>::target_to_repr(inner)); + Vc { node:cell.into(), _t:PhantomData } + } +} + +/// Mode that compares the cell's content with the new value and only updates +/// if the new value is different. +pub struct VcCellSharedMode { + _phantom:PhantomData, +} + +impl VcCellMode for VcCellSharedMode +where + T: VcValueType, + <::Read as VcRead>::Repr: PartialEq, +{ + fn cell(inner:>::Target) -> Vc { + let cell = find_cell_by_type(T::get_value_type_id()); + cell.compare_and_update_shared(>::target_to_repr(inner)); + Vc { node:cell.into(), _t:PhantomData } + } +} diff --git a/crates/turbo-tasks/Source/vc/default.rs b/crates/turbo-tasks/Source/vc/default.rs new file mode 100644 index 0000000000000..7e512ef5c9027 --- /dev/null +++ b/crates/turbo-tasks/Source/vc/default.rs @@ -0,0 +1,19 @@ +use turbo_tasks::Vc; + +use crate::{self as turbo_tasks}; + +/// `Vc` analog to the `Default` trait. +/// +/// Implementing this trait on `T` will make `Vc::default()` produce +/// `T::value_default()`. +/// +/// There are two ways to implement this trait: +/// 1. Annotating with `#[turbo_tasks::value_impl]`: this will make +/// `Vc::default()` always return the same underlying value (i.e. a +/// singleton). +/// 2. No annotations: this will make `Vc::default()` always return a different +/// value. +#[turbo_tasks::value_trait] +pub trait ValueDefault { + fn value_default() -> Vc; +} diff --git a/crates/turbo-tasks/Source/vc/mod.rs b/crates/turbo-tasks/Source/vc/mod.rs new file mode 100644 index 0000000000000..5a7791a9051b6 --- /dev/null +++ b/crates/turbo-tasks/Source/vc/mod.rs @@ -0,0 +1,491 @@ +pub(crate) mod cast; +mod cell_mode; +pub(crate) mod default; +mod read; +mod traits; + +use std::{any::Any, marker::PhantomData, ops::Deref}; + +use anyhow::Result; +use auto_hash_map::AutoSet; +use serde::{Deserialize, Serialize}; + +use self::cell_mode::VcCellMode; +pub use self::{ + cast::{VcValueTraitCast, VcValueTypeCast}, + cell_mode::{VcCellNewMode, VcCellSharedMode}, + default::ValueDefault, + read::{VcDefaultRead, VcRead, VcTransparentRead}, + traits::{Dynamic, TypedForInput, Upcast, VcValueTrait, VcValueType}, +}; +use crate::{ + CellId, + CollectiblesSource, + RawVc, + ReadRawVcFuture, + ResolveTypeError, + debug::{ValueDebug, ValueDebugFormat, ValueDebugFormatString}, + registry, + trace::{TraceRawVcs, TraceRawVcsContext}, +}; + +/// A Value Cell (`Vc` for short) is a reference to a memoized computation +/// result stored on the heap or in persistent cache, depending on the +/// Turbo Engine backend implementation. +/// +/// In order to get a reference to the pointed value, you need to `.await` the +/// [`Vc`] to get a [`ReadRef`]: +/// +/// ``` +/// let some_vc:Vc; +/// let some_ref:ReadRef = some_vc.await?; +/// some_ref.some_method_on_t(); +/// ``` +#[must_use] +pub struct Vc +where + T: ?Sized + Send, { + pub(crate) node:RawVc, + #[doc(hidden)] + pub(crate) _t:PhantomData, +} + +/// This only exists to satisfy the Rust type system. However, this struct can +/// never actually be instantiated, as dereferencing a `Vc` will result in a +/// linker error. See the implementation of `Deref` for `Vc`. +pub struct VcDeref +where + T: ?Sized, { + _t:PhantomData, +} + +macro_rules! do_not_use_or_you_will_be_fired { + ($($name:ident)*) => { + impl VcDeref + where + T: ?Sized, + { + $( + #[doc(hidden)] + #[allow(unused)] + #[allow(clippy::wrong_self_convention)] + #[deprecated = "This is not the method you are looking for."] + pub fn $name(self) {} + )* + } + }; +} + +// Hide raw pointer methods on `Vc`. This is an artifact of having +// implement `Deref` on `Vc` for `arbitrary_self_types` to +// do its thing. This can be removed once the `Receiver` trait no longer depends +// on `Deref`. +do_not_use_or_you_will_be_fired!( + add + addr + align_offset + as_mut + as_mut_ptr + as_ptr + as_ref + as_uninit_mut + as_uninit_ref + as_uninit_slice + as_uninit_slice_mut + byte_add + byte_offset + byte_offset_from + byte_sub + cast + cast_const + cast_mut + copy_from + copy_from_nonoverlapping + copy_to + copy_to_nonoverlapping + drop_in_place + expose_addr + from_bits + get_unchecked + get_unchecked_mut + guaranteed_eq + guaranteed_ne + is_aligned + is_aligned_to + is_empty + is_null + len + map_addr + mask + offset + offset_from + read + read_unaligned + read_volatile + replace + split_at_mut + split_at_mut_unchecked + sub + sub_ptr + swap + to_bits + to_raw_parts + with_addr + with_metadata_of + wrapping_add + wrapping_byte_add + wrapping_byte_offset + wrapping_byte_sub + wrapping_offset + wrapping_sub + write + write_bytes + write_unaligned + write_volatile +); + +// Call this macro for all the applicable methods above: + +#[doc(hidden)] +impl Deref for VcDeref +where + T: ?Sized, +{ + // `*const T` or `*mut T` would be enough here, but from an abundance of + // caution, we use `*const *mut *const T` to make sure there will never be an + // applicable method. + type Target = *const *mut *const T; + + fn deref(&self) -> &Self::Target { + extern { + #[link_name = "\n\nERROR: you tried to dereference a `Vc`\n"] + fn trigger() -> !; + } + + unsafe { trigger() }; + } +} + +// This is the magic that makes `Vc` accept `self: Vc` methods through +// `arbitrary_self_types`, while not allowing any other receiver type: +// * `Vc` dereferences to `*const *mut *const T`, which means that it is +// valid under the `arbitrary_self_types` rules. +// * `*const *mut *const T` is not a valid receiver for any attribute access on +// `T`, which means that the only applicable items will be the methods +// declared on `self: Vc`. +// +// If we had used `type Target = T` instead, `vc_t.some_attr_defined_on_t` would +// have been accepted by the compiler. +#[doc(hidden)] +impl Deref for Vc +where + T: ?Sized + Send, +{ + type Target = VcDeref; + + fn deref(&self) -> &Self::Target { + extern { + #[link_name = "\n\nERROR: you tried to dereference a `Vc`\n"] + fn trigger() -> !; + } + + unsafe { trigger() }; + } +} + +impl Copy for Vc where T: ?Sized + Send {} + +unsafe impl Send for Vc where T: ?Sized + Send {} +unsafe impl Sync for Vc where T: ?Sized + Send {} + +impl Clone for Vc +where + T: ?Sized + Send, +{ + fn clone(&self) -> Self { *self } +} + +impl core::hash::Hash for Vc +where + T: ?Sized + Send, +{ + fn hash(&self, state:&mut H) { self.node.hash(state); } +} + +impl PartialEq> for Vc +where + T: ?Sized + Send, +{ + fn eq(&self, other:&Self) -> bool { self.node == other.node } +} + +impl Eq for Vc where T: ?Sized + Send {} + +impl PartialOrd> for Vc +where + T: ?Sized + Send, +{ + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for Vc +where + T: ?Sized + Send, +{ + fn cmp(&self, other:&Self) -> std::cmp::Ordering { self.node.cmp(&other.node) } +} + +impl Serialize for Vc +where + T: ?Sized + Send, +{ + fn serialize(&self, serializer:S) -> Result { + self.node.serialize(serializer) + } +} + +impl<'de, T> Deserialize<'de> for Vc +where + T: ?Sized + Send, +{ + fn deserialize>(deserializer:D) -> Result { + Ok(Vc { node:RawVc::deserialize(deserializer)?, _t:PhantomData }) + } +} + +// TODO(alexkirsz) This should not be implemented for Vc. Instead, users should +// use the `ValueDebug` implementation to get a `D: Debug`. +impl std::fmt::Debug for Vc +where + T: Send, +{ + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Vc").field("node", &self.node).finish() + } +} + +impl Vc +where + T: VcValueType, +{ + #[doc(hidden)] + pub fn cell_private(inner:>::Target) -> Self { + >::cell(inner) + } +} + +impl Vc +where + T: VcValueType>, + Inner: Any + Send + Sync, + Repr: VcValueType, +{ + pub fn cell(inner:Inner) -> Self { >::cell(inner) } +} + +impl Vc +where + T: ?Sized + Send, +{ + /// Connects the operation pointed to by this `Vc` to the current task. + pub fn connect(vc:Self) { vc.node.connect() } + + /// Returns a debug identifier for this `Vc`. + pub async fn debug_identifier(vc:Self) -> Result { + let resolved = vc.resolve().await?; + let raw_vc:RawVc = resolved.node; + if let RawVc::TaskCell(task_id, CellId { type_id, index }) = raw_vc { + let value_ty = registry::get_value_type(type_id); + Ok(format!("{}#{}: {}", value_ty.name, index, task_id)) + } else { + unreachable!() + } + } + + /// Returns the `RawVc` corresponding to this `Vc`. + pub fn into_raw(vc:Self) -> RawVc { vc.node } + + /// Creates a `Vc` from a `RawVc`. + /// + /// # Safety + /// + /// The caller must ensure that `RawVc` points to a value of type `T`. + pub(crate) unsafe fn from_raw(vc:RawVc) -> Self { Vc { node:vc, _t:std::marker::PhantomData } } + + /// Upcasts the given `Vc` to a `Vc>`. + /// + /// This is also available as an `Into`/`From` conversion. + #[inline(always)] + pub fn upcast(vc:Self) -> Vc + where + T: Upcast, + K: VcValueTrait + ?Sized + Send, { + Vc { node:vc.node, _t:PhantomData } + } +} + +impl Vc +where + T: ?Sized + Send, +{ + /// Resolve the reference until it points to a cell directly. + /// + /// Resolving will wait for task execution to be finished, so that the + /// returned `Vc` points to a cell that stores a value. + /// + /// Resolving is necessary to compare identities of `Vc`s. + /// + /// This is async and will rethrow any fatal error that happened during task + /// execution. + pub async fn resolve(self) -> Result { + Ok(Self { node:self.node.resolve().await?, _t:PhantomData }) + } + + /// Resolve the reference until it points to a cell directly in a strongly + /// consistent way. + /// + /// Resolving will wait for task execution to be finished, so that the + /// returned Vc points to a cell that stores a value. + /// + /// Resolving is necessary to compare identities of Vcs. + /// + /// This is async and will rethrow any fatal error that happened during task + /// execution. + pub async fn resolve_strongly_consistent(self) -> Result { + Ok(Self { node:self.node.resolve_strongly_consistent().await?, _t:PhantomData }) + } +} + +impl Vc +where + T: VcValueTrait + ?Sized + Send, +{ + /// Attempts to sidecast the given `Vc>` to a `Vc>`. + /// This operation also resolves the `Vc`. + /// + /// Returns `None` if the underlying value type does not implement `K`. + /// + /// **Note:** if the trait T is required to implement K, use + /// `Vc::upcast(vc).resolve()` instead. This provides stronger guarantees, + /// removing the need for a `Result` return type. + pub async fn try_resolve_sidecast(vc:Self) -> Result>, ResolveTypeError> + where + K: VcValueTrait + ?Sized + Send, { + let raw_vc:RawVc = vc.node; + let raw_vc = raw_vc.resolve_trait(::get_trait_type_id()).await?; + Ok(raw_vc.map(|raw_vc| Vc { node:raw_vc, _t:PhantomData })) + } + + /// Attempts to downcast the given `Vc>` to a `Vc`, where `K` + /// is of the form `Box`, and `L` is a value trait. + /// This operation also resolves the `Vc`. + /// + /// Returns `None` if the underlying value type is not a `K`. + pub async fn try_resolve_downcast(vc:Self) -> Result>, ResolveTypeError> + where + K: Upcast, + K: VcValueTrait + ?Sized + Send, { + let raw_vc:RawVc = vc.node; + let raw_vc = raw_vc.resolve_trait(::get_trait_type_id()).await?; + Ok(raw_vc.map(|raw_vc| Vc { node:raw_vc, _t:PhantomData })) + } + + /// Attempts to downcast the given `Vc>` to a `Vc`, where `K` + /// is a value type. + /// This operation also resolves the `Vc`. + /// + /// Returns `None` if the underlying value type is not a `K`. + pub async fn try_resolve_downcast_type(vc:Self) -> Result>, ResolveTypeError> + where + K: Upcast, + K: VcValueType, { + let raw_vc:RawVc = vc.node; + let raw_vc = raw_vc.resolve_value(::get_value_type_id()).await?; + Ok(raw_vc.map(|raw_vc| Vc { node:raw_vc, _t:PhantomData })) + } +} + +impl CollectiblesSource for Vc +where + T: ?Sized + Send, +{ + fn take_collectibles(self) -> AutoSet> { + self.node.take_collectibles() + } + + fn peek_collectibles(self) -> AutoSet> { + self.node.peek_collectibles() + } +} + +impl From for Vc +where + T: ?Sized + Send, +{ + fn from(node:RawVc) -> Self { Self { node, _t:PhantomData } } +} + +impl TraceRawVcs for Vc +where + T: ?Sized + Send, +{ + fn trace_raw_vcs(&self, trace_context:&mut TraceRawVcsContext) { + TraceRawVcs::trace_raw_vcs(&self.node, trace_context); + } +} + +impl ValueDebugFormat for Vc +where + T: ?Sized + Send, + T: Upcast>, +{ + fn value_debug_format(&self, depth:usize) -> ValueDebugFormatString { + ValueDebugFormatString::Async(Box::pin(async move { + Ok({ + let vc_value_debug = Vc::upcast::>(*self); + vc_value_debug.dbg_depth(depth).await?.to_string() + }) + })) + } +} + +impl std::future::IntoFuture for Vc +where + T: VcValueType, +{ + type IntoFuture = ReadRawVcFuture; + type Output = as std::future::Future>::Output; + + fn into_future(self) -> Self::IntoFuture { self.node.into_read::() } +} + +impl std::future::IntoFuture for &Vc +where + T: VcValueType, +{ + type IntoFuture = as std::future::IntoFuture>::IntoFuture; + type Output = as std::future::IntoFuture>::Output; + + fn into_future(self) -> Self::IntoFuture { (*self).into_future() } +} + +impl Vc +where + T: VcValueType, +{ + /// Returns a strongly consistent read of the value. This ensures that all + /// internal tasks are finished before the read is returned. + #[must_use] + pub fn strongly_consistent(self) -> ReadRawVcFuture { + self.node.into_strongly_consistent_read::() + } +} + +impl Unpin for Vc where T: ?Sized + Send {} + +impl Default for Vc +where + T: ValueDefault + Send, +{ + fn default() -> Self { T::value_default() } +} diff --git a/crates/turbo-tasks/Source/vc/read.rs b/crates/turbo-tasks/Source/vc/read.rs new file mode 100644 index 0000000000000..f0a5926d9aefb --- /dev/null +++ b/crates/turbo-tasks/Source/vc/read.rs @@ -0,0 +1,105 @@ +use std::{any::Any, marker::PhantomData, mem::ManuallyDrop}; + +use super::traits::VcValueType; + +/// Trait that controls [`Vc`]'s read representation. +/// +/// Has two implementations: +/// * [`VcDefaultRead`] +/// * [`VcTransparentRead`] +/// +/// This trait must remain sealed within this crate. +pub trait VcRead +where + T: VcValueType, { + /// The read target type. This is the type that will be returned when + /// `.await`ing a `Vc` of a value type. + /// + /// For instance, the target of `.await`ing a `Vc` will be a + /// `Completion`. When using `#[turbo_tasks::value(transparent)]`, the + /// target will be different than the value type. + type Target; + + /// The representation type. This is what will be used to + /// serialize/deserialize the value, and this determines the + /// type that the value will be upcasted to for storage. + /// + /// For instance, when storing generic collection types such as + /// `Vec>`, we first cast them to a shared `Vec>` + /// type instead, which has an equivalent memory representation to any + /// `Vec>` type. This allows sharing implementations of methods and + /// traits between all `Vec>`. + type Repr: VcValueType; + + /// Convert a reference to a value to a reference to the target type. + fn value_to_target_ref(value:&T) -> &Self::Target; + + /// Convert the target type to the repr. + fn target_to_repr(target:Self::Target) -> Self::Repr; + + /// Convert a reference to a target type to a reference to a value. + fn target_to_value_ref(target:&Self::Target) -> &T; +} + +/// Representation for standard `#[turbo_tasks::value]`, where a read return a +/// reference to the value type[] +pub struct VcDefaultRead { + _phantom:PhantomData, +} + +impl VcRead for VcDefaultRead +where + T: VcValueType, +{ + type Repr = T; + type Target = T; + + fn value_to_target_ref(value:&T) -> &Self::Target { value } + + fn target_to_repr(target:Self::Target) -> T { target } + + fn target_to_value_ref(target:&Self::Target) -> &T { target } +} + +/// Representation for `#[turbo_tasks::value(transparent)]` types, where reads +/// return a reference to the target type. +pub struct VcTransparentRead { + _phantom:PhantomData<(T, Target, Repr)>, +} + +impl VcRead for VcTransparentRead +where + T: VcValueType, + Target: Any + Send + Sync, + Repr: VcValueType, +{ + type Repr = Repr; + type Target = Target; + + fn value_to_target_ref(value:&T) -> &Self::Target { + // Safety: the `VcValueType` implementor must guarantee that both `T` and + // `Target` are #[repr(transparent)]. This is guaranteed by the + // `#[turbo_tasks::value(transparent)]` macro. + // We can't use `std::mem::transmute` here as it doesn't support generic types. + // See https://users.rust-lang.org/t/transmute-doesnt-work-on-generic-types/87272/9 + unsafe { + std::mem::transmute_copy::, &Self::Target>(&ManuallyDrop::new(value)) + } + } + + fn target_to_repr(target:Self::Target) -> Self::Repr { + // Safety: see `Self::value_to_target` above. + unsafe { + std::mem::transmute_copy::, Self::Repr>(&ManuallyDrop::new( + target, + )) + } + } + + fn target_to_value_ref(target:&Self::Target) -> &T { + // Safety: see `Self::value_to_target` above. + unsafe { + std::mem::transmute_copy::, &T>(&ManuallyDrop::new(target)) + } + } +} diff --git a/crates/turbo-tasks/Source/vc/traits.rs b/crates/turbo-tasks/Source/vc/traits.rs new file mode 100644 index 0000000000000..32c3e29e6673a --- /dev/null +++ b/crates/turbo-tasks/Source/vc/traits.rs @@ -0,0 +1,58 @@ +use super::{cell_mode::VcCellMode, read::VcRead}; +use crate::{TraitTypeId, ValueTypeId}; + +/// A trait implemented on all values types that can be put into a Value Cell +/// ([`Vc`]). +/// +/// # Safety +/// +/// The implementor of this trait must ensure that the read and cell mode +/// implementations are correct for the value type. Otherwise, it is possible to +/// generate invalid reads, for instance by using `VcTransparentRead` for a +/// value type that is not repr(transparent). +pub unsafe trait VcValueType: Sized + Send + Sync + 'static { + /// How to read the value. + type Read: VcRead; + + /// How to update cells of this value type. + type CellMode: VcCellMode; + + /// Returns the type id of the value type. + fn get_value_type_id() -> ValueTypeId; +} + +/// A trait implemented on all values trait object references that can be put +/// into a Value Cell ([`Vc<&dyn Trait>`]). +pub trait VcValueTrait { + fn get_trait_type_id() -> TraitTypeId; +} + +/// Marker trait that indicates that a [`Vc`] can be upcasted to a +/// [`Vc`]. +/// +/// # Safety +/// +/// The implementor of this trait must ensure that `Self` implements the +/// trait `T`. +pub unsafe trait Upcast: Send +where + T: VcValueTrait + ?Sized + Send, { +} + +/// Marker trait that indicates that a [`Vc`] can accept all methods +/// declared on a [`Vc`]. +/// +/// # Safety +/// +/// The implementor of this trait must ensure that `Self` implements the +/// trait `T`. +pub unsafe trait Dynamic: Send +where + T: VcValueTrait + ?Sized + Send, { +} + +/// Marker trait that a turbo_tasks::value is prepared for +/// serialization as Value<...> input. +/// Either use `#[turbo_tasks::value(serialization: auto_for_input)]` +/// or avoid Value<...> in favor of a real Vc +pub trait TypedForInput: VcValueType {} diff --git a/crates/turbo-tasks/build.rs b/crates/turbo-tasks/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbo-tasks/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbo-trace/Cargo.toml b/crates/turbo-trace/Cargo.toml index 6cde76bece2f8..ad0fc79d54d3b 100644 --- a/crates/turbo-trace/Cargo.toml +++ b/crates/turbo-trace/Cargo.toml @@ -1,11 +1,4 @@ -[package] -name = "turbo-trace" -version = "0.1.0" -edition = "2021" -license = "MIT" - [dependencies] -camino.workspace = true clap = { version = "4.5.17", features = ["derive"] } futures = { workspace = true } globwalk = { version = "0.1.0", path = "../turborepo-globwalk" } @@ -21,5 +14,17 @@ tracing = { workspace = true } tracing-subscriber = { workspace = true } turbopath = { workspace = true } +[dependencies.camino] +workspace = true + +[lib] +path = "Source/lib.rs" + [lints] workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turbo-trace" +version = "0.1.0" diff --git a/crates/turbo-trace/src/import_finder.rs b/crates/turbo-trace/Source/import_finder.rs similarity index 100% rename from crates/turbo-trace/src/import_finder.rs rename to crates/turbo-trace/Source/import_finder.rs diff --git a/crates/turbo-trace/src/lib.rs b/crates/turbo-trace/Source/lib.rs similarity index 100% rename from crates/turbo-trace/src/lib.rs rename to crates/turbo-trace/Source/lib.rs diff --git a/crates/turbo-trace/Source/main.rs b/crates/turbo-trace/Source/main.rs new file mode 100644 index 0000000000000..91a4812194e75 --- /dev/null +++ b/crates/turbo-trace/Source/main.rs @@ -0,0 +1,61 @@ +mod import_finder; +mod tracer; + +use camino::Utf8PathBuf; +use clap::Parser; +use miette::Report; +use tracer::Tracer; +use turbopath::{AbsoluteSystemPathBuf, PathError}; + +#[derive(Parser, Debug)] +struct Args { + #[clap(long, value_parser)] + cwd:Option, + #[clap(long)] + ts_config:Option, + #[clap(long)] + node_modules:Option, + files:Vec, + #[clap(long)] + depth:Option, + reverse:bool, +} + +#[tokio::main] +async fn main() -> Result<(), PathError> { + tracing_subscriber::fmt::init(); + let args = Args::parse(); + + let abs_cwd = if let Some(cwd) = args.cwd { + AbsoluteSystemPathBuf::from_cwd(cwd)? + } else { + AbsoluteSystemPathBuf::cwd()? + }; + + let files = args + .files + .into_iter() + .map(|f| AbsoluteSystemPathBuf::from_unknown(&abs_cwd, f)) + .collect(); + + let tracer = Tracer::new(abs_cwd, files, args.ts_config); + + let result = if args.reverse { + tracer.reverse_trace().await + } else { + tracer.trace(args.depth).await + }; + + if !result.errors.is_empty() { + for error in result.errors { + println!("{:?}", Report::new(error)) + } + std::process::exit(1); + } else { + for file in result.files.keys() { + println!("{}", file); + } + } + + Ok(()) +} diff --git a/crates/turbo-trace/src/tracer.rs b/crates/turbo-trace/Source/tracer.rs similarity index 100% rename from crates/turbo-trace/src/tracer.rs rename to crates/turbo-trace/Source/tracer.rs diff --git a/crates/turbo-trace/src/main.rs b/crates/turbo-trace/src/main.rs deleted file mode 100644 index c1b97c6f86cdf..0000000000000 --- a/crates/turbo-trace/src/main.rs +++ /dev/null @@ -1,61 +0,0 @@ -mod import_finder; -mod tracer; - -use camino::Utf8PathBuf; -use clap::Parser; -use miette::Report; -use tracer::Tracer; -use turbopath::{AbsoluteSystemPathBuf, PathError}; - -#[derive(Parser, Debug)] -struct Args { - #[clap(long, value_parser)] - cwd: Option, - #[clap(long)] - ts_config: Option, - #[clap(long)] - node_modules: Option, - files: Vec, - #[clap(long)] - depth: Option, - reverse: bool, -} - -#[tokio::main] -async fn main() -> Result<(), PathError> { - tracing_subscriber::fmt::init(); - let args = Args::parse(); - - let abs_cwd = if let Some(cwd) = args.cwd { - AbsoluteSystemPathBuf::from_cwd(cwd)? - } else { - AbsoluteSystemPathBuf::cwd()? - }; - - let files = args - .files - .into_iter() - .map(|f| AbsoluteSystemPathBuf::from_unknown(&abs_cwd, f)) - .collect(); - - let tracer = Tracer::new(abs_cwd, files, args.ts_config); - - let result = if args.reverse { - tracer.reverse_trace().await - } else { - tracer.trace(args.depth).await - }; - - if !result.errors.is_empty() { - for error in result.errors { - println!("{:?}", Report::new(error)) - } - std::process::exit(1); - } else { - for file in result.files.keys() { - println!("{}", file); - } - } - - Ok(()) -} diff --git a/crates/turbopack-bench/Source/bundlers/mod.rs b/crates/turbopack-bench/Source/bundlers/mod.rs new file mode 100644 index 0000000000000..3ee87307bfb46 --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/mod.rs @@ -0,0 +1,200 @@ +use std::{path::Path, process::Child, time::Duration}; + +use anyhow::Result; + +use self::{ + nextjs::{NextJs, NextJsVersion}, + parcel::Parcel, + vite::Vite, + webpack::Webpack, +}; +use crate::bundlers::rspack::Rspack; + +mod nextjs; +mod parcel; +mod rspack; +mod vite; +mod webpack; + +#[derive(Debug, Clone, Copy)] +pub enum RenderType { + /// App is completely rendered on client side, the initial HTML is empty. + ClientSideRendered, + /// App is intially rendered on server side, then hydrated on client side. + ServerSidePrerendered, + /// App is rendered on server side, but additional client side javascript + /// emits events on hydration and changes + ServerSideRenderedWithEvents, + /// App is rendered on server side, without any client side events. + #[allow(dead_code)] + ServerSideRenderedWithoutInteractivity, +} + +pub trait Bundler { + fn get_name(&self) -> &str; + fn get_path(&self) -> &str { "/" } + fn react_version(&self) -> &str { "^18.2.0" } + fn render_type(&self) -> RenderType { RenderType::ClientSideRendered } + /// There is a hydration done event emitted by client side JavaScript + fn has_hydration_event(&self) -> bool { + !matches!(self.render_type(), RenderType::ServerSideRenderedWithoutInteractivity) + } + + fn prepare(&self, _template_dir:&Path) -> Result<()> { Ok(()) } + fn prepare_each(&self, _template_dir:&Path) -> Result<()> { Ok(()) } + fn start_server(&self, test_dir:&Path) -> Result<(Child, String)>; + + /// The maximum amount of time to wait for HMR during the setup and warmup + /// phase. + fn max_init_update_timeout(&self, _module_count:usize) -> Duration { Duration::from_secs(60) } + + /// The maximum amount of time to wait for HMR during the actual benchmark. + /// This is a lot shorter than the init timeout because we expect + /// updates to generally happen quickly, and we don't want to wait for a + /// long time when an update is dropped. + fn max_update_timeout(&self, _module_count:usize) -> Duration { Duration::from_secs(5) } +} + +pub fn get_bundlers() -> Vec> { + vec![ + Box::new(NextJs::new( + NextJsVersion::Canary, + "Next.js canary Turbo SSR", + "/page", + true, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::Canary, + "Next.js canary Turbo RSC", + "/app", + true, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::Canary, + "Next.js canary Turbo RCC", + "/client", + true, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::V14, + "Next.js 14 Turbo SSR", + "/page", + true, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::V14, + "Next.js 14 Turbo RSC", + "/app", + true, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::V14, + "Next.js 14 Turbo RCC", + "/client", + true, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::V13, + "Next.js 13 Turbo SSR", + "/page", + true, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::V13, + "Next.js 13 Turbo RSC", + "/app", + true, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::V13, + "Next.js 13 Turbo RCC", + "/client", + true, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::Canary, + "Next.js canary webpack SSR", + "/page", + false, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::Canary, + "Next.js canary webpack RSC", + "/app", + false, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::Canary, + "Next.js canary webpack RCC", + "/client", + false, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::V14, + "Next.js 14 webpack SSR", + "/page", + false, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::V14, + "Next.js 14 webpack RSC", + "/app", + false, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::V14, + "Next.js 14 webpack RCC", + "/client", + false, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::V13, + "Next.js 13 webpack SSR", + "/page", + false, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::V13, + "Next.js 13 webpack RSC", + "/app", + false, + RenderType::ServerSideRenderedWithEvents, + )), + Box::new(NextJs::new( + NextJsVersion::V13, + "Next.js 13 webpack RCC", + "/client", + false, + RenderType::ServerSidePrerendered, + )), + Box::new(NextJs::new( + NextJsVersion::V12, + "Next.js 12 webpack SSR", + "/page", + false, + RenderType::ServerSidePrerendered, + )), + Box::new(Parcel {}), + Box::new(Vite::new(false, false)), + Box::new(Vite::new(true, false)), + Box::new(Vite::new(false, true)), + Box::new(Webpack {}), + Box::new(Rspack {}), + ] +} diff --git a/crates/turbopack-bench/Source/bundlers/nextjs/mod.rs b/crates/turbopack-bench/Source/bundlers/nextjs/mod.rs new file mode 100644 index 0000000000000..8a50828223bbc --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/nextjs/mod.rs @@ -0,0 +1,150 @@ +use std::{ + fs, + path::Path, + process::{Child, Command, Stdio}, + time::Duration, +}; + +use anyhow::{Context, Result, anyhow}; +use regex::Regex; + +use super::RenderType; +use crate::{ + bundlers::Bundler, + util::{ + npm::{ + NpmPackage, + {self}, + }, + wait_for_match, + }, +}; + +#[derive(Debug)] +pub enum NextJsVersion { + V12, + V13, + V14, + Canary, +} + +#[derive(Debug)] +pub struct NextJs { + version:NextJsVersion, + name:String, + path:String, + turbo:bool, + render_type:RenderType, +} + +impl NextJs { + pub fn new( + version:NextJsVersion, + name:&str, + path:&str, + turbo:bool, + render_type:RenderType, + ) -> Self { + Self { name:name.to_owned(), path:path.to_owned(), render_type, turbo, version } + } +} + +impl Bundler for NextJs { + fn get_name(&self) -> &str { &self.name } + + fn get_path(&self) -> &str { &self.path } + + fn render_type(&self) -> RenderType { self.render_type } + + fn react_version(&self) -> &str { self.version.react_version() } + + fn prepare(&self, install_dir:&Path) -> Result<()> { + npm::install(install_dir, &[NpmPackage::new("next", self.version.version())]) + .context("failed to install `next` module")?; + + if self.version.app_dir() { + fs::write(install_dir.join("next.config.js"), include_bytes!("next.config.js"))?; + } + Ok(()) + } + + fn start_server(&self, test_dir:&Path) -> Result<(Child, String)> { + // Using `node_modules/.bin/next` would sometimes error with `Error: Cannot find + // module '../build/output/log'` + let mut proc = Command::new("node"); + proc.args([ + test_dir + .join("node_modules") + .join("next") + .join("dist") + .join("bin") + .join("next") + .to_str() + .unwrap(), + "dev", + "--port", + &match self.version { + NextJsVersion::V12 => { + // Next.js 12 has a bug where requests for port 0 are ignored and it falls + // back to the default 3000. Use portpicker instead. + portpicker::pick_unused_port() + .ok_or_else(|| anyhow!("failed to pick unused port"))? + }, + _ => 0, + } + .to_string(), + ]) + .current_dir(test_dir) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()); + if self.turbo { + proc.arg("--turbo"); + } + let mut proc = proc.spawn().context("failed to run `next` command")?; + + let addr = wait_for_match( + proc.stdout.as_mut().ok_or_else(|| anyhow!("missing stdout"))?, + match self.version { + NextJsVersion::V12 => Regex::new("started server.*url: (.*)"), + _ => Regex::new("- Local:\\s+(.*)"), + }?, + ) + .ok_or_else(|| anyhow!("failed to find devserver address"))?; + + Ok((proc, format!("{addr}/page"))) + } + + fn max_update_timeout(&self, module_count:usize) -> std::time::Duration { + match (self.render_type, self.turbo) { + (RenderType::ServerSidePrerendered, true) => Duration::from_millis(500), + // Arbitrary default timeout that seems to work well for Next.js Webpack + _ => Duration::from_millis(5000 + (module_count as f64 / 2.0).ceil() as u64), + } + } +} + +impl NextJsVersion { + /// Returns the version of Next.js to install from npm. + pub fn version(&self) -> &'static str { + match self { + NextJsVersion::V12 => "^12", + NextJsVersion::V13 => "^13", + NextJsVersion::V14 => "^14", + NextJsVersion::Canary => "canary", + } + } + + /// Returns the version of React to install from npm alongside this version + /// of Next.js. + pub fn react_version(&self) -> &'static str { + match self { + NextJsVersion::V12 => "^18.2.0", + NextJsVersion::V13 => "^18.2.0", + NextJsVersion::V14 => "^18.2.0", + NextJsVersion::Canary => "rc", + } + } + + /// Returns whether this version of Next.js supports the appDir option. + pub fn app_dir(&self) -> bool { matches!(self, NextJsVersion::V13 | NextJsVersion::Canary) } +} diff --git a/crates/turbopack-bench/Source/bundlers/nextjs/next.config.js b/crates/turbopack-bench/Source/bundlers/nextjs/next.config.js new file mode 100644 index 0000000000000..f053ebf7976e3 --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/nextjs/next.config.js @@ -0,0 +1 @@ +module.exports = {}; diff --git a/crates/turbopack-bench/Source/bundlers/parcel.rs b/crates/turbopack-bench/Source/bundlers/parcel.rs new file mode 100644 index 0000000000000..6c67b76050877 --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/parcel.rs @@ -0,0 +1,69 @@ +use std::{ + path::Path, + process::{Child, Command, Stdio}, +}; + +use anyhow::{Context, Result, anyhow}; +use regex::Regex; + +use crate::{ + bundlers::Bundler, + util::{ + npm::{ + NpmPackage, + {self}, + }, + wait_for_match, + }, +}; + +pub struct Parcel; +impl Bundler for Parcel { + fn get_name(&self) -> &str { "Parcel CSR" } + + fn prepare(&self, install_dir:&Path) -> Result<()> { + npm::install( + install_dir, + &[ + NpmPackage::new("parcel", "^2.8.0"), + // `process` would otherwise be auto-installed by Parcel. Do this in advance as + // to not influence the benchmark. + NpmPackage::new("process", "^0.11.10"), + ], + ) + .context("failed to install from npm")?; + + Ok(()) + } + + fn start_server(&self, test_dir:&Path) -> Result<(Child, String)> { + let mut proc = Command::new("node") + .args([ + (test_dir + .join("node_modules") + .join("parcel") + .join("lib") + .join("bin.js") + .to_str() + .unwrap()), + "--port", + &portpicker::pick_unused_port() + .ok_or_else(|| anyhow!("failed to pick unused port"))? + .to_string(), + "index.html", + ]) + .current_dir(test_dir) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .context("failed to run `parcel` command")?; + + let addr = wait_for_match( + proc.stdout.as_mut().ok_or_else(|| anyhow!("missing stdout"))?, + Regex::new("Server running at\\s+(.*)")?, + ) + .ok_or_else(|| anyhow!("failed to find devserver address"))?; + + Ok((proc, addr)) + } +} diff --git a/crates/turbopack-bench/Source/bundlers/rspack/mod.rs b/crates/turbopack-bench/Source/bundlers/rspack/mod.rs new file mode 100644 index 0000000000000..7532c717b1ece --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/rspack/mod.rs @@ -0,0 +1,68 @@ +use std::{ + fs, + path::Path, + process::{Child, Command, Stdio}, +}; + +use anyhow::{Context, Result, anyhow}; +use regex::Regex; + +use crate::{ + bundlers::Bundler, + util::{ + npm::{ + NpmPackage, + {self}, + }, + wait_for_match, + }, +}; + +pub struct Rspack; +impl Bundler for Rspack { + fn get_name(&self) -> &str { "Rspack CSR" } + + fn prepare(&self, install_dir:&Path) -> Result<()> { + npm::install( + install_dir, + &[ + NpmPackage::new("react-refresh", "^0.14.0"), + NpmPackage::new("@rspack/cli", "0.1.9"), + ], + ) + .context("failed to install from npm")?; + + fs::write(install_dir.join("rspack.config.js"), include_bytes!("rspack.config.js"))?; + + Ok(()) + } + + fn start_server(&self, test_dir:&Path) -> Result<(Child, String)> { + let mut proc = Command::new("node") + .args([ + (test_dir + .join("node_modules") + .join("@rspack") + .join("cli") + .join("bin") + .join("rspack") + .to_str() + .unwrap()), + "serve", + ]) + .env("NO_COLOR", "1") + .current_dir(test_dir) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .context("failed to run `rspack-dev-server` command")?; + + let addr = wait_for_match( + proc.stderr.as_mut().ok_or_else(|| anyhow!("missing stderr"))?, + Regex::new("Loopback:\\s+(.*)")?, + ) + .ok_or_else(|| anyhow!("failed to find devserver address"))?; + + Ok((proc, addr)) + } +} diff --git a/crates/turbopack-bench/Source/bundlers/rspack/rspack.config.js b/crates/turbopack-bench/Source/bundlers/rspack/rspack.config.js new file mode 100644 index 0000000000000..db0f385f01a65 --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/rspack/rspack.config.js @@ -0,0 +1,14 @@ +const path = require("path"); + +module.exports = { + entry: { + main: "./src/index.jsx", + }, + output: { + filename: "main.js", + path: path.resolve(__dirname, "dist"), + }, + devServer: { + port: 0, + }, +}; diff --git a/crates/turbopack-bench/Source/bundlers/vite/mod.rs b/crates/turbopack-bench/Source/bundlers/vite/mod.rs new file mode 100644 index 0000000000000..1d00e66dabc76 --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/vite/mod.rs @@ -0,0 +1,99 @@ +use std::{ + fs, + path::Path, + process::{Child, Command, Stdio}, +}; + +use anyhow::{Context, Result, anyhow}; +use regex::Regex; + +use crate::{ + bundlers::Bundler, + util::{ + npm::{ + NpmPackage, + {self}, + }, + wait_for_match, + }, +}; + +pub struct Vite { + swc:bool, + ssr:bool, +} + +impl Vite { + pub fn new(swc:bool, ssr:bool) -> Self { Vite { swc, ssr } } +} + +impl Bundler for Vite { + fn get_name(&self) -> &str { + if self.ssr { + if self.swc { "Vite SWC SSR" } else { "Vite SSR" } + } else if self.swc { + "Vite SWC CSR" + } else { + "Vite CSR" + } + } + + fn prepare(&self, install_dir:&Path) -> Result<()> { + let mut packages = vec![NpmPackage::new("vite", "4.3.0-beta.2")]; + if self.swc { + packages.push(NpmPackage::new("@vitejs/plugin-react-swc", "^3.2.0")); + } else { + packages.push(NpmPackage::new("@vitejs/plugin-react", "^3.1.0")); + }; + if self.ssr { + packages.push(NpmPackage::new("express", "^4.18.2")); + } + npm::install(install_dir, &packages).context("failed to install from npm")?; + + fs::write( + install_dir.join("vite.config.js"), + if self.swc { + include_bytes!("vite.swc.config.js") as &[u8] + } else { + include_bytes!("vite.config.js") as &[u8] + }, + )?; + + Ok(()) + } + + fn start_server(&self, test_dir:&Path) -> Result<(Child, String)> { + let args = if self.ssr { + vec![test_dir.join("vite-server.mjs").to_str().unwrap().to_string()] + } else { + vec![ + test_dir + .join("node_modules") + .join("vite") + .join("bin") + .join("vite.js") + .to_str() + .unwrap() + .to_string(), + "--port".to_string(), + "0".to_string(), + ] + }; + let mut proc = Command::new("node") + .args(args) + .env("NO_COLOR", "1") + .current_dir(test_dir) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .context("failed to run `vite` command")?; + + let addr = wait_for_match( + proc.stdout.as_mut().ok_or_else(|| anyhow!("missing stdout"))?, + Regex::new("Local:\\s+(.*)")?, + ) + .ok_or_else(|| anyhow!("failed to find devserver address"))?; + + Ok((proc, addr)) + } +} diff --git a/crates/turbopack-bench/Source/bundlers/vite/vite.config.js b/crates/turbopack-bench/Source/bundlers/vite/vite.config.js new file mode 100644 index 0000000000000..081c8d9f69fcb --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/vite/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/crates/turbopack-bench/Source/bundlers/vite/vite.swc.config.js b/crates/turbopack-bench/Source/bundlers/vite/vite.swc.config.js new file mode 100644 index 0000000000000..642ef87a8e9a7 --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/vite/vite.swc.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react-swc"; + +export default defineConfig({ + plugins: [react()], + esbuild: { jsx: "automatic" }, +}); diff --git a/crates/turbopack-bench/Source/bundlers/webpack/mod.rs b/crates/turbopack-bench/Source/bundlers/webpack/mod.rs new file mode 100644 index 0000000000000..b2eecfe7a3cca --- /dev/null +++ b/crates/turbopack-bench/Source/bundlers/webpack/mod.rs @@ -0,0 +1,74 @@ +use std::{ + fs, + path::Path, + process::{Child, Command, Stdio}, +}; + +use anyhow::{Context, Result, anyhow}; +use regex::Regex; + +use crate::{ + bundlers::Bundler, + util::{ + npm::{ + NpmPackage, + {self}, + }, + wait_for_match, + }, +}; + +pub struct Webpack; +impl Bundler for Webpack { + fn get_name(&self) -> &str { "Webpack CSR" } + + fn prepare(&self, install_dir:&Path) -> Result<()> { + npm::install( + install_dir, + &[ + NpmPackage::new("@pmmmwh/react-refresh-webpack-plugin", "^0.5.7"), + NpmPackage::new("@swc/core", "^1.2.249"), + NpmPackage::new("@swc/helpers", "^0.4.13"), + NpmPackage::new("react-refresh", "^0.14.0"), + NpmPackage::new("swc-loader", "^0.2.3"), + NpmPackage::new("webpack", "^5.75.0"), + NpmPackage::new("webpack-cli", "^4.10.0"), + NpmPackage::new("webpack-dev-server", "^4.11.0"), + ], + ) + .context("failed to install from npm")?; + + fs::write(install_dir.join("webpack.config.js"), include_bytes!("webpack.config.js"))?; + + Ok(()) + } + + fn start_server(&self, test_dir:&Path) -> Result<(Child, String)> { + let mut proc = Command::new("node") + .args([ + (test_dir + .join("node_modules") + .join("webpack-dev-server") + .join("bin") + .join("webpack-dev-server.js") + .to_str() + .unwrap()), + "--port", + "0", + ]) + .env("NO_COLOR", "1") + .current_dir(test_dir) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .context("failed to run `webpack-dev-server` command")?; + + let addr = wait_for_match( + proc.stderr.as_mut().ok_or_else(|| anyhow!("missing stderr"))?, + Regex::new("\\[webpack\\-dev\\-server\\] Loopback:\\s+(.*)")?, + ) + .ok_or_else(|| anyhow!("failed to find devserver address"))?; + + Ok((proc, addr)) + } +} diff --git a/crates/turbopack-bench/Source/lib.rs b/crates/turbopack-bench/Source/lib.rs new file mode 100644 index 0000000000000..12a5fd230045e --- /dev/null +++ b/crates/turbopack-bench/Source/lib.rs @@ -0,0 +1,547 @@ +use std::{ + fs::{self}, + panic::AssertUnwindSafe, + path::Path, + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, + time::Duration, +}; + +use anyhow::{Context, Result, anyhow}; +use criterion::{ + BenchmarkGroup, + BenchmarkId, + Criterion, + measurement::{Measurement, WallTime}, +}; +use once_cell::sync::Lazy; +use tokio::{ + runtime::Runtime, + time::{sleep, timeout}, +}; +use turbo_tasks::util::FormatDuration; +use util::{ + AsyncBencherExtension, + BINDING_NAME, + PreparedApp, + build_test, + create_browser, + env::{read_env, read_env_bool, read_env_list}, + module_picker::ModulePicker, +}; + +use self::{bundlers::RenderType, util::resume_on_error}; +use crate::{bundlers::Bundler, util::PageGuard}; + +pub mod bundlers; +pub mod util; + +pub fn bench_startup(c:&mut Criterion, bundlers:&[Box]) { + let mut g = c.benchmark_group("bench_startup"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(60)); + + bench_startup_internal(g, false, bundlers); +} + +pub fn bench_hydration(c:&mut Criterion, bundlers:&[Box]) { + let mut g = c.benchmark_group("bench_hydration"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(60)); + + bench_startup_internal(g, true, bundlers); +} + +fn bench_startup_internal( + mut g:BenchmarkGroup, + hydration:bool, + bundlers:&[Box], +) { + let runtime = Runtime::new().unwrap(); + let browser = Lazy::new(|| runtime.block_on(create_browser())); + + for bundler in bundlers { + let wait_for_hydration = match bundler.render_type() { + RenderType::ClientSideRendered => { + // For bundlers without server rendered html "startup" means time to hydration + // as they only render an empty screen without hydration. Since startup and + // hydration would be the same we skip the hydration benchmark for them. + if hydration { + continue; + } else { + true + } + }, + RenderType::ServerSidePrerendered => hydration, + RenderType::ServerSideRenderedWithEvents => hydration, + RenderType::ServerSideRenderedWithoutInteractivity => { + // For bundlers without interactivity there is no hydration event to wait for + if hydration { + continue; + } else { + false + } + }, + }; + for module_count in get_module_counts() { + let test_app = Lazy::new(|| build_test(module_count, bundler.as_ref())); + let input = (bundler.as_ref(), &test_app); + resume_on_error(AssertUnwindSafe(|| { + g.bench_with_input( + BenchmarkId::new(bundler.get_name(), format!("{} modules", module_count)), + &input, + |b, &(bundler, test_app)| { + let test_app = &**test_app; + let browser = &*browser; + b.to_async(&runtime).try_iter_custom(|iters, m| { + async move { + let mut value = m.zero(); + + for _ in 0..iters { + let mut app = + PreparedApp::new(bundler, test_app.path().to_path_buf()) + .await?; + let start = m.start(); + app.start_server()?; + let mut guard = app.with_page(browser).await?; + if wait_for_hydration { + guard.wait_for_hydration().await?; + } + let duration = m.end(start); + value = m.add(&value, &duration); + + // Defer the dropping of the guard. + drop(guard); + } + Ok(value) + } + }); + }, + ); + })); + } + } + g.finish(); +} + +#[derive(Copy, Clone)] +enum CodeLocation { + Effect, + Evaluation, +} + +pub fn bench_hmr_to_eval(c:&mut Criterion, bundlers:&[Box]) { + let mut g = c.benchmark_group("bench_hmr_to_eval"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(60)); + + bench_hmr_internal(g, CodeLocation::Evaluation, bundlers); +} + +pub fn bench_hmr_to_commit(c:&mut Criterion, bundlers:&[Box]) { + let mut g = c.benchmark_group("bench_hmr_to_commit"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(60)); + + bench_hmr_internal(g, CodeLocation::Effect, bundlers); +} + +fn bench_hmr_internal( + mut g:BenchmarkGroup, + location:CodeLocation, + bundlers:&[Box], +) { + // Only capture one sample for warmup + g.warm_up_time(Duration::from_millis(1)); + + let runtime = Runtime::new().unwrap(); + let browser = Lazy::new(|| runtime.block_on(create_browser())); + let hmr_warmup = read_env("TURBOPACK_BENCH_HMR_WARMUP", 10).unwrap(); + + for bundler in bundlers { + if matches!( + bundler.render_type(), + RenderType::ServerSideRenderedWithEvents + | RenderType::ServerSideRenderedWithoutInteractivity + ) && matches!(location, CodeLocation::Evaluation) + { + // We can't measure evaluation time for these bundlers since it's not evaluated + // in the browser + continue; + } + for module_count in get_module_counts() { + let test_app = Lazy::new(|| build_test(module_count, bundler.as_ref())); + let input = (bundler.as_ref(), &test_app); + let module_picker = + Lazy::new(|| Arc::new(ModulePicker::new(test_app.modules().to_vec()))); + + resume_on_error(AssertUnwindSafe(|| { + g.bench_with_input( + BenchmarkId::new(bundler.get_name(), format!("{} modules", module_count)), + &input, + |b, &(bundler, test_app)| { + let test_app = &**test_app; + let modules = test_app.modules(); + let module_picker = &*module_picker; + let browser = &*browser; + + let max_init_update_timeout = bundler.max_init_update_timeout(module_count); + let max_update_timeout = bundler.max_update_timeout(module_count); + + b.to_async(&runtime).try_iter_async( + &runtime, + || { + async { + let mut app = PreparedApp::new_without_copy( + bundler, + test_app.path().to_path_buf(), + ) + .await?; + app.start_server()?; + let mut guard = app.with_page(browser).await?; + if bundler.has_hydration_event() { + guard.wait_for_hydration().await?; + } else { + guard.page().wait_for_navigation().await?; + } + guard + .page() + .evaluate_expression("globalThis.HMR_IS_HAPPENING = true") + .await + .context( + "Unable to evaluate JavaScript in the page for HMR \ + check flag", + )?; + + // There's a possible race condition between hydration and + // connection to the HMR server. We attempt to make updates with + // an exponential backoff until one succeeds. + let mut exponential_duration = Duration::from_millis(100); + loop { + match make_change( + &modules[0].0, + bundler, + &mut guard, + location, + exponential_duration, + &WallTime, + ) + .await + { + Ok(_) => { + break; + }, + Err(e) => { + exponential_duration *= 2; + if exponential_duration > max_init_update_timeout { + return Err( + e.context("failed to make warmup change") + ); + } + }, + } + } + + // Once we know the HMR server is connected, we make a few + // warmup changes. + let mut hmr_warmup_iter = 0; + let mut hmr_warmup_dropped = 0; + while hmr_warmup_iter < hmr_warmup { + match make_change( + &modules[0].0, + bundler, + &mut guard, + location, + max_update_timeout, + &WallTime, + ) + .await + { + Err(_) => { + // We don't care about dropped updates during + // warmup. + hmr_warmup_dropped += 1; + + if hmr_warmup_dropped >= hmr_warmup { + return Err(anyhow!( + "failed to make warmup change {} times", + hmr_warmup_dropped + )); + } + }, + Ok(_) => { + hmr_warmup_iter += 1; + }, + } + } + + Ok(guard) + } + }, + |mut guard, iters, m, verbose| { + let module_picker = Arc::clone(module_picker); + async move { + let mut value = m.zero(); + let mut dropped = 0; + let mut iter = 0; + while iter < iters { + let module = module_picker.pick(); + let duration = match make_change( + module, + bundler, + &mut guard, + location, + max_update_timeout, + &m, + ) + .await + { + Err(_) => { + // Some bundlers (e.g. Turbopack and Vite) can drop + // updates under certain conditions. We don't want + // to crash or stop the benchmark + // because of this. Instead, we keep going and + // report the number of dropped updates at the end. + dropped += 1; + continue; + }, + Ok(duration) => duration, + }; + value = m.add(&value, &duration); + + iter += 1; + if verbose && iter != iters && iter.count_ones() == 1 { + eprint!( + " [{:?} {:?}/{}{}]", + duration, + FormatDuration(value / (iter as u32)), + iter, + if dropped > 0 { + format!(" ({} dropped)", dropped) + } else { + "".to_string() + } + ); + } + } + + Ok((guard, value)) + } + }, + |guard| { + async move { + let hmr_is_happening = guard + .page() + .evaluate_expression("globalThis.HMR_IS_HAPPENING") + .await + .unwrap(); + // Make sure that we are really measuring HMR and not + // accidentically full refreshing the page + assert!(hmr_is_happening.value().unwrap().as_bool().unwrap()); + } + }, + ); + }, + ); + })); + } + } +} + +fn insert_code( + path:&Path, + bundler:&dyn Bundler, + message:&str, + location:CodeLocation, +) -> Result Result<()>> { + let mut contents = fs::read_to_string(path)?; + + const PRAGMA_EVAL_START:&str = "/* @turbopack-bench:eval-start */"; + const PRAGMA_EVAL_END:&str = "/* @turbopack-bench:eval-end */"; + + let eval_start = contents + .find(PRAGMA_EVAL_START) + .ok_or_else(|| anyhow!("unable to find effect start pragma in {}", contents))?; + let eval_end = contents + .find(PRAGMA_EVAL_END) + .ok_or_else(|| anyhow!("unable to find effect end pragma in {}", contents))?; + + match (location, bundler.render_type()) { + (CodeLocation::Effect, _) => { + contents.replace_range( + eval_start + PRAGMA_EVAL_START.len()..eval_end, + &format!("\nEFFECT_PROPS.message = \"{message}\";\n"), + ); + }, + ( + CodeLocation::Evaluation, + RenderType::ClientSideRendered | RenderType::ServerSidePrerendered, + ) => { + let code = format!( + "\nglobalThis.{BINDING_NAME} && globalThis.{BINDING_NAME}(\"{message}\");\n" + ); + contents.replace_range(eval_start + PRAGMA_EVAL_START.len()..eval_end, &code); + }, + ( + CodeLocation::Evaluation, + RenderType::ServerSideRenderedWithEvents + | RenderType::ServerSideRenderedWithoutInteractivity, + ) => { + panic!("evaluation can't be measured for bundlers which evaluate on server side"); + }, + } + + let path = path.to_owned(); + Ok(move || Ok(fs::write(&path, contents)?)) +} + +static CHANGE_TIMEOUT_MESSAGE:&str = "update was not registered by bundler"; + +async fn make_change<'a>( + module:&Path, + bundler:&dyn Bundler, + guard:&mut PageGuard<'a>, + location:CodeLocation, + timeout_duration:Duration, + measurement:&WallTime, +) -> Result { + static CHANGE_COUNTER:AtomicUsize = AtomicUsize::new(0); + + let msg = format!("TURBOPACK_BENCH_CHANGE_{}", CHANGE_COUNTER.fetch_add(1, Ordering::Relaxed)); + + // Keep the IO out of the measurement. + let commit = insert_code(module, bundler, &msg, location)?; + + let start = measurement.start(); + + commit()?; + + // Wait for the change introduced above to be reflected at runtime. + // This expects HMR or automatic reloading to occur. + timeout(timeout_duration, guard.wait_for_binding(&msg)) + .await + .context(CHANGE_TIMEOUT_MESSAGE)??; + + let duration = measurement.end(start); + + if cfg!(target_os = "linux") { + // TODO(sokra) triggering HMR updates too fast can have weird effects on Linux + tokio::time::sleep(std::cmp::max(duration, Duration::from_millis(100))).await; + } + Ok(duration) +} + +pub fn bench_startup_cached(c:&mut Criterion, bundlers:&[Box]) { + let mut g = c.benchmark_group("bench_startup_cached"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(60)); + + bench_startup_cached_internal(g, false, bundlers); +} + +pub fn bench_hydration_cached(c:&mut Criterion, bundlers:&[Box]) { + let mut g = c.benchmark_group("bench_hydration_cached"); + g.sample_size(10); + g.measurement_time(Duration::from_secs(60)); + + bench_startup_cached_internal(g, true, bundlers); +} + +fn bench_startup_cached_internal( + mut g:BenchmarkGroup, + hydration:bool, + bundlers:&[Box], +) { + if !read_env_bool("TURBOPACK_BENCH_CACHED") { + return; + } + + let runtime = Runtime::new().unwrap(); + let browser = Lazy::new(|| runtime.block_on(create_browser())); + + for bundler in bundlers { + let wait_for_hydration = match bundler.render_type() { + RenderType::ClientSideRendered => { + // For bundlers without server rendered html "startup" means time to hydration + // as they only render an empty screen without hydration. Since startup and + // hydration would be the same we skip the hydration benchmark for them. + if hydration { + continue; + } else { + true + } + }, + RenderType::ServerSidePrerendered => hydration, + RenderType::ServerSideRenderedWithEvents => hydration, + RenderType::ServerSideRenderedWithoutInteractivity => { + // For bundlers without interactivity there is no hydration event to wait for + if hydration { + continue; + } else { + false + } + }, + }; + for module_count in get_module_counts() { + let test_app = Lazy::new(|| build_test(module_count, bundler.as_ref())); + let input = (bundler.as_ref(), &test_app); + + resume_on_error(AssertUnwindSafe(|| { + g.bench_with_input( + BenchmarkId::new(bundler.get_name(), format!("{} modules", module_count)), + &input, + |b, &(bundler, test_app)| { + let test_app = &**test_app; + let browser = &*browser; + b.to_async(&runtime).try_iter_custom(|iters, m| { + async move { + // Run a complete build, shut down, and test running it again + let mut app = + PreparedApp::new(bundler, test_app.path().to_path_buf()) + .await?; + app.start_server()?; + let mut guard = app.with_page(browser).await?; + if bundler.has_hydration_event() { + guard.wait_for_hydration().await?; + } else { + guard.page().wait_for_navigation().await?; + } + + let mut app = guard.close_page().await?; + + // Give it 4 seconds time to store the cache + sleep(Duration::from_secs(4)).await; + + app.stop_server()?; + + let mut value = m.zero(); + for _ in 0..iters { + let start = m.start(); + app.start_server()?; + let mut guard = app.with_page(browser).await?; + if wait_for_hydration { + guard.wait_for_hydration().await?; + } + let duration = m.end(start); + value = m.add(&value, &duration); + + app = guard.close_page().await?; + app.stop_server()?; + } + + drop(app); + Ok(value) + } + }); + }, + ); + })); + } + } +} + +fn get_module_counts() -> Vec { + read_env_list("TURBOPACK_BENCH_COUNTS", vec![1_000usize]).unwrap() +} diff --git a/crates/turbopack-bench/Source/util/env.rs b/crates/turbopack-bench/Source/util/env.rs new file mode 100644 index 0000000000000..17ebc4a1c463c --- /dev/null +++ b/crates/turbopack-bench/Source/util/env.rs @@ -0,0 +1,39 @@ +use std::{error::Error, str::FromStr}; + +use anyhow::{Context, Result, anyhow}; + +/// Reads an environment variable. +pub fn read_env(name:&str, default:T) -> Result +where + T: FromStr, + ::Err: Error + Send + Sync + 'static, { + let config = std::env::var(name).ok(); + match config.as_deref() { + None | Some("") => Ok(default), + Some(config) => config.parse().with_context(|| anyhow!("Invalid value for {}", name)), + } +} + +/// Reads an boolean-like environment variable, where any value but "0", "no", +/// or "false" is are considered true. +pub fn read_env_bool(name:&str) -> bool { + let config = std::env::var(name).ok(); + !matches!(config.as_deref(), None | Some("") | Some("0") | Some("no") | Some("false")) +} + +/// Reads a comma-separated environment variable as a vector. +pub fn read_env_list(name:&str, default:Vec) -> Result> +where + T: FromStr, + ::Err: Error + Send + Sync + 'static, { + let config = std::env::var(name).ok(); + match config.as_deref() { + None | Some("") => Ok(default), + Some(config) => { + config + .split(',') + .map(|s| s.parse().with_context(|| anyhow!("Invalid value for {}", name))) + .collect() + }, + } +} diff --git a/crates/turbopack-bench/Source/util/mod.rs b/crates/turbopack-bench/Source/util/mod.rs new file mode 100644 index 0000000000000..0f8c0a61a57de --- /dev/null +++ b/crates/turbopack-bench/Source/util/mod.rs @@ -0,0 +1,261 @@ +use std::{ + io::{ + BufRead, + BufReader, + Read, + Write, + {self}, + }, + panic::UnwindSafe, + process::Command, + time::{Duration, Instant}, +}; + +use anyhow::Result; +use chromiumoxide::{ + browser::{Browser, BrowserConfig}, + error::CdpError::Ws, +}; +use criterion::{AsyncBencher, async_executor::AsyncExecutor, black_box, measurement::WallTime}; +use futures::{Future, StreamExt}; +pub use page_guard::PageGuard; +use parking_lot::Mutex; +pub use prepared_app::PreparedApp; +use regex::Regex; +use tungstenite::{Error::Protocol, error::ProtocolError::ResetWithoutClosingHandshake}; +use turbo_tasks::util::FormatDuration; +use turbo_tasks_testing::retry::{retry, retry_async}; +use turbopack_create_test_app::test_app_builder::{ + EffectMode, + PackageJsonConfig, + TestApp, + TestAppBuilder, +}; + +use self::env::read_env_bool; +use crate::bundlers::{Bundler, RenderType}; + +pub mod env; +pub mod module_picker; +pub mod npm; +mod page_guard; +mod prepared_app; + +pub const BINDING_NAME:&str = "__turbopackBenchBinding"; + +fn retry_default(args:A, f:F) -> Result +where + F: Fn(&mut A) -> Result, { + // waits 5, 10, 20, 40 seconds = 75 seconds total + retry(args, f, 3, Duration::from_secs(5)) +} + +async fn retry_async_default(args:A, f:F) -> Result +where + F: Fn(&mut A) -> Fut, + Fut: Future>, { + // waits 5, 10, 20, 40 seconds = 75 seconds total + retry_async(args, f, 3, Duration::from_secs(5)).await +} + +pub fn build_test(module_count:usize, bundler:&dyn Bundler) -> TestApp { + let test_app = TestAppBuilder { + module_count, + directories_count:module_count / 20, + package_json:Some(PackageJsonConfig { react_version:bundler.react_version().to_string() }), + effect_mode:match bundler.render_type() { + RenderType::ServerSideRenderedWithEvents => EffectMode::Component, + _ => EffectMode::Hook, + }, + ..Default::default() + } + .build() + .unwrap(); + + let npm = command("npm") + .args(["install", "--loglevel=error"]) + .current_dir(test_app.path()) + .output() + .unwrap(); + + if !npm.status.success() { + io::stdout().write_all(&npm.stdout).unwrap(); + io::stderr().write_all(&npm.stderr).unwrap(); + panic!("npm install failed. See above."); + } + + retry_default((), |_| bundler.prepare(test_app.path())).unwrap(); + + test_app +} + +pub async fn create_browser() -> Browser { + let with_head = read_env_bool("TURBOPACK_BENCH_WITH_HEAD"); + let with_devtools = read_env_bool("TURBOPACK_BENCH_DEVTOOLS"); + let mut builder = BrowserConfig::builder(); + builder = builder.no_sandbox(); + if with_head { + builder = builder.with_head(); + } + if with_devtools { + builder = builder.arg("--auto-open-devtools-for-tabs"); + } + let (browser, mut handler) = retry_async( + builder.build().unwrap(), + |c| { + let c = c.clone(); + Browser::launch(c) + }, + 3, + Duration::from_millis(100), + ) + .await + .expect("Launching the browser failed"); + + // See https://crates.io/crates/chromiumoxide + tokio::task::spawn(async move { + loop { + if let Err(Ws(Protocol(ResetWithoutClosingHandshake))) = handler.next().await.unwrap() { + break; + } + } + }); + + browser +} + +pub fn resume_on_error(f:F) { + let runs_as_bench = std::env::args().find(|a| a == "--bench"); + let ignore_errors = read_env_bool("TURBOPACK_BENCH_IGNORE_ERRORS"); + + if runs_as_bench.is_some() || ignore_errors { + use std::panic::catch_unwind; + // panics are already printed to the console, so no need to handle the result. + let _ = catch_unwind(f); + } else { + f(); + } +} + +pub trait AsyncBencherExtension { + fn try_iter_custom(&mut self, routine:R) + where + R: Fn(u64, WallTime) -> F, + F: Future>; + + fn try_iter_async(&mut self, runner:A, setup:S, routine:R, teardown:T) + where + S: Fn() -> SF, + SF: Future>, + R: Fn(I, u64, WallTime, bool) -> F, + F: Future>, + T: Fn(I) -> TF, + TF: Future; +} + +impl<'a, 'b, A:AsyncExecutor> AsyncBencherExtension for AsyncBencher<'a, 'b, A, WallTime> { + fn try_iter_custom(&mut self, routine:R) + where + R: Fn(u64, WallTime) -> F, + F: Future>, { + let log_progress = read_env_bool("TURBOPACK_BENCH_PROGRESS"); + + let routine = &routine; + self.iter_custom(|iters| { + async move { + let measurement = WallTime; + let value = routine(iters, measurement).await.expect("routine failed"); + if log_progress { + eprint!(" {:?}/{}", FormatDuration(value / (iters as u32)), iters); + } + value + } + }); + } + + fn try_iter_async(&mut self, runner:A, setup:S, routine:R, teardown:T) + where + S: Fn() -> SF, + SF: Future>, + R: Fn(I, u64, WallTime, bool) -> F, + F: Future>, + T: Fn(I) -> TF, + TF: Future, { + let log_progress = read_env_bool("TURBOPACK_BENCH_PROGRESS"); + + let setup = &setup; + let routine = &routine; + let teardown = &teardown; + let input_mutex = &Mutex::new(Some(black_box(runner.block_on(async { + if log_progress { + eprint!(" setup..."); + } + let start = Instant::now(); + let input = retry_async_default((), |_| setup()).await.expect("failed to setup"); + if log_progress { + let duration = start.elapsed(); + eprint!(" [{:?}]", FormatDuration(duration)); + } + input + })))); + + self.iter_custom(|iters| { + async move { + let measurement = WallTime; + + let input = + input_mutex.lock().take().expect("iter_custom only executes its closure once"); + + let (output, value) = + routine(input, iters, measurement, log_progress).await.expect("Routine failed"); + let output = black_box(output); + + if log_progress { + eprint!(" {:?}/{}", FormatDuration(value / (iters as u32)), iters); + } + + input_mutex.lock().replace(output); + + value + } + }); + + let input = input_mutex.lock().take().unwrap(); + if log_progress { + eprint!(" teardown..."); + } + let start = Instant::now(); + runner.block_on(teardown(input)); + let duration = start.elapsed(); + if log_progress { + eprintln!(" [{:?}]", FormatDuration(duration)); + } + } +} + +pub fn command(bin:&str) -> Command { + if cfg!(windows) { + let mut command = Command::new("cmd.exe"); + command.args(["/C", bin]); + command + } else { + Command::new(bin) + } +} + +pub fn wait_for_match(readable:R, re:Regex) -> Option +where + R: Read, { + // See https://docs.rs/async-process/latest/async_process/#examples + let mut line_reader = BufReader::new(readable).lines(); + // Read until the match appears in the buffer + let mut matched:Option = None; + while let Some(Ok(line)) = line_reader.next() { + if let Some(cap) = re.captures(&line) { + matched = Some(cap.get(1).unwrap().as_str().into()); + break; + } + } + + matched +} diff --git a/crates/turbopack-bench/Source/util/module_picker.rs b/crates/turbopack-bench/Source/util/module_picker.rs new file mode 100644 index 0000000000000..dae76e7008d8b --- /dev/null +++ b/crates/turbopack-bench/Source/util/module_picker.rs @@ -0,0 +1,42 @@ +use std::{collections::HashMap, path::PathBuf}; + +use rand::{SeedableRng, rngs::StdRng, seq::SliceRandom}; + +/// Picks modules at random, but with a fixed seed so runs are somewhat +/// reproducible. +/// +/// This must be initialized outside of `bench_with_input` so we don't repeat +/// the same sequence in different samples. +pub struct ModulePicker { + depths:Vec, + modules_by_depth:HashMap>, + rng:parking_lot::Mutex, +} + +impl ModulePicker { + /// Creates a new module picker. + pub fn new(mut modules:Vec<(PathBuf, usize)>) -> Self { + let rng = StdRng::seed_from_u64(42); + + // Ensure the module order is deterministic. + modules.sort(); + + let mut modules_by_depth:HashMap<_, Vec<_>> = HashMap::new(); + for (module, depth) in modules { + modules_by_depth.entry(depth).or_default().push(module); + } + let mut depths:Vec<_> = modules_by_depth.keys().copied().collect(); + // Ensure the depth order is deterministic. + depths.sort(); + + Self { depths, modules_by_depth, rng:parking_lot::Mutex::new(rng) } + } + + /// Picks a random module with a uniform distribution over all depths. + pub fn pick(&self) -> &PathBuf { + let mut rng = self.rng.lock(); + // Sample from all depths uniformly. + let depth = self.depths.choose(&mut *rng).unwrap(); + self.modules_by_depth[depth].choose(&mut *rng).unwrap() + } +} diff --git a/crates/turbopack-bench/Source/util/npm.rs b/crates/turbopack-bench/Source/util/npm.rs new file mode 100644 index 0000000000000..a15723dacd975 --- /dev/null +++ b/crates/turbopack-bench/Source/util/npm.rs @@ -0,0 +1,68 @@ +use std::{ + fs::{ + File, + {self}, + }, + io::{ + Write, + {self}, + }, + path::Path, +}; + +use anyhow::{Result, anyhow}; +use serde_json::json; + +use crate::util::command; + +pub struct NpmPackage<'a> { + pub name:&'a str, + pub version:&'a str, +} + +impl<'a> NpmPackage<'a> { + pub fn new(name:&'a str, version:&'a str) -> Self { NpmPackage { name, version } } +} + +impl<'a> std::fmt::Display for NpmPackage<'a> { + fn fmt(&self, fmt:&mut std::fmt::Formatter) -> std::fmt::Result { + fmt.write_fmt(format_args!("{}@{}", self.name, self.version)) + } +} + +pub fn install(install_dir:&Path, packages:&[NpmPackage<'_>]) -> Result<()> { + if !fs::metadata(install_dir.join("package.json")) + .map(|metadata| metadata.is_file()) + .unwrap_or(false) + { + // Create a simple package.json if one doesn't exist + + let package_json = json!({ + "private": true, + "version": "0.0.0", + }); + + File::create(install_dir.join("package.json"))? + .write_all(format!("{:#}", package_json).as_bytes())?; + } + + let mut args = vec![ + "install".to_owned(), + "--force".to_owned(), + // install-links will copy local dependencies into the node_modules folder instead of + // symlinking, which fixes our root detection. + "--install-links".to_owned(), + "true".to_owned(), + ]; + args.append(&mut packages.iter().map(|p| p.to_string()).collect::>()); + + let npm = command("npm").args(args).current_dir(install_dir).output()?; + + if !npm.status.success() { + io::stdout().write_all(&npm.stdout)?; + io::stderr().write_all(&npm.stderr)?; + return Err(anyhow!("npm install failed. See above.")); + } + + Ok(()) +} diff --git a/crates/turbopack-bench/Source/util/page_guard.rs b/crates/turbopack-bench/Source/util/page_guard.rs new file mode 100644 index 0000000000000..74a76e6b42f2f --- /dev/null +++ b/crates/turbopack-bench/Source/util/page_guard.rs @@ -0,0 +1,100 @@ +use std::{sync::Arc, time::Duration}; + +use anyhow::{Context, Result, anyhow}; +use chromiumoxide::{ + Page, + cdp::js_protocol::runtime::{EventBindingCalled, EventExceptionThrown}, + listeners::EventStream, +}; +use futures::{Stream, StreamExt}; +use tokio::time::timeout; + +use crate::{BINDING_NAME, PreparedApp}; + +const MAX_HYDRATION_TIMEOUT:Duration = Duration::from_secs(120); +const TEST_APP_HYDRATION_DONE:&str = "Hydration done"; + +/// Closes a browser page on Drop. +pub struct PageGuard<'a> { + page:Option, + app:Option>, + events:Box + Unpin>, +} + +enum Event { + EventBindingCalled(Arc), + EventExceptionThrown(Arc), +} + +impl<'a> PageGuard<'a> { + /// Creates a new guard for the given page. + pub fn new( + page:Page, + events:EventStream, + errors:EventStream, + app:PreparedApp<'a>, + ) -> Self { + Self { + page:Some(page), + app:Some(app), + events:Box::new(futures::stream::select( + events.map(Event::EventBindingCalled), + errors.map(Event::EventExceptionThrown), + )), + } + } + + /// Returns a reference to the page. + pub fn page(&self) -> &Page { + // Invariant: page is always Some while the guard is alive. + self.page.as_ref().unwrap() + } + + /// Closes the page, returns the app. + pub async fn close_page(mut self) -> Result> { + // Invariant: the page is always Some while the guard is alive. + self.page.take().unwrap().close().await?; + Ok( + // Invariant: the app is always Some while the guard is alive. + self.app.take().unwrap(), + ) + } + + /// Waits until the binding is called with the given payload. + pub async fn wait_for_binding(&mut self, payload:&str) -> Result<()> { + while let Some(event) = self.events.next().await { + match event { + Event::EventBindingCalled(event) => { + if event.name == BINDING_NAME && event.payload == payload { + return Ok(()); + } + }, + Event::EventExceptionThrown(event) => { + return Err(anyhow!("Exception throw in page: {}", event.exception_details)); + }, + } + } + + Err(anyhow!("event stream ended before binding was called")) + } + + /// Waits until the page and the page JavaScript is hydrated. + pub async fn wait_for_hydration(&mut self) -> Result<()> { + timeout(MAX_HYDRATION_TIMEOUT, self.wait_for_binding(TEST_APP_HYDRATION_DONE)) + .await + .context("Timeout happened while waiting for hydration")? + .context("Error happened while waiting for hydration")?; + Ok(()) + } +} + +impl<'a> Drop for PageGuard<'a> { + fn drop(&mut self) { + // The page might have been closed already in `close_page`. + if let Some(page) = self.page.take() { + // This is a way to block on a future in a destructor. It's not ideal, but for + // the purposes of this benchmark it's fine. + futures::executor::block_on(page.close()).expect("failed to close page"); + } + } +} diff --git a/crates/turbopack-bench/Source/util/prepared_app.rs b/crates/turbopack-bench/Source/util/prepared_app.rs new file mode 100644 index 0000000000000..2c0ecd106f98a --- /dev/null +++ b/crates/turbopack-bench/Source/util/prepared_app.rs @@ -0,0 +1,227 @@ +use std::{ + future::Future, + path::{Path, PathBuf}, + pin::Pin, + process::Child, +}; + +use anyhow::{Context, Result, anyhow}; +use chromiumoxide::{ + Browser, + Page, + cdp::{ + browser_protocol::network::EventResponseReceived, + js_protocol::runtime::{AddBindingParams, EventBindingCalled, EventExceptionThrown}, + }, +}; +use futures::{FutureExt, StreamExt}; +use tokio::task::spawn_blocking; +use url::Url; + +use crate::{BINDING_NAME, bundlers::Bundler, util::PageGuard}; + +fn copy_dir_boxed( + from:PathBuf, + to:PathBuf, +) -> Pin> + Sync + Send>> { + Box::pin(copy_dir(from, to)) +} + +async fn copy_dir(from:PathBuf, to:PathBuf) -> anyhow::Result<()> { + let dir = spawn_blocking(|| std::fs::read_dir(from)).await??; + let mut jobs = Vec::new(); + let mut file_futures = Vec::new(); + for entry in dir { + let entry = entry?; + let ty = entry.file_type()?; + let to = to.join(entry.file_name()); + if ty.is_dir() { + jobs.push(tokio::spawn(async move { + tokio::fs::create_dir(&to).await?; + copy_dir_boxed(entry.path(), to).await + })); + } else if ty.is_file() { + file_futures.push(async move { + tokio::fs::copy(entry.path(), to).await?; + Ok::<_, anyhow::Error>(()) + }); + } + } + + for future in file_futures { + jobs.push(tokio::spawn(future)); + } + + for job in jobs { + job.await??; + } + + Ok(()) +} + +enum PreparedDir { + TempDir(tempfile::TempDir), + Path(PathBuf), +} + +pub struct PreparedApp<'a> { + bundler:&'a dyn Bundler, + server:Option<(Child, String)>, + test_dir:PreparedDir, +} + +impl<'a> PreparedApp<'a> { + pub async fn new(bundler:&'a dyn Bundler, template_dir:PathBuf) -> Result> { + let test_dir = tempfile::tempdir()?; + + tokio::fs::create_dir_all(&test_dir).await?; + copy_dir(template_dir, test_dir.path().to_path_buf()).await?; + + Ok(Self { bundler, server:None, test_dir:PreparedDir::TempDir(test_dir) }) + } + + pub async fn new_without_copy( + bundler:&'a dyn Bundler, + template_dir:PathBuf, + ) -> Result> { + Ok(Self { bundler, server:None, test_dir:PreparedDir::Path(template_dir) }) + } + + pub fn start_server(&mut self) -> Result<()> { + assert!(self.server.is_none(), "Server already started"); + + self.server = Some(self.bundler.start_server(self.path())?); + + Ok(()) + } + + pub async fn with_page(self, browser:&Browser) -> Result> { + let server = self.server.as_ref().context("Server must be started")?; + let page = browser.new_page("about:blank").await.context("Unable to open about:blank")?; + // Bindings survive page reloads. Set them up as early as possible. + add_binding(&page).await.context("Failed to add bindings to the browser tab")?; + + let mut errors = page + .event_listener::() + .await + .context("Unable to listen to exception events")?; + let binding_events = page + .event_listener::() + .await + .context("Unable to listen to binding events")?; + let mut network_response_events = page + .event_listener::() + .await + .context("Unable to listen to response received events")?; + + let destination = Url::parse(&server.1)?.join(self.bundler.get_path())?; + // We can't use page.goto() here since this will wait for the naviation to be + // completed. A naviation would be complete when all sync script are + // evaluated, but the page actually can rendered earlier without JavaScript + // needing to be evaluated. + // So instead we navigate via JavaScript and wait only for the HTML response to + // be completed. + page.evaluate_expression(format!("window.location='{destination}'")) + .await + .context("Unable to evaluate javascript to naviagate to target page")?; + + // Wait for HTML response completed + loop { + match network_response_events.next().await { + Some(event) => { + if event.response.url == destination.as_str() { + break; + } + }, + None => return Err(anyhow!("event stream ended too early")), + } + } + + // Make sure no runtime errors occurred when loading the page + assert!(errors.next().now_or_never().is_none()); + + let page_guard = PageGuard::new(page, binding_events, errors, self); + + Ok(page_guard) + } + + pub fn stop_server(&mut self) -> Result<()> { + let mut proc = self.server.take().expect("Server never started").0; + stop_process(&mut proc)?; + Ok(()) + } + + pub fn path(&self) -> &Path { + match self.test_dir { + PreparedDir::TempDir(ref dir) => dir.path(), + PreparedDir::Path(ref path) => path, + } + } +} + +impl<'a> Drop for PreparedApp<'a> { + fn drop(&mut self) { + if let Some(mut server) = self.server.take() { + stop_process(&mut server.0).expect("failed to stop process"); + } + } +} + +/// Adds benchmark-specific bindings to the page. +async fn add_binding(page:&Page) -> Result<()> { + page.execute(AddBindingParams::new(BINDING_NAME)).await?; + Ok(()) +} + +#[cfg(unix)] +fn stop_process(proc:&mut Child) -> Result<()> { + use std::time::Duration; + + use nix::{ + sys::signal::{Signal, kill}, + unistd::Pid, + }; + use owo_colors::OwoColorize; + + const KILL_DEADLINE:Duration = Duration::from_secs(5); + const KILL_DEADLINE_CHECK_STEPS:u32 = 10; + + let pid = Pid::from_raw(proc.id() as _); + match kill(pid, Signal::SIGINT) { + Ok(()) => { + let expire = std::time::Instant::now() + KILL_DEADLINE; + while let Ok(None) = proc.try_wait() { + if std::time::Instant::now() > expire { + break; + } + std::thread::sleep(KILL_DEADLINE / KILL_DEADLINE_CHECK_STEPS); + } + if let Ok(None) = proc.try_wait() { + eprintln!( + "{event_type} - process {pid} did not exit after SIGINT, sending SIGKILL", + event_type = "error".red(), + pid = pid + ); + kill_process(proc)?; + } + }, + Err(_) => { + eprintln!( + "{event_type} - failed to send SIGINT to process {pid}, sending SIGKILL", + event_type = "error".red(), + pid = pid + ); + kill_process(proc)?; + }, + } + Ok(()) +} + +#[cfg(not(unix))] +fn stop_process(proc:&mut Child) -> Result<()> { kill_process(proc) } + +fn kill_process(proc:&mut Child) -> Result<()> { + proc.kill()?; + proc.wait()?; + Ok(()) +} diff --git a/crates/turbopack-bench/benches/mod.rs b/crates/turbopack-bench/benches/mod.rs new file mode 100644 index 0000000000000..696d65bff2e51 --- /dev/null +++ b/crates/turbopack-bench/benches/mod.rs @@ -0,0 +1,29 @@ +use criterion::{Criterion, criterion_group, criterion_main}; +use turbopack_bench::bundlers::Bundler; + +fn get_bundlers() -> Vec> { turbopack_bench::bundlers::get_bundlers() } + +fn bench_startup(c:&mut Criterion) { turbopack_bench::bench_startup(c, &get_bundlers()) } + +fn bench_hydration(c:&mut Criterion) { turbopack_bench::bench_hydration(c, &get_bundlers()) } + +fn bench_startup_cached(c:&mut Criterion) { + turbopack_bench::bench_startup_cached(c, &get_bundlers()) +} + +fn bench_hydration_cached(c:&mut Criterion) { + turbopack_bench::bench_hydration_cached(c, &get_bundlers()) +} + +fn bench_hmr_to_eval(c:&mut Criterion) { turbopack_bench::bench_hmr_to_eval(c, &get_bundlers()) } + +fn bench_hmr_to_commit(c:&mut Criterion) { + turbopack_bench::bench_hmr_to_commit(c, &get_bundlers()) +} + +criterion_group!( + name = benches; + config = Criterion::default(); + targets = bench_startup, bench_hydration, bench_startup_cached, bench_hydration_cached, bench_hmr_to_eval, bench_hmr_to_commit +); +criterion_main!(benches); diff --git a/crates/turbopack-binding/Source/lib.rs b/crates/turbopack-binding/Source/lib.rs new file mode 100644 index 0000000000000..e8b0feb760234 --- /dev/null +++ b/crates/turbopack-binding/Source/lib.rs @@ -0,0 +1,117 @@ +#[cfg(feature = "__swc")] +pub mod swc { + #[cfg(feature = "__swc_core")] + pub use swc_core as core; + + #[cfg(feature = "__swc_custom_transform")] + pub mod custom_transform { + #[cfg(feature = "__swc_transform_modularize_imports")] + pub use modularize_imports; + #[cfg(feature = "__swc_transform_styled_components")] + pub use styled_components; + #[cfg(feature = "__swc_transform_styled_jsx")] + pub use styled_jsx; + #[cfg(feature = "__swc_transform_emotion")] + pub use swc_emotion as emotion; + #[cfg(feature = "__swc_transform_relay")] + pub use swc_relay as relay; + } + + #[cfg(feature = "testing")] + pub use testing; +} + +#[cfg(feature = "__turbo")] +pub mod turbo { + #[cfg(feature = "__turbo_tasks")] + pub use turbo_tasks as tasks; + #[cfg(feature = "__turbo_tasks_build")] + pub use turbo_tasks_build as tasks_build; + #[cfg(feature = "__turbo_tasks_bytes")] + pub use turbo_tasks_bytes as tasks_bytes; + #[cfg(feature = "__turbo_tasks_env")] + pub use turbo_tasks_env as tasks_env; + #[cfg(feature = "__turbo_tasks_fetch")] + pub use turbo_tasks_fetch as tasks_fetch; + #[cfg(feature = "__turbo_tasks_fs")] + pub use turbo_tasks_fs as tasks_fs; + #[cfg(feature = "__turbo_tasks_hash")] + pub use turbo_tasks_hash as tasks_hash; + #[cfg(feature = "__turbo_tasks_macros")] + pub use turbo_tasks_macros as tasks_macros; + #[cfg(feature = "__turbo_tasks_macros_shared")] + pub use turbo_tasks_macros_shared as tasks_macros_shared; + #[cfg(feature = "__turbo_tasks_malloc")] + pub use turbo_tasks_malloc as malloc; + #[cfg(feature = "__turbo_tasks_memory")] + pub use turbo_tasks_memory as tasks_memory; + #[cfg(feature = "__turbo_tasks_testing")] + pub use turbo_tasks_testing as tasks_testing; + #[cfg(feature = "__turbo_updater")] + pub use turbo_updater as updater; +} + +#[cfg(feature = "__turbopack")] +pub mod turbopack { + pub use turbopack; + #[cfg(feature = "__turbopack_bench")] + pub use turbopack_bench as bench; + #[cfg(feature = "__turbopack_browser")] + pub use turbopack_browser as browser; + #[cfg(feature = "__turbopack_cli_utils")] + pub use turbopack_cli_utils as cli_utils; + #[cfg(feature = "__turbopack_core")] + pub use turbopack_core as core; + #[cfg(feature = "__turbopack_create_test_app")] + pub use turbopack_create_test_app as create_test_app; + #[cfg(feature = "__turbopack_css")] + pub use turbopack_css as css; + #[cfg(feature = "__turbopack_dev_server")] + pub use turbopack_dev_server as dev_server; + #[cfg(feature = "__turbopack_ecmascript")] + pub use turbopack_ecmascript as ecmascript; + #[cfg(feature = "__turbopack_ecmascript_hmr_protocol")] + pub use turbopack_ecmascript_hmr_protocol as ecmascript_hmr_protocol; + #[cfg(feature = "__turbopack_ecmascript_plugin")] + pub use turbopack_ecmascript_plugins as ecmascript_plugin; + #[cfg(feature = "__turbopack_ecmascript_runtime")] + pub use turbopack_ecmascript_runtime as ecmascript_runtime; + #[cfg(feature = "__turbopack_env")] + pub use turbopack_env as env; + #[cfg(feature = "__turbopack_image")] + pub use turbopack_image as image; + #[cfg(feature = "__turbopack_json")] + pub use turbopack_json as json; + #[cfg(feature = "__turbopack_mdx")] + pub use turbopack_mdx as mdx; + #[cfg(feature = "__turbopack_node")] + pub use turbopack_node as node; + #[cfg(feature = "__turbopack_nodejs")] + pub use turbopack_nodejs as nodejs; + #[cfg(feature = "__turbopack_static")] + pub use turbopack_static as r#static; + #[cfg(feature = "__turbopack_swc_utils")] + pub use turbopack_swc_utils as swc_utils; + #[cfg(feature = "__turbopack_test_utils")] + pub use turbopack_test_utils as test_utils; + #[cfg(feature = "__turbopack_tests")] + pub use turbopack_tests as tests; + #[cfg(feature = "__turbopack_trace_server")] + pub use turbopack_trace_server as trace_server; + #[cfg(feature = "__turbopack_trace_utils")] + pub use turbopack_trace_utils as trace_utils; +} + +#[cfg(feature = "__features")] +pub mod features { + #[cfg(feature = "__feature_auto_hash_map")] + pub use auto_hash_map; + #[cfg(feature = "__feature_mdx_rs")] + pub use mdxjs; + #[cfg(feature = "__feature_node_file_trace")] + pub use node_file_trace; + #[cfg(feature = "__feature_swc_ast_explorer")] + pub use swc_ast_explorer; + #[cfg(feature = "__feature_tracing_signpost")] + pub use tracing_signpost; +} diff --git a/crates/turbopack-browser/Source/chunking_context.rs b/crates/turbopack-browser/Source/chunking_context.rs new file mode 100644 index 0000000000000..031aa52eb475b --- /dev/null +++ b/crates/turbopack-browser/Source/chunking_context.rs @@ -0,0 +1,468 @@ +use anyhow::{Context, Result, bail}; +use tracing::Instrument; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + chunk::{ + Chunk, + ChunkGroupResult, + ChunkItem, + ChunkableModule, + ChunkingContext, + EntryChunkGroupResult, + EvaluatableAssets, + MinifyType, + ModuleId, + availability_info::AvailabilityInfo, + chunk_group::{MakeChunkGroupResult, make_chunk_group}, + }, + environment::Environment, + ident::AssetIdent, + module::Module, + output::{OutputAsset, OutputAssets}, +}; +use turbopack_ecmascript::{ + async_chunk::module::AsyncLoaderModule, + chunk::EcmascriptChunk, + manifest::{chunk_asset::ManifestAsyncModule, loader_item::ManifestLoaderChunkItem}, +}; +use turbopack_ecmascript_runtime::RuntimeType; + +use crate::ecmascript::{ + chunk::EcmascriptDevChunk, + evaluate::chunk::EcmascriptDevEvaluateChunk, + list::asset::{EcmascriptDevChunkList, EcmascriptDevChunkListSource}, +}; + +pub struct BrowserChunkingContextBuilder { + chunking_context:BrowserChunkingContext, +} + +impl BrowserChunkingContextBuilder { + pub fn name(mut self, name:RcStr) -> Self { + self.chunking_context.name = Some(name); + self + } + + pub fn hot_module_replacement(mut self) -> Self { + self.chunking_context.enable_hot_module_replacement = true; + self + } + + pub fn asset_base_path(mut self, asset_base_path:Vc>) -> Self { + self.chunking_context.asset_base_path = asset_base_path; + self + } + + pub fn chunk_base_path(mut self, chunk_base_path:Vc>) -> Self { + self.chunking_context.chunk_base_path = chunk_base_path; + self + } + + pub fn reference_chunk_source_maps(mut self, source_maps:bool) -> Self { + self.chunking_context.reference_chunk_source_maps = source_maps; + self + } + + pub fn reference_css_chunk_source_maps(mut self, source_maps:bool) -> Self { + self.chunking_context.reference_css_chunk_source_maps = source_maps; + self + } + + pub fn runtime_type(mut self, runtime_type:RuntimeType) -> Self { + self.chunking_context.runtime_type = runtime_type; + self + } + + pub fn manifest_chunks(mut self, manifest_chunks:bool) -> Self { + self.chunking_context.manifest_chunks = manifest_chunks; + self + } + + pub fn minify_type(mut self, minify_type:MinifyType) -> Self { + self.chunking_context.minify_type = minify_type; + self + } + + pub fn build(self) -> Vc { + BrowserChunkingContext::new(Value::new(self.chunking_context)) + } +} + +/// A chunking context for development mode. +/// It uses readable filenames and module ids to improve development. +/// It also uses a chunking heuristic that is incremental and cacheable. +/// It splits "node_modules" separately as these are less likely to change +/// during development +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(Debug, Clone, Hash, PartialOrd, Ord)] +pub struct BrowserChunkingContext { + name:Option, + /// This path get stripped off of chunk paths before generating output asset + /// paths. + context_path:Vc, + /// This path is used to compute the url to request chunks from + output_root:Vc, + /// This path is used to compute the url to request assets from + client_root:Vc, + /// Chunks are placed at this path + chunk_root_path:Vc, + /// Chunks reference source maps assets + reference_chunk_source_maps:bool, + /// Css chunks reference source maps assets + reference_css_chunk_source_maps:bool, + /// Static assets are placed at this path + asset_root_path:Vc, + /// Base path that will be prepended to all chunk URLs when loading them. + /// This path will not appear in chunk paths or chunk data. + chunk_base_path:Vc>, + /// URL prefix that will be prepended to all static asset URLs when loading + /// them. + asset_base_path:Vc>, + /// Enable HMR for this chunking + enable_hot_module_replacement:bool, + /// The environment chunks will be evaluated in. + environment:Vc, + /// The kind of runtime to include in the output. + runtime_type:RuntimeType, + /// Whether to minify resulting chunks + minify_type:MinifyType, + /// Whether to use manifest chunks for lazy compilation + manifest_chunks:bool, +} + +impl BrowserChunkingContext { + pub fn builder( + context_path:Vc, + output_root:Vc, + client_root:Vc, + chunk_root_path:Vc, + asset_root_path:Vc, + environment:Vc, + runtime_type:RuntimeType, + ) -> BrowserChunkingContextBuilder { + BrowserChunkingContextBuilder { + chunking_context:BrowserChunkingContext { + name:None, + context_path, + output_root, + client_root, + chunk_root_path, + reference_chunk_source_maps:true, + reference_css_chunk_source_maps:true, + asset_root_path, + chunk_base_path:Default::default(), + asset_base_path:Default::default(), + enable_hot_module_replacement:false, + environment, + runtime_type, + minify_type:MinifyType::NoMinify, + manifest_chunks:false, + }, + } + } +} + +impl BrowserChunkingContext { + /// Returns the kind of runtime to include in output chunks. + /// + /// This is defined directly on `BrowserChunkingContext` so it is zero-cost + /// when `RuntimeType` has a single variant. + pub fn runtime_type(&self) -> RuntimeType { self.runtime_type } + + /// Returns the asset base path. + pub fn chunk_base_path(&self) -> Vc> { self.chunk_base_path } + + /// Returns the minify type. + pub fn minify_type(&self) -> MinifyType { self.minify_type } +} + +#[turbo_tasks::value_impl] +impl BrowserChunkingContext { + #[turbo_tasks::function] + fn new(this:Value) -> Vc { this.into_value().cell() } + + #[turbo_tasks::function] + fn generate_evaluate_chunk( + self: Vc, + ident:Vc, + other_chunks:Vc, + evaluatable_assets:Vc, + ) -> Vc> { + Vc::upcast(EcmascriptDevEvaluateChunk::new(self, ident, other_chunks, evaluatable_assets)) + } + + #[turbo_tasks::function] + fn generate_chunk_list_register_chunk( + self: Vc, + ident:Vc, + evaluatable_assets:Vc, + other_chunks:Vc, + source:Value, + ) -> Vc> { + Vc::upcast(EcmascriptDevChunkList::new( + self, + ident, + evaluatable_assets, + other_chunks, + source, + )) + } + + #[turbo_tasks::function] + async fn generate_chunk( + self: Vc, + chunk:Vc>, + ) -> Result>> { + Ok( + if let Some(ecmascript_chunk) = + Vc::try_resolve_downcast_type::(chunk).await? + { + Vc::upcast(EcmascriptDevChunk::new(self, ecmascript_chunk)) + } else if let Some(output_asset) = + Vc::try_resolve_sidecast::>(chunk).await? + { + output_asset + } else { + bail!("Unable to generate output asset for chunk"); + }, + ) + } +} + +#[turbo_tasks::value_impl] +impl ChunkingContext for BrowserChunkingContext { + #[turbo_tasks::function] + fn name(&self) -> Vc { + if let Some(name) = &self.name { + Vc::cell(name.clone()) + } else { + Vc::cell("unknown".into()) + } + } + + #[turbo_tasks::function] + fn context_path(&self) -> Vc { self.context_path } + + #[turbo_tasks::function] + fn output_root(&self) -> Vc { self.output_root } + + #[turbo_tasks::function] + fn environment(&self) -> Vc { self.environment } + + #[turbo_tasks::function] + async fn chunk_path( + &self, + ident:Vc, + extension:RcStr, + ) -> Result> { + let root_path = self.chunk_root_path; + let name = ident.output_name(self.context_path, extension).await?; + Ok(root_path.join(name.clone_value())) + } + + #[turbo_tasks::function] + async fn asset_url(self: Vc, ident:Vc) -> Result> { + let this = self.await?; + let asset_path = ident.path().await?.to_string(); + let asset_path = asset_path + .strip_prefix(&format!("{}/", this.client_root.await?.path)) + .context("expected asset_path to contain client_root")?; + + Ok(Vc::cell( + format!( + "{}{}", + this.asset_base_path.await?.as_ref().map(|s| s.as_str()).unwrap_or("/"), + asset_path + ) + .into(), + )) + } + + #[turbo_tasks::function] + async fn reference_chunk_source_maps( + &self, + chunk:Vc>, + ) -> Result> { + let mut source_maps = self.reference_chunk_source_maps; + let path = chunk.ident().path().await?; + let extension = path.extension_ref().unwrap_or_default(); + #[allow(clippy::single_match, reason = "future extensions")] + match extension { + ".css" => { + source_maps = self.reference_css_chunk_source_maps; + }, + _ => {}, + } + Ok(Vc::cell(source_maps)) + } + + #[turbo_tasks::function] + async fn asset_path( + &self, + content_hash:RcStr, + original_asset_ident:Vc, + ) -> Result> { + let source_path = original_asset_ident.path().await?; + let basename = source_path.file_name(); + let asset_path = match source_path.extension_ref() { + Some(ext) => { + format!( + "{basename}.{content_hash}.{ext}", + basename = &basename[..basename.len() - ext.len() - 1], + content_hash = &content_hash[..8] + ) + }, + None => format!("{basename}.{content_hash}", content_hash = &content_hash[..8]), + }; + Ok(self.asset_root_path.join(asset_path.into())) + } + + #[turbo_tasks::function] + fn is_hot_module_replacement_enabled(&self) -> Vc { + Vc::cell(self.enable_hot_module_replacement) + } + + #[turbo_tasks::function] + async fn chunk_group( + self: Vc, + module:Vc>, + availability_info:Value, + ) -> Result> { + let span = + tracing::info_span!("chunking", module = module.ident().to_string().await?.to_string()); + async move { + let this = self.await?; + let input_availability_info = availability_info.into_value(); + let MakeChunkGroupResult { chunks, availability_info } = + make_chunk_group(Vc::upcast(self), [Vc::upcast(module)], input_availability_info) + .await?; + + let mut assets:Vec>> = + chunks.iter().map(|chunk| self.generate_chunk(*chunk)).collect(); + + if this.enable_hot_module_replacement { + let mut ident = module.ident(); + match input_availability_info { + AvailabilityInfo::Root => {}, + AvailabilityInfo::Untracked => { + ident = ident.with_modifier(Vc::cell("untracked".into())); + }, + AvailabilityInfo::Complete { available_chunk_items } => { + ident = ident.with_modifier(Vc::cell( + available_chunk_items.hash().await?.to_string().into(), + )); + }, + } + assets.push(self.generate_chunk_list_register_chunk( + ident, + EvaluatableAssets::empty(), + Vc::cell(assets.clone()), + Value::new(EcmascriptDevChunkListSource::Dynamic), + )); + } + + // Resolve assets + for asset in assets.iter_mut() { + *asset = asset.resolve().await?; + } + + Ok(ChunkGroupResult { assets:Vc::cell(assets), availability_info }.cell()) + } + .instrument(span) + .await + } + + #[turbo_tasks::function] + async fn evaluated_chunk_group( + self: Vc, + ident:Vc, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Result> { + let span = { + let ident = ident.to_string().await?.to_string(); + tracing::info_span!("chunking", chunking_type = "evaluated", ident = ident) + }; + async move { + let this = self.await?; + let availability_info = availability_info.into_value(); + + let evaluatable_assets_ref = evaluatable_assets.await?; + + // TODO this collect is unnecessary, but it hits a compiler bug when it's not + // used + let entries = evaluatable_assets_ref + .iter() + .map(|&evaluatable| Vc::upcast(evaluatable)) + .collect::>(); + + let MakeChunkGroupResult { chunks, availability_info } = + make_chunk_group(Vc::upcast(self), entries, availability_info).await?; + + let mut assets:Vec>> = + chunks.iter().map(|chunk| self.generate_chunk(*chunk)).collect(); + + let other_assets = Vc::cell(assets.clone()); + + if this.enable_hot_module_replacement { + assets.push(self.generate_chunk_list_register_chunk( + ident, + evaluatable_assets, + other_assets, + Value::new(EcmascriptDevChunkListSource::Entry), + )); + } + + assets.push(self.generate_evaluate_chunk(ident, other_assets, evaluatable_assets)); + + // Resolve assets + for asset in assets.iter_mut() { + *asset = asset.resolve().await?; + } + + Ok(ChunkGroupResult { assets:Vc::cell(assets), availability_info }.cell()) + } + .instrument(span) + .await + } + + #[turbo_tasks::function] + fn entry_chunk_group( + self: Vc, + _path:Vc, + _module:Vc>, + _evaluatable_assets:Vc, + _availability_info:Value, + ) -> Result> { + bail!("Browser chunking context does not support entry chunk groups") + } + + #[turbo_tasks::function] + async fn async_loader_chunk_item( + self: Vc, + module:Vc>, + availability_info:Value, + ) -> Result>> { + Ok(if self.await?.manifest_chunks { + let manifest_asset = + ManifestAsyncModule::new(module, Vc::upcast(self), availability_info); + Vc::upcast(ManifestLoaderChunkItem::new(manifest_asset, Vc::upcast(self))) + } else { + let module = AsyncLoaderModule::new(module, Vc::upcast(self), availability_info); + Vc::upcast(module.as_chunk_item(Vc::upcast(self))) + }) + } + + #[turbo_tasks::function] + async fn async_loader_chunk_item_id( + self: Vc, + module:Vc>, + ) -> Result> { + Ok(if self.await?.manifest_chunks { + self.chunk_item_id_from_ident(ManifestLoaderChunkItem::asset_ident_for(module)) + } else { + self.chunk_item_id_from_ident(AsyncLoaderModule::asset_ident_for(module)) + }) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/chunk.rs b/crates/turbopack-browser/Source/ecmascript/chunk.rs new file mode 100644 index 0000000000000..15b1fa732ff5f --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/chunk.rs @@ -0,0 +1,141 @@ +use anyhow::Result; +use indexmap::IndexSet; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{Chunk, ChunkingContext, OutputChunk, OutputChunkRuntimeInfo}, + ident::AssetIdent, + introspect::{Introspectable, IntrospectableChildren}, + output::{OutputAsset, OutputAssets}, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAsset}, + version::VersionedContent, +}; +use turbopack_ecmascript::chunk::EcmascriptChunk; + +use crate::{BrowserChunkingContext, ecmascript::content::EcmascriptDevChunkContent}; + +/// Development Ecmascript chunk. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptDevChunk { + chunking_context:Vc, + chunk:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunk { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new(chunking_context:Vc, chunk:Vc) -> Vc { + EcmascriptDevChunk { chunking_context, chunk }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptDevChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { Ok(Vc::cell("Ecmascript Dev Chunk".into())) } +} + +#[turbo_tasks::value_impl] +impl OutputChunk for EcmascriptDevChunk { + #[turbo_tasks::function] + fn runtime_info(&self) -> Vc { + OutputChunkRuntimeInfo { included_ids:Some(self.chunk.entry_ids()), ..Default::default() } + .cell() + } +} + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("ecmascript dev chunk".into()) } + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunk { + #[turbo_tasks::function] + async fn own_content(self: Vc) -> Result> { + let this = self.await?; + Ok(EcmascriptDevChunkContent::new( + this.chunking_context, + self, + this.chunk.chunk_content(), + )) + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for EcmascriptDevChunk { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + let ident = self.chunk.ident().with_modifier(modifier()); + AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".into())) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let chunk_references = this.chunk.references().await?; + let include_source_map = + *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await?; + let mut references = + Vec::with_capacity(chunk_references.len() + if include_source_map { 1 } else { 0 }); + + references.extend(chunk_references.iter().copied()); + + if include_source_map { + references.push(Vc::upcast(SourceMapAsset::new(Vc::upcast(self)))); + } + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptDevChunk { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { self.own_content().content() } + + #[turbo_tasks::function] + fn versioned_content(self: Vc) -> Vc> { + Vc::upcast(self.own_content()) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptDevChunk { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.own_content().generate_source_map() + } + + #[turbo_tasks::function] + fn by_section(self: Vc, section:RcStr) -> Vc { + self.own_content().by_section(section) + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("dev ecmascript chunk".into()) } + +#[turbo_tasks::function] +fn introspectable_details() -> Vc { + Vc::cell("generates a development ecmascript chunk".into()) +} + +#[turbo_tasks::value_impl] +impl Introspectable for EcmascriptDevChunk { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(self: Vc) -> Vc { self.ident().to_string() } + + #[turbo_tasks::function] + fn details(&self) -> Vc { introspectable_details() } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + let mut children = IndexSet::new(); + let chunk = Vc::upcast::>(self.chunk).resolve().await?; + children.insert((Vc::cell("chunk".into()), chunk)); + Ok(Vc::cell(children)) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/content.rs b/crates/turbopack-browser/Source/ecmascript/content.rs new file mode 100644 index 0000000000000..cfc23fabdc35b --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/content.rs @@ -0,0 +1,160 @@ +use std::io::Write; + +use anyhow::{Result, bail}; +use indoc::writedoc; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::AssetContent, + chunk::{ChunkingContext, MinifyType, ModuleId}, + code_builder::{Code, CodeBuilder}, + output::OutputAsset, + source_map::{GenerateSourceMap, OptionSourceMap}, + version::{MergeableVersionedContent, Version, VersionedContent, VersionedContentMerger}, +}; +use turbopack_ecmascript::{chunk::EcmascriptChunkContent, minify::minify, utils::StringifyJs}; + +use super::{ + chunk::EcmascriptDevChunk, + content_entry::EcmascriptDevChunkContentEntries, + merged::merger::EcmascriptDevChunkContentMerger, + version::EcmascriptDevChunkVersion, +}; +use crate::BrowserChunkingContext; + +#[turbo_tasks::value(serialization = "none")] +pub struct EcmascriptDevChunkContent { + pub(super) entries:Vc, + pub(super) chunking_context:Vc, + pub(super) chunk:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkContent { + #[turbo_tasks::function] + pub(crate) async fn new( + chunking_context:Vc, + chunk:Vc, + content:Vc, + ) -> Result> { + let entries = EcmascriptDevChunkContentEntries::new(content).resolve().await?; + Ok(EcmascriptDevChunkContent { entries, chunking_context, chunk }.cell()) + } + + #[turbo_tasks::function] + pub async fn entries( + self: Vc, + ) -> Result> { + Ok(self.await?.entries) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkContent { + #[turbo_tasks::function] + pub(crate) async fn own_version(self: Vc) -> Result> { + let this = self.await?; + Ok(EcmascriptDevChunkVersion::new( + this.chunking_context.output_root(), + this.chunk.ident().path(), + this.entries, + )) + } + + #[turbo_tasks::function] + async fn code(self: Vc) -> Result> { + let this = self.await?; + let output_root = this.chunking_context.output_root().await?; + let chunk_path_vc = this.chunk.ident().path(); + let chunk_path = chunk_path_vc.await?; + let chunk_server_path = if let Some(path) = output_root.get_path_to(&chunk_path) { + path + } else { + bail!( + "chunk path {} is not in output root {}", + chunk_path.to_string(), + output_root.to_string() + ); + }; + let mut code = CodeBuilder::default(); + + // When a chunk is executed, it will either register itself with the current + // instance of the runtime, or it will push itself onto the list of pending + // chunks (`self.TURBOPACK`). + // + // When the runtime executes (see the `evaluate` module), it will pick up and + // register all pending chunks, and replace the list of pending chunks + // with itself so later chunks can register directly with it. + writedoc!( + code, + r#" + (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([{chunk_path}, {{ + "#, + chunk_path = StringifyJs(chunk_server_path) + )?; + + for (id, entry) in this.entries.await?.iter() { + write!(code, "\n{}: ", StringifyJs(&id))?; + code.push_code(&*entry.code.await?); + write!(code, ",")?; + } + + write!(code, "\n}}]);")?; + + if code.has_source_map() { + let filename = chunk_path.file_name(); + write!(code, "\n\n//# sourceMappingURL={}.map", urlencoding::encode(filename))?; + } + + let code = code.build().cell(); + if matches!(this.chunking_context.await?.minify_type(), MinifyType::Minify) { + return Ok(minify(chunk_path_vc, code)); + } + + Ok(code) + } +} + +#[turbo_tasks::value_impl] +impl VersionedContent for EcmascriptDevChunkContent { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } + + #[turbo_tasks::function] + fn version(self: Vc) -> Vc> { Vc::upcast(self.own_version()) } +} + +#[turbo_tasks::value_impl] +impl MergeableVersionedContent for EcmascriptDevChunkContent { + #[turbo_tasks::function] + fn get_merger(&self) -> Vc> { + Vc::upcast(EcmascriptDevChunkContentMerger::new()) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptDevChunkContent { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() + } + + #[turbo_tasks::function] + async fn by_section(&self, section:RcStr) -> Result> { + // Weirdly, the ContentSource will have already URL decoded the ModuleId, and we + // can't reparse that via serde. + if let Ok(id) = ModuleId::parse(§ion) { + for (entry_id, entry) in self.entries.await?.iter() { + if id == **entry_id { + let sm = entry.code.generate_source_map(); + return Ok(sm); + } + } + } + + Ok(Vc::cell(None)) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/content_entry.rs b/crates/turbopack-browser/Source/ecmascript/content_entry.rs new file mode 100644 index 0000000000000..b20bc61f0c594 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/content_entry.rs @@ -0,0 +1,120 @@ +use std::io::Write as _; + +use anyhow::Result; +use indexmap::IndexMap; +use tracing::{Instrument, info_span}; +use turbo_tasks::{ReadRef, TryJoinIterExt, ValueToString, Vc}; +use turbopack_core::{ + chunk::{AsyncModuleInfo, ChunkItem, ChunkItemExt, ModuleId}, + code_builder::{Code, CodeBuilder}, + error::PrettyPrintError, + issue::{IssueExt, IssueSeverity, StyledString, code_gen::CodeGenerationIssue}, +}; +use turbopack_ecmascript::chunk::{ + EcmascriptChunkContent, + EcmascriptChunkItem, + EcmascriptChunkItemExt, +}; + +/// A chunk item's content entry. +/// +/// Instead of storing the [`Vc>`] itself from +/// which `code` and `hash` are derived, we store `Vc`s directly. This avoids +/// creating tasks in a hot loop when iterating over thousands of entries when +/// computing updates. +#[turbo_tasks::value] +#[derive(Debug)] +pub struct EcmascriptDevChunkContentEntry { + pub code:Vc, + pub hash:Vc, +} + +impl EcmascriptDevChunkContentEntry { + pub async fn new( + chunk_item:Vc>, + async_module_info:Option>, + ) -> Result { + let code = chunk_item.code(async_module_info).resolve().await?; + Ok(EcmascriptDevChunkContentEntry { code, hash:code.source_code_hash().resolve().await? }) + } +} + +#[turbo_tasks::value(transparent)] +pub struct EcmascriptDevChunkContentEntries( + IndexMap, EcmascriptDevChunkContentEntry>, +); + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkContentEntries { + #[turbo_tasks::function] + pub async fn new( + chunk_content:Vc, + ) -> Result> { + let chunk_content = chunk_content.await?; + + let entries:IndexMap<_, _> = chunk_content + .chunk_items + .iter() + .map(|&(chunk_item, async_module_info)| { + async move { + async move { + Ok(( + chunk_item.id().await?, + EcmascriptDevChunkContentEntry::new(chunk_item, async_module_info) + .await?, + )) + } + .instrument(info_span!( + "chunk item", + name = display(chunk_item.asset_ident().to_string().await?) + )) + .await + } + }) + .try_join() + .await? + .into_iter() + .collect(); + + Ok(Vc::cell(entries)) + } +} + +#[turbo_tasks::function] +async fn item_code( + item:Vc>, + async_module_info:Option>, +) -> Result> { + Ok( + match item + .content_with_async_module_info(async_module_info) + .module_factory() + .resolve() + .await + { + Ok(factory) => factory, + Err(error) => { + let id = item.id().to_string().await; + let id = id.as_ref().map_or_else(|_| "unknown", |id| &**id); + let error = error + .context(format!("An error occurred while generating the chunk item {}", id)); + let error_message = format!("{}", PrettyPrintError(&error)); + let js_error_message = serde_json::to_string(&error_message)?; + CodeGenerationIssue { + severity:IssueSeverity::Error.cell(), + path:item.asset_ident().path(), + title:StyledString::Text("Code generation for chunk item errored".into()) + .cell(), + message:StyledString::Text(error_message.into()).cell(), + } + .cell() + .emit(); + let mut code = CodeBuilder::default(); + code += "(() => {{\n\n"; + writeln!(code, "throw new Error({error});", error = &js_error_message)?; + code += "\n}})"; + code.build().cell() + }, + }, + ) +} diff --git a/crates/turbopack-browser/Source/ecmascript/evaluate/chunk.rs b/crates/turbopack-browser/Source/ecmascript/evaluate/chunk.rs new file mode 100644 index 0000000000000..0130885f546c8 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/evaluate/chunk.rs @@ -0,0 +1,258 @@ +use std::io::Write; + +use anyhow::{Result, bail}; +use indoc::writedoc; +use serde::Serialize; +use turbo_tasks::{RcStr, ReadRef, TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ + ChunkData, + ChunkItemExt, + ChunkableModule, + ChunkingContext, + ChunksData, + EvaluatableAssets, + MinifyType, + ModuleId, + }, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + module::Module, + output::{OutputAsset, OutputAssets}, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAsset}, +}; +use turbopack_ecmascript::{ + chunk::{EcmascriptChunkData, EcmascriptChunkPlaceable}, + minify::minify, + utils::StringifyJs, +}; +use turbopack_ecmascript_runtime::RuntimeType; + +use crate::BrowserChunkingContext; + +/// An Ecmascript chunk that: +/// * Contains the Turbopack dev runtime code; and +/// * Evaluates a list of runtime entries. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptDevEvaluateChunk { + chunking_context:Vc, + ident:Vc, + other_chunks:Vc, + evaluatable_assets:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevEvaluateChunk { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new( + chunking_context:Vc, + ident:Vc, + other_chunks:Vc, + evaluatable_assets:Vc, + ) -> Vc { + EcmascriptDevEvaluateChunk { chunking_context, ident, other_chunks, evaluatable_assets } + .cell() + } + + #[turbo_tasks::function] + async fn chunks_data(self: Vc) -> Result> { + let this = self.await?; + Ok(ChunkData::from_assets(this.chunking_context.output_root(), this.other_chunks)) + } + + #[turbo_tasks::function] + async fn code(self: Vc) -> Result> { + let this = self.await?; + let chunking_context = this.chunking_context.await?; + let environment = this.chunking_context.environment(); + + let output_root = this.chunking_context.output_root().await?; + let chunk_path_vc = self.ident().path(); + let chunk_path = chunk_path_vc.await?; + let chunk_public_path = if let Some(path) = output_root.get_path_to(&chunk_path) { + path + } else { + bail!( + "chunk path {} is not in output root {}", + chunk_path.to_string(), + output_root.to_string() + ); + }; + + let other_chunks_data = self.chunks_data().await?; + let other_chunks_data = other_chunks_data.iter().try_join().await?; + let other_chunks_data:Vec<_> = other_chunks_data + .iter() + .map(|chunk_data| EcmascriptChunkData::new(chunk_data)) + .collect(); + + let runtime_module_ids = this + .evaluatable_assets + .await? + .iter() + .map({ + let chunking_context = this.chunking_context; + move |entry| { + async move { + if let Some(placeable) = + Vc::try_resolve_sidecast::>(*entry) + .await? + { + Ok(Some( + placeable.as_chunk_item(Vc::upcast(chunking_context)).id().await?, + )) + } else { + Ok(None) + } + } + } + }) + .try_join() + .await? + .into_iter() + .flatten() + .collect(); + + let params = + EcmascriptDevChunkRuntimeParams { other_chunks:&other_chunks_data, runtime_module_ids }; + + let mut code = CodeBuilder::default(); + + // We still use the `TURBOPACK` global variable to store the chunk here, + // as there may be another runtime already loaded in the page. + // This is the case in integration tests. + writedoc!( + code, + r#" + (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + {}, + {{}}, + {} + ]); + "#, + StringifyJs(&chunk_public_path), + StringifyJs(¶ms), + )?; + + match chunking_context.runtime_type() { + RuntimeType::Development => { + let runtime_code = turbopack_ecmascript_runtime::get_browser_runtime_code( + environment, + chunking_context.chunk_base_path(), + Vc::cell(output_root.to_string().into()), + ); + code.push_code(&*runtime_code.await?); + }, + RuntimeType::Production => { + let runtime_code = turbopack_ecmascript_runtime::get_browser_runtime_code( + environment, + chunking_context.chunk_base_path(), + Vc::cell(output_root.to_string().into()), + ); + code.push_code(&*runtime_code.await?); + }, + #[cfg(feature = "test")] + RuntimeType::Dummy => { + let runtime_code = turbopack_ecmascript_runtime::get_dummy_runtime_code(); + code.push_code(&runtime_code); + }, + } + + if code.has_source_map() { + let filename = chunk_path.file_name(); + write!(code, "\n\n//# sourceMappingURL={}.map", urlencoding::encode(filename))?; + } + + let code = code.build().cell(); + if matches!(this.chunking_context.await?.minify_type(), MinifyType::Minify) { + return Ok(minify(chunk_path_vc, code)); + } + + Ok(code) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptDevEvaluateChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Dev Evaluate Chunk".into())) + } +} + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("ecmascript dev evaluate chunk".into()) } + +#[turbo_tasks::value_impl] +impl OutputAsset for EcmascriptDevEvaluateChunk { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let mut ident = self.ident.await?.clone_value(); + + ident.add_modifier(modifier()); + + let evaluatable_assets = self.evaluatable_assets.await?; + ident + .modifiers + .extend(evaluatable_assets.iter().map(|entry| entry.ident().to_string())); + + for chunk in &*self.other_chunks.await? { + ident.add_modifier(chunk.ident().to_string()); + } + + let ident = AssetIdent::new(Value::new(ident)); + Ok(AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".into()))) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let mut references = Vec::new(); + + let include_source_map = + *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await?; + + if include_source_map { + references.push(Vc::upcast(SourceMapAsset::new(Vc::upcast(self)))); + } + + for chunk_data in &*self.chunks_data().await? { + references.extend(chunk_data.references().await?.iter().copied()); + } + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptDevEvaluateChunk { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptDevEvaluateChunk { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +struct EcmascriptDevChunkRuntimeParams<'a, T> { + /// Other chunks in the chunk group this chunk belongs to, if any. Does not + /// include the chunk itself. + /// + /// These chunks must be loaed before the runtime modules can be + /// instantiated. + other_chunks:&'a [T], + /// List of module IDs that this chunk should instantiate when executed. + runtime_module_ids:Vec>, +} diff --git a/crates/turbopack-browser/Source/ecmascript/evaluate/mod.rs b/crates/turbopack-browser/Source/ecmascript/evaluate/mod.rs new file mode 100644 index 0000000000000..90699270917e0 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/evaluate/mod.rs @@ -0,0 +1 @@ +pub(crate) mod chunk; diff --git a/crates/turbopack-browser/Source/ecmascript/list/asset.rs b/crates/turbopack-browser/Source/ecmascript/list/asset.rs new file mode 100644 index 0000000000000..36e8b5844d445 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/list/asset.rs @@ -0,0 +1,131 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkingContext, EvaluatableAssets}, + ident::AssetIdent, + module::Module, + output::{OutputAsset, OutputAssets}, + version::VersionedContent, +}; + +use super::content::EcmascriptDevChunkListContent; +use crate::BrowserChunkingContext; + +/// An asset that represents a list of chunks that exist together in a chunk +/// group, and should be *updated* together. +/// +/// The chunk list's content registers itself as a Turbopack chunk and a chunk +/// list. +/// +/// Then, on updates, it merges updates from its chunks into a single update +/// when possible. This is useful for keeping track of changes that affect more +/// than one chunk, or affect the chunk group, e.g.: +/// * moving a module from one chunk to another; +/// * changing a chunk's path. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptDevChunkList { + pub(super) chunking_context:Vc, + pub(super) ident:Vc, + pub(super) evaluatable_assets:Vc, + pub(super) chunks:Vc, + pub(super) source:EcmascriptDevChunkListSource, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkList { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new( + chunking_context:Vc, + ident:Vc, + evaluatable_assets:Vc, + chunks:Vc, + source:Value, + ) -> Vc { + EcmascriptDevChunkList { + chunking_context, + ident, + evaluatable_assets, + chunks, + source:source.into_value(), + } + .cell() + } + + #[turbo_tasks::function] + fn own_content(self: Vc) -> Vc { + EcmascriptDevChunkListContent::new(self) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptDevChunkList { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Dev Chunk List".into())) + } +} + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("ecmascript dev chunk list".into()) } + +#[turbo_tasks::function] +fn dynamic_modifier() -> Vc { Vc::cell("dynamic".into()) } + +#[turbo_tasks::function] +fn chunk_list_chunk_reference_description() -> Vc { Vc::cell("chunk list chunk".into()) } + +#[turbo_tasks::function] +fn chunk_key() -> Vc { Vc::cell("chunk".into()) } + +#[turbo_tasks::value_impl] +impl OutputAsset for EcmascriptDevChunkList { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let mut ident = self.ident.await?.clone_value(); + for &evaluatable_asset in self.evaluatable_assets.await?.iter() { + ident.add_asset(Vc::::default(), evaluatable_asset.ident()); + } + + ident.add_modifier(modifier()); + + match self.source { + EcmascriptDevChunkListSource::Entry => {}, + EcmascriptDevChunkListSource::Dynamic => { + ident.add_modifier(dynamic_modifier()); + }, + } + + // We must not include the actual chunks idents as part of the chunk list's + // ident, because it must remain stable whenever a chunk is added or + // removed from the list. + + let ident = AssetIdent::new(Value::new(ident)); + Ok(AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".into()))) + } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { Ok(self.chunks) } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptDevChunkList { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { self.own_content().content() } + + #[turbo_tasks::function] + fn versioned_content(self: Vc) -> Vc> { + Vc::upcast(self.own_content()) + } +} + +#[derive(Debug, Clone, Copy, Ord, PartialOrd, Hash)] +#[turbo_tasks::value(serialization = "auto_for_input")] +#[serde(rename_all = "camelCase")] +pub enum EcmascriptDevChunkListSource { + /// The chunk list is from a runtime entry. + Entry, + /// The chunk list is from a dynamic import. + Dynamic, +} diff --git a/crates/turbopack-browser/Source/ecmascript/list/content.rs b/crates/turbopack-browser/Source/ecmascript/list/content.rs new file mode 100644 index 0000000000000..f48018891fdfe --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/list/content.rs @@ -0,0 +1,168 @@ +use std::io::Write; + +use anyhow::{Context, Result}; +use indexmap::IndexMap; +use indoc::writedoc; +use serde::Serialize; +use turbo_tasks::{IntoTraitRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::ChunkingContext, + code_builder::{Code, CodeBuilder}, + output::OutputAsset, + version::{ + MergeableVersionedContent, + Update, + Version, + VersionedContent, + VersionedContentMerger, + }, +}; +use turbopack_ecmascript::utils::StringifyJs; + +use super::{ + asset::{EcmascriptDevChunkList, EcmascriptDevChunkListSource}, + update::update_chunk_list, + version::EcmascriptDevChunkListVersion, +}; + +/// Contents of an [`EcmascriptDevChunkList`]. +#[turbo_tasks::value] +pub(super) struct EcmascriptDevChunkListContent { + chunk_list_path:String, + pub(super) chunks_contents:IndexMap>>, + source:EcmascriptDevChunkListSource, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkListContent { + /// Creates a new [`EcmascriptDevChunkListContent`]. + #[turbo_tasks::function] + pub async fn new(chunk_list:Vc) -> Result> { + let chunk_list_ref = chunk_list.await?; + let output_root = chunk_list_ref.chunking_context.output_root().await?; + Ok(EcmascriptDevChunkListContent { + chunk_list_path:output_root + .get_path_to(&*chunk_list.ident().path().await?) + .context("chunk list path not in output root")? + .to_string(), + chunks_contents:chunk_list_ref + .chunks + .await? + .iter() + .map(|chunk| { + let output_root = output_root.clone(); + async move { + Ok(( + output_root + .get_path_to(&*chunk.ident().path().await?) + .map(|path| path.to_string()), + chunk.versioned_content(), + )) + } + }) + .try_join() + .await? + .into_iter() + .filter_map(|(path, content)| path.map(|path| (path, content))) + .collect(), + source:chunk_list_ref.source, + } + .cell()) + } + + /// Computes the version of this content. + #[turbo_tasks::function] + pub async fn version(self: Vc) -> Result> { + let this = self.await?; + + let mut by_merger = IndexMap::<_, Vec<_>>::new(); + let mut by_path = IndexMap::<_, _>::new(); + + for (chunk_path, chunk_content) in &this.chunks_contents { + if let Some(mergeable) = + Vc::try_resolve_sidecast::>(*chunk_content) + .await? + { + let merger = mergeable.get_merger().resolve().await?; + by_merger.entry(merger).or_default().push(*chunk_content); + } else { + by_path.insert(chunk_path.clone(), chunk_content.version().into_trait_ref().await?); + } + } + + let by_merger = by_merger + .into_iter() + .map(|(merger, contents)| { + async move { + Ok((merger, merger.merge(Vc::cell(contents)).version().into_trait_ref().await?)) + } + }) + .try_join() + .await? + .into_iter() + .collect(); + + Ok(EcmascriptDevChunkListVersion { by_path, by_merger }.cell()) + } + + #[turbo_tasks::function] + pub(super) async fn code(self: Vc) -> Result> { + let this = self.await?; + + let params = EcmascriptDevChunkListParams { + path:&this.chunk_list_path, + chunks:this.chunks_contents.keys().map(|s| s.as_str()).collect(), + source:this.source, + }; + + let mut code = CodeBuilder::default(); + + // When loaded, JS chunks must register themselves with the `TURBOPACK` global + // variable. Similarly, we register the chunk list with the + // `TURBOPACK_CHUNK_LISTS` global variable. + writedoc!( + code, + r#" + (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + {}, + {{}}, + ]); + (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({:#}); + "#, + StringifyJs(&this.chunk_list_path), + StringifyJs(¶ms), + )?; + + Ok(Code::cell(code.build())) + } +} + +#[turbo_tasks::value_impl] +impl VersionedContent for EcmascriptDevChunkListContent { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } + + #[turbo_tasks::function] + fn version(self: Vc) -> Vc> { Vc::upcast(self.version()) } + + #[turbo_tasks::function] + fn update(self: Vc, from_version:Vc>) -> Vc { + update_chunk_list(self, from_version) + } +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +struct EcmascriptDevChunkListParams<'a> { + /// Path to the chunk list to register. + path:&'a str, + /// All chunks that belong to the chunk list. + chunks:Vec<&'a str>, + /// Where this chunk list is from. + source:EcmascriptDevChunkListSource, +} diff --git a/crates/turbopack-browser/Source/ecmascript/list/mod.rs b/crates/turbopack-browser/Source/ecmascript/list/mod.rs new file mode 100644 index 0000000000000..cb3fddcd2276a --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/list/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod asset; +pub(crate) mod content; +pub(crate) mod update; +pub(crate) mod version; diff --git a/crates/turbopack-browser/Source/ecmascript/list/update.rs b/crates/turbopack-browser/Source/ecmascript/list/update.rs new file mode 100644 index 0000000000000..be242f20429b7 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/list/update.rs @@ -0,0 +1,173 @@ +use std::sync::Arc; + +use anyhow::Result; +use indexmap::IndexMap; +use serde::Serialize; +use turbo_tasks::{IntoTraitRef, TraitRef, Vc}; +use turbopack_core::version::{ + MergeableVersionedContent, + PartialUpdate, + TotalUpdate, + Update, + Version, + VersionedContent, + VersionedContentMerger, +}; + +use super::{content::EcmascriptDevChunkListContent, version::EcmascriptDevChunkListVersion}; + +/// Update of a chunk list from one version to another. +#[derive(Serialize)] +#[serde(tag = "type")] +#[serde(rename_all = "camelCase")] +struct ChunkListUpdate<'a> { + /// A map from chunk path to a corresponding update of that chunk. + #[serde(skip_serializing_if = "IndexMap::is_empty")] + chunks:IndexMap<&'a str, ChunkUpdate>, + /// List of merged updates since the last version. + #[serde(skip_serializing_if = "Vec::is_empty")] + merged:Vec>, +} + +/// Update of a chunk from one version to another. +#[derive(Serialize)] +#[serde(tag = "type")] +#[serde(rename_all = "camelCase")] +enum ChunkUpdate { + /// The chunk was updated and must be reloaded. + Total, + /// The chunk was updated and can be merged with the previous version. + Partial { instruction:Arc }, + /// The chunk was added. + Added, + /// The chunk was deleted. + Deleted, +} + +impl<'a> ChunkListUpdate<'a> { + /// Returns `true` if this update is empty. + fn is_empty(&self) -> bool { + let ChunkListUpdate { chunks, merged } = self; + chunks.is_empty() && merged.is_empty() + } +} + +/// Computes the update of a chunk list from one version to another. +#[turbo_tasks::function] +pub(super) async fn update_chunk_list( + content:Vc, + from_version:Vc>, +) -> Result> { + let to_version = content.version(); + let from_version = if let Some(from) = + Vc::try_resolve_downcast_type::(from_version).await? + { + from + } else { + // It's likely `from_version` is `NotFoundVersion`. + return Ok(Update::Total(TotalUpdate { + to:Vc::upcast::>(to_version).into_trait_ref().await?, + }) + .cell()); + }; + + let to = to_version.await?; + let from = from_version.await?; + + // When to and from point to the same value we can skip comparing them. + // This will happen since `TraitRef>>::cell` will not clone + // the value, but only make the cell point to the same immutable value + // (Arc). + if from.ptr_eq(&to) { + return Ok(Update::None.cell()); + } + + let content = content.await?; + + // There are two kind of updates nested within a chunk list update: + // * merged updates; and + // * single chunk updates. + // In order to compute merged updates, we first need to group mergeable chunks + // by common mergers. Then, we compute the update of each group separately. + // Single chunk updates are computed separately and only require a stable chunk + // path to identify the chunk across versions. + let mut by_merger = IndexMap::<_, Vec<_>>::new(); + let mut by_path = IndexMap::<_, _>::new(); + + for (chunk_path, chunk_content) in &content.chunks_contents { + if let Some(mergeable) = + Vc::try_resolve_sidecast::>(*chunk_content).await? + { + let merger = mergeable.get_merger().resolve().await?; + by_merger.entry(merger).or_default().push(*chunk_content); + } else { + by_path.insert(chunk_path, chunk_content); + } + } + + let mut chunks = IndexMap::<_, _>::new(); + + for (chunk_path, from_chunk_version) in &from.by_path { + if let Some(chunk_content) = by_path.remove(chunk_path) { + let chunk_update = + chunk_content.update(TraitRef::cell(from_chunk_version.clone())).await?; + + match &*chunk_update { + Update::Total(_) => { + chunks.insert(chunk_path.as_ref(), ChunkUpdate::Total); + }, + Update::Partial(partial) => { + chunks.insert( + chunk_path.as_ref(), + ChunkUpdate::Partial { instruction:partial.instruction.clone() }, + ); + }, + Update::None => {}, + } + } else { + chunks.insert(chunk_path.as_ref(), ChunkUpdate::Deleted); + } + } + + for chunk_path in by_path.keys() { + chunks.insert(chunk_path.as_ref(), ChunkUpdate::Added); + } + + let mut merged = vec![]; + + for (merger, chunks_contents) in by_merger { + if let Some(from_version) = from.by_merger.get(&merger) { + let content = merger.merge(Vc::cell(chunks_contents)); + + let chunk_update = content.update(TraitRef::cell(from_version.clone())).await?; + + match &*chunk_update { + // Getting a total or not found update from a merger is unexpected. If it + // happens, we have no better option than to short-circuit + // the update. + Update::Total(_) => { + return Ok(Update::Total(TotalUpdate { + to:Vc::upcast::>(to_version).into_trait_ref().await?, + }) + .cell()); + }, + Update::Partial(partial) => { + merged.push(partial.instruction.clone()); + }, + Update::None => {}, + } + } + } + let update = ChunkListUpdate { chunks, merged }; + + let update = if update.is_empty() { + Update::None + } else { + Update::Partial(PartialUpdate { + to:Vc::upcast::>(to_version).into_trait_ref().await?, + instruction:Arc::new(serde_json::to_value(&update)?), + }) + }; + + Ok(update.into()) +} diff --git a/crates/turbopack-browser/Source/ecmascript/list/version.rs b/crates/turbopack-browser/Source/ecmascript/list/version.rs new file mode 100644 index 0000000000000..2f15109e27b76 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/list/version.rs @@ -0,0 +1,67 @@ +use anyhow::Result; +use indexmap::IndexMap; +use turbo_tasks::{RcStr, TraitRef, TryJoinIterExt, Vc}; +use turbo_tasks_hash::{Xxh3Hash64Hasher, encode_hex}; +use turbopack_core::version::{Version, VersionedContentMerger}; + +type VersionTraitRef = TraitRef>; + +/// The version of a [`EcmascriptDevChunkListContent`]. +/// +/// [`EcmascriptDevChunkListContent`]: super::content::EcmascriptDevChunkListContent +#[turbo_tasks::value(shared)] +pub(super) struct EcmascriptDevChunkListVersion { + /// A map from chunk path to its version. + #[turbo_tasks(trace_ignore)] + pub by_path:IndexMap, + /// A map from chunk merger to the version of the merged contents of chunks. + #[turbo_tasks(trace_ignore)] + pub by_merger:IndexMap>, VersionTraitRef>, +} + +#[turbo_tasks::value_impl] +impl Version for EcmascriptDevChunkListVersion { + #[turbo_tasks::function] + async fn id(&self) -> Result> { + let by_path = { + let mut by_path = self + .by_path + .iter() + .map(|(path, version)| { + async move { + let id = TraitRef::cell(version.clone()).id().await?.clone_value(); + Ok((path, id)) + } + }) + .try_join() + .await?; + by_path.sort(); + by_path + }; + let by_merger = { + let mut by_merger = self + .by_merger + .iter() + .map(|(_merger, version)| { + async move { Ok(TraitRef::cell(version.clone()).id().await?.clone_value()) } + }) + .try_join() + .await?; + by_merger.sort(); + by_merger + }; + let mut hasher = Xxh3Hash64Hasher::new(); + hasher.write_value(by_path.len()); + for (path, id) in by_path { + hasher.write_value(path); + hasher.write_value(id); + } + hasher.write_value(by_merger.len()); + for id in by_merger { + hasher.write_value(id); + } + let hash = hasher.finish(); + let hex_hash = encode_hex(hash); + Ok(Vc::cell(hex_hash.into())) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/merged/content.rs b/crates/turbopack-browser/Source/ecmascript/merged/content.rs new file mode 100644 index 0000000000000..e408c6bf0d955 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/merged/content.rs @@ -0,0 +1,55 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbopack_core::{ + asset::AssetContent, + version::{Update, Version, VersionedContent}, +}; + +use super::{ + super::content::EcmascriptDevChunkContent, + update::update_ecmascript_merged_chunk, + version::EcmascriptDevMergedChunkVersion, +}; + +/// Composite [`EcmascriptChunkContent`] that is the result of merging multiple +/// EcmaScript chunk's contents together through the +/// [`EcmascriptChunkContentMerger`]. +/// +/// [`EcmascriptChunkContentMerger`]: super::merger::EcmascriptChunkContentMerger +#[turbo_tasks::value(serialization = "none", shared)] +pub(super) struct EcmascriptDevMergedChunkContent { + pub contents:Vec>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevMergedChunkContent { + #[turbo_tasks::function] + pub async fn version(self: Vc) -> Result> { + Ok(EcmascriptDevMergedChunkVersion { + versions:self + .await? + .contents + .iter() + .map(|content| async move { content.own_version().await }) + .try_join() + .await?, + } + .cell()) + } +} + +#[turbo_tasks::value_impl] +impl VersionedContent for EcmascriptDevMergedChunkContent { + #[turbo_tasks::function] + fn content(self: Vc) -> Result> { + bail!("EcmascriptDevMergedChunkContent does not have content") + } + + #[turbo_tasks::function] + fn version(self: Vc) -> Vc> { Vc::upcast(self.version()) } + + #[turbo_tasks::function] + async fn update(self: Vc, from_version:Vc>) -> Result> { + Ok(update_ecmascript_merged_chunk(self, from_version).await?.cell()) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/merged/merger.rs b/crates/turbopack-browser/Source/ecmascript/merged/merger.rs new file mode 100644 index 0000000000000..f7eb24f5d7acd --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/merged/merger.rs @@ -0,0 +1,43 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbopack_core::version::{VersionedContent, VersionedContentMerger, VersionedContents}; + +use super::{super::content::EcmascriptDevChunkContent, content::EcmascriptDevMergedChunkContent}; + +/// Merges multiple [`EcmascriptChunkContent`] into a single +/// [`EcmascriptDevMergedChunkContent`]. This is useful for generating a single +/// update for multiple ES chunks updating all at the same time. +#[turbo_tasks::value] +pub(crate) struct EcmascriptDevChunkContentMerger; + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkContentMerger { + /// Creates a new [`EcmascriptDevChunkContentMerger`]. + #[turbo_tasks::function] + pub fn new() -> Vc { Self::cell(EcmascriptDevChunkContentMerger) } +} + +#[turbo_tasks::value_impl] +impl VersionedContentMerger for EcmascriptDevChunkContentMerger { + #[turbo_tasks::function] + async fn merge(&self, contents:Vc) -> Result>> { + let contents = contents + .await? + .iter() + .map(|content| { + async move { + if let Some(content) = + Vc::try_resolve_downcast_type::(*content).await? + { + Ok(content) + } else { + bail!("expected Vc") + } + } + }) + .try_join() + .await?; + + Ok(Vc::upcast(EcmascriptDevMergedChunkContent { contents }.cell())) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/merged/mod.rs b/crates/turbopack-browser/Source/ecmascript/merged/mod.rs new file mode 100644 index 0000000000000..38431505fc60f --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/merged/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod content; +pub(crate) mod merger; +pub(crate) mod update; +pub(crate) mod version; diff --git a/crates/turbopack-browser/Source/ecmascript/merged/update.rs b/crates/turbopack-browser/Source/ecmascript/merged/update.rs new file mode 100644 index 0000000000000..dc9eef0d23139 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/merged/update.rs @@ -0,0 +1,273 @@ +use std::sync::Arc; + +use anyhow::Result; +use indexmap::{IndexMap, IndexSet}; +use serde::Serialize; +use turbo_tasks::{IntoTraitRef, ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::rope::Rope; +use turbopack_core::{ + chunk::{ChunkingContext, ModuleId}, + code_builder::Code, + output::OutputAsset, + source_map::GenerateSourceMap, + version::{PartialUpdate, TotalUpdate, Update, Version}, +}; + +use super::{ + super::{ + update::{EcmascriptChunkUpdate, update_ecmascript_chunk}, + version::EcmascriptDevChunkVersion, + }, + content::EcmascriptDevMergedChunkContent, + version::EcmascriptDevMergedChunkVersion, +}; + +#[derive(Serialize, Default)] +#[serde(tag = "type", rename_all = "camelCase")] +struct EcmascriptMergedUpdate<'a> { + /// A map from module id to latest module entry. + #[serde(skip_serializing_if = "IndexMap::is_empty")] + entries:IndexMap, EcmascriptModuleEntry>, + /// A map from chunk path to the chunk update. + #[serde(skip_serializing_if = "IndexMap::is_empty")] + chunks:IndexMap<&'a str, EcmascriptMergedChunkUpdate>, +} + +impl EcmascriptMergedUpdate<'_> { + fn is_empty(&self) -> bool { self.entries.is_empty() && self.chunks.is_empty() } +} + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +enum EcmascriptMergedChunkUpdate { + Added(EcmascriptMergedChunkAdded), + Deleted(EcmascriptMergedChunkDeleted), + Partial(EcmascriptMergedChunkPartial), +} + +#[derive(Serialize, Default)] +#[serde(rename_all = "camelCase")] +struct EcmascriptMergedChunkAdded { + #[serde(skip_serializing_if = "IndexSet::is_empty")] + modules:IndexSet>, +} + +#[derive(Serialize, Default)] +#[serde(rename_all = "camelCase")] +struct EcmascriptMergedChunkDeleted { + // Technically, this is redundant, since the client will already know all + // modules in the chunk from the previous version. However, it's useful for + // merging updates without access to an initial state. + #[serde(skip_serializing_if = "IndexSet::is_empty")] + modules:IndexSet>, +} + +#[derive(Serialize, Default)] +#[serde(rename_all = "camelCase")] +struct EcmascriptMergedChunkPartial { + #[serde(skip_serializing_if = "IndexSet::is_empty")] + added:IndexSet>, + #[serde(skip_serializing_if = "IndexSet::is_empty")] + deleted:IndexSet>, +} + +#[derive(Serialize)] +struct EcmascriptModuleEntry { + code:Rope, + url:String, + map:Option, +} + +impl EcmascriptModuleEntry { + async fn from_code(id:&ModuleId, code:Vc, chunk_path:&str) -> Result { + let map = match &*code.generate_source_map().await? { + Some(map) => { + let map = map.await?.to_source_map().await?; + let mut map_str = vec![]; + (*map).to_writer(&mut map_str)?; + Some(String::from_utf8(map_str)?) + }, + None => None, + }; + + Ok(Self::new(id, code.await?, map, chunk_path)) + } + + fn new(id:&ModuleId, code:ReadRef, map:Option, chunk_path:&str) -> Self { + /// serde_qs can't serialize a lone enum when it's [serde::untagged]. + #[derive(Serialize)] + struct Id<'a> { + id:&'a ModuleId, + } + let id = serde_qs::to_string(&Id { id }).unwrap(); + + EcmascriptModuleEntry { + // Cloning a rope is cheap. + code:code.source_code().clone(), + url:format!("{}?{}", chunk_path, &id), + map, + } + } +} + +/// Helper structure to get a module's hash from multiple different chunk +/// versions, without having to actually merge the versions into a single +/// hashmap, which would be expensive. +struct MergedModuleMap { + versions:Vec>, +} + +impl MergedModuleMap { + /// Creates a new `MergedModuleMap` from the given versions. + fn new(versions:Vec>) -> Self { Self { versions } } + + /// Returns the hash of the module with the given id, or `None` if the + /// module is not present in any of the versions. + fn get(&self, id:&ReadRef) -> Option { + for version in &self.versions { + if let Some(hash) = version.entries_hashes.get(id) { + return Some(*hash); + } + } + None + } +} + +pub(super) async fn update_ecmascript_merged_chunk( + content:Vc, + from_version:Vc>, +) -> Result { + let to_merged_version = content.version(); + let from_merged_version = if let Some(from) = + Vc::try_resolve_downcast_type::(from_version).await? + { + from + } else { + // It's likely `from_version` is `NotFoundVersion`. + return Ok(Update::Total(TotalUpdate { + to:Vc::upcast::>(to_merged_version).into_trait_ref().await?, + })); + }; + + let to = to_merged_version.await?; + let from = from_merged_version.await?; + + // When to and from point to the same value we can skip comparing them. + // This will happen since `TraitRef>>::cell` will not clone + // the value, but only make the cell point to the same immutable value + // (Arc). + if from.ptr_eq(&to) { + return Ok(Update::None); + } + + let mut from_versions_by_chunk_path:IndexMap<_, _> = + from.versions.iter().map(|version| (&*version.chunk_path, version)).collect(); + + let merged_module_map = MergedModuleMap::new(from.versions.to_vec()); + + let content = content.await?; + let to_contents = content + .contents + .iter() + .map(|content| { + async move { + let content_ref = content.await?; + let output_root = content_ref.chunking_context.output_root().await?; + let path = content_ref.chunk.ident().path().await?; + Ok((*content, content_ref, output_root, path)) + } + }) + .try_join() + .await?; + + let mut merged_update = EcmascriptMergedUpdate::default(); + + for (content, content_ref, output_root, path) in &to_contents { + let Some(chunk_path) = output_root.get_path_to(path) else { + continue; + }; + + let chunk_update = if let Some(from_version) = + from_versions_by_chunk_path.remove(chunk_path) + { + // The chunk was present in the previous version, so we must update it. + let update = update_ecmascript_chunk(*content, from_version).await?; + + match update { + EcmascriptChunkUpdate::None => { + // Nothing changed, so we can skip this chunk. + continue; + }, + EcmascriptChunkUpdate::Partial(chunk_partial) => { + // The chunk was updated. + let mut partial = EcmascriptMergedChunkPartial::default(); + + for (module_id, (module_hash, module_code)) in chunk_partial.added { + partial.added.insert(module_id.clone()); + + if merged_module_map.get(&module_id) != Some(module_hash) { + let entry = EcmascriptModuleEntry::from_code( + &module_id, + module_code, + chunk_path, + ) + .await?; + merged_update.entries.insert(module_id, entry); + } + } + + partial.deleted.extend(chunk_partial.deleted.into_keys()); + + for (module_id, module_code) in chunk_partial.modified { + let entry = + EcmascriptModuleEntry::from_code(&module_id, module_code, chunk_path) + .await?; + merged_update.entries.insert(module_id, entry); + } + + EcmascriptMergedChunkUpdate::Partial(partial) + }, + } + } else { + // The chunk was added in this version. + let mut added = EcmascriptMergedChunkAdded::default(); + + for (id, entry) in &content_ref.entries.await? { + let hash = *entry.hash.await?; + added.modules.insert(id.clone()); + + if merged_module_map.get(id) != Some(hash) { + let entry = + EcmascriptModuleEntry::from_code(id, entry.code, chunk_path).await?; + merged_update.entries.insert(id.clone(), entry); + } + } + + EcmascriptMergedChunkUpdate::Added(added) + }; + + merged_update.chunks.insert(chunk_path, chunk_update); + } + + // Deleted chunks. + for (chunk_path, chunk_version) in from_versions_by_chunk_path { + let hashes = &chunk_version.entries_hashes; + merged_update.chunks.insert( + chunk_path, + EcmascriptMergedChunkUpdate::Deleted(EcmascriptMergedChunkDeleted { + modules:hashes.keys().cloned().collect(), + }), + ); + } + + let update = if merged_update.is_empty() { + Update::None + } else { + Update::Partial(PartialUpdate { + to:Vc::upcast::>(to_merged_version).into_trait_ref().await?, + instruction:Arc::new(serde_json::to_value(&merged_update)?), + }) + }; + + Ok(update) +} diff --git a/crates/turbopack-browser/Source/ecmascript/merged/version.rs b/crates/turbopack-browser/Source/ecmascript/merged/version.rs new file mode 100644 index 0000000000000..9448a2749e063 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/merged/version.rs @@ -0,0 +1,39 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_hash::{Xxh3Hash64Hasher, encode_hex}; +use turbopack_core::version::Version; + +use super::super::version::EcmascriptDevChunkVersion; + +/// The version of a [`super::content::EcmascriptMergedChunkContent`]. This is +/// essentially a composite [`EcmascriptChunkVersion`]. +#[turbo_tasks::value(serialization = "none", shared)] +pub(super) struct EcmascriptDevMergedChunkVersion { + #[turbo_tasks(trace_ignore)] + pub(super) versions:Vec>, +} + +#[turbo_tasks::value_impl] +impl Version for EcmascriptDevMergedChunkVersion { + #[turbo_tasks::function] + async fn id(&self) -> Result> { + let mut hasher = Xxh3Hash64Hasher::new(); + hasher.write_value(self.versions.len()); + let sorted_ids = { + let mut sorted_ids = self + .versions + .iter() + .map(|version| async move { ReadRef::cell(version.clone()).id().await }) + .try_join() + .await?; + sorted_ids.sort(); + sorted_ids + }; + for id in sorted_ids { + hasher.write_value(id); + } + let hash = hasher.finish(); + let hex_hash = encode_hex(hash); + Ok(Vc::cell(hex_hash.into())) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/mod.rs b/crates/turbopack-browser/Source/ecmascript/mod.rs new file mode 100644 index 0000000000000..a819a6d13264e --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/mod.rs @@ -0,0 +1,10 @@ +pub(crate) mod chunk; +pub(crate) mod content; +pub(crate) mod content_entry; +pub(crate) mod evaluate; +pub(crate) mod list; +pub(crate) mod merged; +pub(crate) mod update; +pub(crate) mod version; + +pub use content::EcmascriptDevChunkContent; diff --git a/crates/turbopack-browser/Source/ecmascript/runtime.rs b/crates/turbopack-browser/Source/ecmascript/runtime.rs new file mode 100644 index 0000000000000..7f2e8decc9052 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/runtime.rs @@ -0,0 +1,196 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{Value, ValueToString, Vc}; +use turbopack_core::{ + asset::Asset, + chunk::{ChunkGroup, ChunkListReference, ChunkingContext}, + ident::AssetIdent, +}; +use turbopack_ecmascript::chunk::{ + ChunkingContext, + EcmascriptChunk, + EcmascriptChunkPlaceables, + EcmascriptChunkRuntime, + EcmascriptChunkRuntimeContent, +}; + +use crate::ecmascript::content::EcmascriptDevChunkContent; + +/// Development runtime for Ecmascript chunks. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptDevChunkRuntime { + /// The chunking context that created this runtime. + chunking_context:Vc>, + /// All chunks of this chunk group need to be ready for execution to start. + /// When None, it will use a chunk group created from the current chunk. + chunk_group:Option>, + /// If any evaluated entries are set, the main runtime code will be included + /// in the chunk and the provided entries will be evaluated as soon as the + /// chunk executes. + evaluated_entries:Option>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkRuntime { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new( + chunking_context:Vc>, + evaluated_entries:Option>, + ) -> Vc { + EcmascriptDevChunkRuntime { chunking_context, chunk_group:None, evaluated_entries }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptDevChunkRuntime { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Dev Runtime".to_string())) + } +} + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("ecmascript dev chunk".to_string()) } + +#[turbo_tasks::value_impl] +impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { + #[turbo_tasks::function] + async fn decorate_asset_ident( + &self, + origin_chunk:Vc, + ident:Vc, + ) -> Result> { + let Self { chunking_context: _, chunk_group, evaluated_entries } = self; + + let mut ident = ident.await?.clone_value(); + + // Add a constant modifier to qualify this runtime. + ident.add_modifier(modifier()); + + // Only add other modifiers when the chunk is evaluated. Otherwise, it will + // not receive any params and as such won't differ from another chunk in a + // different chunk group. + if let Some(evaluated_entries) = evaluated_entries { + ident + .modifiers + .extend(evaluated_entries.await?.iter().map(|entry| entry.ident().to_string())); + + // When the chunk group has changed, e.g. due to optimization, we want to + // include the information too. Since the optimization is + // deterministic, it's enough to include the entry chunk which is the only + // factor that influences the chunk group chunks. + // We want to avoid a cycle when this chunk is the entry chunk. + if let Some(chunk_group) = chunk_group { + let entry = chunk_group.entry().resolve().await?; + if entry != origin_chunk.into() { + ident.add_modifier(entry.ident().to_string()); + } + } + } + + Ok(AssetIdent::new(Value::new(ident))) + } + + #[turbo_tasks::function] + fn with_chunk_group(&self, chunk_group:Vc) -> Vc { + EcmascriptDevChunkRuntime::cell(EcmascriptDevChunkRuntime { + chunking_context:self.chunking_context, + chunk_group:Some(chunk_group), + evaluated_entries:self.evaluated_entries, + }) + } + + #[turbo_tasks::function] + fn references(&self, origin_chunk:Vc) -> Vc { + let Self { chunk_group, chunking_context, evaluated_entries } = self; + + let mut references = vec![]; + if evaluated_entries.is_some() { + let chunk_group = + chunk_group.unwrap_or_else(|| ChunkGroup::from_chunk(origin_chunk.into())); + references.push(Vc::upcast(ChunkListReference::new( + chunking_context.output_root(), + chunk_group, + ))); + } + Vc::cell(references) + } + + #[turbo_tasks::function] + fn content(&self, origin_chunk:Vc) -> Vc { + Vc::upcast(EcmascriptDevChunkContent::new( + origin_chunk, + self.chunking_context, + self.chunk_group, + self.evaluated_entries, + )) + } + + #[turbo_tasks::function] + async fn merge( + &self, + runtimes:Vec>, + ) -> Result> { + let Self { chunking_context, chunk_group, evaluated_entries } = self; + + let chunking_context = chunking_context.resolve().await?; + let chunk_group = if let Some(chunk_group) = chunk_group { + Some(chunk_group.resolve().await?) + } else { + None + }; + + let mut evaluated_entries = if let Some(evaluated_entries) = evaluated_entries { + Some(evaluated_entries.await?.clone_value()) + } else { + None + }; + + for runtime in runtimes { + let Some(runtime) = + Vc::try_resolve_downcast_type::(runtime).await? + else { + bail!("cannot merge EcmascriptDevChunkRuntime with non-EcmascriptDevChunkRuntime"); + }; + + let Self { + chunking_context: other_chunking_context, + chunk_group: other_chunk_group, + evaluated_entries: other_evaluated_entries, + } = &*runtime.await?; + + let other_chunking_context = other_chunking_context.resolve().await?; + let other_chunk_group = if let Some(other_chunk_group) = other_chunk_group { + Some(other_chunk_group.resolve().await?) + } else { + None + }; + + if chunking_context != other_chunking_context { + bail!("cannot merge EcmascriptDevChunkRuntime with different chunking contexts",); + } + + if chunk_group != other_chunk_group { + bail!("cannot merge EcmascriptDevChunkRuntime with different chunk groups",); + } + + match (&mut evaluated_entries, other_evaluated_entries) { + (Some(evaluated_entries), Some(other_evaluated_entries)) => { + evaluated_entries.extend(other_evaluated_entries.await?.iter().copied()); + }, + (None, Some(other_evaluated_entries)) => { + evaluated_entries = Some(other_evaluated_entries.await?.clone_value()); + }, + _ => {}, + } + } + + Ok(EcmascriptDevChunkRuntime { + chunking_context, + chunk_group, + evaluated_entries:evaluated_entries.map(Vc::cell), + } + .cell() + .into()) + } +} diff --git a/crates/turbopack-browser/Source/ecmascript/update.rs b/crates/turbopack-browser/Source/ecmascript/update.rs new file mode 100644 index 0000000000000..f0b6a20a3c946 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/update.rs @@ -0,0 +1,64 @@ +use anyhow::Result; +use indexmap::IndexMap; +use turbo_tasks::{ReadRef, Vc}; +use turbopack_core::{chunk::ModuleId, code_builder::Code}; + +use super::{content::EcmascriptDevChunkContent, version::EcmascriptDevChunkVersion}; + +pub(super) enum EcmascriptChunkUpdate { + None, + Partial(EcmascriptChunkPartialUpdate), +} + +pub(super) struct EcmascriptChunkPartialUpdate { + pub added:IndexMap, (u64, Vc)>, + pub deleted:IndexMap, u64>, + pub modified:IndexMap, Vc>, +} + +pub(super) async fn update_ecmascript_chunk( + content:Vc, + from:&ReadRef, +) -> Result { + let to = content.own_version().await?; + + // When to and from point to the same value we can skip comparing them. + // This will happen since `TraitRef>>::cell` will not clone + // the value, but only make the cell point to the same immutable value + // (Arc). + if from.ptr_eq(&to) { + return Ok(EcmascriptChunkUpdate::None); + } + + let content = content.await?; + + let entries = content.entries.await?; + let mut added = IndexMap::default(); + let mut modified = IndexMap::default(); + let mut deleted = IndexMap::default(); + + for (id, from_hash) in &from.entries_hashes { + if let Some(entry) = entries.get(id) { + if *entry.hash.await? != *from_hash { + modified.insert(id.clone(), entry.code); + } + } else { + deleted.insert(id.clone(), *from_hash); + } + } + + // Remaining entries are added + for (id, entry) in entries.iter() { + if !from.entries_hashes.contains_key(id) { + added.insert(id.clone(), (*entry.hash.await?, entry.code)); + } + } + + let update = if added.is_empty() && modified.is_empty() && deleted.is_empty() { + EcmascriptChunkUpdate::None + } else { + EcmascriptChunkUpdate::Partial(EcmascriptChunkPartialUpdate { added, modified, deleted }) + }; + + Ok(update) +} diff --git a/crates/turbopack-browser/Source/ecmascript/version.rs b/crates/turbopack-browser/Source/ecmascript/version.rs new file mode 100644 index 0000000000000..30fa78879f794 --- /dev/null +++ b/crates/turbopack-browser/Source/ecmascript/version.rs @@ -0,0 +1,62 @@ +use anyhow::{Result, bail}; +use indexmap::IndexMap; +use turbo_tasks::{RcStr, ReadRef, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbo_tasks_hash::{Xxh3Hash64Hasher, encode_hex}; +use turbopack_core::{chunk::ModuleId, version::Version}; + +use super::content_entry::EcmascriptDevChunkContentEntries; + +#[turbo_tasks::value(serialization = "none")] +pub(super) struct EcmascriptDevChunkVersion { + pub(super) chunk_path:String, + pub(super) entries_hashes:IndexMap, u64>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkVersion { + #[turbo_tasks::function] + pub async fn new( + output_root:Vc, + chunk_path:Vc, + entries:Vc, + ) -> Result> { + let output_root = output_root.await?; + let chunk_path = chunk_path.await?; + let chunk_path = if let Some(path) = output_root.get_path_to(&chunk_path) { + path + } else { + bail!( + "chunk path {} is not in client root {}", + chunk_path.to_string(), + output_root.to_string() + ); + }; + let entries = entries.await?; + let mut entries_hashes = IndexMap::with_capacity(entries.len()); + for (id, entry) in entries.iter() { + entries_hashes.insert(id.clone(), *entry.hash.await?); + } + Ok(EcmascriptDevChunkVersion { chunk_path:chunk_path.to_string(), entries_hashes }.cell()) + } +} + +#[turbo_tasks::value_impl] +impl Version for EcmascriptDevChunkVersion { + #[turbo_tasks::function] + fn id(&self) -> Vc { + let mut hasher = Xxh3Hash64Hasher::new(); + hasher.write_ref(&self.chunk_path); + let sorted_hashes = { + let mut hashes:Vec<_> = self.entries_hashes.values().copied().collect(); + hashes.sort(); + hashes + }; + for hash in sorted_hashes { + hasher.write_value(hash); + } + let hash = hasher.finish(); + let hex_hash = encode_hex(hash); + Vc::cell(hex_hash.into()) + } +} diff --git a/crates/turbopack-browser/Source/lib.rs b/crates/turbopack-browser/Source/lib.rs new file mode 100644 index 0000000000000..7a72d17938dbd --- /dev/null +++ b/crates/turbopack-browser/Source/lib.rs @@ -0,0 +1,20 @@ +#![feature(lint_reasons)] +#![feature(iter_intersperse)] +#![feature(int_roundings)] +#![feature(arbitrary_self_types)] + +pub(crate) mod chunking_context; +pub mod ecmascript; +pub mod react_refresh; + +pub use chunking_context::{BrowserChunkingContext, BrowserChunkingContextBuilder}; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + turbopack_ecmascript_runtime::register(); + turbopack_resolve::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-browser/Source/react_refresh.rs b/crates/turbopack-browser/Source/react_refresh.rs new file mode 100644 index 0000000000000..cdc8538ba6d1d --- /dev/null +++ b/crates/turbopack-browser/Source/react_refresh.rs @@ -0,0 +1,111 @@ +use anyhow::Result; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + reference_type::{CommonJsReferenceSubType, ReferenceType}, + resolve::parse::Request, +}; +use turbopack_resolve::{ + ecmascript::apply_cjs_specific_options, + resolve_options_context::ResolveOptionsContext, +}; + +#[turbo_tasks::function] +fn react_refresh_request() -> Vc { + Request::parse_string("@next/react-refresh-utils/dist/runtime".into()) +} + +#[turbo_tasks::function] +fn react_refresh_request_in_next() -> Vc { + Request::parse_string("next/dist/compiled/@next/react-refresh-utils/dist/runtime".into()) +} + +#[turbo_tasks::value] +pub enum ResolveReactRefreshResult { + NotFound, + Found(Vc), +} + +impl ResolveReactRefreshResult { + pub fn as_request(&self) -> Option> { + match self { + ResolveReactRefreshResult::NotFound => None, + ResolveReactRefreshResult::Found(r) => Some(*r), + } + } + + pub fn is_found(&self) -> bool { + match self { + ResolveReactRefreshResult::NotFound => false, + ResolveReactRefreshResult::Found(_) => true, + } + } +} + +/// Checks whether we can resolve the React Refresh runtime module from the +/// given path. Emits an issue if we can't. +#[turbo_tasks::function] +pub async fn assert_can_resolve_react_refresh( + path:Vc, + resolve_options_context:Vc, +) -> Result> { + let resolve_options = apply_cjs_specific_options(turbopack_resolve::resolve::resolve_options( + path, + resolve_options_context, + )); + for request in [react_refresh_request_in_next(), react_refresh_request()] { + let result = turbopack_core::resolve::resolve( + path, + Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)), + request, + resolve_options, + ) + .first_source(); + + if result.await?.is_some() { + return Ok(ResolveReactRefreshResult::Found(request).cell()); + } + } + ReactRefreshResolvingIssue { path }.cell().emit(); + Ok(ResolveReactRefreshResult::NotFound.cell()) +} + +/// An issue that occurred while resolving the React Refresh runtime module. +#[turbo_tasks::value(shared)] +pub struct ReactRefreshResolvingIssue { + path:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for ReactRefreshResolvingIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Could not resolve React Refresh runtime".into()).cell() + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Resolve.cell() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.path } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some( + StyledString::Line(vec![ + StyledString::Text( + "React Refresh will be disabled.\nTo enable React Refresh, install the ".into(), + ), + StyledString::Code("react-refresh".into()), + StyledString::Text(" and ".into()), + StyledString::Code("@next/react-refresh-utils".into()), + StyledString::Text(" modules.".into()), + ]) + .cell(), + )) + } +} diff --git a/crates/turbopack-browser/build.rs b/crates/turbopack-browser/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-browser/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-cli-utils/Source/issue.rs b/crates/turbopack-cli-utils/Source/issue.rs new file mode 100644 index 0000000000000..bf1d8b4eceea9 --- /dev/null +++ b/crates/turbopack-cli-utils/Source/issue.rs @@ -0,0 +1,553 @@ +use std::{ + borrow::Cow, + cmp::min, + collections::{HashMap, HashSet, hash_map::Entry}, + fmt::Write as _, + path::{Path, PathBuf}, + str::FromStr, + sync::{Arc, Mutex}, +}; + +use anyhow::{Result, anyhow}; +use crossterm::style::{StyledContent, Stylize}; +use owo_colors::{OwoColorize as _, Style}; +use turbo_tasks::{RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, Vc}; +use turbo_tasks_fs::{FileLinesContent, source_context::get_source_context}; +use turbopack_core::issue::{ + CapturedIssues, + Issue, + IssueReporter, + IssueSeverity, + PlainIssue, + PlainIssueProcessingPathItem, + PlainIssueSource, + StyledString, +}; + +use crate::source_context::format_source_context_lines; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct IssueSeverityCliOption(pub IssueSeverity); + +impl serde::Serialize for IssueSeverityCliOption { + fn serialize(&self, serializer:S) -> Result { + serializer.serialize_str(&self.0.to_string()) + } +} + +impl<'de> serde::Deserialize<'de> for IssueSeverityCliOption { + fn deserialize>(deserializer:D) -> Result { + let s = String::deserialize(deserializer)?; + IssueSeverityCliOption::from_str(&s).map_err(serde::de::Error::custom) + } +} + +impl clap::ValueEnum for IssueSeverityCliOption { + fn value_variants<'a>() -> &'a [Self] { + const VARIANTS:[IssueSeverityCliOption; 8] = [ + IssueSeverityCliOption(IssueSeverity::Bug), + IssueSeverityCliOption(IssueSeverity::Fatal), + IssueSeverityCliOption(IssueSeverity::Error), + IssueSeverityCliOption(IssueSeverity::Warning), + IssueSeverityCliOption(IssueSeverity::Hint), + IssueSeverityCliOption(IssueSeverity::Note), + IssueSeverityCliOption(IssueSeverity::Suggestion), + IssueSeverityCliOption(IssueSeverity::Info), + ]; + &VARIANTS + } + + fn to_possible_value<'a>(&self) -> Option { + Some(clap::builder::PossibleValue::new(self.0.as_str()).help(self.0.as_help_str())) + } +} + +impl FromStr for IssueSeverityCliOption { + type Err = anyhow::Error; + + fn from_str(s:&str) -> Result { + ::from_str(s, true).map_err(|s| anyhow!("{}", s)) + } +} + +fn severity_to_style(severity:IssueSeverity) -> Style { + match severity { + IssueSeverity::Bug => Style::new().bright_red().underline(), + IssueSeverity::Fatal => Style::new().bright_red().underline(), + IssueSeverity::Error => Style::new().bright_red(), + IssueSeverity::Warning => Style::new().bright_yellow(), + IssueSeverity::Hint => Style::new().bold(), + IssueSeverity::Note => Style::new().bold(), + IssueSeverity::Suggestion => Style::new().bright_green().underline(), + IssueSeverity::Info => Style::new().bright_green(), + } +} + +fn format_source_content(source:&PlainIssueSource, formatted_issue:&mut String) { + if let FileLinesContent::Lines(lines) = source.asset.content.lines_ref() { + if let Some((start, end)) = source.range { + let lines = lines.iter().map(|l| l.content.as_str()); + let ctx = get_source_context(lines, start.line, start.column, end.line, end.column); + format_source_context_lines(&ctx, formatted_issue); + } + } +} + +fn format_optional_path( + path:&Option>>, + formatted_issue:&mut String, +) -> Result<()> { + if let Some(path) = path { + let mut last_context = None; + for item in path.iter().rev() { + let PlainIssueProcessingPathItem { file_path: ref context, ref description } = **item; + if let Some(context) = context { + let option_context = Some(context.clone()); + if last_context == option_context { + writeln!(formatted_issue, " at {}", description)?; + } else { + writeln!( + formatted_issue, + " at {} ({})", + context.to_string().bright_blue(), + description + )?; + last_context = option_context; + } + } else { + writeln!(formatted_issue, " at {}", description)?; + last_context = None; + } + } + } + Ok(()) +} + +pub fn format_issue(plain_issue:&PlainIssue, path:Option, options:&LogOptions) -> String { + let &LogOptions { ref current_dir, log_detail, .. } = options; + + let mut issue_text = String::new(); + + let severity = plain_issue.severity; + // TODO CLICKABLE PATHS + let context_path = plain_issue + .file_path + .replace("[project]", ¤t_dir.to_string_lossy()) + .replace("/./", "/") + .replace("\\\\?\\", ""); + let stgae = plain_issue.stage.to_string(); + + let mut styled_issue = style_issue_source(plain_issue, &context_path); + let description = &plain_issue.description; + if let Some(description) = description { + writeln!(styled_issue, "\n{}", render_styled_string_to_ansi(description)).unwrap(); + } + + if log_detail { + styled_issue.push('\n'); + let detail = &plain_issue.detail; + if let Some(detail) = detail { + for line in render_styled_string_to_ansi(detail).split('\n') { + writeln!(styled_issue, "| {line}").unwrap(); + } + } + let documentation_link = &plain_issue.documentation_link; + if !documentation_link.is_empty() { + writeln!(styled_issue, "\ndocumentation: {documentation_link}").unwrap(); + } + if let Some(path) = path { + writeln!(styled_issue, "{}", path).unwrap(); + } + } + + write!( + issue_text, + "{} - [{}] {}", + severity.style(severity_to_style(severity)), + stgae, + plain_issue.file_path + ) + .unwrap(); + + for line in styled_issue.lines() { + writeln!(issue_text, " {line}").unwrap(); + } + + issue_text +} + +pub type GroupedIssues = HashMap>>>; + +const DEFAULT_SHOW_COUNT:usize = 3; + +const ORDERED_GROUPS:&[IssueSeverity] = &[ + IssueSeverity::Bug, + IssueSeverity::Fatal, + IssueSeverity::Error, + IssueSeverity::Warning, + IssueSeverity::Hint, + IssueSeverity::Note, + IssueSeverity::Suggestion, + IssueSeverity::Info, +]; + +#[turbo_tasks::value(shared)] +#[derive(Debug, Clone)] +pub struct LogOptions { + pub current_dir:PathBuf, + pub project_dir:PathBuf, + pub show_all:bool, + pub log_detail:bool, + pub log_level:IssueSeverity, +} + +/// Tracks the state of currently seen issues. +/// +/// An issue is considered seen as long as a single source has pulled the issue. +/// When a source repulls emitted issues due to a recomputation somewhere in its +/// graph, there are a few possibilities: +/// +/// 1. An issue from this pull is brand new to all sources, in which case it +/// will be logged and the issue's count is inremented. +/// 2. An issue from this pull is brand new to this source but another source +/// has already pulled it, in which case it will be logged and the issue's +/// count is incremented. +/// 3. The previous pull from this source had already seen the issue, in which +/// case the issue will be skipped and the issue's count remains constant. +/// 4. An issue seen in a previous pull was not repulled, and the issue's count +/// is decremented. +/// +/// Once an issue's count reaches zero, it's removed. If it is ever seen again, +/// it is considered new and will be relogged. +#[derive(Default)] +struct SeenIssues { + /// Keeps track of all issue pulled from the source. Used so that we can + /// decrement issues that are not pulled in the current synchronization. + source_to_issue_ids:HashMap>, + + /// Counts the number of times a particular issue is seen across all + /// sources. As long as the count is positive, an issue is considered + /// "seen" and will not be relogged. Once the count reaches zero, the + /// issue is removed and the next time its seen it will be considered new. + issues_count:HashMap, +} + +impl SeenIssues { + fn new() -> Self { Default::default() } + + /// Synchronizes state between the issues previously pulled from this + /// source, to the issues now pulled. + fn new_ids(&mut self, source:RawVc, issue_ids:HashSet) -> HashSet { + let old = self.source_to_issue_ids.entry(source).or_default(); + + // difference is the issues that were never counted before. + let difference = issue_ids + .iter() + .filter(|id| { + match self.issues_count.entry(**id) { + Entry::Vacant(e) => { + // If the issue not currently counted, then it's new and should be logged. + e.insert(1); + true + }, + Entry::Occupied(mut e) => { + if old.contains(*id) { + // If old contains the id, then we don't need to change the count, but + // we do need to remove the entry. Doing so allows us to iterate + // the final old state and decrement old issues. + old.remove(*id); + } else { + // If old didn't contain the entry, then this issue was already counted + // from a difference source. + *e.get_mut() += 1; + } + false + }, + } + }) + .cloned() + .collect::>(); + + // Old now contains only the ids that were not present in the new issue_ids. + for id in old.iter() { + match self.issues_count.entry(*id) { + Entry::Vacant(_) => unreachable!("issue must already be tracked to appear in old"), + Entry::Occupied(mut e) => { + let v = e.get_mut(); + if *v == 1 { + // If this was the last counter of the issue, then we need to prune the + // value to free memory. + e.remove(); + } else { + // Another source counted the issue, and it must not be relogged until all + // sources remove it. + *v -= 1; + } + }, + } + } + + *old = issue_ids; + difference + } +} + +/// Logs emitted issues to console logs, deduplicating issues between peeks of +/// the collected issues. The ConsoleUi can be shared and capture issues from +/// multiple sources, with deduplication operating across all issues. +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +#[derive(Clone)] +pub struct ConsoleUi { + options:LogOptions, + + #[turbo_tasks(trace_ignore, debug_ignore)] + seen:Arc>, +} + +impl PartialEq for ConsoleUi { + fn eq(&self, other:&Self) -> bool { self.options == other.options } +} + +#[turbo_tasks::value_impl] +impl ConsoleUi { + #[turbo_tasks::function] + pub fn new(options:TransientInstance) -> Vc { + ConsoleUi { options:(*options).clone(), seen:Arc::new(Mutex::new(SeenIssues::new())) } + .cell() + } +} + +#[turbo_tasks::value_impl] +impl IssueReporter for ConsoleUi { + #[turbo_tasks::function] + async fn report_issues( + &self, + issues:TransientInstance, + source:TransientValue, + min_failing_severity:Vc, + ) -> Result> { + let issues = &*issues; + let LogOptions { + ref current_dir, ref project_dir, show_all, log_detail, log_level, .. + } = self.options; + let mut grouped_issues:GroupedIssues = HashMap::new(); + + let issues = issues + .iter_with_shortest_path() + .map(|(issue, path)| { + async move { + let plain_issue = issue.into_plain(path); + let id = plain_issue.internal_hash(false).await?; + Ok((plain_issue.await?, *id)) + } + }) + .try_join() + .await?; + + let issue_ids = issues.iter().map(|(_, id)| *id).collect::>(); + let mut new_ids = self.seen.lock().unwrap().new_ids(source.into_value(), issue_ids); + + let mut has_fatal = false; + for (plain_issue, id) in issues { + if !new_ids.remove(&id) { + continue; + } + + let severity = plain_issue.severity; + if severity <= *min_failing_severity.await? { + has_fatal = true; + } + + let context_path = + make_relative_to_cwd(&plain_issue.file_path, project_dir, current_dir); + let stage = plain_issue.stage.to_string(); + let processing_path = &*plain_issue.processing_path; + let severity_map = grouped_issues.entry(severity).or_default(); + let category_map = severity_map.entry(stage.clone()).or_default(); + let issues = category_map.entry(context_path.to_string()).or_default(); + + let mut styled_issue = style_issue_source(&plain_issue, &context_path); + let description = &plain_issue.description; + if let Some(description) = description { + writeln!(&mut styled_issue, "\n{}", render_styled_string_to_ansi(description))?; + } + + if log_detail { + styled_issue.push('\n'); + let detail = &plain_issue.detail; + if let Some(detail) = detail { + for line in render_styled_string_to_ansi(detail).split('\n') { + writeln!(&mut styled_issue, "| {line}")?; + } + } + let documentation_link = &plain_issue.documentation_link; + if !documentation_link.is_empty() { + writeln!(&mut styled_issue, "\ndocumentation: {documentation_link}")?; + } + format_optional_path(processing_path, &mut styled_issue)?; + } + issues.push(styled_issue); + } + + for severity in ORDERED_GROUPS.iter().copied().filter(|l| *l <= log_level) { + if let Some(severity_map) = grouped_issues.get_mut(&severity) { + let severity_map_size = severity_map.len(); + let indent = if severity_map_size == 1 { + print!("{} - ", severity.style(severity_to_style(severity))); + "" + } else { + println!("{} -", severity.style(severity_to_style(severity))); + " " + }; + let severity_map_take_count = + if show_all { severity_map_size } else { DEFAULT_SHOW_COUNT }; + let mut categories = severity_map.keys().cloned().collect::>(); + categories.sort(); + for category in categories.iter().take(severity_map_take_count) { + let category_issues = severity_map.get_mut(category).unwrap(); + let category_issues_size = category_issues.len(); + let indent = if category_issues_size == 1 && indent.is_empty() { + print!("[{category}] "); + "".to_string() + } else { + println!("{indent}[{category}]"); + format!("{indent} ") + }; + let (mut contextes, mut vendor_contextes):(Vec<_>, Vec<_>) = category_issues + .iter_mut() + .partition(|(context, _)| !context.contains("node_modules")); + contextes.sort_by_key(|(c, _)| *c); + if show_all { + vendor_contextes.sort_by_key(|(c, _)| *c); + contextes.extend(vendor_contextes); + } + let category_issues_take_count = if show_all { + category_issues_size + } else { + min(contextes.len(), DEFAULT_SHOW_COUNT) + }; + for (context, issues) in contextes.into_iter().take(category_issues_take_count) + { + issues.sort(); + println!("{indent}{}", context.bright_blue()); + let issues_size = issues.len(); + let issues_take_count = + if show_all { issues_size } else { DEFAULT_SHOW_COUNT }; + for issue in issues.iter().take(issues_take_count) { + let mut i = 0; + for line in issue.lines() { + println!("{indent} {line}"); + i += 1; + } + if i > 1 { + // Spacing after multi line issues + println!(); + } + } + if issues_size > issues_take_count { + println!("{indent} {}", show_all_message("issues", issues_size)); + } + } + if category_issues_size > category_issues_take_count { + println!( + "{indent}{}", + show_all_message_with_shown_count( + "paths", + category_issues_size, + category_issues_take_count + ) + ); + } + } + if severity_map_size > severity_map_take_count { + println!("{indent}{}", show_all_message("categories", severity_map_size)) + } + } + } + + Ok(Vc::cell(has_fatal)) + } +} + +fn make_relative_to_cwd<'a>(path:&'a str, project_dir:&Path, cwd:&Path) -> Cow<'a, str> { + if let Some(path_in_project) = path.strip_prefix("[project]/") { + let abs_path = if std::path::MAIN_SEPARATOR != '/' { + project_dir.join(path_in_project.replace('/', std::path::MAIN_SEPARATOR_STR)) + } else { + project_dir.join(path_in_project) + }; + let relative = + abs_path.strip_prefix(cwd).unwrap_or(&abs_path).to_string_lossy().to_string(); + relative.into() + } else { + path.into() + } +} + +fn show_all_message(label:&str, size:usize) -> StyledContent { + show_all_message_with_shown_count(label, size, DEFAULT_SHOW_COUNT) +} + +fn show_all_message_with_shown_count(label:&str, size:usize, shown:usize) -> StyledContent { + if shown == 0 { + format!( + "... [{} {label}] are hidden, run with {} to show them", + size, + "--show-all".bright_green() + ) + .bold() + } else { + format!( + "... [{} more {label}] are hidden, run with {} to show all", + size - shown, + "--show-all".bright_green() + ) + .bold() + } +} + +fn render_styled_string_to_ansi(styled_string:&StyledString) -> String { + match styled_string { + StyledString::Line(parts) => { + let mut string = String::new(); + for part in parts { + string.push_str(&render_styled_string_to_ansi(part)); + } + string.push('\n'); + string + }, + StyledString::Stack(parts) => { + let mut string = String::new(); + for part in parts { + string.push_str(&render_styled_string_to_ansi(part)); + string.push('\n'); + } + string + }, + StyledString::Text(string) => string.to_string(), + StyledString::Code(string) => string.blue().to_string(), + StyledString::Strong(string) => string.bold().to_string(), + } +} + +fn style_issue_source(plain_issue:&PlainIssue, context_path:&str) -> String { + let title = &plain_issue.title; + let formatted_title = match title { + StyledString::Text(text) => text.bold().to_string(), + _ => render_styled_string_to_ansi(title), + }; + + if let Some(source) = &plain_issue.source { + let mut styled_issue = match source.range { + Some((start, _)) => { + format!("{}:{}:{} {}", context_path, start.line + 1, start.column, formatted_title) + }, + None => format!("{} {}", context_path, formatted_title), + }; + styled_issue.push('\n'); + format_source_content(source, &mut styled_issue); + styled_issue + } else { + formatted_title + } +} diff --git a/crates/turbopack-cli-utils/Source/lib.rs b/crates/turbopack-cli-utils/Source/lib.rs new file mode 100644 index 0000000000000..59b518e1b8750 --- /dev/null +++ b/crates/turbopack-cli-utils/Source/lib.rs @@ -0,0 +1,17 @@ +#![feature(async_closure)] +#![feature(min_specialization)] +#![feature(round_char_boundary)] +#![feature(thread_id_value)] +#![feature(arbitrary_self_types)] + +pub mod issue; +pub mod runtime_entry; +pub mod source_context; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_resolve::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-cli-utils/Source/runtime_entry.rs b/crates/turbopack-cli-utils/Source/runtime_entry.rs new file mode 100644 index 0000000000000..3e670fe3e5537 --- /dev/null +++ b/crates/turbopack-cli-utils/Source/runtime_entry.rs @@ -0,0 +1,84 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + chunk::{EvaluatableAsset, EvaluatableAssetExt, EvaluatableAssets}, + context::AssetContext, + issue::IssueSeverity, + module::Module, + resolve::{origin::PlainResolveOrigin, parse::Request}, + source::Source, +}; +use turbopack_resolve::ecmascript::cjs_resolve; + +#[turbo_tasks::value(shared)] +pub enum RuntimeEntry { + Request(Vc, Vc), + Evaluatable(Vc>), + Source(Vc>), +} + +#[turbo_tasks::value_impl] +impl RuntimeEntry { + #[turbo_tasks::function] + pub async fn resolve_entry( + self: Vc, + asset_context:Vc>, + ) -> Result> { + let (request, path) = match *self.await? { + RuntimeEntry::Evaluatable(e) => return Ok(EvaluatableAssets::one(e)), + RuntimeEntry::Source(source) => { + return Ok(EvaluatableAssets::one(source.to_evaluatable(asset_context))); + }, + RuntimeEntry::Request(r, path) => (r, path), + }; + + let modules = cjs_resolve( + Vc::upcast(PlainResolveOrigin::new(asset_context, path)), + request, + None, + IssueSeverity::Error.cell(), + ) + .resolve() + .await? + .primary_modules() + .await?; + + let mut runtime_entries = Vec::with_capacity(modules.len()); + for &module in &modules { + if let Some(entry) = + Vc::try_resolve_sidecast::>(module).await? + { + runtime_entries.push(entry); + } else { + bail!( + "runtime reference resolved to an asset ({}) that cannot be evaluated", + module.ident().to_string().await? + ); + } + } + + Ok(Vc::cell(runtime_entries)) + } +} + +#[turbo_tasks::value(transparent)] +pub struct RuntimeEntries(Vec>); + +#[turbo_tasks::value_impl] +impl RuntimeEntries { + #[turbo_tasks::function] + pub async fn resolve_entries( + self: Vc, + asset_context:Vc>, + ) -> Result> { + let mut runtime_entries = Vec::new(); + + for reference in &self.await? { + let resolved_entries = reference.resolve_entry(asset_context).await?; + runtime_entries.extend(&resolved_entries); + } + + Ok(Vc::cell(runtime_entries)) + } +} diff --git a/crates/turbopack-cli-utils/Source/source_context.rs b/crates/turbopack-cli-utils/Source/source_context.rs new file mode 100644 index 0000000000000..8f4abb3c4fbfa --- /dev/null +++ b/crates/turbopack-cli-utils/Source/source_context.rs @@ -0,0 +1,93 @@ +use std::fmt::{Display, Write}; + +use owo_colors::OwoColorize; +use turbo_tasks_fs::source_context::{SourceContextLine, SourceContextLines}; + +struct MarkerRange { + start:char, + end:char, + pos:usize, + len:usize, +} + +impl Display for MarkerRange { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for _ in 0..self.pos { + f.write_char(' ')?; + } + f.write_char(self.start)?; + if self.len > 1 { + for _ in 2..self.len { + f.write_char('-')?; + } + f.write_char(self.end)?; + } + Ok(()) + } +} + +pub fn format_source_context_lines(ctx:&SourceContextLines, f:&mut impl Write) { + const PADDING:usize = 6; + const SPACE:char = ' '; + for line in &ctx.0 { + match line { + SourceContextLine::Context { line, outside } => { + writeln!(f, "{}", format_args!("{line:>PADDING$} | {outside}").dimmed()).unwrap(); + }, + SourceContextLine::Start { line, before, inside } => { + writeln!( + f, + "{SPACE:PADDING$} | {}", + MarkerRange { start:'v', end:'-', pos:before.len(), len:inside.len() }.bold(), + ) + .unwrap(); + writeln!(f, "{line:>PADDING$} + {}{}", before.dimmed(), inside.bold()).unwrap(); + }, + SourceContextLine::End { line, inside, after } => { + writeln!(f, "{line:>PADDING$} + {}{}", inside.bold(), after.dimmed()).unwrap(); + writeln!( + f, + "{SPACE:PADDING$} +{}", + MarkerRange { start:'-', end:'^', pos:0, len:inside.len() + 1 }.bold() + ) + .unwrap(); + }, + SourceContextLine::StartAndEnd { line, before, inside, after } => { + writeln!( + f, + "{SPACE:PADDING$} + {}", + MarkerRange { start:'v', end:'v', pos:before.len(), len:inside.len() }.bold() + ) + .unwrap(); + if inside.len() >= 2 { + writeln!( + f, + "{line:>PADDING$} + {}{}{}", + before.dimmed(), + inside.bold(), + after.dimmed() + ) + .unwrap(); + } else { + writeln!( + f, + "{line:>PADDING$} + {}{}{}", + before.bold(), + inside.bold(), + after.bold() + ) + .unwrap(); + } + writeln!( + f, + "{SPACE:PADDING$} + {}", + MarkerRange { start:'^', end:'^', pos:before.len(), len:inside.len() }.bold() + ) + .unwrap(); + }, + SourceContextLine::Inside { line, inside } => { + writeln!(f, "{:>PADDING$} + {}", line.bold(), inside.bold()).unwrap(); + }, + } + } +} diff --git a/crates/turbopack-cli-utils/build.rs b/crates/turbopack-cli-utils/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-cli-utils/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-cli/Source/arguments.rs b/crates/turbopack-cli/Source/arguments.rs new file mode 100644 index 0000000000000..32a40999ce76e --- /dev/null +++ b/crates/turbopack-cli/Source/arguments.rs @@ -0,0 +1,110 @@ +use std::{ + net::IpAddr, + path::{Path, PathBuf}, +}; + +use clap::{Args, Parser}; +use turbopack_cli_utils::issue::IssueSeverityCliOption; + +#[derive(Debug, Parser)] +#[clap(author, version, about, long_about = None)] +pub enum Arguments { + Build(BuildArguments), + Dev(DevArguments), +} + +impl Arguments { + /// The directory of the application. see [CommonArguments]::dir + pub fn dir(&self) -> Option<&Path> { + match self { + Arguments::Build(args) => args.common.dir.as_deref(), + Arguments::Dev(args) => args.common.dir.as_deref(), + } + } +} + +#[derive(Debug, Args, Clone)] +pub struct CommonArguments { + /// The entrypoints of the project. Resolved relative to the project's + /// directory (`--dir`). + #[clap(value_parser)] + pub entries:Option>, + + /// The directory of the application. + /// If no directory is provided, the current directory will be used. + #[clap(short, long, value_parser)] + pub dir:Option, + + /// The root directory of the project. Nothing outside of this directory can + /// be accessed. e. g. the monorepo root. + /// If no directory is provided, `dir` will be used. + #[clap(long, value_parser)] + pub root:Option, + + /// Filter by issue severity. + #[clap(short, long)] + pub log_level:Option, + + /// Show all log messages without limit. + #[clap(long)] + pub show_all:bool, + + /// Expand the log details. + #[clap(long)] + pub log_detail:bool, + + /// Whether to enable full task stats recording in Turbo Engine. + #[clap(long)] + pub full_stats:bool, + + /// Enable experimental garbage collection with the provided memory limit in + /// MB. + #[clap(long)] + pub memory_limit:Option, +} + +#[derive(Debug, Args)] +#[clap(author, version, about, long_about = None)] +pub struct DevArguments { + #[clap(flatten)] + pub common:CommonArguments, + + /// The port number on which to start the application + /// Note: setting env PORT allows to configure port without explicit cli + /// args. However, this is temporary measure to conform with existing + /// next.js devserver and can be removed in the future. + #[clap(short, long, value_parser, default_value_t = 3000, env = "PORT")] + pub port:u16, + + /// Hostname on which to start the application + #[clap(short = 'H', long, value_parser, default_value = "0.0.0.0")] + pub hostname:IpAddr, + + /// Compile all, instead of only compiling referenced assets when their + /// parent asset is requested + #[clap(long)] + pub eager_compile:bool, + + /// Don't open the browser automatically when the dev server has started. + #[clap(long)] + pub no_open:bool, + + // == + // = Inherited options from next-dev, need revisit later. + // == + /// If port is not explicitly specified, use different port if it's already + /// in use. + #[clap(long)] + pub allow_retry:bool, +} + +#[derive(Debug, Args)] +#[clap(author, version, about, long_about = None)] +pub struct BuildArguments { + #[clap(flatten)] + pub common:CommonArguments, + + /// Don't minify build output. + #[clap(long)] + pub no_minify:bool, +} diff --git a/crates/turbopack-cli/Source/build/mod.rs b/crates/turbopack-cli/Source/build/mod.rs new file mode 100644 index 0000000000000..4597f0b13d69b --- /dev/null +++ b/crates/turbopack-cli/Source/build/mod.rs @@ -0,0 +1,346 @@ +use std::{ + collections::HashSet, + env::current_dir, + path::{MAIN_SEPARATOR, PathBuf}, + sync::Arc, +}; + +use anyhow::{Context, Result, bail}; +use turbo_tasks::{RcStr, TransientInstance, TryJoinIterExt, TurboTasks, Value, Vc}; +use turbo_tasks_fs::FileSystem; +use turbo_tasks_memory::MemoryBackend; +use turbopack::ecmascript::EcmascriptModuleAsset; +use turbopack_cli_utils::issue::{ConsoleUi, LogOptions}; +use turbopack_core::{ + asset::Asset, + chunk::{ + ChunkableModule, + ChunkingContext, + ChunkingContextExt, + EvaluatableAssets, + MinifyType, + availability_info::AvailabilityInfo, + }, + environment::{BrowserEnvironment, Environment, ExecutionEnvironment}, + issue::{IssueReporter, IssueSeverity, handle_issues}, + module::Module, + output::OutputAsset, + reference::all_assets_from_entries, + reference_type::{EntryReferenceSubType, ReferenceType}, + resolve::{ + origin::{PlainResolveOrigin, ResolveOriginExt}, + parse::Request, + }, +}; +use turbopack_ecmascript_runtime::RuntimeType; +use turbopack_env::dotenv::load_env; +use turbopack_node::execution_context::ExecutionContext; +use turbopack_nodejs::NodeJsChunkingContext; + +use crate::{ + arguments::BuildArguments, + contexts::{NodeEnv, get_client_asset_context, get_client_compile_time_info}, + util::{ + EntryRequest, + EntryRequests, + NormalizedDirs, + normalize_dirs, + normalize_entries, + output_fs, + project_fs, + }, +}; + +pub fn register() { + turbopack::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} + +pub struct TurbopackBuildBuilder { + turbo_tasks:Arc>, + project_dir:RcStr, + root_dir:RcStr, + entry_requests:Vec, + browserslist_query:RcStr, + log_level:IssueSeverity, + show_all:bool, + log_detail:bool, + minify_type:MinifyType, +} + +impl TurbopackBuildBuilder { + pub fn new( + turbo_tasks:Arc>, + project_dir:RcStr, + root_dir:RcStr, + ) -> Self { + TurbopackBuildBuilder { + turbo_tasks, + project_dir, + root_dir, + entry_requests:vec![], + browserslist_query:"chrome 64, edge 79, firefox 67, opera 51, safari 12".into(), + log_level:IssueSeverity::Warning, + show_all:false, + log_detail:false, + minify_type:MinifyType::Minify, + } + } + + pub fn entry_request(mut self, entry_asset_path:EntryRequest) -> Self { + self.entry_requests.push(entry_asset_path); + self + } + + pub fn browserslist_query(mut self, browserslist_query:RcStr) -> Self { + self.browserslist_query = browserslist_query; + self + } + + pub fn log_level(mut self, log_level:IssueSeverity) -> Self { + self.log_level = log_level; + self + } + + pub fn show_all(mut self, show_all:bool) -> Self { + self.show_all = show_all; + self + } + + pub fn log_detail(mut self, log_detail:bool) -> Self { + self.log_detail = log_detail; + self + } + + pub fn minify_type(mut self, minify_type:MinifyType) -> Self { + self.minify_type = minify_type; + self + } + + pub async fn build(self) -> Result<()> { + let task = self.turbo_tasks.spawn_once_task::<(), _>(async move { + let build_result = build_internal( + self.project_dir.clone(), + self.root_dir, + EntryRequests( + self.entry_requests.iter().cloned().map(EntryRequest::cell).collect(), + ) + .cell(), + self.browserslist_query, + self.minify_type, + ); + + // Await the result to propagate any errors. + build_result.await?; + + let issue_reporter:Vc> = + Vc::upcast(ConsoleUi::new(TransientInstance::new(LogOptions { + project_dir:PathBuf::from(self.project_dir), + current_dir:current_dir().unwrap(), + show_all:self.show_all, + log_detail:self.log_detail, + log_level:self.log_level, + }))); + + handle_issues(build_result, issue_reporter, IssueSeverity::Error.into(), None, None) + .await?; + + Ok(Default::default()) + }); + + self.turbo_tasks.wait_task_completion(task, true).await?; + + Ok(()) + } +} + +#[turbo_tasks::function] +async fn build_internal( + project_dir:RcStr, + root_dir:RcStr, + entry_requests:Vc, + browserslist_query:RcStr, + minify_type:MinifyType, +) -> Result> { + let env = Environment::new(Value::new(ExecutionEnvironment::Browser( + BrowserEnvironment { + dom:true, + web_worker:false, + service_worker:false, + browserslist_query:browserslist_query.clone(), + } + .into(), + ))); + let output_fs = output_fs(project_dir.clone()); + let project_fs = project_fs(root_dir.clone()); + let project_relative = project_dir.strip_prefix(&*root_dir).unwrap(); + let project_relative:RcStr = project_relative + .strip_prefix(MAIN_SEPARATOR) + .unwrap_or(project_relative) + .replace(MAIN_SEPARATOR, "/") + .into(); + let project_path = project_fs.root().join(project_relative); + let build_output_root = output_fs.root().join("dist".into()); + + let node_env = NodeEnv::Production.cell(); + + let chunking_context = Vc::upcast( + NodeJsChunkingContext::builder( + project_path, + build_output_root, + build_output_root, + build_output_root, + build_output_root, + env, + match *node_env.await? { + NodeEnv::Development => RuntimeType::Development, + NodeEnv::Production => RuntimeType::Production, + }, + ) + .minify_type(minify_type) + .build(), + ); + + let compile_time_info = get_client_compile_time_info(browserslist_query, node_env); + let execution_context = + ExecutionContext::new(project_path, chunking_context, load_env(project_path)); + let asset_context = + get_client_asset_context(project_path, execution_context, compile_time_info, node_env); + + let entry_requests = (*entry_requests + .await? + .iter() + .cloned() + .map(|r| { + async move { + Ok(match &*r.await? { + EntryRequest::Relative(p) => { + Request::relative( + Value::new(p.clone().into()), + Default::default(), + Default::default(), + false, + ) + }, + EntryRequest::Module(m, p) => { + Request::module( + m.clone(), + Value::new(p.clone().into()), + Default::default(), + Default::default(), + ) + }, + }) + } + }) + .try_join() + .await?) + .to_vec(); + + let origin = PlainResolveOrigin::new(asset_context, output_fs.root().join("_".into())); + let project_dir = &project_dir; + let entries = entry_requests + .into_iter() + .map(|request_vc| { + async move { + let ty = Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)); + let request = request_vc.await?; + origin + .resolve_asset(request_vc, origin.resolve_options(ty.clone()), ty) + .first_module() + .await? + .with_context(|| { + format!( + "Unable to resolve entry {} from directory {}.", + request.request().unwrap(), + project_dir + ) + }) + } + }) + .try_join() + .await?; + + let entry_chunk_groups = entries + .into_iter() + .map(|entry_module| { + async move { + Ok( + if let Some(ecmascript) = + Vc::try_resolve_downcast_type::(entry_module).await? + { + Vc::cell(vec![ + Vc::try_resolve_downcast_type::( + chunking_context, + ) + .await? + .unwrap() + .entry_chunk_group( + build_output_root + .join( + ecmascript + .ident() + .path() + .file_stem() + .await? + .as_deref() + .unwrap() + .into(), + ) + .with_extension("entry.js".into()), + Vc::upcast(ecmascript), + EvaluatableAssets::one(Vc::upcast(ecmascript)), + Value::new(AvailabilityInfo::Root), + ) + .await? + .asset, + ]) + } else if let Some(chunkable) = + Vc::try_resolve_sidecast::>(entry_module).await? + { + chunking_context.root_chunk_group_assets(chunkable) + } else { + // TODO convert into a serve-able asset + bail!( + "Entry module is not chunkable, so it can't be used to bootstrap the \ + application" + ) + }, + ) + } + }) + .try_join() + .await?; + + let mut chunks:HashSet>> = HashSet::new(); + for chunk_group in entry_chunk_groups { + chunks.extend(&*all_assets_from_entries(chunk_group).await?); + } + + chunks.iter().map(|c| c.content().write(c.ident().path())).try_join().await?; + + Ok(Default::default()) +} + +pub async fn build(args:&BuildArguments) -> Result<()> { + let NormalizedDirs { project_dir, root_dir } = + normalize_dirs(&args.common.dir, &args.common.root)?; + + let tt = TurboTasks::new(MemoryBackend::new( + args.common.memory_limit.map_or(usize::MAX, |l| l * 1024 * 1024), + )); + + let mut builder = TurbopackBuildBuilder::new(tt, project_dir, root_dir) + .log_detail(args.common.log_detail) + .log_level(args.common.log_level.map_or_else(|| IssueSeverity::Warning, |l| l.0)) + .minify_type(if args.no_minify { MinifyType::NoMinify } else { MinifyType::Minify }) + .show_all(args.common.show_all); + + for entry in normalize_entries(&args.common.entries) { + builder = builder.entry_request(EntryRequest::Relative(entry)); + } + + builder.build().await?; + + Ok(()) +} diff --git a/crates/turbopack-cli/Source/contexts.rs b/crates/turbopack-cli/Source/contexts.rs new file mode 100644 index 0000000000000..7d1206f29ca98 --- /dev/null +++ b/crates/turbopack-cli/Source/contexts.rs @@ -0,0 +1,225 @@ +use std::{collections::HashMap, fmt}; + +use anyhow::Result; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_fs::{FileSystem, FileSystemPath}; +use turbopack::{ + ModuleAssetContext, + ecmascript::{EcmascriptInputTransform, TreeShakingMode}, + module_options::{ + JsxTransformOptions, + ModuleOptionsContext, + ModuleRule, + ModuleRuleCondition, + ModuleRuleEffect, + }, +}; +use turbopack_browser::react_refresh::assert_can_resolve_react_refresh; +use turbopack_core::{ + compile_time_defines, + compile_time_info::{CompileTimeDefines, CompileTimeInfo}, + condition::ContextCondition, + context::AssetContext, + environment::{BrowserEnvironment, Environment, ExecutionEnvironment}, + resolve::options::{ImportMap, ImportMapping}, +}; +use turbopack_ecmascript_plugins::transform::{ + emotion::{EmotionTransformConfig, EmotionTransformer}, + styled_components::{StyledComponentsTransformConfig, StyledComponentsTransformer}, + styled_jsx::StyledJsxTransformer, +}; +use turbopack_node::{ + execution_context::ExecutionContext, + transforms::postcss::PostCssTransformOptions, +}; +use turbopack_resolve::resolve_options_context::ResolveOptionsContext; + +#[turbo_tasks::value(shared)] +pub enum NodeEnv { + Development, + Production, +} + +impl fmt::Display for NodeEnv { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + match self { + NodeEnv::Development => f.write_str("development"), + NodeEnv::Production => f.write_str("production"), + } + } +} + +async fn foreign_code_context_condition() -> Result { + Ok(ContextCondition::InDirectory("node_modules".to_string())) +} + +#[turbo_tasks::function] +pub async fn get_client_import_map(project_path:Vc) -> Result> { + let mut import_map = ImportMap::empty(); + + import_map.insert_singleton_alias("@swc/helpers", project_path); + import_map.insert_singleton_alias("styled-jsx", project_path); + import_map.insert_singleton_alias("react", project_path); + import_map.insert_singleton_alias("react-dom", project_path); + + import_map.insert_wildcard_alias( + "@vercel/turbopack-ecmascript-runtime/", + ImportMapping::PrimaryAlternative( + "./*".into(), + Some(turbopack_ecmascript_runtime::embed_fs().root()), + ) + .cell(), + ); + + Ok(import_map.cell()) +} + +#[turbo_tasks::function] +pub async fn get_client_resolve_options_context( + project_path:Vc, +) -> Result> { + let next_client_import_map = get_client_import_map(project_path); + let module_options_context = ResolveOptionsContext { + enable_node_modules:Some(project_path.root().resolve().await?), + custom_conditions:vec!["development".into()], + import_map:Some(next_client_import_map), + browser:true, + module:true, + ..Default::default() + }; + Ok(ResolveOptionsContext { + enable_typescript:true, + enable_react:true, + rules:vec![( + foreign_code_context_condition().await?, + module_options_context.clone().cell(), + )], + ..module_options_context + } + .cell()) +} + +#[turbo_tasks::function] +async fn get_client_module_options_context( + project_path:Vc, + execution_context:Vc, + env:Vc, + node_env:Vc, +) -> Result> { + let module_options_context = ModuleOptionsContext { + preset_env_versions:Some(env), + execution_context:Some(execution_context), + tree_shaking_mode:Some(TreeShakingMode::ReexportsOnly), + ..Default::default() + }; + + let resolve_options_context = get_client_resolve_options_context(project_path); + + let enable_react_refresh = matches!(*node_env.await?, NodeEnv::Development) + && assert_can_resolve_react_refresh(project_path, resolve_options_context) + .await? + .is_found(); + + let enable_jsx = Some( + JsxTransformOptions { react_refresh:enable_react_refresh, ..Default::default() }.cell(), + ); + + let versions = *env.runtime_versions().await?; + + let conditions = ModuleRuleCondition::any(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".js".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".jsx".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".ts".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".tsx".to_string()), + ]); + + let custom_rules = ModuleRule::new( + conditions, + vec![ModuleRuleEffect::ExtendEcmascriptTransforms { + prepend:Vc::cell(vec![ + EcmascriptInputTransform::Plugin(Vc::cell(Box::new( + EmotionTransformer::new(&EmotionTransformConfig::default()) + .expect("Should be able to create emotion transformer"), + ) as _)), + EcmascriptInputTransform::Plugin(Vc::cell(Box::new( + StyledComponentsTransformer::new(&StyledComponentsTransformConfig::default()), + ) as _)), + EcmascriptInputTransform::Plugin(Vc::cell(Box::new(StyledJsxTransformer::new( + !module_options_context.use_swc_css, + versions, + )) as _)), + ]), + append:Vc::cell(vec![]), + }], + ); + + let module_options_context = ModuleOptionsContext { + enable_jsx, + enable_postcss_transform:Some(PostCssTransformOptions::default().cell()), + enable_typescript_transform:Some(Default::default()), + rules:vec![( + foreign_code_context_condition().await?, + module_options_context.clone().cell(), + )], + custom_rules:vec![custom_rules], + ..module_options_context + } + .cell(); + + Ok(module_options_context) +} + +#[turbo_tasks::function] +pub fn get_client_asset_context( + project_path:Vc, + execution_context:Vc, + compile_time_info:Vc, + node_env:Vc, +) -> Vc> { + let resolve_options_context = get_client_resolve_options_context(project_path); + let module_options_context = get_client_module_options_context( + project_path, + execution_context, + compile_time_info.environment(), + node_env, + ); + + let asset_context:Vc> = Vc::upcast(ModuleAssetContext::new( + Vc::cell(HashMap::new()), + compile_time_info, + module_options_context, + resolve_options_context, + Vc::cell("client".into()), + )); + + asset_context +} + +fn client_defines(node_env:&NodeEnv) -> Vc { + compile_time_defines!( + process.turbopack = true, + process.env.TURBOPACK = true, + process.env.NODE_ENV = node_env.to_string() + ) + .cell() +} + +#[turbo_tasks::function] +pub async fn get_client_compile_time_info( + browserslist_query:RcStr, + node_env:Vc, +) -> Result> { + Ok( + CompileTimeInfo::builder(Environment::new(Value::new(ExecutionEnvironment::Browser( + BrowserEnvironment { + dom:true, + web_worker:false, + service_worker:false, + browserslist_query, + } + .into(), + )))) + .defines(client_defines(&*node_env.await?)) + .cell(), + ) +} diff --git a/crates/turbopack-cli/Source/dev/mod.rs b/crates/turbopack-cli/Source/dev/mod.rs new file mode 100644 index 0000000000000..3886ff0557d38 --- /dev/null +++ b/crates/turbopack-cli/Source/dev/mod.rs @@ -0,0 +1,511 @@ +use std::{ + collections::HashSet, + env::current_dir, + future::{Future, join}, + io::{Write, stdout}, + net::{IpAddr, SocketAddr}, + path::{MAIN_SEPARATOR, PathBuf}, + sync::Arc, + time::{Duration, Instant}, +}; + +use anyhow::{Context, Result}; +use owo_colors::OwoColorize; +use turbo_tasks::{ + RcStr, + TransientInstance, + TurboTasks, + UpdateInfo, + Value, + Vc, + util::{FormatBytes, FormatDuration}, +}; +use turbo_tasks_fs::FileSystem; +use turbo_tasks_malloc::TurboMalloc; +use turbo_tasks_memory::MemoryBackend; +use turbopack::evaluate_context::node_build_environment; +use turbopack_cli_utils::issue::{ConsoleUi, LogOptions}; +use turbopack_core::{ + issue::{IssueReporter, IssueSeverity}, + resolve::parse::Request, + server_fs::ServerFileSystem, +}; +use turbopack_dev_server::{ + DevServer, + DevServerBuilder, + introspect::IntrospectionSource, + source::{ + ContentSource, + combined::CombinedContentSource, + router::PrefixedRouterContentSource, + static_assets::StaticAssetsContentSource, + }, +}; +use turbopack_ecmascript_runtime::RuntimeType; +use turbopack_env::dotenv::load_env; +use turbopack_node::execution_context::ExecutionContext; +use turbopack_nodejs::NodeJsChunkingContext; + +use self::web_entry_source::create_web_entry_source; +use crate::{ + arguments::DevArguments, + contexts::NodeEnv, + util::{ + EntryRequest, + NormalizedDirs, + normalize_dirs, + normalize_entries, + output_fs, + project_fs, + }, +}; + +pub(crate) mod web_entry_source; + +pub struct TurbopackDevServerBuilder { + turbo_tasks:Arc>, + project_dir:RcStr, + root_dir:RcStr, + entry_requests:Vec, + eager_compile:bool, + hostname:Option, + issue_reporter:Option>, + port:Option, + browserslist_query:RcStr, + log_level:IssueSeverity, + show_all:bool, + log_detail:bool, + allow_retry:bool, +} + +impl TurbopackDevServerBuilder { + pub fn new( + turbo_tasks:Arc>, + project_dir:RcStr, + root_dir:RcStr, + ) -> TurbopackDevServerBuilder { + TurbopackDevServerBuilder { + turbo_tasks, + project_dir, + root_dir, + entry_requests:vec![], + eager_compile:false, + hostname:None, + issue_reporter:None, + port:None, + browserslist_query:"last 1 Chrome versions, last 1 Firefox versions, last 1 Safari \ + versions, last 1 Edge versions" + .into(), + log_level:IssueSeverity::Warning, + show_all:false, + log_detail:false, + allow_retry:false, + } + } + + pub fn entry_request(mut self, entry_asset_path:EntryRequest) -> TurbopackDevServerBuilder { + self.entry_requests.push(entry_asset_path); + self + } + + pub fn eager_compile(mut self, eager_compile:bool) -> TurbopackDevServerBuilder { + self.eager_compile = eager_compile; + self + } + + pub fn hostname(mut self, hostname:IpAddr) -> TurbopackDevServerBuilder { + self.hostname = Some(hostname); + self + } + + pub fn port(mut self, port:u16) -> TurbopackDevServerBuilder { + self.port = Some(port); + self + } + + pub fn browserslist_query(mut self, browserslist_query:RcStr) -> TurbopackDevServerBuilder { + self.browserslist_query = browserslist_query; + self + } + + pub fn log_level(mut self, log_level:IssueSeverity) -> TurbopackDevServerBuilder { + self.log_level = log_level; + self + } + + pub fn show_all(mut self, show_all:bool) -> TurbopackDevServerBuilder { + self.show_all = show_all; + self + } + + pub fn allow_retry(mut self, allow_retry:bool) -> TurbopackDevServerBuilder { + self.allow_retry = allow_retry; + self + } + + pub fn log_detail(mut self, log_detail:bool) -> TurbopackDevServerBuilder { + self.log_detail = log_detail; + self + } + + pub fn issue_reporter( + mut self, + issue_reporter:Box, + ) -> TurbopackDevServerBuilder { + self.issue_reporter = Some(issue_reporter); + self + } + + /// Attempts to find an open port to bind. + fn find_port(&self, host:IpAddr, port:u16, max_attempts:u16) -> Result { + // max_attempts of 1 means we loop 0 times. + let max_attempts = max_attempts - 1; + let mut attempts = 0; + loop { + let current_port = port + attempts; + let addr = SocketAddr::new(host, current_port); + let listen_result = DevServer::listen(addr); + + if let Err(e) = &listen_result { + if self.allow_retry && attempts < max_attempts { + // Returned error from `listen` is not `std::io::Error` but `anyhow::Error`, + // so we need to access its source to check if it is + // `std::io::ErrorKind::AddrInUse`. + let should_retry = e + .source() + .and_then(|e| { + e.downcast_ref::() + .map(|e| e.kind() == std::io::ErrorKind::AddrInUse) + }) + .unwrap_or(false); + + if should_retry { + println!( + "{} - Port {} is in use, trying {} instead", + "warn ".yellow(), + current_port, + current_port + 1 + ); + attempts += 1; + continue; + } + } + } + + return listen_result; + } + } + + pub async fn build(self) -> Result { + let port = self.port.context("port must be set")?; + let host = self.hostname.context("hostname must be set")?; + + let server = self.find_port(host, port, 10)?; + + let turbo_tasks = self.turbo_tasks; + let project_dir:RcStr = self.project_dir; + let root_dir:RcStr = self.root_dir; + let eager_compile = self.eager_compile; + let show_all = self.show_all; + let log_detail:bool = self.log_detail; + let browserslist_query:RcStr = self.browserslist_query; + let log_args = Arc::new(LogOptions { + current_dir:current_dir().unwrap(), + project_dir:PathBuf::from(project_dir.clone()), + show_all, + log_detail, + log_level:self.log_level, + }); + let entry_requests = Arc::new(self.entry_requests); + let tasks = turbo_tasks.clone(); + let issue_provider = self.issue_reporter.unwrap_or_else(|| { + // Initialize a ConsoleUi reporter if no custom reporter was provided + Box::new(move || Vc::upcast(ConsoleUi::new(log_args.clone().into()))) + }); + + let source = move || { + source( + root_dir.clone(), + project_dir.clone(), + entry_requests.clone().into(), + eager_compile, + browserslist_query.clone(), + ) + }; + + let issue_reporter_arc = Arc::new(move || issue_provider.get_issue_reporter()); + Ok(server.serve(tasks, source, issue_reporter_arc)) + } +} + +#[turbo_tasks::function] +async fn source( + root_dir:RcStr, + project_dir:RcStr, + entry_requests:TransientInstance>, + eager_compile:bool, + browserslist_query:RcStr, +) -> Result>> { + let project_relative = project_dir.strip_prefix(&*root_dir).unwrap(); + let project_relative:RcStr = project_relative + .strip_prefix(MAIN_SEPARATOR) + .unwrap_or(project_relative) + .replace(MAIN_SEPARATOR, "/") + .into(); + + let output_fs = output_fs(project_dir); + let fs = project_fs(root_dir); + let project_path:Vc = fs.root().join(project_relative); + + let env = load_env(project_path); + let build_output_root = output_fs.root().join(".turbopack/build".into()); + + let build_chunking_context = NodeJsChunkingContext::builder( + project_path, + build_output_root, + build_output_root, + build_output_root.join("chunks".into()), + build_output_root.join("assets".into()), + node_build_environment(), + RuntimeType::Development, + ) + .build(); + + let execution_context = + ExecutionContext::new(project_path, Vc::upcast(build_chunking_context), env); + + let server_fs = Vc::upcast::>(ServerFileSystem::new()); + let server_root = server_fs.root(); + let entry_requests = entry_requests + .iter() + .map(|r| { + match r { + EntryRequest::Relative(p) => { + Request::relative( + Value::new(p.clone().into()), + Default::default(), + Default::default(), + false, + ) + }, + EntryRequest::Module(m, p) => { + Request::module( + m.clone(), + Value::new(p.clone().into()), + Default::default(), + Default::default(), + ) + }, + } + }) + .collect(); + + let web_source = create_web_entry_source( + project_path, + execution_context, + entry_requests, + server_root, + env, + eager_compile, + NodeEnv::Development.cell(), + browserslist_query, + ); + let static_source = Vc::upcast(StaticAssetsContentSource::new( + Default::default(), + project_path.join("public".into()), + )); + let main_source = CombinedContentSource::new(vec![static_source, web_source]); + let introspect = + Vc::upcast(IntrospectionSource { roots:HashSet::from([Vc::upcast(main_source)]) }.cell()); + let main_source = Vc::upcast(main_source); + let source = Vc::upcast(PrefixedRouterContentSource::new( + Default::default(), + vec![("__turbopack__".into(), introspect)], + main_source, + )); + + Ok(source) +} + +pub fn register() { + turbopack::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} + +/// Start a devserver with the given args. +pub async fn start_server(args:&DevArguments) -> Result<()> { + let start = Instant::now(); + + #[cfg(feature = "tokio_console")] + console_subscriber::init(); + register(); + + let NormalizedDirs { project_dir, root_dir } = + normalize_dirs(&args.common.dir, &args.common.root)?; + + let tt = TurboTasks::new(MemoryBackend::new( + args.common.memory_limit.map_or(usize::MAX, |l| l * 1024 * 1024), + )); + + let tt_clone = tt.clone(); + + let mut server = TurbopackDevServerBuilder::new(tt, project_dir, root_dir) + .eager_compile(args.eager_compile) + .hostname(args.hostname) + .port(args.port) + .log_detail(args.common.log_detail) + .show_all(args.common.show_all) + .log_level(args.common.log_level.map_or_else(|| IssueSeverity::Warning, |l| l.0)); + + for entry in normalize_entries(&args.common.entries) { + server = server.entry_request(EntryRequest::Relative(entry)) + } + + #[cfg(feature = "serializable")] + { + server = server.allow_retry(args.allow_retry); + } + + let server = server.build().await?; + + { + let addr = &server.addr; + let hostname = if addr.ip().is_loopback() || addr.ip().is_unspecified() { + "localhost".to_string() + } else if addr.is_ipv6() { + // When using an IPv6 address, we need to surround the IP in brackets to + // distinguish it from the port's `:`. + format!("[{}]", addr.ip()) + } else { + addr.ip().to_string() + }; + let index_uri = match addr.port() { + 443 => format!("https://{hostname}"), + 80 => format!("http://{hostname}"), + port => format!("http://{hostname}:{port}"), + }; + println!("{} - started server on {}, url: {}", "ready".green(), server.addr, index_uri); + if !args.no_open { + let _ = webbrowser::open(&index_uri); + } + } + + let stats_future = async move { + if args.common.log_detail { + println!( + "{event_type} - initial compilation {start} ({memory})", + event_type = "event".purple(), + start = FormatDuration(start.elapsed()), + memory = FormatBytes(TurboMalloc::memory_usage()) + ); + } + + let mut progress_counter = 0; + loop { + let update_future = profile_timeout( + tt_clone.as_ref(), + tt_clone.aggregated_update_info(Duration::from_millis(100), Duration::MAX), + ); + + if let Some(UpdateInfo { duration, tasks, reasons, .. }) = update_future.await { + progress_counter = 0; + match (args.common.log_detail, !reasons.is_empty()) { + (true, true) => { + println!( + "\x1b[2K{event_type} - {reasons} {duration} ({tasks} tasks, {memory})", + event_type = "event".purple(), + duration = FormatDuration(duration), + tasks = tasks, + memory = FormatBytes(TurboMalloc::memory_usage()) + ); + }, + (true, false) => { + println!( + "\x1b[2K{event_type} - compilation {duration} ({tasks} tasks, \ + {memory})", + event_type = "event".purple(), + duration = FormatDuration(duration), + tasks = tasks, + memory = FormatBytes(TurboMalloc::memory_usage()) + ); + }, + (false, true) => { + println!( + "\x1b[2K{event_type} - {reasons} {duration}", + event_type = "event".purple(), + duration = FormatDuration(duration), + ); + }, + (false, false) => { + if duration > Duration::from_secs(1) { + println!( + "\x1b[2K{event_type} - compilation {duration}", + event_type = "event".purple(), + duration = FormatDuration(duration), + ); + } + }, + } + } else { + progress_counter += 1; + if args.common.log_detail { + print!( + "\x1b[2K{event_type} - updating for {progress_counter}s... ({memory})\r", + event_type = "event".purple(), + memory = FormatBytes(TurboMalloc::memory_usage()) + ); + } else { + print!( + "\x1b[2K{event_type} - updating for {progress_counter}s...\r", + event_type = "event".purple(), + ); + } + let _ = stdout().lock().flush(); + } + } + }; + + join!(stats_future, async { server.future.await.unwrap() }).await; + + Ok(()) +} + +#[cfg(feature = "profile")] +// When profiling, exits the process when no new updates have been received for +// a given timeout and there are no more tasks in progress. +async fn profile_timeout(tt:&TurboTasks, future:impl Future) -> T { + /// How long to wait in between updates before force-exiting the process + /// during profiling. + const PROFILE_EXIT_TIMEOUT:Duration = Duration::from_secs(5); + + futures::pin_mut!(future); + loop { + match tokio::time::timeout(PROFILE_EXIT_TIMEOUT, &mut future).await { + Ok(res) => return res, + Err(_) => { + if tt.get_in_progress_count() == 0 { + std::process::exit(0) + } + }, + } + } +} + +#[cfg(not(feature = "profile"))] +fn profile_timeout( + _tt:&TurboTasks, + future:impl Future, +) -> impl Future { + future +} + +pub trait IssueReporterProvider: Send + Sync + 'static { + fn get_issue_reporter(&self) -> Vc>; +} + +impl IssueReporterProvider for T +where + T: Fn() -> Vc> + Send + Sync + Clone + 'static, +{ + fn get_issue_reporter(&self) -> Vc> { self() } +} diff --git a/crates/turbopack-cli/Source/dev/web_entry_source.rs b/crates/turbopack-cli/Source/dev/web_entry_source.rs new file mode 100644 index 0000000000000..472ef464cbe5a --- /dev/null +++ b/crates/turbopack-cli/Source/dev/web_entry_source.rs @@ -0,0 +1,163 @@ +use anyhow::{Result, anyhow}; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, Vc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; +use turbopack::ecmascript::EcmascriptModuleAsset; +use turbopack_browser::{BrowserChunkingContext, react_refresh::assert_can_resolve_react_refresh}; +use turbopack_cli_utils::runtime_entry::{RuntimeEntries, RuntimeEntry}; +use turbopack_core::{ + chunk::{ChunkableModule, ChunkingContext}, + environment::Environment, + file_source::FileSource, + reference_type::{EntryReferenceSubType, ReferenceType}, + resolve::{ + origin::{PlainResolveOrigin, ResolveOriginExt}, + parse::Request, + }, +}; +use turbopack_dev_server::{ + html::DevHtmlAsset, + source::{ContentSource, asset_graph::AssetGraphContentSource}, +}; +use turbopack_ecmascript_runtime::RuntimeType; +use turbopack_node::execution_context::ExecutionContext; + +use crate::{ + contexts::{ + NodeEnv, + get_client_asset_context, + get_client_compile_time_info, + get_client_resolve_options_context, + }, + embed_js::embed_file_path, +}; + +#[turbo_tasks::function] +pub fn get_client_chunking_context( + project_path:Vc, + server_root:Vc, + environment:Vc, +) -> Vc> { + Vc::upcast( + BrowserChunkingContext::builder( + project_path, + server_root, + server_root, + server_root.join("/_chunks".into()), + server_root.join("/_assets".into()), + environment, + RuntimeType::Development, + ) + .hot_module_replacement() + .build(), + ) +} + +#[turbo_tasks::function] +pub async fn get_client_runtime_entries( + project_path:Vc, +) -> Result> { + let resolve_options_context = get_client_resolve_options_context(project_path); + + let mut runtime_entries = Vec::new(); + + let enable_react_refresh = + assert_can_resolve_react_refresh(project_path, resolve_options_context) + .await? + .as_request(); + // It's important that React Refresh come before the regular bootstrap file, + // because the bootstrap contains JSX which requires Refresh's global + // functions to be available. + if let Some(request) = enable_react_refresh { + runtime_entries.push(RuntimeEntry::Request(request, project_path.join("_".into())).cell()) + }; + + runtime_entries.push( + RuntimeEntry::Source(Vc::upcast(FileSource::new(embed_file_path( + "entry/bootstrap.ts".into(), + )))) + .cell(), + ); + + Ok(Vc::cell(runtime_entries)) +} + +#[turbo_tasks::function] +pub async fn create_web_entry_source( + project_path:Vc, + execution_context:Vc, + entry_requests:Vec>, + server_root:Vc, + _env:Vc>, + eager_compile:bool, + node_env:Vc, + browserslist_query:RcStr, +) -> Result>> { + let compile_time_info = get_client_compile_time_info(browserslist_query, node_env); + let asset_context = + get_client_asset_context(project_path, execution_context, compile_time_info, node_env); + let chunking_context = + get_client_chunking_context(project_path, server_root, compile_time_info.environment()); + let entries = get_client_runtime_entries(project_path); + + let runtime_entries = entries.resolve_entries(asset_context); + + let origin = PlainResolveOrigin::new(asset_context, project_path.join("_".into())); + let entries = entry_requests + .into_iter() + .map(|request| { + async move { + let ty = Value::new(ReferenceType::Entry(EntryReferenceSubType::Web)); + Ok(origin + .resolve_asset(request, origin.resolve_options(ty.clone()), ty) + .resolve() + .await? + .primary_modules() + .await? + .first() + .copied()) + } + }) + .try_join() + .await?; + + let entries:Vec<_> = entries + .into_iter() + .flatten() + .map(|module| { + async move { + if let Some(ecmascript) = + Vc::try_resolve_downcast_type::(module).await? + { + Ok(( + Vc::upcast(ecmascript), + chunking_context, + Some(runtime_entries.with_entry(Vc::upcast(ecmascript))), + )) + } else if let Some(chunkable) = + Vc::try_resolve_sidecast::>(module).await? + { + // TODO this is missing runtime code, so it's probably broken and we should also + // add an ecmascript chunk with the runtime code + Ok((chunkable, chunking_context, None)) + } else { + // TODO convert into a serve-able asset + Err(anyhow!( + "Entry module is not chunkable, so it can't be used to bootstrap the \ + application" + )) + } + } + }) + .try_join() + .await?; + + let entry_asset = Vc::upcast(DevHtmlAsset::new(server_root.join("index.html".into()), entries)); + + let graph = Vc::upcast(if eager_compile { + AssetGraphContentSource::new_eager(server_root, entry_asset) + } else { + AssetGraphContentSource::new_lazy(server_root, entry_asset) + }); + Ok(graph) +} diff --git a/crates/turbopack-cli/Source/embed_js.rs b/crates/turbopack-cli/Source/embed_js.rs new file mode 100644 index 0000000000000..5588821ba433e --- /dev/null +++ b/crates/turbopack-cli/Source/embed_js.rs @@ -0,0 +1,13 @@ +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::{FileContent, FileSystem, FileSystemPath, embed_directory}; + +#[turbo_tasks::function] +fn embed_fs() -> Vc> { + embed_directory!("turbopack-cli", "$CARGO_MANIFEST_DIR/js/src") +} + +#[turbo_tasks::function] +pub(crate) fn embed_file(path:RcStr) -> Vc { embed_fs().root().join(path).read() } + +#[turbo_tasks::function] +pub(crate) fn embed_file_path(path:RcStr) -> Vc { embed_fs().root().join(path) } diff --git a/crates/turbopack-cli/Source/lib.rs b/crates/turbopack-cli/Source/lib.rs new file mode 100644 index 0000000000000..fc513ef3411d5 --- /dev/null +++ b/crates/turbopack-cli/Source/lib.rs @@ -0,0 +1,19 @@ +#![feature(future_join)] +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +pub mod arguments; +pub mod build; +pub(crate) mod contexts; +pub mod dev; +pub(crate) mod embed_js; +pub(crate) mod util; + +pub fn register() { + turbopack::register(); + turbopack_nodejs::register(); + turbopack_browser::register(); + turbopack_ecmascript_plugins::register(); + turbopack_resolve::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-cli/Source/main.rs b/crates/turbopack-cli/Source/main.rs new file mode 100644 index 0000000000000..e339b5ceaedd8 --- /dev/null +++ b/crates/turbopack-cli/Source/main.rs @@ -0,0 +1,86 @@ +#![feature(future_join)] +#![feature(min_specialization)] + +use std::path::Path; + +use anyhow::{Context, Result}; +use clap::Parser; +use tracing_subscriber::{EnvFilter, Registry, layer::SubscriberExt, util::SubscriberInitExt}; +use turbopack_cli::{arguments::Arguments, register}; +use turbopack_trace_utils::{ + exit::ExitGuard, + raw_trace::RawTraceLayer, + trace_writer::TraceWriter, + tracing_presets::{ + TRACING_OVERVIEW_TARGETS, + TRACING_TURBO_TASKS_TARGETS, + TRACING_TURBOPACK_TARGETS, + }, +}; + +#[global_allocator] +static ALLOC:turbo_tasks_malloc::TurboMalloc = turbo_tasks_malloc::TurboMalloc; + +fn main() { + use turbo_tasks_malloc::TurboMalloc; + + let args = Arguments::parse(); + + let trace = std::env::var("TURBOPACK_TRACING").ok(); + + let _guard = if let Some(mut trace) = trace { + // Trace presets + match trace.as_str() { + "overview" => { + trace = TRACING_OVERVIEW_TARGETS.join(","); + }, + "turbopack" => { + trace = TRACING_TURBOPACK_TARGETS.join(","); + }, + "turbo-tasks" => { + trace = TRACING_TURBO_TASKS_TARGETS.join(","); + }, + _ => {}, + } + + let subscriber = Registry::default(); + + let subscriber = subscriber.with(EnvFilter::builder().parse(trace).unwrap()); + + let internal_dir = args.dir().unwrap_or_else(|| Path::new(".")).join(".turbopack"); + std::fs::create_dir_all(&internal_dir) + .context("Unable to create .turbopack directory") + .unwrap(); + let trace_file = internal_dir.join("trace.log"); + let trace_writer = std::fs::File::create(trace_file).unwrap(); + let (trace_writer, guard) = TraceWriter::new(trace_writer); + let subscriber = subscriber.with(RawTraceLayer::new(trace_writer)); + + let guard = ExitGuard::new(guard).unwrap(); + + subscriber.init(); + + Some(guard) + } else { + None + }; + + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .on_thread_stop(|| { + TurboMalloc::thread_stop(); + }) + .build() + .unwrap() + .block_on(main_inner(args)) + .unwrap(); +} + +async fn main_inner(args:Arguments) -> Result<()> { + register(); + + match args { + Arguments::Build(args) => turbopack_cli::build::build(&args).await, + Arguments::Dev(args) => turbopack_cli::dev::start_server(&args).await, + } +} diff --git a/crates/turbopack-cli/Source/util.rs b/crates/turbopack-cli/Source/util.rs new file mode 100644 index 0000000000000..3df8f99fab5c5 --- /dev/null +++ b/crates/turbopack-cli/Source/util.rs @@ -0,0 +1,73 @@ +use std::{env::current_dir, path::PathBuf}; + +use anyhow::{Context, Result}; +use dunce::canonicalize; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem}; + +#[turbo_tasks::value(transparent)] +pub struct EntryRequests(pub Vec>); + +#[turbo_tasks::value(shared)] +#[derive(Clone)] +pub enum EntryRequest { + Relative(RcStr), + Module(RcStr, RcStr), +} + +pub struct NormalizedDirs { + /// Normalized project directory path as an absolute path + pub project_dir:RcStr, + /// Normalized root directory path as an absolute path + pub root_dir:RcStr, +} + +/// Normalizes (canonicalizes and represents as an absolute path in a String) +/// the project and root directories. +pub fn normalize_dirs( + project_dir:&Option, + root_dir:&Option, +) -> Result { + let project_dir:RcStr = project_dir + .as_ref() + .map(canonicalize) + .unwrap_or_else(current_dir) + .context("project directory can't be found")? + .to_str() + .context("project directory contains invalid characters")? + .into(); + + let root_dir = match root_dir.as_ref() { + Some(root) => { + canonicalize(root) + .context("root directory can't be found")? + .to_str() + .context("root directory contains invalid characters")? + .into() + }, + None => project_dir.clone(), + }; + + Ok(NormalizedDirs { project_dir, root_dir }) +} + +pub fn normalize_entries(entries:&Option>) -> Vec { + entries + .as_ref() + .map(|v| v.iter().map(|v| RcStr::from(&**v)).collect()) + .unwrap_or_else(|| vec!["src/entry".into()]) +} + +#[turbo_tasks::function] +pub async fn project_fs(project_dir:RcStr) -> Result>> { + let disk_fs = DiskFileSystem::new("project".into(), project_dir, vec![]); + disk_fs.await?.start_watching()?; + Ok(Vc::upcast(disk_fs)) +} + +#[turbo_tasks::function] +pub async fn output_fs(project_dir:RcStr) -> Result>> { + let disk_fs = DiskFileSystem::new("output".into(), project_dir, vec![]); + disk_fs.await?.start_watching()?; + Ok(Vc::upcast(disk_fs)) +} diff --git a/crates/turbopack-cli/benches/bundler.rs b/crates/turbopack-cli/benches/bundler.rs new file mode 100644 index 0000000000000..5ea4228779299 --- /dev/null +++ b/crates/turbopack-cli/benches/bundler.rs @@ -0,0 +1,78 @@ +use std::{ + path::Path, + process::{Child, Command, Stdio}, + time::Duration, +}; + +use anyhow::{Context, Result, anyhow}; +use regex::Regex; +use turbopack_bench::{ + bundlers::{Bundler, RenderType}, + util::{ + npm::{ + NpmPackage, + {self}, + }, + wait_for_match, + }, +}; + +pub struct Turbopack; + +impl Turbopack { + pub fn new() -> Self { Turbopack } +} + +impl Bundler for Turbopack { + fn get_name(&self) -> &str { "Turbopack CSR" } + + fn get_path(&self) -> &str { "/" } + + fn render_type(&self) -> RenderType { RenderType::ClientSideRendered } + + fn prepare(&self, install_dir:&Path) -> Result<()> { + npm::install( + install_dir, + &[ + NpmPackage::new("react-refresh", "^0.14.0"), + NpmPackage::new("@next/react-refresh-utils", "^13.3.0"), + NpmPackage::new("@swc/helpers", "0.4.11"), + ], + ) + .context("failed to install from npm")?; + + Ok(()) + } + + fn start_server(&self, test_dir:&Path) -> Result<(Child, String)> { + let binary = std::env::var("CARGO_BIN_EXE_turobpack-cli") + .unwrap_or_else(|_| std::env!("CARGO_BIN_EXE_turbopack-cli").to_string()); + let mut proc = Command::new(binary) + .args([ + "dev", + "--dir", + test_dir + .to_str() + .ok_or_else(|| anyhow!("failed to convert test directory path to string"))?, + "src/index", + "--no-open", + "--port", + "0", + ]) + .stdout(Stdio::piped()) + .spawn()?; + + // Wait for the devserver address to appear in stdout. + let addr = wait_for_match( + proc.stdout.as_mut().ok_or_else(|| anyhow!("missing stdout"))?, + Regex::new("started server on .+, url: (.*)")?, + ) + .ok_or_else(|| anyhow!("failed to find devserver address"))?; + + Ok((proc, addr)) + } + + fn max_update_timeout(&self, _module_count:usize) -> std::time::Duration { + Duration::from_millis(500) + } +} diff --git a/crates/turbopack-cli/benches/mod.rs b/crates/turbopack-cli/benches/mod.rs new file mode 100644 index 0000000000000..42bd36fbf8147 --- /dev/null +++ b/crates/turbopack-cli/benches/mod.rs @@ -0,0 +1,31 @@ +use criterion::{Criterion, criterion_group, criterion_main}; +use turbopack_bench::bundlers::Bundler; + +mod bundler; + +fn get_bundlers() -> Vec> { vec![Box::new(bundler::Turbopack::new())] } + +fn bench_startup(c:&mut Criterion) { turbopack_bench::bench_startup(c, &get_bundlers()) } + +fn bench_hydration(c:&mut Criterion) { turbopack_bench::bench_hydration(c, &get_bundlers()) } + +fn bench_startup_cached(c:&mut Criterion) { + turbopack_bench::bench_startup_cached(c, &get_bundlers()) +} + +fn bench_hydration_cached(c:&mut Criterion) { + turbopack_bench::bench_hydration_cached(c, &get_bundlers()) +} + +fn bench_hmr_to_eval(c:&mut Criterion) { turbopack_bench::bench_hmr_to_eval(c, &get_bundlers()) } + +fn bench_hmr_to_commit(c:&mut Criterion) { + turbopack_bench::bench_hmr_to_commit(c, &get_bundlers()) +} + +criterion_group!( + name = benches; + config = Criterion::default(); + targets = bench_startup, bench_hydration, bench_startup_cached, bench_hydration_cached, bench_hmr_to_eval, bench_hmr_to_commit +); +criterion_main!(benches); diff --git a/crates/turbopack-cli/build.rs b/crates/turbopack-cli/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-cli/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-cli/js/Source/entry/bootstrap.ts b/crates/turbopack-cli/js/Source/entry/bootstrap.ts new file mode 100644 index 0000000000000..ed6a95a855f35 --- /dev/null +++ b/crates/turbopack-cli/js/Source/entry/bootstrap.ts @@ -0,0 +1,5 @@ +import { initializeHMR } from "./client"; + +initializeHMR({ + assetPrefix: "", +}); diff --git a/crates/turbopack-cli/js/Source/entry/client.ts b/crates/turbopack-cli/js/Source/entry/client.ts new file mode 100644 index 0000000000000..e508087323207 --- /dev/null +++ b/crates/turbopack-cli/js/Source/entry/client.ts @@ -0,0 +1,19 @@ +import { connect } from "@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/hmr-client"; +import { + connectHMR, + addMessageListener, + sendMessage, +} from "@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/websocket"; + +export function initializeHMR(options: { assetPrefix: string }) { + connect({ + addMessageListener, + sendMessage, + onUpdateError: console.error, + }); + connectHMR({ + assetPrefix: options.assetPrefix, + log: true, + path: "/turbopack-hmr", + }); +} diff --git a/crates/turbopack-cli/js/package.json b/crates/turbopack-cli/js/package.json new file mode 100644 index 0000000000000..c9d84baf0559a --- /dev/null +++ b/crates/turbopack-cli/js/package.json @@ -0,0 +1,11 @@ +{ + "name": "@vercel/turbopack-cli", + "description": "Turbopack-cli runtime", + "scripts": {}, + "dependencies": { + "@vercel/turbopack-ecmascript-runtime": "*" + }, + "devDependencies": { + "@types/node": "22.13.1" + } +} diff --git a/crates/turbopack-cli/js/tsconfig.json b/crates/turbopack-cli/js/tsconfig.json new file mode 100644 index 0000000000000..199259563288a --- /dev/null +++ b/crates/turbopack-cli/js/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + // type checking + "strict": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + + // environment + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "target": "esnext", + + // modules + "baseUrl": ".", + "module": "nodenext", + "moduleResolution": "nodenext", + "types": [], + + // emit + "noEmit": true, + "stripInternal": true + }, + "include": ["src"] +} diff --git a/crates/turbopack-core/Source/asset.rs b/crates/turbopack-core/Source/asset.rs new file mode 100644 index 0000000000000..c099819604753 --- /dev/null +++ b/crates/turbopack-core/Source/asset.rs @@ -0,0 +1,93 @@ +use anyhow::Result; +use turbo_tasks::{Completion, RcStr, Vc}; +use turbo_tasks_fs::{ + FileContent, + FileJsonContent, + FileLinesContent, + FileSystemPath, + LinkContent, + LinkType, +}; + +use crate::version::{VersionedAssetContent, VersionedContent}; + +/// An asset. It also forms a graph when following [Asset::references]. +#[turbo_tasks::value_trait] +pub trait Asset { + /// The content of the [Asset]. + fn content(self: Vc) -> Vc; + + /// The content of the [Asset] alongside its version. + async fn versioned_content(self: Vc) -> Result>> { + Ok(Vc::upcast(VersionedAssetContent::new(self.content()))) + } +} + +#[turbo_tasks::value(shared)] +#[derive(Clone)] +pub enum AssetContent { + File(Vc), + // for the relative link, the target is raw value read from the link + // for the absolute link, the target is stripped of the root path while reading + // See [LinkContent::Link] for more details. + Redirect { target:RcStr, link_type:LinkType }, +} + +#[turbo_tasks::value_impl] +impl AssetContent { + #[turbo_tasks::function] + pub fn file(file:Vc) -> Vc { AssetContent::File(file).cell() } + + #[turbo_tasks::function] + pub async fn parse_json(self: Vc) -> Result> { + let this = self.await?; + match &*this { + AssetContent::File(content) => Ok(content.parse_json()), + AssetContent::Redirect { .. } => { + Ok(FileJsonContent::unparseable("a redirect can't be parsed as json").cell()) + }, + } + } + + #[turbo_tasks::function] + pub async fn file_content(self: Vc) -> Result> { + let this = self.await?; + match &*this { + AssetContent::File(content) => Ok(*content), + AssetContent::Redirect { .. } => Ok(FileContent::NotFound.cell()), + } + } + + #[turbo_tasks::function] + pub async fn lines(self: Vc) -> Result> { + let this = self.await?; + match &*this { + AssetContent::File(content) => Ok(content.lines()), + AssetContent::Redirect { .. } => Ok(FileLinesContent::Unparseable.cell()), + } + } + + #[turbo_tasks::function] + pub async fn parse_json_with_comments(self: Vc) -> Result> { + let this = self.await?; + match &*this { + AssetContent::File(content) => Ok(content.parse_json_with_comments()), + AssetContent::Redirect { .. } => { + Ok(FileJsonContent::unparseable("a redirect can't be parsed as json").cell()) + }, + } + } + + #[turbo_tasks::function] + pub async fn write(self: Vc, path:Vc) -> Result> { + let this = self.await?; + Ok(match &*this { + AssetContent::File(file) => path.write(*file), + AssetContent::Redirect { target, link_type } => { + path.write_link( + LinkContent::Link { target:target.clone(), link_type:*link_type }.cell(), + ) + }, + }) + } +} diff --git a/crates/turbopack-core/Source/changed.rs b/crates/turbopack-core/Source/changed.rs new file mode 100644 index 0000000000000..5ac1cff9cfcba --- /dev/null +++ b/crates/turbopack-core/Source/changed.rs @@ -0,0 +1,83 @@ +use anyhow::Result; +use turbo_tasks::{ + Completion, + Completions, + Vc, + graph::{GraphTraversal, NonDeterministic}, +}; + +use crate::{ + asset::Asset, + module::Module, + output::{OutputAsset, OutputAssets}, + reference::primary_referenced_modules, +}; + +async fn get_referenced_output_assets( + parent:Vc>, +) -> Result>> + Send> { + Ok(parent.references().await?.clone_value().into_iter()) +} + +async fn get_referenced_modules( + parent:Vc>, +) -> Result>> + Send> { + Ok(primary_referenced_modules(parent).await?.clone_value().into_iter()) +} + +/// Returns a completion that changes when any content of any asset in the whole +/// asset graph changes. +#[turbo_tasks::function] +pub async fn any_content_changed_of_module(root:Vc>) -> Result> { + let completions = NonDeterministic::new() + .skip_duplicates() + .visit([root], get_referenced_modules) + .await + .completed()? + .into_inner() + .into_iter() + .map(|m| content_changed(Vc::upcast(m))) + .collect(); + + Ok(Vc::::cell(completions).completed()) +} + +/// Returns a completion that changes when any content of any asset in the whole +/// asset graph changes. +#[turbo_tasks::function] +pub async fn any_content_changed_of_output_asset( + root:Vc>, +) -> Result> { + let completions = NonDeterministic::new() + .skip_duplicates() + .visit([root], get_referenced_output_assets) + .await + .completed()? + .into_inner() + .into_iter() + .map(|m| content_changed(Vc::upcast(m))) + .collect(); + + Ok(Vc::::cell(completions).completed()) +} + +/// Returns a completion that changes when any content of any asset in the given +/// output asset graphs changes. +#[turbo_tasks::function] +pub async fn any_content_changed_of_output_assets( + roots:Vc, +) -> Result> { + Ok(Vc::::cell( + roots.await?.iter().map(|&a| any_content_changed_of_output_asset(a)).collect(), + ) + .completed()) +} + +/// Returns a completion that changes when the content of the given asset +/// changes. +#[turbo_tasks::function] +pub async fn content_changed(asset:Vc>) -> Result> { + // Reading the file content is enough to add as dependency + asset.content().file_content().await?; + Ok(Completion::new()) +} diff --git a/crates/turbopack-core/Source/chunk/availability_info.rs b/crates/turbopack-core/Source/chunk/availability_info.rs new file mode 100644 index 0000000000000..6f68ed604bdbf --- /dev/null +++ b/crates/turbopack-core/Source/chunk/availability_info.rs @@ -0,0 +1,44 @@ +use anyhow::Result; +use turbo_tasks::Vc; + +use super::available_chunk_items::{AvailableChunkItemInfoMap, AvailableChunkItems}; + +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(PartialOrd, Ord, Hash, Clone, Copy, Debug)] +pub enum AvailabilityInfo { + /// Availability of modules is not tracked + Untracked, + /// Availablility of modules is tracked, but no modules are available + Root, + /// There are modules already available. + Complete { available_chunk_items:Vc }, +} + +impl AvailabilityInfo { + pub fn available_chunk_items(&self) -> Option> { + match self { + Self::Untracked => None, + Self::Root => None, + Self::Complete { available_chunk_items, .. } => Some(*available_chunk_items), + } + } + + pub async fn with_chunk_items(self, chunk_items:Vc) -> Result { + Ok(match self { + AvailabilityInfo::Untracked => AvailabilityInfo::Untracked, + AvailabilityInfo::Root => { + AvailabilityInfo::Complete { + available_chunk_items:AvailableChunkItems::new(chunk_items).resolve().await?, + } + }, + AvailabilityInfo::Complete { available_chunk_items } => { + AvailabilityInfo::Complete { + available_chunk_items:available_chunk_items + .with_chunk_items(chunk_items) + .resolve() + .await?, + } + }, + }) + } +} diff --git a/crates/turbopack-core/Source/chunk/available_chunk_items.rs b/crates/turbopack-core/Source/chunk/available_chunk_items.rs new file mode 100644 index 0000000000000..b6f8ebbdc6982 --- /dev/null +++ b/crates/turbopack-core/Source/chunk/available_chunk_items.rs @@ -0,0 +1,99 @@ +use anyhow::Result; +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{ + TryFlatJoinIterExt, + TryJoinIterExt, + ValueToString, + Vc, + debug::ValueDebugFormat, + trace::TraceRawVcs, +}; +use turbo_tasks_hash::Xxh3Hash64Hasher; + +use super::ChunkItem; + +#[derive(PartialEq, Eq, TraceRawVcs, Copy, Clone, Serialize, Deserialize, ValueDebugFormat)] +pub struct AvailableChunkItemInfo { + pub is_async:bool, +} + +#[turbo_tasks::value(transparent)] +pub struct OptionAvailableChunkItemInfo(Option); + +#[turbo_tasks::value(transparent)] +pub struct AvailableChunkItemInfoMap(IndexMap>, AvailableChunkItemInfo>); + +/// Allows to gather information about which assets are already available. +/// Adding more roots will form a linked list like structure to allow caching +/// `include` queries. +#[turbo_tasks::value] +pub struct AvailableChunkItems { + parent:Option>, + chunk_items:Vc, +} + +#[turbo_tasks::value_impl] +impl AvailableChunkItems { + #[turbo_tasks::function] + pub fn new(chunk_items:Vc) -> Vc { + AvailableChunkItems { parent:None, chunk_items }.cell() + } + + #[turbo_tasks::function] + pub async fn with_chunk_items( + self: Vc, + chunk_items:Vc, + ) -> Result> { + let chunk_items = chunk_items + .await? + .into_iter() + .map(|(&chunk_item, &info)| { + async move { Ok(self.get(chunk_item).await?.is_none().then_some((chunk_item, info))) } + }) + .try_flat_join() + .await?; + Ok(AvailableChunkItems { + parent:Some(self), + chunk_items:Vc::cell(chunk_items.into_iter().collect()), + } + .cell()) + } + + #[turbo_tasks::function] + pub async fn hash(self: Vc) -> Result> { + let this = self.await?; + let mut hasher = Xxh3Hash64Hasher::new(); + if let Some(parent) = this.parent { + hasher.write_value(parent.hash().await?); + } else { + hasher.write_value(0u64); + } + let item_idents = this + .chunk_items + .await? + .iter() + .map(|(&chunk_item, _)| chunk_item.asset_ident().to_string()) + .try_join() + .await?; + for ident in item_idents { + hasher.write_value(ident); + } + Ok(Vc::cell(hasher.finish())) + } + + #[turbo_tasks::function] + pub async fn get( + self: Vc, + chunk_item:Vc>, + ) -> Result> { + let this = self.await?; + if let Some(&info) = this.chunk_items.await?.get(&chunk_item) { + return Ok(Vc::cell(Some(info))); + }; + if let Some(parent) = this.parent { + return Ok(parent.get(chunk_item)); + } + Ok(Vc::cell(None)) + } +} diff --git a/crates/turbopack-core/Source/chunk/chunk_group.rs b/crates/turbopack-core/Source/chunk/chunk_group.rs new file mode 100644 index 0000000000000..b073fdfa870a0 --- /dev/null +++ b/crates/turbopack-core/Source/chunk/chunk_group.rs @@ -0,0 +1,181 @@ +use std::collections::HashSet; + +use anyhow::Result; +use auto_hash_map::AutoSet; +use indexmap::{IndexMap, IndexSet}; +use turbo_tasks::{TryFlatJoinIterExt, TryJoinIterExt, Value, Vc}; + +use super::{ + AsyncModuleInfo, + Chunk, + ChunkContentResult, + ChunkItem, + ChunkingContext, + availability_info::AvailabilityInfo, + available_chunk_items::AvailableChunkItemInfo, + chunk_content, + chunking::make_chunks, +}; +use crate::{module::Module, output::OutputAssets, reference::ModuleReference}; + +pub struct MakeChunkGroupResult { + pub chunks:Vec>>, + pub availability_info:AvailabilityInfo, +} + +/// Creates a chunk group from a set of entries. +pub async fn make_chunk_group( + chunking_context:Vc>, + entries:impl IntoIterator>>, + availability_info:AvailabilityInfo, +) -> Result { + let ChunkContentResult { + chunk_items, + async_modules, + external_module_references, + forward_edges_inherit_async, + local_back_edges_inherit_async, + available_async_modules_back_edges_inherit_async, + } = chunk_content(chunking_context, entries, availability_info).await?; + + // Find all local chunk items that are self async + let self_async_children = chunk_items + .iter() + .copied() + .map(|chunk_item| { + async move { + let is_self_async = *chunk_item.is_self_async().await?; + Ok(is_self_async.then_some(chunk_item)) + } + }) + .try_flat_join() + .await?; + + // Get all available async modules and concatenate with local async modules + let mut async_chunk_items = available_async_modules_back_edges_inherit_async + .keys() + .copied() + .chain(self_async_children.into_iter()) + .map(|chunk_item| (chunk_item, AutoSet::>>::new())) + .collect::>(); + + // Propagate async inheritance + let mut i = 0; + loop { + let Some((&chunk_item, _)) = async_chunk_items.get_index(i) else { + break; + }; + // The first few entries are from + // available_async_modules_back_edges_inherit_async and need to use that map, + // all other entries are local + let map = if i < available_async_modules_back_edges_inherit_async.len() { + &available_async_modules_back_edges_inherit_async + } else { + &local_back_edges_inherit_async + }; + if let Some(parents) = map.get(&chunk_item) { + for &parent in parents.iter() { + // Add item, it will be iterated by this loop too + async_chunk_items.entry(parent).or_default().insert(chunk_item); + } + } + i += 1; + } + + // Create map for chunk items with empty [Option>] + let mut chunk_items = chunk_items + .into_iter() + .map(|chunk_item| (chunk_item, None)) + .collect::>>>(); + + // Insert AsyncModuleInfo for every async module + for (async_item, referenced_async_modules) in async_chunk_items { + let referenced_async_modules = + if let Some(references) = forward_edges_inherit_async.get(&async_item) { + references + .iter() + .copied() + .filter(|item| referenced_async_modules.contains(item)) + .collect() + } else { + Default::default() + }; + chunk_items.insert(async_item, Some(AsyncModuleInfo::new(referenced_async_modules))); + } + + // Compute new [AvailabilityInfo] + let availability_info = { + let map = chunk_items + .iter() + .map(|(&chunk_item, async_info)| { + (chunk_item, AvailableChunkItemInfo { is_async:async_info.is_some() }) + }) + .collect(); + let map = Vc::cell(map); + availability_info.with_chunk_items(map).await? + }; + + // Insert async chunk loaders for every referenced async module + let async_loaders = async_modules + .into_iter() + .map(|module| { + chunking_context.async_loader_chunk_item(module, Value::new(availability_info)) + }) + .collect::>(); + let has_async_loaders = !async_loaders.is_empty(); + let async_loader_chunk_items = async_loaders.iter().map(|&chunk_item| (chunk_item, None)); + + // And also add output assets referenced by async chunk loaders + let async_loader_references = + async_loaders.iter().map(|&loader| loader.references()).try_join().await?; + let async_loader_external_module_references = async_loader_references + .iter() + .flat_map(|references| references.iter().copied()) + .collect(); + + // Pass chunk items to chunking algorithm + let mut chunks = make_chunks( + chunking_context, + Vc::cell(chunk_items.into_iter().collect()), + "".into(), + references_to_output_assets(external_module_references).await?, + ) + .await? + .clone_value(); + + if has_async_loaders { + // Pass async chunk loaders to chunking algorithm + // We want them to be separate since they are specific to this chunk group due + // to available chunk items differing + let async_loader_chunks = make_chunks( + chunking_context, + Vc::cell(async_loader_chunk_items.into_iter().collect()), + "async-loader-".into(), + references_to_output_assets(async_loader_external_module_references).await?, + ) + .await?; + + // concatenate chunks + chunks.extend(async_loader_chunks.iter().copied()); + } + + Ok(MakeChunkGroupResult { chunks, availability_info }) +} + +async fn references_to_output_assets( + references:IndexSet>>, +) -> Result> { + let output_assets = references + .into_iter() + .map(|reference| reference.resolve_reference().primary_output_assets()) + .try_join() + .await?; + let mut set = HashSet::new(); + let output_assets = output_assets + .iter() + .flatten() + .copied() + .filter(|&asset| set.insert(asset)) + .collect::>(); + Ok(OutputAssets::new(output_assets)) +} diff --git a/crates/turbopack-core/Source/chunk/chunking.rs b/crates/turbopack-core/Source/chunk/chunking.rs new file mode 100644 index 0000000000000..ea530104bc8a0 --- /dev/null +++ b/crates/turbopack-core/Source/chunk/chunking.rs @@ -0,0 +1,350 @@ +use std::{ + borrow::Cow, + mem::{replace, take}, + pin::Pin, +}; + +use anyhow::Result; +use futures::Future; +use indexmap::IndexMap; +use once_cell::sync::Lazy; +use regex::Regex; +use tracing::Level; +use turbo_tasks::{RcStr, ReadRef, TryJoinIterExt, ValueToString, Vc}; + +use super::{ + AsyncModuleInfo, + Chunk, + ChunkItem, + ChunkItemsWithAsyncModuleInfo, + ChunkType, + ChunkingContext, + Chunks, +}; +use crate::output::OutputAssets; + +#[turbo_tasks::value] +struct ChunkItemInfo { + ty:Vc>, + name:Vc, + size:usize, +} + +#[turbo_tasks::function] +async fn chunk_item_info( + chunking_context:Vc>, + chunk_item:Vc>, + async_info:Option>, +) -> Result> { + let asset_ident = chunk_item.asset_ident().to_string(); + let ty = chunk_item.ty().resolve().await?; + let chunk_item_size = ty.chunk_item_size(chunking_context, chunk_item, async_info); + Ok( + ChunkItemInfo { ty, size:*chunk_item_size.await?, name:asset_ident.resolve().await? } + .cell(), + ) +} + +/// Creates chunks based on heuristics for the passed `chunk_items`. Also +/// attaches `referenced_output_assets` to the first chunk. +#[turbo_tasks::function] +pub async fn make_chunks( + chunking_context:Vc>, + chunk_items:Vc, + key_prefix:RcStr, + mut referenced_output_assets:Vc, +) -> Result> { + let chunk_items = chunk_items + .await? + .iter() + .map(|&(chunk_item, async_info)| { + async move { + let chunk_item_info = + chunk_item_info(chunking_context, chunk_item, async_info).await?; + Ok((chunk_item, async_info, chunk_item_info)) + } + }) + .try_join() + .await?; + let mut map = IndexMap::<_, Vec<_>>::new(); + for (chunk_item, async_info, chunk_item_info) in chunk_items { + map.entry(chunk_item_info.ty) + .or_default() + .push((chunk_item, async_info, chunk_item_info)); + } + + let mut chunks = Vec::new(); + for (ty, chunk_items) in map { + let ty_name = ty.to_string().await?; + + let chunk_items = chunk_items + .into_iter() + .map(|(chunk_item, async_info, chunk_item_info)| { + async move { + Ok((chunk_item, async_info, chunk_item_info.size, chunk_item_info.name.await?)) + } + }) + .try_join() + .await?; + + let mut split_context = SplitContext { + ty, + chunking_context, + chunks:&mut chunks, + referenced_output_assets:&mut referenced_output_assets, + empty_referenced_output_assets:OutputAssets::empty().resolve().await?, + }; + + app_vendors_split(chunk_items, format!("{key_prefix}{ty_name}"), &mut split_context) + .await?; + } + + Ok(Vc::cell(chunks)) +} + +type ChunkItemWithInfo = + (Vc>, Option>, usize, ReadRef); + +struct SplitContext<'a> { + ty:Vc>, + chunking_context:Vc>, + chunks:&'a mut Vec>>, + referenced_output_assets:&'a mut Vc, + empty_referenced_output_assets:Vc, +} + +/// Handle chunk items based on their total size. If the total size is too +/// small, they will be pushed into `remaining`, if possible. If the total size +/// is too large, it will return `false` and the caller should hand of the chunk +/// items to be further split. Otherwise it creates a chunk. +async fn handle_split_group( + chunk_items:&mut Vec, + key:&mut String, + split_context:&mut SplitContext<'_>, + remaining:Option<&mut Vec>, +) -> Result { + Ok(match (chunk_size(chunk_items), remaining) { + (ChunkSize::Large, _) => false, + (ChunkSize::Perfect, _) | (ChunkSize::Small, None) => { + make_chunk(take(chunk_items), key, split_context).await?; + true + }, + (ChunkSize::Small, Some(remaining)) => { + remaining.extend(take(chunk_items)); + true + }, + }) +} + +/// Creates a chunk with the given `chunk_items. `key` should be unique and is +/// used with [keyed_cell] to place the chunk items into a cell. +#[tracing::instrument(level = Level::TRACE, skip_all, fields(key = display(key)))] +async fn make_chunk( + chunk_items:Vec, + key:&mut String, + split_context:&mut SplitContext<'_>, +) -> Result<()> { + split_context.chunks.push( + split_context.ty.chunk( + split_context.chunking_context, + chunk_items + .into_iter() + .map(|(chunk_item, async_info, ..)| (chunk_item, async_info)) + .collect(), + replace( + split_context.referenced_output_assets, + split_context.empty_referenced_output_assets, + ), + ), + ); + Ok(()) +} + +/// Split chunk items into app code and vendor code. Continues splitting with +/// [package_name_split] if necessary. +#[tracing::instrument(level = Level::TRACE, skip_all, fields(name = display(&name)))] +async fn app_vendors_split( + chunk_items:Vec, + mut name:String, + split_context:&mut SplitContext<'_>, +) -> Result<()> { + let mut app_chunk_items = Vec::new(); + let mut vendors_chunk_items = Vec::new(); + for item in chunk_items { + let (_, _, _, asset_ident) = &item; + if is_app_code(asset_ident) { + app_chunk_items.push(item); + } else { + vendors_chunk_items.push(item); + } + } + let mut remaining = Vec::new(); + let mut key = format!("{}-app", name); + if !handle_split_group(&mut app_chunk_items, &mut key, split_context, Some(&mut remaining)) + .await? + { + folder_split(app_chunk_items, 0, key.into(), split_context).await?; + } + let mut key = format!("{}-vendors", name); + if !handle_split_group(&mut vendors_chunk_items, &mut key, split_context, Some(&mut remaining)) + .await? + { + package_name_split(vendors_chunk_items, key, split_context).await?; + } + if !remaining.is_empty() + && !handle_split_group(&mut remaining, &mut name, split_context, None).await? + { + package_name_split(remaining, name, split_context).await?; + } + Ok(()) +} + +/// Split chunk items by node_modules package name. Continues splitting with +/// [folder_split] if necessary. +#[tracing::instrument(level = Level::TRACE, skip_all, fields(name = display(&name)))] +async fn package_name_split( + chunk_items:Vec, + mut name:String, + split_context:&mut SplitContext<'_>, +) -> Result<()> { + let mut map = IndexMap::<_, Vec>::new(); + for item in chunk_items { + let (_, _, _, asset_ident) = &item; + let package_name = package_name(asset_ident); + if let Some(list) = map.get_mut(package_name) { + list.push(item); + } else { + map.insert(package_name.to_string(), vec![item]); + } + } + let mut remaining = Vec::new(); + for (package_name, mut list) in map { + let mut key = format!("{}-{}", name, package_name); + if !handle_split_group(&mut list, &mut key, split_context, Some(&mut remaining)).await? { + folder_split(list, 0, key.into(), split_context).await?; + } + } + if !remaining.is_empty() + && !handle_split_group(&mut remaining, &mut name, split_context, None).await? + { + folder_split(remaining, 0, name.into(), split_context).await?; + } + Ok(()) +} + +/// A boxed version of [folder_split] for recursion. +fn folder_split_boxed<'a, 'b>( + chunk_items:Vec, + location:usize, + name:Cow<'a, str>, + split_context:&'a mut SplitContext<'b>, +) -> Pin> + Send + 'a>> { + Box::pin(folder_split(chunk_items, location, name, split_context)) +} + +/// Split chunk items by folder structure. +#[tracing::instrument(level = Level::TRACE, skip_all, fields(name = display(&name), location))] +async fn folder_split( + mut chunk_items:Vec, + mut location:usize, + name:Cow<'_, str>, + split_context:&mut SplitContext<'_>, +) -> Result<()> { + let mut map = IndexMap::<_, (_, Vec)>::new(); + loop { + for item in chunk_items { + let (_, _, _, asset_ident) = &item; + let (folder_name, new_location) = folder_name(asset_ident, location); + if let Some((_, list)) = map.get_mut(folder_name) { + list.push(item); + } else { + map.insert(folder_name.to_string(), (new_location, vec![item])); + } + } + if map.len() == 1 { + // shortcut + let (folder_name, (new_location, list)) = map.into_iter().next().unwrap(); + if let Some(new_location) = new_location { + chunk_items = list; + location = new_location; + map = IndexMap::new(); + continue; + } else { + let mut key = format!("{}-{}", name, folder_name); + make_chunk(list, &mut key, split_context).await?; + return Ok(()); + } + } else { + break; + } + } + let mut remaining = Vec::new(); + for (folder_name, (new_location, mut list)) in map { + let mut key = format!("{}-{}", name, folder_name); + if !handle_split_group(&mut list, &mut key, split_context, Some(&mut remaining)).await? { + if let Some(new_location) = new_location { + folder_split_boxed(list, new_location, Cow::Borrowed(&name), split_context).await?; + } else { + make_chunk(list, &mut key, split_context).await?; + } + } + } + if !remaining.is_empty() { + let (_, _, _, asset_ident) = &remaining[0]; + let mut key = format!("{}-{}", name, &asset_ident[..location]); + if !handle_split_group(&mut remaining, &mut key, split_context, None).await? { + make_chunk(remaining, &mut key, split_context).await?; + } + } + Ok(()) +} + +/// Returns `true` if the given `ident` is app code. +fn is_app_code(ident:&str) -> bool { !ident.contains("/node_modules/") } + +/// Returns the package name of the given `ident`. +fn package_name(ident:&str) -> &str { + static PACKAGE_NAME_REGEX:Lazy = + Lazy::new(|| Regex::new(r"/node_modules/((?:@[^/]+/)?[^/]+)").unwrap()); + if let Some(result) = PACKAGE_NAME_REGEX.find_iter(ident).last() { + &result.as_str()["/node_modules/".len()..] + } else { + "" + } +} + +/// Returns the folder name at the given `location` of the given `ident`. Also +/// returns the next folder name location if any. +fn folder_name(ident:&str, location:usize) -> (&str, Option) { + if let Some(offset) = ident[location..].find('/') { + let new_location = location + offset + 1; + (&ident[..new_location], Some(new_location)) + } else { + (ident, None) + } +} + +const LARGE_CHUNK:usize = 1_000_000; +const SMALL_CHUNK:usize = 100_000; + +enum ChunkSize { + Large, + Perfect, + Small, +} + +/// Determines the total size of the passed chunk items. Returns too small, too +/// large or perfect fit. +fn chunk_size(chunk_items:&[ChunkItemWithInfo]) -> ChunkSize { + let mut total_size = 0; + for (_, _, size, _) in chunk_items { + total_size += size; + } + if total_size >= LARGE_CHUNK { + ChunkSize::Large + } else if total_size > SMALL_CHUNK { + ChunkSize::Perfect + } else { + ChunkSize::Small + } +} diff --git a/crates/turbopack-core/Source/chunk/chunking_context.rs b/crates/turbopack-core/Source/chunk/chunking_context.rs new file mode 100644 index 0000000000000..2adaad05f600f --- /dev/null +++ b/crates/turbopack-core/Source/chunk/chunking_context.rs @@ -0,0 +1,303 @@ +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{RcStr, TaskInput, Upcast, Value, ValueToString, Vc, trace::TraceRawVcs}; +use turbo_tasks_fs::FileSystemPath; +use turbo_tasks_hash::DeterministicHash; + +use super::{ChunkableModule, EvaluatableAssets, availability_info::AvailabilityInfo}; +use crate::{ + chunk::{ChunkItem, ModuleId}, + environment::Environment, + ident::AssetIdent, + module::Module, + output::{OutputAsset, OutputAssets}, +}; + +#[derive( + Debug, + Default, + TaskInput, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, + TraceRawVcs, + DeterministicHash, +)] +pub enum MinifyType { + #[default] + Minify, + NoMinify, +} + +#[turbo_tasks::value(shared)] +pub struct ChunkGroupResult { + pub assets:Vc, + pub availability_info:AvailabilityInfo, +} + +#[turbo_tasks::value(shared)] +pub struct EntryChunkGroupResult { + pub asset:Vc>, + pub availability_info:AvailabilityInfo, +} + +/// A context for the chunking that influences the way chunks are created +#[turbo_tasks::value_trait] +pub trait ChunkingContext { + fn name(self: Vc) -> Vc; + fn context_path(self: Vc) -> Vc; + fn output_root(self: Vc) -> Vc; + + // TODO remove this, a chunking context should not be bound to a specific + // environment since this can change due to transitions in the module graph + fn environment(self: Vc) -> Vc; + + // TODO(alexkirsz) Remove this from the chunking context. This should be at the + // discretion of chunking context implementors. However, we currently use this + // in a couple of places in `turbopack-css`, so we need to remove that + // dependency first. + fn chunk_path(self: Vc, ident:Vc, extension:RcStr) -> Vc; + + // TODO(alexkirsz) Remove this from the chunking context. + /// Reference Source Map Assets for chunks + fn reference_chunk_source_maps(self: Vc, chunk:Vc>) -> Vc; + + /// Returns a URL (relative or absolute, depending on the asset prefix) to + /// the static asset based on its `ident`. + fn asset_url(self: Vc, ident:Vc) -> Result>; + + fn asset_path( + self: Vc, + content_hash:RcStr, + original_asset_ident:Vc, + ) -> Vc; + + fn is_hot_module_replacement_enabled(self: Vc) -> Vc { Vc::cell(false) } + + fn async_loader_chunk_item( + &self, + module:Vc>, + availability_info:Value, + ) -> Vc>; + fn async_loader_chunk_item_id(&self, module:Vc>) -> Vc; + + fn chunk_group( + self: Vc, + module:Vc>, + availability_info:Value, + ) -> Vc; + + fn evaluated_chunk_group( + self: Vc, + ident:Vc, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Vc; + + /// Generates an output chunk that: + /// * evaluates the given assets; and + /// * exports the result of evaluating the given module as a CommonJS + /// default export. + fn entry_chunk_group( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Result>; + + async fn chunk_item_id_from_ident( + self: Vc, + ident:Vc, + ) -> Result> { + Ok(ModuleId::String(ident.to_string().await?.clone_value()).cell()) + } + + fn chunk_item_id(self: Vc, chunk_item:Vc>) -> Vc { + self.chunk_item_id_from_ident(chunk_item.asset_ident()) + } +} + +pub trait ChunkingContextExt { + fn root_chunk_group( + self: Vc, + module:Vc>, + ) -> Vc + where + Self: Send; + + fn root_chunk_group_assets( + self: Vc, + module:Vc>, + ) -> Vc + where + Self: Send; + + fn evaluated_chunk_group_assets( + self: Vc, + ident:Vc, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Vc + where + Self: Send; + + fn entry_chunk_group_asset( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Vc> + where + Self: Send; + + fn root_entry_chunk_group( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + ) -> Vc + where + Self: Send; + + fn root_entry_chunk_group_asset( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + ) -> Vc> + where + Self: Send; + + fn chunk_group_assets( + self: Vc, + module:Vc>, + availability_info:Value, + ) -> Vc + where + Self: Send; +} + +impl>> ChunkingContextExt for T { + fn root_chunk_group( + self: Vc, + module:Vc>, + ) -> Vc { + self.chunk_group(module, Value::new(AvailabilityInfo::Root)) + } + + fn root_chunk_group_assets( + self: Vc, + module:Vc>, + ) -> Vc { + root_chunk_group_assets(Vc::upcast(self), module) + } + + fn evaluated_chunk_group_assets( + self: Vc, + ident:Vc, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Vc { + evaluated_chunk_group_assets(Vc::upcast(self), ident, evaluatable_assets, availability_info) + } + + fn entry_chunk_group_asset( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Vc> { + entry_chunk_group_asset( + path, + Vc::upcast(self), + module, + evaluatable_assets, + availability_info, + ) + } + + fn root_entry_chunk_group( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + ) -> Vc { + self.entry_chunk_group(path, module, evaluatable_assets, Value::new(AvailabilityInfo::Root)) + } + + fn root_entry_chunk_group_asset( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + ) -> Vc> { + entry_chunk_group_asset( + path, + Vc::upcast(self), + module, + evaluatable_assets, + Value::new(AvailabilityInfo::Root), + ) + } + + fn chunk_group_assets( + self: Vc, + module:Vc>, + availability_info:Value, + ) -> Vc { + chunk_group_assets(Vc::upcast(self), module, availability_info) + } +} + +#[turbo_tasks::function] +async fn root_chunk_group_assets( + chunking_context:Vc>, + module:Vc>, +) -> Result> { + Ok(chunking_context.root_chunk_group(module).await?.assets) +} + +#[turbo_tasks::function] +async fn evaluated_chunk_group_assets( + chunking_context:Vc>, + ident:Vc, + evaluatable_assets:Vc, + availability_info:Value, +) -> Result> { + Ok(chunking_context + .evaluated_chunk_group(ident, evaluatable_assets, availability_info) + .await? + .assets) +} + +#[turbo_tasks::function] +async fn entry_chunk_group_asset( + path:Vc, + chunking_context:Vc>, + module:Vc>, + evaluatable_assets:Vc, + availability_info:Value, +) -> Result>> { + Ok(chunking_context + .entry_chunk_group(path, module, evaluatable_assets, availability_info) + .await? + .asset) +} + +#[turbo_tasks::function] +async fn chunk_group_assets( + chunking_context:Vc>, + module:Vc>, + availability_info:Value, +) -> Result> { + Ok(chunking_context.chunk_group(module, availability_info).await?.assets) +} diff --git a/crates/turbopack-core/Source/chunk/containment_tree.rs b/crates/turbopack-core/Source/chunk/containment_tree.rs new file mode 100644 index 0000000000000..ab1e5de910104 --- /dev/null +++ b/crates/turbopack-core/Source/chunk/containment_tree.rs @@ -0,0 +1,255 @@ +use std::{cell::RefCell, mem::take, rc::Rc}; + +use anyhow::Result; +use indexmap::{IndexMap, IndexSet}; +use turbo_tasks::TryJoinIterExt; + +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct ContainmentTree { + pub key:Option, + pub values:Option>, + pub children:Vec>, +} + +// Temp structure which uses Rc and RefCell +struct Node { + key:K, + values:Vec, + children:Vec>>>, +} + +#[async_trait::async_trait] +pub trait ContainmentTreeKey: Sized { + async fn parent(&self) -> Result; +} + +impl ContainmentTree +where + K: ContainmentTreeKey + std::hash::Hash + Eq + Clone, +{ + pub async fn build(values:I) -> Result> + where + I: IntoIterator, V)>, { + let values:Vec<_> = values.into_iter().collect(); + + // compute all unique common_parents + let mut common_parents = + values.iter().filter_map(|(key, _)| key.clone()).collect::>(); + + Self::expand_common_parents(&mut common_parents).await?; + + let relationships = Self::compute_relationships(&common_parents).await?; + + let mut trees = Self::create_node_tree(common_parents); + + let orphan_values = Self::add_values_to_tree(&mut trees, values); + + let roots = Self::treeify(relationships, &trees); + + // optimize tree by removing unnecessary nodes + Self::skip_unnecessary_nodes(&mut trees); + + // do conversion + let roots = Self::convert_into_common_parent_tree(roots, orphan_values); + + // top level nesting + Ok(if roots.len() == 1 { + roots.into_iter().next().unwrap() + } else { + ContainmentTree { key:None, values:None, children:roots } + }) + } + + /// Expand all common parents to include all their parents. + async fn expand_common_parents(common_parents:&mut IndexSet) -> Result<()> { + // This is mutated while iterating, so we need to loop with index + let mut i = 0; + while i < common_parents.len() { + let current = &common_parents[i]; + let parent = current.parent().await?; + common_parents.insert(parent); + i += 1; + } + Ok(()) + } + + /// Compute parent -> child relationships between common_parents. + async fn compute_relationships(common_parents:&IndexSet) -> Result, K)>> { + common_parents + .iter() + .map(|key| { + let common_parents = &common_parents; + async move { + let mut current = key.clone(); + loop { + let parent = current.parent().await?; + if parent == current { + return Ok((None, key.clone())); + } + if common_parents.contains(&parent) { + // Can't insert here into the parent tree, since we want the order + // of children to be deterministic + return Ok((Some(parent), key.clone())); + } + current = parent; + } + } + }) + .try_join() + .await + } + + /// Create the tree nodes. + fn create_node_tree(common_parents:IndexSet) -> IndexMap>>> { + let mut trees = IndexMap::>>>::new(); + for common_parent in common_parents { + trees.insert( + common_parent.clone(), + Rc::new(RefCell::new(Node { + key:common_parent, + values:Vec::new(), + children:Vec::new(), + })), + ); + } + trees + } + + /// Add chunks to nodes. + fn add_values_to_tree( + trees:&mut IndexMap>>>, + values:Vec<(Option, V)>, + ) -> Vec { + let mut orphan_values = Vec::new(); + for (common_parent, chunk) in values { + if let Some(common_parent) = common_parent { + trees.get_mut(&common_parent).unwrap().borrow_mut().values.push(chunk); + } else { + orphan_values.push(chunk); + } + } + orphan_values + } + + /// Nest each tree by relationship, compute the roots + fn treeify( + relationships:Vec<(Option, K)>, + trees:&IndexMap>>>, + ) -> Vec>>> { + relationships + .into_iter() + .flat_map(|(parent, key)| { + let tree = trees.get(&key).unwrap().clone(); + if let Some(parent) = parent { + trees.get(&parent).unwrap().borrow_mut().children.push(tree); + None + } else { + Some(tree) + } + }) + .collect::>() + } + + /// Optimize tree by removing unnecessary nodes. + fn skip_unnecessary_nodes(trees:&mut IndexMap>>>) { + for tree in trees.values_mut() { + let mut tree = tree.borrow_mut(); + if tree.values.is_empty() && tree.children.len() == 1 { + let child = tree.children.pop().unwrap(); + let mut child = child.borrow_mut(); + tree.key = child.key.clone(); + tree.values.append(&mut child.values); + tree.children.append(&mut child.children); + } + } + } + + // Convert function to the real data structure + fn node_to_common_parent_tree(node:Rc>>) -> ContainmentTree { + let mut node = node.borrow_mut(); + let children = take(&mut node.children) + .into_iter() + .map(Self::node_to_common_parent_tree) + .collect(); + // TODO keyed cell: this would benefit from keying the cell by node.path + let values = Some(take(&mut node.values)); + ContainmentTree { key:Some(node.key.clone()), values, children } + } + + fn convert_into_common_parent_tree( + roots:Vec>>>, + orphan_values:Vec, + ) -> Vec> { + roots + .into_iter() + .map(Self::node_to_common_parent_tree) + .chain(orphan_values.into_iter().map(|value| { + ContainmentTree { key:None, values:Some(vec![value]), children:Vec::new() } + })) + .collect::>() + } +} + +#[cfg(test)] +mod tests { + use async_trait::async_trait; + + use super::*; + + #[derive(Clone, Debug, PartialEq, Eq, Hash)] + struct TestKey(u32, u32); + + #[async_trait] + impl ContainmentTreeKey for TestKey { + async fn parent(&self) -> Result { + if self.1 == 0 { + Ok(TestKey(self.0, 0)) + } else { + Ok(TestKey(self.0, self.1 - 1)) + } + } + } + + #[tokio::test] + async fn test_build_simple_input() -> Result<()> { + let input = vec![ + (None, "value0"), + (Some(TestKey(0, 0)), "value1"), + (Some(TestKey(0, 1)), "value2"), + (Some(TestKey(0, 2)), "value3"), + (Some(TestKey(1, 2)), "value4"), + ]; + + let tree = ContainmentTree::::build(input).await?; + + assert_eq!( + tree, + ContainmentTree { + key:None, + values:None, + children:vec![ + ContainmentTree { + key:Some(TestKey(0, 0)), + values:Some(vec!["value1"]), + children:vec![ContainmentTree { + key:Some(TestKey(0, 1)), + values:Some(vec!["value2"]), + children:vec![ContainmentTree { + key:Some(TestKey(0, 2)), + values:Some(vec!["value3"]), + children:vec![] + }] + }] + }, + ContainmentTree { + key:Some(TestKey(1, 2)), + values:Some(vec!["value4"]), + children:vec![] + }, + ContainmentTree { key:None, values:Some(vec!["value0"]), children:vec![] }, + ] + } + ); + Ok(()) + } +} diff --git a/crates/turbopack-core/Source/chunk/data.rs b/crates/turbopack-core/Source/chunk/data.rs new file mode 100644 index 0000000000000..c57a24d83e880 --- /dev/null +++ b/crates/turbopack-core/Source/chunk/data.rs @@ -0,0 +1,141 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::FileSystemPath; + +use crate::{ + chunk::{ModuleId, OutputChunk, OutputChunkRuntimeInfo}, + output::{OutputAsset, OutputAssets}, +}; + +#[turbo_tasks::value] +pub struct ChunkData { + pub path:String, + pub included:Vec>, + pub excluded:Vec>, + pub module_chunks:Vec, + pub references:Vc, +} + +#[turbo_tasks::value(transparent)] +pub struct ChunkDataOption(Option>); + +// NOTE(alexkirsz) Our convention for naming vector types is to add an "s" to +// the end of the type name, but in this case it would be both gramatically +// incorrect and clash with the variable names everywhere. +// TODO(WEB-101) Should fix this. +#[turbo_tasks::value(transparent)] +pub struct ChunksData(Vec>); + +#[turbo_tasks::function] +fn module_chunk_reference_description() -> Vc { Vc::cell("module chunk".into()) } + +#[turbo_tasks::value_impl] +impl ChunkData { + #[turbo_tasks::function] + pub async fn from_asset( + output_root:Vc, + chunk:Vc>, + ) -> Result> { + let output_root = output_root.await?; + let path = chunk.ident().path().await?; + // The "path" in this case is the chunk's path, not the chunk item's path. + // The difference is a chunk is a file served by the dev server, and an + // item is one of several that are contained in that chunk file. + let Some(path) = output_root.get_path_to(&path) else { + return Ok(Vc::cell(None)); + }; + let path = path.to_string(); + + let Some(output_chunk) = Vc::try_resolve_sidecast::>(chunk).await? + else { + return Ok(Vc::cell(Some( + ChunkData { + path, + included:Vec::new(), + excluded:Vec::new(), + module_chunks:Vec::new(), + references:OutputAssets::empty(), + } + .cell(), + ))); + }; + + let runtime_info = output_chunk.runtime_info().await?; + + let OutputChunkRuntimeInfo { + included_ids, + excluded_ids, + module_chunks, + placeholder_for_future_extensions: _, + } = &*runtime_info; + + let included = if let Some(included_ids) = included_ids { + included_ids.await?.iter().copied().try_join().await? + } else { + Vec::new() + }; + let excluded = if let Some(excluded_ids) = excluded_ids { + excluded_ids.await?.iter().copied().try_join().await? + } else { + Vec::new() + }; + let (module_chunks, module_chunks_references) = if let Some(module_chunks) = module_chunks { + module_chunks + .await? + .iter() + .copied() + .map(|chunk| { + let output_root = output_root.clone(); + + async move { + let chunk_path = chunk.ident().path().await?; + Ok(output_root + .get_path_to(&chunk_path) + .map(|path| (path.to_owned(), chunk))) + } + }) + .try_join() + .await? + .into_iter() + .flatten() + .unzip() + } else { + (Vec::new(), Vec::new()) + }; + + Ok(Vc::cell(Some( + ChunkData { + path, + included, + excluded, + module_chunks, + references:Vc::cell(module_chunks_references), + } + .cell(), + ))) + } + + #[turbo_tasks::function] + pub async fn from_assets( + output_root:Vc, + chunks:Vc, + ) -> Result> { + Ok(Vc::cell( + chunks + .await? + .iter() + .map(|&chunk| ChunkData::from_asset(output_root, chunk)) + .try_join() + .await? + .into_iter() + .flat_map(|chunk| *chunk) + .collect(), + )) + } + + /// Returns [`OutputAsset`]s that this chunk data references. + #[turbo_tasks::function] + pub async fn references(self: Vc) -> Result> { + Ok(self.await?.references) + } +} diff --git a/crates/turbopack-core/Source/chunk/evaluate.rs b/crates/turbopack-core/Source/chunk/evaluate.rs new file mode 100644 index 0000000000000..41bbc8ad0aaab --- /dev/null +++ b/crates/turbopack-core/Source/chunk/evaluate.rs @@ -0,0 +1,80 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{Upcast, Value, ValueToString, Vc}; + +use super::ChunkableModule; +use crate::{ + asset::Asset, + context::AssetContext, + module::Module, + reference_type::{EntryReferenceSubType, ReferenceType}, + source::Source, +}; + +/// Marker trait for the chunking context to accept evaluated entries. +/// +/// The chunking context implementation will resolve the dynamic entry to a +/// well-known value or trait object. +#[turbo_tasks::value_trait] +pub trait EvaluatableAsset: Asset + Module + ChunkableModule {} + +pub trait EvaluatableAssetExt: Send { + fn to_evaluatable( + self: Vc, + asset_context:Vc>, + ) -> Vc>; +} + +impl EvaluatableAssetExt for T +where + T: Upcast>, +{ + fn to_evaluatable( + self: Vc, + asset_context:Vc>, + ) -> Vc> { + to_evaluatable(Vc::upcast(self), asset_context) + } +} + +#[turbo_tasks::function] +async fn to_evaluatable( + asset:Vc>, + asset_context:Vc>, +) -> Result>> { + let module = asset_context + .process(asset, Value::new(ReferenceType::Entry(EntryReferenceSubType::Runtime))) + .module(); + let Some(entry) = Vc::try_resolve_downcast::>(module).await? else { + bail!("{} is not a valid evaluated entry", module.ident().to_string().await?) + }; + Ok(entry) +} + +#[turbo_tasks::value(transparent)] +pub struct EvaluatableAssets(Vec>>); + +#[turbo_tasks::value_impl] +impl EvaluatableAssets { + #[turbo_tasks::function] + pub fn empty() -> Vc { EvaluatableAssets(vec![]).cell() } + + #[turbo_tasks::function] + pub fn one(entry:Vc>) -> Vc { + EvaluatableAssets(vec![entry]).cell() + } + + #[turbo_tasks::function] + pub fn many(assets:Vec>>) -> Vc { + EvaluatableAssets(assets).cell() + } + + #[turbo_tasks::function] + pub async fn with_entry( + self: Vc, + entry:Vc>, + ) -> Result> { + let mut entries = self.await?.clone_value(); + entries.push(entry); + Ok(EvaluatableAssets(entries).cell()) + } +} diff --git a/crates/turbopack-core/Source/chunk/mod.rs b/crates/turbopack-core/Source/chunk/mod.rs new file mode 100644 index 0000000000000..73f4cbbd3ea58 --- /dev/null +++ b/crates/turbopack-core/Source/chunk/mod.rs @@ -0,0 +1,752 @@ +pub mod availability_info; +pub mod available_chunk_items; +pub mod chunk_group; +pub mod chunking; +pub(crate) mod chunking_context; +pub(crate) mod containment_tree; +pub(crate) mod data; +pub(crate) mod evaluate; +pub mod optimize; + +use std::{ + collections::{HashMap, HashSet}, + fmt::{Debug, Display}, + future::Future, + hash::Hash, +}; + +use anyhow::Result; +use auto_hash_map::AutoSet; +use indexmap::{IndexMap, IndexSet}; +use serde::{Deserialize, Serialize}; +use tracing::{Span, info_span}; +use turbo_tasks::{ + RcStr, + ReadRef, + TaskInput, + TryFlatJoinIterExt, + TryJoinIterExt, + Upcast, + ValueToString, + Vc, + debug::ValueDebugFormat, + graph::{AdjacencyMap, GraphTraversal, GraphTraversalResult, Visit, VisitControlFlow}, + trace::TraceRawVcs, +}; +use turbo_tasks_fs::FileSystemPath; +use turbo_tasks_hash::DeterministicHash; + +use self::{availability_info::AvailabilityInfo, available_chunk_items::AvailableChunkItems}; +pub use self::{ + chunking_context::{ + ChunkGroupResult, + ChunkingContext, + ChunkingContextExt, + EntryChunkGroupResult, + MinifyType, + }, + data::{ChunkData, ChunkDataOption, ChunksData}, + evaluate::{EvaluatableAsset, EvaluatableAssetExt, EvaluatableAssets}, +}; +use crate::{ + asset::Asset, + environment::ChunkLoading, + ident::AssetIdent, + module::Module, + output::OutputAssets, + reference::{ModuleReference, ModuleReferences}, +}; + +/// A module id, which can be a number or string +#[turbo_tasks::value(shared)] +#[derive(Debug, Clone, Hash, Ord, PartialOrd, DeterministicHash)] +#[serde(untagged)] +pub enum ModuleId { + Number(u32), + String(RcStr), +} + +impl Display for ModuleId { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ModuleId::Number(i) => write!(f, "{}", i), + ModuleId::String(s) => write!(f, "{}", s), + } + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for ModuleId { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { Vc::cell(self.to_string().into()) } +} + +impl ModuleId { + pub fn parse(id:&str) -> Result { + Ok(match id.parse::() { + Ok(i) => ModuleId::Number(i), + Err(_) => ModuleId::String(id.into()), + }) + } +} + +/// A list of module ids. +#[turbo_tasks::value(transparent, shared)] +pub struct ModuleIds(Vec>); + +/// A [Module] that can be converted into a [Chunk]. +#[turbo_tasks::value_trait] +pub trait ChunkableModule: Module + Asset { + fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Vc>; +} + +#[turbo_tasks::value(transparent)] +pub struct Chunks(Vec>>); + +#[turbo_tasks::value_impl] +impl Chunks { + /// Creates a new empty [Vc]. + #[turbo_tasks::function] + pub fn empty() -> Vc { Vc::cell(vec![]) } +} + +/// A chunk is one type of asset. +/// It usually contains multiple chunk items. +#[turbo_tasks::value_trait] +pub trait Chunk: Asset { + fn ident(self: Vc) -> Vc; + fn chunking_context(self: Vc) -> Vc>; + // TODO Once output assets have their own trait, this path() method will move + // into that trait and ident() will be removed from that. Assets on the + // output-level only have a path and no complex ident. + /// The path of the chunk. + fn path(self: Vc) -> Vc { self.ident().path() } + + /// Other [OutputAsset]s referenced from this [Chunk]. + fn references(self: Vc) -> Vc { OutputAssets::empty() } +} + +/// Aggregated information about a chunk content that can be used by the runtime +/// code to optimize chunk loading. +#[turbo_tasks::value(shared)] +#[derive(Default)] +pub struct OutputChunkRuntimeInfo { + pub included_ids:Option>, + pub excluded_ids:Option>, + /// List of paths of chunks containing individual modules that are part of + /// this chunk. This is useful for selectively loading modules from a chunk + /// without loading the whole chunk. + pub module_chunks:Option>, + pub placeholder_for_future_extensions:(), +} + +#[turbo_tasks::value_trait] +pub trait OutputChunk: Asset { + fn runtime_info(self: Vc) -> Vc; +} + +/// Specifies how a chunk interacts with other chunks when building a chunk +/// group +#[derive( + Copy, Default, Clone, Hash, TraceRawVcs, Serialize, Deserialize, Eq, PartialEq, ValueDebugFormat, +)] +pub enum ChunkingType { + /// Module is placed in the same chunk group and is loaded in parallel. It + /// doesn't become an async module when the referenced module is async. + #[default] + Parallel, + /// Module is placed in the same chunk group and is loaded in parallel. It + /// becomes an async module when the referenced module is async. + ParallelInheritAsync, + /// An async loader is placed into the referencing chunk and loads the + /// separate chunk group in which the module is placed. + Async, + /// Module not placed in chunk group, but its references are still followed. + Passthrough, +} + +#[turbo_tasks::value(transparent)] +pub struct ChunkingTypeOption(Option); + +/// A [ModuleReference] implementing this trait and returning true for +/// [ChunkableModuleReference::is_chunkable] are considered as potentially +/// chunkable references. When all [Module]s of such a reference implement +/// [ChunkableModule] they are placed in [Chunk]s during chunking. +/// They are even potentially placed in the same [Chunk] when a chunk type +/// specific interface is implemented. +#[turbo_tasks::value_trait] +pub trait ChunkableModuleReference: ModuleReference + ValueToString { + fn chunking_type(self: Vc) -> Vc { + Vc::cell(Some(ChunkingType::default())) + } +} + +type AsyncInfo = IndexMap>, Vec>>>; + +pub struct ChunkContentResult { + pub chunk_items:IndexSet>>, + pub async_modules:IndexSet>>, + pub external_module_references:IndexSet>>, + /// A map from local module to all children from which the async module + /// status is inherited + pub forward_edges_inherit_async:AsyncInfo, + /// A map from local module to all parents that inherit the async module + /// status + pub local_back_edges_inherit_async:AsyncInfo, + /// A map from already available async modules to all local parents that + /// inherit the async module status + pub available_async_modules_back_edges_inherit_async:AsyncInfo, +} + +pub async fn chunk_content( + chunking_context:Vc>, + entries:impl IntoIterator>>, + availability_info:AvailabilityInfo, +) -> Result { + chunk_content_internal_parallel(chunking_context, entries, availability_info).await +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, TraceRawVcs, Debug)] +enum InheritAsyncEdge { + /// The chunk item is in the current chunk group and async module info need + /// to be computed for it + LocalModule, + /// The chunk item is already available in the parent chunk group and is an + /// async module. Chunk items that are available but not async modules are + /// not included in back edges at all since they don't influence the parent + /// module in terms of being an async module. + AvailableAsyncModule, +} + +#[derive(Eq, PartialEq, Clone, Hash, Serialize, Deserialize, TraceRawVcs, Debug)] +enum ChunkContentGraphNode { + // A chunk item not placed in the current chunk, but whose references we will + // follow to find more graph nodes. + PassthroughChunkItem { + item:Vc>, + }, + // Chunk items that are placed into the current chunk group + ChunkItem { + item:Vc>, + ident:ReadRef, + }, + // Async module that is referenced from the chunk group + AsyncModule { + module:Vc>, + }, + // ModuleReferences that are not placed in the current chunk group + ExternalModuleReference(Vc>), + /// A list of directly referenced chunk items from which `is_async_module` + /// will be inherited. + InheritAsyncInfo { + item:Vc>, + references:Vec<(Vc>, InheritAsyncEdge)>, + }, +} + +#[derive(Debug, Clone, Copy, TaskInput)] +enum ChunkGraphNodeToReferences { + PassthroughChunkItem(Vc>), + ChunkItem(Vc>), +} + +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, TraceRawVcs)] +struct ChunkGraphEdge { + key:Option>>, + node:ChunkContentGraphNode, +} + +#[derive(Debug, Clone)] +#[turbo_tasks::value(transparent)] +struct ChunkGraphEdges(Vec); + +#[turbo_tasks::function] +async fn graph_node_to_referenced_nodes_with_available_chunk_items( + node:ChunkGraphNodeToReferences, + chunking_context:Vc>, + available_chunk_items:Vc, +) -> Result> { + let edges = graph_node_to_referenced_nodes(node, chunking_context); + let edges_ref = edges.await?; + for (unchanged, edge) in edges_ref.iter().enumerate() { + if let ChunkContentGraphNode::ChunkItem { item, .. } = edge.node { + if let Some(info) = *available_chunk_items.get(item).await? { + let mut new_edges = Vec::with_capacity(edges_ref.len()); + new_edges.extend(edges_ref[0..unchanged].iter().cloned()); + let mut available_chunk_item_info = HashMap::new(); + available_chunk_item_info.insert(item, info); + for edge in edges_ref[unchanged + 1..].iter() { + match edge.node { + ChunkContentGraphNode::ChunkItem { item, .. } => { + if let Some(info) = *available_chunk_items.get(item).await? { + available_chunk_item_info.insert(item, info); + continue; + } + }, + ChunkContentGraphNode::InheritAsyncInfo { item, ref references } => { + let new_references = references + .iter() + .filter_map(|&(r, _)| { + if let Some(info) = available_chunk_item_info.get(&r) { + if info.is_async { + Some((r, InheritAsyncEdge::AvailableAsyncModule)) + } else { + None + } + } else { + Some((r, InheritAsyncEdge::LocalModule)) + } + }) + .collect(); + new_edges.push(ChunkGraphEdge { + key:edge.key, + node:ChunkContentGraphNode::InheritAsyncInfo { + item, + references:new_references, + }, + }); + continue; + }, + _ => {}, + } + new_edges.push(edge.clone()) + } + return Ok(Vc::cell(new_edges)); + } + } + } + Ok(edges) +} + +#[turbo_tasks::function] +async fn graph_node_to_referenced_nodes( + node:ChunkGraphNodeToReferences, + chunking_context:Vc>, +) -> Result> { + let (parent, references) = match &node { + ChunkGraphNodeToReferences::PassthroughChunkItem(item) => (None, item.references()), + ChunkGraphNodeToReferences::ChunkItem(item) => (Some(*item), item.references()), + }; + + let references = references.await?; + let graph_nodes = references + .iter() + .map(|reference| { + async { + let reference = *reference; + let Some(chunkable_module_reference) = + Vc::try_resolve_downcast::>(reference) + .await? + else { + return Ok(vec![ChunkGraphEdge { + key:None, + node:ChunkContentGraphNode::ExternalModuleReference(reference), + }]); + }; + + let Some(chunking_type) = *chunkable_module_reference.chunking_type().await? else { + return Ok(vec![ChunkGraphEdge { + key:None, + node:ChunkContentGraphNode::ExternalModuleReference(reference), + }]); + }; + + let module_data = reference + .resolve_reference() + .resolve() + .await? + .primary_modules() + .await? + .into_iter() + .map(|&module| { + async move { + let Some(chunkable_module) = + Vc::try_resolve_sidecast::>(module) + .await? + else { + return Ok(( + Some(ChunkGraphEdge { + key:None, + node:ChunkContentGraphNode::ExternalModuleReference( + reference, + ), + }), + None, + )); + }; + + match chunking_type { + ChunkingType::Parallel => { + let chunk_item = chunkable_module + .as_chunk_item(chunking_context) + .resolve() + .await?; + Ok(( + Some(ChunkGraphEdge { + key:Some(module), + node:ChunkContentGraphNode::ChunkItem { + item:chunk_item, + ident:module.ident().to_string().await?, + }, + }), + None, + )) + }, + ChunkingType::ParallelInheritAsync => { + let chunk_item = chunkable_module + .as_chunk_item(chunking_context) + .resolve() + .await?; + Ok(( + Some(ChunkGraphEdge { + key:Some(module), + node:ChunkContentGraphNode::ChunkItem { + item:chunk_item, + ident:module.ident().to_string().await?, + }, + }), + Some((chunk_item, InheritAsyncEdge::LocalModule)), + )) + }, + ChunkingType::Passthrough => { + let chunk_item = chunkable_module + .as_chunk_item(chunking_context) + .resolve() + .await?; + + Ok(( + Some(ChunkGraphEdge { + key:None, + node:ChunkContentGraphNode::PassthroughChunkItem { + item:chunk_item, + }, + }), + None, + )) + }, + ChunkingType::Async => { + let chunk_loading = + chunking_context.environment().chunk_loading().await?; + if matches!(*chunk_loading, ChunkLoading::Edge) { + let chunk_item = chunkable_module + .as_chunk_item(chunking_context) + .resolve() + .await?; + Ok(( + Some(ChunkGraphEdge { + key:Some(module), + node:ChunkContentGraphNode::ChunkItem { + item:chunk_item, + ident:module.ident().to_string().await?, + }, + }), + None, + )) + } else { + Ok(( + Some(ChunkGraphEdge { + key:None, + node:ChunkContentGraphNode::AsyncModule { + module:chunkable_module, + }, + }), + None, + )) + } + }, + } + } + }) + .try_join() + .await?; + + let mut graph_nodes = vec![]; + let mut inherit_async_references = vec![]; + for (n, iar) in module_data { + if let Some(n) = n { + graph_nodes.push(n); + } + if let Some(iar) = iar { + inherit_async_references.push(iar); + } + } + + if !inherit_async_references.is_empty() { + if let Some(parent) = parent { + graph_nodes.push(ChunkGraphEdge { + key:None, + node:ChunkContentGraphNode::InheritAsyncInfo { + item:parent, + references:inherit_async_references, + }, + }) + } + } + + Ok(graph_nodes) + } + }) + .try_flat_join() + .await?; + + Ok(Vc::cell(graph_nodes)) +} + +struct ChunkContentVisit { + chunking_context:Vc>, + available_chunk_items:Option>, + processed_modules:HashSet>>, +} + +type ChunkItemToGraphNodesEdges = impl Iterator; + +type ChunkItemToGraphNodesFuture = impl Future>; + +impl Visit for ChunkContentVisit { + type Edge = ChunkGraphEdge; + type EdgesFuture = ChunkItemToGraphNodesFuture; + type EdgesIntoIter = ChunkItemToGraphNodesEdges; + + fn visit(&mut self, edge:ChunkGraphEdge) -> VisitControlFlow { + let ChunkGraphEdge { key, node } = edge; + let Some(module) = key else { + if matches!(node, ChunkContentGraphNode::PassthroughChunkItem { .. }) { + return VisitControlFlow::Continue(node); + } else { + // All other types don't have edges + return VisitControlFlow::Skip(node); + } + }; + + if !self.processed_modules.insert(module) { + return VisitControlFlow::Skip(node); + } + + VisitControlFlow::Continue(node) + } + + fn edges(&mut self, node:&ChunkContentGraphNode) -> Self::EdgesFuture { + let node = node.clone(); + + let chunking_context = self.chunking_context; + let available_chunk_items = self.available_chunk_items; + + async move { + let node = match node { + ChunkContentGraphNode::PassthroughChunkItem { item } => { + ChunkGraphNodeToReferences::PassthroughChunkItem(item) + }, + ChunkContentGraphNode::ChunkItem { item, .. } => { + ChunkGraphNodeToReferences::ChunkItem(item) + }, + _ => { + return Ok(None.into_iter().flatten()); + }, + }; + + let nodes = if let Some(available_chunk_items) = available_chunk_items { + graph_node_to_referenced_nodes_with_available_chunk_items( + node, + chunking_context, + available_chunk_items, + ) + } else { + graph_node_to_referenced_nodes(node, chunking_context) + } + .await?; + Ok(Some(nodes.into_iter().cloned()).into_iter().flatten()) + } + } + + fn span(&mut self, node:&ChunkContentGraphNode) -> Span { + if let ChunkContentGraphNode::ChunkItem { ident, .. } = node { + info_span!("chunking module", name = display(ident)) + } else { + Span::current() + } + } +} + +async fn chunk_content_internal_parallel( + chunking_context:Vc>, + entries:impl IntoIterator>>, + availability_info:AvailabilityInfo, +) -> Result { + let root_edges = entries + .into_iter() + .map(|entry| { + async move { + let entry = entry.resolve().await?; + let Some(chunkable_module) = + Vc::try_resolve_downcast::>(entry).await? + else { + return Ok(None); + }; + Ok(Some(ChunkGraphEdge { + key:Some(entry), + node:ChunkContentGraphNode::ChunkItem { + item:chunkable_module.as_chunk_item(chunking_context).resolve().await?, + ident:chunkable_module.ident().to_string().await?, + }, + })) + } + }) + .try_flat_join() + .await?; + + let visit = ChunkContentVisit { + chunking_context, + available_chunk_items:availability_info.available_chunk_items(), + processed_modules:Default::default(), + }; + + let GraphTraversalResult::Completed(traversal_result) = + AdjacencyMap::new().visit(root_edges, visit).await + else { + unreachable!(); + }; + + let graph_nodes:Vec<_> = traversal_result?.into_reverse_topological().collect(); + + let mut chunk_items = IndexSet::new(); + let mut async_modules = IndexSet::new(); + let mut external_module_references = IndexSet::new(); + let mut forward_edges_inherit_async = IndexMap::new(); + let mut local_back_edges_inherit_async = IndexMap::new(); + let mut available_async_modules_back_edges_inherit_async = IndexMap::new(); + + for graph_node in graph_nodes { + match graph_node { + ChunkContentGraphNode::PassthroughChunkItem { .. } => {}, + ChunkContentGraphNode::ChunkItem { item, .. } => { + chunk_items.insert(item); + }, + ChunkContentGraphNode::AsyncModule { module } => { + let module = module.resolve().await?; + async_modules.insert(module); + }, + ChunkContentGraphNode::ExternalModuleReference(reference) => { + let reference = reference.resolve().await?; + external_module_references.insert(reference); + }, + ChunkContentGraphNode::InheritAsyncInfo { item, references } => { + for &(reference, ty) in &references { + match ty { + InheritAsyncEdge::LocalModule => { + local_back_edges_inherit_async + .entry(reference) + .or_insert_with(Vec::new) + .push(item) + }, + InheritAsyncEdge::AvailableAsyncModule => { + available_async_modules_back_edges_inherit_async + .entry(reference) + .or_insert_with(Vec::new) + .push(item) + }, + } + } + forward_edges_inherit_async + .entry(item) + .or_insert_with(Vec::new) + .extend(references.into_iter().map(|(r, _)| r)); + }, + } + } + + Ok(ChunkContentResult { + chunk_items, + async_modules, + external_module_references, + forward_edges_inherit_async, + local_back_edges_inherit_async, + available_async_modules_back_edges_inherit_async, + }) +} + +#[turbo_tasks::value_trait] +pub trait ChunkItem { + /// The [AssetIdent] of the [Module] that this [ChunkItem] was created from. + /// For most chunk types this must uniquely identify the chunk item at + /// runtime as it's the source of the module id used at runtime. + fn asset_ident(self: Vc) -> Vc; + /// A [AssetIdent] that uniquely identifies the content of this [ChunkItem]. + /// It is unusally identical to [ChunkItem::asset_ident] but can be + /// different when the chunk item content depends on available modules e. g. + /// for chunk loaders. + fn content_ident(self: Vc) -> Vc { self.asset_ident() } + /// A [ChunkItem] can describe different `references` than its original + /// [Module]. + /// TODO(alexkirsz) This should have a default impl that returns empty + /// references. + fn references(self: Vc) -> Vc; + + /// The type of chunk this item should be assembled into. + fn ty(self: Vc) -> Vc>; + + /// A temporary method to retrieve the module associated with this + /// ChunkItem. TODO: Remove this as part of the chunk refactoring. + fn module(self: Vc) -> Vc>; + + fn chunking_context(self: Vc) -> Vc>; + + fn is_self_async(self: Vc) -> Vc { Vc::cell(false) } +} + +#[turbo_tasks::value_trait] +pub trait ChunkType: ValueToString { + /// Create a new chunk for the given chunk items + fn chunk( + &self, + chunking_context:Vc>, + chunk_items:Vec, + referenced_output_assets:Vc, + ) -> Vc>; + + fn chunk_item_size( + &self, + chunking_context:Vc>, + chunk_item:Vc>, + async_module_info:Option>, + ) -> Vc; +} + +#[turbo_tasks::value(transparent)] +pub struct ChunkItems(Vec>>); + +#[turbo_tasks::value] +pub struct AsyncModuleInfo { + pub referenced_async_modules:AutoSet>>, +} + +#[turbo_tasks::value_impl] +impl AsyncModuleInfo { + #[turbo_tasks::function] + pub fn new(referenced_async_modules:Vec>>) -> Vc { + Self { referenced_async_modules:referenced_async_modules.into_iter().collect() }.cell() + } +} + +pub type ChunkItemWithAsyncModuleInfo = (Vc>, Option>); + +#[turbo_tasks::value(transparent)] +pub struct ChunkItemsWithAsyncModuleInfo(Vec); + +pub trait ChunkItemExt: Send { + /// Returns the module id of this chunk item. + fn id(self: Vc) -> Vc; +} + +impl ChunkItemExt for T +where + T: Upcast>, +{ + /// Returns the module id of this chunk item. + fn id(self: Vc) -> Vc { + let chunk_item = Vc::upcast(self); + chunk_item.chunking_context().chunk_item_id(chunk_item) + } +} diff --git a/crates/turbopack-core/Source/chunk/optimize.rs b/crates/turbopack-core/Source/chunk/optimize.rs new file mode 100644 index 0000000000000..e8d234d2f6640 --- /dev/null +++ b/crates/turbopack-core/Source/chunk/optimize.rs @@ -0,0 +1,70 @@ +//! Traits and functions to optimize a list of chunks. +//! +//! Usually chunks are optimized by limiting their total count, restricting +//! their size and eliminating duplicates between them. + +use anyhow::Result; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbo_tasks_fs::{FileSystemPath, FileSystemPathOption}; + +use crate::chunk::containment_tree::{ContainmentTree, ContainmentTreeKey}; + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +struct FileSystemPathKey(Vc); + +impl FileSystemPathKey { + async fn new(path:Vc) -> Result { Ok(Self(path.resolve().await?)) } +} + +#[async_trait::async_trait] +impl ContainmentTreeKey for FileSystemPathKey { + async fn parent(&self) -> Result { Ok(FileSystemPathKey::new(self.0.parent()).await?) } +} + +pub async fn optimize_by_common_parent( + chunks:&[T], + get_common_parent:GetCommonParent, + optimize:Optimize, +) -> Result +where + T: Clone, + GetCommonParent: Fn(T) -> Vc + Clone, + Optimize: Fn(Option>, Vec) -> Acc, { + let tree = ContainmentTree::build( + chunks + .iter() + .map(move |chunk| { + let get_common_parent = get_common_parent.clone(); + async move { + let common_parent = get_common_parent(chunk.clone()).await?; + + Ok(( + if let Some(common_parent) = &*common_parent { + Some(FileSystemPathKey::new(*common_parent).await?) + } else { + None + }, + chunk.clone(), + )) + } + }) + .try_join() + .await?, + ) + .await?; + + fn optimize_tree( + tree:ContainmentTree, + optimize:&impl Fn(Option>, Vec) -> Acc, + ) -> Acc { + let children = tree + .children + .into_iter() + .map(|tree| optimize_tree(tree, optimize)) + .collect::>(); + + optimize(tree.values, children) + } + + Ok(optimize_tree(tree, &optimize)) +} diff --git a/crates/turbopack-core/Source/code_builder.rs b/crates/turbopack-core/Source/code_builder.rs new file mode 100644 index 0000000000000..41af99e01520b --- /dev/null +++ b/crates/turbopack-core/Source/code_builder.rs @@ -0,0 +1,180 @@ +use std::{ + cmp::min, + io::{BufRead, Result as IoResult, Write}, + ops, +}; + +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::rope::{Rope, RopeBuilder}; +use turbo_tasks_hash::hash_xxh3_hash64; + +use crate::{ + source_map::{GenerateSourceMap, OptionSourceMap, SourceMap, SourceMapSection}, + source_pos::SourcePos, +}; + +/// A mapping of byte-offset in the code string to an associated source map. +pub type Mapping = (usize, Option>>); + +/// Code stores combined output code and the source map of that output code. +#[turbo_tasks::value(shared)] +#[derive(Debug, Clone)] +pub struct Code { + code:Rope, + + mappings:Vec, +} + +/// CodeBuilder provides a mutable container to append source code. +#[derive(Default)] +pub struct CodeBuilder { + code:RopeBuilder, + + mappings:Vec, +} + +impl Code { + pub fn source_code(&self) -> &Rope { &self.code } + + /// Tests if any code in this Code contains an associated source map. + pub fn has_source_map(&self) -> bool { !self.mappings.is_empty() } +} + +impl CodeBuilder { + /// Pushes synthetic runtime code without an associated source map. This is + /// the default concatenation operation, but it's designed to be used + /// with the `+=` operator. + fn push_static_bytes(&mut self, code:&'static [u8]) { + self.push_map(None); + self.code.push_static_bytes(code); + } + + /// Pushes original user code with an optional source map if one is + /// available. If it's not, this is no different than pushing Synthetic + /// code. + pub fn push_source(&mut self, code:&Rope, map:Option>>) { + self.push_map(map); + self.code += code; + } + + /// Copies the Synthetic/Original code of an already constructed Code into + /// this instance. + pub fn push_code(&mut self, prebuilt:&Code) { + if let Some((index, _)) = prebuilt.mappings.first() { + if *index > 0 { + // If the index is positive, then the code starts with a synthetic section. We + // may need to push an empty map in order to end the current + // section's mappings. + self.push_map(None); + } + + let len = self.code.len(); + self.mappings + .extend(prebuilt.mappings.iter().map(|(index, map)| (index + len, *map))); + } else { + self.push_map(None); + } + + self.code += &prebuilt.code; + } + + /// Setting breakpoints on synthetic code can cause weird behaviors + /// because Chrome will treat the location as belonging to the previous + /// original code section. By inserting an empty source map when reaching a + /// synthetic section directly after an original section, we tell Chrome + /// that the previous map ended at this point. + fn push_map(&mut self, map:Option>>) { + if map.is_none() && matches!(self.mappings.last(), None | Some((_, None))) { + // No reason to push an empty map directly after an empty map + return; + } + + debug_assert!( + map.is_some() || !self.mappings.is_empty(), + "the first mapping is never a None" + ); + self.mappings.push((self.code.len(), map)); + } + + /// Tests if any code in this CodeBuilder contains an associated source map. + pub fn has_source_map(&self) -> bool { !self.mappings.is_empty() } + + pub fn build(self) -> Code { Code { code:self.code.build(), mappings:self.mappings } } +} + +impl ops::AddAssign<&'static str> for CodeBuilder { + fn add_assign(&mut self, rhs:&'static str) { self.push_static_bytes(rhs.as_bytes()); } +} + +impl ops::AddAssign<&'static str> for &mut CodeBuilder { + fn add_assign(&mut self, rhs:&'static str) { self.push_static_bytes(rhs.as_bytes()); } +} + +impl Write for CodeBuilder { + fn write(&mut self, bytes:&[u8]) -> IoResult { + self.push_map(None); + self.code.write(bytes) + } + + fn flush(&mut self) -> IoResult<()> { self.code.flush() } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for Code { + /// Generates the source map out of all the pushed Original code. + /// The SourceMap v3 spec has a "sectioned" source map specifically designed + /// for concatenation in post-processing steps. This format consists of + /// a `sections` array, with section item containing a `offset` object + /// and a `map` object. The section's map applies only after the + /// starting offset, and until the start of the next section. This is by + /// far the simplest way to concatenate the source maps of the multiple + /// chunk items into a single map file. + #[turbo_tasks::function] + pub async fn generate_source_map(&self) -> Result> { + let mut pos = SourcePos::new(); + let mut last_byte_pos = 0; + + let mut sections = Vec::with_capacity(self.mappings.len()); + let mut read = self.code.read(); + for (byte_pos, map) in &self.mappings { + let mut want = byte_pos - last_byte_pos; + while want > 0 { + let buf = read.fill_buf()?; + debug_assert!(!buf.is_empty()); + + let end = min(want, buf.len()); + pos.update(&buf[0..end]); + + read.consume(end); + want -= end; + } + last_byte_pos = *byte_pos; + + let encoded = match map { + None => SourceMap::empty(), + Some(map) => { + match *map.generate_source_map().await? { + None => SourceMap::empty(), + Some(map) => map, + } + }, + }; + + sections.push(SourceMapSection::new(pos, encoded)) + } + + Ok(Vc::cell(Some(SourceMap::new_sectioned(sections).cell()))) + } +} + +#[turbo_tasks::value_impl] +impl Code { + /// Returns the hash of the source code of this Code. + #[turbo_tasks::function] + pub async fn source_code_hash(self: Vc) -> Result> { + let code = self.await?; + let hash = hash_xxh3_hash64(code.source_code()); + Ok(Vc::cell(hash)) + } +} diff --git a/crates/turbopack-core/Source/compile_time_info.rs b/crates/turbopack-core/Source/compile_time_info.rs new file mode 100644 index 0000000000000..c0ba62004370e --- /dev/null +++ b/crates/turbopack-core/Source/compile_time_info.rs @@ -0,0 +1,214 @@ +use anyhow::Result; +use indexmap::IndexMap; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::FileSystemPath; + +use crate::environment::Environment; + +// TODO stringify split map collect could be optimized with a marco +#[macro_export] +macro_rules! definable_name_map_internal { + ($map:ident, .. $value:expr) => { + for (key, value) in $value { + $map.insert( + key.into(), + value.into() + ); + } + }; + ($map:ident, $($name:ident).+ = $value:expr) => { + $map.insert( + $crate::definable_name_map_internal!($($name).+).into(), + $value.into() + ); + }; + ($map:ident, $($name:ident).+ = $value:expr,) => { + $map.insert( + $crate::definable_name_map_internal!($($name).+).into(), + $value.into() + ); + }; + ($map:ident, $($name:ident).+ = $value:expr, $($more:tt)+) => { + $crate::definable_name_map_internal!($map, $($name).+ = $value); + $crate::definable_name_map_internal!($map, $($more)+); + }; + ($map:ident, .. $value:expr, $($more:tt)+) => { + $crate::definable_name_map_internal!($map, .. $value); + $crate::definable_name_map_internal!($map, $($more)+); + }; + ($name:ident) => { + [stringify!($name).into()] + }; + ($name:ident . $($more:ident).+) => { + $crate::definable_name_map_internal!($($more).+, [stringify!($name).into()]) + }; + ($name:ident, [$($array:expr),+]) => { + [$($array),+, stringify!($name).into()] + }; + ($name:ident . $($more:ident).+, [$($array:expr),+]) => { + $crate::definable_name_map_internal!($($more).+, [$($array),+, stringify!($name).into()]) + }; +} + +#[macro_export] +macro_rules! compile_time_defines { + ($($more:tt)+) => { + { + let mut map = $crate::__private::IndexMap::new(); + $crate::definable_name_map_internal!(map, $($more)+); + $crate::compile_time_info::CompileTimeDefines(map) + } + }; +} + +#[macro_export] +macro_rules! free_var_references { + ($($more:tt)+) => { + { + let mut map = $crate::__private::IndexMap::new(); + $crate::definable_name_map_internal!(map, $($more)+); + $crate::compile_time_info::FreeVarReferences(map) + } + }; +} + +// TODO: replace with just a `serde_json::Value` +// https://linear.app/vercel/issue/WEB-1641/compiletimedefinevalue-should-just-use-serde-jsonvalue +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(Debug, Clone, Hash, PartialOrd, Ord)] +pub enum CompileTimeDefineValue { + Bool(bool), + String(RcStr), + JSON(RcStr), +} + +impl From for CompileTimeDefineValue { + fn from(value:bool) -> Self { Self::Bool(value) } +} + +impl From for CompileTimeDefineValue { + fn from(value:RcStr) -> Self { Self::String(value) } +} + +impl From for CompileTimeDefineValue { + fn from(value:String) -> Self { Self::String(value.into()) } +} + +impl From<&str> for CompileTimeDefineValue { + fn from(value:&str) -> Self { Self::String(value.into()) } +} + +impl From for CompileTimeDefineValue { + fn from(value:serde_json::Value) -> Self { Self::JSON(value.to_string().into()) } +} + +#[turbo_tasks::value(transparent)] +#[derive(Debug, Clone)] +pub struct CompileTimeDefines(pub IndexMap, CompileTimeDefineValue>); + +impl IntoIterator for CompileTimeDefines { + type IntoIter = indexmap::map::IntoIter, CompileTimeDefineValue>; + type Item = (Vec, CompileTimeDefineValue); + + fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } +} + +#[turbo_tasks::value_impl] +impl CompileTimeDefines { + #[turbo_tasks::function] + pub fn empty() -> Vc { Vc::cell(IndexMap::new()) } +} + +#[turbo_tasks::value] +#[derive(Debug, Clone)] +pub enum FreeVarReference { + EcmaScriptModule { request:RcStr, lookup_path:Option>, export:Option }, + Value(CompileTimeDefineValue), + Error(RcStr), +} + +impl From for FreeVarReference { + fn from(value:bool) -> Self { Self::Value(value.into()) } +} + +impl From for FreeVarReference { + fn from(value:String) -> Self { Self::Value(value.into()) } +} + +impl From<&str> for FreeVarReference { + fn from(value:&str) -> Self { Self::Value(value.into()) } +} + +impl From for FreeVarReference { + fn from(value:CompileTimeDefineValue) -> Self { Self::Value(value) } +} + +#[turbo_tasks::value(transparent)] +#[derive(Debug, Clone)] +pub struct FreeVarReferences(pub IndexMap, FreeVarReference>); + +#[turbo_tasks::value_impl] +impl FreeVarReferences { + #[turbo_tasks::function] + pub fn empty() -> Vc { Vc::cell(IndexMap::new()) } +} + +#[turbo_tasks::value(shared)] +#[derive(Debug, Clone)] +pub struct CompileTimeInfo { + pub environment:Vc, + pub defines:Vc, + pub free_var_references:Vc, +} + +impl CompileTimeInfo { + pub fn builder(environment:Vc) -> CompileTimeInfoBuilder { + CompileTimeInfoBuilder { environment, defines:None, free_var_references:None } + } +} + +#[turbo_tasks::value_impl] +impl CompileTimeInfo { + #[turbo_tasks::function] + pub fn new(environment:Vc) -> Vc { + CompileTimeInfo { + environment, + defines:CompileTimeDefines::empty(), + free_var_references:FreeVarReferences::empty(), + } + .cell() + } + + #[turbo_tasks::function] + pub async fn environment(self: Vc) -> Result> { + Ok(self.await?.environment) + } +} + +pub struct CompileTimeInfoBuilder { + environment:Vc, + defines:Option>, + free_var_references:Option>, +} + +impl CompileTimeInfoBuilder { + pub fn defines(mut self, defines:Vc) -> Self { + self.defines = Some(defines); + self + } + + pub fn free_var_references(mut self, free_var_references:Vc) -> Self { + self.free_var_references = Some(free_var_references); + self + } + + pub fn build(self) -> CompileTimeInfo { + CompileTimeInfo { + environment:self.environment, + defines:self.defines.unwrap_or_else(CompileTimeDefines::empty), + free_var_references:self.free_var_references.unwrap_or_else(FreeVarReferences::empty), + } + } + + pub fn cell(self) -> Vc { self.build().cell() } +} diff --git a/crates/turbopack-core/Source/condition.rs b/crates/turbopack-core/Source/condition.rs new file mode 100644 index 0000000000000..a323fe5923431 --- /dev/null +++ b/crates/turbopack-core/Source/condition.rs @@ -0,0 +1,64 @@ +use anyhow::Result; +use async_recursion::async_recursion; +use futures::{StreamExt, stream}; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{Vc, trace::TraceRawVcs}; +use turbo_tasks_fs::FileSystemPath; + +#[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq)] +pub enum ContextCondition { + All(Vec), + Any(Vec), + Not(Box), + InDirectory(String), + InPath(Vc), +} + +impl ContextCondition { + /// Creates a condition that matches if all of the given conditions match. + pub fn all(conditions:Vec) -> ContextCondition { + ContextCondition::All(conditions) + } + + /// Creates a condition that matches if any of the given conditions match. + pub fn any(conditions:Vec) -> ContextCondition { + ContextCondition::Any(conditions) + } + + /// Creates a condition that matches if the given condition does not match. + #[allow(clippy::should_implement_trait)] + pub fn not(condition:ContextCondition) -> ContextCondition { + ContextCondition::Not(Box::new(condition)) + } + + #[async_recursion] + /// Returns true if the condition matches the context. + pub async fn matches(&self, path:&FileSystemPath) -> Result { + match self { + ContextCondition::All(conditions) => { + // False positive. + #[allow(clippy::manual_try_fold)] + stream::iter(conditions) + .fold(Ok(true), |acc, c| async move { Ok(acc? && c.matches(path).await?) }) + .await + }, + ContextCondition::Any(conditions) => { + // False positive. + #[allow(clippy::manual_try_fold)] + stream::iter(conditions) + .fold(Ok(false), |acc, c| async move { Ok(acc? || c.matches(path).await?) }) + .await + }, + ContextCondition::Not(condition) => condition.matches(path).await.map(|b| !b), + ContextCondition::InPath(other_path) => { + Ok(path.is_inside_or_equal_ref(&*other_path.await?)) + }, + ContextCondition::InDirectory(dir) => { + Ok(path.path.starts_with(&format!("{dir}/")) + || path.path.contains(&format!("/{dir}/")) + || path.path.ends_with(&format!("/{dir}")) + || path.path == *dir) + }, + } + } +} diff --git a/crates/turbopack-core/Source/context.rs b/crates/turbopack-core/Source/context.rs new file mode 100644 index 0000000000000..cb13b9ce852be --- /dev/null +++ b/crates/turbopack-core/Source/context.rs @@ -0,0 +1,81 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_fs::{FileSystemPath, glob::Glob}; + +use crate::{ + compile_time_info::CompileTimeInfo, + module::Module, + reference_type::ReferenceType, + resolve::{ModuleResolveResult, ResolveResult, options::ResolveOptions, parse::Request}, + source::Source, +}; + +#[turbo_tasks::value(shared)] +pub enum ProcessResult { + /// A module was created. + Module(Vc>), + + /// Reference is ignored. This should lead to no module being included by + /// the reference. + Ignore, +} + +#[turbo_tasks::value_impl] +impl ProcessResult { + #[turbo_tasks::function] + pub async fn module(&self) -> Result>> { + match *self { + ProcessResult::Module(m) => Ok(m), + ProcessResult::Ignore => { + bail!("Expected process result to be a module, but it was ignored") + }, + } + } +} + +/// A context for building an asset graph. It's passed through the assets while +/// creating them. It's needed to resolve assets and upgrade assets to a higher +/// type (e. g. from FileSource to ModuleAsset). +#[turbo_tasks::value_trait] +pub trait AssetContext { + /// Gets the compile time info of the asset context. + fn compile_time_info(self: Vc) -> Vc; + + /// Gets the layer of the asset context. + fn layer(self: Vc) -> Vc; + + /// Gets the resolve options for a given path. + fn resolve_options( + self: Vc, + origin_path:Vc, + reference_type:Value, + ) -> Vc; + + /// Resolves an request to an [ModuleResolveResult]. + fn resolve_asset( + self: Vc, + origin_path:Vc, + request:Vc, + resolve_options:Vc, + reference_type:Value, + ) -> Vc; + + /// Process a source into a module. + fn process( + self: Vc, + asset:Vc>, + reference_type:Value, + ) -> Vc; + + /// Process an [ResolveResult] into an [ModuleResolveResult]. + fn process_resolve_result( + self: Vc, + result:Vc, + reference_type:Value, + ) -> Vc; + + /// Gets a new AssetContext with the transition applied. + fn with_transition(self: Vc, transition:RcStr) -> Vc>; + + fn side_effect_free_packages(self: Vc) -> Vc; +} diff --git a/crates/turbopack-core/Source/diagnostics/mod.rs b/crates/turbopack-core/Source/diagnostics/mod.rs new file mode 100644 index 0000000000000..684cd14ed171a --- /dev/null +++ b/crates/turbopack-core/Source/diagnostics/mod.rs @@ -0,0 +1,81 @@ +use std::collections::HashMap; + +use anyhow::Result; +use async_trait::async_trait; +use turbo_tasks::{CollectiblesSource, RcStr, Upcast, Vc, emit}; + +#[turbo_tasks::value(serialization = "none")] +#[derive(Clone, Debug)] +pub struct PlainDiagnostic { + pub category:RcStr, + pub name:RcStr, + pub payload:HashMap, +} + +#[turbo_tasks::value(transparent)] +pub struct DiagnosticPayload(pub HashMap); + +/// An arbitrary payload can be used to analyze, diagnose +/// Turbopack's behavior. +#[turbo_tasks::value_trait] +pub trait Diagnostic { + /// [NOTE]: Psuedo-reserved; this is not being used currently. + /// The `type` of the diagnostics that can be used selectively filtered by + /// consumers. For example, this could be `telemetry`, or + /// `slow_perf_event`, or something else. This is not strongly typed + /// though; since consumer or implementation may need to define own + /// category. + fn category(&self) -> Vc; + /// Name of the specific diagnostic event. + fn name(&self) -> Vc; + /// Arbitarary payload included in the diagnostic event. + fn payload(&self) -> Vc; + + async fn into_plain(self: Vc) -> Result> { + Ok(PlainDiagnostic { + category:self.category().await?.clone_value(), + name:self.name().await?.clone_value(), + payload:self.payload().await?.clone_value(), + } + .cell()) + } +} + +pub trait DiagnosticExt { + fn emit(self); +} + +impl DiagnosticExt for Vc +where + T: Upcast>, +{ + fn emit(self) { + let diagnostic = Vc::upcast::>(self); + emit(diagnostic); + } +} + +#[async_trait] +pub trait DiagnosticContextExt +where + Self: Sized, { + async fn peek_diagnostics(self) -> Result; +} + +#[async_trait] +impl DiagnosticContextExt for T +where + T: CollectiblesSource + Copy + Send, +{ + async fn peek_diagnostics(self) -> Result { + Ok(CapturedDiagnostics { diagnostics:self.peek_collectibles() }) + } +} + +/// A list of diagnostics captured with +/// [`DiagnosticsVc::peek_diagnostics_with_path`] and +#[derive(Debug)] +#[turbo_tasks::value] +pub struct CapturedDiagnostics { + pub diagnostics:auto_hash_map::AutoSet>>, +} diff --git a/crates/turbopack-core/Source/environment.rs b/crates/turbopack-core/Source/environment.rs new file mode 100644 index 0000000000000..ddb6c90636193 --- /dev/null +++ b/crates/turbopack-core/Source/environment.rs @@ -0,0 +1,316 @@ +use std::{ + process::{Command, Stdio}, + str::FromStr, +}; + +use anyhow::{Context, Result, anyhow}; +use swc_core::ecma::preset_env::{Version, Versions}; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_env::ProcessEnv; + +use crate::target::CompileTarget; + +static DEFAULT_NODEJS_VERSION:&str = "16.0.0"; + +#[turbo_tasks::value] +#[derive(Default)] +pub enum Rendering { + #[default] + None, + Client, + Server, +} + +impl Rendering { + pub fn is_none(&self) -> bool { matches!(self, Rendering::None) } +} + +#[turbo_tasks::value] +pub enum ChunkLoading { + Edge, + /// CommonJS in Node.js + NodeJs, + /// + +`; + +async function createServer() { + const app = express(); + const vite = await createViteServer({ + server: { middlewareMode: true }, + appType: "custom", + }); + app.use(vite.middlewares); + app.use("*", async (req, res, next) => { + const url = req.originalUrl; + try { + const template = await vite.transformIndexHtml(url, TEMPLATE); + const { render } = await vite.ssrLoadModule("/src/vite-entry-server.jsx"); + const appHtml = await render(url); + const html = template.replace(``, appHtml); + res.status(200).set({ "Content-Type": "text/html" }).end(html); + } catch (e) { + vite.ssrFixStacktrace(e); + next(e); + } + }); + + const listener = app.listen(0, () => { + console.log(`Local: http://localhost:${listener.address().port}`); + }); +} + +createServer(); diff --git a/crates/turbopack-create-test-app/Source/test_app_builder.rs b/crates/turbopack-create-test-app/Source/test_app_builder.rs new file mode 100644 index 0000000000000..448e20049aadb --- /dev/null +++ b/crates/turbopack-create-test-app/Source/test_app_builder.rs @@ -0,0 +1,542 @@ +use std::{ + collections::VecDeque, + fs::{File, create_dir_all}, + io::prelude::*, + path::{Path, PathBuf}, + str::FromStr, +}; + +use anyhow::{Context, Result, anyhow}; +use indoc::{formatdoc, indoc}; +use serde_json::json; +use tempfile::TempDir; + +fn decide(remaining:usize, min_remaining_decisions:usize) -> bool { + if remaining == 0 { + false + } else if min_remaining_decisions <= remaining { + true + } else { + let urgentness = min_remaining_decisions / remaining; + (min_remaining_decisions * 11 * 7 * 5) % urgentness == 0 + } +} + +fn decide_early(remaining:usize, min_remaining_decisions:usize) -> bool { + if remaining == 0 { + false + } else if min_remaining_decisions <= remaining { + true + } else { + let urgentness = min_remaining_decisions / remaining / remaining; + (min_remaining_decisions * 11 * 7 * 5) % urgentness == 0 + } +} + +fn write_file>(name:&str, path:P, content:&[u8]) -> Result<()> { + File::create(path) + .with_context(|| format!("creating {name}"))? + .write_all(content) + .with_context(|| format!("writing {name}")) +} + +/// How to run effects in components. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub enum EffectMode { + /// No effects at all. + #[default] + None, + /// As a direct `useEffect` hook in the component's body. + Hook, + /// Rendering an client-side component that has the `useEffect` + /// hook instead. Good for testing React Server Components, as they can't + /// use `useEffect` hooks directly. + Component, +} + +impl FromStr for EffectMode { + type Err = anyhow::Error; + + fn from_str(s:&str) -> Result { + match s { + "none" => Ok(EffectMode::None), + "hook" => Ok(EffectMode::Hook), + "component" => Ok(EffectMode::Component), + _ => Err(anyhow!("unknown effect mode: {}", s)), + } + } +} + +#[derive(Debug)] +pub struct TestAppBuilder { + pub target:Option, + pub module_count:usize, + pub directories_count:usize, + pub dynamic_import_count:usize, + pub flatness:usize, + pub package_json:Option, + pub effect_mode:EffectMode, + pub leaf_client_components:bool, +} + +impl Default for TestAppBuilder { + fn default() -> Self { + Self { + target:None, + module_count:1000, + directories_count:50, + dynamic_import_count:0, + flatness:5, + package_json:Some(Default::default()), + effect_mode:EffectMode::Hook, + leaf_client_components:false, + } + } +} + +const SETUP_IMPORTS:&str = indoc! {r#" +import React from "react"; +"#}; +const SETUP_EFFECT_PROPS:&str = indoc! {r#" +let EFFECT_PROPS = {}; +"#}; +const SETUP_EVAL:&str = indoc! {r#" +/* @turbopack-bench:eval-start */ +/* @turbopack-bench:eval-end */ +"#}; +const USE_EFFECT:&str = indoc! {r#" +React.useEffect(() => { + if (EFFECT_PROPS.hydration) { + globalThis.__turbopackBenchBinding && globalThis.__turbopackBenchBinding("Hydration done"); + } + if (EFFECT_PROPS.message) { + globalThis.__turbopackBenchBinding && globalThis.__turbopackBenchBinding(EFFECT_PROPS.message); + } +}, [EFFECT_PROPS]); +"#}; +const EFFECT_ELEMENT:&str = indoc! {r#" + +"#}; + +impl TestAppBuilder { + pub fn build(&self) -> Result { + let target = if let Some(target) = self.target.clone() { + TestAppTarget::Set(target) + } else { + TestAppTarget::Temp(tempfile::tempdir().context("creating tempdir")?) + }; + let path = target.path(); + let mut modules = vec![]; + let src = path.join("src"); + create_dir_all(&src).context("creating src dir")?; + + let mut remaining_modules = self.module_count - 1; + let mut remaining_directories = self.directories_count; + let mut remaining_dynamic_imports = self.dynamic_import_count; + + let mut queue = VecDeque::with_capacity(32); + queue.push_back((src.join("triangle.jsx"), 0)); + remaining_modules -= 1; + let mut is_root = true; + + let (additional_body, additional_elements) = match self.effect_mode { + EffectMode::None => ("", ""), + EffectMode::Component => ("", EFFECT_ELEMENT), + EffectMode::Hook => (USE_EFFECT, ""), + }; + + while let Some((file, depth)) = queue.pop_front() { + modules.push((file.clone(), depth)); + + let setup_imports = match self.effect_mode { + EffectMode::Hook | EffectMode::None => SETUP_IMPORTS.to_string(), + EffectMode::Component => { + let relative_effect = if src == file.parent().unwrap() { + "./effect.jsx".to_string() + } else { + pathdiff::diff_paths(src.join("effect.jsx"), file.parent().unwrap()) + .unwrap() + .display() + .to_string() + }; + + #[cfg(windows)] + let relative_effect = relative_effect.replace('\\', "/"); + + formatdoc! {r#" + {SETUP_IMPORTS} + import Effect from "{relative_effect}"; + "#} + }, + }; + + let leaf = remaining_modules == 0 + || (!queue.is_empty() + && (queue.len() + remaining_modules) % (self.flatness + 1) == 0); + if leaf { + let maybe_use_client = + if self.leaf_client_components { r#""use client";"# } else { "" }; + write_file( + &format!("leaf file {}", file.display()), + &file, + formatdoc! {r#" + {maybe_use_client} + + {setup_imports} + + {SETUP_EFFECT_PROPS} + {SETUP_EVAL} + + function Triangle({{ style }}) {{ + {additional_body} + return <> + + {additional_elements} + ; + }} + + export default React.memo(Triangle); + "#} + .as_bytes(), + )?; + } else { + let in_subdirectory = decide(remaining_directories, remaining_modules / 3); + + let import_path; + let base_file = file.with_extension(""); + let base_file = if in_subdirectory { + remaining_directories -= 1; + create_dir_all(&base_file).context("creating subdirectory")?; + import_path = + format!("./{}/triangle_", base_file.file_name().unwrap().to_str().unwrap()); + base_file.join("triangle") + } else { + import_path = + format!("./{}_", base_file.file_name().unwrap().to_str().unwrap()); + base_file + }; + + for i in 1..=3 { + let mut f = base_file.clone(); + f.set_file_name(format!( + "{}_{}.jsx", + f.file_name().unwrap().to_str().unwrap(), + i + )); + queue.push_back((f, depth + 1)); + } + remaining_modules = remaining_modules.saturating_sub(3); + + if let [(a, a_), (b, b_), (c, c_)] = &*[("A", "1"), ("B", "2"), ("C", "3")] + .into_iter() + .enumerate() + .map(|(i, (name, n))| { + if decide_early(remaining_dynamic_imports, remaining_modules + (2 - i)) { + remaining_dynamic_imports -= 1; + ( + format!( + "const {name}Lazy = React.lazy(() => \ + import('{import_path}{n}'));" + ), + format!( + "<{name}Lazy style={{style}} \ + />" + ), + ) + } else { + ( + format!("import {name} from '{import_path}{n}'"), + format!("<{name} style={{style}} />"), + ) + } + }) + .collect::>() + { + let setup_hydration = if is_root { + is_root = false; + "\nEFFECT_PROPS.hydration = true;" + } else { + "" + }; + write_file( + &format!("file with children {}", file.display()), + &file, + formatdoc! {r#" + {setup_imports} + {a} + {b} + {c} + + {SETUP_EFFECT_PROPS}{setup_hydration} + {SETUP_EVAL} + + function Container({{ style }}) {{ + {additional_body} + return <> + + {a_} + + + {b_} + + + {c_} + + {additional_elements} + ; + }} + + export default React.memo(Container); + "#} + .as_bytes(), + )?; + } else { + unreachable!() + } + } + } + + let bootstrap = indoc! {r#" + import React from "react"; + import { createRoot } from "react-dom/client"; + import Triangle from "./triangle.jsx"; + + function App() { + return + + + } + + document.body.style.backgroundColor = "black"; + let root = document.createElement("main"); + document.body.appendChild(root); + createRoot(root).render(); + "#}; + write_file("bootstrap file", src.join("index.jsx"), bootstrap.as_bytes())?; + + let pages = src.join("pages"); + create_dir_all(&pages)?; + + // The page is e. g. used by Next.js + let bootstrap_page = indoc! {r#" + import React from "react"; + import Triangle from "../triangle.jsx"; + + export default function Page() { + return + + + } + "#}; + write_file("bootstrap page", pages.join("page.jsx"), bootstrap_page.as_bytes())?; + + // The page is e. g. used by Next.js + let bootstrap_static_page = indoc! {r#" + import React from "react"; + import Triangle from "../triangle.jsx"; + + export default function Page() { + return + + + } + + export function getStaticProps() { + return { + props: {} + }; + } + "#}; + write_file( + "bootstrap static page", + pages.join("static.jsx"), + bootstrap_static_page.as_bytes(), + )?; + + let app_dir = src.join("app"); + create_dir_all(app_dir.join("app"))?; + create_dir_all(app_dir.join("client"))?; + + // The page is e. g. used by Next.js + let bootstrap_app_page = indoc! {r#" + import React from "react"; + import Triangle from "../../triangle.jsx"; + + export default function Page() { + return + + + } + "#}; + write_file( + "bootstrap app page", + app_dir.join("app/page.jsx"), + bootstrap_app_page.as_bytes(), + )?; + + if matches!(self.effect_mode, EffectMode::Component) { + // The component is used to measure hydration and commit time for app/page.jsx + let effect_component = formatdoc! {r#" + "use client"; + + import React from "react"; + + export default function Effect(EFFECT_PROPS) {{ + {USE_EFFECT} + return null; + }} + "#}; + write_file("effect component", src.join("effect.jsx"), effect_component.as_bytes())?; + } + + // The page is e. g. used by Next.js + let bootstrap_app_client_page = indoc! {r#" + "use client"; + import React from "react"; + import Triangle from "../../triangle.jsx"; + + export default function Page() { + return + + + } + "#}; + write_file( + "bootstrap app client page", + app_dir.join("client/page.jsx"), + bootstrap_app_client_page.as_bytes(), + )?; + + // This root layout is e. g. used by Next.js + let bootstrap_layout = indoc! {r#" + export default function RootLayout({ children }) { + return ( + + + + + Turbopack Test App + + + {children} + + + ); + } + "#}; + write_file("bootstrap layout", app_dir.join("layout.jsx"), bootstrap_layout.as_bytes())?; + + // This HTML is used e. g. by Vite + let bootstrap_html = indoc! {r#" + + + + + + Turbopack Test App + + + + + + "#}; + write_file("bootstrap html in root", path.join("index.html"), bootstrap_html.as_bytes())?; + + // This HTML is used e. g. by webpack + let bootstrap_html2 = indoc! {r#" + + + + + + Turbopack Test App + + + + + + "#}; + + let public = path.join("public"); + create_dir_all(&public).context("creating public dir")?; + + write_file("bootstrap html", public.join("index.html"), bootstrap_html2.as_bytes())?; + + write_file( + "vite node.js server", + path.join("vite-server.mjs"), + include_bytes!("templates/vite-server.mjs"), + )?; + write_file( + "vite server entry", + path.join("src/vite-entry-server.jsx"), + include_bytes!("templates/vite-entry-server.jsx"), + )?; + write_file( + "vite client entry", + path.join("src/vite-entry-client.jsx"), + include_bytes!("templates/vite-entry-client.jsx"), + )?; + + if let Some(package_json) = &self.package_json { + // These dependencies are needed + let package_json = json!({ + "name": "turbopack-test-app", + "private": true, + "version": "0.0.0", + "dependencies": { + "react": package_json.react_version.clone(), + "react-dom": package_json.react_version.clone(), + } + }); + write_file( + "package.json", + path.join("package.json"), + format!("{:#}", package_json).as_bytes(), + )?; + } + + Ok(TestApp { target, modules }) + } +} + +/// Configuration struct to generate the `package.json` file of the test app. +#[derive(Debug)] +pub struct PackageJsonConfig { + /// The version of React to use. + pub react_version:String, +} + +impl Default for PackageJsonConfig { + fn default() -> Self { Self { react_version:"^18.2.0".to_string() } } +} + +#[derive(Debug)] +enum TestAppTarget { + Set(PathBuf), + Temp(TempDir), +} + +impl TestAppTarget { + /// Returns the path to the directory containing the app. + fn path(&self) -> &Path { + match &self { + TestAppTarget::Set(target) => target.as_path(), + TestAppTarget::Temp(target) => target.path(), + } + } +} + +#[derive(Debug)] +pub struct TestApp { + target:TestAppTarget, + modules:Vec<(PathBuf, usize)>, +} + +impl TestApp { + /// Returns the path to the directory containing the app. + pub fn path(&self) -> &Path { self.target.path() } + + /// Returns the list of modules and their depth in this app. + pub fn modules(&self) -> &[(PathBuf, usize)] { &self.modules } +} diff --git a/crates/turbopack-css/Source/asset.rs b/crates/turbopack-css/Source/asset.rs new file mode 100644 index 0000000000000..f08a9c6a275a5 --- /dev/null +++ b/crates/turbopack-css/Source/asset.rs @@ -0,0 +1,277 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, TryJoinIterExt, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext}, + context::AssetContext, + ident::AssetIdent, + module::Module, + reference::{ModuleReference, ModuleReferences}, + reference_type::ImportContext, + resolve::origin::ResolveOrigin, + source::Source, +}; + +use crate::{ + CssModuleAssetType, + chunk::{CssChunkItem, CssChunkItemContent, CssChunkPlaceable, CssChunkType, CssImport}, + code_gen::CodeGenerateable, + process::{ + CssWithPlaceholderResult, + FinalCssResult, + ParseCss, + ParseCssResult, + ProcessCss, + finalize_css, + parse_css, + process_css_with_placeholder, + }, + references::{compose::CssModuleComposeReference, import::ImportAssetReference}, +}; + +#[turbo_tasks::function] +fn modifier(use_swc_css:bool) -> Vc { + if use_swc_css { Vc::cell("swc css".into()) } else { Vc::cell("css".into()) } +} + +#[turbo_tasks::value] +#[derive(Clone)] +pub struct CssModuleAsset { + source:Vc>, + asset_context:Vc>, + import_context:Option>, + ty:CssModuleAssetType, + use_swc_css:bool, +} + +#[turbo_tasks::value_impl] +impl CssModuleAsset { + /// Creates a new CSS asset. + #[turbo_tasks::function] + pub fn new( + source:Vc>, + asset_context:Vc>, + ty:CssModuleAssetType, + use_swc_css:bool, + import_context:Option>, + ) -> Vc { + Self::cell(CssModuleAsset { source, asset_context, import_context, ty, use_swc_css }) + } + + /// Retrns the asset ident of the source without the "css" modifier + #[turbo_tasks::function] + pub async fn source_ident(self: Vc) -> Result> { + Ok(self.await?.source.ident()) + } +} + +#[turbo_tasks::value_impl] +impl ParseCss for CssModuleAsset { + #[turbo_tasks::function] + async fn parse_css(self: Vc) -> Result> { + let this = self.await?; + + Ok(parse_css( + this.source, + Vc::upcast(self), + this.import_context + .unwrap_or_else(|| ImportContext::new(vec![], vec![], vec![])), + this.ty, + this.use_swc_css, + )) + } +} + +#[turbo_tasks::value_impl] +impl ProcessCss for CssModuleAsset { + #[turbo_tasks::function] + async fn get_css_with_placeholder(self: Vc) -> Result> { + let parse_result = self.parse_css(); + + Ok(process_css_with_placeholder(parse_result)) + } + + #[turbo_tasks::function] + async fn finalize_css( + self: Vc, + chunking_context:Vc>, + ) -> Result> { + let process_result = self.get_css_with_placeholder(); + + Ok(finalize_css(process_result, chunking_context)) + } +} + +#[turbo_tasks::value_impl] +impl Module for CssModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + let mut ident = self + .source + .ident() + .with_modifier(modifier(self.use_swc_css)) + .with_layer(self.asset_context.layer()); + if let Some(import_context) = self.import_context { + ident = ident.with_modifier(import_context.modifier()) + } + ident + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let result = self.parse_css().await?; + // TODO: include CSS source map + + match &*result { + ParseCssResult::Ok { references, .. } => Ok(*references), + ParseCssResult::Unparseable => Ok(ModuleReferences::empty()), + ParseCssResult::NotFound => Ok(ModuleReferences::empty()), + } + } +} + +#[turbo_tasks::value_impl] +impl Asset for CssModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for CssModuleAsset { + #[turbo_tasks::function] + fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Vc> { + Vc::upcast(CssModuleChunkItem::cell(CssModuleChunkItem { module:self, chunking_context })) + } +} + +#[turbo_tasks::value_impl] +impl CssChunkPlaceable for CssModuleAsset {} + +#[turbo_tasks::value_impl] +impl ResolveOrigin for CssModuleAsset { + #[turbo_tasks::function] + fn origin_path(&self) -> Vc { self.source.ident().path() } + + #[turbo_tasks::function] + fn asset_context(&self) -> Vc> { self.asset_context } +} + +#[turbo_tasks::value] +struct CssModuleChunkItem { + module:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for CssModuleChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + fn ty(&self) -> Vc> { Vc::upcast(Vc::::default()) } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } +} + +#[turbo_tasks::value_impl] +impl CssChunkItem for CssModuleChunkItem { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let references = &*self.module.references().await?; + let mut imports = vec![]; + let chunking_context = self.chunking_context; + + for reference in references.iter() { + if let Some(import_ref) = + Vc::try_resolve_downcast_type::(*reference).await? + { + for &module in + import_ref.resolve_reference().resolve().await?.primary_modules().await?.iter() + { + if let Some(placeable) = + Vc::try_resolve_downcast::>(module).await? + { + let item = placeable.as_chunk_item(chunking_context); + if let Some(css_item) = + Vc::try_resolve_downcast::>(item).await? + { + imports.push(CssImport::Internal(import_ref, css_item)); + } + } + } + } else if let Some(compose_ref) = + Vc::try_resolve_downcast_type::(*reference).await? + { + for &module in + compose_ref.resolve_reference().resolve().await?.primary_modules().await?.iter() + { + if let Some(placeable) = + Vc::try_resolve_downcast::>(module).await? + { + let item = placeable.as_chunk_item(chunking_context); + if let Some(css_item) = + Vc::try_resolve_downcast::>(item).await? + { + imports.push(CssImport::Composes(css_item)); + } + } + } + } + } + + let mut code_gens = Vec::new(); + for r in references.iter() { + if let Some(code_gen) = + Vc::try_resolve_sidecast::>(*r).await? + { + code_gens.push(code_gen.code_generation(chunking_context)); + } + } + // need to keep that around to allow references into that + let code_gens = code_gens.into_iter().try_join().await?; + let code_gens = code_gens.iter().map(|cg| &**cg).collect::>(); + // TOOD use interval tree with references into "code_gens" + for code_gen in code_gens { + for import in &code_gen.imports { + imports.push(import.clone()); + } + } + + let result = self.module.finalize_css(chunking_context).await?; + + if let FinalCssResult::Ok { output_code, source_map, .. } = &*result { + Ok(CssChunkItemContent { + inner_code:output_code.to_owned().into(), + imports, + import_context:self.module.await?.import_context, + source_map:Some(*source_map), + } + .into()) + } else { + Ok(CssChunkItemContent { + inner_code:format!("/* unparseable {} */", self.module.ident().to_string().await?) + .into(), + imports:vec![], + import_context:None, + source_map:None, + } + .into()) + } + } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } +} diff --git a/crates/turbopack-css/Source/chunk/mod.rs b/crates/turbopack-css/Source/chunk/mod.rs new file mode 100644 index 0000000000000..a4f422605e7ad --- /dev/null +++ b/crates/turbopack-css/Source/chunk/mod.rs @@ -0,0 +1,470 @@ +pub(crate) mod single_item_chunk; +pub mod source_map; + +use std::fmt::Write; + +use anyhow::{Result, bail}; +use indexmap::IndexSet; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, ValueDefault, ValueToString, Vc}; +use turbo_tasks_fs::{File, FileSystem, rope::Rope}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ + AsyncModuleInfo, + Chunk, + ChunkItem, + ChunkItemWithAsyncModuleInfo, + ChunkType, + ChunkableModule, + ChunkingContext, + ModuleId, + OutputChunk, + OutputChunkRuntimeInfo, + }, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + introspect::{ + Introspectable, + IntrospectableChildren, + module::IntrospectableModule, + utils::{children_from_output_assets, content_to_details}, + }, + module::Module, + output::{OutputAsset, OutputAssets}, + reference_type::ImportContext, + server_fs::ServerFileSystem, + source_map::{GenerateSourceMap, OptionSourceMap}, +}; + +use self::{single_item_chunk::chunk::SingleItemCssChunk, source_map::CssChunkSourceMapAsset}; +use crate::{ImportAssetReference, process::ParseCssResultSourceMap, util::stringify_js}; + +#[turbo_tasks::value] +pub struct CssChunk { + pub chunking_context:Vc>, + pub content:Vc, +} + +#[turbo_tasks::value(transparent)] +pub struct CssChunks(Vec>); + +#[turbo_tasks::value_impl] +impl CssChunk { + #[turbo_tasks::function] + pub fn new( + chunking_context:Vc>, + content:Vc, + ) -> Vc { + CssChunk { chunking_context, content }.cell() + } + + #[turbo_tasks::function] + fn chunk_content(&self) -> Vc { self.content } + + #[turbo_tasks::function] + async fn code(self: Vc) -> Result> { + use std::io::Write; + + let this = self.await?; + + let mut code = CodeBuilder::default(); + let mut body = CodeBuilder::default(); + let mut external_imports = IndexSet::new(); + for css_item in &this.content.await?.chunk_items { + let id = &*css_item.id().await?; + + let content = &css_item.content().await?; + for import in &content.imports { + if let CssImport::External(external_import) = import { + external_imports.insert((*external_import.await?).to_string()); + } + } + + writeln!(body, "/* {} */", id)?; + let close = write_import_context(&mut body, content.import_context).await?; + + body.push_source(&content.inner_code, content.source_map.map(Vc::upcast)); + + writeln!(body, "{close}")?; + writeln!(body)?; + } + + for external_import in external_imports { + writeln!(code, "@import {};", stringify_js(&external_import))?; + } + + let built = &body.build(); + code.push_code(built); + + if *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await? + && code.has_source_map() + { + let chunk_path = self.path().await?; + writeln!( + code, + "/*# sourceMappingURL={}.map*/", + urlencoding::encode(chunk_path.file_name()) + )?; + } + + let c = code.build().cell(); + Ok(c) + } + + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } +} + +pub async fn write_import_context( + body:&mut impl std::io::Write, + import_context:Option>, +) -> Result { + let mut close = String::new(); + if let Some(import_context) = import_context { + let import_context = &*import_context.await?; + if !&import_context.layers.is_empty() { + writeln!(body, "@layer {} {{", import_context.layers.join("."))?; + close.push_str("\n}"); + } + if !&import_context.media.is_empty() { + writeln!(body, "@media {} {{", import_context.media.join(" and "))?; + close.push_str("\n}"); + } + if !&import_context.supports.is_empty() { + writeln!(body, "@supports {} {{", import_context.supports.join(" and "))?; + close.push_str("\n}"); + } + } + Ok(close) +} + +#[turbo_tasks::value] +pub struct CssChunkContent { + pub chunk_items:Vec>>, + pub referenced_output_assets:Vc, +} + +#[turbo_tasks::value_impl] +impl Chunk for CssChunk { + #[turbo_tasks::function] + fn ident(self: Vc) -> Vc { + let self_as_output_asset:Vc> = Vc::upcast(self); + self_as_output_asset.ident() + } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + fn references(self: Vc) -> Vc { OutputAsset::references(self) } +} + +#[turbo_tasks::value_impl] +impl OutputChunk for CssChunk { + #[turbo_tasks::function] + async fn runtime_info(&self) -> Result> { + let content = self.content.await?; + let entries_chunk_items = &content.chunk_items; + let included_ids = entries_chunk_items + .iter() + .map(|chunk_item| CssChunkItem::id(*chunk_item)) + .collect(); + let imports_chunk_items:Vec<_> = entries_chunk_items + .iter() + .map(|&chunk_item| { + async move { + let Some(css_item) = + Vc::try_resolve_downcast::>(chunk_item).await? + else { + return Ok(vec![]); + }; + Ok(css_item + .content() + .await? + .imports + .iter() + .filter_map(|import| { + if let CssImport::Internal(_, item) = import { + Some(*item) + } else { + None + } + }) + .collect::>()) + } + }) + .try_join() + .await? + .into_iter() + .flatten() + .collect(); + let module_chunks:Vec<_> = content + .chunk_items + .iter() + .chain(imports_chunk_items.iter()) + .map(|item| Vc::upcast(SingleItemCssChunk::new(self.chunking_context, *item))) + .collect(); + Ok(OutputChunkRuntimeInfo { + included_ids:Some(Vc::cell(included_ids)), + module_chunks:Some(Vc::cell(module_chunks)), + ..Default::default() + } + .cell()) + } +} + +#[turbo_tasks::function] +fn chunk_item_key() -> Vc { Vc::cell("chunk item".into()) } + +#[turbo_tasks::value_impl] +impl OutputAsset for CssChunk { + #[turbo_tasks::function] + async fn ident(self: Vc) -> Result> { + let this = self.await?; + + let mut assets = Vec::new(); + + let CssChunkContent { chunk_items, .. } = &*this.content.await?; + let mut common_path = if let Some(chunk_item) = chunk_items.first() { + let path = chunk_item.asset_ident().path().resolve().await?; + Some((path, path.await?)) + } else { + None + }; + + // The included chunk items and the availability info describe the chunk + // uniquely + let chunk_item_key = chunk_item_key(); + for &chunk_item in chunk_items.iter() { + if let Some((common_path_vc, common_path_ref)) = common_path.as_mut() { + let path = chunk_item.asset_ident().path().await?; + while !path.is_inside_or_equal_ref(common_path_ref) { + let parent = common_path_vc.parent().resolve().await?; + if parent == *common_path_vc { + common_path = None; + break; + } + *common_path_vc = parent; + *common_path_ref = (*common_path_vc).await?; + } + } + assets.push((chunk_item_key, chunk_item.content_ident())); + } + + // Make sure the idents are resolved + for (_, ident) in assets.iter_mut() { + *ident = ident.resolve().await?; + } + + let ident = AssetIdent { + path:if let Some((common_path, _)) = common_path { + common_path + } else { + ServerFileSystem::new().root() + }, + query:Vc::::default(), + fragment:None, + assets, + modifiers:Vec::new(), + part:None, + layer:None, + }; + + Ok(AssetIdent::from_path( + this.chunking_context + .chunk_path(AssetIdent::new(Value::new(ident)), ".css".into()), + )) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let content = this.content.await?; + let mut references = content.referenced_output_assets.await?.clone_value(); + for item in content.chunk_items.iter() { + references.push(Vc::upcast(SingleItemCssChunk::new(this.chunking_context, *item))); + } + if *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await? { + references.push(Vc::upcast(CssChunkSourceMapAsset::new(self))); + } + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for CssChunk { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { self.content() } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for CssChunk { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() + } +} + +#[turbo_tasks::value] +pub struct CssChunkContext { + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl CssChunkContext { + #[turbo_tasks::function] + pub fn of(chunking_context:Vc>) -> Vc { + CssChunkContext { chunking_context }.cell() + } + + #[turbo_tasks::function] + pub async fn chunk_item_id( + self: Vc, + chunk_item:Vc>, + ) -> Result> { + Ok(ModuleId::String(chunk_item.asset_ident().to_string().await?.clone_value()).cell()) + } +} + +// TODO: remove +#[turbo_tasks::value_trait] +pub trait CssChunkPlaceable: ChunkableModule + Module + Asset {} + +#[turbo_tasks::value(transparent)] +pub struct CssChunkPlaceables(Vec>>); + +#[derive(Clone, Debug)] +#[turbo_tasks::value(shared)] +pub enum CssImport { + External(Vc), + Internal(Vc, Vc>), + Composes(Vc>), +} + +#[derive(Debug)] +#[turbo_tasks::value(shared)] +pub struct CssChunkItemContent { + pub import_context:Option>, + pub imports:Vec, + pub inner_code:Rope, + pub source_map:Option>, +} + +#[turbo_tasks::value_trait] +pub trait CssChunkItem: ChunkItem { + fn content(self: Vc) -> Vc; + fn chunking_context(self: Vc) -> Vc>; + fn id(self: Vc) -> Vc { + CssChunkContext::of(CssChunkItem::chunking_context(self)).chunk_item_id(self) + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("css chunk".into()) } + +#[turbo_tasks::function] +fn entry_module_key() -> Vc { Vc::cell("entry module".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for CssChunk { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(self: Vc) -> Vc { self.path().to_string() } + + #[turbo_tasks::function] + async fn details(self: Vc) -> Result> { + let content = content_to_details(self.content()); + let mut details = String::new(); + let this = self.await?; + let chunk_content = this.content.await?; + details += "Chunk items:\n\n"; + for item in chunk_content.chunk_items.iter() { + writeln!(details, "- {}", item.asset_ident().to_string().await?)?; + } + details += "\nContent:\n\n"; + write!(details, "{}", content.await?)?; + Ok(Vc::cell(details.into())) + } + + #[turbo_tasks::function] + async fn children(self: Vc) -> Result> { + let mut children = + children_from_output_assets(OutputAsset::references(self)).await?.clone_value(); + for &chunk_item in self.await?.content.await?.chunk_items.iter() { + children.insert((entry_module_key(), IntrospectableModule::new(chunk_item.module()))); + } + Ok(Vc::cell(children)) + } +} + +#[derive(Default)] +#[turbo_tasks::value] +pub struct CssChunkType {} + +#[turbo_tasks::value_impl] +impl ValueToString for CssChunkType { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { Vc::cell("css".into()) } +} + +#[turbo_tasks::value_impl] +impl ChunkType for CssChunkType { + #[turbo_tasks::function] + async fn chunk( + &self, + chunking_context:Vc>, + chunk_items:Vec, + referenced_output_assets:Vc, + ) -> Result>> { + let content = CssChunkContent { + chunk_items:chunk_items + .iter() + .map(|(chunk_item, _async_info)| { + async move { + let Some(chunk_item) = + Vc::try_resolve_downcast::>(*chunk_item).await? + else { + bail!( + "Chunk item is not an css chunk item but reporting chunk type css" + ); + }; + // CSS doesn't need to care about async_info, so we can discard it + Ok(chunk_item) + } + }) + .try_join() + .await?, + referenced_output_assets, + } + .cell(); + Ok(Vc::upcast(CssChunk::new(chunking_context, content))) + } + + #[turbo_tasks::function] + async fn chunk_item_size( + &self, + _chunking_context:Vc>, + chunk_item:Vc>, + _async_module_info:Option>, + ) -> Result> { + let Some(chunk_item) = + Vc::try_resolve_downcast::>(chunk_item).await? + else { + bail!("Chunk item is not an css chunk item but reporting chunk type css"); + }; + Ok(Vc::cell( + chunk_item.content().await.map_or(0, |content| content.inner_code.len()), + )) + } +} + +#[turbo_tasks::value_impl] +impl ValueDefault for CssChunkType { + #[turbo_tasks::function] + fn value_default() -> Vc { Self::default().cell() } +} diff --git a/crates/turbopack-css/Source/chunk/single_item_chunk/chunk.rs b/crates/turbopack-css/Source/chunk/single_item_chunk/chunk.rs new file mode 100644 index 0000000000000..c8a6bfed1d871 --- /dev/null +++ b/crates/turbopack-css/Source/chunk/single_item_chunk/chunk.rs @@ -0,0 +1,148 @@ +use std::fmt::Write; + +use anyhow::Result; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{Chunk, ChunkItem, ChunkingContext}, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + introspect::Introspectable, + output::{OutputAsset, OutputAssets}, + source_map::{GenerateSourceMap, OptionSourceMap}, +}; + +use super::source_map::SingleItemCssChunkSourceMapAsset; +use crate::chunk::{CssChunkItem, write_import_context}; + +/// A CSS chunk that only contains a single item. This is used for selectively +/// loading CSS modules that are part of a larger chunk in development mode, and +/// avoiding rule duplication. +#[turbo_tasks::value] +pub struct SingleItemCssChunk { + chunking_context:Vc>, + item:Vc>, +} + +#[turbo_tasks::value_impl] +impl SingleItemCssChunk { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new( + chunking_context:Vc>, + item:Vc>, + ) -> Vc { + SingleItemCssChunk { chunking_context, item }.cell() + } +} + +#[turbo_tasks::value_impl] +impl SingleItemCssChunk { + #[turbo_tasks::function] + async fn code(self: Vc) -> Result> { + use std::io::Write; + + let this = self.await?; + let mut code = CodeBuilder::default(); + + let id = &*this.item.id().await?; + + writeln!(code, "/* {} */", id)?; + let content = this.item.content().await?; + let close = write_import_context(&mut code, content.import_context).await?; + + code.push_source(&content.inner_code, content.source_map.map(Vc::upcast)); + write!(code, "{close}")?; + + if *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await? + && code.has_source_map() + { + let chunk_path = self.path().await?; + write!( + code, + "\n/*# sourceMappingURL={}.map*/", + urlencoding::encode(chunk_path.file_name()) + )?; + } + + let c = code.build().cell(); + Ok(c) + } +} + +#[turbo_tasks::value_impl] +impl Chunk for SingleItemCssChunk { + #[turbo_tasks::function] + fn ident(self: Vc) -> Vc { + let self_as_output_asset:Vc> = Vc::upcast(self); + self_as_output_asset.ident() + } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } +} + +#[turbo_tasks::function] +fn single_item_modifier() -> Vc { Vc::cell("single item css chunk".into()) } + +#[turbo_tasks::value_impl] +impl OutputAsset for SingleItemCssChunk { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + Ok(AssetIdent::from_path(self.chunking_context.chunk_path( + self.item.asset_ident().with_modifier(single_item_modifier()), + ".css".into(), + ))) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let mut references = Vec::new(); + if *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await? { + references.push(Vc::upcast(SingleItemCssChunkSourceMapAsset::new(self))); + } + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for SingleItemCssChunk { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for SingleItemCssChunk { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("single asset css chunk".into()) } + +#[turbo_tasks::function] +fn entry_module_key() -> Vc { Vc::cell("entry module".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for SingleItemCssChunk { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(self: Vc) -> Vc { self.path().to_string() } + + #[turbo_tasks::function] + async fn details(self: Vc) -> Result> { + let this = self.await?; + let mut details = String::new(); + write!(details, "Chunk item: {}", this.item.asset_ident().to_string().await?)?; + Ok(Vc::cell(details.into())) + } +} diff --git a/crates/turbopack-css/Source/chunk/single_item_chunk/mod.rs b/crates/turbopack-css/Source/chunk/single_item_chunk/mod.rs new file mode 100644 index 0000000000000..9950d4389711d --- /dev/null +++ b/crates/turbopack-css/Source/chunk/single_item_chunk/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod chunk; +pub(crate) mod source_map; diff --git a/crates/turbopack-css/Source/chunk/single_item_chunk/source_map.rs b/crates/turbopack-css/Source/chunk/single_item_chunk/source_map.rs new file mode 100644 index 0000000000000..15216010112eb --- /dev/null +++ b/crates/turbopack-css/Source/chunk/single_item_chunk/source_map.rs @@ -0,0 +1,48 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::Chunk, + ident::AssetIdent, + output::OutputAsset, + source_map::{GenerateSourceMap, SourceMap}, +}; + +use super::chunk::SingleItemCssChunk; + +/// Represents the source map of a single item CSS chunk. +#[turbo_tasks::value] +pub struct SingleItemCssChunkSourceMapAsset { + chunk:Vc, +} + +#[turbo_tasks::value_impl] +impl SingleItemCssChunkSourceMapAsset { + #[turbo_tasks::function] + pub fn new(chunk:Vc) -> Vc { + SingleItemCssChunkSourceMapAsset { chunk }.cell() + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for SingleItemCssChunkSourceMapAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + Ok(AssetIdent::from_path(self.chunk.path().append(".map".into()))) + } +} + +#[turbo_tasks::value_impl] +impl Asset for SingleItemCssChunkSourceMapAsset { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let sm = if let Some(sm) = *self.chunk.generate_source_map().await? { + sm + } else { + SourceMap::empty() + }; + let sm = sm.to_rope().await?; + Ok(AssetContent::file(File::from(sm).into())) + } +} diff --git a/crates/turbopack-css/Source/chunk/source_map.rs b/crates/turbopack-css/Source/chunk/source_map.rs new file mode 100644 index 0000000000000..1ee13aecd0399 --- /dev/null +++ b/crates/turbopack-css/Source/chunk/source_map.rs @@ -0,0 +1,46 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::Chunk, + ident::AssetIdent, + output::OutputAsset, + source_map::{GenerateSourceMap, SourceMap}, +}; + +use super::CssChunk; + +/// Represents the source map of an css chunk. +#[turbo_tasks::value] +pub struct CssChunkSourceMapAsset { + chunk:Vc, +} + +#[turbo_tasks::value_impl] +impl CssChunkSourceMapAsset { + #[turbo_tasks::function] + pub fn new(chunk:Vc) -> Vc { CssChunkSourceMapAsset { chunk }.cell() } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for CssChunkSourceMapAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + Ok(AssetIdent::from_path(self.chunk.path().append(".map".into()))) + } +} + +#[turbo_tasks::value_impl] +impl Asset for CssChunkSourceMapAsset { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let sm = if let Some(sm) = *self.chunk.generate_source_map().await? { + sm + } else { + SourceMap::empty() + }; + let sm = sm.to_rope().await?; + Ok(AssetContent::file(File::from(sm).into())) + } +} diff --git a/crates/turbopack-css/Source/code_gen.rs b/crates/turbopack-css/Source/code_gen.rs new file mode 100644 index 0000000000000..95d2e824b7362 --- /dev/null +++ b/crates/turbopack-css/Source/code_gen.rs @@ -0,0 +1,23 @@ +use turbo_tasks::Vc; +use turbopack_core::chunk::ChunkingContext; + +use crate::chunk::CssImport; + +/// impl of code generation inferred from a ModuleReference. +/// This is rust only and can't be implemented by non-rust plugins. +#[turbo_tasks::value(shared, serialization = "none", eq = "manual", into = "new", cell = "new")] +pub struct CodeGeneration { + #[turbo_tasks(debug_ignore, trace_ignore)] + pub imports:Vec, +} + +#[turbo_tasks::value_trait] +pub trait CodeGenerateable { + fn code_generation( + self: Vc, + chunking_context:Vc>, + ) -> Vc; +} + +#[turbo_tasks::value(transparent)] +pub struct CodeGenerateables(Vec>>); diff --git a/crates/turbopack-css/Source/embed.rs b/crates/turbopack-css/Source/embed.rs new file mode 100644 index 0000000000000..c0de310bf5ea1 --- /dev/null +++ b/crates/turbopack-css/Source/embed.rs @@ -0,0 +1,7 @@ +use turbo_tasks::Vc; +use turbopack_core::{chunk::ChunkItem, output::OutputAsset}; + +#[turbo_tasks::value_trait] +pub trait CssEmbed: ChunkItem { + fn embedded_asset(self: Vc) -> Vc>; +} diff --git a/crates/turbopack-css/Source/lib.rs b/crates/turbopack-css/Source/lib.rs new file mode 100644 index 0000000000000..53bef3ad05d32 --- /dev/null +++ b/crates/turbopack-css/Source/lib.rs @@ -0,0 +1,55 @@ +#![feature(min_specialization)] +#![feature(box_patterns)] +#![feature(iter_intersperse)] +#![feature(int_roundings)] +#![feature(arbitrary_self_types)] + +mod asset; +pub mod chunk; +mod code_gen; +pub mod embed; +mod lifetime_util; +mod module_asset; +pub(crate) mod parse; +pub(crate) mod process; +pub(crate) mod references; +pub(crate) mod util; + +pub use asset::CssModuleAsset; +pub use module_asset::ModuleCssAsset; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{TaskInput, trace::TraceRawVcs}; + +pub use self::process::*; +use crate::references::import::ImportAssetReference; + +#[derive( + PartialOrd, + Ord, + Eq, + PartialEq, + Hash, + Debug, + Copy, + Clone, + Default, + Serialize, + Deserialize, + TaskInput, + TraceRawVcs, +)] +pub enum CssModuleAssetType { + /// Default parsing mode. + #[default] + Default, + /// The CSS is parsed as CSS modules. + Module, +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-css/Source/lifetime_util.rs b/crates/turbopack-css/Source/lifetime_util.rs new file mode 100644 index 0000000000000..dbf6d2a1b742d --- /dev/null +++ b/crates/turbopack-css/Source/lifetime_util.rs @@ -0,0 +1,16 @@ +use lightningcss::{ + stylesheet::{ParserOptions, StyleSheet}, + traits::IntoOwned, +}; + +pub fn stylesheet_into_static<'i, 'o>( + ss:&StyleSheet, + options:ParserOptions<'o, 'i>, +) -> StyleSheet<'i, 'o> { + let sources = ss.sources.clone(); + let rules = ss.rules.clone().into_owned(); + + // + + StyleSheet::new(sources, rules, options) +} diff --git a/crates/turbopack-css/Source/module_asset.rs b/crates/turbopack-css/Source/module_asset.rs new file mode 100644 index 0000000000000..deaa80fd50651 --- /dev/null +++ b/crates/turbopack-css/Source/module_asset.rs @@ -0,0 +1,407 @@ +use std::{fmt::Write, sync::Arc}; + +use anyhow::{Context, Result, bail}; +use indexmap::IndexMap; +use indoc::formatdoc; +use lightningcss::css_modules::CssModuleReference; +use swc_core::common::{BytePos, FileName, LineCol, SourceMap}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkItem, ChunkItemExt, ChunkType, ChunkableModule, ChunkingContext}, + context::{AssetContext, ProcessResult}, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + module::Module, + reference::{ModuleReference, ModuleReferences}, + reference_type::{CssReferenceSubType, ReferenceType}, + resolve::{origin::ResolveOrigin, parse::Request}, + source::Source, + source_map::OptionSourceMap, +}; +use turbopack_ecmascript::{ + ParseResultSourceMap, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + utils::StringifyJs, +}; + +use crate::{ + process::{CssWithPlaceholderResult, ProcessCss}, + references::{compose::CssModuleComposeReference, internal::InternalCssAssetReference}, +}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("css module".into()) } + +#[turbo_tasks::value] +#[derive(Clone)] +pub struct ModuleCssAsset { + pub source:Vc>, + pub asset_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ModuleCssAsset { + #[turbo_tasks::function] + pub async fn new( + source:Vc>, + asset_context:Vc>, + ) -> Result> { + Ok(Self::cell(ModuleCssAsset { source, asset_context })) + } +} + +#[turbo_tasks::value_impl] +impl Module for ModuleCssAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + self.source + .ident() + .with_modifier(modifier()) + .with_layer(self.asset_context.layer()) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + // The inner reference must come last so it is loaded as the last in the + // resulting css. @import or composes references must be loaded first so + // that the css style rules in them are overridable from the local css. + + // This affects the order in which the resulting CSS chunks will be loaded: + // 1. @import or composes references are loaded first + // 2. The local CSS is loaded last + + let references = self + .module_references() + .await? + .iter() + .copied() + .chain(match *self.inner().await? { + ProcessResult::Module(inner) => { + Some(Vc::upcast(InternalCssAssetReference::new(inner))) + }, + ProcessResult::Ignore => None, + }) + .collect(); + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for ModuleCssAsset { + #[turbo_tasks::function] + fn content(&self) -> Result> { bail!("CSS module asset has no contents") } +} + +/// A CSS class that is exported from a CSS module. +/// +/// See [`ModuleCssClasses`] for more information. +#[turbo_tasks::value] +#[derive(Debug, Clone)] +enum ModuleCssClass { + Local { name:String }, + Global { name:String }, + Import { original:String, from:Vc }, +} + +/// A map of CSS classes exported from a CSS module. +/// +/// ## Example +/// +/// ```css +/// :global(.class1) { +/// color: red; +/// } +/// +/// .class2 { +/// color: blue; +/// } +/// +/// .class3 { +/// composes: class4 from "./other.module.css"; +/// } +/// ``` +/// +/// The above CSS module would have the following exports: +/// 1. class1: [Global("exported_class1")] +/// 2. class2: [Local("exported_class2")] +/// 3. class3: [Local("exported_class3), Import("class4", "./other.module.css")] +#[turbo_tasks::value(transparent)] +#[derive(Debug, Clone)] +struct ModuleCssClasses(IndexMap>); + +#[turbo_tasks::value_impl] +impl ModuleCssAsset { + #[turbo_tasks::function] + async fn inner(self: Vc) -> Result> { + let this = self.await?; + Ok(this + .asset_context + .process(this.source, Value::new(ReferenceType::Css(CssReferenceSubType::Internal)))) + } + + #[turbo_tasks::function] + async fn classes(self: Vc) -> Result> { + let inner = self.inner().module(); + + let inner = Vc::try_resolve_sidecast::>(inner) + .await? + .context("inner asset should be CSS processable")?; + + let result = inner.get_css_with_placeholder().await?; + let mut classes = IndexMap::default(); + + // TODO(alexkirsz) Should we report an error on parse error here? + if let CssWithPlaceholderResult::Ok { exports: Some(exports), .. } = &*result { + for (class_name, export_class_names) in exports { + let mut export = Vec::default(); + + export.push(ModuleCssClass::Local { name:export_class_names.name.clone() }); + + for export_class_name in &export_class_names.composes { + export.push(match export_class_name { + CssModuleReference::Dependency { specifier, name } => { + ModuleCssClass::Import { + original:name.to_string(), + from:CssModuleComposeReference::new( + Vc::upcast(self), + Request::parse(Value::new( + RcStr::from(specifier.clone()).into(), + )), + ), + } + }, + CssModuleReference::Local { name } => { + ModuleCssClass::Local { name:name.to_string() } + }, + CssModuleReference::Global { name } => { + ModuleCssClass::Global { name:name.to_string() } + }, + }) + } + + classes.insert(class_name.to_string(), export); + } + } + + Ok(Vc::cell(classes)) + } + + #[turbo_tasks::function] + async fn module_references(self: Vc) -> Result> { + let mut references = vec![]; + + for (_, class_names) in &*self.classes().await? { + for class_name in class_names { + match class_name { + ModuleCssClass::Import { from, .. } => { + references.push(Vc::upcast(*from)); + }, + ModuleCssClass::Local { .. } | ModuleCssClass::Global { .. } => {}, + } + } + } + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for ModuleCssAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(ModuleChunkItem { chunking_context, module:self }.cell())) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for ModuleCssAsset { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } +} + +#[turbo_tasks::value_impl] +impl ResolveOrigin for ModuleCssAsset { + #[turbo_tasks::function] + fn origin_path(&self) -> Vc { self.source.ident().path() } + + #[turbo_tasks::function] + fn asset_context(&self) -> Vc> { self.asset_context } +} + +#[turbo_tasks::value] +struct ModuleChunkItem { + module:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let classes = self.module.classes().await?; + + let mut code = "__turbopack_export_value__({\n".to_string(); + for (export_name, class_names) in &*classes { + let mut exported_class_names = Vec::with_capacity(class_names.len()); + + for class_name in class_names { + match class_name { + ModuleCssClass::Import { original: original_name, from } => { + let resolved_module = from.resolve_reference().first_module().await?; + + let Some(resolved_module) = &*resolved_module else { + CssModuleComposesIssue { + severity: IssueSeverity::Error.cell(), + source: self.module.ident(), + message: formatdoc! { + r#" + Module {from} referenced in `composes: ... from {from};` can't be resolved. + "#, + from = &*from.await?.request.to_string().await? + }.into(), + }.cell().emit(); + continue; + }; + + let Some(css_module) = + Vc::try_resolve_downcast_type::(*resolved_module) + .await? + else { + CssModuleComposesIssue { + severity: IssueSeverity::Error.cell(), + source: self.module.ident(), + message: formatdoc! { + r#" + Module {from} referenced in `composes: ... from {from};` is not a CSS module. + "#, + from = &*from.await?.request.to_string().await? + }.into(), + }.cell().emit(); + continue; + }; + + // TODO(alexkirsz) We should also warn if `original_name` can't be found in + // the target module. + + let placeable:Vc> = + Vc::upcast(css_module); + + let module_id = + placeable.as_chunk_item(Vc::upcast(self.chunking_context)).id().await?; + let module_id = StringifyJs(&*module_id); + let original_name = StringifyJs(&original_name); + exported_class_names.push(format! { + "__turbopack_import__({module_id})[{original_name}]" + }); + }, + ModuleCssClass::Local { name: class_name } + | ModuleCssClass::Global { name: class_name } => { + exported_class_names.push(StringifyJs(&class_name).to_string()); + }, + } + } + + writeln!( + code, + " {}: {},", + StringifyJs(export_name), + exported_class_names.join(" + \" \" + ") + )?; + } + code += "});\n"; + Ok(EcmascriptChunkItemContent { + inner_code:code.clone().into(), + // We generate a minimal map for runtime code so that the filename is + // displayed in dev tools. + source_map:Some(Vc::upcast(generate_minimal_source_map( + self.module.ident().to_string().await?.to_string(), + code, + ))), + ..Default::default() + } + .cell()) + } +} + +fn generate_minimal_source_map(filename:String, source:String) -> Vc { + let mut mappings = vec![]; + // Start from 1 because 0 is reserved for dummy spans in SWC. + let mut pos = 1; + for (index, line) in source.split_inclusive('\n').enumerate() { + mappings.push((BytePos(pos), LineCol { line:index as u32, col:0 })); + pos += line.len() as u32; + } + let sm:Arc = Default::default(); + sm.new_source_file(FileName::Custom(filename), source); + let map = ParseResultSourceMap::new(sm, mappings, OptionSourceMap::none()); + map.cell() +} + +#[turbo_tasks::value(shared)] +struct CssModuleComposesIssue { + severity:Vc, + source:Vc, + message:RcStr, +} + +#[turbo_tasks::value_impl] +impl Issue for CssModuleComposesIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { self.severity } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { + Ok(StyledString::Text( + "An issue occurred while resolving a CSS module `composes:` rule".into(), + ) + .cell()) + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::CodeGen.cell() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.source.path() } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some(StyledString::Text(self.message.clone()).cell())) + } +} diff --git a/crates/turbopack-css/Source/parse.rs b/crates/turbopack-css/Source/parse.rs new file mode 100644 index 0000000000000..303db68102972 --- /dev/null +++ b/crates/turbopack-css/Source/parse.rs @@ -0,0 +1,18 @@ +use swc_core::common::{FileName, source_map::SourceMapGenConfig}; +use turbopack_core::SOURCE_MAP_PREFIX; + +/// A config to generate a source map which includes the source content of every +/// source file. SWC doesn't inline sources content by default when generating a +/// sourcemap, so we need to provide a custom config to do it. +pub struct InlineSourcesContentConfig {} + +impl SourceMapGenConfig for InlineSourcesContentConfig { + fn file_name_to_source(&self, f:&FileName) -> String { + match f { + FileName::Custom(s) => format!("{SOURCE_MAP_PREFIX}{s}"), + _ => f.to_string(), + } + } + + fn inline_sources_content(&self, _f:&FileName) -> bool { true } +} diff --git a/crates/turbopack-css/Source/process.rs b/crates/turbopack-css/Source/process.rs new file mode 100644 index 0000000000000..906ef1cfac651 --- /dev/null +++ b/crates/turbopack-css/Source/process.rs @@ -0,0 +1,1267 @@ +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; + +use anyhow::{Context, Result, bail}; +use indexmap::IndexMap; +use lightningcss::{ + css_modules::{CssModuleExport, CssModuleExports, CssModuleReference, Pattern, Segment}, + dependencies::{Dependency, ImportDependency, Location, SourceRange}, + stylesheet::{ParserOptions, PrinterOptions, StyleSheet, ToCssResult}, + targets::{Features, Targets}, + values::url::Url, + visit_types, + visitor::Visit, +}; +use once_cell::sync::Lazy; +use regex::Regex; +use smallvec::smallvec; +use swc_core::{ + atoms::Atom, + base::sourcemap::SourceMapBuilder, + common::{BytePos, FileName, LineCol, Span}, + css::{ + ast::{ + ComplexSelector, + ComplexSelectorChildren, + CompoundSelector, + ForgivingComplexSelector, + ForgivingRelativeSelector, + PseudoClassSelectorChildren, + PseudoElementSelectorChildren, + RelativeSelector, + SubclassSelector, + TypeSelector, + UrlValue, + }, + codegen::{CodeGenerator, writer::basic::BasicCssWriter}, + modules::{CssClassName, TransformConfig}, + visit::{VisitMut, VisitMutWith, VisitWith}, + }, +}; +use tracing::Instrument; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbo_tasks_fs::{FileContent, FileSystemPath}; +use turbopack_core::{ + SOURCE_MAP_PREFIX, + asset::{Asset, AssetContent}, + chunk::ChunkingContext, + issue::{ + Issue, + IssueExt, + IssueSource, + IssueStage, + OptionIssueSource, + OptionStyledString, + StyledString, + }, + reference::ModuleReferences, + reference_type::ImportContext, + resolve::origin::ResolveOrigin, + source::Source, + source_map::{GenerateSourceMap, OptionSourceMap}, + source_pos::SourcePos, +}; +use turbopack_swc_utils::emitter::IssueEmitter; + +use crate::{ + CssModuleAssetType, + lifetime_util::stylesheet_into_static, + parse::InlineSourcesContentConfig, + references::{ + analyze_references, + url::{UrlAssetReference, replace_url_references, resolve_url_reference}, + }, +}; + +// Capture up until the first "." +static BASENAME_RE:Lazy = Lazy::new(|| Regex::new(r"^[^.]*").unwrap()); + +#[derive(Debug)] +pub enum StyleSheetLike<'i, 'o> { + LightningCss(StyleSheet<'i, 'o>), + Swc { stylesheet:swc_core::css::ast::Stylesheet, css_modules:Option }, +} + +#[derive(Debug, Clone)] +pub struct SwcCssModuleMode { + basename:String, + path_hash:u32, +} + +impl PartialEq for StyleSheetLike<'_, '_> { + fn eq(&self, _:&Self) -> bool { false } +} + +pub type CssOutput = (ToCssResult, Option); + +impl<'i, 'o> StyleSheetLike<'i, 'o> { + pub fn to_static( + &self, + options:ParserOptions<'static, 'static>, + ) -> StyleSheetLike<'static, 'static> { + match self { + StyleSheetLike::LightningCss(ss) => { + StyleSheetLike::LightningCss(stylesheet_into_static(ss, options)) + }, + StyleSheetLike::Swc { stylesheet, css_modules } => { + StyleSheetLike::Swc { + stylesheet:stylesheet.clone(), + css_modules:css_modules.clone(), + } + }, + } + } + + pub fn to_css( + &self, + cm:Arc, + code:&str, + enable_srcmap:bool, + remove_imports:bool, + handle_nesting:bool, + ) -> Result { + match self { + StyleSheetLike::LightningCss(ss) => { + let mut srcmap = + if enable_srcmap { Some(parcel_sourcemap::SourceMap::new("")) } else { None }; + + let result = ss.to_css(PrinterOptions { + minify:false, + source_map:srcmap.as_mut(), + targets:if handle_nesting { + Targets { include:Features::Nesting, ..Default::default() } + } else { + Default::default() + }, + analyze_dependencies:None, + ..Default::default() + })?; + + if let Some(srcmap) = &mut srcmap { + debug_assert_eq!(ss.sources.len(), 1); + + srcmap.add_sources(ss.sources.clone()); + srcmap.set_source_content(0, code)?; + } + + Ok((result, srcmap.map(ParseCssResultSourceMap::new_lightningcss))) + }, + StyleSheetLike::Swc { stylesheet, css_modules } => { + let mut stylesheet = stylesheet.clone(); + // We always analyze dependencies, but remove them only if remove_imports is + // true + let mut deps = vec![]; + stylesheet.visit_mut_with(&mut SwcDepColllector { deps:&mut deps, remove_imports }); + + // lightningcss specifies css module mode in the parser options. + let mut css_module_exports = None; + if let Some(SwcCssModuleMode { basename, path_hash }) = css_modules { + let output = swc_core::css::modules::compile( + &mut stylesheet, + ModuleTransformConfig { suffix:format!("__{}__{:x}", basename, path_hash) }, + ); + + let mut map = CssModuleExports::default(); + + for (class_name, export_class_names) in output.renamed { + for export_class_name in export_class_names { + // If the class name is already in the map, the first + // one is the reference to itself and the current one is + // the reference to the other class. + match export_class_name { + CssClassName::Local { name } => { + map.entry(class_name.to_string()) + .and_modify(|e| { + e.composes.push(CssModuleReference::Local { + name:name.value.to_string(), + }) + }) + .or_insert_with(|| { + CssModuleExport { + name:name.value.to_string(), + composes:Vec::new(), + is_referenced:true, + } + }); + }, + CssClassName::Global { name } => { + map.entry(class_name.to_string()) + .and_modify(|e| { + e.composes.push(CssModuleReference::Global { + name:name.value.to_string(), + }) + }) + .or_insert_with(|| { + CssModuleExport { + name:name.value.to_string(), + composes:Vec::new(), + is_referenced:true, + } + }); + }, + CssClassName::Import { name, from } => { + let e = + map.entry(class_name.to_string()).or_insert_with(|| { + CssModuleExport { + name:name.value.to_string(), + composes:Vec::new(), + is_referenced:true, + } + }); + + e.composes.push(CssModuleReference::Dependency { + name:name.value.to_string(), + specifier:from.to_string(), + }); + }, + } + } + } + + css_module_exports = Some(map); + } + + if handle_nesting { + stylesheet.visit_mut_with(&mut swc_core::css::compat::compiler::Compiler::new( + swc_core::css::compat::compiler::Config { + process:swc_core::css::compat::feature::Features::NESTING, + }, + )); + } + + use swc_core::css::codegen::Emit; + + let mut code_string = String::new(); + let mut srcmap = if enable_srcmap { Some(vec![]) } else { None }; + + let mut code_gen = CodeGenerator::new( + BasicCssWriter::new(&mut code_string, srcmap.as_mut(), Default::default()), + Default::default(), + ); + + code_gen.emit(&stylesheet)?; + + let srcmap = + srcmap.map(|srcmap| ParseCssResultSourceMap::new_swc(cm.clone(), srcmap)); + + Ok(( + ToCssResult { + code:code_string, + dependencies:Some(deps), + exports:css_module_exports, + references:None, + }, + srcmap, + )) + }, + } + } +} + +/// Multiple [ModuleReference]s +#[turbo_tasks::value(transparent)] +pub struct UnresolvedUrlReferences(pub Vec<(String, Vc)>); + +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +pub enum ParseCssResult { + Ok { + #[turbo_tasks(debug_ignore, trace_ignore)] + cm:Arc, + + code:Vc, + + #[turbo_tasks(trace_ignore)] + stylesheet:StyleSheetLike<'static, 'static>, + + references:Vc, + + url_references:Vc, + + #[turbo_tasks(trace_ignore)] + options:ParserOptions<'static, 'static>, + }, + Unparseable, + NotFound, +} + +impl PartialEq for ParseCssResult { + fn eq(&self, _:&Self) -> bool { false } +} + +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +pub enum CssWithPlaceholderResult { + Ok { + parse_result:Vc, + + #[turbo_tasks(debug_ignore, trace_ignore)] + cm:Arc, + + references:Vc, + + url_references:Vc, + + #[turbo_tasks(trace_ignore)] + exports:Option>, + + #[turbo_tasks(trace_ignore)] + placeholders:HashMap>, + }, + Unparseable, + NotFound, +} + +impl PartialEq for CssWithPlaceholderResult { + fn eq(&self, _:&Self) -> bool { false } +} + +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +pub enum FinalCssResult { + Ok { + #[turbo_tasks(trace_ignore)] + output_code:String, + + #[turbo_tasks(trace_ignore)] + exports:Option, + + source_map:Vc, + }, + Unparseable, + NotFound, +} + +impl PartialEq for FinalCssResult { + fn eq(&self, _:&Self) -> bool { false } +} + +#[turbo_tasks::function] +pub async fn process_css_with_placeholder( + parse_result:Vc, +) -> Result> { + let result = parse_result.await?; + + match &*result { + ParseCssResult::Ok { cm, stylesheet, references, url_references, code, .. } => { + let code = code.await?; + let code = match &*code { + FileContent::Content(v) => v.content().to_str()?, + _ => bail!("this case should be filtered out while parsing"), + }; + + let (result, _) = stylesheet.to_css(cm.clone(), &code, false, false, false)?; + + let exports = result.exports.map(|exports| { + let mut exports = exports.into_iter().collect::>(); + + exports.sort_keys(); + + exports + }); + + Ok(CssWithPlaceholderResult::Ok { + parse_result, + cm:cm.clone(), + exports, + references:*references, + url_references:*url_references, + placeholders:HashMap::new(), + } + .into()) + }, + ParseCssResult::Unparseable => Ok(CssWithPlaceholderResult::Unparseable.into()), + ParseCssResult::NotFound => Ok(CssWithPlaceholderResult::NotFound.into()), + } +} + +#[turbo_tasks::function] +pub async fn finalize_css( + result:Vc, + chunking_context:Vc>, +) -> Result> { + let result = result.await?; + match &*result { + CssWithPlaceholderResult::Ok { cm, parse_result, url_references, .. } => { + let (mut stylesheet, code) = match &*parse_result.await? { + ParseCssResult::Ok { stylesheet, options, code, .. } => { + (stylesheet.to_static(options.clone()), *code) + }, + ParseCssResult::Unparseable => return Ok(FinalCssResult::Unparseable.into()), + ParseCssResult::NotFound => return Ok(FinalCssResult::NotFound.into()), + }; + + let url_references = *url_references; + + let mut url_map = HashMap::new(); + + for (src, reference) in (*url_references.await?).iter() { + let resolved = resolve_url_reference(*reference, chunking_context).await?; + if let Some(v) = resolved.as_ref().cloned() { + url_map.insert(RcStr::from(src.as_str()), v); + } + } + + replace_url_references(&mut stylesheet, &url_map); + + let code = code.await?; + let code = match &*code { + FileContent::Content(v) => v.content().to_str()?, + _ => unreachable!("this case should be filtered out while parsing"), + }; + let (result, srcmap) = stylesheet.to_css(cm.clone(), &code, true, true, true)?; + + Ok(FinalCssResult::Ok { + output_code:result.code, + exports:result.exports, + source_map:srcmap.unwrap().cell(), + } + .into()) + }, + CssWithPlaceholderResult::Unparseable => Ok(FinalCssResult::Unparseable.into()), + CssWithPlaceholderResult::NotFound => Ok(FinalCssResult::NotFound.into()), + } +} + +#[turbo_tasks::value_trait] +pub trait ParseCss { + async fn parse_css(self: Vc) -> Result>; +} + +#[turbo_tasks::value_trait] +pub trait ProcessCss: ParseCss { + async fn get_css_with_placeholder(self: Vc) -> Result>; + + async fn finalize_css( + self: Vc, + chunking_context:Vc>, + ) -> Result>; +} + +#[turbo_tasks::function] +pub async fn parse_css( + source:Vc>, + origin:Vc>, + import_context:Vc, + ty:CssModuleAssetType, + use_swc_css:bool, +) -> Result> { + let span = { + let name = source.ident().to_string().await?.to_string(); + tracing::info_span!("parse css", name = name) + }; + async move { + let content = source.content(); + let fs_path = source.ident().path(); + let ident_str = &*source.ident().to_string().await?; + Ok(match &*content.await? { + AssetContent::Redirect { .. } => ParseCssResult::Unparseable.cell(), + AssetContent::File(file_content) => { + match &*file_content.await? { + FileContent::NotFound => ParseCssResult::NotFound.cell(), + FileContent::Content(file) => { + match file.content().to_str() { + Err(_err) => ParseCssResult::Unparseable.cell(), + Ok(string) => { + process_content( + *file_content, + string.into_owned(), + fs_path, + ident_str, + source, + origin, + import_context, + ty, + use_swc_css, + ) + .await? + }, + } + }, + } + }, + }) + } + .instrument(span) + .await +} + +async fn process_content( + content_vc:Vc, + code:String, + fs_path_vc:Vc, + filename:&str, + source:Vc>, + origin:Vc>, + import_context:Vc, + ty:CssModuleAssetType, + use_swc_css:bool, +) -> Result> { + #[allow(clippy::needless_lifetimes)] + fn without_warnings<'o, 'i>(config:ParserOptions<'o, 'i>) -> ParserOptions<'o, 'static> { + ParserOptions { + filename:config.filename, + css_modules:config.css_modules, + source_index:config.source_index, + error_recovery:config.error_recovery, + warnings:None, + flags:config.flags, + } + } + + let config = ParserOptions { + css_modules:match ty { + CssModuleAssetType::Module => { + Some(lightningcss::css_modules::Config { + pattern:Pattern { + segments:smallvec![ + Segment::Name, + Segment::Literal("__"), + Segment::Hash, + Segment::Literal("__"), + Segment::Local, + ], + }, + dashed_idents:false, + grid:false, + ..Default::default() + }) + }, + + _ => None, + }, + filename:filename.to_string(), + error_recovery:true, + ..Default::default() + }; + + let cm:Arc = Default::default(); + + let stylesheet = if !use_swc_css { + StyleSheetLike::LightningCss({ + let warnings:Arc> = Default::default(); + + match StyleSheet::parse( + &code, + ParserOptions { warnings:Some(warnings.clone()), ..config.clone() }, + ) { + Ok(mut ss) => { + if matches!(ty, CssModuleAssetType::Module) { + let mut validator = CssValidator { errors:Vec::new() }; + ss.visit(&mut validator).unwrap(); + + for err in validator.errors { + err.report(source, fs_path_vc); + } + } + + for err in warnings.read().unwrap().iter() { + match err.kind { + lightningcss::error::ParserError::UnexpectedToken(_) + | lightningcss::error::ParserError::UnexpectedImportRule + | lightningcss::error::ParserError::EndOfInput => { + let source = err.loc.as_ref().map(|loc| { + let pos = + SourcePos { line:loc.line as _, column:loc.column as _ }; + IssueSource::from_line_col(source, pos, pos) + }); + + ParsingIssue { + file:fs_path_vc, + msg:Vc::cell(err.to_string().into()), + source:Vc::cell(source), + } + .cell() + .emit(); + return Ok(ParseCssResult::Unparseable.into()); + }, + + _ => { + // Ignore + }, + } + } + + stylesheet_into_static(&ss, without_warnings(config.clone())) + }, + Err(e) => { + let source = e.loc.as_ref().map(|loc| { + let pos = SourcePos { line:loc.line as _, column:loc.column as _ }; + IssueSource::from_line_col(source, pos, pos) + }); + + ParsingIssue { + file:fs_path_vc, + msg:Vc::cell(e.to_string().into()), + source:Vc::cell(source), + } + .cell() + .emit(); + return Ok(ParseCssResult::Unparseable.into()); + }, + } + }) + } else { + let fs_path = &*fs_path_vc.await?; + + let handler = swc_core::common::errors::Handler::with_emitter( + true, + false, + Box::new(IssueEmitter::new( + source, + cm.clone(), + Some("Parsing css source code failed".into()), + )), + ); + + let fm = cm.new_source_file(FileName::Custom(filename.to_string()), code.clone()); + let mut errors = vec![]; + + let ss = swc_core::css::parser::parse_file( + &fm, + Default::default(), + swc_core::css::parser::parser::ParserConfig { + css_modules:true, + legacy_ie:true, + legacy_nesting:true, + ..Default::default() + }, + &mut errors, + ); + + for err in errors { + err.to_diagnostics(&handler).emit(); + } + + let ss:swc_core::css::ast::Stylesheet = match ss { + Ok(v) => v, + Err(err) => { + err.to_diagnostics(&handler).emit(); + return Ok(ParseCssResult::Unparseable.into()); + }, + }; + + if handler.has_errors() { + return Ok(ParseCssResult::Unparseable.into()); + } + + if matches!(ty, CssModuleAssetType::Module) { + let mut validator = CssValidator { errors:vec![] }; + ss.visit_with(&mut validator); + + for err in validator.errors { + err.report(source, fs_path_vc); + } + } + + StyleSheetLike::Swc { + stylesheet:ss, + css_modules:if matches!(ty, CssModuleAssetType::Module) { + let basename = BASENAME_RE + .captures(fs_path.file_name()) + .context("Must include basename preceding .")? + .get(0) + .context("Must include basename preceding .")? + .as_str(); + // Truncate this as u32 so it's formated as 8-character hex in the suffic below + let path_hash = turbo_tasks_hash::hash_xxh3_hash64(filename) as u32; + + Some(SwcCssModuleMode { basename:basename.to_string(), path_hash }) + } else { + None + }, + } + }; + + let config = without_warnings(config); + let mut stylesheet = stylesheet.to_static(config.clone()); + + let (references, url_references) = + analyze_references(&mut stylesheet, source, origin, import_context)?; + + Ok(ParseCssResult::Ok { + cm, + code:content_vc, + stylesheet, + references:Vc::cell(references), + url_references:Vc::cell(url_references), + options:config, + } + .into()) +} + +/// Visitor that lints wrong css module usage. +/// +/// ```css +/// button { +/// } +/// ``` +/// +/// is wrong for a css module because it doesn't have a class name. +struct CssValidator { + errors:Vec, +} + +#[derive(Debug, PartialEq, Eq)] +enum CssError { + SwcSelectorInModuleNotPure { span:Span }, + LightningCssSelectorInModuleNotPure { selector:String }, +} + +impl CssError { + fn report(self, source:Vc>, file:Vc) { + match self { + CssError::SwcSelectorInModuleNotPure { span } => { + ParsingIssue { + file, + msg:Vc::cell(CSS_MODULE_ERROR.into()), + source:Vc::cell(Some(IssueSource::from_swc_offsets( + source, + span.lo.0 as _, + span.hi.0 as _, + ))), + } + .cell() + .emit(); + }, + CssError::LightningCssSelectorInModuleNotPure { selector } => { + ParsingIssue { + file, + msg:Vc::cell(format!("{CSS_MODULE_ERROR}, (lightningcss, {selector})").into()), + source:Vc::cell(None), + } + .cell() + .emit(); + }, + } + } +} + +const CSS_MODULE_ERROR:&str = + "Selector is not pure (pure selectors must contain at least one local class or id)"; + +/// We only vist top-level selectors. +impl swc_core::css::visit::Visit for CssValidator { + fn visit_complex_selector(&mut self, n:&ComplexSelector) { + fn is_complex_not_pure(sel:&ComplexSelector) -> bool { + sel.children.iter().all(|sel| { + match sel { + ComplexSelectorChildren::CompoundSelector(sel) => is_compound_not_pure(sel), + ComplexSelectorChildren::Combinator(_) => true, + } + }) + } + + fn is_forgiving_selector_not_pure(sel:&ForgivingComplexSelector) -> bool { + match sel { + ForgivingComplexSelector::ComplexSelector(sel) => is_complex_not_pure(sel), + ForgivingComplexSelector::ListOfComponentValues(_) => false, + } + } + + fn is_forgiving_relative_selector_not_pure(sel:&ForgivingRelativeSelector) -> bool { + match sel { + ForgivingRelativeSelector::RelativeSelector(sel) => { + is_relative_selector_not_pure(sel) + }, + ForgivingRelativeSelector::ListOfComponentValues(_) => false, + } + } + + fn is_relative_selector_not_pure(sel:&RelativeSelector) -> bool { + is_complex_not_pure(&sel.selector) + } + + fn is_compound_not_pure(sel:&CompoundSelector) -> bool { + sel.subclass_selectors.iter().all(|sel| { + match sel { + SubclassSelector::Attribute { .. } => true, + SubclassSelector::PseudoClass(cls) => { + cls.name.value == "not" + || cls.name.value == "has" + || if let Some(c) = &cls.children { + c.iter().all(|c| { + match c { + PseudoClassSelectorChildren::ComplexSelector(sel) => { + is_complex_not_pure(sel) + } + + PseudoClassSelectorChildren::CompoundSelector(sel) => { + is_compound_not_pure(sel) + } + + PseudoClassSelectorChildren::SelectorList(sels) => { + sels.children.iter().all(is_complex_not_pure) + } + PseudoClassSelectorChildren::ForgivingSelectorList(sels) => { + sels.children.iter().all(is_forgiving_selector_not_pure) + } + PseudoClassSelectorChildren::CompoundSelectorList(sels) => { + sels.children.iter().all(is_compound_not_pure) + } + PseudoClassSelectorChildren::RelativeSelectorList(sels) => { + sels.children.iter().all(is_relative_selector_not_pure) + } + PseudoClassSelectorChildren::ForgivingRelativeSelectorList( + sels, + ) => sels + .children + .iter() + .all(is_forgiving_relative_selector_not_pure), + + PseudoClassSelectorChildren::Ident(_) + | PseudoClassSelectorChildren::Str(_) + | PseudoClassSelectorChildren::Delimiter(_) + | PseudoClassSelectorChildren::PreservedToken(_) + | PseudoClassSelectorChildren::AnPlusB(_) => false, + } + }) + } else { + true + } + }, + SubclassSelector::PseudoElement(el) => { + match &el.children { + Some(c) => { + c.iter().all(|c| { + match c { + PseudoElementSelectorChildren::CompoundSelector(sel) => { + is_compound_not_pure(sel) + }, + + _ => false, + } + }) + }, + None => true, + } + }, + _ => false, + } + }) && match &sel.type_selector.as_deref() { + Some(TypeSelector::TagName(tag)) => { + !matches!(&*tag.name.value.value, "html" | "body") + }, + Some(TypeSelector::Universal(..)) => true, + None => true, + } + } + + if is_complex_not_pure(n) { + self.errors.push(CssError::SwcSelectorInModuleNotPure { span:n.span }); + } + } + + fn visit_simple_block(&mut self, _:&swc_core::css::ast::SimpleBlock) {} +} + +/// We only vist top-level selectors. +impl lightningcss::visitor::Visitor<'_> for CssValidator { + type Error = (); + + fn visit_types(&self) -> lightningcss::visitor::VisitTypes { visit_types!(SELECTORS) } + + fn visit_selector( + &mut self, + selector:&mut lightningcss::selector::Selector<'_>, + ) -> Result<(), Self::Error> { + fn is_selector_problematic(sel:&lightningcss::selector::Selector) -> bool { + sel.iter_raw_parse_order_from(0).all(is_problematic) + } + + fn is_problematic(c:&lightningcss::selector::Component) -> bool { + match c { + parcel_selectors::parser::Component::ID(..) + | parcel_selectors::parser::Component::Class(..) => false, + + parcel_selectors::parser::Component::Combinator(..) + | parcel_selectors::parser::Component::AttributeOther(..) + | parcel_selectors::parser::Component::AttributeInNoNamespaceExists { .. } + | parcel_selectors::parser::Component::AttributeInNoNamespace { .. } + | parcel_selectors::parser::Component::ExplicitUniversalType + | parcel_selectors::parser::Component::Negation(..) => true, + + parcel_selectors::parser::Component::Where(sel) => { + sel.iter().all(is_selector_problematic) + }, + + parcel_selectors::parser::Component::LocalName(local) => { + // Allow html and body. They are not pure selectors but are allowed. + !matches!(&*local.name.0, "html" | "body") + }, + _ => false, + } + } + + if is_selector_problematic(selector) { + self.errors.push(CssError::LightningCssSelectorInModuleNotPure { + selector:format!("{selector:?}"), + }); + } + + Ok(()) + } +} + +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +pub enum ParseCssResultSourceMap { + Parcel { + #[turbo_tasks(debug_ignore, trace_ignore)] + source_map:parcel_sourcemap::SourceMap, + }, + + Swc { + #[turbo_tasks(debug_ignore, trace_ignore)] + source_map:Arc, + + /// The position mappings that can generate a real source map given a + /// (SWC) SourceMap. + #[turbo_tasks(debug_ignore, trace_ignore)] + mappings:Vec<(BytePos, LineCol)>, + }, +} + +impl PartialEq for ParseCssResultSourceMap { + fn eq(&self, _:&Self) -> bool { false } +} + +impl ParseCssResultSourceMap { + pub fn new_lightningcss(source_map:parcel_sourcemap::SourceMap) -> Self { + ParseCssResultSourceMap::Parcel { source_map } + } + + pub fn new_swc( + source_map:Arc, + mappings:Vec<(BytePos, LineCol)>, + ) -> Self { + ParseCssResultSourceMap::Swc { source_map, mappings } + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for ParseCssResultSourceMap { + #[turbo_tasks::function] + fn generate_source_map(&self) -> Vc { + match self { + ParseCssResultSourceMap::Parcel { source_map } => { + let mut builder = SourceMapBuilder::new(None); + + for src in source_map.get_sources() { + builder.add_source(&format!("{SOURCE_MAP_PREFIX}{src}")); + } + + for (idx, content) in source_map.get_sources_content().iter().enumerate() { + builder.set_source_contents(idx as _, Some(content)); + } + + for m in source_map.get_mappings() { + builder.add_raw( + m.generated_line, + m.generated_column, + m.original.map(|v| v.original_line).unwrap_or_default(), + m.original.map(|v| v.original_column).unwrap_or_default(), + Some(0), + None, + false, + ); + } + + Vc::cell(Some( + turbopack_core::source_map::SourceMap::new_regular(builder.into_sourcemap()) + .cell(), + )) + }, + ParseCssResultSourceMap::Swc { source_map, mappings } => { + let map = source_map.build_source_map_with_config( + mappings, + None, + InlineSourcesContentConfig {}, + ); + Vc::cell(Some(turbopack_core::source_map::SourceMap::new_regular(map).cell())) + }, + } + } +} + +struct SwcDepColllector<'a> { + deps:&'a mut Vec, + remove_imports:bool, +} + +impl VisitMut for SwcDepColllector<'_> { + fn visit_mut_rules(&mut self, n:&mut Vec) { + n.visit_mut_children_with(self); + + if self.remove_imports { + n.retain(|v| { + match v { + swc_core::css::ast::Rule::AtRule(v) => { + match &v.name { + swc_core::css::ast::AtRuleName::DashedIdent(_) => true, + swc_core::css::ast::AtRuleName::Ident(name) => name.value != "import", + } + }, + _ => true, + } + }); + } + } + + fn visit_mut_at_rule_prelude(&mut self, node:&mut swc_core::css::ast::AtRulePrelude) { + match node { + swc_core::css::ast::AtRulePrelude::ImportPrelude(i) => { + let src = match &*i.href { + swc_core::css::ast::ImportHref::Url(v) => { + match v.value.as_deref().unwrap() { + UrlValue::Str(v) => v.value.clone(), + UrlValue::Raw(v) => v.value.clone(), + } + }, + swc_core::css::ast::ImportHref::Str(v) => v.value.clone(), + }; + + self.deps.push(Dependency::Import(ImportDependency { + url:src.to_string(), + placeholder:Default::default(), + supports:None, + media:None, + loc:SourceRange { + file_path:String::new(), + start:Location { line:0, column:0 }, + end:Location { line:0, column:0 }, + }, + })); + }, + + _ => { + node.visit_mut_children_with(self); + }, + } + } +} + +struct ModuleTransformConfig { + suffix:String, +} + +impl TransformConfig for ModuleTransformConfig { + fn new_name_for(&self, local:&Atom) -> Atom { format!("{}{}", *local, self.suffix).into() } +} + +#[turbo_tasks::value] +struct ParsingIssue { + msg:Vc, + file:Vc, + source:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for ParsingIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.file } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Parse.cell() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Parsing css source code failed".into()).cell() + } + + #[turbo_tasks::function] + fn source(&self) -> Vc { self.source } + + #[turbo_tasks::function] + async fn description(&self) -> Result> { + Ok(Vc::cell(Some(StyledString::Text(self.msg.await?.as_str().into()).cell()))) + } +} + +#[cfg(test)] +mod tests { + use lightningcss::{ + css_modules::Pattern, + stylesheet::{ParserOptions, StyleSheet}, + visitor::Visit, + }; + use swc_core::{ + common::{FileName, FilePathMapping}, + css::{ast::Stylesheet, parser::parser::ParserConfig, visit::VisitWith}, + }; + + use super::{CssError, CssValidator}; + + fn lint_lightningcss(code:&str) -> Vec { + let mut ss = StyleSheet::parse( + code, + ParserOptions { + css_modules:Some(lightningcss::css_modules::Config { + pattern:Pattern::default(), + dashed_idents:false, + grid:false, + ..Default::default() + }), + ..Default::default() + }, + ) + .unwrap(); + + let mut validator = CssValidator { errors:Vec::new() }; + ss.visit(&mut validator).unwrap(); + + validator.errors + } + + fn lint_swc(code:&str) -> Vec { + let cm = swc_core::common::SourceMap::new(FilePathMapping::empty()); + + let fm = cm.new_source_file(FileName::Custom("test.css".to_string()), code.to_string()); + + let ss:Stylesheet = swc_core::css::parser::parse_file( + &fm, + None, + ParserConfig { css_modules:true, ..Default::default() }, + &mut vec![], + ) + .unwrap(); + + let mut validator = CssValidator { errors:Vec::new() }; + ss.visit_with(&mut validator); + + validator.errors + } + + #[track_caller] + fn assert_lint_success(code:&str) { + assert_eq!(lint_lightningcss(code), vec![], "lightningcss: {code}"); + assert_eq!(lint_swc(code), vec![], "swc: {code}"); + } + + #[track_caller] + fn assert_lint_failure(code:&str) { + assert_ne!(lint_lightningcss(code), vec![], "lightningcss: {code}"); + assert_ne!(lint_swc(code), vec![], "swc: {code}"); + } + + #[test] + fn css_module_pure_lint() { + assert_lint_success( + "html { + --foo: 1; + }", + ); + + assert_lint_success( + "#id { + color: red; + }", + ); + + assert_lint_success( + ".class { + color: red; + }", + ); + + assert_lint_success( + "html.class { + color: red; + }", + ); + + assert_lint_success( + ".class > * { + color: red; + }", + ); + + assert_lint_success( + ".class * { + color: red; + }", + ); + + assert_lint_success( + ":where(.main > *) { + color: red; + }", + ); + + assert_lint_success( + ":where(.main > *, .root > *) { + color: red; + }", + ); + + assert_lint_failure( + "div { + color: red; + }", + ); + + assert_lint_failure( + "div > span { + color: red; + }", + ); + + assert_lint_failure( + "div span { + color: red; + }", + ); + + assert_lint_failure( + "div[data-foo] { + color: red; + }", + ); + + assert_lint_failure( + "div[data-foo=\"bar\"] { + color: red; + }", + ); + + assert_lint_failure( + "div[data-foo=\"bar\"] span { + color: red; + }", + ); + + assert_lint_failure( + "* { + --foo: 1; + }", + ); + + assert_lint_failure( + "[data-foo] { + --foo: 1; + }", + ); + + assert_lint_failure( + ":not(.class) { + --foo: 1; + }", + ); + + assert_lint_failure( + ":not(div) { + --foo: 1; + }", + ); + + assert_lint_failure( + ":where(div > *) { + color: red; + }", + ); + + assert_lint_failure( + ":where(div) { + color: red; + }", + ); + } +} diff --git a/crates/turbopack-css/Source/references/compose.rs b/crates/turbopack-css/Source/references/compose.rs new file mode 100644 index 0000000000000..55c8b9dbc57ea --- /dev/null +++ b/crates/turbopack-css/Source/references/compose.rs @@ -0,0 +1,54 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + chunk::ChunkableModuleReference, + reference::ModuleReference, + reference_type::CssReferenceSubType, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request}, +}; + +use crate::references::css_resolve; + +/// A `composes: ... from ...` CSS module reference. +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct CssModuleComposeReference { + pub origin:Vc>, + pub request:Vc, +} + +#[turbo_tasks::value_impl] +impl CssModuleComposeReference { + /// Creates a new [`CssModuleComposeReference`]. + #[turbo_tasks::function] + pub fn new(origin:Vc>, request:Vc) -> Vc { + Self::cell(CssModuleComposeReference { origin, request }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for CssModuleComposeReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + css_resolve( + self.origin, + self.request, + Value::new(CssReferenceSubType::Compose), + // TODO: add real issue source, currently impossible because `CssClassName` doesn't + // contain the source span + // https://docs.rs/swc_css_modules/0.21.16/swc_css_modules/enum.CssClassName.html + None, + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for CssModuleComposeReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("compose(url) {}", self.request.to_string().await?,).into())) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for CssModuleComposeReference {} diff --git a/crates/turbopack-css/Source/references/import.rs b/crates/turbopack-css/Source/references/import.rs new file mode 100644 index 0000000000000..00f7fdac97a5c --- /dev/null +++ b/crates/turbopack-css/Source/references/import.rs @@ -0,0 +1,260 @@ +use anyhow::Result; +use lightningcss::{ + media_query::MediaList, + rules::{import::ImportRule, layer::LayerName, supports::SupportsCondition}, + traits::ToCss, +}; +use swc_core::{ + common::{DUMMY_SP, Spanned}, + css::codegen::{ + CodeGenerator, + CodegenConfig, + Emit, + writer::basic::{BasicCssWriter, BasicCssWriterConfig}, + }, +}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ChunkableModuleReference, ChunkingContext}, + issue::IssueSource, + reference::ModuleReference, + reference_type::{CssReferenceSubType, ImportContext}, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request}, +}; + +use crate::{ + chunk::CssImport, + code_gen::{CodeGenerateable, CodeGeneration}, + references::css_resolve, +}; + +#[turbo_tasks::value(into = "new", eq = "manual", serialization = "none")] +pub enum ImportAttributes { + LightningCss { + #[turbo_tasks(trace_ignore)] + layer_name:Option>, + #[turbo_tasks(trace_ignore)] + supports:Option>, + #[turbo_tasks(trace_ignore)] + media:MediaList<'static>, + }, + Swc { + #[turbo_tasks(trace_ignore)] + layer_name:Option, + #[turbo_tasks(trace_ignore)] + supports:Option, + #[turbo_tasks(trace_ignore)] + media:Option>, + }, +} + +impl PartialEq for ImportAttributes { + fn eq(&self, _:&Self) -> bool { false } +} + +impl ImportAttributes { + pub fn new_from_lightningcss(prelude:&ImportRule<'static>) -> Self { + let layer_name = prelude.layer.clone().flatten(); + + let supports = prelude.supports.clone(); + + let media = prelude.media.clone(); + + Self::LightningCss { layer_name, supports, media } + } + + pub fn new_from_swc(prelude:&swc_core::css::ast::ImportPrelude) -> Self { + let layer_name = prelude.layer_name.as_ref().map(|l| { + match l { + box swc_core::css::ast::ImportLayerName::Ident(_) => { + swc_core::css::ast::LayerName { span:DUMMY_SP, name:vec![] } + }, + box swc_core::css::ast::ImportLayerName::Function(f) => { + assert_eq!(f.value.len(), 1); + assert!(matches!( + &f.value[0], + swc_core::css::ast::ComponentValue::LayerName(_) + )); + if let swc_core::css::ast::ComponentValue::LayerName(layer_name) = &f.value[0] { + *layer_name.clone() + } else { + unreachable!() + } + }, + } + }); + + let (supports, media) = prelude + .import_conditions + .as_ref() + .map(|c| { + let supports = if let Some(supports) = &c.supports { + let v = supports.value.iter().find(|v| { + matches!( + v, + swc_core::css::ast::ComponentValue::SupportsCondition(..) + | swc_core::css::ast::ComponentValue::Declaration(..) + ) + }); + + if let Some(supports) = v { + match &supports { + swc_core::css::ast::ComponentValue::SupportsCondition(s) => { + Some(*s.clone()) + }, + swc_core::css::ast::ComponentValue::Declaration(d) => { + Some(swc_core::css::ast::SupportsCondition { + span:DUMMY_SP, + conditions:vec![ + swc_core::css::ast::SupportsConditionType::SupportsInParens( + swc_core::css::ast::SupportsInParens::Feature( + swc_core::css::ast::SupportsFeature::Declaration( + d.clone(), + ), + ), + ), + ], + }) + }, + _ => None, + } + } else { + None + } + } else { + None + }; + + let media = c.media.as_ref().map(|m| m.queries.clone()); + + (supports, media) + }) + .unwrap_or_else(|| (None, None)); + + Self::Swc { layer_name, supports, media } + } + + fn as_reference_import_attributes(&self) -> turbopack_core::reference_type::ImportAttributes { + match self { + ImportAttributes::LightningCss { layer_name, supports, media } => { + turbopack_core::reference_type::ImportAttributes { + layer:layer_name + .as_ref() + .map(|l| l.to_css_string(Default::default()).unwrap()) + .map(From::from), + supports:supports + .as_ref() + .map(|s| s.to_css_string(Default::default()).unwrap()) + .map(From::from), + media:{ + if media.always_matches() { + None + } else { + Some(media.to_css_string(Default::default()).unwrap().into()) + } + }, + } + }, + ImportAttributes::Swc { layer_name, supports, media } => { + turbopack_core::reference_type::ImportAttributes { + layer:layer_name.as_ref().map(gen_swc_node).map(From::from), + supports:supports.as_ref().map(gen_swc_node).map(From::from), + media:media + .as_ref() + .map(|queries| queries.iter().map(gen_swc_node).collect::().into()), + } + }, + } + } +} + +fn gen_swc_node(node:N) -> String +where + N: Spanned, + for<'a> CodeGenerator>: Emit, { + let mut code = String::new(); + { + let wr = BasicCssWriter::new(&mut code, None, BasicCssWriterConfig::default()); + let mut gen = CodeGenerator::new(wr, CodegenConfig { minify:true }); + + gen.emit(&node).unwrap(); + } + code +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct ImportAssetReference { + pub origin:Vc>, + pub request:Vc, + pub attributes:Vc, + pub import_context:Vc, + pub issue_source:Vc, +} + +#[turbo_tasks::value_impl] +impl ImportAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + attributes:Vc, + import_context:Vc, + issue_source:Vc, + ) -> Vc { + Self::cell(ImportAssetReference { + origin, + request, + attributes, + import_context, + issue_source, + }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for ImportAssetReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Result> { + let import_context = { + let own_attrs = (*self.attributes.await?).as_reference_import_attributes(); + self.import_context + .add_attributes(own_attrs.layer, own_attrs.media, own_attrs.supports) + }; + + Ok(css_resolve( + self.origin, + self.request, + Value::new(CssReferenceSubType::AtImport(Some(import_context))), + Some(self.issue_source), + )) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for ImportAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("import(url) {}", self.request.to_string().await?,).into())) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for ImportAssetReference { + #[turbo_tasks::function] + async fn code_generation( + self: Vc, + _context:Vc>, + ) -> Result> { + let this = &*self.await?; + let mut imports = vec![]; + if let Request::Uri { protocol, remainder, .. } = &*this.request.await? { + imports.push(CssImport::External(Vc::cell(format!("{}{}", protocol, remainder).into()))) + } + + Ok(CodeGeneration { imports }.into()) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for ImportAssetReference {} diff --git a/crates/turbopack-css/Source/references/internal.rs b/crates/turbopack-css/Source/references/internal.rs new file mode 100644 index 0000000000000..db13e3adcb4f1 --- /dev/null +++ b/crates/turbopack-css/Source/references/internal.rs @@ -0,0 +1,45 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + chunk::ChunkableModuleReference, + module::Module, + reference::ModuleReference, + resolve::ModuleResolveResult, +}; + +/// A reference to an internal CSS asset. +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct InternalCssAssetReference { + module:Vc>, +} + +#[turbo_tasks::value_impl] +impl InternalCssAssetReference { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new(module:Vc>) -> Vc { + Self::cell(InternalCssAssetReference { module }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for InternalCssAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + ModuleResolveResult::module(self.module).cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for InternalCssAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("internal css {}", self.module.ident().to_string().await?).into(), + )) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for InternalCssAssetReference {} diff --git a/crates/turbopack-css/Source/references/mod.rs b/crates/turbopack-css/Source/references/mod.rs new file mode 100644 index 0000000000000..97c2b3084c73e --- /dev/null +++ b/crates/turbopack-css/Source/references/mod.rs @@ -0,0 +1,236 @@ +use std::convert::Infallible; + +use anyhow::Result; +use lightningcss::{ + rules::CssRule, + traits::IntoOwned, + values::url::Url, + visitor::{Visit, Visitor}, +}; +use swc_core::css::{ + ast::UrlValue, + visit::{VisitMut, VisitMutWith}, +}; +use turbo_tasks::{RcStr, Value, Vc}; +use turbopack_core::{ + issue::{IssueSeverity, IssueSource}, + reference::ModuleReference, + reference_type::{CssReferenceSubType, ImportContext, ReferenceType}, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request, url_resolve}, + source::Source, + source_pos::SourcePos, +}; + +use crate::{ + StyleSheetLike, + references::{ + import::{ImportAssetReference, ImportAttributes}, + url::UrlAssetReference, + }, +}; + +pub(crate) mod compose; +pub(crate) mod import; +pub(crate) mod internal; +pub(crate) mod url; + +pub type AnalyzedRefs = (Vec>>, Vec<(String, Vc)>); + +/// Returns `(all_references, urls)`. +pub fn analyze_references( + stylesheet:&mut StyleSheetLike<'static, 'static>, + source:Vc>, + origin:Vc>, + import_context:Vc, +) -> Result { + let mut references = Vec::new(); + let mut urls = Vec::new(); + + let mut visitor = + ModuleReferencesVisitor::new(source, origin, import_context, &mut references, &mut urls); + match stylesheet { + StyleSheetLike::LightningCss(ss) => { + ss.visit(&mut visitor).unwrap(); + }, + StyleSheetLike::Swc { stylesheet, .. } => { + stylesheet.visit_mut_with(&mut visitor); + }, + } + + Ok((references, urls)) +} + +struct ModuleReferencesVisitor<'a> { + source:Vc>, + origin:Vc>, + import_context:Vc, + references:&'a mut Vec>>, + urls:&'a mut Vec<(String, Vc)>, +} + +impl<'a> ModuleReferencesVisitor<'a> { + fn new( + source:Vc>, + origin:Vc>, + import_context:Vc, + references:&'a mut Vec>>, + urls:&'a mut Vec<(String, Vc)>, + ) -> Self { + Self { source, origin, import_context, references, urls } + } +} + +impl VisitMut for ModuleReferencesVisitor<'_> { + fn visit_mut_import_prelude(&mut self, i:&mut swc_core::css::ast::ImportPrelude) { + let src = match &*i.href { + swc_core::css::ast::ImportHref::Url(v) => { + match v.value.as_deref().unwrap() { + UrlValue::Str(v) => v.value.clone(), + UrlValue::Raw(v) => v.value.clone(), + } + }, + swc_core::css::ast::ImportHref::Str(v) => v.value.clone(), + }; + + let issue_span = i.span; + + self.references.push(Vc::upcast(ImportAssetReference::new( + self.origin, + Request::parse(Value::new(RcStr::from(src.as_str()).into())), + ImportAttributes::new_from_swc(&i.clone()).into(), + self.import_context, + IssueSource::from_swc_offsets( + Vc::upcast(self.source), + issue_span.lo.0 as _, + issue_span.hi.0 as _, + ), + ))); + + // let res = i.visit_children(self); + // res + } + + /// Noop. Urls in `@supports` are not used. + /// + /// See https://github.com/vercel/next.js/issues/63102 + fn visit_mut_supports_condition(&mut self, _:&mut swc_core::css::ast::SupportsCondition) {} + + fn visit_mut_url(&mut self, u:&mut swc_core::css::ast::Url) { + u.visit_mut_children_with(self); + + let src = match u.value.as_deref().unwrap() { + UrlValue::Str(v) => v.value.clone(), + UrlValue::Raw(v) => v.value.clone(), + }; + + // ignore internal urls like `url(#noiseFilter)` + // ignore server-relative urls like `url(/foo)` + if !matches!(src.bytes().next(), Some(b'#') | Some(b'/')) { + let issue_span = u.span; + + let vc = UrlAssetReference::new( + self.origin, + Request::parse(Value::new(RcStr::from(src.as_str()).into())), + IssueSource::from_swc_offsets( + Vc::upcast(self.source), + issue_span.lo.0 as _, + issue_span.hi.0 as _, + ), + ); + + self.references.push(Vc::upcast(vc)); + self.urls.push((src.to_string(), vc)); + } + } +} + +impl<'a> Visitor<'_> for ModuleReferencesVisitor<'a> { + type Error = Infallible; + + fn visit_types(&self) -> lightningcss::visitor::VisitTypes { + lightningcss::visitor::VisitTypes::all() + } + + fn visit_rule(&mut self, rule:&mut CssRule) -> std::result::Result<(), Self::Error> { + match rule { + CssRule::Import(i) => { + let src = &*i.url; + + let issue_span = i.loc; + + self.references.push(Vc::upcast(ImportAssetReference::new( + self.origin, + Request::parse(Value::new(RcStr::from(src).into())), + ImportAttributes::new_from_lightningcss(&i.clone().into_owned()).into(), + self.import_context, + IssueSource::from_line_col( + Vc::upcast(self.source), + SourcePos { line:issue_span.line as _, column:issue_span.column as _ }, + SourcePos { line:issue_span.line as _, column:issue_span.column as _ }, + ), + ))); + + *rule = CssRule::Ignored; + + // let res = i.visit_children(self); + // res + Ok(()) + }, + + _ => rule.visit_children(self), + } + } + + fn visit_url(&mut self, u:&mut Url) -> std::result::Result<(), Self::Error> { + let src = &*u.url; + + // ignore internal urls like `url(#noiseFilter)` + // ignore server-relative urls like `url(/foo)` + if !matches!(src.bytes().next(), Some(b'#') | Some(b'/')) { + let issue_span = u.loc; + + let vc = UrlAssetReference::new( + self.origin, + Request::parse(Value::new(RcStr::from(src).into())), + IssueSource::from_line_col( + Vc::upcast(self.source), + SourcePos { line:issue_span.line as _, column:issue_span.column as _ }, + SourcePos { line:issue_span.line as _, column:issue_span.column as _ }, + ), + ); + + self.references.push(Vc::upcast(vc)); + self.urls.push((u.url.to_string(), vc)); + } + + // u.visit_children(self)?; + + Ok(()) + } + + /// Noop. Urls in `@supports` are not used. + /// + /// See https://github.com/vercel/next.js/issues/63102 + fn visit_supports_condition( + &mut self, + _:&mut lightningcss::rules::supports::SupportsCondition<'_>, + ) -> Result<(), Self::Error> { + Ok(()) + } +} + +#[turbo_tasks::function] +pub async fn css_resolve( + origin:Vc>, + request:Vc, + ty:Value, + issue_source:Option>, +) -> Vc { + url_resolve( + origin, + request, + Value::new(ReferenceType::Css(ty.into_value())), + issue_source, + IssueSeverity::Error.cell(), + ) +} diff --git a/crates/turbopack-css/Source/references/url.rs b/crates/turbopack-css/Source/references/url.rs new file mode 100644 index 0000000000000..2652b771cd3b4 --- /dev/null +++ b/crates/turbopack-css/Source/references/url.rs @@ -0,0 +1,194 @@ +use std::{collections::HashMap, convert::Infallible}; + +use anyhow::{Result, bail}; +use lightningcss::{ + values::url::Url, + visit_types, + visitor::{Visit, Visitor}, +}; +use swc_core::css::{ + ast::UrlValue, + visit::{VisitMut, VisitMutWith}, +}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc, debug::ValueDebug}; +use turbopack_core::{ + chunk::{ + ChunkableModule, + ChunkableModuleReference, + ChunkingContext, + ChunkingType, + ChunkingTypeOption, + }, + ident::AssetIdent, + issue::{IssueSeverity, IssueSource}, + output::OutputAsset, + reference::ModuleReference, + reference_type::{ReferenceType, UrlReferenceSubType}, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request, url_resolve}, +}; + +use crate::{StyleSheetLike, embed::CssEmbed}; + +#[turbo_tasks::value(into = "new")] +pub enum ReferencedAsset { + Some(Vc>), + None, +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct UrlAssetReference { + pub origin:Vc>, + pub request:Vc, + pub issue_source:Vc, +} + +#[turbo_tasks::value_impl] +impl UrlAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + issue_source:Vc, + ) -> Vc { + Self::cell(UrlAssetReference { origin, request, issue_source }) + } + + #[turbo_tasks::function] + async fn get_referenced_asset( + self: Vc, + chunking_context:Vc>, + ) -> Result> { + if let Some(module) = *self.resolve_reference().first_module().await? { + if let Some(chunkable) = + Vc::try_resolve_downcast::>(module).await? + { + let chunk_item = chunkable.as_chunk_item(chunking_context); + if let Some(embeddable) = + Vc::try_resolve_downcast::>(chunk_item).await? + { + return Ok(ReferencedAsset::Some(embeddable.embedded_asset()).into()); + } + } + bail!( + "A module referenced by a url() reference must be chunkable and the chunk item \ + must be css embeddable\nreferenced module: {:?}", + module.dbg_depth(1).await? + ) + } + Ok(ReferencedAsset::cell(ReferencedAsset::None)) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for UrlAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + url_resolve( + self.origin, + self.request, + Value::new(ReferenceType::Url(UrlReferenceSubType::CssUrl)), + Some(self.issue_source), + IssueSeverity::Error.cell(), + ) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for UrlAssetReference { + #[turbo_tasks::function] + fn chunking_type(self: Vc) -> Vc { + // Since this chunk item is embedded, we don't want to put it in the chunk group + Vc::cell(Some(ChunkingType::Passthrough)) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for UrlAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("url {}", self.request.to_string().await?,).into())) + } +} + +#[turbo_tasks::function] +pub async fn resolve_url_reference( + url:Vc, + chunking_context:Vc>, +) -> Result>> { + let this = url.await?; + // TODO(WEB-662) This is not the correct way to get the current chunk path. It + // currently works as all chunks are in the same directory. + let chunk_path = chunking_context + .chunk_path(AssetIdent::from_path(this.origin.origin_path()), ".css".into()); + let context_path = chunk_path.parent().await?; + + if let ReferencedAsset::Some(asset) = &*url.get_referenced_asset(chunking_context).await? { + // TODO(WEB-662) This is not the correct way to get the path of the asset. + // `asset` is on module-level, but we need the output-level asset instead. + let path = asset.ident().path().await?; + let relative_path = context_path + .get_relative_path_to(&path) + .unwrap_or_else(|| format!("/{}", path.path).into()); + + return Ok(Vc::cell(Some(relative_path))); + } + + Ok(Vc::cell(None)) +} + +pub fn replace_url_references( + ss:&mut StyleSheetLike<'static, 'static>, + urls:&HashMap, +) { + let mut replacer = AssetReferenceReplacer { urls }; + match ss { + StyleSheetLike::LightningCss(ss) => { + ss.visit(&mut replacer).unwrap(); + }, + StyleSheetLike::Swc { stylesheet, .. } => { + stylesheet.visit_mut_with(&mut replacer); + }, + } +} + +struct AssetReferenceReplacer<'a> { + urls:&'a HashMap, +} + +impl VisitMut for AssetReferenceReplacer<'_> { + fn visit_mut_url_value(&mut self, u:&mut UrlValue) { + u.visit_mut_children_with(self); + + match u { + UrlValue::Str(v) => { + if let Some(new) = self.urls.get(&*v.value) { + v.value = (&**new).into(); + v.raw = None; + } + }, + UrlValue::Raw(v) => { + if let Some(new) = self.urls.get(&*v.value) { + v.value = (&**new).into(); + v.raw = None; + } + }, + } + } +} + +impl<'i> Visitor<'i> for AssetReferenceReplacer<'_> { + type Error = Infallible; + + fn visit_types(&self) -> lightningcss::visitor::VisitTypes { visit_types!(URLS) } + + fn visit_url(&mut self, u:&mut Url) -> std::result::Result<(), Self::Error> { + u.visit_children(self)?; + + if let Some(new) = self.urls.get(&*u.url) { + u.url = new.to_string().into(); + } + + Ok(()) + } +} diff --git a/crates/turbopack-css/Source/util.rs b/crates/turbopack-css/Source/util.rs new file mode 100644 index 0000000000000..b6d84567dcb30 --- /dev/null +++ b/crates/turbopack-css/Source/util.rs @@ -0,0 +1,53 @@ +pub fn stringify_js(str:&str) -> String { + let mut escaped = String::with_capacity(str.len()); + for char in str.chars() { + match char { + // Escape the following characters required for strings by the CSS scanner: + // https://www.w3.org/TR/CSS21/grammar.html#scanner + // https://github.com/vercel/turbo/pull/2598#discussion_r1022625909 + // + // Note that the form feed character is not representable as \f in Rust strings, so + // the unicode representation \u{0c} is used. + '\\' => escaped.push_str(r"\\"), + '\n' => escaped.push_str(r"\n"), + '\r' => escaped.push_str(r"\r"), + '"' => escaped.push_str(r#"\""#), + '\u{0c}' => escaped.push_str(r"\f"), + _ => escaped.push(char), + } + } + + format!("\"{}\"", escaped) +} + +#[cfg(test)] +mod tests { + use crate::util::stringify_js; + + #[test] + fn surrounds_with_double_quotes() { + assert_eq!(stringify_js("foo"), r#""foo""#); + } + + #[test] + fn escapes_double_quotes() { + assert_eq!(stringify_js(r#""""#), r#""\"\"""#); + } + + #[test] + fn escapes_backslash() { + assert_eq!(stringify_js(r"\"), r#""\\""#); + assert_eq!(stringify_js(r"\\"), r#""\\\\""#); + assert_eq!(stringify_js(r"\n"), r#""\\n""#); + } + + #[test] + fn escapes_newlines() { + assert_eq!(stringify_js("\n"), r#""\n""#); + } + + #[test] + fn escapes_mixed() { + assert_eq!(stringify_js("\n\r\u{0c}"), r#""\n\r\f""#); + } +} diff --git a/crates/turbopack-css/build.rs b/crates/turbopack-css/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-css/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-dev-server/Source/html.rs b/crates/turbopack-dev-server/Source/html.rs new file mode 100644 index 0000000000000..b81b69921862a --- /dev/null +++ b/crates/turbopack-dev-server/Source/html.rs @@ -0,0 +1,241 @@ +use anyhow::{Result, anyhow}; +use mime_guess::mime::TEXT_HTML_UTF_8; +use turbo_tasks::{RcStr, ReadRef, TryJoinIterExt, Value, Vc}; +use turbo_tasks_fs::{File, FileSystemPath}; +use turbo_tasks_hash::{Xxh3Hash64Hasher, encode_hex}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ + ChunkableModule, + ChunkingContext, + ChunkingContextExt, + EvaluatableAssets, + availability_info::AvailabilityInfo, + }, + ident::AssetIdent, + module::Module, + output::{OutputAsset, OutputAssets}, + version::{Version, VersionedContent}, +}; + +// TODO(WEB-945) This should become a struct once we have a +// `turbo_tasks::input` attribute macro/`Input` derive macro. +type DevHtmlEntry = ( + Vc>, + Vc>, + Option>, +); + +/// The HTML entry point of the dev server. +/// +/// Generates an HTML page that includes the ES and CSS chunks. +#[turbo_tasks::value(shared)] +#[derive(Clone)] +pub struct DevHtmlAsset { + path:Vc, + entries:Vec, + body:Option, +} + +#[turbo_tasks::function] +fn dev_html_chunk_reference_description() -> Vc { Vc::cell("dev html chunk".into()) } + +#[turbo_tasks::value_impl] +impl OutputAsset for DevHtmlAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { AssetIdent::from_path(self.path) } + + #[turbo_tasks::function] + fn references(self: Vc) -> Vc { self.chunks() } +} + +#[turbo_tasks::value_impl] +impl Asset for DevHtmlAsset { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { self.html_content().content() } + + #[turbo_tasks::function] + fn versioned_content(self: Vc) -> Vc> { + Vc::upcast(self.html_content()) + } +} + +impl DevHtmlAsset { + /// Create a new dev HTML asset. + pub fn new(path:Vc, entries:Vec) -> Vc { + DevHtmlAsset { path, entries, body:None }.cell() + } + + /// Create a new dev HTML asset. + pub fn new_with_body( + path:Vc, + entries:Vec, + body:RcStr, + ) -> Vc { + DevHtmlAsset { path, entries, body:Some(body) }.cell() + } +} + +#[turbo_tasks::value_impl] +impl DevHtmlAsset { + #[turbo_tasks::function] + pub async fn with_path(self: Vc, path:Vc) -> Result> { + let mut html:DevHtmlAsset = self.await?.clone_value(); + html.path = path; + Ok(html.cell()) + } + + #[turbo_tasks::function] + pub async fn with_body(self: Vc, body:RcStr) -> Result> { + let mut html:DevHtmlAsset = self.await?.clone_value(); + html.body = Some(body); + Ok(html.cell()) + } +} + +#[turbo_tasks::value_impl] +impl DevHtmlAsset { + #[turbo_tasks::function] + async fn html_content(self: Vc) -> Result> { + let this = self.await?; + let context_path = this.path.parent().await?; + let mut chunk_paths = vec![]; + for chunk in &*self.chunks().await? { + let chunk_path = &*chunk.ident().path().await?; + if let Some(relative_path) = context_path.get_path_to(chunk_path) { + chunk_paths.push(format!("/{relative_path}").into()); + } + } + + Ok(DevHtmlAssetContent::new(chunk_paths, this.body.clone())) + } + + #[turbo_tasks::function] + async fn chunks(self: Vc) -> Result> { + let this = self.await?; + + let all_assets = this + .entries + .iter() + .map(|entry| { + async move { + let &(chunkable_module, chunking_context, runtime_entries) = entry; + + let assets = if let Some(runtime_entries) = runtime_entries { + let runtime_entries = if let Some(evaluatable) = + Vc::try_resolve_downcast(chunkable_module).await? + { + runtime_entries.with_entry(evaluatable) + } else { + runtime_entries + }; + chunking_context.evaluated_chunk_group_assets( + chunkable_module.ident(), + runtime_entries, + Value::new(AvailabilityInfo::Root), + ) + } else { + chunking_context.root_chunk_group_assets(Vc::upcast(chunkable_module)) + }; + + assets.await + } + }) + .try_join() + .await? + .iter() + .flatten() + .copied() + .collect(); + + Ok(Vc::cell(all_assets)) + } +} + +#[turbo_tasks::value] +struct DevHtmlAssetContent { + chunk_paths:Vec, + body:Option, +} + +impl DevHtmlAssetContent { + fn new(chunk_paths:Vec, body:Option) -> Vc { + DevHtmlAssetContent { chunk_paths, body }.cell() + } +} + +#[turbo_tasks::value_impl] +impl DevHtmlAssetContent { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let this = self.await?; + + let mut scripts = Vec::new(); + let mut stylesheets = Vec::new(); + + for relative_path in &*this.chunk_paths { + if relative_path.ends_with(".js") { + scripts.push(format!("", relative_path)); + } else if relative_path.ends_with(".css") { + stylesheets.push(format!( + "", + relative_path + )); + } else { + return Err(anyhow!("chunk with unknown asset type: {}", relative_path)); + } + } + + let body = match &this.body { + Some(body) => body.as_str(), + None => "", + }; + + let html:RcStr = format!( + "\n\n\n{}\n\n\n{}\n{}\n\n", + stylesheets.join("\n"), + body, + scripts.join("\n"), + ) + .into(); + + Ok(AssetContent::file(File::from(html).with_content_type(TEXT_HTML_UTF_8).into())) + } + + #[turbo_tasks::function] + async fn version(self: Vc) -> Result> { + let this = self.await?; + Ok(DevHtmlAssetVersion { content:this }.cell()) + } +} + +#[turbo_tasks::value_impl] +impl VersionedContent for DevHtmlAssetContent { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { self.content() } + + #[turbo_tasks::function] + fn version(self: Vc) -> Vc> { Vc::upcast(self.version()) } +} + +#[turbo_tasks::value] +struct DevHtmlAssetVersion { + content:ReadRef, +} + +#[turbo_tasks::value_impl] +impl Version for DevHtmlAssetVersion { + #[turbo_tasks::function] + async fn id(&self) -> Result> { + let mut hasher = Xxh3Hash64Hasher::new(); + for relative_path in &*self.content.chunk_paths { + hasher.write_ref(relative_path); + } + if let Some(body) = &self.content.body { + hasher.write_ref(body); + } + let hash = hasher.finish(); + let hex_hash = encode_hex(hash); + Ok(Vc::cell(hex_hash.into())) + } +} diff --git a/crates/turbopack-dev-server/Source/http.rs b/crates/turbopack-dev-server/Source/http.rs new file mode 100644 index 0000000000000..06c14310f0052 --- /dev/null +++ b/crates/turbopack-dev-server/Source/http.rs @@ -0,0 +1,238 @@ +use std::io::{Error, ErrorKind}; + +use anyhow::{Result, anyhow}; +use auto_hash_map::AutoSet; +use futures::{StreamExt, TryStreamExt}; +use hyper::{ + Request, + Response, + header::{CONTENT_ENCODING, CONTENT_LENGTH, HeaderName}, + http::HeaderValue, +}; +use mime::Mime; +use tokio_util::io::{ReaderStream, StreamReader}; +use turbo_tasks::{CollectiblesSource, ReadRef, TransientInstance, Vc, util::SharedError}; +use turbo_tasks_bytes::Bytes; +use turbo_tasks_fs::FileContent; +use turbopack_core::{ + asset::AssetContent, + issue::{IssueReporter, IssueSeverity, handle_issues}, + version::VersionedContent, +}; + +use crate::source::{ + Body, + ContentSource, + ContentSourceSideEffect, + HeaderList, + ProxyResult, + request::SourceRequest, + resolve::{ResolveSourceRequestResult, resolve_source_request}, +}; + +#[turbo_tasks::value(serialization = "none")] +enum GetFromSourceResult { + Static { + content:ReadRef, + status_code:u16, + headers:ReadRef, + header_overwrites:ReadRef, + }, + HttpProxy(ReadRef), + NotFound, +} + +/// Resolves a [SourceRequest] within a [super::ContentSource], returning the +/// corresponding content as a +#[turbo_tasks::function] +async fn get_from_source( + source:Vc>, + request:TransientInstance, +) -> Result> { + Ok(match &*resolve_source_request(source, request).await? { + ResolveSourceRequestResult::Static(static_content_vc, header_overwrites) => { + let static_content = static_content_vc.await?; + if let AssetContent::File(file) = &*static_content.content.content().await? { + GetFromSourceResult::Static { + content:file.await?, + status_code:static_content.status_code, + headers:static_content.headers.await?, + header_overwrites:header_overwrites.await?, + } + } else { + GetFromSourceResult::NotFound + } + }, + ResolveSourceRequestResult::HttpProxy(proxy) => { + GetFromSourceResult::HttpProxy(proxy.await?) + }, + ResolveSourceRequestResult::NotFound => GetFromSourceResult::NotFound, + } + .cell()) +} + +/// Processes an HTTP request within a given content source and returns the +/// response. +pub async fn process_request_with_content_source( + source:Vc>, + request:Request, + issue_reporter:Vc>, +) -> Result<(Response, AutoSet>>)> { + let original_path = request.uri().path().to_string(); + let request = http_request_to_source_request(request).await?; + let result = get_from_source(source, TransientInstance::new(request)); + let resolved_result = result.resolve_strongly_consistent().await?; + let side_effects:AutoSet>> = result.peek_collectibles(); + handle_issues( + result, + issue_reporter, + IssueSeverity::Fatal.cell(), + Some(&original_path), + Some("get_from_source"), + ) + .await?; + match &*resolved_result.await? { + GetFromSourceResult::Static { content, status_code, headers, header_overwrites } => { + if let FileContent::Content(file) = &**content { + let mut response = Response::builder().status(*status_code); + + let header_map = response.headers_mut().expect("headers must be defined"); + + for (header_name, header_value) in headers { + header_map.append( + HeaderName::try_from(header_name.as_str())?, + hyper::header::HeaderValue::try_from(header_value.as_str())?, + ); + } + + for (header_name, header_value) in header_overwrites.iter() { + header_map.insert( + HeaderName::try_from(header_name.as_str())?, + hyper::header::HeaderValue::try_from(header_value.as_str())?, + ); + } + + // naively checking if content is `compressible`. + let mut should_compress = false; + let should_compress_predicate = |mime:&Mime| { + matches!( + (mime.type_(), mime.subtype(), mime.suffix()), + (_, mime::PLAIN, _) + | (_, mime::JSON, _) | (mime::TEXT, _, _) + | (mime::APPLICATION, mime::XML, _) + | (mime::APPLICATION, mime::JAVASCRIPT, _) + | (_, _, Some(mime::XML)) + | (_, _, Some(mime::JSON)) + | (_, _, Some(mime::TEXT)) + ) + }; + + if let Some(content_type) = file.content_type() { + header_map.append( + "content-type", + hyper::header::HeaderValue::try_from(content_type.to_string())?, + ); + + should_compress = should_compress_predicate(content_type); + } else if let hyper::header::Entry::Vacant(entry) = header_map.entry("content-type") + { + let guess = mime_guess::from_path(&original_path).first_or_octet_stream(); + should_compress = should_compress_predicate(&guess); + // If a text type, application/javascript, or application/json was + // guessed, use a utf-8 charset as we most likely generated it as + // such. + entry.insert(hyper::header::HeaderValue::try_from( + if (guess.type_() == mime::TEXT + || guess.subtype() == mime::JAVASCRIPT + || guess.subtype() == mime::JSON) + && guess.get_param("charset").is_none() + { + guess.to_string() + "; charset=utf-8" + } else { + guess.to_string() + }, + )?); + } + + if !header_map.contains_key("cache-control") { + // The dev server contents might change at any time, we can't cache them. + header_map.append( + "cache-control", + hyper::header::HeaderValue::try_from("must-revalidate")?, + ); + } + + let content = file.content(); + let response = if should_compress { + header_map.insert(CONTENT_ENCODING, HeaderValue::from_static("gzip")); + + // Grab ropereader stream, coerce anyhow::Error to std::io::Error + let stream_ext = content + .read() + .into_stream() + .map_err(|err| Error::new(ErrorKind::Other, err)); + + let gzipped_stream = + ReaderStream::new(async_compression::tokio::bufread::GzipEncoder::new( + StreamReader::new(stream_ext), + )); + + response.body(hyper::Body::wrap_stream(gzipped_stream))? + } else { + header_map.insert( + CONTENT_LENGTH, + hyper::header::HeaderValue::try_from(content.len().to_string())?, + ); + + response.body(hyper::Body::wrap_stream(content.read()))? + }; + + return Ok((response, side_effects)); + } + }, + GetFromSourceResult::HttpProxy(proxy_result) => { + let mut response = Response::builder().status(proxy_result.status); + let headers = response.headers_mut().expect("headers must be defined"); + + for (name, value) in &proxy_result.headers { + headers.append( + HeaderName::from_bytes(name.as_bytes())?, + hyper::header::HeaderValue::from_str(value)?, + ); + } + + return Ok(( + response.body(hyper::Body::wrap_stream(proxy_result.body.read()))?, + side_effects, + )); + }, + GetFromSourceResult::NotFound => {}, + } + + Ok((Response::builder().status(404).body(hyper::Body::empty())?, side_effects)) +} + +async fn http_request_to_source_request(request:Request) -> Result { + let (parts, body) = request.into_parts(); + + // For simplicity, we fully consume the body now and early return if there were + // any errors. + let bytes:Vec<_> = body + .map(|bytes| { + bytes.map_or_else( + |e| Err(SharedError::new(anyhow!(e))), + // The outer Ok is consumed by try_collect, but the Body type requires a Result, so + // we need to double wrap. + |b| Ok(Ok(Bytes::from(b))), + ) + }) + .try_collect::>() + .await?; + + Ok(SourceRequest { + method:parts.method.to_string(), + uri:parts.uri, + headers:parts.headers, + body:Body::new(bytes), + }) +} diff --git a/crates/turbopack-dev-server/Source/introspect/mod.rs b/crates/turbopack-dev-server/Source/introspect/mod.rs new file mode 100644 index 0000000000000..bc34bfe1f0d38 --- /dev/null +++ b/crates/turbopack-dev-server/Source/introspect/mod.rs @@ -0,0 +1,171 @@ +use std::{borrow::Cow, collections::HashSet, fmt::Display}; + +use anyhow::Result; +use turbo_tasks::{RcStr, ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::{File, json::parse_json_with_source_context}; +use turbopack_core::{ + asset::AssetContent, + introspect::{Introspectable, IntrospectableChildren}, + version::VersionedContentExt, +}; +use turbopack_ecmascript::utils::FormatIter; + +use crate::source::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + GetContentSourceContent, + route_tree::{RouteTree, RouteTrees, RouteType}, +}; + +#[turbo_tasks::value(shared)] +pub struct IntrospectionSource { + pub roots:HashSet>>, +} + +#[turbo_tasks::value_impl] +impl Introspectable for IntrospectionSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { Vc::cell("introspection-source".into()) } + + #[turbo_tasks::function] + fn title(&self) -> Vc { Vc::cell("introspection-source".into()) } + + #[turbo_tasks::function] + fn children(&self) -> Vc { + let name = Vc::cell("root".into()); + Vc::cell(self.roots.iter().map(|root| (name, *root)).collect()) + } +} + +struct HtmlEscaped(T); + +impl Display for HtmlEscaped { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str( + &self + .0 + .to_string() + // TODO this is pretty inefficient + .replace('&', "&") + .replace('>', ">") + .replace('<', "<"), + ) + } +} + +struct HtmlStringEscaped(T); + +impl Display for HtmlStringEscaped { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str( + &self + .0 + .to_string() + // TODO this is pretty inefficient + .replace('&', "&") + .replace('"', """) + .replace('>', ">") + .replace('<', "<"), + ) + } +} + +#[turbo_tasks::value_impl] +impl ContentSource for IntrospectionSource { + #[turbo_tasks::function] + fn get_routes(self: Vc) -> Vc { + Vc::::cell(vec![ + RouteTree::new_route(Vec::new(), RouteType::Exact, Vc::upcast(self)), + RouteTree::new_route(Vec::new(), RouteType::CatchAll, Vc::upcast(self)), + ]) + .merge() + } +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for IntrospectionSource { + #[turbo_tasks::function] + async fn get( + self: Vc, + path:RcStr, + _data:turbo_tasks::Value, + ) -> Result> { + // get last segment + let path = &path[path.rfind('/').unwrap_or(0) + 1..]; + let introspectable = if path.is_empty() { + let roots = &self.await?.roots; + if roots.len() == 1 { *roots.iter().next().unwrap() } else { Vc::upcast(self) } + } else { + parse_json_with_source_context(path)? + }; + let internal_ty = Vc::debug_identifier(introspectable).await?; + fn str_or_err(s:&Result>) -> Cow<'_, str> { + s.as_ref().map_or_else( + |e| Cow::<'_, str>::Owned(format!("ERROR: {:?}", e)), + |d| Cow::Borrowed(&**d), + ) + } + let ty = introspectable.ty().await; + let ty = str_or_err(&ty); + let title = introspectable.title().await; + let title = str_or_err(&title); + let details = introspectable.details().await; + let details = str_or_err(&details); + let children = introspectable.children().await?; + let has_children = !children.is_empty(); + let children = children + .iter() + .map(|&(name, child)| { + async move { + let name = name.await; + let name = str_or_err(&name); + let ty = child.ty().await; + let ty = str_or_err(&ty); + let title = child.title().await; + let title = str_or_err(&title); + let path = serde_json::to_string(&child)?; + Ok(format!( + "

  • {name} [{ty}] {title}
  • ", + name = HtmlEscaped(name), + title = HtmlEscaped(title), + path = HtmlStringEscaped(urlencoding::encode(&path)), + ty = HtmlEscaped(ty), + )) + } + }) + .try_join() + .await?; + let details = if details.is_empty() { + String::new() + } else if has_children { + format!( + "

    Details

    {details}
    ", + details = HtmlEscaped(details) + ) + } else { + format!("

    Details

    {details}
    ", details = HtmlEscaped(details)) + }; + let html:RcStr = format!( + " + {title} + +

    {internal_ty}

    +

    {ty}

    +

    {title}

    + {details} +
      {children}
    + + ", + title = HtmlEscaped(title), + ty = HtmlEscaped(ty), + children = FormatIter(|| children.iter()) + ) + .into(); + Ok(ContentSourceContent::static_content( + AssetContent::file(File::from(html).with_content_type(mime::TEXT_HTML_UTF_8).into()) + .versioned(), + )) + } +} diff --git a/crates/turbopack-dev-server/Source/invalidation.rs b/crates/turbopack-dev-server/Source/invalidation.rs new file mode 100644 index 0000000000000..116cb1f3f1a0c --- /dev/null +++ b/crates/turbopack-dev-server/Source/invalidation.rs @@ -0,0 +1,91 @@ +use std::fmt::{Display, Formatter}; + +use hyper::{Method, Uri}; +use indexmap::IndexSet; +use turbo_tasks::{InvalidationReason, InvalidationReasonKind, util::StaticOrArc}; + +/// Computation was caused by a request to the server. +#[derive(PartialEq, Eq, Hash)] +pub struct ServerRequest { + pub method:Method, + pub uri:Uri, +} + +impl InvalidationReason for ServerRequest { + fn kind(&self) -> Option> { + Some(StaticOrArc::Static(&SERVER_REQUEST_KIND)) + } +} + +impl Display for ServerRequest { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{} {}", self.method, self.uri.path()) + } +} + +/// Invalidation kind for [ServerRequest] +#[derive(PartialEq, Eq, Hash)] +struct ServerRequestKind; + +static SERVER_REQUEST_KIND:ServerRequestKind = ServerRequestKind; + +impl InvalidationReasonKind for ServerRequestKind { + fn fmt( + &self, + reasons:&IndexSet>, + f:&mut Formatter<'_>, + ) -> std::fmt::Result { + let example = reasons + .into_iter() + .map(|reason| reason.as_any().downcast_ref::().unwrap()) + .min_by_key(|reason| reason.uri.path().len()) + .unwrap(); + write!(f, "{} requests ({} {}, ...)", reasons.len(), example.method, example.uri.path()) + } +} + +/// Side effect that was caused by a request to the server. +#[derive(PartialEq, Eq, Hash)] +pub struct ServerRequestSideEffects { + pub method:Method, + pub uri:Uri, +} + +impl InvalidationReason for ServerRequestSideEffects { + fn kind(&self) -> Option> { + Some(StaticOrArc::Static(&SERVER_REQUEST_SIDE_EFFECTS_KIND)) + } +} + +impl Display for ServerRequestSideEffects { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + write!(f, "side effects of {} {}", self.method, self.uri.path()) + } +} + +/// Invalidation kind for [ServerRequestSideEffects] +#[derive(PartialEq, Eq, Hash)] +struct ServerRequestSideEffectsKind; + +static SERVER_REQUEST_SIDE_EFFECTS_KIND:ServerRequestSideEffectsKind = ServerRequestSideEffectsKind; + +impl InvalidationReasonKind for ServerRequestSideEffectsKind { + fn fmt( + &self, + reasons:&IndexSet>, + f:&mut Formatter<'_>, + ) -> std::fmt::Result { + let example = reasons + .into_iter() + .map(|reason| reason.as_any().downcast_ref::().unwrap()) + .min_by_key(|reason| reason.uri.path().len()) + .unwrap(); + write!( + f, + "side effects of {} requests ({} {}, ...)", + reasons.len(), + example.method, + example.uri.path() + ) + } +} diff --git a/crates/turbopack-dev-server/Source/lib.rs b/crates/turbopack-dev-server/Source/lib.rs new file mode 100644 index 0000000000000..b34c8ff57d531 --- /dev/null +++ b/crates/turbopack-dev-server/Source/lib.rs @@ -0,0 +1,300 @@ +#![feature(min_specialization)] +#![feature(trait_alias)] +#![feature(array_chunks)] +#![feature(iter_intersperse)] +#![feature(str_split_remainder)] +#![feature(arbitrary_self_types)] + +pub mod html; +mod http; +pub mod introspect; +mod invalidation; +pub mod source; +pub mod update; + +use std::{ + collections::VecDeque, + future::Future, + net::{SocketAddr, TcpListener}, + pin::Pin, + sync::Arc, + time::{Duration, Instant}, +}; + +use anyhow::{Context, Result}; +use hyper::{ + Request, + Response, + Server, + server::{Builder, conn::AddrIncoming}, + service::{make_service_fn, service_fn}, +}; +use parking_lot::Mutex; +use socket2::{Domain, Protocol, Socket, Type}; +use tokio::task::JoinHandle; +use tracing::{Instrument, Level, Span, event, info_span}; +use turbo_tasks::{ + TurboTasksApi, + Vc, + run_once_with_reason, + trace::TraceRawVcs, + util::FormatDuration, +}; +use turbopack_core::{ + error::PrettyPrintError, + issue::{IssueReporter, IssueSeverity, handle_issues}, +}; + +use self::{source::ContentSource, update::UpdateServer}; +use crate::{ + invalidation::{ServerRequest, ServerRequestSideEffects}, + source::ContentSourceSideEffect, +}; + +pub trait SourceProvider: Send + Clone + 'static { + /// must call a turbo-tasks function internally + fn get_source(&self) -> Vc>; +} + +impl SourceProvider for T +where + T: Fn() -> Vc> + Send + Clone + 'static, +{ + fn get_source(&self) -> Vc> { self() } +} + +#[derive(TraceRawVcs, Debug)] +pub struct DevServerBuilder { + #[turbo_tasks(trace_ignore)] + pub addr:SocketAddr, + #[turbo_tasks(trace_ignore)] + server:Builder, +} + +#[derive(TraceRawVcs)] +pub struct DevServer { + #[turbo_tasks(trace_ignore)] + pub addr:SocketAddr, + #[turbo_tasks(trace_ignore)] + pub future:Pin> + Send + 'static>>, +} + +impl DevServer { + pub fn listen(addr:SocketAddr) -> Result { + // This is annoying. The hyper::Server doesn't allow us to know which port was + // bound (until we build it with a request handler) when using the standard + // `server::try_bind` approach. This is important when binding the `0` port, + // because the OS will remap that to an actual free port, and we need to know + // that port before we build the request handler. So we need to construct a + // real TCP listener, see if it bound, and get its bound address. + let socket = Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP)) + .context("unable to create socket")?; + // Allow the socket to be reused immediately after closing. This ensures that + // the dev server can be restarted on the same address without a buffer time for + // the OS to release the socket. + // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse + #[cfg(not(windows))] + let _ = socket.set_reuse_address(true); + if matches!(addr, SocketAddr::V6(_)) { + // When possible bind to v4 and v6, otherwise ignore the error + let _ = socket.set_only_v6(false); + } + let sock_addr = addr.into(); + socket.bind(&sock_addr).context("not able to bind address")?; + socket.listen(128).context("not able to listen on socket")?; + + let listener:TcpListener = socket.into(); + let addr = listener.local_addr().context("not able to get bound address")?; + let server = Server::from_tcp(listener).context("Not able to start server")?; + Ok(DevServerBuilder { addr, server }) + } +} + +impl DevServerBuilder { + pub fn serve( + self, + turbo_tasks:Arc, + source_provider:impl SourceProvider + Sync, + get_issue_reporter:Arc Vc> + Send + Sync>, + ) -> DevServer { + let ongoing_side_effects = Arc::new(Mutex::new(VecDeque::< + Arc>>>>, + >::with_capacity(16))); + let make_svc = make_service_fn(move |_| { + let tt = turbo_tasks.clone(); + let source_provider = source_provider.clone(); + let get_issue_reporter = get_issue_reporter.clone(); + let ongoing_side_effects = ongoing_side_effects.clone(); + async move { + let handler = move |request:Request| { + let request_span = info_span!(parent: None, "request", name = ?request.uri()); + let start = Instant::now(); + let tt = tt.clone(); + let get_issue_reporter = get_issue_reporter.clone(); + let ongoing_side_effects = ongoing_side_effects.clone(); + let source_provider = source_provider.clone(); + let future = async move { + event!(parent: Span::current(), Level::DEBUG, "request start"); + // Wait until all ongoing side effects are completed + // We only need to wait for the ongoing side effects that were started + // before this request. Later added side effects are not relevant for this. + let current_ongoing_side_effects = { + // Cleanup the ongoing_side_effects list + let mut guard = ongoing_side_effects.lock(); + while let Some(front) = guard.front() { + let Ok(front_guard) = front.try_lock() else { + break; + }; + if front_guard.is_some() { + break; + } + drop(front_guard); + guard.pop_front(); + } + // Get a clone of the remaining list + (*guard).clone() + }; + // Wait for the side effects to complete + for side_effect_mutex in current_ongoing_side_effects { + let mut guard = side_effect_mutex.lock().await; + if let Some(join_handle) = guard.take() { + join_handle.await??; + } + drop(guard); + } + let reason = ServerRequest { + method:request.method().clone(), + uri:request.uri().clone(), + }; + let side_effects_reason = ServerRequestSideEffects { + method:request.method().clone(), + uri:request.uri().clone(), + }; + run_once_with_reason(tt.clone(), reason, async move { + let issue_reporter = get_issue_reporter(); + + if hyper_tungstenite::is_upgrade_request(&request) { + let uri = request.uri(); + let path = uri.path(); + + if path == "/turbopack-hmr" { + let (response, websocket) = + hyper_tungstenite::upgrade(request, None)?; + let update_server = + UpdateServer::new(source_provider, issue_reporter); + update_server.run(&*tt, websocket); + return Ok(response); + } + + println!("[404] {} (WebSocket)", path); + if path == "/_next/webpack-hmr" { + // Special-case requests to webpack-hmr as these are made by + // Next.js clients built + // without turbopack, which may be making requests in + // development. + println!( + "A non-turbopack next.js client is trying to connect." + ); + println!( + "Make sure to reload/close any browser window which has \ + been opened without --turbo." + ); + } + + return Ok(Response::builder() + .status(404) + .body(hyper::Body::empty())?); + } + + let uri = request.uri(); + let path = uri.path().to_string(); + let source = source_provider.get_source(); + let resolved_source = source.resolve_strongly_consistent().await?; + handle_issues( + source, + issue_reporter, + IssueSeverity::Fatal.cell(), + Some(&path), + Some("get source"), + ) + .await?; + let (response, side_effects) = + http::process_request_with_content_source( + resolved_source, + request, + issue_reporter, + ) + .await?; + let status = response.status().as_u16(); + let is_error = response.status().is_client_error() + || response.status().is_server_error(); + let elapsed = start.elapsed(); + if is_error + || (cfg!(feature = "log_request_stats") + && elapsed > Duration::from_secs(1)) + { + println!( + "[{status}] {path} ({duration})", + duration = FormatDuration(elapsed) + ); + } + if !side_effects.is_empty() { + let join_handle = tokio::spawn(run_once_with_reason( + tt.clone(), + side_effects_reason, + async move { + for side_effect in side_effects { + side_effect.apply().await?; + } + Ok(()) + }, + )); + ongoing_side_effects.lock().push_back(Arc::new( + tokio::sync::Mutex::new(Some(join_handle)), + )); + } + Ok(response) + }) + .await + }; + async move { + match future.await { + Ok(r) => Ok::<_, hyper::http::Error>(r), + Err(e) => { + println!( + "[500] error ({}): {}", + FormatDuration(start.elapsed()), + PrettyPrintError(&e), + ); + Ok(Response::builder() + .status(500) + .body(hyper::Body::from(format!("{}", PrettyPrintError(&e))))?) + }, + } + } + .instrument(request_span) + }; + anyhow::Ok(service_fn(handler)) + } + }); + let server = self.server.serve(make_svc); + + DevServer { + addr:self.addr, + future:Box::pin(async move { + server.await?; + Ok(()) + }), + } + } +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_bytes::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_cli_utils::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-dev-server/Source/source/asset_graph.rs b/crates/turbopack-dev-server/Source/source/asset_graph.rs new file mode 100644 index 0000000000000..eef4cd8d3e969 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/asset_graph.rs @@ -0,0 +1,349 @@ +use std::{ + collections::{HashSet, VecDeque}, + iter::once, +}; + +use anyhow::Result; +use indexmap::{IndexMap, IndexSet, indexset}; +use turbo_tasks::{Completion, RcStr, State, TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + asset::Asset, + introspect::{Introspectable, IntrospectableChildren, output_asset::IntrospectableOutputAsset}, + output::{OutputAsset, OutputAssetsSet}, +}; + +use super::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + ContentSourceSideEffect, + GetContentSourceContent, + route_tree::{BaseSegment, RouteTree, RouteTrees, RouteType}, +}; + +#[turbo_tasks::value(transparent)] +struct OutputAssetsMap(IndexMap>>); + +type ExpandedState = State>; + +#[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")] +pub struct AssetGraphContentSource { + root_path:Vc, + root_assets:Vc, + expanded:Option, +} + +#[turbo_tasks::value_impl] +impl AssetGraphContentSource { + /// Serves all assets references by root_asset. + #[turbo_tasks::function] + pub fn new_eager( + root_path:Vc, + root_asset:Vc>, + ) -> Vc { + Self::cell(AssetGraphContentSource { + root_path, + root_assets:Vc::cell(indexset! { root_asset }), + expanded:None, + }) + } + + /// Serves all assets references by root_asset. Only serve references of an + /// asset when it has served its content before. + #[turbo_tasks::function] + pub fn new_lazy(root_path:Vc, root_asset:Vc>) -> Vc { + Self::cell(AssetGraphContentSource { + root_path, + root_assets:Vc::cell(indexset! { root_asset }), + expanded:Some(State::new(HashSet::new())), + }) + } + + /// Serves all assets references by all root_assets. + #[turbo_tasks::function] + pub fn new_eager_multiple( + root_path:Vc, + root_assets:Vc, + ) -> Vc { + Self::cell(AssetGraphContentSource { root_path, root_assets, expanded:None }) + } + + /// Serves all assets references by all root_assets. Only serve references + /// of an asset when it has served its content before. + #[turbo_tasks::function] + pub fn new_lazy_multiple( + root_path:Vc, + root_assets:Vc, + ) -> Vc { + Self::cell(AssetGraphContentSource { + root_path, + root_assets, + expanded:Some(State::new(HashSet::new())), + }) + } + + #[turbo_tasks::function] + async fn all_assets_map(self: Vc) -> Result> { + let this = self.await?; + Ok(Vc::cell( + expand(&*this.root_assets.await?, &*this.root_path.await?, this.expanded.as_ref()) + .await?, + )) + } +} + +async fn expand( + root_assets:&IndexSet>>, + root_path:&FileSystemPath, + expanded:Option<&ExpandedState>, +) -> Result>>> { + let mut map = IndexMap::new(); + let mut assets = Vec::new(); + let mut queue = VecDeque::with_capacity(32); + let mut assets_set = HashSet::new(); + let root_assets_with_path = root_assets + .iter() + .map(|&asset| { + async move { + let path = asset.ident().path().await?; + Ok((path, asset)) + } + }) + .try_join() + .await?; + + if let Some(expanded) = &expanded { + let expanded = expanded.get(); + for (path, root_asset) in root_assets_with_path.into_iter() { + if let Some(sub_path) = root_path.get_path_to(&path) { + let (sub_paths_buffer, sub_paths) = get_sub_paths(sub_path); + let expanded = sub_paths_buffer + .iter() + .take(sub_paths) + .any(|sub_path| expanded.contains(sub_path)); + for sub_path in sub_paths_buffer.into_iter().take(sub_paths) { + assets.push((sub_path, root_asset)); + } + assets_set.insert(root_asset); + if expanded { + queue.push_back(root_asset.references()); + } + } + } + } else { + for (path, root_asset) in root_assets_with_path.into_iter() { + if let Some(sub_path) = root_path.get_path_to(&path) { + let (sub_paths_buffer, sub_paths) = get_sub_paths(sub_path); + for sub_path in sub_paths_buffer.into_iter().take(sub_paths) { + assets.push((sub_path, root_asset)); + } + queue.push_back(root_asset.references()); + assets_set.insert(root_asset); + } + } + } + + while let Some(references) = queue.pop_front() { + for asset in references.await?.iter() { + if assets_set.insert(*asset) { + let path = asset.ident().path().await?; + if let Some(sub_path) = root_path.get_path_to(&path) { + let (sub_paths_buffer, sub_paths) = get_sub_paths(sub_path); + let expanded = if let Some(expanded) = &expanded { + let expanded = expanded.get(); + sub_paths_buffer + .iter() + .take(sub_paths) + .any(|sub_path| expanded.contains(sub_path)) + } else { + true + }; + if expanded { + queue.push_back(asset.references()); + } + for sub_path in sub_paths_buffer.into_iter().take(sub_paths) { + assets.push((sub_path, *asset)); + } + } + } + } + } + for (sub_path, asset) in assets { + let asset = asset.resolve().await?; + if &*sub_path == "index.html" { + map.insert("".into(), asset); + } else if let Some(p) = sub_path.strip_suffix("/index.html") { + map.insert(p.into(), asset); + map.insert(format!("{p}/").into(), asset); + } else if let Some(p) = sub_path.strip_suffix(".html") { + map.insert(p.into(), asset); + } + map.insert(sub_path, asset); + } + Ok(map) +} + +fn get_sub_paths(sub_path:&str) -> ([RcStr; 3], usize) { + let sub_paths_buffer:[RcStr; 3]; + let n = if sub_path == "index.html" { + sub_paths_buffer = ["".into(), sub_path.into(), Default::default()]; + 2 + } else if let Some(p) = sub_path.strip_suffix("/index.html") { + sub_paths_buffer = [p.into(), format!("{p}/").into(), sub_path.into()]; + 3 + } else if let Some(p) = sub_path.strip_suffix(".html") { + sub_paths_buffer = [p.into(), sub_path.into(), Default::default()]; + 2 + } else { + sub_paths_buffer = [sub_path.into(), Default::default(), Default::default()]; + 1 + }; + (sub_paths_buffer, n) +} + +#[turbo_tasks::value_impl] +impl ContentSource for AssetGraphContentSource { + #[turbo_tasks::function] + async fn get_routes(self: Vc) -> Result> { + let assets = self.all_assets_map().strongly_consistent().await?; + let mut paths = Vec::new(); + let routes = assets + .iter() + .map(|(path, asset)| { + paths.push(path.as_str()); + RouteTree::new_route( + BaseSegment::from_static_pathname(path).collect(), + RouteType::Exact, + Vc::upcast(AssetGraphGetContentSourceContent::new(self, path.clone(), *asset)), + ) + }) + .collect(); + Ok(Vc::::cell(routes).merge()) + } +} + +#[turbo_tasks::value] +struct AssetGraphGetContentSourceContent { + source:Vc, + path:RcStr, + asset:Vc>, +} + +#[turbo_tasks::value_impl] +impl AssetGraphGetContentSourceContent { + #[turbo_tasks::function] + pub fn new( + source:Vc, + path:RcStr, + asset:Vc>, + ) -> Vc { + Self::cell(AssetGraphGetContentSourceContent { source, path, asset }) + } +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for AssetGraphGetContentSourceContent { + #[turbo_tasks::function] + async fn get( + self: Vc, + _path:RcStr, + _data:Value, + ) -> Result> { + let this = self.await?; + turbo_tasks::emit(Vc::upcast::>(self)); + Ok(ContentSourceContent::static_content(this.asset.versioned_content())) + } +} + +#[turbo_tasks::value_impl] +impl ContentSourceSideEffect for AssetGraphGetContentSourceContent { + #[turbo_tasks::function] + async fn apply(&self) -> Result> { + let source = self.source.await?; + + if let Some(expanded) = &source.expanded { + expanded.update_conditionally(|expanded| expanded.insert(self.path.clone())); + } + Ok(Completion::new()) + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("asset graph content source".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for AssetGraphContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { self.root_path.to_string() } + + #[turbo_tasks::function] + fn details(&self) -> Vc { + Vc::cell(if let Some(expanded) = &self.expanded { + format!("{} assets expanded", expanded.get().len()).into() + } else { + "eager".into() + }) + } + + #[turbo_tasks::function] + async fn children(self: Vc) -> Result> { + let this = self.await?; + let key = Vc::cell("root".into()); + let inner_key = Vc::cell("inner".into()); + let expanded_key = Vc::cell("expanded".into()); + + let root_assets = this.root_assets.await?; + let root_asset_children = root_assets + .iter() + .map(|&asset| (key, IntrospectableOutputAsset::new(Vc::upcast(asset)))); + + let expanded_assets = self.all_assets_map().await?; + let expanded_asset_children = expanded_assets + .values() + .filter(|a| !root_assets.contains(*a)) + .map(|asset| (inner_key, IntrospectableOutputAsset::new(Vc::upcast(*asset)))); + + Ok(Vc::cell( + root_asset_children + .chain(expanded_asset_children) + .chain(once((expanded_key, Vc::upcast(FullyExpaned(self).cell())))) + .collect(), + )) + } +} + +#[turbo_tasks::function] +fn fully_expaned_introspectable_type() -> Vc { + Vc::cell("fully expanded asset graph content source".into()) +} + +#[turbo_tasks::value] +struct FullyExpaned(Vc); + +#[turbo_tasks::value_impl] +impl Introspectable for FullyExpaned { + #[turbo_tasks::function] + fn ty(&self) -> Vc { fully_expaned_introspectable_type() } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { Ok(self.0.await?.root_path.to_string()) } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + let source = self.0.await?; + let key = Vc::cell("asset".into()); + + let expanded_assets = + expand(&*source.root_assets.await?, &*source.root_path.await?, None).await?; + let children = expanded_assets + .iter() + .map(|(_k, &v)| (key, IntrospectableOutputAsset::new(v))) + .collect(); + + Ok(Vc::cell(children)) + } +} diff --git a/crates/turbopack-dev-server/Source/source/combined.rs b/crates/turbopack-dev-server/Source/source/combined.rs new file mode 100644 index 0000000000000..071dfe257b9f9 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/combined.rs @@ -0,0 +1,95 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, TryJoinIterExt, Vc}; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; + +use super::{ + ContentSource, + route_tree::{RouteTree, RouteTrees}, +}; +use crate::source::ContentSources; + +/// Combines multiple [ContentSource]s by trying all content sources in order. +/// The content source which responds with the most specific response (that is +/// not a [ContentSourceContent::NotFound]) will be returned. +#[turbo_tasks::value(shared)] +pub struct CombinedContentSource { + pub sources:Vec>>, +} + +impl CombinedContentSource { + pub fn new(sources:Vec>>) -> Vc { + CombinedContentSource { sources }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ContentSource for CombinedContentSource { + #[turbo_tasks::function] + fn get_routes(&self) -> Vc { + let all_routes = self.sources.iter().map(|s| s.get_routes()).collect(); + Vc::::cell(all_routes).merge() + } + + #[turbo_tasks::function] + fn get_children(&self) -> Vc { Vc::cell(self.sources.clone()) } +} + +#[turbo_tasks::value_impl] +impl Introspectable for CombinedContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { Vc::cell("combined content source".into()) } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { + let titles = self + .sources + .iter() + .map(|&source| { + async move { + Ok( + if let Some(source) = + Vc::try_resolve_sidecast::>(source).await? + { + Some(source.title().await?) + } else { + None + }, + ) + } + }) + .try_join() + .await?; + let mut titles = titles.into_iter().flatten().collect::>(); + titles.sort(); + const NUMBER_OF_TITLES_TO_DISPLAY:usize = 5; + let mut titles = titles + .iter() + .map(|t| t.as_str()) + .filter(|t| !t.is_empty()) + .take(NUMBER_OF_TITLES_TO_DISPLAY + 1) + .collect::>(); + if titles.len() > NUMBER_OF_TITLES_TO_DISPLAY { + titles[NUMBER_OF_TITLES_TO_DISPLAY] = "..."; + } + Ok(Vc::cell(titles.join(", ").into())) + } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + let source = Vc::cell("source".into()); + Ok(Vc::cell( + self.sources + .iter() + .copied() + .map(|s| { + async move { Ok(Vc::try_resolve_sidecast::>(s).await?) } + }) + .try_join() + .await? + .into_iter() + .flatten() + .map(|i| (source, i)) + .collect(), + )) + } +} diff --git a/crates/turbopack-dev-server/Source/source/conditional.rs b/crates/turbopack-dev-server/Source/source/conditional.rs new file mode 100644 index 0000000000000..26e81087a5846 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/conditional.rs @@ -0,0 +1,157 @@ +use anyhow::Result; +use turbo_tasks::{Completion, RcStr, State, Value, Vc}; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; + +use super::{ + ContentSource, + ContentSourceData, + ContentSourceDataVary, + ContentSourceSideEffect, + GetContentSourceContent, + route_tree::{MapGetContentSourceContent, RouteTree, RouteTrees}, +}; +use crate::source::{ContentSourceContent, ContentSources}; + +/// Combines two [ContentSource]s like the [CombinedContentSource], but only +/// allows to serve from the second source when the first source has +/// successfully served something once. +/// This is a laziness optimization when the content of the second source can +/// only be reached via references from the first source. +/// +/// For example, we use that in the content source that handles SSR rendering of +/// pages. Here HTML and "other assets" are in different content sources. So we +/// use this source to only serve (and process) "other assets" when the HTML was +/// served once. +#[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")] +pub struct ConditionalContentSource { + activator:Vc>, + action:Vc>, + activated:State, +} + +#[turbo_tasks::value_impl] +impl ConditionalContentSource { + #[turbo_tasks::function] + pub fn new( + activator:Vc>, + action:Vc>, + ) -> Vc { + ConditionalContentSource { activator, action, activated:State::new(false) }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ContentSource for ConditionalContentSource { + #[turbo_tasks::function] + async fn get_routes(self: Vc) -> Result> { + let this = self.await?; + Ok(if !*this.activated.get() { + this.activator + .get_routes() + .map_routes(Vc::upcast(ConditionalContentSourceMapper { source:self }.cell())) + } else { + Vc::::cell(vec![this.activator.get_routes(), this.action.get_routes()]) + .merge() + }) + } + + #[turbo_tasks::function] + fn get_children(&self) -> Vc { Vc::cell(vec![self.activator, self.action]) } +} + +#[turbo_tasks::value] +struct ConditionalContentSourceMapper { + source:Vc, +} + +#[turbo_tasks::value_impl] +impl MapGetContentSourceContent for ConditionalContentSourceMapper { + #[turbo_tasks::function] + fn map_get_content( + &self, + get_content:Vc>, + ) -> Vc> { + Vc::upcast(ActivateOnGetContentSource { source:self.source, get_content }.cell()) + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("conditional content source".into()) } + +#[turbo_tasks::function] +fn activator_key() -> Vc { Vc::cell("activator".into()) } + +#[turbo_tasks::function] +fn action_key() -> Vc { Vc::cell("action".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for ConditionalContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + async fn details(&self) -> Result> { + Ok(Vc::cell( + if *self.activated.get() { "activated" } else { "not activated" }.into(), + )) + } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { + if let Some(activator) = + Vc::try_resolve_sidecast::>(self.activator).await? + { + Ok(activator.title()) + } else { + Ok(Vc::::default()) + } + } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + Ok(Vc::cell( + [ + Vc::try_resolve_sidecast::>(self.activator) + .await? + .map(|i| (activator_key(), i)), + Vc::try_resolve_sidecast::>(self.action) + .await? + .map(|i| (action_key(), i)), + ] + .into_iter() + .flatten() + .collect(), + )) + } +} + +#[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")] +struct ActivateOnGetContentSource { + source:Vc, + get_content:Vc>, +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for ActivateOnGetContentSource { + #[turbo_tasks::function] + fn vary(&self) -> Vc { self.get_content.vary() } + + #[turbo_tasks::function] + async fn get( + self: Vc, + path:RcStr, + data:Value, + ) -> Result> { + turbo_tasks::emit(Vc::upcast::>(self)); + Ok(self.await?.get_content.get(path, data)) + } +} + +#[turbo_tasks::value_impl] +impl ContentSourceSideEffect for ActivateOnGetContentSource { + #[turbo_tasks::function] + async fn apply(&self) -> Result> { + self.source.await?.activated.set(true); + Ok(Completion::new()) + } +} diff --git a/crates/turbopack-dev-server/Source/source/headers.rs b/crates/turbopack-dev-server/Source/source/headers.rs new file mode 100644 index 0000000000000..eadfeb68f7351 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/headers.rs @@ -0,0 +1,87 @@ +use std::{collections::BTreeMap, hash::Hash, mem::replace, ops::DerefMut}; + +use serde::{Deserialize, Serialize}; +use turbo_tasks::trace::TraceRawVcs; + +/// A parsed query string from a http request +#[derive(Clone, Debug, PartialEq, Eq, Default, Hash, TraceRawVcs, Serialize, Deserialize)] +#[serde(transparent)] +pub struct Headers(BTreeMap); + +/// The value of an http header. HTTP headers might contain non-utf-8 bytes. An +/// header might also occur multiple times. +#[derive( + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TraceRawVcs, Serialize, Deserialize, +)] +#[serde(untagged)] +pub enum HeaderValue { + SingleString(String), + SingleBytes(Vec), + MultiStrings(Vec), + MultiBytes(Vec>), +} + +impl PartialOrd for Headers { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for Headers { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + self.0.len().cmp(&other.0.len()).then_with(|| self.0.iter().cmp(other.0.iter())) + } +} + +impl std::ops::Deref for Headers { + type Target = BTreeMap; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +impl DerefMut for Headers { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } +} + +impl HeaderValue { + /// Extends the current value with another occurrence of that header which + /// is a string + pub fn extend_with_string(&mut self, new:String) { + *self = match replace(self, HeaderValue::SingleBytes(Vec::new())) { + HeaderValue::SingleString(s) => HeaderValue::MultiStrings(vec![s, new]), + HeaderValue::SingleBytes(b) => HeaderValue::MultiBytes(vec![b, new.into()]), + HeaderValue::MultiStrings(mut v) => { + v.push(new); + HeaderValue::MultiStrings(v) + }, + HeaderValue::MultiBytes(mut v) => { + v.push(new.into()); + HeaderValue::MultiBytes(v) + }, + } + } + + /// Extends the current value with another occurrence of that header which + /// is a non-utf-8 valid byte sequence + pub fn extend_with_bytes(&mut self, new:Vec) { + *self = match replace(self, HeaderValue::SingleBytes(Vec::new())) { + HeaderValue::SingleString(s) => HeaderValue::MultiBytes(vec![s.into(), new]), + HeaderValue::SingleBytes(b) => HeaderValue::MultiBytes(vec![b, new]), + HeaderValue::MultiStrings(v) => { + let mut v:Vec> = v.into_iter().map(|s| s.into()).collect(); + v.push(new); + HeaderValue::MultiBytes(v) + }, + HeaderValue::MultiBytes(mut v) => { + v.push(new); + HeaderValue::MultiBytes(v) + }, + } + } + + pub fn contains(&self, string_value:&str) -> bool { + match self { + HeaderValue::SingleString(s) => s.contains(string_value), + HeaderValue::MultiStrings(s) => s.iter().any(|s| s.contains(string_value)), + _ => false, + } + } +} diff --git a/crates/turbopack-dev-server/Source/source/issue_context.rs b/crates/turbopack-dev-server/Source/source/issue_context.rs new file mode 100644 index 0000000000000..ee4bf28c2bc18 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/issue_context.rs @@ -0,0 +1,165 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + introspect::{Introspectable, IntrospectableChildren}, + issue::IssueDescriptionExt, +}; + +use super::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + ContentSourceDataVary, + ContentSources, + GetContentSourceContent, + route_tree::{MapGetContentSourceContent, RouteTree}, +}; + +#[turbo_tasks::value] +pub struct IssueFilePathContentSource { + file_path:Option>, + description:RcStr, + source:Vc>, +} + +#[turbo_tasks::value_impl] +impl IssueFilePathContentSource { + #[turbo_tasks::function] + pub fn new_file_path( + file_path:Vc, + description:RcStr, + source:Vc>, + ) -> Vc { + IssueFilePathContentSource { file_path:Some(file_path), description, source }.cell() + } + + #[turbo_tasks::function] + pub fn new_description(description:RcStr, source:Vc>) -> Vc { + IssueFilePathContentSource { file_path:None, description, source }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ContentSource for IssueFilePathContentSource { + #[turbo_tasks::function] + async fn get_routes(self: Vc) -> Result> { + let this = self.await?; + let routes = this + .source + .get_routes() + .issue_file_path(this.file_path, &*this.description) + .await?; + Ok(routes.map_routes(Vc::upcast(IssueContextContentSourceMapper { source:self }.cell()))) + } + + #[turbo_tasks::function] + fn get_children(&self) -> Vc { Vc::cell(vec![self.source]) } +} + +#[turbo_tasks::value] +struct IssueContextContentSourceMapper { + source:Vc, +} + +#[turbo_tasks::value_impl] +impl MapGetContentSourceContent for IssueContextContentSourceMapper { + #[turbo_tasks::function] + fn map_get_content( + &self, + get_content:Vc>, + ) -> Vc> { + Vc::upcast(IssueContextGetContentSourceContent { get_content, source:self.source }.cell()) + } +} + +#[turbo_tasks::value] +struct IssueContextGetContentSourceContent { + get_content:Vc>, + source:Vc, +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for IssueContextGetContentSourceContent { + #[turbo_tasks::function] + async fn vary(&self) -> Result> { + let source = self.source.await?; + let result = self + .get_content + .vary() + .issue_file_path(source.file_path, &*source.description) + .await?; + Ok(result) + } + + #[turbo_tasks::function] + async fn get( + &self, + path:RcStr, + data:Value, + ) -> Result> { + let source = self.source.await?; + let result = self + .get_content + .get(path, data) + .issue_file_path(source.file_path, &*source.description) + .await?; + Ok(result) + } +} + +#[turbo_tasks::value_impl] +impl Introspectable for IssueFilePathContentSource { + #[turbo_tasks::function] + async fn ty(&self) -> Result> { + Ok( + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { + source.ty() + } else { + Vc::cell("IssueContextContentSource".into()) + }, + ) + } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { + Ok( + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { + let title = source.title().await?; + Vc::cell(format!("{}: {}", self.description, title).into()) + } else { + Vc::cell(self.description.clone()) + }, + ) + } + + #[turbo_tasks::function] + async fn details(&self) -> Result> { + Ok( + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { + source.details() + } else { + Vc::cell(RcStr::default()) + }, + ) + } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + Ok( + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { + source.children() + } else { + Vc::cell(Default::default()) + }, + ) + } +} diff --git a/crates/turbopack-dev-server/Source/source/lazy_instantiated.rs b/crates/turbopack-dev-server/Source/source/lazy_instantiated.rs new file mode 100644 index 0000000000000..0aaae59e27131 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/lazy_instantiated.rs @@ -0,0 +1,54 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; + +use super::{ContentSource, route_tree::RouteTree}; + +/// A functor to get a [ContentSource]. Will be invoked when needed when using +/// [LazyInstantiatedContentSource]. +#[turbo_tasks::value_trait] +pub trait GetContentSource { + /// Returns the [ContentSource] + fn content_source(self: Vc) -> Vc>; +} + +/// Wraps the [ContentSource] creation in a way that only creates it when +/// actually used. +#[turbo_tasks::value(shared)] +pub struct LazyInstantiatedContentSource { + pub get_source:Vc>, +} + +#[turbo_tasks::value_impl] +impl ContentSource for LazyInstantiatedContentSource { + #[turbo_tasks::function] + fn get_routes(&self) -> Vc { self.get_source.content_source().get_routes() } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("lazy instantiated content source".into()) } + +#[turbo_tasks::function] +fn source_key() -> Vc { Vc::cell("source".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for LazyInstantiatedContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + Ok(Vc::cell( + [ + Vc::try_resolve_sidecast::>( + self.get_source.content_source(), + ) + .await? + .map(|i| (source_key(), i)), + ] + .into_iter() + .flatten() + .collect(), + )) + } +} diff --git a/crates/turbopack-dev-server/Source/source/mod.rs b/crates/turbopack-dev-server/Source/source/mod.rs new file mode 100644 index 0000000000000..06d33aa8d8ee6 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/mod.rs @@ -0,0 +1,538 @@ +pub mod asset_graph; +pub mod combined; +pub mod conditional; +pub mod headers; +pub mod issue_context; +pub mod lazy_instantiated; +pub mod query; +pub mod request; +pub(crate) mod resolve; +pub mod route_tree; +pub mod router; +pub mod static_assets; +pub mod wrapping_source; + +use std::collections::BTreeSet; + +use anyhow::Result; +use futures::{TryStreamExt, stream::Stream as StreamTrait}; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{ + Completion, + RcStr, + Upcast, + Value, + ValueDefault, + Vc, + trace::TraceRawVcs, + util::SharedError, +}; +use turbo_tasks_bytes::{Bytes, Stream, StreamRead}; +use turbo_tasks_fs::FileSystemPath; +use turbo_tasks_hash::{DeterministicHash, DeterministicHasher, Xxh3Hash64Hasher}; +use turbopack_core::version::{Version, VersionedContent}; + +use self::{ + headers::Headers, + issue_context::IssueFilePathContentSource, + query::Query, + route_tree::RouteTree, +}; + +/// The result of proxying a request to another HTTP server. +#[turbo_tasks::value(shared)] +pub struct ProxyResult { + /// The HTTP status code to return. + pub status:u16, + /// Headers arranged as contiguous (name, value) pairs. + pub headers:Vec<(RcStr, RcStr)>, + /// The body to return. + pub body:Body, +} + +#[turbo_tasks::value_impl] +impl Version for ProxyResult { + #[turbo_tasks::function] + async fn id(&self) -> Result> { + let mut hash = Xxh3Hash64Hasher::new(); + hash.write_u16(self.status); + for (name, value) in &self.headers { + name.deterministic_hash(&mut hash); + value.deterministic_hash(&mut hash); + } + let mut read = self.body.read(); + while let Some(chunk) = read.try_next().await? { + hash.write_bytes(&chunk); + } + Ok(Vc::cell(hash.finish().to_string().into())) + } +} + +/// A functor to receive the actual content of a content source result. +#[turbo_tasks::value_trait] +pub trait GetContentSourceContent { + /// Specifies data requirements for the get function. Restricting data + /// passed allows to cache the get method. + fn vary(self: Vc) -> Vc { ContentSourceDataVary::default().cell() } + + /// Get the content + fn get(self: Vc, path:RcStr, data:Value) -> Vc; +} + +#[turbo_tasks::value(transparent)] +pub struct GetContentSourceContents(Vec>>); + +#[turbo_tasks::value] +pub struct StaticContent { + pub content:Vc>, + pub status_code:u16, + pub headers:Vc, +} + +#[turbo_tasks::value(shared)] +// TODO add Dynamic variant in future to allow streaming and server responses +/// The content of a result that is returned by a content source. +pub enum ContentSourceContent { + NotFound, + Static(Vc), + HttpProxy(Vc), + Rewrite(Vc), + /// Continue with the next route + Next, +} + +/// This trait can be emitted as collectible and will be applied after the +/// request is handled and it's ensured that it finishes before the next request +/// is handled. +#[turbo_tasks::value_trait] +pub trait ContentSourceSideEffect { + fn apply(self: Vc) -> Vc; +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for ContentSourceContent { + #[turbo_tasks::function] + fn get( + self: Vc, + _path:RcStr, + _data:Value, + ) -> Vc { + self + } +} + +#[turbo_tasks::value_impl] +impl ContentSourceContent { + #[turbo_tasks::function] + pub fn static_content(content:Vc>) -> Vc { + ContentSourceContent::Static( + StaticContent { content, status_code:200, headers:HeaderList::empty() }.cell(), + ) + .cell() + } + + #[turbo_tasks::function] + pub fn static_with_headers( + content:Vc>, + status_code:u16, + headers:Vc, + ) -> Vc { + ContentSourceContent::Static(StaticContent { content, status_code, headers }.cell()).cell() + } + + #[turbo_tasks::function] + pub fn not_found() -> Vc { ContentSourceContent::NotFound.cell() } +} + +/// A list of headers arranged as contiguous (name, value) pairs. +#[turbo_tasks::value(transparent)] +pub struct HeaderList(Vec<(RcStr, RcStr)>); + +#[turbo_tasks::value_impl] +impl HeaderList { + #[turbo_tasks::function] + pub fn new(headers:Vec<(RcStr, RcStr)>) -> Vc { HeaderList(headers).cell() } + + #[turbo_tasks::function] + pub fn empty() -> Vc { HeaderList(vec![]).cell() } +} + +/// Additional info passed to the ContentSource. It was extracted from the http +/// request. +/// +/// Note that you might not receive information that has not been requested via +/// `ContentSource::vary()`. So make sure to request all information that's +/// needed. +#[turbo_tasks::value(shared, serialization = "auto_for_input")] +#[derive(Clone, Debug, PartialOrd, Ord, Hash, Default)] +pub struct ContentSourceData { + /// HTTP method, if requested. + pub method:Option, + /// The full url (including query string), if requested. + pub url:Option, + /// The full url (including query string) before rewrites where applied, if + /// requested. + pub original_url:Option, + /// Query string items, if requested. + pub query:Option, + /// raw query string, if requested. Does not include the `?`. + pub raw_query:Option, + /// HTTP headers, might contain multiple headers with the same name, if + /// requested. + pub headers:Option, + /// Raw HTTP headers, might contain multiple headers with the same name, if + /// requested. + pub raw_headers:Option>, + /// Request body, if requested. + pub body:Option>, + /// See [ContentSourceDataVary::cache_buster]. + pub cache_buster:u64, +} + +pub type BodyChunk = Result; + +/// A request body. +#[turbo_tasks::value(shared)] +#[derive(Default, Clone, Debug)] +pub struct Body { + #[turbo_tasks(trace_ignore)] + chunks:Stream, +} + +impl Body { + /// Creates a new body from a list of chunks. + pub fn new(chunks:Vec) -> Self { Self { chunks:Stream::new_closed(chunks) } } + + /// Returns an iterator over the body's chunks. + pub fn read(&self) -> StreamRead { self.chunks.read() } + + pub fn from_stream + Send + Unpin + 'static>(source:T) -> Self { + Self { chunks:Stream::from(source) } + } +} + +impl> From for Body { + fn from(value:T) -> Self { Body::new(vec![Ok(value.into())]) } +} + +impl ValueDefault for Body { + fn value_default() -> Vc { Body::default().cell() } +} + +/// Filter function that describes which information is required. +#[derive( + Debug, Clone, PartialEq, Eq, TraceRawVcs, Hash, PartialOrd, Ord, Serialize, Deserialize, +)] +pub enum ContentSourceDataFilter { + All, + Subset(BTreeSet), +} + +impl ContentSourceDataFilter { + /// Merges the filtering to get a filter that covers both filters. + pub fn extend(&mut self, other:&ContentSourceDataFilter) { + match self { + ContentSourceDataFilter::All => {}, + ContentSourceDataFilter::Subset(set) => { + match other { + ContentSourceDataFilter::All => *self = ContentSourceDataFilter::All, + ContentSourceDataFilter::Subset(set2) => set.extend(set2.iter().cloned()), + } + }, + } + } + + /// Merges the filtering to get a filter that covers both filters. Works on + /// Option where None is considers as empty filter. + pub fn extend_options( + this:&mut Option, + other:&Option, + ) { + if let Some(this) = this.as_mut() { + if let Some(other) = other.as_ref() { + this.extend(other); + } + } else { + this.clone_from(other); + } + } + + /// Returns true if the filter contains the given key. + pub fn contains(&self, key:&str) -> bool { + match self { + ContentSourceDataFilter::All => true, + ContentSourceDataFilter::Subset(set) => set.contains(key), + } + } + + /// Returns true if the first argument at least contains all values that the + /// second argument would contain. + pub fn fulfills( + this:&Option, + other:&Option, + ) -> bool { + match (this, other) { + (_, None) => true, + (None, Some(_)) => false, + (Some(this), Some(other)) => { + match (this, other) { + (ContentSourceDataFilter::All, _) => true, + (_, ContentSourceDataFilter::All) => false, + ( + ContentSourceDataFilter::Subset(this), + ContentSourceDataFilter::Subset(other), + ) => this.is_superset(other), + } + }, + } + } +} + +/// Describes additional information that need to be sent to requests to +/// ContentSource. By sending these information ContentSource responses are +/// cached-keyed by them and they can access them. +#[turbo_tasks::value(shared, serialization = "auto_for_input")] +#[derive(Debug, Default, Clone, PartialOrd, Ord, Hash)] +pub struct ContentSourceDataVary { + pub method:bool, + pub url:bool, + pub original_url:bool, + pub query:Option, + pub raw_query:bool, + pub headers:Option, + pub raw_headers:bool, + pub body:bool, + /// When true, a `cache_buster` value is added to the [ContentSourceData]. + /// This value will be different on every request, which ensures the + /// content is never cached. + pub cache_buster:bool, + pub placeholder_for_future_extensions:(), +} + +impl ContentSourceDataVary { + /// Merges two vary specification to create a combination of both that cover + /// all information requested by either one + pub fn extend(&mut self, other:&ContentSourceDataVary) { + let ContentSourceDataVary { + method, + url, + original_url, + query, + raw_query, + headers, + raw_headers, + body, + cache_buster, + placeholder_for_future_extensions: _, + } = self; + *method = *method || other.method; + *url = *url || other.url; + *original_url = *original_url || other.original_url; + *body = *body || other.body; + *cache_buster = *cache_buster || other.cache_buster; + *raw_query = *raw_query || other.raw_query; + *raw_headers = *raw_headers || other.raw_headers; + ContentSourceDataFilter::extend_options(query, &other.query); + ContentSourceDataFilter::extend_options(headers, &other.headers); + } + + /// Returns true if `self` at least contains all values that the + /// argument would contain. + pub fn fulfills(&self, other:&ContentSourceDataVary) -> bool { + // All fields must be used! + let ContentSourceDataVary { + method, + url, + original_url, + query, + raw_query, + headers, + raw_headers, + body, + cache_buster, + placeholder_for_future_extensions: _, + } = self; + if other.method && !method { + return false; + } + if other.url && !url { + return false; + } + if other.original_url && !original_url { + return false; + } + if other.body && !body { + return false; + } + if other.raw_query && !raw_query { + return false; + } + if other.raw_headers && !raw_headers { + return false; + } + if other.cache_buster && !cache_buster { + return false; + } + if !ContentSourceDataFilter::fulfills(query, &other.query) { + return false; + } + if !ContentSourceDataFilter::fulfills(headers, &other.headers) { + return false; + } + true + } +} + +/// A source of content that the dev server uses to respond to http requests. +#[turbo_tasks::value_trait] +pub trait ContentSource { + fn get_routes(self: Vc) -> Vc; + + /// Gets any content sources wrapped in this content source. + fn get_children(self: Vc) -> Vc { ContentSources::empty() } +} + +pub trait ContentSourceExt: Send { + fn issue_file_path( + self: Vc, + file_path:Vc, + description:RcStr, + ) -> Vc>; +} + +impl ContentSourceExt for T +where + T: Upcast>, +{ + fn issue_file_path( + self: Vc, + file_path:Vc, + description:RcStr, + ) -> Vc> { + Vc::upcast(IssueFilePathContentSource::new_file_path( + file_path, + description, + Vc::upcast(self), + )) + } +} + +#[turbo_tasks::value(transparent)] +pub struct ContentSources(Vec>>); + +#[turbo_tasks::value_impl] +impl ContentSources { + #[turbo_tasks::function] + pub fn empty() -> Vc { Vc::cell(Vec::new()) } +} + +/// An empty ContentSource implementation that responds with NotFound for every +/// request. +#[turbo_tasks::value] +pub struct NoContentSource; + +#[turbo_tasks::value_impl] +impl NoContentSource { + #[turbo_tasks::function] + pub fn new() -> Vc { NoContentSource.cell() } +} +#[turbo_tasks::value_impl] +impl ContentSource for NoContentSource { + #[turbo_tasks::function] + fn get_routes(&self) -> Vc { RouteTree::empty() } +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] +pub enum RewriteType { + Location { + /// The new path and query used to lookup content. This _does not_ need + /// to be the original path or query. + path_and_query:RcStr, + }, + ContentSource { + /// [Vc>]s from which to restart the lookup + /// process. This _does not_ need to be the original content + /// source. + source:Vc>, + /// The new path and query used to lookup content. This _does not_ need + /// to be the original path or query. + path_and_query:RcStr, + }, + Sources { + /// [GetContentSourceContent]s from which to restart the lookup + /// process. This _does not_ need to be the original content + /// source. + sources:Vc, + }, +} + +/// A rewrite returned from a [ContentSource]. This tells the dev server to +/// update its parsed url, path, and queries with this new information. +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub struct Rewrite { + pub ty:RewriteType, + + /// A [Headers] which will be appended to the eventual, fully resolved + /// content result. This overwrites any previous matching headers. + pub response_headers:Option>, + + /// A [HeaderList] which will overwrite the values used during the lookup + /// process. All headers not present in this list will be deleted. + pub request_headers:Option>, +} + +pub struct RewriteBuilder { + rewrite:Rewrite, +} + +impl RewriteBuilder { + pub fn new(path_and_query:RcStr) -> Self { + Self { + rewrite:Rewrite { + ty:RewriteType::Location { path_and_query }, + response_headers:None, + request_headers:None, + }, + } + } + + pub fn new_source_with_path_and_query( + source:Vc>, + path_and_query:RcStr, + ) -> Self { + Self { + rewrite:Rewrite { + ty:RewriteType::ContentSource { source, path_and_query }, + response_headers:None, + request_headers:None, + }, + } + } + + pub fn new_sources(sources:Vc) -> Self { + Self { + rewrite:Rewrite { + ty:RewriteType::Sources { sources }, + response_headers:None, + request_headers:None, + }, + } + } + + /// Sets response headers to append to the eventual, fully resolved content + /// result. + pub fn response_headers(mut self, headers:Vc) -> Self { + self.rewrite.response_headers = Some(headers); + self + } + + /// Sets request headers to overwrite the headers used during the lookup + /// process. + pub fn request_headers(mut self, headers:Vc) -> Self { + self.rewrite.request_headers = Some(headers); + self + } + + pub fn build(self) -> Vc { self.rewrite.cell() } +} diff --git a/crates/turbopack-dev-server/Source/source/query.rs b/crates/turbopack-dev-server/Source/source/query.rs new file mode 100644 index 0000000000000..89be51002c719 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/query.rs @@ -0,0 +1,55 @@ +use std::{collections::BTreeMap, hash::Hash, ops::DerefMut}; + +use serde::{Deserialize, Serialize}; +use turbo_tasks::trace::TraceRawVcs; + +use super::ContentSourceDataFilter; + +/// A parsed query string from a http request +#[derive(Clone, Debug, PartialEq, Eq, Default, Hash, TraceRawVcs, Serialize, Deserialize)] +#[serde(transparent)] +pub struct Query(BTreeMap); + +impl Query { + pub fn filter_with(&mut self, filter:&ContentSourceDataFilter) { + match filter { + ContentSourceDataFilter::All => { + // fast path without iterating query + }, + _ => self.0.retain(|k, _| filter.contains(k)), + } + } +} + +impl PartialOrd for Query { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for Query { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + self.0.len().cmp(&other.0.len()).then_with(|| self.0.iter().cmp(other.0.iter())) + } +} + +impl std::ops::Deref for Query { + type Target = BTreeMap; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +impl DerefMut for Query { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } +} + +#[derive( + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TraceRawVcs, Serialize, Deserialize, +)] +#[serde(untagged)] +pub enum QueryValue { + /// Simple string value, might be an empty string when there is no value + String(String), + /// An array of values + Array(Vec), + /// A nested structure + Nested(Query), +} diff --git a/crates/turbopack-dev-server/Source/source/request.rs b/crates/turbopack-dev-server/Source/source/request.rs new file mode 100644 index 0000000000000..7b709ac255113 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/request.rs @@ -0,0 +1,16 @@ +use hyper::{HeaderMap, Uri}; + +use super::Body; + +/// A request to a content source. +#[derive(Debug, Clone)] +pub struct SourceRequest { + /// The HTTP method to use. + pub method:String, + /// The URI to request. + pub uri:Uri, + /// The headers to send. + pub headers:HeaderMap, + /// The body to send. + pub body:Body, +} diff --git a/crates/turbopack-dev-server/Source/source/resolve.rs b/crates/turbopack-dev-server/Source/source/resolve.rs new file mode 100644 index 0000000000000..25cc0452b72f6 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/resolve.rs @@ -0,0 +1,202 @@ +use std::{ + collections::btree_map::Entry, + sync::atomic::{AtomicU64, Ordering}, +}; + +use anyhow::Result; +use hyper::{ + Uri, + header::{HeaderName as HyperHeaderName, HeaderValue as HyperHeaderValue}, +}; +use turbo_tasks::{RcStr, TransientInstance, Value, Vc}; + +use super::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + ContentSourceDataVary, + GetContentSourceContent, + HeaderList, + ProxyResult, + RewriteType, + StaticContent, + headers::{HeaderValue, Headers}, + query::Query, + request::SourceRequest, +}; + +/// The result of [`resolve_source_request`]. Similar to a +/// `ContentSourceContent`, but without the `Rewrite` variant as this is taken +/// care in the function. +#[turbo_tasks::value(serialization = "none")] +pub enum ResolveSourceRequestResult { + NotFound, + Static(Vc, Vc), + HttpProxy(Vc), +} + +/// Resolves a [SourceRequest] within a [super::ContentSource], returning the +/// corresponding content. +/// +/// This function is the boundary of consistency. All invoked methods should be +/// invoked strongly consistent. This ensures that all requests serve the latest +/// version of the content. We don't make resolve_source_request strongly +/// consistent as we want get_routes and get to be independent consistent and +/// any side effect in get should not wait for recomputing of get_routes. +#[turbo_tasks::function] +pub async fn resolve_source_request( + source:Vc>, + request:TransientInstance, +) -> Result> { + let original_path = request.uri.path().to_string(); + // Remove leading slash. + let mut current_asset_path:RcStr = urlencoding::decode(&original_path[1..])?.into(); + let mut request_overwrites = (*request).clone(); + let mut response_header_overwrites = Vec::new(); + let mut route_tree = source.get_routes().resolve_strongly_consistent().await?; + 'routes: loop { + let mut sources = route_tree.get(current_asset_path.clone()); + 'sources: loop { + for get_content in sources.strongly_consistent().await?.iter() { + let content_vary = get_content.vary().strongly_consistent().await?; + let content_data = + request_to_data(&request_overwrites, &request, &content_vary).await?; + let content = get_content.get(current_asset_path.clone(), Value::new(content_data)); + match &*content.strongly_consistent().await? { + ContentSourceContent::Rewrite(rewrite) => { + let rewrite = rewrite.await?; + // apply rewrite extras + if let Some(headers) = &rewrite.response_headers { + response_header_overwrites.extend(headers.await?.iter().cloned()); + } + if let Some(headers) = &rewrite.request_headers { + request_overwrites.headers.clear(); + for (name, value) in &*headers.await? { + request_overwrites.headers.insert( + HyperHeaderName::try_from(name.as_str())?, + HyperHeaderValue::try_from(value.as_str())?, + ); + } + } + // do the rewrite + match &rewrite.ty { + RewriteType::Location { path_and_query } => { + let new_uri = Uri::try_from(path_and_query.as_str())?; + let new_asset_path = + urlencoding::decode(&new_uri.path()[1..])?.into_owned(); + request_overwrites.uri = new_uri; + current_asset_path = new_asset_path.into(); + continue 'routes; + }, + RewriteType::ContentSource { source, path_and_query } => { + let new_uri = Uri::try_from(path_and_query.as_str())?; + let new_asset_path = + urlencoding::decode(&new_uri.path()[1..])?.into_owned(); + request_overwrites.uri = new_uri; + current_asset_path = new_asset_path.into(); + route_tree = + source.get_routes().resolve_strongly_consistent().await?; + continue 'routes; + }, + RewriteType::Sources { sources: new_sources } => { + sources = *new_sources; + continue 'sources; + }, + } + }, + ContentSourceContent::NotFound => { + return Ok(ResolveSourceRequestResult::NotFound.cell()); + }, + ContentSourceContent::Static(static_content) => { + return Ok(ResolveSourceRequestResult::Static( + *static_content, + HeaderList::new(response_header_overwrites), + ) + .cell()); + }, + ContentSourceContent::HttpProxy(proxy_result) => { + return Ok(ResolveSourceRequestResult::HttpProxy(*proxy_result).cell()); + }, + ContentSourceContent::Next => continue, + } + } + break; + } + break; + } + Ok(ResolveSourceRequestResult::NotFound.cell()) +} + +static CACHE_BUSTER:AtomicU64 = AtomicU64::new(0); + +async fn request_to_data( + request:&SourceRequest, + original_request:&SourceRequest, + vary:&ContentSourceDataVary, +) -> Result { + let mut data = ContentSourceData::default(); + if vary.method { + data.method = Some(request.method.clone().into()); + } + if vary.url { + data.url = Some(request.uri.to_string().into()); + } + if vary.original_url { + data.original_url = Some(original_request.uri.to_string().into()); + } + if vary.body { + data.body = Some(request.body.clone().into()); + } + if vary.raw_query { + data.raw_query = Some(request.uri.query().unwrap_or("").into()); + } + if vary.raw_headers { + data.raw_headers = Some( + request + .headers + .iter() + .map(|(name, value)| { + Ok((name.to_string().into(), value.to_str()?.to_string().into())) + }) + .collect::>>()?, + ); + } + if let Some(filter) = vary.query.as_ref() { + if let Some(query) = request.uri.query() { + let mut query:Query = serde_qs::from_str(query)?; + query.filter_with(filter); + data.query = Some(query); + } else { + data.query = Some(Query::default()) + } + } + if let Some(filter) = vary.headers.as_ref() { + let mut headers = Headers::default(); + for (header_name, header_value) in request.headers.iter() { + if !filter.contains(header_name.as_str()) { + continue; + } + match headers.entry(header_name.to_string()) { + Entry::Vacant(e) => { + if let Ok(s) = header_value.to_str() { + e.insert(HeaderValue::SingleString(s.to_string())); + } else { + e.insert(HeaderValue::SingleBytes(header_value.as_bytes().to_vec())); + } + }, + Entry::Occupied(mut e) => { + if let Ok(s) = header_value.to_str() { + e.get_mut().extend_with_string(s.to_string()); + } else { + e.get_mut().extend_with_bytes(header_value.as_bytes().to_vec()); + } + }, + } + } + data.headers = Some(headers); + } + if vary.cache_buster { + data.cache_buster = CACHE_BUSTER.fetch_add(1, Ordering::SeqCst); + } + Ok(data) +} diff --git a/crates/turbopack-dev-server/Source/source/route_tree.rs b/crates/turbopack-dev-server/Source/source/route_tree.rs new file mode 100644 index 0000000000000..1f4c109fbe846 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/route_tree.rs @@ -0,0 +1,372 @@ +use std::{fmt::Write, mem::replace}; + +use anyhow::Result; +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{RcStr, TaskInput, TryJoinIterExt, ValueToString, Vc, trace::TraceRawVcs}; + +use super::{GetContentSourceContent, GetContentSourceContents}; + +/// The type of the route. THis will decide about the remaining segements of the +/// route after the base. +#[derive(TaskInput, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] +pub enum RouteType { + Exact, + CatchAll, + Fallback, + NotFound, +} + +/// Some normal segment of a route. +#[derive(TaskInput, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] +pub enum BaseSegment { + Static(RcStr), + Dynamic, +} + +impl BaseSegment { + pub fn from_static_pathname(str:&str) -> impl Iterator + '_ { + str.split('/').filter(|s| !s.is_empty()).map(|s| BaseSegment::Static(s.into())) + } +} + +/// This struct allows to cell a list of RouteTrees and merge them into one. +/// This can't be a single method `fn merge(Vec>)` as this would +/// lead to creating new tasks over and over. A celled list leads to task reuse +/// and faster operation. +#[turbo_tasks::value(transparent)] +pub struct RouteTrees(Vec>); + +#[turbo_tasks::value_impl] +impl RouteTrees { + /// Merges the list of RouteTrees into one RouteTree. + #[turbo_tasks::function] + pub async fn merge(self: Vc) -> Result> { + let trees = &*self.await?; + if trees.is_empty() { + return Ok(RouteTree::default().cell()); + } + if trees.len() == 1 { + return Ok(*trees.iter().next().unwrap()); + } + + // Find common base + let mut tree_values = trees.iter().try_join().await?; + let mut common_base = 0; + let last_tree = tree_values.pop().unwrap(); + 'outer: while common_base < last_tree.base.len() { + for tree in tree_values.iter() { + if tree.base.len() <= common_base { + break 'outer; + } + if tree.base[common_base] != last_tree.base[common_base] { + break 'outer; + } + } + common_base += 1; + } + tree_values.push(last_tree); + + // Normalize bases to common base + let trees = trees + .iter() + .enumerate() + .map(|(i, tree)| { + if tree_values[i].base.len() > common_base { + tree.with_base_len(common_base) + } else { + *tree + } + }) + .collect::>(); + + // Flat merge trees + let tree_values = trees.into_iter().try_join().await?; + let mut iter = tree_values.iter().map(|rr| &**rr); + let mut merged = iter.next().unwrap().clone(); + merged.flat_merge(iter).await?; + + Ok(merged.cell()) + } +} + +/// The prefix tree of routes. Also handling dynamic and catch all segments. +#[turbo_tasks::value] +#[derive(Default, Clone, Debug)] +pub struct RouteTree { + base:Vec, + sources:Vec>>, + static_segments:IndexMap>, + dynamic_segments:Vec>, + catch_all_sources:Vec>>, + fallback_sources:Vec>>, + not_found_sources:Vec>>, +} + +impl RouteTree { + /// Creates a route tree for a single route. + pub fn new_route_ref( + base_segments:Vec, + route_type:RouteType, + source:Vc>, + ) -> Self { + match route_type { + RouteType::Exact => { + Self { base:base_segments, sources:vec![source], ..Default::default() } + }, + RouteType::CatchAll => { + Self { base:base_segments, catch_all_sources:vec![source], ..Default::default() } + }, + RouteType::Fallback => { + Self { base:base_segments, fallback_sources:vec![source], ..Default::default() } + }, + RouteType::NotFound => { + Self { base:base_segments, not_found_sources:vec![source], ..Default::default() } + }, + } + } + + async fn flat_merge(&mut self, others:impl IntoIterator + '_) -> Result<()> { + let mut static_segments = IndexMap::new(); + for other in others { + debug_assert_eq!(self.base, other.base); + self.sources.extend(other.sources.iter().copied()); + self.catch_all_sources.extend(other.catch_all_sources.iter().copied()); + self.fallback_sources.extend(other.fallback_sources.iter().copied()); + self.not_found_sources.extend(other.not_found_sources.iter().copied()); + for (key, value) in other.static_segments.iter() { + if let Some((key, self_value)) = self.static_segments.remove_entry(key) { + static_segments.insert(key, vec![self_value, *value]); + } else if let Some(list) = static_segments.get_mut(key) { + list.push(*value); + } else { + static_segments.insert(key.clone(), vec![*value]); + } + } + self.dynamic_segments.extend(other.dynamic_segments.iter().copied()); + } + self.static_segments.extend( + static_segments + .into_iter() + .map(|(key, value)| { + async { + Ok(( + key, + if value.len() == 1 { + value.into_iter().next().unwrap() + } else { + Vc::::cell(value).merge().resolve().await? + }, + )) + } + }) + .try_join() + .await?, + ); + Ok(()) + } + + fn prepend_base(&mut self, segments:Vec) { self.base.splice(..0, segments); } +} + +#[turbo_tasks::value_impl] +impl ValueToString for RouteTree { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + let RouteTree { + base, + sources, + static_segments, + dynamic_segments, + catch_all_sources, + fallback_sources, + not_found_sources, + } = self; + let mut result = "RouteTree(".to_string(); + for segment in base { + match segment { + BaseSegment::Static(str) => write!(result, "/{}", str)?, + BaseSegment::Dynamic => result.push_str("/[dynamic]"), + } + } + if !base.is_empty() { + result.push_str(", "); + } + for (key, tree) in static_segments { + let tree = tree.to_string().await?; + write!(result, "{}: {}, ", key, tree)?; + } + if !sources.is_empty() { + write!(result, "{} x source, ", sources.len())?; + } + if !dynamic_segments.is_empty() { + write!(result, "{} x dynamic, ", dynamic_segments.len())?; + } + if !catch_all_sources.is_empty() { + write!(result, "{} x catch-all, ", catch_all_sources.len())?; + } + if !fallback_sources.is_empty() { + write!(result, "{} x fallback, ", fallback_sources.len())?; + } + if !not_found_sources.is_empty() { + write!(result, "{} x not-found, ", not_found_sources.len())?; + } + if result.ends_with(", ") { + result.truncate(result.len() - 2); + } + result.push(')'); + Ok(Vc::cell(result.into())) + } +} + +#[turbo_tasks::value_impl] +impl RouteTree { + /// Creates an empty route tree. + #[turbo_tasks::function] + pub fn empty() -> Vc { RouteTree::default().cell() } + + /// Creates a route tree for a single route. + #[turbo_tasks::function] + pub fn new_route( + base_segments:Vec, + route_type:RouteType, + source:Vc>, + ) -> Vc { + RouteTree::new_route_ref(base_segments, route_type, source).cell() + } + + /// Gets the [`GetContentSourceContent`]s for the given path. + // TODO(WEB-1252) It's unneccesary to compute all [`GetContentSourceContent`]s at once, we could + // return some lazy iterator to make it more efficient. + #[turbo_tasks::function] + pub async fn get(self: Vc, path:RcStr) -> Result> { + let RouteTree { + base, + sources, + static_segments, + dynamic_segments, + catch_all_sources, + fallback_sources, + not_found_sources, + } = &*self.await?; + let mut results = Vec::new(); + if path.is_empty() { + if !base.is_empty() { + return Ok(Vc::cell(vec![])); + } + results.extend(sources.iter().copied()); + } else { + let mut segments = path.split('/'); + for base in base.iter() { + let Some(segment) = segments.next() else { + return Ok(Vc::cell(vec![])); + }; + match base { + BaseSegment::Static(str) => { + if str != segment { + return Ok(Vc::cell(vec![])); + } + }, + BaseSegment::Dynamic => { + // always matching + }, + } + } + + if let Some(segment) = segments.next() { + let remainder = segments.remainder().unwrap_or(""); + if let Some(tree) = static_segments.get(segment) { + results.extend(tree.get(remainder.into()).await?.iter().copied()); + } + for tree in dynamic_segments.iter() { + results.extend(tree.get(remainder.into()).await?.iter().copied()); + } + } else { + results.extend(sources.iter().copied()); + }; + } + results.extend(catch_all_sources.iter().copied()); + results.extend(fallback_sources.iter().copied()); + results.extend(not_found_sources.iter().copied()); + Ok(Vc::cell(results)) + } + + /// Prepends a base path to all routes. + #[turbo_tasks::function] + pub async fn with_prepended_base( + self: Vc, + segments:Vec, + ) -> Result> { + let mut this = self.await?.clone_value(); + this.prepend_base(segments); + Ok(this.cell()) + } + + #[turbo_tasks::function] + async fn with_base_len(self: Vc, base_len:usize) -> Result> { + let this = self.await?; + if this.base.len() > base_len { + let mut inner = this.clone_value(); + let mut drain = inner.base.drain(base_len..); + let selector_segment = drain.next().unwrap(); + let inner_base = drain.collect(); + let base = replace(&mut inner.base, inner_base); + debug_assert!(base.len() == base_len); + match selector_segment { + BaseSegment::Static(value) => { + Ok(RouteTree { + base, + static_segments:IndexMap::from([(value, inner.cell())]), + ..Default::default() + } + .cell()) + }, + BaseSegment::Dynamic => { + Ok(RouteTree { + base, + dynamic_segments:vec![inner.cell()], + ..Default::default() + } + .cell()) + }, + } + } else { + Ok(self) + } + } + + /// Applies a transformation on all [`GetContentSourceContent`]s in the + /// tree. + #[turbo_tasks::function] + pub async fn map_routes( + self: Vc, + mapper:Vc>, + ) -> Result> { + let mut this = self.await?.clone_value(); + let RouteTree { + base: _, + static_segments, + dynamic_segments, + sources, + catch_all_sources, + fallback_sources, + not_found_sources, + } = &mut this; + sources.iter_mut().for_each(|s| *s = mapper.map_get_content(*s)); + catch_all_sources.iter_mut().for_each(|s| *s = mapper.map_get_content(*s)); + fallback_sources.iter_mut().for_each(|s| *s = mapper.map_get_content(*s)); + not_found_sources.iter_mut().for_each(|s| *s = mapper.map_get_content(*s)); + static_segments.values_mut().for_each(|r| *r = r.map_routes(mapper)); + dynamic_segments.iter_mut().for_each(|r| *r = r.map_routes(mapper)); + Ok(this.cell()) + } +} + +/// Transformation functor +#[turbo_tasks::value_trait] +pub trait MapGetContentSourceContent { + fn map_get_content( + self: Vc, + get_content:Vc>, + ) -> Vc>; +} diff --git a/crates/turbopack-dev-server/Source/source/router.rs b/crates/turbopack-dev-server/Source/source/router.rs new file mode 100644 index 0000000000000..59d57c8bca525 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/router.rs @@ -0,0 +1,163 @@ +use std::iter::once; + +use anyhow::Result; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, Vc}; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; + +use super::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + ContentSourceDataVary, + GetContentSourceContent, + route_tree::{BaseSegment, RouteTree, RouteTrees}, +}; +use crate::source::{ContentSources, route_tree::MapGetContentSourceContent}; + +/// Binds different ContentSources to different subpaths. The request path must +/// begin with the prefix, which will be stripped (along with the subpath) +/// before querying the ContentSource. A fallback ContentSource will serve all +/// other subpaths, including if the request path does not include the prefix. +#[turbo_tasks::value(shared)] +pub struct PrefixedRouterContentSource { + pub prefix:Vc, + pub routes:Vec<(RcStr, Vc>)>, + pub fallback:Vc>, +} + +#[turbo_tasks::value_impl] +impl PrefixedRouterContentSource { + #[turbo_tasks::function] + pub async fn new( + prefix:Vc, + routes:Vec<(RcStr, Vc>)>, + fallback:Vc>, + ) -> Result> { + Ok(PrefixedRouterContentSource { prefix, routes, fallback }.cell()) + } +} + +fn get_children( + routes:&[(RcStr, Vc>)], + fallback:&Vc>, +) -> Vc { + Vc::cell(routes.iter().map(|r| r.1).chain(std::iter::once(*fallback)).collect()) +} + +async fn get_introspection_children( + routes:&[(RcStr, Vc>)], + fallback:&Vc>, +) -> Result> { + Ok(Vc::cell( + routes + .iter() + .cloned() + .chain(std::iter::once((RcStr::default(), *fallback))) + .map(|(path, source)| { + async move { + Ok(Vc::try_resolve_sidecast::>(source) + .await? + .map(|i| (Vc::cell(path), i))) + } + }) + .try_join() + .await? + .into_iter() + .flatten() + .collect(), + )) +} + +#[turbo_tasks::value_impl] +impl ContentSource for PrefixedRouterContentSource { + #[turbo_tasks::function] + async fn get_routes(&self) -> Result> { + let prefix = &*self.prefix.await?; + if cfg!(debug_assertions) { + debug_assert!(prefix.is_empty() || prefix.ends_with('/')); + debug_assert!(!prefix.starts_with('/')); + } + let prefix = (!prefix.is_empty()) + .then(|| BaseSegment::from_static_pathname(prefix.as_str()).collect()) + .unwrap_or(Vec::new()); + let inner_trees = self.routes.iter().map(|(path, source)| { + let prepended_base = + prefix.iter().cloned().chain(BaseSegment::from_static_pathname(path)).collect(); + source.get_routes().with_prepended_base(prepended_base).map_routes(Vc::upcast( + PrefixedRouterContentSourceMapper { prefix:self.prefix, path:path.clone() }.cell(), + )) + }); + Ok( + Vc::::cell(inner_trees.chain(once(self.fallback.get_routes())).collect()) + .merge(), + ) + } + + #[turbo_tasks::function] + fn get_children(&self) -> Vc { get_children(&self.routes, &self.fallback) } +} + +#[turbo_tasks::value] +struct PrefixedRouterContentSourceMapper { + prefix:Vc, + path:RcStr, +} + +#[turbo_tasks::value_impl] +impl MapGetContentSourceContent for PrefixedRouterContentSourceMapper { + #[turbo_tasks::function] + fn map_get_content( + self: Vc, + get_content:Vc>, + ) -> Vc> { + Vc::upcast(PrefixedRouterGetContentSourceContent { mapper:self, get_content }.cell()) + } +} + +#[turbo_tasks::value] +struct PrefixedRouterGetContentSourceContent { + mapper:Vc, + get_content:Vc>, +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for PrefixedRouterGetContentSourceContent { + #[turbo_tasks::function] + fn vary(&self) -> Vc { self.get_content.vary() } + + #[turbo_tasks::function] + async fn get( + &self, + path:RcStr, + data:Value, + ) -> Result> { + let prefix = self.mapper.await?.prefix.await?; + if let Some(path) = path.strip_prefix(&**prefix) { + if path.is_empty() { + return Ok(self.get_content.get("".into(), data)); + } else if prefix.is_empty() { + return Ok(self.get_content.get(path.into(), data)); + } else if let Some(path) = path.strip_prefix('/') { + return Ok(self.get_content.get(path.into(), data)); + } + } + Ok(ContentSourceContent::not_found()) + } +} + +#[turbo_tasks::value_impl] +impl Introspectable for PrefixedRouterContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { Vc::cell("prefixed router content source".into()) } + + #[turbo_tasks::function] + async fn details(&self) -> Result> { + let prefix = self.prefix.await?; + Ok(Vc::cell(format!("prefix: '{}'", prefix).into())) + } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + get_introspection_children(&self.routes, &self.fallback).await + } +} diff --git a/crates/turbopack-dev-server/Source/source/static_assets.rs b/crates/turbopack-dev-server/Source/source/static_assets.rs new file mode 100644 index 0000000000000..7d1f072624a25 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/static_assets.rs @@ -0,0 +1,145 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemPath}; +use turbopack_core::{ + asset::Asset, + file_source::FileSource, + introspect::{Introspectable, IntrospectableChildren, source::IntrospectableSource}, + version::VersionedContentExt, +}; + +use super::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + GetContentSourceContent, + route_tree::{BaseSegment, RouteTree, RouteTrees, RouteType}, +}; + +#[turbo_tasks::value(shared)] +pub struct StaticAssetsContentSource { + pub prefix:Vc, + pub dir:Vc, +} + +#[turbo_tasks::value_impl] +impl StaticAssetsContentSource { + // TODO(WEB-1151): Remove this method and migrate users to `with_prefix`. + #[turbo_tasks::function] + pub fn new(prefix:RcStr, dir:Vc) -> Vc { + StaticAssetsContentSource::with_prefix(Vc::cell(prefix), dir) + } + + #[turbo_tasks::function] + pub async fn with_prefix( + prefix:Vc, + dir:Vc, + ) -> Result> { + if cfg!(debug_assertions) { + let prefix_string = prefix.await?; + debug_assert!(prefix_string.is_empty() || prefix_string.ends_with('/')); + debug_assert!(!prefix_string.starts_with('/')); + } + Ok(StaticAssetsContentSource { prefix, dir }.cell()) + } +} + +// TODO(WEB-1251) It would be better to lazily enumerate the directory +#[turbo_tasks::function] +async fn get_routes_from_directory(dir:Vc) -> Result> { + let dir = dir.read_dir().await?; + let DirectoryContent::Entries(entries) = &*dir else { + return Ok(RouteTree::empty()); + }; + + let routes = entries + .iter() + .flat_map(|(name, entry)| { + match entry { + DirectoryEntry::File(path) | DirectoryEntry::Symlink(path) => { + Some(RouteTree::new_route( + vec![BaseSegment::Static(name.clone())], + RouteType::Exact, + Vc::upcast(StaticAssetsContentSourceItem::new(*path)), + )) + }, + DirectoryEntry::Directory(path) => { + Some( + get_routes_from_directory(*path) + .with_prepended_base(vec![BaseSegment::Static(name.clone())]), + ) + }, + _ => None, + } + }) + .collect(); + Ok(Vc::::cell(routes).merge()) +} + +#[turbo_tasks::value_impl] +impl ContentSource for StaticAssetsContentSource { + #[turbo_tasks::function] + async fn get_routes(&self) -> Result> { + let prefix = self.prefix.await?; + let prefix = BaseSegment::from_static_pathname(prefix.as_str()).collect::>(); + Ok(get_routes_from_directory(self.dir).with_prepended_base(prefix)) + } +} + +#[turbo_tasks::value] +struct StaticAssetsContentSourceItem { + path:Vc, +} + +#[turbo_tasks::value_impl] +impl StaticAssetsContentSourceItem { + #[turbo_tasks::function] + pub fn new(path:Vc) -> Vc { + StaticAssetsContentSourceItem { path }.cell() + } +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for StaticAssetsContentSourceItem { + #[turbo_tasks::function] + fn get(&self, _path:RcStr, _data:Value) -> Vc { + let content = Vc::upcast::>(FileSource::new(self.path)).content(); + ContentSourceContent::static_content(content.versioned()) + } +} + +#[turbo_tasks::value_impl] +impl Introspectable for StaticAssetsContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { Vc::cell("static assets directory content source".into()) } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + let dir = self.dir.read_dir().await?; + let DirectoryContent::Entries(entries) = &*dir else { + return Ok(Vc::cell(Default::default())); + }; + + let prefix = self.prefix.await?; + let children = entries + .iter() + .map(|(name, entry)| { + let child = match entry { + DirectoryEntry::File(path) | DirectoryEntry::Symlink(path) => { + IntrospectableSource::new(Vc::upcast(FileSource::new(*path))) + }, + DirectoryEntry::Directory(path) => { + Vc::upcast(StaticAssetsContentSource::with_prefix( + Vc::cell(format!("{}{name}/", &*prefix).into()), + *path, + )) + }, + DirectoryEntry::Other(_) => todo!("what's DirectoryContent::Other?"), + DirectoryEntry::Error => todo!(), + }; + (Vc::cell(name.clone()), child) + }) + .collect(); + Ok(Vc::cell(children)) + } +} diff --git a/crates/turbopack-dev-server/Source/source/wrapping_source.rs b/crates/turbopack-dev-server/Source/source/wrapping_source.rs new file mode 100644 index 0000000000000..15b1926d04a48 --- /dev/null +++ b/crates/turbopack-dev-server/Source/source/wrapping_source.rs @@ -0,0 +1,95 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, Vc}; + +use super::{ + ContentSourceContent, + ContentSourceData, + ContentSourceDataVary, + GetContentSourceContent, + Rewrite, + RewriteType, +}; + +/// A ContentSourceProcessor handles the final processing of an eventual +/// [ContentSourceContent]. +/// +/// Used in conjunction with [WrappedGetContentSourceContent], this allows a +/// [ContentSource] implementation to easily register a final process step over +/// some inner ContentSource's fully resolved [ContentSourceResult] and +/// [ContentSourceContent]. +#[turbo_tasks::value_trait] +pub trait ContentSourceProcessor { + fn process(self: Vc, content:Vc) -> Vc; +} + +/// A WrappedGetContentSourceContent simply wraps the get_content of a +/// [ContentSourceResult], allowing us to process whatever +/// [ContentSourceContent] it would have returned. + +#[turbo_tasks::value] +pub struct WrappedGetContentSourceContent { + inner:Vc>, + processor:Vc>, +} + +#[turbo_tasks::value_impl] +impl WrappedGetContentSourceContent { + #[turbo_tasks::function] + pub async fn new( + inner:Vc>, + processor:Vc>, + ) -> Vc { + WrappedGetContentSourceContent { inner, processor }.cell() + } +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for WrappedGetContentSourceContent { + #[turbo_tasks::function] + fn vary(&self) -> Vc { self.inner.vary() } + + #[turbo_tasks::function] + async fn get( + &self, + path:RcStr, + data:Value, + ) -> Result> { + let res = self.inner.get(path, data); + if let ContentSourceContent::Rewrite(rewrite) = &*res.await? { + let rewrite = rewrite.await?; + return Ok(ContentSourceContent::Rewrite( + Rewrite { + ty:match &rewrite.ty { + RewriteType::Location { .. } | RewriteType::ContentSource { .. } => { + todo!( + "Rewrites for WrappedGetContentSourceContent are not implemented \ + yet" + ) + }, + RewriteType::Sources { sources } => { + RewriteType::Sources { + sources:Vc::cell( + sources + .await? + .iter() + .map(|s| { + Vc::upcast(WrappedGetContentSourceContent::new( + *s, + self.processor, + )) + }) + .collect(), + ), + } + }, + }, + response_headers:rewrite.response_headers, + request_headers:rewrite.request_headers, + } + .cell(), + ) + .cell()); + } + Ok(self.processor.process(res)) + } +} diff --git a/crates/turbopack-dev-server/Source/update/mod.rs b/crates/turbopack-dev-server/Source/update/mod.rs new file mode 100644 index 0000000000000..f07e04a8f32de --- /dev/null +++ b/crates/turbopack-dev-server/Source/update/mod.rs @@ -0,0 +1,4 @@ +pub mod server; +pub mod stream; + +pub(super) use server::UpdateServer; diff --git a/crates/turbopack-dev-server/Source/update/server.rs b/crates/turbopack-dev-server/Source/update/server.rs new file mode 100644 index 0000000000000..06b480f08f985 --- /dev/null +++ b/crates/turbopack-dev-server/Source/update/server.rs @@ -0,0 +1,262 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use anyhow::{Context as _, Error, Result}; +use futures::{SinkExt, prelude::*, ready, stream::FusedStream}; +use hyper::{HeaderMap, Uri, upgrade::Upgraded}; +use hyper_tungstenite::{HyperWebsocket, WebSocketStream, tungstenite::Message}; +use pin_project_lite::pin_project; +use tokio::select; +use tokio_stream::StreamMap; +use tracing::{Level, instrument}; +use turbo_tasks::{TransientInstance, TurboTasksApi, Vc}; +use turbo_tasks_fs::json::parse_json_with_source_context; +use turbopack_core::{error::PrettyPrintError, issue::IssueReporter, version::Update}; +use turbopack_ecmascript_hmr_protocol::{ + ClientMessage, + ClientUpdateInstruction, + Issue, + ResourceIdentifier, +}; + +use super::stream::UpdateStream; +use crate::{ + SourceProvider, + source::{Body, request::SourceRequest, resolve::resolve_source_request}, + update::stream::UpdateStreamItem, +}; + +/// A server that listens for updates and sends them to connected clients. +pub(crate) struct UpdateServer { + source_provider:P, + #[allow(dead_code)] + issue_reporter:Vc>, +} + +impl UpdateServer

    { + /// Create a new update server with the given websocket and content source. + pub fn new(source_provider:P, issue_reporter:Vc>) -> Self { + Self { source_provider, issue_reporter } + } + + /// Run the update server loop. + pub fn run(self, tt:&dyn TurboTasksApi, ws:HyperWebsocket) { + tt.run_once_process(Box::pin(async move { + if let Err(err) = self.run_internal(ws).await { + println!("[UpdateServer]: error {:#}", err); + } + Ok(()) + })); + } + + #[instrument(level = Level::TRACE, skip_all, name = "UpdateServer::run_internal")] + async fn run_internal(self, ws:HyperWebsocket) -> Result<()> { + let mut client:UpdateClient = ws.await?.into(); + + let mut streams = StreamMap::new(); + + loop { + select! { + message = client.try_next() => { + match message? { + Some(ClientMessage::Subscribe { resource }) => { + let get_content = { + let source_provider = self.source_provider.clone(); + let request = resource_to_request(&resource)?; + move || { + let request = request.clone(); + let source = source_provider.get_source(); + resolve_source_request( + source, + TransientInstance::new(request) + ) + } + }; + match UpdateStream::new(resource.to_string().into(), TransientInstance::new(Box::new(get_content))).await { + Ok(stream) => { + streams.insert(resource, stream); + } + Err(err) => { + eprintln!("Failed to create update stream for {resource}: {}", PrettyPrintError(&err)); + client + .send(ClientUpdateInstruction::not_found(&resource)) + .await?; + } + } + } + Some(ClientMessage::Unsubscribe { resource }) => { + streams.remove(&resource); + } + None => { + // WebSocket was closed, stop sending updates + break; + } + } + } + Some((resource, update)) = streams.next() => { + match update { + Ok(update) => { + Self::send_update(&mut client, &mut streams, resource, &update).await?; + } + Err(err) => { + eprintln!("Failed to get update for {resource}: {}", PrettyPrintError(&err)); + } + } + } + else => break + } + } + + Ok(()) + } + + async fn send_update( + client:&mut UpdateClient, + streams:&mut StreamMap, + resource:ResourceIdentifier, + item:&UpdateStreamItem, + ) -> Result<()> { + match item { + UpdateStreamItem::NotFound => { + // If the resource was not found, we remove the stream and indicate that to the + // client. + streams.remove(&resource); + client.send(ClientUpdateInstruction::not_found(&resource)).await?; + }, + UpdateStreamItem::Found { update, issues } => { + let issues = issues.iter().map(|p| (&**p).into()).collect::>>(); + match &**update { + Update::Partial(partial) => { + let partial_instruction = &partial.instruction; + client + .send(ClientUpdateInstruction::partial( + &resource, + partial_instruction, + &issues, + )) + .await?; + }, + Update::Total(_total) => { + client.send(ClientUpdateInstruction::restart(&resource, &issues)).await?; + }, + Update::None => { + client.send(ClientUpdateInstruction::issues(&resource, &issues)).await?; + }, + } + }, + } + + Ok(()) + } +} + +fn resource_to_request(resource:&ResourceIdentifier) -> Result { + let mut headers = HeaderMap::new(); + + if let Some(res_headers) = &resource.headers { + for (name, value) in res_headers { + headers.append( + hyper::header::HeaderName::from_bytes(name.as_bytes()).unwrap(), + hyper::header::HeaderValue::from_bytes(value.as_bytes()).unwrap(), + ); + } + } + + Ok(SourceRequest { + uri:Uri::try_from(format!("/{}", resource.path))?, + headers, + method:"GET".to_string(), + body:Body::new(vec![]), + }) +} + +pin_project! { + struct UpdateClient { + #[pin] + ws: WebSocketStream, + ended: bool, + } +} + +impl Stream for UpdateClient { + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx:&mut Context<'_>) -> Poll> { + if self.ended { + return Poll::Ready(None); + } + + let this = self.project(); + let item = ready!(this.ws.poll_next(cx)); + + let msg = match item { + Some(Ok(Message::Text(msg))) => msg, + Some(Err(err)) => { + *this.ended = true; + + let err = Error::new(err).context("reading from websocket"); + return Poll::Ready(Some(Err(err))); + }, + _ => { + *this.ended = true; + return Poll::Ready(None); + }, + }; + + match parse_json_with_source_context(&msg).context("deserializing websocket message") { + Ok(msg) => Poll::Ready(Some(Ok(msg))), + Err(err) => { + *this.ended = true; + + Poll::Ready(Some(Err(err))) + }, + } + } +} + +impl FusedStream for UpdateClient { + fn is_terminated(&self) -> bool { self.ended || self.ws.is_terminated() } +} + +impl<'a> Sink> for UpdateClient { + type Error = Error; + + fn poll_ready( + self: Pin<&mut Self>, + cx:&mut Context<'_>, + ) -> Poll> { + self.project() + .ws + .poll_ready(cx) + .map(|res| res.context("polling WebSocket ready")) + } + + fn start_send( + self: Pin<&mut Self>, + item:ClientUpdateInstruction<'a>, + ) -> std::result::Result<(), Self::Error> { + let msg = Message::text(serde_json::to_string(&item)?); + + self.project().ws.start_send(msg).context("sending to WebSocket") + } + + fn poll_flush( + self: Pin<&mut Self>, + cx:&mut Context<'_>, + ) -> Poll> { + self.project().ws.poll_flush(cx).map(|res| res.context("flushing WebSocket")) + } + + fn poll_close( + self: Pin<&mut Self>, + cx:&mut Context<'_>, + ) -> Poll> { + self.project().ws.poll_close(cx).map(|res| res.context("closing WebSocket")) + } +} + +impl From> for UpdateClient { + fn from(ws:WebSocketStream) -> Self { Self { ws, ended:false } } +} diff --git a/crates/turbopack-dev-server/Source/update/stream.rs b/crates/turbopack-dev-server/Source/update/stream.rs new file mode 100644 index 0000000000000..9e713788f3b04 --- /dev/null +++ b/crates/turbopack-dev-server/Source/update/stream.rs @@ -0,0 +1,294 @@ +use std::pin::Pin; + +use anyhow::Result; +use futures::prelude::*; +use tokio::sync::mpsc::Sender; +use tokio_stream::wrappers::ReceiverStream; +use tracing::Instrument; +use turbo_tasks::{IntoTraitRef, RcStr, ReadRef, TransientInstance, Vc}; +use turbo_tasks_fs::{FileSystem, FileSystemPath}; +use turbopack_core::{ + error::PrettyPrintError, + issue::{ + Issue, + IssueDescriptionExt, + IssueSeverity, + IssueStage, + OptionIssueProcessingPathItems, + OptionStyledString, + PlainIssue, + StyledString, + }, + server_fs::ServerFileSystem, + version::{ + NotFoundVersion, + PartialUpdate, + TotalUpdate, + Update, + Version, + VersionState, + VersionedContent, + }, +}; + +use crate::source::{ProxyResult, resolve::ResolveSourceRequestResult}; + +type GetContentFn = Box Vc + Send + Sync>; + +async fn peek_issues(source:Vc) -> Result>> { + let captured = source.peek_issues_with_path().await?; + + captured.get_plain_issues().await +} + +fn extend_issues(issues:&mut Vec>, new_issues:Vec>) { + for issue in new_issues { + if issues.contains(&issue) { + continue; + } + + issues.push(issue); + } +} + +#[turbo_tasks::function] +async fn get_update_stream_item( + resource:RcStr, + from:Vc, + get_content:TransientInstance, +) -> Result> { + let content = get_content(); + let _ = content.resolve_strongly_consistent().await?; + let mut plain_issues = peek_issues(content).await?; + + let content_value = match content.await { + Ok(content) => content, + Err(e) => { + plain_issues.push( + FatalStreamIssue { + resource, + description:StyledString::Text(format!("{}", PrettyPrintError(&e)).into()) + .cell(), + } + .cell() + .into_plain(OptionIssueProcessingPathItems::none()) + .await?, + ); + + let update = Update::Total(TotalUpdate { + to:Vc::upcast::>(NotFoundVersion::new()).into_trait_ref().await?, + }) + .cell(); + return Ok(UpdateStreamItem::Found { update:update.await?, issues:plain_issues }.cell()); + }, + }; + + match *content_value { + ResolveSourceRequestResult::Static(static_content_vc, _) => { + let static_content = static_content_vc.await?; + + // This can happen when a chunk is removed from the asset graph. + if static_content.status_code == 404 { + return Ok(UpdateStreamItem::NotFound.cell()); + } + + let resolved_content = static_content.content; + let from = from.get(); + let update = resolved_content.update(from); + + extend_issues(&mut plain_issues, peek_issues(update).await?); + + let update = update.await?; + + Ok(UpdateStreamItem::Found { update, issues:plain_issues }.cell()) + }, + ResolveSourceRequestResult::HttpProxy(proxy_result) => { + let proxy_result_value = proxy_result.await?; + + if proxy_result_value.status == 404 { + return Ok(UpdateStreamItem::NotFound.cell()); + } + + extend_issues(&mut plain_issues, peek_issues(proxy_result).await?); + + let from = from.get(); + if let Some(from) = Vc::try_resolve_downcast_type::(from).await? { + if from.await? == proxy_result_value { + return Ok(UpdateStreamItem::Found { + update:Update::None.cell().await?, + issues:plain_issues, + } + .cell()); + } + } + + Ok(UpdateStreamItem::Found { + update:Update::Total(TotalUpdate { + to:Vc::upcast::>(proxy_result).into_trait_ref().await?, + }) + .cell() + .await?, + issues:plain_issues, + } + .cell()) + }, + _ => { + let update = if plain_issues.is_empty() { + // Client requested a non-existing asset + // It might be removed in meantime, reload client + // TODO add special instructions for removed assets to handled it in a better + // way + Update::Total(TotalUpdate { + to:Vc::upcast::>(NotFoundVersion::new()) + .into_trait_ref() + .await?, + }) + .cell() + } else { + Update::None.cell() + }; + + Ok(UpdateStreamItem::Found { update:update.await?, issues:plain_issues }.cell()) + }, + } +} + +#[turbo_tasks::function] +async fn compute_update_stream( + resource:RcStr, + from:Vc, + get_content:TransientInstance, + sender:TransientInstance>>>, +) -> Result> { + let item = get_update_stream_item(resource, from, get_content).strongly_consistent().await; + + // Send update. Ignore channel closed error. + let _ = sender.send(item).await; + + Ok(Default::default()) +} + +pub(super) struct UpdateStream( + Pin>> + Send + Sync>>, +); + +impl UpdateStream { + #[tracing::instrument(skip(get_content), name = "UpdateStream::new")] + pub async fn new( + resource:RcStr, + get_content:TransientInstance, + ) -> Result { + let (sx, rx) = tokio::sync::mpsc::channel(32); + + let content = get_content(); + // We can ignore issues reported in content here since [compute_update_stream] + // will handle them + let version = match *content.await? { + ResolveSourceRequestResult::Static(static_content, _) => { + static_content.await?.content.version() + }, + ResolveSourceRequestResult::HttpProxy(proxy_result) => Vc::upcast(proxy_result), + _ => Vc::upcast(NotFoundVersion::new()), + }; + let version_state = VersionState::new(version.into_trait_ref().await?).await?; + + let _ = + compute_update_stream(resource, version_state, get_content, TransientInstance::new(sx)); + + let mut last_had_issues = false; + + let stream = ReceiverStream::new(rx).filter_map(move |item| { + { + let (has_issues, issues_changed) = + if let Ok(UpdateStreamItem::Found { issues, .. }) = item.as_deref() { + let has_issues = !issues.is_empty(); + let issues_changed = has_issues != last_had_issues; + last_had_issues = has_issues; + (has_issues, issues_changed) + } else { + (false, false) + }; + + async move { + match item.as_deref() { + Ok(UpdateStreamItem::Found { update, .. }) => { + match &**update { + Update::Partial(PartialUpdate { to, .. }) + | Update::Total(TotalUpdate { to }) => { + version_state + .set(to.clone()) + .await + .expect("failed to update version"); + + Some(item) + }, + // Do not propagate empty updates. + Update::None => { + if has_issues || issues_changed { + Some(item) + } else { + None + } + }, + } + }, + _ => { + // Propagate other updates + Some(item) + }, + } + } + .in_current_span() + } + .in_current_span() + }); + + Ok(UpdateStream(Box::pin(stream))) + } +} + +impl Stream for UpdateStream { + type Item = Result>; + + fn poll_next( + self: Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll> { + Pin::new(&mut self.get_mut().0).poll_next(cx) + } +} + +#[turbo_tasks::value(serialization = "none")] +#[derive(Debug)] +pub enum UpdateStreamItem { + NotFound, + Found { update:ReadRef, issues:Vec> }, +} + +#[turbo_tasks::value(serialization = "none")] +struct FatalStreamIssue { + description:Vc, + resource:RcStr, +} + +#[turbo_tasks::value_impl] +impl Issue for FatalStreamIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Fatal.into() } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Other("websocket".into()).cell() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { + ServerFileSystem::new().root().join(self.resource.clone()) + } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Fatal error while getting content to stream".into()).cell() + } + + #[turbo_tasks::function] + fn description(&self) -> Vc { Vc::cell(Some(self.description)) } +} diff --git a/crates/turbopack-dev-server/build.rs b/crates/turbopack-dev-server/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-dev-server/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-ecmascript-hmr-protocol/Source/lib.rs b/crates/turbopack-ecmascript-hmr-protocol/Source/lib.rs new file mode 100644 index 0000000000000..e6b794d0f831e --- /dev/null +++ b/crates/turbopack-ecmascript-hmr-protocol/Source/lib.rs @@ -0,0 +1,176 @@ +use std::{collections::BTreeMap, fmt::Display, ops::Deref, path::PathBuf}; + +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use turbopack_cli_utils::issue::{LogOptions, format_issue}; +use turbopack_core::{ + issue::{IssueSeverity, IssueStage, PlainIssue, StyledString}, + source_pos::SourcePos, +}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ResourceIdentifier { + pub path:String, + pub headers:Option>, +} + +impl Display for ResourceIdentifier { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.path)?; + if let Some(headers) = &self.headers { + for (key, value) in headers.iter() { + write!(f, " [{}: {}]", key, value)?; + } + } + Ok(()) + } +} + +#[derive(Deserialize)] +#[serde(tag = "type")] +pub enum ClientMessage { + #[serde(rename = "turbopack-subscribe")] + Subscribe { + #[serde(flatten)] + resource:ResourceIdentifier, + }, + #[serde(rename = "turbopack-unsubscribe")] + Unsubscribe { + #[serde(flatten)] + resource:ResourceIdentifier, + }, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ClientUpdateInstruction<'a> { + pub resource:&'a ResourceIdentifier, + #[serde(flatten)] + pub ty:ClientUpdateInstructionType<'a>, + pub issues:&'a [Issue<'a>], +} + +pub const EMPTY_ISSUES:&[Issue<'static>] = &[]; + +impl<'a> ClientUpdateInstruction<'a> { + pub fn new( + resource:&'a ResourceIdentifier, + ty:ClientUpdateInstructionType<'a>, + issues:&'a [Issue<'a>], + ) -> Self { + Self { resource, ty, issues } + } + + pub fn restart(resource:&'a ResourceIdentifier, issues:&'a [Issue<'a>]) -> Self { + Self::new(resource, ClientUpdateInstructionType::Restart, issues) + } + + /// Returns a [`ClientUpdateInstruction`] that indicates that the resource + /// was not found. + pub fn not_found(resource:&'a ResourceIdentifier) -> Self { + Self::new(resource, ClientUpdateInstructionType::NotFound, &[]) + } + + pub fn partial( + resource:&'a ResourceIdentifier, + instruction:&'a Value, + issues:&'a [Issue<'a>], + ) -> Self { + Self::new(resource, ClientUpdateInstructionType::Partial { instruction }, issues) + } + + pub fn issues(resource:&'a ResourceIdentifier, issues:&'a [Issue<'a>]) -> Self { + Self::new(resource, ClientUpdateInstructionType::Issues, issues) + } + + pub fn with_issues(self, issues:&'a [Issue<'a>]) -> Self { + Self { resource:self.resource, ty:self.ty, issues } + } +} + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum ClientUpdateInstructionType<'a> { + Restart, + NotFound, + Partial { instruction:&'a Value }, + Issues, +} + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum ServerError { + SSR(String), + Turbo(String), +} + +#[derive(Serialize)] +pub struct Asset<'a> { + pub path:&'a str, +} + +#[derive(Serialize)] +pub struct IssueSource<'a> { + pub asset:Asset<'a>, + pub range:Option, +} + +#[derive(Serialize)] +pub struct IssueSourceRange { + pub start:SourcePos, + pub end:SourcePos, +} + +#[derive(Serialize)] +pub struct Issue<'a> { + pub severity:IssueSeverity, + pub file_path:&'a str, + pub stage:&'a IssueStage, + + pub title:&'a StyledString, + pub description:Option<&'a StyledString>, + pub detail:Option<&'a StyledString>, + pub documentation_link:&'a str, + + pub source:Option>, + pub sub_issues:Vec>, + + pub formatted:String, +} + +impl<'a> From<&'a PlainIssue> for Issue<'a> { + fn from(plain:&'a PlainIssue) -> Self { + let source = plain.source.as_deref().map(|source| { + IssueSource { + asset:Asset { path:&source.asset.ident }, + range:source.range.map(|(start, end)| IssueSourceRange { start, end }), + } + }); + + Issue { + severity:plain.severity, + file_path:&plain.file_path, + stage:&plain.stage, + title:&plain.title, + description:plain.description.as_ref(), + documentation_link:&plain.documentation_link, + detail:plain.detail.as_ref(), + source, + sub_issues:plain.sub_issues.iter().map(|p| p.deref().into()).collect(), + // TODO(WEB-691) formatting the issue should be handled by the error overlay. + // The browser could handle error formatting in a better way than the text only + // formatting here + formatted:format_issue( + plain, + None, + &LogOptions { + current_dir:PathBuf::new(), + project_dir:PathBuf::new(), + show_all:true, + log_detail:true, + log_level:IssueSeverity::Info, + }, + ), + } + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/lib.rs b/crates/turbopack-ecmascript-plugins/Source/lib.rs new file mode 100644 index 0000000000000..0bbfe67c87dfd --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/lib.rs @@ -0,0 +1,9 @@ +#![feature(arbitrary_self_types)] + +pub mod transform; + +pub fn register() { + turbo_tasks::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/directives/client.rs b/crates/turbopack-ecmascript-plugins/Source/transform/directives/client.rs new file mode 100644 index 0000000000000..6ebc891ddcd6b --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/directives/client.rs @@ -0,0 +1,30 @@ +use anyhow::Result; +use async_trait::async_trait; +use swc_core::ecma::{ast::Program, transforms::base::resolver, visit::VisitMutWith}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +use super::{is_client_module, server_to_client_proxy::create_proxy_module}; + +#[derive(Debug)] +pub struct ClientDirectiveTransformer { + transition_name:Vc, +} + +impl ClientDirectiveTransformer { + pub fn new(transition_name:Vc) -> Self { Self { transition_name } } +} + +#[async_trait] +impl CustomTransformer for ClientDirectiveTransformer { + #[tracing::instrument(level = tracing::Level::TRACE, name = "client_directive", skip_all)] + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + if is_client_module(program) { + let transition_name = &*self.transition_name.await?; + *program = create_proxy_module(transition_name, &format!("./{}", ctx.file_name_str)); + program.visit_mut_with(&mut resolver(ctx.unresolved_mark, ctx.top_level_mark, false)); + } + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/directives/client_disallowed.rs b/crates/turbopack-ecmascript-plugins/Source/transform/directives/client_disallowed.rs new file mode 100644 index 0000000000000..a54bf5bd519cf --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/directives/client_disallowed.rs @@ -0,0 +1,27 @@ +use anyhow::Result; +use async_trait::async_trait; +use swc_core::ecma::{ast::Program, transforms::base::resolver, visit::VisitMutWith}; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +use super::{is_client_module, server_to_client_proxy::create_error_proxy_module}; + +#[derive(Debug)] +pub struct ClientDisallowedDirectiveTransformer { + error_proxy_module:String, +} + +impl ClientDisallowedDirectiveTransformer { + pub fn new(error_proxy_module:String) -> Self { Self { error_proxy_module } } +} + +#[async_trait] +impl CustomTransformer for ClientDisallowedDirectiveTransformer { + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + if is_client_module(program) { + *program = create_error_proxy_module(&self.error_proxy_module); + program.visit_mut_with(&mut resolver(ctx.unresolved_mark, ctx.top_level_mark, false)); + } + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/directives/mod.rs b/crates/turbopack-ecmascript-plugins/Source/transform/directives/mod.rs new file mode 100644 index 0000000000000..e345193f5985e --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/directives/mod.rs @@ -0,0 +1,40 @@ +use swc_core::ecma::ast::{Lit, Program}; + +pub mod client; +pub mod client_disallowed; +pub mod server; +mod server_to_client_proxy; + +macro_rules! has_directive { + ($stmts:expr, $name:literal) => { + $stmts + .map(|item| { + if let Lit::Str(str) = item?.as_expr()?.expr.as_lit()? { + Some(str) + } else { + None + } + }) + .take_while(Option::is_some) + .map(Option::unwrap) + .any(|s| &*s.value == $name) + }; +} + +fn is_client_module(program:&Program) -> bool { + match program { + Program::Module(m) => { + has_directive!(m.body.iter().map(|item| item.as_stmt()), "use client") + }, + Program::Script(s) => has_directive!(s.body.iter().map(Some), "use client"), + } +} + +fn is_server_module(program:&Program) -> bool { + match program { + Program::Module(m) => { + has_directive!(m.body.iter().map(|item| item.as_stmt()), "use server") + }, + Program::Script(s) => has_directive!(s.body.iter().map(Some), "use server"), + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/directives/server.rs b/crates/turbopack-ecmascript-plugins/Source/transform/directives/server.rs new file mode 100644 index 0000000000000..fb87dd0067d43 --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/directives/server.rs @@ -0,0 +1,43 @@ +use anyhow::Result; +use async_trait::async_trait; +use swc_core::{ + ecma::ast::{ModuleItem, Program}, + quote, +}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::issue::IssueExt; +use turbopack_ecmascript::{CustomTransformer, TransformContext, UnsupportedServerActionIssue}; + +use super::is_server_module; + +#[derive(Debug)] +pub struct ServerDirectiveTransformer { + // ServerDirective is not implemented yet and always reports an issue. + // We don't have to pass a valid transition name yet, but the API is prepared. + #[allow(unused)] + transition_name:Vc, +} + +impl ServerDirectiveTransformer { + pub fn new(transition_name:&Vc) -> Self { Self { transition_name:*transition_name } } +} + +#[async_trait] +impl CustomTransformer for ServerDirectiveTransformer { + #[tracing::instrument(level = tracing::Level::TRACE, name = "server_directive", skip_all)] + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + if is_server_module(program) { + let stmt = quote!( + "throw new Error('Server actions (\"use server\") are not yet supported in \ + Turbopack');" as Stmt + ); + match program { + Program::Module(m) => m.body = vec![ModuleItem::Stmt(stmt)], + Program::Script(s) => s.body = vec![stmt], + } + UnsupportedServerActionIssue { file_path:ctx.file_path }.cell().emit(); + } + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/directives/server_to_client_proxy.rs b/crates/turbopack-ecmascript-plugins/Source/transform/directives/server_to_client_proxy.rs new file mode 100644 index 0000000000000..7211fa170afc9 --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/directives/server_to_client_proxy.rs @@ -0,0 +1,74 @@ +use swc_core::{ + common::DUMMY_SP, + ecma::{ + ast::{ + ImportDecl, + ImportDefaultSpecifier, + ImportSpecifier, + ImportStarAsSpecifier, + Module, + ModuleDecl, + ModuleItem, + Program, + }, + utils::private_ident, + }, + quote, +}; +use turbopack_ecmascript::{ + TURBOPACK_HELPER, + annotations::{ANNOTATION_TRANSITION, with_clause}, +}; + +pub fn create_proxy_module(transition_name:&str, target_import:&str) -> Program { + let ident = private_ident!("clientProxy"); + Program::Module(Module { + body:vec![ + ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + specifiers:vec![ImportSpecifier::Namespace(ImportStarAsSpecifier { + local:ident.clone(), + span:DUMMY_SP, + })], + src:Box::new(target_import.into()), + type_only:false, + with:Some(with_clause(&[ + (TURBOPACK_HELPER.as_str(), "true"), + (ANNOTATION_TRANSITION, transition_name), + ])), + span:DUMMY_SP, + phase:Default::default(), + })), + ModuleItem::Stmt(quote!( + "__turbopack_export_namespace__($proxy);" as Stmt, + proxy = ident, + )), + ], + shebang:None, + span:DUMMY_SP, + }) +} + +pub fn create_error_proxy_module(error_proxy_module:&str) -> Program { + let ident = private_ident!("errorProxy"); + Program::Module(Module { + body:vec![ + ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + specifiers:vec![ImportSpecifier::Default(ImportDefaultSpecifier { + local:ident.clone(), + span:DUMMY_SP, + })], + src:Box::new(error_proxy_module.into()), + type_only:false, + with:Some(with_clause(&[(TURBOPACK_HELPER.as_str(), "true")])), + span:DUMMY_SP, + phase:Default::default(), + })), + ModuleItem::Stmt(quote!( + "__turbopack_export_namespace__($proxy);" as Stmt, + proxy = ident, + )), + ], + shebang:None, + span:DUMMY_SP, + }) +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/emotion.rs b/crates/turbopack-ecmascript-plugins/Source/transform/emotion.rs new file mode 100644 index 0000000000000..f55469d9c2c1f --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/emotion.rs @@ -0,0 +1,113 @@ +#![allow(unused)] +use std::{ + hash::{Hash, Hasher}, + path::Path, +}; + +use anyhow::Result; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use swc_core::{ + common::util::take::Take, + ecma::{ + ast::{Module, Program}, + visit::FoldWith, + }, +}; +use turbo_tasks::{ValueDefault, Vc, trace::TraceRawVcs}; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum EmotionLabelKind { + DevOnly, + Always, + Never, +} + +#[turbo_tasks::value(transparent)] +pub struct OptionEmotionTransformConfig(Option>); + +//[TODO]: need to support importmap, there are type mismatch between +// next.config.js to swc's emotion options +#[turbo_tasks::value(shared)] +#[derive(Default, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct EmotionTransformConfig { + pub sourcemap:Option, + pub label_format:Option, + pub auto_label:Option, +} + +#[turbo_tasks::value_impl] +impl EmotionTransformConfig { + #[turbo_tasks::function] + pub fn default_private() -> Vc { Self::cell(Default::default()) } +} + +impl ValueDefault for EmotionTransformConfig { + fn value_default() -> Vc { EmotionTransformConfig::default_private() } +} + +#[derive(Debug)] +pub struct EmotionTransformer { + #[cfg(feature = "transform_emotion")] + config:swc_emotion::EmotionOptions, +} + +#[cfg(feature = "transform_emotion")] +impl EmotionTransformer { + pub fn new(config:&EmotionTransformConfig) -> Option { + let config = swc_emotion::EmotionOptions { + // When you create a transformer structure, it is assumed that you are performing an + // emotion transform. + enabled:Some(true), + sourcemap:config.sourcemap, + label_format:config.label_format.clone(), + auto_label:if let Some(auto_label) = config.auto_label.as_ref() { + match auto_label { + EmotionLabelKind::Always => Some(true), + EmotionLabelKind::Never => Some(false), + // [TODO]: this is not correct coerece, need to be fixed + EmotionLabelKind::DevOnly => None, + } + } else { + None + }, + ..Default::default() + }; + + Some(EmotionTransformer { config }) + } +} + +#[cfg(not(feature = "transform_emotion"))] +impl EmotionTransformer { + pub fn new(_config:&EmotionTransformConfig) -> Option { None } +} + +#[async_trait] +impl CustomTransformer for EmotionTransformer { + #[tracing::instrument(level = tracing::Level::TRACE, name = "emotion", skip_all)] + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + #[cfg(feature = "transform_emotion")] + { + let p = std::mem::replace(program, Program::Module(Module::dummy())); + let hash = { + #[allow(clippy::disallowed_types)] + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + p.hash(&mut hasher); + hasher.finish() + }; + *program = p.fold_with(&mut swc_emotion::emotion( + self.config.clone(), + Path::new(ctx.file_name_str), + hash as u32, + ctx.source_map.clone(), + ctx.comments.clone(), + )); + } + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/mod.rs b/crates/turbopack-ecmascript-plugins/Source/transform/mod.rs new file mode 100644 index 0000000000000..620985013c091 --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/mod.rs @@ -0,0 +1,7 @@ +pub mod directives; +pub mod emotion; +pub mod modularize_imports; +pub mod relay; +pub mod styled_components; +pub mod styled_jsx; +pub mod swc_ecma_transform_plugins; diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/modularize_imports.rs b/crates/turbopack-ecmascript-plugins/Source/transform/modularize_imports.rs new file mode 100644 index 0000000000000..14b3187682122 --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/modularize_imports.rs @@ -0,0 +1,62 @@ +use std::collections::HashMap; + +use anyhow::Result; +use async_trait::async_trait; +use indexmap::IndexMap; +use modularize_imports::{Config, PackageConfig, modularize_imports}; +use serde::{Deserialize, Serialize}; +use swc_core::{ + common::util::take::Take, + ecma::{ + ast::{Module, Program}, + visit::FoldWith, + }, +}; +use turbo_tasks::trace::TraceRawVcs; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(rename_all = "camelCase")] +pub struct ModularizeImportPackageConfig { + pub transform:String, + #[serde(default)] + pub prevent_full_import:bool, + #[serde(default)] + pub skip_default_conversion:bool, +} + +#[derive(Debug)] +pub struct ModularizeImportsTransformer { + packages:HashMap, +} + +impl ModularizeImportsTransformer { + pub fn new(packages:&IndexMap) -> Self { + Self { + packages:packages + .iter() + .map(|(k, v)| { + ( + k.clone(), + PackageConfig { + transform:modularize_imports::Transform::String(v.transform.clone()), + prevent_full_import:v.prevent_full_import, + skip_default_conversion:v.skip_default_conversion, + }, + ) + }) + .collect(), + } + } +} + +#[async_trait] +impl CustomTransformer for ModularizeImportsTransformer { + #[tracing::instrument(level = tracing::Level::TRACE, name = "modularize_imports", skip_all)] + async fn transform(&self, program:&mut Program, _ctx:&TransformContext<'_>) -> Result<()> { + let p = std::mem::replace(program, Program::Module(Module::dummy())); + *program = p.fold_with(&mut modularize_imports(Config { packages:self.packages.clone() })); + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/relay.rs b/crates/turbopack-ecmascript-plugins/Source/transform/relay.rs new file mode 100644 index 0000000000000..9bd2486d4c2aa --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/relay.rs @@ -0,0 +1,84 @@ +use std::path::PathBuf; + +use anyhow::Result; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use swc_core::{ + common::{FileName, util::take::Take}, + ecma::{ + ast::{Module, Program}, + visit::FoldWith, + }, +}; +use swc_relay::RelayLanguageConfig; +use turbo_tasks::trace::TraceRawVcs; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(rename_all = "camelCase")] +pub struct RelayConfig { + pub src:String, + pub artifact_directory:Option, + pub language:Option, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(rename_all = "lowercase")] +pub enum RelayLanguage { + TypeScript, + Flow, + JavaScript, +} + +#[derive(Debug)] +pub struct RelayTransformer { + config:swc_relay::Config, +} + +impl RelayTransformer { + pub fn new(config:&RelayConfig) -> Self { + let options = swc_relay::Config { + artifact_directory:config.artifact_directory.as_ref().map(PathBuf::from), + language:config.language.as_ref().map_or(RelayLanguageConfig::TypeScript, |v| { + match v { + RelayLanguage::JavaScript => RelayLanguageConfig::JavaScript, + RelayLanguage::TypeScript => RelayLanguageConfig::TypeScript, + RelayLanguage::Flow => RelayLanguageConfig::Flow, + } + }), + ..Default::default() + }; + Self { config:options } + } +} + +#[async_trait] +impl CustomTransformer for RelayTransformer { + #[tracing::instrument(level = tracing::Level::TRACE, name = "relay", skip_all)] + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + // If user supplied artifact_directory, it should be resolvable already. + // Otherwise, supply default relative path (./__generated__) + let (root, config) = if self.config.artifact_directory.is_some() { + (PathBuf::new(), None) + } else { + let config = swc_relay::Config { + artifact_directory:Some(PathBuf::from("__generated__")), + ..self.config + }; + (PathBuf::from("."), Some(config)) + }; + + let p = std::mem::replace(program, Program::Module(Module::dummy())); + *program = p.fold_with(&mut swc_relay::relay( + config.as_ref().unwrap_or(&self.config), + FileName::Real(PathBuf::from(ctx.file_name_str)), + root, + // [TODO]: pages_dir comes through next-swc-loader + // https://github.com/vercel/next.js/blob/ea472e8058faea8ebdab2ef6d3aab257a1f0d11c/packages/next/src/build/webpack-config.ts#L792 + None, + Some(ctx.unresolved_mark), + )); + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/styled_components.rs b/crates/turbopack-ecmascript-plugins/Source/transform/styled_components.rs new file mode 100644 index 0000000000000..ac1969beb84c9 --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/styled_components.rs @@ -0,0 +1,98 @@ +use std::path::PathBuf; + +use anyhow::Result; +use async_trait::async_trait; +use swc_core::{ + common::{FileName, comments::NoopComments}, + ecma::{ast::Program, atoms::JsWord, visit::VisitMutWith}, +}; +use turbo_tasks::{ValueDefault, Vc}; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +#[turbo_tasks::value(transparent)] +pub struct OptionStyledComponentsTransformConfig(Option>); + +#[turbo_tasks::value(shared)] +#[derive(Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct StyledComponentsTransformConfig { + pub display_name:bool, + pub ssr:bool, + pub file_name:bool, + pub top_level_import_paths:Vec, + pub meaningless_file_names:Vec, + pub css_prop:bool, + pub namespace:Option, +} + +impl Default for StyledComponentsTransformConfig { + fn default() -> Self { + StyledComponentsTransformConfig { + display_name:true, + ssr:true, + file_name:true, + top_level_import_paths:vec![], + meaningless_file_names:vec!["index".to_string()], + css_prop:true, + namespace:None, + } + } +} + +#[turbo_tasks::value_impl] +impl StyledComponentsTransformConfig { + #[turbo_tasks::function] + fn default_private() -> Vc { Self::cell(Default::default()) } +} + +impl ValueDefault for StyledComponentsTransformConfig { + fn value_default() -> Vc { StyledComponentsTransformConfig::default_private() } +} + +#[derive(Debug)] +pub struct StyledComponentsTransformer { + config:styled_components::Config, +} + +impl StyledComponentsTransformer { + pub fn new(config:&StyledComponentsTransformConfig) -> Self { + let mut options = styled_components::Config { + display_name:config.display_name, + ssr:config.ssr, + file_name:config.file_name, + css_prop:config.css_prop, + ..Default::default() + }; + + if let Some(namespace) = &config.namespace { + options.namespace.clone_from(namespace); + } + + let top_level_import_paths = &config.top_level_import_paths; + if !top_level_import_paths.is_empty() { + options.top_level_import_paths = + top_level_import_paths.iter().map(|s| JsWord::from(s.clone())).collect(); + } + let meaningless_file_names = &config.meaningless_file_names; + if !meaningless_file_names.is_empty() { + options.meaningless_file_names.clone_from(meaningless_file_names); + } + + Self { config:options } + } +} + +#[async_trait] +impl CustomTransformer for StyledComponentsTransformer { + #[tracing::instrument(level = tracing::Level::TRACE, name = "styled_components", skip_all)] + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + program.visit_mut_with(&mut styled_components::styled_components( + FileName::Real(PathBuf::from(ctx.file_path_str)), + ctx.file_name_hash, + self.config.clone(), + NoopComments, + )); + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/styled_jsx.rs b/crates/turbopack-ecmascript-plugins/Source/transform/styled_jsx.rs new file mode 100644 index 0000000000000..0e3a9260aa004 --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/styled_jsx.rs @@ -0,0 +1,95 @@ +use anyhow::{Result, bail}; +use async_trait::async_trait; +use lightningcss::{ + stylesheet::{PrinterOptions, StyleSheet}, + targets::{Browsers, Targets}, +}; +use swc_core::{ + common::{FileName, util::take::Take}, + ecma::{ + ast::{Module, Program}, + preset_env::{Version, Versions}, + visit::FoldWith, + }, +}; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +#[derive(Debug)] +pub struct StyledJsxTransformer { + use_lightningcss:bool, + target_browsers:Versions, +} + +impl StyledJsxTransformer { + pub fn new(use_lightningcss:bool, target_browsers:Versions) -> Self { + Self { use_lightningcss, target_browsers } + } +} + +#[async_trait] +impl CustomTransformer for StyledJsxTransformer { + #[tracing::instrument(level = tracing::Level::TRACE, name = "styled_jsx", skip_all)] + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + let p = std::mem::replace(program, Program::Module(Module::dummy())); + *program = p.fold_with(&mut styled_jsx::visitor::styled_jsx( + ctx.source_map.clone(), + // styled_jsx don't really use that in a relevant way + FileName::Anon, + styled_jsx::visitor::Config { + use_lightningcss:self.use_lightningcss, + browsers:self.target_browsers, + }, + styled_jsx::visitor::NativeConfig { + process_css:if self.use_lightningcss || self.target_browsers.is_any_target() { + None + } else { + let targets = Targets { + browsers:Some(convert_browsers(&self.target_browsers)), + ..Default::default() + }; + + Some(Box::new(move |css| { + let ss = StyleSheet::parse(css, Default::default()); + + let ss = match ss { + Ok(v) => v, + Err(err) => { + bail!("failed to parse css using lightningcss: {}", err) + }, + }; + + let output = ss.to_css(PrinterOptions { + minify:true, + source_map:None, + project_root:None, + targets, + analyze_dependencies:None, + pseudo_classes:None, + })?; + Ok(output.code) + })) + }, + }, + )); + + Ok(()) + } +} + +fn convert_browsers(browsers:&Versions) -> Browsers { + fn convert(v:Option) -> Option { + v.map(|v| v.major << 16 | v.minor << 8 | v.patch) + } + + Browsers { + android:convert(browsers.android), + chrome:convert(browsers.chrome), + edge:convert(browsers.edge), + firefox:convert(browsers.firefox), + ie:convert(browsers.ie), + ios_saf:convert(browsers.ios), + opera:convert(browsers.opera), + safari:convert(browsers.safari), + samsung:convert(browsers.samsung), + } +} diff --git a/crates/turbopack-ecmascript-plugins/Source/transform/swc_ecma_transform_plugins.rs b/crates/turbopack-ecmascript-plugins/Source/transform/swc_ecma_transform_plugins.rs new file mode 100644 index 0000000000000..3529bf98a8e7c --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/Source/transform/swc_ecma_transform_plugins.rs @@ -0,0 +1,226 @@ +use anyhow::Result; +use async_trait::async_trait; +use swc_core::ecma::ast::Program; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueSeverity, IssueStage, OptionStyledString, StyledString}; +use turbopack_ecmascript::{CustomTransformer, TransformContext}; + +/// A wrapper around an SWC's ecma transform wasm plugin module bytes, allowing +/// it to operate with the turbo_tasks caching requirements. +/// Internally this contains a `CompiledPluginModuleBytes`, which points to the +/// compiled, serialized wasmer::Module instead of raw file bytes to reduce the +/// cost of the compilation. +#[turbo_tasks::value(serialization = "none", eq = "manual", into = "new", cell = "new")] +pub struct SwcPluginModule( + #[turbo_tasks(trace_ignore)] + #[cfg(feature = "swc_ecma_transform_plugin")] + pub swc_core::plugin_runner::plugin_module_bytes::CompiledPluginModuleBytes, + // Dummy field to avoid turbo_tasks macro complaining about empty struct. + // This is because we can't import CompiledPluginModuleBytes by default, it should be only + // available for the target / platforms that support swc plugins (which can build wasmer) + #[cfg(not(feature = "swc_ecma_transform_plugin"))] pub (), +); + +impl SwcPluginModule { + pub fn new(plugin_name:&str, plugin_bytes:Vec) -> Self { + #[cfg(feature = "swc_ecma_transform_plugin")] + { + Self({ + use swc_core::plugin_runner::plugin_module_bytes::{ + CompiledPluginModuleBytes, + RawPluginModuleBytes, + }; + CompiledPluginModuleBytes::from(RawPluginModuleBytes::new( + plugin_name.to_string(), + plugin_bytes, + )) + }) + } + + #[cfg(not(feature = "swc_ecma_transform_plugin"))] + { + let _ = plugin_name; + let _ = plugin_bytes; + Self(()) + } + } +} + +#[turbo_tasks::value(shared)] +struct UnsupportedSwcEcmaTransformPluginsIssue { + pub file_path:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for UnsupportedSwcEcmaTransformPluginsIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Transform.cell() } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { + Ok(StyledString::Text( + "Unsupported SWC EcmaScript transform plugins on this platform.".into(), + ) + .cell()) + } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.file_path } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some( + StyledString::Text( + "Turbopack does not yet support running SWC EcmaScript transform plugins on this \ + platform." + .into(), + ) + .cell(), + )) + } +} + +/// A custom transformer plugin to execute SWC's transform plugins. +#[derive(Debug)] +pub struct SwcEcmaTransformPluginsTransformer { + #[cfg(feature = "swc_ecma_transform_plugin")] + plugins:Vec<(Vc, serde_json::Value)>, +} + +impl SwcEcmaTransformPluginsTransformer { + #[cfg(feature = "swc_ecma_transform_plugin")] + pub fn new(plugins:Vec<(Vc, serde_json::Value)>) -> Self { Self { plugins } } + + // [TODO] Due to WEB-1102 putting this module itself behind compile time feature + // doesn't work. Instead allow to instantiate dummy instance. + #[cfg(not(feature = "swc_ecma_transform_plugin"))] + #[allow(clippy::new_without_default)] + pub fn new() -> Self { Self {} } +} + +#[async_trait] +impl CustomTransformer for SwcEcmaTransformPluginsTransformer { + #[cfg_attr(not(feature = "swc_ecma_transform_plugin"), allow(unused))] + #[tracing::instrument(level = tracing::Level::TRACE, name = "swc_ecma_transform_plugin", skip_all)] + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + #[cfg(feature = "swc_ecma_transform_plugin")] + { + use std::{cell::RefCell, rc::Rc, sync::Arc}; + + use swc_core::{ + common::{ + comments::SingleThreadedComments, + plugin::{ + metadata::TransformPluginMetadataContext, + serialized::PluginSerializedBytes, + }, + util::take::Take, + }, + ecma::ast::Module, + plugin::proxies::{COMMENTS, HostCommentsStorage}, + plugin_runner::plugin_module_bytes::PluginModuleBytes, + }; + + let mut plugins = vec![]; + for (plugin_module, config) in &self.plugins { + let plugin_module = &plugin_module.await?.0; + + plugins.push(( + plugin_module.get_module_name().to_string(), + config.clone(), + Box::new(plugin_module.clone()), + )); + } + + let should_enable_comments_proxy = + !ctx.comments.leading.is_empty() && !ctx.comments.trailing.is_empty(); + + //[TODO]: as same as swc/core does, we should set should_enable_comments_proxy + // depends on the src's comments availability. For now, check naively if leading + // / trailing comments are empty. + let comments = if should_enable_comments_proxy { + // Plugin only able to accept singlethreaded comments, interop from + // multithreaded comments. + let mut leading = + swc_core::common::comments::SingleThreadedCommentsMapInner::default(); + ctx.comments.leading.as_ref().into_iter().for_each(|c| { + leading.insert(*c.key(), c.value().clone()); + }); + + let mut trailing = + swc_core::common::comments::SingleThreadedCommentsMapInner::default(); + ctx.comments.trailing.as_ref().into_iter().for_each(|c| { + trailing.insert(*c.key(), c.value().clone()); + }); + + Some(SingleThreadedComments::from_leading_and_trailing( + Rc::new(RefCell::new(leading)), + Rc::new(RefCell::new(trailing)), + )) + } else { + None + }; + + let transformed_program = + COMMENTS.set(&HostCommentsStorage { inner:comments }, || { + let module_program = + std::mem::replace(program, Program::Module(Module::dummy())); + let module_program = + swc_core::common::plugin::serialized::VersionedSerializable::new( + module_program, + ); + let mut serialized_program = + PluginSerializedBytes::try_serialize(&module_program)?; + + let transform_metadata_context = Arc::new(TransformPluginMetadataContext::new( + Some(ctx.file_name_str.to_string()), + //[TODO]: Support env-related variable injection, i.e process.env.NODE_ENV + "development".to_string(), + None, + )); + + // Run plugin transformation against current program. + // We do not serialize / deserialize between each plugin execution but + // copies raw transformed bytes directly into plugin's memory space. + // Note: This doesn't mean plugin won't perform any se/deserialization: it + // still have to construct from raw bytes internally to perform actual + // transform. + for (_plugin_name, plugin_config, plugin_module) in plugins.drain(..) { + let runtime = + swc_core::plugin_runner::wasix_runtime::build_wasi_runtime(None); + let mut transform_plugin_executor = + swc_core::plugin_runner::create_plugin_transform_executor( + ctx.source_map, + &ctx.unresolved_mark, + &transform_metadata_context, + plugin_module, + Some(plugin_config), + runtime, + ); + + serialized_program = transform_plugin_executor + .transform(&serialized_program, Some(should_enable_comments_proxy))?; + } + + serialized_program.deserialize().map(|v| v.into_inner()) + })?; + + *program = transformed_program; + } + + #[cfg(not(feature = "swc_ecma_transform_plugin"))] + { + use turbopack_core::issue::IssueExt; + + UnsupportedSwcEcmaTransformPluginsIssue { file_path:ctx.file_path } + .cell() + .emit(); + } + + Ok(()) + } +} diff --git a/crates/turbopack-ecmascript-plugins/build.rs b/crates/turbopack-ecmascript-plugins/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-ecmascript-plugins/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-ecmascript-runtime/Source/asset_context.rs b/crates/turbopack-ecmascript-runtime/Source/asset_context.rs new file mode 100644 index 0000000000000..10d00e3e25d62 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Source/asset_context.rs @@ -0,0 +1,32 @@ +use turbo_tasks::Vc; +use turbopack::{ + ModuleAssetContext, + module_options::{ModuleOptionsContext, TypescriptTransformOptions}, +}; +use turbopack_core::{ + compile_time_info::CompileTimeInfo, + context::AssetContext, + environment::Environment, +}; +use turbopack_ecmascript::TreeShakingMode; + +/// Returns the runtime asset context to use to process runtime code assets. +pub fn get_runtime_asset_context(environment:Vc) -> Vc> { + let module_options_context = ModuleOptionsContext { + enable_typescript_transform:Some(TypescriptTransformOptions::default().cell()), + tree_shaking_mode:Some(TreeShakingMode::ReexportsOnly), + ..Default::default() + } + .cell(); + let compile_time_info = CompileTimeInfo::builder(environment).cell(); + + let asset_context:Vc> = Vc::upcast(ModuleAssetContext::new( + Vc::cell(Default::default()), + compile_time_info, + module_options_context, + Vc::default(), + Vc::cell("runtime".into()), + )); + + asset_context +} diff --git a/crates/turbopack-ecmascript-runtime/Source/browser_runtime.rs b/crates/turbopack-ecmascript-runtime/Source/browser_runtime.rs new file mode 100644 index 0000000000000..a1e25ef12122f --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Source/browser_runtime.rs @@ -0,0 +1,101 @@ +use std::io::Write; + +use anyhow::Result; +use indoc::writedoc; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::{ + code_builder::{Code, CodeBuilder}, + context::AssetContext, + environment::{ChunkLoading, Environment}, +}; +use turbopack_ecmascript::utils::StringifyJs; + +use crate::{asset_context::get_runtime_asset_context, embed_js::embed_static_code}; + +/// Returns the code for the development ECMAScript runtime. +#[turbo_tasks::function] +pub async fn get_browser_runtime_code( + environment:Vc, + chunk_base_path:Vc>, + output_root:Vc, +) -> Result> { + let asset_context = get_runtime_asset_context(environment); + + let shared_runtime_utils_code = + embed_static_code(asset_context, "shared/runtime-utils.ts".into()); + let runtime_base_code = + embed_static_code(asset_context, "browser/dev/runtime/base/runtime-base.ts".into()); + + let chunk_loading = &*asset_context.compile_time_info().environment().chunk_loading().await?; + + let runtime_backend_code = embed_static_code( + asset_context, + match chunk_loading { + ChunkLoading::Edge => "browser/dev/runtime/edge/runtime-backend-edge.ts".into(), + // This case should never be hit. + ChunkLoading::NodeJs => { + panic!("Node.js runtime is not supported in the browser runtime!") + }, + ChunkLoading::Dom => "browser/dev/runtime/dom/runtime-backend-dom.ts".into(), + }, + ); + + let mut code:CodeBuilder = CodeBuilder::default(); + let output_root = output_root.await?.to_string(); + let chunk_base_path = &*chunk_base_path.await?; + let chunk_base_path = chunk_base_path.as_ref().map_or_else(|| "", |f| f.as_str()); + + writedoc!( + code, + r#" + (() => {{ + if (!Array.isArray(globalThis.TURBOPACK)) {{ + return; + }} + + const CHUNK_BASE_PATH = {}; + const RUNTIME_PUBLIC_PATH = {}; + const OUTPUT_ROOT = {}; + "#, + StringifyJs(chunk_base_path), + StringifyJs(chunk_base_path), + StringifyJs(output_root.as_str()), + )?; + + code.push_code(&*shared_runtime_utils_code.await?); + code.push_code(&*runtime_base_code.await?); + + if *environment.supports_commonjs_externals().await? { + code.push_code( + &*embed_static_code(asset_context, "shared-node/base-externals-utils.ts".into()) + .await?, + ); + } + if *environment.node_externals().await? { + code.push_code( + &*embed_static_code(asset_context, "shared-node/node-externals-utils.ts".into()) + .await?, + ); + } + if *environment.supports_wasm().await? { + code.push_code( + &*embed_static_code(asset_context, "shared-node/node-wasm-utils.ts".into()).await?, + ); + } + + code.push_code(&*runtime_backend_code.await?); + + // Registering chunks depends on the BACKEND variable, which is set by the + // specific runtime code, hence it must be appended after it. + writedoc!( + code, + r#" + const chunksToRegister = globalThis.TURBOPACK; + globalThis.TURBOPACK = {{ push: registerChunk }}; + chunksToRegister.forEach(registerChunk); + }})(); + "# + )?; + + Ok(Code::cell(code.build())) +} diff --git a/crates/turbopack-ecmascript-runtime/Source/dummy_runtime.rs b/crates/turbopack-ecmascript-runtime/Source/dummy_runtime.rs new file mode 100644 index 0000000000000..5af7e9949b3d8 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Source/dummy_runtime.rs @@ -0,0 +1,10 @@ +use turbopack_core::code_builder::{Code, CodeBuilder}; + +/// Returns the code for the dummy runtime, which is used for snapshots. +pub fn get_dummy_runtime_code() -> Code { + let mut code = CodeBuilder::default(); + + code += "// Dummy runtime\n"; + + code.build() +} diff --git a/crates/turbopack-ecmascript-runtime/Source/embed_js.rs b/crates/turbopack-ecmascript-runtime/Source/embed_js.rs new file mode 100644 index 0000000000000..224b045da1c49 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Source/embed_js.rs @@ -0,0 +1,20 @@ +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::{FileContent, FileSystem, FileSystemPath, embed_directory}; +use turbopack_core::{code_builder::Code, context::AssetContext}; +use turbopack_ecmascript::StaticEcmascriptCode; + +#[turbo_tasks::function] +pub fn embed_fs() -> Vc> { + embed_directory!("turbopack", "$CARGO_MANIFEST_DIR/js/src") +} + +#[turbo_tasks::function] +pub fn embed_file(path:RcStr) -> Vc { embed_fs().root().join(path).read() } + +#[turbo_tasks::function] +pub fn embed_file_path(path:RcStr) -> Vc { embed_fs().root().join(path) } + +#[turbo_tasks::function] +pub fn embed_static_code(asset_context:Vc>, path:RcStr) -> Vc { + StaticEcmascriptCode::new(asset_context, embed_file_path(path)).code() +} diff --git a/crates/turbopack-ecmascript-runtime/Source/lib.rs b/crates/turbopack-ecmascript-runtime/Source/lib.rs new file mode 100644 index 0000000000000..452a71e2a6052 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Source/lib.rs @@ -0,0 +1,24 @@ +#![feature(arbitrary_self_types)] + +pub(crate) mod asset_context; +pub(crate) mod browser_runtime; +#[cfg(feature = "test")] +pub(crate) mod dummy_runtime; +pub(crate) mod embed_js; +pub(crate) mod nodejs_runtime; +pub(crate) mod runtime_type; + +pub use browser_runtime::get_browser_runtime_code; +#[cfg(feature = "test")] +pub use dummy_runtime::get_dummy_runtime_code; +pub use embed_js::{embed_file, embed_file_path, embed_fs}; +pub use nodejs_runtime::get_nodejs_runtime_code; +pub use runtime_type::RuntimeType; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-ecmascript-runtime/Source/nodejs_runtime.rs b/crates/turbopack-ecmascript-runtime/Source/nodejs_runtime.rs new file mode 100644 index 0000000000000..e33fcb6ef9a3d --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Source/nodejs_runtime.rs @@ -0,0 +1,33 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbopack_core::{ + code_builder::{Code, CodeBuilder}, + environment::Environment, +}; + +use crate::{asset_context::get_runtime_asset_context, embed_js::embed_static_code}; + +/// Returns the code for the Node.js production ECMAScript runtime. +#[turbo_tasks::function] +pub async fn get_nodejs_runtime_code(environment:Vc) -> Result> { + let asset_context = get_runtime_asset_context(environment); + + let shared_runtime_utils_code = + embed_static_code(asset_context, "shared/runtime-utils.ts".into()); + let shared_base_external_utils_code = + embed_static_code(asset_context, "shared-node/base-externals-utils.ts".into()); + let shared_node_external_utils_code = + embed_static_code(asset_context, "shared-node/node-externals-utils.ts".into()); + let shared_node_wasm_utils_code = + embed_static_code(asset_context, "shared-node/node-wasm-utils.ts".into()); + let runtime_code = embed_static_code(asset_context, "nodejs/runtime.ts".into()); + + let mut code = CodeBuilder::default(); + code.push_code(&*shared_runtime_utils_code.await?); + code.push_code(&*shared_base_external_utils_code.await?); + code.push_code(&*shared_node_external_utils_code.await?); + code.push_code(&*shared_node_wasm_utils_code.await?); + code.push_code(&*runtime_code.await?); + + Ok(Code::cell(code.build())) +} diff --git a/crates/turbopack-ecmascript-runtime/Source/runtime_type.rs b/crates/turbopack-ecmascript-runtime/Source/runtime_type.rs new file mode 100644 index 0000000000000..80698d6a34830 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Source/runtime_type.rs @@ -0,0 +1,13 @@ +use serde::{Deserialize, Serialize}; +use turbo_tasks::trace::TraceRawVcs; + +#[derive( + Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, TraceRawVcs, +)] +pub enum RuntimeType { + Development, + Production, + #[cfg(feature = "test")] + /// Dummy runtime for snapshot tests. + Dummy, +} diff --git a/crates/turbopack-ecmascript-runtime/build.rs b/crates/turbopack-ecmascript-runtime/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/hmr-client.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/hmr-client.ts new file mode 100644 index 0000000000000..fc011843a752c --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/hmr-client.ts @@ -0,0 +1,601 @@ +/// +/// +/// +/// + +import { + addMessageListener as turboSocketAddMessageListener, + sendMessage as turboSocketSendMessage, +} from "./websocket"; +type SendMessage = typeof import("./websocket").sendMessage; + +export type ClientOptions = { + addMessageListener: typeof import("./websocket").addMessageListener; + sendMessage: SendMessage; + onUpdateError: (err: unknown) => void; +}; + +export function connect({ + // TODO(WEB-1465) Remove this backwards compat fallback once + // vercel/next.js#54586 is merged. + addMessageListener = turboSocketAddMessageListener, + // TODO(WEB-1465) Remove this backwards compat fallback once + // vercel/next.js#54586 is merged. + sendMessage = turboSocketSendMessage, + onUpdateError = console.error, +}: ClientOptions) { + addMessageListener((msg) => { + switch (msg.type) { + case "turbopack-connected": + handleSocketConnected(sendMessage); + break; + default: + try { + if (Array.isArray(msg.data)) { + for (let i = 0; i < msg.data.length; i++) { + handleSocketMessage(msg.data[i] as ServerMessage); + } + } else { + handleSocketMessage(msg.data as ServerMessage); + } + applyAggregatedUpdates(); + } catch (e: unknown) { + console.warn( + "[Fast Refresh] performing full reload\n\n" + + "Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React rendering tree.\n" + + "You might have a file which exports a React component but also exports a value that is imported by a non-React component file.\n" + + "Consider migrating the non-React component export to a separate file and importing it into both files.\n\n" + + "It is also possible the parent component of the component you edited is a class component, which disables Fast Refresh.\n" + + "Fast Refresh requires at least one parent function component in your React tree." + ); + onUpdateError(e); + location.reload(); + } + break; + } + }); + + const queued = globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS; + if (queued != null && !Array.isArray(queued)) { + throw new Error("A separate HMR handler was already registered"); + } + globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = { + push: ([chunkPath, callback]: [ChunkPath, UpdateCallback]) => { + subscribeToChunkUpdate(chunkPath, sendMessage, callback); + }, + }; + + if (Array.isArray(queued)) { + for (const [chunkPath, callback] of queued) { + subscribeToChunkUpdate(chunkPath, sendMessage, callback); + } + } +} + +type UpdateCallbackSet = { + callbacks: Set; + unsubscribe: () => void; +}; + +const updateCallbackSets: Map = new Map(); + +function sendJSON(sendMessage: SendMessage, message: ClientMessage) { + sendMessage(JSON.stringify(message)); +} + +type ResourceKey = string; + +function resourceKey(resource: ResourceIdentifier): ResourceKey { + return JSON.stringify({ + path: resource.path, + headers: resource.headers || null, + }); +} + +function subscribeToUpdates( + sendMessage: SendMessage, + resource: ResourceIdentifier +): () => void { + sendJSON(sendMessage, { + type: "turbopack-subscribe", + ...resource, + }); + + return () => { + sendJSON(sendMessage, { + type: "turbopack-unsubscribe", + ...resource, + }); + }; +} + +function handleSocketConnected(sendMessage: SendMessage) { + for (const key of updateCallbackSets.keys()) { + subscribeToUpdates(sendMessage, JSON.parse(key)); + } +} + +// we aggregate all pending updates until the issues are resolved +const chunkListsWithPendingUpdates: Map = + new Map(); + +function aggregateUpdates(msg: PartialServerMessage) { + const key = resourceKey(msg.resource); + let aggregated = chunkListsWithPendingUpdates.get(key); + + if (aggregated) { + aggregated.instruction = mergeChunkListUpdates( + aggregated.instruction, + msg.instruction + ); + } else { + chunkListsWithPendingUpdates.set(key, msg); + } +} + +function applyAggregatedUpdates() { + if (chunkListsWithPendingUpdates.size === 0) return; + hooks.beforeRefresh(); + for (const msg of chunkListsWithPendingUpdates.values()) { + triggerUpdate(msg); + } + chunkListsWithPendingUpdates.clear(); + finalizeUpdate(); +} + +function mergeChunkListUpdates( + updateA: ChunkListUpdate, + updateB: ChunkListUpdate +): ChunkListUpdate { + let chunks; + if (updateA.chunks != null) { + if (updateB.chunks == null) { + chunks = updateA.chunks; + } else { + chunks = mergeChunkListChunks(updateA.chunks, updateB.chunks); + } + } else if (updateB.chunks != null) { + chunks = updateB.chunks; + } + + let merged; + if (updateA.merged != null) { + if (updateB.merged == null) { + merged = updateA.merged; + } else { + // Since `merged` is an array of updates, we need to merge them all into + // one, consistent update. + // Since there can only be `EcmascriptMergeUpdates` in the array, there is + // no need to key on the `type` field. + let update = updateA.merged[0]; + for (let i = 1; i < updateA.merged.length; i++) { + update = mergeChunkListEcmascriptMergedUpdates( + update, + updateA.merged[i] + ); + } + + for (let i = 0; i < updateB.merged.length; i++) { + update = mergeChunkListEcmascriptMergedUpdates( + update, + updateB.merged[i] + ); + } + + merged = [update]; + } + } else if (updateB.merged != null) { + merged = updateB.merged; + } + + return { + type: "ChunkListUpdate", + chunks, + merged, + }; +} + +function mergeChunkListChunks( + chunksA: Record, + chunksB: Record +): Record { + const chunks: Record = {}; + + for (const [chunkPath, chunkUpdateA] of Object.entries(chunksA)) { + const chunkUpdateB = chunksB[chunkPath]; + if (chunkUpdateB != null) { + const mergedUpdate = mergeChunkUpdates(chunkUpdateA, chunkUpdateB); + if (mergedUpdate != null) { + chunks[chunkPath] = mergedUpdate; + } + } else { + chunks[chunkPath] = chunkUpdateA; + } + } + + for (const [chunkPath, chunkUpdateB] of Object.entries(chunksB)) { + if (chunks[chunkPath] == null) { + chunks[chunkPath] = chunkUpdateB; + } + } + + return chunks; +} + +function mergeChunkUpdates( + updateA: ChunkUpdate, + updateB: ChunkUpdate +): ChunkUpdate | undefined { + if ( + (updateA.type === "added" && updateB.type === "deleted") || + (updateA.type === "deleted" && updateB.type === "added") + ) { + return undefined; + } + + if (updateA.type === "partial") { + invariant(updateA.instruction, "Partial updates are unsupported"); + } + + if (updateB.type === "partial") { + invariant(updateB.instruction, "Partial updates are unsupported"); + } + + return undefined; +} + +function mergeChunkListEcmascriptMergedUpdates( + mergedA: EcmascriptMergedUpdate, + mergedB: EcmascriptMergedUpdate +): EcmascriptMergedUpdate { + const entries = mergeEcmascriptChunkEntries(mergedA.entries, mergedB.entries); + const chunks = mergeEcmascriptChunksUpdates(mergedA.chunks, mergedB.chunks); + + return { + type: "EcmascriptMergedUpdate", + entries, + chunks, + }; +} + +function mergeEcmascriptChunkEntries( + entriesA: Record | undefined, + entriesB: Record | undefined +): Record { + return { ...entriesA, ...entriesB }; +} + +function mergeEcmascriptChunksUpdates( + chunksA: Record | undefined, + chunksB: Record | undefined +): Record | undefined { + if (chunksA == null) { + return chunksB; + } + + if (chunksB == null) { + return chunksA; + } + + const chunks: Record = {}; + + for (const [chunkPath, chunkUpdateA] of Object.entries(chunksA)) { + const chunkUpdateB = chunksB[chunkPath]; + if (chunkUpdateB != null) { + const mergedUpdate = mergeEcmascriptChunkUpdates( + chunkUpdateA, + chunkUpdateB + ); + if (mergedUpdate != null) { + chunks[chunkPath] = mergedUpdate; + } + } else { + chunks[chunkPath] = chunkUpdateA; + } + } + + for (const [chunkPath, chunkUpdateB] of Object.entries(chunksB)) { + if (chunks[chunkPath] == null) { + chunks[chunkPath] = chunkUpdateB; + } + } + + if (Object.keys(chunks).length === 0) { + return undefined; + } + + return chunks; +} + +function mergeEcmascriptChunkUpdates( + updateA: EcmascriptMergedChunkUpdate, + updateB: EcmascriptMergedChunkUpdate +): EcmascriptMergedChunkUpdate | undefined { + if (updateA.type === "added" && updateB.type === "deleted") { + // These two completely cancel each other out. + return undefined; + } + + if (updateA.type === "deleted" && updateB.type === "added") { + const added = []; + const deleted = []; + const deletedModules = new Set(updateA.modules ?? []); + const addedModules = new Set(updateB.modules ?? []); + + for (const moduleId of addedModules) { + if (!deletedModules.has(moduleId)) { + added.push(moduleId); + } + } + + for (const moduleId of deletedModules) { + if (!addedModules.has(moduleId)) { + deleted.push(moduleId); + } + } + + if (added.length === 0 && deleted.length === 0) { + return undefined; + } + + return { + type: "partial", + added, + deleted, + }; + } + + if (updateA.type === "partial" && updateB.type === "partial") { + const added = new Set([...(updateA.added ?? []), ...(updateB.added ?? [])]); + const deleted = new Set([ + ...(updateA.deleted ?? []), + ...(updateB.deleted ?? []), + ]); + + if (updateB.added != null) { + for (const moduleId of updateB.added) { + deleted.delete(moduleId); + } + } + + if (updateB.deleted != null) { + for (const moduleId of updateB.deleted) { + added.delete(moduleId); + } + } + + return { + type: "partial", + added: [...added], + deleted: [...deleted], + }; + } + + if (updateA.type === "added" && updateB.type === "partial") { + const modules = new Set([ + ...(updateA.modules ?? []), + ...(updateB.added ?? []), + ]); + + for (const moduleId of updateB.deleted ?? []) { + modules.delete(moduleId); + } + + return { + type: "added", + modules: [...modules], + }; + } + + if (updateA.type === "partial" && updateB.type === "deleted") { + // We could eagerly return `updateB` here, but this would potentially be + // incorrect if `updateA` has added modules. + + const modules = new Set(updateB.modules ?? []); + + if (updateA.added != null) { + for (const moduleId of updateA.added) { + modules.delete(moduleId); + } + } + + return { + type: "deleted", + modules: [...modules], + }; + } + + // Any other update combination is invalid. + + return undefined; +} + +function invariant(_: never, message: string): never { + throw new Error(`Invariant: ${message}`); +} + +const CRITICAL = ["bug", "error", "fatal"]; + +function compareByList(list: any[], a: any, b: any) { + const aI = list.indexOf(a) + 1 || list.length; + const bI = list.indexOf(b) + 1 || list.length; + return aI - bI; +} + +const chunksWithIssues: Map = new Map(); + +function emitIssues() { + const issues = []; + const deduplicationSet = new Set(); + + for (const [_, chunkIssues] of chunksWithIssues) { + for (const chunkIssue of chunkIssues) { + if (deduplicationSet.has(chunkIssue.formatted)) continue; + + issues.push(chunkIssue); + deduplicationSet.add(chunkIssue.formatted); + } + } + + sortIssues(issues); + + hooks.issues(issues); +} + +function handleIssues(msg: ServerMessage): boolean { + const key = resourceKey(msg.resource); + let hasCriticalIssues = false; + + for (const issue of msg.issues) { + if (CRITICAL.includes(issue.severity)) { + hasCriticalIssues = true; + } + } + + if (msg.issues.length > 0) { + chunksWithIssues.set(key, msg.issues); + } else if (chunksWithIssues.has(key)) { + chunksWithIssues.delete(key); + } + + emitIssues(); + + return hasCriticalIssues; +} + +const SEVERITY_ORDER = ["bug", "fatal", "error", "warning", "info", "log"]; +const CATEGORY_ORDER = [ + "parse", + "resolve", + "code generation", + "rendering", + "typescript", + "other", +]; + +function sortIssues(issues: Issue[]) { + issues.sort((a, b) => { + const first = compareByList(SEVERITY_ORDER, a.severity, b.severity); + if (first !== 0) return first; + return compareByList(CATEGORY_ORDER, a.category, b.category); + }); +} + +const hooks = { + beforeRefresh: () => {}, + refresh: () => {}, + buildOk: () => {}, + issues: (_issues: Issue[]) => {}, +}; + +export function setHooks(newHooks: typeof hooks) { + Object.assign(hooks, newHooks); +} + +function handleSocketMessage(msg: ServerMessage) { + sortIssues(msg.issues); + + handleIssues(msg); + + switch (msg.type) { + case "issues": + // issues are already handled + break; + case "partial": + // aggregate updates + aggregateUpdates(msg); + break; + default: + // run single update + const runHooks = chunkListsWithPendingUpdates.size === 0; + if (runHooks) hooks.beforeRefresh(); + triggerUpdate(msg); + if (runHooks) finalizeUpdate(); + break; + } +} + +function finalizeUpdate() { + hooks.refresh(); + hooks.buildOk(); + + // This is used by the Next.js integration test suite to notify it when HMR + // updates have been completed. + // TODO: Only run this in test environments (gate by `process.env.__NEXT_TEST_MODE`) + if (globalThis.__NEXT_HMR_CB) { + globalThis.__NEXT_HMR_CB(); + globalThis.__NEXT_HMR_CB = null; + } +} + +function subscribeToChunkUpdate( + chunkPath: ChunkPath, + sendMessage: SendMessage, + callback: UpdateCallback +): () => void { + return subscribeToUpdate( + { + path: chunkPath, + }, + sendMessage, + callback + ); +} + +export function subscribeToUpdate( + resource: ResourceIdentifier, + sendMessage: SendMessage, + callback: UpdateCallback +) { + // TODO(WEB-1465) Remove this backwards compat fallback once + // vercel/next.js#54586 is merged. + if (callback === undefined) { + callback = sendMessage; + sendMessage = turboSocketSendMessage; + } + + const key = resourceKey(resource); + let callbackSet: UpdateCallbackSet; + const existingCallbackSet = updateCallbackSets.get(key); + if (!existingCallbackSet) { + callbackSet = { + callbacks: new Set([callback]), + unsubscribe: subscribeToUpdates(sendMessage, resource), + }; + updateCallbackSets.set(key, callbackSet); + } else { + existingCallbackSet.callbacks.add(callback); + callbackSet = existingCallbackSet; + } + + return () => { + callbackSet.callbacks.delete(callback); + + if (callbackSet.callbacks.size === 0) { + callbackSet.unsubscribe(); + updateCallbackSets.delete(key); + } + }; +} + +function triggerUpdate(msg: ServerMessage) { + const key = resourceKey(msg.resource); + const callbackSet = updateCallbackSets.get(key); + if (!callbackSet) { + return; + } + + for (const callback of callbackSet.callbacks) { + callback(msg); + } + + if (msg.type === "notFound") { + // This indicates that the resource which we subscribed to either does not exist or + // has been deleted. In either case, we should clear all update callbacks, so if a + // new subscription is created for the same resource, it will send a new "subscribe" + // message to the server. + // No need to send an "unsubscribe" message to the server, it will have already + // dropped the update stream before sending the "notFound" message. + updateCallbackSets.delete(key); + } +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/index.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/index.ts new file mode 100644 index 0000000000000..6b455222c37eb --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/index.ts @@ -0,0 +1,2 @@ +export * from "./hmr-client"; +export * from "./websocket"; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/tsconfig.json new file mode 100644 index 0000000000000..7ce726cb8210c --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "skipLibCheck": true, + + // environment + "lib": ["ESNext", "DOM"], + "target": "esnext" + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/websocket.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/websocket.ts new file mode 100644 index 0000000000000..d7da330bb8173 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/hmr-client/websocket.ts @@ -0,0 +1,101 @@ +// Adapted from https://github.com/vercel/next.js/blob/canary/packages/next/client/dev/error-overlay/websocket.ts + +let source: WebSocket; +const eventCallbacks: ((msg: WebSocketMessage) => void)[] = []; + +// TODO: add timeout again +// let lastActivity = Date.now() + +function getSocketProtocol(assetPrefix: string): string { + let protocol = location.protocol; + + try { + // assetPrefix is a url + protocol = new URL(assetPrefix).protocol; + } catch (_) {} + + return protocol === "http:" ? "ws" : "wss"; +} + +export type WebSocketMessage = + | { + type: "turbopack-connected"; + } + | { + type: "turbopack-message"; + data: Record; + }; + +export function addMessageListener(cb: (msg: WebSocketMessage) => void) { + eventCallbacks.push(cb); +} + +export function sendMessage(data: any) { + if (!source || source.readyState !== source.OPEN) return; + return source.send(data); +} + +export type HMROptions = { + path: string; + assetPrefix: string; + timeout?: number; + log?: boolean; +}; + +export function connectHMR(options: HMROptions) { + const { timeout = 5 * 1000 } = options; + + function init() { + if (source) source.close(); + + console.log("[HMR] connecting..."); + + function handleOnline() { + const connected = { type: "turbopack-connected" as const }; + eventCallbacks.forEach((cb) => { + cb(connected); + }); + + if (options.log) console.log("[HMR] connected"); + // lastActivity = Date.now() + } + + function handleMessage(event: MessageEvent) { + // lastActivity = Date.now() + + const message = { + type: "turbopack-message" as const, + data: JSON.parse(event.data), + }; + eventCallbacks.forEach((cb) => { + cb(message); + }); + } + + // let timer: NodeJS.Timeout + + function handleDisconnect() { + source.close(); + setTimeout(init, timeout); + } + + const { hostname, port } = location; + const protocol = getSocketProtocol(options.assetPrefix || ""); + const assetPrefix = options.assetPrefix.replace(/^\/+/, ""); + + let url = `${protocol}://${hostname}:${port}${ + assetPrefix ? `/${assetPrefix}` : "" + }`; + + if (assetPrefix.startsWith("http")) { + url = `${protocol}://${assetPrefix.split("://")[1]}`; + } + + source = new window.WebSocket(`${url}${options.path}`); + source.onopen = handleOnline; + source.onerror = handleDisconnect; + source.onmessage = handleMessage; + } + + init(); +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/dummy.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/dummy.ts new file mode 100644 index 0000000000000..eabcfaa5a5bc8 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/dummy.ts @@ -0,0 +1,27 @@ +/** + * This file acts as a dummy implementor for the interface that + * `runtime-base.ts` expects to be available in the global scope. + * + * This interface will be implemented by runtime backends. + */ + +/// + +declare var BACKEND: RuntimeBackend; +declare var _eval: (code: EcmascriptModuleEntry) => any; +/** + * Adds additional properties to the `TurbopackDevBaseContext` interface. + */ +declare var augmentContext: ( + context: TurbopackDevBaseContext +) => TurbopackDevContext; +declare var loadWebAssembly: ( + source: SourceInfo, + wasmChunkPath: ChunkPath, + imports: WebAssembly.Imports +) => Exports; +declare var loadWebAssemblyModule: ( + source: SourceInfo, + wasmChunkPath: ChunkPath +) => WebAssembly.Module; +declare var relativeURL: (inputUrl: string) => void; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/extensions.d.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/extensions.d.ts new file mode 100644 index 0000000000000..a6f011eb863b2 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/extensions.d.ts @@ -0,0 +1,65 @@ +/** + * Extensions to the shared runtime types that are specific to the development + * runtime (e.g. `module.hot`). + */ + +declare const enum HotUpdateStatus { + idle = "idle", +} + +type HotUpdateStatusHandler = (status: HotUpdateStatus) => void; + +interface HotData { + prevExports?: Exports; +} + +interface HotState { + selfAccepted: boolean | Function; + selfDeclined: boolean; + selfInvalidated: boolean; + disposeHandlers: ((data: object) => void)[]; +} + +type AcceptErrorHandler = ( + err: Error, + context: { moduleId: ModuleId; dependencyId: string | number } +) => void; +type AcceptCallback = (outdatedDependencies: string[]) => void; + +interface AcceptFunction { + // accept updates for self + (errorHandler?: AcceptErrorHandler): void; + + // accept updates for the given modules + ( + modules?: string | string[], + callback?: AcceptCallback, + errorHandler?: AcceptErrorHandler + ): void; +} + +interface Hot { + active: boolean; + data: HotData; + + accept: AcceptFunction; + + decline: (module?: string | string[]) => void; + + dispose: (callback: (data: HotData) => void) => void; + + addDisposeHandler: (callback: (data: object) => void) => void; + + removeDisposeHandler: (callback: (data: object) => void) => void; + + invalidate: () => void; + + status: () => keyof typeof HotUpdateStatus; + addStatusHandler: (handler: HotUpdateStatusHandler) => void; + removeStatusHandler: (handler: HotUpdateStatusHandler) => void; + check: (autoApply: boolean) => Promise; +} + +interface Module { + hot: Hot; +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/globals.d.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/globals.d.ts new file mode 100644 index 0000000000000..eae4e2323ee6c --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/globals.d.ts @@ -0,0 +1,30 @@ +/** + * Definitions for globals that are injected by the Turbopack runtime. + * + * These are available from every module, but should only be used by Turbopack + * code, not by user code. + */ + +type UpdateCallback = (update: ServerMessage) => void; + +type ChunkRegistry = { + push: (registration: ChunkRegistration) => void; +}; + +type ChunkListProvider = { + push: (registration: ChunkList) => void; +}; + +type ChunkUpdateProvider = { + push: (registration: [ChunkPath, UpdateCallback]) => void; +}; + +declare var TURBOPACK: ChunkRegistry | ChunkRegistration[] | undefined; +declare var TURBOPACK_CHUNK_LISTS: ChunkListProvider | ChunkList[] | undefined; +declare var TURBOPACK_CHUNK_UPDATE_LISTENERS: + | ChunkUpdateProvider + | [ChunkPath, UpdateCallback][] + | undefined; +// This is used by the Next.js integration test suite to notify it when HMR +// updates have been completed. +declare var __NEXT_HMR_CB: undefined | null | (() => void); diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/protocol.d.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/protocol.d.ts new file mode 100644 index 0000000000000..2123ac8e8e888 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/protocol.d.ts @@ -0,0 +1,148 @@ +/** + * Definitions for the protocol that is used to communicate between the + * Turbopack runtime and the Turbopack server for issue reporting and HMR. + */ +type PartialServerMessage = { + resource: ResourceIdentifier; + issues: Issue[]; + type: "partial"; + instruction: PartialUpdate; +}; + +type ServerMessage = { + resource: ResourceIdentifier; + issues: Issue[]; +} & ( + | { + type: "restart"; + } + | { + type: "notFound"; + } + | PartialServerMessage + | { + type: "issues"; + } + | UnknownType +); + +type UnknownType = { + type: "future-type-marker-do-not-use-or-you-will-be-fired"; +}; + +type PartialUpdate = + | ChunkListUpdate + | { + type: never; + }; + +type ChunkListUpdate = { + type: "ChunkListUpdate"; + chunks?: Record; + merged?: MergedChunkUpdate[]; +}; + +type ChunkUpdate = + | { + type: "added"; + } + | { type: "deleted" } + | { type: "total" } + // We currently don't have any chunks that can be updated partially that can't + // be merged either. So these updates would go into `MergedChunkUpdate` instead. + | { type: "partial"; instruction: never }; + +type MergedChunkUpdate = + | EcmascriptMergedUpdate + | { + type: never; + }; + +type EcmascriptMergedUpdate = { + type: "EcmascriptMergedUpdate"; + entries?: Record; + chunks?: Record; +}; + +type EcmascriptMergedChunkUpdate = + | { + type: "added"; + modules?: ModuleId[]; + } + | { + type: "deleted"; + modules?: ModuleId[]; + } + | { + type: "partial"; + added?: ModuleId[]; + deleted?: ModuleId[]; + } + | { + type: never; + }; + +type EcmascriptModuleEntry = { + code: ModuleFactoryString; + url: string; + map?: string; +}; + +type ResourceIdentifier = { + path: string; + headers?: { [key: string]: string }; +}; + +type ClientMessageSubscribe = { + type: "turbopack-subscribe"; +} & ResourceIdentifier; + +type ClientMessageUnsubscribe = { + type: "turbopack-unsubscribe"; +} & ResourceIdentifier; + +type ClientMessage = ClientMessageSubscribe | ClientMessageUnsubscribe; + +type IssueSeverity = + | "bug" + | "fatal" + | "error" + | "warning" + | "hint" + | "note" + | "suggestion" + | "info"; + +type IssueAsset = { + path: string; +}; + +type SourcePos = { + line: number; + column: number; +}; + +type IssueSource = { + asset: IssueAsset; + range?: IssueSourceRange; +}; + +type IssueSourceRange = { + start: SourcePos; + end: SourcePos; +}; + +type Issue = { + severity: IssueSeverity; + file_path: string; + category: string; + + title: string; + description: string; + detail: string; + documentation_link: string; + + source: IssueSource | null; + sub_issues: Issue[]; + formatted: string; +}; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/runtime-base.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/runtime-base.ts new file mode 100644 index 0000000000000..afc49cbb94fc2 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/runtime-base.ts @@ -0,0 +1,1389 @@ +/** + * This file contains runtime types and functions that are shared between all + * Turbopack *development* ECMAScript runtimes. + * + * It will be appended to the runtime code of each runtime right after the + * shared runtime utils. + */ + +/* eslint-disable @next/next/no-assign-module-variable */ + +/// +/// +/// +/// + +// This file must not use `import` and `export` statements. Otherwise, it +// becomes impossible to augment interfaces declared in ``d files +// (e.g. `Module`). Hence, the need for `import()` here. +type RefreshRuntimeGlobals = + import("@next/react-refresh-utils/dist/runtime").RefreshRuntimeGlobals; + +declare var CHUNK_BASE_PATH: string; +declare var $RefreshHelpers$: RefreshRuntimeGlobals["$RefreshHelpers$"]; +declare var $RefreshReg$: RefreshRuntimeGlobals["$RefreshReg$"]; +declare var $RefreshSig$: RefreshRuntimeGlobals["$RefreshSig$"]; +declare var $RefreshInterceptModuleExecution$: + | RefreshRuntimeGlobals["$RefreshInterceptModuleExecution$"]; + +type RefreshContext = { + register: RefreshRuntimeGlobals["$RefreshReg$"]; + signature: RefreshRuntimeGlobals["$RefreshSig$"]; + registerExports: typeof registerExportsAndSetupBoundaryForReactRefresh; +}; + +type RefreshHelpers = RefreshRuntimeGlobals["$RefreshHelpers$"]; + +interface TurbopackDevBaseContext extends TurbopackBaseContext { + k: RefreshContext; + R: ResolvePathFromModule; +} + +interface TurbopackDevContext extends TurbopackDevBaseContext {} + +// string encoding of a module factory (used in hmr updates) +type ModuleFactoryString = string; + +type ModuleFactory = ( + this: Module["exports"], + context: TurbopackDevContext +) => undefined; + +type DevRuntimeParams = { + otherChunks: ChunkData[]; + runtimeModuleIds: ModuleId[]; +}; + +type ChunkRegistration = [ + chunkPath: ChunkPath, + chunkModules: ModuleFactories, + params: DevRuntimeParams | undefined +]; +type ChunkList = { + path: ChunkPath; + chunks: ChunkData[]; + source: "entry" | "dynamic"; +}; + +enum SourceType { + /** + * The module was instantiated because it was included in an evaluated chunk's + * runtime. + */ + Runtime = 0, + /** + * The module was instantiated because a parent module imported it. + */ + Parent = 1, + /** + * The module was instantiated because it was included in a chunk's hot module + * update. + */ + Update = 2, +} + +type SourceInfo = + | { + type: SourceType.Runtime; + chunkPath: ChunkPath; + } + | { + type: SourceType.Parent; + parentId: ModuleId; + } + | { + type: SourceType.Update; + parents?: ModuleId[]; + }; + +interface RuntimeBackend { + registerChunk: (chunkPath: ChunkPath, params?: DevRuntimeParams) => void; + loadChunk: (chunkPath: ChunkPath, source: SourceInfo) => Promise; + reloadChunk?: (chunkPath: ChunkPath) => Promise; + unloadChunk?: (chunkPath: ChunkPath) => void; + + restart: () => void; +} + +class UpdateApplyError extends Error { + name = "UpdateApplyError"; + + dependencyChain: string[]; + + constructor(message: string, dependencyChain: string[]) { + super(message); + this.dependencyChain = dependencyChain; + } +} + +const moduleFactories: ModuleFactories = Object.create(null); +const moduleCache: ModuleCache = Object.create(null); +/** + * Maps module IDs to persisted data between executions of their hot module + * implementation (`hot.data`). + */ +const moduleHotData: Map = new Map(); +/** + * Maps module instances to their hot module state. + */ +const moduleHotState: Map = new Map(); +/** + * Modules that call `module.hot.invalidate()` (while being updated). + */ +const queuedInvalidatedModules: Set = new Set(); +/** + * Module IDs that are instantiated as part of the runtime of a chunk. + */ +const runtimeModules: Set = new Set(); +/** + * Map from module ID to the chunks that contain this module. + * + * In HMR, we need to keep track of which modules are contained in which so + * chunks. This is so we don't eagerly dispose of a module when it is removed + * from chunk A, but still exists in chunk B. + */ +const moduleChunksMap: Map> = new Map(); +/** + * Map from a chunk path to all modules it contains. + */ +const chunkModulesMap: Map> = new Map(); +/** + * Chunk lists that contain a runtime. When these chunk lists receive an update + * that can't be reconciled with the current state of the page, we need to + * reload the runtime entirely. + */ +const runtimeChunkLists: Set = new Set(); +/** + * Map from a chunk list to the chunk paths it contains. + */ +const chunkListChunksMap: Map> = new Map(); +/** + * Map from a chunk path to the chunk lists it belongs to. + */ +const chunkChunkListsMap: Map> = new Map(); + +const availableModules: Map | true> = new Map(); + +const availableModuleChunks: Map | true> = new Map(); + +async function loadChunk( + source: SourceInfo, + chunkData: ChunkData +): Promise { + if (typeof chunkData === "string") { + return loadChunkPath(source, chunkData); + } + + const includedList = chunkData.included || []; + const modulesPromises = includedList.map((included) => { + if (moduleFactories[included]) return true; + return availableModules.get(included); + }); + if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { + // When all included items are already loaded or loading, we can skip loading ourselves + return Promise.all(modulesPromises); + } + + const includedModuleChunksList = chunkData.moduleChunks || []; + const moduleChunksPromises = includedModuleChunksList + .map((included) => { + // TODO(alexkirsz) Do we need this check? + // if (moduleFactories[included]) return true; + return availableModuleChunks.get(included); + }) + .filter((p) => p); + + let promise; + if (moduleChunksPromises.length > 0) { + // Some module chunks are already loaded or loading. + + if (moduleChunksPromises.length == includedModuleChunksList.length) { + // When all included module chunks are already loaded or loading, we can skip loading ourselves + return Promise.all(moduleChunksPromises); + } + + const moduleChunksToLoad: Set = new Set(); + for (const moduleChunk of includedModuleChunksList) { + if (!availableModuleChunks.has(moduleChunk)) { + moduleChunksToLoad.add(moduleChunk); + } + } + + for (const moduleChunkToLoad of moduleChunksToLoad) { + const promise = loadChunkPath(source, moduleChunkToLoad); + + availableModuleChunks.set(moduleChunkToLoad, promise); + + moduleChunksPromises.push(promise); + } + + promise = Promise.all(moduleChunksPromises); + } else { + promise = loadChunkPath(source, chunkData.path); + + // Mark all included module chunks as loading if they are not already loaded or loading. + for (const includedModuleChunk of includedModuleChunksList) { + if (!availableModuleChunks.has(includedModuleChunk)) { + availableModuleChunks.set(includedModuleChunk, promise); + } + } + } + + for (const included of includedList) { + if (!availableModules.has(included)) { + // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. + // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. + availableModules.set(included, promise); + } + } + + return promise; +} + +async function loadChunkPath( + source: SourceInfo, + chunkPath: ChunkPath +): Promise { + try { + await BACKEND.loadChunk(chunkPath, source); + } catch (error) { + let loadReason; + switch (source.type) { + case SourceType.Runtime: + loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; + break; + case SourceType.Parent: + loadReason = `from module ${source.parentId}`; + break; + case SourceType.Update: + loadReason = "from an HMR update"; + break; + } + throw new Error( + `Failed to load chunk ${chunkPath} ${loadReason}${ + error ? `: ${error}` : "" + }`, + error + ? { + cause: error, + } + : undefined + ); + } +} + +/** + * Returns an absolute url to an asset. + */ +function createResolvePathFromModule( + resolver: (moduleId: string) => Exports +): (moduleId: string) => string { + return function resolvePathFromModule(moduleId: string): string { + const exported = resolver(moduleId); + return exported?.default ?? exported; + }; +} + +function instantiateModule(id: ModuleId, source: SourceInfo): Module { + const moduleFactory = moduleFactories[id]; + if (typeof moduleFactory !== "function") { + // This can happen if modules incorrectly handle HMR disposes/updates, + // e.g. when they keep a `setTimeout` around which still executes old code + // and contains e.g. a `require("something")` call. + let instantiationReason; + switch (source.type) { + case SourceType.Runtime: + instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; + break; + case SourceType.Parent: + instantiationReason = `because it was required from module ${source.parentId}`; + break; + case SourceType.Update: + instantiationReason = "because of an HMR update"; + break; + } + throw new Error( + `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` + ); + } + + const hotData = moduleHotData.get(id)!; + const { hot, hotState } = createModuleHot(id, hotData); + + let parents: ModuleId[]; + switch (source.type) { + case SourceType.Runtime: + runtimeModules.add(id); + parents = []; + break; + case SourceType.Parent: + // No need to add this module as a child of the parent module here, this + // has already been taken care of in `getOrInstantiateModuleFromParent`. + parents = [source.parentId]; + break; + case SourceType.Update: + parents = source.parents || []; + break; + } + const module: Module = { + exports: {}, + error: undefined, + loaded: false, + id, + parents, + children: [], + namespaceObject: undefined, + hot, + }; + + moduleCache[id] = module; + moduleHotState.set(module, hotState); + + // NOTE(alexkirsz) This can fail when the module encounters a runtime error. + try { + const sourceInfo: SourceInfo = { type: SourceType.Parent, parentId: id }; + + runModuleExecutionHooks(module, (refresh) => { + const r = commonJsRequire.bind(null, module); + moduleFactory.call( + module.exports, + augmentContext({ + a: asyncModule.bind(null, module), + e: module.exports, + r: commonJsRequire.bind(null, module), + t: runtimeRequire, + f: moduleContext, + i: esmImport.bind(null, module), + s: esmExport.bind(null, module, module.exports), + j: dynamicExport.bind(null, module, module.exports), + v: exportValue.bind(null, module), + n: exportNamespace.bind(null, module), + m: module, + c: moduleCache, + M: moduleFactories, + l: loadChunk.bind(null, sourceInfo), + w: loadWebAssembly.bind(null, sourceInfo), + u: loadWebAssemblyModule.bind(null, sourceInfo), + g: globalThis, + U: relativeURL, + k: refresh, + R: createResolvePathFromModule(r), + __dirname: module.id.replace(/(^|\/)\/+$/, ""), + }) + ); + }); + } catch (error) { + module.error = error as any; + throw error; + } + + module.loaded = true; + if (module.namespaceObject && module.exports !== module.namespaceObject) { + // in case of a circular dependency: cjs1 -> esm2 -> cjs1 + interopEsm(module.exports, module.namespaceObject); + } + + return module; +} + +/** + * NOTE(alexkirsz) Webpack has a "module execution" interception hook that + * Next.js' React Refresh runtime hooks into to add module context to the + * refresh registry. + */ +function runModuleExecutionHooks( + module: Module, + executeModule: (ctx: RefreshContext) => void +) { + const cleanupReactRefreshIntercept = + typeof globalThis.$RefreshInterceptModuleExecution$ === "function" + ? globalThis.$RefreshInterceptModuleExecution$(module.id) + : () => {}; + + try { + executeModule({ + register: globalThis.$RefreshReg$, + signature: globalThis.$RefreshSig$, + registerExports: registerExportsAndSetupBoundaryForReactRefresh, + }); + } catch (e) { + throw e; + } finally { + // Always cleanup the intercept, even if module execution failed. + cleanupReactRefreshIntercept(); + } +} + +/** + * Retrieves a module from the cache, or instantiate it if it is not cached. + */ +const getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent = ( + id, + sourceModule +) => { + if (!sourceModule.hot.active) { + console.warn( + `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` + ); + } + + const module = moduleCache[id]; + + if (sourceModule.children.indexOf(id) === -1) { + sourceModule.children.push(id); + } + + if (module) { + if (module.parents.indexOf(sourceModule.id) === -1) { + module.parents.push(sourceModule.id); + } + + return module; + } + + return instantiateModule(id, { + type: SourceType.Parent, + parentId: sourceModule.id, + }); +}; + +/** + * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts + */ +function registerExportsAndSetupBoundaryForReactRefresh( + module: Module, + helpers: RefreshHelpers +) { + const currentExports = module.exports; + const prevExports = module.hot.data.prevExports ?? null; + + helpers.registerExportsForReactRefresh(currentExports, module.id); + + // A module can be accepted automatically based on its exports, e.g. when + // it is a Refresh Boundary. + if (helpers.isReactRefreshBoundary(currentExports)) { + // Save the previous exports on update, so we can compare the boundary + // signatures. + module.hot.dispose((data) => { + data.prevExports = currentExports; + }); + // Unconditionally accept an update to this module, we'll check if it's + // still a Refresh Boundary later. + module.hot.accept(); + + // This field is set when the previous version of this module was a + // Refresh Boundary, letting us know we need to check for invalidation or + // enqueue an update. + if (prevExports !== null) { + // A boundary can become ineligible if its exports are incompatible + // with the previous exports. + // + // For example, if you add/remove/change exports, we'll want to + // re-execute the importing modules, and force those components to + // re-render. Similarly, if you convert a class component to a + // function, we want to invalidate the boundary. + if ( + helpers.shouldInvalidateReactRefreshBoundary( + helpers.getRefreshBoundarySignature(prevExports), + helpers.getRefreshBoundarySignature(currentExports) + ) + ) { + module.hot.invalidate(); + } else { + helpers.scheduleUpdate(); + } + } + } else { + // Since we just executed the code for the module, it's possible that the + // new exports made it ineligible for being a boundary. + // We only care about the case when we were _previously_ a boundary, + // because we already accepted this update (accidental side effect). + const isNoLongerABoundary = prevExports !== null; + if (isNoLongerABoundary) { + module.hot.invalidate(); + } + } +} + +function formatDependencyChain(dependencyChain: ModuleId[]): string { + return `Dependency chain: ${dependencyChain.join(" -> ")}`; +} + +function computeOutdatedModules( + added: Map, + modified: Map +): { + outdatedModules: Set; + newModuleFactories: Map; +} { + const newModuleFactories = new Map(); + + for (const [moduleId, entry] of added) { + if (entry != null) { + newModuleFactories.set(moduleId, _eval(entry)); + } + } + + const outdatedModules = computedInvalidatedModules(modified.keys()); + + for (const [moduleId, entry] of modified) { + newModuleFactories.set(moduleId, _eval(entry)); + } + + return { outdatedModules, newModuleFactories }; +} + +function computedInvalidatedModules( + invalidated: Iterable +): Set { + const outdatedModules = new Set(); + + for (const moduleId of invalidated) { + const effect = getAffectedModuleEffects(moduleId); + + switch (effect.type) { + case "unaccepted": + throw new UpdateApplyError( + `cannot apply update: unaccepted module. ${formatDependencyChain( + effect.dependencyChain + )}.`, + effect.dependencyChain + ); + case "self-declined": + throw new UpdateApplyError( + `cannot apply update: self-declined module. ${formatDependencyChain( + effect.dependencyChain + )}.`, + effect.dependencyChain + ); + case "accepted": + for (const outdatedModuleId of effect.outdatedModules) { + outdatedModules.add(outdatedModuleId); + } + break; + // TODO(alexkirsz) Dependencies: handle dependencies effects. + } + } + + return outdatedModules; +} + +function computeOutdatedSelfAcceptedModules( + outdatedModules: Iterable +): { moduleId: ModuleId; errorHandler: true | Function }[] { + const outdatedSelfAcceptedModules = []; + for (const moduleId of outdatedModules) { + const module = moduleCache[moduleId]; + const hotState = moduleHotState.get(module)!; + if (module && hotState.selfAccepted && !hotState.selfInvalidated) { + outdatedSelfAcceptedModules.push({ + moduleId, + errorHandler: hotState.selfAccepted, + }); + } + } + return outdatedSelfAcceptedModules; +} + +/** + * Adds, deletes, and moves modules between chunks. This must happen before the + * dispose phase as it needs to know which modules were removed from all chunks, + * which we can only compute *after* taking care of added and moved modules. + */ +function updateChunksPhase( + chunksAddedModules: Map>, + chunksDeletedModules: Map> +): { disposedModules: Set } { + for (const [chunkPath, addedModuleIds] of chunksAddedModules) { + for (const moduleId of addedModuleIds) { + addModuleToChunk(moduleId, chunkPath); + } + } + + const disposedModules: Set = new Set(); + for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { + for (const moduleId of addedModuleIds) { + if (removeModuleFromChunk(moduleId, chunkPath)) { + disposedModules.add(moduleId); + } + } + } + + return { disposedModules }; +} + +function disposePhase( + outdatedModules: Iterable, + disposedModules: Iterable +): { outdatedModuleParents: Map> } { + for (const moduleId of outdatedModules) { + disposeModule(moduleId, "replace"); + } + + for (const moduleId of disposedModules) { + disposeModule(moduleId, "clear"); + } + + // Removing modules from the module cache is a separate step. + // We also want to keep track of previous parents of the outdated modules. + const outdatedModuleParents = new Map(); + for (const moduleId of outdatedModules) { + const oldModule = moduleCache[moduleId]; + outdatedModuleParents.set(moduleId, oldModule?.parents); + delete moduleCache[moduleId]; + } + + // TODO(alexkirsz) Dependencies: remove outdated dependency from module + // children. + + return { outdatedModuleParents }; +} + +/** + * Disposes of an instance of a module. + * + * Returns the persistent hot data that should be kept for the next module + * instance. + * + * NOTE: mode = "replace" will not remove modules from the moduleCache. + * This must be done in a separate step afterwards. + * This is important because all modules need to be disposed to update the + * parent/child relationships before they are actually removed from the moduleCache. + * If this was done in this method, the following disposeModule calls won't find + * the module from the module id in the cache. + */ +function disposeModule(moduleId: ModuleId, mode: "clear" | "replace") { + const module = moduleCache[moduleId]; + if (!module) { + return; + } + + const hotState = moduleHotState.get(module)!; + const data = {}; + + // Run the `hot.dispose` handler, if any, passing in the persistent + // `hot.data` object. + for (const disposeHandler of hotState.disposeHandlers) { + disposeHandler(data); + } + + // This used to warn in `getOrInstantiateModuleFromParent` when a disposed + // module is still importing other modules. + module.hot.active = false; + + moduleHotState.delete(module); + + // TODO(alexkirsz) Dependencies: delete the module from outdated deps. + + // Remove the disposed module from its children's parent list. + // It will be added back once the module re-instantiates and imports its + // children again. + for (const childId of module.children) { + const child = moduleCache[childId]; + if (!child) { + continue; + } + + const idx = child.parents.indexOf(module.id); + if (idx >= 0) { + child.parents.splice(idx, 1); + } + } + + switch (mode) { + case "clear": + delete moduleCache[module.id]; + moduleHotData.delete(module.id); + break; + case "replace": + moduleHotData.set(module.id, data); + break; + default: + invariant(mode, (mode) => `invalid mode: ${mode}`); + } +} + +function applyPhase( + outdatedSelfAcceptedModules: { + moduleId: ModuleId; + errorHandler: true | Function; + }[], + newModuleFactories: Map, + outdatedModuleParents: Map>, + reportError: (err: any) => void +) { + // Update module factories. + for (const [moduleId, factory] of newModuleFactories.entries()) { + moduleFactories[moduleId] = factory; + } + + // TODO(alexkirsz) Run new runtime entries here. + + // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. + + // Re-instantiate all outdated self-accepted modules. + for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { + try { + instantiateModule(moduleId, { + type: SourceType.Update, + parents: outdatedModuleParents.get(moduleId), + }); + } catch (err) { + if (typeof errorHandler === "function") { + try { + errorHandler(err, { moduleId, module: moduleCache[moduleId] }); + } catch (err2) { + reportError(err2); + reportError(err); + } + } else { + reportError(err); + } + } + } +} + +/** + * Utility function to ensure all variants of an enum are handled. + */ +function invariant(never: never, computeMessage: (arg: any) => string): never { + throw new Error(`Invariant: ${computeMessage(never)}`); +} + +function applyUpdate(update: PartialUpdate) { + switch (update.type) { + case "ChunkListUpdate": + applyChunkListUpdate(update); + break; + default: + invariant(update, (update) => `Unknown update type: ${update.type}`); + } +} + +function applyChunkListUpdate(update: ChunkListUpdate) { + if (update.merged != null) { + for (const merged of update.merged) { + switch (merged.type) { + case "EcmascriptMergedUpdate": + applyEcmascriptMergedUpdate(merged); + break; + default: + invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); + } + } + } + + if (update.chunks != null) { + for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { + switch (chunkUpdate.type) { + case "added": + BACKEND.loadChunk(chunkPath, { type: SourceType.Update }); + break; + case "total": + BACKEND.reloadChunk?.(chunkPath); + break; + case "deleted": + BACKEND.unloadChunk?.(chunkPath); + break; + case "partial": + invariant( + chunkUpdate.instruction, + (instruction) => + `Unknown partial instruction: ${JSON.stringify(instruction)}.` + ); + default: + invariant( + chunkUpdate, + (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` + ); + } + } + } +} + +function applyEcmascriptMergedUpdate(update: EcmascriptMergedUpdate) { + const { entries = {}, chunks = {} } = update; + const { added, modified, chunksAdded, chunksDeleted } = computeChangedModules( + entries, + chunks + ); + const { outdatedModules, newModuleFactories } = computeOutdatedModules( + added, + modified + ); + const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); + + applyInternal(outdatedModules, disposedModules, newModuleFactories); +} + +function applyInvalidatedModules(outdatedModules: Set) { + if (queuedInvalidatedModules.size > 0) { + computedInvalidatedModules(queuedInvalidatedModules).forEach((moduleId) => { + outdatedModules.add(moduleId); + }); + + queuedInvalidatedModules.clear(); + } + + return outdatedModules; +} + +function applyInternal( + outdatedModules: Set, + disposedModules: Iterable, + newModuleFactories: Map +) { + outdatedModules = applyInvalidatedModules(outdatedModules); + + const outdatedSelfAcceptedModules = + computeOutdatedSelfAcceptedModules(outdatedModules); + + const { outdatedModuleParents } = disposePhase( + outdatedModules, + disposedModules + ); + + // we want to continue on error and only throw the error after we tried applying all updates + let error: any; + + function reportError(err: any) { + if (!error) error = err; + } + + applyPhase( + outdatedSelfAcceptedModules, + newModuleFactories, + outdatedModuleParents, + reportError + ); + + if (error) { + throw error; + } + + if (queuedInvalidatedModules.size > 0) { + applyInternal(new Set(), [], new Map()); + } +} + +function computeChangedModules( + entries: Record, + updates: Record +): { + added: Map; + modified: Map; + deleted: Set; + chunksAdded: Map>; + chunksDeleted: Map>; +} { + const chunksAdded = new Map(); + const chunksDeleted = new Map(); + const added: Map = new Map(); + const modified = new Map(); + const deleted: Set = new Set(); + + for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { + switch (mergedChunkUpdate.type) { + case "added": { + const updateAdded = new Set(mergedChunkUpdate.modules); + for (const moduleId of updateAdded) { + added.set(moduleId, entries[moduleId]); + } + chunksAdded.set(chunkPath, updateAdded); + break; + } + case "deleted": { + // We could also use `mergedChunkUpdate.modules` here. + const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); + for (const moduleId of updateDeleted) { + deleted.add(moduleId); + } + chunksDeleted.set(chunkPath, updateDeleted); + break; + } + case "partial": { + const updateAdded = new Set(mergedChunkUpdate.added); + const updateDeleted = new Set(mergedChunkUpdate.deleted); + for (const moduleId of updateAdded) { + added.set(moduleId, entries[moduleId]); + } + for (const moduleId of updateDeleted) { + deleted.add(moduleId); + } + chunksAdded.set(chunkPath, updateAdded); + chunksDeleted.set(chunkPath, updateDeleted); + break; + } + default: + invariant( + mergedChunkUpdate, + (mergedChunkUpdate) => + `Unknown merged chunk update type: ${mergedChunkUpdate.type}` + ); + } + } + + // If a module was added from one chunk and deleted from another in the same update, + // consider it to be modified, as it means the module was moved from one chunk to another + // AND has new code in a single update. + for (const moduleId of added.keys()) { + if (deleted.has(moduleId)) { + added.delete(moduleId); + deleted.delete(moduleId); + } + } + + for (const [moduleId, entry] of Object.entries(entries)) { + // Modules that haven't been added to any chunk but have new code are considered + // to be modified. + // This needs to be under the previous loop, as we need it to get rid of modules + // that were added and deleted in the same update. + if (!added.has(moduleId)) { + modified.set(moduleId, entry); + } + } + + return { added, deleted, modified, chunksAdded, chunksDeleted }; +} + +type ModuleEffect = + | { + type: "unaccepted"; + dependencyChain: ModuleId[]; + } + | { + type: "self-declined"; + dependencyChain: ModuleId[]; + moduleId: ModuleId; + } + | { + type: "accepted"; + moduleId: ModuleId; + outdatedModules: Set; + }; + +function getAffectedModuleEffects(moduleId: ModuleId): ModuleEffect { + const outdatedModules: Set = new Set(); + + type QueueItem = { moduleId?: ModuleId; dependencyChain: ModuleId[] }; + + const queue: QueueItem[] = [ + { + moduleId, + dependencyChain: [], + }, + ]; + + let nextItem; + while ((nextItem = queue.shift())) { + const { moduleId, dependencyChain } = nextItem; + + if (moduleId != null) { + if (outdatedModules.has(moduleId)) { + // Avoid infinite loops caused by cycles between modules in the dependency chain. + continue; + } + + outdatedModules.add(moduleId); + } + + // We've arrived at the runtime of the chunk, which means that nothing + // else above can accept this update. + if (moduleId === undefined) { + return { + type: "unaccepted", + dependencyChain, + }; + } + + const module = moduleCache[moduleId]; + const hotState = moduleHotState.get(module)!; + + if ( + // The module is not in the cache. Since this is a "modified" update, + // it means that the module was never instantiated before. + !module || // The module accepted itself without invalidating globalThis. + // TODO is that right? + (hotState.selfAccepted && !hotState.selfInvalidated) + ) { + continue; + } + + if (hotState.selfDeclined) { + return { + type: "self-declined", + dependencyChain, + moduleId, + }; + } + + if (runtimeModules.has(moduleId)) { + queue.push({ + moduleId: undefined, + dependencyChain: [...dependencyChain, moduleId], + }); + continue; + } + + for (const parentId of module.parents) { + const parent = moduleCache[parentId]; + + if (!parent) { + // TODO(alexkirsz) Is this even possible? + continue; + } + + // TODO(alexkirsz) Dependencies: check accepted and declined + // dependencies here. + + queue.push({ + moduleId: parentId, + dependencyChain: [...dependencyChain, moduleId], + }); + } + } + + return { + type: "accepted", + moduleId, + outdatedModules, + }; +} + +function handleApply(chunkListPath: ChunkPath, update: ServerMessage) { + switch (update.type) { + case "partial": { + // This indicates that the update is can be applied to the current state of the application. + applyUpdate(update.instruction); + break; + } + case "restart": { + // This indicates that there is no way to apply the update to the + // current state of the application, and that the application must be + // restarted. + BACKEND.restart(); + break; + } + case "notFound": { + // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, + // or the page itself was deleted. + // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. + // If it is a runtime chunk list, we restart the application. + if (runtimeChunkLists.has(chunkListPath)) { + BACKEND.restart(); + } else { + disposeChunkList(chunkListPath); + } + break; + } + default: + throw new Error(`Unknown update type: ${update.type}`); + } +} + +function createModuleHot( + moduleId: ModuleId, + hotData: HotData +): { hot: Hot; hotState: HotState } { + const hotState: HotState = { + selfAccepted: false, + selfDeclined: false, + selfInvalidated: false, + disposeHandlers: [], + }; + + const hot: Hot = { + // TODO(alexkirsz) This is not defined in the HMR API. It was used to + // decide whether to warn whenever an HMR-disposed module required other + // modules. We might want to remove it. + active: true, + + data: hotData ?? {}, + + // TODO(alexkirsz) Support full (dep, callback, errorHandler) form. + accept: ( + modules?: string | string[] | AcceptErrorHandler, + _callback?: AcceptCallback, + _errorHandler?: AcceptErrorHandler + ) => { + if (modules === undefined) { + hotState.selfAccepted = true; + } else if (typeof modules === "function") { + hotState.selfAccepted = modules; + } else { + throw new Error("unsupported `accept` signature"); + } + }, + + decline: (dep) => { + if (dep === undefined) { + hotState.selfDeclined = true; + } else { + throw new Error("unsupported `decline` signature"); + } + }, + + dispose: (callback) => { + hotState.disposeHandlers.push(callback); + }, + + addDisposeHandler: (callback) => { + hotState.disposeHandlers.push(callback); + }, + + removeDisposeHandler: (callback) => { + const idx = hotState.disposeHandlers.indexOf(callback); + if (idx >= 0) { + hotState.disposeHandlers.splice(idx, 1); + } + }, + + invalidate: () => { + hotState.selfInvalidated = true; + queuedInvalidatedModules.add(moduleId); + }, + + // NOTE(alexkirsz) This is part of the management API, which we don't + // implement, but the Next.js React Refresh runtime uses this to decide + // whether to schedule an update. + status: () => "idle", + + // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. + addStatusHandler: (_handler) => {}, + removeStatusHandler: (_handler) => {}, + + // NOTE(jridgewell) Check returns the list of updated modules, but we don't + // want the webpack code paths to ever update (the turbopack paths handle + // this already). + check: () => Promise.resolve(null), + }; + + return { hot, hotState }; +} + +/** + * Adds a module to a chunk. + */ +function addModuleToChunk(moduleId: ModuleId, chunkPath: ChunkPath) { + let moduleChunks = moduleChunksMap.get(moduleId); + if (!moduleChunks) { + moduleChunks = new Set([chunkPath]); + moduleChunksMap.set(moduleId, moduleChunks); + } else { + moduleChunks.add(chunkPath); + } + + let chunkModules = chunkModulesMap.get(chunkPath); + if (!chunkModules) { + chunkModules = new Set([moduleId]); + chunkModulesMap.set(chunkPath, chunkModules); + } else { + chunkModules.add(moduleId); + } +} + +/** + * Returns the first chunk that included a module. + * This is used by the Node.js backend, hence why it's marked as unused in this + * file. + */ +function getFirstModuleChunk(moduleId: ModuleId) { + const moduleChunkPaths = moduleChunksMap.get(moduleId); + if (moduleChunkPaths == null) { + return null; + } + + return moduleChunkPaths.values().next().value; +} + +/** + * Removes a module from a chunk. + * Returns `true` if there are no remaining chunks including this module. + */ +function removeModuleFromChunk( + moduleId: ModuleId, + chunkPath: ChunkPath +): boolean { + const moduleChunks = moduleChunksMap.get(moduleId)!; + moduleChunks.delete(chunkPath); + + const chunkModules = chunkModulesMap.get(chunkPath)!; + chunkModules.delete(moduleId); + + const noRemainingModules = chunkModules.size === 0; + if (noRemainingModules) { + chunkModulesMap.delete(chunkPath); + } + + const noRemainingChunks = moduleChunks.size === 0; + if (noRemainingChunks) { + moduleChunksMap.delete(moduleId); + } + + return noRemainingChunks; +} + +/** + * Disposes of a chunk list and its corresponding exclusive chunks. + */ +function disposeChunkList(chunkListPath: ChunkPath): boolean { + const chunkPaths = chunkListChunksMap.get(chunkListPath); + if (chunkPaths == null) { + return false; + } + chunkListChunksMap.delete(chunkListPath); + + for (const chunkPath of chunkPaths) { + const chunkChunkLists = chunkChunkListsMap.get(chunkPath)!; + chunkChunkLists.delete(chunkListPath); + + if (chunkChunkLists.size === 0) { + chunkChunkListsMap.delete(chunkPath); + disposeChunk(chunkPath); + } + } + + // We must also dispose of the chunk list's chunk itself to ensure it may + // be reloaded properly in the future. + BACKEND.unloadChunk?.(chunkListPath); + + return true; +} + +/** + * Disposes of a chunk and its corresponding exclusive modules. + * + * @returns Whether the chunk was disposed of. + */ +function disposeChunk(chunkPath: ChunkPath): boolean { + // This should happen whether the chunk has any modules in it or not. + // For instance, CSS chunks have no modules in them, but they still need to be unloaded. + BACKEND.unloadChunk?.(chunkPath); + + const chunkModules = chunkModulesMap.get(chunkPath); + if (chunkModules == null) { + return false; + } + chunkModules.delete(chunkPath); + + for (const moduleId of chunkModules) { + const moduleChunks = moduleChunksMap.get(moduleId)!; + moduleChunks.delete(chunkPath); + + const noRemainingChunks = moduleChunks.size === 0; + if (noRemainingChunks) { + moduleChunksMap.delete(moduleId); + disposeModule(moduleId, "clear"); + availableModules.delete(moduleId); + } + } + + return true; +} + +/** + * Instantiates a runtime module. + */ +function instantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { + return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath }); +} + +/** + * Gets or instantiates a runtime module. + */ +function getOrInstantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { + const module = moduleCache[moduleId]; + if (module) { + if (module.error) { + throw module.error; + } + return module; + } + + return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath }); +} + +/** + * Returns the URL relative to the origin where a chunk can be fetched from. + */ +function getChunkRelativeUrl(chunkPath: ChunkPath): string { + return `${CHUNK_BASE_PATH}${chunkPath + .split("/") + .map((p) => encodeURIComponent(p)) + .join("/")}`; +} + +/** + * Subscribes to chunk list updates from the update server and applies them. + */ +function registerChunkList( + chunkUpdateProvider: ChunkUpdateProvider, + chunkList: ChunkList +) { + chunkUpdateProvider.push([ + chunkList.path, + handleApply.bind(null, chunkList.path), + ]); + + // Adding chunks to chunk lists and vice versa. + const chunks = new Set(chunkList.chunks.map(getChunkPath)); + chunkListChunksMap.set(chunkList.path, chunks); + for (const chunkPath of chunks) { + let chunkChunkLists = chunkChunkListsMap.get(chunkPath); + if (!chunkChunkLists) { + chunkChunkLists = new Set([chunkList.path]); + chunkChunkListsMap.set(chunkPath, chunkChunkLists); + } else { + chunkChunkLists.add(chunkList.path); + } + } + + if (chunkList.source === "entry") { + markChunkListAsRuntime(chunkList.path); + } +} + +/** + * Marks a chunk list as a runtime chunk list. There can be more than one + * runtime chunk list. For instance, integration tests can have multiple chunk + * groups loaded at runtime, each with its own chunk list. + */ +function markChunkListAsRuntime(chunkListPath: ChunkPath) { + runtimeChunkLists.add(chunkListPath); +} + +function registerChunk([ + chunkPath, + chunkModules, + runtimeParams, +]: ChunkRegistration) { + for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { + if (!moduleFactories[moduleId]) { + moduleFactories[moduleId] = moduleFactory; + } + addModuleToChunk(moduleId, chunkPath); + } + + return BACKEND.registerChunk(chunkPath, runtimeParams); +} + +globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS ??= []; + +const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS; +if (Array.isArray(chunkListsToRegister)) { + for (const chunkList of chunkListsToRegister) { + registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS, chunkList); + } +} + +globalThis.TURBOPACK_CHUNK_LISTS = { + push: (chunkList) => { + registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS!, chunkList); + }, +} satisfies ChunkListProvider; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/tsconfig.json new file mode 100644 index 0000000000000..cc70058649bb6 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/base/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + // environment, we need WebWorker for WebAssembly types + "lib": ["ESNext", "WebWorker"] + }, + "include": ["runtime-base.ts", "dummy.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/dom/runtime-backend-dom.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/dom/runtime-backend-dom.ts new file mode 100644 index 0000000000000..17295aec962db --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/dom/runtime-backend-dom.ts @@ -0,0 +1,303 @@ +/** + * This file contains the runtime code specific to the Turbopack development + * ECMAScript DOM runtime. + * + * It will be appended to the base development runtime code. + */ + +/// +/// + +type ChunkResolver = { + resolved: boolean; + resolve: () => void; + reject: (error?: Error) => void; + promise: Promise; +}; + +let BACKEND: RuntimeBackend; + +function augmentContext(context: TurbopackDevBaseContext): TurbopackDevContext { + return context; +} + +function fetchWebAssembly(wasmChunkPath: ChunkPath) { + return fetch(getChunkRelativeUrl(wasmChunkPath)); +} + +async function loadWebAssembly( + _source: SourceInfo, + wasmChunkPath: ChunkPath, + importsObj: WebAssembly.Imports +): Promise { + const req = fetchWebAssembly(wasmChunkPath); + + const { instance } = await WebAssembly.instantiateStreaming(req, importsObj); + + return instance.exports; +} + +async function loadWebAssemblyModule( + _source: SourceInfo, + wasmChunkPath: ChunkPath +): Promise { + const req = fetchWebAssembly(wasmChunkPath); + + return await WebAssembly.compileStreaming(req); +} + +(() => { + BACKEND = { + async registerChunk(chunkPath, params) { + const resolver = getOrCreateResolver(chunkPath); + resolver.resolve(); + + if (params == null) { + return; + } + + for (const otherChunkData of params.otherChunks) { + const otherChunkPath = getChunkPath(otherChunkData); + // Chunk might have started loading, so we want to avoid triggering another load. + getOrCreateResolver(otherChunkPath); + } + + // This waits for chunks to be loaded, but also marks included items as available. + await Promise.all( + params.otherChunks.map((otherChunkData) => + loadChunk({ type: SourceType.Runtime, chunkPath }, otherChunkData) + ) + ); + + if (params.runtimeModuleIds.length > 0) { + for (const moduleId of params.runtimeModuleIds) { + getOrInstantiateRuntimeModule(moduleId, chunkPath); + } + } + }, + + loadChunk(chunkPath, source) { + return doLoadChunk(chunkPath, source); + }, + + unloadChunk(chunkPath) { + deleteResolver(chunkPath); + + const chunkUrl = getChunkRelativeUrl(chunkPath); + // TODO(PACK-2140): remove this once all filenames are guaranteed to be escaped. + const decodedChunkUrl = decodeURI(chunkUrl); + + if (chunkPath.endsWith(".css")) { + const links = document.querySelectorAll( + `link[href="${chunkUrl}"],link[href^="${chunkUrl}?"],link[href="${decodedChunkUrl}"],link[href^="${decodedChunkUrl}?"]` + ); + for (const link of Array.from(links)) { + link.remove(); + } + } else if (chunkPath.endsWith(".js")) { + // Unloading a JS chunk would have no effect, as it lives in the JS + // runtime once evaluated. + // However, we still want to remove the script tag from the DOM to keep + // the HTML somewhat consistent from the user's perspective. + const scripts = document.querySelectorAll( + `script[src="${chunkUrl}"],script[src^="${chunkUrl}?"],script[src="${decodedChunkUrl}"],script[src^="${decodedChunkUrl}?"]` + ); + for (const script of Array.from(scripts)) { + script.remove(); + } + } else { + throw new Error(`can't infer type of chunk from path ${chunkPath}`); + } + }, + + reloadChunk(chunkPath) { + return new Promise((resolve, reject) => { + if (!chunkPath.endsWith(".css")) { + reject(new Error("The DOM backend can only reload CSS chunks")); + return; + } + + const chunkUrl = getChunkRelativeUrl(chunkPath); + const decodedChunkUrl = decodeURI(chunkUrl); + + const previousLinks = document.querySelectorAll( + `link[rel=stylesheet][href="${chunkUrl}"],link[rel=stylesheet][href^="${chunkUrl}?"],link[rel=stylesheet][href="${decodedChunkUrl}"],link[rel=stylesheet][href^="${decodedChunkUrl}?"]` + ); + + if (previousLinks.length == 0) { + reject(new Error(`No link element found for chunk ${chunkPath}`)); + return; + } + + const link = document.createElement("link"); + link.rel = "stylesheet"; + + if (navigator.userAgent.includes("Firefox")) { + // Firefox won't reload CSS files that were previously loaded on the current page, + // we need to add a query param to make sure CSS is actually reloaded from the server. + // + // I believe this is this issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1037506 + // + // Safari has a similar issue, but only if you have a `` tag + // pointing to the same URL as the stylesheet: https://bugs.webkit.org/show_bug.cgi?id=187726 + link.href = `${chunkUrl}?ts=${Date.now()}`; + } else { + link.href = chunkUrl; + } + + link.onerror = () => { + reject(); + }; + link.onload = () => { + // First load the new CSS, then remove the old ones. This prevents visible + // flickering that would happen in-between removing the previous CSS and + // loading the new one. + for (const previousLink of Array.from(previousLinks)) + previousLink.remove(); + + // CSS chunks do not register themselves, and as such must be marked as + // loaded instantly. + resolve(); + }; + + // Make sure to insert the new CSS right after the previous one, so that + // its precedence is higher. + previousLinks[0].parentElement!.insertBefore( + link, + previousLinks[0].nextSibling + ); + }); + }, + + restart: () => self.location.reload(), + }; + + /** + * Maps chunk paths to the corresponding resolver. + */ + const chunkResolvers: Map = new Map(); + + function getOrCreateResolver(chunkPath: ChunkPath): ChunkResolver { + let resolver = chunkResolvers.get(chunkPath); + if (!resolver) { + let resolve: () => void; + let reject: (error?: Error) => void; + const promise = new Promise((innerResolve, innerReject) => { + resolve = innerResolve; + reject = innerReject; + }); + resolver = { + resolved: false, + promise, + resolve: () => { + resolver!.resolved = true; + resolve(); + }, + reject: reject!, + }; + chunkResolvers.set(chunkPath, resolver); + } + return resolver; + } + + function deleteResolver(chunkPath: ChunkPath) { + chunkResolvers.delete(chunkPath); + } + + /** + * Loads the given chunk, and returns a promise that resolves once the chunk + * has been loaded. + */ + async function doLoadChunk(chunkPath: ChunkPath, source: SourceInfo) { + const resolver = getOrCreateResolver(chunkPath); + if (resolver.resolved) { + return resolver.promise; + } + + if (source.type === SourceType.Runtime) { + // We don't need to load chunks references from runtime code, as they're already + // present in the DOM. + + if (chunkPath.endsWith(".css")) { + // CSS chunks do not register themselves, and as such must be marked as + // loaded instantly. + resolver.resolve(); + } + + // We need to wait for JS chunks to register themselves within `registerChunk` + // before we can start instantiating runtime modules, hence the absence of + // `resolver.resolve()` in this branch. + + return resolver.promise; + } + + const chunkUrl = getChunkRelativeUrl(chunkPath); + const decodedChunkUrl = decodeURI(chunkUrl); + + if (chunkPath.endsWith(".css")) { + const previousLinks = document.querySelectorAll( + `link[rel=stylesheet][href="${chunkUrl}"],link[rel=stylesheet][href^="${chunkUrl}?"],link[rel=stylesheet][href="${decodedChunkUrl}"],link[rel=stylesheet][href^="${decodedChunkUrl}?"]` + ); + if (previousLinks.length > 0) { + // CSS chunks do not register themselves, and as such must be marked as + // loaded instantly. + resolver.resolve(); + } else { + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = chunkUrl; + link.onerror = () => { + resolver.reject(); + }; + link.onload = () => { + // CSS chunks do not register themselves, and as such must be marked as + // loaded instantly. + resolver.resolve(); + }; + document.body.appendChild(link); + } + } else if (chunkPath.endsWith(".js")) { + const previousScripts = document.querySelectorAll( + `script[src="${chunkUrl}"],script[src^="${chunkUrl}?"],script[src="${decodedChunkUrl}"],script[src^="${decodedChunkUrl}?"]` + ); + if (previousScripts.length > 0) { + // There is this edge where the script already failed loading, but we + // can't detect that. The Promise will never resolve in this case. + for (const script of Array.from(previousScripts)) { + script.addEventListener("error", () => { + resolver.reject(); + }); + } + } else { + const script = document.createElement("script"); + script.src = chunkUrl; + // We'll only mark the chunk as loaded once the script has been executed, + // which happens in `registerChunk`. Hence the absence of `resolve()` in + // this branch. + script.onerror = () => { + resolver.reject(); + }; + document.body.appendChild(script); + } + } else { + throw new Error(`can't infer type of chunk from path ${chunkPath}`); + } + + return resolver.promise; + } +})(); + +function _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory { + code += `\n\n//# sourceURL=${encodeURI( + location.origin + CHUNK_BASE_PATH + url + )}`; + if (map) { + code += `\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${btoa( + // btoa doesn't handle nonlatin characters, so escape them as \x sequences + // See https://stackoverflow.com/a/26603875 + unescape(encodeURIComponent(map)) + )}`; + } + + return eval(code); +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/dom/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/dom/tsconfig.json new file mode 100644 index 0000000000000..802c6823e3451 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/dom/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext", "DOM"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/edge/runtime-backend-edge.ts b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/edge/runtime-backend-edge.ts new file mode 100644 index 0000000000000..0f4851977a735 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/edge/runtime-backend-edge.ts @@ -0,0 +1,202 @@ +/** + * This file contains the runtime code specific to the Turbopack development + * ECMAScript "None" runtime (e.g. for Edge). + * + * It will be appended to the base development runtime code. + */ + +/// +/// +/// + +type ChunkRunner = { + requiredChunks: Set; + chunkPath: ChunkPath; + runtimeModuleIds: ModuleId[]; +}; + +let BACKEND: RuntimeBackend; + +type ExternalRequire = ( + id: ModuleId, + esm?: boolean +) => Exports | EsmNamespaceObject; +type ExternalImport = (id: ModuleId) => Promise; + +interface TurbopackDevContext extends TurbopackDevBaseContext { + x: ExternalRequire; + y: ExternalImport; +} + +function augmentContext(context: TurbopackDevBaseContext): TurbopackDevContext { + const nodejsContext = context as TurbopackDevContext; + nodejsContext.x = externalRequire; + nodejsContext.y = externalImport; + return nodejsContext; +} + +async function loadWebAssembly( + source: SourceInfo, + chunkPath: ChunkPath, + imports: WebAssembly.Imports +): Promise { + const module = await loadWebAssemblyModule(source, chunkPath); + + return await WebAssembly.instantiate(module, imports); +} + +function getFileStem(path: string): string { + const fileName = path.split("/").pop()!; + + const stem = fileName.split(".").shift()!; + + if (stem == "") { + return fileName; + } + + return stem; +} + +type GlobalWithInjectedWebAssembly = typeof globalThis & { + [key: `wasm_${string}`]: WebAssembly.Module; +}; + +async function loadWebAssemblyModule( + _source: SourceInfo, + chunkPath: ChunkPath +): Promise { + const stem = getFileStem(chunkPath); + + // very simple escaping just replacing unsupported characters with `_` + const escaped = stem.replace(/[^a-zA-Z0-9$_]/gi, "_"); + + const identifier: `wasm_${string}` = `wasm_${escaped}`; + + const module = (globalThis as GlobalWithInjectedWebAssembly)[identifier]; + + if (!module) { + throw new Error( + `dynamically loading WebAssembly is not supported in this runtime and global \`${identifier}\` was not injected` + ); + } + + return module; +} + +(() => { + BACKEND = { + // The "none" runtime expects all chunks within the same chunk group to be + // registered before any of them are instantiated. + // Furthermore, modules must be instantiated synchronously, hence we don't + // use promises here. + registerChunk(chunkPath, params) { + registeredChunks.add(chunkPath); + instantiateDependentChunks(chunkPath); + + if (params == null) { + return; + } + + if (params.otherChunks.length === 0) { + // The current chunk does not depend on any other chunks, it can be + // instantiated immediately. + instantiateRuntimeModules(params.runtimeModuleIds, chunkPath); + } else { + // The current chunk depends on other chunks, so we need to wait for + // those chunks to be registered before instantiating the runtime + // modules. + registerChunkRunner( + chunkPath, + params.otherChunks.filter((chunk) => + // The none runtime can only handle JS chunks, so we only wait for these + getChunkPath(chunk).endsWith(".js") + ), + params.runtimeModuleIds + ); + } + }, + + loadChunk(_chunkPath, _fromChunkPath) { + throw new Error("chunk loading is not supported"); + }, + + restart: () => { + throw new Error("restart is not supported"); + }, + }; + + const registeredChunks: Set = new Set(); + const runners: Map> = new Map(); + + /** + * Registers a chunk runner that will be instantiated once all of the + * dependencies of the chunk have been registered. + */ + function registerChunkRunner( + chunkPath: ChunkPath, + otherChunks: ChunkData[], + runtimeModuleIds: ModuleId[] + ) { + const requiredChunks: Set = new Set(); + const runner = { + runtimeModuleIds, + chunkPath, + requiredChunks, + }; + + for (const otherChunkData of otherChunks) { + const otherChunkPath = getChunkPath(otherChunkData); + if (registeredChunks.has(otherChunkPath)) { + continue; + } + + requiredChunks.add(otherChunkPath); + let runnersForChunk = runners.get(otherChunkPath); + if (runnersForChunk == null) { + runnersForChunk = new Set(); + runners.set(otherChunkPath, runnersForChunk); + } + runnersForChunk.add(runner); + } + // When all chunks are already registered, we can instantiate the runtime module + if (runner.requiredChunks.size === 0) { + instantiateRuntimeModules(runner.runtimeModuleIds, runner.chunkPath); + } + } + + /** + * Instantiates any chunk runners that were waiting for the given chunk to be + * registered. + */ + function instantiateDependentChunks(chunkPath: ChunkPath) { + // Run any chunk runners that were waiting for this chunk to be + // registered. + const runnersForChunk = runners.get(chunkPath); + if (runnersForChunk != null) { + for (const runner of runnersForChunk) { + runner.requiredChunks.delete(chunkPath); + + if (runner.requiredChunks.size === 0) { + instantiateRuntimeModules(runner.runtimeModuleIds, runner.chunkPath); + } + } + runners.delete(chunkPath); + } + } + + /** + * Instantiates the runtime modules for the given chunk. + */ + function instantiateRuntimeModules( + runtimeModuleIds: ModuleId[], + chunkPath: ChunkPath + ) { + for (const moduleId of runtimeModuleIds) { + getOrInstantiateRuntimeModule(moduleId, chunkPath); + } + } +})(); + +function _eval(_: EcmascriptModuleEntry): ModuleFactory { + throw new Error("HMR evaluation is not implemented on this backend"); +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/edge/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/edge/tsconfig.json new file mode 100644 index 0000000000000..fabb2ed16dbbb --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/browser/dev/runtime/edge/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + // environment, we need WebWorker for WebAssembly types + "lib": ["ESNext", "WebWorker"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/main.js b/crates/turbopack-ecmascript-runtime/js/Source/main.js new file mode 100644 index 0000000000000..dddce0ffc51a2 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/main.js @@ -0,0 +1 @@ +// required for NCC to work diff --git a/crates/turbopack-ecmascript-runtime/js/Source/nodejs/runtime.ts b/crates/turbopack-ecmascript-runtime/js/Source/nodejs/runtime.ts new file mode 100644 index 0000000000000..acfdeaa5e003b --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/nodejs/runtime.ts @@ -0,0 +1,289 @@ +/// +/// +/// +/// + +enum SourceType { + /** + * The module was instantiated because it was included in an evaluated chunk's + * runtime. + */ + Runtime = 0, + /** + * The module was instantiated because a parent module imported it. + */ + Parent = 1, +} + +type SourceInfo = + | { + type: SourceType.Runtime; + chunkPath: ChunkPath; + } + | { + type: SourceType.Parent; + parentId: ModuleId; + }; + +function stringifySourceInfo(source: SourceInfo): string { + switch (source.type) { + case SourceType.Runtime: + return `runtime for chunk ${source.chunkPath}`; + case SourceType.Parent: + return `parent module ${source.parentId}`; + } +} + +type ExternalRequire = (id: ModuleId) => Exports | EsmNamespaceObject; +type ExternalImport = (id: ModuleId) => Promise; +type ResolveAbsolutePath = (modulePath?: string) => string; + +interface TurbopackNodeBuildContext extends TurbopackBaseContext { + P: ResolveAbsolutePath; + R: ResolvePathFromModule; + x: ExternalRequire; + y: ExternalImport; +} + +type ModuleFactory = ( + this: Module["exports"], + context: TurbopackNodeBuildContext +) => undefined; + +const url = require("url"); + +const moduleFactories: ModuleFactories = Object.create(null); +const moduleCache: ModuleCache = Object.create(null); + +/** + * Returns an absolute path to the given module's id. + */ +function createResolvePathFromModule( + resolver: (moduleId: string) => Exports +): (moduleId: string) => string { + return function resolvePathFromModule(moduleId: string): string { + const exported = resolver(moduleId); + const exportedPath = exported?.default ?? exported; + if (typeof exportedPath !== "string") { + return exported as any; + } + + const strippedAssetPrefix = exportedPath.slice(ASSET_PREFIX.length); + const resolved = path.resolve( + ABSOLUTE_ROOT, + OUTPUT_ROOT, + strippedAssetPrefix + ); + + return url.pathToFileURL(resolved); + }; +} + +function loadChunk(chunkData: ChunkData, source?: SourceInfo): void { + if (typeof chunkData === "string") { + return loadChunkPath(chunkData, source); + } else { + return loadChunkPath(chunkData.path, source); + } +} + +function loadChunkPath(chunkPath: ChunkPath, source?: SourceInfo): void { + if (!chunkPath.endsWith(".js")) { + // We only support loading JS chunks in Node.js. + // This branch can be hit when trying to load a CSS chunk. + return; + } + + try { + const resolved = path.resolve(RUNTIME_ROOT, chunkPath); + const chunkModules: ModuleFactories = require(resolved); + + for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { + if (!moduleFactories[moduleId]) { + moduleFactories[moduleId] = moduleFactory; + } + } + } catch (e) { + let errorMessage = `Failed to load chunk ${chunkPath}`; + + if (source) { + errorMessage += ` from ${stringifySourceInfo(source)}`; + } + + throw new Error(errorMessage, { + cause: e, + }); + } +} + +async function loadChunkAsync( + source: SourceInfo, + chunkData: ChunkData +): Promise { + return new Promise((resolve, reject) => { + try { + loadChunk(chunkData, source); + } catch (err) { + reject(err); + return; + } + resolve(); + }); +} + +function loadWebAssembly(chunkPath: ChunkPath, imports: WebAssembly.Imports) { + const resolved = path.resolve(RUNTIME_ROOT, chunkPath); + + return instantiateWebAssemblyFromPath(resolved, imports); +} + +function loadWebAssemblyModule(chunkPath: ChunkPath) { + const resolved = path.resolve(RUNTIME_ROOT, chunkPath); + + return compileWebAssemblyFromPath(resolved); +} + +function instantiateModule(id: ModuleId, source: SourceInfo): Module { + const moduleFactory = moduleFactories[id]; + if (typeof moduleFactory !== "function") { + // This can happen if modules incorrectly handle HMR disposes/updates, + // e.g. when they keep a `setTimeout` around which still executes old code + // and contains e.g. a `require("something")` call. + let instantiationReason; + switch (source.type) { + case SourceType.Runtime: + instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; + break; + case SourceType.Parent: + instantiationReason = `because it was required from module ${source.parentId}`; + break; + } + throw new Error( + `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` + ); + } + + let parents: ModuleId[]; + switch (source.type) { + case SourceType.Runtime: + parents = []; + break; + case SourceType.Parent: + // No need to add this module as a child of the parent module here, this + // has already been taken care of in `getOrInstantiateModuleFromParent`. + parents = [source.parentId]; + break; + } + + const module: Module = { + exports: {}, + error: undefined, + loaded: false, + id, + parents, + children: [], + namespaceObject: undefined, + }; + moduleCache[id] = module; + + // NOTE(alexkirsz) This can fail when the module encounters a runtime error. + try { + const r = commonJsRequire.bind(null, module); + moduleFactory.call(module.exports, { + a: asyncModule.bind(null, module), + e: module.exports, + r, + t: runtimeRequire, + x: externalRequire, + y: externalImport, + f: moduleContext, + i: esmImport.bind(null, module), + s: esmExport.bind(null, module, module.exports), + j: dynamicExport.bind(null, module, module.exports), + v: exportValue.bind(null, module), + n: exportNamespace.bind(null, module), + m: module, + c: moduleCache, + M: moduleFactories, + l: loadChunkAsync.bind(null, { type: SourceType.Parent, parentId: id }), + w: loadWebAssembly, + u: loadWebAssemblyModule, + g: globalThis, + P: resolveAbsolutePath, + U: relativeURL, + R: createResolvePathFromModule(r), + __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), + }); + } catch (error) { + module.error = error as any; + throw error; + } + + module.loaded = true; + if (module.namespaceObject && module.exports !== module.namespaceObject) { + // in case of a circular dependency: cjs1 -> esm2 -> cjs1 + interopEsm(module.exports, module.namespaceObject); + } + + return module; +} + +/** + * Retrieves a module from the cache, or instantiate it if it is not cached. + */ +function getOrInstantiateModuleFromParent( + id: ModuleId, + sourceModule: Module +): Module { + const module = moduleCache[id]; + + if (sourceModule.children.indexOf(id) === -1) { + sourceModule.children.push(id); + } + + if (module) { + if (module.parents.indexOf(sourceModule.id) === -1) { + module.parents.push(sourceModule.id); + } + + return module; + } + + return instantiateModule(id, { + type: SourceType.Parent, + parentId: sourceModule.id, + }); +} + +/** + * Instantiates a runtime module. + */ +function instantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { + return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath }); +} + +/** + * Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached. + */ +function getOrInstantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { + const module = moduleCache[moduleId]; + if (module) { + if (module.error) { + throw module.error; + } + return module; + } + + return instantiateRuntimeModule(moduleId, chunkPath); +} + +module.exports = { + getOrInstantiateRuntimeModule, + loadChunk, +}; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/nodejs/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/Source/nodejs/tsconfig.json new file mode 100644 index 0000000000000..fbc393330f47e --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/nodejs/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + // environment, we need WebWorker for WebAssembly types (not part of @types/node yet) + "lib": ["ESNext", "WebWorker"], + "types": ["node"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared-node/base-externals-utils.ts b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/base-externals-utils.ts new file mode 100644 index 0000000000000..a47faf56fe65a --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/base-externals-utils.ts @@ -0,0 +1,55 @@ +/// + +/// A 'base' utilities to support runtime can have externals. +/// Currently this is for node.js / edge runtime both. +/// If a fn requires node.js specific behavior, it should be placed in `node-external-utils` instead. + +async function externalImport(id: ModuleId) { + let raw; + try { + raw = await import(id); + } catch (err) { + // TODO(alexkirsz) This can happen when a client-side module tries to load + // an external module we don't provide a shim for (e.g. querystring, url). + // For now, we fail semi-silently, but in the future this should be a + // compilation error. + throw new Error(`Failed to load external module ${id}: ${err}`); + } + + if (raw && raw.__esModule && raw.default && "default" in raw.default) { + return interopEsm(raw.default, createNS(raw), true); + } + + return raw; +} + +function externalRequire( + id: ModuleId, + esm: boolean = false +): Exports | EsmNamespaceObject { + let raw; + try { + raw = require(id); + } catch (err) { + // TODO(alexkirsz) This can happen when a client-side module tries to load + // an external module we don't provide a shim for (e.g. querystring, url). + // For now, we fail semi-silently, but in the future this should be a + // compilation error. + throw new Error(`Failed to load external module ${id}: ${err}`); + } + + if (!esm || raw.__esModule) { + return raw; + } + + return interopEsm(raw, createNS(raw), true); +} + +externalRequire.resolve = ( + id: string, + options?: { + paths?: string[]; + } +) => { + return require.resolve(id, options); +}; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared-node/node-externals-utils.ts b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/node-externals-utils.ts new file mode 100644 index 0000000000000..ce2e1d5da5535 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/node-externals-utils.ts @@ -0,0 +1,30 @@ +declare var RUNTIME_PUBLIC_PATH: string; +declare var OUTPUT_ROOT: string; +declare var ASSET_PREFIX: string; + +const path = require("path"); + +const relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, "."); +// Compute the relative path to the `distDir`. +const relativePathToDistRoot = path.relative( + path.join(OUTPUT_ROOT, RUNTIME_PUBLIC_PATH), + "." +); +const RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot); +// Compute the absolute path to the root, by stripping distDir from the absolute path to this file. +const ABSOLUTE_ROOT = path.resolve(__filename, relativePathToDistRoot); + +/** + * Returns an absolute path to the given module path. + * Module path should be relative, either path to a file or a directory. + * + * This fn allows to calculate an absolute path for some global static values, such as + * `__dirname` or `import.meta.url` that Turbopack will not embeds in compile time. + * See ImportMetaBinding::code_generation for the usage. + */ +function resolveAbsolutePath(modulePath?: string): string { + if (modulePath) { + return path.join(ABSOLUTE_ROOT, modulePath); + } + return ABSOLUTE_ROOT; +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared-node/node-wasm-utils.ts b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/node-wasm-utils.ts new file mode 100644 index 0000000000000..1baa2fc01c0c3 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/node-wasm-utils.ts @@ -0,0 +1,37 @@ +/// + +function readWebAssemblyAsResponse(path: string) { + const { createReadStream } = require("fs") as typeof import("fs"); + const { Readable } = require("stream") as typeof import("stream"); + + const stream = createReadStream(path); + + // @ts-ignore unfortunately there's a slight type mismatch with the stream. + return new Response(Readable.toWeb(stream), { + headers: { + "content-type": "application/wasm", + }, + }); +} + +async function compileWebAssemblyFromPath( + path: string +): Promise { + const response = readWebAssemblyAsResponse(path); + + return await WebAssembly.compileStreaming(response); +} + +async function instantiateWebAssemblyFromPath( + path: string, + importsObj: WebAssembly.Imports +): Promise { + const response = readWebAssemblyAsResponse(path); + + const { instance } = await WebAssembly.instantiateStreaming( + response, + importsObj + ); + + return instance.exports; +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared-node/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/tsconfig.json new file mode 100644 index 0000000000000..fbc393330f47e --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared-node/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + // environment, we need WebWorker for WebAssembly types (not part of @types/node yet) + "lib": ["ESNext", "WebWorker"], + "types": ["node"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared/dummy.ts b/crates/turbopack-ecmascript-runtime/js/Source/shared/dummy.ts new file mode 100644 index 0000000000000..a3aea592da891 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared/dummy.ts @@ -0,0 +1,8 @@ +/** + * This file acts as a dummy implementor for the interface that + * `runtime-utils.ts` expects to be available in the global scope. + * + * This interface will be implemented by runtimes. + */ + +declare var getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared/require-type.d.ts b/crates/turbopack-ecmascript-runtime/js/Source/shared/require-type.d.ts new file mode 100644 index 0000000000000..b28e19778e877 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared/require-type.d.ts @@ -0,0 +1,9 @@ +// Make sure that `require` is available for runtime-utils.ts. +declare var require: ((moduleId: ModuleId) => Exports) & { + resolve: ( + moduleId: ModuleId, + options?: { + paths?: string[]; + } + ) => ModuleId; +}; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared/runtime-types.d.ts b/crates/turbopack-ecmascript-runtime/js/Source/shared/runtime-types.d.ts new file mode 100644 index 0000000000000..dd2e336c7e1de --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared/runtime-types.d.ts @@ -0,0 +1,76 @@ +/** + * This file contains runtime types that are shared between all TurboPack + * ECMAScript runtimes. + * + * It is separate from `runtime-utils.ts` because it can be used outside of + * runtime code, hence it should not contain any function declarations that are + * specific to the runtime context. + */ + +type ChunkPath = string; +type ModuleId = string; + +type ChunkData = + | ChunkPath + | { + path: ChunkPath; + included: ModuleId[]; + excluded: ModuleId[]; + moduleChunks: ChunkPath[]; + }; + +type CommonJsRequire = (moduleId: ModuleId) => Exports; +type ModuleContextFactory = (map: ModuleContextMap) => ModuleContext; +type EsmImport = ( + moduleId: ModuleId, + allowExportDefault: boolean +) => EsmNamespaceObject | Promise; +type EsmExport = (exportGetters: Record any>) => void; +type ExportValue = (value: any) => void; +type ExportNamespace = (namespace: any) => void; +type DynamicExport = (object: Record) => void; + +type LoadChunk = (chunkPath: ChunkPath) => Promise | undefined; +type LoadWebAssembly = ( + wasmChunkPath: ChunkPath, + imports: WebAssembly.Imports +) => Exports; +type LoadWebAssemblyModule = (wasmChunkPath: ChunkPath) => WebAssembly.Module; + +type ModuleCache = Record; +type ModuleFactories = Record; + +type RelativeURL = (inputUrl: string) => void; +type ResolvePathFromModule = (moduleId: string) => string; + +type AsyncModule = ( + body: ( + handleAsyncDependencies: ( + deps: Dep[] + ) => Exports[] | Promise<() => Exports[]>, + asyncResult: (err?: any) => void + ) => void, + hasAwait: boolean +) => void; + +interface TurbopackBaseContext { + a: AsyncModule; + e: Module["exports"]; + r: CommonJsRequire; + t: CommonJsRequire; + f: ModuleContextFactory; + i: EsmImport; + s: EsmExport; + j: DynamicExport; + v: ExportValue; + n: ExportNamespace; + m: Module; + c: ModuleCache; + M: ModuleFactories; + l: LoadChunk; + w: LoadWebAssembly; + u: LoadWebAssemblyModule; + g: typeof globalThis; + U: RelativeURL; + __dirname: string; +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared/runtime-utils.ts b/crates/turbopack-ecmascript-runtime/js/Source/shared/runtime-utils.ts new file mode 100644 index 0000000000000..b79197790fd74 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared/runtime-utils.ts @@ -0,0 +1,516 @@ +/** + * This file contains runtime types and functions that are shared between all + * TurboPack ECMAScript runtimes. + * + * It will be prepended to the runtime code of each runtime. + */ + +/* eslint-disable @next/next/no-assign-module-variable */ + +/// + +interface Exports { + __esModule?: boolean; + + [key: string]: any; +} + +type EsmNamespaceObject = Record; + +const REEXPORTED_OBJECTS = Symbol("reexported objects"); + +interface BaseModule { + exports: Function | Exports | Promise | AsyncModulePromise; + error: Error | undefined; + loaded: boolean; + id: ModuleId; + children: ModuleId[]; + parents: ModuleId[]; + namespaceObject?: + | EsmNamespaceObject + | Promise + | AsyncModulePromise; + [REEXPORTED_OBJECTS]?: any[]; +} + +interface Module extends BaseModule {} + +type ModuleContextMap = Record; + +interface ModuleContextEntry { + id: () => ModuleId; + module: () => any; +} + +interface ModuleContext { + // require call + (moduleId: ModuleId): Exports | EsmNamespaceObject; + + // async import call + import(moduleId: ModuleId): Promise; + + keys(): ModuleId[]; + + resolve(moduleId: ModuleId): ModuleId; +} + +type GetOrInstantiateModuleFromParent = ( + moduleId: ModuleId, + parentModule: Module +) => Module; + +const hasOwnProperty = Object.prototype.hasOwnProperty; +const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; + +function defineProp( + obj: any, + name: PropertyKey, + options: PropertyDescriptor & ThisType +) { + if (!hasOwnProperty.call(obj, name)) + Object.defineProperty(obj, name, options); +} + +/** + * Adds the getters to the exports object. + */ +function esm( + exports: Exports, + getters: Record any) | [() => any, (v: any) => void]> +) { + defineProp(exports, "__esModule", { value: true }); + if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); + for (const key in getters) { + const item = getters[key]; + if (Array.isArray(item)) { + defineProp(exports, key, { + get: item[0], + set: item[1], + enumerable: true, + }); + } else { + defineProp(exports, key, { get: item, enumerable: true }); + } + } + Object.seal(exports); +} + +/** + * Makes the module an ESM with exports + */ +function esmExport( + module: Module, + exports: Exports, + getters: Record any> +) { + module.namespaceObject = module.exports; + esm(exports, getters); +} + +function ensureDynamicExports(module: Module, exports: Exports) { + let reexportedObjects = module[REEXPORTED_OBJECTS]; + + if (!reexportedObjects) { + reexportedObjects = module[REEXPORTED_OBJECTS] = []; + module.exports = module.namespaceObject = new Proxy(exports, { + get(target, prop) { + if ( + hasOwnProperty.call(target, prop) || + prop === "default" || + prop === "__esModule" + ) { + return Reflect.get(target, prop); + } + for (const obj of reexportedObjects!) { + const value = Reflect.get(obj, prop); + if (value !== undefined) return value; + } + return undefined; + }, + ownKeys(target) { + const keys = Reflect.ownKeys(target); + for (const obj of reexportedObjects!) { + for (const key of Reflect.ownKeys(obj)) { + if (key !== "default" && !keys.includes(key)) keys.push(key); + } + } + return keys; + }, + }); + } +} + +/** + * Dynamically exports properties from an object + */ +function dynamicExport( + module: Module, + exports: Exports, + object: Record +) { + ensureDynamicExports(module, exports); + + if (typeof object === "object" && object !== null) { + module[REEXPORTED_OBJECTS]!.push(object); + } +} + +function exportValue(module: Module, value: any) { + module.exports = value; +} + +function exportNamespace(module: Module, namespace: any) { + module.exports = module.namespaceObject = namespace; +} + +function createGetter(obj: Record, key: string | symbol) { + return () => obj[key]; +} + +/** + * @returns prototype of the object + */ +const getProto: (obj: any) => any = Object.getPrototypeOf + ? (obj) => Object.getPrototypeOf(obj) + : (obj) => obj.__proto__; + +/** Prototypes that are not expanded for exports */ +const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; + +/** + * @param raw + * @param ns + * @param allowExportDefault + * * `false`: will have the raw module as default export + * * `true`: will have the default property as default export + */ +function interopEsm( + raw: Exports, + ns: EsmNamespaceObject, + allowExportDefault?: boolean +) { + const getters: { [s: string]: () => any } = Object.create(null); + for ( + let current = raw; + (typeof current === "object" || typeof current === "function") && + !LEAF_PROTOTYPES.includes(current); + current = getProto(current) + ) { + for (const key of Object.getOwnPropertyNames(current)) { + getters[key] = createGetter(raw, key); + } + } + + // this is not really correct + // we should set the `default` getter if the imported module is a `.cjs file` + if (!(allowExportDefault && "default" in getters)) { + getters["default"] = () => raw; + } + + esm(ns, getters); + return ns; +} + +function createNS(raw: BaseModule["exports"]): EsmNamespaceObject { + if (typeof raw === "function") { + return function (this: any, ...args: any[]) { + return raw.apply(this, args); + }; + } else { + return Object.create(null); + } +} + +function esmImport( + sourceModule: Module, + id: ModuleId +): Exclude { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + + // any ES module has to have `module.namespaceObject` defined. + if (module.namespaceObject) return module.namespaceObject; + + // only ESM can be an async module, so we don't need to worry about exports being a promise here. + const raw = module.exports; + return (module.namespaceObject = interopEsm( + raw, + createNS(raw), + raw && (raw as any).__esModule + )); +} + +// Add a simple runtime require so that environments without one can still pass +// `typeof require` CommonJS checks so that exports are correctly registered. +const runtimeRequire = + typeof require === "function" + ? require + : function require() { + throw new Error("Unexpected use of runtime require"); + }; + +function commonJsRequire(sourceModule: Module, id: ModuleId): Exports { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + return module.exports; +} + +/** + * `require.context` and require/import expression runtime. + */ +function moduleContext(map: ModuleContextMap): ModuleContext { + function moduleContext(id: ModuleId): Exports { + if (hasOwnProperty.call(map, id)) { + return map[id].module(); + } + + const e = new Error(`Cannot find module '${name}'`); + (e as any).code = "MODULE_NOT_FOUND"; + throw e; + } + + moduleContext.keys = (): ModuleId[] => { + return Object.keys(map); + }; + + moduleContext.resolve = (id: ModuleId): ModuleId => { + if (hasOwnProperty.call(map, id)) { + return map[id].id(); + } + + const e = new Error(`Cannot find module '${name}'`); + (e as any).code = "MODULE_NOT_FOUND"; + throw e; + }; + + moduleContext.import = async (id: ModuleId) => { + return await (moduleContext(id) as Promise); + }; + + return moduleContext; +} + +/** + * Returns the path of a chunk defined by its data. + */ +function getChunkPath(chunkData: ChunkData): ChunkPath { + return typeof chunkData === "string" ? chunkData : chunkData.path; +} + +function isPromise(maybePromise: any): maybePromise is Promise { + return ( + maybePromise != null && + typeof maybePromise === "object" && + "then" in maybePromise && + typeof maybePromise.then === "function" + ); +} + +function isAsyncModuleExt(obj: T): obj is AsyncModuleExt & T { + return turbopackQueues in obj; +} + +function createPromise() { + let resolve: (value: T | PromiseLike) => void; + let reject: (reason?: any) => void; + + const promise = new Promise((res, rej) => { + reject = rej; + resolve = res; + }); + + return { + promise, + resolve: resolve!, + reject: reject!, + }; +} + +// everything below is adapted from webpack +// https://github.com/webpack/webpack/blob/6be4065ade1e252c1d8dcba4af0f43e32af1bdc1/lib/runtime/AsyncModuleRuntimeModule.js#L13 + +const turbopackQueues = Symbol("turbopack queues"); +const turbopackExports = Symbol("turbopack exports"); +const turbopackError = Symbol("turbopack error"); + +const enum QueueStatus { + Unknown = -1, + Unresolved = 0, + Resolved = 1, +} + +type AsyncQueueFn = (() => void) & { queueCount: number }; +type AsyncQueue = AsyncQueueFn[] & { + status: QueueStatus; +}; + +function resolveQueue(queue?: AsyncQueue) { + if (queue && queue.status !== QueueStatus.Resolved) { + queue.status = QueueStatus.Resolved; + queue.forEach((fn) => fn.queueCount--); + queue.forEach((fn) => (fn.queueCount-- ? fn.queueCount++ : fn())); + } +} + +type Dep = Exports | AsyncModulePromise | Promise; + +type AsyncModuleExt = { + [turbopackQueues]: (fn: (queue: AsyncQueue) => void) => void; + [turbopackExports]: Exports; + [turbopackError]?: any; +}; + +type AsyncModulePromise = Promise & AsyncModuleExt; + +function wrapDeps(deps: Dep[]): AsyncModuleExt[] { + return deps.map((dep): AsyncModuleExt => { + if (dep !== null && typeof dep === "object") { + if (isAsyncModuleExt(dep)) return dep; + if (isPromise(dep)) { + const queue: AsyncQueue = Object.assign([], { + status: QueueStatus.Unresolved, + }); + + const obj: AsyncModuleExt = { + [turbopackExports]: {}, + [turbopackQueues]: (fn: (queue: AsyncQueue) => void) => fn(queue), + }; + + dep.then( + (res) => { + obj[turbopackExports] = res; + resolveQueue(queue); + }, + (err) => { + obj[turbopackError] = err; + resolveQueue(queue); + } + ); + + return obj; + } + } + + return { + [turbopackExports]: dep, + [turbopackQueues]: () => {}, + }; + }); +} + +function asyncModule( + module: Module, + body: ( + handleAsyncDependencies: ( + deps: Dep[] + ) => Exports[] | Promise<() => Exports[]>, + asyncResult: (err?: any) => void + ) => void, + hasAwait: boolean +) { + const queue: AsyncQueue | undefined = hasAwait + ? Object.assign([], { status: QueueStatus.Unknown }) + : undefined; + + const depQueues: Set = new Set(); + + const { resolve, reject, promise: rawPromise } = createPromise(); + + const promise: AsyncModulePromise = Object.assign(rawPromise, { + [turbopackExports]: module.exports, + [turbopackQueues]: (fn) => { + queue && fn(queue); + depQueues.forEach(fn); + promise["catch"](() => {}); + }, + } satisfies AsyncModuleExt); + + const attributes: PropertyDescriptor = { + get(): any { + return promise; + }, + set(v: any) { + // Calling `esmExport` leads to this. + if (v !== promise) { + promise[turbopackExports] = v; + } + }, + }; + + Object.defineProperty(module, "exports", attributes); + Object.defineProperty(module, "namespaceObject", attributes); + + function handleAsyncDependencies(deps: Dep[]) { + const currentDeps = wrapDeps(deps); + + const getResult = () => + currentDeps.map((d) => { + if (d[turbopackError]) throw d[turbopackError]; + return d[turbopackExports]; + }); + + const { promise, resolve } = createPromise<() => Exports[]>(); + + const fn: AsyncQueueFn = Object.assign(() => resolve(getResult), { + queueCount: 0, + }); + + function fnQueue(q: AsyncQueue) { + if (q !== queue && !depQueues.has(q)) { + depQueues.add(q); + if (q && q.status === QueueStatus.Unresolved) { + fn.queueCount++; + q.push(fn); + } + } + } + + currentDeps.map((dep) => dep[turbopackQueues](fnQueue)); + + return fn.queueCount ? promise : getResult(); + } + + function asyncResult(err?: any) { + if (err) { + reject((promise[turbopackError] = err)); + } else { + resolve(promise[turbopackExports]); + } + + resolveQueue(queue); + } + + body(handleAsyncDependencies, asyncResult); + + if (queue && queue.status === QueueStatus.Unknown) { + queue.status = QueueStatus.Unresolved; + } +} + +/** + * A pseudo "fake" URL object to resolve to its relative path. + * + * When UrlRewriteBehavior is set to relative, calls to the `new URL()` will construct url without base using this + * runtime function to generate context-agnostic urls between different rendering context, i.e ssr / client to avoid + * hydration mismatch. + * + * This is based on webpack's existing implementation: + * https://github.com/webpack/webpack/blob/87660921808566ef3b8796f8df61bd79fc026108/lib/runtime/RelativeUrlRuntimeModule.js + */ +const relativeURL = function relativeURL(this: any, inputUrl: string) { + const realUrl = new URL(inputUrl, "x:/"); + const values: Record = {}; + for (const key in realUrl) values[key] = (realUrl as any)[key]; + values.href = inputUrl; + values.pathname = inputUrl.replace(/[?#].*/, ""); + values.origin = values.protocol = ""; + values.toString = values.toJSON = (..._args: Array) => inputUrl; + for (const key in values) + Object.defineProperty(this, key, { + enumerable: true, + configurable: true, + value: values[key], + }); +}; + +relativeURL.prototype = URL.prototype; diff --git a/crates/turbopack-ecmascript-runtime/js/Source/shared/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/Source/shared/tsconfig.json new file mode 100644 index 0000000000000..c255a6ca179fc --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/shared/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + // environment, we need WebWorker for WebAssembly types + "lib": ["ESNext", "WebWorker"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/Source/tsconfig.base.json b/crates/turbopack-ecmascript-runtime/js/Source/tsconfig.base.json new file mode 100644 index 0000000000000..978189abece60 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/Source/tsconfig.base.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + // type checking + "strict": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + // environment + "target": "ESNext", + + // modules + "baseUrl": ".", + "module": "CommonJS", + "types": [], // disable implicit types. + + // emit + "noEmit": true, + "stripInternal": true + } +} diff --git a/crates/turbopack-ecmascript-runtime/js/package.json b/crates/turbopack-ecmascript-runtime/js/package.json new file mode 100644 index 0000000000000..6813f3058e1ad --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/package.json @@ -0,0 +1,22 @@ +{ + "name": "@vercel/turbopack-ecmascript-runtime", + "description": "Turbopack EcmaScript runtime code and utilities", + "exports": { + ".": "./src/main.js", + "./*": "./src/*.ts" + }, + "scripts": { + "check:browser-dev-client": "tsc -p src/browser/dev/hmr-client", + "check:browser-dev-runtime-base": "tsc -p src/browser/dev/runtime/base", + "check:browser-dev-runtime-dom": "tsc -p src/browser/dev/runtime/dom", + "check:browser-dev-runtime-edge": "tsc -p src/browser/dev/runtime/edge", + "check:nodejs": "tsc -p src/nodejs" + }, + "dependencies": { + "@types/node": "22.13.1" + }, + "devDependencies": { + "@next/react-refresh-utils": "15.1.7", + "npm-run-all": "4.1.5" + } +} diff --git a/crates/turbopack-ecmascript/Source/analyzer/builtin.rs b/crates/turbopack-ecmascript/Source/analyzer/builtin.rs new file mode 100644 index 0000000000000..408eb71973746 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/analyzer/builtin.rs @@ -0,0 +1,544 @@ +use std::mem::take; + +use swc_core::ecma::atoms::js_word; + +use super::{ConstantNumber, ConstantValue, JsValue, LogicalOperator, ObjectPart}; + +/// Replaces some builtin values with their resulting values. Called early +/// without lazy nested values. This allows to skip a lot of work to process the +/// arguments. +pub fn early_replace_builtin(value:&mut JsValue) -> bool { + match value { + // matching calls like `callee(arg1, arg2, ...)` + JsValue::Call(_, box ref mut callee, args) => { + let args_have_side_effects = || args.iter().any(|arg| arg.has_side_effects()); + match callee { + // We don't know what the callee is, so we can early return + &mut JsValue::Unknown { original_value: _, reason: _, has_side_effects } => { + let has_side_effects = has_side_effects || args_have_side_effects(); + value.make_unknown(has_side_effects, "unknown callee"); + true + }, + // We known that these callee will lead to an error at runtime, so we can skip + // processing them + JsValue::Constant(_) + | JsValue::Url(_) + | JsValue::WellKnownObject(_) + | JsValue::Array { .. } + | JsValue::Object { .. } + | JsValue::Alternatives(..) + | JsValue::Concat(..) + | JsValue::Add(..) + | JsValue::Not(..) => { + let has_side_effects = args_have_side_effects(); + value.make_unknown(has_side_effects, "non-function callee"); + true + }, + _ => false, + } + }, + // matching calls with this context like `obj.prop(arg1, arg2, ...)` + JsValue::MemberCall(_, box ref mut obj, box ref mut prop, args) => { + let args_have_side_effects = || args.iter().any(|arg| arg.has_side_effects()); + match obj { + // We don't know what the callee is, so we can early return + &mut JsValue::Unknown { original_value: _, reason: _, has_side_effects } => { + let side_effects = + has_side_effects || prop.has_side_effects() || args_have_side_effects(); + value.make_unknown(side_effects, "unknown callee object"); + true + }, + // otherwise we need to look at the property + _ => { + match prop { + // We don't know what the property is, so we can early return + &mut JsValue::Unknown { + original_value: _, + reason: _, + has_side_effects, + } => { + let side_effects = has_side_effects || args_have_side_effects(); + value.make_unknown(side_effects, "unknown callee property"); + true + }, + _ => false, + } + }, + } + }, + // matching property access like `obj.prop` when we don't know what the obj is. + // We can early return here + &mut JsValue::Member( + _, + box JsValue::Unknown { original_value: _, reason: _, has_side_effects }, + box ref mut prop, + ) => { + let side_effects = has_side_effects || prop.has_side_effects(); + value.make_unknown(side_effects, "unknown object"); + true + }, + _ => false, + } +} + +/// Replaces some builtin functions and values with their resulting values. In +/// contrast to early_replace_builtin this has all inner values already +/// processed. +pub fn replace_builtin(value:&mut JsValue) -> bool { + match value { + // matching property access like `obj.prop` + // Accessing a property on something can be handled in some cases + JsValue::Member(_, box ref mut obj, ref mut prop) => { + match obj { + // matching property access when obj is a bunch of alternatives + // like `(obj1 | obj2 | obj3).prop` + // We expand these to `obj1.prop | obj2.prop | obj3.prop` + JsValue::Alternatives(_, alts) => { + *value = JsValue::alternatives( + take(alts) + .into_iter() + .map(|alt| JsValue::member(Box::new(alt), prop.clone())) + .collect(), + ); + true + }, + // matching property access on an array like `[1,2,3].prop` or `[1,2,3][1]` + &mut JsValue::Array { ref mut items, mutable, .. } => { + fn items_to_alternatives( + items:&mut Vec, + prop:&mut JsValue, + ) -> JsValue { + items.push(JsValue::unknown( + JsValue::member( + Box::new(JsValue::array(Vec::new())), + Box::new(take(prop)), + ), + false, + "unknown array prototype methods or values", + )); + JsValue::alternatives(take(items)) + } + match &mut **prop { + // accessing a numeric property on an array like `[1,2,3][1]` + // We can replace this with the value at the index + JsValue::Constant(ConstantValue::Num(num @ ConstantNumber(_))) => { + if let Some(index) = num.as_u32_index() { + if index < items.len() { + *value = items.swap_remove(index); + if mutable { + value.add_unknown_mutations(true); + } + true + } else { + *value = JsValue::unknown( + JsValue::member(Box::new(take(obj)), Box::new(take(prop))), + false, + "invalid index", + ); + true + } + } else { + value.make_unknown(false, "non-num constant property on array"); + true + } + }, + // accessing a non-numeric property on an array like `[1,2,3].length` + // We don't know what happens here + JsValue::Constant(_) => { + value.make_unknown(false, "non-num constant property on array"); + true + }, + // accessing multiple alternative properties on an array like `[1,2,3][(1 | + // 2 | prop3)]` + JsValue::Alternatives(_, alts) => { + *value = JsValue::alternatives( + take(alts) + .into_iter() + .map(|alt| { + JsValue::member(Box::new(obj.clone()), Box::new(alt)) + }) + .collect(), + ); + true + }, + // otherwise we can say that this might gives an item of the array + // but we also add an unknown value to the alternatives for other properties + _ => { + *value = items_to_alternatives(items, prop); + true + }, + } + }, + // matching property access on an object like `{a: 1, b: 2}.a` + &mut JsValue::Object { ref mut parts, mutable, .. } => { + fn parts_to_alternatives( + parts:&mut Vec, + prop:&mut Box, + include_unknown:bool, + ) -> JsValue { + let mut values = Vec::new(); + for part in parts { + match part { + ObjectPart::KeyValue(_, value) => { + values.push(take(value)); + }, + ObjectPart::Spread(_) => { + values.push(JsValue::unknown( + JsValue::member( + Box::new(JsValue::object(vec![take(part)])), + prop.clone(), + ), + true, + "spreaded object", + )); + }, + } + } + if include_unknown { + values.push(JsValue::unknown( + JsValue::member( + Box::new(JsValue::object(Vec::new())), + Box::new(take(prop)), + ), + true, + "unknown object prototype methods or values", + )); + } + JsValue::alternatives(values) + } + + /// Convert a list of potential values into + /// JsValue::Alternatives Optionally add a + /// unknown value to the alternatives for object prototype + /// methods + fn potential_values_to_alternatives( + mut potential_values:Vec, + parts:&mut Vec, + prop:&mut Box, + include_unknown:bool, + ) -> JsValue { + // Note: potential_values are already in reverse order + let mut potential_values = take(parts) + .into_iter() + .enumerate() + .filter(|(i, _)| { + if potential_values.last() == Some(i) { + potential_values.pop(); + true + } else { + false + } + }) + .map(|(_, part)| part) + .collect(); + parts_to_alternatives(&mut potential_values, prop, include_unknown) + } + + match &mut **prop { + // matching constant string property access on an object like `{a: 1, b: + // 2}["a"]` + JsValue::Constant(ConstantValue::Str(_)) => { + let prop_str = prop.as_str().unwrap(); + let mut potential_values = Vec::new(); + for (i, part) in parts.iter_mut().enumerate().rev() { + match part { + ObjectPart::KeyValue(key, val) => { + if let Some(key) = key.as_str() { + if key == prop_str { + if potential_values.is_empty() { + *value = take(val); + } else { + potential_values.push(i); + *value = potential_values_to_alternatives( + potential_values, + parts, + prop, + false, + ); + } + if mutable { + value.add_unknown_mutations(true); + } + return true; + } + } else { + potential_values.push(i); + } + }, + ObjectPart::Spread(_) => { + value.make_unknown(true, "spread object"); + return true; + }, + } + } + if potential_values.is_empty() { + *value = JsValue::FreeVar(js_word!("undefined")); + } else { + *value = potential_values_to_alternatives( + potential_values, + parts, + prop, + true, + ); + } + if mutable { + value.add_unknown_mutations(true); + } + true + }, + // matching mutliple alternative properties on an object like `{a: 1, b: + // 2}[(a | b)]` + JsValue::Alternatives(_, alts) => { + *value = JsValue::alternatives( + take(alts) + .into_iter() + .map(|alt| { + JsValue::member(Box::new(obj.clone()), Box::new(alt)) + }) + .collect(), + ); + true + }, + _ => { + *value = parts_to_alternatives(parts, prop, true); + true + }, + } + }, + _ => false, + } + }, + // matching calls with this context like `obj.prop(arg1, arg2, ...)` + JsValue::MemberCall(_, box ref mut obj, box ref mut prop, ref mut args) => { + match obj { + // matching calls on an array like `[1,2,3].concat([4,5,6])` + JsValue::Array { items, mutable, .. } => { + // matching cases where the property is a const string + if let Some(str) = prop.as_str() { + match str { + // The Array.prototype.concat method + "concat" => { + if args.iter().all(|arg| { + matches!( + arg, + JsValue::Array { .. } + | JsValue::Constant(_) | JsValue::Url(_) + | JsValue::Concat(..) | JsValue::Add(..) + | JsValue::WellKnownObject(_) | JsValue::WellKnownFunction( + _ + ) | JsValue::Function(..) + ) + }) { + for arg in args { + match arg { + JsValue::Array { + items: inner, + mutable: inner_mutable, + .. + } => { + items.extend(take(inner)); + *mutable |= *inner_mutable; + }, + JsValue::Constant(_) + | JsValue::Url(_) + | JsValue::Concat(..) + | JsValue::Add(..) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) + | JsValue::Function(..) => { + items.push(take(arg)); + }, + _ => { + unreachable!(); + }, + } + } + obj.update_total_nodes(); + *value = take(obj); + return true; + } + }, + // The Array.prototype.map method + "map" => { + if let Some(func) = args.first() { + *value = JsValue::array( + take(items) + .into_iter() + .enumerate() + .map(|(i, item)| { + JsValue::call( + Box::new(func.clone()), + vec![ + item, + JsValue::Constant(ConstantValue::Num( + ConstantNumber(i as f64), + )), + ], + ) + }) + .collect(), + ); + return true; + } + }, + _ => {}, + } + } + }, + // matching calls on multiple alternative objects like `(obj1 | obj2).prop(arg1, + // arg2, ...)` + JsValue::Alternatives(_, alts) => { + *value = JsValue::alternatives( + take(alts) + .into_iter() + .map(|alt| { + JsValue::member_call( + Box::new(alt), + Box::new(prop.clone()), + args.clone(), + ) + }) + .collect(), + ); + return true; + }, + _ => {}, + } + // without special handling, we convert it into a normal call like + // `(obj.prop)(arg1, arg2, ...)` + *value = JsValue::call( + Box::new(JsValue::member(Box::new(take(obj)), Box::new(take(prop)))), + take(args), + ); + true + }, + // match calls when the callee are multiple alternative functions like `(func1 | + // func2)(arg1, arg2, ...)` + JsValue::Call(_, box JsValue::Alternatives(_, alts), ref mut args) => { + *value = JsValue::alternatives( + take(alts) + .into_iter() + .map(|alt| JsValue::call(Box::new(alt), args.clone())) + .collect(), + ); + true + }, + // match object literals + JsValue::Object { parts, mutable, .. } => { + // If the object contains any spread, we might be able to flatten that + if parts + .iter() + .any(|part| matches!(part, ObjectPart::Spread(JsValue::Object { .. }))) + { + let old_parts = take(parts); + for part in old_parts { + if let ObjectPart::Spread(JsValue::Object { + parts: inner_parts, + mutable: inner_mutable, + .. + }) = part + { + parts.extend(inner_parts); + *mutable |= inner_mutable; + } else { + parts.push(part); + } + } + value.update_total_nodes(); + true + } else { + false + } + }, + // match logical expressions like `a && b` or `a || b || c` or `a ?? b` + // Reduce logical expressions to their final value(s) + JsValue::Logical(_, op, ref mut parts) => { + let len = parts.len(); + for (i, part) in take(parts).into_iter().enumerate() { + // The last part is never skipped. + if i == len - 1 { + parts.push(part); + break; + } + // We might know at compile-time if a part is skipped or the final value. + let skip_part = match op { + LogicalOperator::And => part.is_truthy(), + LogicalOperator::Or => part.is_falsy(), + LogicalOperator::NullishCoalescing => part.is_nullish(), + }; + match skip_part { + Some(true) => { + // We known this part is skipped, so we can remove it. + continue; + }, + Some(false) => { + // We known this part is the final value, so we can remove the rest. + parts.push(part); + break; + }, + None => { + // We don't know if this part is skipped or the final value, so we keep it. + parts.push(part); + continue; + }, + } + } + // If we reduced the expression to a single value, we can replace it. + if parts.len() == 1 { + *value = parts.pop().unwrap(); + true + } else { + // If not, we know that it will be one of the remaining values. + *value = JsValue::alternatives(take(parts)); + true + } + }, + JsValue::Tenary(_, test, cons, alt) => { + if test.is_truthy() == Some(true) { + *value = take(cons); + true + } else if test.is_falsy() == Some(true) { + *value = take(alt); + true + } else { + false + } + }, + // match a binary operator like `a == b` + JsValue::Binary(..) => { + if let Some(v) = value.is_truthy() { + let v = if v { ConstantValue::True } else { ConstantValue::False }; + *value = JsValue::Constant(v); + true + } else { + false + } + }, + // match the not operator like `!a` + // Evaluate not when the inner value is truthy or falsy + JsValue::Not(_, ref inner) => { + match inner.is_truthy() { + Some(true) => { + *value = JsValue::Constant(ConstantValue::False); + true + }, + Some(false) => { + *value = JsValue::Constant(ConstantValue::True); + true + }, + None => false, + } + }, + + JsValue::Iterated(_, iterable) => { + if let JsValue::Array { items, .. } = &mut **iterable { + *value = JsValue::alternatives(take(items)); + true + } else { + false + } + }, + + _ => false, + } +} diff --git a/crates/turbopack-ecmascript/Source/analyzer/graph.rs b/crates/turbopack-ecmascript/Source/analyzer/graph.rs new file mode 100644 index 0000000000000..70ed73e03b5aa --- /dev/null +++ b/crates/turbopack-ecmascript/Source/analyzer/graph.rs @@ -0,0 +1,1771 @@ +use std::{ + collections::HashMap, + iter, + mem::{replace, take}, +}; + +use swc_core::{ + common::{GLOBALS, Mark, Span, Spanned, SyntaxContext, pass::AstNodePath}, + ecma::{ + ast::*, + atoms::js_word, + visit::{fields::*, *}, + }, +}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::source::Source; + +use super::{ConstantNumber, ConstantValue, ImportMap, JsValue, ObjectPart, WellKnownFunctionKind}; +use crate::{analyzer::is_unresolved, utils::unparen}; + +#[derive(Debug, Clone, Default)] +pub struct EffectsBlock { + pub effects:Vec, + /// The ast path to the block or expression. + pub ast_path:Vec, +} + +impl EffectsBlock { + pub fn is_empty(&self) -> bool { self.effects.is_empty() } +} + +#[derive(Debug, Clone)] +pub enum ConditionalKind { + /// The blocks of an `if` statement without an `else` block. + If { then:EffectsBlock }, + /// The blocks of an `if ... else` statement. + IfElse { then:EffectsBlock, r#else:EffectsBlock }, + /// The expressions on the right side of the `?:` operator. + Ternary { then:EffectsBlock, r#else:EffectsBlock }, + /// The expression on the right side of the `&&` operator. + And { expr:EffectsBlock }, + /// The expression on the right side of the `||` operator. + Or { expr:EffectsBlock }, + /// The expression on the right side of the `??` operator. + NullishCoalescing { expr:EffectsBlock }, +} + +impl ConditionalKind { + /// Normalizes all contained values. + pub fn normalize(&mut self) { + match self { + ConditionalKind::If { then, .. } => { + for effect in &mut then.effects { + effect.normalize(); + } + }, + ConditionalKind::IfElse { then, r#else, .. } + | ConditionalKind::Ternary { then, r#else, .. } => { + for effect in &mut then.effects { + effect.normalize(); + } + for effect in &mut r#else.effects { + effect.normalize(); + } + }, + ConditionalKind::And { expr, .. } + | ConditionalKind::Or { expr, .. } + | ConditionalKind::NullishCoalescing { expr, .. } => { + for effect in &mut expr.effects { + effect.normalize(); + } + }, + } + } +} + +#[derive(Debug, Clone)] +pub enum EffectArg { + Value(JsValue), + Closure(JsValue, EffectsBlock), + Spread, +} + +impl EffectArg { + /// Normalizes all contained values. + pub fn normalize(&mut self) { + match self { + EffectArg::Value(value) => value.normalize(), + EffectArg::Closure(value, effects) => { + value.normalize(); + for effect in &mut effects.effects { + effect.normalize(); + } + }, + EffectArg::Spread => {}, + } + } +} + +#[derive(Debug, Clone)] +pub enum Effect { + /// Some condition which affects which effects might be executed. If the + /// condition evaluates to some compile-time constant, we can use that + /// to determine which effects are executed and remove the others. + Conditional { + condition:JsValue, + kind:Box, + /// The ast path to the condition. + ast_path:Vec, + span:Span, + in_try:bool, + }, + /// A function call. + Call { + func:JsValue, + args:Vec, + ast_path:Vec, + span:Span, + in_try:bool, + }, + /// A function call of a property of an object. + MemberCall { + obj:JsValue, + prop:JsValue, + args:Vec, + ast_path:Vec, + span:Span, + in_try:bool, + }, + /// A property access. + Member { obj:JsValue, prop:JsValue, ast_path:Vec, span:Span, in_try:bool }, + /// A reference to an imported binding. + ImportedBinding { + esm_reference_index:usize, + export:Option, + ast_path:Vec, + span:Span, + in_try:bool, + }, + /// A reference to a free var access. + FreeVar { var:JsValue, ast_path:Vec, span:Span, in_try:bool }, + // TODO ImportMeta should be replaced with Member + /// A reference to `import.meta`. + ImportMeta { ast_path:Vec, span:Span, in_try:bool }, + /// A reference to `new URL(..., import.meta.url)`. + Url { input:JsValue, ast_path:Vec, span:Span, in_try:bool }, +} + +impl Effect { + /// Normalizes all contained values. + pub fn normalize(&mut self) { + match self { + Effect::Conditional { condition, kind, .. } => { + condition.normalize(); + kind.normalize(); + }, + Effect::Call { func, args, .. } => { + func.normalize(); + for arg in args.iter_mut() { + arg.normalize(); + } + }, + Effect::MemberCall { obj, prop, args, .. } => { + obj.normalize(); + prop.normalize(); + for arg in args.iter_mut() { + arg.normalize(); + } + }, + Effect::Member { obj, prop, .. } => { + obj.normalize(); + prop.normalize(); + }, + Effect::FreeVar { var, .. } => { + var.normalize(); + }, + Effect::ImportedBinding { .. } => {}, + Effect::ImportMeta { .. } => {}, + Effect::Url { input, .. } => { + input.normalize(); + }, + } + } +} + +#[derive(Debug)] +pub struct VarGraph { + pub values:HashMap, + + pub effects:Vec, +} + +impl VarGraph { + pub fn normalize(&mut self) { + for value in self.values.values_mut() { + value.normalize(); + } + for effect in self.effects.iter_mut() { + effect.normalize(); + } + } +} + +/// You should use same [Mark] for this function and +/// [swc_ecma_transforms_base::resolver::resolver_with_mark] +pub fn create_graph(m:&Program, eval_context:&EvalContext) -> VarGraph { + let mut graph = VarGraph { values:Default::default(), effects:Default::default() }; + + m.visit_with_path( + &mut Analyzer { + data:&mut graph, + eval_context, + effects:Default::default(), + var_decl_kind:Default::default(), + current_value:Default::default(), + cur_fn_return_values:Default::default(), + cur_fn_ident:Default::default(), + }, + &mut Default::default(), + ); + + graph.normalize(); + + graph +} + +pub struct EvalContext { + pub(crate) unresolved_mark:Mark, + pub(crate) top_level_mark:Mark, + pub(crate) imports:ImportMap, +} + +impl EvalContext { + pub fn new( + module:&Program, + unresolved_mark:Mark, + top_level_mark:Mark, + skip_namespace:bool, + source:Option>>, + ) -> Self { + Self { + unresolved_mark, + top_level_mark, + imports:ImportMap::analyze(module, skip_namespace, source), + } + } + + pub fn is_esm(&self) -> bool { self.imports.is_esm() } + + fn eval_prop_name(&self, prop:&PropName) -> JsValue { + match prop { + PropName::Ident(ident) => ident.sym.clone().into(), + PropName::Str(str) => str.value.clone().into(), + PropName::Num(num) => num.value.into(), + PropName::Computed(ComputedPropName { expr, .. }) => self.eval(expr), + PropName::BigInt(bigint) => (*bigint.value.clone()).into(), + } + } + + fn eval_tpl(&self, e:&Tpl, raw:bool) -> JsValue { + debug_assert!(e.quasis.len() == e.exprs.len() + 1); + + let mut values = vec![]; + + for idx in 0..(e.quasis.len() + e.exprs.len()) { + if idx % 2 == 0 { + let idx = idx / 2; + let e = &e.quasis[idx]; + + if raw { + values.push(JsValue::from(e.raw.clone())); + } else { + match &e.cooked { + Some(v) => { + values.push(JsValue::from(v.clone())); + }, + // This is actually unreachable + None => return JsValue::unknown_empty(true, ""), + } + } + } else { + let idx = idx / 2; + let e = &e.exprs[idx]; + + values.push(self.eval(e)); + } + } + + if values.len() == 1 { + return values.into_iter().next().unwrap(); + } + + JsValue::concat(values) + } + + fn eval_ident(&self, i:&Ident) -> JsValue { + let id = i.to_id(); + if let Some(imported) = self.imports.get_import(&id) { + return imported; + } + if is_unresolved(i, self.unresolved_mark) { + JsValue::FreeVar(i.sym.clone()) + } else { + JsValue::Variable(id) + } + } + + pub fn eval(&self, e:&Expr) -> JsValue { + debug_assert!(GLOBALS.is_set(), "Eval requires globals from its parsed result"); + match e { + Expr::Paren(e) => self.eval(&e.expr), + Expr::Lit(e) => JsValue::Constant(e.clone().into()), + Expr::Ident(i) => self.eval_ident(i), + + Expr::Unary(UnaryExpr { op: op!("!"), arg, .. }) => { + let arg = self.eval(arg); + + JsValue::logical_not(Box::new(arg)) + }, + + Expr::Unary(UnaryExpr { op: op!("typeof"), arg, .. }) => { + let arg = self.eval(arg); + + JsValue::type_of(Box::new(arg)) + }, + + Expr::Bin(BinExpr { op: op!(bin, "+"), left, right, .. }) => { + let l = self.eval(left); + let r = self.eval(right); + + match (l, r) { + (JsValue::Add(c, l), r) => { + JsValue::Add( + c + r.total_nodes(), + l.into_iter().chain(iter::once(r)).collect(), + ) + }, + (l, r) => JsValue::add(vec![l, r]), + } + }, + + Expr::Bin(BinExpr { op: op!("&&"), left, right, .. }) => { + JsValue::logical_and(vec![self.eval(left), self.eval(right)]) + }, + + Expr::Bin(BinExpr { op: op!("||"), left, right, .. }) => { + JsValue::logical_or(vec![self.eval(left), self.eval(right)]) + }, + + Expr::Bin(BinExpr { op: op!("??"), left, right, .. }) => { + JsValue::nullish_coalescing(vec![self.eval(left), self.eval(right)]) + }, + + Expr::Bin(BinExpr { op: op!("=="), left, right, .. }) => { + JsValue::equal(self.eval(left), self.eval(right)) + }, + + Expr::Bin(BinExpr { op: op!("!="), left, right, .. }) => { + JsValue::not_equal(self.eval(left), self.eval(right)) + }, + + Expr::Bin(BinExpr { op: op!("==="), left, right, .. }) => { + JsValue::strict_equal(self.eval(left), self.eval(right)) + }, + + Expr::Bin(BinExpr { op: op!("!=="), left, right, .. }) => { + JsValue::strict_not_equal(self.eval(left), self.eval(right)) + }, + + &Expr::Cond(CondExpr { box ref cons, box ref alt, box ref test, .. }) => { + let test = self.eval(test); + if let Some(truthy) = test.is_truthy() { + if truthy { self.eval(cons) } else { self.eval(alt) } + } else { + JsValue::tenary( + Box::new(test), + Box::new(self.eval(cons)), + Box::new(self.eval(alt)), + ) + } + }, + + Expr::Tpl(e) => self.eval_tpl(e, false), + + Expr::TaggedTpl(TaggedTpl { + tag: + box Expr::Member(MemberExpr { + obj: box Expr::Ident(tag_obj), + prop: MemberProp::Ident(tag_prop), + .. + }), + tpl, + .. + }) => { + if &*tag_obj.sym == "String" + && &*tag_prop.sym == "raw" + && is_unresolved(tag_obj, self.unresolved_mark) + { + self.eval_tpl(tpl, true) + } else { + JsValue::unknown_empty(true, "tagged template literal is not supported yet") + } + }, + + Expr::Fn(expr) => { + if let Some(ident) = &expr.ident { + JsValue::Variable(ident.to_id()) + } else { + JsValue::Variable(( + format!("*anonymous function {}*", expr.function.span.lo.0).into(), + SyntaxContext::empty(), + )) + } + }, + Expr::Arrow(expr) => { + JsValue::Variable(( + format!("*arrow function {}*", expr.span.lo.0).into(), + SyntaxContext::empty(), + )) + }, + + Expr::Await(AwaitExpr { arg, .. }) => self.eval(arg), + + Expr::New(..) => JsValue::unknown_empty(true, "unknown new expression"), + + Expr::Seq(e) => { + let mut seq = e.exprs.iter().map(|e| self.eval(e)).peekable(); + let mut side_effects = false; + let mut last = seq.next().unwrap(); + for e in seq { + side_effects |= last.has_side_effects(); + last = e; + } + if side_effects { + last.make_unknown(true, "sequence with side effects"); + } + last + }, + + Expr::Member(MemberExpr { obj, prop: MemberProp::Ident(prop), .. }) => { + let obj = self.eval(obj); + JsValue::member(Box::new(obj), Box::new(prop.sym.clone().into())) + }, + + Expr::Member(MemberExpr { obj, prop: MemberProp::Computed(computed), .. }) => { + let obj = self.eval(obj); + let prop = self.eval(&computed.expr); + JsValue::member(Box::new(obj), Box::new(prop)) + }, + + Expr::Call(CallExpr { callee: Callee::Expr(box callee), args, .. }) => { + // We currently do not handle spreads. + if args.iter().any(|arg| arg.spread.is_some()) { + return JsValue::unknown_empty( + true, + "spread in function calls is not supported", + ); + } + + let args = args.iter().map(|arg| self.eval(&arg.expr)).collect(); + if let Expr::Member(MemberExpr { obj, prop, .. }) = unparen(callee) { + let obj = Box::new(self.eval(obj)); + let prop = Box::new(match prop { + // TODO avoid clone + MemberProp::Ident(i) => i.sym.clone().into(), + MemberProp::PrivateName(_) => { + return JsValue::unknown_empty( + false, + "private names in function calls is not supported", + ); + }, + MemberProp::Computed(ComputedPropName { expr, .. }) => self.eval(expr), + }); + JsValue::member_call(obj, prop, args) + } else { + let callee = Box::new(self.eval(callee)); + + JsValue::call(callee, args) + } + }, + + Expr::Call(CallExpr { callee: Callee::Super(_), args, .. }) => { + // We currently do not handle spreads. + if args.iter().any(|arg| arg.spread.is_some()) { + return JsValue::unknown_empty( + true, + "spread in function calls is not supported", + ); + } + + let args = args.iter().map(|arg| self.eval(&arg.expr)).collect(); + + JsValue::super_call(args) + }, + + Expr::Call(CallExpr { callee: Callee::Import(_), args, .. }) => { + // We currently do not handle spreads. + if args.iter().any(|arg| arg.spread.is_some()) { + return JsValue::unknown_empty(true, "spread in import() is not supported"); + } + let args = args.iter().map(|arg| self.eval(&arg.expr)).collect(); + + let callee = Box::new(JsValue::FreeVar(js_word!("import"))); + + JsValue::call(callee, args) + }, + + Expr::Array(arr) => { + if arr.elems.iter().flatten().any(|v| v.spread.is_some()) { + return JsValue::unknown_empty(true, "spread is not supported"); + } + + let arr = arr + .elems + .iter() + .map(|e| { + match e { + Some(e) => self.eval(&e.expr), + _ => JsValue::FreeVar(js_word!("undefined")), + } + }) + .collect(); + JsValue::array(arr) + }, + + Expr::Object(obj) => { + return JsValue::object( + obj.props + .iter() + .map(|prop| { + match prop { + PropOrSpread::Spread(SpreadElement { expr, .. }) => { + ObjectPart::Spread(self.eval(expr)) + }, + PropOrSpread::Prop(box Prop::KeyValue(KeyValueProp { + key, + box value, + })) => { + ObjectPart::KeyValue(self.eval_prop_name(key), self.eval(value)) + }, + PropOrSpread::Prop(box Prop::Shorthand(ident)) => { + ObjectPart::KeyValue( + ident.sym.clone().into(), + self.eval(&Expr::Ident(ident.clone())), + ) + }, + _ => { + ObjectPart::Spread(JsValue::unknown_empty( + true, + "unsupported object part", + )) + }, + } + }) + .collect(), + ); + }, + + _ => JsValue::unknown_empty(true, "unsupported expression"), + } + } +} + +struct Analyzer<'a> { + data:&'a mut VarGraph, + + effects:Vec, + + eval_context:&'a EvalContext, + + var_decl_kind:Option, + + /// Used for patterns + current_value:Option, + + /// Return values of the current function. + /// + /// This is configured to [Some] by function handlers and filled by the + /// return statement handler. + cur_fn_return_values:Option>, + + cur_fn_ident:u32, +} + +pub fn as_parent_path(ast_path:&AstNodePath>) -> Vec { + ast_path.iter().map(|n| n.kind()).collect() +} + +pub fn as_parent_path_with( + ast_path:&AstNodePath>, + additional:AstParentKind, +) -> Vec { + ast_path.iter().map(|n| n.kind()).chain([additional]).collect() +} + +pub fn is_in_try(ast_path:&AstNodePath>) -> bool { + ast_path + .iter() + .rev() + .find_map(|ast_ref| { + match ast_ref.kind() { + AstParentKind::ArrowExpr(ArrowExprField::Body) => Some(false), + AstParentKind::Function(FunctionField::Body) => Some(false), + AstParentKind::TryStmt(TryStmtField::Block) => Some(true), + _ => None, + } + }) + .unwrap_or(false) +} + +impl Analyzer<'_> { + fn add_value(&mut self, id:Id, value:JsValue) { + if let Some(prev) = self.data.values.get_mut(&id) { + prev.add_alt(value); + } else { + self.data.values.insert(id, value); + } + // TODO(kdy1): We may need to report an error for this. + // Variables declared with `var` are hoisted, but using undefined as its + // value does not seem like a good idea. + } + + fn add_value_from_expr(&mut self, id:Id, value:&Expr) { + let value = self.eval_context.eval(value); + + self.add_value(id, value); + } + + fn add_effect(&mut self, effect:Effect) { self.effects.push(effect); } + + fn check_iife<'ast:'r, 'r>( + &mut self, + n:&'ast CallExpr, + ast_path:&mut AstNodePath>, + ) -> bool { + fn unparen<'ast:'r, 'r, T>( + expr:&'ast Expr, + ast_path:&mut AstNodePath>, + f:impl FnOnce(&'ast Expr, &mut AstNodePath>) -> T, + ) -> T { + if let Some(inner_expr) = expr.as_paren() { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Expr(expr, ExprField::Paren)); + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::ParenExpr(inner_expr, ParenExprField::Expr)); + unparen(&inner_expr.expr, &mut ast_path, f) + } else { + f(expr, ast_path) + } + } + + if n.args.iter().any(|arg| arg.spread.is_some()) { + return false; + } + + let Some(expr) = n.callee.as_expr() else { + return false; + }; + + let fn_expr = { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::CallExpr(n, CallExprField::Callee)); + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Callee(&n.callee, CalleeField::Expr)); + unparen(expr, &mut ast_path, |expr, ast_path| { + match expr { + Expr::Fn(fn_expr @ FnExpr { function, ident }) => { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Expr(expr, ExprField::Fn)); + { + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::FnExpr(fn_expr, FnExprField::Ident)); + self.visit_opt_ident(ident.as_ref(), &mut ast_path); + } + + { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::FnExpr( + fn_expr, + FnExprField::Function, + )); + self.handle_iife_function(function, &mut ast_path, &n.args); + } + + true + }, + + Expr::Arrow(arrow_expr) => { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Expr(expr, ExprField::Arrow)); + let args = &n.args; + self.handle_iife_arrow(arrow_expr, args, &mut ast_path); + true + }, + _ => false, + } + }) + }; + + if !fn_expr { + return false; + } + + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::CallExpr(n, CallExprField::Args(usize::MAX))); + + self.visit_expr_or_spreads(&n.args, &mut ast_path); + + true + } + + fn handle_iife_arrow<'ast:'r, 'r>( + &mut self, + arrow_expr:&'ast ArrowExpr, + args:&[ExprOrSpread], + ast_path:&mut AstNodePath>, + ) { + let ArrowExpr { + params, + body, + is_async: _, + is_generator: _, + return_type, + span: _, + type_params, + } = arrow_expr; + let mut iter = args.iter(); + for (i, param) in params.iter().enumerate() { + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::ArrowExpr(arrow_expr, ArrowExprField::Params(i))); + if let Some(arg) = iter.next() { + self.current_value = Some(self.eval_context.eval(&arg.expr)); + self.visit_pat(param, &mut ast_path); + self.current_value = None; + } else { + self.visit_pat(param, &mut ast_path); + } + } + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::ArrowExpr(arrow_expr, ArrowExprField::Body)); + self.visit_block_stmt_or_expr(body, &mut ast_path); + } + + { + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::ArrowExpr(arrow_expr, ArrowExprField::ReturnType)); + self.visit_opt_ts_type_ann(return_type.as_ref(), &mut ast_path); + } + + { + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::ArrowExpr(arrow_expr, ArrowExprField::TypeParams)); + self.visit_opt_ts_type_param_decl(type_params.as_ref(), &mut ast_path); + } + } + + fn handle_iife_function<'ast:'r, 'r>( + &mut self, + function:&'ast Function, + ast_path:&mut AstNodePath>, + args:&[ExprOrSpread], + ) { + let mut iter = args.iter(); + let Function { + body, + decorators, + is_async: _, + is_generator: _, + params, + return_type, + span: _, + type_params, + } = function; + for (i, param) in params.iter().enumerate() { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Function(function, FunctionField::Params(i))); + if let Some(arg) = iter.next() { + self.current_value = Some(self.eval_context.eval(&arg.expr)); + self.visit_param(param, &mut ast_path); + self.current_value = None; + } else { + self.visit_param(param, &mut ast_path); + } + } + + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Function(function, FunctionField::Body)); + + self.visit_opt_block_stmt(body.as_ref(), &mut ast_path); + } + + { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::Function( + function, + FunctionField::Decorators(usize::MAX), + )); + + self.visit_decorators(decorators, &mut ast_path); + } + + { + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::Function(function, FunctionField::ReturnType)); + + self.visit_opt_ts_type_ann(return_type.as_ref(), &mut ast_path); + } + + { + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::Function(function, FunctionField::TypeParams)); + + self.visit_opt_ts_type_param_decl(type_params.as_ref(), &mut ast_path); + } + } + + fn check_call_expr_for_effects<'ast:'r, 'r>( + &mut self, + n:&'ast CallExpr, + args:Vec, + ast_path:&AstNodePath>, + ) { + match &n.callee { + Callee::Import(_) => { + self.add_effect(Effect::Call { + func:JsValue::FreeVar(js_word!("import")), + args, + ast_path:as_parent_path(ast_path), + span:n.span(), + in_try:is_in_try(ast_path), + }); + }, + Callee::Expr(box expr) => { + if let Expr::Member(MemberExpr { obj, prop, .. }) = unparen(expr) { + let obj_value = self.eval_context.eval(obj); + let prop_value = match prop { + // TODO avoid clone + MemberProp::Ident(i) => i.sym.clone().into(), + MemberProp::PrivateName(_) => { + return; + }, + MemberProp::Computed(ComputedPropName { expr, .. }) => { + self.eval_context.eval(expr) + }, + }; + self.add_effect(Effect::MemberCall { + obj:obj_value, + prop:prop_value, + args, + ast_path:as_parent_path(ast_path), + span:n.span(), + in_try:is_in_try(ast_path), + }); + } else { + let fn_value = self.eval_context.eval(expr); + self.add_effect(Effect::Call { + func:fn_value, + args, + ast_path:as_parent_path(ast_path), + span:n.span(), + in_try:is_in_try(ast_path), + }); + } + }, + Callee::Super(_) => { + self.add_effect(Effect::Call { + func:self.eval_context.eval(&Expr::Call(n.clone())), + args, + ast_path:as_parent_path(ast_path), + span:n.span(), + in_try:is_in_try(ast_path), + }) + }, + } + } + + fn check_member_expr_for_effects<'ast:'r, 'r>( + &mut self, + member_expr:&'ast MemberExpr, + ast_path:&AstNodePath>, + ) { + let obj_value = self.eval_context.eval(&member_expr.obj); + let prop_value = match &member_expr.prop { + // TODO avoid clone + MemberProp::Ident(i) => i.sym.clone().into(), + MemberProp::PrivateName(_) => { + return; + }, + MemberProp::Computed(ComputedPropName { expr, .. }) => self.eval_context.eval(expr), + }; + self.add_effect(Effect::Member { + obj:obj_value, + prop:prop_value, + ast_path:as_parent_path(ast_path), + span:member_expr.span(), + in_try:is_in_try(ast_path), + }); + } + + fn take_return_values(&mut self) -> Box { + let values = self.cur_fn_return_values.take().unwrap(); + + Box::new(match values.len() { + 0 => JsValue::FreeVar(js_word!("undefined")), + 1 => values.into_iter().next().unwrap(), + _ => JsValue::alternatives(values), + }) + } +} + +impl VisitAstPath for Analyzer<'_> { + fn visit_assign_expr<'ast:'r, 'r>( + &mut self, + n:&'ast AssignExpr, + ast_path:&mut AstNodePath>, + ) { + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::AssignExpr(n, AssignExprField::Left)); + + match n.op { + AssignOp::Assign => { + self.current_value = Some(self.eval_context.eval(&n.right)); + n.left.visit_children_with_path(self, &mut ast_path); + self.current_value = None; + }, + + _ => { + if let Some(key) = n.left.as_ident() { + let value = match n.op { + AssignOp::AndAssign | AssignOp::OrAssign | AssignOp::NullishAssign => { + let right = self.eval_context.eval(&n.right); + // We can handle the right value as alternative to the existing + // value + Some(right) + }, + AssignOp::AddAssign => { + let left = self.eval_context.eval(&Expr::Ident(key.clone())); + let right = self.eval_context.eval(&n.right); + Some(JsValue::add(vec![left, right])) + }, + _ => Some(JsValue::unknown_empty(true, "unsupported assign operation")), + }; + if let Some(value) = value { + self.add_value(key.to_id(), value); + } + } + if n.left.as_ident().is_none() { + n.left.visit_children_with_path(self, &mut ast_path); + } + }, + } + } + + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::AssignExpr(n, AssignExprField::Right)); + self.visit_expr(&n.right, &mut ast_path); + } + } + + fn visit_update_expr<'ast:'r, 'r>( + &mut self, + n:&'ast UpdateExpr, + ast_path:&mut AstNodePath>, + ) { + if let Some(key) = n.arg.as_ident() { + self.add_value( + key.to_id(), + JsValue::unknown_empty(true, "updated with update expression"), + ); + } + + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::UpdateExpr(n, UpdateExprField::Arg)); + self.visit_expr(&n.arg, &mut ast_path); + } + + fn visit_call_expr<'ast:'r, 'r>( + &mut self, + n:&'ast CallExpr, + ast_path:&mut AstNodePath>, + ) { + // We handle `define(function (require) {})` here. + if let Callee::Expr(callee) = &n.callee { + if n.args.len() == 1 { + if let Some(require_var_id) = extract_var_from_umd_factory(callee, &n.args) { + self.add_value( + require_var_id, + JsValue::WellKnownFunction(WellKnownFunctionKind::Require), + ); + } + } + } + + // special behavior of IIFEs + if !self.check_iife(n, ast_path) { + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::CallExpr(n, CallExprField::Callee)); + n.callee.visit_with_path(self, &mut ast_path); + } + let args = n + .args + .iter() + .enumerate() + .map(|(i, arg)| { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::CallExpr(n, CallExprField::Args(i))); + if arg.spread.is_none() { + let value = self.eval_context.eval(&arg.expr); + + let block_path = match &*arg.expr { + Expr::Fn(FnExpr { .. }) => { + let mut path = as_parent_path(&ast_path); + path.push(AstParentKind::ExprOrSpread(ExprOrSpreadField::Expr)); + path.push(AstParentKind::Expr(ExprField::Fn)); + path.push(AstParentKind::FnExpr(FnExprField::Function)); + path.push(AstParentKind::Function(FunctionField::Body)); + Some(path) + }, + Expr::Arrow(ArrowExpr { + body: box BlockStmtOrExpr::BlockStmt(_), + .. + }) => { + let mut path = as_parent_path(&ast_path); + path.push(AstParentKind::ExprOrSpread(ExprOrSpreadField::Expr)); + path.push(AstParentKind::Expr(ExprField::Arrow)); + path.push(AstParentKind::ArrowExpr(ArrowExprField::Body)); + path.push(AstParentKind::BlockStmtOrExpr( + BlockStmtOrExprField::BlockStmt, + )); + Some(path) + }, + Expr::Arrow(ArrowExpr { + body: box BlockStmtOrExpr::Expr(_), .. + }) => { + let mut path = as_parent_path(&ast_path); + path.push(AstParentKind::ExprOrSpread(ExprOrSpreadField::Expr)); + path.push(AstParentKind::Expr(ExprField::Arrow)); + path.push(AstParentKind::ArrowExpr(ArrowExprField::Body)); + path.push(AstParentKind::BlockStmtOrExpr( + BlockStmtOrExprField::Expr, + )); + Some(path) + }, + _ => None, + }; + if let Some(path) = block_path { + let old_effects = take(&mut self.effects); + arg.visit_with_path(self, &mut ast_path); + let effects = replace(&mut self.effects, old_effects); + EffectArg::Closure(value, EffectsBlock { effects, ast_path:path }) + } else { + arg.visit_with_path(self, &mut ast_path); + EffectArg::Value(value) + } + } else { + arg.visit_with_path(self, &mut ast_path); + EffectArg::Spread + } + }) + .collect(); + self.check_call_expr_for_effects(n, args, ast_path); + } + } + + fn visit_new_expr<'ast:'r, 'r>( + &mut self, + new_expr:&'ast NewExpr, + ast_path:&mut AstNodePath>, + ) { + // new URL("path", import.meta.url) + if let box Expr::Ident(ref callee) = &new_expr.callee { + if &*callee.sym == "URL" && is_unresolved(callee, self.eval_context.unresolved_mark) { + if let Some(args) = &new_expr.args { + if args.len() == 2 { + if let Expr::Member(MemberExpr { + obj: + box Expr::MetaProp(MetaPropExpr { + kind: MetaPropKind::ImportMeta, .. + }), + prop: MemberProp::Ident(prop), + .. + }) = &*args[1].expr + { + if &*prop.sym == "url" { + self.add_effect(Effect::Url { + input:self.eval_context.eval(&args[0].expr), + ast_path:as_parent_path(ast_path), + span:new_expr.span(), + in_try:is_in_try(ast_path), + }); + } + } + } + } + } + } + new_expr.visit_children_with_path(self, ast_path); + } + + fn visit_member_expr<'ast:'r, 'r>( + &mut self, + member_expr:&'ast MemberExpr, + ast_path:&mut AstNodePath>, + ) { + self.check_member_expr_for_effects(member_expr, ast_path); + member_expr.visit_children_with_path(self, ast_path); + } + + fn visit_expr<'ast:'r, 'r>( + &mut self, + n:&'ast Expr, + ast_path:&mut AstNodePath>, + ) { + let old = self.var_decl_kind; + self.var_decl_kind = None; + n.visit_children_with_path(self, ast_path); + self.var_decl_kind = old; + } + + fn visit_params<'ast:'r, 'r>( + &mut self, + n:&'ast [Param], + ast_path:&mut AstNodePath>, + ) { + let value = self.current_value.take(); + for (index, p) in n.iter().enumerate() { + self.current_value = Some(JsValue::Argument(self.cur_fn_ident, index)); + let mut ast_path = ast_path.with_index_guard(index); + p.visit_with_path(self, &mut ast_path); + } + self.current_value = value; + } + + fn visit_param<'ast:'r, 'r>( + &mut self, + n:&'ast Param, + ast_path:&mut AstNodePath>, + ) { + let old = self.var_decl_kind; + let Param { decorators, pat, span: _ } = n; + self.var_decl_kind = None; + let value = self.current_value.take(); + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Param(n, ParamField::Decorators(usize::MAX))); + self.visit_decorators(decorators, &mut ast_path); + } + self.current_value = value; + { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::Param(n, ParamField::Pat)); + self.visit_pat(pat, &mut ast_path); + } + self.current_value = None; + self.var_decl_kind = old; + } + + fn visit_fn_decl<'ast:'r, 'r>( + &mut self, + decl:&'ast FnDecl, + ast_path:&mut AstNodePath>, + ) { + let old = replace( + &mut self.cur_fn_return_values, + Some(get_fn_init_return_vals(decl.function.body.as_ref())), + ); + let old_ident = self.cur_fn_ident; + self.cur_fn_ident = decl.function.span.lo.0; + decl.visit_children_with_path(self, ast_path); + let return_value = self.take_return_values(); + + self.add_value(decl.ident.to_id(), JsValue::function(self.cur_fn_ident, return_value)); + + self.cur_fn_ident = old_ident; + self.cur_fn_return_values = old; + } + + fn visit_fn_expr<'ast:'r, 'r>( + &mut self, + expr:&'ast FnExpr, + ast_path:&mut AstNodePath>, + ) { + let old = replace( + &mut self.cur_fn_return_values, + Some(get_fn_init_return_vals(expr.function.body.as_ref())), + ); + let old_ident = self.cur_fn_ident; + self.cur_fn_ident = expr.function.span.lo.0; + expr.visit_children_with_path(self, ast_path); + let return_value = self.take_return_values(); + + if let Some(ident) = &expr.ident { + self.add_value(ident.to_id(), JsValue::function(self.cur_fn_ident, return_value)); + } else { + self.add_value( + ( + format!("*anonymous function {}*", expr.function.span.lo.0).into(), + SyntaxContext::empty(), + ), + JsValue::function(self.cur_fn_ident, return_value), + ); + } + + self.cur_fn_ident = old_ident; + self.cur_fn_return_values = old; + } + + fn visit_arrow_expr<'ast:'r, 'r>( + &mut self, + expr:&'ast ArrowExpr, + ast_path:&mut AstNodePath>, + ) { + let old_return_values = replace( + &mut self.cur_fn_return_values, + expr.body.as_block_stmt().map(|block| get_fn_init_return_vals(Some(block))), + ); + let old_ident = self.cur_fn_ident; + self.cur_fn_ident = expr.span.lo.0; + + let value = self.current_value.take(); + for (index, p) in expr.params.iter().enumerate() { + self.current_value = Some(JsValue::Argument(self.cur_fn_ident, index)); + let mut ast_path = ast_path + .with_guard(AstParentNodeRef::ArrowExpr(expr, ArrowExprField::Params(index))); + p.visit_with_path(self, &mut ast_path); + } + self.current_value = value; + + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::ArrowExpr(expr, ArrowExprField::Body)); + expr.body.visit_with_path(self, &mut ast_path); + } + + let return_value = match &*expr.body { + BlockStmtOrExpr::BlockStmt(_) => self.take_return_values(), + BlockStmtOrExpr::Expr(inner_expr) => Box::new(self.eval_context.eval(inner_expr)), + }; + + self.add_value( + (format!("*arrow function {}*", expr.span.lo.0).into(), SyntaxContext::empty()), + JsValue::function(self.cur_fn_ident, return_value), + ); + + self.cur_fn_ident = old_ident; + self.cur_fn_return_values = old_return_values; + } + + fn visit_class_decl<'ast:'r, 'r>( + &mut self, + decl:&'ast ClassDecl, + ast_path:&mut AstNodePath>, + ) { + self.add_value_from_expr( + decl.ident.to_id(), + // TODO avoid clone + &Expr::Class(ClassExpr { ident:Some(decl.ident.clone()), class:decl.class.clone() }), + ); + decl.visit_children_with_path(self, ast_path); + } + + fn visit_var_decl<'ast:'r, 'r>( + &mut self, + n:&'ast VarDecl, + ast_path:&mut AstNodePath>, + ) { + let old = self.var_decl_kind; + self.var_decl_kind = Some(n.kind); + n.visit_children_with_path(self, ast_path); + self.var_decl_kind = old; + } + + fn visit_var_declarator<'ast:'r, 'r>( + &mut self, + n:&'ast VarDeclarator, + ast_path:&mut AstNodePath>, + ) { + if self.var_decl_kind.is_some() { + if let Some(init) = &n.init { + self.current_value = Some(self.eval_context.eval(init)); + } + } + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::VarDeclarator(n, VarDeclaratorField::Name)); + + self.visit_pat(&n.name, &mut ast_path); + } + self.current_value = None; + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::VarDeclarator(n, VarDeclaratorField::Init)); + + self.visit_opt_expr(n.init.as_ref(), &mut ast_path); + } + } + + fn visit_for_of_stmt<'ast:'r, 'r>( + &mut self, + n:&'ast ForOfStmt, + ast_path:&mut swc_core::ecma::visit::AstNodePath<'r>, + ) { + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::ForOfStmt(n, ForOfStmtField::Right)); + self.current_value = None; + self.visit_expr(&n.right, &mut ast_path); + } + + let array = self.eval_context.eval(&n.right); + + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::ForOfStmt(n, ForOfStmtField::Left)); + self.current_value = Some(JsValue::iterated(array)); + self.visit_for_head(&n.left, &mut ast_path); + } + + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::ForOfStmt(n, ForOfStmtField::Body)); + + self.visit_stmt(&n.body, &mut ast_path); + } + + fn visit_simple_assign_target<'ast:'r, 'r>( + &mut self, + n:&'ast SimpleAssignTarget, + ast_path:&mut swc_core::ecma::visit::AstNodePath<'r>, + ) { + let value = self.current_value.take(); + if let SimpleAssignTarget::Ident(i) = n { + n.visit_children_with_path(self, ast_path); + + self.add_value( + i.to_id(), + value.unwrap_or_else(|| { + JsValue::unknown(JsValue::Variable(i.to_id()), false, "pattern without value") + }), + ); + return; + } + + n.visit_children_with_path(self, ast_path); + } + + fn visit_pat<'ast:'r, 'r>( + &mut self, + pat:&'ast Pat, + ast_path:&mut AstNodePath>, + ) { + let value = self.current_value.take(); + match pat { + Pat::Ident(i) => { + self.add_value( + i.to_id(), + value.unwrap_or_else(|| { + JsValue::unknown( + JsValue::Variable(i.to_id()), + false, + "pattern without value", + ) + }), + ); + }, + + Pat::Array(arr) => { + match &value { + Some(JsValue::Array { items, .. }) => { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Pat(pat, PatField::Array)); + for (idx, elem) in arr.elems.iter().enumerate() { + self.current_value = items.get(idx).cloned(); + let mut ast_path = ast_path.with_guard(AstParentNodeRef::ArrayPat( + arr, + ArrayPatField::Elems(idx), + )); + elem.visit_with_path(self, &mut ast_path); + } + + // We should not call visit_children_with + return; + }, + + Some(value) => { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::Pat(pat, PatField::Array)); + for (idx, elem) in arr.elems.iter().enumerate() { + self.current_value = Some(JsValue::member( + Box::new(value.clone()), + Box::new(JsValue::Constant(ConstantValue::Num(ConstantNumber( + idx as f64, + )))), + )); + let mut ast_path = ast_path.with_guard(AstParentNodeRef::ArrayPat( + arr, + ArrayPatField::Elems(idx), + )); + elem.visit_with_path(self, &mut ast_path); + } + // We should not call visit_children_with + return; + }, + + None => {}, + } + }, + + Pat::Object(obj) => { + let value = + value.unwrap_or_else(|| JsValue::unknown_empty(false, "pattern without value")); + + self.visit_pat_with_value(pat, obj, value, ast_path); + + // We should not call visit_children_with + return; + }, + + _ => {}, + } + pat.visit_children_with_path(self, ast_path); + } + + fn visit_return_stmt<'ast:'r, 'r>( + &mut self, + stmt:&'ast ReturnStmt, + ast_path:&mut AstNodePath>, + ) { + stmt.visit_children_with_path(self, ast_path); + + if let Some(values) = &mut self.cur_fn_return_values { + let return_value = stmt + .arg + .as_deref() + .map(|e| self.eval_context.eval(e)) + .unwrap_or(JsValue::FreeVar(js_word!("undefined"))); + + values.push(return_value); + } + } + + fn visit_ident<'ast:'r, 'r>( + &mut self, + ident:&'ast Ident, + ast_path:&mut AstNodePath>, + ) { + if !(matches!( + ast_path.last(), + Some(AstParentNodeRef::Expr(_, ExprField::Ident)) + | Some(AstParentNodeRef::Prop(_, PropField::Shorthand)) + ) || matches!( + ast_path.get(ast_path.len() - 2), + Some(AstParentNodeRef::SimpleAssignTarget(_, SimpleAssignTargetField::Ident,)) + )) { + return; + } + + if let Some((esm_reference_index, export)) = + self.eval_context.imports.get_binding(&ident.to_id()) + { + self.add_effect(Effect::ImportedBinding { + esm_reference_index, + export, + ast_path:as_parent_path(ast_path), + span:ident.span(), + in_try:is_in_try(ast_path), + }) + } else if is_unresolved(ident, self.eval_context.unresolved_mark) { + self.add_effect(Effect::FreeVar { + var:JsValue::FreeVar(ident.sym.clone()), + ast_path:as_parent_path(ast_path), + span:ident.span(), + in_try:is_in_try(ast_path), + }) + } + } + + fn visit_meta_prop_expr<'ast:'r, 'r>( + &mut self, + expr:&'ast MetaPropExpr, + ast_path:&mut AstNodePath>, + ) { + if expr.kind == MetaPropKind::ImportMeta { + // MetaPropExpr also covers `new.target`. Only consider `import.meta` + // an effect. + self.add_effect(Effect::ImportMeta { + span:expr.span, + ast_path:as_parent_path(ast_path), + in_try:is_in_try(ast_path), + }) + } + } + + fn visit_program<'ast:'r, 'r>( + &mut self, + program:&'ast Program, + ast_path:&mut AstNodePath>, + ) { + self.effects = take(&mut self.data.effects); + program.visit_children_with_path(self, ast_path); + self.data.effects = take(&mut self.effects); + } + + fn visit_cond_expr<'ast:'r, 'r>( + &mut self, + expr:&'ast CondExpr, + ast_path:&mut AstNodePath>, + ) { + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::CondExpr(expr, CondExprField::Test)); + expr.test.visit_with_path(self, &mut ast_path); + } + + let prev_effects = take(&mut self.effects); + let then = { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::CondExpr(expr, CondExprField::Cons)); + expr.cons.visit_with_path(self, &mut ast_path); + EffectsBlock { effects:take(&mut self.effects), ast_path:as_parent_path(&ast_path) } + }; + let r#else = { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::CondExpr(expr, CondExprField::Alt)); + expr.alt.visit_with_path(self, &mut ast_path); + EffectsBlock { effects:take(&mut self.effects), ast_path:as_parent_path(&ast_path) } + }; + self.effects = prev_effects; + + self.add_conditional_effect( + &expr.test, + ast_path, + AstParentKind::CondExpr(CondExprField::Test), + expr.span(), + ConditionalKind::Ternary { then, r#else }, + ); + } + + fn visit_if_stmt<'ast:'r, 'r>( + &mut self, + stmt:&'ast IfStmt, + ast_path:&mut AstNodePath>, + ) { + { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::IfStmt(stmt, IfStmtField::Test)); + stmt.test.visit_with_path(self, &mut ast_path); + } + let prev_effects = take(&mut self.effects); + let then = { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::IfStmt(stmt, IfStmtField::Cons)); + stmt.cons.visit_with_path(self, &mut ast_path); + EffectsBlock { effects:take(&mut self.effects), ast_path:as_parent_path(&ast_path) } + }; + let r#else = stmt + .alt + .as_ref() + .map(|alt| { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::IfStmt(stmt, IfStmtField::Alt)); + alt.visit_with_path(self, &mut ast_path); + EffectsBlock { effects:take(&mut self.effects), ast_path:as_parent_path(&ast_path) } + }) + .unwrap_or_default(); + self.effects = prev_effects; + match (!then.is_empty(), !r#else.is_empty()) { + (true, false) => { + self.add_conditional_effect( + &stmt.test, + ast_path, + AstParentKind::IfStmt(IfStmtField::Test), + stmt.span(), + ConditionalKind::If { then }, + ); + }, + (_, true) => { + self.add_conditional_effect( + &stmt.test, + ast_path, + AstParentKind::IfStmt(IfStmtField::Test), + stmt.span(), + ConditionalKind::IfElse { then, r#else }, + ); + }, + (false, false) => { + // no effects, can be ignored + }, + } + } +} + +impl<'a> Analyzer<'a> { + fn add_conditional_effect( + &mut self, + test:&Expr, + ast_path:&AstNodePath>, + ast_kind:AstParentKind, + span:Span, + mut cond_kind:ConditionalKind, + ) { + let condition = self.eval_context.eval(test); + if condition.is_unknown() { + match &mut cond_kind { + ConditionalKind::If { then } => { + self.effects.append(&mut then.effects); + }, + ConditionalKind::IfElse { then, r#else } + | ConditionalKind::Ternary { then, r#else } => { + self.effects.append(&mut then.effects); + self.effects.append(&mut r#else.effects); + }, + ConditionalKind::And { expr } + | ConditionalKind::Or { expr } + | ConditionalKind::NullishCoalescing { expr } => { + self.effects.append(&mut expr.effects); + }, + } + } else { + self.add_effect(Effect::Conditional { + condition, + kind:Box::new(cond_kind), + ast_path:as_parent_path_with(ast_path, ast_kind), + span, + in_try:is_in_try(ast_path), + }); + } + } + + fn visit_pat_with_value<'ast:'r, 'r>( + &mut self, + pat:&'ast Pat, + obj:&'ast ObjectPat, + current_value:JsValue, + ast_path:&mut AstNodePath>, + ) { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::Pat(pat, PatField::Object)); + for (i, prop) in obj.props.iter().enumerate() { + let mut ast_path = + ast_path.with_guard(AstParentNodeRef::ObjectPat(obj, ObjectPatField::Props(i))); + match prop { + ObjectPatProp::KeyValue(kv) => { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::ObjectPatProp( + prop, + ObjectPatPropField::KeyValue, + )); + let KeyValuePatProp { key, value } = kv; + let key_value = self.eval_context.eval_prop_name(key); + { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::KeyValuePatProp( + kv, + KeyValuePatPropField::Key, + )); + key.visit_with_path(self, &mut ast_path); + } + self.current_value = + Some(JsValue::member(Box::new(current_value.clone()), Box::new(key_value))); + { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::KeyValuePatProp( + kv, + KeyValuePatPropField::Value, + )); + value.visit_with_path(self, &mut ast_path); + } + }, + ObjectPatProp::Assign(assign) => { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::ObjectPatProp( + prop, + ObjectPatPropField::Assign, + )); + let AssignPatProp { key, value, .. } = assign; + let key_value = key.sym.clone().into(); + { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::AssignPatProp( + assign, + AssignPatPropField::Key, + )); + key.visit_with_path(self, &mut ast_path); + } + self.add_value( + key.to_id(), + if let Some(box value) = value { + let value = self.eval_context.eval(value); + JsValue::alternatives(vec![ + JsValue::member( + Box::new(current_value.clone()), + Box::new(key_value), + ), + value, + ]) + } else { + JsValue::member(Box::new(current_value.clone()), Box::new(key_value)) + }, + ); + { + let mut ast_path = ast_path.with_guard(AstParentNodeRef::AssignPatProp( + assign, + AssignPatPropField::Value, + )); + value.visit_with_path(self, &mut ast_path); + } + }, + + _ => prop.visit_with_path(self, &mut ast_path), + } + } + } +} + +fn extract_var_from_umd_factory(callee:&Expr, args:&[ExprOrSpread]) -> Option { + match unparen(callee) { + Expr::Ident(Ident { sym, .. }) => { + if &**sym == "define" { + if let Expr::Fn(FnExpr { function, .. }) = &*args[0].expr { + let params = &*function.params; + if params.len() == 1 { + if let Pat::Ident(param) = ¶ms[0].pat { + if &*param.id.sym == "require" { + return Some(param.to_id()); + } + } + } + } + } + }, + + // umd may use (function (factory){ + // // Somewhere, define(['require', 'exports'], factory) + // }(function (require, exports){})) + // + // In all module system which has `require`, `require` in the factory function can be + // treated as a well-known require. + Expr::Fn(FnExpr { function, .. }) => { + let params = &*function.params; + if params.len() == 1 { + if let Some(FnExpr { function, .. }) = + args.first().and_then(|arg| arg.expr.as_fn_expr()) + { + let params = &*function.params; + if !params.is_empty() { + if let Pat::Ident(param) = ¶ms[0].pat { + if &*param.id.sym == "require" { + return Some(param.to_id()); + } + } + } + } + } + }, + + _ => {}, + } + + None +} + +fn get_fn_init_return_vals(fn_body_stmts:Option<&BlockStmt>) -> Vec { + let has_final_return_val = match fn_body_stmts { + Some(fn_body_stmts) => { + matches!(fn_body_stmts.stmts.last(), Some(Stmt::Return(ReturnStmt { arg:Some(_), .. }))) + }, + None => false, + }; + + if has_final_return_val { + vec![] + } else { + vec![JsValue::Constant(ConstantValue::Undefined)] + } +} diff --git a/crates/turbopack-ecmascript/Source/analyzer/imports.rs b/crates/turbopack-ecmascript/Source/analyzer/imports.rs new file mode 100644 index 0000000000000..b5655325e3600 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/analyzer/imports.rs @@ -0,0 +1,445 @@ +use std::{collections::BTreeMap, fmt::Display}; + +use indexmap::{IndexMap, IndexSet}; +use once_cell::sync::Lazy; +use swc_core::{ + common::{Span, source_map::Pos}, + ecma::{ + ast::*, + atoms::{JsWord, js_word}, + visit::{Visit, VisitWith}, + }, +}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::{issue::IssueSource, source::Source}; + +use super::{JsValue, ModuleValue, top_level_await::has_top_level_await}; +use crate::tree_shake::{PartId, find_turbopack_part_id_in_asserts}; + +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(Default, Debug, Clone, Hash, PartialOrd, Ord)] +pub struct ImportAnnotations { + // TODO store this in more structured way + #[turbo_tasks(trace_ignore)] + map:BTreeMap, +} + +/// Enables a specified transition for the annotated import +static ANNOTATION_TRANSITION:Lazy = + Lazy::new(|| crate::annotations::ANNOTATION_TRANSITION.into()); + +/// Changes the chunking type for the annotated import +static ANNOTATION_CHUNKING_TYPE:Lazy = + Lazy::new(|| crate::annotations::ANNOTATION_CHUNKING_TYPE.into()); + +/// Changes the type of the resolved module (only "json" is supported currently) +static ATTRIBUTE_MODULE_TYPE:Lazy = Lazy::new(|| "type".into()); + +impl ImportAnnotations { + pub fn parse(with:Option<&ObjectLit>) -> ImportAnnotations { + let Some(with) = with else { + return ImportAnnotations::default(); + }; + + let mut map = BTreeMap::new(); + + // The `with` clause is way more restrictive than `ObjectLit`, it only allows + // string -> value and value can only be a string. + // We just ignore everything else here till the SWC ast is more restrictive. + for (key, value) in with.props.iter().filter_map(|prop| { + let kv = prop.as_prop()?.as_key_value()?; + + let Lit::Str(str) = kv.value.as_lit()? else { + return None; + }; + + Some((&kv.key, str)) + }) { + let key = match key { + PropName::Ident(ident) => ident.sym.as_str(), + PropName::Str(str) => str.value.as_str(), + // the rest are invalid, ignore for now till SWC ast is correct + _ => continue, + }; + + map.insert(key.into(), value.value.as_str().into()); + } + + ImportAnnotations { map } + } + + /// Returns the content on the transition annotation + pub fn transition(&self) -> Option<&str> { self.get(&ANNOTATION_TRANSITION) } + + /// Returns the content on the chunking-type annotation + pub fn chunking_type(&self) -> Option<&str> { self.get(&ANNOTATION_CHUNKING_TYPE) } + + /// Returns the content on the type attribute + pub fn module_type(&self) -> Option<&str> { self.get(&ATTRIBUTE_MODULE_TYPE) } + + pub fn get(&self, key:&JsWord) -> Option<&str> { self.map.get(key).map(|w| w.as_str()) } +} + +impl Display for ImportAnnotations { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut it = self.map.iter(); + if let Some((k, v)) = it.next() { + write!(f, "{{ {k}: {v}")? + } else { + return f.write_str("{}"); + }; + for (k, v) in it { + write!(f, ", {k}: {v}")? + } + f.write_str(" }") + } +} + +#[derive(Debug)] +pub(crate) enum Reexport { + Star, + Namespace { exported:JsWord }, + Named { imported:JsWord, exported:JsWord }, +} + +/// The storage for all kinds of imports. +/// +/// Note that when it's initialized by calling `analyze`, it only contains ESM +/// import/exports. +#[derive(Default, Debug)] +pub(crate) struct ImportMap { + /// Map from identifier to (index in references, exported symbol) + imports:IndexMap, + + /// Map from identifier to index in references + namespace_imports:IndexMap, + + /// List of (index in references, imported symbol, exported symbol) + reexports:Vec<(usize, Reexport)>, + + /// Ordered list of imported symbols + references:IndexSet, + + /// True, when the module has exports + has_exports:bool, + + /// True if the module is an ESM module due to top-level await. + has_top_level_await:bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub(crate) enum ImportedSymbol { + ModuleEvaluation, + Symbol(JsWord), + /// User requested the whole module + Namespace, + Exports, + Part(u32), +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub(crate) struct ImportMapReference { + pub module_path:JsWord, + pub imported_symbol:ImportedSymbol, + pub annotations:ImportAnnotations, + pub issue_source:Option>, +} + +impl ImportMap { + pub fn is_esm(&self) -> bool { + self.has_exports + || self.has_top_level_await + || !self.imports.is_empty() + || !self.namespace_imports.is_empty() + } + + pub fn get_import(&self, id:&Id) -> Option { + if let Some((i, i_sym)) = self.imports.get(id) { + let r = &self.references[*i]; + return Some(JsValue::member( + Box::new(JsValue::Module(ModuleValue { + module:r.module_path.clone(), + annotations:r.annotations.clone(), + })), + Box::new(i_sym.clone().into()), + )); + } + if let Some(i) = self.namespace_imports.get(id) { + let r = &self.references[*i]; + return Some(JsValue::Module(ModuleValue { + module:r.module_path.clone(), + annotations:r.annotations.clone(), + })); + } + None + } + + // TODO this could return &str instead of String to avoid cloning + pub fn get_binding(&self, id:&Id) -> Option<(usize, Option)> { + if let Some((i, i_sym)) = self.imports.get(id) { + return Some((*i, Some(i_sym.as_str().into()))); + } + if let Some(i) = self.namespace_imports.get(id) { + return Some((*i, None)); + } + None + } + + pub fn references(&self) -> impl Iterator { self.references.iter() } + + pub fn reexports(&self) -> impl Iterator { + self.reexports.iter().map(|(i, r)| (*i, r)) + } + + /// Analyze ES import + pub(super) fn analyze( + m:&Program, + skip_namespace:bool, + source:Option>>, + ) -> Self { + let mut data = ImportMap::default(); + + m.visit_with(&mut Analyzer { data:&mut data, skip_namespace, source }); + + data + } +} + +struct Analyzer<'a> { + data:&'a mut ImportMap, + skip_namespace:bool, + source:Option>>, +} + +impl<'a> Analyzer<'a> { + fn ensure_reference( + &mut self, + span:Span, + module_path:JsWord, + imported_symbol:ImportedSymbol, + annotations:ImportAnnotations, + ) -> Option { + if self.skip_namespace && matches!(imported_symbol, ImportedSymbol::Namespace) { + return None; + } + + let issue_source = self + .source + .map(|s| IssueSource::from_swc_offsets(s, span.lo.to_usize(), span.hi.to_usize())); + + let r = ImportMapReference { module_path, imported_symbol, issue_source, annotations }; + if let Some(i) = self.data.references.get_index_of(&r) { + Some(i) + } else { + let i = self.data.references.len(); + self.data.references.insert(r); + Some(i) + } + } +} + +fn to_word(name:&ModuleExportName) -> JsWord { + match name { + ModuleExportName::Ident(ident) => ident.sym.clone(), + ModuleExportName::Str(str) => str.value.clone(), + } +} + +impl Visit for Analyzer<'_> { + fn visit_import_decl(&mut self, import:&ImportDecl) { + let annotations = ImportAnnotations::parse(import.with.as_deref()); + + let internal_symbol = parse_with(import.with.as_deref()); + + if internal_symbol.is_none() { + self.ensure_reference( + import.span, + import.src.value.clone(), + ImportedSymbol::ModuleEvaluation, + annotations.clone(), + ); + } + + for s in &import.specifiers { + let symbol = + internal_symbol.clone().unwrap_or_else(|| get_import_symbol_from_import(s)); + let i = self.ensure_reference( + import.span, + import.src.value.clone(), + symbol, + annotations.clone(), + ); + let i = match i { + Some(v) => v, + None => continue, + }; + + let (local, orig_sym) = match s { + ImportSpecifier::Named(ImportNamedSpecifier { local, imported, .. }) => { + match imported { + Some(imported) => (local.to_id(), orig_name(imported)), + _ => (local.to_id(), local.sym.clone()), + } + }, + ImportSpecifier::Default(s) => (s.local.to_id(), "default".into()), + ImportSpecifier::Namespace(s) => { + self.data.namespace_imports.insert(s.local.to_id(), i); + continue; + }, + }; + + self.data.imports.insert(local, (i, orig_sym)); + } + + if import.specifiers.is_empty() { + if let Some(internal_symbol) = internal_symbol { + self.ensure_reference( + import.span, + import.src.value.clone(), + internal_symbol, + annotations, + ); + } + } + } + + fn visit_export_all(&mut self, export:&ExportAll) { + self.data.has_exports = true; + + let annotations = ImportAnnotations::parse(export.with.as_deref()); + + self.ensure_reference( + export.span, + export.src.value.clone(), + ImportedSymbol::ModuleEvaluation, + annotations.clone(), + ); + let symbol = parse_with(export.with.as_deref()); + + let i = self.ensure_reference( + export.span, + export.src.value.clone(), + symbol.unwrap_or(ImportedSymbol::Namespace), + annotations, + ); + if let Some(i) = i { + self.data.reexports.push((i, Reexport::Star)); + } + } + + fn visit_named_export(&mut self, export:&NamedExport) { + self.data.has_exports = true; + + let Some(ref src) = export.src else { + return; + }; + + let annotations = ImportAnnotations::parse(export.with.as_deref()); + + let internal_symbol = parse_with(export.with.as_deref()); + + if internal_symbol.is_none() || export.specifiers.is_empty() { + self.ensure_reference( + export.span, + src.value.clone(), + ImportedSymbol::ModuleEvaluation, + annotations.clone(), + ); + } + + for spec in export.specifiers.iter() { + let symbol = + internal_symbol.clone().unwrap_or_else(|| get_import_symbol_from_export(spec)); + + let i = + self.ensure_reference(export.span, src.value.clone(), symbol, annotations.clone()); + let i = match i { + Some(v) => v, + None => continue, + }; + + match spec { + ExportSpecifier::Namespace(n) => { + self.data + .reexports + .push((i, Reexport::Namespace { exported:to_word(&n.name) })); + }, + ExportSpecifier::Default(d) => { + self.data.reexports.push(( + i, + Reexport::Named { + imported:js_word!("default"), + exported:d.exported.sym.clone(), + }, + )); + }, + ExportSpecifier::Named(n) => { + self.data.reexports.push(( + i, + Reexport::Named { + imported:to_word(&n.orig), + exported:to_word(n.exported.as_ref().unwrap_or(&n.orig)), + }, + )); + }, + } + } + } + + fn visit_export_decl(&mut self, _:&ExportDecl) { self.data.has_exports = true; } + + fn visit_export_default_decl(&mut self, _:&ExportDefaultDecl) { self.data.has_exports = true; } + + fn visit_export_default_expr(&mut self, _:&ExportDefaultExpr) { self.data.has_exports = true; } + + fn visit_stmt(&mut self, _:&Stmt) { + // don't visit children + } + + fn visit_program(&mut self, m:&Program) { + self.data.has_top_level_await = has_top_level_await(m).is_some(); + + m.visit_children_with(self); + } +} + +pub(crate) fn orig_name(n:&ModuleExportName) -> JsWord { + match n { + ModuleExportName::Ident(v) => v.sym.clone(), + ModuleExportName::Str(v) => v.value.clone(), + } +} + +fn parse_with(with:Option<&ObjectLit>) -> Option { + find_turbopack_part_id_in_asserts(with?).map(|v| { + match v { + PartId::Internal(index) => ImportedSymbol::Part(index), + PartId::ModuleEvaluation => ImportedSymbol::ModuleEvaluation, + PartId::Export(e) => ImportedSymbol::Symbol(e.as_str().into()), + PartId::Exports => ImportedSymbol::Exports, + } + }) +} + +fn get_import_symbol_from_import(specifier:&ImportSpecifier) -> ImportedSymbol { + match specifier { + ImportSpecifier::Named(ImportNamedSpecifier { local, imported, .. }) => { + ImportedSymbol::Symbol(match imported { + Some(imported) => orig_name(imported), + _ => local.sym.clone(), + }) + }, + ImportSpecifier::Default(..) => ImportedSymbol::Symbol(js_word!("default")), + ImportSpecifier::Namespace(..) => ImportedSymbol::Namespace, + } +} + +fn get_import_symbol_from_export(specifier:&ExportSpecifier) -> ImportedSymbol { + match specifier { + ExportSpecifier::Named(ExportNamedSpecifier { orig, .. }) => { + ImportedSymbol::Symbol(orig_name(orig)) + }, + ExportSpecifier::Default(..) => ImportedSymbol::Symbol(js_word!("default")), + ExportSpecifier::Namespace(..) => ImportedSymbol::Namespace, + } +} diff --git a/crates/turbopack-ecmascript/Source/analyzer/linker.rs b/crates/turbopack-ecmascript/Source/analyzer/linker.rs new file mode 100644 index 0000000000000..4c9e8d60bbd1a --- /dev/null +++ b/crates/turbopack-ecmascript/Source/analyzer/linker.rs @@ -0,0 +1,332 @@ +use std::{ + collections::{HashMap, HashSet, hash_map::Entry}, + future::Future, + mem::take, +}; + +use anyhow::Result; +use swc_core::ecma::ast::Id; + +use super::{JsValue, graph::VarGraph}; + +pub async fn link<'a, B, RB, F, RF>( + graph:&VarGraph, + mut val:JsValue, + early_visitor:&B, + visitor:&F, + fun_args_values:HashMap>, +) -> Result +where + RB: 'a + Future> + Send, + B: 'a + Fn(JsValue) -> RB + Sync, + RF: 'a + Future> + Send, + F: 'a + Fn(JsValue) -> RF + Sync, { + val.normalize(); + let val = link_internal_iterative(graph, val, early_visitor, visitor, fun_args_values).await?; + Ok(val) +} + +const LIMIT_NODE_SIZE:usize = 300; +const LIMIT_IN_PROGRESS_NODES:usize = 1000; +const LIMIT_LINK_STEPS:usize = 1500; + +pub(crate) async fn link_internal_iterative<'a, B, RB, F, RF>( + graph:&'a VarGraph, + val:JsValue, + early_visitor:&'a B, + visitor:&'a F, + mut fun_args_values:HashMap>, +) -> Result +where + RB: 'a + Future> + Send, + B: 'a + Fn(JsValue) -> RB + Sync, + RF: 'a + Future> + Send, + F: 'a + Fn(JsValue) -> RF + Sync, { + #[derive(Debug)] + enum Step { + Enter(JsValue), + EarlyVisit(JsValue), + Leave(JsValue), + LeaveVar(Id), + LeaveLate(JsValue), + Visit(JsValue), + LeaveCall(u32), + } + + let mut work_queue_stack:Vec = Vec::new(); + let mut done:Vec = Vec::new(); + // Tracks the number of nodes in the queue and done combined + let mut total_nodes = 0; + let mut cycle_stack:HashSet = HashSet::new(); + // Tracks the number linking steps so far + let mut steps = 0; + + total_nodes += val.total_nodes(); + work_queue_stack.push(Step::Enter(val)); + + while let Some(step) = work_queue_stack.pop() { + steps += 1; + + match step { + // Enter a variable + // - replace it with value from graph + // - process value + // - on leave: cache value + Step::Enter(JsValue::Variable(var)) => { + // Replace with unknown for now + if cycle_stack.contains(&var) { + done.push(JsValue::unknown( + JsValue::Variable(var.clone()), + false, + "circular variable reference", + )); + } else { + total_nodes -= 1; + if let Some(val) = graph.values.get(&var) { + cycle_stack.insert(var.clone()); + work_queue_stack.push(Step::LeaveVar(var)); + total_nodes += val.total_nodes(); + work_queue_stack.push(Step::Enter(val.clone())); + } else { + total_nodes += 1; + done.push(JsValue::unknown( + JsValue::Variable(var.clone()), + false, + "no value of this variable analysed", + )); + }; + } + }, + // Leave a variable + Step::LeaveVar(var) => { + cycle_stack.remove(&var); + }, + // Enter a function argument + // We want to replace the argument with the value from the function call + Step::Enter(JsValue::Argument(func_ident, index)) => { + total_nodes -= 1; + if let Some(args) = fun_args_values.get(&func_ident) { + if let Some(val) = args.get(index) { + total_nodes += val.total_nodes(); + done.push(val.clone()); + } else { + total_nodes += 1; + done.push(JsValue::unknown_empty( + false, + "unknown function argument (out of bounds)", + )); + } + } else { + total_nodes += 1; + done.push(JsValue::unknown( + JsValue::Argument(func_ident, index), + false, + "function calls are not analysed yet", + )); + } + }, + // Visit a function call + // This need special handling, since we want to replace the function call and process + // the function return value after that. + Step::Visit(JsValue::Call( + _, + box JsValue::Function(_, func_ident, return_value), + args, + )) => { + total_nodes -= 2; // Call + Function + if let Entry::Vacant(entry) = fun_args_values.entry(func_ident) { + // Return value will stay in total_nodes + for arg in args.iter() { + total_nodes -= arg.total_nodes(); + } + entry.insert(args); + work_queue_stack.push(Step::LeaveCall(func_ident)); + work_queue_stack.push(Step::Enter(*return_value)); + } else { + total_nodes -= return_value.total_nodes(); + for arg in args.iter() { + total_nodes -= arg.total_nodes(); + } + total_nodes += 1; + done.push(JsValue::unknown( + JsValue::call(Box::new(JsValue::function(func_ident, return_value)), args), + true, + "recursive function call", + )); + } + }, + // Leaving a function call evaluation + // - remove function arguments from the map + Step::LeaveCall(func_ident) => { + fun_args_values.remove(&func_ident); + }, + // Enter a function + // We don't want to process the function return value yet, this will happen after + // function calls + // - just put it into done + Step::Enter(func @ JsValue::Function(..)) => { + done.push(func); + }, + // Enter a value + // - take and queue children for processing + // - on leave: insert children again and optimize + Step::Enter(mut val) => { + let i = work_queue_stack.len(); + work_queue_stack.push(Step::Leave(JsValue::default())); + let mut has_early_children = false; + val.for_each_early_children_mut(&mut |child| { + has_early_children = true; + work_queue_stack.push(Step::Enter(take(child))); + false + }); + if has_early_children { + work_queue_stack[i] = Step::EarlyVisit(val); + } else { + val.for_each_children_mut(&mut |child| { + work_queue_stack.push(Step::Enter(take(child))); + false + }); + work_queue_stack[i] = Step::Leave(val); + } + }, + // Early visit a value + // - reconstruct the value from early children + // - visit the value + // - insert late children and process for Leave + Step::EarlyVisit(mut val) => { + val.for_each_early_children_mut(&mut |child| { + let val = done.pop().unwrap(); + *child = val; + true + }); + val.debug_assert_total_nodes_up_to_date(); + total_nodes -= val.total_nodes(); + if val.total_nodes() > LIMIT_NODE_SIZE { + total_nodes += 1; + done.push(JsValue::unknown_empty(true, "node limit reached")); + continue; + } + + let (mut val, visit_modified) = early_visitor(val).await?; + val.debug_assert_total_nodes_up_to_date(); + if visit_modified && val.total_nodes() > LIMIT_NODE_SIZE { + total_nodes += 1; + done.push(JsValue::unknown_empty(true, "node limit reached")); + continue; + } + + let count = val.total_nodes(); + if total_nodes + count > LIMIT_IN_PROGRESS_NODES { + // There is always space for one more node since we just popped at least one + // count + total_nodes += 1; + done.push(JsValue::unknown_empty(true, "in progress nodes limit reached")); + continue; + } + total_nodes += count; + + if visit_modified { + // When the early visitor has changed the value, we need to enter it again + work_queue_stack.push(Step::Enter(val)); + } else { + // Otherwise we can just process the late children + let i = work_queue_stack.len(); + work_queue_stack.push(Step::LeaveLate(JsValue::default())); + val.for_each_late_children_mut(&mut |child| { + work_queue_stack.push(Step::Enter(take(child))); + false + }); + work_queue_stack[i] = Step::LeaveLate(val); + } + }, + // Leave a value + Step::Leave(mut val) => { + val.for_each_children_mut(&mut |child| { + let val = done.pop().unwrap(); + *child = val; + true + }); + val.debug_assert_total_nodes_up_to_date(); + + total_nodes -= val.total_nodes(); + + if val.total_nodes() > LIMIT_NODE_SIZE { + total_nodes += 1; + done.push(JsValue::unknown_empty(true, "node limit reached")); + continue; + } + val.normalize_shallow(); + + val.debug_assert_total_nodes_up_to_date(); + + total_nodes += val.total_nodes(); + work_queue_stack.push(Step::Visit(val)); + }, + // Leave a value from EarlyVisit + Step::LeaveLate(mut val) => { + val.for_each_late_children_mut(&mut |child| { + let val = done.pop().unwrap(); + *child = val; + true + }); + val.debug_assert_total_nodes_up_to_date(); + + total_nodes -= val.total_nodes(); + + if val.total_nodes() > LIMIT_NODE_SIZE { + total_nodes += 1; + done.push(JsValue::unknown_empty(true, "node limit reached")); + continue; + } + val.normalize_shallow(); + + val.debug_assert_total_nodes_up_to_date(); + + total_nodes += val.total_nodes(); + work_queue_stack.push(Step::Visit(val)); + }, + // Visit a value with the visitor + // - visited value is put into done + Step::Visit(val) => { + total_nodes -= val.total_nodes(); + + let (mut val, visit_modified) = visitor(val).await?; + if visit_modified { + val.normalize_shallow(); + #[cfg(debug_assertions)] + val.debug_assert_total_nodes_up_to_date(); + if val.total_nodes() > LIMIT_NODE_SIZE { + total_nodes += 1; + done.push(JsValue::unknown_empty(true, "node limit reached")); + continue; + } + } + + let count = val.total_nodes(); + if total_nodes + count > LIMIT_IN_PROGRESS_NODES { + // There is always space for one more node since we just popped at least one + // count + total_nodes += 1; + done.push(JsValue::unknown_empty(true, "in progress nodes limit reached")); + continue; + } + total_nodes += count; + if visit_modified { + work_queue_stack.push(Step::Enter(val)); + } else { + done.push(val); + } + }, + } + if steps > LIMIT_LINK_STEPS { + return Ok(JsValue::unknown_empty(true, "max number of linking steps reached")); + } + } + + let final_value = done.pop().unwrap(); + + debug_assert!(work_queue_stack.is_empty()); + debug_assert_eq!(total_nodes, final_value.total_nodes()); + + Ok(final_value) +} diff --git a/crates/turbopack-ecmascript/Source/analyzer/mod.rs b/crates/turbopack-ecmascript/Source/analyzer/mod.rs new file mode 100644 index 0000000000000..d2715384653f9 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/analyzer/mod.rs @@ -0,0 +1,3698 @@ +#![allow(clippy::redundant_closure_call)] + +use std::{ + borrow::Cow, + cmp::Ordering, + fmt::{Display, Write}, + future::Future, + hash::{Hash, Hasher}, + mem::take, + pin::Pin, + sync::Arc, +}; + +use anyhow::{Context, Result, bail}; +use indexmap::{IndexMap, IndexSet}; +use num_bigint::BigInt; +use num_traits::identities::Zero; +use once_cell::sync::Lazy; +use regex::Regex; +use swc_core::{ + common::Mark, + ecma::{ + ast::{Id, Ident, Lit}, + atoms::{Atom, JsWord}, + }, +}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::compile_time_info::CompileTimeDefineValue; +use url::Url; + +use self::imports::ImportAnnotations; +pub(crate) use self::imports::ImportMap; +use crate::{references::require_context::RequireContextMap, utils::StringifyJs}; + +pub mod builtin; +pub mod graph; +pub mod imports; +pub mod linker; +pub mod top_level_await; +pub mod well_known; + +type PinnedAsyncUntilSettledBox<'a, E> = + Pin> + Send + 'a>>; + +type PinnedAsyncBox<'a, E> = Pin> + 'a>>; + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub enum ObjectPart { + KeyValue(JsValue, JsValue), + Spread(JsValue), +} + +impl Default for ObjectPart { + fn default() -> Self { ObjectPart::Spread(Default::default()) } +} + +#[derive(Debug, Clone)] +pub struct ConstantNumber(pub f64); + +fn integer_decode(val:f64) -> (u64, i16, i8) { + let bits:u64 = val.to_bits(); + let sign:i8 = if bits >> 63 == 0 { 1 } else { -1 }; + let mut exponent:i16 = ((bits >> 52) & 0x7FF) as i16; + let mantissa = if exponent == 0 { + (bits & 0xFFFFFFFFFFFFF) << 1 + } else { + (bits & 0xFFFFFFFFFFFFF) | 0x10000000000000 + }; + + exponent -= 1023 + 52; + (mantissa, exponent, sign) +} + +impl ConstantNumber { + pub fn as_u32_index(&self) -> Option { + let index:u32 = self.0 as u32; + (index as f64 == self.0).then_some(index as usize) + } +} + +impl Hash for ConstantNumber { + fn hash(&self, state:&mut H) { integer_decode(self.0).hash(state); } +} + +impl PartialEq for ConstantNumber { + fn eq(&self, other:&Self) -> bool { integer_decode(self.0) == integer_decode(other.0) } +} + +impl Eq for ConstantNumber {} + +#[derive(Debug, Clone)] +pub enum ConstantString { + Word(JsWord), + Atom(Atom), + RcStr(RcStr), +} + +impl ConstantString { + pub fn as_str(&self) -> &str { + match self { + Self::Word(s) => s, + Self::Atom(s) => s, + Self::RcStr(s) => s, + } + } + + pub fn is_empty(&self) -> bool { self.as_str().is_empty() } +} + +impl PartialEq for ConstantString { + fn eq(&self, other:&Self) -> bool { self.as_str() == other.as_str() } +} + +impl Eq for ConstantString {} + +impl Hash for ConstantString { + fn hash(&self, state:&mut H) { self.as_str().hash(state); } +} + +impl Display for ConstantString { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.as_str().fmt(f) } +} + +impl From for ConstantString { + fn from(v:Atom) -> Self { ConstantString::Atom(v) } +} + +impl From<&'static str> for ConstantString { + fn from(v:&'static str) -> Self { ConstantString::Word(v.into()) } +} + +impl From for ConstantString { + fn from(v:String) -> Self { ConstantString::Atom(v.into()) } +} + +impl From for ConstantString { + fn from(v:RcStr) -> Self { ConstantString::RcStr(v) } +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, Default)] +pub enum ConstantValue { + #[default] + Undefined, + Str(ConstantString), + Num(ConstantNumber), + True, + False, + Null, + BigInt(BigInt), + Regex(Atom, Atom), +} + +impl ConstantValue { + pub fn as_str(&self) -> Option<&str> { + match self { + Self::Str(s) => Some(s.as_str()), + _ => None, + } + } + + pub fn as_bool(&self) -> Option { + match self { + Self::True => Some(true), + Self::False => Some(false), + _ => None, + } + } + + pub fn is_truthy(&self) -> bool { + match self { + Self::Undefined | Self::False | Self::Null => false, + Self::True | Self::Regex(..) => true, + Self::Str(s) => !s.is_empty(), + Self::Num(ConstantNumber(n)) => *n != 0.0, + Self::BigInt(n) => !n.is_zero(), + } + } + + pub fn is_nullish(&self) -> bool { + match self { + Self::Undefined | Self::Null => true, + Self::Str(..) + | Self::Num(..) + | Self::True + | Self::False + | Self::BigInt(..) + | Self::Regex(..) => false, + } + } + + pub fn is_empty_string(&self) -> bool { + match self { + Self::Str(s) => s.is_empty(), + _ => false, + } + } + + pub fn is_value_type(&self) -> bool { !matches!(self, Self::Regex(..)) } +} + +impl From for ConstantValue { + fn from(v:bool) -> Self { + match v { + true => ConstantValue::True, + false => ConstantValue::False, + } + } +} + +impl From<&'_ str> for ConstantValue { + fn from(v:&str) -> Self { ConstantValue::Str(ConstantString::Word(v.into())) } +} + +impl From for ConstantValue { + fn from(v:Lit) -> Self { + match v { + Lit::Str(v) => ConstantValue::Str(ConstantString::Word(v.value)), + Lit::Bool(v) => { + if v.value { + ConstantValue::True + } else { + ConstantValue::False + } + }, + Lit::Null(_) => ConstantValue::Null, + Lit::Num(v) => ConstantValue::Num(ConstantNumber(v.value)), + Lit::BigInt(v) => ConstantValue::BigInt(*v.value), + Lit::Regex(v) => ConstantValue::Regex(v.exp, v.flags), + Lit::JSXText(v) => ConstantValue::Str(ConstantString::Atom(v.value)), + } + } +} + +impl Display for ConstantValue { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstantValue::Undefined => write!(f, "undefined"), + ConstantValue::Str(str) => write!(f, "{}", StringifyJs(str.as_str())), + ConstantValue::True => write!(f, "true"), + ConstantValue::False => write!(f, "false"), + ConstantValue::Null => write!(f, "null"), + ConstantValue::Num(ConstantNumber(n)) => write!(f, "{n}"), + ConstantValue::BigInt(n) => write!(f, "{n}"), + ConstantValue::Regex(exp, flags) => write!(f, "/{exp}/{flags}"), + } + } +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct ModuleValue { + pub module:JsWord, + pub annotations:ImportAnnotations, +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +pub enum LogicalOperator { + And, + Or, + NullishCoalescing, +} + +impl LogicalOperator { + fn joiner(&self) -> &'static str { + match self { + LogicalOperator::And => " && ", + LogicalOperator::Or => " || ", + LogicalOperator::NullishCoalescing => " ?? ", + } + } + + fn multi_line_joiner(&self) -> &'static str { + match self { + LogicalOperator::And => "&& ", + LogicalOperator::Or => "|| ", + LogicalOperator::NullishCoalescing => "?? ", + } + } +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +pub enum BinaryOperator { + Equal, + NotEqual, + StrictEqual, + StrictNotEqual, +} + +impl BinaryOperator { + fn joiner(&self) -> &'static str { + match self { + BinaryOperator::Equal => " == ", + BinaryOperator::NotEqual => " != ", + BinaryOperator::StrictEqual => " === ", + BinaryOperator::StrictNotEqual => " !== ", + } + } + + fn positive_op(&self) -> (PositiveBinaryOperator, bool) { + match self { + BinaryOperator::Equal => (PositiveBinaryOperator::Equal, false), + BinaryOperator::NotEqual => (PositiveBinaryOperator::Equal, true), + BinaryOperator::StrictEqual => (PositiveBinaryOperator::StrictEqual, false), + BinaryOperator::StrictNotEqual => (PositiveBinaryOperator::StrictEqual, true), + } + } +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +pub enum PositiveBinaryOperator { + Equal, + StrictEqual, +} + +/// The four categories of [JsValue]s. +enum JsValueMetaKind { + /// Doesn't contain nested values. + Leaf, + /// Contains nested values. Nested values represent some structure and can't + /// be replaced during linking. They might contain placeholders. + Nested, + /// Contains nested values. Operations are replaced during linking. They + /// might contain placeholders. + Operation, + /// These values are replaced during linking. + Placeholder, +} + +/// TODO: Use `Arc` +/// There are 4 kinds of values: Leaves, Nested, Operations, and Placeholders +/// (see [JsValueMetaKind] for details). Values are processed in two phases: +/// - Analyze phase: We convert AST into [JsValue]s. We don't have contextual +/// information so we need to insert placeholders to represent that. +/// - Link phase: We try to reduce a value to a constant value. The link phase +/// has 5 substeps that are executed on each node in the graph depth-first. +/// When a value is modified, we need to visit the new children again. +/// - Replace variables with their values. This replaces [JsValue::Variable]. No +/// variable should be remaining after that. +/// - Replace placeholders with contextual information. This usually replaces +/// [JsValue::FreeVar] and [JsValue::Module]. Some [JsValue::Call] on well- +/// known functions might also be replaced. No free vars or modules should be +/// remaining after that. +/// - Replace operations on well-known objects and functions. This handles +/// [JsValue::Call] and [JsValue::Member] on well-known objects and functions. +/// - Replace all built-in functions with their values when they are +/// compile-time constant. +/// - For optimization, any nested operations are replaced with +/// [JsValue::Unknown]. So only one layer of operation remains. Any remaining +/// operation or placeholder can be treated as unknown. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub enum JsValue { + // LEAF VALUES + // ---------------------------- + /// A constant primitive value. + Constant(ConstantValue), + /// An constant URL object. + Url(Box), + /// Some kind of well-known object + /// (must not be an array, otherwise Array.concat needs to be changed) + WellKnownObject(WellKnownObjectKind), + /// Some kind of well-known function + WellKnownFunction(WellKnownFunctionKind), + /// Not-analyzable value. Might contain the original value for additional + /// info. Has a reason string for explanation. + Unknown { + original_value:Option>, + reason:Cow<'static, str>, + has_side_effects:bool, + }, + + // NESTED VALUES + // ---------------------------- + /// An array of nested values + Array { total_nodes:usize, items:Vec, mutable:bool }, + /// An object of nested values + Object { total_nodes:usize, parts:Vec, mutable:bool }, + /// A list of alternative values + Alternatives(usize, Vec), + /// A function reference. The return value might contain [JsValue::Argument] + /// placeholders that need to be replaced when calling this function. + /// `(total_node_count, func_ident, return_value)` + Function(usize, u32, Box), + + // OPERATIONS + // ---------------------------- + /// A string concatenation of values. + /// `foo.${unknownVar}.js` => 'foo' + Unknown + '.js' + Concat(usize, Vec), + /// An addition of values. + /// This can be converted to [JsValue::Concat] if the type of the variable + /// is string. + Add(usize, Vec), + /// Logical negation `!expr` + Not(usize, Box), + /// Logical operator chain e. g. `expr && expr` + Logical(usize, LogicalOperator, Vec), + /// Binary expression e. g. `expr == expr` + Binary(usize, Box, BinaryOperator, Box), + /// A function call without a this context. + /// `(total_node_count, callee, args)` + Call(usize, Box, Vec), + /// A super call to the parent constructor. + /// `(total_node_count, args)` + SuperCall(usize, Vec), + /// A function call with a this context. + /// `(total_node_count, obj, prop, args)` + MemberCall(usize, Box, Box, Vec), + /// A member access `obj[prop]` + /// `(total_node_count, obj, prop)` + Member(usize, Box, Box), + /// A tenary operator `test ? cons : alt` + /// `(total_node_count, test, cons, alt)` + Tenary(usize, Box, Box, Box), + + /// A for-of loop + /// + /// `(total_node_count, iterable)` + Iterated(usize, Box), + + /// A `typeof` expression. + /// + /// `(total_node_count, operand)` + TypeOf(usize, Box), + + // PLACEHOLDERS + // ---------------------------- + /// A reference to a variable. + Variable(Id), + /// A reference to an function argument. + /// (func_ident, arg_index) + Argument(u32, usize), + // TODO no predefined kinds, only JsWord + /// A reference to a free variable. + FreeVar(JsWord), + /// This is a reference to a imported module. + Module(ModuleValue), +} + +impl From<&'_ str> for JsValue { + fn from(v:&str) -> Self { ConstantValue::Str(ConstantString::Word(v.into())).into() } +} + +impl From for JsValue { + fn from(v:Atom) -> Self { ConstantValue::Str(ConstantString::Atom(v)).into() } +} + +impl From for JsValue { + fn from(v:BigInt) -> Self { ConstantValue::BigInt(v).into() } +} + +impl From for JsValue { + fn from(v:f64) -> Self { ConstantValue::Num(ConstantNumber(v)).into() } +} + +impl From for JsValue { + fn from(v:RcStr) -> Self { ConstantValue::Str(v.into()).into() } +} + +impl From for JsValue { + fn from(v:String) -> Self { RcStr::from(v).into() } +} + +impl From for JsValue { + fn from(v:swc_core::ecma::ast::Str) -> Self { ConstantValue::Str(v.value.into()).into() } +} + +impl From for JsValue { + fn from(v:ConstantValue) -> Self { JsValue::Constant(v) } +} + +impl From<&CompileTimeDefineValue> for JsValue { + fn from(v:&CompileTimeDefineValue) -> Self { + match v { + CompileTimeDefineValue::String(s) => JsValue::Constant(s.as_str().into()), + CompileTimeDefineValue::Bool(b) => JsValue::Constant((*b).into()), + CompileTimeDefineValue::JSON(_) => { + JsValue::unknown_empty(false, "compile time injected JSON") + }, + } + } +} + +impl Default for JsValue { + fn default() -> Self { JsValue::unknown_empty(false, "") } +} + +impl Display for ObjectPart { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ObjectPart::KeyValue(key, value) => write!(f, "{key}: {value}"), + ObjectPart::Spread(value) => write!(f, "...{value}"), + } + } +} + +impl Display for JsValue { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + JsValue::Constant(v) => write!(f, "{v}"), + JsValue::Url(url) => write!(f, "{}", url), + JsValue::Array { items, mutable, .. } => { + write!( + f, + "{}[{}]", + if *mutable { "" } else { "frozen " }, + items.iter().map(|v| v.to_string()).collect::>().join(", ") + ) + }, + JsValue::Object { parts, mutable, .. } => { + write!( + f, + "{}{{{}}}", + if *mutable { "" } else { "frozen " }, + parts.iter().map(|v| v.to_string()).collect::>().join(", ") + ) + }, + JsValue::Alternatives(_, list) => { + write!( + f, + "({})", + list.iter().map(|v| v.to_string()).collect::>().join(" | ") + ) + }, + JsValue::FreeVar(name) => write!(f, "FreeVar({:?})", name), + JsValue::Variable(name) => write!(f, "Variable({}#{:?})", name.0, name.1), + JsValue::Concat(_, list) => { + write!( + f, + "`{}`", + list.iter() + .map(|v| { + v.as_str().map_or_else(|| format!("${{{}}}", v), |str| str.to_string()) + }) + .collect::>() + .join("") + ) + }, + JsValue::Add(_, list) => { + write!( + f, + "({})", + list.iter().map(|v| v.to_string()).collect::>().join(" + ") + ) + }, + JsValue::Not(_, value) => write!(f, "!({})", value), + JsValue::Logical(_, op, list) => { + write!( + f, + "({})", + list.iter().map(|v| v.to_string()).collect::>().join(op.joiner()) + ) + }, + JsValue::Binary(_, a, op, b) => write!(f, "({}{}{})", a, op.joiner(), b), + JsValue::Tenary(_, test, cons, alt) => write!(f, "({} ? {} : {})", test, cons, alt), + JsValue::Call(_, callee, list) => { + write!( + f, + "{}({})", + callee, + list.iter().map(|v| v.to_string()).collect::>().join(", ") + ) + }, + JsValue::SuperCall(_, list) => { + write!( + f, + "super({})", + list.iter().map(|v| v.to_string()).collect::>().join(", ") + ) + }, + JsValue::MemberCall(_, obj, prop, list) => { + write!( + f, + "{}[{}]({})", + obj, + prop, + list.iter().map(|v| v.to_string()).collect::>().join(", ") + ) + }, + JsValue::Member(_, obj, prop) => write!(f, "{}[{}]", obj, prop), + JsValue::Module(ModuleValue { module: name, annotations }) => { + write!(f, "Module({}, {})", name, annotations) + }, + JsValue::Unknown { .. } => write!(f, "???"), + JsValue::WellKnownObject(obj) => write!(f, "WellKnownObject({:?})", obj), + JsValue::WellKnownFunction(func) => write!(f, "WellKnownFunction({:?})", func), + JsValue::Function(_, func_ident, return_value) => { + write!(f, "Function#{}(return = {:?})", func_ident, return_value) + }, + JsValue::Argument(func_ident, index) => { + write!(f, "arguments[{}#{}]", index, func_ident) + }, + JsValue::Iterated(_, iterable) => write!(f, "Iterated({})", iterable), + JsValue::TypeOf(_, operand) => write!(f, "typeof({})", operand), + } + } +} + +fn pretty_join( + items:&[String], + indent_depth:usize, + single_line_separator:&str, + multi_line_separator_end:&str, + multi_line_separator_start:&str, +) -> String { + let multi_line = items.iter().any(|item| item.len() > 50 || item.contains('\n')) + || items.iter().map(|item| item.len() + single_line_separator.len()).sum::() > 100; + if !multi_line { + items.join(single_line_separator) + } else if multi_line_separator_start.is_empty() { + format!( + "\n{}{}\n{}", + " ".repeat(indent_depth + 1), + items.join(&format!("{multi_line_separator_end}\n{}", " ".repeat(indent_depth + 1))), + " ".repeat(indent_depth) + ) + } else { + format!( + "\n{}{multi_line_separator_start}{}\n{}", + " ".repeat(indent_depth * 4 + 4 - multi_line_separator_start.len()), + items.join(&format!( + "{multi_line_separator_end}\n{}{multi_line_separator_start}", + " ".repeat(indent_depth * 4 + 4 - multi_line_separator_start.len()) + )), + " ".repeat(indent_depth) + ) + } +} + +fn total_nodes(vec:&[JsValue]) -> usize { vec.iter().map(|v| v.total_nodes()).sum::() } + +// Private meta methods +impl JsValue { + fn meta_type(&self) -> JsValueMetaKind { + match self { + JsValue::Constant(..) + | JsValue::Url(..) + | JsValue::WellKnownObject(..) + | JsValue::WellKnownFunction(..) + | JsValue::Unknown { .. } => JsValueMetaKind::Leaf, + JsValue::Array { .. } + | JsValue::Object { .. } + | JsValue::Alternatives(..) + | JsValue::Function(..) + | JsValue::Member(..) => JsValueMetaKind::Nested, + JsValue::Concat(..) + | JsValue::Add(..) + | JsValue::Not(..) + | JsValue::Logical(..) + | JsValue::Binary(..) + | JsValue::Call(..) + | JsValue::SuperCall(..) + | JsValue::Tenary(..) + | JsValue::MemberCall(..) + | JsValue::Iterated(..) + | JsValue::TypeOf(..) => JsValueMetaKind::Operation, + JsValue::Variable(..) + | JsValue::Argument(..) + | JsValue::FreeVar(..) + | JsValue::Module(..) => JsValueMetaKind::Placeholder, + } + } +} + +// Constructors +impl JsValue { + pub fn alternatives(list:Vec) -> Self { + Self::Alternatives(1 + total_nodes(&list), list) + } + + pub fn concat(list:Vec) -> Self { Self::Concat(1 + total_nodes(&list), list) } + + pub fn add(list:Vec) -> Self { Self::Add(1 + total_nodes(&list), list) } + + pub fn logical_and(list:Vec) -> Self { + Self::Logical(1 + total_nodes(&list), LogicalOperator::And, list) + } + + pub fn logical_or(list:Vec) -> Self { + Self::Logical(1 + total_nodes(&list), LogicalOperator::Or, list) + } + + pub fn nullish_coalescing(list:Vec) -> Self { + Self::Logical(1 + total_nodes(&list), LogicalOperator::NullishCoalescing, list) + } + + pub fn tenary(test:Box, cons:Box, alt:Box) -> Self { + Self::Tenary( + 1 + test.total_nodes() + cons.total_nodes() + alt.total_nodes(), + test, + cons, + alt, + ) + } + + pub fn iterated(iterable:JsValue) -> Self { + Self::Iterated(1 + iterable.total_nodes(), Box::new(iterable)) + } + + pub fn equal(a:JsValue, b:JsValue) -> Self { + Self::Binary( + 1 + a.total_nodes() + b.total_nodes(), + Box::new(a), + BinaryOperator::Equal, + Box::new(b), + ) + } + + pub fn not_equal(a:JsValue, b:JsValue) -> Self { + Self::Binary( + 1 + a.total_nodes() + b.total_nodes(), + Box::new(a), + BinaryOperator::NotEqual, + Box::new(b), + ) + } + + pub fn strict_equal(a:JsValue, b:JsValue) -> Self { + Self::Binary( + 1 + a.total_nodes() + b.total_nodes(), + Box::new(a), + BinaryOperator::StrictEqual, + Box::new(b), + ) + } + + pub fn strict_not_equal(a:JsValue, b:JsValue) -> Self { + Self::Binary( + 1 + a.total_nodes() + b.total_nodes(), + Box::new(a), + BinaryOperator::StrictNotEqual, + Box::new(b), + ) + } + + pub fn logical_not(inner:Box) -> Self { Self::Not(1 + inner.total_nodes(), inner) } + + pub fn type_of(operand:Box) -> Self { + Self::TypeOf(1 + operand.total_nodes(), operand) + } + + pub fn array(items:Vec) -> Self { + Self::Array { total_nodes:1 + total_nodes(&items), items, mutable:true } + } + + pub fn frozen_array(items:Vec) -> Self { + Self::Array { total_nodes:1 + total_nodes(&items), items, mutable:false } + } + + pub fn function(func_ident:u32, return_value:Box) -> Self { + Self::Function(1 + return_value.total_nodes(), func_ident, return_value) + } + + pub fn object(list:Vec) -> Self { + Self::Object { + total_nodes:1 + list + .iter() + .map(|v| { + match v { + ObjectPart::KeyValue(k, v) => k.total_nodes() + v.total_nodes(), + ObjectPart::Spread(s) => s.total_nodes(), + } + }) + .sum::(), + parts:list, + mutable:true, + } + } + + pub fn frozen_object(list:Vec) -> Self { + Self::Object { + total_nodes:1 + list + .iter() + .map(|v| { + match v { + ObjectPart::KeyValue(k, v) => k.total_nodes() + v.total_nodes(), + ObjectPart::Spread(s) => s.total_nodes(), + } + }) + .sum::(), + parts:list, + mutable:false, + } + } + + pub fn call(f:Box, args:Vec) -> Self { + Self::Call(1 + f.total_nodes() + total_nodes(&args), f, args) + } + + pub fn super_call(args:Vec) -> Self { Self::SuperCall(1 + total_nodes(&args), args) } + + pub fn member_call(o:Box, p:Box, args:Vec) -> Self { + Self::MemberCall(1 + o.total_nodes() + p.total_nodes() + total_nodes(&args), o, p, args) + } + + pub fn member(o:Box, p:Box) -> Self { + Self::Member(1 + o.total_nodes() + p.total_nodes(), o, p) + } + + pub fn unknown( + value:impl Into>, + side_effects:bool, + reason:impl Into>, + ) -> Self { + Self::Unknown { + original_value:Some(value.into()), + reason:reason.into(), + has_side_effects:side_effects, + } + } + + pub fn unknown_empty(side_effects:bool, reason:impl Into>) -> Self { + Self::Unknown { original_value:None, reason:reason.into(), has_side_effects:side_effects } + } +} + +// Methods regarding node count +impl JsValue { + pub fn total_nodes(&self) -> usize { + match self { + JsValue::Constant(_) + | JsValue::Url(_) + | JsValue::FreeVar(_) + | JsValue::Variable(_) + | JsValue::Module(..) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) + | JsValue::Unknown { .. } + | JsValue::Argument(..) => 1, + + JsValue::Array { total_nodes: c, .. } + | JsValue::Object { total_nodes: c, .. } + | JsValue::Alternatives(c, _) + | JsValue::Concat(c, _) + | JsValue::Add(c, _) + | JsValue::Not(c, _) + | JsValue::Logical(c, ..) + | JsValue::Binary(c, ..) + | JsValue::Tenary(c, ..) + | JsValue::Call(c, ..) + | JsValue::SuperCall(c, _) + | JsValue::MemberCall(c, ..) + | JsValue::Member(c, ..) + | JsValue::Function(c, ..) + | JsValue::Iterated(c, ..) + | JsValue::TypeOf(c, ..) => *c, + } + } + + fn update_total_nodes(&mut self) { + match self { + JsValue::Constant(_) + | JsValue::Url(_) + | JsValue::FreeVar(_) + | JsValue::Variable(_) + | JsValue::Module(..) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) + | JsValue::Unknown { .. } + | JsValue::Argument(..) => {}, + + JsValue::Array { total_nodes: c, items: list, .. } + | JsValue::Alternatives(c, list) + | JsValue::Concat(c, list) + | JsValue::Add(c, list) + | JsValue::Logical(c, _, list) => { + *c = 1 + total_nodes(list); + }, + + JsValue::Binary(c, a, _, b) => { + *c = 1 + a.total_nodes() + b.total_nodes(); + }, + JsValue::Tenary(c, test, cons, alt) => { + *c = 1 + test.total_nodes() + cons.total_nodes() + alt.total_nodes(); + }, + JsValue::Not(c, r) => { + *c = 1 + r.total_nodes(); + }, + + JsValue::Object { total_nodes: c, parts, mutable: _ } => { + *c = 1 + parts + .iter() + .map(|v| { + match v { + ObjectPart::KeyValue(k, v) => k.total_nodes() + v.total_nodes(), + ObjectPart::Spread(s) => s.total_nodes(), + } + }) + .sum::(); + }, + JsValue::Call(c, f, list) => { + *c = 1 + f.total_nodes() + total_nodes(list); + }, + JsValue::SuperCall(c, list) => { + *c = 1 + total_nodes(list); + }, + JsValue::MemberCall(c, o, m, list) => { + *c = 1 + o.total_nodes() + m.total_nodes() + total_nodes(list); + }, + JsValue::Member(c, o, p) => { + *c = 1 + o.total_nodes() + p.total_nodes(); + }, + JsValue::Function(c, _, r) => { + *c = 1 + r.total_nodes(); + }, + + JsValue::Iterated(c, iterable) => { + *c = 1 + iterable.total_nodes(); + }, + + JsValue::TypeOf(c, operand) => { + *c = 1 + operand.total_nodes(); + }, + } + } + + #[cfg(debug_assertions)] + pub fn debug_assert_total_nodes_up_to_date(&mut self) { + let old = self.total_nodes(); + self.update_total_nodes(); + assert_eq!(old, self.total_nodes(), "total nodes not up to date {:?}", self); + } + + #[cfg(not(debug_assertions))] + pub fn debug_assert_total_nodes_up_to_date(&mut self) {} + + pub fn ensure_node_limit(&mut self, limit:usize) { + fn cmp_nodes(a:&JsValue, b:&JsValue) -> Ordering { a.total_nodes().cmp(&b.total_nodes()) } + fn make_max_unknown<'a>(mut iter:impl Iterator) { + let mut max = iter.next().unwrap(); + let mut side_effects = max.has_side_effects(); + for item in iter { + side_effects |= item.has_side_effects(); + if cmp_nodes(item, max) == Ordering::Greater { + max = item; + } + } + max.make_unknown_without_content(side_effects, "node limit reached"); + } + if self.total_nodes() > limit { + match self { + JsValue::Constant(_) + | JsValue::Url(_) + | JsValue::FreeVar(_) + | JsValue::Variable(_) + | JsValue::Module(..) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) + | JsValue::Argument(..) => self.make_unknown_without_content(false, "node limit reached"), + &mut JsValue::Unknown { original_value: _, reason: _, has_side_effects } => { + self.make_unknown_without_content(has_side_effects, "node limit reached") + }, + + JsValue::Array { items: list, .. } + | JsValue::Alternatives(_, list) + | JsValue::Concat(_, list) + | JsValue::Logical(_, _, list) + | JsValue::Add(_, list) => { + make_max_unknown(list.iter_mut()); + self.update_total_nodes(); + }, + JsValue::Not(_, r) => { + r.make_unknown_without_content(false, "node limit reached"); + }, + JsValue::Binary(_, a, _, b) => { + if a.total_nodes() > b.total_nodes() { + a.make_unknown_without_content(b.has_side_effects(), "node limit reached"); + } else { + b.make_unknown_without_content(a.has_side_effects(), "node limit reached"); + } + self.update_total_nodes(); + }, + JsValue::Object { parts, .. } => { + make_max_unknown(parts.iter_mut().flat_map(|v| { + match v { + // TODO this probably can avoid heap allocation somehow + ObjectPart::KeyValue(k, v) => vec![k, v].into_iter(), + ObjectPart::Spread(s) => vec![s].into_iter(), + } + })); + self.update_total_nodes(); + }, + JsValue::Call(_, f, args) => { + make_max_unknown([&mut **f].into_iter().chain(args.iter_mut())); + self.update_total_nodes(); + }, + JsValue::SuperCall(_, args) => { + make_max_unknown(args.iter_mut()); + self.update_total_nodes(); + }, + JsValue::MemberCall(_, o, p, args) => { + make_max_unknown([&mut **o, &mut **p].into_iter().chain(args.iter_mut())); + self.update_total_nodes(); + }, + JsValue::Tenary(_, test, cons, alt) => { + make_max_unknown([&mut **test, &mut **cons, &mut **alt].into_iter()); + self.update_total_nodes(); + }, + JsValue::Iterated(_, iterable) => { + iterable.make_unknown_without_content(false, "node limit reached"); + }, + JsValue::TypeOf(_, operand) => { + operand.make_unknown_without_content(false, "node limit reached"); + }, + JsValue::Member(_, o, p) => { + make_max_unknown([&mut **o, &mut **p].into_iter()); + self.update_total_nodes(); + }, + JsValue::Function(_, _, r) => { + r.make_unknown_without_content(false, "node limit reached"); + }, + } + } + } +} + +// Methods for explaining a value +impl JsValue { + pub fn explain_args(args:&[JsValue], depth:usize, unknown_depth:usize) -> (String, String) { + let mut hints = Vec::new(); + let args = args + .iter() + .map(|arg| arg.explain_internal(&mut hints, 1, depth, unknown_depth)) + .collect::>(); + let explainer = pretty_join(&args, 0, ", ", ",", ""); + ( + explainer, + hints.into_iter().fold(String::new(), |mut out, h| { + let _ = write!(out, "\n{h}"); + out + }), + ) + } + + pub fn explain(&self, depth:usize, unknown_depth:usize) -> (String, String) { + let mut hints = Vec::new(); + let explainer = self.explain_internal(&mut hints, 0, depth, unknown_depth); + ( + explainer, + hints.into_iter().fold(String::new(), |mut out, h| { + let _ = write!(out, "\n{h}"); + out + }), + ) + } + + fn explain_internal_inner( + &self, + hints:&mut Vec, + indent_depth:usize, + depth:usize, + unknown_depth:usize, + ) -> String { + if depth == 0 { + return "...".to_string(); + } + // let i = hints.len(); + + // if explainer.len() < 100 { + self.explain_internal(hints, indent_depth, depth - 1, unknown_depth) + // } + // hints.truncate(i); + // hints.push(String::new()); + // hints[i] = format!( + // "- *{}* {}", + // i, + // self.explain_internal(hints, 1, depth - 1, unknown_depth) + // ); + // format!("*{}*", i) + } + + fn explain_internal( + &self, + hints:&mut Vec, + indent_depth:usize, + depth:usize, + unknown_depth:usize, + ) -> String { + match self { + JsValue::Constant(v) => format!("{v}"), + JsValue::Array { items, mutable, .. } => { + format!( + "{}[{}]", + if *mutable { "" } else { "frozen " }, + pretty_join( + &items + .iter() + .map(|v| { + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth, + ) + }) + .collect::>(), + indent_depth, + ", ", + ",", + "" + ) + ) + }, + JsValue::Object { parts, mutable, .. } => { + format!( + "{}{{{}}}", + if *mutable { "" } else { "frozen " }, + pretty_join( + &parts + .iter() + .map(|v| { + match v { + ObjectPart::KeyValue(key, value) => { + format!( + "{}: {}", + key.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth + ), + value.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth + ) + ) + }, + ObjectPart::Spread(value) => { + format!( + "...{}", + value.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth + ) + ) + }, + } + }) + .collect::>(), + indent_depth, + ", ", + ",", + "" + ) + ) + }, + JsValue::Url(url) => format!("{}", url), + JsValue::Alternatives(_, list) => { + format!( + "({})", + pretty_join( + &list + .iter() + .map(|v| { + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth, + ) + }) + .collect::>(), + indent_depth, + " | ", + "", + "| " + ) + ) + }, + JsValue::FreeVar(name) => format!("FreeVar({})", name), + JsValue::Variable(name) => { + format!("{}", name.0) + }, + JsValue::Argument(_, index) => { + format!("arguments[{}]", index) + }, + JsValue::Concat(_, list) => { + format!( + "`{}`", + list.iter() + .map(|v| { + v.as_str().map_or_else( + || { + format!( + "${{{}}}", + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth + ) + ) + }, + |str| str.to_string(), + ) + }) + .collect::>() + .join("") + ) + }, + JsValue::Add(_, list) => { + format!( + "({})", + pretty_join( + &list + .iter() + .map(|v| { + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth, + ) + }) + .collect::>(), + indent_depth, + " + ", + "", + "+ " + ) + ) + }, + JsValue::Logical(_, op, list) => { + format!( + "({})", + pretty_join( + &list + .iter() + .map(|v| { + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth, + ) + }) + .collect::>(), + indent_depth, + op.joiner(), + "", + op.multi_line_joiner() + ) + ) + }, + JsValue::Binary(_, a, op, b) => { + format!( + "({}{}{})", + a.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + op.joiner(), + b.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + ) + }, + JsValue::Tenary(_, test, cons, alt) => { + format!( + "({} ? {} : {})", + test.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + cons.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + alt.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + ) + }, + JsValue::Not(_, value) => { + format!( + "!({})", + value.explain_internal_inner(hints, indent_depth, depth, unknown_depth) + ) + }, + JsValue::Iterated(_, iterable) => { + format!( + "Iterated({})", + iterable.explain_internal_inner(hints, indent_depth, depth, unknown_depth) + ) + }, + JsValue::TypeOf(_, operand) => { + format!( + "typeof({})", + operand.explain_internal_inner(hints, indent_depth, depth, unknown_depth) + ) + }, + JsValue::Call(_, callee, list) => { + format!( + "{}({})", + callee.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + pretty_join( + &list + .iter() + .map(|v| { + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth, + ) + }) + .collect::>(), + indent_depth, + ", ", + ",", + "" + ) + ) + }, + JsValue::SuperCall(_, list) => { + format!( + "super({})", + pretty_join( + &list + .iter() + .map(|v| { + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth, + ) + }) + .collect::>(), + indent_depth, + ", ", + ",", + "" + ) + ) + }, + JsValue::MemberCall(_, obj, prop, list) => { + format!( + "{}[{}]({})", + obj.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + prop.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + pretty_join( + &list + .iter() + .map(|v| { + v.explain_internal_inner( + hints, + indent_depth + 1, + depth, + unknown_depth, + ) + }) + .collect::>(), + indent_depth, + ", ", + ",", + "" + ) + ) + }, + JsValue::Member(_, obj, prop) => { + format!( + "{}[{}]", + obj.explain_internal_inner(hints, indent_depth, depth, unknown_depth), + prop.explain_internal_inner(hints, indent_depth, depth, unknown_depth) + ) + }, + JsValue::Module(ModuleValue { module: name, annotations }) => { + format!("module<{}, {}>", name, annotations) + }, + JsValue::Unknown { original_value: inner, reason: explainer, has_side_effects } => { + let has_side_effects = *has_side_effects; + if unknown_depth == 0 || explainer.is_empty() { + "???".to_string() + } else if let Some(inner) = inner { + let i = hints.len(); + hints.push(String::new()); + hints[i] = format!( + "- *{}* {}\n âš ï¸ {}{}", + i, + inner.explain_internal(hints, 1, depth, unknown_depth - 1), + explainer, + if has_side_effects { + "\n âš ï¸ This value might have side effects" + } else { + "" + } + ); + format!("???*{}*", i) + } else { + let i = hints.len(); + hints.push(String::new()); + hints[i] = format!( + "- *{}* {}{}", + i, + explainer, + if has_side_effects { + "\n âš ï¸ This value might have side effects" + } else { + "" + } + ); + format!("???*{}*", i) + } + }, + JsValue::WellKnownObject(obj) => { + let (name, explainer) = match obj { + WellKnownObjectKind::GlobalObject => ( + "Object", + "The global Object variable", + ), + WellKnownObjectKind::PathModule | WellKnownObjectKind::PathModuleDefault => ( + "path", + "The Node.js path module: https://nodejs.org/api/path.html", + ), + WellKnownObjectKind::FsModule | WellKnownObjectKind::FsModuleDefault => ( + "fs", + "The Node.js fs module: https://nodejs.org/api/fs.html", + ), + WellKnownObjectKind::FsModulePromises => ( + "fs/promises", + "The Node.js fs module: https://nodejs.org/api/fs.html#promises-api", + ), + WellKnownObjectKind::UrlModule | WellKnownObjectKind::UrlModuleDefault => ( + "url", + "The Node.js url module: https://nodejs.org/api/url.html", + ), + WellKnownObjectKind::ChildProcess | WellKnownObjectKind::ChildProcessDefault => ( + "child_process", + "The Node.js child_process module: https://nodejs.org/api/child_process.html", + ), + WellKnownObjectKind::OsModule | WellKnownObjectKind::OsModuleDefault => ( + "os", + "The Node.js os module: https://nodejs.org/api/os.html", + ), + WellKnownObjectKind::NodeProcess => ( + "process", + "The Node.js process module: https://nodejs.org/api/process.html", + ), + WellKnownObjectKind::NodeProcessArgv => ( + "process.argv", + "The Node.js process.argv property: https://nodejs.org/api/process.html#processargv", + ), + WellKnownObjectKind::NodeProcessEnv => ( + "process.env", + "The Node.js process.env property: https://nodejs.org/api/process.html#processenv", + ), + WellKnownObjectKind::NodePreGyp => ( + "@mapbox/node-pre-gyp", + "The Node.js @mapbox/node-pre-gyp module: https://github.com/mapbox/node-pre-gyp", + ), + WellKnownObjectKind::NodeExpressApp => ( + "express", + "The Node.js express package: https://github.com/expressjs/express" + ), + WellKnownObjectKind::NodeProtobufLoader => ( + "@grpc/proto-loader", + "The Node.js @grpc/proto-loader package: https://github.com/grpc/grpc-node" + ), + WellKnownObjectKind::NodeBuffer => ( + "Buffer", + "The Node.js Buffer object: https://nodejs.org/api/buffer.html#class-buffer" + ), + WellKnownObjectKind::RequireCache => ( + "require.cache", + "The CommonJS require.cache object: https://nodejs.org/api/modules.html#requirecache" + ), + }; + if depth > 0 { + let i = hints.len(); + hints.push(format!("- *{i}* {name}: {explainer}")); + format!("{name}*{i}*") + } else { + name.to_string() + } + }, + JsValue::WellKnownFunction(func) => { + let (name, explainer) = match func { + WellKnownFunctionKind::ObjectAssign => ( + "Object.assign".to_string(), + "Object.assign method: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign", + ), + WellKnownFunctionKind::PathJoin => ( + "path.join".to_string(), + "The Node.js path.join method: https://nodejs.org/api/path.html#pathjoinpaths", + ), + WellKnownFunctionKind::PathDirname => ( + "path.dirname".to_string(), + "The Node.js path.dirname method: https://nodejs.org/api/path.html#pathdirnamepath", + ), + WellKnownFunctionKind::PathResolve(cwd) => ( + format!("path.resolve({cwd})"), + "The Node.js path.resolve method: https://nodejs.org/api/path.html#pathresolvepaths", + ), + WellKnownFunctionKind::Import => ( + "import".to_string(), + "The dynamic import() method from the ESM specification: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports" + ), + WellKnownFunctionKind::Require => ("require".to_string(), "The require method from CommonJS"), + WellKnownFunctionKind::RequireResolve => ("require.resolve".to_string(), "The require.resolve method from CommonJS"), + WellKnownFunctionKind::RequireContext => ("require.context".to_string(), "The require.context method from webpack"), + WellKnownFunctionKind::RequireContextRequire(..) => ("require.context(...)".to_string(), "The require.context(...) method from webpack: https://webpack.js.org/api/module-methods/#requirecontext"), + WellKnownFunctionKind::RequireContextRequireKeys(..) => ("require.context(...).keys".to_string(), "The require.context(...).keys method from webpack: https://webpack.js.org/guides/dependency-management/#requirecontext"), + WellKnownFunctionKind::RequireContextRequireResolve(..) => ("require.context(...).resolve".to_string(), "The require.context(...).resolve method from webpack: https://webpack.js.org/guides/dependency-management/#requirecontext"), + WellKnownFunctionKind::Define => ("define".to_string(), "The define method from AMD"), + WellKnownFunctionKind::FsReadMethod(name) => ( + format!("fs.{name}"), + "A file reading method from the Node.js fs module: https://nodejs.org/api/fs.html", + ), + WellKnownFunctionKind::PathToFileUrl => ( + "url.pathToFileURL".to_string(), + "The Node.js url.pathToFileURL method: https://nodejs.org/api/url.html#urlpathtofileurlpath", + ), + WellKnownFunctionKind::ChildProcessSpawnMethod(name) => ( + format!("child_process.{name}"), + "A process spawning method from the Node.js child_process module: https://nodejs.org/api/child_process.html", + ), + WellKnownFunctionKind::ChildProcessFork => ( + "child_process.fork".to_string(), + "The Node.js child_process.fork method: https://nodejs.org/api/child_process.html#child_processforkmodulepath-args-options", + ), + WellKnownFunctionKind::OsArch => ( + "os.arch".to_string(), + "The Node.js os.arch method: https://nodejs.org/api/os.html#os_os_arch", + ), + WellKnownFunctionKind::OsPlatform => ( + "os.process".to_string(), + "The Node.js os.process method: https://nodejs.org/api/os.html#os_os_process", + ), + WellKnownFunctionKind::OsEndianness => ( + "os.endianness".to_string(), + "The Node.js os.endianness method: https://nodejs.org/api/os.html#os_os_endianness", + ), + WellKnownFunctionKind::ProcessCwd => ( + "process.cwd".to_string(), + "The Node.js process.cwd method: https://nodejs.org/api/process.html#processcwd", + ), + WellKnownFunctionKind::NodePreGypFind => ( + "find".to_string(), + "The Node.js @mapbox/node-pre-gyp module: https://github.com/mapbox/node-pre-gyp", + ), + WellKnownFunctionKind::NodeGypBuild => ( + "node-gyp-build".to_string(), + "The Node.js node-gyp-build module: https://github.com/prebuild/node-gyp-build" + ), + WellKnownFunctionKind::NodeBindings => ( + "bindings".to_string(), + "The Node.js bindings module: https://github.com/TooTallNate/node-bindings" + ), + WellKnownFunctionKind::NodeExpress => ( + "express".to_string(), + "require('express')() : https://github.com/expressjs/express" + ), + WellKnownFunctionKind::NodeExpressSet => ( + "set".to_string(), + "require('express')().set('view engine', 'jade') https://github.com/expressjs/express" + ), + WellKnownFunctionKind::NodeStrongGlobalize => ( + "SetRootDir".to_string(), + "require('strong-globalize')() https://github.com/strongloop/strong-globalize" + ), + WellKnownFunctionKind::NodeStrongGlobalizeSetRootDir => ( + "SetRootDir".to_string(), + "require('strong-globalize').SetRootDir(__dirname) https://github.com/strongloop/strong-globalize" + ), + WellKnownFunctionKind::NodeResolveFrom => ( + "resolveFrom".to_string(), + "require('resolve-from')(__dirname, 'node-gyp/bin/node-gyp') https://github.com/sindresorhus/resolve-from" + ), + WellKnownFunctionKind::NodeProtobufLoad => ( + "load/loadSync".to_string(), + "require('@grpc/proto-loader').load(filepath, { includeDirs: [root] }) https://github.com/grpc/grpc-node" + ), + }; + if depth > 0 { + let i = hints.len(); + hints.push(format!("- *{i}* {name}: {explainer}")); + format!("{name}*{i}*") + } else { + name + } + }, + JsValue::Function(_, _, return_value) => { + if depth > 0 { + format!( + "(...) => {}", + return_value.explain_internal( + hints, + indent_depth, + depth - 1, + unknown_depth + ) + ) + } else { + "(...) => ...".to_string() + } + }, + } + } +} + +// Unknown management +impl JsValue { + /// Convert the value into unknown with a specific reason. + pub fn make_unknown(&mut self, side_effects:bool, reason:impl Into>) { + *self = JsValue::unknown(take(self), side_effects || self.has_side_effects(), reason); + } + + /// Convert the owned value into unknown with a specific reason. + pub fn into_unknown(mut self, side_effects:bool, reason:impl Into>) -> Self { + self.make_unknown(side_effects, reason); + self + } + + /// Convert the value into unknown with a specific reason, but don't retain + /// the original value. + pub fn make_unknown_without_content( + &mut self, + side_effects:bool, + reason:impl Into>, + ) { + *self = JsValue::unknown_empty(side_effects || self.has_side_effects(), reason); + } + + /// Make all nested operations unknown when the value is an operation. + pub fn make_nested_operations_unknown(&mut self) -> bool { + fn inner(this:&mut JsValue) -> bool { + if matches!(this.meta_type(), JsValueMetaKind::Operation) { + this.make_unknown(false, "nested operation"); + true + } else { + this.for_each_children_mut(&mut inner) + } + } + if matches!(self.meta_type(), JsValueMetaKind::Operation) { + self.for_each_children_mut(&mut inner) + } else { + false + } + } + + pub fn add_unknown_mutations(&mut self, side_effects:bool) { + self.add_alt(JsValue::unknown_empty(side_effects, "unknown mutation")); + } +} + +// Defineable name management +impl JsValue { + /// When the value has a user-defineable name, return the length of it (in + /// segments). Otherwise returns None. + /// - any free var has itself as user-defineable name. + /// - any member access adds the identifier as segement to the name of the + /// object. + /// - some well-known objects/functions have a user-defineable names. + /// - member calls without arguments also have a user-defineable name which + /// is the property with `()` appended. + pub fn get_defineable_name_len(&self) -> Option { + match self { + JsValue::FreeVar(_) => Some(1), + JsValue::Member(_, obj, prop) if prop.as_str().is_some() => { + Some(obj.get_defineable_name_len()? + 1) + }, + JsValue::WellKnownObject(obj) => obj.as_define_name().map(|d| d.len()), + JsValue::WellKnownFunction(func) => func.as_define_name().map(|d| d.len()), + JsValue::MemberCall(_, callee, prop, args) + if args.is_empty() && prop.as_str().is_some() => + { + Some(callee.get_defineable_name_len()? + 1) + }, + + _ => None, + } + } + + /// Returns a reverse iterator over the segments of the user-defineable + /// name. e. g. `foo.bar().baz` would yield `baz`, `bar()`, `foo`. + /// `(1+2).foo.baz` would also yield `baz`, `foo` even while the value is + /// not a complete user-defineable name. Before calling this method you must + /// use [JsValue::get_defineable_name_len] to determine if the value has a + /// user-defineable name at all. + pub fn iter_defineable_name_rev(&self) -> DefineableNameIter<'_> { + DefineableNameIter { next:Some(self), index:0 } + } +} + +pub struct DefineableNameIter<'a> { + next:Option<&'a JsValue>, + index:usize, +} + +impl<'a> Iterator for DefineableNameIter<'a> { + type Item = Cow<'a, str>; + + fn next(&mut self) -> Option { + let value = self.next.take()?; + Some(match value { + JsValue::FreeVar(kind) => (&**kind).into(), + JsValue::Member(_, obj, prop) => { + self.next = Some(obj); + prop.as_str()?.into() + }, + JsValue::WellKnownObject(obj) => { + let name = obj.as_define_name()?; + let i = self.index; + self.index += 1; + if self.index < name.len() { + self.next = Some(value); + } + name[name.len() - i - 1].into() + }, + JsValue::WellKnownFunction(func) => { + let name = func.as_define_name()?; + let i = self.index; + self.index += 1; + if self.index < name.len() { + self.next = Some(value); + } + name[name.len() - i - 1].into() + }, + JsValue::MemberCall(_, callee, prop, args) if args.is_empty() => { + self.next = Some(callee); + format!("{}()", prop.as_str()?).into() + }, + _ => return None, + }) + } +} + +// Compile-time information gathering +impl JsValue { + /// Returns the constant string if the value represents a constant string. + pub fn as_str(&self) -> Option<&str> { + match self { + JsValue::Constant(c) => c.as_str(), + _ => None, + } + } + + /// Returns the constant bool if the value represents a constant boolean. + pub fn as_bool(&self) -> Option { + match self { + JsValue::Constant(c) => c.as_bool(), + _ => None, + } + } + + pub fn has_side_effects(&self) -> bool { + match self { + JsValue::Constant(_) => false, + JsValue::Concat(_, list) + | JsValue::Add(_, list) + | JsValue::Logical(_, _, list) + | JsValue::Alternatives(_, list) => list.iter().any(JsValue::has_side_effects), + JsValue::Binary(_, a, _, b) => a.has_side_effects() || b.has_side_effects(), + JsValue::Tenary(_, test, cons, alt) => { + test.has_side_effects() || cons.has_side_effects() || alt.has_side_effects() + }, + JsValue::Not(_, value) => value.has_side_effects(), + JsValue::Array { items, .. } => items.iter().any(JsValue::has_side_effects), + JsValue::Object { parts, .. } => { + parts.iter().any(|v| { + match v { + ObjectPart::KeyValue(k, v) => k.has_side_effects() || v.has_side_effects(), + ObjectPart::Spread(v) => v.has_side_effects(), + } + }) + }, + JsValue::Call(_, callee, args) => { + callee.has_side_effects() || args.iter().any(JsValue::has_side_effects) + }, + JsValue::SuperCall(_, args) => args.iter().any(JsValue::has_side_effects), + JsValue::MemberCall(_, obj, prop, args) => { + obj.has_side_effects() + || prop.has_side_effects() + || args.iter().any(JsValue::has_side_effects) + }, + JsValue::Member(_, obj, prop) => obj.has_side_effects() || prop.has_side_effects(), + JsValue::Function(..) => false, + JsValue::Url(_) => false, + JsValue::Variable(_) => false, + JsValue::Module(_) => false, + JsValue::WellKnownObject(_) => false, + JsValue::WellKnownFunction(_) => false, + JsValue::FreeVar(_) => false, + JsValue::Unknown { has_side_effects, .. } => *has_side_effects, + JsValue::Argument(..) => false, + JsValue::Iterated(_, iterable) => iterable.has_side_effects(), + JsValue::TypeOf(_, operand) => operand.has_side_effects(), + } + } + + /// Checks if the value is truthy. Returns None if we don't know. Returns + /// Some if we know if or if not the value is truthy. + pub fn is_truthy(&self) -> Option { + match self { + JsValue::Constant(c) => Some(c.is_truthy()), + JsValue::Concat(..) => self.is_empty_string().map(|x| !x), + JsValue::Url(..) + | JsValue::Array { .. } + | JsValue::Object { .. } + | JsValue::WellKnownObject(..) + | JsValue::WellKnownFunction(..) + | JsValue::Function(..) => Some(true), + JsValue::Alternatives(_, list) => merge_if_known(list, JsValue::is_truthy), + JsValue::Not(_, value) => value.is_truthy().map(|x| !x), + JsValue::Logical(_, op, list) => { + match op { + LogicalOperator::And => all_if_known(list, JsValue::is_truthy), + LogicalOperator::Or => any_if_known(list, JsValue::is_truthy), + LogicalOperator::NullishCoalescing => { + shortcircuit_if_known(list, JsValue::is_not_nullish, JsValue::is_truthy) + }, + } + }, + JsValue::Binary(_, box a, op, box b) => { + let (positive_op, negate) = op.positive_op(); + match (positive_op, a, b) { + ( + PositiveBinaryOperator::StrictEqual, + JsValue::Constant(a), + JsValue::Constant(b), + ) if a.is_value_type() => Some(a == b), + ( + PositiveBinaryOperator::StrictEqual, + JsValue::Constant(a), + JsValue::Constant(b), + ) if a.is_value_type() => { + let same_type = { + use ConstantValue::*; + matches!( + (a, b), + (Num(_), Num(_)) + | (Str(_), Str(_)) | (BigInt(_), BigInt(_)) + | (True | False, True | False) + | (Undefined, Undefined) | (Null, Null) + ) + }; + if same_type { Some(a == b) } else { None } + }, + ( + PositiveBinaryOperator::Equal, + JsValue::Constant(ConstantValue::Str(a)), + JsValue::Constant(ConstantValue::Str(b)), + ) => Some(a == b), + ( + PositiveBinaryOperator::Equal, + JsValue::Constant(ConstantValue::Num(a)), + JsValue::Constant(ConstantValue::Num(b)), + ) => Some(a == b), + _ => None, + } + .map(|x| x ^ negate) + }, + _ => None, + } + } + + /// Checks if the value is falsy. Returns None if we don't know. Returns + /// Some if we know if or if not the value is falsy. + pub fn is_falsy(&self) -> Option { self.is_truthy().map(|x| !x) } + + /// Checks if the value is nullish (null or undefined). Returns None if we + /// don't know. Returns Some if we know if or if not the value is nullish. + pub fn is_nullish(&self) -> Option { + match self { + JsValue::Constant(c) => Some(c.is_nullish()), + JsValue::Concat(..) + | JsValue::Url(..) + | JsValue::Array { .. } + | JsValue::Object { .. } + | JsValue::WellKnownObject(..) + | JsValue::WellKnownFunction(..) + | JsValue::Not(..) + | JsValue::Binary(..) + | JsValue::Function(..) => Some(false), + JsValue::Alternatives(_, list) => merge_if_known(list, JsValue::is_nullish), + JsValue::Logical(_, op, list) => { + match op { + LogicalOperator::And => { + shortcircuit_if_known(list, JsValue::is_truthy, JsValue::is_nullish) + }, + LogicalOperator::Or => { + shortcircuit_if_known(list, JsValue::is_falsy, JsValue::is_nullish) + }, + LogicalOperator::NullishCoalescing => all_if_known(list, JsValue::is_nullish), + } + }, + _ => None, + } + } + + /// Checks if we know that the value is not nullish. Returns None if we + /// don't know. Returns Some if we know if or if not the value is not + /// nullish. + pub fn is_not_nullish(&self) -> Option { self.is_nullish().map(|x| !x) } + + /// Checks if we know that the value is an empty string. Returns None if we + /// don't know. Returns Some if we know if or if not the value is an empty + /// string. + pub fn is_empty_string(&self) -> Option { + match self { + JsValue::Constant(c) => Some(c.is_empty_string()), + JsValue::Concat(_, list) => all_if_known(list, JsValue::is_empty_string), + JsValue::Alternatives(_, list) => merge_if_known(list, JsValue::is_empty_string), + JsValue::Logical(_, op, list) => { + match op { + LogicalOperator::And => { + shortcircuit_if_known(list, JsValue::is_truthy, JsValue::is_empty_string) + }, + LogicalOperator::Or => { + shortcircuit_if_known(list, JsValue::is_falsy, JsValue::is_empty_string) + }, + LogicalOperator::NullishCoalescing => { + shortcircuit_if_known( + list, + JsValue::is_not_nullish, + JsValue::is_empty_string, + ) + }, + } + }, + // Booleans are not empty strings + JsValue::Not(..) | JsValue::Binary(..) => Some(false), + // Objects are not empty strings + JsValue::Url(..) + | JsValue::Array { .. } + | JsValue::Object { .. } + | JsValue::WellKnownObject(..) + | JsValue::WellKnownFunction(..) + | JsValue::Function(..) => Some(false), + _ => None, + } + } + + /// Returns true, if the value is unknown and storing it as condition + /// doesn't make sense. This is for optimization purposes. + pub fn is_unknown(&self) -> bool { + match self { + JsValue::Unknown { .. } => true, + JsValue::Alternatives(_, list) => list.iter().any(|x| x.is_unknown()), + _ => false, + } + } + + /// Checks if we know that the value is a string. Returns None if we + /// don't know. Returns Some if we know if or if not the value is a string. + pub fn is_string(&self) -> Option { + match self { + JsValue::Constant(ConstantValue::Str(..)) + | JsValue::Concat(..) + | JsValue::TypeOf(..) => Some(true), + + // Objects are not strings + JsValue::Constant(..) + | JsValue::Array { .. } + | JsValue::Object { .. } + | JsValue::Url(..) + | JsValue::Module(..) + | JsValue::Function(..) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) => Some(false), + + // Booleans are not strings + JsValue::Not(..) | JsValue::Binary(..) => Some(false), + + JsValue::Add(_, list) => any_if_known(list, JsValue::is_string), + JsValue::Logical(_, op, list) => { + match op { + LogicalOperator::And => { + shortcircuit_if_known(list, JsValue::is_truthy, JsValue::is_string) + }, + LogicalOperator::Or => { + shortcircuit_if_known(list, JsValue::is_falsy, JsValue::is_string) + }, + LogicalOperator::NullishCoalescing => { + shortcircuit_if_known(list, JsValue::is_not_nullish, JsValue::is_string) + }, + } + }, + + JsValue::Alternatives(_, v) => merge_if_known(v, JsValue::is_string), + + JsValue::Call( + _, + box JsValue::WellKnownFunction( + WellKnownFunctionKind::RequireResolve + | WellKnownFunctionKind::PathJoin + | WellKnownFunctionKind::PathResolve(..) + | WellKnownFunctionKind::OsArch + | WellKnownFunctionKind::OsPlatform + | WellKnownFunctionKind::PathDirname + | WellKnownFunctionKind::PathToFileUrl + | WellKnownFunctionKind::ProcessCwd, + ), + _, + ) => Some(true), + + JsValue::FreeVar(..) + | JsValue::Variable(_) + | JsValue::Unknown { .. } + | JsValue::Argument(..) + | JsValue::Call(..) + | JsValue::MemberCall(..) + | JsValue::Member(..) + | JsValue::Tenary(..) + | JsValue::SuperCall(..) + | JsValue::Iterated(..) => None, + } + } + + /// Checks if we know that the value starts with a given string. Returns + /// None if we don't know. Returns Some if we know if or if not the + /// value starts with the given string. + pub fn starts_with(&self, str:&str) -> Option { + if let Some(s) = self.as_str() { + return Some(s.starts_with(str)); + } + match self { + JsValue::Alternatives(_, alts) => merge_if_known(alts, |a| a.starts_with(str)), + JsValue::Concat(_, list) => { + if let Some(item) = list.iter().next() { + if item.starts_with(str) == Some(true) { + Some(true) + } else if let Some(s) = item.as_str() { + if str.starts_with(s) { None } else { Some(false) } + } else { + None + } + } else { + Some(false) + } + }, + + _ => None, + } + } + + /// Checks if we know that the value ends with a given string. Returns + /// None if we don't know. Returns Some if we know if or if not the + /// value ends with the given string. + pub fn ends_with(&self, str:&str) -> Option { + if let Some(s) = self.as_str() { + return Some(s.ends_with(str)); + } + match self { + JsValue::Alternatives(_, alts) => merge_if_known(alts, |alt| alt.ends_with(str)), + JsValue::Concat(_, list) => { + if let Some(item) = list.last() { + if item.ends_with(str) == Some(true) { + Some(true) + } else if let Some(s) = item.as_str() { + if str.ends_with(s) { None } else { Some(false) } + } else { + None + } + } else { + Some(false) + } + }, + + _ => None, + } + } +} + +/// Compute the compile-time value of all elements of the list. If all evaluate +/// to the same value return that. Otherwise return None. +fn merge_if_known( + list:impl IntoIterator, + func:impl Fn(T) -> Option, +) -> Option { + let mut current = None; + for item in list.into_iter().map(func) { + if item.is_some() { + if current.is_none() { + current = item; + } else if current != item { + return None; + } + } else { + return None; + } + } + current +} + +/// Evaluates all elements of the list and returns Some(true) if all elements +/// are compile-time true. If any element is compile-time false, return +/// Some(false). Otherwise return None. +fn all_if_known( + list:impl IntoIterator, + func:impl Fn(T) -> Option, +) -> Option { + let mut unknown = false; + for item in list.into_iter().map(func) { + match item { + Some(false) => return Some(false), + None => unknown = true, + _ => {}, + } + } + if unknown { None } else { Some(true) } +} + +/// Evaluates all elements of the list and returns Some(true) if any element is +/// compile-time true. If all elements are compile-time false, return +/// Some(false). Otherwise return None. +fn any_if_known( + list:impl IntoIterator, + func:impl Fn(T) -> Option, +) -> Option { + all_if_known(list, |x| func(x).map(|x| !x)).map(|x| !x) +} + +/// Selects the first element of the list where `use_item` is compile-time true. +/// For this element returns the result of `item_value`. Otherwise returns None. +fn shortcircuit_if_known( + list:impl IntoIterator, + use_item:impl Fn(T) -> Option, + item_value:impl FnOnce(T) -> Option, +) -> Option { + let mut it = list.into_iter().peekable(); + while let Some(item) = it.next() { + if it.peek().is_none() { + return item_value(item); + } else { + match use_item(item) { + Some(true) => return item_value(item), + None => return None, + _ => {}, + } + } + } + None +} + +/// Macro to visit all children of a node with an async function +macro_rules! for_each_children_async { + ($value:expr, $visit_fn:expr, $($args:expr),+) => { + Ok(match &mut $value { + JsValue::Alternatives(_, list) + | JsValue::Concat(_, list) + | JsValue::Add(_, list) + | JsValue::Logical(_, _, list) + | JsValue::Array{ items: list, ..} => { + let mut modified = false; + for item in list.iter_mut() { + let (v, m) = $visit_fn(take(item), $($args),+).await?; + *item = v; + if m { + modified = true + } + } + $value.update_total_nodes(); + ($value, modified) + } + JsValue::Object{ parts, ..} => { + let mut modified = false; + for item in parts.iter_mut() { + match item { + ObjectPart::KeyValue(key, value) => { + let (v, m) = $visit_fn(take(key), $($args),+).await?; + *key = v; + if m { + modified = true + } + let (v, m) = $visit_fn(take(value), $($args),+).await?; + *value = v; + if m { + modified = true + } + } + ObjectPart::Spread(value) => { + let (v, m) = $visit_fn(take(value), $($args),+).await?; + *value = v; + if m { + modified = true + } + } + } + + } + $value.update_total_nodes(); + ($value, modified) + } + JsValue::Call(_, box callee, list) => { + let (new_callee, mut modified) = $visit_fn(take(callee), $($args),+).await?; + *callee = new_callee; + for item in list.iter_mut() { + let (v, m) = $visit_fn(take(item), $($args),+).await?; + *item = v; + if m { + modified = true + } + } + $value.update_total_nodes(); + ($value, modified) + } + JsValue::SuperCall(_, list) => { + let mut modified = false; + for item in list.iter_mut() { + let (v, m) = $visit_fn(take(item), $($args),+).await?; + *item = v; + if m { + modified = true + } + } + $value.update_total_nodes(); + ($value, modified) + } + JsValue::MemberCall(_, box obj, box prop, list) => { + let (new_callee, m1) = $visit_fn(take(obj), $($args),+).await?; + *obj = new_callee; + let (new_member, m2) = $visit_fn(take(prop), $($args),+).await?; + *prop = new_member; + let mut modified = m1 || m2; + for item in list.iter_mut() { + let (v, m) = $visit_fn(take(item), $($args),+).await?; + *item = v; + if m { + modified = true + } + } + $value.update_total_nodes(); + ($value, modified) + } + + JsValue::Function(_, _, box return_value) => { + let (new_return_value, modified) = $visit_fn(take(return_value), $($args),+).await?; + *return_value = new_return_value; + + $value.update_total_nodes(); + ($value, modified) + } + JsValue::Not(_, box value) => { + let (new_value, modified) = $visit_fn(take(value), $($args),+).await?; + *value = new_value; + + $value.update_total_nodes(); + ($value, modified) + } + JsValue::Binary(_, box a, _, box b) => { + let (v, m1) = $visit_fn(take(a), $($args),+).await?; + *a = v; + let (v, m2) = $visit_fn(take(b), $($args),+).await?; + *b = v; + $value.update_total_nodes(); + ($value, m1 || m2) + } + JsValue::Tenary(_, box test, box cons, box alt) => { + let (v, m1) = $visit_fn(take(test), $($args),+).await?; + *test = v; + let (v, m2) = $visit_fn(take(cons), $($args),+).await?; + *cons = v; + let (v, m3) = $visit_fn(take(alt), $($args),+).await?; + *alt = v; + $value.update_total_nodes(); + ($value, m1 || m2 || m3) + } + JsValue::Member(_, box obj, box prop) => { + let (v, m1) = $visit_fn(take(obj), $($args),+).await?; + *obj = v; + let (v, m2) = $visit_fn(take(prop), $($args),+).await?; + *prop = v; + $value.update_total_nodes(); + ($value, m1 || m2) + } + JsValue::Iterated(_, box iterable) => { + let (new_iterable, modified) = $visit_fn(take(iterable), $($args),+).await?; + *iterable = new_iterable; + + $value.update_total_nodes(); + ($value, modified) + } + JsValue::TypeOf(_, box operand) => { + let (new_operand, modified) = $visit_fn(take(operand), $($args),+).await?; + *operand = new_operand; + + $value.update_total_nodes(); + ($value, modified) + } + JsValue::Constant(_) + | JsValue::FreeVar(_) + | JsValue::Variable(_) + | JsValue::Module(..) + | JsValue::Url(_) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) + | JsValue::Unknown { .. } + | JsValue::Argument(..) => ($value, false), + }) + } +} + +// Visiting +impl JsValue { + /// Visit the node and all its children with a function in a loop until the + /// visitor returns false for the node and all children + pub async fn visit_async_until_settled<'a, F, R, E>( + self, + visitor:&mut F, + ) -> Result<(Self, bool), E> + where + R: 'a + Future> + Send, + F: 'a + FnMut(JsValue) -> R + Send, { + let mut modified = false; + let mut v = self; + loop { + let m; + (v, m) = visitor(take(&mut v)).await?; + if !m { + break; + } + modified = true; + v = take(&mut v).visit_each_children_async_until_settled(visitor).await?; + } + Ok((v, modified)) + } + + /// Visit all children of the node with an async function in a loop until + /// the visitor returns false + pub async fn visit_each_children_async_until_settled<'a, F, R, E>( + mut self, + visitor:&mut F, + ) -> Result + where + R: 'a + Future> + Send, + F: 'a + FnMut(JsValue) -> R + Send, { + fn visit_async_until_settled_box<'a, F, R, E>( + value:JsValue, + visitor:&'a mut F, + ) -> PinnedAsyncUntilSettledBox + where + R: 'a + Future> + Send, + F: 'a + FnMut(JsValue) -> R + Send, + E: 'a, { + Box::pin(value.visit_async_until_settled(visitor)) + } + let (v, _) = for_each_children_async!(self, visit_async_until_settled_box, visitor)?; + Ok(v) + } + + /// Visit the node and all its children with an async function. + pub async fn visit_async<'a, F, R, E>(self, visitor:&mut F) -> Result<(Self, bool), E> + where + R: 'a + Future>, + F: 'a + FnMut(JsValue) -> R, { + let (v, modified) = self.visit_each_children_async(visitor).await?; + let (v, m) = visitor(v).await?; + if m { Ok((v, true)) } else { Ok((v, modified)) } + } + + /// Visit all children of the node with an async function. + pub async fn visit_each_children_async<'a, F, R, E>( + mut self, + visitor:&mut F, + ) -> Result<(Self, bool), E> + where + R: 'a + Future>, + F: 'a + FnMut(JsValue) -> R, { + fn visit_async_box<'a, F, R, E>(value:JsValue, visitor:&'a mut F) -> PinnedAsyncBox + where + R: 'a + Future>, + F: 'a + FnMut(JsValue) -> R, + E: 'a, { + Box::pin(value.visit_async(visitor)) + } + for_each_children_async!(self, visit_async_box, visitor) + } + + /// Call an async function for each child of the node. + pub async fn for_each_children_async<'a, F, R, E>( + mut self, + visitor:&mut F, + ) -> Result<(Self, bool), E> + where + R: 'a + Future>, + F: 'a + FnMut(JsValue) -> R, { + for_each_children_async!(self, |v, ()| visitor(v), ()) + } + + /// Visit the node and all its children with a function in a loop until the + /// visitor returns false + pub fn visit_mut_until_settled(&mut self, visitor:&mut impl FnMut(&mut JsValue) -> bool) { + while visitor(self) { + self.for_each_children_mut(&mut |value| { + value.visit_mut_until_settled(visitor); + false + }); + } + } + + /// Visit the node and all its children with a function. + pub fn visit_mut(&mut self, visitor:&mut impl FnMut(&mut JsValue) -> bool) -> bool { + let modified = self.for_each_children_mut(&mut |value| value.visit_mut(visitor)); + if visitor(self) { true } else { modified } + } + + /// Visit all children of the node with a function. Only visits nodes where + /// the condition is true. + pub fn visit_mut_conditional( + &mut self, + condition:impl Fn(&JsValue) -> bool, + visitor:&mut impl FnMut(&mut JsValue) -> bool, + ) -> bool { + if condition(self) { + let modified = self.for_each_children_mut(&mut |value| value.visit_mut(visitor)); + if visitor(self) { true } else { modified } + } else { + false + } + } + + /// Calls a function for each child of the node. Allows mutating the node. + /// Updates the total nodes count after mutation. + pub fn for_each_children_mut(&mut self, visitor:&mut impl FnMut(&mut JsValue) -> bool) -> bool { + match self { + JsValue::Alternatives(_, list) + | JsValue::Concat(_, list) + | JsValue::Add(_, list) + | JsValue::Logical(_, _, list) + | JsValue::Array { items: list, .. } => { + let mut modified = false; + for item in list.iter_mut() { + if visitor(item) { + modified = true + } + } + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Not(_, value) => { + let modified = visitor(value); + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Object { parts, .. } => { + let mut modified = false; + for item in parts.iter_mut() { + match item { + ObjectPart::KeyValue(key, value) => { + if visitor(key) { + modified = true + } + if visitor(value) { + modified = true + } + }, + ObjectPart::Spread(value) => { + if visitor(value) { + modified = true + } + }, + } + } + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Call(_, callee, list) => { + let mut modified = visitor(callee); + for item in list.iter_mut() { + if visitor(item) { + modified = true + } + } + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::SuperCall(_, list) => { + let mut modified = false; + for item in list.iter_mut() { + if visitor(item) { + modified = true + } + } + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::MemberCall(_, obj, prop, list) => { + let m1 = visitor(obj); + let m2 = visitor(prop); + let mut modified = m1 || m2; + for item in list.iter_mut() { + if visitor(item) { + modified = true + } + } + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Function(_, _, return_value) => { + let modified = visitor(return_value); + + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Binary(_, a, _, b) => { + let m1 = visitor(a); + let m2 = visitor(b); + let modified = m1 || m2; + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Tenary(_, test, cons, alt) => { + let m1 = visitor(test); + let m2 = visitor(cons); + let m3 = visitor(alt); + let modified = m1 || m2 || m3; + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Member(_, obj, prop) => { + let m1 = visitor(obj); + let m2 = visitor(prop); + let modified = m1 || m2; + if modified { + self.update_total_nodes(); + } + modified + }, + + JsValue::Iterated(_, iterable) => { + let modified = visitor(iterable); + if modified { + self.update_total_nodes(); + } + modified + }, + + JsValue::TypeOf(_, operand) => { + let modified = visitor(operand); + if modified { + self.update_total_nodes(); + } + modified + }, + + JsValue::Constant(_) + | JsValue::FreeVar(_) + | JsValue::Variable(_) + | JsValue::Module(..) + | JsValue::Url(_) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) + | JsValue::Unknown { .. } + | JsValue::Argument(..) => false, + } + } + + /// Calls a function for only early children. Allows mutating the + /// node. Updates the total nodes count after mutation. + pub fn for_each_early_children_mut( + &mut self, + visitor:&mut impl FnMut(&mut JsValue) -> bool, + ) -> bool { + match self { + JsValue::Call(_, callee, list) if !list.is_empty() => { + let m = visitor(callee); + if m { + self.update_total_nodes(); + } + m + }, + JsValue::MemberCall(_, obj, prop, list) if !list.is_empty() => { + let m1 = visitor(obj); + let m2 = visitor(prop); + let modified = m1 || m2; + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Member(_, obj, _) => { + let m = visitor(obj); + if m { + self.update_total_nodes(); + } + m + }, + _ => false, + } + } + + /// Calls a function for only late children. Allows mutating the + /// node. Updates the total nodes count after mutation. + pub fn for_each_late_children_mut( + &mut self, + visitor:&mut impl FnMut(&mut JsValue) -> bool, + ) -> bool { + match self { + JsValue::Call(_, _, list) if !list.is_empty() => { + let mut modified = false; + for item in list.iter_mut() { + if visitor(item) { + modified = true + } + } + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::MemberCall(_, _, _, list) if !list.is_empty() => { + let mut modified = false; + for item in list.iter_mut() { + if visitor(item) { + modified = true + } + } + if modified { + self.update_total_nodes(); + } + modified + }, + JsValue::Member(_, _, prop) => { + let m = visitor(prop); + if m { + self.update_total_nodes(); + } + m + }, + _ => self.for_each_children_mut(visitor), + } + } + + /// Visit the node and all its children with a function. + pub fn visit(&self, visitor:&mut impl FnMut(&JsValue)) { + self.for_each_children(&mut |value| value.visit(visitor)); + visitor(self); + } + + /// Calls a function for all children of the node. + pub fn for_each_children(&self, visitor:&mut impl FnMut(&JsValue)) { + match self { + JsValue::Alternatives(_, list) + | JsValue::Concat(_, list) + | JsValue::Add(_, list) + | JsValue::Logical(_, _, list) + | JsValue::Array { items: list, .. } => { + for item in list.iter() { + visitor(item); + } + }, + JsValue::Not(_, value) => { + visitor(value); + }, + JsValue::Object { parts, .. } => { + for item in parts.iter() { + match item { + ObjectPart::KeyValue(key, value) => { + visitor(key); + visitor(value); + }, + ObjectPart::Spread(value) => { + visitor(value); + }, + } + } + }, + JsValue::Call(_, callee, list) => { + visitor(callee); + for item in list.iter() { + visitor(item); + } + }, + JsValue::SuperCall(_, list) => { + for item in list.iter() { + visitor(item); + } + }, + JsValue::MemberCall(_, obj, prop, list) => { + visitor(obj); + visitor(prop); + for item in list.iter() { + visitor(item); + } + }, + JsValue::Function(_, _, return_value) => { + visitor(return_value); + }, + JsValue::Member(_, obj, prop) => { + visitor(obj); + visitor(prop); + }, + JsValue::Binary(_, a, _, b) => { + visitor(a); + visitor(b); + }, + JsValue::Tenary(_, test, cons, alt) => { + visitor(test); + visitor(cons); + visitor(alt); + }, + + JsValue::Iterated(_, iterable) => { + visitor(iterable); + }, + + JsValue::TypeOf(_, operand) => { + visitor(operand); + }, + + JsValue::Constant(_) + | JsValue::FreeVar(_) + | JsValue::Variable(_) + | JsValue::Module(..) + | JsValue::Url(_) + | JsValue::WellKnownObject(_) + | JsValue::WellKnownFunction(_) + | JsValue::Unknown { .. } + | JsValue::Argument(..) => {}, + } + } +} + +// Alternatives management +impl JsValue { + /// Add an alternative to the current value. Might be a no-op if the value + /// already contains this alternative. Potentially expensive operation + /// as it has to compare the value with all existing alternatives. + fn add_alt(&mut self, v:Self) { + if self == &v { + return; + } + + if let JsValue::Alternatives(c, list) = self { + if !list.contains(&v) { + *c += v.total_nodes(); + list.push(v); + } + } else { + let l = take(self); + *self = JsValue::Alternatives(1 + l.total_nodes() + v.total_nodes(), vec![l, v]); + } + } +} + +// Normalization +impl JsValue { + /// Normalizes only the current node. Nested alternatives, concatenations, + /// or operations are collapsed. + pub fn normalize_shallow(&mut self) { + match self { + JsValue::Alternatives(_, v) => { + if v.len() == 1 { + *self = take(&mut v[0]); + } else { + let mut set = IndexSet::with_capacity(v.len()); + for v in take(v) { + match v { + JsValue::Alternatives(_, v) => { + for v in v { + set.insert(SimilarJsValue(v)); + } + }, + v => { + set.insert(SimilarJsValue(v)); + }, + } + } + if set.len() == 1 { + *self = set.into_iter().next().unwrap().0; + } else { + *v = set.into_iter().map(|v| v.0).collect(); + self.update_total_nodes(); + } + } + }, + JsValue::Concat(_, v) => { + // Remove empty strings + v.retain(|v| v.as_str() != Some("")); + + // TODO(kdy1): Remove duplicate + let mut new:Vec = vec![]; + for v in take(v) { + if let Some(str) = v.as_str() { + if let Some(last) = new.last_mut() { + if let Some(last_str) = last.as_str() { + *last = [last_str, str].concat().into(); + } else { + new.push(v); + } + } else { + new.push(v); + } + } else if let JsValue::Concat(_, v) = v { + new.extend(v); + } else { + new.push(v); + } + } + if new.len() == 1 { + *self = new.into_iter().next().unwrap(); + } else { + *v = new; + self.update_total_nodes(); + } + }, + JsValue::Add(_, v) => { + let mut added:Vec = Vec::new(); + let mut iter = take(v).into_iter(); + while let Some(item) = iter.next() { + if item.is_string() == Some(true) { + let mut concat = match added.len() { + 0 => Vec::new(), + 1 => vec![added.into_iter().next().unwrap()], + _ => { + vec![JsValue::Add( + 1 + added.iter().map(|v| v.total_nodes()).sum::(), + added, + )] + }, + }; + concat.push(item); + for item in iter.by_ref() { + concat.push(item); + } + *self = JsValue::Concat( + 1 + concat.iter().map(|v| v.total_nodes()).sum::(), + concat, + ); + return; + } else { + added.push(item); + } + } + if added.len() == 1 { + *self = added.into_iter().next().unwrap(); + } else { + *v = added; + self.update_total_nodes(); + } + }, + JsValue::Logical(_, op, list) => { + // Nested logical expressions can be normalized: e. g. `a && (b && c)` => `a && + // b && c` + if list.iter().any(|v| { + if let JsValue::Logical(_, inner_op, _) = v { inner_op == op } else { false } + }) { + // Taking the old list and constructing a new merged list + for mut v in take(list).into_iter() { + if let JsValue::Logical(_, inner_op, inner_list) = &mut v { + if inner_op == op { + list.append(inner_list); + } else { + list.push(v); + } + } else { + list.push(v); + } + } + self.update_total_nodes(); + } + }, + _ => {}, + } + } + + /// Normalizes the current node and all nested nodes. + pub fn normalize(&mut self) { + self.for_each_children_mut(&mut |child| { + child.normalize(); + true + }); + self.normalize_shallow(); + } +} + +// Similarity +// Like equality, but with depth limit +impl JsValue { + /// Check if the values are equal up to the given depth. Might return false + /// even if the values are equal when hitting the depth limit. + fn similar(&self, other:&JsValue, depth:usize) -> bool { + if depth == 0 { + return false; + } + fn all_similar(a:&[JsValue], b:&[JsValue], depth:usize) -> bool { + if a.len() != b.len() { + return false; + } + a.iter().zip(b.iter()).all(|(a, b)| a.similar(b, depth)) + } + fn all_parts_similar(a:&[ObjectPart], b:&[ObjectPart], depth:usize) -> bool { + if a.len() != b.len() { + return false; + } + a.iter().zip(b.iter()).all(|(a, b)| { + match (a, b) { + (ObjectPart::KeyValue(lk, lv), ObjectPart::KeyValue(rk, rv)) => { + lk.similar(rk, depth) && lv.similar(rv, depth) + }, + (ObjectPart::Spread(l), ObjectPart::Spread(r)) => l.similar(r, depth), + _ => false, + } + }) + } + match (self, other) { + (JsValue::Constant(l), JsValue::Constant(r)) => l == r, + ( + JsValue::Array { total_nodes: lc, items: li, mutable: lm }, + JsValue::Array { total_nodes: rc, items: ri, mutable: rm }, + ) => lc == rc && lm == rm && all_similar(li, ri, depth - 1), + ( + JsValue::Object { total_nodes: lc, parts: lp, mutable: lm }, + JsValue::Object { total_nodes: rc, parts: rp, mutable: rm }, + ) => lc == rc && lm == rm && all_parts_similar(lp, rp, depth - 1), + (JsValue::Url(l), JsValue::Url(r)) => l == r, + (JsValue::Alternatives(lc, l), JsValue::Alternatives(rc, r)) => { + lc == rc && all_similar(l, r, depth - 1) + }, + (JsValue::FreeVar(l), JsValue::FreeVar(r)) => l == r, + (JsValue::Variable(l), JsValue::Variable(r)) => l == r, + (JsValue::Concat(lc, l), JsValue::Concat(rc, r)) => { + lc == rc && all_similar(l, r, depth - 1) + }, + (JsValue::Add(lc, l), JsValue::Add(rc, r)) => lc == rc && all_similar(l, r, depth - 1), + (JsValue::Logical(lc, lo, l), JsValue::Logical(rc, ro, r)) => { + lc == rc && lo == ro && all_similar(l, r, depth - 1) + }, + (JsValue::Not(lc, l), JsValue::Not(rc, r)) => lc == rc && l.similar(r, depth - 1), + (JsValue::Call(lc, lf, la), JsValue::Call(rc, rf, ra)) => { + lc == rc && lf.similar(rf, depth - 1) && all_similar(la, ra, depth - 1) + }, + (JsValue::MemberCall(lc, lo, lp, la), JsValue::MemberCall(rc, ro, rp, ra)) => { + lc == rc + && lo.similar(ro, depth - 1) + && lp.similar(rp, depth - 1) + && all_similar(la, ra, depth - 1) + }, + (JsValue::Member(lc, lo, lp), JsValue::Member(rc, ro, rp)) => { + lc == rc && lo.similar(ro, depth - 1) && lp.similar(rp, depth - 1) + }, + (JsValue::Binary(lc, la, lo, lb), JsValue::Binary(rc, ra, ro, rb)) => { + lc == rc && lo == ro && la.similar(ra, depth - 1) && lb.similar(rb, depth - 1) + }, + ( + JsValue::Module(ModuleValue { module: l, annotations: la }), + JsValue::Module(ModuleValue { module: r, annotations: ra }), + ) => l == r && la == ra, + (JsValue::WellKnownObject(l), JsValue::WellKnownObject(r)) => l == r, + (JsValue::WellKnownFunction(l), JsValue::WellKnownFunction(r)) => l == r, + ( + JsValue::Unknown { original_value: _, reason: l, has_side_effects: ls }, + JsValue::Unknown { original_value: _, reason: r, has_side_effects: rs }, + ) => l == r && ls == rs, + (JsValue::Function(lc, _, l), JsValue::Function(rc, _, r)) => { + lc == rc && l.similar(r, depth - 1) + }, + (JsValue::Argument(li, l), JsValue::Argument(ri, r)) => li == ri && l == r, + _ => false, + } + } + + /// Hashes the value up to the given depth. + fn similar_hash(&self, state:&mut H, depth:usize) { + if depth == 0 { + self.total_nodes().hash(state); + return; + } + + fn all_similar_hash(slice:&[JsValue], state:&mut H, depth:usize) { + for item in slice { + item.similar_hash(state, depth); + } + } + + fn all_parts_similar_hash( + slice:&[ObjectPart], + state:&mut H, + depth:usize, + ) { + for item in slice { + match item { + ObjectPart::KeyValue(key, value) => { + key.similar_hash(state, depth); + value.similar_hash(state, depth); + }, + ObjectPart::Spread(value) => { + value.similar_hash(state, depth); + }, + } + } + } + + match self { + JsValue::Constant(v) => Hash::hash(v, state), + JsValue::Object { parts, .. } => all_parts_similar_hash(parts, state, depth - 1), + JsValue::Url(v) => Hash::hash(v, state), + JsValue::FreeVar(v) => Hash::hash(v, state), + JsValue::Variable(v) => Hash::hash(v, state), + JsValue::Array { items: v, .. } + | JsValue::Alternatives(_, v) + | JsValue::Concat(_, v) + | JsValue::Add(_, v) + | JsValue::Logical(_, _, v) => all_similar_hash(v, state, depth - 1), + JsValue::Not(_, v) => v.similar_hash(state, depth - 1), + JsValue::Call(_, a, b) => { + a.similar_hash(state, depth - 1); + all_similar_hash(b, state, depth - 1); + }, + JsValue::SuperCall(_, a) => { + all_similar_hash(a, state, depth - 1); + }, + JsValue::MemberCall(_, a, b, c) => { + a.similar_hash(state, depth - 1); + b.similar_hash(state, depth - 1); + all_similar_hash(c, state, depth - 1); + }, + JsValue::Member(_, o, p) => { + o.similar_hash(state, depth - 1); + p.similar_hash(state, depth - 1); + }, + JsValue::Binary(_, a, o, b) => { + a.similar_hash(state, depth - 1); + o.hash(state); + b.similar_hash(state, depth - 1); + }, + JsValue::Tenary(_, test, cons, alt) => { + test.similar_hash(state, depth - 1); + cons.similar_hash(state, depth - 1); + alt.similar_hash(state, depth - 1); + }, + JsValue::Iterated(_, iterable) => { + iterable.similar_hash(state, depth - 1); + }, + JsValue::TypeOf(_, operand) => { + operand.similar_hash(state, depth - 1); + }, + JsValue::Module(ModuleValue { module: v, annotations: a }) => { + Hash::hash(v, state); + Hash::hash(a, state); + }, + JsValue::WellKnownObject(v) => Hash::hash(v, state), + JsValue::WellKnownFunction(v) => Hash::hash(v, state), + JsValue::Unknown { original_value: _, reason: v, has_side_effects } => { + Hash::hash(v, state); + Hash::hash(has_side_effects, state); + }, + JsValue::Function(_, _, v) => v.similar_hash(state, depth - 1), + JsValue::Argument(i, v) => { + Hash::hash(i, state); + Hash::hash(v, state); + }, + } + } +} + +/// The depth to use when comparing values for similarity. +const SIMILAR_EQ_DEPTH:usize = 3; +/// The depth to use when hashing values for similarity. +const SIMILAR_HASH_DEPTH:usize = 2; + +/// A wrapper around `JsValue` that implements `PartialEq` and `Hash` by +/// comparing the values with a depth of [SIMILAR_EQ_DEPTH] and hashing values +/// with a depth of [SIMILAR_HASH_DEPTH]. +struct SimilarJsValue(JsValue); + +impl PartialEq for SimilarJsValue { + fn eq(&self, other:&Self) -> bool { self.0.similar(&other.0, SIMILAR_EQ_DEPTH) } +} + +impl Eq for SimilarJsValue {} + +impl Hash for SimilarJsValue { + fn hash(&self, state:&mut H) { + self.0.similar_hash(state, SIMILAR_HASH_DEPTH) + } +} + +/// A list of well-known objects that have special meaning in the analysis. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub enum WellKnownObjectKind { + GlobalObject, + PathModule, + PathModuleDefault, + FsModule, + FsModuleDefault, + FsModulePromises, + UrlModule, + UrlModuleDefault, + ChildProcess, + ChildProcessDefault, + OsModule, + OsModuleDefault, + NodeProcess, + NodeProcessArgv, + NodeProcessEnv, + NodePreGyp, + NodeExpressApp, + NodeProtobufLoader, + NodeBuffer, + RequireCache, +} + +impl WellKnownObjectKind { + pub fn as_define_name(&self) -> Option<&[&str]> { + match self { + Self::GlobalObject => Some(&["global"]), + Self::PathModule => Some(&["path"]), + Self::FsModule => Some(&["fs"]), + Self::UrlModule => Some(&["url"]), + Self::ChildProcess => Some(&["child_process"]), + Self::OsModule => Some(&["os"]), + Self::NodeProcess => Some(&["process"]), + Self::NodeProcessArgv => Some(&["process", "argv"]), + Self::NodeProcessEnv => Some(&["process", "env"]), + Self::NodeBuffer => Some(&["Buffer"]), + Self::RequireCache => Some(&["require", "cache"]), + _ => None, + } + } +} + +#[derive(Debug, Clone)] +pub struct RequireContextOptions { + pub dir:RcStr, + pub include_subdirs:bool, + /// this is a regex (pattern, flags) + pub filter:Regex, +} + +/// Convert an ECMAScript regex to a Rust regex. +fn regex_from_js(pattern:&str, flags:&str) -> Result { + // rust regex doesn't allow escaped slashes, but they are necessary in js + let pattern = pattern.replace("\\/", "/"); + + let mut applied_flags = String::new(); + for flag in flags.chars() { + match flag { + // indices for substring matches: not relevant for the regex itself + 'd' => {}, + // global: default in rust, ignore + 'g' => {}, + // case-insensitive: letters match both upper and lower case + 'i' => applied_flags.push('i'), + // multi-line mode: ^ and $ match begin/end of line + 'm' => applied_flags.push('m'), + // allow . to match \n + 's' => applied_flags.push('s'), + // Unicode support (enabled by default) + 'u' => applied_flags.push('u'), + // sticky search: not relevant for the regex itself + 'y' => {}, + _ => bail!("unsupported flag `{}` in regex", flag), + } + } + + let regex = if !applied_flags.is_empty() { + format!("(?{}){}", applied_flags, pattern) + } else { + pattern + }; + + Regex::new(®ex).context("could not convert ECMAScript regex to Rust regex") +} + +/// Parse the arguments passed to a require.context invocation, validate them +/// and convert them to the appropriate rust values. +pub fn parse_require_context(args:&[JsValue]) -> Result { + if !(1..=3).contains(&args.len()) { + // https://linear.app/vercel/issue/WEB-910/add-support-for-requirecontexts-mode-argument + bail!("require.context() only supports 1-3 arguments (mode is not supported)"); + } + + let Some(dir) = args[0].as_str().map(|s| s.into()) else { + bail!("require.context(dir, ...) requires dir to be a constant string"); + }; + + let include_subdirs = if let Some(include_subdirs) = args.get(1) { + if let Some(include_subdirs) = include_subdirs.as_bool() { + include_subdirs + } else { + bail!( + "require.context(..., includeSubdirs, ...) requires includeSubdirs to be a \ + constant boolean", + ); + } + } else { + true + }; + + let filter = if let Some(filter) = args.get(2) { + if let JsValue::Constant(ConstantValue::Regex(pattern, flags)) = filter { + regex_from_js(pattern, flags)? + } else { + bail!("require.context(..., ..., filter) requires filter to be a regex"); + } + } else { + // https://webpack.js.org/api/module-methods/#requirecontext + // > optional, default /^\.\/.*$/, any file + static DEFAULT_REGEX:Lazy = Lazy::new(|| Regex::new(r"^\\./.*$").unwrap()); + + DEFAULT_REGEX.clone() + }; + + Ok(RequireContextOptions { dir, include_subdirs, filter }) +} + +#[turbo_tasks::value(transparent)] +#[derive(Debug, Clone)] +pub struct RequireContextValue(IndexMap); + +#[turbo_tasks::value_impl] +impl RequireContextValue { + #[turbo_tasks::function] + pub async fn from_context_map(map:Vc) -> Result> { + let mut context_map = IndexMap::new(); + + for (key, entry) in map.await?.iter() { + context_map.insert(key.clone(), entry.origin_relative.clone()); + } + + Ok(Vc::cell(context_map)) + } +} + +impl Hash for RequireContextValue { + fn hash(&self, state:&mut H) { + self.0.len().hash(state); + for (i, (k, v)) in self.0.iter().enumerate() { + i.hash(state); + k.hash(state); + v.hash(state); + } + } +} + +/// A list of well-known functions that have special meaning in the analysis. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub enum WellKnownFunctionKind { + ObjectAssign, + PathJoin, + PathDirname, + /// `0` is the current working directory. + PathResolve(Box), + Import, + Require, + RequireResolve, + RequireContext, + RequireContextRequire(Vc), + RequireContextRequireKeys(Vc), + RequireContextRequireResolve(Vc), + Define, + FsReadMethod(JsWord), + PathToFileUrl, + ChildProcessSpawnMethod(JsWord), + ChildProcessFork, + OsArch, + OsPlatform, + OsEndianness, + ProcessCwd, + NodePreGypFind, + NodeGypBuild, + NodeBindings, + NodeExpress, + NodeExpressSet, + NodeStrongGlobalize, + NodeStrongGlobalizeSetRootDir, + NodeResolveFrom, + NodeProtobufLoad, +} + +impl WellKnownFunctionKind { + pub fn as_define_name(&self) -> Option<&[&str]> { + match self { + Self::Import => Some(&["import"]), + Self::Require => Some(&["require"]), + Self::RequireResolve => Some(&["require", "resolve"]), + Self::RequireContext => Some(&["require", "context"]), + Self::Define => Some(&["define"]), + _ => None, + } + } +} + +fn is_unresolved(i:&Ident, unresolved_mark:Mark) -> bool { i.span.ctxt.outer() == unresolved_mark } + +#[doc(hidden)] +pub mod test_utils { + use anyhow::Result; + use indexmap::IndexMap; + use turbo_tasks::Vc; + use turbopack_core::{compile_time_info::CompileTimeInfo, error::PrettyPrintError}; + + use super::{ + JsValue, + ModuleValue, + WellKnownFunctionKind, + WellKnownObjectKind, + builtin::early_replace_builtin, + well_known::replace_well_known, + }; + use crate::analyzer::{ + builtin::replace_builtin, + imports::ImportAnnotations, + parse_require_context, + }; + + pub async fn early_visitor(mut v:JsValue) -> Result<(JsValue, bool)> { + let m = early_replace_builtin(&mut v); + Ok((v, m)) + } + + pub async fn visitor( + v:JsValue, + compile_time_info:Vc, + ) -> Result<(JsValue, bool)> { + let mut new_value = match v { + JsValue::Call( + _, + box JsValue::WellKnownFunction(WellKnownFunctionKind::Import), + ref args, + ) => { + match &args[0] { + JsValue::Constant(v) => { + JsValue::Module(ModuleValue { + module:v.to_string().into(), + annotations:ImportAnnotations::default(), + }) + }, + _ => v.into_unknown(true, "import() non constant"), + } + }, + JsValue::Call( + _, + box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve), + ref args, + ) => { + match &args[0] { + JsValue::Constant(v) => (v.to_string() + "/resolved/lib/index.js").into(), + _ => v.into_unknown(true, "require.resolve non constant"), + } + }, + JsValue::Call( + _, + box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext), + ref args, + ) => { + match parse_require_context(args) { + Ok(options) => { + let mut map = IndexMap::new(); + + map.insert("./a".into(), format!("[context: {}]/a", options.dir).into()); + map.insert("./b".into(), format!("[context: {}]/b", options.dir).into()); + map.insert("./c".into(), format!("[context: {}]/c", options.dir).into()); + + JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequire( + Vc::cell(map), + )) + }, + Err(err) => v.into_unknown(true, PrettyPrintError(&err).to_string()), + } + }, + JsValue::FreeVar(ref var) => { + match &**var { + "import" => JsValue::WellKnownFunction(WellKnownFunctionKind::Import), + "require" => JsValue::WellKnownFunction(WellKnownFunctionKind::Require), + "define" => JsValue::WellKnownFunction(WellKnownFunctionKind::Define), + "__dirname" => "__dirname".into(), + "__filename" => "__filename".into(), + "process" => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess), + _ => v.into_unknown(true, "unknown global"), + } + }, + JsValue::Module(ModuleValue { module: ref name, .. }) => { + match name.as_ref() { + "path" => JsValue::WellKnownObject(WellKnownObjectKind::PathModule), + "os" => JsValue::WellKnownObject(WellKnownObjectKind::OsModule), + "process" => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess), + "@mapbox/node-pre-gyp" => { + JsValue::WellKnownObject(WellKnownObjectKind::NodePreGyp) + }, + "node-pre-gyp" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeGypBuild) + }, + _ => return Ok((v, false)), + } + }, + _ => { + let (mut v, m1) = replace_well_known(v, compile_time_info).await?; + let m2 = replace_builtin(&mut v); + let m = m1 || m2 || v.make_nested_operations_unknown(); + return Ok((v, m)); + }, + }; + new_value.normalize_shallow(); + Ok((new_value, true)) + } +} + +#[cfg(test)] +mod tests { + use std::{mem::take, path::PathBuf, time::Instant}; + + use swc_core::{ + common::Mark, + ecma::{ + ast::EsVersion, + parser::parse_file_as_program, + transforms::base::resolver, + visit::VisitMutWith, + }, + testing::{NormalizedOutput, fixture, run_test}, + }; + use turbo_tasks::{Value, util::FormatDuration}; + use turbopack_core::{ + compile_time_info::CompileTimeInfo, + environment::{Environment, ExecutionEnvironment, NodeJsEnvironment}, + target::{Arch, CompileTarget, Endianness, Libc, Platform}, + }; + + use super::{ + JsValue, + graph::{ConditionalKind, Effect, EffectArg, EvalContext, VarGraph, create_graph}, + linker::link, + }; + + #[fixture("tests/analyzer/graph/**/input.js")] + fn fixture(input:PathBuf) { + crate::register(); + let graph_snapshot_path = input.with_file_name("graph.snapshot"); + let graph_explained_snapshot_path = input.with_file_name("graph-explained.snapshot"); + let graph_effects_snapshot_path = input.with_file_name("graph-effects.snapshot"); + let resolved_explained_snapshot_path = input.with_file_name("resolved-explained.snapshot"); + let resolved_effects_snapshot_path = input.with_file_name("resolved-effects.snapshot"); + let large_marker = input.with_file_name("large"); + + run_test(false, |cm, handler| { + let r = tokio::runtime::Builder::new_current_thread().build().unwrap(); + r.block_on(async move { + let fm = cm.load_file(&input).unwrap(); + + let mut m = parse_file_as_program( + &fm, + Default::default(), + EsVersion::latest(), + None, + &mut vec![], + ) + .map_err(|err| err.into_diagnostic(handler).emit())?; + + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + m.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false)); + + let eval_context = + EvalContext::new(&m, unresolved_mark, top_level_mark, false, None); + + let mut var_graph = create_graph(&m, &eval_context); + + let mut named_values = var_graph + .values + .clone() + .into_iter() + .map(|((id, ctx), value)| { + let unique = var_graph.values.keys().filter(|(i, _)| &id == i).count() == 1; + if unique { + (id.to_string(), value) + } else { + (format!("{id}{ctx:?}"), value) + } + }) + .collect::>(); + named_values.sort_by(|a, b| a.0.cmp(&b.0)); + + fn explain_all(values:&[(String, JsValue)]) -> String { + values + .iter() + .map(|(id, value)| { + let (explainer, hints) = value.explain(10, 5); + format!("{id} = {explainer}{hints}") + }) + .collect::>() + .join("\n\n") + } + + { + // Dump snapshot of graph + + let large = large_marker.exists(); + + if !large { + NormalizedOutput::from(format!("{:#?}", named_values)) + .compare_to_file(&graph_snapshot_path) + .unwrap(); + } + NormalizedOutput::from(explain_all(&named_values)) + .compare_to_file(&graph_explained_snapshot_path) + .unwrap(); + if !large { + NormalizedOutput::from(format!("{:#?}", var_graph.effects)) + .compare_to_file(&graph_effects_snapshot_path) + .unwrap(); + } + } + + { + // Dump snapshot of resolved + + let start = Instant::now(); + let mut resolved = Vec::new(); + for (id, val) in named_values.iter() { + let val = val.clone(); + let start = Instant::now(); + let res = resolve(&var_graph, val).await; + let time = start.elapsed(); + if time.as_millis() > 1 { + println!( + "linking {} {id} took {}", + input.display(), + FormatDuration(time) + ); + } + + resolved.push((id.clone(), res)); + } + let time = start.elapsed(); + if time.as_millis() > 1 { + println!("linking {} took {}", input.display(), FormatDuration(time)); + } + + let start = Instant::now(); + let explainer = explain_all(&resolved); + let time = start.elapsed(); + if time.as_millis() > 1 { + println!("explaining {} took {}", input.display(), FormatDuration(time)); + } + + NormalizedOutput::from(explainer) + .compare_to_file(&resolved_explained_snapshot_path) + .unwrap(); + } + + { + // Dump snapshot of resolved effects + + let start = Instant::now(); + let mut resolved = Vec::new(); + let mut queue = take(&mut var_graph.effects) + .into_iter() + .map(|effect| (0, effect)) + .rev() + .collect::>(); + let mut i = 0; + while let Some((parent, effect)) = queue.pop() { + i += 1; + let start = Instant::now(); + async fn handle_args( + args:Vec, + queue:&mut Vec<(usize, Effect)>, + var_graph:&VarGraph, + i:usize, + ) -> Vec { + let mut new_args = Vec::new(); + for arg in args { + match arg { + EffectArg::Value(v) => { + new_args.push(resolve(var_graph, v).await); + }, + EffectArg::Closure(v, effects) => { + new_args.push(resolve(var_graph, v).await); + queue.extend( + effects.effects.into_iter().rev().map(|e| (i, e)), + ); + }, + EffectArg::Spread => { + new_args.push(JsValue::unknown_empty(true, "spread")); + }, + } + } + new_args + } + match effect { + Effect::Conditional { condition, kind, .. } => { + let condition = resolve(&var_graph, condition).await; + resolved.push((format!("{parent} -> {i} conditional"), condition)); + match *kind { + ConditionalKind::If { then } => { + queue + .extend(then.effects.into_iter().rev().map(|e| (i, e))); + }, + ConditionalKind::IfElse { then, r#else } + | ConditionalKind::Ternary { then, r#else } => { + queue.extend( + r#else.effects.into_iter().rev().map(|e| (i, e)), + ); + queue + .extend(then.effects.into_iter().rev().map(|e| (i, e))); + }, + ConditionalKind::And { expr } + | ConditionalKind::Or { expr } + | ConditionalKind::NullishCoalescing { expr } => { + queue + .extend(expr.effects.into_iter().rev().map(|e| (i, e))); + }, + }; + }, + Effect::Call { func, args, .. } => { + let func = resolve(&var_graph, func).await; + let new_args = handle_args(args, &mut queue, &var_graph, i).await; + resolved.push(( + format!("{parent} -> {i} call"), + JsValue::call(Box::new(func), new_args), + )); + }, + Effect::FreeVar { var, .. } => { + resolved.push((format!("{parent} -> {i} free var"), var)); + }, + Effect::MemberCall { obj, prop, args, .. } => { + let obj = resolve(&var_graph, obj).await; + let prop = resolve(&var_graph, prop).await; + let new_args = handle_args(args, &mut queue, &var_graph, i).await; + resolved.push(( + format!("{parent} -> {i} member call"), + JsValue::member_call(Box::new(obj), Box::new(prop), new_args), + )); + }, + _ => {}, + } + let time = start.elapsed(); + if time.as_millis() > 1 { + println!( + "linking effect {} took {}", + input.display(), + FormatDuration(time) + ); + } + } + let time = start.elapsed(); + if time.as_millis() > 1 { + println!( + "linking effects {} took {}", + input.display(), + FormatDuration(time) + ); + } + + let start = Instant::now(); + let explainer = explain_all(&resolved); + let time = start.elapsed(); + if time.as_millis() > 1 { + println!( + "explaining effects {} took {}", + input.display(), + FormatDuration(time) + ); + } + + NormalizedOutput::from(explainer) + .compare_to_file(&resolved_effects_snapshot_path) + .unwrap(); + } + + Ok(()) + }) + }) + .unwrap(); + } + + async fn resolve(var_graph:&VarGraph, val:JsValue) -> JsValue { + turbo_tasks_testing::VcStorage::with(async { + let compile_time_info = CompileTimeInfo::builder(Environment::new(Value::new( + ExecutionEnvironment::NodeJsLambda( + NodeJsEnvironment { + compile_target:CompileTarget { + arch:Arch::X64, + platform:Platform::Linux, + endianness:Endianness::Little, + libc:Libc::Glibc, + } + .into(), + ..Default::default() + } + .into(), + ), + ))) + .cell(); + link( + var_graph, + val, + &super::test_utils::early_visitor, + &(|val| Box::pin(super::test_utils::visitor(val, compile_time_info))), + Default::default(), + ) + .await + }) + .await + .unwrap() + } +} diff --git a/crates/turbopack-ecmascript/Source/analyzer/top_level_await.rs b/crates/turbopack-ecmascript/Source/analyzer/top_level_await.rs new file mode 100644 index 0000000000000..cb97df455919f --- /dev/null +++ b/crates/turbopack-ecmascript/Source/analyzer/top_level_await.rs @@ -0,0 +1,72 @@ +use swc_core::{ + common::Span, + ecma::{ + ast::*, + visit::{Visit, VisitWith, noop_visit_type}, + }, +}; + +/// Checks if the program contains a top level await, if it does it will returns +/// the span of the first await. +pub(crate) fn has_top_level_await(m:&Program) -> Option { + let mut visitor = TopLevelAwaitVisitor::default(); + + m.visit_with(&mut visitor); + + visitor.top_level_await_span +} + +#[derive(Default)] +struct TopLevelAwaitVisitor { + top_level_await_span:Option, +} + +macro_rules! noop { + ($name:ident, $T:path) => { + fn $name(&mut self, _:&$T) {} + }; +} + +impl Visit for TopLevelAwaitVisitor { + // prevent non top level items from visiting their children + noop_visit_type!(); + + noop!(visit_arrow_expr, ArrowExpr); + + noop!(visit_constructor, Constructor); + + noop!(visit_function, Function); + + fn visit_await_expr(&mut self, n:&AwaitExpr) { + if self.top_level_await_span.is_none() { + self.top_level_await_span = Some(n.span); + } + } + + fn visit_getter_prop(&mut self, n:&GetterProp) { n.key.visit_children_with(self); } + + fn visit_setter_prop(&mut self, n:&SetterProp) { n.key.visit_children_with(self); } + + fn visit_class_prop(&mut self, n:&ClassProp) { + n.key.visit_children_with(self); + n.decorators.visit_children_with(self); + if n.is_static { + n.value.visit_children_with(self); + } + } + + fn visit_private_prop(&mut self, n:&PrivateProp) { + n.decorators.visit_children_with(self); + if n.is_static { + n.value.visit_children_with(self); + } + } + + fn visit_auto_accessor(&mut self, n:&AutoAccessor) { + n.key.visit_children_with(self); + n.decorators.visit_children_with(self); + if n.is_static { + n.value.visit_children_with(self); + } + } +} diff --git a/crates/turbopack-ecmascript/Source/analyzer/well_known.rs b/crates/turbopack-ecmascript/Source/analyzer/well_known.rs new file mode 100644 index 0000000000000..883c75dd5621c --- /dev/null +++ b/crates/turbopack-ecmascript/Source/analyzer/well_known.rs @@ -0,0 +1,792 @@ +use std::mem::take; + +use anyhow::Result; +use turbo_tasks::Vc; +use turbopack_core::compile_time_info::CompileTimeInfo; +use url::Url; + +use super::{ + ConstantValue, + JsValue, + ModuleValue, + WellKnownFunctionKind, + WellKnownObjectKind, + imports::ImportAnnotations, +}; +use crate::analyzer::RequireContextValue; + +pub async fn replace_well_known( + value:JsValue, + compile_time_info:Vc, +) -> Result<(JsValue, bool)> { + Ok(match value { + JsValue::Call(_, box JsValue::WellKnownFunction(kind), args) => { + ( + well_known_function_call( + kind, + JsValue::unknown_empty(false, "this is not analyzed yet"), + args, + compile_time_info, + ) + .await?, + true, + ) + }, + JsValue::Call(usize, callee, args) => { + // var fs = require('fs'), fs = __importStar(fs); + // TODO(WEB-552) this is not correct and has many false positives! + if args.len() == 1 { + if let JsValue::WellKnownObject(_) = &args[0] { + return Ok((args[0].clone(), true)); + } + } + (JsValue::Call(usize, callee, args), false) + }, + JsValue::Member(_, box JsValue::WellKnownObject(kind), box prop) => { + well_known_object_member(kind, prop, compile_time_info).await? + }, + JsValue::Member(_, box JsValue::WellKnownFunction(kind), box prop) => { + well_known_function_member(kind, prop) + }, + _ => (value, false), + }) +} + +pub async fn well_known_function_call( + kind:WellKnownFunctionKind, + _this:JsValue, + args:Vec, + compile_time_info:Vc, +) -> Result { + Ok(match kind { + WellKnownFunctionKind::ObjectAssign => object_assign(args), + WellKnownFunctionKind::PathJoin => path_join(args), + WellKnownFunctionKind::PathDirname => path_dirname(args), + WellKnownFunctionKind::PathResolve(cwd) => path_resolve(*cwd, args), + WellKnownFunctionKind::Import => { + JsValue::unknown( + JsValue::call(Box::new(JsValue::WellKnownFunction(kind)), args), + true, + "import() is not supported", + ) + }, + WellKnownFunctionKind::Require => require(args), + WellKnownFunctionKind::RequireContextRequire(value) => { + require_context_require(value, args).await? + }, + WellKnownFunctionKind::RequireContextRequireKeys(value) => { + require_context_require_keys(value, args).await? + }, + WellKnownFunctionKind::RequireContextRequireResolve(value) => { + require_context_require_resolve(value, args).await? + }, + WellKnownFunctionKind::PathToFileUrl => path_to_file_url(args), + WellKnownFunctionKind::OsArch => { + compile_time_info.environment().compile_target().await?.arch.as_str().into() + }, + WellKnownFunctionKind::OsPlatform => { + compile_time_info.environment().compile_target().await?.platform.as_str().into() + }, + WellKnownFunctionKind::ProcessCwd => { + if let Some(cwd) = &*compile_time_info.environment().cwd().await? { + cwd.clone().into() + } else { + JsValue::unknown( + JsValue::call(Box::new(JsValue::WellKnownFunction(kind)), args), + true, + "process.cwd is not specified in the environment", + ) + } + }, + WellKnownFunctionKind::OsEndianness => { + compile_time_info + .environment() + .compile_target() + .await? + .endianness + .as_str() + .into() + }, + WellKnownFunctionKind::NodeExpress => { + JsValue::WellKnownObject(WellKnownObjectKind::NodeExpressApp) + }, + // bypass + WellKnownFunctionKind::NodeResolveFrom => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom) + }, + + _ => { + JsValue::unknown( + JsValue::call(Box::new(JsValue::WellKnownFunction(kind)), args), + true, + "unsupported function", + ) + }, + }) +} + +pub fn object_assign(args:Vec) -> JsValue { + if args.iter().all(|arg| matches!(arg, JsValue::Object { .. })) { + if let Some(mut merged_object) = args.into_iter().reduce(|mut acc, cur| { + if let JsValue::Object { parts, mutable, .. } = &mut acc { + if let JsValue::Object { parts: next_parts, mutable: next_mutable, .. } = &cur { + parts.extend_from_slice(next_parts); + *mutable |= *next_mutable; + } + } + acc + }) { + merged_object.update_total_nodes(); + merged_object + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::ObjectAssign)), + vec![], + ), + true, + "empty arguments for Object.assign", + ) + } + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::ObjectAssign)), + args, + ), + true, + "only const object assign is supported", + ) + } +} + +pub fn path_join(args:Vec) -> JsValue { + if args.is_empty() { + return ".".into(); + } + let mut parts = Vec::new(); + for item in args { + if let Some(str) = item.as_str() { + let splitted = str.split('/'); + parts.extend(splitted.map(|s| s.into())); + } else { + parts.push(item); + } + } + let mut results_final = Vec::new(); + let mut results:Vec = Vec::new(); + for item in parts { + if let Some(str) = item.as_str() { + match str { + "" | "." => { + if results_final.is_empty() && results.is_empty() { + results_final.push(item); + } + }, + ".." => { + if results.pop().is_none() { + results_final.push(item); + } + }, + _ => results.push(item), + } + } else { + results_final.append(&mut results); + results_final.push(item); + } + } + results_final.append(&mut results); + let mut iter = results_final.into_iter(); + let first = iter.next().unwrap(); + let mut last_is_str = first.as_str().is_some(); + results.push(first); + for part in iter { + let is_str = part.as_str().is_some(); + if last_is_str && is_str { + results.push("/".into()); + } else { + results.push(JsValue::alternatives(vec!["/".into(), "".into()])); + } + results.push(part); + last_is_str = is_str; + } + JsValue::concat(results) +} + +pub fn path_resolve(cwd:JsValue, mut args:Vec) -> JsValue { + // If no path segments are passed, `path.resolve()` will return the absolute + // path of the current working directory. + if args.is_empty() { + return JsValue::unknown_empty(false, "cwd is not static analyzable"); + } + if args.len() == 1 { + return args.into_iter().next().unwrap(); + } + + // path.resolve stops at the string starting with `/` + for (idx, arg) in args.iter().enumerate().rev() { + if idx != 0 { + if let Some(str) = arg.as_str() { + if str.starts_with('/') { + return path_resolve(cwd, args.drain(idx..).collect()); + } + } + } + } + + let mut results_final = Vec::new(); + let mut results:Vec = Vec::new(); + for item in args { + if let Some(str) = item.as_str() { + for str in str.split('/') { + match str { + "" | "." => { + if results_final.is_empty() && results.is_empty() { + results_final.push(str.into()); + } + }, + ".." => { + if results.pop().is_none() { + results_final.push("..".into()); + } + }, + _ => results.push(str.into()), + } + } + } else { + results_final.append(&mut results); + results_final.push(item); + } + } + results_final.append(&mut results); + let mut iter = results_final.into_iter(); + let first = iter.next().unwrap(); + + let is_already_absolute = + first.is_empty_string() == Some(true) || first.starts_with("/") == Some(true); + + let mut last_was_str = first.as_str().is_some(); + + if !is_already_absolute { + results.push(cwd); + } + + results.push(first); + for part in iter { + let is_str = part.as_str().is_some(); + if last_was_str && is_str { + results.push("/".into()); + } else { + results.push(JsValue::alternatives(vec!["/".into(), "".into()])); + } + results.push(part); + last_was_str = is_str; + } + + JsValue::concat(results) +} + +pub fn path_dirname(mut args:Vec) -> JsValue { + if let Some(arg) = args.iter_mut().next() { + if let Some(str) = arg.as_str() { + if let Some(i) = str.rfind('/') { + return JsValue::Constant(ConstantValue::Str(str[..i].to_string().into())); + } else { + return JsValue::Constant(ConstantValue::Str("".into())); + } + } else if let JsValue::Concat(_, items) = arg { + if let Some(last) = items.last_mut() { + if let Some(str) = last.as_str() { + if let Some(i) = str.rfind('/') { + *last = JsValue::Constant(ConstantValue::Str(str[..i].to_string().into())); + return take(arg); + } + } + } + } + } + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::PathDirname)), + args, + ), + true, + "path.dirname with unsupported arguments", + ) +} + +pub fn require(args:Vec) -> JsValue { + if args.len() == 1 { + if let Some(s) = args[0].as_str() { + JsValue::Module(ModuleValue { + module:s.into(), + annotations:ImportAnnotations::default(), + }) + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require)), + args, + ), + true, + "only constant argument is supported", + ) + } + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require)), + args, + ), + true, + "only a single argument is supported", + ) + } +} + +/// (try to) statically evaluate `require.context(...)()` +pub async fn require_context_require( + val:Vc, + args:Vec, +) -> Result { + if args.is_empty() { + return Ok(JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequire( + val, + ))), + args, + ), + true, + "require.context(...).require() requires an argument specifying the module path", + )); + } + + let Some(s) = args[0].as_str() else { + return Ok(JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequire( + val, + ))), + args, + ), + true, + "require.context(...).require() only accepts a single, constant string argument", + )); + }; + + let map = val.await?; + let Some(m) = map.get(s) else { + return Ok(JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequire( + val, + ))), + args, + ), + true, + "require.context(...).require() can only be called with an argument that's in the \ + context", + )); + }; + + Ok(JsValue::Module(ModuleValue { + module:m.to_string().into(), + annotations:ImportAnnotations::default(), + })) +} + +/// (try to) statically evaluate `require.context(...).keys()` +pub async fn require_context_require_keys( + val:Vc, + args:Vec, +) -> Result { + Ok(if args.is_empty() { + let map = val.await?; + JsValue::array(map.keys().cloned().map(|k| k.into()).collect()) + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction( + WellKnownFunctionKind::RequireContextRequireKeys(val), + )), + args, + ), + true, + "require.context(...).keys() does not accept arguments", + ) + }) +} + +/// (try to) statically evaluate `require.context(...).resolve()` +pub async fn require_context_require_resolve( + val:Vc, + args:Vec, +) -> Result { + if args.len() != 1 { + return Ok(JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction( + WellKnownFunctionKind::RequireContextRequireResolve(val), + )), + args, + ), + true, + "require.context(...).resolve() only accepts a single, constant string argument", + )); + } + + let Some(s) = args[0].as_str() else { + return Ok(JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction( + WellKnownFunctionKind::RequireContextRequireResolve(val), + )), + args, + ), + true, + "require.context(...).resolve() only accepts a single, constant string argument", + )); + }; + + let map = val.await?; + let Some(m) = map.get(s) else { + return Ok(JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction( + WellKnownFunctionKind::RequireContextRequireResolve(val), + )), + args, + ), + true, + "require.context(...).resolve() can only be called with an argument that's in the \ + context", + )); + }; + + Ok(m.as_str().into()) +} + +pub fn path_to_file_url(args:Vec) -> JsValue { + if args.len() == 1 { + if let Some(path) = args[0].as_str() { + Url::from_file_path(path).map(Box::new).map(JsValue::Url).unwrap_or_else(|_| { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::PathToFileUrl)), + args, + ), + true, + "url not parseable: path is relative or has an invalid prefix", + ) + }) + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::PathToFileUrl)), + args, + ), + true, + "only constant argument is supported", + ) + } + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::PathToFileUrl)), + args, + ), + true, + "only a single argument is supported", + ) + } +} + +pub fn well_known_function_member(kind:WellKnownFunctionKind, prop:JsValue) -> (JsValue, bool) { + let new_value = match (kind, prop.as_str()) { + (WellKnownFunctionKind::Require, Some("resolve")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve) + }, + (WellKnownFunctionKind::Require, Some("cache")) => { + JsValue::WellKnownObject(WellKnownObjectKind::RequireCache) + }, + (WellKnownFunctionKind::Require, Some("context")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext) + }, + (WellKnownFunctionKind::RequireContextRequire(val), Some("resolve")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequireResolve(val)) + }, + (WellKnownFunctionKind::RequireContextRequire(val), Some("keys")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequireKeys(val)) + }, + (WellKnownFunctionKind::NodeStrongGlobalize, Some("SetRootDir")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeStrongGlobalizeSetRootDir) + }, + (WellKnownFunctionKind::NodeResolveFrom, Some("silent")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom) + }, + #[allow(unreachable_patterns)] + (kind, _) => { + return ( + JsValue::member(Box::new(JsValue::WellKnownFunction(kind)), Box::new(prop)), + false, + ); + }, + }; + (new_value, true) +} + +pub async fn well_known_object_member( + kind:WellKnownObjectKind, + prop:JsValue, + compile_time_info:Vc, +) -> Result<(JsValue, bool)> { + let new_value = match kind { + WellKnownObjectKind::GlobalObject => global_object(prop), + WellKnownObjectKind::PathModule | WellKnownObjectKind::PathModuleDefault => { + path_module_member(kind, prop) + }, + WellKnownObjectKind::FsModule + | WellKnownObjectKind::FsModuleDefault + | WellKnownObjectKind::FsModulePromises => fs_module_member(kind, prop), + WellKnownObjectKind::UrlModule | WellKnownObjectKind::UrlModuleDefault => { + url_module_member(kind, prop) + }, + WellKnownObjectKind::ChildProcess | WellKnownObjectKind::ChildProcessDefault => { + child_process_module_member(kind, prop) + }, + WellKnownObjectKind::OsModule | WellKnownObjectKind::OsModuleDefault => { + os_module_member(kind, prop) + }, + WellKnownObjectKind::NodeProcess => node_process_member(prop, compile_time_info).await?, + WellKnownObjectKind::NodePreGyp => node_pre_gyp(prop), + WellKnownObjectKind::NodeExpressApp => express(prop), + WellKnownObjectKind::NodeProtobufLoader => protobuf_loader(prop), + #[allow(unreachable_patterns)] + _ => { + return Ok(( + JsValue::member(Box::new(JsValue::WellKnownObject(kind)), Box::new(prop)), + false, + )); + }, + }; + Ok((new_value, true)) +} + +fn global_object(prop:JsValue) -> JsValue { + match prop.as_str() { + Some("assign") => JsValue::WellKnownFunction(WellKnownFunctionKind::ObjectAssign), + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::GlobalObject)), + Box::new(prop), + ), + true, + "unsupported property on global Object", + ) + }, + } +} + +pub fn path_module_member(kind:WellKnownObjectKind, prop:JsValue) -> JsValue { + match (kind, prop.as_str()) { + (.., Some("join")) => JsValue::WellKnownFunction(WellKnownFunctionKind::PathJoin), + (.., Some("dirname")) => JsValue::WellKnownFunction(WellKnownFunctionKind::PathDirname), + (.., Some("resolve")) => { + // cwd is added while resolving in refernces.rs + JsValue::WellKnownFunction(WellKnownFunctionKind::PathResolve(Box::new(JsValue::from( + "", + )))) + }, + (WellKnownObjectKind::PathModule, Some("default")) => { + JsValue::WellKnownObject(WellKnownObjectKind::PathModuleDefault) + }, + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::PathModule)), + Box::new(prop), + ), + true, + "unsupported property on Node.js path module", + ) + }, + } +} + +pub fn fs_module_member(kind:WellKnownObjectKind, prop:JsValue) -> JsValue { + if let Some(word) = prop.as_str() { + match (kind, word) { + ( + .., + "realpath" | "realpathSync" | "stat" | "statSync" | "existsSync" + | "createReadStream" | "exists" | "open" | "openSync" | "readFile" | "readFileSync", + ) => { + return JsValue::WellKnownFunction(WellKnownFunctionKind::FsReadMethod( + word.into(), + )); + }, + (WellKnownObjectKind::FsModule | WellKnownObjectKind::FsModuleDefault, "promises") => { + return JsValue::WellKnownObject(WellKnownObjectKind::FsModulePromises); + }, + (WellKnownObjectKind::FsModule, "default") => { + return JsValue::WellKnownObject(WellKnownObjectKind::FsModuleDefault); + }, + _ => {}, + } + } + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::FsModule)), + Box::new(prop), + ), + true, + "unsupported property on Node.js fs module", + ) +} + +pub fn url_module_member(kind:WellKnownObjectKind, prop:JsValue) -> JsValue { + match (kind, prop.as_str()) { + (.., Some("pathToFileURL")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::PathToFileUrl) + }, + (WellKnownObjectKind::UrlModuleDefault, Some("default")) => { + JsValue::WellKnownObject(WellKnownObjectKind::UrlModuleDefault) + }, + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::UrlModule)), + Box::new(prop), + ), + true, + "unsupported property on Node.js url module", + ) + }, + } +} + +pub fn child_process_module_member(kind:WellKnownObjectKind, prop:JsValue) -> JsValue { + let prop_str = prop.as_str(); + match (kind, prop_str) { + (.., Some("spawn" | "spawnSync" | "execFile" | "execFileSync")) => { + JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessSpawnMethod( + prop_str.unwrap().into(), + )) + }, + (.., Some("fork")) => JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessFork), + (WellKnownObjectKind::ChildProcess, Some("default")) => { + JsValue::WellKnownObject(WellKnownObjectKind::ChildProcessDefault) + }, + + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::ChildProcess)), + Box::new(prop), + ), + true, + "unsupported property on Node.js child_process module", + ) + }, + } +} + +fn os_module_member(kind:WellKnownObjectKind, prop:JsValue) -> JsValue { + match (kind, prop.as_str()) { + (.., Some("platform")) => JsValue::WellKnownFunction(WellKnownFunctionKind::OsPlatform), + (.., Some("arch")) => JsValue::WellKnownFunction(WellKnownFunctionKind::OsArch), + (.., Some("endianness")) => JsValue::WellKnownFunction(WellKnownFunctionKind::OsEndianness), + (WellKnownObjectKind::OsModule, Some("default")) => { + JsValue::WellKnownObject(WellKnownObjectKind::OsModuleDefault) + }, + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::OsModule)), + Box::new(prop), + ), + true, + "unsupported property on Node.js os module", + ) + }, + } +} + +async fn node_process_member( + prop:JsValue, + compile_time_info:Vc, +) -> Result { + Ok(match prop.as_str() { + Some("arch") => { + compile_time_info.environment().compile_target().await?.arch.as_str().into() + }, + Some("platform") => { + compile_time_info.environment().compile_target().await?.platform.as_str().into() + }, + Some("cwd") => JsValue::WellKnownFunction(WellKnownFunctionKind::ProcessCwd), + Some("argv") => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcessArgv), + Some("env") => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcessEnv), + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess)), + Box::new(prop), + ), + true, + "unsupported property on Node.js process object", + ) + }, + }) +} + +fn node_pre_gyp(prop:JsValue) -> JsValue { + match prop.as_str() { + Some("find") => JsValue::WellKnownFunction(WellKnownFunctionKind::NodePreGypFind), + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::NodePreGyp)), + Box::new(prop), + ), + true, + "unsupported property on @mapbox/node-pre-gyp module", + ) + }, + } +} + +fn express(prop:JsValue) -> JsValue { + match prop.as_str() { + Some("set") => JsValue::WellKnownFunction(WellKnownFunctionKind::NodeExpressSet), + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::NodeExpressApp)), + Box::new(prop), + ), + true, + "unsupported property on require('express')() object", + ) + }, + } +} + +fn protobuf_loader(prop:JsValue) -> JsValue { + match prop.as_str() { + Some("load") | Some("loadSync") => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeProtobufLoad) + }, + _ => { + JsValue::unknown( + JsValue::member( + Box::new(JsValue::WellKnownObject(WellKnownObjectKind::NodeProtobufLoader)), + Box::new(prop), + ), + true, + "unsupported property on require('@grpc/proto-loader') object", + ) + }, + } +} diff --git a/crates/turbopack-ecmascript/Source/annotations.rs b/crates/turbopack-ecmascript/Source/annotations.rs new file mode 100644 index 0000000000000..9438b7f208d90 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/annotations.rs @@ -0,0 +1,32 @@ +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{Expr, KeyValueProp, ObjectLit, Prop, PropName, PropOrSpread}, +}; + +/// Changes the chunking type for the annotated import +pub const ANNOTATION_CHUNKING_TYPE:&str = "turbopack-chunking-type"; + +/// Enables a specified transition for the annotated import +pub const ANNOTATION_TRANSITION:&str = "turbopack-transition"; + +pub fn with_chunking_type(chunking_type:&str) -> Box { + with_clause(&[(ANNOTATION_CHUNKING_TYPE, chunking_type)]) +} + +pub fn with_transition(transition_name:&str) -> Box { + with_clause(&[(ANNOTATION_TRANSITION, transition_name)]) +} + +pub fn with_clause<'a>(entries:impl IntoIterator) -> Box { + Box::new(ObjectLit { + span:DUMMY_SP, + props:entries.into_iter().map(|(k, v)| with_prop(k, v)).collect(), + }) +} + +fn with_prop(key:&str, value:&str) -> PropOrSpread { + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key:PropName::Str(key.into()), + value:Box::new(Expr::Lit(value.into())), + }))) +} diff --git a/crates/turbopack-ecmascript/Source/async_chunk/chunk_item.rs b/crates/turbopack-ecmascript/Source/async_chunk/chunk_item.rs new file mode 100644 index 0000000000000..a853c515d64e1 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/async_chunk/chunk_item.rs @@ -0,0 +1,194 @@ +use anyhow::Result; +use indoc::formatdoc; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, Vc}; +use turbopack_core::{ + chunk::{ + ChunkData, + ChunkItem, + ChunkItemExt, + ChunkType, + ChunkableModule, + ChunkingContext, + ChunkingContextExt, + ChunksData, + }, + ident::AssetIdent, + module::Module, + output::OutputAssets, + reference::{ModuleReferences, SingleOutputAssetReference}, +}; + +use crate::{ + async_chunk::module::AsyncLoaderModule, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + data::EcmascriptChunkData, + }, + utils::StringifyJs, +}; + +#[turbo_tasks::value(shared)] +pub struct AsyncLoaderChunkItem { + pub module:Vc, + pub chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl AsyncLoaderChunkItem { + #[turbo_tasks::function] + pub(super) async fn chunks(self: Vc) -> Result> { + let this = self.await?; + let module = this.module.await?; + if let Some(chunk_items) = module.availability_info.available_chunk_items() { + if chunk_items + .get(module.inner.as_chunk_item(Vc::upcast(this.chunking_context)).resolve().await?) + .await? + .is_some() + { + return Ok(Vc::cell(vec![])); + } + } + Ok(this + .chunking_context + .chunk_group_assets(Vc::upcast(module.inner), Value::new(module.availability_info))) + } + + #[turbo_tasks::function] + async fn chunks_data(self: Vc) -> Result> { + let this = self.await?; + Ok(ChunkData::from_assets(this.chunking_context.output_root(), self.chunks())) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for AsyncLoaderChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let this = self.await?; + let module = this.module.await?; + + let id = if let Some(placeable) = + Vc::try_resolve_downcast::>(module.inner).await? + { + Some(placeable.as_chunk_item(Vc::upcast(this.chunking_context)).id().await?) + } else { + None + }; + let id = id.as_deref(); + + let chunks_data = self.chunks_data().await?; + let chunks_data = chunks_data.iter().try_join().await?; + let chunks_data:Vec<_> = chunks_data + .iter() + .map(|chunk_data| EcmascriptChunkData::new(chunk_data)) + .collect(); + + let code = match (id, chunks_data.is_empty()) { + (Some(id), true) => { + formatdoc! { + r#" + __turbopack_export_value__((__turbopack_import__) => {{ + return Promise.resolve().then(() => {{ + return __turbopack_import__({id}); + }}); + }}); + "#, + id = StringifyJs(id), + } + }, + (Some(id), false) => { + formatdoc! { + r#" + __turbopack_export_value__((__turbopack_import__) => {{ + return Promise.all({chunks:#}.map((chunk) => __turbopack_load__(chunk))).then(() => {{ + return __turbopack_import__({id}); + }}); + }}); + "#, + chunks = StringifyJs(&chunks_data), + id = StringifyJs(id), + } + }, + (None, true) => { + formatdoc! { + r#" + __turbopack_export_value__((__turbopack_import__) => {{ + return Promise.resolve(); + }}); + "#, + } + }, + (None, false) => { + formatdoc! { + r#" + __turbopack_export_value__((__turbopack_import__) => {{ + return Promise.all({chunks:#}.map((chunk) => __turbopack_load__(chunk))).then(() => {{}}); + }}); + "#, + chunks = StringifyJs(&chunks_data), + } + }, + }; + + Ok(EcmascriptChunkItemContent { inner_code:code.into(), ..Default::default() }.into()) + } +} + +#[turbo_tasks::function] +fn chunk_reference_description() -> Vc { Vc::cell("chunk".into()) } + +#[turbo_tasks::value_impl] +impl ChunkItem for AsyncLoaderChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + async fn content_ident(&self) -> Result> { + let mut ident = self.module.ident(); + if let Some(available_chunk_items) = + self.module.await?.availability_info.available_chunk_items() + { + ident = ident + .with_modifier(Vc::cell(available_chunk_items.hash().await?.to_string().into())); + } + Ok(ident) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let chunks = self.chunks(); + + Ok(Vc::cell( + chunks + .await? + .iter() + .copied() + .map(|chunk| { + Vc::upcast(SingleOutputAssetReference::new( + chunk, + chunk_reference_description(), + )) + }) + .collect(), + )) + } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } +} diff --git a/crates/turbopack-ecmascript/Source/async_chunk/mod.rs b/crates/turbopack-ecmascript/Source/async_chunk/mod.rs new file mode 100644 index 0000000000000..dd8dfeedf3096 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/async_chunk/mod.rs @@ -0,0 +1,2 @@ +pub mod chunk_item; +pub mod module; diff --git a/crates/turbopack-ecmascript/Source/async_chunk/module.rs b/crates/turbopack-ecmascript/Source/async_chunk/module.rs new file mode 100644 index 0000000000000..cdb0ab27fc3f5 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/async_chunk/module.rs @@ -0,0 +1,78 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkableModule, ChunkingContext, availability_info::AvailabilityInfo}, + ident::AssetIdent, + module::Module, + reference::{ModuleReferences, SingleModuleReference}, +}; + +use crate::async_chunk::chunk_item::AsyncLoaderChunkItem; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("async loader".into()) } + +/// The AsyncLoaderModule is a module that loads another module async, by +/// putting it into a separate chunk group. +#[turbo_tasks::value] +pub struct AsyncLoaderModule { + pub inner:Vc>, + pub chunking_context:Vc>, + pub availability_info:AvailabilityInfo, +} + +#[turbo_tasks::value_impl] +impl AsyncLoaderModule { + #[turbo_tasks::function] + pub fn new( + module:Vc>, + chunking_context:Vc>, + availability_info:Value, + ) -> Vc { + Self::cell(AsyncLoaderModule { + inner:module, + chunking_context, + availability_info:availability_info.into_value(), + }) + } + + #[turbo_tasks::function] + pub fn asset_ident_for(module:Vc>) -> Vc { + module.ident().with_modifier(modifier()) + } +} + +#[turbo_tasks::function] +fn inner_module_reference_description() -> Vc { Vc::cell("async module".into()) } + +#[turbo_tasks::value_impl] +impl Module for AsyncLoaderModule { + #[turbo_tasks::function] + fn ident(&self) -> Vc { Self::asset_ident_for(self.inner) } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + Ok(Vc::cell(vec![Vc::upcast(SingleModuleReference::new( + Vc::upcast(self.await?.inner), + inner_module_reference_description(), + ))])) + } +} + +#[turbo_tasks::value_impl] +impl Asset for AsyncLoaderModule { + #[turbo_tasks::function] + fn content(&self) -> Vc { todo!() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for AsyncLoaderModule { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(AsyncLoaderChunkItem { chunking_context, module:self }.cell())) + } +} diff --git a/crates/turbopack-ecmascript/Source/chunk/chunk_type.rs b/crates/turbopack-ecmascript/Source/chunk/chunk_type.rs new file mode 100644 index 0000000000000..50abb4268c22c --- /dev/null +++ b/crates/turbopack-ecmascript/Source/chunk/chunk_type.rs @@ -0,0 +1,91 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{RcStr, TryJoinIterExt, ValueDefault, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ + AsyncModuleInfo, + Chunk, + ChunkItem, + ChunkItemWithAsyncModuleInfo, + ChunkType, + ChunkingContext, + }, + output::OutputAssets, +}; + +use super::{EcmascriptChunk, EcmascriptChunkContent, EcmascriptChunkItem}; + +#[turbo_tasks::value] +#[derive(Default)] +pub struct EcmascriptChunkType {} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptChunkType { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { Vc::cell("ecmascript".into()) } +} + +#[turbo_tasks::value_impl] +impl ChunkType for EcmascriptChunkType { + #[turbo_tasks::function] + async fn chunk( + &self, + chunking_context:Vc>, + chunk_items:Vec, + referenced_output_assets:Vc, + ) -> Result>> { + let Some(chunking_context) = + Vc::try_resolve_downcast::>(chunking_context).await? + else { + bail!("Ecmascript chunking context not found"); + }; + let content = EcmascriptChunkContent { + chunk_items:chunk_items + .iter() + .map(|(chunk_item, async_info)| { + async move { + let Some(chunk_item) = + Vc::try_resolve_downcast::>(*chunk_item) + .await? + else { + bail!( + "Chunk item is not an ecmascript chunk item but reporting chunk \ + type ecmascript" + ); + }; + Ok((chunk_item, *async_info)) + } + }) + .try_join() + .await?, + referenced_output_assets:referenced_output_assets.await?.clone_value(), + } + .cell(); + Ok(Vc::upcast(EcmascriptChunk::new(chunking_context, content))) + } + + #[turbo_tasks::function] + async fn chunk_item_size( + &self, + _chunking_context:Vc>, + chunk_item:Vc>, + async_module_info:Option>, + ) -> Result> { + let Some(chunk_item) = + Vc::try_resolve_downcast::>(chunk_item).await? + else { + bail!("Chunk item is not an ecmascript chunk item but reporting chunk type ecmascript"); + }; + Ok(Vc::cell( + chunk_item + .content_with_async_module_info(async_module_info) + .await + .map_or(0, |content| content.inner_code.len()), + )) + } +} + +#[turbo_tasks::value_impl] +impl ValueDefault for EcmascriptChunkType { + #[turbo_tasks::function] + fn value_default() -> Vc { Self::default().cell() } +} diff --git a/crates/turbopack-ecmascript/Source/chunk/content.rs b/crates/turbopack-ecmascript/Source/chunk/content.rs new file mode 100644 index 0000000000000..cbc8f4fd5f51d --- /dev/null +++ b/crates/turbopack-ecmascript/Source/chunk/content.rs @@ -0,0 +1,13 @@ +use turbo_tasks::Vc; +use turbopack_core::{chunk::AsyncModuleInfo, output::OutputAsset}; + +use super::item::EcmascriptChunkItem; + +type EcmascriptChunkItemWithAsyncInfo = + (Vc>, Option>); + +#[turbo_tasks::value(shared)] +pub struct EcmascriptChunkContent { + pub chunk_items:Vec, + pub referenced_output_assets:Vec>>, +} diff --git a/crates/turbopack-ecmascript/Source/chunk/data.rs b/crates/turbopack-ecmascript/Source/chunk/data.rs new file mode 100644 index 0000000000000..5d68cea81452e --- /dev/null +++ b/crates/turbopack-ecmascript/Source/chunk/data.rs @@ -0,0 +1,29 @@ +use serde::Serialize; +use turbo_tasks::ReadRef; +use turbopack_core::chunk::{ChunkData, ModuleId}; + +#[derive(Serialize, Hash, PartialEq, Eq)] +#[serde(untagged)] +pub enum EcmascriptChunkData<'a> { + Simple(&'a str), + #[serde(rename_all = "camelCase")] + WithRuntimeInfo { + path:&'a str, + #[serde(skip_serializing_if = "<[_]>::is_empty", default)] + included:&'a [ReadRef], + #[serde(skip_serializing_if = "<[_]>::is_empty", default)] + excluded:&'a [ReadRef], + #[serde(skip_serializing_if = "<[_]>::is_empty", default)] + module_chunks:&'a [String], + }, +} + +impl<'a> EcmascriptChunkData<'a> { + pub fn new(chunk_data:&ChunkData) -> EcmascriptChunkData { + let ChunkData { path, included, excluded, module_chunks, references: _ } = chunk_data; + if included.is_empty() && excluded.is_empty() && module_chunks.is_empty() { + return EcmascriptChunkData::Simple(path); + } + EcmascriptChunkData::WithRuntimeInfo { path, included, excluded, module_chunks } + } +} diff --git a/crates/turbopack-ecmascript/Source/chunk/item.rs b/crates/turbopack-ecmascript/Source/chunk/item.rs new file mode 100644 index 0000000000000..b61aabcbcdcdd --- /dev/null +++ b/crates/turbopack-ecmascript/Source/chunk/item.rs @@ -0,0 +1,263 @@ +use std::io::Write; + +use anyhow::{Result, bail}; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{Upcast, ValueToString, Vc, trace::TraceRawVcs}; +use turbo_tasks_fs::rope::Rope; +use turbopack_core::{ + chunk::{AsyncModuleInfo, ChunkItem, ChunkItemExt, ChunkingContext}, + code_builder::{Code, CodeBuilder}, + error::PrettyPrintError, + issue::{IssueExt, IssueSeverity, StyledString, code_gen::CodeGenerationIssue}, + source_map::GenerateSourceMap, +}; + +use crate::{ + EcmascriptModuleContent, + EcmascriptOptions, + references::async_module::{AsyncModuleOptions, OptionAsyncModuleOptions}, + utils::FormatIter, +}; + +#[turbo_tasks::value(shared)] +#[derive(Default, Clone)] +pub struct EcmascriptChunkItemContent { + pub inner_code:Rope, + pub source_map:Option>>, + pub options:EcmascriptChunkItemOptions, + pub placeholder_for_future_extensions:(), +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItemContent { + #[turbo_tasks::function] + pub async fn new( + content:Vc, + chunking_context:Vc>, + options:Vc, + async_module_options:Vc, + ) -> Result> { + let refresh = options.await?.refresh; + let externals = *chunking_context.environment().supports_commonjs_externals().await?; + + let content = content.await?; + let async_module = async_module_options.await?.clone_value(); + + Ok(EcmascriptChunkItemContent { + inner_code:content.inner_code.clone(), + source_map:content.source_map, + options:if content.is_esm { + EcmascriptChunkItemOptions { + strict:true, + refresh, + externals, + async_module, + ..Default::default() + } + } else { + if async_module.is_some() { + bail!("CJS module can't be async."); + } + + EcmascriptChunkItemOptions { + refresh, + externals, + // These things are not available in ESM + module:true, + exports:true, + require:true, + this:true, + ..Default::default() + } + }, + ..Default::default() + } + .cell()) + } + + #[turbo_tasks::function] + pub async fn module_factory(self: Vc) -> Result> { + let this = self.await?; + let mut args = vec![ + "r: __turbopack_require__", + "f: __turbopack_module_context__", + "i: __turbopack_import__", + "s: __turbopack_esm__", + "v: __turbopack_export_value__", + "n: __turbopack_export_namespace__", + "c: __turbopack_cache__", + "M: __turbopack_modules__", + "l: __turbopack_load__", + "j: __turbopack_dynamic__", + "P: __turbopack_resolve_absolute_path__", + "U: __turbopack_relative_url__", + "R: __turbopack_resolve_module_id_path__", + "g: global", + // HACK + "__dirname", + ]; + if this.options.async_module.is_some() { + args.push("a: __turbopack_async_module__"); + } + if this.options.externals { + args.push("x: __turbopack_external_require__"); + args.push("y: __turbopack_external_import__"); + } + if this.options.refresh { + args.push("k: __turbopack_refresh__"); + } + if this.options.module || this.options.refresh { + args.push("m: module"); + } + if this.options.exports { + args.push("e: exports"); + } + if this.options.require { + args.push("t: require"); + } + if this.options.wasm { + args.push("w: __turbopack_wasm__"); + args.push("u: __turbopack_wasm_module__"); + } + let mut code = CodeBuilder::default(); + let args = FormatIter(|| args.iter().copied().intersperse(", ")); + if this.options.this { + writeln!(code, "(function({{ {} }}) {{ !function() {{", args,)?; + } else { + writeln!(code, "(({{ {} }}) => (() => {{", args,)?; + } + if this.options.strict { + code += "\"use strict\";\n\n"; + } else { + code += "\n"; + } + + if this.options.async_module.is_some() { + code += "__turbopack_async_module__(async (__turbopack_handle_async_dependencies__, \ + __turbopack_async_result__) => { try {\n"; + } + + code.push_source(&this.inner_code, this.source_map); + + if let Some(opts) = &this.options.async_module { + write!( + code, + "__turbopack_async_result__();\n}} catch(e) {{ __turbopack_async_result__(e); }} \ + }}, {});", + opts.has_top_level_await + )?; + } + + if this.options.this { + code += "\n}.call(this) })"; + } else { + code += "\n})())"; + } + Ok(code.build().cell()) + } +} + +#[derive(PartialEq, Eq, Default, Debug, Clone, Serialize, Deserialize, TraceRawVcs)] +pub struct EcmascriptChunkItemOptions { + /// Whether this chunk item should be in "use strict" mode. + pub strict:bool, + /// Whether this chunk item's module factory should include a + /// `__turbopack_refresh__` argument. + pub refresh:bool, + /// Whether this chunk item's module factory should include a `module` + /// argument. + pub module:bool, + /// Whether this chunk item's module factory should include an `exports` + /// argument. + pub exports:bool, + /// Whether this chunk item's module factory should include a `require` + /// argument. + pub require:bool, + /// Whether this chunk item's module factory should include a + /// `__turbopack_external_require__` argument. + pub externals:bool, + /// Whether this chunk item's module is async (either has a top level await + /// or is importing async modules). + pub async_module:Option, + pub this:bool, + /// Whether this chunk item's module factory should include + /// `__turbopack_wasm__` to load WebAssembly. + pub wasm:bool, + pub placeholder_for_future_extensions:(), +} + +#[turbo_tasks::value_trait] +pub trait EcmascriptChunkItem: ChunkItem { + fn content(self: Vc) -> Vc; + fn content_with_async_module_info( + self: Vc, + _async_module_info:Option>, + ) -> Vc { + self.content() + } + fn chunking_context(self: Vc) -> Vc>; + + /// Specifies which availablility information the chunk item needs for code + /// generation + fn need_async_module_info(self: Vc) -> Vc { Vc::cell(false) } +} + +pub trait EcmascriptChunkItemExt: Send { + /// Generates the module factory for this chunk item. + fn code(self: Vc, async_module_info:Option>) -> Vc; +} + +impl EcmascriptChunkItemExt for T +where + T: Upcast>, +{ + /// Generates the module factory for this chunk item. + fn code(self: Vc, async_module_info:Option>) -> Vc { + module_factory_with_code_generation_issue(Vc::upcast(self), async_module_info) + } +} + +#[turbo_tasks::function] +async fn module_factory_with_code_generation_issue( + chunk_item:Vc>, + async_module_info:Option>, +) -> Result> { + Ok( + match chunk_item + .content_with_async_module_info(async_module_info) + .module_factory() + .resolve() + .await + { + Ok(factory) => factory, + Err(error) => { + let id = chunk_item.id().to_string().await; + let id = id.as_ref().map_or_else(|_| "unknown", |id| &**id); + let error = error + .context(format!("An error occurred while generating the chunk item {}", id)); + let error_message = format!("{}", PrettyPrintError(&error)).into(); + let js_error_message = serde_json::to_string(&error_message)?; + CodeGenerationIssue { + severity:IssueSeverity::Error.cell(), + path:chunk_item.asset_ident().path(), + title:StyledString::Text("Code generation for chunk item errored".into()) + .cell(), + message:StyledString::Text(error_message).cell(), + } + .cell() + .emit(); + let mut code = CodeBuilder::default(); + code += "(() => {{\n\n"; + writeln!(code, "throw new Error({error});", error = &js_error_message)?; + code += "\n}})"; + code.build().cell() + }, + }, + ) +} + +#[turbo_tasks::value(transparent)] +pub struct EcmascriptChunkItemsChunk(Vec>>); + +#[turbo_tasks::value(transparent)] +pub struct EcmascriptChunkItems(pub(super) Vec>>); diff --git a/crates/turbopack-ecmascript/Source/chunk/mod.rs b/crates/turbopack-ecmascript/Source/chunk/mod.rs new file mode 100644 index 0000000000000..0341f3d9cb8b4 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/chunk/mod.rs @@ -0,0 +1,204 @@ +pub(crate) mod chunk_type; +pub(crate) mod content; +pub(crate) mod data; +pub(crate) mod item; +pub(crate) mod placeable; + +use std::fmt::Write; + +use anyhow::{Result, bail}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystem; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{Chunk, ChunkItem, ChunkingContext, ModuleIds}, + ident::AssetIdent, + introspect::{ + Introspectable, + IntrospectableChildren, + module::IntrospectableModule, + utils::{children_from_output_assets, content_to_details}, + }, + output::OutputAssets, + server_fs::ServerFileSystem, +}; + +pub use self::{ + chunk_type::EcmascriptChunkType, + content::EcmascriptChunkContent, + data::EcmascriptChunkData, + item::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkItemExt, + EcmascriptChunkItemOptions, + }, + placeable::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceables, EcmascriptExports}, +}; + +#[turbo_tasks::value] +pub struct EcmascriptChunk { + pub chunking_context:Vc>, + pub content:Vc, +} + +#[turbo_tasks::value(transparent)] +pub struct EcmascriptChunks(Vec>); + +#[turbo_tasks::value_impl] +impl EcmascriptChunk { + #[turbo_tasks::function] + pub async fn new( + chunking_context:Vc>, + content:Vc, + ) -> Result> { + Ok(EcmascriptChunk { chunking_context, content }.cell()) + } + + #[turbo_tasks::function] + pub async fn entry_ids(self: Vc) -> Result> { + // TODO return something usefull + Ok(Vc::cell(Default::default())) + } +} + +#[turbo_tasks::function] +fn chunk_item_key() -> Vc { Vc::cell("chunk item".into()) } + +#[turbo_tasks::function] +fn availability_root_key() -> Vc { Vc::cell("current_availability_root".into()) } + +#[turbo_tasks::value_impl] +impl Chunk for EcmascriptChunk { + #[turbo_tasks::function] + async fn ident(self: Vc) -> Result> { + let this = self.await?; + + let mut assets = Vec::new(); + + let EcmascriptChunkContent { chunk_items, .. } = &*this.content.await?; + let mut common_path = if let Some((chunk_item, _)) = chunk_items.first() { + let path = chunk_item.asset_ident().path().resolve().await?; + Some((path, path.await?)) + } else { + None + }; + + // The included chunk items describe the chunk uniquely + let chunk_item_key = chunk_item_key(); + for &(chunk_item, _) in chunk_items.iter() { + if let Some((common_path_vc, common_path_ref)) = common_path.as_mut() { + let path = chunk_item.asset_ident().path().await?; + while !path.is_inside_or_equal_ref(common_path_ref) { + let parent = common_path_vc.parent().resolve().await?; + if parent == *common_path_vc { + common_path = None; + break; + } + *common_path_vc = parent; + *common_path_ref = (*common_path_vc).await?; + } + } + assets.push((chunk_item_key, chunk_item.content_ident())); + } + + // Make sure the idents are resolved + for (_, ident) in assets.iter_mut() { + *ident = ident.resolve().await?; + } + + let ident = AssetIdent { + path:if let Some((common_path, _)) = common_path { + common_path + } else { + ServerFileSystem::new().root() + }, + query:Vc::::default(), + fragment:None, + assets, + modifiers:Vec::new(), + part:None, + layer:None, + }; + + Ok(AssetIdent::new(Value::new(ident))) + } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { Vc::upcast(self.chunking_context) } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let content = this.content.await?; + Ok(Vc::cell(content.referenced_output_assets.clone())) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptChunk { + #[turbo_tasks::function] + async fn to_string(self: Vc) -> Result> { + Ok(Vc::cell(format!("chunk {}", self.ident().to_string().await?).into())) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunk { + #[turbo_tasks::function] + pub fn chunk_content(&self) -> Vc { self.content } + + #[turbo_tasks::function] + pub async fn chunk_items_count(&self) -> Result> { + Ok(Vc::cell(self.content.await?.chunk_items.len())) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptChunk { + #[turbo_tasks::function] + fn content(self: Vc) -> Result> { + bail!("EcmascriptChunk::content() is not implemented") + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("ecmascript chunk".into()) } + +#[turbo_tasks::function] +fn chunk_item_module_key() -> Vc { Vc::cell("module".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for EcmascriptChunk { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(self: Vc) -> Vc { self.path().to_string() } + + #[turbo_tasks::function] + async fn details(self: Vc) -> Result> { + let content = content_to_details(self.content()); + let mut details = String::new(); + let this = self.await?; + let chunk_content = this.content.await?; + details += "Chunk items:\n\n"; + for (chunk_item, _) in chunk_content.chunk_items.iter() { + writeln!(details, "- {}", chunk_item.asset_ident().to_string().await?)?; + } + details += "\nContent:\n\n"; + write!(details, "{}", content.await?)?; + Ok(Vc::cell(details.into())) + } + + #[turbo_tasks::function] + async fn children(self: Vc) -> Result> { + let mut children = children_from_output_assets(self.references()).await?.clone_value(); + let chunk_item_module_key = chunk_item_module_key(); + for &(chunk_item, _) in self.await?.content.await?.chunk_items.iter() { + children + .insert((chunk_item_module_key, IntrospectableModule::new(chunk_item.module()))); + } + Ok(Vc::cell(children)) + } +} diff --git a/crates/turbopack-ecmascript/Source/chunk/placeable.rs b/crates/turbopack-ecmascript/Source/chunk/placeable.rs new file mode 100644 index 0000000000000..48a8dad5e2e86 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/chunk/placeable.rs @@ -0,0 +1,218 @@ +use anyhow::Result; +use turbo_tasks::{TryFlatJoinIterExt, Vc}; +use turbo_tasks_fs::{FileJsonContent, FileSystemPath, glob::Glob}; +use turbopack_core::{ + asset::Asset, + chunk::ChunkableModule, + error::PrettyPrintError, + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + module::Module, + resolve::{FindContextFileResult, find_context_file, package_json}, +}; + +use crate::references::{ + async_module::OptionAsyncModule, + esm::{EsmExport, EsmExports}, +}; + +#[turbo_tasks::value_trait] +pub trait EcmascriptChunkPlaceable: ChunkableModule + Module + Asset { + fn get_exports(self: Vc) -> Vc; + fn get_async_module(self: Vc) -> Vc { Vc::cell(None) } + fn is_marked_as_side_effect_free( + self: Vc, + side_effect_free_packages:Vc, + ) -> Vc { + is_marked_as_side_effect_free(self.ident().path(), side_effect_free_packages) + } +} + +#[turbo_tasks::value] +enum SideEffectsValue { + None, + Constant(bool), + Glob(Vc), +} + +#[turbo_tasks::function] +async fn side_effects_from_package_json( + package_json:Vc, +) -> Result> { + if let FileJsonContent::Content(content) = &*package_json.read_json().await? { + if let Some(side_effects) = content.get("sideEffects") { + if let Some(side_effects) = side_effects.as_bool() { + return Ok(SideEffectsValue::Constant(side_effects).cell()); + } else if let Some(side_effects) = side_effects.as_array() { + let globs = side_effects + .iter() + .filter_map(|side_effect| { + if let Some(side_effect) = side_effect.as_str() { + if side_effect.contains('/') { + Some(Glob::new(side_effect.into())) + } else { + Some(Glob::new(format!("**/{side_effect}").into())) + } + } else { + SideEffectsInPackageJsonIssue { + path:package_json, + description:Some( + StyledString::Text( + format!( + "Each element in sideEffects must be a string, but \ + found {:?}", + side_effect + ) + .into(), + ) + .cell(), + ), + } + .cell() + .emit(); + None + } + }) + .map(|glob| { + async move { + match glob.resolve().await { + Ok(glob) => Ok(Some(glob)), + Err(err) => { + SideEffectsInPackageJsonIssue { + path:package_json, + description:Some( + StyledString::Text( + format!( + "Invalid glob in sideEffects: {}", + PrettyPrintError(&err) + ) + .into(), + ) + .cell(), + ), + } + .cell() + .emit(); + Ok(None) + }, + } + } + }) + .try_flat_join() + .await?; + return Ok( + SideEffectsValue::Glob(Glob::alternatives(globs).resolve().await?).cell() + ); + } else { + SideEffectsInPackageJsonIssue { + path:package_json, + description:Some( + StyledString::Text( + format!( + "sideEffects must be a boolean or an array, but found {:?}", + side_effects + ) + .into(), + ) + .cell(), + ), + } + .cell() + .emit(); + } + } + } + Ok(SideEffectsValue::None.cell()) +} + +#[turbo_tasks::value] +struct SideEffectsInPackageJsonIssue { + path:Vc, + description:Option>, +} + +#[turbo_tasks::value_impl] +impl Issue for SideEffectsInPackageJsonIssue { + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Parse.into() } + + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Warning.cell() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.path } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Invalid value for sideEffects in package.json".into()).cell() + } + + #[turbo_tasks::function] + fn description(&self) -> Vc { Vc::cell(self.description) } +} + +#[turbo_tasks::function] +pub async fn is_marked_as_side_effect_free( + path:Vc, + side_effect_free_packages:Vc, +) -> Result> { + if side_effect_free_packages.await?.execute(&path.await?.path) { + return Ok(Vc::cell(true)); + } + + let find_package_json = find_context_file(path.parent(), package_json()).await?; + + if let FindContextFileResult::Found(package_json, _) = *find_package_json { + match *side_effects_from_package_json(package_json).await? { + SideEffectsValue::None => {}, + SideEffectsValue::Constant(side_effects) => return Ok(Vc::cell(!side_effects)), + SideEffectsValue::Glob(glob) => { + if let Some(rel_path) = + package_json.parent().await?.get_relative_path_to(&*path.await?) + { + return Ok(Vc::cell(!glob.await?.execute(&rel_path))); + } + }, + } + } + + Ok(Vc::cell(false)) +} + +#[turbo_tasks::value(transparent)] +pub struct EcmascriptChunkPlaceables(Vec>>); + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceables { + #[turbo_tasks::function] + pub fn empty() -> Vc { Vc::cell(Vec::new()) } +} + +#[turbo_tasks::value(shared)] +pub enum EcmascriptExports { + EsmExports(Vc), + DynamicNamespace, + CommonJs, + Value, + None, +} + +#[turbo_tasks::value_impl] +impl EcmascriptExports { + #[turbo_tasks::function] + pub async fn needs_facade(&self) -> Result> { + Ok(match self { + EcmascriptExports::EsmExports(exports) => { + let exports = exports.await?; + let has_reexports = !exports.star_exports.is_empty() + || exports.exports.iter().any(|(_, export)| { + matches!( + export, + EsmExport::ImportedBinding(..) | EsmExport::ImportedNamespace(_) + ) + }); + Vc::cell(has_reexports) + }, + _ => Vc::cell(false), + }) + } +} diff --git a/crates/turbopack-ecmascript/Source/chunk_group_files_asset.rs b/crates/turbopack-ecmascript/Source/chunk_group_files_asset.rs new file mode 100644 index 0000000000000..ea83b68041e0c --- /dev/null +++ b/crates/turbopack-ecmascript/Source/chunk_group_files_asset.rs @@ -0,0 +1,234 @@ +use anyhow::Result; +use indexmap::IndexSet; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::{File, FileSystemPath}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ + ChunkItem, + ChunkType, + ChunkableModule, + ChunkingContext, + ChunkingContextExt, + EvaluatableAssets, + availability_info::AvailabilityInfo, + }, + ident::AssetIdent, + introspect::{ + Introspectable, + IntrospectableChildren, + module::IntrospectableModule, + utils::content_to_details, + }, + module::Module, + output::{OutputAsset, OutputAssets}, + reference::{ + ModuleReference, + ModuleReferences, + SingleModuleReference, + SingleOutputAssetReference, + }, +}; + +use crate::{ + EcmascriptModuleAsset, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + utils::StringifyJs, +}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("chunk group files".into()) } + +/// An asset that exports a list of chunk URLs by putting the [asset] into a +/// ChunkGroup with the provided ChunkingContext. +#[turbo_tasks::value(shared)] +pub struct ChunkGroupFilesAsset { + pub module:Vc>, + pub client_root:Vc, + pub chunking_context:Vc>, + pub runtime_entries:Option>, +} + +#[turbo_tasks::function] +fn module_description() -> Vc { Vc::cell("module".into()) } + +#[turbo_tasks::function] +fn runtime_entry_description() -> Vc { Vc::cell("runtime entry".into()) } + +#[turbo_tasks::value_impl] +impl Module for ChunkGroupFilesAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { self.module.ident().with_modifier(modifier()) } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let mut references:Vec>> = vec![Vc::upcast( + SingleModuleReference::new(Vc::upcast(self.module), module_description()), + )]; + + if let Some(runtime_entries) = self.runtime_entries { + references.extend(runtime_entries.await?.iter().map(|&entry| { + Vc::upcast(SingleModuleReference::new( + Vc::upcast(entry), + runtime_entry_description(), + )) + })); + } + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for ChunkGroupFilesAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { + AssetContent::file(File::from(RcStr::from("// Chunking only content")).into()) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for ChunkGroupFilesAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + let this = self.await?; + Ok(Vc::upcast( + ChunkGroupFilesChunkItem { chunking_context, client_root:this.client_root, inner:self } + .cell(), + )) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for ChunkGroupFilesAsset { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } +} + +#[turbo_tasks::value] +struct ChunkGroupFilesChunkItem { + chunking_context:Vc>, + client_root:Vc, + inner:Vc, +} + +#[turbo_tasks::value_impl] +impl ChunkGroupFilesChunkItem { + #[turbo_tasks::function] + async fn chunks(self: Vc) -> Result> { + let this = self.await?; + let inner = this.inner.await?; + let chunks = if let Some(ecma) = + Vc::try_resolve_downcast_type::(inner.module).await? + { + inner.chunking_context.evaluated_chunk_group_assets( + inner.module.ident(), + inner + .runtime_entries + .unwrap_or_else(EvaluatableAssets::empty) + .with_entry(Vc::upcast(ecma)), + Value::new(AvailabilityInfo::Root), + ) + } else { + inner.chunking_context.root_chunk_group_assets(Vc::upcast(inner.module)) + }; + Ok(chunks) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for ChunkGroupFilesChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let chunks = self.chunks(); + let this = self.await?; + let module = this.inner.await?; + let client_root = module.client_root.await?; + let chunks_paths = + chunks.await?.iter().map(|chunk| chunk.ident().path()).try_join().await?; + let chunks_paths:Vec<_> = + chunks_paths.iter().filter_map(|path| client_root.get_path_to(path)).collect(); + Ok(EcmascriptChunkItemContent { + inner_code:format!("__turbopack_export_value__({:#});\n", StringifyJs(&chunks_paths)) + .into(), + ..Default::default() + } + .cell()) + } +} + +#[turbo_tasks::function] +fn chunk_group_chunk_reference_description() -> Vc { Vc::cell("chunk group chunk".into()) } + +#[turbo_tasks::value_impl] +impl ChunkItem for ChunkGroupFilesChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.inner.ident() } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let chunks = self.chunks(); + + Ok(Vc::cell( + chunks + .await? + .iter() + .copied() + .map(|chunk| { + SingleOutputAssetReference::new( + chunk, + chunk_group_chunk_reference_description(), + ) + }) + .map(Vc::upcast) + .collect(), + )) + } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.inner) } +} + +#[turbo_tasks::value_impl] +impl Introspectable for ChunkGroupFilesAsset { + #[turbo_tasks::function] + fn ty(&self) -> Vc { Vc::cell("chunk group files asset".into()) } + + #[turbo_tasks::function] + fn details(self: Vc) -> Vc { content_to_details(self.content()) } + + #[turbo_tasks::function] + fn title(self: Vc) -> Vc { self.ident().to_string() } + + #[turbo_tasks::function] + async fn children(self: Vc) -> Result> { + let mut children = IndexSet::new(); + children.insert(( + Vc::cell("inner asset".into()), + IntrospectableModule::new(Vc::upcast(self.await?.module)), + )); + Ok(Vc::cell(children)) + } +} diff --git a/crates/turbopack-ecmascript/Source/code_gen.rs b/crates/turbopack-ecmascript/Source/code_gen.rs new file mode 100644 index 0000000000000..fbfd3f6032aa2 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/code_gen.rs @@ -0,0 +1,132 @@ +use serde::{Deserialize, Serialize}; +use swc_core::ecma::visit::{AstParentKind, VisitMut}; +use turbo_tasks::{Vc, debug::ValueDebugFormat, trace::TraceRawVcs}; +use turbopack_core::chunk::{AsyncModuleInfo, ChunkingContext}; + +/// impl of code generation inferred from a ModuleReference. +/// This is rust only and can't be implemented by non-rust plugins. +#[turbo_tasks::value(shared, serialization = "none", eq = "manual", into = "new", cell = "new")] +pub struct CodeGeneration { + /// ast nodes matching the span will be visitor by the visitor + #[turbo_tasks(debug_ignore, trace_ignore)] + pub visitors:Vec<(Vec, Box)>, +} + +pub trait VisitorFactory: Send + Sync { + fn create<'a>(&'a self) -> Box; +} + +#[turbo_tasks::value_trait] +pub trait CodeGenerateable { + fn code_generation( + self: Vc, + chunking_context:Vc>, + ) -> Vc; +} + +#[turbo_tasks::value_trait] +pub trait CodeGenerateableWithAsyncModuleInfo { + fn code_generation( + self: Vc, + chunking_context:Vc>, + async_module_info:Option>, + ) -> Vc; +} + +#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat)] +pub enum CodeGen { + CodeGenerateable(Vc>), + CodeGenerateableWithAsyncModuleInfo(Vc>), +} + +#[turbo_tasks::value(transparent)] +pub struct CodeGenerateables(Vec); + +pub fn path_to(path:&[AstParentKind], f:impl FnMut(&AstParentKind) -> bool) -> Vec { + if let Some(pos) = path.iter().rev().position(f) { + let index = path.len() - pos - 1; + path[..index].to_vec() + } else { + path.to_vec() + } +} + +/// Creates a single-method visitor that will visit the AST nodes matching the +/// provided path. +/// +/// If you pass in `exact`, the visitor will only visit the nodes that match the +/// path exactly. Otherwise, the visitor will visit the closest matching parent +/// node in the path. +/// +/// Refer to the [swc_core::ecma::visit::VisitMut] trait for a list of all +/// possible visit methods. +#[macro_export] +macro_rules! create_visitor { + // This rule needs to be first, otherwise we run into the following error: + // expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `:` + // This is a regression on nightly. + (visit_mut_program($arg:ident: &mut Program) $b:block) => {{ + struct Visitor { + visit_mut_program: T, + } + + impl $crate::code_gen::VisitorFactory + for Box> + { + fn create<'a>(&'a self) -> Box { + Box::new(&**self) + } + } + + impl<'a, T: Fn(&mut swc_core::ecma::ast::Program) + Send + Sync> swc_core::ecma::visit::VisitMut + for &'a Visitor + { + fn visit_mut_program(&mut self, $arg: &mut swc_core::ecma::ast::Program) { + (self.visit_mut_program)($arg); + } + } + + ( + Vec::new(), + Box::new(Box::new(Visitor { + visit_mut_program: move |$arg: &mut swc_core::ecma::ast::Program| $b, + })) as Box, + ) + }}; + (exact $ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => { + $crate::create_visitor!(__ $ast_path.to_vec(), $name($arg: &mut $ty) $b) + }; + ($ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => { + $crate::create_visitor!(__ $crate::code_gen::path_to(&$ast_path, |n| { + matches!(n, swc_core::ecma::visit::AstParentKind::$ty(_)) + }), $name($arg: &mut $ty) $b) + }; + (__ $ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => {{ + struct Visitor { + $name: T, + } + + impl $crate::code_gen::VisitorFactory + for Box> + { + fn create<'a>(&'a self) -> Box { + Box::new(&**self) + } + } + + impl<'a, T: Fn(&mut swc_core::ecma::ast::$ty) + Send + Sync> swc_core::ecma::visit::VisitMut + for &'a Visitor + { + fn $name(&mut self, $arg: &mut swc_core::ecma::ast::$ty) { + (self.$name)($arg); + } + } + + ( + $ast_path, + Box::new(Box::new(Visitor { + $name: move |$arg: &mut swc_core::ecma::ast::$ty| $b, + })) as Box, + ) + }}; +} diff --git a/crates/turbopack-ecmascript/Source/errors.rs b/crates/turbopack-ecmascript/Source/errors.rs new file mode 100644 index 0000000000000..632136f58bb6a --- /dev/null +++ b/crates/turbopack-ecmascript/Source/errors.rs @@ -0,0 +1,20 @@ +pub mod failed_to_analyse { + pub mod ecmascript { + pub const DYNAMIC_IMPORT:&str = "TP1001"; + pub const REQUIRE:&str = "TP1002"; + pub const REQUIRE_RESOLVE:&str = "TP1003"; + pub const FS_METHOD:&str = "TP1004"; + pub const CHILD_PROCESS_SPAWN:&str = "TP1005"; + pub const PATH_METHOD:&str = "TP1006"; + pub const REQUIRE_CONTEXT:&str = "TP1007"; + pub const NODE_PRE_GYP_FIND:&str = "TP1100"; + pub const NODE_GYP_BUILD:&str = "TP1101"; + pub const NODE_BINDINGS:&str = "TP1102"; + pub const NODE_EXPRESS:&str = "TP1103"; + pub const NODE_RESOLVE_FROM:&str = "TP1104"; + pub const NODE_PROTOBUF_LOADER:&str = "TP1105"; + pub const AMD_DEFINE:&str = "TP1200"; + pub const NEW_URL_IMPORT_META:&str = "TP1201"; + pub const FREE_VAR_REFERENCE:&str = "TP1202"; + } +} diff --git a/crates/turbopack-ecmascript/Source/lib.rs b/crates/turbopack-ecmascript/Source/lib.rs new file mode 100644 index 0000000000000..d99071cfdee76 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/lib.rs @@ -0,0 +1,899 @@ +// Needed for swc visit_ macros +#![allow(non_local_definitions)] +#![feature(box_patterns)] +#![feature(min_specialization)] +#![feature(iter_intersperse)] +#![feature(int_roundings)] +#![feature(arbitrary_self_types)] +#![recursion_limit = "256"] + +pub mod analyzer; +pub mod annotations; +pub mod async_chunk; +pub mod chunk; +pub mod chunk_group_files_asset; +pub mod code_gen; +mod errors; +pub mod magic_identifier; +pub mod manifest; +pub mod minify; +pub mod parse; +mod path_visitor; +pub mod references; +pub mod side_effect_optimization; +pub(crate) mod special_cases; +pub(crate) mod static_code; +mod swc_comments; +pub mod text; +pub(crate) mod transform; +pub mod tree_shake; +pub mod typescript; +pub mod utils; +pub mod webpack; + +use std::fmt::{Display, Formatter}; + +use anyhow::Result; +use chunk::EcmascriptChunkItem; +use code_gen::CodeGenerateable; +pub use parse::ParseResultSourceMap; +use parse::{ParseResult, parse}; +use path_visitor::ApplyVisitors; +use references::esm::UrlRewriteBehavior; +pub use references::{AnalyzeEcmascriptModuleResult, TURBOPACK_HELPER}; +use serde::{Deserialize, Serialize}; +pub use static_code::StaticEcmascriptCode; +use swc_core::{ + common::GLOBALS, + ecma::{ + codegen::{Emitter, text_writer::JsWriter}, + visit::{VisitMutWith, VisitMutWithPath}, + }, +}; +pub use transform::{ + CustomTransformer, + EcmascriptInputTransform, + EcmascriptInputTransforms, + OptionTransformPlugin, + TransformContext, + TransformPlugin, + UnsupportedServerActionIssue, +}; +use turbo_tasks::{ + RcStr, + ReadRef, + TaskInput, + TryJoinIterExt, + Value, + ValueToString, + Vc, + trace::TraceRawVcs, +}; +use turbo_tasks_fs::{FileJsonContent, FileSystemPath, rope::Rope}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ + AsyncModuleInfo, + ChunkItem, + ChunkType, + ChunkableModule, + ChunkingContext, + EvaluatableAsset, + }, + compile_time_info::CompileTimeInfo, + context::AssetContext, + ident::AssetIdent, + module::{Module, OptionModule}, + reference::ModuleReferences, + reference_type::InnerAssets, + resolve::{ + FindContextFileResult, + ModulePart, + find_context_file, + origin::ResolveOrigin, + package_json, + parse::Request, + }, + source::Source, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMap}, +}; +// TODO remove this +pub use turbopack_resolve::ecmascript as resolve; + +use self::{ + chunk::{EcmascriptChunkItemContent, EcmascriptChunkType, EcmascriptExports}, + code_gen::{CodeGen, CodeGenerateableWithAsyncModuleInfo, CodeGenerateables, VisitorFactory}, + tree_shake::asset::EcmascriptModulePartAsset, +}; +use crate::{ + chunk::EcmascriptChunkPlaceable, + references::{analyse_ecmascript_module, async_module::OptionAsyncModule}, + transform::remove_shebang, +}; + +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(PartialOrd, Ord, Hash, Debug, Clone, Copy, Default, TaskInput)] +pub enum SpecifiedModuleType { + #[default] + Automatic, + CommonJs, + EcmaScript, +} + +#[derive( + PartialOrd, + Ord, + PartialEq, + Eq, + Hash, + Debug, + Clone, + Copy, + Default, + Serialize, + Deserialize, + TraceRawVcs, +)] +#[serde(rename_all = "kebab-case")] +pub enum TreeShakingMode { + #[default] + ModuleFragments, + ReexportsOnly, +} + +#[turbo_tasks::value(shared, serialization = "auto_for_input")] +#[derive(PartialOrd, Ord, Hash, Debug, Default, Copy, Clone)] +pub struct EcmascriptOptions { + pub refresh:bool, + /// variant of tree shaking to use + pub tree_shaking_mode:Option, + /// module is forced to a specific type (happens e. g. for .cjs and .mjs) + pub specified_module_type:SpecifiedModuleType, + /// Determines how to treat `new URL(...)` rewrites. + /// This allows to construct url depends on the different building context, + /// e.g. SSR, CSR, or Node.js. + pub url_rewrite_behavior:Option, + /// External imports should used `__turbopack_import__` instead of + /// `__turbopack_require__` and become async module references. + pub import_externals:bool, + /// Ignore very dynamic requests which doesn't have any static known part. + /// If false, they will reference the whole directory. If true, they won't + /// reference anything and lead to an runtime error instead. + pub ignore_dynamic_requests:bool, +} + +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(PartialOrd, Ord, Hash, Debug, Copy, Clone)] +pub enum EcmascriptModuleAssetType { + /// Module with EcmaScript code + Ecmascript, + /// Module with TypeScript code without types + Typescript { + // parse JSX syntax. + tsx:bool, + // follow references to imported types. + analyze_types:bool, + }, + /// Module with TypeScript declaration code + TypescriptDeclaration, +} + +impl Display for EcmascriptModuleAssetType { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + match self { + EcmascriptModuleAssetType::Ecmascript => write!(f, "ecmascript"), + EcmascriptModuleAssetType::Typescript { tsx, analyze_types } => { + write!(f, "typescript")?; + if *tsx { + write!(f, "with JSX")?; + } + if *analyze_types { + write!(f, "with types")?; + } + Ok(()) + }, + EcmascriptModuleAssetType::TypescriptDeclaration => write!(f, "typescript declaration"), + } + } +} + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("ecmascript".into()) } + +#[derive(PartialEq, Eq, Clone, TraceRawVcs)] +struct MemoizedSuccessfulAnalysis { + operation:Vc, + references:ReadRef, + local_references:ReadRef, + reexport_references:ReadRef, + evaluation_references:ReadRef, + exports:ReadRef, + async_module:ReadRef, + source_map:Option>, +} + +#[derive(Clone)] +pub struct EcmascriptModuleAssetBuilder { + source:Vc>, + asset_context:Vc>, + ty:EcmascriptModuleAssetType, + transforms:Vc, + options:Vc, + compile_time_info:Vc, + inner_assets:Option>, +} + +impl EcmascriptModuleAssetBuilder { + pub fn with_inner_assets(mut self, inner_assets:Vc) -> Self { + self.inner_assets = Some(inner_assets); + self + } + + pub fn with_type(mut self, ty:EcmascriptModuleAssetType) -> Self { + self.ty = ty; + self + } + + pub fn build(self) -> Vc { + if let Some(inner_assets) = self.inner_assets { + EcmascriptModuleAsset::new_with_inner_assets( + self.source, + self.asset_context, + Value::new(self.ty), + self.transforms, + self.options, + self.compile_time_info, + inner_assets, + ) + } else { + EcmascriptModuleAsset::new( + self.source, + self.asset_context, + Value::new(self.ty), + self.transforms, + self.options, + self.compile_time_info, + ) + } + } + + pub async fn build_part(self, part:Vc) -> Result> { + let import_externals = self.options.await?.import_externals; + let base = self.build(); + Ok(EcmascriptModulePartAsset::new(base, part, import_externals)) + } +} + +#[turbo_tasks::value] +pub struct EcmascriptModuleAsset { + pub source:Vc>, + pub asset_context:Vc>, + pub ty:EcmascriptModuleAssetType, + pub transforms:Vc, + pub options:Vc, + pub compile_time_info:Vc, + pub inner_assets:Option>, + #[turbo_tasks(debug_ignore)] + #[serde(skip)] + last_successful_analysis:turbo_tasks::State>, +} + +/// An optional [EcmascriptModuleAsset] +#[turbo_tasks::value(transparent)] +pub struct OptionEcmascriptModuleAsset(Option>); + +/// A list of [EcmascriptModuleAsset]s +#[turbo_tasks::value(transparent)] +pub struct EcmascriptModuleAssets(Vec>); + +impl EcmascriptModuleAsset { + pub fn builder( + source:Vc>, + asset_context:Vc>, + transforms:Vc, + options:Vc, + compile_time_info:Vc, + ) -> EcmascriptModuleAssetBuilder { + EcmascriptModuleAssetBuilder { + source, + asset_context, + ty:EcmascriptModuleAssetType::Ecmascript, + transforms, + options, + compile_time_info, + inner_assets:None, + } + } +} + +#[turbo_tasks::value] +#[derive(Copy, Clone)] +pub(crate) struct ModuleTypeResult { + pub module_type:SpecifiedModuleType, + pub referenced_package_json:Option>, +} + +#[turbo_tasks::value_impl] +impl ModuleTypeResult { + #[turbo_tasks::function] + fn new(module_type:SpecifiedModuleType) -> Vc { + Self::cell(ModuleTypeResult { module_type, referenced_package_json:None }) + } + + #[turbo_tasks::function] + fn new_with_package_json( + module_type:SpecifiedModuleType, + package_json:Vc, + ) -> Vc { + Self::cell(ModuleTypeResult { module_type, referenced_package_json:Some(package_json) }) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptModuleAsset { + #[turbo_tasks::function] + pub fn new( + source:Vc>, + asset_context:Vc>, + ty:Value, + transforms:Vc, + options:Vc, + compile_time_info:Vc, + ) -> Vc { + Self::cell(EcmascriptModuleAsset { + source, + asset_context, + ty:ty.into_value(), + transforms, + options, + compile_time_info, + inner_assets:None, + last_successful_analysis:Default::default(), + }) + } + + #[turbo_tasks::function] + pub fn new_with_inner_assets( + source:Vc>, + asset_context:Vc>, + ty:Value, + transforms:Vc, + options:Vc, + compile_time_info:Vc, + inner_assets:Vc, + ) -> Vc { + Self::cell(EcmascriptModuleAsset { + source, + asset_context, + ty:ty.into_value(), + transforms, + options, + compile_time_info, + inner_assets:Some(inner_assets), + last_successful_analysis:Default::default(), + }) + } + + #[turbo_tasks::function] + pub async fn source(self: Vc) -> Result>> { Ok(self.await?.source) } + + #[turbo_tasks::function] + pub fn analyze(self: Vc) -> Vc { + analyse_ecmascript_module(self, None) + } + + #[turbo_tasks::function] + pub async fn options(self: Vc) -> Result> { + Ok(self.await?.options) + } + + #[turbo_tasks::function] + pub async fn failsafe_analyze(self: Vc) -> Result> { + let this = self.await?; + + let result = self.analyze(); + let result_value = result.await?; + + if result_value.successful { + this.last_successful_analysis.set(Some(MemoizedSuccessfulAnalysis { + operation:result, + // We need to store the ReadRefs since we want to keep a snapshot. + references:result_value.references.await?, + local_references:result_value.local_references.await?, + reexport_references:result_value.reexport_references.await?, + evaluation_references:result_value.evaluation_references.await?, + exports:result_value.exports.await?, + async_module:result_value.async_module.await?, + source_map:if let Some(map) = *result_value.source_map.await? { + Some(map.await?) + } else { + None + }, + })); + } else if let Some(MemoizedSuccessfulAnalysis { + operation, + references, + local_references, + reexport_references, + evaluation_references, + exports, + async_module, + source_map, + }) = &*this.last_successful_analysis.get() + { + // It's important to connect to the last operation here to keep it active, so + // it's potentially recomputed when garbage collected + Vc::connect(*operation); + return Ok(AnalyzeEcmascriptModuleResult { + references:ReadRef::cell(references.clone()), + local_references:ReadRef::cell(local_references.clone()), + reexport_references:ReadRef::cell(reexport_references.clone()), + evaluation_references:ReadRef::cell(evaluation_references.clone()), + exports:ReadRef::cell(exports.clone()), + code_generation:result_value.code_generation, + async_module:ReadRef::cell(async_module.clone()), + source_map:Vc::cell(source_map.clone().map(ReadRef::cell)), + successful:false, + } + .cell()); + } + + Ok(ReadRef::cell(result_value)) + } + + #[turbo_tasks::function] + pub fn parse(&self) -> Vc { + parse(self.source, Value::new(self.ty), self.transforms) + } + + #[turbo_tasks::function] + pub(crate) async fn determine_module_type(self: Vc) -> Result> { + let this = self.await?; + + match this.options.await?.specified_module_type { + SpecifiedModuleType::EcmaScript => { + return Ok(ModuleTypeResult::new(SpecifiedModuleType::EcmaScript)); + }, + SpecifiedModuleType::CommonJs => { + return Ok(ModuleTypeResult::new(SpecifiedModuleType::CommonJs)); + }, + SpecifiedModuleType::Automatic => {}, + } + + let find_package_json = find_context_file( + self.origin_path().resolve().await?.parent().resolve().await?, + package_json().resolve().await?, + ) + .await?; + let FindContextFileResult::Found(package_json, _) = *find_package_json else { + return Ok(ModuleTypeResult::new(SpecifiedModuleType::Automatic)); + }; + + // analysis.add_reference(PackageJsonReference::new(package_json)); + if let FileJsonContent::Content(content) = &*package_json.read_json().await? { + if let Some(r#type) = content.get("type") { + return Ok(ModuleTypeResult::new_with_package_json( + match r#type.as_str() { + Some("module") => SpecifiedModuleType::EcmaScript, + Some("commonjs") => SpecifiedModuleType::CommonJs, + _ => SpecifiedModuleType::Automatic, + }, + package_json, + )); + } + } + + Ok(ModuleTypeResult::new_with_package_json( + SpecifiedModuleType::Automatic, + package_json, + )) + } + + /// Generates module contents without an analysis pass. This is useful for + /// transforming code that is not a module, e.g. runtime code. + #[turbo_tasks::function] + pub async fn module_content_without_analysis( + self: Vc, + ) -> Result> { + let this = self.await?; + + let parsed = parse(this.source, Value::new(this.ty), this.transforms); + + Ok(EcmascriptModuleContent::new_without_analysis( + parsed, + self.ident(), + this.options.await?.specified_module_type, + )) + } + + #[turbo_tasks::function] + pub async fn module_content( + self: Vc, + chunking_context:Vc>, + async_module_info:Option>, + ) -> Result> { + let this = self.await?; + + let parsed = parse(this.source, Value::new(this.ty), this.transforms).resolve().await?; + + let analyze = self.analyze().await?; + + let module_type_result = *self.determine_module_type().await?; + + Ok(EcmascriptModuleContent::new( + parsed, + self.ident(), + module_type_result.module_type, + chunking_context, + analyze.references, + analyze.code_generation, + analyze.async_module, + analyze.source_map, + analyze.exports, + async_module_info, + )) + } +} + +#[turbo_tasks::value_impl] +impl Module for EcmascriptModuleAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + if let Some(inner_assets) = self.inner_assets { + let mut ident = self.source.ident().await?.clone_value(); + for (name, asset) in inner_assets.await?.iter() { + ident.add_asset(Vc::cell(name.to_string().into()), asset.ident()); + } + ident.add_modifier(modifier()); + ident.layer = Some(self.asset_context.layer()); + Ok(AssetIdent::new(Value::new(ident))) + } else { + Ok(self + .source + .ident() + .with_modifier(modifier()) + .with_layer(self.asset_context.layer())) + } + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let analyze = self.failsafe_analyze().await?; + let references = analyze.references.await?.iter().copied().collect(); + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for EcmascriptModuleAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(ModuleChunkItem::cell(ModuleChunkItem { + module:self, + chunking_context, + }))) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for EcmascriptModuleAsset { + #[turbo_tasks::function] + async fn get_exports(self: Vc) -> Result> { + Ok(self.failsafe_analyze().await?.exports) + } + + #[turbo_tasks::function] + async fn get_async_module(self: Vc) -> Result> { + Ok(self.failsafe_analyze().await?.async_module) + } +} + +#[turbo_tasks::value_impl] +impl EvaluatableAsset for EcmascriptModuleAsset {} + +#[turbo_tasks::value_impl] +impl ResolveOrigin for EcmascriptModuleAsset { + #[turbo_tasks::function] + fn origin_path(&self) -> Vc { self.source.ident().path() } + + #[turbo_tasks::function] + fn asset_context(&self) -> Vc> { self.asset_context } + + #[turbo_tasks::function] + async fn get_inner_asset(&self, request:Vc) -> Result> { + Ok(Vc::cell(if let Some(inner_assets) = &self.inner_assets { + if let Some(request) = request.await?.request() { + inner_assets.await?.get(&request).copied() + } else { + None + } + } else { + None + })) + } +} + +#[turbo_tasks::value] +struct ModuleChunkItem { + module:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } + + #[turbo_tasks::function] + async fn is_self_async(&self) -> Result> { + if let Some(async_module) = *self.module.get_async_module().await? { + Ok(async_module.is_self_async(self.module.failsafe_analyze().await?.references)) + } else { + Ok(Vc::cell(false)) + } + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + panic!("content() should not be called"); + } + + #[turbo_tasks::function] + async fn content_with_async_module_info( + self: Vc, + async_module_info:Option>, + ) -> Result> { + let this = self.await?; + let _span = tracing::info_span!( + "code generation", + module = self.asset_ident().to_string().await?.to_string() + ) + .entered(); + let async_module_options = this.module.get_async_module().module_options(async_module_info); + + // TODO check if we need to pass async_module_info at all + let content = this.module.module_content(this.chunking_context, async_module_info); + + Ok(EcmascriptChunkItemContent::new( + content, + this.chunking_context, + this.module.options(), + async_module_options, + )) + } +} + +/// The transformed contents of an Ecmascript module. +#[turbo_tasks::value] +pub struct EcmascriptModuleContent { + pub inner_code:Rope, + pub source_map:Option>>, + pub is_esm:bool, + // pub refresh: bool, +} + +#[turbo_tasks::value_impl] +impl EcmascriptModuleContent { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub async fn new( + parsed:Vc, + ident:Vc, + specified_module_type:SpecifiedModuleType, + chunking_context:Vc>, + references:Vc, + code_generation:Vc, + async_module:Vc, + source_map:Vc, + exports:Vc, + async_module_info:Option>, + ) -> Result> { + let mut code_gens = Vec::new(); + for r in references.await?.iter() { + let r = r.resolve().await?; + if let Some(code_gen) = + Vc::try_resolve_sidecast::>(r).await? + { + code_gens.push(code_gen.code_generation(chunking_context, async_module_info)); + } else if let Some(code_gen) = + Vc::try_resolve_sidecast::>(r).await? + { + code_gens.push(code_gen.code_generation(chunking_context)); + } + } + if let Some(async_module) = *async_module.await? { + code_gens.push(async_module.code_generation( + chunking_context, + async_module_info, + references, + )); + } + for c in code_generation.await?.iter() { + match c { + CodeGen::CodeGenerateable(c) => { + code_gens.push(c.code_generation(chunking_context)); + }, + CodeGen::CodeGenerateableWithAsyncModuleInfo(c) => { + code_gens.push(c.code_generation(chunking_context, async_module_info)); + }, + } + } + if let EcmascriptExports::EsmExports(exports) = *exports.await? { + code_gens.push(exports.code_generation(chunking_context)); + } + + // need to keep that around to allow references into that + let code_gens = code_gens.into_iter().try_join().await?; + let code_gens = code_gens.iter().map(|cg| &**cg).collect::>(); + let mut visitors = Vec::new(); + let mut root_visitors = Vec::new(); + for code_gen in code_gens { + for (path, visitor) in code_gen.visitors.iter() { + if path.is_empty() { + root_visitors.push(&**visitor); + } else { + visitors.push((path, &**visitor)); + } + } + } + + gen_content_with_visitors( + parsed, + ident, + specified_module_type, + visitors, + root_visitors, + source_map, + ) + .await + } + + /// Creates a new [`Vc`] without an analysis pass. + #[turbo_tasks::function] + pub async fn new_without_analysis( + parsed:Vc, + ident:Vc, + specified_module_type:SpecifiedModuleType, + ) -> Result> { + gen_content_with_visitors( + parsed, + ident, + specified_module_type, + Vec::new(), + Vec::new(), + OptionSourceMap::none(), + ) + .await + } +} + +async fn gen_content_with_visitors( + parsed:Vc, + ident:Vc, + specified_module_type:SpecifiedModuleType, + visitors:Vec<(&Vec, &dyn VisitorFactory)>, + root_visitors:Vec<&dyn VisitorFactory>, + original_src_map:Vc, +) -> Result> { + let parsed = parsed.await?; + + match &*parsed { + ParseResult::Ok { program, source_map, globals, eval_context, comments, .. } => { + let mut program = program.clone(); + + GLOBALS.set(globals, || { + if !visitors.is_empty() { + program.visit_mut_with_path( + &mut ApplyVisitors::new(visitors), + &mut Default::default(), + ); + } + for visitor in root_visitors { + program.visit_mut_with(&mut visitor.create()); + } + program.visit_mut_with(&mut swc_core::ecma::transforms::base::hygiene::hygiene()); + program.visit_mut_with(&mut swc_core::ecma::transforms::base::fixer::fixer(None)); + + // we need to remove any shebang before bundling as it's only valid as the first + // line in a js file (not in a chunk item wrapped in the runtime) + remove_shebang(&mut program); + }); + + let mut bytes:Vec = vec![]; + // TODO: Insert this as a sourceless segment so that sourcemaps aren't affected. + // = format!("/* {} */\n", self.module.path().to_string().await?).into_bytes(); + + let mut mappings = vec![]; + + let comments = comments.consumable(); + + let mut emitter = Emitter { + cfg:swc_core::ecma::codegen::Config::default(), + cm:source_map.clone(), + comments:Some(&comments), + wr:JsWriter::new(source_map.clone(), "\n", &mut bytes, Some(&mut mappings)), + }; + + emitter.emit_program(&program)?; + + let srcmap = + ParseResultSourceMap::new(source_map.clone(), mappings, original_src_map).cell(); + + Ok(EcmascriptModuleContent { + inner_code:bytes.into(), + source_map:Some(Vc::upcast(srcmap)), + is_esm:eval_context.is_esm() + || specified_module_type == SpecifiedModuleType::EcmaScript, + } + .cell()) + }, + ParseResult::Unparseable { messages } => { + Ok(EcmascriptModuleContent { + inner_code:format!( + "const e = new Error(`Could not parse module \ + '{path}'\n{error_messages}`);\ne.code = 'MODULE_UNPARSEABLE';\nthrow e;", + path = ident.path().to_string().await?, + error_messages = messages + .as_ref() + .and_then(|m| { m.first().map(|f| format!("\n{}", f)) }) + .unwrap_or("".into()) + ) + .into(), + source_map:None, + is_esm:false, + } + .cell()) + }, + _ => { + Ok(EcmascriptModuleContent { + inner_code:format!( + "const e = new Error(\"Could not parse module '{path}'\");\ne.code = \ + 'MODULE_UNPARSEABLE';\nthrow e;", + path = ident.path().to_string().await? + ) + .into(), + source_map:None, + is_esm:false, + } + .cell()) + }, + } +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-ecmascript/Source/magic_identifier.rs b/crates/turbopack-ecmascript/Source/magic_identifier.rs new file mode 100644 index 0000000000000..cdc88963dab75 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/magic_identifier.rs @@ -0,0 +1,200 @@ +use std::{ + borrow::Cow, + fmt::{Display, Write}, +}; + +use once_cell::sync::Lazy; +use regex::{Captures, Regex, Replacer}; + +pub fn mangle(content:&str) -> String { + let mut r = "__TURBOPACK__".to_string(); + let mut hex_mode = false; + for c in content.chars() { + if matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | ' ') { + if hex_mode { + r.push('$'); + hex_mode = false; + } + if c == ' ' { + r += "__"; + } else { + r.push(c); + } + } else if c == '_' && (!r.ends_with('_') || hex_mode) { + if hex_mode { + r.push('$'); + hex_mode = false; + } + r += "_"; + } else if c == '$' && !hex_mode { + r += "$$"; + } else if matches!(c, '\0'..='\u{ff}') { + if !hex_mode { + r.push('$'); + hex_mode = true; + } + write!(r, "{0:2x}", c as u8).unwrap(); + } else { + if !hex_mode { + r.push('$'); + } + write!(r, "_{:x}$", c as u32).unwrap(); + hex_mode = false; + } + } + if hex_mode { + r.push('$'); + } + r += "__"; + r +} + +/// Decodes a magic identifier into a string. +pub fn unmangle(identifier:&str) -> String { + static DECODE_REGEX:Lazy = + Lazy::new(|| Regex::new(r"^__TURBOPACK__([a-zA-Z0-9_$]+)__$").unwrap()); + + let Some(captures) = DECODE_REGEX.captures(identifier) else { + return identifier.to_string(); + }; + + let content = captures.get(1).unwrap().as_str(); + + enum Mode { + Text, + Underscore, + Hex, + LongHex, + } + let mut mode = Mode::Text; + let mut output = String::new(); + let mut buffer = String::with_capacity(2); + for char in content.chars() { + match mode { + Mode::Text => { + match char { + '_' => mode = Mode::Underscore, + '$' => mode = Mode::Hex, + c => output.push(c), + } + }, + Mode::Underscore => { + match char { + '_' => { + output.push(' '); + mode = Mode::Text; + }, + '$' => { + output.push('_'); + mode = Mode::Hex; + }, + c => { + output.push('_'); + output.push(c); + mode = Mode::Text; + }, + } + }, + Mode::Hex => { + if buffer.len() == 2 { + if let Ok(byte) = u8::from_str_radix(&buffer, 16) { + output.push(byte as char); + } + buffer.clear(); + } + match char { + '_' => { + debug_assert!(buffer.is_empty()); + mode = Mode::LongHex; + }, + '$' => { + debug_assert!(buffer.is_empty()); + mode = Mode::Text; + }, + c => { + buffer.push(c); + }, + } + }, + Mode::LongHex => { + debug_assert!(char != '_'); + match char { + '$' => { + if let Ok(code) = u32::from_str_radix(&buffer, 16) { + output.push(std::char::from_u32(code).unwrap()); + } + buffer.clear(); + mode = Mode::Text; + }, + c => { + buffer.push(c); + }, + } + }, + } + } + debug_assert!(matches!(mode, Mode::Text)); + output +} + +/// Decode all magic identifiers in a string. +pub fn unmangle_identifiers(text:&str, magic:impl Fn(String) -> T) -> Cow<'_, str> { + static IDENTIFIER_REGEX:Lazy = + Lazy::new(|| Regex::new(r"__TURBOPACK__[a-zA-Z0-9_$]+__").unwrap()); + + struct Rep O, O:Display>(T); + + impl O, O:Display> Replacer for Rep { + fn replace_append(&mut self, caps:&Captures<'_>, dst:&mut String) { + write!(dst, "{}", self.0(unmangle(caps.get(0).unwrap().as_str()))).unwrap(); + } + } + + IDENTIFIER_REGEX.replace_all(text, Rep(magic)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_encode() { + assert_eq!(mangle("Hello World"), "__TURBOPACK__Hello__World__"); + assert_eq!(mangle("Hello_World"), "__TURBOPACK__Hello_World__"); + assert_eq!(mangle("Hello__World"), "__TURBOPACK__Hello_$5f$World__"); + assert_eq!(mangle("Hello___World"), "__TURBOPACK__Hello_$5f$_World__"); + assert_eq!(mangle("Hello/World"), "__TURBOPACK__Hello$2f$World__"); + assert_eq!(mangle("Hello///World"), "__TURBOPACK__Hello$2f2f2f$World__"); + assert_eq!(mangle("Hello/_World"), "__TURBOPACK__Hello$2f$_World__"); + assert_eq!(mangle("Hello_/_World"), "__TURBOPACK__Hello_$2f$_World__"); + assert_eq!(mangle("Hello😀World"), "__TURBOPACK__Hello$_1f600$World__"); + assert_eq!(mangle("Hello/😀/World"), "__TURBOPACK__Hello$2f_1f600$$2f$World__"); + assert_eq!(mangle("Hello😀😀World"), "__TURBOPACK__Hello$_1f600$$_1f600$World__"); + } + + #[test] + fn test_decode() { + assert_eq!(unmangle("__TURBOPACK__Hello__World__"), "Hello World"); + assert_eq!(unmangle("__TURBOPACK__Hello_World__"), "Hello_World"); + assert_eq!(unmangle("__TURBOPACK__Hello_$5f$World__"), "Hello__World"); + assert_eq!(unmangle("__TURBOPACK__Hello_$5f$_World__"), "Hello___World"); + assert_eq!(unmangle("__TURBOPACK__Hello$2f$World__"), "Hello/World"); + assert_eq!(unmangle("__TURBOPACK__Hello$2f2f2f$World__"), "Hello///World"); + assert_eq!(unmangle("__TURBOPACK__Hello$2f$_World__"), "Hello/_World"); + assert_eq!(unmangle("__TURBOPACK__Hello_$2f$_World__"), "Hello_/_World"); + assert_eq!(unmangle("__TURBOPACK__Hello$_1f600$World__"), "Hello😀World"); + assert_eq!(unmangle("__TURBOPACK__Hello$2f_1f600$$2f$World__"), "Hello/😀/World"); + assert_eq!(unmangle("__TURBOPACK__Hello$_1f600$$_1f600$World__"), "Hello😀😀World"); + } + + #[test] + fn test_unmangle_identifiers() { + assert_eq!( + unmangle_identifiers( + "Hello __TURBOPACK__Hello__World__ __TURBOPACK__Hello_World__", + |s| format!("{{{s}}}") + ), + "Hello {Hello World} {Hello_World}" + ); + } +} diff --git a/crates/turbopack-ecmascript/Source/manifest/chunk_asset.rs b/crates/turbopack-ecmascript/Source/manifest/chunk_asset.rs new file mode 100644 index 0000000000000..df229d8ed6ea2 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/manifest/chunk_asset.rs @@ -0,0 +1,143 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ + ChunkableModule, + ChunkingContext, + ChunkingContextExt, + availability_info::AvailabilityInfo, + }, + ident::AssetIdent, + module::Module, + output::OutputAssets, + reference::{ModuleReferences, SingleOutputAssetReference}, +}; + +use super::chunk_item::ManifestChunkItem; +use crate::chunk::{EcmascriptChunkPlaceable, EcmascriptExports}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("manifest chunk".into()) } + +/// The manifest module is deferred until requested by the manifest loader +/// item when the dynamic `import()` expression is reached. Its responsibility +/// is to generate a Promise that will resolve only after all the necessary +/// chunks needed by the dynamic import are loaded by the client. +/// +/// Splitting the dynamic import into a quickly generate-able manifest loader +/// item and a slow-to-generate manifest chunk allows for faster incremental +/// compilation. The traversal won't be performed until the dynamic import is +/// actually reached, instead of eagerly as part of the chunk that the dynamic +/// import appears in. +#[turbo_tasks::value(shared)] +pub struct ManifestAsyncModule { + pub inner:Vc>, + pub chunking_context:Vc>, + pub availability_info:AvailabilityInfo, +} + +#[turbo_tasks::value_impl] +impl ManifestAsyncModule { + #[turbo_tasks::function] + pub fn new( + module:Vc>, + chunking_context:Vc>, + availability_info:Value, + ) -> Vc { + Self::cell(ManifestAsyncModule { + inner:module, + chunking_context, + availability_info:availability_info.into_value(), + }) + } + + #[turbo_tasks::function] + pub(super) async fn chunks(self: Vc) -> Result> { + let this = self.await?; + Ok(this + .chunking_context + .chunk_group_assets(Vc::upcast(this.inner), Value::new(this.availability_info))) + } + + #[turbo_tasks::function] + pub async fn manifest_chunks(self: Vc) -> Result> { + let this = self.await?; + if let Some(chunk_items) = this.availability_info.available_chunk_items() { + if chunk_items + .get(this.inner.as_chunk_item(Vc::upcast(this.chunking_context)).resolve().await?) + .await? + .is_some() + { + return Ok(Vc::cell(vec![])); + } + } + Ok(this + .chunking_context + .chunk_group_assets(Vc::upcast(self), Value::new(this.availability_info))) + } + + #[turbo_tasks::function] + pub fn module_ident(&self) -> Vc { self.inner.ident() } + + #[turbo_tasks::function] + pub async fn content_ident(&self) -> Result> { + let mut ident = self.inner.ident(); + if let Some(available_modules) = self.availability_info.available_chunk_items() { + ident = + ident.with_modifier(Vc::cell(available_modules.hash().await?.to_string().into())); + } + Ok(ident) + } +} + +#[turbo_tasks::function] +fn manifest_chunk_reference_description() -> Vc { Vc::cell("manifest chunk".into()) } + +#[turbo_tasks::value_impl] +impl Module for ManifestAsyncModule { + #[turbo_tasks::function] + fn ident(&self) -> Vc { self.inner.ident().with_modifier(modifier()) } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let chunks = self.chunks(); + + Ok(Vc::cell( + chunks + .await? + .iter() + .copied() + .map(|chunk| { + Vc::upcast(SingleOutputAssetReference::new( + chunk, + manifest_chunk_reference_description(), + )) + }) + .collect(), + )) + } +} + +#[turbo_tasks::value_impl] +impl Asset for ManifestAsyncModule { + #[turbo_tasks::function] + fn content(&self) -> Vc { todo!() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for ManifestAsyncModule { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(ManifestChunkItem { chunking_context, manifest:self }.cell())) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for ManifestAsyncModule { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } +} diff --git a/crates/turbopack-ecmascript/Source/manifest/chunk_item.rs b/crates/turbopack-ecmascript/Source/manifest/chunk_item.rs new file mode 100644 index 0000000000000..53bea4ff57b5e --- /dev/null +++ b/crates/turbopack-ecmascript/Source/manifest/chunk_item.rs @@ -0,0 +1,104 @@ +use anyhow::Result; +use indoc::formatdoc; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbopack_core::{ + chunk::{ChunkData, ChunkItem, ChunkType, ChunkingContext, ChunksData}, + ident::AssetIdent, + module::Module, + reference::{ModuleReferences, SingleOutputAssetReference}, +}; + +use super::chunk_asset::ManifestAsyncModule; +use crate::{ + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkType, + data::EcmascriptChunkData, + }, + utils::StringifyJs, +}; + +/// The ManifestChunkItem generates a __turbopack_load__ call for every chunk +/// necessary to load the real asset. Once all the loads resolve, it is safe to +/// __turbopack_import__ the actual module that was dynamically imported. +#[turbo_tasks::value(shared)] +pub(super) struct ManifestChunkItem { + pub chunking_context:Vc>, + pub manifest:Vc, +} + +#[turbo_tasks::value_impl] +impl ManifestChunkItem { + #[turbo_tasks::function] + async fn chunks_data(self: Vc) -> Result> { + let this = self.await?; + Ok(ChunkData::from_assets( + this.chunking_context.output_root(), + this.manifest.chunks(), + )) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for ManifestChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let chunks_data = self.chunks_data().await?; + let chunks_data = chunks_data.iter().try_join().await?; + let chunks_data:Vec<_> = chunks_data + .iter() + .map(|chunk_data| EcmascriptChunkData::new(chunk_data)) + .collect(); + + let code = formatdoc! { + r#" + __turbopack_export_value__({:#}); + "#, + StringifyJs(&chunks_data) + }; + + Ok(EcmascriptChunkItemContent { inner_code:code.into(), ..Default::default() }.into()) + } +} + +#[turbo_tasks::value_impl] +impl ChunkItem for ManifestChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.manifest.ident() } + + #[turbo_tasks::function] + fn content_ident(&self) -> Vc { self.manifest.content_ident() } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let mut references = this.manifest.references().await?.clone_value(); + + let key = Vc::cell("chunk data reference".into()); + + for chunk_data in &*self.chunks_data().await? { + references.extend(chunk_data.references().await?.iter().map(|&output_asset| { + Vc::upcast(SingleOutputAssetReference::new(output_asset, key)) + })); + } + + Ok(Vc::cell(references)) + } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.manifest) } +} diff --git a/crates/turbopack-ecmascript/Source/manifest/loader_item.rs b/crates/turbopack-ecmascript/Source/manifest/loader_item.rs new file mode 100644 index 0000000000000..d78b42a06436b --- /dev/null +++ b/crates/turbopack-ecmascript/Source/manifest/loader_item.rs @@ -0,0 +1,205 @@ +use std::io::Write as _; + +use anyhow::{Result, anyhow}; +use indoc::writedoc; +use turbo_tasks::{RcStr, TryJoinIterExt, Vc}; +use turbopack_core::{ + chunk::{ + ChunkData, + ChunkItem, + ChunkItemExt, + ChunkType, + ChunkableModule, + ChunkingContext, + ChunksData, + }, + ident::AssetIdent, + module::Module, + reference::{ModuleReference, ModuleReferences, SingleOutputAssetReference}, +}; + +use super::chunk_asset::ManifestAsyncModule; +use crate::{ + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + data::EcmascriptChunkData, + }, + utils::StringifyJs, +}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("loader".into()) } + +/// The manifest loader item is shipped in the same chunk that uses the dynamic +/// `import()` expression. Its responsibility is to load the manifest chunk from +/// the server. The dynamic import has been rewritten to import this manifest +/// loader item, which will load the manifest chunk from the server, which +/// will load all the chunks needed by the dynamic import. Finally, we'll be +/// able to import the module we're trying to dynamically import. +/// +/// Splitting the dynamic import into a quickly generate-able manifest loader +/// item and a slow-to-generate manifest chunk allows for faster incremental +/// compilation. The traversal won't be performed until the dynamic import is +/// actually reached, instead of eagerly as part of the chunk that the dynamic +/// import appears in. +#[turbo_tasks::value] +pub struct ManifestLoaderChunkItem { + manifest:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ManifestLoaderChunkItem { + #[turbo_tasks::function] + pub fn new( + manifest:Vc, + chunking_context:Vc>, + ) -> Vc { + Self::cell(ManifestLoaderChunkItem { manifest, chunking_context }) + } + + #[turbo_tasks::function] + pub async fn chunks_data(self: Vc) -> Result> { + let this = self.await?; + let chunks = this.manifest.manifest_chunks(); + Ok(ChunkData::from_assets(this.chunking_context.output_root(), chunks)) + } + + #[turbo_tasks::function] + pub fn asset_ident_for(module:Vc>) -> Vc { + module.ident().with_modifier(modifier()) + } +} + +#[turbo_tasks::function] +fn manifest_loader_chunk_reference_description() -> Vc { + Vc::cell("manifest loader chunk".into()) +} + +#[turbo_tasks::function] +fn chunk_data_reference_description() -> Vc { Vc::cell("chunk data reference".into()) } + +#[turbo_tasks::value_impl] +impl ChunkItem for ManifestLoaderChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { + self.manifest.module_ident().with_modifier(modifier()) + } + + #[turbo_tasks::function] + fn content_ident(&self) -> Vc { + self.manifest.content_ident().with_modifier(modifier()) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + + let chunks = this.manifest.manifest_chunks(); + + let mut references:Vec>> = chunks + .await? + .iter() + .map(|&chunk| { + Vc::upcast(SingleOutputAssetReference::new( + chunk, + manifest_loader_chunk_reference_description(), + )) + }) + .collect(); + + for chunk_data in &*self.chunks_data().await? { + references.extend(chunk_data.references().await?.iter().map(|&output_asset| { + Vc::upcast(SingleOutputAssetReference::new( + output_asset, + chunk_data_reference_description(), + )) + })); + } + + Ok(Vc::cell(references)) + } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Result>> { + Ok(Vc::upcast(self.chunking_context)) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.manifest) } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for ManifestLoaderChunkItem { + #[turbo_tasks::function] + async fn chunking_context(&self) -> Result>> { + Ok(self.manifest.await?.chunking_context) + } + + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let this = &*self.await?; + let mut code = Vec::new(); + + let manifest = this.manifest.await?; + + // We need several items in order for a dynamic import to fully load. First, we + // need the chunk path of the manifest chunk, relative from the output root. The + // chunk is a servable file, which will contain the manifest chunk item, which + // will perform the actual chunk traversal and generate load statements. + let chunks_server_data = &*self.chunks_data().await?.iter().try_join().await?; + + // We also need the manifest chunk item's id, which points to a CJS module that + // exports a promise for all of the necessary chunk loads. + let item_id = + &*this.manifest.as_chunk_item(Vc::upcast(manifest.chunking_context)).id().await?; + + // Finally, we need the id of the module that we're actually trying to + // dynamically import. + let placeable = + Vc::try_resolve_downcast::>(manifest.inner) + .await? + .ok_or_else(|| anyhow!("asset is not placeable in ecmascript chunk"))?; + let dynamic_id = + &*placeable.as_chunk_item(Vc::upcast(manifest.chunking_context)).id().await?; + + // This is the code that will be executed when the dynamic import is reached. + // It will load the manifest chunk, which will load all the chunks needed by + // the dynamic import, and finally we'll be able to import the module we're + // trying to dynamically import. + // This is similar to what happens when the first evaluated chunk is executed + // on first page load, but it's happening on-demand instead of eagerly. + writedoc!( + code, + r#" + __turbopack_export_value__((__turbopack_import__) => {{ + return Promise.all({chunks_server_data}.map((chunk) => __turbopack_load__(chunk))).then(() => {{ + return __turbopack_require__({item_id}); + }}).then((chunks) => {{ + return Promise.all(chunks.map((chunk) => __turbopack_load__(chunk))); + }}).then(() => {{ + return __turbopack_import__({dynamic_id}); + }}); + }}); + "#, + chunks_server_data = StringifyJs( + &chunks_server_data + .iter() + .map(|chunk_data| EcmascriptChunkData::new(chunk_data)) + .collect::>() + ), + item_id = StringifyJs(item_id), + dynamic_id = StringifyJs(dynamic_id), + )?; + + Ok(EcmascriptChunkItemContent { inner_code:code.into(), ..Default::default() }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/manifest/mod.rs b/crates/turbopack-ecmascript/Source/manifest/mod.rs new file mode 100644 index 0000000000000..d327d4dbd8309 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/manifest/mod.rs @@ -0,0 +1,3 @@ +pub mod chunk_asset; +pub mod chunk_item; +pub mod loader_item; diff --git a/crates/turbopack-ecmascript/Source/minify.rs b/crates/turbopack-ecmascript/Source/minify.rs new file mode 100644 index 0000000000000..b4bf242c5d738 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/minify.rs @@ -0,0 +1,145 @@ +use std::{io::Write, sync::Arc}; + +use anyhow::{Context, Result, bail}; +use swc_core::{ + base::{Compiler, try_with_handler}, + common::{ + BytePos, + FileName, + FilePathMapping, + GLOBALS, + LineCol, + Mark, + SourceMap as SwcSourceMap, + comments::{Comments, SingleThreadedComments}, + }, + ecma::{ + self, + ast::{EsVersion, Program}, + codegen::{ + Emitter, + Node, + text_writer::{self, JsWriter, WriteJs}, + }, + minifier::option::{ExtraOptions, MinifyOptions}, + parser::{Parser, StringInput, Syntax, lexer::Lexer}, + transforms::base::fixer::paren_remover, + visit::FoldWith, + }, +}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + code_builder::{Code, CodeBuilder}, + source_map::GenerateSourceMap, +}; + +use crate::ParseResultSourceMap; + +#[turbo_tasks::function] +pub async fn minify(path:Vc, code:Vc) -> Result> { + let path = path.await?; + let original_map = code.generate_source_map(); + let code = code.await?; + + let cm = Arc::new(SwcSourceMap::new(FilePathMapping::empty())); + let compiler = Arc::new(Compiler::new(cm.clone())); + let fm = compiler.cm.new_source_file( + FileName::Custom(path.path.to_string()), + code.source_code().to_str()?.to_string(), + ); + + let lexer = Lexer::new(Syntax::default(), EsVersion::latest(), StringInput::from(&*fm), None); + let mut parser = Parser::new_from(lexer); + // TODO should use our own handler that emits issues instead. + let program = try_with_handler(cm.clone(), Default::default(), |handler| { + GLOBALS.set(&Default::default(), || { + let program = match parser.parse_program() { + Ok(program) => program, + Err(_error) => { + // TODO should emit an issue + bail!("failed to parse source code") + }, + }; + let comments = SingleThreadedComments::default(); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + Ok(compiler.run_transform(handler, false, || { + let program = program.fold_with(&mut paren_remover(Some(&comments))); + + let mut program = + program.fold_with(&mut swc_core::ecma::transforms::base::resolver( + unresolved_mark, + top_level_mark, + false, + )); + + program = swc_core::ecma::minifier::optimize( + program, + cm.clone(), + Some(&comments), + None, + &MinifyOptions { + compress:Some(Default::default()), + mangle:Some(Default::default()), + ..Default::default() + }, + &ExtraOptions { top_level_mark, unresolved_mark }, + ); + + program.fold_with(&mut ecma::transforms::base::fixer::fixer(Some( + &comments as &dyn Comments, + ))) + })) + }) + })?; + + let (src, src_map_buf) = print_program(cm.clone(), program)?; + + let mut builder = CodeBuilder::default(); + builder.push_source( + &src.into(), + Some(Vc::upcast(ParseResultSourceMap::new(cm, src_map_buf, original_map).cell())), + ); + + write!( + builder, + "\n\n//# sourceMappingURL={}.map", + urlencoding::encode(path.file_name()) + )?; + Ok(builder.build().cell()) +} + +// From https://github.com/swc-project/swc/blob/11efd4e7c5e8081f8af141099d3459c3534c1e1d/crates/swc/src/lib.rs#L523-L560 +fn print_program( + cm:Arc, + program:Program, +) -> Result<(String, Vec<(BytePos, LineCol)>)> { + let mut src_map_buf = vec![]; + + let src = { + let mut buf = vec![]; + { + let wr = Box::new(text_writer::omit_trailing_semi(Box::new(JsWriter::new( + cm.clone(), + "\n", + &mut buf, + Some(&mut src_map_buf), + )))) as Box; + + let mut emitter = Emitter { + cfg:swc_core::ecma::codegen::Config::default().with_minify(true), + comments:None, + cm:cm.clone(), + wr, + }; + + program.emit_with(&mut emitter).context("failed to emit module")?; + } + // Invalid utf8 is valid in javascript world. + String::from_utf8(buf).expect("invalid utf8 character detected") + }; + + Ok((src, src_map_buf)) +} diff --git a/crates/turbopack-ecmascript/Source/parse.rs b/crates/turbopack-ecmascript/Source/parse.rs new file mode 100644 index 0000000000000..488ce982b02db --- /dev/null +++ b/crates/turbopack-ecmascript/Source/parse.rs @@ -0,0 +1,477 @@ +use std::{borrow::Cow, future::Future, sync::Arc}; + +use anyhow::{Context, Result, anyhow}; +use swc_core::{ + base::SwcComments, + common::{ + BytePos, + FileName, + GLOBALS, + Globals, + LineCol, + Mark, + SyntaxContext, + errors::{HANDLER, Handler}, + input::StringInput, + source_map::SourceMapGenConfig, + }, + ecma::{ + ast::{EsVersion, Program}, + lints::{config::LintConfig, rules::LintParams}, + parser::{EsConfig, Parser, Syntax, TsConfig, lexer::Lexer}, + transforms::base::{ + helpers::{HELPERS, Helpers}, + resolver, + }, + visit::{FoldWith, VisitMutWith}, + }, +}; +use tracing::Instrument; +use turbo_tasks::{RcStr, Value, ValueToString, Vc, util::WrapFuture}; +use turbo_tasks_fs::{FileContent, FileSystemPath}; +use turbo_tasks_hash::hash_xxh3_hash64; +use turbopack_core::{ + SOURCE_MAP_PREFIX, + asset::{Asset, AssetContent}, + error::PrettyPrintError, + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + source::Source, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMap}, +}; +use turbopack_swc_utils::emitter::IssueEmitter; + +use super::EcmascriptModuleAssetType; +use crate::{ + EcmascriptInputTransform, + analyzer::graph::EvalContext, + swc_comments::ImmutableComments, + transform::{EcmascriptInputTransforms, TransformContext}, +}; + +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +#[allow(clippy::large_enum_variant)] +pub enum ParseResult { + Ok { + #[turbo_tasks(debug_ignore, trace_ignore)] + program:Program, + #[turbo_tasks(debug_ignore, trace_ignore)] + comments:Arc, + #[turbo_tasks(debug_ignore, trace_ignore)] + eval_context:EvalContext, + #[turbo_tasks(debug_ignore, trace_ignore)] + globals:Arc, + #[turbo_tasks(debug_ignore, trace_ignore)] + source_map:Arc, + }, + Unparseable { + messages:Option>, + }, + NotFound, +} + +impl PartialEq for ParseResult { + fn eq(&self, other:&Self) -> bool { + match (self, other) { + (Self::Ok { .. }, Self::Ok { .. }) => false, + _ => core::mem::discriminant(self) == core::mem::discriminant(other), + } + } +} + +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +pub struct ParseResultSourceMap { + /// Confusingly, SWC's SourceMap is not a mapping of transformed locations + /// to source locations. It's a map of filesnames to file contents. + #[turbo_tasks(debug_ignore, trace_ignore)] + files_map:Arc, + + /// The position mappings that can generate a real source map. + #[turbo_tasks(debug_ignore, trace_ignore)] + mappings:Vec<(BytePos, LineCol)>, + + /// An input's original source map, if one exists. This will be used to + /// trace locations back to the input's pre-transformed sources. + original_source_map:Vc, +} + +impl PartialEq for ParseResultSourceMap { + fn eq(&self, other:&Self) -> bool { + Arc::ptr_eq(&self.files_map, &other.files_map) && self.mappings == other.mappings + } +} + +impl ParseResultSourceMap { + pub fn new( + files_map:Arc, + mappings:Vec<(BytePos, LineCol)>, + original_source_map:Vc, + ) -> Self { + ParseResultSourceMap { files_map, mappings, original_source_map } + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for ParseResultSourceMap { + #[turbo_tasks::function] + async fn generate_source_map(&self) -> Result> { + let original_src_map = if let Some(input) = *self.original_source_map.await? { + Some(input.await?.to_source_map().await?) + } else { + None + }; + let input_map = if let Some(map) = original_src_map.as_ref() { + map.as_regular_source_map().map(Cow::into_owned) + } else { + None + }; + let map = self.files_map.build_source_map_with_config( + &self.mappings, + input_map, + InlineSourcesContentConfig {}, + ); + Ok(Vc::cell(Some(SourceMap::new_regular(map).cell()))) + } +} + +/// A config to generate a source map which includes the source content of every +/// source file. SWC doesn't inline sources content by default when generating a +/// sourcemap, so we need to provide a custom config to do it. +struct InlineSourcesContentConfig {} + +impl SourceMapGenConfig for InlineSourcesContentConfig { + fn file_name_to_source(&self, f:&FileName) -> String { + match f { + FileName::Custom(s) => { + format!("{SOURCE_MAP_PREFIX}{s}") + }, + _ => f.to_string(), + } + } + + fn inline_sources_content(&self, _f:&FileName) -> bool { true } +} + +#[turbo_tasks::function] +pub async fn parse( + source:Vc>, + ty:Value, + transforms:Vc, +) -> Result> { + let name = source.ident().to_string().await?.to_string(); + let span = tracing::info_span!("parse ecmascript", name = name, ty = display(&*ty)); + match parse_internal(source, ty, transforms).instrument(span).await { + Ok(result) => Ok(result), + Err(error) => { + Err(error.context(format!("failed to parse {}", source.ident().to_string().await?))) + }, + } +} + +async fn parse_internal( + source:Vc>, + ty:Value, + transforms:Vc, +) -> Result> { + let content = source.content(); + let fs_path_vc = source.ident().path(); + let fs_path = &*fs_path_vc.await?; + let ident = &*source.ident().to_string().await?; + let file_path_hash = hash_xxh3_hash64(&*source.ident().to_string().await?) as u128; + let ty = ty.into_value(); + let content = match content.await { + Ok(content) => content, + Err(error) => { + let error:RcStr = PrettyPrintError(&error).to_string().into(); + ReadSourceIssue { source, error:error.clone() }.cell().emit(); + + return Ok(ParseResult::Unparseable { messages:Some(vec![error]) }.cell()); + }, + }; + Ok(match &*content { + AssetContent::File(file) => { + match &*file.await? { + FileContent::NotFound => ParseResult::NotFound.cell(), + FileContent::Content(file) => { + match file.content().to_str() { + Ok(string) => { + let transforms = &*transforms.await?; + match parse_content( + string.into_owned(), + fs_path_vc, + fs_path, + ident, + file_path_hash, + source, + ty, + transforms, + ) + .await + { + Ok(result) => result, + Err(e) => { + return Err(e).context(anyhow!( + "Transforming and/or parsing of {} failed", + source.ident().to_string().await? + )); + }, + } + }, + Err(error) => { + let error:RcStr = PrettyPrintError(&error).to_string().into(); + ReadSourceIssue { source, error:error.clone() }.cell().emit(); + ParseResult::Unparseable { messages:Some(vec![error]) }.cell() + }, + } + }, + } + }, + AssetContent::Redirect { .. } => ParseResult::Unparseable { messages:None }.cell(), + }) +} + +async fn parse_content( + string:String, + fs_path_vc:Vc, + fs_path:&FileSystemPath, + ident:&str, + file_path_hash:u128, + source:Vc>, + ty:EcmascriptModuleAssetType, + transforms:&[EcmascriptInputTransform], +) -> Result> { + let source_map:Arc = Default::default(); + let handler = Handler::with_emitter( + true, + false, + Box::new(IssueEmitter::new( + source, + source_map.clone(), + Some("Ecmascript file had an error".into()), + )), + ); + + let emitter = Box::new(IssueEmitter::new( + source, + source_map.clone(), + Some("Parsing ecmascript source code failed".into()), + )); + let parser_handler = Handler::with_emitter(true, false, emitter.clone()); + let globals = Arc::new(Globals::new()); + let globals_ref = &globals; + let helpers = GLOBALS.set(globals_ref, || Helpers::new(true)); + let mut result = WrapFuture::new( + async { + let file_name = FileName::Custom(ident.to_string()); + let fm = source_map.new_source_file(file_name.clone(), string); + + let comments = SwcComments::default(); + + let mut parsed_program = { + let lexer = Lexer::new( + match ty { + EcmascriptModuleAssetType::Ecmascript => { + Syntax::Es(EsConfig { + jsx:true, + fn_bind:true, + decorators:true, + decorators_before_export:true, + export_default_from:true, + import_attributes:true, + allow_super_outside_method:true, + allow_return_outside_function:true, + auto_accessors:true, + explicit_resource_management:true, + }) + }, + EcmascriptModuleAssetType::Typescript { tsx, .. } => { + Syntax::Typescript(TsConfig { + decorators:true, + dts:false, + no_early_errors:true, + tsx, + disallow_ambiguous_jsx_like:false, + }) + }, + EcmascriptModuleAssetType::TypescriptDeclaration => { + Syntax::Typescript(TsConfig { + decorators:true, + dts:true, + no_early_errors:true, + tsx:false, + disallow_ambiguous_jsx_like:false, + }) + }, + }, + EsVersion::latest(), + StringInput::from(&*fm), + Some(&comments), + ); + + let mut parser = Parser::new_from(lexer); + let span = tracing::trace_span!("swc_parse").entered(); + let program_result = parser.parse_program(); + drop(span); + + let mut has_errors = vec![]; + for e in parser.take_errors() { + let mut e = e.into_diagnostic(&parser_handler); + has_errors.extend(e.message.iter().map(|m| m.0.as_str().into())); + e.emit(); + } + + if !has_errors.is_empty() { + return Ok(ParseResult::Unparseable { messages:Some(has_errors) }); + } + + match program_result { + Ok(parsed_program) => parsed_program, + Err(e) => { + let mut e = e.into_diagnostic(&parser_handler); + let messages = e.message.iter().map(|m| m.0.as_str().into()).collect(); + + e.emit(); + + return Ok(ParseResult::Unparseable { messages:Some(messages) }); + }, + } + }; + + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + let is_typescript = matches!( + ty, + EcmascriptModuleAssetType::Typescript { .. } + | EcmascriptModuleAssetType::TypescriptDeclaration + ); + let span = tracing::trace_span!("swc_resolver").entered(); + + parsed_program.visit_mut_with(&mut resolver( + unresolved_mark, + top_level_mark, + is_typescript, + )); + drop(span); + + let span = tracing::trace_span!("swc_lint").entered(); + + let lint_config = LintConfig::default(); + let rules = swc_core::ecma::lints::rules::all(LintParams { + program:&parsed_program, + lint_config:&lint_config, + unresolved_ctxt:SyntaxContext::empty().apply_mark(unresolved_mark), + top_level_ctxt:SyntaxContext::empty().apply_mark(top_level_mark), + es_version:EsVersion::latest(), + source_map:source_map.clone(), + }); + parsed_program = + parsed_program.fold_with(&mut swc_core::ecma::lints::rules::lint_to_fold(rules)); + drop(span); + + let transform_context = TransformContext { + comments:&comments, + source_map:&source_map, + top_level_mark, + unresolved_mark, + file_path_str:&fs_path.path, + file_name_str:fs_path.file_name(), + file_name_hash:file_path_hash, + file_path:fs_path_vc, + }; + let span = tracing::trace_span!("transforms"); + async { + for transform in transforms.iter() { + transform.apply(&mut parsed_program, &transform_context).await?; + } + anyhow::Ok(()) + } + .instrument(span) + .await?; + + if parser_handler.has_errors() { + let messages = if let Some(error) = emitter.emitted_issues.last() { + // The emitter created in here only uses StyledString::Text + if let StyledString::Text(xx) = &*error.await?.message.await? { + Some(vec![xx.clone()]) + } else { + None + } + } else { + None + }; + let messages = Some(messages.unwrap_or_else(|| vec![fm.src.clone().into()])); + return Ok(ParseResult::Unparseable { messages }); + } + + parsed_program.visit_mut_with( + &mut swc_core::ecma::transforms::base::helpers::inject_helpers(unresolved_mark), + ); + + let eval_context = EvalContext::new( + &parsed_program, + unresolved_mark, + top_level_mark, + false, + Some(source), + ); + + Ok::(ParseResult::Ok { + program:parsed_program, + comments:Arc::new(ImmutableComments::new(comments)), + eval_context, + // Temporary globals as the current one can't be moved yet, since they are + // borrowed + globals:Arc::new(Globals::new()), + source_map, + }) + }, + |f, cx| { + GLOBALS + .set(globals_ref, || HANDLER.set(&handler, || HELPERS.set(&helpers, || f.poll(cx)))) + }, + ) + .await?; + if let ParseResult::Ok { globals: ref mut g, .. } = result { + // Assign the correct globals + *g = globals; + } + Ok(result.cell()) +} + +#[turbo_tasks::value] +struct ReadSourceIssue { + source:Vc>, + error:RcStr, +} + +#[turbo_tasks::value_impl] +impl Issue for ReadSourceIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.source.ident().path() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Reading source code for parsing failed".into()).cell() + } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some( + StyledString::Text( + format!( + "An unexpected error happened while trying to read the source code to parse: \ + {}", + self.error + ) + .into(), + ) + .cell(), + )) + } + + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Error.cell() } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Load.cell() } +} diff --git a/crates/turbopack-ecmascript/Source/path_visitor.rs b/crates/turbopack-ecmascript/Source/path_visitor.rs new file mode 100644 index 0000000000000..b6357522435b6 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/path_visitor.rs @@ -0,0 +1,303 @@ +use std::borrow::Cow; + +use swc_core::{ + common::pass::AstKindPath, + ecma::{ + ast::*, + visit::{AstParentKind, VisitMut, VisitMutAstPath, VisitMutWith, VisitMutWithPath}, + }, +}; + +use crate::code_gen::VisitorFactory; + +pub type AstPath = Vec; + +// Invariant: Each [AstPath] in `visitors` contains a value at position `index`. +pub struct ApplyVisitors<'a, 'b> { + /// `VisitMut` should be shallow. In other words, it should not visit + /// children of the node. + visitors:Cow<'b, [(&'a AstPath, &'a dyn VisitorFactory)]>, + + index:usize, +} + +/// Do two binary searches to find the sub-slice that has `path[index] == kind`. +/// Returns None if no item matches that. `visitors` need to be sorted by path. +fn find_range<'a, 'b>( + visitors:&'b [(&'a AstPath, &'a dyn VisitorFactory)], + kind:&AstParentKind, + index:usize, +) -> Option<&'b [(&'a AstPath, &'a dyn VisitorFactory)]> { + // Precondition: visitors is never empty + if visitors.first().unwrap().0[index] > *kind || visitors.last().unwrap().0[index] < *kind { + // Fast path: If ast path of the first visitor is already out of range, then we + // can skip the whole visit. + return None; + } + + let start = if visitors.first().unwrap().0[index] == *kind { + // Fast path: It looks like the whole range is selected + 0 + } else { + visitors.partition_point(|(path, _)| path[index] < *kind) + }; + + if start >= visitors.len() { + return None; + } + + if visitors[start].0[index] > *kind { + // Fast path: If the starting point is greater than the given kind, it's + // meaningless to visit later. + return None; + } + + let end = if visitors.last().unwrap().0[index] == *kind { + // Fast path: It's likely that the whole range is selected + visitors.len() + } else { + visitors[start..].partition_point(|(path, _)| path[index] == *kind) + start + }; + if end == start { + return None; + } + // Postcondition: return value is never empty + Some(&visitors[start..end]) +} + +impl<'a, 'b> ApplyVisitors<'a, 'b> { + /// `visitors` must have an non-empty [AstPath]. + pub fn new(mut visitors:Vec<(&'a AstPath, &'a dyn VisitorFactory)>) -> Self { + assert!(!visitors.is_empty()); + visitors.sort_by_key(|(path, _)| *path); + Self { visitors:Cow::Owned(visitors), index:0 } + } + + #[inline(never)] + fn visit_if_required(&mut self, n:&mut N, ast_path:&mut AstKindPath) + where + N: for<'aa> VisitMutWith + + for<'aa, 'bb> VisitMutWithPath>, { + let mut index = self.index; + let mut current_visitors = self.visitors.as_ref(); + while index < ast_path.len() { + let current = index == ast_path.len() - 1; + let kind = ast_path[index]; + if let Some(visitors) = find_range(current_visitors, &kind, index) { + // visitors contains all items that match kind at index. Some of them terminate + // here, some need furth visiting. The terminating items are at the start due to + // sorting of the list. + index += 1; + + // skip items that terminate here + let nested_visitors_start = + visitors.partition_point(|(path, _)| path.len() == index); + if current { + // Potentially skip visiting this sub tree + if nested_visitors_start < visitors.len() { + n.visit_mut_children_with_path( + &mut ApplyVisitors { + // We only select visitors starting from `nested_visitors_start` + // which maintains the invariant. + visitors:Cow::Borrowed(&visitors[nested_visitors_start..]), + index, + }, + ast_path, + ); + } + for (_, visitor) in visitors[..nested_visitors_start].iter() { + n.visit_mut_with(&mut visitor.create()); + } + return; + } else { + // `current_visitors` has the invariant that is must not be empty. + // When it becomes empty, we must early exit + current_visitors = &visitors[nested_visitors_start..]; + if current_visitors.is_empty() { + // Nothing to do in this subtree, skip it + return; + } + } + } else { + // Skip visiting this sub tree + return; + } + } + // Ast path is unchanged, just keep visiting + n.visit_mut_children_with_path(self, ast_path); + } +} + +macro_rules! method { + ($name:ident, $T:ty) => { + fn $name(&mut self, n:&mut $T, ast_path:&mut AstKindPath) { + self.visit_if_required(n, ast_path); + } + }; +} + +impl VisitMutAstPath for ApplyVisitors<'_, '_> { + // TODO: we need a macro to apply that for all methods + method!(visit_mut_prop, Prop); + + method!(visit_mut_simple_assign_target, SimpleAssignTarget); + + method!(visit_mut_expr, Expr); + + method!(visit_mut_member_expr, MemberExpr); + + method!(visit_mut_pat, Pat); + + method!(visit_mut_stmt, Stmt); + + method!(visit_mut_module_decl, ModuleDecl); + + method!(visit_mut_module_item, ModuleItem); + + method!(visit_mut_call_expr, CallExpr); + + method!(visit_mut_lit, Lit); + + method!(visit_mut_str, Str); +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use swc_core::{ + common::{FileName, Mark, SourceFile, SourceMap, errors::HANDLER}, + ecma::{ + ast::*, + codegen::{Emitter, text_writer::JsWriter}, + parser::parse_file_as_module, + transforms::base::resolver, + visit::{AstParentKind, VisitMut, VisitMutWith, VisitMutWithPath, fields::*}, + }, + testing::run_test, + }; + + use super::{ApplyVisitors, VisitorFactory}; + + fn parse(fm:&SourceFile) -> Module { + let mut m = + parse_file_as_module(fm, Default::default(), EsVersion::latest(), None, &mut vec![]) + .map_err(|err| HANDLER.with(|handler| err.into_diagnostic(handler).emit())) + .unwrap(); + + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + m.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false)); + + m + } + + struct StrReplacer<'a> { + from:&'a str, + to:&'a str, + } + + impl VisitorFactory for Box> { + fn create<'a>(&'a self) -> Box { Box::new(&**self) } + } + + impl VisitMut for &'_ StrReplacer<'_> { + fn visit_mut_str(&mut self, s:&mut Str) { + s.value = s.value.replace(self.from, self.to).into(); + s.raw = None; + } + } + + fn replacer(from:&'static str, to:&'static str) -> impl VisitorFactory { + Box::new(StrReplacer { from, to }) + } + + fn to_js(m:&Module, cm:&Arc) -> String { + let mut bytes = Vec::new(); + let mut emitter = Emitter { + cfg:swc_core::ecma::codegen::Config::default().with_minify(true), + cm:cm.clone(), + comments:None, + wr:JsWriter::new(cm.clone(), "\n", &mut bytes, None), + }; + + emitter.emit_module(m).unwrap(); + + String::from_utf8(bytes).unwrap() + } + + #[test] + fn path_visitor() { + run_test(false, |cm, _handler| { + let fm = cm.new_source_file(FileName::Anon, "('foo', 'bar', ['baz']);".into()); + + let m = parse(&fm); + + let module_kind = AstParentKind::Module(ModuleField::Body(0)); + let module_item_kind = AstParentKind::ModuleItem(ModuleItemField::Stmt); + let stmt_kind = AstParentKind::Stmt(StmtField::Expr); + let expr_stmt_kind = AstParentKind::ExprStmt(ExprStmtField::Expr); + let expr_kind = AstParentKind::Expr(ExprField::Paren); + let paren_kind = AstParentKind::ParenExpr(ParenExprField::Expr); + let expr2_kind = AstParentKind::Expr(ExprField::Seq); + let seq_kind = AstParentKind::SeqExpr(SeqExprField::Exprs(1)); + let expr3_kind = AstParentKind::Expr(ExprField::Lit); + let lit_kind = AstParentKind::Lit(LitField::Str); + + { + let path = vec![ + module_kind, + module_item_kind, + stmt_kind, + expr_stmt_kind, + expr_kind, + paren_kind, + expr2_kind, + seq_kind, + expr3_kind, + lit_kind, + ]; + let bar_replacer = replacer("bar", "bar-success"); + + let mut m = m.clone(); + m.visit_mut_with_path( + &mut ApplyVisitors::new(vec![(&path, &bar_replacer)]), + &mut Default::default(), + ); + + let s = to_js(&m, &cm); + assert_eq!(s, r#"("foo","bar-success",["baz"]);"#); + } + + { + let wrong_path = vec![ + module_kind, + module_item_kind, + stmt_kind, + expr_stmt_kind, + // expr_kind, + paren_kind, + expr2_kind, + seq_kind, + expr3_kind, + lit_kind, + ]; + let bar_replacer = replacer("bar", "bar-success"); + + let mut m = m.clone(); + m.visit_mut_with_path( + &mut ApplyVisitors::new(vec![(&wrong_path, &bar_replacer)]), + &mut Default::default(), + ); + + let s = to_js(&m, &cm); + assert!(!s.contains("bar-success")); + } + + drop(m); + + Ok(()) + }) + .unwrap(); + } +} diff --git a/crates/turbopack-ecmascript/Source/references/amd.rs b/crates/turbopack-ecmascript/Source/references/amd.rs new file mode 100644 index 0000000000000..ff7bf43a895ee --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/amd.rs @@ -0,0 +1,273 @@ +use std::mem::take; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use swc_core::{ + common::DUMMY_SP, + ecma::{ + ast::{CallExpr, Callee, Expr, ExprOrSpread, Lit}, + utils::private_ident, + }, + quote, + quote_expr, +}; +use turbo_tasks::{ + RcStr, + ReadRef, + TryJoinIterExt, + Value, + ValueToString, + Vc, + debug::ValueDebugFormat, + trace::TraceRawVcs, +}; +use turbopack_core::{ + chunk::{ChunkableModuleReference, ChunkingContext}, + issue::IssueSource, + reference::ModuleReference, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request}, +}; +use turbopack_resolve::ecmascript::{cjs_resolve, try_to_severity}; + +use super::pattern_mapping::{PatternMapping, ResolveType::ChunkItem}; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::AstPath, +}; + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct AmdDefineAssetReference { + origin:Vc>, + request:Vc, + issue_source:Vc, + in_try:bool, +} + +#[turbo_tasks::value_impl] +impl AmdDefineAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + issue_source:Vc, + in_try:bool, + ) -> Vc { + Self::cell(AmdDefineAssetReference { origin, request, issue_source, in_try }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for AmdDefineAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + cjs_resolve( + self.origin, + self.request, + Some(self.issue_source), + try_to_severity(self.in_try), + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for AmdDefineAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("AMD define dependency {}", self.request.to_string().await?,).into(), + )) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for AmdDefineAssetReference {} + +#[derive(ValueDebugFormat, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, Clone)] +pub enum AmdDefineDependencyElement { + Request { request:Vc, request_str:String }, + Exports, + Module, + Require, +} + +#[derive( + ValueDebugFormat, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, Copy, Clone, +)] +pub enum AmdDefineFactoryType { + Unknown, + Function, + Value, +} + +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub struct AmdDefineWithDependenciesCodeGen { + dependencies_requests:Vec, + origin:Vc>, + path:Vc, + factory_type:AmdDefineFactoryType, + issue_source:Vc, + in_try:bool, +} + +impl AmdDefineWithDependenciesCodeGen { + pub fn new( + dependencies_requests:Vec, + origin:Vc>, + path:Vc, + factory_type:AmdDefineFactoryType, + issue_source:Vc, + in_try:bool, + ) -> Vc { + Self::cell(AmdDefineWithDependenciesCodeGen { + dependencies_requests, + origin, + path, + factory_type, + issue_source, + in_try, + }) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for AmdDefineWithDependenciesCodeGen { + #[turbo_tasks::function] + async fn code_generation( + &self, + chunking_context:Vc>, + ) -> Result> { + let mut visitors = Vec::new(); + + let resolved_elements = self + .dependencies_requests + .iter() + .map(|element| { + async move { + Ok(match element { + AmdDefineDependencyElement::Request { request, request_str } => { + ResolvedElement::PatternMapping { + pattern_mapping:PatternMapping::resolve_request( + *request, + self.origin, + Vc::upcast(chunking_context), + cjs_resolve( + self.origin, + *request, + Some(self.issue_source), + try_to_severity(self.in_try), + ), + Value::new(ChunkItem), + ) + .await?, + request_str:request_str.to_string(), + } + }, + AmdDefineDependencyElement::Exports => { + ResolvedElement::Expr(quote!("exports" as Expr)) + }, + AmdDefineDependencyElement::Module => { + ResolvedElement::Expr(quote!("module" as Expr)) + }, + AmdDefineDependencyElement::Require => { + ResolvedElement::Expr(quote!("__turbopack_require__" as Expr)) + }, + }) + } + }) + .try_join() + .await?; + + let factory_type = self.factory_type; + + let path = self.path.await?; + visitors.push(create_visitor!(exact path, visit_mut_call_expr(call_expr: &mut CallExpr) { + transform_amd_factory(call_expr, &resolved_elements, factory_type) + })); + + Ok(CodeGeneration { visitors }.into()) + } +} + +enum ResolvedElement { + PatternMapping { pattern_mapping:ReadRef, request_str:String }, + Expr(Expr), +} + +/// Transforms `define([dep1, dep2], factory)` into: +/// ```js +/// __turbopack_export_value__( +/// factory( +/// __turbopack_require__(dep1), +/// __turbopack_require__(dep2), +/// ), +/// ); +/// ``` +fn transform_amd_factory( + call_expr:&mut CallExpr, + resolved_elements:&[ResolvedElement], + factory_type:AmdDefineFactoryType, +) { + let CallExpr { args, callee, .. } = call_expr; + let Some(factory) = take(args).pop().map(|e| e.expr) else { + return; + }; + + let deps = resolved_elements + .iter() + .map(|element| { + match element { + ResolvedElement::PatternMapping { pattern_mapping: pm, request_str: request } => { + let key_expr = Expr::Lit(Lit::Str(request.as_str().into())); + pm.create_require(key_expr) + }, + ResolvedElement::Expr(expr) => expr.clone(), + } + }) + .map(ExprOrSpread::from) + .collect(); + + match factory_type { + AmdDefineFactoryType::Unknown => { + // ((f, r = typeof f !== "function" ? f : f([...])) => r !== undefined && + // __turbopack_export_value__(r))(...) + let f = private_ident!("f"); + let call_f = Expr::Call(CallExpr { + args:deps, + callee:Callee::Expr(Box::new(Expr::Ident(f.clone()))), + span:DUMMY_SP, + type_args:None, + }); + *callee = Callee::Expr(quote_expr!( + "($f1, r = typeof $f2 !== \"function\" ? $f3 : $call_f) => r !== undefined && \ + __turbopack_export_value(r)", + f1 = f.clone(), + f2 = f.clone(), + f3 = f, + call_f: Expr = call_f + )); + args.push(ExprOrSpread { expr:factory, spread:None }); + }, + AmdDefineFactoryType::Function => { + // (r => r !== undefined && __turbopack_export_value__(r))(...([...])) + *callee = + Callee::Expr(quote_expr!("r => r !== undefined && __turbopack_export_value__(r)")); + args.push(ExprOrSpread { + expr:Box::new(Expr::Call(CallExpr { + args:deps, + callee:Callee::Expr(factory), + span:DUMMY_SP, + type_args:None, + })), + spread:None, + }); + }, + AmdDefineFactoryType::Value => { + // __turbopack_export_value__(...) + *callee = Callee::Expr(quote_expr!("__turbopack_export_value__")); + args.push(ExprOrSpread { expr:factory, spread:None }); + }, + } +} diff --git a/crates/turbopack-ecmascript/Source/references/async_module.rs b/crates/turbopack-ecmascript/Source/references/async_module.rs new file mode 100644 index 0000000000000..f38411d80b4b1 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/async_module.rs @@ -0,0 +1,251 @@ +use anyhow::Result; +use indexmap::IndexSet; +use serde::{Deserialize, Serialize}; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{ArrayLit, ArrayPat, Expr, Ident, Program}, + quote, +}; +use turbo_tasks::{ReadRef, TryFlatJoinIterExt, TryJoinIterExt, Vc, trace::TraceRawVcs}; +use turbopack_core::{ + chunk::{ + AsyncModuleInfo, + ChunkableModule, + ChunkableModuleReference, + ChunkingContext, + ChunkingType, + }, + reference::{ModuleReference, ModuleReferences}, + resolve::ExternalType, +}; + +use super::esm::base::ReferencedAsset; +use crate::{code_gen::CodeGeneration, create_visitor, references::esm::base::insert_hoisted_stmt}; + +/// Information needed for generating the async module wrapper for +/// [EcmascriptChunkItem](crate::chunk::EcmascriptChunkItem)s. +#[derive(PartialEq, Eq, Default, Debug, Clone, Serialize, Deserialize, TraceRawVcs)] +pub struct AsyncModuleOptions { + pub has_top_level_await:bool, +} + +/// Option<[AsyncModuleOptions]>. +#[turbo_tasks::value(transparent)] +pub struct OptionAsyncModuleOptions(Option); + +#[turbo_tasks::value_impl] +impl OptionAsyncModuleOptions { + #[turbo_tasks::function] + pub(crate) fn none() -> Vc { Vc::cell(None) } +} + +/// Contains the information necessary to decide if an ecmascript module is +/// async. +/// +/// It will check if the current module or any of it's children contain a top +/// level await statement or is referencing an external ESM module. +#[turbo_tasks::value(shared)] +pub struct AsyncModule { + pub has_top_level_await:bool, + pub import_externals:bool, +} + +/// Option<[AsyncModule]>. +#[turbo_tasks::value(transparent)] +pub struct OptionAsyncModule(Option>); + +#[turbo_tasks::value_impl] +impl OptionAsyncModule { + /// Create an empty [OptionAsyncModule]. + #[turbo_tasks::function] + pub fn none() -> Vc { Vc::cell(None) } + + #[turbo_tasks::function] + pub async fn module_options( + self: Vc, + async_module_info:Option>, + ) -> Result> { + if let Some(async_module) = &*self.await? { + return Ok(async_module.module_options(async_module_info)); + } + + Ok(OptionAsyncModuleOptions::none()) + } +} + +#[turbo_tasks::value(transparent)] +struct AsyncModuleIdents(IndexSet); + +async fn get_inherit_async_referenced_asset( + r:Vc>, +) -> Result>> { + let Some(r) = Vc::try_resolve_downcast::>(r).await? else { + return Ok(None); + }; + let Some(ty) = *r.chunking_type().await? else { + return Ok(None); + }; + if !matches!(ty, ChunkingType::ParallelInheritAsync) { + return Ok(None); + }; + let referenced_asset:turbo_tasks::ReadRef = + ReferencedAsset::from_resolve_result(r.resolve_reference()).await?; + Ok(Some(referenced_asset)) +} + +#[turbo_tasks::value_impl] +impl AsyncModule { + #[turbo_tasks::function] + async fn get_async_idents( + &self, + chunking_context:Vc>, + async_module_info:Vc, + references:Vc, + ) -> Result> { + let async_module_info = async_module_info.await?; + + let reference_idents = references + .await? + .iter() + .map(|r| { + async { + let Some(referenced_asset) = get_inherit_async_referenced_asset(*r).await? + else { + return Ok(None); + }; + Ok(match &*referenced_asset { + ReferencedAsset::External(_, ExternalType::EcmaScriptModule) => { + if self.import_externals { + referenced_asset.get_ident().await? + } else { + None + } + }, + ReferencedAsset::Some(placeable) => { + let chunk_item = placeable + .as_chunk_item(Vc::upcast(chunking_context)) + .resolve() + .await?; + if async_module_info.referenced_async_modules.contains(&chunk_item) { + referenced_asset.get_ident().await? + } else { + None + } + }, + ReferencedAsset::External(..) => None, + ReferencedAsset::None => None, + }) + } + }) + .try_flat_join() + .await?; + + Ok(Vc::cell(IndexSet::from_iter(reference_idents))) + } + + #[turbo_tasks::function] + pub(crate) async fn is_self_async(&self, references:Vc) -> Result> { + if self.has_top_level_await { + return Ok(Vc::cell(true)); + } + + Ok(Vc::cell( + self.import_externals + && references + .await? + .iter() + .map(|r| { + async { + let Some(referenced_asset) = + get_inherit_async_referenced_asset(*r).await? + else { + return Ok(false); + }; + Ok(matches!( + &*referenced_asset, + ReferencedAsset::External(_, ExternalType::EcmaScriptModule) + )) + } + }) + .try_join() + .await? + .iter() + .any(|&b| b), + )) + } + + /// Returns + #[turbo_tasks::function] + pub async fn module_options( + self: Vc, + async_module_info:Option>, + ) -> Result> { + if async_module_info.is_none() { + return Ok(Vc::cell(None)); + } + + Ok(Vc::cell(Some(AsyncModuleOptions { + has_top_level_await:self.await?.has_top_level_await, + }))) + } + + #[turbo_tasks::function] + pub async fn code_generation( + self: Vc, + chunking_context:Vc>, + async_module_info:Option>, + references:Vc, + ) -> Result> { + let mut visitors = Vec::new(); + + if let Some(async_module_info) = async_module_info { + let async_idents = + self.get_async_idents(chunking_context, async_module_info, references).await?; + + if !async_idents.is_empty() { + visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { + add_async_dependency_handler(program, &async_idents); + })); + } + } + + Ok(CodeGeneration { visitors }.into()) + } +} + +fn add_async_dependency_handler(program:&mut Program, idents:&IndexSet) { + let idents = idents + .iter() + .map(|ident| Ident::new(ident.clone().into(), DUMMY_SP)) + .collect::>(); + + let stmt = quote!( + "var __turbopack_async_dependencies__ = __turbopack_handle_async_dependencies__($deps);" + as Stmt, + deps: Expr = Expr::Array(ArrayLit { + span: DUMMY_SP, + elems: idents + .iter() + .map(|ident| { Some(Expr::Ident(ident.clone()).into()) }) + .collect(), + }), + ); + + insert_hoisted_stmt(program, stmt); + + let stmt = quote!( + "($deps = __turbopack_async_dependencies__.then ? (await \ + __turbopack_async_dependencies__)() : __turbopack_async_dependencies__);" as Stmt, + deps: AssignTarget = ArrayPat { + span: DUMMY_SP, + elems: idents + .into_iter() + .map(|ident| { Some(ident.into()) }) + .collect(), + optional: false, + type_ann: None, + }.into(), + ); + + insert_hoisted_stmt(program, stmt); +} diff --git a/crates/turbopack-ecmascript/Source/references/cjs.rs b/crates/turbopack-ecmascript/Source/references/cjs.rs new file mode 100644 index 0000000000000..9fdd7e2a874e9 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/cjs.rs @@ -0,0 +1,299 @@ +use anyhow::Result; +use swc_core::{ + common::{DUMMY_SP, util::take::Take}, + ecma::ast::{CallExpr, Expr, ExprOrSpread, Ident, Lit}, + quote, +}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ChunkableModuleReference, ChunkingContext}, + issue::IssueSource, + reference::ModuleReference, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request}, +}; +use turbopack_resolve::ecmascript::{cjs_resolve, try_to_severity}; + +use super::pattern_mapping::{PatternMapping, ResolveType::ChunkItem}; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::AstPath, +}; + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct CjsAssetReference { + pub origin:Vc>, + pub request:Vc, + pub issue_source:Vc, + pub in_try:bool, +} + +#[turbo_tasks::value_impl] +impl CjsAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + issue_source:Vc, + in_try:bool, + ) -> Vc { + Self::cell(CjsAssetReference { origin, request, issue_source, in_try }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for CjsAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + cjs_resolve( + self.origin, + self.request, + Some(self.issue_source), + try_to_severity(self.in_try), + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for CjsAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("generic commonjs {}", self.request.to_string().await?,).into(), + )) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for CjsAssetReference {} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct CjsRequireAssetReference { + pub origin:Vc>, + pub request:Vc, + pub path:Vc, + pub issue_source:Vc, + pub in_try:bool, +} + +#[turbo_tasks::value_impl] +impl CjsRequireAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + path:Vc, + issue_source:Vc, + in_try:bool, + ) -> Vc { + Self::cell(CjsRequireAssetReference { origin, request, path, issue_source, in_try }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for CjsRequireAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + cjs_resolve( + self.origin, + self.request, + Some(self.issue_source), + try_to_severity(self.in_try), + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for CjsRequireAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("require {}", self.request.to_string().await?,).into())) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for CjsRequireAssetReference {} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for CjsRequireAssetReference { + #[turbo_tasks::function] + async fn code_generation( + &self, + chunking_context:Vc>, + ) -> Result> { + let pm = PatternMapping::resolve_request( + self.request, + self.origin, + Vc::upcast(chunking_context), + cjs_resolve( + self.origin, + self.request, + Some(self.issue_source), + try_to_severity(self.in_try), + ), + Value::new(ChunkItem), + ) + .await?; + let mut visitors = Vec::new(); + + let path = &self.path.await?; + visitors.push(create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + let old_expr = expr.take(); + let message = if let Expr::Call(CallExpr { args, ..}) = old_expr { + match args.into_iter().next() { + Some(ExprOrSpread { spread: None, expr: key_expr }) => { + *expr = pm.create_require(*key_expr); + return; + } + Some(ExprOrSpread { spread: Some(_), expr: _ }) => { + "spread operator is not analyse-able in require() expressions." + } + _ => { + "require() expressions require at least 1 argument" + } + } + } else { + "visitor must be executed on a CallExpr" + }; + *expr = quote!( + "(() => { throw new Error($message); })()" as Expr, + message: Expr = Expr::Lit(Lit::Str(message.into())) + ); + })); + + Ok(CodeGeneration { visitors }.into()) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct CjsRequireResolveAssetReference { + pub origin:Vc>, + pub request:Vc, + pub path:Vc, + pub issue_source:Vc, + pub in_try:bool, +} + +#[turbo_tasks::value_impl] +impl CjsRequireResolveAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + path:Vc, + issue_source:Vc, + in_try:bool, + ) -> Vc { + Self::cell(CjsRequireResolveAssetReference { origin, request, path, issue_source, in_try }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for CjsRequireResolveAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + cjs_resolve( + self.origin, + self.request, + Some(self.issue_source), + try_to_severity(self.in_try), + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for CjsRequireResolveAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("require.resolve {}", self.request.to_string().await?,).into())) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for CjsRequireResolveAssetReference {} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for CjsRequireResolveAssetReference { + #[turbo_tasks::function] + async fn code_generation( + &self, + chunking_context:Vc>, + ) -> Result> { + let pm = PatternMapping::resolve_request( + self.request, + self.origin, + Vc::upcast(chunking_context), + cjs_resolve( + self.origin, + self.request, + Some(self.issue_source), + try_to_severity(self.in_try), + ), + Value::new(ChunkItem), + ) + .await?; + let mut visitors = Vec::new(); + + let path = &self.path.await?; + // Inline the result of the `require.resolve` call as a literal. + visitors.push(create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + if let Expr::Call(call_expr) = expr { + let args = std::mem::take(&mut call_expr.args); + *expr = match args.into_iter().next() { + Some(ExprOrSpread { expr, spread: None }) => pm.create_id(*expr), + other => { + let message = match other { + // These are SWC bugs: https://github.com/swc-project/swc/issues/5394 + Some(ExprOrSpread { spread: Some(_), expr: _ }) => { + "spread operator is not analyse-able in require() expressions." + } + _ => { + "require() expressions require at least 1 argument" + } + }; + quote!( + "(() => { throw new Error($message); })()" as Expr, + message: Expr = Expr::Lit(Lit::Str(message.into())) + ) + }, + }; + } + // CjsRequireResolveAssetReference will only be used for Expr::Call. + // Due to eventual consistency the path might match something else, + // but we can ignore that as it will be recomputed anyway. + })); + + Ok(CodeGeneration { visitors }.into()) + } +} + +#[turbo_tasks::value(shared)] +#[derive(Hash, Debug)] +pub struct CjsRequireCacheAccess { + pub path:Vc, +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for CjsRequireCacheAccess { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let mut visitors = Vec::new(); + + let path = &self.path.await?; + visitors.push(create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + if let Expr::Member(_) = expr { + *expr = Expr::Ident(Ident::new("__turbopack_cache__".into(), DUMMY_SP)); + } else { + unreachable!("`CjsRequireCacheAccess` is only created from `MemberExpr`"); + } + })); + + Ok(CodeGeneration { visitors }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/constant_condition.rs b/crates/turbopack-ecmascript/Source/references/constant_condition.rs new file mode 100644 index 0000000000000..86955399637a2 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/constant_condition.rs @@ -0,0 +1,53 @@ +use anyhow::Result; +use swc_core::quote; +use turbo_tasks::{Value, Vc}; +use turbopack_core::chunk::ChunkingContext; + +use super::AstPath; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, +}; + +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(Debug, Clone, Copy, Hash, PartialOrd, Ord)] +pub enum ConstantConditionValue { + Truthy, + Falsy, + Nullish, +} + +#[turbo_tasks::value] +pub struct ConstantCondition { + value:ConstantConditionValue, + path:Vc, +} + +#[turbo_tasks::value_impl] +impl ConstantCondition { + #[turbo_tasks::function] + pub fn new(value:Value, path:Vc) -> Vc { + Self::cell(ConstantCondition { value:value.into_value(), path }) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for ConstantCondition { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let value = self.value; + let visitors = [create_visitor!(exact &self.path.await?, visit_mut_expr(expr: &mut Expr) { + *expr = match value { + ConstantConditionValue::Truthy => quote!("(\"TURBOPACK compile-time truthy\", 1)" as Expr), + ConstantConditionValue::Falsy => quote!("(\"TURBOPACK compile-time falsy\", 0)" as Expr), + ConstantConditionValue::Nullish => quote!("(\"TURBOPACK compile-time nullish\", null)" as Expr), + }; + })] + .into(); + + Ok(CodeGeneration { visitors }.cell()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/constant_value.rs b/crates/turbopack-ecmascript/Source/references/constant_value.rs new file mode 100644 index 0000000000000..97fd8455688e2 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/constant_value.rs @@ -0,0 +1,47 @@ +use anyhow::Result; +use swc_core::quote; +use turbo_tasks::{Value, Vc}; +use turbopack_core::{chunk::ChunkingContext, compile_time_info::CompileTimeDefineValue}; + +use super::AstPath; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, +}; + +#[turbo_tasks::value] +pub struct ConstantValue { + value:CompileTimeDefineValue, + path:Vc, +} + +#[turbo_tasks::value_impl] +impl ConstantValue { + #[turbo_tasks::function] + pub fn new(value:Value, path:Vc) -> Vc { + Self::cell(ConstantValue { value:value.into_value(), path }) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for ConstantValue { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let value = self.value.clone(); + let path = &self.path.await?; + + let visitor = create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + *expr = match value { + CompileTimeDefineValue::Bool(true) => quote!("(\"TURBOPACK compile-time value\", true)" as Expr), + CompileTimeDefineValue::Bool(false) => quote!("(\"TURBOPACK compile-time value\", false)" as Expr), + CompileTimeDefineValue::String(ref s) => quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = s.to_string().into()), + CompileTimeDefineValue::JSON(ref s) => quote!("(\"TURBOPACK compile-time value\", JSON.parse($e))" as Expr, e: Expr = s.to_string().into()), + }; + }); + + Ok(CodeGeneration { visitors:vec![visitor] }.cell()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/dynamic_expression.rs b/crates/turbopack-ecmascript/Source/references/dynamic_expression.rs new file mode 100644 index 0000000000000..f860118838aa8 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/dynamic_expression.rs @@ -0,0 +1,62 @@ +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use swc_core::quote; +use turbo_tasks::{Vc, debug::ValueDebugFormat, trace::TraceRawVcs}; +use turbopack_core::chunk::ChunkingContext; + +use super::AstPath; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, +}; + +#[derive(PartialEq, Eq, TraceRawVcs, Serialize, Deserialize, ValueDebugFormat)] +enum DynamicExpressionType { + Promise, + Normal, +} + +#[turbo_tasks::value] +pub struct DynamicExpression { + path:Vc, + ty:DynamicExpressionType, +} + +#[turbo_tasks::value_impl] +impl DynamicExpression { + #[turbo_tasks::function] + pub fn new(path:Vc) -> Vc { + Self::cell(DynamicExpression { path, ty:DynamicExpressionType::Normal }) + } + + #[turbo_tasks::function] + pub fn new_promise(path:Vc) -> Vc { + Self::cell(DynamicExpression { path, ty:DynamicExpressionType::Promise }) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for DynamicExpression { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let path = &self.path.await?; + + let visitor = match self.ty { + DynamicExpressionType::Normal => { + create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + *expr = quote!("(() => { const e = new Error(\"Cannot find module as expression is too dynamic\"); e.code = 'MODULE_NOT_FOUND'; throw e; })()" as Expr); + }) + }, + DynamicExpressionType::Promise => { + create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + *expr = quote!("Promise.resolve().then(() => { const e = new Error(\"Cannot find module as expression is too dynamic\"); e.code = 'MODULE_NOT_FOUND'; throw e; })" as Expr); + }) + }, + }; + + Ok(CodeGeneration { visitors:vec![visitor] }.cell()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/base.rs b/crates/turbopack-ecmascript/Source/references/esm/base.rs new file mode 100644 index 0000000000000..752e498bea764 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/base.rs @@ -0,0 +1,390 @@ +use anyhow::{Result, anyhow, bail}; +use lazy_static::lazy_static; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{self, Expr, ExprStmt, Ident, Lit, ModuleItem, Program, Script, Stmt}, + quote, +}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ + ChunkItemExt, + ChunkableModule, + ChunkableModuleReference, + ChunkingContext, + ChunkingType, + ChunkingTypeOption, + ModuleId, + }, + issue::{IssueSeverity, IssueSource}, + module::Module, + reference::ModuleReference, + reference_type::{EcmaScriptModulesReferenceSubType, ImportWithType}, + resolve::{ + ExternalType, + ModulePart, + ModuleResolveResult, + ModuleResolveResultItem, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + }, +}; +use turbopack_resolve::ecmascript::esm_resolve; + +use crate::{ + analyzer::imports::ImportAnnotations, + chunk::EcmascriptChunkPlaceable, + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + magic_identifier, + references::util::{request_to_string, throw_module_not_found_expr}, + tree_shake::{TURBOPACK_PART_IMPORT_SOURCE, asset::EcmascriptModulePartAsset}, +}; + +#[turbo_tasks::value] +pub enum ReferencedAsset { + Some(Vc>), + External(RcStr, ExternalType), + None, +} + +impl ReferencedAsset { + pub async fn get_ident(&self) -> Result> { + Ok(match self { + ReferencedAsset::Some(asset) => Some(Self::get_ident_from_placeable(asset).await?), + ReferencedAsset::External(request, ty) => { + Some(magic_identifier::mangle(&format!("{ty} external {request}"))) + }, + ReferencedAsset::None => None, + }) + } + + pub(crate) async fn get_ident_from_placeable( + asset:&Vc>, + ) -> Result { + let path = asset.ident().to_string().await?; + Ok(magic_identifier::mangle(&format!("imported module {}", path))) + } +} + +#[turbo_tasks::value_impl] +impl ReferencedAsset { + #[turbo_tasks::function] + pub async fn from_resolve_result(resolve_result:Vc) -> Result> { + // TODO handle multiple keyed results + for (_key, result) in resolve_result.await?.primary.iter() { + match result { + ModuleResolveResultItem::External(request, ty) => { + return Ok(ReferencedAsset::External(request.clone(), *ty).cell()); + }, + &ModuleResolveResultItem::Module(module) => { + if let Some(placeable) = + Vc::try_resolve_downcast::>(module) + .await? + { + return Ok(ReferencedAsset::cell(ReferencedAsset::Some(placeable))); + } + }, + // TODO ignore should probably be handled differently + _ => {}, + } + } + Ok(ReferencedAsset::cell(ReferencedAsset::None)) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct EsmAssetReference { + pub origin:Vc>, + pub request:Vc, + pub annotations:ImportAnnotations, + pub issue_source:Option>, + pub export_name:Option>, + pub import_externals:bool, +} + +/// A list of [EsmAssetReference]s +#[turbo_tasks::value(transparent)] +pub struct EsmAssetReferences(Vec>); + +impl EsmAssetReference { + fn get_origin(&self) -> Vc> { + let mut origin = self.origin; + if let Some(transition) = self.annotations.transition() { + origin = origin.with_transition(transition.into()); + } + origin + } +} + +#[turbo_tasks::value_impl] +impl EsmAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + issue_source:Option>, + annotations:Value, + export_name:Option>, + import_externals:bool, + ) -> Vc { + Self::cell(EsmAssetReference { + origin, + request, + issue_source, + annotations:annotations.into_value(), + export_name, + import_externals, + }) + } + + #[turbo_tasks::function] + pub(crate) fn get_referenced_asset(self: Vc) -> Vc { + ReferencedAsset::from_resolve_result(self.resolve_reference()) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for EsmAssetReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Result> { + let ty = if matches!(self.annotations.module_type(), Some("json")) { + EcmaScriptModulesReferenceSubType::ImportWithType(ImportWithType::Json) + } else if let Some(part) = &self.export_name { + EcmaScriptModulesReferenceSubType::ImportPart(*part) + } else { + EcmaScriptModulesReferenceSubType::Import + }; + + if let Request::Module { module, .. } = &*self.request.await? { + if module == TURBOPACK_PART_IMPORT_SOURCE { + if let Some(part) = self.export_name { + let full_module:Vc = + Vc::try_resolve_downcast_type(self.origin) + .await? + .expect("EsmAssetReference origin should be a EcmascriptModuleAsset"); + + let module = + EcmascriptModulePartAsset::new(full_module, part, self.import_externals); + + return Ok(ModuleResolveResult::module(Vc::upcast(module)).cell()); + } + + bail!("export_name is required for part import") + } + } + + Ok(esm_resolve( + self.get_origin().resolve().await?, + self.request, + Value::new(ty), + IssueSeverity::Error.cell(), + self.issue_source, + )) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EsmAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("import {} with {}", self.request.to_string().await?, self.annotations).into(), + )) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for EsmAssetReference { + #[turbo_tasks::function] + fn chunking_type(&self) -> Result> { + Ok(Vc::cell(if let Some(chunking_type) = self.annotations.chunking_type() { + match chunking_type { + "parallel" => Some(ChunkingType::ParallelInheritAsync), + "none" => None, + _ => return Err(anyhow!("unknown chunking_type: {}", chunking_type)), + } + } else { + Some(ChunkingType::ParallelInheritAsync) + })) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for EsmAssetReference { + #[turbo_tasks::function] + async fn code_generation( + self: Vc, + chunking_context:Vc>, + ) -> Result> { + let mut visitors = Vec::new(); + + let this = &*self.await?; + let chunking_type = self.chunking_type().await?; + let resolved = self.resolve_reference().await?; + + // Insert code that throws immediately at time of import if a request is + // unresolvable + if resolved.is_unresolveable_ref() { + let request = request_to_string(this.request).await?.to_string(); + visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { + insert_hoisted_stmt(program, Stmt::Expr(ExprStmt { + expr: Box::new(throw_module_not_found_expr( + &request + )), + span: DUMMY_SP, + })); + })); + + return Ok(CodeGeneration { visitors }.into()); + } + + // only chunked references can be imported + if chunking_type.is_some() { + let referenced_asset = self.get_referenced_asset().await?; + let import_externals = this.import_externals; + if let Some(ident) = referenced_asset.get_ident().await? { + match &*referenced_asset { + ReferencedAsset::Some(asset) => { + let id = asset.as_chunk_item(Vc::upcast(chunking_context)).id().await?; + visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { + let stmt = quote!( + "var $name = __turbopack_import__($id);" as Stmt, + name = Ident::new(ident.clone().into(), DUMMY_SP), + id: Expr = Expr::Lit(match &*id { + ModuleId::String(s) => s.clone().as_str().into(), + ModuleId::Number(n) => (*n as f64).into(), + }) + ); + insert_hoisted_stmt(program, stmt); + })); + }, + ReferencedAsset::External(request, ExternalType::EcmaScriptModule) => { + if !*chunking_context.environment().supports_esm_externals().await? { + bail!( + "the chunking context ({}) does not support external modules (esm \ + request: {})", + chunking_context.name().await?, + request + ); + } + let request = request.clone(); + visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { + let stmt = if import_externals { + quote!( + "var $name = __turbopack_external_import__($id);" as Stmt, + name = Ident::new(ident.clone().into(), DUMMY_SP), + id: Expr = Expr::Lit(request.to_string().into()) + ) + } else { + quote!( + "var $name = __turbopack_external_require__($id, true);" as Stmt, + name = Ident::new(ident.clone().into(), DUMMY_SP), + id: Expr = Expr::Lit(request.to_string().into()) + ) + }; + insert_hoisted_stmt(program, stmt); + })); + }, + ReferencedAsset::External( + request, + ExternalType::CommonJs | ExternalType::Url, + ) => { + if !*chunking_context.environment().supports_commonjs_externals().await? { + bail!( + "the chunking context ({}) does not support external modules \ + (request: {})", + chunking_context.name().await?, + request + ); + } + let request = request.clone(); + visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { + let stmt = quote!( + "var $name = __turbopack_external_require__($id, true);" as Stmt, + name = Ident::new(ident.clone().into(), DUMMY_SP), + id: Expr = Expr::Lit(request.to_string().into()) + ); + insert_hoisted_stmt(program, stmt); + })); + }, + #[allow(unreachable_patterns)] + ReferencedAsset::External(request, ty) => { + bail!( + "Unsupported external type {:?} for ESM reference with request: {:?}", + ty, + request + ) + }, + ReferencedAsset::None => {}, + } + } + } + + Ok(CodeGeneration { visitors }.into()) + } +} + +lazy_static! { + static ref ESM_HOISTING_LOCATION: &'static str = + Box::leak(Box::new(magic_identifier::mangle("ecmascript hoisting location"))); +} + +pub(crate) fn insert_hoisted_stmt(program:&mut Program, stmt:Stmt) { + match program { + Program::Module(ast::Module { body, .. }) => { + let pos = body.iter().position(|item| { + if let ModuleItem::Stmt(Stmt::Expr(ExprStmt { + expr: box Expr::Lit(Lit::Str(s)), + .. + })) = item + { + &*s.value == *ESM_HOISTING_LOCATION + } else { + false + } + }); + if let Some(pos) = pos { + let has_stmt = body[0..pos].iter().any(|item| { + if let ModuleItem::Stmt(item_stmt) = item { stmt == *item_stmt } else { false } + }); + if !has_stmt { + body.insert(pos, ModuleItem::Stmt(stmt)); + } + } else { + body.splice( + 0..0, + [ + ModuleItem::Stmt(stmt), + ModuleItem::Stmt(Stmt::Expr(ExprStmt { + expr:Box::new(Expr::Lit(Lit::Str((*ESM_HOISTING_LOCATION).into()))), + span:DUMMY_SP, + })), + ], + ); + } + }, + Program::Script(Script { body, .. }) => { + let pos = body.iter().position(|item| { + if let Stmt::Expr(ExprStmt { expr: box Expr::Lit(Lit::Str(s)), .. }) = item { + &*s.value == *ESM_HOISTING_LOCATION + } else { + false + } + }); + if let Some(pos) = pos { + body.insert(pos, stmt); + } else { + body.insert( + 0, + Stmt::Expr(ExprStmt { + expr:Box::new(Expr::Lit(Lit::Str((*ESM_HOISTING_LOCATION).into()))), + span:DUMMY_SP, + }), + ); + body.insert(0, stmt); + } + }, + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/binding.rs b/crates/turbopack-ecmascript/Source/references/esm/binding.rs new file mode 100644 index 0000000000000..aae036ca7a65e --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/binding.rs @@ -0,0 +1,177 @@ +use anyhow::Result; +use swc_core::{ + common::{Span, SyntaxContext}, + ecma::{ + ast::{ + ComputedPropName, + Expr, + Ident, + KeyValueProp, + Lit, + MemberExpr, + MemberProp, + Number, + Prop, + PropName, + SeqExpr, + SimpleAssignTarget, + Str, + }, + visit::fields::{CalleeField, PropField}, + }, +}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::chunk::ChunkingContext; + +use super::EsmAssetReference; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::AstPath, +}; + +#[turbo_tasks::value(shared)] +#[derive(Hash, Debug)] +pub struct EsmBinding { + pub reference:Vc, + pub export:Option, + pub ast_path:Vc, +} + +#[turbo_tasks::value_impl] +impl EsmBinding { + #[turbo_tasks::function] + pub fn new( + reference:Vc, + export:Option, + ast_path:Vc, + ) -> Vc { + EsmBinding { reference, export, ast_path }.cell() + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for EsmBinding { + #[turbo_tasks::function] + async fn code_generation( + self: Vc, + _context:Vc>, + ) -> Result> { + let this = self.await?; + let mut visitors = Vec::new(); + let imported_module = this.reference.get_referenced_asset(); + + fn make_expr(imported_module:&str, export:Option<&str>, span:Span, in_call:bool) -> Expr { + let span = span.with_ctxt(SyntaxContext::empty()); + if let Some(export) = export { + let mut expr = Expr::Member(MemberExpr { + span, + obj:Box::new(Expr::Ident(Ident::new(imported_module.into(), span))), + prop:MemberProp::Computed(ComputedPropName { + span, + expr:Box::new(Expr::Lit(Lit::Str(Str { + span, + value:export.into(), + raw:None, + }))), + }), + }); + if in_call { + expr = Expr::Seq(SeqExpr { + exprs:vec![ + Box::new(Expr::Lit(Lit::Num(Number { span, value:0.0, raw:None }))), + Box::new(expr), + ], + span, + }); + } + expr + } else { + Expr::Ident(Ident::new(imported_module.into(), span)) + } + } + + let mut ast_path = this.ast_path.await?.clone_value(); + let imported_module = imported_module.await?.get_ident().await?; + + loop { + match ast_path.last() { + // Shorthand properties get special treatment because we need to rewrite them to + // normal key-value pairs. + Some(swc_core::ecma::visit::AstParentKind::Prop(PropField::Shorthand)) => { + ast_path.pop(); + visitors.push( + create_visitor!(exact ast_path, visit_mut_prop(prop: &mut Prop) { + if let Prop::Shorthand(ident) = prop { + // TODO: Merge with the above condition when https://rust-lang.github.io/rfcs/2497-if-let-chains.html lands. + if let Some(imported_ident) = imported_module.as_deref() { + *prop = Prop::KeyValue(KeyValueProp { + key: PropName::Ident(ident.clone()), + value: Box::new(make_expr(imported_ident, this.export.as_deref(), ident.span, false)) + }); + } + } + }), + ); + break; + }, + // Any other expression can be replaced with the import accessor. + Some(swc_core::ecma::visit::AstParentKind::Expr(_)) => { + ast_path.pop(); + let in_call = matches!( + ast_path.last(), + Some(swc_core::ecma::visit::AstParentKind::Callee(CalleeField::Expr)) + ); + + visitors.push( + create_visitor!(exact ast_path, visit_mut_expr(expr: &mut Expr) { + if let Some(ident) = imported_module.as_deref() { + use swc_core::common::Spanned; + *expr = make_expr(ident, this.export.as_deref(), expr.span(), in_call); + } + // If there's no identifier for the imported module, + // resolution failed and will insert code that throws + // before this expression is reached. Leave behind the original identifier. + }), + ); + break; + }, + Some(swc_core::ecma::visit::AstParentKind::BindingIdent( + swc_core::ecma::visit::fields::BindingIdentField::Id, + )) => { + ast_path.pop(); + + // We need to handle LHS because of code like + // (function (RouteKind1){})(RouteKind || RouteKind = {}) + if let Some(swc_core::ecma::visit::AstParentKind::SimpleAssignTarget( + swc_core::ecma::visit::fields::SimpleAssignTargetField::Ident, + )) = ast_path.last() + { + ast_path.pop(); + + visitors.push( + create_visitor!(exact ast_path, visit_mut_simple_assign_target(l: &mut SimpleAssignTarget) { + if let Some(ident) = imported_module.as_deref() { + use swc_core::common::Spanned; + *l = match make_expr(ident, this.export.as_deref(), l.span(), false) { + Expr::Ident(ident) => SimpleAssignTarget::Ident(ident.into()), + Expr::Member(member) => SimpleAssignTarget::Member(member), + _ => unreachable!(), + }; + } + }), + ); + + break; + } + }, + Some(_) => { + ast_path.pop(); + }, + None => break, + } + } + + Ok(CodeGeneration { visitors }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/dynamic.rs b/crates/turbopack-ecmascript/Source/references/esm/dynamic.rs new file mode 100644 index 0000000000000..50945682a5bf5 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/dynamic.rs @@ -0,0 +1,152 @@ +use anyhow::Result; +use swc_core::{ + common::{DUMMY_SP, util::take::Take}, + ecma::ast::{CallExpr, Callee, Expr, ExprOrSpread, Lit}, + quote_expr, +}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ChunkableModuleReference, ChunkingContext, ChunkingType, ChunkingTypeOption}, + environment::ChunkLoading, + issue::IssueSource, + reference::ModuleReference, + reference_type::EcmaScriptModulesReferenceSubType, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request}, +}; +use turbopack_resolve::ecmascript::{esm_resolve, try_to_severity}; + +use super::super::pattern_mapping::{PatternMapping, ResolveType}; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::AstPath, +}; + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct EsmAsyncAssetReference { + pub origin:Vc>, + pub request:Vc, + pub path:Vc, + pub issue_source:Vc, + pub in_try:bool, + pub import_externals:bool, +} + +#[turbo_tasks::value_impl] +impl EsmAsyncAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + path:Vc, + issue_source:Vc, + in_try:bool, + import_externals:bool, + ) -> Vc { + Self::cell(EsmAsyncAssetReference { + origin, + request, + path, + issue_source, + in_try, + import_externals, + }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for EsmAsyncAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + esm_resolve( + self.origin, + self.request, + Value::new(EcmaScriptModulesReferenceSubType::DynamicImport), + try_to_severity(self.in_try), + Some(self.issue_source), + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EsmAsyncAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("dynamic import {}", self.request.to_string().await?,).into())) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for EsmAsyncAssetReference { + #[turbo_tasks::function] + fn chunking_type(&self) -> Vc { Vc::cell(Some(ChunkingType::Async)) } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for EsmAsyncAssetReference { + #[turbo_tasks::function] + async fn code_generation( + &self, + chunking_context:Vc>, + ) -> Result> { + let pm = PatternMapping::resolve_request( + self.request, + self.origin, + Vc::upcast(chunking_context), + esm_resolve( + self.origin, + self.request, + Value::new(EcmaScriptModulesReferenceSubType::DynamicImport), + try_to_severity(self.in_try), + Some(self.issue_source), + ), + if matches!(*chunking_context.environment().chunk_loading().await?, ChunkLoading::Edge) + { + Value::new(ResolveType::ChunkItem) + } else { + Value::new(ResolveType::AsyncChunkLoader) + }, + ) + .await?; + + let path = &self.path.await?; + let import_externals = self.import_externals; + + let visitor = create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + let old_expr = expr.take(); + let message = if let Expr::Call(CallExpr { args, ..}) = old_expr { + match args.into_iter().next() { + Some(ExprOrSpread { spread: None, expr: key_expr }) => { + *expr = pm.create_import(*key_expr, import_externals); + return; + } + // These are SWC bugs: https://github.com/swc-project/swc/issues/5394 + Some(ExprOrSpread { spread: Some(_), expr: _ }) => { + "spread operator is illegal in import() expressions." + } + _ => { + "import() expressions require at least 1 argument" + } + } + } else { + "visitor must be executed on a CallExpr" + }; + let error = quote_expr!( + "() => { throw new Error($message); }", + message: Expr = Expr::Lit(Lit::Str(message.into())) + ); + *expr = Expr::Call(CallExpr { + callee: Callee::Expr(quote_expr!("Promise.resolve().then")), + args: vec![ExprOrSpread { + spread: None, + expr: error, + }], + span: DUMMY_SP, + type_args: None, + }); + }); + + Ok(CodeGeneration { visitors:vec![visitor] }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/export.rs b/crates/turbopack-ecmascript/Source/references/esm/export.rs new file mode 100644 index 0000000000000..a8908935a706b --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/export.rs @@ -0,0 +1,541 @@ +use std::{ + collections::{BTreeMap, HashSet}, + ops::ControlFlow, +}; + +use anyhow::Result; +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{ + self, + ComputedPropName, + Expr, + ExprStmt, + Ident, + KeyValueProp, + Lit, + MemberExpr, + MemberProp, + ModuleItem, + ObjectLit, + Program, + Prop, + PropName, + PropOrSpread, + Script, + Stmt, + Str, + }, + quote, + quote_expr, +}; +use turbo_tasks::{RcStr, TryFlatJoinIterExt, ValueToString, Vc, trace::TraceRawVcs}; +use turbo_tasks_fs::glob::Glob; +use turbopack_core::{ + chunk::ChunkingContext, + ident::AssetIdent, + issue::{IssueExt, IssueSeverity, StyledString, analyze::AnalyzeIssue}, + module::Module, + reference::ModuleReference, +}; + +use super::base::ReferencedAsset; +use crate::{ + chunk::{EcmascriptChunkPlaceable, EcmascriptExports}, + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::esm::base::insert_hoisted_stmt, +}; + +#[derive(Clone, Hash, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] +pub enum EsmExport { + /// A local binding that is exported (export { a } or export const a = 1) + /// + /// The last bool is true if the binding is a mutable binding + LocalBinding(RcStr, bool), + /// An imported binding that is exported (export { a as b } from "...") + /// + /// The last bool is true if the binding is a mutable binding + ImportedBinding(Vc>, RcStr, bool), + /// An imported namespace that is exported (export * from "...") + ImportedNamespace(Vc>), + /// An error occurred while resolving the export + Error, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] +pub enum FoundExportType { + Found, + Dynamic, + NotFound, + SideEffects, + Unknown, +} + +#[turbo_tasks::value] +pub struct FollowExportsResult { + pub module:Vc>, + pub export_name:Option, + pub ty:FoundExportType, +} + +#[turbo_tasks::function] +pub async fn follow_reexports( + module:Vc>, + export_name:RcStr, + side_effect_free_packages:Vc, +) -> Result> { + if !*module.is_marked_as_side_effect_free(side_effect_free_packages).await? { + return Ok(FollowExportsResult::cell(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::SideEffects, + })); + } + let mut module = module; + let mut export_name = export_name; + loop { + let exports = module.get_exports().await?; + let EcmascriptExports::EsmExports(exports) = &*exports else { + return Ok(FollowExportsResult::cell(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::Dynamic, + })); + }; + + // Try to find the export in the local exports + let exports_ref = exports.await?; + if let Some(export) = exports_ref.exports.get(&export_name) { + match handle_declared_export(module, export_name, export, side_effect_free_packages) + .await? + { + ControlFlow::Continue((m, n)) => { + module = m; + export_name = n; + continue; + }, + ControlFlow::Break(result) => { + return Ok(result.cell()); + }, + } + } + + // Try to find the export in the star exports + if !exports_ref.star_exports.is_empty() && &*export_name != "default" { + let result = get_all_export_names(module).await?; + if let Some(m) = result.esm_exports.get(&export_name) { + module = *m; + continue; + } + return match &result.dynamic_exporting_modules[..] { + [] => { + Ok(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::NotFound, + } + .cell()) + }, + [module] => { + Ok(FollowExportsResult { + module:*module, + export_name:Some(export_name), + ty:FoundExportType::Dynamic, + } + .cell()) + }, + _ => { + Ok(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::Dynamic, + } + .cell()) + }, + }; + } + + return Ok(FollowExportsResult::cell(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::NotFound, + })); + } +} + +async fn handle_declared_export( + module:Vc>, + export_name:RcStr, + export:&EsmExport, + side_effect_free_packages:Vc, +) -> Result>, RcStr)>> { + match export { + EsmExport::ImportedBinding(reference, name, _) => { + if let ReferencedAsset::Some(module) = + *ReferencedAsset::from_resolve_result(reference.resolve_reference()).await? + { + if !*module.is_marked_as_side_effect_free(side_effect_free_packages).await? { + return Ok(ControlFlow::Break(FollowExportsResult { + module, + export_name:Some(name.clone()), + ty:FoundExportType::SideEffects, + })); + } + return Ok(ControlFlow::Continue((module, name.clone()))); + } + }, + EsmExport::ImportedNamespace(reference) => { + if let ReferencedAsset::Some(m) = + *ReferencedAsset::from_resolve_result(reference.resolve_reference()).await? + { + return Ok(ControlFlow::Break(FollowExportsResult { + module:m, + export_name:None, + ty:FoundExportType::Found, + })); + } + }, + EsmExport::LocalBinding(..) => { + return Ok(ControlFlow::Break(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::Found, + })); + }, + EsmExport::Error => { + return Ok(ControlFlow::Break(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::Unknown, + })); + }, + } + Ok(ControlFlow::Break(FollowExportsResult { + module, + export_name:Some(export_name), + ty:FoundExportType::Unknown, + })) +} + +#[turbo_tasks::value] +struct AllExportNamesResult { + esm_exports:IndexMap>>, + dynamic_exporting_modules:Vec>>, +} + +#[turbo_tasks::function] +async fn get_all_export_names( + module:Vc>, +) -> Result> { + let exports = module.get_exports().await?; + let EcmascriptExports::EsmExports(exports) = &*exports else { + return Ok(AllExportNamesResult { + esm_exports:IndexMap::new(), + dynamic_exporting_modules:vec![module], + } + .cell()); + }; + + let exports = exports.await?; + let mut esm_exports = IndexMap::new(); + let mut dynamic_exporting_modules = Vec::new(); + esm_exports.extend(exports.exports.keys().cloned().map(|n| (n, module))); + let star_export_names = exports + .star_exports + .iter() + .map(|esm_ref| { + async { + Ok( + if let ReferencedAsset::Some(m) = + *ReferencedAsset::from_resolve_result(esm_ref.resolve_reference()).await? + { + Some(get_all_export_names(m)) + } else { + None + }, + ) + } + }) + .try_flat_join() + .await?; + for star_export_names in star_export_names { + let star_export_names = star_export_names.await?; + esm_exports.extend(star_export_names.esm_exports.iter().map(|(k, &v)| (k.clone(), v))); + dynamic_exporting_modules + .extend(star_export_names.dynamic_exporting_modules.iter().copied()); + } + + Ok(AllExportNamesResult { esm_exports, dynamic_exporting_modules }.cell()) +} + +#[turbo_tasks::value] +pub struct ExpandStarResult { + pub star_exports:Vec, + pub has_dynamic_exports:bool, +} + +#[turbo_tasks::function] +pub async fn expand_star_exports( + root_module:Vc>, +) -> Result> { + let mut set = HashSet::new(); + let mut has_dynamic_exports = false; + let mut checked_modules = HashSet::new(); + checked_modules.insert(root_module); + let mut queue = vec![(root_module, root_module.get_exports())]; + while let Some((asset, exports)) = queue.pop() { + match &*exports.await? { + EcmascriptExports::EsmExports(exports) => { + let exports = exports.await?; + set.extend(exports.exports.keys().filter(|n| *n != "default").cloned()); + for esm_ref in exports.star_exports.iter() { + if let ReferencedAsset::Some(asset) = + &*ReferencedAsset::from_resolve_result(esm_ref.resolve_reference()).await? + { + if checked_modules.insert(*asset) { + queue.push((*asset, asset.get_exports())); + } + } + } + }, + EcmascriptExports::None => { + emit_star_exports_issue( + asset.ident(), + format!( + "export * used with module {} which has no exports\nTypescript only: Did \ + you want to export only types with `export type * from \"...\"`?\nNote: \ + Using `export type` is more efficient than `export *` as it won't emit \ + any runtime code.", + asset.ident().to_string().await? + ) + .into(), + ) + }, + EcmascriptExports::Value => { + emit_star_exports_issue( + asset.ident(), + format!( + "export * used with module {} which only has a default export (default \ + export is not exported with export *)\nDid you want to use `export {{ \ + default }} from \"...\";` instead?", + asset.ident().to_string().await? + ) + .into(), + ) + }, + EcmascriptExports::CommonJs => { + has_dynamic_exports = true; + emit_star_exports_issue( + asset.ident(), + format!( + "export * used with module {} which is a CommonJS module with exports \ + only available at runtime\nList all export names manually (`export {{ a, \ + b, c }} from \"...\") or rewrite the module to ESM, to avoid the \ + additional runtime code.`", + asset.ident().to_string().await? + ) + .into(), + ); + }, + EcmascriptExports::DynamicNamespace => { + has_dynamic_exports = true; + }, + } + } + + Ok(ExpandStarResult { star_exports:set.into_iter().collect(), has_dynamic_exports }.cell()) +} + +fn emit_star_exports_issue(source_ident:Vc, message:RcStr) { + AnalyzeIssue { + code:None, + message:StyledString::Text(message).cell(), + source_ident, + severity:IssueSeverity::Warning.into(), + source:None, + title:Vc::cell("unexpected export *".into()), + } + .cell() + .emit(); +} + +#[turbo_tasks::value(shared)] +#[derive(Hash, Debug)] +pub struct EsmExports { + pub exports:BTreeMap, + pub star_exports:Vec>>, +} + +/// The expanded version of [EsmExports], the `exports` field here includes all +/// exports that could be expanded from `star_exports`. +/// +/// `star_exports` that could not be (fully) expanded end up in +/// `dynamic_exports`. +#[turbo_tasks::value(shared)] +#[derive(Hash, Debug)] +pub struct ExpandedExports { + pub exports:BTreeMap, + /// Modules we couldn't analyse all exports of. + pub dynamic_exports:Vec>>, +} + +#[turbo_tasks::value_impl] +impl EsmExports { + #[turbo_tasks::function] + pub async fn expand_exports(&self) -> Result> { + let mut exports:BTreeMap = self.exports.clone(); + let mut dynamic_exports = vec![]; + + for esm_ref in self.star_exports.iter() { + // TODO(PACK-2176): we probably need to handle re-exporting from external + // modules. + let ReferencedAsset::Some(asset) = + &*ReferencedAsset::from_resolve_result(esm_ref.resolve_reference()).await? + else { + continue; + }; + + let export_info = expand_star_exports(*asset).await?; + + for export in &export_info.star_exports { + if !exports.contains_key(export) { + exports.insert( + export.clone(), + EsmExport::ImportedBinding(Vc::upcast(*esm_ref), export.clone(), false), + ); + } + } + + if export_info.has_dynamic_exports { + dynamic_exports.push(*asset); + } + } + + Ok(ExpandedExports { exports, dynamic_exports }.cell()) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for EsmExports { + #[turbo_tasks::function] + async fn code_generation( + self: Vc, + _context:Vc>, + ) -> Result> { + let mut visitors = Vec::new(); + + let expanded = self.expand_exports().await?; + + let mut dynamic_exports = Vec::>::new(); + for dynamic_export_asset in &expanded.dynamic_exports { + let ident = ReferencedAsset::get_ident_from_placeable(dynamic_export_asset).await?; + + dynamic_exports.push(quote_expr!( + "__turbopack_dynamic__($arg)", + arg: Expr = Ident::new(ident.into(), DUMMY_SP).into() + )); + } + + let mut props = Vec::new(); + for (exported, local) in &expanded.exports { + let expr = match local { + EsmExport::Error => { + Some(quote!( + "(() => { throw new Error(\"Failed binding. See build errors!\"); })" + as Expr, + )) + }, + EsmExport::LocalBinding(name, mutable) => { + if *mutable { + Some(quote!( + "([() => $local, (v) => $local = v])" as Expr, + local = Ident::new((name as &str).into(), DUMMY_SP) + )) + } else { + Some(quote!( + "(() => $local)" as Expr, + local = Ident::new((name as &str).into(), DUMMY_SP) + )) + } + }, + EsmExport::ImportedBinding(esm_ref, name, mutable) => { + let referenced_asset = + ReferencedAsset::from_resolve_result(esm_ref.resolve_reference()).await?; + referenced_asset.get_ident().await?.map(|ident| { + let expr = Expr::Member(MemberExpr { + span:DUMMY_SP, + obj:Box::new(Expr::Ident(Ident::new(ident.into(), DUMMY_SP))), + prop:MemberProp::Computed(ComputedPropName { + span:DUMMY_SP, + expr:Box::new(Expr::Lit(Lit::Str(Str { + span:DUMMY_SP, + value:(name as &str).into(), + raw:None, + }))), + }), + }); + if *mutable { + quote!( + "([() => $expr, (v) => $expr = v])" as Expr, + expr: Expr = expr, + ) + } else { + quote!( + "(() => $expr)" as Expr, + expr: Expr = expr, + ) + } + }) + }, + EsmExport::ImportedNamespace(esm_ref) => { + let referenced_asset = + ReferencedAsset::from_resolve_result(esm_ref.resolve_reference()).await?; + referenced_asset.get_ident().await?.map(|ident| { + quote!( + "(() => $imported)" as Expr, + imported = Ident::new(ident.into(), DUMMY_SP) + ) + }) + }, + }; + if let Some(expr) = expr { + props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key:PropName::Str(Str { + span:DUMMY_SP, + value:exported.as_str().into(), + raw:None, + }), + value:Box::new(expr), + })))); + } + } + let getters = Expr::Object(ObjectLit { span:DUMMY_SP, props }); + let dynamic_stmt = if !dynamic_exports.is_empty() { + Some(Stmt::Expr(ExprStmt { span:DUMMY_SP, expr:Expr::from_exprs(dynamic_exports) })) + } else { + None + }; + + visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { + let stmt = quote!("__turbopack_esm__($getters);" as Stmt, + getters: Expr = getters.clone() + ); + match program { + Program::Module(ast::Module { body, .. }) => { + body.insert(0, ModuleItem::Stmt(stmt)); + } + Program::Script(Script { body, .. }) => { + body.insert(0, stmt); + } + } + if let Some(dynamic_stmt) = dynamic_stmt.clone() { + insert_hoisted_stmt(program, dynamic_stmt); + } + })); + + Ok(CodeGeneration { visitors }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/meta.rs b/crates/turbopack-ecmascript/Source/references/esm/meta.rs new file mode 100644 index 0000000000000..76f7f358ca8ef --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/meta.rs @@ -0,0 +1,174 @@ +use std::borrow::Cow; + +use anyhow::Result; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{Expr, Ident}, + quote, +}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::chunk::ChunkingContext; + +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + magic_identifier, + references::{AstPath, as_abs_path, esm::base::insert_hoisted_stmt}, +}; + +/// Responsible for initializing the `import.meta` object binding, so that it +/// may be referenced in th the file. +/// +/// There can be many references to import.meta, and they appear at any nesting +/// in the file. But we must only initialize the binding a single time. +#[turbo_tasks::value(shared)] +#[derive(Hash, Debug)] +pub struct ImportMetaBinding { + path:Vc, +} + +#[turbo_tasks::value_impl] +impl ImportMetaBinding { + #[turbo_tasks::function] + pub fn new(path:Vc) -> Vc { ImportMetaBinding { path }.cell() } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for ImportMetaBinding { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let path = as_abs_path(self.path).await?.as_str().map_or_else( + || { + quote!( + "(() => { throw new Error('could not convert import.meta.url to filepath') })()" + as Expr + ) + }, + |path| { + let formatted = encode_path(path).trim_start_matches("/ROOT/").to_string(); + quote!( + "`file://${__turbopack_resolve_absolute_path__($formatted)}`" as Expr, + formatted: Expr = formatted.into() + ) + }, + ); + + let visitor = create_visitor!(visit_mut_program(program: &mut Program) { + // [NOTE] url property is lazy-evaluated, as it should be computed once turbopack_runtime injects a function + // to calculate an absolute path. + let meta = quote!( + "const $name = { get url() { return $path } };" as Stmt, + name = meta_ident(), + path: Expr = path.clone(), + ); + insert_hoisted_stmt(program, meta); + }); + + Ok(CodeGeneration { visitors:vec![visitor] }.into()) + } +} + +/// Handles rewriting `import.meta` references into the injected binding created +/// by ImportMetaBindi ImportMetaBinding. +/// +/// There can be many references to import.meta, and they appear at any nesting +/// in the file. But all references refer to the same mutable object. +#[turbo_tasks::value(shared)] +#[derive(Hash, Debug)] +pub struct ImportMetaRef { + ast_path:Vc, +} + +#[turbo_tasks::value_impl] +impl ImportMetaRef { + #[turbo_tasks::function] + pub fn new(ast_path:Vc) -> Vc { ImportMetaRef { ast_path }.cell() } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for ImportMetaRef { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let ast_path = &self.ast_path.await?; + let visitor = create_visitor!(ast_path, visit_mut_expr(expr: &mut Expr) { + *expr = Expr::Ident(meta_ident()); + }); + + Ok(CodeGeneration { visitors:vec![visitor] }.into()) + } +} + +/// URL encodes special chars that would appear in the "pathname" portion. +/// https://github.com/nodejs/node/blob/3bed5f11e039153eff5cbfd9513b8f55fd53fc43/lib/internal/url.js#L1513-L1526 +fn encode_path(path:&'_ str) -> Cow<'_, str> { + let mut encoded = String::new(); + let mut start = 0; + for (i, c) in path.chars().enumerate() { + let mapping = match c { + '%' => "%25", + '\\' => "%5C", + '\n' => "%0A", + '\r' => "%0D", + '\t' => "%09", + _ => continue, + }; + + if encoded.is_empty() { + encoded.reserve(path.len()); + } + + encoded += &path[start..i]; + encoded += mapping; + start = i + 1; + } + + if encoded.is_empty() { + return Cow::Borrowed(path); + } + encoded += &path[start..]; + Cow::Owned(encoded) +} + +fn meta_ident() -> Ident { Ident::new(magic_identifier::mangle("import.meta").into(), DUMMY_SP) } + +#[cfg(test)] +mod test { + use super::encode_path; + + #[test] + fn test_encode_path_regular() { + let input = "abc"; + assert_eq!(encode_path(input), "abc"); + } + + #[test] + fn test_encode_path_special_chars() { + let input = "abc%def\\ghi\njkl\rmno\tpqr"; + assert_eq!(encode_path(input), "abc%25def%5Cghi%0Ajkl%0Dmno%09pqr"); + } + + #[test] + fn test_encode_path_special_char_start() { + let input = "%abc"; + assert_eq!(encode_path(input), "%25abc"); + } + + #[test] + fn test_encode_path_special_char_end() { + let input = "abc%"; + assert_eq!(encode_path(input), "abc%25"); + } + + #[test] + fn test_encode_path_special_char_contiguous() { + let input = "%%%"; + assert_eq!(encode_path(input), "%25%25%25"); + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/mod.rs b/crates/turbopack-ecmascript/Source/references/esm/mod.rs new file mode 100644 index 0000000000000..99ddb245db43d --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/mod.rs @@ -0,0 +1,18 @@ +pub(crate) mod base; +pub(crate) mod binding; +pub(crate) mod dynamic; +pub(crate) mod export; +pub(crate) mod meta; +pub(crate) mod module_id; +pub(crate) mod module_item; +pub(crate) mod url; + +pub use self::{ + base::EsmAssetReference, + binding::EsmBinding, + dynamic::EsmAsyncAssetReference, + export::{EsmExport, EsmExports}, + meta::{ImportMetaBinding, ImportMetaRef}, + module_item::EsmModuleItem, + url::{UrlAssetReference, UrlRewriteBehavior}, +}; diff --git a/crates/turbopack-ecmascript/Source/references/esm/module_id.rs b/crates/turbopack-ecmascript/Source/references/esm/module_id.rs new file mode 100644 index 0000000000000..2042c81f34116 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/module_id.rs @@ -0,0 +1,88 @@ +use anyhow::Result; +use swc_core::{ecma::ast::Expr, quote}; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ + ChunkItemExt, + ChunkableModule, + ChunkableModuleReference, + ChunkingContext, + ChunkingTypeOption, + ModuleId, + }, + reference::ModuleReference, + resolve::ModuleResolveResult, +}; + +use super::{EsmAssetReference, base::ReferencedAsset}; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::AstPath, +}; + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct EsmModuleIdAssetReference { + inner:Vc, + ast_path:Vc, +} + +#[turbo_tasks::value_impl] +impl EsmModuleIdAssetReference { + #[turbo_tasks::function] + pub fn new(inner:Vc, ast_path:Vc) -> Vc { + Self::cell(EsmModuleIdAssetReference { inner, ast_path }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for EsmModuleIdAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { self.inner.resolve_reference() } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EsmModuleIdAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("module id of {}", self.inner.to_string().await?,).into())) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for EsmModuleIdAssetReference { + #[turbo_tasks::function] + fn chunking_type(&self) -> Vc { self.inner.chunking_type() } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for EsmModuleIdAssetReference { + #[turbo_tasks::function] + async fn code_generation( + &self, + chunking_context:Vc>, + ) -> Result> { + let mut visitors = Vec::new(); + + if let ReferencedAsset::Some(asset) = &*self.inner.get_referenced_asset().await? { + let id = asset.as_chunk_item(Vc::upcast(chunking_context)).id().await?; + let id = Expr::Lit(match &*id { + ModuleId::String(s) => s.as_str().into(), + ModuleId::Number(n) => (*n as f64).into(), + }); + visitors.push(create_visitor!(self.ast_path.await?, visit_mut_expr(expr: &mut Expr) { + *expr = id.clone() + })); + } else { + // If the referenced asset can't be found, replace the expression with null. + // This can happen if the referenced asset is an external, or doesn't resolve + // to anything. + visitors.push(create_visitor!(self.ast_path.await?, visit_mut_expr(expr: &mut Expr) { + *expr = quote!("null" as Expr); + })); + } + + Ok(CodeGeneration { visitors }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/module_item.rs b/crates/turbopack-ecmascript/Source/references/esm/module_item.rs new file mode 100644 index 0000000000000..19e50a81ab051 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/module_item.rs @@ -0,0 +1,116 @@ +use std::mem::replace; + +use anyhow::Result; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{ + ClassDecl, + Decl, + DefaultDecl, + ExportDecl, + ExportDefaultDecl, + ExportDefaultExpr, + FnDecl, + Ident, + ModuleDecl, + ModuleItem, + Stmt, + }, + quote, +}; +use turbo_tasks::Vc; +use turbopack_core::chunk::ChunkingContext; + +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + magic_identifier, + references::AstPath, +}; + +/// Makes code changes to remove export/import declarations and places the +/// expr/decl in a normal statement. Unnamed expr/decl will be named with the +/// magic identifier "export default" +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct EsmModuleItem { + pub path:Vc, +} + +#[turbo_tasks::value_impl] +impl EsmModuleItem { + #[turbo_tasks::function] + pub fn new(path:Vc) -> Vc { Self::cell(EsmModuleItem { path }) } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for EsmModuleItem { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let mut visitors = Vec::new(); + + let path = &self.path.await?; + visitors.push( + create_visitor!(path, visit_mut_module_item(module_item: &mut ModuleItem) { + let item = replace(module_item, ModuleItem::Stmt(quote!(";" as Stmt))); + if let ModuleItem::ModuleDecl(module_decl) = item { + match module_decl { + ModuleDecl::ExportDefaultExpr(ExportDefaultExpr { box expr, .. }) => { + let stmt = quote!("const $name = $expr;" as Stmt, + name = Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP), + expr: Expr = expr + ); + *module_item = ModuleItem::Stmt(stmt); + } + ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span }) => { + match decl { + DefaultDecl::Class(class) => { + *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl { + ident: class.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP)), + declare: false, + class: class.class + }))) + } + DefaultDecl::Fn(fn_expr) => { + *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl { + ident: fn_expr.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP)), + declare: false, + function: fn_expr.function + }))) + } + DefaultDecl::TsInterfaceDecl(_) => { + // not matching, might happen due to eventual consistency + *module_item = ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span })); + } + } + } + ModuleDecl::ExportDecl(ExportDecl { decl, .. }) => { + *module_item = ModuleItem::Stmt(Stmt::Decl(decl)); + } + ModuleDecl::ExportNamed(_) => { + // already removed + } + ModuleDecl::ExportAll(_) => { + // already removed + } + ModuleDecl::Import(_) => { + // already removed + } + _ => { + // not matching, might happen due to eventual consistency + *module_item = ModuleItem::ModuleDecl(module_decl); + } + } + } else { + // not matching, might happen due to eventual consistency + *module_item = item; + } + }), + ); + + Ok(CodeGeneration { visitors }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/esm/url.rs b/crates/turbopack-ecmascript/Source/references/esm/url.rs new file mode 100644 index 0000000000000..646b0f6127e2c --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/esm/url.rs @@ -0,0 +1,312 @@ +use anyhow::{Result, bail}; +use swc_core::{ + ecma::ast::{Expr, ExprOrSpread, NewExpr}, + quote, +}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ + ChunkItemExt, + ChunkableModule, + ChunkableModuleReference, + ChunkingContext, + ChunkingType, + ChunkingTypeOption, + }, + environment::Rendering, + issue::IssueSource, + reference::ModuleReference, + reference_type::{ReferenceType, UrlReferenceSubType}, + resolve::{ + ExternalType, + ModuleResolveResult, + origin::ResolveOrigin, + parse::Request, + url_resolve, + }, +}; +use turbopack_resolve::ecmascript::try_to_severity; + +use super::base::ReferencedAsset; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::AstPath, + utils::module_id_to_lit, +}; + +/// Determines how to treat `new URL(...)` rewrites. +/// This allows to construct url depends on the different building context, +/// e.g. SSR, CSR, or Node.js. +#[turbo_tasks::value(shared)] +#[derive(Debug, Copy, Clone, PartialOrd, Ord, Hash)] +pub enum UrlRewriteBehavior { + /// Omits base, resulting in a relative URL. + Relative, + /// Uses the full URL, including the base. + Full, + /// Do not attempt to rewrite the URL. + None, +} + +/// URL Asset References are injected during code analysis when we find a +/// (staticly analyzable) `new URL("path", import.meta.url)`. +/// +/// It's responsible rewriting the `URL` constructor's arguments to allow the +/// referenced file to be imported/fetched/etc. +#[turbo_tasks::value] +pub struct UrlAssetReference { + origin:Vc>, + request:Vc, + rendering:Vc, + ast_path:Vc, + issue_source:Vc, + in_try:bool, + url_rewrite_behavior:Vc, +} + +#[turbo_tasks::value_impl] +impl UrlAssetReference { + #[turbo_tasks::function] + pub fn new( + origin:Vc>, + request:Vc, + rendering:Vc, + ast_path:Vc, + issue_source:Vc, + in_try:bool, + url_rewrite_behavior:Vc, + ) -> Vc { + UrlAssetReference { + origin, + request, + rendering, + ast_path, + issue_source, + in_try, + url_rewrite_behavior, + } + .cell() + } + + #[turbo_tasks::function] + pub(crate) fn get_referenced_asset(self: Vc) -> Vc { + ReferencedAsset::from_resolve_result(self.resolve_reference()) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for UrlAssetReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Vc { + url_resolve( + self.origin, + self.request, + Value::new(ReferenceType::Url(UrlReferenceSubType::EcmaScriptNewUrl)), + Some(self.issue_source), + try_to_severity(self.in_try), + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for UrlAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("new URL({})", self.request.to_string().await?,).into())) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for UrlAssetReference { + #[turbo_tasks::function] + fn chunking_type(&self) -> Vc { Vc::cell(Some(ChunkingType::Parallel)) } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for UrlAssetReference { + /// Rewrites call to the `new URL()` ctor depends on the current + /// conditions. Generated code will point to the output path of the asset, + /// as similar to the webpack's behavior. This is based on the + /// configuration (UrlRewriteBehavior), and the current context + /// (rendering), lastly the asset's condition (if it's referenced / + /// external). The following table shows the behavior: + // original call: `new URL(url, base);` + // ┌───────────────────────────────┬─────────────────────────────────────────────────────────────────────────┬────────────────────────────────────────────────┬───────────────────────┠+ // │ UrlRewriteBehavior\RefAsset │ ReferencedAsset::Some() + // │ ReferencedAsset::External │ ReferencedAsset::None │ + // ├───────────────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────┼───────────────────────┤ + // │ Relative │ __turbopack_relative_url__(__turbopack_require__(urlId)) + // │ __turbopack_relative_url__(url) │ new URL(url, base) │ + // │ Full(RenderingClient::Client) │ new URL(__turbopack_require__(urlId), location.origin) + // │ new URL(url, location.origin) │ new URL(url, base) │ + // │ Full(RenderingClient::..) │ new URL(__turbopack_resolve_module_id_path__(urlId)) + // │ new URL(url, base) │ new URL(url, base) │ │ None + // │ new URL(url, base) │ new URL(url, + // base) │ new URL(url, base) │ + // └───────────────────────────────┴─────────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────┴───────────────────────┘ + #[turbo_tasks::function] + async fn code_generation( + self: Vc, + chunking_context:Vc>, + ) -> Result> { + let this = self.await?; + let mut visitors = vec![]; + let rewrite_behavior = &*this.url_rewrite_behavior.await?; + + match rewrite_behavior { + UrlRewriteBehavior::Relative => { + let referenced_asset = self.get_referenced_asset().await?; + let ast_path = this.ast_path.await?; + + // if the referenced url is in the module graph of turbopack, replace it into + // the chunk item will be emitted into output path to point the + // static asset path. for the `new URL()` call, replace it into + // pseudo url object `__turbopack_relative_url__` + // which is injected by turbopack's runtime to resolve into the relative path + // omitting the base. + match &*referenced_asset { + ReferencedAsset::Some(asset) => { + // We rewrite the first `new URL()` arguments to be a require() of the chunk + // item, which exports the static asset path to the linked file. + let id = asset.as_chunk_item(Vc::upcast(chunking_context)).id().await?; + + visitors.push(create_visitor!(ast_path, visit_mut_expr(new_expr: &mut Expr) { + let should_rewrite_to_relative = if let Expr::New(NewExpr { args: Some(args), .. }) = new_expr { + matches!(args.first(), Some(ExprOrSpread { .. })) + } else { + false + }; + + if should_rewrite_to_relative { + *new_expr = quote!( + "new __turbopack_relative_url__(__turbopack_require__($id))" as Expr, + id: Expr = module_id_to_lit(&id), + ); + } + })); + }, + ReferencedAsset::External(request, ExternalType::Url) => { + let request = request.to_string(); + visitors.push(create_visitor!(ast_path, visit_mut_expr(new_expr: &mut Expr) { + let should_rewrite_to_relative = if let Expr::New(NewExpr { args: Some(args), .. }) = new_expr { + matches!(args.first(), Some(ExprOrSpread { .. })) + } else { + false + }; + + if should_rewrite_to_relative { + *new_expr = quote!( + "new __turbopack_relative_url__($id)" as Expr, + id: Expr = request.as_str().into(), + ); + } + })); + }, + ReferencedAsset::External(request, ty) => { + bail!( + "Unsupported external type {:?} for URL reference with request: {:?}", + ty, + request + ) + }, + ReferencedAsset::None => {}, + } + }, + UrlRewriteBehavior::Full => { + let referenced_asset = self.get_referenced_asset().await?; + let ast_path = this.ast_path.await?; + + // For rendering environments (CSR), we rewrite the `import.meta.url` to + // be a location.origin because it allows us to access files from the root of + // the dev server. + // + // By default for the remaining environments, turbopack's runtime have overriden + // `import.meta.url`. + let rewrite_url_base = match &*this.rendering.await? { + Rendering::Client => Some(quote!("location.origin" as Expr)), + Rendering::None | Rendering::Server => None, + }; + + match &*referenced_asset { + ReferencedAsset::Some(asset) => { + // We rewrite the first `new URL()` arguments to be a require() of the + // chunk item, which returns the asset path as its exports. + let id = asset.as_chunk_item(Vc::upcast(chunking_context)).id().await?; + + // If there's a rewrite to the base url, then the current rendering + // environment should able to resolve the asset path + // (asset_url) from the base. Wrap the module id + // with __turbopack_require__ which returns the asset_url. + // + // Otherwise, the envioronment should provide an absolute path to the actual + // output asset; delegate those calculation to the + // runtime fn __turbopack_resolve_module_id_path__. + let url_segment_resolver = if rewrite_url_base.is_some() { + quote!( + "__turbopack_require__($id)" as Expr, + id: Expr = module_id_to_lit(&id), + ) + } else { + quote!( + "__turbopack_resolve_module_id_path__($id)" as Expr, + id: Expr = module_id_to_lit(&id), + ) + }; + + visitors.push( + create_visitor!(ast_path, visit_mut_expr(new_expr: &mut Expr) { + if let Expr::New(NewExpr { args: Some(args), .. }) = new_expr { + if let Some(ExprOrSpread { box expr, spread: None }) = args.get_mut(0) { + *expr = url_segment_resolver.clone(); + } + + if let Some(ExprOrSpread { box expr, spread: None }) = args.get_mut(1) { + if let Some(rewrite) = &rewrite_url_base { + *expr = rewrite.clone(); + } else { + // If rewrite for the base doesn't exists, means __turbopack_resolve_module_id_path__ + // should resolve the full path correctly and there shouldn't be a base. + args.remove(1); + } + } + } + }), + ); + }, + ReferencedAsset::External(request, ExternalType::Url) => { + let request = request.to_string(); + visitors.push( + create_visitor!(ast_path, visit_mut_expr(new_expr: &mut Expr) { + if let Expr::New(NewExpr { args: Some(args), .. }) = new_expr { + if let Some(ExprOrSpread { box expr, spread: None }) = args.get_mut(0) { + *expr = request.as_str().into() + } + + if let Some(rewrite) = &rewrite_url_base { + if let Some(ExprOrSpread { box expr, spread: None }) = args.get_mut(1) { + *expr = rewrite.clone(); + } + } + } + }), + ); + }, + ReferencedAsset::External(request, ty) => { + bail!( + "Unsupported external type {:?} for URL reference with request: {:?}", + ty, + request + ) + }, + ReferencedAsset::None => {}, + } + }, + UrlRewriteBehavior::None => { + // Asked to not rewrite the URL, so we don't do anything. + }, + }; + + Ok(CodeGeneration { visitors }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/external_module.rs b/crates/turbopack-ecmascript/Source/references/external_module.rs new file mode 100644 index 0000000000000..094727be38d85 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/external_module.rs @@ -0,0 +1,218 @@ +use std::{fmt::Display, io::Write}; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{RcStr, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks_fs::{FileContent, FileSystem, VirtualFileSystem, glob::Glob, rope::RopeBuilder}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{AsyncModuleInfo, ChunkItem, ChunkType, ChunkableModule, ChunkingContext}, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, +}; + +use crate::{ + EcmascriptModuleContent, + EcmascriptOptions, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + references::async_module::{AsyncModule, OptionAsyncModule}, + utils::StringifyJs, +}; + +#[turbo_tasks::function] +fn layer() -> Vc { Vc::cell("external".into()) } + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TraceRawVcs, TaskInput)] +pub enum CachedExternalType { + CommonJs, + EcmaScriptViaRequire, + EcmaScriptViaImport, +} + +impl Display for CachedExternalType { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CachedExternalType::CommonJs => write!(f, "cjs"), + CachedExternalType::EcmaScriptViaRequire => write!(f, "esm_require"), + CachedExternalType::EcmaScriptViaImport => write!(f, "esm_import"), + } + } +} + +#[turbo_tasks::value] +pub struct CachedExternalModule { + pub request:RcStr, + pub external_type:CachedExternalType, +} + +#[turbo_tasks::value_impl] +impl CachedExternalModule { + #[turbo_tasks::function] + pub fn new(request:RcStr, external_type:CachedExternalType) -> Vc { + Self::cell(CachedExternalModule { request, external_type }) + } + + #[turbo_tasks::function] + pub fn content(&self) -> Result> { + let mut code = RopeBuilder::default(); + + if self.external_type == CachedExternalType::EcmaScriptViaImport { + writeln!( + code, + "const mod = await __turbopack_external_import__({});", + StringifyJs(&self.request) + )?; + } else { + writeln!( + code, + "const mod = __turbopack_external_require__({});", + StringifyJs(&self.request) + )?; + } + + writeln!(code)?; + + if self.external_type == CachedExternalType::CommonJs { + writeln!(code, "module.exports = mod;")?; + } else { + writeln!(code, "__turbopack_export_namespace__(mod);")?; + } + + Ok(EcmascriptModuleContent { + inner_code:code.build(), + source_map:None, + is_esm:self.external_type != CachedExternalType::CommonJs, + } + .cell()) + } +} + +#[turbo_tasks::value_impl] +impl Module for CachedExternalModule { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + let fs = VirtualFileSystem::new_with_name("externals".into()); + + AssetIdent::from_path(fs.root()) + .with_layer(layer()) + .with_modifier(Vc::cell(self.request.clone())) + .with_modifier(Vc::cell(self.external_type.to_string().into())) + } +} + +#[turbo_tasks::value_impl] +impl Asset for CachedExternalModule { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + // should be `NotFound` as this function gets called to detect source changes + AssetContent::file(FileContent::NotFound.cell()) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for CachedExternalModule { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast( + CachedExternalModuleChunkItem { module:self, chunking_context }.cell(), + )) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for CachedExternalModule { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { + if self.external_type == CachedExternalType::CommonJs { + EcmascriptExports::CommonJs.cell() + } else { + EcmascriptExports::DynamicNamespace.cell() + } + } + + #[turbo_tasks::function] + fn get_async_module(&self) -> Vc { + Vc::cell(if self.external_type == CachedExternalType::EcmaScriptViaImport { + Some(AsyncModule { has_top_level_await:true, import_externals:true }.cell()) + } else { + None + }) + } + + #[turbo_tasks::function] + fn is_marked_as_side_effect_free( + self: Vc, + _side_effect_free_packages:Vc, + ) -> Vc { + Vc::cell(false) + } +} + +#[turbo_tasks::value] +pub struct CachedExternalModuleChunkItem { + module:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for CachedExternalModuleChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + fn ty(self: Vc) -> Vc> { + Vc::upcast(Vc::::default()) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn is_self_async(&self) -> Result> { + Ok(Vc::cell( + self.module.await?.external_type == CachedExternalType::EcmaScriptViaImport, + )) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for CachedExternalModuleChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + panic!("content() should not be called"); + } + + #[turbo_tasks::function] + async fn content_with_async_module_info( + &self, + async_module_info:Option>, + ) -> Result> { + let async_module_options = self.module.get_async_module().module_options(async_module_info); + + Ok(EcmascriptChunkItemContent::new( + self.module.content(), + self.chunking_context, + EcmascriptOptions::default().cell(), + async_module_options, + )) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/mod.rs b/crates/turbopack-ecmascript/Source/references/mod.rs new file mode 100644 index 0000000000000..bfc768db58744 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/mod.rs @@ -0,0 +1,2857 @@ +pub mod amd; +pub mod async_module; +pub mod cjs; +pub mod constant_condition; +pub mod constant_value; +pub mod dynamic_expression; +pub mod esm; +pub mod external_module; +pub mod node; +pub mod pattern_mapping; +pub mod raw; +pub mod require_context; +pub mod type_issue; +pub mod typescript; +pub mod unreachable; +pub mod util; + +use std::{ + borrow::Cow, + collections::{BTreeMap, HashMap}, + future::Future, + mem::take, + pin::Pin, + sync::Arc, +}; + +use anyhow::Result; +use constant_condition::{ConstantCondition, ConstantConditionValue}; +use constant_value::ConstantValue; +use indexmap::IndexSet; +use lazy_static::lazy_static; +use num_traits::Zero; +use once_cell::sync::Lazy; +use parking_lot::Mutex; +use regex::Regex; +use sourcemap::decode_data_url; +use swc_core::{ + atoms::JsWord, + common::{ + GLOBALS, + Globals, + Span, + Spanned, + comments::{CommentKind, Comments}, + errors::{DiagnosticId, HANDLER, Handler}, + pass::AstNodePath, + source_map::Pos, + }, + ecma::{ + ast::*, + visit::{ + AstParentKind, + AstParentNodeRef, + VisitAstPath, + VisitWithPath, + fields::{AssignExprField, AssignTargetField, SimpleAssignTargetField}, + }, + }, +}; +use tracing::Instrument; +use turbo_tasks::{RcStr, TryJoinIterExt, Upcast, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + compile_time_info::{CompileTimeInfo, FreeVarReference}, + error::PrettyPrintError, + issue::{IssueExt, IssueSeverity, IssueSource, StyledString, analyze::AnalyzeIssue}, + module::Module, + reference::{ModuleReference, ModuleReferences, SourceMapReference}, + reference_type::{CommonJsReferenceSubType, ReferenceType}, + resolve::{ + FindContextFileResult, + ModulePart, + find_context_file, + origin::{PlainResolveOrigin, ResolveOrigin, ResolveOriginExt}, + parse::Request, + pattern::Pattern, + resolve, + }, + source::Source, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMap}, +}; +use turbopack_resolve::{ + ecmascript::{apply_cjs_specific_options, cjs_resolve, try_to_severity}, + typescript::tsconfig, +}; +use turbopack_swc_utils::emitter::IssueEmitter; +use unreachable::Unreachable; + +use self::{ + amd::{ + AmdDefineAssetReference, + AmdDefineDependencyElement, + AmdDefineFactoryType, + AmdDefineWithDependenciesCodeGen, + }, + cjs::CjsAssetReference, + esm::{ + EsmAssetReference, + EsmAsyncAssetReference, + EsmExports, + EsmModuleItem, + ImportMetaBinding, + ImportMetaRef, + UrlAssetReference, + export::EsmExport, + }, + node::DirAssetReference, + raw::FileSourceReference, + typescript::{TsConfigReference, TsReferencePathAssetReference, TsReferenceTypeAssetReference}, +}; +use super::{ + EcmascriptModuleAssetType, + ModuleTypeResult, + analyzer::{ + ConstantValue as JsConstantValue, + JsValue, + ObjectPart, + WellKnownFunctionKind, + WellKnownObjectKind, + builtin::replace_builtin, + graph::{Effect, create_graph}, + linker::link, + well_known::replace_well_known, + }, + errors, + parse::{ParseResult, parse}, + special_cases::special_cases, + utils::js_value_to_pattern, + webpack::{ + WebpackChunkAssetReference, + WebpackEntryAssetReference, + WebpackRuntimeAssetReference, + parse::{WebpackRuntime, webpack_runtime}, + }, +}; +pub use crate::references::esm::export::{FollowExportsResult, follow_reexports}; +use crate::{ + EcmascriptInputTransforms, + EcmascriptModuleAsset, + SpecifiedModuleType, + TreeShakingMode, + analyzer::{ + ConstantNumber, + ConstantString, + ModuleValue, + RequireContextValue, + builtin::early_replace_builtin, + graph::{ConditionalKind, EffectArg, EvalContext, VarGraph}, + imports::{ImportAnnotations, ImportedSymbol, Reexport}, + parse_require_context, + top_level_await::has_top_level_await, + }, + chunk::EcmascriptExports, + code_gen::{CodeGen, CodeGenerateable, CodeGenerateableWithAsyncModuleInfo, CodeGenerateables}, + magic_identifier, + references::{ + async_module::{AsyncModule, OptionAsyncModule}, + cjs::{CjsRequireAssetReference, CjsRequireCacheAccess, CjsRequireResolveAssetReference}, + dynamic_expression::DynamicExpression, + esm::{EsmBinding, UrlRewriteBehavior, module_id::EsmModuleIdAssetReference}, + node::PackageJsonReference, + require_context::{RequireContextAssetReference, RequireContextMap}, + type_issue::SpecifiedModuleTypeIssue, + }, + tree_shake::{find_turbopack_part_id_in_asserts, part_of_module, split}, +}; + +#[derive(Clone)] +#[turbo_tasks::value(shared)] +pub struct AnalyzeEcmascriptModuleResult { + pub references:Vc, + pub local_references:Vc, + pub reexport_references:Vc, + pub evaluation_references:Vc, + pub code_generation:Vc, + pub exports:Vc, + pub async_module:Vc, + /// `true` when the analysis was successful. + pub successful:bool, + pub source_map:Vc, +} + +/// A temporary analysis result builder to pass around, to be turned into an +/// `Vc` eventually. +pub struct AnalyzeEcmascriptModuleResultBuilder { + references:IndexSet>>, + local_references:IndexSet>>, + reexport_references:IndexSet>>, + evaluation_references:IndexSet>>, + code_gens:Vec, + exports:EcmascriptExports, + async_module:Vc, + successful:bool, + source_map:Option>, +} + +impl AnalyzeEcmascriptModuleResultBuilder { + pub fn new() -> Self { + Self { + references:IndexSet::new(), + local_references:IndexSet::new(), + reexport_references:IndexSet::new(), + evaluation_references:IndexSet::new(), + code_gens:Vec::new(), + exports:EcmascriptExports::None, + async_module:Vc::cell(None), + successful:false, + source_map:None, + } + } + + /// Adds an asset reference to the analysis result. + pub fn add_reference(&mut self, reference:Vc) + where + R: Upcast>, { + let r = Vc::upcast(reference); + self.references.insert(r); + self.local_references.insert(Vc::upcast(reference)); + } + + /// Adds an asset reference to the analysis result. + pub fn add_import_reference(&mut self, reference:Vc) { + self.references.insert(Vc::upcast(reference)); + } + + /// Adds an reexport reference to the analysis result. + pub fn add_local_reference(&mut self, reference:Vc) + where + R: Upcast>, { + self.local_references.insert(Vc::upcast(reference)); + } + + /// Adds an reexport reference to the analysis result. + pub fn add_reexport_reference(&mut self, reference:Vc) + where + R: Upcast>, { + self.reexport_references.insert(Vc::upcast(reference)); + } + + /// Adds an evaluation reference to the analysis result. + pub fn add_evaluation_reference(&mut self, reference:Vc) { + self.evaluation_references.insert(Vc::upcast(reference)); + } + + /// Adds a codegen to the analysis result. + pub fn add_code_gen(&mut self, code_gen:Vc) + where + C: Upcast>, { + self.code_gens.push(CodeGen::CodeGenerateable(Vc::upcast(code_gen))); + } + + /// Adds a codegen to the analysis result. + #[allow(dead_code)] + pub fn add_code_gen_with_availability_info(&mut self, code_gen:Vc) + where + C: Upcast>, { + self.code_gens + .push(CodeGen::CodeGenerateableWithAsyncModuleInfo(Vc::upcast(code_gen))); + } + + /// Sets the analysis result ES export. + pub fn set_source_map(&mut self, source_map:Vc) { + self.source_map = Some(source_map); + } + + /// Sets the analysis result ES export. + pub fn set_exports(&mut self, exports:EcmascriptExports) { self.exports = exports; } + + /// Sets the analysis result ES export. + pub fn set_async_module(&mut self, async_module:Vc) { + self.async_module = Vc::cell(Some(async_module)); + } + + /// Sets whether the analysis was successful. + pub fn set_successful(&mut self, successful:bool) { self.successful = successful; } + + /// Builds the final analysis result. Resolves internal Vcs for performance + /// in using them. + pub async fn build( + mut self, + track_reexport_references:bool, + ) -> Result> { + let mut references:Vec<_> = self.references.into_iter().collect(); + for r in references.iter_mut() { + *r = r.resolve().await?; + } + let mut local_references:Vec<_> = track_reexport_references + .then(|| self.local_references.into_iter()) + .into_iter() + .flatten() + .collect(); + for r in local_references.iter_mut() { + *r = r.resolve().await?; + } + let mut reexport_references:Vec<_> = track_reexport_references + .then(|| self.reexport_references.into_iter()) + .into_iter() + .flatten() + .collect(); + for r in reexport_references.iter_mut() { + *r = r.resolve().await?; + } + let mut evaluation_references:Vec<_> = track_reexport_references + .then(|| self.evaluation_references.into_iter()) + .into_iter() + .flatten() + .collect(); + for r in evaluation_references.iter_mut() { + *r = r.resolve().await?; + } + for c in self.code_gens.iter_mut() { + match c { + CodeGen::CodeGenerateable(c) => { + *c = c.resolve().await?; + }, + CodeGen::CodeGenerateableWithAsyncModuleInfo(c) => { + *c = c.resolve().await?; + }, + } + } + let source_map = if let Some(source_map) = self.source_map { + source_map + } else { + OptionSourceMap::none() + }; + Ok(AnalyzeEcmascriptModuleResult::cell(AnalyzeEcmascriptModuleResult { + references:Vc::cell(references), + local_references:Vc::cell(local_references), + reexport_references:Vc::cell(reexport_references), + evaluation_references:Vc::cell(evaluation_references), + code_generation:Vc::cell(self.code_gens), + exports:self.exports.into(), + async_module:self.async_module, + successful:self.successful, + source_map, + })) + } +} + +impl Default for AnalyzeEcmascriptModuleResultBuilder { + fn default() -> Self { Self::new() } +} + +struct AnalysisState<'a> { + handler:&'a Handler, + source:Vc>, + origin:Vc>, + compile_time_info:Vc, + var_graph:&'a VarGraph, + /// This is the current state of known values of function + /// arguments. + fun_args_values:Mutex>>, + // There can be many references to import.meta, but only the first should hoist + // the object allocation. + first_import_meta:bool, + tree_shaking_mode:Option, + import_externals:bool, + ignore_dynamic_requests:bool, +} + +impl<'a> AnalysisState<'a> { + async fn link_value(&self, value:JsValue, in_try:bool) -> Result { + let fun_args_values = self.fun_args_values.lock().clone(); + link( + self.var_graph, + value, + &early_value_visitor, + &|value| value_visitor(self.origin, value, self.compile_time_info, in_try), + fun_args_values, + ) + .await + } +} + +fn set_handler_and_globals(handler:&Handler, globals:&Arc, f:F) -> R +where + F: FnOnce() -> R, { + HANDLER.set(handler, || GLOBALS.set(globals, f)) +} + +#[turbo_tasks::function] +pub(crate) async fn analyse_ecmascript_module( + module:Vc, + part:Option>, +) -> Result> { + let span = { + let module = module.ident().to_string().await?.to_string(); + tracing::info_span!("analyse ecmascript module", module = module) + }; + let result = analyse_ecmascript_module_internal(module, part).instrument(span).await; + + match result { + Ok(result) => Ok(result), + Err(err) => { + Err(err.context(format!( + "failed to analyse ecmascript module '{}'", + module.ident().to_string().await? + ))) + }, + } +} + +pub(crate) async fn analyse_ecmascript_module_internal( + module:Vc, + part:Option>, +) -> Result> { + let raw_module = module.await?; + + let source = raw_module.source; + let ty = Value::new(raw_module.ty); + let transforms = raw_module.transforms; + let options = raw_module.options; + let compile_time_info = raw_module.compile_time_info; + let options = options.await?; + let import_externals = options.import_externals; + + let origin = Vc::upcast::>(module); + + let mut analysis = AnalyzeEcmascriptModuleResultBuilder::new(); + let path = origin.origin_path(); + + // Is this a typescript file that requires analzying type references? + let analyze_types = match &*ty { + EcmascriptModuleAssetType::Typescript { analyze_types, .. } => *analyze_types, + EcmascriptModuleAssetType::TypescriptDeclaration => true, + EcmascriptModuleAssetType::Ecmascript => false, + }; + + let parsed = if let Some(part) = part { + let parsed = parse(source, ty, transforms); + let split_data = split(source.ident(), source, parsed); + part_of_module(split_data, part) + } else { + parse(source, ty, transforms) + }; + + let ModuleTypeResult { module_type: specified_type, referenced_package_json } = + *module.determine_module_type().await?; + + if let Some(package_json) = referenced_package_json { + analysis.add_reference(PackageJsonReference::new(package_json)); + } + + if analyze_types { + match &*find_context_file(path.parent(), tsconfig()).await? { + FindContextFileResult::Found(tsconfig, _) => { + analysis.add_reference(TsConfigReference::new(origin, *tsconfig)); + }, + FindContextFileResult::NotFound(_) => {}, + }; + } + + special_cases(&path.await?.path, &mut analysis); + + let parsed = parsed.await?; + + let ParseResult::Ok { program, globals, eval_context, comments, source_map, .. } = &*parsed + else { + return analysis.build(false).await; + }; + + let mut import_references = Vec::new(); + + let pos = program.span().lo; + if analyze_types { + if let Some(comments) = comments.get_leading(pos) { + for comment in comments.iter() { + if let CommentKind::Line = comment.kind { + lazy_static! { + static ref REFERENCE_PATH: Regex = + Regex::new(r#"^/\s*\s*$"#) + .unwrap(); + static ref REFERENCE_TYPES: Regex = + Regex::new(r#"^/\s*\s*$"#) + .unwrap(); + } + let text = &comment.text; + if let Some(m) = REFERENCE_PATH.captures(text) { + let path = &m[1]; + analysis + .add_reference(TsReferencePathAssetReference::new(origin, path.into())); + } else if let Some(m) = REFERENCE_TYPES.captures(text) { + let types = &m[1]; + analysis.add_reference(TsReferenceTypeAssetReference::new( + origin, + types.into(), + )); + } + } + } + } + } + + // Only use the last sourceMappingURL comment by spec + let mut paths_by_pos = Vec::new(); + for (pos, comments) in comments.trailing.iter() { + for comment in comments.iter().rev() { + lazy_static! { + static ref SOURCE_MAP_FILE_REFERENCE: Regex = + Regex::new(r"# sourceMappingURL=(.*)$").unwrap(); + } + if let Some(m) = SOURCE_MAP_FILE_REFERENCE.captures(&comment.text) { + let path = m.get(1).unwrap().as_str(); + paths_by_pos.push((pos, path)); + break; + } + } + } + let mut source_map_from_comment = false; + if let Some((_, path)) = paths_by_pos.into_iter().max_by_key(|&(pos, _)| pos) { + let origin_path = origin.origin_path(); + if path.ends_with(".map") { + let source_map_origin = origin_path.parent().join(path.into()); + let reference = SourceMapReference::new(origin_path, source_map_origin); + analysis.add_reference(reference); + let source_map = reference.generate_source_map(); + analysis.set_source_map(convert_to_turbopack_source_map(source_map, source_map_origin)); + source_map_from_comment = true; + } else if path.starts_with("data:application/json;base64,") { + let source_map_origin = origin_path; + let source_map = maybe_decode_data_url(path.into()); + analysis.set_source_map(convert_to_turbopack_source_map(source_map, source_map_origin)); + source_map_from_comment = true; + } + } + if !source_map_from_comment { + if let Some(generate_source_map) = + Vc::try_resolve_sidecast::>(source).await? + { + let source_map_origin = source.ident().path(); + analysis.set_source_map(convert_to_turbopack_source_map( + generate_source_map.generate_source_map(), + source_map_origin, + )); + } + } + + let handler = Handler::with_emitter( + true, + false, + Box::new(IssueEmitter::new(source, source_map.clone(), None)), + ); + + let mut var_graph = + set_handler_and_globals(&handler, globals, || create_graph(program, eval_context)); + + let mut evaluation_references = Vec::new(); + + for (i, r) in eval_context.imports.references().enumerate() { + let r = EsmAssetReference::new( + origin, + Request::parse(Value::new(RcStr::from(&*r.module_path).into())), + r.issue_source, + Value::new(r.annotations.clone()), + match options.tree_shaking_mode { + Some(TreeShakingMode::ModuleFragments) => { + match &r.imported_symbol { + ImportedSymbol::ModuleEvaluation => { + evaluation_references.push(i); + Some(ModulePart::evaluation()) + }, + ImportedSymbol::Symbol(name) => Some(ModulePart::export((&**name).into())), + ImportedSymbol::Part(part_id) => Some(ModulePart::internal(*part_id)), + ImportedSymbol::Exports => Some(ModulePart::exports()), + ImportedSymbol::Namespace => None, + } + }, + Some(TreeShakingMode::ReexportsOnly) => { + match &r.imported_symbol { + ImportedSymbol::ModuleEvaluation => { + evaluation_references.push(i); + Some(ModulePart::evaluation()) + }, + ImportedSymbol::Symbol(name) => Some(ModulePart::export((&**name).into())), + ImportedSymbol::Part(part_id) => Some(ModulePart::internal(*part_id)), + ImportedSymbol::Exports => None, + ImportedSymbol::Namespace => None, + } + }, + None => None, + }, + import_externals, + ); + + import_references.push(r); + } + + for r in import_references.iter_mut() { + // Resolving these references here avoids many resolve wrapper tasks when + // passing that to other turbo tasks functions later. + *r = r.resolve().await?; + } + + for r in import_references.iter() { + // `add_import_reference` will avoid adding duplicate references + analysis.add_import_reference(*r); + } + for i in evaluation_references { + analysis.add_evaluation_reference(import_references[i]); + } + + let (webpack_runtime, webpack_entry, webpack_chunks, esm_exports, esm_star_exports) = + set_handler_and_globals(&handler, globals, || { + // TODO migrate to effects + let mut visitor = + ModuleReferencesVisitor::new(eval_context, &import_references, &mut analysis); + + for (i, reexport) in eval_context.imports.reexports() { + let import_ref = import_references[i]; + match reexport { + Reexport::Star => { + visitor.esm_star_exports.push(Vc::upcast(import_ref)); + }, + Reexport::Namespace { exported: n } => { + visitor.esm_exports.insert( + n.as_str().into(), + EsmExport::ImportedNamespace(Vc::upcast(import_ref)), + ); + }, + Reexport::Named { imported: i, exported: e } => { + visitor.esm_exports.insert( + e.as_str().into(), + EsmExport::ImportedBinding( + Vc::upcast(import_ref), + i.to_string().into(), + false, + ), + ); + }, + } + } + + program.visit_with_path(&mut visitor, &mut Default::default()); + + ( + visitor.webpack_runtime, + visitor.webpack_entry, + visitor.webpack_chunks, + visitor.esm_exports, + visitor.esm_star_exports, + ) + }); + + for export in esm_exports.values() { + match *export { + EsmExport::LocalBinding(..) => {}, + EsmExport::ImportedNamespace(reference) => { + analysis.add_reexport_reference(reference); + }, + EsmExport::ImportedBinding(reference, ..) => { + analysis.add_reexport_reference(reference); + }, + EsmExport::Error => {}, + } + } + for &export in esm_star_exports.iter() { + analysis.add_reexport_reference(export); + } + + let mut ignore_effect_span = None; + // Check if it was a webpack entry + if let Some((request, span)) = webpack_runtime { + let request = Request::parse(Value::new(request.into())); + let runtime = resolve_as_webpack_runtime(origin, request, transforms); + + if let WebpackRuntime::Webpack5 { .. } = &*runtime.await? { + ignore_effect_span = Some(span); + analysis.add_reference( + WebpackRuntimeAssetReference { origin, request, runtime, transforms }.cell(), + ); + + if webpack_entry { + analysis.add_reference( + WebpackEntryAssetReference { source, runtime, transforms }.cell(), + ); + } + + for chunk in webpack_chunks { + analysis.add_reference( + WebpackChunkAssetReference { chunk_id:chunk, runtime, transforms }.cell(), + ); + } + } + } + + let exports = if !esm_exports.is_empty() || !esm_star_exports.is_empty() { + if specified_type == SpecifiedModuleType::CommonJs { + SpecifiedModuleTypeIssue { path:source.ident().path(), specified_type } + .cell() + .emit(); + } + + let esm_exports = EsmExports { exports:esm_exports, star_exports:esm_star_exports }.cell(); + + EcmascriptExports::EsmExports(esm_exports) + } else if specified_type == SpecifiedModuleType::EcmaScript { + match detect_dynamic_export(program) { + DetectedDynamicExportType::CommonJs => { + SpecifiedModuleTypeIssue { path:source.ident().path(), specified_type } + .cell() + .emit(); + + EcmascriptExports::EsmExports( + EsmExports { exports:Default::default(), star_exports:Default::default() } + .cell(), + ) + }, + DetectedDynamicExportType::Namespace => EcmascriptExports::DynamicNamespace, + DetectedDynamicExportType::Value => EcmascriptExports::Value, + DetectedDynamicExportType::UsingModuleDeclarations + | DetectedDynamicExportType::None => { + EcmascriptExports::EsmExports( + EsmExports { exports:Default::default(), star_exports:Default::default() } + .cell(), + ) + }, + } + } else { + match detect_dynamic_export(program) { + DetectedDynamicExportType::CommonJs => EcmascriptExports::CommonJs, + DetectedDynamicExportType::Namespace => EcmascriptExports::DynamicNamespace, + DetectedDynamicExportType::Value => EcmascriptExports::Value, + DetectedDynamicExportType::UsingModuleDeclarations => { + EcmascriptExports::EsmExports( + EsmExports { exports:Default::default(), star_exports:Default::default() } + .cell(), + ) + }, + DetectedDynamicExportType::None => EcmascriptExports::None, + } + }; + + let top_level_await_span = + set_handler_and_globals(&handler, globals, || has_top_level_await(program)); + let has_top_level_await = top_level_await_span.is_some(); + + if eval_context.is_esm() || specified_type == SpecifiedModuleType::EcmaScript { + let async_module = AsyncModule { has_top_level_await, import_externals }.cell(); + analysis.set_async_module(async_module); + } else if let Some(span) = top_level_await_span { + AnalyzeIssue { + code:None, + message:StyledString::Text("top level await is only supported in ESM modules.".into()) + .cell(), + source_ident:source.ident(), + severity:IssueSeverity::Error.into(), + source:Some(issue_source(source, span)), + title:Vc::cell("unexpected top level await".into()), + } + .cell() + .emit(); + } + + analysis.set_exports(exports); + + let effects = take(&mut var_graph.effects); + + let mut analysis_state = AnalysisState { + handler:&handler, + source, + origin, + compile_time_info, + var_graph:&var_graph, + fun_args_values:Mutex::new(HashMap::>::new()), + first_import_meta:true, + tree_shaking_mode:options.tree_shaking_mode, + import_externals:options.import_externals, + ignore_dynamic_requests:options.ignore_dynamic_requests, + }; + + enum Action { + Effect(Effect), + LeaveScope(u32), + } + + // This is a stack of effects to process. We use a stack since during processing + // of an effect we might want to add more effects into the middle of the + // processing. Using a stack where effects are appended in reverse + // order allows us to do that. It's recursion implemented as Stack. + let mut queue_stack = Mutex::new(Vec::new()); + queue_stack.get_mut().extend(effects.into_iter().map(Action::Effect).rev()); + + while let Some(action) = queue_stack.get_mut().pop() { + let effect = match action { + Action::LeaveScope(func_ident) => { + analysis_state.fun_args_values.get_mut().remove(&func_ident); + continue; + }, + Action::Effect(effect) => effect, + }; + + let add_effects = |effects:Vec| { + queue_stack.lock().extend(effects.into_iter().map(Action::Effect).rev()) + }; + + match effect { + Effect::Conditional { + condition, + kind, + ast_path: condition_ast_path, + span: _, + in_try, + } => { + let condition = analysis_state.link_value(condition, in_try).await?; + + macro_rules! inactive { + ($block:ident) => { + analysis.add_code_gen(Unreachable::new(Vc::cell($block.ast_path.to_vec()))); + }; + } + macro_rules! condition { + ($expr:expr) => { + analysis.add_code_gen(ConstantCondition::new( + Value::new($expr), + Vc::cell(condition_ast_path.to_vec()), + )); + }; + } + macro_rules! active { + ($block:ident) => { + queue_stack + .get_mut() + .extend($block.effects.into_iter().map(Action::Effect).rev()) + }; + } + match *kind { + ConditionalKind::If { then } => { + match condition.is_truthy() { + Some(true) => { + condition!(ConstantConditionValue::Truthy); + active!(then); + }, + Some(false) => { + condition!(ConstantConditionValue::Falsy); + inactive!(then); + }, + None => { + active!(then); + }, + } + }, + ConditionalKind::IfElse { then, r#else } + | ConditionalKind::Ternary { then, r#else } => { + match condition.is_truthy() { + Some(true) => { + condition!(ConstantConditionValue::Truthy); + active!(then); + inactive!(r#else); + }, + Some(false) => { + condition!(ConstantConditionValue::Falsy); + active!(r#else); + inactive!(then); + }, + None => { + active!(then); + active!(r#else); + }, + } + }, + ConditionalKind::And { expr } => { + match condition.is_truthy() { + Some(true) => { + condition!(ConstantConditionValue::Truthy); + active!(expr); + }, + Some(false) => { + // The condition value needs to stay since it's used + inactive!(expr); + }, + None => { + active!(expr); + }, + } + }, + ConditionalKind::Or { expr } => { + match condition.is_truthy() { + Some(true) => { + // The condition value needs to stay since it's used + inactive!(expr); + }, + Some(false) => { + condition!(ConstantConditionValue::Falsy); + active!(expr); + }, + None => { + active!(expr); + }, + } + }, + ConditionalKind::NullishCoalescing { expr } => { + match condition.is_nullish() { + Some(true) => { + condition!(ConstantConditionValue::Nullish); + active!(expr); + }, + Some(false) => { + inactive!(expr); + }, + None => { + active!(expr); + }, + } + }, + } + }, + Effect::Call { func, args, ast_path, span, in_try } => { + if let Some(ignored) = &ignore_effect_span { + if *ignored == span { + continue; + } + } + let func = analysis_state.link_value(func, in_try).await?; + + handle_call( + &ast_path, + span, + func, + JsValue::unknown_empty(false, "no this provided"), + args, + &analysis_state, + &add_effects, + &mut analysis, + in_try, + ) + .await?; + }, + Effect::MemberCall { obj, prop, mut args, ast_path, span, in_try } => { + if let Some(ignored) = &ignore_effect_span { + if *ignored == span { + continue; + } + } + let mut obj = analysis_state.link_value(obj, in_try).await?; + let prop = analysis_state.link_value(prop, in_try).await?; + + if let JsValue::Array { items: ref mut values, mutable, .. } = obj { + if matches!(prop.as_str(), Some("map" | "forEach" | "filter")) { + if let [EffectArg::Closure(value, block)] = &mut args[..] { + *value = analysis_state.link_value(take(value), in_try).await?; + if let JsValue::Function(_, func_ident, _) = value { + let mut closure_arg = JsValue::alternatives(take(values)); + if mutable { + closure_arg.add_unknown_mutations(true); + } + analysis_state + .fun_args_values + .get_mut() + .insert(*func_ident, vec![closure_arg]); + queue_stack.get_mut().push(Action::LeaveScope(*func_ident)); + queue_stack.get_mut().extend( + take(&mut block.effects).into_iter().map(Action::Effect).rev(), + ); + continue; + } + } + } + } + + let func = analysis_state + .link_value(JsValue::member(Box::new(obj.clone()), Box::new(prop)), in_try) + .await?; + + handle_call( + &ast_path, + span, + func, + obj, + args, + &analysis_state, + &add_effects, + &mut analysis, + in_try, + ) + .await?; + }, + Effect::FreeVar { var, ast_path, span, in_try: _ } => { + handle_free_var(&ast_path, var, span, &analysis_state, &mut analysis).await?; + }, + Effect::Member { obj, prop, ast_path, span, in_try } => { + let obj = analysis_state.link_value(obj, in_try).await?; + let prop = analysis_state.link_value(prop, in_try).await?; + + handle_member(&ast_path, obj, prop, span, &analysis_state, &mut analysis).await?; + }, + Effect::ImportedBinding { + esm_reference_index, + export, + ast_path, + span: _, + in_try: _, + } => { + if let Some(r) = import_references.get(esm_reference_index) { + if let Some("__turbopack_module_id__") = export.as_deref() { + analysis + .add_reference(EsmModuleIdAssetReference::new(*r, Vc::cell(ast_path))) + } else { + analysis.add_local_reference(*r); + analysis.add_code_gen(EsmBinding::new(*r, export, Vc::cell(ast_path))); + } + } + }, + Effect::ImportMeta { ast_path, span: _, in_try: _ } => { + if analysis_state.first_import_meta { + analysis_state.first_import_meta = false; + analysis.add_code_gen(ImportMetaBinding::new(source.ident().path())); + } + + analysis.add_code_gen(ImportMetaRef::new(Vc::cell(ast_path))); + }, + Effect::Url { input, ast_path, span, in_try } => { + let pat = js_value_to_pattern(&input); + if !pat.has_constant_parts() { + handler.span_warn_with_code( + span, + &format!("new URL({input}, import.meta.url) is very dynamic"), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::NEW_URL_IMPORT_META.to_string(), + ), + ); + if options.ignore_dynamic_requests { + continue; + } + } + analysis.add_reference(UrlAssetReference::new( + origin, + Request::parse(Value::new(pat)), + compile_time_info.environment().rendering(), + Vc::cell(ast_path), + IssueSource::from_swc_offsets(source, span.lo.to_usize(), span.hi.to_usize()), + in_try, + options.url_rewrite_behavior.unwrap_or(UrlRewriteBehavior::Relative).cell(), + )); + }, + } + } + + analysis.set_successful(true); + + analysis + .build(matches!(options.tree_shaking_mode, Some(TreeShakingMode::ReexportsOnly))) + .await +} + +fn handle_call_boxed<'a, G:Fn(Vec) + Send + Sync + 'a>( + ast_path:&'a [AstParentKind], + span:Span, + func:JsValue, + this:JsValue, + args:Vec, + state:&'a AnalysisState<'a>, + add_effects:&'a G, + analysis:&'a mut AnalyzeEcmascriptModuleResultBuilder, + in_try:bool, +) -> Pin> + Send + 'a>> { + Box::pin(handle_call( + ast_path, + span, + func, + this, + args, + state, + add_effects, + analysis, + in_try, + )) +} + +async fn handle_call) + Send + Sync>( + ast_path:&[AstParentKind], + span:Span, + func:JsValue, + this:JsValue, + args:Vec, + state:&AnalysisState<'_>, + add_effects:&G, + analysis:&mut AnalyzeEcmascriptModuleResultBuilder, + in_try:bool, +) -> Result<()> { + let &AnalysisState { + handler, origin, source, compile_time_info, ignore_dynamic_requests, .. + } = state; + fn explain_args(args:&[JsValue]) -> (String, String) { JsValue::explain_args(args, 10, 2) } + let linked_args = |args:Vec| { + async move { + args.into_iter() + .map(|arg| { + let add_effects = &add_effects; + async move { + let value = match arg { + EffectArg::Value(value) => value, + EffectArg::Closure(value, block) => { + add_effects(block.effects); + value + }, + EffectArg::Spread => { + JsValue::unknown_empty(true, "spread is not supported yet") + }, + }; + state.link_value(value, in_try).await + } + }) + .try_join() + .await + } + }; + match func { + JsValue::Alternatives(_, alts) => { + for alt in alts { + handle_call_boxed( + ast_path, + span, + alt, + this.clone(), + args.clone(), + state, + add_effects, + analysis, + in_try, + ) + .await?; + } + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::Import) => { + let args = linked_args(args).await?; + if args.len() == 1 { + let pat = js_value_to_pattern(&args[0]); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("import({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::DYNAMIC_IMPORT.to_string(), + ), + ); + if ignore_dynamic_requests { + analysis.add_code_gen(DynamicExpression::new_promise(Vc::cell( + ast_path.to_vec(), + ))); + return Ok(()); + } + } + analysis.add_reference(EsmAsyncAssetReference::new( + origin, + Request::parse(Value::new(pat)), + Vc::cell(ast_path.to_vec()), + issue_source(source, span), + in_try, + state.import_externals, + )); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("import({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::DYNAMIC_IMPORT.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::Require) => { + let args = linked_args(args).await?; + if args.len() == 1 { + let pat = js_value_to_pattern(&args[0]); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::REQUIRE.to_string(), + ), + ); + if ignore_dynamic_requests { + analysis.add_code_gen(DynamicExpression::new(Vc::cell(ast_path.to_vec()))); + return Ok(()); + } + } + analysis.add_reference(CjsRequireAssetReference::new( + origin, + Request::parse(Value::new(pat)), + Vc::cell(ast_path.to_vec()), + issue_source(source, span), + in_try, + )); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error(errors::failed_to_analyse::ecmascript::REQUIRE.to_string()), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::Define) => { + analyze_amd_define( + source, + analysis, + origin, + handler, + span, + ast_path, + linked_args(args).await?, + in_try, + ); + }, + + JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve) => { + let args = linked_args(args).await?; + if args.len() == 1 { + let pat = js_value_to_pattern(&args[0]); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require.resolve({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::REQUIRE_RESOLVE.to_string(), + ), + ); + if ignore_dynamic_requests { + analysis.add_code_gen(DynamicExpression::new(Vc::cell(ast_path.to_vec()))); + return Ok(()); + } + } + analysis.add_reference(CjsRequireResolveAssetReference::new( + origin, + Request::parse(Value::new(pat)), + Vc::cell(ast_path.to_vec()), + issue_source(source, span), + in_try, + )); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require.resolve({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::REQUIRE_RESOLVE.to_string(), + ), + ) + }, + + JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext) => { + let args = linked_args(args).await?; + let options = match parse_require_context(&args) { + Ok(options) => options, + Err(err) => { + let (args, hints) = explain_args(&args); + handler.span_err_with_code( + span, + &format!( + "require.context({args}) is not statically analyze-able: {}{hints}", + PrettyPrintError(&err) + ), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::REQUIRE_CONTEXT.to_string(), + ), + ); + return Ok(()); + }, + }; + + analysis.add_reference(RequireContextAssetReference::new( + source, + origin, + options.dir, + options.include_subdirs, + Vc::cell(options.filter), + Vc::cell(ast_path.to_vec()), + Some(issue_source(source, span)), + in_try, + )); + }, + + JsValue::WellKnownFunction(WellKnownFunctionKind::FsReadMethod(name)) => { + let args = linked_args(args).await?; + if !args.is_empty() { + let pat = js_value_to_pattern(&args[0]); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("fs.{name}({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::FS_METHOD.to_string(), + ), + ); + if ignore_dynamic_requests { + return Ok(()); + } + } + analysis.add_reference(FileSourceReference::new(source, Pattern::new(pat))); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("fs.{name}({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error(errors::failed_to_analyse::ecmascript::FS_METHOD.to_string()), + ) + }, + + JsValue::WellKnownFunction(WellKnownFunctionKind::PathResolve(..)) => { + let parent_path = origin.origin_path().parent().await?; + let args = linked_args(args).await?; + + let linked_func_call = state + .link_value( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::PathResolve( + Box::new(parent_path.path.as_str().into()), + ))), + args.clone(), + ), + in_try, + ) + .await?; + + let pat = js_value_to_pattern(&linked_func_call); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("path.resolve({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::PATH_METHOD.to_string(), + ), + ); + if ignore_dynamic_requests { + return Ok(()); + } + } + analysis.add_reference(FileSourceReference::new(source, Pattern::new(pat))); + return Ok(()); + }, + + JsValue::WellKnownFunction(WellKnownFunctionKind::PathJoin) => { + let context_path = source.ident().path().await?; + // ignore path.join in `node-gyp`, it will includes too many files + if context_path.path.contains("node_modules/node-gyp") { + return Ok(()); + } + let args = linked_args(args).await?; + let linked_func_call = state + .link_value( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::PathJoin)), + args.clone(), + ), + in_try, + ) + .await?; + let pat = js_value_to_pattern(&linked_func_call); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("path.join({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::PATH_METHOD.to_string(), + ), + ); + if ignore_dynamic_requests { + return Ok(()); + } + } + analysis.add_reference(DirAssetReference::new(source, Pattern::new(pat))); + return Ok(()); + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessSpawnMethod(name)) => { + let args = linked_args(args).await?; + + // Is this specifically `spawn(process.argv[0], ['-e', ...])`? + if is_invoking_node_process_eval(&args) { + return Ok(()); + } + + if !args.is_empty() { + let mut show_dynamic_warning = false; + let pat = js_value_to_pattern(&args[0]); + if pat.is_match_ignore_dynamic("node") && args.len() >= 2 { + let first_arg = + JsValue::member(Box::new(args[1].clone()), Box::new(0_f64.into())); + let first_arg = state.link_value(first_arg, in_try).await?; + let pat = js_value_to_pattern(&first_arg); + let dynamic = !pat.has_constant_parts(); + if dynamic { + show_dynamic_warning = true; + } + if !dynamic || !ignore_dynamic_requests { + analysis.add_reference(CjsAssetReference::new( + origin, + Request::parse(Value::new(pat)), + issue_source(source, span), + in_try, + )); + } + } + let dynamic = !pat.has_constant_parts(); + if dynamic { + show_dynamic_warning = true; + } + if !dynamic || !ignore_dynamic_requests { + analysis.add_reference(FileSourceReference::new(source, Pattern::new(pat))); + } + if show_dynamic_warning { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("child_process.{name}({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::CHILD_PROCESS_SPAWN.to_string(), + ), + ); + } + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("child_process.{name}({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::CHILD_PROCESS_SPAWN.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessFork) => { + let args = linked_args(args).await?; + if !args.is_empty() { + let first_arg = &args[0]; + let pat = js_value_to_pattern(first_arg); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("child_process.fork({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::CHILD_PROCESS_SPAWN.to_string(), + ), + ); + if ignore_dynamic_requests { + return Ok(()); + } + } + analysis.add_reference(CjsAssetReference::new( + origin, + Request::parse(Value::new(pat)), + issue_source(source, span), + in_try, + )); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("child_process.fork({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::CHILD_PROCESS_SPAWN.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::NodePreGypFind) => { + use turbopack_resolve::node_native_binding::NodePreGypConfigReference; + + let args = linked_args(args).await?; + if args.len() == 1 { + let first_arg = &args[0]; + let pat = js_value_to_pattern(first_arg); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("node-pre-gyp.find({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::NODE_PRE_GYP_FIND.to_string(), + ), + ); + // Always ignore this dynamic request + return Ok(()); + } + analysis.add_reference(NodePreGypConfigReference::new( + origin.origin_path().parent(), + Pattern::new(pat), + compile_time_info.environment().compile_target(), + )); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!( + "require('@mapbox/node-pre-gyp').find({args}) is not statically \ + analyse-able{hints}", + ), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::NODE_PRE_GYP_FIND.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeGypBuild) => { + use turbopack_resolve::node_native_binding::NodeGypBuildReference; + + let args = linked_args(args).await?; + if args.len() == 1 { + let first_arg = state.link_value(args[0].clone(), in_try).await?; + if let Some(s) = first_arg.as_str() { + // TODO this resolving should happen within Vc + let current_context = + origin.origin_path().root().join(s.trim_start_matches("/ROOT/").into()); + analysis.add_reference(NodeGypBuildReference::new( + current_context, + compile_time_info.environment().compile_target(), + )); + return Ok(()); + } + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require('node-gyp-build')({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::NODE_GYP_BUILD.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeBindings) => { + use turbopack_resolve::node_native_binding::NodeBindingsReference; + + let args = linked_args(args).await?; + if args.len() == 1 { + let first_arg = state.link_value(args[0].clone(), in_try).await?; + if let Some(s) = first_arg.as_str() { + analysis + .add_reference(NodeBindingsReference::new(origin.origin_path(), s.into())); + return Ok(()); + } + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require('bindings')({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::NODE_BINDINGS.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeExpressSet) => { + let args = linked_args(args).await?; + if args.len() == 2 { + if let Some(s) = args.first().and_then(|arg| arg.as_str()) { + let pkg_or_dir = args.get(1).unwrap(); + let pat = js_value_to_pattern(pkg_or_dir); + if !pat.has_constant_parts() { + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require('express')().set({args}) is very dynamic{hints}",), + DiagnosticId::Lint( + errors::failed_to_analyse::ecmascript::NODE_EXPRESS.to_string(), + ), + ); + // Always ignore this dynamic request + return Ok(()); + } + match s { + "views" => { + if let Pattern::Constant(p) = &pat { + let abs_pattern = if p.starts_with("/ROOT/") { + pat + } else { + let linked_func_call = state + .link_value( + JsValue::call( + Box::new(JsValue::WellKnownFunction( + WellKnownFunctionKind::PathJoin, + )), + vec![ + JsValue::FreeVar("__dirname".into()), + pkg_or_dir.clone(), + ], + ), + in_try, + ) + .await?; + js_value_to_pattern(&linked_func_call) + }; + analysis.add_reference(DirAssetReference::new( + source, + Pattern::new(abs_pattern), + )); + return Ok(()); + } + }, + "view engine" => { + if let Some(pkg) = pkg_or_dir.as_str() { + if pkg != "html" { + let pat = js_value_to_pattern(pkg_or_dir); + analysis.add_reference(CjsAssetReference::new( + origin, + Request::parse(Value::new(pat)), + issue_source(source, span), + in_try, + )); + } + return Ok(()); + } + }, + _ => {}, + } + } + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require('express')().set({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::NODE_EXPRESS.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeStrongGlobalizeSetRootDir) => { + let args = linked_args(args).await?; + if let Some(p) = args.first().and_then(|arg| arg.as_str()) { + let abs_pattern = if p.starts_with("/ROOT/") { + Pattern::Constant(format!("{p}/intl").into()) + } else { + let linked_func_call = state + .link_value( + JsValue::call( + Box::new(JsValue::WellKnownFunction( + WellKnownFunctionKind::PathJoin, + )), + vec![JsValue::FreeVar("__dirname".into()), p.into(), "intl".into()], + ), + in_try, + ) + .await?; + js_value_to_pattern(&linked_func_call) + }; + analysis.add_reference(DirAssetReference::new(source, Pattern::new(abs_pattern))); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!( + "require('strong-globalize').SetRootDir({args}) is not statically \ + analyse-able{hints}", + ), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::NODE_GYP_BUILD.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom) => { + let args = linked_args(args).await?; + if args.len() == 2 && args.get(1).and_then(|arg| arg.as_str()).is_some() { + analysis.add_reference(CjsAssetReference::new( + origin, + Request::parse(Value::new(js_value_to_pattern(&args[1]))), + issue_source(source, span), + in_try, + )); + return Ok(()); + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!("require('resolve-from')({args}) is not statically analyse-able{hints}",), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::NODE_RESOLVE_FROM.to_string(), + ), + ) + }, + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeProtobufLoad) => { + let args = linked_args(args).await?; + if args.len() == 2 { + if let Some(JsValue::Object { parts, .. }) = args.get(1) { + for dir in + parts + .iter() + .filter_map(|object_part| { + if let ObjectPart::KeyValue( + JsValue::Constant(key), + JsValue::Array { items: dirs, .. }, + ) = object_part + { + if key.as_str() == Some("includeDirs") { + return Some(dirs.iter().filter_map(|dir| { + dir.as_str().map(ToString::to_string) + })); + } + } + None + }) + .flatten() + { + analysis.add_reference(DirAssetReference::new( + source, + Pattern::new(Pattern::Constant(dir.into())), + )); + } + return Ok(()); + } + } + let (args, hints) = explain_args(&args); + handler.span_warn_with_code( + span, + &format!( + "require('@grpc/proto-loader').load({args}) is not statically \ + analyse-able{hints}", + ), + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::NODE_PROTOBUF_LOADER.to_string(), + ), + ) + }, + _ => { + for arg in args { + if let EffectArg::Closure(_, block) = arg { + add_effects(block.effects); + } + } + }, + } + Ok(()) +} + +async fn handle_member( + ast_path:&[AstParentKind], + obj:JsValue, + prop:JsValue, + span:Span, + state:&AnalysisState<'_>, + analysis:&mut AnalyzeEcmascriptModuleResultBuilder, +) -> Result<()> { + if let Some(prop) = prop.as_str() { + if let Some(def_name_len) = obj.get_defineable_name_len() { + let compile_time_info = state.compile_time_info.await?; + let free_var_references = compile_time_info.free_var_references.await?; + for (name, value) in free_var_references.iter() { + if name.len() != def_name_len + 1 { + continue; + } + let mut it = name.iter().map(|v| Cow::Borrowed(&**v)).rev(); + if it.next().unwrap() != Cow::Borrowed(prop) { + continue; + } + if it.eq(obj.iter_defineable_name_rev()) + && handle_free_var_reference(ast_path, value, span, state, analysis).await? + { + return Ok(()); + } + } + } + } + match (obj, prop) { + (JsValue::WellKnownFunction(WellKnownFunctionKind::Require), JsValue::Constant(s)) + if s.as_str() == Some("cache") => + { + analysis + .add_code_gen(CjsRequireCacheAccess { path:Vc::cell(ast_path.to_vec()) }.cell()); + }, + _ => {}, + } + + Ok(()) +} + +async fn handle_free_var( + ast_path:&[AstParentKind], + var:JsValue, + span:Span, + state:&AnalysisState<'_>, + analysis:&mut AnalyzeEcmascriptModuleResultBuilder, +) -> Result<()> { + if let Some(def_name_len) = var.get_defineable_name_len() { + let compile_time_info = state.compile_time_info.await?; + let free_var_references = compile_time_info.free_var_references.await?; + for (name, value) in free_var_references.iter() { + if name.len() != def_name_len { + continue; + } + + if var + .iter_defineable_name_rev() + .eq(name.iter().map(|v| Cow::Borrowed(&**v)).rev()) + && handle_free_var_reference(ast_path, value, span, state, analysis).await? + { + return Ok(()); + } + } + } + + Ok(()) +} + +async fn handle_free_var_reference( + ast_path:&[AstParentKind], + value:&FreeVarReference, + span:Span, + state:&AnalysisState<'_>, + analysis:&mut AnalyzeEcmascriptModuleResultBuilder, +) -> Result { + // We don't want to replace assignments as this would lead to invalid code. + if matches!( + ast_path, + [ + .., + AstParentKind::AssignExpr(AssignExprField::Left), + AstParentKind::AssignTarget(AssignTargetField::Simple), + AstParentKind::SimpleAssignTarget(SimpleAssignTargetField::Member), + ] + ) { + return Ok(false); + } + + match value { + FreeVarReference::Error(error_message) => { + state.handler.span_err_with_code( + span, + error_message, + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::FREE_VAR_REFERENCE.to_string(), + ), + ) + }, + + FreeVarReference::Value(value) => { + analysis.add_code_gen(ConstantValue::new( + Value::new(value.clone()), + Vc::cell(ast_path.to_vec()), + )); + }, + FreeVarReference::EcmaScriptModule { request, lookup_path, export } => { + let esm_reference = EsmAssetReference::new( + lookup_path.map_or(state.origin, |lookup_path| { + Vc::upcast(PlainResolveOrigin::new(state.origin.asset_context(), lookup_path)) + }), + Request::parse(Value::new(request.clone().into())), + Some(IssueSource::from_swc_offsets( + state.source, + span.lo.to_usize(), + span.hi.to_usize(), + )), + Default::default(), + match state.tree_shaking_mode { + Some(TreeShakingMode::ModuleFragments) + | Some(TreeShakingMode::ReexportsOnly) => { + export.as_ref().map(|export| ModulePart::export(export.clone())) + }, + None => None, + }, + state.import_externals, + ) + .resolve() + .await?; + analysis.add_reference(esm_reference); + analysis.add_code_gen(EsmBinding::new( + esm_reference, + export.clone(), + Vc::cell(ast_path.to_vec()), + )); + }, + } + Ok(true) +} + +fn issue_source(source:Vc>, span:Span) -> Vc { + IssueSource::from_swc_offsets(source, span.lo.to_usize(), span.hi.to_usize()) +} + +fn analyze_amd_define( + source:Vc>, + analysis:&mut AnalyzeEcmascriptModuleResultBuilder, + origin:Vc>, + handler:&Handler, + span:Span, + ast_path:&[AstParentKind], + args:Vec, + in_try:bool, +) { + match &args[..] { + [JsValue::Constant(id), JsValue::Array { items: deps, .. }, _] if id.as_str().is_some() => { + analyze_amd_define_with_deps( + source, + analysis, + origin, + handler, + span, + ast_path, + id.as_str(), + deps, + in_try, + ); + }, + [JsValue::Array { items: deps, .. }, _] => { + analyze_amd_define_with_deps( + source, analysis, origin, handler, span, ast_path, None, deps, in_try, + ); + }, + [JsValue::Constant(id), JsValue::Function(..)] if id.as_str().is_some() => { + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( + vec![ + AmdDefineDependencyElement::Require, + AmdDefineDependencyElement::Exports, + AmdDefineDependencyElement::Module, + ], + origin, + Vc::cell(ast_path.to_vec()), + AmdDefineFactoryType::Function, + issue_source(source, span), + in_try, + )); + }, + [JsValue::Constant(id), _] if id.as_str().is_some() => { + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( + vec![ + AmdDefineDependencyElement::Require, + AmdDefineDependencyElement::Exports, + AmdDefineDependencyElement::Module, + ], + origin, + Vc::cell(ast_path.to_vec()), + AmdDefineFactoryType::Unknown, + issue_source(source, span), + in_try, + )); + }, + [JsValue::Function(..)] => { + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( + vec![ + AmdDefineDependencyElement::Require, + AmdDefineDependencyElement::Exports, + AmdDefineDependencyElement::Module, + ], + origin, + Vc::cell(ast_path.to_vec()), + AmdDefineFactoryType::Function, + issue_source(source, span), + in_try, + )); + }, + [JsValue::Object { .. }] => { + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( + vec![], + origin, + Vc::cell(ast_path.to_vec()), + AmdDefineFactoryType::Value, + issue_source(source, span), + in_try, + )); + }, + [_] => { + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( + vec![ + AmdDefineDependencyElement::Require, + AmdDefineDependencyElement::Exports, + AmdDefineDependencyElement::Module, + ], + origin, + Vc::cell(ast_path.to_vec()), + AmdDefineFactoryType::Unknown, + issue_source(source, span), + in_try, + )); + }, + _ => { + handler.span_err_with_code( + span, + "unsupported AMD define() form", + DiagnosticId::Error(errors::failed_to_analyse::ecmascript::AMD_DEFINE.to_string()), + ); + }, + } +} + +fn analyze_amd_define_with_deps( + source:Vc>, + analysis:&mut AnalyzeEcmascriptModuleResultBuilder, + origin:Vc>, + handler:&Handler, + span:Span, + ast_path:&[AstParentKind], + id:Option<&str>, + deps:&[JsValue], + in_try:bool, +) { + let mut requests = Vec::new(); + for dep in deps { + if let Some(dep) = dep.as_str() { + match dep { + "exports" => { + requests.push(AmdDefineDependencyElement::Exports); + }, + "require" => { + handler.span_warn_with_code( + span, + "using \"require\" as dependency in an AMD define() is not yet supported", + DiagnosticId::Error( + errors::failed_to_analyse::ecmascript::AMD_DEFINE.to_string(), + ), + ); + requests.push(AmdDefineDependencyElement::Require); + }, + "module" => { + requests.push(AmdDefineDependencyElement::Module); + }, + _ => { + let request = Request::parse_string(dep.into()); + let reference = AmdDefineAssetReference::new( + origin, + request, + issue_source(source, span), + in_try, + ); + requests.push(AmdDefineDependencyElement::Request { + request, + request_str:dep.to_string(), + }); + analysis.add_reference(reference); + }, + } + } else { + handler.span_err_with_code( + // TODO(alexkirsz) It'd be best to highlight the argument's span, but + // `JsValue`s do not keep a hold of their original span. + span, + "unsupported AMD define() dependency element form", + DiagnosticId::Error(errors::failed_to_analyse::ecmascript::AMD_DEFINE.to_string()), + ); + } + } + + if id.is_some() { + handler.span_warn_with_code( + span, + "passing an ID to AMD define() is not yet fully supported", + DiagnosticId::Lint(errors::failed_to_analyse::ecmascript::AMD_DEFINE.to_string()), + ); + } + + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( + requests, + origin, + Vc::cell(ast_path.to_vec()), + AmdDefineFactoryType::Function, + issue_source(source, span), + in_try, + )); +} + +/// Used to generate the "root" path to a __filename/__dirname/import.meta.url +/// reference. +pub async fn as_abs_path(path:Vc) -> Result { + // TODO: This should be updated to generate a real system path on the fly + // during runtime, so that the generated code is constant between systems + // but the runtime evaluation can take into account the project's + // actual root directory. + require_resolve(path).await +} + +/// Generates an absolute path usable for `require.resolve()` calls. +async fn require_resolve(path:Vc) -> Result { + Ok(format!("/ROOT/{}", path.await?.path.as_str()).into()) +} + +async fn early_value_visitor(mut v:JsValue) -> Result<(JsValue, bool)> { + let modified = early_replace_builtin(&mut v); + Ok((v, modified)) +} + +async fn value_visitor( + origin:Vc>, + v:JsValue, + compile_time_info:Vc, + in_try:bool, +) -> Result<(JsValue, bool)> { + let (mut v, modified) = value_visitor_inner(origin, v, compile_time_info, in_try).await?; + v.normalize_shallow(); + Ok((v, modified)) +} + +async fn value_visitor_inner( + origin:Vc>, + v:JsValue, + compile_time_info:Vc, + in_try:bool, +) -> Result<(JsValue, bool)> { + if let Some(def_name_len) = v.get_defineable_name_len() { + let compile_time_info = compile_time_info.await?; + let defines = compile_time_info.defines.await?; + for (name, value) in defines.iter() { + if name.len() != def_name_len { + continue; + } + if v.iter_defineable_name_rev().eq(name.iter().map(|v| Cow::Borrowed(&**v)).rev()) { + return Ok((value.into(), true)); + } + } + } + let value = match v { + JsValue::Call( + _, + box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve), + args, + ) => require_resolve_visitor(origin, args, in_try).await?, + JsValue::Call( + _, + box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext), + args, + ) => require_context_visitor(origin, args, in_try).await?, + JsValue::Call( + _, + box JsValue::WellKnownFunction( + WellKnownFunctionKind::RequireContextRequire(..) + | WellKnownFunctionKind::RequireContextRequireKeys(..) + | WellKnownFunctionKind::RequireContextRequireResolve(..), + ), + _, + ) => { + // TODO: figure out how to do static analysis without invalidating the while + // analysis when a new file gets added + v.into_unknown(true, "require.context() static analysis is currently limited") + }, + JsValue::FreeVar(ref kind) => { + match &**kind { + "__dirname" => as_abs_path(origin.origin_path().parent()).await?, + "__filename" => as_abs_path(origin.origin_path()).await?, + + "require" => JsValue::WellKnownFunction(WellKnownFunctionKind::Require), + "define" => JsValue::WellKnownFunction(WellKnownFunctionKind::Define), + "import" => JsValue::WellKnownFunction(WellKnownFunctionKind::Import), + "process" => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess), + "Object" => JsValue::WellKnownObject(WellKnownObjectKind::GlobalObject), + "Buffer" => JsValue::WellKnownObject(WellKnownObjectKind::NodeBuffer), + _ => return Ok((v, false)), + } + }, + JsValue::Module(ModuleValue { module: ref name, .. }) => { + if *compile_time_info.environment().node_externals().await? { + // TODO check externals + match &**name { + "node:path" | "path" => { + JsValue::WellKnownObject(WellKnownObjectKind::PathModule) + }, + "node:fs/promises" | "fs/promises" => { + JsValue::WellKnownObject(WellKnownObjectKind::FsModule) + }, + "node:fs" | "fs" => JsValue::WellKnownObject(WellKnownObjectKind::FsModule), + "node:child_process" | "child_process" => { + JsValue::WellKnownObject(WellKnownObjectKind::ChildProcess) + }, + "node:os" | "os" => JsValue::WellKnownObject(WellKnownObjectKind::OsModule), + "node:process" | "process" => { + JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess) + }, + "@mapbox/node-pre-gyp" => { + JsValue::WellKnownObject(WellKnownObjectKind::NodePreGyp) + }, + "node-gyp-build" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeGypBuild) + }, + "node:bindings" | "bindings" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeBindings) + }, + "express" => JsValue::WellKnownFunction(WellKnownFunctionKind::NodeExpress), + "strong-globalize" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeStrongGlobalize) + }, + "resolve-from" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom) + }, + "@grpc/proto-loader" => { + JsValue::WellKnownObject(WellKnownObjectKind::NodeProtobufLoader) + }, + _ => v.into_unknown(true, "cross module analyzing is not yet supported"), + } + } else { + v.into_unknown(true, "cross module analyzing is not yet supported") + } + }, + JsValue::Argument(..) => { + v.into_unknown(true, "cross function analyzing is not yet supported") + }, + _ => { + let (mut v, mut modified) = replace_well_known(v, compile_time_info).await?; + modified = replace_builtin(&mut v) || modified; + modified = modified || v.make_nested_operations_unknown(); + return Ok((v, modified)); + }, + }; + Ok((value, true)) +} + +async fn require_resolve_visitor( + origin:Vc>, + args:Vec, + in_try:bool, +) -> Result { + Ok(if args.len() == 1 { + let pat = js_value_to_pattern(&args[0]); + let request = Request::parse(Value::new(pat.clone())); + let resolved = + cjs_resolve(origin, request, None, try_to_severity(in_try)).resolve().await?; + let mut values = resolved + .primary_modules() + .await? + .iter() + .map(|&module| async move { require_resolve(module.ident().path()).await }) + .try_join() + .await?; + + match values.len() { + 0 => { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve)), + args, + ), + false, + "unresolveable request", + ) + }, + 1 => values.pop().unwrap(), + _ => JsValue::alternatives(values), + } + } else { + JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve)), + args, + ), + true, + "only a single argument is supported", + ) + }) +} + +async fn require_context_visitor( + origin:Vc>, + args:Vec, + in_try:bool, +) -> Result { + let options = match parse_require_context(&args) { + Ok(options) => options, + Err(err) => { + return Ok(JsValue::unknown( + JsValue::call( + Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext)), + args, + ), + true, + PrettyPrintError(&err).to_string(), + )); + }, + }; + + let dir = origin.origin_path().parent().join(options.dir.clone()); + + let map = RequireContextMap::generate( + origin, + dir, + options.include_subdirs, + Vc::cell(options.filter), + None, + try_to_severity(in_try), + ); + + Ok(JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequire( + RequireContextValue::from_context_map(map), + ))) +} + +#[derive(Debug)] +enum StaticExpr { + String(String), + FreeVar(Vec), + ImportedVar(String, Vec), + Unknown, +} + +// TODO get rid of that +#[derive(Default)] +struct StaticAnalyser { + imports:HashMap)>, +} + +impl StaticAnalyser { + fn prop_to_name(&self, prop:&MemberProp) -> Option { + match prop { + MemberProp::Ident(ident) => Some(ident.sym.to_string()), + MemberProp::PrivateName(_) => None, + MemberProp::Computed(ComputedPropName { expr, .. }) => { + match self.evaluate_expr(expr) { + StaticExpr::String(str) => Some(str), + _ => None, + } + }, + } + } + + fn evaluate_expr(&self, expr:&Expr) -> StaticExpr { + match expr { + Expr::Lit(Lit::Str(str)) => StaticExpr::String(str.value.to_string()), + Expr::Ident(ident) => { + let str = ident.sym.to_string(); + match self.imports.get(&str) { + Some((module, import)) => { + StaticExpr::ImportedVar(module.clone(), import.clone()) + }, + None => StaticExpr::FreeVar(vec![str]), + } + }, + Expr::Member(member) => { + match self.evaluate_expr(&member.obj) { + StaticExpr::FreeVar(mut vec) => { + match self.prop_to_name(&member.prop) { + Some(name) => { + vec.push(name); + StaticExpr::FreeVar(vec) + }, + None => StaticExpr::Unknown, + } + }, + StaticExpr::ImportedVar(module, mut vec) => { + match self.prop_to_name(&member.prop) { + Some(name) => { + vec.push(name); + StaticExpr::ImportedVar(module, vec) + }, + None => StaticExpr::Unknown, + } + }, + _ => StaticExpr::Unknown, + } + }, + _ => StaticExpr::Unknown, + } + } +} + +struct ModuleReferencesVisitor<'a> { + eval_context:&'a EvalContext, + old_analyser:StaticAnalyser, + import_references:&'a [Vc], + analysis:&'a mut AnalyzeEcmascriptModuleResultBuilder, + esm_exports:BTreeMap, + esm_star_exports:Vec>>, + webpack_runtime:Option<(RcStr, Span)>, + webpack_entry:bool, + webpack_chunks:Vec, +} + +impl<'a> ModuleReferencesVisitor<'a> { + fn new( + eval_context:&'a EvalContext, + import_references:&'a [Vc], + analysis:&'a mut AnalyzeEcmascriptModuleResultBuilder, + ) -> Self { + Self { + eval_context, + old_analyser:StaticAnalyser::default(), + import_references, + analysis, + esm_exports:BTreeMap::new(), + esm_star_exports:Vec::new(), + webpack_runtime:None, + webpack_entry:false, + webpack_chunks:Vec::new(), + } + } +} + +fn as_parent_path(ast_path:&AstNodePath>) -> Vec { + ast_path.iter().map(|n| n.kind()).collect() +} + +fn for_each_ident_in_decl(decl:&Decl, f:&mut impl FnMut(RcStr)) { + match decl { + Decl::Class(ClassDecl { ident, .. }) | Decl::Fn(FnDecl { ident, .. }) => { + f(ident.sym.as_str().into()); + }, + Decl::Var(var_decl) => { + let decls = &*var_decl.decls; + decls + .iter() + .for_each(|VarDeclarator { name, .. }| for_each_ident_in_pat(name, f)); + }, + Decl::Using(using_decl) => { + let decls = &*using_decl.decls; + decls + .iter() + .for_each(|VarDeclarator { name, .. }| for_each_ident_in_pat(name, f)); + }, + Decl::TsInterface(_) | Decl::TsTypeAlias(_) | Decl::TsEnum(_) | Decl::TsModule(_) => { + // ignore typescript for code generation + }, + } +} +fn for_each_ident_in_pat(pat:&Pat, f:&mut impl FnMut(RcStr)) { + match pat { + Pat::Ident(BindingIdent { id, .. }) => { + f(id.sym.as_str().into()); + }, + Pat::Array(ArrayPat { elems, .. }) => { + elems.iter().for_each(|e| { + if let Some(e) = e { + for_each_ident_in_pat(e, f); + } + }) + }, + Pat::Rest(RestPat { arg, .. }) => { + for_each_ident_in_pat(arg, f); + }, + Pat::Object(ObjectPat { props, .. }) => { + props.iter().for_each(|p| { + match p { + ObjectPatProp::KeyValue(KeyValuePatProp { value, .. }) => { + for_each_ident_in_pat(value, f); + }, + ObjectPatProp::Assign(AssignPatProp { key, .. }) => { + f(key.sym.as_str().into()); + }, + ObjectPatProp::Rest(RestPat { arg, .. }) => { + for_each_ident_in_pat(arg, f); + }, + } + }); + }, + Pat::Assign(AssignPat { left, .. }) => { + for_each_ident_in_pat(left, f); + }, + Pat::Invalid(_) | Pat::Expr(_) => { + panic!("Unexpected pattern while enumerating idents"); + }, + } +} + +impl<'a> VisitAstPath for ModuleReferencesVisitor<'a> { + fn visit_export_all<'ast:'r, 'r>( + &mut self, + export:&'ast ExportAll, + ast_path:&mut AstNodePath>, + ) { + let path = Vc::cell(as_parent_path(ast_path)); + self.analysis.add_code_gen(EsmModuleItem::new(path)); + export.visit_children_with_path(self, ast_path); + } + + fn visit_named_export<'ast:'r, 'r>( + &mut self, + export:&'ast NamedExport, + ast_path:&mut AstNodePath>, + ) { + let path = Vc::cell(as_parent_path(ast_path)); + // We create mutable exports for fake ESMs generated by module splitting + let is_fake_esm = export.with.as_deref().map(find_turbopack_part_id_in_asserts).is_some(); + + if export.src.is_none() { + for spec in export.specifiers.iter() { + fn to_string(name:&ModuleExportName) -> &JsWord { name.atom() } + match spec { + ExportSpecifier::Namespace(_) => { + panic!( + "ExportNamespaceSpecifier will not happen in combination with src == \ + None" + ); + }, + ExportSpecifier::Default(_) => { + panic!( + "ExportDefaultSpecifier will not happen in combination with src == \ + None" + ); + }, + ExportSpecifier::Named(ExportNamedSpecifier { orig, exported, .. }) => { + let key = to_string(exported.as_ref().unwrap_or(orig)).as_str().into(); + let binding_name = to_string(orig).as_str().into(); + let export = { + let imported_binding = if let ModuleExportName::Ident(ident) = orig { + self.eval_context.imports.get_binding(&ident.to_id()) + } else { + None + }; + if let Some((index, export)) = imported_binding { + let esm_ref = self.import_references[index]; + if let Some(export) = export { + EsmExport::ImportedBinding( + Vc::upcast(esm_ref), + export, + is_fake_esm, + ) + } else { + EsmExport::ImportedNamespace(Vc::upcast(esm_ref)) + } + } else { + EsmExport::LocalBinding(binding_name, is_fake_esm) + } + }; + self.esm_exports.insert(key, export); + }, + } + } + } + + self.analysis.add_code_gen(EsmModuleItem::new(path)); + export.visit_children_with_path(self, ast_path); + } + + fn visit_export_decl<'ast:'r, 'r>( + &mut self, + export:&'ast ExportDecl, + ast_path:&mut AstNodePath>, + ) { + for_each_ident_in_decl(&export.decl, &mut |name| { + self.esm_exports.insert(name.clone(), EsmExport::LocalBinding(name, false)); + }); + self.analysis + .add_code_gen(EsmModuleItem::new(Vc::cell(as_parent_path(ast_path)))); + export.visit_children_with_path(self, ast_path); + } + + fn visit_export_default_expr<'ast:'r, 'r>( + &mut self, + export:&'ast ExportDefaultExpr, + ast_path:&mut AstNodePath>, + ) { + self.esm_exports.insert( + "default".into(), + EsmExport::LocalBinding(magic_identifier::mangle("default export").into(), false), + ); + self.analysis + .add_code_gen(EsmModuleItem::new(Vc::cell(as_parent_path(ast_path)))); + export.visit_children_with_path(self, ast_path); + } + + fn visit_export_default_decl<'ast:'r, 'r>( + &mut self, + export:&'ast ExportDefaultDecl, + ast_path:&mut AstNodePath>, + ) { + match &export.decl { + DefaultDecl::Class(ClassExpr { ident, .. }) | DefaultDecl::Fn(FnExpr { ident, .. }) => { + self.esm_exports.insert( + "default".into(), + EsmExport::LocalBinding( + ident + .as_ref() + .map(|i| i.sym.as_str().into()) + .unwrap_or_else(|| magic_identifier::mangle("default export").into()), + false, + ), + ); + }, + DefaultDecl::TsInterfaceDecl(..) => { + // ignore + }, + } + self.analysis + .add_code_gen(EsmModuleItem::new(Vc::cell(as_parent_path(ast_path)))); + export.visit_children_with_path(self, ast_path); + } + + fn visit_import_decl<'ast:'r, 'r>( + &mut self, + import:&'ast ImportDecl, + ast_path:&mut AstNodePath>, + ) { + let path = Vc::cell(as_parent_path(ast_path)); + let src = import.src.value.to_string(); + import.visit_children_with_path(self, ast_path); + if import.type_only { + return; + } + for specifier in &import.specifiers { + match specifier { + ImportSpecifier::Named(named) => { + if !named.is_type_only { + self.old_analyser.imports.insert( + named.local.sym.to_string(), + ( + src.clone(), + vec![match &named.imported { + Some(ModuleExportName::Ident(ident)) => ident.sym.to_string(), + Some(ModuleExportName::Str(str)) => str.value.to_string(), + None => named.local.sym.to_string(), + }], + ), + ); + } + }, + ImportSpecifier::Default(default_import) => { + self.old_analyser.imports.insert( + default_import.local.sym.to_string(), + (src.clone(), vec!["default".to_string()]), + ); + }, + ImportSpecifier::Namespace(namespace) => { + self.old_analyser + .imports + .insert(namespace.local.sym.to_string(), (src.clone(), Vec::new())); + }, + } + } + self.analysis.add_code_gen(EsmModuleItem::new(path)); + } + + fn visit_var_declarator<'ast:'r, 'r>( + &mut self, + decl:&'ast VarDeclarator, + ast_path:&mut AstNodePath>, + ) { + if let Some(ident) = decl.name.as_ident() { + if &*ident.id.sym == "__webpack_require__" { + if let Some(init) = &decl.init { + if let Some(call) = init.as_call() { + if let Some(expr) = call.callee.as_expr() { + if let Some(ident) = expr.as_ident() { + if &*ident.sym == "require" { + if let [ExprOrSpread { spread: None, expr }] = &call.args[..] { + if let Some(Lit::Str(str)) = expr.as_lit() { + self.webpack_runtime = + Some((str.value.as_str().into(), call.span)); + return; + } + } + } + } + } + } + } + } + } + decl.visit_children_with_path(self, ast_path); + } + + fn visit_call_expr<'ast:'r, 'r>( + &mut self, + call:&'ast CallExpr, + ast_path:&mut AstNodePath>, + ) { + if let Callee::Expr(expr) = &call.callee { + if let StaticExpr::FreeVar(var) = self.old_analyser.evaluate_expr(expr) { + match &var[..] { + [webpack_require, property] + if webpack_require == "__webpack_require__" && property == "C" => + { + self.webpack_entry = true; + }, + [webpack_require, property] + if webpack_require == "__webpack_require__" && property == "X" => + { + if let [_, ExprOrSpread { spread: None, expr: chunk_ids }, _] = + &call.args[..] + { + if let Some(array) = chunk_ids.as_array() { + for elem in array.elems.iter().flatten() { + if let ExprOrSpread { spread: None, expr } = elem { + if let Some(lit) = expr.as_lit() { + self.webpack_chunks.push(lit.clone()); + } + } + } + } + } + }, + _ => {}, + } + } + } + call.visit_children_with_path(self, ast_path); + } +} + +#[turbo_tasks::function] +async fn resolve_as_webpack_runtime( + origin:Vc>, + request:Vc, + transforms:Vc, +) -> Result> { + let ty = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)); + let options = origin.resolve_options(ty.clone()); + + let options = apply_cjs_specific_options(options); + + let resolved = resolve( + origin.origin_path().parent().resolve().await?, + Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)), + request, + options, + ); + + if let Some(source) = *resolved.first_source().await? { + Ok(webpack_runtime(source, transforms)) + } else { + Ok(WebpackRuntime::None.into()) + } +} + +// TODO enable serialization +#[turbo_tasks::value(transparent, serialization = "none")] +pub struct AstPath(#[turbo_tasks(trace_ignore)] Vec); + +pub static TURBOPACK_HELPER:Lazy = Lazy::new(|| "__turbopack-helper__".into()); + +pub fn is_turbopack_helper_import(import:&ImportDecl) -> bool { + let annotations = ImportAnnotations::parse(import.with.as_deref()); + + annotations.get(&TURBOPACK_HELPER).is_some() +} + +#[derive(Debug)] +enum DetectedDynamicExportType { + CommonJs, + Namespace, + Value, + None, + UsingModuleDeclarations, +} + +fn detect_dynamic_export(p:&Program) -> DetectedDynamicExportType { + use swc_core::ecma::visit::{Visit, VisitWith, visit_obj_and_computed}; + + if let Program::Module(m) = p { + // Check for imports/exports + if m.body.iter().any(|item| { + item.as_module_decl().map_or(false, |module_decl| { + module_decl + .as_import() + .map_or(true, |import| !is_turbopack_helper_import(import)) + }) + }) { + return DetectedDynamicExportType::UsingModuleDeclarations; + } + } + + struct Visitor { + cjs:bool, + value:bool, + namespace:bool, + found:bool, + } + + impl Visit for Visitor { + visit_obj_and_computed!(); + + fn visit_ident(&mut self, i:&Ident) { + // The detection is not perfect, it might have some false positives, e. g. in + // cases where `module` is used in some other way. e. g. `const module = 42;`. + // But a false positive doesn't break anything, it only opts out of some + // optimizations, which is acceptable. + if &*i.sym == "module" || &*i.sym == "exports" { + self.cjs = true; + self.found = true; + } + if &*i.sym == "__turbopack_export_value__" { + self.value = true; + self.found = true; + } + if &*i.sym == "__turbopack_export_namespace__" { + self.namespace = true; + self.found = true; + } + } + + fn visit_expr(&mut self, n:&Expr) { + if self.found { + return; + } + n.visit_children_with(self); + } + + fn visit_stmt(&mut self, n:&Stmt) { + if self.found { + return; + } + n.visit_children_with(self); + } + } + + let mut v = Visitor { cjs:false, value:false, namespace:false, found:false }; + p.visit_with(&mut v); + if v.cjs { + DetectedDynamicExportType::CommonJs + } else if v.value { + DetectedDynamicExportType::Value + } else if v.namespace { + DetectedDynamicExportType::Namespace + } else { + DetectedDynamicExportType::None + } +} + +/// Detects whether a list of arguments is specifically +/// `(process.argv[0], ['-e', ...])`. This is useful for detecting if a node +/// process is being spawned to interpret a string of JavaScript code, and does +/// not require static analysis. +fn is_invoking_node_process_eval(args:&[JsValue]) -> bool { + if args.len() < 2 { + return false; + } + + if let JsValue::Member(_, obj, constant) = &args[0] { + // Is the first argument to spawn `process.argv[]`? + if let ( + box JsValue::WellKnownObject(WellKnownObjectKind::NodeProcessArgv), + box JsValue::Constant(JsConstantValue::Num(ConstantNumber(num))), + ) = (obj, constant) + { + // Is it specifically `process.argv[0]`? + if num.is_zero() { + if let JsValue::Array { total_nodes: _, items, mutable: _ } = &args[1] { + // Is `-e` one of the arguments passed to the program? + if items.iter().any(|e| { + if let JsValue::Constant(JsConstantValue::Str(ConstantString::Word(arg))) = + e + { + arg == "-e" + } else { + false + } + }) { + // If so, this is likely spawning node to evaluate a string, and + // does not need to be statically analyzed. + return true; + } + } + } + } + } + + false +} + +#[turbo_tasks::function] +fn maybe_decode_data_url(url:RcStr) -> Vc { + if let Ok(map) = decode_data_url(&url) { + Vc::cell(Some(SourceMap::new_decoded(map).cell())) + } else { + Vc::cell(None) + } +} + +#[turbo_tasks::function] +async fn convert_to_turbopack_source_map( + source_map:Vc, + origin:Vc, +) -> Result> { + let Some(source_map) = *source_map.await? else { + return Ok(Vc::cell(None)); + }; + Ok(Vc::cell(Some(source_map.with_resolved_sources(origin)))) +} diff --git a/crates/turbopack-ecmascript/Source/references/node.rs b/crates/turbopack-ecmascript/Source/references/node.rs new file mode 100644 index 0000000000000..377202640c6da --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/node.rs @@ -0,0 +1,160 @@ +use anyhow::Result; +use either::Either; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + file_source::FileSource, + raw_module::RawModule, + reference::ModuleReference, + resolve::{ + ModuleResolveResult, + RequestKey, + pattern::{Pattern, PatternMatch, read_matches}, + }, + source::Source, +}; + +#[turbo_tasks::value] +#[derive(Hash, Clone, Debug)] +pub struct PackageJsonReference { + pub package_json:Vc, +} + +#[turbo_tasks::value_impl] +impl PackageJsonReference { + #[turbo_tasks::function] + pub fn new(package_json:Vc) -> Vc { + Self::cell(PackageJsonReference { package_json }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for PackageJsonReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + ModuleResolveResult::module(Vc::upcast(RawModule::new(Vc::upcast(FileSource::new( + self.package_json, + ))))) + .cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for PackageJsonReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("package.json {}", self.package_json.to_string().await?,).into(), + )) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct DirAssetReference { + pub source:Vc>, + pub path:Vc, +} + +#[turbo_tasks::value_impl] +impl DirAssetReference { + #[turbo_tasks::function] + pub fn new(source:Vc>, path:Vc) -> Vc { + Self::cell(DirAssetReference { source, path }) + } +} + +#[turbo_tasks::function] +async fn resolve_reference_from_dir( + parent_path:Vc, + path:Vc, +) -> Result> { + let path_ref = path.await?; + let (abs_path, rel_path) = path_ref.split_could_match("/ROOT/"); + let matches = match (abs_path, rel_path) { + (Some(abs_path), Some(rel_path)) => { + Either::Right( + read_matches( + parent_path.root().resolve().await?, + "/ROOT/".into(), + true, + Pattern::new(abs_path.or_any_nested_file()), + ) + .await? + .into_iter() + .chain( + read_matches( + parent_path, + "".into(), + true, + Pattern::new(rel_path.or_any_nested_file()), + ) + .await? + .into_iter(), + ), + ) + }, + (Some(abs_path), None) => { + Either::Left( + // absolute path only + read_matches( + parent_path.root().resolve().await?, + "/ROOT/".into(), + true, + Pattern::new(abs_path.or_any_nested_file()), + ) + .await? + .into_iter(), + ) + }, + (None, Some(rel_path)) => { + Either::Left( + // relative path only + read_matches( + parent_path, + "".into(), + true, + Pattern::new(rel_path.or_any_nested_file()), + ) + .await? + .into_iter(), + ) + }, + (None, None) => return Ok(ModuleResolveResult::unresolveable().cell()), + }; + let mut affecting_sources = Vec::new(); + let mut results = Vec::new(); + for pat_match in matches { + match pat_match { + PatternMatch::File(matched_path, file) => { + let realpath = file.realpath_with_links().await?; + for &symlink in &realpath.symlinks { + affecting_sources.push(Vc::upcast(FileSource::new(symlink))); + } + results.push(( + RequestKey::new(matched_path.clone()), + Vc::upcast(RawModule::new(Vc::upcast(FileSource::new(realpath.path)))), + )); + }, + PatternMatch::Directory(..) => {}, + } + } + Ok(ModuleResolveResult::modules_with_affecting_sources(results, affecting_sources).cell()) +} + +#[turbo_tasks::value_impl] +impl ModuleReference for DirAssetReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Result> { + let parent_path = self.source.ident().path().parent(); + Ok(resolve_reference_from_dir(parent_path.resolve().await?, self.path)) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for DirAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("directory assets {}", self.path.to_string().await?,).into())) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/pattern_mapping.rs b/crates/turbopack-ecmascript/Source/references/pattern_mapping.rs new file mode 100644 index 0000000000000..61861b89f267c --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/pattern_mapping.rs @@ -0,0 +1,440 @@ +use std::{borrow::Cow, collections::HashSet}; + +use anyhow::Result; +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{ + CallExpr, + Callee, + Expr, + ExprOrSpread, + KeyValueProp, + Lit, + ObjectLit, + Prop, + PropName, + PropOrSpread, + }, + quote, + quote_expr, +}; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, Vc, debug::ValueDebugFormat, trace::TraceRawVcs}; +use turbopack_core::{ + chunk::{ChunkItemExt, ChunkableModule, ChunkingContext, ModuleId}, + issue::{IssueExt, IssueSeverity, StyledString, code_gen::CodeGenerationIssue}, + resolve::{ + ExternalType, + ModuleResolveResult, + ModuleResolveResultItem, + origin::ResolveOrigin, + parse::Request, + }, +}; + +use super::util::{request_to_string, throw_module_not_found_expr}; +use crate::{references::util::throw_module_not_found_error_expr, utils::module_id_to_lit}; + +#[derive(PartialEq, Eq, ValueDebugFormat, TraceRawVcs, Serialize, Deserialize)] +pub(crate) enum SinglePatternMapping { + /// Invalid request. + Invalid, + /// Unresolveable request. + Unresolveable(String), + /// Ignored request. + Ignored, + /// Constant request that always maps to the same module. + /// + /// ### Example + /// ```js + /// require("./module") + /// ``` + Module(ModuleId), + /// Constant request that always maps to the same module. + /// This is used for dynamic imports. + /// Module id points to a loader module. + /// + /// ### Example + /// ```js + /// import("./module") + /// ``` + ModuleLoader(ModuleId), + /// External reference with request and type + External(RcStr, ExternalType), +} + +/// A mapping from a request pattern (e.g. "./module", `./images/${name}.png`) +/// to corresponding module ids. The same pattern can map to multiple module ids +/// at runtime when using variable interpolation. +#[turbo_tasks::value] +pub(crate) enum PatternMapping { + /// Constant request that always maps to the same module. + /// + /// ### Example + /// ```js + /// require("./module") + /// ``` + Single(SinglePatternMapping), + /// Variable request that can map to different modules at runtime. + /// + /// ### Example + /// ```js + /// require(`./images/${name}.png`) + /// ``` + Map(IndexMap), +} + +#[derive(PartialOrd, Ord, Hash, Debug, Copy, Clone)] +#[turbo_tasks::value(serialization = "auto_for_input")] +pub(crate) enum ResolveType { + AsyncChunkLoader, + ChunkItem, +} + +impl SinglePatternMapping { + pub fn create_id(&self, key_expr:Cow<'_, Expr>) -> Expr { + match self { + Self::Invalid => { + quote!( + "(() => { throw new Error('could not resolve \"' + $arg + '\" into a module'); })()" as Expr, + arg: Expr = key_expr.into_owned() + ) + }, + Self::Unresolveable(request) => throw_module_not_found_expr(request), + Self::Ignored => { + quote!("undefined" as Expr) + }, + Self::Module(module_id) | Self::ModuleLoader(module_id) => module_id_to_lit(module_id), + Self::External(s, _) => Expr::Lit(Lit::Str(s.as_str().into())), + } + } + + pub fn create_require(&self, key_expr:Cow<'_, Expr>) -> Expr { + match self { + Self::Invalid => self.create_id(key_expr), + Self::Unresolveable(request) => throw_module_not_found_expr(request), + Self::Ignored => { + quote!("{}" as Expr) + }, + Self::Module(_) | Self::ModuleLoader(_) => { + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!("__turbopack_require__")), + args:vec![ExprOrSpread { + spread:None, + expr:Box::new(self.create_id(key_expr)), + }], + span:DUMMY_SP, + type_args:None, + }) + }, + Self::External(request, ExternalType::CommonJs) => { + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!("__turbopack_external_require__")), + args:vec![ExprOrSpread { spread:None, expr:request.as_str().into() }], + span:DUMMY_SP, + type_args:None, + }) + }, + Self::External(request, ty) => { + throw_module_not_found_error_expr( + request, + &format!("Unsupported external type {:?} for commonjs reference", ty), + ) + }, + } + } + + pub fn create_import(&self, key_expr:Cow<'_, Expr>, import_externals:bool) -> Expr { + match self { + Self::Invalid => { + let error = quote_expr!( + "() => { throw new Error('could not resolve \"' + $arg + '\" into a module'); }", + arg: Expr = key_expr.into_owned() + ); + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!("Promise.resolve().then")), + args:vec![ExprOrSpread { spread:None, expr:error }], + span:DUMMY_SP, + type_args:None, + }) + }, + Self::Unresolveable(_) => self.create_id(key_expr), + Self::External(_, ExternalType::EcmaScriptModule) => { + if import_externals { + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!("__turbopack_external_import__")), + args:vec![ExprOrSpread { + spread:None, + expr:Box::new(key_expr.into_owned()), + }], + span:DUMMY_SP, + type_args:None, + }) + } else { + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!("Promise.resolve().then")), + args:vec![ExprOrSpread { + spread:None, + expr:quote_expr!( + "() => __turbopack_external_require__($arg, true)", + arg: Expr = key_expr.into_owned() + ), + }], + span:DUMMY_SP, + type_args:None, + }) + } + }, + Self::External(_, ExternalType::CommonJs | ExternalType::Url) => { + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!("Promise.resolve().then")), + args:vec![ExprOrSpread { + spread:None, + expr:quote_expr!( + "() => __turbopack_external_require__($arg, true)", + arg: Expr = key_expr.into_owned() + ), + }], + span:DUMMY_SP, + type_args:None, + }) + }, + #[allow(unreachable_patterns)] + Self::External(request, ty) => { + throw_module_not_found_error_expr( + request, + &format!("Unsupported external type {:?} for dynamic import reference", ty), + ) + }, + Self::ModuleLoader(module_id) => { + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!( + "__turbopack_require__($arg)", + arg: Expr = module_id_to_lit(module_id) + )), + args:vec![ExprOrSpread { + spread:None, + expr:quote_expr!("__turbopack_import__"), + }], + span:DUMMY_SP, + type_args:None, + }) + }, + Self::Ignored => { + quote!("Promise.resolve({})" as Expr) + }, + Self::Module(_) => { + Expr::Call(CallExpr { + callee:Callee::Expr(quote_expr!("Promise.resolve().then")), + args:vec![ExprOrSpread { + spread:None, + expr:quote_expr!( + "() => __turbopack_import__($arg)", + arg: Expr = self.create_id(key_expr) + ), + }], + span:DUMMY_SP, + type_args:None, + }) + }, + } + } +} + +enum ImportMode { + Require, + Import { import_externals:bool }, +} + +fn create_context_map( + map:&IndexMap, + key_expr:&Expr, + import_mode:ImportMode, +) -> Expr { + let props = map + .iter() + .map(|(k, v)| { + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Str(k.as_str().into()), + value: quote_expr!( + "{ id: () => $id, module: () => $module }", + id: Expr = v.create_id(Cow::Borrowed(key_expr)), + module: Expr = match import_mode { + ImportMode::Require => v.create_require(Cow::Borrowed(key_expr)), + ImportMode::Import { import_externals } => v.create_import(Cow::Borrowed(key_expr), import_externals), + }, + ), + }))) + }) + .collect(); + + Expr::Object(ObjectLit { span:DUMMY_SP, props }) +} + +impl PatternMapping { + pub fn create_id(&self, key_expr:Expr) -> Expr { + match self { + PatternMapping::Single(pm) => pm.create_id(Cow::Owned(key_expr)), + PatternMapping::Map(map) => { + let map = create_context_map(map, &key_expr, ImportMode::Require); + + quote!("__turbopack_module_context__($map).resolve($key)" as Expr, + map: Expr = map, + key: Expr = key_expr + ) + }, + } + } + + pub fn create_require(&self, key_expr:Expr) -> Expr { + match self { + PatternMapping::Single(pm) => pm.create_require(Cow::Owned(key_expr)), + PatternMapping::Map(map) => { + let map = create_context_map(map, &key_expr, ImportMode::Require); + + quote!("__turbopack_module_context__($map)($key)" as Expr, + map: Expr = map, + key: Expr = key_expr + ) + }, + } + } + + pub fn create_import(&self, key_expr:Expr, import_externals:bool) -> Expr { + match self { + PatternMapping::Single(pm) => pm.create_import(Cow::Owned(key_expr), import_externals), + PatternMapping::Map(map) => { + let map = + create_context_map(map, &key_expr, ImportMode::Import { import_externals }); + + quote!("__turbopack_module_context__($map).import($key)" as Expr, + map: Expr = map, + key: Expr = key_expr + ) + }, + } + } +} + +async fn to_single_pattern_mapping( + origin:Vc>, + chunking_context:Vc>, + resolve_item:&ModuleResolveResultItem, + resolve_type:ResolveType, +) -> Result { + let module = match resolve_item { + ModuleResolveResultItem::Module(module) => *module, + ModuleResolveResultItem::External(s, ty) => { + return Ok(SinglePatternMapping::External(s.clone(), *ty)); + }, + ModuleResolveResultItem::Ignore => return Ok(SinglePatternMapping::Ignored), + _ => { + // TODO implement mapping + CodeGenerationIssue { + severity:IssueSeverity::Bug.into(), + title:StyledString::Text( + "pattern mapping is not implemented for this result".into(), + ) + .cell(), + message:StyledString::Text( + format!( + "the reference resolves to a non-trivial result, which is not supported \ + yet: {:?}", + resolve_item + ) + .into(), + ) + .cell(), + path:origin.origin_path(), + } + .cell() + .emit(); + return Ok(SinglePatternMapping::Invalid); + }, + }; + if let Some(chunkable) = Vc::try_resolve_downcast::>(module).await? { + match resolve_type { + ResolveType::AsyncChunkLoader => { + let loader_id = chunking_context.async_loader_chunk_item_id(chunkable); + return Ok(SinglePatternMapping::ModuleLoader(loader_id.await?.clone_value())); + }, + ResolveType::ChunkItem => { + let chunk_item = chunkable.as_chunk_item(chunking_context); + return Ok(SinglePatternMapping::Module(chunk_item.id().await?.clone_value())); + }, + } + } + CodeGenerationIssue { + severity:IssueSeverity::Bug.into(), + title:StyledString::Text("non-ecmascript placeable asset".into()).cell(), + message:StyledString::Text( + "asset is not placeable in ESM chunks, so it doesn't have a module id".into(), + ) + .cell(), + path:origin.origin_path(), + } + .cell() + .emit(); + Ok(SinglePatternMapping::Invalid) +} + +#[turbo_tasks::value_impl] +impl PatternMapping { + /// Resolves a request into a pattern mapping. + // NOTE(alexkirsz) I would rather have used `resolve` here but it's already reserved by the Vc + // impl. + #[turbo_tasks::function] + pub async fn resolve_request( + request:Vc, + origin:Vc>, + chunking_context:Vc>, + resolve_result:Vc, + resolve_type:Value, + ) -> Result> { + let resolve_type = resolve_type.into_value(); + let result = resolve_result.await?; + match result.primary.len() { + 0 => { + Ok(PatternMapping::Single(SinglePatternMapping::Unresolveable( + request_to_string(request).await?.to_string(), + )) + .cell()) + }, + 1 => { + let resolve_item = result.primary.first().unwrap().1; + let single_pattern_mapping = + to_single_pattern_mapping(origin, chunking_context, resolve_item, resolve_type) + .await?; + Ok(PatternMapping::Single(single_pattern_mapping).cell()) + }, + _ => { + let mut set = HashSet::new(); + let map = result + .primary + .iter() + .filter_map(|(k, v)| { + let request = k.request.as_ref()?; + set.insert(request).then(|| (request.to_string(), v)) + }) + .map(|(k, v)| { + async move { + let single_pattern_mapping = to_single_pattern_mapping( + origin, + chunking_context, + v, + resolve_type, + ) + .await?; + Ok((k, single_pattern_mapping)) + } + }) + .try_join() + .await? + .into_iter() + .collect(); + Ok(PatternMapping::Map(map).cell()) + }, + } + } +} diff --git a/crates/turbopack-ecmascript/Source/references/raw.rs b/crates/turbopack-ecmascript/Source/references/raw.rs new file mode 100644 index 0000000000000..645c6a3585730 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/raw.rs @@ -0,0 +1,40 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + reference::ModuleReference, + resolve::{ModuleResolveResult, pattern::Pattern, resolve_raw}, + source::Source, +}; + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct FileSourceReference { + pub source:Vc>, + pub path:Vc, +} + +#[turbo_tasks::value_impl] +impl FileSourceReference { + #[turbo_tasks::function] + pub fn new(source:Vc>, path:Vc) -> Vc { + Self::cell(FileSourceReference { source, path }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for FileSourceReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + let context_dir = self.source.ident().path().parent(); + + resolve_raw(context_dir, self.path, false).as_raw_module_result() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for FileSourceReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("raw asset {}", self.path.to_string().await?,).into())) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/require_context.rs b/crates/turbopack-ecmascript/Source/references/require_context.rs new file mode 100644 index 0000000000000..aee2e9e7688d2 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/require_context.rs @@ -0,0 +1,499 @@ +use std::{borrow::Cow, collections::VecDeque, sync::Arc}; + +use anyhow::{Result, bail}; +use indexmap::IndexMap; +use swc_core::{ + common::DUMMY_SP, + ecma::{ + ast::{ + Expr, + ExprStmt, + KeyValueProp, + Lit, + ModuleItem, + ObjectLit, + Prop, + PropName, + PropOrSpread, + Stmt, + {self}, + }, + codegen::{Emitter, text_writer::JsWriter}, + }, + quote, + quote_expr, +}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc, primitives::Regex}; +use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemPath}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ + ChunkItem, + ChunkItemExt, + ChunkType, + ChunkableModule, + ChunkableModuleReference, + ChunkingContext, + }, + ident::AssetIdent, + issue::{IssueSeverity, IssueSource}, + module::Module, + reference::{ModuleReference, ModuleReferences}, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request}, + source::Source, +}; +use turbopack_resolve::ecmascript::{cjs_resolve, try_to_severity}; + +use crate::{ + CodeGenerateable, + EcmascriptChunkPlaceable, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkType, + EcmascriptExports, + }, + code_gen::CodeGeneration, + create_visitor, + references::{ + AstPath, + pattern_mapping::{PatternMapping, ResolveType}, + }, + utils::module_id_to_lit, +}; + +#[turbo_tasks::value] +#[derive(Debug)] +pub(crate) enum DirListEntry { + File(Vc), + Dir(Vc), +} + +#[turbo_tasks::value(transparent)] +pub(crate) struct DirList(IndexMap); + +#[turbo_tasks::value_impl] +impl DirList { + #[turbo_tasks::function] + pub(crate) fn read(dir:Vc, recursive:bool, filter:Vc) -> Vc { + Self::read_internal(dir, dir, recursive, filter) + } + + #[turbo_tasks::function] + pub(crate) async fn read_internal( + root:Vc, + dir:Vc, + recursive:bool, + filter:Vc, + ) -> Result> { + let root_val = &*dir.await?; + let regex = &*filter.await?; + + let mut list = IndexMap::new(); + + let dir_content = dir.read_dir().await?; + let entries = match &*dir_content { + DirectoryContent::Entries(entries) => Some(entries), + DirectoryContent::NotFound => None, + }; + + for (_, entry) in entries.iter().flat_map(|m| m.iter()) { + match entry { + DirectoryEntry::File(path) => { + if let Some(relative_path) = root_val.get_relative_path_to(&*path.await?) { + if regex.is_match(&relative_path) { + list.insert(relative_path, DirListEntry::File(*path)); + } + } + }, + DirectoryEntry::Directory(path) if recursive => { + if let Some(relative_path) = root_val.get_relative_path_to(&*path.await?) { + list.insert( + relative_path, + DirListEntry::Dir(DirList::read_internal( + root, *path, recursive, filter, + )), + ); + } + }, + // ignore everything else + _ => {}, + } + } + + list.sort_keys(); + + Ok(Vc::cell(list)) + } + + #[turbo_tasks::function] + async fn flatten(self: Vc) -> Result> { + let this = self.await?; + + let mut queue = VecDeque::from([this]); + + let mut list = IndexMap::new(); + + while let Some(dir) = queue.pop_front() { + for (k, entry) in &*dir { + match entry { + DirListEntry::File(path) => { + list.insert(k.clone(), *path); + }, + DirListEntry::Dir(d) => { + queue.push_back(d.await?); + }, + } + } + } + + Ok(Vc::cell(list)) + } +} + +#[turbo_tasks::value(transparent)] +pub(crate) struct FlatDirList(IndexMap>); + +#[turbo_tasks::value_impl] +impl FlatDirList { + #[turbo_tasks::function] + pub(crate) fn read(dir:Vc, recursive:bool, filter:Vc) -> Vc { + DirList::read(dir, recursive, filter).flatten() + } +} + +#[turbo_tasks::value] +#[derive(Debug)] +pub struct RequireContextMapEntry { + pub origin_relative:RcStr, + pub request:Vc, + pub result:Vc, +} + +/// The resolved context map for a `require.context(..)` call. +#[turbo_tasks::value(transparent)] +pub struct RequireContextMap(IndexMap); + +#[turbo_tasks::value_impl] +impl RequireContextMap { + #[turbo_tasks::function] + pub(crate) async fn generate( + origin:Vc>, + dir:Vc, + recursive:bool, + filter:Vc, + issue_source:Option>, + issue_severity:Vc, + ) -> Result> { + let origin_path = &*origin.origin_path().parent().await?; + + let list = &*FlatDirList::read(dir, recursive, filter).await?; + + let mut map = IndexMap::new(); + + for (context_relative, path) in list { + if let Some(origin_relative) = origin_path.get_relative_path_to(&*path.await?) { + let request = Request::parse(Value::new(origin_relative.clone().into())); + let result = cjs_resolve(origin, request, issue_source, issue_severity); + + map.insert( + context_relative.clone(), + RequireContextMapEntry { origin_relative, request, result }, + ); + } else { + bail!("invariant error: this was already checked in `list_dir`"); + } + } + + Ok(Vc::cell(map)) + } +} + +/// A reference for `require.context()`, will replace it with an inlined map +/// wrapped in `__turbopack_module_context__`; +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct RequireContextAssetReference { + pub inner:Vc, + pub dir:RcStr, + pub include_subdirs:bool, + + pub path:Vc, + pub issue_source:Option>, + pub in_try:bool, +} + +#[turbo_tasks::value_impl] +impl RequireContextAssetReference { + #[turbo_tasks::function] + pub fn new( + source:Vc>, + origin:Vc>, + dir:RcStr, + include_subdirs:bool, + filter:Vc, + path:Vc, + issue_source:Option>, + in_try:bool, + ) -> Vc { + let map = RequireContextMap::generate( + origin, + origin.origin_path().parent().join(dir.clone()), + include_subdirs, + filter, + issue_source, + try_to_severity(in_try), + ); + let inner = + RequireContextAsset { source, origin, map, dir:dir.clone(), include_subdirs }.cell(); + + Self::cell(RequireContextAssetReference { + inner, + dir, + include_subdirs, + path, + issue_source, + in_try, + }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for RequireContextAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + ModuleResolveResult::module(Vc::upcast(self.inner)).cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for RequireContextAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!( + "require.context {}/{}", + self.dir, + if self.include_subdirs { "**" } else { "*" }, + ) + .into(), + )) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for RequireContextAssetReference {} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for RequireContextAssetReference { + #[turbo_tasks::function] + async fn code_generation( + &self, + chunking_context:Vc>, + ) -> Result> { + let chunk_item = self.inner.as_chunk_item(Vc::upcast(chunking_context)); + let module_id = chunk_item.id().await?.clone_value(); + + let mut visitors = Vec::new(); + + let path = &self.path.await?; + visitors.push(create_visitor!(path, visit_mut_expr(expr: &mut Expr) { + if let Expr::Call(_) = expr { + *expr = quote!( + "__turbopack_module_context__(__turbopack_require__($id))" as Expr, + id: Expr = module_id_to_lit(&module_id) + ); + } + })); + + Ok(CodeGeneration { visitors }.into()) + } +} + +#[turbo_tasks::value(transparent)] +pub struct ResolvedModuleReference(Vc); + +#[turbo_tasks::value_impl] +impl ModuleReference for ResolvedModuleReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { self.0 } +} + +#[turbo_tasks::value_impl] +impl ValueToString for ResolvedModuleReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { Ok(Vc::cell("resolved reference".into())) } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for ResolvedModuleReference {} + +#[turbo_tasks::value] +pub struct RequireContextAsset { + source:Vc>, + + origin:Vc>, + map:Vc, + + dir:RcStr, + include_subdirs:bool, +} + +#[turbo_tasks::function] +fn modifier(dir:RcStr, include_subdirs:bool) -> Vc { + Vc::cell( + format!("require.context {}/{}", dir, if include_subdirs { "**" } else { "*" },).into(), + ) +} + +#[turbo_tasks::value_impl] +impl Module for RequireContextAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + self.source + .ident() + .with_modifier(modifier(self.dir.clone(), self.include_subdirs)) + } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let map = &*self.map.await?; + + Ok(Vc::cell( + map.iter() + .map(|(_, entry)| Vc::upcast(Vc::::cell(entry.result))) + .collect(), + )) + } +} + +#[turbo_tasks::value_impl] +impl Asset for RequireContextAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { unimplemented!() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for RequireContextAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + let this = self.await?; + Ok(Vc::upcast( + RequireContextChunkItem { + chunking_context, + inner:self, + + origin:this.origin, + map:this.map, + } + .cell(), + )) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for RequireContextAsset { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } +} + +#[turbo_tasks::value] +pub struct RequireContextChunkItem { + chunking_context:Vc>, + inner:Vc, + + origin:Vc>, + map:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for RequireContextChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let map = &*self.map.await?; + + let mut context_map = ObjectLit { span:DUMMY_SP, props:vec![] }; + + for (key, entry) in map { + let pm = PatternMapping::resolve_request( + entry.request, + self.origin, + Vc::upcast(self.chunking_context), + entry.result, + Value::new(ResolveType::ChunkItem), + ) + .await?; + + let PatternMapping::Single(pm) = &*pm else { + continue; + }; + + let key_expr = Expr::Lit(Lit::Str(entry.origin_relative.as_str().into())); + + let prop = KeyValueProp { + key:PropName::Str(key.as_str().into()), + value:quote_expr!( + "{ id: () => $id, module: () => $module }", + id: Expr = + pm.create_id(Cow::Borrowed(&key_expr)), + module: Expr = + pm.create_require(Cow::Borrowed(&key_expr)), + ), + }; + + context_map.props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(prop)))); + } + + let expr = quote_expr!( + "__turbopack_export_value__($obj);", + obj: Expr = Expr::Object(context_map), + ); + + let module = ast::Module { + span:DUMMY_SP, + body:vec![ModuleItem::Stmt(Stmt::Expr(ExprStmt { span:DUMMY_SP, expr }))], + shebang:None, + }; + + let source_map:Arc = Default::default(); + let mut bytes:Vec = vec![]; + let mut emitter = Emitter { + cfg:swc_core::ecma::codegen::Config::default(), + cm:source_map.clone(), + comments:None, + wr:JsWriter::new(source_map, "\n", &mut bytes, None), + }; + + emitter.emit_module(&module)?; + + Ok(EcmascriptChunkItemContent { inner_code:bytes.into(), ..Default::default() }.cell()) + } +} + +#[turbo_tasks::value_impl] +impl ChunkItem for RequireContextChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.inner.ident() } + + #[turbo_tasks::function] + fn references(&self) -> Vc { self.inner.references() } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.inner) } +} diff --git a/crates/turbopack-ecmascript/Source/references/type_issue.rs b/crates/turbopack-ecmascript/Source/references/type_issue.rs new file mode 100644 index 0000000000000..7243c8c4bc979 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/type_issue.rs @@ -0,0 +1,86 @@ +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueSeverity, IssueStage, OptionStyledString, StyledString}; + +use crate::SpecifiedModuleType; + +#[turbo_tasks::value(shared)] +pub struct SpecifiedModuleTypeIssue { + pub path:Vc, + pub specified_type:SpecifiedModuleType, +} + +#[turbo_tasks::value_impl] +impl Issue for SpecifiedModuleTypeIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.path } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text(match self.specified_type { + SpecifiedModuleType::CommonJs => { + "Specified module format (CommonJs) is not matching the module format of the \ + source code (EcmaScript Modules)" + .into() + }, + SpecifiedModuleType::EcmaScript => { + "Specified module format (EcmaScript Modules) is not matching the module format of \ + the source code (CommonJs)" + .into() + }, + SpecifiedModuleType::Automatic => { + "Specified module format is not matching the module format of the source code" + .into() + }, + }) + .cell() + } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some( + StyledString::Text(match self.specified_type { + SpecifiedModuleType::CommonJs => { + "The CommonJs module format was specified in the package.json that is \ + affecting this source file or by using an special extension, but Ecmascript \ + import/export syntax is used in the source code.\nThe module was \ + automatically converted to an EcmaScript module, but that is in conflict with \ + the specified module format. Either change the \"type\" field in the \ + package.json or replace EcmaScript import/export syntax with CommonJs syntas \ + in the source file.\nIn some cases EcmaScript import/export syntax is added \ + by an transform and isn't actually part of the source code. In these cases \ + revisit transformation options to inject the correct syntax." + .into() + }, + SpecifiedModuleType::EcmaScript => { + "The EcmaScript module format was specified in the package.json that is \ + affecting this source file or by using an special extension, but it looks \ + like that CommonJs syntax is used in the source code.\nExports made by \ + CommonJs syntax will lead to a runtime error, since the module is in \ + EcmaScript mode. Either change the \"type\" field in the package.json or \ + replace CommonJs syntax with EcmaScript import/export syntax in the source \ + file." + .into() + }, + SpecifiedModuleType::Automatic => { + "The module format specified in the package.json file is not matching the \ + module format of the source code." + .into() + }, + }) + .cell(), + )) + } + + #[turbo_tasks::function] + fn severity(&self) -> Vc { + match self.specified_type { + SpecifiedModuleType::CommonJs => IssueSeverity::Error.cell(), + SpecifiedModuleType::EcmaScript => IssueSeverity::Warning.cell(), + SpecifiedModuleType::Automatic => IssueSeverity::Hint.cell(), + } + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Analysis.into() } +} diff --git a/crates/turbopack-ecmascript/Source/references/typescript.rs b/crates/turbopack-ecmascript/Source/references/typescript.rs new file mode 100644 index 0000000000000..d1a1943e7789d --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/typescript.rs @@ -0,0 +1,136 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + context::AssetContext, + file_source::FileSource, + reference::ModuleReference, + reference_type::{ReferenceType, TypeScriptReferenceSubType}, + resolve::{ModuleResolveResult, origin::ResolveOrigin, parse::Request}, +}; +use turbopack_resolve::typescript::type_resolve; + +use crate::typescript::TsConfigModuleAsset; + +#[turbo_tasks::value] +#[derive(Hash, Clone, Debug)] +pub struct TsConfigReference { + pub tsconfig:Vc, + pub origin:Vc>, +} + +#[turbo_tasks::value_impl] +impl TsConfigReference { + #[turbo_tasks::function] + pub fn new(origin:Vc>, tsconfig:Vc) -> Vc { + Self::cell(TsConfigReference { tsconfig, origin }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for TsConfigReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + ModuleResolveResult::module(Vc::upcast(TsConfigModuleAsset::new( + self.origin, + Vc::upcast(FileSource::new(self.tsconfig)), + ))) + .into() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for TsConfigReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("tsconfig {}", self.tsconfig.to_string().await?,).into())) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct TsReferencePathAssetReference { + pub origin:Vc>, + pub path:RcStr, +} + +#[turbo_tasks::value_impl] +impl TsReferencePathAssetReference { + #[turbo_tasks::function] + pub fn new(origin:Vc>, path:RcStr) -> Vc { + Self::cell(TsReferencePathAssetReference { origin, path }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for TsReferencePathAssetReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Result> { + Ok( + if let Some(path) = + &*self.origin.origin_path().parent().try_join(self.path.clone()).await? + { + let module = self + .origin + .asset_context() + .process( + Vc::upcast(FileSource::new(*path)), + Value::new(ReferenceType::TypeScript( + TypeScriptReferenceSubType::Undefined, + )), + ) + .module(); + ModuleResolveResult::module(module).cell() + } else { + ModuleResolveResult::unresolveable().cell() + }, + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for TsReferencePathAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("typescript reference path comment {}", self.path,).into())) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct TsReferenceTypeAssetReference { + pub origin:Vc>, + pub module:RcStr, +} + +#[turbo_tasks::value_impl] +impl TsReferenceTypeAssetReference { + #[turbo_tasks::function] + pub fn new(origin:Vc>, module:RcStr) -> Vc { + Self::cell(TsReferenceTypeAssetReference { origin, module }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for TsReferenceTypeAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + type_resolve( + self.origin, + Request::module( + self.module.clone(), + Value::new(RcStr::default().into()), + Vc::::default(), + Vc::::default(), + ), + ) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for TsReferenceTypeAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("typescript reference type comment {}", self.module,).into())) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/unreachable.rs b/crates/turbopack-ecmascript/Source/references/unreachable.rs new file mode 100644 index 0000000000000..73dd95f5da626 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/unreachable.rs @@ -0,0 +1,46 @@ +use anyhow::Result; +use swc_core::quote; +use turbo_tasks::Vc; +use turbopack_core::chunk::ChunkingContext; + +use super::AstPath; +use crate::{ + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, +}; + +#[turbo_tasks::value] +pub struct Unreachable { + path:Vc, +} + +#[turbo_tasks::value_impl] +impl Unreachable { + #[turbo_tasks::function] + pub fn new(path:Vc) -> Vc { Self::cell(Unreachable { path }) } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for Unreachable { + #[turbo_tasks::function] + async fn code_generation( + &self, + _context:Vc>, + ) -> Result> { + let path = self.path.await?; + let visitors = [ + // Unreachable might be used on Stmt or Expr + create_visitor!(exact path, visit_mut_expr(expr: &mut Expr) { + *expr = quote!("(\"TURBOPACK unreachable\", undefined)" as Expr); + }), + create_visitor!(exact path, visit_mut_stmt(stmt: &mut Stmt) { + // TODO(WEB-553) walk ast to find all `var` declarations and keep them + // since they hoist out of the scope + *stmt = quote!("{\"TURBOPACK unreachable\";}" as Stmt); + }), + ] + .into(); + + Ok(CodeGeneration { visitors }.cell()) + } +} diff --git a/crates/turbopack-ecmascript/Source/references/util.rs b/crates/turbopack-ecmascript/Source/references/util.rs new file mode 100644 index 0000000000000..8896a8c43173e --- /dev/null +++ b/crates/turbopack-ecmascript/Source/references/util.rs @@ -0,0 +1,35 @@ +use anyhow::Result; +use swc_core::{ecma::ast::Expr, quote}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::resolve::parse::Request; + +/// Creates a IIFE expression that throws a "Cannot find module" error for the +/// given request string +pub fn throw_module_not_found_expr(request:&str) -> Expr { + let message = format!("Cannot find module '{request}'"); + quote!( + "(() => { const e = new Error($message); e.code = 'MODULE_NOT_FOUND'; throw e; })()" + as Expr, + message: Expr = message.into() + ) +} + +/// Creates a IIFE expression that throws a "Cannot find module" error for the +/// given request string +pub fn throw_module_not_found_error_expr(request:&str, message:&str) -> Expr { + let message = format!("Cannot find module '{request}': {message}"); + quote!( + "(() => { const e = new Error($message); e.code = 'MODULE_NOT_FOUND'; throw e; })()" + as Expr, + message: Expr = message.into() + ) +} + +#[turbo_tasks::function] +pub async fn request_to_string(request:Vc) -> Result> { + Ok(Vc::cell(request + .await? + .request() + // TODO: Handle Request::Dynamic, Request::Alternatives + .unwrap_or_else(|| "unknown".into()))) +} diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/chunk_item.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/chunk_item.rs new file mode 100644 index 0000000000000..a5f7f61222630 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/chunk_item.rs @@ -0,0 +1,185 @@ +use std::sync::Arc; + +use anyhow::{Result, bail}; +use swc_core::{ + common::{GLOBALS, Globals, util::take::Take}, + ecma::{ + ast::Program, + codegen::{Emitter, text_writer::JsWriter}, + visit::{VisitMutWith, VisitMutWithPath}, + }, +}; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbo_tasks_fs::rope::RopeBuilder; +use turbopack_core::{ + chunk::{AsyncModuleInfo, ChunkItem, ChunkType, ChunkingContext}, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, +}; + +use super::module::EcmascriptModuleFacadeModule; +use crate::{ + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkItemOptions, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + code_gen::{CodeGenerateable, CodeGenerateableWithAsyncModuleInfo}, + path_visitor::ApplyVisitors, +}; + +/// The chunk item for [EcmascriptModuleFacadeModule]. +#[turbo_tasks::value(shared)] +pub struct EcmascriptModuleFacadeChunkItem { + pub(crate) module:Vc, + pub(crate) chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for EcmascriptModuleFacadeChunkItem { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + panic!("content() should never be called"); + } + + #[turbo_tasks::function] + async fn content_with_async_module_info( + &self, + async_module_info:Option>, + ) -> Result> { + let chunking_context = self.chunking_context; + let exports = self.module.get_exports(); + let EcmascriptExports::EsmExports(exports) = *exports.await? else { + bail!("Expected EsmExports"); + }; + + let externals = *chunking_context.environment().supports_commonjs_externals().await?; + + let async_module_options = self.module.get_async_module().module_options(async_module_info); + + let async_module = async_module_options.await?.clone_value(); + + let mut code = RopeBuilder::default(); + + let references = self.module.references(); + let references_ref = references.await?; + let mut code_gens = Vec::with_capacity(references_ref.len() + 2); + for r in references_ref.iter() { + let r = r.resolve().await?; + if let Some(code_gen) = + Vc::try_resolve_sidecast::>(r).await? + { + code_gens.push(code_gen.code_generation(chunking_context, async_module_info)); + } else if let Some(code_gen) = + Vc::try_resolve_sidecast::>(r).await? + { + code_gens.push(code_gen.code_generation(chunking_context)); + } + } + code_gens.push(self.module.async_module().code_generation( + chunking_context, + async_module_info, + references, + )); + code_gens.push(exports.code_generation(chunking_context)); + let code_gens = code_gens.into_iter().try_join().await?; + let code_gens = code_gens.iter().map(|cg| &**cg).collect::>(); + + let mut visitors = Vec::new(); + let mut root_visitors = Vec::new(); + for code_gen in code_gens { + for (path, visitor) in code_gen.visitors.iter() { + if path.is_empty() { + root_visitors.push(&**visitor); + } else { + visitors.push((path, &**visitor)); + } + } + } + + let mut program = Program::Module(swc_core::ecma::ast::Module::dummy()); + GLOBALS.set(&Globals::new(), || { + if !visitors.is_empty() { + program.visit_mut_with_path( + &mut ApplyVisitors::new(visitors), + &mut Default::default(), + ); + } + for visitor in root_visitors { + program.visit_mut_with(&mut visitor.create()); + } + + program.visit_mut_with(&mut swc_core::ecma::transforms::base::hygiene::hygiene()); + program.visit_mut_with(&mut swc_core::ecma::transforms::base::fixer::fixer(None)); + }); + + let mut bytes:Vec = vec![]; + + let source_map:Arc = Default::default(); + + let mut emitter = Emitter { + cfg:swc_core::ecma::codegen::Config::default(), + cm:source_map.clone(), + comments:None, + wr:JsWriter::new(source_map.clone(), "\n", &mut bytes, None), + }; + + emitter.emit_program(&program)?; + + code.push_bytes(&bytes); + + Ok(EcmascriptChunkItemContent { + inner_code:code.build(), + source_map:None, + options:EcmascriptChunkItemOptions { + strict:true, + externals, + async_module, + ..Default::default() + }, + ..Default::default() + } + .cell()) + } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } +} + +#[turbo_tasks::value_impl] +impl ChunkItem for EcmascriptModuleFacadeChunkItem { + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + fn asset_ident(&self) -> Result> { Ok(self.module.ident()) } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { Vc::upcast(self.chunking_context) } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } + + #[turbo_tasks::function] + async fn is_self_async(&self) -> Result> { + let module = self.module; + let async_module = module.async_module(); + let references = module.references(); + let is_self_async = async_module + .resolve() + .await? + .is_self_async(references.resolve().await?) + .resolve() + .await?; + Ok(is_self_async) + } +} diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/mod.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/mod.rs new file mode 100644 index 0000000000000..dd8dfeedf3096 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/mod.rs @@ -0,0 +1,2 @@ +pub mod chunk_item; +pub mod module; diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/module.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/module.rs new file mode 100644 index 0000000000000..451b66f25e574 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/facade/module.rs @@ -0,0 +1,283 @@ +use std::collections::BTreeMap; + +use anyhow::{Result, bail}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{File, FileContent, glob::Glob}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkableModule, ChunkingContext, EvaluatableAsset}, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, + resolve::ModulePart, +}; + +use super::chunk_item::EcmascriptModuleFacadeChunkItem; +use crate::{ + EcmascriptModuleAsset, + chunk::{EcmascriptChunkPlaceable, EcmascriptExports}, + references::{ + async_module::{AsyncModule, OptionAsyncModule}, + esm::{EsmExport, EsmExports}, + }, + side_effect_optimization::reference::EcmascriptModulePartReference, +}; + +/// A module derived from an original ecmascript module that only contains all +/// the reexports from that module and also reexports the locals from +/// [EcmascriptModuleLocalsModule]. It allows to follow +#[turbo_tasks::value] +pub struct EcmascriptModuleFacadeModule { + pub module:Vc>, + pub ty:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptModuleFacadeModule { + #[turbo_tasks::function] + pub fn new(module:Vc>, ty:Vc) -> Vc { + EcmascriptModuleFacadeModule { module, ty }.cell() + } + + #[turbo_tasks::function] + pub async fn async_module(self: Vc) -> Result> { + let (import_externals, has_top_level_await) = + if let Some(async_module) = *self.await?.module.get_async_module().await? { + (async_module.await?.import_externals, async_module.await?.has_top_level_await) + } else { + (false, false) + }; + Ok(AsyncModule { has_top_level_await, import_externals }.cell()) + } +} + +#[turbo_tasks::value_impl] +impl Module for EcmascriptModuleFacadeModule { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let inner = self.module.ident(); + + Ok(inner.with_part(self.ty)) + } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let references = match &*self.ty.await? { + ModulePart::Evaluation => { + let Some(module) = + Vc::try_resolve_downcast_type::(self.module).await? + else { + bail!( + "Expected EcmascriptModuleAsset for a EcmascriptModuleFacadeModule with \ + ModulePart::Evaluation" + ); + }; + let result = module.failsafe_analyze().await?; + let references = result.evaluation_references; + let mut references = references.await?.clone_value(); + references.push(Vc::upcast(EcmascriptModulePartReference::new_part( + self.module, + ModulePart::locals(), + ))); + references + }, + ModulePart::Exports => { + let Some(module) = + Vc::try_resolve_downcast_type::(self.module).await? + else { + bail!( + "Expected EcmascriptModuleAsset for a EcmascriptModuleFacadeModule with \ + ModulePart::Evaluation" + ); + }; + let result = module.failsafe_analyze().await?; + let references = result.reexport_references; + let mut references = references.await?.clone_value(); + references.push(Vc::upcast(EcmascriptModulePartReference::new_part( + self.module, + ModulePart::locals(), + ))); + references + }, + ModulePart::Facade => { + vec![ + Vc::upcast(EcmascriptModulePartReference::new_part( + self.module, + ModulePart::evaluation(), + )), + Vc::upcast(EcmascriptModulePartReference::new_part( + self.module, + ModulePart::exports(), + )), + ] + }, + ModulePart::RenamedNamespace { .. } => { + vec![Vc::upcast(EcmascriptModulePartReference::new(self.module))] + }, + ModulePart::RenamedExport { .. } => { + vec![Vc::upcast(EcmascriptModulePartReference::new(self.module))] + }, + _ => { + bail!("Unexpected ModulePart for EcmascriptModuleFacadeModule"); + }, + }; + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptModuleFacadeModule { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let f = File::from(""); + + Ok(AssetContent::file(FileContent::Content(f).cell())) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for EcmascriptModuleFacadeModule { + #[turbo_tasks::function] + async fn get_exports(&self) -> Result> { + let mut exports = BTreeMap::new(); + let mut star_exports = Vec::new(); + + match &*self.ty.await? { + ModulePart::Exports => { + let EcmascriptExports::EsmExports(esm_exports) = *self.module.get_exports().await? + else { + bail!( + "EcmascriptModuleFacadeModule must only be used on modules with EsmExports" + ); + }; + let esm_exports = esm_exports.await?; + for (name, export) in &esm_exports.exports { + let name = name.clone(); + match export { + EsmExport::LocalBinding(_, mutable) => { + exports.insert( + name.clone(), + EsmExport::ImportedBinding( + Vc::upcast(EcmascriptModulePartReference::new_part( + self.module, + ModulePart::locals(), + )), + name, + *mutable, + ), + ); + }, + EsmExport::ImportedNamespace(reference) => { + exports.insert(name, EsmExport::ImportedNamespace(*reference)); + }, + EsmExport::ImportedBinding(reference, imported_name, mutable) => { + exports.insert( + name, + EsmExport::ImportedBinding( + *reference, + imported_name.clone(), + *mutable, + ), + ); + }, + EsmExport::Error => { + exports.insert(name, EsmExport::Error); + }, + } + } + star_exports.extend(esm_exports.star_exports.iter().copied()); + }, + ModulePart::Facade => { + // Reexport everything from the reexports module + // (including default export if any) + let EcmascriptExports::EsmExports(esm_exports) = *self.module.get_exports().await? + else { + bail!( + "EcmascriptModuleFacadeModule must only be used on modules with EsmExports" + ); + }; + let esm_exports = esm_exports.await?; + if esm_exports.exports.keys().any(|name| name == "default") { + exports.insert( + "default".into(), + EsmExport::ImportedBinding( + Vc::upcast(EcmascriptModulePartReference::new_part( + self.module, + ModulePart::exports(), + )), + "default".into(), + false, + ), + ); + } + star_exports.push(Vc::upcast(EcmascriptModulePartReference::new_part( + self.module, + ModulePart::exports(), + ))); + }, + ModulePart::RenamedExport { original_export, export } => { + let original_export = original_export.await?; + exports.insert( + export.await?.clone_value(), + EsmExport::ImportedBinding( + Vc::upcast(EcmascriptModulePartReference::new(self.module)), + original_export.clone_value(), + false, + ), + ); + }, + ModulePart::RenamedNamespace { export } => { + exports.insert( + export.await?.clone_value(), + EsmExport::ImportedNamespace(Vc::upcast(EcmascriptModulePartReference::new( + self.module, + ))), + ); + }, + ModulePart::Evaluation => { + // no exports + }, + _ => bail!("Unexpected ModulePart for EcmascriptModuleFacadeModule"), + } + + let exports = EsmExports { exports, star_exports }.cell(); + Ok(EcmascriptExports::EsmExports(exports).cell()) + } + + #[turbo_tasks::function] + async fn is_marked_as_side_effect_free( + &self, + side_effect_free_packages:Vc, + ) -> Result> { + Ok(match *self.ty.await? { + ModulePart::Evaluation | ModulePart::Facade => { + self.module.is_marked_as_side_effect_free(side_effect_free_packages) + }, + ModulePart::Exports + | ModulePart::RenamedExport { .. } + | ModulePart::RenamedNamespace { .. } => Vc::cell(true), + _ => bail!("Unexpected ModulePart for EcmascriptModuleFacadeModule"), + }) + } + + #[turbo_tasks::function] + fn get_async_module(self: Vc) -> Vc { + Vc::cell(Some(self.async_module())) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for EcmascriptModuleFacadeModule { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast( + EcmascriptModuleFacadeChunkItem { module:self, chunking_context }.cell(), + )) + } +} + +#[turbo_tasks::value_impl] +impl EvaluatableAsset for EcmascriptModuleFacadeModule {} diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/chunk_item.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/chunk_item.rs new file mode 100644 index 0000000000000..a09234f69ee43 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/chunk_item.rs @@ -0,0 +1,106 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbopack_core::{ + chunk::{AsyncModuleInfo, ChunkItem, ChunkType, ChunkingContext}, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, +}; + +use super::module::EcmascriptModuleLocalsModule; +use crate::{ + EcmascriptModuleContent, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + }, +}; + +/// The chunk item for [EcmascriptModuleLocalsModule]. +#[turbo_tasks::value(shared)] +pub struct EcmascriptModuleLocalsChunkItem { + pub(super) module:Vc, + pub(super) chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + panic!("content() should never be called"); + } + + #[turbo_tasks::function] + async fn content_with_async_module_info( + &self, + async_module_info:Option>, + ) -> Result> { + let module = self.module.await?; + let chunking_context = self.chunking_context; + let exports = self.module.get_exports(); + let original_module = module.module; + let parsed = original_module.parse().resolve().await?; + + let analyze_result = original_module.analyze().await?; + let async_module_options = analyze_result.async_module.module_options(async_module_info); + + let module_type_result = *original_module.determine_module_type().await?; + + let content = EcmascriptModuleContent::new( + parsed, + self.module.ident(), + module_type_result.module_type, + chunking_context, + analyze_result.local_references, + analyze_result.code_generation, + analyze_result.async_module, + analyze_result.source_map, + exports, + async_module_info, + ); + + Ok(EcmascriptChunkItemContent::new( + content, + self.chunking_context, + original_module.await?.options, + async_module_options, + )) + } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } +} + +#[turbo_tasks::value_impl] +impl ChunkItem for EcmascriptModuleLocalsChunkItem { + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + fn asset_ident(&self) -> Result> { Ok(self.module.ident()) } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { Vc::upcast(self.chunking_context) } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } + + #[turbo_tasks::function] + async fn is_self_async(&self) -> Result> { + let module = self.module.await?; + let analyze = module.module.analyze().await?; + if let Some(async_module) = *analyze.async_module.await? { + let is_self_async = async_module.is_self_async(analyze.local_references); + Ok(is_self_async) + } else { + Ok(Vc::cell(false)) + } + } +} diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/mod.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/mod.rs new file mode 100644 index 0000000000000..dd8dfeedf3096 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/mod.rs @@ -0,0 +1,2 @@ +pub mod chunk_item; +pub mod module; diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/module.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/module.rs new file mode 100644 index 0000000000000..4c9bb3dfbfa30 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/locals/module.rs @@ -0,0 +1,114 @@ +use std::collections::BTreeMap; + +use anyhow::{Result, bail}; +use turbo_tasks::Vc; +use turbo_tasks_fs::glob::Glob; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkableModule, ChunkingContext}, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, + resolve::ModulePart, +}; + +use super::chunk_item::EcmascriptModuleLocalsChunkItem; +use crate::{ + EcmascriptModuleAsset, + chunk::{EcmascriptChunkPlaceable, EcmascriptExports}, + references::{ + async_module::OptionAsyncModule, + esm::{EsmExport, EsmExports}, + }, +}; + +/// A module derived from an original ecmascript module that only contains the +/// local declarations, but excludes all reexports. These reexports are exposed +/// from [EcmascriptModuleFacadeModule] instead. +#[turbo_tasks::value] +pub struct EcmascriptModuleLocalsModule { + pub module:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptModuleLocalsModule { + #[turbo_tasks::function] + pub fn new(module:Vc) -> Vc { + EcmascriptModuleLocalsModule { module }.cell() + } +} + +#[turbo_tasks::value_impl] +impl Module for EcmascriptModuleLocalsModule { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let inner = self.module.ident(); + + Ok(inner.with_part(ModulePart::locals())) + } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let result = self.module.failsafe_analyze().await?; + Ok(result.local_references) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptModuleLocalsModule { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.module.content() } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for EcmascriptModuleLocalsModule { + #[turbo_tasks::function] + async fn get_exports(&self) -> Result> { + let EcmascriptExports::EsmExports(exports) = *self.module.get_exports().await? else { + bail!("EcmascriptModuleLocalsModule must only be used on modules with EsmExports"); + }; + let esm_exports = exports.await?; + let mut exports = BTreeMap::new(); + + for (name, export) in &esm_exports.exports { + match export { + EsmExport::ImportedBinding(..) | EsmExport::ImportedNamespace(..) => { + // not included in locals module + }, + EsmExport::LocalBinding(local_name, mutable) => { + exports.insert( + name.clone(), + EsmExport::LocalBinding(local_name.clone(), *mutable), + ); + }, + EsmExport::Error => { + exports.insert(name.clone(), EsmExport::Error); + }, + } + } + + let exports = EsmExports { exports, star_exports:vec![] }.cell(); + Ok(EcmascriptExports::EsmExports(exports).cell()) + } + + #[turbo_tasks::function] + fn is_marked_as_side_effect_free(&self, side_effect_free_packages:Vc) -> Vc { + self.module.is_marked_as_side_effect_free(side_effect_free_packages) + } + + #[turbo_tasks::function] + fn get_async_module(&self) -> Vc { self.module.get_async_module() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for EcmascriptModuleLocalsModule { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast( + EcmascriptModuleLocalsChunkItem { module:self, chunking_context }.cell(), + )) + } +} diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/mod.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/mod.rs new file mode 100644 index 0000000000000..3be31d481dc0b --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/mod.rs @@ -0,0 +1,3 @@ +pub mod facade; +pub mod locals; +pub(crate) mod reference; diff --git a/crates/turbopack-ecmascript/Source/side_effect_optimization/reference.rs b/crates/turbopack-ecmascript/Source/side_effect_optimization/reference.rs new file mode 100644 index 0000000000000..0b07c733b1738 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/side_effect_optimization/reference.rs @@ -0,0 +1,141 @@ +use anyhow::{Context, Result, bail}; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{Expr, Ident}, + quote, +}; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + chunk::{ + ChunkItemExt, + ChunkableModule, + ChunkableModuleReference, + ChunkingContext, + ChunkingType, + ChunkingTypeOption, + ModuleId, + }, + reference::ModuleReference, + resolve::{ModulePart, ModuleResolveResult}, +}; + +use super::{ + facade::module::EcmascriptModuleFacadeModule, + locals::module::EcmascriptModuleLocalsModule, +}; +use crate::{ + chunk::EcmascriptChunkPlaceable, + code_gen::{CodeGenerateable, CodeGeneration}, + create_visitor, + references::esm::base::{ReferencedAsset, insert_hoisted_stmt}, +}; + +/// A reference to the [EcmascriptModuleLocalsModule] variant of an original +/// module. +#[turbo_tasks::value] +pub struct EcmascriptModulePartReference { + pub module:Vc>, + pub part:Option>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptModulePartReference { + #[turbo_tasks::function] + pub fn new_part(module:Vc>, part:Vc) -> Vc { + EcmascriptModulePartReference { module, part:Some(part) }.cell() + } + + #[turbo_tasks::function] + pub fn new(module:Vc>) -> Vc { + EcmascriptModulePartReference { module, part:None }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptModulePartReference { + #[turbo_tasks::function] + fn to_string(&self) -> Vc { + self.part.map_or_else(|| Vc::cell("module".into()), |part| part.to_string()) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for EcmascriptModulePartReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Result> { + let module = if let Some(part) = self.part { + match *part.await? { + ModulePart::Locals => { + let Some(module) = Vc::try_resolve_downcast_type(self.module).await? else { + bail!( + "Expected EcmascriptModuleAsset for a EcmascriptModulePartReference \ + with ModulePart::Locals" + ); + }; + Vc::upcast(EcmascriptModuleLocalsModule::new(module)) + }, + ModulePart::Exports + | ModulePart::Evaluation + | ModulePart::Facade + | ModulePart::RenamedExport { .. } + | ModulePart::RenamedNamespace { .. } => { + Vc::upcast(EcmascriptModuleFacadeModule::new(self.module, part)) + }, + ModulePart::Export(..) | ModulePart::Internal(..) => { + bail!( + "Unexpected ModulePart {} for EcmascriptModulePartReference", + part.to_string().await? + ); + }, + } + } else { + Vc::upcast(self.module) + }; + Ok(ModuleResolveResult::module(module).cell()) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModuleReference for EcmascriptModulePartReference { + #[turbo_tasks::function] + fn chunking_type(self: Vc) -> Vc { + Vc::cell(Some(ChunkingType::ParallelInheritAsync)) + } +} + +#[turbo_tasks::value_impl] +impl CodeGenerateable for EcmascriptModulePartReference { + #[turbo_tasks::function] + async fn code_generation( + self: Vc, + chunking_context:Vc>, + ) -> Result> { + let mut visitors = Vec::new(); + + let referenced_asset = ReferencedAsset::from_resolve_result(self.resolve_reference()); + let referenced_asset = referenced_asset.await?; + let ident = referenced_asset + .get_ident() + .await? + .context("part module reference should have an ident")?; + + let ReferencedAsset::Some(module) = *referenced_asset else { + bail!("part module reference should have an module reference"); + }; + let id = module.as_chunk_item(Vc::upcast(chunking_context)).id().await?; + + visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { + let stmt = quote!( + "var $name = __turbopack_import__($id);" as Stmt, + name = Ident::new(ident.clone().into(), DUMMY_SP), + id: Expr = Expr::Lit(match &*id { + ModuleId::String(s) => s.as_str().into(), + ModuleId::Number(n) => (*n as f64).into(), + }) + ); + insert_hoisted_stmt(program, stmt); + })); + + Ok(CodeGeneration { visitors }.into()) + } +} diff --git a/crates/turbopack-ecmascript/Source/special_cases.rs b/crates/turbopack-ecmascript/Source/special_cases.rs new file mode 100644 index 0000000000000..8f2f5f0728255 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/special_cases.rs @@ -0,0 +1,3 @@ +use crate::references::AnalyzeEcmascriptModuleResultBuilder; + +pub(crate) fn special_cases(_path:&str, _references:&mut AnalyzeEcmascriptModuleResultBuilder) {} diff --git a/crates/turbopack-ecmascript/Source/static_code.rs b/crates/turbopack-ecmascript/Source/static_code.rs new file mode 100644 index 0000000000000..e6091e2f07bd8 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/static_code.rs @@ -0,0 +1,51 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + code_builder::{Code, CodeBuilder}, + context::AssetContext, + file_source::FileSource, + reference_type::ReferenceType, +}; + +use crate::EcmascriptModuleAsset; + +/// Static ECMAScript file code, to be used as part of some code. +/// +/// Useful to transform partial runtime code files, which get concatenated into +/// the final runtime code, while keeping source map information. +#[turbo_tasks::value] +pub struct StaticEcmascriptCode { + asset_context:Vc>, + asset:Vc, +} + +#[turbo_tasks::value_impl] +impl StaticEcmascriptCode { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub async fn new( + asset_context:Vc>, + asset_path:Vc, + ) -> Result> { + let module = asset_context + .process(Vc::upcast(FileSource::new(asset_path)), Value::new(ReferenceType::Runtime)) + .module(); + let Some(asset) = Vc::try_resolve_downcast_type::(module).await? + else { + bail!("asset is not an Ecmascript module") + }; + Ok(Self::cell(StaticEcmascriptCode { asset_context, asset })) + } + + /// Computes the contents of the asset and pushes it to + /// the code builder, including the source map if available. + #[turbo_tasks::function] + pub async fn code(self: Vc) -> Result> { + let this = self.await?; + let runtime_base_content = this.asset.module_content_without_analysis().await?; + let mut code = CodeBuilder::default(); + code.push_source(&runtime_base_content.inner_code, runtime_base_content.source_map); + Ok(Code::cell(code.build())) + } +} diff --git a/crates/turbopack-ecmascript/Source/swc_comments.rs b/crates/turbopack-ecmascript/Source/swc_comments.rs new file mode 100644 index 0000000000000..5507f31092b2a --- /dev/null +++ b/crates/turbopack-ecmascript/Source/swc_comments.rs @@ -0,0 +1,264 @@ +use std::{cell::RefCell, collections::HashMap, mem::take}; + +use swc_core::{ + base::SwcComments, + common::{ + BytePos, + comments::{Comment, Comments}, + }, +}; + +/// Immutable version of [SwcComments] which doesn't allow mutation. The `take` +/// variants are still implemented, but do not mutate the content. They are used +/// by the SWC Emitter. +pub struct ImmutableComments { + pub leading:HashMap>, + pub trailing:HashMap>, +} + +impl ImmutableComments { + pub fn new(comments:SwcComments) -> Self { + Self { + leading:comments + .leading + .iter_mut() + .filter_map(|mut r| { + let c = take(r.value_mut()); + (!c.is_empty()).then_some((*r.key(), c)) + }) + .collect(), + trailing:comments + .trailing + .iter_mut() + .filter_map(|mut r| { + let c = take(r.value_mut()); + (!c.is_empty()).then_some((*r.key(), c)) + }) + .collect(), + } + } + + pub fn consumable(&self) -> CowComments<'_> { CowComments::new(self) } +} + +impl Comments for ImmutableComments { + fn add_leading( + &self, + _pos:swc_core::common::BytePos, + _cmt:swc_core::common::comments::Comment, + ) { + panic!("Comments are immutable after parsing") + } + + fn add_leading_comments( + &self, + _pos:swc_core::common::BytePos, + _comments:Vec, + ) { + panic!("Comments are immutable after parsing") + } + + fn has_leading(&self, pos:swc_core::common::BytePos) -> bool { self.leading.contains_key(&pos) } + + fn move_leading(&self, _from:swc_core::common::BytePos, _to:swc_core::common::BytePos) { + panic!("Comments are immutable after parsing") + } + + fn take_leading( + &self, + _pos:swc_core::common::BytePos, + ) -> Option> { + panic!( + "Comments are immutable after parsing (Use ImmutableComments::consumable() to allow \ + taking out values)" + ) + } + + fn get_leading( + &self, + pos:swc_core::common::BytePos, + ) -> Option> { + self.leading.get(&pos).map(|v| v.to_owned()) + } + + fn add_trailing( + &self, + _pos:swc_core::common::BytePos, + _cmt:swc_core::common::comments::Comment, + ) { + panic!("Comments are immutable after parsing") + } + + fn add_trailing_comments( + &self, + _pos:swc_core::common::BytePos, + _comments:Vec, + ) { + panic!("Comments are immutable after parsing") + } + + fn has_trailing(&self, pos:swc_core::common::BytePos) -> bool { + self.trailing.contains_key(&pos) + } + + fn move_trailing(&self, _from:swc_core::common::BytePos, _to:swc_core::common::BytePos) { + panic!("Comments are immutable after parsing") + } + + fn take_trailing( + &self, + _pos:swc_core::common::BytePos, + ) -> Option> { + panic!( + "Comments are immutable after parsing (Use ImmutableComments::consumable() to allow \ + taking out values)" + ) + } + + fn get_trailing( + &self, + pos:swc_core::common::BytePos, + ) -> Option> { + self.trailing.get(&pos).map(|v| v.to_owned()) + } + + fn add_pure_comment(&self, _pos:swc_core::common::BytePos) { + panic!("Comments are immutable after parsing") + } + + fn with_leading(&self, pos:BytePos, f:F) -> Ret + where + Self: Sized, + F: FnOnce(&[Comment]) -> Ret, { + let cmts = self.get_leading(pos); + + if let Some(cmts) = &cmts { f(cmts) } else { f(&[]) } + } + + fn with_trailing(&self, pos:BytePos, f:F) -> Ret + where + Self: Sized, + F: FnOnce(&[Comment]) -> Ret, { + let cmts = self.get_trailing(pos); + + if let Some(cmts) = &cmts { f(cmts) } else { f(&[]) } + } +} + +pub struct CowComments<'a> { + leading:RefCell>>, + trailing:RefCell>>, +} + +impl<'a> CowComments<'a> { + fn new(comments:&'a ImmutableComments) -> Self { + Self { + leading:RefCell::new( + comments.leading.iter().map(|(&key, value)| (key, value)).collect(), + ), + trailing:RefCell::new( + comments.trailing.iter().map(|(&key, value)| (key, value)).collect(), + ), + } + } +} + +impl<'a> Comments for CowComments<'a> { + fn add_leading( + &self, + _pos:swc_core::common::BytePos, + _cmt:swc_core::common::comments::Comment, + ) { + panic!("Comments are immutable after parsing") + } + + fn add_leading_comments( + &self, + _pos:swc_core::common::BytePos, + _comments:Vec, + ) { + panic!("Comments are immutable after parsing") + } + + fn has_leading(&self, pos:swc_core::common::BytePos) -> bool { + self.leading.borrow().contains_key(&pos) + } + + fn move_leading(&self, _from:swc_core::common::BytePos, _to:swc_core::common::BytePos) { + panic!("Comments are immutable after parsing") + } + + fn take_leading( + &self, + pos:swc_core::common::BytePos, + ) -> Option> { + self.leading.borrow_mut().remove(&pos).map(|v| v.to_owned()) + } + + fn get_leading( + &self, + pos:swc_core::common::BytePos, + ) -> Option> { + self.leading.borrow().get(&pos).map(|&v| v.to_owned()) + } + + fn add_trailing( + &self, + _pos:swc_core::common::BytePos, + _cmt:swc_core::common::comments::Comment, + ) { + panic!("Comments are immutable after parsing") + } + + fn add_trailing_comments( + &self, + _pos:swc_core::common::BytePos, + _comments:Vec, + ) { + panic!("Comments are immutable after parsing") + } + + fn has_trailing(&self, pos:swc_core::common::BytePos) -> bool { + self.trailing.borrow().contains_key(&pos) + } + + fn move_trailing(&self, _from:swc_core::common::BytePos, _to:swc_core::common::BytePos) { + panic!("Comments are immutable after parsing") + } + + fn take_trailing( + &self, + pos:swc_core::common::BytePos, + ) -> Option> { + self.trailing.borrow_mut().remove(&pos).map(|v| v.to_owned()) + } + + fn get_trailing( + &self, + pos:swc_core::common::BytePos, + ) -> Option> { + self.trailing.borrow().get(&pos).map(|&v| v.to_owned()) + } + + fn add_pure_comment(&self, _pos:swc_core::common::BytePos) { + panic!("Comments are immutable after parsing") + } + + fn with_leading(&self, pos:BytePos, f:F) -> Ret + where + Self: Sized, + F: FnOnce(&[Comment]) -> Ret, { + let cmts = self.get_leading(pos); + + if let Some(cmts) = &cmts { f(cmts) } else { f(&[]) } + } + + fn with_trailing(&self, pos:BytePos, f:F) -> Ret + where + Self: Sized, + F: FnOnce(&[Comment]) -> Ret, { + let cmts = self.get_trailing(pos); + + if let Some(cmts) = &cmts { f(cmts) } else { f(&[]) } + } +} diff --git a/crates/turbopack-ecmascript/Source/text/mod.rs b/crates/turbopack-ecmascript/Source/text/mod.rs new file mode 100644 index 0000000000000..a7fa151c1e2b5 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/text/mod.rs @@ -0,0 +1,49 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::FileContent; +use turbopack_core::{ + asset::{Asset, AssetContent}, + ident::AssetIdent, + source::Source, +}; + +use crate::utils::StringifyJs; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("text content".into()) } + +/// A source asset that exports the string content of an asset as the default +/// export of a JS module. +#[turbo_tasks::value] +pub struct TextContentFileSource { + pub source:Vc>, +} + +#[turbo_tasks::value_impl] +impl TextContentFileSource { + #[turbo_tasks::function] + pub fn new(source:Vc>) -> Vc { TextContentFileSource { source }.cell() } +} + +#[turbo_tasks::value_impl] +impl Source for TextContentFileSource { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + self.source.ident().with_modifier(modifier()).rename_as("*.mjs".into()) + } +} + +#[turbo_tasks::value_impl] +impl Asset for TextContentFileSource { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let source = self.source.content().file_content(); + let FileContent::Content(content) = &*source.await? else { + return Ok(AssetContent::file(FileContent::NotFound.cell())); + }; + let text = content.content().to_str()?; + let code:RcStr = format!("export default {};", StringifyJs(&text)).into(); + let content = FileContent::Content(code.into()).cell(); + Ok(AssetContent::file(content)) + } +} diff --git a/crates/turbopack-ecmascript/Source/transform/mod.rs b/crates/turbopack-ecmascript/Source/transform/mod.rs new file mode 100644 index 0000000000000..95f30640d58c4 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/transform/mod.rs @@ -0,0 +1,325 @@ +use std::{fmt::Debug, hash::Hash, sync::Arc}; + +use anyhow::Result; +use async_trait::async_trait; +use swc_core::{ + atoms::JsWord, + base::SwcComments, + common::{Mark, SourceMap, chain, collections::AHashMap, comments::Comments, util::take::Take}, + ecma::{ + ast::{Module, ModuleItem, Program, Script}, + preset_env::{self, Targets}, + transforms::{ + base::{Assumptions, feature::FeatureFlag, helpers::inject_helpers}, + optimization::inline_globals2, + react::react, + }, + visit::{FoldWith, VisitMutWith}, + }, + quote, +}; +use turbo_tasks::{RcStr, ValueDefault, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + environment::Environment, + issue::{Issue, IssueSeverity, IssueStage, StyledString}, +}; + +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(Debug, Clone, PartialOrd, Ord, Hash)] +pub enum EcmascriptInputTransform { + CommonJs, + Plugin(Vc), + PresetEnv(Vc), + React { + #[serde(default)] + development:bool, + #[serde(default)] + refresh:bool, + // swc.jsc.transform.react.importSource + import_source:Vc>, + // swc.jsc.transform.react.runtime, + runtime:Vc>, + }, + GlobalTypeofs { + window_value:String, + }, + // These options are subset of swc_core::ecma::transforms::typescript::Config, but + // it doesn't derive `Copy` so repeating values in here + TypeScript { + #[serde(default)] + use_define_for_class_fields:bool, + }, + Decorators { + #[serde(default)] + is_legacy:bool, + #[serde(default)] + is_ecma:bool, + #[serde(default)] + emit_decorators_metadata:bool, + #[serde(default)] + use_define_for_class_fields:bool, + }, +} + +/// The CustomTransformer trait allows you to implement your own custom SWC +/// transformer to run over all ECMAScript files imported in the graph. +#[async_trait] +pub trait CustomTransformer: Debug { + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()>; +} + +/// A wrapper around a TransformPlugin instance, allowing it to operate with +/// the turbo_task caching requirements. +#[turbo_tasks::value( + transparent, + serialization = "none", + eq = "manual", + into = "new", + cell = "new" +)] +#[derive(Debug)] +pub struct TransformPlugin(#[turbo_tasks(trace_ignore)] Box); + +#[turbo_tasks::value(transparent)] +pub struct OptionTransformPlugin(Option>); + +#[turbo_tasks::value_impl] +impl ValueDefault for OptionTransformPlugin { + #[turbo_tasks::function] + fn value_default() -> Vc { Vc::cell(None) } +} + +#[async_trait] +impl CustomTransformer for TransformPlugin { + async fn transform(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + self.0.transform(program, ctx).await + } +} + +#[turbo_tasks::value(transparent, serialization = "auto_for_input")] +#[derive(Debug, Clone, PartialOrd, Ord, Hash)] +pub struct EcmascriptInputTransforms(Vec); + +#[turbo_tasks::value_impl] +impl EcmascriptInputTransforms { + #[turbo_tasks::function] + pub fn empty() -> Vc { Vc::cell(Vec::new()) } + + #[turbo_tasks::function] + pub async fn extend(self: Vc, other:Vc) -> Result> { + let mut transforms = self.await?.clone_value(); + transforms.extend(other.await?.clone_value()); + Ok(Vc::cell(transforms)) + } +} + +pub struct TransformContext<'a> { + pub comments:&'a SwcComments, + pub top_level_mark:Mark, + pub unresolved_mark:Mark, + pub source_map:&'a Arc, + pub file_path_str:&'a str, + pub file_name_str:&'a str, + pub file_name_hash:u128, + pub file_path:Vc, +} + +impl EcmascriptInputTransform { + pub async fn apply(&self, program:&mut Program, ctx:&TransformContext<'_>) -> Result<()> { + let &TransformContext { comments, source_map, top_level_mark, unresolved_mark, .. } = ctx; + match self { + EcmascriptInputTransform::GlobalTypeofs { window_value } => { + let mut typeofs:AHashMap = Default::default(); + typeofs.insert("window".into(), JsWord::from(&**window_value)); + + program.visit_mut_with(&mut inline_globals2( + Default::default(), + Default::default(), + Default::default(), + Arc::new(typeofs), + )); + }, + EcmascriptInputTransform::React { development, refresh, import_source, runtime } => { + use swc_core::ecma::transforms::react::{Options, Runtime}; + let runtime = if let Some(runtime) = &*runtime.await? { + match runtime.as_str() { + "classic" => Runtime::Classic, + "automatic" => Runtime::Automatic, + _ => { + return Err(anyhow::anyhow!( + "Invalid value for swc.jsc.transform.react.runtime: {}", + runtime + )); + }, + } + } else { + Runtime::Automatic + }; + + let config = Options { + runtime:Some(runtime), + development:Some(*development), + import_source:import_source.await?.as_deref().map(ToString::to_string), + refresh:if *refresh { + Some(swc_core::ecma::transforms::react::RefreshOptions { + refresh_reg:"__turbopack_refresh__.register".to_string(), + refresh_sig:"__turbopack_refresh__.signature".to_string(), + ..Default::default() + }) + } else { + None + }, + ..Default::default() + }; + + // Explicit type annotation to ensure that we don't duplicate transforms in the + // final binary + program.visit_mut_with(&mut react::<&dyn Comments>( + source_map.clone(), + Some(&comments), + config, + top_level_mark, + unresolved_mark, + )); + + if *refresh { + let stmt = quote!( + // AMP / No-JS mode does not inject these helpers + "\nif (typeof globalThis.$RefreshHelpers$ === 'object' && \ + globalThis.$RefreshHelpers !== null) { \ + __turbopack_refresh__.registerExports(module, \ + globalThis.$RefreshHelpers$); }\n" as Stmt + ); + + match program { + Program::Module(module) => { + module.body.push(ModuleItem::Stmt(stmt)); + }, + Program::Script(script) => { + script.body.push(stmt); + }, + } + } + }, + EcmascriptInputTransform::CommonJs => { + // Explicit type annotation to ensure that we don't duplicate transforms in the + // final binary + program.visit_mut_with(&mut swc_core::ecma::transforms::module::common_js::< + &dyn Comments, + >( + unresolved_mark, + swc_core::ecma::transforms::module::util::Config { + allow_top_level_this:true, + import_interop:Some( + swc_core::ecma::transforms::module::util::ImportInterop::Swc, + ), + ..Default::default() + }, + swc_core::ecma::transforms::base::feature::FeatureFlag::all(), + Some(&comments), + )); + }, + EcmascriptInputTransform::PresetEnv(env) => { + let versions = env.runtime_versions().await?; + let config = swc_core::ecma::preset_env::Config { + targets:Some(Targets::Versions(*versions)), + mode:None, // Don't insert core-js polyfills + ..Default::default() + }; + + let module_program = std::mem::replace(program, Program::Module(Module::dummy())); + + let module_program = + if let Program::Script(Script { span, mut body, shebang }) = module_program { + Program::Module(Module { + span, + body:body.drain(..).map(ModuleItem::Stmt).collect(), + shebang, + }) + } else { + module_program + }; + + // Explicit type annotation to ensure that we don't duplicate transforms in the + // final binary + *program = module_program.fold_with(&mut chain!( + preset_env::preset_env::<&'_ dyn Comments>( + top_level_mark, + Some(&comments), + config, + Assumptions::default(), + &mut FeatureFlag::empty(), + ), + inject_helpers(unresolved_mark), + )); + }, + EcmascriptInputTransform::TypeScript { + // TODO(WEB-1213) + use_define_for_class_fields: _use_define_for_class_fields, + } => { + use swc_core::ecma::transforms::typescript::typescript; + let config = Default::default(); + program.visit_mut_with(&mut typescript(config, unresolved_mark)); + }, + EcmascriptInputTransform::Decorators { + is_legacy, + is_ecma: _, + emit_decorators_metadata, + // TODO(WEB-1213) + use_define_for_class_fields: _use_define_for_class_fields, + } => { + use swc_core::ecma::transforms::proposal::decorators::{Config, decorators}; + let config = Config { + legacy:*is_legacy, + emit_metadata:*emit_decorators_metadata, + ..Default::default() + }; + + let p = std::mem::replace(program, Program::Module(Module::dummy())); + *program = + p.fold_with(&mut chain!(decorators(config), inject_helpers(unresolved_mark))); + }, + EcmascriptInputTransform::Plugin(transform) => { + transform.await?.transform(program, ctx).await? + }, + } + Ok(()) + } +} + +pub fn remove_shebang(program:&mut Program) { + match program { + Program::Module(m) => { + m.shebang = None; + }, + Program::Script(s) => { + s.shebang = None; + }, + } +} + +#[turbo_tasks::value(shared)] +pub struct UnsupportedServerActionIssue { + pub file_path:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for UnsupportedServerActionIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Error.into() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text( + "Server actions (\"use server\") are not yet supported in Turbopack".into(), + ) + .cell() + } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.file_path } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Transform.cell() } +} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/asset.rs b/crates/turbopack-ecmascript/Source/tree_shake/asset.rs new file mode 100644 index 0000000000000..ca4a5bc58641c --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/asset.rs @@ -0,0 +1,218 @@ +use anyhow::{Context, Result}; +use turbo_tasks::Vc; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkableModule, ChunkingContext, EvaluatableAsset}, + ident::AssetIdent, + module::Module, + reference::{ModuleReferences, SingleModuleReference}, + resolve::ModulePart, +}; + +use super::{ + Key, + SplitResult, + chunk_item::EcmascriptModulePartChunkItem, + get_part_id, + split_module, +}; +use crate::{ + AnalyzeEcmascriptModuleResult, + EcmascriptModuleAsset, + chunk::{EcmascriptChunkPlaceable, EcmascriptExports}, + references::analyse_ecmascript_module, +}; + +/// A reference to part of an ES module. +/// +/// This type is used for an advanced tree shkaing. +#[turbo_tasks::value] +pub struct EcmascriptModulePartAsset { + pub(crate) full_module:Vc, + pub(crate) part:Vc, + pub(crate) import_externals:bool, +} + +#[turbo_tasks::value_impl] +impl EcmascriptModulePartAsset { + /// Create a new instance of [Vc], whcih consists + /// of a pointer to the full module and the [ModulePart] pointing the part + /// of the module. + #[turbo_tasks::function] + pub fn new( + module:Vc, + part:Vc, + import_externals:bool, + ) -> Vc { + EcmascriptModulePartAsset { full_module:module, part, import_externals }.cell() + } + + #[turbo_tasks::function] + pub async fn is_async_module(self: Vc) -> Result> { + let this = self.await?; + let result = this.full_module.failsafe_analyze(); + + if let Some(async_module) = *result.await?.async_module.await? { + Ok(async_module.is_self_async(self.references())) + } else { + Ok(Vc::cell(false)) + } + } +} + +#[turbo_tasks::value_impl] +impl Module for EcmascriptModulePartAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let inner = self.full_module.ident(); + let result = split_module(self.full_module); + + match &*result.await? { + SplitResult::Ok { .. } => Ok(inner.with_part(self.part)), + SplitResult::Failed { .. } => Ok(inner), + } + } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let split_data = split_module(self.full_module).await?; + + let analyze = analyze(self.full_module, self.part).await?; + + let (deps, entrypoints) = match &*split_data { + SplitResult::Ok { deps, entrypoints, .. } => (deps, entrypoints), + SplitResult::Failed { .. } => return Ok(analyze.references), + }; + + // Facade depends on evaluation and re-exports + if matches!(&*self.part.await?, ModulePart::Facade) { + let mut references = vec![]; + + let reference = Vc::upcast(SingleModuleReference::new( + Vc::upcast(EcmascriptModulePartAsset::new( + self.full_module, + ModulePart::evaluation(), + self.import_externals, + )), + Vc::cell("ecmascript module evaluation".into()), + )); + + references.push(reference); + + let reference = Vc::upcast(SingleModuleReference::new( + Vc::upcast(EcmascriptModulePartAsset::new( + self.full_module, + ModulePart::exports(), + self.import_externals, + )), + Vc::cell("ecmascript reexports".into()), + )); + + references.push(reference); + + references.extend(analyze.references.await?.iter().cloned()); + + return Ok(Vc::cell(references)); + } + + // ModulePart::Exports contains all reexports and a reexport of the Locals + if matches!(&*self.part.await?, ModulePart::Exports) { + let mut references = vec![]; + + for key in entrypoints.keys() { + if let Key::Export(e) = key { + let reference = Vc::upcast(SingleModuleReference::new( + Vc::upcast(EcmascriptModulePartAsset::new( + self.full_module, + ModulePart::export(e.clone()), + self.import_externals, + )), + Vc::cell(format!("ecmascript export '{e}'").into()), + )); + + references.push(reference); + } + } + + references.extend(analyze.references.await?.iter().cloned()); + + return Ok(Vc::cell(references)); + } + let deps = { + let part_id = get_part_id(&split_data, self.part) + .await + .with_context(|| format!("part {:?} is not found in the module", self.part))?; + + match deps.get(&part_id) { + Some(v) => &**v, + None => &[], + } + }; + + let mut assets = deps + .iter() + .map(|&part_id| { + Ok(Vc::upcast(SingleModuleReference::new( + Vc::upcast(EcmascriptModulePartAsset::new( + self.full_module, + ModulePart::internal(part_id), + self.import_externals, + )), + Vc::cell("ecmascript module part".into()), + ))) + }) + .collect::>>()?; + + assets.extend(analyze.references.await?.iter().cloned()); + + Ok(Vc::cell(assets)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptModulePartAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { todo!() } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for EcmascriptModulePartAsset { + #[turbo_tasks::function] + async fn get_exports(self: Vc) -> Result> { + Ok(self.analyze().await?.exports) + } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for EcmascriptModulePartAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast( + EcmascriptModulePartChunkItem { module:self, chunking_context }.cell(), + )) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptModulePartAsset { + #[turbo_tasks::function] + pub(super) async fn analyze(self: Vc) -> Result> { + let this = self.await?; + + Ok(analyze(this.full_module, this.part)) + } +} + +#[turbo_tasks::function] +async fn analyze( + module:Vc, + part:Vc, +) -> Result> { + Ok(analyse_ecmascript_module(module, Some(part))) +} + +#[turbo_tasks::value_impl] +impl EvaluatableAsset for EcmascriptModulePartAsset {} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/chunk_item.rs b/crates/turbopack-ecmascript/Source/tree_shake/chunk_item.rs new file mode 100644 index 0000000000000..788e989258e9f --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/chunk_item.rs @@ -0,0 +1,97 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbopack_core::{ + chunk::{AsyncModuleInfo, ChunkItem, ChunkType, ChunkingContext}, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, +}; + +use super::{asset::EcmascriptModulePartAsset, part_of_module, split_module}; +use crate::{ + EcmascriptModuleContent, + chunk::{EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkType}, +}; + +/// This is an implementation of [ChunkItem] for +/// [Vc]. +/// +/// This is a pointer to a part of an ES module. +#[turbo_tasks::value(shared)] +pub struct EcmascriptModulePartChunkItem { + pub(super) module:Vc, + pub(super) chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + panic!("content() should never be called"); + } + + #[turbo_tasks::function] + async fn content_with_async_module_info( + self: Vc, + async_module_info:Option>, + ) -> Result> { + let this = self.await?; + let module = this.module.await?; + + let split_data = split_module(module.full_module); + let parsed = part_of_module(split_data, module.part); + + let analyze = this.module.analyze().await?; + let async_module_options = analyze.async_module.module_options(async_module_info); + + let module_type_result = *module.full_module.determine_module_type().await?; + + let content = EcmascriptModuleContent::new( + parsed, + module.full_module.ident(), + module_type_result.module_type, + this.chunking_context, + analyze.references, + analyze.code_generation, + analyze.async_module, + analyze.source_map, + analyze.exports, + async_module_info, + ); + + Ok(EcmascriptChunkItemContent::new( + content, + this.chunking_context, + module.full_module.await?.options, + async_module_options, + )) + } + + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } +} + +#[turbo_tasks::value_impl] +impl ChunkItem for EcmascriptModulePartChunkItem { + #[turbo_tasks::function] + async fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + async fn asset_ident(&self) -> Result> { Ok(self.module.ident()) } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } + + #[turbo_tasks::function] + fn is_self_async(&self) -> Vc { self.module.is_async_module() } +} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/cjs_finder.rs b/crates/turbopack-ecmascript/Source/tree_shake/cjs_finder.rs new file mode 100644 index 0000000000000..210adb988f552 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/cjs_finder.rs @@ -0,0 +1,11 @@ +use swc_core::ecma::ast::*; + +pub fn contains_cjs(m:&Program) -> bool { + if let Program::Module(m) = m { + if m.body.iter().any(|s| s.is_module_decl()) { + return false; + } + } + + true +} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/graph.rs b/crates/turbopack-ecmascript/Source/tree_shake/graph.rs new file mode 100644 index 0000000000000..492705d1b832e --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/graph.rs @@ -0,0 +1,1151 @@ +use std::{ + fmt, + hash::{BuildHasherDefault, Hash}, +}; + +use indexmap::IndexSet; +use petgraph::{ + algo::{has_path_connecting, kosaraju_scc}, + prelude::DiGraphMap, +}; +use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; +use swc_core::{ + common::{DUMMY_SP, SyntaxContext, util::take::Take}, + ecma::{ + ast::{ + ClassDecl, + Decl, + DefaultDecl, + ExportDecl, + ExportNamedSpecifier, + ExportSpecifier, + Expr, + ExprStmt, + FnDecl, + Id, + Ident, + ImportDecl, + ImportNamedSpecifier, + ImportSpecifier, + ImportStarAsSpecifier, + KeyValueProp, + Lit, + Module, + ModuleDecl, + ModuleExportName, + ModuleItem, + NamedExport, + ObjectLit, + Prop, + PropName, + PropOrSpread, + Stmt, + VarDecl, + VarDeclKind, + VarDeclarator, + op, + }, + atoms::JsWord, + utils::{find_pat_ids, private_ident, quote_ident}, + }, +}; +use turbo_tasks::RcStr; + +use super::{ + Key, + TURBOPACK_PART_IMPORT_SOURCE, + util::{ids_captured_by, ids_used_by, ids_used_by_ignoring_nested}, +}; +use crate::magic_identifier; + +/// The id of an item +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) enum ItemId { + Group(ItemIdGroupKind), + Item { index:usize, kind:ItemIdItemKind }, +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) enum ItemIdGroupKind { + ModuleEvaluation, + /// `(local, export_name)`` + Export(Id, JsWord), +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) enum ItemIdItemKind { + Normal, + + ImportOfModule, + /// Imports are split as multiple items. + ImportBinding(u32), + VarDeclarator(u32), +} + +impl fmt::Debug for ItemId { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ItemId::Group(kind) => { + write!(f, "ItemId({:?})", kind) + }, + ItemId::Item { index, kind } => { + write!(f, "ItemId({}, {:?})", index, kind) + }, + } + } +} + +type FxBuildHasher = BuildHasherDefault; + +/// Data about a module item +#[derive(Debug)] +pub(crate) struct ItemData { + /// Is the module item hoisted? + pub is_hoisted:bool, + + pub pure:bool, + + /// Variables declared or bound by this module item + pub var_decls:IndexSet, + + /// Variables read by this module item during evaluation + pub read_vars:IndexSet, + + /// Variables read by this module item eventually + /// + /// - e.g. variables read in the body of function declarations are + /// considered as eventually read + /// - This is only used when reads are not trigger directly by this module + /// item, but require a side effect to be triggered. We don’t know when + /// this is executed. + /// - Note: This doesn’t mean they are only read “after†initial evaluation. + /// They might also be read “during†initial evaluation on any module item + /// with SIDE_EFFECTS. This kind of interaction is handled by the module + /// item with SIDE_EFFECTS. + pub eventual_read_vars:IndexSet, + + /// Side effects that are triggered on local variables during evaluation + pub write_vars:IndexSet, + + /// Side effects that are triggered on local variables eventually + pub eventual_write_vars:IndexSet, + + /// Any other unknown side effects that are trigger during evaluation + pub side_effects:bool, + + pub content:ModuleItem, + + pub export:Option, +} + +impl Default for ItemData { + fn default() -> Self { + Self { + is_hoisted:Default::default(), + var_decls:Default::default(), + read_vars:Default::default(), + eventual_read_vars:Default::default(), + write_vars:Default::default(), + eventual_write_vars:Default::default(), + side_effects:Default::default(), + content:ModuleItem::dummy(), + pure:Default::default(), + export:Default::default(), + } + } +} + +#[derive(Debug, Clone)] +pub struct InternedGraph +where + T: Eq + Hash + Clone, { + pub(super) idx_graph:DiGraphMap, + pub(super) graph_ix:IndexSet>, +} + +#[derive(Debug, Clone, Copy)] +pub enum Dependency { + Strong, + Weak, +} + +impl Default for InternedGraph +where + T: Eq + Hash + Clone, +{ + fn default() -> Self { Self { idx_graph:Default::default(), graph_ix:Default::default() } } +} + +impl InternedGraph +where + T: Eq + Hash + Clone, +{ + pub(super) fn node(&mut self, id:&T) -> u32 { + self.graph_ix.get_index_of(id).unwrap_or_else(|| { + let ix = self.graph_ix.len(); + self.graph_ix.insert_full(id.clone()); + ix + }) as _ + } + + /// Panics if `id` is not found. + pub(super) fn get_node(&self, id:&T) -> u32 { self.graph_ix.get_index_of(id).unwrap() as _ } +} + +#[derive(Debug, Clone, Default)] +pub struct DepGraph { + pub(super) g:InternedGraph, +} + +#[derive(Debug, Clone, Copy)] +pub(super) enum Mode { + #[allow(dead_code)] + Development, + Production, +} + +pub(super) struct SplitModuleResult { + pub entrypoints:FxHashMap, + + /// Dependency between parts. + pub part_deps:FxHashMap>, + pub modules:Vec, +} + +impl DepGraph { + /// Weak imports are imports only if it is referenced strongly. But this + /// is production-only, and weak dependencies are treated as strong + /// dependencies in development mode. + pub(super) fn handle_weak(&mut self, mode:Mode) { + if !matches!(mode, Mode::Production) { + return; + } + + for start in self.g.graph_ix.iter() { + let start = self.g.get_node(start); + for end in self.g.graph_ix.iter() { + let end = self.g.get_node(end); + + if let Some(Dependency::Weak) = self.g.idx_graph.edge_weight(start, end) { + self.g.idx_graph.remove_edge(start, end); + } + } + } + } + + /// Split modules into parts. Additionally, this function adds imports to + /// _connect_ variables. + /// + /// _connect_ here means if a variable is declared in a different part than + /// a usage side, `import` and `export` will be added. + /// + /// Note: ESM imports are immutable, but we do not handle it. + pub(super) fn split_module(&self, data:&FxHashMap) -> SplitModuleResult { + let groups = self.finalize(data); + let mut exports = FxHashMap::default(); + let mut part_deps = FxHashMap::<_, Vec<_>>::default(); + + let mut modules = vec![]; + + if groups.graph_ix.is_empty() { + // If there's no dependency, all nodes are in the module evaluaiotn group. + modules.push(Module { + span:DUMMY_SP, + body:data.values().map(|v| v.content.clone()).collect(), + shebang:None, + }); + exports.insert(Key::ModuleEvaluation, 0); + } + + for (ix, group) in groups.graph_ix.iter().enumerate() { + let mut chunk = Module { span:DUMMY_SP, body:vec![], shebang:None }; + + let mut required_vars = group + .iter() + .flat_map(|id| { + let data = data.get(id).unwrap(); + + data.read_vars + .iter() + .chain(data.write_vars.iter()) + .chain(data.eventual_read_vars.iter()) + .chain(data.eventual_write_vars.iter()) + }) + .collect::>(); + + for id in group { + let data = data.get(id).unwrap(); + + for var in data.var_decls.iter() { + required_vars.remove(var); + } + } + + for item in group { + match item { + ItemId::Group(ItemIdGroupKind::Export(id, _)) => { + required_vars.insert(id); + + if let Some(export) = &data[item].export { + exports.insert(Key::Export(export.as_str().into()), ix as u32); + } + }, + ItemId::Group(ItemIdGroupKind::ModuleEvaluation) => { + exports.insert(Key::ModuleEvaluation, ix as u32); + }, + + _ => {}, + } + } + + for dep in groups.idx_graph.neighbors_directed(ix as u32, petgraph::Direction::Outgoing) + { + let mut specifiers = vec![]; + + let dep_items = groups.graph_ix.get_index(dep as usize).unwrap(); + + for dep_item in dep_items { + let data = data.get(dep_item).unwrap(); + + for var in data.var_decls.iter() { + if required_vars.remove(var) { + specifiers.push(ImportSpecifier::Named(ImportNamedSpecifier { + span:DUMMY_SP, + local:var.clone().into(), + imported:None, + is_type_only:false, + })); + } + } + } + + part_deps.entry(ix as u32).or_default().push(dep); + + chunk.body.push(ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + span:DUMMY_SP, + specifiers, + src:Box::new(TURBOPACK_PART_IMPORT_SOURCE.into()), + type_only:false, + with:Some(Box::new(create_turbopack_part_id_assert(PartId::Internal(dep)))), + phase:Default::default(), + }))); + } + + for g in group { + chunk.body.push(data[g].content.clone()); + } + + for g in group { + let data = data.get(g).unwrap(); + + // Emit `export { foo }` + for var in data.var_decls.iter() { + let assertion_prop = + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key:quote_ident!("__turbopack_var__").into(), + value:Box::new(true.into()), + }))); + + chunk.body.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport { + span:DUMMY_SP, + specifiers:vec![ExportSpecifier::Named(ExportNamedSpecifier { + span:DUMMY_SP, + orig:ModuleExportName::Ident(var.clone().into()), + exported:None, + is_type_only:false, + })], + src:if cfg!(test) { + Some(Box::new("__TURBOPACK_VAR__".into())) + } else { + None + }, + type_only:false, + with:Some(Box::new(ObjectLit { + span:DUMMY_SP, + props:vec![assertion_prop], + })), + }))); + } + } + + modules.push(chunk); + } + + SplitModuleResult { entrypoints:exports, part_deps, modules } + } + + /// Merges a dependency group between [ModuleItem]s into a dependency graph + /// of [Module]s. + /// + /// Note that [ModuleItem] and [Module] are represented as [ItemId] for + /// performance. + pub(super) fn finalize(&self, data:&FxHashMap) -> InternedGraph> { + /// Returns true if it should be called again + fn add_to_group( + graph:&InternedGraph, + data:&FxHashMap, + group:&mut Vec, + start_ix:u32, + global_done:&mut FxHashSet, + group_done:&mut FxHashSet, + ) -> bool { + let mut changed = false; + + // Check deps of `start`. + for dep_ix in + graph.idx_graph.neighbors_directed(start_ix, petgraph::Direction::Outgoing) + { + let dep_id = graph.graph_ix.get_index(dep_ix as _).unwrap(); + + if global_done.insert(dep_ix) + || (data.get(dep_id).map_or(false, |data| data.pure) + && group_done.insert(dep_ix)) + { + changed = true; + + group.push(dep_id.clone()); + + add_to_group(graph, data, group, dep_ix, global_done, group_done); + } + } + + changed + } + + let mut cycles = kosaraju_scc(&self.g.idx_graph); + cycles.retain(|v| v.len() > 1); + + // If a node have two or more dependents, it should be in a separate + // group. + + let mut groups = vec![]; + let mut global_done = FxHashSet::default(); + + // Module evaluation node and export nodes starts a group + for id in self.g.graph_ix.iter() { + let ix = self.g.get_node(id); + + if let ItemId::Group(_) = id { + groups.push((vec![id.clone()], FxHashSet::default())); + global_done.insert(ix); + } + } + + // Cycles should form a separate group + for id in self.g.graph_ix.iter() { + let ix = self.g.get_node(id); + + if let Some(cycle) = cycles.iter().find(|v| v.contains(&ix)) { + if cycle.iter().all(|v| !global_done.contains(v)) { + let ids = cycle + .iter() + .map(|&ix| self.g.graph_ix[ix as usize].clone()) + .collect::>(); + + global_done.extend(cycle.iter().copied()); + + groups.push((ids, Default::default())); + } + } + } + + // Expand **starting** nodes + for (ix, id) in self.g.graph_ix.iter().enumerate() { + // If a node is reachable from two or more nodes, it should be in a + // separate group. + + if global_done.contains(&(ix as u32)) { + continue; + } + + // Don't store a pure item in a separate chunk + if data.get(id).map_or(false, |data| data.pure) { + continue; + } + + // The number of nodes that this node is dependent on. + let dependant_count = self + .g + .idx_graph + .neighbors_directed(ix as _, petgraph::Direction::Incoming) + .count(); + + // The number of starting points that can reach to this node. + let count_of_startings = global_done + .iter() + .filter(|&&staring_point| { + has_path_connecting(&self.g.idx_graph, staring_point, ix as _, None) + }) + .count(); + + if dependant_count >= 2 && count_of_startings >= 2 { + groups.push((vec![id.clone()], FxHashSet::default())); + global_done.insert(ix as u32); + } + } + + loop { + let mut changed = false; + + for (group, group_done) in &mut groups { + let start = &group[0]; + let start_ix = self.g.get_node(start); + changed |= + add_to_group(&self.g, data, group, start_ix, &mut global_done, group_done); + } + + if !changed { + break; + } + } + + let mut groups = groups.into_iter().map(|v| v.0).collect::>(); + + // We need to sort, because we start from the group item and add others start + // from them. But the final module should be in the order of the original code. + for group in groups.iter_mut() { + group.sort(); + group.dedup(); + } + + let mut new_graph = InternedGraph::default(); + let mut group_ix_by_item_ix = FxHashMap::default(); + + for group in &groups { + let group_ix = new_graph.node(group); + + for item in group { + let item_ix = self.g.get_node(item); + group_ix_by_item_ix.insert(item_ix, group_ix); + } + } + + for group in &groups { + let group_ix = new_graph.node(group); + + for item in group { + let item_ix = self.g.get_node(item); + + for item_dep_ix in + self.g.idx_graph.neighbors_directed(item_ix, petgraph::Direction::Outgoing) + { + let dep_group_ix = group_ix_by_item_ix.get(&item_dep_ix); + if let Some(&dep_group_ix) = dep_group_ix { + if group_ix == dep_group_ix { + continue; + } + new_graph.idx_graph.add_edge(group_ix, dep_group_ix, Dependency::Strong); + } + } + } + } + + new_graph + } + + /// Fills information per module items + pub(super) fn init( + &mut self, + module:&Module, + unresolved_ctxt:SyntaxContext, + top_level_ctxt:SyntaxContext, + ) -> (Vec, FxHashMap) { + let mut exports = vec![]; + let mut items = FxHashMap::default(); + let mut ids = vec![]; + + for (index, item) in module.body.iter().enumerate() { + // Fill exports + if let ModuleItem::ModuleDecl(item) = item { + match item { + ModuleDecl::ExportDecl(item) => { + match &item.decl { + Decl::Fn(FnDecl { ident, .. }) + | Decl::Class(ClassDecl { ident, .. }) => { + exports.push((ident.to_id(), None)); + }, + Decl::Var(v) => { + for decl in &v.decls { + let ids:Vec = find_pat_ids(&decl.name); + for id in ids { + exports.push((id, None)); + } + } + }, + _ => {}, + } + }, + ModuleDecl::ExportNamed(item) => { + if let Some(src) = &item.src { + // One item for the import for re-export + let id = ItemId::Item { index, kind:ItemIdItemKind::ImportOfModule }; + ids.push(id.clone()); + items.insert( + id, + ItemData { + is_hoisted:true, + side_effects:true, + content:ModuleItem::ModuleDecl(ModuleDecl::Import( + ImportDecl { + specifiers:Default::default(), + src:src.clone(), + ..ImportDecl::dummy() + }, + )), + ..Default::default() + }, + ); + } + + for (si, s) in item.specifiers.iter().enumerate() { + let (orig, mut local, exported) = match s { + ExportSpecifier::Named(s) => { + ( + Some(s.orig.clone()), + match &s.orig { + ModuleExportName::Ident(i) => i.clone(), + ModuleExportName::Str(..) => quote_ident!("_tmp"), + }, + Some(s.exported.clone().unwrap_or_else(|| s.orig.clone())), + ) + }, + ExportSpecifier::Default(s) => { + ( + Some(ModuleExportName::Ident(Ident::new( + "default".into(), + DUMMY_SP, + ))), + quote_ident!("default"), + Some(ModuleExportName::Ident(s.exported.clone())), + ) + }, + ExportSpecifier::Namespace(s) => { + ( + None, + match &s.name { + ModuleExportName::Ident(i) => i.clone(), + ModuleExportName::Str(..) => quote_ident!("_tmp"), + }, + Some(s.name.clone()), + ) + }, + }; + + if item.src.is_some() { + local.sym = + magic_identifier::mangle(&format!("reexport {}", local.sym)) + .into(); + local = local.into_private(); + } + + exports.push((local.to_id(), exported.clone())); + + if let Some(src) = &item.src { + let id = ItemId::Item { + index, + kind:ItemIdItemKind::ImportBinding(si as _), + }; + ids.push(id.clone()); + + let import = match s { + ExportSpecifier::Namespace(..) => { + ImportSpecifier::Namespace(ImportStarAsSpecifier { + span:DUMMY_SP, + local:local.clone(), + }) + }, + _ => { + ImportSpecifier::Named(ImportNamedSpecifier { + span:DUMMY_SP, + local:local.clone(), + imported:orig, + is_type_only:false, + }) + }, + }; + items.insert( + id, + ItemData { + is_hoisted:true, + var_decls:[local.to_id()].into_iter().collect(), + pure:true, + content:ModuleItem::ModuleDecl(ModuleDecl::Import( + ImportDecl { + span:DUMMY_SP, + specifiers:vec![import], + src:src.clone(), + type_only:false, + with:None, + phase:Default::default(), + }, + )), + ..Default::default() + }, + ); + } + } + }, + + ModuleDecl::ExportDefaultDecl(export) => { + let id = match &export.decl { + DefaultDecl::Class(c) => c.ident.clone(), + DefaultDecl::Fn(f) => f.ident.clone(), + DefaultDecl::TsInterfaceDecl(_) => unreachable!(), + }; + + let default_var = id.unwrap_or_else(|| { + private_ident!(magic_identifier::mangle("default export")) + }); + + { + let mut used_ids = ids_used_by_ignoring_nested( + &export.decl, + unresolved_ctxt, + top_level_ctxt, + ); + used_ids.write.insert(default_var.to_id()); + let captured_ids = + ids_captured_by(&export.decl, unresolved_ctxt, top_level_ctxt); + let data = ItemData { + read_vars:used_ids.read, + eventual_read_vars:captured_ids.read, + write_vars:used_ids.write, + eventual_write_vars:captured_ids.write, + var_decls:[default_var.to_id()].into_iter().collect(), + side_effects:true, + content:ModuleItem::ModuleDecl(item.clone()), + ..Default::default() + }; + + let id = ItemId::Item { index, kind:ItemIdItemKind::Normal }; + ids.push(id.clone()); + items.insert(id, data); + } + + exports.push(( + default_var.to_id(), + Some(ModuleExportName::Ident(quote_ident!("default"))), + )); + }, + ModuleDecl::ExportDefaultExpr(export) => { + let default_var = + private_ident!(magic_identifier::mangle("default export")); + + { + // For + // let __TURBOPACK_default_export__ = expr; + + let mut used_ids = ids_used_by_ignoring_nested( + &export.expr, + unresolved_ctxt, + top_level_ctxt, + ); + let captured_ids = + ids_captured_by(&export.expr, unresolved_ctxt, top_level_ctxt); + + used_ids.write.insert(default_var.to_id()); + + let data = ItemData { + read_vars:used_ids.read, + eventual_read_vars:captured_ids.read, + write_vars:used_ids.write, + eventual_write_vars:captured_ids.write, + var_decls:[default_var.to_id()].into_iter().collect(), + side_effects:true, + content:ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new( + VarDecl { + span:DUMMY_SP, + kind:VarDeclKind::Const, + declare:false, + decls:vec![VarDeclarator { + span:DUMMY_SP, + name:default_var.clone().into(), + init:Some(export.expr.clone()), + definite:false, + }], + }, + )))), + ..Default::default() + }; + + let id = ItemId::Item { index, kind:ItemIdItemKind::Normal }; + ids.push(id.clone()); + items.insert(id, data); + } + + { + // For export default __TURBOPACK__default__export__ + + exports.push(( + default_var.to_id(), + Some(ModuleExportName::Ident(quote_ident!("default"))), + )); + } + }, + + ModuleDecl::ExportAll(item) => { + // One item for the import for re-export + let id = ItemId::Item { index, kind:ItemIdItemKind::ImportOfModule }; + ids.push(id.clone()); + items.insert( + id, + ItemData { + is_hoisted:true, + side_effects:true, + content:ModuleItem::ModuleDecl(ModuleDecl::ExportAll(item.clone())), + ..Default::default() + }, + ); + }, + _ => {}, + } + } + + match item { + ModuleItem::ModuleDecl(ModuleDecl::Import(item)) => { + // We create multiple items for each import. + + { + // One item for the import itself + let id = ItemId::Item { index, kind:ItemIdItemKind::ImportOfModule }; + ids.push(id.clone()); + items.insert( + id, + ItemData { + is_hoisted:true, + side_effects:true, + content:ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + specifiers:Default::default(), + ..item.clone() + })), + ..Default::default() + }, + ); + } + + // One per binding + for (si, s) in item.specifiers.iter().enumerate() { + let id = + ItemId::Item { index, kind:ItemIdItemKind::ImportBinding(si as _) }; + ids.push(id.clone()); + let local = match s { + ImportSpecifier::Named(s) => s.local.to_id(), + ImportSpecifier::Default(s) => s.local.to_id(), + ImportSpecifier::Namespace(s) => s.local.to_id(), + }; + items.insert( + id, + ItemData { + is_hoisted:true, + var_decls:[local].into_iter().collect(), + pure:true, + content:ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + specifiers:vec![s.clone()], + ..item.clone() + })), + ..Default::default() + }, + ); + } + }, + + ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { + decl: Decl::Fn(f), + .. + })) + | ModuleItem::Stmt(Stmt::Decl(Decl::Fn(f))) => { + let id = ItemId::Item { index, kind:ItemIdItemKind::Normal }; + ids.push(id.clone()); + + let vars = ids_used_by(&f.function, unresolved_ctxt, top_level_ctxt); + let var_decls = { + let mut v = IndexSet::with_capacity_and_hasher(1, Default::default()); + v.insert(f.ident.to_id()); + v + }; + items.insert( + id, + ItemData { + is_hoisted:true, + eventual_read_vars:vars.read, + eventual_write_vars:vars.write, + write_vars:var_decls.clone(), + var_decls, + content:ModuleItem::Stmt(Stmt::Decl(Decl::Fn(f.clone()))), + ..Default::default() + }, + ); + }, + ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { + decl: Decl::Class(c), + .. + })) + | ModuleItem::Stmt(Stmt::Decl(Decl::Class(c))) => { + let id = ItemId::Item { index, kind:ItemIdItemKind::Normal }; + ids.push(id.clone()); + + let vars = ids_used_by(&c.class, unresolved_ctxt, top_level_ctxt); + let var_decls = { + let mut v = IndexSet::with_capacity_and_hasher(1, Default::default()); + v.insert(c.ident.to_id()); + v + }; + items.insert( + id, + ItemData { + is_hoisted:true, + eventual_read_vars:vars.read, + eventual_write_vars:vars.write, + write_vars:var_decls.clone(), + var_decls, + content:ModuleItem::Stmt(Stmt::Decl(Decl::Class(c.clone()))), + ..Default::default() + }, + ); + }, + ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { + decl: Decl::Var(v), + .. + })) + | ModuleItem::Stmt(Stmt::Decl(Decl::Var(v))) => { + for (i, decl) in v.decls.iter().enumerate() { + let id = ItemId::Item { index, kind:ItemIdItemKind::VarDeclarator(i as _) }; + ids.push(id.clone()); + + let decl_ids:Vec = find_pat_ids(&decl.name); + let vars = ids_used_by_ignoring_nested( + &decl.init, + unresolved_ctxt, + top_level_ctxt, + ); + let eventual_vars = + ids_captured_by(&decl.init, unresolved_ctxt, top_level_ctxt); + + let side_effects = vars.found_unresolved; + + let var_decl = Box::new(VarDecl { decls:vec![decl.clone()], ..*v.clone() }); + let content = ModuleItem::Stmt(Stmt::Decl(Decl::Var(var_decl))); + items.insert( + id, + ItemData { + var_decls:decl_ids.clone().into_iter().collect(), + read_vars:vars.read, + eventual_read_vars:eventual_vars.read, + write_vars:decl_ids.into_iter().chain(vars.write).collect(), + eventual_write_vars:eventual_vars.write, + content, + side_effects, + ..Default::default() + }, + ); + } + }, + + ModuleItem::Stmt(Stmt::Expr(ExprStmt { + expr: box Expr::Assign(assign), .. + })) => { + let mut used_ids = + ids_used_by_ignoring_nested(item, unresolved_ctxt, top_level_ctxt); + let captured_ids = ids_captured_by(item, unresolved_ctxt, top_level_ctxt); + + if assign.op != op!("=") { + used_ids.read.extend(used_ids.write.iter().cloned()); + + let extra_ids = ids_used_by_ignoring_nested( + &assign.left, + unresolved_ctxt, + top_level_ctxt, + ); + used_ids.read.extend(extra_ids.read); + used_ids.write.extend(extra_ids.write); + } + + let side_effects = used_ids.found_unresolved; + + let data = ItemData { + read_vars:used_ids.read, + eventual_read_vars:captured_ids.read, + write_vars:used_ids.write, + eventual_write_vars:captured_ids.write, + content:item.clone(), + side_effects, + ..Default::default() + }; + + let id = ItemId::Item { index, kind:ItemIdItemKind::Normal }; + ids.push(id.clone()); + items.insert(id, data); + }, + + ModuleItem::ModuleDecl( + ModuleDecl::ExportDefaultDecl(..) + | ModuleDecl::ExportDefaultExpr(..) + | ModuleDecl::ExportNamed(NamedExport { .. }), + ) => {}, + + _ => { + // Default to normal + + let used_ids = + ids_used_by_ignoring_nested(item, unresolved_ctxt, top_level_ctxt); + let captured_ids = ids_captured_by(item, unresolved_ctxt, top_level_ctxt); + let data = ItemData { + read_vars:used_ids.read, + eventual_read_vars:captured_ids.read, + write_vars:used_ids.write, + eventual_write_vars:captured_ids.write, + side_effects:true, + content:item.clone(), + ..Default::default() + }; + + let id = ItemId::Item { index, kind:ItemIdItemKind::Normal }; + ids.push(id.clone()); + items.insert(id, data); + }, + } + } + + { + // `module evaluation side effects` Node + let id = ItemId::Group(ItemIdGroupKind::ModuleEvaluation); + ids.push(id.clone()); + items.insert( + id, + ItemData { + content:ModuleItem::Stmt(Stmt::Expr(ExprStmt { + span:DUMMY_SP, + expr:"module evaluation".into(), + })), + ..Default::default() + }, + ); + } + + for (local, export_name) in exports { + let name = match &export_name { + Some(ModuleExportName::Ident(v)) => v.to_id(), + _ => local.clone(), + }; + let id = ItemId::Group(ItemIdGroupKind::Export(local.clone(), name.0.clone())); + ids.push(id.clone()); + items.insert( + id.clone(), + ItemData { + content:ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport { + span:DUMMY_SP, + specifiers:vec![ExportSpecifier::Named(ExportNamedSpecifier { + span:DUMMY_SP, + orig:ModuleExportName::Ident(local.clone().into()), + exported:export_name, + is_type_only:false, + })], + src:None, + type_only:false, + with:None, + })), + read_vars:[name.clone()].into_iter().collect(), + export:Some(name.0), + ..Default::default() + }, + ); + } + + (ids, items) + } + + pub(super) fn add_strong_deps<'a, T>(&mut self, from:&ItemId, to:T) + where + T: IntoIterator, { + // This value cannot be lazily initialized because we need to ensure that + // ModuleEvaluation exists even if there's no side effect. + let from = self.g.node(from); + + for to in to { + let to = self.g.node(to); + + self.g.idx_graph.add_edge(from, to, Dependency::Strong); + } + } + + pub(super) fn add_weak_deps<'a, T>(&mut self, from:&ItemId, to:T) + where + T: IntoIterator, { + let from = self.g.node(from); + + for to in to { + let to = self.g.node(to); + + if let Some(Dependency::Strong) = self.g.idx_graph.edge_weight(from, to) { + continue; + } + self.g.idx_graph.add_edge(from, to, Dependency::Weak); + } + } + + pub(crate) fn has_dep(&mut self, id:&ItemId, dep:&ItemId, only_strong:bool) -> bool { + let from = self.g.node(id); + let to = self.g.node(dep); + self.g + .idx_graph + .edge_weight(from, to) + .map(|d| matches!(d, Dependency::Strong) || !only_strong) + .unwrap_or(false) + } + + pub(crate) fn has_path_connecting(&mut self, from:&ItemId, to:&ItemId) -> bool { + let from = self.g.node(from); + let to = self.g.node(to); + + has_path_connecting(&self.g.idx_graph, from, to, None) + } +} + +const ASSERT_CHUNK_KEY:&str = "__turbopack_part__"; + +#[derive(Debug, Clone)] +pub(crate) enum PartId { + ModuleEvaluation, + Exports, + Export(RcStr), + Internal(u32), +} + +pub(crate) fn create_turbopack_part_id_assert(dep:PartId) -> ObjectLit { + // We can't use quote! as `with` is not standard yet + ObjectLit { + span:DUMMY_SP, + props:vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key:PropName::Ident(Ident::new(ASSERT_CHUNK_KEY.into(), DUMMY_SP)), + value:match dep { + PartId::ModuleEvaluation => "module evaluation".into(), + PartId::Exports => "exports".into(), + PartId::Export(e) => format!("export {e}").into(), + PartId::Internal(dep) => (dep as f64).into(), + }, + })))], + } +} + +pub(crate) fn find_turbopack_part_id_in_asserts(asserts:&ObjectLit) -> Option { + asserts.props.iter().find_map(|prop| { + match prop { + PropOrSpread::Prop(box Prop::KeyValue(KeyValueProp { + key: PropName::Ident(key), + value: box Expr::Lit(Lit::Num(chunk_id)), + })) if &*key.sym == ASSERT_CHUNK_KEY => Some(PartId::Internal(chunk_id.value as u32)), + + PropOrSpread::Prop(box Prop::KeyValue(KeyValueProp { + key: PropName::Ident(key), + value: box Expr::Lit(Lit::Str(s)), + })) if &*key.sym == ASSERT_CHUNK_KEY => { + match &*s.value { + "module evaluation" => Some(PartId::ModuleEvaluation), + "exports" => Some(PartId::Exports), + _ => None, + } + }, + _ => None, + } + }) +} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/merge.rs b/crates/turbopack-ecmascript/Source/tree_shake/merge.rs new file mode 100644 index 0000000000000..89f7dbebec40e --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/merge.rs @@ -0,0 +1,73 @@ +use anyhow::Error; +use rustc_hash::FxHashSet; +use swc_core::ecma::{ + ast::{Module, ModuleDecl, ModuleItem}, + atoms::JsWord, +}; + +use super::{PartId, graph::find_turbopack_part_id_in_asserts}; + +/// A loader used to merge module items after splitting. +pub trait Load { + /// Loads a module while returning [None] if the module is already loaded. + fn load(&mut self, uri:&str, part_id:u32) -> Result, Error>; +} + +/// A module merger. +/// +/// This ensures that a module is loaded only once. +pub struct Merger +where + L: Load, { + loader:L, + + done:FxHashSet<(JsWord, u32)>, +} + +impl Merger +where + L: Load, +{ + /// Creates a module merger. + pub fn new(loader:L) -> Self { Merger { loader, done:Default::default() } } + + /// Merges module content by appending the content of imported modules. This + /// is recursive, so a single call is enoguh. + pub fn merge_recursively(&mut self, entry:Module) -> Result { + let mut content = vec![]; + let mut extra_body = vec![]; + + for stmt in entry.body { + match stmt { + ModuleItem::ModuleDecl(ModuleDecl::Import(import)) => { + // Try to prepend the content of module + + let part_id = + import.with.as_deref().and_then(find_turbopack_part_id_in_asserts); + + if let Some(PartId::Internal(part_id)) = part_id { + if self.done.insert((import.src.value.clone(), part_id)) { + if let Some(dep) = self.loader.load(&import.src.value, part_id)? { + let mut dep = self.merge_recursively(dep)?; + + extra_body.append(&mut dep.body); + } else { + content.push(ModuleItem::ModuleDecl(ModuleDecl::Import(import))); + } + } else { + // Remove import + } + } else { + // Preserve normal imports + content.push(ModuleItem::ModuleDecl(ModuleDecl::Import(import))); + } + }, + _ => extra_body.push(stmt), + } + } + + content.append(&mut extra_body); + + Ok(Module { span:entry.span, body:content, shebang:entry.shebang }) + } +} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/mod.rs b/crates/turbopack-ecmascript/Source/tree_shake/mod.rs new file mode 100644 index 0000000000000..93d7ac641002b --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/mod.rs @@ -0,0 +1,611 @@ +use std::borrow::Cow; + +use anyhow::{Result, bail}; +use indexmap::IndexSet; +use rustc_hash::FxHashMap; +use swc_core::{ + common::{DUMMY_SP, GLOBALS, SyntaxContext, util::take::Take}, + ecma::ast::{ + ExportNamedSpecifier, + Id, + Ident, + ImportDecl, + Module, + ModuleDecl, + ModuleExportName, + ModuleItem, + NamedExport, + Program, + }, +}; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ident::AssetIdent, resolve::ModulePart, source::Source}; + +use self::graph::{DepGraph, ItemData, ItemId, ItemIdGroupKind, Mode, SplitModuleResult}; +pub(crate) use self::graph::{ + PartId, + create_turbopack_part_id_assert, + find_turbopack_part_id_in_asserts, +}; +use crate::{EcmascriptModuleAsset, analyzer::graph::EvalContext, parse::ParseResult}; + +pub mod asset; +pub mod chunk_item; +mod cjs_finder; +mod graph; +pub mod merge; +#[cfg(test)] +mod tests; +mod util; + +pub(crate) const TURBOPACK_PART_IMPORT_SOURCE:&str = "__TURBOPACK_PART__"; + +pub struct Analyzer<'a> { + g:&'a mut DepGraph, + item_ids:&'a Vec, + items:&'a mut FxHashMap, + + last_side_effects:Vec, + + vars:FxHashMap, +} + +#[derive(Debug, Default, Clone)] +struct VarState { + declarator:Option, + + /// The module items that might trigger side effects on that variable. + /// We also store if this is a `const` write, so no further change will + /// happen to this var. + last_writes:Vec, + /// The module items that might read that variable. + last_reads:Vec, +} + +fn get_var<'a>(map:&'a FxHashMap, id:&Id) -> Cow<'a, VarState> { + let v = map.get(id); + match v { + Some(v) => Cow::Borrowed(v), + None => Cow::Owned(Default::default()), + } +} + +impl Analyzer<'_> { + pub(super) fn analyze( + module:&Module, + unresolved_ctxt:SyntaxContext, + top_level_ctxt:SyntaxContext, + ) -> (DepGraph, FxHashMap) { + let mut g = DepGraph::default(); + let (item_ids, mut items) = g.init(module, unresolved_ctxt, top_level_ctxt); + + let mut analyzer = Analyzer { + g:&mut g, + item_ids:&item_ids, + items:&mut items, + last_side_effects:Default::default(), + vars:Default::default(), + }; + + let eventual_ids = analyzer.hoist_vars_and_bindings(); + + analyzer.evaluate_immediate(module, &eventual_ids); + + analyzer.evaluate_eventual(module); + + analyzer.handle_exports(module); + + (g, items) + } + + /// Phase 1: Hoisted Variables and Bindings + /// + /// + /// Returns all (EVENTUAL_READ/WRITE_VARS) in the module. + fn hoist_vars_and_bindings(&mut self) -> IndexSet { + let mut eventual_ids = IndexSet::default(); + + for item_id in self.item_ids.iter() { + if let Some(item) = self.items.get(item_id) { + eventual_ids.extend(item.eventual_read_vars.iter().cloned()); + eventual_ids.extend(item.eventual_write_vars.iter().cloned()); + + if item.is_hoisted && item.side_effects { + self.g.add_strong_deps(item_id, self.last_side_effects.iter()); + + self.last_side_effects.push(item_id.clone()); + } + + for id in item.var_decls.iter() { + let state = self.vars.entry(id.clone()).or_default(); + + if item.is_hoisted { + state.last_writes.push(item_id.clone()); + } else { + // TODO(WEB-705): Create a fake module item + // state.last_writes.push(item_id.clone()); + } + } + } + } + + eventual_ids + } + + /// Phase 2: Immediate evaluation + fn evaluate_immediate(&mut self, _module:&Module, eventual_ids:&IndexSet) { + for item_id in self.item_ids.iter() { + if let Some(item) = self.items.get(item_id) { + // Ignore HOISTED module items, they have been processed in phase 1 already. + if item.is_hoisted { + continue; + } + + for id in item.var_decls.iter() { + let state = self.vars.entry(id.clone()).or_default(); + if state.declarator.is_none() { + state.declarator = Some(item_id.clone()); + } + } + + // For each var in READ_VARS: + for id in item.read_vars.iter() { + // Create a strong dependency to all module items listed in LAST_WRITES for that + // var. + + // (the writes need to be executed before this read) + let state = get_var(&self.vars, id); + self.g.add_strong_deps(item_id, state.last_writes.iter()); + + if let Some(declarator) = &state.declarator { + if declarator != item_id { + // A read also depends on the declaration. + self.g.add_strong_deps(item_id, [declarator].iter().copied()); + } + } + } + + // For each var in WRITE_VARS: + for id in item.write_vars.iter() { + // Create a weak dependency to all module items listed in + // LAST_READS for that var. + + // (the reads need to be executed before this write, when + // it’s needed) + + let state = get_var(&self.vars, id); + self.g.add_weak_deps(item_id, state.last_reads.iter()); + + if let Some(declarator) = &state.declarator { + if declarator != item_id { + // A write also depends on the declaration. + self.g.add_weak_deps(item_id, [declarator].iter().copied()); + } + } + } + + if item.side_effects { + // Create a strong dependency to LAST_SIDE_EFFECT. + + self.g.add_strong_deps(item_id, self.last_side_effects.iter()); + + // Create weak dependencies to all LAST_WRITES and + // LAST_READS. + for id in eventual_ids.iter() { + let state = get_var(&self.vars, id); + + self.g.add_weak_deps(item_id, state.last_writes.iter()); + self.g.add_weak_deps(item_id, state.last_reads.iter()); + } + } + + // For each var in WRITE_VARS: + for id in item.write_vars.iter() { + // Add this module item to LAST_WRITES + + let state = self.vars.entry(id.clone()).or_default(); + state.last_writes.push(item_id.clone()); + + // Optimization: Remove each module item to which we + // just created a strong dependency from LAST_WRITES + + state + .last_writes + .retain(|last_write| !self.g.has_dep(item_id, last_write, true)); + + // Drop all writes which are not reachable from this item. + // + // For + // + // var x = 0 + // x = 1 + // x = 2 + // x += 3 + // + // this will drop `x = 1` as not reachable from `x += 3`. + + state + .last_writes + .retain(|last_write| self.g.has_path_connecting(item_id, last_write)); + } + + // For each var in READ_VARS: + for id in item.read_vars.iter() { + // Add this module item to LAST_READS + + let state = self.vars.entry(id.clone()).or_default(); + state.last_reads.push(item_id.clone()); + + // Optimization: Remove each module item to which we + // have a strong dependency + + state.last_reads.retain(|last_read| !self.g.has_dep(item_id, last_read, true)); + } + + if item.side_effects { + self.last_side_effects.push(item_id.clone()); + } + } + } + } + + /// Phase 3: Eventual evaluation + fn evaluate_eventual(&mut self, _module:&Module) { + for item_id in self.item_ids.iter() { + if let Some(item) = self.items.get(item_id) { + // For each var in EVENTUAL_READ_VARS: + + for id in item.eventual_read_vars.iter() { + // Create a strong dependency to all module items listed in + // LAST_WRITES for that var. + + let state = get_var(&self.vars, id); + self.g.add_strong_deps(item_id, state.last_writes.iter()); + } + + // For each var in EVENTUAL_WRITE_VARS: + for id in item.eventual_write_vars.iter() { + // Create a weak dependency to all module items listed in + // LAST_READS for that var. + + let state = get_var(&self.vars, id); + + self.g.add_weak_deps(item_id, state.last_reads.iter()); + } + + // (no state update happens, since this is only triggered by + // side effects, which we already handled) + } + } + } + + /// Phase 4: Exports + fn handle_exports(&mut self, _module:&Module) { + for item_id in self.item_ids.iter() { + if let ItemId::Group(kind) = item_id { + match kind { + ItemIdGroupKind::ModuleEvaluation => { + // Create a strong dependency to LAST_SIDE_EFFECTS + + self.g.add_strong_deps(item_id, self.last_side_effects.iter()); + }, + ItemIdGroupKind::Export(local, _) => { + // Create a strong dependency to LAST_WRITES for this var + + let state = get_var(&self.vars, local); + + self.g.add_strong_deps(item_id, state.last_writes.iter()); + }, + } + } + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub(crate) enum Key { + ModuleEvaluation, + Export(RcStr), +} + +/// Converts [Vc] to the index. +async fn get_part_id(result:&SplitResult, part:Vc) -> Result { + let part = part.await?; + + // TODO implement ModulePart::Facade + let key = match &*part { + ModulePart::Evaluation => Key::ModuleEvaluation, + ModulePart::Export(export) => Key::Export(export.await?.as_str().into()), + ModulePart::Internal(part_id) => return Ok(*part_id), + ModulePart::Locals + | ModulePart::Exports + | ModulePart::Facade + | ModulePart::RenamedExport { .. } + | ModulePart::RenamedNamespace { .. } => { + bail!("invalid module part") + }, + }; + + let entrypoints = match &result { + SplitResult::Ok { entrypoints, .. } => entrypoints, + _ => bail!("split failed"), + }; + + let part_id = match entrypoints.get(&key) { + Some(id) => *id, + None => { + bail!("could not find part id for module part {:?} in {:?}", key, entrypoints) + }, + }; + + Ok(part_id) +} + +#[turbo_tasks::value(shared, serialization = "none", eq = "manual")] +pub(crate) enum SplitResult { + Ok { + asset_ident:Vc, + + /// `u32` is a index to `modules`. + #[turbo_tasks(trace_ignore)] + entrypoints:FxHashMap, + + #[turbo_tasks(debug_ignore, trace_ignore)] + modules:Vec>, + + #[turbo_tasks(trace_ignore)] + deps:FxHashMap>, + }, + Failed { + parse_result:Vc, + }, +} + +impl PartialEq for SplitResult { + fn eq(&self, other:&Self) -> bool { + match (self, other) { + (Self::Ok { .. }, Self::Ok { .. }) => false, + _ => core::mem::discriminant(self) == core::mem::discriminant(other), + } + } +} + +#[turbo_tasks::function] +pub(super) async fn split_module(asset:Vc) -> Result> { + Ok(split(asset.source().ident(), asset.source(), asset.parse())) +} + +#[turbo_tasks::function] +pub(super) async fn split( + ident:Vc, + source:Vc>, + parsed:Vc, +) -> Result> { + let parse_result = parsed.await?; + + match &*parse_result { + ParseResult::Ok { program, comments, eval_context, source_map, globals, .. } => { + // If the script file is a common js file, we cannot split the module + if cjs_finder::contains_cjs(program) { + return Ok(SplitResult::Failed { parse_result:parsed }.cell()); + } + + let module = match program { + Program::Module(module) => module, + Program::Script(..) => unreachable!("CJS is already handled"), + }; + + let (mut dep_graph, items) = GLOBALS.set(globals, || { + Analyzer::analyze( + module, + SyntaxContext::empty().apply_mark(eval_context.unresolved_mark), + SyntaxContext::empty().apply_mark(eval_context.top_level_mark), + ) + }); + + dep_graph.handle_weak(Mode::Production); + + let SplitModuleResult { entrypoints, part_deps, modules } = + dep_graph.split_module(&items); + + assert_ne!(modules.len(), 0, "modules.len() == 0;\nModule: {module:?}",); + + for &v in entrypoints.values() { + debug_assert!( + v < modules.len() as u32, + "Invalid entrypoint '{}' while there are only '{}' modules", + v, + modules.len() + ); + } + + let modules = modules + .into_iter() + .map(|module| { + let program = Program::Module(module); + let eval_context = EvalContext::new( + &program, + eval_context.unresolved_mark, + eval_context.top_level_mark, + false, + Some(source), + ); + + ParseResult::cell(ParseResult::Ok { + program, + globals:globals.clone(), + comments:comments.clone(), + source_map:source_map.clone(), + eval_context, + }) + }) + .collect(); + + Ok(SplitResult::Ok { asset_ident:ident, entrypoints, deps:part_deps, modules }.cell()) + }, + + _ => Ok(SplitResult::Failed { parse_result:parsed }.cell()), + } +} + +#[turbo_tasks::function] +pub(super) async fn part_of_module( + split_data:Vc, + part:Vc, +) -> Result> { + let split_data = split_data.await?; + + match &*split_data { + SplitResult::Ok { asset_ident, modules, entrypoints, deps, .. } => { + debug_assert_ne!(modules.len(), 0, "modules.len() == 0"); + + if matches!(&*part.await?, ModulePart::Facade) { + if let ParseResult::Ok { comments, eval_context, globals, source_map, .. } = + &*modules[0].await? + { + let mut module = Module::dummy(); + + let mut export_names = + entrypoints + .keys() + .filter_map(|key| { + if let Key::Export(v) = key { Some(v.clone()) } else { None } + }) + .collect::>(); + export_names.sort(); + + module.body.push(ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + span:DUMMY_SP, + specifiers:vec![], + src:Box::new(TURBOPACK_PART_IMPORT_SOURCE.into()), + type_only:false, + with:Some(Box::new(create_turbopack_part_id_assert( + PartId::ModuleEvaluation, + ))), + phase:Default::default(), + }))); + + let specifiers = export_names + .into_iter() + .map(|export_name| { + swc_core::ecma::ast::ExportSpecifier::Named(ExportNamedSpecifier { + span:DUMMY_SP, + orig:ModuleExportName::Ident(Ident::new( + export_name.as_str().into(), + DUMMY_SP, + )), + exported:None, + is_type_only:false, + }) + }) + .collect::>(); + + module.body.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed( + NamedExport { + span:DUMMY_SP, + specifiers, + src:Some(Box::new(TURBOPACK_PART_IMPORT_SOURCE.into())), + type_only:false, + with:Some(Box::new(create_turbopack_part_id_assert(PartId::Exports))), + }, + ))); + + let program = Program::Module(module); + let eval_context = EvalContext::new( + &program, + eval_context.unresolved_mark, + eval_context.top_level_mark, + true, + None, + ); + return Ok(ParseResult::Ok { + program, + comments:comments.clone(), + eval_context, + globals:globals.clone(), + source_map:source_map.clone(), + } + .cell()); + } else { + unreachable!() + } + } + + if matches!(&*part.await?, ModulePart::Exports) { + if let ParseResult::Ok { comments, eval_context, globals, source_map, .. } = + &*modules[0].await? + { + let mut export_names = + entrypoints + .keys() + .filter_map(|key| { + if let Key::Export(v) = key { Some(v.clone()) } else { None } + }) + .collect::>(); + export_names.sort(); + + let mut module = Module::dummy(); + + for export_name in export_names { + // We can't use quote! as `with` is not standard yet + let chunk_prop = + create_turbopack_part_id_assert(PartId::Export(export_name.clone())); + + let specifier = + swc_core::ecma::ast::ExportSpecifier::Named(ExportNamedSpecifier { + span:DUMMY_SP, + orig:ModuleExportName::Ident(Ident::new( + export_name.as_str().into(), + DUMMY_SP, + )), + exported:None, + is_type_only:false, + }); + module.body.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed( + NamedExport { + span:DUMMY_SP, + specifiers:vec![specifier], + src:Some(Box::new(TURBOPACK_PART_IMPORT_SOURCE.into())), + type_only:false, + with:Some(Box::new(chunk_prop)), + }, + ))); + } + + let program = Program::Module(module); + let eval_context = EvalContext::new( + &program, + eval_context.unresolved_mark, + eval_context.top_level_mark, + true, + None, + ); + return Ok(ParseResult::Ok { + program, + comments:comments.clone(), + eval_context, + globals:globals.clone(), + source_map:source_map.clone(), + } + .cell()); + } else { + unreachable!() + } + } + + let part_id = get_part_id(&split_data, part).await?; + + if part_id as usize >= modules.len() { + bail!( + "part_id is out of range: {part_id} >= {}; asset = {}; entrypoints = \ + {entrypoints:?}: part_deps = {deps:?}", + asset_ident.to_string().await?, + modules.len(), + ); + } + + Ok(modules[part_id as usize]) + }, + SplitResult::Failed { parse_result } => Ok(*parse_result), + } +} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/tests.rs b/crates/turbopack-ecmascript/Source/tree_shake/tests.rs new file mode 100644 index 0000000000000..9faa42a4dcdc6 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/tests.rs @@ -0,0 +1,345 @@ +use std::{ + fmt::Write, + hash::{BuildHasherDefault, Hash}, + path::PathBuf, + sync::Arc, +}; + +use anyhow::Error; +use indexmap::IndexSet; +use rustc_hash::FxHasher; +use serde::Deserialize; +use swc_core::{ + common::{Mark, SourceMap, SyntaxContext, util::take::Take}, + ecma::{ + ast::{EsVersion, Id, Module}, + atoms::JsWord, + codegen::text_writer::JsWriter, + parser::parse_file_as_module, + visit::VisitMutWith, + }, + testing::{self, NormalizedOutput, fixture}, +}; + +use super::{ + Analyzer, + Key, + graph::{ + DepGraph, + Dependency, + InternedGraph, + ItemId, + ItemIdGroupKind, + Mode, + SplitModuleResult, + }, + merge::Merger, +}; + +#[fixture("tests/tree-shaker/analyzer/**/input.js")] +fn test_fixture(input:PathBuf) { run(input); } + +#[derive(Deserialize)] +struct TestConfig { + /// Enabled exports. This is `Vec>` because we test multiple + /// exports at once. + #[serde(default)] + exports:Vec>, +} + +fn run(input:PathBuf) { + let config = input.with_file_name("config.json"); + let config = std::fs::read_to_string(config).unwrap_or_else(|_| "{}".into()); + let config = serde_json::from_str::(&config).unwrap_or_else(|_e| { + panic!("failed to parse config.json: {}", config); + }); + + testing::run_test(false, |cm, _handler| { + let fm = cm.load_file(&input).unwrap(); + + let mut module = + parse_file_as_module(&fm, Default::default(), EsVersion::latest(), None, &mut vec![]) + .unwrap(); + + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + let unresolved_ctxt = SyntaxContext::empty().apply_mark(unresolved_mark); + let top_level_ctxt = SyntaxContext::empty().apply_mark(top_level_mark); + + module.visit_mut_with(&mut swc_core::ecma::transforms::base::resolver( + unresolved_mark, + top_level_mark, + false, + )); + + let mut g = DepGraph::default(); + let (item_ids, mut items) = g.init(&module, unresolved_ctxt, top_level_ctxt); + + let mut s = String::new(); + + writeln!(s, "# Items\n").unwrap(); + writeln!(s, "Count: {}", item_ids.len()).unwrap(); + writeln!(s).unwrap(); + + for (i, id) in item_ids.iter().enumerate() { + let item = &items[id]; + + let (index, kind) = match id { + ItemId::Group(_) => continue, + ItemId::Item { index, kind } => (*index, kind), + }; + + writeln!(s, "## Item {}: Stmt {}, `{:?}`", i + 1, index, kind).unwrap(); + writeln!(s, "\n```js\n{}\n```\n", print(&cm, &[&module.body[index]])).unwrap(); + + if item.is_hoisted { + writeln!(s, "- Hoisted").unwrap(); + } + + if item.side_effects { + writeln!(s, "- Side effects").unwrap(); + } + + let f = |ids:&IndexSet>| { + let mut s = String::new(); + for (i, id) in ids.iter().enumerate() { + if i == 0 { + write!(s, "`{}`", id.0).unwrap(); + } else { + write!(s, ", `{}`", id.0).unwrap(); + } + } + s + }; + + if !item.var_decls.is_empty() { + writeln!(s, "- Declares: {}", f(&item.var_decls)).unwrap(); + } + + if !item.read_vars.is_empty() { + writeln!(s, "- Reads: {}", f(&item.read_vars)).unwrap(); + } + + if !item.eventual_read_vars.is_empty() { + writeln!(s, "- Reads (eventual): {}", f(&item.eventual_read_vars)).unwrap(); + } + + if !item.write_vars.is_empty() { + writeln!(s, "- Write: {}", f(&item.write_vars)).unwrap(); + } + + if !item.eventual_write_vars.is_empty() { + writeln!(s, "- Write (eventual): {}", f(&item.eventual_write_vars)).unwrap(); + } + + writeln!(s).unwrap(); + } + + let mut analyzer = Analyzer { + g:&mut g, + item_ids:&item_ids, + items:&mut items, + last_side_effects:Default::default(), + vars:Default::default(), + }; + + let eventual_ids = analyzer.hoist_vars_and_bindings(); + + writeln!(s, "# Phase 1").unwrap(); + writeln!(s, "```mermaid\n{}```", render_graph(&item_ids, analyzer.g)).unwrap(); + + analyzer.evaluate_immediate(&module, &eventual_ids); + + writeln!(s, "# Phase 2").unwrap(); + writeln!(s, "```mermaid\n{}```", render_graph(&item_ids, analyzer.g)).unwrap(); + + analyzer.evaluate_eventual(&module); + + writeln!(s, "# Phase 3").unwrap(); + writeln!(s, "```mermaid\n{}```", render_graph(&item_ids, analyzer.g)).unwrap(); + + analyzer.handle_exports(&module); + + writeln!(s, "# Phase 4").unwrap(); + writeln!(s, "```mermaid\n{}```", render_graph(&item_ids, analyzer.g)).unwrap(); + + let mut condensed = analyzer.g.finalize(analyzer.items); + + writeln!(s, "# Final").unwrap(); + writeln!( + s, + "```mermaid\n{}```", + render_mermaid(&mut condensed, &|buf:&Vec| format!("Items: {:?}", buf)) + ) + .unwrap(); + + let uri_of_module:JsWord = "entry.js".into(); + + let mut describe = + |is_debug:bool, title:&str, entries:Vec, skip_parts:bool| { + let mut g = analyzer.g.clone(); + g.handle_weak(if is_debug { Mode::Development } else { Mode::Production }); + let SplitModuleResult { modules, entrypoints, .. } = g.split_module(analyzer.items); + + writeln!(s, "# Entrypoints\n\n```\n{:#?}\n```\n\n", entrypoints).unwrap(); + + if !skip_parts { + writeln!(s, "# Modules ({})", if is_debug { "dev" } else { "prod" }).unwrap(); + for (i, module) in modules.iter().enumerate() { + writeln!(s, "## Part {}", i).unwrap(); + writeln!(s, "```js\n{}\n```", print(&cm, &[module])).unwrap(); + } + } + + let mut merger = Merger::new(SingleModuleLoader { + modules:&modules, + entry_module_uri:&uri_of_module, + }); + let mut entry = Module::dummy(); + + for e in &entries { + let key = match e { + ItemIdGroupKind::ModuleEvaluation => Key::ModuleEvaluation, + ItemIdGroupKind::Export(_, name) => Key::Export(name.as_str().into()), + }; + + let index = entrypoints[&key]; + entry.body.extend(modules[index as usize].body.clone()); + } + + let module = merger.merge_recursively(entry).unwrap(); + + writeln!(s, "## Merged ({})", title).unwrap(); + writeln!(s, "```js\n{}\n```", print(&cm, &[&module])).unwrap(); + }; + describe(true, "module eval", vec![ItemIdGroupKind::ModuleEvaluation], false); + describe(false, "module eval", vec![ItemIdGroupKind::ModuleEvaluation], false); + + for exports in config.exports { + describe( + false, + &exports.join(","), + exports + .into_iter() + .map(|e| ItemIdGroupKind::Export(((*e).into(), Default::default()), e.into())) + .collect(), + true, + ); + } + + NormalizedOutput::from(s) + .compare_to_file(input.with_file_name("output.md")) + .unwrap(); + + Ok(()) + }) + .unwrap(); +} + +struct SingleModuleLoader<'a> { + entry_module_uri:&'a str, + modules:&'a [Module], +} + +impl super::merge::Load for SingleModuleLoader<'_> { + fn load(&mut self, uri:&str, chunk_id:u32) -> Result, Error> { + if self.entry_module_uri == uri { + return Ok(Some(self.modules[chunk_id as usize].clone())); + } + + Ok(None) + } +} + +fn print(cm:&Arc, nodes:&[&N]) -> String { + let mut buf = vec![]; + + { + let mut emitter = swc_core::ecma::codegen::Emitter { + cfg:swc_core::ecma::codegen::Config::default() + .with_emit_assert_for_import_attributes(true), + cm:cm.clone(), + comments:None, + wr:Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None)), + }; + + for n in nodes { + n.emit_with(&mut emitter).unwrap(); + } + } + + String::from_utf8(buf).unwrap() +} + +fn render_graph(item_ids:&[ItemId], g:&mut DepGraph) -> String { + let mut mermaid = String::from("graph TD\n"); + + for id in item_ids.iter() { + let i = g.g.node(id); + + writeln!(mermaid, " Item{};", i + 1).unwrap(); + + if let Some(item_id) = render_item_id(id) { + writeln!(mermaid, " Item{}[\"{}\"];", i + 1, item_id).unwrap(); + } + } + + for (from, to, kind) in g.g.idx_graph.all_edges() { + writeln!( + mermaid, + " Item{} -{}-> Item{};", + from + 1, + match kind { + Dependency::Strong => "", + Dependency::Weak => ".", + }, + to + 1, + ) + .unwrap(); + } + + mermaid +} + +fn render_mermaid(g:&mut InternedGraph, render:&dyn Fn(&T) -> String) -> String +where + T: Clone + Eq + Hash, { + let mut mermaid = String::from("graph TD\n"); + let ix = g.graph_ix.clone(); + + for item in &ix { + let i = g.node(item); + + writeln!( + mermaid, + " N{}[\"{}\"];", + i, + render(item).replace([';', '\n'], "").replace('"', """) + ) + .unwrap(); + } + + for (from, to, kind) in g.idx_graph.all_edges() { + writeln!( + mermaid, + " N{} -{}-> N{};", + from, + match kind { + Dependency::Strong => "", + Dependency::Weak => ".", + }, + to, + ) + .unwrap(); + } + + mermaid +} + +fn render_item_id(id:&ItemId) -> Option { + match id { + ItemId::Group(ItemIdGroupKind::ModuleEvaluation) => Some("ModuleEvaluation".into()), + ItemId::Group(ItemIdGroupKind::Export(_, name)) => Some(format!("export {name}")), + _ => None, + } +} diff --git a/crates/turbopack-ecmascript/Source/tree_shake/util.rs b/crates/turbopack-ecmascript/Source/tree_shake/util.rs new file mode 100644 index 0000000000000..8faf023957d38 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/tree_shake/util.rs @@ -0,0 +1,250 @@ +use std::hash::BuildHasherDefault; + +use indexmap::IndexSet; +use rustc_hash::FxHasher; +use swc_core::{ + common::SyntaxContext, + ecma::{ + ast::{ + AssignTarget, + BlockStmtOrExpr, + Constructor, + ExportNamedSpecifier, + ExportSpecifier, + Expr, + Function, + Id, + Ident, + MemberExpr, + MemberProp, + NamedExport, + Pat, + PropName, + }, + visit::{Visit, VisitWith, noop_visit_type}, + }, +}; + +#[derive(Debug, Default, Clone, Copy)] +enum Mode { + Read, + #[default] + Write, +} + +#[derive(Default)] +struct Target { + direct:bool, + eventual:bool, +} + +/// A visitor which collects variables which are read or written. +#[derive(Default)] +pub(crate) struct IdentUsageCollector { + unresolved:SyntaxContext, + top_level:SyntaxContext, + vars:Vars, + + is_nested:bool, + target:Target, + /// None means both read and write + mode:Option, +} + +impl IdentUsageCollector { + fn with_nested(&mut self, f:impl FnOnce(&mut Self)) { + if !self.target.eventual { + return; + } + + let old = self.is_nested; + self.is_nested = true; + f(self); + self.is_nested = old; + } + + fn with_mode(&mut self, mode:Option, f:impl FnOnce(&mut Self)) { + let old = self.mode; + self.mode = mode; + f(self); + self.mode = old; + } +} + +impl Visit for IdentUsageCollector { + noop_visit_type!(); + + fn visit_assign_target(&mut self, n:&AssignTarget) { + self.with_mode(Some(Mode::Write), |this| { + n.visit_children_with(this); + }) + } + + fn visit_block_stmt_or_expr(&mut self, n:&BlockStmtOrExpr) { + self.with_nested(|this| { + n.visit_children_with(this); + }) + } + + fn visit_constructor(&mut self, n:&Constructor) { + self.with_nested(|this| { + n.visit_children_with(this); + }) + } + + fn visit_export_named_specifier(&mut self, n:&ExportNamedSpecifier) { n.orig.visit_with(self); } + + fn visit_export_specifier(&mut self, n:&ExportSpecifier) { + self.with_mode(Some(Mode::Read), |this| { + n.visit_children_with(this); + }) + } + + fn visit_expr(&mut self, e:&Expr) { + self.with_mode(Some(Mode::Read), |this| { + e.visit_children_with(this); + }) + } + + fn visit_function(&mut self, n:&Function) { + self.with_nested(|this| { + n.visit_children_with(this); + }) + } + + fn visit_ident(&mut self, n:&Ident) { + if !self.target.direct && !self.is_nested { + return; + } + + if n.span.ctxt == self.unresolved { + self.vars.found_unresolved = true; + return; + } + + // We allow SyntaxContext::empty() because Some built-in files do not go into + // resolver() + if n.span.ctxt != self.unresolved + && n.span.ctxt != self.top_level + && n.span.ctxt != SyntaxContext::empty() + { + return; + } + + match self.mode { + Some(Mode::Read) => { + self.vars.read.insert(n.to_id()); + }, + Some(Mode::Write) => { + self.vars.write.insert(n.to_id()); + }, + None => { + self.vars.read.insert(n.to_id()); + self.vars.write.insert(n.to_id()); + }, + } + } + + fn visit_member_expr(&mut self, e:&MemberExpr) { + self.with_mode(None, |this| { + // Skip visit_expr + e.obj.visit_children_with(this); + }); + + e.prop.visit_with(self); + } + + fn visit_member_prop(&mut self, n:&MemberProp) { + if let MemberProp::Computed(..) = n { + self.with_mode(Some(Mode::Read), |v| { + n.visit_children_with(v); + }) + } + } + + fn visit_named_export(&mut self, n:&NamedExport) { + if n.src.is_some() { + return; + } + + n.visit_children_with(self); + } + + fn visit_pat(&mut self, p:&Pat) { + self.with_mode(Some(Mode::Write), |this| { + p.visit_children_with(this); + }) + } + + fn visit_prop_name(&mut self, n:&PropName) { + if let PropName::Computed(..) = n { + n.visit_children_with(self); + } + } +} + +/// The list of variables which are read or written. +#[derive(Debug, Default)] +pub(crate) struct Vars { + /// Variables which are read. + pub read:IndexSet>, + /// Variables which are written. + pub write:IndexSet>, + + pub found_unresolved:bool, +} + +/// Returns `(read, write)` +/// +/// Note: This functions accept `SyntaxContext` to filter out variables which +/// are not interesting. We only need to analyze top-level variables. +pub(crate) fn ids_captured_by(n:&N, unresolved:SyntaxContext, top_level:SyntaxContext) -> Vars +where + N: VisitWith, { + let mut v = IdentUsageCollector { + unresolved, + top_level, + target:Target { direct:false, eventual:true }, + ..Default::default() + }; + n.visit_with(&mut v); + v.vars +} + +/// Returns `(read, write)` +/// +/// Note: This functions accept `SyntaxContext` to filter out variables which +/// are not interesting. We only need to analyze top-level variables. +pub(crate) fn ids_used_by(n:&N, unresolved:SyntaxContext, top_level:SyntaxContext) -> Vars +where + N: VisitWith, { + let mut v = IdentUsageCollector { + unresolved, + top_level, + target:Target { direct:true, eventual:true }, + ..Default::default() + }; + n.visit_with(&mut v); + v.vars +} + +/// Returns `(read, write)` +/// +/// Note: This functions accept `SyntaxContext` to filter out variables which +/// are not interesting. We only need to analyze top-level variables. +pub(crate) fn ids_used_by_ignoring_nested( + n:&N, + unresolved:SyntaxContext, + top_level:SyntaxContext, +) -> Vars +where + N: VisitWith, { + let mut v = IdentUsageCollector { + unresolved, + top_level, + target:Target { direct:true, eventual:false }, + ..Default::default() + }; + n.visit_with(&mut v); + v.vars +} diff --git a/crates/turbopack-ecmascript/Source/typescript/mod.rs b/crates/turbopack-ecmascript/Source/typescript/mod.rs new file mode 100644 index 0000000000000..f43f82c375a52 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/typescript/mod.rs @@ -0,0 +1,281 @@ +use anyhow::Result; +use serde_json::Value as JsonValue; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbo_tasks_fs::DirectoryContent; +use turbopack_core::{ + asset::{Asset, AssetContent}, + ident::AssetIdent, + issue::IssueSeverity, + module::Module, + raw_module::RawModule, + reference::{ModuleReference, ModuleReferences}, + reference_type::{CommonJsReferenceSubType, ReferenceType}, + resolve::{ + ModuleResolveResult, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + }, + source::Source, +}; +// TODO remove this +pub use turbopack_resolve::typescript as resolve; +use turbopack_resolve::{ + ecmascript::{apply_cjs_specific_options, cjs_resolve}, + typescript::{read_from_tsconfigs, read_tsconfigs, type_resolve}, +}; + +#[turbo_tasks::value] +pub struct TsConfigModuleAsset { + pub source:Vc>, + pub origin:Vc>, +} + +#[turbo_tasks::value_impl] +impl TsConfigModuleAsset { + #[turbo_tasks::function] + pub fn new(origin:Vc>, source:Vc>) -> Vc { + Self::cell(TsConfigModuleAsset { origin, source }) + } +} + +#[turbo_tasks::value_impl] +impl Module for TsConfigModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { self.source.ident() } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let mut references = Vec::new(); + let configs = read_tsconfigs( + self.source.content().file_content(), + self.source, + apply_cjs_specific_options(self.origin.resolve_options(Value::new( + ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined), + ))), + ) + .await?; + for (_, config_asset) in configs[1..].iter() { + references.push(Vc::upcast(TsExtendsReference::new(*config_asset))); + } + // ts-node options + { + let compiler = read_from_tsconfigs(&configs, |json, source| { + json["ts-node"]["compiler"].as_str().map(|s| (source, s.to_string())) + }) + .await?; + let compiler:RcStr = + compiler.map(|(_, c)| c).unwrap_or_else(|| "typescript".to_string()).into(); + references.push(Vc::upcast(CompilerReference::new( + self.origin, + Request::parse(Value::new(compiler.into())), + ))); + let require = read_from_tsconfigs(&configs, |json, source| { + if let JsonValue::Array(array) = &json["ts-node"]["require"] { + Some( + array + .iter() + .filter_map(|name| name.as_str().map(|s| (source, RcStr::from(s)))) + .collect::>(), + ) + } else { + None + } + }) + .await?; + if let Some(require) = require { + for (_, request) in require { + references.push(Vc::upcast(TsNodeRequireReference::new( + self.origin, + Request::parse(Value::new(request.into())), + ))); + } + } + } + // compilerOptions + { + let types = read_from_tsconfigs(&configs, |json, source| { + if let JsonValue::Array(array) = &json["compilerOptions"]["types"] { + Some( + array + .iter() + .filter_map(|name| name.as_str().map(|s| (source, RcStr::from(s)))) + .collect::>(), + ) + } else { + None + } + }) + .await?; + let types = if let Some(types) = types { + types + } else { + let mut all_types = Vec::new(); + let mut current = self.source.ident().path().parent().resolve().await?; + loop { + if let DirectoryContent::Entries(entries) = + &*current.join("node_modules/@types".into()).read_dir().await? + { + all_types.extend(entries.iter().filter_map(|(name, _)| { + if name.starts_with('.') { + None + } else { + Some((self.source, name.clone())) + } + })); + } + let parent = current.parent().resolve().await?; + if parent == current { + break; + } + current = parent; + } + all_types + }; + for (_, name) in types { + references.push(Vc::upcast(TsConfigTypesReference::new( + self.origin, + Request::module( + name, + Value::new(RcStr::default().into()), + Vc::::default(), + Vc::::default(), + ), + ))); + } + } + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for TsConfigModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct CompilerReference { + pub origin:Vc>, + pub request:Vc, +} + +#[turbo_tasks::value_impl] +impl CompilerReference { + #[turbo_tasks::function] + pub fn new(origin:Vc>, request:Vc) -> Vc { + Self::cell(CompilerReference { origin, request }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for CompilerReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + cjs_resolve(self.origin, self.request, None, IssueSeverity::Error.cell()) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for CompilerReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("compiler reference {}", self.request.to_string().await?).into(), + )) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct TsExtendsReference { + pub config:Vc>, +} + +#[turbo_tasks::value_impl] +impl TsExtendsReference { + #[turbo_tasks::function] + pub fn new(config:Vc>) -> Vc { Self::cell(TsExtendsReference { config }) } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for TsExtendsReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + ModuleResolveResult::module(Vc::upcast(RawModule::new(Vc::upcast(self.config)))).cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for TsExtendsReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("tsconfig extends {}", self.config.ident().to_string().await?,).into(), + )) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct TsNodeRequireReference { + pub origin:Vc>, + pub request:Vc, +} + +#[turbo_tasks::value_impl] +impl TsNodeRequireReference { + #[turbo_tasks::function] + pub fn new(origin:Vc>, request:Vc) -> Vc { + Self::cell(TsNodeRequireReference { origin, request }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for TsNodeRequireReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + cjs_resolve(self.origin, self.request, None, IssueSeverity::Error.cell()) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for TsNodeRequireReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("tsconfig tsnode require {}", self.request.to_string().await?).into(), + )) + } +} + +#[turbo_tasks::value] +#[derive(Hash, Debug)] +pub struct TsConfigTypesReference { + pub origin:Vc>, + pub request:Vc, +} + +#[turbo_tasks::value_impl] +impl TsConfigTypesReference { + #[turbo_tasks::function] + pub fn new(origin:Vc>, request:Vc) -> Vc { + Self::cell(TsConfigTypesReference { origin, request }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for TsConfigTypesReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + type_resolve(self.origin, self.request) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for TsConfigTypesReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("tsconfig types {}", self.request.to_string().await?,).into())) + } +} diff --git a/crates/turbopack-ecmascript/Source/utils.rs b/crates/turbopack-ecmascript/Source/utils.rs new file mode 100644 index 0000000000000..f8c11f5621abc --- /dev/null +++ b/crates/turbopack-ecmascript/Source/utils.rs @@ -0,0 +1,122 @@ +use serde::Serialize; +use swc_core::{ + common::DUMMY_SP, + ecma::ast::{Expr, Lit, Str}, +}; +use turbopack_core::{chunk::ModuleId, resolve::pattern::Pattern}; + +use crate::analyzer::{ConstantNumber, ConstantValue, JsValue}; + +pub fn unparen(expr:&Expr) -> &Expr { + if let Some(expr) = expr.as_paren() { + return unparen(&expr.expr); + } + if let Expr::Seq(seq) = expr { + return unparen(seq.exprs.last().unwrap()); + } + expr +} + +pub fn js_value_to_pattern(value:&JsValue) -> Pattern { + let mut result = match value { + JsValue::Constant(v) => { + Pattern::Constant(match v { + ConstantValue::Str(str) => str.as_str().into(), + ConstantValue::True => "true".into(), + ConstantValue::False => "false".into(), + ConstantValue::Null => "null".into(), + ConstantValue::Num(ConstantNumber(n)) => n.to_string().into(), + ConstantValue::BigInt(n) => n.to_string().into(), + ConstantValue::Regex(exp, flags) => format!("/{exp}/{flags}").into(), + ConstantValue::Undefined => "undefined".into(), + }) + }, + JsValue::Alternatives(_, alts) => { + Pattern::Alternatives(alts.iter().map(js_value_to_pattern).collect()) + }, + JsValue::Concat(_, parts) => { + Pattern::Concatenation(parts.iter().map(js_value_to_pattern).collect()) + }, + JsValue::Add(..) => { + // TODO do we need to handle that here + // or is that already covered by normalization of JsValue + Pattern::Dynamic + }, + _ => Pattern::Dynamic, + }; + result.normalize(); + result +} + +pub fn module_id_to_lit(module_id:&ModuleId) -> Expr { + Expr::Lit(match module_id { + ModuleId::Number(n) => Lit::Num((*n as f64).into()), + ModuleId::String(s) => Lit::Str(Str { span:DUMMY_SP, value:(s as &str).into(), raw:None }), + }) +} + +pub struct StringifyJs<'a, T>(pub &'a T) +where + T: ?Sized; + +impl<'a, T> std::fmt::Display for StringifyJs<'a, T> +where + T: Serialize + ?Sized, +{ + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// [`std::fmt::Formatter`] does not implement [`std::io::Write`], + /// so we need to wrap it in a struct that does. + struct DisplayWriter<'a, 'b> { + f:&'a mut std::fmt::Formatter<'b>, + } + + impl<'a, 'b> std::io::Write for DisplayWriter<'a, 'b> { + fn write(&mut self, bytes:&[u8]) -> std::result::Result { + self.f + .write_str( + std::str::from_utf8(bytes) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?, + ) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?; + Ok(bytes.len()) + } + + fn flush(&mut self) -> std::result::Result<(), std::io::Error> { unreachable!() } + } + + let to_writer = match f.alternate() { + true => serde_json::to_writer_pretty, + false => serde_json::to_writer, + }; + + to_writer(DisplayWriter { f }, self.0).map_err(|_err| std::fmt::Error) + } +} + +pub struct FormatIter T>(pub F); + +macro_rules! format_iter { + ($trait:path) => { + impl T> $trait for FormatIter + where + T::Item: $trait, + { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for item in self.0() { + item.fmt(f)?; + } + Ok(()) + } + } + }; +} + +format_iter!(std::fmt::Binary); +format_iter!(std::fmt::Debug); +format_iter!(std::fmt::Display); +format_iter!(std::fmt::LowerExp); +format_iter!(std::fmt::LowerHex); +format_iter!(std::fmt::Octal); +format_iter!(std::fmt::Pointer); +format_iter!(std::fmt::UpperExp); +format_iter!(std::fmt::UpperHex); diff --git a/crates/turbopack-ecmascript/Source/webpack/mod.rs b/crates/turbopack-ecmascript/Source/webpack/mod.rs new file mode 100644 index 0000000000000..9ceb796157da7 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/webpack/mod.rs @@ -0,0 +1,188 @@ +use anyhow::Result; +use swc_core::ecma::ast::Lit; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + file_source::FileSource, + ident::AssetIdent, + module::Module, + reference::{ModuleReference, ModuleReferences}, + reference_type::{CommonJsReferenceSubType, ReferenceType}, + resolve::{ + ModuleResolveResult, + ModuleResolveResultItem, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + resolve, + }, + source::Source, +}; +use turbopack_resolve::ecmascript::apply_cjs_specific_options; + +use self::{parse::WebpackRuntime, references::module_references}; +use crate::EcmascriptInputTransforms; + +pub mod parse; +pub(crate) mod references; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("webpack".into()) } + +#[turbo_tasks::value] +pub struct WebpackModuleAsset { + pub source:Vc>, + pub runtime:Vc, + pub transforms:Vc, +} + +#[turbo_tasks::value_impl] +impl WebpackModuleAsset { + #[turbo_tasks::function] + pub fn new( + source:Vc>, + runtime:Vc, + transforms:Vc, + ) -> Vc { + Self::cell(WebpackModuleAsset { source, runtime, transforms }) + } +} + +#[turbo_tasks::value_impl] +impl Module for WebpackModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { self.source.ident().with_modifier(modifier()) } + + #[turbo_tasks::function] + fn references(&self) -> Vc { + module_references(self.source, self.runtime, self.transforms) + } +} + +#[turbo_tasks::value_impl] +impl Asset for WebpackModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value(shared)] +pub struct WebpackChunkAssetReference { + #[turbo_tasks(trace_ignore)] + pub chunk_id:Lit, + pub runtime:Vc, + pub transforms:Vc, +} + +#[turbo_tasks::value_impl] +impl ModuleReference for WebpackChunkAssetReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Result> { + let runtime = self.runtime.await?; + Ok(match &*runtime { + WebpackRuntime::Webpack5 { chunk_request_expr: _, context_path } => { + // TODO determine filename from chunk_request_expr + let chunk_id = match &self.chunk_id { + Lit::Str(str) => str.value.to_string(), + Lit::Num(num) => format!("{num}"), + _ => todo!(), + }; + let filename = format!("./chunks/{}.js", chunk_id).into(); + let source = Vc::upcast(FileSource::new(context_path.join(filename))); + + ModuleResolveResult::module(Vc::upcast(WebpackModuleAsset::new( + source, + self.runtime, + self.transforms, + ))) + .into() + }, + WebpackRuntime::None => ModuleResolveResult::unresolveable().into(), + }) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for WebpackChunkAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + let chunk_id = match &self.chunk_id { + Lit::Str(str) => str.value.to_string(), + Lit::Num(num) => format!("{num}"), + _ => todo!(), + }; + Ok(Vc::cell(format!("webpack chunk {}", chunk_id).into())) + } +} + +#[turbo_tasks::value(shared)] +pub struct WebpackEntryAssetReference { + pub source:Vc>, + pub runtime:Vc, + pub transforms:Vc, +} + +#[turbo_tasks::value_impl] +impl ModuleReference for WebpackEntryAssetReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + ModuleResolveResult::module(Vc::upcast(WebpackModuleAsset::new( + self.source, + self.runtime, + self.transforms, + ))) + .into() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for WebpackEntryAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { Ok(Vc::cell("webpack entry".into())) } +} + +#[turbo_tasks::value(shared)] +pub struct WebpackRuntimeAssetReference { + pub origin:Vc>, + pub request:Vc, + pub runtime:Vc, + pub transforms:Vc, +} + +#[turbo_tasks::value_impl] +impl ModuleReference for WebpackRuntimeAssetReference { + #[turbo_tasks::function] + async fn resolve_reference(&self) -> Result> { + let ty = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)); + let options = self.origin.resolve_options(ty.clone()); + + let options = apply_cjs_specific_options(options); + + let resolved = resolve( + self.origin.origin_path().parent().resolve().await?, + Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)), + self.request, + options, + ); + + Ok(resolved + .await? + .map_module(|source| { + async move { + Ok(ModuleResolveResultItem::Module(Vc::upcast(WebpackModuleAsset::new( + source, + self.runtime, + self.transforms, + )))) + } + }) + .await? + .cell()) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for WebpackRuntimeAssetReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("webpack {}", self.request.to_string().await?,).into())) + } +} diff --git a/crates/turbopack-ecmascript/Source/webpack/parse.rs b/crates/turbopack-ecmascript/Source/webpack/parse.rs new file mode 100644 index 0000000000000..59b61032c3d85 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/webpack/parse.rs @@ -0,0 +1,241 @@ +use std::borrow::Cow; + +use anyhow::Result; +use swc_core::{ + common::GLOBALS, + ecma::{ + ast::{ + ArrowExpr, + AssignOp, + AssignTarget, + BinExpr, + BinaryOp, + CallExpr, + Callee, + Expr, + ExprOrSpread, + ExprStmt, + FnExpr, + Lit, + Module, + ModuleItem, + Program, + Script, + SimpleAssignTarget, + Stmt, + }, + visit::{Visit, VisitWith}, + }, +}; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::source::Source; + +use crate::{ + EcmascriptInputTransforms, + EcmascriptModuleAssetType, + analyzer::{JsValue, graph::EvalContext}, + parse::{ParseResult, parse}, + utils::unparen, +}; + +#[turbo_tasks::value(shared, serialization = "none")] +#[derive(Debug)] +pub enum WebpackRuntime { + Webpack5 { + /// There is a [JsValue]::FreeVar("chunkId") that need to be replaced + /// before converting to string + #[turbo_tasks(trace_ignore)] + chunk_request_expr:JsValue, + context_path:Vc, + }, + None, +} + +fn iife(stmt:&Stmt) -> Option<&Vec> { + if let Stmt::Expr(ExprStmt { expr, .. }) = &stmt { + if let Expr::Call(CallExpr { callee: Callee::Expr(callee), args, .. }) = unparen(expr) { + if !args.is_empty() { + return None; + } + return get_fn_body(callee); + } + } + None +} + +fn program_iife(program:&Program) -> Option<&Vec> { + match program { + Program::Module(Module { body, .. }) => { + if let [ModuleItem::Stmt(stmt)] = &body[..] { + return iife(stmt); + } + }, + Program::Script(Script { body, .. }) => { + if let [stmt] = &body[..] { + return iife(stmt); + } + }, + } + None +} + +fn is_webpack_require_decl(stmt:&Stmt) -> bool { + if let Some(decl) = stmt.as_decl() { + if let Some(fn_decl) = decl.as_fn_decl() { + return &*fn_decl.ident.sym == "__webpack_require__"; + } + } + false +} + +fn get_assign_target_identifier(expr:&AssignTarget) -> Option> { + match expr.as_simple()? { + SimpleAssignTarget::Ident(ident) => Some(Cow::Borrowed(&*ident.sym)), + SimpleAssignTarget::Member(member) => { + if let Some(obj_name) = get_expr_identifier(&member.obj) { + if let Some(ident) = member.prop.as_ident() { + return Some(Cow::Owned(obj_name.into_owned() + "." + &*ident.sym)); + } + } + None + }, + SimpleAssignTarget::Paren(p) => get_expr_identifier(&p.expr), + + _ => None, + } +} + +fn get_expr_identifier(expr:&Expr) -> Option> { + let expr = unparen(expr); + if let Some(ident) = expr.as_ident() { + return Some(Cow::Borrowed(&*ident.sym)); + } + if let Some(member) = expr.as_member() { + if let Some(ident) = member.prop.as_ident() { + if let Some(obj_name) = get_expr_identifier(&member.obj) { + return Some(Cow::Owned(obj_name.into_owned() + "." + &*ident.sym)); + } + } + } + None +} + +fn get_assignment<'a>(stmts:&'a Vec, property:&str) -> Option<&'a Expr> { + for stmt in stmts { + if let Some(stmts) = iife(stmt) { + if let Some(result) = get_assignment(stmts, property) { + return Some(result); + } + } + if let Some(expr_stmt) = stmt.as_expr() { + if let Some(assign) = unparen(&expr_stmt.expr).as_assign() { + if assign.op == AssignOp::Assign { + if let Some(name) = get_assign_target_identifier(&assign.left) { + if name == property { + return Some(unparen(&assign.right)); + } + } + } + } + } + } + None +} + +fn get_fn_body(expr:&Expr) -> Option<&Vec> { + let expr = unparen(expr); + if let Some(FnExpr { function, .. }) = expr.as_fn_expr() { + if let Some(body) = &function.body { + return Some(&body.stmts); + } + } + if let Some(ArrowExpr { body, .. }) = expr.as_arrow() { + if let Some(block) = body.as_block_stmt() { + return Some(&block.stmts); + } + } + None +} + +fn get_javascript_chunk_filename(stmts:&Vec, eval_context:&EvalContext) -> Option { + if let Some(expr) = get_assignment(stmts, "__webpack_require__.u") { + if let Some(stmts) = get_fn_body(expr) { + if let Some(ret) = stmts.iter().find_map(|stmt| stmt.as_return_stmt()) { + if let Some(expr) = &ret.arg { + return Some(eval_context.eval(expr)); + } + } + } + } + None +} + +struct RequirePrefixVisitor { + result:Option, +} + +impl Visit for RequirePrefixVisitor { + fn visit_call_expr(&mut self, call:&CallExpr) { + if let Some(expr) = call.callee.as_expr() { + if let Some(name) = get_expr_identifier(expr) { + if name == "require" { + if let [ExprOrSpread { spread: None, expr }] = &call.args[..] { + if let Some(BinExpr { op: BinaryOp::Add, left, .. }) = expr.as_bin() { + self.result = left.as_lit().cloned(); + return; + } + } + } + } + } + call.visit_children_with(self); + } +} + +fn get_require_prefix(stmts:&Vec) -> Option { + if let Some(expr) = get_assignment(stmts, "__webpack_require__.f.require") { + let mut visitor = RequirePrefixVisitor { result:None }; + expr.visit_children_with(&mut visitor); + return visitor.result; + } + None +} + +#[turbo_tasks::function] +pub async fn webpack_runtime( + source:Vc>, + transforms:Vc, +) -> Result> { + let parsed = + parse(source, Value::new(EcmascriptModuleAssetType::Ecmascript), transforms).await?; + match &*parsed { + ParseResult::Ok { program, eval_context, globals, .. } => { + if let Some(stmts) = program_iife(program) { + if stmts.iter().any(is_webpack_require_decl) { + // extract webpack/runtime/get javascript chunk filename + let chunk_filename = + GLOBALS.set(globals, || get_javascript_chunk_filename(stmts, eval_context)); + + let prefix_path = get_require_prefix(stmts); + + if let (Some(chunk_filename), Some(prefix_path)) = (chunk_filename, prefix_path) + { + let value = JsValue::concat(vec![ + JsValue::Constant(prefix_path.into()), + chunk_filename, + ]); + + return Ok(WebpackRuntime::Webpack5 { + chunk_request_expr:value, + context_path:source.ident().path().parent().resolve().await?, + } + .into()); + } + } + } + }, + ParseResult::Unparseable { .. } | ParseResult::NotFound => {}, + } + Ok(WebpackRuntime::None.into()) +} diff --git a/crates/turbopack-ecmascript/Source/webpack/references.rs b/crates/turbopack-ecmascript/Source/webpack/references.rs new file mode 100644 index 0000000000000..23e543d802247 --- /dev/null +++ b/crates/turbopack-ecmascript/Source/webpack/references.rs @@ -0,0 +1,82 @@ +use anyhow::Result; +use swc_core::{ + common::errors::{HANDLER, Handler}, + ecma::{ + ast::{CallExpr, Expr, ExprOrSpread}, + visit::{Visit, VisitWith}, + }, +}; +use turbo_tasks::{Value, Vc}; +use turbopack_core::{ + reference::{ModuleReference, ModuleReferences}, + source::Source, +}; +use turbopack_swc_utils::emitter::IssueEmitter; + +use super::{WebpackChunkAssetReference, parse::WebpackRuntime}; +use crate::{ + EcmascriptInputTransforms, + EcmascriptModuleAssetType, + parse::{ParseResult, parse}, +}; + +#[turbo_tasks::function] +pub async fn module_references( + source:Vc>, + runtime:Vc, + transforms:Vc, +) -> Result> { + let parsed = + parse(source, Value::new(EcmascriptModuleAssetType::Ecmascript), transforms).await?; + match &*parsed { + ParseResult::Ok { program, source_map, .. } => { + let mut references = Vec::new(); + let mut visitor = + ModuleReferencesVisitor { references:&mut references, runtime, transforms }; + let handler = Handler::with_emitter( + true, + false, + Box::new(IssueEmitter::new( + source, + source_map.clone(), + Some("Parsing webpack bundle failed".into()), + )), + ); + HANDLER.set(&handler, || { + program.visit_with(&mut visitor); + }); + Ok(Vc::cell(references)) + }, + ParseResult::Unparseable { .. } | ParseResult::NotFound => Ok(Vc::cell(Vec::new())), + } +} + +struct ModuleReferencesVisitor<'a> { + runtime:Vc, + references:&'a mut Vec>>, + transforms:Vc, +} + +impl<'a> Visit for ModuleReferencesVisitor<'a> { + fn visit_call_expr(&mut self, call:&CallExpr) { + if let Some(member) = call.callee.as_expr().and_then(|e| e.as_member()) { + if let (Some(obj), Some(prop)) = (member.obj.as_ident(), member.prop.as_ident()) { + if &*obj.sym == "__webpack_require__" && &*prop.sym == "e" { + if let [ExprOrSpread { spread: None, expr }] = &call.args[..] { + if let Expr::Lit(lit) = &**expr { + self.references.push(Vc::upcast( + WebpackChunkAssetReference { + chunk_id:lit.clone(), + runtime:self.runtime, + transforms:self.transforms, + } + .cell(), + )); + } + } + } + } + } + call.visit_children_with(self); + } +} diff --git a/crates/turbopack-ecmascript/benches/analyzer.rs b/crates/turbopack-ecmascript/benches/analyzer.rs new file mode 100644 index 0000000000000..cb3b112a6fcf0 --- /dev/null +++ b/crates/turbopack-ecmascript/benches/analyzer.rs @@ -0,0 +1,116 @@ +use std::{fs, path::PathBuf, sync::Arc, time::Duration}; + +use criterion::{Bencher, BenchmarkId, Criterion}; +use swc_core::{ + common::{FilePathMapping, GLOBALS, Mark, SourceMap}, + ecma::{ + ast::{EsVersion, Program}, + parser::parse_file_as_program, + transforms::base::resolver, + visit::VisitMutWith, + }, +}; +use turbo_tasks::Value; +use turbo_tasks_testing::VcStorage; +use turbopack_core::{ + compile_time_info::CompileTimeInfo, + environment::{Environment, ExecutionEnvironment, NodeJsEnvironment}, + target::CompileTarget, +}; +use turbopack_ecmascript::analyzer::{ + graph::{EvalContext, VarGraph, create_graph}, + linker::link, + test_utils::{early_visitor, visitor}, +}; + +pub fn benchmark(c:&mut Criterion) { + turbopack_ecmascript::register(); + + let tests_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/analyzer/graph"); + let results = fs::read_dir(tests_dir).unwrap(); + + let mut group = c.benchmark_group("analyzer"); + group.warm_up_time(Duration::from_secs(1)); + group.measurement_time(Duration::from_secs(3)); + + for result in results { + let entry = result.unwrap(); + if entry.file_type().unwrap().is_dir() { + let name = entry.file_name().into_string().unwrap(); + let input = entry.path().join("input.js"); + + let cm = Arc::new(SourceMap::new(FilePathMapping::empty())); + let fm = cm.load_file(&input).unwrap(); + GLOBALS.set(&swc_core::common::Globals::new(), || { + let mut program = parse_file_as_program( + &fm, + Default::default(), + EsVersion::latest(), + None, + &mut vec![], + ) + .unwrap(); + + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + program.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false)); + + let eval_context = + EvalContext::new(&program, unresolved_mark, top_level_mark, false, None); + let var_graph = create_graph(&program, &eval_context); + + let input = BenchInput { program, eval_context, var_graph }; + + group.bench_with_input( + BenchmarkId::new("create_graph", &name), + &input, + bench_create_graph, + ); + group.bench_with_input(BenchmarkId::new("link", &name), &input, bench_link); + }); + } + } +} + +struct BenchInput { + program:Program, + eval_context:EvalContext, + var_graph:VarGraph, +} + +fn bench_create_graph(b:&mut Bencher, input:&BenchInput) { + b.iter(|| create_graph(&input.program, &input.eval_context)); +} + +fn bench_link(b:&mut Bencher, input:&BenchInput) { + let rt = tokio::runtime::Builder::new_current_thread().build().unwrap(); + + b.to_async(rt).iter(|| { + async { + for val in input.var_graph.values.values() { + VcStorage::with(async { + let compile_time_info = CompileTimeInfo::builder(Environment::new(Value::new( + ExecutionEnvironment::NodeJsLambda( + NodeJsEnvironment { + compile_target:CompileTarget::unknown(), + ..Default::default() + } + .into(), + ), + ))) + .cell(); + link( + &input.var_graph, + val.clone(), + &early_visitor, + &(|val| visitor(val, compile_time_info)), + Default::default(), + ) + .await + }) + .await + .unwrap(); + } + } + }); +} diff --git a/crates/turbopack-ecmascript/benches/mod.rs b/crates/turbopack-ecmascript/benches/mod.rs new file mode 100644 index 0000000000000..48208446e41e4 --- /dev/null +++ b/crates/turbopack-ecmascript/benches/mod.rs @@ -0,0 +1,6 @@ +use criterion::{criterion_group, criterion_main}; + +mod analyzer; + +criterion_group!(analyzer_benches, analyzer::benchmark); +criterion_main!(analyzer_benches); diff --git a/crates/turbopack-ecmascript/build.rs b/crates/turbopack-ecmascript/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-ecmascript/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-env/Source/asset.rs b/crates/turbopack-env/Source/asset.rs new file mode 100644 index 0000000000000..facc559769ac6 --- /dev/null +++ b/crates/turbopack-env/Source/asset.rs @@ -0,0 +1,62 @@ +use std::io::Write; + +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{File, FileSystemPath, rope::RopeBuilder}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + ident::AssetIdent, + source::Source, +}; +use turbopack_ecmascript::utils::StringifyJs; + +/// The `process.env` asset, responsible for initializing the env (shared by all +/// chunks) during app startup. +#[turbo_tasks::value] +pub struct ProcessEnvAsset { + /// The root path which we can construct our env asset path. + root:Vc, + + /// A HashMap filled with the env key/values. + env:Vc>, +} + +#[turbo_tasks::value_impl] +impl ProcessEnvAsset { + #[turbo_tasks::function] + pub fn new(root:Vc, env:Vc>) -> Vc { + ProcessEnvAsset { root, env }.cell() + } +} + +#[turbo_tasks::value_impl] +impl Source for ProcessEnvAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { AssetIdent::from_path(self.root.join(".env.js".into())) } +} + +#[turbo_tasks::value_impl] +impl Asset for ProcessEnvAsset { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let env = self.env.read_all().await?; + + // TODO: In SSR, we use the native process.env, which can only contain string + // values. We need to inject literal values (to emulate webpack's + // DefinePlugin), so create a new regular object out of the old env. + let mut code = RopeBuilder::default(); + code += "const env = process.env = {...process.env};\n\n"; + + for (name, val) in &*env { + // It's assumed the env has passed through an EmbeddableProcessEnv, so the value + // is ready to be directly embedded. Values _after_ an embeddable + // env can be used to inject live code into the output. + // TODO this is not completely correct as env vars need to ignore casing + // So `process.env.path === process.env.PATH === process.env.PaTh` + writeln!(code, "env[{}] = {};", StringifyJs(name), val)?; + } + + Ok(AssetContent::file(File::from(code.build()).into())) + } +} diff --git a/crates/turbopack-env/Source/dotenv.rs b/crates/turbopack-env/Source/dotenv.rs new file mode 100644 index 0000000000000..cabf04705b5b8 --- /dev/null +++ b/crates/turbopack-env/Source/dotenv.rs @@ -0,0 +1,40 @@ +use anyhow::Result; +use indexmap::indexmap; +use turbo_tasks::Vc; +use turbo_tasks_env::{CommandLineProcessEnv, CustomProcessEnv, ProcessEnv}; +use turbo_tasks_fs::FileSystemPath; + +use crate::TryDotenvProcessEnv; + +/// Loads a series of dotenv files according to the precedence rules set by +/// https://nextjs.org/docs/basic-features/environment-variables#environment-variable-load-order +#[turbo_tasks::function] +pub async fn load_env(project_path:Vc) -> Result>> { + let env:Vc> = Vc::upcast(CommandLineProcessEnv::new()); + + let node_env = env.read("NODE_ENV".into()).await?; + let node_env = node_env.as_deref().unwrap_or("development"); + + let env = Vc::upcast(CustomProcessEnv::new( + env, + Vc::cell(indexmap! { + "NODE_ENV".into() => node_env.into(), + }), + )); + + let files = [ + Some(format!(".env.{node_env}.local")), + if node_env == "test" { None } else { Some(".env.local".into()) }, + Some(format!(".env.{node_env}")), + Some(".env".into()), + ] + .into_iter() + .flatten(); + + let env = files.fold(env, |prior, f| { + let path = project_path.join(f.into()); + Vc::upcast(TryDotenvProcessEnv::new(prior, path)) + }); + + Ok(env) +} diff --git a/crates/turbopack-env/Source/embeddable.rs b/crates/turbopack-env/Source/embeddable.rs new file mode 100644 index 0000000000000..ac1213f2667f3 --- /dev/null +++ b/crates/turbopack-env/Source/embeddable.rs @@ -0,0 +1,39 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_env::{EnvMap, ProcessEnv}; +use turbopack_ecmascript::utils::StringifyJs; + +/// Encodes values as JS strings so that they can be safely injected into a JS +/// output. +#[turbo_tasks::value] +pub struct EmbeddableProcessEnv { + prior:Vc>, +} + +#[turbo_tasks::value_impl] +impl EmbeddableProcessEnv { + #[turbo_tasks::function] + pub fn new(prior:Vc>) -> Vc { EmbeddableProcessEnv { prior }.cell() } +} + +#[turbo_tasks::value_impl] +impl ProcessEnv for EmbeddableProcessEnv { + #[turbo_tasks::function] + async fn read_all(&self) -> Result> { + let prior = self.prior.read_all().await?; + + let encoded = prior + .iter() + .map(|(k, v)| (k.clone(), StringifyJs(v).to_string().into())) + .collect(); + + Ok(Vc::cell(encoded)) + } + + #[turbo_tasks::function] + async fn read(&self, name:RcStr) -> Result>> { + let prior = self.prior.read(name).await?; + let encoded = prior.as_deref().map(|s| StringifyJs(s).to_string()).map(RcStr::from); + Ok(Vc::cell(encoded)) + } +} diff --git a/crates/turbopack-env/Source/issue.rs b/crates/turbopack-env/Source/issue.rs new file mode 100644 index 0000000000000..3f2e448dffb2f --- /dev/null +++ b/crates/turbopack-env/Source/issue.rs @@ -0,0 +1,27 @@ +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueStage, OptionStyledString, StyledString}; + +/// An issue that occurred while resolving the parsing or evaluating the .env. +#[turbo_tasks::value(shared)] +pub struct ProcessEnvIssue { + pub path:Vc, + pub description:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for ProcessEnvIssue { + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Error loading dotenv file".into()).cell() + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Load.into() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.path } + + #[turbo_tasks::function] + fn description(&self) -> Vc { Vc::cell(Some(self.description)) } +} diff --git a/crates/turbopack-env/Source/lib.rs b/crates/turbopack-env/Source/lib.rs new file mode 100644 index 0000000000000..cbe20d0f2074d --- /dev/null +++ b/crates/turbopack-env/Source/lib.rs @@ -0,0 +1,34 @@ +//! Environment Variable support for turbopack. +//! +//! Environment variables can come from multiple sources, including the rust +//! process's env (immutable and by passing `FOO=BAR` keys when executing the +//! turbopack binary) or loaded via dotenv files. +//! +//! Dotenv file loading is a chain. Dotenv files that come first in the chain +//! have higher priority to define a environment variable (later dotenv files +//! cannot override it). Later dotenv files can reference variables prior +//! defined variables. + +#![feature(async_closure)] +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +mod asset; +pub mod dotenv; +mod embeddable; +mod issue; +mod try_env; + +pub use asset::ProcessEnvAsset; +pub use embeddable::EmbeddableProcessEnv; +pub use issue::ProcessEnvIssue; +pub use try_env::TryDotenvProcessEnv; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbo_tasks_env::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-env/Source/try_env.rs b/crates/turbopack-env/Source/try_env.rs new file mode 100644 index 0000000000000..1a28745f77025 --- /dev/null +++ b/crates/turbopack-env/Source/try_env.rs @@ -0,0 +1,56 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_env::{DotenvProcessEnv, EnvMap, ProcessEnv}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{IssueExt, StyledString}; + +use crate::ProcessEnvIssue; + +#[turbo_tasks::value] +pub struct TryDotenvProcessEnv { + dotenv:Vc, + prior:Vc>, + path:Vc, +} + +#[turbo_tasks::value_impl] +impl TryDotenvProcessEnv { + #[turbo_tasks::function] + pub fn new(prior:Vc>, path:Vc) -> Vc { + let dotenv = DotenvProcessEnv::new(Some(prior), path); + TryDotenvProcessEnv { dotenv, prior, path }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ProcessEnv for TryDotenvProcessEnv { + #[turbo_tasks::function] + async fn read_all(&self) -> Result> { + let dotenv = self.dotenv; + let prior = dotenv.read_prior(); + + // Ensure prior succeeds. If it doesn't, then we don't want to attempt to read + // the dotenv file (and potentially emit an Issue), just trust that the prior + // will have emitted its own. + prior.await?; + + let vars = dotenv.read_all_with_prior(prior); + match vars.await { + Ok(_) => Ok(vars), + Err(e) => { + // If parsing the dotenv file fails (but getting the prior value didn't), then + // we want to emit an Issue and fall back to the prior's read. + ProcessEnvIssue { + path:self.path, + // read_all_with_prior will wrap a current error with a context containing the + // failing file, which we don't really care about (we report the filepath as the + // Issue context, not the description). So extract the real error. + description:StyledString::Text(e.root_cause().to_string().into()).cell(), + } + .cell() + .emit(); + Ok(prior) + }, + } + } +} diff --git a/crates/turbopack-env/build.rs b/crates/turbopack-env/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-env/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-image/Source/lib.rs b/crates/turbopack-image/Source/lib.rs new file mode 100644 index 0000000000000..3a2cf56f1e8b2 --- /dev/null +++ b/crates/turbopack-image/Source/lib.rs @@ -0,0 +1,10 @@ +#![feature(arbitrary_self_types)] + +pub mod process; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-image/Source/process/SVG_LICENSE b/crates/turbopack-image/Source/process/SVG_LICENSE new file mode 100644 index 0000000000000..1341a90d565fa --- /dev/null +++ b/crates/turbopack-image/Source/process/SVG_LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright © 2017 Aditya Yadav, http://netroy.in + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Softwareâ€), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/crates/turbopack-image/Source/process/mod.rs b/crates/turbopack-image/Source/process/mod.rs new file mode 100644 index 0000000000000..9188300064605 --- /dev/null +++ b/crates/turbopack-image/Source/process/mod.rs @@ -0,0 +1,505 @@ +pub mod svg; + +use std::{io::Cursor, str::FromStr}; + +use anyhow::{Context, Result, bail}; +use base64::{display::Base64Display, engine::general_purpose::STANDARD}; +use image::{ + DynamicImage, + GenericImageView, + ImageEncoder, + ImageFormat, + codecs::{ + bmp::BmpEncoder, + ico::IcoEncoder, + jpeg::JpegEncoder, + png::{CompressionType, PngEncoder}, + }, + imageops::FilterType, +}; +use mime::Mime; +use serde::{Deserialize, Serialize}; +use serde_with::{DisplayFromStr, serde_as}; +use turbo_tasks::{Vc, debug::ValueDebugFormat, trace::TraceRawVcs}; +use turbo_tasks_fs::{File, FileContent, FileSystemPath}; +use turbopack_core::{ + error::PrettyPrintError, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, +}; + +use self::svg::calculate; + +/// Small placeholder version of the image. +#[derive(PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat)] +pub struct BlurPlaceholder { + pub data_url:String, + pub width:u32, + pub height:u32, +} + +impl BlurPlaceholder { + pub fn fallback() -> Self { + BlurPlaceholder { + data_url:"data:image/gif;base64,R0lGODlhAQABAIAAAP///\ + wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" + .to_string(), + width:1, + height:1, + } + } +} + +/// Gathered meta information about an image. +#[allow(clippy::manual_non_exhaustive)] +#[serde_as] +#[turbo_tasks::value] +#[derive(Default)] +#[non_exhaustive] +pub struct ImageMetaData { + pub width:u32, + pub height:u32, + #[turbo_tasks(trace_ignore, debug_ignore)] + #[serde_as(as = "Option")] + pub mime_type:Option, + pub blur_placeholder:Option, +} + +impl ImageMetaData { + pub fn fallback_value(mime_type:Option) -> Self { + ImageMetaData { + width:100, + height:100, + mime_type, + blur_placeholder:Some(BlurPlaceholder::fallback()), + } + } +} + +/// Options for generating a blur placeholder. +#[turbo_tasks::value(shared)] +pub struct BlurPlaceholderOptions { + pub quality:u8, + pub size:u32, +} + +fn extension_to_image_format(extension:&str) -> Option { + Some(match extension { + "avif" => ImageFormat::Avif, + "jpg" | "jpeg" => ImageFormat::Jpeg, + "png" => ImageFormat::Png, + "gif" => ImageFormat::Gif, + "webp" => ImageFormat::WebP, + "tif" | "tiff" => ImageFormat::Tiff, + "tga" => ImageFormat::Tga, + "dds" => ImageFormat::Dds, + "bmp" => ImageFormat::Bmp, + "ico" => ImageFormat::Ico, + "hdr" => ImageFormat::Hdr, + "exr" => ImageFormat::OpenExr, + "pbm" | "pam" | "ppm" | "pgm" => ImageFormat::Pnm, + "ff" | "farbfeld" => ImageFormat::Farbfeld, + "qoi" => ImageFormat::Qoi, + _ => return None, + }) +} + +fn result_to_issue(ident:Vc, result:Result) -> Option { + match result { + Ok(r) => Some(r), + Err(err) => { + ImageProcessingIssue { + path:ident.path(), + message:StyledString::Text(format!("{}", PrettyPrintError(&err)).into()).cell(), + issue_severity:None, + title:None, + } + .cell() + .emit(); + None + }, + } +} + +fn load_image( + ident:Vc, + bytes:&[u8], + extension:Option<&str>, +) -> Option<(ImageBuffer, Option)> { + result_to_issue(ident, load_image_internal(ident, bytes, extension)) +} + +/// Type of raw image buffer read by reader from `load_image`. +/// If the image could not be decoded, the raw bytes are returned. +enum ImageBuffer { + Raw(Vec), + Decoded(image::DynamicImage), +} + +fn load_image_internal( + ident:Vc, + bytes:&[u8], + extension:Option<&str>, +) -> Result<(ImageBuffer, Option)> { + let reader = image::io::Reader::new(Cursor::new(&bytes)); + let mut reader = reader + .with_guessed_format() + .context("unable to determine image format from file content")?; + let mut format = reader.format(); + if format.is_none() { + if let Some(extension) = extension { + if let Some(new_format) = extension_to_image_format(extension) { + format = Some(new_format); + reader.set_format(new_format); + } + } + } + + // [NOTE] + // Workaround for missing codec supports in Turbopack, + // Instead of erroring out the whole build, emitting raw image bytes as-is + // (Not applying resize, not applying optimization or anything else) + // and expect a browser decodes it. + // This is a stop gap until we have proper encoding/decoding in majority of the + // platforms + + #[cfg(not(feature = "avif"))] + if matches!(format, Some(ImageFormat::Avif)) { + ImageProcessingIssue { + path:ident.path(), + message:StyledString::Text( + "This version of Turbopack does not support AVIF images, will emit without \ + optimization or encoding" + .into(), + ) + .cell(), + title:Some(StyledString::Text("AVIF image not supported".into()).cell()), + issue_severity:Some(IssueSeverity::Warning.into()), + } + .cell() + .emit(); + return Ok((ImageBuffer::Raw(bytes.to_vec()), format)); + } + + #[cfg(not(feature = "webp"))] + if matches!(format, Some(ImageFormat::WebP)) { + ImageProcessingIssue { + path:ident.path(), + message:StyledString::Text( + "This version of Turbopack does not support WEBP images, will emit without \ + optimization or encoding" + .into(), + ) + .cell(), + title:Some(StyledString::Text("WEBP image not supported".into()).cell()), + issue_severity:Some(IssueSeverity::Warning.into()), + } + .cell() + .emit(); + return Ok((ImageBuffer::Raw(bytes.to_vec()), format)); + } + + let image = reader.decode().context("unable to decode image data")?; + Ok((ImageBuffer::Decoded(image), format)) +} + +fn compute_blur_data( + ident:Vc, + image:image::DynamicImage, + format:ImageFormat, + options:&BlurPlaceholderOptions, +) -> Option { + match compute_blur_data_internal(image, format, options) + .context("unable to compute blur placeholder") + { + Ok(r) => Some(r), + Err(err) => { + ImageProcessingIssue { + path:ident.path(), + message:StyledString::Text(format!("{}", PrettyPrintError(&err)).into()).cell(), + issue_severity:None, + title:None, + } + .cell() + .emit(); + Some(BlurPlaceholder::fallback()) + }, + } +} + +fn encode_image(image:DynamicImage, format:ImageFormat, quality:u8) -> Result<(Vec, Mime)> { + let mut buf = Vec::new(); + let (width, height) = image.dimensions(); + + Ok(match format { + ImageFormat::Png => { + PngEncoder::new_with_quality( + &mut buf, + CompressionType::Best, + image::codecs::png::FilterType::NoFilter, + ) + .write_image(image.as_bytes(), width, height, image.color().into())?; + (buf, mime::IMAGE_PNG) + }, + ImageFormat::Jpeg => { + JpegEncoder::new_with_quality(&mut buf, quality).write_image( + image.as_bytes(), + width, + height, + image.color().into(), + )?; + (buf, mime::IMAGE_JPEG) + }, + ImageFormat::Ico => { + IcoEncoder::new(&mut buf).write_image( + image.as_bytes(), + width, + height, + image.color().into(), + )?; + // mime does not support typed IMAGE_X_ICO yet + (buf, Mime::from_str("image/x-icon")?) + }, + ImageFormat::Bmp => { + BmpEncoder::new(&mut buf).write_image( + image.as_bytes(), + width, + height, + image.color().into(), + )?; + (buf, mime::IMAGE_BMP) + }, + #[cfg(feature = "webp")] + ImageFormat::WebP => { + use image::codecs::webp::WebPEncoder; + let encoder = WebPEncoder::new_lossless(&mut buf); + encoder.encode(image.as_bytes(), width, height, image.color().into())?; + + (buf, Mime::from_str("image/webp")?) + }, + #[cfg(feature = "avif")] + ImageFormat::Avif => { + use image::codecs::avif::AvifEncoder; + AvifEncoder::new_with_speed_quality(&mut buf, 6, quality).write_image( + image.as_bytes(), + width, + height, + image.color().into(), + )?; + (buf, Mime::from_str("image/avif")?) + }, + _ => { + bail!( + "Encoding for image format {:?} has not been compiled into the current build", + format + ) + }, + }) +} + +fn compute_blur_data_internal( + image:image::DynamicImage, + format:ImageFormat, + options:&BlurPlaceholderOptions, +) -> Result { + let small_image = image.resize(options.size, options.size, FilterType::Triangle); + let width = small_image.width(); + let height = small_image.height(); + let (data, mime) = encode_image(small_image, format, options.quality)?; + let data_url = format!("data:{mime};base64,{}", Base64Display::new(&data, &STANDARD)); + + Ok(BlurPlaceholder { data_url, width, height }) +} + +fn image_format_to_mime_type(format:ImageFormat) -> Result> { + Ok(match format { + ImageFormat::Png => Some(mime::IMAGE_PNG), + ImageFormat::Jpeg => Some(mime::IMAGE_JPEG), + ImageFormat::WebP => Some(Mime::from_str("image/webp")?), + ImageFormat::Avif => Some(Mime::from_str("image/avif")?), + ImageFormat::Bmp => Some(mime::IMAGE_BMP), + ImageFormat::Dds => Some(Mime::from_str("image/vnd-ms.dds")?), + ImageFormat::Farbfeld => Some(mime::APPLICATION_OCTET_STREAM), + ImageFormat::Gif => Some(mime::IMAGE_GIF), + ImageFormat::Hdr => Some(Mime::from_str("image/vnd.radiance")?), + ImageFormat::Ico => Some(Mime::from_str("image/x-icon")?), + ImageFormat::OpenExr => Some(Mime::from_str("image/x-exr")?), + ImageFormat::Pnm => Some(Mime::from_str("image/x-portable-anymap")?), + ImageFormat::Qoi => Some(mime::APPLICATION_OCTET_STREAM), + ImageFormat::Tga => Some(Mime::from_str("image/x-tga")?), + ImageFormat::Tiff => Some(Mime::from_str("image/tiff")?), + _ => None, + }) +} + +/// Analyze an image and return meta information about it. +/// Optionally computes a blur placeholder. +#[turbo_tasks::function] +pub async fn get_meta_data( + ident:Vc, + content:Vc, + blur_placeholder:Option>, +) -> Result> { + let FileContent::Content(content) = &*content.await? else { + bail!("Input image not found"); + }; + let bytes = content.content().to_bytes()?; + let path = ident.path().await?; + let extension = path.extension_ref(); + if extension == Some("svg") { + let content = result_to_issue( + ident, + std::str::from_utf8(&bytes).context("Input image is not valid utf-8"), + ); + let Some(content) = content else { + return Ok(ImageMetaData::fallback_value(Some(mime::IMAGE_SVG)).cell()); + }; + let info = result_to_issue( + ident, + calculate(content).context("Failed to parse svg source code for image dimensions"), + ); + let Some((width, height)) = info else { + return Ok(ImageMetaData::fallback_value(Some(mime::IMAGE_SVG)).cell()); + }; + return Ok(ImageMetaData { + width, + height, + mime_type:Some(mime::IMAGE_SVG), + blur_placeholder:None, + } + .cell()); + } + let Some((image, format)) = load_image(ident, &bytes, extension) else { + return Ok(ImageMetaData::fallback_value(None).cell()); + }; + + match image { + ImageBuffer::Raw(..) => Ok(ImageMetaData::fallback_value(None).cell()), + ImageBuffer::Decoded(image) => { + let (width, height) = image.dimensions(); + let blur_placeholder = if let Some(blur_placeholder) = blur_placeholder { + if matches!( + format, + // list should match next/client/image.tsx + Some(ImageFormat::Png) + | Some(ImageFormat::Jpeg) + | Some(ImageFormat::WebP) + | Some(ImageFormat::Avif) + ) { + compute_blur_data(ident, image, format.unwrap(), &*blur_placeholder.await?) + } else { + None + } + } else { + None + }; + + Ok(ImageMetaData { + width, + height, + mime_type:if let Some(format) = format { + image_format_to_mime_type(format)? + } else { + None + }, + blur_placeholder, + } + .cell()) + }, + } +} + +#[turbo_tasks::function] +pub async fn optimize( + ident:Vc, + content:Vc, + max_width:u32, + max_height:u32, + quality:u8, +) -> Result> { + let FileContent::Content(content) = &*content.await? else { + return Ok(FileContent::NotFound.cell()); + }; + let bytes = content.content().to_bytes()?; + + let Some((image, format)) = load_image(ident, &bytes, ident.path().await?.extension_ref()) + else { + return Ok(FileContent::NotFound.cell()); + }; + match image { + ImageBuffer::Raw(buffer) => { + #[cfg(not(feature = "avif"))] + if matches!(format, Some(ImageFormat::Avif)) { + return Ok(FileContent::Content( + File::from(buffer).with_content_type(Mime::from_str("image/avif")?), + ) + .cell()); + } + + #[cfg(not(feature = "webp"))] + if matches!(format, Some(ImageFormat::WebP)) { + return Ok(FileContent::Content( + File::from(buffer).with_content_type(Mime::from_str("image/webp")?), + ) + .cell()); + } + + let mime_type = if let Some(format) = format { + image_format_to_mime_type(format)? + } else { + None + }; + + // Falls back to image/jpeg if the format is unknown, thouogh it is not + // technically correct + Ok(FileContent::Content( + File::from(buffer).with_content_type(mime_type.unwrap_or(mime::IMAGE_JPEG)), + ) + .cell()) + }, + ImageBuffer::Decoded(image) => { + let (width, height) = image.dimensions(); + let image = if width > max_width || height > max_height { + image.resize(max_width, max_height, FilterType::Lanczos3) + } else { + image + }; + + let format = format.unwrap_or(ImageFormat::Jpeg); + let (data, mime_type) = encode_image(image, format, quality)?; + + Ok(FileContent::Content(File::from(data).with_content_type(mime_type)).cell()) + }, + } +} + +#[turbo_tasks::value] +struct ImageProcessingIssue { + path:Vc, + message:Vc, + title:Option>, + issue_severity:Option>, +} + +#[turbo_tasks::value_impl] +impl Issue for ImageProcessingIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { + self.issue_severity.unwrap_or(IssueSeverity::Error.into()) + } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.path } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Transform.cell() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + self.title + .unwrap_or(StyledString::Text("Processing image failed".into()).cell()) + } + + #[turbo_tasks::function] + fn description(&self) -> Vc { Vc::cell(Some(self.message)) } +} diff --git a/crates/turbopack-image/Source/process/svg.rs b/crates/turbopack-image/Source/process/svg.rs new file mode 100644 index 0000000000000..3cff6c14b40be --- /dev/null +++ b/crates/turbopack-image/Source/process/svg.rs @@ -0,0 +1,168 @@ +// Ported from https://github.com/image-size/image-size/blob/94e9c1ee913b71222d7583dc904ac0116ae00834/lib/types/svg.ts +// see SVG_LICENSE for license info + +use std::collections::HashMap; + +use anyhow::{Result, anyhow, bail}; +use once_cell::sync::Lazy; +use regex::Regex; + +const INCH_CM:f64 = 2.54; +static UNITS:Lazy> = Lazy::new(|| { + HashMap::from([ + ("in", 96.0), + ("cm", 96.0 / INCH_CM), + ("em", 16.0), + ("ex", 8.0), + ("m", 96.0 / INCH_CM * 100.0), + ("mm", 96.0 / INCH_CM / 10.0), + ("pc", 96.0 / 72.0 / 12.0), + ("pt", 96.0 / 72.0), + ("px", 1.0), + ("", 1.0), + ]) +}); + +static UNIT_REGEX:Lazy = + Lazy::new(|| Regex::new(r"^([0-9.]+(?:e-?\d+)?)((?:in|cm|em|ex|m|mm|pc|pt|px)?)$").unwrap()); + +static ROOT_REGEX:Lazy = + Lazy::new(|| Regex::new(r#""']|"[^"]*"|'[^']*')*>"#).unwrap()); +static WIDTH_REGEX:Lazy = Lazy::new(|| Regex::new(r#"\swidth=['"]([^%]+?)['"]"#).unwrap()); +static HEIGHT_REGEX:Lazy = Lazy::new(|| Regex::new(r#"\sheight=['"]([^%]+?)['"]"#).unwrap()); +static VIEW_BOX_REGEX:Lazy = Lazy::new(|| Regex::new(r#"\sviewBox=['"](.+?)['"]"#).unwrap()); +static VIEW_BOX_CONTENT_REGEX:Lazy = Lazy::new(|| { + Regex::new(r"^\s*((?:\w|\.|-)+)\s+((?:\w|\.|-)+)\s+((?:\w|\.|-)+)\s+((?:\w|\.|-)+)\s*$") + .unwrap() +}); + +fn parse_length(len:&str) -> Result { + let captures = UNIT_REGEX + .captures(len) + .ok_or_else(|| anyhow!("Unknown syntax for length, expected value with unit ({len})"))?; + let val = captures[1].parse::()?; + let unit = &captures[2]; + let unit_scale = UNITS.get(unit).ok_or_else(|| anyhow!("Unknown unit {unit}"))?; + Ok(val * unit_scale) +} + +fn parse_viewbox(viewbox:&str) -> Result<(f64, f64)> { + let captures = VIEW_BOX_CONTENT_REGEX + .captures(viewbox) + .ok_or_else(|| anyhow!("Unknown syntax for viewBox ({viewbox})"))?; + let width = parse_length(&captures[3])?; + let height = parse_length(&captures[4])?; + Ok((width, height)) +} + +fn calculate_by_viewbox( + view_box:(f64, f64), + width:Option>, + height:Option>, +) -> Result<(u32, u32)> { + let ratio = view_box.0 / view_box.1; + if let Some(width) = width { + let width = width?.round() as u32; + let height = (width as f64 / ratio).round() as u32; + return Ok((width, height)); + } + if let Some(height) = height { + let height = height?.round() as u32; + let width = (height as f64 * ratio).round() as u32; + return Ok((width, height)); + } + Ok((view_box.0.round() as u32, view_box.1.round() as u32)) +} + +pub fn calculate(content:&str) -> Result<(u32, u32)> { + let Some(root) = ROOT_REGEX.find(content) else { + bail!("Source code does not contain a root element"); + }; + let root = root.as_str(); + let width = WIDTH_REGEX.captures(root).map(|c| parse_length(&c[1])); + let height = HEIGHT_REGEX.captures(root).map(|c| parse_length(&c[1])); + let viewbox = VIEW_BOX_REGEX.captures(root).map(|c| parse_viewbox(&c[1])); + if let Some(width) = width { + if let Some(height) = height { + Ok((width?.round() as u32, height?.round() as u32)) + } else { + bail!("SVG source code contains only a width attribute but not height attribute"); + } + } else if let Some(viewbox) = viewbox { + calculate_by_viewbox(viewbox?, width, height) + } else { + bail!("SVG source code does not contain width and height or viewBox attribute"); + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + + use super::calculate; + + #[test] + fn test_calculate() { + let svg1 = r#""#; + assert_eq!(calculate(svg1).unwrap(), (100, 50)); + + let svg2 = r#""#; + assert_eq!(calculate(svg2).unwrap(), (100, 50)); + + let svg3 = r#""#; + assert_eq!(calculate(svg3).unwrap(), (200, 100)); + + let svg4 = r#""#; + assert_eq!(calculate(svg4).unwrap(), (100, 50)); + + let svg5 = r#""#; + assert_eq!(calculate(svg5).unwrap(), (100, 50)); + + let svg6 = r#""#; + assert!(calculate(svg6).is_err()); + + let svg7 = r#""#; + assert!(calculate(svg7).is_err()); + + let svg8 = r#""#; + assert!(calculate(svg8).is_err()); + + let svg9 = r#""#; + assert!(calculate(svg9).is_err()); + + let svg10 = r#""#; + assert!(calculate(svg10).is_err()); + } + + #[test] + fn test_calculate_with_units() -> Result<()> { + let svg = r#""#; + let result = calculate(svg)?; + assert_eq!(result, (76, 189)); + Ok(()) + } + + #[test] + fn test_calculate_with_em() -> Result<()> { + let svg = r#""#; + let result = calculate(svg)?; + assert_eq!(result, (320, 160)); + Ok(()) + } + + #[test] + fn test_calculate_with_ex() -> Result<()> { + let svg = r#""#; + let result = calculate(svg)?; + assert_eq!(result, (160, 80)); + Ok(()) + } + + #[test] + fn test_calculate_complex_viewbox() -> Result<()> { + let svg = r#""#; + let result = calculate(svg)?; + assert_eq!(result, (50, 50420)); + Ok(()) + } +} diff --git a/crates/turbopack-image/build.rs b/crates/turbopack-image/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-image/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-json/Source/lib.rs b/crates/turbopack-json/Source/lib.rs new file mode 100644 index 0000000000000..97e39ac20aa47 --- /dev/null +++ b/crates/turbopack-json/Source/lib.rs @@ -0,0 +1,150 @@ +//! JSON asset support for turbopack. +//! +//! JSON assets are parsed to ensure they contain valid JSON. +//! +//! When imported from ES modules, they produce a module that exports the +//! JSON value as an object. + +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +use std::fmt::Write; + +use anyhow::{Error, Result, bail}; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbo_tasks_fs::{FileContent, FileJsonContent}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext}, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, + source::Source, +}; +use turbopack_ecmascript::chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, +}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("json".into()) } + +#[turbo_tasks::value] +pub struct JsonModuleAsset { + source:Vc>, +} + +#[turbo_tasks::value_impl] +impl JsonModuleAsset { + #[turbo_tasks::function] + pub fn new(source:Vc>) -> Vc { Self::cell(JsonModuleAsset { source }) } +} + +#[turbo_tasks::value_impl] +impl Module for JsonModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { self.source.ident().with_modifier(modifier()) } +} + +#[turbo_tasks::value_impl] +impl Asset for JsonModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for JsonModuleAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(JsonChunkItem::cell(JsonChunkItem { module:self, chunking_context }))) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for JsonModuleAsset { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } +} + +#[turbo_tasks::value] +struct JsonChunkItem { + module:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for JsonChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for JsonChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(&self) -> Result> { + // We parse to JSON and then stringify again to ensure that the + // JSON is valid. + let content = self.module.content().file_content(); + let data = content.parse_json().await?; + match &*data { + FileJsonContent::Content(data) => { + let js_str_content = serde_json::to_string(&data.to_string())?; + let inner_code = + format!("__turbopack_export_value__(JSON.parse({js_str_content}));"); + + Ok(EcmascriptChunkItemContent { + inner_code:inner_code.into(), + ..Default::default() + } + .into()) + }, + FileJsonContent::Unparseable(e) => { + let mut message = "Unable to make a module from invalid JSON: ".to_string(); + if let FileContent::Content(content) = &*content.await? { + let text = content.content().to_str()?; + e.write_with_content(&mut message, text.as_ref())?; + } else { + write!(message, "{}", e)?; + } + + Err(Error::msg(message)) + }, + FileJsonContent::NotFound => { + bail!("JSON file not found: {}", self.module.ident().to_string().await?); + }, + } + } +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-json/build.rs b/crates/turbopack-json/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-json/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-mdx/Source/lib.rs b/crates/turbopack-mdx/Source/lib.rs new file mode 100644 index 0000000000000..868963815b06d --- /dev/null +++ b/crates/turbopack-mdx/Source/lib.rs @@ -0,0 +1,311 @@ +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +use anyhow::{Context, Result, anyhow}; +use mdxjs::{MdxParseOptions, Options, compile}; +use turbo_tasks::{RcStr, Value, ValueDefault, Vc}; +use turbo_tasks_fs::{File, FileContent, FileSystemPath, rope::Rope}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{AsyncModuleInfo, ChunkItem, ChunkType, ChunkableModule, ChunkingContext}, + context::AssetContext, + ident::AssetIdent, + module::Module, + reference::ModuleReferences, + resolve::origin::ResolveOrigin, + source::Source, + virtual_source::VirtualSource, +}; +use turbopack_ecmascript::{ + AnalyzeEcmascriptModuleResult, + EcmascriptInputTransforms, + EcmascriptModuleAsset, + EcmascriptModuleAssetType, + EcmascriptOptions, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + references::AnalyzeEcmascriptModuleResultBuilder, +}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("mdx".into()) } + +#[turbo_tasks::value(shared)] +#[derive(PartialOrd, Ord, Hash, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub enum MdxParseConstructs { + Commonmark, + Gfm, +} + +/// Subset of mdxjs::Options to allow to inherit turbopack's jsx-related configs +/// into mdxjs. This is thin, near straightforward subset of mdxjs::Options to +/// enable turbo tasks. +#[turbo_tasks::value(shared)] +#[derive(PartialOrd, Ord, Hash, Debug, Clone)] +#[serde(rename_all = "camelCase", default)] +pub struct MdxTransformOptions { + pub development:Option, + pub jsx:Option, + pub jsx_runtime:Option, + pub jsx_import_source:Option, + /// The path to a module providing Components to mdx modules. + /// The provider must export a useMDXComponents, which is called to access + /// an object of components. + pub provider_import_source:Option, + /// Determines how to parse mdx contents. + pub mdx_type:Option, +} + +impl Default for MdxTransformOptions { + fn default() -> Self { + Self { + development:Some(true), + jsx:Some(false), + jsx_runtime:None, + jsx_import_source:None, + provider_import_source:None, + mdx_type:Some(MdxParseConstructs::Commonmark), + } + } +} + +#[turbo_tasks::value_impl] +impl MdxTransformOptions { + #[turbo_tasks::function] + fn default_private() -> Vc { Self::cell(Default::default()) } +} + +impl ValueDefault for MdxTransformOptions { + fn value_default() -> Vc { Self::default_private() } +} + +#[turbo_tasks::value] +#[derive(Clone, Copy)] +pub struct MdxModuleAsset { + source:Vc>, + asset_context:Vc>, + transforms:Vc, + options:Vc, + ecmascript_options:Vc, +} + +/// MDX components should be treated as normal j|tsx components to analyze +/// its imports or run ecma transforms, +/// only difference is it is not a valid ecmascript AST we +/// can't pass it forward directly. Internally creates an jsx from mdx +/// via mdxrs, then pass it through existing ecmascript analyzer. +/// +/// To make mdx as a variant of ecmascript and use its `source_transforms` +/// instead, there should be a way to get a valid SWC ast from mdx source input +/// - which we don't have yet. +async fn into_ecmascript_module_asset( + current_context:&Vc, +) -> Result> { + let content = current_context.content(); + let this = current_context.await?; + let transform_options = this.options.await?; + + let AssetContent::File(file) = &*content.await? else { + anyhow::bail!("Unexpected mdx asset content"); + }; + + let FileContent::Content(file) = &*file.await? else { + anyhow::bail!("Not able to read mdx file content"); + }; + + let jsx_runtime = if let Some(runtime) = &transform_options.jsx_runtime { + match runtime.as_str() { + "automatic" => Some(mdxjs::JsxRuntime::Automatic), + "classic" => Some(mdxjs::JsxRuntime::Classic), + _ => None, + } + } else { + None + }; + + let parse_options = match transform_options.mdx_type { + Some(MdxParseConstructs::Gfm) => MdxParseOptions::gfm(), + _ => MdxParseOptions::default(), + }; + + let options = Options { + parse:parse_options, + development:transform_options.development.unwrap_or(false), + provider_import_source:transform_options + .provider_import_source + .clone() + .map(RcStr::into_owned), + jsx:transform_options.jsx.unwrap_or(false), // true means 'preserve' jsx syntax. + jsx_runtime, + jsx_import_source:transform_options.jsx_import_source.clone().map(RcStr::into_owned), + filepath:Some(this.source.ident().path().await?.to_string()), + ..Default::default() + }; + // TODO: upstream mdx currently bubbles error as string + let mdx_jsx_component = + compile(&file.content().to_str()?, &options).map_err(|e| anyhow!("{}", e))?; + + let source = VirtualSource::new_with_ident( + this.source.ident(), + AssetContent::file(File::from(Rope::from(mdx_jsx_component)).into()), + ); + Ok(EcmascriptModuleAsset::new( + Vc::upcast(source), + this.asset_context, + Value::new(EcmascriptModuleAssetType::Typescript { tsx:true, analyze_types:false }), + this.transforms, + this.ecmascript_options, + this.asset_context.compile_time_info(), + )) +} + +#[turbo_tasks::value_impl] +impl MdxModuleAsset { + #[turbo_tasks::function] + pub fn new( + source:Vc>, + asset_context:Vc>, + transforms:Vc, + options:Vc, + ecmascript_options:Vc, + ) -> Vc { + Self::cell(MdxModuleAsset { + source, + asset_context, + transforms, + options, + ecmascript_options, + }) + } + + #[turbo_tasks::function] + async fn failsafe_analyze(self: Vc) -> Result> { + let asset = into_ecmascript_module_asset(&self).await; + + if let Ok(asset) = asset { + Ok(asset.failsafe_analyze()) + } else { + let mut result = AnalyzeEcmascriptModuleResultBuilder::new(); + result.set_successful(false); + result.build(false).await + } + } +} + +#[turbo_tasks::value_impl] +impl Module for MdxModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + self.source + .ident() + .with_modifier(modifier()) + .with_layer(self.asset_context.layer()) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let analyze = self.failsafe_analyze().await?; + Ok(analyze.references) + } +} + +#[turbo_tasks::value_impl] +impl Asset for MdxModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for MdxModuleAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(MdxChunkItem::cell(MdxChunkItem { module:self, chunking_context }))) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for MdxModuleAsset { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } +} + +#[turbo_tasks::value_impl] +impl ResolveOrigin for MdxModuleAsset { + #[turbo_tasks::function] + fn origin_path(&self) -> Vc { self.source.ident().path() } + + #[turbo_tasks::function] + fn asset_context(&self) -> Vc> { self.asset_context } +} + +#[turbo_tasks::value] +struct MdxChunkItem { + module:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for MdxChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + fn references(&self) -> Vc { self.module.references() } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for MdxChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + panic!("MdxChunkItem::content should never be called"); + } + + /// Once we have mdx contents, we should treat it as j|tsx components and + /// apply all of the ecma transforms + #[turbo_tasks::function] + async fn content_with_async_module_info( + &self, + async_module_info:Option>, + ) -> Result> { + let item = into_ecmascript_module_asset(&self.module) + .await? + .as_chunk_item(Vc::upcast(self.chunking_context)); + let ecmascript_item = Vc::try_resolve_downcast::>(item) + .await? + .context("MdxChunkItem must generate an EcmascriptChunkItem")?; + Ok(ecmascript_item.content_with_async_module_info(async_module_info)) + } +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-mdx/build.rs b/crates/turbopack-mdx/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-mdx/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-node/Source/debug.rs b/crates/turbopack-node/Source/debug.rs new file mode 100644 index 0000000000000..06bf83ca30b35 --- /dev/null +++ b/crates/turbopack-node/Source/debug.rs @@ -0,0 +1,18 @@ +use std::env; + +const DEBUG_JS_VAR:&str = "TURBOPACK_DEBUG_JS"; + +/// Checks if the operation passed is included in the `TURBOPACK_DEBUG_JS` env +/// var to enable node.js debugging at runtime. +/// +/// This is preferable to manually passing a boolean because recompiling won't +/// be necessary. +pub fn should_debug(operation:&str) -> bool { + // TODO(sokra) It's not persistent caching safe to read an env var this way. + // This must use turbo_tasks_env instead. + let Ok(val) = env::var(DEBUG_JS_VAR) else { + return false; + }; + + val == "*" || val.split(',').any(|part| part == operation) +} diff --git a/crates/turbopack-node/Source/embed_js.rs b/crates/turbopack-node/Source/embed_js.rs new file mode 100644 index 0000000000000..671b811ca124a --- /dev/null +++ b/crates/turbopack-node/Source/embed_js.rs @@ -0,0 +1,13 @@ +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::{FileContent, FileSystem, FileSystemPath, embed_directory}; + +#[turbo_tasks::function] +pub fn embed_fs() -> Vc> { + embed_directory!("turbopack-node", "$CARGO_MANIFEST_DIR/js/src") +} + +#[turbo_tasks::function] +pub(crate) fn embed_file(path:RcStr) -> Vc { embed_fs().root().join(path).read() } + +#[turbo_tasks::function] +pub(crate) fn embed_file_path(path:RcStr) -> Vc { embed_fs().root().join(path) } diff --git a/crates/turbopack-node/Source/evaluate.rs b/crates/turbopack-node/Source/evaluate.rs new file mode 100644 index 0000000000000..7627f4e5f74cc --- /dev/null +++ b/crates/turbopack-node/Source/evaluate.rs @@ -0,0 +1,592 @@ +use std::{borrow::Cow, ops::ControlFlow, thread::available_parallelism, time::Duration}; + +use anyhow::{Result, anyhow, bail}; +use async_stream::try_stream as generator; +use async_trait::async_trait; +use futures::{ + SinkExt, + StreamExt, + channel::mpsc::{UnboundedSender, unbounded}, + pin_mut, +}; +use futures_retry::{FutureRetry, RetryPolicy}; +use indexmap::indexmap; +use parking_lot::Mutex; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; +use serde_json::Value as JsonValue; +use turbo_tasks::{ + Completion, + RawVc, + TaskInput, + TryJoinIterExt, + Value, + Vc, + duration_span, + mark_finished, + prevent_gc, + util::SharedError, +}; +use turbo_tasks_bytes::{Bytes, Stream}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{File, FileSystemPath, to_sys_path}; +use turbopack_core::{ + asset::AssetContent, + chunk::{ChunkingContext, ChunkingContextExt, EvaluatableAsset, EvaluatableAssets}, + context::AssetContext, + error::PrettyPrintError, + file_source::FileSource, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueStage, OptionStyledString, StyledString}, + module::Module, + reference_type::{InnerAssets, ReferenceType}, + virtual_source::VirtualSource, +}; + +use crate::{ + AssetsForSourceMapping, + embed_js::embed_file_path, + emit, + emit_package_json, + internal_assets_for_source_mapping, + pool::{FormattingMode, NodeJsOperation, NodeJsPool}, + source_map::StructuredError, +}; + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +enum EvalJavaScriptOutgoingMessage<'a> { + #[serde(rename_all = "camelCase")] + Evaluate { + args:Vec<&'a JsonValue>, + }, + Result { + id:u64, + data:Option, + error:Option, + }, +} + +#[derive(Deserialize, Debug)] +#[serde(tag = "type", rename_all = "camelCase")] +enum EvalJavaScriptIncomingMessage { + Info { data:JsonValue }, + Request { id:u64, data:JsonValue }, + End { data:Option }, + Error(StructuredError), +} + +type LoopResult = ControlFlow, StructuredError>, String>; + +type EvaluationItem = Result; +type JavaScriptStream = Stream; + +#[turbo_tasks::value(eq = "manual", cell = "new", serialization = "none")] +pub struct JavaScriptStreamSender { + #[turbo_tasks(trace_ignore, debug_ignore)] + get:Box UnboundedSender> + Send + Sync>, +} + +#[turbo_tasks::value(transparent)] +#[derive(Clone, Debug)] +pub struct JavaScriptEvaluation(#[turbo_tasks(trace_ignore)] JavaScriptStream); + +#[turbo_tasks::function] +/// Pass the file you cared as `runtime_entries` to invalidate and reload the +/// evaluated result automatically. +pub async fn get_evaluate_pool( + module_asset:Vc>, + cwd:Vc, + env:Vc>, + asset_context:Vc>, + chunking_context:Vc>, + runtime_entries:Option>, + additional_invalidation:Vc, + debug:bool, +) -> Result> { + let runtime_asset = asset_context + .process( + Vc::upcast(FileSource::new(embed_file_path("ipc/evaluate.ts".into()))), + Value::new(ReferenceType::Internal(InnerAssets::empty())), + ) + .module(); + + let module_path = module_asset.ident().path().await?; + let file_name = module_path.file_name(); + let file_name = if file_name.ends_with(".js") { + Cow::Borrowed(file_name) + } else if let Some(file_name) = file_name.strip_suffix(".ts") { + Cow::Owned(format!("{file_name}.js")) + } else { + Cow::Owned(format!("{file_name}.js")) + }; + let path = chunking_context.output_root().join(file_name.into()); + let entry_module = asset_context + .process( + Vc::upcast(VirtualSource::new( + runtime_asset.ident().path().join("evaluate.js".into()), + AssetContent::file( + File::from("import { run } from 'RUNTIME'; run(() => import('INNER'))").into(), + ), + )), + Value::new(ReferenceType::Internal(Vc::cell(indexmap! { + "INNER".into() => module_asset, + "RUNTIME".into() => runtime_asset + }))), + ) + .module(); + + let (Some(cwd), Some(entrypoint)) = (to_sys_path(cwd).await?, to_sys_path(path).await?) else { + panic!("can only evaluate from a disk filesystem"); + }; + + let runtime_entries = { + let globals_module = asset_context + .process( + Vc::upcast(FileSource::new(embed_file_path("globals.ts".into()))), + Value::new(ReferenceType::Internal(InnerAssets::empty())), + ) + .module(); + + let Some(globals_module) = + Vc::try_resolve_sidecast::>(globals_module).await? + else { + bail!("Internal module is not evaluatable"); + }; + + let mut entries = vec![globals_module]; + if let Some(runtime_entries) = runtime_entries { + for &entry in &*runtime_entries.await? { + entries.push(entry) + } + } + + Vc::::cell(entries) + }; + + let bootstrap = + chunking_context.root_entry_chunk_group_asset(path, entry_module, runtime_entries); + + let output_root:Vc = chunking_context.output_root(); + let emit_package = emit_package_json(output_root); + let emit = emit(bootstrap, output_root); + let assets_for_source_mapping = internal_assets_for_source_mapping(bootstrap, output_root); + emit_package.await?; + emit.await?; + let pool = NodeJsPool::new( + cwd, + entrypoint, + env.read_all().await?.iter().map(|(k, v)| (k.clone(), v.clone())).collect(), + assets_for_source_mapping, + output_root, + chunking_context.context_path().root(), + available_parallelism().map_or(1, |v| v.get()), + debug, + ); + additional_invalidation.await?; + Ok(pool.cell()) +} + +struct PoolErrorHandler; + +/// Number of attempts before we start slowing down the retry. +const MAX_FAST_ATTEMPTS:usize = 5; +/// Total number of attempts. +const MAX_ATTEMPTS:usize = MAX_FAST_ATTEMPTS * 2; + +impl futures_retry::ErrorHandler for PoolErrorHandler { + type OutError = anyhow::Error; + + fn handle(&mut self, attempt:usize, err:anyhow::Error) -> RetryPolicy { + if attempt >= MAX_ATTEMPTS { + RetryPolicy::ForwardError(err) + } else if attempt >= MAX_FAST_ATTEMPTS { + RetryPolicy::WaitRetry(Duration::from_secs(1)) + } else { + RetryPolicy::Repeat + } + } +} + +#[async_trait] +pub trait EvaluateContext { + type InfoMessage: DeserializeOwned; + type RequestMessage: DeserializeOwned; + type ResponseMessage: Serialize; + type State: Default; + + fn compute(self, sender:Vc); + fn pool(&self) -> Vc; + fn keep_alive(&self) -> bool { false } + fn args(&self) -> &[Vc]; + fn cwd(&self) -> Vc; + async fn emit_error(&self, error:StructuredError, pool:&NodeJsPool) -> Result<()>; + async fn info( + &self, + state:&mut Self::State, + data:Self::InfoMessage, + pool:&NodeJsPool, + ) -> Result<()>; + async fn request( + &self, + state:&mut Self::State, + data:Self::RequestMessage, + pool:&NodeJsPool, + ) -> Result; + async fn finish(&self, _state:Self::State, _pool:&NodeJsPool) -> Result<()>; +} + +pub fn custom_evaluate(evaluate_context:impl EvaluateContext) -> Vc { + // TODO: The way we invoke compute_evaluate_stream as side effect is not + // GC-safe, so we disable GC for this task. + prevent_gc(); + + // Note the following code uses some hacks to create a child task that produces + // a stream that is returned by this task. + + // We create a new cell in this task, which will be updated from the + // [compute_evaluate_stream] task. + let cell = turbo_tasks::macro_helpers::find_cell_by_type(*JAVASCRIPTEVALUATION_VALUE_TYPE_ID); + + // We initialize the cell with a stream that is open, but has no values. + // The first [compute_evaluate_stream] pipe call will pick up that stream. + let (sender, receiver) = unbounded(); + cell.update_shared(JavaScriptEvaluation(JavaScriptStream::new_open( + vec![], + Box::new(receiver), + ))); + let initial = Mutex::new(Some(sender)); + + // run the evaluation as side effect + evaluate_context.compute( + JavaScriptStreamSender { + get:Box::new(move || { + if let Some(sender) = initial.lock().take() { + sender + } else { + // In cases when only [compute_evaluate_stream] is (re)executed, we need to + // update the old stream with a new value. + let (sender, receiver) = unbounded(); + cell.update_shared(JavaScriptEvaluation(JavaScriptStream::new_open( + vec![], + Box::new(receiver), + ))); + sender + } + }), + } + .cell(), + ); + + let raw:RawVc = cell.into(); + raw.into() +} + +/// Pass the file you cared as `runtime_entries` to invalidate and reload the +/// evaluated result automatically. +#[turbo_tasks::function] +pub fn evaluate( + module_asset:Vc>, + cwd:Vc, + env:Vc>, + context_ident_for_issue:Vc, + asset_context:Vc>, + chunking_context:Vc>, + runtime_entries:Option>, + args:Vec>, + additional_invalidation:Vc, + debug:bool, +) -> Vc { + custom_evaluate(BasicEvaluateContext { + module_asset, + cwd, + env, + context_ident_for_issue, + asset_context, + chunking_context, + runtime_entries, + args, + additional_invalidation, + debug, + }) +} + +pub async fn compute( + evaluate_context:impl EvaluateContext, + sender:Vc, +) -> Result> { + mark_finished(); + let Ok(sender) = sender.await else { + // Impossible to handle the error in a good way. + return Ok(Default::default()); + }; + + let stream = generator! { + let pool = evaluate_context.pool(); + let mut state = Default::default(); + + // Read this strongly consistent, since we don't want to run inconsistent + // node.js code. + let pool = pool.strongly_consistent().await?; + + let args = evaluate_context.args().iter().try_join().await?; + // Assume this is a one-off operation, so we can kill the process + // TODO use a better way to decide that. + let kill = !evaluate_context.keep_alive(); + + // Workers in the pool could be in a bad state that we didn't detect yet. + // The bad state might even be unnoticeable until we actually send the job to the + // worker. So we retry picking workers from the pools until we succeed + // sending the job. + + let (mut operation, _) = FutureRetry::new( + || async { + let mut operation = pool.operation().await?; + operation + .send(EvalJavaScriptOutgoingMessage::Evaluate { + args: args.iter().map(|v| &**v).collect(), + }) + .await?; + Ok(operation) + }, + PoolErrorHandler, + ) + .await + .map_err(|(e, _)| e)?; + + // The evaluation sent an initial intermediate value without completing. We'll + // need to spawn a new thread to continually pull data out of the process, + // and ferry that along. + loop { + let output = pull_operation(&mut operation, &pool, &evaluate_context, &mut state).await?; + + match output { + LoopResult::Continue(data) => { + yield data.into(); + } + LoopResult::Break(Ok(Some(data))) => { + yield data.into(); + break; + } + LoopResult::Break(Err(e)) => { + let error = print_error(e, &pool, &evaluate_context).await?; + Err(anyhow!("Node.js evaluation failed: {}", error))?; + break; + } + LoopResult::Break(Ok(None)) => { + break; + } + } + } + + evaluate_context.finish(state, &pool).await?; + + if kill { + operation.wait_or_kill().await?; + } + }; + + let mut sender = (sender.get)(); + pin_mut!(stream); + while let Some(value) = stream.next().await { + if sender.send(value).await.is_err() { + return Ok(Default::default()); + } + if sender.flush().await.is_err() { + return Ok(Default::default()); + } + } + + Ok(Default::default()) +} + +/// Repeatedly pulls from the NodeJsOperation until we receive a +/// value/error/end. +async fn pull_operation( + operation:&mut NodeJsOperation, + pool:&NodeJsPool, + evaluate_context:&T, + state:&mut T::State, +) -> Result { + let guard = duration_span!("Node.js evaluation"); + + let output = loop { + match operation.recv().await? { + EvalJavaScriptIncomingMessage::Error(error) => { + evaluate_context.emit_error(error, pool).await?; + // Do not reuse the process in case of error + operation.disallow_reuse(); + // Issue emitted, we want to break but don't want to return an error + break ControlFlow::Break(Ok(None)); + }, + EvalJavaScriptIncomingMessage::End { data } => break ControlFlow::Break(Ok(data)), + EvalJavaScriptIncomingMessage::Info { data } => { + evaluate_context.info(state, serde_json::from_value(data)?, pool).await?; + }, + EvalJavaScriptIncomingMessage::Request { id, data } => { + match evaluate_context.request(state, serde_json::from_value(data)?, pool).await { + Ok(response) => { + operation + .send(EvalJavaScriptOutgoingMessage::Result { + id, + error:None, + data:Some(serde_json::to_value(response)?), + }) + .await?; + }, + Err(e) => { + operation + .send(EvalJavaScriptOutgoingMessage::Result { + id, + error:Some(PrettyPrintError(&e).to_string()), + data:None, + }) + .await?; + }, + } + }, + } + }; + drop(guard); + + Ok(output) +} + +#[turbo_tasks::function] +async fn basic_compute( + evaluate_context:BasicEvaluateContext, + sender:Vc, +) -> Result> { + compute(evaluate_context, sender).await +} + +#[derive(Clone, PartialEq, Eq, TaskInput)] +struct BasicEvaluateContext { + module_asset:Vc>, + cwd:Vc, + env:Vc>, + context_ident_for_issue:Vc, + asset_context:Vc>, + chunking_context:Vc>, + runtime_entries:Option>, + args:Vec>, + additional_invalidation:Vc, + debug:bool, +} + +#[async_trait] +impl EvaluateContext for BasicEvaluateContext { + type InfoMessage = (); + type RequestMessage = (); + type ResponseMessage = (); + type State = (); + + fn compute(self, sender:Vc) { let _ = basic_compute(self, sender); } + + fn pool(&self) -> Vc { + get_evaluate_pool( + self.module_asset, + self.cwd, + self.env, + self.asset_context, + self.chunking_context, + self.runtime_entries, + self.additional_invalidation, + self.debug, + ) + } + + fn args(&self) -> &[Vc] { &self.args } + + fn cwd(&self) -> Vc { self.cwd } + + fn keep_alive(&self) -> bool { !self.args.is_empty() } + + async fn emit_error(&self, error:StructuredError, pool:&NodeJsPool) -> Result<()> { + EvaluationIssue { + error, + context_ident:self.context_ident_for_issue, + assets_for_source_mapping:pool.assets_for_source_mapping, + assets_root:pool.assets_root, + project_dir:self.chunking_context.context_path().root(), + } + .cell() + .emit(); + Ok(()) + } + + async fn info( + &self, + _state:&mut Self::State, + _data:Self::InfoMessage, + _pool:&NodeJsPool, + ) -> Result<()> { + bail!("BasicEvaluateContext does not support info messages") + } + + async fn request( + &self, + _state:&mut Self::State, + _data:Self::RequestMessage, + _pool:&NodeJsPool, + ) -> Result { + bail!("BasicEvaluateContext does not support request messages") + } + + async fn finish(&self, _state:Self::State, _pool:&NodeJsPool) -> Result<()> { Ok(()) } +} + +async fn print_error( + error:StructuredError, + pool:&NodeJsPool, + evaluate_context:&impl EvaluateContext, +) -> Result { + error + .print( + pool.assets_for_source_mapping, + pool.assets_root, + evaluate_context.cwd(), + FormattingMode::Plain, + ) + .await +} +/// An issue that occurred while evaluating node code. +#[turbo_tasks::value(shared)] +pub struct EvaluationIssue { + pub context_ident:Vc, + pub error:StructuredError, + pub assets_for_source_mapping:Vc, + pub assets_root:Vc, + pub project_dir:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for EvaluationIssue { + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Error evaluating Node.js code".into()).cell() + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Transform.into() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.context_ident.path() } + + #[turbo_tasks::function] + async fn description(&self) -> Result> { + Ok(Vc::cell(Some( + StyledString::Text( + self.error + .print( + self.assets_for_source_mapping, + self.assets_root, + self.project_dir, + FormattingMode::Plain, + ) + .await? + .into(), + ) + .cell(), + ))) + } +} diff --git a/crates/turbopack-node/Source/execution_context.rs b/crates/turbopack-node/Source/execution_context.rs new file mode 100644 index 0000000000000..7b8fdf59fd7f0 --- /dev/null +++ b/crates/turbopack-node/Source/execution_context.rs @@ -0,0 +1,37 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::chunk::ChunkingContext; + +#[turbo_tasks::value] +pub struct ExecutionContext { + pub project_path:Vc, + pub chunking_context:Vc>, + pub env:Vc>, +} + +#[turbo_tasks::value_impl] +impl ExecutionContext { + #[turbo_tasks::function] + pub fn new( + project_path:Vc, + chunking_context:Vc>, + env:Vc>, + ) -> Vc { + ExecutionContext { project_path, chunking_context, env }.cell() + } + + #[turbo_tasks::function] + pub async fn project_path(self: Vc) -> Result> { + Ok(self.await?.project_path) + } + + #[turbo_tasks::function] + pub async fn chunking_context(self: Vc) -> Result>> { + Ok(self.await?.chunking_context) + } + + #[turbo_tasks::function] + pub async fn env(self: Vc) -> Result>> { Ok(self.await?.env) } +} diff --git a/crates/turbopack-node/Source/lib.rs b/crates/turbopack-node/Source/lib.rs new file mode 100644 index 0000000000000..bf9ab21d147c3 --- /dev/null +++ b/crates/turbopack-node/Source/lib.rs @@ -0,0 +1,282 @@ +#![feature(async_closure)] +#![feature(min_specialization)] +#![feature(lint_reasons)] +#![feature(arbitrary_self_types)] +#![feature(extract_if)] + +use std::{collections::HashMap, iter::once, thread::available_parallelism}; + +use anyhow::{Result, bail}; +use indexmap::IndexSet; +pub use node_entry::{NodeEntry, NodeRenderingEntries, NodeRenderingEntry}; +use turbo_tasks::{ + Completion, + Completions, + RcStr, + TryJoinIterExt, + ValueToString, + Vc, + graph::{AdjacencyMap, GraphTraversal}, +}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{File, FileSystemPath, to_sys_path}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkingContext, ChunkingContextExt, EvaluatableAssets}, + module::Module, + output::{OutputAsset, OutputAssetsSet}, + source_map::GenerateSourceMap, + virtual_output::VirtualOutputAsset, +}; + +use self::{pool::NodeJsPool, source_map::StructuredError}; + +pub mod debug; +pub mod embed_js; +pub mod evaluate; +pub mod execution_context; +mod node_entry; +mod pool; +pub mod render; +pub mod route_matcher; +pub mod source_map; +pub mod transforms; + +#[turbo_tasks::function] +async fn emit( + intermediate_asset:Vc>, + intermediate_output_path:Vc, +) -> Result> { + Ok(Vc::::cell( + internal_assets(intermediate_asset, intermediate_output_path) + .strongly_consistent() + .await? + .iter() + .map(|a| a.content().write(a.ident().path())) + .collect(), + ) + .completed()) +} + +/// List of the all assets of the "internal" subgraph and a list of boundary +/// assets that are not considered "internal" ("external") +#[derive(Debug)] +#[turbo_tasks::value] +struct SeparatedAssets { + internal_assets:Vc, + external_asset_entrypoints:Vc, +} + +/// Extracts the subgraph of "internal" assets (assets within the passes +/// directory). Also lists all boundary assets that are not part of the +/// "internal" subgraph. +#[turbo_tasks::function] +async fn internal_assets( + intermediate_asset:Vc>, + intermediate_output_path:Vc, +) -> Result> { + Ok(separate_assets(intermediate_asset, intermediate_output_path) + .strongly_consistent() + .await? + .internal_assets) +} + +#[turbo_tasks::value(transparent)] +pub struct AssetsForSourceMapping(HashMap>>); + +/// Extracts a map of "internal" assets ([`internal_assets`]) which implement +/// the [GenerateSourceMap] trait. +#[turbo_tasks::function] +async fn internal_assets_for_source_mapping( + intermediate_asset:Vc>, + intermediate_output_path:Vc, +) -> Result> { + let internal_assets = internal_assets(intermediate_asset, intermediate_output_path).await?; + let intermediate_output_path = &*intermediate_output_path.await?; + let mut internal_assets_for_source_mapping = HashMap::new(); + for asset in internal_assets.iter() { + if let Some(generate_source_map) = + Vc::try_resolve_sidecast::>(*asset).await? + { + if let Some(path) = intermediate_output_path.get_path_to(&*asset.ident().path().await?) + { + internal_assets_for_source_mapping.insert(path.to_string(), generate_source_map); + } + } + } + Ok(Vc::cell(internal_assets_for_source_mapping)) +} + +/// Returns a set of "external" assets on the boundary of the "internal" +/// subgraph +#[turbo_tasks::function] +pub async fn external_asset_entrypoints( + module:Vc>, + runtime_entries:Vc, + chunking_context:Vc>, + intermediate_output_path:Vc, +) -> Result> { + Ok(separate_assets( + get_intermediate_asset(chunking_context, module, runtime_entries) + .resolve() + .await?, + intermediate_output_path, + ) + .strongly_consistent() + .await? + .external_asset_entrypoints) +} + +/// Splits the asset graph into "internal" assets and boundaries to "external" +/// assets. +#[turbo_tasks::function] +async fn separate_assets( + intermediate_asset:Vc>, + intermediate_output_path:Vc, +) -> Result> { + let intermediate_output_path = &*intermediate_output_path.await?; + #[derive(PartialEq, Eq, Hash, Clone, Copy)] + enum Type { + Internal(Vc>), + External(Vc>), + } + let get_asset_children = |asset| { + async move { + let Type::Internal(asset) = asset else { + return Ok(Vec::new()); + }; + asset + .references() + .await? + .iter() + .map(|asset| { + async { + // Assets within the output directory are considered as "internal" and all + // others as "external". We follow references on "internal" assets, but do + // not look into references of "external" assets, since there are no + // "internal" assets behind "externals" + if asset.ident().path().await?.is_inside_ref(intermediate_output_path) { + Ok(Type::Internal(*asset)) + } else { + Ok(Type::External(*asset)) + } + } + }) + .try_join() + .await + } + }; + + let graph = AdjacencyMap::new() + .skip_duplicates() + .visit(once(Type::Internal(intermediate_asset)), get_asset_children) + .await + .completed()? + .into_inner(); + + let mut internal_assets = IndexSet::new(); + let mut external_asset_entrypoints = IndexSet::new(); + + for item in graph.into_reverse_topological() { + match item { + Type::Internal(asset) => { + internal_assets.insert(asset); + }, + Type::External(asset) => { + external_asset_entrypoints.insert(asset); + }, + } + } + + Ok(SeparatedAssets { + internal_assets:Vc::cell(internal_assets), + external_asset_entrypoints:Vc::cell(external_asset_entrypoints), + } + .cell()) +} + +/// Emit a basic package.json that sets the type of the package to commonjs. +/// Currently code generated for Node is CommonJS, while authored code may be +/// ESM, for example. +fn emit_package_json(dir:Vc) -> Vc { + emit( + Vc::upcast(VirtualOutputAsset::new( + dir.join("package.json".into()), + AssetContent::file(File::from("{\"type\": \"commonjs\"}").into()), + )), + dir, + ) +} + +/// Creates a node.js renderer pool for an entrypoint. +#[turbo_tasks::function] +pub async fn get_renderer_pool( + cwd:Vc, + env:Vc>, + intermediate_asset:Vc>, + intermediate_output_path:Vc, + output_root:Vc, + project_dir:Vc, + debug:bool, +) -> Result> { + emit_package_json(intermediate_output_path).await?; + + let emit = emit(intermediate_asset, output_root); + let assets_for_source_mapping = + internal_assets_for_source_mapping(intermediate_asset, output_root); + + let entrypoint = intermediate_asset.ident().path(); + + let Some(cwd) = to_sys_path(cwd).await? else { + bail!("can only render from a disk filesystem, but `cwd = {}`", cwd.to_string().await?); + }; + let Some(entrypoint) = to_sys_path(entrypoint).await? else { + bail!( + "can only render from a disk filesystem, but `entrypoint = {}`", + entrypoint.to_string().await? + ); + }; + + emit.await?; + Ok(NodeJsPool::new( + cwd, + entrypoint, + env.read_all().await?.iter().map(|(k, v)| (k.clone(), v.clone())).collect(), + assets_for_source_mapping, + output_root, + project_dir, + available_parallelism().map_or(1, |v| v.get()), + debug, + ) + .cell()) +} + +/// Converts a module graph into node.js executable assets +#[turbo_tasks::function] +pub async fn get_intermediate_asset( + chunking_context:Vc>, + main_entry:Vc>, + other_entries:Vc, +) -> Result>> { + Ok(Vc::upcast(chunking_context.root_entry_chunk_group_asset( + chunking_context.chunk_path(main_entry.ident(), ".js".into()), + main_entry, + other_entries, + ))) +} + +#[derive(Clone, Debug)] +#[turbo_tasks::value(shared)] +pub struct ResponseHeaders { + pub status:u16, + pub headers:Vec<(RcStr, RcStr)>, +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_bytes::register(); + turbo_tasks_fs::register(); + turbopack_dev_server::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-node/Source/node_entry.rs b/crates/turbopack-node/Source/node_entry.rs new file mode 100644 index 0000000000000..03ebeaad8e46a --- /dev/null +++ b/crates/turbopack-node/Source/node_entry.rs @@ -0,0 +1,29 @@ +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + chunk::{ChunkingContext, EvaluatableAssets}, + module::Module, +}; +use turbopack_dev_server::source::ContentSourceData; + +#[turbo_tasks::value(shared)] +pub struct NodeRenderingEntry { + pub runtime_entries:Vc, + pub module:Vc>, + pub chunking_context:Vc>, + pub intermediate_output_path:Vc, + pub output_root:Vc, + pub project_dir:Vc, +} + +#[turbo_tasks::value(transparent)] +pub struct NodeRenderingEntries(Vec>); + +/// Trait that allows to get the entry module for rendering something in Node.js +#[turbo_tasks::value_trait] +pub trait NodeEntry { + fn entry(self: Vc, data:Value) -> Vc; + fn entries(self: Vc) -> Vc { + Vc::cell(vec![self.entry(Value::new(Default::default()))]) + } +} diff --git a/crates/turbopack-node/Source/pool.rs b/crates/turbopack-node/Source/pool.rs new file mode 100644 index 0000000000000..e60ed1dfe7a34 --- /dev/null +++ b/crates/turbopack-node/Source/pool.rs @@ -0,0 +1,902 @@ +use std::{ + borrow::Cow, + cmp::max, + collections::HashMap, + fmt::{Debug, Display}, + future::Future, + mem::take, + path::{Path, PathBuf}, + process::{ExitStatus, Stdio}, + sync::Arc, + time::{Duration, Instant}, +}; + +use anyhow::{Context, Result, bail}; +use futures::join; +use indexmap::IndexSet; +use owo_colors::{OwoColorize, Style}; +use parking_lot::Mutex; +use serde::{Serialize, de::DeserializeOwned}; +use tokio::{ + io::{ + AsyncBufReadExt, + AsyncRead, + AsyncReadExt, + AsyncWrite, + AsyncWriteExt, + BufReader, + Stderr, + Stdout, + stderr, + stdout, + }, + net::{TcpListener, TcpStream}, + process::{Child, ChildStderr, ChildStdout, Command}, + select, + sync::{OwnedSemaphorePermit, Semaphore}, + time::{sleep, timeout}, +}; +use turbo_tasks::{RcStr, Vc, duration_span}; +use turbo_tasks_fs::{FileSystemPath, json::parse_json_with_source_context}; +use turbopack_ecmascript::magic_identifier::unmangle_identifiers; + +use crate::{AssetsForSourceMapping, source_map::apply_source_mapping}; + +#[derive(Clone, Copy)] +pub enum FormattingMode { + /// No formatting, just print the output + Plain, + /// Use ansi colors to format the output + AnsiColors, +} + +impl FormattingMode { + pub fn magic_identifier<'a>(&self, content:impl Display + 'a) -> impl Display + 'a { + match self { + FormattingMode::Plain => format!("{{{}}}", content), + FormattingMode::AnsiColors => format!("{{{}}}", content).italic().to_string(), + } + } + + pub fn lowlight<'a>(&self, content:impl Display + 'a) -> impl Display + 'a { + match self { + FormattingMode::Plain => Style::new(), + FormattingMode::AnsiColors => Style::new().dimmed(), + } + .style(content) + } + + pub fn highlight<'a>(&self, content:impl Display + 'a) -> impl Display + 'a { + match self { + FormattingMode::Plain => Style::new(), + FormattingMode::AnsiColors => Style::new().bold().underline(), + } + .style(content) + } +} + +struct NodeJsPoolProcess { + child:Option, + connection:TcpStream, + assets_for_source_mapping:Vc, + assets_root:Vc, + project_dir:Vc, + stdout_handler:OutputStreamHandler, + stderr_handler:OutputStreamHandler, + debug:bool, +} + +impl NodeJsPoolProcess { + pub async fn apply_source_mapping<'a>( + &self, + text:&'a str, + formatting_mode:FormattingMode, + ) -> Result> { + let text = unmangle_identifiers(text, |content| formatting_mode.magic_identifier(content)); + match text { + Cow::Borrowed(text) => { + apply_source_mapping( + text, + self.assets_for_source_mapping, + self.assets_root, + self.project_dir, + formatting_mode, + ) + .await + }, + Cow::Owned(ref text) => { + let cow = apply_source_mapping( + text, + self.assets_for_source_mapping, + self.assets_root, + self.project_dir, + formatting_mode, + ) + .await?; + Ok(Cow::Owned(cow.into_owned())) + }, + } + } +} + +const CONNECT_TIMEOUT:Duration = Duration::from_secs(30); + +#[derive(Clone, PartialEq, Eq, Hash)] +struct OutputEntry { + data:Arc<[u8]>, + stack_trace:Option>, +} + +type SharedOutputSet = Arc>>; + +static GLOBAL_OUTPUT_LOCK:tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(()); +static MARKER:&[u8] = b"TURBOPACK_OUTPUT_"; +static MARKER_STR:&str = "TURBOPACK_OUTPUT_"; + +struct OutputStreamHandler { + stream:BufReader, + shared:SharedOutputSet, + assets_for_source_mapping:Vc, + root:Vc, + project_dir:Vc, + final_stream:W, +} + +impl OutputStreamHandler { + /// Pipes the `stream` from `final_stream`, but uses `shared` to deduplicate + /// lines that has beem emitted by other [OutputStreamHandler] instances + /// with the same `shared` before. + /// Returns when one operation is done. + pub async fn handle_operation(&mut self) -> Result<()> { + let Self { stream, shared, assets_for_source_mapping, root, project_dir, final_stream } = + self; + + async fn write_final( + mut bytes:&[u8], + final_stream:&mut W, + ) -> Result<()> { + let _lock = GLOBAL_OUTPUT_LOCK.lock().await; + while !bytes.is_empty() { + let count = final_stream.write(bytes).await?; + if count == 0 { + bail!("Failed to write to final stream as it was closed"); + } + bytes = &bytes[count..]; + } + Ok(()) + } + + async fn write_source_mapped_final( + bytes:&[u8], + assets_for_source_mapping:Vc, + root:Vc, + project_dir:Vc, + final_stream:&mut W, + ) -> Result<()> { + if let Ok(text) = std::str::from_utf8(bytes) { + let text = unmangle_identifiers(text, |content| { + format!("{{{}}}", content).italic().to_string() + }); + match apply_source_mapping( + text.as_ref(), + assets_for_source_mapping, + root, + project_dir, + FormattingMode::AnsiColors, + ) + .await + { + Err(e) => { + write_final( + format!("Error applying source mapping: {e}\n").as_bytes(), + final_stream, + ) + .await?; + write_final(text.as_bytes(), final_stream).await?; + }, + Ok(text) => { + write_final(text.as_bytes(), final_stream).await?; + }, + } + } else { + write_final(bytes, final_stream).await?; + } + Ok(()) + } + + let mut buffer = Vec::new(); + let mut own_output = HashMap::new(); + let mut nesting:u32 = 0; + let mut in_stack = None; + let mut stack_trace_buffer = Vec::new(); + loop { + let start = buffer.len(); + if stream + .read_until(b'\n', &mut buffer) + .await + .context("error reading from stream")? + == 0 + { + bail!("stream closed unexpectedly") + } + if buffer.len() - start == MARKER.len() + 2 + && &buffer[start..buffer.len() - 2] == MARKER + { + // This is new line + buffer.pop(); + // This is the type + match buffer.pop() { + Some(b'B') => { + stack_trace_buffer.clear(); + buffer.truncate(start); + nesting += 1; + in_stack = None; + continue; + }, + Some(b'E') => { + buffer.truncate(start); + if let Some(in_stack) = in_stack { + if nesting != 0 { + stack_trace_buffer = buffer[in_stack..].to_vec(); + } + buffer.truncate(in_stack); + } + nesting = nesting.saturating_sub(1); + in_stack = None; + if nesting == 0 { + let line = Arc::from(take(&mut buffer).into_boxed_slice()); + let stack_trace = if stack_trace_buffer.is_empty() { + None + } else { + Some(Arc::from(take(&mut stack_trace_buffer).into_boxed_slice())) + }; + let entry = OutputEntry { data:line, stack_trace }; + let occurrence_number = *own_output + .entry(entry.clone()) + .and_modify(|c| *c += 1) + .or_insert(0); + let new_entry = { + let mut shared = shared.lock(); + shared.insert((entry.clone(), occurrence_number)) + }; + if !new_entry { + // This line has been printed by another process, so we don't need + // to print it again. + continue; + } + write_source_mapped_final( + &entry.data, + *assets_for_source_mapping, + *root, + *project_dir, + final_stream, + ) + .await?; + } + }, + Some(b'S') => { + buffer.truncate(start); + in_stack = Some(start); + continue; + }, + Some(b'D') => { + // operation done + break; + }, + _ => {}, + } + } + if nesting != 0 { + // When inside of a marked output we want to aggregate until the end marker + continue; + } + + write_source_mapped_final( + &buffer, + *assets_for_source_mapping, + *root, + *project_dir, + final_stream, + ) + .await?; + buffer.clear(); + } + Ok(()) + } +} + +impl NodeJsPoolProcess { + async fn new( + cwd:&Path, + env:&HashMap, + entrypoint:&Path, + assets_for_source_mapping:Vc, + assets_root:Vc, + project_dir:Vc, + shared_stdout:SharedOutputSet, + shared_stderr:SharedOutputSet, + debug:bool, + ) -> Result { + let guard = Box::new(duration_span!("Node.js process startup")); + let listener = TcpListener::bind("127.0.0.1:0").await.context("binding to a port")?; + let port = listener.local_addr().context("getting port")?.port(); + let mut cmd = Command::new("node"); + cmd.current_dir(cwd); + if debug { + cmd.arg("--inspect-brk"); + } + cmd.arg(entrypoint); + cmd.arg(port.to_string()); + cmd.env_clear(); + cmd.env( + "PATH", + std::env::var("PATH").expect("the PATH environment variable should always be set"), + ); + #[cfg(target_family = "windows")] + cmd.env( + "SystemRoot", + std::env::var("SystemRoot") + .expect("the SystemRoot environment variable should always be set"), + ); + cmd.envs(env); + cmd.stderr(Stdio::piped()); + cmd.stdout(Stdio::piped()); + cmd.kill_on_drop(true); + + let mut child = cmd.spawn().context("spawning node pooled process")?; + + let timeout = if debug { Duration::MAX } else { CONNECT_TIMEOUT }; + + async fn get_output(child:&mut Child) -> Result<(String, String)> { + let mut stdout = Vec::new(); + let mut stderr = Vec::new(); + child.stdout.take().unwrap().read_to_end(&mut stdout).await?; + child.stderr.take().unwrap().read_to_end(&mut stderr).await?; + fn clean(buffer:Vec) -> Result { + Ok(String::from_utf8(buffer)? + .lines() + .filter(|line| { + line.len() != MARKER_STR.len() + 1 && !line.starts_with(MARKER_STR) + }) + .collect::>() + .join("\n")) + } + Ok((clean(stdout)?, clean(stderr)?)) + } + + let (connection, _) = select! { + connection = listener.accept() => connection.context("accepting connection")?, + status = child.wait() => { + match status { + Ok(status) => { + let (stdout, stderr) = get_output(&mut child).await?; + bail!("node process exited before we could connect to it with {status}\nProcess output:\n{stdout}\nProcess error output:\n{stderr}"); + } + Err(err) => { + let _ = child.start_kill(); + let (stdout, stderr) = get_output(&mut child).await?; + bail!("node process exited before we could connect to it: {err:?}\nProcess output:\n{stdout}\nProcess error output:\n{stderr}"); + }, + } + }, + _ = sleep(timeout) => { + let _ = child.start_kill(); + let (stdout, stderr) = get_output(&mut child).await?; + bail!("timed out waiting for the Node.js process to connect ({timeout:?} timeout)\nProcess output:\n{stdout}\nProcess error output:\n{stderr}"); + }, + }; + + let child_stdout = BufReader::new(child.stdout.take().unwrap()); + let child_stderr = BufReader::new(child.stderr.take().unwrap()); + + let stdout_handler = OutputStreamHandler { + stream:child_stdout, + shared:shared_stdout, + assets_for_source_mapping, + root:assets_root, + project_dir, + final_stream:stdout(), + }; + let stderr_handler = OutputStreamHandler { + stream:child_stderr, + shared:shared_stderr, + assets_for_source_mapping, + root:assets_root, + project_dir, + final_stream:stderr(), + }; + + let mut process = Self { + child:Some(child), + connection, + assets_for_source_mapping, + assets_root, + project_dir, + stdout_handler, + stderr_handler, + debug, + }; + + drop(guard); + + let guard = duration_span!("Node.js initialization"); + let ready_signal = process.recv().await?; + + if !ready_signal.is_empty() { + bail!( + "Node.js process didn't send the expected ready signal\nOutput:\n{}", + String::from_utf8_lossy(&ready_signal) + ); + } + + drop(guard); + + Ok(process) + } + + async fn recv(&mut self) -> Result> { + let connection = &mut self.connection; + async fn with_timeout>( + debug:bool, + fast:bool, + future:impl Future> + Send, + ) -> Result { + if debug { + future.await.map_err(Into::into) + } else { + let time = if fast { Duration::from_secs(20) } else { Duration::from_secs(5 * 60) }; + timeout(time, future) + .await + .context("timeout while receiving message from process")? + .map_err(Into::into) + } + } + let debug = self.debug; + let recv_future = async move { + let packet_len = with_timeout(debug, false, connection.read_u32()) + .await + .context("reading packet length")? + .try_into() + .context("storing packet length")?; + let mut packet_data = vec![0; packet_len]; + with_timeout(debug, true, connection.read_exact(&mut packet_data)) + .await + .context("reading packet data")?; + Ok::<_, anyhow::Error>(packet_data) + }; + let (result, stdout, stderr) = join!( + recv_future, + self.stdout_handler.handle_operation(), + self.stderr_handler.handle_operation(), + ); + let result = result?; + stdout.context("unable to handle stdout from the Node.js process in a structured way")?; + stderr.context("unable to handle stderr from the Node.js process in a structured way")?; + Ok(result) + } + + async fn send(&mut self, packet_data:Vec) -> Result<()> { + self.connection + .write_u32(packet_data.len().try_into().context("packet length does not fit into u32")?) + .await + .context("writing packet length")?; + self.connection.write_all(&packet_data).await.context("writing packet data")?; + Ok(()) + } +} + +#[derive(Default)] +struct NodeJsPoolStats { + pub total_bootup_time:Duration, + pub bootup_count:u32, + pub total_cold_process_time:Duration, + pub cold_process_count:u32, + pub total_warm_process_time:Duration, + pub warm_process_count:u32, + pub workers:u32, + pub booting_workers:u32, + pub queued_tasks:u32, +} + +impl NodeJsPoolStats { + fn add_bootup_time(&mut self, time:Duration) { + self.total_bootup_time += time; + self.bootup_count += 1; + } + + fn add_booting_worker(&mut self) { + self.booting_workers += 1; + self.workers += 1; + } + + fn finished_booting_worker(&mut self) { self.booting_workers -= 1; } + + fn remove_worker(&mut self) { self.workers -= 1; } + + fn add_queued_task(&mut self) { self.queued_tasks += 1; } + + fn add_cold_process_time(&mut self, time:Duration) { + self.total_cold_process_time += time; + self.cold_process_count += 1; + self.queued_tasks -= 1; + } + + fn add_warm_process_time(&mut self, time:Duration) { + self.total_warm_process_time += time; + self.warm_process_count += 1; + self.queued_tasks -= 1; + } + + fn estimated_bootup_time(&self) -> Duration { + if self.bootup_count == 0 { + Duration::from_millis(200) + } else { + self.total_bootup_time / self.bootup_count + } + } + + fn estimated_warm_process_time(&self) -> Duration { + if self.warm_process_count == 0 { + self.estimated_cold_process_time() + } else { + self.total_warm_process_time / self.warm_process_count + } + } + + fn estimated_cold_process_time(&self) -> Duration { + if self.cold_process_count == 0 { + // We assume cold processing is half of bootup time + self.estimated_bootup_time() / 2 + } else { + self.total_cold_process_time / self.cold_process_count + } + } + + fn wait_time_before_bootup(&self) -> Duration { + if self.workers == 0 { + return Duration::ZERO; + } + let booting_workers = self.booting_workers; + let workers = self.workers; + let warm_process_time = self.estimated_warm_process_time(); + let expected_completion = self.expected_completion(workers, booting_workers); + + let new_process_duration = + self.estimated_bootup_time() + self.estimated_cold_process_time(); + if expected_completion + warm_process_time < new_process_duration { + // Running the task with the existing warm pool is faster + return (expected_completion + warm_process_time + new_process_duration) / 2; + } + + let expected_completion_with_additional_worker = + max(new_process_duration, self.expected_completion(workers + 1, booting_workers + 1)); + if expected_completion > expected_completion_with_additional_worker { + // Scaling up the pool would help to complete work faster + return Duration::ZERO; + } + + // It's expected to be faster if we queue the task + (expected_completion + expected_completion_with_additional_worker) / 2 + } + + fn expected_completion(&self, workers:u32, booting_workers:u32) -> Duration { + if workers == 0 { + return Duration::MAX; + } + let bootup_time = self.estimated_bootup_time(); + let cold_process_time = self.estimated_cold_process_time(); + let warm_process_time = self.estimated_warm_process_time(); + let expected_full_workers_in = booting_workers * (bootup_time / 2 + cold_process_time); + let expected_completed_task_until_full_workers = { + let millis = max(1, warm_process_time.as_millis()); + let ready_workers = workers - booting_workers; + (expected_full_workers_in.as_millis() / millis) as u32 * ready_workers + }; + let remaining_tasks = + self.queued_tasks.saturating_sub(expected_completed_task_until_full_workers); + if remaining_tasks > 0 { + expected_full_workers_in + warm_process_time * remaining_tasks / workers + } else { + warm_process_time * self.queued_tasks / workers + } + } +} + +impl Debug for NodeJsPoolStats { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("NodeJsPoolStats") + .field("queued_tasks", &self.queued_tasks) + .field("workers", &self.workers) + .field("booting_workers", &self.booting_workers) + .field( + "expected_completion", + &self.expected_completion(self.workers, self.booting_workers), + ) + .field("bootup_time", &self.estimated_bootup_time()) + .field("cold_process_time", &self.estimated_cold_process_time()) + .field("warm_process_time", &self.estimated_warm_process_time()) + .field("bootup_count", &self.bootup_count) + .field("cold_process_count", &self.cold_process_count) + .field("warm_process_count", &self.warm_process_count) + .finish() + } +} + +enum AcquiredPermits { + Idle { + // This is used for drop + #[allow(dead_code)] + concurrency_permit:OwnedSemaphorePermit, + }, + Fresh { + // This is used for drop + #[allow(dead_code)] + concurrency_permit:OwnedSemaphorePermit, + // This is used for drop + #[allow(dead_code)] + bootup_permit:OwnedSemaphorePermit, + }, +} + +/// A pool of Node.js workers operating on [entrypoint] with specific [cwd] and +/// [env]. +/// +/// The pool will spawn processes when needed and reuses old ones. It will never +/// spawn more then a certain number of concurrent processes. This is specified +/// with the `concurrency` argument in the constructor. +/// +/// The worker will *not* use the env of the parent process by default. All env +/// vars need to be provided to make the execution as pure as possible. +#[turbo_tasks::value(into = "new", cell = "new", serialization = "none", eq = "manual")] +pub struct NodeJsPool { + cwd:PathBuf, + entrypoint:PathBuf, + env:HashMap, + pub assets_for_source_mapping:Vc, + pub assets_root:Vc, + pub project_dir:Vc, + #[turbo_tasks(trace_ignore, debug_ignore)] + processes:Arc>>, + /// Semaphore to limit the number of concurrent operations in general + #[turbo_tasks(trace_ignore, debug_ignore)] + concurrency_semaphore:Arc, + /// Semaphore to limit the number of concurrently booting up processes + /// (excludes one-off processes) + #[turbo_tasks(trace_ignore, debug_ignore)] + bootup_semaphore:Arc, + /// Semaphore to wait for an idle process to become available + #[turbo_tasks(trace_ignore, debug_ignore)] + idle_process_semaphore:Arc, + #[turbo_tasks(trace_ignore, debug_ignore)] + shared_stdout:SharedOutputSet, + #[turbo_tasks(trace_ignore, debug_ignore)] + shared_stderr:SharedOutputSet, + debug:bool, + #[turbo_tasks(trace_ignore, debug_ignore)] + stats:Arc>, +} + +impl NodeJsPool { + /// * debug: Whether to automatically enable Node's `--inspect-brk` when + /// spawning it. Note: automatically overrides concurrency to 1. + pub(super) fn new( + cwd:PathBuf, + entrypoint:PathBuf, + env:HashMap, + assets_for_source_mapping:Vc, + assets_root:Vc, + project_dir:Vc, + concurrency:usize, + debug:bool, + ) -> Self { + Self { + cwd, + entrypoint, + env, + assets_for_source_mapping, + assets_root, + project_dir, + processes:Arc::new(Mutex::new(Vec::new())), + concurrency_semaphore:Arc::new(Semaphore::new(if debug { 1 } else { concurrency })), + bootup_semaphore:Arc::new(Semaphore::new(1)), + idle_process_semaphore:Arc::new(Semaphore::new(0)), + shared_stdout:Arc::new(Mutex::new(IndexSet::new())), + shared_stderr:Arc::new(Mutex::new(IndexSet::new())), + debug, + stats:Default::default(), + } + } + + async fn acquire_process(&self) -> Result<(NodeJsPoolProcess, AcquiredPermits)> { + { + self.stats.lock().add_queued_task(); + } + + let concurrency_permit = self.concurrency_semaphore.clone().acquire_owned().await?; + + let bootup = async { + let permit = self.bootup_semaphore.clone().acquire_owned().await; + let wait_time = self.stats.lock().wait_time_before_bootup(); + tokio::time::sleep(wait_time).await; + permit + }; + + select! { + idle_process_permit = self.idle_process_semaphore.clone().acquire_owned() => { + let idle_process_permit = idle_process_permit.context("acquiring idle process permit")?; + let process = { + let mut processes = self.processes.lock(); + processes.pop().unwrap() + }; + idle_process_permit.forget(); + Ok((process, AcquiredPermits::Idle { concurrency_permit })) + }, + bootup_permit = bootup => { + let bootup_permit = bootup_permit.context("acquiring bootup permit")?; + { + self.stats.lock().add_booting_worker(); + } + let (process, bootup_time) = self.create_process().await?; + // Update the worker count + { + let mut stats = self.stats.lock(); + stats.add_bootup_time(bootup_time); + stats.finished_booting_worker(); + } + // Increase the allowed booting up processes + self.bootup_semaphore.add_permits(1); + Ok((process, AcquiredPermits::Fresh { concurrency_permit, bootup_permit })) + } + } + } + + async fn create_process(&self) -> Result<(NodeJsPoolProcess, Duration), anyhow::Error> { + let start = Instant::now(); + let process = NodeJsPoolProcess::new( + self.cwd.as_path(), + &self.env, + self.entrypoint.as_path(), + self.assets_for_source_mapping, + self.assets_root, + self.project_dir, + self.shared_stdout.clone(), + self.shared_stderr.clone(), + self.debug, + ) + .await + .context("creating new process")?; + Ok((process, start.elapsed())) + } + + pub async fn operation(&self) -> Result { + // Acquire a running process (handles concurrency limits, boots up the process) + let (process, permits) = self.acquire_process().await?; + + Ok(NodeJsOperation { + process:Some(process), + permits, + processes:self.processes.clone(), + idle_process_semaphore:self.idle_process_semaphore.clone(), + start:Instant::now(), + stats:self.stats.clone(), + allow_process_reuse:true, + }) + } +} + +pub struct NodeJsOperation { + process:Option, + // This is used for drop + #[allow(dead_code)] + permits:AcquiredPermits, + processes:Arc>>, + idle_process_semaphore:Arc, + start:Instant, + stats:Arc>, + allow_process_reuse:bool, +} + +impl NodeJsOperation { + async fn with_process<'a, F:Future> + Send + 'a, T>( + &'a mut self, + f:impl FnOnce(&'a mut NodeJsPoolProcess) -> F, + ) -> Result { + let process = self.process.as_mut().context("Node.js operation already finished")?; + + if !self.allow_process_reuse { + bail!("Node.js process is no longer usable"); + } + + let result = f(process).await; + if result.is_err() && self.allow_process_reuse { + self.stats.lock().remove_worker(); + self.allow_process_reuse = false; + } + result + } + + pub async fn recv(&mut self) -> Result + where + M: DeserializeOwned, { + let message = self + .with_process(|process| { + async move { process.recv().await.context("failed to receive message") } + }) + .await?; + let message = std::str::from_utf8(&message).context("message is not valid UTF-8")?; + parse_json_with_source_context(message).context("failed to deserialize message") + } + + pub async fn send(&mut self, message:M) -> Result<()> + where + M: Serialize, { + let message = serde_json::to_vec(&message).context("failed to serialize message")?; + self.with_process(|process| { + async move { + timeout(Duration::from_secs(30), process.send(message)) + .await + .context("timeout while sending message")? + .context("failed to send message")?; + Ok(()) + } + }) + .await + } + + pub async fn wait_or_kill(mut self) -> Result { + let mut process = self.process.take().context("Node.js operation already finished")?; + + if self.allow_process_reuse { + self.stats.lock().remove_worker(); + } + + let mut child = process.child.take().context("Node.js operation already finished")?; + + // Ignore error since we are not sure if the process is still alive + let _ = child.start_kill(); + let status = timeout(Duration::from_secs(30), child.wait()) + .await + .context("timeout while waiting for process end")? + .context("waiting for process end")?; + + Ok(status) + } + + pub fn disallow_reuse(&mut self) { + if self.allow_process_reuse { + self.stats.lock().remove_worker(); + self.allow_process_reuse = false; + } + } + + pub async fn apply_source_mapping<'a>( + &self, + text:&'a str, + formatting_mode:FormattingMode, + ) -> Result> { + if let Some(process) = self.process.as_ref() { + process.apply_source_mapping(text, formatting_mode).await + } else { + Ok(Cow::Borrowed(text)) + } + } +} + +impl Drop for NodeJsOperation { + fn drop(&mut self) { + if let Some(process) = self.process.take() { + let elapsed = self.start.elapsed(); + { + let stats = &mut self.stats.lock(); + match self.permits { + AcquiredPermits::Idle { .. } => stats.add_warm_process_time(elapsed), + AcquiredPermits::Fresh { .. } => stats.add_cold_process_time(elapsed), + } + } + if self.allow_process_reuse { + self.processes.lock().push(process); + self.idle_process_semaphore.add_permits(1); + } + } + } +} diff --git a/crates/turbopack-node/Source/render/error.html b/crates/turbopack-node/Source/render/error.html new file mode 100644 index 0000000000000..c526518f929ce --- /dev/null +++ b/crates/turbopack-node/Source/render/error.html @@ -0,0 +1,118 @@ + + + + + ${TITLE} + + +

    + + + +
    +
    +

    ${STATUS_CODE}

    +
    +

    ${TITLE}.

    +
    +
    +
    +

    Details

    +
    ${DETAILS}
    +
    +
    +
    + + diff --git a/crates/turbopack-node/Source/render/error_page.rs b/crates/turbopack-node/Source/render/error_page.rs new file mode 100644 index 0000000000000..c1e90e7daa2a7 --- /dev/null +++ b/crates/turbopack-node/Source/render/error_page.rs @@ -0,0 +1,39 @@ +use anyhow::{Context, Result}; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::embed_file; + +#[turbo_tasks::function] +pub(super) async fn error_html(status_code:u16, title:RcStr, details:RcStr) -> Result> { + let html = create_html(status_code, title, details).await?; + + Ok(Vc::cell(html.into())) +} + +#[turbo_tasks::function] +pub(super) async fn error_html_body( + status_code:u16, + title:RcStr, + details:RcStr, +) -> Result> { + let html = create_html(status_code, title, details).await?; + + let (_, body) = html.split_once("").context("no body in html")?; + let (body, _) = body.split_once("").context("no body in html")?; + + Ok(Vc::cell(body.into())) +} + +async fn create_html(status_code:u16, title:RcStr, details:RcStr) -> Result { + let file_content = embed_file!("src/render/error.html").await?; + let file = file_content + .as_content() + .context("embedded file not found (this should not happen)")?; + + let html = file.content().to_str().context("couldn't convert embedded html to string")?; + + let html = html.replace("${TITLE}", &title); + let html = html.replace("${STATUS_CODE}", &status_code.to_string()); + let html = html.replace("${DETAILS}", &details); + + Ok(html) +} diff --git a/crates/turbopack-node/Source/render/issue.rs b/crates/turbopack-node/Source/render/issue.rs new file mode 100644 index 0000000000000..5b6f1707fa106 --- /dev/null +++ b/crates/turbopack-node/Source/render/issue.rs @@ -0,0 +1,44 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueStage, OptionStyledString, StyledString}; + +#[turbo_tasks::value(shared)] +#[derive(Copy, Clone)] +pub struct RenderingIssue { + pub file_path:Vc, + pub message:Vc, + pub status:Option, +} + +#[turbo_tasks::value_impl] +impl Issue for RenderingIssue { + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Error during SSR Rendering".into()).cell() + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::CodeGen.cell() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.file_path } + + #[turbo_tasks::function] + fn description(&self) -> Vc { Vc::cell(Some(self.message)) } + + #[turbo_tasks::function] + async fn detail(&self) -> Result> { + let mut details = vec![]; + + if let Some(status) = self.status { + if status != 0 { + details.push(StyledString::Text(format!("Node.js exit code: {status}").into())); + } + } + + Ok(Vc::cell(Some(StyledString::Stack(details).cell()))) + } + + // TODO parse stack trace into source location +} diff --git a/crates/turbopack-node/Source/render/mod.rs b/crates/turbopack-node/Source/render/mod.rs new file mode 100644 index 0000000000000..5be57086c5dfc --- /dev/null +++ b/crates/turbopack-node/Source/render/mod.rs @@ -0,0 +1,71 @@ +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; +use serde_json::Value as JsonValue; +use turbo_tasks::{RcStr, ReadRef}; + +use crate::{ResponseHeaders, StructuredError, route_matcher::Param}; + +pub(crate) mod error_page; +pub mod issue; +pub mod node_api_source; +pub mod render_proxy; +pub mod render_static; +pub mod rendered_source; + +#[turbo_tasks::value(shared)] +#[serde(rename_all = "camelCase")] +pub struct RenderData { + params:IndexMap, + method:RcStr, + url:RcStr, + original_url:RcStr, + raw_query:RcStr, + raw_headers:Vec<(RcStr, RcStr)>, + path:RcStr, + data:Option>, +} + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +enum RenderStaticOutgoingMessage<'a> { + Headers { data:&'a RenderData }, +} + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +enum RenderProxyOutgoingMessage<'a> { + Headers { data:&'a RenderData }, + BodyChunk { data:&'a [u8] }, + BodyEnd, +} + +#[derive(Deserialize, Debug)] +#[serde(tag = "type", rename_all = "camelCase")] +enum RenderProxyIncomingMessage { + Headers { data:ResponseHeaders }, + BodyChunk { data:Vec }, + BodyEnd, + Error(StructuredError), +} + +#[derive(Deserialize, Debug)] +#[serde(tag = "type", rename_all = "camelCase")] +enum RenderStaticIncomingMessage { + #[serde(rename_all = "camelCase")] + Response { + status_code:u16, + headers:Vec<(RcStr, RcStr)>, + body:RcStr, + }, + Headers { + data:ResponseHeaders, + }, + BodyChunk { + data:Vec, + }, + BodyEnd, + Rewrite { + path:RcStr, + }, + Error(StructuredError), +} diff --git a/crates/turbopack-node/Source/render/node_api_source.rs b/crates/turbopack-node/Source/render/node_api_source.rs new file mode 100644 index 0000000000000..2e0aa8c5ee151 --- /dev/null +++ b/crates/turbopack-node/Source/render/node_api_source.rs @@ -0,0 +1,200 @@ +use anyhow::{Result, anyhow}; +use indexmap::IndexSet; +use serde_json::Value as JsonValue; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::introspect::{ + Introspectable, + IntrospectableChildren, + module::IntrospectableModule, + output_asset::IntrospectableOutputAsset, +}; +use turbopack_dev_server::source::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + ContentSourceDataVary, + GetContentSourceContent, + route_tree::{BaseSegment, RouteTree, RouteType}, +}; + +use super::{RenderData, render_proxy::render_proxy}; +use crate::{get_intermediate_asset, node_entry::NodeEntry, route_matcher::RouteMatcher}; + +/// Creates a [NodeApiContentSource]. +#[turbo_tasks::function] +pub fn create_node_api_source( + cwd:Vc, + env:Vc>, + base_segments:Vec, + route_type:RouteType, + server_root:Vc, + route_match:Vc>, + pathname:Vc, + entry:Vc>, + render_data:Vc, + debug:bool, +) -> Vc> { + Vc::upcast( + NodeApiContentSource { + cwd, + env, + base_segments, + route_type, + server_root, + pathname, + route_match, + entry, + render_data, + debug, + } + .cell(), + ) +} + +/// A content source that proxies API requests to one-off Node.js +/// servers running the passed `entry` when it matches a `path_regex`. +/// +/// It needs a temporary directory (`intermediate_output_path`) to place file +/// for Node.js execution during rendering. The `chunking_context` should emit +/// to this directory. +#[turbo_tasks::value] +pub struct NodeApiContentSource { + cwd:Vc, + env:Vc>, + base_segments:Vec, + route_type:RouteType, + server_root:Vc, + pathname:Vc, + route_match:Vc>, + entry:Vc>, + render_data:Vc, + debug:bool, +} + +#[turbo_tasks::value_impl] +impl NodeApiContentSource { + #[turbo_tasks::function] + pub async fn get_pathname(self: Vc) -> Result> { Ok(self.await?.pathname) } +} + +#[turbo_tasks::value_impl] +impl ContentSource for NodeApiContentSource { + #[turbo_tasks::function] + async fn get_routes(self: Vc) -> Result> { + let this = self.await?; + Ok(RouteTree::new_route( + this.base_segments.clone(), + this.route_type.clone(), + Vc::upcast(self), + )) + } +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for NodeApiContentSource { + #[turbo_tasks::function] + fn vary(&self) -> Vc { + ContentSourceDataVary { + method:true, + url:true, + original_url:true, + raw_headers:true, + raw_query:true, + body:true, + cache_buster:true, + ..Default::default() + } + .cell() + } + + #[turbo_tasks::function] + async fn get( + &self, + path:RcStr, + data:Value, + ) -> Result> { + let Some(params) = &*self.route_match.params(path.clone()).await? else { + return Err(anyhow!("Non matching path provided")); + }; + let ContentSourceData { + method: Some(method), + url: Some(url), + original_url: Some(original_url), + raw_headers: Some(raw_headers), + raw_query: Some(raw_query), + body: Some(body), + .. + } = &*data + else { + return Err(anyhow!("Missing request data")); + }; + let entry = self.entry.entry(data.clone()).await?; + Ok(ContentSourceContent::HttpProxy(render_proxy( + self.cwd, + self.env, + self.server_root.join(path.clone()), + entry.module, + entry.runtime_entries, + entry.chunking_context, + entry.intermediate_output_path, + entry.output_root, + entry.project_dir, + RenderData { + params:params.clone(), + method:method.clone(), + url:url.clone(), + original_url:original_url.clone(), + raw_query:raw_query.clone(), + raw_headers:raw_headers.clone(), + path:format!("/{}", path).into(), + data:Some(self.render_data.await?), + } + .cell(), + *body, + self.debug, + )) + .cell()) + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("node api content source".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for NodeApiContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { self.pathname } + + #[turbo_tasks::function] + async fn details(&self) -> Result> { + Ok(Vc::cell( + format!("base: {:?}\ntype: {:?}", self.base_segments, self.route_type).into(), + )) + } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + let mut set = IndexSet::new(); + for &entry in self.entry.entries().await?.iter() { + let entry = entry.await?; + set.insert(( + Vc::cell("module".into()), + IntrospectableModule::new(Vc::upcast(entry.module)), + )); + set.insert(( + Vc::cell("intermediate asset".into()), + IntrospectableOutputAsset::new(get_intermediate_asset( + entry.chunking_context, + Vc::upcast(entry.module), + entry.runtime_entries, + )), + )); + } + Ok(Vc::cell(set)) + } +} diff --git a/crates/turbopack-node/Source/render/render_proxy.rs b/crates/turbopack-node/Source/render/render_proxy.rs new file mode 100644 index 0000000000000..3a860d6b2c530 --- /dev/null +++ b/crates/turbopack-node/Source/render/render_proxy.rs @@ -0,0 +1,355 @@ +use anyhow::{Result, anyhow, bail}; +use async_stream::try_stream as generator; +use futures::{ + SinkExt, + StreamExt, + TryStreamExt, + channel::mpsc::{UnboundedSender, unbounded}, + pin_mut, +}; +use parking_lot::Mutex; +use turbo_tasks::{ + RawVc, + RcStr, + ValueToString, + Vc, + duration_span, + mark_finished, + prevent_gc, + util::SharedError, +}; +use turbo_tasks_bytes::{Bytes, Stream}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + chunk::{ChunkingContext, EvaluatableAssets}, + error::PrettyPrintError, + issue::{IssueExt, StyledString}, + module::Module, +}; +use turbopack_dev_server::source::{Body, ProxyResult}; + +use super::{ + RenderData, + RenderProxyIncomingMessage, + RenderProxyOutgoingMessage, + ResponseHeaders, + issue::RenderingIssue, +}; +use crate::{ + get_intermediate_asset, + get_renderer_pool, + pool::NodeJsOperation, + render::error_page::error_html, + source_map::trace_stack, +}; + +/// Renders a module as static HTML in a node.js process. +#[turbo_tasks::function] +pub async fn render_proxy( + cwd:Vc, + env:Vc>, + path:Vc, + module:Vc>, + runtime_entries:Vc, + chunking_context:Vc>, + intermediate_output_path:Vc, + output_root:Vc, + project_dir:Vc, + data:Vc, + body:Vc, + debug:bool, +) -> Result> { + let render = render_stream( + cwd, + env, + path, + module, + runtime_entries, + chunking_context, + intermediate_output_path, + output_root, + project_dir, + data, + body, + debug, + ) + .await?; + + let mut stream = render.read(); + let first = match stream.try_next().await? { + Some(f) => f, + None => { + // If an Error was received first, then it would have been + // transformed into a proxy err error response. + bail!("did not receive response from render"); + }, + }; + + let RenderItem::Headers(data) = first else { + bail!("did not receive headers from render"); + }; + + let body = Body::from_stream(stream.map(|item| { + match item { + Ok(RenderItem::BodyChunk(b)) => Ok(b), + Ok(v) => Err(SharedError::new(anyhow!("unexpected render item: {:#?}", v))), + Err(e) => Err(e), + } + })); + let result = ProxyResult { status:data.status, headers:data.headers, body }; + + Ok(result.cell()) +} + +async fn proxy_error( + path:Vc, + error:anyhow::Error, + operation:Option, +) -> Result<(u16, RcStr)> { + let message = format!("{}", PrettyPrintError(&error)); + + let status = match operation { + Some(operation) => Some(operation.wait_or_kill().await?), + None => None, + }; + + let mut details = vec![]; + if let Some(status) = status { + details.push(format!("status: {status}")); + } + + let status_code = 500; + let body = error_html( + status_code, + "An error occurred while proxying the request to Node.js".into(), + format!("{message}\n\n{}", details.join("\n")).into(), + ) + .await? + .clone_value(); + + RenderingIssue { + file_path:path, + message:StyledString::Text(message.into()).cell(), + status:status.and_then(|status| status.code()), + } + .cell() + .emit(); + + Ok((status_code, body)) +} + +#[derive(Clone, Debug)] +#[turbo_tasks::value] +enum RenderItem { + Headers(ResponseHeaders), + BodyChunk(Bytes), +} + +type RenderItemResult = Result; + +#[turbo_tasks::value(eq = "manual", cell = "new", serialization = "none")] +struct RenderStreamSender { + #[turbo_tasks(trace_ignore, debug_ignore)] + get:Box UnboundedSender + Send + Sync>, +} + +#[turbo_tasks::value(transparent)] +struct RenderStream(#[turbo_tasks(trace_ignore)] Stream); + +#[turbo_tasks::function] +fn render_stream( + cwd:Vc, + env:Vc>, + path:Vc, + module:Vc>, + runtime_entries:Vc, + chunking_context:Vc>, + intermediate_output_path:Vc, + output_root:Vc, + project_dir:Vc, + data:Vc, + body:Vc, + debug:bool, +) -> Vc { + // TODO: The way we invoke render_stream_internal as side effect is not + // GC-safe, so we disable GC for this task. + prevent_gc(); + + // Note the following code uses some hacks to create a child task that produces + // a stream that is returned by this task. + + // We create a new cell in this task, which will be updated from the + // [render_stream_internal] task. + let cell = turbo_tasks::macro_helpers::find_cell_by_type(*RENDERSTREAM_VALUE_TYPE_ID); + + // We initialize the cell with a stream that is open, but has no values. + // The first [render_stream_internal] pipe call will pick up that stream. + let (sender, receiver) = unbounded(); + cell.update_shared(RenderStream(Stream::new_open(vec![], Box::new(receiver)))); + let initial = Mutex::new(Some(sender)); + + // run the evaluation as side effect + let _ = render_stream_internal( + cwd, + env, + path, + module, + runtime_entries, + chunking_context, + intermediate_output_path, + output_root, + project_dir, + data, + body, + RenderStreamSender { + get:Box::new(move || { + if let Some(sender) = initial.lock().take() { + sender + } else { + // In cases when only [render_stream_internal] is (re)executed, we need to + // update the old stream with a new value. + let (sender, receiver) = unbounded(); + cell.update_shared(RenderStream(Stream::new_open(vec![], Box::new(receiver)))); + sender + } + }), + } + .cell(), + debug, + ); + + let raw:RawVc = cell.into(); + raw.into() +} + +#[turbo_tasks::function] +async fn render_stream_internal( + cwd:Vc, + env:Vc>, + path:Vc, + module:Vc>, + runtime_entries:Vc, + chunking_context:Vc>, + intermediate_output_path:Vc, + output_root:Vc, + project_dir:Vc, + data:Vc, + body:Vc, + sender:Vc, + debug:bool, +) -> Result> { + mark_finished(); + let Ok(sender) = sender.await else { + // Impossible to handle the error in a good way. + return Ok(Default::default()); + }; + + let stream = generator! { + let intermediate_asset = get_intermediate_asset( + chunking_context, + module, + runtime_entries, + ); + let pool = get_renderer_pool( + cwd, + env, + intermediate_asset, + intermediate_output_path, + output_root, + project_dir, + debug, + ); + + // Read this strongly consistent, since we don't want to run inconsistent + // node.js code. + let pool = pool.strongly_consistent().await?; + let data = data.await?; + let mut operation = pool.operation().await?; + + // First, send the render data. + operation + .send(RenderProxyOutgoingMessage::Headers { data: &data }) + .await?; + // Then, send the binary body in chunks. + let mut body = body.await?.read(); + while let Some(data) = body.next().await { + operation + .send(RenderProxyOutgoingMessage::BodyChunk { data: &data.unwrap() }) + .await?; + } + operation.send(RenderProxyOutgoingMessage::BodyEnd).await?; + + let entry = module.ident().to_string().await?; + let guard = duration_span!("Node.js api execution", entry = display(entry)); + + match operation.recv().await? { + RenderProxyIncomingMessage::Headers { data } => yield RenderItem::Headers(data), + RenderProxyIncomingMessage::Error(error) => { + drop(guard); + // If we don't get headers, then something is very wrong. Instead, we send down a + // 500 proxy error as if it were the proper result. + let trace = trace_stack( + error, + intermediate_asset, + intermediate_output_path, + project_dir + ) + .await?; + let (status, body) = proxy_error(path, anyhow!("error rendering: {}", trace), Some(operation)).await?; + yield RenderItem::Headers(ResponseHeaders { + status, + headers: vec![( + "content-type".into(), + "text/html; charset=utf-8".into(), + )], + }); + yield RenderItem::BodyChunk(body.into_owned().into_bytes().into()); + return; + } + v => { + drop(guard); + Err(anyhow!("unexpected message during rendering: {:#?}", v))?; + return; + }, + }; + + loop { + match operation.recv().await? { + RenderProxyIncomingMessage::BodyChunk { data } => { + yield RenderItem::BodyChunk(data.into()); + } + RenderProxyIncomingMessage::BodyEnd => break, + RenderProxyIncomingMessage::Error(error) => { + drop(guard); + // We have already started to send a result, so we can't change the + // headers/body to a proxy error. + operation.disallow_reuse(); + let trace = + trace_stack(error, intermediate_asset, intermediate_output_path, project_dir).await?; + Err(anyhow!("error during streaming render: {}", trace))?; + return; + } + v => { + drop(guard); + Err(anyhow!("unexpected message during rendering: {:#?}", v))?; + return; + }, + } + } + drop(guard); + }; + + let mut sender = (sender.get)(); + pin_mut!(stream); + while let Some(value) = stream.next().await { + if sender.send(value).await.is_err() { + return Ok(Default::default()); + } + if sender.flush().await.is_err() { + return Ok(Default::default()); + } + } + + Ok(Default::default()) +} diff --git a/crates/turbopack-node/Source/render/render_static.rs b/crates/turbopack-node/Source/render/render_static.rs new file mode 100644 index 0000000000000..f0f5b019a26b2 --- /dev/null +++ b/crates/turbopack-node/Source/render/render_static.rs @@ -0,0 +1,401 @@ +use anyhow::{Context, Result, anyhow, bail}; +use async_stream::try_stream as generator; +use futures::{ + SinkExt, + StreamExt, + TryStreamExt, + channel::mpsc::{UnboundedSender, unbounded}, + pin_mut, +}; +use parking_lot::Mutex; +use turbo_tasks::{ + RawVc, + ValueToString, + Vc, + duration_span, + mark_finished, + prevent_gc, + util::SharedError, +}; +use turbo_tasks_bytes::{Bytes, Stream}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{File, FileSystemPath}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkingContext, EvaluatableAssets}, + error::PrettyPrintError, + issue::{IssueExt, StyledString}, + module::Module, +}; +use turbopack_dev_server::{ + html::DevHtmlAsset, + source::{Body, HeaderList, Rewrite, RewriteBuilder}, +}; + +use super::{ + RenderData, + RenderStaticIncomingMessage, + RenderStaticOutgoingMessage, + issue::RenderingIssue, +}; +use crate::{ + ResponseHeaders, + get_intermediate_asset, + get_renderer_pool, + pool::NodeJsOperation, + render::error_page::error_html_body, + source_map::trace_stack, +}; + +#[derive(Clone, Debug)] +#[turbo_tasks::value] +pub enum StaticResult { + Content { content:Vc, status_code:u16, headers:Vc }, + StreamedContent { status:u16, headers:Vc, body:Body }, + Rewrite(Vc), +} + +#[turbo_tasks::value_impl] +impl StaticResult { + #[turbo_tasks::function] + pub fn content(content:Vc, status_code:u16, headers:Vc) -> Vc { + StaticResult::Content { content, status_code, headers }.cell() + } + + #[turbo_tasks::function] + pub fn rewrite(rewrite:Vc) -> Vc { StaticResult::Rewrite(rewrite).cell() } +} + +/// Renders a module as static HTML in a node.js process. +#[turbo_tasks::function] +pub async fn render_static( + cwd:Vc, + env:Vc>, + path:Vc, + module:Vc>, + runtime_entries:Vc, + fallback_page:Vc, + chunking_context:Vc>, + intermediate_output_path:Vc, + output_root:Vc, + project_dir:Vc, + data:Vc, + debug:bool, +) -> Result> { + let render = render_stream( + cwd, + env, + path, + module, + runtime_entries, + fallback_page, + chunking_context, + intermediate_output_path, + output_root, + project_dir, + data, + debug, + ) + .await?; + + let mut stream = render.read(); + let first = match stream.try_next().await? { + Some(f) => f, + None => { + // If an Error was received first, then it would have been + // transformed into a proxy err error response. + bail!("did not receive response from render"); + }, + }; + + Ok(match first { + RenderItem::Response(response) => response, + RenderItem::Headers(data) => { + let body = stream.map(|item| { + match item { + Ok(RenderItem::BodyChunk(b)) => Ok(b), + Ok(v) => Err(SharedError::new(anyhow!("unexpected render item: {:#?}", v))), + Err(e) => Err(e), + } + }); + StaticResult::StreamedContent { + status:data.status, + headers:Vc::cell(data.headers), + body:Body::from_stream(body), + } + .cell() + }, + v => bail!("unexpected render item: {:#?}", v), + }) +} + +async fn static_error( + path:Vc, + error:anyhow::Error, + operation:Option, + fallback_page:Vc, +) -> Result> { + let status = match operation { + Some(operation) => Some(operation.wait_or_kill().await?), + None => None, + }; + + let error = format!("{}", PrettyPrintError(&error)); + let mut message = error + // TODO this is pretty inefficient + .replace('&', "&") + .replace('>', ">") + .replace('<', "<"); + + if let Some(status) = status { + message.push_str(&format!("\n\nStatus: {}", status)); + } + + let mut body = "" + .to_string(); + + body.push_str( + error_html_body(500, "Error rendering page".into(), message.into()) + .await? + .as_str(), + ); + + let issue = RenderingIssue { + file_path:path, + message:StyledString::Text(error.into()).cell(), + status:status.and_then(|status| status.code()), + }; + + issue.cell().emit(); + + let html = fallback_page.with_body(body.into()); + + Ok(html.content()) +} + +#[derive(Clone, Debug)] +#[turbo_tasks::value] +enum RenderItem { + Response(Vc), + Headers(ResponseHeaders), + BodyChunk(Bytes), +} + +type RenderItemResult = Result; + +#[turbo_tasks::value(eq = "manual", cell = "new", serialization = "none")] +struct RenderStreamSender { + #[turbo_tasks(trace_ignore, debug_ignore)] + get:Box UnboundedSender + Send + Sync>, +} + +#[turbo_tasks::value(transparent)] +struct RenderStream(#[turbo_tasks(trace_ignore)] Stream); + +#[turbo_tasks::function] +fn render_stream( + cwd:Vc, + env:Vc>, + path:Vc, + module:Vc>, + runtime_entries:Vc, + fallback_page:Vc, + chunking_context:Vc>, + intermediate_output_path:Vc, + output_root:Vc, + project_dir:Vc, + data:Vc, + debug:bool, +) -> Vc { + // TODO: The way we invoke render_stream_internal as side effect is not + // GC-safe, so we disable GC for this task. + prevent_gc(); + + // Note the following code uses some hacks to create a child task that produces + // a stream that is returned by this task. + + // We create a new cell in this task, which will be updated from the + // [render_stream_internal] task. + let cell = turbo_tasks::macro_helpers::find_cell_by_type(*RENDERSTREAM_VALUE_TYPE_ID); + + // We initialize the cell with a stream that is open, but has no values. + // The first [render_stream_internal] pipe call will pick up that stream. + let (sender, receiver) = unbounded(); + cell.update_shared(RenderStream(Stream::new_open(vec![], Box::new(receiver)))); + let initial = Mutex::new(Some(sender)); + + // run the evaluation as side effect + let _ = render_stream_internal( + cwd, + env, + path, + module, + runtime_entries, + fallback_page, + chunking_context, + intermediate_output_path, + output_root, + project_dir, + data, + RenderStreamSender { + get:Box::new(move || { + if let Some(sender) = initial.lock().take() { + sender + } else { + // In cases when only [render_stream_internal] is (re)executed, we need to + // update the old stream with a new value. + let (sender, receiver) = unbounded(); + cell.update_shared(RenderStream(Stream::new_open(vec![], Box::new(receiver)))); + sender + } + }), + } + .cell(), + debug, + ); + + let raw:RawVc = cell.into(); + raw.into() +} + +#[turbo_tasks::function] +async fn render_stream_internal( + cwd:Vc, + env:Vc>, + path:Vc, + module:Vc>, + runtime_entries:Vc, + fallback_page:Vc, + chunking_context:Vc>, + intermediate_output_path:Vc, + output_root:Vc, + project_dir:Vc, + data:Vc, + sender:Vc, + debug:bool, +) -> Result> { + mark_finished(); + let Ok(sender) = sender.await else { + // Impossible to handle the error in a good way. + return Ok(Default::default()); + }; + + let stream = generator! { + let intermediate_asset = get_intermediate_asset( + chunking_context, + module, + runtime_entries, + ); + let renderer_pool = get_renderer_pool( + cwd, + env, + intermediate_asset, + intermediate_output_path, + output_root, + project_dir, + debug, + ); + + // Read this strongly consistent, since we don't want to run inconsistent + // node.js code. + let pool = renderer_pool.strongly_consistent().await?; + let data = data.await?; + let mut operation = pool.operation().await?; + + operation + .send(RenderStaticOutgoingMessage::Headers { data: &data }) + .await + .context("sending headers to node.js process")?; + + let entry = module.ident().to_string().await?; + let guard = duration_span!("Node.js rendering", entry = display(entry)); + + match operation.recv().await? { + RenderStaticIncomingMessage::Headers { data } => yield RenderItem::Headers(data), + RenderStaticIncomingMessage::Rewrite { path } => { + drop(guard); + yield RenderItem::Response(StaticResult::rewrite(RewriteBuilder::new(path).build())); + return; + } + RenderStaticIncomingMessage::Response { + status_code, + headers, + body, + } => { + drop(guard); + yield RenderItem::Response(StaticResult::content( + AssetContent::file(File::from(body).into()), + status_code, + Vc::cell(headers), + )); + return; + } + RenderStaticIncomingMessage::Error(error) => { + drop(guard); + // If we don't get headers, then something is very wrong. Instead, we send down a + // 500 proxy error as if it were the proper result. + let trace = trace_stack( + error, + intermediate_asset, + intermediate_output_path, + project_dir, + ) + .await?; + yield RenderItem::Response( + StaticResult::content( + static_error(path, anyhow!(trace), Some(operation), fallback_page).await?, + 500, + HeaderList::empty(), + ) + ); + return; + } + v => { + drop(guard); + Err(anyhow!("unexpected message during rendering: {:#?}", v))?; + return; + }, + }; + + // If we get here, then the first message was a Headers. Now we need to stream out the body + // chunks. + loop { + match operation.recv().await? { + RenderStaticIncomingMessage::BodyChunk { data } => { + yield RenderItem::BodyChunk(data.into()); + } + RenderStaticIncomingMessage::BodyEnd => break, + RenderStaticIncomingMessage::Error(error) => { + // We have already started to send a result, so we can't change the + // headers/body to a proxy error. + operation.disallow_reuse(); + let trace = + trace_stack(error, intermediate_asset, intermediate_output_path, project_dir).await?; + drop(guard); + Err(anyhow!("error during streaming render: {}", trace))?; + return; + } + v => { + drop(guard); + Err(anyhow!("unexpected message during rendering: {:#?}", v))?; + return; + }, + } + } + drop(guard); + }; + + let mut sender = (sender.get)(); + pin_mut!(stream); + while let Some(value) = stream.next().await { + if sender.send(value).await.is_err() { + return Ok(Default::default()); + } + if sender.flush().await.is_err() { + return Ok(Default::default()); + } + } + + Ok(Default::default()) +} diff --git a/crates/turbopack-node/Source/render/rendered_source.rs b/crates/turbopack-node/Source/render/rendered_source.rs new file mode 100644 index 0000000000000..b12428bc97a53 --- /dev/null +++ b/crates/turbopack-node/Source/render/rendered_source.rs @@ -0,0 +1,270 @@ +use anyhow::{Result, anyhow}; +use indexmap::IndexSet; +use serde_json::Value as JsonValue; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + introspect::{ + Introspectable, + IntrospectableChildren, + module::IntrospectableModule, + output_asset::IntrospectableOutputAsset, + }, + issue::IssueDescriptionExt, + module::Module, + output::OutputAsset, + version::VersionedContentExt, +}; +use turbopack_dev_server::{ + html::DevHtmlAsset, + source::{ + ContentSource, + ContentSourceContent, + ContentSourceData, + ContentSourceDataVary, + GetContentSourceContent, + ProxyResult, + asset_graph::AssetGraphContentSource, + conditional::ConditionalContentSource, + lazy_instantiated::{GetContentSource, LazyInstantiatedContentSource}, + route_tree::{BaseSegment, RouteTree, RouteType}, + }, +}; + +use super::{ + RenderData, + render_static::{StaticResult, render_static}, +}; +use crate::{ + external_asset_entrypoints, + get_intermediate_asset, + node_entry::NodeEntry, + route_matcher::RouteMatcher, +}; + +/// Creates a content source that renders something in Node.js with the passed +/// `entry` when it matches a `path_regex`. Once rendered it serves +/// all assets referenced by the `entry` that are within the `server_root`. +/// It needs a temporary directory (`intermediate_output_path`) to place file +/// for Node.js execution during rendering. The `chunking_context` should emit +/// to this directory. +#[turbo_tasks::function] +pub fn create_node_rendered_source( + cwd:Vc, + env:Vc>, + base_segments:Vec, + route_type:RouteType, + server_root:Vc, + route_match:Vc>, + pathname:Vc, + entry:Vc>, + fallback_page:Vc, + render_data:Vc, + debug:bool, +) -> Vc> { + let source = NodeRenderContentSource { + cwd, + env, + base_segments, + route_type, + server_root, + route_match, + pathname, + entry, + fallback_page, + render_data, + debug, + } + .cell(); + Vc::upcast(ConditionalContentSource::new( + Vc::upcast(source), + Vc::upcast(LazyInstantiatedContentSource { get_source:Vc::upcast(source) }.cell()), + )) +} + +/// see [create_node_rendered_source] +#[turbo_tasks::value] +pub struct NodeRenderContentSource { + cwd:Vc, + env:Vc>, + base_segments:Vec, + route_type:RouteType, + server_root:Vc, + route_match:Vc>, + pathname:Vc, + entry:Vc>, + fallback_page:Vc, + render_data:Vc, + debug:bool, +} + +#[turbo_tasks::value_impl] +impl NodeRenderContentSource { + #[turbo_tasks::function] + pub async fn get_pathname(self: Vc) -> Result> { Ok(self.await?.pathname) } +} + +#[turbo_tasks::value_impl] +impl GetContentSource for NodeRenderContentSource { + /// Returns the [ContentSource] that serves all referenced external + /// assets. This is wrapped into [LazyInstantiatedContentSource]. + #[turbo_tasks::function] + async fn content_source(&self) -> Result>> { + let entries = self.entry.entries(); + let mut set = IndexSet::new(); + for &reference in self.fallback_page.references().await?.iter() { + set.insert(reference); + } + for &entry in entries.await?.iter() { + let entry = entry.await?; + set.extend( + external_asset_entrypoints( + entry.module, + entry.runtime_entries, + entry.chunking_context, + entry.intermediate_output_path, + ) + .await? + .iter() + .copied(), + ) + } + Ok(Vc::upcast(AssetGraphContentSource::new_lazy_multiple( + self.server_root, + Vc::cell(set), + ))) + } +} + +#[turbo_tasks::value_impl] +impl ContentSource for NodeRenderContentSource { + #[turbo_tasks::function] + async fn get_routes(self: Vc) -> Result> { + let this = self.await?; + Ok(RouteTree::new_route( + this.base_segments.clone(), + this.route_type.clone(), + Vc::upcast(self), + )) + } +} + +#[turbo_tasks::value_impl] +impl GetContentSourceContent for NodeRenderContentSource { + #[turbo_tasks::function] + fn vary(&self) -> Vc { + ContentSourceDataVary { + method:true, + url:true, + original_url:true, + raw_headers:true, + raw_query:true, + ..Default::default() + } + .cell() + } + + #[turbo_tasks::function] + async fn get( + &self, + path:RcStr, + data:Value, + ) -> Result> { + let pathname = self.pathname.await?; + let Some(params) = &*self.route_match.params(path.clone()).await? else { + return Err(anyhow!("Non matching path ({}) provided for {}", path, pathname)); + }; + let ContentSourceData { + method: Some(method), + url: Some(url), + original_url: Some(original_url), + raw_headers: Some(raw_headers), + raw_query: Some(raw_query), + .. + } = &*data + else { + return Err(anyhow!("Missing request data")); + }; + let entry = self.entry.entry(data.clone()).await?; + let result = render_static( + self.cwd, + self.env, + self.server_root.join(path.clone()), + entry.module, + entry.runtime_entries, + self.fallback_page, + entry.chunking_context, + entry.intermediate_output_path, + entry.output_root, + entry.project_dir, + RenderData { + params:params.clone(), + method:method.clone(), + url:url.clone(), + original_url:original_url.clone(), + raw_query:raw_query.clone(), + raw_headers:raw_headers.clone(), + path:pathname.as_str().into(), + data:Some(self.render_data.await?), + } + .cell(), + self.debug, + ) + .issue_file_path(entry.module.ident().path(), format!("server-side rendering {}", pathname)) + .await?; + Ok(match *result.await? { + StaticResult::Content { content, status_code, headers } => { + ContentSourceContent::static_with_headers(content.versioned(), status_code, headers) + }, + StaticResult::StreamedContent { status, headers, ref body } => { + ContentSourceContent::HttpProxy( + ProxyResult { status, headers:headers.await?.clone_value(), body:body.clone() } + .cell(), + ) + .cell() + }, + StaticResult::Rewrite(rewrite) => ContentSourceContent::Rewrite(rewrite).cell(), + }) + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("node render content source".into()) } + +#[turbo_tasks::value_impl] +impl Introspectable for NodeRenderContentSource { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { self.pathname } + + #[turbo_tasks::function] + async fn details(&self) -> Result> { + Ok(Vc::cell( + format!("base: {:?}\ntype: {:?}", self.base_segments, self.route_type).into(), + )) + } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + let mut set = IndexSet::new(); + for &entry in self.entry.entries().await?.iter() { + let entry = entry.await?; + set.insert(( + Vc::cell("module".into()), + IntrospectableModule::new(Vc::upcast(entry.module)), + )); + set.insert(( + Vc::cell("intermediate asset".into()), + IntrospectableOutputAsset::new(get_intermediate_asset( + entry.chunking_context, + entry.module, + entry.runtime_entries, + )), + )); + } + Ok(Vc::cell(set)) + } +} diff --git a/crates/turbopack-node/Source/route_matcher.rs b/crates/turbopack-node/Source/route_matcher.rs new file mode 100644 index 0000000000000..d7dcde4cdc6d8 --- /dev/null +++ b/crates/turbopack-node/Source/route_matcher.rs @@ -0,0 +1,33 @@ +use indexmap::IndexMap; +use turbo_tasks::{RcStr, Vc}; + +#[turbo_tasks::value] +#[derive(Debug, Clone)] +#[serde(untagged)] +pub enum Param { + Single(RcStr), + Multi(Vec), +} + +#[turbo_tasks::value(transparent)] +#[derive(Debug, Clone)] +pub struct Params(pub Option>); + +/// Extracts parameters from a URL path. +pub trait RouteMatcherRef { + /// Returns whether the given path is a match for the route. + fn matches(&self, path:&str) -> bool; + + /// Returns the parameters extracted from the given path. + fn params(&self, path:&str) -> Params; +} + +/// Extracts parameters from a URL path (Vc version) +#[turbo_tasks::value_trait] +pub trait RouteMatcher { + /// Returns whether the given path is a match for the route. + fn matches(self: Vc, path:RcStr) -> Vc; + + /// Returns the parameters extracted from the given path. + fn params(self: Vc, path:RcStr) -> Vc; +} diff --git a/crates/turbopack-node/Source/source_map/mod.rs b/crates/turbopack-node/Source/source_map/mod.rs new file mode 100644 index 0000000000000..e90db9d1276db --- /dev/null +++ b/crates/turbopack-node/Source/source_map/mod.rs @@ -0,0 +1,331 @@ +use std::{ + borrow::Cow, + fmt::Write, + path::{MAIN_SEPARATOR, Path}, +}; + +use anyhow::Result; +use const_format::concatcp; +use once_cell::sync::Lazy; +use regex::Regex; +pub use trace::{SourceMapTrace, StackFrame, TraceResult}; +use tracing::{Level, instrument}; +use turbo_tasks::{ReadRef, Vc}; +use turbo_tasks_fs::{ + FileLinesContent, + FileSystemPath, + source_context::get_source_context, + to_sys_path, +}; +use turbopack_cli_utils::source_context::format_source_context_lines; +use turbopack_core::{ + PROJECT_FILESYSTEM_NAME, + SOURCE_MAP_PREFIX, + output::OutputAsset, + source_map::GenerateSourceMap, +}; +use turbopack_ecmascript::magic_identifier::unmangle_identifiers; + +use crate::{AssetsForSourceMapping, internal_assets_for_source_mapping, pool::FormattingMode}; + +pub mod trace; + +const MAX_CODE_FRAMES:usize = 3; + +pub async fn apply_source_mapping( + text:&'_ str, + assets_for_source_mapping:Vc, + root:Vc, + project_dir:Vc, + formatting_mode:FormattingMode, +) -> Result> { + static STACK_TRACE_LINE:Lazy = + Lazy::new(|| Regex::new("\n at (?:(.+) \\()?(.+):(\\d+):(\\d+)\\)?").unwrap()); + + let mut it = STACK_TRACE_LINE.captures_iter(text).peekable(); + if it.peek().is_none() { + return Ok(Cow::Borrowed(text)); + } + let mut first_error = true; + let mut visible_code_frames = 0; + let mut new = String::with_capacity(text.len() * 2); + let mut last_match = 0; + for cap in it { + // unwrap on 0 is OK because captures only reports matches + let m = cap.get(0).unwrap(); + new.push_str(&text[last_match..m.start()]); + let name = cap.get(1).map(|s| s.as_str()); + let file = cap.get(2).unwrap().as_str(); + let line = cap.get(3).unwrap().as_str(); + let column = cap.get(4).unwrap().as_str(); + let line = line.parse::()?; + let column = column.parse::()?; + let frame = StackFrame { + name:name.map(|s| s.into()), + file:file.into(), + line:Some(line), + column:Some(column), + }; + let resolved = + resolve_source_mapping(assets_for_source_mapping, root, project_dir.root(), &frame) + .await; + write_resolved( + &mut new, + resolved, + &frame, + &mut first_error, + &mut visible_code_frames, + formatting_mode, + )?; + last_match = m.end(); + } + new.push_str(&text[last_match..]); + Ok(Cow::Owned(new)) +} + +fn write_resolved( + writable:&mut impl Write, + resolved:Result, + original_frame:&StackFrame<'_>, + first_error:&mut bool, + visible_code_frames:&mut usize, + formatting_mode:FormattingMode, +) -> Result<()> { + const PADDING:&str = "\n "; + match resolved { + Err(err) => { + // There was an error resolving the source map + write!(writable, "{PADDING}at {}", original_frame)?; + if *first_error { + write!(writable, "{PADDING}(error resolving source map: {})", err)?; + *first_error = false; + } else { + write!(writable, "{PADDING}(error resolving source map)")?; + } + }, + Ok(ResolvedSourceMapping::NoSourceMap) | Ok(ResolvedSourceMapping::Unmapped) => { + // There is no source map for this file or no mapping for the line + write!( + writable, + "{PADDING}{}", + formatting_mode.lowlight(&format_args!("[at {}]", original_frame)) + )?; + }, + Ok(ResolvedSourceMapping::Mapped { frame }) => { + // There is a mapping to something outside of the project (e. g. plugins, + // internal code) + write!( + writable, + "{PADDING}{}", + formatting_mode.lowlight(&format_args!( + "at {} [{}]", + frame, + original_frame.with_name(None) + )) + )?; + }, + Ok(ResolvedSourceMapping::MappedLibrary { frame, project_path }) => { + // There is a mapping to a file in the project directory, but to library code + write!( + writable, + "{PADDING}{}", + formatting_mode.lowlight(&format_args!( + "at {} [{}]", + frame.with_path(&project_path.path), + original_frame.with_name(None) + )) + )?; + }, + Ok(ResolvedSourceMapping::MappedProject { frame, project_path, lines }) => { + // There is a mapping to a file in the project directory + if let Some(name) = frame.name.as_ref() { + write!( + writable, + "{PADDING}at {name} ({}) {}", + formatting_mode.highlight(&frame.with_name(None).with_path(&project_path.path)), + formatting_mode.lowlight(&format_args!("[{}]", original_frame.with_name(None))) + )?; + } else { + write!( + writable, + "{PADDING}at {} {}", + formatting_mode.highlight(&frame.with_path(&project_path.path)), + formatting_mode.lowlight(&format_args!("[{}]", original_frame.with_name(None))) + )?; + } + let (line, column) = frame.get_pos().unwrap_or((0, 0)); + let line = line.saturating_sub(1); + let column = column.saturating_sub(1); + if let FileLinesContent::Lines(lines) = &*lines { + if *visible_code_frames < MAX_CODE_FRAMES { + let lines = lines.iter().map(|l| l.content.as_str()); + let ctx = get_source_context(lines, line, column, line, column); + match formatting_mode { + FormattingMode::Plain => { + write!(writable, "\n{}", ctx)?; + }, + FormattingMode::AnsiColors => { + writable.write_char('\n')?; + format_source_context_lines(&ctx, writable); + }, + } + *visible_code_frames += 1; + } + } + }, + } + Ok(()) +} + +enum ResolvedSourceMapping { + NoSourceMap, + Unmapped, + Mapped { + frame:StackFrame<'static>, + }, + MappedProject { + frame:StackFrame<'static>, + project_path:ReadRef, + lines:ReadRef, + }, + MappedLibrary { + frame:StackFrame<'static>, + project_path:ReadRef, + }, +} + +async fn resolve_source_mapping( + assets_for_source_mapping:Vc, + root:Vc, + project_dir:Vc, + frame:&StackFrame<'_>, +) -> Result { + let Some((line, column)) = frame.get_pos() else { + return Ok(ResolvedSourceMapping::NoSourceMap); + }; + let name = frame.name.as_ref(); + let file = &frame.file; + let Some(root) = to_sys_path(root).await? else { + return Ok(ResolvedSourceMapping::NoSourceMap); + }; + let Ok(file) = Path::new(file.as_ref()).strip_prefix(root) else { + return Ok(ResolvedSourceMapping::NoSourceMap); + }; + let file = file.to_string_lossy(); + let file = if MAIN_SEPARATOR != '/' { + Cow::Owned(file.replace(MAIN_SEPARATOR, "/")) + } else { + file + }; + let map = assets_for_source_mapping.await?; + let Some(generate_source_map) = map.get(file.as_ref()) else { + return Ok(ResolvedSourceMapping::NoSourceMap); + }; + let Some(sm) = *generate_source_map.generate_source_map().await? else { + return Ok(ResolvedSourceMapping::NoSourceMap); + }; + let trace = SourceMapTrace::new(sm, line, column, name.map(|s| s.clone().into())) + .trace() + .await?; + match &*trace { + TraceResult::Found(frame) => { + let lib_code = frame.file.contains("/node_modules/"); + if let Some(project_path) = frame.file.strip_prefix(concatcp!( + SOURCE_MAP_PREFIX, + "[", + PROJECT_FILESYSTEM_NAME, + "]/" + )) { + let fs_path = project_dir.join(project_path.into()); + if lib_code { + return Ok(ResolvedSourceMapping::MappedLibrary { + frame:frame.clone(), + project_path:fs_path.await?, + }); + } else { + let lines = fs_path.read().lines().await?; + return Ok(ResolvedSourceMapping::MappedProject { + frame:frame.clone(), + project_path:fs_path.await?, + lines, + }); + } + } + Ok(ResolvedSourceMapping::Mapped { frame:frame.clone() }) + }, + TraceResult::NotFound => Ok(ResolvedSourceMapping::Unmapped), + } +} + +#[turbo_tasks::value(shared)] +#[derive(Clone, Debug)] +pub struct StructuredError { + pub name:String, + pub message:String, + #[turbo_tasks(trace_ignore)] + stack:Vec>, +} + +impl StructuredError { + pub async fn print( + &self, + assets_for_source_mapping:Vc, + root:Vc, + project_dir:Vc, + formatting_mode:FormattingMode, + ) -> Result { + let mut message = String::new(); + + let magic = |content| formatting_mode.magic_identifier(content); + + write!(message, "{}: {}", self.name, unmangle_identifiers(&self.message, magic))?; + + let mut first_error = true; + let mut visible_code_frames = 0; + + for frame in &self.stack { + let frame = frame.unmangle_identifiers(magic); + let resolved = + resolve_source_mapping(assets_for_source_mapping, root, project_dir.root(), &frame) + .await; + write_resolved( + &mut message, + resolved, + &frame, + &mut first_error, + &mut visible_code_frames, + formatting_mode, + )?; + } + Ok(message) + } +} + +pub async fn trace_stack( + error:StructuredError, + root_asset:Vc>, + output_path:Vc, + project_dir:Vc, +) -> Result { + let assets_for_source_mapping = internal_assets_for_source_mapping(root_asset, output_path); + + trace_stack_with_source_mapping_assets( + error, + assets_for_source_mapping, + output_path, + project_dir, + ) + .await +} + +#[instrument(level = Level::TRACE, skip_all)] +pub async fn trace_stack_with_source_mapping_assets( + error:StructuredError, + assets_for_source_mapping:Vc, + output_path:Vc, + project_dir:Vc, +) -> Result { + error + .print(assets_for_source_mapping, output_path, project_dir, FormattingMode::Plain) + .await +} diff --git a/crates/turbopack-node/Source/source_map/trace.rs b/crates/turbopack-node/Source/source_map/trace.rs new file mode 100644 index 0000000000000..d4c03125f8cb6 --- /dev/null +++ b/crates/turbopack-node/Source/source_map/trace.rs @@ -0,0 +1,162 @@ +use std::{borrow::Cow, fmt::Display}; + +use anyhow::Result; +use mime::APPLICATION_JSON; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::AssetContent, + source_map::{SourceMap, Token}, +}; +use turbopack_ecmascript::magic_identifier::unmangle_identifiers; + +/// An individual stack frame, as parsed by the stacktrace-parser npm module. +/// +/// Line and column can be None if the frame is anonymous. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub struct StackFrame<'a> { + pub file:Cow<'a, str>, + #[serde(rename = "lineNumber")] + pub line:Option, + pub column:Option, + #[serde(rename = "methodName")] + pub name:Option>, +} + +impl<'a> StackFrame<'a> { + pub fn unmangle_identifiers(&self, magic:impl Fn(String) -> T) -> StackFrame<'_> { + StackFrame { + file:Cow::Borrowed(self.file.as_ref()), + line:self.line, + column:self.column, + name:self.name.as_ref().map(|n| unmangle_identifiers(n.as_ref(), magic)), + } + } + + pub fn with_path<'b>(&'a self, path:&'b str) -> StackFrame<'b> + where + 'a:'b, { + StackFrame { + file:Cow::Borrowed(path), + line:self.line, + column:self.column, + name:self.name.as_ref().map(|n| Cow::Borrowed(n.as_ref())), + } + } + + pub fn with_name<'b>(&'a self, name:Option<&'b str>) -> StackFrame<'b> + where + 'a:'b, { + StackFrame { + file:Cow::Borrowed(self.file.as_ref()), + line:self.line, + column:self.column, + name:name.map(Cow::Borrowed), + } + } + + pub fn get_pos(&self) -> Option<(usize, usize)> { self.line.zip(self.column) } +} + +impl<'a> Display for StackFrame<'a> { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.get_pos() { + Some((l, c)) => { + match &self.name.as_deref() { + None | Some("") | Some("(anonymous)") => { + write!(f, "{}:{}:{}", self.file, l, c) + }, + Some(n) => write!(f, "{} ({}:{}:{})", n, self.file, l, c), + } + }, + None => write!(f, "{}", self.file), + } + } +} +/// Source Map Trace is a convenient wrapper to perform and consume a source map +/// trace's token. +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub struct SourceMapTrace { + map:Vc, + line:usize, + column:usize, + name:Option, +} + +/// The result of performing a source map trace. +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub enum TraceResult { + NotFound, + Found(#[turbo_tasks(trace_ignore)] StackFrame<'static>), +} + +#[turbo_tasks::value_impl] +impl SourceMapTrace { + #[turbo_tasks::function] + pub async fn new(map:Vc, line:usize, column:usize, name:Option) -> Vc { + SourceMapTrace { map, line, column, name }.cell() + } + + /// Traces the line/column through the source map into its original + /// position. + /// + /// This method is god-awful slow. We're getting the content + /// of a .map file, which means we're serializing all of the individual + /// sections into a string and concatenating, taking that and + /// deserializing into a DecodedMap, and then querying it. Besides being a + /// memory hog, it'd be so much faster if we could just directly access + /// the individual sections of the JS file's map without the + /// serialization. + #[turbo_tasks::function] + pub async fn trace(self: Vc) -> Result> { + let this = self.await?; + + let token = this + .map + .lookup_token(this.line.saturating_sub(1), this.column.saturating_sub(1)) + .await?; + let result = match &*token { + Token::Original(t) => { + TraceResult::Found(StackFrame { + file:t.original_file.clone().into(), + line:Some(t.original_line.saturating_add(1)), + column:Some(t.original_column.saturating_add(1)), + name:t + .name + .clone() + .or_else(|| this.name.clone()) + .map(|v| v.into_owned()) + .map(Cow::Owned), + }) + }, + _ => TraceResult::NotFound, + }; + + Ok(result.cell()) + } + + /// Takes the trace and generates a (possibly valid) JSON asset content. + #[turbo_tasks::function] + pub async fn content(self: Vc) -> Result> { + let trace = self.trace().await?; + let result = match &*trace { + // purposefully invalid JSON (it can't be empty), so that the catch handler will default + // to the generated stack frame. + TraceResult::NotFound => "".to_string(), + TraceResult::Found(frame) => { + json!({ + "originalStackFrame": frame, + // TODO + "originalCodeFrame": null, + }) + .to_string() + }, + }; + let file = File::from(result).with_content_type(APPLICATION_JSON); + Ok(AssetContent::file(file.into())) + } +} diff --git a/crates/turbopack-node/Source/transforms/mod.rs b/crates/turbopack-node/Source/transforms/mod.rs new file mode 100644 index 0000000000000..996a8a5fc86dc --- /dev/null +++ b/crates/turbopack-node/Source/transforms/mod.rs @@ -0,0 +1,3 @@ +pub mod postcss; +mod util; +pub mod webpack; diff --git a/crates/turbopack-node/Source/transforms/postcss.rs b/crates/turbopack-node/Source/transforms/postcss.rs new file mode 100644 index 0000000000000..0d33397ec8d87 --- /dev/null +++ b/crates/turbopack-node/Source/transforms/postcss.rs @@ -0,0 +1,444 @@ +use anyhow::{Context, Result, bail}; +use indexmap::indexmap; +use indoc::formatdoc; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{ + Completion, + Completions, + RcStr, + TaskInput, + TryFlatJoinIterExt, + Value, + Vc, + trace::TraceRawVcs, +}; +use turbo_tasks_bytes::stream::SingleValue; +use turbo_tasks_fs::{ + File, + FileContent, + FileSystemEntryType, + FileSystemPath, + json::parse_json_with_source_context, +}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + changed::any_content_changed_of_module, + context::{AssetContext, ProcessResult}, + file_source::FileSource, + ident::AssetIdent, + issue::{ + Issue, + IssueDescriptionExt, + IssueSeverity, + IssueStage, + OptionStyledString, + StyledString, + }, + reference_type::{EntryReferenceSubType, InnerAssets, ReferenceType}, + resolve::{FindContextFileResult, find_context_file, options::ImportMapping}, + source::Source, + source_transform::SourceTransform, + virtual_source::VirtualSource, +}; + +use super::{ + util::{EmittedAsset, emitted_assets_to_virtual_sources}, + webpack::WebpackLoaderContext, +}; +use crate::{ + embed_js::embed_file, + execution_context::ExecutionContext, + transforms::webpack::evaluate_webpack_loader, +}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +#[turbo_tasks::value(serialization = "custom")] +struct PostCssProcessingResult { + css:String, + map:Option, + #[turbo_tasks(trace_ignore)] + assets:Option>, +} + +#[derive( + Default, Copy, Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize, TaskInput, +)] +pub enum PostCssConfigLocation { + #[default] + ProjectPath, + ProjectPathOrLocalPath, +} + +#[turbo_tasks::value(shared)] +#[derive(Clone, Default)] +pub struct PostCssTransformOptions { + pub postcss_package:Option>, + pub config_location:PostCssConfigLocation, + pub placeholder_for_future_extensions:u8, +} + +#[turbo_tasks::function] +fn postcss_configs() -> Vc> { + Vc::cell( + [ + ".postcssrc", + ".postcssrc.json", + ".postcssrc.yaml", + ".postcssrc.yml", + ".postcssrc.js", + ".postcssrc.mjs", + ".postcssrc.cjs", + ".config/postcssrc", + ".config/postcssrc.json", + ".config/postcssrc.yaml", + ".config/postcssrc.yml", + ".config/postcssrc.js", + ".config/postcssrc.mjs", + ".config/postcssrc.cjs", + "postcss.config.js", + "postcss.config.mjs", + "postcss.config.cjs", + "postcss.config.json", + ] + .into_iter() + .map(RcStr::from) + .collect(), + ) +} + +#[turbo_tasks::value] +pub struct PostCssTransform { + evaluate_context:Vc>, + execution_context:Vc, + config_location:PostCssConfigLocation, +} + +#[turbo_tasks::value_impl] +impl PostCssTransform { + #[turbo_tasks::function] + pub fn new( + evaluate_context:Vc>, + execution_context:Vc, + config_location:PostCssConfigLocation, + ) -> Vc { + PostCssTransform { evaluate_context, execution_context, config_location }.cell() + } +} + +#[turbo_tasks::value_impl] +impl SourceTransform for PostCssTransform { + #[turbo_tasks::function] + fn transform(&self, source:Vc>) -> Vc> { + Vc::upcast( + PostCssTransformedAsset { + evaluate_context:self.evaluate_context, + execution_context:self.execution_context, + config_location:self.config_location, + source, + } + .cell(), + ) + } +} + +#[turbo_tasks::value] +struct PostCssTransformedAsset { + evaluate_context:Vc>, + execution_context:Vc, + config_location:PostCssConfigLocation, + source:Vc>, +} + +#[turbo_tasks::value_impl] +impl Source for PostCssTransformedAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { self.source.ident() } +} + +#[turbo_tasks::value_impl] +impl Asset for PostCssTransformedAsset { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let this = self.await?; + Ok(self + .process() + .issue_file_path(this.source.ident().path(), "PostCSS processing") + .await? + .await? + .content) + } +} + +#[turbo_tasks::value] +struct ProcessPostCssResult { + content:Vc, + assets:Vec>, +} + +#[turbo_tasks::function] +async fn config_changed( + asset_context:Vc>, + postcss_config_path:Vc, +) -> Result> { + let config_asset = asset_context + .process( + Vc::upcast(FileSource::new(postcss_config_path)), + Value::new(ReferenceType::Internal(InnerAssets::empty())), + ) + .module(); + + Ok(Vc::::cell(vec![ + any_content_changed_of_module(config_asset), + extra_configs_changed(asset_context, postcss_config_path), + ]) + .completed()) +} + +#[turbo_tasks::function] +async fn extra_configs_changed( + asset_context:Vc>, + postcss_config_path:Vc, +) -> Result> { + let parent_path = postcss_config_path.parent(); + + let config_paths = [ + parent_path.join("tailwind.config.js".into()), + parent_path.join("tailwind.config.ts".into()), + ]; + + let configs = config_paths + .into_iter() + .map(|path| { + async move { + Ok(if matches!(&*path.get_type().await?, FileSystemEntryType::File) { + match *asset_context + .process( + Vc::upcast(FileSource::new(path)), + Value::new(ReferenceType::Internal(InnerAssets::empty())), + ) + .await? + { + ProcessResult::Module(module) => { + Some(any_content_changed_of_module(module)) + }, + ProcessResult::Ignore => None, + } + } else { + None + }) + } + }) + .try_flat_join() + .await?; + + Ok(Vc::::cell(configs).completed()) +} + +#[turbo_tasks::function] +pub(crate) async fn config_loader_source( + project_path:Vc, + postcss_config_path:Vc, +) -> Result>> { + let postcss_config_path_value = &*postcss_config_path.await?; + + // We can only load js files with `import()`. + if !postcss_config_path_value.path.ends_with(".js") { + return Ok(Vc::upcast(FileSource::new(postcss_config_path))); + } + + let Some(config_path) = project_path.await?.get_relative_path_to(postcss_config_path_value) + else { + bail!("Unable to get relative path to postcss config"); + }; + + // We don't want to bundle the config file, so we load it with `import()`. + // Bundling would break the ability to use `require.resolve` in the config file. + let code = formatdoc! { + r#" + import {{ pathToFileURL }} from 'node:url'; + import path from 'node:path'; + + const configPath = path.join(process.cwd(), {config_path}); + // Absolute paths don't work with ESM imports on Windows: + // https://github.com/nodejs/node/issues/31710 + // convert it to a file:// URL, which works on all platforms + const configUrl = pathToFileURL(configPath).toString(); + const mod = await __turbopack_external_import__(configUrl); + + export default mod.default ?? mod; + "#, + config_path = serde_json::to_string(&config_path).expect("a string should be serializable"), + }; + + Ok(Vc::upcast(VirtualSource::new( + postcss_config_path.append("_.loader.mjs".into()), + AssetContent::file(File::from(code).into()), + ))) +} + +#[turbo_tasks::function] +async fn postcss_executor( + asset_context:Vc>, + project_path:Vc, + postcss_config_path:Vc, +) -> Result> { + let config_asset = asset_context + .process( + config_loader_source(project_path, postcss_config_path), + Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)), + ) + .module(); + + Ok(asset_context.process( + Vc::upcast(VirtualSource::new( + postcss_config_path.join("transform.ts".into()), + AssetContent::File(embed_file("transforms/postcss.ts".into())).cell(), + )), + Value::new(ReferenceType::Internal(Vc::cell(indexmap! { + "CONFIG".into() => config_asset + }))), + )) +} + +async fn find_config_in_location( + project_path:Vc, + location:PostCssConfigLocation, + source:Vc>, +) -> Result>> { + if let FindContextFileResult::Found(config_path, _) = + *find_context_file(project_path, postcss_configs()).await? + { + return Ok(Some(config_path)); + } + + if matches!(location, PostCssConfigLocation::ProjectPathOrLocalPath) { + if let FindContextFileResult::Found(config_path, _) = + *find_context_file(source.ident().path().parent(), postcss_configs()).await? + { + return Ok(Some(config_path)); + } + } + + Ok(None) +} + +#[turbo_tasks::value_impl] +impl PostCssTransformedAsset { + #[turbo_tasks::function] + async fn process(self: Vc) -> Result> { + let this = self.await?; + let ExecutionContext { project_path, chunking_context, env } = + *this.execution_context.await?; + + // For this postcss transform, there is no gaurantee that looking up for the + // source path will arrives specific project config for the postcss. + // i.e, this is possible + // - root + // - node_modules + // - somepkg/(some.module.css, postcss.config.js) // this could be symlinked + // local, or actual remote pkg or anything + // - packages // root of workspace pkgs + // - pkg1/(postcss.config.js) // The actual config we're looking for + // + // We look for the config in the project path first, then the source path + let Some(config_path) = + find_config_in_location(project_path, this.config_location, this.source).await? + else { + return Ok( + ProcessPostCssResult { content:this.source.content(), assets:Vec::new() }.cell() + ); + }; + + let source_content = this.source.content(); + let AssetContent::File(file) = *source_content.await? else { + bail!("PostCSS transform only support transforming files"); + }; + let FileContent::Content(content) = &*file.await? else { + return Ok(ProcessPostCssResult { + content:AssetContent::File(FileContent::NotFound.cell()).cell(), + assets:Vec::new(), + } + .cell()); + }; + let content = content.content().to_str()?; + let evaluate_context = this.evaluate_context; + + // This invalidates the transform when the config changes. + let config_changed = config_changed(evaluate_context, config_path); + + let postcss_executor = + postcss_executor(evaluate_context, project_path, config_path).module(); + let css_fs_path = this.source.ident().path(); + + // We need to get a path relative to the project because the postcss loader + // runs with the project as the current working directory. + let css_path = if let Some(css_path) = + project_path.await?.get_relative_path_to(&*css_fs_path.await?) + { + css_path.into_owned() + } else { + // This shouldn't be an error since it can happen on virtual assets + "".into() + }; + + let config_value = evaluate_webpack_loader(WebpackLoaderContext { + module_asset:postcss_executor, + cwd:project_path, + env, + context_ident_for_issue:this.source.ident(), + asset_context:evaluate_context, + chunking_context, + resolve_options_context:None, + args:vec![Vc::cell(content.into()), Vc::cell(css_path.into())], + additional_invalidation:config_changed, + }) + .await?; + + let SingleValue::Single(val) = config_value.try_into_single().await? else { + // An error happened, which has already been converted into an issue. + return Ok(ProcessPostCssResult { + content:AssetContent::File(FileContent::NotFound.cell()).cell(), + assets:Vec::new(), + } + .cell()); + }; + let processed_css:PostCssProcessingResult = + parse_json_with_source_context(val.to_str()?) + .context("Unable to deserializate response from PostCSS transform operation")?; + + // TODO handle SourceMap + let file = File::from(processed_css.css); + let assets = emitted_assets_to_virtual_sources(processed_css.assets); + let content = AssetContent::File(FileContent::Content(file).cell()).cell(); + Ok(ProcessPostCssResult { content, assets }.cell()) + } +} + +#[turbo_tasks::value] +struct PostCssTransformIssue { + source:Vc, + description:RcStr, + severity:Vc, + title:RcStr, +} + +#[turbo_tasks::value_impl] +impl Issue for PostCssTransformIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.source } + + #[turbo_tasks::function] + fn title(&self) -> Vc { StyledString::Text(self.title.clone()).cell() } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some(StyledString::Text(self.description.clone()).cell())) + } + + #[turbo_tasks::function] + fn severity(&self) -> Vc { self.severity } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Transform.cell() } +} diff --git a/crates/turbopack-node/Source/transforms/util.rs b/crates/turbopack-node/Source/transforms/util.rs new file mode 100644 index 0000000000000..cf6679c34db6d --- /dev/null +++ b/crates/turbopack-node/Source/transforms/util.rs @@ -0,0 +1,45 @@ +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; +use serde_json::Value as JsonValue; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::{File, FileContent, FileSystem}; +use turbopack_core::{ + asset::AssetContent, + server_fs::ServerFileSystem, + virtual_source::VirtualSource, +}; + +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct EmittedAsset { + file:RcStr, + content:RcStr, + source_map:Option, +} + +pub fn emitted_assets_to_virtual_sources( + assets:Option>, +) -> Vec> { + assets + .into_iter() + .flatten() + .map( + |EmittedAsset { + file, + content, + source_map, + }| (file, (content, source_map)), + ) + // Sort it to make it determinstic + .collect::>() + .into_iter() + .map(|(file, (content, _source_map))| { + // TODO handle SourceMap + VirtualSource::new( + ServerFileSystem::new().root().join(file), + AssetContent::File(FileContent::Content(File::from(content)).cell()).cell(), + ) + }) + .collect() +} diff --git a/crates/turbopack-node/Source/transforms/webpack.rs b/crates/turbopack-node/Source/transforms/webpack.rs new file mode 100644 index 0000000000000..08aa7d5add463 --- /dev/null +++ b/crates/turbopack-node/Source/transforms/webpack.rs @@ -0,0 +1,791 @@ +use std::mem::take; + +use anyhow::{Context, Result, bail}; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use serde_json::{Value as JsonValue, json}; +use turbo_tasks::{ + Completion, + RcStr, + TaskInput, + TryJoinIterExt, + Value, + ValueToString, + Vc, + trace::TraceRawVcs, +}; +use turbo_tasks_bytes::stream::SingleValue; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{ + DirectoryEntry, + File, + FileContent, + FileSystemPath, + ReadGlobResult, + glob::Glob, + json::parse_json_with_source_context, +}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::ChunkingContext, + context::{AssetContext, ProcessResult}, + file_source::FileSource, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + module::Module, + reference_type::{InnerAssets, ReferenceType}, + resolve::{ + options::{ConditionValue, ResolveInPackage, ResolveIntoPackage, ResolveOptions}, + parse::Request, + pattern::Pattern, + resolve, + }, + source::Source, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMap}, + source_transform::SourceTransform, + virtual_source::VirtualSource, +}; +use turbopack_resolve::{ + ecmascript::get_condition_maps, + resolve::resolve_options, + resolve_options_context::ResolveOptionsContext, +}; + +use super::util::{EmittedAsset, emitted_assets_to_virtual_sources}; +use crate::{ + AssetsForSourceMapping, + debug::should_debug, + embed_js::embed_file_path, + evaluate::{ + EvaluateContext, + EvaluationIssue, + JavaScriptEvaluation, + JavaScriptStreamSender, + compute, + custom_evaluate, + get_evaluate_pool, + }, + execution_context::ExecutionContext, + pool::{FormattingMode, NodeJsPool}, + source_map::{StackFrame, StructuredError}, +}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +#[turbo_tasks::value(serialization = "custom")] +struct WebpackLoadersProcessingResult { + source:RcStr, + map:Option, + #[turbo_tasks(trace_ignore)] + assets:Option>, +} + +#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] +pub struct WebpackLoaderItem { + pub loader:RcStr, + #[turbo_tasks(trace_ignore)] + pub options:serde_json::Map, +} + +#[derive(Debug, Clone)] +#[turbo_tasks::value(shared, transparent)] +pub struct WebpackLoaderItems(pub Vec); + +#[turbo_tasks::value] +pub struct WebpackLoaders { + evaluate_context:Vc>, + execution_context:Vc, + loaders:Vc, + rename_as:Option, + resolve_options_context:Vc, +} + +#[turbo_tasks::value_impl] +impl WebpackLoaders { + #[turbo_tasks::function] + pub fn new( + evaluate_context:Vc>, + execution_context:Vc, + loaders:Vc, + rename_as:Option, + resolve_options_context:Vc, + ) -> Vc { + WebpackLoaders { + evaluate_context, + execution_context, + loaders, + rename_as, + resolve_options_context, + } + .cell() + } +} + +#[turbo_tasks::value_impl] +impl SourceTransform for WebpackLoaders { + #[turbo_tasks::function] + fn transform(self: Vc, source:Vc>) -> Vc> { + Vc::upcast(WebpackLoadersProcessedAsset { transform:self, source }.cell()) + } +} + +#[turbo_tasks::value] +struct WebpackLoadersProcessedAsset { + transform:Vc, + source:Vc>, +} + +#[turbo_tasks::value_impl] +impl Source for WebpackLoadersProcessedAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + Ok(if let Some(rename_as) = self.transform.await?.rename_as.as_deref() { + self.source.ident().rename_as(rename_as.into()) + } else { + self.source.ident() + }) + } +} + +#[turbo_tasks::value_impl] +impl Asset for WebpackLoadersProcessedAsset { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + Ok(self.process().await?.content) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for WebpackLoadersProcessedAsset { + #[turbo_tasks::function] + async fn generate_source_map(self: Vc) -> Result> { + Ok(Vc::cell(self.process().await?.source_map)) + } +} + +#[turbo_tasks::value] +struct ProcessWebpackLoadersResult { + content:Vc, + source_map:Option>, + assets:Vec>, +} + +#[turbo_tasks::function] +fn webpack_loaders_executor(evaluate_context:Vc>) -> Vc { + evaluate_context.process( + Vc::upcast(FileSource::new(embed_file_path("transforms/webpack-loaders.ts".into()))), + Value::new(ReferenceType::Internal(InnerAssets::empty())), + ) +} + +#[turbo_tasks::value_impl] +impl WebpackLoadersProcessedAsset { + #[turbo_tasks::function] + async fn process(self: Vc) -> Result> { + let this = self.await?; + let transform = this.transform.await?; + + let ExecutionContext { project_path, chunking_context, env } = + *transform.execution_context.await?; + let source_content = this.source.content(); + let AssetContent::File(file) = *source_content.await? else { + bail!("Webpack Loaders transform only support transforming files"); + }; + let FileContent::Content(content) = &*file.await? else { + return Ok(ProcessWebpackLoadersResult { + content:AssetContent::File(FileContent::NotFound.cell()).cell(), + assets:Vec::new(), + source_map:None, + } + .cell()); + }; + let content = content.content().to_str()?; + let evaluate_context = transform.evaluate_context; + + let webpack_loaders_executor = webpack_loaders_executor(evaluate_context).module(); + let resource_fs_path = this.source.ident().path(); + let resource_fs_path_ref = resource_fs_path.await?; + let Some(resource_path) = project_path.await?.get_relative_path_to(&resource_fs_path_ref) + else { + bail!(format!( + "Resource path \"{}\" need to be on project filesystem \"{}\"", + resource_fs_path_ref, + project_path.await? + )); + }; + let loaders = transform.loaders.await?; + let config_value = evaluate_webpack_loader(WebpackLoaderContext { + module_asset:webpack_loaders_executor, + cwd:project_path, + env, + context_ident_for_issue:this.source.ident(), + asset_context:evaluate_context, + chunking_context, + resolve_options_context:Some(transform.resolve_options_context), + args:vec![ + Vc::cell(content.into()), + Vc::cell(resource_path.to_string().into()), + Vc::cell(json!(*loaders)), + ], + additional_invalidation:Completion::immutable(), + }) + .await?; + + let SingleValue::Single(val) = config_value.try_into_single().await? else { + // An error happened, which has already been converted into an issue. + return Ok(ProcessWebpackLoadersResult { + content:AssetContent::File(FileContent::NotFound.cell()).cell(), + assets:Vec::new(), + source_map:None, + } + .cell()); + }; + let processed:WebpackLoadersProcessingResult = parse_json_with_source_context( + val.to_str()?, + ) + .context("Unable to deserializate response from webpack loaders transform operation")?; + + // handle SourceMap + let source_map = if let Some(source_map) = processed.map { + SourceMap::new_from_file_content(FileContent::Content(File::from(source_map)).cell()) + .await? + .map(|source_map| source_map.cell()) + } else { + None + }; + let file = File::from(processed.source); + let assets = emitted_assets_to_virtual_sources(processed.assets); + let content = AssetContent::File(FileContent::Content(file).cell()).cell(); + Ok(ProcessWebpackLoadersResult { content, assets, source_map }.cell()) + } +} + +#[turbo_tasks::function] +pub(crate) fn evaluate_webpack_loader( + webpack_loader_context:WebpackLoaderContext, +) -> Vc { + custom_evaluate(webpack_loader_context) +} + +#[turbo_tasks::function] +async fn compute_webpack_loader_evaluation( + webpack_loader_context:WebpackLoaderContext, + sender:Vc, +) -> Result> { + compute(webpack_loader_context, sender).await +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +enum LogType { + Error, + Warn, + Info, + Log, + Debug, + Trace, + Group, + GroupCollapsed, + GroupEnd, + Profile, + ProfileEnd, + Time, + Clear, + Status, +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct LogInfo { + time:u64, + log_type:LogType, + args:Vec, + trace:Option>>, +} + +#[derive(Deserialize, Debug)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum InfoMessage { + FileDependency { path:RcStr }, + BuildDependency { path:RcStr }, + DirDependency { path:RcStr, glob:RcStr }, + EmittedError { severity:IssueSeverity, error:StructuredError }, + Log(LogInfo), +} + +#[derive(Deserialize, Debug, Clone, TaskInput)] +#[serde(rename_all = "camelCase")] + +pub struct WebpackResolveOptions { + alias_fields:Option>, + condition_names:Option>, + no_package_json:bool, + extensions:Option>, + main_fields:Option>, + no_exports_field:bool, + main_files:Option>, + no_modules:bool, + prefer_relative:bool, +} + +#[derive(Deserialize, Debug)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum RequestMessage { + #[serde(rename_all = "camelCase")] + Resolve { options:WebpackResolveOptions, lookup_path:RcStr, request:RcStr }, +} + +#[derive(Serialize, Debug)] +#[serde(untagged)] +pub enum ResponseMessage { + Resolve { path:RcStr }, +} + +#[derive(Clone, PartialEq, Eq, TaskInput)] +pub struct WebpackLoaderContext { + pub module_asset:Vc>, + pub cwd:Vc, + pub env:Vc>, + pub context_ident_for_issue:Vc, + pub asset_context:Vc>, + pub chunking_context:Vc>, + pub resolve_options_context:Option>, + pub args:Vec>, + pub additional_invalidation:Vc, +} + +#[async_trait] +impl EvaluateContext for WebpackLoaderContext { + type InfoMessage = InfoMessage; + type RequestMessage = RequestMessage; + type ResponseMessage = ResponseMessage; + type State = Vec; + + fn compute(self, sender:Vc) { + let _ = compute_webpack_loader_evaluation(self, sender); + } + + fn pool(&self) -> Vc { + get_evaluate_pool( + self.module_asset, + self.cwd, + self.env, + self.asset_context, + self.chunking_context, + None, + self.additional_invalidation, + should_debug("webpack_loader"), + ) + } + + fn args(&self) -> &[Vc] { &self.args } + + fn cwd(&self) -> Vc { self.cwd } + + fn keep_alive(&self) -> bool { true } + + async fn emit_error(&self, error:StructuredError, pool:&NodeJsPool) -> Result<()> { + EvaluationIssue { + error, + context_ident:self.context_ident_for_issue, + assets_for_source_mapping:pool.assets_for_source_mapping, + assets_root:pool.assets_root, + project_dir:self.chunking_context.context_path().root(), + } + .cell() + .emit(); + Ok(()) + } + + async fn info( + &self, + state:&mut Self::State, + data:Self::InfoMessage, + pool:&NodeJsPool, + ) -> Result<()> { + match data { + InfoMessage::FileDependency { path } => { + // TODO We might miss some changes that happened during execution + // Read dependencies to make them a dependencies of this task. This task will + // execute again when they change. + self.cwd.join(path).read().await?; + }, + InfoMessage::BuildDependency { path } => { + // TODO We might miss some changes that happened during execution + BuildDependencyIssue { + context_ident:self.context_ident_for_issue, + path:self.cwd.join(path), + } + .cell() + .emit(); + }, + InfoMessage::DirDependency { path, glob } => { + // TODO We might miss some changes that happened during execution + // Read dependencies to make them a dependencies of this task. This task will + // execute again when they change. + dir_dependency(self.cwd.join(path).read_glob(Glob::new(glob), false)).await?; + }, + InfoMessage::EmittedError { error, severity } => { + EvaluateEmittedErrorIssue { + file_path:self.context_ident_for_issue.path(), + error, + severity:severity.cell(), + assets_for_source_mapping:pool.assets_for_source_mapping, + assets_root:pool.assets_root, + project_dir:self.chunking_context.context_path().root(), + } + .cell() + .emit(); + }, + InfoMessage::Log(log) => { + state.push(log); + }, + } + Ok(()) + } + + async fn request( + &self, + _state:&mut Self::State, + data:Self::RequestMessage, + _pool:&NodeJsPool, + ) -> Result { + match data { + RequestMessage::Resolve { options: webpack_options, lookup_path, request } => { + let Some(resolve_options_context) = self.resolve_options_context else { + bail!("Resolve options are not available in this context"); + }; + let lookup_path = self.cwd.join(lookup_path); + let request = Request::parse(Value::new(Pattern::Constant(request))); + let options = resolve_options(lookup_path, resolve_options_context); + + let options = apply_webpack_resolve_options(options, webpack_options); + + let resolved = + resolve(lookup_path, Value::new(ReferenceType::Undefined), request, options); + + let request_str = request.to_string().await?; + let lookup_path_str = lookup_path.to_string().await?; + if let Some(source) = *resolved.first_source().await? { + if let Some(path) = + self.cwd.await?.get_relative_path_to(&*source.ident().path().await?) + { + Ok(ResponseMessage::Resolve { path }) + } else { + bail!( + "Resolving {} in {} ends up on a different filesystem", + request_str, + lookup_path_str + ); + } + } else { + bail!("Unable to resolve {} in {}", request_str, lookup_path_str); + } + }, + } + } + + async fn finish(&self, state:Self::State, pool:&NodeJsPool) -> Result<()> { + let has_errors = state.iter().any(|log| log.log_type == LogType::Error); + let has_warnings = state.iter().any(|log| log.log_type == LogType::Warn); + if has_errors || has_warnings { + let logs = state + .into_iter() + .filter(|log| { + matches!( + log.log_type, + LogType::Error + | LogType::Warn | LogType::Info + | LogType::Log | LogType::Clear, + ) + }) + .collect(); + + EvaluateErrorLoggingIssue { + file_path:self.context_ident_for_issue.path(), + logging:logs, + severity:if has_errors { + IssueSeverity::Error.cell() + } else { + IssueSeverity::Warning.cell() + }, + assets_for_source_mapping:pool.assets_for_source_mapping, + assets_root:pool.assets_root, + project_dir:self.chunking_context.context_path().root(), + } + .cell() + .emit(); + } + Ok(()) + } +} + +#[turbo_tasks::function] +async fn apply_webpack_resolve_options( + resolve_options:Vc, + webpack_resolve_options:WebpackResolveOptions, +) -> Result> { + let mut resolve_options = resolve_options.await?.clone_value(); + if let Some(alias_fields) = webpack_resolve_options.alias_fields { + let mut old = resolve_options + .in_package + .extract_if(|field| matches!(field, ResolveInPackage::AliasField(..))) + .collect::>(); + for field in alias_fields { + if &*field == "..." { + resolve_options.in_package.extend(take(&mut old)); + } else { + resolve_options.in_package.push(ResolveInPackage::AliasField(field)); + } + } + } + if let Some(condition_names) = webpack_resolve_options.condition_names { + for conditions in get_condition_maps(&mut resolve_options) { + let mut old = take(conditions); + for name in &condition_names { + if name == "..." { + conditions.extend(take(&mut old)); + } else { + conditions.insert(name.clone(), ConditionValue::Set); + } + } + } + } + if webpack_resolve_options.no_package_json { + resolve_options.into_package.retain(|item| { + !matches!( + item, + ResolveIntoPackage::ExportsField { .. } | ResolveIntoPackage::MainField { .. } + ) + }); + } + if let Some(mut extensions) = webpack_resolve_options.extensions { + if let Some(pos) = extensions.iter().position(|ext| ext == "...") { + extensions.splice(pos..=pos, take(&mut resolve_options.extensions)); + } + resolve_options.extensions = extensions; + } + if let Some(main_fields) = webpack_resolve_options.main_fields { + let mut old = resolve_options + .into_package + .extract_if(|field| matches!(field, ResolveIntoPackage::MainField { .. })) + .collect::>(); + for field in main_fields { + if &*field == "..." { + resolve_options.into_package.extend(take(&mut old)); + } else { + resolve_options.into_package.push(ResolveIntoPackage::MainField { field }); + } + } + } + if webpack_resolve_options.no_exports_field { + resolve_options + .into_package + .retain(|field| !matches!(field, ResolveIntoPackage::ExportsField { .. })); + } + if let Some(main_files) = webpack_resolve_options.main_files { + resolve_options.default_files = main_files; + } + if webpack_resolve_options.no_modules { + resolve_options.modules.clear(); + } + if webpack_resolve_options.prefer_relative { + resolve_options.prefer_relative = true; + } + Ok(resolve_options.cell()) +} + +/// An issue that occurred while evaluating node code. +#[turbo_tasks::value(shared)] +pub struct BuildDependencyIssue { + pub context_ident:Vc, + pub path:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for BuildDependencyIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Build dependencies are not yet supported".into()).cell() + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Unsupported.cell() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.context_ident.path() } + + #[turbo_tasks::function] + async fn description(&self) -> Result> { + Ok(Vc::cell(Some( + StyledString::Line(vec![ + StyledString::Text("The file at ".into()), + StyledString::Code(self.path.await?.to_string().into()), + StyledString::Text( + " is a build dependency, which is not yet implemented. + Changing this file or any dependency will not be recognized and might require restarting the \ + server" + .into(), + ), + ]) + .cell(), + ))) + } +} + +/// A hack to invalidate when any file in a directory changes. Need to be +/// awaited before files are accessed. +#[turbo_tasks::function] +async fn dir_dependency(glob:Vc) -> Result> { + let shallow = dir_dependency_shallow(glob); + let glob = glob.await?; + glob.inner.values().map(|&inner| dir_dependency(inner)).try_join().await?; + shallow.await?; + Ok(Completion::new()) +} + +#[turbo_tasks::function] +async fn dir_dependency_shallow(glob:Vc) -> Result> { + let glob = glob.await?; + for item in glob.results.values() { + // Reading all files to add itself as dependency + match *item { + DirectoryEntry::File(file) => { + file.track().await?; + }, + DirectoryEntry::Directory(dir) => { + dir_dependency(dir.read_glob(Glob::new("**".into()), false)).await?; + }, + DirectoryEntry::Symlink(symlink) => { + symlink.read_link().await?; + }, + DirectoryEntry::Other(other) => { + other.get_type().await?; + }, + DirectoryEntry::Error => {}, + } + } + Ok(Completion::new()) +} + +#[turbo_tasks::value(shared)] +pub struct EvaluateEmittedErrorIssue { + pub file_path:Vc, + pub severity:Vc, + pub error:StructuredError, + pub assets_for_source_mapping:Vc, + pub assets_root:Vc, + pub project_dir:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for EvaluateEmittedErrorIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.file_path } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Transform.cell() } + + #[turbo_tasks::function] + fn severity(&self) -> Vc { self.severity } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Issue while running loader".into()).cell() + } + + #[turbo_tasks::function] + async fn description(&self) -> Result> { + Ok(Vc::cell(Some( + StyledString::Text( + self.error + .print( + self.assets_for_source_mapping, + self.assets_root, + self.project_dir, + FormattingMode::Plain, + ) + .await? + .into(), + ) + .cell(), + ))) + } +} + +#[turbo_tasks::value(shared)] +pub struct EvaluateErrorLoggingIssue { + pub file_path:Vc, + pub severity:Vc, + #[turbo_tasks(trace_ignore)] + pub logging:Vec, + pub assets_for_source_mapping:Vc, + pub assets_root:Vc, + pub project_dir:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for EvaluateErrorLoggingIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.file_path } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Transform.cell() } + + #[turbo_tasks::function] + fn severity(&self) -> Vc { self.severity } + + #[turbo_tasks::function] + fn title(&self) -> Vc { + StyledString::Text("Error logging while running loader".into()).cell() + } + + #[turbo_tasks::function] + async fn description(&self) -> Result> { + fn fmt_args(prefix:String, args:&[JsonValue]) -> String { + let mut iter = args.iter(); + let Some(first) = iter.next() else { + return "".to_string(); + }; + let mut result = prefix; + if let JsonValue::String(s) = first { + result.push_str(s); + } else { + result.push_str(&first.to_string()); + } + for arg in iter { + result.push(' '); + result.push_str(&arg.to_string()); + } + result + } + let lines = self + .logging + .iter() + .map(|log| { + match log.log_type { + LogType::Error => { + StyledString::Strong(fmt_args(" ".to_string(), &log.args).into()) + }, + LogType::Warn => { + StyledString::Text(fmt_args(" ".to_string(), &log.args).into()) + }, + LogType::Info => { + StyledString::Text(fmt_args(" ".to_string(), &log.args).into()) + }, + LogType::Log => { + StyledString::Text(fmt_args(" ".to_string(), &log.args).into()) + }, + LogType::Clear => StyledString::Strong("---".into()), + _ => { + unimplemented!("{:?} is not implemented", log.log_type) + }, + } + }) + .collect::>(); + Ok(Vc::cell(Some(StyledString::Stack(lines).cell()))) + } +} diff --git a/crates/turbopack-node/build.rs b/crates/turbopack-node/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-node/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-node/js/Source/compiled/stacktrace-parser/LICENSE b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/LICENSE new file mode 100644 index 0000000000000..89e0797d875e1 --- /dev/null +++ b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2014-2019 Georg Tavonius + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/crates/turbopack-node/js/Source/compiled/stacktrace-parser/index.d.ts b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/index.d.ts new file mode 100644 index 0000000000000..59cb13c617d30 --- /dev/null +++ b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/index.d.ts @@ -0,0 +1,2 @@ +export type StackFrame = any; +export const parse: any; diff --git a/crates/turbopack-node/js/Source/compiled/stacktrace-parser/index.js b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/index.js new file mode 100644 index 0000000000000..e6546a064f7a0 --- /dev/null +++ b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/index.js @@ -0,0 +1,110 @@ +if (typeof __nccwpck_require__ !== "undefined") + __nccwpck_require__.ab = __dirname + "/"; + +var n = ""; +export function parse(e) { + var r = e.split("\n"); + return r.reduce(function (e, r) { + var n = + parseChrome(r) || + parseWinjs(r) || + parseGecko(r) || + parseNode(r) || + parseJSC(r); + if (n) { + e.push(n); + } + return e; + }, []); +} +var a = + /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; +var l = /\((\S*)(?::(\d+))(?::(\d+))\)/; +function parseChrome(e) { + var r = a.exec(e); + if (!r) { + return null; + } + var u = r[2] && r[2].indexOf("native") === 0; + var t = r[2] && r[2].indexOf("eval") === 0; + var i = l.exec(r[2]); + if (t && i != null) { + r[2] = i[1]; + r[3] = i[2]; + r[4] = i[3]; + } + return { + file: !u ? r[2] : null, + methodName: r[1] || n, + arguments: u ? [r[2]] : [], + lineNumber: r[3] ? +r[3] : null, + column: r[4] ? +r[4] : null, + }; +} +var u = + /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i; +function parseWinjs(e) { + var r = u.exec(e); + if (!r) { + return null; + } + return { + file: r[2], + methodName: r[1] || n, + arguments: [], + lineNumber: +r[3], + column: r[4] ? +r[4] : null, + }; +} +var t = + /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i; +var i = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i; +function parseGecko(e) { + var r = t.exec(e); + if (!r) { + return null; + } + var a = r[3] && r[3].indexOf(" > eval") > -1; + var l = i.exec(r[3]); + if (a && l != null) { + r[3] = l[1]; + r[4] = l[2]; + r[5] = null; + } + return { + file: r[3], + methodName: r[1] || n, + arguments: r[2] ? r[2].split(",") : [], + lineNumber: r[4] ? +r[4] : null, + column: r[5] ? +r[5] : null, + }; +} +var s = /^\s*(?:([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i; +function parseJSC(e) { + var r = s.exec(e); + if (!r) { + return null; + } + return { + file: r[3], + methodName: r[1] || n, + arguments: [], + lineNumber: +r[4], + column: r[5] ? +r[5] : null, + }; +} +var o = + /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i; +function parseNode(e) { + var r = o.exec(e); + if (!r) { + return null; + } + return { + file: r[2], + methodName: r[1] || n, + arguments: [], + lineNumber: +r[3], + column: r[4] ? +r[4] : null, + }; +} diff --git a/crates/turbopack-node/js/Source/compiled/stacktrace-parser/package.json b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/package.json new file mode 100644 index 0000000000000..22c43cd162463 --- /dev/null +++ b/crates/turbopack-node/js/Source/compiled/stacktrace-parser/package.json @@ -0,0 +1,7 @@ +{ + "name": "stacktrace-parser", + "main": "index.js", + "types": "index.d.ts", + "dependencies": {}, + "devDependencies": {} +} diff --git a/crates/turbopack-node/js/Source/globals.ts b/crates/turbopack-node/js/Source/globals.ts new file mode 100644 index 0000000000000..257842725280c --- /dev/null +++ b/crates/turbopack-node/js/Source/globals.ts @@ -0,0 +1,2 @@ +// @ts-ignore +process.turbopack = {}; diff --git a/crates/turbopack-node/js/Source/ipc/error.ts b/crates/turbopack-node/js/Source/ipc/error.ts new file mode 100644 index 0000000000000..fbab205b99cdc --- /dev/null +++ b/crates/turbopack-node/js/Source/ipc/error.ts @@ -0,0 +1,52 @@ +// merged from next.js +// https://github.com/vercel/next.js/blob/e657741b9908cf0044aaef959c0c4defb19ed6d8/packages/next/src/lib/is-error.ts +// https://github.com/vercel/next.js/blob/e657741b9908cf0044aaef959c0c4defb19ed6d8/packages/next/src/shared/lib/is-plain-object.ts + +export default function isError(err: unknown): err is Error { + return ( + typeof err === "object" && err !== null && "name" in err && "message" in err + ); +} + +export function getProperError(err: unknown): Error { + if (isError(err)) { + return err; + } + + if (process.env.NODE_ENV === "development") { + // Provide a better error message for cases where `throw undefined` + // is called in development + if (typeof err === "undefined") { + return new Error("`undefined` was thrown instead of a real error"); + } + + if (err === null) { + return new Error("`null` was thrown instead of a real error"); + } + } + + return new Error(isPlainObject(err) ? JSON.stringify(err) : err + ""); +} + +function getObjectClassLabel(value: any): string { + return Object.prototype.toString.call(value); +} + +function isPlainObject(value: any): boolean { + if (getObjectClassLabel(value) !== "[object Object]") { + return false; + } + + const prototype = Object.getPrototypeOf(value); + + /** + * this used to be previously: + * + * `return prototype === null || prototype === Object.prototype` + * + * but Edge Runtime expose Object from vm, being that kind of type-checking wrongly fail. + * + * It was changed to the current implementation since it's resilient to serialization. + */ + return prototype === null || prototype.hasOwnProperty("isPrototypeOf"); +} diff --git a/crates/turbopack-node/js/Source/ipc/evaluate.ts b/crates/turbopack-node/js/Source/ipc/evaluate.ts new file mode 100644 index 0000000000000..beb0c03229c99 --- /dev/null +++ b/crates/turbopack-node/js/Source/ipc/evaluate.ts @@ -0,0 +1,139 @@ +import { IPC, StructuredError } from "./index"; +import type { Ipc as GenericIpc } from "./index"; + +type IpcIncomingMessage = + | { + type: "evaluate"; + args: string[]; + } + | { + type: "result"; + id: number; + error: string | null; + data: any | null; + }; + +type IpcOutgoingMessage = + | { + type: "end"; + data: string | undefined; + duration: number; + } + | { + type: "info"; + data: any; + } + | { + type: "request"; + id: number; + data: any; + }; + +export type Ipc = { + sendInfo(message: IM): Promise; + sendRequest(message: RM): Promise; + sendError(error: Error): Promise; +}; +const ipc = IPC as GenericIpc; + +const queue: string[][] = []; + +export const run = async ( + moduleFactory: () => Promise<{ + init?: () => Promise; + default: (ipc: Ipc, ...deserializedArgs: any[]) => any; + }> +) => { + let nextId = 1; + const requests = new Map(); + const internalIpc = { + sendInfo: (message: any) => + ipc.send({ + type: "info", + data: message, + }), + sendRequest: (message: any) => { + const id = nextId++; + let resolve, reject; + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + requests.set(id, { resolve, reject }); + return ipc + .send({ type: "request", id, data: message }) + .then(() => promise); + }, + sendError: (error: Error) => { + return ipc.sendError(error); + }, + }; + + // Initialize module and send ready message + let getValue: (ipc: Ipc, ...deserializedArgs: any[]) => any; + try { + const module = await moduleFactory(); + if (typeof module.init === "function") { + await module.init(); + } + getValue = module.default; + await ipc.sendReady(); + } catch (err) { + await ipc.sendReady(); + await ipc.sendError(err as Error); + } + + // Queue handling + let isRunning = false; + const run = async () => { + while (queue.length > 0) { + const args = queue.shift()!; + try { + const value = await getValue(internalIpc, ...args); + await ipc.send({ + type: "end", + data: + value === undefined ? undefined : JSON.stringify(value, null, 2), + duration: 0, + }); + } catch (e) { + await ipc.sendError(e as Error); + } + } + isRunning = false; + }; + + // Communication handling + while (true) { + const msg = await ipc.recv(); + + switch (msg.type) { + case "evaluate": { + queue.push(msg.args); + if (!isRunning) { + isRunning = true; + run(); + } + break; + } + case "result": { + const request = requests.get(msg.id); + if (request) { + requests.delete(msg.id); + if (msg.error) { + request.reject(new Error(msg.error)); + } else { + request.resolve(msg.data); + } + } + break; + } + default: { + console.error("unexpected message type", (msg as any).type); + process.exit(1); + } + } + } +}; + +export type { IpcIncomingMessage, IpcOutgoingMessage }; diff --git a/crates/turbopack-node/js/Source/ipc/index.ts b/crates/turbopack-node/js/Source/ipc/index.ts new file mode 100644 index 0000000000000..fa8d37f0c8a74 --- /dev/null +++ b/crates/turbopack-node/js/Source/ipc/index.ts @@ -0,0 +1,209 @@ +import { createConnection } from "node:net"; +import type { StackFrame } from "../compiled/stacktrace-parser"; +import { parse as parseStackTrace } from "../compiled/stacktrace-parser"; +import { getProperError } from "./error"; + +export type StructuredError = { + name: string; + message: string; + stack: StackFrame[]; +}; + +export function structuredError(e: Error): StructuredError { + e = getProperError(e); + + return { + name: e.name, + message: e.message, + stack: typeof e.stack === "string" ? parseStackTrace(e.stack!) : [], + }; +} + +type State = + | { + type: "waiting"; + } + | { + type: "packet"; + length: number; + }; + +export type Ipc = { + recv(): Promise; + send(message: TOutgoing): Promise; + sendError(error: Error): Promise; + sendReady(): Promise; +}; + +function createIpc( + port: number +): Ipc { + const socket = createConnection(port, "127.0.0.1"); + const packetQueue: Buffer[] = []; + const recvPromiseResolveQueue: Array<(message: TIncoming) => void> = []; + + function pushPacket(packet: Buffer) { + const recvPromiseResolve = recvPromiseResolveQueue.shift(); + if (recvPromiseResolve != null) { + recvPromiseResolve(JSON.parse(packet.toString("utf8")) as TIncoming); + } else { + packetQueue.push(packet); + } + } + + let state: State = { type: "waiting" }; + let buffer: Buffer = Buffer.alloc(0); + socket.once("connect", () => { + socket.on("data", (chunk) => { + buffer = Buffer.concat([buffer, chunk]); + + loop: while (true) { + switch (state.type) { + case "waiting": { + if (buffer.length >= 4) { + const length = buffer.readUInt32BE(0); + buffer = buffer.subarray(4); + state = { type: "packet", length }; + } else { + break loop; + } + break; + } + case "packet": { + if (buffer.length >= state.length) { + const packet = buffer.subarray(0, state.length); + buffer = buffer.subarray(state.length); + state = { type: "waiting" }; + pushPacket(packet); + } else { + break loop; + } + break; + } + } + } + }); + }); + // When the socket is closed, this process is no longer needed. + // This might happen e. g. when parent process is killed or + // node.js pool is garbage collected. + socket.once("close", () => { + process.exit(0); + }); + + function send(message: any): Promise { + const packet = Buffer.from(JSON.stringify(message), "utf8"); + const length = Buffer.alloc(4); + length.writeUInt32BE(packet.length); + socket.write(length); + + return new Promise((resolve, reject) => { + socket.write(packet, (err) => { + process.stderr.write(`TURBOPACK_OUTPUT_D\n`); + process.stdout.write(`TURBOPACK_OUTPUT_D\n`); + if (err != null) { + reject(err); + } else { + resolve(); + } + }); + }); + } + + function sendReady(): Promise { + const length = Buffer.from([0, 0, 0, 0]); + return new Promise((resolve, reject) => { + socket.write(length, (err) => { + process.stderr.write(`TURBOPACK_OUTPUT_D\n`); + process.stdout.write(`TURBOPACK_OUTPUT_D\n`); + + if (err != null) { + reject(err); + } else { + resolve(); + } + }); + }); + } + + return { + async recv() { + const packet = packetQueue.shift(); + if (packet != null) { + return JSON.parse(packet.toString("utf8")) as TIncoming; + } + + const result = await new Promise((resolve) => { + recvPromiseResolveQueue.push((result) => { + resolve(result); + }); + }); + + return result; + }, + + send(message: TOutgoing) { + return send(message); + }, + + sendReady, + + async sendError(error: Error): Promise { + try { + await send({ + type: "error", + ...structuredError(error), + }); + } catch (err) { + console.error("failed to send error back to rust:", err); + // ignore and exit anyway + process.exit(1); + } + + process.exit(0); + }, + }; +} + +const PORT = process.argv[2]; + +export const IPC = createIpc(parseInt(PORT, 10)); + +process.on("uncaughtException", (err) => { + IPC.sendError(err); +}); + +const improveConsole = (name: string, stream: string, addStack: boolean) => { + // @ts-ignore + const original = console[name]; + // @ts-ignore + const stdio = process[stream]; + // @ts-ignore + console[name] = (...args: any[]) => { + stdio.write(`TURBOPACK_OUTPUT_B\n`); + original(...args); + if (addStack) { + const stack = new Error().stack?.replace(/^.+\n.+\n/, "") + "\n"; + stdio.write("TURBOPACK_OUTPUT_S\n"); + stdio.write(stack); + } + stdio.write("TURBOPACK_OUTPUT_E\n"); + }; +}; + +improveConsole("error", "stderr", true); +improveConsole("warn", "stderr", true); +improveConsole("count", "stdout", true); +improveConsole("trace", "stderr", false); +improveConsole("log", "stdout", true); +improveConsole("group", "stdout", true); +improveConsole("groupCollapsed", "stdout", true); +improveConsole("table", "stdout", true); +improveConsole("debug", "stdout", true); +improveConsole("info", "stdout", true); +improveConsole("dir", "stdout", true); +improveConsole("dirxml", "stdout", true); +improveConsole("timeEnd", "stdout", true); +improveConsole("timeLog", "stdout", true); +improveConsole("timeStamp", "stdout", true); +improveConsole("assert", "stderr", true); diff --git a/crates/turbopack-node/js/Source/transforms/postcss.ts b/crates/turbopack-node/js/Source/transforms/postcss.ts new file mode 100644 index 0000000000000..7d7a558a32bac --- /dev/null +++ b/crates/turbopack-node/js/Source/transforms/postcss.ts @@ -0,0 +1,134 @@ +declare const __turbopack_external_require__: (id: string) => any; + +// @ts-ignore +import postcss from "@vercel/turbopack/postcss"; +// @ts-ignore +import importedConfig from "CONFIG"; +import { relative, isAbsolute, sep } from "path"; +import type { Ipc } from "../ipc/evaluate"; +import type { IpcInfoMessage, IpcRequestMessage } from "./webpack-loaders"; + +const contextDir = process.cwd(); + +function toPath(file: string) { + const relPath = relative(contextDir, file); + if (isAbsolute(relPath)) { + throw new Error( + `Cannot depend on path (${file}) outside of root directory (${contextDir})` + ); + } + return sep !== "/" ? relPath.replaceAll(sep, "/") : relPath; +} + +let processor: any; + +export const init = async (ipc: Ipc) => { + let config = importedConfig; + if (typeof config === "function") { + config = await config({ env: "development" }); + } + if (typeof config === "undefined") { + throw new Error( + "PostCSS config is undefined (make sure to export an function or object from config file)" + ); + } + let plugins: any[]; + if (Array.isArray(config.plugins)) { + plugins = config.plugins.map((plugin: [string, any] | string | any) => { + if (Array.isArray(plugin)) { + return plugin; + } else if (typeof plugin === "string") { + return [plugin, {}]; + } else { + return plugin; + } + }); + } else if (typeof config.plugins === "object") { + plugins = Object.entries(config.plugins).filter(([, options]) => options); + } else { + plugins = []; + } + const loadedPlugins = plugins.map((plugin) => { + if (Array.isArray(plugin)) { + const [arg, options] = plugin; + let pluginFactory = arg; + + if (typeof pluginFactory === "string") { + pluginFactory = __turbopack_external_require__(pluginFactory); + } + + if (pluginFactory.default) { + pluginFactory = pluginFactory.default; + } + + return pluginFactory(options); + } + return plugin; + }); + + processor = postcss(loadedPlugins); +}; + +export default async function transform( + ipc: Ipc, + cssContent: string, + name: string +) { + const { css, map, messages } = await processor.process(cssContent, { + from: name, + to: name, + map: { + inline: false, + annotation: false, + }, + }); + + const assets = []; + for (const msg of messages) { + switch (msg.type) { + case "asset": + assets.push({ + file: msg.file, + content: msg.content, + sourceMap: + typeof msg.sourceMap === "string" + ? msg.sourceMap + : JSON.stringify(msg.sourceMap), + // There is also an info field, which we currently ignore + }); + break; + case "file-dependency": + case "missing-dependency": + ipc.sendInfo({ + type: "fileDependency", + path: toPath(msg.file), + }); + break; + case "build-dependency": + ipc.sendInfo({ + type: "buildDependency", + path: toPath(msg.file), + }); + break; + case "dir-dependency": + ipc.sendInfo({ + type: "dirDependency", + path: toPath(msg.dir), + glob: msg.glob, + }); + break; + case "context-dependency": + ipc.sendInfo({ + type: "dirDependency", + path: toPath(msg.file), + glob: "**", + }); + break; + } + } + return { + css, + map: JSON.stringify(map), + assets, + }; +} diff --git a/crates/turbopack-node/js/Source/transforms/webpack-loaders.ts b/crates/turbopack-node/js/Source/transforms/webpack-loaders.ts new file mode 100644 index 0000000000000..ff254a0bccd04 --- /dev/null +++ b/crates/turbopack-node/js/Source/transforms/webpack-loaders.ts @@ -0,0 +1,519 @@ +declare const __turbopack_external_require__: { + resolve: (name: string, opt: { paths: string[] }) => string; +} & ((id: string) => any); + +import type { Ipc } from "../ipc/evaluate"; +import { + relative, + isAbsolute, + join, + sep, + dirname, + resolve as pathResolve, +} from "path"; +import { + StackFrame, + parse as parseStackTrace, +} from "../compiled/stacktrace-parser"; +import { type StructuredError } from "src/ipc"; + +export type IpcInfoMessage = + | { + type: "fileDependency"; + path: string; + } + | { + type: "buildDependency"; + path: string; + } + | { + type: "dirDependency"; + path: string; + glob: string; + } + | { + type: "emittedError"; + severity: "warning" | "error"; + error: StructuredError; + } + | { + type: "log"; + time: number; + logType: string; + args: any[]; + trace?: StackFrame[]; + }; + +export type IpcRequestMessage = { + type: "resolve"; + options: any; + lookupPath: string; + request: string; +}; + +type LoaderConfig = + | string + | { + loader: string; + options: { [k: string]: unknown }; + }; + +let runLoaders: typeof import("loader-runner")["runLoaders"]; +try { + ({ runLoaders } = require("@vercel/turbopack/loader-runner")); +} catch { + ({ runLoaders } = __turbopack_external_require__("loader-runner")); +} + +const contextDir = process.cwd(); +const toPath = (file: string) => { + const relPath = relative(contextDir, file); + if (isAbsolute(relPath)) { + throw new Error( + `Cannot depend on path (${file}) outside of root directory (${contextDir})` + ); + } + return sep !== "/" ? relPath.replaceAll(sep, "/") : relPath; +}; +const fromPath = (path: string) => { + return join(contextDir, sep !== "/" ? path.replaceAll("/", sep) : path); +}; + +const LogType = Object.freeze({ + error: "error", + warn: "warn", + info: "info", + log: "log", + debug: "debug", + + trace: "trace", + + group: "group", + groupCollapsed: "groupCollapsed", + groupEnd: "groupEnd", + + profile: "profile", + profileEnd: "profileEnd", + + time: "time", + + clear: "clear", + status: "status", +}); + +const loaderFlag = "LOADER_EXECUTION"; + +const cutOffByFlag = (stack: string, flag: string): string => { + const errorStack = stack.split("\n"); + for (let i = 0; i < errorStack.length; i++) { + if (errorStack[i].includes(flag)) { + errorStack.length = i; + } + } + return errorStack.join("\n"); +}; + +/** + * @param stack stack trace + * @returns stack trace without the loader execution flag included + */ +const cutOffLoaderExecution = (stack: string): string => + cutOffByFlag(stack, loaderFlag); + +class DummySpan { + traceChild() { + return new DummySpan(); + } + + traceFn(fn: (span: DummySpan) => T): T { + return fn(this); + } + + async traceAsyncFn(fn: (span: DummySpan) => T | Promise): Promise { + return await fn(this); + } + + stop() { + return; + } +} + +type ResolveOptions = { + dependencyType?: string; + alias?: Record | unknown[]; + aliasFields?: string[]; + cacheWithContext?: boolean; + conditionNames?: string[]; + descriptionFiles?: string[]; + enforceExtension?: boolean; + extensionAlias: Record; + extensions?: string[]; + fallback?: Record; + mainFields?: string[]; + mainFiles?: string[]; + exportsFields?: string[]; + modules?: string[]; + plugins?: unknown[]; + symlinks?: boolean; + unsafeCache?: boolean; + useSyncFileSystemCalls?: boolean; + preferRelative?: boolean; + preferAbsolute?: boolean; + restrictions?: unknown[]; + roots?: string[]; + importFields?: string[]; +}; +const SUPPORTED_RESOLVE_OPTIONS = new Set([ + "alias", + "aliasFields", + "conditionNames", + "descriptionFiles", + "extensions", + "exportsFields", + "mainFields", + "mainFiles", + "modules", + "restrictions", + "preferRelative", + "dependencyType", +]); + +const transform = ( + ipc: Ipc, + content: string, + name: string, + loaders: LoaderConfig[] +) => { + return new Promise((resolve, reject) => { + const resource = pathResolve(contextDir, name); + const resourceDir = dirname(resource); + + const loadersWithOptions = loaders.map((loader) => + typeof loader === "string" ? { loader, options: {} } : loader + ); + + runLoaders( + { + resource, + context: { + _module: { + // For debugging purpose, if someone find context is not full compatible to + // webpack they can guess this comes from turbopack + __reserved: "TurbopackContext", + }, + currentTraceSpan: new DummySpan(), + rootContext: contextDir, + getOptions() { + const entry = this.loaders[this.loaderIndex]; + return entry.options && typeof entry.options === "object" + ? entry.options + : {}; + }, + getResolve: (options: ResolveOptions) => { + const rustOptions = { + aliasFields: undefined as undefined | string[], + conditionNames: undefined as undefined | string[], + noPackageJson: false, + extensions: undefined as undefined | string[], + mainFields: undefined as undefined | string[], + noExportsField: false, + mainFiles: undefined as undefined | string[], + noModules: false, + preferRelative: false, + }; + if (options.alias) { + if (!Array.isArray(options.alias) || options.alias.length > 0) { + throw new Error("alias resolve option is not supported"); + } + } + if (options.aliasFields) { + if (!Array.isArray(options.aliasFields)) { + throw new Error("aliasFields resolve option must be an array"); + } + rustOptions.aliasFields = options.aliasFields; + } + if (options.conditionNames) { + if (!Array.isArray(options.conditionNames)) { + throw new Error( + "conditionNames resolve option must be an array" + ); + } + rustOptions.conditionNames = options.conditionNames; + } + if (options.descriptionFiles) { + if ( + !Array.isArray(options.descriptionFiles) || + options.descriptionFiles.length > 0 + ) { + throw new Error( + "descriptionFiles resolve option is not supported" + ); + } + rustOptions.noPackageJson = true; + } + if (options.extensions) { + if (!Array.isArray(options.extensions)) { + throw new Error("extensions resolve option must be an array"); + } + rustOptions.extensions = options.extensions; + } + if (options.mainFields) { + if (!Array.isArray(options.mainFields)) { + throw new Error("mainFields resolve option must be an array"); + } + rustOptions.mainFields = options.mainFields; + } + if (options.exportsFields) { + if ( + !Array.isArray(options.exportsFields) || + options.exportsFields.length > 0 + ) { + throw new Error( + "exportsFields resolve option is not supported" + ); + } + rustOptions.noExportsField = true; + } + if (options.mainFiles) { + if (!Array.isArray(options.mainFiles)) { + throw new Error("mainFiles resolve option must be an array"); + } + rustOptions.mainFiles = options.mainFiles; + } + if (options.modules) { + if ( + !Array.isArray(options.modules) || + options.modules.length > 0 + ) { + throw new Error("modules resolve option is not supported"); + } + rustOptions.noModules = true; + } + if (options.restrictions) { + // TODO This is ignored for now + } + if (options.dependencyType) { + // TODO This is ignored for now + } + if (options.preferRelative) { + if (typeof options.preferRelative !== "boolean") { + throw new Error( + "preferRelative resolve option must be a boolean" + ); + } + rustOptions.preferRelative = options.preferRelative; + } + return ( + lookupPath: string, + request: string, + callback?: (err?: Error, result?: string) => void + ) => { + const promise = ipc + .sendRequest({ + type: "resolve", + options: rustOptions, + lookupPath: toPath(lookupPath), + request, + }) + .then((unknownResult) => { + let result = unknownResult as { path: string }; + if (result && typeof result.path === "string") { + return fromPath(result.path); + } else { + throw Error( + "Expected { path: string } from resolve request" + ); + } + }); + if (callback) { + promise + .then( + (result) => callback(undefined, result), + (err) => callback(err) + ) + .catch((err) => { + ipc.sendError(err); + }); + } else { + return promise; + } + }; + }, + emitWarning: makeErrorEmitter("warning", ipc), + emitError: makeErrorEmitter("error", ipc), + getLogger(name: unknown) { + const logFn = (logType: string, ...args: unknown[]) => { + let trace; + switch (logType) { + case LogType.warn: + case LogType.error: + case LogType.trace: + case LogType.debug: + trace = parseStackTrace( + cutOffLoaderExecution(new Error("Trace").stack!) + .split("\n") + .slice(3) + .join("\n") + ); + break; + } + + ipc.sendInfo({ + type: "log", + time: Date.now(), + logType, + args, + trace, + }); + }; + let timers: Map | undefined; + let timersAggregates: Map | undefined; + + // See https://github.com/webpack/webpack/blob/a48c34b34d2d6c44f9b2b221d7baf278d34ac0be/lib/logging/Logger.js#L8 + return { + error: logFn.bind(this, LogType.error), + warn: logFn.bind(this, LogType.warn), + info: logFn.bind(this, LogType.info), + log: logFn.bind(this, LogType.log), + debug: logFn.bind(this, LogType.debug), + assert: (assertion: boolean, ...args: any[]) => { + if (!assertion) { + logFn(LogType.error, ...args); + } + }, + trace: logFn.bind(this, LogType.trace), + clear: logFn.bind(this, LogType.clear), + status: logFn.bind(this, LogType.status), + group: logFn.bind(this, LogType.group), + groupCollapsed: logFn.bind(this, LogType.groupCollapsed), + groupEnd: logFn.bind(this, LogType.groupEnd), + profile: logFn.bind(this, LogType.profile), + profileEnd: logFn.bind(this, LogType.profileEnd), + time: (label: string) => { + timers = timers || new Map(); + timers.set(label, process.hrtime()); + }, + timeLog: (label: string) => { + const prev = timers && timers.get(label); + if (!prev) { + throw new Error( + `No such label '${label}' for WebpackLogger.timeLog()` + ); + } + const time = process.hrtime(prev); + logFn(LogType.time, [label, ...time]); + }, + timeEnd: (label: string) => { + const prev = timers && timers.get(label); + if (!prev) { + throw new Error( + `No such label '${label}' for WebpackLogger.timeEnd()` + ); + } + const time = process.hrtime(prev); + /** @type {Map} */ + timers!.delete(label); + logFn(LogType.time, [label, ...time]); + }, + timeAggregate: (label: string) => { + const prev = timers && timers.get(label); + if (!prev) { + throw new Error( + `No such label '${label}' for WebpackLogger.timeAggregate()` + ); + } + const time = process.hrtime(prev); + /** @type {Map} */ + timers!.delete(label); + /** @type {Map} */ + timersAggregates = timersAggregates || new Map(); + const current = timersAggregates.get(label); + if (current !== undefined) { + if (time[1] + current[1] > 1e9) { + time[0] += current[0] + 1; + time[1] = time[1] - 1e9 + current[1]; + } else { + time[0] += current[0]; + time[1] += current[1]; + } + } + timersAggregates.set(label, time); + }, + timeAggregateEnd: (label: string) => { + if (timersAggregates === undefined) return; + const time = timersAggregates.get(label); + if (time === undefined) return; + timersAggregates.delete(label); + logFn(LogType.time, [label, ...time]); + }, + }; + }, + }, + + loaders: loadersWithOptions.map((loader) => ({ + loader: __turbopack_external_require__.resolve(loader.loader, { + paths: [resourceDir], + }), + options: loader.options, + })), + readResource: (_filename, callback) => { + // TODO assuming the filename === resource, but loaders might change that + callback(null, Buffer.from(content, "utf-8")); + }, + }, + (err, result) => { + if (err) return reject(err); + for (const dep of result.contextDependencies) { + ipc.sendInfo({ + type: "dirDependency", + path: toPath(dep), + glob: "**", + }); + } + for (const dep of result.fileDependencies) { + ipc.sendInfo({ + type: "fileDependency", + path: toPath(dep), + }); + } + if (!result.result) return reject(new Error("No result from loaders")); + const [source, map] = result.result; + resolve({ + source, + map: + typeof map === "string" + ? map + : typeof map === "object" + ? JSON.stringify(map) + : undefined, + }); + } + ); + }); +}; + +export { transform as default }; + +function makeErrorEmitter( + severity: "warning" | "error", + ipc: Ipc +) { + return function (error: Error | string) { + ipc.sendInfo({ + type: "emittedError", + severity: severity, + error: + error instanceof Error + ? { + name: error.name, + message: error.message, + stack: parseStackTrace(error.stack), + } + : { + name: "Error", + message: error, + stack: [], + }, + }); + }; +} diff --git a/crates/turbopack-node/js/package.json b/crates/turbopack-node/js/package.json new file mode 100644 index 0000000000000..3e34fbb0311e0 --- /dev/null +++ b/crates/turbopack-node/js/package.json @@ -0,0 +1,15 @@ +{ + "name": "@vercel/turbopack-node", + "description": "turbopack node runtime", + "exports": { + "./*": "./src/*.ts" + }, + "scripts": {}, + "dependencies": { + "loader-runner": "4.3.0" + }, + "devDependencies": { + "@types/loader-runner": "2.2.8", + "@types/node": "22.13.1" + } +} diff --git a/crates/turbopack-node/js/tsconfig.json b/crates/turbopack-node/js/tsconfig.json new file mode 100644 index 0000000000000..4c88e2f5ef179 --- /dev/null +++ b/crates/turbopack-node/js/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + // type checking + "strict": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + + // interop constraints + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + + // js support + "allowJs": true, + "checkJs": false, + + // environment + "lib": ["ESNext"], + "target": "esnext", + + // modules + "baseUrl": ".", + "module": "esnext", + "moduleResolution": "node", + + // emit + "noEmit": true, + "stripInternal": true + }, + "include": ["src"] +} diff --git a/crates/turbopack-nodejs/Source/chunking_context.rs b/crates/turbopack-nodejs/Source/chunking_context.rs new file mode 100644 index 0000000000000..31ea5091047b7 --- /dev/null +++ b/crates/turbopack-nodejs/Source/chunking_context.rs @@ -0,0 +1,345 @@ +use std::iter::once; + +use anyhow::{Context, Result, bail}; +use tracing::Instrument; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + chunk::{ + Chunk, + ChunkGroupResult, + ChunkItem, + ChunkableModule, + ChunkingContext, + EntryChunkGroupResult, + EvaluatableAssets, + MinifyType, + ModuleId, + availability_info::AvailabilityInfo, + chunk_group::{MakeChunkGroupResult, make_chunk_group}, + }, + environment::Environment, + ident::AssetIdent, + module::Module, + output::OutputAsset, +}; +use turbopack_ecmascript::{ + async_chunk::module::AsyncLoaderModule, + chunk::EcmascriptChunk, + manifest::{chunk_asset::ManifestAsyncModule, loader_item::ManifestLoaderChunkItem}, +}; +use turbopack_ecmascript_runtime::RuntimeType; + +use crate::ecmascript::node::{ + chunk::EcmascriptBuildNodeChunk, + entry::chunk::EcmascriptBuildNodeEntryChunk, +}; + +/// A builder for [`Vc`]. +pub struct NodeJsChunkingContextBuilder { + chunking_context:NodeJsChunkingContext, +} + +impl NodeJsChunkingContextBuilder { + pub fn asset_prefix(mut self, asset_prefix:Vc>) -> Self { + self.chunking_context.asset_prefix = asset_prefix; + self + } + + pub fn minify_type(mut self, minify_type:MinifyType) -> Self { + self.chunking_context.minify_type = minify_type; + self + } + + pub fn runtime_type(mut self, runtime_type:RuntimeType) -> Self { + self.chunking_context.runtime_type = runtime_type; + self + } + + pub fn manifest_chunks(mut self, manifest_chunks:bool) -> Self { + self.chunking_context.manifest_chunks = manifest_chunks; + self + } + + /// Builds the chunking context. + pub fn build(self) -> Vc { + NodeJsChunkingContext::new(Value::new(self.chunking_context)) + } +} + +/// A chunking context for build mode. +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(Debug, Clone, Hash, PartialOrd, Ord)] +pub struct NodeJsChunkingContext { + /// This path get stripped off of chunk paths before generating output asset + /// paths. + context_path:Vc, + /// This path is used to compute the url to request chunks or assets from + output_root:Vc, + /// This path is used to compute the url to request chunks or assets from + client_root:Vc, + /// Chunks are placed at this path + chunk_root_path:Vc, + /// Static assets are placed at this path + asset_root_path:Vc, + /// Static assets requested from this url base + asset_prefix:Vc>, + /// The environment chunks will be evaluated in. + environment:Vc, + /// The kind of runtime to include in the output. + runtime_type:RuntimeType, + /// Whether to minify resulting chunks + minify_type:MinifyType, + /// Whether to use manifest chunks for lazy compilation + manifest_chunks:bool, +} + +impl NodeJsChunkingContext { + /// Creates a new chunking context builder. + pub fn builder( + context_path:Vc, + output_root:Vc, + client_root:Vc, + chunk_root_path:Vc, + asset_root_path:Vc, + environment:Vc, + runtime_type:RuntimeType, + ) -> NodeJsChunkingContextBuilder { + NodeJsChunkingContextBuilder { + chunking_context:NodeJsChunkingContext { + context_path, + output_root, + client_root, + chunk_root_path, + asset_root_path, + asset_prefix:Default::default(), + environment, + runtime_type, + minify_type:MinifyType::NoMinify, + manifest_chunks:false, + }, + } + } +} + +impl NodeJsChunkingContext { + /// Returns the kind of runtime to include in output chunks. + /// + /// This is defined directly on `NodeJsChunkingContext` so it is zero-cost + /// when `RuntimeType` has a single variant. + pub fn runtime_type(&self) -> RuntimeType { self.runtime_type } + + /// Returns the minify type. + pub fn minify_type(&self) -> MinifyType { self.minify_type } +} + +#[turbo_tasks::value_impl] +impl NodeJsChunkingContext { + #[turbo_tasks::function] + fn new(this:Value) -> Vc { this.into_value().cell() } + + #[turbo_tasks::function] + pub fn asset_prefix(&self) -> Vc> { self.asset_prefix } + + #[turbo_tasks::function] + async fn generate_chunk( + self: Vc, + chunk:Vc>, + ) -> Result>> { + Ok( + if let Some(ecmascript_chunk) = + Vc::try_resolve_downcast_type::(chunk).await? + { + Vc::upcast(EcmascriptBuildNodeChunk::new(self, ecmascript_chunk)) + } else if let Some(output_asset) = + Vc::try_resolve_sidecast::>(chunk).await? + { + output_asset + } else { + bail!("Unable to generate output asset for chunk"); + }, + ) + } +} + +#[turbo_tasks::value_impl] +impl ChunkingContext for NodeJsChunkingContext { + #[turbo_tasks::function] + fn name(&self) -> Vc { Vc::cell("unknown".into()) } + + #[turbo_tasks::function] + fn context_path(&self) -> Vc { self.context_path } + + #[turbo_tasks::function] + fn output_root(&self) -> Vc { self.output_root } + + #[turbo_tasks::function] + fn environment(&self) -> Vc { self.environment } + + #[turbo_tasks::function] + async fn asset_url(self: Vc, ident:Vc) -> Result> { + let this = self.await?; + let asset_path = ident.path().await?.to_string(); + let asset_path = asset_path + .strip_prefix(&format!("{}/", this.client_root.await?.path)) + .context("expected client root to contain asset path")?; + + Ok(Vc::cell( + format!( + "{}{}", + this.asset_prefix + .await? + .as_ref() + .map(|s| s.clone()) + .unwrap_or_else(|| "/".into()), + asset_path + ) + .into(), + )) + } + + #[turbo_tasks::function] + async fn chunk_path( + &self, + ident:Vc, + extension:RcStr, + ) -> Result> { + let root_path = self.chunk_root_path; + let name = ident.output_name(self.context_path, extension).await?; + Ok(root_path.join(name.clone_value())) + } + + #[turbo_tasks::function] + fn reference_chunk_source_maps(&self, _chunk:Vc>) -> Vc { + Vc::cell(true) + } + + #[turbo_tasks::function] + async fn asset_path( + &self, + content_hash:RcStr, + original_asset_ident:Vc, + ) -> Result> { + let source_path = original_asset_ident.path().await?; + let basename = source_path.file_name(); + let asset_path = match source_path.extension_ref() { + Some(ext) => { + format!( + "{basename}.{content_hash}.{ext}", + basename = &basename[..basename.len() - ext.len() - 1], + content_hash = &content_hash[..8] + ) + }, + None => format!("{basename}.{content_hash}", content_hash = &content_hash[..8]), + }; + Ok(self.asset_root_path.join(asset_path.into())) + } + + #[turbo_tasks::function] + async fn chunk_group( + self: Vc, + module:Vc>, + availability_info:Value, + ) -> Result> { + let span = + tracing::info_span!("chunking", module = module.ident().to_string().await?.to_string()); + async move { + let MakeChunkGroupResult { chunks, availability_info } = make_chunk_group( + Vc::upcast(self), + [Vc::upcast(module)], + availability_info.into_value(), + ) + .await?; + + let mut assets:Vec>> = + chunks.iter().map(|chunk| self.generate_chunk(*chunk)).collect(); + + // Resolve assets + for asset in assets.iter_mut() { + *asset = asset.resolve().await?; + } + + Ok(ChunkGroupResult { assets:Vc::cell(assets), availability_info }.cell()) + } + .instrument(span) + .await + } + + /// Generates an output chunk that: + /// * evaluates the given assets; and + /// * exports the result of evaluating the given module as a CommonJS + /// default export. + #[turbo_tasks::function] + pub async fn entry_chunk_group( + self: Vc, + path:Vc, + module:Vc>, + evaluatable_assets:Vc, + availability_info:Value, + ) -> Result> { + let availability_info = availability_info.into_value(); + + let MakeChunkGroupResult { chunks, availability_info } = make_chunk_group( + Vc::upcast(self), + once(module).chain(evaluatable_assets.await?.iter().map(|&asset| Vc::upcast(asset))), + availability_info, + ) + .await?; + + let other_chunks:Vec<_> = chunks.iter().map(|chunk| self.generate_chunk(*chunk)).collect(); + + let Some(module) = Vc::try_resolve_downcast(module).await? else { + bail!("module must be placeable in an ecmascript chunk"); + }; + + let asset = Vc::upcast(EcmascriptBuildNodeEntryChunk::new( + path, + self, + Vc::cell(other_chunks), + evaluatable_assets, + module, + )); + + Ok(EntryChunkGroupResult { asset, availability_info }.cell()) + } + + #[turbo_tasks::function] + fn evaluated_chunk_group( + self: Vc, + _ident:Vc, + _evaluatable_assets:Vc, + _availability_info:Value, + ) -> Result> { + // TODO(alexkirsz) This method should be part of a separate trait that is + // only implemented for client/edge runtimes. + bail!("the build chunking context does not support evaluated chunk groups") + } + + #[turbo_tasks::function] + async fn async_loader_chunk_item( + self: Vc, + module:Vc>, + availability_info:Value, + ) -> Result>> { + Ok(if self.await?.manifest_chunks { + let manifest_asset = + ManifestAsyncModule::new(module, Vc::upcast(self), availability_info); + Vc::upcast(ManifestLoaderChunkItem::new(manifest_asset, Vc::upcast(self))) + } else { + let module = AsyncLoaderModule::new(module, Vc::upcast(self), availability_info); + Vc::upcast(module.as_chunk_item(Vc::upcast(self))) + }) + } + + #[turbo_tasks::function] + async fn async_loader_chunk_item_id( + self: Vc, + module:Vc>, + ) -> Result> { + Ok(if self.await?.manifest_chunks { + self.chunk_item_id_from_ident(ManifestLoaderChunkItem::asset_ident_for(module)) + } else { + self.chunk_item_id_from_ident(AsyncLoaderModule::asset_ident_for(module)) + }) + } +} diff --git a/crates/turbopack-nodejs/Source/ecmascript/mod.rs b/crates/turbopack-nodejs/Source/ecmascript/mod.rs new file mode 100644 index 0000000000000..6b3c8edd4cf78 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/mod.rs @@ -0,0 +1 @@ +pub(crate) mod node; diff --git a/crates/turbopack-nodejs/Source/ecmascript/node/chunk.rs b/crates/turbopack-nodejs/Source/ecmascript/node/chunk.rs new file mode 100644 index 0000000000000..8849c10f13471 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/node/chunk.rs @@ -0,0 +1,133 @@ +use anyhow::Result; +use indexmap::IndexSet; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{Chunk, ChunkingContext}, + ident::AssetIdent, + introspect::{Introspectable, IntrospectableChildren}, + output::{OutputAsset, OutputAssets}, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAsset}, + version::VersionedContent, +}; +use turbopack_ecmascript::chunk::EcmascriptChunk; + +use super::content::EcmascriptBuildNodeChunkContent; +use crate::NodeJsChunkingContext; + +/// Production Ecmascript chunk targeting Node.js. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptBuildNodeChunk { + chunking_context:Vc, + chunk:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunk { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new(chunking_context:Vc, chunk:Vc) -> Vc { + EcmascriptBuildNodeChunk { chunking_context, chunk }.cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Build Node Chunk".into())) + } +} + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("ecmascript build node chunk".into()) } + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + async fn own_content(self: Vc) -> Result> { + let this = self.await?; + Ok(EcmascriptBuildNodeChunkContent::new( + this.chunking_context, + self, + this.chunk.chunk_content(), + )) + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + let ident = self.chunk.ident().with_modifier(modifier()); + AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".into())) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let chunk_references = this.chunk.references().await?; + let include_source_map = + *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await?; + let mut references = + Vec::with_capacity(chunk_references.len() + if include_source_map { 1 } else { 0 }); + + for reference in &*chunk_references { + references.push(*reference); + } + + if include_source_map { + references.push(Vc::upcast(SourceMapAsset::new(Vc::upcast(self)))); + } + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { self.own_content().content() } + + #[turbo_tasks::function] + fn versioned_content(self: Vc) -> Vc> { + Vc::upcast(self.own_content()) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.own_content().generate_source_map() + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> Vc { Vc::cell("ecmascript build node chunk".into()) } + +#[turbo_tasks::function] +fn introspectable_details() -> Vc { + Vc::cell("generates a production EcmaScript chunk targeting Node.js".into()) +} + +#[turbo_tasks::value_impl] +impl Introspectable for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + fn ty(&self) -> Vc { introspectable_type() } + + #[turbo_tasks::function] + fn title(self: Vc) -> Vc { self.ident().to_string() } + + #[turbo_tasks::function] + fn details(&self) -> Vc { introspectable_details() } + + #[turbo_tasks::function] + async fn children(&self) -> Result> { + let mut children = IndexSet::new(); + let introspectable_chunk = + Vc::upcast::>(self.chunk).resolve().await?; + children.insert((Vc::cell("chunk".into()), introspectable_chunk)); + Ok(Vc::cell(children)) + } +} diff --git a/crates/turbopack-nodejs/Source/ecmascript/node/content.rs b/crates/turbopack-nodejs/Source/ecmascript/node/content.rs new file mode 100644 index 0000000000000..503c87d465817 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/node/content.rs @@ -0,0 +1,126 @@ +use std::io::Write; + +use anyhow::Result; +use indoc::writedoc; +use turbo_tasks::{ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::AssetContent, + chunk::{ChunkItemExt, ChunkingContext, MinifyType, ModuleId}, + code_builder::{Code, CodeBuilder}, + output::OutputAsset, + source_map::{GenerateSourceMap, OptionSourceMap}, + version::{Version, VersionedContent}, +}; +use turbopack_ecmascript::{ + chunk::{EcmascriptChunkContent, EcmascriptChunkItemExt}, + minify::minify, + utils::StringifyJs, +}; + +use super::{chunk::EcmascriptBuildNodeChunk, version::EcmascriptBuildNodeChunkVersion}; +use crate::NodeJsChunkingContext; + +#[turbo_tasks::value] +pub(super) struct EcmascriptBuildNodeChunkContent { + pub(super) content:Vc, + pub(super) chunking_context:Vc, + pub(super) chunk:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunkContent { + #[turbo_tasks::function] + pub(crate) async fn new( + chunking_context:Vc, + chunk:Vc, + content:Vc, + ) -> Result> { + Ok(EcmascriptBuildNodeChunkContent { content, chunking_context, chunk }.cell()) + } +} + +pub(super) async fn chunk_items( + content:Vc, +) -> Result, ReadRef)>> { + content + .await? + .chunk_items + .iter() + .map(|&(chunk_item, async_module_info)| { + async move { Ok((chunk_item.id().await?, chunk_item.code(async_module_info).await?)) } + }) + .try_join() + .await +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunkContent { + #[turbo_tasks::function] + async fn code(self: Vc) -> Result> { + let this = self.await?; + let chunk_path_vc = this.chunk.ident().path(); + let chunk_path = chunk_path_vc.await?; + + let mut code = CodeBuilder::default(); + + writedoc!( + code, + r#" + module.exports = {{ + + "#, + )?; + + for (id, item_code) in chunk_items(this.content).await? { + write!(code, "{}: ", StringifyJs(&id))?; + code.push_code(&item_code); + writeln!(code, ",")?; + } + + write!(code, "\n}};")?; + + if code.has_source_map() { + let filename = chunk_path.file_name(); + write!(code, "\n\n//# sourceMappingURL={}.map", urlencoding::encode(filename))?; + } + + let code = code.build().cell(); + if matches!(this.chunking_context.await?.minify_type(), MinifyType::Minify) { + return Ok(minify(chunk_path_vc, code)); + } + + Ok(code) + } + + #[turbo_tasks::function] + pub(crate) async fn own_version(self: Vc) -> Result> { + let this = self.await?; + Ok(EcmascriptBuildNodeChunkVersion::new( + this.chunking_context.output_root(), + this.chunk.ident().path(), + this.content, + this.chunking_context.await?.minify_type(), + )) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeChunkContent { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() + } +} + +#[turbo_tasks::value_impl] +impl VersionedContent for EcmascriptBuildNodeChunkContent { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } + + #[turbo_tasks::function] + fn version(self: Vc) -> Vc> { Vc::upcast(self.own_version()) } +} diff --git a/crates/turbopack-nodejs/Source/ecmascript/node/entry/chunk.rs b/crates/turbopack-nodejs/Source/ecmascript/node/entry/chunk.rs new file mode 100644 index 0000000000000..05cb2d601d222 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/node/entry/chunk.rs @@ -0,0 +1,203 @@ +use std::io::Write; + +use anyhow::{Result, bail}; +use indoc::writedoc; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbo_tasks_fs::{File, FileSystemPath}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkItemExt, ChunkableModule, ChunkingContext, EvaluatableAssets}, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + output::{OutputAsset, OutputAssets}, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAsset}, +}; +use turbopack_ecmascript::{chunk::EcmascriptChunkPlaceable, utils::StringifyJs}; + +use super::runtime::EcmascriptBuildNodeRuntimeChunk; +use crate::NodeJsChunkingContext; + +/// An Ecmascript chunk that loads a list of parallel chunks, then instantiates +/// runtime entries. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptBuildNodeEntryChunk { + path:Vc, + chunking_context:Vc, + other_chunks:Vc, + evaluatable_assets:Vc, + exported_module:Vc>, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeEntryChunk { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new( + path:Vc, + chunking_context:Vc, + other_chunks:Vc, + evaluatable_assets:Vc, + exported_module:Vc>, + ) -> Vc { + EcmascriptBuildNodeEntryChunk { + path, + chunking_context, + other_chunks, + evaluatable_assets, + exported_module, + } + .cell() + } + + #[turbo_tasks::function] + async fn code(self: Vc) -> Result> { + let this = self.await?; + + let output_root = this.chunking_context.output_root().await?; + let chunk_path = self.ident().path().await?; + let chunk_directory = self.ident().path().parent().await?; + let runtime_path = self.runtime_chunk().ident().path().await?; + let runtime_relative_path = + if let Some(path) = chunk_directory.get_relative_path_to(&runtime_path) { + path + } else { + bail!( + "cannot find a relative path from the chunk ({}) to the runtime chunk ({})", + chunk_path.to_string(), + runtime_path.to_string(), + ); + }; + let chunk_public_path = if let Some(path) = output_root.get_path_to(&chunk_path) { + path + } else { + bail!( + "chunk path ({}) is not in output root ({})", + chunk_path.to_string(), + output_root.to_string() + ); + }; + + let mut code = CodeBuilder::default(); + + writedoc!( + code, + r#" + const CHUNK_PUBLIC_PATH = {}; + const runtime = require({}); + "#, + StringifyJs(chunk_public_path), + StringifyJs(&*runtime_relative_path) + )?; + + let other_chunks = this.other_chunks.await?; + for other_chunk in &*other_chunks { + let other_chunk_path = &*other_chunk.ident().path().await?; + if let Some(other_chunk_public_path) = output_root.get_path_to(other_chunk_path) { + writedoc!( + code, + // TODO(WEB-1112) This should call `require()` directly, perhaps as an argument + // to `loadChunk`. + r#" + runtime.loadChunk({}); + "#, + StringifyJs(&other_chunk_public_path) + )?; + } + } + + let evaluatable_assets = this.evaluatable_assets.await?; + for evaluatable_asset in &*evaluatable_assets { + if let Some(placeable) = + Vc::try_resolve_sidecast::>(*evaluatable_asset) + .await? + { + let runtime_module_id = + placeable.as_chunk_item(Vc::upcast(this.chunking_context)).id().await?; + + writedoc!( + code, + r#" + runtime.getOrInstantiateRuntimeModule({}, CHUNK_PUBLIC_PATH); + "#, + StringifyJs(&*runtime_module_id), + )?; + } + } + + let runtime_module_id = this + .exported_module + .as_chunk_item(Vc::upcast(this.chunking_context)) + .id() + .await?; + + writedoc!( + code, + r#" + module.exports = runtime.getOrInstantiateRuntimeModule({}, CHUNK_PUBLIC_PATH).exports; + "#, + StringifyJs(&*runtime_module_id), + )?; + + Ok(Code::cell(code.build())) + } + + #[turbo_tasks::function] + async fn runtime_chunk(self: Vc) -> Result> { + let this = self.await?; + Ok(EcmascriptBuildNodeRuntimeChunk::new(this.chunking_context)) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptBuildNodeEntryChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Build Node Evaluate Chunk".into())) + } +} + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("ecmascript build node evaluate chunk".into()) } + +#[turbo_tasks::function] +fn chunk_reference_description() -> Vc { Vc::cell("chunk".into()) } + +#[turbo_tasks::value_impl] +impl OutputAsset for EcmascriptBuildNodeEntryChunk { + #[turbo_tasks::function] + fn ident(&self) -> Vc { AssetIdent::from_path(self.path) } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let mut references = vec![Vc::upcast(self.runtime_chunk())]; + + if *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await? { + references.push(Vc::upcast(SourceMapAsset::new(Vc::upcast(self)))) + } + + let other_chunks = this.other_chunks.await?; + for &other_chunk in &*other_chunks { + references.push(Vc::upcast(other_chunk)); + } + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptBuildNodeEntryChunk { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeEntryChunk { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() + } +} diff --git a/crates/turbopack-nodejs/Source/ecmascript/node/entry/mod.rs b/crates/turbopack-nodejs/Source/ecmascript/node/entry/mod.rs new file mode 100644 index 0000000000000..cd4d9271d1b59 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/node/entry/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod chunk; +pub(crate) mod runtime; diff --git a/crates/turbopack-nodejs/Source/ecmascript/node/entry/runtime.rs b/crates/turbopack-nodejs/Source/ecmascript/node/entry/runtime.rs new file mode 100644 index 0000000000000..7f47ee8d31a89 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/node/entry/runtime.rs @@ -0,0 +1,138 @@ +use std::io::Write; + +use anyhow::{Result, bail}; +use indoc::writedoc; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbo_tasks_fs::{File, FileSystem}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::ChunkingContext, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + output::{OutputAsset, OutputAssets}, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAsset}, +}; +use turbopack_ecmascript::utils::StringifyJs; +use turbopack_ecmascript_runtime::RuntimeType; + +use crate::NodeJsChunkingContext; + +/// An Ecmascript chunk that contains the Node.js runtime code. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptBuildNodeRuntimeChunk { + chunking_context:Vc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeRuntimeChunk { + /// Creates a new [`Vc`]. + #[turbo_tasks::function] + pub fn new(chunking_context:Vc) -> Vc { + EcmascriptBuildNodeRuntimeChunk { chunking_context }.cell() + } + + #[turbo_tasks::function] + async fn code(self: Vc) -> Result> { + let this = self.await?; + + let output_root = this.chunking_context.output_root().await?; + let runtime_path = self.ident().path().await?; + let runtime_public_path = if let Some(path) = output_root.get_path_to(&runtime_path) { + path + } else { + bail!( + "runtime path {} is not in output root {}", + runtime_path.to_string(), + output_root.to_string() + ); + }; + + let mut code = CodeBuilder::default(); + let output_root = output_root.to_string(); + let asset_prefix = this.chunking_context.asset_prefix().await?; + let asset_prefix = asset_prefix.as_deref().unwrap_or("/"); + + writedoc!( + code, + r#" + const RUNTIME_PUBLIC_PATH = {}; + const OUTPUT_ROOT = {}; + const ASSET_PREFIX = {}; + "#, + StringifyJs(runtime_public_path), + StringifyJs(output_root.as_str()), + StringifyJs(asset_prefix), + )?; + + match this.chunking_context.await?.runtime_type() { + RuntimeType::Development => { + let runtime_code = turbopack_ecmascript_runtime::get_nodejs_runtime_code( + this.chunking_context.environment(), + ); + code.push_code(&*runtime_code.await?); + }, + RuntimeType::Production => { + let runtime_code = turbopack_ecmascript_runtime::get_nodejs_runtime_code( + this.chunking_context.environment(), + ); + code.push_code(&*runtime_code.await?); + }, + #[cfg(feature = "test")] + RuntimeType::Dummy => { + let runtime_code = turbopack_ecmascript_runtime::get_dummy_runtime_code(); + code.push_code(&runtime_code); + }, + } + + Ok(Code::cell(code.build())) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptBuildNodeRuntimeChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Build Node Runtime Chunk".into())) + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for EcmascriptBuildNodeRuntimeChunk { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + let ident = AssetIdent::from_path( + turbopack_ecmascript_runtime::embed_fs().root().join("runtime.js".into()), + ); + + AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".into())) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + let this = self.await?; + let mut references = vec![]; + + if *this.chunking_context.reference_chunk_source_maps(Vc::upcast(self)).await? { + references.push(Vc::upcast(SourceMapAsset::new(Vc::upcast(self)))) + } + + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptBuildNodeRuntimeChunk { + #[turbo_tasks::function] + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file(File::from(code.source_code().clone()).into())) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeRuntimeChunk { + #[turbo_tasks::function] + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() + } +} diff --git a/crates/turbopack-nodejs/Source/ecmascript/node/mod.rs b/crates/turbopack-nodejs/Source/ecmascript/node/mod.rs new file mode 100644 index 0000000000000..f5006f4d8ece3 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/node/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod chunk; +pub(crate) mod content; +pub(crate) mod entry; +pub(crate) mod version; diff --git a/crates/turbopack-nodejs/Source/ecmascript/node/version.rs b/crates/turbopack-nodejs/Source/ecmascript/node/version.rs new file mode 100644 index 0000000000000..c25dbbee285b2 --- /dev/null +++ b/crates/turbopack-nodejs/Source/ecmascript/node/version.rs @@ -0,0 +1,66 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{RcStr, ReadRef, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbo_tasks_hash::{Xxh3Hash64Hasher, encode_hex}; +use turbopack_core::{ + chunk::{MinifyType, ModuleId}, + code_builder::Code, + version::Version, +}; +use turbopack_ecmascript::chunk::EcmascriptChunkContent; + +use super::content::chunk_items; + +#[turbo_tasks::value(serialization = "none")] +pub(super) struct EcmascriptBuildNodeChunkVersion { + chunk_path:String, + chunk_items:Vec<(ReadRef, ReadRef)>, + minify_type:MinifyType, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunkVersion { + #[turbo_tasks::function] + pub async fn new( + output_root:Vc, + chunk_path:Vc, + content:Vc, + minify_type:MinifyType, + ) -> Result> { + let output_root = output_root.await?; + let chunk_path = chunk_path.await?; + let chunk_path = if let Some(path) = output_root.get_path_to(&chunk_path) { + path + } else { + bail!( + "chunk path {} is not in client root {}", + chunk_path.to_string(), + output_root.to_string() + ); + }; + let chunk_items = chunk_items(content).await?; + Ok(EcmascriptBuildNodeChunkVersion { + chunk_path:chunk_path.to_string(), + chunk_items, + minify_type, + } + .cell()) + } +} + +#[turbo_tasks::value_impl] +impl Version for EcmascriptBuildNodeChunkVersion { + #[turbo_tasks::function] + fn id(&self) -> Vc { + let mut hasher = Xxh3Hash64Hasher::new(); + hasher.write_ref(&self.chunk_path); + hasher.write_ref(&self.minify_type); + hasher.write_value(self.chunk_items.len()); + for (module_id, code) in &self.chunk_items { + hasher.write_value((module_id, code.source_code())); + } + let hash = hasher.finish(); + let hex_hash = encode_hex(hash); + Vc::cell(hex_hash.into()) + } +} diff --git a/crates/turbopack-nodejs/Source/lib.rs b/crates/turbopack-nodejs/Source/lib.rs new file mode 100644 index 0000000000000..deb83dd114f79 --- /dev/null +++ b/crates/turbopack-nodejs/Source/lib.rs @@ -0,0 +1,17 @@ +#![feature(lint_reasons)] +#![feature(iter_intersperse)] +#![feature(arbitrary_self_types)] + +pub(crate) mod chunking_context; +pub(crate) mod ecmascript; + +pub use chunking_context::{NodeJsChunkingContext, NodeJsChunkingContextBuilder}; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + turbopack_ecmascript_runtime::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-nodejs/build.rs b/crates/turbopack-nodejs/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-nodejs/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-resolve/Source/ecmascript.rs b/crates/turbopack-resolve/Source/ecmascript.rs new file mode 100644 index 0000000000000..704f79480d441 --- /dev/null +++ b/crates/turbopack-resolve/Source/ecmascript.rs @@ -0,0 +1,131 @@ +use anyhow::Result; +use turbo_tasks::{Value, Vc}; +use turbopack_core::{ + issue::{IssueSeverity, IssueSource}, + reference_type::{CommonJsReferenceSubType, EcmaScriptModulesReferenceSubType, ReferenceType}, + resolve::{ + ModuleResolveResult, + handle_resolve_error, + options::{ + ConditionValue, + ResolutionConditions, + ResolveInPackage, + ResolveIntoPackage, + ResolveOptions, + }, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + }, +}; +/// Retrieves the [ResolutionConditions] of both the "into" package (allowing a +/// package to control how it can be imported) and the "in" package (controlling +/// how this package imports others) resolution options, so that they can be +/// manipulated together. +pub fn get_condition_maps( + options:&mut ResolveOptions, +) -> impl Iterator { + options + .into_package + .iter_mut() + .filter_map(|item| { + if let ResolveIntoPackage::ExportsField { conditions, .. } = item { + Some(conditions) + } else { + None + } + }) + .chain(options.in_package.iter_mut().filter_map(|item| { + if let ResolveInPackage::ImportsField { conditions, .. } = item { + Some(conditions) + } else { + None + } + })) +} + +#[turbo_tasks::function] +pub async fn apply_esm_specific_options( + options:Vc, + reference_type:Value, +) -> Result> { + let mut options:ResolveOptions = options.await?.clone_value(); + // TODO set fully_specified when in strict ESM mode + // options.fully_specified = true; + for conditions in get_condition_maps(&mut options) { + conditions.insert("import".into(), ConditionValue::Set); + conditions.insert("require".into(), ConditionValue::Unset); + } + + if matches!( + reference_type.into_value(), + ReferenceType::EcmaScriptModules(EcmaScriptModulesReferenceSubType::ImportWithType(_)) + ) { + options.extensions.clear(); + } + + Ok(options.into()) +} + +#[turbo_tasks::function] +pub async fn apply_cjs_specific_options(options:Vc) -> Result> { + let mut options:ResolveOptions = options.await?.clone_value(); + for conditions in get_condition_maps(&mut options) { + conditions.insert("import".into(), ConditionValue::Unset); + conditions.insert("require".into(), ConditionValue::Set); + } + Ok(options.into()) +} + +#[turbo_tasks::function] +pub async fn esm_resolve( + origin:Vc>, + request:Vc, + ty:Value, + issue_severity:Vc, + issue_source:Option>, +) -> Result> { + let ty = Value::new(ReferenceType::EcmaScriptModules(ty.into_value())); + let options = apply_esm_specific_options(origin.resolve_options(ty.clone()), ty.clone()) + .resolve() + .await?; + specific_resolve(origin, request, options, ty, issue_severity, issue_source).await +} + +#[turbo_tasks::function] +pub async fn cjs_resolve( + origin:Vc>, + request:Vc, + issue_source:Option>, + issue_severity:Vc, +) -> Result> { + // TODO pass CommonJsReferenceSubType + let ty = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)); + let options = apply_cjs_specific_options(origin.resolve_options(ty.clone())).resolve().await?; + specific_resolve(origin, request, options, ty, issue_severity, issue_source).await +} + +async fn specific_resolve( + origin:Vc>, + request:Vc, + options:Vc, + reference_type:Value, + issue_severity:Vc, + issue_source:Option>, +) -> Result> { + let result = origin.resolve_asset(request, options, reference_type.clone()); + + handle_resolve_error( + result, + reference_type, + origin.origin_path(), + request, + options, + issue_severity, + issue_source, + ) + .await +} + +pub fn try_to_severity(in_try:bool) -> Vc { + if in_try { IssueSeverity::Warning.cell() } else { IssueSeverity::Error.cell() } +} diff --git a/crates/turbopack-resolve/Source/lib.rs b/crates/turbopack-resolve/Source/lib.rs new file mode 100644 index 0000000000000..1a8c83f4f8683 --- /dev/null +++ b/crates/turbopack-resolve/Source/lib.rs @@ -0,0 +1,14 @@ +#![feature(arbitrary_self_types)] + +pub mod ecmascript; +pub mod node_native_binding; +pub mod resolve; +pub mod resolve_options_context; +pub mod typescript; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-resolve/Source/node_native_binding.rs b/crates/turbopack-resolve/Source/node_native_binding.rs new file mode 100644 index 0000000000000..b1c26b24ccf9e --- /dev/null +++ b/crates/turbopack-resolve/Source/node_native_binding.rs @@ -0,0 +1,397 @@ +use anyhow::Result; +use indexmap::IndexMap; +use lazy_static::lazy_static; +use regex::Regex; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{RcStr, TryFlatJoinIterExt, ValueToString, Vc}; +use turbo_tasks_fs::{ + DirectoryEntry, + FileContent, + FileSystemEntryType, + FileSystemPath, + glob::Glob, + json::parse_json_rope_with_source_context, +}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + file_source::FileSource, + raw_module::RawModule, + reference::ModuleReference, + resolve::{ModuleResolveResult, RequestKey, ResolveResultItem, pattern::Pattern, resolve_raw}, + source::Source, + target::{CompileTarget, Platform}, +}; + +#[derive(Serialize, Deserialize, Debug)] +struct NodePreGypConfigJson { + binary:NodePreGypConfig, +} + +#[derive(Serialize, Deserialize, Debug)] +struct NodePreGypConfig { + module_name:String, + module_path:String, + napi_versions:Vec, +} + +#[turbo_tasks::value] +#[derive(Hash, Clone, Debug)] +pub struct NodePreGypConfigReference { + pub context_dir:Vc, + pub config_file_pattern:Vc, + pub compile_target:Vc, +} + +#[turbo_tasks::value_impl] +impl NodePreGypConfigReference { + #[turbo_tasks::function] + pub fn new( + context_dir:Vc, + config_file_pattern:Vc, + compile_target:Vc, + ) -> Vc { + Self::cell(NodePreGypConfigReference { context_dir, config_file_pattern, compile_target }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for NodePreGypConfigReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + resolve_node_pre_gyp_files(self.context_dir, self.config_file_pattern, self.compile_target) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for NodePreGypConfigReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + let context_dir = self.context_dir.to_string().await?; + let config_file_pattern = self.config_file_pattern.to_string().await?; + let compile_target = self.compile_target.await?; + Ok(Vc::cell( + format!( + "node-gyp in {} with {} for {}", + context_dir, config_file_pattern, compile_target + ) + .into(), + )) + } +} + +#[turbo_tasks::function] +pub async fn resolve_node_pre_gyp_files( + context_dir:Vc, + config_file_pattern:Vc, + compile_target:Vc, +) -> Result> { + lazy_static! { + static ref NAPI_VERSION_TEMPLATE: Regex = + Regex::new(r"\{(napi_build_version|node_napi_label)\}") + .expect("create napi_build_version regex failed"); + static ref PLATFORM_TEMPLATE: Regex = + Regex::new(r"\{platform\}").expect("create node_platform regex failed"); + static ref ARCH_TEMPLATE: Regex = + Regex::new(r"\{arch\}").expect("create node_arch regex failed"); + static ref LIBC_TEMPLATE: Regex = + Regex::new(r"\{libc\}").expect("create node_libc regex failed"); + } + let config = resolve_raw(context_dir, config_file_pattern, true).first_source().await?; + let compile_target = compile_target.await?; + if let Some(config_asset) = *config { + if let AssetContent::File(file) = &*config_asset.content().await? { + if let FileContent::Content(ref config_file) = &*file.await? { + let config_file_path = config_asset.ident().path(); + let mut affecting_paths = vec![config_file_path]; + let config_file_dir = config_file_path.parent(); + let node_pre_gyp_config:NodePreGypConfigJson = + parse_json_rope_with_source_context(config_file.content())?; + let mut sources:IndexMap>> = IndexMap::new(); + for version in node_pre_gyp_config.binary.napi_versions.iter() { + let native_binding_path = NAPI_VERSION_TEMPLATE.replace( + node_pre_gyp_config.binary.module_path.as_str(), + format!("{}", version), + ); + let platform = compile_target.platform; + let native_binding_path = + PLATFORM_TEMPLATE.replace(&native_binding_path, platform.as_str()); + let native_binding_path = + ARCH_TEMPLATE.replace(&native_binding_path, compile_target.arch.as_str()); + let native_binding_path:RcStr = LIBC_TEMPLATE + .replace( + &native_binding_path, + // node-pre-gyp only cares about libc on linux + if platform == Platform::Linux { + compile_target.libc.as_str() + } else { + "unknown" + }, + ) + .into(); + + for (key, entry) in config_file_dir + .join(native_binding_path.clone()) + .read_glob( + Glob::new(format!("*.{}", compile_target.dylib_ext()).into()), + false, + ) + .await? + .results + .iter() + { + if let &DirectoryEntry::File(dylib) | &DirectoryEntry::Symlink(dylib) = + entry + { + sources.insert( + format!("{native_binding_path}/{key}").into(), + Vc::upcast(FileSource::new(dylib)), + ); + } + } + + let node_file_path:RcStr = format!( + "{}/{}.node", + native_binding_path, node_pre_gyp_config.binary.module_name + ) + .into(); + let resolved_file_vc = config_file_dir.join(node_file_path.clone()); + sources.insert(node_file_path, Vc::upcast(FileSource::new(resolved_file_vc))); + } + for (key, entry) in config_file_dir + // TODO + // read the dependencies path from `bindings.gyp` + .join("deps/lib".into()) + .read_glob(Glob::new("*".into()), false) + .await? + .results + .iter() + { + match *entry { + DirectoryEntry::File(dylib) => { + sources.insert( + format!("deps/lib/{key}").into(), + Vc::upcast(FileSource::new(dylib)), + ); + }, + DirectoryEntry::Symlink(dylib) => { + let realpath_with_links = dylib.realpath_with_links().await?; + for &symlink in realpath_with_links.symlinks.iter() { + affecting_paths.push(symlink); + } + sources.insert( + format!("deps/lib/{key}").into(), + Vc::upcast(FileSource::new(realpath_with_links.path)), + ); + }, + _ => {}, + } + } + return Ok(ModuleResolveResult::modules_with_affecting_sources( + sources.into_iter().map(|(key, source)| { + (RequestKey::new(key), Vc::upcast(RawModule::new(source))) + }), + affecting_paths.into_iter().map(|p| Vc::upcast(FileSource::new(p))).collect(), + ) + .into()); + } + }; + } + Ok(ModuleResolveResult::unresolveable().into()) +} + +#[turbo_tasks::value] +#[derive(Hash, Clone, Debug)] +pub struct NodeGypBuildReference { + pub context_dir:Vc, + pub compile_target:Vc, +} + +#[turbo_tasks::value_impl] +impl NodeGypBuildReference { + #[turbo_tasks::function] + pub fn new(context_dir:Vc, target:Vc) -> Vc { + Self::cell(NodeGypBuildReference { context_dir, compile_target:target }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for NodeGypBuildReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + resolve_node_gyp_build_files(self.context_dir, self.compile_target) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for NodeGypBuildReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + let context_dir = self.context_dir.to_string().await?; + let compile_target = self.compile_target.await?; + Ok(Vc::cell(format!("node-gyp in {} for {}", context_dir, compile_target).into())) + } +} + +#[turbo_tasks::function] +pub async fn resolve_node_gyp_build_files( + context_dir:Vc, + compile_target:Vc, +) -> Result> { + lazy_static! { + // TODO Proper parser + static ref GYP_BUILD_TARGET_NAME: Regex = + Regex::new(r#"['"]target_name['"]\s*:\s*(?:"(.*?)"|'(.*?)')"#) + .expect("create napi_build_version regex failed"); + } + let binding_gyp_pat = Pattern::new(Pattern::Constant("binding.gyp".into())); + let gyp_file = resolve_raw(context_dir, binding_gyp_pat, true); + if let [binding_gyp] = &gyp_file.primary_sources().await?[..] { + let mut merged_affecting_sources = + gyp_file.await?.get_affecting_sources().collect::>(); + if let AssetContent::File(file) = &*binding_gyp.content().await? { + if let FileContent::Content(config_file) = &*file.await? { + if let Some(captured) = + GYP_BUILD_TARGET_NAME.captures(&config_file.content().to_str()?) + { + let mut resolved:IndexMap>> = + IndexMap::with_capacity(captured.len()); + for found in captured.iter().skip(1).flatten() { + let name = found.as_str(); + let target_path = context_dir.join("build/Release".into()); + let resolved_prebuilt_file = resolve_raw( + target_path, + Pattern::new(Pattern::Constant(format!("{}.node", name).into())), + true, + ) + .await?; + if let Some((_, ResolveResultItem::Source(source))) = + resolved_prebuilt_file.primary.first() + { + resolved.insert( + format!("build/Release/{name}.node").into(), + source.resolve().await?, + ); + merged_affecting_sources + .extend(resolved_prebuilt_file.affecting_sources.iter().copied()); + } + } + if !resolved.is_empty() { + return Ok(ModuleResolveResult::modules_with_affecting_sources( + resolved.into_iter().map(|(key, source)| { + (RequestKey::new(key), Vc::upcast(RawModule::new(source))) + }), + merged_affecting_sources, + ) + .into()); + } + } + } + } + } + let compile_target = compile_target.await?; + let arch = compile_target.arch; + let platform = compile_target.platform; + let prebuilt_dir = format!("{}-{}", platform, arch); + Ok(resolve_raw( + context_dir, + Pattern::new(Pattern::Concatenation(vec![ + Pattern::Constant(format!("prebuilds/{}/", prebuilt_dir).into()), + Pattern::Dynamic, + Pattern::Constant(".node".into()), + ])), + true, + ) + .as_raw_module_result()) +} + +#[turbo_tasks::value] +#[derive(Hash, Clone, Debug)] +pub struct NodeBindingsReference { + pub context_dir:Vc, + pub file_name:RcStr, +} + +#[turbo_tasks::value_impl] +impl NodeBindingsReference { + #[turbo_tasks::function] + pub fn new(context_dir:Vc, file_name:RcStr) -> Vc { + Self::cell(NodeBindingsReference { context_dir, file_name }) + } +} + +#[turbo_tasks::value_impl] +impl ModuleReference for NodeBindingsReference { + #[turbo_tasks::function] + fn resolve_reference(&self) -> Vc { + resolve_node_bindings_files(self.context_dir, self.file_name.clone()) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for NodeBindingsReference { + #[turbo_tasks::function] + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!("bindings in {}", self.context_dir.to_string().await?,).into())) + } +} + +#[turbo_tasks::function] +pub async fn resolve_node_bindings_files( + context_dir:Vc, + file_name:RcStr, +) -> Result> { + lazy_static! { + static ref BINDINGS_TRY: [&'static str; 5] = [ + "build/bindings", + "build/Release", + "build/Release/bindings", + "out/Release/bindings", + "Release/bindings", + ]; + } + let mut root_context_dir = context_dir; + loop { + let resolved = resolve_raw( + root_context_dir, + Pattern::new(Pattern::Constant("package.json".into())), + true, + ) + .first_source() + .await?; + if let Some(asset) = *resolved { + if let AssetContent::File(file) = &*asset.content().await? { + if let FileContent::Content(_) = &*file.await? { + break; + } + } + }; + let current_context = root_context_dir.await?; + let parent = root_context_dir.parent(); + let parent_context = parent.await?; + if parent_context.path == current_context.path { + break; + } + root_context_dir = parent; + } + + let try_path = |sub_path:RcStr| { + async move { + let path = root_context_dir.join(sub_path.clone()); + Ok(if matches!(*path.get_type().await?, FileSystemEntryType::File) { + Some(( + RequestKey::new(sub_path), + Vc::upcast(RawModule::new(Vc::upcast(FileSource::new(path)))), + )) + } else { + None + }) + } + }; + + let modules = BINDINGS_TRY + .iter() + .map(|try_dir| try_path(format!("{}/{}", try_dir, &file_name).into())) + .try_flat_join() + .await?; + Ok(ModuleResolveResult::modules(modules).cell()) +} diff --git a/crates/turbopack-resolve/Source/resolve.rs b/crates/turbopack-resolve/Source/resolve.rs new file mode 100644 index 0000000000000..a1df312b2c63b --- /dev/null +++ b/crates/turbopack-resolve/Source/resolve.rs @@ -0,0 +1,302 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::{FileSystem, FileSystemPath}; +use turbopack_core::resolve::{ + AliasMap, + AliasPattern, + ExternalType, + FindContextFileResult, + find_context_file, + options::{ + ConditionValue, + ImportMap, + ImportMapping, + ResolutionConditions, + ResolveInPackage, + ResolveIntoPackage, + ResolveModules, + ResolveOptions, + }, +}; + +use crate::{ + resolve_options_context::ResolveOptionsContext, + typescript::{apply_tsconfig_resolve_options, tsconfig, tsconfig_resolve_options}, +}; + +const NODE_EXTERNALS:[&str; 51] = [ + "assert", + "async_hooks", + "buffer", + "child_process", + "cluster", + "console", + "constants", + "crypto", + "dgram", + "diagnostics_channel", + "dns", + "dns/promises", + "domain", + "events", + "fs", + "fs/promises", + "http", + "http2", + "https", + "inspector", + "module", + "net", + "os", + "path", + "path/posix", + "path/win32", + "perf_hooks", + "process", + "punycode", + "querystring", + "readline", + "repl", + "stream", + "stream/promises", + "stream/web", + "string_decoder", + "sys", + "timers", + "timers/promises", + "tls", + "trace_events", + "tty", + "url", + "util", + "util/types", + "v8", + "vm", + "wasi", + "worker_threads", + "zlib", + "pnpapi", +]; + +const EDGE_NODE_EXTERNALS:[&str; 5] = ["buffer", "events", "assert", "util", "async_hooks"]; + +#[turbo_tasks::function] +async fn base_resolve_options( + resolve_path:Vc, + options_context:Vc, +) -> Result> { + let parent = resolve_path.parent().resolve().await?; + if parent != resolve_path { + return Ok(base_resolve_options(parent, options_context)); + } + let resolve_path_value = resolve_path.await?; + let opt = options_context.await?; + let emulating = opt.emulate_environment; + let root = resolve_path_value.fs.root(); + let mut direct_mappings = AliasMap::new(); + let node_externals = if let Some(environment) = emulating { + environment.node_externals().await?.clone_value() + } else { + opt.enable_node_externals + }; + if node_externals { + for req in NODE_EXTERNALS { + direct_mappings.insert( + AliasPattern::exact(req), + ImportMapping::External(None, ExternalType::CommonJs).into(), + ); + direct_mappings.insert( + AliasPattern::exact(format!("node:{req}")), + ImportMapping::External(None, ExternalType::CommonJs).into(), + ); + } + } + if opt.enable_edge_node_externals { + for req in EDGE_NODE_EXTERNALS { + direct_mappings.insert( + AliasPattern::exact(req), + ImportMapping::External(Some(format!("node:{req}").into()), ExternalType::CommonJs) + .into(), + ); + direct_mappings.insert( + AliasPattern::exact(format!("node:{req}")), + ImportMapping::External(None, ExternalType::CommonJs).into(), + ); + } + } + + let mut import_map = ImportMap::new(direct_mappings); + if let Some(additional_import_map) = opt.import_map { + let additional_import_map = additional_import_map.await?; + import_map.extend_ref(&additional_import_map); + } + let import_map = import_map.cell(); + + let plugins = opt.after_resolve_plugins.clone(); + + let conditions = { + let mut conditions:ResolutionConditions = [ + ("import".into(), ConditionValue::Unknown), + ("require".into(), ConditionValue::Unknown), + ] + .into_iter() + .collect(); + if opt.browser { + conditions.insert("browser".into(), ConditionValue::Set); + } + if opt.module { + conditions.insert("module".into(), ConditionValue::Set); + } + if let Some(environment) = emulating { + for condition in environment.resolve_conditions().await?.iter() { + conditions.insert(condition.clone(), ConditionValue::Set); + } + } + for condition in opt.custom_conditions.iter() { + conditions.insert(condition.clone(), ConditionValue::Set); + } + // Infer some well-known conditions + let dev = conditions.get("development").cloned(); + let prod = conditions.get("production").cloned(); + if prod.is_none() { + conditions.insert( + "production".into(), + if matches!(dev, Some(ConditionValue::Set)) { + ConditionValue::Unset + } else { + ConditionValue::Unknown + }, + ); + } + if dev.is_none() { + conditions.insert( + "development".into(), + if matches!(prod, Some(ConditionValue::Set)) { + ConditionValue::Unset + } else { + ConditionValue::Unknown + }, + ); + } + conditions + }; + + let extensions = if let Some(custom_extension) = &opt.custom_extensions { + custom_extension.clone() + } else if let Some(environment) = emulating { + environment.resolve_extensions().await?.clone_value() + } else { + let mut ext = Vec::new(); + if opt.enable_typescript && opt.enable_react { + ext.push(".tsx".into()); + } + if opt.enable_typescript { + ext.push(".ts".into()); + } + if opt.enable_react { + ext.push(".jsx".into()); + } + ext.push(".js".into()); + if opt.enable_mjs_extension { + ext.push(".mjs".into()); + } + if opt.enable_node_native_modules { + ext.push(".node".into()); + } + ext.push(".json".into()); + ext + }; + Ok(ResolveOptions { + extensions, + modules:if let Some(environment) = emulating { + if *environment.resolve_node_modules().await? { + vec![ResolveModules::Nested(root, vec!["node_modules".into()])] + } else { + Vec::new() + } + } else { + let mut mods = Vec::new(); + if let Some(dir) = opt.enable_node_modules { + mods.push(ResolveModules::Nested(dir, vec!["node_modules".into()])); + } + mods + }, + into_package:{ + let mut resolve_into = vec![ResolveIntoPackage::ExportsField { + conditions:conditions.clone(), + unspecified_conditions:ConditionValue::Unset, + }]; + if opt.browser { + resolve_into.push(ResolveIntoPackage::MainField { field:"browser".into() }); + } + if opt.module { + resolve_into.push(ResolveIntoPackage::MainField { field:"module".into() }); + } + resolve_into.push(ResolveIntoPackage::MainField { field:"main".into() }); + resolve_into + }, + in_package:{ + let mut resolve_in = vec![ResolveInPackage::ImportsField { + conditions, + unspecified_conditions:ConditionValue::Unset, + }]; + if opt.browser { + resolve_in.push(ResolveInPackage::AliasField("browser".into())); + } + resolve_in + }, + default_files:vec!["index".into()], + import_map:Some(import_map), + resolved_map:opt.resolved_map, + plugins, + before_resolve_plugins:opt.before_resolve_plugins.clone(), + ..Default::default() + } + .into()) +} + +#[turbo_tasks::function] +pub async fn resolve_options( + resolve_path:Vc, + options_context:Vc, +) -> Result> { + let options_context_value = options_context.await?; + if !options_context_value.rules.is_empty() { + let context_value = &*resolve_path.await?; + for (condition, new_options_context) in options_context_value.rules.iter() { + if condition.matches(context_value).await? { + return Ok(resolve_options(resolve_path, *new_options_context)); + } + } + } + + let resolve_options = base_resolve_options(resolve_path, options_context); + + let resolve_options = if options_context_value.enable_typescript { + let tsconfig = find_context_file(resolve_path, tsconfig()).await?; + match *tsconfig { + FindContextFileResult::Found(path, _) => { + apply_tsconfig_resolve_options(resolve_options, tsconfig_resolve_options(path)) + }, + FindContextFileResult::NotFound(_) => resolve_options, + } + } else { + resolve_options + }; + + // Make sure to always apply `options_context.import_map` last, so it properly + // overwrites any other mappings. + let resolve_options = options_context_value + .import_map + .map(|import_map| resolve_options.with_extended_import_map(import_map)) + .unwrap_or(resolve_options); + // And the same for the fallback_import_map + let resolve_options = options_context_value + .fallback_import_map + .map(|fallback_import_map| { + resolve_options.with_extended_fallback_import_map(fallback_import_map) + }) + .unwrap_or(resolve_options); + + Ok(resolve_options) +} diff --git a/crates/turbopack-resolve/Source/resolve_options_context.rs b/crates/turbopack-resolve/Source/resolve_options_context.rs new file mode 100644 index 0000000000000..4c914746508a3 --- /dev/null +++ b/crates/turbopack-resolve/Source/resolve_options_context.rs @@ -0,0 +1,130 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, ValueDefault, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + condition::ContextCondition, + environment::Environment, + resolve::{ + options::{ImportMap, ResolvedMap}, + plugin::{AfterResolvePlugin, BeforeResolvePlugin}, + }, +}; + +#[turbo_tasks::value(shared)] +#[derive(Default, Clone)] +pub struct ResolveOptionsContext { + #[serde(default)] + pub emulate_environment:Option>, + #[serde(default)] + pub enable_types:bool, + #[serde(default)] + pub enable_typescript:bool, + #[serde(default)] + pub enable_react:bool, + #[serde(default)] + pub enable_node_native_modules:bool, + #[serde(default)] + // Enable resolving of .mjs files without the .mjs extension + pub enable_mjs_extension: bool, + #[serde(default)] + /// Enable resolving of the node_modules folder when within the provided + /// directory + pub enable_node_modules:Option>, + #[serde(default)] + /// Mark well-known Node.js modules as external imports and load them using + /// native `require`. e.g. url, querystring, os + pub enable_node_externals:bool, + /// Mark well-known Edge modules as external imports and load them using + /// native `require`. e.g. buffer, events, assert + pub enable_edge_node_externals:bool, + #[serde(default)] + /// Enables the "browser" field and export condition in package.json + pub browser:bool, + #[serde(default)] + /// Enables the "module" field and export condition in package.json + pub module:bool, + #[serde(default)] + pub custom_conditions:Vec, + #[serde(default)] + pub custom_extensions:Option>, + #[serde(default)] + /// An additional import map to use when resolving modules. + /// + /// If set, this import map will be applied to `ResolveOption::import_map`. + /// It is always applied last, so any mapping defined within will take + /// precedence over any other (e.g. tsconfig.json `compilerOptions.paths`). + pub import_map:Option>, + #[serde(default)] + /// An import map to fall back to when a request could not be resolved. + /// + /// If set, this import map will be applied to + /// `ResolveOption::fallback_import_map`. It is always applied last, so + /// any mapping defined within will take precedence over any other. + pub fallback_import_map:Option>, + #[serde(default)] + /// An additional resolved map to use after modules have been resolved. + pub resolved_map:Option>, + #[serde(default)] + /// A list of rules to use a different resolve option context for certain + /// context paths. The first matching is used. + pub rules:Vec<(ContextCondition, Vc)>, + #[serde(default)] + /// Plugins which get applied before and after resolving. + pub after_resolve_plugins:Vec>>, + pub before_resolve_plugins:Vec>>, + #[serde(default)] + pub placeholder_for_future_extensions:(), +} + +#[turbo_tasks::value_impl] +impl ResolveOptionsContext { + #[turbo_tasks::function] + pub async fn with_types_enabled(self: Vc) -> Result> { + let mut clone = self.await?.clone_value(); + clone.enable_types = true; + clone.enable_typescript = true; + Ok(Self::cell(clone)) + } + + /// Returns a new [Vc] with its import map extended + /// to include the given import map. + #[turbo_tasks::function] + pub async fn with_extended_import_map( + self: Vc, + import_map:Vc, + ) -> Result> { + let mut resolve_options_context = self.await?.clone_value(); + resolve_options_context.import_map = Some( + resolve_options_context + .import_map + .map(|current_import_map| current_import_map.extend(import_map)) + .unwrap_or(import_map), + ); + Ok(resolve_options_context.into()) + } + + /// Returns a new [Vc] with its fallback import map + /// extended to include the given import map. + #[turbo_tasks::function] + pub async fn with_extended_fallback_import_map( + self: Vc, + fallback_import_map:Vc, + ) -> Result> { + let mut resolve_options_context = self.await?.clone_value(); + resolve_options_context.fallback_import_map = Some( + resolve_options_context + .fallback_import_map + .map(|current_fallback_import_map| { + current_fallback_import_map.extend(fallback_import_map) + }) + .unwrap_or(fallback_import_map), + ); + Ok(resolve_options_context.into()) + } +} + +#[turbo_tasks::value_impl] +impl ValueDefault for ResolveOptionsContext { + #[turbo_tasks::function] + fn value_default() -> Vc { Self::cell(Default::default()) } +} diff --git a/crates/turbopack-resolve/Source/typescript.rs b/crates/turbopack-resolve/Source/typescript.rs new file mode 100644 index 0000000000000..084c8b0dbe109 --- /dev/null +++ b/crates/turbopack-resolve/Source/typescript.rs @@ -0,0 +1,482 @@ +use std::{collections::HashMap, fmt::Write, mem::take}; + +use anyhow::Result; +use serde_json::Value as JsonValue; +use turbo_tasks::{RcStr, Value, ValueDefault, Vc}; +use turbo_tasks_fs::{FileContent, FileJsonContent, FileSystemPath}; +use turbopack_core::{ + asset::Asset, + context::AssetContext, + file_source::FileSource, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + reference_type::{ReferenceType, TypeScriptReferenceSubType}, + resolve::{ + AliasPattern, + ModuleResolveResult, + handle_resolve_error, + node::node_cjs_resolve_options, + options::{ + ConditionValue, + ImportMap, + ImportMapping, + ResolveIntoPackage, + ResolveModules, + ResolveOptions, + }, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + pattern::Pattern, + resolve, + }, + source::{OptionSource, Source}, +}; + +use crate::ecmascript::get_condition_maps; + +#[turbo_tasks::value(shared)] +pub struct TsConfigIssue { + pub severity:Vc, + pub source_ident:Vc, + pub message:RcStr, +} + +#[turbo_tasks::function] +async fn json_only(resolve_options:Vc) -> Result> { + let mut opts = resolve_options.await?.clone_value(); + opts.extensions = vec![".json".into()]; + Ok(opts.cell()) +} + +type TsConfigs = Vec<(Vc, Vc>)>; + +#[tracing::instrument(skip_all)] +pub async fn read_tsconfigs( + mut data:Vc, + mut tsconfig:Vc>, + resolve_options:Vc, +) -> Result { + let mut configs = Vec::new(); + let resolve_options = json_only(resolve_options); + loop { + let parsed_data = data.parse_json_with_comments(); + match &*parsed_data.await? { + FileJsonContent::Unparseable(e) => { + let mut message = "tsconfig is not parseable: invalid JSON: ".to_string(); + if let FileContent::Content(content) = &*data.await? { + let text = content.content().to_str()?; + e.write_with_content(&mut message, text.as_ref())?; + } else { + write!(message, "{}", e)?; + } + TsConfigIssue { + severity:IssueSeverity::Error.into(), + source_ident:tsconfig.ident(), + message:message.into(), + } + .cell() + .emit(); + }, + FileJsonContent::NotFound => { + TsConfigIssue { + severity:IssueSeverity::Error.into(), + source_ident:tsconfig.ident(), + message:"tsconfig not found".into(), + } + .cell() + .emit(); + }, + FileJsonContent::Content(json) => { + configs.push((parsed_data, tsconfig)); + if let Some(extends) = json["extends"].as_str() { + let resolved = resolve_extends(tsconfig, extends, resolve_options).await?; + if let Some(source) = *resolved.await? { + data = source.content().file_content(); + tsconfig = source; + continue; + } else { + TsConfigIssue { + severity:IssueSeverity::Error.into(), + source_ident:tsconfig.ident(), + message:format!("extends: \"{}\" doesn't resolve correctly", extends) + .into(), + } + .cell() + .emit(); + } + } + }, + } + break; + } + Ok(configs) +} + +/// Resolves tsconfig files according to TS's implementation: +/// https://github.com/microsoft/TypeScript/blob/611a912d/src/compiler/commandLineParser.ts#L3294-L3326 +#[tracing::instrument(skip_all)] +async fn resolve_extends( + tsconfig:Vc>, + extends:&str, + resolve_options:Vc, +) -> Result> { + let parent_dir = tsconfig.ident().path().parent(); + let request = Request::parse_string(extends.into()); + + // TS's resolution is weird, and has special behavior for different import + // types. There might be multiple alternatives like + // "some/path/node_modules/xyz/abc.json" and "some/node_modules/xyz/abc.json". + // We only want to use the first one. + match &*request.await? { + // TS has special behavior for "rooted" paths (absolute paths): + // https://github.com/microsoft/TypeScript/blob/611a912d/src/compiler/commandLineParser.ts#L3303-L3313 + Request::Windows { path: Pattern::Constant(path), .. } | + // Server relative is treated as absolute + Request::ServerRelative { path: Pattern::Constant(path), .. } => { + resolve_extends_rooted_or_relative(parent_dir, request, resolve_options, path).await + } + + // TS has special behavior for (explicitly) './' and '../', but not '.' nor '..': + // https://github.com/microsoft/TypeScript/blob/611a912d/src/compiler/commandLineParser.ts#L3303-L3313 + Request::Relative { + path: Pattern::Constant(path), + .. + } if path.starts_with("./") || path.starts_with("../") => { + resolve_extends_rooted_or_relative(parent_dir, request, resolve_options, path).await + } + + // An empty extends is treated as "./tsconfig" + Request::Empty => { + let request = Request::parse_string("./tsconfig".into()); + Ok(resolve(parent_dir, + Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), request, resolve_options).first_source()) + } + + // All other types are treated as module imports, and potentially joined with + // "tsconfig.json". This includes "relative" imports like '.' and '..'. + _ => { + let mut result = resolve(parent_dir, Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), request, resolve_options).first_source(); + if result.await?.is_none() { + let request = Request::parse_string(format!("{extends}/tsconfig").into()); + result = resolve(parent_dir, Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), request, resolve_options).first_source(); + } + Ok(result) + } + } +} + +async fn resolve_extends_rooted_or_relative( + lookup_path:Vc, + request:Vc, + resolve_options:Vc, + path:&str, +) -> Result> { + let mut result = resolve( + lookup_path, + Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), + request, + resolve_options, + ) + .first_source(); + + // If the file doesn't end with ".json" and we can't find the file, then we have + // to try again with it. + // https://github.com/microsoft/TypeScript/blob/611a912d/src/compiler/commandLineParser.ts#L3305 + if !path.ends_with(".json") && result.await?.is_none() { + let request = Request::parse_string(format!("{path}.json").into()); + result = resolve( + lookup_path, + Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), + request, + resolve_options, + ) + .first_source(); + } + Ok(result) +} + +type Config = (Vc, Vc>); + +pub async fn read_from_tsconfigs( + configs:&[Config], + accessor:impl Fn(&JsonValue, Vc>) -> Option, +) -> Result> { + for (config, source) in configs.iter() { + if let FileJsonContent::Content(json) = &*config.await? { + if let Some(result) = accessor(json, *source) { + return Ok(Some(result)); + } + } + } + Ok(None) +} + +/// Resolve options specific to tsconfig.json. +#[turbo_tasks::value] +#[derive(Default)] +pub struct TsConfigResolveOptions { + base_url:Option>, + import_map:Option>, +} + +#[turbo_tasks::value_impl] +impl ValueDefault for TsConfigResolveOptions { + #[turbo_tasks::function] + fn value_default() -> Vc { Self::default().cell() } +} + +/// Returns the resolve options +#[turbo_tasks::function] +pub async fn tsconfig_resolve_options( + tsconfig:Vc, +) -> Result> { + let configs = read_tsconfigs( + tsconfig.read(), + Vc::upcast(FileSource::new(tsconfig)), + node_cjs_resolve_options(tsconfig.root()), + ) + .await?; + + if configs.is_empty() { + return Ok(Default::default()); + } + + let base_url = if let Some(base_url) = read_from_tsconfigs(&configs, |json, source| { + json["compilerOptions"]["baseUrl"] + .as_str() + .map(|base_url| source.ident().path().parent().try_join(base_url.into())) + }) + .await? + { + *base_url.await? + } else { + None + }; + + let mut all_paths = HashMap::new(); + for (content, source) in configs.iter().rev() { + if let FileJsonContent::Content(json) = &*content.await? { + if let JsonValue::Object(paths) = &json["compilerOptions"]["paths"] { + let mut context_dir = source.ident().path().parent(); + if let Some(base_url) = json["compilerOptions"]["baseUrl"].as_str() { + if let Some(new_context) = *context_dir.try_join(base_url.into()).await? { + context_dir = new_context; + } + }; + for (key, value) in paths.iter() { + if let JsonValue::Array(vec) = value { + let entries = vec + .iter() + .filter_map(|entry| { + let entry = entry.as_str(); + + if entry.map(|e| e.ends_with(".d.ts")).unwrap_or_default() { + return None; + } + + entry.map(|s| { + // tsconfig paths are always relative requests + if s.starts_with("./") || s.starts_with("../") { + s.into() + } else { + format!("./{s}").into() + } + }) + }) + .collect(); + all_paths.insert( + key.to_string(), + ImportMapping::primary_alternatives(entries, Some(context_dir)), + ); + } else { + TsConfigIssue { + severity:IssueSeverity::Warning.cell(), + source_ident:source.ident(), + message:format!( + "compilerOptions.paths[{key}] doesn't contains an array as \ + expected\n{key}: {value:#}", + key = serde_json::to_string(key)?, + value = value + ) + .into(), + } + .cell() + .emit() + } + } + } + } + } + + let import_map = if !all_paths.is_empty() { + let mut import_map = ImportMap::empty(); + for (key, value) in all_paths { + import_map.insert_alias(AliasPattern::parse(key), value.into()); + } + Some(import_map.cell()) + } else { + None + }; + + Ok(TsConfigResolveOptions { base_url, import_map }.cell()) +} + +#[turbo_tasks::function] +pub fn tsconfig() -> Vc> { + Vc::cell(vec!["tsconfig.json".into(), "jsconfig.json".into()]) +} + +#[turbo_tasks::function] +pub async fn apply_tsconfig_resolve_options( + resolve_options:Vc, + tsconfig_resolve_options:Vc, +) -> Result> { + let tsconfig_resolve_options = tsconfig_resolve_options.await?; + let mut resolve_options = resolve_options.await?.clone_value(); + if let Some(base_url) = tsconfig_resolve_options.base_url { + // We want to resolve in `compilerOptions.baseUrl` first, then in other + // locations as a fallback. + resolve_options.modules.insert(0, ResolveModules::Path(base_url)); + } + if let Some(tsconfig_import_map) = tsconfig_resolve_options.import_map { + resolve_options.import_map = Some( + resolve_options + .import_map + .map(|import_map| import_map.extend(tsconfig_import_map)) + .unwrap_or(tsconfig_import_map), + ); + } + Ok(resolve_options.cell()) +} + +#[turbo_tasks::function] +pub async fn type_resolve( + origin:Vc>, + request:Vc, +) -> Result> { + let ty = Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)); + let context_path = origin.origin_path().parent(); + let options = origin.resolve_options(ty.clone()); + let options = apply_typescript_types_options(options); + let types_request = + if let Request::Module { module: m, path: p, query: _, fragment: _ } = &*request.await? { + let m = if let Some(stripped) = m.strip_prefix('@') { + stripped.replace('/', "__").into() + } else { + m.clone() + }; + Some(Request::module( + format!("@types/{m}").into(), + Value::new(p.clone()), + Vc::::default(), + Vc::::default(), + )) + } else { + None + }; + let context_path = context_path.resolve().await?; + let result = if let Some(types_request) = types_request { + let result1 = resolve( + context_path, + Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), + request, + options, + ); + if !*result1.is_unresolveable().await? { + result1 + } else { + resolve( + context_path, + Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), + types_request, + options, + ) + } + } else { + resolve( + context_path, + Value::new(ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)), + request, + options, + ) + }; + let result = + as_typings_result(origin.asset_context().process_resolve_result(result, ty.clone())); + handle_resolve_error( + result, + ty, + origin.origin_path(), + request, + options, + IssueSeverity::Error.cell(), + None, + ) + .await +} + +#[turbo_tasks::function] +pub async fn as_typings_result(result:Vc) -> Result> { + let mut result = result.await?.clone_value(); + result.primary = take(&mut result.primary) + .into_iter() + .map(|(mut k, v)| { + k.conditions.insert("types".to_string(), true); + (k, v) + }) + .collect(); + Ok(result.cell()) +} + +#[turbo_tasks::function] +async fn apply_typescript_types_options( + resolve_options:Vc, +) -> Result> { + let mut resolve_options = resolve_options.await?.clone_value(); + resolve_options.extensions = vec![".tsx".into(), ".ts".into(), ".d.ts".into()]; + resolve_options.into_package = resolve_options + .into_package + .drain(..) + .filter_map(|into| { + if let ResolveIntoPackage::ExportsField { mut conditions, unspecified_conditions } = + into + { + conditions.insert("types".into(), ConditionValue::Set); + Some(ResolveIntoPackage::ExportsField { conditions, unspecified_conditions }) + } else { + None + } + }) + .collect(); + resolve_options + .into_package + .push(ResolveIntoPackage::MainField { field:"types".into() }); + for conditions in get_condition_maps(&mut resolve_options) { + conditions.insert("types".into(), ConditionValue::Set); + } + Ok(resolve_options.into()) +} + +#[turbo_tasks::value_impl] +impl Issue for TsConfigIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { self.severity } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { + Ok( + StyledString::Text("An issue occurred while parsing a tsconfig.json file.".into()) + .cell(), + ) + } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.source_ident.path() } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some(StyledString::Text(self.message.clone()).cell())) + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Analysis.cell() } +} diff --git a/crates/turbopack-resolve/build.rs b/crates/turbopack-resolve/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-resolve/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-static/Source/fixed.rs b/crates/turbopack-static/Source/fixed.rs new file mode 100644 index 0000000000000..d1abe50ac649a --- /dev/null +++ b/crates/turbopack-static/Source/fixed.rs @@ -0,0 +1,37 @@ +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + asset::{Asset, AssetContent}, + ident::AssetIdent, + output::OutputAsset, + source::Source, +}; + +/// A static asset that is served at a fixed output path. It won't use +/// content hashing to generate a long term cacheable URL. +#[turbo_tasks::value] +pub struct FixedStaticAsset { + output_path:Vc, + source:Vc>, +} + +#[turbo_tasks::value_impl] +impl FixedStaticAsset { + #[turbo_tasks::function] + pub fn new(output_path:Vc, source:Vc>) -> Vc { + FixedStaticAsset { output_path, source }.cell() + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for FixedStaticAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { Ok(AssetIdent::from_path(self.output_path)) } +} + +#[turbo_tasks::value_impl] +impl Asset for FixedStaticAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} diff --git a/crates/turbopack-static/Source/lib.rs b/crates/turbopack-static/Source/lib.rs new file mode 100644 index 0000000000000..30a1e39d0b2a6 --- /dev/null +++ b/crates/turbopack-static/Source/lib.rs @@ -0,0 +1,175 @@ +//! Static asset support for turbopack. +//! +//! Static assets are copied directly to the output folder. +//! +//! When imported from ES modules, they produce a thin module that simply +//! exports the asset's path. +//! +//! When referred to from CSS assets, the reference is replaced with the asset's +//! path. + +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +pub mod fixed; +pub mod output_asset; + +use anyhow::Result; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext}, + context::AssetContext, + ident::AssetIdent, + module::Module, + output::OutputAsset, + reference::{ModuleReferences, SingleOutputAssetReference}, + source::Source, +}; +use turbopack_css::embed::CssEmbed; +use turbopack_ecmascript::{ + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + utils::StringifyJs, +}; + +use self::output_asset::StaticAsset; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("static".into()) } + +#[turbo_tasks::value] +#[derive(Clone)] +pub struct StaticModuleAsset { + pub source:Vc>, + pub asset_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl StaticModuleAsset { + #[turbo_tasks::function] + pub fn new(source:Vc>, asset_context:Vc>) -> Vc { + Self::cell(StaticModuleAsset { source, asset_context }) + } + + #[turbo_tasks::function] + async fn static_asset( + self: Vc, + chunking_context:Vc>, + ) -> Result> { + Ok(StaticAsset::new(chunking_context, self.await?.source)) + } +} + +#[turbo_tasks::value_impl] +impl Module for StaticModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + self.source + .ident() + .with_modifier(modifier()) + .with_layer(self.asset_context.layer()) + } +} + +#[turbo_tasks::value_impl] +impl Asset for StaticModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for StaticModuleAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(ModuleChunkItem::cell(ModuleChunkItem { + module:self, + chunking_context, + static_asset:self.static_asset(Vc::upcast(chunking_context)), + }))) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for StaticModuleAsset { + #[turbo_tasks::function] + fn get_exports(&self) -> Vc { EcmascriptExports::Value.into() } +} + +#[turbo_tasks::value] +struct ModuleChunkItem { + module:Vc, + chunking_context:Vc>, + static_asset:Vc, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + Ok(Vc::cell(vec![Vc::upcast(SingleOutputAssetReference::new( + Vc::upcast(self.static_asset), + Vc::cell( + format!("static(url) {}", self.static_asset.ident().to_string().await?).into(), + ), + ))])) + } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(&self) -> Result> { + Ok(EcmascriptChunkItemContent { + inner_code:format!( + "__turbopack_export_value__({path});", + path = + StringifyJs(&self.chunking_context.asset_url(self.static_asset.ident()).await?) + ) + .into(), + ..Default::default() + } + .into()) + } +} + +#[turbo_tasks::value_impl] +impl CssEmbed for ModuleChunkItem { + #[turbo_tasks::function] + fn embedded_asset(&self) -> Vc> { Vc::upcast(self.static_asset) } +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-static/Source/output_asset.rs b/crates/turbopack-static/Source/output_asset.rs new file mode 100644 index 0000000000000..c18b5f64a08f4 --- /dev/null +++ b/crates/turbopack-static/Source/output_asset.rs @@ -0,0 +1,53 @@ +use anyhow::{Result, anyhow}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileContent; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::ChunkingContext, + ident::AssetIdent, + output::OutputAsset, + source::Source, +}; +#[turbo_tasks::value] +pub struct StaticAsset { + chunking_context:Vc>, + source:Vc>, +} + +#[turbo_tasks::value_impl] +impl StaticAsset { + #[turbo_tasks::function] + pub fn new( + chunking_context:Vc>, + source:Vc>, + ) -> Vc { + Self::cell(StaticAsset { chunking_context, source }) + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for StaticAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let content = self.source.content(); + let content_hash = if let AssetContent::File(file) = &*content.await? { + if let FileContent::Content(file) = &*file.await? { + turbo_tasks_hash::hash_xxh3_hash64(file.content()) + } else { + return Err(anyhow!("StaticAsset::path: not found")); + } + } else { + return Err(anyhow!("StaticAsset::path: unsupported file content")); + }; + let content_hash_b16 = turbo_tasks_hash::encode_hex(content_hash); + let asset_path = + self.chunking_context.asset_path(content_hash_b16.into(), self.source.ident()); + Ok(AssetIdent::from_path(asset_path)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for StaticAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} diff --git a/crates/turbopack-static/build.rs b/crates/turbopack-static/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-static/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-swc-ast-explorer/Source/main.rs b/crates/turbopack-swc-ast-explorer/Source/main.rs new file mode 100644 index 0000000000000..10cbdd7203730 --- /dev/null +++ b/crates/turbopack-swc-ast-explorer/Source/main.rs @@ -0,0 +1,68 @@ +use std::{io::stdin, sync::Arc}; + +use anyhow::Result; +use clap::Parser; +use owo_colors::OwoColorize; +use regex::{NoExpand, Regex}; +use swc_core::{ + base::{Compiler, HandlerOpts, config::IsModule, try_with_handler}, + common::{GLOBALS, Globals, SourceMap, errors::ColorConfig, source_map::FileName}, + ecma::{ + ast::EsVersion, + parser::{Syntax, TsConfig}, + }, +}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Whether to keep Span (location) markers + #[clap(long, value_parser, default_value_t = false)] + spans:bool, +} + +fn main() -> Result<()> { + let args = Args::parse(); + + let mut contents = String::new(); + stdin().read_line(&mut contents)?; + + let sm = Arc::new(SourceMap::default()); + let file = sm.new_source_file(FileName::Anon, contents); + let target = EsVersion::latest(); + let syntax = Syntax::Typescript(TsConfig { + tsx:true, + decorators:false, + dts:false, + no_early_errors:true, + disallow_ambiguous_jsx_like:false, + }); + + let compiler = Compiler::new(sm.clone()); + let res = GLOBALS.set(&Globals::new(), || { + try_with_handler( + sm, + HandlerOpts { color:ColorConfig::Always, skip_filename:false }, + |handler| compiler.parse_js(file, handler, target, syntax, IsModule::Unknown, None), + ) + }); + + let print = format!("{:#?}", res?); + + let stripped = if args.spans { + print + } else { + let span = Regex::new(r"(?m)^\s+\w+: Span \{[^}]*\},\n").unwrap(); + span.replace_all(&print, NoExpand("")).to_string() + }; + + let alernate_ws = Regex::new(r" {8}").unwrap(); + let alternating = alernate_ws.replace_all( + &stripped, + NoExpand(&format!("{}{}", " ".on_default_color(), " ".on_black())), + ); + let ws = Regex::new(r" {4}").unwrap(); + println!("{}", ws.replace_all(&alternating, NoExpand(" "))); + + Ok(()) +} diff --git a/crates/turbopack-swc-utils/Source/emitter.rs b/crates/turbopack-swc-utils/Source/emitter.rs new file mode 100644 index 0000000000000..7eaf87278ab22 --- /dev/null +++ b/crates/turbopack-swc-utils/Source/emitter.rs @@ -0,0 +1,77 @@ +use std::sync::Arc; + +use swc_core::common::{ + SourceMap, + errors::{DiagnosticBuilder, DiagnosticId, Emitter, Level}, + source_map::Pos, +}; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::{ + issue::{IssueExt, IssueSeverity, IssueSource, StyledString, analyze::AnalyzeIssue}, + source::Source, +}; + +#[derive(Clone)] +pub struct IssueEmitter { + pub source:Vc>, + pub source_map:Arc, + pub title:Option, + pub emitted_issues:Vec>, +} + +impl IssueEmitter { + pub fn new(source:Vc>, source_map:Arc, title:Option) -> Self { + Self { source, source_map, title, emitted_issues:vec![] } + } +} + +impl Emitter for IssueEmitter { + fn emit(&mut self, db:&DiagnosticBuilder<'_>) { + let level = db.level; + let mut message = db.message.iter().map(|s| s.0.as_ref()).collect::>().join(""); + let code = db.code.as_ref().map(|d| { + match d { + DiagnosticId::Error(s) => format!("error {s}").into(), + DiagnosticId::Lint(s) => format!("lint {s}").into(), + } + }); + + let title; + if let Some(t) = self.title.as_ref() { + title = t.clone(); + } else { + let mut message_split = message.split('\n'); + title = message_split.next().unwrap().to_string().into(); + message = message_split.remainder().unwrap_or("").to_string(); + } + + let source = db.span.primary_span().map(|span| { + IssueSource::from_swc_offsets(self.source, span.lo.to_usize(), span.hi.to_usize()) + }); + // TODO add other primary and secondary spans with labels as sub_issues + + let issue = AnalyzeIssue { + severity:match level { + Level::Bug => IssueSeverity::Bug, + Level::Fatal | Level::PhaseFatal => IssueSeverity::Fatal, + Level::Error => IssueSeverity::Error, + Level::Warning => IssueSeverity::Warning, + Level::Note => IssueSeverity::Note, + Level::Help => IssueSeverity::Hint, + Level::Cancelled => IssueSeverity::Error, + Level::FailureNote => IssueSeverity::Note, + } + .cell(), + source_ident:self.source.ident(), + title:Vc::cell(title), + message:StyledString::Text(message.into()).cell(), + code, + source, + } + .cell(); + + self.emitted_issues.push(issue); + + issue.emit(); + } +} diff --git a/crates/turbopack-swc-utils/Source/lib.rs b/crates/turbopack-swc-utils/Source/lib.rs new file mode 100644 index 0000000000000..3f961f3b4c4cc --- /dev/null +++ b/crates/turbopack-swc-utils/Source/lib.rs @@ -0,0 +1,4 @@ +#![feature(min_specialization)] +#![feature(str_split_remainder)] + +pub mod emitter; diff --git a/crates/turbopack-swc-utils/build.rs b/crates/turbopack-swc-utils/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-swc-utils/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-test-utils/Source/jest.rs b/crates/turbopack-test-utils/Source/jest.rs new file mode 100644 index 0000000000000..51a93d7b9924d --- /dev/null +++ b/crates/turbopack-test-utils/Source/jest.rs @@ -0,0 +1,19 @@ +use serde::{Deserialize, Serialize}; + +// Defines common structures returned by jest/jest-circus. Shared across turbo +// and next.js repos. + +/// The serialized form of the JS object returned from jest.run() +/// describing results. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct JestRunResult { + pub test_results:Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct JestTestResult { + pub test_path:Vec, + pub errors:Vec, +} diff --git a/crates/turbopack-test-utils/Source/lib.rs b/crates/turbopack-test-utils/Source/lib.rs new file mode 100644 index 0000000000000..050f83fa2bbb0 --- /dev/null +++ b/crates/turbopack-test-utils/Source/lib.rs @@ -0,0 +1,5 @@ +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +pub mod jest; +pub mod snapshot; diff --git a/crates/turbopack-test-utils/Source/snapshot.rs b/crates/turbopack-test-utils/Source/snapshot.rs new file mode 100644 index 0000000000000..6c37f66baf044 --- /dev/null +++ b/crates/turbopack-test-utils/Source/snapshot.rs @@ -0,0 +1,235 @@ +use std::{ + collections::{HashMap, HashSet}, + env, + fs, + path::PathBuf, +}; + +use anyhow::{Context, Result, anyhow, bail}; +use once_cell::sync::Lazy; +use regex::Regex; +use similar::TextDiff; +use turbo_tasks::{RcStr, ReadRef, TryJoinIterExt, ValueToString, Vc}; +use turbo_tasks_fs::{ + DirectoryContent, + DirectoryEntry, + DiskFileSystem, + File, + FileContent, + FileSystemEntryType, + FileSystemPath, +}; +use turbo_tasks_hash::encode_hex; +use turbopack_cli_utils::issue::{LogOptions, format_issue}; +use turbopack_core::{ + asset::AssetContent, + issue::{IssueSeverity, PlainIssue, StyledString}, +}; + +// Updates the existing snapshot outputs with the actual outputs of this run. +// e.g. `UPDATE=1 cargo test -p turbopack-tests -- test_my_pattern` +static UPDATE:Lazy = Lazy::new(|| env::var("UPDATE").unwrap_or_default() == "1"); + +static ANSI_REGEX:Lazy = Lazy::new(|| Regex::new(r"\x1b\[\d+m").unwrap()); + +pub async fn snapshot_issues>>( + captured_issues:I, + issues_path:Vc, + workspace_root:&str, +) -> Result<()> { + let expected_issues = expected(issues_path).await?; + let mut seen = HashSet::new(); + for plain_issue in captured_issues.into_iter() { + let title = styled_string_to_file_safe_string(&plain_issue.title) + .replace('/', "__") + // We replace "*", "?", and '"' because they're not allowed in filenames on Windows. + .replace('*', "__star__") + .replace('"', "__quo__") + .replace('?', "__q__") + .replace(':', "__c__"); + let title = if title.len() > 50 { &title[0..50] } else { &title }; + let hash = encode_hex(plain_issue.internal_hash_ref(true)); + + let path = issues_path.join(format!("{title}-{}.txt", &hash[0..6]).into()); + if !seen.insert(path) { + continue; + } + + let formatted = format_issue( + &plain_issue, + None, + &LogOptions { + current_dir:PathBuf::new(), + project_dir:PathBuf::new(), + show_all:true, + log_detail:true, + log_level:IssueSeverity::Info, + }, + ); + + // Annoyingly, the PlainIssue.source -> PlainIssueSource.asset -> + // PlainSource.path -> FileSystemPath.fs -> DiskFileSystem.root changes + // for everyone. + let content:RcStr = formatted + .as_str() + .replace(workspace_root, "WORKSPACE_ROOT") + .replace(&*ANSI_REGEX, "") + // Normalize syspaths from Windows. These appear in stack traces. + .replace("\\\\", "/") + .into(); + + let asset = AssetContent::file(File::from(content).into()); + + diff(path, asset).await?; + } + + matches_expected(expected_issues, seen).await +} + +pub async fn expected(dir:Vc) -> Result>> { + let mut expected = HashSet::new(); + let entries = dir.read_dir().await?; + if let DirectoryContent::Entries(entries) = &*entries { + for (file, entry) in entries { + match entry { + DirectoryEntry::File(file) => { + expected.insert(*file); + }, + _ => { + bail!("expected file at {}, found {:?}", file, FileSystemEntryType::from(entry)) + }, + } + } + } + Ok(expected) +} + +pub async fn matches_expected( + expected:HashSet>, + seen:HashSet>, +) -> Result<()> { + for path in diff_paths(&expected, &seen).await? { + let p = &path.await?.path; + if *UPDATE { + remove_file(path).await?; + println!("removed file {}", p); + } else { + bail!("expected file {}, but it was not emitted", p); + } + } + Ok(()) +} + +pub async fn diff(path:Vc, actual:Vc) -> Result<()> { + let path_str = &path.await?.path; + let expected = AssetContent::file(path.read()); + + let actual = get_contents(actual, path).await?; + let expected = get_contents(expected, path).await?; + + if actual != expected { + if let Some(actual) = actual { + if *UPDATE { + let content = File::from(RcStr::from(actual)).into(); + path.write(content).await?; + println!("updated contents of {}", path_str); + } else { + if expected.is_none() { + eprintln!("new file {path_str} detected:"); + } else { + eprintln!("contents of {path_str} did not match:"); + } + let expected = expected.unwrap_or_default(); + let diff = TextDiff::from_lines(&expected, &actual); + eprintln!("{}", diff.unified_diff().context_radius(3).header("expected", "actual")); + bail!("contents of {path_str} did not match"); + } + } else { + bail!("{path_str} was not generated"); + } + } + + Ok(()) +} + +async fn get_contents(file:Vc, path:Vc) -> Result> { + Ok( + match &*file + .await + .context(format!("Unable to read AssetContent of {}", path.to_string().await?))? + { + AssetContent::File(file) => { + match &*file + .await + .context(format!("Unable to read FileContent of {}", path.to_string().await?))? + { + FileContent::NotFound => None, + FileContent::Content(expected) => { + Some(expected.content().to_str()?.trim().to_string()) + }, + } + }, + AssetContent::Redirect { target, link_type } => { + Some(format!("Redirect {{ target: {target}, link_type: {:?} }}", link_type)) + }, + }, + ) +} + +async fn remove_file(path:Vc) -> Result<()> { + let fs = Vc::try_resolve_downcast_type::(path.fs()) + .await? + .context(anyhow!("unexpected fs type"))? + .await?; + let sys_path = fs.to_sys_path(path).await?; + fs::remove_file(&sys_path).context(format!("remove file {} error", sys_path.display()))?; + Ok(()) +} + +/// Values in left that are not in right. +/// Vc hashes as a Vc, not as the file path, so we need to get +/// the path to properly diff. +async fn diff_paths( + left:&HashSet>, + right:&HashSet>, +) -> Result>> { + let mut map = left + .iter() + .map(|p| async move { Ok((p.await?.path.clone(), *p)) }) + .try_join() + .await? + .iter() + .cloned() + .collect::>(); + for p in right { + map.remove(&p.await?.path); + } + Ok(map.values().copied().collect()) +} + +fn styled_string_to_file_safe_string(styled_string:&StyledString) -> String { + match styled_string { + StyledString::Line(parts) => { + let mut string = String::new(); + string += "__l_"; + for part in parts { + string.push_str(&styled_string_to_file_safe_string(part)); + } + string += "__"; + string + }, + StyledString::Stack(parts) => { + let mut string = String::new(); + string += "__s_"; + for part in parts { + string.push_str(&styled_string_to_file_safe_string(part)); + string.push('_'); + } + string += "__"; + string + }, + StyledString::Text(string) => string.to_string(), + StyledString::Code(string) => format!("__c_{}__", string), + StyledString::Strong(string) => format!("__{}__", string), + } +} diff --git a/crates/turbopack-test-utils/build.rs b/crates/turbopack-test-utils/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-test-utils/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack-tests/.gitignore b/crates/turbopack-tests/.gitignore new file mode 100644 index 0000000000000..7932e8715ab95 --- /dev/null +++ b/crates/turbopack-tests/.gitignore @@ -0,0 +1,4 @@ +tests/execution/**/*/output/ +tests/snapshot/**/output/ +!tests/execution/**/*/node_modules +!tests/snapshot/**/*/node_modules diff --git a/crates/turbopack-tests/build.rs b/crates/turbopack-tests/build.rs new file mode 100644 index 0000000000000..47874e4d0a3d3 --- /dev/null +++ b/crates/turbopack-tests/build.rs @@ -0,0 +1,9 @@ +use turbo_tasks_build::{generate_register, rerun_if_glob}; + +fn main() { + generate_register(); + // The test/snapshot crate need to be rebuilt if any snapshots are added. + rerun_if_glob("tests/execution/*/*/*", "tests/execution"); + rerun_if_glob("tests/execution/*/*/__skipped__/*", "tests/execution"); + rerun_if_glob("tests/snapshot/*/*", "tests/snapshot"); +} diff --git a/crates/turbopack-tests/index.d.ts b/crates/turbopack-tests/index.d.ts new file mode 100644 index 0000000000000..28760b9c833ec --- /dev/null +++ b/crates/turbopack-tests/index.d.ts @@ -0,0 +1,12 @@ +import * as expectMod from "./tests/execution/node_modules/expect"; +import * as jest from "./tests/execution/node_modules/jest-circus"; + +export {}; + +declare global { + var describe: typeof jest.describe; + var expect: typeof expectMod.expect; + var it: typeof jest.it; + var test: typeof jest.test; + var nsObj: (obj: Object) => Object; +} diff --git a/crates/turbopack-tests/js/jest-entry.ts b/crates/turbopack-tests/js/jest-entry.ts new file mode 100644 index 0000000000000..6a31422b25a79 --- /dev/null +++ b/crates/turbopack-tests/js/jest-entry.ts @@ -0,0 +1,47 @@ +/// + +const jest = __turbopack_external_require__("jest-circus"); +const expectMod = __turbopack_external_require__("expect"); + +function setupGlobals() { + globalThis.describe = jest.describe; + globalThis.it = jest.it; + globalThis.test = jest.test; + globalThis.expect = expectMod.expect; + + // From https://github.com/webpack/webpack/blob/9fcaa243573005d6fdece9a3f8d89a0e8b399613/test/TestCases.template.js#L422 + globalThis.nsObj = function nsObj(obj) { + Object.defineProperty(obj, Symbol.toStringTag, { + value: "Module", + }); + return obj; + }; +} + +const uncaughtExceptions: string[] = []; +const unhandledRejections: string[] = []; + +process.on("uncaughtException", (e) => { + uncaughtExceptions.push(String(e)); +}); + +process.on("unhandledRejection", (e) => { + unhandledRejections.push(String(e)); +}); + +export default async function run() { + setupGlobals(); + + await import("TESTS"); + + const jestResult = await jest.run(); + + // Wait a full tick for unhandledRejection handlers to run -- a microtask is not sufficient. + await new Promise((resolve) => setTimeout(resolve, 0)); + + return { + jestResult, + uncaughtExceptions, + unhandledRejections, + }; +} diff --git a/crates/turbopack-tests/js/types.d.ts b/crates/turbopack-tests/js/types.d.ts new file mode 100644 index 0000000000000..46f543b0c5054 --- /dev/null +++ b/crates/turbopack-tests/js/types.d.ts @@ -0,0 +1,3 @@ +declare const __turbopack_external_require__: (id: string) => any; + +declare module "TESTS"; diff --git a/crates/turbopack-trace-server/Source/bottom_up.rs b/crates/turbopack-trace-server/Source/bottom_up.rs new file mode 100644 index 0000000000000..f79830fd9cc07 --- /dev/null +++ b/crates/turbopack-trace-server/Source/bottom_up.rs @@ -0,0 +1,78 @@ +use std::{collections::HashMap, env, sync::Arc}; + +use crate::{ + span::{SpanBottomUp, SpanIndex}, + span_ref::SpanRef, +}; + +pub struct SpanBottomUpBuilder { + // These values won't change after creation: + pub self_spans:Vec, + pub children:HashMap, + pub example_span:SpanIndex, +} + +impl SpanBottomUpBuilder { + pub fn new(example_span:SpanIndex) -> Self { + Self { self_spans:vec![], children:HashMap::new(), example_span } + } + + pub fn build(self) -> SpanBottomUp { + SpanBottomUp::new( + self.self_spans, + self.example_span, + self.children.into_values().map(|child| Arc::new(child.build())).collect(), + ) + } +} + +pub fn build_bottom_up_graph<'a>( + spans:impl Iterator>, +) -> Vec> { + let max_depth = env::var("BOTTOM_UP_DEPTH") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(usize::MAX); + let mut roots = HashMap::new(); + + // unfortunately there is a rustc bug that fails the typechecking here + // when using Either. This error appears + // in certain cases when building next-swc. + // + // see here: https://github.com/rust-lang/rust/issues/124891 + let mut current_iterators:Vec>>> = + vec![Box::new(spans.flat_map(|span| span.children()))]; + + let mut current_path:Vec<(&'_ str, SpanIndex)> = vec![]; + while let Some(mut iter) = current_iterators.pop() { + if let Some(child) = iter.next() { + current_iterators.push(iter); + + let name = child.group_name(); + let (_, mut bottom_up) = roots + .raw_entry_mut() + .from_key(name) + .or_insert_with(|| (name.to_string(), SpanBottomUpBuilder::new(child.index()))); + bottom_up.self_spans.push(child.index()); + let mut prev = None; + for &(name, example_span) in current_path.iter().rev().take(max_depth) { + if prev == Some(name) { + continue; + } + let (_, child_bottom_up) = + bottom_up.children.raw_entry_mut().from_key(name).or_insert_with(|| { + (name.to_string(), SpanBottomUpBuilder::new(example_span)) + }); + child_bottom_up.self_spans.push(child.index()); + bottom_up = child_bottom_up; + prev = Some(name); + } + + current_path.push((child.group_name(), child.index())); + current_iterators.push(Box::new(child.children())); + } else { + current_path.pop(); + } + } + roots.into_values().map(|b| Arc::new(b.build())).collect() +} diff --git a/crates/turbopack-trace-server/Source/lib.rs b/crates/turbopack-trace-server/Source/lib.rs new file mode 100644 index 0000000000000..688a9b539c7e2 --- /dev/null +++ b/crates/turbopack-trace-server/Source/lib.rs @@ -0,0 +1,30 @@ +#![feature(iter_intersperse)] +#![feature(hash_raw_entry)] +#![feature(box_patterns)] + +use std::{path::PathBuf, sync::Arc}; + +use self::{reader::TraceReader, server::serve, store_container::StoreContainer}; + +mod bottom_up; +mod reader; +mod self_time_tree; +mod server; +mod span; +mod span_bottom_up_ref; +mod span_graph_ref; +mod span_ref; +mod store; +mod store_container; +mod u64_empty_string; +mod u64_string; +mod viewer; + +pub fn start_turbopack_trace_server(path:PathBuf) { + let store = Arc::new(StoreContainer::new()); + let reader = TraceReader::spawn(store.clone(), path); + + serve(store); + + reader.join().unwrap(); +} diff --git a/crates/turbopack-trace-server/Source/main.rs b/crates/turbopack-trace-server/Source/main.rs new file mode 100644 index 0000000000000..0f26709a195f1 --- /dev/null +++ b/crates/turbopack-trace-server/Source/main.rs @@ -0,0 +1,34 @@ +#![feature(iter_intersperse)] +#![feature(hash_raw_entry)] +#![feature(box_patterns)] + +use std::{collections::HashSet, sync::Arc}; + +use self::{reader::TraceReader, server::serve, store_container::StoreContainer}; + +mod bottom_up; +mod reader; +mod self_time_tree; +mod server; +mod span; +mod span_bottom_up_ref; +mod span_graph_ref; +mod span_ref; +mod store; +mod store_container; +mod u64_empty_string; +mod u64_string; +mod viewer; + +fn main() { + let args:HashSet = std::env::args().skip(1).collect(); + + let arg = args.iter().next().expect("missing argument: trace file path"); + + let store = Arc::new(StoreContainer::new()); + let reader = TraceReader::spawn(store.clone(), arg.into()); + + serve(store); + + reader.join().unwrap(); +} diff --git a/crates/turbopack-trace-server/Source/reader/heaptrack.rs b/crates/turbopack-trace-server/Source/reader/heaptrack.rs new file mode 100644 index 0000000000000..30b339355f23c --- /dev/null +++ b/crates/turbopack-trace-server/Source/reader/heaptrack.rs @@ -0,0 +1,478 @@ +use std::{ + collections::{HashMap, HashSet}, + env, + str::from_utf8, + sync::Arc, +}; + +use anyhow::{Context, Result, bail}; +use indexmap::{IndexMap, indexmap, map::Entry}; +use rustc_demangle::demangle; + +use super::TraceFormat; +use crate::{span::SpanIndex, store_container::StoreContainer}; + +#[derive(Debug, Clone, Copy)] +struct TraceNode { + ip_index:usize, + parent_index:usize, +} + +impl TraceNode { + pub fn read(s:&mut &[u8]) -> Result { + Ok(Self { ip_index:read_hex_index(s)?, parent_index:read_hex_index(s)? }) + } +} + +#[derive(Debug, Hash, PartialEq, Eq)] +struct InstructionPointer { + module_index:usize, + frames:Vec, + custom_name:Option, +} + +impl InstructionPointer { + pub fn read(s:&mut &[u8]) -> Result { + let _ip = read_hex(s)?; + Ok(Self { + module_index:read_hex_index(s)?, + frames:read_all(s, Frame::read)?, + custom_name:None, + }) + } +} + +#[derive(Debug, Hash, PartialEq, Eq)] +struct Frame { + function_index:usize, + file_index:usize, + line:u64, +} + +impl Frame { + pub fn read(s:&mut &[u8]) -> Result { + Ok(Self { + function_index:read_hex_index(s)?, + file_index:read_hex_index(s)?, + line:read_hex(s)?, + }) + } +} + +#[derive(Debug)] +struct AllocationInfo { + size:u64, + trace_index:usize, +} + +impl AllocationInfo { + pub fn read(s:&mut &[u8]) -> Result { + Ok(Self { size:read_hex(s)?, trace_index:read_hex_index(s)? }) + } +} + +struct InstructionPointerExtraInfo { + first_trace_of_ip:Option, +} + +#[derive(Clone, Copy)] +struct TraceData { + span_index:SpanIndex, + ip_index:usize, + parent_trace_index:usize, +} + +pub struct HeaptrackFormat { + store:Arc, + version:u32, + last_timestamp:u64, + strings:Vec, + traces:Vec, + ip_parent_map:HashMap<(usize, SpanIndex), usize>, + trace_instruction_pointers:Vec, + instruction_pointers:IndexMap, + allocations:Vec, + spans:usize, + collapse_crates:HashSet, + expand_crates:HashSet, + expand_recursion:bool, + allocated_memory:u64, + temp_allocated_memory:u64, +} + +const RECURSION_IP:usize = 1; + +impl HeaptrackFormat { + pub fn new(store:Arc) -> Self { + Self { + store, + version:0, + last_timestamp:0, + strings:vec!["".to_string()], + traces:vec![TraceData { + span_index:SpanIndex::new(usize::MAX).unwrap(), + ip_index:0, + parent_trace_index:0, + }], + ip_parent_map:HashMap::new(), + instruction_pointers:indexmap! { + InstructionPointer { + module_index: 0, + frames: Vec::new(), + custom_name: Some("root".to_string()) + } => InstructionPointerExtraInfo { + first_trace_of_ip: None, + }, + InstructionPointer { + module_index: 0, + frames: Vec::new(), + custom_name: Some("recursion".to_string()) + } => InstructionPointerExtraInfo { + first_trace_of_ip: None, + } + }, + trace_instruction_pointers:vec![0], + allocations:vec![], + spans:0, + collapse_crates:env::var("COLLAPSE_CRATES") + .unwrap_or_default() + .split(',') + .map(|s| s.to_string()) + .collect(), + expand_crates:env::var("EXPAND_CRATES") + .unwrap_or_default() + .split(',') + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect(), + expand_recursion:env::var("EXPAND_RECURSION").is_ok(), + allocated_memory:0, + temp_allocated_memory:0, + } + } +} + +impl TraceFormat for HeaptrackFormat { + fn stats(&self) -> String { + format!( + "{} spans, {} strings, {} ips, {} traces, {} allocations, {:.2} GB allocated, {:.2} \ + GB temporarily allocated", + self.spans, + self.strings.len() - 1, + self.trace_instruction_pointers.len() - 1, + self.traces.len() - 1, + self.allocations.len() - 1, + (self.allocated_memory / 1024 / 1024) as f32 / 1024.0, + (self.temp_allocated_memory / 1024 / 1024) as f32 / 1024.0, + ) + } + + fn read(&mut self, mut buffer:&[u8]) -> anyhow::Result { + let mut bytes_read = 0; + let mut outdated_spans = HashSet::new(); + let mut store = self.store.write(); + 'outer: loop { + let Some(line_end) = buffer.iter().position(|b| *b == b'\n') else { + break; + }; + let full_line = &buffer[..line_end]; + buffer = &buffer[line_end + 1..]; + bytes_read += full_line.len() + 1; + + if full_line.is_empty() { + continue; + } + let ty = full_line[0]; + let mut line = &full_line[2..]; + + // For format see https://github.com/KDE/heaptrack/blob/b000a73e0bf0a275ec41eef0fe34701a0942cdd8/src/analyze/accumulatedtracedata.cpp#L151 + match ty { + b'v' => { + let _ = read_hex(&mut line)?; + self.version = read_hex(&mut line)? as u32; + if self.version != 2 && self.version != 3 { + bail!("Unsupported version: {} (expected 2 or 3)", self.version); + } + }, + b's' => { + let string = if self.version == 2 { + String::from_utf8(line.to_vec())? + } else { + read_sized_string(&mut line)? + }; + self.strings.push(demangle(&string).to_string()); + }, + b't' => { + let TraceNode { ip_index, parent_index } = TraceNode::read(&mut line)?; + let ip_index = + *self.trace_instruction_pointers.get(ip_index).context("ip not found")?; + let (ip, ip_info) = + self.instruction_pointers.get_index(ip_index).context("ip not found")?; + // Try to fix cut-off traces + if parent_index == 0 { + if let Some(trace_index) = ip_info.first_trace_of_ip { + let trace = self.traces.get(trace_index).context("trace not found")?; + self.traces.push(*trace); + continue; + } + } + // Lookup parent + let parent = if parent_index > 0 { + let parent = *self.traces.get(parent_index).context("parent not found")?; + // Check if we have an duplicate (can only happen due to cut-off traces) + if let Some(trace_index) = + self.ip_parent_map.get(&(ip_index, parent.span_index)) + { + let trace = self.traces.get(*trace_index).context("trace not found")?; + self.traces.push(*trace); + continue; + } + // Check if we repeat parent frame + if parent.ip_index == ip_index { + self.traces.push(parent); + continue; + } + if !self.expand_recursion { + // Check for recursion + let mut current = parent.parent_trace_index; + while current > 0 { + let current_parent = + self.traces.get(current).context("parent not found")?; + current = current_parent.parent_trace_index; + if current_parent.ip_index == ip_index { + if parent.ip_index == RECURSION_IP { + // Parent is recursion node, do nothing + self.traces.push(parent); + } else if let Some(trace_index) = + self.ip_parent_map.get(&(RECURSION_IP, parent.span_index)) + { + // There is already one recursion node, reuse it + let trace = self + .traces + .get(*trace_index) + .context("trace not found")?; + self.traces.push(*trace); + } else { + // create a new recursion node + let span_index = store.add_span( + Some(parent.span_index), + self.last_timestamp, + "".to_string(), + "recursion".to_string(), + Vec::new(), + &mut outdated_spans, + ); + store.complete_span(span_index); + let index = self.traces.len(); + self.traces.push(TraceData { + ip_index:RECURSION_IP, + parent_trace_index:parent_index, + span_index, + }); + self.ip_parent_map + .insert((RECURSION_IP, parent.span_index), index); + } + continue 'outer; + } + } + } + Some(parent.span_index) + } else { + None + }; + let InstructionPointer { module_index, frames, custom_name } = ip; + let module = self.strings.get(*module_index).context("module not found")?; + let name = if let Some(name) = custom_name.as_ref() { + name.to_string() + } else if let Some(first_frame) = frames.first() { + let file = + self.strings.get(first_frame.file_index).context("file not found")?; + let function = self + .strings + .get(first_frame.function_index) + .context("function not found")?; + format!("{} @ {file}:{}", function, first_frame.line) + } else { + "unknown".to_string() + }; + let mut args = Vec::new(); + for Frame { function_index, file_index, line } in frames.iter() { + let file = self.strings.get(*file_index).context("file not found")?; + let function = + self.strings.get(*function_index).context("function not found")?; + args.push(( + "location".to_string(), + format!("{} @ {file}:{line}", function), + )); + } + + let span_index = store.add_span( + parent, + self.last_timestamp, + module.to_string(), + name, + args, + &mut outdated_spans, + ); + store.complete_span(span_index); + self.spans += 1; + let index = self.traces.len(); + self.traces.push(TraceData { + span_index, + ip_index, + parent_trace_index:parent_index, + }); + self.instruction_pointers + .get_index_mut(ip_index) + .unwrap() + .1 + .first_trace_of_ip + .get_or_insert(index); + if let Some(parent) = parent { + self.ip_parent_map.insert((ip_index, parent), index); + } + }, + b'i' => { + let mut ip = InstructionPointer::read(&mut line)?; + if let Some(frame) = ip.frames.first() { + if let Some(function) = self.strings.get(frame.function_index) { + let crate_name = function + .strip_prefix('<') + .unwrap_or(function) + .split("::") + .next() + .unwrap() + .split('[') + .next() + .unwrap(); + if self.collapse_crates.contains(crate_name) + || !self.expand_crates.is_empty() + && !self.expand_crates.contains(crate_name) + { + ip.frames.clear(); + ip.custom_name = Some(crate_name.to_string()); + } + } + } + match self.instruction_pointers.entry(ip) { + Entry::Occupied(e) => { + self.trace_instruction_pointers.push(e.index()); + }, + Entry::Vacant(e) => { + self.trace_instruction_pointers.push(e.index()); + e.insert(InstructionPointerExtraInfo { first_trace_of_ip:None }); + }, + } + }, + b'#' => { + // comment + }, + b'X' => { + let line = from_utf8(line)?; + println!("Debuggee: {line}"); + }, + b'c' => { + // timestamp + let timestamp = read_hex(&mut line)?; + self.last_timestamp = timestamp; + }, + b'a' => { + // allocation info + let info = AllocationInfo::read(&mut line)?; + self.allocations.push(info); + }, + b'+' => { + // allocation + let index = read_hex_index(&mut line)?; + let AllocationInfo { size, trace_index } = + self.allocations.get(index).context("allocation not found")?; + if *trace_index > 0 { + let TraceData { span_index, .. } = + self.traces.get(*trace_index).context("trace not found")?; + store.add_allocation(*span_index, *size, 1, &mut outdated_spans); + self.allocated_memory += *size; + } + }, + b'-' => { + // deallocation + let index = read_hex_index(&mut line)?; + let AllocationInfo { size, trace_index } = + self.allocations.get(index).context("allocation not found")?; + if *trace_index > 0 { + let TraceData { span_index, .. } = + self.traces.get(*trace_index).context("trace not found")?; + store.add_deallocation(*span_index, *size, 1, &mut outdated_spans); + self.allocated_memory -= *size; + self.temp_allocated_memory += *size; + } + }, + b'R' => { + // RSS timestamp + }, + b'A' => { + // attached + // ignore + }, + b'S' => { + // embedded suppression + // ignore + }, + b'I' => { + // System info + // ignore + }, + _ => { + let line = from_utf8(line)?; + println!("{} {line}", ty as char) + }, + } + } + store.invalidate_outdated_spans(&outdated_spans); + Ok(bytes_read) + } +} + +fn read_hex_index(s:&mut &[u8]) -> anyhow::Result { Ok(read_hex(s)? as usize) } + +fn read_hex(s:&mut &[u8]) -> anyhow::Result { + let mut n:u64 = 0; + loop { + if let Some(c) = s.first() { + match c { + b'0'..=b'9' => { + n *= 16; + n += (*c - b'0') as u64; + }, + b'a'..=b'f' => { + n *= 16; + n += (*c - b'a' + 10) as u64; + }, + b' ' => { + *s = &s[1..]; + return Ok(n); + }, + _ => { + bail!("Expected hex char"); + }, + } + *s = &s[1..]; + } else { + return Ok(n); + } + } +} + +fn read_sized_string(s:&mut &[u8]) -> anyhow::Result { + let size = read_hex(s)? as usize; + let str = &s[..size]; + *s = &s[size..]; + Ok(String::from_utf8(str.to_vec())?) +} + +fn read_all(s:&mut &[u8], f:impl Fn(&mut &[u8]) -> anyhow::Result) -> anyhow::Result> { + let mut res = Vec::new(); + while !s.is_empty() { + res.push(f(s)?); + } + Ok(res) +} diff --git a/crates/turbopack-trace-server/Source/reader/mod.rs b/crates/turbopack-trace-server/Source/reader/mod.rs new file mode 100644 index 0000000000000..68cedb0fd0ab8 --- /dev/null +++ b/crates/turbopack-trace-server/Source/reader/mod.rs @@ -0,0 +1,283 @@ +mod heaptrack; +mod nextjs; +mod turbopack; + +use std::{ + env, + fs::File, + io::{self, BufReader, Read, Seek, SeekFrom}, + path::PathBuf, + sync::Arc, + thread::{self, JoinHandle}, + time::Duration, +}; + +use anyhow::Result; +use flate2::bufread::GzDecoder; + +use crate::{ + reader::{heaptrack::HeaptrackFormat, nextjs::NextJsFormat, turbopack::TurbopackFormat}, + store_container::StoreContainer, +}; + +const MIN_INITIAL_REPORT_SIZE:u64 = 100 * 1024 * 1024; + +trait TraceFormat { + fn read(&mut self, buffer:&[u8]) -> Result; + fn stats(&self) -> String { String::new() } +} + +#[derive(Default)] +enum TraceFile { + Raw(File), + Zstd(zstd::Decoder<'static, BufReader>), + Gz(GzDecoder>), + #[default] + Unloaded, +} + +impl TraceFile { + fn read(&mut self, buffer:&mut [u8]) -> io::Result { + match self { + Self::Raw(file) => file.read(buffer), + Self::Zstd(decoder) => decoder.read(buffer), + Self::Gz(decoder) => decoder.read(buffer), + Self::Unloaded => unreachable!(), + } + } + + fn stream_position(&mut self) -> io::Result { + match self { + Self::Raw(file) => file.stream_position(), + Self::Zstd(decoder) => decoder.get_mut().stream_position(), + Self::Gz(decoder) => decoder.get_mut().stream_position(), + Self::Unloaded => unreachable!(), + } + } + + fn seek(&mut self, pos:SeekFrom) -> io::Result { + match self { + Self::Raw(file) => file.seek(pos), + Self::Zstd(decoder) => decoder.get_mut().seek(pos), + Self::Gz(decoder) => decoder.get_mut().seek(pos), + Self::Unloaded => unreachable!(), + } + } +} + +pub struct TraceReader { + store:Arc, + path:PathBuf, +} + +impl TraceReader { + pub fn spawn(store:Arc, path:PathBuf) -> JoinHandle<()> { + let mut reader = Self { store, path }; + std::thread::spawn(move || reader.run()) + } + + pub fn run(&mut self) { + loop { + self.try_read(); + thread::sleep(Duration::from_millis(500)); + } + } + + fn trace_file_from_file(&self, file:File) -> io::Result { + let path = &self.path.to_string_lossy(); + Ok(if path.ends_with(".zst") { + TraceFile::Zstd(zstd::Decoder::new(file)?) + } else if path.ends_with(".gz") { + TraceFile::Gz(GzDecoder::new(BufReader::new(file))) + } else { + TraceFile::Raw(file) + }) + } + + fn try_read(&mut self) -> bool { + let Ok(mut file) = File::open(&self.path) else { + return false; + }; + println!("Trace file opened"); + let stop_at = env::var("STOP_AT") + .unwrap_or_default() + .parse() + .map_or(u64::MAX, |v:u64| v * 1024 * 1024); + if stop_at != u64::MAX { + println!("Will stop reading file at {} MB", stop_at / 1024 / 1024) + } + + { + let mut store = self.store.write(); + store.reset(); + } + + let mut format:Option> = None; + + let mut current_read = 0; + let mut initial_read = { file.seek(SeekFrom::End(0)).ok() }; + if file.seek(SeekFrom::Start(0)).is_err() { + return false; + } + let mut file = match self.trace_file_from_file(file) { + Ok(f) => f, + Err(err) => { + println!("Error creating zstd decoder: {err}"); + return false; + }, + }; + + let mut buffer = Vec::new(); + let mut index = 0; + + let mut chunk = vec![0; 64 * 1024 * 1024]; + loop { + match file.read(&mut chunk) { + Ok(bytes_read) => { + if bytes_read == 0 { + if let Some(value) = + self.wait_for_more_data(&mut file, &mut initial_read, format.as_deref()) + { + return value; + } + } else { + // If we have partially consumed some data, and we are at buffer capacity, + // remove the consumed data to make more space. + if index > 0 && buffer.len() + bytes_read > buffer.capacity() { + buffer.splice(..index, std::iter::empty()); + index = 0; + } + buffer.extend_from_slice(&chunk[..bytes_read]); + if format.is_none() && buffer.len() >= 8 { + if buffer.starts_with(b"TRACEv0") { + index = 7; + format = Some(Box::new(TurbopackFormat::new(self.store.clone()))); + } else if buffer.starts_with(b"[{\"name\"") { + format = Some(Box::new(NextJsFormat::new(self.store.clone()))); + } else if buffer.starts_with(b"v ") { + format = Some(Box::new(HeaptrackFormat::new(self.store.clone()))) + } else { + // Fallback to the format without magic bytes + // TODO Remove this after a while and show an error instead + format = Some(Box::new(TurbopackFormat::new(self.store.clone()))); + } + } + if let Some(format) = &mut format { + match format.read(&buffer[index..]) { + Ok(bytes_read) => { + index += bytes_read; + }, + Err(err) => { + println!("Trace file error: {err}"); + return true; + }, + } + if self.store.want_to_read() { + thread::yield_now(); + } + let prev_read = current_read; + current_read += bytes_read as u64; + if let Some(total) = &mut initial_read { + let old_mbs = prev_read / (97 * 1024 * 1024); + let new_mbs = current_read / (97 * 1024 * 1024); + if old_mbs != new_mbs { + let pos = file.stream_position().unwrap_or(current_read); + *total = (*total).max(pos); + let percentage = pos * 100 / *total; + let read = pos / (1024 * 1024); + let uncompressed = current_read / (1024 * 1024); + let total = *total / (1024 * 1024); + let stats = format.stats(); + print!("{}% read ({}/{} MB)", percentage, read, total); + if uncompressed != read { + print!(" ({} MB uncompressed)", uncompressed); + } + if stats.is_empty() { + println!(); + } else { + println!(" - {}", stats); + } + } + } + if current_read >= stop_at { + println!( + "Stopped reading file as requested by STOP_AT env var. \ + Waiting for new file..." + ); + self.wait_for_new_file(&mut file); + return true; + } + } + } + }, + Err(err) => { + if err.kind() == io::ErrorKind::UnexpectedEof { + if let Some(value) = + self.wait_for_more_data(&mut file, &mut initial_read, format.as_deref()) + { + return value; + } + } else { + // Error reading file, maybe it was removed + println!("Error reading trace file: {err:?}"); + return true; + } + }, + } + } + } + + fn wait_for_more_data( + &mut self, + file:&mut TraceFile, + initial_read:&mut Option, + format:Option<&dyn TraceFormat>, + ) -> Option { + let Ok(pos) = file.stream_position() else { + return Some(true); + }; + if let Some(total) = initial_read.take() { + if let Some(format) = format { + let stats = format.stats(); + println!("{}", stats); + } + if total > MIN_INITIAL_REPORT_SIZE { + println!("Initial read completed ({} MB)", total / (1024 * 1024)); + } + } + thread::sleep(Duration::from_millis(100)); + let Ok(end) = file.seek(SeekFrom::End(0)) else { + return Some(true); + }; + // No more data to read, sleep for a while to wait for more data + if end < pos { + // new file + return Some(true); + } else if end != pos { + // Seek to the same position. This will fail when the file was + // truncated. + let Ok(new_pos) = file.seek(SeekFrom::Start(pos)) else { + return Some(true); + }; + if new_pos != pos { + return Some(true); + } + } + None + } + + fn wait_for_new_file(&self, file:&mut TraceFile) { + let Ok(pos) = file.stream_position() else { + return; + }; + loop { + thread::sleep(Duration::from_millis(1000)); + let Ok(end) = file.seek(SeekFrom::End(0)) else { + return; + }; + if end < pos { + return; + } + } + } +} diff --git a/crates/turbopack-trace-server/Source/reader/nextjs.rs b/crates/turbopack-trace-server/Source/reader/nextjs.rs new file mode 100644 index 0000000000000..1cf8907824e9e --- /dev/null +++ b/crates/turbopack-trace-server/Source/reader/nextjs.rs @@ -0,0 +1,136 @@ +use std::{ + borrow::Cow, + collections::{HashMap, HashSet}, + fmt::Display, + sync::Arc, +}; + +use indexmap::IndexMap; +use serde::Deserialize; + +use super::TraceFormat; +use crate::{span::SpanIndex, store_container::StoreContainer}; + +pub struct NextJsFormat { + store:Arc, + id_mapping:HashMap, + queued_children:HashMap>, +} + +impl NextJsFormat { + pub fn new(store:Arc) -> Self { + Self { store, id_mapping:HashMap::new(), queued_children:HashMap::new() } + } +} + +impl TraceFormat for NextJsFormat { + fn read(&mut self, mut buffer:&[u8]) -> anyhow::Result { + let mut bytes_read = 0; + let mut outdated_spans = HashSet::new(); + loop { + let Some(line_end) = buffer.iter().position(|b| *b == b'\n') else { + break; + }; + let line = &buffer[..line_end]; + buffer = &buffer[line_end + 1..]; + bytes_read += line.len() + 1; + + let spans:Vec = serde_json::from_slice(line)?; + + let mut store = self.store.write(); + + for span in spans { + let NextJsSpan { + name, + duration, + timestamp, + id, + parent_id, + tags, + start_time: _, + trace_id: _, + } = span; + let (parent, queue_parent) = if let Some(parent) = parent_id { + if let Some(parent) = self.id_mapping.get(&parent) { + (Some(*parent), None) + } else { + (None, Some(parent)) + } + } else { + (None, None) + }; + let index = store.add_span( + parent, + timestamp, + "nextjs".to_string(), + name.into_owned(), + tags.iter() + .map(|(k, v)| { + (k.to_string(), v.as_ref().map(|v| v.to_string()).unwrap_or_default()) + }) + .collect(), + &mut outdated_spans, + ); + self.id_mapping.insert(id, index); + if let Some(parent) = queue_parent { + self.queued_children.entry(parent).or_default().push(index); + } + if let Some(children) = self.queued_children.remove(&id) { + for child in children { + store.set_parent(child, index, &mut outdated_spans); + } + } + store.set_total_time(index, timestamp, duration, &mut outdated_spans); + store.complete_span(index); + } + store.invalidate_outdated_spans(&outdated_spans); + drop(store); + } + Ok(bytes_read) + } +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] + +enum TagValue<'a> { + String(Cow<'a, str>), + Number(f64), + Bool(bool), + Array(Vec>), +} + +impl<'a> Display for TagValue<'a> { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TagValue::String(s) => write!(f, "{}", s), + TagValue::Number(n) => write!(f, "{}", n), + TagValue::Bool(b) => write!(f, "{}", b), + TagValue::Array(a) => { + write!(f, "[")?; + for (i, v) in a.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{}", v)?; + } + write!(f, "]") + }, + } + } +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct NextJsSpan<'a> { + name:Cow<'a, str>, + duration:u64, + timestamp:u64, + id:u64, + parent_id:Option, + tags:IndexMap, Option>>, + #[allow(dead_code)] + start_time:u64, + #[allow(dead_code)] + trace_id:Cow<'a, str>, +} diff --git a/crates/turbopack-trace-server/Source/reader/turbopack.rs b/crates/turbopack-trace-server/Source/reader/turbopack.rs new file mode 100644 index 0000000000000..c8452b1e808dd --- /dev/null +++ b/crates/turbopack-trace-server/Source/reader/turbopack.rs @@ -0,0 +1,297 @@ +use std::{ + collections::{HashMap, HashSet, hash_map::Entry}, + sync::Arc, +}; + +use anyhow::Result; +use indexmap::IndexMap; +use turbopack_trace_utils::tracing::TraceRow; + +use super::TraceFormat; +use crate::{ + span::SpanIndex, + store_container::{StoreContainer, StoreWriteGuard}, +}; + +#[derive(Default)] +struct AllocationInfo { + allocations:u64, + deallocations:u64, + allocation_count:u64, + deallocation_count:u64, +} + +pub struct TurbopackFormat { + store:Arc, + active_ids:HashMap, + queued_rows:HashMap>>, + outdated_spans:HashSet, + thread_stacks:HashMap>, + thread_allocation_counters:HashMap, + self_time_started:HashMap<(SpanIndex, u64), u64>, +} + +impl TurbopackFormat { + pub fn new(store:Arc) -> Self { + Self { + store, + active_ids:HashMap::new(), + queued_rows:HashMap::new(), + outdated_spans:HashSet::new(), + thread_stacks:HashMap::new(), + thread_allocation_counters:HashMap::new(), + self_time_started:HashMap::new(), + } + } + + fn process(&mut self, store:&mut StoreWriteGuard, row:TraceRow<'_>) { + match row { + TraceRow::Start { ts, id, parent, name, target, values } => { + let parent = if let Some(parent) = parent { + if let Some(parent) = self.active_ids.get(&parent) { + Some(*parent) + } else { + self.queued_rows.entry(parent).or_default().push(TraceRow::Start { + ts, + id, + parent:Some(parent), + name:name.into_owned().into(), + target:target.into_owned().into(), + values:values + .into_iter() + .map(|(k, v)| (k.into_owned().into(), v.into_static())) + .collect(), + }); + return; + } + } else { + None + }; + let span_id = store.add_span( + parent, + ts, + target.into_owned(), + name.into_owned(), + values.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(), + &mut self.outdated_spans, + ); + self.active_ids.insert(id, span_id); + }, + TraceRow::Record { id, values } => { + let Some(&id) = self.active_ids.get(&id) else { + self.queued_rows.entry(id).or_default().push(TraceRow::Record { + id, + values:values + .into_iter() + .map(|(k, v)| (k.into_owned().into(), v.into_static())) + .collect(), + }); + return; + }; + store.add_args( + id, + values.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(), + &mut self.outdated_spans, + ); + }, + TraceRow::End { ts: _, id } => { + // id might be reused + let index = self.active_ids.remove(&id); + if let Some(index) = index { + store.complete_span(index); + } + }, + TraceRow::Enter { ts, id, thread_id } => { + let Some(&id) = self.active_ids.get(&id) else { + self.queued_rows.entry(id).or_default().push(TraceRow::Enter { + ts, + id, + thread_id, + }); + return; + }; + let stack = self.thread_stacks.entry(thread_id).or_default(); + if let Some(&parent) = stack.last() { + if let Some(parent_start) = self.self_time_started.remove(&(parent, thread_id)) + { + store.add_self_time(parent, parent_start, ts, &mut self.outdated_spans); + } + } + stack.push(id); + self.self_time_started.insert((id, thread_id), ts); + }, + TraceRow::Exit { ts, id, thread_id } => { + let Some(&id) = self.active_ids.get(&id) else { + self.queued_rows.entry(id).or_default().push(TraceRow::Exit { + ts, + id, + thread_id, + }); + return; + }; + let stack = self.thread_stacks.entry(thread_id).or_default(); + if let Some(pos) = stack.iter().rev().position(|&x| x == id) { + let stack_index = stack.len() - pos - 1; + stack.remove(stack_index); + if stack_index > 0 { + let parent = stack[stack_index - 1]; + self.self_time_started.insert((parent, thread_id), ts); + } + } + if let Some(start) = self.self_time_started.remove(&(id, thread_id)) { + store.add_self_time(id, start, ts, &mut self.outdated_spans); + } + }, + TraceRow::Event { ts, parent, values } => { + let parent = if let Some(parent) = parent { + if let Some(parent) = self.active_ids.get(&parent) { + Some(*parent) + } else { + self.queued_rows.entry(parent).or_default().push(TraceRow::Event { + ts, + parent:Some(parent), + values:values + .into_iter() + .map(|(k, v)| (k.into_owned().into(), v.into_static())) + .collect(), + }); + return; + } + } else { + None + }; + let mut values = values.into_iter().collect::>(); + let duration = values.remove("duration").and_then(|v| v.as_u64()).unwrap_or(0); + let name = values + .remove("name") + .and_then(|v| v.as_str().map(|s| s.to_string())) + .unwrap_or("event".into()); + + let id = store.add_span( + parent, + ts.saturating_sub(duration), + "event".into(), + name, + values.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(), + &mut self.outdated_spans, + ); + store.add_self_time(id, ts.saturating_sub(duration), ts, &mut self.outdated_spans); + }, + TraceRow::Allocation { + ts: _, + thread_id, + allocations, + allocation_count, + deallocations, + deallocation_count, + } => { + let stack = self.thread_stacks.entry(thread_id).or_default(); + if let Some(&id) = stack.last() { + if allocations > 0 { + store.add_allocation( + id, + allocations, + allocation_count, + &mut self.outdated_spans, + ); + } + if deallocations > 0 { + store.add_deallocation( + id, + deallocations, + deallocation_count, + &mut self.outdated_spans, + ); + } + } + }, + TraceRow::AllocationCounters { + ts: _, + thread_id, + allocations, + allocation_count, + deallocations, + deallocation_count, + } => { + let info = AllocationInfo { + allocations, + deallocations, + allocation_count, + deallocation_count, + }; + let mut diff = AllocationInfo::default(); + match self.thread_allocation_counters.entry(thread_id) { + Entry::Occupied(mut entry) => { + let counter = entry.get_mut(); + diff.allocations = info.allocations - counter.allocations; + diff.deallocations = info.deallocations - counter.deallocations; + diff.allocation_count = info.allocation_count - counter.allocation_count; + diff.deallocation_count = + info.deallocation_count - counter.deallocation_count; + counter.allocations = info.allocations; + counter.deallocations = info.deallocations; + counter.allocation_count = info.allocation_count; + counter.deallocation_count = info.deallocation_count; + }, + Entry::Vacant(entry) => { + entry.insert(info); + }, + } + let stack = self.thread_stacks.entry(thread_id).or_default(); + if let Some(&id) = stack.last() { + if diff.allocations > 0 { + store.add_allocation( + id, + diff.allocations, + diff.allocation_count, + &mut self.outdated_spans, + ); + } + if diff.deallocations > 0 { + store.add_deallocation( + id, + diff.deallocations, + diff.deallocation_count, + &mut self.outdated_spans, + ); + } + } + }, + } + } +} + +impl TraceFormat for TurbopackFormat { + fn read(&mut self, mut buffer:&[u8]) -> Result { + let mut rows = Vec::new(); + let mut bytes_read = 0; + loop { + match postcard::take_from_bytes(buffer) { + Ok((row, remaining)) => { + bytes_read += buffer.len() - remaining.len(); + buffer = remaining; + rows.push(row); + }, + Err(err) => { + if matches!(err, postcard::Error::DeserializeUnexpectedEnd) { + break; + } + return Err(err.into()); + }, + } + } + if !rows.is_empty() { + let store = self.store.clone(); + let mut iter = rows.into_iter(); + { + let mut store = store.write(); + for row in iter.by_ref() { + self.process(&mut store, row); + } + store.invalidate_outdated_spans(&self.outdated_spans); + self.outdated_spans.clear(); + } + } + Ok(bytes_read) + } +} diff --git a/crates/turbopack-trace-server/Source/self_time_tree.rs b/crates/turbopack-trace-server/Source/self_time_tree.rs new file mode 100644 index 0000000000000..77bb23452f457 --- /dev/null +++ b/crates/turbopack-trace-server/Source/self_time_tree.rs @@ -0,0 +1,229 @@ +use std::{ + cmp::{max, min}, + mem::{replace, take}, +}; + +const SPLIT_COUNT:usize = 128; + +pub struct SelfTimeTree { + entries:Vec>, + children:Option>>, + count:usize, +} + +struct SelfTimeEntry { + start:u64, + end:u64, + item:T, +} + +struct SelfTimeChildren { + /// Entries < split_point + left:SelfTimeTree, + split_point:u64, + /// Entries >= split_point + right:SelfTimeTree, +} + +impl Default for SelfTimeTree { + fn default() -> Self { Self { entries:Vec::new(), children:None, count:0 } } +} + +impl SelfTimeTree { + pub fn new() -> Self { Self::default() } + + pub fn len(&self) -> usize { self.count } + + pub fn insert(&mut self, start:u64, end:u64, item:T) { + self.count += 1; + if let Some(children) = &mut self.children { + if end <= children.split_point { + children.left.insert(start, end, item); + } else if start >= children.split_point { + children.right.insert(start, end, item); + } else { + self.entries.push(SelfTimeEntry { start, end, item }); + } + self.rebalance(); + } else { + self.entries.push(SelfTimeEntry { start, end, item }); + if self.entries.len() >= SPLIT_COUNT { + self.split(); + } + } + } + + fn split(&mut self) { + if self.entries.is_empty() { + return; + } + let entries = take(&mut self.entries); + let start = entries.iter().min_by_key(|e| e.start).unwrap().start; + let end = entries.iter().max_by_key(|e| e.end).unwrap().end; + let middle = (start + end) / 2; + self.children = Some(Box::new(SelfTimeChildren { + left:SelfTimeTree::new(), + split_point:middle, + right:SelfTimeTree::new(), + })); + self.count = 0; + for entry in entries { + self.insert(entry.start, entry.end, entry.item); + } + } + + fn rebalance(&mut self) { + if let Some(box SelfTimeChildren { left, split_point, right }) = &mut self.children { + let SelfTimeTree { count: left_count, children: left_children, entries: left_entries } = + left; + let SelfTimeTree { + count: right_count, + children: right_children, + entries: right_entries, + } = right; + if *left_count > *right_count * 3 + left_entries.len() { + if let Some(box SelfTimeChildren { + left: left_left, + split_point: left_split_point, + right: left_right, + }) = left_children + { + let left_entries = take(left_entries); + *right = Self { + count:left_right.count + right.count + self.entries.len(), + entries:take(&mut self.entries), + children:Some(Box::new(SelfTimeChildren { + left:take(left_right), + split_point:*split_point, + right:take(right), + })), + }; + *split_point = *left_split_point; + *left = take(left_left); + let entries = replace(&mut self.entries, left_entries); + self.count = left.count + right.count + self.entries.len(); + for SelfTimeEntry { start, end, item } in entries { + self.insert(start, end, item); + } + } + } else if *right_count > *left_count * 3 + right_entries.len() { + if let Some(box SelfTimeChildren { + left: right_left, + split_point: right_split_point, + right: right_right, + }) = right_children + { + let right_entries = take(right_entries); + *left = Self { + count:left.count + right_left.count + self.entries.len(), + entries:take(&mut self.entries), + children:Some(Box::new(SelfTimeChildren { + left:take(left), + split_point:*split_point, + right:take(right_left), + })), + }; + *split_point = *right_split_point; + *right = take(right_right); + let entries = replace(&mut self.entries, right_entries); + self.count = left.count + right.count + self.entries.len(); + for SelfTimeEntry { start, end, item } in entries { + self.insert(start, end, item); + } + } + } + } + } + + pub fn lookup_range_count(&self, start:u64, end:u64) -> u64 { + let mut total_count = 0; + for entry in &self.entries { + if entry.start < end && entry.end > start { + let start = max(entry.start, start); + let end = min(entry.end, end); + let span = end - start; + total_count += span; + } + } + if let Some(children) = &self.children { + if start < children.split_point { + total_count += children.left.lookup_range_count(start, end); + } + if end > children.split_point { + total_count += children.right.lookup_range_count(start, end); + } + } + total_count + } + + pub fn for_each_in_range(&self, start:u64, end:u64, mut f:impl FnMut(u64, u64, &T)) { + self.for_each_in_range_ref(start, end, &mut f); + } + + fn for_each_in_range_ref(&self, start:u64, end:u64, f:&mut impl FnMut(u64, u64, &T)) { + for entry in &self.entries { + if entry.start < end && entry.end > start { + f(entry.start, entry.end, &entry.item); + } + } + if let Some(children) = &self.children { + if start < children.split_point { + children.left.for_each_in_range_ref(start, end, f); + } + if end > children.split_point { + children.right.for_each_in_range_ref(start, end, f); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn print_tree(tree:&SelfTimeTree, indent:usize) { + if let Some(children) = &tree.children { + println!( + "{}{} items (split at {}, {} total)", + " ".repeat(indent), + tree.entries.len(), + children.split_point, + tree.count + ); + print_tree(&children.left, indent + 2); + print_tree(&children.right, indent + 2); + } else { + println!("{}{} items ({} total)", " ".repeat(indent), tree.entries.len(), tree.count); + } + } + + #[test] + fn test_simple() { + let mut tree = SelfTimeTree::new(); + for i in 0..1000 { + tree.insert(i, i + 1, i); + } + assert_eq!(tree.lookup_range_count(0, 1000), 1000); + print_tree(&tree, 0); + } + + #[test] + fn test_overlapping() { + let mut tree = SelfTimeTree::new(); + for i in 0..1000 { + tree.insert(i, i + 100, i); + } + assert_eq!(tree.lookup_range_count(0, 1100), 1000 * 100); + print_tree(&tree, 0); + } + + #[test] + fn test_overlapping_heavy() { + let mut tree = SelfTimeTree::new(); + for i in 0..1000 { + tree.insert(i, i + 500, i); + } + assert_eq!(tree.lookup_range_count(0, 2000), 1000 * 500); + print_tree(&tree, 0); + } +} diff --git a/crates/turbopack-trace-server/Source/server.rs b/crates/turbopack-trace-server/Source/server.rs new file mode 100644 index 0000000000000..850e7937a5afc --- /dev/null +++ b/crates/turbopack-trace-server/Source/server.rs @@ -0,0 +1,362 @@ +use std::{ + net::{TcpListener, TcpStream}, + sync::{Arc, Mutex}, + thread::spawn, +}; + +use anyhow::{Result, bail}; +use serde::{Deserialize, Serialize}; +use tungstenite::{Message, accept}; + +use crate::{ + store::SpanId, + store_container::StoreContainer, + u64_string, + viewer::{Update, ViewLineUpdate, ViewMode, Viewer}, +}; + +#[derive(Serialize, Deserialize, Debug)] +#[serde(tag = "type")] +#[serde(rename_all = "kebab-case")] +pub enum ServerToClientMessage { + ViewLine { + #[serde(flatten)] + update:ViewLineUpdate, + }, + ViewLinesCount { + count:usize, + max:u64, + }, + #[serde(rename_all = "camelCase")] + QueryResult { + #[serde(with = "u64_string")] + id:SpanId, + is_graph:bool, + start:u64, + end:u64, + duration:u64, + cpu:u64, + allocations:u64, + deallocations:u64, + allocation_count:u64, + persistent_allocations:u64, + args:Vec<(String, String)>, + path:Vec, + }, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(tag = "type")] +#[serde(rename_all = "kebab-case")] +pub enum ClientToServerMessage { + #[serde(rename_all = "camelCase")] + ViewRect { + view_rect:ViewRect, + }, + ViewMode { + #[serde(with = "u64_string")] + id:SpanId, + mode:String, + inherit:bool, + }, + ResetViewMode { + #[serde(with = "u64_string")] + id:SpanId, + }, + Query { + #[serde(with = "u64_string")] + id:SpanId, + }, + Ack, + CheckForMoreData, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct SpanViewEvent { + pub start:u64, + pub duration:u64, + pub name:String, + pub id:Option, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Filter { + pub op:Op, + pub value:u64, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum Op { + Gt, + Lt, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ViewRect { + pub x:u64, + pub y:u64, + pub width:u64, + pub height:u64, + pub horizontal_pixels:u64, + pub query:String, + pub view_mode:String, + pub value_mode:String, + pub value_filter:Option, + pub count_filter:Option, +} + +struct ConnectionState { + store:Arc, + viewer:Viewer, + view_rect:ViewRect, + last_update_generation:usize, +} + +pub fn serve(store:Arc) { + let server = TcpListener::bind("127.0.0.1:5747").unwrap(); + for stream in server.incoming() { + let store = store.clone(); + + spawn(move || { + let websocket = accept(stream.unwrap()).unwrap(); + if let Err(err) = handle_connection(websocket, store) { + eprintln!("Error: {:?}", err); + } + }); + } +} + +fn handle_connection( + mut websocket:tungstenite::WebSocket, + store:Arc, +) -> Result<()> { + let state = Arc::new(Mutex::new(ConnectionState { + store, + viewer:Viewer::new(), + view_rect:ViewRect { + x:0, + y:0, + width:1, + height:1, + horizontal_pixels:1, + query:String::new(), + view_mode:"aggregated".to_string(), + value_mode:"duration".to_string(), + count_filter:None, + value_filter:None, + }, + last_update_generation:0, + })); + let mut update_skipped = false; + let mut ready_for_update = true; + + fn send_update( + websocket:&mut tungstenite::WebSocket, + state:&mut ConnectionState, + force_send:bool, + ready_for_update:&mut bool, + update_skipped:&mut bool, + ) -> Result<()> { + if !*ready_for_update { + if force_send { + *update_skipped = true; + } + return Ok(()); + } + let store = state.store.read(); + if !force_send && state.last_update_generation == store.generation() { + return Ok(()); + } + state.last_update_generation = store.generation(); + let Update { lines: updates, max } = state.viewer.compute_update(&store, &state.view_rect); + let count = updates.len(); + for update in updates { + let message = ServerToClientMessage::ViewLine { update }; + let message = serde_json::to_string(&message).unwrap(); + websocket.send(Message::Text(message))?; + } + let message = ServerToClientMessage::ViewLinesCount { count, max }; + let message = serde_json::to_string(&message).unwrap(); + websocket.send(Message::Text(message))?; + *ready_for_update = false; + Ok(()) + } + loop { + match websocket.read()? { + Message::Frame(_frame) => {}, + Message::Text(text) => { + let message:ClientToServerMessage = serde_json::from_str(&text)?; + let mut state = state.lock().unwrap(); + match message { + ClientToServerMessage::CheckForMoreData => { + send_update( + &mut websocket, + &mut state, + false, + &mut ready_for_update, + &mut update_skipped, + )?; + }, + ClientToServerMessage::ViewRect { view_rect } => { + state.view_rect = view_rect; + send_update( + &mut websocket, + &mut state, + true, + &mut ready_for_update, + &mut update_skipped, + )?; + }, + ClientToServerMessage::ViewMode { id, mode, inherit } => { + let (mode, sorted) = if let Some(mode) = mode.strip_suffix("-sorted") { + (mode, true) + } else { + (mode.as_str(), false) + }; + match mode { + "raw-spans" => { + state.viewer.set_view_mode( + id, + Some((ViewMode::RawSpans { sorted }, inherit)), + ); + }, + "aggregated" => { + state.viewer.set_view_mode( + id, + Some((ViewMode::Aggregated { sorted }, inherit)), + ); + }, + "bottom-up" => { + state.viewer.set_view_mode( + id, + Some((ViewMode::BottomUp { sorted }, inherit)), + ); + }, + "aggregated-bottom-up" => { + state.viewer.set_view_mode( + id, + Some((ViewMode::AggregatedBottomUp { sorted }, inherit)), + ); + }, + _ => { + bail!("unknown view mode: {}", mode) + }, + } + send_update( + &mut websocket, + &mut state, + true, + &mut ready_for_update, + &mut update_skipped, + )?; + }, + ClientToServerMessage::ResetViewMode { id } => { + state.viewer.set_view_mode(id, None); + send_update( + &mut websocket, + &mut state, + true, + &mut ready_for_update, + &mut update_skipped, + )?; + }, + ClientToServerMessage::Query { id } => { + let message = { + let store = state.store.read(); + if let Some((span, is_graph)) = store.span(id) { + let root_start = store.root_span().start(); + let span_start = span.start() - root_start; + let span_end = span.end() - root_start; + let duration = span.corrected_total_time(); + let cpu = span.total_time(); + let allocations = span.total_allocations(); + let deallocations = span.total_deallocations(); + let allocation_count = span.total_allocation_count(); + let persistent_allocations = span.total_persistent_allocations(); + let args = span + .args() + .map(|(k, v)| (k.to_string(), v.to_string())) + .collect(); + let mut path = Vec::new(); + let mut current = span; + while let Some(parent) = current.parent() { + path.push(parent.nice_name().1.to_string()); + current = parent; + } + path.reverse(); + ServerToClientMessage::QueryResult { + id, + is_graph, + start:span_start, + end:span_end, + duration, + cpu, + allocations, + deallocations, + allocation_count, + persistent_allocations, + args, + path, + } + } else { + ServerToClientMessage::QueryResult { + id, + is_graph:false, + start:0, + end:0, + duration:0, + cpu:0, + allocations:0, + deallocations:0, + allocation_count:0, + persistent_allocations:0, + args:Vec::new(), + path:Vec::new(), + } + } + }; + let message = serde_json::to_string(&message).unwrap(); + websocket.send(Message::Text(message))?; + send_update( + &mut websocket, + &mut state, + true, + &mut ready_for_update, + &mut update_skipped, + )?; + + continue; + }, + ClientToServerMessage::Ack => { + ready_for_update = true; + if update_skipped { + update_skipped = false; + send_update( + &mut websocket, + &mut state, + true, + &mut ready_for_update, + &mut update_skipped, + )?; + } + }, + } + }, + Message::Binary(_) => { + // This doesn't happen + }, + Message::Close(_) => { + return Ok(()); + }, + Message::Ping(d) => { + websocket.send(Message::Pong(d))?; + }, + Message::Pong(_) => { + // thanks for the fish + }, + } + } +} diff --git a/crates/turbopack-trace-server/Source/span.rs b/crates/turbopack-trace-server/Source/span.rs new file mode 100644 index 0000000000000..a7752c8f8f831 --- /dev/null +++ b/crates/turbopack-trace-server/Source/span.rs @@ -0,0 +1,174 @@ +use std::{ + collections::HashMap, + num::NonZeroUsize, + sync::{Arc, OnceLock}, +}; + +pub type SpanIndex = NonZeroUsize; + +pub struct Span { + // These values won't change after creation: + pub parent:Option, + pub depth:u32, + pub start:u64, + pub category:String, + pub name:String, + pub args:Vec<(String, String)>, + + // This might change during writing: + pub events:Vec, + pub is_complete:bool, + + // These values are computed automatically: + pub self_allocations:u64, + pub self_allocation_count:u64, + pub self_deallocations:u64, + pub self_deallocation_count:u64, + + // These values are computed when accessed (and maybe deleted during writing): + pub max_depth:OnceLock, + pub total_allocations:OnceLock, + pub total_deallocations:OnceLock, + pub total_persistent_allocations:OnceLock, + pub total_span_count:OnceLock, + pub total_allocation_count:OnceLock, + + // More nested fields, but memory lazily allocated + pub time_data:OnceLock>, + pub extra:OnceLock>, + pub names:OnceLock>, +} + +#[derive(Default)] +pub struct SpanTimeData { + // These values won't change after creation: + pub ignore_self_time:bool, + + // This might change during writing: + pub self_end:u64, + + // These values are computed automatically: + pub self_time:u64, + + // These values are computed when accessed (and maybe deleted during writing): + pub end:OnceLock, + pub total_time:OnceLock, + pub corrected_self_time:OnceLock, + pub corrected_total_time:OnceLock, +} + +#[derive(Default)] +pub struct SpanExtra { + pub graph:OnceLock>, + pub bottom_up:OnceLock>>, + pub search_index:OnceLock>>, +} + +#[derive(Default)] +pub struct SpanNames { + // These values are computed when accessed (and maybe deleted during writing): + pub nice_name:OnceLock<(String, String)>, + pub group_name:OnceLock, +} + +impl Span { + pub fn time_data(&self) -> &SpanTimeData { + self.time_data.get_or_init(|| { + Box::new(SpanTimeData { + self_end:self.start, + ignore_self_time:&self.name == "thread", + ..Default::default() + }) + }) + } + + pub fn time_data_mut(&mut self) -> &mut SpanTimeData { + self.time_data(); + self.time_data.get_mut().unwrap() + } + + pub fn extra(&self) -> &SpanExtra { self.extra.get_or_init(Default::default) } + + pub fn names(&self) -> &SpanNames { self.names.get_or_init(Default::default) } +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum SpanEvent { + SelfTime { start:u64, end:u64 }, + Child { index:SpanIndex }, +} + +#[derive(Clone)] +pub enum SpanGraphEvent { + // TODO(sokra) use events instead of children for visualizing span graphs + #[allow(dead_code)] + SelfTime { + duration:u64, + }, + Child { + child:Arc, + }, +} + +pub struct SpanGraph { + // These values won't change after creation: + pub root_spans:Vec, + pub recursive_spans:Vec, + + // These values are computed when accessed: + pub max_depth:OnceLock, + pub events:OnceLock>, + pub self_time:OnceLock, + pub self_allocations:OnceLock, + pub self_deallocations:OnceLock, + pub self_persistent_allocations:OnceLock, + pub self_allocation_count:OnceLock, + pub total_time:OnceLock, + pub total_allocations:OnceLock, + pub total_deallocations:OnceLock, + pub total_persistent_allocations:OnceLock, + pub total_allocation_count:OnceLock, + pub total_span_count:OnceLock, + pub corrected_self_time:OnceLock, + pub corrected_total_time:OnceLock, + pub bottom_up:OnceLock>>, +} + +pub struct SpanBottomUp { + // These values won't change after creation: + pub self_spans:Vec, + pub children:Vec>, + pub example_span:SpanIndex, + + // These values are computed when accessed: + pub max_depth:OnceLock, + pub events:OnceLock>, + pub self_time:OnceLock, + pub corrected_self_time:OnceLock, + pub self_allocations:OnceLock, + pub self_deallocations:OnceLock, + pub self_persistent_allocations:OnceLock, + pub self_allocation_count:OnceLock, +} + +impl SpanBottomUp { + pub fn new( + self_spans:Vec, + example_span:SpanIndex, + children:Vec>, + ) -> Self { + Self { + self_spans, + children, + example_span, + max_depth:OnceLock::new(), + events:OnceLock::new(), + self_time:OnceLock::new(), + corrected_self_time:OnceLock::new(), + self_allocations:OnceLock::new(), + self_deallocations:OnceLock::new(), + self_persistent_allocations:OnceLock::new(), + self_allocation_count:OnceLock::new(), + } + } +} diff --git a/crates/turbopack-trace-server/Source/span_bottom_up_ref.rs b/crates/turbopack-trace-server/Source/span_bottom_up_ref.rs new file mode 100644 index 0000000000000..aaf628edb7571 --- /dev/null +++ b/crates/turbopack-trace-server/Source/span_bottom_up_ref.rs @@ -0,0 +1,170 @@ +use std::{ + collections::VecDeque, + fmt::{Debug, Formatter}, + sync::Arc, +}; + +use indexmap::IndexMap; + +use crate::{ + span::{SpanBottomUp, SpanGraphEvent, SpanIndex}, + span_graph_ref::{SpanGraphEventRef, SpanGraphRef, event_map_to_list}, + span_ref::SpanRef, + store::{SpanId, Store}, +}; + +pub struct SpanBottomUpRef<'a> { + pub(crate) bottom_up:Arc, + pub(crate) store:&'a Store, +} + +impl<'a> SpanBottomUpRef<'a> { + pub fn id(&self) -> SpanId { + unsafe { SpanId::new_unchecked((self.bottom_up.example_span.get() << 1) | 1) } + } + + fn first_span(&self) -> SpanRef<'a> { + let index = self.bottom_up.self_spans[0].get(); + SpanRef { span:&self.store.spans[index], store:self.store, index } + } + + fn example_span(&self) -> SpanRef<'a> { + let index = self.bottom_up.example_span.get(); + SpanRef { span:&self.store.spans[index], store:self.store, index } + } + + pub fn spans(&self) -> impl Iterator> + '_ { + let store = self.store; + self.bottom_up + .self_spans + .iter() + .map(move |span| SpanRef { span:&store.spans[span.get()], store, index:span.get() }) + } + + pub fn count(&self) -> usize { self.bottom_up.self_spans.len() } + + pub fn group_name(&self) -> &'a str { self.first_span().group_name() } + + pub fn nice_name(&self) -> (&'a str, &'a str) { + if self.count() == 1 { + self.example_span().nice_name() + } else { + ("", self.example_span().group_name()) + } + } + + pub fn children(&self) -> impl Iterator> + '_ { + self.bottom_up + .children + .iter() + .map(|bottom_up| SpanBottomUpRef { bottom_up:bottom_up.clone(), store:self.store }) + } + + #[allow(dead_code)] + pub fn graph(&self) -> impl Iterator> + '_ { + self.bottom_up + .events + .get_or_init(|| { + if self.count() == 1 { + let _ = self.first_span().graph(); + self.first_span().extra().graph.get().unwrap().clone() + } else { + let mut map:IndexMap<&str, (Vec, Vec)> = IndexMap::new(); + let mut queue = VecDeque::with_capacity(8); + for child in self.spans() { + let name = child.group_name(); + let (list, recursive_list) = map.entry(name).or_default(); + list.push(child.index()); + queue.push_back(child); + while let Some(child) = queue.pop_front() { + for nested_child in child.children() { + let nested_name = nested_child.group_name(); + if name == nested_name { + recursive_list.push(nested_child.index()); + queue.push_back(nested_child); + } + } + } + } + event_map_to_list(map) + } + }) + .iter() + .map(|graph| { + match graph { + SpanGraphEvent::SelfTime { duration } => { + SpanGraphEventRef::SelfTime { duration:*duration } + }, + SpanGraphEvent::Child { child } => { + SpanGraphEventRef::Child { + graph:SpanGraphRef { graph:child.clone(), store:self.store }, + } + }, + } + }) + } + + pub fn max_depth(&self) -> u32 { + *self.bottom_up.max_depth.get_or_init(|| { + self.children().map(|bottom_up| bottom_up.max_depth() + 1).max().unwrap_or(0) + }) + } + + pub fn corrected_self_time(&self) -> u64 { + *self + .bottom_up + .corrected_self_time + .get_or_init(|| self.spans().map(|span| span.corrected_self_time()).sum()) + } + + pub fn self_time(&self) -> u64 { + *self + .bottom_up + .self_time + .get_or_init(|| self.spans().map(|span| span.self_time()).sum()) + } + + pub fn self_allocations(&self) -> u64 { + *self + .bottom_up + .self_allocations + .get_or_init(|| self.spans().map(|span| span.self_allocations()).sum()) + } + + pub fn self_deallocations(&self) -> u64 { + *self + .bottom_up + .self_deallocations + .get_or_init(|| self.spans().map(|span| span.self_deallocations()).sum()) + } + + pub fn self_persistent_allocations(&self) -> u64 { + *self + .bottom_up + .self_persistent_allocations + .get_or_init(|| self.spans().map(|span| span.self_persistent_allocations()).sum()) + } + + pub fn self_allocation_count(&self) -> u64 { + *self + .bottom_up + .self_allocation_count + .get_or_init(|| self.spans().map(|span| span.self_allocation_count()).sum()) + } + + pub fn self_span_count(&self) -> u64 { self.bottom_up.self_spans.len() as u64 } +} + +impl<'a> Debug for SpanBottomUpRef<'a> { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SpanBottomUpRef") + .field("group_name", &self.group_name()) + .field("max_depth", &self.max_depth()) + .field("corrected_self_time", &self.corrected_self_time()) + .field("self_allocations", &self.self_allocations()) + .field("self_deallocations", &self.self_deallocations()) + .field("self_persistent_allocations", &self.self_persistent_allocations()) + .field("self_allocation_count", &self.self_allocation_count()) + .finish() + } +} diff --git a/crates/turbopack-trace-server/Source/span_graph_ref.rs b/crates/turbopack-trace-server/Source/span_graph_ref.rs new file mode 100644 index 0000000000000..161c5be62e338 --- /dev/null +++ b/crates/turbopack-trace-server/Source/span_graph_ref.rs @@ -0,0 +1,361 @@ +use std::{ + collections::VecDeque, + fmt::{Debug, Formatter}, + sync::{Arc, OnceLock}, +}; + +use indexmap::IndexMap; + +use crate::{ + bottom_up::build_bottom_up_graph, + span::{SpanGraph, SpanGraphEvent, SpanIndex}, + span_bottom_up_ref::SpanBottomUpRef, + span_ref::SpanRef, + store::{SpanId, Store}, +}; + +#[derive(Clone)] +pub struct SpanGraphRef<'a> { + pub(crate) graph:Arc, + pub(crate) store:&'a Store, +} + +impl<'a> SpanGraphRef<'a> { + pub fn first_span(&self) -> SpanRef<'a> { + let index = self.graph.root_spans[0].get(); + SpanRef { span:&self.store.spans[index], store:self.store, index } + } + + pub fn id(&self) -> SpanId { + unsafe { SpanId::new_unchecked((self.first_span().index << 1) | 1) } + } + + pub fn nice_name(&self) -> (&str, &str) { + if self.count() == 1 { + self.first_span().nice_name() + } else { + ("", self.first_span().group_name()) + } + } + + pub fn count(&self) -> usize { self.graph.root_spans.len() + self.graph.recursive_spans.len() } + + pub fn root_spans(&self) -> impl DoubleEndedIterator> + '_ { + self.graph.root_spans.iter().map(move |span| { + SpanRef { span:&self.store.spans[span.get()], store:self.store, index:span.get() } + }) + } + + fn recursive_spans(&self) -> impl DoubleEndedIterator> + '_ { + self.graph + .root_spans + .iter() + .chain(self.graph.recursive_spans.iter()) + .map(move |span| { + SpanRef { span:&self.store.spans[span.get()], store:self.store, index:span.get() } + }) + } + + pub fn events(&self) -> impl DoubleEndedIterator> + '_ { + self.graph + .events + .get_or_init(|| { + if self.count() == 1 { + let _ = self.first_span().graph(); + self.first_span().extra().graph.get().unwrap().clone() + } else { + let self_group = self.first_span().group_name(); + let mut map:IndexMap<&str, (Vec, Vec)> = IndexMap::new(); + let mut queue = VecDeque::with_capacity(8); + for span in self.recursive_spans() { + for span in span.children() { + let name = span.group_name(); + if name != self_group { + let (list, recusive_list) = map.entry(name).or_default(); + list.push(span.index()); + queue.push_back(span); + while let Some(child) = queue.pop_front() { + for nested_child in child.children() { + let nested_name = nested_child.group_name(); + if name == nested_name { + recusive_list.push(nested_child.index()); + queue.push_back(nested_child); + } + } + } + } + } + } + event_map_to_list(map) + } + }) + .iter() + .map(|graph| { + match graph { + SpanGraphEvent::SelfTime { duration } => { + SpanGraphEventRef::SelfTime { duration:*duration } + }, + SpanGraphEvent::Child { child } => { + SpanGraphEventRef::Child { + graph:SpanGraphRef { graph:child.clone(), store:self.store }, + } + }, + } + }) + } + + pub fn children(&self) -> impl DoubleEndedIterator> + '_ { + self.events().filter_map(|event| { + match event { + SpanGraphEventRef::SelfTime { .. } => None, + SpanGraphEventRef::Child { graph: span } => Some(span), + } + }) + } + + pub fn bottom_up(&self) -> impl Iterator> + '_ { + self.graph + .bottom_up + .get_or_init(|| build_bottom_up_graph(self.root_spans())) + .iter() + .map(move |bottom_up| SpanBottomUpRef { bottom_up:bottom_up.clone(), store:self.store }) + } + + pub fn max_depth(&self) -> u32 { + *self.graph.max_depth.get_or_init(|| { + self.children().map(|graph| graph.max_depth() + 1).max().unwrap_or_default() + }) + } + + pub fn self_time(&self) -> u64 { + *self.graph.self_time.get_or_init(|| { + self.recursive_spans() + .map(|span| span.self_time()) + .reduce(|a, b| a + b) + .unwrap_or_default() + }) + } + + pub fn total_time(&self) -> u64 { + *self.graph.total_time.get_or_init(|| { + self.children() + .map(|graph| graph.total_time()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_time() + }) + } + + pub fn self_allocations(&self) -> u64 { + *self.graph.self_allocations.get_or_init(|| { + self.recursive_spans() + .map(|span| span.self_allocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + }) + } + + pub fn self_deallocations(&self) -> u64 { + *self.graph.self_deallocations.get_or_init(|| { + self.recursive_spans() + .map(|span| span.self_deallocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + }) + } + + pub fn self_persistent_allocations(&self) -> u64 { + *self.graph.self_persistent_allocations.get_or_init(|| { + self.recursive_spans() + .map(|span| span.self_persistent_allocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + }) + } + + pub fn self_allocation_count(&self) -> u64 { + *self.graph.self_allocation_count.get_or_init(|| { + self.recursive_spans() + .map(|span| span.self_allocation_count()) + .reduce(|a, b| a + b) + .unwrap_or_default() + }) + } + + pub fn self_span_count(&self) -> u64 { + self.graph.root_spans.len() as u64 + self.graph.recursive_spans.len() as u64 + } + + pub fn total_allocations(&self) -> u64 { + *self.graph.total_allocations.get_or_init(|| { + self.children() + .map(|graph| graph.total_allocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_allocations() + }) + } + + pub fn total_deallocations(&self) -> u64 { + *self.graph.total_deallocations.get_or_init(|| { + self.children() + .map(|graph| graph.total_deallocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_deallocations() + }) + } + + pub fn total_persistent_allocations(&self) -> u64 { + *self.graph.total_persistent_allocations.get_or_init(|| { + self.children() + .map(|graph| graph.total_persistent_allocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_persistent_allocations() + }) + } + + pub fn total_allocation_count(&self) -> u64 { + *self.graph.total_allocation_count.get_or_init(|| { + self.children() + .map(|graph| graph.total_allocation_count()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_allocation_count() + }) + } + + pub fn total_span_count(&self) -> u64 { + *self.graph.total_span_count.get_or_init(|| { + self.children() + .map(|graph| graph.total_span_count()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_span_count() + }) + } + + pub fn corrected_self_time(&self) -> u64 { + *self.graph.corrected_self_time.get_or_init(|| { + self.recursive_spans() + .map(|span| span.corrected_self_time()) + .reduce(|a, b| a + b) + .unwrap_or_default() + }) + } + + pub fn corrected_total_time(&self) -> u64 { + *self.graph.corrected_total_time.get_or_init(|| { + self.children() + .map(|graph| graph.corrected_total_time()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.corrected_self_time() + }) + } +} + +pub fn event_map_to_list( + map:IndexMap<&str, (Vec, Vec)>, +) -> Vec { + map.into_iter() + .map(|(_, (root_spans, recursive_spans))| { + let graph = SpanGraph { + root_spans, + recursive_spans, + max_depth:OnceLock::new(), + events:OnceLock::new(), + self_time:OnceLock::new(), + self_allocations:OnceLock::new(), + self_deallocations:OnceLock::new(), + self_persistent_allocations:OnceLock::new(), + self_allocation_count:OnceLock::new(), + total_time:OnceLock::new(), + total_allocations:OnceLock::new(), + total_deallocations:OnceLock::new(), + total_persistent_allocations:OnceLock::new(), + total_allocation_count:OnceLock::new(), + total_span_count:OnceLock::new(), + corrected_self_time:OnceLock::new(), + corrected_total_time:OnceLock::new(), + bottom_up:OnceLock::new(), + }; + SpanGraphEvent::Child { child:Arc::new(graph) } + }) + .collect() +} + +impl<'a> Debug for SpanGraphRef<'a> { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SpanGraphRef") + .field("id", &self.id()) + .field("name", &self.nice_name()) + .field("count", &self.count()) + .field("max_depth", &self.max_depth()) + .field("self_time", &self.self_time()) + .field("self_allocations", &self.self_allocations()) + .field("total_time", &self.total_time()) + .field("total_allocations", &self.total_allocations()) + .finish() + } +} + +// TODO(sokra) use events instead of children for visualizing span graphs +#[allow(dead_code)] +#[derive(Clone)] +pub enum SpanGraphEventRef<'a> { + SelfTime { duration:u64 }, + Child { graph:SpanGraphRef<'a> }, +} + +impl<'a> SpanGraphEventRef<'a> { + pub fn corrected_total_time(&self) -> u64 { + match self { + SpanGraphEventRef::SelfTime { duration } => *duration, + SpanGraphEventRef::Child { graph } => graph.corrected_total_time(), + } + } + + pub fn total_time(&self) -> u64 { + match self { + SpanGraphEventRef::SelfTime { duration } => *duration, + SpanGraphEventRef::Child { graph } => graph.total_time(), + } + } + + pub fn total_allocations(&self) -> u64 { + match self { + SpanGraphEventRef::SelfTime { .. } => 0, + SpanGraphEventRef::Child { graph } => graph.total_allocations(), + } + } + + pub fn total_deallocations(&self) -> u64 { + match self { + SpanGraphEventRef::SelfTime { .. } => 0, + SpanGraphEventRef::Child { graph } => graph.total_deallocations(), + } + } + + pub fn total_persistent_allocations(&self) -> u64 { + match self { + SpanGraphEventRef::SelfTime { .. } => 0, + SpanGraphEventRef::Child { graph } => graph.total_persistent_allocations(), + } + } + + pub fn total_allocation_count(&self) -> u64 { + match self { + SpanGraphEventRef::SelfTime { .. } => 0, + SpanGraphEventRef::Child { graph } => graph.total_allocation_count(), + } + } + + pub fn total_span_count(&self) -> u64 { + match self { + SpanGraphEventRef::SelfTime { .. } => 0, + SpanGraphEventRef::Child { graph } => graph.total_span_count(), + } + } +} diff --git a/crates/turbopack-trace-server/Source/span_ref.rs b/crates/turbopack-trace-server/Source/span_ref.rs new file mode 100644 index 0000000000000..675b4130c84b1 --- /dev/null +++ b/crates/turbopack-trace-server/Source/span_ref.rs @@ -0,0 +1,387 @@ +use std::{ + cmp::max, + collections::{HashMap, HashSet, VecDeque}, + fmt::{Debug, Formatter}, + vec, +}; + +use indexmap::IndexMap; + +use crate::{ + bottom_up::build_bottom_up_graph, + span::{Span, SpanEvent, SpanExtra, SpanGraphEvent, SpanIndex, SpanNames, SpanTimeData}, + span_bottom_up_ref::SpanBottomUpRef, + span_graph_ref::{SpanGraphEventRef, SpanGraphRef, event_map_to_list}, + store::{SpanId, Store}, +}; + +#[derive(Copy, Clone)] +pub struct SpanRef<'a> { + pub(crate) span:&'a Span, + pub(crate) store:&'a Store, + pub(crate) index:usize, +} + +impl<'a> SpanRef<'a> { + pub fn id(&self) -> SpanId { unsafe { SpanId::new_unchecked(self.index << 1) } } + + pub fn index(&self) -> SpanIndex { SpanIndex::new(self.index).unwrap() } + + pub fn parent(&self) -> Option> { + self.span.parent.map(|index| { + SpanRef { span:&self.store.spans[index.get()], store:self.store, index:index.get() } + }) + } + + pub fn start(&self) -> u64 { self.span.start } + + pub fn time_data(&self) -> &'a SpanTimeData { self.span.time_data() } + + pub fn extra(&self) -> &'a SpanExtra { self.span.extra() } + + pub fn names(&self) -> &'a SpanNames { self.span.names() } + + pub fn end(&self) -> u64 { + let time_data = self.time_data(); + *time_data.end.get_or_init(|| { + max( + time_data.self_end, + self.children().map(|child| child.end()).max().unwrap_or_default(), + ) + }) + } + + pub fn is_complete(&self) -> bool { self.span.is_complete } + + pub fn is_root(&self) -> bool { self.index == 0 } + + pub fn nice_name(&self) -> (&'a str, &'a str) { + let (category, title) = self.names().nice_name.get_or_init(|| { + if let Some(name) = + self.span.args.iter().find(|&(k, _)| k == "name").map(|(_, v)| v.as_str()) + { + if matches!( + self.span.name.as_str(), + "turbo_tasks::resolve_call" | "turbo_tasks::resolve_trait_call" + ) { + (format!("{} {}", self.span.name, self.span.category), format!("*{name}")) + } else { + (format!("{} {}", self.span.name, self.span.category), name.to_string()) + } + } else { + (self.span.category.to_string(), self.span.name.to_string()) + } + }); + (category, title) + } + + pub fn group_name(&self) -> &'a str { + self.names().group_name.get_or_init(|| { + if matches!(self.span.name.as_str(), "turbo_tasks::function") { + self.span + .args + .iter() + .find(|&(k, _)| k == "name") + .map(|(_, v)| v.to_string()) + .unwrap_or_else(|| self.span.name.to_string()) + } else if matches!( + self.span.name.as_str(), + "turbo_tasks::resolve_call" | "turbo_tasks::resolve_trait_call" + ) { + self.span + .args + .iter() + .find(|&(k, _)| k == "name") + .map(|(_, v)| format!("*{v}")) + .unwrap_or_else(|| self.span.name.to_string()) + } else { + self.span.name.to_string() + } + }) + } + + pub fn args(&self) -> impl Iterator { + self.span.args.iter().map(|(k, v)| (k.as_str(), v.as_str())) + } + + pub fn self_time(&self) -> u64 { self.time_data().self_time } + + pub fn self_allocations(&self) -> u64 { + // 32 bytes for the tracing itself + self.span.self_allocations.saturating_sub(32) + } + + pub fn self_deallocations(&self) -> u64 { self.span.self_deallocations } + + pub fn self_persistent_allocations(&self) -> u64 { + self.self_allocations().saturating_sub(self.span.self_deallocations) + } + + pub fn self_allocation_count(&self) -> u64 { + // 4 allocations for the tracing itself + self.span.self_allocation_count.saturating_sub(4) + } + + pub fn self_span_count(&self) -> u64 { 1 } + + // TODO(sokra) use events instead of children for visualizing span graphs + #[allow(dead_code)] + pub fn events_count(&self) -> usize { self.span.events.len() } + + // TODO(sokra) use events instead of children for visualizing span graphs + #[allow(dead_code)] + pub fn events(&self) -> impl Iterator> { + self.span.events.iter().map(|event| { + match event { + &SpanEvent::SelfTime { start, end } => SpanEventRef::SelfTime { start, end }, + SpanEvent::Child { index } => { + SpanEventRef::Child { + span:SpanRef { + span:&self.store.spans[index.get()], + store:self.store, + index:index.get(), + }, + } + }, + } + }) + } + + pub fn children(&self) -> impl DoubleEndedIterator> + 'a { + self.span.events.iter().filter_map(|event| { + match event { + SpanEvent::SelfTime { .. } => None, + SpanEvent::Child { index } => { + Some(SpanRef { + span:&self.store.spans[index.get()], + store:self.store, + index:index.get(), + }) + }, + } + }) + } + + pub fn total_time(&self) -> u64 { + *self.time_data().total_time.get_or_init(|| { + self.children() + .map(|child| child.total_time()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_time() + }) + } + + pub fn total_allocations(&self) -> u64 { + *self.span.total_allocations.get_or_init(|| { + self.children() + .map(|child| child.total_allocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_allocations() + }) + } + + pub fn total_deallocations(&self) -> u64 { + *self.span.total_deallocations.get_or_init(|| { + self.children() + .map(|child| child.total_deallocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_deallocations() + }) + } + + pub fn total_persistent_allocations(&self) -> u64 { + *self.span.total_persistent_allocations.get_or_init(|| { + self.children() + .map(|child| child.total_persistent_allocations()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_persistent_allocations() + }) + } + + pub fn total_allocation_count(&self) -> u64 { + *self.span.total_allocation_count.get_or_init(|| { + self.children() + .map(|child| child.total_allocation_count()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.self_allocation_count() + }) + } + + pub fn total_span_count(&self) -> u64 { + *self.span.total_span_count.get_or_init(|| { + self.children() + .map(|child| child.total_span_count()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + 1 + }) + } + + pub fn corrected_self_time(&self) -> u64 { + let store = self.store; + *self.time_data().corrected_self_time.get_or_init(|| { + let mut self_time = 0; + for event in self.span.events.iter() { + if let SpanEvent::SelfTime { start, end } = event { + let duration = end - start; + if duration == 0 { + continue; + } + store.set_max_self_time_lookup(*end); + let concurrent_time = store.self_time_tree.lookup_range_count(*start, *end); + self_time += duration * duration / concurrent_time; + } + } + self_time + }) + } + + pub fn corrected_total_time(&self) -> u64 { + *self.time_data().corrected_total_time.get_or_init(|| { + self.children() + .map(|child| child.corrected_total_time()) + .reduce(|a, b| a + b) + .unwrap_or_default() + + self.corrected_self_time() + }) + } + + pub fn max_depth(&self) -> u32 { + *self.span.max_depth.get_or_init(|| { + self.children().map(|child| child.max_depth() + 1).max().unwrap_or_default() + }) + } + + pub fn graph(&self) -> impl Iterator> + '_ { + self.extra() + .graph + .get_or_init(|| { + let mut map:IndexMap<&str, (Vec, Vec)> = IndexMap::new(); + let mut queue = VecDeque::with_capacity(8); + for child in self.children() { + let name = child.group_name(); + let (list, recursive_list) = map.entry(name).or_default(); + list.push(child.index()); + queue.push_back(child); + while let Some(child) = queue.pop_front() { + for nested_child in child.children() { + let nested_name = nested_child.group_name(); + if name == nested_name { + recursive_list.push(nested_child.index()); + queue.push_back(nested_child); + } + } + } + } + event_map_to_list(map) + }) + .iter() + .map(|event| { + match event { + SpanGraphEvent::SelfTime { duration } => { + SpanGraphEventRef::SelfTime { duration:*duration } + }, + SpanGraphEvent::Child { child } => { + SpanGraphEventRef::Child { + graph:SpanGraphRef { graph:child.clone(), store:self.store }, + } + }, + } + }) + } + + pub fn bottom_up(self) -> impl Iterator> { + self.extra() + .bottom_up + .get_or_init(|| build_bottom_up_graph([self].into_iter())) + .iter() + .map(move |bottom_up| SpanBottomUpRef { bottom_up:bottom_up.clone(), store:self.store }) + } + + pub fn search(&self, query:&str) -> impl Iterator> { + let index = self.search_index(); + let mut result = HashSet::new(); + for (key, spans) in index { + if key.contains(query) { + result.extend(spans.iter().copied()); + } + } + let store = self.store; + result + .into_iter() + .map(move |index| SpanRef { span:&store.spans[index.get()], store, index:index.get() }) + } + + fn search_index(&self) -> &HashMap> { + self.extra().search_index.get_or_init(|| { + let mut index:HashMap> = HashMap::new(); + let mut queue = VecDeque::with_capacity(8); + queue.push_back(*self); + while let Some(span) = queue.pop_front() { + if !span.is_root() { + let (cat, name) = span.nice_name(); + if !cat.is_empty() { + index + .raw_entry_mut() + .from_key(cat) + .and_modify(|_, v| v.push(span.index())) + .or_insert_with(|| (cat.to_string(), vec![span.index()])); + } + if !name.is_empty() { + index + .raw_entry_mut() + .from_key(name) + .and_modify(|_, v| v.push(span.index())) + .or_insert_with(|| (name.to_string(), vec![span.index()])); + } + for (_, value) in span.span.args.iter() { + index + .raw_entry_mut() + .from_key(value) + .and_modify(|_, v| v.push(span.index())) + .or_insert_with(|| (value.to_string(), vec![span.index()])); + } + if !span.is_complete() { + let name = "incomplete"; + index + .raw_entry_mut() + .from_key(name) + .and_modify(|_, v| v.push(span.index())) + .or_insert_with(|| (name.to_string(), vec![span.index()])); + } + } + for child in span.children() { + queue.push_back(child); + } + } + index + }) + } +} + +impl<'a> Debug for SpanRef<'a> { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SpanRef") + .field("id", &self.id()) + .field("name", &self.nice_name()) + .field("start", &self.start()) + .field("end", &self.end()) + .field("is_complete", &self.is_complete()) + .field("self_time", &self.self_time()) + .field("total_time", &self.total_time()) + .field("max_depth", &self.max_depth()) + .finish() + } +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub enum SpanEventRef<'a> { + SelfTime { start:u64, end:u64 }, + Child { span:SpanRef<'a> }, +} diff --git a/crates/turbopack-trace-server/Source/store.rs b/crates/turbopack-trace-server/Source/store.rs new file mode 100644 index 0000000000000..363a74119806e --- /dev/null +++ b/crates/turbopack-trace-server/Source/store.rs @@ -0,0 +1,348 @@ +use std::{ + cmp::{max, min}, + collections::HashSet, + mem::replace, + num::NonZeroUsize, + sync::{OnceLock, atomic::AtomicU64}, +}; + +use crate::{ + self_time_tree::SelfTimeTree, + span::{Span, SpanEvent, SpanIndex}, + span_ref::SpanRef, +}; + +pub type SpanId = NonZeroUsize; + +const CUT_OFF_DEPTH:u32 = 150; + +pub struct Store { + pub(crate) spans:Vec, + pub(crate) self_time_tree:SelfTimeTree, + max_self_time_lookup_time:AtomicU64, +} + +fn new_root_span() -> Span { + Span { + parent:None, + depth:0, + start:u64::MAX, + category:"".into(), + name:"(root)".into(), + args:vec![], + events:vec![], + is_complete:true, + max_depth:OnceLock::new(), + self_allocations:0, + self_allocation_count:0, + self_deallocations:0, + self_deallocation_count:0, + total_allocations:OnceLock::new(), + total_deallocations:OnceLock::new(), + total_persistent_allocations:OnceLock::new(), + total_allocation_count:OnceLock::new(), + total_span_count:OnceLock::new(), + time_data:OnceLock::new(), + extra:OnceLock::new(), + names:OnceLock::new(), + } +} + +impl Store { + pub fn new() -> Self { + Self { + spans:vec![new_root_span()], + self_time_tree:SelfTimeTree::new(), + max_self_time_lookup_time:AtomicU64::new(0), + } + } + + pub fn reset(&mut self) { + self.spans.truncate(1); + self.spans[0] = new_root_span(); + self.self_time_tree = SelfTimeTree::new(); + *self.max_self_time_lookup_time.get_mut() = 0; + } + + pub fn has_time_info(&self) -> bool { self.self_time_tree.len() > 0 } + + pub fn add_span( + &mut self, + parent:Option, + start:u64, + category:String, + name:String, + args:Vec<(String, String)>, + outdated_spans:&mut HashSet, + ) -> SpanIndex { + let id = SpanIndex::new(self.spans.len()).unwrap(); + self.spans.push(Span { + parent, + depth:0, + start, + category, + name, + args, + events:vec![], + is_complete:false, + max_depth:OnceLock::new(), + self_allocations:0, + self_allocation_count:0, + self_deallocations:0, + self_deallocation_count:0, + total_allocations:OnceLock::new(), + total_deallocations:OnceLock::new(), + total_persistent_allocations:OnceLock::new(), + total_allocation_count:OnceLock::new(), + total_span_count:OnceLock::new(), + time_data:OnceLock::new(), + extra:OnceLock::new(), + names:OnceLock::new(), + }); + let parent = if let Some(parent) = parent { + outdated_spans.insert(parent); + &mut self.spans[parent.get()] + } else { + &mut self.spans[0] + }; + parent.start = min(parent.start, start); + let depth = parent.depth + 1; + if depth < CUT_OFF_DEPTH { + parent.events.push(SpanEvent::Child { index:id }); + } + let span = &mut self.spans[id.get()]; + span.depth = depth; + id + } + + pub fn add_args( + &mut self, + span_index:SpanIndex, + args:Vec<(String, String)>, + outdated_spans:&mut HashSet, + ) { + let span = &mut self.spans[span_index.get()]; + span.args.extend(args); + outdated_spans.insert(span_index); + } + + pub fn set_max_self_time_lookup(&self, time:u64) { + let mut old = self.max_self_time_lookup_time.load(std::sync::atomic::Ordering::Relaxed); + while old < time { + match self.max_self_time_lookup_time.compare_exchange( + old, + time, + std::sync::atomic::Ordering::Relaxed, + std::sync::atomic::Ordering::Relaxed, + ) { + Ok(_) => break, + Err(real_old) => old = real_old, + } + } + } + + fn insert_self_time( + &mut self, + start:u64, + end:u64, + span_index:SpanIndex, + outdated_spans:&mut HashSet, + ) { + if *self.max_self_time_lookup_time.get_mut() >= start { + self.self_time_tree.for_each_in_range(start, end, |_, _, span| { + outdated_spans.insert(*span); + }); + } + self.self_time_tree.insert(start, end, span_index); + } + + pub fn add_self_time( + &mut self, + span_index:SpanIndex, + start:u64, + end:u64, + outdated_spans:&mut HashSet, + ) { + let span = &mut self.spans[span_index.get()]; + let time_data = span.time_data_mut(); + if time_data.ignore_self_time { + return; + } + outdated_spans.insert(span_index); + time_data.self_time += end - start; + time_data.self_end = max(time_data.self_end, end); + span.events.push(SpanEvent::SelfTime { start, end }); + self.insert_self_time(start, end, span_index, outdated_spans); + } + + pub fn set_total_time( + &mut self, + span_index:SpanIndex, + start_time:u64, + total_time:u64, + outdated_spans:&mut HashSet, + ) { + let span = + SpanRef { span:&self.spans[span_index.get()], store:self, index:span_index.get() }; + let mut children = span + .children() + .map(|c| (c.span.start, c.span.time_data().self_end, c.index())) + .collect::>(); + children.sort(); + let self_end = start_time + total_time; + let mut self_time = 0; + let mut current = start_time; + let mut events = Vec::new(); + for (start, end, index) in children { + if start > current { + if start > self_end { + events.push(SpanEvent::SelfTime { start:current, end:self_end }); + self.insert_self_time(current, self_end, span_index, outdated_spans); + self_time += self_end - current; + break; + } + events.push(SpanEvent::SelfTime { start:current, end:start }); + self.insert_self_time(current, start, span_index, outdated_spans); + self_time += start - current; + } + events.push(SpanEvent::Child { index }); + current = max(current, end); + } + current -= start_time; + if current < total_time { + self_time += total_time - current; + events.push(SpanEvent::SelfTime { + start:current + start_time, + end:start_time + total_time, + }); + self.insert_self_time( + current + start_time, + start_time + total_time, + span_index, + outdated_spans, + ); + } + let span = &mut self.spans[span_index.get()]; + outdated_spans.insert(span_index); + let time_data = span.time_data_mut(); + time_data.self_time = self_time; + time_data.self_end = self_end; + span.events = events; + span.start = start_time; + } + + pub fn set_parent( + &mut self, + span_index:SpanIndex, + parent:SpanIndex, + outdated_spans:&mut HashSet, + ) { + outdated_spans.insert(span_index); + let span = &mut self.spans[span_index.get()]; + + let old_parent = replace(&mut span.parent, Some(parent)); + let old_parent = if let Some(parent) = old_parent { + outdated_spans.insert(parent); + &mut self.spans[parent.get()] + } else { + &mut self.spans[0] + }; + if let Some(index) = old_parent + .events + .iter() + .position(|event| *event == SpanEvent::Child { index:span_index }) + { + old_parent.events.remove(index); + } + + outdated_spans.insert(parent); + let parent = &mut self.spans[parent.get()]; + parent.events.push(SpanEvent::Child { index:span_index }); + } + + pub fn add_allocation( + &mut self, + span_index:SpanIndex, + allocation:u64, + count:u64, + outdated_spans:&mut HashSet, + ) { + let span = &mut self.spans[span_index.get()]; + outdated_spans.insert(span_index); + span.self_allocations += allocation; + span.self_allocation_count += count; + } + + pub fn add_deallocation( + &mut self, + span_index:SpanIndex, + deallocation:u64, + count:u64, + outdated_spans:&mut HashSet, + ) { + let span = &mut self.spans[span_index.get()]; + outdated_spans.insert(span_index); + span.self_deallocations += deallocation; + span.self_deallocation_count += count; + } + + pub fn complete_span(&mut self, span_index:SpanIndex) { + let span = &mut self.spans[span_index.get()]; + span.is_complete = true; + } + + pub fn invalidate_outdated_spans(&mut self, outdated_spans:&HashSet) { + fn invalidate_span(span:&mut Span) { + if let Some(time_data) = span.time_data.get_mut() { + time_data.end.take(); + time_data.total_time.take(); + time_data.corrected_self_time.take(); + time_data.corrected_total_time.take(); + } + span.total_allocations.take(); + span.total_deallocations.take(); + span.total_persistent_allocations.take(); + span.total_allocation_count.take(); + span.total_span_count.take(); + span.extra.take(); + } + + for id in outdated_spans.iter() { + let mut span = &mut self.spans[id.get()]; + loop { + invalidate_span(span); + let Some(parent) = span.parent else { + break; + }; + if outdated_spans.contains(&parent) { + break; + } + span = &mut self.spans[parent.get()]; + } + } + + invalidate_span(&mut self.spans[0]); + } + + pub fn root_spans(&self) -> impl Iterator> { + self.spans[0].events.iter().filter_map(|event| { + match event { + &SpanEvent::Child { index: id } => { + Some(SpanRef { span:&self.spans[id.get()], store:self, index:id.get() }) + }, + _ => None, + } + }) + } + + pub fn root_span(&self) -> SpanRef<'_> { SpanRef { span:&self.spans[0], store:self, index:0 } } + + pub fn span(&self, id:SpanId) -> Option<(SpanRef<'_>, bool)> { + let id = id.get(); + let is_graph = id & 1 == 1; + let index = id >> 1; + self.spans + .get(index) + .map(|span| (SpanRef { span, store:self, index }, is_graph)) + } +} diff --git a/crates/turbopack-trace-server/Source/store_container.rs b/crates/turbopack-trace-server/Source/store_container.rs new file mode 100644 index 0000000000000..0907f143dbf68 --- /dev/null +++ b/crates/turbopack-trace-server/Source/store_container.rs @@ -0,0 +1,76 @@ +use std::{ + ops::{Deref, DerefMut}, + sync::{ + RwLock, + RwLockReadGuard, + RwLockWriteGuard, + atomic::{AtomicBool, Ordering}, + }, +}; + +use crate::store::Store; + +pub struct StoreContainer { + store:RwLock, + want_to_read:AtomicBool, +} + +struct StoreWithGeneration { + store:Store, + generation:usize, +} + +impl StoreContainer { + pub fn new() -> Self { + Self { + store:RwLock::new(StoreWithGeneration { store:Store::new(), generation:0 }), + want_to_read:AtomicBool::new(false), + } + } + + pub fn read(&self) -> StoreReadGuard<'_> { + if let Ok(guard) = self.store.try_read() { + return StoreReadGuard { guard }; + } + self.want_to_read.store(true, Ordering::Relaxed); + let guard = StoreReadGuard { guard:self.store.read().unwrap() }; + self.want_to_read.store(false, Ordering::Relaxed); + guard + } + + pub fn write(&self) -> StoreWriteGuard<'_> { + let mut guard = self.store.write().unwrap(); + guard.generation += 1; + StoreWriteGuard { guard } + } + + pub fn want_to_read(&self) -> bool { self.want_to_read.load(Ordering::Relaxed) } +} + +pub struct StoreReadGuard<'a> { + guard:RwLockReadGuard<'a, StoreWithGeneration>, +} + +impl<'a> StoreReadGuard<'a> { + pub fn generation(&self) -> usize { self.guard.generation } +} + +impl<'a> Deref for StoreReadGuard<'a> { + type Target = Store; + + fn deref(&self) -> &Self::Target { &self.guard.store } +} + +pub struct StoreWriteGuard<'a> { + guard:RwLockWriteGuard<'a, StoreWithGeneration>, +} + +impl<'a> Deref for StoreWriteGuard<'a> { + type Target = Store; + + fn deref(&self) -> &Self::Target { &self.guard.store } +} + +impl<'a> DerefMut for StoreWriteGuard<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.guard.store } +} diff --git a/crates/turbopack-trace-server/Source/u64_empty_string.rs b/crates/turbopack-trace-server/Source/u64_empty_string.rs new file mode 100644 index 0000000000000..f7960ac6cde9d --- /dev/null +++ b/crates/turbopack-trace-server/Source/u64_empty_string.rs @@ -0,0 +1,18 @@ +use serde::{Deserialize, Deserializer, Serializer, de}; + +pub fn serialize(value:&u64, serializer:S) -> Result +where + S: Serializer, { + if *value == 0 { + serializer.serialize_str("") + } else { + serializer.collect_str(&value) + } +} + +pub fn deserialize<'de, D>(deserializer:D) -> Result +where + D: Deserializer<'de>, { + let str = &String::deserialize(deserializer)?; + if str.is_empty() { Ok(0) } else { str.parse().map_err(de::Error::custom) } +} diff --git a/crates/turbopack-trace-server/Source/u64_string.rs b/crates/turbopack-trace-server/Source/u64_string.rs new file mode 100644 index 0000000000000..898b5b6672191 --- /dev/null +++ b/crates/turbopack-trace-server/Source/u64_string.rs @@ -0,0 +1,18 @@ +use std::{fmt::Display, str::FromStr}; + +use serde::{Deserialize, Deserializer, Serializer, de}; + +pub fn serialize(value:&T, serializer:S) -> Result +where + T: Display, + S: Serializer, { + serializer.collect_str(value) +} + +pub fn deserialize<'de, T, D>(deserializer:D) -> Result +where + T: FromStr, + T::Err: Display, + D: Deserializer<'de>, { + String::deserialize(deserializer)?.parse().map_err(de::Error::custom) +} diff --git a/crates/turbopack-trace-server/Source/viewer.rs b/crates/turbopack-trace-server/Source/viewer.rs new file mode 100644 index 0000000000000..5254a958a9dc7 --- /dev/null +++ b/crates/turbopack-trace-server/Source/viewer.rs @@ -0,0 +1,1094 @@ +use std::{ + cmp::{Reverse, max}, + collections::{HashMap, HashSet}, +}; + +use either::Either; +use itertools::Itertools; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use serde::{Deserialize, Serialize}; + +use crate::{ + server::ViewRect, + span_bottom_up_ref::SpanBottomUpRef, + span_graph_ref::{SpanGraphEventRef, SpanGraphRef}, + span_ref::SpanRef, + store::{SpanId, Store}, + u64_empty_string, +}; + +const EXTRA_WIDTH_PERCENTAGE:u64 = 50; +const EXTRA_HEIGHT:u64 = 5; + +#[derive(Default)] +pub struct Viewer { + span_options:HashMap, +} + +#[derive(Clone, Copy, Debug)] +pub enum ValueMode { + Duration, + Cpu, + Allocations, + Deallocations, + PersistentAllocations, + AllocationCount, + Count, + AllocationsPerTime, + PersistentAllocationsPerTime, + AllocationCountPerTime, +} + +impl ValueMode { + fn secondary(&self) -> ValueMode { + match self { + ValueMode::Duration => ValueMode::Cpu, + ValueMode::Cpu => ValueMode::Duration, + ValueMode::Allocations => ValueMode::PersistentAllocations, + ValueMode::Deallocations => ValueMode::PersistentAllocations, + ValueMode::PersistentAllocations => ValueMode::Allocations, + ValueMode::AllocationCount => ValueMode::Allocations, + ValueMode::Count => ValueMode::Count, + ValueMode::AllocationsPerTime => ValueMode::PersistentAllocationsPerTime, + ValueMode::PersistentAllocationsPerTime => ValueMode::AllocationsPerTime, + ValueMode::AllocationCountPerTime => ValueMode::AllocationsPerTime, + } + } + + fn value_from_span(&self, span:&SpanRef<'_>) -> u64 { + match self { + ValueMode::Duration => span.corrected_total_time(), + ValueMode::Cpu => span.total_time(), + ValueMode::Allocations => span.total_allocations(), + ValueMode::Deallocations => span.total_deallocations(), + ValueMode::PersistentAllocations => span.total_persistent_allocations(), + ValueMode::AllocationCount => span.total_allocation_count(), + ValueMode::Count => span.total_span_count(), + ValueMode::AllocationsPerTime => { + value_over_time(span.total_allocations(), span.corrected_total_time()) + }, + ValueMode::AllocationCountPerTime => { + value_over_time(span.total_allocation_count(), span.corrected_total_time()) + }, + ValueMode::PersistentAllocationsPerTime => { + value_over_time(span.total_persistent_allocations(), span.corrected_total_time()) + }, + } + } + + fn value_from_graph(&self, graph:&SpanGraphRef<'_>) -> u64 { + match self { + ValueMode::Duration => graph.corrected_total_time(), + ValueMode::Cpu => graph.total_time(), + ValueMode::Allocations => graph.total_allocations(), + ValueMode::Deallocations => graph.total_deallocations(), + ValueMode::PersistentAllocations => graph.total_persistent_allocations(), + ValueMode::AllocationCount => graph.total_allocation_count(), + ValueMode::Count => graph.total_span_count(), + ValueMode::AllocationsPerTime => { + value_over_time(graph.total_allocations(), graph.corrected_total_time()) + }, + ValueMode::AllocationCountPerTime => { + value_over_time(graph.total_allocation_count(), graph.corrected_total_time()) + }, + ValueMode::PersistentAllocationsPerTime => { + value_over_time(graph.total_persistent_allocations(), graph.corrected_total_time()) + }, + } + } + + fn value_from_graph_event(&self, event:&SpanGraphEventRef<'_>) -> u64 { + match self { + ValueMode::Duration => event.corrected_total_time(), + ValueMode::Cpu => event.total_time(), + ValueMode::Allocations => event.total_allocations(), + ValueMode::Deallocations => event.total_deallocations(), + ValueMode::PersistentAllocations => event.total_persistent_allocations(), + ValueMode::AllocationCount => event.total_allocation_count(), + ValueMode::Count => event.total_span_count(), + ValueMode::AllocationsPerTime => { + value_over_time(event.total_allocations(), event.corrected_total_time()) + }, + ValueMode::AllocationCountPerTime => { + value_over_time(event.total_allocation_count(), event.corrected_total_time()) + }, + ValueMode::PersistentAllocationsPerTime => { + value_over_time(event.total_persistent_allocations(), event.corrected_total_time()) + }, + } + } + + fn value_from_bottom_up(&self, bottom_up:&SpanBottomUpRef<'_>) -> u64 { + match self { + ValueMode::Duration => bottom_up.corrected_self_time(), + ValueMode::Cpu => bottom_up.self_time(), + ValueMode::Allocations => bottom_up.self_allocations(), + ValueMode::Deallocations => bottom_up.self_deallocations(), + ValueMode::PersistentAllocations => bottom_up.self_persistent_allocations(), + ValueMode::AllocationCount => bottom_up.self_allocation_count(), + ValueMode::Count => bottom_up.self_span_count(), + ValueMode::AllocationsPerTime => { + value_over_time(bottom_up.self_allocations(), bottom_up.corrected_self_time()) + }, + ValueMode::AllocationCountPerTime => { + value_over_time(bottom_up.self_allocation_count(), bottom_up.corrected_self_time()) + }, + ValueMode::PersistentAllocationsPerTime => { + value_over_time( + bottom_up.self_persistent_allocations(), + bottom_up.corrected_self_time(), + ) + }, + } + } + + fn value_from_bottom_up_span(&self, bottom_up_span:&SpanRef<'_>) -> u64 { + match self { + ValueMode::Duration => bottom_up_span.corrected_self_time(), + ValueMode::Cpu => bottom_up_span.self_time(), + ValueMode::Allocations => bottom_up_span.self_allocations(), + ValueMode::Deallocations => bottom_up_span.self_deallocations(), + ValueMode::PersistentAllocations => bottom_up_span.self_persistent_allocations(), + ValueMode::AllocationCount => bottom_up_span.self_allocation_count(), + ValueMode::Count => bottom_up_span.self_span_count(), + ValueMode::AllocationsPerTime => { + value_over_time( + bottom_up_span.self_allocations(), + bottom_up_span.corrected_self_time(), + ) + }, + ValueMode::AllocationCountPerTime => { + value_over_time( + bottom_up_span.self_allocation_count(), + bottom_up_span.corrected_self_time(), + ) + }, + ValueMode::PersistentAllocationsPerTime => { + value_over_time( + bottom_up_span.self_persistent_allocations(), + bottom_up_span.corrected_self_time(), + ) + }, + } + } +} + +/// this is unfortunately int division but itll have to do. +/// +/// cases where count per time is very low is probably not important +fn value_over_time(value:u64, time:u64) -> u64 { if time == 0 { 0 } else { value / time } } + +#[derive(Clone, Copy, Debug)] +pub enum ViewMode { + RawSpans { sorted:bool }, + Aggregated { sorted:bool }, + BottomUp { sorted:bool }, + AggregatedBottomUp { sorted:bool }, +} + +impl ViewMode { + fn as_spans(self) -> Self { + match self { + ViewMode::RawSpans { sorted } => ViewMode::RawSpans { sorted }, + ViewMode::Aggregated { sorted } => ViewMode::RawSpans { sorted }, + ViewMode::BottomUp { sorted } => ViewMode::BottomUp { sorted }, + ViewMode::AggregatedBottomUp { sorted } => ViewMode::BottomUp { sorted }, + } + } + + fn as_bottom_up(self) -> Self { + match self { + ViewMode::RawSpans { sorted } => ViewMode::BottomUp { sorted }, + ViewMode::Aggregated { sorted } => ViewMode::AggregatedBottomUp { sorted }, + ViewMode::BottomUp { sorted } => ViewMode::BottomUp { sorted }, + ViewMode::AggregatedBottomUp { sorted } => ViewMode::AggregatedBottomUp { sorted }, + } + } + + fn aggregate_children(&self) -> bool { + match self { + ViewMode::RawSpans { .. } => false, + ViewMode::Aggregated { .. } => true, + ViewMode::BottomUp { .. } => false, + ViewMode::AggregatedBottomUp { .. } => true, + } + } + + fn bottom_up(&self) -> bool { + match self { + ViewMode::RawSpans { .. } => false, + ViewMode::Aggregated { .. } => false, + ViewMode::BottomUp { .. } => true, + ViewMode::AggregatedBottomUp { .. } => true, + } + } + + fn sort_children(&self) -> bool { + match self { + ViewMode::RawSpans { sorted } => *sorted, + ViewMode::Aggregated { sorted } => *sorted, + ViewMode::BottomUp { sorted } => *sorted, + ViewMode::AggregatedBottomUp { sorted } => *sorted, + } + } +} + +#[derive(Default)] +struct SpanOptions { + view_mode:Option<(ViewMode, bool)>, +} + +pub struct Update { + pub lines:Vec, + pub max:u64, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ViewLineUpdate { + y:u64, + spans:Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ViewSpan { + #[serde(with = "u64_empty_string")] + id:u64, + #[serde(rename = "x")] + start:u64, + #[serde(rename = "w")] + width:u64, + #[serde(rename = "cat")] + category:String, + #[serde(rename = "t")] + text:String, + #[serde(rename = "c")] + count:u64, + #[serde(rename = "k")] + kind:u8, + #[serde(rename = "s")] + start_in_parent:u32, + #[serde(rename = "e")] + end_in_parent:u32, + #[serde(rename = "v")] + secondary:u64, +} + +#[derive(Debug)] +enum QueueItem<'a> { + Span(SpanRef<'a>), + SpanGraph(SpanGraphRef<'a>), + SpanBottomUp(SpanBottomUpRef<'a>), + SpanBottomUpSpan(SpanRef<'a>), +} + +impl<'a> QueueItem<'a> { + fn value(&self, value_mode:ValueMode) -> u64 { + match self { + QueueItem::Span(span) => value_mode.value_from_span(span), + QueueItem::SpanGraph(span_graph) => value_mode.value_from_graph(span_graph), + QueueItem::SpanBottomUp(span_bottom_up) => { + value_mode.value_from_bottom_up(span_bottom_up) + }, + QueueItem::SpanBottomUpSpan(span) => value_mode.value_from_bottom_up_span(span), + } + } + + fn max_depth(&self) -> u32 { + match self { + QueueItem::Span(span) => span.max_depth(), + QueueItem::SpanGraph(span_graph) => span_graph.max_depth(), + QueueItem::SpanBottomUp(span_bottom_up) => span_bottom_up.max_depth(), + QueueItem::SpanBottomUpSpan(span) => span.max_depth(), + } + } +} + +#[derive(Debug, PartialEq, Eq)] +enum FilterMode { + SelectedItem, + Parent, + Child, +} + +#[derive(Debug)] +struct QueueItemWithState<'a> { + item:QueueItem<'a>, + line_index:usize, + start:u64, + placeholder:bool, + view_mode:ViewMode, + filtered:Option, +} + +struct ChildItem<'a> { + item:QueueItemWithState<'a>, + depth:u32, + pixel_range:(u64, u64), +} + +impl Viewer { + pub fn new() -> Self { Self::default() } + + pub fn set_view_mode(&mut self, id:SpanId, view_mode:Option<(ViewMode, bool)>) { + self.span_options.entry(id).or_default().view_mode = view_mode; + } + + pub fn compute_update(&mut self, store:&Store, view_rect:&ViewRect) -> Update { + let mut highlighted_spans:HashSet = HashSet::new(); + let mut highlighted_span_parents:HashSet = HashSet::new(); + let search_mode = !view_rect.query.is_empty(); + let (query, focus_mode) = if let Some(query) = view_rect.query.strip_suffix('!') { + (query, true) + } else { + (view_rect.query.as_str(), false) + }; + + let default_view_mode = view_rect.view_mode.as_str(); + let (default_view_mode, default_sorted) = default_view_mode + .strip_suffix("-sorted") + .map_or((default_view_mode, false), |s| (s, true)); + let (default_view_mode, with_root) = match default_view_mode { + "aggregated" => (ViewMode::Aggregated { sorted:default_sorted }, false), + "root-aggregated" => (ViewMode::Aggregated { sorted:default_sorted }, true), + "raw-spans" => (ViewMode::RawSpans { sorted:default_sorted }, false), + "bottom-up" => (ViewMode::BottomUp { sorted:default_sorted }, false), + "aggregated-bottom-up" => { + (ViewMode::AggregatedBottomUp { sorted:default_sorted }, false) + }, + "root-aggregated-bottom-up" => { + (ViewMode::AggregatedBottomUp { sorted:default_sorted }, true) + }, + _ => (ViewMode::Aggregated { sorted:default_sorted }, false), + }; + + let value_mode = match view_rect.value_mode.as_str() { + "duration" => ValueMode::Duration, + "cpu" => ValueMode::Cpu, + "allocations" => ValueMode::Allocations, + "deallocations" => ValueMode::Deallocations, + "persistent-deallocations" => ValueMode::PersistentAllocations, + "allocation-count" => ValueMode::AllocationCount, + "allocations-per-time" => ValueMode::AllocationsPerTime, + "allocation-count-per-time" => ValueMode::AllocationCountPerTime, + "persistent-allocations-per-time" => ValueMode::PersistentAllocationsPerTime, + "count" => ValueMode::Count, + _ => ValueMode::Duration, + }; + + if !store.has_time_info() && matches!(value_mode, ValueMode::Duration) { + return Update { + lines:vec![ViewLineUpdate { + spans:vec![ViewSpan { + id:0, + start:0, + width:1, + category:"info".to_string(), + text:"No time info in trace".to_string(), + count:1, + kind:0, + start_in_parent:0, + end_in_parent:0, + secondary:0, + }], + y:0, + }], + max:1, + }; + } + + let mut queue = Vec::new(); + + let root_spans = if with_root { + vec![store.root_span()] + } else { + let mut root_spans = store.root_spans().collect::>(); + root_spans.sort_by_key(|span| span.start()); + root_spans + }; + + let mut children = Vec::new(); + let mut current = 0; + let offset = + root_spans.iter().min_by_key(|span| span.start()).map_or(0, |span| span.start()); + root_spans.par_iter().for_each(|span| { + span.max_depth(); + QueueItem::Span(*span).value(value_mode); + }); + for span in root_spans { + if matches!(value_mode, ValueMode::Duration) { + // Move current to start if needed. + current = max(current, span.start() - offset); + } + if add_child_item( + &mut children, + &mut current, + view_rect, + 0, + default_view_mode, + value_mode, + QueueItem::Span(span), + Some(if search_mode { FilterMode::Parent } else { FilterMode::SelectedItem }), + ) && search_mode + { + let mut has_results = false; + for mut result in span.search(query) { + has_results = true; + highlighted_spans.insert(result.id()); + while let Some(parent) = result.parent() { + result = parent; + if !highlighted_span_parents.insert(result.id()) { + break; + } + } + } + if has_results { + highlighted_spans.insert(span.id()); + } else { + children.last_mut().unwrap().item.filtered = None; + } + } + } + enqueue_children(children, &mut queue); + queue.par_iter().for_each(|item| { + let QueueItem::Span(span) = item.item else { + return; + }; + let view_mode = + if span.is_complete() { item.view_mode } else { item.view_mode.as_spans() }; + + match (view_mode.bottom_up(), view_mode.aggregate_children()) { + (false, false) => {}, + (false, true) => { + span.graph().collect::>().par_iter().for_each(|event| { + value_mode.value_from_graph_event(event); + }); + }, + (true, false) => { + span.bottom_up().collect::>().par_iter().for_each(|bu| { + bu.spans().collect::>().par_iter().for_each(|span| { + value_mode.value_from_bottom_up_span(span); + }); + }); + }, + (true, true) => { + span.bottom_up().collect::>().par_iter().for_each(|bu| { + value_mode.value_from_bottom_up(bu); + }); + }, + } + }); + + let mut lines:Vec>> = vec![]; + + while let Some(QueueItemWithState { + item: span, + line_index, + start, + placeholder, + view_mode, + mut filtered, + }) = queue.pop() + { + let line = get_line(&mut lines, line_index); + let width = span.value(value_mode); + let secondary = span.value(value_mode.secondary()); + + let skipped_by_focus = + focus_mode && matches!(filtered, Some(FilterMode::Parent) | None); + + let get_filter_mode = |span:SpanId| { + if focus_mode + && matches!(filtered, Some(FilterMode::SelectedItem | FilterMode::Child)) + { + Some(FilterMode::Child) + } else if search_mode { + if highlighted_spans.contains(&span) { + Some(FilterMode::SelectedItem) + } else if highlighted_span_parents.contains(&span) { + Some(FilterMode::Parent) + } else { + None + } + } else { + Some(FilterMode::SelectedItem) + } + }; + + // compute children + let mut children = Vec::new(); + let mut current = start; + let child_line_index = if skipped_by_focus { line_index } else { line_index + 1 }; + match &span { + QueueItem::Span(span) => { + let (selected_view_mode, inherit) = (!span.is_root()) + .then(|| self.span_options.get(&span.id()).and_then(|o| o.view_mode)) + .flatten() + .unwrap_or_else(|| { + ( + if span.is_complete() { view_mode } else { view_mode.as_spans() }, + false, + ) + }); + + let view_mode = if inherit { selected_view_mode } else { view_mode }; + + let selected_view_mode = + if search_mode && highlighted_span_parents.contains(&span.id()) { + selected_view_mode.as_spans() + } else { + selected_view_mode + }; + + if selected_view_mode.bottom_up() { + let bottom_up = span.bottom_up(); + if selected_view_mode.aggregate_children() { + let bottom_up = if selected_view_mode.sort_children() { + Either::Left(bottom_up.sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_bottom_up(child)) + })) + } else { + Either::Right(bottom_up) + }; + for child in bottom_up { + // TODO search + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanBottomUp(child), + Some(FilterMode::SelectedItem), + ); + } + } else { + let bottom_up = bottom_up + .flat_map(|bottom_up| bottom_up.spans().collect::>()); + let bottom_up = if selected_view_mode.sort_children() { + Either::Left(bottom_up.sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_bottom_up_span(child)) + })) + } else { + Either::Right(bottom_up) + }; + for child in bottom_up { + let filtered = get_filter_mode(child.id()); + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanBottomUpSpan(child), + filtered, + ); + } + } + } else if !selected_view_mode.aggregate_children() { + let spans = if selected_view_mode.sort_children() { + Either::Left(span.children().sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_span(child)) + })) + } else { + Either::Right(span.children()) + }; + for child in spans { + let filtered = get_filter_mode(child.id()); + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::Span(child), + filtered, + ); + } + } else { + let events = if selected_view_mode.sort_children() { + Either::Left(span.graph().sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_graph_event(child)) + })) + } else { + Either::Right(span.graph()) + }; + for event in events { + let filtered = + if search_mode { None } else { Some(FilterMode::SelectedItem) }; + match event { + SpanGraphEventRef::SelfTime { duration: _ } => {}, + SpanGraphEventRef::Child { graph } => { + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanGraph(graph), + filtered, + ); + }, + } + } + } + }, + QueueItem::SpanGraph(span_graph) => { + let (selected_view_mode, inherit) = self + .span_options + .get(&span_graph.id()) + .and_then(|o| o.view_mode) + .unwrap_or((view_mode, false)); + + let view_mode = if inherit { selected_view_mode } else { view_mode }; + if selected_view_mode.bottom_up() { + let bottom_up = span_graph.bottom_up(); + if selected_view_mode.aggregate_children() { + let bottom_up = if selected_view_mode.sort_children() { + Either::Left(bottom_up.sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_bottom_up(child)) + })) + } else { + Either::Right(bottom_up) + }; + for child in bottom_up { + // TODO search + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanBottomUp(child), + Some(FilterMode::SelectedItem), + ); + } + } else { + let bottom_up = bottom_up + .flat_map(|bottom_up| bottom_up.spans().collect::>()); + let bottom_up = if selected_view_mode.sort_children() { + Either::Left(bottom_up.sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_bottom_up_span(child)) + })) + } else { + Either::Right(bottom_up) + }; + for child in bottom_up { + let filtered = get_filter_mode(child.id()); + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanBottomUpSpan(child), + filtered, + ); + } + } + } else if !selected_view_mode.aggregate_children() && span_graph.count() > 1 { + let spans = if selected_view_mode.sort_children() { + Either::Left(span_graph.root_spans().sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_span(child)) + })) + } else { + Either::Right(span_graph.root_spans()) + }; + for child in spans { + let filtered = get_filter_mode(child.id()); + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::Span(child), + filtered, + ); + } + } else { + let events = if selected_view_mode.sort_children() { + Either::Left(span_graph.events().sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_graph_event(child)) + })) + } else { + Either::Right(span_graph.events()) + }; + for child in events { + if let SpanGraphEventRef::Child { graph } = child { + let filtered = + if search_mode { None } else { Some(FilterMode::SelectedItem) }; + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanGraph(graph), + filtered, + ); + } + } + } + }, + QueueItem::SpanBottomUp(bottom_up) => { + let view_mode = self + .span_options + .get(&bottom_up.id()) + .and_then(|o| o.view_mode) + .map(|(v, _)| v.as_bottom_up()) + .unwrap_or(view_mode); + + if view_mode.aggregate_children() { + let bottom_up = if view_mode.sort_children() { + Either::Left(bottom_up.children().sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_bottom_up(child)) + })) + } else { + Either::Right(bottom_up.children()) + }; + for child in bottom_up { + // TODO search + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanBottomUp(child), + Some(FilterMode::SelectedItem), + ); + } + } else { + let spans = if view_mode.sort_children() { + Either::Left(bottom_up.spans().sorted_by_cached_key(|child| { + Reverse(value_mode.value_from_bottom_up_span(child)) + })) + } else { + Either::Right(bottom_up.spans()) + }; + for child in spans { + let filtered = get_filter_mode(child.id()); + add_child_item( + &mut children, + &mut current, + view_rect, + child_line_index, + view_mode, + value_mode, + QueueItem::SpanBottomUpSpan(child), + filtered, + ); + } + } + }, + QueueItem::SpanBottomUpSpan(_) => { + // no children + }, + } + + // When span size is smaller than a pixel, we only show the deepest child. + if placeholder { + let child = children + .into_iter() + .max_by_key(|ChildItem { item, depth, .. }| (item.filtered.is_some(), *depth)); + if let Some(ChildItem { item: mut entry, .. }) = child { + entry.placeholder = true; + queue.push(entry); + } + + if !skipped_by_focus { + // add span to line + line.push(LineEntry { + start, + width, + secondary:0, + ty:LineEntryType::Placeholder(filtered), + }); + } + } else { + // add children to queue + enqueue_children(children, &mut queue); + + // check if we should filter based on width or count + if !skipped_by_focus { + let count = match &span { + QueueItem::Span(_) => 1, + QueueItem::SpanGraph(span_graph) => span_graph.count(), + QueueItem::SpanBottomUp(bottom_up) => bottom_up.count(), + QueueItem::SpanBottomUpSpan(_) => 1, + }; + + if let Some(false) = view_rect.count_filter.as_ref().map(|filter| { + match filter.op { + crate::server::Op::Gt => count > filter.value as usize, + crate::server::Op::Lt => count < filter.value as usize, + } + }) { + filtered = Some(FilterMode::SelectedItem) + } + + if let Some(false) = view_rect.value_filter.as_ref().map(|filter| { + match filter.op { + crate::server::Op::Gt => width > filter.value, + crate::server::Op::Lt => width < filter.value, + } + }) { + filtered = Some(FilterMode::SelectedItem) + } + + // add span to line + line.push(LineEntry { + start, + width, + secondary, + ty:match span { + QueueItem::Span(span) => LineEntryType::Span { span, filtered }, + QueueItem::SpanGraph(span_graph) => { + LineEntryType::SpanGraph(span_graph, filtered) + }, + QueueItem::SpanBottomUp(bottom_up) => { + LineEntryType::SpanBottomUp(bottom_up, filtered) + }, + QueueItem::SpanBottomUpSpan(bottom_up_span) => { + LineEntryType::SpanBottomUpSpan(bottom_up_span, filtered) + }, + }, + }); + } + } + } + + let lines = lines + .into_iter() + .enumerate() + .map(|(y, line)| { + ViewLineUpdate { + y:y as u64, + spans:line + .into_iter() + .map(|entry| { + match entry.ty { + LineEntryType::Placeholder(filtered) => { + ViewSpan { + id:0, + start:entry.start, + width:entry.width, + category:String::new(), + text:String::new(), + count:1, + kind:match filtered { + Some(_) => 1, + None => 11, + }, + start_in_parent:0, + end_in_parent:0, + secondary:0, + } + }, + LineEntryType::Span { span, filtered } => { + let (category, text) = span.nice_name(); + let mut start_in_parent = 0; + let mut end_in_parent = 0; + if let Some(parent) = span.parent() { + let parent_start = parent.start(); + let parent_duration = parent.end() - parent_start; + if parent_duration > 0 { + start_in_parent = ((span.start() - parent_start) + * 10000 / parent_duration) + as u32; + end_in_parent = ((span.end() - parent_start) * 10000 + / parent_duration) as u32; + } else { + start_in_parent = 0; + end_in_parent = 10000; + } + } + ViewSpan { + id:(!span.is_root()) + .then(|| span.id().get() as u64) + .unwrap_or_default(), + start:entry.start, + width:entry.width, + category:category.to_string(), + text:text.to_string(), + count:1, + kind:match filtered { + Some(_) => 0, + None => 10, + }, + start_in_parent, + end_in_parent, + secondary:entry.secondary, + } + }, + LineEntryType::SpanGraph(graph, filtered) => { + let (category, text) = graph.nice_name(); + ViewSpan { + id:graph.id().get() as u64, + start:entry.start, + width:entry.width, + category:category.to_string(), + text:text.to_string(), + count:graph.count() as u64, + kind:match filtered { + Some(_) => 0, + None => 10, + }, + start_in_parent:0, + end_in_parent:0, + secondary:entry.secondary, + } + }, + LineEntryType::SpanBottomUp(bottom_up, filtered) => { + let (category, text) = bottom_up.nice_name(); + ViewSpan { + id:bottom_up.id().get() as u64, + start:entry.start, + width:entry.width, + category:category.to_string(), + text:text.to_string(), + count:bottom_up.count() as u64, + kind:match filtered { + Some(_) => 2, + None => 12, + }, + start_in_parent:0, + end_in_parent:0, + secondary:entry.secondary, + } + }, + LineEntryType::SpanBottomUpSpan(bottom_up_span, filtered) => { + let (category, text) = bottom_up_span.nice_name(); + ViewSpan { + id:bottom_up_span.id().get() as u64, + start:entry.start, + width:entry.width, + category:category.to_string(), + text:text.to_string(), + count:1, + kind:match filtered { + Some(_) => 2, + None => 12, + }, + start_in_parent:0, + end_in_parent:0, + secondary:entry.secondary, + } + }, + } + }) + .collect(), + } + }) + .collect(); + + Update { lines, max:max(1, current) } + } +} + +#[allow(clippy::too_many_arguments)] +fn add_child_item<'a>( + children:&mut Vec>, + current:&mut u64, + view_rect:&ViewRect, + line_index:usize, + view_mode:ViewMode, + value_mode:ValueMode, + child:QueueItem<'a>, + filtered:Option, +) -> bool { + let child_width = child.value(value_mode); + let max_depth = child.max_depth(); + let pixel1 = *current * view_rect.horizontal_pixels / view_rect.width; + let pixel2 = ((*current + child_width) * view_rect.horizontal_pixels + view_rect.width - 1) + / view_rect.width; + let start = *current; + *current += child_width; + + // filter by view rect (vertical) + if line_index > (view_rect.y + view_rect.height + EXTRA_HEIGHT) as usize { + return false; + } + + if line_index > 0 { + // filter by view rect (horizontal) + if start > view_rect.x + view_rect.width * (100 + EXTRA_WIDTH_PERCENTAGE) / 100 { + return false; + } + if *current < view_rect.x.saturating_sub(view_rect.width * EXTRA_WIDTH_PERCENTAGE / 100) { + return false; + } + } + + children.push(ChildItem { + item:QueueItemWithState { + item:child, + line_index, + start, + placeholder:false, + view_mode, + filtered, + }, + depth:max_depth, + pixel_range:(pixel1, pixel2), + }); + + true +} + +const MIN_VISIBLE_PIXEL_SIZE:u64 = 3; + +fn enqueue_children<'a>(mut children:Vec>, queue:&mut Vec>) { + children.reverse(); + let mut last_pixel = u64::MAX; + let mut last_max_depth = 0; + for ChildItem { item: mut entry, depth: max_depth, pixel_range: (pixel1, pixel2) } in children { + if last_pixel <= pixel1 + MIN_VISIBLE_PIXEL_SIZE { + if last_max_depth < max_depth { + queue.pop(); + entry.placeholder = true; + } else { + if let Some(entry) = queue.last_mut() { + entry.placeholder = true; + } + continue; + } + }; + queue.push(entry); + last_max_depth = max_depth; + last_pixel = pixel2; + } +} + +fn get_line(lines:&mut Vec, i:usize) -> &mut T { + if i >= lines.len() { + lines.resize_with(i + 1, || Default::default()); + } + &mut lines[i] +} + +struct LineEntry<'a> { + start:u64, + width:u64, + secondary:u64, + ty:LineEntryType<'a>, +} + +enum LineEntryType<'a> { + Placeholder(Option), + Span { span:SpanRef<'a>, filtered:Option }, + SpanGraph(SpanGraphRef<'a>, Option), + SpanBottomUp(SpanBottomUpRef<'a>, Option), + SpanBottomUpSpan(SpanRef<'a>, Option), +} diff --git a/crates/turbopack-trace-utils/Source/exit.rs b/crates/turbopack-trace-utils/Source/exit.rs new file mode 100644 index 0000000000000..ca7663a9a566f --- /dev/null +++ b/crates/turbopack-trace-utils/Source/exit.rs @@ -0,0 +1,27 @@ +use std::sync::{Arc, Mutex}; + +use anyhow::Result; + +/// A guard for the exit handler. When dropped, the exit guard will be dropped. +/// It might also be dropped on Ctrl-C. +pub struct ExitGuard(Arc>>); + +impl Drop for ExitGuard { + fn drop(&mut self) { drop(self.0.lock().unwrap().take()) } +} + +impl ExitGuard { + /// Drop a guard when Ctrl-C is pressed or the [ExitGuard] is dropped. + pub fn new(guard:T) -> Result { + let guard = Arc::new(Mutex::new(Some(guard))); + { + let guard = guard.clone(); + tokio::spawn(async move { + tokio::signal::ctrl_c().await.unwrap(); + drop(guard.lock().unwrap().take()); + std::process::exit(0); + }); + } + Ok(ExitGuard(guard)) + } +} diff --git a/crates/turbopack-trace-utils/Source/flavor.rs b/crates/turbopack-trace-utils/Source/flavor.rs new file mode 100644 index 0000000000000..1ce7b1d68b804 --- /dev/null +++ b/crates/turbopack-trace-utils/Source/flavor.rs @@ -0,0 +1,21 @@ +use postcard::ser_flavors::Flavor; + +pub struct BufFlavor { + pub buf:Vec, +} + +impl Flavor for BufFlavor { + type Output = Vec; + + fn try_push(&mut self, data:u8) -> postcard::Result<()> { + self.buf.push(data); + Ok(()) + } + + fn finalize(self) -> postcard::Result { Ok(self.buf) } + + fn try_extend(&mut self, data:&[u8]) -> postcard::Result<()> { + self.buf.extend_from_slice(data); + Ok(()) + } +} diff --git a/crates/turbopack-trace-utils/Source/lib.rs b/crates/turbopack-trace-utils/Source/lib.rs new file mode 100644 index 0000000000000..8b94c0e853ae9 --- /dev/null +++ b/crates/turbopack-trace-utils/Source/lib.rs @@ -0,0 +1,12 @@ +#![feature(async_closure)] +#![feature(min_specialization)] +#![feature(round_char_boundary)] +#![feature(thread_id_value)] +#![feature(arbitrary_self_types)] + +pub mod exit; +mod flavor; +pub mod raw_trace; +pub mod trace_writer; +pub mod tracing; +pub mod tracing_presets; diff --git a/crates/turbopack-trace-utils/Source/raw_trace.rs b/crates/turbopack-trace-utils/Source/raw_trace.rs new file mode 100644 index 0000000000000..d345d30968614 --- /dev/null +++ b/crates/turbopack-trace-utils/Source/raw_trace.rs @@ -0,0 +1,173 @@ +use std::{borrow::Cow, fmt::Write, marker::PhantomData, thread, time::Instant}; + +use tracing::{ + Subscriber, + field::{Visit, display}, + span, +}; +use tracing_subscriber::{Layer, registry::LookupSpan}; +use turbo_tasks_malloc::TurboMalloc; + +use crate::{ + flavor::BufFlavor, + trace_writer::TraceWriter, + tracing::{TraceRow, TraceValue}, +}; + +/// A tracing layer that writes raw trace data to a writer. The data format is +/// defined by [FullTraceRow]. +pub struct RawTraceLayer LookupSpan<'a>> { + trace_writer:TraceWriter, + start:Instant, + _phantom:PhantomData, +} + +impl LookupSpan<'a>> RawTraceLayer { + pub fn new(trace_writer:TraceWriter) -> Self { + Self { trace_writer, start:Instant::now(), _phantom:PhantomData } + } + + fn write(&self, data:TraceRow<'_>) { + let start = TurboMalloc::allocation_counters(); + // Buffer is recycled + let buf = self.trace_writer.try_get_buffer().unwrap_or_default(); + let buf = postcard::serialize_with_flavor(&data, BufFlavor { buf }).unwrap(); + self.trace_writer.write(buf); + TurboMalloc::reset_allocation_counters(start); + } + + fn report_allocations(&self, ts:u64, thread_id:u64) { + let allocation_counters = turbo_tasks_malloc::TurboMalloc::allocation_counters(); + self.write(TraceRow::AllocationCounters { + ts, + thread_id, + allocations:allocation_counters.allocations as u64, + deallocations:allocation_counters.deallocations as u64, + allocation_count:allocation_counters.allocation_count as u64, + deallocation_count:allocation_counters.deallocation_count as u64, + }); + } +} + +impl LookupSpan<'a>> Layer for RawTraceLayer { + fn on_new_span( + &self, + attrs:&span::Attributes<'_>, + id:&span::Id, + ctx:tracing_subscriber::layer::Context<'_, S>, + ) { + let ts = self.start.elapsed().as_micros() as u64; + let mut values = ValuesVisitor::new(); + attrs.values().record(&mut values); + self.write(TraceRow::Start { + ts, + id:id.into_u64(), + parent:if attrs.is_contextual() { + ctx.current_span().id().map(|p| p.into_u64()) + } else { + attrs.parent().map(|p| p.into_u64()) + }, + name:attrs.metadata().name().into(), + target:attrs.metadata().target().into(), + values:values.values, + }); + } + + fn on_close(&self, id:span::Id, _ctx:tracing_subscriber::layer::Context<'_, S>) { + let ts = self.start.elapsed().as_micros() as u64; + self.write(TraceRow::End { ts, id:id.into_u64() }); + } + + fn on_enter(&self, id:&span::Id, _ctx:tracing_subscriber::layer::Context<'_, S>) { + let ts = self.start.elapsed().as_micros() as u64; + let thread_id = thread::current().id().as_u64().into(); + self.report_allocations(ts, thread_id); + self.write(TraceRow::Enter { ts, id:id.into_u64(), thread_id }); + } + + fn on_exit(&self, id:&span::Id, _ctx:tracing_subscriber::layer::Context<'_, S>) { + let ts = self.start.elapsed().as_micros() as u64; + let thread_id = thread::current().id().as_u64().into(); + self.report_allocations(ts, thread_id); + self.write(TraceRow::Exit { ts, id:id.into_u64(), thread_id }); + } + + fn on_event(&self, event:&tracing::Event<'_>, ctx:tracing_subscriber::layer::Context<'_, S>) { + let ts = self.start.elapsed().as_micros() as u64; + let mut values = ValuesVisitor::new(); + event.record(&mut values); + self.write(TraceRow::Event { + ts, + parent:if event.is_contextual() { + ctx.current_span().id().map(|p| p.into_u64()) + } else { + event.parent().map(|p| p.into_u64()) + }, + values:values.values, + }); + } + + fn on_record( + &self, + id:&span::Id, + record:&span::Record<'_>, + _ctx:tracing_subscriber::layer::Context<'_, S>, + ) { + let mut values = ValuesVisitor::new(); + record.record(&mut values); + self.write(TraceRow::Record { id:id.into_u64(), values:values.values }); + } +} + +struct ValuesVisitor { + values:Vec<(Cow<'static, str>, TraceValue<'static>)>, +} + +impl ValuesVisitor { + fn new() -> Self { Self { values:Vec::new() } } +} + +impl Visit for ValuesVisitor { + fn record_debug(&mut self, field:&tracing::field::Field, value:&dyn std::fmt::Debug) { + let mut str = String::new(); + let _ = write!(str, "{:?}", value); + self.values.push((field.name().into(), TraceValue::String(str.into()))); + } + + fn record_f64(&mut self, field:&tracing::field::Field, value:f64) { + self.values.push((field.name().into(), TraceValue::Float(value))); + } + + fn record_i64(&mut self, field:&tracing::field::Field, value:i64) { + self.values.push((field.name().into(), TraceValue::Int(value))); + } + + fn record_u64(&mut self, field:&tracing::field::Field, value:u64) { + self.values.push((field.name().into(), TraceValue::UInt(value))); + } + + fn record_i128(&mut self, field:&tracing::field::Field, value:i128) { + self.record_debug(field, &value) + } + + fn record_u128(&mut self, field:&tracing::field::Field, value:u128) { + self.record_debug(field, &value) + } + + fn record_bool(&mut self, field:&tracing::field::Field, value:bool) { + self.values.push((field.name().into(), TraceValue::Bool(value))); + } + + fn record_str(&mut self, field:&tracing::field::Field, value:&str) { + self.values + .push((field.name().into(), TraceValue::String(value.to_string().into()))); + } + + fn record_error( + &mut self, + field:&tracing::field::Field, + value:&(dyn std::error::Error + 'static), + ) { + self.record_debug(field, &display(value)) + } +} diff --git a/crates/turbopack-trace-utils/Source/trace_writer.rs b/crates/turbopack-trace-utils/Source/trace_writer.rs new file mode 100644 index 0000000000000..635c2d3b1809e --- /dev/null +++ b/crates/turbopack-trace-utils/Source/trace_writer.rs @@ -0,0 +1,112 @@ +use std::{debug_assert, io::Write, thread::JoinHandle}; + +use crossbeam_channel::{Receiver, Sender, TryRecvError, bounded, unbounded}; + +#[derive(Clone, Debug)] +pub struct TraceWriter { + data_tx:Sender>, + return_rx:Receiver>, +} + +impl TraceWriter { + /// This is a non-blocking writer that writes a file in a background thread. + /// This is inspired by tracing-appender non_blocking, but has some + /// differences: + /// * It allows writing an owned Vec instead of a reference, so avoiding + /// additional allocation. + /// * It uses an unbounded channel to avoid slowing down the application at + /// all (memory) cost. + /// * It issues less writes by buffering the data into chunks of ~1MB, when + /// possible. + pub fn new(mut writer:W) -> (Self, TraceWriterGuard) { + let (data_tx, data_rx) = unbounded::>(); + let (return_tx, return_rx) = bounded::>(1024 * 10); + + let handle:std::thread::JoinHandle<()> = std::thread::spawn(move || { + let _ = writer.write(b"TRACEv0"); + let mut buf = Vec::with_capacity(1024 * 1024 * 1024); + 'outer: loop { + if !buf.is_empty() { + let _ = writer.write_all(&buf); + let _ = writer.flush(); + buf.clear(); + } + let Ok(mut data) = data_rx.recv() else { + break 'outer; + }; + if data.is_empty() { + break 'outer; + } + if data.len() > buf.capacity() { + let _ = writer.write_all(&data); + } else { + buf.extend_from_slice(&data); + } + data.clear(); + let _ = return_tx.try_send(data); + loop { + match data_rx.try_recv() { + Ok(data) => { + if data.is_empty() { + break 'outer; + } + if buf.len() + data.len() > buf.capacity() { + let _ = writer.write_all(&buf); + buf.clear(); + if data.len() > buf.capacity() { + let _ = writer.write_all(&data); + } else { + buf.extend_from_slice(&data); + } + } else { + buf.extend_from_slice(&data); + } + }, + Err(TryRecvError::Disconnected) => { + break 'outer; + }, + Err(TryRecvError::Empty) => { + break; + }, + } + } + } + if !buf.is_empty() { + let _ = writer.write_all(&buf); + } + let _ = writer.flush(); + drop(writer); + }); + + ( + Self { data_tx:data_tx.clone(), return_rx:return_rx.clone() }, + TraceWriterGuard { + data_tx:Some(data_tx), + return_rx:Some(return_rx), + handle:Some(handle), + }, + ) + } + + pub fn write(&self, data:Vec) { + debug_assert!(!data.is_empty()); + let _ = self.data_tx.send(data); + } + + pub fn try_get_buffer(&self) -> Option> { self.return_rx.try_recv().ok() } +} + +pub struct TraceWriterGuard { + data_tx:Option>>, + return_rx:Option>>, + handle:Option>, +} + +impl Drop for TraceWriterGuard { + fn drop(&mut self) { + let _ = self.data_tx.take().unwrap().send(Vec::new()); + let return_rx = self.return_rx.take().unwrap(); + while return_rx.recv().is_ok() {} + let _ = self.handle.take().unwrap().join(); + } +} diff --git a/crates/turbopack-trace-utils/Source/tracing.rs b/crates/turbopack-trace-utils/Source/tracing.rs new file mode 100644 index 0000000000000..13b909c2da6e6 --- /dev/null +++ b/crates/turbopack-trace-utils/Source/tracing.rs @@ -0,0 +1,150 @@ +use std::{ + borrow::Cow, + fmt::{Display, Formatter}, +}; + +use serde::{Deserialize, Serialize}; + +/// A raw trace line. +#[derive(Debug, Serialize, Deserialize)] +pub enum TraceRow<'a> { + /// A new span has been started, but not entered yet. + Start { + /// Timestamp + ts:u64, + /// Unique id for this span. + id:u64, + /// Id of the parent span, if any. + parent:Option, + /// The name of the span. + #[serde(borrow)] + name:Cow<'a, str>, + /// The target of the span. + #[serde(borrow)] + target:Cow<'a, str>, + /// A list of key-value pairs for all attributes of the span. + #[serde(borrow)] + values:Vec<(Cow<'a, str>, TraceValue<'a>)>, + }, + /// A span has ended. The id might be reused in future. + End { + /// Timestamp + ts:u64, + /// Unique id for this span. Must be created by a `Start` event before. + id:u64, + }, + /// A span has been entered. This means it is spending CPU time now. + Enter { + /// Timestamp + ts:u64, + /// Unique id for this span. Must be created by a `Start` event before. + id:u64, + /// The thread id of the thread that entered the span. + thread_id:u64, + }, + /// A span has been exited. This means it is not spending CPU time anymore. + Exit { + /// Timestamp + ts:u64, + /// Unique id for this span. Must be entered by a `Enter` event before. + id:u64, + /// The thread id of the thread that exits the span. + thread_id:u64, + }, + /// A event has happened for some span. + Event { + /// Timestamp + ts:u64, + /// Id of the parent span, if any. + parent:Option, + /// A list of key-value pairs for all attributes of the event. + #[serde(borrow)] + values:Vec<(Cow<'a, str>, TraceValue<'a>)>, + }, + /// Additional fields for a span + Record { + /// Unique id for this span. Must be created by a `Start` event before. + id:u64, + /// A list of key-value pairs for all attributes of the span. + #[serde(borrow)] + values:Vec<(Cow<'a, str>, TraceValue<'a>)>, + }, + /// Data about (de)allocations that happened + Allocation { + /// Timestamp + ts:u64, + /// The thread id of the thread where allocations happend. + thread_id:u64, + /// Allocations + allocations:u64, + /// Allocation count + allocation_count:u64, + /// Deallocations + deallocations:u64, + /// Deallocation count + deallocation_count:u64, + }, + /// Data about (de)allocations per thread counters. Actual allocations can + /// be computed from the difference. + AllocationCounters { + /// Timestamp + ts:u64, + /// The thread id of the thread where allocations happend. + thread_id:u64, + /// Allocations + allocations:u64, + /// Allocation count + allocation_count:u64, + /// Deallocations + deallocations:u64, + /// Deallocation count + deallocation_count:u64, + }, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum TraceValue<'a> { + String(#[serde(borrow)] Cow<'a, str>), + Bool(bool), + UInt(u64), + Int(i64), + Float(f64), +} + +impl Display for TraceValue<'_> { + fn fmt(&self, f:&mut Formatter<'_>) -> std::fmt::Result { + match self { + TraceValue::String(s) => write!(f, "{}", s), + TraceValue::Bool(b) => write!(f, "{}", b), + TraceValue::UInt(u) => write!(f, "{}", u), + TraceValue::Int(i) => write!(f, "{}", i), + TraceValue::Float(fl) => write!(f, "{}", fl), + } + } +} + +impl<'a> TraceValue<'a> { + pub fn as_u64(&self) -> Option { + match self { + TraceValue::UInt(u) => Some(*u), + _ => None, + } + } + + pub fn as_str(&self) -> Option<&str> { + match self { + TraceValue::String(s) => Some(s), + _ => None, + } + } + + pub fn into_static(self) -> TraceValue<'static> { + match self { + TraceValue::String(s) => TraceValue::String(s.into_owned().into()), + TraceValue::Bool(b) => TraceValue::Bool(b), + TraceValue::UInt(u) => TraceValue::UInt(u), + TraceValue::Int(i) => TraceValue::Int(i), + TraceValue::Float(fl) => TraceValue::Float(fl), + } + } +} diff --git a/crates/turbopack-trace-utils/Source/tracing_presets.rs b/crates/turbopack-trace-utils/Source/tracing_presets.rs new file mode 100644 index 0000000000000..d7aba75484521 --- /dev/null +++ b/crates/turbopack-trace-utils/Source/tracing_presets.rs @@ -0,0 +1,75 @@ +use once_cell::sync::Lazy; + +pub static TRACING_OVERVIEW_TARGETS:Lazy> = Lazy::new(|| { + vec![ + "turbo_tasks=info", + "turbopack=info", + "turbopack_binding=info", + "turbopack_nodejs=info", + "turbopack_cli=info", + "turbopack_cli_utils=info", + "turbopack_core=info", + "turbopack_css=info", + "turbopack_browser=info", + "turbopack_dev_server=info", + "turbopack_ecmascript=info", + "turbopack_ecmascript_hmr_protocol=info", + "turbopack_ecmascript_plugins=info", + "turbopack_ecmascript_runtime=info", + "turbopack_env=info", + "turbopack_image=info", + "turbopack_json=info", + "turbopack_mdx=info", + "turbopack_node=info", + "turbopack_static=info", + "turbopack_swc_utils=info", + "turbopack_wasm=info", + ] +}); +pub static TRACING_TURBOPACK_TARGETS:Lazy> = Lazy::new(|| { + [ + &TRACING_OVERVIEW_TARGETS[..], + &[ + "turbo_tasks=info", + "turbopack=trace", + "turbopack_binding=trace", + "turbopack_nodejs=trace", + "turbopack_cli=trace", + "turbopack_cli_utils=trace", + "turbopack_core=trace", + "turbopack_css=trace", + "turbopack_browser=trace", + "turbopack_dev_server=trace", + "turbopack_ecmascript=trace", + "turbopack_ecmascript_hmr_protocol=trace", + "turbopack_ecmascript_plugins=trace", + "turbopack_ecmascript_runtime=trace", + "turbopack_env=trace", + "turbopack_image=trace", + "turbopack_json=trace", + "turbopack_mdx=trace", + "turbopack_node=trace", + "turbopack_static=trace", + "turbopack_swc_utils=trace", + "turbopack_wasm=trace", + ], + ] + .concat() +}); +pub static TRACING_TURBO_TASKS_TARGETS:Lazy> = Lazy::new(|| { + [ + &TRACING_TURBOPACK_TARGETS[..], + &[ + "turbo_tasks=trace", + "turbo_tasks_auto_hash_map=trace", + "turbo_tasks_build=trace", + "turbo_tasks_bytes=trace", + "turbo_tasks_env=trace", + "turbo_tasks_fetch=trace", + "turbo_tasks_fs=trace", + "turbo_tasks_hash=trace", + "turbo_tasks_memory=trace", + ], + ] + .concat() +}); diff --git a/crates/turbopack-wasm/Source/analysis.rs b/crates/turbopack-wasm/Source/analysis.rs new file mode 100644 index 0000000000000..6bd909d37d249 --- /dev/null +++ b/crates/turbopack-wasm/Source/analysis.rs @@ -0,0 +1,77 @@ +use std::collections::BTreeMap; + +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileContent; +use turbopack_core::asset::Asset; +use wasmparser::{Chunk, Parser, Payload}; + +use crate::source::WebAssemblySource; + +/// Imports and exports of a WebAssembly file. +#[turbo_tasks::value] +#[derive(Default)] +pub(crate) struct WebAssemblyAnalysis { + pub imports:BTreeMap>, + pub exports:Vec, +} + +/// Analyse a WebAssembly file. +/// +/// Extracts imports and exports. +#[turbo_tasks::function] +pub(crate) async fn analyze(source:Vc) -> Result> { + let content = source.content().file_content().await?; + + let mut analysis = WebAssemblyAnalysis::default(); + + let FileContent::Content(file) = &*content else { + return Ok(analysis.cell()); + }; + + let mut bytes = &*file.content().to_bytes()?; + + let mut parser = Parser::new(0); + loop { + let payload = match parser.parse(bytes, true)? { + Chunk::Parsed { consumed, payload } => { + bytes = &bytes[consumed..]; + payload + }, + // this state isn't possible with `eof = true` + Chunk::NeedMoreData(_) => unreachable!(), + }; + + match payload { + Payload::ImportSection(s) => { + for import in s { + let import = import?; + + analysis + .imports + .entry(import.module.to_string()) + .or_default() + .push(import.name.to_string()); + } + }, + Payload::ExportSection(s) => { + for export in s { + let export = export?; + + analysis.exports.push(export.name.to_string()); + } + }, + + // skip over code sections + Payload::CodeSectionStart { size, .. } => { + parser.skip_section(); + bytes = &bytes[size as usize..]; + }, + + Payload::End(_) => break, + _ => {}, + } + } + + Ok(analysis.cell()) +} diff --git a/crates/turbopack-wasm/Source/lib.rs b/crates/turbopack-wasm/Source/lib.rs new file mode 100644 index 0000000000000..cca355f633244 --- /dev/null +++ b/crates/turbopack-wasm/Source/lib.rs @@ -0,0 +1,24 @@ +//! WebAssembly support for turbopack. +//! +//! WASM assets are copied directly to the output folder. +//! +//! When imported from ES modules, they produce a thin module that loads and +//! instantiates the WebAssembly module. + +#![feature(min_specialization)] +#![feature(arbitrary_self_types)] + +pub(crate) mod analysis; +pub(crate) mod loader; +pub mod module_asset; +pub(crate) mod output_asset; +pub mod raw; +pub mod source; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-wasm/Source/loader.rs b/crates/turbopack-wasm/Source/loader.rs new file mode 100644 index 0000000000000..e69304080712d --- /dev/null +++ b/crates/turbopack-wasm/Source/loader.rs @@ -0,0 +1,78 @@ +use std::fmt::Write; + +use anyhow::Result; +use indoc::{formatdoc, writedoc}; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::File; +use turbopack_core::{asset::AssetContent, source::Source, virtual_source::VirtualSource}; +use turbopack_ecmascript::utils::StringifyJs; + +use crate::{analysis::analyze, source::WebAssemblySource}; + +/// Create a javascript loader to instantiate the WebAssembly module with the +/// necessary imports and exports to be processed by [turbopack_ecmascript]. +#[turbo_tasks::function] +pub(crate) async fn instantiating_loader_source( + source:Vc, +) -> Result>> { + let analysis = analyze(source).await?; + + let mut code = String::new(); + + let mut imports_obj = "{".to_string(); + for (path, items) in &analysis.imports { + writeln!(code, "import {{ {} }} from {};", items.join(", "), StringifyJs(path))?; + + writeln!(imports_obj, "\n {}: {{", StringifyJs(path))?; + for item in items { + writeln!(imports_obj, " {}: {},", StringifyJs(item), item)?; + } + writeln!(imports_obj, " }},")?; + } + writeln!(imports_obj, "}}")?; + + writeln!(code, "import wasmPath from \"WASM_PATH\";")?; + + writeln!(code)?; + + writedoc!( + code, + r#" + const {{ {exports} }} = await __turbopack_wasm__(wasmPath, {imports}); + + export {{ {exports} }}; + "#, + imports = imports_obj, + exports = analysis.exports.join(", "), + )?; + + let code:RcStr = code.into(); + + Ok(Vc::upcast(VirtualSource::new( + source.ident().path().append("_.loader.mjs".into()), + AssetContent::file(File::from(code).into()), + ))) +} + +/// Create a javascript loader to compile the WebAssembly module and export it +/// without instantiating. +#[turbo_tasks::function] +pub(crate) async fn compiling_loader_source( + source:Vc, +) -> Result>> { + let code:RcStr = formatdoc! { + r#" + import wasmPath from "WASM_PATH"; + + const mod = await __turbopack_wasm_module__(wasmPath); + + export default mod; + "# + } + .into(); + + Ok(Vc::upcast(VirtualSource::new( + source.ident().path().append("_.loader.mjs".into()), + AssetContent::file(File::from(code).into()), + ))) +} diff --git a/crates/turbopack-wasm/Source/module_asset.rs b/crates/turbopack-wasm/Source/module_asset.rs new file mode 100644 index 0000000000000..7f793f7b1e9f5 --- /dev/null +++ b/crates/turbopack-wasm/Source/module_asset.rs @@ -0,0 +1,209 @@ +use anyhow::{Context, Result, bail}; +use indexmap::indexmap; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{AsyncModuleInfo, ChunkItem, ChunkType, ChunkableModule, ChunkingContext}, + context::AssetContext, + ident::AssetIdent, + module::{Module, OptionModule}, + reference::ModuleReferences, + reference_type::ReferenceType, + resolve::{origin::ResolveOrigin, parse::Request}, + source::Source, +}; +use turbopack_ecmascript::{ + EcmascriptModuleAsset, + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkItemOptions, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + references::async_module::OptionAsyncModule, +}; + +use crate::{ + loader::{compiling_loader_source, instantiating_loader_source}, + output_asset::WebAssemblyAsset, + raw::RawWebAssemblyModuleAsset, + source::WebAssemblySource, +}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("wasm module".into()) } + +/// Creates a javascript loader which instantiates the WebAssembly source and +/// re-exports its exports. +#[turbo_tasks::value] +#[derive(Clone)] +pub struct WebAssemblyModuleAsset { + source:Vc, + asset_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl WebAssemblyModuleAsset { + #[turbo_tasks::function] + pub fn new(source:Vc, asset_context:Vc>) -> Vc { + Self::cell(WebAssemblyModuleAsset { source, asset_context }) + } + + #[turbo_tasks::function] + fn wasm_asset(&self, chunking_context:Vc>) -> Vc { + WebAssemblyAsset::new(self.source, chunking_context) + } + + #[turbo_tasks::function] + async fn loader(&self) -> Result> { + let query = &*self.source.ident().query().await?; + + let loader_source = if query == "?module" { + compiling_loader_source(self.source) + } else { + instantiating_loader_source(self.source) + }; + + let module = self.asset_context.process( + loader_source, + Value::new(ReferenceType::Internal(Vc::cell(indexmap! { + "WASM_PATH".into() => Vc::upcast(RawWebAssemblyModuleAsset::new(self.source, self.asset_context)), + }))), + ).module(); + + let Some(esm_asset) = + Vc::try_resolve_downcast_type::(module).await? + else { + bail!("WASM loader was not processed into an EcmascriptModuleAsset"); + }; + + Ok(esm_asset) + } +} + +#[turbo_tasks::value_impl] +impl Module for WebAssemblyModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + self.source + .ident() + .with_modifier(modifier()) + .with_layer(self.asset_context.layer()) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Vc { self.loader().references() } +} + +#[turbo_tasks::value_impl] +impl Asset for WebAssemblyModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for WebAssemblyModuleAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast(ModuleChunkItem { module:self, chunking_context }.cell())) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for WebAssemblyModuleAsset { + #[turbo_tasks::function] + fn get_exports(self: Vc) -> Vc { self.loader().get_exports() } + + #[turbo_tasks::function] + fn get_async_module(self: Vc) -> Vc { + self.loader().get_async_module() + } +} + +#[turbo_tasks::value_impl] +impl ResolveOrigin for WebAssemblyModuleAsset { + #[turbo_tasks::function] + fn origin_path(&self) -> Vc { self.source.ident().path() } + + #[turbo_tasks::function] + fn asset_context(&self) -> Vc> { self.asset_context } + + #[turbo_tasks::function] + fn get_inner_asset(self: Vc, request:Vc) -> Vc { + self.loader().get_inner_asset(request) + } +} + +#[turbo_tasks::value] +struct ModuleChunkItem { + module:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let loader = self.module.loader().as_chunk_item(Vc::upcast(self.chunking_context)); + + Ok(loader.references()) + } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } + + #[turbo_tasks::function] + fn is_self_async(self: Vc) -> Vc { Vc::cell(true) } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for ModuleChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + fn content(self: Vc) -> Vc { + panic!("content() should not be called"); + } + + #[turbo_tasks::function] + async fn content_with_async_module_info( + &self, + async_module_info:Option>, + ) -> Result> { + let loader_asset = self.module.loader(); + let item = loader_asset.as_chunk_item(Vc::upcast(self.chunking_context)); + + let ecmascript_item = Vc::try_resolve_downcast::>(item) + .await? + .context("EcmascriptModuleAsset must implement EcmascriptChunkItem")?; + + let chunk_item_content = + ecmascript_item.content_with_async_module_info(async_module_info).await?; + + Ok(EcmascriptChunkItemContent { + options:EcmascriptChunkItemOptions { wasm:true, ..chunk_item_content.options.clone() }, + ..chunk_item_content.clone_value() + } + .into()) + } +} diff --git a/crates/turbopack-wasm/Source/output_asset.rs b/crates/turbopack-wasm/Source/output_asset.rs new file mode 100644 index 0000000000000..06477d45bba08 --- /dev/null +++ b/crates/turbopack-wasm/Source/output_asset.rs @@ -0,0 +1,51 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::ChunkingContext, + ident::AssetIdent, + output::OutputAsset, + source::Source, +}; + +use crate::source::WebAssemblySource; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("wasm".into()) } + +/// Emits the [WebAssemblySource] at a chunk path determined by the +/// [ChunkingContext]. +#[turbo_tasks::value] +pub(crate) struct WebAssemblyAsset { + source:Vc, + chunking_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl WebAssemblyAsset { + #[turbo_tasks::function] + pub(crate) fn new( + source:Vc, + chunking_context:Vc>, + ) -> Vc { + Self::cell(WebAssemblyAsset { source, chunking_context }) + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for WebAssemblyAsset { + #[turbo_tasks::function] + async fn ident(&self) -> Result> { + let ident = self.source.ident().with_modifier(modifier()); + + let asset_path = self.chunking_context.chunk_path(ident, ".wasm".into()); + + Ok(AssetIdent::from_path(asset_path)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for WebAssemblyAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} diff --git a/crates/turbopack-wasm/Source/raw.rs b/crates/turbopack-wasm/Source/raw.rs new file mode 100644 index 0000000000000..2fc9243eb6aa8 --- /dev/null +++ b/crates/turbopack-wasm/Source/raw.rs @@ -0,0 +1,146 @@ +use anyhow::{Result, bail}; +use turbo_tasks::{RcStr, ValueToString, Vc}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext}, + context::AssetContext, + ident::AssetIdent, + module::Module, + output::OutputAsset, + reference::{ModuleReferences, SingleOutputAssetReference}, + source::Source, +}; +use turbopack_ecmascript::{ + chunk::{ + EcmascriptChunkItem, + EcmascriptChunkItemContent, + EcmascriptChunkPlaceable, + EcmascriptChunkType, + EcmascriptExports, + }, + utils::StringifyJs, +}; + +use crate::{output_asset::WebAssemblyAsset, source::WebAssemblySource}; + +#[turbo_tasks::function] +fn modifier() -> Vc { Vc::cell("wasm raw".into()) } + +/// Exports the relative path to the WebAssembly file without loading it. +#[turbo_tasks::value] +#[derive(Clone)] +pub struct RawWebAssemblyModuleAsset { + source:Vc, + asset_context:Vc>, +} + +#[turbo_tasks::value_impl] +impl RawWebAssemblyModuleAsset { + #[turbo_tasks::function] + pub fn new(source:Vc, asset_context:Vc>) -> Vc { + Self::cell(RawWebAssemblyModuleAsset { source, asset_context }) + } + + #[turbo_tasks::function] + fn wasm_asset(&self, chunking_context:Vc>) -> Vc { + WebAssemblyAsset::new(self.source, chunking_context) + } +} + +#[turbo_tasks::value_impl] +impl Module for RawWebAssemblyModuleAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + self.source + .ident() + .with_modifier(modifier()) + .with_layer(self.asset_context.layer()) + } +} + +#[turbo_tasks::value_impl] +impl Asset for RawWebAssemblyModuleAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} + +#[turbo_tasks::value_impl] +impl ChunkableModule for RawWebAssemblyModuleAsset { + #[turbo_tasks::function] + async fn as_chunk_item( + self: Vc, + chunking_context:Vc>, + ) -> Result>> { + Ok(Vc::upcast( + RawModuleChunkItem { + module:self, + chunking_context, + wasm_asset:self.wasm_asset(Vc::upcast(chunking_context)), + } + .cell(), + )) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkPlaceable for RawWebAssemblyModuleAsset { + #[turbo_tasks::function] + fn get_exports(self: Vc) -> Vc { EcmascriptExports::Value.cell() } +} + +#[turbo_tasks::value] +struct RawModuleChunkItem { + module:Vc, + chunking_context:Vc>, + wasm_asset:Vc, +} + +#[turbo_tasks::value_impl] +impl ChunkItem for RawModuleChunkItem { + #[turbo_tasks::function] + fn asset_ident(&self) -> Vc { self.module.ident() } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + Ok(Vc::cell(vec![Vc::upcast(SingleOutputAssetReference::new( + Vc::upcast(self.wasm_asset), + Vc::cell(format!("wasm(url) {}", self.wasm_asset.ident().to_string().await?).into()), + ))])) + } + + #[turbo_tasks::function] + async fn chunking_context(&self) -> Vc> { + Vc::upcast(self.chunking_context) + } + + #[turbo_tasks::function] + async fn ty(&self) -> Result>> { + Ok(Vc::upcast(Vc::::default().resolve().await?)) + } + + #[turbo_tasks::function] + fn module(&self) -> Vc> { Vc::upcast(self.module) } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkItem for RawModuleChunkItem { + #[turbo_tasks::function] + fn chunking_context(&self) -> Vc> { self.chunking_context } + + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let path = self.wasm_asset.ident().path().await?; + let output_root = self.chunking_context.output_root().await?; + + let Some(path) = output_root.get_path_to(&path) else { + bail!("WASM asset ident is not relative to output root"); + }; + + Ok(EcmascriptChunkItemContent { + inner_code:format!("__turbopack_export_value__({path});", path = StringifyJs(path)) + .into(), + ..Default::default() + } + .into()) + } +} diff --git a/crates/turbopack-wasm/Source/source.rs b/crates/turbopack-wasm/Source/source.rs new file mode 100644 index 0000000000000..23d663353664d --- /dev/null +++ b/crates/turbopack-wasm/Source/source.rs @@ -0,0 +1,84 @@ +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks_fs::{File, FileContent}; +use turbopack_core::{ + asset::{Asset, AssetContent}, + ident::AssetIdent, + source::Source, +}; + +#[derive( + PartialOrd, + Ord, + Eq, + PartialEq, + Hash, + Debug, + Copy, + Clone, + Serialize, + Deserialize, + TaskInput, + TraceRawVcs, +)] +pub enum WebAssemblySourceType { + /// Binary WebAssembly files (.wasm). + Binary, + /// WebAssembly text format (.wat). + Text, +} + +/// Returns the raw binary WebAssembly source or the assembled version of a text +/// format source. +#[turbo_tasks::value] +#[derive(Clone)] +pub struct WebAssemblySource { + source:Vc>, + source_ty:WebAssemblySourceType, +} + +#[turbo_tasks::value_impl] +impl WebAssemblySource { + #[turbo_tasks::function] + pub fn new(source:Vc>, source_ty:WebAssemblySourceType) -> Vc { + Self::cell(WebAssemblySource { source, source_ty }) + } +} + +#[turbo_tasks::value_impl] +impl Source for WebAssemblySource { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + match self.source_ty { + WebAssemblySourceType::Binary => self.source.ident(), + WebAssemblySourceType::Text => { + self.source + .ident() + .with_path(self.source.ident().path().append("_.wasm".into())) + }, + } + } +} + +#[turbo_tasks::value_impl] +impl Asset for WebAssemblySource { + #[turbo_tasks::function] + async fn content(&self) -> Result> { + let content = match self.source_ty { + WebAssemblySourceType::Binary => return Ok(self.source.content()), + WebAssemblySourceType::Text => self.source.content(), + }; + + let content = content.file_content().await?; + + let FileContent::Content(file) = &*content else { + return Ok(AssetContent::file(FileContent::NotFound.cell())); + }; + + let bytes = file.content().to_bytes()?; + let parsed = wat::parse_bytes(&bytes)?; + + Ok(AssetContent::file(File::from(&*parsed).into())) + } +} diff --git a/crates/turbopack-wasm/build.rs b/crates/turbopack-wasm/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack-wasm/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack/.gitignore b/crates/turbopack/.gitignore new file mode 100644 index 0000000000000..518a4fb2a2c1e --- /dev/null +++ b/crates/turbopack/.gitignore @@ -0,0 +1,2 @@ +bench.json +.pnpm diff --git a/crates/turbopack/Source/evaluate_context.rs b/crates/turbopack/Source/evaluate_context.rs new file mode 100644 index 0000000000000..2fadc6aff0dee --- /dev/null +++ b/crates/turbopack/Source/evaluate_context.rs @@ -0,0 +1,100 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Value, Vc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystem; +use turbopack_core::{ + compile_time_defines, + compile_time_info::CompileTimeInfo, + condition::ContextCondition, + context::AssetContext, + environment::{Environment, ExecutionEnvironment, NodeJsEnvironment}, + resolve::options::{ImportMap, ImportMapping}, +}; +use turbopack_ecmascript::TreeShakingMode; +use turbopack_node::execution_context::ExecutionContext; +use turbopack_resolve::resolve_options_context::ResolveOptionsContext; + +use crate::{ + ModuleAssetContext, + module_options::ModuleOptionsContext, + transition::TransitionsByName, +}; + +#[turbo_tasks::function] +pub fn node_build_environment() -> Vc { + Environment::new(Value::new(ExecutionEnvironment::NodeJsBuildTime( + NodeJsEnvironment::default().cell(), + ))) +} + +#[turbo_tasks::function] +pub async fn node_evaluate_asset_context( + execution_context:Vc, + import_map:Option>, + transitions:Option>, + layer:RcStr, +) -> Result>> { + let mut import_map = if let Some(import_map) = import_map { + import_map.await?.clone_value() + } else { + ImportMap::empty() + }; + import_map.insert_wildcard_alias( + "@vercel/turbopack-node/", + ImportMapping::PrimaryAlternative( + "./*".into(), + Some(turbopack_node::embed_js::embed_fs().root()), + ) + .cell(), + ); + let import_map = import_map.cell(); + let node_env:RcStr = + if let Some(node_env) = &*execution_context.env().read("NODE_ENV".into()).await? { + node_env.as_str().into() + } else { + "development".into() + }; + + // base context used for node_modules (and context for app code will be derived + // from this) + let resolve_options_context = ResolveOptionsContext { + enable_node_modules:Some(execution_context.project_path().root().resolve().await?), + enable_node_externals:true, + enable_node_native_modules:true, + custom_conditions:vec![node_env.clone(), "node".into()], + ..Default::default() + }; + // app code context, includes a rule to switch to the node_modules context + let resolve_options_context = ResolveOptionsContext { + enable_typescript:true, + import_map:Some(import_map), + rules:vec![( + ContextCondition::InDirectory("node_modules".to_string()), + resolve_options_context.clone().cell(), + )], + ..resolve_options_context + } + .cell(); + + Ok(Vc::upcast(ModuleAssetContext::new( + transitions.unwrap_or_else(|| Vc::cell(Default::default())), + CompileTimeInfo::builder(node_build_environment()) + .defines( + compile_time_defines!( + process.turbopack = true, + process.env.NODE_ENV = node_env.into_owned(), + process.env.TURBOPACK = true + ) + .cell(), + ) + .cell(), + ModuleOptionsContext { + enable_typescript_transform:Some(Default::default()), + tree_shaking_mode:Some(TreeShakingMode::ReexportsOnly), + ..Default::default() + } + .cell(), + resolve_options_context, + Vc::cell(layer), + ))) +} diff --git a/crates/turbopack/Source/graph/mod.rs b/crates/turbopack/Source/graph/mod.rs new file mode 100644 index 0000000000000..09425c690a7b5 --- /dev/null +++ b/crates/turbopack/Source/graph/mod.rs @@ -0,0 +1,185 @@ +use std::collections::HashSet; + +use anyhow::Result; +use turbo_tasks::Vc; +use turbopack_core::output::OutputAsset; + +#[turbo_tasks::value(shared)] +pub enum AggregatedGraph { + Leaf(Vc>), + Node { + depth:usize, + content:HashSet>, + references:HashSet>, + }, +} + +#[turbo_tasks::value_impl] +impl AggregatedGraph { + #[turbo_tasks::function] + fn leaf(asset:Vc>) -> Vc { Self::cell(AggregatedGraph::Leaf(asset)) } +} + +impl AggregatedGraph { + fn depth(&self) -> usize { + match self { + AggregatedGraph::Leaf(_) => 0, + AggregatedGraph::Node { depth, .. } => *depth, + } + } +} + +#[turbo_tasks::value_impl] +impl AggregatedGraph { + #[turbo_tasks::function] + pub async fn content(self: Vc) -> Result> { + Ok(match *self.await? { + AggregatedGraph::Leaf(asset) => AggregatedGraphNodeContent::Asset(asset).into(), + AggregatedGraph::Node { ref content, .. } => { + AggregatedGraphNodeContent::Children(content.clone()).into() + }, + }) + } + + #[turbo_tasks::function] + async fn references(self: Vc) -> Result> { + Ok(match *self.await? { + AggregatedGraph::Leaf(asset) => { + let mut refs = HashSet::new(); + for reference in asset.references().await?.iter() { + let reference = reference.resolve().await?; + if asset != reference { + refs.insert(AggregatedGraph::leaf(reference)); + } + } + AggregatedGraphsSet { set:refs }.into() + }, + AggregatedGraph::Node { ref references, .. } => { + let mut set = HashSet::new(); + for item in references + .iter() + .map(|&reference| aggregate_more(reference)) + .collect::>() + .into_iter() + { + set.insert(item.resolve().await?); + } + AggregatedGraphsSet { set }.into() + }, + }) + } + + #[turbo_tasks::function] + async fn cost(self: Vc) -> Result> { + Ok(match *self.await? { + AggregatedGraph::Leaf(asset) => AggregationCost(asset.references().await?.len()).into(), + AggregatedGraph::Node { ref references, .. } => { + AggregationCost(references.len()).into() + }, + }) + } + + #[turbo_tasks::function] + async fn valued_references(self: Vc) -> Result> { + let self_cost = self.cost().await?.0; + let mut inner = HashSet::new(); + let mut outer = HashSet::new(); + let mut references = HashSet::new(); + for (reference, cost) in self + .references() + .await? + .set + .iter() + .map(|&reference| (reference, reference.cost())) + .collect::>() + { + let cost = cost.await?.0; + if cost == 0 { + inner.insert(reference); + } else if cost > self_cost { + references.insert(reference); + } else { + outer.insert(reference); + } + } + Ok(AggregatedGraphsValuedReferences { inner, outer, references }.into()) + } +} + +#[turbo_tasks::function] +pub async fn aggregate(asset:Vc>) -> Result> { + let mut current = AggregatedGraph::leaf(asset); + loop { + if current.references().await?.set.is_empty() { + return Ok(current); + } + current = aggregate_more(current); + } +} + +#[turbo_tasks::value(shared)] +#[derive(Clone, Hash, Debug)] +struct AggregationCost(usize); + +#[turbo_tasks::function] +async fn aggregate_more(node:Vc) -> Result> { + let node_data = node.await?; + let depth = node_data.depth(); + let mut in_progress = HashSet::new(); + let mut content = HashSet::new(); + let mut references = HashSet::new(); + in_progress.insert(node); + + // only one kind of aggregation can't eliminate cycles with that + // number of nodes. Alternating the aggregation will get rid of all + // cycles + let aggregation = if depth > 0 && depth % 2 == 0 { 3 } else { 2 }; + for _ in 0..aggregation { + for &node in in_progress.iter() { + content.insert(node); + } + let valued_refs = + in_progress.drain().map(|node| node.valued_references()).collect::>(); + for valued_refs in valued_refs { + let valued_refs = valued_refs.await?; + for &reference in valued_refs.inner.iter() { + content.insert(reference); + } + for &reference in valued_refs.references.iter() { + if content.contains(&reference) { + continue; + } + references.insert(reference); + } + for &reference in valued_refs.outer.iter() { + if content.contains(&reference) { + continue; + } + references.remove(&reference); + in_progress.insert(reference); + } + } + } + for node in in_progress.into_iter() { + references.insert(node); + } + Ok(AggregatedGraph::Node { depth:depth + 1, content, references }.into()) +} + +#[turbo_tasks::value(shared)] +struct AggregatedGraphsSet { + pub set:HashSet>, +} + +#[turbo_tasks::value(shared)] +pub enum AggregatedGraphNodeContent { + Asset(Vc>), + Children(HashSet>), +} + +#[turbo_tasks::value(shared)] +struct AggregatedGraphsValuedReferences { + pub inner:HashSet>, + pub outer:HashSet>, + pub references:HashSet>, +} diff --git a/crates/turbopack/Source/lib.rs b/crates/turbopack/Source/lib.rs new file mode 100644 index 0000000000000..75853bf07359c --- /dev/null +++ b/crates/turbopack/Source/lib.rs @@ -0,0 +1,890 @@ +#![feature(box_patterns)] +#![feature(trivial_bounds)] +#![feature(min_specialization)] +#![feature(map_try_insert)] +#![feature(option_get_or_insert_default)] +#![feature(hash_set_entry)] +#![recursion_limit = "256"] +#![feature(arbitrary_self_types)] + +pub mod evaluate_context; +mod graph; +pub mod module_options; +pub mod rebase; +pub mod transition; +pub(crate) mod unsupported_sass; + +use std::{ + collections::{HashMap, HashSet}, + mem::swap, +}; + +use anyhow::{Result, bail}; +use css::{CssModuleAsset, ModuleCssAsset}; +use ecmascript::{ + EcmascriptModuleAsset, + EcmascriptModuleAssetType, + TreeShakingMode, + chunk::EcmascriptChunkPlaceable, + references::{FollowExportsResult, follow_reexports}, + side_effect_optimization::facade::module::EcmascriptModuleFacadeModule, +}; +use graph::{AggregatedGraph, AggregatedGraphNodeContent, aggregate}; +use module_options::{ModuleOptions, ModuleOptionsContext, ModuleRuleEffect, ModuleType}; +use tracing::Instrument; +use turbo_tasks::{Completion, RcStr, Value, ValueToString, Vc}; +use turbo_tasks_fs::{FileSystemPath, glob::Glob}; +pub use turbopack_core::condition; +use turbopack_core::{ + asset::Asset, + compile_time_info::CompileTimeInfo, + context::{AssetContext, ProcessResult}, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueStage, OptionStyledString, StyledString}, + module::Module, + output::OutputAsset, + raw_module::RawModule, + reference_type::{ + CssReferenceSubType, + EcmaScriptModulesReferenceSubType, + ImportWithType, + InnerAssets, + ReferenceType, + }, + resolve::{ + ExternalType, + ModulePart, + ModuleResolveResult, + ModuleResolveResultItem, + ResolveResult, + options::ResolveOptions, + origin::PlainResolveOrigin, + parse::Request, + resolve, + }, + source::Source, +}; +pub use turbopack_css as css; +pub use turbopack_ecmascript as ecmascript; +use turbopack_ecmascript::references::external_module::{CachedExternalModule, CachedExternalType}; +use turbopack_json::JsonModuleAsset; +use turbopack_mdx::MdxModuleAsset; +pub use turbopack_resolve::{resolve::resolve_options, resolve_options_context}; +use turbopack_resolve::{resolve_options_context::ResolveOptionsContext, typescript::type_resolve}; +use turbopack_static::StaticModuleAsset; +use turbopack_wasm::{module_asset::WebAssemblyModuleAsset, source::WebAssemblySource}; + +use self::{ + module_options::CustomModuleType, + transition::{Transition, TransitionsByName}, +}; + +#[turbo_tasks::value] +struct ModuleIssue { + ident:Vc, + title:Vc, + description:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for ModuleIssue { + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::ProcessModule.cell() } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.ident.path() } + + #[turbo_tasks::function] + fn title(&self) -> Vc { self.title } + + #[turbo_tasks::function] + fn description(&self) -> Vc { Vc::cell(Some(self.description)) } +} + +#[turbo_tasks::function] +async fn apply_module_type( + source:Vc>, + module_asset_context:Vc, + module_type:Vc, + reference_type:Value, + part:Option>, + inner_assets:Option>, + runtime_code:bool, +) -> Result> { + let module_type = &*module_type.await?; + Ok(ProcessResult::Module(match module_type { + ModuleType::Ecmascript { transforms, options } + | ModuleType::Typescript { transforms, tsx: _, analyze_types: _, options } + | ModuleType::TypescriptDeclaration { transforms, options } => { + let context_for_module = match module_type { + ModuleType::Typescript { analyze_types, .. } if *analyze_types => { + module_asset_context.with_types_resolving_enabled() + }, + ModuleType::TypescriptDeclaration { .. } => { + module_asset_context.with_types_resolving_enabled() + }, + _ => module_asset_context, + }; + let mut builder = EcmascriptModuleAsset::builder( + source, + Vc::upcast(context_for_module), + *transforms, + *options, + module_asset_context.compile_time_info(), + ); + match module_type { + ModuleType::Ecmascript { .. } => { + builder = builder.with_type(EcmascriptModuleAssetType::Ecmascript) + }, + ModuleType::Typescript { tsx, analyze_types, .. } => { + builder = builder.with_type(EcmascriptModuleAssetType::Typescript { + tsx:*tsx, + analyze_types:*analyze_types, + }) + }, + ModuleType::TypescriptDeclaration { .. } => { + builder = builder.with_type(EcmascriptModuleAssetType::TypescriptDeclaration) + }, + _ => unreachable!(), + } + + if let Some(inner_assets) = inner_assets { + builder = builder.with_inner_assets(inner_assets); + } + + if runtime_code { + Vc::upcast(builder.build()) + } else { + let options = options.await?; + match options.tree_shaking_mode { + Some(TreeShakingMode::ModuleFragments) => { + let side_effect_free_packages = + module_asset_context.side_effect_free_packages(); + + let module = builder.clone().build(); + + Vc::upcast( + if let Some(part) = part { + if let ModulePart::Evaluation = *part.await? { + if *module + .is_marked_as_side_effect_free(side_effect_free_packages) + .await? + { + return Ok(ProcessResult::Ignore.cell()); + } + } + + builder.build_part(part) + } else { + builder.build_part(ModulePart::facade()) + } + .await?, + ) + }, + Some(TreeShakingMode::ReexportsOnly) => { + let side_effect_free_packages = + module_asset_context.side_effect_free_packages(); + + let module = builder.build(); + if let Some(part) = part { + match *part.await? { + ModulePart::Evaluation => { + if *module + .is_marked_as_side_effect_free(side_effect_free_packages) + .await? + { + return Ok(ProcessResult::Ignore.cell()); + } + if *module.get_exports().needs_facade().await? { + Vc::upcast(EcmascriptModuleFacadeModule::new( + Vc::upcast(module), + part, + )) + } else { + Vc::upcast(module) + } + }, + ModulePart::Export(_) => { + if *module.get_exports().needs_facade().await? { + apply_reexport_tree_shaking( + Vc::upcast(EcmascriptModuleFacadeModule::new( + Vc::upcast(module), + ModulePart::exports(), + )), + part, + side_effect_free_packages, + ) + } else { + apply_reexport_tree_shaking( + Vc::upcast(module), + part, + side_effect_free_packages, + ) + } + }, + _ => { + bail!( + "Invalid module part for reexports only tree shaking mode" + ) + }, + } + } else if *module.get_exports().needs_facade().await? { + Vc::upcast(EcmascriptModuleFacadeModule::new( + Vc::upcast(module), + ModulePart::facade(), + )) + } else { + Vc::upcast(module) + } + }, + None => Vc::upcast(builder.build()), + } + } + }, + ModuleType::Json => Vc::upcast(JsonModuleAsset::new(source)), + ModuleType::Raw => Vc::upcast(RawModule::new(source)), + ModuleType::CssGlobal => { + return Ok(module_asset_context + .process(source, Value::new(ReferenceType::Css(CssReferenceSubType::Internal)))); + }, + ModuleType::CssModule => { + Vc::upcast(ModuleCssAsset::new(source, Vc::upcast(module_asset_context))) + }, + ModuleType::Css { ty, use_swc_css } => { + Vc::upcast(CssModuleAsset::new( + source, + Vc::upcast(module_asset_context), + *ty, + *use_swc_css, + if let ReferenceType::Css(CssReferenceSubType::AtImport(import)) = + reference_type.into_value() + { + import + } else { + None + }, + )) + }, + ModuleType::Static => { + Vc::upcast(StaticModuleAsset::new(source, Vc::upcast(module_asset_context))) + }, + ModuleType::Mdx { transforms, options, ecmascript_options } => { + Vc::upcast(MdxModuleAsset::new( + source, + Vc::upcast(module_asset_context), + *transforms, + *options, + *ecmascript_options, + )) + }, + ModuleType::WebAssembly { source_ty } => { + Vc::upcast(WebAssemblyModuleAsset::new( + WebAssemblySource::new(source, *source_ty), + Vc::upcast(module_asset_context), + )) + }, + ModuleType::Custom(custom) => custom.create_module(source, module_asset_context, part), + }) + .cell()) +} + +#[turbo_tasks::function] +async fn apply_reexport_tree_shaking( + module:Vc>, + part:Vc, + side_effect_free_packages:Vc, +) -> Result>> { + if let ModulePart::Export(export) = *part.await? { + let export = export.await?; + let FollowExportsResult { module: final_module, export_name: new_export, .. } = + &*follow_reexports(module, export.clone_value(), side_effect_free_packages).await?; + let module = if let Some(new_export) = new_export { + if *new_export == *export { + Vc::upcast(*final_module) + } else { + Vc::upcast(EcmascriptModuleFacadeModule::new( + *final_module, + ModulePart::renamed_export(new_export.clone(), export.clone_value()), + )) + } + } else { + Vc::upcast(EcmascriptModuleFacadeModule::new( + *final_module, + ModulePart::renamed_namespace(export.clone_value()), + )) + }; + return Ok(module); + } + Ok(Vc::upcast(module)) +} + +#[turbo_tasks::value] +#[derive(Debug)] +pub struct ModuleAssetContext { + pub transitions:Vc, + pub compile_time_info:Vc, + pub module_options_context:Vc, + pub resolve_options_context:Vc, + pub layer:Vc, + transition:Option>>, +} + +#[turbo_tasks::value_impl] +impl ModuleAssetContext { + #[turbo_tasks::function] + pub fn new( + transitions:Vc, + compile_time_info:Vc, + module_options_context:Vc, + resolve_options_context:Vc, + layer:Vc, + ) -> Vc { + Self::cell(ModuleAssetContext { + transitions, + compile_time_info, + module_options_context, + resolve_options_context, + transition:None, + layer, + }) + } + + #[turbo_tasks::function] + pub fn new_transition( + transitions:Vc, + compile_time_info:Vc, + module_options_context:Vc, + resolve_options_context:Vc, + layer:Vc, + transition:Vc>, + ) -> Vc { + Self::cell(ModuleAssetContext { + transitions, + compile_time_info, + module_options_context, + resolve_options_context, + layer, + transition:Some(transition), + }) + } + + #[turbo_tasks::function] + pub async fn module_options_context(self: Vc) -> Result> { + Ok(self.await?.module_options_context) + } + + #[turbo_tasks::function] + pub async fn resolve_options_context(self: Vc) -> Result> { + Ok(self.await?.resolve_options_context) + } + + #[turbo_tasks::function] + pub async fn is_types_resolving_enabled(self: Vc) -> Result> { + let resolve_options_context = self.await?.resolve_options_context.await?; + Ok(Vc::cell( + resolve_options_context.enable_types && resolve_options_context.enable_typescript, + )) + } + + #[turbo_tasks::function] + pub async fn with_types_resolving_enabled(self: Vc) -> Result> { + if *self.is_types_resolving_enabled().await? { + return Ok(self); + } + let this = self.await?; + let resolve_options_context = + this.resolve_options_context.with_types_enabled().resolve().await?; + + Ok(ModuleAssetContext::new( + this.transitions, + this.compile_time_info, + this.module_options_context, + resolve_options_context, + this.layer, + )) + } + + #[turbo_tasks::function] + fn process_default( + self: Vc, + source:Vc>, + reference_type:Value, + ) -> Vc { + process_default(self, source, reference_type, Vec::new()) + } +} + +#[turbo_tasks::function] +async fn process_default( + module_asset_context:Vc, + source:Vc>, + reference_type:Value, + processed_rules:Vec, +) -> Result> { + let span = tracing::info_span!( + "process module", + name = source.ident().to_string().await?.to_string(), + reference_type = display(&*reference_type) + ); + process_default_internal(module_asset_context, source, reference_type, processed_rules) + .instrument(span) + .await +} + +async fn process_default_internal( + module_asset_context:Vc, + source:Vc>, + reference_type:Value, + processed_rules:Vec, +) -> Result> { + let ident = source.ident().resolve().await?; + let path_ref = ident.path().await?; + let options = ModuleOptions::new( + ident.path().parent(), + module_asset_context.module_options_context(), + module_asset_context.resolve_options_context(), + ); + + let reference_type = reference_type.into_value(); + let part:Option> = match &reference_type { + ReferenceType::EcmaScriptModules(EcmaScriptModulesReferenceSubType::ImportPart(part)) => { + Some(*part) + }, + _ => None, + }; + let inner_assets = match &reference_type { + ReferenceType::Internal(inner_assets) => Some(*inner_assets), + _ => None, + }; + + let mut has_type_attribute = false; + + let mut current_source = source; + let mut current_module_type = match &reference_type { + ReferenceType::EcmaScriptModules(EcmaScriptModulesReferenceSubType::ImportWithType(ty)) => { + has_type_attribute = true; + + match ty { + ImportWithType::Json => Some(ModuleType::Json), + } + }, + _ => None, + }; + + for (i, rule) in options.await?.rules.iter().enumerate() { + if has_type_attribute && current_module_type.is_some() { + continue; + } + if processed_rules.contains(&i) { + continue; + } + if rule.matches(source, &path_ref, &reference_type).await? { + for effect in rule.effects() { + match effect { + ModuleRuleEffect::SourceTransforms(transforms) => { + current_source = transforms.transform(current_source); + if current_source.ident().resolve().await? != ident { + // The ident has been changed, so we need to apply new rules. + let mut processed_rules = processed_rules.clone(); + processed_rules.push(i); + return Ok(process_default( + module_asset_context, + current_source, + Value::new(reference_type), + processed_rules, + )); + } + }, + ModuleRuleEffect::ModuleType(module) => { + current_module_type = Some(*module); + }, + ModuleRuleEffect::ExtendEcmascriptTransforms { prepend, append } => { + current_module_type = match current_module_type { + Some(ModuleType::Ecmascript { transforms, options }) => { + Some(ModuleType::Ecmascript { + transforms:prepend.extend(transforms).extend(*append), + options, + }) + }, + Some(ModuleType::Typescript { + transforms, + tsx, + analyze_types, + options, + }) => { + Some(ModuleType::Typescript { + transforms:prepend.extend(transforms).extend(*append), + tsx, + analyze_types, + options, + }) + }, + Some(ModuleType::Mdx { transforms, options, ecmascript_options }) => { + Some(ModuleType::Mdx { + transforms:prepend.extend(transforms).extend(*append), + options, + ecmascript_options, + }) + }, + Some(module_type) => { + ModuleIssue { + ident, + title:StyledString::Text("Invalid module type".into()).cell(), + description:StyledString::Text( + "The module type must be Ecmascript or Typescript to add \ + Ecmascript transforms" + .into(), + ) + .cell(), + } + .cell() + .emit(); + Some(module_type) + }, + None => { + ModuleIssue { + ident, + title:StyledString::Text("Missing module type".into()).cell(), + description:StyledString::Text( + "The module type effect must be applied before adding \ + Ecmascript transforms" + .into(), + ) + .cell(), + } + .cell() + .emit(); + None + }, + }; + }, + } + } + } + } + + let module_type = match current_module_type { + Some(module_type) => module_type, + None => { + ModuleIssue { + ident, + title: StyledString::Text("Unknown module type".into()).cell(), + description: StyledString::Text( + r"This module doesn't have an associated type. Use a known file extension, or register a loader for it. + +Read more: https://nextjs.org/docs/app/api-reference/next-config-js/turbo#webpack-loaders".into(), + ) + .cell(), + } + .cell() + .emit(); + + return Ok(ProcessResult::Ignore.cell()); + } + }.cell(); + + Ok(apply_module_type( + current_source, + module_asset_context, + module_type, + Value::new(reference_type.clone()), + part, + inner_assets, + matches!(reference_type, ReferenceType::Runtime), + )) +} + +#[turbo_tasks::value_impl] +impl AssetContext for ModuleAssetContext { + #[turbo_tasks::function] + fn compile_time_info(&self) -> Vc { self.compile_time_info } + + #[turbo_tasks::function] + fn layer(&self) -> Vc { self.layer } + + #[turbo_tasks::function] + async fn resolve_options( + self: Vc, + origin_path:Vc, + _reference_type:Value, + ) -> Result> { + let this = self.await?; + let module_asset_context = if let Some(transition) = this.transition { + transition.process_context(self) + } else { + self + }; + // TODO move `apply_commonjs/esm_resolve_options` etc. to here + Ok(resolve_options( + origin_path.parent().resolve().await?, + module_asset_context.await?.resolve_options_context, + )) + } + + #[turbo_tasks::function] + async fn resolve_asset( + self: Vc, + origin_path:Vc, + request:Vc, + resolve_options:Vc, + reference_type:Value, + ) -> Result> { + let context_path = origin_path.parent().resolve().await?; + + let result = resolve(context_path, reference_type.clone(), request, resolve_options); + let mut result = self.process_resolve_result(result.resolve().await?, reference_type); + + if *self.is_types_resolving_enabled().await? { + let types_result = type_resolve( + Vc::upcast(PlainResolveOrigin::new(Vc::upcast(self), origin_path)), + request, + ); + + result = ModuleResolveResult::alternatives(vec![result, types_result]); + } + + Ok(result) + } + + #[turbo_tasks::function] + async fn process_resolve_result( + self: Vc, + result:Vc, + reference_type:Value, + ) -> Result> { + let this = self.await?; + let transition = this.transition; + + let result = result + .await? + .map_module(|source| { + let reference_type = reference_type.clone(); + async move { + let process_result = if let Some(transition) = transition { + transition.process(source, self, reference_type) + } else { + self.process_default(source, reference_type) + }; + Ok(match *process_result.await? { + ProcessResult::Module(m) => ModuleResolveResultItem::Module(Vc::upcast(m)), + ProcessResult::Ignore => ModuleResolveResultItem::Ignore, + }) + } + }) + .await?; + + let result = + replace_externals(result, this.module_options_context.await?.import_externals).await?; + + Ok(result.cell()) + } + + #[turbo_tasks::function] + async fn process( + self: Vc, + asset:Vc>, + reference_type:Value, + ) -> Result> { + let this = self.await?; + if let Some(transition) = this.transition { + Ok(transition.process(asset, self, reference_type)) + } else { + Ok(self.process_default(asset, reference_type)) + } + } + + #[turbo_tasks::function] + async fn with_transition(&self, transition:RcStr) -> Result>> { + Ok(if let Some(transition) = self.transitions.await?.get(&transition) { + Vc::upcast(ModuleAssetContext::new_transition( + self.transitions, + self.compile_time_info, + self.module_options_context, + self.resolve_options_context, + self.layer, + *transition, + )) + } else { + // TODO report issue + Vc::upcast(ModuleAssetContext::new( + self.transitions, + self.compile_time_info, + self.module_options_context, + self.resolve_options_context, + self.layer, + )) + }) + } + + #[turbo_tasks::function] + async fn side_effect_free_packages(self: Vc) -> Result> { + let pkgs = &*self.await?.module_options_context.await?.side_effect_free_packages; + + let mut globs = Vec::with_capacity(pkgs.len()); + + for pkg in pkgs { + globs.push(Glob::new(format!("**/node_modules/{{{}}}/**", pkg).into())); + } + + Ok(Glob::alternatives(globs)) + } +} + +#[turbo_tasks::function] +pub async fn emit_with_completion( + asset:Vc>, + output_dir:Vc, +) -> Vc { + emit_assets_aggregated(asset, output_dir) +} + +#[turbo_tasks::function] +async fn emit_assets_aggregated( + asset:Vc>, + output_dir:Vc, +) -> Vc { + let aggregated = aggregate(asset); + emit_aggregated_assets(aggregated, output_dir) +} + +#[turbo_tasks::function] +async fn emit_aggregated_assets( + aggregated:Vc, + output_dir:Vc, +) -> Result> { + Ok(match &*aggregated.content().await? { + AggregatedGraphNodeContent::Asset(asset) => emit_asset_into_dir(*asset, output_dir), + AggregatedGraphNodeContent::Children(children) => { + for aggregated in children { + emit_aggregated_assets(*aggregated, output_dir).await?; + } + Completion::new() + }, + }) +} + +#[turbo_tasks::function] +pub async fn emit_asset(asset:Vc>) -> Vc { + asset.content().write(asset.ident().path()) +} + +#[turbo_tasks::function] +pub async fn emit_asset_into_dir( + asset:Vc>, + output_dir:Vc, +) -> Result> { + let dir = &*output_dir.await?; + Ok(if asset.ident().path().await?.is_inside_ref(dir) { + emit_asset(asset) + } else { + Completion::new() + }) +} + +type OutputAssetSet = HashSet>>; + +#[turbo_tasks::value(shared)] +struct ReferencesList { + referenced_by:HashMap>, OutputAssetSet>, +} + +#[turbo_tasks::function] +async fn compute_back_references(aggregated:Vc) -> Result> { + Ok(match &*aggregated.content().await? { + &AggregatedGraphNodeContent::Asset(asset) => { + let mut referenced_by = HashMap::new(); + for reference in asset.references().await?.iter() { + referenced_by.insert(*reference, [asset].into_iter().collect()); + } + ReferencesList { referenced_by }.into() + }, + AggregatedGraphNodeContent::Children(children) => { + let mut referenced_by = HashMap::>, OutputAssetSet>::new(); + let lists = + children.iter().map(|child| compute_back_references(*child)).collect::>(); + for list in lists { + for (key, values) in list.await?.referenced_by.iter() { + if let Some(set) = referenced_by.get_mut(key) { + for value in values { + set.insert(*value); + } + } else { + referenced_by.insert(*key, values.clone()); + } + } + } + ReferencesList { referenced_by }.into() + }, + }) +} + +#[turbo_tasks::function] +async fn top_references(list:Vc) -> Result> { + let list = list.await?; + const N:usize = 5; + let mut top = Vec::<(&Vc>, &HashSet>>)>::new(); + for tuple in list.referenced_by.iter() { + let mut current = tuple; + for item in &mut top { + if item.1.len() < tuple.1.len() { + swap(item, &mut current); + } + } + if top.len() < N { + top.push(current); + } + } + Ok(ReferencesList { + referenced_by:top.into_iter().map(|(asset, set)| (*asset, set.clone())).collect(), + } + .into()) +} + +/// Replaces the externals in the result with `ExternalModuleAsset` instances. +pub async fn replace_externals( + mut result:ModuleResolveResult, + import_externals:bool, +) -> Result { + for item in result.primary.values_mut() { + let ModuleResolveResultItem::External(request, ty) = item else { + continue; + }; + + let external_type = match ty { + ExternalType::CommonJs => CachedExternalType::CommonJs, + ExternalType::EcmaScriptModule => { + if import_externals { + CachedExternalType::EcmaScriptViaImport + } else { + CachedExternalType::EcmaScriptViaRequire + } + }, + ExternalType::Url => { + // we don't want to wrap url externals. + continue; + }, + }; + + let module = CachedExternalModule::new(request.clone(), external_type).resolve().await?; + + *item = ModuleResolveResultItem::Module(Vc::upcast(module)); + } + + Ok(result) +} + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_css::register(); + turbopack_ecmascript::register(); + turbopack_node::register(); + turbopack_env::register(); + turbopack_mdx::register(); + turbopack_json::register(); + turbopack_resolve::register(); + turbopack_static::register(); + turbopack_wasm::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack/Source/module_options/custom_module_type.rs b/crates/turbopack/Source/module_options/custom_module_type.rs new file mode 100644 index 0000000000000..68637e8030d44 --- /dev/null +++ b/crates/turbopack/Source/module_options/custom_module_type.rs @@ -0,0 +1,14 @@ +use turbo_tasks::Vc; +use turbopack_core::{module::Module, resolve::ModulePart, source::Source}; + +use crate::ModuleAssetContext; + +#[turbo_tasks::value_trait] +pub trait CustomModuleType { + fn create_module( + self: Vc, + source:Vc>, + module_asset_context:Vc, + part:Option>, + ) -> Vc>; +} diff --git a/crates/turbopack/Source/module_options/mod.rs b/crates/turbopack/Source/module_options/mod.rs new file mode 100644 index 0000000000000..018cc61e6775e --- /dev/null +++ b/crates/turbopack/Source/module_options/mod.rs @@ -0,0 +1,582 @@ +pub(crate) mod custom_module_type; +pub mod module_options_context; +pub mod module_rule; +pub mod rule_condition; + +use anyhow::{Context, Result}; +pub use custom_module_type::CustomModuleType; +pub use module_options_context::*; +pub use module_rule::*; +pub use rule_condition::*; +use turbo_tasks::{RcStr, Vc}; +use turbo_tasks_fs::{FileSystemPath, glob::Glob}; +use turbopack_core::{ + reference_type::{CssReferenceSubType, ReferenceType, UrlReferenceSubType}, + resolve::options::{ImportMap, ImportMapping}, +}; +use turbopack_css::CssModuleAssetType; +use turbopack_ecmascript::{EcmascriptInputTransform, EcmascriptOptions, SpecifiedModuleType}; +use turbopack_node::transforms::{postcss::PostCssTransform, webpack::WebpackLoaders}; +use turbopack_wasm::source::WebAssemblySourceType; + +use crate::{ + evaluate_context::node_evaluate_asset_context, + resolve_options_context::ResolveOptionsContext, +}; + +#[turbo_tasks::function] +async fn package_import_map_from_import_mapping( + package_name:RcStr, + package_mapping:Vc, +) -> Result> { + let mut import_map = ImportMap::default(); + import_map.insert_exact_alias(format!("@vercel/turbopack/{}", package_name), package_mapping); + Ok(import_map.cell()) +} + +#[turbo_tasks::function] +async fn package_import_map_from_context( + package_name:RcStr, + context_path:Vc, +) -> Result> { + let mut import_map = ImportMap::default(); + import_map.insert_exact_alias( + format!("@vercel/turbopack/{}", package_name), + ImportMapping::PrimaryAlternative(package_name, Some(context_path)).cell(), + ); + Ok(import_map.cell()) +} + +#[turbo_tasks::value(cell = "new", eq = "manual")] +pub struct ModuleOptions { + pub rules:Vec, +} + +#[turbo_tasks::value_impl] +impl ModuleOptions { + #[turbo_tasks::function] + pub async fn new( + path:Vc, + module_options_context:Vc, + resolve_options_context:Vc, + ) -> Result> { + let ModuleOptionsContext { + enable_jsx, + enable_types, + tree_shaking_mode, + ref enable_typescript_transform, + ref decorators, + enable_mdx, + enable_mdx_rs, + enable_raw_css, + ref enable_postcss_transform, + ref enable_webpack_loaders, + preset_env_versions, + ref custom_rules, + execution_context, + ref rules, + esm_url_rewrite_behavior, + import_externals, + ignore_dynamic_requests, + use_swc_css, + ref enable_typeof_window_inlining, + .. + } = *module_options_context.await?; + + if !rules.is_empty() { + let path_value = path.await?; + + for (condition, new_context) in rules.iter() { + if condition.matches(&path_value).await? { + return Ok(ModuleOptions::new(path, *new_context, resolve_options_context)); + } + } + } + + let mut refresh = false; + let mut transforms = vec![]; + + // Order of transforms is important. e.g. if the React transform occurs before + // Styled JSX, there won't be JSX nodes for Styled JSX to transform. + // If a custom plugin requires specific order _before_ core transform kicks in, + // should use `before_transform_plugins`. + if let Some(enable_jsx) = enable_jsx { + let jsx = enable_jsx.await?; + refresh = jsx.react_refresh; + + transforms.push(EcmascriptInputTransform::React { + development:jsx.development, + refresh:jsx.react_refresh, + import_source:Vc::cell(jsx.import_source.clone()), + runtime:Vc::cell(jsx.runtime.clone()), + }); + } + + let ecmascript_options = EcmascriptOptions { + tree_shaking_mode, + url_rewrite_behavior:esm_url_rewrite_behavior, + import_externals, + ignore_dynamic_requests, + refresh, + ..Default::default() + }; + let ecmascript_options_vc = ecmascript_options.cell(); + + if let Some(env) = preset_env_versions { + transforms.push(EcmascriptInputTransform::PresetEnv(env)); + } + + if let Some(enable_typeof_window_inlining) = enable_typeof_window_inlining { + transforms.push(EcmascriptInputTransform::GlobalTypeofs { + window_value:match enable_typeof_window_inlining { + TypeofWindow::Object => "object".to_string(), + TypeofWindow::Undefined => "undefined".to_string(), + }, + }); + } + + let ts_transform = if let Some(options) = enable_typescript_transform { + let options = options.await?; + Some(EcmascriptInputTransform::TypeScript { + use_define_for_class_fields:options.use_define_for_class_fields, + }) + } else { + None + }; + + let decorators_transform = if let Some(options) = &decorators { + let options = options.await?; + options.decorators_kind.as_ref().map(|kind| { + EcmascriptInputTransform::Decorators { + is_legacy:kind == &DecoratorsKind::Legacy, + is_ecma:kind == &DecoratorsKind::Ecma, + emit_decorators_metadata:options.emit_decorators_metadata, + use_define_for_class_fields:options.use_define_for_class_fields, + } + }) + } else { + None + }; + + let vendor_transforms = Vc::cell(vec![]); + let ts_app_transforms = if let Some(transform) = &ts_transform { + let base_transforms = if let Some(decorators_transform) = &decorators_transform { + vec![decorators_transform.clone(), transform.clone()] + } else { + vec![transform.clone()] + }; + Vc::cell(base_transforms.iter().cloned().chain(transforms.iter().cloned()).collect()) + } else { + Vc::cell(transforms.clone()) + }; + + let mdx_transforms = Vc::cell( + if let Some(transform) = &ts_transform { + if let Some(decorators_transform) = &decorators_transform { + vec![decorators_transform.clone(), transform.clone()] + } else { + vec![transform.clone()] + } + } else { + vec![] + } + .iter() + .cloned() + .chain(transforms.iter().cloned()) + .collect(), + ); + + // Apply decorators transform for the ModuleType::Ecmascript as well after + // constructing ts_app_transforms. Ecmascript can have decorators for + // the cases of 1. using jsconfig, to enable ts-specific runtime + // decorators (i.e legacy) 2. ecma spec decorators + // + // Since typescript transform (`ts_app_transforms`) needs to apply decorators + // _before_ stripping types, we create ts_app_transforms first in a + // specific order with typescript, then apply decorators to app_transforms. + let app_transforms = Vc::cell( + if let Some(decorators_transform) = &decorators_transform { + vec![decorators_transform.clone()] + } else { + vec![] + } + .iter() + .cloned() + .chain(transforms.iter().cloned()) + .collect(), + ); + + let mut rules = vec![ + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".json".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Json)], + ), + ModuleRule::new_all( + ModuleRuleCondition::any(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".js".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".jsx".to_string()), + ]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Ecmascript { + transforms:app_transforms, + options:ecmascript_options_vc, + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".mjs".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Ecmascript { + transforms:app_transforms, + options:EcmascriptOptions { + specified_module_type:SpecifiedModuleType::EcmaScript, + ..ecmascript_options + } + .into(), + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".cjs".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Ecmascript { + transforms:app_transforms, + options:EcmascriptOptions { + specified_module_type:SpecifiedModuleType::CommonJs, + ..ecmascript_options + } + .into(), + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".ts".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Typescript { + transforms:ts_app_transforms, + tsx:false, + analyze_types:enable_types, + options:ecmascript_options_vc, + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".tsx".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Typescript { + transforms:ts_app_transforms, + tsx:true, + analyze_types:enable_types, + options:ecmascript_options_vc, + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".mts".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Typescript { + transforms:ts_app_transforms, + tsx:false, + analyze_types:enable_types, + options:EcmascriptOptions { + specified_module_type:SpecifiedModuleType::EcmaScript, + ..ecmascript_options + } + .into(), + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".mtsx".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Typescript { + transforms:ts_app_transforms, + tsx:true, + analyze_types:enable_types, + options:EcmascriptOptions { + specified_module_type:SpecifiedModuleType::EcmaScript, + ..ecmascript_options + } + .into(), + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".cts".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Typescript { + transforms:ts_app_transforms, + tsx:false, + analyze_types:enable_types, + options:EcmascriptOptions { + specified_module_type:SpecifiedModuleType::CommonJs, + ..ecmascript_options + } + .into(), + })], + ), + ModuleRule::new_all( + ModuleRuleCondition::ResourcePathEndsWith(".ctsx".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Typescript { + transforms:ts_app_transforms, + tsx:true, + analyze_types:enable_types, + options:EcmascriptOptions { + specified_module_type:SpecifiedModuleType::CommonJs, + ..ecmascript_options + } + .into(), + })], + ), + ModuleRule::new( + ModuleRuleCondition::ResourcePathEndsWith(".d.ts".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::TypescriptDeclaration { + transforms:vendor_transforms, + options:ecmascript_options_vc, + })], + ), + ModuleRule::new( + ModuleRuleCondition::any(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".apng".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".avif".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".gif".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".ico".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".jpg".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".jpeg".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".png".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".svg".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".webp".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".woff2".to_string()), + ]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Static)], + ), + ModuleRule::new( + ModuleRuleCondition::any(vec![ModuleRuleCondition::ResourcePathEndsWith( + ".node".to_string(), + )]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Raw)], + ), + ModuleRule::new( + ModuleRuleCondition::any(vec![ModuleRuleCondition::ResourcePathEndsWith( + ".wasm".to_string(), + )]), + vec![ModuleRuleEffect::ModuleType(ModuleType::WebAssembly { + source_ty:WebAssemblySourceType::Binary, + })], + ), + ModuleRule::new( + ModuleRuleCondition::any(vec![ModuleRuleCondition::ResourcePathEndsWith( + ".wat".to_string(), + )]), + vec![ModuleRuleEffect::ModuleType(ModuleType::WebAssembly { + source_ty:WebAssemblySourceType::Text, + })], + ), + ModuleRule::new( + ModuleRuleCondition::ResourcePathHasNoExtension, + vec![ModuleRuleEffect::ModuleType(ModuleType::Ecmascript { + transforms:vendor_transforms, + options:ecmascript_options_vc, + })], + ), + ModuleRule::new( + ModuleRuleCondition::ReferenceType(ReferenceType::Url( + UrlReferenceSubType::Undefined, + )), + vec![ModuleRuleEffect::ModuleType(ModuleType::Static)], + ), + ]; + + if enable_raw_css { + rules.extend([ + ModuleRule::new( + ModuleRuleCondition::all(vec![ModuleRuleCondition::ResourcePathEndsWith( + ".css".to_string(), + )]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Css { + ty:CssModuleAssetType::Default, + use_swc_css, + })], + ), + ModuleRule::new( + ModuleRuleCondition::all(vec![ModuleRuleCondition::ResourcePathEndsWith( + ".module.css".to_string(), + )]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Css { + ty:CssModuleAssetType::Module, + use_swc_css, + })], + ), + ]); + } else { + if let Some(options) = enable_postcss_transform { + let options = options.await?; + let execution_context = execution_context + .context("execution_context is required for the postcss_transform")?; + + let import_map = if let Some(postcss_package) = options.postcss_package { + package_import_map_from_import_mapping("postcss".into(), postcss_package) + } else { + package_import_map_from_context("postcss".into(), path) + }; + + rules.push(ModuleRule::new( + ModuleRuleCondition::ResourcePathEndsWith(".css".to_string()), + vec![ModuleRuleEffect::SourceTransforms(Vc::cell(vec![Vc::upcast( + PostCssTransform::new( + node_evaluate_asset_context( + execution_context, + Some(import_map), + None, + "postcss".into(), + ), + execution_context, + options.config_location, + ), + )]))], + )); + } + + rules.extend([ + ModuleRule::new( + ModuleRuleCondition::all(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".css".to_string()), + // Only create a global CSS asset if not `@import`ed from CSS already. + ModuleRuleCondition::not(ModuleRuleCondition::ReferenceType( + ReferenceType::Css(CssReferenceSubType::AtImport(None)), + )), + ]), + vec![ModuleRuleEffect::ModuleType(ModuleType::CssGlobal)], + ), + ModuleRule::new( + ModuleRuleCondition::all(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".module.css".to_string()), + // Only create a module CSS asset if not `@import`ed from CSS already. + // NOTE: `composes` references should not be treated as `@import`s and + // should also create a module CSS asset. + ModuleRuleCondition::not(ModuleRuleCondition::ReferenceType( + ReferenceType::Css(CssReferenceSubType::AtImport(None)), + )), + ]), + vec![ModuleRuleEffect::ModuleType(ModuleType::CssModule)], + ), + ModuleRule::new( + ModuleRuleCondition::all(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".css".to_string()), + // Create a normal CSS asset if `@import`ed from CSS already. + ModuleRuleCondition::ReferenceType(ReferenceType::Css( + CssReferenceSubType::AtImport(None), + )), + ]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Css { + ty:CssModuleAssetType::Default, + use_swc_css, + })], + ), + ModuleRule::new( + ModuleRuleCondition::all(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".module.css".to_string()), + // Create a normal CSS asset if `@import`ed from CSS already. + ModuleRuleCondition::ReferenceType(ReferenceType::Css( + CssReferenceSubType::AtImport(None), + )), + ]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Css { + ty:CssModuleAssetType::Module, + use_swc_css, + })], + ), + ModuleRule::new_internal( + ModuleRuleCondition::ResourcePathEndsWith(".css".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Css { + ty:CssModuleAssetType::Default, + use_swc_css, + })], + ), + ModuleRule::new_internal( + ModuleRuleCondition::ResourcePathEndsWith(".module.css".to_string()), + vec![ModuleRuleEffect::ModuleType(ModuleType::Css { + ty:CssModuleAssetType::Module, + use_swc_css, + })], + ), + ]); + } + + if enable_mdx || enable_mdx_rs.is_some() { + let (jsx_runtime, jsx_import_source) = if let Some(enable_jsx) = enable_jsx { + let jsx = enable_jsx.await?; + (jsx.runtime.clone(), jsx.import_source.clone()) + } else { + (None, None) + }; + + let mdx_options = &*enable_mdx_rs.unwrap_or(Default::default()).await?; + + let mdx_transform_options = (MdxTransformOptions { + development:Some(true), + jsx:Some(false), + jsx_runtime, + jsx_import_source, + ..(mdx_options.clone()) + }) + .cell(); + + rules.push(ModuleRule::new( + ModuleRuleCondition::any(vec![ + ModuleRuleCondition::ResourcePathEndsWith(".md".to_string()), + ModuleRuleCondition::ResourcePathEndsWith(".mdx".to_string()), + ]), + vec![ModuleRuleEffect::ModuleType(ModuleType::Mdx { + transforms:mdx_transforms, + options:mdx_transform_options, + ecmascript_options:ecmascript_options_vc, + })], + )); + } + + if let Some(webpack_loaders_options) = enable_webpack_loaders { + let webpack_loaders_options = webpack_loaders_options.await?; + let execution_context = + execution_context.context("execution_context is required for webpack_loaders")?; + let import_map = if let Some(loader_runner_package) = + webpack_loaders_options.loader_runner_package + { + package_import_map_from_import_mapping( + "loader-runner".into(), + loader_runner_package, + ) + } else { + package_import_map_from_context("loader-runner".into(), path) + }; + for (glob, rule) in webpack_loaders_options.rules.await?.iter() { + rules.push(ModuleRule::new( + ModuleRuleCondition::All(vec![ + if !glob.contains('/') { + ModuleRuleCondition::ResourceBasePathGlob( + Glob::new(glob.clone()).await?, + ) + } else { + ModuleRuleCondition::ResourcePathGlob { + base:execution_context.project_path().await?, + glob:Glob::new(glob.clone()).await?, + } + }, + ModuleRuleCondition::not(ModuleRuleCondition::ResourceIsVirtualSource), + ]), + vec![ + // By default, loaders are expected to return ecmascript code. + // This can be overriden by specifying e. g. `as: "*.css"` in the rule. + ModuleRuleEffect::ModuleType(ModuleType::Ecmascript { + transforms:app_transforms, + options:ecmascript_options_vc, + }), + ModuleRuleEffect::SourceTransforms(Vc::cell(vec![Vc::upcast( + WebpackLoaders::new( + node_evaluate_asset_context( + execution_context, + Some(import_map), + None, + "webpack_loaders".into(), + ), + execution_context, + rule.loaders, + rule.rename_as.clone(), + resolve_options_context, + ), + )])), + ], + )); + } + } + + rules.extend(custom_rules.iter().cloned()); + + Ok(ModuleOptions::cell(ModuleOptions { rules })) + } +} diff --git a/crates/turbopack/Source/module_options/module_options_context.rs b/crates/turbopack/Source/module_options/module_options_context.rs new file mode 100644 index 0000000000000..c92f3cd37fc92 --- /dev/null +++ b/crates/turbopack/Source/module_options/module_options_context.rs @@ -0,0 +1,159 @@ +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{RcStr, ValueDefault, Vc, trace::TraceRawVcs}; +use turbopack_core::{ + condition::ContextCondition, + environment::Environment, + resolve::options::ImportMapping, +}; +use turbopack_ecmascript::{TreeShakingMode, references::esm::UrlRewriteBehavior}; +pub use turbopack_mdx::MdxTransformOptions; +use turbopack_node::{ + execution_context::ExecutionContext, + transforms::{postcss::PostCssTransformOptions, webpack::WebpackLoaderItems}, +}; + +use super::ModuleRule; + +#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] +pub struct LoaderRuleItem { + pub loaders:Vc, + pub rename_as:Option, +} + +#[derive(Default)] +#[turbo_tasks::value(transparent)] +pub struct WebpackRules(IndexMap); + +#[derive(Default)] +#[turbo_tasks::value(transparent)] +pub struct OptionWebpackRules(Option>); + +#[turbo_tasks::value(shared)] +#[derive(Clone, Debug)] +pub struct WebpackLoadersOptions { + pub rules:Vc, + pub loader_runner_package:Option>, +} + +#[derive(Default)] +#[turbo_tasks::value(transparent)] +pub struct OptionWebpackLoadersOptions(Option>); + +/// The kind of decorators transform to use. +/// [TODO]: might need bikeshed for the name (Ecma) +#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] +pub enum DecoratorsKind { + Legacy, + Ecma, +} + +/// The types when replacing `typeof window` with a constant. +#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] +pub enum TypeofWindow { + Object, + Undefined, +} + +/// Configuration options for the decorators transform. +/// This is not part of Typescript transform: while there are typescript +/// specific transforms (legay decorators), there is an ecma decorator transform +/// as well for the JS. +#[turbo_tasks::value(shared)] +#[derive(Default, Clone, Debug)] +pub struct DecoratorsOptions { + pub decorators_kind:Option, + /// Option to control whether to emit decorator metadata. + /// (https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata) + /// This'll be applied only if `decorators_type` and + /// `enable_typescript_transform` is enabled. + pub emit_decorators_metadata:bool, + /// Mimic babel's `decorators.decoratorsBeforeExport` option. + /// This'll be applied only if `decorators_type` is enabled. + /// ref: https://github.com/swc-project/swc/blob/d4ebb5e6efbed0758f25e46e8f74d7c47ec6cb8f/crates/swc_ecma_parser/src/lib.rs#L327 + /// [TODO]: this option is not actively being used currently. + pub decorators_before_export:bool, + pub use_define_for_class_fields:bool, +} + +#[turbo_tasks::value_impl] +impl ValueDefault for DecoratorsOptions { + #[turbo_tasks::function] + fn value_default() -> Vc { Self::default().cell() } +} + +/// Subset of Typescript options configured via tsconfig.json or jsconfig.json, +/// which affects the runtime transform output. +#[turbo_tasks::value(shared)] +#[derive(Default, Clone, Debug)] +pub struct TypescriptTransformOptions { + pub use_define_for_class_fields:bool, +} + +#[turbo_tasks::value_impl] +impl ValueDefault for TypescriptTransformOptions { + #[turbo_tasks::function] + fn value_default() -> Vc { Self::default().cell() } +} + +// [TODO]: should enabled_react_refresh belong to this options? +#[turbo_tasks::value(shared)] +#[derive(Default, Clone, Debug)] +pub struct JsxTransformOptions { + pub development:bool, + pub react_refresh:bool, + pub import_source:Option, + pub runtime:Option, +} + +#[turbo_tasks::value(shared)] +#[derive(Clone, Default)] +#[serde(default)] +pub struct ModuleOptionsContext { + pub enable_typeof_window_inlining:Option, + pub enable_jsx:Option>, + pub enable_postcss_transform:Option>, + pub enable_webpack_loaders:Option>, + /// Follow type references and resolve declaration files in additional to + /// normal resolution. + pub enable_types:bool, + pub enable_typescript_transform:Option>, + pub decorators:Option>, + pub enable_mdx:bool, + /// This skips `GlobalCss` and `ModuleCss` module assets from being + /// generated in the module graph, generating only `Css` module assets. + /// + /// This is useful for node-file-trace, which tries to emit all assets in + /// the module graph, but neither asset types can be emitted directly. + pub enable_raw_css:bool, + // [Note]: currently mdx, and mdx_rs have different configuration entrypoint from next.config.js, + // however we might want to unify them in the future. + pub enable_mdx_rs:Option>, + pub preset_env_versions:Option>, + /// Custom rules to be applied after all default rules. + pub custom_rules:Vec, + pub execution_context:Option>, + /// A list of rules to use a different module option context for certain + /// context paths. The first matching is used. + pub rules:Vec<(ContextCondition, Vc)>, + pub placeholder_for_future_extensions:(), + pub tree_shaking_mode:Option, + pub esm_url_rewrite_behavior:Option, + /// References to externals from ESM imports should use `import()` and make + /// async modules. + pub import_externals:bool, + /// Ignore very dynamic requests which doesn't have any static known part. + /// If false, they will reference the whole directory. If true, they won't + /// reference anything and lead to an runtime error instead. + pub ignore_dynamic_requests:bool, + + pub use_swc_css:bool, + + pub side_effect_free_packages:Vec, +} + +#[turbo_tasks::value_impl] +impl ValueDefault for ModuleOptionsContext { + #[turbo_tasks::function] + fn value_default() -> Vc { Self::cell(Default::default()) } +} diff --git a/crates/turbopack/Source/module_options/module_rule.rs b/crates/turbopack/Source/module_options/module_rule.rs new file mode 100644 index 0000000000000..1743adf497342 --- /dev/null +++ b/crates/turbopack/Source/module_options/module_rule.rs @@ -0,0 +1,129 @@ +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{Vc, trace::TraceRawVcs}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + reference_type::ReferenceType, + source::Source, + source_transform::SourceTransforms, +}; +use turbopack_css::CssModuleAssetType; +use turbopack_ecmascript::{EcmascriptInputTransforms, EcmascriptOptions}; +use turbopack_mdx::MdxTransformOptions; +use turbopack_wasm::source::WebAssemblySourceType; + +use super::{CustomModuleType, ModuleRuleCondition}; + +#[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq)] +pub struct ModuleRule { + condition:ModuleRuleCondition, + effects:Vec, + match_mode:MatchMode, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] +enum MatchMode { + // Match all but internal references. + NonInternal, + // Only match internal references. + Internal, + // Match both internal and non-internal references. + All, +} + +impl MatchMode { + fn matches(&self, reference_type:&ReferenceType) -> bool { + matches!( + (self, reference_type.is_internal()), + (MatchMode::All, _) | (MatchMode::NonInternal, false) | (MatchMode::Internal, true) + ) + } +} + +impl ModuleRule { + /// Creates a new module rule. Will not match internal references. + pub fn new(condition:ModuleRuleCondition, effects:Vec) -> Self { + ModuleRule { condition, effects, match_mode:MatchMode::NonInternal } + } + + /// Creates a new module rule. Will only matches internal references. + pub fn new_internal(condition:ModuleRuleCondition, effects:Vec) -> Self { + ModuleRule { condition, effects, match_mode:MatchMode::Internal } + } + + /// Creates a new module rule. Will only matches internal references. + pub fn new_all(condition:ModuleRuleCondition, effects:Vec) -> Self { + ModuleRule { condition, effects, match_mode:MatchMode::All } + } + + pub fn effects(&self) -> impl Iterator { self.effects.iter() } + + pub async fn matches( + &self, + source:Vc>, + path:&FileSystemPath, + reference_type:&ReferenceType, + ) -> Result { + Ok(self.match_mode.matches(reference_type) + && self.condition.matches(source, path, reference_type).await?) + } +} + +#[turbo_tasks::value(shared)] +#[derive(Debug, Clone)] +pub enum ModuleRuleEffect { + ModuleType(ModuleType), + /// Allow to extend an existing Ecmascript module rules for the additional + /// transforms. First argument will prepend the existing transforms, and + /// the second argument will append the new transforms. + ExtendEcmascriptTransforms { + prepend:Vc, + append:Vc, + }, + SourceTransforms(Vc), +} + +#[turbo_tasks::value(serialization = "auto_for_input", shared)] +#[derive(PartialOrd, Ord, Hash, Debug, Copy, Clone)] +pub enum ModuleType { + Ecmascript { + transforms:Vc, + #[turbo_tasks(trace_ignore)] + options:Vc, + }, + Typescript { + transforms:Vc, + // parse JSX syntax. + tsx:bool, + // follow references to imported types. + analyze_types:bool, + #[turbo_tasks(trace_ignore)] + options:Vc, + }, + TypescriptDeclaration { + transforms:Vc, + #[turbo_tasks(trace_ignore)] + options:Vc, + }, + Json, + Raw, + // [TODO] We want to consolidate mdx as a type of ecma|typescript module types with + // its source transform. Refer `turbopack-mdx::into_ecmascript_module_asset` for the reason + // why we keep this separately. + Mdx { + transforms:Vc, + options:Vc, + ecmascript_options:Vc, + }, + CssGlobal, + CssModule, + Css { + ty:CssModuleAssetType, + use_swc_css:bool, + }, + Static, + WebAssembly { + source_ty:WebAssemblySourceType, + }, + Custom(Vc>), +} diff --git a/crates/turbopack/Source/module_options/rule_condition.rs b/crates/turbopack/Source/module_options/rule_condition.rs new file mode 100644 index 0000000000000..b328e45562381 --- /dev/null +++ b/crates/turbopack/Source/module_options/rule_condition.rs @@ -0,0 +1,117 @@ +use anyhow::Result; +use async_recursion::async_recursion; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{ReadRef, Vc, primitives::Regex, trace::TraceRawVcs}; +use turbo_tasks_fs::{FileSystemPath, glob::Glob}; +use turbopack_core::{ + reference_type::ReferenceType, + source::Source, + virtual_source::VirtualSource, +}; + +#[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq)] +pub enum ModuleRuleCondition { + All(Vec), + Any(Vec), + Not(Box), + ReferenceType(ReferenceType), + ResourceIsVirtualSource, + ResourcePathEquals(ReadRef), + ResourcePathHasNoExtension, + ResourcePathEndsWith(String), + ResourcePathInDirectory(String), + ResourcePathInExactDirectory(ReadRef), + ResourcePathRegex(#[turbo_tasks(trace_ignore)] Regex), + /// For paths that are within the same filesystem as the `base`, it need to + /// match the relative path from base to resource. This includes `./` or + /// `../` prefix. For paths in a different filesystem, it need to match + /// the resource path in that filesystem without any prefix. This means + /// any glob starting with `./` or `../` will only match paths in the + /// project. Globs starting with `**` can match any path. + ResourcePathGlob { + base:ReadRef, + #[turbo_tasks(trace_ignore)] + glob:ReadRef, + }, + ResourceBasePathGlob(#[turbo_tasks(trace_ignore)] ReadRef), +} + +impl ModuleRuleCondition { + pub fn all(conditions:Vec) -> ModuleRuleCondition { + ModuleRuleCondition::All(conditions) + } + + pub fn any(conditions:Vec) -> ModuleRuleCondition { + ModuleRuleCondition::Any(conditions) + } + + #[allow(clippy::should_implement_trait)] + pub fn not(condition:ModuleRuleCondition) -> ModuleRuleCondition { + ModuleRuleCondition::Not(Box::new(condition)) + } +} + +impl ModuleRuleCondition { + #[async_recursion] + pub async fn matches( + &self, + source:Vc>, + path:&FileSystemPath, + reference_type:&ReferenceType, + ) -> Result { + Ok(match self { + ModuleRuleCondition::All(conditions) => { + for condition in conditions { + if !condition.matches(source, path, reference_type).await? { + return Ok(false); + } + } + true + }, + ModuleRuleCondition::Any(conditions) => { + for condition in conditions { + if condition.matches(source, path, reference_type).await? { + return Ok(true); + } + } + false + }, + ModuleRuleCondition::Not(condition) => { + !condition.matches(source, path, reference_type).await? + }, + ModuleRuleCondition::ResourcePathEquals(other) => path == &**other, + ModuleRuleCondition::ResourcePathEndsWith(end) => path.path.ends_with(end), + ModuleRuleCondition::ResourcePathHasNoExtension => { + if let Some(i) = path.path.rfind('.') { + if let Some(j) = path.path.rfind('/') { j > i } else { false } + } else { + true + } + }, + ModuleRuleCondition::ResourcePathInDirectory(dir) => { + path.path.starts_with(&format!("{dir}/")) || path.path.contains(&format!("/{dir}/")) + }, + ModuleRuleCondition::ResourcePathInExactDirectory(parent_path) => { + path.is_inside_ref(parent_path) + }, + ModuleRuleCondition::ReferenceType(condition_ty) => { + condition_ty.includes(reference_type) + }, + ModuleRuleCondition::ResourceIsVirtualSource => { + Vc::try_resolve_downcast_type::(source).await?.is_some() + }, + ModuleRuleCondition::ResourcePathGlob { glob, base } => { + if let Some(path) = base.get_relative_path_to(path) { + glob.execute(&path) + } else { + glob.execute(&path.path) + } + }, + ModuleRuleCondition::ResourceBasePathGlob(glob) => { + let basename = path.path.rsplit_once('/').map_or(path.path.as_str(), |(_, b)| b); + glob.execute(basename) + }, + _ => todo!("not implemented yet"), + }) + } +} diff --git a/crates/turbopack/Source/rebase/mod.rs b/crates/turbopack/Source/rebase/mod.rs new file mode 100644 index 0000000000000..2e24db88521ec --- /dev/null +++ b/crates/turbopack/Source/rebase/mod.rs @@ -0,0 +1,61 @@ +use std::hash::Hash; + +use anyhow::Result; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::{ + asset::{Asset, AssetContent}, + ident::AssetIdent, + module::Module, + output::{OutputAsset, OutputAssets}, + reference::referenced_modules_and_affecting_sources, +}; + +/// Converts a [Module] graph into an [OutputAsset] graph by placing it into a +/// different directory. +#[turbo_tasks::value] +#[derive(Hash)] +pub struct RebasedAsset { + source:Vc>, + input_dir:Vc, + output_dir:Vc, +} + +#[turbo_tasks::value_impl] +impl RebasedAsset { + #[turbo_tasks::function] + pub fn new( + source:Vc>, + input_dir:Vc, + output_dir:Vc, + ) -> Vc { + Self::cell(RebasedAsset { source, input_dir, output_dir }) + } +} + +#[turbo_tasks::value_impl] +impl OutputAsset for RebasedAsset { + #[turbo_tasks::function] + fn ident(&self) -> Vc { + AssetIdent::from_path(FileSystemPath::rebase( + self.source.ident().path(), + self.input_dir, + self.output_dir, + )) + } + + #[turbo_tasks::function] + async fn references(&self) -> Result> { + let mut references = Vec::new(); + for &module in referenced_modules_and_affecting_sources(self.source).await?.iter() { + references.push(Vc::upcast(RebasedAsset::new(module, self.input_dir, self.output_dir))); + } + Ok(Vc::cell(references)) + } +} + +#[turbo_tasks::value_impl] +impl Asset for RebasedAsset { + #[turbo_tasks::function] + fn content(&self) -> Vc { self.source.content() } +} diff --git a/crates/turbopack/Source/transition/context_transition.rs b/crates/turbopack/Source/transition/context_transition.rs new file mode 100644 index 0000000000000..f9ac3f2ac73af --- /dev/null +++ b/crates/turbopack/Source/transition/context_transition.rs @@ -0,0 +1,64 @@ +use anyhow::Result; +use turbo_tasks::{RcStr, Vc}; +use turbopack_core::compile_time_info::CompileTimeInfo; +use turbopack_resolve::resolve_options_context::ResolveOptionsContext; + +use crate::{module_options::ModuleOptionsContext, transition::Transition}; + +/// A transition that only affects the asset context. +#[turbo_tasks::value(shared)] +pub struct ContextTransition { + compile_time_info:Vc, + module_options_context:Vc, + resolve_options_context:Vc, + layer:Vc, +} + +#[turbo_tasks::value_impl] +impl ContextTransition { + #[turbo_tasks::function] + pub async fn new( + compile_time_info:Vc, + module_options_context:Vc, + resolve_options_context:Vc, + layer:Vc, + ) -> Result> { + Ok(ContextTransition { + module_options_context, + resolve_options_context, + compile_time_info, + layer, + } + .cell()) + } +} + +#[turbo_tasks::value_impl] +impl Transition for ContextTransition { + #[turbo_tasks::function] + fn process_compile_time_info( + &self, + _compile_time_info:Vc, + ) -> Vc { + self.compile_time_info + } + + #[turbo_tasks::function] + fn process_layer(&self, _layer:Vc) -> Vc { self.layer } + + #[turbo_tasks::function] + fn process_module_options_context( + &self, + _context:Vc, + ) -> Vc { + self.module_options_context + } + + #[turbo_tasks::function] + fn process_resolve_options_context( + &self, + _context:Vc, + ) -> Vc { + self.resolve_options_context + } +} diff --git a/crates/turbopack/Source/transition/full_context_transition.rs b/crates/turbopack/Source/transition/full_context_transition.rs new file mode 100644 index 0000000000000..0dcf5cb3e75c0 --- /dev/null +++ b/crates/turbopack/Source/transition/full_context_transition.rs @@ -0,0 +1,29 @@ +use anyhow::Result; +use turbo_tasks::Vc; + +use crate::{ModuleAssetContext, transition::Transition}; + +/// A transition that only affects the asset context. +#[turbo_tasks::value(shared)] +pub struct FullContextTransition { + module_context:Vc, +} + +#[turbo_tasks::value_impl] +impl FullContextTransition { + #[turbo_tasks::function] + pub async fn new(module_context:Vc) -> Result> { + Ok(FullContextTransition { module_context }.cell()) + } +} + +#[turbo_tasks::value_impl] +impl Transition for FullContextTransition { + #[turbo_tasks::function] + fn process_context( + &self, + _module_asset_context:Vc, + ) -> Vc { + self.module_context + } +} diff --git a/crates/turbopack/Source/transition/mod.rs b/crates/turbopack/Source/transition/mod.rs new file mode 100644 index 0000000000000..c54900e5480ee --- /dev/null +++ b/crates/turbopack/Source/transition/mod.rs @@ -0,0 +1,108 @@ +pub(crate) mod context_transition; +pub(crate) mod full_context_transition; + +use std::collections::HashMap; + +use anyhow::Result; +pub use context_transition::ContextTransition; +pub use full_context_transition::FullContextTransition; +use turbo_tasks::{RcStr, Value, ValueDefault, Vc}; +use turbopack_core::{ + compile_time_info::CompileTimeInfo, + context::ProcessResult, + module::Module, + reference_type::ReferenceType, + source::Source, +}; +use turbopack_resolve::resolve_options_context::ResolveOptionsContext; + +use crate::{ModuleAssetContext, module_options::ModuleOptionsContext}; + +/// Some kind of operation that is executed during reference processing. e. g. +/// you can transition to a different environment on a specific import +/// (reference). +#[turbo_tasks::value_trait] +pub trait Transition { + /// Apply modifications/wrapping to the source asset + fn process_source(self: Vc, asset:Vc>) -> Vc> { asset } + /// Apply modifications to the compile-time information + fn process_compile_time_info( + self: Vc, + compile_time_info:Vc, + ) -> Vc { + compile_time_info + } + /// Apply modifications to the layer + fn process_layer(self: Vc, layer:Vc) -> Vc { layer } + /// Apply modifications/wrapping to the module options context + fn process_module_options_context( + self: Vc, + module_options_context:Vc, + ) -> Vc { + module_options_context + } + /// Apply modifications/wrapping to the resolve options context + fn process_resolve_options_context( + self: Vc, + resolve_options_context:Vc, + ) -> Vc { + resolve_options_context + } + /// Apply modifications/wrapping to the final asset + fn process_module( + self: Vc, + module:Vc>, + _context:Vc, + ) -> Vc> { + module + } + /// Apply modifications to the context + async fn process_context( + self: Vc, + module_asset_context:Vc, + ) -> Result> { + let module_asset_context = module_asset_context.await?; + let compile_time_info = + self.process_compile_time_info(module_asset_context.compile_time_info); + let module_options_context = + self.process_module_options_context(module_asset_context.module_options_context); + let resolve_options_context = + self.process_resolve_options_context(module_asset_context.resolve_options_context); + let layer = self.process_layer(module_asset_context.layer); + let module_asset_context = ModuleAssetContext::new( + module_asset_context.transitions, + compile_time_info, + module_options_context, + resolve_options_context, + layer, + ); + Ok(module_asset_context) + } + /// Apply modification on the processing of the asset + async fn process( + self: Vc, + asset:Vc>, + module_asset_context:Vc, + reference_type:Value, + ) -> Result> { + let asset = self.process_source(asset); + let module_asset_context = self.process_context(module_asset_context); + let m = module_asset_context.process_default(asset, reference_type); + Ok(match *m.await? { + ProcessResult::Module(m) => { + ProcessResult::Module(self.process_module(m, module_asset_context)) + }, + ProcessResult::Ignore => ProcessResult::Ignore, + } + .cell()) + } +} + +#[turbo_tasks::value(transparent)] +pub struct TransitionsByName(HashMap>>); + +#[turbo_tasks::value_impl] +impl ValueDefault for TransitionsByName { + #[turbo_tasks::function] + fn value_default() -> Vc { Vc::cell(Default::default()) } +} diff --git a/crates/turbopack/Source/unsupported_sass.rs b/crates/turbopack/Source/unsupported_sass.rs new file mode 100644 index 0000000000000..039086a68fef0 --- /dev/null +++ b/crates/turbopack/Source/unsupported_sass.rs @@ -0,0 +1,88 @@ +//! TODO(WEB-741) Remove this file once Sass is supported. + +use anyhow::Result; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::{FileSystemPath, glob::Glob}; +use turbopack_core::{ + issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, + reference_type::ReferenceType, + resolve::{ + ResolveResultOption, + parse::Request, + plugin::{AfterResolvePlugin, AfterResolvePluginCondition}, + }, +}; + +/// Resolve plugins that warns when importing a sass file. +#[turbo_tasks::value] +pub(crate) struct UnsupportedSassResolvePlugin { + root:Vc, +} + +#[turbo_tasks::value_impl] +impl UnsupportedSassResolvePlugin { + #[turbo_tasks::function] + pub fn new(root:Vc) -> Vc { UnsupportedSassResolvePlugin { root }.cell() } +} + +#[turbo_tasks::value_impl] +impl AfterResolvePlugin for UnsupportedSassResolvePlugin { + #[turbo_tasks::function] + fn after_resolve_condition(&self) -> Vc { + AfterResolvePluginCondition::new(self.root.root(), Glob::new("**/*.{sass,scss}".into())) + } + + #[turbo_tasks::function] + async fn after_resolve( + &self, + fs_path:Vc, + lookup_path:Vc, + _reference_type:Value, + request:Vc, + ) -> Result> { + let extension = fs_path.extension().await?; + if ["sass", "scss"].iter().any(|ext| *ext == &**extension) { + UnsupportedSassModuleIssue { file_path:lookup_path, request }.cell().emit(); + } + + Ok(ResolveResultOption::none()) + } +} + +#[turbo_tasks::value(shared)] +struct UnsupportedSassModuleIssue { + file_path:Vc, + request:Vc, +} + +#[turbo_tasks::value_impl] +impl Issue for UnsupportedSassModuleIssue { + #[turbo_tasks::function] + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } + + #[turbo_tasks::function] + async fn title(&self) -> Result> { + Ok(StyledString::Text( + format!( + "Unsupported Sass request: {}", + self.request.await?.request().as_deref().unwrap_or("N/A") + ) + .into(), + ) + .cell()) + } + + #[turbo_tasks::function] + fn file_path(&self) -> Vc { self.file_path } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some( + StyledString::Text("Turbopack does not yet support importing Sass modules.".into()) + .cell(), + )) + } + + #[turbo_tasks::function] + fn stage(&self) -> Vc { IssueStage::Unsupported.cell() } +} diff --git a/crates/turbopack/benches/mod.rs b/crates/turbopack/benches/mod.rs new file mode 100644 index 0000000000000..b1d1f6d977a1f --- /dev/null +++ b/crates/turbopack/benches/mod.rs @@ -0,0 +1,6 @@ +use criterion::{criterion_group, criterion_main}; + +mod node_file_trace; + +criterion_group!(node_file_trace_benches, node_file_trace::benchmark); +criterion_main!(node_file_trace_benches); diff --git a/crates/turbopack/benches/node_file_trace.rs b/crates/turbopack/benches/node_file_trace.rs new file mode 100644 index 0000000000000..251f280b25b06 --- /dev/null +++ b/crates/turbopack/benches/node_file_trace.rs @@ -0,0 +1,110 @@ +use std::{collections::HashMap, fs, path::PathBuf}; + +use criterion::{Bencher, BenchmarkId, Criterion}; +use regex::Regex; +use turbo_tasks::{RcStr, TurboTasks, Value, Vc}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem, NullFileSystem}; +use turbo_tasks_memory::MemoryBackend; +use turbopack::{ + ModuleAssetContext, + emit_with_completion, + module_options::ModuleOptionsContext, + rebase::RebasedAsset, + register, +}; +use turbopack_core::{ + compile_time_info::CompileTimeInfo, + context::AssetContext, + environment::{Environment, ExecutionEnvironment, NodeJsEnvironment}, + file_source::FileSource, + reference_type::ReferenceType, +}; +use turbopack_resolve::resolve_options_context::ResolveOptionsContext; + +// TODO this should move to the `node-file-trace` crate +pub fn benchmark(c:&mut Criterion) { + register(); + + let bench_filter = Regex::new(r"(empty|simple|dynamic-in-package|react|whatwg-url|axios|azure-cosmos|cowsay|env-var|fast-glob)\.js$").unwrap(); + + let tests_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests"); + let tests_dir = tests_root.join("node-file-trace/integration"); + + let mut group = c.benchmark_group("node-file-trace"); + group.sample_size(10); + + let results = fs::read_dir(tests_dir).unwrap(); + for result in results { + let entry = result.unwrap(); + if entry.file_type().unwrap().is_file() { + let name = entry.file_name().into_string().unwrap(); + if !bench_filter.is_match(&name) { + continue; + } + + let input = format!("node-file-trace/integration/{name}"); + let tests_root = tests_root.to_string_lossy().to_string(); + + let bench_input = BenchInput { tests_root, input }; + + group.bench_with_input( + BenchmarkId::new("emit", &bench_input.input), + &bench_input, + bench_emit, + ); + } + } + + group.finish(); +} + +struct BenchInput { + tests_root:String, + input:String, +} + +fn bench_emit(b:&mut Bencher, bench_input:&BenchInput) { + let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); + + b.to_async(rt).iter(move || { + let tt = TurboTasks::new(MemoryBackend::default()); + let tests_root:RcStr = bench_input.tests_root.clone().into(); + let input:RcStr = bench_input.input.clone().into(); + async move { + let task = tt.spawn_once_task(async move { + let input_fs = DiskFileSystem::new("tests".into(), tests_root.clone(), vec![]); + let input = input_fs.root().join(input.clone()); + + let input_dir = input.parent().parent(); + let output_fs:Vc = NullFileSystem.into(); + let output_dir = output_fs.root(); + + let source = FileSource::new(input); + let compile_time_info = CompileTimeInfo::builder(Environment::new(Value::new( + ExecutionEnvironment::NodeJsLambda(NodeJsEnvironment::default().into()), + ))) + .cell(); + let module_asset_context = ModuleAssetContext::new( + Vc::cell(HashMap::new()), + compile_time_info, + ModuleOptionsContext { enable_types:true, ..Default::default() }.cell(), + ResolveOptionsContext { + emulate_environment:Some(compile_time_info.environment().resolve().await?), + ..Default::default() + } + .cell(), + Vc::cell("node_file_trace".into()), + ); + let module = module_asset_context + .process(Vc::upcast(source), Value::new(ReferenceType::Undefined)) + .module(); + let rebased = RebasedAsset::new(Vc::upcast(module), input_dir, output_dir); + + emit_with_completion(Vc::upcast(rebased), output_dir).await?; + + Ok::, _>(Default::default()) + }); + tt.wait_task_completion(task, true).await.unwrap(); + } + }) +} diff --git a/crates/turbopack/build.rs b/crates/turbopack/build.rs new file mode 100644 index 0000000000000..322a6400757e9 --- /dev/null +++ b/crates/turbopack/build.rs @@ -0,0 +1,3 @@ +use turbo_tasks_build::generate_register; + +fn main() { generate_register(); } diff --git a/crates/turbopack/examples/turbopack.rs b/crates/turbopack/examples/turbopack.rs new file mode 100644 index 0000000000000..b9b3fba5871f4 --- /dev/null +++ b/crates/turbopack/examples/turbopack.rs @@ -0,0 +1,91 @@ +#![feature(trivial_bounds)] + +use std::{ + collections::HashMap, + env::current_dir, + time::{Duration, Instant}, +}; + +use anyhow::Result; +use tokio::{spawn, time::sleep}; +use turbo_tasks::{RcStr, TurboTasks, UpdateInfo, Value, Vc, util::FormatDuration}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem}; +use turbo_tasks_memory::MemoryBackend; +use turbopack::{emit_with_completion, rebase::RebasedAsset, register}; +use turbopack_core::{ + PROJECT_FILESYSTEM_NAME, + compile_time_info::CompileTimeInfo, + context::AssetContext, + environment::{Environment, ExecutionEnvironment, NodeJsEnvironment}, + file_source::FileSource, +}; +use turbopack_resolve::resolve_options_context::ResolveOptionsContext; + +#[tokio::main] +async fn main() -> Result<()> { + register(); + + let tt = TurboTasks::new(MemoryBackend::default()); + let start = Instant::now(); + + let task = tt.spawn_root_task(|| { + Box::pin(async { + let root:RcStr = current_dir().unwrap().to_str().unwrap().into(); + let disk_fs = DiskFileSystem::new(PROJECT_FILESYSTEM_NAME.into(), root, vec![]); + disk_fs.await?.start_watching()?; + + // Smart Pointer cast + let fs:Vc> = Vc::upcast(disk_fs); + let input = fs.root().join("demo".into()); + let output = fs.root().join("out".into()); + let entry = fs.root().join("demo/index.js".into()); + + let source = FileSource::new(entry); + let module_asset_context = turbopack::ModuleAssetContext::new( + Vc::cell(HashMap::new()), + CompileTimeInfo::new(Environment::new(Value::new( + ExecutionEnvironment::NodeJsLambda(NodeJsEnvironment::default().into()), + ))), + Default::default(), + ResolveOptionsContext { + enable_typescript:true, + enable_react:true, + enable_node_modules:Some(fs.root()), + custom_conditions:vec!["development".into()], + ..Default::default() + } + .cell(), + Vc::cell("default".into()), + ); + let module = module_asset_context + .process( + Vc::upcast(source), + Value::new(turbopack_core::reference_type::ReferenceType::Undefined), + ) + .module(); + let rebased = RebasedAsset::new(module, input, output); + emit_with_completion(Vc::upcast(rebased), output).await?; + + Ok::, _>(Default::default()) + }) + }); + spawn({ + let tt = tt.clone(); + async move { + tt.wait_task_completion(task, true).await.unwrap(); + println!("done in {}", FormatDuration(start.elapsed())); + + loop { + let UpdateInfo { duration, tasks, .. } = + tt.get_or_wait_aggregated_update_info(Duration::from_millis(100)).await; + println!("updated {} tasks in {}", tasks, FormatDuration(duration)); + } + } + }) + .await + .unwrap(); + + loop { + sleep(Duration::from_secs(10)).await; + } +} diff --git a/crates/turborepo-analytics/Cargo.toml b/crates/turborepo-analytics/Cargo.toml index 554c3a5675e63..9a5c08fc969b5 100644 --- a/crates/turborepo-analytics/Cargo.toml +++ b/crates/turborepo-analytics/Cargo.toml @@ -1,19 +1,22 @@ -[package] -name = "turborepo-analytics" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] -futures.workspace = true thiserror = { workspace = true } tokio = { workspace = true, features = ["full", "time"] } tracing = { workspace = true } turborepo-api-client = { workspace = true } turborepo-vercel-api = { workspace = true } uuid = { version = "1.5.0", features = ["v4"] } + +[dependencies.futures] +workspace = true + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-analytics" +version = "0.1.0" diff --git a/crates/turborepo-analytics/src/lib.rs b/crates/turborepo-analytics/Source/lib.rs similarity index 100% rename from crates/turborepo-analytics/src/lib.rs rename to crates/turborepo-analytics/Source/lib.rs diff --git a/crates/turborepo-api-client/Cargo.toml b/crates/turborepo-api-client/Cargo.toml index dc2290a4b2301..8798f5234ed80 100644 --- a/crates/turborepo-api-client/Cargo.toml +++ b/crates/turborepo-api-client/Cargo.toml @@ -1,28 +1,4 @@ -[package] -name = "turborepo-api-client" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[features] -native-tls = ["reqwest/native-tls"] -rustls-tls = ["reqwest/rustls-tls-native-roots"] - -[dev-dependencies] -anyhow = { workspace = true } -http = "1.1.0" -httpmock = { workspace = true } -insta = { workspace = true } -port_scanner = { workspace = true } -test-case = { workspace = true } -turborepo-vercel-api-mock = { workspace = true } - -[lints] -workspace = true - [dependencies] -bytes.workspace = true chrono = { workspace = true, features = ["serde"] } lazy_static = { workspace = true } regex = { workspace = true } @@ -39,3 +15,31 @@ turbopath = { workspace = true } turborepo-ci = { workspace = true } turborepo-vercel-api = { workspace = true } url = { workspace = true } + +[dependencies.bytes] +workspace = true + +[dev-dependencies] +anyhow = { workspace = true } +http = "1.1.0" +httpmock = { workspace = true } +insta = { workspace = true } +port_scanner = { workspace = true } +test-case = { workspace = true } +turborepo-vercel-api-mock = { workspace = true } + +[features] +native-tls = ["reqwest/native-tls"] +rustls-tls = ["reqwest/rustls-tls-native-roots"] + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-api-client" +version = "0.1.0" diff --git a/crates/turborepo-api-client/Source/analytics.rs b/crates/turborepo-api-client/Source/analytics.rs new file mode 100644 index 0000000000000..620dc6df5e5ff --- /dev/null +++ b/crates/turborepo-api-client/Source/analytics.rs @@ -0,0 +1,35 @@ +use std::future::Future; + +use reqwest::Method; +pub use turborepo_vercel_api::{AnalyticsEvent, CacheEvent, CacheSource}; + +use crate::{APIAuth, APIClient, Error, retry}; + +pub trait AnalyticsClient { + fn record_analytics( + &self, + api_auth:&APIAuth, + events:Vec, + ) -> impl Future> + Send; +} + +impl AnalyticsClient for APIClient { + #[tracing::instrument(skip_all)] + async fn record_analytics( + &self, + api_auth:&APIAuth, + events:Vec, + ) -> Result<(), Error> { + let request_builder = self + .create_request_builder("/v8/artifacts/events", api_auth, Method::POST) + .await? + .json(&events); + + retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) + .await? + .into_response() + .error_for_status()?; + + Ok(()) + } +} diff --git a/crates/turborepo-api-client/src/error.rs b/crates/turborepo-api-client/Source/error.rs similarity index 100% rename from crates/turborepo-api-client/src/error.rs rename to crates/turborepo-api-client/Source/error.rs diff --git a/crates/turborepo-api-client/src/lib.rs b/crates/turborepo-api-client/Source/lib.rs similarity index 100% rename from crates/turborepo-api-client/src/lib.rs rename to crates/turborepo-api-client/Source/lib.rs diff --git a/crates/turborepo-api-client/Source/retry.rs b/crates/turborepo-api-client/Source/retry.rs new file mode 100644 index 0000000000000..dbf32907bd091 --- /dev/null +++ b/crates/turborepo-api-client/Source/retry.rs @@ -0,0 +1,168 @@ +use reqwest::{RequestBuilder, Response, StatusCode}; +use tokio::time::sleep; + +use crate::Error; + +const MIN_SLEEP_TIME_SECS:u64 = 2; +const MAX_SLEEP_TIME_SECS:u64 = 10; +const RETRY_MAX:u32 = 2; + +#[derive(Debug)] +pub enum Retry { + Once(Response), + #[allow(dead_code)] + Retried(Response, u32), +} + +impl Retry { + pub fn into_response(self) -> Response { + match self { + Retry::Once(response) => response, + Retry::Retried(response, _) => response, + } + } + + #[allow(dead_code)] + pub fn retry_count(&self) -> Option { + match self { + Retry::Once(_) => None, + Retry::Retried(_, count) => Some(*count), + } + } +} + +/// Retries a request until `RETRY_MAX` is reached, the `should_retry_request` +/// function returns false, or the future succeeds. Uses an exponential backoff +/// with a base of 2 to delay between retries. +/// +/// # Arguments +/// +/// * `request_builder`: The request builder with everything, i.e. headers and +/// body already set. NOTE: This must be cloneable, so no streams are allowed. +/// * `strategy`: The strategy to use for retrying requests. +/// +/// returns: Result +pub(crate) async fn make_retryable_request( + request_builder:RequestBuilder, + strategy:RetryStrategy, +) -> Result { + let mut last_error = None; + for retry_count in 0..RETRY_MAX { + // A request builder can fail to clone for two reasons: + // - the URL given was given as a string and isn't a valid URL this can be + // mitigated by constructing requests with pre-parsed URLs via Url::parse + // - the request body is a stream, in this case we'll just send the one request + // we have + let Some(builder) = request_builder.try_clone() else { + return Ok(Retry::Once(request_builder.send().await?)); + }; + match builder.send().await { + Ok(value) => return Ok(Retry::Retried(value, retry_count)), + Err(err) => { + if !strategy.should_retry(&err) { + return Err(err.into()); + } + last_error = Some(err); + }, + } + + let sleep_period = (2_u64).pow(retry_count).clamp(MIN_SLEEP_TIME_SECS, MAX_SLEEP_TIME_SECS); + sleep(std::time::Duration::from_secs(sleep_period)).await; + } + + Err(Error::TooManyFailures(Box::new(last_error.unwrap()))) +} + +/// A retry strategy. Note that error statuses and TOO_MANY_REQUESTS are always +/// retried. +pub enum RetryStrategy { + /// Retry in the case of connection issues, but ignore timeouts. + Connection, + /// Retry in the case of connection issues and timeouts. + Timeout, +} + +impl RetryStrategy { + fn should_retry(&self, error:&reqwest::Error) -> bool { + if let Some(status) = error.status() { + if status == StatusCode::TOO_MANY_REQUESTS { + return true; + } + + if status.as_u16() >= 500 && status.as_u16() != 501 { + return true; + } + } + + match self { + RetryStrategy::Connection => error.is_connect(), + RetryStrategy::Timeout => error.is_timeout(), + } + } +} + +#[cfg(test)] +mod test { + use std::{assert_matches::assert_matches, time::Duration}; + + use crate::{ + Error, + retry::{RetryStrategy, make_retryable_request}, + }; + + #[tokio::test] + async fn handles_too_many_failures() { + let mock = httpmock::MockServer::start_async().await; + let req = mock + .mock_async(|when, then| { + when.method(httpmock::Method::GET); + then.delay(Duration::from_secs(100)); + }) + .await; + + let request_builder = + reqwest::Client::new().get(mock.url("/")).timeout(Duration::from_millis(10)); + let result = make_retryable_request(request_builder, RetryStrategy::Timeout).await; + + req.assert_hits_async(2).await; + assert_matches!(result, Err(Error::TooManyFailures(_))); + } + + #[tokio::test] + async fn handles_connection_timeout() { + let client = reqwest::Client::builder() + .connect_timeout(Duration::from_millis(10)) + .build() + .unwrap(); + + let request_builder = client.get("http://localhost:1").send().await; // bad port + let should_retry = RetryStrategy::Connection.should_retry(&request_builder.unwrap_err()); + + assert_matches!(should_retry, true); + } + + #[tokio::test] + async fn handles_connection_timeout_retries() { + let client = reqwest::Client::builder() + .timeout(Duration::from_millis(20)) + .connect_timeout(Duration::from_millis(10)) + .build() + .unwrap(); + + let mock = httpmock::MockServer::start_async().await; + let req = mock + .mock_async(|when, then| { + when.method(httpmock::Method::GET); + then.delay(Duration::from_secs(100)); + }) + .await; + + let request_builder = client.get(mock.url("/")); // bad port + let result = make_retryable_request(request_builder, RetryStrategy::Connection).await; + + // we should make at most one request and give up if it times out after + // connecting + assert_matches!(result, Err(_)); + req.assert_hits_async(1).await; + } +} diff --git a/crates/turborepo-api-client/Source/spaces.rs b/crates/turborepo-api-client/Source/spaces.rs new file mode 100644 index 0000000000000..52f207cdb6c56 --- /dev/null +++ b/crates/turborepo-api-client/Source/spaces.rs @@ -0,0 +1,250 @@ +use chrono::{DateTime, Local}; +use reqwest::Method; +use serde::Serialize; +use turbopath::AnchoredSystemPath; +use turborepo_vercel_api::SpaceRun; + +use crate::{APIAuth, APIClient, Error, retry}; + +#[derive(Debug, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum RunStatus { + Running, + Completed, +} + +#[derive(Serialize)] +pub struct SpaceClientSummary { + pub id:&'static str, + pub name:&'static str, + pub version:String, +} + +#[derive(Debug, Serialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct SpacesCacheStatus { + pub status:CacheStatus, + #[serde(skip_serializing_if = "Option::is_none")] + pub source:Option, + pub time_saved:u64, +} + +#[derive(Debug, Serialize, Copy, Clone)] +#[serde(rename_all = "UPPERCASE")] +pub enum CacheStatus { + Hit, + Miss, +} + +#[derive(Debug, Serialize, Copy, Clone)] +#[serde(rename_all = "UPPERCASE")] +pub enum CacheSource { + Local, + Remote, +} + +#[derive(Default, Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct SpaceTaskSummary { + pub key:String, + pub name:String, + pub workspace:String, + pub hash:String, + pub start_time:i64, + pub end_time:i64, + pub cache:SpacesCacheStatus, + pub exit_code:Option, + pub dependencies:Vec, + pub dependents:Vec, + #[serde(rename = "log")] + pub logs:String, +} + +#[derive(Serialize)] +#[serde(rename_all = "UPPERCASE")] +pub enum SpaceRunType { + Turbo, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateSpaceRunPayload { + pub start_time:i64, + pub status:RunStatus, + #[serde(rename = "type")] + pub ty:SpaceRunType, // Hardcoded to "TURBO" + pub command:String, + #[serde(rename = "repositoryPath")] + pub package_inference_root:String, + #[serde(rename = "context")] + pub run_context:&'static str, + pub git_branch:Option, + pub git_sha:Option, + #[serde(rename = "originationUser")] + pub user:String, + pub client:SpaceClientSummary, +} + +impl CreateSpaceRunPayload { + pub fn new( + start_time:DateTime, + synthesized_command:String, + package_inference_root:Option<&AnchoredSystemPath>, + git_branch:Option, + git_sha:Option, + version:String, + user:String, + ) -> Self { + let start_time = start_time.timestamp_millis(); + let vendor = turborepo_ci::Vendor::infer(); + let run_context = vendor.map(|v| v.constant).unwrap_or("LOCAL"); + + CreateSpaceRunPayload { + start_time, + status:RunStatus::Running, + command:synthesized_command, + package_inference_root:package_inference_root + .map(|p| p.to_string()) + .unwrap_or_default(), + ty:SpaceRunType::Turbo, + run_context, + git_branch, + git_sha, + user, + client:SpaceClientSummary { id:"turbo", name:"Turbo", version }, + } + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct FinishSpaceRunPayload { + status:RunStatus, + end_time:i64, + exit_code:i32, +} + +impl FinishSpaceRunPayload { + pub fn new(end_time:i64, exit_code:i32) -> Self { + Self { status:RunStatus::Completed, end_time, exit_code } + } +} + +impl APIClient { + #[tracing::instrument(skip_all)] + pub async fn create_space_run( + &self, + space_id:&str, + api_auth:&APIAuth, + payload:CreateSpaceRunPayload, + ) -> Result { + let url = format!("/v0/spaces/{}/runs", space_id); + let request_builder = + self.create_request_builder(&url, api_auth, Method::POST).await?.json(&payload); + + let response = + retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) + .await? + .into_response() + .error_for_status()?; + + Ok(response.json().await?) + } + + #[tracing::instrument(skip_all)] + pub async fn create_task_summary( + &self, + space_id:&str, + run_id:&str, + api_auth:&APIAuth, + task:SpaceTaskSummary, + ) -> Result<(), Error> { + let request_builder = self + .create_request_builder( + &format!("/v0/spaces/{}/runs/{}/tasks", space_id, run_id), + api_auth, + Method::POST, + ) + .await? + .json(&task); + + retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) + .await? + .into_response() + .error_for_status()?; + + Ok(()) + } + + #[tracing::instrument(skip_all)] + pub async fn finish_space_run( + &self, + space_id:&str, + run_id:&str, + api_auth:&APIAuth, + end_time:i64, + exit_code:i32, + ) -> Result<(), Error> { + let url = format!("/v0/spaces/{}/runs/{}", space_id, run_id); + + let payload = FinishSpaceRunPayload::new(end_time, exit_code); + + let request_builder = + self.create_request_builder(&url, api_auth, Method::PATCH).await?.json(&payload); + + retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) + .await? + .into_response() + .error_for_status()?; + + Ok(()) + } +} + +impl Default for CacheStatus { + fn default() -> Self { Self::Miss } +} + +#[cfg(test)] +mod test { + use serde_json::json; + use test_case::test_case; + + use super::*; + + #[test_case(CacheStatus::Hit, json!("HIT") ; "hit")] + #[test_case(CacheStatus::Miss, json!("MISS") ; "miss")] + #[test_case(CacheSource::Local, json!("LOCAL") ; "local")] + #[test_case(CacheSource::Remote, json!("REMOTE") ; "remote")] + #[test_case(SpacesCacheStatus { + source: None, + status: CacheStatus::Miss, + time_saved: 0, + }, + json!({ "status": "MISS", "timeSaved": 0 }) + ; "cache miss")] + #[test_case(SpaceTaskSummary{ + key: "foo#build".into(), + exit_code: Some(0), + ..Default::default()}, + json!({ + "key": "foo#build", + "name": "", + "workspace": "", + "hash": "", + "startTime": 0, + "endTime": 0, + "cache": { + "timeSaved": 0, + "status": "MISS" + }, + "exitCode": 0, + "dependencies": [], + "dependents": [], + "log": "", + }) + ; "spaces task summary")] + fn test_serialization(value:impl serde::Serialize, expected:serde_json::Value) { + assert_eq!(serde_json::to_value(value).unwrap(), expected); + } +} diff --git a/crates/turborepo-api-client/Source/telemetry.rs b/crates/turborepo-api-client/Source/telemetry.rs new file mode 100644 index 0000000000000..f4b8cd8aa4369 --- /dev/null +++ b/crates/turborepo-api-client/Source/telemetry.rs @@ -0,0 +1,43 @@ +use std::future::Future; + +use reqwest::Method; +use turborepo_vercel_api::telemetry::TelemetryEvent; + +use crate::{AnonAPIClient, Error, retry}; + +const TELEMETRY_ENDPOINT:&str = "/api/turborepo/v1/events"; + +pub trait TelemetryClient { + fn record_telemetry( + &self, + events:Vec, + telemetry_id:&str, + session_id:&str, + ) -> impl Future> + Send; +} + +impl TelemetryClient for AnonAPIClient { + async fn record_telemetry( + &self, + events:Vec, + telemetry_id:&str, + session_id:&str, + ) -> Result<(), Error> { + let url = self.make_url(TELEMETRY_ENDPOINT); + let telemetry_request = self + .client + .request(Method::POST, url) + .header("User-Agent", self.user_agent.clone()) + .header("Content-Type", "application/json") + .header("x-turbo-telemetry-id", telemetry_id) + .header("x-turbo-session-id", session_id) + .json(&events); + + retry::make_retryable_request(telemetry_request, retry::RetryStrategy::Timeout) + .await? + .into_response() + .error_for_status()?; + + Ok(()) + } +} diff --git a/crates/turborepo-api-client/src/analytics.rs b/crates/turborepo-api-client/src/analytics.rs deleted file mode 100644 index c847c266ee6ce..0000000000000 --- a/crates/turborepo-api-client/src/analytics.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::future::Future; - -use reqwest::Method; -pub use turborepo_vercel_api::{AnalyticsEvent, CacheEvent, CacheSource}; - -use crate::{retry, APIAuth, APIClient, Error}; - -pub trait AnalyticsClient { - fn record_analytics( - &self, - api_auth: &APIAuth, - events: Vec, - ) -> impl Future> + Send; -} - -impl AnalyticsClient for APIClient { - #[tracing::instrument(skip_all)] - async fn record_analytics( - &self, - api_auth: &APIAuth, - events: Vec, - ) -> Result<(), Error> { - let request_builder = self - .create_request_builder("/v8/artifacts/events", api_auth, Method::POST) - .await? - .json(&events); - - retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) - .await? - .into_response() - .error_for_status()?; - - Ok(()) - } -} diff --git a/crates/turborepo-api-client/src/retry.rs b/crates/turborepo-api-client/src/retry.rs deleted file mode 100644 index 8f027534d5782..0000000000000 --- a/crates/turborepo-api-client/src/retry.rs +++ /dev/null @@ -1,171 +0,0 @@ -use reqwest::{RequestBuilder, Response, StatusCode}; -use tokio::time::sleep; - -use crate::Error; - -const MIN_SLEEP_TIME_SECS: u64 = 2; -const MAX_SLEEP_TIME_SECS: u64 = 10; -const RETRY_MAX: u32 = 2; - -#[derive(Debug)] -pub enum Retry { - Once(Response), - #[allow(dead_code)] - Retried(Response, u32), -} - -impl Retry { - pub fn into_response(self) -> Response { - match self { - Retry::Once(response) => response, - Retry::Retried(response, _) => response, - } - } - - #[allow(dead_code)] - pub fn retry_count(&self) -> Option { - match self { - Retry::Once(_) => None, - Retry::Retried(_, count) => Some(*count), - } - } -} - -/// Retries a request until `RETRY_MAX` is reached, the `should_retry_request` -/// function returns false, or the future succeeds. Uses an exponential backoff -/// with a base of 2 to delay between retries. -/// -/// # Arguments -/// -/// * `request_builder`: The request builder with everything, i.e. headers and -/// body already set. NOTE: This must be cloneable, so no streams are allowed. -/// * `strategy`: The strategy to use for retrying requests. -/// -/// returns: Result -pub(crate) async fn make_retryable_request( - request_builder: RequestBuilder, - strategy: RetryStrategy, -) -> Result { - let mut last_error = None; - for retry_count in 0..RETRY_MAX { - // A request builder can fail to clone for two reasons: - // - the URL given was given as a string and isn't a valid URL this can be - // mitigated by constructing requests with pre-parsed URLs via Url::parse - // - the request body is a stream, in this case we'll just send the one request - // we have - let Some(builder) = request_builder.try_clone() else { - return Ok(Retry::Once(request_builder.send().await?)); - }; - match builder.send().await { - Ok(value) => return Ok(Retry::Retried(value, retry_count)), - Err(err) => { - if !strategy.should_retry(&err) { - return Err(err.into()); - } - last_error = Some(err); - } - } - - let sleep_period = (2_u64) - .pow(retry_count) - .clamp(MIN_SLEEP_TIME_SECS, MAX_SLEEP_TIME_SECS); - sleep(std::time::Duration::from_secs(sleep_period)).await; - } - - Err(Error::TooManyFailures(Box::new(last_error.unwrap()))) -} - -/// A retry strategy. Note that error statuses and TOO_MANY_REQUESTS are always -/// retried. -pub enum RetryStrategy { - /// Retry in the case of connection issues, but ignore timeouts. - Connection, - /// Retry in the case of connection issues and timeouts. - Timeout, -} - -impl RetryStrategy { - fn should_retry(&self, error: &reqwest::Error) -> bool { - if let Some(status) = error.status() { - if status == StatusCode::TOO_MANY_REQUESTS { - return true; - } - - if status.as_u16() >= 500 && status.as_u16() != 501 { - return true; - } - } - - match self { - RetryStrategy::Connection => error.is_connect(), - RetryStrategy::Timeout => error.is_timeout(), - } - } -} - -#[cfg(test)] -mod test { - use std::{assert_matches::assert_matches, time::Duration}; - - use crate::{ - retry::{make_retryable_request, RetryStrategy}, - Error, - }; - - #[tokio::test] - async fn handles_too_many_failures() { - let mock = httpmock::MockServer::start_async().await; - let req = mock - .mock_async(|when, then| { - when.method(httpmock::Method::GET); - then.delay(Duration::from_secs(100)); - }) - .await; - - let request_builder = reqwest::Client::new() - .get(mock.url("/")) - .timeout(Duration::from_millis(10)); - let result = make_retryable_request(request_builder, RetryStrategy::Timeout).await; - - req.assert_hits_async(2).await; - assert_matches!(result, Err(Error::TooManyFailures(_))); - } - - #[tokio::test] - async fn handles_connection_timeout() { - let client = reqwest::Client::builder() - .connect_timeout(Duration::from_millis(10)) - .build() - .unwrap(); - - let request_builder = client.get("http://localhost:1").send().await; // bad port - let should_retry = RetryStrategy::Connection.should_retry(&request_builder.unwrap_err()); - - assert_matches!(should_retry, true); - } - - #[tokio::test] - async fn handles_connection_timeout_retries() { - let client = reqwest::Client::builder() - .timeout(Duration::from_millis(20)) - .connect_timeout(Duration::from_millis(10)) - .build() - .unwrap(); - - let mock = httpmock::MockServer::start_async().await; - let req = mock - .mock_async(|when, then| { - when.method(httpmock::Method::GET); - then.delay(Duration::from_secs(100)); - }) - .await; - - let request_builder = client.get(mock.url("/")); // bad port - let result = make_retryable_request(request_builder, RetryStrategy::Connection).await; - - // we should make at most one request and give up if it times out after - // connecting - assert_matches!(result, Err(_)); - req.assert_hits_async(1).await; - } -} diff --git a/crates/turborepo-api-client/src/spaces.rs b/crates/turborepo-api-client/src/spaces.rs deleted file mode 100644 index cc6f11a78e90e..0000000000000 --- a/crates/turborepo-api-client/src/spaces.rs +++ /dev/null @@ -1,264 +0,0 @@ -use chrono::{DateTime, Local}; -use reqwest::Method; -use serde::Serialize; -use turbopath::AnchoredSystemPath; -use turborepo_vercel_api::SpaceRun; - -use crate::{retry, APIAuth, APIClient, Error}; - -#[derive(Debug, Serialize)] -#[serde(rename_all = "lowercase")] -pub enum RunStatus { - Running, - Completed, -} - -#[derive(Serialize)] -pub struct SpaceClientSummary { - pub id: &'static str, - pub name: &'static str, - pub version: String, -} - -#[derive(Debug, Serialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct SpacesCacheStatus { - pub status: CacheStatus, - #[serde(skip_serializing_if = "Option::is_none")] - pub source: Option, - pub time_saved: u64, -} - -#[derive(Debug, Serialize, Copy, Clone)] -#[serde(rename_all = "UPPERCASE")] -pub enum CacheStatus { - Hit, - Miss, -} - -#[derive(Debug, Serialize, Copy, Clone)] -#[serde(rename_all = "UPPERCASE")] -pub enum CacheSource { - Local, - Remote, -} - -#[derive(Default, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct SpaceTaskSummary { - pub key: String, - pub name: String, - pub workspace: String, - pub hash: String, - pub start_time: i64, - pub end_time: i64, - pub cache: SpacesCacheStatus, - pub exit_code: Option, - pub dependencies: Vec, - pub dependents: Vec, - #[serde(rename = "log")] - pub logs: String, -} - -#[derive(Serialize)] -#[serde(rename_all = "UPPERCASE")] -pub enum SpaceRunType { - Turbo, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateSpaceRunPayload { - pub start_time: i64, - pub status: RunStatus, - #[serde(rename = "type")] - pub ty: SpaceRunType, // Hardcoded to "TURBO" - pub command: String, - #[serde(rename = "repositoryPath")] - pub package_inference_root: String, - #[serde(rename = "context")] - pub run_context: &'static str, - pub git_branch: Option, - pub git_sha: Option, - #[serde(rename = "originationUser")] - pub user: String, - pub client: SpaceClientSummary, -} - -impl CreateSpaceRunPayload { - pub fn new( - start_time: DateTime, - synthesized_command: String, - package_inference_root: Option<&AnchoredSystemPath>, - git_branch: Option, - git_sha: Option, - version: String, - user: String, - ) -> Self { - let start_time = start_time.timestamp_millis(); - let vendor = turborepo_ci::Vendor::infer(); - let run_context = vendor.map(|v| v.constant).unwrap_or("LOCAL"); - - CreateSpaceRunPayload { - start_time, - status: RunStatus::Running, - command: synthesized_command, - package_inference_root: package_inference_root - .map(|p| p.to_string()) - .unwrap_or_default(), - ty: SpaceRunType::Turbo, - run_context, - git_branch, - git_sha, - user, - client: SpaceClientSummary { - id: "turbo", - name: "Turbo", - version, - }, - } - } -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct FinishSpaceRunPayload { - status: RunStatus, - end_time: i64, - exit_code: i32, -} - -impl FinishSpaceRunPayload { - pub fn new(end_time: i64, exit_code: i32) -> Self { - Self { - status: RunStatus::Completed, - end_time, - exit_code, - } - } -} - -impl APIClient { - #[tracing::instrument(skip_all)] - pub async fn create_space_run( - &self, - space_id: &str, - api_auth: &APIAuth, - payload: CreateSpaceRunPayload, - ) -> Result { - let url = format!("/v0/spaces/{}/runs", space_id); - let request_builder = self - .create_request_builder(&url, api_auth, Method::POST) - .await? - .json(&payload); - - let response = - retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) - .await? - .into_response() - .error_for_status()?; - - Ok(response.json().await?) - } - - #[tracing::instrument(skip_all)] - pub async fn create_task_summary( - &self, - space_id: &str, - run_id: &str, - api_auth: &APIAuth, - task: SpaceTaskSummary, - ) -> Result<(), Error> { - let request_builder = self - .create_request_builder( - &format!("/v0/spaces/{}/runs/{}/tasks", space_id, run_id), - api_auth, - Method::POST, - ) - .await? - .json(&task); - - retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) - .await? - .into_response() - .error_for_status()?; - - Ok(()) - } - - #[tracing::instrument(skip_all)] - pub async fn finish_space_run( - &self, - space_id: &str, - run_id: &str, - api_auth: &APIAuth, - end_time: i64, - exit_code: i32, - ) -> Result<(), Error> { - let url = format!("/v0/spaces/{}/runs/{}", space_id, run_id); - - let payload = FinishSpaceRunPayload::new(end_time, exit_code); - - let request_builder = self - .create_request_builder(&url, api_auth, Method::PATCH) - .await? - .json(&payload); - - retry::make_retryable_request(request_builder, retry::RetryStrategy::Timeout) - .await? - .into_response() - .error_for_status()?; - - Ok(()) - } -} - -impl Default for CacheStatus { - fn default() -> Self { - Self::Miss - } -} - -#[cfg(test)] -mod test { - use serde_json::json; - use test_case::test_case; - - use super::*; - - #[test_case(CacheStatus::Hit, json!("HIT") ; "hit")] - #[test_case(CacheStatus::Miss, json!("MISS") ; "miss")] - #[test_case(CacheSource::Local, json!("LOCAL") ; "local")] - #[test_case(CacheSource::Remote, json!("REMOTE") ; "remote")] - #[test_case(SpacesCacheStatus { - source: None, - status: CacheStatus::Miss, - time_saved: 0, - }, - json!({ "status": "MISS", "timeSaved": 0 }) - ; "cache miss")] - #[test_case(SpaceTaskSummary{ - key: "foo#build".into(), - exit_code: Some(0), - ..Default::default()}, - json!({ - "key": "foo#build", - "name": "", - "workspace": "", - "hash": "", - "startTime": 0, - "endTime": 0, - "cache": { - "timeSaved": 0, - "status": "MISS" - }, - "exitCode": 0, - "dependencies": [], - "dependents": [], - "log": "", - }) - ; "spaces task summary")] - fn test_serialization(value: impl serde::Serialize, expected: serde_json::Value) { - assert_eq!(serde_json::to_value(value).unwrap(), expected); - } -} diff --git a/crates/turborepo-api-client/src/telemetry.rs b/crates/turborepo-api-client/src/telemetry.rs deleted file mode 100644 index a0382af1dc779..0000000000000 --- a/crates/turborepo-api-client/src/telemetry.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::future::Future; - -use reqwest::Method; -use turborepo_vercel_api::telemetry::TelemetryEvent; - -use crate::{retry, AnonAPIClient, Error}; - -const TELEMETRY_ENDPOINT: &str = "/api/turborepo/v1/events"; - -pub trait TelemetryClient { - fn record_telemetry( - &self, - events: Vec, - telemetry_id: &str, - session_id: &str, - ) -> impl Future> + Send; -} - -impl TelemetryClient for AnonAPIClient { - async fn record_telemetry( - &self, - events: Vec, - telemetry_id: &str, - session_id: &str, - ) -> Result<(), Error> { - let url = self.make_url(TELEMETRY_ENDPOINT); - let telemetry_request = self - .client - .request(Method::POST, url) - .header("User-Agent", self.user_agent.clone()) - .header("Content-Type", "application/json") - .header("x-turbo-telemetry-id", telemetry_id) - .header("x-turbo-session-id", session_id) - .json(&events); - - retry::make_retryable_request(telemetry_request, retry::RetryStrategy::Timeout) - .await? - .into_response() - .error_for_status()?; - - Ok(()) - } -} diff --git a/crates/turborepo-auth/Cargo.toml b/crates/turborepo-auth/Cargo.toml index 477a04ab73664..d8edd9bc812e0 100644 --- a/crates/turborepo-auth/Cargo.toml +++ b/crates/turborepo-auth/Cargo.toml @@ -1,35 +1,56 @@ -[package] -name = "turborepo-auth" -version = "0.1.0" -edition = "2021" -license = "MIT" - -[lints] -workspace = true - [dependencies] anyhow = { workspace = true, features = ["backtrace"] } -async-trait.workspace = true axum-server = { workspace = true } -axum.workspace = true -chrono.workspace = true hostname = "0.3.1" -lazy_static.workspace = true -reqwest.workspace = true serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } tempfile = { workspace = true } thiserror = "1.0.38" -tokio.workspace = true -tracing.workspace = true -turbopath.workspace = true turborepo-api-client = { workspace = true } turborepo-dirs = { version = "0.1.0", path = "../turborepo-dirs" } -turborepo-ui.workspace = true turborepo-vercel-api = { workspace = true } turborepo-vercel-api-mock = { workspace = true } url = { workspace = true } webbrowser = { workspace = true } +[dependencies.async-trait] +workspace = true + +[dependencies.axum] +workspace = true + +[dependencies.chrono] +workspace = true + +[dependencies.lazy_static] +workspace = true + +[dependencies.reqwest] +workspace = true + +[dependencies.tokio] +workspace = true + +[dependencies.tracing] +workspace = true + +[dependencies.turbopath] +workspace = true + +[dependencies.turborepo-ui] +workspace = true + [dev-dependencies] port_scanner = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-auth" +version = "0.1.0" diff --git a/crates/turborepo-auth/Source/auth/login.rs b/crates/turborepo-auth/Source/auth/login.rs new file mode 100644 index 0000000000000..f4a414fc5980e --- /dev/null +++ b/crates/turborepo-auth/Source/auth/login.rs @@ -0,0 +1,387 @@ +use std::sync::Arc; + +pub use error::Error; +use reqwest::Url; +use tokio::sync::OnceCell; +use tracing::{debug, warn}; +use turborepo_api_client::{CacheClient, Client, TokenClient}; +use turborepo_ui::{BOLD, ColorConfig, start_spinner}; + +use crate::{LoginOptions, Token, auth::extract_vercel_token, error, ui}; + +const DEFAULT_HOST_NAME:&str = "127.0.0.1"; +const DEFAULT_PORT:u16 = 9789; + +/// Login returns a `Token` struct. If a token is already present, +/// we do not overwrite it and instead log that we found an existing token, +/// setting the `exists` field to `true`. +/// +/// First checks if an existing option has been passed in, then if the login is +/// to Vercel, checks if the user has a Vercel CLI token on disk. +pub async fn login( + options:&LoginOptions<'_, T>, +) -> Result { + let LoginOptions { + api_client, + color_config, + login_url: login_url_configuration, + login_server, + existing_token, + force, + sso_team: _, + } = *options; // Deref or we get double references for each of these + + // I created a closure that gives back a closure since the `is_valid` checks do + // a call to get the user, so instead of doing that multiple times we have + // `is_valid` give back the user email. + // + // In the future I want to make the Token have some non-skewable information and + // be able to get rid of this, but it works for now. + let valid_token_callback = |message:&str, color_config:&ColorConfig| { + let message = message.to_string(); + let color_config = *color_config; + move |user_email:&str| { + println!("{}", color_config.apply(BOLD.apply_to(message))); + ui::print_cli_authorized(user_email, &color_config); + } + }; + + // Check if passed in token exists first. + if !force { + if let Some(token) = existing_token { + debug!("found existing turbo token"); + let token = Token::existing(token.into()); + if token + .is_valid( + api_client, + Some(valid_token_callback("Existing token found!", color_config)), + ) + .await? + { + return Ok(token); + } + // If the user is logging into Vercel, check for an existing `vc` token. + } else if login_url_configuration.contains("vercel.com") { + // The extraction can return an error, but we don't want to fail the login if + // the token is not found. + if let Ok(Some(token)) = extract_vercel_token() { + debug!("found existing Vercel token"); + let token = Token::existing(token); + if token + .is_valid( + api_client, + Some(valid_token_callback("Existing Vercel token found!", color_config)), + ) + .await? + { + return Ok(token); + } + } + } + } + + let redirect_url = format!("http://{DEFAULT_HOST_NAME}:{DEFAULT_PORT}"); + let mut login_url = Url::parse(login_url_configuration)?; + let mut success_url = login_url.clone(); + success_url + .path_segments_mut() + .map_err(|_:()| Error::LoginUrlCannotBeABase { value:login_url_configuration.to_string() })? + .extend(["turborepo", "success"]); + + // Create the full login URL. + login_url + .path_segments_mut() + .map_err(|_:()| Error::LoginUrlCannotBeABase { value:login_url_configuration.to_string() })? + .extend(["turborepo", "token"]); + + login_url.query_pairs_mut().append_pair("redirect_uri", &redirect_url); + + println!(">>> Opening browser to {login_url}"); + let spinner = start_spinner("Waiting for your authorization..."); + + // Try to open browser for auth confirmation. + let url = login_url.as_str(); + if !cfg!(test) && webbrowser::open(url).is_err() { + warn!("Failed to open browser. Please visit {url} in your browser."); + } + + let token_cell = Arc::new(OnceCell::new()); + login_server + .run( + DEFAULT_PORT, + crate::LoginType::Basic { success_redirect:success_url.to_string() }, + token_cell.clone(), + ) + .await?; + + spinner.finish_and_clear(); + + let token = token_cell.get().ok_or(Error::FailedToGetToken)?; + + // TODO: make this a request to /teams endpoint instead? + let user_response = + api_client.get_user(token.as_str()).await.map_err(Error::FailedToFetchUser)?; + + ui::print_cli_authorized(&user_response.user.email, color_config); + + Ok(Token::new(token.into())) +} + +#[cfg(test)] +mod tests { + use std::{assert_matches::assert_matches, sync::atomic::AtomicUsize}; + + use async_trait::async_trait; + use reqwest::{Method, RequestBuilder, Response}; + use turborepo_vercel_api::{ + CachingStatus, + CachingStatusResponse, + Membership, + Role, + SpacesResponse, + Team, + TeamsResponse, + User, + UserResponse, + VerifiedSsoUser, + }; + use turborepo_vercel_api_mock::start_test_server; + + use super::*; + use crate::{LoginServer, login_server}; + + struct MockLoginServer { + hits:Arc, + } + + #[async_trait] + impl LoginServer for MockLoginServer { + async fn run( + &self, + _:u16, + _:login_server::LoginType, + login_token:Arc>, + ) -> Result<(), Error> { + self.hits.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + login_token.set(turborepo_vercel_api_mock::EXPECTED_TOKEN.to_string()).unwrap(); + Ok(()) + } + } + + #[derive(Debug, thiserror::Error)] + enum MockApiError { + #[error("Empty token")] + EmptyToken, + } + + impl From for turborepo_api_client::Error { + fn from(error:MockApiError) -> Self { + match error { + MockApiError::EmptyToken => { + turborepo_api_client::Error::UnknownStatus { + code:"empty token".to_string(), + message:"token is empty".to_string(), + backtrace:std::backtrace::Backtrace::capture(), + } + }, + } + } + } + + struct MockApiClient { + pub base_url:String, + } + + impl MockApiClient { + fn new() -> Self { Self { base_url:String::new() } } + } + + impl Client for MockApiClient { + async fn get_user(&self, token:&str) -> turborepo_api_client::Result { + if token.is_empty() { + return Err(MockApiError::EmptyToken.into()); + } + + Ok(UserResponse { + user:User { + id:"id".to_string(), + username:"username".to_string(), + email:"email".to_string(), + name:None, + created_at:None, + }, + }) + } + + async fn get_teams(&self, token:&str) -> turborepo_api_client::Result { + if token.is_empty() { + return Err(MockApiError::EmptyToken.into()); + } + + Ok(TeamsResponse { + teams:vec![Team { + id:"id".to_string(), + slug:"something".to_string(), + name:"name".to_string(), + created_at:0, + created:chrono::Utc::now(), + membership:Membership::new(Role::Member), + }], + }) + } + + async fn get_team( + &self, + _token:&str, + _team_id:&str, + ) -> turborepo_api_client::Result> { + unimplemented!("get_team") + } + + fn add_ci_header(_request_builder:RequestBuilder) -> RequestBuilder { + unimplemented!("add_ci_header") + } + + async fn get_spaces( + &self, + _token:&str, + _team_id:Option<&str>, + ) -> turborepo_api_client::Result { + unimplemented!("get_spaces") + } + + async fn verify_sso_token( + &self, + token:&str, + _:&str, + ) -> turborepo_api_client::Result { + Ok(VerifiedSsoUser { token:token.to_string(), team_id:Some("team_id".to_string()) }) + } + + async fn handle_403(_response:Response) -> turborepo_api_client::Error { + unimplemented!("handle_403") + } + + fn make_url(&self, endpoint:&str) -> turborepo_api_client::Result { + let url = format!("{}{}", self.base_url, endpoint); + Url::parse(&url).map_err(|err| turborepo_api_client::Error::InvalidUrl { url, err }) + } + } + + impl TokenClient for MockApiClient { + async fn get_metadata( + &self, + token:&str, + ) -> turborepo_api_client::Result { + if token.is_empty() { + return Err(MockApiError::EmptyToken.into()); + } + + Ok(turborepo_vercel_api::token::ResponseTokenMetadata { + id:"id".to_string(), + name:"name".to_string(), + token_type:"token".to_string(), + origin:"github".to_string(), + scopes:vec![turborepo_vercel_api::token::Scope { + scope_type:"user".to_string(), + origin:"github".to_string(), + team_id:None, + expires_at:None, + created_at:1111111111111, + }], + active_at:0, + created_at:123456, + }) + } + + async fn delete_token(&self, _token:&str) -> turborepo_api_client::Result<()> { Ok(()) } + } + + impl CacheClient for MockApiClient { + async fn get_artifact( + &self, + _hash:&str, + _token:&str, + _team_id:Option<&str>, + _team_slug:Option<&str>, + _method:Method, + ) -> Result, turborepo_api_client::Error> { + unimplemented!("get_artifact") + } + + async fn put_artifact( + &self, + _hash:&str, + _artifact_body:impl turborepo_api_client::Stream< + Item = Result, + > + Send + + Sync + + 'static, + _body_len:usize, + _duration:u64, + _tag:Option<&str>, + _token:&str, + _team_id:Option<&str>, + _team_slug:Option<&str>, + ) -> Result<(), turborepo_api_client::Error> { + unimplemented!("set_artifact") + } + + async fn fetch_artifact( + &self, + _hash:&str, + _token:&str, + _team_id:Option<&str>, + _team_slug:Option<&str>, + ) -> Result, turborepo_api_client::Error> { + unimplemented!("fetch_artifact") + } + + async fn artifact_exists( + &self, + _hash:&str, + _token:&str, + _team_id:Option<&str>, + _team_slug:Option<&str>, + ) -> Result, turborepo_api_client::Error> { + unimplemented!("artifact_exists") + } + + async fn get_caching_status( + &self, + _token:&str, + _team_id:Option<&str>, + _team_slug:Option<&str>, + ) -> Result { + Ok(CachingStatusResponse { status:CachingStatus::Enabled }) + } + } + + #[tokio::test] + async fn test_login() { + let port = port_scanner::request_open_port().unwrap(); + let api_server = tokio::spawn(start_test_server(port)); + let color_config = ColorConfig::new(false); + let url = format!("http://localhost:{port}"); + + let api_client = MockApiClient::new(); + + let login_server = MockLoginServer { hits:Arc::new(0.into()) }; + let mut options = LoginOptions::new(&color_config, &url, &api_client, &login_server); + + let token = login(&options).await.unwrap(); + assert_matches!(token, Token::New(..)); + + let got_token = token.into_inner().to_string(); + assert_eq!(&got_token, turborepo_vercel_api_mock::EXPECTED_TOKEN); + + // Call the login function a second time to test that we check for existing + // tokens. Total server hits should be 1. + options.existing_token = Some(&got_token); + let second_token = login(&options).await.unwrap(); + assert!(matches!(second_token, Token::Existing(..))); + + api_server.abort(); + assert_eq!(login_server.hits.load(std::sync::atomic::Ordering::SeqCst), 1); + } +} diff --git a/crates/turborepo-auth/Source/auth/logout.rs b/crates/turborepo-auth/Source/auth/logout.rs new file mode 100644 index 0000000000000..f832cce55a65c --- /dev/null +++ b/crates/turborepo-auth/Source/auth/logout.rs @@ -0,0 +1,221 @@ +use tracing::error; +use turbopath::AbsoluteSystemPath; +use turborepo_api_client::TokenClient; +use turborepo_dirs::{config_dir, vercel_config_dir}; +use turborepo_ui::{GREY, cprintln}; + +use crate::{ + Error, + LogoutOptions, + TURBO_TOKEN_DIR, + TURBO_TOKEN_FILE, + Token, + VERCEL_TOKEN_DIR, + VERCEL_TOKEN_FILE, +}; + +pub async fn logout(options:&LogoutOptions) -> Result<(), Error> { + if let Err(err) = options.remove_tokens().await { + error!("could not logout. Something went wrong: {}", err); + return Err(err); + } + + cprintln!(options.color_config, GREY, ">>> Logged out"); + Ok(()) +} + +impl LogoutOptions { + async fn try_remove_token(&self, path:&AbsoluteSystemPath) -> Result<(), Error> { + // Read the existing content from the global configuration path + let Ok(content) = path.read_to_string() else { + return Ok(()); + }; + + if self.invalidate { + match Token::from_file(path) { + Ok(token) => token.invalidate(&self.api_client).await?, + // If token doesn't exist, don't do anything. + Err(Error::TokenNotFound) => {}, + Err(err) => return Err(err), + } + } + + // Attempt to deserialize the content into a serde_json::Value + let mut data:serde_json::Value = serde_json::from_str(&content)?; + + // Check if the data is an object and remove the "token" field if present + if let Some(obj) = data.as_object_mut() { + if obj.remove("token").is_none() { + return Ok(()); + } + } else { + return Ok(()); + } + + // Serialize the updated data back to a string + let new_content = serde_json::to_string_pretty(&data)?; + + // Write the updated content back to the file + path.create_with_contents(new_content)?; + + Ok(()) + } + + async fn remove_tokens(&self) -> Result<(), Error> { + #[cfg(test)] + if let Some(path) = &self.path { + return self.try_remove_token(path).await; + } + + if let Some(vercel_config_dir) = vercel_config_dir()? { + self.try_remove_token( + &vercel_config_dir.join_components(&[VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE]), + ) + .await?; + } + if let Some(turbo_config_dir) = config_dir()? { + self.try_remove_token( + &turbo_config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE]), + ) + .await?; + } + + Ok(()) + } +} +#[cfg(test)] +mod tests { + use std::backtrace::Backtrace; + + use reqwest::{RequestBuilder, Response}; + use tempfile::tempdir; + use turbopath::AbsoluteSystemPathBuf; + use turborepo_api_client::Client; + use turborepo_ui::ColorConfig; + use turborepo_vercel_api::{ + SpacesResponse, + Team, + TeamsResponse, + UserResponse, + VerifiedSsoUser, + token::ResponseTokenMetadata, + }; + use url::Url; + + use super::*; + + struct MockApiClient { + pub succeed_delete_request:bool, + } + + impl Client for MockApiClient { + async fn get_user(&self, _token:&str) -> turborepo_api_client::Result { + unimplemented!("get_user") + } + + async fn get_teams(&self, _token:&str) -> turborepo_api_client::Result { + unimplemented!("get_teams") + } + + async fn get_team( + &self, + _token:&str, + _team_id:&str, + ) -> turborepo_api_client::Result> { + unimplemented!("get_team") + } + + fn add_ci_header(_request_builder:RequestBuilder) -> RequestBuilder { + unimplemented!("add_ci_header") + } + + async fn get_spaces( + &self, + _token:&str, + _team_id:Option<&str>, + ) -> turborepo_api_client::Result { + unimplemented!("get_spaces") + } + + async fn verify_sso_token( + &self, + token:&str, + _:&str, + ) -> turborepo_api_client::Result { + Ok(VerifiedSsoUser { token:token.to_string(), team_id:Some("team_id".to_string()) }) + } + + async fn handle_403(_response:Response) -> turborepo_api_client::Error { + unimplemented!("handle_403") + } + + fn make_url(&self, _endpoint:&str) -> turborepo_api_client::Result { + unimplemented!("make_url") + } + } + + impl TokenClient for MockApiClient { + async fn delete_token(&self, _token:&str) -> turborepo_api_client::Result<()> { + if self.succeed_delete_request { + Ok(()) + } else { + Err(turborepo_api_client::Error::UnknownStatus { + code:"code".to_string(), + message:"this failed".to_string(), + backtrace:Backtrace::capture(), + }) + } + } + + async fn get_metadata( + &self, + _token:&str, + ) -> turborepo_api_client::Result { + unimplemented!("get_metadata") + } + } + + #[tokio::test] + async fn test_remove_token() { + let tmp_dir = tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tmp_dir.path().join("config.json")) + .expect("could not create path"); + let content = r#"{"token":"some-token"}"#; + path.create_with_contents(content).expect("could not create file"); + + let logout_options = LogoutOptions { + color_config:ColorConfig::new(false), + api_client:MockApiClient { succeed_delete_request:true }, + invalidate:false, + path:Some(path.clone()), + }; + + logout_options.remove_tokens().await.unwrap(); + + let new_content = path.read_to_string().unwrap(); + assert_eq!(new_content, "{}"); + } + + #[tokio::test] + async fn test_invalidate_token() { + let tmp_dir = tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tmp_dir.path().join("config.json")) + .expect("could not create path"); + let content = r#"{"token":"some-token"}"#; + path.create_with_contents(content).expect("could not create file"); + + let api_client = MockApiClient { succeed_delete_request:true }; + + let options = LogoutOptions { + color_config:ColorConfig::new(false), + api_client, + path:Some(path.clone()), + invalidate:true, + }; + + logout(&options).await.unwrap(); + + let new_content = path.read_to_string().unwrap(); + assert_eq!(new_content, "{}"); + } +} diff --git a/crates/turborepo-auth/Source/auth/mod.rs b/crates/turborepo-auth/Source/auth/mod.rs new file mode 100644 index 0000000000000..e743de290614b --- /dev/null +++ b/crates/turborepo-auth/Source/auth/mod.rs @@ -0,0 +1,74 @@ +mod login; +mod logout; +mod sso; + +pub use login::*; +pub use logout::*; +pub use sso::*; +#[cfg(test)] +use turbopath::AbsoluteSystemPathBuf; +use turborepo_api_client::{CacheClient, Client, TokenClient}; +use turborepo_ui::ColorConfig; + +use crate::LoginServer; + +const VERCEL_TOKEN_DIR:&str = "com.vercel.cli"; +const VERCEL_TOKEN_FILE:&str = "auth.json"; + +pub struct LoginOptions<'a, T:Client + TokenClient + CacheClient> { + pub color_config:&'a ColorConfig, + pub login_url:&'a str, + pub api_client:&'a T, + pub login_server:&'a dyn LoginServer, + + pub sso_team:Option<&'a str>, + pub existing_token:Option<&'a str>, + pub force:bool, +} +impl<'a, T:Client + TokenClient + CacheClient> LoginOptions<'a, T> { + pub fn new( + color_config:&'a ColorConfig, + login_url:&'a str, + api_client:&'a T, + login_server:&'a dyn LoginServer, + ) -> Self { + Self { + color_config, + login_url, + api_client, + login_server, + sso_team:None, + existing_token:None, + force:false, + } + } +} + +/// Options for logging out. +pub struct LogoutOptions { + pub color_config:ColorConfig, + pub api_client:T, + /// If we should invalidate the token on the server. + pub invalidate:bool, + /// Path override for testing + #[cfg(test)] + pub path:Option, +} + +fn extract_vercel_token() -> Result, Error> { + let vercel_config_dir = + turborepo_dirs::vercel_config_dir()?.ok_or_else(|| Error::ConfigDirNotFound)?; + + let vercel_token_path = + vercel_config_dir.join_components(&[VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE]); + let contents = std::fs::read_to_string(vercel_token_path)?; + + #[derive(serde::Deserialize)] + struct VercelToken { + // This isn't actually dead code, it's used by serde to deserialize the JSON. + #[allow(dead_code)] + token:Option, + } + + Ok(serde_json::from_str::(&contents)?.token) +} diff --git a/crates/turborepo-auth/src/auth/sso.rs b/crates/turborepo-auth/Source/auth/sso.rs similarity index 100% rename from crates/turborepo-auth/src/auth/sso.rs rename to crates/turborepo-auth/Source/auth/sso.rs diff --git a/crates/turborepo-auth/src/error.rs b/crates/turborepo-auth/Source/error.rs similarity index 100% rename from crates/turborepo-auth/src/error.rs rename to crates/turborepo-auth/Source/error.rs diff --git a/crates/turborepo-auth/src/lib.rs b/crates/turborepo-auth/Source/lib.rs similarity index 100% rename from crates/turborepo-auth/src/lib.rs rename to crates/turborepo-auth/Source/lib.rs diff --git a/crates/turborepo-auth/Source/login_server.rs b/crates/turborepo-auth/Source/login_server.rs new file mode 100644 index 0000000000000..c7a67780cd331 --- /dev/null +++ b/crates/turborepo-auth/Source/login_server.rs @@ -0,0 +1,204 @@ +use std::{net::SocketAddr, sync::Arc}; + +use anyhow::Result; +use async_trait::async_trait; +use axum::{Router, extract::Query, response::Redirect, routing::get}; +use serde::Deserialize; +use tokio::sync::OnceCell; +use url::Url; + +use crate::Error; + +pub enum LoginType { + Basic { success_redirect:String }, + SSO, +} + +#[derive(Debug, Clone, Deserialize)] +struct LoginPayload { + token:String, +} + +#[derive(Debug, Default, Clone, Deserialize)] +#[allow(dead_code)] +pub struct SsoPayload { + login_error:Option, + sso_email:Option, + team_name:Option, + sso_type:Option, + token:Option, + email:Option, +} + +#[async_trait] +pub trait LoginServer { + async fn run( + &self, + port:u16, + login_type:LoginType, + token:Arc>, + ) -> Result<(), Error>; +} + +/// A struct that implements LoginServer. +/// +/// Listens on 127.0.0.1 and a port that's passed in. +pub struct DefaultLoginServer; + +#[async_trait] +impl LoginServer for DefaultLoginServer { + async fn run( + &self, + port:u16, + login_type:LoginType, + login_token:Arc>, + ) -> Result<(), Error> { + let handle = axum_server::Handle::new(); + let route_handle = handle.clone(); + let addr = SocketAddr::from(([127, 0, 0, 1], port)); + match login_type { + LoginType::Basic { success_redirect } => { + let app = Router::new().route( + "/", + get(|login_payload:Query| { + async move { + let _ = login_token.set(login_payload.0.token); + route_handle.shutdown(); + Redirect::to(&success_redirect) + } + }), + ); + + axum_server::bind(addr) + .handle(handle) + .serve(app.into_make_service()) + .await + .expect("failed to start one-shot server"); + }, + LoginType::SSO => { + let app = Router::new().route( + "/", + get(|sso_payload:Query| { + async move { + let (token, location) = get_token_and_redirect(sso_payload.0).unwrap(); + if let Some(token) = token { + // If token is already set, it's not a big deal, so we ignore the + // error. + let _ = login_token.set(token); + } + route_handle.shutdown(); + Redirect::to(location.as_str()) + } + }), + ); + + axum_server::bind(addr) + .handle(handle) + .serve(app.into_make_service()) + .await + .expect("failed to start one-shot server"); + }, + } + + Ok(()) + } +} + +fn get_token_and_redirect(payload:SsoPayload) -> Result<(Option, Url), Error> { + let location_stub = "https://vercel.com/notifications/cli-login/turbo/"; + if let Some(login_error) = payload.login_error { + let mut url = Url::parse(&format!("{}failed", location_stub))?; + url.query_pairs_mut().append_pair("loginError", login_error.as_str()); + return Ok((None, url)); + } + + if let Some(sso_email) = payload.sso_email { + let mut url = Url::parse(&format!("{}incomplete", location_stub))?; + url.query_pairs_mut().append_pair("ssoEmail", sso_email.as_str()); + if let Some(team_name) = payload.team_name { + url.query_pairs_mut().append_pair("teamName", team_name.as_str()); + } + if let Some(sso_type) = payload.sso_type { + url.query_pairs_mut().append_pair("ssoType", sso_type.as_str()); + } + + return Ok((None, url)); + } + let mut url = Url::parse(&format!("{}success", location_stub))?; + if let Some(email) = payload.email { + url.query_pairs_mut().append_pair("email", email.as_str()); + } + + Ok((payload.token, url)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_token_and_redirect() { + assert_eq!( + get_token_and_redirect(SsoPayload::default()).unwrap(), + ( + None, + Url::parse("https://vercel.com/notifications/cli-login/turbo/success").unwrap() + ) + ); + + assert_eq!( + get_token_and_redirect(SsoPayload { + login_error:Some("error".to_string()), + ..SsoPayload::default() + }) + .unwrap(), + ( + None, + Url::parse( + "https://vercel.com/notifications/cli-login/turbo/failed?loginError=error" + ) + .unwrap() + ) + ); + + assert_eq!( + get_token_and_redirect(SsoPayload { + sso_email:Some("email".to_string()), + ..SsoPayload::default() + }) + .unwrap(), + ( + None, + Url::parse( + "https://vercel.com/notifications/cli-login/turbo/incomplete?ssoEmail=email" + ) + .unwrap() + ) + ); + + assert_eq!( + get_token_and_redirect(SsoPayload { + sso_email: Some("email".to_string()), + team_name: Some("team".to_string()), + ..SsoPayload::default() + }).unwrap(), + ( + None, + Url::parse("https://vercel.com/notifications/cli-login/turbo/incomplete?ssoEmail=email&teamName=team") + .unwrap() + ) + ); + + assert_eq!( + get_token_and_redirect(SsoPayload { + token:Some("token".to_string()), + ..SsoPayload::default() + }) + .unwrap(), + ( + Some("token".to_string()), + Url::parse("https://vercel.com/notifications/cli-login/turbo/success").unwrap() + ) + ); + } +} diff --git a/crates/turborepo-auth/Source/ui/messages.rs b/crates/turborepo-auth/Source/ui/messages.rs new file mode 100644 index 0000000000000..93b884d90f189 --- /dev/null +++ b/crates/turborepo-auth/Source/ui/messages.rs @@ -0,0 +1,17 @@ +use turborepo_ui::{BOLD, CYAN, ColorConfig}; + +pub fn print_cli_authorized(user:&str, color_config:&ColorConfig) { + println!( + " +{} Turborepo CLI authorized for {} +{} +{} +", + color_config.rainbow(">>> Success!"), + user, + color_config.apply( + CYAN.apply_to("To connect to your Remote Cache, run the following in any turborepo:") + ), + color_config.apply(BOLD.apply_to(" npx turbo link")) + ); +} diff --git a/crates/turborepo-auth/src/ui/mod.rs b/crates/turborepo-auth/Source/ui/mod.rs similarity index 100% rename from crates/turborepo-auth/src/ui/mod.rs rename to crates/turborepo-auth/Source/ui/mod.rs diff --git a/crates/turborepo-auth/src/auth/login.rs b/crates/turborepo-auth/src/auth/login.rs deleted file mode 100644 index d2fa22be6facb..0000000000000 --- a/crates/turborepo-auth/src/auth/login.rs +++ /dev/null @@ -1,397 +0,0 @@ -use std::sync::Arc; - -pub use error::Error; -use reqwest::Url; -use tokio::sync::OnceCell; -use tracing::{debug, warn}; -use turborepo_api_client::{CacheClient, Client, TokenClient}; -use turborepo_ui::{start_spinner, ColorConfig, BOLD}; - -use crate::{auth::extract_vercel_token, error, ui, LoginOptions, Token}; - -const DEFAULT_HOST_NAME: &str = "127.0.0.1"; -const DEFAULT_PORT: u16 = 9789; - -/// Login returns a `Token` struct. If a token is already present, -/// we do not overwrite it and instead log that we found an existing token, -/// setting the `exists` field to `true`. -/// -/// First checks if an existing option has been passed in, then if the login is -/// to Vercel, checks if the user has a Vercel CLI token on disk. -pub async fn login( - options: &LoginOptions<'_, T>, -) -> Result { - let LoginOptions { - api_client, - color_config, - login_url: login_url_configuration, - login_server, - existing_token, - force, - sso_team: _, - } = *options; // Deref or we get double references for each of these - - // I created a closure that gives back a closure since the `is_valid` checks do - // a call to get the user, so instead of doing that multiple times we have - // `is_valid` give back the user email. - // - // In the future I want to make the Token have some non-skewable information and - // be able to get rid of this, but it works for now. - let valid_token_callback = |message: &str, color_config: &ColorConfig| { - let message = message.to_string(); - let color_config = *color_config; - move |user_email: &str| { - println!("{}", color_config.apply(BOLD.apply_to(message))); - ui::print_cli_authorized(user_email, &color_config); - } - }; - - // Check if passed in token exists first. - if !force { - if let Some(token) = existing_token { - debug!("found existing turbo token"); - let token = Token::existing(token.into()); - if token - .is_valid( - api_client, - Some(valid_token_callback("Existing token found!", color_config)), - ) - .await? - { - return Ok(token); - } - // If the user is logging into Vercel, check for an existing `vc` token. - } else if login_url_configuration.contains("vercel.com") { - // The extraction can return an error, but we don't want to fail the login if - // the token is not found. - if let Ok(Some(token)) = extract_vercel_token() { - debug!("found existing Vercel token"); - let token = Token::existing(token); - if token - .is_valid( - api_client, - Some(valid_token_callback( - "Existing Vercel token found!", - color_config, - )), - ) - .await? - { - return Ok(token); - } - } - } - } - - let redirect_url = format!("http://{DEFAULT_HOST_NAME}:{DEFAULT_PORT}"); - let mut login_url = Url::parse(login_url_configuration)?; - let mut success_url = login_url.clone(); - success_url - .path_segments_mut() - .map_err(|_: ()| Error::LoginUrlCannotBeABase { - value: login_url_configuration.to_string(), - })? - .extend(["turborepo", "success"]); - - // Create the full login URL. - login_url - .path_segments_mut() - .map_err(|_: ()| Error::LoginUrlCannotBeABase { - value: login_url_configuration.to_string(), - })? - .extend(["turborepo", "token"]); - - login_url - .query_pairs_mut() - .append_pair("redirect_uri", &redirect_url); - - println!(">>> Opening browser to {login_url}"); - let spinner = start_spinner("Waiting for your authorization..."); - - // Try to open browser for auth confirmation. - let url = login_url.as_str(); - if !cfg!(test) && webbrowser::open(url).is_err() { - warn!("Failed to open browser. Please visit {url} in your browser."); - } - - let token_cell = Arc::new(OnceCell::new()); - login_server - .run( - DEFAULT_PORT, - crate::LoginType::Basic { - success_redirect: success_url.to_string(), - }, - token_cell.clone(), - ) - .await?; - - spinner.finish_and_clear(); - - let token = token_cell.get().ok_or(Error::FailedToGetToken)?; - - // TODO: make this a request to /teams endpoint instead? - let user_response = api_client - .get_user(token.as_str()) - .await - .map_err(Error::FailedToFetchUser)?; - - ui::print_cli_authorized(&user_response.user.email, color_config); - - Ok(Token::new(token.into())) -} - -#[cfg(test)] -mod tests { - use std::{assert_matches::assert_matches, sync::atomic::AtomicUsize}; - - use async_trait::async_trait; - use reqwest::{Method, RequestBuilder, Response}; - use turborepo_vercel_api::{ - CachingStatus, CachingStatusResponse, Membership, Role, SpacesResponse, Team, - TeamsResponse, User, UserResponse, VerifiedSsoUser, - }; - use turborepo_vercel_api_mock::start_test_server; - - use super::*; - use crate::{login_server, LoginServer}; - - struct MockLoginServer { - hits: Arc, - } - - #[async_trait] - impl LoginServer for MockLoginServer { - async fn run( - &self, - _: u16, - _: login_server::LoginType, - login_token: Arc>, - ) -> Result<(), Error> { - self.hits.fetch_add(1, std::sync::atomic::Ordering::SeqCst); - login_token - .set(turborepo_vercel_api_mock::EXPECTED_TOKEN.to_string()) - .unwrap(); - Ok(()) - } - } - - #[derive(Debug, thiserror::Error)] - enum MockApiError { - #[error("Empty token")] - EmptyToken, - } - - impl From for turborepo_api_client::Error { - fn from(error: MockApiError) -> Self { - match error { - MockApiError::EmptyToken => turborepo_api_client::Error::UnknownStatus { - code: "empty token".to_string(), - message: "token is empty".to_string(), - backtrace: std::backtrace::Backtrace::capture(), - }, - } - } - } - - struct MockApiClient { - pub base_url: String, - } - - impl MockApiClient { - fn new() -> Self { - Self { - base_url: String::new(), - } - } - } - - impl Client for MockApiClient { - async fn get_user(&self, token: &str) -> turborepo_api_client::Result { - if token.is_empty() { - return Err(MockApiError::EmptyToken.into()); - } - - Ok(UserResponse { - user: User { - id: "id".to_string(), - username: "username".to_string(), - email: "email".to_string(), - name: None, - created_at: None, - }, - }) - } - async fn get_teams(&self, token: &str) -> turborepo_api_client::Result { - if token.is_empty() { - return Err(MockApiError::EmptyToken.into()); - } - - Ok(TeamsResponse { - teams: vec![Team { - id: "id".to_string(), - slug: "something".to_string(), - name: "name".to_string(), - created_at: 0, - created: chrono::Utc::now(), - membership: Membership::new(Role::Member), - }], - }) - } - async fn get_team( - &self, - _token: &str, - _team_id: &str, - ) -> turborepo_api_client::Result> { - unimplemented!("get_team") - } - fn add_ci_header(_request_builder: RequestBuilder) -> RequestBuilder { - unimplemented!("add_ci_header") - } - async fn get_spaces( - &self, - _token: &str, - _team_id: Option<&str>, - ) -> turborepo_api_client::Result { - unimplemented!("get_spaces") - } - async fn verify_sso_token( - &self, - token: &str, - _: &str, - ) -> turborepo_api_client::Result { - Ok(VerifiedSsoUser { - token: token.to_string(), - team_id: Some("team_id".to_string()), - }) - } - async fn handle_403(_response: Response) -> turborepo_api_client::Error { - unimplemented!("handle_403") - } - fn make_url(&self, endpoint: &str) -> turborepo_api_client::Result { - let url = format!("{}{}", self.base_url, endpoint); - Url::parse(&url).map_err(|err| turborepo_api_client::Error::InvalidUrl { url, err }) - } - } - - impl TokenClient for MockApiClient { - async fn get_metadata( - &self, - token: &str, - ) -> turborepo_api_client::Result - { - if token.is_empty() { - return Err(MockApiError::EmptyToken.into()); - } - - Ok(turborepo_vercel_api::token::ResponseTokenMetadata { - id: "id".to_string(), - name: "name".to_string(), - token_type: "token".to_string(), - origin: "github".to_string(), - scopes: vec![turborepo_vercel_api::token::Scope { - scope_type: "user".to_string(), - origin: "github".to_string(), - team_id: None, - expires_at: None, - created_at: 1111111111111, - }], - active_at: 0, - created_at: 123456, - }) - } - async fn delete_token(&self, _token: &str) -> turborepo_api_client::Result<()> { - Ok(()) - } - } - - impl CacheClient for MockApiClient { - async fn get_artifact( - &self, - _hash: &str, - _token: &str, - _team_id: Option<&str>, - _team_slug: Option<&str>, - _method: Method, - ) -> Result, turborepo_api_client::Error> { - unimplemented!("get_artifact") - } - async fn put_artifact( - &self, - _hash: &str, - _artifact_body: impl turborepo_api_client::Stream< - Item = Result, - > + Send - + Sync - + 'static, - _body_len: usize, - _duration: u64, - _tag: Option<&str>, - _token: &str, - _team_id: Option<&str>, - _team_slug: Option<&str>, - ) -> Result<(), turborepo_api_client::Error> { - unimplemented!("set_artifact") - } - async fn fetch_artifact( - &self, - _hash: &str, - _token: &str, - _team_id: Option<&str>, - _team_slug: Option<&str>, - ) -> Result, turborepo_api_client::Error> { - unimplemented!("fetch_artifact") - } - async fn artifact_exists( - &self, - _hash: &str, - _token: &str, - _team_id: Option<&str>, - _team_slug: Option<&str>, - ) -> Result, turborepo_api_client::Error> { - unimplemented!("artifact_exists") - } - async fn get_caching_status( - &self, - _token: &str, - _team_id: Option<&str>, - _team_slug: Option<&str>, - ) -> Result { - Ok(CachingStatusResponse { - status: CachingStatus::Enabled, - }) - } - } - - #[tokio::test] - async fn test_login() { - let port = port_scanner::request_open_port().unwrap(); - let api_server = tokio::spawn(start_test_server(port)); - let color_config = ColorConfig::new(false); - let url = format!("http://localhost:{port}"); - - let api_client = MockApiClient::new(); - - let login_server = MockLoginServer { - hits: Arc::new(0.into()), - }; - let mut options = LoginOptions::new(&color_config, &url, &api_client, &login_server); - - let token = login(&options).await.unwrap(); - assert_matches!(token, Token::New(..)); - - let got_token = token.into_inner().to_string(); - assert_eq!(&got_token, turborepo_vercel_api_mock::EXPECTED_TOKEN); - - // Call the login function a second time to test that we check for existing - // tokens. Total server hits should be 1. - options.existing_token = Some(&got_token); - let second_token = login(&options).await.unwrap(); - assert!(matches!(second_token, Token::Existing(..))); - - api_server.abort(); - assert_eq!( - login_server.hits.load(std::sync::atomic::Ordering::SeqCst), - 1 - ); - } -} diff --git a/crates/turborepo-auth/src/auth/logout.rs b/crates/turborepo-auth/src/auth/logout.rs deleted file mode 100644 index 4d50a47d5030d..0000000000000 --- a/crates/turborepo-auth/src/auth/logout.rs +++ /dev/null @@ -1,213 +0,0 @@ -use tracing::error; -use turbopath::AbsoluteSystemPath; -use turborepo_api_client::TokenClient; -use turborepo_dirs::{config_dir, vercel_config_dir}; -use turborepo_ui::{cprintln, GREY}; - -use crate::{ - Error, LogoutOptions, Token, TURBO_TOKEN_DIR, TURBO_TOKEN_FILE, VERCEL_TOKEN_DIR, - VERCEL_TOKEN_FILE, -}; - -pub async fn logout(options: &LogoutOptions) -> Result<(), Error> { - if let Err(err) = options.remove_tokens().await { - error!("could not logout. Something went wrong: {}", err); - return Err(err); - } - - cprintln!(options.color_config, GREY, ">>> Logged out"); - Ok(()) -} - -impl LogoutOptions { - async fn try_remove_token(&self, path: &AbsoluteSystemPath) -> Result<(), Error> { - // Read the existing content from the global configuration path - let Ok(content) = path.read_to_string() else { - return Ok(()); - }; - - if self.invalidate { - match Token::from_file(path) { - Ok(token) => token.invalidate(&self.api_client).await?, - // If token doesn't exist, don't do anything. - Err(Error::TokenNotFound) => {} - Err(err) => return Err(err), - } - } - - // Attempt to deserialize the content into a serde_json::Value - let mut data: serde_json::Value = serde_json::from_str(&content)?; - - // Check if the data is an object and remove the "token" field if present - if let Some(obj) = data.as_object_mut() { - if obj.remove("token").is_none() { - return Ok(()); - } - } else { - return Ok(()); - } - - // Serialize the updated data back to a string - let new_content = serde_json::to_string_pretty(&data)?; - - // Write the updated content back to the file - path.create_with_contents(new_content)?; - - Ok(()) - } - - async fn remove_tokens(&self) -> Result<(), Error> { - #[cfg(test)] - if let Some(path) = &self.path { - return self.try_remove_token(path).await; - } - - if let Some(vercel_config_dir) = vercel_config_dir()? { - self.try_remove_token( - &vercel_config_dir.join_components(&[VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE]), - ) - .await?; - } - if let Some(turbo_config_dir) = config_dir()? { - self.try_remove_token( - &turbo_config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE]), - ) - .await?; - } - - Ok(()) - } -} -#[cfg(test)] -mod tests { - use std::backtrace::Backtrace; - - use reqwest::{RequestBuilder, Response}; - use tempfile::tempdir; - use turbopath::AbsoluteSystemPathBuf; - use turborepo_api_client::Client; - use turborepo_ui::ColorConfig; - use turborepo_vercel_api::{ - token::ResponseTokenMetadata, SpacesResponse, Team, TeamsResponse, UserResponse, - VerifiedSsoUser, - }; - use url::Url; - - use super::*; - - struct MockApiClient { - pub succeed_delete_request: bool, - } - - impl Client for MockApiClient { - async fn get_user(&self, _token: &str) -> turborepo_api_client::Result { - unimplemented!("get_user") - } - async fn get_teams(&self, _token: &str) -> turborepo_api_client::Result { - unimplemented!("get_teams") - } - async fn get_team( - &self, - _token: &str, - _team_id: &str, - ) -> turborepo_api_client::Result> { - unimplemented!("get_team") - } - fn add_ci_header(_request_builder: RequestBuilder) -> RequestBuilder { - unimplemented!("add_ci_header") - } - async fn get_spaces( - &self, - _token: &str, - _team_id: Option<&str>, - ) -> turborepo_api_client::Result { - unimplemented!("get_spaces") - } - async fn verify_sso_token( - &self, - token: &str, - _: &str, - ) -> turborepo_api_client::Result { - Ok(VerifiedSsoUser { - token: token.to_string(), - team_id: Some("team_id".to_string()), - }) - } - async fn handle_403(_response: Response) -> turborepo_api_client::Error { - unimplemented!("handle_403") - } - fn make_url(&self, _endpoint: &str) -> turborepo_api_client::Result { - unimplemented!("make_url") - } - } - - impl TokenClient for MockApiClient { - async fn delete_token(&self, _token: &str) -> turborepo_api_client::Result<()> { - if self.succeed_delete_request { - Ok(()) - } else { - Err(turborepo_api_client::Error::UnknownStatus { - code: "code".to_string(), - message: "this failed".to_string(), - backtrace: Backtrace::capture(), - }) - } - } - async fn get_metadata( - &self, - _token: &str, - ) -> turborepo_api_client::Result { - unimplemented!("get_metadata") - } - } - - #[tokio::test] - async fn test_remove_token() { - let tmp_dir = tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tmp_dir.path().join("config.json")) - .expect("could not create path"); - let content = r#"{"token":"some-token"}"#; - path.create_with_contents(content) - .expect("could not create file"); - - let logout_options = LogoutOptions { - color_config: ColorConfig::new(false), - api_client: MockApiClient { - succeed_delete_request: true, - }, - invalidate: false, - path: Some(path.clone()), - }; - - logout_options.remove_tokens().await.unwrap(); - - let new_content = path.read_to_string().unwrap(); - assert_eq!(new_content, "{}"); - } - - #[tokio::test] - async fn test_invalidate_token() { - let tmp_dir = tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tmp_dir.path().join("config.json")) - .expect("could not create path"); - let content = r#"{"token":"some-token"}"#; - path.create_with_contents(content) - .expect("could not create file"); - - let api_client = MockApiClient { - succeed_delete_request: true, - }; - - let options = LogoutOptions { - color_config: ColorConfig::new(false), - api_client, - path: Some(path.clone()), - invalidate: true, - }; - - logout(&options).await.unwrap(); - - let new_content = path.read_to_string().unwrap(); - assert_eq!(new_content, "{}"); - } -} diff --git a/crates/turborepo-auth/src/auth/mod.rs b/crates/turborepo-auth/src/auth/mod.rs deleted file mode 100644 index bac8ef2add74c..0000000000000 --- a/crates/turborepo-auth/src/auth/mod.rs +++ /dev/null @@ -1,74 +0,0 @@ -mod login; -mod logout; -mod sso; - -pub use login::*; -pub use logout::*; -pub use sso::*; -#[cfg(test)] -use turbopath::AbsoluteSystemPathBuf; -use turborepo_api_client::{CacheClient, Client, TokenClient}; -use turborepo_ui::ColorConfig; - -use crate::LoginServer; - -const VERCEL_TOKEN_DIR: &str = "com.vercel.cli"; -const VERCEL_TOKEN_FILE: &str = "auth.json"; - -pub struct LoginOptions<'a, T: Client + TokenClient + CacheClient> { - pub color_config: &'a ColorConfig, - pub login_url: &'a str, - pub api_client: &'a T, - pub login_server: &'a dyn LoginServer, - - pub sso_team: Option<&'a str>, - pub existing_token: Option<&'a str>, - pub force: bool, -} -impl<'a, T: Client + TokenClient + CacheClient> LoginOptions<'a, T> { - pub fn new( - color_config: &'a ColorConfig, - login_url: &'a str, - api_client: &'a T, - login_server: &'a dyn LoginServer, - ) -> Self { - Self { - color_config, - login_url, - api_client, - login_server, - sso_team: None, - existing_token: None, - force: false, - } - } -} - -/// Options for logging out. -pub struct LogoutOptions { - pub color_config: ColorConfig, - pub api_client: T, - /// If we should invalidate the token on the server. - pub invalidate: bool, - /// Path override for testing - #[cfg(test)] - pub path: Option, -} - -fn extract_vercel_token() -> Result, Error> { - let vercel_config_dir = - turborepo_dirs::vercel_config_dir()?.ok_or_else(|| Error::ConfigDirNotFound)?; - - let vercel_token_path = - vercel_config_dir.join_components(&[VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE]); - let contents = std::fs::read_to_string(vercel_token_path)?; - - #[derive(serde::Deserialize)] - struct VercelToken { - // This isn't actually dead code, it's used by serde to deserialize the JSON. - #[allow(dead_code)] - token: Option, - } - - Ok(serde_json::from_str::(&contents)?.token) -} diff --git a/crates/turborepo-auth/src/login_server.rs b/crates/turborepo-auth/src/login_server.rs deleted file mode 100644 index 0ef4ebd8a0952..0000000000000 --- a/crates/turborepo-auth/src/login_server.rs +++ /dev/null @@ -1,203 +0,0 @@ -use std::{net::SocketAddr, sync::Arc}; - -use anyhow::Result; -use async_trait::async_trait; -use axum::{extract::Query, response::Redirect, routing::get, Router}; -use serde::Deserialize; -use tokio::sync::OnceCell; -use url::Url; - -use crate::Error; - -pub enum LoginType { - Basic { success_redirect: String }, - SSO, -} - -#[derive(Debug, Clone, Deserialize)] -struct LoginPayload { - token: String, -} - -#[derive(Debug, Default, Clone, Deserialize)] -#[allow(dead_code)] -pub struct SsoPayload { - login_error: Option, - sso_email: Option, - team_name: Option, - sso_type: Option, - token: Option, - email: Option, -} - -#[async_trait] -pub trait LoginServer { - async fn run( - &self, - port: u16, - login_type: LoginType, - token: Arc>, - ) -> Result<(), Error>; -} - -/// A struct that implements LoginServer. -/// -/// Listens on 127.0.0.1 and a port that's passed in. -pub struct DefaultLoginServer; - -#[async_trait] -impl LoginServer for DefaultLoginServer { - async fn run( - &self, - port: u16, - login_type: LoginType, - login_token: Arc>, - ) -> Result<(), Error> { - let handle = axum_server::Handle::new(); - let route_handle = handle.clone(); - let addr = SocketAddr::from(([127, 0, 0, 1], port)); - match login_type { - LoginType::Basic { success_redirect } => { - let app = Router::new().route( - "/", - get(|login_payload: Query| async move { - let _ = login_token.set(login_payload.0.token); - route_handle.shutdown(); - Redirect::to(&success_redirect) - }), - ); - - axum_server::bind(addr) - .handle(handle) - .serve(app.into_make_service()) - .await - .expect("failed to start one-shot server"); - } - LoginType::SSO => { - let app = Router::new().route( - "/", - get(|sso_payload: Query| async move { - let (token, location) = get_token_and_redirect(sso_payload.0).unwrap(); - if let Some(token) = token { - // If token is already set, it's not a big deal, so we ignore the error. - let _ = login_token.set(token); - } - route_handle.shutdown(); - Redirect::to(location.as_str()) - }), - ); - - axum_server::bind(addr) - .handle(handle) - .serve(app.into_make_service()) - .await - .expect("failed to start one-shot server"); - } - } - - Ok(()) - } -} - -fn get_token_and_redirect(payload: SsoPayload) -> Result<(Option, Url), Error> { - let location_stub = "https://vercel.com/notifications/cli-login/turbo/"; - if let Some(login_error) = payload.login_error { - let mut url = Url::parse(&format!("{}failed", location_stub))?; - url.query_pairs_mut() - .append_pair("loginError", login_error.as_str()); - return Ok((None, url)); - } - - if let Some(sso_email) = payload.sso_email { - let mut url = Url::parse(&format!("{}incomplete", location_stub))?; - url.query_pairs_mut() - .append_pair("ssoEmail", sso_email.as_str()); - if let Some(team_name) = payload.team_name { - url.query_pairs_mut() - .append_pair("teamName", team_name.as_str()); - } - if let Some(sso_type) = payload.sso_type { - url.query_pairs_mut() - .append_pair("ssoType", sso_type.as_str()); - } - - return Ok((None, url)); - } - let mut url = Url::parse(&format!("{}success", location_stub))?; - if let Some(email) = payload.email { - url.query_pairs_mut().append_pair("email", email.as_str()); - } - - Ok((payload.token, url)) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_get_token_and_redirect() { - assert_eq!( - get_token_and_redirect(SsoPayload::default()).unwrap(), - ( - None, - Url::parse("https://vercel.com/notifications/cli-login/turbo/success").unwrap() - ) - ); - - assert_eq!( - get_token_and_redirect(SsoPayload { - login_error: Some("error".to_string()), - ..SsoPayload::default() - }) - .unwrap(), - ( - None, - Url::parse( - "https://vercel.com/notifications/cli-login/turbo/failed?loginError=error" - ) - .unwrap() - ) - ); - - assert_eq!( - get_token_and_redirect(SsoPayload { - sso_email: Some("email".to_string()), - ..SsoPayload::default() - }) - .unwrap(), - ( - None, - Url::parse( - "https://vercel.com/notifications/cli-login/turbo/incomplete?ssoEmail=email" - ) - .unwrap() - ) - ); - - assert_eq!( - get_token_and_redirect(SsoPayload { - sso_email: Some("email".to_string()), - team_name: Some("team".to_string()), - ..SsoPayload::default() - }).unwrap(), - ( - None, - Url::parse("https://vercel.com/notifications/cli-login/turbo/incomplete?ssoEmail=email&teamName=team") - .unwrap() - ) - ); - - assert_eq!( - get_token_and_redirect(SsoPayload { - token: Some("token".to_string()), - ..SsoPayload::default() - }) - .unwrap(), - ( - Some("token".to_string()), - Url::parse("https://vercel.com/notifications/cli-login/turbo/success").unwrap() - ) - ); - } -} diff --git a/crates/turborepo-auth/src/ui/messages.rs b/crates/turborepo-auth/src/ui/messages.rs deleted file mode 100644 index edd08db023cb4..0000000000000 --- a/crates/turborepo-auth/src/ui/messages.rs +++ /dev/null @@ -1,17 +0,0 @@ -use turborepo_ui::{ColorConfig, BOLD, CYAN}; - -pub fn print_cli_authorized(user: &str, color_config: &ColorConfig) { - println!( - " -{} Turborepo CLI authorized for {} -{} -{} -", - color_config.rainbow(">>> Success!"), - user, - color_config.apply( - CYAN.apply_to("To connect to your Remote Cache, run the following in any turborepo:") - ), - color_config.apply(BOLD.apply_to(" npx turbo link")) - ); -} diff --git a/crates/turborepo-cache/Cargo.toml b/crates/turborepo-cache/Cargo.toml index acfdf821d4010..481b4897b5c59 100644 --- a/crates/turborepo-cache/Cargo.toml +++ b/crates/turborepo-cache/Cargo.toml @@ -1,32 +1,5 @@ -[package] -name = "turborepo-cache" -version = "0.1.0" -license = "MIT" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[features] -native-tls = ["turborepo-api-client/native-tls"] -rustls-tls = ["turborepo-api-client/rustls-tls"] - - -[dev-dependencies] -anyhow = { workspace = true, features = ["backtrace"] } -futures = { workspace = true } -insta = { workspace = true } -libc = "0.2.146" -port_scanner = { workspace = true } -tempfile = { workspace = true } -test-case = { workspace = true } -turborepo-vercel-api = { workspace = true } -turborepo-vercel-api-mock = { workspace = true } - -[lints] -workspace = true - [dependencies] base64 = "0.21.0" -bytes.workspace = true camino = { workspace = true } futures = { workspace = true } hmac = "0.12.1" @@ -49,3 +22,33 @@ turbopath = { workspace = true } turborepo-analytics = { workspace = true } turborepo-api-client = { workspace = true } zstd = "0.12.3" + +[dependencies.bytes] +workspace = true + +[dev-dependencies] +anyhow = { workspace = true, features = ["backtrace"] } +futures = { workspace = true } +insta = { workspace = true } +libc = "0.2.146" +port_scanner = { workspace = true } +tempfile = { workspace = true } +test-case = { workspace = true } +turborepo-vercel-api = { workspace = true } +turborepo-vercel-api-mock = { workspace = true } + +[features] +native-tls = ["turborepo-api-client/native-tls"] +rustls-tls = ["turborepo-api-client/rustls-tls"] + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-cache" +version = "0.1.0" diff --git a/crates/turborepo-cache/Source/async_cache.rs b/crates/turborepo-cache/Source/async_cache.rs new file mode 100644 index 0000000000000..d9804fcc8cb83 --- /dev/null +++ b/crates/turborepo-cache/Source/async_cache.rs @@ -0,0 +1,487 @@ +use std::sync::{Arc, Mutex, atomic::AtomicU8}; + +use futures::{StreamExt, stream::FuturesUnordered}; +use tokio::sync::{Semaphore, mpsc, oneshot}; +use tracing::{Instrument, Level, warn}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; +use turborepo_analytics::AnalyticsSender; +use turborepo_api_client::{APIAuth, APIClient}; + +use crate::{ + CacheError, + CacheHitMetadata, + CacheOpts, + http::UploadMap, + multiplexer::CacheMultiplexer, +}; + +const WARNING_CUTOFF:u8 = 4; + +#[derive(Clone)] +pub struct AsyncCache { + real_cache:Arc, + writer_sender:mpsc::Sender, +} + +enum WorkerRequest { + WriteRequest { + anchor:AbsoluteSystemPathBuf, + key:String, + duration:u64, + files:Vec, + }, + Flush(oneshot::Sender<()>), + /// Shutdown the cache. The first oneshot notifies when shutdown starts and + /// allows the user to inspect the status of the uploads. The second + /// oneshot notifies when the shutdown is complete. + Shutdown(oneshot::Sender>>, oneshot::Sender<()>), +} + +impl AsyncCache { + pub fn new( + opts:&CacheOpts, + repo_root:&AbsoluteSystemPath, + api_client:APIClient, + api_auth:Option, + analytics_recorder:Option, + ) -> Result { + let max_workers = opts.workers.try_into().expect("usize is smaller than u32"); + let real_cache = Arc::new(CacheMultiplexer::new( + opts, + repo_root, + api_client, + api_auth, + analytics_recorder, + )?); + let (writer_sender, mut write_consumer) = mpsc::channel(1); + + // start a task to manage workers + let worker_real_cache = real_cache.clone(); + tokio::spawn(async move { + let semaphore = Arc::new(Semaphore::new(max_workers)); + let mut workers = FuturesUnordered::new(); + let real_cache = worker_real_cache; + let warnings = Arc::new(AtomicU8::new(0)); + + let mut shutdown_callback = None; + while let Some(request) = write_consumer.recv().await { + match request { + WorkerRequest::WriteRequest { anchor, key, duration, files } => { + let permit = semaphore.clone().acquire_owned().await.unwrap(); + let real_cache = real_cache.clone(); + let warnings = warnings.clone(); + let worker_span = tracing::span!(Level::TRACE, "cache worker: cache PUT"); + workers.push(tokio::spawn( + async move { + if let Err(err) = + real_cache.put(&anchor, &key, &files, duration).await + { + let num_warnings = + warnings.load(std::sync::atomic::Ordering::Acquire); + if num_warnings <= WARNING_CUTOFF { + warnings.store( + num_warnings + 1, + std::sync::atomic::Ordering::Release, + ); + warn!("{err}"); + } + } + // Release permit once we're done with the write + drop(permit); + } + .instrument(worker_span), + )) + }, + WorkerRequest::Flush(callback) => { + // Wait on all workers to finish writing + while let Some(worker) = workers.next().await { + let _ = worker; + } + drop(callback); + }, + WorkerRequest::Shutdown(closing, done) => { + shutdown_callback = Some((closing, done)); + break; + }, + }; + } + // Drop write consumer to immediately notify callers that cache is shutting down + drop(write_consumer); + + let shutdown_callback = if let Some((closing, done)) = shutdown_callback { + closing.send(real_cache.requests().unwrap_or_default()).ok(); + Some(done) + } else { + None + }; + + // wait for all writers to finish + while let Some(worker) = workers.next().await { + let _ = worker; + } + + if let Some(callback) = shutdown_callback { + callback.send(()).ok(); + } + }); + + Ok(AsyncCache { real_cache, writer_sender }) + } + + #[tracing::instrument(skip_all)] + pub async fn put( + &self, + anchor:AbsoluteSystemPathBuf, + key:String, + files:Vec, + duration:u64, + ) -> Result<(), CacheError> { + if self + .writer_sender + .send(WorkerRequest::WriteRequest { anchor, key, duration, files }) + .await + .is_err() + { + Err(CacheError::CacheShuttingDown) + } else { + Ok(()) + } + } + + #[tracing::instrument(skip_all)] + pub async fn exists(&self, key:&str) -> Result, CacheError> { + self.real_cache.exists(key).await + } + + #[tracing::instrument(skip_all)] + pub async fn fetch( + &self, + anchor:&AbsoluteSystemPath, + key:&str, + ) -> Result)>, CacheError> { + self.real_cache.fetch(anchor, key).await + } + + // Used for testing to ensure that the workers resolve + // before checking the cache. + #[tracing::instrument(skip_all)] + pub async fn wait(&self) -> Result<(), CacheError> { + let (tx, rx) = oneshot::channel(); + self.writer_sender + .send(WorkerRequest::Flush(tx)) + .await + .map_err(|_| CacheError::CacheShuttingDown)?; + // Wait until flush callback is finished + rx.await.ok(); + Ok(()) + } + + /// Shut down the cache, waiting for all workers to finish writing. + /// This function returns as soon as the shut down has started, + /// returning a channel through which workers can report on their + /// progress. + #[tracing::instrument(skip_all)] + pub async fn start_shutdown( + &self, + ) -> Result<(Arc>, oneshot::Receiver<()>), CacheError> { + let (closing_tx, closing_rx) = oneshot::channel::>>(); + let (closed_tx, closed_rx) = oneshot::channel::<()>(); + self.writer_sender + .send(WorkerRequest::Shutdown(closing_tx, closed_tx)) + .await + .map_err(|_| CacheError::CacheShuttingDown)?; + Ok((closing_rx.await.unwrap(), closed_rx)) // todo + } + + /// Shut down the cache, waiting for all workers to finish writing. + /// This function returns only when the last worker is complete. + /// It is a convenience wrapper around `start_shutdown`. + #[tracing::instrument(skip_all)] + pub async fn shutdown(&self) -> Result<(), CacheError> { + let (_, closed_rx) = self.start_shutdown().await?; + closed_rx.await.ok(); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::{assert_matches::assert_matches, time::Duration}; + + use anyhow::Result; + use camino::Utf8PathBuf; + use futures::future::try_join_all; + use tempfile::tempdir; + use turbopath::AbsoluteSystemPathBuf; + use turborepo_api_client::{APIAuth, APIClient}; + use turborepo_vercel_api_mock::start_test_server; + + use crate::{ + AsyncCache, + CacheActions, + CacheConfig, + CacheHitMetadata, + CacheOpts, + CacheSource, + RemoteCacheOpts, + test_cases::{TestCase, get_test_cases}, + }; + + #[tokio::test] + async fn test_async_cache() -> Result<()> { + let port = port_scanner::request_open_port().unwrap(); + let handle = tokio::spawn(start_test_server(port)); + + try_join_all(get_test_cases().into_iter().map(|test_case| { + async move { + round_trip_test_with_both_caches(&test_case, port).await?; + round_trip_test_without_remote_cache(&test_case).await?; + round_trip_test_without_fs(&test_case, port).await + } + })) + .await?; + + handle.abort(); + Ok(()) + } + + async fn round_trip_test_without_fs(test_case:&TestCase, port:u16) -> Result<()> { + let repo_root = tempdir()?; + let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; + test_case.initialize(&repo_root_path)?; + + let hash = format!("{}-no-fs", test_case.hash); + + let opts = CacheOpts { + cache_dir:Utf8PathBuf::from(".turbo/cache"), + cache:CacheConfig { + local:CacheActions { read:false, write:false }, + remote:CacheActions { read:true, write:true }, + }, + workers:10, + remote_cache_opts:Some(RemoteCacheOpts { + unused_team_id:Some("my-team".to_string()), + signature:false, + }), + }; + + let api_client = APIClient::new( + format!("http://localhost:{}", port), + Some(Duration::from_secs(200)), + None, + "2.0.0", + true, + )?; + let api_auth = Some(APIAuth { + team_id:Some("my-team-id".to_string()), + token:"my-token".to_string(), + team_slug:None, + }); + let async_cache = AsyncCache::new(&opts, &repo_root_path, api_client, api_auth, None)?; + + // Ensure that the cache is empty + let response = async_cache.exists(&hash).await; + + assert_matches!(response, Ok(None)); + + // Add test case + async_cache + .put( + repo_root_path.clone(), + hash.clone(), + test_case.files.iter().map(|f| f.path().to_owned()).collect(), + test_case.duration, + ) + .await + .unwrap(); + + // Wait for async cache to process + async_cache.wait().await.unwrap(); + + let fs_cache_path = + repo_root_path.join_components(&[".turbo", "cache", &format!("{}.tar.zst", hash)]); + + // Confirm that fs cache file does *not* exist + assert!(!fs_cache_path.exists()); + + let response = async_cache.exists(&hash).await?; + + // Confirm that we fetch from remote cache and not local. + assert_eq!( + response, + Some(CacheHitMetadata { source:CacheSource::Remote, time_saved:test_case.duration }) + ); + + async_cache.shutdown().await.unwrap(); + assert!(async_cache.shutdown().await.is_err(), "second shutdown should error"); + + Ok(()) + } + + async fn round_trip_test_without_remote_cache(test_case:&TestCase) -> Result<()> { + let repo_root = tempdir()?; + let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; + test_case.initialize(&repo_root_path)?; + + let hash = format!("{}-no-remote", test_case.hash); + + let opts = CacheOpts { + cache_dir:Utf8PathBuf::from(".turbo/cache"), + cache:CacheConfig { + local:CacheActions { read:true, write:true }, + remote:CacheActions { read:false, write:false }, + }, + workers:10, + remote_cache_opts:Some(RemoteCacheOpts { + unused_team_id:Some("my-team".to_string()), + signature:false, + }), + }; + + // Initialize client with invalid API url to ensure that we don't hit the + // network + let api_client = APIClient::new( + "http://example.com", + Some(Duration::from_secs(200)), + None, + "2.0.0", + true, + )?; + let api_auth = Some(APIAuth { + team_id:Some("my-team-id".to_string()), + token:"my-token".to_string(), + team_slug:None, + }); + let async_cache = AsyncCache::new(&opts, &repo_root_path, api_client, api_auth, None)?; + + // Ensure that the cache is empty + let response = async_cache.exists(&hash).await; + + assert_matches!(response, Ok(None)); + + // Add test case + async_cache + .put( + repo_root_path.clone(), + hash.clone(), + test_case.files.iter().map(|f| f.path().to_owned()).collect(), + test_case.duration, + ) + .await + .unwrap(); + + // Wait for async cache to process + async_cache.wait().await.unwrap(); + + let fs_cache_path = + repo_root_path.join_components(&[".turbo", "cache", &format!("{}.tar.zst", hash)]); + + // Confirm that fs cache file exists + assert!(fs_cache_path.exists()); + + let response = async_cache.exists(&hash).await?; + + // Confirm that we fetch from local cache first. + assert_eq!( + response, + Some(CacheHitMetadata { source:CacheSource::Local, time_saved:test_case.duration }) + ); + + // Remove fs cache file + fs_cache_path.remove_file()?; + + let response = async_cache.exists(&hash).await?; + + // Confirm that we get a cache miss + assert!(response.is_none()); + + async_cache.shutdown().await.unwrap(); + assert!(async_cache.shutdown().await.is_err(), "second shutdown should error"); + + Ok(()) + } + + async fn round_trip_test_with_both_caches(test_case:&TestCase, port:u16) -> Result<()> { + let repo_root = tempdir()?; + let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; + test_case.initialize(&repo_root_path)?; + + let hash = format!("{}-both", test_case.hash); + + let opts = CacheOpts { + cache_dir:Utf8PathBuf::from(".turbo/cache"), + cache:CacheConfig { + local:CacheActions { read:true, write:true }, + remote:CacheActions { read:true, write:true }, + }, + workers:10, + remote_cache_opts:Some(RemoteCacheOpts { + unused_team_id:Some("my-team".to_string()), + signature:false, + }), + }; + + let api_client = APIClient::new( + format!("http://localhost:{}", port), + Some(Duration::from_secs(200)), + None, + "2.0.0", + true, + )?; + let api_auth = Some(APIAuth { + team_id:Some("my-team-id".to_string()), + token:"my-token".to_string(), + team_slug:None, + }); + let async_cache = AsyncCache::new(&opts, &repo_root_path, api_client, api_auth, None)?; + + // Ensure that the cache is empty + let response = async_cache.exists(&hash).await; + + assert_matches!(response, Ok(None)); + + // Add test case + async_cache + .put( + repo_root_path.clone(), + hash.clone(), + test_case.files.iter().map(|f| f.path().to_owned()).collect(), + test_case.duration, + ) + .await + .unwrap(); + + // Wait for async cache to process + async_cache.wait().await.unwrap(); + + let fs_cache_path = + repo_root_path.join_components(&[".turbo", "cache", &format!("{}.tar.zst", hash)]); + + // Confirm that fs cache file exists + assert!(fs_cache_path.exists()); + + let response = async_cache.exists(&hash).await?; + + // Confirm that we fetch from local cache first. + assert_eq!( + response, + Some(CacheHitMetadata { source:CacheSource::Local, time_saved:test_case.duration }) + ); + + // Remove fs cache file + fs_cache_path.remove_file()?; + + let response = async_cache.exists(&hash).await?; + + // Confirm that we still can fetch from remote cache + assert_eq!( + response, + Some(CacheHitMetadata { source:CacheSource::Remote, time_saved:test_case.duration }) + ); + + async_cache.shutdown().await.unwrap(); + assert!(async_cache.shutdown().await.is_err(), "second shutdown should error"); + + Ok(()) + } +} diff --git a/crates/turborepo-cache/Source/cache_archive/create.rs b/crates/turborepo-cache/Source/cache_archive/create.rs new file mode 100644 index 0000000000000..17432b188832e --- /dev/null +++ b/crates/turborepo-cache/Source/cache_archive/create.rs @@ -0,0 +1,444 @@ +use std::{ + backtrace::Backtrace, + fs, + fs::OpenOptions, + io::{BufWriter, Read, Write}, + path::Path, +}; + +use tar::{EntryType, Header}; +use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, IntoUnix}; + +use crate::CacheError; + +pub struct CacheWriter<'a> { + builder:tar::Builder>, +} + +impl<'a> CacheWriter<'a> { + // Appends data to tar builder. + fn append_data( + &mut self, + header:&mut Header, + path:impl AsRef, + body:impl Read, + ) -> Result<(), CacheError> { + Ok(self.builder.append_data(header, path, body)?) + } + + fn append_link( + &mut self, + header:&mut Header, + path:impl AsRef, + target:impl AsRef, + ) -> Result<(), CacheError> { + Ok(self.builder.append_link(header, path, target)?) + } + + pub fn finish(mut self) -> Result<(), CacheError> { Ok(self.builder.finish()?) } + + pub fn from_writer(writer:impl Write + 'a, use_compression:bool) -> Result { + if use_compression { + let zw = zstd::Encoder::new(writer, 0)?.auto_finish(); + Ok(CacheWriter { builder:tar::Builder::new(Box::new(zw)) }) + } else { + Ok(CacheWriter { builder:tar::Builder::new(Box::new(writer)) }) + } + } + + // Makes a new CacheArchive at the specified path + // Wires up the chain of writers: + // tar::Builder -> zstd::Encoder (optional) -> BufWriter -> File + pub fn create(path:&AbsoluteSystemPath) -> Result { + let mut options = OpenOptions::new(); + options.write(true).create(true).truncate(true); + + let file = path.open_with_options(options)?; + + // Flush to disk in 1mb chunks. + let file_buffer = BufWriter::with_capacity(2usize.pow(20), file); + + let is_compressed = path.extension() == Some("zst"); + + if is_compressed { + let zw = zstd::Encoder::new(file_buffer, 0)?.auto_finish(); + + Ok(CacheWriter { builder:tar::Builder::new(Box::new(zw)) }) + } else { + Ok(CacheWriter { builder:tar::Builder::new(Box::new(file_buffer)) }) + } + } + + // Adds a user-cached item to the tar + pub(crate) fn add_file( + &mut self, + anchor:&AbsoluteSystemPath, + file_path:&AnchoredSystemPath, + ) -> Result<(), CacheError> { + // Resolve the fully-qualified path to the file to read it. + let source_path = anchor.resolve(file_path); + + // Grab the file info to construct the header. + let file_info = source_path.symlink_metadata()?; + + // Normalize the path within the cache + let mut file_path = file_path.to_unix(); + file_path.make_canonical_for_tar(file_info.is_dir()); + + let mut header = Self::create_header(&file_info)?; + + if matches!(header.entry_type(), EntryType::Regular) && file_info.len() > 0 { + let file = source_path.open()?; + self.append_data(&mut header, file_path.as_str(), file)?; + } else if matches!(header.entry_type(), EntryType::Symlink) { + // We convert to a Unix path because all paths in tar should be + // Unix-style. This will get restored to a system path. + let target = source_path.read_link()?.into_unix(); + self.append_link(&mut header, file_path.as_str(), &target)?; + } else { + self.append_data(&mut header, file_path.as_str(), &mut std::io::empty())?; + } + + Ok(()) + } + + fn create_header(file_info:&fs::Metadata) -> Result { + let mut header = Header::new_gnu(); + + let mode:u32; + #[cfg(unix)] + { + use std::os::unix::fs::MetadataExt; + mode = file_info.mode(); + } + #[cfg(windows)] + { + // Windows makes up 0o666 for files, which in the Go code + // we do: (0o666 & 0o755) | 0o111 which produces 0o755 + mode = 0o755 + } + header.set_mode(mode); + + if file_info.is_symlink() { + // We do *not* set the linkname here because it could be too long + // Instead we set it when we add the file to the archive + header.set_entry_type(EntryType::Symlink); + header.set_size(0); + } else if file_info.is_dir() { + header.set_size(0); + header.set_entry_type(EntryType::Directory); + } else if file_info.is_file() { + header.set_entry_type(EntryType::Regular); + header.set_size(file_info.len()); + } else { + // Throw an error if trying to create a cache that contains a type we don't + // support. + return Err(CacheError::CreateUnsupportedFileType(Backtrace::capture())); + } + + // Consistent creation + header.set_uid(0); + header.set_gid(0); + header.as_gnu_mut().unwrap().set_atime(0); + header.set_mtime(0); + header.as_gnu_mut().unwrap().set_ctime(0); + + Ok(header) + } +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use anyhow::Result; + use tempfile::tempdir; + use test_case::test_case; + use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; + + use super::*; + use crate::cache_archive::restore::CacheReader; + + #[derive(Debug)] + enum FileType { + Dir, + Symlink { linkname:String }, + Fifo, + File, + } + + #[derive(Debug)] + struct CreateFileDefinition { + path:AnchoredSystemPathBuf, + mode:u32, + file_type:FileType, + } + + fn create_entry(anchor:&AbsoluteSystemPath, file:&CreateFileDefinition) -> Result<()> { + match &file.file_type { + FileType::Dir => create_dir(anchor, file), + FileType::Symlink { linkname } => create_symlink(anchor, file, linkname), + FileType::Fifo => create_fifo(anchor, file), + FileType::File => create_file(anchor, file), + } + } + + fn create_dir(anchor:&AbsoluteSystemPath, file:&CreateFileDefinition) -> Result<()> { + let path = anchor.resolve(&file.path); + path.create_dir_all()?; + + #[cfg(unix)] + { + path.set_mode(file.mode & 0o777)?; + } + + Ok(()) + } + + fn create_symlink( + anchor:&AbsoluteSystemPath, + file:&CreateFileDefinition, + linkname:&str, + ) -> Result<()> { + let path = anchor.resolve(&file.path); + path.symlink_to_file(linkname)?; + + Ok(()) + } + + #[cfg(unix)] + fn create_fifo(anchor:&AbsoluteSystemPath, file:&CreateFileDefinition) -> Result<()> { + use std::ffi::CString; + + let path = anchor.resolve(&file.path); + let path_cstr = CString::new(path.as_str())?; + + unsafe { + libc::mkfifo(path_cstr.as_ptr(), 0o644); + } + + Ok(()) + } + + #[cfg(windows)] + fn create_fifo(_:&AbsoluteSystemPath, _:&CreateFileDefinition) -> Result<()> { + Err(CacheError::CreateUnsupportedFileType(Backtrace::capture()).into()) + } + + fn create_file(anchor:&AbsoluteSystemPath, file:&CreateFileDefinition) -> Result<()> { + let path = anchor.resolve(&file.path); + fs::write(&path, b"file contents")?; + #[cfg(unix)] + { + path.set_mode(file.mode & 0o777)?; + } + + Ok(()) + } + + #[test_case( + vec![ + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("hello world.txt").unwrap(), + mode: 0o644, + file_type: FileType::File, + } + ], + None + ; "create regular file" + )] + #[test_case( + vec![ + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("one").unwrap(), + mode: 0o777, + file_type: FileType::Symlink { linkname: "two".to_string() }, + }, + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("two").unwrap(), + mode: 0o777, + file_type: FileType::Symlink { linkname: "three".to_string() }, + }, + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("three").unwrap(), + mode: 0o777, + file_type: FileType::Symlink { linkname: "real".to_string() }, + }, + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("real").unwrap(), + mode: 0o777, + file_type: FileType::File, + } + ], + None + ; "create symlinks" + )] + #[test_case( + vec![ + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("parent").unwrap(), + mode: 0o777, + file_type: FileType::Dir, + }, + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("parent/child").unwrap(), + mode: 0o644, + file_type: FileType::File, + }, + ], + None + ; "create directory" + )] + #[test_case( + vec![ + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("one").unwrap(), + mode: 0o644, + file_type: FileType::Symlink { linkname: "two".to_string() }, + }, + ], + None + ; "create broken symlink" + )] + #[test_case( + vec![ + CreateFileDefinition { + path: AnchoredSystemPathBuf::from_raw("one").unwrap(), + mode: 0o644, + file_type: FileType::Fifo, + } + ], + Some("attempted to create unsupported file type") + ; "create unsupported" + )] + fn test_create( + files:Vec, + #[allow(unused_variables)] expected_err:Option<&str>, + ) -> Result<()> { + 'outer: for compressed in [false, true] { + let input_dir = tempdir()?; + let archive_dir = tempdir()?; + let input_dir_path = AbsoluteSystemPathBuf::try_from(input_dir.path())?; + let archive_path = if compressed { + AbsoluteSystemPathBuf::try_from(archive_dir.path().join("out.tar.zst"))? + } else { + AbsoluteSystemPathBuf::try_from(archive_dir.path().join("out.tar"))? + }; + + let mut cache_archive = CacheWriter::create(&archive_path)?; + + for file in files.iter() { + let result = create_entry(&input_dir_path, file); + if let Err(err) = result { + assert!(expected_err.is_some()); + assert_eq!(err.to_string(), expected_err.unwrap()); + continue 'outer; + } + + let result = cache_archive.add_file(&input_dir_path, &file.path); + if let Err(err) = result { + assert!(expected_err.is_some()); + assert_eq!(err.to_string(), expected_err.unwrap()); + continue 'outer; + } + } + + cache_archive.finish()?; + } + + Ok(()) + } + + #[test] + #[cfg(unix)] + fn test_add_trailing_slash_unix() { + let mut path = PathBuf::from("foo/bar"); + assert_eq!(path.to_string_lossy(), "foo/bar"); + path.push(""); + assert_eq!(path.to_string_lossy(), "foo/bar/"); + + // Confirm that this is idempotent + path.push(""); + assert_eq!(path.to_string_lossy(), "foo/bar/"); + } + + #[test] + #[cfg(windows)] + fn test_add_trailing_slash_windows() { + let mut path = PathBuf::from("foo\\bar"); + assert_eq!(path.to_string_lossy(), "foo\\bar"); + path.push(""); + assert_eq!(path.to_string_lossy(), "foo\\bar\\"); + + // Confirm that this is idempotent + path.push(""); + assert_eq!(path.to_string_lossy(), "foo\\bar\\"); + } + + #[test] + fn create_tar_with_really_long_name() -> Result<()> { + let archive_dir = tempdir()?; + let archive_dir_path = AbsoluteSystemPath::new(archive_dir.path().to_str().unwrap())?; + + let tar_dir = tempdir()?; + let tar_dir_path = AbsoluteSystemPath::new(tar_dir.path().to_str().unwrap())?; + + let tar_path = tar_dir_path.join_component("test.tar"); + let mut archive = CacheWriter::create(&tar_path)?; + let base = "this-is-a-really-really-really-long-path-like-so-very-long-that-i-can-list-all-of-my-favorite-directors-like-edward-yang-claire-denis-lucrecia-martel-wong-kar-wai-even-kurosawa"; + let file_name = format!("{base}.txt"); + let dir_symlink_name = format!("{base}-dir"); + let really_long_file = AnchoredSystemPath::new(&file_name).unwrap(); + let really_long_dir = AnchoredSystemPath::new(base).unwrap(); + let really_long_symlink = AnchoredSystemPath::new("this-is-a-really-really-really-long-symlink-like-so-very-long-that-i-can-list-all-of-my-other-favorite-directors-like-jim-jarmusch-michelangelo-antonioni-and-terrence-malick-symlink").unwrap(); + let really_long_dir_symlink = AnchoredSystemPath::new(&dir_symlink_name).unwrap(); + + let really_long_path = archive_dir_path.resolve(really_long_file); + really_long_path.create_with_contents("The End!")?; + + let really_long_symlink_path = archive_dir_path.resolve(really_long_symlink); + really_long_symlink_path.symlink_to_file(really_long_file.as_str())?; + + let really_long_dir_path = archive_dir_path.resolve(really_long_dir); + really_long_dir_path.create_dir_all()?; + + let really_long_dir_symlink_path = archive_dir_path.resolve(really_long_dir_symlink); + really_long_dir_symlink_path.symlink_to_dir(really_long_dir.as_str())?; + + archive.add_file(archive_dir_path, really_long_file)?; + archive.add_file(archive_dir_path, really_long_dir_symlink)?; + archive.add_file(archive_dir_path, really_long_dir)?; + archive.add_file(archive_dir_path, really_long_symlink)?; + + archive.finish()?; + + let restore_dir = tempdir()?; + let restore_dir_path = AbsoluteSystemPath::new(restore_dir.path().to_str().unwrap())?; + + let mut restore = CacheReader::open(&tar_path)?; + let files = restore.restore(restore_dir_path)?; + assert_eq!(files.len(), 4); + assert_eq!(files[0].as_str(), really_long_file.as_str()); + assert_eq!(files[1].as_str(), really_long_dir.as_str()); + assert_eq!(files[2].as_str(), really_long_symlink.as_str()); + assert_eq!(files[3].as_str(), really_long_dir_symlink.as_str()); + Ok(()) + } + + #[test] + fn test_compression() -> Result<()> { + let mut buffer = Vec::new(); + let mut encoder = zstd::Encoder::new(&mut buffer, 0)?.auto_finish(); + encoder.write_all(b"hello world")?; + // Should finish encoding on drop + drop(encoder); + + let mut decoder = zstd::Decoder::new(&buffer[..])?; + let mut out = String::new(); + decoder.read_to_string(&mut out)?; + + assert_eq!(out, "hello world"); + + Ok(()) + } +} diff --git a/crates/turborepo-cache/src/cache_archive/mod.rs b/crates/turborepo-cache/Source/cache_archive/mod.rs similarity index 100% rename from crates/turborepo-cache/src/cache_archive/mod.rs rename to crates/turborepo-cache/Source/cache_archive/mod.rs diff --git a/crates/turborepo-cache/Source/cache_archive/restore.rs b/crates/turborepo-cache/Source/cache_archive/restore.rs new file mode 100644 index 0000000000000..0b05c79462eb1 --- /dev/null +++ b/crates/turborepo-cache/Source/cache_archive/restore.rs @@ -0,0 +1,898 @@ +use std::{backtrace::Backtrace, collections::HashMap, io::Read}; + +use petgraph::graph::DiGraph; +use sha2::{Digest, Sha512}; +use tar::Entry; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; + +use crate::{ + CacheError, + cache_archive::{ + restore_directory::{CachedDirTree, restore_directory}, + restore_regular::restore_regular, + restore_symlink::{ + canonicalize_linkname, + restore_symlink, + restore_symlink_allow_missing_target, + }, + }, +}; + +pub struct CacheReader<'a> { + reader:Box, +} + +impl<'a> CacheReader<'a> { + pub fn from_reader(reader:impl Read + 'a, is_compressed:bool) -> Result { + let reader:Box = if is_compressed { + Box::new(zstd::Decoder::new(reader)?) + } else { + Box::new(reader) + }; + + Ok(CacheReader { reader }) + } + + pub fn open(path:&AbsoluteSystemPathBuf) -> Result { + let file = path.open()?; + let is_compressed = path.extension() == Some("zst"); + + let reader:Box = + if is_compressed { Box::new(zstd::Decoder::new(file)?) } else { Box::new(file) }; + + Ok(CacheReader { reader }) + } + + pub fn get_sha(mut self) -> Result, CacheError> { + let mut hasher = Sha512::new(); + let mut buffer = [0; 8192]; + loop { + let n = self.reader.read(&mut buffer)?; + if n == 0 { + break; + } + hasher.update(&buffer[..n]); + } + + Ok(hasher.finalize().to_vec()) + } + + pub fn restore( + &mut self, + anchor:&AbsoluteSystemPath, + ) -> Result, CacheError> { + let mut restored = Vec::new(); + anchor.create_dir_all()?; + + // We're going to make the following two assumptions here for "fast" + // path restoration: + // - All directories are enumerated in the `tar`. + // - The contents of the tar are enumerated depth-first. + // + // This allows us to avoid: + // - Attempts at recursive creation of directories. + // - Repetitive `lstat` on restore of a file. + // + // Violating these assumptions won't cause things to break but we're + // only going to maintain an `lstat` cache for the current tree. + // If you violate these assumptions and the current cache does + // not apply for your path, it will clobber and re-start from the common + // shared prefix. + let dir_cache = CachedDirTree::new(anchor.to_owned()); + let mut tr = tar::Archive::new(&mut self.reader); + + Self::restore_entries(&mut tr, &mut restored, dir_cache, anchor)?; + Ok(restored) + } + + fn restore_entries( + tr:&mut tar::Archive, + restored:&mut Vec, + mut dir_cache:CachedDirTree, + anchor:&AbsoluteSystemPath, + ) -> Result<(), CacheError> { + // On first attempt to restore it's possible that a link target doesn't exist. + // Save them and topologically sort them. + let mut symlinks = Vec::new(); + + for entry in tr.entries()? { + let mut entry = entry?; + match restore_entry(&mut dir_cache, anchor, &mut entry) { + Err(CacheError::LinkTargetDoesNotExist(..)) => { + symlinks.push(entry); + }, + Err(e) => return Err(e), + Ok(restored_path) => restored.push(restored_path), + } + } + + let mut restored_symlinks = + Self::topologically_restore_symlinks(&mut dir_cache, anchor, &symlinks)?; + restored.append(&mut restored_symlinks); + Ok(()) + } + + fn topologically_restore_symlinks( + dir_cache:&mut CachedDirTree, + anchor:&AbsoluteSystemPath, + symlinks:&[Entry<'_, T>], + ) -> Result, CacheError> { + let mut graph = DiGraph::new(); + let mut entry_lookup = HashMap::new(); + let mut restored = Vec::new(); + let mut nodes = HashMap::new(); + + for entry in symlinks { + let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; + let processed_sourcename = + canonicalize_linkname(anchor, &processed_name, processed_name.as_path())?; + // symlink must have a linkname + let linkname = entry.link_name()?.expect("symlink without linkname"); + + let processed_linkname = canonicalize_linkname(anchor, &processed_name, &linkname)?; + + let source_node = *nodes + .entry(processed_sourcename.clone()) + .or_insert_with(|| graph.add_node(processed_sourcename.clone())); + let link_node = *nodes + .entry(processed_linkname.clone()) + .or_insert_with(|| graph.add_node(processed_linkname.clone())); + + graph.add_edge(source_node, link_node, ()); + + entry_lookup.insert(processed_sourcename, entry); + } + + let nodes = petgraph::algo::toposort(&graph, None) + .map_err(|_| CacheError::CycleDetected(Backtrace::capture()))?; + + for node in nodes { + let key = &graph[node]; + + let Some(entry) = entry_lookup.get(key) else { + continue; + }; + let file = restore_symlink_allow_missing_target(dir_cache, anchor, entry)?; + restored.push(file); + } + + Ok(restored) + } +} + +fn restore_entry( + dir_cache:&mut CachedDirTree, + anchor:&AbsoluteSystemPath, + entry:&mut Entry, +) -> Result { + let header = entry.header(); + + match header.entry_type() { + tar::EntryType::Directory => restore_directory(dir_cache, anchor, entry), + tar::EntryType::Regular => restore_regular(dir_cache, anchor, entry), + tar::EntryType::Symlink => restore_symlink(dir_cache, anchor, entry), + ty => Err(CacheError::RestoreUnsupportedFileType(ty, Backtrace::capture())), + } +} + +#[cfg(test)] +mod tests { + use std::{fs, fs::File, io::empty, path::Path}; + + use anyhow::Result; + use tar::Header; + use tempfile::{TempDir, tempdir}; + use test_case::test_case; + use tracing::debug; + use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; + + use crate::cache_archive::{restore::CacheReader, restore_symlink::canonicalize_linkname}; + + // Expected output of the cache + #[derive(Debug)] + struct ExpectedOutput(Vec); + + enum TarFile { + File { + body:Vec, + path:AnchoredSystemPathBuf, + }, + Directory { + path:AnchoredSystemPathBuf, + }, + Symlink { + // The path of the symlink itself + link_path:AnchoredSystemPathBuf, + // The target of the symlink + link_target:AnchoredSystemPathBuf, + }, + Fifo { + path:AnchoredSystemPathBuf, + }, + } + + struct TestCase { + name:&'static str, + // The files we start with + input_files:Vec, + // The expected files (there will be more files than `expected_output` + // since we want to check entries of symlinked directories) + expected_files:Vec, + // What we expect to get from CacheArchive::restore, either a + // Vec of restored files, or an error (represented as a string) + expected_output:Result, String>, + } + + fn generate_tar(test_dir:&TempDir, files:&[TarFile]) -> Result { + let test_archive_path = test_dir.path().join("test.tar"); + let archive_file = File::create(&test_archive_path)?; + + let mut tar_writer = tar::Builder::new(archive_file); + + for file in files { + match file { + TarFile::File { path, body } => { + debug!("Adding file: {:?}", path); + let mut header = Header::new_gnu(); + header.set_size(body.len() as u64); + header.set_entry_type(tar::EntryType::Regular); + header.set_mode(0o644); + tar_writer.append_data(&mut header, path, &body[..])?; + }, + TarFile::Directory { path } => { + debug!("Adding directory: {:?}", path); + let mut header = Header::new_gnu(); + header.set_entry_type(tar::EntryType::Directory); + header.set_size(0); + header.set_mode(0o755); + tar_writer.append_data(&mut header, path, empty())?; + }, + TarFile::Symlink { link_path: link_file, link_target } => { + debug!("Adding symlink: {:?} -> {:?}", link_file, link_target); + let mut header = tar::Header::new_gnu(); + header.set_username("foo")?; + header.set_entry_type(tar::EntryType::Symlink); + header.set_size(0); + + tar_writer.append_link(&mut header, link_file, link_target)?; + }, + // We don't support this, but we need to add it to a tar for testing purposes + TarFile::Fifo { path } => { + let mut header = tar::Header::new_gnu(); + header.set_entry_type(tar::EntryType::Fifo); + header.set_size(0); + tar_writer.append_data(&mut header, path, empty())?; + }, + } + } + + tar_writer.into_inner()?; + + Ok(AbsoluteSystemPathBuf::new(test_archive_path.to_string_lossy())?) + } + + fn compress_tar(archive_path:&AbsoluteSystemPathBuf) -> Result { + let mut input_file = File::open(archive_path)?; + + let output_file_path = format!("{}.zst", archive_path); + let output_file = File::create(&output_file_path)?; + + let mut zw = zstd::stream::Encoder::new(output_file, 0)?; + std::io::copy(&mut input_file, &mut zw)?; + + zw.finish()?; + + Ok(AbsoluteSystemPathBuf::new(output_file_path)?) + } + + fn assert_file_exists(anchor:&AbsoluteSystemPath, disk_file:&TarFile) -> Result<()> { + match disk_file { + TarFile::File { path, body } => { + let full_name = anchor.resolve(path); + debug!("reading {}", full_name); + let file_contents = fs::read(full_name)?; + + assert_eq!(file_contents, *body); + }, + TarFile::Directory { path } => { + let full_name = anchor.resolve(path); + let metadata = fs::metadata(full_name)?; + + assert!(metadata.is_dir()); + }, + TarFile::Symlink { link_path: link_file, link_target: expected_link_target } => { + let full_link_file = anchor.resolve(link_file); + let link_target = fs::read_link(full_link_file)?; + + assert_eq!(link_target, expected_link_target.as_path().to_path_buf()); + }, + TarFile::Fifo { .. } => unreachable!("FIFOs are not supported"), + } + + Ok(()) + } + + fn into_anchored_system_path_vec(items:Vec<&'static str>) -> Vec { + items + .into_iter() + .map(|item| AnchoredSystemPathBuf::try_from(Path::new(item)).unwrap()) + .collect() + } + + #[test] + fn test_name_traversal() -> Result<()> { + let uncompressed_tar = include_bytes!("../../fixtures/name-traversal.tar"); + let compressed_tar = include_bytes!("../../fixtures/name-traversal.tar.zst"); + for (tar_bytes, is_compressed) in + [(&uncompressed_tar[..], false), (&compressed_tar[..], true)] + { + let mut cache_reader = CacheReader::from_reader(tar_bytes, is_compressed)?; + let output_dir = tempdir()?; + let output_dir_path = output_dir.path().to_string_lossy(); + let anchor = AbsoluteSystemPath::new(&output_dir_path)?; + let result = cache_reader.restore(anchor); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + "Invalid file path: path is malformed: ../escape" + ); + } + + Ok(()) + } + + #[test] + fn test_windows_unsafe() -> Result<()> { + let uncompressed_tar = include_bytes!("../../fixtures/windows-unsafe.tar"); + let compressed_tar = include_bytes!("../../fixtures/windows-unsafe.tar.zst"); + + for (tar_bytes, is_compressed) in + [(&uncompressed_tar[..], false), (&compressed_tar[..], true)] + { + let mut cache_reader = CacheReader::from_reader(tar_bytes, is_compressed)?; + let output_dir = tempdir()?; + let output_dir_path = output_dir.path().to_string_lossy(); + let anchor = AbsoluteSystemPath::new(&output_dir_path)?; + let result = cache_reader.restore(anchor); + #[cfg(windows)] + { + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + "Invalid file path: Path is not safe for windows: \ + windows-unsafe/this\\is\\a\\file\\on\\unix" + ); + } + #[cfg(unix)] + { + assert!(result.is_ok()); + let path = result.unwrap().pop().unwrap(); + assert_eq!(path.as_str(), "windows-unsafe/this\\is\\a\\file\\on\\unix"); + } + } + + Ok(()) + } + + #[test] + fn test_restore() -> Result<()> { + let tests = vec![ + TestCase { + name:"cache optimized", + input_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("one/").unwrap() }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), + }, + ], + expected_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("one/").unwrap() }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), + body:vec![], + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), + body:vec![], + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), + body:vec![], + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), + body:vec![], + }, + ], + expected_output:Ok(into_anchored_system_path_vec(vec![ + "one", + "one/two", + "one/two/three", + "one/two/a", + "one/two/three/file-one", + "one/two/three/file-two", + "one/two/a/file", + "one/two/b", + "one/two/b/file", + ])), + }, + TestCase { + name:"pathological cache works", + input_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("one/").unwrap() }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), + }, + TarFile::File { + body:vec![], + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), + }, + ], + expected_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("one/").unwrap() }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), + body:vec![], + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), + body:vec![], + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), + body:vec![], + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), + body:vec![], + }, + ], + expected_output:Ok(into_anchored_system_path_vec(vec![ + "one", + "one/two", + "one/two/a", + "one/two/b", + "one/two/three", + "one/two/a/file", + "one/two/b/file", + "one/two/three/file-one", + "one/two/three/file-two", + ])), + }, + TestCase { + name:"symlink hello world", + input_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("target").unwrap() }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("source").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("target").unwrap(), + }, + ], + expected_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("source").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("target").unwrap(), + }, + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("target").unwrap() }, + ], + expected_output:Ok(into_anchored_system_path_vec(vec!["target", "source"])), + }, + TestCase { + name:"nested file", + input_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("folder/").unwrap() }, + TarFile::File { + body:b"file".to_vec(), + path:AnchoredSystemPathBuf::from_raw("folder/file").unwrap(), + }, + ], + expected_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("folder/").unwrap() }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("folder/file").unwrap(), + body:b"file".to_vec(), + }, + ], + expected_output:Ok(into_anchored_system_path_vec(vec!["folder", "folder/file"])), + }, + TestCase { + name:"nested symlink", + input_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("folder/").unwrap() }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("folder/symlink").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("../").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("folder/symlink/folder-sibling") + .unwrap(), + body:b"folder-sibling".to_vec(), + }, + ], + expected_files:vec![ + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("folder/").unwrap() }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("folder/symlink").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("../").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("folder/symlink/folder-sibling") + .unwrap(), + body:b"folder-sibling".to_vec(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("folder-sibling").unwrap(), + body:b"folder-sibling".to_vec(), + }, + ], + #[cfg(unix)] + expected_output:Ok(into_anchored_system_path_vec(vec![ + "folder", + "folder/symlink", + "folder/symlink/folder-sibling", + ])), + #[cfg(windows)] + expected_output:Err("IO error: The filename, directory name, or volume label \ + syntax is incorrect. (os error 123)" + .to_string()), + }, + TestCase { + name:"pathological symlinks", + input_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("one").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("two").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("two").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("three").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("three").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("real").unwrap(), + }, + TarFile::File { + body:b"real".to_vec(), + path:AnchoredSystemPathBuf::from_raw("real").unwrap(), + }, + ], + expected_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("one").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("two").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("two").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("three").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("three").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("real").unwrap(), + }, + TarFile::File { + path:AnchoredSystemPathBuf::from_raw("real").unwrap(), + body:b"real".to_vec(), + }, + ], + expected_output:Ok(into_anchored_system_path_vec(vec![ + "real", "one", "two", "three", + ])), + }, + TestCase { + name:"place file at dir location", + input_files:vec![ + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("folder-not-file/").unwrap(), + }, + TarFile::File { + body:b"subfile".to_vec(), + path:AnchoredSystemPathBuf::from_raw("folder-not-file/subfile").unwrap(), + }, + TarFile::File { + body:b"this shouldn't work".to_vec(), + path:AnchoredSystemPathBuf::from_raw("folder-not-file").unwrap(), + }, + ], + + expected_files:vec![ + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("folder-not-file/").unwrap(), + }, + TarFile::File { + body:b"subfile".to_vec(), + path:AnchoredSystemPathBuf::from_raw("folder-not-file/subfile").unwrap(), + }, + ], + #[cfg(unix)] + expected_output:Err("IO error: Is a directory (os error 21)".to_string()), + #[cfg(windows)] + expected_output:Err("IO error: Access is denied. (os error 5)".to_string()), + }, + TestCase { + name:"symlink cycle", + input_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("one").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("two").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("two").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("three").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("three").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("one").unwrap(), + }, + ], + expected_files:vec![], + expected_output:Err("links in the cache are cyclic".to_string()), + }, + TestCase { + name:"symlink clobber", + input_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("one").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("two").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("one").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("three").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("one").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("real").unwrap(), + }, + TarFile::File { + body:b"real".to_vec(), + path:AnchoredSystemPathBuf::from_raw("real").unwrap(), + }, + ], + expected_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("one").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("real").unwrap(), + }, + TarFile::File { + body:b"real".to_vec(), + path:AnchoredSystemPathBuf::from_raw("real").unwrap(), + }, + ], + expected_output:Ok(into_anchored_system_path_vec(vec!["real", "one"])), + }, + TestCase { + name:"symlink traversal", + input_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("escape").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("../").unwrap(), + }, + TarFile::File { + body:b"file".to_vec(), + path:AnchoredSystemPathBuf::from_raw("escape/file").unwrap(), + }, + ], + expected_files:vec![TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("escape").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("../").unwrap(), + }], + expected_output:Err("tar attempts to write outside of directory: ../".to_string()), + }, + TestCase { + name:"Double indirection: file", + input_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("up").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("../").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("link").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("up").unwrap(), + }, + TarFile::File { + body:b"file".to_vec(), + path:AnchoredSystemPathBuf::from_raw("link/outside-file").unwrap(), + }, + ], + expected_files:vec![], + expected_output:Err("tar attempts to write outside of directory: ../".to_string()), + }, + TestCase { + name:"Double indirection: folder", + input_files:vec![ + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("up").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("../").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("link").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("up").unwrap(), + }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("link/level-one/level-two").unwrap(), + }, + ], + expected_files:vec![], + expected_output:Err("tar attempts to write outside of directory: ../".to_string()), + }, + TestCase { + name:"fifo (and others) unsupported", + input_files:vec![TarFile::Fifo { + path:AnchoredSystemPathBuf::from_raw("fifo").unwrap(), + }], + expected_files:vec![], + expected_output:Err("attempted to restore unsupported file type: Fifo".to_string()), + }, + TestCase { + name:"duplicate restores", + input_files:vec![ + TarFile::File { + body:b"target".to_vec(), + path:AnchoredSystemPathBuf::from_raw("target").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("source").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("target").unwrap(), + }, + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("one/").unwrap() }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), + }, + ], + expected_files:vec![ + TarFile::File { + body:b"target".to_vec(), + path:AnchoredSystemPathBuf::from_raw("target").unwrap(), + }, + TarFile::Directory { path:AnchoredSystemPathBuf::from_raw("one/").unwrap() }, + TarFile::Directory { + path:AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), + }, + TarFile::Symlink { + link_path:AnchoredSystemPathBuf::from_raw("source").unwrap(), + link_target:AnchoredSystemPathBuf::from_raw("target").unwrap(), + }, + ], + expected_output:Ok(into_anchored_system_path_vec(vec![ + "target", "source", "one", "one/two", + ])), + }, + ]; + + for is_compressed in [true, false] { + for test in &tests { + debug!("test: {}", test.name); + let input_dir = tempdir()?; + let archive_path = generate_tar(&input_dir, &test.input_files)?; + let output_dir = tempdir()?; + let output_dir_path = output_dir.path().to_string_lossy(); + let anchor = AbsoluteSystemPath::new(&output_dir_path)?; + + let archive_path = + if is_compressed { compress_tar(&archive_path)? } else { archive_path }; + + let mut cache_reader = CacheReader::open(&archive_path)?; + + match (cache_reader.restore(anchor), &test.expected_output) { + (Ok(restored_files), Err(expected_error)) => { + panic!( + "expected error: {:?}, received {:?}", + expected_error, restored_files + ); + }, + (Ok(restored_files), Ok(expected_files)) => { + assert_eq!(&restored_files, expected_files); + }, + (Err(err), Err(expected_error)) => { + assert_eq!(&err.to_string(), expected_error); + continue; + }, + (Err(err), Ok(_)) => { + panic!("unexpected error: {:?}", err); + }, + }; + + let expected_files = &test.expected_files; + + for expected_file in expected_files { + assert_file_exists(anchor, expected_file)?; + } + } + } + + Ok(()) + } + + #[test_case(Path::new("source").try_into()?, Path::new("target"), "/Users/test/target", "C:\\Users\\test\\target" ; "hello world")] + #[test_case(Path::new("child/source").try_into()?, Path::new("../sibling/target"), "/Users/test/sibling/target", "C:\\Users\\test\\sibling\\target" ; "Unix path subdirectory traversal")] + #[test_case(Path::new("child/source").try_into()?, Path::new("..\\sibling\\target"), "/Users/test/child/..\\sibling\\target", "C:\\Users\\test\\sibling\\target" ; "Windows path subdirectory traversal")] + fn test_canonicalize_linkname( + processed_name:AnchoredSystemPathBuf, + linkname:&Path, + #[allow(unused_variables)] canonical_unix:&'static str, + #[allow(unused_variables)] canonical_windows:&'static str, + ) -> Result<()> { + #[cfg(unix)] + let anchor = AbsoluteSystemPath::new("/Users/test").unwrap(); + #[cfg(windows)] + let anchor = AbsoluteSystemPath::new("C:\\Users\\test").unwrap(); + + let received_path = canonicalize_linkname(anchor, &processed_name, linkname)?; + + #[cfg(unix)] + assert_eq!(received_path.to_string(), canonical_unix); + #[cfg(windows)] + assert_eq!(received_path.to_string(), canonical_windows); + + Ok(()) + } +} diff --git a/crates/turborepo-cache/Source/cache_archive/restore_directory.rs b/crates/turborepo-cache/Source/cache_archive/restore_directory.rs new file mode 100644 index 0000000000000..ab632e3083ca8 --- /dev/null +++ b/crates/turborepo-cache/Source/cache_archive/restore_directory.rs @@ -0,0 +1,162 @@ +use std::{backtrace::Backtrace, ffi::OsString, io}; + +use camino::Utf8Component; +use tar::Entry; +use tracing::debug; +use turbopath::{ + AbsoluteSystemPath, + AbsoluteSystemPathBuf, + AnchoredSystemPath, + AnchoredSystemPathBuf, +}; + +use crate::CacheError; + +pub fn restore_directory( + dir_cache:&mut CachedDirTree, + anchor:&AbsoluteSystemPath, + entry:&Entry, +) -> Result { + let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; + + dir_cache.safe_mkdir_all(anchor, &processed_name, entry.header().mode()?)?; + + Ok(processed_name) +} + +pub struct CachedDirTree { + anchor_at_depth:Vec, + prefix:Vec, +} + +impl CachedDirTree { + pub fn new(initial_anchor:AbsoluteSystemPathBuf) -> Self { + CachedDirTree { anchor_at_depth:vec![initial_anchor], prefix:vec![] } + } + + // Given a path, checks the dir cache to determine where we actually need + // to start restoring, i.e. which directories we can skip over because + // we've already created them. + // Returns the anchor at the depth where we need to start restoring, and + // the index into the path components where we need to start restoring. + fn get_starting_point(&mut self, path:&AnchoredSystemPath) -> (AbsoluteSystemPathBuf, usize) { + let mut i = 0; + for (idx, (path_component, prefix_component)) in + path.components().zip(self.prefix.iter()).enumerate() + { + i = idx; + if path_component.as_os_str() != prefix_component.as_os_str() { + break; + } + } + let anchor = self.anchor_at_depth[i].clone(); + + self.anchor_at_depth.truncate(i + 1); + self.prefix.truncate(i); + + (anchor, i) + } + + fn update(&mut self, anchor:AbsoluteSystemPathBuf, new_component:OsString) { + self.anchor_at_depth.push(anchor); + self.prefix.push(new_component); + } + + // Windows doesn't have file modes, so mode is unused + #[allow(unused_variables)] + pub fn safe_mkdir_all( + &mut self, + anchor:&AbsoluteSystemPath, + processed_name:&AnchoredSystemPath, + mode:u32, + ) -> Result<(), CacheError> { + // Iterate through path segments by os.Separator, appending them onto + // current_path. Check to see if that path segment is a symlink + // with a target outside of anchor. + let (mut calculated_anchor, start_idx) = self.get_starting_point(processed_name); + for component in processed_name.components().skip(start_idx) { + calculated_anchor = check_path( + anchor, + &calculated_anchor, + AnchoredSystemPath::new(component.as_str())?, + )?; + + self.update(calculated_anchor.clone(), component.as_os_str().to_os_string()); + } + + // If we have made it here we know that it is safe to call fs::create_dir_all + // on the join of anchor and processed_name. + // + // This could _still_ error, but we don't care. + let resolved_name = anchor.resolve(processed_name); + let directory_exists = resolved_name.try_exists(); + if matches!(directory_exists, Ok(false)) { + resolved_name.create_dir_all()?; + } + + #[cfg(unix)] + { + use std::{fs, os::unix::fs::PermissionsExt}; + + let metadata = resolved_name.symlink_metadata()?; + let mut permissions = metadata.permissions(); + permissions.set_mode(mode); + fs::set_permissions(&resolved_name, permissions)?; + } + + Ok(()) + } +} + +fn check_path( + original_anchor:&AbsoluteSystemPath, + accumulated_anchor:&AbsoluteSystemPath, + segment:&AnchoredSystemPath, +) -> Result { + // Check if the segment itself is sneakily an absolute path... + // (looking at you, Windows. CON, AUX...) + if segment + .components() + .any(|c| matches!(c, Utf8Component::Prefix(_) | Utf8Component::RootDir)) + { + return Err(CacheError::LinkOutsideOfDirectory(segment.to_string(), Backtrace::capture())); + } + + let combined_path = accumulated_anchor.resolve(segment); + let Ok(file_info) = combined_path.symlink_metadata() else { + // Getting an error here means we failed to stat the path. + // Assume that means we're safe and continue. + return Ok(combined_path); + }; + + // If we don't have a symlink, it's safe + if !file_info.is_symlink() { + return Ok(combined_path); + } + + // Check to see if the symlink targets outside of the originalAnchor. + // We don't do eval symlinks because we could find ourself in a totally + // different place. + + // 1. Get the target. + let link_target = combined_path.read_link()?; + debug!("link source: {:?}, link target {:?}", combined_path, link_target); + if link_target.is_absolute() { + let absolute_link_target = AbsoluteSystemPathBuf::new(link_target.clone())?; + if path_clean::clean(&absolute_link_target).starts_with(original_anchor) { + return Ok(absolute_link_target); + } + } else { + let relative_link_target = AnchoredSystemPath::new(link_target.as_str())?; + // We clean here to resolve the `..` and `.` segments. + let computed_target = path_clean::clean(accumulated_anchor.resolve(relative_link_target)); + if computed_target.starts_with(original_anchor) { + return check_path(original_anchor, accumulated_anchor, relative_link_target); + } + } + + Err(CacheError::LinkOutsideOfDirectory( + link_target.to_string(), + Backtrace::capture(), + )) +} diff --git a/crates/turborepo-cache/Source/cache_archive/restore_regular.rs b/crates/turborepo-cache/Source/cache_archive/restore_regular.rs new file mode 100644 index 0000000000000..e66e445237bdb --- /dev/null +++ b/crates/turborepo-cache/Source/cache_archive/restore_regular.rs @@ -0,0 +1,60 @@ +use std::{fs::OpenOptions, io, io::Read, path::Path}; + +use tar::Entry; +use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, AnchoredSystemPathBuf}; + +use crate::{CacheError, cache_archive::restore_directory::CachedDirTree}; + +pub fn restore_regular( + dir_cache:&mut CachedDirTree, + anchor:&AbsoluteSystemPath, + entry:&mut Entry, +) -> Result { + // Assuming this was a `turbo`-created input, we currently have an + // RelativeUnixPath. Assuming this is malicious input we don't really care + // if we do the wrong thing. + // + // Note that we don't use `header.path()` as some archive formats have support + // for longer path names described in separate entries instead of solely in the + // header + let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; + + // We need to traverse `processedName` from base to root split at + // `os.Separator` to make sure we don't end up following a symlink + // outside of the restore path. + dir_cache.safe_mkdir_file(anchor, &processed_name)?; + + let resolved_path = anchor.resolve(&processed_name); + let mut open_options = OpenOptions::new(); + open_options.write(true).truncate(true).create(true); + + #[cfg(unix)] + { + use std::os::unix::fs::OpenOptionsExt; + let header = entry.header(); + open_options.mode(header.mode()?); + } + + let mut file = open_options.open(resolved_path.as_path())?; + io::copy(entry, &mut file)?; + + Ok(processed_name) +} + +impl CachedDirTree { + pub fn safe_mkdir_file( + &mut self, + anchor:&AbsoluteSystemPath, + processed_name:&AnchoredSystemPath, + ) -> Result<(), CacheError> { + let parent = processed_name.as_path().parent(); + // Handles ./foo and foo + let is_root_file = parent == Some(Path::new(".")) || parent == Some(Path::new("")); + if !is_root_file { + let dir = processed_name.parent().unwrap(); + self.safe_mkdir_all(anchor, dir, 0o755)?; + } + + Ok(()) + } +} diff --git a/crates/turborepo-cache/Source/cache_archive/restore_symlink.rs b/crates/turborepo-cache/Source/cache_archive/restore_symlink.rs new file mode 100644 index 0000000000000..878a30eb86fe1 --- /dev/null +++ b/crates/turborepo-cache/Source/cache_archive/restore_symlink.rs @@ -0,0 +1,150 @@ +use std::{backtrace::Backtrace, io::Read}; + +use camino::Utf8Path; +use turbopath::{ + AbsoluteSystemPath, + AbsoluteSystemPathBuf, + AnchoredSystemPath, + AnchoredSystemPathBuf, + PathError, + UnknownPathType, +}; + +use crate::{CacheError, cache_archive::restore_directory::CachedDirTree}; + +pub fn restore_symlink( + dir_cache:&mut CachedDirTree, + anchor:&AbsoluteSystemPath, + entry:&tar::Entry, +) -> Result { + let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; + + let linkname = entry + .link_name()? + .ok_or_else(|| CacheError::MalformedTar(Backtrace::capture()))?; + + let processed_linkname = canonicalize_linkname(anchor, &processed_name, &linkname)?; + + if processed_linkname.symlink_metadata().is_err() { + return Err(CacheError::LinkTargetDoesNotExist( + processed_linkname.to_string(), + Backtrace::capture(), + )); + } + + actually_restore_symlink(dir_cache, anchor, &processed_name, entry)?; + + Ok(processed_name) +} + +pub fn restore_symlink_allow_missing_target( + dir_cache:&mut CachedDirTree, + anchor:&AbsoluteSystemPath, + entry:&tar::Entry, +) -> Result { + let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; + + actually_restore_symlink(dir_cache, anchor, &processed_name, entry)?; + + Ok(processed_name) +} + +fn actually_restore_symlink<'a>( + dir_cache:&mut CachedDirTree, + anchor:&AbsoluteSystemPath, + processed_name:&'a AnchoredSystemPath, + entry:&tar::Entry, +) -> Result<&'a AnchoredSystemPath, CacheError> { + dir_cache.safe_mkdir_file(anchor, processed_name)?; + + let symlink_from = anchor.resolve(processed_name); + + _ = symlink_from.remove(); + + let link_name = entry.link_name()?.expect("have linkname"); + let symlink_to = link_name.to_str().ok_or_else(|| { + CacheError::PathError( + PathError::InvalidUnicode(link_name.to_string_lossy().to_string()), + Backtrace::capture(), + ) + })?; + + if Utf8Path::new(symlink_to).is_dir() { + symlink_from.symlink_to_dir(symlink_to)?; + } else { + symlink_from.symlink_to_file(symlink_to)?; + } + + #[cfg(target_os = "macos")] + { + use std::os::unix::fs::PermissionsExt; + let metadata = symlink_from.symlink_metadata()?; + let mut permissions = metadata.permissions(); + if let Ok(mode) = entry.header().mode() { + permissions.set_mode(mode); + } + } + + Ok(processed_name) +} + +// canonicalize_linkname determines (lexically) what the resolved path on the +// system will be when linkname is restored verbatim. +pub fn canonicalize_linkname( + anchor:&AbsoluteSystemPath, + processed_name:&AnchoredSystemPathBuf, + linkname:&std::path::Path, +) -> Result { + let linkname = linkname.try_into().map_err(|_| { + CacheError::PathError( + PathError::InvalidUnicode(linkname.to_string_lossy().to_string()), + Backtrace::capture(), + ) + })?; + // We don't know _anything_ about linkname. It could be any of: + // + // - Absolute Unix Path + // - Absolute Windows Path + // - Relative Unix Path + // - Relative Windows Path + // + // We also can't _truly_ distinguish if the path is Unix or Windows. + // Take for example: `/Users/turbobot/weird-filenames/\foo\/lol` + // It is a valid file on Unix, but if we do slash conversion it breaks. + // Or `i\am\a\normal\unix\file\but\super\nested\on\windows`. + // + // We also can't safely assume that paths in link targets on one platform + // should be treated as targets for that platform. The author may be + // generating an artifact that should work on Windows on a Unix device. + // + // Given all of that, our best option is to restore link targets _verbatim_. + // No modification, no slash conversion. + // + // In order to DAG sort them, however, we do need to canonicalize them. + // We canonicalize them as if we're restoring them verbatim. + // + match turbopath::categorize(linkname) { + // 1. Check to see if the link target is absolute _on the current platform_. + // If it is an absolute path it's canonical by rule. + UnknownPathType::Absolute(abs) => Ok(abs), + // Remaining options: + // - Absolute (other platform) Path + // - Relative Unix Path + // - Relative Windows Path + // + // At this point we simply assume that it's a relative path—no matter + // which separators appear in it and where they appear, We can't do + // anything else because the OS will also treat it like that when it is + // a link target. + UnknownPathType::Anchored(cleaned_linkname) => { + let source = anchor.resolve(processed_name); + let canonicalized = source + .parent() + .expect("expected parent for file") + .resolve(&cleaned_linkname) + .clean()?; + + Ok(canonicalized) + }, + } +} diff --git a/crates/turborepo-cache/src/config.rs b/crates/turborepo-cache/Source/config.rs similarity index 100% rename from crates/turborepo-cache/src/config.rs rename to crates/turborepo-cache/Source/config.rs diff --git a/crates/turborepo-cache/Source/fs.rs b/crates/turborepo-cache/Source/fs.rs new file mode 100644 index 0000000000000..f43c4cda36528 --- /dev/null +++ b/crates/turborepo-cache/Source/fs.rs @@ -0,0 +1,234 @@ +use std::{backtrace::Backtrace, fs::OpenOptions}; + +use camino::Utf8Path; +use serde::{Deserialize, Serialize}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; +use turborepo_analytics::AnalyticsSender; +use turborepo_api_client::{analytics, analytics::AnalyticsEvent}; + +use crate::{ + CacheError, + CacheHitMetadata, + CacheSource, + cache_archive::{CacheReader, CacheWriter}, +}; + +pub struct FSCache { + cache_directory:AbsoluteSystemPathBuf, + analytics_recorder:Option, +} + +#[derive(Debug, Deserialize, Serialize)] +struct CacheMetadata { + hash:String, + duration:u64, +} + +impl CacheMetadata { + fn read(path:&AbsoluteSystemPath) -> Result { + serde_json::from_str(&path.read_to_string()?) + .map_err(|e| CacheError::InvalidMetadata(e, Backtrace::capture())) + } +} + +impl FSCache { + fn resolve_cache_dir( + repo_root:&AbsoluteSystemPath, + cache_dir:&Utf8Path, + ) -> AbsoluteSystemPathBuf { + AbsoluteSystemPathBuf::from_unknown(repo_root, cache_dir) + } + + #[tracing::instrument(skip_all)] + pub fn new( + cache_dir:&Utf8Path, + repo_root:&AbsoluteSystemPath, + analytics_recorder:Option, + ) -> Result { + let cache_directory = Self::resolve_cache_dir(repo_root, cache_dir); + cache_directory.create_dir_all()?; + + Ok(FSCache { cache_directory, analytics_recorder }) + } + + fn log_fetch(&self, event:analytics::CacheEvent, hash:&str, duration:u64) { + // If analytics fails to record, it's not worth failing the cache + if let Some(analytics_recorder) = &self.analytics_recorder { + let analytics_event = AnalyticsEvent { + session_id:None, + source:analytics::CacheSource::Local, + event, + hash:hash.to_string(), + duration, + }; + + let _ = analytics_recorder.send(analytics_event); + } + } + + #[tracing::instrument(skip_all)] + pub fn fetch( + &self, + anchor:&AbsoluteSystemPath, + hash:&str, + ) -> Result)>, CacheError> { + let uncompressed_cache_path = self.cache_directory.join_component(&format!("{}.tar", hash)); + let compressed_cache_path = + self.cache_directory.join_component(&format!("{}.tar.zst", hash)); + + let cache_path = if uncompressed_cache_path.exists() { + uncompressed_cache_path + } else if compressed_cache_path.exists() { + compressed_cache_path + } else { + self.log_fetch(analytics::CacheEvent::Miss, hash, 0); + return Ok(None); + }; + + let mut cache_reader = CacheReader::open(&cache_path)?; + + let restored_files = cache_reader.restore(anchor)?; + + let meta = CacheMetadata::read( + &self.cache_directory.join_component(&format!("{}-meta.json", hash)), + )?; + + self.log_fetch(analytics::CacheEvent::Hit, hash, meta.duration); + + Ok(Some(( + CacheHitMetadata { time_saved:meta.duration, source:CacheSource::Local }, + restored_files, + ))) + } + + #[tracing::instrument(skip_all)] + pub(crate) fn exists(&self, hash:&str) -> Result, CacheError> { + let uncompressed_cache_path = self.cache_directory.join_component(&format!("{}.tar", hash)); + let compressed_cache_path = + self.cache_directory.join_component(&format!("{}.tar.zst", hash)); + + if !uncompressed_cache_path.exists() && !compressed_cache_path.exists() { + return Ok(None); + } + + let duration = CacheMetadata::read( + &self.cache_directory.join_component(&format!("{}-meta.json", hash)), + ) + .map(|meta| meta.duration) + .unwrap_or(0); + + Ok(Some(CacheHitMetadata { time_saved:duration, source:CacheSource::Local })) + } + + #[tracing::instrument(skip_all)] + pub fn put( + &self, + anchor:&AbsoluteSystemPath, + hash:&str, + files:&[AnchoredSystemPathBuf], + duration:u64, + ) -> Result<(), CacheError> { + let cache_path = self.cache_directory.join_component(&format!("{}.tar.zst", hash)); + + let mut cache_item = CacheWriter::create(&cache_path)?; + + for file in files { + cache_item.add_file(anchor, file)?; + } + + let metadata_path = self.cache_directory.join_component(&format!("{}-meta.json", hash)); + + let meta = CacheMetadata { hash:hash.to_string(), duration }; + + let mut metadata_options = OpenOptions::new(); + metadata_options.create(true).write(true).truncate(true); + + let metadata_file = metadata_path.open_with_options(metadata_options)?; + + serde_json::to_writer(metadata_file, &meta) + .map_err(|e| CacheError::InvalidMetadata(e, Backtrace::capture()))?; + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use anyhow::Result; + use futures::future::try_join_all; + use tempfile::tempdir; + use turbopath::AnchoredSystemPath; + use turborepo_analytics::start_analytics; + use turborepo_api_client::{APIAuth, APIClient}; + use turborepo_vercel_api_mock::start_test_server; + + use super::*; + use crate::test_cases::{TestCase, get_test_cases, validate_analytics}; + + #[tokio::test] + async fn test_fs_cache() -> Result<()> { + let port = port_scanner::request_open_port().unwrap(); + tokio::spawn(start_test_server(port)); + + let test_cases = get_test_cases(); + + try_join_all(test_cases.iter().map(|test_case| round_trip_test(test_case, port))).await?; + + validate_analytics(&test_cases, analytics::CacheSource::Local, port).await?; + Ok(()) + } + + async fn round_trip_test(test_case:&TestCase, port:u16) -> Result<()> { + let repo_root = tempdir()?; + let repo_root_path = AbsoluteSystemPath::from_std_path(repo_root.path())?; + test_case.initialize(repo_root_path)?; + + let api_client = APIClient::new( + format!("http://localhost:{}", port), + Some(Duration::from_secs(200)), + None, + "2.0.0", + true, + )?; + let api_auth = APIAuth { + team_id:Some("my-team".to_string()), + token:"my-token".to_string(), + team_slug:None, + }; + let (analytics_sender, analytics_handle) = + start_analytics(api_auth.clone(), api_client.clone()); + + let cache = + FSCache::new(Utf8Path::new(""), repo_root_path, Some(analytics_sender.clone()))?; + + let expected_miss = cache.fetch(repo_root_path, test_case.hash)?; + assert!(expected_miss.is_none()); + + let files:Vec<_> = test_case.files.iter().map(|f| f.path().to_owned()).collect(); + cache.put(repo_root_path, test_case.hash, &files, test_case.duration)?; + + let (status, files) = cache.fetch(repo_root_path, test_case.hash)?.unwrap(); + + assert_eq!( + status, + CacheHitMetadata { time_saved:test_case.duration, source:CacheSource::Local } + ); + + assert_eq!(files.len(), test_case.files.len()); + for (expected, actual) in test_case.files.iter().zip(files.iter()) { + let actual:&AnchoredSystemPath = actual; + assert_eq!(expected.path(), actual); + let actual_file = repo_root_path.resolve(actual); + if let Some(contents) = expected.contents() { + assert_eq!(contents, actual_file.read_to_string()?); + } else { + assert!(actual_file.exists()); + } + } + + analytics_handle.close_with_timeout().await; + Ok(()) + } +} diff --git a/crates/turborepo-cache/src/http.rs b/crates/turborepo-cache/Source/http.rs similarity index 100% rename from crates/turborepo-cache/src/http.rs rename to crates/turborepo-cache/Source/http.rs diff --git a/crates/turborepo-cache/src/lib.rs b/crates/turborepo-cache/Source/lib.rs similarity index 100% rename from crates/turborepo-cache/src/lib.rs rename to crates/turborepo-cache/Source/lib.rs diff --git a/crates/turborepo-cache/Source/multiplexer.rs b/crates/turborepo-cache/Source/multiplexer.rs new file mode 100644 index 0000000000000..01d7715c3dbb6 --- /dev/null +++ b/crates/turborepo-cache/Source/multiplexer.rs @@ -0,0 +1,202 @@ +use std::sync::{ + Arc, + Mutex, + atomic::{AtomicBool, Ordering}, +}; + +use tracing::{debug, warn}; +use turbopath::{AbsoluteSystemPath, AnchoredSystemPathBuf}; +use turborepo_analytics::AnalyticsSender; +use turborepo_api_client::{APIAuth, APIClient}; + +use crate::{ + CacheConfig, + CacheError, + CacheHitMetadata, + CacheOpts, + fs::FSCache, + http::{HTTPCache, UploadMap}, +}; + +pub struct CacheMultiplexer { + // We use an `AtomicBool` instead of removing the cache because that would require + // wrapping the cache in a `Mutex` which would cause a lot of contention. + // This does create a mild race condition where we might use the cache + // even though another thread might be removing it, but that's fine. + should_use_http_cache:AtomicBool, + // Just for keeping track of whether we've already printed a warning about the remote cache + // being read-only + should_print_skipping_remote_put:AtomicBool, + cache_config:CacheConfig, + fs:Option, + http:Option, +} + +impl CacheMultiplexer { + #[tracing::instrument(skip_all)] + pub fn new( + opts:&CacheOpts, + repo_root:&AbsoluteSystemPath, + api_client:APIClient, + api_auth:Option, + analytics_recorder:Option, + ) -> Result { + let use_fs_cache = opts.cache.local.should_use(); + let use_http_cache = opts.cache.remote.should_use(); + + // Since the above two flags are not mutually exclusive it is possible to + // configure yourself out of having a cache. We should tell you about it + // but we shouldn't fail your build for that reason. + if !use_fs_cache && !use_http_cache { + warn!("no caches are enabled"); + } + + let fs_cache = use_fs_cache + .then(|| FSCache::new(&opts.cache_dir, repo_root, analytics_recorder.clone())) + .transpose()?; + + let http_cache = use_http_cache.then_some(api_auth).flatten().map(|api_auth| { + HTTPCache::new( + api_client, + opts, + repo_root.to_owned(), + api_auth, + analytics_recorder.clone(), + ) + }); + + Ok(CacheMultiplexer { + should_print_skipping_remote_put:AtomicBool::new(true), + should_use_http_cache:AtomicBool::new(http_cache.is_some()), + cache_config:opts.cache, + fs:fs_cache, + http:http_cache, + }) + } + + // This is technically a TOCTOU bug, but at worst it'll cause + // a few extra cache requests. + fn get_http_cache(&self) -> Option<&HTTPCache> { + if self.should_use_http_cache.load(Ordering::Relaxed) { + self.http.as_ref() + } else { + None + } + } + + pub fn requests(&self) -> Option>> { + self.http.as_ref().map(|http| http.requests()) + } + + #[tracing::instrument(skip_all)] + pub async fn put( + &self, + anchor:&AbsoluteSystemPath, + key:&str, + files:&[AnchoredSystemPathBuf], + duration:u64, + ) -> Result<(), CacheError> { + if self.cache_config.local.write { + self.fs.as_ref().map(|fs| fs.put(anchor, key, files, duration)).transpose()?; + } + + let http_result = match self.get_http_cache() { + Some(http) => { + if self.cache_config.remote.write { + let http_result = http.put(anchor, key, files, duration).await; + + Some(http_result) + } else { + if self.should_print_skipping_remote_put.load(Ordering::Relaxed) { + // Warn once per build, not per task + warn!("Remote cache is read-only, skipping upload"); + self.should_print_skipping_remote_put.store(false, Ordering::Relaxed); + } + // Cache is functional but running in read-only mode, so we don't want to try to + // write to it + None + } + }, + _ => None, + }; + + match http_result { + Some(Err(CacheError::ApiClientError( + box turborepo_api_client::Error::CacheDisabled { .. }, + .., + ))) => { + warn!("failed to put to http cache: cache disabled"); + self.should_use_http_cache.store(false, Ordering::Relaxed); + Ok(()) + }, + Some(Err(e)) => Err(e), + None | Some(Ok(())) => Ok(()), + } + } + + #[tracing::instrument(skip_all)] + pub async fn fetch( + &self, + anchor:&AbsoluteSystemPath, + key:&str, + ) -> Result)>, CacheError> { + if self.cache_config.local.read { + if let Some(fs) = &self.fs { + if let response @ Ok(Some(_)) = fs.fetch(anchor, key) { + return response; + } + } + } + + if self.cache_config.remote.read { + if let Some(http) = self.get_http_cache() { + if let Ok(Some((CacheHitMetadata { source, time_saved }, files))) = + http.fetch(key).await + { + // Store this into fs cache. We can ignore errors here because we know + // we have previously successfully stored in HTTP cache, and so the overall + // result is a success at fetching. Storing in lower-priority caches is an + // optimization. + if self.cache_config.local.write { + if let Some(fs) = &self.fs { + let _ = fs.put(anchor, key, &files, time_saved); + } + } + + return Ok(Some((CacheHitMetadata { source, time_saved }, files))); + } + } + } + + Ok(None) + } + + #[tracing::instrument(skip_all)] + pub async fn exists(&self, key:&str) -> Result, CacheError> { + if self.cache_config.local.read { + if let Some(fs) = &self.fs { + match fs.exists(key) { + cache_hit @ Ok(Some(_)) => { + return cache_hit; + }, + Ok(None) => {}, + Err(err) => debug!("failed to check fs cache: {:?}", err), + } + } + } + + if self.cache_config.remote.read { + if let Some(http) = self.get_http_cache() { + match http.exists(key).await { + cache_hit @ Ok(Some(_)) => { + return cache_hit; + }, + Ok(None) => {}, + Err(err) => debug!("failed to check http cache: {:?}", err), + } + } + } + + Ok(None) + } +} diff --git a/crates/turborepo-cache/Source/signature_authentication.rs b/crates/turborepo-cache/Source/signature_authentication.rs new file mode 100644 index 0000000000000..acad297592dfb --- /dev/null +++ b/crates/turborepo-cache/Source/signature_authentication.rs @@ -0,0 +1,269 @@ +use std::env; + +use base64::{Engine, prelude::BASE64_STANDARD}; +use hmac::{Hmac, Mac}; +use os_str_bytes::OsStringBytes; +use sha2::Sha256; +use thiserror::Error; + +type HmacSha256 = Hmac; + +#[derive(Debug, Error)] +pub enum SignatureError { + #[error( + "signature secret key not found. You must specify a secret key in the \ + TURBO_REMOTE_CACHE_SIGNATURE_KEY environment variable" + )] + NoSignatureSecretKey, + #[error("serialization error: {0}")] + SerializationError(#[from] serde_json::Error), + #[error("base64 encoding error: {0}")] + Base64EncodingError(#[from] base64::DecodeError), + #[error(transparent)] + Hmac(#[from] hmac::digest::InvalidLength), +} + +#[derive(Debug)] +pub struct ArtifactSignatureAuthenticator { + pub(crate) team_id:Vec, + // An override for testing purposes (to avoid env var race conditions) + pub(crate) secret_key_override:Option>, +} + +impl ArtifactSignatureAuthenticator { + pub fn new(team_id:Vec, secret_key_override:Option>) -> Self { + Self { team_id, secret_key_override } + } + + // Gets secret key from either secret key override or environment variable. + // HMAC_SHA256 has no key length limit, although it's generally recommended + // to keep key length under 64 bytes since anything longer is hashed using + // SHA-256. + fn secret_key(&self) -> Result, SignatureError> { + if let Some(secret_key) = &self.secret_key_override { + return Ok(secret_key.to_vec()); + } + + Ok(env::var_os("TURBO_REMOTE_CACHE_SIGNATURE_KEY") + .ok_or(SignatureError::NoSignatureSecretKey)? + .into_raw_vec()) + } + + fn construct_metadata(&self, hash:&[u8]) -> Result, SignatureError> { + let mut metadata = hash.to_vec(); + metadata.extend_from_slice(&self.team_id); + + Ok(metadata) + } + + fn get_tag_generator(&self, hash:&[u8]) -> Result { + let mut mac = HmacSha256::new_from_slice(&self.secret_key()?)?; + let metadata = self.construct_metadata(hash)?; + + mac.update(&metadata); + + Ok(mac) + } + + #[tracing::instrument(skip_all)] + pub fn generate_tag_bytes( + &self, + hash:&[u8], + artifact_body:&[u8], + ) -> Result, SignatureError> { + let mut mac = self.get_tag_generator(hash)?; + + mac.update(artifact_body); + let hmac_output = mac.finalize(); + Ok(hmac_output.into_bytes().to_vec()) + } + + #[tracing::instrument(skip_all)] + pub fn generate_tag(&self, hash:&[u8], artifact_body:&[u8]) -> Result { + let mut hmac_ctx = self.get_tag_generator(hash)?; + + hmac_ctx.update(artifact_body); + let hmac_output = hmac_ctx.finalize(); + Ok(BASE64_STANDARD.encode(hmac_output.into_bytes())) + } + + #[tracing::instrument(skip_all)] + pub fn validate( + &self, + hash:&[u8], + artifact_body:&[u8], + expected_tag:&str, + ) -> Result { + let mut mac = HmacSha256::new_from_slice(&self.secret_key()?)?; + let message = self.construct_metadata(hash)?; + mac.update(&message); + mac.update(artifact_body); + + let expected_bytes = BASE64_STANDARD.decode(expected_tag)?; + Ok(mac.verify_slice(&expected_bytes).is_ok()) + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + + use super::*; + + impl ArtifactSignatureAuthenticator { + pub fn validate_tag( + &self, + hash:&[u8], + artifact_body:&[u8], + expected_tag:&[u8], + ) -> Result { + let mut mac = HmacSha256::new_from_slice(&self.secret_key()?)?; + let message = self.construct_metadata(hash)?; + mac.update(&message); + mac.update(artifact_body); + + Ok(mac.verify_slice(expected_tag).is_ok()) + } + } + + struct TestCase { + secret_key:&'static str, + team_id:&'static [u8], + artifact_hash:&'static [u8], + artifact_body:&'static [u8], + } + + fn get_test_cases() -> Vec { + vec![ + TestCase { + secret_key:"x3vq8mFz0J", + team_id:b"tH7sL1Rn9K", + artifact_hash:b"d5b7e4688f", + artifact_body:&[5, 72, 219, 39, 156], + }, + TestCase { + secret_key:"r8cP5sTn0Y", + team_id:b"sL2vM9Qj1D", + artifact_hash:b"a1c8f3e3d7", + artifact_body:&[128, 234, 49, 67, 96], + }, + TestCase { + secret_key:"g4kS2nDv6L", + team_id:b"mB8pF9hJ0X", + artifact_hash:b"f2e6d4a2c1", + artifact_body:&[217, 88, 71, 16, 53], + }, + TestCase { + secret_key:"j0fT3qPz6N", + team_id:b"cH1rK7vD5B", + artifact_hash:b"e8a5c7f0b2", + artifact_body:&[202, 12, 104, 90, 182], + }, + TestCase { + secret_key:"w1xM5bVz2Q", + team_id:b"sL9cJ0nK7F", + artifact_hash:b"c4e6f9a1d8", + artifact_body:&[67, 93, 241, 78, 192], + }, + TestCase { + secret_key:"f9gD2tNc8K", + team_id:b"pJ1xL6rF0V", + artifact_hash:b"b3a9c5e8f7", + artifact_body:&[23, 160, 36, 208, 97], + }, + TestCase { + secret_key:"k5nB1tLc9Z", + team_id:b"wF0xV8jP7G", + artifact_hash:b"e7a9c1b8f6", + artifact_body:&[237, 148, 107, 51, 241], + }, + TestCase { + secret_key:"d8mR2vZn5X", + team_id:b"kP6cV1jN7T", + artifact_hash:b"f2c8e7b6a1", + artifact_body:&[128, 36, 180, 67, 230], + }, + TestCase { + secret_key:"p4kS5nHv3L", + team_id:b"tR1cF2bD0M", + artifact_hash:b"d5b8e4f3c9", + artifact_body:&[47, 161, 218, 119, 223], + }, + TestCase { + secret_key:"j5nG1bDv6X", + team_id:b"tH8rK0pJ3L", + artifact_hash:b"e3c5a9b2f1", + artifact_body:&[188, 245, 109, 12, 167], + }, + TestCase { + secret_key:"f2cB1tLm9X", + team_id:b"rG7sK0vD4N", + artifact_hash:b"b5a9c8e3f6", + artifact_body:&[205, 154, 83, 60, 27], + }, + TestCase { + secret_key:"t1sN2mFj8Z", + team_id:b"pK3cH7rD6B", + artifact_hash:b"d4e9c1f7b6", + artifact_body:&[226, 245, 85, 79, 136], + }, + TestCase { + secret_key:"h5jM3pZv8X", + team_id:b"dR1bF2cK6L", + artifact_hash:b"f2e6d5b1c8", + artifact_body:&[70, 184, 71, 150, 238], + }, + TestCase { + secret_key:"n0cT2bDk9J", + team_id:b"pJ3sF6rM8N", + artifact_hash:b"e4a9d7c1f8", + artifact_body:&[240, 130, 13, 167, 75], + }, + TestCase { + secret_key:"b2dV6kPf9X", + team_id:b"tN3cH7mK8J", + artifact_hash:b"c9e3d7b6f8", + artifact_body:&[58, 42, 80, 138, 189], + }, + ] + } + + #[test] + fn test_signatures() -> Result<()> { + for test_case in get_test_cases() { + test_signature(test_case)?; + } + Ok(()) + } + + fn test_signature(test_case:TestCase) -> Result<()> { + env::set_var("TURBO_REMOTE_CACHE_SIGNATURE_KEY", test_case.secret_key); + let signature = ArtifactSignatureAuthenticator { + team_id:test_case.team_id.to_vec(), + secret_key_override:None, + }; + + let hash = test_case.artifact_hash; + let artifact_body = &test_case.artifact_body; + let tag = signature.generate_tag_bytes(hash, artifact_body)?; + + assert!(signature.validate_tag(hash, artifact_body, tag.as_ref())?); + + // Generate some bad tag that is not correct + let bad_tag = BASE64_STANDARD.encode(b"bad tag"); + assert!(!signature.validate(hash, artifact_body, &bad_tag)?); + + // Change the key + env::set_var("TURBO_REMOTE_CACHE_SIGNATURE_KEY", "some other key"); + + // Confirm that the tag is no longer valid + assert!(!signature.validate_tag(hash, artifact_body, tag.as_ref())?); + + // Generate new tag + let tag = signature.generate_tag(hash, artifact_body)?; + + // Confirm it's valid + assert!(signature.validate(hash, artifact_body, &tag)?); + Ok(()) + } +} diff --git a/crates/turborepo-cache/Source/test_cases.rs b/crates/turborepo-cache/Source/test_cases.rs new file mode 100644 index 0000000000000..2fb5fce3e0fc0 --- /dev/null +++ b/crates/turborepo-cache/Source/test_cases.rs @@ -0,0 +1,135 @@ +use anyhow::Result; +use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, AnchoredSystemPathBuf}; +use turborepo_analytics::AnalyticsEvent; +use turborepo_api_client::analytics; + +pub(crate) struct TestFile { + path:AnchoredSystemPathBuf, + contents:Option<&'static str>, +} + +impl TestFile { + pub fn file(path:AnchoredSystemPathBuf, contents:&'static str) -> Self { + Self { path, contents:Some(contents) } + } + + pub fn directory(path:AnchoredSystemPathBuf) -> Self { Self { path, contents:None } } + + pub fn create(&self, repo_root:&AbsoluteSystemPath) -> Result<()> { + let file_path = repo_root.resolve(&self.path); + match self.contents { + Some(contents) => { + std::fs::create_dir_all(file_path.parent().unwrap())?; + std::fs::write(file_path, contents)?; + }, + None => { + std::fs::create_dir(&file_path)?; + }, + } + + Ok(()) + } + + pub fn path(&self) -> &AnchoredSystemPath { &self.path } + + pub fn contents(&self) -> Option<&str> { self.contents } +} + +pub(crate) struct TestCase { + pub files:Vec, + pub duration:u64, + pub hash:&'static str, +} + +impl TestCase { + pub fn initialize(&self, repo_root:&AbsoluteSystemPath) -> Result<()> { + for file in &self.files { + file.create(repo_root)?; + } + + Ok(()) + } +} + +pub(crate) async fn validate_analytics( + test_cases:&[TestCase], + source:analytics::CacheSource, + port:u16, +) -> Result<()> { + let response = reqwest::get(format!("http://localhost:{}/v8/artifacts/events", port)).await?; + assert_eq!(response.status(), 200); + let analytics_events:Vec = response.json().await?; + + assert_eq!(analytics_events.len(), test_cases.len() * 2); + + println!("{:#?}", analytics_events); + for test_case in test_cases { + println!("finding {}", test_case.hash); + // We should have a hit and a miss event for both test cases + analytics_events + .iter() + .find(|event| { + event.hash == test_case.hash + && matches!(event.event, analytics::CacheEvent::Miss) + && event.source == source + }) + .unwrap(); + + analytics_events + .iter() + .find(|event| { + event.hash == test_case.hash + && matches!(event.event, analytics::CacheEvent::Hit) + && event.source == source + }) + .unwrap(); + } + + Ok(()) +} + +pub(crate) fn get_test_cases() -> Vec { + vec![ + TestCase { + files:vec![TestFile::file( + AnchoredSystemPathBuf::from_raw("package.json").unwrap(), + "hello world", + )], + duration:58, + hash:"Faces Places", + }, + TestCase { + files:vec![ + TestFile::file( + AnchoredSystemPathBuf::from_raw("package.json").unwrap(), + "Days of Heaven", + ), + TestFile::file( + AnchoredSystemPathBuf::from_raw("package-lock.json").unwrap(), + "Badlands", + ), + ], + duration:1284, + hash:"Cleo from 5 to 7", + }, + TestCase { + files:vec![ + TestFile::file( + AnchoredSystemPathBuf::from_raw("package.json").unwrap(), + "Days of Heaven", + ), + TestFile::file( + AnchoredSystemPathBuf::from_raw("package-lock.json").unwrap(), + "Badlands", + ), + TestFile::directory(AnchoredSystemPathBuf::from_raw("src").unwrap()), + TestFile::file( + AnchoredSystemPathBuf::from_raw("src/main.js").unwrap(), + "Tree of Life", + ), + ], + duration:12845, + hash:"The Gleaners and I", + }, + ] +} diff --git a/crates/turborepo-cache/Source/upload_progress.rs b/crates/turborepo-cache/Source/upload_progress.rs new file mode 100644 index 0000000000000..2c72d46f2a8ee --- /dev/null +++ b/crates/turborepo-cache/Source/upload_progress.rs @@ -0,0 +1,141 @@ +use std::{ + pin::Pin, + sync::{Arc, Mutex, Weak}, + task::{Context, Poll}, + time::Instant, +}; + +use futures::Stream; +use pin_project::pin_project; + +type State = Mutex<(usize, [(usize, usize); BUCKETS])>; + +/// Consists of a total file upload time and a ring buffer of bytes sent per +/// second over some time interval. +#[pin_project] +pub struct UploadProgress { + /// A pair of bucket generation and bytes uploaded in that bucket. + /// + /// We need to store the generation to ensure that we don't accidentally + /// read from an expired bucket if there is a gap in writing. + state:Arc>, + start:Instant, + #[pin] + inner:S, +} + +impl UploadProgress { + /// Create a new `UploadProgress` with the given stream and interval. + pub fn new(inner:S, size:Option) -> (Self, UploadProgressQuery) { + let state = Arc::new(Mutex::new((0, [(0, 0); BUCKETS]))); + let now = Instant::now(); + let query = UploadProgressQuery::new(now, Arc::downgrade(&state), size); + + (Self { state, start:now, inner }, query) + } +} + +impl Stream + for UploadProgress +where + S::Item: ProgressLen, +{ + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx:&mut Context) -> Poll> { + let this = self.as_mut().project(); + match this.inner.poll_next(cx) { + Poll::Ready(Some(item)) => { + // same as `curr_gen_index` but we can't borrow `self` twice + let (curr_gen, index) = { + // usize fits 570 million years of milliseconds since start on 64 bit + let gen = (this.start.elapsed().as_millis() as usize) / INTERVAL; + (gen, gen % BUCKETS) + }; + let mut state = this.state.lock().unwrap(); + let (gen, value) = &mut state.1[index]; + if *gen != curr_gen { + *gen = curr_gen; + *value = item.len(); + } else { + *value += item.len(); + } + + state.0 += item.len(); + + Poll::Ready(Some(item)) + }, + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } + + fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } +} + +trait ProgressLen { + fn len(&self) -> usize; +} + +impl ProgressLen for bytes::Bytes { + fn len(&self) -> usize { self.len() } +} + +impl ProgressLen for Result { + fn len(&self) -> usize { + match self { + Ok(t) => t.len(), + Err(_) => 0, + } + } +} + +#[derive(Clone)] +pub struct UploadProgressQuery { + start:Instant, + state:Weak>, + size:Option, +} + +impl UploadProgressQuery { + fn new(start:Instant, state:Weak>, size:Option) -> Self { + Self { start, state, size } + } + + // Note: this usize is since the upload started so, on 64 bit systems, it + // should be good for 584.5 million years. Downcasting is probably safe... + fn curr_gen(&self) -> usize { + let since = self.start.elapsed().as_millis() as usize; + since / self.interval_ms() + } + + pub const fn interval_ms(&self) -> usize { INTERVAL } + + /// Get the total number of bytes uploaded. + /// + /// Returns `None` if the `UploadProgress` has been dropped. + pub fn bytes(&self) -> Option { self.state.upgrade().map(|s| s.lock().unwrap().0) } + + pub fn size(&self) -> Option { self.size } + + pub fn done(&self) -> bool { self.state.strong_count() == 0 } + + /// Get the average bytes per second over the last `SIZE` intervals. + /// + /// Returns `None` if the `UploadProgress` has been dropped. + pub fn average_bps(&self) -> Option { + let curr_gen = self.curr_gen(); + let min_gen = curr_gen.saturating_sub(BUCKETS); + self.state.upgrade().map(|s| { + let s = s.lock().unwrap(); + let total_bytes = + s.1.iter() + .filter(|(gen, _)| *gen >= min_gen) + .map(|(_, bytes)| *bytes) + .sum::(); + + // buckets * interval = milliseconds, so we multiply by 1000 to get seconds + (total_bytes as f64 / (BUCKETS * INTERVAL) as f64) * 1000.0 + }) + } +} diff --git a/crates/turborepo-cache/fixtures/name-traversal.tar b/crates/turborepo-cache/fixtures/name-traversal.tar deleted file mode 100644 index c7fddce76facc..0000000000000 Binary files a/crates/turborepo-cache/fixtures/name-traversal.tar and /dev/null differ diff --git a/crates/turborepo-cache/fixtures/name-traversal.tar.zst b/crates/turborepo-cache/fixtures/name-traversal.tar.zst deleted file mode 100644 index 939adebe502c1..0000000000000 Binary files a/crates/turborepo-cache/fixtures/name-traversal.tar.zst and /dev/null differ diff --git a/crates/turborepo-cache/fixtures/windows-unsafe.tar b/crates/turborepo-cache/fixtures/windows-unsafe.tar deleted file mode 100644 index 123fccacfee81..0000000000000 Binary files a/crates/turborepo-cache/fixtures/windows-unsafe.tar and /dev/null differ diff --git a/crates/turborepo-cache/fixtures/windows-unsafe.tar.zst b/crates/turborepo-cache/fixtures/windows-unsafe.tar.zst deleted file mode 100644 index 57c7cfaccc6e8..0000000000000 Binary files a/crates/turborepo-cache/fixtures/windows-unsafe.tar.zst and /dev/null differ diff --git a/crates/turborepo-cache/src/async_cache.rs b/crates/turborepo-cache/src/async_cache.rs deleted file mode 100644 index 23126ce07a5c1..0000000000000 --- a/crates/turborepo-cache/src/async_cache.rs +++ /dev/null @@ -1,540 +0,0 @@ -use std::sync::{atomic::AtomicU8, Arc, Mutex}; - -use futures::{stream::FuturesUnordered, StreamExt}; -use tokio::sync::{mpsc, oneshot, Semaphore}; -use tracing::{warn, Instrument, Level}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; -use turborepo_analytics::AnalyticsSender; -use turborepo_api_client::{APIAuth, APIClient}; - -use crate::{ - http::UploadMap, multiplexer::CacheMultiplexer, CacheError, CacheHitMetadata, CacheOpts, -}; - -const WARNING_CUTOFF: u8 = 4; - -#[derive(Clone)] -pub struct AsyncCache { - real_cache: Arc, - writer_sender: mpsc::Sender, -} - -enum WorkerRequest { - WriteRequest { - anchor: AbsoluteSystemPathBuf, - key: String, - duration: u64, - files: Vec, - }, - Flush(oneshot::Sender<()>), - /// Shutdown the cache. The first oneshot notifies when shutdown starts and - /// allows the user to inspect the status of the uploads. The second - /// oneshot notifies when the shutdown is complete. - Shutdown(oneshot::Sender>>, oneshot::Sender<()>), -} - -impl AsyncCache { - pub fn new( - opts: &CacheOpts, - repo_root: &AbsoluteSystemPath, - api_client: APIClient, - api_auth: Option, - analytics_recorder: Option, - ) -> Result { - let max_workers = opts.workers.try_into().expect("usize is smaller than u32"); - let real_cache = Arc::new(CacheMultiplexer::new( - opts, - repo_root, - api_client, - api_auth, - analytics_recorder, - )?); - let (writer_sender, mut write_consumer) = mpsc::channel(1); - - // start a task to manage workers - let worker_real_cache = real_cache.clone(); - tokio::spawn(async move { - let semaphore = Arc::new(Semaphore::new(max_workers)); - let mut workers = FuturesUnordered::new(); - let real_cache = worker_real_cache; - let warnings = Arc::new(AtomicU8::new(0)); - - let mut shutdown_callback = None; - while let Some(request) = write_consumer.recv().await { - match request { - WorkerRequest::WriteRequest { - anchor, - key, - duration, - files, - } => { - let permit = semaphore.clone().acquire_owned().await.unwrap(); - let real_cache = real_cache.clone(); - let warnings = warnings.clone(); - let worker_span = tracing::span!(Level::TRACE, "cache worker: cache PUT"); - workers.push(tokio::spawn( - async move { - if let Err(err) = - real_cache.put(&anchor, &key, &files, duration).await - { - let num_warnings = - warnings.load(std::sync::atomic::Ordering::Acquire); - if num_warnings <= WARNING_CUTOFF { - warnings.store( - num_warnings + 1, - std::sync::atomic::Ordering::Release, - ); - warn!("{err}"); - } - } - // Release permit once we're done with the write - drop(permit); - } - .instrument(worker_span), - )) - } - WorkerRequest::Flush(callback) => { - // Wait on all workers to finish writing - while let Some(worker) = workers.next().await { - let _ = worker; - } - drop(callback); - } - WorkerRequest::Shutdown(closing, done) => { - shutdown_callback = Some((closing, done)); - break; - } - }; - } - // Drop write consumer to immediately notify callers that cache is shutting down - drop(write_consumer); - - let shutdown_callback = if let Some((closing, done)) = shutdown_callback { - closing.send(real_cache.requests().unwrap_or_default()).ok(); - Some(done) - } else { - None - }; - - // wait for all writers to finish - while let Some(worker) = workers.next().await { - let _ = worker; - } - - if let Some(callback) = shutdown_callback { - callback.send(()).ok(); - } - }); - - Ok(AsyncCache { - real_cache, - writer_sender, - }) - } - - #[tracing::instrument(skip_all)] - pub async fn put( - &self, - anchor: AbsoluteSystemPathBuf, - key: String, - files: Vec, - duration: u64, - ) -> Result<(), CacheError> { - if self - .writer_sender - .send(WorkerRequest::WriteRequest { - anchor, - key, - duration, - files, - }) - .await - .is_err() - { - Err(CacheError::CacheShuttingDown) - } else { - Ok(()) - } - } - - #[tracing::instrument(skip_all)] - pub async fn exists(&self, key: &str) -> Result, CacheError> { - self.real_cache.exists(key).await - } - - #[tracing::instrument(skip_all)] - pub async fn fetch( - &self, - anchor: &AbsoluteSystemPath, - key: &str, - ) -> Result)>, CacheError> { - self.real_cache.fetch(anchor, key).await - } - - // Used for testing to ensure that the workers resolve - // before checking the cache. - #[tracing::instrument(skip_all)] - pub async fn wait(&self) -> Result<(), CacheError> { - let (tx, rx) = oneshot::channel(); - self.writer_sender - .send(WorkerRequest::Flush(tx)) - .await - .map_err(|_| CacheError::CacheShuttingDown)?; - // Wait until flush callback is finished - rx.await.ok(); - Ok(()) - } - - /// Shut down the cache, waiting for all workers to finish writing. - /// This function returns as soon as the shut down has started, - /// returning a channel through which workers can report on their - /// progress. - #[tracing::instrument(skip_all)] - pub async fn start_shutdown( - &self, - ) -> Result<(Arc>, oneshot::Receiver<()>), CacheError> { - let (closing_tx, closing_rx) = oneshot::channel::>>(); - let (closed_tx, closed_rx) = oneshot::channel::<()>(); - self.writer_sender - .send(WorkerRequest::Shutdown(closing_tx, closed_tx)) - .await - .map_err(|_| CacheError::CacheShuttingDown)?; - Ok((closing_rx.await.unwrap(), closed_rx)) // todo - } - - /// Shut down the cache, waiting for all workers to finish writing. - /// This function returns only when the last worker is complete. - /// It is a convenience wrapper around `start_shutdown`. - #[tracing::instrument(skip_all)] - pub async fn shutdown(&self) -> Result<(), CacheError> { - let (_, closed_rx) = self.start_shutdown().await?; - closed_rx.await.ok(); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use std::{assert_matches::assert_matches, time::Duration}; - - use anyhow::Result; - use camino::Utf8PathBuf; - use futures::future::try_join_all; - use tempfile::tempdir; - use turbopath::AbsoluteSystemPathBuf; - use turborepo_api_client::{APIAuth, APIClient}; - use turborepo_vercel_api_mock::start_test_server; - - use crate::{ - test_cases::{get_test_cases, TestCase}, - AsyncCache, CacheActions, CacheConfig, CacheHitMetadata, CacheOpts, CacheSource, - RemoteCacheOpts, - }; - - #[tokio::test] - async fn test_async_cache() -> Result<()> { - let port = port_scanner::request_open_port().unwrap(); - let handle = tokio::spawn(start_test_server(port)); - - try_join_all(get_test_cases().into_iter().map(|test_case| async move { - round_trip_test_with_both_caches(&test_case, port).await?; - round_trip_test_without_remote_cache(&test_case).await?; - round_trip_test_without_fs(&test_case, port).await - })) - .await?; - - handle.abort(); - Ok(()) - } - - async fn round_trip_test_without_fs(test_case: &TestCase, port: u16) -> Result<()> { - let repo_root = tempdir()?; - let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; - test_case.initialize(&repo_root_path)?; - - let hash = format!("{}-no-fs", test_case.hash); - - let opts = CacheOpts { - cache_dir: Utf8PathBuf::from(".turbo/cache"), - cache: CacheConfig { - local: CacheActions { - read: false, - write: false, - }, - remote: CacheActions { - read: true, - write: true, - }, - }, - workers: 10, - remote_cache_opts: Some(RemoteCacheOpts { - unused_team_id: Some("my-team".to_string()), - signature: false, - }), - }; - - let api_client = APIClient::new( - format!("http://localhost:{}", port), - Some(Duration::from_secs(200)), - None, - "2.0.0", - true, - )?; - let api_auth = Some(APIAuth { - team_id: Some("my-team-id".to_string()), - token: "my-token".to_string(), - team_slug: None, - }); - let async_cache = AsyncCache::new(&opts, &repo_root_path, api_client, api_auth, None)?; - - // Ensure that the cache is empty - let response = async_cache.exists(&hash).await; - - assert_matches!(response, Ok(None)); - - // Add test case - async_cache - .put( - repo_root_path.clone(), - hash.clone(), - test_case - .files - .iter() - .map(|f| f.path().to_owned()) - .collect(), - test_case.duration, - ) - .await - .unwrap(); - - // Wait for async cache to process - async_cache.wait().await.unwrap(); - - let fs_cache_path = - repo_root_path.join_components(&[".turbo", "cache", &format!("{}.tar.zst", hash)]); - - // Confirm that fs cache file does *not* exist - assert!(!fs_cache_path.exists()); - - let response = async_cache.exists(&hash).await?; - - // Confirm that we fetch from remote cache and not local. - assert_eq!( - response, - Some(CacheHitMetadata { - source: CacheSource::Remote, - time_saved: test_case.duration - }) - ); - - async_cache.shutdown().await.unwrap(); - assert!( - async_cache.shutdown().await.is_err(), - "second shutdown should error" - ); - - Ok(()) - } - - async fn round_trip_test_without_remote_cache(test_case: &TestCase) -> Result<()> { - let repo_root = tempdir()?; - let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; - test_case.initialize(&repo_root_path)?; - - let hash = format!("{}-no-remote", test_case.hash); - - let opts = CacheOpts { - cache_dir: Utf8PathBuf::from(".turbo/cache"), - cache: CacheConfig { - local: CacheActions { - read: true, - write: true, - }, - remote: CacheActions { - read: false, - write: false, - }, - }, - workers: 10, - remote_cache_opts: Some(RemoteCacheOpts { - unused_team_id: Some("my-team".to_string()), - signature: false, - }), - }; - - // Initialize client with invalid API url to ensure that we don't hit the - // network - let api_client = APIClient::new( - "http://example.com", - Some(Duration::from_secs(200)), - None, - "2.0.0", - true, - )?; - let api_auth = Some(APIAuth { - team_id: Some("my-team-id".to_string()), - token: "my-token".to_string(), - team_slug: None, - }); - let async_cache = AsyncCache::new(&opts, &repo_root_path, api_client, api_auth, None)?; - - // Ensure that the cache is empty - let response = async_cache.exists(&hash).await; - - assert_matches!(response, Ok(None)); - - // Add test case - async_cache - .put( - repo_root_path.clone(), - hash.clone(), - test_case - .files - .iter() - .map(|f| f.path().to_owned()) - .collect(), - test_case.duration, - ) - .await - .unwrap(); - - // Wait for async cache to process - async_cache.wait().await.unwrap(); - - let fs_cache_path = - repo_root_path.join_components(&[".turbo", "cache", &format!("{}.tar.zst", hash)]); - - // Confirm that fs cache file exists - assert!(fs_cache_path.exists()); - - let response = async_cache.exists(&hash).await?; - - // Confirm that we fetch from local cache first. - assert_eq!( - response, - Some(CacheHitMetadata { - source: CacheSource::Local, - time_saved: test_case.duration - }) - ); - - // Remove fs cache file - fs_cache_path.remove_file()?; - - let response = async_cache.exists(&hash).await?; - - // Confirm that we get a cache miss - assert!(response.is_none()); - - async_cache.shutdown().await.unwrap(); - assert!( - async_cache.shutdown().await.is_err(), - "second shutdown should error" - ); - - Ok(()) - } - - async fn round_trip_test_with_both_caches(test_case: &TestCase, port: u16) -> Result<()> { - let repo_root = tempdir()?; - let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; - test_case.initialize(&repo_root_path)?; - - let hash = format!("{}-both", test_case.hash); - - let opts = CacheOpts { - cache_dir: Utf8PathBuf::from(".turbo/cache"), - cache: CacheConfig { - local: CacheActions { - read: true, - write: true, - }, - remote: CacheActions { - read: true, - write: true, - }, - }, - workers: 10, - remote_cache_opts: Some(RemoteCacheOpts { - unused_team_id: Some("my-team".to_string()), - signature: false, - }), - }; - - let api_client = APIClient::new( - format!("http://localhost:{}", port), - Some(Duration::from_secs(200)), - None, - "2.0.0", - true, - )?; - let api_auth = Some(APIAuth { - team_id: Some("my-team-id".to_string()), - token: "my-token".to_string(), - team_slug: None, - }); - let async_cache = AsyncCache::new(&opts, &repo_root_path, api_client, api_auth, None)?; - - // Ensure that the cache is empty - let response = async_cache.exists(&hash).await; - - assert_matches!(response, Ok(None)); - - // Add test case - async_cache - .put( - repo_root_path.clone(), - hash.clone(), - test_case - .files - .iter() - .map(|f| f.path().to_owned()) - .collect(), - test_case.duration, - ) - .await - .unwrap(); - - // Wait for async cache to process - async_cache.wait().await.unwrap(); - - let fs_cache_path = - repo_root_path.join_components(&[".turbo", "cache", &format!("{}.tar.zst", hash)]); - - // Confirm that fs cache file exists - assert!(fs_cache_path.exists()); - - let response = async_cache.exists(&hash).await?; - - // Confirm that we fetch from local cache first. - assert_eq!( - response, - Some(CacheHitMetadata { - source: CacheSource::Local, - time_saved: test_case.duration - }) - ); - - // Remove fs cache file - fs_cache_path.remove_file()?; - - let response = async_cache.exists(&hash).await?; - - // Confirm that we still can fetch from remote cache - assert_eq!( - response, - Some(CacheHitMetadata { - source: CacheSource::Remote, - time_saved: test_case.duration - }) - ); - - async_cache.shutdown().await.unwrap(); - assert!( - async_cache.shutdown().await.is_err(), - "second shutdown should error" - ); - - Ok(()) - } -} diff --git a/crates/turborepo-cache/src/cache_archive/create.rs b/crates/turborepo-cache/src/cache_archive/create.rs deleted file mode 100644 index a63de864de958..0000000000000 --- a/crates/turborepo-cache/src/cache_archive/create.rs +++ /dev/null @@ -1,454 +0,0 @@ -use std::{ - backtrace::Backtrace, - fs, - fs::OpenOptions, - io::{BufWriter, Read, Write}, - path::Path, -}; - -use tar::{EntryType, Header}; -use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, IntoUnix}; - -use crate::CacheError; - -pub struct CacheWriter<'a> { - builder: tar::Builder>, -} - -impl<'a> CacheWriter<'a> { - // Appends data to tar builder. - fn append_data( - &mut self, - header: &mut Header, - path: impl AsRef, - body: impl Read, - ) -> Result<(), CacheError> { - Ok(self.builder.append_data(header, path, body)?) - } - - fn append_link( - &mut self, - header: &mut Header, - path: impl AsRef, - target: impl AsRef, - ) -> Result<(), CacheError> { - Ok(self.builder.append_link(header, path, target)?) - } - - pub fn finish(mut self) -> Result<(), CacheError> { - Ok(self.builder.finish()?) - } - - pub fn from_writer(writer: impl Write + 'a, use_compression: bool) -> Result { - if use_compression { - let zw = zstd::Encoder::new(writer, 0)?.auto_finish(); - Ok(CacheWriter { - builder: tar::Builder::new(Box::new(zw)), - }) - } else { - Ok(CacheWriter { - builder: tar::Builder::new(Box::new(writer)), - }) - } - } - - // Makes a new CacheArchive at the specified path - // Wires up the chain of writers: - // tar::Builder -> zstd::Encoder (optional) -> BufWriter -> File - pub fn create(path: &AbsoluteSystemPath) -> Result { - let mut options = OpenOptions::new(); - options.write(true).create(true).truncate(true); - - let file = path.open_with_options(options)?; - - // Flush to disk in 1mb chunks. - let file_buffer = BufWriter::with_capacity(2usize.pow(20), file); - - let is_compressed = path.extension() == Some("zst"); - - if is_compressed { - let zw = zstd::Encoder::new(file_buffer, 0)?.auto_finish(); - - Ok(CacheWriter { - builder: tar::Builder::new(Box::new(zw)), - }) - } else { - Ok(CacheWriter { - builder: tar::Builder::new(Box::new(file_buffer)), - }) - } - } - - // Adds a user-cached item to the tar - pub(crate) fn add_file( - &mut self, - anchor: &AbsoluteSystemPath, - file_path: &AnchoredSystemPath, - ) -> Result<(), CacheError> { - // Resolve the fully-qualified path to the file to read it. - let source_path = anchor.resolve(file_path); - - // Grab the file info to construct the header. - let file_info = source_path.symlink_metadata()?; - - // Normalize the path within the cache - let mut file_path = file_path.to_unix(); - file_path.make_canonical_for_tar(file_info.is_dir()); - - let mut header = Self::create_header(&file_info)?; - - if matches!(header.entry_type(), EntryType::Regular) && file_info.len() > 0 { - let file = source_path.open()?; - self.append_data(&mut header, file_path.as_str(), file)?; - } else if matches!(header.entry_type(), EntryType::Symlink) { - // We convert to a Unix path because all paths in tar should be - // Unix-style. This will get restored to a system path. - let target = source_path.read_link()?.into_unix(); - self.append_link(&mut header, file_path.as_str(), &target)?; - } else { - self.append_data(&mut header, file_path.as_str(), &mut std::io::empty())?; - } - - Ok(()) - } - - fn create_header(file_info: &fs::Metadata) -> Result { - let mut header = Header::new_gnu(); - - let mode: u32; - #[cfg(unix)] - { - use std::os::unix::fs::MetadataExt; - mode = file_info.mode(); - } - #[cfg(windows)] - { - // Windows makes up 0o666 for files, which in the Go code - // we do: (0o666 & 0o755) | 0o111 which produces 0o755 - mode = 0o755 - } - header.set_mode(mode); - - if file_info.is_symlink() { - // We do *not* set the linkname here because it could be too long - // Instead we set it when we add the file to the archive - header.set_entry_type(EntryType::Symlink); - header.set_size(0); - } else if file_info.is_dir() { - header.set_size(0); - header.set_entry_type(EntryType::Directory); - } else if file_info.is_file() { - header.set_entry_type(EntryType::Regular); - header.set_size(file_info.len()); - } else { - // Throw an error if trying to create a cache that contains a type we don't - // support. - return Err(CacheError::CreateUnsupportedFileType(Backtrace::capture())); - } - - // Consistent creation - header.set_uid(0); - header.set_gid(0); - header.as_gnu_mut().unwrap().set_atime(0); - header.set_mtime(0); - header.as_gnu_mut().unwrap().set_ctime(0); - - Ok(header) - } -} - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use anyhow::Result; - use tempfile::tempdir; - use test_case::test_case; - use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; - - use super::*; - use crate::cache_archive::restore::CacheReader; - - #[derive(Debug)] - enum FileType { - Dir, - Symlink { linkname: String }, - Fifo, - File, - } - - #[derive(Debug)] - struct CreateFileDefinition { - path: AnchoredSystemPathBuf, - mode: u32, - file_type: FileType, - } - - fn create_entry(anchor: &AbsoluteSystemPath, file: &CreateFileDefinition) -> Result<()> { - match &file.file_type { - FileType::Dir => create_dir(anchor, file), - FileType::Symlink { linkname } => create_symlink(anchor, file, linkname), - FileType::Fifo => create_fifo(anchor, file), - FileType::File => create_file(anchor, file), - } - } - - fn create_dir(anchor: &AbsoluteSystemPath, file: &CreateFileDefinition) -> Result<()> { - let path = anchor.resolve(&file.path); - path.create_dir_all()?; - - #[cfg(unix)] - { - path.set_mode(file.mode & 0o777)?; - } - - Ok(()) - } - - fn create_symlink( - anchor: &AbsoluteSystemPath, - file: &CreateFileDefinition, - linkname: &str, - ) -> Result<()> { - let path = anchor.resolve(&file.path); - path.symlink_to_file(linkname)?; - - Ok(()) - } - - #[cfg(unix)] - fn create_fifo(anchor: &AbsoluteSystemPath, file: &CreateFileDefinition) -> Result<()> { - use std::ffi::CString; - - let path = anchor.resolve(&file.path); - let path_cstr = CString::new(path.as_str())?; - - unsafe { - libc::mkfifo(path_cstr.as_ptr(), 0o644); - } - - Ok(()) - } - - #[cfg(windows)] - fn create_fifo(_: &AbsoluteSystemPath, _: &CreateFileDefinition) -> Result<()> { - Err(CacheError::CreateUnsupportedFileType(Backtrace::capture()).into()) - } - - fn create_file(anchor: &AbsoluteSystemPath, file: &CreateFileDefinition) -> Result<()> { - let path = anchor.resolve(&file.path); - fs::write(&path, b"file contents")?; - #[cfg(unix)] - { - path.set_mode(file.mode & 0o777)?; - } - - Ok(()) - } - - #[test_case( - vec![ - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("hello world.txt").unwrap(), - mode: 0o644, - file_type: FileType::File, - } - ], - None - ; "create regular file" - )] - #[test_case( - vec![ - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - mode: 0o777, - file_type: FileType::Symlink { linkname: "two".to_string() }, - }, - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("two").unwrap(), - mode: 0o777, - file_type: FileType::Symlink { linkname: "three".to_string() }, - }, - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("three").unwrap(), - mode: 0o777, - file_type: FileType::Symlink { linkname: "real".to_string() }, - }, - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("real").unwrap(), - mode: 0o777, - file_type: FileType::File, - } - ], - None - ; "create symlinks" - )] - #[test_case( - vec![ - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("parent").unwrap(), - mode: 0o777, - file_type: FileType::Dir, - }, - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("parent/child").unwrap(), - mode: 0o644, - file_type: FileType::File, - }, - ], - None - ; "create directory" - )] - #[test_case( - vec![ - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - mode: 0o644, - file_type: FileType::Symlink { linkname: "two".to_string() }, - }, - ], - None - ; "create broken symlink" - )] - #[test_case( - vec![ - CreateFileDefinition { - path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - mode: 0o644, - file_type: FileType::Fifo, - } - ], - Some("attempted to create unsupported file type") - ; "create unsupported" - )] - fn test_create( - files: Vec, - #[allow(unused_variables)] expected_err: Option<&str>, - ) -> Result<()> { - 'outer: for compressed in [false, true] { - let input_dir = tempdir()?; - let archive_dir = tempdir()?; - let input_dir_path = AbsoluteSystemPathBuf::try_from(input_dir.path())?; - let archive_path = if compressed { - AbsoluteSystemPathBuf::try_from(archive_dir.path().join("out.tar.zst"))? - } else { - AbsoluteSystemPathBuf::try_from(archive_dir.path().join("out.tar"))? - }; - - let mut cache_archive = CacheWriter::create(&archive_path)?; - - for file in files.iter() { - let result = create_entry(&input_dir_path, file); - if let Err(err) = result { - assert!(expected_err.is_some()); - assert_eq!(err.to_string(), expected_err.unwrap()); - continue 'outer; - } - - let result = cache_archive.add_file(&input_dir_path, &file.path); - if let Err(err) = result { - assert!(expected_err.is_some()); - assert_eq!(err.to_string(), expected_err.unwrap()); - continue 'outer; - } - } - - cache_archive.finish()?; - } - - Ok(()) - } - - #[test] - #[cfg(unix)] - fn test_add_trailing_slash_unix() { - let mut path = PathBuf::from("foo/bar"); - assert_eq!(path.to_string_lossy(), "foo/bar"); - path.push(""); - assert_eq!(path.to_string_lossy(), "foo/bar/"); - - // Confirm that this is idempotent - path.push(""); - assert_eq!(path.to_string_lossy(), "foo/bar/"); - } - - #[test] - #[cfg(windows)] - fn test_add_trailing_slash_windows() { - let mut path = PathBuf::from("foo\\bar"); - assert_eq!(path.to_string_lossy(), "foo\\bar"); - path.push(""); - assert_eq!(path.to_string_lossy(), "foo\\bar\\"); - - // Confirm that this is idempotent - path.push(""); - assert_eq!(path.to_string_lossy(), "foo\\bar\\"); - } - - #[test] - fn create_tar_with_really_long_name() -> Result<()> { - let archive_dir = tempdir()?; - let archive_dir_path = AbsoluteSystemPath::new(archive_dir.path().to_str().unwrap())?; - - let tar_dir = tempdir()?; - let tar_dir_path = AbsoluteSystemPath::new(tar_dir.path().to_str().unwrap())?; - - let tar_path = tar_dir_path.join_component("test.tar"); - let mut archive = CacheWriter::create(&tar_path)?; - let base = "this-is-a-really-really-really-long-path-like-so-very-long-that-i-can-list-all-of-my-favorite-directors-like-edward-yang-claire-denis-lucrecia-martel-wong-kar-wai-even-kurosawa"; - let file_name = format!("{base}.txt"); - let dir_symlink_name = format!("{base}-dir"); - let really_long_file = AnchoredSystemPath::new(&file_name).unwrap(); - let really_long_dir = AnchoredSystemPath::new(base).unwrap(); - let really_long_symlink = AnchoredSystemPath::new("this-is-a-really-really-really-long-symlink-like-so-very-long-that-i-can-list-all-of-my-other-favorite-directors-like-jim-jarmusch-michelangelo-antonioni-and-terrence-malick-symlink").unwrap(); - let really_long_dir_symlink = AnchoredSystemPath::new(&dir_symlink_name).unwrap(); - - let really_long_path = archive_dir_path.resolve(really_long_file); - really_long_path.create_with_contents("The End!")?; - - let really_long_symlink_path = archive_dir_path.resolve(really_long_symlink); - really_long_symlink_path.symlink_to_file(really_long_file.as_str())?; - - let really_long_dir_path = archive_dir_path.resolve(really_long_dir); - really_long_dir_path.create_dir_all()?; - - let really_long_dir_symlink_path = archive_dir_path.resolve(really_long_dir_symlink); - really_long_dir_symlink_path.symlink_to_dir(really_long_dir.as_str())?; - - archive.add_file(archive_dir_path, really_long_file)?; - archive.add_file(archive_dir_path, really_long_dir_symlink)?; - archive.add_file(archive_dir_path, really_long_dir)?; - archive.add_file(archive_dir_path, really_long_symlink)?; - - archive.finish()?; - - let restore_dir = tempdir()?; - let restore_dir_path = AbsoluteSystemPath::new(restore_dir.path().to_str().unwrap())?; - - let mut restore = CacheReader::open(&tar_path)?; - let files = restore.restore(restore_dir_path)?; - assert_eq!(files.len(), 4); - assert_eq!(files[0].as_str(), really_long_file.as_str()); - assert_eq!(files[1].as_str(), really_long_dir.as_str()); - assert_eq!(files[2].as_str(), really_long_symlink.as_str()); - assert_eq!(files[3].as_str(), really_long_dir_symlink.as_str()); - Ok(()) - } - - #[test] - fn test_compression() -> Result<()> { - let mut buffer = Vec::new(); - let mut encoder = zstd::Encoder::new(&mut buffer, 0)?.auto_finish(); - encoder.write_all(b"hello world")?; - // Should finish encoding on drop - drop(encoder); - - let mut decoder = zstd::Decoder::new(&buffer[..])?; - let mut out = String::new(); - decoder.read_to_string(&mut out)?; - - assert_eq!(out, "hello world"); - - Ok(()) - } -} diff --git a/crates/turborepo-cache/src/cache_archive/restore.rs b/crates/turborepo-cache/src/cache_archive/restore.rs deleted file mode 100644 index 7dbf1ebb3e7a1..0000000000000 --- a/crates/turborepo-cache/src/cache_archive/restore.rs +++ /dev/null @@ -1,937 +0,0 @@ -use std::{backtrace::Backtrace, collections::HashMap, io::Read}; - -use petgraph::graph::DiGraph; -use sha2::{Digest, Sha512}; -use tar::Entry; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; - -use crate::{ - cache_archive::{ - restore_directory::{restore_directory, CachedDirTree}, - restore_regular::restore_regular, - restore_symlink::{ - canonicalize_linkname, restore_symlink, restore_symlink_allow_missing_target, - }, - }, - CacheError, -}; - -pub struct CacheReader<'a> { - reader: Box, -} - -impl<'a> CacheReader<'a> { - pub fn from_reader(reader: impl Read + 'a, is_compressed: bool) -> Result { - let reader: Box = if is_compressed { - Box::new(zstd::Decoder::new(reader)?) - } else { - Box::new(reader) - }; - - Ok(CacheReader { reader }) - } - - pub fn open(path: &AbsoluteSystemPathBuf) -> Result { - let file = path.open()?; - let is_compressed = path.extension() == Some("zst"); - - let reader: Box = if is_compressed { - Box::new(zstd::Decoder::new(file)?) - } else { - Box::new(file) - }; - - Ok(CacheReader { reader }) - } - - pub fn get_sha(mut self) -> Result, CacheError> { - let mut hasher = Sha512::new(); - let mut buffer = [0; 8192]; - loop { - let n = self.reader.read(&mut buffer)?; - if n == 0 { - break; - } - hasher.update(&buffer[..n]); - } - - Ok(hasher.finalize().to_vec()) - } - - pub fn restore( - &mut self, - anchor: &AbsoluteSystemPath, - ) -> Result, CacheError> { - let mut restored = Vec::new(); - anchor.create_dir_all()?; - - // We're going to make the following two assumptions here for "fast" - // path restoration: - // - All directories are enumerated in the `tar`. - // - The contents of the tar are enumerated depth-first. - // - // This allows us to avoid: - // - Attempts at recursive creation of directories. - // - Repetitive `lstat` on restore of a file. - // - // Violating these assumptions won't cause things to break but we're - // only going to maintain an `lstat` cache for the current tree. - // If you violate these assumptions and the current cache does - // not apply for your path, it will clobber and re-start from the common - // shared prefix. - let dir_cache = CachedDirTree::new(anchor.to_owned()); - let mut tr = tar::Archive::new(&mut self.reader); - - Self::restore_entries(&mut tr, &mut restored, dir_cache, anchor)?; - Ok(restored) - } - - fn restore_entries( - tr: &mut tar::Archive, - restored: &mut Vec, - mut dir_cache: CachedDirTree, - anchor: &AbsoluteSystemPath, - ) -> Result<(), CacheError> { - // On first attempt to restore it's possible that a link target doesn't exist. - // Save them and topologically sort them. - let mut symlinks = Vec::new(); - - for entry in tr.entries()? { - let mut entry = entry?; - match restore_entry(&mut dir_cache, anchor, &mut entry) { - Err(CacheError::LinkTargetDoesNotExist(_, _)) => { - symlinks.push(entry); - } - Err(e) => return Err(e), - Ok(restored_path) => restored.push(restored_path), - } - } - - let mut restored_symlinks = - Self::topologically_restore_symlinks(&mut dir_cache, anchor, &symlinks)?; - restored.append(&mut restored_symlinks); - Ok(()) - } - - fn topologically_restore_symlinks( - dir_cache: &mut CachedDirTree, - anchor: &AbsoluteSystemPath, - symlinks: &[Entry<'_, T>], - ) -> Result, CacheError> { - let mut graph = DiGraph::new(); - let mut entry_lookup = HashMap::new(); - let mut restored = Vec::new(); - let mut nodes = HashMap::new(); - - for entry in symlinks { - let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; - let processed_sourcename = - canonicalize_linkname(anchor, &processed_name, processed_name.as_path())?; - // symlink must have a linkname - let linkname = entry.link_name()?.expect("symlink without linkname"); - - let processed_linkname = canonicalize_linkname(anchor, &processed_name, &linkname)?; - - let source_node = *nodes - .entry(processed_sourcename.clone()) - .or_insert_with(|| graph.add_node(processed_sourcename.clone())); - let link_node = *nodes - .entry(processed_linkname.clone()) - .or_insert_with(|| graph.add_node(processed_linkname.clone())); - - graph.add_edge(source_node, link_node, ()); - - entry_lookup.insert(processed_sourcename, entry); - } - - let nodes = petgraph::algo::toposort(&graph, None) - .map_err(|_| CacheError::CycleDetected(Backtrace::capture()))?; - - for node in nodes { - let key = &graph[node]; - - let Some(entry) = entry_lookup.get(key) else { - continue; - }; - let file = restore_symlink_allow_missing_target(dir_cache, anchor, entry)?; - restored.push(file); - } - - Ok(restored) - } -} - -fn restore_entry( - dir_cache: &mut CachedDirTree, - anchor: &AbsoluteSystemPath, - entry: &mut Entry, -) -> Result { - let header = entry.header(); - - match header.entry_type() { - tar::EntryType::Directory => restore_directory(dir_cache, anchor, entry), - tar::EntryType::Regular => restore_regular(dir_cache, anchor, entry), - tar::EntryType::Symlink => restore_symlink(dir_cache, anchor, entry), - ty => Err(CacheError::RestoreUnsupportedFileType( - ty, - Backtrace::capture(), - )), - } -} - -#[cfg(test)] -mod tests { - use std::{fs, fs::File, io::empty, path::Path}; - - use anyhow::Result; - use tar::Header; - use tempfile::{tempdir, TempDir}; - use test_case::test_case; - use tracing::debug; - use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; - - use crate::cache_archive::{restore::CacheReader, restore_symlink::canonicalize_linkname}; - - // Expected output of the cache - #[derive(Debug)] - struct ExpectedOutput(Vec); - - enum TarFile { - File { - body: Vec, - path: AnchoredSystemPathBuf, - }, - Directory { - path: AnchoredSystemPathBuf, - }, - Symlink { - // The path of the symlink itself - link_path: AnchoredSystemPathBuf, - // The target of the symlink - link_target: AnchoredSystemPathBuf, - }, - Fifo { - path: AnchoredSystemPathBuf, - }, - } - - struct TestCase { - name: &'static str, - // The files we start with - input_files: Vec, - // The expected files (there will be more files than `expected_output` - // since we want to check entries of symlinked directories) - expected_files: Vec, - // What we expect to get from CacheArchive::restore, either a - // Vec of restored files, or an error (represented as a string) - expected_output: Result, String>, - } - - fn generate_tar(test_dir: &TempDir, files: &[TarFile]) -> Result { - let test_archive_path = test_dir.path().join("test.tar"); - let archive_file = File::create(&test_archive_path)?; - - let mut tar_writer = tar::Builder::new(archive_file); - - for file in files { - match file { - TarFile::File { path, body } => { - debug!("Adding file: {:?}", path); - let mut header = Header::new_gnu(); - header.set_size(body.len() as u64); - header.set_entry_type(tar::EntryType::Regular); - header.set_mode(0o644); - tar_writer.append_data(&mut header, path, &body[..])?; - } - TarFile::Directory { path } => { - debug!("Adding directory: {:?}", path); - let mut header = Header::new_gnu(); - header.set_entry_type(tar::EntryType::Directory); - header.set_size(0); - header.set_mode(0o755); - tar_writer.append_data(&mut header, path, empty())?; - } - TarFile::Symlink { - link_path: link_file, - link_target, - } => { - debug!("Adding symlink: {:?} -> {:?}", link_file, link_target); - let mut header = tar::Header::new_gnu(); - header.set_username("foo")?; - header.set_entry_type(tar::EntryType::Symlink); - header.set_size(0); - - tar_writer.append_link(&mut header, link_file, link_target)?; - } - // We don't support this, but we need to add it to a tar for testing purposes - TarFile::Fifo { path } => { - let mut header = tar::Header::new_gnu(); - header.set_entry_type(tar::EntryType::Fifo); - header.set_size(0); - tar_writer.append_data(&mut header, path, empty())?; - } - } - } - - tar_writer.into_inner()?; - - Ok(AbsoluteSystemPathBuf::new( - test_archive_path.to_string_lossy(), - )?) - } - - fn compress_tar(archive_path: &AbsoluteSystemPathBuf) -> Result { - let mut input_file = File::open(archive_path)?; - - let output_file_path = format!("{}.zst", archive_path); - let output_file = File::create(&output_file_path)?; - - let mut zw = zstd::stream::Encoder::new(output_file, 0)?; - std::io::copy(&mut input_file, &mut zw)?; - - zw.finish()?; - - Ok(AbsoluteSystemPathBuf::new(output_file_path)?) - } - - fn assert_file_exists(anchor: &AbsoluteSystemPath, disk_file: &TarFile) -> Result<()> { - match disk_file { - TarFile::File { path, body } => { - let full_name = anchor.resolve(path); - debug!("reading {}", full_name); - let file_contents = fs::read(full_name)?; - - assert_eq!(file_contents, *body); - } - TarFile::Directory { path } => { - let full_name = anchor.resolve(path); - let metadata = fs::metadata(full_name)?; - - assert!(metadata.is_dir()); - } - TarFile::Symlink { - link_path: link_file, - link_target: expected_link_target, - } => { - let full_link_file = anchor.resolve(link_file); - let link_target = fs::read_link(full_link_file)?; - - assert_eq!(link_target, expected_link_target.as_path().to_path_buf()); - } - TarFile::Fifo { .. } => unreachable!("FIFOs are not supported"), - } - - Ok(()) - } - - fn into_anchored_system_path_vec(items: Vec<&'static str>) -> Vec { - items - .into_iter() - .map(|item| AnchoredSystemPathBuf::try_from(Path::new(item)).unwrap()) - .collect() - } - - #[test] - fn test_name_traversal() -> Result<()> { - let uncompressed_tar = include_bytes!("../../fixtures/name-traversal.tar"); - let compressed_tar = include_bytes!("../../fixtures/name-traversal.tar.zst"); - for (tar_bytes, is_compressed) in - [(&uncompressed_tar[..], false), (&compressed_tar[..], true)] - { - let mut cache_reader = CacheReader::from_reader(tar_bytes, is_compressed)?; - let output_dir = tempdir()?; - let output_dir_path = output_dir.path().to_string_lossy(); - let anchor = AbsoluteSystemPath::new(&output_dir_path)?; - let result = cache_reader.restore(anchor); - assert!(result.is_err()); - assert_eq!( - result.unwrap_err().to_string(), - "Invalid file path: path is malformed: ../escape" - ); - } - - Ok(()) - } - - #[test] - fn test_windows_unsafe() -> Result<()> { - let uncompressed_tar = include_bytes!("../../fixtures/windows-unsafe.tar"); - let compressed_tar = include_bytes!("../../fixtures/windows-unsafe.tar.zst"); - - for (tar_bytes, is_compressed) in - [(&uncompressed_tar[..], false), (&compressed_tar[..], true)] - { - let mut cache_reader = CacheReader::from_reader(tar_bytes, is_compressed)?; - let output_dir = tempdir()?; - let output_dir_path = output_dir.path().to_string_lossy(); - let anchor = AbsoluteSystemPath::new(&output_dir_path)?; - let result = cache_reader.restore(anchor); - #[cfg(windows)] - { - assert!(result.is_err()); - assert_eq!( - result.unwrap_err().to_string(), - "Invalid file path: Path is not safe for windows: \ - windows-unsafe/this\\is\\a\\file\\on\\unix" - ); - } - #[cfg(unix)] - { - assert!(result.is_ok()); - let path = result.unwrap().pop().unwrap(); - assert_eq!(path.as_str(), "windows-unsafe/this\\is\\a\\file\\on\\unix"); - } - } - - Ok(()) - } - - #[test] - fn test_restore() -> Result<()> { - let tests = vec![ - TestCase { - name: "cache optimized", - input_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), - }, - ], - expected_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), - body: vec![], - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), - body: vec![], - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), - body: vec![], - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), - body: vec![], - }, - ], - expected_output: Ok(into_anchored_system_path_vec(vec![ - "one", - "one/two", - "one/two/three", - "one/two/a", - "one/two/three/file-one", - "one/two/three/file-two", - "one/two/a/file", - "one/two/b", - "one/two/b/file", - ])), - }, - TestCase { - name: "pathological cache works", - input_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), - }, - TarFile::File { - body: vec![], - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), - }, - ], - expected_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/three/").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-one").unwrap(), - body: vec![], - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/three/file-two").unwrap(), - body: vec![], - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/a/").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/a/file").unwrap(), - body: vec![], - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/b/").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("one/two/b/file").unwrap(), - body: vec![], - }, - ], - expected_output: Ok(into_anchored_system_path_vec(vec![ - "one", - "one/two", - "one/two/a", - "one/two/b", - "one/two/three", - "one/two/a/file", - "one/two/b/file", - "one/two/three/file-one", - "one/two/three/file-two", - ])), - }, - TestCase { - name: "symlink hello world", - input_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("source").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - ], - expected_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("source").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - ], - expected_output: Ok(into_anchored_system_path_vec(vec!["target", "source"])), - }, - TestCase { - name: "nested file", - input_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("folder/").unwrap(), - }, - TarFile::File { - body: b"file".to_vec(), - path: AnchoredSystemPathBuf::from_raw("folder/file").unwrap(), - }, - ], - expected_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("folder/").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("folder/file").unwrap(), - body: b"file".to_vec(), - }, - ], - expected_output: Ok(into_anchored_system_path_vec(vec!["folder", "folder/file"])), - }, - TestCase { - name: "nested symlink", - input_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("folder/").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("folder/symlink").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("../").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("folder/symlink/folder-sibling") - .unwrap(), - body: b"folder-sibling".to_vec(), - }, - ], - expected_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("folder/").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("folder/symlink").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("../").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("folder/symlink/folder-sibling") - .unwrap(), - body: b"folder-sibling".to_vec(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("folder-sibling").unwrap(), - body: b"folder-sibling".to_vec(), - }, - ], - #[cfg(unix)] - expected_output: Ok(into_anchored_system_path_vec(vec![ - "folder", - "folder/symlink", - "folder/symlink/folder-sibling", - ])), - #[cfg(windows)] - expected_output: Err("IO error: The filename, directory name, or volume label \ - syntax is incorrect. (os error 123)" - .to_string()), - }, - TestCase { - name: "pathological symlinks", - input_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("two").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("two").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("three").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("three").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("real").unwrap(), - }, - TarFile::File { - body: b"real".to_vec(), - path: AnchoredSystemPathBuf::from_raw("real").unwrap(), - }, - ], - expected_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("two").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("two").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("three").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("three").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("real").unwrap(), - }, - TarFile::File { - path: AnchoredSystemPathBuf::from_raw("real").unwrap(), - body: b"real".to_vec(), - }, - ], - expected_output: Ok(into_anchored_system_path_vec(vec![ - "real", "one", "two", "three", - ])), - }, - TestCase { - name: "place file at dir location", - input_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("folder-not-file/").unwrap(), - }, - TarFile::File { - body: b"subfile".to_vec(), - path: AnchoredSystemPathBuf::from_raw("folder-not-file/subfile").unwrap(), - }, - TarFile::File { - body: b"this shouldn't work".to_vec(), - path: AnchoredSystemPathBuf::from_raw("folder-not-file").unwrap(), - }, - ], - - expected_files: vec![ - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("folder-not-file/").unwrap(), - }, - TarFile::File { - body: b"subfile".to_vec(), - path: AnchoredSystemPathBuf::from_raw("folder-not-file/subfile").unwrap(), - }, - ], - #[cfg(unix)] - expected_output: Err("IO error: Is a directory (os error 21)".to_string()), - #[cfg(windows)] - expected_output: Err("IO error: Access is denied. (os error 5)".to_string()), - }, - TestCase { - name: "symlink cycle", - input_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("two").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("two").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("three").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("three").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("one").unwrap(), - }, - ], - expected_files: vec![], - expected_output: Err("links in the cache are cyclic".to_string()), - }, - TestCase { - name: "symlink clobber", - input_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("two").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("three").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("real").unwrap(), - }, - TarFile::File { - body: b"real".to_vec(), - path: AnchoredSystemPathBuf::from_raw("real").unwrap(), - }, - ], - expected_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("one").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("real").unwrap(), - }, - TarFile::File { - body: b"real".to_vec(), - path: AnchoredSystemPathBuf::from_raw("real").unwrap(), - }, - ], - expected_output: Ok(into_anchored_system_path_vec(vec!["real", "one"])), - }, - TestCase { - name: "symlink traversal", - input_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("escape").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("../").unwrap(), - }, - TarFile::File { - body: b"file".to_vec(), - path: AnchoredSystemPathBuf::from_raw("escape/file").unwrap(), - }, - ], - expected_files: vec![TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("escape").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("../").unwrap(), - }], - expected_output: Err("tar attempts to write outside of directory: ../".to_string()), - }, - TestCase { - name: "Double indirection: file", - input_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("up").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("../").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("link").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("up").unwrap(), - }, - TarFile::File { - body: b"file".to_vec(), - path: AnchoredSystemPathBuf::from_raw("link/outside-file").unwrap(), - }, - ], - expected_files: vec![], - expected_output: Err("tar attempts to write outside of directory: ../".to_string()), - }, - TestCase { - name: "Double indirection: folder", - input_files: vec![ - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("up").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("../").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("link").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("up").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("link/level-one/level-two").unwrap(), - }, - ], - expected_files: vec![], - expected_output: Err("tar attempts to write outside of directory: ../".to_string()), - }, - TestCase { - name: "fifo (and others) unsupported", - input_files: vec![TarFile::Fifo { - path: AnchoredSystemPathBuf::from_raw("fifo").unwrap(), - }], - expected_files: vec![], - expected_output: Err("attempted to restore unsupported file type: Fifo".to_string()), - }, - TestCase { - name: "duplicate restores", - input_files: vec![ - TarFile::File { - body: b"target".to_vec(), - path: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("source").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), - }, - ], - expected_files: vec![ - TarFile::File { - body: b"target".to_vec(), - path: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/").unwrap(), - }, - TarFile::Directory { - path: AnchoredSystemPathBuf::from_raw("one/two/").unwrap(), - }, - TarFile::Symlink { - link_path: AnchoredSystemPathBuf::from_raw("source").unwrap(), - link_target: AnchoredSystemPathBuf::from_raw("target").unwrap(), - }, - ], - expected_output: Ok(into_anchored_system_path_vec(vec![ - "target", "source", "one", "one/two", - ])), - }, - ]; - - for is_compressed in [true, false] { - for test in &tests { - debug!("test: {}", test.name); - let input_dir = tempdir()?; - let archive_path = generate_tar(&input_dir, &test.input_files)?; - let output_dir = tempdir()?; - let output_dir_path = output_dir.path().to_string_lossy(); - let anchor = AbsoluteSystemPath::new(&output_dir_path)?; - - let archive_path = if is_compressed { - compress_tar(&archive_path)? - } else { - archive_path - }; - - let mut cache_reader = CacheReader::open(&archive_path)?; - - match (cache_reader.restore(anchor), &test.expected_output) { - (Ok(restored_files), Err(expected_error)) => { - panic!( - "expected error: {:?}, received {:?}", - expected_error, restored_files - ); - } - (Ok(restored_files), Ok(expected_files)) => { - assert_eq!(&restored_files, expected_files); - } - (Err(err), Err(expected_error)) => { - assert_eq!(&err.to_string(), expected_error); - continue; - } - (Err(err), Ok(_)) => { - panic!("unexpected error: {:?}", err); - } - }; - - let expected_files = &test.expected_files; - - for expected_file in expected_files { - assert_file_exists(anchor, expected_file)?; - } - } - } - - Ok(()) - } - - #[test_case(Path::new("source").try_into()?, Path::new("target"), "/Users/test/target", "C:\\Users\\test\\target" ; "hello world")] - #[test_case(Path::new("child/source").try_into()?, Path::new("../sibling/target"), "/Users/test/sibling/target", "C:\\Users\\test\\sibling\\target" ; "Unix path subdirectory traversal")] - #[test_case(Path::new("child/source").try_into()?, Path::new("..\\sibling\\target"), "/Users/test/child/..\\sibling\\target", "C:\\Users\\test\\sibling\\target" ; "Windows path subdirectory traversal")] - fn test_canonicalize_linkname( - processed_name: AnchoredSystemPathBuf, - linkname: &Path, - #[allow(unused_variables)] canonical_unix: &'static str, - #[allow(unused_variables)] canonical_windows: &'static str, - ) -> Result<()> { - #[cfg(unix)] - let anchor = AbsoluteSystemPath::new("/Users/test").unwrap(); - #[cfg(windows)] - let anchor = AbsoluteSystemPath::new("C:\\Users\\test").unwrap(); - - let received_path = canonicalize_linkname(anchor, &processed_name, linkname)?; - - #[cfg(unix)] - assert_eq!(received_path.to_string(), canonical_unix); - #[cfg(windows)] - assert_eq!(received_path.to_string(), canonical_windows); - - Ok(()) - } -} diff --git a/crates/turborepo-cache/src/cache_archive/restore_directory.rs b/crates/turborepo-cache/src/cache_archive/restore_directory.rs deleted file mode 100644 index e684de3a9e77e..0000000000000 --- a/crates/turborepo-cache/src/cache_archive/restore_directory.rs +++ /dev/null @@ -1,171 +0,0 @@ -use std::{backtrace::Backtrace, ffi::OsString, io}; - -use camino::Utf8Component; -use tar::Entry; -use tracing::debug; -use turbopath::{ - AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPath, AnchoredSystemPathBuf, -}; - -use crate::CacheError; - -pub fn restore_directory( - dir_cache: &mut CachedDirTree, - anchor: &AbsoluteSystemPath, - entry: &Entry, -) -> Result { - let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; - - dir_cache.safe_mkdir_all(anchor, &processed_name, entry.header().mode()?)?; - - Ok(processed_name) -} - -pub struct CachedDirTree { - anchor_at_depth: Vec, - prefix: Vec, -} - -impl CachedDirTree { - pub fn new(initial_anchor: AbsoluteSystemPathBuf) -> Self { - CachedDirTree { - anchor_at_depth: vec![initial_anchor], - prefix: vec![], - } - } - - // Given a path, checks the dir cache to determine where we actually need - // to start restoring, i.e. which directories we can skip over because - // we've already created them. - // Returns the anchor at the depth where we need to start restoring, and - // the index into the path components where we need to start restoring. - fn get_starting_point(&mut self, path: &AnchoredSystemPath) -> (AbsoluteSystemPathBuf, usize) { - let mut i = 0; - for (idx, (path_component, prefix_component)) in - path.components().zip(self.prefix.iter()).enumerate() - { - i = idx; - if path_component.as_os_str() != prefix_component.as_os_str() { - break; - } - } - let anchor = self.anchor_at_depth[i].clone(); - - self.anchor_at_depth.truncate(i + 1); - self.prefix.truncate(i); - - (anchor, i) - } - - fn update(&mut self, anchor: AbsoluteSystemPathBuf, new_component: OsString) { - self.anchor_at_depth.push(anchor); - self.prefix.push(new_component); - } - - // Windows doesn't have file modes, so mode is unused - #[allow(unused_variables)] - pub fn safe_mkdir_all( - &mut self, - anchor: &AbsoluteSystemPath, - processed_name: &AnchoredSystemPath, - mode: u32, - ) -> Result<(), CacheError> { - // Iterate through path segments by os.Separator, appending them onto - // current_path. Check to see if that path segment is a symlink - // with a target outside of anchor. - let (mut calculated_anchor, start_idx) = self.get_starting_point(processed_name); - for component in processed_name.components().skip(start_idx) { - calculated_anchor = check_path( - anchor, - &calculated_anchor, - AnchoredSystemPath::new(component.as_str())?, - )?; - - self.update( - calculated_anchor.clone(), - component.as_os_str().to_os_string(), - ); - } - - // If we have made it here we know that it is safe to call fs::create_dir_all - // on the join of anchor and processed_name. - // - // This could _still_ error, but we don't care. - let resolved_name = anchor.resolve(processed_name); - let directory_exists = resolved_name.try_exists(); - if matches!(directory_exists, Ok(false)) { - resolved_name.create_dir_all()?; - } - - #[cfg(unix)] - { - use std::{fs, os::unix::fs::PermissionsExt}; - - let metadata = resolved_name.symlink_metadata()?; - let mut permissions = metadata.permissions(); - permissions.set_mode(mode); - fs::set_permissions(&resolved_name, permissions)?; - } - - Ok(()) - } -} - -fn check_path( - original_anchor: &AbsoluteSystemPath, - accumulated_anchor: &AbsoluteSystemPath, - segment: &AnchoredSystemPath, -) -> Result { - // Check if the segment itself is sneakily an absolute path... - // (looking at you, Windows. CON, AUX...) - if segment - .components() - .any(|c| matches!(c, Utf8Component::Prefix(_) | Utf8Component::RootDir)) - { - return Err(CacheError::LinkOutsideOfDirectory( - segment.to_string(), - Backtrace::capture(), - )); - } - - let combined_path = accumulated_anchor.resolve(segment); - let Ok(file_info) = combined_path.symlink_metadata() else { - // Getting an error here means we failed to stat the path. - // Assume that means we're safe and continue. - return Ok(combined_path); - }; - - // If we don't have a symlink, it's safe - if !file_info.is_symlink() { - return Ok(combined_path); - } - - // Check to see if the symlink targets outside of the originalAnchor. - // We don't do eval symlinks because we could find ourself in a totally - // different place. - - // 1. Get the target. - let link_target = combined_path.read_link()?; - debug!( - "link source: {:?}, link target {:?}", - combined_path, link_target - ); - if link_target.is_absolute() { - let absolute_link_target = AbsoluteSystemPathBuf::new(link_target.clone())?; - if path_clean::clean(&absolute_link_target).starts_with(original_anchor) { - return Ok(absolute_link_target); - } - } else { - let relative_link_target = AnchoredSystemPath::new(link_target.as_str())?; - // We clean here to resolve the `..` and `.` segments. - let computed_target = path_clean::clean(accumulated_anchor.resolve(relative_link_target)); - if computed_target.starts_with(original_anchor) { - return check_path(original_anchor, accumulated_anchor, relative_link_target); - } - } - - Err(CacheError::LinkOutsideOfDirectory( - link_target.to_string(), - Backtrace::capture(), - )) -} diff --git a/crates/turborepo-cache/src/cache_archive/restore_regular.rs b/crates/turborepo-cache/src/cache_archive/restore_regular.rs deleted file mode 100644 index 3eaca0614aed2..0000000000000 --- a/crates/turborepo-cache/src/cache_archive/restore_regular.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::{fs::OpenOptions, io, io::Read, path::Path}; - -use tar::Entry; -use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, AnchoredSystemPathBuf}; - -use crate::{cache_archive::restore_directory::CachedDirTree, CacheError}; - -pub fn restore_regular( - dir_cache: &mut CachedDirTree, - anchor: &AbsoluteSystemPath, - entry: &mut Entry, -) -> Result { - // Assuming this was a `turbo`-created input, we currently have an - // RelativeUnixPath. Assuming this is malicious input we don't really care - // if we do the wrong thing. - // - // Note that we don't use `header.path()` as some archive formats have support - // for longer path names described in separate entries instead of solely in the - // header - let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; - - // We need to traverse `processedName` from base to root split at - // `os.Separator` to make sure we don't end up following a symlink - // outside of the restore path. - dir_cache.safe_mkdir_file(anchor, &processed_name)?; - - let resolved_path = anchor.resolve(&processed_name); - let mut open_options = OpenOptions::new(); - open_options.write(true).truncate(true).create(true); - - #[cfg(unix)] - { - use std::os::unix::fs::OpenOptionsExt; - let header = entry.header(); - open_options.mode(header.mode()?); - } - - let mut file = open_options.open(resolved_path.as_path())?; - io::copy(entry, &mut file)?; - - Ok(processed_name) -} - -impl CachedDirTree { - pub fn safe_mkdir_file( - &mut self, - anchor: &AbsoluteSystemPath, - processed_name: &AnchoredSystemPath, - ) -> Result<(), CacheError> { - let parent = processed_name.as_path().parent(); - // Handles ./foo and foo - let is_root_file = parent == Some(Path::new(".")) || parent == Some(Path::new("")); - if !is_root_file { - let dir = processed_name.parent().unwrap(); - self.safe_mkdir_all(anchor, dir, 0o755)?; - } - - Ok(()) - } -} diff --git a/crates/turborepo-cache/src/cache_archive/restore_symlink.rs b/crates/turborepo-cache/src/cache_archive/restore_symlink.rs deleted file mode 100644 index de69e145d5736..0000000000000 --- a/crates/turborepo-cache/src/cache_archive/restore_symlink.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::{backtrace::Backtrace, io::Read}; - -use camino::Utf8Path; -use turbopath::{ - AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPath, AnchoredSystemPathBuf, - PathError, UnknownPathType, -}; - -use crate::{cache_archive::restore_directory::CachedDirTree, CacheError}; - -pub fn restore_symlink( - dir_cache: &mut CachedDirTree, - anchor: &AbsoluteSystemPath, - entry: &tar::Entry, -) -> Result { - let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; - - let linkname = entry - .link_name()? - .ok_or_else(|| CacheError::MalformedTar(Backtrace::capture()))?; - - let processed_linkname = canonicalize_linkname(anchor, &processed_name, &linkname)?; - - if processed_linkname.symlink_metadata().is_err() { - return Err(CacheError::LinkTargetDoesNotExist( - processed_linkname.to_string(), - Backtrace::capture(), - )); - } - - actually_restore_symlink(dir_cache, anchor, &processed_name, entry)?; - - Ok(processed_name) -} - -pub fn restore_symlink_allow_missing_target( - dir_cache: &mut CachedDirTree, - anchor: &AbsoluteSystemPath, - entry: &tar::Entry, -) -> Result { - let processed_name = AnchoredSystemPathBuf::from_system_path(&entry.path()?)?; - - actually_restore_symlink(dir_cache, anchor, &processed_name, entry)?; - - Ok(processed_name) -} - -fn actually_restore_symlink<'a>( - dir_cache: &mut CachedDirTree, - anchor: &AbsoluteSystemPath, - processed_name: &'a AnchoredSystemPath, - entry: &tar::Entry, -) -> Result<&'a AnchoredSystemPath, CacheError> { - dir_cache.safe_mkdir_file(anchor, processed_name)?; - - let symlink_from = anchor.resolve(processed_name); - - _ = symlink_from.remove(); - - let link_name = entry.link_name()?.expect("have linkname"); - let symlink_to = link_name.to_str().ok_or_else(|| { - CacheError::PathError( - PathError::InvalidUnicode(link_name.to_string_lossy().to_string()), - Backtrace::capture(), - ) - })?; - - if Utf8Path::new(symlink_to).is_dir() { - symlink_from.symlink_to_dir(symlink_to)?; - } else { - symlink_from.symlink_to_file(symlink_to)?; - } - - #[cfg(target_os = "macos")] - { - use std::os::unix::fs::PermissionsExt; - let metadata = symlink_from.symlink_metadata()?; - let mut permissions = metadata.permissions(); - if let Ok(mode) = entry.header().mode() { - permissions.set_mode(mode); - } - } - - Ok(processed_name) -} - -// canonicalize_linkname determines (lexically) what the resolved path on the -// system will be when linkname is restored verbatim. -pub fn canonicalize_linkname( - anchor: &AbsoluteSystemPath, - processed_name: &AnchoredSystemPathBuf, - linkname: &std::path::Path, -) -> Result { - let linkname = linkname.try_into().map_err(|_| { - CacheError::PathError( - PathError::InvalidUnicode(linkname.to_string_lossy().to_string()), - Backtrace::capture(), - ) - })?; - // We don't know _anything_ about linkname. It could be any of: - // - // - Absolute Unix Path - // - Absolute Windows Path - // - Relative Unix Path - // - Relative Windows Path - // - // We also can't _truly_ distinguish if the path is Unix or Windows. - // Take for example: `/Users/turbobot/weird-filenames/\foo\/lol` - // It is a valid file on Unix, but if we do slash conversion it breaks. - // Or `i\am\a\normal\unix\file\but\super\nested\on\windows`. - // - // We also can't safely assume that paths in link targets on one platform - // should be treated as targets for that platform. The author may be - // generating an artifact that should work on Windows on a Unix device. - // - // Given all of that, our best option is to restore link targets _verbatim_. - // No modification, no slash conversion. - // - // In order to DAG sort them, however, we do need to canonicalize them. - // We canonicalize them as if we're restoring them verbatim. - // - match turbopath::categorize(linkname) { - // 1. Check to see if the link target is absolute _on the current platform_. - // If it is an absolute path it's canonical by rule. - UnknownPathType::Absolute(abs) => Ok(abs), - // Remaining options: - // - Absolute (other platform) Path - // - Relative Unix Path - // - Relative Windows Path - // - // At this point we simply assume that it's a relative path—no matter - // which separators appear in it and where they appear, We can't do - // anything else because the OS will also treat it like that when it is - // a link target. - UnknownPathType::Anchored(cleaned_linkname) => { - let source = anchor.resolve(processed_name); - let canonicalized = source - .parent() - .expect("expected parent for file") - .resolve(&cleaned_linkname) - .clean()?; - - Ok(canonicalized) - } - } -} diff --git a/crates/turborepo-cache/src/fs.rs b/crates/turborepo-cache/src/fs.rs deleted file mode 100644 index 89af74907790d..0000000000000 --- a/crates/turborepo-cache/src/fs.rs +++ /dev/null @@ -1,273 +0,0 @@ -use std::{backtrace::Backtrace, fs::OpenOptions}; - -use camino::Utf8Path; -use serde::{Deserialize, Serialize}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; -use turborepo_analytics::AnalyticsSender; -use turborepo_api_client::{analytics, analytics::AnalyticsEvent}; - -use crate::{ - cache_archive::{CacheReader, CacheWriter}, - CacheError, CacheHitMetadata, CacheSource, -}; - -pub struct FSCache { - cache_directory: AbsoluteSystemPathBuf, - analytics_recorder: Option, -} - -#[derive(Debug, Deserialize, Serialize)] -struct CacheMetadata { - hash: String, - duration: u64, -} - -impl CacheMetadata { - fn read(path: &AbsoluteSystemPath) -> Result { - serde_json::from_str(&path.read_to_string()?) - .map_err(|e| CacheError::InvalidMetadata(e, Backtrace::capture())) - } -} - -impl FSCache { - fn resolve_cache_dir( - repo_root: &AbsoluteSystemPath, - cache_dir: &Utf8Path, - ) -> AbsoluteSystemPathBuf { - AbsoluteSystemPathBuf::from_unknown(repo_root, cache_dir) - } - - #[tracing::instrument(skip_all)] - pub fn new( - cache_dir: &Utf8Path, - repo_root: &AbsoluteSystemPath, - analytics_recorder: Option, - ) -> Result { - let cache_directory = Self::resolve_cache_dir(repo_root, cache_dir); - cache_directory.create_dir_all()?; - - Ok(FSCache { - cache_directory, - analytics_recorder, - }) - } - - fn log_fetch(&self, event: analytics::CacheEvent, hash: &str, duration: u64) { - // If analytics fails to record, it's not worth failing the cache - if let Some(analytics_recorder) = &self.analytics_recorder { - let analytics_event = AnalyticsEvent { - session_id: None, - source: analytics::CacheSource::Local, - event, - hash: hash.to_string(), - duration, - }; - - let _ = analytics_recorder.send(analytics_event); - } - } - - #[tracing::instrument(skip_all)] - pub fn fetch( - &self, - anchor: &AbsoluteSystemPath, - hash: &str, - ) -> Result)>, CacheError> { - let uncompressed_cache_path = self - .cache_directory - .join_component(&format!("{}.tar", hash)); - let compressed_cache_path = self - .cache_directory - .join_component(&format!("{}.tar.zst", hash)); - - let cache_path = if uncompressed_cache_path.exists() { - uncompressed_cache_path - } else if compressed_cache_path.exists() { - compressed_cache_path - } else { - self.log_fetch(analytics::CacheEvent::Miss, hash, 0); - return Ok(None); - }; - - let mut cache_reader = CacheReader::open(&cache_path)?; - - let restored_files = cache_reader.restore(anchor)?; - - let meta = CacheMetadata::read( - &self - .cache_directory - .join_component(&format!("{}-meta.json", hash)), - )?; - - self.log_fetch(analytics::CacheEvent::Hit, hash, meta.duration); - - Ok(Some(( - CacheHitMetadata { - time_saved: meta.duration, - source: CacheSource::Local, - }, - restored_files, - ))) - } - - #[tracing::instrument(skip_all)] - pub(crate) fn exists(&self, hash: &str) -> Result, CacheError> { - let uncompressed_cache_path = self - .cache_directory - .join_component(&format!("{}.tar", hash)); - let compressed_cache_path = self - .cache_directory - .join_component(&format!("{}.tar.zst", hash)); - - if !uncompressed_cache_path.exists() && !compressed_cache_path.exists() { - return Ok(None); - } - - let duration = CacheMetadata::read( - &self - .cache_directory - .join_component(&format!("{}-meta.json", hash)), - ) - .map(|meta| meta.duration) - .unwrap_or(0); - - Ok(Some(CacheHitMetadata { - time_saved: duration, - source: CacheSource::Local, - })) - } - - #[tracing::instrument(skip_all)] - pub fn put( - &self, - anchor: &AbsoluteSystemPath, - hash: &str, - files: &[AnchoredSystemPathBuf], - duration: u64, - ) -> Result<(), CacheError> { - let cache_path = self - .cache_directory - .join_component(&format!("{}.tar.zst", hash)); - - let mut cache_item = CacheWriter::create(&cache_path)?; - - for file in files { - cache_item.add_file(anchor, file)?; - } - - let metadata_path = self - .cache_directory - .join_component(&format!("{}-meta.json", hash)); - - let meta = CacheMetadata { - hash: hash.to_string(), - duration, - }; - - let mut metadata_options = OpenOptions::new(); - metadata_options.create(true).write(true).truncate(true); - - let metadata_file = metadata_path.open_with_options(metadata_options)?; - - serde_json::to_writer(metadata_file, &meta) - .map_err(|e| CacheError::InvalidMetadata(e, Backtrace::capture()))?; - - Ok(()) - } -} - -#[cfg(test)] -mod test { - use std::time::Duration; - - use anyhow::Result; - use futures::future::try_join_all; - use tempfile::tempdir; - use turbopath::AnchoredSystemPath; - use turborepo_analytics::start_analytics; - use turborepo_api_client::{APIAuth, APIClient}; - use turborepo_vercel_api_mock::start_test_server; - - use super::*; - use crate::test_cases::{get_test_cases, validate_analytics, TestCase}; - - #[tokio::test] - async fn test_fs_cache() -> Result<()> { - let port = port_scanner::request_open_port().unwrap(); - tokio::spawn(start_test_server(port)); - - let test_cases = get_test_cases(); - - try_join_all( - test_cases - .iter() - .map(|test_case| round_trip_test(test_case, port)), - ) - .await?; - - validate_analytics(&test_cases, analytics::CacheSource::Local, port).await?; - Ok(()) - } - - async fn round_trip_test(test_case: &TestCase, port: u16) -> Result<()> { - let repo_root = tempdir()?; - let repo_root_path = AbsoluteSystemPath::from_std_path(repo_root.path())?; - test_case.initialize(repo_root_path)?; - - let api_client = APIClient::new( - format!("http://localhost:{}", port), - Some(Duration::from_secs(200)), - None, - "2.0.0", - true, - )?; - let api_auth = APIAuth { - team_id: Some("my-team".to_string()), - token: "my-token".to_string(), - team_slug: None, - }; - let (analytics_sender, analytics_handle) = - start_analytics(api_auth.clone(), api_client.clone()); - - let cache = FSCache::new( - Utf8Path::new(""), - repo_root_path, - Some(analytics_sender.clone()), - )?; - - let expected_miss = cache.fetch(repo_root_path, test_case.hash)?; - assert!(expected_miss.is_none()); - - let files: Vec<_> = test_case - .files - .iter() - .map(|f| f.path().to_owned()) - .collect(); - cache.put(repo_root_path, test_case.hash, &files, test_case.duration)?; - - let (status, files) = cache.fetch(repo_root_path, test_case.hash)?.unwrap(); - - assert_eq!( - status, - CacheHitMetadata { - time_saved: test_case.duration, - source: CacheSource::Local - } - ); - - assert_eq!(files.len(), test_case.files.len()); - for (expected, actual) in test_case.files.iter().zip(files.iter()) { - let actual: &AnchoredSystemPath = actual; - assert_eq!(expected.path(), actual); - let actual_file = repo_root_path.resolve(actual); - if let Some(contents) = expected.contents() { - assert_eq!(contents, actual_file.read_to_string()?); - } else { - assert!(actual_file.exists()); - } - } - - analytics_handle.close_with_timeout().await; - Ok(()) - } -} diff --git a/crates/turborepo-cache/src/multiplexer.rs b/crates/turborepo-cache/src/multiplexer.rs deleted file mode 100644 index 44bc51afaeaf8..0000000000000 --- a/crates/turborepo-cache/src/multiplexer.rs +++ /dev/null @@ -1,208 +0,0 @@ -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, Mutex, -}; - -use tracing::{debug, warn}; -use turbopath::{AbsoluteSystemPath, AnchoredSystemPathBuf}; -use turborepo_analytics::AnalyticsSender; -use turborepo_api_client::{APIAuth, APIClient}; - -use crate::{ - fs::FSCache, - http::{HTTPCache, UploadMap}, - CacheConfig, CacheError, CacheHitMetadata, CacheOpts, -}; - -pub struct CacheMultiplexer { - // We use an `AtomicBool` instead of removing the cache because that would require - // wrapping the cache in a `Mutex` which would cause a lot of contention. - // This does create a mild race condition where we might use the cache - // even though another thread might be removing it, but that's fine. - should_use_http_cache: AtomicBool, - // Just for keeping track of whether we've already printed a warning about the remote cache - // being read-only - should_print_skipping_remote_put: AtomicBool, - cache_config: CacheConfig, - fs: Option, - http: Option, -} - -impl CacheMultiplexer { - #[tracing::instrument(skip_all)] - pub fn new( - opts: &CacheOpts, - repo_root: &AbsoluteSystemPath, - api_client: APIClient, - api_auth: Option, - analytics_recorder: Option, - ) -> Result { - let use_fs_cache = opts.cache.local.should_use(); - let use_http_cache = opts.cache.remote.should_use(); - - // Since the above two flags are not mutually exclusive it is possible to - // configure yourself out of having a cache. We should tell you about it - // but we shouldn't fail your build for that reason. - if !use_fs_cache && !use_http_cache { - warn!("no caches are enabled"); - } - - let fs_cache = use_fs_cache - .then(|| FSCache::new(&opts.cache_dir, repo_root, analytics_recorder.clone())) - .transpose()?; - - let http_cache = use_http_cache - .then_some(api_auth) - .flatten() - .map(|api_auth| { - HTTPCache::new( - api_client, - opts, - repo_root.to_owned(), - api_auth, - analytics_recorder.clone(), - ) - }); - - Ok(CacheMultiplexer { - should_print_skipping_remote_put: AtomicBool::new(true), - should_use_http_cache: AtomicBool::new(http_cache.is_some()), - cache_config: opts.cache, - fs: fs_cache, - http: http_cache, - }) - } - - // This is technically a TOCTOU bug, but at worst it'll cause - // a few extra cache requests. - fn get_http_cache(&self) -> Option<&HTTPCache> { - if self.should_use_http_cache.load(Ordering::Relaxed) { - self.http.as_ref() - } else { - None - } - } - - pub fn requests(&self) -> Option>> { - self.http.as_ref().map(|http| http.requests()) - } - - #[tracing::instrument(skip_all)] - pub async fn put( - &self, - anchor: &AbsoluteSystemPath, - key: &str, - files: &[AnchoredSystemPathBuf], - duration: u64, - ) -> Result<(), CacheError> { - if self.cache_config.local.write { - self.fs - .as_ref() - .map(|fs| fs.put(anchor, key, files, duration)) - .transpose()?; - } - - let http_result = match self.get_http_cache() { - Some(http) => { - if self.cache_config.remote.write { - let http_result = http.put(anchor, key, files, duration).await; - - Some(http_result) - } else { - if self - .should_print_skipping_remote_put - .load(Ordering::Relaxed) - { - // Warn once per build, not per task - warn!("Remote cache is read-only, skipping upload"); - self.should_print_skipping_remote_put - .store(false, Ordering::Relaxed); - } - // Cache is functional but running in read-only mode, so we don't want to try to - // write to it - None - } - } - _ => None, - }; - - match http_result { - Some(Err(CacheError::ApiClientError( - box turborepo_api_client::Error::CacheDisabled { .. }, - .., - ))) => { - warn!("failed to put to http cache: cache disabled"); - self.should_use_http_cache.store(false, Ordering::Relaxed); - Ok(()) - } - Some(Err(e)) => Err(e), - None | Some(Ok(())) => Ok(()), - } - } - - #[tracing::instrument(skip_all)] - pub async fn fetch( - &self, - anchor: &AbsoluteSystemPath, - key: &str, - ) -> Result)>, CacheError> { - if self.cache_config.local.read { - if let Some(fs) = &self.fs { - if let response @ Ok(Some(_)) = fs.fetch(anchor, key) { - return response; - } - } - } - - if self.cache_config.remote.read { - if let Some(http) = self.get_http_cache() { - if let Ok(Some((CacheHitMetadata { source, time_saved }, files))) = - http.fetch(key).await - { - // Store this into fs cache. We can ignore errors here because we know - // we have previously successfully stored in HTTP cache, and so the overall - // result is a success at fetching. Storing in lower-priority caches is an - // optimization. - if self.cache_config.local.write { - if let Some(fs) = &self.fs { - let _ = fs.put(anchor, key, &files, time_saved); - } - } - - return Ok(Some((CacheHitMetadata { source, time_saved }, files))); - } - } - } - - Ok(None) - } - - #[tracing::instrument(skip_all)] - pub async fn exists(&self, key: &str) -> Result, CacheError> { - if self.cache_config.local.read { - if let Some(fs) = &self.fs { - match fs.exists(key) { - cache_hit @ Ok(Some(_)) => { - return cache_hit; - } - Ok(None) => {} - Err(err) => debug!("failed to check fs cache: {:?}", err), - } - } - } - - if self.cache_config.remote.read { - if let Some(http) = self.get_http_cache() { - match http.exists(key).await { - cache_hit @ Ok(Some(_)) => { - return cache_hit; - } - Ok(None) => {} - Err(err) => debug!("failed to check http cache: {:?}", err), - } - } - } - - Ok(None) - } -} diff --git a/crates/turborepo-cache/src/signature_authentication.rs b/crates/turborepo-cache/src/signature_authentication.rs deleted file mode 100644 index d3e45b2105b13..0000000000000 --- a/crates/turborepo-cache/src/signature_authentication.rs +++ /dev/null @@ -1,276 +0,0 @@ -use std::env; - -use base64::{prelude::BASE64_STANDARD, Engine}; -use hmac::{Hmac, Mac}; -use os_str_bytes::OsStringBytes; -use sha2::Sha256; -use thiserror::Error; - -type HmacSha256 = Hmac; - -#[derive(Debug, Error)] -pub enum SignatureError { - #[error( - "signature secret key not found. You must specify a secret key in the \ - TURBO_REMOTE_CACHE_SIGNATURE_KEY environment variable" - )] - NoSignatureSecretKey, - #[error("serialization error: {0}")] - SerializationError(#[from] serde_json::Error), - #[error("base64 encoding error: {0}")] - Base64EncodingError(#[from] base64::DecodeError), - #[error(transparent)] - Hmac(#[from] hmac::digest::InvalidLength), -} - -#[derive(Debug)] -pub struct ArtifactSignatureAuthenticator { - pub(crate) team_id: Vec, - // An override for testing purposes (to avoid env var race conditions) - pub(crate) secret_key_override: Option>, -} - -impl ArtifactSignatureAuthenticator { - pub fn new(team_id: Vec, secret_key_override: Option>) -> Self { - Self { - team_id, - secret_key_override, - } - } - - // Gets secret key from either secret key override or environment variable. - // HMAC_SHA256 has no key length limit, although it's generally recommended - // to keep key length under 64 bytes since anything longer is hashed using - // SHA-256. - fn secret_key(&self) -> Result, SignatureError> { - if let Some(secret_key) = &self.secret_key_override { - return Ok(secret_key.to_vec()); - } - - Ok(env::var_os("TURBO_REMOTE_CACHE_SIGNATURE_KEY") - .ok_or(SignatureError::NoSignatureSecretKey)? - .into_raw_vec()) - } - - fn construct_metadata(&self, hash: &[u8]) -> Result, SignatureError> { - let mut metadata = hash.to_vec(); - metadata.extend_from_slice(&self.team_id); - - Ok(metadata) - } - - fn get_tag_generator(&self, hash: &[u8]) -> Result { - let mut mac = HmacSha256::new_from_slice(&self.secret_key()?)?; - let metadata = self.construct_metadata(hash)?; - - mac.update(&metadata); - - Ok(mac) - } - - #[tracing::instrument(skip_all)] - pub fn generate_tag_bytes( - &self, - hash: &[u8], - artifact_body: &[u8], - ) -> Result, SignatureError> { - let mut mac = self.get_tag_generator(hash)?; - - mac.update(artifact_body); - let hmac_output = mac.finalize(); - Ok(hmac_output.into_bytes().to_vec()) - } - - #[tracing::instrument(skip_all)] - pub fn generate_tag( - &self, - hash: &[u8], - artifact_body: &[u8], - ) -> Result { - let mut hmac_ctx = self.get_tag_generator(hash)?; - - hmac_ctx.update(artifact_body); - let hmac_output = hmac_ctx.finalize(); - Ok(BASE64_STANDARD.encode(hmac_output.into_bytes())) - } - - #[tracing::instrument(skip_all)] - pub fn validate( - &self, - hash: &[u8], - artifact_body: &[u8], - expected_tag: &str, - ) -> Result { - let mut mac = HmacSha256::new_from_slice(&self.secret_key()?)?; - let message = self.construct_metadata(hash)?; - mac.update(&message); - mac.update(artifact_body); - - let expected_bytes = BASE64_STANDARD.decode(expected_tag)?; - Ok(mac.verify_slice(&expected_bytes).is_ok()) - } -} - -#[cfg(test)] -mod tests { - use anyhow::Result; - - use super::*; - - impl ArtifactSignatureAuthenticator { - pub fn validate_tag( - &self, - hash: &[u8], - artifact_body: &[u8], - expected_tag: &[u8], - ) -> Result { - let mut mac = HmacSha256::new_from_slice(&self.secret_key()?)?; - let message = self.construct_metadata(hash)?; - mac.update(&message); - mac.update(artifact_body); - - Ok(mac.verify_slice(expected_tag).is_ok()) - } - } - - struct TestCase { - secret_key: &'static str, - team_id: &'static [u8], - artifact_hash: &'static [u8], - artifact_body: &'static [u8], - } - - fn get_test_cases() -> Vec { - vec![ - TestCase { - secret_key: "x3vq8mFz0J", - team_id: b"tH7sL1Rn9K", - artifact_hash: b"d5b7e4688f", - artifact_body: &[5, 72, 219, 39, 156], - }, - TestCase { - secret_key: "r8cP5sTn0Y", - team_id: b"sL2vM9Qj1D", - artifact_hash: b"a1c8f3e3d7", - artifact_body: &[128, 234, 49, 67, 96], - }, - TestCase { - secret_key: "g4kS2nDv6L", - team_id: b"mB8pF9hJ0X", - artifact_hash: b"f2e6d4a2c1", - artifact_body: &[217, 88, 71, 16, 53], - }, - TestCase { - secret_key: "j0fT3qPz6N", - team_id: b"cH1rK7vD5B", - artifact_hash: b"e8a5c7f0b2", - artifact_body: &[202, 12, 104, 90, 182], - }, - TestCase { - secret_key: "w1xM5bVz2Q", - team_id: b"sL9cJ0nK7F", - artifact_hash: b"c4e6f9a1d8", - artifact_body: &[67, 93, 241, 78, 192], - }, - TestCase { - secret_key: "f9gD2tNc8K", - team_id: b"pJ1xL6rF0V", - artifact_hash: b"b3a9c5e8f7", - artifact_body: &[23, 160, 36, 208, 97], - }, - TestCase { - secret_key: "k5nB1tLc9Z", - team_id: b"wF0xV8jP7G", - artifact_hash: b"e7a9c1b8f6", - artifact_body: &[237, 148, 107, 51, 241], - }, - TestCase { - secret_key: "d8mR2vZn5X", - team_id: b"kP6cV1jN7T", - artifact_hash: b"f2c8e7b6a1", - artifact_body: &[128, 36, 180, 67, 230], - }, - TestCase { - secret_key: "p4kS5nHv3L", - team_id: b"tR1cF2bD0M", - artifact_hash: b"d5b8e4f3c9", - artifact_body: &[47, 161, 218, 119, 223], - }, - TestCase { - secret_key: "j5nG1bDv6X", - team_id: b"tH8rK0pJ3L", - artifact_hash: b"e3c5a9b2f1", - artifact_body: &[188, 245, 109, 12, 167], - }, - TestCase { - secret_key: "f2cB1tLm9X", - team_id: b"rG7sK0vD4N", - artifact_hash: b"b5a9c8e3f6", - artifact_body: &[205, 154, 83, 60, 27], - }, - TestCase { - secret_key: "t1sN2mFj8Z", - team_id: b"pK3cH7rD6B", - artifact_hash: b"d4e9c1f7b6", - artifact_body: &[226, 245, 85, 79, 136], - }, - TestCase { - secret_key: "h5jM3pZv8X", - team_id: b"dR1bF2cK6L", - artifact_hash: b"f2e6d5b1c8", - artifact_body: &[70, 184, 71, 150, 238], - }, - TestCase { - secret_key: "n0cT2bDk9J", - team_id: b"pJ3sF6rM8N", - artifact_hash: b"e4a9d7c1f8", - artifact_body: &[240, 130, 13, 167, 75], - }, - TestCase { - secret_key: "b2dV6kPf9X", - team_id: b"tN3cH7mK8J", - artifact_hash: b"c9e3d7b6f8", - artifact_body: &[58, 42, 80, 138, 189], - }, - ] - } - - #[test] - fn test_signatures() -> Result<()> { - for test_case in get_test_cases() { - test_signature(test_case)?; - } - Ok(()) - } - - fn test_signature(test_case: TestCase) -> Result<()> { - env::set_var("TURBO_REMOTE_CACHE_SIGNATURE_KEY", test_case.secret_key); - let signature = ArtifactSignatureAuthenticator { - team_id: test_case.team_id.to_vec(), - secret_key_override: None, - }; - - let hash = test_case.artifact_hash; - let artifact_body = &test_case.artifact_body; - let tag = signature.generate_tag_bytes(hash, artifact_body)?; - - assert!(signature.validate_tag(hash, artifact_body, tag.as_ref())?); - - // Generate some bad tag that is not correct - let bad_tag = BASE64_STANDARD.encode(b"bad tag"); - assert!(!signature.validate(hash, artifact_body, &bad_tag)?); - - // Change the key - env::set_var("TURBO_REMOTE_CACHE_SIGNATURE_KEY", "some other key"); - - // Confirm that the tag is no longer valid - assert!(!signature.validate_tag(hash, artifact_body, tag.as_ref())?); - - // Generate new tag - let tag = signature.generate_tag(hash, artifact_body)?; - - // Confirm it's valid - assert!(signature.validate(hash, artifact_body, &tag)?); - Ok(()) - } -} diff --git a/crates/turborepo-cache/src/test_cases.rs b/crates/turborepo-cache/src/test_cases.rs deleted file mode 100644 index 2fff6954b1cf1..0000000000000 --- a/crates/turborepo-cache/src/test_cases.rs +++ /dev/null @@ -1,147 +0,0 @@ -use anyhow::Result; -use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, AnchoredSystemPathBuf}; -use turborepo_analytics::AnalyticsEvent; -use turborepo_api_client::analytics; - -pub(crate) struct TestFile { - path: AnchoredSystemPathBuf, - contents: Option<&'static str>, -} - -impl TestFile { - pub fn file(path: AnchoredSystemPathBuf, contents: &'static str) -> Self { - Self { - path, - contents: Some(contents), - } - } - - pub fn directory(path: AnchoredSystemPathBuf) -> Self { - Self { - path, - contents: None, - } - } - - pub fn create(&self, repo_root: &AbsoluteSystemPath) -> Result<()> { - let file_path = repo_root.resolve(&self.path); - match self.contents { - Some(contents) => { - std::fs::create_dir_all(file_path.parent().unwrap())?; - std::fs::write(file_path, contents)?; - } - None => { - std::fs::create_dir(&file_path)?; - } - } - - Ok(()) - } - - pub fn path(&self) -> &AnchoredSystemPath { - &self.path - } - - pub fn contents(&self) -> Option<&str> { - self.contents - } -} - -pub(crate) struct TestCase { - pub files: Vec, - pub duration: u64, - pub hash: &'static str, -} - -impl TestCase { - pub fn initialize(&self, repo_root: &AbsoluteSystemPath) -> Result<()> { - for file in &self.files { - file.create(repo_root)?; - } - - Ok(()) - } -} - -pub(crate) async fn validate_analytics( - test_cases: &[TestCase], - source: analytics::CacheSource, - port: u16, -) -> Result<()> { - let response = reqwest::get(format!("http://localhost:{}/v8/artifacts/events", port)).await?; - assert_eq!(response.status(), 200); - let analytics_events: Vec = response.json().await?; - - assert_eq!(analytics_events.len(), test_cases.len() * 2); - - println!("{:#?}", analytics_events); - for test_case in test_cases { - println!("finding {}", test_case.hash); - // We should have a hit and a miss event for both test cases - analytics_events - .iter() - .find(|event| { - event.hash == test_case.hash - && matches!(event.event, analytics::CacheEvent::Miss) - && event.source == source - }) - .unwrap(); - - analytics_events - .iter() - .find(|event| { - event.hash == test_case.hash - && matches!(event.event, analytics::CacheEvent::Hit) - && event.source == source - }) - .unwrap(); - } - - Ok(()) -} - -pub(crate) fn get_test_cases() -> Vec { - vec![ - TestCase { - files: vec![TestFile::file( - AnchoredSystemPathBuf::from_raw("package.json").unwrap(), - "hello world", - )], - duration: 58, - hash: "Faces Places", - }, - TestCase { - files: vec![ - TestFile::file( - AnchoredSystemPathBuf::from_raw("package.json").unwrap(), - "Days of Heaven", - ), - TestFile::file( - AnchoredSystemPathBuf::from_raw("package-lock.json").unwrap(), - "Badlands", - ), - ], - duration: 1284, - hash: "Cleo from 5 to 7", - }, - TestCase { - files: vec![ - TestFile::file( - AnchoredSystemPathBuf::from_raw("package.json").unwrap(), - "Days of Heaven", - ), - TestFile::file( - AnchoredSystemPathBuf::from_raw("package-lock.json").unwrap(), - "Badlands", - ), - TestFile::directory(AnchoredSystemPathBuf::from_raw("src").unwrap()), - TestFile::file( - AnchoredSystemPathBuf::from_raw("src/main.js").unwrap(), - "Tree of Life", - ), - ], - duration: 12845, - hash: "The Gleaners and I", - }, - ] -} diff --git a/crates/turborepo-cache/src/upload_progress.rs b/crates/turborepo-cache/src/upload_progress.rs deleted file mode 100644 index 8d8979698ad37..0000000000000 --- a/crates/turborepo-cache/src/upload_progress.rs +++ /dev/null @@ -1,160 +0,0 @@ -use std::{ - pin::Pin, - sync::{Arc, Mutex, Weak}, - task::{Context, Poll}, - time::Instant, -}; - -use futures::Stream; -use pin_project::pin_project; - -type State = Mutex<(usize, [(usize, usize); BUCKETS])>; - -/// Consists of a total file upload time and a ring buffer of bytes sent per -/// second over some time interval. -#[pin_project] -pub struct UploadProgress { - /// A pair of bucket generation and bytes uploaded in that bucket. - /// - /// We need to store the generation to ensure that we don't accidentally - /// read from an expired bucket if there is a gap in writing. - state: Arc>, - start: Instant, - #[pin] - inner: S, -} - -impl UploadProgress { - /// Create a new `UploadProgress` with the given stream and interval. - pub fn new(inner: S, size: Option) -> (Self, UploadProgressQuery) { - let state = Arc::new(Mutex::new((0, [(0, 0); BUCKETS]))); - let now = Instant::now(); - let query = UploadProgressQuery::new(now, Arc::downgrade(&state), size); - - ( - Self { - state, - start: now, - inner, - }, - query, - ) - } -} - -impl Stream - for UploadProgress -where - S::Item: ProgressLen, -{ - type Item = S::Item; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - let this = self.as_mut().project(); - match this.inner.poll_next(cx) { - Poll::Ready(Some(item)) => { - // same as `curr_gen_index` but we can't borrow `self` twice - let (curr_gen, index) = { - // usize fits 570 million years of milliseconds since start on 64 bit - let gen = (this.start.elapsed().as_millis() as usize) / INTERVAL; - (gen, gen % BUCKETS) - }; - let mut state = this.state.lock().unwrap(); - let (gen, value) = &mut state.1[index]; - if *gen != curr_gen { - *gen = curr_gen; - *value = item.len(); - } else { - *value += item.len(); - } - - state.0 += item.len(); - - Poll::Ready(Some(item)) - } - Poll::Ready(None) => Poll::Ready(None), - Poll::Pending => Poll::Pending, - } - } - - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} - -trait ProgressLen { - fn len(&self) -> usize; -} - -impl ProgressLen for bytes::Bytes { - fn len(&self) -> usize { - self.len() - } -} - -impl ProgressLen for Result { - fn len(&self) -> usize { - match self { - Ok(t) => t.len(), - Err(_) => 0, - } - } -} - -#[derive(Clone)] -pub struct UploadProgressQuery { - start: Instant, - state: Weak>, - size: Option, -} - -impl UploadProgressQuery { - fn new(start: Instant, state: Weak>, size: Option) -> Self { - Self { start, state, size } - } - - // Note: this usize is since the upload started so, on 64 bit systems, it - // should be good for 584.5 million years. Downcasting is probably safe... - fn curr_gen(&self) -> usize { - let since = self.start.elapsed().as_millis() as usize; - since / self.interval_ms() - } - - pub const fn interval_ms(&self) -> usize { - INTERVAL - } - - /// Get the total number of bytes uploaded. - /// - /// Returns `None` if the `UploadProgress` has been dropped. - pub fn bytes(&self) -> Option { - self.state.upgrade().map(|s| s.lock().unwrap().0) - } - - pub fn size(&self) -> Option { - self.size - } - - pub fn done(&self) -> bool { - self.state.strong_count() == 0 - } - - /// Get the average bytes per second over the last `SIZE` intervals. - /// - /// Returns `None` if the `UploadProgress` has been dropped. - pub fn average_bps(&self) -> Option { - let curr_gen = self.curr_gen(); - let min_gen = curr_gen.saturating_sub(BUCKETS); - self.state.upgrade().map(|s| { - let s = s.lock().unwrap(); - let total_bytes = - s.1.iter() - .filter(|(gen, _)| *gen >= min_gen) - .map(|(_, bytes)| *bytes) - .sum::(); - - // buckets * interval = milliseconds, so we multiply by 1000 to get seconds - (total_bytes as f64 / (BUCKETS * INTERVAL) as f64) * 1000.0 - }) - } -} diff --git a/crates/turborepo-ci/Cargo.toml b/crates/turborepo-ci/Cargo.toml index 68047101f491c..cd1e7178a851e 100644 --- a/crates/turborepo-ci/Cargo.toml +++ b/crates/turborepo-ci/Cargo.toml @@ -1,17 +1,18 @@ -[package] -name = "turborepo-ci" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] chrono = { workspace = true } [dev-dependencies] test-case = "3.1.0" tracing = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-ci" +version = "0.1.0" diff --git a/crates/turborepo-ci/src/lib.rs b/crates/turborepo-ci/Source/lib.rs similarity index 100% rename from crates/turborepo-ci/src/lib.rs rename to crates/turborepo-ci/Source/lib.rs diff --git a/crates/turborepo-ci/Source/vendor_behavior.rs b/crates/turborepo-ci/Source/vendor_behavior.rs new file mode 100644 index 0000000000000..7168d4dff7b24 --- /dev/null +++ b/crates/turborepo-ci/Source/vendor_behavior.rs @@ -0,0 +1,31 @@ +use std::sync::Arc; + +use chrono::{DateTime, Utc}; + +pub type GroupPrefixFn = Arc) -> String + Send + Sync>; +type GroupPrefixFnFactory = fn(group_name:String) -> GroupPrefixFn; + +#[derive(Clone, Debug, PartialEq)] +pub struct VendorBehavior { + pub group_prefix:GroupPrefixFnFactory, + pub group_suffix:GroupPrefixFnFactory, + pub error_group_prefix:Option, + pub error_group_suffix:Option, +} + +impl VendorBehavior { + pub fn new(prefix:GroupPrefixFnFactory, suffix:GroupPrefixFnFactory) -> Self { + Self { + group_prefix:prefix, + group_suffix:suffix, + error_group_prefix:None, + error_group_suffix:None, + } + } + + pub fn with_error(mut self, prefix:GroupPrefixFnFactory, suffix:GroupPrefixFnFactory) -> Self { + self.error_group_prefix = Some(prefix); + self.error_group_suffix = Some(suffix); + self + } +} diff --git a/crates/turborepo-ci/src/vendors.rs b/crates/turborepo-ci/Source/vendors.rs similarity index 100% rename from crates/turborepo-ci/src/vendors.rs rename to crates/turborepo-ci/Source/vendors.rs diff --git a/crates/turborepo-ci/src/vendor_behavior.rs b/crates/turborepo-ci/src/vendor_behavior.rs deleted file mode 100644 index 54de63b717d40..0000000000000 --- a/crates/turborepo-ci/src/vendor_behavior.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::sync::Arc; - -use chrono::{DateTime, Utc}; - -pub type GroupPrefixFn = Arc) -> String + Send + Sync>; -type GroupPrefixFnFactory = fn(group_name: String) -> GroupPrefixFn; - -#[derive(Clone, Debug, PartialEq)] -pub struct VendorBehavior { - pub group_prefix: GroupPrefixFnFactory, - pub group_suffix: GroupPrefixFnFactory, - pub error_group_prefix: Option, - pub error_group_suffix: Option, -} - -impl VendorBehavior { - pub fn new(prefix: GroupPrefixFnFactory, suffix: GroupPrefixFnFactory) -> Self { - Self { - group_prefix: prefix, - group_suffix: suffix, - error_group_prefix: None, - error_group_suffix: None, - } - } - - pub fn with_error( - mut self, - prefix: GroupPrefixFnFactory, - suffix: GroupPrefixFnFactory, - ) -> Self { - self.error_group_prefix = Some(prefix); - self.error_group_suffix = Some(suffix); - self - } -} diff --git a/crates/turborepo-dirs/Cargo.toml b/crates/turborepo-dirs/Cargo.toml index 9761ce2f6cf59..76e1953a84450 100644 --- a/crates/turborepo-dirs/Cargo.toml +++ b/crates/turborepo-dirs/Cargo.toml @@ -1,15 +1,18 @@ -[package] -name = "turborepo-dirs" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] dirs-next = "2.0.0" -thiserror.workspace = true turbopath = { workspace = true } +[dependencies.thiserror] +workspace = true + +[lib] +path = "Source/lib.rs" + [lints] workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-dirs" +version = "0.1.0" diff --git a/crates/turborepo-dirs/Source/lib.rs b/crates/turborepo-dirs/Source/lib.rs new file mode 100644 index 0000000000000..3787e85a7db5f --- /dev/null +++ b/crates/turborepo-dirs/Source/lib.rs @@ -0,0 +1,35 @@ +use dirs_next::config_dir as dirs_config_dir; +use thiserror::Error; +use turbopath::{AbsoluteSystemPathBuf, PathError}; + +/// Returns the path to the user's configuration directory. +/// +/// This is a wrapper around `dirs_next::config_dir` that also checks the +/// `TURBO_CONFIG_DIR_PATH` environment variable. If the environment variable +/// is set, it will return that path instead of `dirs_next::config_dir`. +pub fn config_dir() -> Result, PathError> { + if let Ok(dir) = std::env::var("TURBO_CONFIG_DIR_PATH") { + return AbsoluteSystemPathBuf::new(dir).map(Some); + } + + dirs_config_dir().map(AbsoluteSystemPathBuf::try_from).transpose() +} + +/// Returns the path to the user's configuration directory. +/// +/// This is a wrapper around `dirs_next::config_dir` that also checks the +/// VERCEL_CONFIG_DIR_PATH` environment variable. If the environment variable +/// is set, it will return that path instead of `dirs_next::config_dir`. +pub fn vercel_config_dir() -> Result, PathError> { + if let Ok(dir) = std::env::var("VERCEL_CONFIG_DIR_PATH") { + return AbsoluteSystemPathBuf::new(dir).map(Some); + } + + dirs_config_dir().map(AbsoluteSystemPathBuf::try_from).transpose() +} + +#[derive(Debug, Error)] +pub enum Error { + #[error("Config directory not found.")] + ConfigDirNotFound, +} diff --git a/crates/turborepo-dirs/src/lib.rs b/crates/turborepo-dirs/src/lib.rs deleted file mode 100644 index c8c46f048dc45..0000000000000 --- a/crates/turborepo-dirs/src/lib.rs +++ /dev/null @@ -1,39 +0,0 @@ -use dirs_next::config_dir as dirs_config_dir; -use thiserror::Error; -use turbopath::{AbsoluteSystemPathBuf, PathError}; - -/// Returns the path to the user's configuration directory. -/// -/// This is a wrapper around `dirs_next::config_dir` that also checks the -/// `TURBO_CONFIG_DIR_PATH` environment variable. If the environment variable -/// is set, it will return that path instead of `dirs_next::config_dir`. -pub fn config_dir() -> Result, PathError> { - if let Ok(dir) = std::env::var("TURBO_CONFIG_DIR_PATH") { - return AbsoluteSystemPathBuf::new(dir).map(Some); - } - - dirs_config_dir() - .map(AbsoluteSystemPathBuf::try_from) - .transpose() -} - -/// Returns the path to the user's configuration directory. -/// -/// This is a wrapper around `dirs_next::config_dir` that also checks the -/// VERCEL_CONFIG_DIR_PATH` environment variable. If the environment variable -/// is set, it will return that path instead of `dirs_next::config_dir`. -pub fn vercel_config_dir() -> Result, PathError> { - if let Ok(dir) = std::env::var("VERCEL_CONFIG_DIR_PATH") { - return AbsoluteSystemPathBuf::new(dir).map(Some); - } - - dirs_config_dir() - .map(AbsoluteSystemPathBuf::try_from) - .transpose() -} - -#[derive(Debug, Error)] -pub enum Error { - #[error("Config directory not found.")] - ConfigDirNotFound, -} diff --git a/crates/turborepo-env/Cargo.toml b/crates/turborepo-env/Cargo.toml index 4751cb2141f7b..586059be110bf 100644 --- a/crates/turborepo-env/Cargo.toml +++ b/crates/turborepo-env/Cargo.toml @@ -1,14 +1,3 @@ -[package] -name = "turborepo-env" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] hex = { workspace = true } regex = { workspace = true } @@ -20,3 +9,15 @@ turborepo-ui = { workspace = true } [dev-dependencies] test-case = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-env" +version = "0.1.0" diff --git a/crates/turborepo-env/src/lib.rs b/crates/turborepo-env/Source/lib.rs similarity index 100% rename from crates/turborepo-env/src/lib.rs rename to crates/turborepo-env/Source/lib.rs diff --git a/crates/turborepo-env/Source/platform.rs b/crates/turborepo-env/Source/platform.rs new file mode 100644 index 0000000000000..30ef4fbbeeb20 --- /dev/null +++ b/crates/turborepo-env/Source/platform.rs @@ -0,0 +1,105 @@ +use turborepo_ci::Vendor; +use turborepo_ui::{BOLD, ColorConfig, GREY, UNDERLINE, YELLOW, ceprint, ceprintln, color}; + +use crate::EnvironmentVariableMap; + +pub struct PlatformEnv { + env_keys:Vec, +} + +impl Default for PlatformEnv { + fn default() -> Self { Self::new() } +} + +const TURBO_PLATFORM_ENV_KEY:&str = "TURBO_PLATFORM_ENV"; +const TURBO_PLATFORM_ENV_DISABLED_KEY:&str = "TURBO_PLATFORM_ENV_DISABLED"; + +impl PlatformEnv { + pub fn new() -> Self { + let env_keys = std::env::var(TURBO_PLATFORM_ENV_KEY) + .unwrap_or_default() + .split(',') + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect(); + + Self { env_keys } + } + + pub fn disabled() -> bool { + let turbo_platform_env_disabled = + std::env::var(TURBO_PLATFORM_ENV_DISABLED_KEY).unwrap_or_default(); + turbo_platform_env_disabled == "1" || turbo_platform_env_disabled == "true" + } + + pub fn validate(&self, execution_env:&EnvironmentVariableMap) -> Vec { + if Self::disabled() { + return vec![]; + } + + self.diff(execution_env) + } + + pub fn diff(&self, execution_env:&EnvironmentVariableMap) -> Vec { + self.env_keys + .iter() + .filter(|key| !execution_env.contains_key(*key)) + .map(|s| s.to_string()) + .collect() + } + + pub fn output_header(is_strict:bool, color_config:ColorConfig) { + let ci = Vendor::get_constant().unwrap_or("unknown"); + + let strict_message = if is_strict { + "These variables WILL NOT be available to your application and may cause your build to \ + fail." + } else { + "These variables WILL NOT be considered in your cache key and could cause inadvertent \ + cache hits." + }; + + let docs_message = color!( + color_config, + UNDERLINE, + "https://turbo.build/repo/docs/platform-environment-variables" + ); + + match ci { + "VERCEL" => { + ceprintln!( + color_config, + BOLD, + "Warning - the following environment variables are set on your Vercel \ + project, but missing from \"turbo.json\". {strict_message} Learn more at \ + {docs_message}\n" + ); + }, + _ => { + ceprintln!( + color_config, + BOLD, + "Warning - the following environment variables are missing from \ + \"turbo.json\". {strict_message} Learn more at {docs_message}\n" + ); + }, + } + } + + pub fn output_for_task( + missing:Vec, + task_id_for_display:&str, + color_config:ColorConfig, + ) { + let ci = Vendor::get_constant().unwrap_or("unknown"); + let log_prefix = match ci { + "VERCEL" => "[warn]", + _ => "", + }; + ceprintln!(color_config, YELLOW, "{} {}", log_prefix, task_id_for_display); + for key in missing { + ceprint!(color_config, GREY, "{} - ", log_prefix); + ceprint!(color_config, GREY, "{} \n", key); + } + } +} diff --git a/crates/turborepo-env/src/platform.rs b/crates/turborepo-env/src/platform.rs deleted file mode 100644 index 819b4f83912e4..0000000000000 --- a/crates/turborepo-env/src/platform.rs +++ /dev/null @@ -1,113 +0,0 @@ -use turborepo_ci::Vendor; -use turborepo_ui::{ceprint, ceprintln, color, ColorConfig, BOLD, GREY, UNDERLINE, YELLOW}; - -use crate::EnvironmentVariableMap; - -pub struct PlatformEnv { - env_keys: Vec, -} - -impl Default for PlatformEnv { - fn default() -> Self { - Self::new() - } -} - -const TURBO_PLATFORM_ENV_KEY: &str = "TURBO_PLATFORM_ENV"; -const TURBO_PLATFORM_ENV_DISABLED_KEY: &str = "TURBO_PLATFORM_ENV_DISABLED"; - -impl PlatformEnv { - pub fn new() -> Self { - let env_keys = std::env::var(TURBO_PLATFORM_ENV_KEY) - .unwrap_or_default() - .split(',') - .filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - .collect(); - - Self { env_keys } - } - - pub fn disabled() -> bool { - let turbo_platform_env_disabled = - std::env::var(TURBO_PLATFORM_ENV_DISABLED_KEY).unwrap_or_default(); - turbo_platform_env_disabled == "1" || turbo_platform_env_disabled == "true" - } - - pub fn validate(&self, execution_env: &EnvironmentVariableMap) -> Vec { - if Self::disabled() { - return vec![]; - } - - self.diff(execution_env) - } - - pub fn diff(&self, execution_env: &EnvironmentVariableMap) -> Vec { - self.env_keys - .iter() - .filter(|key| !execution_env.contains_key(*key)) - .map(|s| s.to_string()) - .collect() - } - - pub fn output_header(is_strict: bool, color_config: ColorConfig) { - let ci = Vendor::get_constant().unwrap_or("unknown"); - - let strict_message = if is_strict { - "These variables WILL NOT be available to your application and may cause your build to \ - fail." - } else { - "These variables WILL NOT be considered in your cache key and could cause inadvertent \ - cache hits." - }; - - let docs_message = color!( - color_config, - UNDERLINE, - "https://turbo.build/repo/docs/platform-environment-variables" - ); - - match ci { - "VERCEL" => { - ceprintln!( - color_config, - BOLD, - "Warning - the following environment variables are set on your Vercel \ - project, but missing from \"turbo.json\". {strict_message} Learn more at \ - {docs_message}\n" - ); - } - _ => { - ceprintln!( - color_config, - BOLD, - "Warning - the following environment variables are missing from \ - \"turbo.json\". {strict_message} Learn more at {docs_message}\n" - ); - } - } - } - - pub fn output_for_task( - missing: Vec, - task_id_for_display: &str, - color_config: ColorConfig, - ) { - let ci = Vendor::get_constant().unwrap_or("unknown"); - let log_prefix = match ci { - "VERCEL" => "[warn]", - _ => "", - }; - ceprintln!( - color_config, - YELLOW, - "{} {}", - log_prefix, - task_id_for_display - ); - for key in missing { - ceprint!(color_config, GREY, "{} - ", log_prefix); - ceprint!(color_config, GREY, "{} \n", key); - } - } -} diff --git a/crates/turborepo-errors/Cargo.toml b/crates/turborepo-errors/Cargo.toml index c5fc4394e3d47..97347fe6a0390 100644 --- a/crates/turborepo-errors/Cargo.toml +++ b/crates/turborepo-errors/Cargo.toml @@ -1,14 +1,7 @@ -[package] -name = "turborepo-errors" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] biome_deserialize = { workspace = true } biome_diagnostics = { workspace = true } +biome_json_parser = { workspace = true } miette = { workspace = true } serde = { workspace = true, features = ["derive"] } thiserror = { workspace = true } @@ -17,5 +10,14 @@ thiserror = { workspace = true } serde_json = { workspace = true } test-case = { workspace = true } +[lib] +path = "Source/lib.rs" + [lints] workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-errors" +version = "0.1.0" diff --git a/crates/turborepo-errors/src/lib.rs b/crates/turborepo-errors/Source/lib.rs similarity index 100% rename from crates/turborepo-errors/src/lib.rs rename to crates/turborepo-errors/Source/lib.rs diff --git a/crates/turborepo-filewatch/Cargo.toml b/crates/turborepo-filewatch/Cargo.toml index fa8af6944e4a2..98bab8b561180 100644 --- a/crates/turborepo-filewatch/Cargo.toml +++ b/crates/turborepo-filewatch/Cargo.toml @@ -1,14 +1,3 @@ -[package] -name = "turborepo-filewatch" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] futures = { version = "0.3.26" } itertools = { workspace = true } @@ -25,10 +14,6 @@ turborepo-scm = { workspace = true } walkdir = "2.3.3" wax = { workspace = true } -[target."cfg(target_os=\"macos\")".dependencies.fsevent-sys] -optional = true -version = "4" - [dependencies.bitflags] version = "1.0.4" @@ -46,3 +31,25 @@ default = ["macos_fsevent"] macos_fsevent = ["fsevent-sys"] manual_recursive_watch = [] watch_ancestors = [] + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-filewatch" +version = "0.1.0" + +[target] + +[target.'cfg(target_os="macos")'] + +[target.'cfg(target_os="macos")'.dependencies] + +[target.'cfg(target_os="macos")'.dependencies.fsevent-sys] +optional = true +version = "4" diff --git a/crates/turborepo-filewatch/Source/cookies.rs b/crates/turborepo-filewatch/Source/cookies.rs new file mode 100644 index 0000000000000..a3bc1c220d472 --- /dev/null +++ b/crates/turborepo-filewatch/Source/cookies.rs @@ -0,0 +1,655 @@ +//! Cookies. +//! +//! They are the file watcher's way of synchronizing file system events. They +//! are files that are added to the file system that are named with the format +//! `[id].cookie`, where `[id]` is an increasing serial number, e.g. +//! `1.cookie`, `2.cookie`, and so on. The daemon can then watch for the +//! file creation event for this cookie file. Once it sees this event, +//! the daemon knows that the file system events are up to date and we +//! won't get any stale events. +//! +//! Here's the `CookieWriter` flow: +//! - `CookieWriter` spins up a `watch_for_cookie_requests` task and creates a +//! `cookie_requests` mpsc channel to send a cookie request to that task. The +//! cookie request consists of a oneshot `Sender` that the task can use to +//! send back the serial number. +//! - The `watch_for_cookie_requests` task watches for cookie requests on +//! `cookie_requests_rx`. When one occurs, it creates the cookie file and +//! bumps the serial. It then sends the serial back using the `Sender` +//! - When `CookieWriter::cookie_request` is called, it sends the cookie request +//! to the `watch_for_cookie_request` channel and then waits for the serial as +//! a response (with a timeout). Upon getting the serial, a `CookiedRequest` +//! gets returned with the serial number attached. +//! +//! And here's the `CookieWatcher` flow: +//! - `GlobWatcher` creates a `CookieWatcher`. +//! - `GlobWatcher` gets queries about globs that are wrapped in +//! `CookiedRequest`. It passes these requests to +//! `CookieWatcher::check_request` +//! - If the serial number attached to `CookiedRequest` has already been seen, +//! `CookieWatcher::check_request` returns the inner query immediately. +//! Otherwise, it gets stored in `CookieWatcher`. +//! - `GlobWatcher` waits for file system events on `recv`. When it gets an +//! event, it passes the event to `CookieWatcher::pop_ready_requests`. If this +//! event is indeed a cookie event, we return all of the requests that are now +//! allowed to be processed (i.e. their serial number is now less than or +//! equal to the latest seen serial). + +use std::{collections::BinaryHeap, fs::OpenOptions, time::Duration}; + +use futures::FutureExt; +use notify::EventKind; +use thiserror::Error; +use tokio::{ + sync::{broadcast, mpsc, oneshot, watch}, + time::error::Elapsed, +}; +use tracing::trace; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathRelation}; + +use crate::{NotifyError, OptionalWatch, optional_watch::SomeRef}; + +#[derive(Debug, Error)] +pub enum CookieError { + #[error("cookie timeout expired")] + Timeout(#[from] Elapsed), + #[error("failed to receiver cookie notification: {0}")] + RecvError(#[from] oneshot::error::RecvError), + #[error("failed to send cookie file request: {0}")] + SendError(#[from] mpsc::error::SendError>>), + #[error("failed to write cookie file at {path}: {io_err}")] + IO { io_err:std::io::Error, path:AbsoluteSystemPathBuf }, + #[error("cookie queue is not available")] + Unavailable(#[from] watch::error::RecvError), +} + +/// CookieWriter is responsible for assigning filesystem cookies to a request +/// for a downstream, filewatching-backed service. +#[derive(Clone)] +pub struct CookieWriter { + // Where we put the cookie files, usually `/.turbo/cookies` + cookie_root:AbsoluteSystemPathBuf, + timeout:Duration, + cookie_request_sender_lazy: + OptionalWatch>>>, + // _exit_ch exists to trigger a close on the receiver when all instances + // of this struct are dropped. The task that is receiving events will exit, + // dropping the other sender for the broadcast channel, causing all receivers + // to be notified of a close. + _exit_ch:mpsc::Sender<()>, +} + +/// A request that can only be processed after the `serial` has been seen by the +/// `CookieWatcher`. +#[derive(Debug)] +pub struct CookiedRequest { + request:T, + serial:usize, +} + +impl PartialEq for CookiedRequest { + fn eq(&self, other:&Self) -> bool { self.serial == other.serial } +} + +impl Eq for CookiedRequest {} + +impl PartialOrd for CookiedRequest { + fn partial_cmp(&self, other:&Self) -> Option { Some(self.cmp(other)) } +} + +impl Ord for CookiedRequest { + fn cmp(&self, other:&Self) -> std::cmp::Ordering { + // Lower serials should be sorted higher, since the heap pops the highest values + // first + other.serial.cmp(&self.serial) + } +} + +/// CookieWatcher is used by downstream filewatching-backed services to +/// know when it is safe to handle a particular request. +pub(crate) struct CookieWatcher { + // Where we expect to find the cookie files, usually `/.turbo/cookies` + cookie_root:AbsoluteSystemPathBuf, + // We don't necessarily get requests in serial-order, but we want to keep them + // in order so we don't have to scan all requests every time we get a new cookie. + pending_requests:BinaryHeap>, + latest:usize, +} + +impl CookieWatcher { + pub(crate) fn new(cookie_root:AbsoluteSystemPathBuf) -> Self { + Self { cookie_root, pending_requests:BinaryHeap::new(), latest:0 } + } + + /// Check if this request can be handled immediately. If so, return it. If + /// not, queue it + pub(crate) fn check_request(&mut self, cookied_request:CookiedRequest) -> Option { + if cookied_request.serial <= self.latest { + // We've already seen the cookie for this request, handle it now + Some(cookied_request.request) + } else { + // We haven't seen the cookie for this request yet, hold onto it + self.pending_requests.push(cookied_request); + None + } + } + + /// If this is a cookie file, pop all requests that are ready to be handled. + /// The returned vector might be empty if this was a cookie file but we + /// don't have any requests that are ready to be handled. None is + /// returned if this is not a cookie file being created. + pub(crate) fn pop_ready_requests( + &mut self, + event_kind:EventKind, + path:&AbsoluteSystemPath, + ) -> Option> { + if !matches!(event_kind, EventKind::Create(_)) { + return None; + } + if let Some(serial) = serial_for_path(&self.cookie_root, path) { + self.latest = serial; + let mut ready_requests = Vec::new(); + while let Some(cookied_request) = self.pending_requests.pop() { + if cookied_request.serial <= serial { + ready_requests.push(cookied_request.request); + } else { + self.pending_requests.push(cookied_request); + break; + } + } + Some(ready_requests) + } else { + None + } + } +} + +fn serial_for_path(root:&AbsoluteSystemPath, path:&AbsoluteSystemPath) -> Option { + if root.relation_to_path(path) == PathRelation::Parent { + let filename = path.file_name()?; + filename.strip_suffix(".cookie")?.parse().ok() + } else { + None + } +} + +impl CookieWriter { + #[cfg(test)] + pub fn new_with_default_cookie_dir( + repo_root:&AbsoluteSystemPath, + timeout:Duration, + recv:OptionalWatch>>, + ) -> Self { + let cookie_root = repo_root.join_components(&[".turbo", "cookies"]); + Self::new(&cookie_root, timeout, recv) + } + + pub fn new( + cookie_root:&AbsoluteSystemPath, + timeout:Duration, + mut recv:OptionalWatch>>, + ) -> Self { + let (cookie_request_sender_tx, cookie_request_sender_lazy) = OptionalWatch::new(); + let (exit_ch, exit_signal) = mpsc::channel(16); + tokio::spawn({ + let root = cookie_root.to_owned(); + async move { + if recv.get().await.is_err() { + // here we need to wait for confirmation that the watching end is ready + // before we start sending requests. this has the side effect of not + // enabling the cookie writing mechanism until the watcher is ready + return; + } + + let (cookie_requests_tx, cookie_requests_rx) = mpsc::channel(16); + + if cookie_request_sender_tx.send(Some(cookie_requests_tx)).is_err() { + // the receiver has already been dropped + tracing::debug!("nobody listening for cookie requests, exiting"); + return; + }; + watch_for_cookie_file_requests(root.to_owned(), cookie_requests_rx, exit_signal) + .await; + } + }); + Self { + cookie_root:cookie_root.to_owned(), + timeout, + cookie_request_sender_lazy, + _exit_ch:exit_ch, + } + } + + pub(crate) fn root(&self) -> &AbsoluteSystemPath { &self.cookie_root } + + /// Sends a request to make a cookie file to the + /// `watch_for_cookie_file_requests` task. Waits on a response from the + /// task, and returns a `CookiedRequest` with the expected serial + /// number. + pub(crate) async fn cookie_request( + &self, + request:T, + ) -> Result, CookieError> { + // we need to write the cookie from a single task so as to serialize them + tokio::time::timeout(self.timeout, self.cookie_request_inner(request, None)).await? + } + + /// Internal services may want to wait for the cookie + /// system to be set up, before issuing a timeout for the + /// cookie request. + pub(crate) async fn initialized_cookie_request( + &self, + request:T, + ) -> Result, CookieError> { + self.cookie_request_inner(request, Some(self.timeout)).await + } + + async fn cookie_request_inner( + &self, + request:T, + timeout:Option, + ) -> Result, CookieError> { + let (resp_tx, resp_rx) = oneshot::channel(); + let mut cookie_request_sender_lazy = self.cookie_request_sender_lazy.clone(); + let cookie_request_sender_lazy = + cookie_request_sender_lazy.get().await.map(|s| s.to_owned())?; + cookie_request_sender_lazy.send(resp_tx).await?; + let serial = match timeout { + Some(timeout) => { + let resp_rx = tokio::time::timeout(timeout, resp_rx).await??; + resp_rx? + }, + None => resp_rx.await??, + }; + Ok(CookiedRequest { request, serial }) + } +} + +async fn watch_for_cookie_file_requests( + root:AbsoluteSystemPathBuf, + mut cookie_requests:mpsc::Receiver>>, + mut exit_signal:mpsc::Receiver<()>, +) { + let mut serial:usize = 0; + loop { + tokio::select! { + biased; + _ = exit_signal.recv() => return, + req = cookie_requests.recv() => handle_cookie_file_request(&root, &mut serial, req), + } + } +} + +fn handle_cookie_file_request( + root:&AbsoluteSystemPath, + serial:&mut usize, + req:Option>>, +) { + if let Some(req) = req { + *serial += 1; + let cookie_path = root.join_component(&format!("{}.cookie", serial)); + let mut opts = OpenOptions::new(); + opts.truncate(true).create(true).write(true); + let result = { + // dropping the resulting file closes the handle + trace!("writing cookie {}", cookie_path); + cookie_path + .ensure_dir() + .and_then(|_| cookie_path.open_with_options(opts)) + .map_err(|io_err| CookieError::IO { io_err, path:cookie_path.clone() }) + }; + let result = result.map(|_| *serial); + // We don't care if the client has timed out and gone away + let _ = req.send(result); + } +} + +/// a lightweight wrapper around OptionalWatch that embeds cookie ids into the +/// get call. for requests that require cookies (ie, waiting for filesystem +/// flushes) then a cookie watch is ideal +pub struct CookiedOptionalWatch { + value:watch::Receiver>, + cookie_index:watch::Receiver, + cookie_writer:CookieWriter, + parent:P, +} + +impl Clone for CookiedOptionalWatch { + fn clone(&self) -> Self { + Self { + value:self.value.clone(), + cookie_index:self.cookie_index.clone(), + cookie_writer:self.cookie_writer.clone(), + parent:self.parent.clone(), + } + } +} + +pub trait CookieReady { + fn ready(&mut self, id:usize) -> impl std::future::Future; +} + +impl CookieReady for () { + async fn ready(&mut self, _id:usize) {} +} + +impl CookieReady for CookiedOptionalWatch { + async fn ready(&mut self, id:usize) { + tracing::debug!("waiting for cookie {}", id); + self.parent.ready(id).await; + _ = self.cookie_index.wait_for(|v| v >= &id).await; + } +} + +impl CookiedOptionalWatch { + pub fn new( + update:CookieWriter, + ) -> (watch::Sender>, CookieRegister, CookiedOptionalWatch) { + let (tx, rx) = watch::channel(None); + let (cookie_tx, cookie_rx) = watch::channel(0); + tracing::debug!("starting cookied optional watch in {}", update.root()); + ( + tx, + CookieRegister(cookie_tx, update.root().to_owned()), + CookiedOptionalWatch { + value:rx, + cookie_index:cookie_rx, + cookie_writer:update, + parent:(), + }, + ) + } +} + +impl CookiedOptionalWatch { + /// Create a new sibling cookie watcher that inherits the same fs source as + /// this one. + pub fn new_sibling(&self) -> (watch::Sender>, CookiedOptionalWatch) { + let (tx, rx) = watch::channel(None); + ( + tx, + CookiedOptionalWatch { + value:rx, + cookie_index:self.cookie_index.clone(), + cookie_writer:self.cookie_writer.clone(), + parent:self.parent.clone(), + }, + ) + } + + /// Create a new child cookie watcher that inherits the same fs source as + /// this one, but also has its own cookie source. This allows you to + /// synchronize two independent cookie streams. + pub fn new_child( + &self, + ) -> (watch::Sender>, CookieRegister, CookiedOptionalWatch) { + let (tx, rx) = watch::channel(None); + let (cookie_tx, cookie_rx) = watch::channel(0); + + ( + tx, + CookieRegister(cookie_tx, self.cookie_writer.root().to_owned()), + CookiedOptionalWatch { + value:rx, + cookie_index:cookie_rx, + cookie_writer:self.cookie_writer.clone(), + parent:self.clone(), + }, + ) + } + + #[tracing::instrument(skip(self))] + pub async fn get(&mut self) -> Result, CookieError> { + let next_id = self.cookie_writer.initialized_cookie_request(()).await?.serial; + self.ready(next_id).await; + tracing::debug!("got cookie, waiting for data"); + Ok(self.get_inner().await?) + } + + #[tracing::instrument(skip(self))] + pub async fn get_change(&mut self) -> Result, watch::error::RecvError> { + self.value.changed().await?; + self.get_inner().await + } + + /// Please do not use this data from a user-facing query. It should only + /// really be used for internal state management. Equivalent to + /// `OptionalWatch::get` + /// + /// For an example as to why we need this, sometimes file event processing + /// needs to access data but issuing a cookie request would deadlock. + /// + /// `_reason` is purely for documentation purposes and is not used. + pub async fn get_raw( + &mut self, + _reason:&str, + ) -> Result, watch::error::RecvError> { + self.get_inner().await + } + + /// Get the current value, if it is available. + /// + /// Unlike `OptionalWatch::get_immediate`, this method will block until the + /// cookie has been seen, at which point it will call `now_or_never` on the + /// value watch. + #[tracing::instrument(skip(self))] + pub async fn get_immediate( + &mut self, + ) -> Option, watch::error::RecvError>> { + let next_id = self.cookie_writer.cookie_request(()).await.ok()?.serial; + self.cookie_index.wait_for(|v| v >= &next_id).await.ok()?; + self.get_inner().now_or_never() + } + + /// Please do not use this data from a user-facing query. It should only + /// really be used for internal state management. Equivalent to + /// `OptionalWatch::get` + /// + /// For an example as to why we need this, sometimes file event processing + /// needs to access data but issuing a cookie request would deadlock. + /// + /// `_reason` is purely for documentation purposes and is not used. + pub async fn get_immediate_raw( + &mut self, + reason:&str, + ) -> Option, watch::error::RecvError>> { + self.get_raw(reason).now_or_never() + } + + async fn get_inner(&mut self) -> Result, watch::error::RecvError> { + self.value.wait_for(|f| f.is_some()).await?; + Ok(SomeRef(self.value.borrow())) + } + + pub(crate) fn watch(&self) -> watch::Receiver> { self.value.clone() } +} + +pub struct CookieRegister(watch::Sender, AbsoluteSystemPathBuf); +impl CookieRegister { + pub fn register(&self, paths:&[&AbsoluteSystemPath]) { + tracing::trace!("registering cookie for {:?}", paths); + for path in paths { + if let Some(serial) = serial_for_path(&self.1, path) { + tracing::trace!("updating cookie to {}", serial); + let _ = self.0.send(serial); + } + } + } +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use notify::{Event, EventKind, event::CreateKind}; + use tokio::{ + sync::{broadcast, mpsc, oneshot}, + task::JoinSet, + }; + use turbopath::AbsoluteSystemPathBuf; + + use super::{CookieWatcher, CookiedRequest}; + use crate::{NotifyError, OptionalWatch, cookies::CookieWriter}; + + struct TestQuery { + resp:oneshot::Sender<()>, + } + + struct TestService { + file_events:broadcast::Receiver>, + cookie_watcher:CookieWatcher, + reqs_rx:mpsc::Receiver>, + } + + impl TestService { + async fn watch(mut self, mut exit_ch:oneshot::Receiver<()>) { + loop { + tokio::select! { + biased; + _ = &mut exit_ch => return, + Some(req) = self.reqs_rx.recv() => { + if let Some(query) = self.cookie_watcher.check_request(req) { + query.resp.send(()).unwrap(); + } + } + file_event = self.file_events.recv() => { + let event = file_event.unwrap().unwrap(); + for path in event.paths { + let path = AbsoluteSystemPathBuf::try_from(path).unwrap(); + if let Some(queries) = self.cookie_watcher.pop_ready_requests(event.kind, &path) { + for query in queries { + query.resp.send(()).unwrap(); + } + } + } + } + } + } + } + } + + #[derive(Clone)] + struct TestClient { + reqs_tx:mpsc::Sender>, + cookie_writer:CookieWriter, + } + + impl TestClient { + async fn request(&self) { + let (resp_tx, resp_rx) = oneshot::channel(); + let query = TestQuery { resp:resp_tx }; + let req = self.cookie_writer.cookie_request(query).await.unwrap(); + self.reqs_tx.send(req).await.unwrap(); + resp_rx.await.unwrap(); + } + } + + #[tokio::test(flavor = "multi_thread")] + async fn test_service_cookies() { + let tempdir = tempfile::tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tempdir.path()).unwrap().to_realpath().unwrap(); + + let (send_file_events, file_events) = broadcast::channel(16); + let recv = OptionalWatch::once(file_events.resubscribe()); + let (reqs_tx, reqs_rx) = mpsc::channel(16); + let cookie_writer = CookieWriter::new(&path, Duration::from_secs(2), recv); + let (exit_tx, exit_rx) = oneshot::channel(); + + let service = + TestService { file_events, cookie_watcher:CookieWatcher::new(path.clone()), reqs_rx }; + let service_handle = tokio::spawn(service.watch(exit_rx)); + + let client = TestClient { reqs_tx, cookie_writer }; + // race request and file event. Either order should work. + tokio_scoped::scope(|scope| { + scope.spawn(client.request()); + send_file_events + .send(Ok(Event { + kind:EventKind::Create(CreateKind::File), + paths:vec![path.join_component("1.cookie").as_std_path().to_owned()], + ..Default::default() + })) + .unwrap(); + }); + + // explicitly send the cookie first + tokio_scoped::scope(|scope| { + send_file_events + .send(Ok(Event { + kind:EventKind::Create(CreateKind::File), + paths:vec![path.join_component("2.cookie").as_std_path().to_owned()], + ..Default::default() + })) + .unwrap(); + scope.spawn(client.request()); + }); + + // send a cookie with a much higher value + tokio_scoped::scope(|scope| { + send_file_events + .send(Ok(Event { + kind:EventKind::Create(CreateKind::File), + paths:vec![path.join_component("20.cookie").as_std_path().to_owned()], + ..Default::default() + })) + .unwrap(); + scope.spawn(client.request()); + }); + exit_tx.send(()).unwrap(); + service_handle.await.unwrap(); + } + + #[tokio::test(flavor = "multi_thread")] + async fn test_out_of_order_requests() { + let tempdir = tempfile::tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tempdir.path()).unwrap().to_realpath().unwrap(); + + let (send_file_events, file_events) = broadcast::channel(16); + let recv = OptionalWatch::once(file_events.resubscribe()); + let (reqs_tx, reqs_rx) = mpsc::channel(16); + let cookie_writer = CookieWriter::new(&path, Duration::from_secs(2), recv); + let (exit_tx, exit_rx) = oneshot::channel(); + + let service = + TestService { file_events, cookie_watcher:CookieWatcher::new(path.clone()), reqs_rx }; + let service_handle = tokio::spawn(service.watch(exit_rx)); + + let client = TestClient { reqs_tx, cookie_writer }; + + let mut join_set = JoinSet::new(); + let client_1 = client.clone(); + join_set.spawn(async move { client_1.request().await }); + + let client_2 = client.clone(); + join_set.spawn(async move { client_2.request().await }); + + let client_3 = client.clone(); + join_set.spawn(async move { client_3.request().await }); + + send_file_events + .send(Ok(Event { + kind:EventKind::Create(CreateKind::File), + paths:vec![path.join_component("2.cookie").as_std_path().to_owned()], + ..Default::default() + })) + .unwrap(); + + // Expect 2 rpcs to be ready. We don't know which ones they will be + // but we also don't care. We don't have ordering semantics on the client + // side. + join_set.join_next().await.unwrap().unwrap(); + join_set.join_next().await.unwrap().unwrap(); + + send_file_events + .send(Ok(Event { + kind:EventKind::Create(CreateKind::File), + paths:vec![path.join_component("3.cookie").as_std_path().to_owned()], + ..Default::default() + })) + .unwrap(); + join_set.join_next().await.unwrap().unwrap(); + + exit_tx.send(()).unwrap(); + service_handle.await.unwrap(); + } +} diff --git a/crates/turborepo-filewatch/Source/debouncer.rs b/crates/turborepo-filewatch/Source/debouncer.rs new file mode 100644 index 0000000000000..36e81f9a24583 --- /dev/null +++ b/crates/turborepo-filewatch/Source/debouncer.rs @@ -0,0 +1,121 @@ +use std::{fmt::Debug, sync::Mutex, time::Duration}; + +use tokio::{select, sync, time::Instant}; +use tracing::trace; + +pub(crate) struct Debouncer { + bump:sync::Notify, + serial:Mutex>, + timeout:Duration, +} + +const DEFAULT_DEBOUNCE_TIMEOUT:Duration = Duration::from_millis(10); + +impl Default for Debouncer { + fn default() -> Self { Self::new(DEFAULT_DEBOUNCE_TIMEOUT) } +} + +impl Debug for Debouncer { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let serial = { self.serial.lock().expect("lock is valid") }; + f.debug_struct("Debouncer") + .field("is_pending", &serial.is_some()) + .field("timeout", &self.timeout) + .finish() + } +} + +impl Debouncer { + pub(crate) fn new(timeout:Duration) -> Self { + let bump = sync::Notify::new(); + let serial = Mutex::new(Some(0)); + Self { bump, serial, timeout } + } + + pub(crate) fn bump(&self) -> bool { + let mut serial = self.serial.lock().expect("lock is valid"); + match *serial { + None => false, + Some(previous) => { + *serial = Some(previous + 1); + self.bump.notify_one(); + true + }, + } + } + + pub(crate) async fn debounce(&self) { + let mut serial = { + self.serial + .lock() + .expect("lock is valid") + .expect("only this thread sets the value to None") + }; + let mut deadline = Instant::now() + self.timeout; + loop { + let timeout = tokio::time::sleep_until(deadline); + select! { + _ = self.bump.notified() => { + trace!("debouncer notified"); + // reset timeout + let current_serial = self.serial.lock().expect("lock is valid").expect("only this thread sets the value to None"); + if current_serial == serial { + // we timed out between the serial update and the notification. + // ignore this notification, we've already bumped the timer + continue; + } else { + serial = current_serial; + deadline = Instant::now() + self.timeout; + } + } + _ = timeout => { + // check if serial is still valid. It's possible a bump came in before the timeout, + // but we haven't been notified yet. + let mut current_serial_opt = self.serial.lock().expect("lock is valid"); + let current_serial = current_serial_opt.expect("only this thread sets the value to None"); + if current_serial == serial { + // if the serial is what we last observed, and the timer expired, we timed out. + // we're done. Mark that we won't accept any more bumps and return + *current_serial_opt = None; + return; + } else { + serial = current_serial; + deadline = Instant::now() + self.timeout; + } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use std::{ + sync::Arc, + time::{Duration, Instant}, + }; + + use crate::debouncer::Debouncer; + + #[tokio::test] + async fn test_debouncer() { + let debouncer = Arc::new(Debouncer::new(Duration::from_millis(10))); + let debouncer_copy = debouncer.clone(); + let handle = tokio::task::spawn(async move { + debouncer_copy.debounce().await; + }); + for _ in 0..10 { + // assert that we can continue bumping it past the original timeout + tokio::time::sleep(Duration::from_millis(2)).await; + assert!(debouncer.bump()); + } + let start = Instant::now(); + handle.await.unwrap(); + let end = Instant::now(); + // give some wiggle room to account for race conditions, but assert that we + // didn't immediately complete after the last bump + assert!(end - start > Duration::from_millis(5)); + // we shouldn't be able to bump it after it's run out it's timeout + assert!(!debouncer.bump()); + } +} diff --git a/crates/turborepo-filewatch/Source/fsevent.rs b/crates/turborepo-filewatch/Source/fsevent.rs new file mode 100644 index 0000000000000..3a16184629cd6 --- /dev/null +++ b/crates/turborepo-filewatch/Source/fsevent.rs @@ -0,0 +1,632 @@ +//! Watcher implementation for Darwin's FSEvents API +//! +//! The FSEvents API provides a mechanism to notify clients about directories +//! they ought to re-scan in order to keep their internal data structures +//! up-to-date with respect to the true state of the file system. (For example, +//! when files or directories are created, modified, or removed.) It sends these +//! notifications "in bulk", possibly notifying the client of changes to several +//! directories in a single callback. +//! +//! For more information see the [FSEvents API reference][ref]. +//! +//! TODO: document event translation +//! +//! [ref]: https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/ + +#![allow(non_upper_case_globals, dead_code)] +// bitflags! with a 0 value defined triggers this clippy error, +// but we want to be able to define a value for fs::kFSEventStreamEventFlagNone +#![allow(clippy::bad_bit_mask)] + +use std::{ + collections::HashMap, + ffi::CStr, + fmt, + io::ErrorKind, + os::{raw, unix::prelude::MetadataExt}, + path::{Path, PathBuf}, + ptr, + sync::{Arc, Mutex}, + thread, +}; + +use fs::core_foundation::Boolean; +use fsevent_sys as fs; +use fsevent_sys::core_foundation as cf; +use notify::{ + Config, + Error, + Event, + EventHandler, + EventKind, + RecursiveMode, + Result, + Watcher, + WatcherKind, + event::{CreateKind, DataChange, Flag, MetadataKind, ModifyKind, RemoveKind, RenameMode}, +}; + +// use crate::event::*; + +type Sender = std::sync::mpsc::Sender; + +bitflags::bitflags! { + #[repr(C)] + struct StreamFlags: u32 { + const NONE = fs::kFSEventStreamEventFlagNone; + const MUST_SCAN_SUBDIRS = fs::kFSEventStreamEventFlagMustScanSubDirs; + const USER_DROPPED = fs::kFSEventStreamEventFlagUserDropped; + const KERNEL_DROPPED = fs::kFSEventStreamEventFlagKernelDropped; + const IDS_WRAPPED = fs::kFSEventStreamEventFlagEventIdsWrapped; + const HISTORY_DONE = fs::kFSEventStreamEventFlagHistoryDone; + const ROOT_CHANGED = fs::kFSEventStreamEventFlagRootChanged; + const MOUNT = fs::kFSEventStreamEventFlagMount; + const UNMOUNT = fs::kFSEventStreamEventFlagUnmount; + const ITEM_CREATED = fs::kFSEventStreamEventFlagItemCreated; + const ITEM_REMOVED = fs::kFSEventStreamEventFlagItemRemoved; + const INODE_META_MOD = fs::kFSEventStreamEventFlagItemInodeMetaMod; + const ITEM_RENAMED = fs::kFSEventStreamEventFlagItemRenamed; + const ITEM_MODIFIED = fs::kFSEventStreamEventFlagItemModified; + const FINDER_INFO_MOD = fs::kFSEventStreamEventFlagItemFinderInfoMod; + const ITEM_CHANGE_OWNER = fs::kFSEventStreamEventFlagItemChangeOwner; + const ITEM_XATTR_MOD = fs::kFSEventStreamEventFlagItemXattrMod; + const IS_FILE = fs::kFSEventStreamEventFlagItemIsFile; + const IS_DIR = fs::kFSEventStreamEventFlagItemIsDir; + const IS_SYMLINK = fs::kFSEventStreamEventFlagItemIsSymlink; + const OWN_EVENT = fs::kFSEventStreamEventFlagOwnEvent; + const IS_HARDLINK = fs::kFSEventStreamEventFlagItemIsHardlink; + const IS_LAST_HARDLINK = fs::kFSEventStreamEventFlagItemIsLastHardlink; + const ITEM_CLONED = fs::kFSEventStreamEventFlagItemCloned; + } +} + +/// FSEvents-based `Watcher` implementation +pub struct FsEventWatcher { + paths:cf::CFMutableArrayRef, + since_when:fs::FSEventStreamEventId, + latency:cf::CFTimeInterval, + flags:fs::FSEventStreamCreateFlags, + event_handler:Arc>, + runloop:Option<(cf::CFRunLoopRef, thread::JoinHandle<()>)>, + recursive_info:HashMap, + device:Option, +} + +impl fmt::Debug for FsEventWatcher { + fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result { + f.debug_struct("FsEventWatcher") + .field("paths", &self.paths) + .field("since_when", &self.since_when) + .field("latency", &self.latency) + .field("flags", &self.flags) + .field("event_handler", &Arc::as_ptr(&self.event_handler)) + .field("runloop", &self.runloop) + .field("recursive_info", &self.recursive_info) + .finish() + } +} + +// CFMutableArrayRef is a type alias to *mut libc::c_void, so FsEventWatcher is +// not Send/Sync automatically. It's Send because the pointer is not used in +// other threads. +unsafe impl Send for FsEventWatcher {} + +// It's Sync because all methods that change the mutable state use `&mut self`. +unsafe impl Sync for FsEventWatcher {} + +fn translate_flags(flags:StreamFlags, precise:bool) -> Vec { + let mut evs = Vec::new(); + + // «Denotes a sentinel event sent to mark the end of the "historical" events + // sent as a result of specifying a `sinceWhen` value in the FSEvents.Create + // call that created this event stream. After invoking the client's callback + // with all the "historical" events that occurred before now, the client's + // callback will be invoked with an event where the HistoryDone flag is set. + // The client should ignore the path supplied in this callback.» + // — https://www.mbsplugins.eu/FSEventsNextEvent.shtml + // + // As a result, we just stop processing here and return an empty vec, which + // will ignore this completely and not emit any Events whatsoever. + if flags.contains(StreamFlags::HISTORY_DONE) { + return evs; + } + + // FSEvents provides two possible hints as to why events were dropped, + // however documentation on what those mean is scant, so we just pass them + // through in the info attr field. The intent is clear enough, and the + // additional information is provided if the user wants it. + if flags.contains(StreamFlags::MUST_SCAN_SUBDIRS) { + let e = Event::new(EventKind::Other).set_flag(Flag::Rescan); + evs.push(if flags.contains(StreamFlags::USER_DROPPED) { + e.set_info("rescan: user dropped") + } else if flags.contains(StreamFlags::KERNEL_DROPPED) { + e.set_info("rescan: kernel dropped") + } else { + e + }); + } + + // In imprecise mode, let's not even bother parsing the kind of the event + // except for the above very special events. + if !precise { + evs.push(Event::new(EventKind::Any)); + return evs; + } + + // This is most likely a rename or a removal. We assume rename but may want + // to figure out if it was a removal some way later (TODO). To denote the + // special nature of the event, we add an info string. + if flags.contains(StreamFlags::ROOT_CHANGED) { + evs.push( + Event::new(EventKind::Modify(ModifyKind::Name(RenameMode::From))) + .set_info("root changed"), + ); + } + + // A path was mounted at the event path; we treat that as a create. + if flags.contains(StreamFlags::MOUNT) { + evs.push(Event::new(EventKind::Create(CreateKind::Other)).set_info("mount")); + } + + // A path was unmounted at the event path; we treat that as a remove. + if flags.contains(StreamFlags::UNMOUNT) { + evs.push(Event::new(EventKind::Remove(RemoveKind::Other)).set_info("mount")); + } + + if flags.contains(StreamFlags::ITEM_CREATED) { + evs.push(if flags.contains(StreamFlags::IS_DIR) { + Event::new(EventKind::Create(CreateKind::Folder)) + } else if flags.contains(StreamFlags::IS_FILE) { + Event::new(EventKind::Create(CreateKind::File)) + } else { + let e = Event::new(EventKind::Create(CreateKind::Other)); + if flags.contains(StreamFlags::IS_SYMLINK) { + e.set_info("is: symlink") + } else if flags.contains(StreamFlags::IS_HARDLINK) { + e.set_info("is: hardlink") + } else if flags.contains(StreamFlags::ITEM_CLONED) { + e.set_info("is: clone") + } else { + Event::new(EventKind::Create(CreateKind::Any)) + } + }); + } + + if flags.contains(StreamFlags::ITEM_REMOVED) { + evs.push(if flags.contains(StreamFlags::IS_DIR) { + Event::new(EventKind::Remove(RemoveKind::Folder)) + } else if flags.contains(StreamFlags::IS_FILE) { + Event::new(EventKind::Remove(RemoveKind::File)) + } else { + let e = Event::new(EventKind::Remove(RemoveKind::Other)); + if flags.contains(StreamFlags::IS_SYMLINK) { + e.set_info("is: symlink") + } else if flags.contains(StreamFlags::IS_HARDLINK) { + e.set_info("is: hardlink") + } else if flags.contains(StreamFlags::ITEM_CLONED) { + e.set_info("is: clone") + } else { + Event::new(EventKind::Remove(RemoveKind::Any)) + } + }); + } + + // FSEvents provides no mechanism to associate the old and new sides of a + // rename event. + if flags.contains(StreamFlags::ITEM_RENAMED) { + evs.push(Event::new(EventKind::Modify(ModifyKind::Name(RenameMode::Any)))); + } + + // This is only described as "metadata changed", but it may be that it's + // only emitted for some more precise subset of events... if so, will need + // amending, but for now we have an Any-shaped bucket to put it in. + if flags.contains(StreamFlags::INODE_META_MOD) { + evs.push(Event::new(EventKind::Modify(ModifyKind::Metadata(MetadataKind::Any)))); + } + + if flags.contains(StreamFlags::FINDER_INFO_MOD) { + evs.push( + Event::new(EventKind::Modify(ModifyKind::Metadata(MetadataKind::Other))) + .set_info("meta: finder info"), + ); + } + + if flags.contains(StreamFlags::ITEM_CHANGE_OWNER) { + evs.push(Event::new(EventKind::Modify(ModifyKind::Metadata(MetadataKind::Ownership)))); + } + + if flags.contains(StreamFlags::ITEM_XATTR_MOD) { + evs.push(Event::new(EventKind::Modify(ModifyKind::Metadata(MetadataKind::Extended)))); + } + + // This is specifically described as a data change, which we take to mean + // is a content change. + if flags.contains(StreamFlags::ITEM_MODIFIED) { + evs.push(Event::new(EventKind::Modify(ModifyKind::Data(DataChange::Content)))); + } + + if flags.contains(StreamFlags::OWN_EVENT) { + for ev in &mut evs { + *ev = std::mem::take(ev).set_process_id(std::process::id()); + } + } + + evs +} + +struct StreamContextInfo { + event_handler:Arc>, + recursive_info:HashMap, +} + +// Free the context when the stream created by `FSEventStreamCreate` is +// released. +extern fn release_context(info:*const libc::c_void) { + // Safety: + // - The [documentation] for `FSEventStreamContext` states that `release` is + // only called when the stream is deallocated, so it is safe to convert `info` + // back into a box and drop it. + // + // [docs]: https://developer.apple.com/documentation/coreservices/fseventstreamcontext?language=objc + unsafe { + drop(Box::from_raw(info as *const StreamContextInfo as *mut StreamContextInfo)); + } +} + +extern { + /// Indicates whether the run loop is waiting for an event. + fn CFRunLoopIsWaiting(runloop:cf::CFRunLoopRef) -> cf::Boolean; +} + +// CoreFoundation false value +const FALSE:Boolean = 0x0; + +impl FsEventWatcher { + fn from_event_handler(event_handler:Arc>) -> Result { + Ok(FsEventWatcher { + paths:unsafe { + cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks) + }, + since_when:fs::kFSEventStreamEventIdSinceNow, + latency:0.01, + flags:fs::kFSEventStreamCreateFlagFileEvents + | fs::kFSEventStreamCreateFlagNoDefer + | fs::kFSEventStreamCreateFlagWatchRoot, + event_handler, + runloop:None, + recursive_info:HashMap::new(), + device:None, + }) + } + + fn watch_inner(&mut self, path:&Path, recursive_mode:RecursiveMode) -> Result<()> { + self.stop(); + let result = self.append_path(path, recursive_mode); + // ignore return error: may be empty path list + let _ = self.run(); + result + } + + fn unwatch_inner(&mut self, path:&Path) -> Result<()> { + self.stop(); + let result = self.remove_path(path); + // ignore return error: may be empty path list + let _ = self.run(); + result + } + + #[inline] + fn is_running(&self) -> bool { self.runloop.is_some() } + + fn stop(&mut self) { + if !self.is_running() { + return; + } + + if let Some((runloop, thread_handle)) = self.runloop.take() { + unsafe { + let runloop = runloop as *mut raw::c_void; + + while CFRunLoopIsWaiting(runloop) == 0 { + thread::yield_now(); + } + + cf::CFRunLoopStop(runloop); + } + + // Wait for the thread to shut down. + thread_handle.join().expect("thread to shut down"); + } + } + + fn remove_path(&mut self, path:&Path) -> Result<()> { + let str_path = path.to_str().unwrap(); + unsafe { + let mut err:cf::CFErrorRef = ptr::null_mut(); + let cf_path = cf::str_path_to_cfstring_ref(str_path, &mut err); + if cf_path.is_null() { + cf::CFRelease(err as cf::CFRef); + return Err(Error::watch_not_found().add_path(path.into())); + } + + let mut to_remove = Vec::new(); + for idx in 0..cf::CFArrayGetCount(self.paths) { + let item = cf::CFArrayGetValueAtIndex(self.paths, idx); + if cf::CFStringCompare(item, cf_path, cf::kCFCompareCaseInsensitive) + == cf::kCFCompareEqualTo + { + to_remove.push(idx); + } + } + + cf::CFRelease(cf_path); + + for idx in to_remove.iter().rev() { + cf::CFArrayRemoveValueAtIndex(self.paths, *idx); + } + } + let p = if let Ok(canonicalized_path) = path.canonicalize() { + canonicalized_path + } else { + path.to_owned() + }; + match self.recursive_info.remove(&p) { + Some(_) => Ok(()), + None => Err(Error::watch_not_found()), + } + } + + // https://github.com/thibaudgg/rb-fsevent/blob/master/ext/fsevent_watch/main.c + fn append_path(&mut self, path:&Path, recursive_mode:RecursiveMode) -> Result<()> { + let device = match std::fs::symlink_metadata(path) { + Err(e) if e.kind() == ErrorKind::NotFound => { + Err(Error::path_not_found().add_path(path.into())) + }, + Err(e) => Err(Error::io(e)), + Ok(metadata) => Ok(metadata.dev() as i32), + }?; + + if self.device.is_none() { + self.device = Some(device); + } else if self.device != Some(device) { + return Err(Error::generic("cannot watch multiple devices")); + } + let canonical_path = path.to_path_buf().canonicalize()?; + let str_path = path.to_str().unwrap(); + unsafe { + let mut err:cf::CFErrorRef = ptr::null_mut(); + let cf_path = cf::str_path_to_cfstring_ref(str_path, &mut err); + if cf_path.is_null() { + // Most likely the directory was deleted, or permissions changed, + // while the above code was running. + cf::CFRelease(err as cf::CFRef); + return Err(Error::path_not_found().add_path(path.into())); + } + cf::CFArrayAppendValue(self.paths, cf_path); + cf::CFRelease(cf_path); + } + let is_recursive = matches!(recursive_mode, RecursiveMode::Recursive); + self.recursive_info.insert(canonical_path, is_recursive); + Ok(()) + } + + fn run(&mut self) -> Result<()> { + if unsafe { cf::CFArrayGetCount(self.paths) } == 0 { + // TODO: Reconstruct and add paths to error + return Err(Error::path_not_found()); + } + let device = self.device.ok_or_else(|| Error::generic("no device set for stream"))?; + + // We need to associate the stream context with our callback in order to + // propagate events to the rest of the system. This will be owned by the + // stream, and will be freed when the stream is closed. This means we + // will leak the context if we panic before reaching + // `FSEventStreamRelease`. + let stream_context_info = Box::into_raw(Box::new(StreamContextInfo { + event_handler:self.event_handler.clone(), + recursive_info:self.recursive_info.clone(), + })); + + let stream_context = fs::FSEventStreamContext { + version:0, + info:stream_context_info as *mut libc::c_void, + retain:None, + release:Some(release_context), + copy_description:None, + }; + + let stream = unsafe { + fs::FSEventStreamCreateRelativeToDevice( + cf::kCFAllocatorDefault, + callback, + &stream_context, + device, + self.paths, + self.since_when, + self.latency, + self.flags, + ) + }; + + // Wrapper to help send CFRef types across threads. + struct CFSendWrapper(cf::CFRef); + + // Safety: + // - According to the Apple documentation, it's safe to move `CFRef`s across threads. + // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html + unsafe impl Send for CFSendWrapper {} + + // move into thread + let stream = CFSendWrapper(stream); + + // channel to pass runloop around + let (rl_tx, rl_rx) = std::sync::mpsc::channel(); + + let thread_handle = thread::Builder::new() + .name("notify-rs fsevents loop".to_string()) + .spawn(move || { + let _ = &stream; + let stream = stream.0; + + unsafe { + let cur_runloop = cf::CFRunLoopGetCurrent(); + + fs::FSEventStreamScheduleWithRunLoop( + stream, + cur_runloop, + cf::kCFRunLoopDefaultMode, + ); + if fs::FSEventStreamStart(stream) == FALSE { + panic!("FSEventStream failed to start"); + } + + // the calling to CFRunLoopRun will be terminated by CFRunLoopStop call in + // drop() + rl_tx + .send(CFSendWrapper(cur_runloop)) + .expect("Unable to send runloop to watcher"); + + cf::CFRunLoopRun(); + fs::FSEventStreamStop(stream); + fs::FSEventStreamInvalidate(stream); + fs::FSEventStreamRelease(stream); + } + })?; + // block until runloop has been sent + self.runloop = Some((rl_rx.recv().unwrap().0, thread_handle)); + + Ok(()) + } + + fn configure_raw_mode(&mut self, _config:Config, tx:Sender>) { + tx.send(Ok(false)).expect("configuration channel disconnect"); + } +} + +extern fn callback( + stream_ref:fs::FSEventStreamRef, + info:*mut libc::c_void, + num_events:libc::size_t, // size_t numEvents + event_paths:*mut libc::c_void, // void *eventPaths + event_flags:*const fs::FSEventStreamEventFlags, // const FSEventStreamEventFlags eventFlags[] + event_ids:*const fs::FSEventStreamEventId, // const FSEventStreamEventId eventIds[] +) { + unsafe { callback_impl(stream_ref, info, num_events, event_paths, event_flags, event_ids) } +} + +unsafe fn callback_impl( + _stream_ref:fs::FSEventStreamRef, + info:*mut libc::c_void, + num_events:libc::size_t, // size_t numEvents + event_paths:*mut libc::c_void, // void *eventPaths + event_flags:*const fs::FSEventStreamEventFlags, // const FSEventStreamEventFlags eventFlags[] + _event_ids:*const fs::FSEventStreamEventId, // const FSEventStreamEventId eventIds[] +) { + let event_paths = event_paths as *const *const libc::c_char; + let info = info as *const StreamContextInfo; + let event_handler = &(*info).event_handler; + + for p in 0..num_events { + let raw_path = CStr::from_ptr(*event_paths.add(p)).to_str().expect("Invalid UTF8 string."); + let path = PathBuf::from(format!("/{}", raw_path)); + + let flag = *event_flags.add(p); + let flag = StreamFlags::from_bits(flag).unwrap_or_else(|| { + panic!("Unable to decode StreamFlags: {}", flag); + }); + + let mut handle_event = false; + for (p, r) in &(*info).recursive_info { + if path.starts_with(p) { + if *r || &path == p { + handle_event = true; + break; + } else if let Some(parent_path) = path.parent() { + if parent_path == p { + handle_event = true; + break; + } + } + } + } + + if !handle_event { + continue; + } + + for ev in translate_flags(flag, true).into_iter() { + // TODO: precise + let ev = ev.add_path(path.clone()); + let mut event_handler = event_handler.lock().expect("lock not to be poisoned"); + event_handler.handle_event(Ok(ev)); + } + } +} + +impl Watcher for FsEventWatcher { + /// Create a new watcher. + fn new(event_handler:F, _config:Config) -> Result { + Self::from_event_handler(Arc::new(Mutex::new(event_handler))) + } + + fn watch(&mut self, path:&Path, recursive_mode:RecursiveMode) -> Result<()> { + self.watch_inner(path, recursive_mode) + } + + fn unwatch(&mut self, path:&Path) -> Result<()> { self.unwatch_inner(path) } + + fn configure(&mut self, config:Config) -> Result { + let (tx, rx) = std::sync::mpsc::channel(); + self.configure_raw_mode(config, tx); + rx.recv() + .map_err(|err| Error::generic(&format!("internal channel disconnect: {:?}", err)))? + } + + fn kind() -> WatcherKind { WatcherKind::Fsevent } +} + +impl Drop for FsEventWatcher { + fn drop(&mut self) { + self.stop(); + unsafe { + cf::CFRelease(self.paths); + } + } +} + +#[test] +fn test_fsevent_watcher_drop() { + use std::time::Duration; + + use super::*; + + let dir = tempfile::tempdir().unwrap(); + + let (tx, rx) = std::sync::mpsc::channel(); + + { + let mut watcher = FsEventWatcher::new(tx, Default::default()).unwrap(); + watcher.watch(dir.path(), RecursiveMode::Recursive).unwrap(); + thread::sleep(Duration::from_millis(2000)); + // println!("is running -> {}", watcher.is_running()); + + thread::sleep(Duration::from_millis(1000)); + watcher.unwatch(dir.path()).unwrap(); + // println!("is running -> {}", watcher.is_running()); + } + + thread::sleep(Duration::from_millis(1000)); + + for res in rx { + let e = res.unwrap(); + println!("debug => {:?} {:?}", e.kind, e.paths); + } + + println!("in test: {} works", file!()); +} + +#[test] +fn test_steam_context_info_send_and_sync() { + fn check_send() {} + check_send::(); +} diff --git a/crates/turborepo-filewatch/src/globwatcher.rs b/crates/turborepo-filewatch/Source/globwatcher.rs similarity index 100% rename from crates/turborepo-filewatch/src/globwatcher.rs rename to crates/turborepo-filewatch/Source/globwatcher.rs diff --git a/crates/turborepo-filewatch/src/hash_watcher.rs b/crates/turborepo-filewatch/Source/hash_watcher.rs similarity index 100% rename from crates/turborepo-filewatch/src/hash_watcher.rs rename to crates/turborepo-filewatch/Source/hash_watcher.rs diff --git a/crates/turborepo-filewatch/Source/lib.rs b/crates/turborepo-filewatch/Source/lib.rs new file mode 100644 index 0000000000000..3fb4e6dff9e28 --- /dev/null +++ b/crates/turborepo-filewatch/Source/lib.rs @@ -0,0 +1,928 @@ +//! File watching utilities for Turborepo. Includes a file watcher that is +//! designed to work across multiple platforms, with consistent behavior and +//! consistent ordering. +//! +//! Also includes watchers that take in file change events and produce derived +//! data like changed packages or the workspaces in a repository. +//! +//! ## Watcher Implementation +//! It's important to note that when implementing a watcher, you should aim to +//! make file change event processing as fast as possible. There should be +//! almost no slow code in the main event loop. Otherwise, the receiver will lag +//! behind, and return a `Lagged` event. +//! +//! A common pattern that we use to avoid lag is having a separate event thread +//! that processes events and accumulates them into a data structure, say a +//! `Trie` for changed files, or a `HashSet` for changed packages. From there, a +//! second thread is responsible for actually taking that accumulated data and +//! processing it. This second thread can do slower tasks like executing a run +//! or mapping files to changed packages. It can either be parked and awoken +//! using `tokio::sync::Notify` or it can run periodically using +//! `tokio::time::interval`. + +#![deny(clippy::all)] +#![allow(clippy::mutable_key_type)] +#![feature(assert_matches)] + +use std::{ + fmt::{Debug, Display}, + future::IntoFuture, + path::Path, + sync::Arc, + time::Duration, +}; + +// windows -> no recursive watch, watch ancestors +// linux -> recursive watch, watch ancestors +// macos -> custom watcher impl in fsevents, no recursive watch, no watching ancestors +#[cfg(target_os = "macos")] +use fsevent::FsEventWatcher; +#[cfg(any(feature = "manual_recursive_watch", feature = "watch_ancestors"))] +use notify::event::EventKind; +#[cfg(not(target_os = "macos"))] +use notify::{Config, RecommendedWatcher}; +use notify::{Event, EventHandler, RecursiveMode, Watcher}; +use thiserror::Error; +use tokio::sync::{broadcast, mpsc, watch::error::RecvError}; +use tracing::{debug, warn}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathRelation}; +#[cfg(feature = "manual_recursive_watch")] +use { + notify::{ + ErrorKind, + event::{CreateKind, EventAttributes}, + }, + std::io, + tracing::trace, + walkdir::WalkDir, +}; + +pub mod cookies; +mod debouncer; +#[cfg(target_os = "macos")] +mod fsevent; +pub mod globwatcher; +pub mod hash_watcher; +mod optional_watch; +pub mod package_watcher; +mod scm_resource; + +pub use optional_watch::OptionalWatch; + +#[cfg(not(target_os = "macos"))] +type Backend = RecommendedWatcher; +#[cfg(target_os = "macos")] +type Backend = FsEventWatcher; + +type EventResult = Result; + +#[derive(Debug, Error)] +pub enum WatchError { + #[error("filewatching backend error: {0}")] + Notify(#[from] notify::Error), + #[error("filewatching stopped")] + Stopped(#[from] std::sync::mpsc::RecvError), + #[error("enumerating recursive watch: {0}")] + WalkDir(#[from] walkdir::Error), + #[error("filewatching failed to start: {0}")] + Setup(String), +} + +// We want to broadcast the errors we get, but notify::Error does not implement +// Clone. We provide a wrapper that uses an Arc to implement Clone so that we +// can send errors on a broadcast channel. +#[derive(Clone, Debug, Error)] +pub struct NotifyError(Arc); + +impl From for NotifyError { + fn from(value:notify::Error) -> Self { Self(Arc::new(value)) } +} + +impl Display for NotifyError { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } +} + +pub struct FileSystemWatcher { + receiver:OptionalWatch>>, + // _exit_ch exists to trigger a close on the receiver when an instance + // of this struct is dropped. The task that is receiving events will exit, + // dropping the other sender for the broadcast channel, causing all receivers + // to be notified of a close. + _exit_ch:tokio::sync::oneshot::Sender<()>, + cookie_dir:AbsoluteSystemPathBuf, +} + +impl FileSystemWatcher { + pub fn new_with_default_cookie_dir(root:&AbsoluteSystemPath) -> Result { + // We already store logs in .turbo and recommend it be gitignore'd. + // Watchman uses .git, but we can't guarantee that git is present _or_ + // that the turbo root is the same as the git root. + Self::new(root, root.join_components(&[".turbo", "cookies"])) + } + + pub fn new( + root:&AbsoluteSystemPath, + cookie_dir:AbsoluteSystemPathBuf, + ) -> Result { + tracing::debug!("initing file-system watcher"); + + if root.relation_to_path(&cookie_dir) != PathRelation::Parent { + return Err(WatchError::Setup(format!( + "Invalid cookie directory: {} does not contain {}", + root, cookie_dir + ))); + } + + let (file_events_receiver_tx, file_events_receiver_lazy) = OptionalWatch::new(); + let (send_file_events, mut recv_file_events) = mpsc::channel(1024); + let (exit_ch, exit_signal) = tokio::sync::oneshot::channel(); + + tokio::task::spawn({ + let cookie_dir = cookie_dir.clone(); + let watch_root = root.to_owned(); + async move { + // this task never yields, so run it in the blocking threadpool + let watch_root_task = watch_root.clone(); + let cookie_dir_task = cookie_dir.clone(); + let task = tokio::task::spawn_blocking(move || { + setup_cookie_dir(&cookie_dir_task)?; + run_watcher(&watch_root_task, send_file_events) + }); + + let Ok(Ok(watcher)) = task.await else { + // if the watcher fails, just return. we don't set the event sender, and other + // services will never start + return; + }; + + // Ensure we are ready to receive new events, not events for existing state + debug!("waiting for initial filesystem cookie"); + if let Err(e) = wait_for_cookie(&cookie_dir, &mut recv_file_events).await { + // if we can't get a cookie here, we should not make the file + // watching available to downstream services + warn!("failed to wait for initial filesystem cookie: {}", e); + return; + } + debug!("filewatching ready"); + + let (sender, receiver) = broadcast::channel(1024); + + if file_events_receiver_tx.send(Some(receiver)).is_err() { + // if this fails, it means that nobody is listening (and + // nobody ever will) likely because the + // watcher has been dropped. We can just exit early. + tracing::debug!("no downstream listeners, exiting"); + return; + } + + watch_events(watcher, watch_root, recv_file_events, exit_signal, sender).await; + } + }); + + Ok(Self { receiver:file_events_receiver_lazy, _exit_ch:exit_ch, cookie_dir }) + } + + /// A convenience method around the sender watcher that waits for file + /// watching to be ready and then returns a handle to the file stream. + pub async fn subscribe( + &self, + ) -> Result>, RecvError> { + let mut receiver = self.receiver.clone(); + receiver.get().await.map(|r| r.resubscribe()) + } + + pub fn watch(&self) -> OptionalWatch>> { + self.receiver.clone() + } + + pub fn cookie_dir(&self) -> &AbsoluteSystemPath { &self.cookie_dir } +} + +fn setup_cookie_dir(cookie_dir:&AbsoluteSystemPath) -> Result<(), WatchError> { + // We need to ensure that the cookie directory is cleared out first so + // that we can start over with cookies. + tracing::debug!("setting up the cookie dir"); + + if cookie_dir.exists() { + cookie_dir.remove_dir_all().map_err(|e| { + WatchError::Setup(format!("failed to clear cookie dir {}: {}", cookie_dir, e)) + })?; + } + cookie_dir.create_dir_all().map_err(|e| { + WatchError::Setup(format!("failed to setup cookie dir {}: {}", cookie_dir, e)) + })?; + Ok(()) +} + +#[cfg(not(any(feature = "watch_ancestors", feature = "manual_recursive_watch")))] +async fn watch_events( + _watcher:Backend, + _watch_root:AbsoluteSystemPathBuf, + mut recv_file_events:mpsc::Receiver, + exit_signal:tokio::sync::oneshot::Receiver<()>, + broadcast_sender:broadcast::Sender>, +) { + let mut exit_signal = exit_signal; + 'outer: loop { + tokio::select! { + _ = &mut exit_signal => break 'outer, + Some(event) = recv_file_events.recv().into_future() => { + // we don't care if we fail to send, it just means no one is currently watching + let _ = broadcast_sender.send(event.map_err(NotifyError::from)); + } + } + } +} + +#[cfg(any(feature = "watch_ancestors", feature = "manual_recursive_watch"))] +async fn watch_events( + #[cfg(feature = "manual_recursive_watch")] mut watcher:Backend, + #[cfg(not(feature = "manual_recursive_watch"))] _watcher:Backend, + watch_root:AbsoluteSystemPathBuf, + mut recv_file_events:mpsc::Receiver, + exit_signal:tokio::sync::oneshot::Receiver<()>, + broadcast_sender:broadcast::Sender>, +) { + let mut exit_signal = exit_signal; + 'outer: loop { + tokio::select! { + _ = &mut exit_signal => break 'outer, + Some(event) = recv_file_events.recv().into_future() => { + match event { + Ok(mut event) => { + // Note that we need to filter relevant events + // before doing manual recursive watching so that + // we don't try to add watches to siblings of the + // directories on our path to the root. + #[cfg(feature = "watch_ancestors")] + filter_relevant(&watch_root, &mut event); + + #[cfg(feature = "manual_recursive_watch")] + { + if event.kind == EventKind::Create(CreateKind::Folder) { + for new_path in &event.paths { + if let Err(err) = manually_add_recursive_watches(new_path, &mut watcher, Some(&broadcast_sender)) { + match err { + WatchError::WalkDir(err) => { + // Likely the path no longer exists + debug!("encountered error watching filesystem {}", err); + continue; + }, + _ => { + warn!("encountered error watching filesystem {}", err); + break 'outer; + } + + } + } + } + } + } + // we don't care if we fail to send, it just means no one is currently watching + let _ = broadcast_sender.send(Ok(event)); + }, + Err(error) => { + // we don't care if we fail to send, it just means no one is currently watching + let _ = broadcast_sender.send(Err(NotifyError::from(error))); + } + } + } + } + } +} + +// Since we're manually watching the parent directories, we need +// to handle both getting irrelevant events and getting ancestor +// events that translate to events at the root. +#[cfg(feature = "watch_ancestors")] +fn filter_relevant(root:&AbsoluteSystemPath, event:&mut Event) { + // If path contains root && event type is modify, synthesize modify at root + let is_modify_existing = matches!(event.kind, EventKind::Remove(_) | EventKind::Modify(_)); + + event.paths.retain_mut(|path| { + let abs_path:&AbsoluteSystemPath = + path.as_path().try_into().expect("Non-absolute path from filewatching"); + match root.relation_to_path(abs_path) { + // An irrelevant path, probably from a non-recursive watch of a parent directory + PathRelation::Divergent => false, + // A path contained in the root + PathRelation::Parent => true, + PathRelation::Child => { + // If we're modifying something along the path to the + // root, move the event to the root + if is_modify_existing { + root.as_std_path().clone_into(path); + } + true + }, + } + }) +} + +#[cfg(feature = "watch_ancestors")] +fn is_permission_denied(result:&Result<(), notify::Error>) -> bool { + if let Err(err) = result { + if let notify::ErrorKind::Io(io_err) = &err.kind { + matches!(io_err.kind(), std::io::ErrorKind::PermissionDenied) + } else { + false + } + } else { + false + } +} + +#[cfg(feature = "watch_ancestors")] +fn watch_parents(root:&AbsoluteSystemPath, watcher:&mut Backend) -> Result<(), WatchError> { + let mut current = root; + while let Some(parent) = current.parent() { + current = parent; + let watch_result = watcher.watch(current.as_std_path(), RecursiveMode::NonRecursive); + if is_permission_denied(&watch_result) { + // It is expected we hit a permission denied error at some point. We won't + // get notifications if someone e.g. deletes all of /home + break; + } else { + watch_result?; + } + } + Ok(()) +} + +#[cfg(not(feature = "manual_recursive_watch"))] +fn watch_recursively(root:&AbsoluteSystemPath, watcher:&mut Backend) -> Result<(), WatchError> { + watcher.watch(root.as_std_path(), RecursiveMode::Recursive)?; + Ok(()) +} + +#[cfg(feature = "manual_recursive_watch")] +fn is_not_found(err:¬ify::Error) -> bool { + if let ErrorKind::Io(ref io_err) = err.kind { + io_err.kind() == io::ErrorKind::NotFound + } else { + false + } +} + +#[cfg(feature = "manual_recursive_watch")] +fn watch_recursively(root:&AbsoluteSystemPath, watcher:&mut Backend) -> Result<(), WatchError> { + // Don't synthesize initial events + manually_add_recursive_watches(root.as_std_path(), watcher, None) +} + +#[cfg(feature = "manual_recursive_watch")] +fn manually_add_recursive_watches( + root:&Path, + watcher:&mut Backend, + sender:Option<&broadcast::Sender>>, +) -> Result<(), WatchError> { + // Note that WalkDir yields the root as well as doing the walk. + for dir in WalkDir::new(root).follow_links(false).into_iter() { + let dir = dir?; + if dir.file_type().is_dir() { + trace!("manually watching {}", dir.path().display()); + match watcher.watch(dir.path(), RecursiveMode::NonRecursive) { + Ok(()) => {}, + // If we try to watch a non-existent path, we can just skip + // it. + Err(e) if is_not_found(&e) => continue, + Err(e) => return Err(e.into()), + } + } + if let Some(sender) = sender.as_ref() { + let create_kind = + if dir.file_type().is_dir() { CreateKind::Folder } else { CreateKind::File }; + let event = Event { + paths:vec![dir.path().to_owned()], + kind:EventKind::Create(create_kind), + attrs:EventAttributes::default(), + }; + // It's ok if we fail to send, it means we're shutting down + let _ = sender.send(Ok(event)); + } + } + Ok(()) +} + +fn run_watcher( + root:&AbsoluteSystemPath, + sender:mpsc::Sender, +) -> Result { + let mut watcher = make_watcher(move |res| { + let _ = sender.blocking_send(res); + })?; + + watch_recursively(root, &mut watcher)?; + + #[cfg(feature = "watch_ancestors")] + watch_parents(root, &mut watcher)?; + Ok(watcher) +} + +#[cfg(not(target_os = "macos"))] +fn make_watcher(event_handler:F) -> Result { + RecommendedWatcher::new(event_handler, Config::default()) +} + +#[cfg(target_os = "macos")] +fn make_watcher(event_handler:F) -> Result { + FsEventWatcher::new(event_handler, notify::Config::default()) +} + +/// wait_for_cookie performs a roundtrip through the filewatching mechanism. +/// This ensures that we are ready to receive *new* filesystem events, rather +/// than receiving events from existing state, which some backends can do. +async fn wait_for_cookie( + cookie_dir:&AbsoluteSystemPath, + recv:&mut mpsc::Receiver, +) -> Result<(), WatchError> { + // TODO: should this be passed in? Currently the caller guarantees that the + // directory is empty, but it could be the responsibility of the + // filewatcher... + let cookie_path = cookie_dir.join_component(".turbo-cookie"); + cookie_path.create_with_contents("cookie").map_err(|e| { + WatchError::Setup(format!("failed to write cookie to {}: {}", cookie_path, e)) + })?; + loop { + let event = tokio::time::timeout(Duration::from_millis(2000), recv.recv()) + .await + .map_err(|e| WatchError::Setup(format!("waiting for cookie timed out: {}", e)))? + .ok_or_else(|| { + WatchError::Setup( + "filewatching closed before cookie file was observed".to_string(), + ) + })? + .map_err(|err| { + WatchError::Setup(format!("initial watch encountered errors: {}", err)) + })?; + if event.paths.iter().any(|path| { + let path:&Path = path; + path == (&cookie_path as &AbsoluteSystemPath) + }) { + // We don't need to stop everything if we failed to remove the cookie file + // for some reason. We can warn about it though. + if let Err(e) = cookie_path.remove() { + warn!("failed to remove cookie file {}", e); + } + return Ok(()); + } + } +} + +#[cfg(test)] +mod test { + use std::{assert_matches::assert_matches, sync::atomic::AtomicUsize, time::Duration}; + + #[cfg(not(target_os = "windows"))] + use notify::event::RenameMode; + use notify::{Event, EventKind, event::ModifyKind}; + use tokio::sync::broadcast; + use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; + + use crate::{FileSystemWatcher, NotifyError}; + + fn temp_dir() -> (AbsoluteSystemPathBuf, tempfile::TempDir) { + let tmp = tempfile::tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap(); + (path, tmp) + } + + macro_rules! expect_filesystem_event { + ($recv:ident, $expected_path:expr, $pattern:pat) => { + 'outer: loop { + let event = tokio::time::timeout(Duration::from_millis(3000), $recv.recv()) + .await + .expect("timed out waiting for filesystem event") + .expect("sender was dropped") + .expect("filewatching error"); + for path in event.paths { + if path == (&$expected_path as &AbsoluteSystemPath) + && matches!(event.kind, $pattern) + { + break 'outer; + } + } + } + }; + } + + static WATCH_COUNT:AtomicUsize = AtomicUsize::new(0); + + async fn expect_watching( + recv:&mut broadcast::Receiver>, + dirs:&[&AbsoluteSystemPath], + ) { + for dir in dirs { + let count = WATCH_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + let filename = dir.join_component(format!("test-{}", count).as_str()); + filename.create_with_contents("hello").unwrap(); + + expect_filesystem_event!(recv, filename, EventKind::Create(_)); + } + } + + #[tokio::test] + async fn test_file_watching() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + let sibling_path = parent_path.join_component("sibling"); + sibling_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + let foo_path = child_path.join_component("foo"); + foo_path.create_with_contents("hello").unwrap(); + expect_filesystem_event!(recv, foo_path, EventKind::Create(_)); + + let deep_path = sibling_path.join_components(&["deep", "path"]); + deep_path.create_dir_all().unwrap(); + expect_filesystem_event!(recv, sibling_path.join_component("deep"), EventKind::Create(_)); + expect_filesystem_event!(recv, deep_path, EventKind::Create(_)); + expect_watching( + &mut recv, + &[ + &repo_root, + &parent_path, + &child_path, + &deep_path, + &sibling_path.join_component("deep"), + ], + ) + .await; + + let test_file_path = repo_root.join_component("test-file"); + test_file_path.create_with_contents("test contents").unwrap(); + expect_filesystem_event!(recv, test_file_path, EventKind::Create(_)); + + // TODO: implement default filtering (.git, node_modules) + } + + #[tokio::test] + async fn test_file_watching_subfolder_deletion() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + // Delete parent folder during file watching + parent_path.remove_dir_all().unwrap(); + expect_filesystem_event!(recv, parent_path, EventKind::Remove(_)); + + // Ensure we get events when creating file in deleted directory + child_path.create_dir_all().unwrap(); + expect_filesystem_event!(recv, parent_path, EventKind::Create(_)); + expect_filesystem_event!(recv, child_path, EventKind::Create(_)); + + let foo_path = child_path.join_component("foo"); + foo_path.create_with_contents("hello").unwrap(); + expect_filesystem_event!(recv, foo_path, EventKind::Create(_)); + // We cannot guarantee no more events, windows sends multiple delete + // events + } + + #[tokio::test] + async fn test_file_watching_root_deletion() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + repo_root.remove_dir_all().unwrap(); + expect_filesystem_event!(recv, repo_root, EventKind::Remove(_)); + } + + #[tokio::test] + async fn test_file_watching_subfolder_rename() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + let new_parent = repo_root.join_component("new_parent"); + parent_path.rename(&new_parent).unwrap(); + + expect_filesystem_event!(recv, new_parent, EventKind::Modify(ModifyKind::Name(_))); + } + + #[tokio::test] + async fn test_file_watching_root_rename() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (tmp_root, _tmp_repo_root) = temp_dir(); + let tmp_root = tmp_root.to_realpath().unwrap(); + let repo_root = tmp_root.join_component("repo_root"); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + let new_repo_root = repo_root.parent().unwrap().join_component("new_repo_root"); + repo_root.rename(&new_repo_root).unwrap(); + + expect_filesystem_event!(recv, repo_root, EventKind::Modify(ModifyKind::Name(_))); + } + + #[tokio::test] + async fn test_file_watching_symlink_create() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + // Create symlink during file watching + let symlink_path = repo_root.join_component("symlink"); + symlink_path.symlink_to_dir(child_path.as_str()).unwrap(); + expect_filesystem_event!(recv, symlink_path, EventKind::Create(_)); + + // we expect that events in the symlinked directory will be raised with the + // original path + let symlink_subfile = symlink_path.join_component("symlink_subfile"); + symlink_subfile.create_with_contents("hello").unwrap(); + let expected_subfile_path = child_path.join_component("symlink_subfile"); + expect_filesystem_event!(recv, expected_subfile_path, EventKind::Create(_)); + } + + #[tokio::test] + async fn test_file_watching_symlink_delete() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + // symlink -> parent/child + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + let symlink_path = repo_root.join_component("symlink"); + symlink_path.symlink_to_dir(child_path.as_str()).unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + // Delete symlink during file watching + // Note that on Windows, to remove a symlink to a directory + // remove_dir is required. + #[cfg(windows)] + symlink_path.remove_dir().unwrap(); + #[cfg(not(windows))] + symlink_path.remove().unwrap(); + expect_filesystem_event!(recv, symlink_path, EventKind::Remove(_)); + } + + #[tokio::test] + async fn test_file_watching_symlink_rename() { + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + // symlink -> parent/child + + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + let symlink_path = repo_root.join_component("symlink"); + symlink_path.symlink_to_dir(child_path.as_str()).unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + // Delete symlink during file watching + let new_symlink_path = repo_root.join_component("new_symlink"); + symlink_path.rename(&new_symlink_path).unwrap(); + expect_filesystem_event!(recv, new_symlink_path, EventKind::Modify(ModifyKind::Name(_))); + } + + // Watching a directory on windows locks it, so we cannot rename it. + // Since we are recursively watching parents, we also cannot rename parents. + // Note the contrast to the root of our watch, which we don't lock, + // but instead rely on watching the parent directory. This means we + // have permission to rename or delete the repo root, but not anything + // else in the path. + #[cfg(not(target_os = "windows"))] + #[tokio::test] + async fn test_file_watching_root_parent_rename() { + // Directory layout: + // repo_parent/ + // repo_root/ + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (tmp_root, _tmp_repo_root) = temp_dir(); + let tmp_root = tmp_root.to_realpath().unwrap().join_component("layer"); + let repo_root = tmp_root.join_components(&["repo_parent", "repo_root"]); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + let repo_parent = repo_root.parent().unwrap(); + let new_parent = tmp_root.join_component("new_parent"); + repo_parent.rename(&new_parent).unwrap(); + + expect_filesystem_event!( + recv, + repo_root, + EventKind::Modify(ModifyKind::Name(RenameMode::From)) + ); + } + + #[tokio::test] + async fn test_file_watching_root_parent_delete() { + // Directory layout: + // repo_parent/ + // repo_root/ + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + let (tmp_root, _tmp_repo_root) = temp_dir(); + let tmp_root = tmp_root.to_realpath().unwrap(); + let repo_root = tmp_root.join_components(&["repo_parent", "repo_root"]); + + repo_root.join_component(".git").create_dir_all().unwrap(); + repo_root + .join_components(&["node_modules", "some-dep"]) + .create_dir_all() + .unwrap(); + let parent_path = repo_root.join_component("parent"); + let child_path = parent_path.join_component("child"); + child_path.create_dir_all().unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let mut recv = watcher.subscribe().await.unwrap(); + expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; + + let repo_parent = repo_root.parent().unwrap(); + repo_parent.remove_dir_all().unwrap(); + expect_filesystem_event!( + recv, + repo_root, + EventKind::Modify(ModifyKind::Name(_)) | EventKind::Remove(_) + ); + } + + #[tokio::test] + async fn test_close() { + let (repo_root, _tmp_repo_root) = temp_dir(); + let repo_root = repo_root.to_realpath().unwrap(); + + let mut recv = { + // create and immediately drop the watcher, which should trigger the exit + // channel + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + watcher.subscribe().await.unwrap() + }; + + // There may be spurious events, but we should expect a close in short order + tokio::time::timeout(Duration::from_millis(100), async move { + loop { + if let Err(e) = recv.recv().await { + assert_matches!(e, broadcast::error::RecvError::Closed); + return; + } + } + }) + .await + .unwrap(); + } +} diff --git a/crates/turborepo-filewatch/src/optional_watch.rs b/crates/turborepo-filewatch/Source/optional_watch.rs similarity index 100% rename from crates/turborepo-filewatch/src/optional_watch.rs rename to crates/turborepo-filewatch/Source/optional_watch.rs diff --git a/crates/turborepo-filewatch/Source/package_watcher.rs b/crates/turborepo-filewatch/Source/package_watcher.rs new file mode 100644 index 0000000000000..068f0d26656ef --- /dev/null +++ b/crates/turborepo-filewatch/Source/package_watcher.rs @@ -0,0 +1,885 @@ +//! This module hosts the `PackageWatcher` type, which is used to watch the +//! filesystem for changes to packages. + +use std::{ + collections::HashMap, + path::Path, + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, + time::Duration, +}; + +use futures::FutureExt; +use notify::Event; +use thiserror::Error; +use tokio::{ + join, + select, + sync::{ + broadcast::{self, error::RecvError}, + mpsc, + oneshot, + watch, + }, +}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; +use turborepo_repository::{ + discovery::{ + DiscoveryResponse, + LocalPackageDiscoveryBuilder, + PackageDiscovery, + PackageDiscoveryBuilder, + WorkspaceData, + }, + package_manager::{self, PackageManager}, + workspaces::WorkspaceGlobs, +}; + +use crate::{ + NotifyError, + cookies::{CookieRegister, CookieWriter, CookiedOptionalWatch}, + debouncer::Debouncer, + optional_watch::OptionalWatch, +}; + +#[derive(Debug, Error)] +enum PackageWatcherProcessError { + #[error("filewatching not available, so package watching is not available")] + Filewatching(watch::error::RecvError), + #[error("filewatching closed, package watching no longer available")] + FilewatchingClosed(broadcast::error::RecvError), +} + +#[derive(Debug, Error)] +pub enum PackageWatchError { + #[error("package layout is in an invalid state {0}")] + InvalidState(String), + #[error("package layout is not available")] + Unavailable, +} + +// If we're in an invalid state, this will be an Err with a description of the +// reason. Typically we don't care though, as the user could be in the middle of +// making a change. +pub(crate) type DiscoveryData = Result; + +// Version is a type that exists to stamp an asynchronous hash computation +// with a version so that we can ignore completion of outdated hash +// computations. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +struct Version(usize); + +struct DiscoveryResult { + version:Version, + state:PackageState, +} + +/// Watches the filesystem for changes to packages and package managers. +pub struct PackageWatcher { + // _exit_ch exists to trigger a close on the receiver when an instance + // of this struct is dropped. The task that is receiving events will exit, + // dropping the other sender for the broadcast channel, causing all receivers + // to be notified of a close. + _exit_tx:oneshot::Sender<()>, + _handle:tokio::task::JoinHandle<()>, + package_discovery_lazy:CookiedOptionalWatch, +} + +impl PackageWatcher { + /// Creates a new package watcher whose current package data can be queried. + /// `backup_discovery` is used to perform the initial discovery of packages, + /// to populate the state before we can watch. + pub fn new( + root:AbsoluteSystemPathBuf, + recv:OptionalWatch>>, + cookie_writer:CookieWriter, + ) -> Result { + let (exit_tx, exit_rx) = oneshot::channel(); + let subscriber = Subscriber::new(root, cookie_writer)?; + let package_discovery_lazy = subscriber.package_discovery(); + let handle = tokio::spawn(subscriber.watch(exit_rx, recv)); + Ok(Self { _exit_tx:exit_tx, _handle:handle, package_discovery_lazy }) + } + + pub fn watch_discovery(&self) -> watch::Receiver> { + self.package_discovery_lazy.watch() + } + + pub async fn discover_packages(&self) -> Option> { + tracing::debug!("discovering packages using watcher implementation"); + + // this can either not have a value ready, or the sender has been dropped. in + // either case just report that the value is unavailable + let mut recv = self.package_discovery_lazy.clone(); + recv.get_immediate().await.map(|resp| { + resp.map_err(|_| PackageWatchError::Unavailable).and_then(|resp| { + match resp.to_owned() { + Ok(resp) => Ok(resp), + Err(error_reason) => Err(PackageWatchError::InvalidState(error_reason)), + } + }) + }) + } + + // if the event that either of the dependencies will never resolve, + // this will still return unavailable + pub async fn discover_packages_blocking(&self) -> Result { + let mut recv = self.package_discovery_lazy.clone(); + recv.get().await.map_err(|_| PackageWatchError::Unavailable).and_then(|resp| { + match resp.to_owned() { + Ok(resp) => Ok(resp), + Err(error_reason) => Err(PackageWatchError::InvalidState(error_reason)), + } + }) + } +} + +/// The underlying task that listens to file system events and updates the +/// internal package state. +struct Subscriber { + repo_root:AbsoluteSystemPathBuf, + // This is the list of paths that will trigger rediscovering everything. + invalidation_paths:Vec, + + package_discovery_tx:watch::Sender>, + package_discovery_lazy:CookiedOptionalWatch, + cookie_tx:CookieRegister, + next_version:AtomicUsize, +} + +/// PackageWatcher state. We either don't have a valid package manager, +/// don't have valid globs, or we have both a package manager and globs +/// and some maybe-empty set of workspaces. +#[derive(Debug)] +enum PackageState { + NoPackageManager(String), + InvalidGlobs(String), + ValidWorkspaces { + package_manager:PackageManager, + filter:Box, + workspaces:HashMap, + }, +} + +#[derive(Debug)] +enum State { + Pending { debouncer:Arc, version:Version }, + Ready(Box), +} + +// Because our package manager detection is coupled with the workspace globs, we +// need to recheck all workspaces any time any of these files change. A change +// in any of these might result in a different package manager being detected, +// or going from no package manager to some package manager. +const INVALIDATION_PATHS:&[&str] = &[ + "package.json", + "pnpm-workspace.yaml", + "pnpm-lock.yaml", + "package-lock.json", + "yarn.lock", + "bun.lockb", +]; + +impl Subscriber { + /// Creates a new instance of PackageDiscovery. This will start a task that + /// performs the initial discovery using the `backup_discovery` of your + /// choice, and then listens to file system events to keep the package + /// data up to date. + fn new( + repo_root:AbsoluteSystemPathBuf, + writer:CookieWriter, + ) -> Result { + let (package_discovery_tx, cookie_tx, package_discovery_lazy) = + CookiedOptionalWatch::new(writer); + let invalidation_paths = + INVALIDATION_PATHS.iter().map(|p| repo_root.join_component(p)).collect(); + Ok(Self { + repo_root, + invalidation_paths, + package_discovery_tx, + package_discovery_lazy, + cookie_tx, + next_version:AtomicUsize::new(0), + }) + } + + fn queue_rediscovery( + &self, + immediate:bool, + package_state_tx:mpsc::Sender, + ) -> (Version, Arc) { + // Every time we're queuing rediscovery, we know our state is no longer valid, + // so reset it for any downstream consumers. + self.reset_discovery_data(); + let version = Version(self.next_version.fetch_add(1, Ordering::SeqCst)); + let debouncer = if immediate { + Debouncer::new(Duration::from_millis(0)) + } else { + Debouncer::default() + }; + let debouncer = Arc::new(debouncer); + let debouncer_copy = debouncer.clone(); + let repo_root = self.repo_root.clone(); + tokio::task::spawn(async move { + debouncer_copy.debounce().await; + let state = discover_packages(repo_root).await; + let _ = package_state_tx.send(DiscoveryResult { version, state }).await; + }); + (version, debouncer) + } + + async fn watch_process( + mut self, + mut recv:OptionalWatch>>, + ) -> PackageWatcherProcessError { + tracing::debug!("starting package watcher"); + let mut recv = match recv.get().await { + Ok(r) => r.resubscribe(), + Err(e) => return PackageWatcherProcessError::Filewatching(e), + }; + + let (package_state_tx, mut package_state_rx) = mpsc::channel::(256); + + let (version, debouncer) = self.queue_rediscovery(true, package_state_tx.clone()); + + // state represents the current state of this process, and is expected to be + // updated in place by the various handler functions. + let mut state = State::Pending { debouncer, version }; + + tracing::debug!("package watcher ready {:?}", state); + loop { + select! { + Some(discovery_result) = package_state_rx.recv() => { + self.handle_discovery_result(discovery_result, &mut state); + }, + file_event = recv.recv() => { + match file_event { + Ok(Ok(event)) => self.handle_file_event(&mut state, &event, &package_state_tx).await, + // if we get an error, we need to re-discover the packages + Ok(Err(_)) => self.bump_or_queue_rediscovery(&mut state, &package_state_tx), + Err(e @ RecvError::Closed) => { + return PackageWatcherProcessError::FilewatchingClosed(e) + } + // if we end up lagging, warn and rediscover packages + Err(RecvError::Lagged(count)) => { + tracing::warn!("lagged behind {count} processing file watching events"); + self.bump_or_queue_rediscovery(&mut state, &package_state_tx); + } + } + } + } + tracing::trace!("package watcher state: {:?}", state); + } + } + + fn handle_discovery_result(&self, package_result:DiscoveryResult, state:&mut State) { + if let State::Pending { version, .. } = state { + // If this response matches an outstanding rediscovery request, write out the + // corresponding state to downstream consumers and update our state + // accordingly. + // + // Note that depending on events that we received since this request was queued, + // we may have a higher version number, at which point we would + // ignore this update, as we know it is stale. + if package_result.version == *version { + self.write_state(&package_result.state); + *state = State::Ready(Box::new(package_result.state)); + } + } + } + + async fn watch( + self, + exit_rx:oneshot::Receiver<()>, + recv:OptionalWatch>>, + ) { + let process = tokio::spawn(self.watch_process(recv)); + tokio::select! { + biased; + _ = exit_rx => { + tracing::debug!("exiting package watcher due to signal"); + }, + err = process => { + if let Ok(err) = err { + tracing::debug!("exiting package watcher due to {err}"); + } else { + tracing::debug!("package watcher process exited"); + } + } + } + } + + fn package_discovery(&self) -> CookiedOptionalWatch { + self.package_discovery_lazy.clone() + } + + fn path_invalidates_everything(&self, path:&Path) -> bool { + self.invalidation_paths + .iter() + .any(|invalidation_path| path.eq(invalidation_path as &AbsoluteSystemPath)) + } + + async fn handle_file_event( + &mut self, + state:&mut State, + file_event:&Event, + package_state_tx:&mpsc::Sender, + ) { + tracing::trace!("file event: {:?} {:?}", file_event.kind, file_event.paths); + + if file_event.paths.iter().any(|path| self.path_invalidates_everything(path)) { + // root package.json changed, rediscover everything + //*state = self.rediscover_and_write_state().await; + self.bump_or_queue_rediscovery(state, package_state_tx); + } else { + tracing::trace!("handling non-root package.json change"); + self.handle_workspace_changes(state, file_event, package_state_tx).await; + } + + tracing::trace!("updating the cookies"); + + // now that we have updated the state, we should bump the cookies so that + // people waiting on downstream cookie watchers can get the new state + self.cookie_tx.register( + &file_event + .paths + .iter() + .map(|p| AbsoluteSystemPath::from_std_path(p).expect("these paths are absolute")) + .collect::>(), + ); + } + + fn bump_or_queue_rediscovery( + &self, + state:&mut State, + package_state_tx:&mpsc::Sender, + ) { + if let State::Pending { debouncer, .. } = state { + if debouncer.bump() { + // We successfully bumped the debouncer, which was already pending, + // so a new discovery will happen shortly. + return; + } + } + // We either failed to bump the debouncer, or we don't have a rediscovery + // queued, but we need one. + let (version, debouncer) = self.queue_rediscovery(false, package_state_tx.clone()); + *state = State::Pending { debouncer, version } + } + + // checks if the file event contains any changes to package.json files, or + // directories that would map to a workspace. + async fn handle_workspace_changes( + &mut self, + state:&mut State, + file_event:&Event, + package_state_tx:&mpsc::Sender, + ) { + let package_state = match state { + State::Pending { .. } => { + // We can't assess this event until we have a valid package manager. To be safe, + // bump or queue another rediscovery, since this could race with the discovery + // in progress. + self.bump_or_queue_rediscovery(state, package_state_tx); + return; + }, + State::Ready(package_state) => package_state, + }; + + // If we don't have a valid package manager and workspace globs, nothing to be + // done here + let PackageState::ValidWorkspaces { ref filter, ref mut workspaces, .. } = **package_state + else { + return; + }; + + // here, we can only update if we have a valid package state + let mut changed = false; + // if a path is not a valid utf8 string, it is not a valid path, so ignore + for path in file_event.paths.iter().filter_map(|p| p.as_os_str().to_str()) { + let path_file = AbsoluteSystemPathBuf::new(path).expect("watched paths are absolute"); + let path_workspace:&AbsoluteSystemPath = + if path_file.file_name() == Some("package.json") { + // The file event is for a package.json file. Check if the parent is a workspace + let path_parent = + path_file.parent().expect("watched paths will not be at the root"); + if filter.target_is_workspace(&self.repo_root, path_parent).unwrap_or(false) { + path_parent + } else { + // irrelevant package.json file update, it's not in a directory + // matching workspace globs + continue; + } + } else if filter.target_is_workspace(&self.repo_root, &path_file).unwrap_or(false) { + // The file event is for a workspace directory itself + &path_file + } else { + // irrelevant file update, it's not a package.json file or a workspace directory + continue; + }; + + tracing::debug!("handling change to workspace {path_workspace}"); + let package_json = path_workspace.join_component("package.json"); + let turbo_json = path_workspace.join_component("turbo.json"); + + let (package_exists, turbo_exists) = join!( + // It's possible that an IO error could occur other than the file not existing, but + // we will treat it like the file doesn't exist. It's possible we'll need to + // revisit this, depending on what kind of errors occur. + tokio::fs::try_exists(&package_json).map(|result| result.unwrap_or(false)), + tokio::fs::try_exists(&turbo_json) + ); + + changed |= if package_exists { + workspaces + .insert( + path_workspace.to_owned(), + WorkspaceData { + package_json, + turbo_json:turbo_exists.unwrap_or_default().then_some(turbo_json), + }, + ) + .is_none() + } else { + workspaces.remove(path_workspace).is_some() + } + } + + if changed { + self.write_state(package_state); + } + } + + fn reset_discovery_data(&self) { + self.package_discovery_tx.send_if_modified(|existing| { + if existing.is_some() { + *existing = None; + true + } else { + false + } + }); + } + + fn write_state(&self, state:&PackageState) { + match state { + PackageState::NoPackageManager(e) | PackageState::InvalidGlobs(e) => { + self.package_discovery_tx.send_if_modified(|existing| { + let error_msg = e.to_string(); + match existing { + Some(Err(existing_error)) if *existing_error == error_msg => false, + Some(_) | None => { + *existing = Some(Err(error_msg)); + true + }, + } + }); + }, + PackageState::ValidWorkspaces { package_manager, workspaces, .. } => { + let resp = DiscoveryResponse { + package_manager:package_manager.clone(), + workspaces:workspaces.values().cloned().collect(), + }; + // Note that we could implement PartialEq for DiscoveryResponse, but we + // would need to sort the workspace data. + let _ = self.package_discovery_tx.send(Some(Ok(resp))); + }, + } + } +} + +async fn discover_packages(repo_root:AbsoluteSystemPathBuf) -> PackageState { + // If we're rediscovering everything, we need to rediscover the package manager. + // It may have changed if a lockfile changed or package.json changed. + let discovery = match LocalPackageDiscoveryBuilder::new(repo_root.clone(), None, None).build() { + Ok(discovery) => discovery, + Err(e) => return PackageState::NoPackageManager(e.to_string()), + }; + let initial_discovery = match discovery.discover_packages().await { + Ok(discovery) => discovery, + Err(e) => { + tracing::debug!("failed to rediscover packages: {}", e); + return PackageState::NoPackageManager(e.to_string()); + }, + }; + + tracing::debug!("rediscovered packages: {:?}", initial_discovery); + let filter = match initial_discovery.package_manager.get_workspace_globs(&repo_root) { + Ok(filter) => filter, + Err(e) => { + tracing::debug!("failed to get workspace globs: {}", e); + return PackageState::InvalidGlobs(e.to_string()); + }, + }; + + let workspaces = initial_discovery + .workspaces + .into_iter() + .map(|p| (p.package_json.parent().expect("non-root").to_owned(), p)) + .collect::>(); + PackageState::ValidWorkspaces { + package_manager:initial_discovery.package_manager, + filter:Box::new(filter), + workspaces, + } +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use turbopath::AbsoluteSystemPathBuf; + use turborepo_repository::{discovery::WorkspaceData, package_manager::PackageManager}; + + use crate::{FileSystemWatcher, cookies::CookieWriter, package_watcher::PackageWatcher}; + + #[tokio::test] + #[tracing_test::traced_test] + async fn subscriber_test() { + let tmp = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap().to_realpath().unwrap(); + + let package_data = vec![ + WorkspaceData { + package_json:repo_root.join_components(&["packages", "foo", "package.json"]), + turbo_json:None, + }, + WorkspaceData { + package_json:repo_root.join_components(&["packages", "bar", "package.json"]), + turbo_json:None, + }, + ]; + + // create folders and files + for data in &package_data { + data.package_json.ensure_dir().unwrap(); + let name = data.package_json.parent().unwrap().file_name().unwrap(); + data.package_json + .create_with_contents(format!("{{\"name\": \"{name}\"}}")) + .unwrap(); + } + repo_root.join_component("package-lock.json").create_with_contents("").unwrap(); + + // write workspaces to root + repo_root + .join_component("package.json") + .create_with_contents( + r#"{"workspaces":["packages/*"], "packageManager": "npm@10.0.0"}"#, + ) + .unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let recv = watcher.watch(); + let cookie_writer = + CookieWriter::new(watcher.cookie_dir(), Duration::from_millis(100), recv.clone()); + + let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); + + let mut data = package_watcher.discover_packages_blocking().await.unwrap(); + data.workspaces.sort_by_key(|workspace| workspace.package_json.clone()); + assert_eq!( + data.workspaces, + vec![ + WorkspaceData { + package_json:repo_root.join_components(&["packages", "bar", "package.json",]), + turbo_json:None, + }, + WorkspaceData { + package_json:repo_root.join_components(&["packages", "foo", "package.json",]), + turbo_json:None, + }, + ] + ); + + tracing::info!("removing subpackage"); + + // delete package.json in foo + repo_root + .join_components(&["packages", "foo", "package.json"]) + .remove_file() + .unwrap(); + + let mut data = package_watcher.discover_packages_blocking().await.unwrap(); + data.workspaces.sort_by_key(|workspace| workspace.package_json.clone()); + assert_eq!( + data.workspaces, + vec![WorkspaceData { + package_json:repo_root.join_components(&["packages", "bar", "package.json"]), + turbo_json:None, + }] + ); + + // move package bar + repo_root + .join_components(&["packages", "bar"]) + .rename(&repo_root.join_component("bar")) + .unwrap(); + + let mut data = package_watcher.discover_packages_blocking().await.unwrap(); + data.workspaces.sort_by_key(|workspace| workspace.package_json.clone()); + assert_eq!(data.workspaces, vec![]); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn subscriber_update_workspaces() { + let tmp = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap().to_realpath().unwrap(); + + let package_data = vec![ + WorkspaceData { + package_json:repo_root + .join_component("packages") + .join_component("foo") + .join_component("package.json"), + turbo_json:None, + }, + WorkspaceData { + package_json:repo_root + .join_component("packages2") + .join_component("bar") + .join_component("package.json"), + turbo_json:None, + }, + ]; + + // create folders and files + for data in &package_data { + data.package_json.ensure_dir().unwrap(); + let name = data.package_json.parent().unwrap().file_name().unwrap(); + data.package_json + .create_with_contents(format!("{{\"name\": \"{name}\"}}")) + .unwrap(); + } + repo_root.join_component("package-lock.json").create_with_contents("").unwrap(); + + // write workspaces to root + repo_root + .join_component("package.json") + .create_with_contents( + r#"{"workspaces":["packages/*", "packages2/*"], "packageManager": "npm@10.0.0"}"#, + ) + .unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let recv = watcher.watch(); + let cookie_writer = + CookieWriter::new(watcher.cookie_dir(), Duration::from_millis(100), recv.clone()); + + let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); + + let mut data = package_watcher.discover_packages_blocking().await.unwrap(); + data.workspaces.sort_by_key(|workspace| workspace.package_json.clone()); + + assert_eq!( + data.workspaces, + vec![ + WorkspaceData { + package_json:repo_root + .join_component("packages") + .join_component("foo") + .join_component("package.json"), + turbo_json:None, + }, + WorkspaceData { + package_json:repo_root + .join_component("packages2") + .join_component("bar") + .join_component("package.json"), + turbo_json:None, + }, + ] + ); + + // update workspaces to no longer cover packages2 + repo_root + .join_component("package.json") + .create_with_contents( + r#"{"workspaces":["packages/*"], "packageManager": "npm@10.0.0"}"#, + ) + .unwrap(); + + let mut data = package_watcher.discover_packages_blocking().await.unwrap(); + data.workspaces.sort_by_key(|workspace| workspace.package_json.clone()); + + assert_eq!( + data.workspaces, + vec![WorkspaceData { + package_json:repo_root + .join_component("packages") + .join_component("foo") + .join_component("package.json"), + turbo_json:None, + }] + ); + + // move the packages2 workspace into package + repo_root + .join_components(&["packages2", "bar"]) + .rename(&repo_root.join_components(&["packages", "bar"])) + .unwrap(); + let mut data = package_watcher.discover_packages_blocking().await.unwrap(); + data.workspaces.sort_by_key(|workspace| workspace.package_json.clone()); + assert_eq!( + data.workspaces, + vec![ + WorkspaceData { + package_json:repo_root + .join_component("packages") + .join_component("bar") + .join_component("package.json"), + turbo_json:None, + }, + WorkspaceData { + package_json:repo_root + .join_component("packages") + .join_component("foo") + .join_component("package.json"), + turbo_json:None, + }, + ] + ); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn pnpm_invalid_states_test() { + let tmp = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap().to_realpath().unwrap(); + + let workspaces_path = repo_root.join_component("pnpm-workspace.yaml"); + // Currently we require valid state to start the daemon + let root_package_json_path = repo_root.join_component("package.json"); + // Start with no workspace glob + root_package_json_path + .create_with_contents(r#"{"packageManager": "pnpm@10.2.1"}"#) + .unwrap(); + repo_root.join_component("pnpm-lock.yaml").create_with_contents("").unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let recv = watcher.watch(); + let cookie_writer = + CookieWriter::new(watcher.cookie_dir(), Duration::from_millis(100), recv.clone()); + + let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); + + package_watcher.discover_packages_blocking().await.unwrap_err(); + + workspaces_path.create_with_contents(r#"packages: ["foo/*"]"#).unwrap(); + + let resp = package_watcher.discover_packages_blocking().await.unwrap(); + assert_eq!(resp.package_manager, PackageManager::Pnpm); + + // Remove workspaces file, verify we get an error + workspaces_path.remove_file().unwrap(); + package_watcher.discover_packages_blocking().await.unwrap_err(); + + // // Create an invalid workspace glob + workspaces_path.create_with_contents(r#"packages: ["foo/***"]"#).unwrap(); + + // we should still get an error since we don't have a valid glob + package_watcher.discover_packages_blocking().await.unwrap_err(); + + // Set it back to valid, ensure we recover + workspaces_path.create_with_contents(r#"packages: ["foo/*"]"#).unwrap(); + + let resp = package_watcher.discover_packages_blocking().await.unwrap(); + assert_eq!(resp.package_manager, PackageManager::Pnpm); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn npm_invalid_states_test() { + let tmp = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap().to_realpath().unwrap(); + + // Currently we require valid state to start the daemon + let root_package_json_path = repo_root.join_component("package.json"); + // Start with no workspace glob + root_package_json_path + .create_with_contents(r#"{"packageManager": "npm@7.0.0"}"#) + .unwrap(); + repo_root.join_component("package-lock.json").create_with_contents("").unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let recv = watcher.watch(); + let cookie_writer = + CookieWriter::new(watcher.cookie_dir(), Duration::from_millis(100), recv.clone()); + + let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); + // expect an error, we don't have a workspaces glob + package_watcher.discover_packages_blocking().await.unwrap_err(); + + root_package_json_path + .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/*"]}"#) + .unwrap(); + + let resp = package_watcher.discover_packages_blocking().await.unwrap(); + assert_eq!(resp.package_manager, PackageManager::Npm); + + // Remove workspaces file, verify we get an error + root_package_json_path.remove_file().unwrap(); + package_watcher.discover_packages_blocking().await.unwrap_err(); + + // Create an invalid workspace glob + root_package_json_path + .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/***"]}"#) + .unwrap(); + + // We expect an error due to invalid workspace glob + package_watcher.discover_packages_blocking().await.unwrap_err(); + + // Set it back to valid, ensure we recover + root_package_json_path + .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/*"]}"#) + .unwrap(); + let resp = package_watcher.discover_packages_blocking().await.unwrap(); + assert_eq!(resp.package_manager, PackageManager::Npm); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn test_change_package_manager() { + let tmp = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap().to_realpath().unwrap(); + + let workspaces_path = repo_root.join_component("pnpm-workspace.yaml"); + workspaces_path.create_with_contents(r#"packages: ["foo/*"]"#).unwrap(); + // Currently we require valid state to start the daemon + let root_package_json_path = repo_root.join_component("package.json"); + // Start with no workspace glob + root_package_json_path + .create_with_contents(r#"{"packageManager": "pnpm@10.2.1"}"#) + .unwrap(); + let pnpm_lock_file = repo_root.join_component("pnpm-lock.yaml"); + pnpm_lock_file.create_with_contents("").unwrap(); + + let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); + let recv = watcher.watch(); + let cookie_writer = + CookieWriter::new(watcher.cookie_dir(), Duration::from_millis(100), recv.clone()); + + let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); + + let resp = package_watcher.discover_packages_blocking().await.unwrap(); + assert_eq!(resp.package_manager, PackageManager::Pnpm); + + workspaces_path.remove_file().unwrap(); + // No more workspaces file, verify we're in an invalid state + package_watcher.discover_packages_blocking().await.unwrap_err(); + + let npm_lock_file = repo_root.join_component("package-lock.json"); + npm_lock_file.create_with_contents("").unwrap(); + // now we have an npm lockfile, but we don't have workspaces. Still invalid + package_watcher.discover_packages_blocking().await.unwrap_err(); + + // update package.json to complete the transition + root_package_json_path + .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/*"]}"#) + .unwrap(); + let resp = package_watcher.discover_packages_blocking().await.unwrap(); + assert_eq!(resp.package_manager, PackageManager::Npm); + } +} diff --git a/crates/turborepo-filewatch/src/scm_resource.rs b/crates/turborepo-filewatch/Source/scm_resource.rs similarity index 100% rename from crates/turborepo-filewatch/src/scm_resource.rs rename to crates/turborepo-filewatch/Source/scm_resource.rs diff --git a/crates/turborepo-filewatch/build.rs b/crates/turborepo-filewatch/build.rs index b482e2c985df4..5e6170d4daddf 100644 --- a/crates/turborepo-filewatch/build.rs +++ b/crates/turborepo-filewatch/build.rs @@ -1,11 +1,11 @@ fn main() { - #[cfg(target_os = "linux")] - { - println!("cargo:rustc-cfg=feature=\"manual_recursive_watch\""); - println!("cargo:rustc-cfg=feature=\"watch_ancestors\""); - } - #[cfg(target_os = "windows")] - { - println!("cargo:rustc-cfg=feature=\"watch_ancestors\""); - } + #[cfg(target_os = "linux")] + { + println!("cargo:rustc-cfg=feature=\"manual_recursive_watch\""); + println!("cargo:rustc-cfg=feature=\"watch_ancestors\""); + } + #[cfg(target_os = "windows")] + { + println!("cargo:rustc-cfg=feature=\"watch_ancestors\""); + } } diff --git a/crates/turborepo-filewatch/src/cookies.rs b/crates/turborepo-filewatch/src/cookies.rs deleted file mode 100644 index a1a1c38473bb4..0000000000000 --- a/crates/turborepo-filewatch/src/cookies.rs +++ /dev/null @@ -1,708 +0,0 @@ -//! Cookies. -//! -//! They are the file watcher's way of synchronizing file system events. They -//! are files that are added to the file system that are named with the format -//! `[id].cookie`, where `[id]` is an increasing serial number, e.g. -//! `1.cookie`, `2.cookie`, and so on. The daemon can then watch for the -//! file creation event for this cookie file. Once it sees this event, -//! the daemon knows that the file system events are up to date and we -//! won't get any stale events. -//! -//! Here's the `CookieWriter` flow: -//! - `CookieWriter` spins up a `watch_for_cookie_requests` task and creates a -//! `cookie_requests` mpsc channel to send a cookie request to that task. The -//! cookie request consists of a oneshot `Sender` that the task can use to -//! send back the serial number. -//! - The `watch_for_cookie_requests` task watches for cookie requests on -//! `cookie_requests_rx`. When one occurs, it creates the cookie file and -//! bumps the serial. It then sends the serial back using the `Sender` -//! - When `CookieWriter::cookie_request` is called, it sends the cookie request -//! to the `watch_for_cookie_request` channel and then waits for the serial as -//! a response (with a timeout). Upon getting the serial, a `CookiedRequest` -//! gets returned with the serial number attached. -//! -//! And here's the `CookieWatcher` flow: -//! - `GlobWatcher` creates a `CookieWatcher`. -//! - `GlobWatcher` gets queries about globs that are wrapped in -//! `CookiedRequest`. It passes these requests to -//! `CookieWatcher::check_request` -//! - If the serial number attached to `CookiedRequest` has already been seen, -//! `CookieWatcher::check_request` returns the inner query immediately. -//! Otherwise, it gets stored in `CookieWatcher`. -//! - `GlobWatcher` waits for file system events on `recv`. When it gets an -//! event, it passes the event to `CookieWatcher::pop_ready_requests`. If this -//! event is indeed a cookie event, we return all of the requests that are now -//! allowed to be processed (i.e. their serial number is now less than or -//! equal to the latest seen serial). - -use std::{collections::BinaryHeap, fs::OpenOptions, time::Duration}; - -use futures::FutureExt; -use notify::EventKind; -use thiserror::Error; -use tokio::{ - sync::{broadcast, mpsc, oneshot, watch}, - time::error::Elapsed, -}; -use tracing::trace; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathRelation}; - -use crate::{optional_watch::SomeRef, NotifyError, OptionalWatch}; - -#[derive(Debug, Error)] -pub enum CookieError { - #[error("cookie timeout expired")] - Timeout(#[from] Elapsed), - #[error("failed to receiver cookie notification: {0}")] - RecvError(#[from] oneshot::error::RecvError), - #[error("failed to send cookie file request: {0}")] - SendError(#[from] mpsc::error::SendError>>), - #[error("failed to write cookie file at {path}: {io_err}")] - IO { - io_err: std::io::Error, - path: AbsoluteSystemPathBuf, - }, - #[error("cookie queue is not available")] - Unavailable(#[from] watch::error::RecvError), -} - -/// CookieWriter is responsible for assigning filesystem cookies to a request -/// for a downstream, filewatching-backed service. -#[derive(Clone)] -pub struct CookieWriter { - // Where we put the cookie files, usually `/.turbo/cookies` - cookie_root: AbsoluteSystemPathBuf, - timeout: Duration, - cookie_request_sender_lazy: - OptionalWatch>>>, - // _exit_ch exists to trigger a close on the receiver when all instances - // of this struct are dropped. The task that is receiving events will exit, - // dropping the other sender for the broadcast channel, causing all receivers - // to be notified of a close. - _exit_ch: mpsc::Sender<()>, -} - -/// A request that can only be processed after the `serial` has been seen by the -/// `CookieWatcher`. -#[derive(Debug)] -pub struct CookiedRequest { - request: T, - serial: usize, -} - -impl PartialEq for CookiedRequest { - fn eq(&self, other: &Self) -> bool { - self.serial == other.serial - } -} - -impl Eq for CookiedRequest {} - -impl PartialOrd for CookiedRequest { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for CookiedRequest { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - // Lower serials should be sorted higher, since the heap pops the highest values - // first - other.serial.cmp(&self.serial) - } -} - -/// CookieWatcher is used by downstream filewatching-backed services to -/// know when it is safe to handle a particular request. -pub(crate) struct CookieWatcher { - // Where we expect to find the cookie files, usually `/.turbo/cookies` - cookie_root: AbsoluteSystemPathBuf, - // We don't necessarily get requests in serial-order, but we want to keep them - // in order so we don't have to scan all requests every time we get a new cookie. - pending_requests: BinaryHeap>, - latest: usize, -} - -impl CookieWatcher { - pub(crate) fn new(cookie_root: AbsoluteSystemPathBuf) -> Self { - Self { - cookie_root, - pending_requests: BinaryHeap::new(), - latest: 0, - } - } - - /// Check if this request can be handled immediately. If so, return it. If - /// not, queue it - pub(crate) fn check_request(&mut self, cookied_request: CookiedRequest) -> Option { - if cookied_request.serial <= self.latest { - // We've already seen the cookie for this request, handle it now - Some(cookied_request.request) - } else { - // We haven't seen the cookie for this request yet, hold onto it - self.pending_requests.push(cookied_request); - None - } - } - - /// If this is a cookie file, pop all requests that are ready to be handled. - /// The returned vector might be empty if this was a cookie file but we - /// don't have any requests that are ready to be handled. None is - /// returned if this is not a cookie file being created. - pub(crate) fn pop_ready_requests( - &mut self, - event_kind: EventKind, - path: &AbsoluteSystemPath, - ) -> Option> { - if !matches!(event_kind, EventKind::Create(_)) { - return None; - } - if let Some(serial) = serial_for_path(&self.cookie_root, path) { - self.latest = serial; - let mut ready_requests = Vec::new(); - while let Some(cookied_request) = self.pending_requests.pop() { - if cookied_request.serial <= serial { - ready_requests.push(cookied_request.request); - } else { - self.pending_requests.push(cookied_request); - break; - } - } - Some(ready_requests) - } else { - None - } - } -} - -fn serial_for_path(root: &AbsoluteSystemPath, path: &AbsoluteSystemPath) -> Option { - if root.relation_to_path(path) == PathRelation::Parent { - let filename = path.file_name()?; - filename.strip_suffix(".cookie")?.parse().ok() - } else { - None - } -} - -impl CookieWriter { - #[cfg(test)] - pub fn new_with_default_cookie_dir( - repo_root: &AbsoluteSystemPath, - timeout: Duration, - recv: OptionalWatch>>, - ) -> Self { - let cookie_root = repo_root.join_components(&[".turbo", "cookies"]); - Self::new(&cookie_root, timeout, recv) - } - - pub fn new( - cookie_root: &AbsoluteSystemPath, - timeout: Duration, - mut recv: OptionalWatch>>, - ) -> Self { - let (cookie_request_sender_tx, cookie_request_sender_lazy) = OptionalWatch::new(); - let (exit_ch, exit_signal) = mpsc::channel(16); - tokio::spawn({ - let root = cookie_root.to_owned(); - async move { - if recv.get().await.is_err() { - // here we need to wait for confirmation that the watching end is ready - // before we start sending requests. this has the side effect of not - // enabling the cookie writing mechanism until the watcher is ready - return; - } - - let (cookie_requests_tx, cookie_requests_rx) = mpsc::channel(16); - - if cookie_request_sender_tx - .send(Some(cookie_requests_tx)) - .is_err() - { - // the receiver has already been dropped - tracing::debug!("nobody listening for cookie requests, exiting"); - return; - }; - watch_for_cookie_file_requests(root.to_owned(), cookie_requests_rx, exit_signal) - .await; - } - }); - Self { - cookie_root: cookie_root.to_owned(), - timeout, - cookie_request_sender_lazy, - _exit_ch: exit_ch, - } - } - - pub(crate) fn root(&self) -> &AbsoluteSystemPath { - &self.cookie_root - } - - /// Sends a request to make a cookie file to the - /// `watch_for_cookie_file_requests` task. Waits on a response from the - /// task, and returns a `CookiedRequest` with the expected serial - /// number. - pub(crate) async fn cookie_request( - &self, - request: T, - ) -> Result, CookieError> { - // we need to write the cookie from a single task so as to serialize them - tokio::time::timeout(self.timeout, self.cookie_request_inner(request, None)).await? - } - - /// Internal services may want to wait for the cookie - /// system to be set up, before issuing a timeout for the - /// cookie request. - pub(crate) async fn initialized_cookie_request( - &self, - request: T, - ) -> Result, CookieError> { - self.cookie_request_inner(request, Some(self.timeout)).await - } - - async fn cookie_request_inner( - &self, - request: T, - timeout: Option, - ) -> Result, CookieError> { - let (resp_tx, resp_rx) = oneshot::channel(); - let mut cookie_request_sender_lazy = self.cookie_request_sender_lazy.clone(); - let cookie_request_sender_lazy = cookie_request_sender_lazy - .get() - .await - .map(|s| s.to_owned())?; - cookie_request_sender_lazy.send(resp_tx).await?; - let serial = match timeout { - Some(timeout) => { - let resp_rx = tokio::time::timeout(timeout, resp_rx).await??; - resp_rx? - } - None => resp_rx.await??, - }; - Ok(CookiedRequest { request, serial }) - } -} - -async fn watch_for_cookie_file_requests( - root: AbsoluteSystemPathBuf, - mut cookie_requests: mpsc::Receiver>>, - mut exit_signal: mpsc::Receiver<()>, -) { - let mut serial: usize = 0; - loop { - tokio::select! { - biased; - _ = exit_signal.recv() => return, - req = cookie_requests.recv() => handle_cookie_file_request(&root, &mut serial, req), - } - } -} - -fn handle_cookie_file_request( - root: &AbsoluteSystemPath, - serial: &mut usize, - req: Option>>, -) { - if let Some(req) = req { - *serial += 1; - let cookie_path = root.join_component(&format!("{}.cookie", serial)); - let mut opts = OpenOptions::new(); - opts.truncate(true).create(true).write(true); - let result = { - // dropping the resulting file closes the handle - trace!("writing cookie {}", cookie_path); - cookie_path - .ensure_dir() - .and_then(|_| cookie_path.open_with_options(opts)) - .map_err(|io_err| CookieError::IO { - io_err, - path: cookie_path.clone(), - }) - }; - let result = result.map(|_| *serial); - // We don't care if the client has timed out and gone away - let _ = req.send(result); - } -} - -/// a lightweight wrapper around OptionalWatch that embeds cookie ids into the -/// get call. for requests that require cookies (ie, waiting for filesystem -/// flushes) then a cookie watch is ideal -pub struct CookiedOptionalWatch { - value: watch::Receiver>, - cookie_index: watch::Receiver, - cookie_writer: CookieWriter, - parent: P, -} - -impl Clone for CookiedOptionalWatch { - fn clone(&self) -> Self { - Self { - value: self.value.clone(), - cookie_index: self.cookie_index.clone(), - cookie_writer: self.cookie_writer.clone(), - parent: self.parent.clone(), - } - } -} - -pub trait CookieReady { - fn ready(&mut self, id: usize) -> impl std::future::Future; -} - -impl CookieReady for () { - async fn ready(&mut self, _id: usize) {} -} - -impl CookieReady for CookiedOptionalWatch { - async fn ready(&mut self, id: usize) { - tracing::debug!("waiting for cookie {}", id); - self.parent.ready(id).await; - _ = self.cookie_index.wait_for(|v| v >= &id).await; - } -} - -impl CookiedOptionalWatch { - pub fn new( - update: CookieWriter, - ) -> ( - watch::Sender>, - CookieRegister, - CookiedOptionalWatch, - ) { - let (tx, rx) = watch::channel(None); - let (cookie_tx, cookie_rx) = watch::channel(0); - tracing::debug!("starting cookied optional watch in {}", update.root()); - ( - tx, - CookieRegister(cookie_tx, update.root().to_owned()), - CookiedOptionalWatch { - value: rx, - cookie_index: cookie_rx, - cookie_writer: update, - parent: (), - }, - ) - } -} - -impl CookiedOptionalWatch { - /// Create a new sibling cookie watcher that inherits the same fs source as - /// this one. - pub fn new_sibling(&self) -> (watch::Sender>, CookiedOptionalWatch) { - let (tx, rx) = watch::channel(None); - ( - tx, - CookiedOptionalWatch { - value: rx, - cookie_index: self.cookie_index.clone(), - cookie_writer: self.cookie_writer.clone(), - parent: self.parent.clone(), - }, - ) - } - - /// Create a new child cookie watcher that inherits the same fs source as - /// this one, but also has its own cookie source. This allows you to - /// synchronize two independent cookie streams. - pub fn new_child( - &self, - ) -> ( - watch::Sender>, - CookieRegister, - CookiedOptionalWatch, - ) { - let (tx, rx) = watch::channel(None); - let (cookie_tx, cookie_rx) = watch::channel(0); - - ( - tx, - CookieRegister(cookie_tx, self.cookie_writer.root().to_owned()), - CookiedOptionalWatch { - value: rx, - cookie_index: cookie_rx, - cookie_writer: self.cookie_writer.clone(), - parent: self.clone(), - }, - ) - } - - #[tracing::instrument(skip(self))] - pub async fn get(&mut self) -> Result, CookieError> { - let next_id = self - .cookie_writer - .initialized_cookie_request(()) - .await? - .serial; - self.ready(next_id).await; - tracing::debug!("got cookie, waiting for data"); - Ok(self.get_inner().await?) - } - - #[tracing::instrument(skip(self))] - pub async fn get_change(&mut self) -> Result, watch::error::RecvError> { - self.value.changed().await?; - self.get_inner().await - } - - /// Please do not use this data from a user-facing query. It should only - /// really be used for internal state management. Equivalent to - /// `OptionalWatch::get` - /// - /// For an example as to why we need this, sometimes file event processing - /// needs to access data but issuing a cookie request would deadlock. - /// - /// `_reason` is purely for documentation purposes and is not used. - pub async fn get_raw( - &mut self, - _reason: &str, - ) -> Result, watch::error::RecvError> { - self.get_inner().await - } - - /// Get the current value, if it is available. - /// - /// Unlike `OptionalWatch::get_immediate`, this method will block until the - /// cookie has been seen, at which point it will call `now_or_never` on the - /// value watch. - #[tracing::instrument(skip(self))] - pub async fn get_immediate( - &mut self, - ) -> Option, watch::error::RecvError>> { - let next_id = self.cookie_writer.cookie_request(()).await.ok()?.serial; - self.cookie_index.wait_for(|v| v >= &next_id).await.ok()?; - self.get_inner().now_or_never() - } - - /// Please do not use this data from a user-facing query. It should only - /// really be used for internal state management. Equivalent to - /// `OptionalWatch::get` - /// - /// For an example as to why we need this, sometimes file event processing - /// needs to access data but issuing a cookie request would deadlock. - /// - /// `_reason` is purely for documentation purposes and is not used. - pub async fn get_immediate_raw( - &mut self, - reason: &str, - ) -> Option, watch::error::RecvError>> { - self.get_raw(reason).now_or_never() - } - - async fn get_inner(&mut self) -> Result, watch::error::RecvError> { - self.value.wait_for(|f| f.is_some()).await?; - Ok(SomeRef(self.value.borrow())) - } - - pub(crate) fn watch(&self) -> watch::Receiver> { - self.value.clone() - } -} - -pub struct CookieRegister(watch::Sender, AbsoluteSystemPathBuf); -impl CookieRegister { - pub fn register(&self, paths: &[&AbsoluteSystemPath]) { - tracing::trace!("registering cookie for {:?}", paths); - for path in paths { - if let Some(serial) = serial_for_path(&self.1, path) { - tracing::trace!("updating cookie to {}", serial); - let _ = self.0.send(serial); - } - } - } -} - -#[cfg(test)] -mod test { - use std::time::Duration; - - use notify::{event::CreateKind, Event, EventKind}; - use tokio::{ - sync::{broadcast, mpsc, oneshot}, - task::JoinSet, - }; - use turbopath::AbsoluteSystemPathBuf; - - use super::{CookieWatcher, CookiedRequest}; - use crate::{cookies::CookieWriter, NotifyError, OptionalWatch}; - - struct TestQuery { - resp: oneshot::Sender<()>, - } - - struct TestService { - file_events: broadcast::Receiver>, - cookie_watcher: CookieWatcher, - reqs_rx: mpsc::Receiver>, - } - - impl TestService { - async fn watch(mut self, mut exit_ch: oneshot::Receiver<()>) { - loop { - tokio::select! { - biased; - _ = &mut exit_ch => return, - Some(req) = self.reqs_rx.recv() => { - if let Some(query) = self.cookie_watcher.check_request(req) { - query.resp.send(()).unwrap(); - } - } - file_event = self.file_events.recv() => { - let event = file_event.unwrap().unwrap(); - for path in event.paths { - let path = AbsoluteSystemPathBuf::try_from(path).unwrap(); - if let Some(queries) = self.cookie_watcher.pop_ready_requests(event.kind, &path) { - for query in queries { - query.resp.send(()).unwrap(); - } - } - } - } - } - } - } - } - - #[derive(Clone)] - struct TestClient { - reqs_tx: mpsc::Sender>, - cookie_writer: CookieWriter, - } - - impl TestClient { - async fn request(&self) { - let (resp_tx, resp_rx) = oneshot::channel(); - let query = TestQuery { resp: resp_tx }; - let req = self.cookie_writer.cookie_request(query).await.unwrap(); - self.reqs_tx.send(req).await.unwrap(); - resp_rx.await.unwrap(); - } - } - - #[tokio::test(flavor = "multi_thread")] - async fn test_service_cookies() { - let tempdir = tempfile::tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tempdir.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let (send_file_events, file_events) = broadcast::channel(16); - let recv = OptionalWatch::once(file_events.resubscribe()); - let (reqs_tx, reqs_rx) = mpsc::channel(16); - let cookie_writer = CookieWriter::new(&path, Duration::from_secs(2), recv); - let (exit_tx, exit_rx) = oneshot::channel(); - - let service = TestService { - file_events, - cookie_watcher: CookieWatcher::new(path.clone()), - reqs_rx, - }; - let service_handle = tokio::spawn(service.watch(exit_rx)); - - let client = TestClient { - reqs_tx, - cookie_writer, - }; - // race request and file event. Either order should work. - tokio_scoped::scope(|scope| { - scope.spawn(client.request()); - send_file_events - .send(Ok(Event { - kind: EventKind::Create(CreateKind::File), - paths: vec![path.join_component("1.cookie").as_std_path().to_owned()], - ..Default::default() - })) - .unwrap(); - }); - - // explicitly send the cookie first - tokio_scoped::scope(|scope| { - send_file_events - .send(Ok(Event { - kind: EventKind::Create(CreateKind::File), - paths: vec![path.join_component("2.cookie").as_std_path().to_owned()], - ..Default::default() - })) - .unwrap(); - scope.spawn(client.request()); - }); - - // send a cookie with a much higher value - tokio_scoped::scope(|scope| { - send_file_events - .send(Ok(Event { - kind: EventKind::Create(CreateKind::File), - paths: vec![path.join_component("20.cookie").as_std_path().to_owned()], - ..Default::default() - })) - .unwrap(); - scope.spawn(client.request()); - }); - exit_tx.send(()).unwrap(); - service_handle.await.unwrap(); - } - - #[tokio::test(flavor = "multi_thread")] - async fn test_out_of_order_requests() { - let tempdir = tempfile::tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tempdir.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let (send_file_events, file_events) = broadcast::channel(16); - let recv = OptionalWatch::once(file_events.resubscribe()); - let (reqs_tx, reqs_rx) = mpsc::channel(16); - let cookie_writer = CookieWriter::new(&path, Duration::from_secs(2), recv); - let (exit_tx, exit_rx) = oneshot::channel(); - - let service = TestService { - file_events, - cookie_watcher: CookieWatcher::new(path.clone()), - reqs_rx, - }; - let service_handle = tokio::spawn(service.watch(exit_rx)); - - let client = TestClient { - reqs_tx, - cookie_writer, - }; - - let mut join_set = JoinSet::new(); - let client_1 = client.clone(); - join_set.spawn(async move { client_1.request().await }); - - let client_2 = client.clone(); - join_set.spawn(async move { client_2.request().await }); - - let client_3 = client.clone(); - join_set.spawn(async move { client_3.request().await }); - - send_file_events - .send(Ok(Event { - kind: EventKind::Create(CreateKind::File), - paths: vec![path.join_component("2.cookie").as_std_path().to_owned()], - ..Default::default() - })) - .unwrap(); - - // Expect 2 rpcs to be ready. We don't know which ones they will be - // but we also don't care. We don't have ordering semantics on the client - // side. - join_set.join_next().await.unwrap().unwrap(); - join_set.join_next().await.unwrap().unwrap(); - - send_file_events - .send(Ok(Event { - kind: EventKind::Create(CreateKind::File), - paths: vec![path.join_component("3.cookie").as_std_path().to_owned()], - ..Default::default() - })) - .unwrap(); - join_set.join_next().await.unwrap().unwrap(); - - exit_tx.send(()).unwrap(); - service_handle.await.unwrap(); - } -} diff --git a/crates/turborepo-filewatch/src/debouncer.rs b/crates/turborepo-filewatch/src/debouncer.rs deleted file mode 100644 index 0f169b2d715b6..0000000000000 --- a/crates/turborepo-filewatch/src/debouncer.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::{fmt::Debug, sync::Mutex, time::Duration}; - -use tokio::{select, sync, time::Instant}; -use tracing::trace; - -pub(crate) struct Debouncer { - bump: sync::Notify, - serial: Mutex>, - timeout: Duration, -} - -const DEFAULT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(10); - -impl Default for Debouncer { - fn default() -> Self { - Self::new(DEFAULT_DEBOUNCE_TIMEOUT) - } -} - -impl Debug for Debouncer { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let serial = { self.serial.lock().expect("lock is valid") }; - f.debug_struct("Debouncer") - .field("is_pending", &serial.is_some()) - .field("timeout", &self.timeout) - .finish() - } -} - -impl Debouncer { - pub(crate) fn new(timeout: Duration) -> Self { - let bump = sync::Notify::new(); - let serial = Mutex::new(Some(0)); - Self { - bump, - serial, - timeout, - } - } - - pub(crate) fn bump(&self) -> bool { - let mut serial = self.serial.lock().expect("lock is valid"); - match *serial { - None => false, - Some(previous) => { - *serial = Some(previous + 1); - self.bump.notify_one(); - true - } - } - } - - pub(crate) async fn debounce(&self) { - let mut serial = { - self.serial - .lock() - .expect("lock is valid") - .expect("only this thread sets the value to None") - }; - let mut deadline = Instant::now() + self.timeout; - loop { - let timeout = tokio::time::sleep_until(deadline); - select! { - _ = self.bump.notified() => { - trace!("debouncer notified"); - // reset timeout - let current_serial = self.serial.lock().expect("lock is valid").expect("only this thread sets the value to None"); - if current_serial == serial { - // we timed out between the serial update and the notification. - // ignore this notification, we've already bumped the timer - continue; - } else { - serial = current_serial; - deadline = Instant::now() + self.timeout; - } - } - _ = timeout => { - // check if serial is still valid. It's possible a bump came in before the timeout, - // but we haven't been notified yet. - let mut current_serial_opt = self.serial.lock().expect("lock is valid"); - let current_serial = current_serial_opt.expect("only this thread sets the value to None"); - if current_serial == serial { - // if the serial is what we last observed, and the timer expired, we timed out. - // we're done. Mark that we won't accept any more bumps and return - *current_serial_opt = None; - return; - } else { - serial = current_serial; - deadline = Instant::now() + self.timeout; - } - } - } - } - } -} - -#[cfg(test)] -mod tests { - use std::{ - sync::Arc, - time::{Duration, Instant}, - }; - - use crate::debouncer::Debouncer; - - #[tokio::test] - async fn test_debouncer() { - let debouncer = Arc::new(Debouncer::new(Duration::from_millis(10))); - let debouncer_copy = debouncer.clone(); - let handle = tokio::task::spawn(async move { - debouncer_copy.debounce().await; - }); - for _ in 0..10 { - // assert that we can continue bumping it past the original timeout - tokio::time::sleep(Duration::from_millis(2)).await; - assert!(debouncer.bump()); - } - let start = Instant::now(); - handle.await.unwrap(); - let end = Instant::now(); - // give some wiggle room to account for race conditions, but assert that we - // didn't immediately complete after the last bump - assert!(end - start > Duration::from_millis(5)); - // we shouldn't be able to bump it after it's run out it's timeout - assert!(!debouncer.bump()); - } -} diff --git a/crates/turborepo-filewatch/src/fsevent.rs b/crates/turborepo-filewatch/src/fsevent.rs deleted file mode 100644 index 55cfb245092ba..0000000000000 --- a/crates/turborepo-filewatch/src/fsevent.rs +++ /dev/null @@ -1,656 +0,0 @@ -//! Watcher implementation for Darwin's FSEvents API -//! -//! The FSEvents API provides a mechanism to notify clients about directories -//! they ought to re-scan in order to keep their internal data structures -//! up-to-date with respect to the true state of the file system. (For example, -//! when files or directories are created, modified, or removed.) It sends these -//! notifications "in bulk", possibly notifying the client of changes to several -//! directories in a single callback. -//! -//! For more information see the [FSEvents API reference][ref]. -//! -//! TODO: document event translation -//! -//! [ref]: https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/ - -#![allow(non_upper_case_globals, dead_code)] -// bitflags! with a 0 value defined triggers this clippy error, -// but we want to be able to define a value for fs::kFSEventStreamEventFlagNone -#![allow(clippy::bad_bit_mask)] - -use std::{ - collections::HashMap, - ffi::CStr, - fmt, - io::ErrorKind, - os::{raw, unix::prelude::MetadataExt}, - path::{Path, PathBuf}, - ptr, - sync::{Arc, Mutex}, - thread, -}; - -use fs::core_foundation::Boolean; -use fsevent_sys as fs; -use fsevent_sys::core_foundation as cf; -use notify::{ - event::{CreateKind, DataChange, Flag, MetadataKind, ModifyKind, RemoveKind, RenameMode}, - Config, Error, Event, EventHandler, EventKind, RecursiveMode, Result, Watcher, WatcherKind, -}; - -//use crate::event::*; - -type Sender = std::sync::mpsc::Sender; - -bitflags::bitflags! { - #[repr(C)] - struct StreamFlags: u32 { - const NONE = fs::kFSEventStreamEventFlagNone; - const MUST_SCAN_SUBDIRS = fs::kFSEventStreamEventFlagMustScanSubDirs; - const USER_DROPPED = fs::kFSEventStreamEventFlagUserDropped; - const KERNEL_DROPPED = fs::kFSEventStreamEventFlagKernelDropped; - const IDS_WRAPPED = fs::kFSEventStreamEventFlagEventIdsWrapped; - const HISTORY_DONE = fs::kFSEventStreamEventFlagHistoryDone; - const ROOT_CHANGED = fs::kFSEventStreamEventFlagRootChanged; - const MOUNT = fs::kFSEventStreamEventFlagMount; - const UNMOUNT = fs::kFSEventStreamEventFlagUnmount; - const ITEM_CREATED = fs::kFSEventStreamEventFlagItemCreated; - const ITEM_REMOVED = fs::kFSEventStreamEventFlagItemRemoved; - const INODE_META_MOD = fs::kFSEventStreamEventFlagItemInodeMetaMod; - const ITEM_RENAMED = fs::kFSEventStreamEventFlagItemRenamed; - const ITEM_MODIFIED = fs::kFSEventStreamEventFlagItemModified; - const FINDER_INFO_MOD = fs::kFSEventStreamEventFlagItemFinderInfoMod; - const ITEM_CHANGE_OWNER = fs::kFSEventStreamEventFlagItemChangeOwner; - const ITEM_XATTR_MOD = fs::kFSEventStreamEventFlagItemXattrMod; - const IS_FILE = fs::kFSEventStreamEventFlagItemIsFile; - const IS_DIR = fs::kFSEventStreamEventFlagItemIsDir; - const IS_SYMLINK = fs::kFSEventStreamEventFlagItemIsSymlink; - const OWN_EVENT = fs::kFSEventStreamEventFlagOwnEvent; - const IS_HARDLINK = fs::kFSEventStreamEventFlagItemIsHardlink; - const IS_LAST_HARDLINK = fs::kFSEventStreamEventFlagItemIsLastHardlink; - const ITEM_CLONED = fs::kFSEventStreamEventFlagItemCloned; - } -} - -/// FSEvents-based `Watcher` implementation -pub struct FsEventWatcher { - paths: cf::CFMutableArrayRef, - since_when: fs::FSEventStreamEventId, - latency: cf::CFTimeInterval, - flags: fs::FSEventStreamCreateFlags, - event_handler: Arc>, - runloop: Option<(cf::CFRunLoopRef, thread::JoinHandle<()>)>, - recursive_info: HashMap, - device: Option, -} - -impl fmt::Debug for FsEventWatcher { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("FsEventWatcher") - .field("paths", &self.paths) - .field("since_when", &self.since_when) - .field("latency", &self.latency) - .field("flags", &self.flags) - .field("event_handler", &Arc::as_ptr(&self.event_handler)) - .field("runloop", &self.runloop) - .field("recursive_info", &self.recursive_info) - .finish() - } -} - -// CFMutableArrayRef is a type alias to *mut libc::c_void, so FsEventWatcher is -// not Send/Sync automatically. It's Send because the pointer is not used in -// other threads. -unsafe impl Send for FsEventWatcher {} - -// It's Sync because all methods that change the mutable state use `&mut self`. -unsafe impl Sync for FsEventWatcher {} - -fn translate_flags(flags: StreamFlags, precise: bool) -> Vec { - let mut evs = Vec::new(); - - // «Denotes a sentinel event sent to mark the end of the "historical" events - // sent as a result of specifying a `sinceWhen` value in the FSEvents.Create - // call that created this event stream. After invoking the client's callback - // with all the "historical" events that occurred before now, the client's - // callback will be invoked with an event where the HistoryDone flag is set. - // The client should ignore the path supplied in this callback.» - // — https://www.mbsplugins.eu/FSEventsNextEvent.shtml - // - // As a result, we just stop processing here and return an empty vec, which - // will ignore this completely and not emit any Events whatsoever. - if flags.contains(StreamFlags::HISTORY_DONE) { - return evs; - } - - // FSEvents provides two possible hints as to why events were dropped, - // however documentation on what those mean is scant, so we just pass them - // through in the info attr field. The intent is clear enough, and the - // additional information is provided if the user wants it. - if flags.contains(StreamFlags::MUST_SCAN_SUBDIRS) { - let e = Event::new(EventKind::Other).set_flag(Flag::Rescan); - evs.push(if flags.contains(StreamFlags::USER_DROPPED) { - e.set_info("rescan: user dropped") - } else if flags.contains(StreamFlags::KERNEL_DROPPED) { - e.set_info("rescan: kernel dropped") - } else { - e - }); - } - - // In imprecise mode, let's not even bother parsing the kind of the event - // except for the above very special events. - if !precise { - evs.push(Event::new(EventKind::Any)); - return evs; - } - - // This is most likely a rename or a removal. We assume rename but may want - // to figure out if it was a removal some way later (TODO). To denote the - // special nature of the event, we add an info string. - if flags.contains(StreamFlags::ROOT_CHANGED) { - evs.push( - Event::new(EventKind::Modify(ModifyKind::Name(RenameMode::From))) - .set_info("root changed"), - ); - } - - // A path was mounted at the event path; we treat that as a create. - if flags.contains(StreamFlags::MOUNT) { - evs.push(Event::new(EventKind::Create(CreateKind::Other)).set_info("mount")); - } - - // A path was unmounted at the event path; we treat that as a remove. - if flags.contains(StreamFlags::UNMOUNT) { - evs.push(Event::new(EventKind::Remove(RemoveKind::Other)).set_info("mount")); - } - - if flags.contains(StreamFlags::ITEM_CREATED) { - evs.push(if flags.contains(StreamFlags::IS_DIR) { - Event::new(EventKind::Create(CreateKind::Folder)) - } else if flags.contains(StreamFlags::IS_FILE) { - Event::new(EventKind::Create(CreateKind::File)) - } else { - let e = Event::new(EventKind::Create(CreateKind::Other)); - if flags.contains(StreamFlags::IS_SYMLINK) { - e.set_info("is: symlink") - } else if flags.contains(StreamFlags::IS_HARDLINK) { - e.set_info("is: hardlink") - } else if flags.contains(StreamFlags::ITEM_CLONED) { - e.set_info("is: clone") - } else { - Event::new(EventKind::Create(CreateKind::Any)) - } - }); - } - - if flags.contains(StreamFlags::ITEM_REMOVED) { - evs.push(if flags.contains(StreamFlags::IS_DIR) { - Event::new(EventKind::Remove(RemoveKind::Folder)) - } else if flags.contains(StreamFlags::IS_FILE) { - Event::new(EventKind::Remove(RemoveKind::File)) - } else { - let e = Event::new(EventKind::Remove(RemoveKind::Other)); - if flags.contains(StreamFlags::IS_SYMLINK) { - e.set_info("is: symlink") - } else if flags.contains(StreamFlags::IS_HARDLINK) { - e.set_info("is: hardlink") - } else if flags.contains(StreamFlags::ITEM_CLONED) { - e.set_info("is: clone") - } else { - Event::new(EventKind::Remove(RemoveKind::Any)) - } - }); - } - - // FSEvents provides no mechanism to associate the old and new sides of a - // rename event. - if flags.contains(StreamFlags::ITEM_RENAMED) { - evs.push(Event::new(EventKind::Modify(ModifyKind::Name( - RenameMode::Any, - )))); - } - - // This is only described as "metadata changed", but it may be that it's - // only emitted for some more precise subset of events... if so, will need - // amending, but for now we have an Any-shaped bucket to put it in. - if flags.contains(StreamFlags::INODE_META_MOD) { - evs.push(Event::new(EventKind::Modify(ModifyKind::Metadata( - MetadataKind::Any, - )))); - } - - if flags.contains(StreamFlags::FINDER_INFO_MOD) { - evs.push( - Event::new(EventKind::Modify(ModifyKind::Metadata(MetadataKind::Other))) - .set_info("meta: finder info"), - ); - } - - if flags.contains(StreamFlags::ITEM_CHANGE_OWNER) { - evs.push(Event::new(EventKind::Modify(ModifyKind::Metadata( - MetadataKind::Ownership, - )))); - } - - if flags.contains(StreamFlags::ITEM_XATTR_MOD) { - evs.push(Event::new(EventKind::Modify(ModifyKind::Metadata( - MetadataKind::Extended, - )))); - } - - // This is specifically described as a data change, which we take to mean - // is a content change. - if flags.contains(StreamFlags::ITEM_MODIFIED) { - evs.push(Event::new(EventKind::Modify(ModifyKind::Data( - DataChange::Content, - )))); - } - - if flags.contains(StreamFlags::OWN_EVENT) { - for ev in &mut evs { - *ev = std::mem::take(ev).set_process_id(std::process::id()); - } - } - - evs -} - -struct StreamContextInfo { - event_handler: Arc>, - recursive_info: HashMap, -} - -// Free the context when the stream created by `FSEventStreamCreate` is -// released. -extern "C" fn release_context(info: *const libc::c_void) { - // Safety: - // - The [documentation] for `FSEventStreamContext` states that `release` is - // only called when the stream is deallocated, so it is safe to convert `info` - // back into a box and drop it. - // - // [docs]: https://developer.apple.com/documentation/coreservices/fseventstreamcontext?language=objc - unsafe { - drop(Box::from_raw( - info as *const StreamContextInfo as *mut StreamContextInfo, - )); - } -} - -extern "C" { - /// Indicates whether the run loop is waiting for an event. - fn CFRunLoopIsWaiting(runloop: cf::CFRunLoopRef) -> cf::Boolean; -} - -// CoreFoundation false value -const FALSE: Boolean = 0x0; - -impl FsEventWatcher { - fn from_event_handler(event_handler: Arc>) -> Result { - Ok(FsEventWatcher { - paths: unsafe { - cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks) - }, - since_when: fs::kFSEventStreamEventIdSinceNow, - latency: 0.01, - flags: fs::kFSEventStreamCreateFlagFileEvents - | fs::kFSEventStreamCreateFlagNoDefer - | fs::kFSEventStreamCreateFlagWatchRoot, - event_handler, - runloop: None, - recursive_info: HashMap::new(), - device: None, - }) - } - - fn watch_inner(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { - self.stop(); - let result = self.append_path(path, recursive_mode); - // ignore return error: may be empty path list - let _ = self.run(); - result - } - - fn unwatch_inner(&mut self, path: &Path) -> Result<()> { - self.stop(); - let result = self.remove_path(path); - // ignore return error: may be empty path list - let _ = self.run(); - result - } - - #[inline] - fn is_running(&self) -> bool { - self.runloop.is_some() - } - - fn stop(&mut self) { - if !self.is_running() { - return; - } - - if let Some((runloop, thread_handle)) = self.runloop.take() { - unsafe { - let runloop = runloop as *mut raw::c_void; - - while CFRunLoopIsWaiting(runloop) == 0 { - thread::yield_now(); - } - - cf::CFRunLoopStop(runloop); - } - - // Wait for the thread to shut down. - thread_handle.join().expect("thread to shut down"); - } - } - - fn remove_path(&mut self, path: &Path) -> Result<()> { - let str_path = path.to_str().unwrap(); - unsafe { - let mut err: cf::CFErrorRef = ptr::null_mut(); - let cf_path = cf::str_path_to_cfstring_ref(str_path, &mut err); - if cf_path.is_null() { - cf::CFRelease(err as cf::CFRef); - return Err(Error::watch_not_found().add_path(path.into())); - } - - let mut to_remove = Vec::new(); - for idx in 0..cf::CFArrayGetCount(self.paths) { - let item = cf::CFArrayGetValueAtIndex(self.paths, idx); - if cf::CFStringCompare(item, cf_path, cf::kCFCompareCaseInsensitive) - == cf::kCFCompareEqualTo - { - to_remove.push(idx); - } - } - - cf::CFRelease(cf_path); - - for idx in to_remove.iter().rev() { - cf::CFArrayRemoveValueAtIndex(self.paths, *idx); - } - } - let p = if let Ok(canonicalized_path) = path.canonicalize() { - canonicalized_path - } else { - path.to_owned() - }; - match self.recursive_info.remove(&p) { - Some(_) => Ok(()), - None => Err(Error::watch_not_found()), - } - } - - // https://github.com/thibaudgg/rb-fsevent/blob/master/ext/fsevent_watch/main.c - fn append_path(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { - let device = match std::fs::symlink_metadata(path) { - Err(e) if e.kind() == ErrorKind::NotFound => { - Err(Error::path_not_found().add_path(path.into())) - } - Err(e) => Err(Error::io(e)), - Ok(metadata) => Ok(metadata.dev() as i32), - }?; - - if self.device.is_none() { - self.device = Some(device); - } else if self.device != Some(device) { - return Err(Error::generic("cannot watch multiple devices")); - } - let canonical_path = path.to_path_buf().canonicalize()?; - let str_path = path.to_str().unwrap(); - unsafe { - let mut err: cf::CFErrorRef = ptr::null_mut(); - let cf_path = cf::str_path_to_cfstring_ref(str_path, &mut err); - if cf_path.is_null() { - // Most likely the directory was deleted, or permissions changed, - // while the above code was running. - cf::CFRelease(err as cf::CFRef); - return Err(Error::path_not_found().add_path(path.into())); - } - cf::CFArrayAppendValue(self.paths, cf_path); - cf::CFRelease(cf_path); - } - let is_recursive = matches!(recursive_mode, RecursiveMode::Recursive); - self.recursive_info.insert(canonical_path, is_recursive); - Ok(()) - } - - fn run(&mut self) -> Result<()> { - if unsafe { cf::CFArrayGetCount(self.paths) } == 0 { - // TODO: Reconstruct and add paths to error - return Err(Error::path_not_found()); - } - let device = self - .device - .ok_or_else(|| Error::generic("no device set for stream"))?; - - // We need to associate the stream context with our callback in order to - // propagate events to the rest of the system. This will be owned by the - // stream, and will be freed when the stream is closed. This means we - // will leak the context if we panic before reaching - // `FSEventStreamRelease`. - let stream_context_info = Box::into_raw(Box::new(StreamContextInfo { - event_handler: self.event_handler.clone(), - recursive_info: self.recursive_info.clone(), - })); - - let stream_context = fs::FSEventStreamContext { - version: 0, - info: stream_context_info as *mut libc::c_void, - retain: None, - release: Some(release_context), - copy_description: None, - }; - - let stream = unsafe { - fs::FSEventStreamCreateRelativeToDevice( - cf::kCFAllocatorDefault, - callback, - &stream_context, - device, - self.paths, - self.since_when, - self.latency, - self.flags, - ) - }; - - // Wrapper to help send CFRef types across threads. - struct CFSendWrapper(cf::CFRef); - - // Safety: - // - According to the Apple documentation, it's safe to move `CFRef`s across threads. - // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html - unsafe impl Send for CFSendWrapper {} - - // move into thread - let stream = CFSendWrapper(stream); - - // channel to pass runloop around - let (rl_tx, rl_rx) = std::sync::mpsc::channel(); - - let thread_handle = thread::Builder::new() - .name("notify-rs fsevents loop".to_string()) - .spawn(move || { - let _ = &stream; - let stream = stream.0; - - unsafe { - let cur_runloop = cf::CFRunLoopGetCurrent(); - - fs::FSEventStreamScheduleWithRunLoop( - stream, - cur_runloop, - cf::kCFRunLoopDefaultMode, - ); - if fs::FSEventStreamStart(stream) == FALSE { - panic!("FSEventStream failed to start"); - } - - // the calling to CFRunLoopRun will be terminated by CFRunLoopStop call in - // drop() - rl_tx - .send(CFSendWrapper(cur_runloop)) - .expect("Unable to send runloop to watcher"); - - cf::CFRunLoopRun(); - fs::FSEventStreamStop(stream); - fs::FSEventStreamInvalidate(stream); - fs::FSEventStreamRelease(stream); - } - })?; - // block until runloop has been sent - self.runloop = Some((rl_rx.recv().unwrap().0, thread_handle)); - - Ok(()) - } - - fn configure_raw_mode(&mut self, _config: Config, tx: Sender>) { - tx.send(Ok(false)) - .expect("configuration channel disconnect"); - } -} - -extern "C" fn callback( - stream_ref: fs::FSEventStreamRef, - info: *mut libc::c_void, - num_events: libc::size_t, // size_t numEvents - event_paths: *mut libc::c_void, // void *eventPaths - event_flags: *const fs::FSEventStreamEventFlags, // const FSEventStreamEventFlags eventFlags[] - event_ids: *const fs::FSEventStreamEventId, // const FSEventStreamEventId eventIds[] -) { - unsafe { - callback_impl( - stream_ref, - info, - num_events, - event_paths, - event_flags, - event_ids, - ) - } -} - -unsafe fn callback_impl( - _stream_ref: fs::FSEventStreamRef, - info: *mut libc::c_void, - num_events: libc::size_t, // size_t numEvents - event_paths: *mut libc::c_void, // void *eventPaths - event_flags: *const fs::FSEventStreamEventFlags, // const FSEventStreamEventFlags eventFlags[] - _event_ids: *const fs::FSEventStreamEventId, // const FSEventStreamEventId eventIds[] -) { - let event_paths = event_paths as *const *const libc::c_char; - let info = info as *const StreamContextInfo; - let event_handler = &(*info).event_handler; - - for p in 0..num_events { - let raw_path = CStr::from_ptr(*event_paths.add(p)) - .to_str() - .expect("Invalid UTF8 string."); - let path = PathBuf::from(format!("/{}", raw_path)); - - let flag = *event_flags.add(p); - let flag = StreamFlags::from_bits(flag).unwrap_or_else(|| { - panic!("Unable to decode StreamFlags: {}", flag); - }); - - let mut handle_event = false; - for (p, r) in &(*info).recursive_info { - if path.starts_with(p) { - if *r || &path == p { - handle_event = true; - break; - } else if let Some(parent_path) = path.parent() { - if parent_path == p { - handle_event = true; - break; - } - } - } - } - - if !handle_event { - continue; - } - - for ev in translate_flags(flag, true).into_iter() { - // TODO: precise - let ev = ev.add_path(path.clone()); - let mut event_handler = event_handler.lock().expect("lock not to be poisoned"); - event_handler.handle_event(Ok(ev)); - } - } -} - -impl Watcher for FsEventWatcher { - /// Create a new watcher. - fn new(event_handler: F, _config: Config) -> Result { - Self::from_event_handler(Arc::new(Mutex::new(event_handler))) - } - - fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { - self.watch_inner(path, recursive_mode) - } - - fn unwatch(&mut self, path: &Path) -> Result<()> { - self.unwatch_inner(path) - } - - fn configure(&mut self, config: Config) -> Result { - let (tx, rx) = std::sync::mpsc::channel(); - self.configure_raw_mode(config, tx); - rx.recv() - .map_err(|err| Error::generic(&format!("internal channel disconnect: {:?}", err)))? - } - - fn kind() -> WatcherKind { - WatcherKind::Fsevent - } -} - -impl Drop for FsEventWatcher { - fn drop(&mut self) { - self.stop(); - unsafe { - cf::CFRelease(self.paths); - } - } -} - -#[test] -fn test_fsevent_watcher_drop() { - use std::time::Duration; - - use super::*; - - let dir = tempfile::tempdir().unwrap(); - - let (tx, rx) = std::sync::mpsc::channel(); - - { - let mut watcher = FsEventWatcher::new(tx, Default::default()).unwrap(); - watcher.watch(dir.path(), RecursiveMode::Recursive).unwrap(); - thread::sleep(Duration::from_millis(2000)); - //println!("is running -> {}", watcher.is_running()); - - thread::sleep(Duration::from_millis(1000)); - watcher.unwatch(dir.path()).unwrap(); - //println!("is running -> {}", watcher.is_running()); - } - - thread::sleep(Duration::from_millis(1000)); - - for res in rx { - let e = res.unwrap(); - println!("debug => {:?} {:?}", e.kind, e.paths); - } - - println!("in test: {} works", file!()); -} - -#[test] -fn test_steam_context_info_send_and_sync() { - fn check_send() {} - check_send::(); -} diff --git a/crates/turborepo-filewatch/src/lib.rs b/crates/turborepo-filewatch/src/lib.rs deleted file mode 100644 index 7ef45bfe65593..0000000000000 --- a/crates/turborepo-filewatch/src/lib.rs +++ /dev/null @@ -1,953 +0,0 @@ -//! File watching utilities for Turborepo. Includes a file watcher that is -//! designed to work across multiple platforms, with consistent behavior and -//! consistent ordering. -//! -//! Also includes watchers that take in file change events and produce derived -//! data like changed packages or the workspaces in a repository. -//! -//! ## Watcher Implementation -//! It's important to note that when implementing a watcher, you should aim to -//! make file change event processing as fast as possible. There should be -//! almost no slow code in the main event loop. Otherwise, the receiver will lag -//! behind, and return a `Lagged` event. -//! -//! A common pattern that we use to avoid lag is having a separate event thread -//! that processes events and accumulates them into a data structure, say a -//! `Trie` for changed files, or a `HashSet` for changed packages. From there, a -//! second thread is responsible for actually taking that accumulated data and -//! processing it. This second thread can do slower tasks like executing a run -//! or mapping files to changed packages. It can either be parked and awoken -//! using `tokio::sync::Notify` or it can run periodically using -//! `tokio::time::interval`. - -#![deny(clippy::all)] -#![allow(clippy::mutable_key_type)] -#![feature(assert_matches)] - -use std::{ - fmt::{Debug, Display}, - future::IntoFuture, - path::Path, - sync::Arc, - time::Duration, -}; - -// windows -> no recursive watch, watch ancestors -// linux -> recursive watch, watch ancestors -// macos -> custom watcher impl in fsevents, no recursive watch, no watching ancestors -#[cfg(target_os = "macos")] -use fsevent::FsEventWatcher; -#[cfg(any(feature = "manual_recursive_watch", feature = "watch_ancestors"))] -use notify::event::EventKind; -#[cfg(not(target_os = "macos"))] -use notify::{Config, RecommendedWatcher}; -use notify::{Event, EventHandler, RecursiveMode, Watcher}; -use thiserror::Error; -use tokio::sync::{broadcast, mpsc, watch::error::RecvError}; -use tracing::{debug, warn}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathRelation}; -#[cfg(feature = "manual_recursive_watch")] -use { - notify::{ - event::{CreateKind, EventAttributes}, - ErrorKind, - }, - std::io, - tracing::trace, - walkdir::WalkDir, -}; - -pub mod cookies; -mod debouncer; -#[cfg(target_os = "macos")] -mod fsevent; -pub mod globwatcher; -pub mod hash_watcher; -mod optional_watch; -pub mod package_watcher; -mod scm_resource; - -pub use optional_watch::OptionalWatch; - -#[cfg(not(target_os = "macos"))] -type Backend = RecommendedWatcher; -#[cfg(target_os = "macos")] -type Backend = FsEventWatcher; - -type EventResult = Result; - -#[derive(Debug, Error)] -pub enum WatchError { - #[error("filewatching backend error: {0}")] - Notify(#[from] notify::Error), - #[error("filewatching stopped")] - Stopped(#[from] std::sync::mpsc::RecvError), - #[error("enumerating recursive watch: {0}")] - WalkDir(#[from] walkdir::Error), - #[error("filewatching failed to start: {0}")] - Setup(String), -} - -// We want to broadcast the errors we get, but notify::Error does not implement -// Clone. We provide a wrapper that uses an Arc to implement Clone so that we -// can send errors on a broadcast channel. -#[derive(Clone, Debug, Error)] -pub struct NotifyError(Arc); - -impl From for NotifyError { - fn from(value: notify::Error) -> Self { - Self(Arc::new(value)) - } -} - -impl Display for NotifyError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -pub struct FileSystemWatcher { - receiver: OptionalWatch>>, - // _exit_ch exists to trigger a close on the receiver when an instance - // of this struct is dropped. The task that is receiving events will exit, - // dropping the other sender for the broadcast channel, causing all receivers - // to be notified of a close. - _exit_ch: tokio::sync::oneshot::Sender<()>, - cookie_dir: AbsoluteSystemPathBuf, -} - -impl FileSystemWatcher { - pub fn new_with_default_cookie_dir(root: &AbsoluteSystemPath) -> Result { - // We already store logs in .turbo and recommend it be gitignore'd. - // Watchman uses .git, but we can't guarantee that git is present _or_ - // that the turbo root is the same as the git root. - Self::new(root, root.join_components(&[".turbo", "cookies"])) - } - - pub fn new( - root: &AbsoluteSystemPath, - cookie_dir: AbsoluteSystemPathBuf, - ) -> Result { - tracing::debug!("initing file-system watcher"); - - if root.relation_to_path(&cookie_dir) != PathRelation::Parent { - return Err(WatchError::Setup(format!( - "Invalid cookie directory: {} does not contain {}", - root, cookie_dir - ))); - } - - let (file_events_receiver_tx, file_events_receiver_lazy) = OptionalWatch::new(); - let (send_file_events, mut recv_file_events) = mpsc::channel(1024); - let (exit_ch, exit_signal) = tokio::sync::oneshot::channel(); - - tokio::task::spawn({ - let cookie_dir = cookie_dir.clone(); - let watch_root = root.to_owned(); - async move { - // this task never yields, so run it in the blocking threadpool - let watch_root_task = watch_root.clone(); - let cookie_dir_task = cookie_dir.clone(); - let task = tokio::task::spawn_blocking(move || { - setup_cookie_dir(&cookie_dir_task)?; - run_watcher(&watch_root_task, send_file_events) - }); - - let Ok(Ok(watcher)) = task.await else { - // if the watcher fails, just return. we don't set the event sender, and other - // services will never start - return; - }; - - // Ensure we are ready to receive new events, not events for existing state - debug!("waiting for initial filesystem cookie"); - if let Err(e) = wait_for_cookie(&cookie_dir, &mut recv_file_events).await { - // if we can't get a cookie here, we should not make the file - // watching available to downstream services - warn!("failed to wait for initial filesystem cookie: {}", e); - return; - } - debug!("filewatching ready"); - - let (sender, receiver) = broadcast::channel(1024); - - if file_events_receiver_tx.send(Some(receiver)).is_err() { - // if this fails, it means that nobody is listening (and - // nobody ever will) likely because the - // watcher has been dropped. We can just exit early. - tracing::debug!("no downstream listeners, exiting"); - return; - } - - watch_events(watcher, watch_root, recv_file_events, exit_signal, sender).await; - } - }); - - Ok(Self { - receiver: file_events_receiver_lazy, - _exit_ch: exit_ch, - cookie_dir, - }) - } - - /// A convenience method around the sender watcher that waits for file - /// watching to be ready and then returns a handle to the file stream. - pub async fn subscribe( - &self, - ) -> Result>, RecvError> { - let mut receiver = self.receiver.clone(); - receiver.get().await.map(|r| r.resubscribe()) - } - - pub fn watch(&self) -> OptionalWatch>> { - self.receiver.clone() - } - - pub fn cookie_dir(&self) -> &AbsoluteSystemPath { - &self.cookie_dir - } -} - -fn setup_cookie_dir(cookie_dir: &AbsoluteSystemPath) -> Result<(), WatchError> { - // We need to ensure that the cookie directory is cleared out first so - // that we can start over with cookies. - tracing::debug!("setting up the cookie dir"); - - if cookie_dir.exists() { - cookie_dir.remove_dir_all().map_err(|e| { - WatchError::Setup(format!("failed to clear cookie dir {}: {}", cookie_dir, e)) - })?; - } - cookie_dir.create_dir_all().map_err(|e| { - WatchError::Setup(format!("failed to setup cookie dir {}: {}", cookie_dir, e)) - })?; - Ok(()) -} - -#[cfg(not(any(feature = "watch_ancestors", feature = "manual_recursive_watch")))] -async fn watch_events( - _watcher: Backend, - _watch_root: AbsoluteSystemPathBuf, - mut recv_file_events: mpsc::Receiver, - exit_signal: tokio::sync::oneshot::Receiver<()>, - broadcast_sender: broadcast::Sender>, -) { - let mut exit_signal = exit_signal; - 'outer: loop { - tokio::select! { - _ = &mut exit_signal => break 'outer, - Some(event) = recv_file_events.recv().into_future() => { - // we don't care if we fail to send, it just means no one is currently watching - let _ = broadcast_sender.send(event.map_err(NotifyError::from)); - } - } - } -} - -#[cfg(any(feature = "watch_ancestors", feature = "manual_recursive_watch"))] -async fn watch_events( - #[cfg(feature = "manual_recursive_watch")] mut watcher: Backend, - #[cfg(not(feature = "manual_recursive_watch"))] _watcher: Backend, - watch_root: AbsoluteSystemPathBuf, - mut recv_file_events: mpsc::Receiver, - exit_signal: tokio::sync::oneshot::Receiver<()>, - broadcast_sender: broadcast::Sender>, -) { - let mut exit_signal = exit_signal; - 'outer: loop { - tokio::select! { - _ = &mut exit_signal => break 'outer, - Some(event) = recv_file_events.recv().into_future() => { - match event { - Ok(mut event) => { - // Note that we need to filter relevant events - // before doing manual recursive watching so that - // we don't try to add watches to siblings of the - // directories on our path to the root. - #[cfg(feature = "watch_ancestors")] - filter_relevant(&watch_root, &mut event); - - #[cfg(feature = "manual_recursive_watch")] - { - if event.kind == EventKind::Create(CreateKind::Folder) { - for new_path in &event.paths { - if let Err(err) = manually_add_recursive_watches(new_path, &mut watcher, Some(&broadcast_sender)) { - match err { - WatchError::WalkDir(err) => { - // Likely the path no longer exists - debug!("encountered error watching filesystem {}", err); - continue; - }, - _ => { - warn!("encountered error watching filesystem {}", err); - break 'outer; - } - - } - } - } - } - } - // we don't care if we fail to send, it just means no one is currently watching - let _ = broadcast_sender.send(Ok(event)); - }, - Err(error) => { - // we don't care if we fail to send, it just means no one is currently watching - let _ = broadcast_sender.send(Err(NotifyError::from(error))); - } - } - } - } - } -} - -// Since we're manually watching the parent directories, we need -// to handle both getting irrelevant events and getting ancestor -// events that translate to events at the root. -#[cfg(feature = "watch_ancestors")] -fn filter_relevant(root: &AbsoluteSystemPath, event: &mut Event) { - // If path contains root && event type is modify, synthesize modify at root - let is_modify_existing = matches!(event.kind, EventKind::Remove(_) | EventKind::Modify(_)); - - event.paths.retain_mut(|path| { - let abs_path: &AbsoluteSystemPath = path - .as_path() - .try_into() - .expect("Non-absolute path from filewatching"); - match root.relation_to_path(abs_path) { - // An irrelevant path, probably from a non-recursive watch of a parent directory - PathRelation::Divergent => false, - // A path contained in the root - PathRelation::Parent => true, - PathRelation::Child => { - // If we're modifying something along the path to the - // root, move the event to the root - if is_modify_existing { - root.as_std_path().clone_into(path); - } - true - } - } - }) -} - -#[cfg(feature = "watch_ancestors")] -fn is_permission_denied(result: &Result<(), notify::Error>) -> bool { - if let Err(err) = result { - if let notify::ErrorKind::Io(io_err) = &err.kind { - matches!(io_err.kind(), std::io::ErrorKind::PermissionDenied) - } else { - false - } - } else { - false - } -} - -#[cfg(feature = "watch_ancestors")] -fn watch_parents(root: &AbsoluteSystemPath, watcher: &mut Backend) -> Result<(), WatchError> { - let mut current = root; - while let Some(parent) = current.parent() { - current = parent; - let watch_result = watcher.watch(current.as_std_path(), RecursiveMode::NonRecursive); - if is_permission_denied(&watch_result) { - // It is expected we hit a permission denied error at some point. We won't - // get notifications if someone e.g. deletes all of /home - break; - } else { - watch_result?; - } - } - Ok(()) -} - -#[cfg(not(feature = "manual_recursive_watch"))] -fn watch_recursively(root: &AbsoluteSystemPath, watcher: &mut Backend) -> Result<(), WatchError> { - watcher.watch(root.as_std_path(), RecursiveMode::Recursive)?; - Ok(()) -} - -#[cfg(feature = "manual_recursive_watch")] -fn is_not_found(err: ¬ify::Error) -> bool { - if let ErrorKind::Io(ref io_err) = err.kind { - io_err.kind() == io::ErrorKind::NotFound - } else { - false - } -} - -#[cfg(feature = "manual_recursive_watch")] -fn watch_recursively(root: &AbsoluteSystemPath, watcher: &mut Backend) -> Result<(), WatchError> { - // Don't synthesize initial events - manually_add_recursive_watches(root.as_std_path(), watcher, None) -} - -#[cfg(feature = "manual_recursive_watch")] -fn manually_add_recursive_watches( - root: &Path, - watcher: &mut Backend, - sender: Option<&broadcast::Sender>>, -) -> Result<(), WatchError> { - // Note that WalkDir yields the root as well as doing the walk. - for dir in WalkDir::new(root).follow_links(false).into_iter() { - let dir = dir?; - if dir.file_type().is_dir() { - trace!("manually watching {}", dir.path().display()); - match watcher.watch(dir.path(), RecursiveMode::NonRecursive) { - Ok(()) => {} - // If we try to watch a non-existent path, we can just skip - // it. - Err(e) if is_not_found(&e) => continue, - Err(e) => return Err(e.into()), - } - } - if let Some(sender) = sender.as_ref() { - let create_kind = if dir.file_type().is_dir() { - CreateKind::Folder - } else { - CreateKind::File - }; - let event = Event { - paths: vec![dir.path().to_owned()], - kind: EventKind::Create(create_kind), - attrs: EventAttributes::default(), - }; - // It's ok if we fail to send, it means we're shutting down - let _ = sender.send(Ok(event)); - } - } - Ok(()) -} - -fn run_watcher( - root: &AbsoluteSystemPath, - sender: mpsc::Sender, -) -> Result { - let mut watcher = make_watcher(move |res| { - let _ = sender.blocking_send(res); - })?; - - watch_recursively(root, &mut watcher)?; - - #[cfg(feature = "watch_ancestors")] - watch_parents(root, &mut watcher)?; - Ok(watcher) -} - -#[cfg(not(target_os = "macos"))] -fn make_watcher(event_handler: F) -> Result { - RecommendedWatcher::new(event_handler, Config::default()) -} - -#[cfg(target_os = "macos")] -fn make_watcher(event_handler: F) -> Result { - FsEventWatcher::new(event_handler, notify::Config::default()) -} - -/// wait_for_cookie performs a roundtrip through the filewatching mechanism. -/// This ensures that we are ready to receive *new* filesystem events, rather -/// than receiving events from existing state, which some backends can do. -async fn wait_for_cookie( - cookie_dir: &AbsoluteSystemPath, - recv: &mut mpsc::Receiver, -) -> Result<(), WatchError> { - // TODO: should this be passed in? Currently the caller guarantees that the - // directory is empty, but it could be the responsibility of the - // filewatcher... - let cookie_path = cookie_dir.join_component(".turbo-cookie"); - cookie_path.create_with_contents("cookie").map_err(|e| { - WatchError::Setup(format!("failed to write cookie to {}: {}", cookie_path, e)) - })?; - loop { - let event = tokio::time::timeout(Duration::from_millis(2000), recv.recv()) - .await - .map_err(|e| WatchError::Setup(format!("waiting for cookie timed out: {}", e)))? - .ok_or_else(|| { - WatchError::Setup( - "filewatching closed before cookie file was observed".to_string(), - ) - })? - .map_err(|err| { - WatchError::Setup(format!("initial watch encountered errors: {}", err)) - })?; - if event.paths.iter().any(|path| { - let path: &Path = path; - path == (&cookie_path as &AbsoluteSystemPath) - }) { - // We don't need to stop everything if we failed to remove the cookie file - // for some reason. We can warn about it though. - if let Err(e) = cookie_path.remove() { - warn!("failed to remove cookie file {}", e); - } - return Ok(()); - } - } -} - -#[cfg(test)] -mod test { - use std::{assert_matches::assert_matches, sync::atomic::AtomicUsize, time::Duration}; - - #[cfg(not(target_os = "windows"))] - use notify::event::RenameMode; - use notify::{event::ModifyKind, Event, EventKind}; - use tokio::sync::broadcast; - use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; - - use crate::{FileSystemWatcher, NotifyError}; - - fn temp_dir() -> (AbsoluteSystemPathBuf, tempfile::TempDir) { - let tmp = tempfile::tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap(); - (path, tmp) - } - - macro_rules! expect_filesystem_event { - ($recv:ident, $expected_path:expr, $pattern:pat) => { - 'outer: loop { - let event = tokio::time::timeout(Duration::from_millis(3000), $recv.recv()) - .await - .expect("timed out waiting for filesystem event") - .expect("sender was dropped") - .expect("filewatching error"); - for path in event.paths { - if path == (&$expected_path as &AbsoluteSystemPath) - && matches!(event.kind, $pattern) - { - break 'outer; - } - } - } - }; - } - - static WATCH_COUNT: AtomicUsize = AtomicUsize::new(0); - - async fn expect_watching( - recv: &mut broadcast::Receiver>, - dirs: &[&AbsoluteSystemPath], - ) { - for dir in dirs { - let count = WATCH_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - let filename = dir.join_component(format!("test-{}", count).as_str()); - filename.create_with_contents("hello").unwrap(); - - expect_filesystem_event!(recv, filename, EventKind::Create(_)); - } - } - - #[tokio::test] - async fn test_file_watching() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - let sibling_path = parent_path.join_component("sibling"); - sibling_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - let foo_path = child_path.join_component("foo"); - foo_path.create_with_contents("hello").unwrap(); - expect_filesystem_event!(recv, foo_path, EventKind::Create(_)); - - let deep_path = sibling_path.join_components(&["deep", "path"]); - deep_path.create_dir_all().unwrap(); - expect_filesystem_event!( - recv, - sibling_path.join_component("deep"), - EventKind::Create(_) - ); - expect_filesystem_event!(recv, deep_path, EventKind::Create(_)); - expect_watching( - &mut recv, - &[ - &repo_root, - &parent_path, - &child_path, - &deep_path, - &sibling_path.join_component("deep"), - ], - ) - .await; - - let test_file_path = repo_root.join_component("test-file"); - test_file_path - .create_with_contents("test contents") - .unwrap(); - expect_filesystem_event!(recv, test_file_path, EventKind::Create(_)); - - // TODO: implement default filtering (.git, node_modules) - } - - #[tokio::test] - async fn test_file_watching_subfolder_deletion() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - // Delete parent folder during file watching - parent_path.remove_dir_all().unwrap(); - expect_filesystem_event!(recv, parent_path, EventKind::Remove(_)); - - // Ensure we get events when creating file in deleted directory - child_path.create_dir_all().unwrap(); - expect_filesystem_event!(recv, parent_path, EventKind::Create(_)); - expect_filesystem_event!(recv, child_path, EventKind::Create(_)); - - let foo_path = child_path.join_component("foo"); - foo_path.create_with_contents("hello").unwrap(); - expect_filesystem_event!(recv, foo_path, EventKind::Create(_)); - // We cannot guarantee no more events, windows sends multiple delete - // events - } - - #[tokio::test] - async fn test_file_watching_root_deletion() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - repo_root.remove_dir_all().unwrap(); - expect_filesystem_event!(recv, repo_root, EventKind::Remove(_)); - } - - #[tokio::test] - async fn test_file_watching_subfolder_rename() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - let new_parent = repo_root.join_component("new_parent"); - parent_path.rename(&new_parent).unwrap(); - - expect_filesystem_event!(recv, new_parent, EventKind::Modify(ModifyKind::Name(_))); - } - - #[tokio::test] - async fn test_file_watching_root_rename() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (tmp_root, _tmp_repo_root) = temp_dir(); - let tmp_root = tmp_root.to_realpath().unwrap(); - let repo_root = tmp_root.join_component("repo_root"); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - let new_repo_root = repo_root.parent().unwrap().join_component("new_repo_root"); - repo_root.rename(&new_repo_root).unwrap(); - - expect_filesystem_event!(recv, repo_root, EventKind::Modify(ModifyKind::Name(_))); - } - - #[tokio::test] - async fn test_file_watching_symlink_create() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - // Create symlink during file watching - let symlink_path = repo_root.join_component("symlink"); - symlink_path.symlink_to_dir(child_path.as_str()).unwrap(); - expect_filesystem_event!(recv, symlink_path, EventKind::Create(_)); - - // we expect that events in the symlinked directory will be raised with the - // original path - let symlink_subfile = symlink_path.join_component("symlink_subfile"); - symlink_subfile.create_with_contents("hello").unwrap(); - let expected_subfile_path = child_path.join_component("symlink_subfile"); - expect_filesystem_event!(recv, expected_subfile_path, EventKind::Create(_)); - } - - #[tokio::test] - async fn test_file_watching_symlink_delete() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - // symlink -> parent/child - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - let symlink_path = repo_root.join_component("symlink"); - symlink_path.symlink_to_dir(child_path.as_str()).unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - // Delete symlink during file watching - // Note that on Windows, to remove a symlink to a directory - // remove_dir is required. - #[cfg(windows)] - symlink_path.remove_dir().unwrap(); - #[cfg(not(windows))] - symlink_path.remove().unwrap(); - expect_filesystem_event!(recv, symlink_path, EventKind::Remove(_)); - } - - #[tokio::test] - async fn test_file_watching_symlink_rename() { - // Directory layout: - // / - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - // symlink -> parent/child - - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - let symlink_path = repo_root.join_component("symlink"); - symlink_path.symlink_to_dir(child_path.as_str()).unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - // Delete symlink during file watching - let new_symlink_path = repo_root.join_component("new_symlink"); - symlink_path.rename(&new_symlink_path).unwrap(); - expect_filesystem_event!( - recv, - new_symlink_path, - EventKind::Modify(ModifyKind::Name(_)) - ); - } - - // Watching a directory on windows locks it, so we cannot rename it. - // Since we are recursively watching parents, we also cannot rename parents. - // Note the contrast to the root of our watch, which we don't lock, - // but instead rely on watching the parent directory. This means we - // have permission to rename or delete the repo root, but not anything - // else in the path. - #[cfg(not(target_os = "windows"))] - #[tokio::test] - async fn test_file_watching_root_parent_rename() { - // Directory layout: - // repo_parent/ - // repo_root/ - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (tmp_root, _tmp_repo_root) = temp_dir(); - let tmp_root = tmp_root.to_realpath().unwrap().join_component("layer"); - let repo_root = tmp_root.join_components(&["repo_parent", "repo_root"]); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - let repo_parent = repo_root.parent().unwrap(); - let new_parent = tmp_root.join_component("new_parent"); - repo_parent.rename(&new_parent).unwrap(); - - expect_filesystem_event!( - recv, - repo_root, - EventKind::Modify(ModifyKind::Name(RenameMode::From)) - ); - } - - #[tokio::test] - async fn test_file_watching_root_parent_delete() { - // Directory layout: - // repo_parent/ - // repo_root/ - // .git/ - // node_modules/ - // some-dep/ - // parent/ - // child/ - let (tmp_root, _tmp_repo_root) = temp_dir(); - let tmp_root = tmp_root.to_realpath().unwrap(); - let repo_root = tmp_root.join_components(&["repo_parent", "repo_root"]); - - repo_root.join_component(".git").create_dir_all().unwrap(); - repo_root - .join_components(&["node_modules", "some-dep"]) - .create_dir_all() - .unwrap(); - let parent_path = repo_root.join_component("parent"); - let child_path = parent_path.join_component("child"); - child_path.create_dir_all().unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let mut recv = watcher.subscribe().await.unwrap(); - expect_watching(&mut recv, &[&repo_root, &parent_path, &child_path]).await; - - let repo_parent = repo_root.parent().unwrap(); - repo_parent.remove_dir_all().unwrap(); - expect_filesystem_event!( - recv, - repo_root, - EventKind::Modify(ModifyKind::Name(_)) | EventKind::Remove(_) - ); - } - - #[tokio::test] - async fn test_close() { - let (repo_root, _tmp_repo_root) = temp_dir(); - let repo_root = repo_root.to_realpath().unwrap(); - - let mut recv = { - // create and immediately drop the watcher, which should trigger the exit - // channel - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - watcher.subscribe().await.unwrap() - }; - - // There may be spurious events, but we should expect a close in short order - tokio::time::timeout(Duration::from_millis(100), async move { - loop { - if let Err(e) = recv.recv().await { - assert_matches!(e, broadcast::error::RecvError::Closed); - return; - } - } - }) - .await - .unwrap(); - } -} diff --git a/crates/turborepo-filewatch/src/package_watcher.rs b/crates/turborepo-filewatch/src/package_watcher.rs deleted file mode 100644 index ec170a412f3d4..0000000000000 --- a/crates/turborepo-filewatch/src/package_watcher.rs +++ /dev/null @@ -1,997 +0,0 @@ -//! This module hosts the `PackageWatcher` type, which is used to watch the -//! filesystem for changes to packages. - -use std::{ - collections::HashMap, - path::Path, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, - time::Duration, -}; - -use futures::FutureExt; -use notify::Event; -use thiserror::Error; -use tokio::{ - join, select, - sync::{ - broadcast::{self, error::RecvError}, - mpsc, oneshot, watch, - }, -}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; -use turborepo_repository::{ - discovery::{ - DiscoveryResponse, LocalPackageDiscoveryBuilder, PackageDiscovery, PackageDiscoveryBuilder, - WorkspaceData, - }, - package_manager::{self, PackageManager}, - workspaces::WorkspaceGlobs, -}; - -use crate::{ - cookies::{CookieRegister, CookieWriter, CookiedOptionalWatch}, - debouncer::Debouncer, - optional_watch::OptionalWatch, - NotifyError, -}; - -#[derive(Debug, Error)] -enum PackageWatcherProcessError { - #[error("filewatching not available, so package watching is not available")] - Filewatching(watch::error::RecvError), - #[error("filewatching closed, package watching no longer available")] - FilewatchingClosed(broadcast::error::RecvError), -} - -#[derive(Debug, Error)] -pub enum PackageWatchError { - #[error("package layout is in an invalid state {0}")] - InvalidState(String), - #[error("package layout is not available")] - Unavailable, -} - -// If we're in an invalid state, this will be an Err with a description of the -// reason. Typically we don't care though, as the user could be in the middle of -// making a change. -pub(crate) type DiscoveryData = Result; - -// Version is a type that exists to stamp an asynchronous hash computation -// with a version so that we can ignore completion of outdated hash -// computations. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -struct Version(usize); - -struct DiscoveryResult { - version: Version, - state: PackageState, -} - -/// Watches the filesystem for changes to packages and package managers. -pub struct PackageWatcher { - // _exit_ch exists to trigger a close on the receiver when an instance - // of this struct is dropped. The task that is receiving events will exit, - // dropping the other sender for the broadcast channel, causing all receivers - // to be notified of a close. - _exit_tx: oneshot::Sender<()>, - _handle: tokio::task::JoinHandle<()>, - package_discovery_lazy: CookiedOptionalWatch, -} - -impl PackageWatcher { - /// Creates a new package watcher whose current package data can be queried. - /// `backup_discovery` is used to perform the initial discovery of packages, - /// to populate the state before we can watch. - pub fn new( - root: AbsoluteSystemPathBuf, - recv: OptionalWatch>>, - cookie_writer: CookieWriter, - ) -> Result { - let (exit_tx, exit_rx) = oneshot::channel(); - let subscriber = Subscriber::new(root, cookie_writer)?; - let package_discovery_lazy = subscriber.package_discovery(); - let handle = tokio::spawn(subscriber.watch(exit_rx, recv)); - Ok(Self { - _exit_tx: exit_tx, - _handle: handle, - package_discovery_lazy, - }) - } - - pub fn watch_discovery(&self) -> watch::Receiver> { - self.package_discovery_lazy.watch() - } - - pub async fn discover_packages(&self) -> Option> { - tracing::debug!("discovering packages using watcher implementation"); - - // this can either not have a value ready, or the sender has been dropped. in - // either case just report that the value is unavailable - let mut recv = self.package_discovery_lazy.clone(); - recv.get_immediate().await.map(|resp| { - resp.map_err(|_| PackageWatchError::Unavailable) - .and_then(|resp| match resp.to_owned() { - Ok(resp) => Ok(resp), - Err(error_reason) => Err(PackageWatchError::InvalidState(error_reason)), - }) - }) - } - - // if the event that either of the dependencies will never resolve, - // this will still return unavailable - pub async fn discover_packages_blocking(&self) -> Result { - let mut recv = self.package_discovery_lazy.clone(); - recv.get() - .await - .map_err(|_| PackageWatchError::Unavailable) - .and_then(|resp| match resp.to_owned() { - Ok(resp) => Ok(resp), - Err(error_reason) => Err(PackageWatchError::InvalidState(error_reason)), - }) - } -} - -/// The underlying task that listens to file system events and updates the -/// internal package state. -struct Subscriber { - repo_root: AbsoluteSystemPathBuf, - // This is the list of paths that will trigger rediscovering everything. - invalidation_paths: Vec, - - package_discovery_tx: watch::Sender>, - package_discovery_lazy: CookiedOptionalWatch, - cookie_tx: CookieRegister, - next_version: AtomicUsize, -} - -/// PackageWatcher state. We either don't have a valid package manager, -/// don't have valid globs, or we have both a package manager and globs -/// and some maybe-empty set of workspaces. -#[derive(Debug)] -enum PackageState { - NoPackageManager(String), - InvalidGlobs(String), - ValidWorkspaces { - package_manager: PackageManager, - filter: Box, - workspaces: HashMap, - }, -} - -#[derive(Debug)] -enum State { - Pending { - debouncer: Arc, - version: Version, - }, - Ready(Box), -} - -// Because our package manager detection is coupled with the workspace globs, we -// need to recheck all workspaces any time any of these files change. A change -// in any of these might result in a different package manager being detected, -// or going from no package manager to some package manager. -const INVALIDATION_PATHS: &[&str] = &[ - "package.json", - "pnpm-workspace.yaml", - "pnpm-lock.yaml", - "package-lock.json", - "yarn.lock", - "bun.lockb", -]; - -impl Subscriber { - /// Creates a new instance of PackageDiscovery. This will start a task that - /// performs the initial discovery using the `backup_discovery` of your - /// choice, and then listens to file system events to keep the package - /// data up to date. - fn new( - repo_root: AbsoluteSystemPathBuf, - writer: CookieWriter, - ) -> Result { - let (package_discovery_tx, cookie_tx, package_discovery_lazy) = - CookiedOptionalWatch::new(writer); - let invalidation_paths = INVALIDATION_PATHS - .iter() - .map(|p| repo_root.join_component(p)) - .collect(); - Ok(Self { - repo_root, - invalidation_paths, - package_discovery_tx, - package_discovery_lazy, - cookie_tx, - next_version: AtomicUsize::new(0), - }) - } - - fn queue_rediscovery( - &self, - immediate: bool, - package_state_tx: mpsc::Sender, - ) -> (Version, Arc) { - // Every time we're queuing rediscovery, we know our state is no longer valid, - // so reset it for any downstream consumers. - self.reset_discovery_data(); - let version = Version(self.next_version.fetch_add(1, Ordering::SeqCst)); - let debouncer = if immediate { - Debouncer::new(Duration::from_millis(0)) - } else { - Debouncer::default() - }; - let debouncer = Arc::new(debouncer); - let debouncer_copy = debouncer.clone(); - let repo_root = self.repo_root.clone(); - tokio::task::spawn(async move { - debouncer_copy.debounce().await; - let state = discover_packages(repo_root).await; - let _ = package_state_tx - .send(DiscoveryResult { version, state }) - .await; - }); - (version, debouncer) - } - - async fn watch_process( - mut self, - mut recv: OptionalWatch>>, - ) -> PackageWatcherProcessError { - tracing::debug!("starting package watcher"); - let mut recv = match recv.get().await { - Ok(r) => r.resubscribe(), - Err(e) => return PackageWatcherProcessError::Filewatching(e), - }; - - let (package_state_tx, mut package_state_rx) = mpsc::channel::(256); - - let (version, debouncer) = self.queue_rediscovery(true, package_state_tx.clone()); - - // state represents the current state of this process, and is expected to be - // updated in place by the various handler functions. - let mut state = State::Pending { debouncer, version }; - - tracing::debug!("package watcher ready {:?}", state); - loop { - select! { - Some(discovery_result) = package_state_rx.recv() => { - self.handle_discovery_result(discovery_result, &mut state); - }, - file_event = recv.recv() => { - match file_event { - Ok(Ok(event)) => self.handle_file_event(&mut state, &event, &package_state_tx).await, - // if we get an error, we need to re-discover the packages - Ok(Err(_)) => self.bump_or_queue_rediscovery(&mut state, &package_state_tx), - Err(e @ RecvError::Closed) => { - return PackageWatcherProcessError::FilewatchingClosed(e) - } - // if we end up lagging, warn and rediscover packages - Err(RecvError::Lagged(count)) => { - tracing::warn!("lagged behind {count} processing file watching events"); - self.bump_or_queue_rediscovery(&mut state, &package_state_tx); - } - } - } - } - tracing::trace!("package watcher state: {:?}", state); - } - } - - fn handle_discovery_result(&self, package_result: DiscoveryResult, state: &mut State) { - if let State::Pending { version, .. } = state { - // If this response matches an outstanding rediscovery request, write out the - // corresponding state to downstream consumers and update our state - // accordingly. - // - // Note that depending on events that we received since this request was queued, - // we may have a higher version number, at which point we would - // ignore this update, as we know it is stale. - if package_result.version == *version { - self.write_state(&package_result.state); - *state = State::Ready(Box::new(package_result.state)); - } - } - } - - async fn watch( - self, - exit_rx: oneshot::Receiver<()>, - recv: OptionalWatch>>, - ) { - let process = tokio::spawn(self.watch_process(recv)); - tokio::select! { - biased; - _ = exit_rx => { - tracing::debug!("exiting package watcher due to signal"); - }, - err = process => { - if let Ok(err) = err { - tracing::debug!("exiting package watcher due to {err}"); - } else { - tracing::debug!("package watcher process exited"); - } - } - } - } - - fn package_discovery(&self) -> CookiedOptionalWatch { - self.package_discovery_lazy.clone() - } - - fn path_invalidates_everything(&self, path: &Path) -> bool { - self.invalidation_paths - .iter() - .any(|invalidation_path| path.eq(invalidation_path as &AbsoluteSystemPath)) - } - - async fn handle_file_event( - &mut self, - state: &mut State, - file_event: &Event, - package_state_tx: &mpsc::Sender, - ) { - tracing::trace!("file event: {:?} {:?}", file_event.kind, file_event.paths); - - if file_event - .paths - .iter() - .any(|path| self.path_invalidates_everything(path)) - { - // root package.json changed, rediscover everything - //*state = self.rediscover_and_write_state().await; - self.bump_or_queue_rediscovery(state, package_state_tx); - } else { - tracing::trace!("handling non-root package.json change"); - self.handle_workspace_changes(state, file_event, package_state_tx) - .await; - } - - tracing::trace!("updating the cookies"); - - // now that we have updated the state, we should bump the cookies so that - // people waiting on downstream cookie watchers can get the new state - self.cookie_tx.register( - &file_event - .paths - .iter() - .map(|p| AbsoluteSystemPath::from_std_path(p).expect("these paths are absolute")) - .collect::>(), - ); - } - - fn bump_or_queue_rediscovery( - &self, - state: &mut State, - package_state_tx: &mpsc::Sender, - ) { - if let State::Pending { debouncer, .. } = state { - if debouncer.bump() { - // We successfully bumped the debouncer, which was already pending, - // so a new discovery will happen shortly. - return; - } - } - // We either failed to bump the debouncer, or we don't have a rediscovery - // queued, but we need one. - let (version, debouncer) = self.queue_rediscovery(false, package_state_tx.clone()); - *state = State::Pending { debouncer, version } - } - - // checks if the file event contains any changes to package.json files, or - // directories that would map to a workspace. - async fn handle_workspace_changes( - &mut self, - state: &mut State, - file_event: &Event, - package_state_tx: &mpsc::Sender, - ) { - let package_state = match state { - State::Pending { .. } => { - // We can't assess this event until we have a valid package manager. To be safe, - // bump or queue another rediscovery, since this could race with the discovery - // in progress. - self.bump_or_queue_rediscovery(state, package_state_tx); - return; - } - State::Ready(package_state) => package_state, - }; - - // If we don't have a valid package manager and workspace globs, nothing to be - // done here - let PackageState::ValidWorkspaces { - ref filter, - ref mut workspaces, - .. - } = **package_state - else { - return; - }; - - // here, we can only update if we have a valid package state - let mut changed = false; - // if a path is not a valid utf8 string, it is not a valid path, so ignore - for path in file_event - .paths - .iter() - .filter_map(|p| p.as_os_str().to_str()) - { - let path_file = AbsoluteSystemPathBuf::new(path).expect("watched paths are absolute"); - let path_workspace: &AbsoluteSystemPath = - if path_file.file_name() == Some("package.json") { - // The file event is for a package.json file. Check if the parent is a workspace - let path_parent = path_file - .parent() - .expect("watched paths will not be at the root"); - if filter - .target_is_workspace(&self.repo_root, path_parent) - .unwrap_or(false) - { - path_parent - } else { - // irrelevant package.json file update, it's not in a directory - // matching workspace globs - continue; - } - } else if filter - .target_is_workspace(&self.repo_root, &path_file) - .unwrap_or(false) - { - // The file event is for a workspace directory itself - &path_file - } else { - // irrelevant file update, it's not a package.json file or a workspace directory - continue; - }; - - tracing::debug!("handling change to workspace {path_workspace}"); - let package_json = path_workspace.join_component("package.json"); - let turbo_json = path_workspace.join_component("turbo.json"); - - let (package_exists, turbo_exists) = join!( - // It's possible that an IO error could occur other than the file not existing, but - // we will treat it like the file doesn't exist. It's possible we'll need to - // revisit this, depending on what kind of errors occur. - tokio::fs::try_exists(&package_json).map(|result| result.unwrap_or(false)), - tokio::fs::try_exists(&turbo_json) - ); - - changed |= if package_exists { - workspaces - .insert( - path_workspace.to_owned(), - WorkspaceData { - package_json, - turbo_json: turbo_exists.unwrap_or_default().then_some(turbo_json), - }, - ) - .is_none() - } else { - workspaces.remove(path_workspace).is_some() - } - } - - if changed { - self.write_state(package_state); - } - } - - fn reset_discovery_data(&self) { - self.package_discovery_tx.send_if_modified(|existing| { - if existing.is_some() { - *existing = None; - true - } else { - false - } - }); - } - - fn write_state(&self, state: &PackageState) { - match state { - PackageState::NoPackageManager(e) | PackageState::InvalidGlobs(e) => { - self.package_discovery_tx.send_if_modified(|existing| { - let error_msg = e.to_string(); - match existing { - Some(Err(existing_error)) if *existing_error == error_msg => false, - Some(_) | None => { - *existing = Some(Err(error_msg)); - true - } - } - }); - } - PackageState::ValidWorkspaces { - package_manager, - workspaces, - .. - } => { - let resp = DiscoveryResponse { - package_manager: package_manager.clone(), - workspaces: workspaces.values().cloned().collect(), - }; - // Note that we could implement PartialEq for DiscoveryResponse, but we - // would need to sort the workspace data. - let _ = self.package_discovery_tx.send(Some(Ok(resp))); - } - } - } -} - -async fn discover_packages(repo_root: AbsoluteSystemPathBuf) -> PackageState { - // If we're rediscovering everything, we need to rediscover the package manager. - // It may have changed if a lockfile changed or package.json changed. - let discovery = match LocalPackageDiscoveryBuilder::new(repo_root.clone(), None, None).build() { - Ok(discovery) => discovery, - Err(e) => return PackageState::NoPackageManager(e.to_string()), - }; - let initial_discovery = match discovery.discover_packages().await { - Ok(discovery) => discovery, - Err(e) => { - tracing::debug!("failed to rediscover packages: {}", e); - return PackageState::NoPackageManager(e.to_string()); - } - }; - - tracing::debug!("rediscovered packages: {:?}", initial_discovery); - let filter = match initial_discovery - .package_manager - .get_workspace_globs(&repo_root) - { - Ok(filter) => filter, - Err(e) => { - tracing::debug!("failed to get workspace globs: {}", e); - return PackageState::InvalidGlobs(e.to_string()); - } - }; - - let workspaces = initial_discovery - .workspaces - .into_iter() - .map(|p| (p.package_json.parent().expect("non-root").to_owned(), p)) - .collect::>(); - PackageState::ValidWorkspaces { - package_manager: initial_discovery.package_manager, - filter: Box::new(filter), - workspaces, - } -} - -#[cfg(test)] -mod test { - use std::time::Duration; - - use turbopath::AbsoluteSystemPathBuf; - use turborepo_repository::{discovery::WorkspaceData, package_manager::PackageManager}; - - use crate::{cookies::CookieWriter, package_watcher::PackageWatcher, FileSystemWatcher}; - - #[tokio::test] - #[tracing_test::traced_test] - async fn subscriber_test() { - let tmp = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let package_data = vec![ - WorkspaceData { - package_json: repo_root.join_components(&["packages", "foo", "package.json"]), - turbo_json: None, - }, - WorkspaceData { - package_json: repo_root.join_components(&["packages", "bar", "package.json"]), - turbo_json: None, - }, - ]; - - // create folders and files - for data in &package_data { - data.package_json.ensure_dir().unwrap(); - let name = data.package_json.parent().unwrap().file_name().unwrap(); - data.package_json - .create_with_contents(format!("{{\"name\": \"{name}\"}}")) - .unwrap(); - } - repo_root - .join_component("package-lock.json") - .create_with_contents("") - .unwrap(); - - // write workspaces to root - repo_root - .join_component("package.json") - .create_with_contents( - r#"{"workspaces":["packages/*"], "packageManager": "npm@10.0.0"}"#, - ) - .unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let recv = watcher.watch(); - let cookie_writer = CookieWriter::new( - watcher.cookie_dir(), - Duration::from_millis(100), - recv.clone(), - ); - - let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); - - let mut data = package_watcher.discover_packages_blocking().await.unwrap(); - data.workspaces - .sort_by_key(|workspace| workspace.package_json.clone()); - assert_eq!( - data.workspaces, - vec![ - WorkspaceData { - package_json: repo_root.join_components(&["packages", "bar", "package.json",]), - turbo_json: None, - }, - WorkspaceData { - package_json: repo_root.join_components(&["packages", "foo", "package.json",]), - turbo_json: None, - }, - ] - ); - - tracing::info!("removing subpackage"); - - // delete package.json in foo - repo_root - .join_components(&["packages", "foo", "package.json"]) - .remove_file() - .unwrap(); - - let mut data = package_watcher.discover_packages_blocking().await.unwrap(); - data.workspaces - .sort_by_key(|workspace| workspace.package_json.clone()); - assert_eq!( - data.workspaces, - vec![WorkspaceData { - package_json: repo_root.join_components(&["packages", "bar", "package.json"]), - turbo_json: None, - }] - ); - - // move package bar - repo_root - .join_components(&["packages", "bar"]) - .rename(&repo_root.join_component("bar")) - .unwrap(); - - let mut data = package_watcher.discover_packages_blocking().await.unwrap(); - data.workspaces - .sort_by_key(|workspace| workspace.package_json.clone()); - assert_eq!(data.workspaces, vec![]); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn subscriber_update_workspaces() { - let tmp = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let package_data = vec![ - WorkspaceData { - package_json: repo_root - .join_component("packages") - .join_component("foo") - .join_component("package.json"), - turbo_json: None, - }, - WorkspaceData { - package_json: repo_root - .join_component("packages2") - .join_component("bar") - .join_component("package.json"), - turbo_json: None, - }, - ]; - - // create folders and files - for data in &package_data { - data.package_json.ensure_dir().unwrap(); - let name = data.package_json.parent().unwrap().file_name().unwrap(); - data.package_json - .create_with_contents(format!("{{\"name\": \"{name}\"}}")) - .unwrap(); - } - repo_root - .join_component("package-lock.json") - .create_with_contents("") - .unwrap(); - - // write workspaces to root - repo_root - .join_component("package.json") - .create_with_contents( - r#"{"workspaces":["packages/*", "packages2/*"], "packageManager": "npm@10.0.0"}"#, - ) - .unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let recv = watcher.watch(); - let cookie_writer = CookieWriter::new( - watcher.cookie_dir(), - Duration::from_millis(100), - recv.clone(), - ); - - let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); - - let mut data = package_watcher.discover_packages_blocking().await.unwrap(); - data.workspaces - .sort_by_key(|workspace| workspace.package_json.clone()); - - assert_eq!( - data.workspaces, - vec![ - WorkspaceData { - package_json: repo_root - .join_component("packages") - .join_component("foo") - .join_component("package.json"), - turbo_json: None, - }, - WorkspaceData { - package_json: repo_root - .join_component("packages2") - .join_component("bar") - .join_component("package.json"), - turbo_json: None, - }, - ] - ); - - // update workspaces to no longer cover packages2 - repo_root - .join_component("package.json") - .create_with_contents( - r#"{"workspaces":["packages/*"], "packageManager": "npm@10.0.0"}"#, - ) - .unwrap(); - - let mut data = package_watcher.discover_packages_blocking().await.unwrap(); - data.workspaces - .sort_by_key(|workspace| workspace.package_json.clone()); - - assert_eq!( - data.workspaces, - vec![WorkspaceData { - package_json: repo_root - .join_component("packages") - .join_component("foo") - .join_component("package.json"), - turbo_json: None, - }] - ); - - // move the packages2 workspace into package - repo_root - .join_components(&["packages2", "bar"]) - .rename(&repo_root.join_components(&["packages", "bar"])) - .unwrap(); - let mut data = package_watcher.discover_packages_blocking().await.unwrap(); - data.workspaces - .sort_by_key(|workspace| workspace.package_json.clone()); - assert_eq!( - data.workspaces, - vec![ - WorkspaceData { - package_json: repo_root - .join_component("packages") - .join_component("bar") - .join_component("package.json"), - turbo_json: None, - }, - WorkspaceData { - package_json: repo_root - .join_component("packages") - .join_component("foo") - .join_component("package.json"), - turbo_json: None, - }, - ] - ); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn pnpm_invalid_states_test() { - let tmp = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let workspaces_path = repo_root.join_component("pnpm-workspace.yaml"); - // Currently we require valid state to start the daemon - let root_package_json_path = repo_root.join_component("package.json"); - // Start with no workspace glob - root_package_json_path - .create_with_contents(r#"{"packageManager": "pnpm@7.0.0"}"#) - .unwrap(); - repo_root - .join_component("pnpm-lock.yaml") - .create_with_contents("") - .unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let recv = watcher.watch(); - let cookie_writer = CookieWriter::new( - watcher.cookie_dir(), - Duration::from_millis(100), - recv.clone(), - ); - - let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); - - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - workspaces_path - .create_with_contents(r#"packages: ["foo/*"]"#) - .unwrap(); - - let resp = package_watcher.discover_packages_blocking().await.unwrap(); - assert_eq!(resp.package_manager, PackageManager::Pnpm); - - // Remove workspaces file, verify we get an error - workspaces_path.remove_file().unwrap(); - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - // // Create an invalid workspace glob - workspaces_path - .create_with_contents(r#"packages: ["foo/***"]"#) - .unwrap(); - - // we should still get an error since we don't have a valid glob - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - // Set it back to valid, ensure we recover - workspaces_path - .create_with_contents(r#"packages: ["foo/*"]"#) - .unwrap(); - - let resp = package_watcher.discover_packages_blocking().await.unwrap(); - assert_eq!(resp.package_manager, PackageManager::Pnpm); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn npm_invalid_states_test() { - let tmp = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()) - .unwrap() - .to_realpath() - .unwrap(); - - // Currently we require valid state to start the daemon - let root_package_json_path = repo_root.join_component("package.json"); - // Start with no workspace glob - root_package_json_path - .create_with_contents(r#"{"packageManager": "npm@7.0.0"}"#) - .unwrap(); - repo_root - .join_component("package-lock.json") - .create_with_contents("") - .unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let recv = watcher.watch(); - let cookie_writer = CookieWriter::new( - watcher.cookie_dir(), - Duration::from_millis(100), - recv.clone(), - ); - - let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); - // expect an error, we don't have a workspaces glob - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - root_package_json_path - .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/*"]}"#) - .unwrap(); - - let resp = package_watcher.discover_packages_blocking().await.unwrap(); - assert_eq!(resp.package_manager, PackageManager::Npm); - - // Remove workspaces file, verify we get an error - root_package_json_path.remove_file().unwrap(); - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - // Create an invalid workspace glob - root_package_json_path - .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/***"]}"#) - .unwrap(); - - // We expect an error due to invalid workspace glob - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - // Set it back to valid, ensure we recover - root_package_json_path - .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/*"]}"#) - .unwrap(); - let resp = package_watcher.discover_packages_blocking().await.unwrap(); - assert_eq!(resp.package_manager, PackageManager::Npm); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn test_change_package_manager() { - let tmp = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let workspaces_path = repo_root.join_component("pnpm-workspace.yaml"); - workspaces_path - .create_with_contents(r#"packages: ["foo/*"]"#) - .unwrap(); - // Currently we require valid state to start the daemon - let root_package_json_path = repo_root.join_component("package.json"); - // Start with no workspace glob - root_package_json_path - .create_with_contents(r#"{"packageManager": "pnpm@7.0.0"}"#) - .unwrap(); - let pnpm_lock_file = repo_root.join_component("pnpm-lock.yaml"); - pnpm_lock_file.create_with_contents("").unwrap(); - - let watcher = FileSystemWatcher::new_with_default_cookie_dir(&repo_root).unwrap(); - let recv = watcher.watch(); - let cookie_writer = CookieWriter::new( - watcher.cookie_dir(), - Duration::from_millis(100), - recv.clone(), - ); - - let package_watcher = PackageWatcher::new(repo_root.clone(), recv, cookie_writer).unwrap(); - - let resp = package_watcher.discover_packages_blocking().await.unwrap(); - assert_eq!(resp.package_manager, PackageManager::Pnpm); - - workspaces_path.remove_file().unwrap(); - // No more workspaces file, verify we're in an invalid state - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - let npm_lock_file = repo_root.join_component("package-lock.json"); - npm_lock_file.create_with_contents("").unwrap(); - // now we have an npm lockfile, but we don't have workspaces. Still invalid - package_watcher - .discover_packages_blocking() - .await - .unwrap_err(); - - // update package.json to complete the transition - root_package_json_path - .create_with_contents(r#"{"packageManager": "npm@7.0.0", "workspaces": ["foo/*"]}"#) - .unwrap(); - let resp = package_watcher.discover_packages_blocking().await.unwrap(); - assert_eq!(resp.package_manager, PackageManager::Npm); - } -} diff --git a/crates/turborepo-fs/Cargo.toml b/crates/turborepo-fs/Cargo.toml index 00207148f26aa..e6a05390c470a 100644 --- a/crates/turborepo-fs/Cargo.toml +++ b/crates/turborepo-fs/Cargo.toml @@ -1,14 +1,3 @@ -[package] -name = "turborepo-fs" -version = "0.1.0" -license = "MIT" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] fs-err = "2.9.0" ignore = "0.4.22" @@ -18,3 +7,15 @@ turbopath = { workspace = true } [dev-dependencies] tempfile = { workspace = true } test-case = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-fs" +version = "0.1.0" diff --git a/crates/turborepo-fs/src/lib.rs b/crates/turborepo-fs/Source/lib.rs similarity index 100% rename from crates/turborepo-fs/src/lib.rs rename to crates/turborepo-fs/Source/lib.rs diff --git a/crates/turborepo-globwalk/Cargo.toml b/crates/turborepo-globwalk/Cargo.toml index 55a113e17d388..2bd0a5217a73d 100644 --- a/crates/turborepo-globwalk/Cargo.toml +++ b/crates/turborepo-globwalk/Cargo.toml @@ -1,27 +1,38 @@ -[package] -name = "globwalk" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] camino = { workspace = true } -itertools.workspace = true path-clean = "1.0.1" path-slash = "0.2.1" rayon = "1" -regex.workspace = true -thiserror.workspace = true tracing = "0.1.37" -turbopath.workspace = true walkdir = "2.3.3" -wax.workspace = true + +[dependencies.itertools] +workspace = true + +[dependencies.regex] +workspace = true + +[dependencies.thiserror] +workspace = true + +[dependencies.turbopath] +workspace = true + +[dependencies.wax] +workspace = true [dev-dependencies] tempfile = { workspace = true } test-case = "3.1.0" + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "globwalk" +version = "0.1.0" diff --git a/crates/turborepo-globwalk/src/lib.rs b/crates/turborepo-globwalk/Source/lib.rs similarity index 100% rename from crates/turborepo-globwalk/src/lib.rs rename to crates/turborepo-globwalk/Source/lib.rs diff --git a/crates/turborepo-globwatch/Cargo.toml b/crates/turborepo-globwatch/Cargo.toml index 1bfba17e0cd25..eac5886009527 100644 --- a/crates/turborepo-globwatch/Cargo.toml +++ b/crates/turborepo-globwatch/Cargo.toml @@ -1,16 +1,5 @@ -[package] -name = "globwatch" -version = "0.1.0" -edition = "2021" -description = "Watch a set of globs efficiently" -license = "MIT OR Apache-2.0" - -[lints] -workspace = true - [dependencies] futures = { version = "0.3.26" } -itertools.workspace = true merge-streams = "0.1.2" notify = { workspace = true } stop-token = "0.7.0" @@ -21,6 +10,9 @@ tracing = "0.1.37" turbopath = { workspace = true } unic-segment = "0.9.0" +[dependencies.itertools] +workspace = true + [dev-dependencies] test-case = "3.0.0" tokio = { version = "1.25.0", features = [ @@ -31,3 +23,16 @@ tokio = { version = "1.25.0", features = [ ] } tracing-subscriber = "0.3.16" tracing-test = "0.2.4" + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +description = "Watch a set of globs efficiently" +edition = "2021" +license-file = "LICENSE" +name = "globwatch" +version = "0.1.0" diff --git a/crates/turborepo-globwatch/Source/lib.rs b/crates/turborepo-globwatch/Source/lib.rs new file mode 100644 index 0000000000000..f5b96889b98a9 --- /dev/null +++ b/crates/turborepo-globwatch/Source/lib.rs @@ -0,0 +1,622 @@ +//! A wrapper around notify that allows for glob-based watching. +//! +//! ## What is flushing? +//! +//! On certain filesystems, file events are not guaranteed to be delivered in +//! the correct order, or on time. This can cause issues when trying to +//! determine if a file has changed, as we don't want to register a watcher +//! for a file if we are not 'up to date'. The flushing mechanism allows us to +//! watch for a full round trip through the filesystem to ensure the watcher is +//! up to date. + +#![allow(clippy::all)] +#![deny( + missing_docs, + missing_debug_implementations, + missing_copy_implementations, + clippy::unwrap_used, + unused_must_use, + unsafe_code +)] +#![feature(extract_if)] + +use std::{ + collections::HashMap, + fs::File, + io, + path::{Path, PathBuf}, + sync::{ + Arc, + Mutex, + atomic::{AtomicU64, Ordering}, + }, +}; + +use futures::{FutureExt, Stream, StreamExt as _, channel::oneshot, future::Either}; +use itertools::Itertools; +use merge_streams::MergeStreams; +pub use notify::{Event, Watcher}; +pub use stop_token::{StopSource, StopToken, TimedOutError, stream::StreamExt}; +use thiserror::Error; +use tokio::sync::{ + mpsc::{UnboundedReceiver, UnboundedSender}, + watch, +}; +use tokio_stream::wrappers::UnboundedReceiverStream; +use tracing::{Level, error, event, span, trace, warn}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathError}; + +/// WatchError wraps errors produced by GlobWatcher +#[derive(Debug, Error)] +pub enum WatchError { + // TODO: find a generic way to include the path in these errors + /// PathError wraps errors encountered dealing with paths while filewatching + #[error("Filewatching encountered a path error: {0}")] + PathError(#[from] PathError), + /// IO wraps IO errors encountered while attempting to watch the filesystem + #[error("Filewatching encountered an IO Error: {0}")] + IO(#[from] io::Error), + /// Backend wraps errors produced from the underlying filewatching + /// implementation. + #[error("Filewatching backend error: {0}")] + Backend(#[from] notify::Error), +} + +/// A wrapper around notify that allows for glob-based watching. +#[derive(Debug)] +pub struct GlobWatcher { + stream:UnboundedReceiver, + flush_dir:AbsoluteSystemPathBuf, + + config:UnboundedReceiver, + setup_handle:tokio::task::JoinHandle>, +} + +impl GlobWatcher { + /// Create a new watcher, using the given flush directory as a temporary + /// storage when flushing file events. For more information on flushing, + /// see the module-level documentation. + #[tracing::instrument] + pub fn new( + flush_dir:&AbsoluteSystemPath, + ) -> Result<(Self, WatchConfig), WatchError> { + let (send_event, receive_event) = tokio::sync::mpsc::unbounded_channel(); + let (send_config, receive_config) = tokio::sync::mpsc::unbounded_channel(); + + flush_dir.create_dir_all()?; + let flush_dir = flush_dir.to_realpath()?; + + let watcher = notify::recommended_watcher(move |event:Result| { + let span = span!(tracing::Level::TRACE, "watcher"); + let _ = span.enter(); + + let result = event.map(|e| { + trace!(parent: &span, "sending event: {:?}", e); + let tx = send_event.clone(); + futures::executor::block_on(async move { tx.send(e) }) + }); + + match result { + Ok(Ok(_)) => {}, + Ok(Err(e)) => { + warn!(parent: &span, "watch server closed: {:?}", e); + }, + Err(e) => { + warn!(parent: &span, "error from notify: {:?}", e); + }, + } + })?; + + let watcher = Arc::new(Mutex::new(watcher)); + + // registering to watch this directory takes a few ms, + // so we just fire and forget a thread to do it in the + // background, to cut our startup time in half. + let flush = watcher.clone(); + let flush_watch_path = flush_dir.clone(); + let (setup_broadcaster, setup_receiver) = watch::channel(None); + let setup_handle = tokio::task::spawn_blocking(move || { + if let Err(e) = flush + .lock() + .expect("only fails if poisoned") + .watch(flush_watch_path.as_std_path(), notify::RecursiveMode::Recursive) + { + warn!("failed to watch flush dir: {}", e); + if setup_broadcaster.send(Some(false)).is_err() { + trace!("failed to notify failed flush watch"); + } + Err(e) + } else { + trace!("watching flush dir: {:?}", flush_watch_path); + if setup_broadcaster.send(Some(true)).is_err() { + trace!("failed to notify successful flush watch"); + } + Ok(()) + } + }); + + Ok(( + Self { flush_dir, stream:receive_event, config:receive_config, setup_handle }, + WatchConfig { flush:send_config, watcher, setup_receiver }, + )) + } +} + +impl GlobWatcher { + /// Convert the watcher into a stream of events, handling config changes and + /// flushing transparently. + /// + /// This is implemented as a zipped stream which processes filesystem events + /// and config changes driven by the same stream. This allows us to ensure + /// that anything watching for filesystem is also propagating config changes + pub fn into_stream( + self, + token:stop_token::StopToken, + ) -> impl Stream, TimedOutError>> + + Send + + Sync + + 'static + + Unpin { + let Self { setup_handle, flush_dir, .. } = self; + let flush_id = Arc::new(AtomicU64::new(1)); + let flush_dir = Arc::new(flush_dir); + let flush = Arc::new(Mutex::new(HashMap::>::new())); + + // Wait until we have watched the flush directory, before we start processing + // events + + // we need to map this to the correct error type + let setup_stream = setup_handle.into_stream().map(|setup_result| { + match setup_result.expect("globwatch setup thread panicked") { + Ok(()) => Ok(WatcherCommand::Start), + Err(e) => { + error!("failed to start server: {}", e); + Err(ConfigError::ServerFailedToStart) + }, + } + }); + + Box::pin( + ( + UnboundedReceiverStream::new(self.stream).map(Either::Left), + setup_stream + .chain(UnboundedReceiverStream::new(self.config).map(Result::Ok)) + .map(Either::Right), + ) + .merge() + // apply a filter_map, yielding only valid events and consuming config changes and + // flushes + .filter_map(move |f| { + let span = span!(tracing::Level::TRACE, "stream_processor"); + let _ = span.enter(); + + // clone all the Arcs needed + let flush_id = flush_id.clone(); + let flush_dir = flush_dir.clone(); + let flush = flush.clone(); + + async move { + match f { + Either::Left(mut e) => { + // if we receive an event for a file in the flush dir, we need to + // remove it from the events list, and send a signal to the flush + // requester. flushes should not be considered as events. + for flush_id in e + .paths + .extract_if(|p| p.starts_with(flush_dir.as_path())) + .filter_map(|p| { + get_flush_id( + p.strip_prefix(flush_dir.as_path()) + .expect("confirmed above"), + ) + }) + { + trace!("flushing {:?}", flush); + if let Some(tx) = flush + .lock() + .expect("only fails if holder panics") + .remove(&flush_id) + { + // if this fails, it just means the requester has gone away + // and we can ignore it + tx.send(()).ok(); + } + } + + // if we have any paths left on the event, yield it + if !e.paths.is_empty() { + event!(parent: &span, Level::TRACE, "yielding {:?}", e); + Some(Ok(e)) + } else { + None + } + } + Either::Right(Ok(WatcherCommand::Start)) => { + trace!("setting up watching flush directory has completed"); + None + } + Either::Right(Ok(WatcherCommand::Flush(tx))) => { + // create file in flush dir + let flush_id = flush_id.fetch_add(1, Ordering::SeqCst); + let flush_file = flush_dir.join_component(&flush_id.to_string()); + if let Err(e) = File::create(flush_file) { + warn!("failed to create flush file: {}", e); + } else { + flush + .lock() + .expect("only fails if holder panics") + .insert(flush_id, tx); + } + None + } + Either::Right(Err(e)) => Some(Err(e)), + } + } + }) + .timeout_at(token), + ) + } +} + +fn get_flush_id(relative_path:&Path) -> Option { + relative_path.file_name().and_then(|p| p.to_str()).and_then(|p| p.parse().ok()) +} + +/// A configuration change to the watcher. +#[derive(Debug)] +pub enum WatcherCommand { + /// A marker command showing that watcher startup completed successfully + Start, + /// A request to flush the watcher. + Flush(oneshot::Sender<()>), +} + +/// A sender for watcher configuration changes. +#[derive(Debug, Clone)] +pub struct WatchConfig { + flush:UnboundedSender, + watcher:Arc>, + setup_receiver:watch::Receiver>, +} + +/// The server is no longer running. +#[derive(Debug)] +pub enum ConfigError { + /// The server is no longer running. + ServerStopped, + /// Watch error + WatchError(Vec), + /// The server has already been consumed. + WatchingAlready, + /// We were unable to watch the flush directory + ServerFailedToStart, +} + +impl WatchConfig { + /// Register a glob to be included by the watcher. + #[tracing::instrument(skip(self))] + pub async fn include(&self, relative_to:&Path, glob:&str) -> Result<(), ConfigError> { + trace!("including {:?}", glob); + + glob_to_paths(glob) + .iter() + .map(|p| relative_to.join(p)) + .map(|p| { + trace!("watching {:?}", p); + self.watcher + .lock() + .expect("only fails if poisoned") + .watch(&p, notify::RecursiveMode::Recursive) + }) + .map(|r| { + match r { + Ok(()) => Ok(()), + Err(notify::Error { kind: notify::ErrorKind::PathNotFound, .. }) => { + // if the path we are trying to watch doesn't exist + // it is not immediately an error; glob_to_paths + // will generate paths that potentially don't exist, + // since it doesn't walk the fs, no no-op + Ok(()) + }, + Err(notify::Error { kind: notify::ErrorKind::Generic(s), .. }) + if s.contains("No such file or directory") + || s.eq("Input watch path is neither a file nor a directory.") => + { + Ok(()) + }, + Err(e) => Err(e), + } + }) + .fold(Ok(()), |acc, next| { + match (acc, next) { + (Ok(()), Ok(())) => Ok(()), + (Ok(()), Err(e)) => Err(vec![e]), + (Err(acc), Ok(())) => Err(acc), + (Err(mut acc), Err(e)) => { + acc.push(e); + Err(acc) + }, + } + }) + .map_err(ConfigError::WatchError) + } + + /// Register a single path to be included by the watcher. + pub async fn include_path(&self, path:&Path) -> Result<(), ConfigError> { + trace!("watching {:?}", path); + // Windows doesn't create an event when a watched directory itself is deleted + // we watch the parent directory instead. + // More information at https://github.com/notify-rs/notify/issues/403 + #[cfg(windows)] + let watched_path = path.parent().expect("turbo is unusable at filesystem root"); + #[cfg(not(windows))] + let watched_path = path; + + self.watcher + .lock() + .expect("watcher lock poisoned") + .watch(watched_path, notify::RecursiveMode::NonRecursive) + .map_err(|e| ConfigError::WatchError(vec![e])) + } + + /// Register a glob to be excluded by the watcher. + #[tracing::instrument(skip(self))] + pub async fn exclude(&self, relative_to:&Path, glob:&str) { + trace!("excluding {:?}", glob); + + for p in glob_to_paths(glob).iter().map(|p| relative_to.join(p)) { + // we don't care if this fails, it's just a best-effort + self.watcher.lock().expect("only fails if poisoned").unwatch(&p).ok(); + } + } +} + +impl WatchConfig { + /// Await a full filesystem flush from the watcher. + pub async fn flush(&self) -> Result<(), ConfigError> { + let mut setup_rx = self.setup_receiver.clone(); + // TODO once upgraded to tokio 1.27 use wait_until + while (*setup_rx.borrow()).is_none() { + // If this fails that means the channel was closed forcefully by the sender + if setup_rx.changed().await.is_err() { + return Err(ConfigError::ServerFailedToStart); + } + } + if *setup_rx.borrow() == Some(false) { + return Err(ConfigError::ServerFailedToStart); + } + + let (tx, rx) = oneshot::channel(); + self.flush + .send(WatcherCommand::Flush(tx)) + .map_err(|_| ConfigError::ServerStopped)?; + rx.await.map_err(|_| ConfigError::ServerStopped) + } +} + +#[derive(PartialEq, Eq, Debug)] +enum GlobSymbol<'a> { + Char(&'a [u8]), + OpenBracket, + CloseBracket, + OpenBrace, + CloseBrace, + Star, + DoubleStar, + Question, + Negation, + PathSeparator, +} + +/// Gets the minimum set of paths that can be watched for a given glob, +/// specified in minimatch glob syntax. +/// +/// syntax: +/// ? Matches any single character. +/// +/// *  Matches zero or more characters, except for path separators. +/// +/// ** Matches zero or more characters, including path separators. +/// Must match a complete path segment. +/// +/// [ab] Matches one of the characters contained in the brackets. +/// Character ranges, e.g. [a-z] are also supported. Use [!ab] or [^ab] +/// to match any character except those contained in the brackets. +/// +/// {a,b} Matches one of the patterns contained in the braces. Any of the +/// wildcard characters can be used in the sub-patterns. Braces may +/// be nested up to 10 levels deep. +/// +/// ! When at the start of the glob, this negates the result. +/// Multiple ! characters negate the glob multiple times. +/// +/// \ A backslash character may be used to escape any special characters. +/// +/// Of these, we only handle `{` and escaping. +/// +/// note: it is currently extremely conservative, handling only `**`, braces, +/// and `?`. any other case watches the entire directory. +fn glob_to_paths(glob:&str) -> Vec { + // get all the symbols and chunk them by path separator + let chunks = glob_to_symbols(glob).group_by(|s| s != &GlobSymbol::PathSeparator); + let chunks = chunks.into_iter().filter_map(|(not_sep, chunk)| (not_sep).then_some(chunk)); + + // multi cartisian product allows us to get all the possible combinations + // of path components for each chunk. for example, if we have a glob + // `{a,b}/1/{c,d}`, it will lazily yield the following sets of segments: + // ["a", "1", "c"] + // ["a", "1", "d"] + // ["b", "1", "c"] + // ["b", "1", "d"] + + chunks + .map(symbols_to_combinations) // yield all the possible segments for each glob chunk + .take_while(|c| c.is_some()) // if any segment has no possible paths, we can stop + .flatten() + .multi_cartesian_product() // get all the possible combinations of path segments + .map(|chunks| { + let prefix = if glob.starts_with('/') { "/" } else { "" }; + std::iter::once(prefix) + .chain(chunks.iter().map(|s| s.as_str())) + .collect::() + }) + .collect() +} + +/// given a set of symbols, returns an iterator over the possible path segments +/// that can be generated from them. this currently is very conservative, and +/// simply ejects if it encounters glob-like symbols. in the future, we should +/// handle brackets and braces. +/// +/// example: given the symbols "{a,b}b" it will yield ["ab"] and ["bb"] +fn symbols_to_combinations<'a, T:Iterator>>( + symbols:T, +) -> Option + Clone> { + let mut bytes = Vec::new(); + + for symbol in symbols { + match symbol { + GlobSymbol::Char(c) => { + bytes.extend_from_slice(c); + }, + GlobSymbol::OpenBracket => return None, // todo handle brackets + GlobSymbol::CloseBracket => return None, + GlobSymbol::OpenBrace => return None, // todo handle braces + GlobSymbol::CloseBrace => return None, + GlobSymbol::Star => return None, + GlobSymbol::DoubleStar => return None, + GlobSymbol::Question => return None, + GlobSymbol::Negation => return None, + GlobSymbol::PathSeparator => return None, + } + } + + Some(std::iter::once(String::from_utf8(bytes).expect("char is always valid utf8"))) +} + +/// parses and escapes a glob, returning an iterator over the symbols +fn glob_to_symbols(glob:&str) -> impl Iterator { + let glob_bytes = glob.as_bytes(); + let mut escaped = false; + let mut cursor = unic_segment::GraphemeCursor::new(0, glob.len()); + + std::iter::from_fn(move || { + loop { + let start = cursor.cur_cursor(); + if start == glob.len() { + return None; + } + + let end = match cursor.next_boundary(glob, 0) { + Ok(Some(end)) => end, + _ => return None, + }; + + if escaped { + escaped = false; + return if end - start == 1 { + Some(GlobSymbol::Char(match glob_bytes[start] { + b'a' => &[b'\x61'], + b'b' => &[b'\x08'], + b'n' => &[b'\n'], + b'r' => &[b'\r'], + b't' => &[b'\t'], + _ => &glob_bytes[start..end], + })) + } else { + return Some(GlobSymbol::Char(&glob_bytes[start..end])); + }; + } + + return if end - start == 1 { + match glob_bytes[start] { + b'\\' => { + escaped = true; + continue; + }, + b'[' => Some(GlobSymbol::OpenBracket), + b']' => Some(GlobSymbol::CloseBracket), + b'{' => Some(GlobSymbol::OpenBrace), + b'}' => Some(GlobSymbol::CloseBrace), + b'*' => { + if glob_bytes.get(end) == Some(&b'*') { + cursor.set_cursor(end + 1); + Some(GlobSymbol::DoubleStar) + } else { + Some(GlobSymbol::Star) + } + }, + b'?' => Some(GlobSymbol::Question), + b'!' => Some(GlobSymbol::Negation), + b'/' => Some(GlobSymbol::PathSeparator), + _ => Some(GlobSymbol::Char(&glob_bytes[start..end])), + } + } else { + Some(GlobSymbol::Char(&glob_bytes[start..end])) + }; + } + }) +} + +#[cfg(test)] +mod test { + use std::{ + path::PathBuf, + sync::{Arc, Mutex}, + time::Duration, + }; + + use test_case::test_case; + use tokio::sync::watch; + + use super::{GlobSymbol::*, WatchConfig}; + use crate::ConfigError; + + #[test_case("foo/**", vec!["foo"])] + #[test_case("foo/{a,b}", vec!["foo"])] + #[test_case("foo/*/bar", vec!["foo"])] + #[test_case("foo/[a-d]/bar", vec!["foo"])] + #[test_case("foo/a?/bar", vec!["foo"])] + #[test_case("foo/ab?/bar", vec!["foo"] ; "question marks ")] + #[test_case("foo/{a,b}/ab?", vec!["foo"])] + #[test_case("/abc", vec!["/abc"])] + #[test_case("/abc/abc/*", vec!["/abc/abc"])] + fn test_glob_to_paths(glob:&str, paths_exp:Vec<&str>) { + let mut paths = super::glob_to_paths(glob); + paths.sort(); + assert_eq!(paths, paths_exp.iter().map(PathBuf::from).collect::>()); + } + + #[test_case("🇳🇴/🇳🇴", vec![Char("🇳🇴".as_bytes()), PathSeparator, Char("🇳🇴".as_bytes())])] + #[test_case("foo/**", vec![Char(b"f"), Char(b"o"), Char(b"o"), PathSeparator, DoubleStar])] + #[test_case("foo/{a,b}", vec![Char(b"f"), Char(b"o"), Char(b"o"), PathSeparator, OpenBrace, Char(b"a"), Char(b","), Char(b"b"), CloseBrace])] + #[test_case("\\f", vec![Char(b"f")])] + #[test_case("\\\\f", vec![Char(b"\\"), Char(b"f")])] + #[test_case("\\🇳🇴", vec![Char("🇳🇴".as_bytes())])] + #[test_case("\\n", vec![Char(b"\n")])] + fn test_glob_to_symbols(glob:&str, symbols_exp:Vec) { + let symbols = super::glob_to_symbols(glob).collect::>(); + assert_eq!(symbols.as_slice(), symbols_exp.as_slice()); + } + + #[tokio::test] + async fn test_flush_on_setup_failure() { + let (setup_tx, setup_rx) = watch::channel(None); + let (tx, _) = tokio::sync::mpsc::unbounded_channel(); + let config = WatchConfig { + flush:tx, + setup_receiver:setup_rx, + // Flush doesn't depend on watcher so we create a watcher for the unit type + watcher:Arc::new(Mutex::new(())), + }; + setup_tx.send(Some(false)).expect("setup channel closed during testing"); + match tokio::time::timeout(Duration::from_millis(10), config.flush()).await { + Err(_) => panic!("flush test timed out"), + Ok(result) => { + if !matches!(result, Err(ConfigError::ServerFailedToStart)) { + panic!("expected flush to fail since setup failed"); + } + }, + } + } +} diff --git a/crates/turborepo-globwatch/examples/cancel.rs b/crates/turborepo-globwatch/examples/cancel.rs index 1fba2b1b9f1bb..4b297d3d4bc88 100644 --- a/crates/turborepo-globwatch/examples/cancel.rs +++ b/crates/turborepo-globwatch/examples/cancel.rs @@ -1,46 +1,41 @@ use std::{path::PathBuf, time::Duration}; -use futures::{join, StreamExt}; +use futures::{StreamExt, join}; use globwatch::GlobWatcher; use tracing::{info, info_span}; use turbopath::AbsoluteSystemPathBuf; #[tokio::main] async fn main() { - tracing_subscriber::fmt::init(); - let flush_dir = AbsoluteSystemPathBuf::from_cwd("./flush").unwrap(); - let (watcher, config) = GlobWatcher::new(&flush_dir).unwrap(); - let stop = stop_token::StopSource::new(); - let mut stream = watcher.into_stream(stop.token()); + tracing_subscriber::fmt::init(); + let flush_dir = AbsoluteSystemPathBuf::from_cwd("./flush").unwrap(); + let (watcher, config) = GlobWatcher::new(&flush_dir).unwrap(); + let stop = stop_token::StopSource::new(); + let mut stream = watcher.into_stream(stop.token()); - let watch_fut = async { - let span = info_span!("watch_fut"); - let _ = span.enter(); - while let Some(Ok(e)) = stream.next().await { - info!(parent: &span, "{:?}", e); - } - info!(parent: &span, "done"); - }; + let watch_fut = async { + let span = info_span!("watch_fut"); + let _ = span.enter(); + while let Some(Ok(e)) = stream.next().await { + info!(parent: &span, "{:?}", e); + } + info!(parent: &span, "done"); + }; - let config_fut = async { - let span = info_span!("config_fut"); - let _ = span.enter(); - for x in 0..5 { - info!(parent: &span, "iteration {}", x); - config - .include(&PathBuf::from("."), "globwatch/src/**") - .await - .unwrap(); - tokio::time::sleep(Duration::from_secs(1)).await; - config - .exclude(&PathBuf::from("."), "globwatch/src/**") - .await; - tokio::time::sleep(Duration::from_secs(1)).await; - } + let config_fut = async { + let span = info_span!("config_fut"); + let _ = span.enter(); + for x in 0..5 { + info!(parent: &span, "iteration {}", x); + config.include(&PathBuf::from("."), "globwatch/src/**").await.unwrap(); + tokio::time::sleep(Duration::from_secs(1)).await; + config.exclude(&PathBuf::from("."), "globwatch/src/**").await; + tokio::time::sleep(Duration::from_secs(1)).await; + } - info!(parent: &span, "dropping stop"); - drop(stop); - }; + info!(parent: &span, "dropping stop"); + drop(stop); + }; - join!(watch_fut, config_fut); + join!(watch_fut, config_fut); } diff --git a/crates/turborepo-globwatch/readme.md b/crates/turborepo-globwatch/readme.md deleted file mode 100644 index 4288ba29597e2..0000000000000 --- a/crates/turborepo-globwatch/readme.md +++ /dev/null @@ -1,27 +0,0 @@ -# Globwatch - -> Watch a set of globs - -This library provides an async interface over notify and glob-match to -efficiently watch a list of globs. Where possible it attempts to minimize the -number of watched directories by registering watchers for the minimum possible -set of files / folders by breaking down the glob pattern into a list of folders. - -This is exposed as a `Stream` and a `Sink`. The stream produces `notify` events, -whereas the `Sink` can be used to update the configuration on-the-fly. - -For a basic example see the `examples/cancel.rs`. - -```rust -let (watcher, mut config) = GlobWatcher::new("./flush").unwrap(); -let stop = StopSource::new(); -let mut stream = watcher.into_stream(stop.token()); -config.include(Path::new("/app/css").into()); -config.include(Path::new("/app/html").into()); -while let Some(Ok(e)) = stream.next().await { - debug!("received event: {:?}", e); - - // use the cancellation token to stop the watcher - drop(stop); -} -``` diff --git a/crates/turborepo-globwatch/src/lib.rs b/crates/turborepo-globwatch/src/lib.rs deleted file mode 100644 index 3048a8c2bdce6..0000000000000 --- a/crates/turborepo-globwatch/src/lib.rs +++ /dev/null @@ -1,648 +0,0 @@ -//! A wrapper around notify that allows for glob-based watching. -//! -//! ## What is flushing? -//! -//! On certain filesystems, file events are not guaranteed to be delivered in -//! the correct order, or on time. This can cause issues when trying to -//! determine if a file has changed, as we don't want to register a watcher -//! for a file if we are not 'up to date'. The flushing mechanism allows us to -//! watch for a full round trip through the filesystem to ensure the watcher is -//! up to date. - -#![allow(clippy::all)] -#![deny( - missing_docs, - missing_debug_implementations, - missing_copy_implementations, - clippy::unwrap_used, - unused_must_use, - unsafe_code -)] -#![feature(extract_if)] - -use std::{ - collections::HashMap, - fs::File, - io, - path::{Path, PathBuf}, - sync::{ - atomic::{AtomicU64, Ordering}, - Arc, Mutex, - }, -}; - -use futures::{channel::oneshot, future::Either, FutureExt, Stream, StreamExt as _}; -use itertools::Itertools; -use merge_streams::MergeStreams; -pub use notify::{Event, Watcher}; -pub use stop_token::{stream::StreamExt, StopSource, StopToken, TimedOutError}; -use thiserror::Error; -use tokio::sync::{ - mpsc::{UnboundedReceiver, UnboundedSender}, - watch, -}; -use tokio_stream::wrappers::UnboundedReceiverStream; -use tracing::{error, event, span, trace, warn, Level}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathError}; - -/// WatchError wraps errors produced by GlobWatcher -#[derive(Debug, Error)] -pub enum WatchError { - // TODO: find a generic way to include the path in these errors - /// PathError wraps errors encountered dealing with paths while filewatching - #[error("Filewatching encountered a path error: {0}")] - PathError(#[from] PathError), - /// IO wraps IO errors encountered while attempting to watch the filesystem - #[error("Filewatching encountered an IO Error: {0}")] - IO(#[from] io::Error), - /// Backend wraps errors produced from the underlying filewatching - /// implementation. - #[error("Filewatching backend error: {0}")] - Backend(#[from] notify::Error), -} - -/// A wrapper around notify that allows for glob-based watching. -#[derive(Debug)] -pub struct GlobWatcher { - stream: UnboundedReceiver, - flush_dir: AbsoluteSystemPathBuf, - - config: UnboundedReceiver, - setup_handle: tokio::task::JoinHandle>, -} - -impl GlobWatcher { - /// Create a new watcher, using the given flush directory as a temporary - /// storage when flushing file events. For more information on flushing, - /// see the module-level documentation. - #[tracing::instrument] - pub fn new( - flush_dir: &AbsoluteSystemPath, - ) -> Result<(Self, WatchConfig), WatchError> { - let (send_event, receive_event) = tokio::sync::mpsc::unbounded_channel(); - let (send_config, receive_config) = tokio::sync::mpsc::unbounded_channel(); - - flush_dir.create_dir_all()?; - let flush_dir = flush_dir.to_realpath()?; - - let watcher = notify::recommended_watcher(move |event: Result| { - let span = span!(tracing::Level::TRACE, "watcher"); - let _ = span.enter(); - - let result = event.map(|e| { - trace!(parent: &span, "sending event: {:?}", e); - let tx = send_event.clone(); - futures::executor::block_on(async move { tx.send(e) }) - }); - - match result { - Ok(Ok(_)) => {} - Ok(Err(e)) => { - warn!(parent: &span, "watch server closed: {:?}", e); - } - Err(e) => { - warn!(parent: &span, "error from notify: {:?}", e); - } - } - })?; - - let watcher = Arc::new(Mutex::new(watcher)); - - // registering to watch this directory takes a few ms, - // so we just fire and forget a thread to do it in the - // background, to cut our startup time in half. - let flush = watcher.clone(); - let flush_watch_path = flush_dir.clone(); - let (setup_broadcaster, setup_receiver) = watch::channel(None); - let setup_handle = tokio::task::spawn_blocking(move || { - if let Err(e) = flush.lock().expect("only fails if poisoned").watch( - flush_watch_path.as_std_path(), - notify::RecursiveMode::Recursive, - ) { - warn!("failed to watch flush dir: {}", e); - if setup_broadcaster.send(Some(false)).is_err() { - trace!("failed to notify failed flush watch"); - } - Err(e) - } else { - trace!("watching flush dir: {:?}", flush_watch_path); - if setup_broadcaster.send(Some(true)).is_err() { - trace!("failed to notify successful flush watch"); - } - Ok(()) - } - }); - - Ok(( - Self { - flush_dir, - stream: receive_event, - config: receive_config, - setup_handle, - }, - WatchConfig { - flush: send_config, - watcher, - setup_receiver, - }, - )) - } -} - -impl GlobWatcher { - /// Convert the watcher into a stream of events, handling config changes and - /// flushing transparently. - /// - /// This is implemented as a zipped stream which processes filesystem events - /// and config changes driven by the same stream. This allows us to ensure - /// that anything watching for filesystem is also propagating config changes - pub fn into_stream( - self, - token: stop_token::StopToken, - ) -> impl Stream, TimedOutError>> - + Send - + Sync - + 'static - + Unpin { - let Self { - setup_handle, - flush_dir, - .. - } = self; - let flush_id = Arc::new(AtomicU64::new(1)); - let flush_dir = Arc::new(flush_dir); - let flush = Arc::new(Mutex::new(HashMap::>::new())); - - // Wait until we have watched the flush directory, before we start processing - // events - - // we need to map this to the correct error type - let setup_stream = setup_handle.into_stream().map(|setup_result| { - match setup_result.expect("globwatch setup thread panicked") { - Ok(()) => Ok(WatcherCommand::Start), - Err(e) => { - error!("failed to start server: {}", e); - Err(ConfigError::ServerFailedToStart) - } - } - }); - - Box::pin( - ( - UnboundedReceiverStream::new(self.stream).map(Either::Left), - setup_stream - .chain(UnboundedReceiverStream::new(self.config).map(Result::Ok)) - .map(Either::Right), - ) - .merge() - // apply a filter_map, yielding only valid events and consuming config changes and - // flushes - .filter_map(move |f| { - let span = span!(tracing::Level::TRACE, "stream_processor"); - let _ = span.enter(); - - // clone all the Arcs needed - let flush_id = flush_id.clone(); - let flush_dir = flush_dir.clone(); - let flush = flush.clone(); - - async move { - match f { - Either::Left(mut e) => { - // if we receive an event for a file in the flush dir, we need to - // remove it from the events list, and send a signal to the flush - // requester. flushes should not be considered as events. - for flush_id in e - .paths - .extract_if(|p| p.starts_with(flush_dir.as_path())) - .filter_map(|p| { - get_flush_id( - p.strip_prefix(flush_dir.as_path()) - .expect("confirmed above"), - ) - }) - { - trace!("flushing {:?}", flush); - if let Some(tx) = flush - .lock() - .expect("only fails if holder panics") - .remove(&flush_id) - { - // if this fails, it just means the requester has gone away - // and we can ignore it - tx.send(()).ok(); - } - } - - // if we have any paths left on the event, yield it - if !e.paths.is_empty() { - event!(parent: &span, Level::TRACE, "yielding {:?}", e); - Some(Ok(e)) - } else { - None - } - } - Either::Right(Ok(WatcherCommand::Start)) => { - trace!("setting up watching flush directory has completed"); - None - } - Either::Right(Ok(WatcherCommand::Flush(tx))) => { - // create file in flush dir - let flush_id = flush_id.fetch_add(1, Ordering::SeqCst); - let flush_file = flush_dir.join_component(&flush_id.to_string()); - if let Err(e) = File::create(flush_file) { - warn!("failed to create flush file: {}", e); - } else { - flush - .lock() - .expect("only fails if holder panics") - .insert(flush_id, tx); - } - None - } - Either::Right(Err(e)) => Some(Err(e)), - } - } - }) - .timeout_at(token), - ) - } -} - -fn get_flush_id(relative_path: &Path) -> Option { - relative_path - .file_name() - .and_then(|p| p.to_str()) - .and_then(|p| p.parse().ok()) -} - -/// A configuration change to the watcher. -#[derive(Debug)] -pub enum WatcherCommand { - /// A marker command showing that watcher startup completed successfully - Start, - /// A request to flush the watcher. - Flush(oneshot::Sender<()>), -} - -/// A sender for watcher configuration changes. -#[derive(Debug, Clone)] -pub struct WatchConfig { - flush: UnboundedSender, - watcher: Arc>, - setup_receiver: watch::Receiver>, -} - -/// The server is no longer running. -#[derive(Debug)] -pub enum ConfigError { - /// The server is no longer running. - ServerStopped, - /// Watch error - WatchError(Vec), - /// The server has already been consumed. - WatchingAlready, - /// We were unable to watch the flush directory - ServerFailedToStart, -} - -impl WatchConfig { - /// Register a glob to be included by the watcher. - #[tracing::instrument(skip(self))] - pub async fn include(&self, relative_to: &Path, glob: &str) -> Result<(), ConfigError> { - trace!("including {:?}", glob); - - glob_to_paths(glob) - .iter() - .map(|p| relative_to.join(p)) - .map(|p| { - trace!("watching {:?}", p); - self.watcher - .lock() - .expect("only fails if poisoned") - .watch(&p, notify::RecursiveMode::Recursive) - }) - .map(|r| match r { - Ok(()) => Ok(()), - Err(notify::Error { - kind: notify::ErrorKind::PathNotFound, - .. - }) => { - // if the path we are trying to watch doesn't exist - // it is not immediately an error; glob_to_paths - // will generate paths that potentially don't exist, - // since it doesn't walk the fs, no no-op - Ok(()) - } - Err(notify::Error { - kind: notify::ErrorKind::Generic(s), - .. - }) if s.contains("No such file or directory") - || s.eq("Input watch path is neither a file nor a directory.") => - { - Ok(()) - } - Err(e) => Err(e), - }) - .fold(Ok(()), |acc, next| match (acc, next) { - (Ok(()), Ok(())) => Ok(()), - (Ok(()), Err(e)) => Err(vec![e]), - (Err(acc), Ok(())) => Err(acc), - (Err(mut acc), Err(e)) => { - acc.push(e); - Err(acc) - } - }) - .map_err(ConfigError::WatchError) - } - - /// Register a single path to be included by the watcher. - pub async fn include_path(&self, path: &Path) -> Result<(), ConfigError> { - trace!("watching {:?}", path); - // Windows doesn't create an event when a watched directory itself is deleted - // we watch the parent directory instead. - // More information at https://github.com/notify-rs/notify/issues/403 - #[cfg(windows)] - let watched_path = path.parent().expect("turbo is unusable at filesystem root"); - #[cfg(not(windows))] - let watched_path = path; - - self.watcher - .lock() - .expect("watcher lock poisoned") - .watch(watched_path, notify::RecursiveMode::NonRecursive) - .map_err(|e| ConfigError::WatchError(vec![e])) - } - - /// Register a glob to be excluded by the watcher. - #[tracing::instrument(skip(self))] - pub async fn exclude(&self, relative_to: &Path, glob: &str) { - trace!("excluding {:?}", glob); - - for p in glob_to_paths(glob).iter().map(|p| relative_to.join(p)) { - // we don't care if this fails, it's just a best-effort - self.watcher - .lock() - .expect("only fails if poisoned") - .unwatch(&p) - .ok(); - } - } -} - -impl WatchConfig { - /// Await a full filesystem flush from the watcher. - pub async fn flush(&self) -> Result<(), ConfigError> { - let mut setup_rx = self.setup_receiver.clone(); - // TODO once upgraded to tokio 1.27 use wait_until - while (*setup_rx.borrow()).is_none() { - // If this fails that means the channel was closed forcefully by the sender - if setup_rx.changed().await.is_err() { - return Err(ConfigError::ServerFailedToStart); - } - } - if *setup_rx.borrow() == Some(false) { - return Err(ConfigError::ServerFailedToStart); - } - - let (tx, rx) = oneshot::channel(); - self.flush - .send(WatcherCommand::Flush(tx)) - .map_err(|_| ConfigError::ServerStopped)?; - rx.await.map_err(|_| ConfigError::ServerStopped) - } -} - -#[derive(PartialEq, Eq, Debug)] -enum GlobSymbol<'a> { - Char(&'a [u8]), - OpenBracket, - CloseBracket, - OpenBrace, - CloseBrace, - Star, - DoubleStar, - Question, - Negation, - PathSeparator, -} - -/// Gets the minimum set of paths that can be watched for a given glob, -/// specified in minimatch glob syntax. -/// -/// syntax: -/// ? Matches any single character. -/// -/// *  Matches zero or more characters, except for path separators. -/// -/// ** Matches zero or more characters, including path separators. -/// Must match a complete path segment. -/// -/// [ab] Matches one of the characters contained in the brackets. -/// Character ranges, e.g. [a-z] are also supported. Use [!ab] or [^ab] -/// to match any character except those contained in the brackets. -/// -/// {a,b} Matches one of the patterns contained in the braces. Any of the -/// wildcard characters can be used in the sub-patterns. Braces may -/// be nested up to 10 levels deep. -/// -/// ! When at the start of the glob, this negates the result. -/// Multiple ! characters negate the glob multiple times. -/// -/// \ A backslash character may be used to escape any special characters. -/// -/// Of these, we only handle `{` and escaping. -/// -/// note: it is currently extremely conservative, handling only `**`, braces, -/// and `?`. any other case watches the entire directory. -fn glob_to_paths(glob: &str) -> Vec { - // get all the symbols and chunk them by path separator - let chunks = glob_to_symbols(glob).group_by(|s| s != &GlobSymbol::PathSeparator); - let chunks = chunks - .into_iter() - .filter_map(|(not_sep, chunk)| (not_sep).then_some(chunk)); - - // multi cartisian product allows us to get all the possible combinations - // of path components for each chunk. for example, if we have a glob - // `{a,b}/1/{c,d}`, it will lazily yield the following sets of segments: - // ["a", "1", "c"] - // ["a", "1", "d"] - // ["b", "1", "c"] - // ["b", "1", "d"] - - chunks - .map(symbols_to_combinations) // yield all the possible segments for each glob chunk - .take_while(|c| c.is_some()) // if any segment has no possible paths, we can stop - .flatten() - .multi_cartesian_product() // get all the possible combinations of path segments - .map(|chunks| { - let prefix = if glob.starts_with('/') { "/" } else { "" }; - std::iter::once(prefix) - .chain(chunks.iter().map(|s| s.as_str())) - .collect::() - }) - .collect() -} - -/// given a set of symbols, returns an iterator over the possible path segments -/// that can be generated from them. this currently is very conservative, and -/// simply ejects if it encounters glob-like symbols. in the future, we should -/// handle brackets and braces. -/// -/// example: given the symbols "{a,b}b" it will yield ["ab"] and ["bb"] -fn symbols_to_combinations<'a, T: Iterator>>( - symbols: T, -) -> Option + Clone> { - let mut bytes = Vec::new(); - - for symbol in symbols { - match symbol { - GlobSymbol::Char(c) => { - bytes.extend_from_slice(c); - } - GlobSymbol::OpenBracket => return None, // todo handle brackets - GlobSymbol::CloseBracket => return None, - GlobSymbol::OpenBrace => return None, // todo handle braces - GlobSymbol::CloseBrace => return None, - GlobSymbol::Star => return None, - GlobSymbol::DoubleStar => return None, - GlobSymbol::Question => return None, - GlobSymbol::Negation => return None, - GlobSymbol::PathSeparator => return None, - } - } - - Some(std::iter::once( - String::from_utf8(bytes).expect("char is always valid utf8"), - )) -} - -/// parses and escapes a glob, returning an iterator over the symbols -fn glob_to_symbols(glob: &str) -> impl Iterator { - let glob_bytes = glob.as_bytes(); - let mut escaped = false; - let mut cursor = unic_segment::GraphemeCursor::new(0, glob.len()); - - std::iter::from_fn(move || loop { - let start = cursor.cur_cursor(); - if start == glob.len() { - return None; - } - - let end = match cursor.next_boundary(glob, 0) { - Ok(Some(end)) => end, - _ => return None, - }; - - if escaped { - escaped = false; - return if end - start == 1 { - Some(GlobSymbol::Char(match glob_bytes[start] { - b'a' => &[b'\x61'], - b'b' => &[b'\x08'], - b'n' => &[b'\n'], - b'r' => &[b'\r'], - b't' => &[b'\t'], - _ => &glob_bytes[start..end], - })) - } else { - return Some(GlobSymbol::Char(&glob_bytes[start..end])); - }; - } - - return if end - start == 1 { - match glob_bytes[start] { - b'\\' => { - escaped = true; - continue; - } - b'[' => Some(GlobSymbol::OpenBracket), - b']' => Some(GlobSymbol::CloseBracket), - b'{' => Some(GlobSymbol::OpenBrace), - b'}' => Some(GlobSymbol::CloseBrace), - b'*' => { - if glob_bytes.get(end) == Some(&b'*') { - cursor.set_cursor(end + 1); - Some(GlobSymbol::DoubleStar) - } else { - Some(GlobSymbol::Star) - } - } - b'?' => Some(GlobSymbol::Question), - b'!' => Some(GlobSymbol::Negation), - b'/' => Some(GlobSymbol::PathSeparator), - _ => Some(GlobSymbol::Char(&glob_bytes[start..end])), - } - } else { - Some(GlobSymbol::Char(&glob_bytes[start..end])) - }; - }) -} - -#[cfg(test)] -mod test { - use std::{ - path::PathBuf, - sync::{Arc, Mutex}, - time::Duration, - }; - - use test_case::test_case; - use tokio::sync::watch; - - use super::{GlobSymbol::*, WatchConfig}; - use crate::ConfigError; - - #[test_case("foo/**", vec!["foo"])] - #[test_case("foo/{a,b}", vec!["foo"])] - #[test_case("foo/*/bar", vec!["foo"])] - #[test_case("foo/[a-d]/bar", vec!["foo"])] - #[test_case("foo/a?/bar", vec!["foo"])] - #[test_case("foo/ab?/bar", vec!["foo"] ; "question marks ")] - #[test_case("foo/{a,b}/ab?", vec!["foo"])] - #[test_case("/abc", vec!["/abc"])] - #[test_case("/abc/abc/*", vec!["/abc/abc"])] - fn test_glob_to_paths(glob: &str, paths_exp: Vec<&str>) { - let mut paths = super::glob_to_paths(glob); - paths.sort(); - assert_eq!( - paths, - paths_exp.iter().map(PathBuf::from).collect::>() - ); - } - - #[test_case("🇳🇴/🇳🇴", vec![Char("🇳🇴".as_bytes()), PathSeparator, Char("🇳🇴".as_bytes())])] - #[test_case("foo/**", vec![Char(b"f"), Char(b"o"), Char(b"o"), PathSeparator, DoubleStar])] - #[test_case("foo/{a,b}", vec![Char(b"f"), Char(b"o"), Char(b"o"), PathSeparator, OpenBrace, Char(b"a"), Char(b","), Char(b"b"), CloseBrace])] - #[test_case("\\f", vec![Char(b"f")])] - #[test_case("\\\\f", vec![Char(b"\\"), Char(b"f")])] - #[test_case("\\🇳🇴", vec![Char("🇳🇴".as_bytes())])] - #[test_case("\\n", vec![Char(b"\n")])] - fn test_glob_to_symbols(glob: &str, symbols_exp: Vec) { - let symbols = super::glob_to_symbols(glob).collect::>(); - assert_eq!(symbols.as_slice(), symbols_exp.as_slice()); - } - - #[tokio::test] - async fn test_flush_on_setup_failure() { - let (setup_tx, setup_rx) = watch::channel(None); - let (tx, _) = tokio::sync::mpsc::unbounded_channel(); - let config = WatchConfig { - flush: tx, - setup_receiver: setup_rx, - // Flush doesn't depend on watcher so we create a watcher for the unit type - watcher: Arc::new(Mutex::new(())), - }; - setup_tx - .send(Some(false)) - .expect("setup channel closed during testing"); - match tokio::time::timeout(Duration::from_millis(10), config.flush()).await { - Err(_) => panic!("flush test timed out"), - Ok(result) => { - if !matches!(result, Err(ConfigError::ServerFailedToStart)) { - panic!("expected flush to fail since setup failed"); - } - } - } - } -} diff --git a/crates/turborepo-graph-utils/Cargo.toml b/crates/turborepo-graph-utils/Cargo.toml index 1cac6e930785e..a186b4c9d4470 100644 --- a/crates/turborepo-graph-utils/Cargo.toml +++ b/crates/turborepo-graph-utils/Cargo.toml @@ -1,12 +1,3 @@ -[package] -name = "turborepo-graph-utils" -version = "0.1.0" -edition = "2021" -license = "MIT" - -[lints] -workspace = true - [dependencies] fixedbitset = "0.4.2" futures = "0.3.26" @@ -19,3 +10,15 @@ tracing = { workspace = true, features = ["log"] } [dev-dependencies] insta = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-graph-utils" +version = "0.1.0" diff --git a/crates/turborepo-graph-utils/src/lib.rs b/crates/turborepo-graph-utils/Source/lib.rs similarity index 100% rename from crates/turborepo-graph-utils/src/lib.rs rename to crates/turborepo-graph-utils/Source/lib.rs diff --git a/crates/turborepo-graph-utils/Source/walker.rs b/crates/turborepo-graph-utils/Source/walker.rs new file mode 100644 index 0000000000000..b1a9e1b9501b4 --- /dev/null +++ b/crates/turborepo-graph-utils/Source/walker.rs @@ -0,0 +1,331 @@ +use std::{collections::HashMap, hash::Hash}; + +use futures::{StreamExt, future::join_all, stream::FuturesUnordered}; +use petgraph::{ + Direction, + visit::{IntoNeighborsDirected, IntoNodeIdentifiers}, +}; +use tokio::{ + sync::{broadcast, mpsc, oneshot, watch}, + task::JoinHandle, +}; +use tracing::log::trace; + +pub struct Walker { + marker:std::marker::PhantomData, + cancel:watch::Sender, + node_events:Option)>>, + join_handles:FuturesUnordered>, +} + +pub struct Start; +pub struct Walking; + +pub type WalkMessage = (N, oneshot::Sender<()>); + +// These constraint might look very stiff, but since all of the petgraph graph +// types use integers as node ids and GraphBase already constraints these types +// to Copy + Eq so adding Hash + Send + 'static as bounds aren't unreasonable. +impl Walker { + /// Create a new graph walker for a DAG that emits nodes only once all of + /// their dependencies have been processed. + /// The graph should not be modified after a walker is created as the nodes + /// emitted might no longer exist or might miss newly added edges. + pub fn new + IntoNeighborsDirected>(graph:G) -> Self { + let (cancel, cancel_rx) = watch::channel(false); + let mut txs = HashMap::new(); + let mut rxs = HashMap::new(); + for node in graph.node_identifiers() { + // Each node can finish at most once so we set the capacity to 1 + let (tx, rx) = broadcast::channel::<()>(1); + txs.insert(node, tx); + rxs.insert(node, rx); + } + // We will be emitting at most txs.len() nodes so emitting a node should never + // block + // + // Always have at least 1 entry in buffer or this will panic + let (node_tx, node_rx) = mpsc::channel(std::cmp::max(txs.len(), 1)); + let join_handles = FuturesUnordered::new(); + for node in graph.node_identifiers() { + let tx = txs.remove(&node).expect("should have sender for all nodes"); + let mut cancel_rx = cancel_rx.clone(); + let node_tx = node_tx.clone(); + let mut deps_rx = graph + .neighbors_directed(node, Direction::Outgoing) + .map(|dep| rxs.get(&dep).expect("graph should have all nodes").resubscribe()) + .collect::>(); + + join_handles.push(tokio::spawn(async move { + let deps_fut = join_all(deps_rx.iter_mut().map(|rx| rx.recv())); + + tokio::select! { + // If both the cancel and dependencies are ready, we want to + // execute the cancel instead of sending an additional node. + biased; + _ = cancel_rx.changed() => { + // If this future resolves this means that either: + // - cancel was updated, this can only happen through + // the cancel method which only sets it to true + // - the cancel sender was dropped which is also a sign that we should exit + } + results = deps_fut => { + for res in results { + match res { + // No errors from reading dependency channels + Ok(()) => (), + // A dependency finished without sending a finish + // Could happen if a cancel is sent and is racing with deps + // so we interpret this as a cancel. + Err(broadcast::error::RecvError::Closed) => { + return; + } + // A dependency sent a finish signal more than once + // which shouldn't be possible. + // Since the message is always the unit type we can proceed + // but we log as this is unexpected behavior. + Err(broadcast::error::RecvError::Lagged(x)) => { + debug_assert!(false, "A node finished {x} more times than expected"); + trace!("A node finished {x} more times than expected"); + } + } + } + + let (callback_tx, callback_rx) = oneshot::channel::<()>(); + // do some err handling with the send failure? + if node_tx.send((node, callback_tx)).await.is_err() { + // Receiving end of node channel has been closed/dropped + // Since there's nothing the mark the node as being done + // we act as if we have been canceled. + trace!("Receiver was dropped before walk finished without calling cancel"); + return; + } + if callback_rx.await.is_err() { + // If the caller drops the callback sender without signaling + // that the node processing is finished we assume that it is finished. + trace!("Callback sender was dropped without sending a finish signal") + } + // Send errors indicate that there are no receivers which + // happens when this node has no dependents + tx.send(()).ok(); + } + } + })); + } + + // All senders should have been moved into their correct node task + debug_assert!(txs.is_empty()); + + Self { cancel, node_events:Some(node_rx), join_handles, marker:std::marker::PhantomData } + } + + /// Start walking the graph and return a channel that emits node + /// indices once all of the nodes dependencies have finished. + /// It is up to the caller to use the oneshot channel to mark + /// a node as being done. + pub fn walk(self) -> (Walker, mpsc::Receiver>) { + let Self { cancel, mut node_events, join_handles, .. } = self; + let node_events = node_events + .take() + .expect("walking graph with walker that has already been used"); + ( + Walker { marker:std::marker::PhantomData, cancel, node_events:None, join_handles }, + node_events, + ) + } +} + +impl Walker { + /// Cancel the walk + /// Any nodes that are already in the queue to be emitted will still be + /// sent, but no new nodes will be sent. + pub fn cancel(&mut self) -> Result<(), watch::error::SendError> { self.cancel.send(true) } + + /// Consumes the watcher and waits for all futures to be finished. + /// Primarily used after the walk is canceled to ensure all tasks + /// have been stopped. + pub async fn wait(self) -> Result<(), tokio::task::JoinError> { + let Self { mut join_handles, .. } = self; + // Wait for all of the handles to finish up + while let Some(result) = join_handles.next().await { + result?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use std::{ + sync::{Arc, Mutex}, + time::Duration, + }; + + use petgraph::Graph; + + use super::*; + + #[tokio::test] + async fn test_ordering() { + // a -> b -> c + let mut g = Graph::new(); + let a = g.add_node("a"); + let b = g.add_node("b"); + let c = g.add_node("c"); + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + + let walker = Walker::new(&g); + let mut visited = Vec::new(); + let (walker, mut node_emitter) = walker.walk(); + while let Some((index, done)) = node_emitter.recv().await { + visited.push(index); + done.send(()).unwrap(); + } + walker.wait().await.unwrap(); + assert_eq!(visited, vec![c, b, a]); + } + + #[tokio::test] + async fn test_cancel() { + // a -> b -> c + let mut g = Graph::new(); + let a = g.add_node("a"); + let b = g.add_node("b"); + let c = g.add_node("c"); + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + + let walker = Walker::new(&g); + let mut visited = Vec::new(); + let (mut walker, mut node_emitter) = walker.walk(); + while let Some((index, done)) = node_emitter.recv().await { + // Cancel after we get the first node + walker.cancel().unwrap(); + + visited.push(index); + done.send(()).unwrap(); + } + assert_eq!(visited, vec![c]); + let Walker { join_handles, .. } = walker; + // Yield to make sure the tasks have a chance to poll the cancel future + tokio::time::sleep(Duration::from_millis(1)).await; + + // Verify that all node tasks stop running + for join_handle in join_handles { + assert!(join_handle.is_finished()); + } + } + // test that long running nodes block dependents, but others can continue + #[tokio::test] + async fn test_dependencies_block_ancestors() { + // a -- b -- c + // \ + // - d -- e + let mut g = Graph::new(); + let a = g.add_node("a"); + let b = g.add_node("b"); + let c = g.add_node("c"); + let d = g.add_node("d"); + let e = g.add_node("e"); + g.add_edge(a, b, ()); + g.add_edge(a, d, ()); + g.add_edge(b, c, ()); + g.add_edge(d, e, ()); + + // We intentionally wait to mark e as finished until b has been finished + let walker = Walker::new(&g); + let visited = Arc::new(Mutex::new(Vec::new())); + let (walker, mut node_emitter) = walker.walk(); + let (b_done, is_b_done) = oneshot::channel::<()>(); + let mut b_done = Some(b_done); + let mut is_b_done = Some(is_b_done); + while let Some((index, done)) = node_emitter.recv().await { + if index == e { + // don't mark as done until we get the signal that b is finished + let is_b_done = is_b_done.take().unwrap(); + let visited = visited.clone(); + tokio::spawn(async move { + is_b_done.await.unwrap(); + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + }); + } else if index == b { + // send the signal that b is finished + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + b_done.take().unwrap().send(()).unwrap(); + } else { + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + } + } + walker.wait().await.unwrap(); + assert_eq!(visited.lock().unwrap().as_slice(), &[c, b, e, d, a]); + } + + #[tokio::test] + async fn test_multiple_roots() { + // a -- b -- c + // / + // d -- e - + let mut g = Graph::new(); + let a = g.add_node("a"); + let b = g.add_node("b"); + let c = g.add_node("c"); + let d = g.add_node("d"); + let e = g.add_node("e"); + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + g.add_edge(d, e, ()); + g.add_edge(e, c, ()); + + // We intentionally wait to mark e as finished until b has been finished + let walker = Walker::new(&g); + let visited = Arc::new(Mutex::new(Vec::new())); + let (walker, mut node_emitter) = walker.walk(); + let (b_done, is_b_done) = oneshot::channel::<()>(); + let (d_done, is_d_done) = oneshot::channel::<()>(); + let mut b_done = Some(b_done); + let mut is_b_done = Some(is_b_done); + let mut d_done = Some(d_done); + let mut is_d_done = Some(is_d_done); + while let Some((index, done)) = node_emitter.recv().await { + if index == e { + // don't mark as done until we get the signal that b is finished + let is_b_done = is_b_done.take().unwrap(); + let visited = visited.clone(); + tokio::spawn(async move { + is_b_done.await.unwrap(); + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + }); + } else if index == b { + // send the signal that b is finished + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + b_done.take().unwrap().send(()).unwrap(); + } else if index == a { + // don't mark as done until d finishes + let is_d_done = is_d_done.take().unwrap(); + let visited = visited.clone(); + tokio::spawn(async move { + is_d_done.await.unwrap(); + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + }); + } else if index == d { + // send the signal that b is finished + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + d_done.take().unwrap().send(()).unwrap(); + } else { + visited.lock().unwrap().push(index); + done.send(()).unwrap(); + } + } + walker.wait().await.unwrap(); + assert_eq!(visited.lock().unwrap().as_slice(), &[c, b, e, d, a]); + } +} diff --git a/crates/turborepo-graph-utils/src/walker.rs b/crates/turborepo-graph-utils/src/walker.rs deleted file mode 100644 index 9f1d739b139f6..0000000000000 --- a/crates/turborepo-graph-utils/src/walker.rs +++ /dev/null @@ -1,354 +0,0 @@ -use std::{collections::HashMap, hash::Hash}; - -use futures::{future::join_all, stream::FuturesUnordered, StreamExt}; -use petgraph::{ - visit::{IntoNeighborsDirected, IntoNodeIdentifiers}, - Direction, -}; -use tokio::{ - sync::{broadcast, mpsc, oneshot, watch}, - task::JoinHandle, -}; -use tracing::log::trace; - -pub struct Walker { - marker: std::marker::PhantomData, - cancel: watch::Sender, - node_events: Option)>>, - join_handles: FuturesUnordered>, -} - -pub struct Start; -pub struct Walking; - -pub type WalkMessage = (N, oneshot::Sender<()>); - -// These constraint might look very stiff, but since all of the petgraph graph -// types use integers as node ids and GraphBase already constraints these types -// to Copy + Eq so adding Hash + Send + 'static as bounds aren't unreasonable. -impl Walker { - /// Create a new graph walker for a DAG that emits nodes only once all of - /// their dependencies have been processed. - /// The graph should not be modified after a walker is created as the nodes - /// emitted might no longer exist or might miss newly added edges. - pub fn new + IntoNeighborsDirected>(graph: G) -> Self { - let (cancel, cancel_rx) = watch::channel(false); - let mut txs = HashMap::new(); - let mut rxs = HashMap::new(); - for node in graph.node_identifiers() { - // Each node can finish at most once so we set the capacity to 1 - let (tx, rx) = broadcast::channel::<()>(1); - txs.insert(node, tx); - rxs.insert(node, rx); - } - // We will be emitting at most txs.len() nodes so emitting a node should never - // block - // - // Always have at least 1 entry in buffer or this will panic - let (node_tx, node_rx) = mpsc::channel(std::cmp::max(txs.len(), 1)); - let join_handles = FuturesUnordered::new(); - for node in graph.node_identifiers() { - let tx = txs.remove(&node).expect("should have sender for all nodes"); - let mut cancel_rx = cancel_rx.clone(); - let node_tx = node_tx.clone(); - let mut deps_rx = graph - .neighbors_directed(node, Direction::Outgoing) - .map(|dep| { - rxs.get(&dep) - .expect("graph should have all nodes") - .resubscribe() - }) - .collect::>(); - - join_handles.push(tokio::spawn(async move { - let deps_fut = join_all(deps_rx.iter_mut().map(|rx| rx.recv())); - - tokio::select! { - // If both the cancel and dependencies are ready, we want to - // execute the cancel instead of sending an additional node. - biased; - _ = cancel_rx.changed() => { - // If this future resolves this means that either: - // - cancel was updated, this can only happen through - // the cancel method which only sets it to true - // - the cancel sender was dropped which is also a sign that we should exit - } - results = deps_fut => { - for res in results { - match res { - // No errors from reading dependency channels - Ok(()) => (), - // A dependency finished without sending a finish - // Could happen if a cancel is sent and is racing with deps - // so we interpret this as a cancel. - Err(broadcast::error::RecvError::Closed) => { - return; - } - // A dependency sent a finish signal more than once - // which shouldn't be possible. - // Since the message is always the unit type we can proceed - // but we log as this is unexpected behavior. - Err(broadcast::error::RecvError::Lagged(x)) => { - debug_assert!(false, "A node finished {x} more times than expected"); - trace!("A node finished {x} more times than expected"); - } - } - } - - let (callback_tx, callback_rx) = oneshot::channel::<()>(); - // do some err handling with the send failure? - if node_tx.send((node, callback_tx)).await.is_err() { - // Receiving end of node channel has been closed/dropped - // Since there's nothing the mark the node as being done - // we act as if we have been canceled. - trace!("Receiver was dropped before walk finished without calling cancel"); - return; - } - if callback_rx.await.is_err() { - // If the caller drops the callback sender without signaling - // that the node processing is finished we assume that it is finished. - trace!("Callback sender was dropped without sending a finish signal") - } - // Send errors indicate that there are no receivers which - // happens when this node has no dependents - tx.send(()).ok(); - } - } - })); - } - - // All senders should have been moved into their correct node task - debug_assert!(txs.is_empty()); - - Self { - cancel, - node_events: Some(node_rx), - join_handles, - marker: std::marker::PhantomData, - } - } - - /// Start walking the graph and return a channel that emits node - /// indices once all of the nodes dependencies have finished. - /// It is up to the caller to use the oneshot channel to mark - /// a node as being done. - pub fn walk(self) -> (Walker, mpsc::Receiver>) { - let Self { - cancel, - mut node_events, - join_handles, - .. - } = self; - let node_events = node_events - .take() - .expect("walking graph with walker that has already been used"); - ( - Walker { - marker: std::marker::PhantomData, - cancel, - node_events: None, - join_handles, - }, - node_events, - ) - } -} - -impl Walker { - /// Cancel the walk - /// Any nodes that are already in the queue to be emitted will still be - /// sent, but no new nodes will be sent. - pub fn cancel(&mut self) -> Result<(), watch::error::SendError> { - self.cancel.send(true) - } - - /// Consumes the watcher and waits for all futures to be finished. - /// Primarily used after the walk is canceled to ensure all tasks - /// have been stopped. - pub async fn wait(self) -> Result<(), tokio::task::JoinError> { - let Self { - mut join_handles, .. - } = self; - // Wait for all of the handles to finish up - while let Some(result) = join_handles.next().await { - result?; - } - - Ok(()) - } -} - -#[cfg(test)] -mod test { - use std::{ - sync::{Arc, Mutex}, - time::Duration, - }; - - use petgraph::Graph; - - use super::*; - - #[tokio::test] - async fn test_ordering() { - // a -> b -> c - let mut g = Graph::new(); - let a = g.add_node("a"); - let b = g.add_node("b"); - let c = g.add_node("c"); - g.add_edge(a, b, ()); - g.add_edge(b, c, ()); - - let walker = Walker::new(&g); - let mut visited = Vec::new(); - let (walker, mut node_emitter) = walker.walk(); - while let Some((index, done)) = node_emitter.recv().await { - visited.push(index); - done.send(()).unwrap(); - } - walker.wait().await.unwrap(); - assert_eq!(visited, vec![c, b, a]); - } - - #[tokio::test] - async fn test_cancel() { - // a -> b -> c - let mut g = Graph::new(); - let a = g.add_node("a"); - let b = g.add_node("b"); - let c = g.add_node("c"); - g.add_edge(a, b, ()); - g.add_edge(b, c, ()); - - let walker = Walker::new(&g); - let mut visited = Vec::new(); - let (mut walker, mut node_emitter) = walker.walk(); - while let Some((index, done)) = node_emitter.recv().await { - // Cancel after we get the first node - walker.cancel().unwrap(); - - visited.push(index); - done.send(()).unwrap(); - } - assert_eq!(visited, vec![c]); - let Walker { join_handles, .. } = walker; - // Yield to make sure the tasks have a chance to poll the cancel future - tokio::time::sleep(Duration::from_millis(1)).await; - - // Verify that all node tasks stop running - for join_handle in join_handles { - assert!(join_handle.is_finished()); - } - } - // test that long running nodes block dependents, but others can continue - #[tokio::test] - async fn test_dependencies_block_ancestors() { - // a -- b -- c - // \ - // - d -- e - let mut g = Graph::new(); - let a = g.add_node("a"); - let b = g.add_node("b"); - let c = g.add_node("c"); - let d = g.add_node("d"); - let e = g.add_node("e"); - g.add_edge(a, b, ()); - g.add_edge(a, d, ()); - g.add_edge(b, c, ()); - g.add_edge(d, e, ()); - - // We intentionally wait to mark e as finished until b has been finished - let walker = Walker::new(&g); - let visited = Arc::new(Mutex::new(Vec::new())); - let (walker, mut node_emitter) = walker.walk(); - let (b_done, is_b_done) = oneshot::channel::<()>(); - let mut b_done = Some(b_done); - let mut is_b_done = Some(is_b_done); - while let Some((index, done)) = node_emitter.recv().await { - if index == e { - // don't mark as done until we get the signal that b is finished - let is_b_done = is_b_done.take().unwrap(); - let visited = visited.clone(); - tokio::spawn(async move { - is_b_done.await.unwrap(); - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - }); - } else if index == b { - // send the signal that b is finished - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - b_done.take().unwrap().send(()).unwrap(); - } else { - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - } - } - walker.wait().await.unwrap(); - assert_eq!(visited.lock().unwrap().as_slice(), &[c, b, e, d, a]); - } - - #[tokio::test] - async fn test_multiple_roots() { - // a -- b -- c - // / - // d -- e - - let mut g = Graph::new(); - let a = g.add_node("a"); - let b = g.add_node("b"); - let c = g.add_node("c"); - let d = g.add_node("d"); - let e = g.add_node("e"); - g.add_edge(a, b, ()); - g.add_edge(b, c, ()); - g.add_edge(d, e, ()); - g.add_edge(e, c, ()); - - // We intentionally wait to mark e as finished until b has been finished - let walker = Walker::new(&g); - let visited = Arc::new(Mutex::new(Vec::new())); - let (walker, mut node_emitter) = walker.walk(); - let (b_done, is_b_done) = oneshot::channel::<()>(); - let (d_done, is_d_done) = oneshot::channel::<()>(); - let mut b_done = Some(b_done); - let mut is_b_done = Some(is_b_done); - let mut d_done = Some(d_done); - let mut is_d_done = Some(is_d_done); - while let Some((index, done)) = node_emitter.recv().await { - if index == e { - // don't mark as done until we get the signal that b is finished - let is_b_done = is_b_done.take().unwrap(); - let visited = visited.clone(); - tokio::spawn(async move { - is_b_done.await.unwrap(); - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - }); - } else if index == b { - // send the signal that b is finished - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - b_done.take().unwrap().send(()).unwrap(); - } else if index == a { - // don't mark as done until d finishes - let is_d_done = is_d_done.take().unwrap(); - let visited = visited.clone(); - tokio::spawn(async move { - is_d_done.await.unwrap(); - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - }); - } else if index == d { - // send the signal that b is finished - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - d_done.take().unwrap().send(()).unwrap(); - } else { - visited.lock().unwrap().push(index); - done.send(()).unwrap(); - } - } - walker.wait().await.unwrap(); - assert_eq!(visited.lock().unwrap().as_slice(), &[c, b, e, d, a]); - } -} diff --git a/crates/turborepo-lib/Cargo.toml b/crates/turborepo-lib/Cargo.toml index 4df3f466905b6..2bf81e18ffb35 100644 --- a/crates/turborepo-lib/Cargo.toml +++ b/crates/turborepo-lib/Cargo.toml @@ -1,36 +1,6 @@ -[package] -name = "turborepo-lib" -version = "0.1.0" -edition = "2021" -license = "MIT" - -[features] -# Allows configuring a specific tls backend for reqwest. -# See top level Cargo.toml for more details. -default = ["rustls-tls", "daemon-package-discovery"] -native-tls = ["turborepo-api-client/native-tls", "turbo-updater/native-tls"] -rustls-tls = ["turborepo-api-client/rustls-tls", "turbo-updater/rustls-tls"] - -daemon-package-discovery = [] -daemon-file-hashing = [] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dev-dependencies] -anyhow = { workspace = true, features = ["backtrace"] } -assert_cmd = { workspace = true } -async-stream = "0.3.4" -insta = { workspace = true } -itertools = { workspace = true } -port_scanner = { workspace = true } -pretty_assertions = { workspace = true } -tempfile = { workspace = true } -test-case = { workspace = true } -tracing-test = { version = "0.2.4", features = ["no-env-filter"] } -tracing.workspace = true -turborepo-vercel-api-mock = { workspace = true } - -[lints] -workspace = true +[build-dependencies] +capnpc = "0.18.0" +tonic-build = "0.8.4" [dependencies] async-graphql = { workspace = true } @@ -84,7 +54,7 @@ path-clean = "1.0.1" petgraph = { workspace = true } pidlock = { path = "../turborepo-pidlock" } portable-pty = "0.8.1" -pprof = { version = "0.12.1", features = [ +pprof = { version = "0.14.0", features = [ "prost-codec", "frame-pointer", ], optional = true } @@ -92,7 +62,6 @@ prost = "0.12.3" radix_trie = { workspace = true } rand = { workspace = true } rayon = "1.7.0" -regex.workspace = true reqwest = { workspace = true, default-features = false, features = ["json"] } semver = { workspace = true } serde = { workspace = true, features = ["derive"] } @@ -120,7 +89,6 @@ tower-http = { version = "0.5.2", features = ["cors"] } tracing-appender = "0.2.2" tracing-chrome = "0.7.1" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } -tracing.workspace = true turbo-trace = { workspace = true } turbo-updater = { workspace = true } turbopath = { workspace = true } @@ -149,14 +117,54 @@ wax = { workspace = true } webbrowser = { workspace = true } which = { workspace = true } +[dependencies.regex] +workspace = true + +[dependencies.tracing] +workspace = true + +[dev-dependencies] +anyhow = { workspace = true, features = ["backtrace"] } +assert_cmd = { workspace = true } +async-stream = "0.3.4" +insta = { workspace = true } +itertools = { workspace = true } +port_scanner = { workspace = true } +pretty_assertions = { workspace = true } +tempfile = { workspace = true } +test-case = { workspace = true } +tracing-test = { version = "0.2.4", features = ["no-env-filter"] } +turborepo-vercel-api-mock = { workspace = true } + +[dev-dependencies.tracing] +workspace = true + +[features] +daemon-file-hashing = [] +daemon-package-discovery = [] +default = ["rustls-tls", "daemon-package-discovery"] +native-tls = ["turborepo-api-client/native-tls", "turbo-updater/native-tls"] +rustls-tls = ["turborepo-api-client/rustls-tls", "turbo-updater/rustls-tls"] + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-lib" +version = "0.1.0" + +[target] + +[target.'cfg(target_os = "windows")'] [target.'cfg(target_os = "windows")'.dependencies] -uds_windows = "1.0.2" async-io = "1.12.0" +uds_windows = "1.0.2" [target.'cfg(target_os = "windows")'.dev-dependencies] windows-sys = { version = "0.59", features = ["Win32_System_Threading"] } - -[build-dependencies] -capnpc = "0.18.0" -tonic-build = "0.8.4" diff --git a/crates/turborepo-lib/README.md b/crates/turborepo-lib/README.md deleted file mode 100644 index 10ec2d56f0ec6..0000000000000 --- a/crates/turborepo-lib/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# turborepo-lib - -This crate contains most of the logic for the Turborepo binary and should only be consumed by the `turbo` crate. -The `turbo` crate handles building the CGO archive and linking it to the Rust code. These crates were split up so that we do not have to build the Go code to run the Rust tests. diff --git a/crates/turborepo-lib/src/boundaries.rs b/crates/turborepo-lib/Source/boundaries.rs similarity index 100% rename from crates/turborepo-lib/src/boundaries.rs rename to crates/turborepo-lib/Source/boundaries.rs diff --git a/crates/turborepo-lib/Source/child.rs b/crates/turborepo-lib/Source/child.rs new file mode 100644 index 0000000000000..b9a6fb99bc59c --- /dev/null +++ b/crates/turborepo-lib/Source/child.rs @@ -0,0 +1,28 @@ +use std::{io, process::Command, sync::Arc}; + +use shared_child::SharedChild; + +/// Spawns a child in a way where SIGINT is correctly forwarded to the child +pub fn spawn_child(mut command:Command) -> Result, io::Error> { + let shared_child = Arc::new(SharedChild::spawn(&mut command)?); + let handler_shared_child = shared_child.clone(); + + ctrlc::set_handler(move || { + // on windows, we can't send signals so just kill + // we are quitting anyways so just ignore + #[cfg(target_os = "windows")] + handler_shared_child.kill().ok(); + + // on unix, we should send a SIGTERM to the child + // so that go can gracefully shut down process groups + // SAFETY: we could pull in the nix crate to handle this + // 'safely' but nix::sys::signal::kill just calls libc::kill + #[cfg(not(target_os = "windows"))] + unsafe { + libc::kill(handler_shared_child.id() as i32, libc::SIGTERM); + } + }) + .expect("handler set"); + + Ok(shared_child) +} diff --git a/crates/turborepo-lib/src/cli/error.rs b/crates/turborepo-lib/Source/cli/error.rs similarity index 100% rename from crates/turborepo-lib/src/cli/error.rs rename to crates/turborepo-lib/Source/cli/error.rs diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/Source/cli/mod.rs similarity index 100% rename from crates/turborepo-lib/src/cli/mod.rs rename to crates/turborepo-lib/Source/cli/mod.rs diff --git a/crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-boundaries.snap b/crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-boundaries.snap similarity index 100% rename from crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-boundaries.snap rename to crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-boundaries.snap diff --git a/crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-run-build.snap b/crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-run-build.snap similarity index 100% rename from crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-run-build.snap rename to crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---filter=foo-run-build.snap diff --git a/crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---filter=web-watch-build.snap b/crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---filter=web-watch-build.snap similarity index 100% rename from crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---filter=web-watch-build.snap rename to crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---filter=web-watch-build.snap diff --git a/crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-boundaries.snap b/crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-boundaries.snap similarity index 100% rename from crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-boundaries.snap rename to crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-boundaries.snap diff --git a/crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-run-build.snap b/crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-run-build.snap similarity index 100% rename from crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-run-build.snap rename to crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-run-build.snap diff --git a/crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-watch-build.snap b/crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-watch-build.snap similarity index 100% rename from crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-watch-build.snap rename to crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo---no-daemon-watch-build.snap diff --git a/crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo-watch-build---no-daemon.snap b/crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo-watch-build---no-daemon.snap similarity index 100% rename from crates/turborepo-lib/src/cli/snapshots/turborepo_lib__cli__test__turbo-watch-build---no-daemon.snap rename to crates/turborepo-lib/Source/cli/snapshots/turborepo_lib__cli__test__turbo-watch-build---no-daemon.snap diff --git a/crates/turborepo-lib/src/commands/bin.rs b/crates/turborepo-lib/Source/commands/bin.rs similarity index 100% rename from crates/turborepo-lib/src/commands/bin.rs rename to crates/turborepo-lib/Source/commands/bin.rs diff --git a/crates/turborepo-lib/src/commands/boundaries.rs b/crates/turborepo-lib/Source/commands/boundaries.rs similarity index 100% rename from crates/turborepo-lib/src/commands/boundaries.rs rename to crates/turborepo-lib/Source/commands/boundaries.rs diff --git a/crates/turborepo-lib/src/commands/info.rs b/crates/turborepo-lib/Source/commands/info.rs similarity index 100% rename from crates/turborepo-lib/src/commands/info.rs rename to crates/turborepo-lib/Source/commands/info.rs diff --git a/crates/turborepo-lib/src/commands/link.rs b/crates/turborepo-lib/Source/commands/link.rs similarity index 100% rename from crates/turborepo-lib/src/commands/link.rs rename to crates/turborepo-lib/Source/commands/link.rs diff --git a/crates/turborepo-lib/src/commands/ls.rs b/crates/turborepo-lib/Source/commands/ls.rs similarity index 100% rename from crates/turborepo-lib/src/commands/ls.rs rename to crates/turborepo-lib/Source/commands/ls.rs diff --git a/crates/turborepo-lib/src/commands/mod.rs b/crates/turborepo-lib/Source/commands/mod.rs similarity index 100% rename from crates/turborepo-lib/src/commands/mod.rs rename to crates/turborepo-lib/Source/commands/mod.rs diff --git a/crates/turborepo-lib/src/commands/prune.rs b/crates/turborepo-lib/Source/commands/prune.rs similarity index 100% rename from crates/turborepo-lib/src/commands/prune.rs rename to crates/turborepo-lib/Source/commands/prune.rs diff --git a/crates/turborepo-lib/Source/config.rs b/crates/turborepo-lib/Source/config.rs new file mode 100644 index 0000000000000..6f2595949f036 --- /dev/null +++ b/crates/turborepo-lib/Source/config.rs @@ -0,0 +1,824 @@ +use std::{ + collections::HashMap, + ffi::{OsStr, OsString}, + io, +}; + +use convert_case::{Case, Casing}; +use miette::{Diagnostic, NamedSource, SourceSpan}; +use serde::Deserialize; +use struct_iterable::Iterable; +use thiserror::Error; +use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPath}; +use turborepo_auth::{TURBO_TOKEN_DIR, TURBO_TOKEN_FILE, VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE}; +use turborepo_dirs::{config_dir, vercel_config_dir}; +use turborepo_errors::TURBO_SITE; + +pub use crate::turbo_json::RawTurboJson; +use crate::{commands::CommandBase, turbo_json}; + +#[derive(Debug, Error, Diagnostic)] +#[error("Environment variables should not be prefixed with \"{env_pipeline_delimiter}\"")] +#[diagnostic( + code(invalid_env_prefix), + url("{}/messages/{}", TURBO_SITE, self.code().unwrap().to_string().to_case(Case::Kebab)) +)] +pub struct InvalidEnvPrefixError { + pub value:String, + pub key:String, + #[source_code] + pub text:NamedSource, + #[label("variable with invalid prefix declared here")] + pub span:Option, + pub env_pipeline_delimiter:&'static str, +} + +#[allow(clippy::enum_variant_names)] +#[derive(Debug, Error, Diagnostic)] +pub enum Error { + #[error("Authentication error: {0}")] + Auth(#[from] turborepo_auth::Error), + #[error("Global config path not found")] + NoGlobalConfigPath, + #[error("Global auth file path not found")] + NoGlobalAuthFilePath, + #[error("Global config directory not found")] + NoGlobalConfigDir, + #[error(transparent)] + PackageJson(#[from] turborepo_repository::package_json::Error), + #[error( + "Could not find turbo.json.\nFollow directions at https://turbo.build/repo/docs to create \ + one" + )] + NoTurboJSON, + #[error(transparent)] + SerdeJson(#[from] serde_json::Error), + #[error(transparent)] + Io(#[from] io::Error), + #[error(transparent)] + Camino(#[from] camino::FromPathBufError), + #[error(transparent)] + Reqwest(#[from] reqwest::Error), + #[error("Encountered an IO error while attempting to read {config_path}: {error}")] + FailedToReadConfig { config_path:AbsoluteSystemPathBuf, error:io::Error }, + #[error("Encountered an IO error while attempting to set {config_path}: {error}")] + FailedToSetConfig { config_path:AbsoluteSystemPathBuf, error:io::Error }, + #[error( + "Package tasks (#) are not allowed in single-package repositories: found \ + {task_id}" + )] + #[diagnostic(code(package_task_in_single_package_mode), url("{}/messages/{}", TURBO_SITE, self.code().unwrap().to_string().to_case(Case::Kebab)))] + PackageTaskInSinglePackageMode { + task_id:String, + #[source_code] + text:NamedSource, + #[label("package task found here")] + span:Option, + }, + #[error(transparent)] + #[diagnostic(transparent)] + InvalidEnvPrefix(Box), + #[error(transparent)] + PathError(#[from] turbopath::PathError), + #[diagnostic( + code(unnecessary_package_task_syntax), + url("{}/messages/{}", TURBO_SITE, self.code().unwrap().to_string().to_case(Case::Kebab)) + )] + #[error("\"{actual}\". Use \"{wanted}\" instead")] + UnnecessaryPackageTaskSyntax { + actual:String, + wanted:String, + #[label("unnecessary package syntax found here")] + span:Option, + #[source_code] + text:NamedSource, + }, + #[error("You can only extend from the root workspace")] + ExtendFromNonRoot { + #[label("non-root workspace found here")] + span:Option, + #[source_code] + text:NamedSource, + }, + #[error("`{field}` cannot contain an environment variable")] + InvalidDependsOnValue { + field:&'static str, + #[label("environment variable found here")] + span:Option, + #[source_code] + text:NamedSource, + }, + #[error("`{field}` cannot contain an absolute path")] + AbsolutePathInConfig { + field:&'static str, + #[label("absolute path found here")] + span:Option, + #[source_code] + text:NamedSource, + }, + #[error("No \"extends\" key found")] + NoExtends { + #[label("add extends key here")] + span:Option, + #[source_code] + text:NamedSource, + }, + #[error("Tasks cannot be marked as interactive and cacheable")] + InteractiveNoCacheable { + #[label("marked interactive here")] + span:Option, + #[source_code] + text:NamedSource, + }, + #[error("found `pipeline` field instead of `tasks`")] + #[diagnostic(help("changed in 2.0: `pipeline` has been renamed to `tasks`"))] + PipelineField { + #[label("rename `pipeline` field to `tasks`")] + span:Option, + #[source_code] + text:NamedSource, + }, + #[error("Failed to create APIClient: {0}")] + ApiClient(#[source] turborepo_api_client::Error), + #[error("{0} is not UTF8.")] + Encoding(String), + #[error("TURBO_SIGNATURE should be either 1 or 0.")] + InvalidSignature, + #[error("TURBO_REMOTE_CACHE_ENABLED should be either 1 or 0.")] + InvalidRemoteCacheEnabled, + #[error("TURBO_REMOTE_CACHE_TIMEOUT: error parsing timeout.")] + InvalidRemoteCacheTimeout(#[source] std::num::ParseIntError), + #[error("TURBO_REMOTE_CACHE_UPLOAD_TIMEOUT: error parsing timeout.")] + InvalidUploadTimeout(#[source] std::num::ParseIntError), + #[error("TURBO_PREFLIGHT should be either 1 or 0.")] + InvalidPreflight, + #[error(transparent)] + #[diagnostic(transparent)] + TurboJsonParseError(#[from] turbo_json::parser::Error), +} + +macro_rules! create_builder { + ($func_name:ident, $property_name:ident, $type:ty) => { + pub fn $func_name(mut self, value:$type) -> Self { + self.override_config.$property_name = value; + self + } + }; +} + +const DEFAULT_API_URL:&str = "https://vercel.com/api"; +const DEFAULT_LOGIN_URL:&str = "https://vercel.com"; +const DEFAULT_TIMEOUT:u64 = 30; +const DEFAULT_UPLOAD_TIMEOUT:u64 = 60; + +// We intentionally don't derive Serialize so that different parts +// of the code that want to display the config can tune how they +// want to display and what fields they want to include. +#[derive(Deserialize, Default, Debug, PartialEq, Eq, Clone, Iterable)] +#[serde(rename_all = "camelCase")] +pub struct ConfigurationOptions { + #[serde(alias = "apiurl")] + #[serde(alias = "ApiUrl")] + #[serde(alias = "APIURL")] + pub(crate) api_url:Option, + #[serde(alias = "loginurl")] + #[serde(alias = "LoginUrl")] + #[serde(alias = "LOGINURL")] + pub(crate) login_url:Option, + #[serde(alias = "teamslug")] + #[serde(alias = "TeamSlug")] + #[serde(alias = "TEAMSLUG")] + pub(crate) team_slug:Option, + #[serde(alias = "teamid")] + #[serde(alias = "TeamId")] + #[serde(alias = "TEAMID")] + pub(crate) team_id:Option, + pub(crate) token:Option, + pub(crate) signature:Option, + pub(crate) preflight:Option, + pub(crate) timeout:Option, + pub(crate) upload_timeout:Option, + pub(crate) enabled:Option, + pub(crate) spaces_id:Option, + #[serde(rename = "ui")] + pub(crate) ui:Option, +} + +#[derive(Default)] +pub struct TurborepoConfigBuilder { + repo_root:AbsoluteSystemPathBuf, + override_config:ConfigurationOptions, + + #[cfg(test)] + global_config_path:Option, + #[cfg(test)] + environment:HashMap, +} + +// Getters +impl ConfigurationOptions { + pub fn api_url(&self) -> &str { + non_empty_str(self.api_url.as_deref()).unwrap_or(DEFAULT_API_URL) + } + + pub fn login_url(&self) -> &str { + non_empty_str(self.login_url.as_deref()).unwrap_or(DEFAULT_LOGIN_URL) + } + + pub fn team_slug(&self) -> Option<&str> { + self.team_slug.as_deref().and_then(|slug| (!slug.is_empty()).then_some(slug)) + } + + pub fn team_id(&self) -> Option<&str> { non_empty_str(self.team_id.as_deref()) } + + pub fn token(&self) -> Option<&str> { non_empty_str(self.token.as_deref()) } + + pub fn signature(&self) -> bool { self.signature.unwrap_or_default() } + + pub fn enabled(&self) -> bool { self.enabled.unwrap_or(true) } + + pub fn preflight(&self) -> bool { self.preflight.unwrap_or_default() } + + /// Note: 0 implies no timeout + pub fn timeout(&self) -> u64 { self.timeout.unwrap_or(DEFAULT_TIMEOUT) } + + /// Note: 0 implies no timeout + pub fn upload_timeout(&self) -> u64 { self.upload_timeout.unwrap_or(DEFAULT_UPLOAD_TIMEOUT) } + + pub fn spaces_id(&self) -> Option<&str> { self.spaces_id.as_deref() } + + pub fn ui(&self) -> bool { self.ui.unwrap_or(true) && atty::is(atty::Stream::Stdout) } +} + +// Maps Some("") to None to emulate how Go handles empty strings +fn non_empty_str(s:Option<&str>) -> Option<&str> { s.filter(|s| !s.is_empty()) } + +trait ResolvedConfigurationOptions { + fn get_configuration_options(self) -> Result; +} + +impl ResolvedConfigurationOptions for RawTurboJson { + fn get_configuration_options(self) -> Result { + let mut opts = if let Some(remote_cache_options) = &self.remote_cache { + remote_cache_options.into() + } else { + ConfigurationOptions::default() + }; + // Don't allow token to be set for shared config. + opts.token = None; + opts.spaces_id = self + .experimental_spaces + .and_then(|spaces| spaces.id) + .map(|spaces_id| spaces_id.into()); + opts.ui = self.ui.map(|ui| ui.use_tui()); + Ok(opts) + } +} + +// Used for global config and local config. +impl ResolvedConfigurationOptions for ConfigurationOptions { + fn get_configuration_options(self) -> Result { Ok(self) } +} + +fn get_lowercased_env_vars() -> HashMap { + std::env::vars_os().map(|(k, v)| (k.to_ascii_lowercase(), v)).collect() +} + +fn get_env_var_config( + environment:&HashMap, +) -> Result { + let mut turbo_mapping = HashMap::new(); + turbo_mapping.insert(OsString::from("turbo_api"), "api_url"); + turbo_mapping.insert(OsString::from("turbo_login"), "login_url"); + turbo_mapping.insert(OsString::from("turbo_team"), "team_slug"); + turbo_mapping.insert(OsString::from("turbo_teamid"), "team_id"); + turbo_mapping.insert(OsString::from("turbo_token"), "token"); + turbo_mapping.insert(OsString::from("turbo_remote_cache_timeout"), "timeout"); + turbo_mapping.insert(OsString::from("turbo_remote_cache_upload_timeout"), "upload_timeout"); + turbo_mapping.insert(OsString::from("turbo_ui"), "ui"); + turbo_mapping.insert(OsString::from("turbo_preflight"), "preflight"); + + // We do not enable new config sources: + // turbo_mapping.insert(String::from("turbo_signature"), "signature"); // new + // turbo_mapping.insert(String::from("turbo_remote_cache_enabled"), "enabled"); + + let mut output_map = HashMap::new(); + + turbo_mapping.into_iter().try_for_each( + |(mapping_key, mapped_property)| -> Result<(), Error> { + if let Some(value) = environment.get(&mapping_key) { + let converted = value.to_str().ok_or_else(|| { + Error::Encoding( + // CORRECTNESS: the mapping_key is hardcoded above. + mapping_key.to_ascii_uppercase().into_string().unwrap(), + ) + })?; + output_map.insert(mapped_property, converted.to_owned()); + Ok(()) + } else { + Ok(()) + } + }, + )?; + + // Process signature + let signature = if let Some(signature) = output_map.get("signature") { + match signature.as_str() { + "0" => Some(false), + "1" => Some(true), + _ => return Err(Error::InvalidSignature), + } + } else { + None + }; + + // Process preflight + let preflight = if let Some(preflight) = output_map.get("preflight") { + match preflight.as_str() { + "0" | "false" => Some(false), + "1" | "true" => Some(true), + "" => None, + _ => return Err(Error::InvalidPreflight), + } + } else { + None + }; + + // Process enabled + let enabled = if let Some(enabled) = output_map.get("enabled") { + match enabled.as_str() { + "0" => Some(false), + "1" => Some(true), + _ => return Err(Error::InvalidRemoteCacheEnabled), + } + } else { + None + }; + + // Process timeout + let timeout = if let Some(timeout) = output_map.get("timeout") { + Some(timeout.parse::().map_err(Error::InvalidRemoteCacheTimeout)?) + } else { + None + }; + + let upload_timeout = if let Some(upload_timeout) = output_map.get("upload_timeout") { + Some(upload_timeout.parse::().map_err(Error::InvalidUploadTimeout)?) + } else { + None + }; + + // Process experimentalUI + let ui = output_map.get("ui").and_then(|val| { + match val.as_str() { + "true" | "1" => Some(true), + "false" | "0" => Some(false), + _ => None, + } + }); + + // We currently don't pick up a Spaces ID via env var, we likely won't + // continue using the Spaces name, we can add an env var when we have the + // name we want to stick with. + let spaces_id = None; + + let output = ConfigurationOptions { + api_url:output_map.get("api_url").cloned(), + login_url:output_map.get("login_url").cloned(), + team_slug:output_map.get("team_slug").cloned(), + team_id:output_map.get("team_id").cloned(), + token:output_map.get("token").cloned(), + + // Processed booleans + signature, + preflight, + enabled, + ui, + + // Processed numbers + timeout, + upload_timeout, + spaces_id, + }; + + Ok(output) +} + +fn get_override_env_var_config( + environment:&HashMap, +) -> Result { + let mut vercel_artifacts_mapping = HashMap::new(); + vercel_artifacts_mapping.insert(OsString::from("vercel_artifacts_token"), "token"); + vercel_artifacts_mapping.insert(OsString::from("vercel_artifacts_owner"), "team_id"); + + let mut output_map = HashMap::new(); + + // Process the VERCEL_ARTIFACTS_* next. + vercel_artifacts_mapping.into_iter().try_for_each( + |(mapping_key, mapped_property)| -> Result<(), Error> { + if let Some(value) = environment.get(&mapping_key) { + let converted = value.to_str().ok_or_else(|| { + Error::Encoding( + // CORRECTNESS: the mapping_key is hardcoded above. + mapping_key.to_ascii_uppercase().into_string().unwrap(), + ) + })?; + output_map.insert(mapped_property, converted.to_owned()); + Ok(()) + } else { + Ok(()) + } + }, + )?; + + let ui = environment + .get(OsStr::new("ci")) + .or_else(|| environment.get(OsStr::new("no_color"))) + .and_then(|value| { + // If either of these are truthy, then we disable the TUI + if value == "true" || value == "1" { Some(false) } else { None } + }); + + let output = ConfigurationOptions { + api_url:None, + login_url:None, + team_slug:None, + team_id:output_map.get("team_id").cloned(), + token:output_map.get("token").cloned(), + + signature:None, + preflight:None, + enabled:None, + ui, + timeout:None, + upload_timeout:None, + spaces_id:None, + }; + + Ok(output) +} + +impl TurborepoConfigBuilder { + create_builder!(with_api_url, api_url, Option); + + create_builder!(with_login_url, login_url, Option); + + create_builder!(with_team_slug, team_slug, Option); + + create_builder!(with_team_id, team_id, Option); + + create_builder!(with_token, token, Option); + + create_builder!(with_signature, signature, Option); + + create_builder!(with_enabled, enabled, Option); + + create_builder!(with_preflight, preflight, Option); + + create_builder!(with_timeout, timeout, Option); + + create_builder!(with_ui, ui, Option); + + pub fn new(base:&CommandBase) -> Self { + Self { + repo_root:base.repo_root.to_owned(), + override_config:Default::default(), + #[cfg(test)] + global_config_path:base.global_config_path.clone(), + #[cfg(test)] + environment:Default::default(), + } + } + + // Getting all of the paths. + fn global_config_path(&self) -> Result { + #[cfg(test)] + if let Some(global_config_path) = self.global_config_path.clone() { + return Ok(global_config_path); + } + + let config_dir = config_dir()?.ok_or(Error::NoGlobalConfigPath)?; + + Ok(config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE])) + } + + fn global_auth_path(&self) -> Result { + #[cfg(test)] + if let Some(global_config_path) = self.global_config_path.clone() { + return Ok(global_config_path); + } + + let vercel_config_dir = vercel_config_dir()?.ok_or(Error::NoGlobalConfigDir)?; + // Check for both Vercel and Turbo paths. Vercel takes priority. + let vercel_path = vercel_config_dir.join_components(&[VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE]); + if vercel_path.exists() { + return Ok(vercel_path); + } + + let turbo_config_dir = config_dir()?.ok_or(Error::NoGlobalConfigDir)?; + + Ok(turbo_config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE])) + } + + fn local_config_path(&self) -> AbsoluteSystemPathBuf { + self.repo_root.join_components(&[".turbo", "config.json"]) + } + + #[allow(dead_code)] + fn root_package_json_path(&self) -> AbsoluteSystemPathBuf { + self.repo_root.join_component("package.json") + } + + #[allow(dead_code)] + fn root_turbo_json_path(&self) -> AbsoluteSystemPathBuf { + self.repo_root.join_component("turbo.json") + } + + #[cfg(test)] + fn get_environment(&self) -> HashMap { self.environment.clone() } + + #[cfg(not(test))] + fn get_environment(&self) -> HashMap { get_lowercased_env_vars() } + + fn get_global_config(&self) -> Result { + let global_config_path = self.global_config_path()?; + let mut contents = + global_config_path.read_existing_to_string_or(Ok("{}")).map_err(|error| { + Error::FailedToReadConfig { config_path:global_config_path.clone(), error } + })?; + if contents.is_empty() { + contents = String::from("{}"); + } + let global_config:ConfigurationOptions = serde_json::from_str(&contents)?; + Ok(global_config) + } + + fn get_local_config(&self) -> Result { + let local_config_path = self.local_config_path(); + let mut contents = + local_config_path.read_existing_to_string_or(Ok("{}")).map_err(|error| { + Error::FailedToReadConfig { config_path:local_config_path.clone(), error } + })?; + if contents.is_empty() { + contents = String::from("{}"); + } + let local_config:ConfigurationOptions = serde_json::from_str(&contents)?; + Ok(local_config) + } + + fn get_global_auth(&self) -> Result { + let global_auth_path = self.global_auth_path()?; + let token = match turborepo_auth::Token::from_file(&global_auth_path) { + Ok(token) => token, + // Multiple ways this can go wrong. Don't error out if we can't find the token - it + // just might not be there. + Err(e) => { + if matches!(e, turborepo_auth::Error::TokenNotFound) { + return Ok(ConfigurationOptions::default()); + } + + return Err(e.into()); + }, + }; + + // No auth token found in either Vercel or Turbo config. + if token.into_inner().is_empty() { + return Ok(ConfigurationOptions::default()); + } + + let global_auth:ConfigurationOptions = ConfigurationOptions { + token:Some(token.into_inner().to_owned()), + ..Default::default() + }; + Ok(global_auth) + } + + pub fn build(&self) -> Result { + // Priority, from least significant to most significant: + // - shared configuration (turbo.json) + // - global configuration (~/.turbo/config.json) + // - local configuration (/.turbo/config.json) + // - environment variables + // - CLI arguments + // - builder pattern overrides. + + let turbo_json = + RawTurboJson::read(&self.repo_root, AnchoredSystemPath::new("turbo.json").unwrap()) + .or_else(|e| { + if let Error::Io(e) = &e { + if matches!(e.kind(), std::io::ErrorKind::NotFound) { + return Ok(Default::default()); + } + } + + Err(e) + })?; + let global_config = self.get_global_config()?; + let global_auth = self.get_global_auth()?; + let local_config = self.get_local_config()?; + let env_vars = self.get_environment(); + let env_var_config = get_env_var_config(&env_vars)?; + let override_env_var_config = get_override_env_var_config(&env_vars)?; + + let sources = [ + turbo_json.get_configuration_options(), + global_config.get_configuration_options(), + global_auth.get_configuration_options(), + local_config.get_configuration_options(), + env_var_config.get_configuration_options(), + Ok(self.override_config.clone()), + override_env_var_config.get_configuration_options(), + ]; + + sources + .into_iter() + .try_fold(ConfigurationOptions::default(), |mut acc, current_source| { + current_source.map(|current_source_config| { + if let Some(api_url) = current_source_config.api_url.clone() { + acc.api_url = Some(api_url); + } + if let Some(login_url) = current_source_config.login_url.clone() { + acc.login_url = Some(login_url); + } + if let Some(team_slug) = current_source_config.team_slug.clone() { + acc.team_slug = Some(team_slug); + } + if let Some(team_id) = current_source_config.team_id.clone() { + acc.team_id = Some(team_id); + } + if let Some(token) = current_source_config.token.clone() { + acc.token = Some(token); + } + if let Some(signature) = current_source_config.signature { + acc.signature = Some(signature); + } + if let Some(enabled) = current_source_config.enabled { + acc.enabled = Some(enabled); + } + if let Some(preflight) = current_source_config.preflight { + acc.preflight = Some(preflight); + } + if let Some(timeout) = current_source_config.timeout { + acc.timeout = Some(timeout); + } + if let Some(spaces_id) = current_source_config.spaces_id { + acc.spaces_id = Some(spaces_id); + } + if let Some(ui) = current_source_config.ui { + acc.ui = Some(ui); + } + + acc + }) + }) + } +} + +#[cfg(test)] +mod test { + use std::{collections::HashMap, ffi::OsString}; + + use tempfile::TempDir; + use turbopath::AbsoluteSystemPathBuf; + + use crate::config::{ + ConfigurationOptions, + DEFAULT_API_URL, + DEFAULT_LOGIN_URL, + DEFAULT_TIMEOUT, + TurborepoConfigBuilder, + get_env_var_config, + get_override_env_var_config, + }; + + #[test] + fn test_defaults() { + let defaults:ConfigurationOptions = Default::default(); + assert_eq!(defaults.api_url(), DEFAULT_API_URL); + assert_eq!(defaults.login_url(), DEFAULT_LOGIN_URL); + assert_eq!(defaults.team_slug(), None); + assert_eq!(defaults.team_id(), None); + assert_eq!(defaults.token(), None); + assert!(!defaults.signature()); + assert!(defaults.enabled()); + assert!(!defaults.preflight()); + assert_eq!(defaults.timeout(), DEFAULT_TIMEOUT); + assert_eq!(defaults.spaces_id(), None); + } + + #[test] + fn test_env_setting() { + let mut env:HashMap = HashMap::new(); + + let turbo_api = "https://example.com/api"; + let turbo_login = "https://example.com/login"; + let turbo_team = "vercel"; + let turbo_teamid = "team_nLlpyC6REAqxydlFKbrMDlud"; + let turbo_token = "abcdef1234567890abcdef"; + let turbo_remote_cache_timeout = 200; + + env.insert("turbo_api".into(), turbo_api.into()); + env.insert("turbo_login".into(), turbo_login.into()); + env.insert("turbo_team".into(), turbo_team.into()); + env.insert("turbo_teamid".into(), turbo_teamid.into()); + env.insert("turbo_token".into(), turbo_token.into()); + env.insert( + "turbo_remote_cache_timeout".into(), + turbo_remote_cache_timeout.to_string().into(), + ); + env.insert("turbo_ui".into(), "true".into()); + env.insert("turbo_preflight".into(), "true".into()); + + let config = get_env_var_config(&env).unwrap(); + assert!(config.preflight()); + assert_eq!(turbo_api, config.api_url.unwrap()); + assert_eq!(turbo_login, config.login_url.unwrap()); + assert_eq!(turbo_team, config.team_slug.unwrap()); + assert_eq!(turbo_teamid, config.team_id.unwrap()); + assert_eq!(turbo_token, config.token.unwrap()); + assert_eq!(turbo_remote_cache_timeout, config.timeout.unwrap()); + assert_eq!(Some(true), config.ui); + } + + #[test] + fn test_empty_env_setting() { + let mut env:HashMap = HashMap::new(); + env.insert("turbo_api".into(), "".into()); + env.insert("turbo_login".into(), "".into()); + env.insert("turbo_team".into(), "".into()); + env.insert("turbo_teamid".into(), "".into()); + env.insert("turbo_token".into(), "".into()); + env.insert("turbo_ui".into(), "".into()); + env.insert("turbo_preflight".into(), "".into()); + + let config = get_env_var_config(&env).unwrap(); + assert_eq!(config.api_url(), DEFAULT_API_URL); + assert_eq!(config.login_url(), DEFAULT_LOGIN_URL); + assert_eq!(config.team_slug(), None); + assert_eq!(config.team_id(), None); + assert_eq!(config.token(), None); + assert_eq!(config.ui, None); + assert!(!config.preflight()); + } + + #[test] + fn test_override_env_setting() { + let mut env:HashMap = HashMap::new(); + + let vercel_artifacts_token = "correct-horse-battery-staple"; + let vercel_artifacts_owner = "bobby_tables"; + + env.insert("vercel_artifacts_token".into(), vercel_artifacts_token.into()); + env.insert("vercel_artifacts_owner".into(), vercel_artifacts_owner.into()); + env.insert("ci".into(), "1".into()); + + let config = get_override_env_var_config(&env).unwrap(); + assert_eq!(vercel_artifacts_token, config.token.unwrap()); + assert_eq!(vercel_artifacts_owner, config.team_id.unwrap()); + assert_eq!(Some(false), config.ui); + } + + #[test] + fn test_env_layering() { + let tmp_dir = TempDir::new().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let global_config_path = AbsoluteSystemPathBuf::try_from( + TempDir::new().unwrap().path().join("nonexistent.json"), + ) + .unwrap(); + + repo_root + .join_component("turbo.json") + .create_with_contents(r#"{"experimentalSpaces": {"id": "my-spaces-id"}}"#) + .unwrap(); + + let turbo_teamid = "team_nLlpyC6REAqxydlFKbrMDlud"; + let turbo_token = "abcdef1234567890abcdef"; + let vercel_artifacts_owner = "team_SOMEHASH"; + let vercel_artifacts_token = "correct-horse-battery-staple"; + + let mut env:HashMap = HashMap::new(); + env.insert("turbo_teamid".into(), turbo_teamid.into()); + env.insert("turbo_token".into(), turbo_token.into()); + env.insert("vercel_artifacts_token".into(), vercel_artifacts_token.into()); + env.insert("vercel_artifacts_owner".into(), vercel_artifacts_owner.into()); + + let override_config = ConfigurationOptions { + token:Some("unseen".into()), + team_id:Some("unseen".into()), + ..Default::default() + }; + + let builder = TurborepoConfigBuilder { + repo_root, + override_config, + global_config_path:Some(global_config_path), + environment:env, + }; + + let config = builder.build().unwrap(); + assert_eq!(config.team_id().unwrap(), vercel_artifacts_owner); + assert_eq!(config.token().unwrap(), vercel_artifacts_token); + assert_eq!(config.spaces_id().unwrap(), "my-spaces-id"); + } +} diff --git a/crates/turborepo-lib/src/config/env.rs b/crates/turborepo-lib/Source/config/env.rs similarity index 100% rename from crates/turborepo-lib/src/config/env.rs rename to crates/turborepo-lib/Source/config/env.rs diff --git a/crates/turborepo-lib/Source/config/file.rs b/crates/turborepo-lib/Source/config/file.rs new file mode 100644 index 0000000000000..3cebb2d2dd5a0 --- /dev/null +++ b/crates/turborepo-lib/Source/config/file.rs @@ -0,0 +1,100 @@ +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; +use turborepo_auth::{TURBO_TOKEN_DIR, TURBO_TOKEN_FILE, VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE}; +use turborepo_dirs::{config_dir, vercel_config_dir}; + +use super::{ConfigurationOptions, Error, ResolvedConfigurationOptions}; + +pub struct ConfigFile { + path:AbsoluteSystemPathBuf, +} + +impl ConfigFile { + pub fn global_config(override_path:Option) -> Result { + let path = override_path.map_or_else(global_config_path, Ok)?; + Ok(Self { path }) + } + + pub fn local_config(repo_root:&AbsoluteSystemPath) -> Self { + let path = repo_root.join_components(&[".turbo", "config.json"]); + Self { path } + } +} + +impl ResolvedConfigurationOptions for ConfigFile { + fn get_configuration_options( + &self, + _existing_config:&ConfigurationOptions, + ) -> Result { + let contents = self + .path + .read_existing_to_string() + .map_err(|error| Error::FailedToReadConfig { config_path:self.path.clone(), error })? + .filter(|s| !s.is_empty()); + + let global_config = contents + .as_deref() + .map_or_else(|| Ok(ConfigurationOptions::default()), serde_json::from_str)?; + Ok(global_config) + } +} + +pub struct AuthFile { + path:AbsoluteSystemPathBuf, +} + +impl AuthFile { + pub fn global_auth(override_path:Option) -> Result { + let path = override_path.map_or_else(global_auth_path, Ok)?; + Ok(Self { path }) + } +} + +impl ResolvedConfigurationOptions for AuthFile { + fn get_configuration_options( + &self, + _existing_config:&ConfigurationOptions, + ) -> Result { + let token = match turborepo_auth::Token::from_file(&self.path) { + Ok(token) => token, + // Multiple ways this can go wrong. Don't error out if we can't find the token - it + // just might not be there. + Err(e) => { + if matches!(e, turborepo_auth::Error::TokenNotFound) { + return Ok(ConfigurationOptions::default()); + } + + return Err(e.into()); + }, + }; + + // No auth token found in either Vercel or Turbo config. + if token.into_inner().is_empty() { + return Ok(ConfigurationOptions::default()); + } + + let global_auth:ConfigurationOptions = ConfigurationOptions { + token:Some(token.into_inner().to_owned()), + ..Default::default() + }; + Ok(global_auth) + } +} + +fn global_config_path() -> Result { + let config_dir = config_dir()?.ok_or(Error::NoGlobalConfigPath)?; + + Ok(config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE])) +} + +fn global_auth_path() -> Result { + let vercel_config_dir = vercel_config_dir()?.ok_or(Error::NoGlobalConfigDir)?; + // Check for both Vercel and Turbo paths. Vercel takes priority. + let vercel_path = vercel_config_dir.join_components(&[VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE]); + if vercel_path.exists() { + return Ok(vercel_path); + } + + let turbo_config_dir = config_dir()?.ok_or(Error::NoGlobalConfigDir)?; + + Ok(turbo_config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE])) +} diff --git a/crates/turborepo-lib/src/config/mod.rs b/crates/turborepo-lib/Source/config/mod.rs similarity index 100% rename from crates/turborepo-lib/src/config/mod.rs rename to crates/turborepo-lib/Source/config/mod.rs diff --git a/crates/turborepo-lib/Source/config/override_env.rs b/crates/turborepo-lib/Source/config/override_env.rs new file mode 100644 index 0000000000000..0188fa9ee3463 --- /dev/null +++ b/crates/turborepo-lib/Source/config/override_env.rs @@ -0,0 +1,415 @@ +use std::{ + collections::HashMap, + ffi::{OsStr, OsString}, +}; + +use super::{ConfigurationOptions, Error, ResolvedConfigurationOptions, env::truth_env_var}; +use crate::turbo_json::UIMode; + +// Hi! If you're new here: +// 1. The general pattern is that: +// - ConfigurationOptions.token corresponds to TURBO_TOKEN or +// VERCEL_ARTIFACTS_TOKEN +// - ConfigurationOptions.team_id corresponds to TURBO_TEAMID or +// VERCEL_ARTIFACTS_OWNER +// - ConfigurationOptions.team_slug corresponds to TURBO_TEAM +// 1. We're ultimately poking around the env vars looking for _pairs_ that make +// sense. +// Since we presume that users are the only ones sending TURBO_* and Vercel is +// the only one sending VERCEL_*, we can make some assumptions. Namely, we +// assume that if we have one of VERCEL_ARTIFACTS_OWNER or +// VERCEL_ARTIFACTS_TOKEN we will always have both. +// 1. Watch out for mixing up `TURBO_TEAM` and `TURBO_TEAMID`. Same for +// ConfigurationOptions.team_id and ConfigurationOptions.team_slug. + +/// these correspond directly to the environment variables that this module +/// needs to do it's work +#[allow(non_snake_case)] +#[derive(Default, Debug, PartialEq)] +struct Input { + TURBO_TEAM:Option, + TURBO_TEAMID:Option, + TURBO_TOKEN:Option, + VERCEL_ARTIFACTS_OWNER:Option, + VERCEL_ARTIFACTS_TOKEN:Option, +} + +impl Input { + fn new() -> Self { Self::default() } +} + +impl<'a> TryFrom<&'a HashMap> for Input { + type Error = Error; + + fn try_from(environment:&'a HashMap) -> Result { + let get_value = |key:&str| -> Result, Error> { + let Some(value) = environment.get(OsStr::new(key)) else { + return Ok(None); + }; + let value = value.to_str().ok_or_else(|| Error::Encoding(key.to_ascii_uppercase()))?; + Ok(Some(value.to_string())) + }; + Ok(Self { + TURBO_TEAM:get_value("turbo_team")?, + TURBO_TEAMID:get_value("turbo_teamid")?, + TURBO_TOKEN:get_value("turbo_token")?, + VERCEL_ARTIFACTS_OWNER:get_value("vercel_artifacts_owner")?, + VERCEL_ARTIFACTS_TOKEN:get_value("vercel_artifacts_token")?, + }) + } +} + +// this is an internal structure (that's a partial of ConfigurationOptions) that +// we use to store +struct Output { + /// maps to ConfigurationOptions.team_id + team_id:Option, + // maps to ConfigurationOptions.team_slug + team_slug:Option, + // maps to ConfigurationOptions.token + token:Option, +} + +impl Output { + fn new() -> Self { Self { team_id:None, team_slug:None, token:None } } +} + +impl From for Output { + fn from(input:Input) -> Self { + // TURBO_TEAMID+TURBO_TOKEN or TURBO_TEAM+TURBO_TOKEN + if input.TURBO_TOKEN.is_some() + && (input.TURBO_TEAMID.is_some() || input.TURBO_TEAM.is_some()) + { + Output { + team_id:input.TURBO_TEAMID, + team_slug:input.TURBO_TEAM, + token:input.TURBO_TOKEN, + } + } + // if there's both Vercel items, we use those next + else if input.VERCEL_ARTIFACTS_TOKEN.is_some() && input.VERCEL_ARTIFACTS_OWNER.is_some() { + Output { + team_id:input.VERCEL_ARTIFACTS_OWNER, + team_slug:input.TURBO_TEAM, /* this may or may not be Some, but if it is we can + * pass it along too */ + token:input.VERCEL_ARTIFACTS_TOKEN, + } + } + // from this point below, there's no token we can do anything with + // ------------------------------------------------ + else { + Output { + // prefer TURBO_TEAMID to VERCEL_ARTIFACTS_OWNER + team_id:input.TURBO_TEAMID.or(input.VERCEL_ARTIFACTS_OWNER), + // No alternative source for team_slug so always use TURBO_TEAM + team_slug:input.TURBO_TEAM, + token:None, + } + } + } +} + +pub struct OverrideEnvVars<'a> { + environment:&'a HashMap, + output:Output, +} + +impl<'a> OverrideEnvVars<'a> { + pub fn new(environment:&'a HashMap) -> Result { + let input = Input::try_from(environment)?; + let output = Output::from(input); + + Ok(Self { environment, output }) + } + + fn ui(&self) -> Option { + let value = self + .environment + .get(OsStr::new("ci")) + .or_else(|| self.environment.get(OsStr::new("no_color")))?; + truth_env_var(value.to_str()?)?.then_some(UIMode::Stream) + } +} + +impl<'a> ResolvedConfigurationOptions for OverrideEnvVars<'a> { + fn get_configuration_options( + &self, + _existing_config:&ConfigurationOptions, + ) -> Result { + let output = ConfigurationOptions { + team_id:self.output.team_id.clone(), + token:self.output.token.clone(), + team_slug:self.output.team_slug.clone(), + ui:self.ui(), + ..Default::default() + }; + Ok(output) + } +} + +#[cfg(test)] +mod test { + use super::*; + + const VERCEL_ARTIFACTS_OWNER:&str = "valueof:VERCEL_ARTIFACTS_OWNER"; + const VERCEL_ARTIFACTS_TOKEN:&str = "valueof:VERCEL_ARTIFACTS_TOKEN"; + const TURBO_TEAMID:&str = "valueof:TURBO_TEAMID"; + const TURBO_TEAM:&str = "valueof:TURBO_TEAM"; + const TURBO_TOKEN:&str = "valueof:TURBO_TOKEN"; + + struct TestCase { + input:Input, + output:Output, + reason:&'static str, + } + + impl TestCase { + fn new() -> Self { Self { input:Input::new(), output:Output::new(), reason:"missing" } } + + fn reason(mut self, reason:&'static str) -> Self { + self.reason = reason; + self + } + + #[allow(non_snake_case)] + fn VERCEL_ARTIFACTS_OWNER(mut self) -> Self { + self.input.VERCEL_ARTIFACTS_OWNER = Some(VERCEL_ARTIFACTS_OWNER.into()); + self + } + + #[allow(non_snake_case)] + fn VERCEL_ARTIFACTS_TOKEN(mut self) -> Self { + self.input.VERCEL_ARTIFACTS_TOKEN = Some(VERCEL_ARTIFACTS_TOKEN.into()); + self + } + + #[allow(non_snake_case)] + fn TURBO_TEAMID(mut self) -> Self { + self.input.TURBO_TEAMID = Some(TURBO_TEAMID.into()); + self + } + + #[allow(non_snake_case)] + fn TURBO_TEAM(mut self) -> Self { + self.input.TURBO_TEAM = Some(TURBO_TEAM.into()); + self + } + + #[allow(non_snake_case)] + fn TURBO_TOKEN(mut self) -> Self { + self.input.TURBO_TOKEN = Some(TURBO_TOKEN.into()); + self + } + + fn team_id(mut self, value:&str) -> Self { + self.output.team_id = Some(value.into()); + self + } + + fn team_slug(mut self, value:&str) -> Self { + self.output.team_slug = Some(value.into()); + self + } + + fn token(mut self, value:&str) -> Self { + self.output.token = Some(value.into()); + self + } + } + + #[test] + fn test_all_the_combos() { + let cases:&[TestCase] = &[ + // Get nothing back + // ------------------------------ + TestCase::new().reason("no env vars set"), + TestCase::new().reason("just VERCEL_ARTIFACTS_TOKEN").VERCEL_ARTIFACTS_TOKEN(), + TestCase::new().reason("just TURBO_TOKEN").TURBO_TOKEN(), + // When 3rd Party Wins with all three + // ------------------------------ + TestCase::new() + .reason("we can use all of TURBO_TEAM, TURBO_TEAMID, and TURBO_TOKEN") + .TURBO_TEAM() + .TURBO_TEAMID() + .TURBO_TOKEN() + .team_id(TURBO_TEAMID) + .team_slug(TURBO_TEAM) + .token(TURBO_TOKEN), + TestCase::new() + .reason("if we have a 3rd party trifecta, that wins, even against a Vercel Pair") + .TURBO_TEAM() + .TURBO_TEAMID() + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_OWNER() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(TURBO_TEAMID) + .team_slug(TURBO_TEAM) + .token(TURBO_TOKEN), + TestCase::new() + .reason("a 3rd party trifecta wins against a partial Vercel (just artifacts token)") + .TURBO_TEAM() + .TURBO_TEAMID() + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(TURBO_TEAMID) + .team_slug(TURBO_TEAM) + .token(TURBO_TOKEN), + TestCase::new() + .reason("a 3rd party trifecta wins against a partial Vercel (just artifacts owner)") + .TURBO_TEAM() + .TURBO_TEAMID() + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_OWNER() + .team_id(TURBO_TEAMID) + .team_slug(TURBO_TEAM) + .token(TURBO_TOKEN), + // When 3rd Party Wins with team_slug + // ------------------------------ + TestCase::new() + .reason("golden path for 3rd party, not deployed on Vercel") + .TURBO_TEAM() + .TURBO_TOKEN() + .team_slug(TURBO_TEAM) + .token(TURBO_TOKEN), + TestCase::new() + .reason( + "a TURBO_TEAM+TURBO_TOKEN pair wins against an incomplete Vercel (just \ + artifacts token)", + ) + .TURBO_TEAM() + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_TOKEN() // disregarded + .team_slug(TURBO_TEAM) + .token(TURBO_TOKEN), + TestCase::new() + .reason("golden path for 3rd party, deployed on Vercel") + .TURBO_TEAM() + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_OWNER() // normally this would map to team_id, but not with a complete 3rd party pair + .VERCEL_ARTIFACTS_TOKEN() + .team_slug(TURBO_TEAM) + .token(TURBO_TOKEN), + // When 3rd Party Wins with team_id + // ------------------------------ + TestCase::new() + .reason("if they pass a TURBO_TEAMID and a TURBO_TOKEN, we use them") + .TURBO_TEAMID() + .TURBO_TOKEN() + .team_id(TURBO_TEAMID) + .token(TURBO_TOKEN), + TestCase::new() + .reason("a TURBO_TEAMID+TURBO_TOKEN pair will also win against a Vercel pair") + .TURBO_TEAMID() + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_OWNER() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(TURBO_TEAMID) + .token(TURBO_TOKEN), + TestCase::new() + .reason( + "a TURBO_TEAMID+TURBO_TOKEN pair wins against an incomplete Vercel (just \ + artifacts token)", + ) + .TURBO_TEAMID() + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(TURBO_TEAMID) + .token(TURBO_TOKEN), + // When Vercel Wins + // ------------------------------ + TestCase::new() + .reason("golden path on Vercel zero config") + .VERCEL_ARTIFACTS_OWNER() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(VERCEL_ARTIFACTS_OWNER) + .token(VERCEL_ARTIFACTS_TOKEN), + TestCase::new() + .reason("Vercel wins: disregard just TURBO_TOKEN") + .TURBO_TOKEN() + .VERCEL_ARTIFACTS_OWNER() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(VERCEL_ARTIFACTS_OWNER) + .token(VERCEL_ARTIFACTS_TOKEN), + TestCase::new() + .reason("Vercel wins: TURBO_TEAM can join in the fun if it wants") + .TURBO_TEAM() + .VERCEL_ARTIFACTS_OWNER() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(VERCEL_ARTIFACTS_OWNER) + .team_slug(TURBO_TEAM) + .token(VERCEL_ARTIFACTS_TOKEN), + TestCase::new() + .reason("Vercel wins: disregard just TURBO_TEAMID") + .TURBO_TEAMID() + .VERCEL_ARTIFACTS_OWNER() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(VERCEL_ARTIFACTS_OWNER) + .token(VERCEL_ARTIFACTS_TOKEN), + TestCase::new() + .reason("Vercel wins if TURBO_TOKEN is missing") + .TURBO_TEAM() + .TURBO_TEAMID() + .VERCEL_ARTIFACTS_OWNER() + .VERCEL_ARTIFACTS_TOKEN() + .team_id(VERCEL_ARTIFACTS_OWNER) + .team_slug(TURBO_TEAM) + .token(VERCEL_ARTIFACTS_TOKEN), + // Just get a team_id + // ------------------------------ + TestCase::new() + .reason("just VERCEL_ARTIFACTS_OWNER") + .VERCEL_ARTIFACTS_OWNER() + .team_id(VERCEL_ARTIFACTS_OWNER), + TestCase::new().reason("just TURBO_TEAMID").TURBO_TEAMID().team_id(TURBO_TEAMID), + // Just get a team_slug + // ------------------------------ + TestCase::new().reason("just TURBO_TEAM").TURBO_TEAM().team_slug(TURBO_TEAM), + // just team_slug and team_id + // ------------------------------ + TestCase::new() + .reason("if we just have TURBO_TEAM+TURBO_TEAMID, that's ok") + .TURBO_TEAM() + .TURBO_TEAMID() + .team_slug(TURBO_TEAM) + .team_id(TURBO_TEAMID), + // just set team_id and team_slug + // ------------------------------ + TestCase::new() + .reason("if we just have a TURBO_TEAM and TURBO_TEAMID we can use them both") + .TURBO_TEAM() + .TURBO_TEAMID() + .team_id(TURBO_TEAMID) + .team_slug(TURBO_TEAM), + ]; + + for case in cases { + let mut env:HashMap = HashMap::new(); + + if let Some(value) = &case.input.TURBO_TEAM { + env.insert("turbo_team".into(), value.into()); + } + if let Some(value) = &case.input.TURBO_TEAMID { + env.insert("turbo_teamid".into(), value.into()); + } + if let Some(value) = &case.input.TURBO_TOKEN { + env.insert("turbo_token".into(), value.into()); + } + if let Some(value) = &case.input.VERCEL_ARTIFACTS_OWNER { + env.insert("vercel_artifacts_owner".into(), value.into()); + } + if let Some(value) = &case.input.VERCEL_ARTIFACTS_TOKEN { + env.insert("vercel_artifacts_token".into(), value.into()); + } + + let actual_input = Input::try_from(&env).unwrap(); + assert_eq!(case.input, actual_input); + + let config = OverrideEnvVars::new(&env).unwrap(); + let reason = case.reason; + + assert_eq!(case.output.team_id, config.output.team_id, "{reason}"); + assert_eq!(case.output.team_slug, config.output.team_slug, "{reason}"); + assert_eq!(case.output.token, config.output.token, "{reason}"); + } + } +} diff --git a/crates/turborepo-lib/Source/config/turbo_json.rs b/crates/turborepo-lib/Source/config/turbo_json.rs new file mode 100644 index 0000000000000..2fa543701c809 --- /dev/null +++ b/crates/turborepo-lib/Source/config/turbo_json.rs @@ -0,0 +1,164 @@ +use camino::Utf8PathBuf; +use turbopath::{AbsoluteSystemPath, RelativeUnixPath}; + +use super::{ConfigurationOptions, Error, ResolvedConfigurationOptions}; +use crate::turbo_json::RawTurboJson; + +pub struct TurboJsonReader<'a> { + repo_root:&'a AbsoluteSystemPath, +} + +impl<'a> TurboJsonReader<'a> { + pub fn new(repo_root:&'a AbsoluteSystemPath) -> Self { Self { repo_root } } + + fn turbo_json_to_config_options( + turbo_json:RawTurboJson, + ) -> Result { + let mut opts = if let Some(remote_cache_options) = &turbo_json.remote_cache { + remote_cache_options.into() + } else { + ConfigurationOptions::default() + }; + + let cache_dir = if let Some(cache_dir) = turbo_json.cache_dir { + let cache_dir_str:&str = &cache_dir; + let cache_dir_unix = RelativeUnixPath::new(cache_dir_str).map_err(|_| { + let (span, text) = cache_dir.span_and_text("turbo.json"); + Error::AbsoluteCacheDir { span, text } + })?; + // Convert the relative unix path to an anchored system path + // For unix/macos this is a no-op + let cache_dir_system = cache_dir_unix.to_anchored_system_path_buf(); + Some(Utf8PathBuf::from(cache_dir_system.to_string())) + } else { + None + }; + + // Don't allow token to be set for shared config. + opts.token = None; + opts.spaces_id = turbo_json + .experimental_spaces + .and_then(|spaces| spaces.id) + .map(|spaces_id| spaces_id.into()); + opts.ui = turbo_json.ui; + opts.allow_no_package_manager = turbo_json.allow_no_package_manager; + opts.daemon = turbo_json.daemon.map(|daemon| *daemon.as_inner()); + opts.env_mode = turbo_json.env_mode; + opts.cache_dir = cache_dir; + Ok(opts) + } +} + +impl<'a> ResolvedConfigurationOptions for TurboJsonReader<'a> { + fn get_configuration_options( + &self, + existing_config:&ConfigurationOptions, + ) -> Result { + let turbo_json_path = existing_config.root_turbo_json_path(self.repo_root); + let turbo_json = RawTurboJson::read(self.repo_root, &turbo_json_path).or_else(|e| { + if let Error::Io(e) = &e { + if matches!(e.kind(), std::io::ErrorKind::NotFound) { + return Ok(Default::default()); + } + } + + Err(e) + })?; + Self::turbo_json_to_config_options(turbo_json) + } +} + +#[cfg(test)] +mod test { + use serde_json::json; + use tempfile::tempdir; + + use super::*; + + #[test] + fn test_reads_from_default() { + let tmpdir = tempdir().unwrap(); + let repo_root = AbsoluteSystemPath::new(tmpdir.path().to_str().unwrap()).unwrap(); + + let existing_config = ConfigurationOptions { ..Default::default() }; + repo_root + .join_component("turbo.json") + .create_with_contents( + serde_json::to_string_pretty(&serde_json::json!({ + "daemon": false + })) + .unwrap(), + ) + .unwrap(); + + let reader = TurboJsonReader::new(repo_root); + let config = reader.get_configuration_options(&existing_config).unwrap(); + // Make sure we read the default turbo.json + assert_eq!(config.daemon(), Some(false)); + } + + #[test] + fn test_respects_root_turbo_json_config() { + let tmpdir = tempdir().unwrap(); + let tmpdir_path = AbsoluteSystemPath::new(tmpdir.path().to_str().unwrap()).unwrap(); + let root_turbo_json_path = tmpdir_path.join_component("yolo.json"); + let repo_root = + AbsoluteSystemPath::new(if cfg!(windows) { "C:\\my\\repo" } else { "/my/repo" }) + .unwrap(); + let existing_config = ConfigurationOptions { + root_turbo_json_path:Some(root_turbo_json_path.to_owned()), + ..Default::default() + }; + root_turbo_json_path + .create_with_contents( + serde_json::to_string_pretty(&json!({ + "daemon": false + })) + .unwrap(), + ) + .unwrap(); + + let reader = TurboJsonReader::new(repo_root); + let config = reader.get_configuration_options(&existing_config).unwrap(); + // Make sure we read the correct turbo.json + assert_eq!(config.daemon(), Some(false)); + } + + #[test] + fn test_remote_cache_options() { + let timeout = 100; + let upload_timeout = 200; + let api_url = "localhost:3000"; + let login_url = "localhost:3001"; + let team_slug = "acme-packers"; + let team_id = "id-123"; + let turbo_json = RawTurboJson::parse( + &serde_json::to_string_pretty(&json!({ + "remoteCache": { + "enabled": true, + "timeout": timeout, + "uploadTimeout": upload_timeout, + "apiUrl": api_url, + "loginUrl": login_url, + "teamSlug": team_slug, + "teamId": team_id, + "signature": true, + "preflight": true + } + })) + .unwrap(), + "junk", + ) + .unwrap(); + let config = TurboJsonReader::turbo_json_to_config_options(turbo_json).unwrap(); + assert!(config.enabled()); + assert_eq!(config.timeout(), timeout); + assert_eq!(config.upload_timeout(), upload_timeout); + assert_eq!(config.api_url(), api_url); + assert_eq!(config.login_url(), login_url); + assert_eq!(config.team_slug(), Some(team_slug)); + assert_eq!(config.team_id(), Some(team_id)); + assert!(config.signature()); + assert!(config.preflight()); + } +} diff --git a/crates/turborepo-lib/Source/daemon/bump_timeout.rs b/crates/turborepo-lib/Source/daemon/bump_timeout.rs new file mode 100644 index 0000000000000..1c8766e0d3b4f --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/bump_timeout.rs @@ -0,0 +1,63 @@ +use std::{ + sync::atomic::{AtomicU64, Ordering}, + time::Duration, +}; + +use tokio::time::Instant; + +/// A timeout that can be bumped forward in time by calling reset. +/// +/// Calling reset with a new duration will change the deadline +/// to the current time plus the new duration. It is non-mutating +/// and can be called from multiple threads. +#[derive(Debug)] +pub struct BumpTimeout { + start:Instant, + increment:Duration, + deadline:AtomicU64, +} + +impl BumpTimeout { + #[allow(dead_code)] + pub fn new(increment:Duration) -> Self { + let start = Instant::now(); + let millis = increment.as_millis(); + Self { start, deadline:AtomicU64::new(millis as u64), increment } + } + + pub fn duration(&self) -> Duration { + Duration::from_millis(self.deadline.load(Ordering::Relaxed)) + } + + #[allow(dead_code)] + pub fn deadline(&self) -> Instant { self.start + self.duration() } + + #[allow(dead_code)] + pub fn elapsed(&self) -> Duration { self.start.elapsed() } + + /// Resets the deadline to the current time plus the given duration. + pub fn reset(&self) { + let duration = self.start.elapsed() + self.increment; + self.deadline.store(duration.as_millis() as u64, Ordering::Relaxed); + } + + #[allow(dead_code)] + pub fn as_instant(&self) -> Instant { self.start + self.duration() } + + /// Waits until the deadline is reached, but if the deadline is + /// changed while waiting, it will wait until the new deadline is reached. + #[allow(dead_code)] + pub async fn wait(&self) { + let mut deadline = self.as_instant(); + loop { + tokio::time::sleep_until(deadline).await; + let new_deadline = self.as_instant(); + + if new_deadline > deadline { + deadline = new_deadline; + } else { + break; + } + } + } +} diff --git a/crates/turborepo-lib/Source/daemon/bump_timeout_layer.rs b/crates/turborepo-lib/Source/daemon/bump_timeout_layer.rs new file mode 100644 index 0000000000000..dd5c1306832d0 --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/bump_timeout_layer.rs @@ -0,0 +1,58 @@ +//! timeout_middleware +//! +//! This is middleware for tonic that integrates with bump_timeout to +//! continually reset the timeout when a request is received. + +use std::sync::Arc; + +use tonic::server::NamedService; +use tower::{Layer, Service}; + +use super::bump_timeout::BumpTimeout; + +/// A layer that resets a when a request is received. +pub struct BumpTimeoutLayer(Arc); + +impl BumpTimeoutLayer { + #[allow(dead_code)] + pub fn new(timeout:Arc) -> Self { Self(timeout) } +} + +impl Layer for BumpTimeoutLayer { + type Service = BumpTimeoutService; + + fn layer(&self, inner:S) -> Self::Service { + BumpTimeoutService { inner, timeout:self.0.clone() } + } +} + +#[derive(Clone)] +pub struct BumpTimeoutService { + inner:S, + timeout:Arc, +} + +impl Service for BumpTimeoutService +where + S: Service, +{ + type Error = S::Error; + type Future = S::Future; + type Response = S::Response; + + fn poll_ready( + &mut self, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, req:Request) -> Self::Future { + self.timeout.reset(); + self.inner.call(req) + } +} + +impl NamedService for BumpTimeoutService { + const NAME:&'static str = T::NAME; +} diff --git a/crates/turborepo-lib/Source/daemon/client.rs b/crates/turborepo-lib/Source/daemon/client.rs new file mode 100644 index 0000000000000..28fbe7b348c99 --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/client.rs @@ -0,0 +1,272 @@ +use std::{io, time::Duration}; + +use globwalk::ValidatedGlob; +use miette::Diagnostic; +use thiserror::Error; +use tonic::{Code, IntoRequest, Status}; +use tracing::info; +use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPath}; + +use super::{ + Paths, + connector::{DaemonConnector, DaemonConnectorError}, + endpoint::SocketOpenError, + proto::{DiscoverPackagesResponse, GetFileHashesResponse}, +}; +use crate::{ + daemon::{proto, proto::PackageChangeEvent}, + globwatcher::HashGlobSetupError, +}; + +#[derive(Debug, Clone)] +pub struct DaemonClient { + client:proto::turbod_client::TurbodClient, + connect_settings:T, +} + +impl DaemonClient<()> { + pub fn new(client:proto::turbod_client::TurbodClient) -> Self { + Self { client, connect_settings:() } + } + + /// Augment the client with the connect settings, allowing it to be + /// restarted. + pub fn with_connect_settings( + self, + connect_settings:DaemonConnector, + ) -> DaemonClient { + DaemonClient { client:self.client, connect_settings } + } +} + +impl DaemonClient { + /// Interrogate the server for its version. + #[tracing::instrument(skip(self))] + pub(super) async fn handshake(&mut self) -> Result<(), DaemonError> { + let _ret = self + .client + .hello(proto::HelloRequest { + version:proto::VERSION.to_string(), + // minor version means that we need the daemon server to have at least the + // same features as us, but it can have more. it is unlikely that we will + // ever want to change the version range but we can tune it if, for example, + // we need to lock to a specific minor version. + supported_version_range:proto::VersionRange::Minor.into(), + // todo(arlyon): add session id + ..Default::default() + }) + .await?; + + Ok(()) + } + + /// Stops the daemon and closes the connection, returning + /// the connection settings that were used to connect. + pub async fn stop(mut self) -> Result { + info!("Stopping daemon"); + self.client.shutdown(proto::ShutdownRequest {}).await?; + Ok(self.connect_settings) + } + + pub async fn get_changed_outputs( + &mut self, + hash:String, + output_globs:&[ValidatedGlob], + ) -> Result, DaemonError> { + let output_globs = output_globs + .iter() + .map(|validated_glob| validated_glob.as_str().to_string()) + .collect(); + Ok(self + .client + .get_changed_outputs(proto::GetChangedOutputsRequest { hash, output_globs }) + .await? + .into_inner() + .changed_output_globs) + } + + pub async fn notify_outputs_written( + &mut self, + hash:String, + output_globs:&[ValidatedGlob], + output_exclusion_globs:&[ValidatedGlob], + time_saved:u64, + ) -> Result<(), DaemonError> { + let output_globs = output_globs + .iter() + .map(|validated_glob| validated_glob.as_str().to_string()) + .collect(); + let output_exclusion_globs = output_exclusion_globs + .iter() + .map(|validated_glob| validated_glob.as_str().to_string()) + .collect(); + self.client + .notify_outputs_written(proto::NotifyOutputsWrittenRequest { + hash, + output_globs, + output_exclusion_globs, + time_saved, + }) + .await?; + + Ok(()) + } + + /// Get the status of the daemon. + pub async fn status(&mut self) -> Result { + self.client + .status(proto::StatusRequest {}) + .await? + .into_inner() + .daemon_status + .ok_or(DaemonError::MalformedResponse) + } + + pub async fn discover_packages(&mut self) -> Result { + let req = proto::DiscoverPackagesRequest {}; + let mut req = req.into_request(); + req.set_timeout(Duration::from_millis(30)); + let response = self.client.discover_packages(req).await?.into_inner(); + + Ok(response) + } + + pub async fn discover_packages_blocking( + &mut self, + ) -> Result { + let response = self + .client + .discover_packages_blocking(proto::DiscoverPackagesRequest {}) + .await? + .into_inner(); + + Ok(response) + } + + pub async fn package_changes( + &mut self, + ) -> Result, DaemonError> { + let response = + self.client.package_changes(proto::PackageChangesRequest {}).await?.into_inner(); + Ok(response) + } + + pub async fn get_file_hashes( + &mut self, + package_path:&AnchoredSystemPath, + inputs:&[String], + ) -> Result { + let response = self + .client + .get_file_hashes(proto::GetFileHashesRequest { + package_path:package_path.to_string(), + input_globs:inputs.to_vec(), + }) + .await? + .into_inner(); + Ok(response) + } +} + +impl DaemonClient { + /// Stops the daemon, closes the connection, and opens a new connection. + pub async fn restart(self) -> Result, DaemonError> { + self.stop().await?.connect().await.map_err(Into::into) + } + + pub fn paths(&self) -> &Paths { &self.connect_settings.paths } +} + +fn format_repo_relative_glob(glob:&str) -> String { + #[cfg(windows)] + let glob = { + let glob = if let Some(idx) = glob.find(':') { &glob[..idx] } else { glob }; + glob.replace("\\", "/") + }; + glob.replace(':', "\\:") +} + +#[derive(Error, Debug, Diagnostic)] +pub enum DaemonError { + /// The server was connected but is now unavailable. + #[error("server is unavailable: {0}")] + Unavailable(String), + #[error("error opening socket: {0}")] + SocketOpen(#[from] SocketOpenError), + /// The server is running a different version of turborepo. + #[error("version mismatch: {0}")] + #[diagnostic(help("try restarting the daemon with `turbo daemon restart`."))] + VersionMismatch(String), + /// There is an issue with the underlying grpc transport. + #[error("bad grpc transport: {0}")] + GrpcTransport(#[from] tonic::transport::Error), + /// The daemon returned an unexpected status code. + #[error("bad grpc status code: {0}")] + GrpcFailure(tonic::Code), + /// The daemon returned a malformed response. + #[error("malformed response")] + MalformedResponse, + /// There was an issue connecting to the daemon. + #[error("unable to connect: {0}")] + DaemonConnect(#[from] DaemonConnectorError), + /// The timeout specified was invalid. + #[error("invalid timeout specified ({0})")] + #[allow(dead_code)] + InvalidTimeout(String), + /// The server is unable to start file watching. + #[error("unable to start file watching")] + SetupFileWatching(#[from] HashGlobSetupError), + + #[error("unable to display output: {0}")] + DisplayError(#[from] serde_json::Error), + + #[error("unable to construct log file name: {0}")] + InvalidLogFile(#[from] time::Error), + + #[error("unable to complete daemon clean")] + CleanFailed, + + #[error("failed to setup cookie dir {1}: {0}")] + CookieDir(io::Error, AbsoluteSystemPathBuf), + + #[error("failed to determine package manager: {0}")] + PackageManager(#[from] turborepo_repository::package_manager::Error), + + #[error("`tail` is not installed. Please install it to use this feature.")] + TailNotInstalled, + + #[error("could not find log file")] + LogFileNotFound, +} + +impl From for DaemonError { + fn from(status:Status) -> DaemonError { + match status.code() { + Code::FailedPrecondition => DaemonError::VersionMismatch(status.message().to_owned()), + Code::Unimplemented => { + DaemonError::VersionMismatch("rpc not implemented on daemon".to_string()) + }, + Code::Unavailable => DaemonError::Unavailable(status.message().to_string()), + c => DaemonError::GrpcFailure(c), + } + } +} + +#[cfg(test)] +mod test { + use std::path::MAIN_SEPARATOR_STR; + + use crate::daemon::client::format_repo_relative_glob; + + #[test] + fn test_format_repo_relative_glob() { + let raw_glob = ["some", ".turbo", "turbo-foo:bar.log"].join(MAIN_SEPARATOR_STR); + #[cfg(windows)] + let expected = "some/.turbo/turbo-foo"; + #[cfg(not(windows))] + let expected = "some/.turbo/turbo-foo\\:bar.log"; + + let result = format_repo_relative_glob(&raw_glob); + assert_eq!(result, expected); + } +} diff --git a/crates/turborepo-lib/Source/daemon/connector.rs b/crates/turborepo-lib/Source/daemon/connector.rs new file mode 100644 index 0000000000000..8c4562ac6d1d3 --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/connector.rs @@ -0,0 +1,672 @@ +use std::{ + ffi::OsStr, + process::Stdio, + sync::Arc, + time::{Duration, Instant}, +}; + +use command_group::AsyncCommandGroup; +use notify::{Config, Event, EventKind, Watcher}; +use pidlock::PidFileError; +use sysinfo::{Pid, ProcessExt, ProcessRefreshKind, RefreshKind, SystemExt}; +use thiserror::Error; +use tokio::{sync::mpsc, time::timeout}; +use tonic::transport::Endpoint; +use tracing::debug; +use turbopath::AbsoluteSystemPath; + +use super::{DaemonClient, Paths, proto::turbod_client::TurbodClient}; +use crate::daemon::DaemonError; + +#[derive(Error, Debug)] +pub enum DaemonConnectorError { + /// There was a problem when forking to start the daemon. + #[error("unable to fork")] + Fork(ForkError), + /// There was a problem reading the pid file. + #[error("the process in the pid is not the daemon ({0}) and still running ({1})")] + WrongPidProcess(Pid, Pid), + /// The daemon is not running and will not be started. + #[error("daemon is not running")] + NotRunning, + /// There was an issue connecting to the socket. + #[error("unable to connect to socket: {0}")] + Socket(#[from] tonic::transport::Error), + /// There was an issue performing the handshake. + #[error("unable to make handshake: {0}")] + Handshake(#[from] Box), + /// Waiting for the socket timed out. + #[error("timeout while watching directory: {0}")] + Timeout(#[from] tokio::time::error::Elapsed), + /// There was an issue in the file watcher. + #[error("unable to watch directory: {0}")] + Watcher(#[from] FileWaitError), + + #[error("unable to connect to daemon after {0} retries")] + ConnectRetriesExceeded(usize), + + #[error("unable to use pid file: {0}")] + PidFile(#[from] PidFileError), +} + +#[derive(Error, Debug)] +pub enum ForkError { + #[error("daemon exited before we could connect")] + Exited, + #[error("unable to spawn daemon: {0}")] + Spawn(#[from] std::io::Error), +} + +#[derive(Debug, Clone)] +pub struct DaemonConnector { + /// Whether the connector is allowed to start a daemon if it is not already + /// running. + pub can_start_server:bool, + /// Whether the connector is allowed to kill a running daemon (for example, + /// in the event of a version mismatch). + pub can_kill_server:bool, + pub paths:Paths, +} + +impl DaemonConnector { + const CONNECT_RETRY_MAX:usize = 3; + const CONNECT_TIMEOUT:Duration = Duration::from_secs(1); + const SHUTDOWN_TIMEOUT:Duration = Duration::from_secs(1); + const SOCKET_ERROR_WAIT:Duration = Duration::from_millis(50); + const SOCKET_TIMEOUT:Duration = Duration::from_secs(1); + + pub fn new(can_start_server:bool, can_kill_server:bool, repo_root:&AbsoluteSystemPath) -> Self { + let paths = Paths::from_repo_root(repo_root); + Self { can_start_server, can_kill_server, paths } + } + + /// Attempt, with retries, to: + /// 1. find (or start) the daemon process + /// 2. locate its unix socket + /// 3. connect to the socket + /// 4. send the 'hello' message, negotiating versions + /// + /// A new server will be spawned (and the old one killed) if + /// dont_kill is unset and one of these cases is hit: + /// 1. the versions do not match + /// 2. the server is not running + /// 3. the server is unresponsive + #[tracing::instrument(skip(self))] + pub async fn connect(self) -> Result, DaemonConnectorError> { + let time = Instant::now(); + for _ in 0..Self::CONNECT_RETRY_MAX { + let pid = self.get_or_start_daemon().await?; + debug!("got daemon with pid: {}", pid); + + let conn = match self.get_connection(self.paths.sock_file.clone()).await { + Err(DaemonConnectorError::Watcher(_)) => continue, + Err(DaemonConnectorError::Socket(e)) => { + // assume the server is not yet ready + debug!("socket error: {}", e); + tokio::time::sleep(DaemonConnector::SOCKET_ERROR_WAIT).await; + continue; + }, + rest => rest?, + }; + + let mut client = DaemonClient::new(conn); + + match client.handshake().await { + Ok(_) => { + return { + debug!("connected in {}µs", time.elapsed().as_micros()); + Ok(client.with_connect_settings(self)) + }; + }, + Err(DaemonError::VersionMismatch(_)) if self.can_kill_server => { + self.kill_live_server(client, pid).await? + }, + Err(DaemonError::Unavailable(_)) => self.kill_dead_server(pid).await?, + Err(e) => return Err(DaemonConnectorError::Handshake(Box::new(e))), + }; + } + + Err(DaemonConnectorError::ConnectRetriesExceeded(Self::CONNECT_RETRY_MAX)) + } + + /// Gets the PID of the daemon process. + /// + /// If a daemon is not running, it starts one. + async fn get_or_start_daemon(&self) -> Result { + debug!("looking for pid in lockfile: {:?}", self.paths.pid_file); + + let pidfile = self.pid_lock(); + + match pidfile.get_owner()? { + Some(pid) => { + debug!("found pid: {}", pid); + Ok(sysinfo::Pid::from(pid as usize)) + }, + None if self.can_start_server => { + debug!("no pid found, starting daemon"); + Self::start_daemon().await + }, + None => Err(DaemonConnectorError::NotRunning), + } + } + + /// Starts the daemon process, returning its PID. + async fn start_daemon() -> Result { + let binary_path = + std::env::current_exe().map_err(|e| DaemonConnectorError::Fork(e.into()))?; + // this creates a new process group for the given command + // in a cross platform way, directing all output to /dev/null + let mut group = tokio::process::Command::new(binary_path) + .arg("--skip-infer") + .arg("daemon") + .stderr(Stdio::null()) + .stdout(Stdio::null()) + .group() + .kill_on_drop(false) + .spawn() + .map_err(|e| DaemonConnectorError::Fork(e.into()))?; + + group + .inner() + .id() + .map(|id| sysinfo::Pid::from(id as usize)) + .ok_or(DaemonConnectorError::Fork(ForkError::Exited)) + } + + /// Gets a connection to given path + /// + /// On Windows the socket file cannot be interacted with via any filesystem + /// apis, due to this we need to just naively attempt to connect on that + /// platform and retry in case of error. + #[tracing::instrument(skip(self))] + async fn get_connection( + &self, + path:turbopath::AbsoluteSystemPathBuf, + ) -> Result, DaemonConnectorError> { + // windows doesn't treat sockets as files, so don't attempt to wait + #[cfg(not(target_os = "windows"))] + self.wait_for_socket().await?; + + debug!("connecting to socket: {}", path); + let path = Arc::new(path); + + #[cfg(not(target_os = "windows"))] + let make_service = move |_| { + // we clone the reference counter here and move it into the async closure + let path = path.clone(); + async move { tokio::net::UnixStream::connect(path.as_path()).await } + }; + + #[cfg(target_os = "windows")] + let make_service = move |_| { + let path = path.clone(); + async move { win(path) } + }; + + // note, this endpoint is just a placeholder. the actual path is passed in via + // make_service + Endpoint::try_from("http://[::]:50051") + .expect("this is a valid uri") + .timeout(Self::CONNECT_TIMEOUT) + .connect_with_connector(tower::service_fn(make_service)) + .await + .map(TurbodClient::new) + .map_err(DaemonConnectorError::Socket) + } + + /// Kills a currently active server by shutting it down and waiting for it + /// to exit. + #[tracing::instrument(skip(self, client))] + async fn kill_live_server( + &self, + client:DaemonClient<()>, + pid:sysinfo::Pid, + ) -> Result<(), DaemonConnectorError> { + if client.stop().await.is_err() { + self.kill_dead_server(pid).await?; + } + + match timeout( + Self::SHUTDOWN_TIMEOUT, + wait_for_file(&self.paths.pid_file, WaitAction::Deleted), + ) + .await? + { + Ok(_) => Ok(()), + Err(_) => self.kill_dead_server(pid).await, + } + } + + /// Kills a server that is not responding. + #[tracing::instrument(skip(self))] + async fn kill_dead_server(&self, pid:sysinfo::Pid) -> Result<(), DaemonConnectorError> { + let lock = self.pid_lock(); + + let system = sysinfo::System::new_with_specifics( + RefreshKind::new().with_processes(ProcessRefreshKind::new()), + ); + + let owner = lock.get_owner()?.and_then(|p| system.process(sysinfo::Pid::from(p as usize))); + + // if the pidfile is owned by the same pid as the one we found, kill it + match owner { + Some(owner) if pid == owner.pid() => { + debug!("killing dead server with pid: {}", pid); + owner.kill(); + + Ok(()) + }, + Some(owner) => { + debug!("pidfile is owned by another process, ignoring"); + Err(DaemonConnectorError::WrongPidProcess(pid, owner.pid())) + }, + // pidfile has no owner and has been cleaned up so we're ok + None => Ok(()), + } + } + + #[tracing::instrument(skip(self))] + async fn wait_for_socket(&self) -> Result<(), DaemonConnectorError> { + // Note that we don't care if this is our daemon + // or not. We started a process, but someone else could beat + // use to listening. That's fine, we'll check the version + // later. However, we need to ensure that _some_ pid file + // exists to protect against stale .sock files + timeout(Self::SOCKET_TIMEOUT, wait_for_file(&self.paths.pid_file, WaitAction::Exists)) + .await??; + timeout(Self::SOCKET_TIMEOUT, wait_for_file(&self.paths.sock_file, WaitAction::Exists)) + .await? + .map_err(Into::into) + } + + fn pid_lock(&self) -> pidlock::Pidlock { + pidlock::Pidlock::new(self.paths.pid_file.clone().into()) + } +} + +#[cfg(target_os = "windows")] +fn win( + path:Arc, +) -> Result { + use tokio_util::compat::FuturesAsyncReadCompatExt; + uds_windows::UnixStream::connect(&*path) + .and_then(async_io::Async::new) + .map(FuturesAsyncReadCompatExt::compat) +} + +#[derive(Debug, Error)] +pub enum FileWaitError { + #[error("failed to register notifier {0}")] + Notify(#[from] notify::Error), + #[error("failed to wait for event {0}")] + Io(#[from] std::io::Error), + #[error("invalid path {0}")] + InvalidPath(turbopath::AbsoluteSystemPathBuf), +} + +/// Waits for a file at some path on the filesystem to be created or deleted. +/// +/// It does this by watching the parent directory of the path, and waiting for +/// events on that path. +#[tracing::instrument] +async fn wait_for_file( + path:&turbopath::AbsoluteSystemPathBuf, + action:WaitAction, +) -> Result<(), FileWaitError> { + let parent = path.parent().ok_or_else(|| FileWaitError::InvalidPath(path.to_owned()))?; + + let file_name = path + .file_name() + .map(|f| f.to_owned()) + .ok_or_else(|| FileWaitError::InvalidPath(path.to_owned()))?; + + let (tx, mut rx) = mpsc::channel(1); + + let mut watcher = notify::PollWatcher::new( + move |res| { + match (res, action) { + ( + Ok(Event { + // for some reason, socket _creation_ is not detected, however, + // we can assume that any event except delete implies readiness + kind: EventKind::Access(_) | EventKind::Create(_) | EventKind::Modify(_), + paths, + .. + }), + WaitAction::Exists, + ) + | (Ok(Event { kind: EventKind::Remove(_), paths, .. }), WaitAction::Deleted) => { + if paths.iter().any(|p| { + p.file_name().map(|f| OsStr::new(&file_name).eq(f)).unwrap_or_default() + }) { + futures::executor::block_on(async { + // if the receiver is dropped, it is because the future has + // been cancelled, so we don't need to do anything + tx.send(()).await.ok(); + }) + } + }, + _ => {}, + } + }, + Config::default().with_poll_interval(Duration::from_millis(10)), + )?; + + debug!("creating {:?}", parent); + std::fs::create_dir_all(parent.as_path())?; + + debug!("watching {:?}", parent); + watcher.watch(parent.as_std_path(), notify::RecursiveMode::NonRecursive)?; + + match (action, path.exists()) { + (WaitAction::Exists, false) => {}, + (WaitAction::Deleted, true) => {}, + _ => return Ok(()), + }; + + // this can only fail if the channel has been closed, which will + // always happen either after this call ends, or after this future + // is cancelled + rx.recv().await.expect("will receive a message"); + + Ok(()) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum WaitAction { + /// Wait for the file to exist. + Exists, + /// Wait for the file to be deleted. + Deleted, +} + +#[cfg(test)] +mod test { + use std::assert_matches::assert_matches; + + use tokio::{ + select, + sync::{Mutex, oneshot::Sender}, + }; + use tokio_stream::wrappers::ReceiverStream; + use tonic::{Request, Response, Status}; + use tower::ServiceBuilder; + use tracing::info; + use turbopath::AbsoluteSystemPathBuf; + + use super::*; + use crate::daemon::{ + default_timeout_layer::DefaultTimeoutLayer, + proto::{self, PackageChangesRequest}, + }; + + #[cfg(not(target_os = "windows"))] + const NODE_EXE:&str = "node"; + #[cfg(target_os = "windows")] + const NODE_EXE:&str = "node.exe"; + + #[tokio::test] + async fn handles_invalid_pid() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + + let connector = DaemonConnector::new(false, false, &repo_root); + connector.paths.pid_file.ensure_dir().unwrap(); + connector.paths.pid_file.create_with_contents("not a pid").unwrap(); + + assert_matches!( + connector.get_or_start_daemon().await, + Err(DaemonConnectorError::PidFile(PidFileError::Invalid { .. })) + ); + } + + #[tokio::test] + async fn handles_missing_server_connect() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let connector = DaemonConnector::new(false, false, &repo_root); + + assert_matches!(connector.connect().await, Err(DaemonConnectorError::NotRunning)); + } + + #[tokio::test] + async fn handles_kill_dead_server_missing_pid() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let connector = DaemonConnector::new(false, false, &repo_root); + + assert_matches!(connector.kill_dead_server(Pid::from(usize::MAX)).await, Ok(())); + } + + #[tokio::test] + async fn handles_kill_dead_server_missing_process() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let connector = DaemonConnector::new(false, false, &repo_root); + + connector.paths.pid_file.ensure_dir().unwrap(); + connector.paths.pid_file.create_with_contents(i32::MAX.to_string()).unwrap(); + connector.paths.sock_file.ensure_dir().unwrap(); + connector.paths.sock_file.create_with_contents("").unwrap(); + + assert_matches!(connector.kill_dead_server(Pid::from(usize::MAX)).await, Ok(())); + + assert!( + !connector.paths.pid_file.exists(), + "pid file should be cleaned up when getting the owner of a stale pid" + ); + } + + #[tokio::test] + async fn handles_kill_dead_server_wrong_process() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let connector = DaemonConnector::new(false, false, &repo_root); + + let proc = tokio::process::Command::new(NODE_EXE) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .arg("-e") + .arg("setInterval(() => {}, 1000)") + .spawn() + .unwrap(); + + connector.paths.pid_file.ensure_dir().unwrap(); + connector + .paths + .pid_file + .create_with_contents(proc.id().unwrap().to_string()) + .unwrap(); + connector.paths.sock_file.ensure_dir().unwrap(); + connector.paths.sock_file.create_with_contents("").unwrap(); + + let kill_pid = Pid::from(usize::MAX); + let proc_id = Pid::from(proc.id().unwrap() as usize); + + assert_matches!( + connector.kill_dead_server(kill_pid).await, + Err(DaemonConnectorError::WrongPidProcess(daemon, running)) if daemon == kill_pid && running == proc_id + ); + + assert!(connector.paths.pid_file.exists(), "pid file should still exist"); + } + + #[tokio::test] + async fn handles_kill_dead_server() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let connector = DaemonConnector::new(false, true, &repo_root); + + let proc = tokio::process::Command::new(NODE_EXE) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .arg("-e") + .arg("setInterval(() => {}, 1000)") + .spawn() + .unwrap(); + + connector.paths.pid_file.ensure_dir().unwrap(); + connector + .paths + .pid_file + .create_with_contents(proc.id().unwrap().to_string()) + .unwrap(); + connector.paths.sock_file.ensure_dir().unwrap(); + connector.paths.sock_file.create_with_contents("").unwrap(); + + assert_matches!( + connector.kill_dead_server(Pid::from(proc.id().unwrap() as usize)).await, + Ok(()) + ); + + assert!(connector.paths.pid_file.exists(), "pid file should still exist"); + } + + struct DummyServer { + shutdown:Mutex>>, + } + + #[tonic::async_trait] + impl proto::turbod_server::Turbod for DummyServer { + type PackageChangesStream = ReceiverStream>; + + async fn shutdown( + &self, + req:tonic::Request, + ) -> tonic::Result> { + info!("shutdown request: {:?}", req); + self.shutdown.lock().await.take().unwrap().send(true).unwrap(); + Ok(tonic::Response::new(proto::ShutdownResponse {})) + } + + async fn hello( + &self, + request:tonic::Request, + ) -> tonic::Result> { + let client_version = request.into_inner().version; + Err(tonic::Status::failed_precondition(format!( + "version mismatch. Client {} Server test-version", + client_version + ))) + } + + async fn status( + &self, + _req:tonic::Request, + ) -> tonic::Result> { + unimplemented!() + } + + async fn notify_outputs_written( + &self, + _req:tonic::Request, + ) -> tonic::Result> { + unimplemented!() + } + + async fn get_changed_outputs( + &self, + _req:tonic::Request, + ) -> tonic::Result> { + unimplemented!() + } + + async fn discover_packages( + &self, + _req:tonic::Request, + ) -> Result, tonic::Status> { + unimplemented!() + } + + async fn discover_packages_blocking( + &self, + _req:tonic::Request, + ) -> Result, tonic::Status> { + unimplemented!() + } + + async fn package_changes( + &self, + _req:Request, + ) -> Result, Status> { + unimplemented!() + } + + async fn get_file_hashes( + &self, + _req:tonic::Request, + ) -> Result, tonic::Status> { + unimplemented!() + } + } + + #[tokio::test] + async fn handles_kill_live_server() { + let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel(); + + let (tx, mut rx) = tokio::sync::mpsc::channel(1); + + // set up the server + let stream = async_stream::stream! { + while let Some(item) = rx.recv().await { + yield item; + } + }; + + let service = ServiceBuilder::new().layer(DefaultTimeoutLayer).service( + proto::turbod_server::TurbodServer::new(DummyServer { + shutdown:Mutex::new(Some(shutdown_tx)), + }), + ); + + let server_fut = tonic::transport::Server::builder() + .add_service(service) + .serve_with_incoming(stream); + + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let connector = DaemonConnector::new(false, false, &repo_root); + + let mut client = Endpoint::try_from("http://[::]:50051") + .expect("this is a valid uri") + .connect_with_connector(tower::service_fn(move |_| { + // when a connection is made, create a duplex stream and send it to the server + let tx = tx.clone(); + async move { + let (client, server) = tokio::io::duplex(1024); + let server:Result<_, anyhow::Error> = Ok(server); + let client:Result<_, anyhow::Error> = Ok(client); + tx.send(server).await.unwrap(); + client + } + })) + .await + .map(TurbodClient::new) + .unwrap(); + + // spawn the future for the server so that it responds to + // the hello request + let server_fut = tokio::spawn(server_fut); + + let hello_resp:DaemonError = client + .hello(proto::HelloRequest { + version:"version-mismatch".to_string(), + ..Default::default() + }) + .await + .unwrap_err() + .into(); + assert_matches!(hello_resp, DaemonError::VersionMismatch(_)); + let client = DaemonClient::new(client); + + let shutdown_fut = connector.kill_live_server(client, Pid::from(1000)); + + // drive the futures to completion + select! { + _ = shutdown_fut => {} + _ = server_fut => panic!("server should not have shut down first"), + } + + assert!(shutdown_rx.await.is_ok(), "shutdown should have been received") + } +} diff --git a/crates/turborepo-lib/Source/daemon/default_timeout_layer.rs b/crates/turborepo-lib/Source/daemon/default_timeout_layer.rs new file mode 100644 index 0000000000000..a62340ec0da2b --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/default_timeout_layer.rs @@ -0,0 +1,142 @@ +//! default timeout layer +//! +//! This module provides some basic middleware that aims to +//! improve the flexibility of the daemon server by doing +//! two things: +//! +//! a) remove the server-wide timeout of 100ms in favour of +//! a less aggressive 30s. the way tonic works is the +//! lowest timeout (server vs request-specific) is always +//! used meaning clients' timeout requests were ignored +//! if set to >100ms +//! b) add a middleware to reinstate the timeout, if the +//! client does not specify it, defaulting to 100ms for +//! 'non-blocking' calls (requests in the hot path for +//! a run of turbo), and falling back to the server +//! limit for blocking ones (useful in cases like the +//! LSP) +//! +//! With this in place, it means that clients can specify +//! a timeout that it wants (as long as it is less than 30s), +//! and the server has sane defaults + +use std::time::Duration; + +use tonic::{codegen::http::Request, server::NamedService, transport::Body}; +use tower::{Layer, Service}; + +#[derive(Clone, Debug)] +pub struct DefaultTimeoutService { + inner:S, +} + +impl Service> for DefaultTimeoutService +where + S: Service>, +{ + type Error = S::Error; + type Future = S::Future; + type Response = S::Response; + + fn poll_ready( + &mut self, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, mut req:Request) -> Self::Future { + if !req.uri().path().ends_with("Blocking") { + req.headers_mut().entry("grpc-timeout").or_insert_with(move || { + let dur = Duration::from_millis(100); + tonic::codegen::http::HeaderValue::from_str(&format!("{}u", dur.as_micros())) + .expect("numbers are always valid ascii") + }); + }; + + self.inner.call(req) + } +} + +/// Provides a middleware that sets a default timeout for +/// non-blocking calls. See the module documentation for +/// more information. +#[derive(Clone, Debug)] +pub struct DefaultTimeoutLayer; + +impl Layer for DefaultTimeoutLayer { + type Service = DefaultTimeoutService; + + fn layer(&self, inner:S) -> Self::Service { DefaultTimeoutService { inner } } +} + +impl NamedService for DefaultTimeoutService { + const NAME:&'static str = T::NAME; +} + +#[cfg(test)] +mod test { + use std::{ + str::FromStr, + sync::{Arc, Mutex}, + }; + + use test_case::test_case; + use tonic::codegen::http::HeaderValue; + + use super::*; + + #[test_case("/ExampleBlocking", None, None ; "no default for blocking calls")] + #[test_case("/Example", None, Some("100000u") ; "default for non-blocking calls")] + #[test_case("/Example", Some("200u"), Some("200u") ; "respect client preference")] + #[tokio::test] + async fn overrides_timeout_for_non_blocking( + path:&str, + timeout:Option<&str>, + expected:Option<&str>, + ) { + #[derive(Clone, Debug)] + struct MockService(Arc>>); + + impl Service> for MockService { + type Error = (); + type Response = (); + + type Future = impl std::future::Future>; + + fn poll_ready( + &mut self, + _cx:&mut std::task::Context<'_>, + ) -> std::task::Poll> { + std::task::Poll::Ready(Ok(())) + } + + fn call(&mut self, req:Request) -> Self::Future { + // get the content of the header + let header = self.0.clone(); + async move { + let mut header = header.lock().unwrap(); + *header = + req.headers().get("grpc-timeout").map(|h| h.to_str().unwrap().to_string()); + Ok(()) + } + } + } + + let inner = MockService(Arc::new(Mutex::new(None))); + let mut svc = DefaultTimeoutLayer.layer(inner.clone()); + let mut req = Request::new(Body::empty()); + let uri = req.uri_mut(); + *uri = tonic::codegen::http::Uri::from_str(path).unwrap(); + if let Some(timeout) = timeout { + req.headers_mut() + .insert("grpc-timeout", HeaderValue::from_str(timeout).unwrap()); + } + + svc.call(req).await.unwrap(); + + let header = inner.0.lock().unwrap(); + + assert_eq!(header.as_deref(), expected); + } +} diff --git a/crates/turborepo-lib/Source/daemon/endpoint.rs b/crates/turborepo-lib/Source/daemon/endpoint.rs new file mode 100644 index 0000000000000..cf53756e92145 --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/endpoint.rs @@ -0,0 +1,243 @@ +use std::sync::{Arc, atomic::AtomicBool}; +#[cfg(windows)] +use std::{io::ErrorKind, sync::atomic::Ordering, time::Duration}; + +use futures::Stream; +use tokio::io::{AsyncRead, AsyncWrite}; +use tonic::transport::server::Connected; +use tracing::{debug, trace}; +use turbopath::AbsoluteSystemPath; + +#[derive(thiserror::Error, Debug)] +pub enum SocketOpenError { + /// Returned when there is an IO error opening the socket, + /// such as the path being too long, or the path being + /// invalid. + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + #[error("pidlock error: {0}")] + LockError(#[from] pidlock::PidlockError), +} + +#[cfg(windows)] +const WINDOWS_POLL_DURATION:Duration = Duration::from_millis(1); + +/// Gets a stream of incoming connections from a Unix socket. +/// On windows, this will use the `uds_windows` crate, and +/// poll the result in another thread. +/// +/// note: the running param is used by the windows +/// code path to shut down the non-blocking polling +#[tracing::instrument] +pub async fn listen_socket( + pid_path:&AbsoluteSystemPath, + sock_path:&AbsoluteSystemPath, + #[allow(unused)] running:Arc, +) -> Result< + ( + pidlock::Pidlock, + impl Stream>, + ), + SocketOpenError, +> { + let mut lock = pidlock::Pidlock::new(pid_path.as_std_path().to_owned()); + + trace!("acquiring pidlock"); + // this will fail if the pid is already owned + // todo: make sure we fall back and handle this + lock.acquire()?; + sock_path.remove_file().ok(); + + debug!("pidlock acquired at {}", pid_path); + debug!("listening on socket at {}", sock_path); + + #[cfg(unix)] + { + Ok(( + lock, + tokio_stream::wrappers::UnixListenerStream::new(tokio::net::UnixListener::bind( + sock_path, + )?), + )) + } + + #[cfg(windows)] + { + use tokio_util::compat::FuturesAsyncReadCompatExt; + + let listener = Arc::new(uds_windows::UnixListener::bind(sock_path)?); + listener.set_nonblocking(true)?; + + let stream = futures::stream::unfold(listener, move |listener| { + let task_running = running.clone(); + async move { + // ensure the underlying thread is aborted on drop + let task_listener = listener.clone(); + let task = tokio::task::spawn_blocking(move || { + loop { + break match task_listener.accept() { + Err(e) if e.kind() == ErrorKind::WouldBlock => { + std::thread::sleep(WINDOWS_POLL_DURATION); + if !task_running.load(Ordering::SeqCst) { + None + } else { + continue; + } + }, + res => Some(res), + }; + } + }); + + let result = task + .await + .expect("no panic")? + .map(|(stream, _)| stream) + .and_then(async_io::Async::new) + .map(FuturesAsyncReadCompatExt::compat) + .map(UdsWindowsStream); + + Some((result, listener)) + } + }); + + Ok((lock, stream)) + } +} + +/// An adaptor over uds_windows that implements AsyncRead and AsyncWrite. +/// +/// It utilizes structural pinning to forward async read and write +/// implementations onto the inner type. +#[cfg(windows)] +struct UdsWindowsStream(T); + +#[cfg(windows)] +impl UdsWindowsStream { + /// Project the (pinned) uds windows stream to get the inner (pinned) type + /// + /// SAFETY + /// + /// structural pinning requires a few invariants to hold which can be seen + /// here https://doc.rust-lang.org/std/pin/#pinning-is-structural-for-field + /// + /// in short: + /// - we cannot implement Unpin for UdsWindowsStream + /// - we cannot use repr packed + /// - we cannot move in the drop impl (the default impl doesn't) + /// - we must uphold the rust 'drop guarantee' + /// - we cannot offer any api to move data out of the pinned value (such as + /// Option::take) + fn project(self: std::pin::Pin<&mut Self>) -> std::pin::Pin<&mut T> { + unsafe { self.map_unchecked_mut(|s| &mut s.0) } + } +} + +#[cfg(windows)] +impl AsyncRead for UdsWindowsStream { + fn poll_read( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + buf:&mut tokio::io::ReadBuf<'_>, + ) -> std::task::Poll> { + self.project().poll_read(cx, buf) + } +} + +#[cfg(windows)] +impl AsyncWrite for UdsWindowsStream { + fn poll_write( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + buf:&[u8], + ) -> std::task::Poll> { + self.project().poll_write(cx, buf) + } + + fn poll_flush( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.project().poll_flush(cx) + } + + fn poll_shutdown( + self: std::pin::Pin<&mut Self>, + cx:&mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.project().poll_shutdown(cx) + } +} + +#[cfg(windows)] +impl Connected for UdsWindowsStream { + type ConnectInfo = (); + + fn connect_info(&self) -> Self::ConnectInfo {} +} + +#[cfg(test)] +mod test { + use std::{ + assert_matches::assert_matches, + process::Command, + sync::{Arc, atomic::AtomicBool}, + }; + + use pidlock::PidlockError; + use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; + + use super::listen_socket; + use crate::daemon::{Paths, endpoint::SocketOpenError}; + + fn pid_path(daemon_root:&AbsoluteSystemPath) -> AbsoluteSystemPathBuf { + daemon_root.join_component("turbod.pid") + } + + #[tokio::test] + async fn test_stale_pid() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let paths = Paths::from_repo_root(&repo_root); + paths.pid_file.ensure_dir().unwrap(); + // A pid that will never be running and is guaranteed not to be us + paths.pid_file.create_with_contents("100000").unwrap(); + + let running = Arc::new(AtomicBool::new(true)); + let result = listen_socket(&paths.pid_file, &paths.sock_file, running).await; + + assert!(result.is_ok(), "expected to clear stale pid file and connect"); + } + + #[tokio::test] + async fn test_existing_process() { + let tmp_dir = tempfile::tempdir().unwrap(); + let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); + let paths = Paths::from_repo_root(&repo_root); + + #[cfg(windows)] + let node_bin = "node.exe"; + #[cfg(not(windows))] + let node_bin = "node"; + + let mut child = Command::new(node_bin).spawn().unwrap(); + paths.pid_file.ensure_dir().unwrap(); + paths.pid_file.create_with_contents(format!("{}", child.id())).unwrap(); + + let running = Arc::new(AtomicBool::new(true)); + let result = listen_socket(&paths.pid_file, &paths.sock_file, running).await; + + // Note: PidLock doesn't implement Debug, so we can't unwrap_err() + + // todo: update this test. we should delete the socket file first, remove the + // pid file, and start a new daemon. the old one should just time + // out, and this should not error. + if let Err(err) = result { + assert_matches!(err, SocketOpenError::LockError(PidlockError::AlreadyOwned)); + } else { + panic!("expected an error") + } + + child.kill().unwrap(); + } +} diff --git a/crates/turborepo-lib/Source/daemon/mod.rs b/crates/turborepo-lib/Source/daemon/mod.rs new file mode 100644 index 0000000000000..e268c60126ce2 --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/mod.rs @@ -0,0 +1,152 @@ +//! The Turborepo daemon watches files and pre-computes data to speed up turbo's +//! execution. Each repository has a separate daemon instance. +//! +//! # Architecture +//! The daemon consists of a gRPC server that can be queried by a client. + +//! The server spins up a `FileWatching` struct, which contains a struct +//! responsible for watching the repository (`FileSystemWatcher`), and the +//! various consumers of that file change data such as `GlobWatcher` and +//! `PackageWatcher`. +//! +//! We use cookie files to ensure proper event synchronization, i.e. +//! that we don't get stale file system events while handling queries. +//! +//! # Naming Conventions +//! `recv` is a receiver of file system events. Structs such as `GlobWatcher` +//! or `PackageWatcher` consume these file system events and either derive state +//! or produce new events. +//! +//! `_tx`/`_rx` suffixes indicate that this variable is respectively a `Sender` +//! or `Receiver`. + +mod bump_timeout; +mod bump_timeout_layer; +mod client; +mod connector; +mod default_timeout_layer; +pub(crate) mod endpoint; +mod server; + +pub use client::{DaemonClient, DaemonError}; +pub use connector::{DaemonConnector, DaemonConnectorError}; +pub use server::{CloseReason, TurboGrpcService}; +use sha2::{Digest, Sha256}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; + +#[derive(Clone, Debug)] +pub struct Paths { + pub pid_file:AbsoluteSystemPathBuf, + pub lock_file:AbsoluteSystemPathBuf, + pub sock_file:AbsoluteSystemPathBuf, + pub lsp_pid_file:AbsoluteSystemPathBuf, + pub log_file:AbsoluteSystemPathBuf, + pub log_folder:AbsoluteSystemPathBuf, +} + +fn repo_hash(repo_root:&AbsoluteSystemPath) -> String { + let mut hasher = Sha256::new(); + hasher.update(repo_root.to_string().as_bytes()); + hex::encode(&hasher.finalize()[..8]) +} + +fn daemon_file_root(repo_hash:&str) -> AbsoluteSystemPathBuf { + AbsoluteSystemPathBuf::new(std::env::temp_dir().to_str().expect("UTF-8 path")) + .expect("temp dir is valid") + .join_component("turbod") + .join_component(repo_hash) +} + +fn daemon_log_file_and_folder( + repo_root:&AbsoluteSystemPath, + repo_hash:&str, +) -> (AbsoluteSystemPathBuf, AbsoluteSystemPathBuf) { + let log_folder = repo_root.join_components(&[".turbo", "daemon"]); + let log_file = log_folder.join_component(format!("{}-turbo.log", repo_hash).as_str()); + + (log_file, log_folder) +} + +impl Paths { + pub fn from_repo_root(repo_root:&AbsoluteSystemPath) -> Self { + let repo_hash = repo_hash(repo_root); + let daemon_root = daemon_file_root(&repo_hash); + let (log_file, log_folder) = daemon_log_file_and_folder(repo_root, &repo_hash); + Self { + pid_file:daemon_root.join_component("turbod.pid"), + lock_file:daemon_root.join_component("turbod.lock"), + sock_file:daemon_root.join_component("turbod.sock"), + lsp_pid_file:daemon_root.join_component("lsp.pid"), + log_file, + log_folder, + } + } +} + +pub(crate) mod proto { + + tonic::include_proto!("turbodprotocol"); + /// The version of the protocol that this library implements. + /// + /// Protocol buffers aim to be backward and forward compatible at a protocol + /// level, however that doesn't mean that our daemon will have the same + /// logical API. We may decide to change the API in the future, and this + /// version number will be used to indicate that. + /// + /// Changes are driven by the server changing its implementation. + /// + /// Guideline for bumping the daemon protocol version: + /// - Bump the major version if making backwards incompatible changes. + /// - Bump the minor version if adding new features, such that clients can + /// mandate at least some set of features on the target server. + /// - Bump the patch version if making backwards compatible bug fixes. + pub const VERSION:&str = "2.0.0"; + + impl From for turborepo_repository::package_manager::PackageManager { + fn from(pm:PackageManager) -> Self { + match pm { + PackageManager::Npm => Self::Npm, + PackageManager::Yarn => Self::Yarn, + PackageManager::Berry => Self::Berry, + PackageManager::Pnpm => Self::Pnpm, + PackageManager::Pnpm6 => Self::Pnpm6, + PackageManager::Pnpm9 => Self::Pnpm9, + PackageManager::Bun => Self::Bun, + } + } + } + + impl From for PackageManager { + fn from(pm:turborepo_repository::package_manager::PackageManager) -> Self { + match pm { + turborepo_repository::package_manager::PackageManager::Npm => Self::Npm, + turborepo_repository::package_manager::PackageManager::Yarn => Self::Yarn, + turborepo_repository::package_manager::PackageManager::Berry => Self::Berry, + turborepo_repository::package_manager::PackageManager::Pnpm => Self::Pnpm, + turborepo_repository::package_manager::PackageManager::Pnpm6 => Self::Pnpm6, + turborepo_repository::package_manager::PackageManager::Pnpm9 => Self::Pnpm9, + turborepo_repository::package_manager::PackageManager::Bun => Self::Bun, + } + } + } +} + +#[cfg(test)] +mod test { + use turbopath::AbsoluteSystemPathBuf; + + use super::repo_hash; + + #[test] + fn test_repo_hash() { + #[cfg(not(target_os = "windows"))] + let (path, expected_hash) = ("/tmp/turborepo", "6e0cfa616f75a61c"); + #[cfg(target_os = "windows")] + let (path, expected_hash) = ("C:\\\\tmp\\turborepo", "0103736e6883e35f"); + let repo_root = AbsoluteSystemPathBuf::new(path).unwrap(); + let hash = repo_hash(&repo_root); + + assert_eq!(hash, expected_hash); + assert_eq!(hash.len(), 16); + } +} diff --git a/crates/turborepo-lib/src/daemon/proto/turbod.proto b/crates/turborepo-lib/Source/daemon/proto/turbod.proto similarity index 100% rename from crates/turborepo-lib/src/daemon/proto/turbod.proto rename to crates/turborepo-lib/Source/daemon/proto/turbod.proto diff --git a/crates/turborepo-lib/Source/daemon/server.rs b/crates/turborepo-lib/Source/daemon/server.rs new file mode 100644 index 0000000000000..cfbbe211b5eda --- /dev/null +++ b/crates/turborepo-lib/Source/daemon/server.rs @@ -0,0 +1,848 @@ +//! Daemon Server +//! +//! This module houses the daemon server. For more information, go to the +//! [daemon module](std::daemon). + +use std::{ + collections::{HashMap, HashSet}, + sync::{ + Arc, + Mutex, + OnceLock, + atomic::{AtomicBool, Ordering}, + }, + time::{Duration, Instant}, +}; + +use futures::Future; +use prost::DecodeError; +use semver::Version; +use thiserror::Error; +use tokio::{ + select, + sync::{broadcast::error::RecvError, mpsc, oneshot}, + task::JoinHandle, +}; +use tokio_stream::wrappers::ReceiverStream; +use tonic::{server::NamedService, transport::Server}; +use tower::ServiceBuilder; +use tracing::{error, info, trace, warn}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf, PathError}; +use turborepo_filewatch::{ + FileSystemWatcher, + WatchError, + cookies::CookieWriter, + globwatcher::{Error as GlobWatcherError, GlobError, GlobSet, GlobWatcher}, + hash_watcher::{Error as HashWatcherError, HashSpec, HashWatcher, InputGlobs}, + package_watcher::{PackageWatchError, PackageWatcher}, +}; +use turborepo_repository::package_manager; +use turborepo_scm::SCM; + +use super::{bump_timeout::BumpTimeout, endpoint::SocketOpenError, proto}; +use crate::{ + daemon::{ + Paths, + bump_timeout_layer::BumpTimeoutLayer, + default_timeout_layer::DefaultTimeoutLayer, + endpoint::listen_socket, + }, + package_changes_watcher::{PackageChangeEvent, PackageChangesWatcher}, +}; + +#[derive(Debug)] +#[allow(dead_code)] +pub enum CloseReason { + Timeout, + Shutdown, + WatcherClosed, + ServerClosed, + Interrupt, + SocketOpenError(SocketOpenError), +} + +/// We may need to pass out references to a subset of these, so +/// we'll make them public Arcs. Eventually we can stabilize on +/// a general API and close this up. +#[derive(Clone)] +pub struct FileWatching { + repo_root:AbsoluteSystemPathBuf, + watcher:Arc, + pub glob_watcher:Arc, + pub package_watcher:Arc, + pub package_changes_watcher:OnceLock>, + pub hash_watcher:Arc, +} + +#[derive(Debug, Error)] +enum RpcError { + #[error("deadline exceeded")] + DeadlineExceeded, + #[error("invalid relative system path {0}: {1}")] + InvalidAnchoredPath(String, PathError), + #[error("invalid glob: {0}")] + InvalidGlob(#[from] GlobError), + #[error("globwatching failed: {0}")] + GlobWatching(#[from] GlobWatcherError), + #[error("filewatching unavailable")] + NoFileWatching, + #[error("file hashing failed: {0}")] + FileHashing(#[from] HashWatcherError), +} + +impl From for tonic::Status { + fn from(value:RpcError) -> Self { + match value { + RpcError::DeadlineExceeded => { + tonic::Status::deadline_exceeded("failed to load filewatching in time") + }, + RpcError::InvalidGlob(e) => tonic::Status::invalid_argument(e.to_string()), + RpcError::GlobWatching(e) => tonic::Status::unavailable(e.to_string()), + RpcError::NoFileWatching => tonic::Status::unavailable("filewatching unavailable"), + RpcError::FileHashing(e) => { + tonic::Status::failed_precondition(format!("File hashing not available: {e}",)) + }, + e @ RpcError::InvalidAnchoredPath(..) => tonic::Status::invalid_argument(e.to_string()), + } + } +} + +impl FileWatching { + /// This function is called in the constructor for the `TurboGrpcService` + /// and should defer ALL heavy computation to the background, making use + /// of `OptionalWatch` to ensure that the server can start up without + /// waiting for the filewatcher to be ready. Using `OptionalWatch`, + /// dependent services can wait for resources they need to become + /// available, and the server can start up without waiting for them. + pub fn new(repo_root:AbsoluteSystemPathBuf) -> Result { + let watcher = Arc::new(FileSystemWatcher::new_with_default_cookie_dir(&repo_root)?); + let recv = watcher.watch(); + + let cookie_writer = + CookieWriter::new(watcher.cookie_dir(), Duration::from_millis(100), recv.clone()); + let glob_watcher = + Arc::new(GlobWatcher::new(repo_root.clone(), cookie_writer.clone(), recv.clone())); + let package_watcher = Arc::new( + PackageWatcher::new(repo_root.clone(), recv.clone(), cookie_writer) + .map_err(|e| WatchError::Setup(format!("{:?}", e)))?, + ); + let scm = SCM::new(&repo_root); + let hash_watcher = Arc::new(HashWatcher::new( + repo_root.clone(), + package_watcher.watch_discovery(), + recv.clone(), + scm, + )); + + Ok(FileWatching { + repo_root, + watcher, + glob_watcher, + package_watcher, + package_changes_watcher:OnceLock::new(), + hash_watcher, + }) + } + + pub fn get_or_init_package_changes_watcher(&self) -> Arc { + self.package_changes_watcher + .get_or_init(|| { + let recv = self.watcher.watch(); + Arc::new(PackageChangesWatcher::new( + self.repo_root.clone(), + recv, + self.hash_watcher.clone(), + )) + }) + .clone() + } +} + +/// Timeout for every RPC the server handles +const REQUEST_TIMEOUT:Duration = Duration::from_secs(30); + +pub struct TurboGrpcService { + repo_root:AbsoluteSystemPathBuf, + paths:Paths, + timeout:Duration, + external_shutdown:S, +} + +impl TurboGrpcService +where + S: Future, +{ + /// Create a gRPC server providing the Turbod interface. external_shutdown + /// can be used to deliver a signal to shutdown the server. This is expected + /// to be wired to signal handling. By default, the server will set up a + /// file system watcher for the purposes of managing package discovery + /// state, and use a `LocalPackageDiscovery` instance to refresh the + /// state if the filewatcher encounters errors. + pub fn new( + repo_root:AbsoluteSystemPathBuf, + paths:Paths, + timeout:Duration, + external_shutdown:S, + ) -> Self { + // Run the actual service. It takes ownership of the struct given to it, + // so we use a private struct with just the pieces of state needed to handle + // RPCs. + TurboGrpcService { repo_root, paths, timeout, external_shutdown } + } + + pub async fn serve(self) -> Result { + let Self { external_shutdown, paths, repo_root, timeout } = self; + + // A channel to trigger the shutdown of the gRPC server. This is handed out + // to components internal to the server process such as root watching, as + // well as available to the gRPC server itself to handle the shutdown RPC. + let (trigger_shutdown, mut shutdown_signal) = mpsc::channel::<()>(1); + + let (service, exit_root_watch, watch_root_handle) = + TurboGrpcServiceInner::new(repo_root.clone(), trigger_shutdown, paths.log_file); + + let running = Arc::new(AtomicBool::new(true)); + let (_pid_lock, stream) = + match listen_socket(&paths.pid_file, &paths.sock_file, running.clone()).await { + Ok((pid_lock, stream)) => (pid_lock, stream), + Err(e) => return Ok(CloseReason::SocketOpenError(e)), + }; + trace!("acquired connection stream for socket"); + + let bump_timeout = Arc::new(BumpTimeout::new(timeout)); + let timeout_fut = bump_timeout.wait(); + + // when one of these futures complete, let the server gracefully shutdown + let (grpc_shutdown_tx, shutdown_reason) = oneshot::channel(); + let shutdown_fut = async move { + select! { + _ = shutdown_signal.recv() => grpc_shutdown_tx.send(CloseReason::Shutdown).ok(), + _ = timeout_fut => grpc_shutdown_tx.send(CloseReason::Timeout).ok(), + reason = external_shutdown => grpc_shutdown_tx.send(reason).ok(), + }; + }; + + let server_fut = { + let service = ServiceBuilder::new() + .layer(BumpTimeoutLayer::new(bump_timeout.clone())) + .layer(DefaultTimeoutLayer) + .service(crate::daemon::proto::turbod_server::TurbodServer::new(service)); + + Server::builder() + // we respect the timeout specified by the client if it is set, but + // have a default timeout for non-blocking calls of 100ms, courtesy of + // `DefaultTimeoutLayer`. the REQUEST_TIMEOUT, however, is the + // maximum time we will wait for a response, regardless of the client's + // preferences. it cannot be exceeded. + .timeout(REQUEST_TIMEOUT) + .add_service(service) + .serve_with_incoming_shutdown(stream, shutdown_fut) + }; + // Wait for the server to exit. + // This can be triggered by timeout, root watcher, or an RPC + tracing::debug!("server started"); + let _ = server_fut.await; + tracing::debug!("server exited"); + // Ensure our timer will exit + running.store(false, Ordering::SeqCst); + // We expect to have a signal from the grpc server on what triggered the exit + let close_reason = shutdown_reason.await.unwrap_or(CloseReason::ServerClosed); + // Now that the server has exited, the TurboGrpcService instance should be + // dropped. The root watcher still has a reference to a receiver, keeping + // the filewatcher alive. Trigger the root watcher to exit. We don't care + // if we fail to send, root watching may have exited already + let _ = exit_root_watch.send(()); + let _ = watch_root_handle.await; + trace!("root watching exited"); + Ok(close_reason) + } +} + +struct TurboGrpcServiceInner { + shutdown:mpsc::Sender<()>, + file_watching:FileWatching, + times_saved:Arc>>, + start_time:Instant, + log_file:AbsoluteSystemPathBuf, + package_watcher:Arc, +} + +// we have a grpc service that uses watching package discovery, and where the +// watching package hasher also uses watching package discovery as well as +// falling back to a local package hasher +impl TurboGrpcServiceInner { + pub fn new( + repo_root:AbsoluteSystemPathBuf, + trigger_shutdown:mpsc::Sender<()>, + log_file:AbsoluteSystemPathBuf, + ) -> (Self, oneshot::Sender<()>, JoinHandle>) { + let file_watching = FileWatching::new(repo_root.clone()).unwrap(); + + tracing::debug!("initing package discovery"); + // Note that we're cloning the Arc, not the package watcher itself + let package_watcher = Arc::clone(&file_watching.package_watcher); + + // exit_root_watch delivers a signal to the root watch loop to exit. + // In the event that the server shuts down via some other mechanism, this + // cleans up root watching task. + let (exit_root_watch, root_watch_exit_signal) = oneshot::channel(); + let watch_root_handle = tokio::task::spawn(watch_root( + file_watching.clone(), + repo_root.clone(), + trigger_shutdown.clone(), + root_watch_exit_signal, + )); + + ( + TurboGrpcServiceInner { + package_watcher, + shutdown:trigger_shutdown, + file_watching, + times_saved:Arc::new(Mutex::new(HashMap::new())), + start_time:Instant::now(), + log_file, + }, + exit_root_watch, + watch_root_handle, + ) + } + + async fn trigger_shutdown(&self) { + info!("triggering shutdown"); + let _ = self.shutdown.send(()).await; + } + + async fn watch_globs( + &self, + hash:String, + output_globs:Vec, + output_glob_exclusions:Vec, + time_saved:u64, + ) -> Result<(), RpcError> { + let glob_set = GlobSet::from_raw(output_globs, output_glob_exclusions)?; + self.file_watching + .glob_watcher + .watch_globs(hash.clone(), glob_set, REQUEST_TIMEOUT) + .await?; + { + let mut times_saved = self.times_saved.lock().expect("times saved lock poisoned"); + times_saved.insert(hash, time_saved); + } + Ok(()) + } + + async fn get_changed_outputs( + &self, + hash:String, + candidates:HashSet, + ) -> Result<(HashSet, u64), RpcError> { + let time_saved = { + let times_saved = self.times_saved.lock().expect("times saved lock poisoned"); + times_saved.get(hash.as_str()).copied().unwrap_or_default() + }; + let changed_globs = self + .file_watching + .glob_watcher + .get_changed_globs(hash, candidates, REQUEST_TIMEOUT) + .await?; + Ok((changed_globs, time_saved)) + } + + async fn get_file_hashes( + &self, + package_path:String, + inputs:Vec, + ) -> Result, RpcError> { + let inputs = InputGlobs::from_raw(inputs)?; + let package_path = AnchoredSystemPathBuf::try_from(package_path.as_str()) + .map_err(|e| RpcError::InvalidAnchoredPath(package_path, e))?; + let hash_spec = HashSpec { package_path, inputs }; + self.file_watching + .hash_watcher + .get_file_hashes(hash_spec) + .await + .map_err(RpcError::FileHashing) + .map(|hashes| hashes.into_iter().map(|(path, hash)| (path.to_string(), hash)).collect()) + } +} + +async fn watch_root( + filewatching_access:FileWatching, + root:AbsoluteSystemPathBuf, + trigger_shutdown:mpsc::Sender<()>, + mut exit_signal:oneshot::Receiver<()>, +) -> Result<(), WatchError> { + let mut recv_events = filewatching_access + .watcher + .subscribe() + .await + // we can only encounter an error here if the file watcher is closed (a recv error) + .map_err(|_| WatchError::Setup("file watching shut down".to_string()))?; + + tracing::debug!("watching root: {:?}", root); + + loop { + // Ignore the outer layer of Result, if the sender has closed, filewatching has + // gone away and we can return. + select! { + _ = &mut exit_signal => break, + event = recv_events.recv() => { + let Ok(event) = event else { + break; + }; + tracing::debug!("root watcher received event: {:?}", event); + let should_trigger_shutdown = match event { + // filewatching can throw some weird events, so check that the root is actually gone + // before triggering a shutdown + Ok(event) if event.paths.iter().any(|p| p == (&root as &AbsoluteSystemPath)) => !root.exists(), + Ok(_) => false, + Err(_) => true + }; + if should_trigger_shutdown { + warn!("Root watcher triggering shutdown"); + // We don't care if a shutdown has already been triggered, + // so we can ignore the error. + let _ = trigger_shutdown.send(()).await; + break; + } + } + } + } + + tracing::debug!("no longer watching root"); + + Ok(()) +} + +#[tonic::async_trait] +impl proto::turbod_server::Turbod for TurboGrpcServiceInner { + type PackageChangesStream = ReceiverStream>; + + async fn hello( + &self, + request:tonic::Request, + ) -> Result, tonic::Status> { + let request = request.into_inner(); + + let client_version = request.version; + let server_version = proto::VERSION; + + let passes_version_check = match ( + proto::VersionRange::try_from(request.supported_version_range), + Version::parse(&client_version), + Version::parse(server_version), + ) { + // if we fail to parse, or the constraint is invalid, we have a version mismatch + (_, Err(_), _) | (_, _, Err(_)) | (Err(DecodeError { .. }), ..) => false, + (Ok(range), Ok(client), Ok(server)) => compare_versions(client, server, range), + }; + + if passes_version_check { + Ok(tonic::Response::new(proto::HelloResponse {})) + } else { + Err(tonic::Status::failed_precondition(format!( + "version mismatch. Client {} Server {}", + client_version, server_version + ))) + } + } + + async fn shutdown( + &self, + _request:tonic::Request, + ) -> Result, tonic::Status> { + self.trigger_shutdown().await; + + // if Some(Ok), then the server is shutting down now + // if Some(Err), then the server is already shutting down + // if None, then someone has already called shutdown + Ok(tonic::Response::new(proto::ShutdownResponse {})) + } + + async fn status( + &self, + _request:tonic::Request, + ) -> Result, tonic::Status> { + Ok(tonic::Response::new(proto::StatusResponse { + daemon_status:Some(proto::DaemonStatus { + uptime_msec:self.start_time.elapsed().as_millis() as u64, + log_file:self.log_file.to_string(), + }), + })) + } + + async fn notify_outputs_written( + &self, + request:tonic::Request, + ) -> Result, tonic::Status> { + let inner = request.into_inner(); + + self.watch_globs( + inner.hash, + inner.output_globs, + inner.output_exclusion_globs, + inner.time_saved, + ) + .await?; + Ok(tonic::Response::new(proto::NotifyOutputsWrittenResponse {})) + } + + async fn get_changed_outputs( + &self, + request:tonic::Request, + ) -> Result, tonic::Status> { + let inner = request.into_inner(); + let (changed, time_saved) = self + .get_changed_outputs(inner.hash, HashSet::from_iter(inner.output_globs)) + .await?; + Ok(tonic::Response::new(proto::GetChangedOutputsResponse { + changed_output_globs:changed.into_iter().collect(), + time_saved, + })) + } + + // Note that this is implemented as a blocking call. We expect the default + // server timeout to apply, as well as whatever timeout the client may have + // set. + async fn get_file_hashes( + &self, + request:tonic::Request, + ) -> Result, tonic::Status> { + let inner = request.into_inner(); + let file_hashes = self.get_file_hashes(inner.package_path, inner.input_globs).await?; + Ok(tonic::Response::new(proto::GetFileHashesResponse { file_hashes })) + } + + async fn discover_packages( + &self, + _request:tonic::Request, + ) -> Result, tonic::Status> { + match self.package_watcher.discover_packages().await { + Some(Ok(packages)) => { + Ok(tonic::Response::new(proto::DiscoverPackagesResponse { + package_files:packages + .workspaces + .into_iter() + .map(|d| { + proto::PackageFiles { + package_json:d.package_json.to_string(), + turbo_json:d.turbo_json.map(|t| t.to_string()), + } + }) + .collect(), + package_manager:proto::PackageManager::from(packages.package_manager).into(), + })) + }, + None | Some(Err(PackageWatchError::Unavailable)) => { + Err(tonic::Status::unavailable("package discovery unavailable")) + }, + Some(Err(PackageWatchError::InvalidState(reason))) => { + Err(tonic::Status::failed_precondition(reason)) + }, + } + } + + async fn discover_packages_blocking( + &self, + _request:tonic::Request, + ) -> Result, tonic::Status> { + match self.package_watcher.discover_packages_blocking().await { + Ok(packages) => { + Ok(tonic::Response::new(proto::DiscoverPackagesResponse { + package_files:packages + .workspaces + .into_iter() + .map(|d| { + proto::PackageFiles { + package_json:d.package_json.to_string(), + turbo_json:d.turbo_json.map(|t| t.to_string()), + } + }) + .collect(), + package_manager:proto::PackageManager::from(packages.package_manager).into(), + })) + }, + Err(PackageWatchError::Unavailable) => { + Err(tonic::Status::unavailable("package discovery unavailable")) + }, + Err(PackageWatchError::InvalidState(reason)) => { + Err(tonic::Status::failed_precondition(reason)) + }, + } + } + + async fn package_changes( + &self, + _request:tonic::Request, + ) -> Result, tonic::Status> { + let mut package_changes_rx = + self.file_watching.get_or_init_package_changes_watcher().package_changes().await; + + let (tx, rx) = mpsc::channel(4096); + + tx.send(Ok(proto::PackageChangeEvent { + event:Some(proto::package_change_event::Event::RediscoverPackages( + proto::RediscoverPackages {}, + )), + })) + .await + .map_err(|e| tonic::Status::unavailable(format!("{}", e)))?; + + tokio::spawn(async move { + loop { + let event = match package_changes_rx.recv().await { + Err(RecvError::Lagged(_)) => { + warn!("package changes stream lagged"); + proto::PackageChangeEvent { + event:Some(proto::package_change_event::Event::RediscoverPackages( + proto::RediscoverPackages {}, + )), + } + }, + Err(err) => { + proto::PackageChangeEvent { + event:Some(proto::package_change_event::Event::Error( + proto::PackageChangeError { message:err.to_string() }, + )), + } + }, + Ok(PackageChangeEvent::Package { name }) => { + proto::PackageChangeEvent { + event:Some(proto::package_change_event::Event::PackageChanged( + proto::PackageChanged { package_name:name.to_string() }, + )), + } + }, + Ok(PackageChangeEvent::Rediscover) => { + proto::PackageChangeEvent { + event:Some(proto::package_change_event::Event::RediscoverPackages( + proto::RediscoverPackages {}, + )), + } + }, + }; + + if let Err(err) = tx.send(Ok(event)).await { + error!("package changes stream closed: {}", err); + break; + } + } + }); + + Ok(tonic::Response::new(ReceiverStream::new(rx))) + } +} + +/// Determine whether a server can serve a client's request based on its +/// version. +/// +/// When the `proto::VersionRange` is anything other than `Exact` it means that +/// the server's version must exceed the client's version. For example, if the +/// client is `1.2.3` and the server is `1.2.4`, then the client's request can +/// be served if the `proto::VersionRange` is `Patch`, `Minor`, or `Major`. +/// However, if the server is `1.3.0`, then the client's request can only be +/// served if the `proto::VersionRange` is `Minor` or `Major`. +fn compare_versions(client:Version, server:Version, constraint:proto::VersionRange) -> bool { + match constraint { + proto::VersionRange::Exact => client == server, + proto::VersionRange::Patch => { + client.major == server.major + && client.minor == server.minor + && client.patch <= server.patch + }, + proto::VersionRange::Minor => client.major == server.major && client.minor <= server.minor, + // changes to major version is always incompatible + proto::VersionRange::Major => client.major == server.major, + } +} + +impl NamedService for TurboGrpcServiceInner { + const NAME:&'static str = "turborepo.Daemon"; +} + +#[cfg(test)] +mod test { + use std::{ + assert_matches::{self, assert_matches}, + time::{Duration, Instant}, + }; + + use futures::FutureExt; + use semver::Version; + use test_case::test_case; + use tokio::sync::oneshot; + use turbopath::AbsoluteSystemPathBuf; + use turborepo_repository::{ + discovery::{DiscoveryResponse, PackageDiscovery}, + package_manager::PackageManager, + }; + + use super::compare_versions; + use crate::daemon::{CloseReason, Paths, TurboGrpcService, proto::VersionRange}; + + #[test_case("1.2.3", "1.2.3", VersionRange::Exact, true ; "exact match")] + #[test_case("1.2.3", "1.2.3", VersionRange::Patch, true ; "patch match")] + #[test_case("1.2.3", "1.2.3", VersionRange::Minor, true ; "minor match")] + #[test_case("1.2.3", "1.2.3", VersionRange::Major, true ; "major match")] + #[test_case("1.2.3", "1.2.4", VersionRange::Exact, false ; "exact mismatch")] + #[test_case("1.2.3", "1.2.4", VersionRange::Patch, true ; "patch greater match")] + #[test_case("1.2.3", "1.2.4", VersionRange::Minor, true ; "minor greater match")] + #[test_case("1.2.3", "1.2.4", VersionRange::Major, true ; "major greater match")] + #[test_case("1.2.3", "1.2.2", VersionRange::Patch, false ; "patch lesser mismatch")] + #[test_case("1.2.3", "1.1.3", VersionRange::Patch, false ; "patch lesser minor mismatch")] + #[test_case("1.2.3", "1.1.0", VersionRange::Minor, false ; "minor lesser mismatch")] + #[test_case("1.2.3", "0.1.0", VersionRange::Major, false ; "major lesser mismatch")] + #[test_case("1.10.17-canary.0", "1.10.17-canary.1", VersionRange::Exact, false ; "canary mismatch")] + #[test_case("1.10.17-canary.0", "1.10.17-canary.1", VersionRange::Patch, true ; "canary match")] + #[test_case("1.0.0", "2.0.0", VersionRange::Major, false ; "major breaking changes")] + + fn version_match(a:&str, b:&str, constraint:VersionRange, expected:bool) { + assert_eq!( + compare_versions(Version::parse(a).unwrap(), Version::parse(b).unwrap(), constraint), + expected + ) + } + + struct MockDiscovery; + impl PackageDiscovery for MockDiscovery { + async fn discover_packages( + &self, + ) -> Result< + turborepo_repository::discovery::DiscoveryResponse, + turborepo_repository::discovery::Error, + > { + Ok(DiscoveryResponse { package_manager:PackageManager::Yarn, workspaces:vec![] }) + } + + async fn discover_packages_blocking( + &self, + ) -> Result< + turborepo_repository::discovery::DiscoveryResponse, + turborepo_repository::discovery::Error, + > { + self.discover_packages().await + } + } + + // the windows runner starts a new thread to accept uds requests, + // so we need a multi-threaded runtime + #[tokio::test(flavor = "multi_thread")] + #[tracing_test::traced_test] + async fn lifecycle() { + let tempdir = tempfile::tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tempdir.path()).unwrap().to_realpath().unwrap(); + + let repo_root = path.join_component("repo"); + let paths = Paths::from_repo_root(&repo_root); + tracing::info!("start"); + + let (tx, rx) = oneshot::channel::(); + let exit_signal = rx.map(|_result| CloseReason::Interrupt); + + let service = TurboGrpcService::new( + repo_root.clone(), + paths.clone(), + Duration::from_secs(60 * 60), + exit_signal, + ); + + // the package watcher reads data from the package.json file + // so we need to create it + repo_root.create_dir_all().unwrap(); + let package_json = repo_root.join_component("package.json"); + package_json.create_with_contents(r#"{"workspaces": ["packages/*"]}"#).unwrap(); + repo_root.join_component("package-lock.json").create_with_contents("").unwrap(); + + let handle = tokio::task::spawn(service.serve()); + + tokio::time::sleep(Duration::from_millis(2000)).await; + assert!(paths.pid_file.exists(), "pid file must be present at {:?}", paths.pid_file); + // signal server exit + tx.send(CloseReason::Interrupt).unwrap(); + handle.await.unwrap().unwrap(); + + // The serve future should be dropped here, closing the server. + tracing::info!("yay we are done"); + + assert!(!paths.pid_file.exists(), "pid file must be deleted"); + + tracing::info!("and files cleaned up"); + } + + // the windows runner starts a new thread to accept uds requests, + // so we need a multi-threaded runtime + #[tokio::test(flavor = "multi_thread")] + #[tracing_test::traced_test] + async fn timeout() { + let tempdir = tempfile::tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tempdir.path()).unwrap().to_realpath().unwrap(); + + let repo_root = path.join_component("repo"); + let paths = Paths::from_repo_root(&repo_root); + + let now = Instant::now(); + let (_tx, rx) = oneshot::channel::(); + let exit_signal = rx.map(|_result| CloseReason::Interrupt); + + let server = TurboGrpcService::new( + repo_root.clone(), + paths.clone(), + Duration::from_millis(10), + exit_signal, + ); + + // the package watcher reads data from the package.json file + // so we need to create it + repo_root.create_dir_all().unwrap(); + let package_json = repo_root.join_component("package.json"); + package_json.create_with_contents(r#"{"workspaces": ["packages/*"]}"#).unwrap(); + repo_root.join_component("package-lock.json").create_with_contents("").unwrap(); + + let close_reason = server.serve().await; + + assert!(now.elapsed() >= Duration::from_millis(10), "must wait at least 5ms"); + assert_matches::assert_matches!( + close_reason, + Ok(CloseReason::Timeout), + "must close due to timeout" + ); + assert!(!paths.pid_file.exists(), "pid file must be deleted"); + } + + #[tokio::test(flavor = "multi_thread")] + #[tracing_test::traced_test] + async fn test_delete_root() { + let tempdir = tempfile::tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tempdir.path()).unwrap().to_realpath().unwrap(); + + let repo_root = path.join_component("repo"); + repo_root.create_dir_all().unwrap(); + let package_json = repo_root.join_component("package.json"); + package_json.create_with_contents(r#"{"workspaces": ["packages/*"]}"#).unwrap(); + repo_root.join_component("package-lock.json").create_with_contents("").unwrap(); + let paths = Paths::from_repo_root(&repo_root); + + let (_tx, rx) = oneshot::channel::(); + let exit_signal = rx.map(|_result| CloseReason::Interrupt); + + let server = TurboGrpcService::new( + repo_root.clone(), + paths, + Duration::from_secs(60 * 60), + exit_signal, + ); + + let handle = tokio::task::spawn(server.serve()); + + // give filewatching some time to bootstrap + tokio::time::sleep(Duration::from_secs(1)).await; + // Remove the root + repo_root.remove_dir_all().unwrap(); + + let close_reason = tokio::time::timeout(Duration::from_secs(1), handle) + .await + .expect("no timeout") + .expect("server exited"); + assert_matches!(close_reason, Ok(CloseReason::Shutdown)); + } +} diff --git a/crates/turborepo-lib/Source/diagnostics.rs b/crates/turborepo-lib/Source/diagnostics.rs new file mode 100644 index 0000000000000..7102e58b573e7 --- /dev/null +++ b/crates/turborepo-lib/Source/diagnostics.rs @@ -0,0 +1,505 @@ +use std::{process::Stdio, sync::Arc, time::Duration}; + +use futures::future::join_all; +use tokio::{ + process::Command, + sync::{ + Mutex, + mpsc::{Receiver as MpscReceiver, Sender as MpscSender}, + oneshot::{self, Receiver, Sender}, + }, +}; +use turbo_updater::check_for_updates; +use turbopath::AbsoluteSystemPathBuf; +use turborepo_scm::Git; + +use crate::{ + DaemonPaths, + commands::{ + CommandBase, + link::{self, link}, + }, + daemon::DaemonConnector, + get_version, +}; + +#[derive(Debug)] +pub enum DiagnosticMessage { + NotApplicable(String), + /// internal name of diag and human readable name + Started(String), + LogLine(String), + Done(String), + Failed(String), + /// a request to suspend terminal output. the renderer + /// will notify the diagnostic when it is safe to render + /// and the diagnostic notify in return when it is done + Suspend(Sender<()>, Receiver<()>), + /// a request to the user with options and a callback to send the response + Request(String, Vec, Sender), +} + +/// A light wrapper around a tokio channel with a must_use such that we ensure +/// the communication is always terminated and the diagnostic is always +/// notified, in absence of linear types. Unfortunately this lint is flaky +/// at best so while we can't solely rely on it to enforce the invariant, +/// it's better than nothing. +#[must_use] +#[derive(Clone)] +pub struct DiagnosticChannel(MpscSender); +impl DiagnosticChannel { + pub fn new() -> (Self, MpscReceiver) { + let (tx, rx) = tokio::sync::mpsc::channel(10); + (Self(tx), rx) + } + + async fn started(&self, message:String) { self.send(DiagnosticMessage::Started(message)).await } + + async fn log_line(&self, message:String) { + self.send(DiagnosticMessage::LogLine(message)).await + } + + /// prompts the user with a message and options + async fn request(&self, message:String, options:Vec) -> Option> { + let (tx, rx) = oneshot::channel(); + self.0.send(DiagnosticMessage::Request(message, options, tx)).await.ok()?; // if the channel is closed, we can't request + Some(rx) + } + + /// suspends the terminal output and returns a pair of channels + /// + /// the first one signifies to the diagnostic when it is safe to render + /// and the second one is used by the diagnostic to notify the renderer + /// when it is done + async fn suspend(&self) -> Option<(Receiver<()>, Sender<()>)> { + let (stopped_tx, stopped_rx) = oneshot::channel(); + let (resume_tx, resume_rx) = oneshot::channel(); + + self.0.send(DiagnosticMessage::Suspend(stopped_tx, resume_rx)).await.ok()?; // if the channel is closed, we can't suspend + + Some((stopped_rx, resume_tx)) + } + + // types of exit + + /// the diagnostic is done + async fn done(self, message:String) { + self.send(DiagnosticMessage::Done(message.to_string())).await + } + + /// the diagnostic failed + async fn failed(self, message:String) { + self.send(DiagnosticMessage::Failed(message.to_string())).await + } + + /// the diagnostic is not applicable + async fn not_applicable(self, message:String) { + self.send(DiagnosticMessage::NotApplicable(message.to_string())).await + } + + pub async fn send(&self, message:DiagnosticMessage) { + _ = self.0.send(message).await // channel closed, ignore + } +} + +// sadly, because we want to use this trait as a trait object, we can't use +// async fn in the trait definition since it desugars to associated types +// which aren't compatible with trait objects. we _can_ box the futures though, +// which is what async_trait does for us. rather than add a dep, lets just +// use the one we use for the daemon though tonic +#[tonic::async_trait] +pub trait Diagnostic { + // this needs to have a self param so it can be a trait object + fn name(&self) -> &'static str; + + /// Execute a diagnostic. You _must_ call `DiagnosticChannel::started` when + /// the diag has begun, and dispose of the channel by calling one of the + /// three exit methods identified by consuming `self`. + fn execute(&self, chan:DiagnosticChannel); +} + +pub struct GitDaemonDiagnostic; + +impl Diagnostic for GitDaemonDiagnostic { + fn name(&self) -> &'static str { "git.daemon" } + + fn execute(&self, chan:DiagnosticChannel) { + tokio::task::spawn(async move { + chan.started("Git FS Monitor".to_string()).await; + + if !(cfg!(target_os = "windows") || cfg!(target_os = "macos")) { + // the git daemon is not implemented on unix + chan.not_applicable("Git FS Monitor (not available on linux)".to_string()).await; + return; + } + + let commands:Result>, _> = join_all( + [ + &["--version"][..], + &["config", "--get", "core.fsmonitor"][..], + &["config", "--get", "core.untrackedcache"][..], + ] + .into_iter() + .map(|args| { + async move { + // get the current setting + let stdout = Stdio::piped(); + + let Ok(git_path) = Git::find_bin() else { + return Err("git not found"); + }; + + let command = Command::new(git_path.as_path()) + .args(args) + .stdout(stdout) + .stdin(Stdio::null()) + .spawn() + .expect("too many processes"); // this can only fail if we run out of processes on unix + + command + .wait_with_output() + .await + .map(|d| d.stdout) + .map_err(|_| "failed to get git metadata") + } + }), + ) + .await + .into_iter() + .collect(); // transpose + + chan.log_line("Collecting metadata".to_string()).await; + + match commands.as_ref().map(|v| v.as_slice()) { + Ok([version, fsmonitor, untrackedcache]) => { + let version = String::from_utf8_lossy(version); + let Some(version) = version.trim().strip_prefix("git version ") else { + chan.failed("Failed to get git version".to_string()).await; + return; + }; + + // attempt to split out the apple git suffix + let version = if let Some((version, _)) = version.split_once(" (Apple") { + version + } else { + version + }; + + let Ok(version) = semver::Version::parse(version) else { + chan.failed("Failed to parse git version".to_string()).await; + return; + }; + + if version.major == 2 && version.minor < 37 || version.major == 1 { + chan.not_applicable(format!( + "Git version {} is too old, please upgrade to 2.37 or newer", + version + )) + .await; + return; + } else { + chan.log_line( + format!("Using supported Git version - {}", version).to_string(), + ) + .await; + } + + let fsmonitor = String::from_utf8_lossy(fsmonitor); + let untrackedcache = String::from_utf8_lossy(untrackedcache); + + if fsmonitor.trim() != "true" || untrackedcache.trim() != "true" { + chan.log_line("Git FS Monitor not configured".to_string()).await; + chan.log_line( "For more information, see https://turbo.build/repo/docs/reference/command-line-reference/scan#fs-monitor".to_string()).await; + let Some(resp) = chan + .request( + "Configure it for this repo now?".to_string(), + vec!["Yes".to_string(), "No".to_string()], + ) + .await + else { + // the sender (terminal) was shut, ignore + return; + }; + match resp.await.as_ref().map(|s| s.as_str()) { + Ok("Yes") => { + chan.log_line("Setting Git FS Monitor settings".to_string()).await; + + let futures = [ + ("core.fsmonitor", fsmonitor), + ("core.untrackedcache", untrackedcache), + ] + .into_iter() + .filter(|(_, value)| value.trim() != "true") + .map(|(key, _)| { + async { + let stdout = Stdio::piped(); + + let command = Command::new("git") + .args(["config", key, "true"]) + .stdout(stdout) + .spawn() + .expect("too many processes"); // this can only fail if we run out of processes on unix + + command.wait_with_output().await + } + }); + + let results:Result, _> = + join_all(futures).await.into_iter().collect(); + + match results { + Ok(_) => { + chan.log_line("Git FS Monitor settings set".to_string()) + .await; + }, + Err(e) => { + chan.failed(format!("Failed to set git settings: {}", e)) + .await; + return; + }, + } + }, + Ok("No") => { + chan.failed("Git FS Monitor not configured".to_string()).await; + return; + }, + Ok(_) => unreachable!(), + Err(_) => { + // the sender (terminal) was shut, ignore + }, + } + } else { + chan.log_line("Git FS Monitor settings set".to_string()).await; + } + }, + Ok(_) => unreachable!(), // the vec of futures has exactly 3 elements + Err(e) => { + chan.failed(format!("Failed to get git version: {}", e)).await; + return; + }, + } + + chan.done("Git FS Monitor enabled".to_string()).await; + }); + } +} + +pub struct DaemonDiagnostic(pub DaemonPaths); + +impl Diagnostic for DaemonDiagnostic { + fn name(&self) -> &'static str { "turbo.daemon" } + + fn execute(&self, chan:DiagnosticChannel) { + let paths = self.0.clone(); + tokio::task::spawn(async move { + chan.started("Turbo Daemon".to_string()).await; + chan.log_line("Connecting to daemon...".to_string()).await; + + let pid_path = paths.pid_file.as_std_path().to_owned(); + + let connector = DaemonConnector { can_kill_server:false, can_start_server:true, paths }; + + let mut client = match connector.connect().await { + Ok(client) => client, + Err(e) => { + chan.failed(format!("Failed to connect to daemon: {}", e)).await; + return; + }, + }; + + chan.log_line("Getting status...".to_string()).await; + + match client.status().await { + Ok(status) => { + chan.log_line(format!("Daemon up for {}ms", status.uptime_msec)).await; + let lock = pidlock::Pidlock::new(pid_path); + let pid = if let Ok(Some(owner)) = lock.get_owner() { + format!(" (pid {})", owner) + } else { + "".to_string() + }; + chan.done(format!("Daemon is running{}", pid)).await; + }, + Err(e) => { + chan.failed(format!("Failed to get daemon status: {}", e)).await; + }, + } + }); + } +} + +pub struct LSPDiagnostic(pub DaemonPaths); +impl Diagnostic for LSPDiagnostic { + fn name(&self) -> &'static str { "turbo.lsp" } + + fn execute(&self, chan:DiagnosticChannel) { + let lsp_root = self.0.lsp_pid_file.as_std_path().to_owned(); + tokio::task::spawn(async move { + chan.started("Turborepo Extension".to_string()).await; + chan.log_line("Checking if extension is running...".to_string()).await; + let pidlock = pidlock::Pidlock::new(lsp_root); + match pidlock.get_owner() { + Ok(Some(pid)) => { + chan.done(format!("Turborepo Extension is running (pid {})", pid)).await; + }, + Ok(None) => { + chan.log_line("Unable to find LSP instance".to_string()).await; + chan.log_line( "For more information, see https://turbo.build/repo/docs/reference/command-line-reference/scan#lsp".to_string()).await; + chan.failed("Turborepo Extension is not running".to_string()).await; + }, + Err(e) => { + chan.failed(format!("Failed to get LSP status: {}", e)).await; + }, + } + }); + } +} + +/// a struct that checks and prompts the user to enable remote cache +pub struct RemoteCacheDiagnostic(pub Arc>); +impl RemoteCacheDiagnostic { + pub fn new(base:CommandBase) -> Self { Self(Arc::new(Mutex::new(base))) } +} + +impl Diagnostic for RemoteCacheDiagnostic { + fn name(&self) -> &'static str { "vercel.auth" } + + fn execute(&self, chan:DiagnosticChannel) { + let base = self.0.clone(); + tokio::task::spawn(async move { + chan.started("Remote Cache".to_string()).await; + + let (has_team_id, has_team_slug) = { + let base = base.lock().await; + ( + base.opts().api_client_opts.team_id.is_some(), + base.opts().api_client_opts.team_slug.is_some(), + ) + }; + + chan.log_line("Checking credentials".to_string()).await; + + if has_team_id || has_team_slug { + chan.done("Remote Cache enabled".to_string()).await; + return; + } + + let result = { + chan.log_line("Linking to remote cache".to_string()).await; + let mut base = base.lock().await; + let Some((stopped, resume)) = chan.suspend().await else { + // the sender (terminal) was shut, ignore + return; + }; + stopped.await.unwrap(); + let link_res = + link(&mut base, None, false, false, crate::cli::LinkTarget::RemoteCache).await; + resume.send(()).unwrap(); + link_res + }; + + match result { + Ok(_) => { + chan.log_line("Linked".to_string()).await; + chan.done("Remote Cache enabled".to_string()).await + }, + Err(link::Error::NotLinking) => { + chan.not_applicable("Remote Cache opted out".to_string()).await + }, + Err(e) => { + chan.failed(format!("Failed to link: {}", e)).await; + }, + } + }); + } +} + +pub struct UpdateDiagnostic(pub AbsoluteSystemPathBuf); + +impl Diagnostic for UpdateDiagnostic { + fn name(&self) -> &'static str { "turbo.update" } + + fn execute(&self, chan:DiagnosticChannel) { + let repo_root = self.0.clone(); + tokio::task::spawn(async move { + chan.started("Update Turborepo to latest version".to_string()).await; + chan.log_line("Checking for updates...".to_string()).await; + let version = tokio::task::spawn_blocking(|| { + check_for_updates( + "turbo", + get_version(), + None, + Some(Duration::from_secs(0)), // check every time + ) + .map_err(|e| e.to_string()) // not send + }) + .await; + + match version { + Ok(Ok(Some(version))) => { + chan.log_line(format!("Turborepo {} is available", version).to_string()).await; + + let Some(resp) = chan + .request( + "Would you like to run the codemod automatically?".to_string(), + vec!["Yes".to_string(), "No".to_string()], + ) + .await + else { + // the sender (terminal) was shut, ignore + return; + }; + + match resp.await.as_ref().map(|s| s.as_str()) { + Ok("Yes") => { + chan.log_line("Updating Turborepo...".to_string()).await; + let mut command = Command::new("npx"); + let command = command + .arg("--yes") + .arg("@turbo/codemod@latest") + .arg("update") + .arg("--force") + .arg(repo_root.as_path()) + .stdout(Stdio::piped()) + .stdin(Stdio::null()) + .spawn() + .expect("too many processes"); // this can only fail if we run out of processes on unix + + match command.wait_with_output().await { + Ok(output) if output.status.success() => { + chan.done("Turborepo on latest version".to_string()).await; + }, + Ok(output) => { + chan.log_line( + String::from_utf8(output.stdout).unwrap_or_default(), + ) + .await; + chan.failed("Unable to update Turborepo".to_string()).await + }, + Err(_) => { + chan.failed("Unable to update Turborepo".to_string()).await + }, + } + }, + Ok("No") => chan.failed("Turborepo on old version".to_string()).await, + Ok(_) => unreachable!(), // yes and no are the only options + Err(_) => { + // the sender (terminal) was shut, ignore + }, + } + }, + // no versions in the registry, just report success + Ok(Ok(None)) => { + chan.log_line("No updates available".to_string()).await; + chan.done("Turborepo on latest version".to_string()).await + }, + Ok(Err(message)) => { + chan.failed(format!("Failed to check for updates: {}", message)).await; + }, + Err(_) => { + chan.failed("Failed to check for updates".to_string()).await; + }, + } + }); + } +} diff --git a/crates/turborepo-lib/src/engine/builder.rs b/crates/turborepo-lib/Source/engine/builder.rs similarity index 100% rename from crates/turborepo-lib/src/engine/builder.rs rename to crates/turborepo-lib/Source/engine/builder.rs diff --git a/crates/turborepo-lib/Source/engine/dot.rs b/crates/turborepo-lib/Source/engine/dot.rs new file mode 100644 index 0000000000000..2592626cdeff3 --- /dev/null +++ b/crates/turborepo-lib/Source/engine/dot.rs @@ -0,0 +1,81 @@ +use std::io; + +use petgraph::{Graph, visit::EdgeRef}; + +use super::{Built, Engine, TaskNode}; + +impl Engine { + pub fn dot_graph(&self, writer:W, is_single:bool) -> Result<(), io::Error> { + let display_node = match is_single { + true => { + |node:&TaskNode| { + match node { + TaskNode::Root => node.to_string(), + TaskNode::Task(task) => task.task().to_string(), + } + } + }, + false => |node:&TaskNode| node.to_string(), + }; + render_graph(&self.task_graph, display_node, writer) + } +} + +const GRAPH_PRELUDE:&str = "\ndigraph {\n\tcompound = \"true\" +\tnewrank = \"true\" +\tsubgraph \"root\" { +"; + +fn render_graph( + graph:&Graph, + mut display_node:impl FnMut(&N) -> String, + mut writer:impl io::Write, +) -> Result<(), io::Error> { + let mut get_node = + |i| display_node(graph.node_weight(i).expect("node index should exist in graph")); + + // These are hardcoded writes from the Go side that we just copy + writer.write_all(GRAPH_PRELUDE.as_bytes())?; + + let mut edges = graph + .edge_references() + .map(|edge| { + let source = get_node(edge.source()); + let target = get_node(edge.target()); + format!("\t\t\"[root] {source}\" -> \"[root] {target}\"") + }) + .collect::>(); + edges.sort(); + + writer.write_all(edges.join("\n").as_bytes())?; + + writer.write_all("\n\t}\n}\n\n".as_bytes())?; + Ok(()) +} + +#[cfg(test)] +mod test { + use pretty_assertions::assert_eq; + + use super::*; + + #[test] + fn test_simple_graph_output() { + let mut bytes = Vec::new(); + let mut graph = Graph::new(); + let root = graph.add_node("___ROOT___"); + let build = graph.add_node("build"); + graph.add_edge(root, build, ()); + render_graph(&graph, |n| n.to_string(), &mut bytes).unwrap(); + assert_eq!( + String::from_utf8(bytes).unwrap(), + "\ndigraph { +\tcompound = \"true\" +\tnewrank = \"true\" +\tsubgraph \"root\" { +\t\t\"[root] ___ROOT___\" -> \"[root] build\" +\t} +}\n\n" + ); + } +} diff --git a/crates/turborepo-lib/Source/engine/execute.rs b/crates/turborepo-lib/Source/engine/execute.rs new file mode 100644 index 0000000000000..021c3c6bde200 --- /dev/null +++ b/crates/turborepo-lib/Source/engine/execute.rs @@ -0,0 +1,138 @@ +use std::sync::{Arc, Mutex}; + +use futures::{StreamExt, stream::FuturesUnordered}; +use tokio::sync::{Semaphore, mpsc, oneshot}; +use tracing::log::debug; +use turborepo_graph_utils::Walker; + +use super::{Engine, TaskNode}; +use crate::run::task_id::TaskId; + +pub struct Message { + pub info:T, + pub callback:oneshot::Sender, +} + +// Type alias used just to make altering the data sent to the visitor easier in +// the future +type VisitorData = TaskId<'static>; +type VisitorResult = Result<(), StopExecution>; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ExecutionOptions { + parallel:bool, + concurrency:usize, +} + +impl ExecutionOptions { + pub fn new(parallel:bool, concurrency:usize) -> Self { Self { parallel, concurrency } } +} + +#[derive(Debug, thiserror::Error)] +pub enum ExecuteError { + #[error("Semaphore closed before all tasks finished")] + Semaphore(#[from] tokio::sync::AcquireError), + #[error("Engine visitor closed channel before walk finished")] + Visitor, +} + +impl From>> for ExecuteError { + fn from(_:mpsc::error::SendError, Result<(), StopExecution>>>) -> Self { + ExecuteError::Visitor + } +} + +#[derive(Debug, Clone, Copy)] +pub struct StopExecution; + +impl Engine { + /// Execute a task graph by sending task ids to the visitor + /// while respecting concurrency limits. + /// The visitor is expected to handle any error handling on its end. + /// We enforce this by only allowing the returning of a sentinel error + /// type which will stop any further execution of tasks. + /// This will not stop any task which is currently running, simply it will + /// stop scheduling new tasks. + // (olszewski) The current impl requires that the visitor receiver is read until + // finish even once a task sends back the stop signal. This is suboptimal + // since it would mean the visitor would need to also track if + // it is cancelled :) + pub async fn execute( + self: Arc, + options:ExecutionOptions, + visitor:mpsc::Sender>, + ) -> Result<(), ExecuteError> { + let ExecutionOptions { parallel, concurrency } = options; + let sema = Arc::new(Semaphore::new(concurrency)); + let mut tasks:FuturesUnordered>> = + FuturesUnordered::new(); + + let (walker, mut nodes) = Walker::new(&self.task_graph).walk(); + let walker = Arc::new(Mutex::new(walker)); + + while let Some((node_id, done)) = nodes.recv().await { + let visitor = visitor.clone(); + let sema = sema.clone(); + let walker = walker.clone(); + let this = self.clone(); + + tasks.push(tokio::spawn(async move { + let TaskNode::Task(task_id) = + this.task_graph.node_weight(node_id).expect("node id should be present") + else { + // Root task has nothing to do so we don't emit any event for it + if done.send(()).is_err() { + debug!( + "Graph walker done callback receiver was closed before done signal \ + could be sent" + ); + } + return Ok(()); + }; + + // Acquire the semaphore unless parallel + let _permit = match parallel { + false => { + Some(sema.acquire().await.expect( + "Graph concurrency semaphore closed while tasks are still attempting \ + to acquire permits", + )) + }, + true => None, + }; + + let (message, result) = Message::new(task_id.clone()); + visitor.send(message).await?; + + if let Err(StopExecution) = result.await.unwrap_or_else(|_| { + // If the visitor doesn't send a callback, then we assume the task finished + tracing::trace!( + "Engine visitor dropped callback sender without sending result" + ); + Ok(()) + }) { + if walker.lock().expect("Walker mutex poisoned").cancel().is_err() { + debug!("Unable to cancel graph walk"); + } + } + if done.send(()).is_err() { + debug!("Graph walk done receiver closed before node was finished processing"); + } + Ok(()) + })); + } + + while let Some(res) = tasks.next().await { + res.expect("unable to join task")?; + } + + Ok(()) + } +} + +impl Message { + pub fn new(info:T) -> (Self, oneshot::Receiver) { + let (callback, receiver) = oneshot::channel(); + (Self { info, callback }, receiver) + } +} diff --git a/crates/turborepo-lib/Source/engine/mermaid.rs b/crates/turborepo-lib/Source/engine/mermaid.rs new file mode 100644 index 0000000000000..635408150c580 --- /dev/null +++ b/crates/turborepo-lib/Source/engine/mermaid.rs @@ -0,0 +1,76 @@ +use std::{collections::HashMap, io}; + +use itertools::Itertools; +use petgraph::{Graph, visit::EdgeRef}; +use rand::{Rng, SeedableRng, distributions::Uniform, prelude::Distribution}; + +use super::{Built, Engine, TaskNode}; + +struct CapitalLetters; + +impl Distribution for CapitalLetters { + fn sample(&self, rng:&mut R) -> char { + const RANGE:u32 = 26; + const GEN_ASCII_STR_CHARSET:&[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + let range = Uniform::new(0u32, GEN_ASCII_STR_CHARSET.len() as u32); + char::from_u32(GEN_ASCII_STR_CHARSET[range.sample(rng) as usize] as u32) + .expect("random number should be in bounds") + } +} + +fn generate_id(rng:&mut R) -> String { CapitalLetters.sample_iter(rng).take(4).join("") } + +impl Engine { + pub fn mermaid_graph(&self, writer:W, is_single:bool) -> Result<(), io::Error> { + render_graph(writer, &self.task_graph, is_single) + } +} + +fn render_graph( + mut writer:W, + graph:&Graph, + is_single:bool, +) -> Result<(), io::Error> { + // Chosen randomly. + // Pick a constant seed so that the same graph generates the same nodes every + // time. This is not a security-sensitive operation, it's just aliases for + // the graph nodes. + let mut rng = rand::rngs::SmallRng::seed_from_u64(4u64); + + let display_node = match is_single { + true => { + |node:&TaskNode| { + match node { + TaskNode::Root => node.to_string(), + TaskNode::Task(task) => task.task().to_string(), + } + } + }, + false => |node:&TaskNode| node.to_string(), + }; + + let mut edges = graph + .edge_references() + .map(|e| { + ( + display_node( + graph.node_weight(e.source()).expect("node index should exist in graph"), + ), + display_node( + graph.node_weight(e.target()).expect("node index should exist in graph"), + ), + ) + }) + .collect::>(); + edges.sort(); + + writeln!(writer, "graph TD")?; + let mut name_cache = HashMap::::new(); + for (src, target) in edges { + let src_name = name_cache.entry(src.clone()).or_insert_with(|| generate_id(&mut rng)); + write!(writer, "\t{src_name}(\"{src}\") --> ")?; + let target_name = name_cache.entry(target.clone()).or_insert_with(|| generate_id(&mut rng)); + writeln!(writer, "{target_name}(\"{target}\")")?; + } + Ok(()) +} diff --git a/crates/turborepo-lib/src/engine/mod.rs b/crates/turborepo-lib/Source/engine/mod.rs similarity index 100% rename from crates/turborepo-lib/src/engine/mod.rs rename to crates/turborepo-lib/Source/engine/mod.rs diff --git a/crates/turborepo-lib/src/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error-2.snap b/crates/turborepo-lib/Source/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error-2.snap similarity index 100% rename from crates/turborepo-lib/src/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error-2.snap rename to crates/turborepo-lib/Source/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error-2.snap diff --git a/crates/turborepo-lib/src/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error.snap b/crates/turborepo-lib/Source/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error.snap similarity index 100% rename from crates/turborepo-lib/src/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error.snap rename to crates/turborepo-lib/Source/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_exact_error.snap diff --git a/crates/turborepo-lib/src/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_invalid_package.snap b/crates/turborepo-lib/Source/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_invalid_package.snap similarity index 100% rename from crates/turborepo-lib/src/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_invalid_package.snap rename to crates/turborepo-lib/Source/engine/snapshots/turborepo_lib__engine__builder__test__run_package_task_invalid_package.snap diff --git a/crates/turborepo-lib/Source/framework.rs b/crates/turborepo-lib/Source/framework.rs new file mode 100644 index 0000000000000..5d519ac94f819 --- /dev/null +++ b/crates/turborepo-lib/Source/framework.rs @@ -0,0 +1,197 @@ +use std::sync::OnceLock; + +use serde::Deserialize; +use turborepo_repository::package_graph::PackageInfo; + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +enum Strategy { + All, + Some, +} + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +struct Matcher { + strategy:Strategy, + dependencies:Vec, +} + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Framework { + slug:String, + env_wildcards:Vec, + dependency_match:Matcher, +} + +impl Framework { + pub fn slug(&self) -> String { self.slug.clone() } + + pub fn env_wildcards(&self) -> &[String] { &self.env_wildcards } +} + +static FRAMEWORKS:OnceLock> = OnceLock::new(); + +const FRAMEWORKS_JSON:&str = include_str!("../../../packages/turbo-types/src/json/frameworks.json"); + +fn get_frameworks() -> &'static Vec { + FRAMEWORKS.get_or_init(|| { + serde_json::from_str(FRAMEWORKS_JSON).expect("Unable to parse embedded JSON") + }) +} + +impl Matcher { + pub fn test(&self, workspace:&PackageInfo, is_monorepo:bool) -> bool { + // In the case where we're not in a monorepo, i.e. single package mode + // `unresolved_external_dependencies` is not populated. In which + // case we should check `dependencies` instead. + let deps = if is_monorepo { + workspace.unresolved_external_dependencies.as_ref() + } else { + workspace.package_json.dependencies.as_ref() + }; + + match self.strategy { + Strategy::All => self + .dependencies + .iter() + .all(|dep| deps.is_some_and(|deps| deps.contains_key(dep))), + Strategy::Some => self + .dependencies + .iter() + .any(|dep| deps.is_some_and(|deps| deps.contains_key(dep))), + } + } +} + +pub fn infer_framework(workspace:&PackageInfo, is_monorepo:bool) -> Option<&Framework> { + let frameworks = get_frameworks(); + + frameworks + .iter() + .find(|framework| framework.dependency_match.test(workspace, is_monorepo)) +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + use turborepo_repository::{package_graph::PackageInfo, package_json::PackageJson}; + + use crate::framework::{Framework, get_frameworks, infer_framework}; + + fn get_framework_by_slug(slug:&str) -> &Framework { + get_frameworks() + .iter() + .find(|framework| framework.slug == slug) + .expect("framework not found") + } + + #[test_case(PackageInfo::default(), None, true; "empty dependencies")] + #[test_case( + PackageInfo { + unresolved_external_dependencies: Some( + vec![("blitz".to_string(), "*".to_string())].into_iter().collect() + ), + ..Default::default() + }, + Some(get_framework_by_slug("blitzjs")), + true; + "blitz" + )] + #[test_case( + PackageInfo { + unresolved_external_dependencies: Some( + vec![("blitz", "*"), ("next", "*")] + .into_iter() + .map(|(s1, s2)| (s1.to_string(), s2.to_string())) + .collect() + ), + ..Default::default() + }, + Some(get_framework_by_slug("blitzjs")), + true; + "Order is preserved (returns blitz, not next)" + )] + #[test_case( + PackageInfo { + unresolved_external_dependencies: Some( + vec![("next", "*")] + .into_iter() + .map(|(s1, s2)| (s1.to_string(), s2.to_string())) + .collect() + ), + ..Default::default() + }, + Some(get_framework_by_slug("nextjs")), + true; + "Finds next without blitz" + )] + #[test_case( + PackageInfo { + unresolved_external_dependencies: Some( + vec![("solid-js", "*"), ("solid-start", "*")] + .into_iter() + .map(|(s1, s2)| (s1.to_string(), s2.to_string())) + .collect() + ), + ..Default::default() + }, + Some(get_framework_by_slug("solidstart")), + true; + "match all strategy works (solid)" + )] + #[test_case( + PackageInfo { + unresolved_external_dependencies: Some( + vec![("nuxt3", "*")] + .into_iter() + .map(|(s1, s2)| (s1.to_string(), s2.to_string())) + .collect() + ), + ..Default::default() + }, + Some(get_framework_by_slug("nuxtjs")), + true; + "match some strategy works (nuxt)" + )] + #[test_case( + PackageInfo { + unresolved_external_dependencies: Some( + vec![("react-scripts", "*")] + .into_iter() + .map(|(s1, s2)| (s1.to_string(), s2.to_string())) + .collect() + ), + ..Default::default() + }, + Some(get_framework_by_slug("create-react-app")), + true; + "match some strategy works (create-react-app)" + )] + #[test_case( + PackageInfo { + package_json: PackageJson { + dependencies: Some( + vec![("next", "*")] + .into_iter() + .map(|(s1, s2)| (s1.to_string(), s2.to_string())) + .collect() + ), + ..Default::default() + }, + ..Default::default() + }, + Some(get_framework_by_slug("nextjs")), + false; + "Finds next in non-monorepo" + )] + fn test_infer_framework( + workspace_info:PackageInfo, + expected:Option<&Framework>, + is_monorepo:bool, + ) { + let framework = infer_framework(&workspace_info, is_monorepo); + assert_eq!(framework, expected); + } +} diff --git a/crates/turborepo-lib/src/gitignore.rs b/crates/turborepo-lib/Source/gitignore.rs similarity index 100% rename from crates/turborepo-lib/src/gitignore.rs rename to crates/turborepo-lib/Source/gitignore.rs diff --git a/crates/turborepo-lib/Source/global_deps_package_change_mapper.rs b/crates/turborepo-lib/Source/global_deps_package_change_mapper.rs new file mode 100644 index 0000000000000..8b3e5a39669f2 --- /dev/null +++ b/crates/turborepo-lib/Source/global_deps_package_change_mapper.rs @@ -0,0 +1,135 @@ +use thiserror::Error; +use turbopath::AnchoredSystemPath; +use turborepo_repository::{ + change_mapper::{DefaultPackageChangeMapper, PackageChangeMapper, PackageMapping}, + package_graph::{PackageGraph, WorkspacePackage}, +}; +use wax::{BuildError, Program}; + +#[derive(Error, Debug)] +pub enum Error { + #[error(transparent)] + InvalidFilter(#[from] BuildError), +} + +/// A package detector that uses a global deps list to determine +/// if a file should cause all packages to be marked as changed. +/// This is less conservative than the `DefaultPackageChangeMapper`, +/// which assumes that any changed file that is not in a package +/// changes all packages. Since we have a list of global deps, +/// we can check against that and avoid invalidating in unnecessary cases. +pub struct GlobalDepsPackageChangeMapper<'a> { + pkg_dep_graph:&'a PackageGraph, + global_deps_matcher:wax::Any<'a>, +} + +impl<'a> GlobalDepsPackageChangeMapper<'a> { + pub fn new, I:Iterator>( + pkg_dep_graph:&'a PackageGraph, + global_deps:I, + ) -> Result { + let global_deps_matcher = wax::any(global_deps)?; + + Ok(Self { pkg_dep_graph, global_deps_matcher }) + } +} + +impl<'a> PackageChangeMapper for GlobalDepsPackageChangeMapper<'a> { + fn detect_package(&self, path:&AnchoredSystemPath) -> PackageMapping { + match DefaultPackageChangeMapper::new(self.pkg_dep_graph).detect_package(path) { + // Since `DefaultPackageChangeMapper` is overly conservative, we can check here if + // the path is actually in globalDeps and if not, return it as + // PackageDetection::Package(WorkspacePackage::root()). + PackageMapping::All => { + let cleaned_path = path.clean(); + let in_global_deps = self.global_deps_matcher.is_match(cleaned_path.as_str()); + + if in_global_deps { + PackageMapping::All + } else { + PackageMapping::Package(WorkspacePackage::root()) + } + }, + result => result, + } + } +} + +#[cfg(test)] +mod tests { + use tempfile::tempdir; + use turbopath::{AbsoluteSystemPath, AnchoredSystemPathBuf}; + use turborepo_repository::{ + change_mapper::{ChangeMapper, DefaultPackageChangeMapper, PackageChanges}, + discovery, + discovery::PackageDiscovery, + package_graph::{PackageGraphBuilder, WorkspacePackage}, + package_json::PackageJson, + }; + + use super::GlobalDepsPackageChangeMapper; + + #[allow(dead_code)] + pub struct MockDiscovery; + + impl PackageDiscovery for MockDiscovery { + async fn discover_packages( + &self, + ) -> Result { + Ok(discovery::DiscoveryResponse { + package_manager:turborepo_repository::package_manager::PackageManager::Npm, + workspaces:vec![], + }) + } + + async fn discover_packages_blocking( + &self, + ) -> Result { + self.discover_packages().await + } + } + + #[tokio::test] + async fn test_different_package_detectors() -> Result<(), anyhow::Error> { + let repo_root = tempdir()?; + let root_package_json = PackageJson::default(); + + let pkg_graph = PackageGraphBuilder::new( + AbsoluteSystemPath::from_std_path(repo_root.path())?, + root_package_json, + ) + .with_package_discovery(MockDiscovery) + .build() + .await?; + + let default_package_detector = DefaultPackageChangeMapper::new(&pkg_graph); + let change_mapper = ChangeMapper::new(&pkg_graph, vec![], default_package_detector); + + let package_changes = change_mapper.changed_packages( + [AnchoredSystemPathBuf::from_raw("README.md")?].into_iter().collect(), + None, + )?; + + // We should return All because we don't have global deps and + // therefore must be conservative about changes + assert_eq!(package_changes, PackageChanges::All); + + let turbo_package_detector = + GlobalDepsPackageChangeMapper::new(&pkg_graph, std::iter::empty::<&str>())?; + let change_mapper = ChangeMapper::new(&pkg_graph, vec![], turbo_package_detector); + + let package_changes = change_mapper.changed_packages( + [AnchoredSystemPathBuf::from_raw("README.md")?].into_iter().collect(), + None, + )?; + + // We only get a root workspace change since we have global deps specified and + // README.md is not one of them + assert_eq!( + package_changes, + PackageChanges::Some([WorkspacePackage::root()].into_iter().collect()) + ); + + Ok(()) + } +} diff --git a/crates/turborepo-lib/Source/globwatcher/mod.rs b/crates/turborepo-lib/Source/globwatcher/mod.rs new file mode 100644 index 0000000000000..b8a938a895856 --- /dev/null +++ b/crates/turborepo-lib/Source/globwatcher/mod.rs @@ -0,0 +1,677 @@ +use std::{ + collections::{HashMap, HashSet, hash_map::Entry}, + path::{Path, PathBuf}, + sync::{Arc, Mutex, MutexGuard}, + time::Duration, +}; + +use futures::{StreamExt, stream::iter}; +use globwatch::{ConfigError, GlobWatcher, StopToken, WatchConfig, WatchError, Watcher}; +use itertools::Itertools; +use notify::{EventKind, RecommendedWatcher}; +use thiserror::Error; +use tokio::time::timeout; +use tracing::{trace, warn}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathError}; +use wax::{Glob as WaxGlob, Program}; + +// these aliases are for readability, but they're just strings. it may make +// sense to use a newtype wrapper for these types in the future. +type Glob = Arc; +type Hash = Arc; + +/// timeout for flushing the watcher +const FLUSH_TIMEOUT:Duration = Duration::from_millis(500); + +/// Tracks changes for a given hash. A hash is a unique identifier for a set of +/// files. Given a hash and a set of globs to track, this will watch for file +/// changes and allow the user to query for changes. Once all globs for a +/// particular hash have changed, that hash is no longer tracked. +#[derive(Clone)] +pub struct HashGlobWatcher { + relative_to:PathBuf, + + /// maintains the list of to watch for a given hash + hash_globs:Arc>>, + + /// maps a glob to the hashes for which this glob hasn't changed + glob_statuses:Arc>>>, + + #[allow(dead_code)] + watcher:Arc>>, + config:WatchConfig, +} + +#[derive(Clone, Debug)] +pub struct GlobSet { + include:HashSet, + exclude:HashSet, +} + +#[derive(Debug, Error)] +pub enum HashGlobSetupError { + #[error("failed to start tracking hash-globs {0}")] + WatchError(#[from] WatchError), + #[error("failed to calculate relative path for hash-glob watching ({1}): {0}")] + PathError(PathError, AbsoluteSystemPathBuf), +} + +impl HashGlobWatcher { + #[tracing::instrument] + pub fn new( + relative_to:&AbsoluteSystemPath, + flush_folder:&AbsoluteSystemPath, + ) -> Result { + let (watcher, config) = GlobWatcher::new(flush_folder)?; + let relative_to = relative_to + .to_realpath() + .map_err(|e| HashGlobSetupError::PathError(e, relative_to.to_owned()))? + .as_std_path() + .to_owned(); + Ok(Self { + relative_to, + hash_globs:Default::default(), + glob_statuses:Default::default(), + watcher:Arc::new(Mutex::new(Some(watcher))), + config, + }) + } +} + +impl HashGlobWatcher { + /// Watches a given path, using the flush_folder as temporary storage to + /// make sure that file events are handled in the appropriate order. + #[tracing::instrument(skip(self, token))] + pub async fn watch(&self, token:StopToken) -> Result<(), ConfigError> { + let start_globs = { + let lock = self.hash_globs.lock().expect("only fails if poisoned"); + lock.iter().flat_map(|(_, g)| &g.include).cloned().collect::>() + }; + + let watcher = self.watcher.lock().expect("only fails if poisoned").take(); + let mut stream = match watcher { + Some(watcher) => watcher.into_stream(token), + None => { + warn!("watcher already consumed"); + return Err(ConfigError::WatchingAlready); + }, + }; + + // watch the root of the repo to shut down if the folder is deleted + self.config.include_path(&self.relative_to).await?; + + // watch all the globs currently in the map + for glob in start_globs { + self.config.include(&self.relative_to, &glob).await.ok(); + } + + while let Some(Ok(result)) = stream.next().await { + let event = result?; + if event.paths.contains(&self.relative_to) && matches!(event.kind, EventKind::Remove(_)) + { + // if the root of the repo is deleted, we shut down + trace!("repo root was removed, shutting down"); + break; + } + + let repo_relative_paths = + event.paths.iter().filter_map(|path| path.strip_prefix(&self.relative_to).ok()); + + // put these in a block so we can drop the locks before we await + let globs_to_exclude = { + let glob_statuses = self.glob_statuses.lock().expect("only fails if poisoned"); + let hash_globs = self.hash_globs.lock().expect("only fails if poisoned"); + + // hash globs is unlocked after this + let (hash_globs_to_clear, globs_to_exclude) = + populate_hash_globs(&glob_statuses, repo_relative_paths, hash_globs); + + // glob_statuses is unlocked after this + clear_hash_globs(glob_statuses, hash_globs_to_clear); + + globs_to_exclude + }; + + for glob in globs_to_exclude { + self.config.exclude(&self.relative_to, &glob).await; + } + } + + Ok(()) + } + + /// registers a hash with a set of globs to watch for changes + pub async fn watch_globs< + Iter:IntoIterator, + Iter2:IntoIterator, + >( + &self, + hash:Hash, + include:Iter, + exclude:Iter2, + ) -> Result<(), ConfigError> { + // wait for a the watcher to flush its events + // that will ensure that we have seen all filesystem writes + // *by the calling client*. Other tasks _could_ write to the + // same output directories, however we are relying on task + // execution dependencies to prevent that. + // + // this is a best effort, and times out after 500ms in + // case there is a lot of activity on the filesystem + match timeout(FLUSH_TIMEOUT, self.config.flush()).await { + Ok(Ok(())) => {}, + Ok(Err(e)) => { + return Err(e); + }, + Err(_) => { + trace!("timed out waiting for flush"); + }, + } + + let include:HashSet<_> = include.into_iter().map(Arc::new).collect(); + let exclude = exclude.into_iter().map(Arc::new).collect(); + + let result:Vec<(Glob, ConfigError)> = iter(include.iter()) + .then(|glob| { + async move { + (glob.clone(), self.config.include(self.relative_to.as_path(), glob).await) + } + }) + .filter_map(|(glob, res)| { + async { + match res { + Ok(_) => None, + Err(err) => Some((glob, err)), + } + } + }) + .collect() + .await; + + { + let mut glob_statuses = self.glob_statuses.lock().expect("only fails if poisoned"); + for glob in include.iter() { + glob_statuses.entry(glob.clone()).or_default().insert(hash.clone()); + } + } + + { + let mut hash_globs = self.hash_globs.lock().expect("only fails if poisoned"); + hash_globs.insert(hash.clone(), GlobSet { include, exclude }); + } + + if !result.is_empty() { + // we now 'undo' the failed watches if we encountered errors watching any + // globs, and return an error + + let hash_globs_to_clear = + result.iter().map(|(glob, _)| (hash.clone(), glob.clone())).collect(); + + let glob_statuses = self.glob_statuses.lock().expect("only fails if poisoned"); + // mutex is consumedd here + clear_hash_globs(glob_statuses, hash_globs_to_clear); + + use ConfigError::*; + Err(result.into_iter().fold(WatchError(vec![]), |acc, (_, err)| { + // accumulate any watch errors, but override if the server stopped + match (acc, err) { + (WatchError(_), ServerStopped) => ServerStopped, + (WatchError(files), WatchError(files2)) => { + WatchError(files.into_iter().chain(files2).collect()) + }, + (err, _) => err, + } + })) + } else { + Ok(()) + } + } + + /// given a hash and a set of candidates, return the subset of candidates + /// that have changed. + pub async fn changed_globs( + &self, + hash:&Hash, + mut candidates:HashSet, + ) -> Result, ConfigError> { + // wait for a the watcher to flush its events + // that will ensure that we have seen all filesystem writes + // *by the calling client*. Other tasks _could_ write to the + // same output directories, however we are relying on task + // execution dependencies to prevent that. + // + // this is a best effort, and times out after 500ms in + // case there is a lot of activity on the filesystem + match timeout(FLUSH_TIMEOUT, self.config.flush()).await { + Ok(Ok(())) => {}, + Ok(Err(e)) => return Err(e), + Err(_) => { + trace!("timed out waiting for flush"); + }, + } + + // hash_globs tracks all unchanged globs for a given hash. + // if a hash is not in globs, then either everything has changed + // or it was never registered. either way, we return all candidates + let hash_globs = self.hash_globs.lock().expect("only fails if poisoned"); + Ok(match hash_globs.get(hash) { + Some(glob) => { + candidates.retain(|c| !glob.include.contains(c)); + candidates + }, + None => candidates, + }) + } +} + +/// iterate each path-glob pair and stop tracking globs whose files have +/// changed. if a path is not a valid utf8 string, it is ignored. this is +/// okay, because we don't register any paths that are not valid utf8, +/// since the source globs are valid utf8 +/// +/// returns a list of hash-glob pairs to clear, and a list of globs to exclude +/// +/// note: we take a mutex guard to make sure that the mutex is dropped +/// when the function returns +#[allow(dead_code)] +#[allow(clippy::type_complexity)] +fn populate_hash_globs<'a>( + glob_statuses:&MutexGuard>>, + repo_relative_paths:impl Iterator + Clone, + mut hash_globs:MutexGuard>, +) -> (Vec<(Arc, Arc)>, Vec>) { + let mut clear_glob_status = vec![]; + let mut exclude_globs = vec![]; + + // for every path, check to see if it matches any of the globs + // if it does, then we need to stop watching that glob + for ((glob, hash_status), path) in glob_statuses + .iter() + .cartesian_product(repo_relative_paths) + .filter(|((glob, _), path)| { + let glob = WaxGlob::new(glob).expect("only watch valid globs"); + glob.is_match(*path) + }) { + let mut stop_watching = true; + + // for every hash that includes this glob, check to see if the glob + // has changed for that hash. if it has, then we need to stop watching + for hash in hash_status.iter() { + let globs = match hash_globs.get_mut(hash).filter(|globs| { + !globs.exclude.iter().any(|glob| { + let glob = WaxGlob::new(glob).expect("only watch valid globs"); + glob.is_match(path) + }) + }) { + Some(globs) => globs, + None => { + // if we get here, then the hash is excluded by a glob + // so we don't need to stop watching this glob + stop_watching = false; + continue; + }, + }; + + // if we get here, we know that the glob has changed for every hash that + // included this glob and is not excluded by a hash's exclusion globs. + // So, we can delete this glob from every hash tracking it as well as stop + // watching this glob. To stop watching, we unref each of the + // directories corresponding to this glob + + // we can stop tracking that glob + globs.include.remove(glob); + if globs.include.is_empty() { + hash_globs.remove(hash); + } + + clear_glob_status.push((hash.clone(), glob.clone())); + } + + if stop_watching { + // store the hash and glob so we can remove it from the glob_status + exclude_globs.push(glob.to_owned()); + } + } + + (clear_glob_status, exclude_globs) +} + +/// given a list of hash-glob pairs to stop tracking, remove them from the +/// map and remove the entry if the set of globs for that hash is empty +/// +/// note: we take a mutex guard to make sure that the mutex is dropped +/// when the function returns +fn clear_hash_globs( + mut glob_status:MutexGuard>>, + hash_globs_to_clear:Vec<(Hash, Glob)>, +) { + for (hash, glob) in hash_globs_to_clear { + if let Entry::Occupied(mut o) = glob_status.entry(glob) { + let val = o.get_mut(); + val.remove(&hash); + if val.is_empty() { + o.remove(); + } + }; + } +} + +#[cfg(test)] +mod test { + use std::{sync::Arc, time::Duration}; + + use globwatch::StopSource; + use tokio::time::timeout; + use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, RelativeUnixPathBuf}; + + fn temp_dir() -> (AbsoluteSystemPathBuf, tempfile::TempDir) { + let tmp = tempfile::tempdir().unwrap(); + let path = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap(); + (path, tmp) + } + + fn setup(tmp:&AbsoluteSystemPath) { + let directories = ["my-pkg/dist/distChild", "my-pkg/.next/cache"]; + + let files = [ + "my-pkg/dist/distChild/dist-file", + "my-pkg/dist/dist-file", + "my-pkg/.next/next-file", + "my-pkg/irrelevant", + ]; + + for dir in directories.iter() { + let dir = RelativeUnixPathBuf::new(*dir).unwrap(); + tmp.join_unix_path(&dir).create_dir_all().unwrap(); + } + + for file in files.iter() { + let file = RelativeUnixPathBuf::new(*file).unwrap(); + tmp.join_unix_path(&file).create_with_contents("").unwrap(); + } + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn track_outputs() { + let (dir, _tmp_dir) = temp_dir(); + setup(&dir); + let (flush, _tmp_flush) = temp_dir(); + let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); + + let stop = StopSource::new(); + + let task_watcher = watcher.clone(); + let token = stop.token(); + + // dropped when the test ends + let _s = tokio::task::spawn(async move { task_watcher.watch(token).await }); + + let hash = Arc::new("the-hash".to_string()); + let include = ["my-pkg/dist/**".to_string(), "my-pkg/.next/**".to_string()]; + let exclude = ["my-pkg/.next/cache/**".to_string()]; + + println!("{:?} {:?}", include, exclude); + + watcher + .watch_globs(hash.clone(), include.clone(), exclude.clone()) + .await + .unwrap(); + + let changed = watcher + .changed_globs(&hash, include.clone().into_iter().collect()) + .await + .unwrap(); + + assert!(changed.is_empty(), "expected no changed globs, got {:?}", changed); + + // change a file that is neither included nor excluded + + dir.join_components(&["my-pkg", "irrelevant2"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash, include.clone().into_iter().collect()) + .await + .unwrap(); + + assert!(changed.is_empty(), "expected no changed globs, got {:?}", changed); + + // change a file that is excluded + + dir.join_components(&["my-pkg", ".next", "cache", "next-file2"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash, include.clone().into_iter().collect()) + .await + .unwrap(); + + assert!(changed.is_empty(), "expected no changed globs, got {:?}", changed); + + // change a file that is included + + dir.join_components(&["my-pkg", "dist", "dist-file2"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash, include.clone().into_iter().collect()) + .await + .unwrap(); + + assert_eq!( + changed, + ["my-pkg/dist/**".to_string()].into_iter().collect(), + "expected one of the globs to have changed" + ); + + // change a file that is included but with a subdirectory that is excluded + // now both globs should be marked as changed + + dir.join_components(&["my-pkg", ".next", "next-file2"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash, include.clone().into_iter().collect()) + .await + .unwrap(); + + assert_eq!(changed, include.into_iter().collect(), "expected both globs to have changed"); + + assert!( + watcher.hash_globs.lock().unwrap().is_empty(), + "we should no longer be watching any hashes" + ); + + assert!( + watcher.glob_statuses.lock().unwrap().is_empty(), + "we should no longer be watching any globs: {:?}", + watcher.glob_statuses.lock().unwrap() + ); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn test_multiple_hashes() { + let (dir, _tmp_dir) = temp_dir(); + setup(&dir); + let (flush, _tmp_flush) = temp_dir(); + let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); + + let stop = StopSource::new(); + + let task_watcher = watcher.clone(); + let token = stop.token(); + + // dropped when the test ends + let _s = tokio::task::spawn(async move { task_watcher.watch(token).await }); + + let hash1 = Arc::new("the-hash-1".to_string()); + let hash2 = Arc::new("the-hash-2".to_string()); + + let globs1_inclusion = ["my-pkg/dist/**".to_string(), "my-pkg/.next/**".to_string()]; + let globs2_inclusion = ["my-pkg/.next/**".to_string()]; + let globs2_exclusion = ["my-pkg/.next/cache/**".to_string()]; + + watcher + .watch_globs(hash1.clone(), globs1_inclusion.clone(), vec![]) + .await + .unwrap(); + + watcher + .watch_globs(hash2.clone(), globs2_inclusion.clone(), globs2_exclusion.clone()) + .await + .unwrap(); + + let changed = watcher + .changed_globs(&hash1, globs1_inclusion.clone().into_iter().collect()) + .await + .unwrap(); + + assert!(changed.is_empty(), "expected no changed globs, got {:?}", changed); + + let changed = watcher + .changed_globs(&hash2, globs2_inclusion.clone().into_iter().collect()) + .await + .unwrap(); + + assert!(changed.is_empty(), "expected no changed globs, got {:?}", changed); + + // make a change excluded in only one of the hashes + + dir.join_components(&["my-pkg", ".next", "cache", "next-file2"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash1, globs1_inclusion.clone().into_iter().collect()) + .await + .unwrap(); + + assert_eq!( + changed, + ["my-pkg/.next/**".to_string()].into_iter().collect(), + "expected one of the globs to have changed" + ); + + let changed = watcher + .changed_globs(&hash2, globs2_inclusion.clone().into_iter().collect()) + .await + .unwrap(); + + assert!(changed.is_empty(), "expected no changed globs, got {:?}", changed); + + // make a change for the other hash + + dir.join_components(&["my-pkg", ".next", "next-file2"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash2, globs2_inclusion.clone().into_iter().collect()) + .await + .unwrap(); + + assert_eq!( + changed, + ["my-pkg/.next/**".to_string()].into_iter().collect(), + "expected one of the globs to have changed" + ); + + assert_eq!( + watcher.hash_globs.lock().unwrap().keys().len(), + 1, + "we should be watching one hash, got {:?}", + watcher.hash_globs.lock().unwrap() + ); + + assert_eq!( + watcher.glob_statuses.lock().unwrap().keys().len(), + 1, + "we should be watching one glob, got {:?}", + watcher.glob_statuses.lock().unwrap() + ); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn watch_single_file() { + let (dir, _tmp_dir) = temp_dir(); + setup(&dir); + let (flush, _tmp_flush) = temp_dir(); + let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); + + let stop = StopSource::new(); + + let task_watcher = watcher.clone(); + let token = stop.token(); + + // dropped when the test ends + let _s = tokio::task::spawn(async move { task_watcher.watch(token).await }); + + let hash = Arc::new("the-hash".to_string()); + let inclusions = ["my-pkg/.next/next-file".to_string()]; + + watcher.watch_globs(hash.clone(), inclusions.clone(), vec![]).await.unwrap(); + + dir.join_components(&["my-pkg", ".next", "irrelevant"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash, inclusions.clone().into_iter().collect()) + .await + .unwrap(); + + assert!(changed.is_empty(), "expected no changed globs, got {:?}", changed); + + dir.join_components(&["my-pkg", ".next", "next-file"]) + .create_with_contents("") + .unwrap(); + let changed = watcher + .changed_globs(&hash, inclusions.clone().into_iter().collect()) + .await + .unwrap(); + + assert_eq!( + changed, + inclusions.clone().into_iter().collect(), + "expected one of the globs to have changed" + ); + + assert!( + watcher.hash_globs.lock().unwrap().is_empty(), + "we should no longer be watching any hashes" + ); + + assert!( + watcher.glob_statuses.lock().unwrap().is_empty(), + "we should no longer be watching any globs: {:?}", + watcher.glob_statuses.lock().unwrap() + ); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn delete_root_kill_daemon() { + let (dir, _tmp_dir) = temp_dir(); + setup(&dir); + let (flush, _tmp_flush) = temp_dir(); + let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); + + let stop = StopSource::new(); + + let task_watcher = watcher.clone(); + let token = stop.token(); + + // dropped when the test ends + let task = tokio::task::spawn(async move { task_watcher.watch(token).await }); + tokio::time::sleep(Duration::from_secs(3)).await; + watcher.config.flush().await.unwrap(); + dir.remove_dir_all().unwrap(); + + // it should shut down + match timeout(Duration::from_secs(60), task).await { + Err(e) => panic!("test timed out: {e}"), + Ok(Err(e)) => panic!("expected task to finish when root is deleted: {e}"), + _ => (), + } + } +} diff --git a/crates/turborepo-lib/Source/hash/mod.rs b/crates/turborepo-lib/Source/hash/mod.rs new file mode 100644 index 0000000000000..741ad1114223f --- /dev/null +++ b/crates/turborepo-lib/Source/hash/mod.rs @@ -0,0 +1,472 @@ +//! hash module +//! +//! This module contains the hash functions used by turborepo for certain +//! data-types. This is managed using capnproto for deterministic hashing across +//! languages and platforms. + +mod traits; + +use std::collections::HashMap; + +use capnp::message::{Builder, HeapAllocator}; +pub use traits::TurboHash; +use turborepo_env::EnvironmentVariablePairs; + +use crate::{cli::EnvMode, task_graph::TaskOutputs}; + +mod proto_capnp { + + use crate::cli::EnvMode; + + include!(concat!(env!("OUT_DIR"), "/src/hash/proto_capnp.rs")); + + impl From for global_hashable::EnvMode { + fn from(value:EnvMode) -> Self { + match value { + EnvMode::Loose => global_hashable::EnvMode::Loose, + EnvMode::Strict => global_hashable::EnvMode::Strict, + } + } + } + + impl From for task_hashable::EnvMode { + fn from(value:EnvMode) -> Self { + match value { + EnvMode::Loose => task_hashable::EnvMode::Loose, + EnvMode::Strict => task_hashable::EnvMode::Strict, + } + } + } +} + +#[derive(Debug)] +pub struct TaskHashable<'a> { + // hashes + pub(crate) global_hash:&'a str, + pub(crate) task_dependency_hashes:Vec, + pub(crate) hash_of_files:&'a str, + pub(crate) external_deps_hash:Option, + + // task + pub(crate) package_dir:Option, + pub(crate) task:&'a str, + pub(crate) outputs:TaskOutputs, + pub(crate) pass_through_args:&'a [String], + + // env + pub(crate) env:&'a [String], + pub(crate) resolved_env_vars:EnvVarPairs, + pub(crate) pass_through_env:&'a [String], + pub(crate) env_mode:EnvMode, +} + +#[derive(Debug, Clone)] +pub struct GlobalHashable<'a> { + pub global_cache_key:&'static str, + pub global_file_hash_map:&'a HashMap, + // These are None in single package mode + pub root_external_dependencies_hash:Option<&'a str>, + pub root_internal_dependencies_hash:Option<&'a str>, + pub engines:HashMap<&'a str, &'a str>, + pub env:&'a [String], + pub resolved_env_vars:EnvironmentVariablePairs, + pub pass_through_env:&'a [String], + pub env_mode:EnvMode, + pub framework_inference:bool, +} + +pub struct LockFilePackages(pub Vec); + +#[derive(Debug, Clone)] +pub struct FileHashes(pub HashMap); + +impl From for Builder { + fn from(value:TaskOutputs) -> Self { + let mut message = ::capnp::message::TypedBuilder::< + proto_capnp::task_outputs::Owned, + HeapAllocator, + >::new_default(); + let mut builder = message.init_root(); + + { + let mut inclusions = builder.reborrow().init_inclusions(value.inclusions.len() as u32); + for (i, inclusion) in value.inclusions.iter().enumerate() { + inclusions.set(i as u32, inclusion); + } + } + + { + let mut exclusions = builder.reborrow().init_exclusions(value.exclusions.len() as u32); + for (i, exclusion) in value.exclusions.iter().enumerate() { + exclusions.set(i as u32, exclusion); + } + } + + message.into_inner() + } +} + +impl From for Builder { + fn from(LockFilePackages(packages):LockFilePackages) -> Self { + let mut message = ::capnp::message::TypedBuilder::< + proto_capnp::lock_file_packages::Owned, + HeapAllocator, + >::new_default(); + let mut builder = message.init_root(); + + { + let mut packages_builder = builder.reborrow().init_packages(packages.len() as u32); + for (i, turborepo_lockfiles::Package { key, version }) in packages.iter().enumerate() { + let mut package = packages_builder.reborrow().get(i as u32); + package.set_key(key); + package.set_version(version); + // we don't track this in rust, set it to true + package.set_found(true); + } + } + + // We're okay to unwrap here because we haven't hit the nesting + // limit and the message will not have cycles. + let size = builder.total_size().expect("unable to calculate total size").word_count + 1; // + 1 to solve an off by one error inside capnp + let mut canon_builder = + Builder::new(HeapAllocator::default().first_segment_words(size as u32)); + canon_builder + .set_root_canonical(builder.reborrow_as_reader()) + .expect("can't fail"); + + canon_builder + } +} + +impl From for Builder { + fn from(FileHashes(file_hashes):FileHashes) -> Self { + let mut message = ::capnp::message::TypedBuilder::< + proto_capnp::file_hashes::Owned, + HeapAllocator, + >::new_default(); + let mut builder = message.init_root(); + + { + let mut entries = builder.reborrow().init_file_hashes(file_hashes.len() as u32); + + // get a sorted iterator over keys and values of the hashmap + // and set the entries in the capnp message + + let mut hashable:Vec<_> = file_hashes.into_iter().collect(); + hashable.sort_by(|(path_a, _), (path_b, _)| path_a.cmp(path_b)); + + for (i, (key, value)) in hashable.iter().enumerate() { + let mut entry = entries.reborrow().get(i as u32); + entry.set_key(key.as_str()); + entry.set_value(value); + } + } + + // We're okay to unwrap here because we haven't hit the nesting + // limit and the message will not have cycles. + let size = builder.total_size().expect("unable to calculate total size").word_count + 1; // + 1 to solve an off by one error inside capnp + let mut canon_builder = + Builder::new(HeapAllocator::default().first_segment_words(size as u32)); + canon_builder + .set_root_canonical(builder.reborrow_as_reader()) + .expect("can't fail"); + + canon_builder + } +} + +type EnvVarPairs = Vec; + +impl From> for Builder { + fn from(task_hashable:TaskHashable) -> Self { + let mut message = + ::capnp::message::TypedBuilder::::new_default(); + let mut builder = message.init_root(); + + builder.set_global_hash(task_hashable.global_hash); + if let Some(package_dir) = task_hashable.package_dir { + builder.set_package_dir(&package_dir.to_string()); + } + + builder.set_hash_of_files(task_hashable.hash_of_files); + if let Some(external_deps_hash) = task_hashable.external_deps_hash { + builder.set_external_deps_hash(&external_deps_hash); + } + + builder.set_task(task_hashable.task); + builder.set_env_mode(task_hashable.env_mode.into()); + + { + let output_builder:Builder<_> = task_hashable.outputs.into(); + builder.set_outputs(output_builder.get_root_as_reader().unwrap()).unwrap(); + } + + { + let mut task_dependency_hashes_builder = builder + .reborrow() + .init_task_dependency_hashes(task_hashable.task_dependency_hashes.len() as u32); + for (i, hash) in task_hashable.task_dependency_hashes.iter().enumerate() { + task_dependency_hashes_builder.set(i as u32, hash); + } + } + + { + let mut pass_through_args_builder = builder + .reborrow() + .init_pass_thru_args(task_hashable.pass_through_args.len() as u32); + for (i, arg) in task_hashable.pass_through_args.iter().enumerate() { + pass_through_args_builder.set(i as u32, arg); + } + } + + { + let mut env_builder = builder.reborrow().init_env(task_hashable.env.len() as u32); + for (i, env) in task_hashable.env.iter().enumerate() { + env_builder.set(i as u32, env); + } + } + + { + let mut pass_through_env_builder = builder + .reborrow() + .init_pass_thru_env(task_hashable.pass_through_env.len() as u32); + for (i, env) in task_hashable.pass_through_env.iter().enumerate() { + pass_through_env_builder.set(i as u32, env); + } + } + + { + let mut resolved_env_vars_builder = builder + .reborrow() + .init_resolved_env_vars(task_hashable.resolved_env_vars.len() as u32); + for (i, env) in task_hashable.resolved_env_vars.iter().enumerate() { + resolved_env_vars_builder.set(i as u32, env); + } + } + + // We're okay to unwrap here because we haven't hit the nesting + // limit and the message will not have cycles. + let size = builder.total_size().expect("unable to calculate total size").word_count + 1; // + 1 to solve an off by one error inside capnp + let mut canon_builder = + Builder::new(HeapAllocator::default().first_segment_words(size as u32)); + canon_builder + .set_root_canonical(builder.reborrow_as_reader()) + .expect("can't fail"); + + canon_builder + } +} + +impl From> for Builder { + fn from(hashable:GlobalHashable) -> Self { + let mut message = + ::capnp::message::TypedBuilder::::new_default(); + + let mut builder = message.init_root(); + + builder.set_global_cache_key(hashable.global_cache_key); + + { + let mut entries = builder + .reborrow() + .init_global_file_hash_map(hashable.global_file_hash_map.len() as u32); + + // get a sorted iterator over keys and values of the hashmap + // and set the entries in the capnp message + + let mut hashable:Vec<_> = hashable.global_file_hash_map.iter().collect(); + hashable.sort_by(|a, b| a.0.cmp(b.0)); + + for (i, (key, value)) in hashable.iter().enumerate() { + let mut entry = entries.reborrow().get(i as u32); + entry.set_key(key.as_str()); + entry.set_value(value); + } + } + + { + let mut entries = builder.reborrow().init_engines(hashable.engines.len() as u32); + + // get a sorted iterator over keys and values of the hashmap + // and set the entries in the capnp message + + let mut hashable:Vec<_> = hashable.engines.iter().collect(); + hashable.sort_by(|a, b| a.0.cmp(b.0)); + + for (i, (key, value)) in hashable.iter().enumerate() { + let mut entry = entries.reborrow().get(i as u32); + entry.set_key(key); + entry.set_value(value); + } + } + + if let Some(root_external_dependencies_hash) = hashable.root_external_dependencies_hash { + builder.set_root_external_deps_hash(root_external_dependencies_hash); + } + + if let Some(root_internal_dependencies_hash) = hashable.root_internal_dependencies_hash { + builder.set_root_internal_deps_hash(root_internal_dependencies_hash); + } + + { + let mut entries = builder.reborrow().init_env(hashable.env.len() as u32); + for (i, env) in hashable.env.iter().enumerate() { + entries.set(i as u32, env); + } + } + + { + let mut resolved_env_vars = builder + .reborrow() + .init_resolved_env_vars(hashable.resolved_env_vars.len() as u32); + for (i, env) in hashable.resolved_env_vars.iter().enumerate() { + resolved_env_vars.set(i as u32, env); + } + } + + { + let mut pass_through_env = + builder.reborrow().init_pass_through_env(hashable.pass_through_env.len() as u32); + for (i, env) in hashable.pass_through_env.iter().enumerate() { + pass_through_env.set(i as u32, env); + } + } + + builder.set_env_mode(match hashable.env_mode { + EnvMode::Loose => proto_capnp::global_hashable::EnvMode::Loose, + EnvMode::Strict => proto_capnp::global_hashable::EnvMode::Strict, + }); + + builder.set_framework_inference(hashable.framework_inference); + + // We're okay to unwrap here because we haven't hit the nesting + // limit and the message will not have cycles. + let size = builder.total_size().expect("unable to calculate total size").word_count + 1; // + 1 to solve an off by one error inside capnp + let mut canon_builder = + Builder::new(HeapAllocator::default().first_segment_words(size as u32)); + canon_builder + .set_root_canonical(builder.reborrow_as_reader()) + .expect("can't fail"); + + canon_builder + } +} + +#[cfg(test)] +mod test { + use test_case::test_case; + use turborepo_lockfiles::Package; + + use super::{ + FileHashes, + GlobalHashable, + LockFilePackages, + TaskHashable, + TaskOutputs, + TurboHash, + }; + use crate::cli::EnvMode; + + #[test] + fn task_hashable() { + let task_hashable = TaskHashable { + global_hash:"global_hash", + task_dependency_hashes:vec!["task_dependency_hash".to_string()], + package_dir:Some(turbopath::RelativeUnixPathBuf::new("package_dir").unwrap()), + hash_of_files:"hash_of_files", + external_deps_hash:Some("external_deps_hash".to_string()), + task:"task", + outputs:TaskOutputs { + inclusions:vec!["inclusions".to_string()], + exclusions:vec!["exclusions".to_string()], + }, + pass_through_args:&["pass_thru_args".to_string()], + env:&["env".to_string()], + resolved_env_vars:vec![], + pass_through_env:&["pass_thru_env".to_string()], + env_mode:EnvMode::Loose, + }; + + assert_eq!(task_hashable.hash(), "1f8b13161f57fca1"); + } + + #[test] + fn global_hashable() { + let global_file_hash_map = vec![( + turbopath::RelativeUnixPathBuf::new("global_file_hash_map").unwrap(), + "global_file_hash_map".to_string(), + )] + .into_iter() + .collect(); + + let global_hash = GlobalHashable { + global_cache_key:"global_cache_key", + global_file_hash_map:&global_file_hash_map, + root_external_dependencies_hash:Some("0000000000000000"), + root_internal_dependencies_hash:Some("0000000000000001"), + engines:Default::default(), + env:&["env".to_string()], + resolved_env_vars:vec![], + pass_through_env:&["pass_through_env".to_string()], + env_mode:EnvMode::Strict, + framework_inference:true, + }; + + assert_eq!(global_hash.hash(), "5072bd005ec02799"); + } + + #[test_case(vec![], "459c029558afe716" ; "empty")] + #[test_case(vec![Package { + key: "key".to_string(), + version: "version".to_string(), + }], "1b266409f3ae154e" ; "non-empty")] + #[test_case(vec![Package { + key: "key".to_string(), + version: "".to_string(), + }], "bde280722f61644a" ; "empty version")] + #[test_case(vec![Package { + key: "key".to_string(), + version: "version".to_string(), + }, Package { + key: "zey".to_string(), + version: "version".to_string(), + }], "6c0185544234b6dc" ; "multiple in-order")] + #[test_case(vec![Package { + key: "zey".to_string(), + version: "version".to_string(), + }, Package { + key: "key".to_string(), + version: "version".to_string(), + }], "26a67c9beeb0d16f" ; "care about order")] + fn lock_file_packages(vec:Vec, expected:&str) { + let packages = LockFilePackages(vec); + assert_eq!(packages.hash(), expected); + } + + #[test] + fn long_lock_file_packages() { + let packages = + (0..100).map(|i| Package { key:format!("key{}", i), version:format!("version{}", i) }); + + lock_file_packages(packages.collect(), "4fd770c37194168e"); + } + + #[test_case(vec![], "459c029558afe716" ; "empty")] + #[test_case(vec![ + ("a".to_string(), "b".to_string()), + ("c".to_string(), "d".to_string()), + ], "c9301c0bf1899c07" ; "non-empty")] + #[test_case(vec![ + ("c".to_string(), "d".to_string()), + ("a".to_string(), "b".to_string()), + ], "c9301c0bf1899c07" ; "order resistant")] + fn file_hashes(pairs:Vec<(String, String)>, expected:&str) { + let file_hashes = FileHashes( + pairs + .into_iter() + .map(|(a, b)| (turbopath::RelativeUnixPathBuf::new(a).unwrap(), b)) + .collect(), + ); + assert_eq!(file_hashes.hash(), expected); + } +} diff --git a/crates/turborepo-lib/src/hash/proto.capnp b/crates/turborepo-lib/Source/hash/proto.capnp similarity index 100% rename from crates/turborepo-lib/src/hash/proto.capnp rename to crates/turborepo-lib/Source/hash/proto.capnp diff --git a/crates/turborepo-lib/Source/hash/std/capnp/c++.capnp b/crates/turborepo-lib/Source/hash/std/capnp/c++.capnp new file mode 100644 index 0000000000000..bcad244bcdd99 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/c++.capnp @@ -0,0 +1,29 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xbdf87d7bb8304e81; +$namespace("capnp::annotations"); + +annotation namespace(file): Text; +annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text; +using Go = import "/go.capnp"; +$Go.package("cxx"); +$Go.import("capnproto.org/go/capnp/v3/std/capnp/cxx"); diff --git a/crates/turborepo-lib/Source/hash/std/capnp/compat/json.capnp b/crates/turborepo-lib/Source/hash/std/capnp/compat/json.capnp new file mode 100644 index 0000000000000..c2752496747f7 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/compat/json.capnp @@ -0,0 +1,118 @@ +# Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0x8ef99297a43a5e34; + +$import "/capnp/c++.capnp".namespace("capnp::json"); + +struct Value { + union { + null @0 :Void; + boolean @1 :Bool; + number @2 :Float64; + string @3 :Text $Go.name("string_"); + array @4 :List(Value); + object @5 :List(Field); + # Standard JSON values. + + call @6 :Call; + # Non-standard: A "function call", applying a named function (named by a single identifier) + # to a parameter list. Examples: + # + # BinData(0, "Zm9vCg==") + # ISODate("2015-04-15T08:44:50.218Z") + # + # Mongo DB users will recognize the above as exactly the syntax Mongo uses to represent BSON + # "binary" and "date" types in text, since JSON has no analog of these. This is basically the + # reason this extension exists. We do NOT recommend using `call` unless you specifically need + # to be compatible with some silly format that uses this syntax. + } + + struct Field { + name @0 :Text; + value @1 :Value; + } + + struct Call { + function @0 :Text; + params @1 :List(Value); + } +} + +# ======================================================================================== +# Annotations to control parsing. Typical usage: +# +# using Json = import "/capnp/compat/json.capnp"; +# +# And then later on: +# +# myField @0 :Text $Json.name("my_field"); + +annotation name @0xfa5b1fd61c2e7c3d (field, enumerant, method, group, union) :Text; +# Define an alternative name to use when encoding the given item in JSON. This can be used, for +# example, to use snake_case names where needed, even though Cap'n Proto uses strictly camelCase. +# +# (However, because JSON is derived from JavaScript, you *should* use camelCase names when +# defining JSON-based APIs. But, when supporting a pre-existing API you may not have a choice.) + +annotation flatten @0x82d3e852af0336bf (field, group, union) :FlattenOptions; +# Specifies that an aggregate field should be flattened into its parent. +# +# In order to flatten a member of a union, the union (or, for an anonymous union, the parent +# struct type) must have the $jsonDiscriminator annotation. +# +# TODO(someday): Maybe support "flattening" a List(Value.Field) as a way to support unknown JSON +# fields? + +struct FlattenOptions { + prefix @0 :Text = ""; + # Optional: Adds the given prefix to flattened field names. +} + +annotation discriminator @0xcfa794e8d19a0162 (struct, union) :DiscriminatorOptions; +# Specifies that a union's variant will be decided not by which fields are present, but instead +# by a special discriminator field. The value of the discriminator field is a string naming which +# variant is active. This allows the members of the union to have the $jsonFlatten annotation, or +# to all have the same name. + +struct DiscriminatorOptions { + name @0 :Text; + # The name of the discriminator field. Defaults to matching the name of the union. + + valueName @1 :Text; + # If non-null, specifies that the union's value shall have the given field name, rather than the + # value's name. In this case the union's variant can only be determined by looking at the + # discriminant field, not by inspecting which value field is present. + # + # It is an error to use `valueName` while also declaring some variants as $flatten. +} + +annotation base64 @0xd7d879450a253e4b (field) :Void; +# Place on a field of type `Data` to indicate that its JSON representation is a Base64 string. + +annotation hex @0xf061e22f0ae5c7b5 (field) :Void; +# Place on a field of type `Data` to indicate that its JSON representation is a hex string. + +annotation notification @0xa0a054dea32fd98c (method) :Void; +# Indicates that this method is a JSON-RPC "notification", meaning it expects no response. +using Go = import "/go.capnp"; +$Go.package("json"); +$Go.import("capnproto.org/go/capnp/v3/std/capnp/json"); diff --git a/crates/turborepo-lib/Source/hash/std/capnp/compat/json/json.capnp.go b/crates/turborepo-lib/Source/hash/std/capnp/compat/json/json.capnp.go new file mode 100644 index 0000000000000..ace5fdda93b96 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/compat/json/json.capnp.go @@ -0,0 +1,744 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package json + +import ( + capnp "capnproto.org/go/capnp/v3" + text "capnproto.org/go/capnp/v3/encoding/text" + schemas "capnproto.org/go/capnp/v3/schemas" + math "math" + strconv "strconv" +) + +const Name = uint64(0xfa5b1fd61c2e7c3d) +const Flatten = uint64(0x82d3e852af0336bf) +const Discriminator = uint64(0xcfa794e8d19a0162) +const Base64 = uint64(0xd7d879450a253e4b) +const Hex = uint64(0xf061e22f0ae5c7b5) +const Notification = uint64(0xa0a054dea32fd98c) + +type Value capnp.Struct +type Value_Which uint16 + +const ( + Value_Which_null Value_Which = 0 + Value_Which_boolean Value_Which = 1 + Value_Which_number Value_Which = 2 + Value_Which_string_ Value_Which = 3 + Value_Which_array Value_Which = 4 + Value_Which_object Value_Which = 5 + Value_Which_call Value_Which = 6 +) + +func (w Value_Which) String() string { + const s = "nullbooleannumberstring_arrayobjectcall" + switch w { + case Value_Which_null: + return s[0:4] + case Value_Which_boolean: + return s[4:11] + case Value_Which_number: + return s[11:17] + case Value_Which_string_: + return s[17:24] + case Value_Which_array: + return s[24:29] + case Value_Which_object: + return s[29:35] + case Value_Which_call: + return s[35:39] + + } + return "Value_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Value_TypeID is the unique identifier for the type Value. +const Value_TypeID = 0xa3fa7845f919dd83 + +func NewValue(s *capnp.Segment) (Value, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Value(st), err +} + +func NewRootValue(s *capnp.Segment) (Value, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Value(st), err +} + +func ReadRootValue(msg *capnp.Message) (Value, error) { + root, err := msg.Root() + return Value(root.Struct()), err +} + +func (s Value) String() string { + str, _ := text.Marshal(0xa3fa7845f919dd83, capnp.Struct(s)) + return str +} + +func (s Value) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Value) DecodeFromPtr(p capnp.Ptr) Value { + return Value(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Value) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Value) Which() Value_Which { + return Value_Which(capnp.Struct(s).Uint16(0)) +} +func (s Value) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Value) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Value) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Value) SetNull() { + capnp.Struct(s).SetUint16(0, 0) + +} + +func (s Value) Boolean() bool { + if capnp.Struct(s).Uint16(0) != 1 { + panic("Which() != boolean") + } + return capnp.Struct(s).Bit(16) +} + +func (s Value) SetBoolean(v bool) { + capnp.Struct(s).SetUint16(0, 1) + capnp.Struct(s).SetBit(16, v) +} + +func (s Value) Number() float64 { + if capnp.Struct(s).Uint16(0) != 2 { + panic("Which() != number") + } + return math.Float64frombits(capnp.Struct(s).Uint64(8)) +} + +func (s Value) SetNumber(v float64) { + capnp.Struct(s).SetUint16(0, 2) + capnp.Struct(s).SetUint64(8, math.Float64bits(v)) +} + +func (s Value) String_() (string, error) { + if capnp.Struct(s).Uint16(0) != 3 { + panic("Which() != string_") + } + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Value) HasString_() bool { + if capnp.Struct(s).Uint16(0) != 3 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) String_Bytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Value) SetString_(v string) error { + capnp.Struct(s).SetUint16(0, 3) + return capnp.Struct(s).SetText(0, v) +} + +func (s Value) Array() (Value_List, error) { + if capnp.Struct(s).Uint16(0) != 4 { + panic("Which() != array") + } + p, err := capnp.Struct(s).Ptr(0) + return Value_List(p.List()), err +} + +func (s Value) HasArray() bool { + if capnp.Struct(s).Uint16(0) != 4 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) SetArray(v Value_List) error { + capnp.Struct(s).SetUint16(0, 4) + return capnp.Struct(s).SetPtr(0, v.ToPtr()) +} + +// NewArray sets the array field to a newly +// allocated Value_List, preferring placement in s's segment. +func (s Value) NewArray(n int32) (Value_List, error) { + capnp.Struct(s).SetUint16(0, 4) + l, err := NewValue_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Value_List{}, err + } + err = capnp.Struct(s).SetPtr(0, l.ToPtr()) + return l, err +} +func (s Value) Object() (Value_Field_List, error) { + if capnp.Struct(s).Uint16(0) != 5 { + panic("Which() != object") + } + p, err := capnp.Struct(s).Ptr(0) + return Value_Field_List(p.List()), err +} + +func (s Value) HasObject() bool { + if capnp.Struct(s).Uint16(0) != 5 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) SetObject(v Value_Field_List) error { + capnp.Struct(s).SetUint16(0, 5) + return capnp.Struct(s).SetPtr(0, v.ToPtr()) +} + +// NewObject sets the object field to a newly +// allocated Value_Field_List, preferring placement in s's segment. +func (s Value) NewObject(n int32) (Value_Field_List, error) { + capnp.Struct(s).SetUint16(0, 5) + l, err := NewValue_Field_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Value_Field_List{}, err + } + err = capnp.Struct(s).SetPtr(0, l.ToPtr()) + return l, err +} +func (s Value) Call() (Value_Call, error) { + if capnp.Struct(s).Uint16(0) != 6 { + panic("Which() != call") + } + p, err := capnp.Struct(s).Ptr(0) + return Value_Call(p.Struct()), err +} + +func (s Value) HasCall() bool { + if capnp.Struct(s).Uint16(0) != 6 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) SetCall(v Value_Call) error { + capnp.Struct(s).SetUint16(0, 6) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewCall sets the call field to a newly +// allocated Value_Call struct, preferring placement in s's segment. +func (s Value) NewCall() (Value_Call, error) { + capnp.Struct(s).SetUint16(0, 6) + ss, err := NewValue_Call(capnp.Struct(s).Segment()) + if err != nil { + return Value_Call{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// Value_List is a list of Value. +type Value_List = capnp.StructList[Value] + +// NewValue creates a new list of Value. +func NewValue_List(s *capnp.Segment, sz int32) (Value_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}, sz) + return capnp.StructList[Value](l), err +} + +// Value_Future is a wrapper for a Value promised by a client call. +type Value_Future struct{ *capnp.Future } + +func (f Value_Future) Struct() (Value, error) { + p, err := f.Future.Ptr() + return Value(p.Struct()), err +} +func (p Value_Future) Call() Value_Call_Future { + return Value_Call_Future{Future: p.Future.Field(0, nil)} +} + +type Value_Field capnp.Struct + +// Value_Field_TypeID is the unique identifier for the type Value_Field. +const Value_Field_TypeID = 0xe31026e735d69ddf + +func NewValue_Field(s *capnp.Segment) (Value_Field, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return Value_Field(st), err +} + +func NewRootValue_Field(s *capnp.Segment) (Value_Field, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return Value_Field(st), err +} + +func ReadRootValue_Field(msg *capnp.Message) (Value_Field, error) { + root, err := msg.Root() + return Value_Field(root.Struct()), err +} + +func (s Value_Field) String() string { + str, _ := text.Marshal(0xe31026e735d69ddf, capnp.Struct(s)) + return str +} + +func (s Value_Field) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Value_Field) DecodeFromPtr(p capnp.Ptr) Value_Field { + return Value_Field(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Value_Field) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Value_Field) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Value_Field) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Value_Field) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Value_Field) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Value_Field) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Value_Field) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Value_Field) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Value_Field) Value() (Value, error) { + p, err := capnp.Struct(s).Ptr(1) + return Value(p.Struct()), err +} + +func (s Value_Field) HasValue() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Value_Field) SetValue(v Value) error { + return capnp.Struct(s).SetPtr(1, capnp.Struct(v).ToPtr()) +} + +// NewValue sets the value field to a newly +// allocated Value struct, preferring placement in s's segment. +func (s Value_Field) NewValue() (Value, error) { + ss, err := NewValue(capnp.Struct(s).Segment()) + if err != nil { + return Value{}, err + } + err = capnp.Struct(s).SetPtr(1, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// Value_Field_List is a list of Value_Field. +type Value_Field_List = capnp.StructList[Value_Field] + +// NewValue_Field creates a new list of Value_Field. +func NewValue_Field_List(s *capnp.Segment, sz int32) (Value_Field_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz) + return capnp.StructList[Value_Field](l), err +} + +// Value_Field_Future is a wrapper for a Value_Field promised by a client call. +type Value_Field_Future struct{ *capnp.Future } + +func (f Value_Field_Future) Struct() (Value_Field, error) { + p, err := f.Future.Ptr() + return Value_Field(p.Struct()), err +} +func (p Value_Field_Future) Value() Value_Future { + return Value_Future{Future: p.Future.Field(1, nil)} +} + +type Value_Call capnp.Struct + +// Value_Call_TypeID is the unique identifier for the type Value_Call. +const Value_Call_TypeID = 0xa0d9f6eca1c93d48 + +func NewValue_Call(s *capnp.Segment) (Value_Call, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return Value_Call(st), err +} + +func NewRootValue_Call(s *capnp.Segment) (Value_Call, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return Value_Call(st), err +} + +func ReadRootValue_Call(msg *capnp.Message) (Value_Call, error) { + root, err := msg.Root() + return Value_Call(root.Struct()), err +} + +func (s Value_Call) String() string { + str, _ := text.Marshal(0xa0d9f6eca1c93d48, capnp.Struct(s)) + return str +} + +func (s Value_Call) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Value_Call) DecodeFromPtr(p capnp.Ptr) Value_Call { + return Value_Call(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Value_Call) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Value_Call) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Value_Call) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Value_Call) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Value_Call) Function() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Value_Call) HasFunction() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Value_Call) FunctionBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Value_Call) SetFunction(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Value_Call) Params() (Value_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return Value_List(p.List()), err +} + +func (s Value_Call) HasParams() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Value_Call) SetParams(v Value_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewParams sets the params field to a newly +// allocated Value_List, preferring placement in s's segment. +func (s Value_Call) NewParams(n int32) (Value_List, error) { + l, err := NewValue_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Value_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} + +// Value_Call_List is a list of Value_Call. +type Value_Call_List = capnp.StructList[Value_Call] + +// NewValue_Call creates a new list of Value_Call. +func NewValue_Call_List(s *capnp.Segment, sz int32) (Value_Call_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz) + return capnp.StructList[Value_Call](l), err +} + +// Value_Call_Future is a wrapper for a Value_Call promised by a client call. +type Value_Call_Future struct{ *capnp.Future } + +func (f Value_Call_Future) Struct() (Value_Call, error) { + p, err := f.Future.Ptr() + return Value_Call(p.Struct()), err +} + +type FlattenOptions capnp.Struct + +// FlattenOptions_TypeID is the unique identifier for the type FlattenOptions. +const FlattenOptions_TypeID = 0xc4df13257bc2ea61 + +func NewFlattenOptions(s *capnp.Segment) (FlattenOptions, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return FlattenOptions(st), err +} + +func NewRootFlattenOptions(s *capnp.Segment) (FlattenOptions, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return FlattenOptions(st), err +} + +func ReadRootFlattenOptions(msg *capnp.Message) (FlattenOptions, error) { + root, err := msg.Root() + return FlattenOptions(root.Struct()), err +} + +func (s FlattenOptions) String() string { + str, _ := text.Marshal(0xc4df13257bc2ea61, capnp.Struct(s)) + return str +} + +func (s FlattenOptions) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (FlattenOptions) DecodeFromPtr(p capnp.Ptr) FlattenOptions { + return FlattenOptions(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s FlattenOptions) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s FlattenOptions) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s FlattenOptions) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s FlattenOptions) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s FlattenOptions) Prefix() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s FlattenOptions) HasPrefix() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s FlattenOptions) PrefixBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s FlattenOptions) SetPrefix(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +// FlattenOptions_List is a list of FlattenOptions. +type FlattenOptions_List = capnp.StructList[FlattenOptions] + +// NewFlattenOptions creates a new list of FlattenOptions. +func NewFlattenOptions_List(s *capnp.Segment, sz int32) (FlattenOptions_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return capnp.StructList[FlattenOptions](l), err +} + +// FlattenOptions_Future is a wrapper for a FlattenOptions promised by a client call. +type FlattenOptions_Future struct{ *capnp.Future } + +func (f FlattenOptions_Future) Struct() (FlattenOptions, error) { + p, err := f.Future.Ptr() + return FlattenOptions(p.Struct()), err +} + +type DiscriminatorOptions capnp.Struct + +// DiscriminatorOptions_TypeID is the unique identifier for the type DiscriminatorOptions. +const DiscriminatorOptions_TypeID = 0xc2f8c20c293e5319 + +func NewDiscriminatorOptions(s *capnp.Segment) (DiscriminatorOptions, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return DiscriminatorOptions(st), err +} + +func NewRootDiscriminatorOptions(s *capnp.Segment) (DiscriminatorOptions, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return DiscriminatorOptions(st), err +} + +func ReadRootDiscriminatorOptions(msg *capnp.Message) (DiscriminatorOptions, error) { + root, err := msg.Root() + return DiscriminatorOptions(root.Struct()), err +} + +func (s DiscriminatorOptions) String() string { + str, _ := text.Marshal(0xc2f8c20c293e5319, capnp.Struct(s)) + return str +} + +func (s DiscriminatorOptions) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (DiscriminatorOptions) DecodeFromPtr(p capnp.Ptr) DiscriminatorOptions { + return DiscriminatorOptions(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s DiscriminatorOptions) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s DiscriminatorOptions) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s DiscriminatorOptions) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s DiscriminatorOptions) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s DiscriminatorOptions) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s DiscriminatorOptions) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s DiscriminatorOptions) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s DiscriminatorOptions) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s DiscriminatorOptions) ValueName() (string, error) { + p, err := capnp.Struct(s).Ptr(1) + return p.Text(), err +} + +func (s DiscriminatorOptions) HasValueName() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s DiscriminatorOptions) ValueNameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(1) + return p.TextBytes(), err +} + +func (s DiscriminatorOptions) SetValueName(v string) error { + return capnp.Struct(s).SetText(1, v) +} + +// DiscriminatorOptions_List is a list of DiscriminatorOptions. +type DiscriminatorOptions_List = capnp.StructList[DiscriminatorOptions] + +// NewDiscriminatorOptions creates a new list of DiscriminatorOptions. +func NewDiscriminatorOptions_List(s *capnp.Segment, sz int32) (DiscriminatorOptions_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz) + return capnp.StructList[DiscriminatorOptions](l), err +} + +// DiscriminatorOptions_Future is a wrapper for a DiscriminatorOptions promised by a client call. +type DiscriminatorOptions_Future struct{ *capnp.Future } + +func (f DiscriminatorOptions_Future) Struct() (DiscriminatorOptions, error) { + p, err := f.Future.Ptr() + return DiscriminatorOptions(p.Struct()), err +} + +const schema_8ef99297a43a5e34 = "x\xda\x8c\x94_h[e\x18\xc6\x9f\xe7\xfb\xce9\xeb" + + "\x9a\xd4\xe6x\"Z\xd8\x88\x17\xab\xda\xa2\xed\xd6\xd5)" + + "\x81-:\xed(\x8a\xb3_#\xde\x88\x7fN\xb2S\xcd" + + "89\x09I\xaa\xad\x0a\x83y'\xfe\xc1!\x08\x03\xa1" + + "2\xc1+Q\xc4\x82\x15E\x17&2A\xa4*\xd3^" + + "\xe8\x8a:\xecd\x82\xbbP\xdaj=\xf2\x9d\xcc&i" + + "\x1dx\x17\xbe\xef\x97\xe7}\xde\xe7}\xbf\xb3\xd3\x12\xb7" + + "\x19\xbb\xban\xb1 \xd4\xa8i\x85\x1f\xed\x91o\x8d/" + + "}u\x14*f.\x86\xc3\x0f\xa5_\x7f\xe5\xd8\xca\x0b" + + "\x00\x1d\xca\xe3\xceV\xb9\x05\xc8\x1aR\x12\x0c\x9f[\x18" + + "<\xf1\xfd}33x)f\x8a6\xf4wQw\xd6" + + "\x84F\x97E\x84\x8e\xee=\xfd\xda\x85?\x16f`\xdb" + + "\x0c\x9f\xf9\xaegedj\xf5\x04L\x8d8\xe7\xc5;" + + "\xce\xc5\xe8\xd7\xaf\xe2\x09\xb4\\\xab\x18[dG\xb8E" + + "3\x0f\xcag\x1dO^\x0f\xec\x9e\x96/j\xe9\x9e\xec" + + "\xbe\xbex}\xb9\x0e;\xc6&\x1dI\xef\x1e1\x05\x1d" + + "e\xea\xff\xddcjm\xf7\x97\xfaS\xbd\xce\xd9S\x1b" + + "`j\xe2M\xf3Kg.bg\xcd\x0c\x18\xe6x|" + + "~\xe9\xe57\xbe\xd0I\x8c\xb5\xb5\xb7`~\xe6\x9c\xd3" + + "dv\xd1\x8c\xda\xbb{_o\xe7\xc8\xf4\xb7\xdfh\xf4" + + "\xda6t\xde<\xe6,D\xe8\xd7\x0d\xf4\xec\xabgn" + + "\xfe\xf9\xba\xc4\x8f\xff\x95\xc4'\xe6\xfb\xce\xe7\x91\x83\xd3" + + "\x91\xdb\xd9O\xcfu\x0e\xfe\xe0\xfe\xb6Y\xb6\xd7z\xd2" + + "\xe9\xb3\xb4\xec\x0e+\x92\xdd\xfb\xf4\xc0\xb63\xa9\x07V" + + "1\x1f3\x97\xda\x87q\x95u\xd4\xe9\x89\xd8\xa4f\x0f" + + "\x86\x87\xab\xa5` \xef\x96\x19\x94\xd3\x13\xbe[\xabI" + + "/\x18#\x99h\xc6\x03\xaeS\"(\xa7\x83R\xad0" + + "Q\xc8\xbb\xb5B)\xc0\x18\x09\xd9&r\xbf\xebOz" + + "\xa9\x81;\\\xdf\x1f#U\x874\x00\x83\x80\xddw\x17" + + "\xa0n\x90T\xc3\x826\x99\xa4>\xdc\x95\x06\xd4\x8d\x92" + + "jT0\x9c\x98\x0c\xf2\x91*\xc08\x04\xe3`\xa6\xec" + + "V\xdcb\x95W\x80cR\xbbZO\x09\xd4\x87\x9bK" + + "\x03\xaa\x83\xad\xd1n\x1dj\xd98\xb3?u\xa0\xe0\xf9" + + "\x87\xba\xb5?\xb5M\x1a\xf10\x8c\xdc\xcd\xf6\x03\xeam" + + "I\xf5\x81\xe0v\xfe\x1d&\x1a\xfe\xe6\xf6\x03\xea]I" + + "\xf5\xb1\xe0v\xb1\x162I\x01\xd8\x1fj\xdb\xefI\xaa" + + "S\x82]\xf2\xaf0I\x09\xd8'\xd3\xf6\xc9\x94Z\x94" + + "T\x17\x04\xbb\x8c?\xc3$\x0d\xc0>?\x04\xa8\x9f$" + + "\xc7)\xd8e\xae\x86I\x9a\x80\xbd\xa6%\x96%\xb3I" + + "}l\xad\x84IZ\x80c\xb3\x1f\xc8\xc6)\x99\xbd\x86" + + "\x82\xdd\xc1\xa4\xef\xc3:\x92+\x95|\xcf\x0dH\x08\x12" + + "\xcc\x04\x93\xc5\x9cWa\x0c\x8210S\xadU\x0a\xc1" + + "\xa3\xca\xa0\x08/>?x\xf5\x95\x8f\xcc\xd5\xa1\x0c\xc1" + + "\xdb\x13d\x1c\xb0\xb9\xffH\x03y\xb8\x19m\xca\xadT" + + "\xdc\xe9\xcb&\x9b)\xe5\x0e{\xf9Z\xf3~=\xd1\xc6" + + "}w\xde\xf5}&\x9a\xd9\x82L\xb4\x0cD\x06\xe5\xf4" + + "\x9d\x85j\xbeR(\x16\x02\xb7V\xaa\xdc[\xd6\xb3\xad" + + "b\xc3V\xe8\xdcwH\xaa\x9d-[q\xd3\xf8\xa5\xad" + + "\xb8U'\xe0\x16\xbd\x7f=\x87\x8f\xeb\x11\x1ft\x8b`" + + "\xf3\xacu9\x0f\xe8\x15\xf6\x82F-Vu-\xa3Q" + + "\x8b\xb4\xbbt\xe4\x1d\x92*)\x98)W\xbc\x89\xc2\xd4" + + "%\x11\xd8\xec\x04\xda\x94\x0e\xb5z\x07\x1aob\xfd\xfb" + + "\xb2a\xf3rn\xd5\xdb\xc3\xe1\xcb\xbc\x86\xcc@\xb4s" + + "\xff\xa7\xf1\xa1\xe6\x1bik<\x155\xbeaJ\xadq" + + "#\x13\x94\xd3\x8fyS\x9b-h\x99\xc8~\x1c\xe2\x9f" + + "\x00\x00\x00\xff\xff\x06\xfd\x9d\x93" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_8ef99297a43a5e34, + Nodes: []uint64{ + 0x82d3e852af0336bf, + 0xa0a054dea32fd98c, + 0xa0d9f6eca1c93d48, + 0xa3fa7845f919dd83, + 0xc2f8c20c293e5319, + 0xc4df13257bc2ea61, + 0xcfa794e8d19a0162, + 0xd7d879450a253e4b, + 0xe31026e735d69ddf, + 0xf061e22f0ae5c7b5, + 0xfa5b1fd61c2e7c3d, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/std/capnp/cxx/c++.capnp.go b/crates/turborepo-lib/Source/hash/std/capnp/cxx/c++.capnp.go new file mode 100644 index 0000000000000..337774f4f854a --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/cxx/c++.capnp.go @@ -0,0 +1,30 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package cxx + +import ( + schemas "capnproto.org/go/capnp/v3/schemas" +) + +const Namespace = uint64(0xb9c6f99ebf805f2c) +const Name = uint64(0xf264a779fef191ce) +const schema_bdf87d7bb8304e81 = "x\xda\x12\x08w`1\xe4\x15gb`\x0a\x94`e" + + "\xfb\xaf\x13\xdf\xb0\x7f\xde\xcfc;\x19\x02\xb9X\x19\xff" + + "7\xfa\x19\xec\xa8\xae\xfd\xb1\x97\x81\x81Q\xf0\xe3\"\xc1" + + "\x9f\xec\x0c\x0c\x81_\x98\x19\x19\x18\xff\x9f\x9b\xf8\xf1_" + + "\xe5\xf2\x94O\x0c\x17\xb9X\xff\xb0\xa3(|Z%\xf8" + + "\x12\xa4\xf0\x093#\x83\xee\xffdmm\xbd\xe4\xc4\x82" + + "<\xc6\x02\xab\xbc\xc4\xdc\xd4\xe2\x02\xf6\xc4\xe4\xd4\x00F" + + "FF\x1e\x06&\xb8$\x83=D\x16*\x0e\x08\x00\x00" + + "\xff\xffM^1\xb8" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_bdf87d7bb8304e81, + Nodes: []uint64{ + 0xb9c6f99ebf805f2c, + 0xf264a779fef191ce, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/std/capnp/persistent.capnp b/crates/turborepo-lib/Source/hash/std/capnp/persistent.capnp new file mode 100644 index 0000000000000..cd16a23a490dd --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/persistent.capnp @@ -0,0 +1,125 @@ +# Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xb8630836983feed7; + +$import "/capnp/c++.capnp".namespace("capnp"); + +interface Persistent@0xc8cb212fcd9f5691(SturdyRef, Owner) { + # Interface implemented by capabilities that outlive a single connection. A client may save() + # the capability, producing a SturdyRef. The SturdyRef can be stored to disk, then later used to + # obtain a new reference to the capability on a future connection. + # + # The exact format of SturdyRef depends on the "realm" in which the SturdyRef appears. A "realm" + # is an abstract space in which all SturdyRefs have the same format and refer to the same set of + # resources. Every vat is in exactly one realm. All capability clients within that vat must + # produce SturdyRefs of the format appropriate for the realm. + # + # Similarly, every VatNetwork also resides in a particular realm. Usually, a vat's "realm" + # corresponds to the realm of its main VatNetwork. However, a Vat can in fact communicate over + # a VatNetwork in a different realm -- in this case, all SturdyRefs need to be transformed when + # coming or going through said VatNetwork. The RPC system has hooks for registering + # transformation callbacks for this purpose. + # + # Since the format of SturdyRef is realm-dependent, it is not defined here. An application should + # choose an appropriate realm for itself as part of its design. Note that under Sandstorm, every + # application exists in its own realm and is therefore free to define its own SturdyRef format; + # the Sandstorm platform handles translating between realms. + # + # Note that whether a capability is persistent is often orthogonal to its type. In these cases, + # the capability's interface should NOT inherit `Persistent`; instead, just perform a cast at + # runtime. It's not type-safe, but trying to be type-safe in these cases will likely lead to + # tears. In cases where a particular interface only makes sense on persistent capabilities, it + # still should not explicitly inherit Persistent because the `SturdyRef` and `Owner` types will + # vary between realms (they may even be different at the call site than they are on the + # implementation). Instead, mark persistent interfaces with the $persistent annotation (defined + # below). + # + # Sealing + # ------- + # + # As an added security measure, SturdyRefs may be "sealed" to a particular owner, such that + # if the SturdyRef itself leaks to a third party, that party cannot actually restore it because + # they are not the owner. To restore a sealed capability, you must first prove to its host that + # you are the rightful owner. The precise mechanism for this authentication is defined by the + # realm. + # + # Sealing is a defense-in-depth mechanism meant to mitigate damage in the case of catastrophic + # attacks. For example, say an attacker temporarily gains read access to a database full of + # SturdyRefs: it would be unfortunate if it were then necessary to revoke every single reference + # in the database to prevent the attacker from using them. + # + # In general, an "owner" is a course-grained identity. Because capability-based security is still + # the primary mechanism of security, it is not necessary nor desirable to have a separate "owner" + # identity for every single process or object; that is exactly what capabilities are supposed to + # avoid! Instead, it makes sense for an "owner" to literally identify the owner of the machines + # where the capability is stored. If untrusted third parties are able to run arbitrary code on + # said machines, then the sandbox for that code should be designed using Distributed Confinement + # such that the third-party code never sees the bits of the SturdyRefs and cannot directly + # exercise the owner's power to restore refs. See: + # + # http://www.erights.org/elib/capability/dist-confine.html + # + # Resist the urge to represent an Owner as a simple public key. The whole point of sealing is to + # defend against leaked-storage attacks. Such attacks can easily result in the owner's private + # key being stolen as well. A better solution is for `Owner` to contain a simple globally unique + # identifier for the owner, and for everyone to separately maintain a mapping of owner IDs to + # public keys. If an owner's private key is compromised, then humans will need to communicate + # and agree on a replacement public key, then update the mapping. + # + # As a concrete example, an `Owner` could simply contain a domain name, and restoring a SturdyRef + # would require signing a request using the domain's private key. Authenticating this key could + # be accomplished through certificate authorities or web-of-trust techniques. + + save @0 SaveParams -> SaveResults; + # Save a capability persistently so that it can be restored by a future connection. Not all + # capabilities can be saved -- application interfaces should define which capabilities support + # this and which do not. + + struct SaveParams { + sealFor @0 :Owner; + # Seal the SturdyRef so that it can only be restored by the specified Owner. This is meant + # to mitigate damage when a SturdyRef is leaked. See comments above. + # + # Leaving this value null may or may not be allowed; it is up to the realm to decide. If a + # realm does allow a null owner, this should indicate that anyone is allowed to restore the + # ref. + } + struct SaveResults { + sturdyRef @0 :SturdyRef; + } +} + +annotation persistent(interface, field) :Void $Go.name("PersistentAnnotation"); +# Apply this annotation to interfaces for objects that will always be persistent, instead of +# extending the Persistent capability, since the correct type parameters to Persistent depend on +# the realm, which is orthogonal to the interface type and therefore should not be defined +# along-side it. +# +# You may also apply this annotation to a capability-typed field which will always contain a +# persistent capability, but where the capability's interface itself is not already marked +# persistent. +# +# Note that absence of the $persistent annotation doesn't mean a capability of that type isn't +# persistent; it just means not *all* such capabilities are persistent. +using Go = import "/go.capnp"; +$Go.package("persistent"); +$Go.import("capnproto.org/go/capnp/v3/std/capnp/persistent"); diff --git a/crates/turborepo-lib/Source/hash/std/capnp/persistent/persistent.capnp.go b/crates/turborepo-lib/Source/hash/std/capnp/persistent/persistent.capnp.go new file mode 100644 index 0000000000000..89185a799bdc7 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/persistent/persistent.capnp.go @@ -0,0 +1,375 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package persistent + +import ( + capnp "capnproto.org/go/capnp/v3" + text "capnproto.org/go/capnp/v3/encoding/text" + fc "capnproto.org/go/capnp/v3/flowcontrol" + schemas "capnproto.org/go/capnp/v3/schemas" + server "capnproto.org/go/capnp/v3/server" + context "context" +) + +const PersistentAnnotation = uint64(0xf622595091cafb67) + +type Persistent capnp.Client + +// Persistent_TypeID is the unique identifier for the type Persistent. +const Persistent_TypeID = 0xc8cb212fcd9f5691 + +func (c Persistent) Save(ctx context.Context, params func(Persistent_SaveParams) error) (Persistent_SaveResults_Future, capnp.ReleaseFunc) { + + s := capnp.Send{ + Method: capnp.Method{ + InterfaceID: 0xc8cb212fcd9f5691, + MethodID: 0, + InterfaceName: "persistent.capnp:Persistent", + MethodName: "save", + }, + } + if params != nil { + s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} + s.PlaceArgs = func(s capnp.Struct) error { return params(Persistent_SaveParams(s)) } + } + + ans, release := capnp.Client(c).SendCall(ctx, s) + return Persistent_SaveResults_Future{Future: ans.Future()}, release + +} + +func (c Persistent) WaitStreaming() error { + return capnp.Client(c).WaitStreaming() +} + +// String returns a string that identifies this capability for debugging +// purposes. Its format should not be depended on: in particular, it +// should not be used to compare clients. Use IsSame to compare clients +// for equality. +func (c Persistent) String() string { + return "Persistent(" + capnp.Client(c).String() + ")" +} + +// AddRef creates a new Client that refers to the same capability as c. +// If c is nil or has resolved to null, then AddRef returns nil. +func (c Persistent) AddRef() Persistent { + return Persistent(capnp.Client(c).AddRef()) +} + +// Release releases a capability reference. If this is the last +// reference to the capability, then the underlying resources associated +// with the capability will be released. +// +// Release will panic if c has already been released, but not if c is +// nil or resolved to null. +func (c Persistent) Release() { + capnp.Client(c).Release() +} + +// Resolve blocks until the capability is fully resolved or the Context +// expires. +func (c Persistent) Resolve(ctx context.Context) error { + return capnp.Client(c).Resolve(ctx) +} + +func (c Persistent) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) +} + +func (Persistent) DecodeFromPtr(p capnp.Ptr) Persistent { + return Persistent(capnp.Client{}.DecodeFromPtr(p)) +} + +// IsValid reports whether c is a valid reference to a capability. +// A reference is invalid if it is nil, has resolved to null, or has +// been released. +func (c Persistent) IsValid() bool { + return capnp.Client(c).IsValid() +} + +// IsSame reports whether c and other refer to a capability created by the +// same call to NewClient. This can return false negatives if c or other +// are not fully resolved: use Resolve if this is an issue. If either +// c or other are released, then IsSame panics. +func (c Persistent) IsSame(other Persistent) bool { + return capnp.Client(c).IsSame(capnp.Client(other)) +} + +// Update the flowcontrol.FlowLimiter used to manage flow control for +// this client. This affects all future calls, but not calls already +// waiting to send. Passing nil sets the value to flowcontrol.NopLimiter, +// which is also the default. +func (c Persistent) SetFlowLimiter(lim fc.FlowLimiter) { + capnp.Client(c).SetFlowLimiter(lim) +} + +// Get the current flowcontrol.FlowLimiter used to manage flow control +// for this client. +func (c Persistent) GetFlowLimiter() fc.FlowLimiter { + return capnp.Client(c).GetFlowLimiter() +} + +// A Persistent_Server is a Persistent with a local implementation. +type Persistent_Server interface { + Save(context.Context, Persistent_save) error +} + +// Persistent_NewServer creates a new Server from an implementation of Persistent_Server. +func Persistent_NewServer(s Persistent_Server) *server.Server { + c, _ := s.(server.Shutdowner) + return server.New(Persistent_Methods(nil, s), s, c) +} + +// Persistent_ServerToClient creates a new Client from an implementation of Persistent_Server. +// The caller is responsible for calling Release on the returned Client. +func Persistent_ServerToClient(s Persistent_Server) Persistent { + return Persistent(capnp.NewClient(Persistent_NewServer(s))) +} + +// Persistent_Methods appends Methods to a slice that invoke the methods on s. +// This can be used to create a more complicated Server. +func Persistent_Methods(methods []server.Method, s Persistent_Server) []server.Method { + if cap(methods) == 0 { + methods = make([]server.Method, 0, 1) + } + + methods = append(methods, server.Method{ + Method: capnp.Method{ + InterfaceID: 0xc8cb212fcd9f5691, + MethodID: 0, + InterfaceName: "persistent.capnp:Persistent", + MethodName: "save", + }, + Impl: func(ctx context.Context, call *server.Call) error { + return s.Save(ctx, Persistent_save{call}) + }, + }) + + return methods +} + +// Persistent_save holds the state for a server call to Persistent.save. +// See server.Call for documentation. +type Persistent_save struct { + *server.Call +} + +// Args returns the call's arguments. +func (c Persistent_save) Args() Persistent_SaveParams { + return Persistent_SaveParams(c.Call.Args()) +} + +// AllocResults allocates the results struct. +func (c Persistent_save) AllocResults() (Persistent_SaveResults, error) { + r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Persistent_SaveResults(r), err +} + +// Persistent_List is a list of Persistent. +type Persistent_List = capnp.CapList[Persistent] + +// NewPersistent creates a new list of Persistent. +func NewPersistent_List(s *capnp.Segment, sz int32) (Persistent_List, error) { + l, err := capnp.NewPointerList(s, sz) + return capnp.CapList[Persistent](l), err +} + +type Persistent_SaveParams capnp.Struct + +// Persistent_SaveParams_TypeID is the unique identifier for the type Persistent_SaveParams. +const Persistent_SaveParams_TypeID = 0xf76fba59183073a5 + +func NewPersistent_SaveParams(s *capnp.Segment) (Persistent_SaveParams, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Persistent_SaveParams(st), err +} + +func NewRootPersistent_SaveParams(s *capnp.Segment) (Persistent_SaveParams, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Persistent_SaveParams(st), err +} + +func ReadRootPersistent_SaveParams(msg *capnp.Message) (Persistent_SaveParams, error) { + root, err := msg.Root() + return Persistent_SaveParams(root.Struct()), err +} + +func (s Persistent_SaveParams) String() string { + str, _ := text.Marshal(0xf76fba59183073a5, capnp.Struct(s)) + return str +} + +func (s Persistent_SaveParams) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Persistent_SaveParams) DecodeFromPtr(p capnp.Ptr) Persistent_SaveParams { + return Persistent_SaveParams(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Persistent_SaveParams) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Persistent_SaveParams) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Persistent_SaveParams) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Persistent_SaveParams) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Persistent_SaveParams) SealFor() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) +} + +func (s Persistent_SaveParams) HasSealFor() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Persistent_SaveParams) SetSealFor(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} + +// Persistent_SaveParams_List is a list of Persistent_SaveParams. +type Persistent_SaveParams_List = capnp.StructList[Persistent_SaveParams] + +// NewPersistent_SaveParams creates a new list of Persistent_SaveParams. +func NewPersistent_SaveParams_List(s *capnp.Segment, sz int32) (Persistent_SaveParams_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return capnp.StructList[Persistent_SaveParams](l), err +} + +// Persistent_SaveParams_Future is a wrapper for a Persistent_SaveParams promised by a client call. +type Persistent_SaveParams_Future struct{ *capnp.Future } + +func (f Persistent_SaveParams_Future) Struct() (Persistent_SaveParams, error) { + p, err := f.Future.Ptr() + return Persistent_SaveParams(p.Struct()), err +} +func (p Persistent_SaveParams_Future) SealFor() *capnp.Future { + return p.Future.Field(0, nil) +} + +type Persistent_SaveResults capnp.Struct + +// Persistent_SaveResults_TypeID is the unique identifier for the type Persistent_SaveResults. +const Persistent_SaveResults_TypeID = 0xb76848c18c40efbf + +func NewPersistent_SaveResults(s *capnp.Segment) (Persistent_SaveResults, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Persistent_SaveResults(st), err +} + +func NewRootPersistent_SaveResults(s *capnp.Segment) (Persistent_SaveResults, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Persistent_SaveResults(st), err +} + +func ReadRootPersistent_SaveResults(msg *capnp.Message) (Persistent_SaveResults, error) { + root, err := msg.Root() + return Persistent_SaveResults(root.Struct()), err +} + +func (s Persistent_SaveResults) String() string { + str, _ := text.Marshal(0xb76848c18c40efbf, capnp.Struct(s)) + return str +} + +func (s Persistent_SaveResults) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Persistent_SaveResults) DecodeFromPtr(p capnp.Ptr) Persistent_SaveResults { + return Persistent_SaveResults(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Persistent_SaveResults) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Persistent_SaveResults) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Persistent_SaveResults) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Persistent_SaveResults) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Persistent_SaveResults) SturdyRef() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) +} + +func (s Persistent_SaveResults) HasSturdyRef() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Persistent_SaveResults) SetSturdyRef(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} + +// Persistent_SaveResults_List is a list of Persistent_SaveResults. +type Persistent_SaveResults_List = capnp.StructList[Persistent_SaveResults] + +// NewPersistent_SaveResults creates a new list of Persistent_SaveResults. +func NewPersistent_SaveResults_List(s *capnp.Segment, sz int32) (Persistent_SaveResults_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return capnp.StructList[Persistent_SaveResults](l), err +} + +// Persistent_SaveResults_Future is a wrapper for a Persistent_SaveResults promised by a client call. +type Persistent_SaveResults_Future struct{ *capnp.Future } + +func (f Persistent_SaveResults_Future) Struct() (Persistent_SaveResults, error) { + p, err := f.Future.Ptr() + return Persistent_SaveResults(p.Struct()), err +} +func (p Persistent_SaveResults_Future) SturdyRef() *capnp.Future { + return p.Future.Field(0, nil) +} + +const schema_b8630836983feed7 = "x\xdat\x91\xbfk\x14A\x1c\xc5\xbfof\xd7\xbd\x83" + + "\x0b\xb9\xb9\x11rE\xe0T\x10A4\xf1\x07X\xa4\xb9" + + "\xdb\x14j\xa5;w \xc4\xca5\x8e\x1a\xb8\xcc\x1d;" + + "\xb3\x11+I\xafE:\xad\xac\x02\xea?\xe0\x8fF\xb4" + + "\x12%\x88\x95X\xd8\xa4\xb3Ql\xb4\x10\x19Y\xf1." + + "K\xbc\xb4\xdf\xe1\xcd\xfb\xbc\xf7\xea_:\xc1\xc9\xa9\xf7" + + "\x9c\x98:\x16\xee\xf3/\xbfu\xee\xbe:\x7f\xf3)\x89" + + "Y\xf8\x8dK\x0f\xb7\xe6\x0f\xbe{C!\xa2:No" + + "a\x11\xf23\"\"\xf9\x09m*\xbd\x0b\xc1\xfd\xc7\xaf" + + "\xed\xfbg*\xcb\xcf\x88\xa8\x0e\xf9\x1b\xdb\xb2\xca\x8e\x10" + + "\xc9\xc3\xec\x9c\xccY$s6\xe3o\xfcz\xbb\x91," + + "\x1d\xfaA\x1fDx\x00%\x09d\xce\xb6\xe5:\x8b\xe4" + + ":k\xf5\x1e1\x0e\x82\xdf\xb4'\x9aK/\x06?'" + + "\xb1<`\x0b\x90\x8fY\xc1\xb2\xc9\xdat\xc1\x0fuf" + + "W\xac\xd3\x81qs\xcb\xe9\xd0\x0c\x17\x92\x7f\x17\xe3\xe6" + + "z\xe9\x9a\xeej\x9b\xf7\x9d\xa5\x04P\x01\x0f\x88\x02\x10" + + "\x89\xa9.\x91\xaaq\xa8&\x83\xb7.\xcf\xae\xdd\xeej" + + "\xc2u4P\xf2$B\x830\xf6`\xbb=\"m\x9c" + + "\xaa\xa0\x8c\\\xbd\\\xea\xb2z\xd5\x17\x08I\x9a\xa5\xc4" + + "W\xad\x1f\xf1P\xd4wV\x05<$\x1aK1\x92\x09" + + "q\x94(\xae!\x9e\x858\x1eM\xdbtM\x0b\xb4T" + + "\xc0J`(2L:v\x90\x00q\x05\"\xec\x8a\xea" + + ")\xdf\xdbI\xd6\xbax\xcb\xe8lB\x96\xe1N\x96\xbf" + + "\x1d\x81\xf9\xef\xf7\xe6g\x1aW\x9e\xbf\xa6\xc2 n\x02" + + "\xb5\xc2\xee\x89\x1fU\x0b\xe3bc\x06.\x9dv+\x03" + + "C\xc1\xf8W\xbe\xd7\x0a\xed\xa2\x83U\xbbk\x84E\"" + + "U\xe1P\xfb\x19\xeeX\x9d\xf6\xcf\x0e24\xc2\xff\x17" + + "\xf8\x13\x00\x00\xff\xff\x80\x98\xd3O" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_b8630836983feed7, + Nodes: []uint64{ + 0xb76848c18c40efbf, + 0xc8cb212fcd9f5691, + 0xf622595091cafb67, + 0xf76fba59183073a5, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/std/capnp/rpc-twoparty.capnp b/crates/turborepo-lib/Source/hash/std/capnp/rpc-twoparty.capnp new file mode 100644 index 0000000000000..9f0c76b4236f9 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/rpc-twoparty.capnp @@ -0,0 +1,172 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xa184c7885cdaf2a1; +# This file defines the "network-specific parameters" in rpc.capnp to support a network consisting +# of two vats. Each of these vats may in fact be in communication with other vats, but any +# capabilities they forward must be proxied. Thus, to each end of the connection, all capabilities +# received from the other end appear to live in a single vat. +# +# Two notable use cases for this model include: +# - Regular client-server communications, where a remote client machine (perhaps living on an end +# user's personal device) connects to a server. The server may be part of a cluster, and may +# call on other servers in the cluster to help service the user's request. It may even obtain +# capabilities from these other servers which it passes on to the user. To simplify network +# common traversal problems (e.g. if the user is behind a firewall), it is probably desirable to +# multiplex all communications between the server cluster and the client over the original +# connection rather than form new ones. This connection should use the two-party protocol, as +# the client has no interest in knowing about additional servers. +# - Applications running in a sandbox. A supervisor process may execute a confined application +# such that all of the confined app's communications with the outside world must pass through +# the supervisor. In this case, the connection between the confined app and the supervisor might +# as well use the two-party protocol, because the confined app is intentionally prevented from +# talking to any other vat anyway. Any external resources will be proxied through the supervisor, +# and so to the contained app will appear as if they were hosted by the supervisor itself. +# +# Since there are only two vats in this network, there is never a need for three-way introductions, +# so level 3 is free. Moreover, because it is never necessary to form new connections, the +# two-party protocol can be used easily anywhere where a two-way byte stream exists, without regard +# to where that byte stream goes or how it was initiated. This makes the two-party runtime library +# highly reusable. +# +# Joins (level 4) _could_ be needed in cases where one or both vats are participating in other +# networks that use joins. For instance, if Alice and Bob are speaking through the two-party +# protocol, and Bob is also participating on another network, Bob may send Alice two or more +# proxied capabilities which, unbeknownst to Bob at the time, are in fact pointing at the same +# remote object. Alice may then request to join these capabilities, at which point Bob will have +# to forward the join to the other network. Note, however, that if Alice is _not_ participating on +# any other network, then Alice will never need to _receive_ a Join, because Alice would always +# know when two locally-hosted capabilities are the same and would never export a redundant alias +# to Bob. So, Alice can respond to all incoming joins with an error, and only needs to implement +# outgoing joins if she herself desires to use this feature. Also, outgoing joins are relatively +# easy to implement in this scenario. +# +# What all this means is that a level 4 implementation of the confined network is barely more +# complicated than a level 2 implementation. However, such an implementation allows the "client" +# or "confined" app to access the server's/supervisor's network with equal functionality to any +# native participant. In other words, an application which implements only the two-party protocol +# can be paired with a proxy app in order to participate in any network. +# +# So, when implementing Cap'n Proto in a new language, it makes sense to implement only the +# two-party protocol initially, and then pair applications with an appropriate proxy written in +# C++, rather than implement other parameterizations of the RPC protocol directly. + +using Cxx = import "/capnp/c++.capnp"; +$Cxx.namespace("capnp::rpc::twoparty"); + +# Note: SturdyRef is not specified here. It is up to the application to define semantics of +# SturdyRefs if desired. + +enum Side { + server @0; + # The object lives on the "server" or "supervisor" end of the connection. Only the + # server/supervisor knows how to interpret the ref; to the client, it is opaque. + # + # Note that containers intending to implement strong confinement should rewrite SturdyRefs + # received from the external network before passing them on to the confined app. The confined + # app thus does not ever receive the raw bits of the SturdyRef (which it could perhaps + # maliciously leak), but instead receives only a thing that it can pass back to the container + # later to restore the ref. See: + # http://www.erights.org/elib/capability/dist-confine.html + + client @1; + # The object lives on the "client" or "confined app" end of the connection. Only the client + # knows how to interpret the ref; to the server/supervisor, it is opaque. Most clients do not + # actually know how to persist capabilities at all, so use of this is unusual. +} + +struct VatId { + side @0 :Side; +} + +struct ProvisionId { + # Only used for joins, since three-way introductions never happen on a two-party network. + + joinId @0 :UInt32; + # The ID from `JoinKeyPart`. +} + +struct RecipientId {} +# Never used, because there are only two parties. + +struct ThirdPartyCapId {} +# Never used, because there is no third party. + +struct JoinKeyPart { + # Joins in the two-party case are simplified by a few observations. + # + # First, on a two-party network, a Join only ever makes sense if the receiving end is also + # connected to other networks. A vat which is not connected to any other network can safely + # reject all joins. + # + # Second, since a two-party connection bisects the network -- there can be no other connections + # between the networks at either end of the connection -- if one part of a join crosses the + # connection, then _all_ parts must cross it. Therefore, a vat which is receiving a Join request + # off some other network which needs to be forwarded across the two-party connection can + # collect all the parts on its end and only forward them across the two-party connection when all + # have been received. + # + # For example, imagine that Alice and Bob are vats connected over a two-party connection, and + # each is also connected to other networks. At some point, Alice receives one part of a Join + # request off her network. The request is addressed to a capability that Alice received from + # Bob and is proxying to her other network. Alice goes ahead and responds to the Join part as + # if she hosted the capability locally (this is important so that if not all the Join parts end + # up at Alice, the original sender can detect the failed Join without hanging). As other parts + # trickle in, Alice verifies that each part is addressed to a capability from Bob and continues + # to respond to each one. Once the complete set of join parts is received, Alice checks if they + # were all for the exact same capability. If so, she doesn't need to send anything to Bob at + # all. Otherwise, she collects the set of capabilities (from Bob) to which the join parts were + # addressed and essentially initiates a _new_ Join request on those capabilities to Bob. Alice + # does not forward the Join parts she received herself, but essentially forwards the Join as a + # whole. + # + # On Bob's end, since he knows that Alice will always send all parts of a Join together, he + # simply waits until he's received them all, then performs a join on the respective capabilities + # as if it had been requested locally. + + joinId @0 :UInt32; + # A number identifying this join, chosen by the sender. May be reused once `Finish` messages are + # sent corresponding to all of the `Join` messages. + + partCount @1 :UInt16; + # The number of capabilities to be joined. + + partNum @2 :UInt16; + # Which part this request targets -- a number in the range [0, partCount). +} + +struct JoinResult { + joinId @0 :UInt32; + # Matches `JoinKeyPart`. + + succeeded @1 :Bool; + # All JoinResults in the set will have the same value for `succeeded`. The receiver actually + # implements the join by waiting for all the `JoinKeyParts` and then performing its own join on + # them, then going back and answering all the join requests afterwards. + + cap @2 :AnyPointer; + # One of the JoinResults will have a non-null `cap` which is the joined capability. + # + # TODO(cleanup): Change `AnyPointer` to `Capability` when that is supported. +} +using Go = import "/go.capnp"; +$Go.package("rpctwoparty"); +$Go.import("capnproto.org/go/capnp/v3/std/capnp/rpctwoparty"); diff --git a/crates/turborepo-lib/Source/hash/std/capnp/rpc.capnp b/crates/turborepo-lib/Source/hash/std/capnp/rpc.capnp new file mode 100644 index 0000000000000..4a54011d38693 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/rpc.capnp @@ -0,0 +1,1484 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xb312981b2552a250; +# Recall that Cap'n Proto RPC allows messages to contain references to remote objects that +# implement interfaces. These references are called "capabilities", because they both designate +# the remote object to use and confer permission to use it. +# +# Recall also that Cap'n Proto RPC has the feature that when a method call itself returns a +# capability, the caller can begin calling methods on that capability _before the first call has +# returned_. The caller essentially sends a message saying "Hey server, as soon as you finish +# that previous call, do this with the result!". Cap'n Proto's RPC protocol makes this possible. +# +# The protocol is significantly more complicated than most RPC protocols. However, this is +# implementation complexity that underlies an easy-to-grasp higher-level model of object oriented +# programming. That is, just like TCP is a surprisingly complicated protocol that implements a +# conceptually-simple byte stream abstraction, Cap'n Proto is a surprisingly complicated protocol +# that implements a conceptually-simple object abstraction. +# +# Cap'n Proto RPC is based heavily on CapTP, the object-capability protocol used by the E +# programming language: +# http://www.erights.org/elib/distrib/captp/index.html +# +# Cap'n Proto RPC takes place between "vats". A vat hosts some set of objects and talks to other +# vats through direct bilateral connections. Typically, there is a 1:1 correspondence between vats +# and processes (in the unix sense of the word), although this is not strictly always true (one +# process could run multiple vats, or a distributed virtual vat might live across many processes). +# +# Cap'n Proto does not distinguish between "clients" and "servers" -- this is up to the application. +# Either end of any connection can potentially hold capabilities pointing to the other end, and +# can call methods on those capabilities. In the doc comments below, we use the words "sender" +# and "receiver". These refer to the sender and receiver of an instance of the struct or field +# being documented. Sometimes we refer to a "third-party" that is neither the sender nor the +# receiver. Documentation is generally written from the point of view of the sender. +# +# It is generally up to the vat network implementation to securely verify that connections are made +# to the intended vat as well as to encrypt transmitted data for privacy and integrity. See the +# `VatNetwork` example interface near the end of this file. +# +# When a new connection is formed, the only interesting things that can be done are to send a +# `Bootstrap` (level 0) or `Accept` (level 3) message. +# +# Unless otherwise specified, messages must be delivered to the receiving application in the same +# order in which they were initiated by the sending application. The goal is to support "E-Order", +# which states that two calls made on the same reference must be delivered in the order which they +# were made: +# http://erights.org/elib/concurrency/partial-order.html +# +# Since the full protocol is complicated, we define multiple levels of support that an +# implementation may target. For many applications, level 1 support will be sufficient. +# Comments in this file indicate which level requires the corresponding feature to be +# implemented. +# +# * **Level 0:** The implementation does not support object references. Only the bootstrap interface +# can be called. At this level, the implementation does not support object-oriented protocols and +# is similar in complexity to JSON-RPC or Protobuf services. This level should be considered only +# a temporary stepping-stone toward level 1 as the lack of object references drastically changes +# how protocols are designed. Applications _should not_ attempt to design their protocols around +# the limitations of level 0 implementations. +# +# * **Level 1:** The implementation supports simple bilateral interaction with object references +# and promise pipelining, but interactions between three or more parties are supported only via +# proxying of objects. E.g. if Alice (in Vat A) wants to send Bob (in Vat B) a capability +# pointing to Carol (in Vat C), Alice must create a proxy of Carol within Vat A and send Bob a +# reference to that; Bob cannot form a direct connection to Carol. Level 1 implementations do +# not support checking if two capabilities received from different vats actually point to the +# same object ("join"), although they should be able to do this check on capabilities received +# from the same vat. +# +# * **Level 2:** The implementation supports saving persistent capabilities -- i.e. capabilities +# that remain valid even after disconnect, and can be restored on a future connection. When a +# capability is saved, the requester receives a `SturdyRef`, which is a token that can be used +# to restore the capability later. +# +# * **Level 3:** The implementation supports three-way interactions. That is, if Alice (in Vat A) +# sends Bob (in Vat B) a capability pointing to Carol (in Vat C), then Vat B will automatically +# form a direct connection to Vat C rather than have requests be proxied through Vat A. +# +# * **Level 4:** The entire protocol is implemented, including joins (checking if two capabilities +# are equivalent). +# +# Note that an implementation must also support specific networks (transports), as described in +# the "Network-specific Parameters" section below. An implementation might have different levels +# depending on the network used. +# +# New implementations of Cap'n Proto should start out targeting the simplistic two-party network +# type as defined in `rpc-twoparty.capnp`. With this network type, level 3 is irrelevant and +# levels 2 and 4 are much easier than usual to implement. When such an implementation is paired +# with a container proxy, the contained app effectively gets to make full use of the proxy's +# network at level 4. And since Cap'n Proto IPC is extremely fast, it may never make sense to +# bother implementing any other vat network protocol -- just use the correct container type and get +# it for free. + +using Cxx = import "/capnp/c++.capnp"; +$Cxx.namespace("capnp::rpc"); + +# ======================================================================================== +# The Four Tables +# +# Cap'n Proto RPC connections are stateful (although an application built on Cap'n Proto could +# export a stateless interface). As in CapTP, for each open connection, a vat maintains four state +# tables: questions, answers, imports, and exports. See the diagram at: +# http://www.erights.org/elib/distrib/captp/4tables.html +# +# The question table corresponds to the other end's answer table, and the imports table corresponds +# to the other end's exports table. +# +# The entries in each table are identified by ID numbers (defined below as 32-bit integers). These +# numbers are always specific to the connection; a newly-established connection starts with no +# valid IDs. Since low-numbered IDs will pack better, it is suggested that IDs be assigned like +# Unix file descriptors -- prefer the lowest-number ID that is currently available. +# +# IDs in the questions/answers tables are chosen by the questioner and generally represent method +# calls that are in progress. +# +# IDs in the imports/exports tables are chosen by the exporter and generally represent objects on +# which methods may be called. Exports may be "settled", meaning the exported object is an actual +# object living in the exporter's vat, or they may be "promises", meaning the exported object is +# the as-yet-unknown result of an ongoing operation and will eventually be resolved to some other +# object once that operation completes. Calls made to a promise will be forwarded to the eventual +# target once it is known. The eventual replacement object does *not* get the same ID as the +# promise, as it may turn out to be an object that is already exported (so already has an ID) or +# may even live in a completely different vat (and so won't get an ID on the same export table +# at all). +# +# IDs can be reused over time. To make this safe, we carefully define the lifetime of IDs. Since +# messages using the ID could be traveling in both directions simultaneously, we must define the +# end of life of each ID _in each direction_. The ID is only safe to reuse once it has been +# released by both sides. +# +# When a Cap'n Proto connection is lost, everything on the four tables is lost. All questions are +# canceled and throw exceptions. All imports become broken (all future calls to them throw +# exceptions). All exports and answers are implicitly released. The only things not lost are +# persistent capabilities (`SturdyRef`s). The application must plan for this and should respond by +# establishing a new connection and restoring from these persistent capabilities. + +using QuestionId = UInt32; +# **(level 0)** +# +# Identifies a question in the sender's question table (which corresponds to the receiver's answer +# table). The questioner (caller) chooses an ID when making a call. The ID remains valid in +# caller -> callee messages until a Finish message is sent, and remains valid in callee -> caller +# messages until a Return message is sent. + +using AnswerId = QuestionId; +# **(level 0)** +# +# Identifies an answer in the sender's answer table (which corresponds to the receiver's question +# table). +# +# AnswerId is physically equivalent to QuestionId, since the question and answer tables correspond, +# but we define a separate type for documentation purposes: we always use the type representing +# the sender's point of view. + +using ExportId = UInt32; +# **(level 1)** +# +# Identifies an exported capability or promise in the sender's export table (which corresponds +# to the receiver's import table). The exporter chooses an ID before sending a capability over the +# wire. If the capability is already in the table, the exporter should reuse the same ID. If the +# ID is a promise (as opposed to a settled capability), this must be indicated at the time the ID +# is introduced (e.g. by using `senderPromise` instead of `senderHosted` in `CapDescriptor`); in +# this case, the importer shall expect a later `Resolve` message that replaces the promise. +# +# ExportId/ImportIds are subject to reference counting. Whenever an `ExportId` is sent over the +# wire (from the exporter to the importer), the export's reference count is incremented (unless +# otherwise specified). The reference count is later decremented by a `Release` message. Since +# the `Release` message can specify an arbitrary number by which to reduce the reference count, the +# importer should usually batch reference decrements and only send a `Release` when it believes the +# reference count has hit zero. Of course, it is possible that a new reference to the export is +# in-flight at the time that the `Release` message is sent, so it is necessary for the exporter to +# keep track of the reference count on its end as well to avoid race conditions. +# +# When a connection is lost, all exports are implicitly released. It is not possible to restore +# a connection state after disconnect (although a transport layer could implement a concept of +# persistent connections if it is transparent to the RPC layer). + +using ImportId = ExportId; +# **(level 1)** +# +# Identifies an imported capability or promise in the sender's import table (which corresponds to +# the receiver's export table). +# +# ImportId is physically equivalent to ExportId, since the export and import tables correspond, +# but we define a separate type for documentation purposes: we always use the type representing +# the sender's point of view. +# +# An `ImportId` remains valid in importer -> exporter messages until the importer has sent +# `Release` messages that (it believes) have reduced the reference count to zero. + +# ======================================================================================== +# Messages + +struct Message { + # An RPC connection is a bi-directional stream of Messages. + + union { + unimplemented @0 :Message; + # The sender previously received this message from the peer but didn't understand it or doesn't + # yet implement the functionality that was requested. So, the sender is echoing the message + # back. In some cases, the receiver may be able to recover from this by pretending the sender + # had taken some appropriate "null" action. + # + # For example, say `resolve` is received by a level 0 implementation (because a previous call + # or return happened to contain a promise). The level 0 implementation will echo it back as + # `unimplemented`. The original sender can then simply release the cap to which the promise + # had resolved, thus avoiding a leak. + # + # For any message type that introduces a question, if the message comes back unimplemented, + # the original sender may simply treat it as if the question failed with an exception. + # + # In cases where there is no sensible way to react to an `unimplemented` message (without + # resource leaks or other serious problems), the connection may need to be aborted. This is + # a gray area; different implementations may take different approaches. + + abort @1 :Exception; + # Sent when a connection is being aborted due to an unrecoverable error. This could be e.g. + # because the sender received an invalid or nonsensical message or because the sender had an + # internal error. The sender will shut down the outgoing half of the connection after `abort` + # and will completely close the connection shortly thereafter (it's up to the sender how much + # of a time buffer they want to offer for the client to receive the `abort` before the + # connection is reset). + + # Level 0 features ----------------------------------------------- + + bootstrap @8 :Bootstrap; # Request the peer's bootstrap interface. + call @2 :Call; # Begin a method call. + return @3 :Return; # Complete a method call. + finish @4 :Finish; # Release a returned answer / cancel a call. + + # Level 1 features ----------------------------------------------- + + resolve @5 :Resolve; # Resolve a previously-sent promise. + release @6 :Release; # Release a capability so that the remote object can be deallocated. + disembargo @13 :Disembargo; # Lift an embargo used to enforce E-order over promise resolution. + + # Level 2 features ----------------------------------------------- + + obsoleteSave @7 :AnyPointer; + # Obsolete request to save a capability, resulting in a SturdyRef. This has been replaced + # by the `Persistent` interface defined in `persistent.capnp`. This operation was never + # implemented. + + obsoleteDelete @9 :AnyPointer; + # Obsolete way to delete a SturdyRef. This operation was never implemented. + + # Level 3 features ----------------------------------------------- + + provide @10 :Provide; # Provide a capability to a third party. + accept @11 :Accept; # Accept a capability provided by a third party. + + # Level 4 features ----------------------------------------------- + + join @12 :Join; # Directly connect to the common root of two or more proxied caps. + } +} + +# Level 0 message types ---------------------------------------------- + +struct Bootstrap { + # **(level 0)** + # + # Get the "bootstrap" interface exported by the remote vat. + # + # For level 0, 1, and 2 implementations, the "bootstrap" interface is simply the main interface + # exported by a vat. If the vat acts as a server fielding connections from clients, then the + # bootstrap interface defines the basic functionality available to a client when it connects. + # The exact interface definition obviously depends on the application. + # + # We call this a "bootstrap" because in an ideal Cap'n Proto world, bootstrap interfaces would + # never be used. In such a world, any time you connect to a new vat, you do so because you + # received an introduction from some other vat (see `ThirdPartyCapId`). Thus, the first message + # you send is `Accept`, and further communications derive from there. `Bootstrap` is not used. + # + # In such an ideal world, DNS itself would support Cap'n Proto -- performing a DNS lookup would + # actually return a new Cap'n Proto capability, thus introducing you to the target system via + # level 3 RPC. Applications would receive the capability to talk to DNS in the first place as + # an initial endowment or part of a Powerbox interaction. Therefore, an app can form arbitrary + # connections without ever using `Bootstrap`. + # + # Of course, in the real world, DNS is not Cap'n-Proto-based, and we don't want Cap'n Proto to + # require a whole new internet infrastructure to be useful. Therefore, we offer bootstrap + # interfaces as a way to get up and running without a level 3 introduction. Thus, bootstrap + # interfaces are used to "bootstrap" from other, non-Cap'n-Proto-based means of service discovery, + # such as legacy DNS. + # + # Note that a vat need not provide a bootstrap interface, and in fact many vats (especially those + # acting as clients) do not. In this case, the vat should either reply to `Bootstrap` with a + # `Return` indicating an exception, or should return a dummy capability with no methods. + + questionId @0 :QuestionId; + # A new question ID identifying this request, which will eventually receive a Return message + # containing the restored capability. + + deprecatedObjectId @1 :AnyPointer; + # ** DEPRECATED ** + # + # A Vat may export multiple bootstrap interfaces. In this case, `deprecatedObjectId` specifies + # which one to return. If this pointer is null, then the default bootstrap interface is returned. + # + # As of verison 0.5, use of this field is deprecated. If a service wants to export multiple + # bootstrap interfaces, it should instead define a single bootstrap interface that has methods + # that return each of the other interfaces. + # + # **History** + # + # In the first version of Cap'n Proto RPC (0.4.x) the `Bootstrap` message was called `Restore`. + # At the time, it was thought that this would eventually serve as the way to restore SturdyRefs + # (level 2). Meanwhile, an application could offer its "main" interface on a well-known + # (non-secret) SturdyRef. + # + # Since level 2 RPC was not implemented at the time, the `Restore` message was in practice only + # used to obtain the main interface. Since most applications had only one main interface that + # they wanted to restore, they tended to designate this with a null `objectId`. + # + # Unfortunately, the earliest version of the EZ RPC interfaces set a precedent of exporting + # multiple main interfaces by allowing them to be exported under string names. In this case, + # `objectId` was a Text value specifying the name. + # + # All of this proved problematic for several reasons: + # + # - The arrangement assumed that a client wishing to restore a SturdyRef would know exactly what + # machine to connect to and would be able to immediately restore a SturdyRef on connection. + # However, in practice, the ability to restore SturdyRefs is itself a capability that may + # require going through an authentication process to obtain. Thus, it makes more sense to + # define a "restorer service" as a full Cap'n Proto interface. If this restorer interface is + # offered as the vat's bootstrap interface, then this is equivalent to the old arrangement. + # + # - Overloading "Restore" for the purpose of obtaining well-known capabilities encouraged the + # practice of exporting singleton services with string names. If singleton services are desired, + # it is better to have one main interface that has methods that can be used to obtain each + # service, in order to get all the usual benefits of schemas and type checking. + # + # - Overloading "Restore" also had a security problem: Often, "main" or "well-known" + # capabilities exported by a vat are in fact not public: they are intended to be accessed only + # by clients who are capable of forming a connection to the vat. This can lead to trouble if + # the client itself has other clients and wishes to foward some `Restore` requests from those + # external clients -- it has to be very careful not to allow through `Restore` requests + # addressing the default capability. + # + # For example, consider the case of a sandboxed Sandstorm application and its supervisor. The + # application exports a default capability to its supervisor that provides access to + # functionality that only the supervisor is supposed to access. Meanwhile, though, applications + # may publish other capabilities that may be persistent, in which case the application needs + # to field `Restore` requests that could come from anywhere. These requests of course have to + # pass through the supervisor, as all communications with the outside world must. But, the + # supervisor has to be careful not to honor an external request addressing the application's + # default capability, since this capability is privileged. Unfortunately, the default + # capability cannot be given an unguessable name, because then the supervisor itself would not + # be able to address it! + # + # As of Cap'n Proto 0.5, `Restore` has been renamed to `Bootstrap` and is no longer planned for + # use in restoring SturdyRefs. + # + # Note that 0.4 also defined a message type called `Delete` that, like `Restore`, addressed a + # SturdyRef, but indicated that the client would not restore the ref again in the future. This + # operation was never implemented, so it was removed entirely. If a "delete" operation is desired, + # it should exist as a method on the same interface that handles restoring SturdyRefs. However, + # the utility of such an operation is questionable. You wouldn't be able to rely on it for + # garbage collection since a client could always disappear permanently without remembering to + # delete all its SturdyRefs, thus leaving them dangling forever. Therefore, it is advisable to + # design systems such that SturdyRefs never represent "owned" pointers. + # + # For example, say a SturdyRef points to an image file hosted on some server. That image file + # should also live inside a collection (a gallery, perhaps) hosted on the same server, owned by + # a user who can delete the image at any time. If the user deletes the image, the SturdyRef + # stops working. On the other hand, if the SturdyRef is discarded, this has no effect on the + # existence of the image in its collection. +} + +struct Call { + # **(level 0)** + # + # Message type initiating a method call on a capability. + + questionId @0 :QuestionId; + # A number, chosen by the caller, that identifies this call in future messages. This number + # must be different from all other calls originating from the same end of the connection (but + # may overlap with question IDs originating from the opposite end). A fine strategy is to use + # sequential question IDs, but the recipient should not assume this. + # + # A question ID can be reused once both: + # - A matching Return has been received from the callee. + # - A matching Finish has been sent from the caller. + + target @1 :MessageTarget; + # The object that should receive this call. + + interfaceId @2 :UInt64; + # The type ID of the interface being called. Each capability may implement multiple interfaces. + + methodId @3 :UInt16; + # The ordinal number of the method to call within the requested interface. + + allowThirdPartyTailCall @8 :Bool = false; + # Indicates whether or not the receiver is allowed to send a `Return` containing + # `acceptFromThirdParty`. Level 3 implementations should set this true. Otherwise, the callee + # will have to proxy the return in the case of a tail call to a third-party vat. + + params @4 :Payload; + # The call parameters. `params.content` is a struct whose fields correspond to the parameters of + # the method. + + sendResultsTo :union { + # Where should the return message be sent? + + caller @5 :Void; + # Send the return message back to the caller (the usual). + + yourself @6 :Void; + # **(level 1)** + # + # Don't actually return the results to the sender. Instead, hold on to them and await + # instructions from the sender regarding what to do with them. In particular, the sender + # may subsequently send a `Return` for some other call (which the receiver had previously made + # to the sender) with `takeFromOtherQuestion` set. The results from this call are then used + # as the results of the other call. + # + # When `yourself` is used, the receiver must still send a `Return` for the call, but sets the + # field `resultsSentElsewhere` in that `Return` rather than including the results. + # + # This feature can be used to implement tail calls in which a call from Vat A to Vat B ends up + # returning the result of a call from Vat B back to Vat A. + # + # In particular, the most common use case for this feature is when Vat A makes a call to a + # promise in Vat B, and then that promise ends up resolving to a capability back in Vat A. + # Vat B must forward all the queued calls on that promise back to Vat A, but can set `yourself` + # in the calls so that the results need not pass back through Vat B. + # + # For example: + # - Alice, in Vat A, calls foo() on Bob in Vat B. + # - Alice makes a pipelined call bar() on the promise returned by foo(). + # - Later on, Bob resolves the promise from foo() to point at Carol, who lives in Vat A (next + # to Alice). + # - Vat B dutifully forwards the bar() call to Carol. Let us call this forwarded call bar'(). + # Notice that bar() and bar'() are travelling in opposite directions on the same network + # link. + # - The `Call` for bar'() has `sendResultsTo` set to `yourself`. + # - Vat B sends a `Return` for bar() with `takeFromOtherQuestion` set in place of the results, + # with the value set to the question ID of bar'(). Vat B does not wait for bar'() to return, + # as doing so would introduce unnecessary round trip latency. + # - Vat A receives bar'() and delivers it to Carol. + # - When bar'() returns, Vat A sends a `Return` for bar'() to Vat B, with `resultsSentElsewhere` + # set in place of results. + # - Vat A sends a `Finish` for the bar() call to Vat B. + # - Vat B receives the `Finish` for bar() and sends a `Finish` for bar'(). + + thirdParty @7 :RecipientId; + # **(level 3)** + # + # The call's result should be returned to a different vat. The receiver (the callee) expects + # to receive an `Accept` message from the indicated vat, and should return the call's result + # to it, rather than to the sender of the `Call`. + # + # This operates much like `yourself`, above, except that Carol is in a separate Vat C. `Call` + # messages are sent from Vat A -> Vat B and Vat B -> Vat C. A `Return` message is sent from + # Vat B -> Vat A that contains `acceptFromThirdParty` in place of results. When Vat A sends + # an `Accept` to Vat C, it receives back a `Return` containing the call's actual result. Vat C + # also sends a `Return` to Vat B with `resultsSentElsewhere`. + } +} + +struct Return { + # **(level 0)** + # + # Message type sent from callee to caller indicating that the call has completed. + + answerId @0 :AnswerId; + # Equal to the QuestionId of the corresponding `Call` message. + + releaseParamCaps @1 :Bool = true; + # If true, all capabilities that were in the params should be considered released. The sender + # must not send separate `Release` messages for them. Level 0 implementations in particular + # should always set this true. This defaults true because if level 0 implementations forget to + # set it they'll never notice (just silently leak caps), but if level >=1 implementations forget + # to set it to false they'll quickly get errors. + # + # The receiver should act as if the sender had sent a release message with count=1 for each + # CapDescriptor in the original Call message. + + union { + results @2 :Payload; + # The result. + # + # For regular method calls, `results.content` points to the result struct. + # + # For a `Return` in response to an `Accept` or `Bootstrap`, `results` contains a single + # capability (rather than a struct), and `results.content` is just a capability pointer with + # index 0. A `Finish` is still required in this case. + + exception @3 :Exception; + # Indicates that the call failed and explains why. + + canceled @4 :Void; + # Indicates that the call was canceled due to the caller sending a Finish message + # before the call had completed. + + resultsSentElsewhere @5 :Void; + # This is set when returning from a `Call` that had `sendResultsTo` set to something other + # than `caller`. + # + # It doesn't matter too much when this is sent, as the receiver doesn't need to do anything + # with it, but the C++ implementation appears to wait for the call to finish before sending + # this. + + takeFromOtherQuestion @6 :QuestionId; + # The sender has also sent (before this message) a `Call` with the given question ID and with + # `sendResultsTo.yourself` set, and the results of that other call should be used as the + # results here. `takeFromOtherQuestion` can only used once per question. + + acceptFromThirdParty @7 :ThirdPartyCapId; + # **(level 3)** + # + # The caller should contact a third-party vat to pick up the results. An `Accept` message + # sent to the vat will return the result. This pairs with `Call.sendResultsTo.thirdParty`. + # It should only be used if the corresponding `Call` had `allowThirdPartyTailCall` set. + } +} + +struct Finish { + # **(level 0)** + # + # Message type sent from the caller to the callee to indicate: + # 1) The questionId will no longer be used in any messages sent by the callee (no further + # pipelined requests). + # 2) If the call has not returned yet, the caller no longer cares about the result. If nothing + # else cares about the result either (e.g. there are no other outstanding calls pipelined on + # the result of this one) then the callee may wish to immediately cancel the operation and + # send back a Return message with "canceled" set. However, implementations are not required + # to support premature cancellation -- instead, the implementation may wait until the call + # actually completes and send a normal `Return` message. + # + # TODO(someday): Should we separate (1) and implicitly releasing result capabilities? It would be + # possible and useful to notify the server that it doesn't need to keep around the response to + # service pipeline requests even though the caller still wants to receive it / hasn't yet + # finished processing it. It could also be useful to notify the server that it need not marshal + # the results because the caller doesn't want them anyway, even if the caller is still sending + # pipelined calls, although this seems less useful (just saving some bytes on the wire). + + questionId @0 :QuestionId; + # ID of the call whose result is to be released. + + releaseResultCaps @1 :Bool = true; + # If true, all capabilities that were in the results should be considered released. The sender + # must not send separate `Release` messages for them. Level 0 implementations in particular + # should always set this true. This defaults true because if level 0 implementations forget to + # set it they'll never notice (just silently leak caps), but if level >=1 implementations forget + # set it false they'll quickly get errors. +} + +# Level 1 message types ---------------------------------------------- + +struct Resolve { + # **(level 1)** + # + # Message type sent to indicate that a previously-sent promise has now been resolved to some other + # object (possibly another promise) -- or broken, or canceled. + # + # Keep in mind that it's possible for a `Resolve` to be sent to a level 0 implementation that + # doesn't implement it. For example, a method call or return might contain a capability in the + # payload. Normally this is fine even if the receiver is level 0, because they will implicitly + # release all such capabilities on return / finish. But if the cap happens to be a promise, then + # a follow-up `Resolve` may be sent regardless of this release. The level 0 receiver will reply + # with an `unimplemented` message, and the sender (of the `Resolve`) can respond to this as if the + # receiver had immediately released any capability to which the promise resolved. + # + # When implementing promise resolution, it's important to understand how embargos work and the + # tricky case of the Tribble 4-way race condition. See the comments for the Disembargo message, + # below. + + promiseId @0 :ExportId; + # The ID of the promise to be resolved. + # + # Unlike all other instances of `ExportId` sent from the exporter, the `Resolve` message does + # _not_ increase the reference count of `promiseId`. In fact, it is expected that the receiver + # will release the export soon after receiving `Resolve`, and the sender will not send this + # `ExportId` again until it has been released and recycled. + # + # When an export ID sent over the wire (e.g. in a `CapDescriptor`) is indicated to be a promise, + # this indicates that the sender will follow up at some point with a `Resolve` message. If the + # same `promiseId` is sent again before `Resolve`, still only one `Resolve` is sent. If the + # same ID is sent again later _after_ a `Resolve`, it can only be because the export's + # reference count hit zero in the meantime and the ID was re-assigned to a new export, therefore + # this later promise does _not_ correspond to the earlier `Resolve`. + # + # If a promise ID's reference count reaches zero before a `Resolve` is sent, the `Resolve` + # message may or may not still be sent (the `Resolve` may have already been in-flight when + # `Release` was sent, but if the `Release` is received before `Resolve` then there is no longer + # any reason to send a `Resolve`). Thus a `Resolve` may be received for a promise of which + # the receiver has no knowledge, because it already released it earlier. In this case, the + # receiver should simply release the capability to which the promise resolved. + + union { + cap @1 :CapDescriptor; + # The object to which the promise resolved. + # + # The sender promises that from this point forth, until `promiseId` is released, it shall + # simply forward all messages to the capability designated by `cap`. This is true even if + # `cap` itself happens to designate another promise, and that other promise later resolves -- + # messages sent to `promiseId` shall still go to that other promise, not to its resolution. + # This is important in the case that the receiver of the `Resolve` ends up sending a + # `Disembargo` message towards `promiseId` in order to control message ordering -- that + # `Disembargo` really needs to reflect back to exactly the object designated by `cap` even + # if that object is itself a promise. + + exception @2 :Exception; + # Indicates that the promise was broken. + } +} + +struct Release { + # **(level 1)** + # + # Message type sent to indicate that the sender is done with the given capability and the receiver + # can free resources allocated to it. + + id @0 :ImportId; + # What to release. + + referenceCount @1 :UInt32; + # The amount by which to decrement the reference count. The export is only actually released + # when the reference count reaches zero. +} + +struct Disembargo { + # **(level 1)** + # + # Message sent to indicate that an embargo on a recently-resolved promise may now be lifted. + # + # Embargos are used to enforce E-order in the presence of promise resolution. That is, if an + # application makes two calls foo() and bar() on the same capability reference, in that order, + # the calls should be delivered in the order in which they were made. But if foo() is called + # on a promise, and that promise happens to resolve before bar() is called, then the two calls + # may travel different paths over the network, and thus could arrive in the wrong order. In + # this case, the call to `bar()` must be embargoed, and a `Disembargo` message must be sent along + # the same path as `foo()` to ensure that the `Disembargo` arrives after `foo()`. Once the + # `Disembargo` arrives, `bar()` can then be delivered. + # + # There are two particular cases where embargos are important. Consider object Alice, in Vat A, + # who holds a promise P, pointing towards Vat B, that eventually resolves to Carol. The two + # cases are: + # - Carol lives in Vat A, i.e. next to Alice. In this case, Vat A needs to send a `Disembargo` + # message that echos through Vat B and back, to ensure that all pipelined calls on the promise + # have been delivered. + # - Carol lives in a different Vat C. When the promise resolves, a three-party handoff occurs + # (see `Provide` and `Accept`, which constitute level 3 of the protocol). In this case, we + # piggyback on the state that has already been set up to handle the handoff: the `Accept` + # message (from Vat A to Vat C) is embargoed, as are all pipelined messages sent to it, while + # a `Disembargo` message is sent from Vat A through Vat B to Vat C. See `Accept.embargo` for + # an example. + # + # Note that in the case where Carol actually lives in Vat B (i.e., the same vat that the promise + # already pointed at), no embargo is needed, because the pipelined calls are delivered over the + # same path as the later direct calls. + # + # Keep in mind that promise resolution happens both in the form of Resolve messages as well as + # Return messages (which resolve PromisedAnswers). Embargos apply in both cases. + # + # An alternative strategy for enforcing E-order over promise resolution could be for Vat A to + # implement the embargo internally. When Vat A is notified of promise resolution, it could + # send a dummy no-op call to promise P and wait for it to complete. Until that call completes, + # all calls to the capability are queued locally. This strategy works, but is pessimistic: + # in the three-party case, it requires an A -> B -> C -> B -> A round trip before calls can start + # being delivered directly to from Vat A to Vat C. The `Disembargo` message allows latency to be + # reduced. (In the two-party loopback case, the `Disembargo` message is just a more explicit way + # of accomplishing the same thing as a no-op call, but isn't any faster.) + # + # *The Tribble 4-way Race Condition* + # + # Any implementation of promise resolution and embargos must be aware of what we call the + # "Tribble 4-way race condition", after Dean Tribble, who explained the problem in a lively + # Friam meeting. + # + # Embargos are designed to work in the case where a two-hop path is being shortened to one hop. + # But sometimes there are more hops. Imagine that Alice has a reference to a remote promise P1 + # that eventually resolves to _another_ remote promise P2 (in a third vat), which _at the same + # time_ happens to resolve to Bob (in a fourth vat). In this case, we're shortening from a 3-hop + # path (with four parties) to a 1-hop path (Alice -> Bob). + # + # Extending the embargo/disembargo protocol to be able to shorted multiple hops at once seems + # difficult. Instead, we make a rule that prevents this case from coming up: + # + # One a promise P has been resolved to a remote object reference R, then all further messages + # received addressed to P will be forwarded strictly to R. Even if it turns out later that R is + # itself a promise, and has resolved to some other object Q, messages sent to P will still be + # forwarded to R, not directly to Q (R will of course further forward the messages to Q). + # + # This rule does not cause a significant performance burden because once P has resolved to R, it + # is expected that people sending messages to P will shortly start sending them to R instead and + # drop P. P is at end-of-life anyway, so it doesn't matter if it ignores chances to further + # optimize its path. + + target @0 :MessageTarget; + # What is to be disembargoed. + + using EmbargoId = UInt32; + # Used in `senderLoopback` and `receiverLoopback`, below. + + context :union { + senderLoopback @1 :EmbargoId; + # The sender is requesting a disembargo on a promise that is known to resolve back to a + # capability hosted by the sender. As soon as the receiver has echoed back all pipelined calls + # on this promise, it will deliver the Disembargo back to the sender with `receiverLoopback` + # set to the same value as `senderLoopback`. This value is chosen by the sender, and since + # it is also consumed be the sender, the sender can use whatever strategy it wants to make sure + # the value is unambiguous. + # + # The receiver must verify that the target capability actually resolves back to the sender's + # vat. Otherwise, the sender has committed a protocol error and should be disconnected. + + receiverLoopback @2 :EmbargoId; + # The receiver previously sent a `senderLoopback` Disembargo towards a promise resolving to + # this capability, and that Disembargo is now being echoed back. + + accept @3 :Void; + # **(level 3)** + # + # The sender is requesting a disembargo on a promise that is known to resolve to a third-party + # capability that the sender is currently in the process of accepting (using `Accept`). + # The receiver of this `Disembargo` has an outstanding `Provide` on said capability. The + # receiver should now send a `Disembargo` with `provide` set to the question ID of that + # `Provide` message. + # + # See `Accept.embargo` for an example. + + provide @4 :QuestionId; + # **(level 3)** + # + # The sender is requesting a disembargo on a capability currently being provided to a third + # party. The question ID identifies the `Provide` message previously sent by the sender to + # this capability. On receipt, the receiver (the capability host) shall release the embargo + # on the `Accept` message that it has received from the third party. See `Accept.embargo` for + # an example. + } +} + +# Level 2 message types ---------------------------------------------- + +# See persistent.capnp. + +# Level 3 message types ---------------------------------------------- + +struct Provide { + # **(level 3)** + # + # Message type sent to indicate that the sender wishes to make a particular capability implemented + # by the receiver available to a third party for direct access (without the need for the third + # party to proxy through the sender). + # + # (In CapTP, `Provide` and `Accept` are methods of the global `NonceLocator` object exported by + # every vat. In Cap'n Proto, we bake this into the core protocol.) + + questionId @0 :QuestionId; + # Question ID to be held open until the recipient has received the capability. A result will be + # returned once the third party has successfully received the capability. The sender must at some + # point send a `Finish` message as with any other call, and that message can be used to cancel the + # whole operation. + + target @1 :MessageTarget; + # What is to be provided to the third party. + + recipient @2 :RecipientId; + # Identity of the third party that is expected to pick up the capability. +} + +struct Accept { + # **(level 3)** + # + # Message type sent to pick up a capability hosted by the receiving vat and provided by a third + # party. The third party previously designated the capability using `Provide`. + # + # This message is also used to pick up a redirected return -- see `Return.acceptFromThirdParty`. + + questionId @0 :QuestionId; + # A new question ID identifying this accept message, which will eventually receive a Return + # message containing the provided capability (or the call result in the case of a redirected + # return). + + provision @1 :ProvisionId; + # Identifies the provided object to be picked up. + + embargo @2 :Bool; + # If true, this accept shall be temporarily embargoed. The resulting `Return` will not be sent, + # and any pipelined calls will not be delivered, until the embargo is released. The receiver + # (the capability host) will expect the provider (the vat that sent the `Provide` message) to + # eventually send a `Disembargo` message with the field `context.provide` set to the question ID + # of the original `Provide` message. At that point, the embargo is released and the queued + # messages are delivered. + # + # For example: + # - Alice, in Vat A, holds a promise P, which currently points toward Vat B. + # - Alice calls foo() on P. The `Call` message is sent to Vat B. + # - The promise P in Vat B ends up resolving to Carol, in Vat C. + # - Vat B sends a `Provide` message to Vat C, identifying Vat A as the recipient. + # - Vat B sends a `Resolve` message to Vat A, indicating that the promise has resolved to a + # `ThirdPartyCapId` identifying Carol in Vat C. + # - Vat A sends an `Accept` message to Vat C to pick up the capability. Since Vat A knows that + # it has an outstanding call to the promise, it sets `embargo` to `true` in the `Accept` + # message. + # - Vat A sends a `Disembargo` message to Vat B on promise P, with `context.accept` set. + # - Alice makes a call bar() to promise P, which is now pointing towards Vat C. Alice doesn't + # know anything about the mechanics of promise resolution happening under the hood, but she + # expects that bar() will be delivered after foo() because that is the order in which she + # initiated the calls. + # - Vat A sends the bar() call to Vat C, as a pipelined call on the result of the `Accept` (which + # hasn't returned yet, due to the embargo). Since calls to the newly-accepted capability + # are embargoed, Vat C does not deliver the call yet. + # - At some point, Vat B forwards the foo() call from the beginning of this example on to Vat C. + # - Vat B forwards the `Disembargo` from Vat A on to vat C. It sets `context.provide` to the + # question ID of the `Provide` message it had sent previously. + # - Vat C receives foo() before `Disembargo`, thus allowing it to correctly deliver foo() + # before delivering bar(). + # - Vat C receives `Disembargo` from Vat B. It can now send a `Return` for the `Accept` from + # Vat A, as well as deliver bar(). +} + +# Level 4 message types ---------------------------------------------- + +struct Join { + # **(level 4)** + # + # Message type sent to implement E.join(), which, given a number of capabilities that are + # expected to be equivalent, finds the underlying object upon which they all agree and forms a + # direct connection to it, skipping any proxies that may have been constructed by other vats + # while transmitting the capability. See: + # http://erights.org/elib/equality/index.html + # + # Note that this should only serve to bypass fully-transparent proxies -- proxies that were + # created merely for convenience, without any intention of hiding the underlying object. + # + # For example, say Bob holds two capabilities hosted by Alice and Carol, but he expects that both + # are simply proxies for a capability hosted elsewhere. He then issues a join request, which + # operates as follows: + # - Bob issues Join requests on both Alice and Carol. Each request contains a different piece + # of the JoinKey. + # - Alice is proxying a capability hosted by Dana, so forwards the request to Dana's cap. + # - Dana receives the first request and sees that the JoinKeyPart is one of two. She notes that + # she doesn't have the other part yet, so she records the request and responds with a + # JoinResult. + # - Alice relays the JoinAnswer back to Bob. + # - Carol is also proxying a capability from Dana, and so forwards her Join request to Dana as + # well. + # - Dana receives Carol's request and notes that she now has both parts of a JoinKey. She + # combines them in order to form information needed to form a secure connection to Bob. She + # also responds with another JoinResult. + # - Bob receives the responses from Alice and Carol. He uses the returned JoinResults to + # determine how to connect to Dana and attempts to form the connection. Since Bob and Dana now + # agree on a secret key that neither Alice nor Carol ever saw, this connection can be made + # securely even if Alice or Carol is conspiring against the other. (If Alice and Carol are + # conspiring _together_, they can obviously reproduce the key, but this doesn't matter because + # the whole point of the join is to verify that Alice and Carol agree on what capability they + # are proxying.) + # + # If the two capabilities aren't actually proxies of the same object, then the join requests + # will come back with conflicting `hostId`s and the join will fail before attempting to form any + # connection. + + questionId @0 :QuestionId; + # Question ID used to respond to this Join. (Note that this ID only identifies one part of the + # request for one hop; each part has a different ID and relayed copies of the request have + # (probably) different IDs still.) + # + # The receiver will reply with a `Return` whose `results` is a JoinResult. This `JoinResult` + # is relayed from the joined object's host, possibly with transformation applied as needed + # by the network. + # + # Like any return, the result must be released using a `Finish`. However, this release + # should not occur until the joiner has either successfully connected to the joined object. + # Vats relaying a `Join` message similarly must not release the result they receive until the + # return they relayed back towards the joiner has itself been released. This allows the + # joined object's host to detect when the Join operation is canceled before completing -- if + # it receives a `Finish` for one of the join results before the joiner successfully + # connects. It can then free any resources it had allocated as part of the join. + + target @1 :MessageTarget; + # The capability to join. + + keyPart @2 :JoinKeyPart; + # A part of the join key. These combine to form the complete join key, which is used to establish + # a direct connection. + + # TODO(before implementing): Change this so that multiple parts can be sent in a single Join + # message, so that if multiple join parts are going to cross the same connection they can be sent + # together, so that the receive can potentially optimize its handling of them. In the case where + # all parts are bundled together, should the recipient be expected to simply return a cap, so + # that the caller can immediately start pipelining to it? +} + +# ======================================================================================== +# Common structures used in messages + +struct MessageTarget { + # The target of a `Call` or other messages that target a capability. + + union { + importedCap @0 :ImportId; + # This message is to a capability or promise previously imported by the caller (exported by + # the receiver). + + promisedAnswer @1 :PromisedAnswer; + # This message is to a capability that is expected to be returned by another call that has not + # yet been completed. + # + # At level 0, this is supported only for addressing the result of a previous `Bootstrap`, so + # that initial startup doesn't require a round trip. + } +} + +struct Payload { + # Represents some data structure that might contain capabilities. + + content @0 :AnyPointer; + # Some Cap'n Proto data structure. Capability pointers embedded in this structure index into + # `capTable`. + + capTable @1 :List(CapDescriptor); + # Descriptors corresponding to the cap pointers in `content`. +} + +struct CapDescriptor { + # **(level 1)** + # + # When an application-defined type contains an interface pointer, that pointer contains an index + # into the message's capability table -- i.e. the `capTable` part of the `Payload`. Each + # capability in the table is represented as a `CapDescriptor`. The runtime API should not reveal + # the CapDescriptor directly to the application, but should instead wrap it in some kind of + # callable object with methods corresponding to the interface that the capability implements. + # + # Keep in mind that `ExportIds` in a `CapDescriptor` are subject to reference counting. See the + # description of `ExportId`. + # + # Note that it is currently not possible to include a broken capability in the CapDescriptor + # table. Instead, create a new export (`senderPromise`) for each broken capability and then + # immediately follow the payload-bearing Call or Return message with one Resolve message for each + # broken capability, resolving it to an exception. + + union { + none @0 :Void; + # There is no capability here. This `CapDescriptor` should not appear in the payload content. + # A `none` CapDescriptor can be generated when an application inserts a capability into a + # message and then later changes its mind and removes it -- rewriting all of the other + # capability pointers may be hard, so instead a tombstone is left, similar to the way a removed + # struct or list instance is zeroed out of the message but the space is not reclaimed. + # Hopefully this is unusual. + + senderHosted @1 :ExportId; + # The ID of a capability in the sender's export table (receiver's import table). It may be a + # newly allocated table entry, or an existing entry (increments the reference count). + + senderPromise @2 :ExportId; + # A promise that the sender will resolve later. The sender will send exactly one Resolve + # message at a future point in time to replace this promise. Note that even if the same + # `senderPromise` is received multiple times, only one `Resolve` is sent to cover all of + # them. If `senderPromise` is released before the `Resolve` is sent, the sender (of this + # `CapDescriptor`) may choose not to send the `Resolve` at all. + + receiverHosted @3 :ImportId; + # A capability (or promise) previously exported by the receiver (imported by the sender). + + receiverAnswer @4 :PromisedAnswer; + # A capability expected to be returned in the results of a currently-outstanding call posed + # by the sender. + + thirdPartyHosted @5 :ThirdPartyCapDescriptor; + # **(level 3)** + # + # A capability that lives in neither the sender's nor the receiver's vat. The sender needs + # to form a direct connection to a third party to pick up the capability. + # + # Level 1 and 2 implementations that receive a `thirdPartyHosted` may simply send calls to its + # `vine` instead. + } + + attachedFd @6 :UInt8 = 0xff; + # If the RPC message in which this CapDescriptor was delivered also had file descriptors + # attached, and `fd` is a valid index into the list of attached file descriptors, then + # that file descriptor should be attached to this capability. If `attachedFd` is out-of-bounds + # for said list, then no FD is attached. + # + # For example, if the RPC message arrived over a Unix socket, then file descriptors may be + # attached by sending an SCM_RIGHTS ancillary message attached to the data bytes making up the + # raw message. Receivers who wish to opt into FD passing should arrange to receive SCM_RIGHTS + # whenever receiving an RPC message. Senders who wish to send FDs need not verify whether the + # receiver knows how to receive them, because the operating system will automatically discard + # ancillary messages like SCM_RIGHTS if the receiver doesn't ask to receive them, including + # automatically closing any FDs. + # + # It is up to the application protocol to define what capabilities are expected to have file + # descriptors attached, and what those FDs mean. But, for example, an application could use this + # to open a file on disk and then transmit the open file descriptor to a sandboxed process that + # does not otherwise have permission to access the filesystem directly. This is usually an + # optimization: the sending process could instead provide an RPC interface supporting all the + # operations needed (such as reading and writing a file), but by passing the file descriptor + # directly, the recipient can often perform operations much more efficiently. Application + # designers are encouraged to provide such RPC interfaces and automatically fall back to them + # when FD passing is not available, so that the application can still work when the parties are + # remote over a network. + # + # An attached FD is most often associated with a `senderHosted` descriptor. It could also make + # sense in the case of `thirdPartyHosted`: in this case, the sender is forwarding the FD that + # they received from the third party, so that the receiver can start using it without first + # interacting with the third party. This is an optional optimization -- the middleman may choose + # not to forward capabilities, in which case the receiver will need to complete the handshake + # with the third party directly before receiving the FD. If an implementation receives a second + # attached FD after having already received one previously (e.g. both in a `thirdPartyHosted` + # CapDescriptor and then later again when receiving the final capability directly from the + # third party), the implementation should discard the later FD and stick with the original. At + # present, there is no known reason why other capability types (e.g. `receiverHosted`) would want + # to carry an attached FD, but we reserve the right to define a meaning for this in the future. + # + # Each file descriptor attached to the message must be used in no more than one CapDescriptor, + # so that the receiver does not need to use dup() or refcounting to handle the possibility of + # multiple capabilities using the same descriptor. If multiple CapDescriptors do point to the + # same FD index, then the receiver can arbitrarily choose which capability ends up having the + # FD attached. + # + # To mitigate DoS attacks, RPC implementations should limit the number of FDs they are willing to + # receive in a single message to a small value. If a message happens to contain more than that, + # the list is truncated. Moreover, in some cases, FD passing needs to be blocked entirely for + # security or implementation reasons, in which case the list may be truncated to zero. Hence, + # `attachedFd` might point past the end of the list, which the implementation should treat as if + # no FD was attached at all. + # + # The type of this field was chosen to be UInt8 because Linux supports sending only a maximum + # of 253 file descriptors in an SCM_RIGHTS message anyway, and CapDescriptor had two bytes of + # padding left -- so after adding this, there is still one byte for a future feature. + # Conveniently, this also means we're able to use 0xff as the default value, which will always + # be out-of-range (of course, the implementation should explicitly enforce that 255 descriptors + # cannot be sent at once, rather than relying on Linux to do so). +} + +struct PromisedAnswer { + # **(mostly level 1)** + # + # Specifies how to derive a promise from an unanswered question, by specifying the path of fields + # to follow from the root of the eventual result struct to get to the desired capability. Used + # to address method calls to a not-yet-returned capability or to pass such a capability as an + # input to some other method call. + # + # Level 0 implementations must support `PromisedAnswer` only for the case where the answer is + # to a `Bootstrap` message. In this case, `path` is always empty since `Bootstrap` always returns + # a raw capability. + + questionId @0 :QuestionId; + # ID of the question (in the sender's question table / receiver's answer table) whose answer is + # expected to contain the capability. + + transform @1 :List(Op); + # Operations / transformations to apply to the result in order to get the capability actually + # being addressed. E.g. if the result is a struct and you want to call a method on a capability + # pointed to by a field of the struct, you need a `getPointerField` op. + + struct Op { + union { + noop @0 :Void; + # Does nothing. This member is mostly defined so that we can make `Op` a union even + # though (as of this writing) only one real operation is defined. + + getPointerField @1 :UInt16; + # Get a pointer field within a struct. The number is an index into the pointer section, NOT + # a field ordinal, so that the receiver does not need to understand the schema. + + # TODO(someday): We could add: + # - For lists, the ability to address every member of the list, or a slice of the list, the + # result of which would be another list. This is useful for implementing the equivalent of + # a SQL table join (not to be confused with the `Join` message type). + # - Maybe some ability to test a union. + # - Probably not a good idea: the ability to specify an arbitrary script to run on the + # result. We could define a little stack-based language where `Op` specifies one + # "instruction" or transformation to apply. Although this is not a good idea + # (over-engineered), any narrower additions to `Op` should be designed as if this + # were the eventual goal. + } + } +} + +struct ThirdPartyCapDescriptor { + # **(level 3)** + # + # Identifies a capability in a third-party vat that the sender wants the receiver to pick up. + + id @0 :ThirdPartyCapId; + # Identifies the third-party host and the specific capability to accept from it. + + vineId @1 :ExportId; + # A proxy for the third-party object exported by the sender. In CapTP terminology this is called + # a "vine", because it is an indirect reference to the third-party object that snakes through the + # sender vat. This serves two purposes: + # + # * Level 1 and 2 implementations that don't understand how to connect to a third party may + # simply send calls to the vine. Such calls will be forwarded to the third-party by the + # sender. + # + # * Level 3 implementations must release the vine only once they have successfully picked up the + # object from the third party. This ensures that the capability is not released by the sender + # prematurely. + # + # The sender will close the `Provide` request that it has sent to the third party as soon as + # it receives either a `Call` or a `Release` message directed at the vine. +} + +struct Exception { + # **(level 0)** + # + # Describes an arbitrary error that prevented an operation (e.g. a call) from completing. + # + # Cap'n Proto exceptions always indicate that something went wrong. In other words, in a fantasy + # world where everything always works as expected, no exceptions would ever be thrown. Clients + # should only ever catch exceptions as a means to implement fault-tolerance, where "fault" can + # mean: + # - Bugs. + # - Invalid input. + # - Configuration errors. + # - Network problems. + # - Insufficient resources. + # - Version skew (unimplemented functionality). + # - Other logistical problems. + # + # Exceptions should NOT be used to flag application-specific conditions that a client is expected + # to handle in an application-specific way. Put another way, in the Cap'n Proto world, + # "checked exceptions" (where an interface explicitly defines the exceptions it throws and + # clients are forced by the type system to handle those exceptions) do NOT make sense. + + reason @0 :Text; + # Human-readable failure description. + + type @3 :Type; + # The type of the error. The purpose of this enum is not to describe the error itself, but + # rather to describe how the client might want to respond to the error. + + enum Type { + failed @0; + # A generic problem occurred, and it is believed that if the operation were repeated without + # any change in the state of the world, the problem would occur again. + # + # A client might respond to this error by logging it for investigation by the developer and/or + # displaying it to the user. + + overloaded @1; + # The request was rejected due to a temporary lack of resources. + # + # Examples include: + # - There's not enough CPU time to keep up with incoming requests, so some are rejected. + # - The server ran out of RAM or disk space during the request. + # - The operation timed out (took significantly longer than it should have). + # + # A client might respond to this error by scheduling to retry the operation much later. The + # client should NOT retry again immediately since this would likely exacerbate the problem. + + disconnected @2; + # The method failed because a connection to some necessary capability was lost. + # + # Examples include: + # - The client introduced the server to a third-party capability, the connection to that third + # party was subsequently lost, and then the client requested that the server use the dead + # capability for something. + # - The client previously requested that the server obtain a capability from some third party. + # The server returned a capability to an object wrapping the third-party capability. Later, + # the server's connection to the third party was lost. + # - The capability has been revoked. Revocation does not necessarily mean that the client is + # no longer authorized to use the capability; it is often used simply as a way to force the + # client to repeat the setup process, perhaps to efficiently move them to a new back-end or + # get them to recognize some other change that has occurred. + # + # A client should normally respond to this error by releasing all capabilities it is currently + # holding related to the one it called and then re-creating them by restoring SturdyRefs and/or + # repeating the method calls used to create them originally. In other words, disconnect and + # start over. This should in turn cause the server to obtain a new copy of the capability that + # it lost, thus making everything work. + # + # If the client receives another `disconnected` error in the process of rebuilding the + # capability and retrying the call, it should treat this as an `overloaded` error: the network + # is currently unreliable, possibly due to load or other temporary issues. + + unimplemented @3; + # The server doesn't implement the requested method. If there is some other method that the + # client could call (perhaps an older and/or slower interface), it should try that instead. + # Otherwise, this should be treated like `failed`. + } + + obsoleteIsCallersFault @1 :Bool; + # OBSOLETE. Ignore. + + obsoleteDurability @2 :UInt16; + # OBSOLETE. See `type` instead. + + trace @4 :Text; + # Stack trace text from the remote server. The format is not specified. By default, + # implementations do not provide stack traces; the application must explicitly enable them + # when desired. +} + +# ======================================================================================== +# Network-specific Parameters +# +# Some parts of the Cap'n Proto RPC protocol are not specified here because different vat networks +# may wish to use different approaches to solving them. For example, on the public internet, you +# may want to authenticate vats using public-key cryptography, but on a local intranet with trusted +# infrastructure, you may be happy to authenticate based on network address only, or some other +# lightweight mechanism. +# +# To accommodate this, we specify several "parameter" types. Each type is defined here as an +# alias for `AnyPointer`, but a specific network will want to define a specific set of types to use. +# All vats in a vat network must agree on these parameters in order to be able to communicate. +# Inter-network communication can be accomplished through "gateways" that perform translation +# between the primitives used on each network; these gateways may need to be deeply stateful, +# depending on the translations they perform. +# +# For interaction over the global internet between parties with no other prior arrangement, a +# particular set of bindings for these types is defined elsewhere. (TODO(someday): Specify where +# these common definitions live.) +# +# Another common network type is the two-party network, in which one of the parties typically +# interacts with the outside world entirely through the other party. In such a connection between +# Alice and Bob, all objects that exist on Bob's other networks appear to Alice as if they were +# hosted by Bob himself, and similarly all objects on Alice's network (if she even has one) appear +# to Bob as if they were hosted by Alice. This network type is interesting because from the point +# of view of a simple application that communicates with only one other party via the two-party +# protocol, there are no three-party interactions at all, and joins are unusually simple to +# implement, so implementing at level 4 is barely more complicated than implementing at level 1. +# Moreover, if you pair an app implementing the two-party network with a container that implements +# some other network, the app can then participate on the container's network just as if it +# implemented that network directly. The types used by the two-party network are defined in +# `rpc-twoparty.capnp`. +# +# The things that we need to parameterize are: +# - How to store capabilities long-term without holding a connection open (mostly level 2). +# - How to authenticate vats in three-party introductions (level 3). +# - How to implement `Join` (level 4). +# +# Persistent references +# --------------------- +# +# **(mostly level 2)** +# +# We want to allow some capabilities to be stored long-term, even if a connection is lost and later +# recreated. ExportId is a short-term identifier that is specific to a connection, so it doesn't +# help here. We need a way to specify long-term identifiers, as well as a strategy for +# reconnecting to a referenced capability later. +# +# Three-party interactions +# ------------------------ +# +# **(level 3)** +# +# In cases where more than two vats are interacting, we have situations where VatA holds a +# capability hosted by VatB and wants to send that capability to VatC. This can be accomplished +# by VatA proxying requests on the new capability, but doing so has two big problems: +# - It's inefficient, requiring an extra network hop. +# - If VatC receives another capability to the same object from VatD, it is difficult for VatC to +# detect that the two capabilities are really the same and to implement the E "join" operation, +# which is necessary for certain four-or-more-party interactions, such as the escrow pattern. +# See: http://www.erights.org/elib/equality/grant-matcher/index.html +# +# Instead, we want a way for VatC to form a direct, authenticated connection to VatB. +# +# Join +# ---- +# +# **(level 4)** +# +# The `Join` message type and corresponding operation arranges for a direct connection to be formed +# between the joiner and the host of the joined object, and this connection must be authenticated. +# Thus, the details are network-dependent. + +using SturdyRef = AnyPointer; +# **(level 2)** +# +# Identifies a persisted capability that can be restored in the future. How exactly a SturdyRef +# is restored to a live object is specified along with the SturdyRef definition (i.e. not by +# rpc.capnp). +# +# Generally a SturdyRef needs to specify three things: +# - How to reach the vat that can restore the ref (e.g. a hostname or IP address). +# - How to authenticate the vat after connecting (e.g. a public key fingerprint). +# - The identity of a specific object hosted by the vat. Generally, this is an opaque pointer whose +# format is defined by the specific vat -- the client has no need to inspect the object ID. +# It is important that the object ID be unguessable if the object is not public (and objects +# should almost never be public). +# +# The above are only suggestions. Some networks might work differently. For example, a private +# network might employ a special restorer service whose sole purpose is to restore SturdyRefs. +# In this case, the entire contents of SturdyRef might be opaque, because they are intended only +# to be forwarded to the restorer service. + +using ProvisionId = AnyPointer; +# **(level 3)** +# +# The information that must be sent in an `Accept` message to identify the object being accepted. +# +# In a network where each vat has a public/private key pair, this could simply be the public key +# fingerprint of the provider vat along with a nonce matching the one in the `RecipientId` used +# in the `Provide` message sent from that provider. + +using RecipientId = AnyPointer; +# **(level 3)** +# +# The information that must be sent in a `Provide` message to identify the recipient of the +# capability. +# +# In a network where each vat has a public/private key pair, this could simply be the public key +# fingerprint of the recipient along with a nonce matching the one in the `ProvisionId`. +# +# As another example, when communicating between processes on the same machine over Unix sockets, +# RecipientId could simply refer to a file descriptor attached to the message via SCM_RIGHTS. +# This file descriptor would be one end of a newly-created socketpair, with the other end having +# been sent to the capability's recipient in ThirdPartyCapId. + +using ThirdPartyCapId = AnyPointer; +# **(level 3)** +# +# The information needed to connect to a third party and accept a capability from it. +# +# In a network where each vat has a public/private key pair, this could be a combination of the +# third party's public key fingerprint, hints on how to connect to the third party (e.g. an IP +# address), and the nonce used in the corresponding `Provide` message's `RecipientId` as sent +# to that third party (used to identify which capability to pick up). +# +# As another example, when communicating between processes on the same machine over Unix sockets, +# ThirdPartyCapId could simply refer to a file descriptor attached to the message via SCM_RIGHTS. +# This file descriptor would be one end of a newly-created socketpair, with the other end having +# been sent to the process hosting the capability in RecipientId. + +using JoinKeyPart = AnyPointer; +# **(level 4)** +# +# A piece of a secret key. One piece is sent along each path that is expected to lead to the same +# place. Once the pieces are combined, a direct connection may be formed between the sender and +# the receiver, bypassing any men-in-the-middle along the paths. See the `Join` message type. +# +# The motivation for Joins is discussed under "Supporting Equality" in the "Unibus" protocol +# sketch: http://www.erights.org/elib/distrib/captp/unibus.html +# +# In a network where each vat has a public/private key pair and each vat forms no more than one +# connection to each other vat, Joins will rarely -- perhaps never -- be needed, as objects never +# need to be transparently proxied and references to the same object sent over the same connection +# have the same export ID. Thus, a successful join requires only checking that the two objects +# come from the same connection and have the same ID, and then completes immediately. +# +# However, in networks where two vats may form more than one connection between each other, or +# where proxying of objects occurs, joins are necessary. +# +# Typically, each JoinKeyPart would include a fixed-length data value such that all value parts +# XOR'd together forms a shared secret that can be used to form an encrypted connection between +# the joiner and the joined object's host. Each JoinKeyPart should also include an indication of +# how many parts to expect and a hash of the shared secret (used to match up parts). + +using JoinResult = AnyPointer; +# **(level 4)** +# +# Information returned as the result to a `Join` message, needed by the joiner in order to form a +# direct connection to a joined object. This might simply be the address of the joined object's +# host vat, since the `JoinKey` has already been communicated so the two vats already have a shared +# secret to use to authenticate each other. +# +# The `JoinResult` should also contain information that can be used to detect when the Join +# requests ended up reaching different objects, so that this situation can be detected easily. +# This could be a simple matter of including a sequence number -- if the joiner receives two +# `JoinResult`s with sequence number 0, then they must have come from different objects and the +# whole join is a failure. + +# ======================================================================================== +# Network interface sketch +# +# The interfaces below are meant to be pseudo-code to illustrate how the details of a particular +# vat network might be abstracted away. They are written like Cap'n Proto interfaces, but in +# practice you'd probably define these interfaces manually in the target programming language. A +# Cap'n Proto RPC implementation should be able to use these interfaces without knowing the +# definitions of the various network-specific parameters defined above. + +# interface VatNetwork { +# # Represents a vat network, with the ability to connect to particular vats and receive +# # connections from vats. +# # +# # Note that methods returning a `Connection` may return a pre-existing `Connection`, and the +# # caller is expected to find and share state with existing users of the connection. +# +# # Level 0 features ----------------------------------------------- +# +# connect(vatId :VatId) :Connection; +# # Connect to the given vat. The transport should return a promise that does not +# # resolve until authentication has completed, but allows messages to be pipelined in before +# # that; the transport either queues these messages until authenticated, or sends them encrypted +# # such that only the authentic vat would be able to decrypt them. The latter approach avoids a +# # round trip for authentication. +# +# accept() :Connection; +# # Wait for the next incoming connection and return it. Only connections formed by +# # connect() are returned by this method. +# +# # Level 4 features ----------------------------------------------- +# +# newJoiner(count :UInt32) :NewJoinerResponse; +# # Prepare a new Join operation, which will eventually lead to forming a new direct connection +# # to the host of the joined capability. `count` is the number of capabilities to join. +# +# struct NewJoinerResponse { +# joinKeyParts :List(JoinKeyPart); +# # Key parts to send in Join messages to each capability. +# +# joiner :Joiner; +# # Used to establish the final connection. +# } +# +# interface Joiner { +# addJoinResult(result :JoinResult) :Void; +# # Add a JoinResult received in response to one of the `Join` messages. All `JoinResult`s +# # returned from all paths must be added before trying to connect. +# +# connect() :ConnectionAndProvisionId; +# # Try to form a connection to the joined capability's host, verifying that it has received +# # all of the JoinKeyParts. Once the connection is formed, the caller should send an `Accept` +# # message on it with the specified `ProvisionId` in order to receive the final capability. +# } +# +# acceptConnectionFromJoiner(parts :List(JoinKeyPart), paths :List(VatPath)) +# :ConnectionAndProvisionId; +# # Called on a joined capability's host to receive the connection from the joiner, once all +# # key parts have arrived. The caller should expect to receive an `Accept` message over the +# # connection with the given ProvisionId. +# } +# +# interface Connection { +# # Level 0 features ----------------------------------------------- +# +# send(message :Message) :Void; +# # Send the message. Returns successfully when the message (and all preceding messages) has +# # been acknowledged by the recipient. +# +# receive() :Message; +# # Receive the next message, and acknowledges receipt to the sender. Messages are received in +# # the order in which they are sent. +# +# # Level 3 features ----------------------------------------------- +# +# introduceTo(recipient :Connection) :IntroductionInfo; +# # Call before starting a three-way introduction, assuming a `Provide` message is to be sent on +# # this connection and a `ThirdPartyCapId` is to be sent to `recipient`. +# +# struct IntroductionInfo { +# sendToRecipient :ThirdPartyCapId; +# sendToTarget :RecipientId; +# } +# +# connectToIntroduced(capId :ThirdPartyCapId) :ConnectionAndProvisionId; +# # Given a ThirdPartyCapId received over this connection, connect to the third party. The +# # caller should then send an `Accept` message over the new connection. +# +# acceptIntroducedConnection(recipientId :RecipientId) :Connection; +# # Given a RecipientId received in a `Provide` message on this `Connection`, wait for the +# # recipient to connect, and return the connection formed. Usually, the first message received +# # on the new connection will be an `Accept` message. +# } +# +# struct ConnectionAndProvisionId { +# # **(level 3)** +# +# connection :Connection; +# # Connection on which to issue `Accept` message. +# +# provision :ProvisionId; +# # `ProvisionId` to send in the `Accept` message. +# } +using Go = import "/go.capnp"; +$Go.package("rpc"); +$Go.import("capnproto.org/go/capnp/v3/std/capnp/rpc"); diff --git a/crates/turborepo-lib/Source/hash/std/capnp/rpc/exception.go b/crates/turborepo-lib/Source/hash/std/capnp/rpc/exception.go new file mode 100644 index 0000000000000..0d80a52dc9ac5 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/rpc/exception.go @@ -0,0 +1,10 @@ +package rpc + +import "capnproto.org/go/capnp/v3/exc" + +// MarshalError fills in the fields of e according to err. Returns a non-nil +// error if marshalling fails. +func (e Exception) MarshalError(err error) error { + e.SetType(Exception_Type(exc.TypeOf(err))) + return e.SetReason(err.Error()) +} diff --git a/crates/turborepo-lib/Source/hash/std/capnp/rpc/rpc.capnp.go b/crates/turborepo-lib/Source/hash/std/capnp/rpc/rpc.capnp.go new file mode 100644 index 0000000000000..dcffa679fdf2b --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/rpc/rpc.capnp.go @@ -0,0 +1,3076 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package rpc + +import ( + capnp "capnproto.org/go/capnp/v3" + text "capnproto.org/go/capnp/v3/encoding/text" + schemas "capnproto.org/go/capnp/v3/schemas" + strconv "strconv" +) + +type Message capnp.Struct +type Message_Which uint16 + +const ( + Message_Which_unimplemented Message_Which = 0 + Message_Which_abort Message_Which = 1 + Message_Which_bootstrap Message_Which = 8 + Message_Which_call Message_Which = 2 + Message_Which_return Message_Which = 3 + Message_Which_finish Message_Which = 4 + Message_Which_resolve Message_Which = 5 + Message_Which_release Message_Which = 6 + Message_Which_disembargo Message_Which = 13 + Message_Which_obsoleteSave Message_Which = 7 + Message_Which_obsoleteDelete Message_Which = 9 + Message_Which_provide Message_Which = 10 + Message_Which_accept Message_Which = 11 + Message_Which_join Message_Which = 12 +) + +func (w Message_Which) String() string { + const s = "unimplementedabortbootstrapcallreturnfinishresolvereleasedisembargoobsoleteSaveobsoleteDeleteprovideacceptjoin" + switch w { + case Message_Which_unimplemented: + return s[0:13] + case Message_Which_abort: + return s[13:18] + case Message_Which_bootstrap: + return s[18:27] + case Message_Which_call: + return s[27:31] + case Message_Which_return: + return s[31:37] + case Message_Which_finish: + return s[37:43] + case Message_Which_resolve: + return s[43:50] + case Message_Which_release: + return s[50:57] + case Message_Which_disembargo: + return s[57:67] + case Message_Which_obsoleteSave: + return s[67:79] + case Message_Which_obsoleteDelete: + return s[79:93] + case Message_Which_provide: + return s[93:100] + case Message_Which_accept: + return s[100:106] + case Message_Which_join: + return s[106:110] + + } + return "Message_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Message_TypeID is the unique identifier for the type Message. +const Message_TypeID = 0x91b79f1f808db032 + +func NewMessage(s *capnp.Segment) (Message, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Message(st), err +} + +func NewRootMessage(s *capnp.Segment) (Message, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Message(st), err +} + +func ReadRootMessage(msg *capnp.Message) (Message, error) { + root, err := msg.Root() + return Message(root.Struct()), err +} + +func (s Message) String() string { + str, _ := text.Marshal(0x91b79f1f808db032, capnp.Struct(s)) + return str +} + +func (s Message) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Message) DecodeFromPtr(p capnp.Ptr) Message { + return Message(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Message) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Message) Which() Message_Which { + return Message_Which(capnp.Struct(s).Uint16(0)) +} +func (s Message) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Message) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Message) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Message) Unimplemented() (Message, error) { + if capnp.Struct(s).Uint16(0) != 0 { + panic("Which() != unimplemented") + } + p, err := capnp.Struct(s).Ptr(0) + return Message(p.Struct()), err +} + +func (s Message) HasUnimplemented() bool { + if capnp.Struct(s).Uint16(0) != 0 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetUnimplemented(v Message) error { + capnp.Struct(s).SetUint16(0, 0) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewUnimplemented sets the unimplemented field to a newly +// allocated Message struct, preferring placement in s's segment. +func (s Message) NewUnimplemented() (Message, error) { + capnp.Struct(s).SetUint16(0, 0) + ss, err := NewMessage(capnp.Struct(s).Segment()) + if err != nil { + return Message{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Abort() (Exception, error) { + if capnp.Struct(s).Uint16(0) != 1 { + panic("Which() != abort") + } + p, err := capnp.Struct(s).Ptr(0) + return Exception(p.Struct()), err +} + +func (s Message) HasAbort() bool { + if capnp.Struct(s).Uint16(0) != 1 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetAbort(v Exception) error { + capnp.Struct(s).SetUint16(0, 1) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewAbort sets the abort field to a newly +// allocated Exception struct, preferring placement in s's segment. +func (s Message) NewAbort() (Exception, error) { + capnp.Struct(s).SetUint16(0, 1) + ss, err := NewException(capnp.Struct(s).Segment()) + if err != nil { + return Exception{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Bootstrap() (Bootstrap, error) { + if capnp.Struct(s).Uint16(0) != 8 { + panic("Which() != bootstrap") + } + p, err := capnp.Struct(s).Ptr(0) + return Bootstrap(p.Struct()), err +} + +func (s Message) HasBootstrap() bool { + if capnp.Struct(s).Uint16(0) != 8 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetBootstrap(v Bootstrap) error { + capnp.Struct(s).SetUint16(0, 8) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewBootstrap sets the bootstrap field to a newly +// allocated Bootstrap struct, preferring placement in s's segment. +func (s Message) NewBootstrap() (Bootstrap, error) { + capnp.Struct(s).SetUint16(0, 8) + ss, err := NewBootstrap(capnp.Struct(s).Segment()) + if err != nil { + return Bootstrap{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Call() (Call, error) { + if capnp.Struct(s).Uint16(0) != 2 { + panic("Which() != call") + } + p, err := capnp.Struct(s).Ptr(0) + return Call(p.Struct()), err +} + +func (s Message) HasCall() bool { + if capnp.Struct(s).Uint16(0) != 2 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetCall(v Call) error { + capnp.Struct(s).SetUint16(0, 2) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewCall sets the call field to a newly +// allocated Call struct, preferring placement in s's segment. +func (s Message) NewCall() (Call, error) { + capnp.Struct(s).SetUint16(0, 2) + ss, err := NewCall(capnp.Struct(s).Segment()) + if err != nil { + return Call{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Return() (Return, error) { + if capnp.Struct(s).Uint16(0) != 3 { + panic("Which() != return") + } + p, err := capnp.Struct(s).Ptr(0) + return Return(p.Struct()), err +} + +func (s Message) HasReturn() bool { + if capnp.Struct(s).Uint16(0) != 3 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetReturn(v Return) error { + capnp.Struct(s).SetUint16(0, 3) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewReturn sets the return field to a newly +// allocated Return struct, preferring placement in s's segment. +func (s Message) NewReturn() (Return, error) { + capnp.Struct(s).SetUint16(0, 3) + ss, err := NewReturn(capnp.Struct(s).Segment()) + if err != nil { + return Return{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Finish() (Finish, error) { + if capnp.Struct(s).Uint16(0) != 4 { + panic("Which() != finish") + } + p, err := capnp.Struct(s).Ptr(0) + return Finish(p.Struct()), err +} + +func (s Message) HasFinish() bool { + if capnp.Struct(s).Uint16(0) != 4 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetFinish(v Finish) error { + capnp.Struct(s).SetUint16(0, 4) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewFinish sets the finish field to a newly +// allocated Finish struct, preferring placement in s's segment. +func (s Message) NewFinish() (Finish, error) { + capnp.Struct(s).SetUint16(0, 4) + ss, err := NewFinish(capnp.Struct(s).Segment()) + if err != nil { + return Finish{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Resolve() (Resolve, error) { + if capnp.Struct(s).Uint16(0) != 5 { + panic("Which() != resolve") + } + p, err := capnp.Struct(s).Ptr(0) + return Resolve(p.Struct()), err +} + +func (s Message) HasResolve() bool { + if capnp.Struct(s).Uint16(0) != 5 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetResolve(v Resolve) error { + capnp.Struct(s).SetUint16(0, 5) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewResolve sets the resolve field to a newly +// allocated Resolve struct, preferring placement in s's segment. +func (s Message) NewResolve() (Resolve, error) { + capnp.Struct(s).SetUint16(0, 5) + ss, err := NewResolve(capnp.Struct(s).Segment()) + if err != nil { + return Resolve{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Release() (Release, error) { + if capnp.Struct(s).Uint16(0) != 6 { + panic("Which() != release") + } + p, err := capnp.Struct(s).Ptr(0) + return Release(p.Struct()), err +} + +func (s Message) HasRelease() bool { + if capnp.Struct(s).Uint16(0) != 6 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetRelease(v Release) error { + capnp.Struct(s).SetUint16(0, 6) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewRelease sets the release field to a newly +// allocated Release struct, preferring placement in s's segment. +func (s Message) NewRelease() (Release, error) { + capnp.Struct(s).SetUint16(0, 6) + ss, err := NewRelease(capnp.Struct(s).Segment()) + if err != nil { + return Release{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Disembargo() (Disembargo, error) { + if capnp.Struct(s).Uint16(0) != 13 { + panic("Which() != disembargo") + } + p, err := capnp.Struct(s).Ptr(0) + return Disembargo(p.Struct()), err +} + +func (s Message) HasDisembargo() bool { + if capnp.Struct(s).Uint16(0) != 13 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetDisembargo(v Disembargo) error { + capnp.Struct(s).SetUint16(0, 13) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewDisembargo sets the disembargo field to a newly +// allocated Disembargo struct, preferring placement in s's segment. +func (s Message) NewDisembargo() (Disembargo, error) { + capnp.Struct(s).SetUint16(0, 13) + ss, err := NewDisembargo(capnp.Struct(s).Segment()) + if err != nil { + return Disembargo{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) ObsoleteSave() (capnp.Ptr, error) { + if capnp.Struct(s).Uint16(0) != 7 { + panic("Which() != obsoleteSave") + } + return capnp.Struct(s).Ptr(0) +} + +func (s Message) HasObsoleteSave() bool { + if capnp.Struct(s).Uint16(0) != 7 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetObsoleteSave(v capnp.Ptr) error { + capnp.Struct(s).SetUint16(0, 7) + return capnp.Struct(s).SetPtr(0, v) +} +func (s Message) ObsoleteDelete() (capnp.Ptr, error) { + if capnp.Struct(s).Uint16(0) != 9 { + panic("Which() != obsoleteDelete") + } + return capnp.Struct(s).Ptr(0) +} + +func (s Message) HasObsoleteDelete() bool { + if capnp.Struct(s).Uint16(0) != 9 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetObsoleteDelete(v capnp.Ptr) error { + capnp.Struct(s).SetUint16(0, 9) + return capnp.Struct(s).SetPtr(0, v) +} +func (s Message) Provide() (Provide, error) { + if capnp.Struct(s).Uint16(0) != 10 { + panic("Which() != provide") + } + p, err := capnp.Struct(s).Ptr(0) + return Provide(p.Struct()), err +} + +func (s Message) HasProvide() bool { + if capnp.Struct(s).Uint16(0) != 10 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetProvide(v Provide) error { + capnp.Struct(s).SetUint16(0, 10) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewProvide sets the provide field to a newly +// allocated Provide struct, preferring placement in s's segment. +func (s Message) NewProvide() (Provide, error) { + capnp.Struct(s).SetUint16(0, 10) + ss, err := NewProvide(capnp.Struct(s).Segment()) + if err != nil { + return Provide{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Accept() (Accept, error) { + if capnp.Struct(s).Uint16(0) != 11 { + panic("Which() != accept") + } + p, err := capnp.Struct(s).Ptr(0) + return Accept(p.Struct()), err +} + +func (s Message) HasAccept() bool { + if capnp.Struct(s).Uint16(0) != 11 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetAccept(v Accept) error { + capnp.Struct(s).SetUint16(0, 11) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewAccept sets the accept field to a newly +// allocated Accept struct, preferring placement in s's segment. +func (s Message) NewAccept() (Accept, error) { + capnp.Struct(s).SetUint16(0, 11) + ss, err := NewAccept(capnp.Struct(s).Segment()) + if err != nil { + return Accept{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Message) Join() (Join, error) { + if capnp.Struct(s).Uint16(0) != 12 { + panic("Which() != join") + } + p, err := capnp.Struct(s).Ptr(0) + return Join(p.Struct()), err +} + +func (s Message) HasJoin() bool { + if capnp.Struct(s).Uint16(0) != 12 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Message) SetJoin(v Join) error { + capnp.Struct(s).SetUint16(0, 12) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewJoin sets the join field to a newly +// allocated Join struct, preferring placement in s's segment. +func (s Message) NewJoin() (Join, error) { + capnp.Struct(s).SetUint16(0, 12) + ss, err := NewJoin(capnp.Struct(s).Segment()) + if err != nil { + return Join{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// Message_List is a list of Message. +type Message_List = capnp.StructList[Message] + +// NewMessage creates a new list of Message. +func NewMessage_List(s *capnp.Segment, sz int32) (Message_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Message](l), err +} + +// Message_Future is a wrapper for a Message promised by a client call. +type Message_Future struct{ *capnp.Future } + +func (f Message_Future) Struct() (Message, error) { + p, err := f.Future.Ptr() + return Message(p.Struct()), err +} +func (p Message_Future) Unimplemented() Message_Future { + return Message_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Abort() Exception_Future { + return Exception_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Bootstrap() Bootstrap_Future { + return Bootstrap_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Call() Call_Future { + return Call_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Return() Return_Future { + return Return_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Finish() Finish_Future { + return Finish_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Resolve() Resolve_Future { + return Resolve_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Release() Release_Future { + return Release_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Disembargo() Disembargo_Future { + return Disembargo_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) ObsoleteSave() *capnp.Future { + return p.Future.Field(0, nil) +} +func (p Message_Future) ObsoleteDelete() *capnp.Future { + return p.Future.Field(0, nil) +} +func (p Message_Future) Provide() Provide_Future { + return Provide_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Accept() Accept_Future { + return Accept_Future{Future: p.Future.Field(0, nil)} +} +func (p Message_Future) Join() Join_Future { + return Join_Future{Future: p.Future.Field(0, nil)} +} + +type Bootstrap capnp.Struct + +// Bootstrap_TypeID is the unique identifier for the type Bootstrap. +const Bootstrap_TypeID = 0xe94ccf8031176ec4 + +func NewBootstrap(s *capnp.Segment) (Bootstrap, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Bootstrap(st), err +} + +func NewRootBootstrap(s *capnp.Segment) (Bootstrap, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Bootstrap(st), err +} + +func ReadRootBootstrap(msg *capnp.Message) (Bootstrap, error) { + root, err := msg.Root() + return Bootstrap(root.Struct()), err +} + +func (s Bootstrap) String() string { + str, _ := text.Marshal(0xe94ccf8031176ec4, capnp.Struct(s)) + return str +} + +func (s Bootstrap) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Bootstrap) DecodeFromPtr(p capnp.Ptr) Bootstrap { + return Bootstrap(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Bootstrap) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Bootstrap) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Bootstrap) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Bootstrap) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Bootstrap) QuestionId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Bootstrap) SetQuestionId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Bootstrap) DeprecatedObjectId() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) +} + +func (s Bootstrap) HasDeprecatedObjectId() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Bootstrap) SetDeprecatedObjectId(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} + +// Bootstrap_List is a list of Bootstrap. +type Bootstrap_List = capnp.StructList[Bootstrap] + +// NewBootstrap creates a new list of Bootstrap. +func NewBootstrap_List(s *capnp.Segment, sz int32) (Bootstrap_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Bootstrap](l), err +} + +// Bootstrap_Future is a wrapper for a Bootstrap promised by a client call. +type Bootstrap_Future struct{ *capnp.Future } + +func (f Bootstrap_Future) Struct() (Bootstrap, error) { + p, err := f.Future.Ptr() + return Bootstrap(p.Struct()), err +} +func (p Bootstrap_Future) DeprecatedObjectId() *capnp.Future { + return p.Future.Field(0, nil) +} + +type Call capnp.Struct +type Call_sendResultsTo Call +type Call_sendResultsTo_Which uint16 + +const ( + Call_sendResultsTo_Which_caller Call_sendResultsTo_Which = 0 + Call_sendResultsTo_Which_yourself Call_sendResultsTo_Which = 1 + Call_sendResultsTo_Which_thirdParty Call_sendResultsTo_Which = 2 +) + +func (w Call_sendResultsTo_Which) String() string { + const s = "calleryourselfthirdParty" + switch w { + case Call_sendResultsTo_Which_caller: + return s[0:6] + case Call_sendResultsTo_Which_yourself: + return s[6:14] + case Call_sendResultsTo_Which_thirdParty: + return s[14:24] + + } + return "Call_sendResultsTo_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Call_TypeID is the unique identifier for the type Call. +const Call_TypeID = 0x836a53ce789d4cd4 + +func NewCall(s *capnp.Segment) (Call, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 3}) + return Call(st), err +} + +func NewRootCall(s *capnp.Segment) (Call, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 3}) + return Call(st), err +} + +func ReadRootCall(msg *capnp.Message) (Call, error) { + root, err := msg.Root() + return Call(root.Struct()), err +} + +func (s Call) String() string { + str, _ := text.Marshal(0x836a53ce789d4cd4, capnp.Struct(s)) + return str +} + +func (s Call) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Call) DecodeFromPtr(p capnp.Ptr) Call { + return Call(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Call) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Call) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Call) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Call) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Call) QuestionId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Call) SetQuestionId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Call) Target() (MessageTarget, error) { + p, err := capnp.Struct(s).Ptr(0) + return MessageTarget(p.Struct()), err +} + +func (s Call) HasTarget() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Call) SetTarget(v MessageTarget) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewTarget sets the target field to a newly +// allocated MessageTarget struct, preferring placement in s's segment. +func (s Call) NewTarget() (MessageTarget, error) { + ss, err := NewMessageTarget(capnp.Struct(s).Segment()) + if err != nil { + return MessageTarget{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Call) InterfaceId() uint64 { + return capnp.Struct(s).Uint64(8) +} + +func (s Call) SetInterfaceId(v uint64) { + capnp.Struct(s).SetUint64(8, v) +} + +func (s Call) MethodId() uint16 { + return capnp.Struct(s).Uint16(4) +} + +func (s Call) SetMethodId(v uint16) { + capnp.Struct(s).SetUint16(4, v) +} + +func (s Call) AllowThirdPartyTailCall() bool { + return capnp.Struct(s).Bit(128) +} + +func (s Call) SetAllowThirdPartyTailCall(v bool) { + capnp.Struct(s).SetBit(128, v) +} + +func (s Call) Params() (Payload, error) { + p, err := capnp.Struct(s).Ptr(1) + return Payload(p.Struct()), err +} + +func (s Call) HasParams() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Call) SetParams(v Payload) error { + return capnp.Struct(s).SetPtr(1, capnp.Struct(v).ToPtr()) +} + +// NewParams sets the params field to a newly +// allocated Payload struct, preferring placement in s's segment. +func (s Call) NewParams() (Payload, error) { + ss, err := NewPayload(capnp.Struct(s).Segment()) + if err != nil { + return Payload{}, err + } + err = capnp.Struct(s).SetPtr(1, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Call) SendResultsTo() Call_sendResultsTo { return Call_sendResultsTo(s) } + +func (s Call_sendResultsTo) Which() Call_sendResultsTo_Which { + return Call_sendResultsTo_Which(capnp.Struct(s).Uint16(6)) +} +func (s Call_sendResultsTo) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Call_sendResultsTo) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Call_sendResultsTo) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Call_sendResultsTo) SetCaller() { + capnp.Struct(s).SetUint16(6, 0) + +} + +func (s Call_sendResultsTo) SetYourself() { + capnp.Struct(s).SetUint16(6, 1) + +} + +func (s Call_sendResultsTo) ThirdParty() (capnp.Ptr, error) { + if capnp.Struct(s).Uint16(6) != 2 { + panic("Which() != thirdParty") + } + return capnp.Struct(s).Ptr(2) +} + +func (s Call_sendResultsTo) HasThirdParty() bool { + if capnp.Struct(s).Uint16(6) != 2 { + return false + } + return capnp.Struct(s).HasPtr(2) +} + +func (s Call_sendResultsTo) SetThirdParty(v capnp.Ptr) error { + capnp.Struct(s).SetUint16(6, 2) + return capnp.Struct(s).SetPtr(2, v) +} + +// Call_List is a list of Call. +type Call_List = capnp.StructList[Call] + +// NewCall creates a new list of Call. +func NewCall_List(s *capnp.Segment, sz int32) (Call_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 24, PointerCount: 3}, sz) + return capnp.StructList[Call](l), err +} + +// Call_Future is a wrapper for a Call promised by a client call. +type Call_Future struct{ *capnp.Future } + +func (f Call_Future) Struct() (Call, error) { + p, err := f.Future.Ptr() + return Call(p.Struct()), err +} +func (p Call_Future) Target() MessageTarget_Future { + return MessageTarget_Future{Future: p.Future.Field(0, nil)} +} +func (p Call_Future) Params() Payload_Future { + return Payload_Future{Future: p.Future.Field(1, nil)} +} +func (p Call_Future) SendResultsTo() Call_sendResultsTo_Future { + return Call_sendResultsTo_Future{p.Future} +} + +// Call_sendResultsTo_Future is a wrapper for a Call_sendResultsTo promised by a client call. +type Call_sendResultsTo_Future struct{ *capnp.Future } + +func (f Call_sendResultsTo_Future) Struct() (Call_sendResultsTo, error) { + p, err := f.Future.Ptr() + return Call_sendResultsTo(p.Struct()), err +} +func (p Call_sendResultsTo_Future) ThirdParty() *capnp.Future { + return p.Future.Field(2, nil) +} + +type Return capnp.Struct +type Return_Which uint16 + +const ( + Return_Which_results Return_Which = 0 + Return_Which_exception Return_Which = 1 + Return_Which_canceled Return_Which = 2 + Return_Which_resultsSentElsewhere Return_Which = 3 + Return_Which_takeFromOtherQuestion Return_Which = 4 + Return_Which_acceptFromThirdParty Return_Which = 5 +) + +func (w Return_Which) String() string { + const s = "resultsexceptioncanceledresultsSentElsewheretakeFromOtherQuestionacceptFromThirdParty" + switch w { + case Return_Which_results: + return s[0:7] + case Return_Which_exception: + return s[7:16] + case Return_Which_canceled: + return s[16:24] + case Return_Which_resultsSentElsewhere: + return s[24:44] + case Return_Which_takeFromOtherQuestion: + return s[44:65] + case Return_Which_acceptFromThirdParty: + return s[65:85] + + } + return "Return_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Return_TypeID is the unique identifier for the type Return. +const Return_TypeID = 0x9e19b28d3db3573a + +func NewReturn(s *capnp.Segment) (Return, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Return(st), err +} + +func NewRootReturn(s *capnp.Segment) (Return, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Return(st), err +} + +func ReadRootReturn(msg *capnp.Message) (Return, error) { + root, err := msg.Root() + return Return(root.Struct()), err +} + +func (s Return) String() string { + str, _ := text.Marshal(0x9e19b28d3db3573a, capnp.Struct(s)) + return str +} + +func (s Return) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Return) DecodeFromPtr(p capnp.Ptr) Return { + return Return(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Return) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Return) Which() Return_Which { + return Return_Which(capnp.Struct(s).Uint16(6)) +} +func (s Return) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Return) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Return) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Return) AnswerId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Return) SetAnswerId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Return) ReleaseParamCaps() bool { + return !capnp.Struct(s).Bit(32) +} + +func (s Return) SetReleaseParamCaps(v bool) { + capnp.Struct(s).SetBit(32, !v) +} + +func (s Return) Results() (Payload, error) { + if capnp.Struct(s).Uint16(6) != 0 { + panic("Which() != results") + } + p, err := capnp.Struct(s).Ptr(0) + return Payload(p.Struct()), err +} + +func (s Return) HasResults() bool { + if capnp.Struct(s).Uint16(6) != 0 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Return) SetResults(v Payload) error { + capnp.Struct(s).SetUint16(6, 0) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewResults sets the results field to a newly +// allocated Payload struct, preferring placement in s's segment. +func (s Return) NewResults() (Payload, error) { + capnp.Struct(s).SetUint16(6, 0) + ss, err := NewPayload(capnp.Struct(s).Segment()) + if err != nil { + return Payload{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Return) Exception() (Exception, error) { + if capnp.Struct(s).Uint16(6) != 1 { + panic("Which() != exception") + } + p, err := capnp.Struct(s).Ptr(0) + return Exception(p.Struct()), err +} + +func (s Return) HasException() bool { + if capnp.Struct(s).Uint16(6) != 1 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Return) SetException(v Exception) error { + capnp.Struct(s).SetUint16(6, 1) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewException sets the exception field to a newly +// allocated Exception struct, preferring placement in s's segment. +func (s Return) NewException() (Exception, error) { + capnp.Struct(s).SetUint16(6, 1) + ss, err := NewException(capnp.Struct(s).Segment()) + if err != nil { + return Exception{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Return) SetCanceled() { + capnp.Struct(s).SetUint16(6, 2) + +} + +func (s Return) SetResultsSentElsewhere() { + capnp.Struct(s).SetUint16(6, 3) + +} + +func (s Return) TakeFromOtherQuestion() uint32 { + if capnp.Struct(s).Uint16(6) != 4 { + panic("Which() != takeFromOtherQuestion") + } + return capnp.Struct(s).Uint32(8) +} + +func (s Return) SetTakeFromOtherQuestion(v uint32) { + capnp.Struct(s).SetUint16(6, 4) + capnp.Struct(s).SetUint32(8, v) +} + +func (s Return) AcceptFromThirdParty() (capnp.Ptr, error) { + if capnp.Struct(s).Uint16(6) != 5 { + panic("Which() != acceptFromThirdParty") + } + return capnp.Struct(s).Ptr(0) +} + +func (s Return) HasAcceptFromThirdParty() bool { + if capnp.Struct(s).Uint16(6) != 5 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Return) SetAcceptFromThirdParty(v capnp.Ptr) error { + capnp.Struct(s).SetUint16(6, 5) + return capnp.Struct(s).SetPtr(0, v) +} + +// Return_List is a list of Return. +type Return_List = capnp.StructList[Return] + +// NewReturn creates a new list of Return. +func NewReturn_List(s *capnp.Segment, sz int32) (Return_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}, sz) + return capnp.StructList[Return](l), err +} + +// Return_Future is a wrapper for a Return promised by a client call. +type Return_Future struct{ *capnp.Future } + +func (f Return_Future) Struct() (Return, error) { + p, err := f.Future.Ptr() + return Return(p.Struct()), err +} +func (p Return_Future) Results() Payload_Future { + return Payload_Future{Future: p.Future.Field(0, nil)} +} +func (p Return_Future) Exception() Exception_Future { + return Exception_Future{Future: p.Future.Field(0, nil)} +} +func (p Return_Future) AcceptFromThirdParty() *capnp.Future { + return p.Future.Field(0, nil) +} + +type Finish capnp.Struct + +// Finish_TypeID is the unique identifier for the type Finish. +const Finish_TypeID = 0xd37d2eb2c2f80e63 + +func NewFinish(s *capnp.Segment) (Finish, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return Finish(st), err +} + +func NewRootFinish(s *capnp.Segment) (Finish, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return Finish(st), err +} + +func ReadRootFinish(msg *capnp.Message) (Finish, error) { + root, err := msg.Root() + return Finish(root.Struct()), err +} + +func (s Finish) String() string { + str, _ := text.Marshal(0xd37d2eb2c2f80e63, capnp.Struct(s)) + return str +} + +func (s Finish) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Finish) DecodeFromPtr(p capnp.Ptr) Finish { + return Finish(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Finish) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Finish) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Finish) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Finish) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Finish) QuestionId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Finish) SetQuestionId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Finish) ReleaseResultCaps() bool { + return !capnp.Struct(s).Bit(32) +} + +func (s Finish) SetReleaseResultCaps(v bool) { + capnp.Struct(s).SetBit(32, !v) +} + +// Finish_List is a list of Finish. +type Finish_List = capnp.StructList[Finish] + +// NewFinish creates a new list of Finish. +func NewFinish_List(s *capnp.Segment, sz int32) (Finish_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[Finish](l), err +} + +// Finish_Future is a wrapper for a Finish promised by a client call. +type Finish_Future struct{ *capnp.Future } + +func (f Finish_Future) Struct() (Finish, error) { + p, err := f.Future.Ptr() + return Finish(p.Struct()), err +} + +type Resolve capnp.Struct +type Resolve_Which uint16 + +const ( + Resolve_Which_cap Resolve_Which = 0 + Resolve_Which_exception Resolve_Which = 1 +) + +func (w Resolve_Which) String() string { + const s = "capexception" + switch w { + case Resolve_Which_cap: + return s[0:3] + case Resolve_Which_exception: + return s[3:12] + + } + return "Resolve_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Resolve_TypeID is the unique identifier for the type Resolve. +const Resolve_TypeID = 0xbbc29655fa89086e + +func NewResolve(s *capnp.Segment) (Resolve, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Resolve(st), err +} + +func NewRootResolve(s *capnp.Segment) (Resolve, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Resolve(st), err +} + +func ReadRootResolve(msg *capnp.Message) (Resolve, error) { + root, err := msg.Root() + return Resolve(root.Struct()), err +} + +func (s Resolve) String() string { + str, _ := text.Marshal(0xbbc29655fa89086e, capnp.Struct(s)) + return str +} + +func (s Resolve) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Resolve) DecodeFromPtr(p capnp.Ptr) Resolve { + return Resolve(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Resolve) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Resolve) Which() Resolve_Which { + return Resolve_Which(capnp.Struct(s).Uint16(4)) +} +func (s Resolve) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Resolve) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Resolve) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Resolve) PromiseId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Resolve) SetPromiseId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Resolve) Cap() (CapDescriptor, error) { + if capnp.Struct(s).Uint16(4) != 0 { + panic("Which() != cap") + } + p, err := capnp.Struct(s).Ptr(0) + return CapDescriptor(p.Struct()), err +} + +func (s Resolve) HasCap() bool { + if capnp.Struct(s).Uint16(4) != 0 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Resolve) SetCap(v CapDescriptor) error { + capnp.Struct(s).SetUint16(4, 0) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewCap sets the cap field to a newly +// allocated CapDescriptor struct, preferring placement in s's segment. +func (s Resolve) NewCap() (CapDescriptor, error) { + capnp.Struct(s).SetUint16(4, 0) + ss, err := NewCapDescriptor(capnp.Struct(s).Segment()) + if err != nil { + return CapDescriptor{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Resolve) Exception() (Exception, error) { + if capnp.Struct(s).Uint16(4) != 1 { + panic("Which() != exception") + } + p, err := capnp.Struct(s).Ptr(0) + return Exception(p.Struct()), err +} + +func (s Resolve) HasException() bool { + if capnp.Struct(s).Uint16(4) != 1 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Resolve) SetException(v Exception) error { + capnp.Struct(s).SetUint16(4, 1) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewException sets the exception field to a newly +// allocated Exception struct, preferring placement in s's segment. +func (s Resolve) NewException() (Exception, error) { + capnp.Struct(s).SetUint16(4, 1) + ss, err := NewException(capnp.Struct(s).Segment()) + if err != nil { + return Exception{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// Resolve_List is a list of Resolve. +type Resolve_List = capnp.StructList[Resolve] + +// NewResolve creates a new list of Resolve. +func NewResolve_List(s *capnp.Segment, sz int32) (Resolve_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Resolve](l), err +} + +// Resolve_Future is a wrapper for a Resolve promised by a client call. +type Resolve_Future struct{ *capnp.Future } + +func (f Resolve_Future) Struct() (Resolve, error) { + p, err := f.Future.Ptr() + return Resolve(p.Struct()), err +} +func (p Resolve_Future) Cap() CapDescriptor_Future { + return CapDescriptor_Future{Future: p.Future.Field(0, nil)} +} +func (p Resolve_Future) Exception() Exception_Future { + return Exception_Future{Future: p.Future.Field(0, nil)} +} + +type Release capnp.Struct + +// Release_TypeID is the unique identifier for the type Release. +const Release_TypeID = 0xad1a6c0d7dd07497 + +func NewRelease(s *capnp.Segment) (Release, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return Release(st), err +} + +func NewRootRelease(s *capnp.Segment) (Release, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return Release(st), err +} + +func ReadRootRelease(msg *capnp.Message) (Release, error) { + root, err := msg.Root() + return Release(root.Struct()), err +} + +func (s Release) String() string { + str, _ := text.Marshal(0xad1a6c0d7dd07497, capnp.Struct(s)) + return str +} + +func (s Release) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Release) DecodeFromPtr(p capnp.Ptr) Release { + return Release(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Release) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Release) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Release) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Release) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Release) Id() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Release) SetId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Release) ReferenceCount() uint32 { + return capnp.Struct(s).Uint32(4) +} + +func (s Release) SetReferenceCount(v uint32) { + capnp.Struct(s).SetUint32(4, v) +} + +// Release_List is a list of Release. +type Release_List = capnp.StructList[Release] + +// NewRelease creates a new list of Release. +func NewRelease_List(s *capnp.Segment, sz int32) (Release_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[Release](l), err +} + +// Release_Future is a wrapper for a Release promised by a client call. +type Release_Future struct{ *capnp.Future } + +func (f Release_Future) Struct() (Release, error) { + p, err := f.Future.Ptr() + return Release(p.Struct()), err +} + +type Disembargo capnp.Struct +type Disembargo_context Disembargo +type Disembargo_context_Which uint16 + +const ( + Disembargo_context_Which_senderLoopback Disembargo_context_Which = 0 + Disembargo_context_Which_receiverLoopback Disembargo_context_Which = 1 + Disembargo_context_Which_accept Disembargo_context_Which = 2 + Disembargo_context_Which_provide Disembargo_context_Which = 3 +) + +func (w Disembargo_context_Which) String() string { + const s = "senderLoopbackreceiverLoopbackacceptprovide" + switch w { + case Disembargo_context_Which_senderLoopback: + return s[0:14] + case Disembargo_context_Which_receiverLoopback: + return s[14:30] + case Disembargo_context_Which_accept: + return s[30:36] + case Disembargo_context_Which_provide: + return s[36:43] + + } + return "Disembargo_context_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Disembargo_TypeID is the unique identifier for the type Disembargo. +const Disembargo_TypeID = 0xf964368b0fbd3711 + +func NewDisembargo(s *capnp.Segment) (Disembargo, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Disembargo(st), err +} + +func NewRootDisembargo(s *capnp.Segment) (Disembargo, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Disembargo(st), err +} + +func ReadRootDisembargo(msg *capnp.Message) (Disembargo, error) { + root, err := msg.Root() + return Disembargo(root.Struct()), err +} + +func (s Disembargo) String() string { + str, _ := text.Marshal(0xf964368b0fbd3711, capnp.Struct(s)) + return str +} + +func (s Disembargo) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Disembargo) DecodeFromPtr(p capnp.Ptr) Disembargo { + return Disembargo(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Disembargo) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Disembargo) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Disembargo) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Disembargo) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Disembargo) Target() (MessageTarget, error) { + p, err := capnp.Struct(s).Ptr(0) + return MessageTarget(p.Struct()), err +} + +func (s Disembargo) HasTarget() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Disembargo) SetTarget(v MessageTarget) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewTarget sets the target field to a newly +// allocated MessageTarget struct, preferring placement in s's segment. +func (s Disembargo) NewTarget() (MessageTarget, error) { + ss, err := NewMessageTarget(capnp.Struct(s).Segment()) + if err != nil { + return MessageTarget{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Disembargo) Context() Disembargo_context { return Disembargo_context(s) } + +func (s Disembargo_context) Which() Disembargo_context_Which { + return Disembargo_context_Which(capnp.Struct(s).Uint16(4)) +} +func (s Disembargo_context) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Disembargo_context) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Disembargo_context) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Disembargo_context) SenderLoopback() uint32 { + if capnp.Struct(s).Uint16(4) != 0 { + panic("Which() != senderLoopback") + } + return capnp.Struct(s).Uint32(0) +} + +func (s Disembargo_context) SetSenderLoopback(v uint32) { + capnp.Struct(s).SetUint16(4, 0) + capnp.Struct(s).SetUint32(0, v) +} + +func (s Disembargo_context) ReceiverLoopback() uint32 { + if capnp.Struct(s).Uint16(4) != 1 { + panic("Which() != receiverLoopback") + } + return capnp.Struct(s).Uint32(0) +} + +func (s Disembargo_context) SetReceiverLoopback(v uint32) { + capnp.Struct(s).SetUint16(4, 1) + capnp.Struct(s).SetUint32(0, v) +} + +func (s Disembargo_context) SetAccept() { + capnp.Struct(s).SetUint16(4, 2) + +} + +func (s Disembargo_context) Provide() uint32 { + if capnp.Struct(s).Uint16(4) != 3 { + panic("Which() != provide") + } + return capnp.Struct(s).Uint32(0) +} + +func (s Disembargo_context) SetProvide(v uint32) { + capnp.Struct(s).SetUint16(4, 3) + capnp.Struct(s).SetUint32(0, v) +} + +// Disembargo_List is a list of Disembargo. +type Disembargo_List = capnp.StructList[Disembargo] + +// NewDisembargo creates a new list of Disembargo. +func NewDisembargo_List(s *capnp.Segment, sz int32) (Disembargo_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Disembargo](l), err +} + +// Disembargo_Future is a wrapper for a Disembargo promised by a client call. +type Disembargo_Future struct{ *capnp.Future } + +func (f Disembargo_Future) Struct() (Disembargo, error) { + p, err := f.Future.Ptr() + return Disembargo(p.Struct()), err +} +func (p Disembargo_Future) Target() MessageTarget_Future { + return MessageTarget_Future{Future: p.Future.Field(0, nil)} +} +func (p Disembargo_Future) Context() Disembargo_context_Future { + return Disembargo_context_Future{p.Future} +} + +// Disembargo_context_Future is a wrapper for a Disembargo_context promised by a client call. +type Disembargo_context_Future struct{ *capnp.Future } + +func (f Disembargo_context_Future) Struct() (Disembargo_context, error) { + p, err := f.Future.Ptr() + return Disembargo_context(p.Struct()), err +} + +type Provide capnp.Struct + +// Provide_TypeID is the unique identifier for the type Provide. +const Provide_TypeID = 0x9c6a046bfbc1ac5a + +func NewProvide(s *capnp.Segment) (Provide, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Provide(st), err +} + +func NewRootProvide(s *capnp.Segment) (Provide, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Provide(st), err +} + +func ReadRootProvide(msg *capnp.Message) (Provide, error) { + root, err := msg.Root() + return Provide(root.Struct()), err +} + +func (s Provide) String() string { + str, _ := text.Marshal(0x9c6a046bfbc1ac5a, capnp.Struct(s)) + return str +} + +func (s Provide) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Provide) DecodeFromPtr(p capnp.Ptr) Provide { + return Provide(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Provide) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Provide) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Provide) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Provide) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Provide) QuestionId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Provide) SetQuestionId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Provide) Target() (MessageTarget, error) { + p, err := capnp.Struct(s).Ptr(0) + return MessageTarget(p.Struct()), err +} + +func (s Provide) HasTarget() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Provide) SetTarget(v MessageTarget) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewTarget sets the target field to a newly +// allocated MessageTarget struct, preferring placement in s's segment. +func (s Provide) NewTarget() (MessageTarget, error) { + ss, err := NewMessageTarget(capnp.Struct(s).Segment()) + if err != nil { + return MessageTarget{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Provide) Recipient() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(1) +} + +func (s Provide) HasRecipient() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Provide) SetRecipient(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(1, v) +} + +// Provide_List is a list of Provide. +type Provide_List = capnp.StructList[Provide] + +// NewProvide creates a new list of Provide. +func NewProvide_List(s *capnp.Segment, sz int32) (Provide_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) + return capnp.StructList[Provide](l), err +} + +// Provide_Future is a wrapper for a Provide promised by a client call. +type Provide_Future struct{ *capnp.Future } + +func (f Provide_Future) Struct() (Provide, error) { + p, err := f.Future.Ptr() + return Provide(p.Struct()), err +} +func (p Provide_Future) Target() MessageTarget_Future { + return MessageTarget_Future{Future: p.Future.Field(0, nil)} +} +func (p Provide_Future) Recipient() *capnp.Future { + return p.Future.Field(1, nil) +} + +type Accept capnp.Struct + +// Accept_TypeID is the unique identifier for the type Accept. +const Accept_TypeID = 0xd4c9b56290554016 + +func NewAccept(s *capnp.Segment) (Accept, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Accept(st), err +} + +func NewRootAccept(s *capnp.Segment) (Accept, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Accept(st), err +} + +func ReadRootAccept(msg *capnp.Message) (Accept, error) { + root, err := msg.Root() + return Accept(root.Struct()), err +} + +func (s Accept) String() string { + str, _ := text.Marshal(0xd4c9b56290554016, capnp.Struct(s)) + return str +} + +func (s Accept) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Accept) DecodeFromPtr(p capnp.Ptr) Accept { + return Accept(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Accept) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Accept) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Accept) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Accept) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Accept) QuestionId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Accept) SetQuestionId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Accept) Provision() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) +} + +func (s Accept) HasProvision() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Accept) SetProvision(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} +func (s Accept) Embargo() bool { + return capnp.Struct(s).Bit(32) +} + +func (s Accept) SetEmbargo(v bool) { + capnp.Struct(s).SetBit(32, v) +} + +// Accept_List is a list of Accept. +type Accept_List = capnp.StructList[Accept] + +// NewAccept creates a new list of Accept. +func NewAccept_List(s *capnp.Segment, sz int32) (Accept_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Accept](l), err +} + +// Accept_Future is a wrapper for a Accept promised by a client call. +type Accept_Future struct{ *capnp.Future } + +func (f Accept_Future) Struct() (Accept, error) { + p, err := f.Future.Ptr() + return Accept(p.Struct()), err +} +func (p Accept_Future) Provision() *capnp.Future { + return p.Future.Field(0, nil) +} + +type Join capnp.Struct + +// Join_TypeID is the unique identifier for the type Join. +const Join_TypeID = 0xfbe1980490e001af + +func NewJoin(s *capnp.Segment) (Join, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Join(st), err +} + +func NewRootJoin(s *capnp.Segment) (Join, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Join(st), err +} + +func ReadRootJoin(msg *capnp.Message) (Join, error) { + root, err := msg.Root() + return Join(root.Struct()), err +} + +func (s Join) String() string { + str, _ := text.Marshal(0xfbe1980490e001af, capnp.Struct(s)) + return str +} + +func (s Join) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Join) DecodeFromPtr(p capnp.Ptr) Join { + return Join(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Join) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Join) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Join) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Join) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Join) QuestionId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s Join) SetQuestionId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s Join) Target() (MessageTarget, error) { + p, err := capnp.Struct(s).Ptr(0) + return MessageTarget(p.Struct()), err +} + +func (s Join) HasTarget() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Join) SetTarget(v MessageTarget) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewTarget sets the target field to a newly +// allocated MessageTarget struct, preferring placement in s's segment. +func (s Join) NewTarget() (MessageTarget, error) { + ss, err := NewMessageTarget(capnp.Struct(s).Segment()) + if err != nil { + return MessageTarget{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Join) KeyPart() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(1) +} + +func (s Join) HasKeyPart() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Join) SetKeyPart(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(1, v) +} + +// Join_List is a list of Join. +type Join_List = capnp.StructList[Join] + +// NewJoin creates a new list of Join. +func NewJoin_List(s *capnp.Segment, sz int32) (Join_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) + return capnp.StructList[Join](l), err +} + +// Join_Future is a wrapper for a Join promised by a client call. +type Join_Future struct{ *capnp.Future } + +func (f Join_Future) Struct() (Join, error) { + p, err := f.Future.Ptr() + return Join(p.Struct()), err +} +func (p Join_Future) Target() MessageTarget_Future { + return MessageTarget_Future{Future: p.Future.Field(0, nil)} +} +func (p Join_Future) KeyPart() *capnp.Future { + return p.Future.Field(1, nil) +} + +type MessageTarget capnp.Struct +type MessageTarget_Which uint16 + +const ( + MessageTarget_Which_importedCap MessageTarget_Which = 0 + MessageTarget_Which_promisedAnswer MessageTarget_Which = 1 +) + +func (w MessageTarget_Which) String() string { + const s = "importedCappromisedAnswer" + switch w { + case MessageTarget_Which_importedCap: + return s[0:11] + case MessageTarget_Which_promisedAnswer: + return s[11:25] + + } + return "MessageTarget_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// MessageTarget_TypeID is the unique identifier for the type MessageTarget. +const MessageTarget_TypeID = 0x95bc14545813fbc1 + +func NewMessageTarget(s *capnp.Segment) (MessageTarget, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return MessageTarget(st), err +} + +func NewRootMessageTarget(s *capnp.Segment) (MessageTarget, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return MessageTarget(st), err +} + +func ReadRootMessageTarget(msg *capnp.Message) (MessageTarget, error) { + root, err := msg.Root() + return MessageTarget(root.Struct()), err +} + +func (s MessageTarget) String() string { + str, _ := text.Marshal(0x95bc14545813fbc1, capnp.Struct(s)) + return str +} + +func (s MessageTarget) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (MessageTarget) DecodeFromPtr(p capnp.Ptr) MessageTarget { + return MessageTarget(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s MessageTarget) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s MessageTarget) Which() MessageTarget_Which { + return MessageTarget_Which(capnp.Struct(s).Uint16(4)) +} +func (s MessageTarget) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s MessageTarget) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s MessageTarget) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s MessageTarget) ImportedCap() uint32 { + if capnp.Struct(s).Uint16(4) != 0 { + panic("Which() != importedCap") + } + return capnp.Struct(s).Uint32(0) +} + +func (s MessageTarget) SetImportedCap(v uint32) { + capnp.Struct(s).SetUint16(4, 0) + capnp.Struct(s).SetUint32(0, v) +} + +func (s MessageTarget) PromisedAnswer() (PromisedAnswer, error) { + if capnp.Struct(s).Uint16(4) != 1 { + panic("Which() != promisedAnswer") + } + p, err := capnp.Struct(s).Ptr(0) + return PromisedAnswer(p.Struct()), err +} + +func (s MessageTarget) HasPromisedAnswer() bool { + if capnp.Struct(s).Uint16(4) != 1 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s MessageTarget) SetPromisedAnswer(v PromisedAnswer) error { + capnp.Struct(s).SetUint16(4, 1) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewPromisedAnswer sets the promisedAnswer field to a newly +// allocated PromisedAnswer struct, preferring placement in s's segment. +func (s MessageTarget) NewPromisedAnswer() (PromisedAnswer, error) { + capnp.Struct(s).SetUint16(4, 1) + ss, err := NewPromisedAnswer(capnp.Struct(s).Segment()) + if err != nil { + return PromisedAnswer{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// MessageTarget_List is a list of MessageTarget. +type MessageTarget_List = capnp.StructList[MessageTarget] + +// NewMessageTarget creates a new list of MessageTarget. +func NewMessageTarget_List(s *capnp.Segment, sz int32) (MessageTarget_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[MessageTarget](l), err +} + +// MessageTarget_Future is a wrapper for a MessageTarget promised by a client call. +type MessageTarget_Future struct{ *capnp.Future } + +func (f MessageTarget_Future) Struct() (MessageTarget, error) { + p, err := f.Future.Ptr() + return MessageTarget(p.Struct()), err +} +func (p MessageTarget_Future) PromisedAnswer() PromisedAnswer_Future { + return PromisedAnswer_Future{Future: p.Future.Field(0, nil)} +} + +type Payload capnp.Struct + +// Payload_TypeID is the unique identifier for the type Payload. +const Payload_TypeID = 0x9a0e61223d96743b + +func NewPayload(s *capnp.Segment) (Payload, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return Payload(st), err +} + +func NewRootPayload(s *capnp.Segment) (Payload, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + return Payload(st), err +} + +func ReadRootPayload(msg *capnp.Message) (Payload, error) { + root, err := msg.Root() + return Payload(root.Struct()), err +} + +func (s Payload) String() string { + str, _ := text.Marshal(0x9a0e61223d96743b, capnp.Struct(s)) + return str +} + +func (s Payload) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Payload) DecodeFromPtr(p capnp.Ptr) Payload { + return Payload(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Payload) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Payload) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Payload) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Payload) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Payload) Content() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) +} + +func (s Payload) HasContent() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Payload) SetContent(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} +func (s Payload) CapTable() (CapDescriptor_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return CapDescriptor_List(p.List()), err +} + +func (s Payload) HasCapTable() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Payload) SetCapTable(v CapDescriptor_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewCapTable sets the capTable field to a newly +// allocated CapDescriptor_List, preferring placement in s's segment. +func (s Payload) NewCapTable(n int32) (CapDescriptor_List, error) { + l, err := NewCapDescriptor_List(capnp.Struct(s).Segment(), n) + if err != nil { + return CapDescriptor_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} + +// Payload_List is a list of Payload. +type Payload_List = capnp.StructList[Payload] + +// NewPayload creates a new list of Payload. +func NewPayload_List(s *capnp.Segment, sz int32) (Payload_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz) + return capnp.StructList[Payload](l), err +} + +// Payload_Future is a wrapper for a Payload promised by a client call. +type Payload_Future struct{ *capnp.Future } + +func (f Payload_Future) Struct() (Payload, error) { + p, err := f.Future.Ptr() + return Payload(p.Struct()), err +} +func (p Payload_Future) Content() *capnp.Future { + return p.Future.Field(0, nil) +} + +type CapDescriptor capnp.Struct +type CapDescriptor_Which uint16 + +const ( + CapDescriptor_Which_none CapDescriptor_Which = 0 + CapDescriptor_Which_senderHosted CapDescriptor_Which = 1 + CapDescriptor_Which_senderPromise CapDescriptor_Which = 2 + CapDescriptor_Which_receiverHosted CapDescriptor_Which = 3 + CapDescriptor_Which_receiverAnswer CapDescriptor_Which = 4 + CapDescriptor_Which_thirdPartyHosted CapDescriptor_Which = 5 +) + +func (w CapDescriptor_Which) String() string { + const s = "nonesenderHostedsenderPromisereceiverHostedreceiverAnswerthirdPartyHosted" + switch w { + case CapDescriptor_Which_none: + return s[0:4] + case CapDescriptor_Which_senderHosted: + return s[4:16] + case CapDescriptor_Which_senderPromise: + return s[16:29] + case CapDescriptor_Which_receiverHosted: + return s[29:43] + case CapDescriptor_Which_receiverAnswer: + return s[43:57] + case CapDescriptor_Which_thirdPartyHosted: + return s[57:73] + + } + return "CapDescriptor_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// CapDescriptor_TypeID is the unique identifier for the type CapDescriptor. +const CapDescriptor_TypeID = 0x8523ddc40b86b8b0 + +func NewCapDescriptor(s *capnp.Segment) (CapDescriptor, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return CapDescriptor(st), err +} + +func NewRootCapDescriptor(s *capnp.Segment) (CapDescriptor, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return CapDescriptor(st), err +} + +func ReadRootCapDescriptor(msg *capnp.Message) (CapDescriptor, error) { + root, err := msg.Root() + return CapDescriptor(root.Struct()), err +} + +func (s CapDescriptor) String() string { + str, _ := text.Marshal(0x8523ddc40b86b8b0, capnp.Struct(s)) + return str +} + +func (s CapDescriptor) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (CapDescriptor) DecodeFromPtr(p capnp.Ptr) CapDescriptor { + return CapDescriptor(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s CapDescriptor) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s CapDescriptor) Which() CapDescriptor_Which { + return CapDescriptor_Which(capnp.Struct(s).Uint16(0)) +} +func (s CapDescriptor) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s CapDescriptor) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s CapDescriptor) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s CapDescriptor) SetNone() { + capnp.Struct(s).SetUint16(0, 0) + +} + +func (s CapDescriptor) SenderHosted() uint32 { + if capnp.Struct(s).Uint16(0) != 1 { + panic("Which() != senderHosted") + } + return capnp.Struct(s).Uint32(4) +} + +func (s CapDescriptor) SetSenderHosted(v uint32) { + capnp.Struct(s).SetUint16(0, 1) + capnp.Struct(s).SetUint32(4, v) +} + +func (s CapDescriptor) SenderPromise() uint32 { + if capnp.Struct(s).Uint16(0) != 2 { + panic("Which() != senderPromise") + } + return capnp.Struct(s).Uint32(4) +} + +func (s CapDescriptor) SetSenderPromise(v uint32) { + capnp.Struct(s).SetUint16(0, 2) + capnp.Struct(s).SetUint32(4, v) +} + +func (s CapDescriptor) ReceiverHosted() uint32 { + if capnp.Struct(s).Uint16(0) != 3 { + panic("Which() != receiverHosted") + } + return capnp.Struct(s).Uint32(4) +} + +func (s CapDescriptor) SetReceiverHosted(v uint32) { + capnp.Struct(s).SetUint16(0, 3) + capnp.Struct(s).SetUint32(4, v) +} + +func (s CapDescriptor) ReceiverAnswer() (PromisedAnswer, error) { + if capnp.Struct(s).Uint16(0) != 4 { + panic("Which() != receiverAnswer") + } + p, err := capnp.Struct(s).Ptr(0) + return PromisedAnswer(p.Struct()), err +} + +func (s CapDescriptor) HasReceiverAnswer() bool { + if capnp.Struct(s).Uint16(0) != 4 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s CapDescriptor) SetReceiverAnswer(v PromisedAnswer) error { + capnp.Struct(s).SetUint16(0, 4) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewReceiverAnswer sets the receiverAnswer field to a newly +// allocated PromisedAnswer struct, preferring placement in s's segment. +func (s CapDescriptor) NewReceiverAnswer() (PromisedAnswer, error) { + capnp.Struct(s).SetUint16(0, 4) + ss, err := NewPromisedAnswer(capnp.Struct(s).Segment()) + if err != nil { + return PromisedAnswer{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s CapDescriptor) ThirdPartyHosted() (ThirdPartyCapDescriptor, error) { + if capnp.Struct(s).Uint16(0) != 5 { + panic("Which() != thirdPartyHosted") + } + p, err := capnp.Struct(s).Ptr(0) + return ThirdPartyCapDescriptor(p.Struct()), err +} + +func (s CapDescriptor) HasThirdPartyHosted() bool { + if capnp.Struct(s).Uint16(0) != 5 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s CapDescriptor) SetThirdPartyHosted(v ThirdPartyCapDescriptor) error { + capnp.Struct(s).SetUint16(0, 5) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewThirdPartyHosted sets the thirdPartyHosted field to a newly +// allocated ThirdPartyCapDescriptor struct, preferring placement in s's segment. +func (s CapDescriptor) NewThirdPartyHosted() (ThirdPartyCapDescriptor, error) { + capnp.Struct(s).SetUint16(0, 5) + ss, err := NewThirdPartyCapDescriptor(capnp.Struct(s).Segment()) + if err != nil { + return ThirdPartyCapDescriptor{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s CapDescriptor) AttachedFd() uint8 { + return capnp.Struct(s).Uint8(2) ^ 255 +} + +func (s CapDescriptor) SetAttachedFd(v uint8) { + capnp.Struct(s).SetUint8(2, v^255) +} + +// CapDescriptor_List is a list of CapDescriptor. +type CapDescriptor_List = capnp.StructList[CapDescriptor] + +// NewCapDescriptor creates a new list of CapDescriptor. +func NewCapDescriptor_List(s *capnp.Segment, sz int32) (CapDescriptor_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[CapDescriptor](l), err +} + +// CapDescriptor_Future is a wrapper for a CapDescriptor promised by a client call. +type CapDescriptor_Future struct{ *capnp.Future } + +func (f CapDescriptor_Future) Struct() (CapDescriptor, error) { + p, err := f.Future.Ptr() + return CapDescriptor(p.Struct()), err +} +func (p CapDescriptor_Future) ReceiverAnswer() PromisedAnswer_Future { + return PromisedAnswer_Future{Future: p.Future.Field(0, nil)} +} +func (p CapDescriptor_Future) ThirdPartyHosted() ThirdPartyCapDescriptor_Future { + return ThirdPartyCapDescriptor_Future{Future: p.Future.Field(0, nil)} +} + +type PromisedAnswer capnp.Struct + +// PromisedAnswer_TypeID is the unique identifier for the type PromisedAnswer. +const PromisedAnswer_TypeID = 0xd800b1d6cd6f1ca0 + +func NewPromisedAnswer(s *capnp.Segment) (PromisedAnswer, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return PromisedAnswer(st), err +} + +func NewRootPromisedAnswer(s *capnp.Segment) (PromisedAnswer, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return PromisedAnswer(st), err +} + +func ReadRootPromisedAnswer(msg *capnp.Message) (PromisedAnswer, error) { + root, err := msg.Root() + return PromisedAnswer(root.Struct()), err +} + +func (s PromisedAnswer) String() string { + str, _ := text.Marshal(0xd800b1d6cd6f1ca0, capnp.Struct(s)) + return str +} + +func (s PromisedAnswer) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (PromisedAnswer) DecodeFromPtr(p capnp.Ptr) PromisedAnswer { + return PromisedAnswer(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s PromisedAnswer) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s PromisedAnswer) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s PromisedAnswer) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s PromisedAnswer) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s PromisedAnswer) QuestionId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s PromisedAnswer) SetQuestionId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s PromisedAnswer) Transform() (PromisedAnswer_Op_List, error) { + p, err := capnp.Struct(s).Ptr(0) + return PromisedAnswer_Op_List(p.List()), err +} + +func (s PromisedAnswer) HasTransform() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s PromisedAnswer) SetTransform(v PromisedAnswer_Op_List) error { + return capnp.Struct(s).SetPtr(0, v.ToPtr()) +} + +// NewTransform sets the transform field to a newly +// allocated PromisedAnswer_Op_List, preferring placement in s's segment. +func (s PromisedAnswer) NewTransform(n int32) (PromisedAnswer_Op_List, error) { + l, err := NewPromisedAnswer_Op_List(capnp.Struct(s).Segment(), n) + if err != nil { + return PromisedAnswer_Op_List{}, err + } + err = capnp.Struct(s).SetPtr(0, l.ToPtr()) + return l, err +} + +// PromisedAnswer_List is a list of PromisedAnswer. +type PromisedAnswer_List = capnp.StructList[PromisedAnswer] + +// NewPromisedAnswer creates a new list of PromisedAnswer. +func NewPromisedAnswer_List(s *capnp.Segment, sz int32) (PromisedAnswer_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[PromisedAnswer](l), err +} + +// PromisedAnswer_Future is a wrapper for a PromisedAnswer promised by a client call. +type PromisedAnswer_Future struct{ *capnp.Future } + +func (f PromisedAnswer_Future) Struct() (PromisedAnswer, error) { + p, err := f.Future.Ptr() + return PromisedAnswer(p.Struct()), err +} + +type PromisedAnswer_Op capnp.Struct +type PromisedAnswer_Op_Which uint16 + +const ( + PromisedAnswer_Op_Which_noop PromisedAnswer_Op_Which = 0 + PromisedAnswer_Op_Which_getPointerField PromisedAnswer_Op_Which = 1 +) + +func (w PromisedAnswer_Op_Which) String() string { + const s = "noopgetPointerField" + switch w { + case PromisedAnswer_Op_Which_noop: + return s[0:4] + case PromisedAnswer_Op_Which_getPointerField: + return s[4:19] + + } + return "PromisedAnswer_Op_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// PromisedAnswer_Op_TypeID is the unique identifier for the type PromisedAnswer_Op. +const PromisedAnswer_Op_TypeID = 0xf316944415569081 + +func NewPromisedAnswer_Op(s *capnp.Segment) (PromisedAnswer_Op, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return PromisedAnswer_Op(st), err +} + +func NewRootPromisedAnswer_Op(s *capnp.Segment) (PromisedAnswer_Op, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return PromisedAnswer_Op(st), err +} + +func ReadRootPromisedAnswer_Op(msg *capnp.Message) (PromisedAnswer_Op, error) { + root, err := msg.Root() + return PromisedAnswer_Op(root.Struct()), err +} + +func (s PromisedAnswer_Op) String() string { + str, _ := text.Marshal(0xf316944415569081, capnp.Struct(s)) + return str +} + +func (s PromisedAnswer_Op) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (PromisedAnswer_Op) DecodeFromPtr(p capnp.Ptr) PromisedAnswer_Op { + return PromisedAnswer_Op(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s PromisedAnswer_Op) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s PromisedAnswer_Op) Which() PromisedAnswer_Op_Which { + return PromisedAnswer_Op_Which(capnp.Struct(s).Uint16(0)) +} +func (s PromisedAnswer_Op) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s PromisedAnswer_Op) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s PromisedAnswer_Op) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s PromisedAnswer_Op) SetNoop() { + capnp.Struct(s).SetUint16(0, 0) + +} + +func (s PromisedAnswer_Op) GetPointerField() uint16 { + if capnp.Struct(s).Uint16(0) != 1 { + panic("Which() != getPointerField") + } + return capnp.Struct(s).Uint16(2) +} + +func (s PromisedAnswer_Op) SetGetPointerField(v uint16) { + capnp.Struct(s).SetUint16(0, 1) + capnp.Struct(s).SetUint16(2, v) +} + +// PromisedAnswer_Op_List is a list of PromisedAnswer_Op. +type PromisedAnswer_Op_List = capnp.StructList[PromisedAnswer_Op] + +// NewPromisedAnswer_Op creates a new list of PromisedAnswer_Op. +func NewPromisedAnswer_Op_List(s *capnp.Segment, sz int32) (PromisedAnswer_Op_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[PromisedAnswer_Op](l), err +} + +// PromisedAnswer_Op_Future is a wrapper for a PromisedAnswer_Op promised by a client call. +type PromisedAnswer_Op_Future struct{ *capnp.Future } + +func (f PromisedAnswer_Op_Future) Struct() (PromisedAnswer_Op, error) { + p, err := f.Future.Ptr() + return PromisedAnswer_Op(p.Struct()), err +} + +type ThirdPartyCapDescriptor capnp.Struct + +// ThirdPartyCapDescriptor_TypeID is the unique identifier for the type ThirdPartyCapDescriptor. +const ThirdPartyCapDescriptor_TypeID = 0xd37007fde1f0027d + +func NewThirdPartyCapDescriptor(s *capnp.Segment) (ThirdPartyCapDescriptor, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return ThirdPartyCapDescriptor(st), err +} + +func NewRootThirdPartyCapDescriptor(s *capnp.Segment) (ThirdPartyCapDescriptor, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return ThirdPartyCapDescriptor(st), err +} + +func ReadRootThirdPartyCapDescriptor(msg *capnp.Message) (ThirdPartyCapDescriptor, error) { + root, err := msg.Root() + return ThirdPartyCapDescriptor(root.Struct()), err +} + +func (s ThirdPartyCapDescriptor) String() string { + str, _ := text.Marshal(0xd37007fde1f0027d, capnp.Struct(s)) + return str +} + +func (s ThirdPartyCapDescriptor) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (ThirdPartyCapDescriptor) DecodeFromPtr(p capnp.Ptr) ThirdPartyCapDescriptor { + return ThirdPartyCapDescriptor(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s ThirdPartyCapDescriptor) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s ThirdPartyCapDescriptor) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s ThirdPartyCapDescriptor) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s ThirdPartyCapDescriptor) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s ThirdPartyCapDescriptor) Id() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) +} + +func (s ThirdPartyCapDescriptor) HasId() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s ThirdPartyCapDescriptor) SetId(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} +func (s ThirdPartyCapDescriptor) VineId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s ThirdPartyCapDescriptor) SetVineId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +// ThirdPartyCapDescriptor_List is a list of ThirdPartyCapDescriptor. +type ThirdPartyCapDescriptor_List = capnp.StructList[ThirdPartyCapDescriptor] + +// NewThirdPartyCapDescriptor creates a new list of ThirdPartyCapDescriptor. +func NewThirdPartyCapDescriptor_List(s *capnp.Segment, sz int32) (ThirdPartyCapDescriptor_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[ThirdPartyCapDescriptor](l), err +} + +// ThirdPartyCapDescriptor_Future is a wrapper for a ThirdPartyCapDescriptor promised by a client call. +type ThirdPartyCapDescriptor_Future struct{ *capnp.Future } + +func (f ThirdPartyCapDescriptor_Future) Struct() (ThirdPartyCapDescriptor, error) { + p, err := f.Future.Ptr() + return ThirdPartyCapDescriptor(p.Struct()), err +} +func (p ThirdPartyCapDescriptor_Future) Id() *capnp.Future { + return p.Future.Field(0, nil) +} + +type Exception capnp.Struct + +// Exception_TypeID is the unique identifier for the type Exception. +const Exception_TypeID = 0xd625b7063acf691a + +func NewException(s *capnp.Segment) (Exception, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Exception(st), err +} + +func NewRootException(s *capnp.Segment) (Exception, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Exception(st), err +} + +func ReadRootException(msg *capnp.Message) (Exception, error) { + root, err := msg.Root() + return Exception(root.Struct()), err +} + +func (s Exception) String() string { + str, _ := text.Marshal(0xd625b7063acf691a, capnp.Struct(s)) + return str +} + +func (s Exception) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Exception) DecodeFromPtr(p capnp.Ptr) Exception { + return Exception(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Exception) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Exception) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Exception) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Exception) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Exception) Reason() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Exception) HasReason() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Exception) ReasonBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Exception) SetReason(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Exception) Type() Exception_Type { + return Exception_Type(capnp.Struct(s).Uint16(4)) +} + +func (s Exception) SetType(v Exception_Type) { + capnp.Struct(s).SetUint16(4, uint16(v)) +} + +func (s Exception) ObsoleteIsCallersFault() bool { + return capnp.Struct(s).Bit(0) +} + +func (s Exception) SetObsoleteIsCallersFault(v bool) { + capnp.Struct(s).SetBit(0, v) +} + +func (s Exception) ObsoleteDurability() uint16 { + return capnp.Struct(s).Uint16(2) +} + +func (s Exception) SetObsoleteDurability(v uint16) { + capnp.Struct(s).SetUint16(2, v) +} + +func (s Exception) Trace() (string, error) { + p, err := capnp.Struct(s).Ptr(1) + return p.Text(), err +} + +func (s Exception) HasTrace() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Exception) TraceBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(1) + return p.TextBytes(), err +} + +func (s Exception) SetTrace(v string) error { + return capnp.Struct(s).SetText(1, v) +} + +// Exception_List is a list of Exception. +type Exception_List = capnp.StructList[Exception] + +// NewException creates a new list of Exception. +func NewException_List(s *capnp.Segment, sz int32) (Exception_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) + return capnp.StructList[Exception](l), err +} + +// Exception_Future is a wrapper for a Exception promised by a client call. +type Exception_Future struct{ *capnp.Future } + +func (f Exception_Future) Struct() (Exception, error) { + p, err := f.Future.Ptr() + return Exception(p.Struct()), err +} + +type Exception_Type uint16 + +// Exception_Type_TypeID is the unique identifier for the type Exception_Type. +const Exception_Type_TypeID = 0xb28c96e23f4cbd58 + +// Values of Exception_Type. +const ( + Exception_Type_failed Exception_Type = 0 + Exception_Type_overloaded Exception_Type = 1 + Exception_Type_disconnected Exception_Type = 2 + Exception_Type_unimplemented Exception_Type = 3 +) + +// String returns the enum's constant name. +func (c Exception_Type) String() string { + switch c { + case Exception_Type_failed: + return "failed" + case Exception_Type_overloaded: + return "overloaded" + case Exception_Type_disconnected: + return "disconnected" + case Exception_Type_unimplemented: + return "unimplemented" + + default: + return "" + } +} + +// Exception_TypeFromString returns the enum value with a name, +// or the zero value if there's no such value. +func Exception_TypeFromString(c string) Exception_Type { + switch c { + case "failed": + return Exception_Type_failed + case "overloaded": + return Exception_Type_overloaded + case "disconnected": + return Exception_Type_disconnected + case "unimplemented": + return Exception_Type_unimplemented + + default: + return 0 + } +} + +type Exception_Type_List = capnp.EnumList[Exception_Type] + +func NewException_Type_List(s *capnp.Segment, sz int32) (Exception_Type_List, error) { + return capnp.NewEnumList[Exception_Type](s, sz) +} + +const schema_b312981b2552a250 = "x\xda\x9cX\x7f\x8c\x15\xd5\xf5?\xe7\xde\xb7\xef-\xec" + + "\x8f\xf7\x86\x99\x95\xc0\xd7\xcd\xa2\xdf\x9a\x14R\x88\xa8i" + + "\xcd\xb6\xe6!,\x84%K\xd8\xbboi\x0dm\xd2\xce" + + "\xce\xbb\xec\xce2;3\xce\xcc\xc2.\x91\x00-4J" + + "\xddt%j\xd1hk\x8d\x7f\xb4\xd6FD\x8c\xdaB" + + "*\x84\xa6jl\xd5(F\x1bI\xc5\xd4T\x9b\xfea" + + "\xab\xb5*?\xa693\xf3f\x1e\xbboC\xec_\xfb" + + "2\x9f3s\xcf\xfd\x9cs>\x9f{\xf7\xda\x9d\xf9U" + + "\xb9\x95m\x9b\xe6\x01\x13VS>|\xbd\xef\xc1\x89?" + + "UF\x7f\x00b>\xf2\xb0\xff\xe1\x81k\xfe\xef\xd0\x82" + + "'\xa1\x89\x17\x00\xd4\xa9\xdcN\xf5\xae\\\x01\xe0\xfa\xa9" + + "\xdc\x8f\x110<\xfc\xcc\x0f[N\x9d\xf9\xff\xfd\x14\x8d" + + "Y\xf4Z,\xe4\x01T%\x7fR]\x94\xa7\xf0\x8e|" + + "\x14~\xdd\xe1\xa9=]?{\xfa\xae\xd9\xe1\xed\x00\xea" + + "\xb3\x85\x83\xea\x89\x02\x85\x1f/,\xe4\x80\xe1\x89s\xea" + + "-\x83\xda\xb1{f\x873d\xea\x85\xf9'\xd5\xa6\x16" + + "J\x0b[v\x00\x86_\x0f\xee\xbd\xe9j\xbd\xfd~P" + + "\xe6\xd7\x0571\x8a\x90-\x07\xd5\xb1(\xd6\x8cb\xb7" + + "<{\xa1\xe0\xbe" + + "6s{Hi>Q\\\x80\xea\x89(\xfax\x91\x92" + + "0\xda?=yd\xc5\xae\xd7\x1a%\xbc\xa8t@\xbd" + + "\xaaD\xbf:K\x14{\xc5\xaa\xcd\xd3CO\xbd\xf0z" + + "\xa3/\xab\xfbK\x07\xd4\xa9(\xf8\x8e\x12\xa5\xb1\xf1\xcc" + + "\xb7\xe5_\x8e\x0e\x9d\x06\xd1\x81\x18*_;^\xfc\xd1" + + "W\xab\x9f\xc1f,`\x0e\x99\xbaT\xf9;\xa0\xba\\" + + "\xf9\x1b`\xb6\xf7F\x05i[\xf0\xb0\xda\xb1`!\xc0" + + "\xf5\x9d\x0b\xba\x10\xf0w\x0f]\xe9\xfc\xf1\x8d'\xdel" + + "\x94\xc3M\xea\x8bj\xaf\xba\x10@\x15*%|\xdfw" + + "\x7f\xb5\xf8\x93\xc3\xef\xff\x19D\x11y\xd6\xdd\x9by\x01" + + "9r\xf5\xf7*\xe5\xf0\x82J\xe9\x9e\xb2\x17\xae\xdc\xf3" + + "r\xdf\x07\x0d\xf7fj\x0f\xab\xb7j\xf4kL\xa3\xef" + + "\xee\x9d\xfefG\xcf\xddW|\x04b\x11\xa6\x09\xf5\x14" + + "\x18\x80zZ{W=\x1b\x85\x9e\x89B\xd3\x8d7\xcc" + + "\xb7\xe3Qum\x07\xfd\xba\xb9\x83\x82\x1f\xc7w\xa6s" + + "\x87\xce\x9ekH\xc4\xde\x8e\x9d\xea\xfe\x8e\xf8\xd7\xe3\xb0" + + "&\xf4\\c\x85\xa1\xbb6\x94\xdd\xee5\xbae\xf5#" + + "\x8a+y\x0e \x87\x00\xcaS[\x00\xc4Q\x8e\xe29" + + "\x86\x88\x1a\xd2\xb3\xe3\xdd\x00\xe2\x19\x8e\xe2\x14C\x85\xa1" + + "\x86\x0c@91\x04 \x9e\xe3(^b\xa8p\xa6!" + + "\x07P^\xd8\x00 \x9e\xe7(^g\xa84\xa1\x869" + + "\x00\xe5Uz\xfd%\x8e\xe2M\x86\x98\xc7:z\x95\xd3" + + "\x1e0%\xb7G\xc3fD\xe5\xc4I\x00q\x8a\xa3x" + + "\x85ax\xeb\xb8\xf4\x03\xd3\xb1\x81\xf7V\xb1\x19\x186" + + "\x03\x96\x03\xdd\x1b\x96\x01\x96\xb2!\x07\xc4\x12`h\xda" + + "\x81\xf4\xb6\xea\x06\x14do\x15\xe7\x01\xc3y\x80\xe1\x98" + + "\x0cF\x9cjo\x15\x00\xb0\x00\x0c\x0b\x80eW\xf7\xf4" + + "1\x1fK\xd9\xe4'\x9f\xf0\xa5]\x1d\x90\xfe8tY" + + "\x81?\xe8\x84\xbae9;\x06GL\xe6U\xfbu/" + + "\x98\x1c\xd4M\x8b\xe8\x02D`H3[#\x92\x11\x8f" + + "n\x8f\xf4\x0d\xcft\x03\xc7\x83\x84\xd1\xd60\x8c)]" + + "\x06 \x0es\x14\xc7\x18v\xe2\xc50a\xf5\xd9\xd1\x8c" + + "\xd5Nv!\xac\xf1\xeae\xbcv\xf2\xf3\xf48bv" + + "g\xc6l[\xee\\\x98PKO_\xe1(\xdef\xd8" + + "\xd6\xf4y\xa8a\x13\x80\xf2\xd6\x01\x00\xf16G\xf1>" + + "C%\xcf4\"]y\x8f\x0a\xfbW\x8e\xe2C\x86E" + + "\xdb\xb1%\xe4\xa3=Ko\xbd\x03E?\x90)\xcd\xc9" + + "\xe3~\x0f\xba\x9c1\xd3\x97\xe9sO\x1a\xd2\xdc.=" + + "(\xafw.y!\x03n\xb6\xfd\x1d\xd2\xc3R\xad\xb9" + + "\x13r\x83\x113\xa2\x11\x83\xc9\xf8U\x00,e\x8a\x93" + + "D\xe9A\xa0\x1b#\xb2\x0a|]\x15\xf3\xc0\x9a\xf2a" + + "\x1d\xcd\xe8vo\x94\xbe\xaf\x0f\xa3$\x82oL\x09V" + + "'\xd1\x03\xa8L \xc7\xca>d\xd8\x86\x17\xc3\x88b" + + "u/^\x07P\xb9\x8d\x80\xdb\x09\xe0\x17\xc2\x88du" + + "?.\x03\xa8\xec!\xe0N\x02r\xe7\xc3\x88f\xf5\x0e" + + "\xec\x06\xa8\xec#`\x9a\x80\xa6\x84iu*\x02n'" + + "\xe0n\x02\xf2\x09\xd9\xea]\xb8\x1a\xa0r'\x01\x87\x08" + + "(|\x16jHFvO\x04L\x13\xf0\x00\x01\xf3>" + + "\x0d\xb5hz\xef\xc3Q\x80\xca!\x02\x1e!\x80\xfd'" + + "\xd4\xb0\x19@\xfd9\x0e\x00T\x1e\"\xe01\x02\xe6\x7f" + + "\x12j8\x0f@\xfd%\xee\x04\xa8\xfc\x82\x80\xa3\x04\xb4" + + "\xfc;\xd4p>\x80\xfaD\xb4\xc6c\x04O" + + "TF\xc1G\x01*\x1a\x01Kh\x9e\xf5\xa8\xec\xb1\x19" + + "f\xba\x1d\x8dQ?\x92)\xae\xd1]\x1f\"wk\"" + + "{\xa3\xe9\x1b\xb7\x82FV)'\xa8\xf7M\x07\xd0\x9e" + + "=\xfe\xa1\xa1\xdb\x86\xb4H\xe2\x0ba\xf2\x8d\x0aJ;" + + "Xk\xf9rGqDz\xe4<\x81\xbeM\xae\xf3\x9c" + + "1\xdc\x14\x8cHO\x8c\xcb\xae\xa8Zif\xf1x\xad" + + "\xf3\xd0\x19\x1b\x8c\xbc\xa3H\x1e\xdc\xb86\xb4\x87\xb8i" + + "\xea\x9auq\xa3f\xdd\x994\xeb\x8d\x0c\xb9Yo_" + + "[\xa5'm\x03\xcar\x8d3n\x07\x19\x90M\xe5\xda" + + "d\xcf\xf6\x8a\xc1IW\xc6\xadP\x8aj\xbb\xb4\x9bv" + + "\xae\\\xb5\x05\x00\x99\xd29\x0a\x80\\Y\xe4\x01\x94\xb7" + + "\xea\xa6%\xab\xa1\xb3]z\x96\xa3W\x81\xcb*\xe9\x80" + + "\xe1\xd8\xb6\x84\xa2\x11\xc8\xeaL\x95\xbdtc\xa4~\xb3" + + "\xa6a \x9b\x866\x0c\x13\x01\xd8xu6\x0fm\xec" + + "b\xd8` \x12\x01\xe8\x05L7^0tw\xc6D" + + "^\xbe\xbc\xb5\x0c\xb9\xdb=\x98\xb8z0Y\x7f\xfeA" + + "o\xeeR\xa4\x95\xe8\xced\x8c*\x91\xd4\xb5\xbc\xdd\xb4" + + "eou\x16\xff\xe8v\xaf\x8bL\x02`\xc6\xb7\xb7d" + + "\xdfIGp\xe5A\x00q\x03G\xb1j\x0e\x1d\xa8\xf5" + + "\xfd\x00F\xedI2\xe9\xa7}_\xbf\xe8\xcdQ\x17\xc6" + + "\x8b^F\x90\x88\xea>\x8e\xe2\x16\x12\xa4%1\xff\x9b" + + "W_F\x90\xc2\xc8_\xfc\x98\xea\x9a\xe7D61\xec" + + "4:f\xf6$&2\xec\xac0\x1c\xbb\x18\xc8\x89@" + + "\x94\"s\x88\xb3\xd0\xa9\xc1\xbf\xc7QX5w\xa04" + + "L\x92$\x8b\xa3\x98\xa0\xe6\xb8\x90\x88\xcf8\x95\xc0\xe5" + + "(n#I:\x9f\x88\xcf$\xa5\x1cp\x14{X\xed" + + "\x1c\xd8\xe7@\xd9q\x87tc\xdb\xac\xf3\x1e\xf691" + + "\x92iJb\x8c\x90O\xbd\xb3A1\xe3a*\x98\x8e" + + "-rX\x7f\xa1\xc5eE\x1a/\xa1\xa5d\xef\xa24" + + "'8\x8a}\x0c\x91\xc5\xdb\xdc\xfb\x1b\x00\xb1\x8f\xa3\x98" + + "\xa6\xabG\xa2\xfeS\xf7\x03\x88i\x8e\xe2\x01j\x85\xe4" + + ">r\x1f\x1d\xbd\xef\xe6(\x1eb\xa8\xe4\x92\xfb\xc8\x83" + + "\xd7\x01\x88C\x1c\xc5#\x8cN%\xba\xef\xd8\xd8\x0a\x0c" + + "[\xebN\x02\xd8\xeb\xd3a_ze\x7f\x9d>n\x05" + + "i5\xd2\x80\x9eqO\x1f2-\x93\x07\x93\xb5\xcbE" + + "1\x98t%\x16\xb3\xfd\x00b\x11\xb0+\xf0tC\xa6" + + "K\xd4\xd5\xb3?1\xe5\xd8\x92\x01\"6\xd2K\xa2\x82" + + "\x8b\xf9&w\x8en\xaf5\xde\xca\x81\xc4\xfa\xfb\xe6\xea" + + "\xb1\xc0\xd3m\x7f\xab\xe3\x01\x8ee.\x9c.2\xc3\x85" + + "Y|'\\Q\xbb\x0dYE\xba\x0cQ\xf3GMF" + + "N\xb4\x96*\xb2*^1n\xb2<\x80\xd2\xbb!S" + + " \xba\xcd\xb0\xc8\x85\x14\xb1%\x1b\x81\xb2\x111\x0a\xf9" + + "p\xd2\x19\xf7|im%\x8b\xa8]\x0d\x807\xd6\xf7" + + "\xd5\xd1\xc9\xad\xe0\xe9\xee\xdc\xa3\x9f\x92q\xff\xe5&\xbf" + + "*]O\x1az\x80\xb2\xbaihT\x1a\x01\x813W" + + "\x9dU\x99\xc2\x8aM\xee\xcc\x83\xd8\xb2L\xd5\xea.u" + + "\xcb\xbf\x9fYL\xd1v\x1c\x17\xf2\xe1\xb0\x0c\xfa\x1d\xd3" + + "\x0ePz\xebLiU\xd3\xcbh\xfd6\xe3\xd1.\xd2" + + "l\xcf\xd8gw\xbd|b\xdd?H\x94\xe5\xab\x81\xcd" + + "y\xa6\x89Oc\x13\xc1%\xf7\xfd\x0d\x8ei\xff\xaf\xa7" + + "\xab\xd5\x99\xc2}\xb1\xd3\xd5\xeemr\x92\\\xa2\xc6\xf3" + + "\x7f\x03\x00\x00\xff\xff\x13\x1e\x1c\xb7" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_b312981b2552a250, + Nodes: []uint64{ + 0x836a53ce789d4cd4, + 0x8523ddc40b86b8b0, + 0x91b79f1f808db032, + 0x95bc14545813fbc1, + 0x9a0e61223d96743b, + 0x9c6a046bfbc1ac5a, + 0x9e19b28d3db3573a, + 0xad1a6c0d7dd07497, + 0xb28c96e23f4cbd58, + 0xbbc29655fa89086e, + 0xd37007fde1f0027d, + 0xd37d2eb2c2f80e63, + 0xd4c9b56290554016, + 0xd562b4df655bdd4d, + 0xd625b7063acf691a, + 0xd800b1d6cd6f1ca0, + 0xdae8b0f61aab5f99, + 0xe94ccf8031176ec4, + 0xf316944415569081, + 0xf964368b0fbd3711, + 0xfbe1980490e001af, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/std/capnp/rpctwoparty/rpc-twoparty.capnp.go b/crates/turborepo-lib/Source/hash/std/capnp/rpctwoparty/rpc-twoparty.capnp.go new file mode 100644 index 0000000000000..92ebcd40613ac --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/rpctwoparty/rpc-twoparty.capnp.go @@ -0,0 +1,560 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package rpctwoparty + +import ( + capnp "capnproto.org/go/capnp/v3" + text "capnproto.org/go/capnp/v3/encoding/text" + schemas "capnproto.org/go/capnp/v3/schemas" +) + +type Side uint16 + +// Side_TypeID is the unique identifier for the type Side. +const Side_TypeID = 0x9fd69ebc87b9719c + +// Values of Side. +const ( + Side_server Side = 0 + Side_client Side = 1 +) + +// String returns the enum's constant name. +func (c Side) String() string { + switch c { + case Side_server: + return "server" + case Side_client: + return "client" + + default: + return "" + } +} + +// SideFromString returns the enum value with a name, +// or the zero value if there's no such value. +func SideFromString(c string) Side { + switch c { + case "server": + return Side_server + case "client": + return Side_client + + default: + return 0 + } +} + +type Side_List = capnp.EnumList[Side] + +func NewSide_List(s *capnp.Segment, sz int32) (Side_List, error) { + return capnp.NewEnumList[Side](s, sz) +} + +type VatId capnp.Struct + +// VatId_TypeID is the unique identifier for the type VatId. +const VatId_TypeID = 0xd20b909fee733a8e + +func NewVatId(s *capnp.Segment) (VatId, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return VatId(st), err +} + +func NewRootVatId(s *capnp.Segment) (VatId, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return VatId(st), err +} + +func ReadRootVatId(msg *capnp.Message) (VatId, error) { + root, err := msg.Root() + return VatId(root.Struct()), err +} + +func (s VatId) String() string { + str, _ := text.Marshal(0xd20b909fee733a8e, capnp.Struct(s)) + return str +} + +func (s VatId) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (VatId) DecodeFromPtr(p capnp.Ptr) VatId { + return VatId(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s VatId) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s VatId) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s VatId) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s VatId) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s VatId) Side() Side { + return Side(capnp.Struct(s).Uint16(0)) +} + +func (s VatId) SetSide(v Side) { + capnp.Struct(s).SetUint16(0, uint16(v)) +} + +// VatId_List is a list of VatId. +type VatId_List = capnp.StructList[VatId] + +// NewVatId creates a new list of VatId. +func NewVatId_List(s *capnp.Segment, sz int32) (VatId_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[VatId](l), err +} + +// VatId_Future is a wrapper for a VatId promised by a client call. +type VatId_Future struct{ *capnp.Future } + +func (f VatId_Future) Struct() (VatId, error) { + p, err := f.Future.Ptr() + return VatId(p.Struct()), err +} + +type ProvisionId capnp.Struct + +// ProvisionId_TypeID is the unique identifier for the type ProvisionId. +const ProvisionId_TypeID = 0xb88d09a9c5f39817 + +func NewProvisionId(s *capnp.Segment) (ProvisionId, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return ProvisionId(st), err +} + +func NewRootProvisionId(s *capnp.Segment) (ProvisionId, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return ProvisionId(st), err +} + +func ReadRootProvisionId(msg *capnp.Message) (ProvisionId, error) { + root, err := msg.Root() + return ProvisionId(root.Struct()), err +} + +func (s ProvisionId) String() string { + str, _ := text.Marshal(0xb88d09a9c5f39817, capnp.Struct(s)) + return str +} + +func (s ProvisionId) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (ProvisionId) DecodeFromPtr(p capnp.Ptr) ProvisionId { + return ProvisionId(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s ProvisionId) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s ProvisionId) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s ProvisionId) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s ProvisionId) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s ProvisionId) JoinId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s ProvisionId) SetJoinId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +// ProvisionId_List is a list of ProvisionId. +type ProvisionId_List = capnp.StructList[ProvisionId] + +// NewProvisionId creates a new list of ProvisionId. +func NewProvisionId_List(s *capnp.Segment, sz int32) (ProvisionId_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[ProvisionId](l), err +} + +// ProvisionId_Future is a wrapper for a ProvisionId promised by a client call. +type ProvisionId_Future struct{ *capnp.Future } + +func (f ProvisionId_Future) Struct() (ProvisionId, error) { + p, err := f.Future.Ptr() + return ProvisionId(p.Struct()), err +} + +type RecipientId capnp.Struct + +// RecipientId_TypeID is the unique identifier for the type RecipientId. +const RecipientId_TypeID = 0x89f389b6fd4082c1 + +func NewRecipientId(s *capnp.Segment) (RecipientId, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return RecipientId(st), err +} + +func NewRootRecipientId(s *capnp.Segment) (RecipientId, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return RecipientId(st), err +} + +func ReadRootRecipientId(msg *capnp.Message) (RecipientId, error) { + root, err := msg.Root() + return RecipientId(root.Struct()), err +} + +func (s RecipientId) String() string { + str, _ := text.Marshal(0x89f389b6fd4082c1, capnp.Struct(s)) + return str +} + +func (s RecipientId) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (RecipientId) DecodeFromPtr(p capnp.Ptr) RecipientId { + return RecipientId(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s RecipientId) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s RecipientId) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s RecipientId) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s RecipientId) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} + +// RecipientId_List is a list of RecipientId. +type RecipientId_List = capnp.StructList[RecipientId] + +// NewRecipientId creates a new list of RecipientId. +func NewRecipientId_List(s *capnp.Segment, sz int32) (RecipientId_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) + return capnp.StructList[RecipientId](l), err +} + +// RecipientId_Future is a wrapper for a RecipientId promised by a client call. +type RecipientId_Future struct{ *capnp.Future } + +func (f RecipientId_Future) Struct() (RecipientId, error) { + p, err := f.Future.Ptr() + return RecipientId(p.Struct()), err +} + +type ThirdPartyCapId capnp.Struct + +// ThirdPartyCapId_TypeID is the unique identifier for the type ThirdPartyCapId. +const ThirdPartyCapId_TypeID = 0xb47f4979672cb59d + +func NewThirdPartyCapId(s *capnp.Segment) (ThirdPartyCapId, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return ThirdPartyCapId(st), err +} + +func NewRootThirdPartyCapId(s *capnp.Segment) (ThirdPartyCapId, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return ThirdPartyCapId(st), err +} + +func ReadRootThirdPartyCapId(msg *capnp.Message) (ThirdPartyCapId, error) { + root, err := msg.Root() + return ThirdPartyCapId(root.Struct()), err +} + +func (s ThirdPartyCapId) String() string { + str, _ := text.Marshal(0xb47f4979672cb59d, capnp.Struct(s)) + return str +} + +func (s ThirdPartyCapId) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (ThirdPartyCapId) DecodeFromPtr(p capnp.Ptr) ThirdPartyCapId { + return ThirdPartyCapId(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s ThirdPartyCapId) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s ThirdPartyCapId) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s ThirdPartyCapId) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s ThirdPartyCapId) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} + +// ThirdPartyCapId_List is a list of ThirdPartyCapId. +type ThirdPartyCapId_List = capnp.StructList[ThirdPartyCapId] + +// NewThirdPartyCapId creates a new list of ThirdPartyCapId. +func NewThirdPartyCapId_List(s *capnp.Segment, sz int32) (ThirdPartyCapId_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) + return capnp.StructList[ThirdPartyCapId](l), err +} + +// ThirdPartyCapId_Future is a wrapper for a ThirdPartyCapId promised by a client call. +type ThirdPartyCapId_Future struct{ *capnp.Future } + +func (f ThirdPartyCapId_Future) Struct() (ThirdPartyCapId, error) { + p, err := f.Future.Ptr() + return ThirdPartyCapId(p.Struct()), err +} + +type JoinKeyPart capnp.Struct + +// JoinKeyPart_TypeID is the unique identifier for the type JoinKeyPart. +const JoinKeyPart_TypeID = 0x95b29059097fca83 + +func NewJoinKeyPart(s *capnp.Segment) (JoinKeyPart, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return JoinKeyPart(st), err +} + +func NewRootJoinKeyPart(s *capnp.Segment) (JoinKeyPart, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return JoinKeyPart(st), err +} + +func ReadRootJoinKeyPart(msg *capnp.Message) (JoinKeyPart, error) { + root, err := msg.Root() + return JoinKeyPart(root.Struct()), err +} + +func (s JoinKeyPart) String() string { + str, _ := text.Marshal(0x95b29059097fca83, capnp.Struct(s)) + return str +} + +func (s JoinKeyPart) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (JoinKeyPart) DecodeFromPtr(p capnp.Ptr) JoinKeyPart { + return JoinKeyPart(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s JoinKeyPart) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s JoinKeyPart) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s JoinKeyPart) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s JoinKeyPart) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s JoinKeyPart) JoinId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s JoinKeyPart) SetJoinId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s JoinKeyPart) PartCount() uint16 { + return capnp.Struct(s).Uint16(4) +} + +func (s JoinKeyPart) SetPartCount(v uint16) { + capnp.Struct(s).SetUint16(4, v) +} + +func (s JoinKeyPart) PartNum() uint16 { + return capnp.Struct(s).Uint16(6) +} + +func (s JoinKeyPart) SetPartNum(v uint16) { + capnp.Struct(s).SetUint16(6, v) +} + +// JoinKeyPart_List is a list of JoinKeyPart. +type JoinKeyPart_List = capnp.StructList[JoinKeyPart] + +// NewJoinKeyPart creates a new list of JoinKeyPart. +func NewJoinKeyPart_List(s *capnp.Segment, sz int32) (JoinKeyPart_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[JoinKeyPart](l), err +} + +// JoinKeyPart_Future is a wrapper for a JoinKeyPart promised by a client call. +type JoinKeyPart_Future struct{ *capnp.Future } + +func (f JoinKeyPart_Future) Struct() (JoinKeyPart, error) { + p, err := f.Future.Ptr() + return JoinKeyPart(p.Struct()), err +} + +type JoinResult capnp.Struct + +// JoinResult_TypeID is the unique identifier for the type JoinResult. +const JoinResult_TypeID = 0x9d263a3630b7ebee + +func NewJoinResult(s *capnp.Segment) (JoinResult, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return JoinResult(st), err +} + +func NewRootJoinResult(s *capnp.Segment) (JoinResult, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return JoinResult(st), err +} + +func ReadRootJoinResult(msg *capnp.Message) (JoinResult, error) { + root, err := msg.Root() + return JoinResult(root.Struct()), err +} + +func (s JoinResult) String() string { + str, _ := text.Marshal(0x9d263a3630b7ebee, capnp.Struct(s)) + return str +} + +func (s JoinResult) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (JoinResult) DecodeFromPtr(p capnp.Ptr) JoinResult { + return JoinResult(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s JoinResult) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s JoinResult) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s JoinResult) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s JoinResult) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s JoinResult) JoinId() uint32 { + return capnp.Struct(s).Uint32(0) +} + +func (s JoinResult) SetJoinId(v uint32) { + capnp.Struct(s).SetUint32(0, v) +} + +func (s JoinResult) Succeeded() bool { + return capnp.Struct(s).Bit(32) +} + +func (s JoinResult) SetSucceeded(v bool) { + capnp.Struct(s).SetBit(32, v) +} + +func (s JoinResult) Cap() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) +} + +func (s JoinResult) HasCap() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s JoinResult) SetCap(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} + +// JoinResult_List is a list of JoinResult. +type JoinResult_List = capnp.StructList[JoinResult] + +// NewJoinResult creates a new list of JoinResult. +func NewJoinResult_List(s *capnp.Segment, sz int32) (JoinResult_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[JoinResult](l), err +} + +// JoinResult_Future is a wrapper for a JoinResult promised by a client call. +type JoinResult_Future struct{ *capnp.Future } + +func (f JoinResult_Future) Struct() (JoinResult, error) { + p, err := f.Future.Ptr() + return JoinResult(p.Struct()), err +} +func (p JoinResult_Future) Cap() *capnp.Future { + return p.Future.Field(0, nil) +} + +const schema_a184c7885cdaf2a1 = "x\xda|\x92\xcfk\xd4@\x14\xc7\xdfw&u\xb7\xe8" + + "\xb2\xa4\xb3\"zQ\x04=\x88J\x8b\xa2\x90K\x16\x17" + + "\xc1h\x91\x9d\xb5\x15\x0b\xf6\x10\x92\xa0\x916I\x93l" + + "e\x0f\xb2\xa0\x82\xf6\xa0\xf4\"x\xb0\x96\x1e=\x89\xe2" + + "\xaf\x82\x1e\x14D\xe8\xd1\x83\x07\xff\x05\xa1\x87\xf6\xb6 " + + "\x91\x09\xd8\x95\xfd\xe1m\xe6\xf1y_>\xef\xcd\x8c\x9b" + + "\xa8j\x13\xa5\xb6FL\x9e\x1e\xd9\x95}\xbe[\xfd\xfd" + + "ni{\x89t\x81lm\xeb\xe7\xf5\x87\xdf\xee\xaf\x91" + + "V \x12GXGL\xb0\x02\xf1\xec\xdeF{tf" + + "\xf9\xf5\x13\x92\x02\xbdT\x89u\xc4~\xa6N{\xd9K" + + "B\xb6\xf9\xeb\xfd\xf8\x19\xe3\xe8J\x0f;\x02\x85\xbcb" + + "[\xe2S\x0e\xaf\xe7\xf0\xb3\x85\xf5\x07\x1f\x9f\xffX%" + + "]\xb0.K\x10\xd3\xfc\x8b\x98\xe5\x0a\x9c\xe1g\x09\xd9" + + "\xca\xdb\xe37ZV\xfbM\xbf\xe6\xa9Y~\x00b\x9e" + + "+\xcf}O\xb7\xbf\xbe\x18}\xf4a\x90\xa7\xc5;b" + + ":O\x94\xdc$d\x8f\x8ddsuy\xf7\xf7A\xec" + + "\x02\xdf\x10wr\xb6\xc5M\xaaeq\xe4\x9cHo\x87" + + "\x11\xb3\xe3\xb4u\xd2\xb1\xa3 2\x1a\x9e\xe3G\xa6\xef" + + "\x05\xa9\xe5\xd6\x81\x81\xcc\xc5\xd0\x0f.\x99^\xabn\xc7" + + "i\x1d\x90{\xb8F\xa4\x81H?o\x10\xc9*\x87\x9c" + + "d\xd0\xc1*PE\xabA$/p\xc8)\x06\x9d\xf1" + + "\x0a\x18\x91.\xcf\x11\xc9I\x0ey\x8d\xc1\xbc\x15\xfa\x81" + + "\xe5\xa2H\x0cEB\x16\xd9qZ\x0b\x9b\x01!E\x81" + + "\x18\x0a\x84\xb6\xaa]n\xce\xff\xbd\x0f\xf5j\x1c\xf4\x92" + + "\xe6\xdc\x7f\xb5\x0e\xf5k)\xd5\xdc\xea\xf0p\xab\xa4\xe9" + + "8\x9e\xe7z\x04\x17 \x06\x10\x0a\x8e\x1da\x8c\x18\xc6" + + "\x86\x18]\xf1]\x8f\x94K1\x8f\xd7\x0d\"@\x1f5" + + "\x88\xcc\xc4\x8b\x17\xbd\xd8t\xe6\xd4\xaew\x9a\xf9?\xcd" + + "S7\xfd\xd8U;n\xd5\xec\x88\x0f\x7f\x8ez\x1c." + + "\xfaf\xe2\x87A\xceHmg\xee\x92\x9a\xbb\xc8!+" + + "\xfd\xe3\x0cJ\xbaj\xa7\x96K\xd4\x13r\xac\x1bRN" + + "|\xd7C\xb9\xfb\xc1\x09(\x13\xfe\x04\x00\x00\xff\xff[" + + "\xb7\xf3\xb7" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_a184c7885cdaf2a1, + Nodes: []uint64{ + 0x89f389b6fd4082c1, + 0x95b29059097fca83, + 0x9d263a3630b7ebee, + 0x9fd69ebc87b9719c, + 0xb47f4979672cb59d, + 0xb88d09a9c5f39817, + 0xd20b909fee733a8e, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/std/capnp/schema.capnp b/crates/turborepo-lib/Source/hash/std/capnp/schema.capnp new file mode 100644 index 0000000000000..f7bdee5b1a9e3 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/schema.capnp @@ -0,0 +1,545 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +using Cxx = import "/capnp/c++.capnp"; + +@0xa93fc509624c72d9; +$Cxx.namespace("capnp::schema"); + +using Id = UInt64; +# The globally-unique ID of a file, type, or annotation. + +struct Node { + id @0 :Id; + + displayName @1 :Text; + # Name to present to humans to identify this Node. You should not attempt to parse this. Its + # format could change. It is not guaranteed to be unique. + # + # (On Zooko's triangle, this is the node's nickname.) + + displayNamePrefixLength @2 :UInt32; + # If you want a shorter version of `displayName` (just naming this node, without its surrounding + # scope), chop off this many characters from the beginning of `displayName`. + + scopeId @3 :Id; + # ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back + # at this node, but robust code should avoid relying on this (and, in fact, group nodes are not + # listed in the outer struct's nestedNodes, since they are listed in the fields). `scopeId` is + # zero if the node has no parent, which is normally only the case with files, but should be + # allowed for any kind of node (in order to make runtime type generation easier). + + parameters @32 :List(Parameter); + # If this node is parameterized (generic), the list of parameters. Empty for non-generic types. + + isGeneric @33 :Bool; + # True if this node is generic, meaning that it or one of its parent scopes has a non-empty + # `parameters`. + + struct Parameter { + # Information about one of the node's parameters. + + name @0 :Text; + } + + nestedNodes @4 :List(NestedNode); + # List of nodes nested within this node, along with the names under which they were declared. + + struct NestedNode { + name @0 :Text; + # Unqualified symbol name. Unlike Node.displayName, this *can* be used programmatically. + # + # (On Zooko's triangle, this is the node's petname according to its parent scope.) + + id @1 :Id; + # ID of the nested node. Typically, the target node's scopeId points back to this node, but + # robust code should avoid relying on this. + } + + annotations @5 :List(Annotation); + # Annotations applied to this node. + + union { + # Info specific to each kind of node. + + file @6 :Void; + + struct :group $Go.name("structNode") { + dataWordCount @7 :UInt16; + # Size of the data section, in words. + + pointerCount @8 :UInt16; + # Size of the pointer section, in pointers (which are one word each). + + preferredListEncoding @9 :ElementSize; + # The preferred element size to use when encoding a list of this struct. If this is anything + # other than `inlineComposite` then the struct is one word or less in size and is a candidate + # for list packing optimization. + + isGroup @10 :Bool; + # If true, then this "struct" node is actually not an independent node, but merely represents + # some named union or group within a particular parent struct. This node's scopeId refers + # to the parent struct, which may itself be a union/group in yet another struct. + # + # All group nodes share the same dataWordCount and pointerCount as the top-level + # struct, and their fields live in the same ordinal and offset spaces as all other fields in + # the struct. + # + # Note that a named union is considered a special kind of group -- in fact, a named union + # is exactly equivalent to a group that contains nothing but an unnamed union. + + discriminantCount @11 :UInt16; + # Number of fields in this struct which are members of an anonymous union, and thus may + # overlap. If this is non-zero, then a 16-bit discriminant is present indicating which + # of the overlapping fields is active. This can never be 1 -- if it is non-zero, it must be + # two or more. + # + # Note that the fields of an unnamed union are considered fields of the scope containing the + # union -- an unnamed union is not its own group. So, a top-level struct may contain a + # non-zero discriminant count. Named unions, on the other hand, are equivalent to groups + # containing unnamed unions. So, a named union has its own independent schema node, with + # `isGroup` = true. + + discriminantOffset @12 :UInt32; + # If `discriminantCount` is non-zero, this is the offset of the union discriminant, in + # multiples of 16 bits. + + fields @13 :List(Field); + # Fields defined within this scope (either the struct's top-level fields, or the fields of + # a particular group; see `isGroup`). + # + # The fields are sorted by ordinal number, but note that because groups share the same + # ordinal space, the field's index in this list is not necessarily exactly its ordinal. + # On the other hand, the field's position in this list does remain the same even as the + # protocol evolves, since it is not possible to insert or remove an earlier ordinal. + # Therefore, for most use cases, if you want to identify a field by number, it may make the + # most sense to use the field's index in this list rather than its ordinal. + } + + enum :group { + enumerants@14 :List(Enumerant); + # Enumerants ordered by numeric value (ordinal). + } + + interface :group { + methods @15 :List(Method); + # Methods ordered by ordinal. + + superclasses @31 :List(Superclass); + # Superclasses of this interface. + } + + const :group { + type @16 :Type; + value @17 :Value; + } + + annotation :group { + type @18 :Type; + + targetsFile @19 :Bool; + targetsConst @20 :Bool; + targetsEnum @21 :Bool; + targetsEnumerant @22 :Bool; + targetsStruct @23 :Bool; + targetsField @24 :Bool; + targetsUnion @25 :Bool; + targetsGroup @26 :Bool; + targetsInterface @27 :Bool; + targetsMethod @28 :Bool; + targetsParam @29 :Bool; + targetsAnnotation @30 :Bool; + } + } + + struct SourceInfo { + # Additional information about a node which is not needed at runtime, but may be useful for + # documentation or debugging purposes. This is kept in a separate struct to make sure it + # doesn't accidentally get included in contexts where it is not needed. The + # `CodeGeneratorRequest` includes this information in a separate array. + + id @0 :Id; + # ID of the Node which this info describes. + + docComment @1 :Text; + # The top-level doc comment for the Node. + + members @2 :List(Member); + # Information about each member -- i.e. fields (for structs), enumerants (for enums), or + # methods (for interfaces). + # + # This list is the same length and order as the corresponding list in the Node, i.e. + # Node.struct.fields, Node.enum.enumerants, or Node.interface.methods. + + struct Member { + docComment @0 :Text; + # Doc comment on the member. + } + + # TODO(someday): Record location of the declaration in the original source code. + } +} + +struct Field { + # Schema for a field of a struct. + + name @0 :Text; + + codeOrder @1 :UInt16; + # Indicates where this member appeared in the code, relative to other members. + # Code ordering may have semantic relevance -- programmers tend to place related fields + # together. So, using code ordering makes sense in human-readable formats where ordering is + # otherwise irrelevant, like JSON. The values of codeOrder are tightly-packed, so the maximum + # value is count(members) - 1. Fields that are members of a union are only ordered relative to + # the other members of that union, so the maximum value there is count(union.members). + + annotations @2 :List(Annotation); + + const noDiscriminant :UInt16 = 0xffff; + + discriminantValue @3 :UInt16 = Field.noDiscriminant; + # If the field is in a union, this is the value which the union's discriminant should take when + # the field is active. If the field is not in a union, this is 0xffff. + + union { + slot :group { + # A regular, non-group, non-fixed-list field. + + offset @4 :UInt32; + # Offset, in units of the field's size, from the beginning of the section in which the field + # resides. E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the + # beginning of the data section. + + type @5 :Type; + defaultValue @6 :Value; + + hadExplicitDefault @10 :Bool; + # Whether the default value was specified explicitly. Non-explicit default values are always + # zero or empty values. Usually, whether the default value was explicit shouldn't matter. + # The main use case for this flag is for structs representing method parameters: + # explicitly-defaulted parameters may be allowed to be omitted when calling the method. + } + + group :group { + # A group. + + typeId @7 :Id; + # The ID of the group's node. + } + } + + ordinal :union { + implicit @8 :Void; + explicit @9 :UInt16; + # The original ordinal number given to the field. You probably should NOT use this; if you need + # a numeric identifier for a field, use its position within the field array for its scope. + # The ordinal is given here mainly just so that the original schema text can be reproduced given + # the compiled version -- i.e. so that `capnp compile -ocapnp` can do its job. + } +} + +struct Enumerant { + # Schema for member of an enum. + + name @0 :Text; + + codeOrder @1 :UInt16; + # Specifies order in which the enumerants were declared in the code. + # Like Struct.Field.codeOrder. + + annotations @2 :List(Annotation); +} + +struct Superclass { + id @0 :Id; + brand @1 :Brand; +} + +struct Method { + # Schema for method of an interface. + + name @0 :Text; + + codeOrder @1 :UInt16; + # Specifies order in which the methods were declared in the code. + # Like Struct.Field.codeOrder. + + implicitParameters @7 :List(Node.Parameter); + # The parameters listed in [] (typically, type / generic parameters), whose bindings are intended + # to be inferred rather than specified explicitly, although not all languages support this. + + paramStructType @2 :Id; + # ID of the parameter struct type. If a named parameter list was specified in the method + # declaration (rather than a single struct parameter type) then a corresponding struct type is + # auto-generated. Such an auto-generated type will not be listed in the interface's + # `nestedNodes` and its `scopeId` will be zero -- it is completely detached from the namespace. + # (Awkwardly, it does of course inherit generic parameters from the method's scope, which makes + # this a situation where you can't just climb the scope chain to find where a particular + # generic parameter was introduced. Making the `scopeId` zero was a mistake.) + + paramBrand @5 :Brand; + # Brand of param struct type. + + resultStructType @3 :Id; + # ID of the return struct type; similar to `paramStructType`. + + resultBrand @6 :Brand; + # Brand of result struct type. + + annotations @4 :List(Annotation); +} + +struct Type { + # Represents a type expression. + + union { + # The ordinals intentionally match those of Value. + + void @0 :Void; + bool @1 :Void; + int8 @2 :Void; + int16 @3 :Void; + int32 @4 :Void; + int64 @5 :Void; + uint8 @6 :Void; + uint16 @7 :Void; + uint32 @8 :Void; + uint64 @9 :Void; + float32 @10 :Void; + float64 @11 :Void; + text @12 :Void; + data @13 :Void; + + list :group { + elementType @14 :Type; + } + + enum :group { + typeId @15 :Id; + brand @21 :Brand; + } + struct :group $Go.name("structType") { + typeId @16 :Id; + brand @22 :Brand; + } + interface :group { + typeId @17 :Id; + brand @23 :Brand; + } + + anyPointer :union { + unconstrained :union { + # A regular AnyPointer. + # + # The name "unconstrained" means as opposed to constraining it to match a type parameter. + # In retrospect this name is probably a poor choice given that it may still be constrained + # to be a struct, list, or capability. + + anyKind @18 :Void; # truly AnyPointer + struct @25 :Void; # AnyStruct + list @26 :Void; # AnyList + capability @27 :Void; # Capability + } + + parameter :group { + # This is actually a reference to a type parameter defined within this scope. + + scopeId @19 :Id; + # ID of the generic type whose parameter we're referencing. This should be a parent of the + # current scope. + + parameterIndex @20 :UInt16; + # Index of the parameter within the generic type's parameter list. + } + + implicitMethodParameter :group { + # This is actually a reference to an implicit (generic) parameter of a method. The only + # legal context for this type to appear is inside Method.paramBrand or Method.resultBrand. + + parameterIndex @24 :UInt16; + } + } + } +} + +struct Brand { + # Specifies bindings for parameters of generics. Since these bindings turn a generic into a + # non-generic, we call it the "brand". + + scopes @0 :List(Scope); + # For each of the target type and each of its parent scopes, a parameterization may be included + # in this list. If no parameterization is included for a particular relevant scope, then either + # that scope has no parameters or all parameters should be considered to be `AnyPointer`. + + struct Scope { + scopeId @0 :Id; + # ID of the scope to which these params apply. + + union { + bind @1 :List(Binding); + # List of parameter bindings. + + inherit @2 :Void; + # The place where the Brand appears is within this scope or a sub-scope, and bindings + # for this scope are deferred to later Brand applications. This is equivalent to a + # pass-through binding list, where each of this scope's parameters is bound to itself. + # For example: + # + # struct Outer(T) { + # struct Inner { + # value @0 :T; + # } + # innerInherit @0 :Inner; # Outer Brand.Scope is `inherit`. + # innerBindSelf @1 :Outer(T).Inner; # Outer Brand.Scope explicitly binds T to T. + # } + # + # The innerInherit and innerBindSelf fields have equivalent types, but different Brand + # styles. + } + } + + struct Binding { + union { + unbound @0 :Void; + type @1 :Type; + + # TODO(someday): Allow non-type parameters? Unsure if useful. + } + } +} + +struct Value { + # Represents a value, e.g. a field default value, constant value, or annotation value. + + union { + # The ordinals intentionally match those of Type. + + void @0 :Void; + bool @1 :Bool; + int8 @2 :Int8; + int16 @3 :Int16; + int32 @4 :Int32; + int64 @5 :Int64; + uint8 @6 :UInt8; + uint16 @7 :UInt16; + uint32 @8 :UInt32; + uint64 @9 :UInt64; + float32 @10 :Float32; + float64 @11 :Float64; + text @12 :Text; + data @13 :Data; + + list @14 :AnyPointer; + + enum @15 :UInt16; + struct @16 :AnyPointer $Go.name("structValue"); + + interface @17 :Void; + # The only interface value that can be represented statically is "null", whose methods always + # throw exceptions. + + anyPointer @18 :AnyPointer; + } +} + +struct Annotation { + # Describes an annotation applied to a declaration. Note AnnotationNode describes the + # annotation's declaration, while this describes a use of the annotation. + + id @0 :Id; + # ID of the annotation node. + + brand @2 :Brand; + # Brand of the annotation. + # + # Note that the annotation itself is not allowed to be parameterized, but its scope might be. + + value @1 :Value; +} + +enum ElementSize { + # Possible element sizes for encoded lists. These correspond exactly to the possible values of + # the 3-bit element size component of a list pointer. + + empty @0; # aka "void", but that's a keyword. + bit @1; + byte @2; + twoBytes @3; + fourBytes @4; + eightBytes @5; + pointer @6; + inlineComposite @7; +} + +struct CapnpVersion { + major @0 :UInt16; + minor @1 :UInt8; + micro @2 :UInt8; +} + +struct CodeGeneratorRequest { + capnpVersion @2 :CapnpVersion; + # Version of the `capnp` executable. Generally, code generators should ignore this, but the code + # generators that ship with `capnp` itself will print a warning if this mismatches since that + # probably indicates something is misconfigured. + # + # The first version of 'capnp' to set this was 0.6.0. So, if it's missing, the compiler version + # is older than that. + + nodes @0 :List(Node); + # All nodes parsed by the compiler, including for the files on the command line and their + # imports. + + sourceInfo @3 :List(Node.SourceInfo); + # Information about the original source code for each node, where available. This array may be + # omitted or may be missing some nodes if no info is available for them. + + requestedFiles @1 :List(RequestedFile); + # Files which were listed on the command line. + + struct RequestedFile { + id @0 :Id; + # ID of the file. + + filename @1 :Text; + # Name of the file as it appeared on the command-line (minus the src-prefix). You may use + # this to decide where to write the output. + + imports @2 :List(Import); + # List of all imported paths seen in this file. + + struct Import { + id @0 :Id; + # ID of the imported file. + + name @1 :Text; + # Name which *this* file used to refer to the foreign file. This may be a relative name. + # This information is provided because it might be useful for code generation, e.g. to + # generate #include directives in C++. We don't put this in Node.file because this + # information is only meaningful at compile time anyway. + # + # (On Zooko's triangle, this is the import's petname according to the importing file.) + } + } +} +using Go = import "/go.capnp"; +$Go.package("schema"); +$Go.import("capnproto.org/go/capnp/v3/std/capnp/schema"); diff --git a/crates/turborepo-lib/Source/hash/std/capnp/schema/schema.capnp.go b/crates/turborepo-lib/Source/hash/std/capnp/schema/schema.capnp.go new file mode 100644 index 0000000000000..1ce378117834f --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/schema/schema.capnp.go @@ -0,0 +1,4193 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package schema + +import ( + capnp "capnproto.org/go/capnp/v3" + text "capnproto.org/go/capnp/v3/encoding/text" + schemas "capnproto.org/go/capnp/v3/schemas" + math "math" + strconv "strconv" +) + +// Constants defined in schema.capnp. +const ( + Field_noDiscriminant = uint16(65535) +) + +type Node capnp.Struct +type Node_structNode Node +type Node_enum Node +type Node_interface Node +type Node_const Node +type Node_annotation Node +type Node_Which uint16 + +const ( + Node_Which_file Node_Which = 0 + Node_Which_structNode Node_Which = 1 + Node_Which_enum Node_Which = 2 + Node_Which_interface Node_Which = 3 + Node_Which_const Node_Which = 4 + Node_Which_annotation Node_Which = 5 +) + +func (w Node_Which) String() string { + const s = "filestructNodeenuminterfaceconstannotation" + switch w { + case Node_Which_file: + return s[0:4] + case Node_Which_structNode: + return s[4:14] + case Node_Which_enum: + return s[14:18] + case Node_Which_interface: + return s[18:27] + case Node_Which_const: + return s[27:32] + case Node_Which_annotation: + return s[32:42] + + } + return "Node_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Node_TypeID is the unique identifier for the type Node. +const Node_TypeID = 0xe682ab4cf923a417 + +func NewNode(s *capnp.Segment) (Node, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 40, PointerCount: 6}) + return Node(st), err +} + +func NewRootNode(s *capnp.Segment) (Node, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 40, PointerCount: 6}) + return Node(st), err +} + +func ReadRootNode(msg *capnp.Message) (Node, error) { + root, err := msg.Root() + return Node(root.Struct()), err +} + +func (s Node) String() string { + str, _ := text.Marshal(0xe682ab4cf923a417, capnp.Struct(s)) + return str +} + +func (s Node) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Node) DecodeFromPtr(p capnp.Ptr) Node { + return Node(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Node) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Node) Which() Node_Which { + return Node_Which(capnp.Struct(s).Uint16(12)) +} +func (s Node) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node) Id() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s Node) SetId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +func (s Node) DisplayName() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Node) HasDisplayName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Node) DisplayNameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Node) SetDisplayName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Node) DisplayNamePrefixLength() uint32 { + return capnp.Struct(s).Uint32(8) +} + +func (s Node) SetDisplayNamePrefixLength(v uint32) { + capnp.Struct(s).SetUint32(8, v) +} + +func (s Node) ScopeId() uint64 { + return capnp.Struct(s).Uint64(16) +} + +func (s Node) SetScopeId(v uint64) { + capnp.Struct(s).SetUint64(16, v) +} + +func (s Node) Parameters() (Node_Parameter_List, error) { + p, err := capnp.Struct(s).Ptr(5) + return Node_Parameter_List(p.List()), err +} + +func (s Node) HasParameters() bool { + return capnp.Struct(s).HasPtr(5) +} + +func (s Node) SetParameters(v Node_Parameter_List) error { + return capnp.Struct(s).SetPtr(5, v.ToPtr()) +} + +// NewParameters sets the parameters field to a newly +// allocated Node_Parameter_List, preferring placement in s's segment. +func (s Node) NewParameters(n int32) (Node_Parameter_List, error) { + l, err := NewNode_Parameter_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Node_Parameter_List{}, err + } + err = capnp.Struct(s).SetPtr(5, l.ToPtr()) + return l, err +} +func (s Node) IsGeneric() bool { + return capnp.Struct(s).Bit(288) +} + +func (s Node) SetIsGeneric(v bool) { + capnp.Struct(s).SetBit(288, v) +} + +func (s Node) NestedNodes() (Node_NestedNode_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return Node_NestedNode_List(p.List()), err +} + +func (s Node) HasNestedNodes() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Node) SetNestedNodes(v Node_NestedNode_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewNestedNodes sets the nestedNodes field to a newly +// allocated Node_NestedNode_List, preferring placement in s's segment. +func (s Node) NewNestedNodes(n int32) (Node_NestedNode_List, error) { + l, err := NewNode_NestedNode_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Node_NestedNode_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} +func (s Node) Annotations() (Annotation_List, error) { + p, err := capnp.Struct(s).Ptr(2) + return Annotation_List(p.List()), err +} + +func (s Node) HasAnnotations() bool { + return capnp.Struct(s).HasPtr(2) +} + +func (s Node) SetAnnotations(v Annotation_List) error { + return capnp.Struct(s).SetPtr(2, v.ToPtr()) +} + +// NewAnnotations sets the annotations field to a newly +// allocated Annotation_List, preferring placement in s's segment. +func (s Node) NewAnnotations(n int32) (Annotation_List, error) { + l, err := NewAnnotation_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Annotation_List{}, err + } + err = capnp.Struct(s).SetPtr(2, l.ToPtr()) + return l, err +} +func (s Node) SetFile() { + capnp.Struct(s).SetUint16(12, 0) + +} + +func (s Node) StructNode() Node_structNode { return Node_structNode(s) } + +func (s Node) SetStructNode() { + capnp.Struct(s).SetUint16(12, 1) +} + +func (s Node_structNode) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_structNode) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_structNode) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_structNode) DataWordCount() uint16 { + return capnp.Struct(s).Uint16(14) +} + +func (s Node_structNode) SetDataWordCount(v uint16) { + capnp.Struct(s).SetUint16(14, v) +} + +func (s Node_structNode) PointerCount() uint16 { + return capnp.Struct(s).Uint16(24) +} + +func (s Node_structNode) SetPointerCount(v uint16) { + capnp.Struct(s).SetUint16(24, v) +} + +func (s Node_structNode) PreferredListEncoding() ElementSize { + return ElementSize(capnp.Struct(s).Uint16(26)) +} + +func (s Node_structNode) SetPreferredListEncoding(v ElementSize) { + capnp.Struct(s).SetUint16(26, uint16(v)) +} + +func (s Node_structNode) IsGroup() bool { + return capnp.Struct(s).Bit(224) +} + +func (s Node_structNode) SetIsGroup(v bool) { + capnp.Struct(s).SetBit(224, v) +} + +func (s Node_structNode) DiscriminantCount() uint16 { + return capnp.Struct(s).Uint16(30) +} + +func (s Node_structNode) SetDiscriminantCount(v uint16) { + capnp.Struct(s).SetUint16(30, v) +} + +func (s Node_structNode) DiscriminantOffset() uint32 { + return capnp.Struct(s).Uint32(32) +} + +func (s Node_structNode) SetDiscriminantOffset(v uint32) { + capnp.Struct(s).SetUint32(32, v) +} + +func (s Node_structNode) Fields() (Field_List, error) { + p, err := capnp.Struct(s).Ptr(3) + return Field_List(p.List()), err +} + +func (s Node_structNode) HasFields() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s Node_structNode) SetFields(v Field_List) error { + return capnp.Struct(s).SetPtr(3, v.ToPtr()) +} + +// NewFields sets the fields field to a newly +// allocated Field_List, preferring placement in s's segment. +func (s Node_structNode) NewFields(n int32) (Field_List, error) { + l, err := NewField_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Field_List{}, err + } + err = capnp.Struct(s).SetPtr(3, l.ToPtr()) + return l, err +} +func (s Node) Enum() Node_enum { return Node_enum(s) } + +func (s Node) SetEnum() { + capnp.Struct(s).SetUint16(12, 2) +} + +func (s Node_enum) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_enum) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_enum) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_enum) Enumerants() (Enumerant_List, error) { + p, err := capnp.Struct(s).Ptr(3) + return Enumerant_List(p.List()), err +} + +func (s Node_enum) HasEnumerants() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s Node_enum) SetEnumerants(v Enumerant_List) error { + return capnp.Struct(s).SetPtr(3, v.ToPtr()) +} + +// NewEnumerants sets the enumerants field to a newly +// allocated Enumerant_List, preferring placement in s's segment. +func (s Node_enum) NewEnumerants(n int32) (Enumerant_List, error) { + l, err := NewEnumerant_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Enumerant_List{}, err + } + err = capnp.Struct(s).SetPtr(3, l.ToPtr()) + return l, err +} +func (s Node) Interface() Node_interface { return Node_interface(s) } + +func (s Node) SetInterface() { + capnp.Struct(s).SetUint16(12, 3) +} + +func (s Node_interface) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_interface) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_interface) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_interface) Methods() (Method_List, error) { + p, err := capnp.Struct(s).Ptr(3) + return Method_List(p.List()), err +} + +func (s Node_interface) HasMethods() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s Node_interface) SetMethods(v Method_List) error { + return capnp.Struct(s).SetPtr(3, v.ToPtr()) +} + +// NewMethods sets the methods field to a newly +// allocated Method_List, preferring placement in s's segment. +func (s Node_interface) NewMethods(n int32) (Method_List, error) { + l, err := NewMethod_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Method_List{}, err + } + err = capnp.Struct(s).SetPtr(3, l.ToPtr()) + return l, err +} +func (s Node_interface) Superclasses() (Superclass_List, error) { + p, err := capnp.Struct(s).Ptr(4) + return Superclass_List(p.List()), err +} + +func (s Node_interface) HasSuperclasses() bool { + return capnp.Struct(s).HasPtr(4) +} + +func (s Node_interface) SetSuperclasses(v Superclass_List) error { + return capnp.Struct(s).SetPtr(4, v.ToPtr()) +} + +// NewSuperclasses sets the superclasses field to a newly +// allocated Superclass_List, preferring placement in s's segment. +func (s Node_interface) NewSuperclasses(n int32) (Superclass_List, error) { + l, err := NewSuperclass_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Superclass_List{}, err + } + err = capnp.Struct(s).SetPtr(4, l.ToPtr()) + return l, err +} +func (s Node) Const() Node_const { return Node_const(s) } + +func (s Node) SetConst() { + capnp.Struct(s).SetUint16(12, 4) +} + +func (s Node_const) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_const) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_const) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_const) Type() (Type, error) { + p, err := capnp.Struct(s).Ptr(3) + return Type(p.Struct()), err +} + +func (s Node_const) HasType() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s Node_const) SetType(v Type) error { + return capnp.Struct(s).SetPtr(3, capnp.Struct(v).ToPtr()) +} + +// NewType sets the type field to a newly +// allocated Type struct, preferring placement in s's segment. +func (s Node_const) NewType() (Type, error) { + ss, err := NewType(capnp.Struct(s).Segment()) + if err != nil { + return Type{}, err + } + err = capnp.Struct(s).SetPtr(3, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Node_const) Value() (Value, error) { + p, err := capnp.Struct(s).Ptr(4) + return Value(p.Struct()), err +} + +func (s Node_const) HasValue() bool { + return capnp.Struct(s).HasPtr(4) +} + +func (s Node_const) SetValue(v Value) error { + return capnp.Struct(s).SetPtr(4, capnp.Struct(v).ToPtr()) +} + +// NewValue sets the value field to a newly +// allocated Value struct, preferring placement in s's segment. +func (s Node_const) NewValue() (Value, error) { + ss, err := NewValue(capnp.Struct(s).Segment()) + if err != nil { + return Value{}, err + } + err = capnp.Struct(s).SetPtr(4, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Node) Annotation() Node_annotation { return Node_annotation(s) } + +func (s Node) SetAnnotation() { + capnp.Struct(s).SetUint16(12, 5) +} + +func (s Node_annotation) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_annotation) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_annotation) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_annotation) Type() (Type, error) { + p, err := capnp.Struct(s).Ptr(3) + return Type(p.Struct()), err +} + +func (s Node_annotation) HasType() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s Node_annotation) SetType(v Type) error { + return capnp.Struct(s).SetPtr(3, capnp.Struct(v).ToPtr()) +} + +// NewType sets the type field to a newly +// allocated Type struct, preferring placement in s's segment. +func (s Node_annotation) NewType() (Type, error) { + ss, err := NewType(capnp.Struct(s).Segment()) + if err != nil { + return Type{}, err + } + err = capnp.Struct(s).SetPtr(3, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Node_annotation) TargetsFile() bool { + return capnp.Struct(s).Bit(112) +} + +func (s Node_annotation) SetTargetsFile(v bool) { + capnp.Struct(s).SetBit(112, v) +} + +func (s Node_annotation) TargetsConst() bool { + return capnp.Struct(s).Bit(113) +} + +func (s Node_annotation) SetTargetsConst(v bool) { + capnp.Struct(s).SetBit(113, v) +} + +func (s Node_annotation) TargetsEnum() bool { + return capnp.Struct(s).Bit(114) +} + +func (s Node_annotation) SetTargetsEnum(v bool) { + capnp.Struct(s).SetBit(114, v) +} + +func (s Node_annotation) TargetsEnumerant() bool { + return capnp.Struct(s).Bit(115) +} + +func (s Node_annotation) SetTargetsEnumerant(v bool) { + capnp.Struct(s).SetBit(115, v) +} + +func (s Node_annotation) TargetsStruct() bool { + return capnp.Struct(s).Bit(116) +} + +func (s Node_annotation) SetTargetsStruct(v bool) { + capnp.Struct(s).SetBit(116, v) +} + +func (s Node_annotation) TargetsField() bool { + return capnp.Struct(s).Bit(117) +} + +func (s Node_annotation) SetTargetsField(v bool) { + capnp.Struct(s).SetBit(117, v) +} + +func (s Node_annotation) TargetsUnion() bool { + return capnp.Struct(s).Bit(118) +} + +func (s Node_annotation) SetTargetsUnion(v bool) { + capnp.Struct(s).SetBit(118, v) +} + +func (s Node_annotation) TargetsGroup() bool { + return capnp.Struct(s).Bit(119) +} + +func (s Node_annotation) SetTargetsGroup(v bool) { + capnp.Struct(s).SetBit(119, v) +} + +func (s Node_annotation) TargetsInterface() bool { + return capnp.Struct(s).Bit(120) +} + +func (s Node_annotation) SetTargetsInterface(v bool) { + capnp.Struct(s).SetBit(120, v) +} + +func (s Node_annotation) TargetsMethod() bool { + return capnp.Struct(s).Bit(121) +} + +func (s Node_annotation) SetTargetsMethod(v bool) { + capnp.Struct(s).SetBit(121, v) +} + +func (s Node_annotation) TargetsParam() bool { + return capnp.Struct(s).Bit(122) +} + +func (s Node_annotation) SetTargetsParam(v bool) { + capnp.Struct(s).SetBit(122, v) +} + +func (s Node_annotation) TargetsAnnotation() bool { + return capnp.Struct(s).Bit(123) +} + +func (s Node_annotation) SetTargetsAnnotation(v bool) { + capnp.Struct(s).SetBit(123, v) +} + +// Node_List is a list of Node. +type Node_List = capnp.StructList[Node] + +// NewNode creates a new list of Node. +func NewNode_List(s *capnp.Segment, sz int32) (Node_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 40, PointerCount: 6}, sz) + return capnp.StructList[Node](l), err +} + +// Node_Future is a wrapper for a Node promised by a client call. +type Node_Future struct{ *capnp.Future } + +func (f Node_Future) Struct() (Node, error) { + p, err := f.Future.Ptr() + return Node(p.Struct()), err +} +func (p Node_Future) StructNode() Node_structNode_Future { return Node_structNode_Future{p.Future} } + +// Node_structNode_Future is a wrapper for a Node_structNode promised by a client call. +type Node_structNode_Future struct{ *capnp.Future } + +func (f Node_structNode_Future) Struct() (Node_structNode, error) { + p, err := f.Future.Ptr() + return Node_structNode(p.Struct()), err +} +func (p Node_Future) Enum() Node_enum_Future { return Node_enum_Future{p.Future} } + +// Node_enum_Future is a wrapper for a Node_enum promised by a client call. +type Node_enum_Future struct{ *capnp.Future } + +func (f Node_enum_Future) Struct() (Node_enum, error) { + p, err := f.Future.Ptr() + return Node_enum(p.Struct()), err +} +func (p Node_Future) Interface() Node_interface_Future { return Node_interface_Future{p.Future} } + +// Node_interface_Future is a wrapper for a Node_interface promised by a client call. +type Node_interface_Future struct{ *capnp.Future } + +func (f Node_interface_Future) Struct() (Node_interface, error) { + p, err := f.Future.Ptr() + return Node_interface(p.Struct()), err +} +func (p Node_Future) Const() Node_const_Future { return Node_const_Future{p.Future} } + +// Node_const_Future is a wrapper for a Node_const promised by a client call. +type Node_const_Future struct{ *capnp.Future } + +func (f Node_const_Future) Struct() (Node_const, error) { + p, err := f.Future.Ptr() + return Node_const(p.Struct()), err +} +func (p Node_const_Future) Type() Type_Future { + return Type_Future{Future: p.Future.Field(3, nil)} +} +func (p Node_const_Future) Value() Value_Future { + return Value_Future{Future: p.Future.Field(4, nil)} +} +func (p Node_Future) Annotation() Node_annotation_Future { return Node_annotation_Future{p.Future} } + +// Node_annotation_Future is a wrapper for a Node_annotation promised by a client call. +type Node_annotation_Future struct{ *capnp.Future } + +func (f Node_annotation_Future) Struct() (Node_annotation, error) { + p, err := f.Future.Ptr() + return Node_annotation(p.Struct()), err +} +func (p Node_annotation_Future) Type() Type_Future { + return Type_Future{Future: p.Future.Field(3, nil)} +} + +type Node_Parameter capnp.Struct + +// Node_Parameter_TypeID is the unique identifier for the type Node_Parameter. +const Node_Parameter_TypeID = 0xb9521bccf10fa3b1 + +func NewNode_Parameter(s *capnp.Segment) (Node_Parameter, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Node_Parameter(st), err +} + +func NewRootNode_Parameter(s *capnp.Segment) (Node_Parameter, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Node_Parameter(st), err +} + +func ReadRootNode_Parameter(msg *capnp.Message) (Node_Parameter, error) { + root, err := msg.Root() + return Node_Parameter(root.Struct()), err +} + +func (s Node_Parameter) String() string { + str, _ := text.Marshal(0xb9521bccf10fa3b1, capnp.Struct(s)) + return str +} + +func (s Node_Parameter) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Node_Parameter) DecodeFromPtr(p capnp.Ptr) Node_Parameter { + return Node_Parameter(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Node_Parameter) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Node_Parameter) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_Parameter) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_Parameter) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_Parameter) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Node_Parameter) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Node_Parameter) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Node_Parameter) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +// Node_Parameter_List is a list of Node_Parameter. +type Node_Parameter_List = capnp.StructList[Node_Parameter] + +// NewNode_Parameter creates a new list of Node_Parameter. +func NewNode_Parameter_List(s *capnp.Segment, sz int32) (Node_Parameter_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return capnp.StructList[Node_Parameter](l), err +} + +// Node_Parameter_Future is a wrapper for a Node_Parameter promised by a client call. +type Node_Parameter_Future struct{ *capnp.Future } + +func (f Node_Parameter_Future) Struct() (Node_Parameter, error) { + p, err := f.Future.Ptr() + return Node_Parameter(p.Struct()), err +} + +type Node_NestedNode capnp.Struct + +// Node_NestedNode_TypeID is the unique identifier for the type Node_NestedNode. +const Node_NestedNode_TypeID = 0xdebf55bbfa0fc242 + +func NewNode_NestedNode(s *capnp.Segment) (Node_NestedNode, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Node_NestedNode(st), err +} + +func NewRootNode_NestedNode(s *capnp.Segment) (Node_NestedNode, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Node_NestedNode(st), err +} + +func ReadRootNode_NestedNode(msg *capnp.Message) (Node_NestedNode, error) { + root, err := msg.Root() + return Node_NestedNode(root.Struct()), err +} + +func (s Node_NestedNode) String() string { + str, _ := text.Marshal(0xdebf55bbfa0fc242, capnp.Struct(s)) + return str +} + +func (s Node_NestedNode) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Node_NestedNode) DecodeFromPtr(p capnp.Ptr) Node_NestedNode { + return Node_NestedNode(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Node_NestedNode) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Node_NestedNode) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_NestedNode) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_NestedNode) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_NestedNode) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Node_NestedNode) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Node_NestedNode) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Node_NestedNode) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Node_NestedNode) Id() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s Node_NestedNode) SetId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +// Node_NestedNode_List is a list of Node_NestedNode. +type Node_NestedNode_List = capnp.StructList[Node_NestedNode] + +// NewNode_NestedNode creates a new list of Node_NestedNode. +func NewNode_NestedNode_List(s *capnp.Segment, sz int32) (Node_NestedNode_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Node_NestedNode](l), err +} + +// Node_NestedNode_Future is a wrapper for a Node_NestedNode promised by a client call. +type Node_NestedNode_Future struct{ *capnp.Future } + +func (f Node_NestedNode_Future) Struct() (Node_NestedNode, error) { + p, err := f.Future.Ptr() + return Node_NestedNode(p.Struct()), err +} + +type Node_SourceInfo capnp.Struct + +// Node_SourceInfo_TypeID is the unique identifier for the type Node_SourceInfo. +const Node_SourceInfo_TypeID = 0xf38e1de3041357ae + +func NewNode_SourceInfo(s *capnp.Segment) (Node_SourceInfo, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Node_SourceInfo(st), err +} + +func NewRootNode_SourceInfo(s *capnp.Segment) (Node_SourceInfo, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Node_SourceInfo(st), err +} + +func ReadRootNode_SourceInfo(msg *capnp.Message) (Node_SourceInfo, error) { + root, err := msg.Root() + return Node_SourceInfo(root.Struct()), err +} + +func (s Node_SourceInfo) String() string { + str, _ := text.Marshal(0xf38e1de3041357ae, capnp.Struct(s)) + return str +} + +func (s Node_SourceInfo) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Node_SourceInfo) DecodeFromPtr(p capnp.Ptr) Node_SourceInfo { + return Node_SourceInfo(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Node_SourceInfo) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Node_SourceInfo) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_SourceInfo) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_SourceInfo) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_SourceInfo) Id() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s Node_SourceInfo) SetId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +func (s Node_SourceInfo) DocComment() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Node_SourceInfo) HasDocComment() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Node_SourceInfo) DocCommentBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Node_SourceInfo) SetDocComment(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Node_SourceInfo) Members() (Node_SourceInfo_Member_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return Node_SourceInfo_Member_List(p.List()), err +} + +func (s Node_SourceInfo) HasMembers() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Node_SourceInfo) SetMembers(v Node_SourceInfo_Member_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewMembers sets the members field to a newly +// allocated Node_SourceInfo_Member_List, preferring placement in s's segment. +func (s Node_SourceInfo) NewMembers(n int32) (Node_SourceInfo_Member_List, error) { + l, err := NewNode_SourceInfo_Member_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Node_SourceInfo_Member_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} + +// Node_SourceInfo_List is a list of Node_SourceInfo. +type Node_SourceInfo_List = capnp.StructList[Node_SourceInfo] + +// NewNode_SourceInfo creates a new list of Node_SourceInfo. +func NewNode_SourceInfo_List(s *capnp.Segment, sz int32) (Node_SourceInfo_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) + return capnp.StructList[Node_SourceInfo](l), err +} + +// Node_SourceInfo_Future is a wrapper for a Node_SourceInfo promised by a client call. +type Node_SourceInfo_Future struct{ *capnp.Future } + +func (f Node_SourceInfo_Future) Struct() (Node_SourceInfo, error) { + p, err := f.Future.Ptr() + return Node_SourceInfo(p.Struct()), err +} + +type Node_SourceInfo_Member capnp.Struct + +// Node_SourceInfo_Member_TypeID is the unique identifier for the type Node_SourceInfo_Member. +const Node_SourceInfo_Member_TypeID = 0xc2ba9038898e1fa2 + +func NewNode_SourceInfo_Member(s *capnp.Segment) (Node_SourceInfo_Member, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Node_SourceInfo_Member(st), err +} + +func NewRootNode_SourceInfo_Member(s *capnp.Segment) (Node_SourceInfo_Member, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Node_SourceInfo_Member(st), err +} + +func ReadRootNode_SourceInfo_Member(msg *capnp.Message) (Node_SourceInfo_Member, error) { + root, err := msg.Root() + return Node_SourceInfo_Member(root.Struct()), err +} + +func (s Node_SourceInfo_Member) String() string { + str, _ := text.Marshal(0xc2ba9038898e1fa2, capnp.Struct(s)) + return str +} + +func (s Node_SourceInfo_Member) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Node_SourceInfo_Member) DecodeFromPtr(p capnp.Ptr) Node_SourceInfo_Member { + return Node_SourceInfo_Member(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Node_SourceInfo_Member) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Node_SourceInfo_Member) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Node_SourceInfo_Member) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Node_SourceInfo_Member) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Node_SourceInfo_Member) DocComment() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Node_SourceInfo_Member) HasDocComment() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Node_SourceInfo_Member) DocCommentBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Node_SourceInfo_Member) SetDocComment(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +// Node_SourceInfo_Member_List is a list of Node_SourceInfo_Member. +type Node_SourceInfo_Member_List = capnp.StructList[Node_SourceInfo_Member] + +// NewNode_SourceInfo_Member creates a new list of Node_SourceInfo_Member. +func NewNode_SourceInfo_Member_List(s *capnp.Segment, sz int32) (Node_SourceInfo_Member_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return capnp.StructList[Node_SourceInfo_Member](l), err +} + +// Node_SourceInfo_Member_Future is a wrapper for a Node_SourceInfo_Member promised by a client call. +type Node_SourceInfo_Member_Future struct{ *capnp.Future } + +func (f Node_SourceInfo_Member_Future) Struct() (Node_SourceInfo_Member, error) { + p, err := f.Future.Ptr() + return Node_SourceInfo_Member(p.Struct()), err +} + +type Field capnp.Struct +type Field_slot Field +type Field_group Field +type Field_ordinal Field +type Field_Which uint16 + +const ( + Field_Which_slot Field_Which = 0 + Field_Which_group Field_Which = 1 +) + +func (w Field_Which) String() string { + const s = "slotgroup" + switch w { + case Field_Which_slot: + return s[0:4] + case Field_Which_group: + return s[4:9] + + } + return "Field_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +type Field_ordinal_Which uint16 + +const ( + Field_ordinal_Which_implicit Field_ordinal_Which = 0 + Field_ordinal_Which_explicit Field_ordinal_Which = 1 +) + +func (w Field_ordinal_Which) String() string { + const s = "implicitexplicit" + switch w { + case Field_ordinal_Which_implicit: + return s[0:8] + case Field_ordinal_Which_explicit: + return s[8:16] + + } + return "Field_ordinal_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Field_TypeID is the unique identifier for the type Field. +const Field_TypeID = 0x9aad50a41f4af45f + +func NewField(s *capnp.Segment) (Field, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 4}) + return Field(st), err +} + +func NewRootField(s *capnp.Segment) (Field, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 4}) + return Field(st), err +} + +func ReadRootField(msg *capnp.Message) (Field, error) { + root, err := msg.Root() + return Field(root.Struct()), err +} + +func (s Field) String() string { + str, _ := text.Marshal(0x9aad50a41f4af45f, capnp.Struct(s)) + return str +} + +func (s Field) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Field) DecodeFromPtr(p capnp.Ptr) Field { + return Field(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Field) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Field) Which() Field_Which { + return Field_Which(capnp.Struct(s).Uint16(8)) +} +func (s Field) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Field) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Field) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Field) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Field) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Field) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Field) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Field) CodeOrder() uint16 { + return capnp.Struct(s).Uint16(0) +} + +func (s Field) SetCodeOrder(v uint16) { + capnp.Struct(s).SetUint16(0, v) +} + +func (s Field) Annotations() (Annotation_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return Annotation_List(p.List()), err +} + +func (s Field) HasAnnotations() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Field) SetAnnotations(v Annotation_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewAnnotations sets the annotations field to a newly +// allocated Annotation_List, preferring placement in s's segment. +func (s Field) NewAnnotations(n int32) (Annotation_List, error) { + l, err := NewAnnotation_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Annotation_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} +func (s Field) DiscriminantValue() uint16 { + return capnp.Struct(s).Uint16(2) ^ 65535 +} + +func (s Field) SetDiscriminantValue(v uint16) { + capnp.Struct(s).SetUint16(2, v^65535) +} + +func (s Field) Slot() Field_slot { return Field_slot(s) } + +func (s Field) SetSlot() { + capnp.Struct(s).SetUint16(8, 0) +} + +func (s Field_slot) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Field_slot) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Field_slot) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Field_slot) Offset() uint32 { + return capnp.Struct(s).Uint32(4) +} + +func (s Field_slot) SetOffset(v uint32) { + capnp.Struct(s).SetUint32(4, v) +} + +func (s Field_slot) Type() (Type, error) { + p, err := capnp.Struct(s).Ptr(2) + return Type(p.Struct()), err +} + +func (s Field_slot) HasType() bool { + return capnp.Struct(s).HasPtr(2) +} + +func (s Field_slot) SetType(v Type) error { + return capnp.Struct(s).SetPtr(2, capnp.Struct(v).ToPtr()) +} + +// NewType sets the type field to a newly +// allocated Type struct, preferring placement in s's segment. +func (s Field_slot) NewType() (Type, error) { + ss, err := NewType(capnp.Struct(s).Segment()) + if err != nil { + return Type{}, err + } + err = capnp.Struct(s).SetPtr(2, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Field_slot) DefaultValue() (Value, error) { + p, err := capnp.Struct(s).Ptr(3) + return Value(p.Struct()), err +} + +func (s Field_slot) HasDefaultValue() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s Field_slot) SetDefaultValue(v Value) error { + return capnp.Struct(s).SetPtr(3, capnp.Struct(v).ToPtr()) +} + +// NewDefaultValue sets the defaultValue field to a newly +// allocated Value struct, preferring placement in s's segment. +func (s Field_slot) NewDefaultValue() (Value, error) { + ss, err := NewValue(capnp.Struct(s).Segment()) + if err != nil { + return Value{}, err + } + err = capnp.Struct(s).SetPtr(3, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Field_slot) HadExplicitDefault() bool { + return capnp.Struct(s).Bit(128) +} + +func (s Field_slot) SetHadExplicitDefault(v bool) { + capnp.Struct(s).SetBit(128, v) +} + +func (s Field) Group() Field_group { return Field_group(s) } + +func (s Field) SetGroup() { + capnp.Struct(s).SetUint16(8, 1) +} + +func (s Field_group) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Field_group) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Field_group) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Field_group) TypeId() uint64 { + return capnp.Struct(s).Uint64(16) +} + +func (s Field_group) SetTypeId(v uint64) { + capnp.Struct(s).SetUint64(16, v) +} + +func (s Field) Ordinal() Field_ordinal { return Field_ordinal(s) } + +func (s Field_ordinal) Which() Field_ordinal_Which { + return Field_ordinal_Which(capnp.Struct(s).Uint16(10)) +} +func (s Field_ordinal) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Field_ordinal) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Field_ordinal) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Field_ordinal) SetImplicit() { + capnp.Struct(s).SetUint16(10, 0) + +} + +func (s Field_ordinal) Explicit() uint16 { + if capnp.Struct(s).Uint16(10) != 1 { + panic("Which() != explicit") + } + return capnp.Struct(s).Uint16(12) +} + +func (s Field_ordinal) SetExplicit(v uint16) { + capnp.Struct(s).SetUint16(10, 1) + capnp.Struct(s).SetUint16(12, v) +} + +// Field_List is a list of Field. +type Field_List = capnp.StructList[Field] + +// NewField creates a new list of Field. +func NewField_List(s *capnp.Segment, sz int32) (Field_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 24, PointerCount: 4}, sz) + return capnp.StructList[Field](l), err +} + +// Field_Future is a wrapper for a Field promised by a client call. +type Field_Future struct{ *capnp.Future } + +func (f Field_Future) Struct() (Field, error) { + p, err := f.Future.Ptr() + return Field(p.Struct()), err +} +func (p Field_Future) Slot() Field_slot_Future { return Field_slot_Future{p.Future} } + +// Field_slot_Future is a wrapper for a Field_slot promised by a client call. +type Field_slot_Future struct{ *capnp.Future } + +func (f Field_slot_Future) Struct() (Field_slot, error) { + p, err := f.Future.Ptr() + return Field_slot(p.Struct()), err +} +func (p Field_slot_Future) Type() Type_Future { + return Type_Future{Future: p.Future.Field(2, nil)} +} +func (p Field_slot_Future) DefaultValue() Value_Future { + return Value_Future{Future: p.Future.Field(3, nil)} +} +func (p Field_Future) Group() Field_group_Future { return Field_group_Future{p.Future} } + +// Field_group_Future is a wrapper for a Field_group promised by a client call. +type Field_group_Future struct{ *capnp.Future } + +func (f Field_group_Future) Struct() (Field_group, error) { + p, err := f.Future.Ptr() + return Field_group(p.Struct()), err +} +func (p Field_Future) Ordinal() Field_ordinal_Future { return Field_ordinal_Future{p.Future} } + +// Field_ordinal_Future is a wrapper for a Field_ordinal promised by a client call. +type Field_ordinal_Future struct{ *capnp.Future } + +func (f Field_ordinal_Future) Struct() (Field_ordinal, error) { + p, err := f.Future.Ptr() + return Field_ordinal(p.Struct()), err +} + +type Enumerant capnp.Struct + +// Enumerant_TypeID is the unique identifier for the type Enumerant. +const Enumerant_TypeID = 0x978a7cebdc549a4d + +func NewEnumerant(s *capnp.Segment) (Enumerant, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Enumerant(st), err +} + +func NewRootEnumerant(s *capnp.Segment) (Enumerant, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Enumerant(st), err +} + +func ReadRootEnumerant(msg *capnp.Message) (Enumerant, error) { + root, err := msg.Root() + return Enumerant(root.Struct()), err +} + +func (s Enumerant) String() string { + str, _ := text.Marshal(0x978a7cebdc549a4d, capnp.Struct(s)) + return str +} + +func (s Enumerant) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Enumerant) DecodeFromPtr(p capnp.Ptr) Enumerant { + return Enumerant(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Enumerant) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Enumerant) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Enumerant) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Enumerant) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Enumerant) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Enumerant) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Enumerant) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Enumerant) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Enumerant) CodeOrder() uint16 { + return capnp.Struct(s).Uint16(0) +} + +func (s Enumerant) SetCodeOrder(v uint16) { + capnp.Struct(s).SetUint16(0, v) +} + +func (s Enumerant) Annotations() (Annotation_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return Annotation_List(p.List()), err +} + +func (s Enumerant) HasAnnotations() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Enumerant) SetAnnotations(v Annotation_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewAnnotations sets the annotations field to a newly +// allocated Annotation_List, preferring placement in s's segment. +func (s Enumerant) NewAnnotations(n int32) (Annotation_List, error) { + l, err := NewAnnotation_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Annotation_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} + +// Enumerant_List is a list of Enumerant. +type Enumerant_List = capnp.StructList[Enumerant] + +// NewEnumerant creates a new list of Enumerant. +func NewEnumerant_List(s *capnp.Segment, sz int32) (Enumerant_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) + return capnp.StructList[Enumerant](l), err +} + +// Enumerant_Future is a wrapper for a Enumerant promised by a client call. +type Enumerant_Future struct{ *capnp.Future } + +func (f Enumerant_Future) Struct() (Enumerant, error) { + p, err := f.Future.Ptr() + return Enumerant(p.Struct()), err +} + +type Superclass capnp.Struct + +// Superclass_TypeID is the unique identifier for the type Superclass. +const Superclass_TypeID = 0xa9962a9ed0a4d7f8 + +func NewSuperclass(s *capnp.Segment) (Superclass, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Superclass(st), err +} + +func NewRootSuperclass(s *capnp.Segment) (Superclass, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Superclass(st), err +} + +func ReadRootSuperclass(msg *capnp.Message) (Superclass, error) { + root, err := msg.Root() + return Superclass(root.Struct()), err +} + +func (s Superclass) String() string { + str, _ := text.Marshal(0xa9962a9ed0a4d7f8, capnp.Struct(s)) + return str +} + +func (s Superclass) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Superclass) DecodeFromPtr(p capnp.Ptr) Superclass { + return Superclass(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Superclass) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Superclass) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Superclass) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Superclass) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Superclass) Id() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s Superclass) SetId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +func (s Superclass) Brand() (Brand, error) { + p, err := capnp.Struct(s).Ptr(0) + return Brand(p.Struct()), err +} + +func (s Superclass) HasBrand() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Superclass) SetBrand(v Brand) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewBrand sets the brand field to a newly +// allocated Brand struct, preferring placement in s's segment. +func (s Superclass) NewBrand() (Brand, error) { + ss, err := NewBrand(capnp.Struct(s).Segment()) + if err != nil { + return Brand{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// Superclass_List is a list of Superclass. +type Superclass_List = capnp.StructList[Superclass] + +// NewSuperclass creates a new list of Superclass. +func NewSuperclass_List(s *capnp.Segment, sz int32) (Superclass_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Superclass](l), err +} + +// Superclass_Future is a wrapper for a Superclass promised by a client call. +type Superclass_Future struct{ *capnp.Future } + +func (f Superclass_Future) Struct() (Superclass, error) { + p, err := f.Future.Ptr() + return Superclass(p.Struct()), err +} +func (p Superclass_Future) Brand() Brand_Future { + return Brand_Future{Future: p.Future.Field(0, nil)} +} + +type Method capnp.Struct + +// Method_TypeID is the unique identifier for the type Method. +const Method_TypeID = 0x9500cce23b334d80 + +func NewMethod(s *capnp.Segment) (Method, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 5}) + return Method(st), err +} + +func NewRootMethod(s *capnp.Segment) (Method, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 5}) + return Method(st), err +} + +func ReadRootMethod(msg *capnp.Message) (Method, error) { + root, err := msg.Root() + return Method(root.Struct()), err +} + +func (s Method) String() string { + str, _ := text.Marshal(0x9500cce23b334d80, capnp.Struct(s)) + return str +} + +func (s Method) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Method) DecodeFromPtr(p capnp.Ptr) Method { + return Method(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Method) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Method) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Method) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Method) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Method) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Method) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Method) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Method) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s Method) CodeOrder() uint16 { + return capnp.Struct(s).Uint16(0) +} + +func (s Method) SetCodeOrder(v uint16) { + capnp.Struct(s).SetUint16(0, v) +} + +func (s Method) ImplicitParameters() (Node_Parameter_List, error) { + p, err := capnp.Struct(s).Ptr(4) + return Node_Parameter_List(p.List()), err +} + +func (s Method) HasImplicitParameters() bool { + return capnp.Struct(s).HasPtr(4) +} + +func (s Method) SetImplicitParameters(v Node_Parameter_List) error { + return capnp.Struct(s).SetPtr(4, v.ToPtr()) +} + +// NewImplicitParameters sets the implicitParameters field to a newly +// allocated Node_Parameter_List, preferring placement in s's segment. +func (s Method) NewImplicitParameters(n int32) (Node_Parameter_List, error) { + l, err := NewNode_Parameter_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Node_Parameter_List{}, err + } + err = capnp.Struct(s).SetPtr(4, l.ToPtr()) + return l, err +} +func (s Method) ParamStructType() uint64 { + return capnp.Struct(s).Uint64(8) +} + +func (s Method) SetParamStructType(v uint64) { + capnp.Struct(s).SetUint64(8, v) +} + +func (s Method) ParamBrand() (Brand, error) { + p, err := capnp.Struct(s).Ptr(2) + return Brand(p.Struct()), err +} + +func (s Method) HasParamBrand() bool { + return capnp.Struct(s).HasPtr(2) +} + +func (s Method) SetParamBrand(v Brand) error { + return capnp.Struct(s).SetPtr(2, capnp.Struct(v).ToPtr()) +} + +// NewParamBrand sets the paramBrand field to a newly +// allocated Brand struct, preferring placement in s's segment. +func (s Method) NewParamBrand() (Brand, error) { + ss, err := NewBrand(capnp.Struct(s).Segment()) + if err != nil { + return Brand{}, err + } + err = capnp.Struct(s).SetPtr(2, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Method) ResultStructType() uint64 { + return capnp.Struct(s).Uint64(16) +} + +func (s Method) SetResultStructType(v uint64) { + capnp.Struct(s).SetUint64(16, v) +} + +func (s Method) ResultBrand() (Brand, error) { + p, err := capnp.Struct(s).Ptr(3) + return Brand(p.Struct()), err +} + +func (s Method) HasResultBrand() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s Method) SetResultBrand(v Brand) error { + return capnp.Struct(s).SetPtr(3, capnp.Struct(v).ToPtr()) +} + +// NewResultBrand sets the resultBrand field to a newly +// allocated Brand struct, preferring placement in s's segment. +func (s Method) NewResultBrand() (Brand, error) { + ss, err := NewBrand(capnp.Struct(s).Segment()) + if err != nil { + return Brand{}, err + } + err = capnp.Struct(s).SetPtr(3, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Method) Annotations() (Annotation_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return Annotation_List(p.List()), err +} + +func (s Method) HasAnnotations() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Method) SetAnnotations(v Annotation_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewAnnotations sets the annotations field to a newly +// allocated Annotation_List, preferring placement in s's segment. +func (s Method) NewAnnotations(n int32) (Annotation_List, error) { + l, err := NewAnnotation_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Annotation_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} + +// Method_List is a list of Method. +type Method_List = capnp.StructList[Method] + +// NewMethod creates a new list of Method. +func NewMethod_List(s *capnp.Segment, sz int32) (Method_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 24, PointerCount: 5}, sz) + return capnp.StructList[Method](l), err +} + +// Method_Future is a wrapper for a Method promised by a client call. +type Method_Future struct{ *capnp.Future } + +func (f Method_Future) Struct() (Method, error) { + p, err := f.Future.Ptr() + return Method(p.Struct()), err +} +func (p Method_Future) ParamBrand() Brand_Future { + return Brand_Future{Future: p.Future.Field(2, nil)} +} +func (p Method_Future) ResultBrand() Brand_Future { + return Brand_Future{Future: p.Future.Field(3, nil)} +} + +type Type capnp.Struct +type Type_list Type +type Type_enum Type +type Type_structType Type +type Type_interface Type +type Type_anyPointer Type +type Type_anyPointer_unconstrained Type +type Type_anyPointer_parameter Type +type Type_anyPointer_implicitMethodParameter Type +type Type_Which uint16 + +const ( + Type_Which_void Type_Which = 0 + Type_Which_bool Type_Which = 1 + Type_Which_int8 Type_Which = 2 + Type_Which_int16 Type_Which = 3 + Type_Which_int32 Type_Which = 4 + Type_Which_int64 Type_Which = 5 + Type_Which_uint8 Type_Which = 6 + Type_Which_uint16 Type_Which = 7 + Type_Which_uint32 Type_Which = 8 + Type_Which_uint64 Type_Which = 9 + Type_Which_float32 Type_Which = 10 + Type_Which_float64 Type_Which = 11 + Type_Which_text Type_Which = 12 + Type_Which_data Type_Which = 13 + Type_Which_list Type_Which = 14 + Type_Which_enum Type_Which = 15 + Type_Which_structType Type_Which = 16 + Type_Which_interface Type_Which = 17 + Type_Which_anyPointer Type_Which = 18 +) + +func (w Type_Which) String() string { + const s = "voidboolint8int16int32int64uint8uint16uint32uint64float32float64textdatalistenumstructTypeinterfaceanyPointer" + switch w { + case Type_Which_void: + return s[0:4] + case Type_Which_bool: + return s[4:8] + case Type_Which_int8: + return s[8:12] + case Type_Which_int16: + return s[12:17] + case Type_Which_int32: + return s[17:22] + case Type_Which_int64: + return s[22:27] + case Type_Which_uint8: + return s[27:32] + case Type_Which_uint16: + return s[32:38] + case Type_Which_uint32: + return s[38:44] + case Type_Which_uint64: + return s[44:50] + case Type_Which_float32: + return s[50:57] + case Type_Which_float64: + return s[57:64] + case Type_Which_text: + return s[64:68] + case Type_Which_data: + return s[68:72] + case Type_Which_list: + return s[72:76] + case Type_Which_enum: + return s[76:80] + case Type_Which_structType: + return s[80:90] + case Type_Which_interface: + return s[90:99] + case Type_Which_anyPointer: + return s[99:109] + + } + return "Type_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +type Type_anyPointer_Which uint16 + +const ( + Type_anyPointer_Which_unconstrained Type_anyPointer_Which = 0 + Type_anyPointer_Which_parameter Type_anyPointer_Which = 1 + Type_anyPointer_Which_implicitMethodParameter Type_anyPointer_Which = 2 +) + +func (w Type_anyPointer_Which) String() string { + const s = "unconstrainedparameterimplicitMethodParameter" + switch w { + case Type_anyPointer_Which_unconstrained: + return s[0:13] + case Type_anyPointer_Which_parameter: + return s[13:22] + case Type_anyPointer_Which_implicitMethodParameter: + return s[22:45] + + } + return "Type_anyPointer_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +type Type_anyPointer_unconstrained_Which uint16 + +const ( + Type_anyPointer_unconstrained_Which_anyKind Type_anyPointer_unconstrained_Which = 0 + Type_anyPointer_unconstrained_Which_struct Type_anyPointer_unconstrained_Which = 1 + Type_anyPointer_unconstrained_Which_list Type_anyPointer_unconstrained_Which = 2 + Type_anyPointer_unconstrained_Which_capability Type_anyPointer_unconstrained_Which = 3 +) + +func (w Type_anyPointer_unconstrained_Which) String() string { + const s = "anyKindstructlistcapability" + switch w { + case Type_anyPointer_unconstrained_Which_anyKind: + return s[0:7] + case Type_anyPointer_unconstrained_Which_struct: + return s[7:13] + case Type_anyPointer_unconstrained_Which_list: + return s[13:17] + case Type_anyPointer_unconstrained_Which_capability: + return s[17:27] + + } + return "Type_anyPointer_unconstrained_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Type_TypeID is the unique identifier for the type Type. +const Type_TypeID = 0xd07378ede1f9cc60 + +func NewType(s *capnp.Segment) (Type, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 1}) + return Type(st), err +} + +func NewRootType(s *capnp.Segment) (Type, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 24, PointerCount: 1}) + return Type(st), err +} + +func ReadRootType(msg *capnp.Message) (Type, error) { + root, err := msg.Root() + return Type(root.Struct()), err +} + +func (s Type) String() string { + str, _ := text.Marshal(0xd07378ede1f9cc60, capnp.Struct(s)) + return str +} + +func (s Type) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Type) DecodeFromPtr(p capnp.Ptr) Type { + return Type(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Type) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Type) Which() Type_Which { + return Type_Which(capnp.Struct(s).Uint16(0)) +} +func (s Type) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type) SetVoid() { + capnp.Struct(s).SetUint16(0, 0) + +} + +func (s Type) SetBool() { + capnp.Struct(s).SetUint16(0, 1) + +} + +func (s Type) SetInt8() { + capnp.Struct(s).SetUint16(0, 2) + +} + +func (s Type) SetInt16() { + capnp.Struct(s).SetUint16(0, 3) + +} + +func (s Type) SetInt32() { + capnp.Struct(s).SetUint16(0, 4) + +} + +func (s Type) SetInt64() { + capnp.Struct(s).SetUint16(0, 5) + +} + +func (s Type) SetUint8() { + capnp.Struct(s).SetUint16(0, 6) + +} + +func (s Type) SetUint16() { + capnp.Struct(s).SetUint16(0, 7) + +} + +func (s Type) SetUint32() { + capnp.Struct(s).SetUint16(0, 8) + +} + +func (s Type) SetUint64() { + capnp.Struct(s).SetUint16(0, 9) + +} + +func (s Type) SetFloat32() { + capnp.Struct(s).SetUint16(0, 10) + +} + +func (s Type) SetFloat64() { + capnp.Struct(s).SetUint16(0, 11) + +} + +func (s Type) SetText() { + capnp.Struct(s).SetUint16(0, 12) + +} + +func (s Type) SetData() { + capnp.Struct(s).SetUint16(0, 13) + +} + +func (s Type) List() Type_list { return Type_list(s) } + +func (s Type) SetList() { + capnp.Struct(s).SetUint16(0, 14) +} + +func (s Type_list) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_list) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_list) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_list) ElementType() (Type, error) { + p, err := capnp.Struct(s).Ptr(0) + return Type(p.Struct()), err +} + +func (s Type_list) HasElementType() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Type_list) SetElementType(v Type) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewElementType sets the elementType field to a newly +// allocated Type struct, preferring placement in s's segment. +func (s Type_list) NewElementType() (Type, error) { + ss, err := NewType(capnp.Struct(s).Segment()) + if err != nil { + return Type{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Type) Enum() Type_enum { return Type_enum(s) } + +func (s Type) SetEnum() { + capnp.Struct(s).SetUint16(0, 15) +} + +func (s Type_enum) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_enum) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_enum) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_enum) TypeId() uint64 { + return capnp.Struct(s).Uint64(8) +} + +func (s Type_enum) SetTypeId(v uint64) { + capnp.Struct(s).SetUint64(8, v) +} + +func (s Type_enum) Brand() (Brand, error) { + p, err := capnp.Struct(s).Ptr(0) + return Brand(p.Struct()), err +} + +func (s Type_enum) HasBrand() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Type_enum) SetBrand(v Brand) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewBrand sets the brand field to a newly +// allocated Brand struct, preferring placement in s's segment. +func (s Type_enum) NewBrand() (Brand, error) { + ss, err := NewBrand(capnp.Struct(s).Segment()) + if err != nil { + return Brand{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Type) StructType() Type_structType { return Type_structType(s) } + +func (s Type) SetStructType() { + capnp.Struct(s).SetUint16(0, 16) +} + +func (s Type_structType) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_structType) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_structType) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_structType) TypeId() uint64 { + return capnp.Struct(s).Uint64(8) +} + +func (s Type_structType) SetTypeId(v uint64) { + capnp.Struct(s).SetUint64(8, v) +} + +func (s Type_structType) Brand() (Brand, error) { + p, err := capnp.Struct(s).Ptr(0) + return Brand(p.Struct()), err +} + +func (s Type_structType) HasBrand() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Type_structType) SetBrand(v Brand) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewBrand sets the brand field to a newly +// allocated Brand struct, preferring placement in s's segment. +func (s Type_structType) NewBrand() (Brand, error) { + ss, err := NewBrand(capnp.Struct(s).Segment()) + if err != nil { + return Brand{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Type) Interface() Type_interface { return Type_interface(s) } + +func (s Type) SetInterface() { + capnp.Struct(s).SetUint16(0, 17) +} + +func (s Type_interface) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_interface) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_interface) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_interface) TypeId() uint64 { + return capnp.Struct(s).Uint64(8) +} + +func (s Type_interface) SetTypeId(v uint64) { + capnp.Struct(s).SetUint64(8, v) +} + +func (s Type_interface) Brand() (Brand, error) { + p, err := capnp.Struct(s).Ptr(0) + return Brand(p.Struct()), err +} + +func (s Type_interface) HasBrand() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Type_interface) SetBrand(v Brand) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewBrand sets the brand field to a newly +// allocated Brand struct, preferring placement in s's segment. +func (s Type_interface) NewBrand() (Brand, error) { + ss, err := NewBrand(capnp.Struct(s).Segment()) + if err != nil { + return Brand{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Type) AnyPointer() Type_anyPointer { return Type_anyPointer(s) } + +func (s Type) SetAnyPointer() { + capnp.Struct(s).SetUint16(0, 18) +} + +func (s Type_anyPointer) Which() Type_anyPointer_Which { + return Type_anyPointer_Which(capnp.Struct(s).Uint16(8)) +} +func (s Type_anyPointer) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_anyPointer) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_anyPointer) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_anyPointer) Unconstrained() Type_anyPointer_unconstrained { + return Type_anyPointer_unconstrained(s) +} + +func (s Type_anyPointer) SetUnconstrained() { + capnp.Struct(s).SetUint16(8, 0) +} + +func (s Type_anyPointer_unconstrained) Which() Type_anyPointer_unconstrained_Which { + return Type_anyPointer_unconstrained_Which(capnp.Struct(s).Uint16(10)) +} +func (s Type_anyPointer_unconstrained) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_anyPointer_unconstrained) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_anyPointer_unconstrained) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_anyPointer_unconstrained) SetAnyKind() { + capnp.Struct(s).SetUint16(10, 0) + +} + +func (s Type_anyPointer_unconstrained) SetStruct() { + capnp.Struct(s).SetUint16(10, 1) + +} + +func (s Type_anyPointer_unconstrained) SetList() { + capnp.Struct(s).SetUint16(10, 2) + +} + +func (s Type_anyPointer_unconstrained) SetCapability() { + capnp.Struct(s).SetUint16(10, 3) + +} + +func (s Type_anyPointer) Parameter() Type_anyPointer_parameter { return Type_anyPointer_parameter(s) } + +func (s Type_anyPointer) SetParameter() { + capnp.Struct(s).SetUint16(8, 1) +} + +func (s Type_anyPointer_parameter) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_anyPointer_parameter) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_anyPointer_parameter) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_anyPointer_parameter) ScopeId() uint64 { + return capnp.Struct(s).Uint64(16) +} + +func (s Type_anyPointer_parameter) SetScopeId(v uint64) { + capnp.Struct(s).SetUint64(16, v) +} + +func (s Type_anyPointer_parameter) ParameterIndex() uint16 { + return capnp.Struct(s).Uint16(10) +} + +func (s Type_anyPointer_parameter) SetParameterIndex(v uint16) { + capnp.Struct(s).SetUint16(10, v) +} + +func (s Type_anyPointer) ImplicitMethodParameter() Type_anyPointer_implicitMethodParameter { + return Type_anyPointer_implicitMethodParameter(s) +} + +func (s Type_anyPointer) SetImplicitMethodParameter() { + capnp.Struct(s).SetUint16(8, 2) +} + +func (s Type_anyPointer_implicitMethodParameter) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Type_anyPointer_implicitMethodParameter) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Type_anyPointer_implicitMethodParameter) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Type_anyPointer_implicitMethodParameter) ParameterIndex() uint16 { + return capnp.Struct(s).Uint16(10) +} + +func (s Type_anyPointer_implicitMethodParameter) SetParameterIndex(v uint16) { + capnp.Struct(s).SetUint16(10, v) +} + +// Type_List is a list of Type. +type Type_List = capnp.StructList[Type] + +// NewType creates a new list of Type. +func NewType_List(s *capnp.Segment, sz int32) (Type_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 24, PointerCount: 1}, sz) + return capnp.StructList[Type](l), err +} + +// Type_Future is a wrapper for a Type promised by a client call. +type Type_Future struct{ *capnp.Future } + +func (f Type_Future) Struct() (Type, error) { + p, err := f.Future.Ptr() + return Type(p.Struct()), err +} +func (p Type_Future) List() Type_list_Future { return Type_list_Future{p.Future} } + +// Type_list_Future is a wrapper for a Type_list promised by a client call. +type Type_list_Future struct{ *capnp.Future } + +func (f Type_list_Future) Struct() (Type_list, error) { + p, err := f.Future.Ptr() + return Type_list(p.Struct()), err +} +func (p Type_list_Future) ElementType() Type_Future { + return Type_Future{Future: p.Future.Field(0, nil)} +} +func (p Type_Future) Enum() Type_enum_Future { return Type_enum_Future{p.Future} } + +// Type_enum_Future is a wrapper for a Type_enum promised by a client call. +type Type_enum_Future struct{ *capnp.Future } + +func (f Type_enum_Future) Struct() (Type_enum, error) { + p, err := f.Future.Ptr() + return Type_enum(p.Struct()), err +} +func (p Type_enum_Future) Brand() Brand_Future { + return Brand_Future{Future: p.Future.Field(0, nil)} +} +func (p Type_Future) StructType() Type_structType_Future { return Type_structType_Future{p.Future} } + +// Type_structType_Future is a wrapper for a Type_structType promised by a client call. +type Type_structType_Future struct{ *capnp.Future } + +func (f Type_structType_Future) Struct() (Type_structType, error) { + p, err := f.Future.Ptr() + return Type_structType(p.Struct()), err +} +func (p Type_structType_Future) Brand() Brand_Future { + return Brand_Future{Future: p.Future.Field(0, nil)} +} +func (p Type_Future) Interface() Type_interface_Future { return Type_interface_Future{p.Future} } + +// Type_interface_Future is a wrapper for a Type_interface promised by a client call. +type Type_interface_Future struct{ *capnp.Future } + +func (f Type_interface_Future) Struct() (Type_interface, error) { + p, err := f.Future.Ptr() + return Type_interface(p.Struct()), err +} +func (p Type_interface_Future) Brand() Brand_Future { + return Brand_Future{Future: p.Future.Field(0, nil)} +} +func (p Type_Future) AnyPointer() Type_anyPointer_Future { return Type_anyPointer_Future{p.Future} } + +// Type_anyPointer_Future is a wrapper for a Type_anyPointer promised by a client call. +type Type_anyPointer_Future struct{ *capnp.Future } + +func (f Type_anyPointer_Future) Struct() (Type_anyPointer, error) { + p, err := f.Future.Ptr() + return Type_anyPointer(p.Struct()), err +} +func (p Type_anyPointer_Future) Unconstrained() Type_anyPointer_unconstrained_Future { + return Type_anyPointer_unconstrained_Future{p.Future} +} + +// Type_anyPointer_unconstrained_Future is a wrapper for a Type_anyPointer_unconstrained promised by a client call. +type Type_anyPointer_unconstrained_Future struct{ *capnp.Future } + +func (f Type_anyPointer_unconstrained_Future) Struct() (Type_anyPointer_unconstrained, error) { + p, err := f.Future.Ptr() + return Type_anyPointer_unconstrained(p.Struct()), err +} +func (p Type_anyPointer_Future) Parameter() Type_anyPointer_parameter_Future { + return Type_anyPointer_parameter_Future{p.Future} +} + +// Type_anyPointer_parameter_Future is a wrapper for a Type_anyPointer_parameter promised by a client call. +type Type_anyPointer_parameter_Future struct{ *capnp.Future } + +func (f Type_anyPointer_parameter_Future) Struct() (Type_anyPointer_parameter, error) { + p, err := f.Future.Ptr() + return Type_anyPointer_parameter(p.Struct()), err +} +func (p Type_anyPointer_Future) ImplicitMethodParameter() Type_anyPointer_implicitMethodParameter_Future { + return Type_anyPointer_implicitMethodParameter_Future{p.Future} +} + +// Type_anyPointer_implicitMethodParameter_Future is a wrapper for a Type_anyPointer_implicitMethodParameter promised by a client call. +type Type_anyPointer_implicitMethodParameter_Future struct{ *capnp.Future } + +func (f Type_anyPointer_implicitMethodParameter_Future) Struct() (Type_anyPointer_implicitMethodParameter, error) { + p, err := f.Future.Ptr() + return Type_anyPointer_implicitMethodParameter(p.Struct()), err +} + +type Brand capnp.Struct + +// Brand_TypeID is the unique identifier for the type Brand. +const Brand_TypeID = 0x903455f06065422b + +func NewBrand(s *capnp.Segment) (Brand, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Brand(st), err +} + +func NewRootBrand(s *capnp.Segment) (Brand, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Brand(st), err +} + +func ReadRootBrand(msg *capnp.Message) (Brand, error) { + root, err := msg.Root() + return Brand(root.Struct()), err +} + +func (s Brand) String() string { + str, _ := text.Marshal(0x903455f06065422b, capnp.Struct(s)) + return str +} + +func (s Brand) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Brand) DecodeFromPtr(p capnp.Ptr) Brand { + return Brand(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Brand) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Brand) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Brand) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Brand) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Brand) Scopes() (Brand_Scope_List, error) { + p, err := capnp.Struct(s).Ptr(0) + return Brand_Scope_List(p.List()), err +} + +func (s Brand) HasScopes() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Brand) SetScopes(v Brand_Scope_List) error { + return capnp.Struct(s).SetPtr(0, v.ToPtr()) +} + +// NewScopes sets the scopes field to a newly +// allocated Brand_Scope_List, preferring placement in s's segment. +func (s Brand) NewScopes(n int32) (Brand_Scope_List, error) { + l, err := NewBrand_Scope_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Brand_Scope_List{}, err + } + err = capnp.Struct(s).SetPtr(0, l.ToPtr()) + return l, err +} + +// Brand_List is a list of Brand. +type Brand_List = capnp.StructList[Brand] + +// NewBrand creates a new list of Brand. +func NewBrand_List(s *capnp.Segment, sz int32) (Brand_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return capnp.StructList[Brand](l), err +} + +// Brand_Future is a wrapper for a Brand promised by a client call. +type Brand_Future struct{ *capnp.Future } + +func (f Brand_Future) Struct() (Brand, error) { + p, err := f.Future.Ptr() + return Brand(p.Struct()), err +} + +type Brand_Scope capnp.Struct +type Brand_Scope_Which uint16 + +const ( + Brand_Scope_Which_bind Brand_Scope_Which = 0 + Brand_Scope_Which_inherit Brand_Scope_Which = 1 +) + +func (w Brand_Scope_Which) String() string { + const s = "bindinherit" + switch w { + case Brand_Scope_Which_bind: + return s[0:4] + case Brand_Scope_Which_inherit: + return s[4:11] + + } + return "Brand_Scope_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Brand_Scope_TypeID is the unique identifier for the type Brand_Scope. +const Brand_Scope_TypeID = 0xabd73485a9636bc9 + +func NewBrand_Scope(s *capnp.Segment) (Brand_Scope, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Brand_Scope(st), err +} + +func NewRootBrand_Scope(s *capnp.Segment) (Brand_Scope, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Brand_Scope(st), err +} + +func ReadRootBrand_Scope(msg *capnp.Message) (Brand_Scope, error) { + root, err := msg.Root() + return Brand_Scope(root.Struct()), err +} + +func (s Brand_Scope) String() string { + str, _ := text.Marshal(0xabd73485a9636bc9, capnp.Struct(s)) + return str +} + +func (s Brand_Scope) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Brand_Scope) DecodeFromPtr(p capnp.Ptr) Brand_Scope { + return Brand_Scope(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Brand_Scope) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Brand_Scope) Which() Brand_Scope_Which { + return Brand_Scope_Which(capnp.Struct(s).Uint16(8)) +} +func (s Brand_Scope) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Brand_Scope) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Brand_Scope) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Brand_Scope) ScopeId() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s Brand_Scope) SetScopeId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +func (s Brand_Scope) Bind() (Brand_Binding_List, error) { + if capnp.Struct(s).Uint16(8) != 0 { + panic("Which() != bind") + } + p, err := capnp.Struct(s).Ptr(0) + return Brand_Binding_List(p.List()), err +} + +func (s Brand_Scope) HasBind() bool { + if capnp.Struct(s).Uint16(8) != 0 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Brand_Scope) SetBind(v Brand_Binding_List) error { + capnp.Struct(s).SetUint16(8, 0) + return capnp.Struct(s).SetPtr(0, v.ToPtr()) +} + +// NewBind sets the bind field to a newly +// allocated Brand_Binding_List, preferring placement in s's segment. +func (s Brand_Scope) NewBind(n int32) (Brand_Binding_List, error) { + capnp.Struct(s).SetUint16(8, 0) + l, err := NewBrand_Binding_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Brand_Binding_List{}, err + } + err = capnp.Struct(s).SetPtr(0, l.ToPtr()) + return l, err +} +func (s Brand_Scope) SetInherit() { + capnp.Struct(s).SetUint16(8, 1) + +} + +// Brand_Scope_List is a list of Brand_Scope. +type Brand_Scope_List = capnp.StructList[Brand_Scope] + +// NewBrand_Scope creates a new list of Brand_Scope. +func NewBrand_Scope_List(s *capnp.Segment, sz int32) (Brand_Scope_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}, sz) + return capnp.StructList[Brand_Scope](l), err +} + +// Brand_Scope_Future is a wrapper for a Brand_Scope promised by a client call. +type Brand_Scope_Future struct{ *capnp.Future } + +func (f Brand_Scope_Future) Struct() (Brand_Scope, error) { + p, err := f.Future.Ptr() + return Brand_Scope(p.Struct()), err +} + +type Brand_Binding capnp.Struct +type Brand_Binding_Which uint16 + +const ( + Brand_Binding_Which_unbound Brand_Binding_Which = 0 + Brand_Binding_Which_type Brand_Binding_Which = 1 +) + +func (w Brand_Binding_Which) String() string { + const s = "unboundtype" + switch w { + case Brand_Binding_Which_unbound: + return s[0:7] + case Brand_Binding_Which_type: + return s[7:11] + + } + return "Brand_Binding_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Brand_Binding_TypeID is the unique identifier for the type Brand_Binding. +const Brand_Binding_TypeID = 0xc863cd16969ee7fc + +func NewBrand_Binding(s *capnp.Segment) (Brand_Binding, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Brand_Binding(st), err +} + +func NewRootBrand_Binding(s *capnp.Segment) (Brand_Binding, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Brand_Binding(st), err +} + +func ReadRootBrand_Binding(msg *capnp.Message) (Brand_Binding, error) { + root, err := msg.Root() + return Brand_Binding(root.Struct()), err +} + +func (s Brand_Binding) String() string { + str, _ := text.Marshal(0xc863cd16969ee7fc, capnp.Struct(s)) + return str +} + +func (s Brand_Binding) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Brand_Binding) DecodeFromPtr(p capnp.Ptr) Brand_Binding { + return Brand_Binding(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Brand_Binding) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Brand_Binding) Which() Brand_Binding_Which { + return Brand_Binding_Which(capnp.Struct(s).Uint16(0)) +} +func (s Brand_Binding) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Brand_Binding) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Brand_Binding) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Brand_Binding) SetUnbound() { + capnp.Struct(s).SetUint16(0, 0) + +} + +func (s Brand_Binding) Type() (Type, error) { + if capnp.Struct(s).Uint16(0) != 1 { + panic("Which() != type") + } + p, err := capnp.Struct(s).Ptr(0) + return Type(p.Struct()), err +} + +func (s Brand_Binding) HasType() bool { + if capnp.Struct(s).Uint16(0) != 1 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Brand_Binding) SetType(v Type) error { + capnp.Struct(s).SetUint16(0, 1) + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewType sets the type field to a newly +// allocated Type struct, preferring placement in s's segment. +func (s Brand_Binding) NewType() (Type, error) { + capnp.Struct(s).SetUint16(0, 1) + ss, err := NewType(capnp.Struct(s).Segment()) + if err != nil { + return Type{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// Brand_Binding_List is a list of Brand_Binding. +type Brand_Binding_List = capnp.StructList[Brand_Binding] + +// NewBrand_Binding creates a new list of Brand_Binding. +func NewBrand_Binding_List(s *capnp.Segment, sz int32) (Brand_Binding_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[Brand_Binding](l), err +} + +// Brand_Binding_Future is a wrapper for a Brand_Binding promised by a client call. +type Brand_Binding_Future struct{ *capnp.Future } + +func (f Brand_Binding_Future) Struct() (Brand_Binding, error) { + p, err := f.Future.Ptr() + return Brand_Binding(p.Struct()), err +} +func (p Brand_Binding_Future) Type() Type_Future { + return Type_Future{Future: p.Future.Field(0, nil)} +} + +type Value capnp.Struct +type Value_Which uint16 + +const ( + Value_Which_void Value_Which = 0 + Value_Which_bool Value_Which = 1 + Value_Which_int8 Value_Which = 2 + Value_Which_int16 Value_Which = 3 + Value_Which_int32 Value_Which = 4 + Value_Which_int64 Value_Which = 5 + Value_Which_uint8 Value_Which = 6 + Value_Which_uint16 Value_Which = 7 + Value_Which_uint32 Value_Which = 8 + Value_Which_uint64 Value_Which = 9 + Value_Which_float32 Value_Which = 10 + Value_Which_float64 Value_Which = 11 + Value_Which_text Value_Which = 12 + Value_Which_data Value_Which = 13 + Value_Which_list Value_Which = 14 + Value_Which_enum Value_Which = 15 + Value_Which_structValue Value_Which = 16 + Value_Which_interface Value_Which = 17 + Value_Which_anyPointer Value_Which = 18 +) + +func (w Value_Which) String() string { + const s = "voidboolint8int16int32int64uint8uint16uint32uint64float32float64textdatalistenumstructValueinterfaceanyPointer" + switch w { + case Value_Which_void: + return s[0:4] + case Value_Which_bool: + return s[4:8] + case Value_Which_int8: + return s[8:12] + case Value_Which_int16: + return s[12:17] + case Value_Which_int32: + return s[17:22] + case Value_Which_int64: + return s[22:27] + case Value_Which_uint8: + return s[27:32] + case Value_Which_uint16: + return s[32:38] + case Value_Which_uint32: + return s[38:44] + case Value_Which_uint64: + return s[44:50] + case Value_Which_float32: + return s[50:57] + case Value_Which_float64: + return s[57:64] + case Value_Which_text: + return s[64:68] + case Value_Which_data: + return s[68:72] + case Value_Which_list: + return s[72:76] + case Value_Which_enum: + return s[76:80] + case Value_Which_structValue: + return s[80:91] + case Value_Which_interface: + return s[91:100] + case Value_Which_anyPointer: + return s[100:110] + + } + return "Value_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Value_TypeID is the unique identifier for the type Value. +const Value_TypeID = 0xce23dcd2d7b00c9b + +func NewValue(s *capnp.Segment) (Value, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Value(st), err +} + +func NewRootValue(s *capnp.Segment) (Value, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}) + return Value(st), err +} + +func ReadRootValue(msg *capnp.Message) (Value, error) { + root, err := msg.Root() + return Value(root.Struct()), err +} + +func (s Value) String() string { + str, _ := text.Marshal(0xce23dcd2d7b00c9b, capnp.Struct(s)) + return str +} + +func (s Value) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Value) DecodeFromPtr(p capnp.Ptr) Value { + return Value(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Value) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} + +func (s Value) Which() Value_Which { + return Value_Which(capnp.Struct(s).Uint16(0)) +} +func (s Value) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Value) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Value) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Value) SetVoid() { + capnp.Struct(s).SetUint16(0, 0) + +} + +func (s Value) Bool() bool { + if capnp.Struct(s).Uint16(0) != 1 { + panic("Which() != bool") + } + return capnp.Struct(s).Bit(16) +} + +func (s Value) SetBool(v bool) { + capnp.Struct(s).SetUint16(0, 1) + capnp.Struct(s).SetBit(16, v) +} + +func (s Value) Int8() int8 { + if capnp.Struct(s).Uint16(0) != 2 { + panic("Which() != int8") + } + return int8(capnp.Struct(s).Uint8(2)) +} + +func (s Value) SetInt8(v int8) { + capnp.Struct(s).SetUint16(0, 2) + capnp.Struct(s).SetUint8(2, uint8(v)) +} + +func (s Value) Int16() int16 { + if capnp.Struct(s).Uint16(0) != 3 { + panic("Which() != int16") + } + return int16(capnp.Struct(s).Uint16(2)) +} + +func (s Value) SetInt16(v int16) { + capnp.Struct(s).SetUint16(0, 3) + capnp.Struct(s).SetUint16(2, uint16(v)) +} + +func (s Value) Int32() int32 { + if capnp.Struct(s).Uint16(0) != 4 { + panic("Which() != int32") + } + return int32(capnp.Struct(s).Uint32(4)) +} + +func (s Value) SetInt32(v int32) { + capnp.Struct(s).SetUint16(0, 4) + capnp.Struct(s).SetUint32(4, uint32(v)) +} + +func (s Value) Int64() int64 { + if capnp.Struct(s).Uint16(0) != 5 { + panic("Which() != int64") + } + return int64(capnp.Struct(s).Uint64(8)) +} + +func (s Value) SetInt64(v int64) { + capnp.Struct(s).SetUint16(0, 5) + capnp.Struct(s).SetUint64(8, uint64(v)) +} + +func (s Value) Uint8() uint8 { + if capnp.Struct(s).Uint16(0) != 6 { + panic("Which() != uint8") + } + return capnp.Struct(s).Uint8(2) +} + +func (s Value) SetUint8(v uint8) { + capnp.Struct(s).SetUint16(0, 6) + capnp.Struct(s).SetUint8(2, v) +} + +func (s Value) Uint16() uint16 { + if capnp.Struct(s).Uint16(0) != 7 { + panic("Which() != uint16") + } + return capnp.Struct(s).Uint16(2) +} + +func (s Value) SetUint16(v uint16) { + capnp.Struct(s).SetUint16(0, 7) + capnp.Struct(s).SetUint16(2, v) +} + +func (s Value) Uint32() uint32 { + if capnp.Struct(s).Uint16(0) != 8 { + panic("Which() != uint32") + } + return capnp.Struct(s).Uint32(4) +} + +func (s Value) SetUint32(v uint32) { + capnp.Struct(s).SetUint16(0, 8) + capnp.Struct(s).SetUint32(4, v) +} + +func (s Value) Uint64() uint64 { + if capnp.Struct(s).Uint16(0) != 9 { + panic("Which() != uint64") + } + return capnp.Struct(s).Uint64(8) +} + +func (s Value) SetUint64(v uint64) { + capnp.Struct(s).SetUint16(0, 9) + capnp.Struct(s).SetUint64(8, v) +} + +func (s Value) Float32() float32 { + if capnp.Struct(s).Uint16(0) != 10 { + panic("Which() != float32") + } + return math.Float32frombits(capnp.Struct(s).Uint32(4)) +} + +func (s Value) SetFloat32(v float32) { + capnp.Struct(s).SetUint16(0, 10) + capnp.Struct(s).SetUint32(4, math.Float32bits(v)) +} + +func (s Value) Float64() float64 { + if capnp.Struct(s).Uint16(0) != 11 { + panic("Which() != float64") + } + return math.Float64frombits(capnp.Struct(s).Uint64(8)) +} + +func (s Value) SetFloat64(v float64) { + capnp.Struct(s).SetUint16(0, 11) + capnp.Struct(s).SetUint64(8, math.Float64bits(v)) +} + +func (s Value) Text() (string, error) { + if capnp.Struct(s).Uint16(0) != 12 { + panic("Which() != text") + } + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s Value) HasText() bool { + if capnp.Struct(s).Uint16(0) != 12 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) TextBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s Value) SetText(v string) error { + capnp.Struct(s).SetUint16(0, 12) + return capnp.Struct(s).SetText(0, v) +} + +func (s Value) Data() ([]byte, error) { + if capnp.Struct(s).Uint16(0) != 13 { + panic("Which() != data") + } + p, err := capnp.Struct(s).Ptr(0) + return []byte(p.Data()), err +} + +func (s Value) HasData() bool { + if capnp.Struct(s).Uint16(0) != 13 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) SetData(v []byte) error { + capnp.Struct(s).SetUint16(0, 13) + return capnp.Struct(s).SetData(0, v) +} + +func (s Value) List() (capnp.Ptr, error) { + if capnp.Struct(s).Uint16(0) != 14 { + panic("Which() != list") + } + return capnp.Struct(s).Ptr(0) +} + +func (s Value) HasList() bool { + if capnp.Struct(s).Uint16(0) != 14 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) SetList(v capnp.Ptr) error { + capnp.Struct(s).SetUint16(0, 14) + return capnp.Struct(s).SetPtr(0, v) +} +func (s Value) Enum() uint16 { + if capnp.Struct(s).Uint16(0) != 15 { + panic("Which() != enum") + } + return capnp.Struct(s).Uint16(2) +} + +func (s Value) SetEnum(v uint16) { + capnp.Struct(s).SetUint16(0, 15) + capnp.Struct(s).SetUint16(2, v) +} + +func (s Value) StructValue() (capnp.Ptr, error) { + if capnp.Struct(s).Uint16(0) != 16 { + panic("Which() != structValue") + } + return capnp.Struct(s).Ptr(0) +} + +func (s Value) HasStructValue() bool { + if capnp.Struct(s).Uint16(0) != 16 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) SetStructValue(v capnp.Ptr) error { + capnp.Struct(s).SetUint16(0, 16) + return capnp.Struct(s).SetPtr(0, v) +} +func (s Value) SetInterface() { + capnp.Struct(s).SetUint16(0, 17) + +} + +func (s Value) AnyPointer() (capnp.Ptr, error) { + if capnp.Struct(s).Uint16(0) != 18 { + panic("Which() != anyPointer") + } + return capnp.Struct(s).Ptr(0) +} + +func (s Value) HasAnyPointer() bool { + if capnp.Struct(s).Uint16(0) != 18 { + return false + } + return capnp.Struct(s).HasPtr(0) +} + +func (s Value) SetAnyPointer(v capnp.Ptr) error { + capnp.Struct(s).SetUint16(0, 18) + return capnp.Struct(s).SetPtr(0, v) +} + +// Value_List is a list of Value. +type Value_List = capnp.StructList[Value] + +// NewValue creates a new list of Value. +func NewValue_List(s *capnp.Segment, sz int32) (Value_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 16, PointerCount: 1}, sz) + return capnp.StructList[Value](l), err +} + +// Value_Future is a wrapper for a Value promised by a client call. +type Value_Future struct{ *capnp.Future } + +func (f Value_Future) Struct() (Value, error) { + p, err := f.Future.Ptr() + return Value(p.Struct()), err +} +func (p Value_Future) List() *capnp.Future { + return p.Future.Field(0, nil) +} +func (p Value_Future) StructValue() *capnp.Future { + return p.Future.Field(0, nil) +} +func (p Value_Future) AnyPointer() *capnp.Future { + return p.Future.Field(0, nil) +} + +type Annotation capnp.Struct + +// Annotation_TypeID is the unique identifier for the type Annotation. +const Annotation_TypeID = 0xf1c8950dab257542 + +func NewAnnotation(s *capnp.Segment) (Annotation, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Annotation(st), err +} + +func NewRootAnnotation(s *capnp.Segment) (Annotation, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return Annotation(st), err +} + +func ReadRootAnnotation(msg *capnp.Message) (Annotation, error) { + root, err := msg.Root() + return Annotation(root.Struct()), err +} + +func (s Annotation) String() string { + str, _ := text.Marshal(0xf1c8950dab257542, capnp.Struct(s)) + return str +} + +func (s Annotation) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (Annotation) DecodeFromPtr(p capnp.Ptr) Annotation { + return Annotation(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s Annotation) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s Annotation) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s Annotation) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s Annotation) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s Annotation) Id() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s Annotation) SetId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +func (s Annotation) Brand() (Brand, error) { + p, err := capnp.Struct(s).Ptr(1) + return Brand(p.Struct()), err +} + +func (s Annotation) HasBrand() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s Annotation) SetBrand(v Brand) error { + return capnp.Struct(s).SetPtr(1, capnp.Struct(v).ToPtr()) +} + +// NewBrand sets the brand field to a newly +// allocated Brand struct, preferring placement in s's segment. +func (s Annotation) NewBrand() (Brand, error) { + ss, err := NewBrand(capnp.Struct(s).Segment()) + if err != nil { + return Brand{}, err + } + err = capnp.Struct(s).SetPtr(1, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s Annotation) Value() (Value, error) { + p, err := capnp.Struct(s).Ptr(0) + return Value(p.Struct()), err +} + +func (s Annotation) HasValue() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s Annotation) SetValue(v Value) error { + return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) +} + +// NewValue sets the value field to a newly +// allocated Value struct, preferring placement in s's segment. +func (s Annotation) NewValue() (Value, error) { + ss, err := NewValue(capnp.Struct(s).Segment()) + if err != nil { + return Value{}, err + } + err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// Annotation_List is a list of Annotation. +type Annotation_List = capnp.StructList[Annotation] + +// NewAnnotation creates a new list of Annotation. +func NewAnnotation_List(s *capnp.Segment, sz int32) (Annotation_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) + return capnp.StructList[Annotation](l), err +} + +// Annotation_Future is a wrapper for a Annotation promised by a client call. +type Annotation_Future struct{ *capnp.Future } + +func (f Annotation_Future) Struct() (Annotation, error) { + p, err := f.Future.Ptr() + return Annotation(p.Struct()), err +} +func (p Annotation_Future) Brand() Brand_Future { + return Brand_Future{Future: p.Future.Field(1, nil)} +} +func (p Annotation_Future) Value() Value_Future { + return Value_Future{Future: p.Future.Field(0, nil)} +} + +type ElementSize uint16 + +// ElementSize_TypeID is the unique identifier for the type ElementSize. +const ElementSize_TypeID = 0xd1958f7dba521926 + +// Values of ElementSize. +const ( + ElementSize_empty ElementSize = 0 + ElementSize_bit ElementSize = 1 + ElementSize_byte ElementSize = 2 + ElementSize_twoBytes ElementSize = 3 + ElementSize_fourBytes ElementSize = 4 + ElementSize_eightBytes ElementSize = 5 + ElementSize_pointer ElementSize = 6 + ElementSize_inlineComposite ElementSize = 7 +) + +// String returns the enum's constant name. +func (c ElementSize) String() string { + switch c { + case ElementSize_empty: + return "empty" + case ElementSize_bit: + return "bit" + case ElementSize_byte: + return "byte" + case ElementSize_twoBytes: + return "twoBytes" + case ElementSize_fourBytes: + return "fourBytes" + case ElementSize_eightBytes: + return "eightBytes" + case ElementSize_pointer: + return "pointer" + case ElementSize_inlineComposite: + return "inlineComposite" + + default: + return "" + } +} + +// ElementSizeFromString returns the enum value with a name, +// or the zero value if there's no such value. +func ElementSizeFromString(c string) ElementSize { + switch c { + case "empty": + return ElementSize_empty + case "bit": + return ElementSize_bit + case "byte": + return ElementSize_byte + case "twoBytes": + return ElementSize_twoBytes + case "fourBytes": + return ElementSize_fourBytes + case "eightBytes": + return ElementSize_eightBytes + case "pointer": + return ElementSize_pointer + case "inlineComposite": + return ElementSize_inlineComposite + + default: + return 0 + } +} + +type ElementSize_List = capnp.EnumList[ElementSize] + +func NewElementSize_List(s *capnp.Segment, sz int32) (ElementSize_List, error) { + return capnp.NewEnumList[ElementSize](s, sz) +} + +type CapnpVersion capnp.Struct + +// CapnpVersion_TypeID is the unique identifier for the type CapnpVersion. +const CapnpVersion_TypeID = 0xd85d305b7d839963 + +func NewCapnpVersion(s *capnp.Segment) (CapnpVersion, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return CapnpVersion(st), err +} + +func NewRootCapnpVersion(s *capnp.Segment) (CapnpVersion, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return CapnpVersion(st), err +} + +func ReadRootCapnpVersion(msg *capnp.Message) (CapnpVersion, error) { + root, err := msg.Root() + return CapnpVersion(root.Struct()), err +} + +func (s CapnpVersion) String() string { + str, _ := text.Marshal(0xd85d305b7d839963, capnp.Struct(s)) + return str +} + +func (s CapnpVersion) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (CapnpVersion) DecodeFromPtr(p capnp.Ptr) CapnpVersion { + return CapnpVersion(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s CapnpVersion) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s CapnpVersion) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s CapnpVersion) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s CapnpVersion) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s CapnpVersion) Major() uint16 { + return capnp.Struct(s).Uint16(0) +} + +func (s CapnpVersion) SetMajor(v uint16) { + capnp.Struct(s).SetUint16(0, v) +} + +func (s CapnpVersion) Minor() uint8 { + return capnp.Struct(s).Uint8(2) +} + +func (s CapnpVersion) SetMinor(v uint8) { + capnp.Struct(s).SetUint8(2, v) +} + +func (s CapnpVersion) Micro() uint8 { + return capnp.Struct(s).Uint8(3) +} + +func (s CapnpVersion) SetMicro(v uint8) { + capnp.Struct(s).SetUint8(3, v) +} + +// CapnpVersion_List is a list of CapnpVersion. +type CapnpVersion_List = capnp.StructList[CapnpVersion] + +// NewCapnpVersion creates a new list of CapnpVersion. +func NewCapnpVersion_List(s *capnp.Segment, sz int32) (CapnpVersion_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[CapnpVersion](l), err +} + +// CapnpVersion_Future is a wrapper for a CapnpVersion promised by a client call. +type CapnpVersion_Future struct{ *capnp.Future } + +func (f CapnpVersion_Future) Struct() (CapnpVersion, error) { + p, err := f.Future.Ptr() + return CapnpVersion(p.Struct()), err +} + +type CodeGeneratorRequest capnp.Struct + +// CodeGeneratorRequest_TypeID is the unique identifier for the type CodeGeneratorRequest. +const CodeGeneratorRequest_TypeID = 0xbfc546f6210ad7ce + +func NewCodeGeneratorRequest(s *capnp.Segment) (CodeGeneratorRequest, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 4}) + return CodeGeneratorRequest(st), err +} + +func NewRootCodeGeneratorRequest(s *capnp.Segment) (CodeGeneratorRequest, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 4}) + return CodeGeneratorRequest(st), err +} + +func ReadRootCodeGeneratorRequest(msg *capnp.Message) (CodeGeneratorRequest, error) { + root, err := msg.Root() + return CodeGeneratorRequest(root.Struct()), err +} + +func (s CodeGeneratorRequest) String() string { + str, _ := text.Marshal(0xbfc546f6210ad7ce, capnp.Struct(s)) + return str +} + +func (s CodeGeneratorRequest) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (CodeGeneratorRequest) DecodeFromPtr(p capnp.Ptr) CodeGeneratorRequest { + return CodeGeneratorRequest(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s CodeGeneratorRequest) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s CodeGeneratorRequest) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s CodeGeneratorRequest) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s CodeGeneratorRequest) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s CodeGeneratorRequest) CapnpVersion() (CapnpVersion, error) { + p, err := capnp.Struct(s).Ptr(2) + return CapnpVersion(p.Struct()), err +} + +func (s CodeGeneratorRequest) HasCapnpVersion() bool { + return capnp.Struct(s).HasPtr(2) +} + +func (s CodeGeneratorRequest) SetCapnpVersion(v CapnpVersion) error { + return capnp.Struct(s).SetPtr(2, capnp.Struct(v).ToPtr()) +} + +// NewCapnpVersion sets the capnpVersion field to a newly +// allocated CapnpVersion struct, preferring placement in s's segment. +func (s CodeGeneratorRequest) NewCapnpVersion() (CapnpVersion, error) { + ss, err := NewCapnpVersion(capnp.Struct(s).Segment()) + if err != nil { + return CapnpVersion{}, err + } + err = capnp.Struct(s).SetPtr(2, capnp.Struct(ss).ToPtr()) + return ss, err +} + +func (s CodeGeneratorRequest) Nodes() (Node_List, error) { + p, err := capnp.Struct(s).Ptr(0) + return Node_List(p.List()), err +} + +func (s CodeGeneratorRequest) HasNodes() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s CodeGeneratorRequest) SetNodes(v Node_List) error { + return capnp.Struct(s).SetPtr(0, v.ToPtr()) +} + +// NewNodes sets the nodes field to a newly +// allocated Node_List, preferring placement in s's segment. +func (s CodeGeneratorRequest) NewNodes(n int32) (Node_List, error) { + l, err := NewNode_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Node_List{}, err + } + err = capnp.Struct(s).SetPtr(0, l.ToPtr()) + return l, err +} +func (s CodeGeneratorRequest) SourceInfo() (Node_SourceInfo_List, error) { + p, err := capnp.Struct(s).Ptr(3) + return Node_SourceInfo_List(p.List()), err +} + +func (s CodeGeneratorRequest) HasSourceInfo() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s CodeGeneratorRequest) SetSourceInfo(v Node_SourceInfo_List) error { + return capnp.Struct(s).SetPtr(3, v.ToPtr()) +} + +// NewSourceInfo sets the sourceInfo field to a newly +// allocated Node_SourceInfo_List, preferring placement in s's segment. +func (s CodeGeneratorRequest) NewSourceInfo(n int32) (Node_SourceInfo_List, error) { + l, err := NewNode_SourceInfo_List(capnp.Struct(s).Segment(), n) + if err != nil { + return Node_SourceInfo_List{}, err + } + err = capnp.Struct(s).SetPtr(3, l.ToPtr()) + return l, err +} +func (s CodeGeneratorRequest) RequestedFiles() (CodeGeneratorRequest_RequestedFile_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return CodeGeneratorRequest_RequestedFile_List(p.List()), err +} + +func (s CodeGeneratorRequest) HasRequestedFiles() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s CodeGeneratorRequest) SetRequestedFiles(v CodeGeneratorRequest_RequestedFile_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewRequestedFiles sets the requestedFiles field to a newly +// allocated CodeGeneratorRequest_RequestedFile_List, preferring placement in s's segment. +func (s CodeGeneratorRequest) NewRequestedFiles(n int32) (CodeGeneratorRequest_RequestedFile_List, error) { + l, err := NewCodeGeneratorRequest_RequestedFile_List(capnp.Struct(s).Segment(), n) + if err != nil { + return CodeGeneratorRequest_RequestedFile_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} + +// CodeGeneratorRequest_List is a list of CodeGeneratorRequest. +type CodeGeneratorRequest_List = capnp.StructList[CodeGeneratorRequest] + +// NewCodeGeneratorRequest creates a new list of CodeGeneratorRequest. +func NewCodeGeneratorRequest_List(s *capnp.Segment, sz int32) (CodeGeneratorRequest_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 4}, sz) + return capnp.StructList[CodeGeneratorRequest](l), err +} + +// CodeGeneratorRequest_Future is a wrapper for a CodeGeneratorRequest promised by a client call. +type CodeGeneratorRequest_Future struct{ *capnp.Future } + +func (f CodeGeneratorRequest_Future) Struct() (CodeGeneratorRequest, error) { + p, err := f.Future.Ptr() + return CodeGeneratorRequest(p.Struct()), err +} +func (p CodeGeneratorRequest_Future) CapnpVersion() CapnpVersion_Future { + return CapnpVersion_Future{Future: p.Future.Field(2, nil)} +} + +type CodeGeneratorRequest_RequestedFile capnp.Struct + +// CodeGeneratorRequest_RequestedFile_TypeID is the unique identifier for the type CodeGeneratorRequest_RequestedFile. +const CodeGeneratorRequest_RequestedFile_TypeID = 0xcfea0eb02e810062 + +func NewCodeGeneratorRequest_RequestedFile(s *capnp.Segment) (CodeGeneratorRequest_RequestedFile, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return CodeGeneratorRequest_RequestedFile(st), err +} + +func NewRootCodeGeneratorRequest_RequestedFile(s *capnp.Segment) (CodeGeneratorRequest_RequestedFile, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) + return CodeGeneratorRequest_RequestedFile(st), err +} + +func ReadRootCodeGeneratorRequest_RequestedFile(msg *capnp.Message) (CodeGeneratorRequest_RequestedFile, error) { + root, err := msg.Root() + return CodeGeneratorRequest_RequestedFile(root.Struct()), err +} + +func (s CodeGeneratorRequest_RequestedFile) String() string { + str, _ := text.Marshal(0xcfea0eb02e810062, capnp.Struct(s)) + return str +} + +func (s CodeGeneratorRequest_RequestedFile) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (CodeGeneratorRequest_RequestedFile) DecodeFromPtr(p capnp.Ptr) CodeGeneratorRequest_RequestedFile { + return CodeGeneratorRequest_RequestedFile(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s CodeGeneratorRequest_RequestedFile) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s CodeGeneratorRequest_RequestedFile) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s CodeGeneratorRequest_RequestedFile) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s CodeGeneratorRequest_RequestedFile) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s CodeGeneratorRequest_RequestedFile) Id() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s CodeGeneratorRequest_RequestedFile) SetId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +func (s CodeGeneratorRequest_RequestedFile) Filename() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s CodeGeneratorRequest_RequestedFile) HasFilename() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s CodeGeneratorRequest_RequestedFile) FilenameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s CodeGeneratorRequest_RequestedFile) SetFilename(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +func (s CodeGeneratorRequest_RequestedFile) Imports() (CodeGeneratorRequest_RequestedFile_Import_List, error) { + p, err := capnp.Struct(s).Ptr(1) + return CodeGeneratorRequest_RequestedFile_Import_List(p.List()), err +} + +func (s CodeGeneratorRequest_RequestedFile) HasImports() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s CodeGeneratorRequest_RequestedFile) SetImports(v CodeGeneratorRequest_RequestedFile_Import_List) error { + return capnp.Struct(s).SetPtr(1, v.ToPtr()) +} + +// NewImports sets the imports field to a newly +// allocated CodeGeneratorRequest_RequestedFile_Import_List, preferring placement in s's segment. +func (s CodeGeneratorRequest_RequestedFile) NewImports(n int32) (CodeGeneratorRequest_RequestedFile_Import_List, error) { + l, err := NewCodeGeneratorRequest_RequestedFile_Import_List(capnp.Struct(s).Segment(), n) + if err != nil { + return CodeGeneratorRequest_RequestedFile_Import_List{}, err + } + err = capnp.Struct(s).SetPtr(1, l.ToPtr()) + return l, err +} + +// CodeGeneratorRequest_RequestedFile_List is a list of CodeGeneratorRequest_RequestedFile. +type CodeGeneratorRequest_RequestedFile_List = capnp.StructList[CodeGeneratorRequest_RequestedFile] + +// NewCodeGeneratorRequest_RequestedFile creates a new list of CodeGeneratorRequest_RequestedFile. +func NewCodeGeneratorRequest_RequestedFile_List(s *capnp.Segment, sz int32) (CodeGeneratorRequest_RequestedFile_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) + return capnp.StructList[CodeGeneratorRequest_RequestedFile](l), err +} + +// CodeGeneratorRequest_RequestedFile_Future is a wrapper for a CodeGeneratorRequest_RequestedFile promised by a client call. +type CodeGeneratorRequest_RequestedFile_Future struct{ *capnp.Future } + +func (f CodeGeneratorRequest_RequestedFile_Future) Struct() (CodeGeneratorRequest_RequestedFile, error) { + p, err := f.Future.Ptr() + return CodeGeneratorRequest_RequestedFile(p.Struct()), err +} + +type CodeGeneratorRequest_RequestedFile_Import capnp.Struct + +// CodeGeneratorRequest_RequestedFile_Import_TypeID is the unique identifier for the type CodeGeneratorRequest_RequestedFile_Import. +const CodeGeneratorRequest_RequestedFile_Import_TypeID = 0xae504193122357e5 + +func NewCodeGeneratorRequest_RequestedFile_Import(s *capnp.Segment) (CodeGeneratorRequest_RequestedFile_Import, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return CodeGeneratorRequest_RequestedFile_Import(st), err +} + +func NewRootCodeGeneratorRequest_RequestedFile_Import(s *capnp.Segment) (CodeGeneratorRequest_RequestedFile_Import, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return CodeGeneratorRequest_RequestedFile_Import(st), err +} + +func ReadRootCodeGeneratorRequest_RequestedFile_Import(msg *capnp.Message) (CodeGeneratorRequest_RequestedFile_Import, error) { + root, err := msg.Root() + return CodeGeneratorRequest_RequestedFile_Import(root.Struct()), err +} + +func (s CodeGeneratorRequest_RequestedFile_Import) String() string { + str, _ := text.Marshal(0xae504193122357e5, capnp.Struct(s)) + return str +} + +func (s CodeGeneratorRequest_RequestedFile_Import) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (CodeGeneratorRequest_RequestedFile_Import) DecodeFromPtr(p capnp.Ptr) CodeGeneratorRequest_RequestedFile_Import { + return CodeGeneratorRequest_RequestedFile_Import(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s CodeGeneratorRequest_RequestedFile_Import) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s CodeGeneratorRequest_RequestedFile_Import) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s CodeGeneratorRequest_RequestedFile_Import) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s CodeGeneratorRequest_RequestedFile_Import) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} +func (s CodeGeneratorRequest_RequestedFile_Import) Id() uint64 { + return capnp.Struct(s).Uint64(0) +} + +func (s CodeGeneratorRequest_RequestedFile_Import) SetId(v uint64) { + capnp.Struct(s).SetUint64(0, v) +} + +func (s CodeGeneratorRequest_RequestedFile_Import) Name() (string, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.Text(), err +} + +func (s CodeGeneratorRequest_RequestedFile_Import) HasName() bool { + return capnp.Struct(s).HasPtr(0) +} + +func (s CodeGeneratorRequest_RequestedFile_Import) NameBytes() ([]byte, error) { + p, err := capnp.Struct(s).Ptr(0) + return p.TextBytes(), err +} + +func (s CodeGeneratorRequest_RequestedFile_Import) SetName(v string) error { + return capnp.Struct(s).SetText(0, v) +} + +// CodeGeneratorRequest_RequestedFile_Import_List is a list of CodeGeneratorRequest_RequestedFile_Import. +type CodeGeneratorRequest_RequestedFile_Import_List = capnp.StructList[CodeGeneratorRequest_RequestedFile_Import] + +// NewCodeGeneratorRequest_RequestedFile_Import creates a new list of CodeGeneratorRequest_RequestedFile_Import. +func NewCodeGeneratorRequest_RequestedFile_Import_List(s *capnp.Segment, sz int32) (CodeGeneratorRequest_RequestedFile_Import_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return capnp.StructList[CodeGeneratorRequest_RequestedFile_Import](l), err +} + +// CodeGeneratorRequest_RequestedFile_Import_Future is a wrapper for a CodeGeneratorRequest_RequestedFile_Import promised by a client call. +type CodeGeneratorRequest_RequestedFile_Import_Future struct{ *capnp.Future } + +func (f CodeGeneratorRequest_RequestedFile_Import_Future) Struct() (CodeGeneratorRequest_RequestedFile_Import, error) { + p, err := f.Future.Ptr() + return CodeGeneratorRequest_RequestedFile_Import(p.Struct()), err +} + +const schema_a93fc509624c72d9 = "x\xda\xacz{\x90\x1c\xd5u\xf79\xb7\xe7\xb1\xaff" + + "\xb6\xe7\xce\"\x10\xe8\x9b\x15\x92>$\x05\xd6\xd2\xae\x90" + + "\xc5\x1a\xb2h\xc5\x0aK\x91\xf0\xb6F\x08\xd8\x84\xb2z" + + "gz\xb5\x8dg\xbaG==\xa0Q\xa0\x16\x88)l" + + "b@&\xc8`\xd9\xa2l\x02UV\x00[J\xa0\xca" + + "\x92I\x80-\x08\xa0\x02\x1b\x1c(\xc0\x86\xc4\x10c\x88" + + "\x12\x05\x14\xf3\x16\xa8S\xe7vOw\xef\xec,\x8f\x0a" + + "\x7f\xed\xcc9w\xee=\xf7\x9c\xf3;\xaf\xbbK\x8e\xb6" + + "\x9f\x13[*\x9f\x9a\x02\xa6\xee\x8d'\xdc[\x0fmn" + + "[p\xe6\xeb\xd7\x81\x9aF\xc9\xdd\xfc\xe4\x07\xaf\x1c\xde" + + "Vy\x1a\xba0\x89\x00\xbc\x96<\x00\xc8k\xc9\x01@" + + "w\xd3\xf2\x8b\x8f\xd5\xbe\xfe\x95\x1bA\x9d\x83\x92{d" + + "\xcd\x9f\xde\xf1\xc6\xc0\x85\x93p\x01&1\x86\xf1\xbe\xdd" + + "\xc9\x11\x04\xe4{\x92\xaf\x03\xba\x7f2\xa8o~\xeb\x82" + + "e;@\x91\xd1}\xd1^7\xda\xfa\xe8\xc0\x1e\x88c" + + "\x12\x80_\xdd\xb2\x8b\x7f\xbb\xe5T\x00\xbe\xbbe\x00\xf0" + + "\xc1\xab\xd6\xf7}\xe5\xd5'w\xaa2J\x91\xa5qZ" + + "\xfaT\xcb\x1d\xfc\xb9\x96$@\xdf3-\x8f!\xa0\xbb" + + "~\xd7\xc6\x97\xfe\xf3\x8a\xebo\x05U\xc6\xe8\xc6\x8cV" + + "\xbf\xd8v\x80\xbf\xd2F\x9f^n\xfb\x19\xa0\x9b~\xec" + + "\xd8\x15\xff\xb4n\xdf\xad\xa0\xf0\x98\xfb\xf5\xb7\xd7f\xef" + + "\x1c\xbew\x17\x00\xf6\xdd\xd0\x9eF\xbe\xbb=\x09\x90\xbb" + + "\xad]\xc2\xdc\x9d\xed\x0c\x01\xc2%SE\x19\x8a%\x19" + + "\xc6\xf8\xce\xf6]|w\xfb,\x80\xbe=\xed7\x91," + + "\xd7\xae\xd5\xde\x9e\xff\xde3\xbb\x1b\xf4\xe1i\xae\xef\xe3" + + "\x8e~RG\\\xbe\x1c\xd0\xdds\xdd\xc4\xec\xad\xdb\x8e" + + "\xbb\xbd\xb9\x92u\x99\x94\xac\x8b\x95g\x9c{\xf4\xcb?" + + "\xd8\xf7#\xb12\xee\xce\xbas\xde\x07\xeb\xee\xbe\xe6\x0f" + + "\xd0\x95\x10+\x1f\x96\x0f\x02\xf6=*\x8b\xf3\xdf\x7f\xfe" + + "\xce\xa7o_\xfc\xbd=\x8d\xba\x10J\xbe25\xc9\xaf" + + "M\x09u\xa7h\xdf'\xbe\x91\xdfs\xed\xb2\xe7\xef\x06" + + "\x95#\x0b\xcd3\x84\xe2n/\xa7\x0e\xf2\xff\x10\xab_" + + "K\x91\xe6\xfe\xe5\x9f\xd7\xbd\xb9\xd9\xea\xbf\xa7\xb9\xbc7" + + "t\x1e\x04\xe4\xdf\xed\xa4}_\xbbp^\xfaoV\x0e" + + "\xff\x14\xd4%\x88\x1f\x8f^\xdd\xb3\xf7\xb8C\xbf\x12\"" + + "\xf4\x1d\xee<\x80<\xae\xd0\xae\xa8\xd0\xda\xee[\xe4\xed" + + "\xf7\xdcu\xfd\xbe\xe6w\xbbD\x99\x04\xe4\x97\x88\x95\xb7" + + "\xbd\xd3\xb7j\xf9?\xac\xbd\xbf\xf9\xca\xfd\x0a\xe9k\xbf" + + "BN\xb9\xefoSG\x9e\xb7\xe3\x17\xa4.)t\x8c\x0b" + + "bId\x18\xe7k\xd2\xbf\x01\xe4\xeb\xd3$\xeb/\x9f" + + "o\x9b\xfb\xee\xeaG\x1flp\xf5\x18\xa9`_:\x8d" + + "\xfc\xe1\xf4,r\xe54\xe1\"8t\xaab\x09C\x12" + + "\xd9\x81\x1f\x02\xe4\xafp\xb2\xc1\x1d\xd9\x1b\xbf\xbdb\xc7" + + "\x81IP\xe6\xa0\xfb\xd3\x0by\xec\xdf\xe7\xdc\xf8G\xef" + + "f}gdNA>\x94\xa1\xab\xad\xcc\x90\xbc\x96s" + + "\xdf7\xce\x8b\xcf{\xa4A\xde\xae\x98\xe7`\x19R\xad" + + "\x9e!\x09>z\xfd\xf6\xef\x1d\xffT\xfeqZ\x89S" + + "\x1d\x01\x80\x0fu\xfd\x86\xab]\xb4\xef\xfa.\xba\x9c2" + + "\xe7\xb7\xe3\xbf}\xea\xa3\x83\xcd\xf7\xdd\xd3E\x8epo" + + "\x17I\xf0\x83\x8e\xbd\xcf\xff\xfa\xa5y\xbf$od\x11" + + "\xf0`\x92\xd3\xed\xbbv\xf1\xe7\xba\x04\x90\xbb\xbe\x14\x83" + + "\xc0S\xd4S0\xa2A\x01\xe3\xbe\x8bg_\x83\xbc4" + + "\x9b\x94V\x9dM\x9a\x08\xd4\xd4\x80Ko\xeb\xb9'\xdd" + + "\xcc\x17\x9dD?\\p\x12m\xed\xfe\xff\x137\x1c\xb8" + + "\xf2\xa6\x9d\xcf\x80\"G\x04\x01\xe4s\xb3\x07\xf9\xe9Y" + + "\xba\xdc\xa2\xecc\x80n\xfe\xfb\x7fu\xe5\x9f/\xb9\xe4" + + "\x85\x06\x00\x91\xe5\xf8\xee\xec\xaf\xf9\x1e\xb1\xf6\xae,\xc9" + + "08\x99\xfa\xf0\x17\x17<\xf8\xafd\xb8i\x8evv" + + "\xf7!\xbe\xa6\x9b>\x0du\x93\xd6\x02\xb6*c<\"" + + "p\"\x99\xc0\x04\xffq\xf7\xcd|O\xf7\x97\x01\xfa\x9e" + + "\xeb\x9e%\x01\xba7\xcd\x9d|\xebW\xb9S\xdfh\xee" + + "\xedG\xe6\xbd\x0a\xc8\xdf\x99G\x1b\xef`m\xe7<{" + + "\xe2\xf1\xff\xd5|eu\xfe!\xc0\xbe\xda\xfc\x7fc\x80" + + "\xee\x83\x1dG\xdf3\x0e\xfe\xf5\xe1\xe6\x10\xbe\xebT\xda" + + "t\xcf\xa9\xb4\xe9`u\xc1\xdd\xf2\xce\xc7\x8f4\x8d\xa9" + + "\xf1\x85\x93\\^H\x9fZ\x17\x92\x1e\x02Gl\xd0\x83" + + "X\xfc\xe3\x85\x87\xf8\xbd\x0b\xc9p\xf7/\xfc\x19\x9c\xef" + + "V\xf2\xe3zI\xeb\xc9\xa3V6\xcb\xfd\x1bk\xe5\x01" + + "\xbd\xa7hT\x1c5&\xc5\x002x\x1c\x80\"\x8f\x02" + + "\xa8\x1d\x12\xaa'0t\xf5\xa2^\xd2Mg#$k" + + "e\x1d;C\xb1\x01\xb1\x130\xd80V\xdfP\xef\xd1" + + "\xcc\xda\xb0e\x98\x8en\xf7T\xcd\xbceV\x1c[3" + + "LI/\xa8\x9dR\xac\xc3u3\x98\x06P\xb4A\x00" + + "\xf5/$T\xc7\x19\xcax\xcc\xcd\xe0\x89\x00\x8a\xde\x0f" + + "\xa0n\x96P-2\x94\xd9\xc7n\x06g\x03(\xc6b" + + "\x00\xb5 \xa1Zf(K\x1f\xb9\x19<\x09@)\x8d" + + "\x00\xa8E\x09\xd5m\x0c'4\xb3\xf6g\x86Y\x80\xc4" + + "@\xc5\xb1\xaby\x07\x12)\xba\x17$\xdc\xbcV\xd6F" + + "\x8d\xa2\x01\x92S\x83D\x83\x06\x06mM2\x0bj\x0b" + + "F\xe2\xb1\xd2\xda\x1bbR\x89\x0ffsy\xab\xacO" + + "\x0c\x1af\xc10\xb7x\x9a\x8a!)\x8a\x84m\x91P" + + "\x9d\xcfp\xa0B\x8b*x\x1c\xe0\xb0\x84\xd8\x19n\x07" + + "H\xc4\x86s\xd7\xebNr\xdc*\x0c#\xaa\xdd\xc1~" + + "\xcf\xd05\x9f\x94P}\x81!b\x06\x89\xf6\xdc\x06\x00" + + "\xf5Y\x09\xd5\xdf1T$\xcc \x03P^\xbe\x06@" + + "}IB\xf5\x0d\x86J\x9ceP\x02P^\xbb\x1e@" + + "}CB\xf5m\x86J\x123\x18\x03P\x8e\x90-\xdf" + + "\x920\xd7\x81\x0c\x95\x18\xcb`\x9c\x1c\x07G\x00r-" + + "(a.C\xf4\x84\x94\xc1\x04\x00Wp\x14 \xd7I" + + "\xf4\x93\x89\xceb\x19\x81\xa6\x13q\x17@\xeed\xa2\xaf" + + "@\x86)S+\xe9\xd8\x01\x0c;\x08\xb3VA\xff\x9a" + + "]\xd0\x01mL\x02\xc3$\xa0[\xd6l\xad\x94sl" + + "\xac\xe6\x1d\xf2\x09\xc0V`\xd8\x0a\xe8\xdaz\xa5Zt" + + "r\x0e\xdauV\xc8\xd3L\xd3r4\xc7\x80\xa4eF" + + "4\x19\xa0\xc1\xd7\xa4\xd8|\xd0\xd6@2\x0b\xd8\x19\x06" + + "L\xdf#\xbd\x13\x06mHjM\xf9F\xa9\\4\xf2" + + "\x86\x83\xc3\xb4\x8f\xee\xe8\x92\x1d9,\xc8^M\xcd6" + + "dV\x07J\xba\xad\x99\x0eY\xae#\xb0\xdc\x10Y\xee" + + "\x1c\x09\xd5u\xa1\xe5\xd6\x90\xe5\xbe*\xa1\xba\x914\xe9" + + "[N%{\x0c{\xfe\xfd\xe9j\xfc\x8c\x0a\xa9\xcb(" + + "\x09\x19W\x1bz\xb1\xd0cZ\xe7\x1a\x95\xbcm\x94\x0c" + + "S3\x91\xc4\xa5]\xe5\xa4\xebN\xbb\xd4jC\x97\x8a" + + "\x055\x86\xd1\xfa\x0c\xb7\xbb\xf5-`@l\xe2\xa8'" + + "\x07\xf7\xbd\x9f\xee\xbbWB\xf5\x81\xf0\xbe\xfb\xe9\xbe?" + + "\x97P}$r\xdf\x87\xe9\xbe\x0fI\xa8\xbe\xe4\xbb\xaf" + + "\x84\xa8\xbcxs\xe8\xber\xccu1\x92-\x95\xd7\x16" + + "\x03\x93\xe3\xc7\x88\x18\xa4:\xe5\xa9^`\x98\xc0H\x15" + + "\xa0\xdc?\x08\xec\x0b\xd3`\xc1\xd7\x15\xd2=7i\xc5" + + "*\xea\xa1\xbaR\x95\xa2\xe5d\xb7\xd8V\xb5\x09\xd5\x87\xe8v\x1d\x19l\x01P\xfe\xf1R\x00" + + "\xf5\x01\x09\xd5\xc7\xc9'\xe4\x0c\xb6\x02(\x8f\xfe=\x80" + + "\xfa\xb8\x84\xea\xb3\xe4\x13\xbf\xcb`\x1b\xc5\xbe\xc10\xf6" + + ")\xb1T\x06\xdb)\xf8\x91\xa3\xbc \xa1\xfa{\x8as" + + "-\x19\xec\x00P^\xd9\x05\xa0\xfe^B\xf5-?r" + + "\xc9\x00\xca\xe1~/\xf8\xe5b\xc8\xd0-h\x8ev\xa1" + + "e\x17 \xbb\xca\xaa\x9aN\x18\x96<\xfb\xac\x82\xd4T" + + "\xb2\xad\x8f\xe9\xb6\xadca\x9dQq\x86\xcc|\xd6\xa2" + + "H\x8f\xa9\xb0p\x01\xc4\x14\xe0\x84Q9\x8f\xdc\x00\x11" + + "\x18b\xa3\xdf\xd0Y\x18\xee:\x85\xf7\xb5\xb1\xb1\x8a\xa4" + + ";\xd8\x02\x0c[\x00\x07\xc6\x08\xa4\x11\x87\x8c\xf4BS" + + " \xed)=W-\xebv\xbe\xa8U*@q\xa7%" + + "\xc0\xe1\xa2\xd9Sm\x8c\x0d6\x96\x8c\xcfk\xdfAZ" + + "\xd5#2\x1e@C\x90\x1b\x0c\x83\x9c\x8c\x94\xc7E\x98" + + "\xa3Pp\xae\x84\xeaf\xca\xd8\x94\xc7\x09\xf7\x97\xd0\xda" + + "\x8b$T\x0b\xd3\xdd:5j\x98\x85\xf0\xeaA\xaa\xf5" + + "\xae>a\x98\xe3\xbam8\x91T\xcdB\x90\x05\x9e\xe7" + + ";zg\x13G?\xfe\xff\xe8\xe8qq\xdc*\xab\xa0" + + "\x9f\xa7\x9b\xba\xad9\x96\xbdA\xdfZ\xd5+N\x8f\xff" + + "W/\xac6\x8az\xcf\xc0\x9aR\xd9\xb2\x9d\xcf`\x92" + + "\xc5MM25|5\xc1\x99(\x9e\xbc\xbbJ\xfe]" + + "\x17GcH,\x83J\xc3eSN\xd3:-{\x99" + + "V\xac\x12=h\x0a\x1a.\x8d\xf5S\xeb\x91$\xe6\x1d" + + "*\x0a\xc2\x11\xbf \\H\x05\xa1Y\x15\x19\x10$'" + + "\xe2\xbf\xc1\x14\xa0\xa9\xff\x8a\xcbx\xe96\xe9\xe86)" + + ",RE-\xf6\xab\xa8\x0c\x9bA#\xf1\xa6A\xb6\x9e" + + "\xc7\xd7\xeb\x0eUR\xb4{J\x84\\\x92<\x9e\xc1\x13" + + "h\xef\xed\x91R\xf6S\xa3)\x8b\xe4O\x11\xe8%\xad" + + "H\xca\x175+\x85\xb3EkCE\xcf\xc1cn\xc2" + + "\x0bhK\x89\xbcDB\xf5,\x16\x96\x17\x00IW\xdf" + + "V\xff\x0c\xd3\x0e\x93f\xf22t(\x15\xd7\xdb1\x05" + + "m\xb7\xeeu\x90\x15~Ge4\xa2\xd0\x9d\xd6\xeb\x17" + + "\xd1\xdb\xfc\xf4J\xc4*]\xda\x91P\xdd\xc1\x90r\x0f" + + "\xe1\xf1\x06\x0a\xc4\xdf\x91P\xbd\x8d\x02\xb1\xe4U\x8c;" + + "\xc9\xae\xb7H\xa8\xeee\x985\xadB\xb4|\x0d\xfa\x08" + + "\xdf\xa0v]\x86\x01!C\xb8\xb2.\xa8\xbf.O\xd7" + + "\xda\xa4\xdb\x90\xaa\x18\x96\x89\x9daKWw8\xabj" + + "\xe7\xf55&HcVx\\\xd0\xc44\xf5\x9f\x88\xe9" + + "Sd{\x0aJ\x1d\xa2n\x08&`\xca\x90\x0d\x8c\xfa" + + "\x08\x8c\x8c\x81\x94\xa5\x1b\x80Q\x1b\x81\x91Q\x832g" + + "\x12\x98[\xefL \xab\x19\xa6^\x08\x9d\x03\xed\xc0\x84" + + "\x89\x88k\x91gA]\xaa\xd0\xa9s\xfem\xc6\xac\x9e" + + "\xf5z)9:\xcd\xb9G\"\x0eX\xb0\xf2\xab\xacR" + + "I\x07\xc9tf\x80\xbd\xe7|Tp\x00\x99\xb9\xd3/" + + "\xe3\xb5\xfe\xb0YR\xd0\xab\xe2\x15}q\xd8+\x09\x9b" + + "&\xa8U\"C\x8fK\xa8:\xe4\x11Wy\xc9u\xeb" + + ".\xdf#\xaeb8`\x8d\x8dU\xc2L4C\xbcp" + + "\x0b\xfa\x98V-:\x9b 5C\xe0\x18\xd7\x0aC\xe4" + + "\xde\x987\x9csi\xb1Tt\x82\xbc\xd8,\xa7\x88\xfe" + + "I2\xb7\xf8\xe1\xb2\xc3u\xbdx\x19\xa9\x8a\xbc>\xb0" + + "1bNT\xcdQ\xabJ\xbd\xddL\xc26\xd3\xa1\xa8" + + "\xd7\x00D4`^\x89\x12\xf4k\x99iI\xa1!\x0e" + + "n\xd2\x8aRU'I\xd7\x05\x92\xf28[\x0c\xb0\x81" + + "Q3\xc5<\xfcw\x0aay+1r1\xe2t\x12" + + "\x87}\xecz\xb0\xe3\xb2\xe0\xb4\x10'C\x1c\xe9#\x17" + + "\x05\xf6\xb8\xc2z\x01r\x1d\xc49\x818\xb1\xa3\xaeg" + + "k\xde%8\x9d\xc49\x998\xf1\x0f\x89Cm\xdb\x89" + + "\x82\x93!N7q\x12\x1f\xd09\xd4\xb8\xcd\x11\x9c\x13" + + "\x883\x9f8\xc9\xf7\xe97\xd4\xba\xcde\xfd\xd4\xba\x11" + + "g!qZ\xde#N\x0b\x00_ 8\xdd\xc49\x8d" + + "8\xad\xef\x12\xa7\x15\x80/\x12\x9c\xf9\xc4YB\x9c\xb6" + + "w\x88\xd3\x06\xc0Og\x83\x00\xb9\x85\xc4YF\x9c\xf6" + + "\xb7\x89\xd3\x0e\xc0\x97\x0a\xcei\xc4Y\xc1\x18\xca\x1d\x7f" + + "tE\xb9\xc6\xcf\x10*XB\x8c\xb3\x88!\xff\x8f+" + + "J6~\xa6`,#\xc69\xc48\xee\x88+\xd2\x0d" + + "?[0V\x10\xe3\\:$\xf5\x96\xeb\x95\xb4|\xa5" + + "\xe0\x9cE\x9c\xaf\xd2O:\xdftEZ\xe4C\xac\x9f" + + "\x0f\xb1ln\x9cX\x0e\xb1\x94\xffvEr\xe4[\xd9" + + "\x06\x80\\\x99\x18W\x10#}\xd8\x1b@\xf0\x1a\xa3&" + + "x\x1b1\xbe\xc9\x18\xa6.\xb3\x0cr\xb1Q\xcb*\xd6" + + "\xfd8e\x98\xce\x0ad\xc0\x90\x01f\x0d\xd3Y\xba\x1c" + + "%`(y\xdf\xfaz1\x06\x0cc\xde\xb7\xe5\xcb0" + + "\x0e\x0c\xe3\x80\xd9\xaa\xf8]\x82z\x16\xc0\x81\xaa\xf7C" + + "?\x01\x88\xaf}\xbdA%X\xf5~\xea\xfb\xe1\xc4X" + + "\xd1\xd2\x88\xdd\x06\x0c\xdb\xea\xdf\x97/\xc3v`\xd8N" + + "p\xd5\xb7\x05\xb1#Eu.\xca\xc0P\x06\x14\xe3\x0e" + + "L\x03\xc34`\x8a\xb2tp\xa2W4\xa91d\xee" + + "\x91\x1b\xbe4+\xbdy\xff$\xa81\x86+3(*" + + "j\x1cu\xbd%\x9b4H\x16\xab\xd4\x92\xfb\xfb\xb8\"" + + "\xd5\x8eiy@\x1d\x12n=\xfb\x82\xa4\xdb\xc1\x92\xcf" + + "[6\x81\xe84\x83)\xb5\x82\xfd~\x1d\x15-5g" + + "7\xe9\xa7\xd76\xeb\xa7)z\xac\xf3\x02c\xa4\xb2r" + + "\xc7\x8c\xa2N\xb5\x04e^_[\x13\x868%\x92\xe3" + + "\x02\x19\x9a\xf6\xfa\x1bke\xfc\xe4\x10\x10\x84\xab\xc6\x08" + + "\xe0M\xae\x9a\x04\x00ox\xd5\x04\xffr\xec\xa8\xdb\x14" + + "\xfer\xfcC\xb7)\xfa\xe5\xc4\x07nS\xf0\xcb\xc9\xf7" + + "\xdd\xa6\xd8\x97[\xdes\x9bB_n}\xd7m\x8a|" + + "\xb9\xed\x1d\xb7)\xf0\xe5\xf6\xb7\xdd/\x10\xf7\x88\xe1\xa3" + + "\x97\x80?\x93\x09\xf4\x91W\x1a\xbe@P;\xdf$j" + + "\xf0\x16\xc2e\xd6\xcfe\x96\x05\x81w\x8c\x8cX\xf9\x1c" + + "F\xa9?}\x98\xa8\xc1\x88\x9f\xb7\xb2\x11`Q\xa4C" + + "B`\x1c\x12\x1e\xba\xbd\xbf}\xbd\xde\xdf\xe5\xcb \xe1" + + "a\x19\x12>\x8a\xfd\x0f\xb4\xc2G.$\xea\x98\xad\x7f" + + "\"\x9a\xc0)$\x04B\xfdQ\xa4\xc0\xe4\xa7cq\xc4" + + "\xc7\xe2\xc6\x1aH\xd4\x83E!8\x05\x80\x0dYo\xc8" + + "\x1b\xd4\xe6\x8c\xed~\xe3\xd6-\x00rq/y\xb7\xa2" + + "\x9e\x02\x80L4k()+\xd7\x02`L9{\x03" + + "\x00\xc6\x953G\x000\xa1\x9c1HU\xaar\xfa5" + + "\x00Y\xbdTvj\xc9Q\xc3I\x8d\xd6\x1c\xddu." + + "\xb7\x06k\x8e^\x01\x00w\xcc\xaa\xda\xf4\x05\xb0\xe2\xea" + + "\xc6\x96qg\xb0F\xe2T&\xfc\xe6\xda5\xcc\xa2a" + + "\xea\xab\xacX\xa9lU\x0cG\x9fZ5\xad\xf2\xeb\xc3" + + "\x8aa\xa1\xd9\xd0_\xf6\x86\xa0\x17E\x8e@}\xaf\xdf" + + "^\x0e\xfbE\x0e]j}o\x18\x0a\xb2%\xedR+" + + "\x18\xf8dK\x86i\xd9\xf5\xd0\x9b-\x19y\xdb\xaa\x7f" + + "k\xd6\x94\x9c/\xc2R\x8a>7\xb4q\x8b\x9b\xb4q" + + "\xb3#}V\xb4S\x89F\x9ei\x0d\x15\xeaj\x07F" + + "\x9f\xc5\x94\x0d\xe1\xdb\x85\xa2\x8c\x84\xb5/}\x19\x8e\xd4" + + "\xa1\x9ep\xe7[ \x15t7\x17\xa9\x9b\xd5\x15u9" + + "y\x0dg\x03\xe4\x1c\x940w\x15\x06\xa2\xf2+\xc5$" + + "\xf7\x0a\"\x7fKLr\xfd\x82\xe4Z\x9c\x04\xc8}\x8b" + + "\xe8\xb7\x10]\xf2\x86\xc7\xfc\xbbH0\xfe\x0e\xd1o\x13" + + "\x13a\xbf\x18\xd9)\xf6\xb9\x85\xe8{\x89\x9e\xf4'\xc8" + + "\xf7\x0a\xfa=D\x7f\x1c)\xb4\xb8~0z\x14\x09\xdd" + + "\x0f\x11\xe3Ib\xb4\x8a\x8afl[\xa7\x9b[\x9cq\xa8'\xf1i" + + "\x83;\xb3n\xb9\xe4\x94\xa6*0\xbb\x9fp>\xdbt" + + "2E\xc9,x\xd8\xf8\x0c\xa1\xc3\xf3\x18\x00\x11q\xa2" + + "\xf1#+z\x9e\xf0X\xc92\xc3\xc6\xe7\x13\xc7\xe0F" + + "E$u\x030?C\x91/\xe0\xe4\x9d\x95\xd4\xf2z" + + "}h\x91\x8a\x96\xf8\xe7\xf8C\x8b,\x80r65*" + + "gI\xa8^\xc4p\xa2$\x1a\xad\xf0\xfc\xfa\x7f \xd4" + + "\x13\xb3?\xff\x82T\xa5\x12\xd5g\xf0\xde>\xf3\xd4\xc1" + + "\xbbk\xca1,S]\xe6\x89D\xc5\xdf%\xc2M/" + + "\"\x1f(\x90_cY\xcch\xb9&\xfcz3\xd1\x8b" + + "\x027[\xc5\x98\x96\x1bx)@n\x9c\xe8\x8e\xc0\x8d" + + "-\x06\xaa|\xabX_&\xfa\x15\xe2\x85\xa5\"\xe6O" + + "\xbc\x86\xd7O\xc1_\xdc\xc9\xe0,\x81?\x1b \xf7M" + + "\xa2\xef\x108\xab\x8aA\x05\xbfA\xec\x1f\xe2/y\x99" + + "x\x0f\xe3;\x05]\xe0\xefGDo\xb9\\\xbc\x88\xf1" + + "\xdd\x82\xfeC\xa2\xff\x84\xe8\xad\xdb\xc4\x9b\x18\xbfK\x9c" + + "\xfb\x13\xa2\xdfG\xf4\xb6Z\x06O\x06\xe0\xfb\xc4\xb9{" + + "\x89\xfe\x00\xd1\xdb\xb7gp\x0e\x00\xdf/\xf6\xf99\xd1" + + "\x1f!z\xc7_f\xf0\xff\x01\xc1\xeef\x80\xdc#D" + + "\x7f\x1ag\x9c*\xb9\x8efo\xd1\x9d\xcajH\x1aE" + + "=p\x0c\x9f\xba\x0aR\xe4n\x8d\xe4!HRq\xda" + + "HE\x7f\xae\xe4\xd0\xdeSy9\xc8\x0a\xbfn\xa4\xaf" + + "\x86\x14\xb5z\x8d\xe4\x0b e\x1a\x96\xd9H>\x0fR" + + "Sf\xb7>y\x0d\xfa\xf8\xd0\xa7\x1f\xbc\x1e\xb2\xc21" + + "\x1b\xe9\xc3\x90\"\xd44\x92W\xa2\x0f,\x0b\xcd\x19P" + + "\"&\x19\x0d(Ao\x8a\xd78\xc6\x9c\xf5\x85\xcc\xeb" + + "W\xd6E2\x1b\xa7\xb9\xd1\x12\xbbY\xb2E\x9c\x9el" + + "\xa3\xf3\xe4\x19&\x8a\x9f\xe7\x1d\xc1\xcbi\xa95\xe6\x98" + + "%\x9a\x82\xf0\x1f,\xb0\x7f`\xbd^\x1a\xf5F=\x9f" + + "\xd4\x14\x8c|\x8e\xa6\xa0\xd9\xfce\xa2$\x8e\x89\x04\x95" + + "@\x08/\xa8\xfco\x00\x00\x00\xff\xffn\xcfm\xe2" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_a93fc509624c72d9, + Nodes: []uint64{ + 0x87e739250a60ea97, + 0x8e3b5f79fe593656, + 0x903455f06065422b, + 0x9500cce23b334d80, + 0x978a7cebdc549a4d, + 0x97b14cbe7cfec712, + 0x9aad50a41f4af45f, + 0x9dd1f724f4614a85, + 0x9e0e78711a7f87a9, + 0x9ea0b19b37fb4435, + 0xa9962a9ed0a4d7f8, + 0xabd73485a9636bc9, + 0xac3a6f60ef4cc6d3, + 0xae504193122357e5, + 0xb18aa5ac7a0d9420, + 0xb54ab3364333f598, + 0xb9521bccf10fa3b1, + 0xbaefc9120c56e274, + 0xbb90d5c287870be6, + 0xbfc546f6210ad7ce, + 0xc2573fe8a23e49f1, + 0xc2ba9038898e1fa2, + 0xc42305476bb4746f, + 0xc863cd16969ee7fc, + 0xcafccddb68db1d11, + 0xce23dcd2d7b00c9b, + 0xcfea0eb02e810062, + 0xd07378ede1f9cc60, + 0xd1958f7dba521926, + 0xd85d305b7d839963, + 0xdebf55bbfa0fc242, + 0xe682ab4cf923a417, + 0xe82753cff0c2218f, + 0xec1619d4400a0290, + 0xed8bca69f7fb0cbf, + 0xf1c8950dab257542, + 0xf38e1de3041357ae, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/std/capnp/stream.capnp b/crates/turborepo-lib/Source/hash/std/capnp/stream.capnp new file mode 100644 index 0000000000000..ef4ea68dfe05d --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/stream.capnp @@ -0,0 +1,53 @@ +# Copyright (c) 2019 Cloudflare, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0x86c366a91393f3f8; +# Defines placeholder types used to provide backwards-compatibility while introducing streaming +# to the language. The goal is that old code generators that don't know about streaming can still +# generate code that functions, leaving it up to the application to implement flow control +# manually. + +$import "/capnp/c++.capnp".namespace("capnp"); + +struct StreamResult @0x995f9a3377c0b16e { + # Empty struct that serves as the return type for "streaming" methods. + # + # Defining a method like: + # + # write @0 (bytes :Data) -> stream; + # + # Is equivalent to: + # + # write @0 (bytes :Data) -> import "/capnp/stream.capnp".StreamResult; + # + # However, implementations that recognize streaming will elide the reference to StreamResult + # and instead give write() a different signature appropriate for streaming. + # + # Streaming methods do not return a result -- that is, they return Promise. This promise + # resolves not to indicate that the call was actually delivered, but instead to provide + # backpressure. When the previous call's promise resolves, it is time to make another call. On + # the client side, the RPC system will resolve promises immediately until an appropriate number + # of requests are in-flight, and then will delay promise resolution to apply back-pressure. + # On the server side, the RPC system will deliver one call at a time. +} +using Go = import "/go.capnp"; +$Go.package("stream"); +$Go.import("capnproto.org/go/capnp/v3/std/capnp/stream"); diff --git a/crates/turborepo-lib/Source/hash/std/capnp/stream/stream.capnp.go b/crates/turborepo-lib/Source/hash/std/capnp/stream/stream.capnp.go new file mode 100644 index 0000000000000..af4c317a20ee6 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/capnp/stream/stream.capnp.go @@ -0,0 +1,91 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package stream + +import ( + capnp "capnproto.org/go/capnp/v3" + text "capnproto.org/go/capnp/v3/encoding/text" + schemas "capnproto.org/go/capnp/v3/schemas" +) + +type StreamResult capnp.Struct + +// StreamResult_TypeID is the unique identifier for the type StreamResult. +const StreamResult_TypeID = 0x995f9a3377c0b16e + +func NewStreamResult(s *capnp.Segment) (StreamResult, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return StreamResult(st), err +} + +func NewRootStreamResult(s *capnp.Segment) (StreamResult, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return StreamResult(st), err +} + +func ReadRootStreamResult(msg *capnp.Message) (StreamResult, error) { + root, err := msg.Root() + return StreamResult(root.Struct()), err +} + +func (s StreamResult) String() string { + str, _ := text.Marshal(0x995f9a3377c0b16e, capnp.Struct(s)) + return str +} + +func (s StreamResult) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Struct(s).EncodeAsPtr(seg) +} + +func (StreamResult) DecodeFromPtr(p capnp.Ptr) StreamResult { + return StreamResult(capnp.Struct{}.DecodeFromPtr(p)) +} + +func (s StreamResult) ToPtr() capnp.Ptr { + return capnp.Struct(s).ToPtr() +} +func (s StreamResult) IsValid() bool { + return capnp.Struct(s).IsValid() +} + +func (s StreamResult) Message() *capnp.Message { + return capnp.Struct(s).Message() +} + +func (s StreamResult) Segment() *capnp.Segment { + return capnp.Struct(s).Segment() +} + +// StreamResult_List is a list of StreamResult. +type StreamResult_List = capnp.StructList[StreamResult] + +// NewStreamResult creates a new list of StreamResult. +func NewStreamResult_List(s *capnp.Segment, sz int32) (StreamResult_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) + return capnp.StructList[StreamResult](l), err +} + +// StreamResult_Future is a wrapper for a StreamResult promised by a client call. +type StreamResult_Future struct{ *capnp.Future } + +func (f StreamResult_Future) Struct() (StreamResult, error) { + p, err := f.Future.Ptr() + return StreamResult(p.Struct()), err +} + +const schema_86c366a91393f3f8 = "x\xda\x12\x88p`1\xe4\xcdgb`\x0a\x94ae" + + "\xfb\x9f\xb7\xf1@\xb9\xf1\xac\xf8\x99\x0c\x82\xbc\x8c\xff\x7f" + + "|\x9e,\xbc2\xedp\x1b\x03\x0b;\x03\x83\xb0,\xe3" + + "%aMFv\x06\xd7\xff\xc5%E\xa9\x89\xb9z\xc9" + + "L\x89\x05y\x05V\xc1`^Pjqi\x0ecI" + + "\x00## \x00\x00\xff\xff\x13|\x19\xd3" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_86c366a91393f3f8, + Nodes: []uint64{ + 0x995f9a3377c0b16e, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/std/fixups.patch b/crates/turborepo-lib/Source/hash/std/fixups.patch new file mode 100644 index 0000000000000..e83d9fb3b144c --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/fixups.patch @@ -0,0 +1,51 @@ +--- a/capnp/compat/json.capnp 2021-10-21 14:59:51.244324279 -0400 ++++ b/capnp/compat/json.capnp 2021-10-21 15:01:09.543760012 -0400 +@@ -28,7 +28,7 @@ + null @0 :Void; + boolean @1 :Bool; + number @2 :Float64; +- string @3 :Text; ++ string @3 :Text $Go.name("string_"); + array @4 :List(Value); + object @5 :List(Field); + # Standard JSON values. +--- a/capnp/schema.capnp 2021-10-21 15:03:20.221774538 -0400 ++++ b/capnp/schema.capnp 2021-10-21 15:04:20.870019327 -0400 +@@ -82,7 +82,7 @@ + + file @6 :Void; + +- struct :group { ++ struct :group $Go.name("structNode") { + dataWordCount @7 :UInt16; + # Size of the data section, in words. + +@@ -336,7 +336,7 @@ + typeId @15 :Id; + brand @21 :Brand; + } +- struct :group { ++ struct :group $Go.name("structType") { + typeId @16 :Id; + brand @22 :Brand; + } +@@ -450,7 +450,7 @@ + list @14 :AnyPointer; + + enum @15 :UInt16; +- struct @16 :AnyPointer; ++ struct @16 :AnyPointer $Go.name("structValue"); + + interface @17 :Void; + # The only interface value that can be represented statically is "null", whose methods always +--- a/capnp/persistent.capnp 2021-10-21 15:12:33.501158612 -0400 ++++ b/capnp/persistent.capnp 2021-10-21 15:13:31.930030219 -0400 +@@ -108,7 +108,7 @@ + } + } + +-annotation persistent(interface, field) :Void; ++annotation persistent(interface, field) :Void $Go.name("PersistentAnnotation"); + # Apply this annotation to interfaces for objects that will always be persistent, instead of + # extending the Persistent capability, since the correct type parameters to Persistent depend on + # the realm, which is orthogonal to the interface type and therefore should not be defined diff --git a/crates/turborepo-lib/Source/hash/std/go.capnp b/crates/turborepo-lib/Source/hash/std/go.capnp new file mode 100644 index 0000000000000..4072b572a48ac --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/go.capnp @@ -0,0 +1,27 @@ +@0xd12a1c51fedd6c88; + +annotation package(file) :Text; +# The Go package name for the generated file. + +annotation import(file) :Text; +# The Go import path that the generated file is accessible from. +# Used to generate import statements and check if two types are in the +# same package. + +annotation doc(struct, field, enum) :Text; +# Adds a doc comment to the generated code. + +annotation tag(enumerant) :Text; +# Changes the string representation of the enum in the generated code. + +annotation notag(enumerant) :Void; +# Removes the string representation of the enum in the generated code. + +annotation customtype(field) :Text; +# OBSOLETE, not used by code generator. + +annotation name(struct, field, union, enum, enumerant, interface, method, param, annotation, const, group) :Text; +# Used to rename the element in the generated code. + +$package("gocp"); +$import("capnproto.org/go/capnp/v3/std/go"); diff --git a/crates/turborepo-lib/Source/hash/std/go/go.capnp.go b/crates/turborepo-lib/Source/hash/std/go/go.capnp.go new file mode 100644 index 0000000000000..f93b51bde6451 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/std/go/go.capnp.go @@ -0,0 +1,50 @@ +// Code generated by capnpc-go. DO NOT EDIT. + +package gocp + +import ( + schemas "capnproto.org/go/capnp/v3/schemas" +) + +const Package = uint64(0xbea97f1023792be0) +const Import = uint64(0xe130b601260e44b5) +const Doc = uint64(0xc58ad6bd519f935e) +const Tag = uint64(0xa574b41924caefc7) +const Notag = uint64(0xc8768679ec52e012) +const Customtype = uint64(0xfa10659ae02f2093) +const Name = uint64(0xc2b96012172f8df1) +const schema_d12a1c51fedd6c88 = "x\xda\x12\x98\xe8\xc0b\xc8{\x9c\x89\x81)P\x81\x95" + + "\xed\xff\xf1\xf7\xa7T$\xb7\x94,e\x08\xe4d\xe5\xf8" + + "\xdf\x91s\xf7_\xa0\x8c\xd6E\x06\x06FaO\xc6," + + "a_Fv\x06\x86`\x0fFfF\x06\xc6\xff\x0f\xb4" + + "+\x95\x05\xeaW\xee\x03)eDQj\xc9\xd8%\xec" + + "\x08Vj\x03Q\xfa\xb1W_\\(a\xe7!\x86\x8b" + + "\x9c\xac\xff\xf8Q\xd4\xea2\x16\x09\x1b\x82\xd5\xea@\xd4" + + "\xc6M\x9e\x1f\xb8\xf7Z\xd7Q\x90\xb1&(Je\x19" + + "\xb3\x84\x15\xc1Je J\x85\x1e\x04\xbd\xa9l+;" + + "\x81\xe9X^\xc6*aA\xb0R\x1e\x88\xd2\xad.|" + + "j\x8c\xdb\x0c\x1eb8V\xf0o\x930#He\xe0" + + "\x1f\xb0\xc2\xc9\x0a\xfa\x0ff\xa5\x0a\xfc\x02)T@Q" + + "\xf8v\x91\xe0W\x90\xba\x0f\xcc\x8c\x0c<\xff\xd3\xf3\xf5" + + "\x92\x13\x0b\xf2\x0a\x18\xf8\xadJ\x12\xd3\x03\x18\x19\x19y" + + "\x18\x98\xe0\xa2\x8cV\x05\x89\xc9\xd9\x89\xe9\xa9\x0c\x0c\xe8" + + "R\x0c\xf2Vy\x89\xb9\xa9\x18\xc2\xfcV)\xf9\xc9\x18" + + "\xa2\xf6Vy\xf9\x10\xf3\x19\x98\x91L\xcf\xcc-\xc8/" + + "*a\xc0\xb46\xb9\xb4\xb8$?\xb7\x84\xbd\xb2\x00f" + + "\x03 \x00\x00\xff\xff\xb5C\x8e\x03" + +func RegisterSchema(reg *schemas.Registry) { + reg.Register(&schemas.Schema{ + String: schema_d12a1c51fedd6c88, + Nodes: []uint64{ + 0xa574b41924caefc7, + 0xbea97f1023792be0, + 0xc2b96012172f8df1, + 0xc58ad6bd519f935e, + 0xc8768679ec52e012, + 0xe130b601260e44b5, + 0xfa10659ae02f2093, + }, + Compressed: true, + }) +} diff --git a/crates/turborepo-lib/Source/hash/traits.rs b/crates/turborepo-lib/Source/hash/traits.rs new file mode 100644 index 0000000000000..d79770d6b7a27 --- /dev/null +++ b/crates/turborepo-lib/Source/hash/traits.rs @@ -0,0 +1,36 @@ +use std::hash::Hasher; + +use capnp::message::{Allocator, Builder}; + +pub trait Sealed {} + +pub trait TurboHash: Sealed { + fn hash(self) -> String; +} + +impl Sealed for T +where + T: Into>, + A: Allocator, +{ +} + +impl TurboHash for T +where + T: Into>, + A: Allocator, +{ + fn hash(self) -> String { + let message = self.into(); + + debug_assert_eq!(message.get_segments_for_output().len(), 1, "message is not canonical"); + + let buf = message.get_segments_for_output()[0]; + + let mut hasher = twox_hash::XxHash64::with_seed(0); + hasher.write(buf); + let out = hasher.finish(); + + hex::encode(out.to_be_bytes()) + } +} diff --git a/crates/turborepo-lib/src/lib.rs b/crates/turborepo-lib/Source/lib.rs similarity index 100% rename from crates/turborepo-lib/src/lib.rs rename to crates/turborepo-lib/Source/lib.rs diff --git a/crates/turborepo-lib/src/microfrontends.rs b/crates/turborepo-lib/Source/microfrontends.rs similarity index 100% rename from crates/turborepo-lib/src/microfrontends.rs rename to crates/turborepo-lib/Source/microfrontends.rs diff --git a/crates/turborepo-lib/src/opts.rs b/crates/turborepo-lib/Source/opts.rs similarity index 100% rename from crates/turborepo-lib/src/opts.rs rename to crates/turborepo-lib/Source/opts.rs diff --git a/crates/turborepo-lib/src/package_changes_watcher.rs b/crates/turborepo-lib/Source/package_changes_watcher.rs similarity index 100% rename from crates/turborepo-lib/src/package_changes_watcher.rs rename to crates/turborepo-lib/Source/package_changes_watcher.rs diff --git a/crates/turborepo-lib/Source/panic_handler.rs b/crates/turborepo-lib/Source/panic_handler.rs new file mode 100644 index 0000000000000..477778dbe89d7 --- /dev/null +++ b/crates/turborepo-lib/Source/panic_handler.rs @@ -0,0 +1,56 @@ +use human_panic::report::{Method, Report}; + +use crate::get_version; + +const OPEN_ISSUE_MESSAGE:&str = + "Please open an issue at https://github.com/vercel/turborepo/issues/new/choose"; + +pub fn panic_handler(panic_info:&std::panic::PanicHookInfo) { + let cause = panic_info.to_string(); + + let explanation = match panic_info.location() { + Some(location) => format!("file '{}' at line {}\n", location.file(), location.line()), + None => "unknown.".to_string(), + }; + + let report = Report::new("turbo", get_version(), Method::Panic, explanation, cause); + // If we're in CI we don't persist the backtrace to a temp file as this is hard + // to retrieve. + let should_persist = !turborepo_ci::is_ci() && turborepo_ci::Vendor::infer().is_none(); + + let report_message = if should_persist { + match report.persist() { + Ok(f) => { + format!( + "A report has been written to {}\n\n{OPEN_ISSUE_MESSAGE} and include this file", + f.display() + ) + }, + Err(e) => { + format!( + "An error has occurred while attempting to write a \ + report.\n\n{OPEN_ISSUE_MESSAGE} and include the following error in your \ + issue: {}", + e + ) + }, + } + } else if let Some(backtrace) = report.serialize() { + format!( + "Caused by \n{backtrace}\n\n{OPEN_ISSUE_MESSAGE} and include this message in your \ + issue" + ) + } else { + format!( + "Unable to serialize backtrace.\n\n{OPEN_ISSUE_MESSAGE} and include this message in \ + your issue" + ) + }; + + eprintln!( + "Oops! Turbo has crashed. + +{}", + report_message + ); +} diff --git a/crates/turborepo-lib/src/process/child.rs b/crates/turborepo-lib/Source/process/child.rs similarity index 100% rename from crates/turborepo-lib/src/process/child.rs rename to crates/turborepo-lib/Source/process/child.rs diff --git a/crates/turborepo-lib/Source/process/command.rs b/crates/turborepo-lib/Source/process/command.rs new file mode 100644 index 0000000000000..fde98c428db1e --- /dev/null +++ b/crates/turborepo-lib/Source/process/command.rs @@ -0,0 +1,143 @@ +use std::{ + collections::BTreeMap, + ffi::{OsStr, OsString}, + process::Stdio, +}; + +use itertools::Itertools; +use turbopath::AbsoluteSystemPathBuf; + +/// A command builder that can be used to build both regular +/// child processes and ones spawned hooked up to a PTY +#[derive(Debug, Clone)] +pub struct Command { + program:OsString, + args:Vec, + cwd:Option, + env:BTreeMap, + open_stdin:bool, + env_clear:bool, +} + +impl Command { + pub fn new(program:impl AsRef) -> Self { + let program = program.as_ref().to_os_string(); + Self { + program, + args:Vec::new(), + cwd:None, + env:BTreeMap::new(), + open_stdin:false, + env_clear:false, + } + } + + pub fn args(&mut self, args:I) -> &mut Self + where + I: IntoIterator, + S: AsRef, { + self.args = args.into_iter().map(|arg| arg.as_ref().to_os_string()).collect(); + self + } + + pub fn current_dir(&mut self, dir:AbsoluteSystemPathBuf) -> &mut Self { + self.cwd = Some(dir); + self + } + + pub fn envs(&mut self, vars:I) -> &mut Self + where + I: IntoIterator, + K: AsRef, + V: AsRef, { + for (ref key, ref val) in vars { + self.env.insert(key.as_ref().to_os_string(), val.as_ref().to_os_string()); + } + self + } + + pub fn env(&mut self, key:K, val:V) -> &mut Self + where + K: AsRef, + V: AsRef, { + self.env.insert(key.as_ref().to_os_string(), val.as_ref().to_os_string()); + self + } + + /// Configure the child process to spawn with a piped stdin + pub fn open_stdin(&mut self) -> &mut Self { + self.open_stdin = true; + self + } + + /// Clears the environment variables for the child process + pub fn env_clear(&mut self) -> &mut Self { + self.env_clear = true; + self.env.clear(); + self + } + + pub fn label(&self) -> String { + format!( + "({}) {} {}", + self.cwd.as_deref().map(|dir| dir.as_str()).unwrap_or_default(), + self.program.to_string_lossy(), + self.args.iter().map(|s| s.to_string_lossy()).join(" ") + ) + } + + /// If stdin is expected to be opened + pub fn will_open_stdin(&self) -> bool { self.open_stdin } + + /// Program for the command + pub fn program(&self) -> &OsStr { &self.program } +} + +impl From for tokio::process::Command { + fn from(value:Command) -> Self { + let Command { program, args, cwd, env, open_stdin, env_clear } = value; + + let mut cmd = tokio::process::Command::new(program); + if env_clear { + cmd.env_clear(); + } + cmd.args(args) + .envs(env) + // We always pipe stdout/stderr to allow us to capture task output + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + // Only open stdin if configured to do so + .stdin(if open_stdin { + Stdio::piped() + } else { + Stdio::null() + }); + if let Some(cwd) = cwd { + cmd.current_dir(cwd.as_std_path()); + } + cmd + } +} + +impl From for portable_pty::CommandBuilder { + fn from(value:Command) -> Self { + let Command { program, args, cwd, env, env_clear, .. } = value; + let mut cmd = portable_pty::CommandBuilder::new(program); + if env_clear { + cmd.env_clear(); + } + cmd.args(args); + if let Some(cwd) = cwd { + cmd.cwd(cwd.as_std_path()); + } else if let Ok(cwd) = std::env::current_dir() { + // portably_pty defaults to a users home directory instead of cwd if one isn't + // configured on the command builder. + // We explicitly set the cwd if one exists to avoid this behavior + cmd.cwd(&cwd); + } + for (key, value) in env { + cmd.env(key, value); + } + cmd + } +} diff --git a/crates/turborepo-lib/Source/process/mod.rs b/crates/turborepo-lib/Source/process/mod.rs new file mode 100644 index 0000000000000..70038fdf70fe2 --- /dev/null +++ b/crates/turborepo-lib/Source/process/mod.rs @@ -0,0 +1,378 @@ +//! `process` +//! +//! This module contains the code that is responsible for running the commands +//! that are queued by run. It consists of a set of child processes that are +//! spawned and managed by the manager. The manager is responsible for +//! running these processes to completion, forwarding signals, and closing +//! them when the manager is closed. +//! +//! As of now, the manager will execute futures in a random order, and +//! must be either `wait`ed on or `stop`ped to drive state. + +mod child; +mod command; + +use std::{ + io, + sync::{Arc, Mutex}, + time::Duration, +}; + +pub use command::Command; +use futures::Future; +use tokio::task::JoinSet; +use tracing::{debug, trace}; + +pub use self::child::{Child, ChildExit}; + +/// A process manager that is responsible for spawning and managing child +/// processes. When the manager is Open, new child processes can be spawned +/// using `spawn`. When the manager is Closed, all currently-running children +/// will be closed, and no new children can be spawned. +#[derive(Debug, Clone)] +pub struct ProcessManager { + state:Arc>, + use_pty:bool, +} + +#[derive(Debug)] +struct ProcessManagerInner { + is_closing:bool, + children:Vec, + size:Option, +} + +#[derive(Debug, Clone, Copy)] +pub struct PtySize { + rows:u16, + cols:u16, +} + +impl ProcessManager { + pub fn new(use_pty:bool) -> Self { + debug!("spawning children with pty: {use_pty}"); + Self { + state:Arc::new(Mutex::new(ProcessManagerInner { + is_closing:false, + children:Vec::new(), + size:None, + })), + use_pty, + } + } + + /// Construct a process manager and infer if pty should be used + pub fn infer() -> Self { + // Only use PTY if we're not on windows and we're currently hooked up to a + // in a TTY + let use_pty = !cfg!(windows) && atty::is(atty::Stream::Stdout); + Self::new(use_pty) + } + + /// Returns whether children will be spawned attached to a pseudoterminal + pub fn use_pty(&self) -> bool { self.use_pty } + + /// Returns whether or not closing a child's stdin will result in it + /// immediately exiting. + pub fn closing_stdin_ends_process(&self) -> bool { + // Processes spawned hooked up to ConPTY on Windows will immediately exit + // if their stdin is closed. We avoid closing stdin in this case. + cfg!(windows) && self.use_pty + } +} + +impl ProcessManager { + /// Spawn a new child process to run the given command. + /// + /// The handle of the child can be either waited or stopped by the caller, + /// as well as the entire process manager. + /// + /// If spawn returns None, the process manager is closed and the child + /// process was not spawned. If spawn returns Some(Err), the process + /// manager is open, but the child process failed to spawn. + pub fn spawn( + &self, + command:Command, + stop_timeout:Duration, + ) -> Option> { + let label = tracing::enabled!(tracing::Level::TRACE) + .then(|| command.label()) + .unwrap_or_default(); + trace!("acquiring lock for spawning {label}"); + let mut lock = self.state.lock().unwrap(); + trace!("acquired lock for spawning {label}"); + if lock.is_closing { + debug!("process manager closing"); + return None; + } + let pty_size = self.use_pty.then(|| lock.pty_size()).flatten(); + let child = + child::Child::spawn(command, child::ShutdownStyle::Graceful(stop_timeout), pty_size); + if let Ok(child) = &child { + lock.children.push(child.clone()); + } + trace!("releasing lock for spawning {label}"); + Some(child) + } + + /// Stop the process manager, closing all child processes. On posix + /// systems this will send a SIGINT, and on windows it will just kill + /// the process immediately. + pub async fn stop(&self) { self.close(|mut c| async move { c.stop().await }).await } + + /// Stop the process manager, waiting for all child processes to exit. + /// + /// If you want to set a timeout, use `tokio::time::timeout` and + /// `Self::stop` if the timeout elapses. + pub async fn wait(&self) { self.close(|mut c| async move { c.wait().await }).await } + + /// Close the process manager, running the given callback on each child + /// + /// note: this is designed to be called multiple times, ie calling close + /// with two different strategies will propagate both signals to the child + /// processes. clearing the task queue and re-enabling spawning are both + /// idempotent operations + async fn close(&self, callback:F) + where + F: Fn(Child) -> C + Sync + Send + Copy + 'static, + C: Future> + Sync + Send + 'static, { + let mut set = JoinSet::new(); + + { + let mut lock = self.state.lock().expect("not poisoned"); + lock.is_closing = true; + for child in lock.children.iter() { + let child = child.clone(); + set.spawn(async move { callback(child).await }); + } + } + + debug!("waiting for {} processes to exit", set.len()); + + while let Some(out) = set.join_next().await { + trace!("process exited: {:?}", out); + } + + { + let mut lock = self.state.lock().expect("not poisoned"); + + // just allocate a new vec rather than clearing the old one + lock.children = vec![]; + } + } + + pub fn set_pty_size(&self, rows:u16, cols:u16) { + self.state.lock().expect("not poisoned").size = Some(PtySize { rows, cols }); + } +} + +impl ProcessManagerInner { + fn pty_size(&mut self) -> Option { + if self.size.is_none() { + self.size = PtySize::from_tty(); + } + self.size + } +} + +impl PtySize { + fn from_tty() -> Option { + console::Term::stdout().size_checked().map(|(rows, cols)| Self { rows, cols }) + } +} + +impl Default for PtySize { + fn default() -> Self { Self { rows:24, cols:80 } } +} + +#[cfg(test)] +mod test { + use std::time::Instant; + + use futures::{StreamExt, stream::FuturesUnordered}; + use test_case::test_case; + use tokio::{join, time::sleep}; + use tracing_test::traced_test; + + use super::*; + + fn get_command() -> Command { get_script_command("sleep_5_interruptable.js") } + + fn get_script_command(script_name:&str) -> Command { + let mut cmd = Command::new("node"); + cmd.args([format!("./test/scripts/{script_name}")]); + cmd + } + + const STOPPED_EXIT:Option = Some(ChildExit::Killed); + + #[tokio::test] + async fn test_basic() { + let manager = ProcessManager::new(false); + let mut child = manager + .spawn(get_script_command("hello_world.js"), Duration::from_secs(2)) + .unwrap() + .unwrap(); + let mut out = Vec::new(); + let exit = child.wait_with_piped_outputs(&mut out).await.unwrap(); + assert_eq!(exit, Some(ChildExit::Finished(Some(0)))); + assert_eq!(out, b"hello world\n"); + } + + #[tokio::test] + async fn test_multiple() { + let manager = ProcessManager::new(false); + + let children = (0..2) + .map(|_| manager.spawn(get_command(), Duration::from_secs(2)).unwrap().unwrap()) + .collect::>(); + + sleep(Duration::from_millis(100)).await; + + manager.stop().await; + + for mut child in children { + let exit = child.wait().await; + assert_eq!(exit, STOPPED_EXIT,); + } + } + + #[tokio::test] + async fn test_closed() { + let manager = ProcessManager::new(false); + let mut child = manager.spawn(get_command(), Duration::from_secs(2)).unwrap().unwrap(); + let mut out = Vec::new(); + let (exit, _) = join! { + child.wait_with_piped_outputs(&mut out), + manager.stop(), + }; + let exit = exit.unwrap(); + assert_eq!(exit, STOPPED_EXIT,); + assert_eq!(out, b"", "child process should exit before output is printed"); + + // Verify that we can't start new child processes + assert!(manager.spawn(get_command(), Duration::from_secs(2)).is_none()); + + manager.stop().await; + } + + #[tokio::test] + async fn test_exit_code() { + let manager = ProcessManager::new(false); + let mut child = manager + .spawn(get_script_command("hello_world.js"), Duration::from_secs(2)) + .unwrap() + .unwrap(); + + let code = child.wait().await; + assert_eq!(code, Some(ChildExit::Finished(Some(0)))); + + // TODO: maybe we should do some assertion that there was nothing to shut down + // and this is a noop? + manager.stop().await; + } + + #[tokio::test] + #[traced_test] + async fn test_message_after_stop() { + let manager = ProcessManager::new(false); + let mut child = manager + .spawn(get_script_command("hello_world.js"), Duration::from_secs(2)) + .unwrap() + .unwrap(); + + sleep(Duration::from_millis(100)).await; + + let exit = child.wait().await; + assert_eq!(exit, Some(ChildExit::Finished(Some(0)))); + + manager.stop().await; + + // this is idempotent, so calling it after the manager is stopped is ok + let kill_code = child.kill().await; + assert_eq!(kill_code, Some(ChildExit::Finished(Some(0)))); + + let code = child.wait().await; + assert_eq!(code, Some(ChildExit::Finished(Some(0)))); + } + + #[tokio::test] + async fn test_reuse_manager() { + let manager = ProcessManager::new(false); + manager.spawn(get_command(), Duration::from_secs(2)); + + sleep(Duration::from_millis(100)).await; + + manager.stop().await; + + assert!(manager.state.lock().unwrap().children.is_empty()); + + // TODO: actually do some check that this is idempotent + // idempotent + manager.stop().await; + } + + #[test_case("stop", "sleep_5_interruptable.js", STOPPED_EXIT)] + #[test_case("wait", "hello_world.js", Some(ChildExit::Finished(Some(0))))] + #[tokio::test] + async fn test_stop_multiple_tasks_shared( + strategy:&str, + script:&str, + expected:Option, + ) { + let manager = ProcessManager::new(false); + let tasks = FuturesUnordered::new(); + + for _ in 0..10 { + let manager = manager.clone(); + let command = get_script_command(script); + tasks.push(tokio::spawn(async move { + manager.spawn(command, Duration::from_secs(1)).unwrap().unwrap().wait().await + })); + } + + // wait for tasks to start + tokio::time::sleep(Duration::from_millis(50)).await; + + match strategy { + "stop" => manager.stop().await, + "wait" => manager.wait().await, + _ => panic!("unknown strategy"), + } + + // tasks return proper exit code + assert!( + tasks.all(|v| async { v.unwrap() == expected }).await, + "not all tasks returned the correct code: {:?}", + expected + ); + } + + #[tokio::test] + async fn test_wait_multiple_tasks() { + let manager = ProcessManager::new(false); + + let mut out = Vec::new(); + let mut child = manager.spawn(get_command(), Duration::from_secs(1)).unwrap().unwrap(); + + // let the task start + tokio::time::sleep(Duration::from_millis(50)).await; + + let start_time = Instant::now(); + + // we support 'close escalation'; someone can call + // stop even if others are waiting + let (exit, ..) = join! { + child.wait_with_piped_outputs(&mut out), + manager.wait(), + manager.stop(), + }; + + assert_eq!(exit.unwrap(), STOPPED_EXIT); + assert_eq!(out, b"", "child process was stopped before any output was written"); + + let finish_time = Instant::now(); + + assert!((finish_time - start_time).lt(&Duration::from_secs(2))); + } +} diff --git a/crates/turborepo-lib/src/query/file.rs b/crates/turborepo-lib/Source/query/file.rs similarity index 100% rename from crates/turborepo-lib/src/query/file.rs rename to crates/turborepo-lib/Source/query/file.rs diff --git a/crates/turborepo-lib/src/query/mod.rs b/crates/turborepo-lib/Source/query/mod.rs similarity index 100% rename from crates/turborepo-lib/src/query/mod.rs rename to crates/turborepo-lib/Source/query/mod.rs diff --git a/crates/turborepo-lib/src/query/package.rs b/crates/turborepo-lib/Source/query/package.rs similarity index 100% rename from crates/turborepo-lib/src/query/package.rs rename to crates/turborepo-lib/Source/query/package.rs diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/13.typescript b/crates/turborepo-lib/Source/query/package_graph.rs similarity index 100% rename from crates/turborepo-vt100/tests/data/fixtures/decstbm/13.typescript rename to crates/turborepo-lib/Source/query/package_graph.rs diff --git a/crates/turborepo-lib/Source/query/server.rs b/crates/turborepo-lib/Source/query/server.rs new file mode 100644 index 0000000000000..e23c45497f5c2 --- /dev/null +++ b/crates/turborepo-lib/Source/query/server.rs @@ -0,0 +1,45 @@ +use std::sync::Arc; + +use async_graphql::{EmptyMutation, EmptySubscription, MergedObject, Schema}; +use async_graphql_axum::GraphQL; +use axum::{Router, http::Method, routing::get}; +use tokio::net::TcpListener; +use tower_http::cors::{Any, CorsLayer}; +use turborepo_ui::wui::query::SharedState; + +use crate::{query, query::graphiql, run::Run}; + +#[derive(MergedObject)] +struct Query(turborepo_ui::wui::RunQuery, query::RepositoryQuery); + +pub async fn run_server( + state:Option, + run:Arc, +) -> Result<(), turborepo_ui::Error> { + let cors = CorsLayer::new() + // allow `GET` and `POST` when accessing the resource + .allow_methods([Method::GET, Method::POST]) + .allow_headers(Any) + // allow requests from any origin + .allow_origin(Any); + + let web_ui_query = turborepo_ui::wui::RunQuery::new(state.clone()); + let turbo_query = query::RepositoryQuery::new(run); + let combined_query = Query(web_ui_query, turbo_query); + + let schema = Schema::new(combined_query, EmptyMutation, EmptySubscription); + let app = Router::new() + .route("/", get(graphiql).post_service(GraphQL::new(schema))) + .layer(cors); + + axum::serve( + TcpListener::bind("127.0.0.1:8000") + .await + .map_err(turborepo_ui::wui::Error::Server)?, + app, + ) + .await + .map_err(turborepo_ui::wui::Error::Server)?; + + Ok(()) +} diff --git a/crates/turborepo-lib/Source/query/task.rs b/crates/turborepo-lib/Source/query/task.rs new file mode 100644 index 0000000000000..4805509d6d78e --- /dev/null +++ b/crates/turborepo-lib/Source/query/task.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; + +use async_graphql::Object; +use turborepo_errors::Spanned; + +use crate::{ + engine::TaskNode, + query::{Array, Error, package::Package}, + run::{Run, task_id::TaskId}, +}; + +pub struct RepositoryTask { + pub name:String, + pub package:Package, + pub script:Option>, +} + +impl RepositoryTask { + pub fn new(task_id:&TaskId, run:&Arc) -> Result { + let package = Package::new(run.clone(), task_id.package().into())?; + let script = package.get_tasks().get(task_id.task()).cloned(); + + Ok(RepositoryTask { name:task_id.task().to_string(), package, script }) + } + + fn collect_and_sort<'a>( + &self, + task_id:&TaskId<'a>, + tasks:impl IntoIterator, + ) -> Result, Error> { + let mut tasks = tasks + .into_iter() + .filter_map(|task| { + match task { + TaskNode::Root => None, + TaskNode::Task(task) if task == task_id => None, + TaskNode::Task(task) => Some(RepositoryTask::new(task, self.package.run())), + } + }) + .collect::, _>>()?; + tasks.sort_by(|a, b| { + a.package.get_name().cmp(b.package.get_name()).then_with(|| a.name.cmp(&b.name)) + }); + Ok(tasks) + } +} + +#[Object] +impl RepositoryTask { + async fn name(&self) -> String { self.name.clone() } + + async fn package(&self) -> Package { self.package.clone() } + + async fn full_name(&self) -> String { format!("{}#{}", self.package.get_name(), self.name) } + + async fn script(&self) -> Option { + self.script.as_ref().map(|script| script.value.to_string()) + } + + async fn direct_dependents(&self) -> Result, Error> { + let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); + + self.collect_and_sort( + &task_id, + self.package.run().engine().dependents(&task_id).into_iter().flatten(), + ) + } + + async fn direct_dependencies(&self) -> Result, Error> { + let task_id = TaskId::new(self.package.get_name().as_ref(), &self.name); + + self.collect_and_sort( + &task_id, + self.package.run().engine().dependencies(&task_id).into_iter().flatten(), + ) + } + + async fn indirect_dependents(&self) -> Result, Error> { + let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); + let direct_dependents = + self.package.run().engine().dependencies(&task_id).unwrap_or_default(); + + self.collect_and_sort( + &task_id, + self.package + .run() + .engine() + .transitive_dependents(&task_id) + .into_iter() + .filter(|node| !direct_dependents.contains(node)), + ) + } + + async fn indirect_dependencies(&self) -> Result, Error> { + let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); + let direct_dependencies = + self.package.run().engine().dependencies(&task_id).unwrap_or_default(); + let mut dependencies = self + .package + .run() + .engine() + .transitive_dependencies(&task_id) + .into_iter() + .filter(|node| !direct_dependencies.contains(node)) + .filter_map(|node| { + match node { + TaskNode::Root => None, + TaskNode::Task(task) if task == &task_id => None, + TaskNode::Task(task) => Some(RepositoryTask::new(task, self.package.run())), + } + }) + .collect::, _>>()?; + + dependencies.sort_by(|a, b| { + a.package.get_name().cmp(b.package.get_name()).then_with(|| a.name.cmp(&b.name)) + }); + + Ok(dependencies) + } + + async fn all_dependents(&self) -> Result, Error> { + let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); + self.collect_and_sort(&task_id, self.package.run().engine().transitive_dependents(&task_id)) + } + + async fn all_dependencies(&self) -> Result, Error> { + let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); + self.collect_and_sort( + &task_id, + self.package.run().engine().transitive_dependencies(&task_id), + ) + } +} diff --git a/crates/turborepo-lib/src/rewrite_json.rs b/crates/turborepo-lib/Source/rewrite_json.rs similarity index 100% rename from crates/turborepo-lib/src/rewrite_json.rs rename to crates/turborepo-lib/Source/rewrite_json.rs diff --git a/crates/turborepo-lib/Source/run/builder.rs b/crates/turborepo-lib/Source/run/builder.rs new file mode 100644 index 0000000000000..9e2c43a61d2d9 --- /dev/null +++ b/crates/turborepo-lib/Source/run/builder.rs @@ -0,0 +1,525 @@ +use std::{ + collections::{HashMap, HashSet}, + io::{ErrorKind, IsTerminal}, + sync::Arc, + time::SystemTime, +}; + +use chrono::Local; +use tracing::debug; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; +use turborepo_analytics::{AnalyticsHandle, AnalyticsSender, start_analytics}; +use turborepo_api_client::{APIAuth, APIClient}; +use turborepo_cache::AsyncCache; +use turborepo_env::EnvironmentVariableMap; +use turborepo_errors::Spanned; +use turborepo_repository::{ + change_mapper::PackageInclusionReason, + package_graph::{PackageGraph, PackageName}, + package_json, + package_json::PackageJson, +}; +use turborepo_scm::SCM; +use turborepo_telemetry::events::{ + EventBuilder, + TrackedErrors, + command::CommandEventBuilder, + generic::{DaemonInitStatus, GenericEventBuilder}, + repo::{RepoEventBuilder, RepoType}, +}; +use turborepo_ui::{ColorConfig, ColorSelector}; +#[cfg(feature = "daemon-package-discovery")] +use { + crate::run::package_discovery::DaemonPackageDiscovery, + std::time::Duration, + turborepo_repository::discovery::{ + Error as DiscoveryError, + FallbackPackageDiscovery, + LocalPackageDiscoveryBuilder, + PackageDiscoveryBuilder, + }, +}; + +use crate::{ + DaemonConnector, + cli::DryRunMode, + commands::CommandBase, + engine::{Engine, EngineBuilder}, + microfrontends::MicrofrontendsConfigs, + opts::Opts, + process::ProcessManager, + run::{Error, Run, RunCache, scope, task_access::TaskAccess, task_id::TaskName}, + shim::TurboState, + signal::{SignalHandler, SignalSubscriber}, + turbo_json::{TurboJson, TurboJsonLoader, UIMode}, +}; + +pub struct RunBuilder { + processes:ProcessManager, + opts:Opts, + api_auth:Option, + repo_root:AbsoluteSystemPathBuf, + color_config:ColorConfig, + version:&'static str, + api_client:APIClient, + analytics_sender:Option, + // In watch mode, we can have a changed package that we want to serve as an entrypoint. + // We will then prune away any tasks that do not depend on tasks inside + // this package. + entrypoint_packages:Option>, + should_print_prelude_override:Option, + // In query, we don't want to validate the engine. Defaults to `true` + should_validate_engine:bool, + // If true, we will add all tasks to the graph, even if they are not specified + add_all_tasks:bool, +} + +impl RunBuilder { + pub fn new(base:CommandBase) -> Result { + let api_client = base.api_client()?; + + let opts = base.opts(); + let api_auth = base.api_auth()?; + + let version = base.version(); + let processes = ProcessManager::new( + // We currently only use a pty if the following are met: + // - we're attached to a tty + atty::is(atty::Stream::Stdout) && + // - if we're on windows, we're using the UI + (!cfg!(windows) || matches!(opts.run_opts.ui_mode, UIMode::Tui)), + ); + + let CommandBase { repo_root, color_config: ui, opts, .. } = base; + + Ok(Self { + processes, + opts, + api_client, + repo_root, + color_config:ui, + version, + api_auth, + analytics_sender:None, + entrypoint_packages:None, + should_print_prelude_override:None, + should_validate_engine:true, + add_all_tasks:false, + }) + } + + pub fn with_entrypoint_packages(mut self, entrypoint_packages:HashSet) -> Self { + self.entrypoint_packages = Some(entrypoint_packages); + self + } + + pub fn hide_prelude(mut self) -> Self { + self.should_print_prelude_override = Some(false); + self + } + + pub fn add_all_tasks(mut self) -> Self { + self.add_all_tasks = true; + self + } + + pub fn do_not_validate_engine(mut self) -> Self { + self.should_validate_engine = false; + self + } + + fn connect_process_manager(&self, signal_subscriber:SignalSubscriber) { + let manager = self.processes.clone(); + tokio::spawn(async move { + let _guard = signal_subscriber.listen().await; + manager.stop().await; + }); + } + + pub fn with_analytics_sender(mut self, analytics_sender:Option) -> Self { + self.analytics_sender = analytics_sender; + self + } + + pub fn calculate_filtered_packages( + repo_root:&AbsoluteSystemPath, + opts:&Opts, + pkg_dep_graph:&PackageGraph, + scm:&SCM, + root_turbo_json:&TurboJson, + ) -> Result, Error> { + let (mut filtered_pkgs, is_all_packages) = scope::resolve_packages( + &opts.scope_opts, + repo_root, + pkg_dep_graph, + scm, + root_turbo_json, + )?; + + if is_all_packages { + for target in opts.run_opts.tasks.iter() { + let mut task_name = TaskName::from(target.as_str()); + // If it's not a package task, we convert to a root task + if !task_name.is_package_task() { + task_name = task_name.into_root_task() + } + + if root_turbo_json.tasks.contains_key(&task_name) { + filtered_pkgs.insert( + PackageName::Root, + PackageInclusionReason::RootTask { task:task_name.to_string() }, + ); + break; + } + } + }; + + Ok(filtered_pkgs) + } + + // Starts analytics and returns handle. This is not included in the main `build` + // function because we don't want the handle stored in the `Run` struct. + pub fn start_analytics(&self) -> (Option, Option) { + // If there's no API auth, we don't want to record analytics + let Some(api_auth) = self.api_auth.clone() else { + return (None, None); + }; + api_auth + .is_linked() + .then(|| start_analytics(api_auth, self.api_client.clone())) + .unzip() + } + + #[tracing::instrument(skip(self, signal_handler))] + pub async fn build( + mut self, + signal_handler:&SignalHandler, + telemetry:CommandEventBuilder, + ) -> Result { + tracing::trace!( + platform = %TurboState::platform_name(), + start_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).expect("system time after epoch").as_micros(), + turbo_version = %TurboState::version(), + numcpus = num_cpus::get(), + "performing run on {:?}", + TurboState::platform_name(), + ); + let start_at = Local::now(); + if let Some(subscriber) = signal_handler.subscribe() { + self.connect_process_manager(subscriber); + } + + let scm = { + let repo_root = self.repo_root.clone(); + tokio::task::spawn_blocking(move || SCM::new(&repo_root)) + }; + let package_json_path = self.repo_root.join_component("package.json"); + let root_package_json = PackageJson::load(&package_json_path)?; + let run_telemetry = GenericEventBuilder::new().with_parent(&telemetry); + let repo_telemetry = + RepoEventBuilder::new(&self.repo_root.to_string()).with_parent(&telemetry); + + // Pulled from initAnalyticsClient in run.go + let is_linked = turborepo_api_client::is_linked(&self.api_auth); + run_telemetry.track_is_linked(is_linked); + run_telemetry.track_arg_usage( + "dangerously_allow_missing_package_manager", + self.opts.repo_opts.allow_no_package_manager, + ); + // we only track the remote cache if we're linked because this defaults to + // Vercel + if is_linked { + run_telemetry.track_remote_cache(self.api_client.base_url()); + } + let _is_structured_output = self.opts.run_opts.graph.is_some() + || matches!(self.opts.run_opts.dry_run, Some(DryRunMode::Json)); + + let is_single_package = self.opts.run_opts.single_package; + repo_telemetry.track_type(if is_single_package { + RepoType::SinglePackage + } else { + RepoType::Monorepo + }); + + let is_ci_or_not_tty = turborepo_ci::is_ci() || !std::io::stdout().is_terminal(); + run_telemetry.track_ci(turborepo_ci::Vendor::get_name()); + + // Remove allow when daemon is flagged back on + let daemon = match (is_ci_or_not_tty, self.opts.run_opts.daemon) { + (true, None) => { + run_telemetry.track_daemon_init(DaemonInitStatus::Skipped); + debug!("skipping turbod since we appear to be in a non-interactive context"); + None + }, + (_, Some(true)) | (false, None) => { + let can_start_server = true; + let can_kill_server = true; + let connector = + DaemonConnector::new(can_start_server, can_kill_server, &self.repo_root); + match (connector.connect().await, self.opts.run_opts.daemon) { + (Ok(client), _) => { + run_telemetry.track_daemon_init(DaemonInitStatus::Started); + debug!("running in daemon mode"); + Some(client) + }, + (Err(e), Some(true)) => { + run_telemetry.track_daemon_init(DaemonInitStatus::Failed); + debug!("failed to connect to daemon when forced {e}, exiting"); + return Err(e.into()); + }, + (Err(e), None) => { + run_telemetry.track_daemon_init(DaemonInitStatus::Failed); + debug!("failed to connect to daemon {e}"); + None + }, + (_, Some(false)) => unreachable!(), + } + }, + (_, Some(false)) => { + run_telemetry.track_daemon_init(DaemonInitStatus::Disabled); + debug!("skipping turbod since --no-daemon was passed"); + None + }, + }; + + let mut pkg_dep_graph = { + let builder = PackageGraph::builder(&self.repo_root, root_package_json.clone()) + .with_single_package_mode(self.opts.run_opts.single_package) + .with_allow_no_package_manager(self.opts.repo_opts.allow_no_package_manager); + + // Daemon package discovery depends on packageManager existing in package.json + let graph = if cfg!(feature = "daemon-package-discovery") + && !self.opts.repo_opts.allow_no_package_manager + { + match (&daemon, self.opts.run_opts.daemon) { + (None, Some(true)) => { + // We've asked for the daemon, but it's not available. This is an error + return Err(turborepo_repository::package_graph::Error::Discovery( + DiscoveryError::Unavailable, + ) + .into()); + }, + (Some(daemon), Some(true)) => { + // We have the daemon, and have explicitly asked to only use that + let daemon_discovery = DaemonPackageDiscovery::new(daemon.clone()); + builder.with_package_discovery(daemon_discovery).build().await + }, + (_, Some(false)) | (None, _) => { + // We have explicitly requested to not use the daemon, or we don't have it + // No change to default. + builder.build().await + }, + (Some(daemon), None) => { + // We have the daemon, and it's not flagged off. Use the fallback strategy + let daemon_discovery = DaemonPackageDiscovery::new(daemon.clone()); + let local_discovery = LocalPackageDiscoveryBuilder::new( + self.repo_root.clone(), + None, + Some(root_package_json.clone()), + ) + .build()?; + let fallback_discover = FallbackPackageDiscovery::new( + daemon_discovery, + local_discovery, + Duration::from_millis(10), + ); + builder.with_package_discovery(fallback_discover).build().await + }, + } + } else { + builder.build().await + }; + + match graph { + Ok(graph) => graph, + // if we can't find the package.json, it is a bug, and we should report it. + // likely cause is that package discovery watching is not up to date. + // note: there _is_ a false positive from a race condition that can occur + // from toctou if the package.json is deleted, but we'd like to know + Err(turborepo_repository::package_graph::Error::PackageJson( + package_json::Error::Io(io), + )) if io.kind() == ErrorKind::NotFound => { + run_telemetry.track_error(TrackedErrors::InvalidPackageDiscovery); + return Err(turborepo_repository::package_graph::Error::PackageJson( + package_json::Error::Io(io), + ) + .into()); + }, + Err(e) => return Err(e.into()), + } + }; + + repo_telemetry.track_package_manager(pkg_dep_graph.package_manager().name().to_string()); + repo_telemetry.track_size(pkg_dep_graph.len()); + run_telemetry.track_run_type(self.opts.run_opts.dry_run.is_some()); + let micro_frontend_configs = + MicrofrontendsConfigs::from_disk(&self.repo_root, &pkg_dep_graph)?; + + let scm = scm.await.expect("detecting scm panicked"); + let async_cache = AsyncCache::new( + &self.opts.cache_opts, + &self.repo_root, + self.api_client.clone(), + self.api_auth.clone(), + self.analytics_sender.take(), + )?; + + // restore config from task access trace if it's enabled + let task_access = TaskAccess::new(self.repo_root.clone(), async_cache.clone(), &scm); + task_access.restore_config().await; + + let mut turbo_json_loader = if task_access.is_enabled() { + TurboJsonLoader::task_access( + self.repo_root.clone(), + self.opts.repo_opts.root_turbo_json_path.clone(), + root_package_json.clone(), + ) + } else if is_single_package { + TurboJsonLoader::single_package( + self.repo_root.clone(), + self.opts.repo_opts.root_turbo_json_path.clone(), + root_package_json.clone(), + ) + } else if !self.opts.repo_opts.root_turbo_json_path.exists() && + // Infer a turbo.json if allowing no turbo.json is explicitly allowed or if MFE configs are discovered + (self.opts.repo_opts.allow_no_turbo_json || micro_frontend_configs.is_some()) + { + TurboJsonLoader::workspace_no_turbo_json( + self.repo_root.clone(), + pkg_dep_graph.packages(), + micro_frontend_configs.clone(), + ) + } else if let Some(micro_frontends) = µ_frontend_configs { + TurboJsonLoader::workspace_with_microfrontends( + self.repo_root.clone(), + self.opts.repo_opts.root_turbo_json_path.clone(), + pkg_dep_graph.packages(), + micro_frontends.clone(), + ) + } else { + TurboJsonLoader::workspace( + self.repo_root.clone(), + self.opts.repo_opts.root_turbo_json_path.clone(), + pkg_dep_graph.packages(), + ) + }; + + let root_turbo_json = turbo_json_loader.load(&PackageName::Root)?.clone(); + + pkg_dep_graph.validate()?; + + let filtered_pkgs = Self::calculate_filtered_packages( + &self.repo_root, + &self.opts, + &pkg_dep_graph, + &scm, + &root_turbo_json, + )?; + + let env_at_execution_start = EnvironmentVariableMap::infer(); + let mut engine = self.build_engine( + &pkg_dep_graph, + &root_turbo_json, + filtered_pkgs.keys(), + turbo_json_loader.clone(), + )?; + + if self.opts.run_opts.parallel { + pkg_dep_graph.remove_package_dependencies(); + engine = self.build_engine( + &pkg_dep_graph, + &root_turbo_json, + filtered_pkgs.keys(), + turbo_json_loader, + )?; + } + + let color_selector = ColorSelector::default(); + + let run_cache = Arc::new(RunCache::new( + async_cache, + &self.repo_root, + self.opts.runcache_opts, + &self.opts.cache_opts, + color_selector, + daemon.clone(), + self.color_config, + self.opts.run_opts.dry_run.is_some(), + )); + + let should_print_prelude = self.should_print_prelude_override.unwrap_or_else(|| { + self.opts.run_opts.dry_run.is_none() && self.opts.run_opts.graph.is_none() + }); + + Ok(Run { + version:self.version, + color_config:self.color_config, + start_at, + processes:self.processes, + run_telemetry, + task_access, + repo_root:self.repo_root, + opts:Arc::new(self.opts), + api_client:self.api_client, + api_auth:self.api_auth, + env_at_execution_start, + filtered_pkgs:filtered_pkgs.keys().cloned().collect(), + pkg_dep_graph:Arc::new(pkg_dep_graph), + root_turbo_json, + scm, + engine:Arc::new(engine), + run_cache, + signal_handler:signal_handler.clone(), + daemon, + should_print_prelude, + micro_frontend_configs, + }) + } + + fn build_engine<'a>( + &self, + pkg_dep_graph:&PackageGraph, + root_turbo_json:&TurboJson, + filtered_pkgs:impl Iterator, + turbo_json_loader:TurboJsonLoader, + ) -> Result { + let tasks = self.opts.run_opts.tasks.iter().map(|task| { + // TODO: Pull span info from command + Spanned::new(TaskName::from(task.as_str()).into_owned()) + }); + let mut builder = EngineBuilder::new( + &self.repo_root, + pkg_dep_graph, + turbo_json_loader, + self.opts.run_opts.single_package, + ) + .with_root_tasks(root_turbo_json.tasks.keys().cloned()) + .with_tasks_only(self.opts.run_opts.only) + .with_workspaces(filtered_pkgs.cloned().collect()) + .with_tasks(tasks); + + if self.add_all_tasks { + builder = builder.add_all_tasks(); + } + + if !self.should_validate_engine { + builder = builder.do_not_validate_engine(); + } + + let mut engine = builder.build()?; + + // If we have an initial task, we prune out the engine to only + // tasks that are reachable from that initial task. + if let Some(entrypoint_packages) = &self.entrypoint_packages { + engine = engine.create_engine_for_subgraph(entrypoint_packages); + } + + if !self.opts.run_opts.parallel && self.should_validate_engine { + engine + .validate(pkg_dep_graph, self.opts.run_opts.concurrency, self.opts.run_opts.ui_mode) + .map_err(Error::EngineValidation)?; + } + + Ok(engine) + } +} diff --git a/crates/turborepo-lib/src/run/cache.rs b/crates/turborepo-lib/Source/run/cache.rs similarity index 100% rename from crates/turborepo-lib/src/run/cache.rs rename to crates/turborepo-lib/Source/run/cache.rs diff --git a/crates/turborepo-lib/src/run/error.rs b/crates/turborepo-lib/Source/run/error.rs similarity index 100% rename from crates/turborepo-lib/src/run/error.rs rename to crates/turborepo-lib/Source/run/error.rs diff --git a/crates/turborepo-lib/src/run/global_hash.rs b/crates/turborepo-lib/Source/run/global_hash.rs similarity index 100% rename from crates/turborepo-lib/src/run/global_hash.rs rename to crates/turborepo-lib/Source/run/global_hash.rs diff --git a/crates/turborepo-lib/src/run/graph_visualizer.rs b/crates/turborepo-lib/Source/run/graph_visualizer.rs similarity index 100% rename from crates/turborepo-lib/src/run/graph_visualizer.rs rename to crates/turborepo-lib/Source/run/graph_visualizer.rs diff --git a/crates/turborepo-lib/src/run/mod.rs b/crates/turborepo-lib/Source/run/mod.rs similarity index 100% rename from crates/turborepo-lib/src/run/mod.rs rename to crates/turborepo-lib/Source/run/mod.rs diff --git a/crates/turborepo-lib/Source/run/package_discovery/mod.rs b/crates/turborepo-lib/Source/run/package_discovery/mod.rs new file mode 100644 index 0000000000000..b49f3d7fc0144 --- /dev/null +++ b/crates/turborepo-lib/Source/run/package_discovery/mod.rs @@ -0,0 +1,72 @@ +use turbopath::AbsoluteSystemPathBuf; +use turborepo_repository::discovery::{DiscoveryResponse, Error, PackageDiscovery, WorkspaceData}; + +use crate::daemon::{DaemonClient, proto::PackageManager}; + +#[derive(Debug)] +pub struct DaemonPackageDiscovery { + daemon:DaemonClient, +} + +impl DaemonPackageDiscovery { + pub fn new(daemon:DaemonClient) -> Self { Self { daemon } } +} + +impl PackageDiscovery for DaemonPackageDiscovery { + async fn discover_packages(&self) -> Result { + tracing::debug!("discovering packages using daemon"); + + // clone here so we can make concurrent requests + let mut daemon = self.daemon.clone(); + + let response = daemon.discover_packages().await.map_err(|e| Error::Failed(Box::new(e)))?; + + Ok(DiscoveryResponse { + workspaces:response + .package_files + .into_iter() + .map(|p| { + WorkspaceData { + package_json:AbsoluteSystemPathBuf::new(p.package_json).expect("absolute"), + turbo_json:p + .turbo_json + .map(|t| AbsoluteSystemPathBuf::new(t).expect("absolute")), + } + }) + .collect(), + package_manager:PackageManager::try_from(response.package_manager) + .expect("valid") + .into(), + }) + } + + async fn discover_packages_blocking(&self) -> Result { + tracing::debug!("discovering packages using daemon"); + + // clone here so we can make concurrent requests + let mut daemon = self.daemon.clone(); + + let response = daemon + .discover_packages_blocking() + .await + .map_err(|e| Error::Failed(Box::new(e)))?; + + Ok(DiscoveryResponse { + workspaces:response + .package_files + .into_iter() + .map(|p| { + WorkspaceData { + package_json:AbsoluteSystemPathBuf::new(p.package_json).expect("absolute"), + turbo_json:p + .turbo_json + .map(|t| AbsoluteSystemPathBuf::new(t).expect("absolute")), + } + }) + .collect(), + package_manager:PackageManager::try_from(response.package_manager) + .expect("valid") + .into(), + }) + } +} diff --git a/crates/turborepo-lib/src/run/scope/change_detector.rs b/crates/turborepo-lib/Source/run/scope/change_detector.rs similarity index 100% rename from crates/turborepo-lib/src/run/scope/change_detector.rs rename to crates/turborepo-lib/Source/run/scope/change_detector.rs diff --git a/crates/turborepo-lib/Source/run/scope/filter.rs b/crates/turborepo-lib/Source/run/scope/filter.rs new file mode 100644 index 0000000000000..6e1fb60ff08e7 --- /dev/null +++ b/crates/turborepo-lib/Source/run/scope/filter.rs @@ -0,0 +1,1335 @@ +use std::{ + collections::{HashMap, HashSet}, + path::Path, + str::FromStr, +}; + +use miette::Diagnostic; +use tracing::debug; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; +use turborepo_repository::{ + change_mapper::{ChangeMapError, PackageInclusionReason, merge_changed_packages}, + package_graph::{self, PackageGraph, PackageName}, +}; +use turborepo_scm::SCM; +use wax::Program; + +use super::{ + change_detector::GitChangeDetector, + simple_glob::{Match, SimpleGlob}, + target_selector::{GitRange, InvalidSelectorError, TargetSelector}, +}; +use crate::{run::scope::change_detector::ScopeChangeDetector, turbo_json::TurboJson}; + +pub struct PackageInference { + package_name:Option, + directory_root:AnchoredSystemPathBuf, +} + +impl PackageInference { + // calculate, based on the directory that global turbo was invoked in, + // the pieces of a filter spec that we will infer. If turbo was invoked + // somewhere between the root and packages, scope turbo invocations to the + // packages below where turbo was invoked. If turbo was invoked at or within + // a particular package, scope the turbo invocation to just that package. + pub fn calculate( + turbo_root:&AbsoluteSystemPath, + pkg_inference_path:&AnchoredSystemPathBuf, + pkg_graph:&PackageGraph, + ) -> Self { + debug!("Using {} as a basis for selecting packages", pkg_inference_path); + let full_inference_path = turbo_root.resolve(pkg_inference_path); + for (workspace_name, workspace_entry) in pkg_graph.packages() { + let pkg_path = turbo_root.resolve(workspace_entry.package_path()); + let inferred_path_is_below = pkg_path.contains(&full_inference_path); + // We skip over the root package as the inferred path will always be below it + if inferred_path_is_below && (&pkg_path as &AbsoluteSystemPath) != turbo_root { + // set both. The user might have set a parent directory filter, + // in which case we *should* fail to find any packages, but we should + // do so in a consistent manner + return Self { + package_name:Some(workspace_name.to_string()), + directory_root:workspace_entry.package_path().to_owned(), + }; + } + let inferred_path_is_between_root_and_pkg = full_inference_path.contains(&pkg_path); + if inferred_path_is_between_root_and_pkg { + // we've found *some* package below our inference directory. We can stop now and + // conclude that we're looking for all packages in a + // subdirectory + break; + } + } + Self { package_name:None, directory_root:pkg_inference_path.to_owned() } + } + + pub fn apply(&self, selector:&mut TargetSelector) { + // if the name pattern is provided, do not attempt inference + if !selector.name_pattern.is_empty() { + return; + }; + + if let Some(name) = &self.package_name { + selector.name_pattern.clone_from(name); + } + + if let Some(parent_dir) = selector.parent_dir.as_deref() { + let repo_relative_parent_dir = self.directory_root.join(parent_dir); + let clean_parent_dir = path_clean::clean(Path::new(repo_relative_parent_dir.as_path())) + .into_os_string() + .into_string() + .expect("path was valid utf8 before cleaning"); + selector.parent_dir = Some( + AnchoredSystemPathBuf::try_from(clean_parent_dir.as_str()) + .expect("path wasn't absolute before cleaning"), + ); + } else if self.package_name.is_none() { + // fallback: the user didn't set a parent directory and we didn't find a single + // package, so use the directory we inferred and select all subdirectories + let mut parent_dir = self.directory_root.clone(); + parent_dir.push("**"); + selector.parent_dir = Some(parent_dir); + } + } +} + +pub struct FilterResolver<'a, T:GitChangeDetector> { + pkg_graph:&'a PackageGraph, + turbo_root:&'a AbsoluteSystemPath, + inference:Option, + scm:&'a SCM, + change_detector:T, +} + +impl<'a> FilterResolver<'a, ScopeChangeDetector<'a>> { + pub(crate) fn new( + opts:&'a super::ScopeOpts, + pkg_graph:&'a PackageGraph, + turbo_root:&'a AbsoluteSystemPath, + inference:Option, + scm:&'a SCM, + root_turbo_json:&'a TurboJson, + ) -> Result { + let global_deps = opts + .global_deps + .iter() + .map(|s| s.as_str()) + .chain(root_turbo_json.global_deps.iter().map(|s| s.as_str())); + + let change_detector = + ScopeChangeDetector::new(turbo_root, scm, pkg_graph, global_deps, vec![])?; + + Ok(Self::new_with_change_detector( + pkg_graph, + turbo_root, + inference, + scm, + change_detector, + )) + } +} + +impl<'a, T:GitChangeDetector> FilterResolver<'a, T> { + pub(crate) fn new_with_change_detector( + pkg_graph:&'a PackageGraph, + turbo_root:&'a AbsoluteSystemPath, + inference:Option, + scm:&'a SCM, + change_detector:T, + ) -> Self { + Self { pkg_graph, turbo_root, inference, scm, change_detector } + } + + /// Resolves a set of filter patterns into a set of packages, + /// based on the current state of the workspace. The result is + /// guaranteed to be a subset of the packages in the workspace, + /// and non-empty. If the filter is empty, none of the packages + /// in the workspace will be returned. + /// + /// It applies the following rules: + pub(crate) fn resolve( + &self, + affected:&Option<(Option, Option)>, + patterns:&[String], + ) -> Result<(HashMap, bool), ResolutionError> { + // inference is None only if we are in the root + let is_all_packages = patterns.is_empty() && self.inference.is_none() && affected.is_none(); + + let filter_patterns = if is_all_packages { + // return all packages in the workspace + self.pkg_graph + .packages() + .filter(|(name, _)| matches!(name, PackageName::Other(_))) + .map(|(name, _)| { + ( + name.to_owned(), + PackageInclusionReason::IncludedByFilter { filters:patterns.to_vec() }, + ) + }) + .collect() + } else { + self.get_packages_from_patterns(affected, patterns)? + }; + + Ok((filter_patterns, is_all_packages)) + } + + fn get_packages_from_patterns( + &self, + affected:&Option<(Option, Option)>, + patterns:&[String], + ) -> Result, ResolutionError> { + let mut selectors = patterns + .iter() + .map(|pattern| TargetSelector::from_str(pattern)) + .collect::, _>>()?; + + if let Some((from_ref, to_ref)) = affected { + selectors.push(TargetSelector { + git_range:Some(GitRange { + from_ref:from_ref.clone(), + to_ref:to_ref.clone(), + include_uncommitted:true, + allow_unknown_objects:true, + merge_base:true, + }), + include_dependents:true, + ..Default::default() + }); + } + + self.get_filtered_packages(selectors) + } + + fn get_filtered_packages( + &self, + selectors:Vec, + ) -> Result, ResolutionError> { + let (_prod_selectors, all_selectors) = self + .apply_inference(selectors) + .into_iter() + .partition::, _>(|t| t.follow_prod_deps_only); + + if !all_selectors.is_empty() { + self.filter_graph(all_selectors) + } else { + Ok(Default::default()) + } + } + + fn apply_inference(&self, selectors:Vec) -> Vec { + let inference = match self.inference { + Some(ref inference) => inference, + None => return selectors, + }; + + // if there is no selector provided, synthesize one + let mut selectors = if selectors.is_empty() { vec![Default::default()] } else { selectors }; + + for selector in &mut selectors { + inference.apply(selector); + } + + selectors + } + + fn filter_graph( + &self, + selectors:Vec, + ) -> Result, ResolutionError> { + let (include_selectors, exclude_selectors) = + selectors.into_iter().partition::, _>(|t| !t.exclude); + + let mut include = if !include_selectors.is_empty() { + // TODO: add telemetry for each selector + self.filter_graph_with_selectors(include_selectors)? + } else { + self.pkg_graph + .packages() + // todo: a type-level way of dealing with non-root packages + .filter(|(name, _)| !PackageName::Root.eq(name)) // the root package has to be explicitly included + .map(|(name, _)| { + ( + name.to_owned(), + PackageInclusionReason::IncludedByFilter { + filters: exclude_selectors + .iter() + .map(|s| s.raw.to_string()) + .collect(), + }, + ) + }) + .collect() + }; + + // We want to just collect the names, not the reasons, so when we check for + // inclusion we don't need to check the reason + let exclude:HashSet = + self.filter_graph_with_selectors(exclude_selectors)?.into_keys().collect(); + + include.retain(|i, _| !exclude.contains(i)); + + Ok(include) + } + + fn filter_graph_with_selectors( + &self, + selectors:Vec, + ) -> Result, ResolutionError> { + let mut unmatched_selectors = Vec::new(); + let mut walked_dependencies = HashMap::new(); + let mut walked_dependents = HashMap::new(); + let mut walked_dependent_dependencies = HashMap::new(); + let mut cherry_picked_packages = HashMap::new(); + + for selector in selectors { + let selector_packages = self.filter_graph_with_selector(&selector)?; + + if selector_packages.is_empty() { + unmatched_selectors.push(selector); + continue; + } + + for (package, reason) in selector_packages { + let node = package_graph::PackageNode::Workspace(package.clone()); + + if selector.include_dependencies { + let dependencies = self.pkg_graph.dependencies(&node); + let dependencies = dependencies + .iter() + .filter(|node| !matches!(node, package_graph::PackageNode::Root)) + .map(|i| { + ( + i.as_package_name().to_owned(), + // While we're adding dependencies, from their + // perspective, they were changed because + // of a *dependent* + PackageInclusionReason::DependentChanged { + dependent:package.to_owned(), + }, + ) + }) + .collect::>(); + + // flatmap through the option, the set, and then the optional package name + merge_changed_packages(&mut walked_dependencies, dependencies); + } + + if selector.include_dependents { + let dependents = self.pkg_graph.ancestors(&node); + for dependent in dependents.iter().map(|i| i.as_package_name()) { + walked_dependents.insert( + dependent.clone(), + // While we're adding dependents, from their + // perspective, they were changed because + // of a *dependency* + PackageInclusionReason::DependencyChanged { + dependency:package.to_owned(), + }, + ); + + // get the dependent's dependencies + if selector.include_dependencies { + let dependent_node = + package_graph::PackageNode::Workspace(dependent.to_owned()); + + let dependent_dependencies = + self.pkg_graph.dependencies(&dependent_node); + + let dependent_dependencies = dependent_dependencies + .iter() + .filter(|node| !matches!(node, package_graph::PackageNode::Root)) + .map(|i| { + ( + i.as_package_name().to_owned(), + PackageInclusionReason::DependencyChanged { + dependency:package.to_owned(), + }, + ) + }) + .collect::>(); + + merge_changed_packages( + &mut walked_dependent_dependencies, + dependent_dependencies, + ); + } + } + } + + if (selector.include_dependents || selector.include_dependencies) + && !selector.exclude_self + { + // if we are including dependents or dependencies, and we are not excluding + // ourselves, then we should add ourselves to the list of packages + walked_dependencies.insert(package, reason); + } else if !selector.include_dependencies && !selector.include_dependents { + // if we are neither including dependents or dependencies, then + // add to the list of cherry picked packages + cherry_picked_packages.insert(package, reason); + } + } + } + + let mut all_packages = HashMap::new(); + merge_changed_packages(&mut all_packages, walked_dependencies); + merge_changed_packages(&mut all_packages, walked_dependents); + merge_changed_packages(&mut all_packages, walked_dependent_dependencies); + merge_changed_packages(&mut all_packages, cherry_picked_packages); + + Ok(all_packages) + } + + fn filter_graph_with_selector( + &self, + selector:&TargetSelector, + ) -> Result, ResolutionError> { + if selector.match_dependencies { + self.filter_subtrees_with_selector(selector) + } else { + self.filter_nodes_with_selector(selector) + } + } + + /// returns the set of nodes where the node or any of its dependencies match + /// the selector. + /// + /// Example: + /// a -> b -> c + /// a -> d + /// + /// filter(b) = {a, b, c} + /// filter(d) = {a, d} + fn filter_subtrees_with_selector( + &self, + selector:&TargetSelector, + ) -> Result, ResolutionError> { + let mut entry_packages = HashMap::new(); + + for (name, info) in self.pkg_graph.packages() { + if let Some(parent_dir) = selector.parent_dir.as_deref() { + let path = parent_dir.to_unix(); + let parent_dir_matcher = wax::Glob::new(path.as_str())?; + let matches = parent_dir_matcher.is_match(info.package_path().as_path()); + + if matches { + entry_packages.insert( + name.to_owned(), + PackageInclusionReason::InFilteredDirectory { + directory:parent_dir.to_owned(), + }, + ); + } + } else { + entry_packages.insert( + name.to_owned(), + PackageInclusionReason::IncludedByFilter { + filters:vec![selector.raw.to_string()], + }, + ); + } + } + + // if we have a filter, use it to filter the entry packages + let filtered_entry_packages = if !selector.name_pattern.is_empty() { + match_package_names(&selector.name_pattern, &self.all_packages(), entry_packages)? + } else { + entry_packages + }; + + let mut roots = HashMap::new(); + let mut matched = HashSet::new(); + let changed_packages = if let Some(git_range) = selector.git_range.as_ref() { + self.packages_changed_in_range(git_range)? + } else { + HashMap::default() + }; + + for (package, reason) in filtered_entry_packages { + if matched.contains(&package) { + roots.insert(package, reason); + continue; + } + + let workspace_node = package_graph::PackageNode::Workspace(package.clone()); + let dependencies = self.pkg_graph.dependencies(&workspace_node); + + for changed_package in changed_packages.keys() { + if !selector.exclude_self && package.eq(changed_package) { + roots.insert(package, reason); + break; + } + + let changed_node = + package_graph::PackageNode::Workspace(changed_package.to_owned()); + + if dependencies.contains(&changed_node) { + roots.insert(package.clone(), reason); + matched.insert(package); + break; + } + } + } + + Ok(roots) + } + + fn filter_nodes_with_selector( + &self, + selector:&TargetSelector, + ) -> Result, ResolutionError> { + let mut entry_packages = HashMap::new(); + let mut selector_valid = false; + + let parent_dir_unix = selector.parent_dir.as_deref().map(|path| path.to_unix()); + let parent_dir_globber = parent_dir_unix + .as_deref() + .map(|path| { + wax::Glob::new(path.as_str()).map_err(|err| { + ResolutionError::InvalidDirectoryGlob { + glob:path.as_str().to_string(), + err:Box::new(err), + } + }) + }) + .transpose()?; + + if let Some(globber) = parent_dir_globber.clone() { + let (base, _) = globber.partition(); + // wax takes a unix-like glob, but partition will return a system path + // TODO: it would be more proper to use + // `AnchoredSystemPathBuf::from_system_path` but that function + // doesn't allow leading `.` or `..`. + let base = AnchoredSystemPathBuf::from_raw( + base.to_str().expect("glob base should be valid utf8"), + ) + .expect("partitioned glob gave absolute path"); + // need to join this with globbing's current dir :) + let path = self.turbo_root.resolve(&base); + if !path.exists() { + return Err(ResolutionError::DirectoryDoesNotExist(path)); + } + } + + if let Some(git_range) = selector.git_range.as_ref() { + selector_valid = true; + let changed_packages = self.packages_changed_in_range(git_range)?; + let package_path_lookup = self + .pkg_graph + .packages() + .map(|(name, entry)| (name, entry.package_path())) + .collect::>(); + + for (package, reason) in changed_packages { + if let Some(parent_dir_globber) = parent_dir_globber.as_ref() { + if package == PackageName::Root { + // The root package changed, only add it if + // the parentDir is equivalent to the root + if parent_dir_globber.matched(&Path::new(".").into()).is_some() { + entry_packages.insert(package, reason); + } + } else { + let path = package_path_lookup + .get(&package) + .ok_or(ResolutionError::MissingPackageInfo(package.to_string()))?; + + if parent_dir_globber.is_match(path.as_path()) { + entry_packages.insert(package, reason); + } + } + } else { + entry_packages.insert(package, reason); + } + } + } else if let Some((parent_dir, parent_dir_globber)) = + selector.parent_dir.as_deref().zip(parent_dir_globber.as_ref()) + { + selector_valid = true; + if parent_dir == &*AnchoredSystemPathBuf::from_raw(".").expect("valid anchored") { + entry_packages.insert( + PackageName::Root, + PackageInclusionReason::InFilteredDirectory { directory:parent_dir.to_owned() }, + ); + } else { + let packages = self.pkg_graph.packages(); + for (name, _) in packages.filter(|(_name, info)| { + let path = info.package_path().as_path(); + parent_dir_globber.is_match(path) + }) { + entry_packages.insert( + name.to_owned(), + PackageInclusionReason::InFilteredDirectory { + directory:parent_dir.to_owned(), + }, + ); + } + } + } + + if !selector.name_pattern.is_empty() { + if !selector_valid { + entry_packages = self + .all_packages() + .into_iter() + .map(|name| { + ( + name, + PackageInclusionReason::IncludedByFilter { + filters:vec![selector.raw.to_string()], + }, + ) + }) + .collect(); + selector_valid = true; + } + let all_packages = self.all_packages(); + entry_packages = + match_package_names(&selector.name_pattern, &all_packages, entry_packages)?; + } + + // if neither a name pattern, parent dir, or from ref is provided, then + // the selector is invalid + if !selector_valid { + Err(ResolutionError::InvalidSelector(InvalidSelectorError::InvalidSelector( + selector.raw.clone(), + ))) + } else { + Ok(entry_packages) + } + } + + pub fn packages_changed_in_range( + &self, + git_range:&GitRange, + ) -> Result, ResolutionError> { + self.change_detector.changed_packages( + git_range.from_ref.as_deref(), + git_range.to_ref.as_deref(), + git_range.include_uncommitted, + git_range.allow_unknown_objects, + git_range.merge_base, + ) + } + + fn all_packages(&self) -> HashSet { + let mut packages = self + .pkg_graph + .packages() + .map(|(name, _)| name.to_owned()) + .collect::>(); + packages.insert(PackageName::Root); + packages + } +} + +/// match the provided name pattern against the provided set of packages +/// and return the set of packages that match the pattern +/// +/// the pattern is normalized, replacing `\*` with `.*` +fn match_package_names( + name_pattern:&str, + all_packages:&HashSet, + mut packages:HashMap, +) -> Result, ResolutionError> { + let matcher = SimpleGlob::new(name_pattern)?; + let matched_packages = all_packages + .iter() + .filter(|e| matcher.is_match(e.as_ref())) + .cloned() + .collect::>(); + + // If the pattern was an exact name and it matched no packages, then error + if matcher.is_exact() && matched_packages.is_empty() { + return Err(ResolutionError::NoPackagesMatchedWithName(name_pattern.to_owned())); + } + + packages.retain(|pkg, _| matched_packages.contains(pkg)); + + Ok(packages) +} + +#[derive(Debug, thiserror::Error, Diagnostic)] +pub enum ResolutionError { + #[error("missing info for package")] + MissingPackageInfo(String), + #[error("No packages matched the provided filter")] + NoPackagesMatched, + #[error("Multiple packages matched the provided filter")] + MultiplePackagesMatched, + #[error("The provided filter matched a package that is not in the workspace")] + PackageNotInWorkspace, + #[error("No package found with name '{0}' in workspace")] + NoPackagesMatchedWithName(String), + #[error("selector not used: {0}")] + InvalidSelector(#[from] InvalidSelectorError), + #[error("Invalid regex pattern")] + InvalidRegex(#[from] regex::Error), + #[error("Invalid glob pattern")] + InvalidGlob(#[from] wax::BuildError), + #[error("Unable to query SCM: {0}")] + Scm(#[from] turborepo_scm::Error), + #[error("Unable to calculate changes: {0}")] + ChangeDetectError(#[from] ChangeMapError), + #[error("'Invalid directory filter '{glob}': {err}")] + InvalidDirectoryGlob { glob:String, err:Box }, + #[error("Directory '{0}' specified in filter does not exist")] + DirectoryDoesNotExist(AbsoluteSystemPathBuf), + #[error("failed to construct glob for globalDependencies")] + GlobalDependenciesGlob(#[from] turborepo_repository::change_mapper::Error), +} + +#[cfg(test)] +mod test { + use std::collections::{HashMap, HashSet}; + + use pretty_assertions::assert_eq; + use tempfile::TempDir; + use test_case::test_case; + use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf, RelativeUnixPathBuf}; + use turborepo_repository::{ + change_mapper::PackageInclusionReason, + discovery::PackageDiscovery, + package_graph::{PackageGraph, PackageName, ROOT_PKG_NAME}, + package_json::PackageJson, + package_manager::PackageManager, + }; + + use super::{FilterResolver, PackageInference, TargetSelector}; + use crate::run::scope::{ + ResolutionError, + change_detector::GitChangeDetector, + target_selector::GitRange, + }; + + fn get_name(name:&str) -> (Option<&str>, &str) { + if let Some(idx) = name.rfind('/') { + // check if the rightmost slash has an @ + if let Some(idx) = name[..idx].find('@') { + return (Some(&name[..idx - 1]), &name[idx..]); + } + + return (Some(&name[..idx]), &name[idx + 1..]); + } + + (None, name) + } + + fn reverse(tuple:(T, U)) -> (U, T) { + let (a, b) = tuple; + (b, a) + } + + struct MockDiscovery; + impl PackageDiscovery for MockDiscovery { + async fn discover_packages( + &self, + ) -> Result< + turborepo_repository::discovery::DiscoveryResponse, + turborepo_repository::discovery::Error, + > { + Ok(turborepo_repository::discovery::DiscoveryResponse { + package_manager:PackageManager::Pnpm6, + workspaces:vec![], // we don't care about this + }) + } + + async fn discover_packages_blocking( + &self, + ) -> Result< + turborepo_repository::discovery::DiscoveryResponse, + turborepo_repository::discovery::Error, + > { + self.discover_packages().await + } + } + + /// Make a project resolver with the provided dependencies. Extras is for + /// packages that are not dependencies of any other package. + fn make_project( + dependencies:&[(&str, &str)], + extras:&[&str], + package_inference:Option, + change_detector:T, + ) -> (TempDir, super::FilterResolver<'static, T>) { + let temp_folder = tempfile::tempdir().unwrap(); + let turbo_root = Box::leak(Box::new( + AbsoluteSystemPathBuf::new(temp_folder.path().as_os_str().to_str().unwrap()).unwrap(), + )); + + let package_dirs = dependencies + .iter() + .flat_map(|(a, b)| vec![a, b]) + .chain(extras.iter()) + .collect::>(); + + let dependencies = + dependencies.iter().fold(HashMap::<&str, Vec<&str>>::new(), |mut acc, (k, v)| { + let k = get_name(k).1; + let v = get_name(v).1; + acc.entry(k).or_default().push(v); + acc + }); + + let package_jsons = package_dirs + .iter() + .map(|package_path| { + let (_, name) = get_name(package_path); + ( + turbo_root.join_unix_path( + RelativeUnixPathBuf::new(format!("{package_path}/package.json")).unwrap(), + ), + PackageJson { + name:Some(name.to_string()), + dependencies:dependencies.get(name).map(|v| { + v.iter().map(|name| (name.to_string(), "*".to_string())).collect() + }), + ..Default::default() + }, + ) + }) + .collect::>(); + + for package_dir in package_jsons.keys() { + package_dir.ensure_dir().unwrap(); + } + + let graph = { + let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); + rt.block_on( + PackageGraph::builder(turbo_root, Default::default()) + .with_package_discovery(MockDiscovery) + .with_package_jsons(Some(package_jsons)) + .build(), + ) + .unwrap() + }; + + let pkg_graph = Box::leak(Box::new(graph)); + + let scm = Box::leak(Box::new(turborepo_scm::SCM::new(turbo_root))); + + let resolver = FilterResolver::<'static>::new_with_change_detector( + pkg_graph, + turbo_root, + package_inference, + scm, + change_detector, + ); + + // TempDir's drop implementation will mark the folder as ready for cleanup + // which can lead to non-deterministic test results if the folder is removed + // before the test finishes. + (temp_folder, resolver) + } + + #[test_case( + vec![ + TargetSelector { + name_pattern: ROOT_PKG_NAME.to_string(), + ..Default::default() + } + ], + None, + &[ROOT_PKG_NAME] ; + "select root package" + )] + #[test_case( + vec![ + TargetSelector { + exclude_self: true, + include_dependencies: true, + name_pattern: "project-1".to_string(), + ..Default::default() + } + ], + None, + &["project-2", "project-4"] ; + "select only package dependencies (excluding the package itself)" + )] + #[test_case( + vec![ + TargetSelector { + exclude_self: false, + include_dependencies: true, + name_pattern: "project-1".to_string(), + ..Default::default() + } + ], + None, + &["project-1", "project-2", "project-4"] ; + "select package with dependencies" + )] + #[test_case( + vec![ + TargetSelector { + exclude_self: false, + include_dependencies: true, + name_pattern: "project-0".to_string(), + ..Default::default() + } + ], + None, + &["project-0", "project-1", "project-2", "project-4", "project-5"] ; + "select package with transitive dependencies" + )] + #[test_case( + vec![ + TargetSelector { + exclude_self: true, + include_dependencies: true, + include_dependents: true, + name_pattern: "project-1".to_string(), + ..Default::default() + } + ], + None, + &["project-0", "project-1", "project-2", "project-4", "project-5"] ; + "select package with dependencies and dependents, including dependent + dependencies" )] + #[test_case( + vec![ + TargetSelector { + include_dependents: true, + name_pattern: "project-2".to_string(), + ..Default::default() + } + ], + None, + &["project-1", "project-2", "project-0"] ; + "select package with dependents" + )] + #[test_case( + vec![ + TargetSelector { + exclude_self: true, + include_dependents: true, + name_pattern: "project-2".to_string(), + ..Default::default() + } + ], + None, + &["project-0", "project-1"] ; + "select dependents excluding package itself" + )] + #[test_case( + vec![ + TargetSelector { + exclude_self: true, + include_dependents: true, + name_pattern: "project-2".to_string(), + ..Default::default() + }, + TargetSelector { + include_dependencies: true, + exclude_self: true, + name_pattern: "project-1".to_string(), + ..Default::default() + } + ], + None, + &["project-0", "project-1", "project-2", "project-4"] ; + "filter using two selectors: one selects dependencies another selects + dependents" )] + #[test_case( + vec![ + TargetSelector { + name_pattern: "project-2".to_string(), + ..Default::default() + } + ], + None, + &["project-2"] ; + "select just a package by name" + )] + #[test_case( + vec![ + TargetSelector { + parent_dir: + Some(AnchoredSystemPathBuf::try_from("packages/*").unwrap()), + ..Default::default() } + ], + None, + &["project-0", "project-1"] ; + "select by parentDir using glob" + )] + #[test_case( + vec![TargetSelector { + parent_dir: Some(AnchoredSystemPathBuf::try_from(if cfg!(windows) { "..\\packages\\*" } else { "../packages/*" }).unwrap()), + ..Default::default() + }], + Some(PackageInference{ + package_name: None, + directory_root: AnchoredSystemPathBuf::try_from("project-5").unwrap(), + }), + &["project-0", "project-1"] ; + "select sibling directory" + )] + #[test_case( + vec![ + TargetSelector { + parent_dir: + Some(AnchoredSystemPathBuf::try_from("project-5/**").unwrap()), + ..Default::default() } + ], + None, + &["project-5", "project-6"] ; + "select by parentDir using globstar" + )] + #[test_case( + vec![ + TargetSelector { + parent_dir: + Some(AnchoredSystemPathBuf::try_from("project-5").unwrap()), + ..Default::default() } + ], + None, + &["project-5"] ; + "select by parentDir with no glob" + )] + #[test_case( + vec![ + TargetSelector { + exclude: true, + name_pattern: "project-1".to_string(), + ..Default::default() + } + ], + None, + &["project-0", "project-2", "project-3", "project-4", "project-5", "project-6"] ; + "select all packages except one" + )] + #[test_case( + vec![ + TargetSelector { + parent_dir: Some(AnchoredSystemPathBuf::try_from("packages/*").unwrap()), + ..Default::default() + }, + TargetSelector { + exclude: true, + name_pattern: "*-1".to_string(), + ..Default::default() + } + ], + None, + &["project-0"] ; + "select by parentDir and exclude one package by pattern" + )] + #[test_case( + vec![ + TargetSelector { + parent_dir: Some(AnchoredSystemPathBuf::try_from(".").unwrap()), + ..Default::default() + } + ], + None, + &[ROOT_PKG_NAME] ; + "select root package by directory" + )] + #[test_case( + vec![], + Some(PackageInference{ + package_name: None, + directory_root: AnchoredSystemPathBuf::try_from("packages").unwrap(), + }), + &["project-0", "project-1"] ; + "select packages directory" + )] + #[test_case( + vec![], + Some(PackageInference{ + package_name: Some("project-0".to_string()), + directory_root: AnchoredSystemPathBuf::try_from("packages/project-0").unwrap(), + }), + &["project-0"] ; + "infer single package" + )] + #[test_case( + vec![], + Some(PackageInference{ + package_name: Some("project-0".to_string()), + directory_root: AnchoredSystemPathBuf::try_from("packages/project-0/src").unwrap(), + }), + &["project-0"] ; + "infer single package from subdirectory" + )] + fn filter( + selectors:Vec, + package_inference:Option, + expected:&[&str], + ) { + let (_tempdir, resolver) = make_project( + &[ + ("packages/project-0", "packages/project-1"), + ("packages/project-0", "project-5"), + ("packages/project-1", "project-2"), + ("packages/project-1", "project-4"), + ], + &["project-3", "project-5/packages/project-6"], + package_inference, + TestChangeDetector::new(&[]), + ); + + let packages = resolver.get_filtered_packages(selectors).unwrap(); + + assert_eq!( + packages.into_keys().collect::>(), + expected.iter().map(|s| PackageName::from(*s)).collect() + ); + } + + #[test] + fn match_exact() { + let (_tempdir, resolver) = make_project( + &[], + &["packages/@foo/bar", "packages/bar"], + None, + TestChangeDetector::new(&[]), + ); + let packages = resolver + .get_filtered_packages(vec![TargetSelector { + name_pattern:"bar".to_string(), + raw:"bar".to_string(), + ..Default::default() + }]) + .unwrap(); + + assert_eq!( + packages, + vec![( + PackageName::Other("bar".to_string()), + PackageInclusionReason::IncludedByFilter { filters:vec!["bar".to_string()] } + )] + .into_iter() + .collect() + ); + } + + #[test] + fn match_scoped_package() { + let (_tempdir, resolver) = + make_project(&[], &["packages/bar/@foo/bar"], None, TestChangeDetector::new(&[])); + let packages = resolver.get_filtered_packages(vec![TargetSelector { + name_pattern:"bar".to_string(), + raw:"bar".to_string(), + ..Default::default() + }]); + + assert!(packages.is_err(), "non existing package name should error",); + + let packages = resolver + .get_filtered_packages(vec![TargetSelector { + name_pattern:"@foo/bar".to_string(), + raw:"@foo/bar".to_string(), + ..Default::default() + }]) + .unwrap(); + + assert_eq!( + packages, + vec![( + PackageName::from("@foo/bar"), + PackageInclusionReason::IncludedByFilter { filters:vec!["@foo/bar".to_string()] } + )] + .into_iter() + .collect() + ); + } + + #[test] + fn test_no_matching_name() { + let (_tempdir, resolver) = + make_project(&[], &["packages/bar/@foo/bar"], None, TestChangeDetector::new(&[])); + let packages = resolver.get_filtered_packages(vec![TargetSelector { + name_pattern:"bar".to_string(), + ..Default::default() + }]); + + assert!(packages.is_err(), "non existing package name should error",); + + let packages = resolver + .get_filtered_packages(vec![TargetSelector { + name_pattern:"baz*".to_string(), + ..Default::default() + }]) + .unwrap(); + assert!(packages.is_empty(), "expected no matches, got {:?}", packages); + } + + #[test] + fn test_no_directory() { + let (_tempdir, resolver) = make_project( + &[("packages/foo", "packages/bar")], + &[], + None, + TestChangeDetector::new(&[]), + ); + let packages = resolver.get_filtered_packages(vec![TargetSelector { + parent_dir:Some(AnchoredSystemPathBuf::try_from("pakcages/*").unwrap()), + ..Default::default() + }]); + + assert!(packages.is_err(), "non existing dir should error",); + } + + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), + ..Default::default() + } + ], + &["package-1", "package-2", ROOT_PKG_NAME] ; + "all changed packages" + )] + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), + parent_dir: Some(AnchoredSystemPathBuf::try_from(".").unwrap()), + ..Default::default() + } + ], + &[ROOT_PKG_NAME] ; + "all changed packages with parent dir exact match" + )] + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), + parent_dir: Some(AnchoredSystemPathBuf::try_from("package-2").unwrap()), + ..Default::default() + } + ], + &["package-2"] ; + "changed packages in directory" + )] + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), + name_pattern: "package-2*".to_string(), + ..Default::default() + } + ], + &["package-2"] ; + "changed packages matching pattern" + )] + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), + name_pattern: "package-1".to_string(), + match_dependencies: true, + ..Default::default() + } + ], + &["package-1"] ; + "changed package was requested scope, and we're matching dependencies" + )] + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~2".to_string()), to_ref: None, ..Default::default() }), + ..Default::default() + } + ], + &["package-1", "package-2", "package-3", ROOT_PKG_NAME] ; + "older commit" + )] + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~2".to_string()), to_ref: Some("HEAD~1".to_string()), ..Default::default() }), + ..Default::default() + } + ], + &["package-3"] ; + "commit range" + )] + #[test_case( + vec![ + TargetSelector { + git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), + parent_dir: Some(AnchoredSystemPathBuf::try_from("package-*").unwrap()), + match_dependencies: true, ..Default::default() + } + ], + &["package-1", "package-2"] ; + "match dependency subtree" + )] + #[test_case( + vec![ + TargetSelector { + name_pattern: "package-3".to_string(), + git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), + ..Default::default() + } + ], + &[] ; + "gh 9096" + )] + fn scm(selectors:Vec, expected:&[&str]) { + let scm_resolver = TestChangeDetector::new(&[ + ("HEAD~1", None, &["package-1", "package-2", ROOT_PKG_NAME]), + ("HEAD~2", Some("HEAD~1"), &["package-3"]), + ("HEAD~2", None, &["package-1", "package-2", "package-3", ROOT_PKG_NAME]), + ]); + + let (_tempdir, resolver) = make_project( + &[("package-3", "package-20")], + &["package-1", "package-2"], + None, + scm_resolver, + ); + + let packages = resolver.get_filtered_packages(selectors).unwrap(); + assert_eq!( + packages.into_keys().collect::>(), + expected.iter().map(|s| PackageName::from(*s)).collect() + ); + } + + struct TestChangeDetector<'a>( + HashMap<(&'a str, Option<&'a str>), HashMap>, + ); + + impl<'a> TestChangeDetector<'a> { + fn new(pairs:&[(&'a str, Option<&'a str>, &[&'a str])]) -> Self { + let mut map = HashMap::new(); + for (from, to, changed) in pairs { + map.insert( + (*from, *to), + changed + .iter() + .map(|s| { + ( + PackageName::from(*s), + // This is just a random reason, + PackageInclusionReason::IncludedByFilter { filters:vec![] }, + ) + }) + .collect(), + ); + } + + Self(map) + } + } + + impl<'a> GitChangeDetector for TestChangeDetector<'a> { + fn changed_packages( + &self, + from:Option<&str>, + to:Option<&str>, + _include_uncommitted:bool, + _allow_unknown_objects:bool, + _merge_base:bool, + ) -> Result, ResolutionError> { + Ok(self + .0 + .get(&(from.expect("expected base branch"), to)) + .map(|h| h.to_owned()) + .expect("unsupported range")) + } + } +} diff --git a/crates/turborepo-lib/Source/run/scope/mod.rs b/crates/turborepo-lib/Source/run/scope/mod.rs new file mode 100644 index 0000000000000..3f3a76977ac1b --- /dev/null +++ b/crates/turborepo-lib/Source/run/scope/mod.rs @@ -0,0 +1,33 @@ +mod change_detector; +pub mod filter; +mod simple_glob; +pub mod target_selector; + +use std::collections::HashMap; + +use filter::{FilterResolver, PackageInference}; +use turbopath::AbsoluteSystemPath; +use turborepo_repository::{ + change_mapper::PackageInclusionReason, + package_graph::{PackageGraph, PackageName}, +}; +use turborepo_scm::SCM; + +pub use crate::run::scope::filter::ResolutionError; +use crate::{opts::ScopeOpts, turbo_json::TurboJson}; + +#[tracing::instrument(skip(opts, pkg_graph, scm))] +pub fn resolve_packages( + opts:&ScopeOpts, + turbo_root:&AbsoluteSystemPath, + pkg_graph:&PackageGraph, + scm:&SCM, + root_turbo_json:&TurboJson, +) -> Result<(HashMap, bool), ResolutionError> { + let pkg_inference = opts.pkg_inference_root.as_ref().map(|pkg_inference_path| { + PackageInference::calculate(turbo_root, pkg_inference_path, pkg_graph) + }); + + FilterResolver::new(opts, pkg_graph, turbo_root, pkg_inference, scm, root_turbo_json)? + .resolve(&opts.affected_range, &opts.get_filters()) +} diff --git a/crates/turborepo-lib/Source/run/scope/simple_glob.rs b/crates/turborepo-lib/Source/run/scope/simple_glob.rs new file mode 100644 index 0000000000000..1edfd66c40ae6 --- /dev/null +++ b/crates/turborepo-lib/Source/run/scope/simple_glob.rs @@ -0,0 +1,77 @@ +use regex::Regex; + +/// A simple glob-like pattern that supports a subset of +/// glob syntax for the purposes of string matching. +/// If you are matching paths, use `turborepo_wax::glob::Glob` instead. +pub enum SimpleGlob { + Regex(Regex), + String(String), + Any, +} + +pub trait Match { + fn is_match(&self, s:&str) -> bool; +} + +impl SimpleGlob { + pub fn new(pattern:&str) -> Result { + if pattern == "*" { + Ok(SimpleGlob::Any) + } else if pattern.contains('*') { + let regex = Regex::new(&format!("^{}$", pattern.replace('*', ".*")))?; + Ok(SimpleGlob::Regex(regex)) + } else { + Ok(SimpleGlob::String(pattern.to_string())) + } + } + + pub fn is_exact(&self) -> bool { matches!(self, Self::String(_)) } +} + +impl Match for SimpleGlob { + fn is_match(&self, s:&str) -> bool { + match self { + SimpleGlob::Regex(regex) => regex.is_match(s), + SimpleGlob::String(string) => string == s, + SimpleGlob::Any => true, + } + } +} + +pub struct AnyGlob(Vec); + +impl Match for AnyGlob { + fn is_match(&self, s:&str) -> bool { self.0.iter().any(|glob| glob.is_match(s)) } +} + +pub struct NotGlob(T); + +impl Match for NotGlob { + fn is_match(&self, s:&str) -> bool { !self.0.is_match(s) } +} + +pub struct IncludeExcludeGlob { + include:I, + exclude:E, +} + +impl IncludeExcludeGlob, AnyGlob> { + pub fn new_from_globs<'a>( + include:impl Iterator>, + exclude:impl Iterator>, + _include_default:bool, + _exclude_default:bool, + ) -> Self { + let include = + AnyGlob(include.map(|glob| SimpleGlob::new(glob.as_ref()).unwrap()).collect()); + + let exclude = + AnyGlob(exclude.map(|glob| SimpleGlob::new(glob.as_ref()).unwrap()).collect()); + + Self { include, exclude } + } +} + +impl Match for IncludeExcludeGlob { + fn is_match(&self, s:&str) -> bool { self.include.is_match(s) && !self.exclude.is_match(s) } +} diff --git a/crates/turborepo-lib/Source/run/scope/target_selector.rs b/crates/turborepo-lib/Source/run/scope/target_selector.rs new file mode 100644 index 0000000000000..b45573137ae32 --- /dev/null +++ b/crates/turborepo-lib/Source/run/scope/target_selector.rs @@ -0,0 +1,296 @@ +use std::str::FromStr; + +use regex::Regex; +use thiserror::Error; +use turbopath::AnchoredSystemPathBuf; + +#[derive(Debug, Default, PartialEq)] +pub struct GitRange { + pub from_ref:Option, + pub to_ref:Option, + pub include_uncommitted:bool, + // Allow unknown objects to be included in the range, without returning an error. + // this is useful for shallow clones where objects may not exist. + // When this happens, we assume that everything has changed. + pub allow_unknown_objects:bool, + // Calculate diff between merge base of the two refs and the second ref + // (this is usually what you want for detecting changes) + pub merge_base:bool, +} + +#[derive(Debug, Default, PartialEq)] +pub struct TargetSelector { + pub include_dependencies:bool, + pub match_dependencies:bool, + pub include_dependents:bool, + pub exclude:bool, + pub exclude_self:bool, + pub follow_prod_deps_only:bool, + pub parent_dir:Option, + pub name_pattern:String, + pub git_range:Option, + pub raw:String, +} + +impl FromStr for TargetSelector { + type Err = InvalidSelectorError; + + fn from_str(raw_selector:&str) -> Result { + let selector = raw_selector.strip_prefix('!'); + let (exclude, selector) = match selector { + Some(selector) => (true, selector), + None => (false, raw_selector), + }; + + let mut exclude_self = false; + let include_dependencies = selector.strip_suffix("..."); + + let (include_dependencies, selector) = if let Some(selector) = include_dependencies { + ( + true, + if let Some(selector) = selector.strip_suffix('^') { + exclude_self = true; + selector + } else { + selector + }, + ) + } else { + (false, selector) + }; + + let include_dependents = selector.strip_prefix("..."); + let (include_dependents, selector) = if let Some(selector) = include_dependents { + ( + true, + if let Some(selector) = selector.strip_prefix('^') { + exclude_self = true; + selector + } else { + selector + }, + ) + } else { + (false, selector) + }; + + // We explicitly allow empty git ranges so we can return a more targeted error + // below + let re = Regex::new(r"^(?P[^.](?:[^{}\[\]]*[^{}\[\].])?)?(\{(?P[^}]*)})?(?P(?:\.{3})?\[[^\]]*\])?$").expect("valid"); + let captures = re.captures(selector); + + let captures = match captures { + Some(captures) => captures, + None => { + return if let Some(relative_path) = is_selector_by_location(selector) { + Ok(TargetSelector { + exclude, + include_dependencies, + include_dependents, + parent_dir:Some(relative_path?), + raw:raw_selector.to_string(), + ..Default::default() + }) + } else { + Ok(TargetSelector { + exclude, + exclude_self, + include_dependencies, + include_dependents, + name_pattern:selector.to_string(), + raw:raw_selector.to_string(), + ..Default::default() + }) + }; + }, + }; + + let mut pre_add_dependencies = false; + + let name_pattern = captures.name("name").map_or(String::new(), |m| m.as_str().to_string()); + + let mut parent_dir = None; + + if let Some(directory) = captures.name("directory") { + let directory = directory.as_str().to_string(); + if directory.is_empty() { + return Err(InvalidSelectorError::EmptyPathSpecification); + } else { + let clean_directory = path_clean::clean(std::path::Path::new(directory.as_str())) + .into_os_string() + .into_string() + .expect("directory was valid utf8 before cleaning"); + parent_dir = Some( + AnchoredSystemPathBuf::try_from(clean_directory.as_str()) + .map_err(|_| InvalidSelectorError::InvalidAnchoredPath(directory))?, + ); + } + } + + let git_range = if let Some(commits) = captures.name("commits") { + let commits_str = if let Some(commits) = commits.as_str().strip_prefix("...") { + if parent_dir.is_none() && name_pattern.is_empty() { + return Err(InvalidSelectorError::CantMatchDependencies); + } + pre_add_dependencies = true; + commits + } else { + commits.as_str() + }; + + // strip the square brackets + let commits_str = commits_str + .strip_prefix('[') + .and_then(|s| s.strip_suffix(']')) + .expect("regex guarantees square brackets"); + if commits_str.is_empty() { + return Err(InvalidSelectorError::InvalidGitRange(commits_str.to_string())); + } + + let git_range = if let Some((a, b)) = commits_str.split_once("...") { + if a.is_empty() || b.is_empty() { + return Err(InvalidSelectorError::InvalidGitRange(commits_str.to_string())); + } + GitRange { + from_ref:Some(a.to_string()), + to_ref:Some(b.to_string()), + include_uncommitted:false, + allow_unknown_objects:false, + merge_base:true, + } + } else { + // If only the start of the range is specified, we assume that + // we want to include uncommitted changes + GitRange { + from_ref:Some(commits_str.to_string()), + to_ref:None, + include_uncommitted:true, + allow_unknown_objects:false, + merge_base:false, + } + }; + Some(git_range) + } else { + None + }; + + Ok(TargetSelector { + git_range, + exclude, + exclude_self, + include_dependencies, + include_dependents, + match_dependencies:pre_add_dependencies, + name_pattern, + parent_dir, + raw:raw_selector.to_string(), + ..Default::default() + }) + } +} + +#[derive(Debug, Error, PartialEq)] +pub enum InvalidSelectorError { + #[error("cannot use match dependencies without specifying either a directory or package")] + CantMatchDependencies, + #[error("invalid anchored path: {0}")] + InvalidAnchoredPath(String), + #[error("empty path specification")] + EmptyPathSpecification, + #[error("invalid git range selector: {0}")] + InvalidGitRange(String), + + #[error("selector \"{0}\" must have a reference, directory, or name pattern")] + InvalidSelector(String), +} + +/// checks if the selector is a filesystem path +pub fn is_selector_by_location( + raw_selector:&str, +) -> Option> { + let exact_matches = [".", ".."]; + let prefixes = ["./", ".\\", "../", "..\\"]; + + if exact_matches.contains(&raw_selector) + || prefixes.iter().any(|prefix| raw_selector.starts_with(prefix)) + { + let cleaned_selector = path_clean::clean(std::path::Path::new(raw_selector)) + .into_os_string() + .into_string() + .expect("raw selector was valid utf8"); + Some( + AnchoredSystemPathBuf::try_from(cleaned_selector.as_str()) + .map_err(|_| InvalidSelectorError::InvalidAnchoredPath(raw_selector.to_string())), + ) + } else { + None + } +} + +#[cfg(test)] +mod test { + use std::str::FromStr; + + use pretty_assertions::assert_eq; + use test_case::test_case; + use turbopath::AnchoredSystemPathBuf; + + use super::TargetSelector; + use crate::run::scope::target_selector::GitRange; + + #[test_case("foo", TargetSelector { name_pattern: "foo".to_string(), raw: "foo".to_string(), ..Default::default() }; "foo")] + #[test_case("foo...", TargetSelector { name_pattern: "foo".to_string(), raw: "foo...".to_string(), include_dependencies: true, ..Default::default() }; "foo dot dot dot")] + #[test_case("...foo", TargetSelector { name_pattern: "foo".to_string(), raw: "...foo".to_string(), include_dependents: true, ..Default::default() }; "dot dot dot foo")] + #[test_case("...foo...", TargetSelector { name_pattern: "foo".to_string(), raw: "...foo...".to_string(), include_dependents: true, include_dependencies: true, ..Default::default() }; "dot dot dot foo dot dot dot")] + #[test_case("foo^...", TargetSelector { name_pattern: "foo".to_string(), raw: "foo^...".to_string(), include_dependencies: true, exclude_self: true, ..Default::default() }; "foo caret dot dot dot")] + #[test_case("...^foo", TargetSelector { name_pattern: "foo".to_string(), raw: "...^foo".to_string(), include_dependents: true, exclude_self: true, ..Default::default() }; "dot dot dot caret foo")] + #[test_case("../foo", TargetSelector { raw: "../foo".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from(if cfg!(windows) { "..\\foo" } else { "../foo" }).unwrap()), ..Default::default() }; "dot dot slash foo")] + #[test_case("./foo", TargetSelector { raw: "./foo".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), ..Default::default() }; "dot slash foo")] + #[test_case("./foo/*", TargetSelector { raw: "./foo/*".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from(if cfg!(windows) { "foo\\*" } else { "foo/*" }).unwrap()), ..Default::default() }; "dot slash foo star")] + #[test_case("...{./foo}", TargetSelector { raw: "...{./foo}".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), include_dependents: true, ..Default::default() }; "dot dot dot curly bracket foo")] + #[test_case(".", TargetSelector { raw: ".".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from(".").unwrap()), ..Default::default() }; "parent dir dot")] + #[test_case("..", TargetSelector { raw: "..".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from("..").unwrap()), ..Default::default() }; "parent dir dot dot")] + #[test_case("[master]", TargetSelector { raw: "[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), ..Default::default() }; "square brackets master")] + #[test_case("[from...to]", TargetSelector { raw: "[from...to]".to_string(), git_range: Some(GitRange { from_ref: Some("from".to_string()), to_ref: Some("to".to_string()), merge_base: true, ..Default::default() }), ..Default::default() }; "[from...to]")] + #[test_case("{foo}[master]", TargetSelector { raw: "{foo}[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), ..Default::default() }; "{foo}[master]")] + #[test_case("pattern{foo}[master]", TargetSelector { raw: "pattern{foo}[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), name_pattern: "pattern".to_string(), ..Default::default() }; "pattern{foo}[master]")] + #[test_case("[master]...", TargetSelector { raw: "[master]...".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), include_dependencies: true, ..Default::default() }; "square brackets master dot dot dot")] + #[test_case("...[master]", TargetSelector { raw: "...[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), include_dependents: true, ..Default::default() }; "dot dot dot master square brackets")] + #[test_case("...[master]...", TargetSelector { raw: "...[master]...".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), include_dependencies: true, include_dependents: true, ..Default::default() }; "dot dot dot master square brackets dot dot dot")] + #[test_case("...[from...to]...", TargetSelector { raw: "...[from...to]...".to_string(), git_range: Some(GitRange { from_ref: Some("from".to_string()), to_ref: Some("to".to_string()), merge_base: true, ..Default::default() }), include_dependencies: true, include_dependents: true, ..Default::default() }; "dot dot dot [from...to] dot dot dot")] + #[test_case("foo...[master]", TargetSelector { raw: "foo...[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), name_pattern: "foo".to_string(), match_dependencies: true, ..Default::default() }; "foo...[master]")] + #[test_case("foo...[master]...", TargetSelector { raw: "foo...[master]...".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), name_pattern: "foo".to_string(), match_dependencies: true, include_dependencies: true, ..Default::default() }; "foo...[master] dot dot dot")] + #[test_case("{foo}...[master]", TargetSelector { raw: "{foo}...[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), match_dependencies: true, ..Default::default() }; " curly brackets foo...[master]")] + #[test_case("...@repo/pkg[master]", TargetSelector { raw: "...@repo/pkg[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), name_pattern: "@repo/pkg".to_string(), include_dependents: true, ..Default::default() }; "gh 9096")] + fn parse_target_selector(raw_selector:&str, want:TargetSelector) { + let result = TargetSelector::from_str(raw_selector); + + match result { + Ok(got) => { + assert_eq!(got, want, "ParseTargetSelector() = {:?}, want {:?}", got, want); + }, + Err(e) => { + panic!("ParseTargetSelector() error = {:?}", e) + }, + } + } + + #[test_case("{}" ; "curly brackets")] + #[test_case("......[master]" ; "......[master]")] + #[test_case("[]" ; "empty git range")] + #[test_case("[...some-ref]" ; "missing git range start")] + #[test_case("[some-ref...]" ; "missing git range end")] + #[test_case("[...]" ; "missing entire git range")] + fn parse_target_selector_invalid(raw_selector:&str) { + let result = TargetSelector::from_str(raw_selector); + + match result { + Ok(_got) => { + panic!("expected error when parsing {}", raw_selector); + }, + Err(e) => { + println!("{:?}", e); + }, + } + } +} diff --git a/crates/turborepo-lib/Source/run/summary/duration.rs b/crates/turborepo-lib/Source/run/summary/duration.rs new file mode 100644 index 0000000000000..8ca84766cab02 --- /dev/null +++ b/crates/turborepo-lib/Source/run/summary/duration.rs @@ -0,0 +1,61 @@ +use std::fmt::{self, Formatter}; + +use chrono::{DateTime, Duration, Local, SubsecRound}; + +#[derive(Debug)] +pub struct TurboDuration(Duration); + +impl TurboDuration { + pub fn new(start_time:&DateTime, end_time:&DateTime) -> Self { + TurboDuration(end_time.trunc_subsecs(3).signed_duration_since(start_time.trunc_subsecs(3))) + } +} + +impl From for TurboDuration { + fn from(duration:Duration) -> Self { Self(duration) } +} + +impl fmt::Display for TurboDuration { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { + let duration = &self.0; + + // If duration is less than a second, we print milliseconds + if duration.num_seconds() <= 0 { + let milliseconds = duration.num_milliseconds() - duration.num_seconds() * 1000; + return write!(f, "{}ms", milliseconds); + } + + if duration.num_hours() > 0 { + write!(f, "{}h", duration.num_hours(),)?; + } + + if duration.num_minutes() > 0 { + let minutes = duration.num_minutes() - duration.num_hours() * 60; + write!(f, "{}m", minutes)?; + } + + if duration.num_seconds() > 0 { + let seconds_in_ms = duration.num_milliseconds() - duration.num_minutes() * 60 * 1000; + let seconds = (seconds_in_ms as f64) / 1000.0; + write!(f, "{}s", seconds)?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use pretty_assertions::assert_eq; + use test_case::test_case; + + use super::*; + + #[test_case(TurboDuration::from(Duration::milliseconds(120)), "120ms")] + #[test_case(TurboDuration::from(Duration::milliseconds(1500)), "1.5s")] + #[test_case(TurboDuration::from(Duration::milliseconds(1234)), "1.234s")] + #[test_case(TurboDuration::from(Duration::seconds(90)), "1m30s")] + fn duration_formatting(duration:TurboDuration, expected:&str) { + assert_eq!(duration.to_string(), expected); + } +} diff --git a/crates/turborepo-lib/Source/run/summary/execution.rs b/crates/turborepo-lib/Source/run/summary/execution.rs new file mode 100644 index 0000000000000..47917dd5bb6bc --- /dev/null +++ b/crates/turborepo-lib/Source/run/summary/execution.rs @@ -0,0 +1,468 @@ +use std::fmt; + +use chrono::{DateTime, Local}; +use serde::Serialize; +use tokio::sync::mpsc; +use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPath}; +use turborepo_ui::{BOLD, BOLD_GREEN, BOLD_RED, ColorConfig, MAGENTA, YELLOW, color, cprintln}; + +use super::TurboDuration; +use crate::run::{summary::task::TaskSummary, task_id::TaskId}; + +// Just used to make changing the type that gets passed to the state management +// thread easy +type Message = TrackerMessage; + +// Should *not* be exposed outside of run summary module +/// Spawns task trackers and records the final state of all tasks +#[derive(Debug)] +pub struct ExecutionTracker { + // this thread handles the state management + state_thread:tokio::task::JoinHandle, + sender:mpsc::Sender, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ExecutionSummary<'a> { + // a synthesized turbo command to produce this invocation + command:String, + // the (possibly empty) path from the turborepo root to where the command was run + #[serde(rename = "repoPath")] + repo_path:&'a AnchoredSystemPath, + // number of tasks that exited successfully (does not include cache hits) + success:usize, + // number of tasks that exited with failure + failed:usize, + // number of tasks that had a cache hit + cached:usize, + // number of tasks that started + attempted:usize, + pub(crate) start_time:i64, + pub(crate) end_time:i64, + #[serde(skip)] + duration:TurboDuration, + pub(crate) exit_code:i32, +} + +impl<'a> ExecutionSummary<'a> { + pub fn new( + command:String, + state:SummaryState, + package_inference_root:Option<&'a AnchoredSystemPath>, + exit_code:i32, + start_time:DateTime, + end_time:DateTime, + ) -> Self { + let duration = TurboDuration::new(&start_time, &end_time); + Self { + command, + success:state.success, + failed:state.failed, + cached:state.cached, + attempted:state.attempted, + // We're either at some path in the repo, or at the root, which is an empty path + repo_path:package_inference_root.unwrap_or_else(|| AnchoredSystemPath::empty()), + start_time:start_time.timestamp_millis(), + end_time:end_time.timestamp_millis(), + duration, + exit_code, + } + } + + /// We implement this on `ExecutionSummary` and not `RunSummary` because + /// the `execution` field is nullable (due to normalize). + pub fn print( + &self, + ui:ColorConfig, + path:AbsoluteSystemPathBuf, + failed_tasks:Vec<&TaskSummary>, + ) { + let maybe_full_turbo = if self.cached == self.attempted && self.attempted > 0 { + match std::env::var("TERM_PROGRAM").as_deref() { + Ok("Apple_Terminal") => color!(ui, MAGENTA, ">>> FULL TURBO").to_string(), + _ => ui.rainbow(">>> FULL TURBO").to_string(), + } + } else { + String::new() + }; + + let mut line_data = vec![ + ( + "Tasks", + format!( + "{}, {} total", + color!(ui, BOLD_GREEN, "{} successful", self.successful()), + self.attempted + ), + ), + ( + "Cached", + format!("{}, {} total", color!(ui, BOLD, "{} cached", self.cached), self.attempted) + .to_string(), + ), + ( + "Time", + format!("{} {}", color!(ui, BOLD, "{}", self.duration), maybe_full_turbo), + ), + ]; + + if path.exists() { + line_data.push(("Summary", path.to_string())); + } + + if !failed_tasks.is_empty() { + let mut formatted:Vec<_> = failed_tasks + .iter() + .map(|task| color!(ui, BOLD_RED, "{}", task.task_id).to_string()) + .collect(); + formatted.sort(); + line_data.push(("Failed", formatted.join(", "))); + } + + let max_length = line_data.iter().map(|(header, _)| header.len()).max().unwrap_or_default(); + + let lines:Vec<_> = line_data + .into_iter() + .map(|(header, trailer)| { + color!( + ui, + BOLD, + "{}{}: {}", + " ".repeat(max_length - header.len()), + header, + trailer + ) + }) + .collect(); + + if self.attempted == 0 { + println!(); + cprintln!(ui, YELLOW, "No tasks were executed as part of this run."); + } + + println!(); + for line in lines { + println!("{}", line); + } + + println!(); + } + + fn successful(&self) -> usize { self.success + self.cached } +} + +/// The final states of all task executions +#[derive(Debug, Default, Clone)] +pub struct SummaryState { + pub attempted:usize, + pub failed:usize, + pub cached:usize, + pub success:usize, + pub tasks:Vec, +} + +#[derive(Debug, Clone)] +pub struct TaskState { + pub task_id:TaskId<'static>, + pub execution:Option, +} + +impl SummaryState { + fn handle_event(&mut self, event:Event) { + match event { + Event::Building => self.attempted += 1, + Event::BuildFailed => self.failed += 1, + Event::Cached => self.cached += 1, + Event::Built => self.success += 1, + Event::Canceled => (), + } + } +} + +/// A tracker constructed for each task and used to communicate task events back +/// to the execution summary. +pub struct TaskTracker { + sender:mpsc::Sender, + started_at:T, + task_id:TaskId<'static>, +} + +#[derive(Debug, Clone)] +struct TrackerMessage { + event:Event, + // Only present if task is finished + state:Option, +} + +#[derive(Debug, Clone, Copy, Serialize)] +enum Event { + Building, + BuildFailed, + Cached, + Built, + // Canceled due to external signal or internal failure + Canceled, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct TaskExecutionSummary { + pub start_time:i64, + pub end_time:i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub error:Option, + pub exit_code:Option, +} + +impl TaskExecutionSummary { + pub fn is_failure(&self) -> bool { + // We consider None as a failure as it indicates the task failed to start + // or was killed in a manner where we didn't collect an exit code. + !matches!(self.exit_code, Some(0)) + } +} + +impl ExecutionTracker { + pub fn new() -> Self { + // This buffer size is probably overkill, but since messages are only a byte + // it's worth the extra memory to avoid the channel filling up. + let (sender, mut receiver) = mpsc::channel::(128); + let state_thread = tokio::spawn(async move { + let mut state = SummaryState::default(); + while let Some(TrackerMessage { event, state: task_state }) = receiver.recv().await { + state.handle_event(event); + if let Some(task_state) = task_state { + state.tasks.push(task_state); + } + } + state + }); + + Self { state_thread, sender } + } + + // Produce a tracker for the task + pub fn task_tracker(&self, task_id:TaskId<'static>) -> TaskTracker<()> { + TaskTracker { sender:self.sender.clone(), task_id, started_at:() } + } + + pub async fn finish(self) -> Result { + let Self { state_thread, sender, .. } = self; + // We drop the sender so the channel closes once all trackers have finished. + // We don't explicitly close as that would cause running trackers to be unable + // to send their execution summary. + drop(sender); + + let summary_state = state_thread.await?; + + Ok(summary_state) + } +} + +impl TaskTracker<()> { + // Start the tracker + pub async fn start(self) -> TaskTracker> { + let TaskTracker { sender, task_id, .. } = self; + let started_at = Local::now(); + sender + .send(TrackerMessage { event:Event::Building, state:None }) + .await + .expect("execution summary state thread finished"); + TaskTracker { sender, started_at, task_id } + } + + // Track that the task would be executed + pub async fn dry_run(self) { + let Self { sender, task_id, .. } = self; + + sender + .send(TrackerMessage { + event:Event::Canceled, + state:Some(TaskState { task_id, execution:None }), + }) + .await + .expect("execution summary state thread finished") + } +} + +impl TaskTracker> { + // In the case of a task getting canceled we send no information as there was an + // internal turbo error + pub fn cancel(self) {} + + pub async fn cached(self) -> TaskExecutionSummary { + let Self { sender, started_at, task_id } = self; + + let ended_at = Local::now(); + let execution = TaskExecutionSummary { + start_time:started_at.timestamp_millis(), + end_time:ended_at.timestamp_millis(), + // Go synthesizes a zero exit code on cache hits + exit_code:Some(0), + error:None, + }; + + let state = TaskState { task_id, execution:Some(execution.clone()) }; + sender + .send(TrackerMessage { event:Event::Cached, state:Some(state) }) + .await + .expect("summary state thread finished"); + execution + } + + pub async fn build_succeeded(self, exit_code:i32) -> TaskExecutionSummary { + let Self { sender, started_at, task_id } = self; + + let ended_at = Local::now(); + let execution = TaskExecutionSummary { + start_time:started_at.timestamp_millis(), + end_time:ended_at.timestamp_millis(), + exit_code:Some(exit_code), + error:None, + }; + + let state = TaskState { task_id, execution:Some(execution.clone()) }; + sender + .send(TrackerMessage { event:Event::Built, state:Some(state) }) + .await + .expect("summary state thread finished"); + execution + } + + pub async fn build_failed( + self, + exit_code:Option, + error:impl fmt::Display, + ) -> TaskExecutionSummary { + let Self { sender, started_at, task_id } = self; + + let ended_at = Local::now(); + let execution = TaskExecutionSummary { + start_time:started_at.timestamp_millis(), + end_time:ended_at.timestamp_millis(), + exit_code, + error:Some(error.to_string()), + }; + + let state = TaskState { task_id, execution:Some(execution.clone()) }; + sender + .send(TrackerMessage { event:Event::BuildFailed, state:Some(state) }) + .await + .expect("summary state thread finished"); + execution + } +} + +#[cfg(test)] +mod test { + use chrono::Duration; + use serde_json::json; + use test_case::test_case; + + use super::*; + + #[tokio::test] + async fn test_multiple_tasks() { + let summary = ExecutionTracker::new(); + let foo = TaskId::new("foo", "build"); + let bar = TaskId::new("bar", "build"); + let baz = TaskId::new("baz", "build"); + let boo = TaskId::new("boo", "build"); + let mut tasks = Vec::new(); + { + let tracker = summary.task_tracker(foo.clone()); + tasks.push(tokio::spawn(async move { + let tracker = tracker.start().await; + tracker.build_succeeded(0).await; + })); + } + { + let tracker = summary.task_tracker(bar.clone()); + tasks.push(tokio::spawn(async move { + let tracker = tracker.start().await; + tracker.cached().await; + })); + } + { + let tracker = summary.task_tracker(baz.clone()); + tasks.push(tokio::spawn(async move { + let tracker = tracker.start().await; + tracker.build_failed(Some(1), "big bad error").await; + })); + } + { + let tracker = summary.task_tracker(boo.clone()); + tasks.push(tokio::spawn(async move { + let tracker = tracker.start().await; + tracker.cancel(); + })); + } + for task in tasks { + task.await.unwrap(); + } + + let state = summary.finish().await.unwrap(); + assert_eq!(state.attempted, 4); + assert_eq!(state.cached, 1); + assert_eq!(state.failed, 1); + assert_eq!(state.success, 1); + let foo_state = state.tasks.iter().find(|task| task.task_id == foo).unwrap(); + assert_eq!(foo_state.execution.as_ref().unwrap().exit_code, Some(0)); + let bar_state = state.tasks.iter().find(|task| task.task_id == bar).unwrap(); + assert_eq!(bar_state.execution.as_ref().unwrap().exit_code, Some(0)); + let baz_state = state.tasks.iter().find(|task| task.task_id == baz).unwrap(); + assert_eq!(baz_state.execution.as_ref().unwrap().exit_code, Some(1)); + let boo_state = state.tasks.iter().find(|task| task.task_id == boo); + assert!(boo_state.is_none(), "canceling doesn't produce execution data"); + } + + #[tokio::test] + async fn test_timing() { + let summary = ExecutionTracker::new(); + let tracker = summary.task_tracker(TaskId::new("foo", "build")); + let post_construction_time = Local::now().timestamp_millis(); + let sleep_duration = Duration::milliseconds(5); + tokio::time::sleep(sleep_duration.to_std().unwrap()).await; + + let tracker = tracker.start().await; + + tokio::time::sleep(sleep_duration.to_std().unwrap()).await; + tracker.build_succeeded(0).await; + let mut state = summary.finish().await.unwrap(); + assert_eq!(state.tasks.len(), 1); + let summary = state.tasks.pop().unwrap().execution.unwrap(); + assert!( + post_construction_time < summary.start_time, + "tracker start time should start when start is called" + ); + assert!( + summary.start_time + sleep_duration.num_milliseconds() <= summary.end_time, + "tracker end should be at least as long as the time between calls" + ); + } + + #[test_case( + TaskExecutionSummary { + start_time: 123, + end_time: 234, + exit_code: Some(0), + error: None + }, + json!({ "startTime": 123, "endTime": 234, "exitCode": 0 }) + ; "success" + )] + #[test_case( + TaskExecutionSummary { + start_time: 123, + end_time: 234, + exit_code: Some(1), + error: Some("cannot find anything".into()), + }, + json!({ "startTime": 123, "endTime": 234, "exitCode": 1, "error": "cannot find anything" }) + ; "failure" + )] + fn test_serialization(value:impl serde::Serialize, expected:serde_json::Value) { + assert_eq!(serde_json::to_value(value).unwrap(), expected); + } +} diff --git a/crates/turborepo-lib/Source/run/summary/global_hash.rs b/crates/turborepo-lib/Source/run/summary/global_hash.rs new file mode 100644 index 0000000000000..081623af9967c --- /dev/null +++ b/crates/turborepo-lib/Source/run/summary/global_hash.rs @@ -0,0 +1,87 @@ +use std::collections::BTreeMap; + +use serde::Serialize; +use turbopath::RelativeUnixPathBuf; +use turborepo_env::EnvironmentVariablePairs; + +use crate::run::{global_hash::GlobalHashableInputs, summary::Error}; + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +// Contains the environment variable inputs for the global hash +pub struct GlobalEnvConfiguration<'a> { + pub env:&'a [String], + pub pass_through_env:Option<&'a [String]>, +} + +// Contains the environment variables that impacted the global hash +#[derive(Debug, Serialize)] +pub struct GlobalEnvVarSummary<'a> { + pub specified:GlobalEnvConfiguration<'a>, + + pub configured:Option, + pub inferred:Option, + #[serde(rename = "passthrough")] + pub pass_through:Option, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GlobalHashSummary<'a> { + pub root_key:&'static str, + pub files:BTreeMap, + pub hash_of_external_dependencies:&'a str, + pub hash_of_internal_dependencies:&'a str, + pub environment_variables:GlobalEnvVarSummary<'a>, + pub engines:Option>, +} + +impl<'a> TryFrom> for GlobalHashSummary<'a> { + type Error = Error; + + #[allow(clippy::too_many_arguments)] + fn try_from(global_hashable_inputs:GlobalHashableInputs<'a>) -> Result { + let GlobalHashableInputs { + global_cache_key, + global_file_hash_map, + root_external_dependencies_hash, + root_internal_dependencies_hash, + env, + resolved_env_vars, + pass_through_env, + env_at_execution_start, + engines, + .. + } = global_hashable_inputs; + + let pass_through = pass_through_env + .map(|pass_through_env| -> Result { + Ok(env_at_execution_start + .from_wildcards(pass_through_env) + .map_err(Error::Env)? + .to_secret_hashable()) + }) + .transpose()?; + + let engines = engines.map(|engines| engines.into_iter().collect()); + + Ok(Self { + root_key:global_cache_key, + files:global_file_hash_map.into_iter().collect(), + // This can be empty in single package mode + hash_of_external_dependencies:root_external_dependencies_hash.unwrap_or_default(), + hash_of_internal_dependencies:root_internal_dependencies_hash.unwrap_or_default(), + environment_variables:GlobalEnvVarSummary { + specified:GlobalEnvConfiguration { env, pass_through_env }, + configured:resolved_env_vars + .as_ref() + .map(|vars| vars.by_source.explicit.to_secret_hashable()), + inferred:resolved_env_vars + .as_ref() + .map(|vars| vars.by_source.matching.to_secret_hashable()), + pass_through, + }, + engines, + }) + } +} diff --git a/crates/turborepo-lib/src/run/summary/mod.rs b/crates/turborepo-lib/Source/run/summary/mod.rs similarity index 100% rename from crates/turborepo-lib/src/run/summary/mod.rs rename to crates/turborepo-lib/Source/run/summary/mod.rs diff --git a/crates/turborepo-lib/Source/run/summary/scm.rs b/crates/turborepo-lib/Source/run/summary/scm.rs new file mode 100644 index 0000000000000..b98fc77114548 --- /dev/null +++ b/crates/turborepo-lib/Source/run/summary/scm.rs @@ -0,0 +1,49 @@ +use serde::{Deserialize, Serialize}; +use turbopath::AbsoluteSystemPath; +use turborepo_ci::Vendor; +use turborepo_env::EnvironmentVariableMap; +use turborepo_scm::SCM; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +enum SCMType { + Git, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub(crate) struct SCMState { + #[serde(rename = "type")] + ty:SCMType, + pub(crate) sha:Option, + pub(crate) branch:Option, +} + +impl SCMState { + pub fn get(env_vars:&EnvironmentVariableMap, scm:&SCM, dir:&AbsoluteSystemPath) -> Self { + let mut state = SCMState { ty:SCMType::Git, sha:None, branch:None }; + + if turborepo_ci::is_ci() { + if let Some(vendor) = Vendor::infer() { + if let Some(sha_env_var) = vendor.sha_env_var { + state.sha = env_vars.get(sha_env_var).cloned() + } + + if let Some(branch_env_var) = vendor.branch_env_var { + state.branch = env_vars.get(branch_env_var).cloned() + } + } + } + + // Fall back to using `git` + if state.branch.is_none() && state.sha.is_none() { + if state.branch.is_none() { + state.branch = scm.get_current_branch(dir).ok(); + } + if state.sha.is_none() { + state.sha = scm.get_current_sha(dir).ok(); + } + } + + state + } +} diff --git a/crates/turborepo-lib/src/run/summary/spaces.rs b/crates/turborepo-lib/Source/run/summary/spaces.rs similarity index 100% rename from crates/turborepo-lib/src/run/summary/spaces.rs rename to crates/turborepo-lib/Source/run/summary/spaces.rs diff --git a/crates/turborepo-lib/Source/run/summary/task.rs b/crates/turborepo-lib/Source/run/summary/task.rs new file mode 100644 index 0000000000000..7929658afb519 --- /dev/null +++ b/crates/turborepo-lib/Source/run/summary/task.rs @@ -0,0 +1,366 @@ +use std::collections::BTreeMap; + +use serde::Serialize; +use turbopath::{AnchoredSystemPathBuf, RelativeUnixPathBuf}; +use turborepo_cache::CacheHitMetadata; +use turborepo_env::{DetailedMap, EnvironmentVariableMap}; + +use super::{EnvMode, execution::TaskExecutionSummary}; +use crate::{ + cli::OutputLogsMode, + run::task_id::TaskId, + task_graph::{TaskDefinition, TaskOutputs}, +}; + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct TaskCacheSummary { + // Deprecated, but keeping around for --dry=json + pub local:bool, + // Deprecated, but keeping around for --dry=json + pub remote:bool, + status:CacheStatus, + // Present unless a cache miss + #[serde(skip_serializing_if = "Option::is_none")] + source:Option, + // 0 if a cache miss + time_saved:u64, +} + +#[derive(Debug, Serialize, Copy, Clone)] +#[serde(rename_all = "UPPERCASE")] +enum CacheStatus { + Hit, + Miss, +} + +#[derive(Debug, Serialize, Copy, Clone)] +#[serde(rename_all = "UPPERCASE")] +enum CacheSource { + Local, + Remote, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub(crate) struct TaskSummary { + pub task_id:TaskId<'static>, + pub task:String, + pub package:String, + #[serde(flatten)] + pub shared:SharedTaskSummary>, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub(crate) struct SinglePackageTaskSummary { + pub task_id:String, + pub task:String, + #[serde(flatten)] + pub shared:SharedTaskSummary, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub(crate) struct SharedTaskSummary { + pub hash:String, + pub inputs:BTreeMap, + pub hash_of_external_dependencies:String, + pub cache:TaskCacheSummary, + pub command:String, + pub cli_arguments:Vec, + pub outputs:Option>, + pub excluded_outputs:Option>, + pub log_file:String, + #[serde(skip_serializing_if = "Option::is_none")] + pub directory:Option, + pub dependencies:Vec, + pub dependents:Vec, + pub resolved_task_definition:TaskSummaryTaskDefinition, + pub expanded_outputs:Vec, + pub framework:String, + pub env_mode:EnvMode, + pub environment_variables:TaskEnvVarSummary, + #[serde(skip_serializing_if = "Option::is_none")] + pub execution:Option, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct TaskEnvConfiguration { + pub env:Vec, + pub pass_through_env:Option>, +} + +#[derive(Debug, Serialize, Clone, Default)] +#[serde(rename_all = "camelCase")] +pub struct TaskSummaryTaskDefinition { + outputs:Vec, + cache:bool, + depends_on:Vec, + inputs:Vec, + output_logs:OutputLogsMode, + persistent:bool, + interruptible:bool, + env:Vec, + pass_through_env:Option>, + interactive:bool, + #[serde(skip_serializing_if = "Option::is_none")] + env_mode:Option, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct TaskEnvVarSummary { + pub specified:TaskEnvConfiguration, + pub configured:Vec, + pub inferred:Vec, + #[serde(rename = "passthrough")] + pub pass_through:Option>, +} + +impl TaskCacheSummary { + pub fn cache_miss() -> Self { + Self { local:false, remote:false, status:CacheStatus::Miss, time_saved:0, source:None } + } +} + +impl From> for TaskCacheSummary { + fn from(response:Option) -> Self { + match response { + Some(CacheHitMetadata { source, time_saved }) => { + let source = CacheSource::from(source); + // Assign these deprecated fields Local and Remote based on the information + // available in the itemStatus. Note that these fields are + // problematic, because an ItemStatus isn't always the composite + // of both local and remote caches. That means that an ItemStatus might say it + // was a local cache hit, and we return remote: false here. That's misleading + // because it does not mean that there is no remote cache hit, + // it _could_ mean that we never checked the remote cache. These + // fields are being deprecated for this reason. + let (local, remote) = match source { + CacheSource::Local => (true, false), + CacheSource::Remote => (false, true), + }; + Self { local, remote, status:CacheStatus::Hit, source:Some(source), time_saved } + }, + None => Self::cache_miss(), + } + } +} + +impl From for CacheSource { + fn from(value:turborepo_cache::CacheSource) -> Self { + match value { + turborepo_cache::CacheSource::Local => Self::Local, + turborepo_cache::CacheSource::Remote => Self::Remote, + } + } +} + +impl TaskEnvVarSummary { + pub fn new( + task_definition:&TaskDefinition, + env_vars:DetailedMap, + env_at_execution_start:&EnvironmentVariableMap, + ) -> Result { + // TODO: this operation differs from the actual env that gets passed in during + // task execution it should be unified, but first we should copy Go's + // behavior as we try to match the implementations + let pass_through = task_definition + .pass_through_env + .as_deref() + .map(|pass_through_env| -> Result<_, turborepo_env::Error> { + Ok(env_at_execution_start.from_wildcards(pass_through_env)?.to_secret_hashable()) + }) + .transpose()?; + + Ok(Self { + specified:TaskEnvConfiguration { + env:task_definition.env.clone(), + pass_through_env:task_definition.pass_through_env.clone(), + }, + configured:env_vars.by_source.explicit.to_secret_hashable(), + inferred:env_vars.by_source.matching.to_secret_hashable(), + pass_through, + }) + } +} + +impl From for SinglePackageTaskSummary { + fn from(value:TaskSummary) -> Self { + let TaskSummary { task_id, shared, .. } = value; + Self { + task_id:task_id.task().to_string(), + task:task_id.task().to_string(), + shared:shared.into(), + } + } +} + +impl From>> for SharedTaskSummary { + fn from(value:SharedTaskSummary>) -> Self { + let SharedTaskSummary { + hash, + inputs, + hash_of_external_dependencies, + cache, + command, + cli_arguments, + outputs, + excluded_outputs, + log_file, + expanded_outputs, + dependencies, + dependents, + resolved_task_definition, + framework, + execution, + env_mode, + environment_variables, + .. + } = value; + Self { + hash, + inputs, + hash_of_external_dependencies, + cache, + command, + cli_arguments, + outputs, + excluded_outputs, + log_file, + directory:None, + expanded_outputs, + dependencies:dependencies + .into_iter() + .map(|task_id| task_id.task().to_string()) + .collect(), + dependents:dependents.into_iter().map(|task_id| task_id.task().to_string()).collect(), + resolved_task_definition, + framework, + execution, + env_mode, + environment_variables, + } + } +} + +impl From for TaskSummaryTaskDefinition { + fn from(value:TaskDefinition) -> Self { + let TaskDefinition { + outputs: TaskOutputs { inclusions, exclusions }, + cache, + mut env, + pass_through_env, + topological_dependencies, + task_dependencies, + mut inputs, + output_logs, + persistent, + interruptible, + interactive, + env_mode, + siblings: _, + } = value; + + let mut outputs = inclusions; + for exclusion in exclusions { + outputs.push(format!("!{exclusion}")); + } + + let mut depends_on = + Vec::with_capacity(task_dependencies.len() + topological_dependencies.len()); + for task_dependency in task_dependencies { + depends_on.push(task_dependency.to_string()); + } + for topological_dependency in topological_dependencies { + depends_on.push(format!("^{}", topological_dependency.as_inner())); + } + + // These _should_ already be sorted when the TaskDefinition struct was + // unmarshaled, but we want to ensure they're sorted on the way out + // also, just in case something in the middle mutates the items. + depends_on.sort(); + outputs.sort(); + env.sort(); + inputs.sort(); + + Self { + outputs, + cache, + depends_on, + inputs, + output_logs, + persistent, + interruptible, + interactive, + env, + pass_through_env, + env_mode, + } + } +} + +#[cfg(test)] +mod test { + use serde_json::json; + use test_case::test_case; + + use super::*; + + #[test_case(CacheStatus::Hit, json!("HIT") ; "hit")] + #[test_case(CacheStatus::Miss, json!("MISS") ; "miss")] + #[test_case(CacheSource::Local, json!("LOCAL") ; "local")] + #[test_case(CacheSource::Remote, json!("REMOTE") ; "remote")] + #[test_case( + TaskCacheSummary::cache_miss(), + serde_json::json!({ + "local": false, + "remote": false, + "status": "MISS", + "timeSaved": 0, + }) + ; "cache miss" + )] + #[test_case( + TaskCacheSummary { + local: true, + remote: false, + status: CacheStatus::Hit, + source: Some(CacheSource::Local), + time_saved: 6, + }, + serde_json::json!({ + "local": true, + "remote": false, + "status": "HIT", + "source": "LOCAL", + "timeSaved": 6, + }) + ; "local cache hit" + )] + #[test_case( + TaskSummaryTaskDefinition { + outputs: vec!["foo".into()], + cache: true, + ..Default::default() + }, + json!({ + "outputs": ["foo"], + "cache": true, + "dependsOn": [], + "inputs": [], + "outputLogs": "full", + "persistent": false, + "interruptible": false, + "interactive": false, + "env": [], + "passThroughEnv": null, + }) + ; "resolved task definition" + )] + fn test_serialization(value:impl serde::Serialize, expected:serde_json::Value) { + assert_eq!(serde_json::to_value(value).unwrap(), expected); + } +} diff --git a/crates/turborepo-lib/src/run/summary/task_factory.rs b/crates/turborepo-lib/Source/run/summary/task_factory.rs similarity index 100% rename from crates/turborepo-lib/src/run/summary/task_factory.rs rename to crates/turborepo-lib/Source/run/summary/task_factory.rs diff --git a/crates/turborepo-lib/Source/run/task_access.rs b/crates/turborepo-lib/Source/run/task_access.rs new file mode 100644 index 0000000000000..740cf6df47255 --- /dev/null +++ b/crates/turborepo-lib/Source/run/task_access.rs @@ -0,0 +1,260 @@ +use std::{ + collections::HashMap, + fs::{self, File}, + io::Write, + sync::{Arc, Mutex}, +}; + +use serde::Deserialize; +use tracing::{debug, error, warn}; +use turbopath::{AbsoluteSystemPathBuf, PathRelation}; +use turborepo_cache::AsyncCache; +use turborepo_scm::SCM; +use turborepo_unescape::UnescapedString; + +use super::ConfigCache; +use crate::{config::RawTurboJson, gitignore::ensure_turbo_is_gitignored}; + +// Environment variable key that will be used to enable, and set the expected +// trace location +const TASK_ACCESS_ENV_KEY:&str = "TURBOREPO_TRACE_FILE"; +/// File name where the task is expected to leave a trace result +const TASK_ACCESS_TRACE_NAME:&str = "trace.json"; +// Path to the config file that will be used to store the trace results +pub const TASK_ACCESS_CONFIG_PATH:[&str; 2] = [".turbo", "traced-config.json"]; +/// File name where the task is expected to leave a trace result +const TURBO_CONFIG_FILE:&str = "turbo.json"; + +#[derive(Debug, thiserror::Error)] +pub enum ToFileError { + #[error("Unable to serialize traced config: {0}")] + Serialize(#[from] serde_json::Error), + #[error("Unable to write traced config: {0}")] + IO(#[from] std::io::Error), + #[error("Unable to cache traced config: {0}")] + Cache(#[from] turborepo_cache::CacheError), +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct TaskAccessTraceAccess { + pub network:bool, + pub file_paths:Vec, + pub env_var_keys:Vec, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct TaskAccessTraceFile { + pub accessed:TaskAccessTraceAccess, + pub outputs:Vec, +} + +#[derive(Deserialize, Debug)] +struct PackageJson { + scripts:Option>, +} + +pub fn trace_file_path(repo_root:&AbsoluteSystemPathBuf, task_hash:&str) -> AbsoluteSystemPathBuf { + repo_root.join_components(&[".turbo", task_hash, TASK_ACCESS_TRACE_NAME]) +} + +fn task_access_trace_enabled(repo_root:&AbsoluteSystemPathBuf) -> Result { + // TODO: use the existing config methods here + let root_turbo_json_path = &repo_root.join_component(TURBO_CONFIG_FILE); + if root_turbo_json_path.exists() { + return Ok(false); + } + + // read package.json at root + let package_json_path = repo_root.join_components(&["package.json"]); + let package_json_content = fs::read_to_string(package_json_path)?; + let package:PackageJson = serde_json::from_str(&package_json_content)?; + + if let Some(scripts) = package.scripts { + return match scripts.get("build") { + Some(script) => Ok(script == "next build"), + _ => Ok(false), + }; + } + + Ok(false) +} + +impl TaskAccessTraceFile { + pub fn read(repo_root:&AbsoluteSystemPathBuf, task_hash:&str) -> Option { + let trace_file = trace_file_path(repo_root, task_hash); + + let Ok(f) = trace_file.open() else { + return None; + }; + + match serde_json::from_reader(f) { + Ok(trace) => Some(trace), + Err(e) => { + warn!("failed to parse trace file {trace_file}: {e}"); + None + }, + } + } + + pub fn can_cache(&self, repo_root:&AbsoluteSystemPathBuf) -> bool { + // network + if self.accessed.network { + warn!( + "skipping automatic task caching - detected network + access", + ); + return false; + } + + // file system + for unescaped_str in &self.accessed.file_paths { + match AbsoluteSystemPathBuf::new(unescaped_str.to_string()) { + Ok(path) => { + let relation = path.relation_to_path(repo_root); + // only paths within the repo can be automatically cached + if relation == PathRelation::Parent || relation == PathRelation::Divergent { + warn!( + "skipping automatic task caching - file accessed outside of repo root \ + ({})", + unescaped_str + ); + return false; + } + }, + Err(e) => { + debug!("failed to parse path {unescaped_str}: {e}"); + }, + } + } + + true + } +} + +#[derive(Clone)] +pub struct TaskAccess { + repo_root:AbsoluteSystemPathBuf, + trace_by_task:Arc>>, + config_cache:Option, + enabled:bool, +} + +impl TaskAccess { + pub fn new(repo_root:AbsoluteSystemPathBuf, cache:AsyncCache, scm:&SCM) -> Self { + let root = repo_root.clone(); + let enabled = task_access_trace_enabled(&root).unwrap_or(false); + let trace_by_task = Arc::new(Mutex::new(HashMap::::new())); + let mut config_cache = Option::::None; + + // we only want to setup the config cacher if task access tracing is enabled + if enabled { + // make sure .turbo is ignored + match ensure_turbo_is_gitignored(&repo_root) { + Ok(_) => debug!("Automatically added .turbo to .gitignore"), + Err(e) => { + error!("Failed to add .turbo to .gitignore. Caching will be disabled - {e}") + }, + } + + let config_hash_result = ConfigCache::calculate_config_hash(scm, &root); + if let Ok(c_hash) = config_hash_result { + let c_cache = ConfigCache::new( + c_hash.to_string(), + root.clone(), + &TASK_ACCESS_CONFIG_PATH, + cache.clone(), + ); + + config_cache = Some(c_cache); + } + } + + Self { repo_root, trace_by_task, enabled, config_cache } + } + + pub fn is_enabled(&self) -> bool { self.enabled } + + pub async fn restore_config(&self) { + match (self.enabled, &self.config_cache) { + (true, Some(config_cache)) => { + match config_cache.restore().await { + Ok(_) => { + debug!("TASK ACCESS TRACE: config restored for {}", config_cache.hash()) + }, + Err(_) => { + debug!("TASK ACCESS TRACE: no config found for {}", config_cache.hash()) + }, + } + }, + _ => { + debug!("TASK ACCESS TRACE: unable to restore config from cache"); + }, + } + } + + pub fn save_trace(&self, task_id:String, trace:TaskAccessTraceFile) { + let trace_by_task = self.trace_by_task.lock(); + match trace_by_task { + Ok(mut trace_by_task) => { + trace_by_task.insert(task_id, trace); + }, + Err(e) => { + error!("Failed to save trace result - {e}"); + }, + } + } + + pub fn get_env_var(&self, task_hash:&str) -> (String, AbsoluteSystemPathBuf) { + let trace_file_path = trace_file_path(&self.repo_root, task_hash); + (TASK_ACCESS_ENV_KEY.to_string(), trace_file_path) + } + + pub async fn save(&self) { + match self.to_file().await { + Ok(_) => (), + Err(e) => { + error!("Failed to write task access trace file - {e}"); + }, + } + } + + // Whether we can cache the given task, returning None if task access isn't + // enabled or the trace can't be found + pub fn can_cache(&self, task_hash:&str, task_id:&str) -> Option { + if !self.is_enabled() { + return None; + } + let trace = TaskAccessTraceFile::read(&self.repo_root, task_hash)?; + if trace.can_cache(&self.repo_root) { + self.save_trace(task_id.to_string(), trace); + Some(true) + } else { + Some(false) + } + } + + async fn to_file(&self) -> Result<(), ToFileError> { + // if task access tracing is not enabled, we don't need to do anything + if !self.is_enabled() { + return Ok(()); + } + + if let Some(config_cache) = &self.config_cache { + let traced_config = + RawTurboJson::from_task_access_trace(&self.trace_by_task.lock().unwrap()); + if traced_config.is_some() { + // convert the traced_config to json and write the file to disk + let traced_config_json = serde_json::to_string_pretty(&traced_config)?; + let file_path = self.repo_root.join_components(&TASK_ACCESS_CONFIG_PATH); + let mut file = File::create(file_path)?; + write!(file, "{}", traced_config_json)?; + file.flush()?; + config_cache.save().await?; + } + } + + Ok(()) + } +} diff --git a/crates/turborepo-lib/Source/run/task_id.rs b/crates/turborepo-lib/Source/run/task_id.rs new file mode 100644 index 0000000000000..f0a13765c8640 --- /dev/null +++ b/crates/turborepo-lib/Source/run/task_id.rs @@ -0,0 +1,246 @@ +use std::{ + borrow::{Borrow, Cow}, + fmt, +}; + +use serde::{Deserialize, Serialize}; +use turborepo_repository::package_graph::{PackageName, ROOT_PKG_NAME}; + +pub const TASK_DELIMITER:&str = "#"; + +/// A task identifier as it will appear in the task graph +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize)] +#[serde(from = "String", into = "String")] +pub struct TaskId<'a> { + package:Cow<'a, str>, + task:Cow<'a, str>, +} + +/// A task name as it appears in a `turbo.json` it might be for all +/// workspaces or just one. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash)] +#[serde(try_from = "String", into = "String")] +pub struct TaskName<'a> { + package:Option>, + task:Cow<'a, str>, +} + +impl<'a> From> for TaskName<'a> { + fn from(value:TaskId<'a>) -> Self { + let TaskId { package, task } = value; + TaskName { package:Some(package), task } + } +} + +#[derive(Debug, thiserror::Error)] +#[error("No workspace found in task id '{input}'")] +pub struct TaskIdError<'a> { + input:&'a str, +} + +impl<'a> fmt::Display for TaskId<'a> { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + f.write_fmt(format_args!("{}{TASK_DELIMITER}{}", self.package, self.task)) + } +} + +impl<'a> From> for String { + fn from(value:TaskId<'a>) -> Self { value.to_string() } +} + +impl TaskId<'static> { + pub fn from_static(package:String, task:String) -> Self { + TaskId { package:package.into(), task:task.into() } + } +} + +impl<'a> TaskId<'a> { + pub fn new(package:&'a str, task:&'a str) -> Self { + TaskId::try_from(task).unwrap_or_else(|_| Self { package:package.into(), task:task.into() }) + } + + pub fn from_graph(workspace:&PackageName, task_name:&TaskName) -> TaskId<'static> { + task_name.task_id().map_or_else( + || { + let package = match workspace { + PackageName::Root => ROOT_PKG_NAME.into(), + PackageName::Other(workspace) => static_cow(workspace.as_str().into()), + }; + TaskId { package, task:static_cow(task_name.task().into()) } + }, + |id| id.into_owned(), + ) + } + + pub fn package(&self) -> &str { &self.package } + + pub fn to_workspace_name(&self) -> PackageName { + match self.package.as_ref() { + ROOT_PKG_NAME => PackageName::Root, + package => PackageName::Other(package.into()), + } + } + + pub fn task(&self) -> &str { &self.task } + + pub fn as_non_workspace_task_name(&self) -> TaskName { + let task:&str = &self.task; + TaskName { package:None, task:task.into() } + } + + pub fn as_task_name(&self) -> TaskName { + let package:&str = &self.package; + let task:&str = &self.task; + TaskName { package:Some(package.into()), task:task.into() } + } + + pub fn into_owned(self) -> TaskId<'static> { + let TaskId { package, task } = self; + TaskId { package:static_cow(package), task:static_cow(task) } + } + + /// Borrows a TaskId reference as a TaskId + pub fn as_borrowed(&self) -> TaskId { + let TaskId { package, task } = self; + let package = shorten_cow(package); + let task = shorten_cow(task); + TaskId { package, task } + } +} + +impl<'a> TryFrom<&'a str> for TaskId<'a> { + type Error = TaskIdError<'a>; + + fn try_from(value:&'a str) -> Result { + // We use split once here as the Go code will fail to find any task + // name that contains a '#' in the task graph. + // e.g. workspace#test#check can't run as we'll look for test and + // attempt to run test instead of test#check + match value.split_once(TASK_DELIMITER) { + None | Some(("", _)) => Err(TaskIdError { input:value }), + Some((package, task)) => Ok(TaskId { package:package.into(), task:task.into() }), + } + } +} + +impl<'a> From<&'a str> for TaskName<'a> { + fn from(value:&'a str) -> Self { + match value.split_once(TASK_DELIMITER) { + // Note we allow empty workspaces + // In the future we shouldn't allow this and throw when we encounter them + Some((package, task)) => Self { package:Some(package.into()), task:task.into() }, + None => Self { package:None, task:value.into() }, + } + } +} + +// Utility method changing the lifetime of an owned cow to reflect that it is +// owned +fn static_cow<'a, T:'a + ToOwned + ?Sized>(cow:Cow<'a, T>) -> Cow<'static, T> { + match cow { + Cow::Borrowed(x) => Cow::Owned(x.to_owned()), + Cow::Owned(x) => Cow::Owned(x), + } +} + +// Utility method for changing &'a Cow<'b, T> to Cow<'a, T> +// 'b must outlive 'a +#[allow(clippy::ptr_arg)] +fn shorten_cow<'a, 'b:'a, T:ToOwned + ?Sized>(cow:&'a Cow<'b, T>) -> Cow<'a, T> { + match cow { + Cow::Borrowed(x) => Cow::Borrowed(x), + Cow::Owned(x) => Cow::Borrowed(x.borrow()), + } +} + +impl From for TaskName<'static> { + fn from(value:String) -> Self { + let str = value.as_str(); + let TaskName { package, task } = TaskName::from(str); + let package = package.map(static_cow); + let task = static_cow(task); + Self { package, task } + } +} + +impl<'a> fmt::Display for TaskName<'a> { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + match &self.package { + Some(package) => f.write_fmt(format_args!("{package}{TASK_DELIMITER}{}", self.task)), + None => f.write_str(&self.task), + } + } +} + +impl<'a> From> for String { + fn from(value:TaskName<'a>) -> Self { value.to_string() } +} + +impl<'a> TaskName<'a> { + pub fn package(&self) -> Option<&str> { + let package:&str = self.package.as_ref()?; + Some(package) + } + + pub fn task(&self) -> &str { &self.task } + + pub fn into_non_workspace_task(self) -> Self { + let Self { task, .. } = self; + Self { package:None, task } + } + + // Makes a task a root workspace task + // e.g. build to //#build + pub fn into_root_task(self) -> TaskName<'static> { + let Self { task, .. } = self; + TaskName { package:Some(ROOT_PKG_NAME.into()), task:static_cow(task) } + } + + pub fn task_id(&self) -> Option> { + let package:&str = self.package.as_deref()?; + let task:&str = &self.task; + Some(TaskId { package:package.into(), task:task.into() }) + } + + pub fn is_package_task(&self) -> bool { self.package.is_some() } + + pub fn in_workspace(&self, workspace:&str) -> bool { + self.task_id().map_or(true, |task_id| task_id.package() == workspace) + } + + pub fn into_owned(self) -> TaskName<'static> { + let TaskName { package, task } = self; + TaskName { package:package.map(static_cow), task:static_cow(task) } + } +} + +#[cfg(test)] +mod test { + use test_case::test_case; + + use super::*; + + #[test_case("foo#build" ; "workspace task")] + #[test_case("//#root" ; "root task")] + #[test_case("@scope/foo#build" ; "workspace with scope")] + fn test_roundtrip(input:&str) { + assert_eq!(input, TaskId::try_from(input).unwrap().to_string()); + } + + #[test_case("foo", "build", "foo#build" ; "normal task")] + #[test_case("foo", "bar#build", "bar#build" ; "workspace specific task")] + #[test_case("foo", "//#build", "//#build" ; "root task")] + fn test_new_task_id(package_name:&str, task_name:&str, expected:&str) { + let expected = TaskId::try_from(expected).unwrap(); + let actual = TaskId::new(package_name, task_name); + assert_eq!(actual, expected); + } + + #[test_case("build" ; "global task")] + #[test_case("foo#build" ; "workspace task")] + #[test_case("//#build" ; "root task")] + #[test_case("#build" ; "empty workspace")] + fn test_task_name_roundtrip(input:&str) { + assert_eq!(input, TaskName::from(input).to_string()); + } +} diff --git a/crates/turborepo-lib/Source/run/ui.rs b/crates/turborepo-lib/Source/run/ui.rs new file mode 100644 index 0000000000000..af53d2d90bd32 --- /dev/null +++ b/crates/turborepo-lib/Source/run/ui.rs @@ -0,0 +1,18 @@ +use std::sync::Arc; + +use turborepo_ui::wui::{event::WebUIEvent, query::SharedState}; + +use crate::{query, run::Run}; + +pub async fn start_web_ui_server( + rx:tokio::sync::mpsc::UnboundedReceiver, + run:Arc, +) -> Result<(), turborepo_ui::Error> { + let state = SharedState::default(); + let subscriber = turborepo_ui::wui::subscriber::Subscriber::new(rx); + tokio::spawn(subscriber.watch(state.clone())); + + query::run_server(Some(state.clone()), run).await?; + + Ok(()) +} diff --git a/crates/turborepo-lib/src/run/watch.rs b/crates/turborepo-lib/Source/run/watch.rs similarity index 100% rename from crates/turborepo-lib/src/run/watch.rs rename to crates/turborepo-lib/Source/run/watch.rs diff --git a/crates/turborepo-lib/Source/shim/local_turbo_config.rs b/crates/turborepo-lib/Source/shim/local_turbo_config.rs new file mode 100644 index 0000000000000..f729f5e63e8bb --- /dev/null +++ b/crates/turborepo-lib/Source/shim/local_turbo_config.rs @@ -0,0 +1,203 @@ +use std::env; + +use tracing::debug; +use turborepo_repository::{inference::RepoState, package_manager::PackageManager}; + +const TURBO_DOWNLOAD_LOCAL_ENABLED:&str = "TURBO_DOWNLOAD_LOCAL_ENABLED"; + +/// Struct containing information about the desired local turbo version +/// according to lockfiles, package.jsons, and if all else fails turbo.json +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LocalTurboConfig { + turbo_version:String, +} + +fn is_env_var_truthy(env_var:&str) -> Option { + let value = env::var(env_var).ok()?; + match value.as_str() { + "1" | "true" => Some(true), + "0" | "false" => Some(false), + _ => None, + } +} + +impl LocalTurboConfig { + pub fn infer(repo_state:&RepoState) -> Option { + Self::infer_internal(repo_state, is_env_var_truthy(TURBO_DOWNLOAD_LOCAL_ENABLED)) + } + + // Used for testing when we want to manually set the controlling env var + fn infer_internal(repo_state:&RepoState, is_enabled:Option) -> Option { + // TODO: once we have properly communicated this functionality we should make + // this opt-out. + if !is_enabled.unwrap_or(false) { + debug!("downloading correct local version not enabled"); + return None; + } + let turbo_version = Self::turbo_version_from_lockfile(repo_state)?; + Some(Self { turbo_version }) + } + + pub fn turbo_version(&self) -> &str { &self.turbo_version } + + fn turbo_version_from_lockfile(repo_state:&RepoState) -> Option { + if let Ok(package_manager) = &repo_state.package_manager { + let lockfile = package_manager + .read_lockfile(&repo_state.root, &repo_state.root_package_json) + .ok()?; + return lockfile.turbo_version(); + } + + // If there isn't a package manager, just try to parse all known lockfiles + // This isn't the most efficient, but since we'll be hitting network to download + // the correct binary the unnecessary file reads aren't costly relative to the + // download. + PackageManager::supported_managers().iter().find_map(|pm| { + let lockfile = + pm.read_lockfile(&repo_state.root, &repo_state.root_package_json).ok()?; + lockfile.turbo_version() + }) + } +} + +#[cfg(test)] +mod test { + use tempfile::TempDir; + use turbopath::AbsoluteSystemPath; + use turborepo_repository::{ + inference::RepoMode, + package_json::PackageJson, + package_manager::Error, + }; + + use super::*; + + #[test] + fn test_package_manager_and_lockfile() { + let tmpdir = TempDir::with_prefix("local_config").unwrap(); + let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); + let repo = RepoState { + root:root.to_owned(), + mode:RepoMode::MultiPackage, + root_package_json:PackageJson::default(), + package_manager:Ok(PackageManager::Npm), + }; + let lockfile = root.join_component("package-lock.json"); + lockfile + .create_with_contents(include_bytes!( + "../../fixtures/local_config/turbov2.package-lock.json" + )) + .unwrap(); + + assert_eq!( + LocalTurboConfig::infer_internal(&repo, Some(true)), + Some(LocalTurboConfig { turbo_version:"2.0.3".into() }) + ); + } + + #[test] + fn test_just_lockfile() { + let tmpdir = TempDir::with_prefix("local_config").unwrap(); + let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); + let repo = RepoState { + root:root.to_owned(), + mode:RepoMode::MultiPackage, + root_package_json:PackageJson::default(), + package_manager:Err(Error::MissingPackageManager), + }; + let lockfile = root.join_component("package-lock.json"); + lockfile + .create_with_contents(include_bytes!( + "../../fixtures/local_config/turbov2.package-lock.json" + )) + .unwrap(); + + assert_eq!( + LocalTurboConfig::infer_internal(&repo, Some(true)), + Some(LocalTurboConfig { turbo_version:"2.0.3".into() }) + ); + } + + #[test] + fn test_package_json_dep() { + let tmpdir = TempDir::with_prefix("local_config").unwrap(); + let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); + let repo = RepoState { + root:root.to_owned(), + mode:RepoMode::MultiPackage, + root_package_json:PackageJson { + dependencies:Some(vec![("turbo".into(), "^2.0.0".into())].into_iter().collect()), + ..Default::default() + }, + package_manager:Err(Error::MissingPackageManager), + }; + + assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None,); + } + + #[test] + fn test_package_json_dev_dep() { + let tmpdir = TempDir::with_prefix("local_config").unwrap(); + let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); + let repo = RepoState { + root:root.to_owned(), + mode:RepoMode::MultiPackage, + root_package_json:PackageJson { + dev_dependencies:Some( + vec![("turbo".into(), "^2.0.0".into())].into_iter().collect(), + ), + ..Default::default() + }, + package_manager:Err(Error::MissingPackageManager), + }; + + assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None); + } + + #[test] + fn test_v1_schema() { + let tmpdir = TempDir::with_prefix("local_config").unwrap(); + let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); + let repo = RepoState { + root:root.to_owned(), + mode:RepoMode::MultiPackage, + root_package_json:PackageJson::default(), + package_manager:Err(Error::MissingPackageManager), + }; + let turbo_json = root.join_component("turbo.json"); + turbo_json + .create_with_contents(include_bytes!("../../fixtures/local_config/turbo.v1.json")) + .unwrap(); + assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None); + } + + #[test] + fn test_v2_schema() { + let tmpdir = TempDir::with_prefix("local_config").unwrap(); + let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); + let repo = RepoState { + root:root.to_owned(), + mode:RepoMode::MultiPackage, + root_package_json:PackageJson::default(), + package_manager:Err(Error::MissingPackageManager), + }; + let turbo_json = root.join_component("turbo.json"); + turbo_json + .create_with_contents(include_bytes!("../../fixtures/local_config/turbo.v2.json")) + .unwrap(); + assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None,); + } + + #[test] + fn nothing() { + let tmpdir = TempDir::with_prefix("local_config").unwrap(); + let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); + let repo = RepoState { + root:root.to_owned(), + mode:RepoMode::MultiPackage, + root_package_json:PackageJson::default(), + package_manager:Err(Error::MissingPackageManager), + }; + assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None,); + } +} diff --git a/crates/turborepo-lib/Source/shim/local_turbo_state.rs b/crates/turborepo-lib/Source/shim/local_turbo_state.rs new file mode 100644 index 0000000000000..3e129411ffe77 --- /dev/null +++ b/crates/turborepo-lib/Source/shim/local_turbo_state.rs @@ -0,0 +1,211 @@ +use std::{ + env, + fs, + path::{Path, PathBuf}, +}; + +use camino::Utf8PathBuf; +use dunce::canonicalize as fs_canonicalize; +use semver::Version; +use serde::Deserialize; +use tracing::debug; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; +use turborepo_repository::package_json::PackageJson; + +use super::TurboState; + +/// Structure that holds information on an existing local turbo install +#[derive(Debug)] +pub struct LocalTurboState { + bin_path:PathBuf, + version:String, +} + +impl LocalTurboState { + pub fn version(&self) -> &str { &self.version } + + pub fn binary(&self) -> &Path { &self.bin_path } + + // Hoisted strategy: + // - `bun install` + // - `npm install` + // - `yarn` + // - `yarn install --flat` + // - berry (nodeLinker: "node-modules") + // + // This also supports people directly depending upon the platform version. + fn generate_hoisted_path(root_path:&AbsoluteSystemPath) -> Option { + Some(root_path.join_component("node_modules")) + } + + // Nested strategy: + // - `npm install --install-strategy=shallow` (`npm install --global-style`) + // - `npm install --install-strategy=nested` (`npm install --legacy-bundling`) + // - berry (nodeLinker: "pnpm") + fn generate_nested_path(root_path:&AbsoluteSystemPath) -> Option { + Some(root_path.join_components(&["node_modules", "turbo", "node_modules"])) + } + + // Linked strategy: + // - `pnpm install` + // - `npm install --install-strategy=linked` + fn generate_linked_path(root_path:&AbsoluteSystemPath) -> Option { + // root_path/node_modules/turbo is a symlink. Canonicalize the symlink to what + // it points to. We do this _before_ traversing up to the parent, + // because on Windows, if you canonicalize a path that ends with `/..` + // it traverses to the parent directory before it follows the symlink, + // leading to the wrong place. We could separate the Windows + // implementation, but this workaround works for other platforms as + // well. + let canonical_path = + fs_canonicalize(root_path.as_path().join("node_modules").join("turbo")).ok()?; + + AbsoluteSystemPathBuf::try_from(canonical_path.parent()?).ok() + } + + // The unplugged directory doesn't have a fixed path. + fn get_unplugged_base_path(root_path:&AbsoluteSystemPath) -> Utf8PathBuf { + let yarn_rc_filename = + env::var("YARN_RC_FILENAME").unwrap_or_else(|_| String::from(".yarnrc.yml")); + let yarn_rc_filepath = root_path.as_path().join(yarn_rc_filename); + + let yarn_rc_yaml_string = fs::read_to_string(yarn_rc_filepath).unwrap_or_default(); + let yarn_rc:YarnRc = serde_yaml::from_str(&yarn_rc_yaml_string).unwrap_or_default(); + + root_path.as_path().join(yarn_rc.pnp_unplugged_folder) + } + + // Unplugged strategy: + // - berry 2.1+ + fn generate_unplugged_path(root_path:&AbsoluteSystemPath) -> Option { + let platform_package_name = TurboState::platform_package_name(); + let unplugged_base_path = Self::get_unplugged_base_path(root_path); + + unplugged_base_path.read_dir_utf8().ok().and_then(|mut read_dir| { + // berry includes additional metadata in the filename. + // We actually have to find the platform package. + read_dir.find_map(|item| { + match item { + Ok(entry) => { + let file_name = entry.file_name(); + if file_name.starts_with(platform_package_name) { + AbsoluteSystemPathBuf::new( + unplugged_base_path.join(file_name).join("node_modules"), + ) + .ok() + } else { + None + } + }, + Err(_) => None, + } + }) + }) + } + + // We support six per-platform packages and one `turbo` package which handles + // indirection. We identify the per-platform package and execute the appropriate + // binary directly. We can choose to operate this aggressively because the + // _worst_ outcome is that we run global `turbo`. + // + // In spite of that, the only known unsupported local invocation is Yarn/Berry < + // 2.1 PnP + pub fn infer(root_path:&AbsoluteSystemPath) -> Option { + let platform_package_name = TurboState::platform_package_name(); + let binary_name = TurboState::binary_name(); + + let platform_package_json_path_components = [platform_package_name, "package.json"]; + let platform_package_executable_path_components = + [platform_package_name, "bin", binary_name]; + + // These are lazy because the last two are more expensive. + let search_functions = [ + Self::generate_hoisted_path, + Self::generate_nested_path, + Self::generate_linked_path, + Self::generate_unplugged_path, + ]; + + // Detecting the package manager is more expensive than just doing an exhaustive + // search. + for root in search_functions.iter().filter_map(|search_function| search_function(root_path)) + { + // Needs borrow because of the loop. + #[allow(clippy::needless_borrow)] + let bin_path = root.join_components(&platform_package_executable_path_components); + match fs_canonicalize(&bin_path) { + Ok(bin_path) => { + let resolved_package_json_path = + root.join_components(&platform_package_json_path_components); + let platform_package_json = + PackageJson::load(&resolved_package_json_path).ok()?; + let local_version = platform_package_json.version?; + + debug!("Local turbo path: {}", bin_path.display()); + debug!("Local turbo version: {}", &local_version); + return Some(Self { bin_path, version:local_version }); + }, + Err(_) => debug!("No local turbo binary found at: {}", bin_path), + } + } + + None + } + + /// Check to see if the detected local executable is the one currently + /// running. + pub fn local_is_self(&self) -> bool { + std::env::current_exe().is_ok_and(|current_exe| { + fs_canonicalize(current_exe) + .is_ok_and(|canonical_current_exe| canonical_current_exe == self.bin_path) + }) + } +} + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +struct YarnRc { + pnp_unplugged_folder:Utf8PathBuf, +} + +impl Default for YarnRc { + fn default() -> Self { Self { pnp_unplugged_folder:[".yarn", "unplugged"].iter().collect() } } +} + +pub fn turbo_version_has_shim(version:&str) -> bool { + if let Ok(version) = Version::parse(version) { + // only need to check major and minor (this will include canaries) + if version.major == 1 { + return version.minor >= 7; + } + version.major > 1 + } else { + // In the case that we don't get passed a valid semver we should avoid a panic. + // We shouldn't hit this we introduce back inferring package version from schema + // or package.json. + true + } +} + +#[cfg(test)] +mod test { + use test_case::test_case; + + use super::*; + + #[test_case("1.7.0-canary.0", true; "canary")] + #[test_case("1.7.0-canary.1", true; "newer_canary")] + #[test_case("1.7.1-canary.6", true; "newer_minor_canary")] + #[test_case("1.7.0", true; "release")] + #[test_case("1.6.3", false; "old")] + #[test_case("1.6.2-canary.1", false; "old_canary")] + #[test_case("1.8.0", true; "new")] + #[test_case("2.1.0", true; "new major")] + #[test_case("*", true; "star")] + #[test_case("2.0", true; "version 2 0")] + #[test_case("latest", true; "latest")] + #[test_case("canary", true; "canary tag")] + fn test_skip_infer_version_constraint(version:&str, expected:bool) { + assert_eq!(turbo_version_has_shim(version), expected); + } +} diff --git a/crates/turborepo-lib/src/shim/mod.rs b/crates/turborepo-lib/Source/shim/mod.rs similarity index 100% rename from crates/turborepo-lib/src/shim/mod.rs rename to crates/turborepo-lib/Source/shim/mod.rs diff --git a/crates/turborepo-lib/Source/shim/parser.rs b/crates/turborepo-lib/Source/shim/parser.rs new file mode 100644 index 0000000000000..a6095300d3671 --- /dev/null +++ b/crates/turborepo-lib/Source/shim/parser.rs @@ -0,0 +1,455 @@ +use std::{backtrace::Backtrace, env}; + +use itertools::Itertools; +use miette::{Diagnostic, SourceSpan}; +use turbopath::AbsoluteSystemPathBuf; +use turborepo_ui::ColorConfig; + +use super::Error; + +// all arguments that result in a stdout that much be directly parsable and +// should not be paired with additional output (from the update notifier for +// example) +static TURBO_PURE_OUTPUT_ARGS:[&str; 6] = + ["--json", "--dry", "--dry-run", "--dry=json", "--graph", "--dry-run=json"]; + +static TURBO_SKIP_NOTIFIER_ARGS:[&str; 5] = + ["--help", "--h", "--version", "--v", "--no-update-notifier"]; + +#[derive(Debug, thiserror::Error, Diagnostic)] +#[error("cannot have multiple `--cwd` flags in command")] +#[diagnostic(code(turbo::shim::multiple_cwd))] +pub struct MultipleCwd { + #[backtrace] + backtrace:Backtrace, + #[source_code] + args_string:String, + #[label("first flag declared here")] + flag1:Option, + #[label("but second flag declared here")] + flag2:Option, + #[label("and here")] + flag3:Option, + // The user should get the idea after the first 4 examples. + #[label("and here")] + flag4:Option, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct ShimArgs { + pub cwd:AbsoluteSystemPathBuf, + pub invocation_dir:AbsoluteSystemPathBuf, + pub skip_infer:bool, + pub verbosity:usize, + pub force_update_check:bool, + pub remaining_turbo_args:Vec, + pub forwarded_args:Vec, + pub color:bool, + pub no_color:bool, +} + +impl ShimArgs { + pub fn parse() -> Result { + let invocation_dir = AbsoluteSystemPathBuf::cwd()?; + Self::parse_from_iter(invocation_dir, std::env::args()) + } + + fn parse_from_iter( + invocation_dir:AbsoluteSystemPathBuf, + args:impl Iterator, + ) -> Result { + let mut cwd_flag_idx = None; + let mut cwds = Vec::new(); + let mut skip_infer = false; + let mut found_verbosity_flag = false; + let mut verbosity = 0; + let mut force_update_check = false; + let mut remaining_turbo_args = Vec::new(); + let mut forwarded_args = Vec::new(); + let mut is_forwarded_args = false; + let mut color = false; + let mut no_color = false; + + let args = args.skip(1); + for (idx, arg) in args.enumerate() { + // We've seen a `--` and therefore we do no parsing + if is_forwarded_args { + forwarded_args.push(arg); + } else if arg == "--skip-infer" { + skip_infer = true; + } else if arg == "--check-for-update" { + force_update_check = true; + } else if arg == "--" { + // If we've hit `--` we've reached the args forwarded to tasks. + is_forwarded_args = true; + } else if arg == "--verbosity" { + // If we see `--verbosity` we expect the next arg to be a number. + remaining_turbo_args.push(arg); + found_verbosity_flag = true + } else if arg.starts_with("--verbosity=") || found_verbosity_flag { + let verbosity_count = if found_verbosity_flag { + found_verbosity_flag = false; + &arg + } else { + arg.strip_prefix("--verbosity=").unwrap_or("0") + }; + + verbosity = verbosity_count.parse::().unwrap_or(0); + remaining_turbo_args.push(arg); + } else if arg == "-v" || arg.starts_with("-vv") { + verbosity = arg[1..].len(); + remaining_turbo_args.push(arg); + } else if cwd_flag_idx.is_some() { + // We've seen a `--cwd` and therefore add this to the cwds list along with + // the index of the `--cwd` (*not* the value) + cwds.push((AbsoluteSystemPathBuf::from_unknown(&invocation_dir, arg), idx - 1)); + cwd_flag_idx = None; + } else if arg == "--cwd" { + // If we see a `--cwd` we expect the next arg to be a path. + cwd_flag_idx = Some(idx) + } else if let Some(cwd_arg) = arg.strip_prefix("--cwd=") { + // In the case where `--cwd` is passed as `--cwd=./path/to/foo`, that + // entire chunk is a single arg, so we need to split it up. + cwds.push((AbsoluteSystemPathBuf::from_unknown(&invocation_dir, cwd_arg), idx)); + } else if arg == "--color" { + color = true; + } else if arg == "--no-color" { + no_color = true; + } else { + remaining_turbo_args.push(arg); + } + } + + if let Some(idx) = cwd_flag_idx { + let (spans, args_string) = + Self::get_spans_in_args_string(vec![idx], env::args().skip(1)); + + return Err(Error::EmptyCwd { + backtrace:Backtrace::capture(), + args_string, + flag_range:spans[0], + }); + } + + if cwds.len() > 1 { + let (indices, args_string) = Self::get_spans_in_args_string( + cwds.iter().map(|(_, idx)| *idx).collect(), + env::args().skip(1), + ); + + let mut flags = indices.into_iter(); + return Err(Error::MultipleCwd(Box::new(MultipleCwd { + backtrace:Backtrace::capture(), + args_string, + flag1:flags.next(), + flag2:flags.next(), + flag3:flags.next(), + flag4:flags.next(), + }))); + } + + let cwd = cwds.pop().map(|(cwd, _)| cwd).unwrap_or_else(|| invocation_dir.clone()); + + Ok(ShimArgs { + cwd, + invocation_dir, + skip_infer, + verbosity, + force_update_check, + remaining_turbo_args, + forwarded_args, + color, + no_color, + }) + } + + /// Takes a list of indices into a Vec of arguments, i.e. ["--graph", "foo", + /// "--cwd"] and converts them into `SourceSpan`'s into the string of those + /// arguments, i.e. "-- graph foo --cwd". Returns the spans and the args + /// string + fn get_spans_in_args_string( + mut args_indices:Vec, + args:impl Iterator>, + ) -> (Vec, String) { + // Sort the indices to keep the invariant + // that if i > j then output[i] > output[j] + args_indices.sort(); + let mut indices_in_args_string = Vec::new(); + let mut i = 0; + let mut current_args_string_idx = 0; + + for (idx, arg) in args.enumerate() { + let Some(arg_idx) = args_indices.get(i) else { + break; + }; + + let arg = arg.into(); + + if idx == *arg_idx { + indices_in_args_string.push((current_args_string_idx, arg.len()).into()); + i += 1; + } + current_args_string_idx += arg.len() + 1; + } + + let args_string = env::args().skip(1).join(" "); + + (indices_in_args_string, args_string) + } + + // returns true if any flags result in pure json output to stdout + fn has_json_flags(&self) -> bool { + self.remaining_turbo_args + .iter() + .any(|arg| TURBO_PURE_OUTPUT_ARGS.contains(&arg.as_str())) + } + + // returns true if any flags should bypass the update notifier + fn has_notifier_skip_flags(&self) -> bool { + self.remaining_turbo_args + .iter() + .any(|arg| TURBO_SKIP_NOTIFIER_ARGS.contains(&arg.as_str())) + } + + pub fn should_check_for_update(&self) -> bool { + if self.force_update_check { + return true; + } + + if self.has_notifier_skip_flags() || self.has_json_flags() { + return false; + } + + true + } + + pub fn color_config(&self) -> ColorConfig { + if self.no_color { + ColorConfig::new(true) + } else if self.color { + // Do our best to enable ansi colors, but even if the terminal doesn't support + // still emit ansi escape sequences. + Self::supports_ansi(); + ColorConfig::new(false) + } else if Self::supports_ansi() { + // If the terminal supports ansi colors, then we can infer if we should emit + // colors + ColorConfig::infer() + } else { + ColorConfig::new(true) + } + } + + #[cfg(windows)] + fn supports_ansi() -> bool { + // This call has the side effect of setting ENABLE_VIRTUAL_TERMINAL_PROCESSING + // to true. https://learn.microsoft.com/en-us/windows/console/setconsolemode + crossterm::ansi_support::supports_ansi() + } + + #[cfg(not(windows))] + fn supports_ansi() -> bool { true } +} + +#[cfg(test)] +mod test { + use miette::SourceSpan; + use pretty_assertions::assert_eq; + use test_case::test_case; + use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; + + use super::ShimArgs; + + #[test_case(vec![3], vec!["--graph", "foo", "--cwd", "apple"], vec![(18, 5).into()])] + #[test_case(vec![0], vec!["--graph", "foo", "--cwd"], vec![(0, 7).into()])] + #[test_case(vec![0, 2], vec!["--graph", "foo", "--cwd"], vec![(0, 7).into(), (12, 5).into()])] + #[test_case(vec![], vec!["--cwd"], vec![])] + fn test_get_indices_in_arg_string( + arg_indices:Vec, + args:Vec<&'static str>, + expected_indices_in_arg_string:Vec, + ) { + let (indices_in_args_string, _) = + ShimArgs::get_spans_in_args_string(arg_indices, args.into_iter()); + assert_eq!(indices_in_args_string, expected_indices_in_arg_string); + } + + #[derive(Default)] + struct ExpectedArgs { + pub skip_infer:bool, + pub verbosity:usize, + pub force_update_check:bool, + pub remaining_turbo_args:&'static [&'static str], + pub forwarded_args:&'static [&'static str], + pub color:bool, + pub no_color:bool, + pub relative_cwd:Option<&'static [&'static str]>, + } + + impl ExpectedArgs { + fn build(self, invocation_dir:&AbsoluteSystemPath) -> ShimArgs { + let Self { + skip_infer, + verbosity, + force_update_check, + remaining_turbo_args, + forwarded_args, + color, + no_color, + relative_cwd, + } = self; + ShimArgs { + cwd:relative_cwd.map_or_else( + || invocation_dir.to_owned(), + |components| invocation_dir.join_components(components), + ), + invocation_dir:invocation_dir.to_owned(), + remaining_turbo_args:remaining_turbo_args + .iter() + .map(|arg| arg.to_string()) + .collect(), + forwarded_args:forwarded_args.iter().map(|arg| arg.to_string()).collect(), + skip_infer, + verbosity, + force_update_check, + color, + no_color, + } + } + } + + #[test_case( + &["turbo"], + ExpectedArgs { + ..Default::default() + } + ; "no args" + )] + #[test_case( + &["turbo", "-v"], + ExpectedArgs { + verbosity: 1, + remaining_turbo_args: &["-v"], + ..Default::default() + } + ; "verbosity count 1" + )] + #[test_case( + &["turbo", "-vv"], + ExpectedArgs { + verbosity: 2, + remaining_turbo_args: &["-vv"], + ..Default::default() + } + ; "verbosity count 2" + )] + #[test_case( + &["turbo", "--verbosity", "3"], + ExpectedArgs { + verbosity: 3, + remaining_turbo_args: &["--verbosity", "3"], + ..Default::default() + } + ; "verbosity flag 3" + )] + #[test_case( + &["turbo", "--verbosity=3"], + ExpectedArgs { + verbosity: 3, + remaining_turbo_args: &["--verbosity=3"], + ..Default::default() + } + ; "verbosity equals 3" + )] + #[test_case( + &["turbo", "--verbosity=3", "-vv"], + ExpectedArgs { + verbosity: 2, + remaining_turbo_args: &["--verbosity=3", "-vv"], + ..Default::default() + } + ; "multi verbosity" + )] + #[test_case( + &["turbo", "--color"], + ExpectedArgs { + color: true, + ..Default::default() + } + ; "color" + )] + #[test_case( + &["turbo", "--no-color"], + ExpectedArgs { + no_color: true, + ..Default::default() + } + ; "no color" + )] + #[test_case( + &["turbo", "--no-color", "--color"], + ExpectedArgs { + color: true, + no_color: true, + ..Default::default() + } + ; "confused color" + )] + #[test_case( + &["turbo", "--skip-infer"], + ExpectedArgs { + skip_infer: true, + ..Default::default() + } + ; "skip infer" + )] + #[test_case( + &["turbo", "--", "another", "--skip-infer"], + ExpectedArgs { + forwarded_args: &["another", "--skip-infer"], + ..Default::default() + } + ; "forwarded args" + )] + #[test_case( + &["turbo", "--check-for-update"], + ExpectedArgs { + force_update_check: true, + ..Default::default() + } + ; "check for update" + )] + #[test_case( + &["turbo", "--check-for-update=true"], + ExpectedArgs { + force_update_check: false, + remaining_turbo_args: &["--check-for-update=true"], + ..Default::default() + } + ; "check for update value" + )] + #[test_case( + &["turbo", "--cwd", "another-dir"], + ExpectedArgs { + relative_cwd: Some(&["another-dir"]), + ..Default::default() + } + ; "cwd value" + )] + #[test_case( + &["turbo", "--cwd=another-dir"], + ExpectedArgs { + relative_cwd: Some(&["another-dir"]), + ..Default::default() + } + ; "cwd equals" + )] + fn test_shim_parsing(args:&[&str], expected:ExpectedArgs) { + let cwd = + AbsoluteSystemPathBuf::new(if cfg!(windows) { "Z:\\some\\dir" } else { "/some/dir" }) + .unwrap(); + let expected = expected.build(&cwd); + let actual = ShimArgs::parse_from_iter(cwd, args.iter().map(|s| s.to_string())).unwrap(); + assert_eq!(expected, actual); + } +} diff --git a/crates/turborepo-lib/Source/shim/turbo_state.rs b/crates/turborepo-lib/Source/shim/turbo_state.rs new file mode 100644 index 0000000000000..19347abc2fd26 --- /dev/null +++ b/crates/turborepo-lib/Source/shim/turbo_state.rs @@ -0,0 +1,70 @@ +use const_format::formatcp; + +/// Struct containing helper methods for querying information about the +/// currently running turbo binary. +#[derive(Debug)] +pub struct TurboState; + +impl TurboState { + pub const fn platform_name() -> &'static str { + const ARCH:&str = { + #[cfg(target_arch = "x86_64")] + { + "64" + } + #[cfg(target_arch = "aarch64")] + { + "arm64" + } + #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))] + { + "unknown" + } + }; + + const OS:&str = { + #[cfg(target_os = "macos")] + { + "darwin" + } + #[cfg(target_os = "windows")] + { + "windows" + } + #[cfg(target_os = "linux")] + { + "linux" + } + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] + { + "unknown" + } + }; + + formatcp!("{}-{}", OS, ARCH) + } + + pub const fn platform_package_name() -> &'static str { + formatcp!("turbo-{}", TurboState::platform_name()) + } + + pub const fn binary_name() -> &'static str { + { + #[cfg(windows)] + { + "turbo.exe" + } + #[cfg(not(windows))] + { + "turbo" + } + } + } + + pub fn version() -> &'static str { + include_str!("../../../../version.txt") + .lines() + .next() + .expect("Failed to read version from version.txt") + } +} diff --git a/crates/turborepo-lib/Source/signal.rs b/crates/turborepo-lib/Source/signal.rs new file mode 100644 index 0000000000000..12e94fc55ee0e --- /dev/null +++ b/crates/turborepo-lib/Source/signal.rs @@ -0,0 +1,205 @@ +use std::{ + fmt::Debug, + future::Future, + sync::{Arc, Mutex}, +}; + +use futures::{StreamExt, stream::FuturesUnordered}; +use tokio::sync::{mpsc, oneshot}; + +/// SignalHandler provides a mechanism to subscribe to a future and get alerted +/// whenever the future completes or the handler gets a close message. +#[derive(Debug, Clone)] +pub struct SignalHandler { + state:Arc>, + close:mpsc::Sender<()>, +} + +#[derive(Debug, Default)] +struct HandlerState { + subscribers:Vec>>, + is_closing:bool, +} + +pub struct SignalSubscriber(oneshot::Receiver>); + +/// SubscriberGuard should be kept until a subscriber is done processing the +/// signal +pub struct SubscriberGuard(oneshot::Sender<()>); + +impl SignalHandler { + /// Construct a new SignalHandler that will alert any subscribers when + /// `signal_source` completes or `close` is called on it. + pub fn new(signal_source:impl Future> + Send + 'static) -> Self { + // think about channel size + let state = Arc::new(Mutex::new(HandlerState::default())); + let worker_state = state.clone(); + let (close, mut rx) = mpsc::channel::<()>(1); + tokio::spawn(async move { + tokio::select! { + // We don't care if we get a signal or if we are unable to receive signals + // Either way we start the shutdown. + _ = signal_source => {}, + // We don't care if a close message was sent or if all handlers are dropped. + // Either way start the shutdown process. + _ = rx.recv() => {} + } + + let mut callbacks = { + let mut state = worker_state.lock().expect("lock poisoned"); + // Mark ourselves as closing to prevent any additional subscribers from being + // added + state.is_closing = true; + state + .subscribers + .drain(..) + .filter_map(|callback| { + let (tx, rx) = oneshot::channel(); + // If the subscriber is no longer around we don't wait for the callback + callback.send(tx).ok()?; + Some(rx) + }) + .collect::>() + }; + + // We don't care if callback gets dropped or if the done signal is sent. + while let Some(_fut) = callbacks.next().await {} + }); + + Self { state, close } + } + + /// Register a new subscriber + /// Will return `None` if SignalHandler is in the process of shutting down + /// or if it has already shut down. + pub fn subscribe(&self) -> Option { + self.state.lock().expect("poisoned lock").add_subscriber().map(SignalSubscriber) + } + + /// Send message to signal handler that it should shut down and alert + /// subscribers + pub async fn close(&self) { + if self.close.send(()).await.is_err() { + // watcher has already closed + return; + } + self.done().await; + } + + /// Wait until handler is finished and all subscribers finish their cleanup + /// work + pub async fn done(&self) { + // Receiver is dropped once the worker task completes + self.close.closed().await; + } + + // Check if the worker thread is done, only meant to be used for assertions in + // testing + #[cfg(test)] + fn is_done(&self) -> bool { self.close.is_closed() } +} + +impl SignalSubscriber { + /// Wait until signal is received by the signal handler + pub async fn listen(self) -> SubscriberGuard { + let callback = self + .0 + .await + .expect("signal handler worker thread exited without alerting subscribers"); + SubscriberGuard(callback) + } +} + +impl HandlerState { + fn add_subscriber(&mut self) -> Option>> { + (!self.is_closing).then(|| { + let (tx, rx) = oneshot::channel(); + self.subscribers.push(tx); + rx + }) + } +} + +#[cfg(test)] +mod test { + use std::{assert_matches::assert_matches, time::Duration}; + + use super::*; + + #[tokio::test] + async fn test_subscribers_triggered_from_signal() { + let (tx, rx) = oneshot::channel(); + let handler = SignalHandler::new(async move { rx.await.ok() }); + let subscriber = handler.subscribe().unwrap(); + // Send mocked SIGINT + tx.send(()).unwrap(); + + let (done, mut is_done) = oneshot::channel(); + let handler2 = handler.clone(); + tokio::spawn(async move { + handler2.done().await; + done.send(()).ok(); + }); + + let _guard = subscriber.listen().await; + assert_matches!( + is_done.try_recv(), + Err(oneshot::error::TryRecvError::Empty), + "done shouldn't be finished" + ); + drop(_guard); + tokio::time::sleep(Duration::from_millis(5)).await; + handler.done().await; + } + + #[tokio::test] + async fn test_subscribers_triggered_from_close() { + let (_tx, rx) = oneshot::channel::<()>(); + let handler = SignalHandler::new(async move { rx.await.ok() }); + let subscriber = handler.subscribe().unwrap(); + let (close_done, mut is_close_done) = oneshot::channel(); + + let h2 = handler.clone(); + let _handle = tokio::spawn(async move { + h2.close().await; + close_done.send(()).ok(); + }); + + let _guard = subscriber.listen().await; + assert_matches!( + is_close_done.try_recv(), + Err(oneshot::error::TryRecvError::Empty), + "close shouldn't be finished" + ); + drop(_guard); + handler.done().await; + } + + #[tokio::test] + async fn test_close_idempotent() { + let (_tx, rx) = oneshot::channel::<()>(); + let handler = SignalHandler::new(async move { rx.await.ok() }); + handler.close().await; + handler.close().await; + } + + #[tokio::test] + async fn test_subscribe_after_close() { + let (tx, rx) = oneshot::channel(); + let handler = SignalHandler::new(async move { rx.await.ok() }); + let subscriber = handler.subscribe().unwrap(); + + // Send SIGINT + tx.send(()).unwrap(); + // Do a quick yield to give the worker a chance to read the sigint + tokio::task::yield_now().await; + assert!(!handler.is_done(), "handler should not finish until subscriber finishes"); + assert!( + handler.subscribe().is_none(), + "handler that has received a signal should not accept new subscribers" + ); + let _guard = subscriber.listen().await; + drop(_guard); + handler.done().await; + } +} diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__force.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__force.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__force.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__force.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__force_remote_r,local_r.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__force_remote_r,local_r.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__force_remote_r,local_r.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__force_remote_r,local_r.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__no-cache.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__no-cache.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__no-cache.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__no-cache.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__no-cache_remote_w,local_rw.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__no-cache_remote_w,local_rw.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__no-cache_remote_w,local_rw.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__no-cache_remote_w,local_rw.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-cache-read-only.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-cache-read-only.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-cache-read-only.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-cache-read-only.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-cache-read-only_remote_rw,local_r.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-cache-read-only_remote_rw,local_r.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-cache-read-only_remote_rw,local_r.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-cache-read-only_remote_rw,local_r.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-only.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-only.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-only.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-only.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-only_remote_r,local_rw.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-only_remote_r,local_rw.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__remote-only_remote_r,local_rw.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__remote-only_remote_r,local_rw.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_boundaries_--filter_foo.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_boundaries_--filter_foo.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_boundaries_--filter_foo.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_boundaries_--filter_foo.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_ls_--filter_foo.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_ls_--filter_foo.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_ls_--filter_foo.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_ls_--filter_foo.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_run_build.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_run_build.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_run_build.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_run_build.snap diff --git a/crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_watch_build.snap b/crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_watch_build.snap similarity index 100% rename from crates/turborepo-lib/src/snapshots/turborepo_lib__opts__test__turbo_watch_build.snap rename to crates/turborepo-lib/Source/snapshots/turborepo_lib__opts__test__turbo_watch_build.snap diff --git a/crates/turborepo-lib/src/task_graph/mod.rs b/crates/turborepo-lib/Source/task_graph/mod.rs similarity index 100% rename from crates/turborepo-lib/src/task_graph/mod.rs rename to crates/turborepo-lib/Source/task_graph/mod.rs diff --git a/crates/turborepo-lib/Source/task_graph/visitor.rs b/crates/turborepo-lib/Source/task_graph/visitor.rs new file mode 100644 index 0000000000000..47e1a7590b7ec --- /dev/null +++ b/crates/turborepo-lib/Source/task_graph/visitor.rs @@ -0,0 +1,1082 @@ +use std::{ + borrow::Cow, + collections::HashSet, + io::Write, + sync::{Arc, Mutex, OnceLock}, + time::{Duration, Instant}, +}; + +use console::{Style, StyledObject}; +use either::Either; +use futures::{StreamExt, stream::FuturesUnordered}; +use itertools::Itertools; +use regex::Regex; +use tokio::sync::{mpsc, oneshot}; +use tracing::{Instrument, Span, debug, error}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPath}; +use turborepo_ci::{Vendor, VendorBehavior}; +use turborepo_env::EnvironmentVariableMap; +use turborepo_repository::{ + package_graph::{PackageGraph, PackageName, ROOT_PKG_NAME}, + package_manager::PackageManager, +}; +use turborepo_telemetry::events::{ + EventBuilder, + TrackedErrors, + generic::GenericEventBuilder, + task::PackageTaskEventBuilder, +}; +use turborepo_ui::{ + ColorSelector, + OutputClient, + OutputSink, + OutputWriter, + PrefixedUI, + UI, + tui::{self, AppSender, TuiTask}, +}; +use which::which; + +use crate::{ + cli::EnvMode, + engine::{Engine, ExecutionOptions, StopExecution}, + opts::RunOpts, + process::{ChildExit, Command, ProcessManager}, + run::{ + CacheOutput, + RunCache, + TaskCache, + global_hash::GlobalHashableInputs, + summary::{ + self, + GlobalHashSummary, + RunTracker, + SpacesTaskClient, + SpacesTaskInformation, + TaskExecutionSummary, + TaskTracker, + }, + task_access::TaskAccess, + task_id::TaskId, + }, + task_hash::{self, PackageInputsHashes, TaskHashTracker, TaskHashTrackerState, TaskHasher}, +}; + +// This holds the whole world +pub struct Visitor<'a> { + color_cache:ColorSelector, + dry:bool, + global_env:EnvironmentVariableMap, + global_env_mode:EnvMode, + manager:ProcessManager, + run_opts:&'a RunOpts, + package_graph:Arc, + repo_root:&'a AbsoluteSystemPath, + run_cache:Arc, + run_tracker:RunTracker, + task_access:&'a TaskAccess, + sink:OutputSink, + task_hasher:TaskHasher<'a>, + ui:UI, + experimental_ui_sender:Option, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("cannot find package {package_name} for task {task_id}")] + MissingPackage { package_name:PackageName, task_id:TaskId<'static> }, + #[error("root task {task_name} ({command}) looks like it invokes turbo and might cause a loop")] + RecursiveTurbo { task_name:String, command:String }, + #[error("Could not find definition for task")] + MissingDefinition, + #[error("error while executing engine: {0}")] + Engine(#[from] crate::engine::ExecuteError), + #[error(transparent)] + TaskHash(#[from] task_hash::Error), + #[error(transparent)] + RunSummary(#[from] summary::Error), + #[error("internal errors encountered: {0}")] + InternalErrors(String), +} + +impl<'a> Visitor<'a> { + // Disabling this lint until we stop adding state to the visitor. + // Once we have the full picture we will go about grouping these pieces of data + // together + #[allow(clippy::too_many_arguments)] + pub fn new( + package_graph:Arc, + run_cache:Arc, + run_tracker:RunTracker, + task_access:&'a TaskAccess, + run_opts:&'a RunOpts, + package_inputs_hashes:PackageInputsHashes, + env_at_execution_start:&'a EnvironmentVariableMap, + global_hash:&'a str, + global_env_mode:EnvMode, + ui:UI, + manager:ProcessManager, + repo_root:&'a AbsoluteSystemPath, + global_env:EnvironmentVariableMap, + experimental_ui_sender:Option, + ) -> Self { + let task_hasher = + TaskHasher::new(package_inputs_hashes, run_opts, env_at_execution_start, global_hash); + + let sink = Self::sink(run_opts); + let color_cache = ColorSelector::default(); + + Self { + color_cache, + dry:false, + global_env_mode, + manager, + run_opts, + package_graph, + repo_root, + run_cache, + run_tracker, + task_access, + sink, + task_hasher, + ui, + global_env, + experimental_ui_sender, + } + } + + #[tracing::instrument(skip_all)] + pub async fn visit( + &self, + engine:Arc, + telemetry:&GenericEventBuilder, + ) -> Result, Error> { + let concurrency = self.run_opts.concurrency as usize; + let (node_sender, mut node_stream) = mpsc::channel(concurrency); + + let engine_handle = { + let engine = engine.clone(); + tokio::spawn(engine.execute(ExecutionOptions::new(false, concurrency), node_sender)) + }; + let mut tasks = FuturesUnordered::new(); + let errors = Arc::new(Mutex::new(Vec::new())); + let span = Span::current(); + + let factory = ExecContextFactory::new(self, errors.clone(), self.manager.clone(), &engine); + + while let Some(message) = node_stream.recv().await { + let span = tracing::debug_span!(parent: &span, "queue_task", task = %message.info); + let _enter = span.enter(); + let crate::engine::Message { info, callback } = message; + let package_name = PackageName::from(info.package()); + + let workspace_info = + self.package_graph.package_info(&package_name).ok_or_else(|| { + Error::MissingPackage { + package_name:package_name.clone(), + task_id:info.clone(), + } + })?; + + let package_task_event = + PackageTaskEventBuilder::new(info.package(), info.task()).with_parent(telemetry); + let command = workspace_info.package_json.scripts.get(info.task()).cloned(); + + match command { + Some(cmd) if info.package() == ROOT_PKG_NAME && turbo_regex().is_match(&cmd) => { + package_task_event.track_error(TrackedErrors::RecursiveError); + return Err(Error::RecursiveTurbo { + task_name:info.to_string(), + command:cmd.to_string(), + }); + }, + _ => (), + } + + let task_definition = engine.task_definition(&info).ok_or(Error::MissingDefinition)?; + + let task_env_mode = self.global_env_mode; + package_task_event.track_env_mode(&task_env_mode.to_string()); + + let dependency_set = engine.dependencies(&info).ok_or(Error::MissingDefinition)?; + + let task_hash_telemetry = package_task_event.child(); + let task_hash = self.task_hasher.calculate_task_hash( + &info, + task_definition, + task_env_mode, + workspace_info, + dependency_set, + task_hash_telemetry, + )?; + + debug!("task {} hash is {}", info, task_hash); + // We do this calculation earlier than we do in Go due to the `task_hasher` + // being !Send. In the future we can look at doing this right before + // task execution instead. + let execution_env = + self.task_hasher.env(&info, task_env_mode, task_definition, &self.global_env)?; + + let task_cache = self.run_cache.task_cache( + task_definition, + workspace_info, + info.clone(), + &task_hash, + ); + + // Drop to avoid holding the span across an await + drop(_enter); + + // here is where we do the logic split + match self.dry { + true => { + let dry_run_exec_context = + factory.dry_run_exec_context(info.clone(), task_cache); + let tracker = self.run_tracker.track_task(info.into_owned()); + tasks.push(tokio::spawn(async move { + dry_run_exec_context.execute_dry_run(tracker).await + })); + }, + false => { + // TODO(gsoltis): if/when we fix https://github.com/vercel/turbo/issues/937 + // the following block should never get hit. In the meantime, keep it after + // hashing so that downstream tasks can count on the hash existing + // + // bail if the script doesn't exist or is empty + if command.map_or(true, |s| s.is_empty()) { + continue; + } + + let workspace_directory = self.repo_root.resolve(workspace_info.package_path()); + + let takes_input = task_definition.interactive || task_definition.persistent; + let mut exec_context = factory.exec_context( + info.clone(), + task_hash, + task_cache, + workspace_directory, + execution_env, + takes_input, + self.task_access.clone(), + ); + + let vendor_behavior = + Vendor::infer().and_then(|vendor| vendor.behavior.as_ref()); + + let output_client = if let Some(handle) = &self.experimental_ui_sender { + TaskOutput::UI(handle.task(info.to_string())) + } else { + TaskOutput::Direct(self.output_client(&info, vendor_behavior)) + }; + let tracker = self.run_tracker.track_task(info.clone().into_owned()); + let spaces_client = self.run_tracker.spaces_task_client(); + let parent_span = Span::current(); + let execution_telemetry = package_task_event.child(); + + tasks.push(tokio::spawn(async move { + exec_context + .execute( + parent_span.id(), + tracker, + output_client, + callback, + spaces_client, + &execution_telemetry, + ) + .await + })); + }, + } + } + + // Wait for the engine task to finish and for all of our tasks to finish + engine_handle.await.expect("engine execution panicked")?; + // This will poll the futures until they are all completed + let mut internal_errors = Vec::new(); + while let Some(result) = tasks.next().await { + if let Err(e) = result.unwrap_or_else(|e| panic!("task executor panicked: {e}")) { + internal_errors.push(e); + } + } + drop(factory); + + if !internal_errors.is_empty() { + return Err(Error::InternalErrors( + internal_errors.into_iter().map(|e| e.to_string()).join(","), + )); + } + + // Write out the traced-config.json file if we have one + self.task_access.save().await; + + let errors = Arc::into_inner(errors) + .expect("only one strong reference to errors should remain") + .into_inner() + .expect("mutex poisoned"); + + Ok(errors) + } + + /// Finishes visiting the tasks, creates the run summary, and either + /// prints, saves, or sends it to spaces. + + #[allow(clippy::too_many_arguments)] + #[tracing::instrument(skip( + self, + packages, + global_hash_inputs, + engine, + env_at_execution_start + ))] + pub(crate) async fn finish( + self, + exit_code:i32, + packages:&HashSet, + global_hash_inputs:GlobalHashableInputs<'_>, + engine:&Engine, + env_at_execution_start:&EnvironmentVariableMap, + pkg_inference_root:Option<&AnchoredSystemPath>, + has_experimental_ui:bool, + ) -> Result<(), Error> { + let Self { package_graph, ui, run_opts, repo_root, global_env_mode, task_hasher, .. } = + self; + + let global_hash_summary = GlobalHashSummary::try_from(global_hash_inputs)?; + + Ok(self + .run_tracker + .finish( + exit_code, + &package_graph, + ui, + repo_root, + pkg_inference_root, + run_opts, + packages, + global_hash_summary, + global_env_mode, + engine, + task_hasher.task_hash_tracker(), + env_at_execution_start, + has_experimental_ui, + ) + .await?) + } + + fn sink(run_opts:&RunOpts) -> OutputSink { + let (out, err) = if run_opts.should_redirect_stderr_to_stdout() { + (std::io::stdout().into(), std::io::stdout().into()) + } else { + (std::io::stdout().into(), std::io::stderr().into()) + }; + OutputSink::new(out, err) + } + + fn output_client( + &self, + task_id:&TaskId, + vendor_behavior:Option<&VendorBehavior>, + ) -> OutputClient { + let behavior = match self.run_opts.log_order { + crate::opts::ResolvedLogOrder::Stream if self.run_tracker.spaces_enabled() => { + turborepo_ui::OutputClientBehavior::InMemoryBuffer + }, + crate::opts::ResolvedLogOrder::Stream => { + turborepo_ui::OutputClientBehavior::Passthrough + }, + crate::opts::ResolvedLogOrder::Grouped => turborepo_ui::OutputClientBehavior::Grouped, + }; + + let mut logger = self.sink.logger(behavior); + if let Some(vendor_behavior) = vendor_behavior { + let group_name = if self.run_opts.single_package { + task_id.task().to_string() + } else { + format!("{}:{}", task_id.package(), task_id.task()) + }; + + let header_factory = (vendor_behavior.group_prefix)(group_name.to_owned()); + let footer_factory = (vendor_behavior.group_suffix)(group_name.to_owned()); + + logger.with_header_footer(Some(header_factory), Some(footer_factory)); + + let (error_header, error_footer) = ( + vendor_behavior.error_group_prefix.map(|f| f(group_name.to_owned())), + vendor_behavior.error_group_suffix.map(|f| f(group_name.to_owned())), + ); + logger.with_error_header_footer(error_header, error_footer); + } + logger + } + + fn prefix<'b>(&self, task_id:&'b TaskId) -> Cow<'b, str> { + match self.run_opts.log_prefix { + crate::opts::ResolvedLogPrefix::Task if self.run_opts.single_package => { + task_id.task().into() + }, + crate::opts::ResolvedLogPrefix::Task => { + format!("{}:{}", task_id.package(), task_id.task()).into() + }, + crate::opts::ResolvedLogPrefix::None => "".into(), + } + } + + // Task ID as displayed in error messages + fn display_task_id(&self, task_id:&TaskId) -> String { + match self.run_opts.single_package { + true => task_id.task().to_string(), + false => task_id.to_string(), + } + } + + fn prefixed_ui( + ui:UI, + is_github_actions:bool, + stdout:W, + stderr:W, + prefix:StyledObject, + ) -> PrefixedUI { + let mut prefixed_ui = PrefixedUI::new(ui, stdout, stderr) + .with_output_prefix(prefix.clone()) + // TODO: we can probably come up with a more ergonomic way to achieve this + .with_error_prefix( + Style::new().apply_to(format!("{}ERROR: ", ui.apply(prefix.clone()))), + ) + .with_warn_prefix(prefix); + if is_github_actions { + prefixed_ui = prefixed_ui + .with_error_prefix(Style::new().apply_to("[ERROR] ".to_string())) + .with_warn_prefix(Style::new().apply_to("[WARN] ".to_string())); + } + prefixed_ui + } + + /// Only used for the hashing comparison between Rust and Go. After port, + /// should delete + pub fn into_task_hash_tracker(self) -> TaskHashTrackerState { + self.task_hasher.into_task_hash_tracker_state() + } + + pub fn dry_run(&mut self) { + self.dry = true; + // No need to start a TUI on dry run + self.experimental_ui_sender = None; + } +} + +// A tiny enum that allows us to use the same type for stdout and stderr without +// the use of Box +enum StdWriter { + Out(std::io::Stdout), + Err(std::io::Stderr), + Null(std::io::Sink), +} + +impl StdWriter { + fn writer(&mut self) -> &mut dyn std::io::Write { + match self { + StdWriter::Out(out) => out, + StdWriter::Err(err) => err, + StdWriter::Null(null) => null, + } + } +} + +impl From for StdWriter { + fn from(value:std::io::Stdout) -> Self { Self::Out(value) } +} + +impl From for StdWriter { + fn from(value:std::io::Stderr) -> Self { Self::Err(value) } +} + +impl From for StdWriter { + fn from(value:std::io::Sink) -> Self { Self::Null(value) } +} + +impl std::io::Write for StdWriter { + fn write(&mut self, buf:&[u8]) -> std::io::Result { self.writer().write(buf) } + + fn flush(&mut self) -> std::io::Result<()> { self.writer().flush() } +} + +/// Small wrapper over our two output types that defines a shared interface for +/// interacting with them. +enum TaskOutput { + Direct(OutputClient), + UI(tui::TuiTask), +} + +fn turbo_regex() -> &'static Regex { + static RE:OnceLock = OnceLock::new(); + RE.get_or_init(|| Regex::new(r"(?:^|\s)turbo(?:$|\s)").unwrap()) +} + +// Error that comes from the execution of the task +#[derive(Debug, thiserror::Error, Clone)] +#[error("{task_id}: {cause}")] +pub struct TaskError { + task_id:String, + cause:TaskErrorCause, +} + +#[derive(Debug, thiserror::Error, Clone)] +enum TaskErrorCause { + #[error("unable to spawn child process: {msg}")] + // We eagerly serialize this in order to allow us to implement clone + Spawn { msg:String }, + #[error("command {command} exited ({exit_code})")] + Exit { command:String, exit_code:i32 }, + #[error("turbo has internal error processing task")] + Internal, +} + +#[derive(Debug, thiserror::Error)] +pub enum InternalError { + #[error(transparent)] + Io(#[from] std::io::Error), + #[error("unable to determine why task exited")] + UnknownChildExit, + #[error("unable to find package manager binary: {0}")] + Which(#[from] which::Error), + #[error("external process killed a task")] + ExternalKill, + #[error("error writing logs: {0}")] + Logs(#[from] crate::run::CacheError), +} + +impl TaskError { + pub fn exit_code(&self) -> Option { + match self.cause { + TaskErrorCause::Exit { exit_code, .. } => Some(exit_code), + _ => None, + } + } + + fn from_spawn(task_id:String, err:std::io::Error) -> Self { + Self { task_id, cause:TaskErrorCause::Spawn { msg:err.to_string() } } + } + + fn from_execution(task_id:String, command:String, exit_code:i32) -> Self { + Self { task_id, cause:TaskErrorCause::Exit { command, exit_code } } + } +} + +impl TaskErrorCause { + fn from_spawn(err:std::io::Error) -> Self { TaskErrorCause::Spawn { msg:err.to_string() } } + + fn from_execution(command:String, exit_code:i32) -> Self { + TaskErrorCause::Exit { command, exit_code } + } +} + +struct ExecContextFactory<'a> { + visitor:&'a Visitor<'a>, + errors:Arc>>, + manager:ProcessManager, + engine:&'a Arc, +} + +impl<'a> ExecContextFactory<'a> { + pub fn new( + visitor:&'a Visitor, + errors:Arc>>, + manager:ProcessManager, + engine:&'a Arc, + ) -> Self { + Self { visitor, errors, manager, engine } + } + + #[allow(clippy::too_many_arguments)] + pub fn exec_context( + &self, + task_id:TaskId<'static>, + task_hash:String, + task_cache:TaskCache, + workspace_directory:AbsoluteSystemPathBuf, + execution_env:EnvironmentVariableMap, + takes_input:bool, + task_access:TaskAccess, + ) -> ExecContext { + let task_id_for_display = self.visitor.display_task_id(&task_id); + let pass_through_args = self.visitor.run_opts.args_for_task(&task_id); + ExecContext { + engine:self.engine.clone(), + ui:self.visitor.ui, + experimental_ui:self.visitor.experimental_ui_sender.is_some(), + is_github_actions:self.visitor.run_opts.is_github_actions, + pretty_prefix:self + .visitor + .color_cache + .prefix_with_color(&task_hash, &self.visitor.prefix(&task_id)), + task_id, + task_id_for_display, + task_cache, + hash_tracker:self.visitor.task_hasher.task_hash_tracker(), + package_manager:*self.visitor.package_graph.package_manager(), + workspace_directory, + manager:self.manager.clone(), + task_hash, + execution_env, + continue_on_error:self.visitor.run_opts.continue_on_error, + pass_through_args, + errors:self.errors.clone(), + takes_input, + task_access, + } + } + + pub fn dry_run_exec_context( + &self, + task_id:TaskId<'static>, + task_cache:TaskCache, + ) -> DryRunExecContext { + DryRunExecContext { + task_id, + task_cache, + hash_tracker:self.visitor.task_hasher.task_hash_tracker(), + } + } +} + +struct ExecContext { + engine:Arc, + ui:UI, + experimental_ui:bool, + is_github_actions:bool, + pretty_prefix:StyledObject, + task_id:TaskId<'static>, + task_id_for_display:String, + task_cache:TaskCache, + hash_tracker:TaskHashTracker, + package_manager:PackageManager, + workspace_directory:AbsoluteSystemPathBuf, + manager:ProcessManager, + task_hash:String, + execution_env:EnvironmentVariableMap, + continue_on_error:bool, + pass_through_args:Option>, + errors:Arc>>, + takes_input:bool, + task_access:TaskAccess, +} + +enum ExecOutcome { + // All operations during execution succeeded + Success(SuccessOutcome), + // An error with the task execution + Task { exit_code:Option, message:String }, + // Task didn't execute normally due to a shutdown being initiated by another task + Shutdown, +} + +enum SuccessOutcome { + CacheHit, + Run, +} + +impl ExecContext { + pub async fn execute_dry_run(&mut self, tracker:TaskTracker<()>) { + if let Ok(Some(status)) = self.task_cache.exists().await { + self.hash_tracker.insert_cache_status(self.task_id.clone(), status); + } + + tracker.dry_run().await; + } + + pub async fn execute( + &mut self, + parent_span_id:Option, + tracker:TaskTracker<()>, + output_client:TaskOutput, + callback:oneshot::Sender>, + spaces_client:Option, + telemetry:&PackageTaskEventBuilder, + ) -> Result<(), InternalError> { + let tracker = tracker.start().await; + let span = tracing::debug_span!("execute_task", task = %self.task_id.task()); + span.follows_from(parent_span_id); + let mut result = self.execute_inner(&output_client, telemetry).instrument(span).await; + + // If the task resulted in an error, do not group in order to better highlight + // the error. + let is_error = matches!(result, Ok(ExecOutcome::Task { .. })); + let logs = match output_client.finish(is_error) { + Ok(logs) => logs, + Err(e) => { + telemetry.track_error(TrackedErrors::DaemonFailedToMarkOutputsAsCached); + error!("unable to flush output client: {e}"); + result = Err(InternalError::Io(e)); + None + }, + }; + + match result { + Ok(ExecOutcome::Success(outcome)) => { + let task_summary = match outcome { + SuccessOutcome::CacheHit => tracker.cached().await, + SuccessOutcome::Run => tracker.build_succeeded(0).await, + }; + callback.send(Ok(())).ok(); + if let Some(client) = spaces_client { + let logs = logs.expect("spaces enabled logs should be collected"); + let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); + client.finish_task(info).await.ok(); + } + }, + Ok(ExecOutcome::Task { exit_code, message }) => { + let task_summary = tracker.build_failed(exit_code, message).await; + callback + .send(match self.continue_on_error { + true => Ok(()), + false => Err(StopExecution), + }) + .ok(); + + match (spaces_client, self.continue_on_error) { + // Nothing to do + (None, true) => (), + // Shut down manager + (None, false) => self.manager.stop().await, + // Send task + (Some(client), true) => { + let logs = logs.expect("spaced enabled logs should be collected"); + let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); + client.finish_task(info).await.ok(); + }, + // Send task and shut down manager + (Some(client), false) => { + let logs = logs.unwrap_or_default(); + let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); + // Ignore spaces result as that indicates handler is shut down and we are + // unable to send information to spaces + let (_spaces_result, _) = + tokio::join!(client.finish_task(info), self.manager.stop()); + }, + } + }, + Ok(ExecOutcome::Shutdown) => { + tracker.cancel(); + callback.send(Err(StopExecution)).ok(); + // Probably overkill here, but we should make sure the process manager is + // stopped if we think we're shutting down. + self.manager.stop().await; + }, + Err(e) => { + tracker.cancel(); + callback.send(Err(StopExecution)).ok(); + self.manager.stop().await; + return Err(e); + }, + } + + Ok(()) + } + + fn prefixed_ui<'a, W:Write>( + &self, + output_client:&'a TaskOutput, + ) -> TaskCacheOutput> { + match output_client { + TaskOutput::Direct(client) => { + TaskCacheOutput::Direct(Visitor::prefixed_ui( + self.ui, + self.is_github_actions, + client.stdout(), + client.stderr(), + self.pretty_prefix.clone(), + )) + }, + TaskOutput::UI(task) => TaskCacheOutput::UI(task.clone()), + } + } + + async fn execute_inner( + &mut self, + output_client:&TaskOutput, + telemetry:&PackageTaskEventBuilder, + ) -> Result { + let task_start = Instant::now(); + let mut prefixed_ui = self.prefixed_ui(output_client); + + if self.experimental_ui { + if let TaskOutput::UI(task) = output_client { + task.start(); + } + } + + match self.task_cache.restore_outputs(&mut prefixed_ui, telemetry).await { + Ok(Some(status)) => { + // we need to set expanded outputs + self.hash_tracker.insert_expanded_outputs( + self.task_id.clone(), + self.task_cache.expanded_outputs().to_vec(), + ); + self.hash_tracker.insert_cache_status(self.task_id.clone(), status); + return Ok(ExecOutcome::Success(SuccessOutcome::CacheHit)); + }, + Ok(None) => (), + Err(e) => { + telemetry.track_error(TrackedErrors::ErrorFetchingFromCache); + prefixed_ui.error(&format!("error fetching from cache: {e}")); + }, + } + + let package_manager_binary = which(self.package_manager.command())?; + + let mut cmd = Command::new(package_manager_binary); + let mut args = vec!["run".to_string(), self.task_id.task().to_string()]; + if let Some(pass_through_args) = &self.pass_through_args { + args.extend( + self.package_manager + .arg_separator(pass_through_args.as_slice()) + .map(|s| s.to_string()), + ); + args.extend(pass_through_args.iter().cloned()); + } + cmd.args(args); + cmd.current_dir(self.workspace_directory.clone()); + + // We clear the env before populating it with variables we expect + cmd.env_clear(); + cmd.envs(self.execution_env.iter()); + // Always last to make sure it overwrites any user configured env var. + cmd.env("TURBO_HASH", &self.task_hash); + // enable task access tracing + + // set the trace file env var - frameworks that support this can use it to + // write out a trace file that we will use to automatically cache the task + if self.task_access.is_enabled() { + let (task_access_trace_key, trace_file) = self.task_access.get_env_var(&self.task_hash); + cmd.env(task_access_trace_key, trace_file.to_string()); + } + + cmd.open_stdin(); + + let mut process = match self.manager.spawn(cmd, Duration::from_millis(500)) { + Some(Ok(child)) => child, + // Turbo was unable to spawn a process + Some(Err(e)) => { + // Note: we actually failed to spawn, but this matches the Go output + prefixed_ui.error(&format!("command finished with error: {e}")); + let error_string = e.to_string(); + self.errors + .lock() + .expect("lock poisoned") + .push(TaskError::from_spawn(self.task_id_for_display.clone(), e)); + return Ok(ExecOutcome::Task { exit_code:None, message:error_string }); + }, + // Turbo is shutting down + None => { + return Ok(ExecOutcome::Shutdown); + }, + }; + + if self.experimental_ui && self.takes_input { + if let TaskOutput::UI(task) = output_client { + if let Some(stdin) = process.stdin() { + task.set_stdin(stdin); + } + } + } + + let mut stdout_writer = + self.task_cache.output_writer(prefixed_ui.task_writer()).map_err(|e| { + telemetry.track_error(TrackedErrors::FailedToCaptureOutputs); + e + })?; + + let exit_status = match process.wait_with_piped_outputs(&mut stdout_writer).await { + Ok(Some(exit_status)) => exit_status, + Err(e) => { + telemetry.track_error(TrackedErrors::FailedToPipeOutputs); + return Err(e.into()); + }, + Ok(None) => { + // TODO: how can this happen? we only update the + // exit status with Some and it is only initialized with + // None. Is it still running? + telemetry.track_error(TrackedErrors::UnknownChildExit); + error!("unable to determine why child exited"); + return Err(InternalError::UnknownChildExit); + }, + }; + let task_duration = task_start.elapsed(); + + match exit_status { + ChildExit::Finished(Some(0)) => { + // Attempt to flush stdout_writer and log any errors encountered + if let Err(e) = stdout_writer.flush() { + error!("{e}"); + } else if self + .task_access + .can_cache(&self.task_hash, &self.task_id_for_display) + .unwrap_or(true) + { + if let Err(e) = self.task_cache.save_outputs(task_duration, telemetry).await { + error!("error caching output: {e}"); + return Err(e.into()); + } else { + // If no errors, update hash tracker with expanded outputs + self.hash_tracker.insert_expanded_outputs( + self.task_id.clone(), + self.task_cache.expanded_outputs().to_vec(), + ); + } + } + + // Return success outcome + Ok(ExecOutcome::Success(SuccessOutcome::Run)) + }, + ChildExit::Finished(Some(code)) => { + // If there was an error, flush the buffered output + if let Err(e) = stdout_writer.flush() { + error!("error flushing logs: {e}"); + } + if let Err(e) = self.task_cache.on_error(&mut prefixed_ui) { + error!("error reading logs: {e}"); + } + let error = TaskErrorCause::from_execution(process.label().to_string(), code); + let message = error.to_string(); + if self.continue_on_error { + prefixed_ui.warn("command finished with error, but continuing..."); + } else { + prefixed_ui.error(&format!("command finished with error: {error}")); + } + self.errors + .lock() + .expect("lock poisoned") + .push(TaskError { task_id:self.task_id_for_display.clone(), cause:error }); + Ok(ExecOutcome::Task { exit_code:Some(code), message }) + }, + // The child exited in a way where we can't figure out how it finished so we assume it + // failed. + ChildExit::Finished(None) | ChildExit::Failed => Err(InternalError::UnknownChildExit), + // Something else killed the child + ChildExit::KilledExternal => Err(InternalError::ExternalKill), + // The child was killed by turbo indicating a shutdown + ChildExit::Killed => Ok(ExecOutcome::Shutdown), + } + } + + fn spaces_task_info( + &self, + task_id:TaskId<'static>, + execution_summary:TaskExecutionSummary, + logs:Vec, + ) -> SpacesTaskInformation { + let dependencies = self.engine.dependencies(&task_id); + let dependents = self.engine.dependents(&task_id); + let cache_status = self.hash_tracker.cache_status(&task_id); + SpacesTaskInformation { + task_id, + execution_summary, + logs, + hash:self.task_hash.clone(), + cache_status, + dependencies, + dependents, + } + } +} + +struct DryRunExecContext { + task_id:TaskId<'static>, + task_cache:TaskCache, + hash_tracker:TaskHashTracker, +} + +impl DryRunExecContext { + pub async fn execute_dry_run(&self, tracker:TaskTracker<()>) -> Result<(), InternalError> { + // may also need to do framework & command stuff? + if let Ok(Some(status)) = self.task_cache.exists().await { + self.hash_tracker.insert_cache_status(self.task_id.clone(), status); + } + tracker.dry_run().await; + Ok(()) + } +} + +/// Struct for displaying information about task's cache +enum TaskCacheOutput { + Direct(PrefixedUI), + UI(TuiTask), +} + +impl TaskCacheOutput { + fn task_writer(&mut self) -> Either, TuiTask> { + match self { + TaskCacheOutput::Direct(prefixed) => Either::Left(prefixed.output_prefixed_writer()), + TaskCacheOutput::UI(task) => Either::Right(task.clone()), + } + } + + fn warn(&mut self, message:impl std::fmt::Display) { + match self { + TaskCacheOutput::Direct(prefixed) => prefixed.warn(message), + TaskCacheOutput::UI(task) => { + let _ = write!(task, "\r\n{message}\r\n"); + }, + } + } +} + +impl CacheOutput for TaskCacheOutput { + fn status(&mut self, message:&str) { + match self { + TaskCacheOutput::Direct(direct) => direct.output(message), + TaskCacheOutput::UI(task) => task.status(message), + } + } + + fn error(&mut self, message:&str) { + match self { + TaskCacheOutput::Direct(prefixed) => prefixed.error(message), + TaskCacheOutput::UI(task) => { + let _ = write!(task, "{message}\r\n"); + }, + } + } + + fn replay_logs(&mut self, log_file:&AbsoluteSystemPath) -> Result<(), turborepo_ui::Error> { + match self { + TaskCacheOutput::Direct(direct) => { + let writer = direct.output_prefixed_writer(); + turborepo_ui::replay_logs(writer, log_file) + }, + TaskCacheOutput::UI(task) => turborepo_ui::replay_logs(task, log_file), + } + } +} + +/// Struct for displaying information about task +impl TaskOutput { + pub fn finish(self, use_error:bool) -> std::io::Result>> { + match self { + TaskOutput::Direct(client) => client.finish(use_error), + TaskOutput::UI(client) if use_error => Ok(Some(client.failed())), + TaskOutput::UI(client) => Ok(Some(client.succeeded())), + } + } + + pub fn stdout(&self) -> Either, TuiTask> { + match self { + TaskOutput::Direct(client) => Either::Left(client.stdout()), + TaskOutput::UI(client) => Either::Right(client.clone()), + } + } + + pub fn stderr(&self) -> Either, TuiTask> { + match self { + TaskOutput::Direct(client) => Either::Left(client.stderr()), + TaskOutput::UI(client) => Either::Right(client.clone()), + } + } + + pub fn task_logs(&self) -> Either, TuiTask> { + match self { + TaskOutput::Direct(client) => Either::Left(client.stdout()), + TaskOutput::UI(client) => Either::Right(client.clone()), + } + } +} diff --git a/crates/turborepo-lib/src/task_graph/visitor/command.rs b/crates/turborepo-lib/Source/task_graph/visitor/command.rs similarity index 100% rename from crates/turborepo-lib/src/task_graph/visitor/command.rs rename to crates/turborepo-lib/Source/task_graph/visitor/command.rs diff --git a/crates/turborepo-lib/Source/task_graph/visitor/error.rs b/crates/turborepo-lib/Source/task_graph/visitor/error.rs new file mode 100644 index 0000000000000..75d1f90193d0a --- /dev/null +++ b/crates/turborepo-lib/Source/task_graph/visitor/error.rs @@ -0,0 +1,89 @@ +// Warning that comes from the execution of the task +#[derive(Debug, Clone)] +pub struct TaskWarning { + task_id:String, + missing_platform_env:Vec, +} + +// Error that comes from the execution of the task +#[derive(Debug, thiserror::Error, Clone)] +#[error("{task_id}: {cause}")] +pub struct TaskError { + task_id:String, + cause:TaskErrorCause, +} + +#[derive(Debug, thiserror::Error, Clone)] +pub enum TaskErrorCause { + #[error("unable to spawn child process: {msg}")] + // We eagerly serialize this in order to allow us to implement clone + Spawn { msg:String }, + #[error("command {command} exited ({exit_code})")] + Exit { command:String, exit_code:i32 }, + #[error("turbo has internal error processing task")] + Internal, +} + +impl TaskWarning { + /// Construct a new warning for a given task with the + /// Returns `None` if there are no missing platform environment variables + pub fn new(task_id:&str, missing_platform_env:Vec) -> Option { + if missing_platform_env.is_empty() { + return None; + } + Some(Self { task_id:task_id.to_owned(), missing_platform_env }) + } + + pub fn task_id(&self) -> &str { &self.task_id } + + /// All missing platform environment variables. + /// Guaranteed to have at least length 1 due to constructor validation. + pub fn missing_platform_env(&self) -> &[String] { &self.missing_platform_env } +} + +impl TaskError { + pub fn new(task_id:String, cause:TaskErrorCause) -> Self { Self { task_id, cause } } + + pub fn exit_code(&self) -> Option { + match self.cause { + TaskErrorCause::Exit { exit_code, .. } => Some(exit_code), + _ => None, + } + } + + pub fn from_spawn(task_id:String, err:std::io::Error) -> Self { + Self { task_id, cause:TaskErrorCause::Spawn { msg:err.to_string() } } + } + + pub fn from_execution(task_id:String, command:String, exit_code:i32) -> Self { + Self { task_id, cause:TaskErrorCause::Exit { command, exit_code } } + } +} + +impl TaskErrorCause { + pub fn from_spawn(err:std::io::Error) -> Self { TaskErrorCause::Spawn { msg:err.to_string() } } + + pub fn from_execution(command:String, exit_code:i32) -> Self { + TaskErrorCause::Exit { command, exit_code } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_warning_no_vars() { + let no_warning = TaskWarning::new("a-task", vec![]); + assert!(no_warning.is_none()); + } + + #[test] + fn test_warning_some_var() { + let warning = TaskWarning::new("a-task", vec!["MY_VAR".into()]); + assert!(warning.is_some()); + let warning = warning.unwrap(); + assert_eq!(warning.task_id(), "a-task"); + assert_eq!(warning.missing_platform_env(), &["MY_VAR".to_owned()]); + } +} diff --git a/crates/turborepo-lib/Source/task_graph/visitor/exec.rs b/crates/turborepo-lib/Source/task_graph/visitor/exec.rs new file mode 100644 index 0000000000000..eb40638df8209 --- /dev/null +++ b/crates/turborepo-lib/Source/task_graph/visitor/exec.rs @@ -0,0 +1,508 @@ +use std::{ + io::Write, + sync::{Arc, Mutex}, + time::{Duration, Instant}, +}; + +use console::StyledObject; +use tokio::sync::oneshot; +use tracing::{Instrument, error}; +use turborepo_env::{EnvironmentVariableMap, platform::PlatformEnv}; +use turborepo_repository::package_manager::PackageManager; +use turborepo_telemetry::events::{TrackedErrors, task::PackageTaskEventBuilder}; +use turborepo_ui::{ColorConfig, OutputWriter}; + +use super::{ + TaskOutput, + Visitor, + command::{CommandFactory, MicroFrontendProxyProvider, PackageGraphCommandProvider}, + error::{TaskError, TaskErrorCause, TaskWarning}, + output::TaskCacheOutput, +}; +use crate::{ + config::UIMode, + engine::{Engine, StopExecution}, + process::{ChildExit, Command, ProcessManager}, + run::{ + CacheOutput, + TaskCache, + summary::{SpacesTaskClient, SpacesTaskInformation, TaskExecutionSummary, TaskTracker}, + task_access::TaskAccess, + task_id::TaskId, + }, + task_hash::TaskHashTracker, +}; + +pub struct ExecContextFactory<'a> { + visitor:&'a Visitor<'a>, + errors:Arc>>, + manager:ProcessManager, + engine:&'a Arc, + command_factory:CommandFactory<'a>, +} + +impl<'a> ExecContextFactory<'a> { + pub fn new( + visitor:&'a Visitor<'a>, + errors:Arc>>, + manager:ProcessManager, + engine:&'a Arc, + ) -> Result { + let pkg_graph_provider = PackageGraphCommandProvider::new( + visitor.repo_root, + &visitor.package_graph, + visitor.run_opts.task_args(), + visitor.micro_frontends_configs, + ); + let mut command_factory = CommandFactory::new(); + if let Some(micro_frontends_configs) = visitor.micro_frontends_configs { + command_factory.add_provider(MicroFrontendProxyProvider::new( + visitor.repo_root, + &visitor.package_graph, + engine, + micro_frontends_configs, + )); + } + command_factory.add_provider(pkg_graph_provider); + + Ok(Self { visitor, errors, manager, engine, command_factory }) + } + + #[allow(clippy::too_many_arguments)] + pub fn exec_context( + &self, + task_id:TaskId<'static>, + task_hash:String, + task_cache:TaskCache, + mut execution_env:EnvironmentVariableMap, + takes_input:bool, + task_access:TaskAccess, + ) -> Result, super::Error> { + let task_id_for_display = self.visitor.display_task_id(&task_id); + let task_id_string = &task_id.to_string(); + self.populate_env(&mut execution_env, &task_hash, &task_access); + let Some(cmd) = self.command_factory.command(&task_id, execution_env.clone())? else { + return Ok(None); + }; + Ok(Some(ExecContext { + engine:self.engine.clone(), + ui_mode:self.visitor.run_opts.ui_mode, + color_config:self.visitor.color_config, + is_github_actions:self.visitor.run_opts.is_github_actions, + pretty_prefix:self + .visitor + .color_cache + .prefix_with_color(task_id_string, &self.visitor.prefix(&task_id)), + task_id, + task_id_for_display, + task_cache, + hash_tracker:self.visitor.task_hasher.task_hash_tracker(), + package_manager:self.visitor.package_graph.package_manager().clone(), + manager:self.manager.clone(), + task_hash, + execution_env, + continue_on_error:self.visitor.run_opts.continue_on_error, + errors:self.errors.clone(), + warnings:self.visitor.warnings.clone(), + takes_input, + task_access, + cmd, + platform_env:PlatformEnv::new(), + })) + } + + pub fn dry_run_exec_context( + &self, + task_id:TaskId<'static>, + task_cache:TaskCache, + ) -> DryRunExecContext { + DryRunExecContext { + task_id, + task_cache, + hash_tracker:self.visitor.task_hasher.task_hash_tracker(), + } + } + + // Add any env vars that `turbo` provides to the task environment + fn populate_env( + &self, + execution_env:&mut EnvironmentVariableMap, + task_hash:&str, + task_access:&TaskAccess, + ) { + // Always last to make sure it overwrites any user configured env var. + execution_env.insert("TURBO_HASH".to_owned(), task_hash.to_owned()); + + // Allow downstream tools to detect if the task is being ran with TUI + if self.visitor.run_opts.ui_mode.use_tui() { + execution_env.insert("TURBO_IS_TUI".to_owned(), "true".to_owned()); + } + + // enable task access tracing + // set the trace file env var - frameworks that support this can use it to + // write out a trace file that we will use to automatically cache the task + if task_access.is_enabled() { + let (task_access_trace_key, trace_file) = task_access.get_env_var(task_hash); + execution_env.insert(task_access_trace_key, trace_file.to_string()); + } + } +} + +pub struct ExecContext { + engine:Arc, + color_config:ColorConfig, + ui_mode:UIMode, + is_github_actions:bool, + pretty_prefix:StyledObject, + task_id:TaskId<'static>, + task_id_for_display:String, + task_cache:TaskCache, + hash_tracker:TaskHashTracker, + package_manager:PackageManager, + manager:ProcessManager, + task_hash:String, + execution_env:EnvironmentVariableMap, + continue_on_error:bool, + errors:Arc>>, + warnings:Arc>>, + takes_input:bool, + task_access:TaskAccess, + cmd:Command, + platform_env:PlatformEnv, +} + +enum ExecOutcome { + // All operations during execution succeeded + Success(SuccessOutcome), + // An error with the task execution + Task { exit_code:Option, message:String }, + // Task didn't execute normally due to a shutdown being initiated by another task + Shutdown, +} + +enum SuccessOutcome { + CacheHit, + Run, +} + +impl ExecContext { + pub async fn execute_dry_run(&mut self, tracker:TaskTracker<()>) { + if let Ok(Some(status)) = self.task_cache.exists().await { + self.hash_tracker.insert_cache_status(self.task_id.clone(), status); + } + + tracker.dry_run().await; + } + + pub async fn execute( + &mut self, + parent_span_id:Option, + tracker:TaskTracker<()>, + output_client:TaskOutput, + callback:oneshot::Sender>, + spaces_client:Option, + telemetry:&PackageTaskEventBuilder, + ) -> Result<(), InternalError> { + let tracker = tracker.start().await; + let span = tracing::debug_span!("execute_task", task = %self.task_id.task()); + span.follows_from(parent_span_id); + let mut result = self.execute_inner(&output_client, telemetry).instrument(span).await; + + // If the task resulted in an error, do not group in order to better highlight + // the error. + let is_error = matches!(result, Ok(ExecOutcome::Task { .. })); + let is_cache_hit = matches!(result, Ok(ExecOutcome::Success(SuccessOutcome::CacheHit))); + let logs = match output_client.finish(is_error, is_cache_hit) { + Ok(logs) => logs, + Err(e) => { + telemetry.track_error(TrackedErrors::DaemonFailedToMarkOutputsAsCached); + error!("unable to flush output client: {e}"); + result = Err(InternalError::Io(e)); + None + }, + }; + + match result { + Ok(ExecOutcome::Success(outcome)) => { + let task_summary = match outcome { + SuccessOutcome::CacheHit => tracker.cached().await, + SuccessOutcome::Run => tracker.build_succeeded(0).await, + }; + callback.send(Ok(())).ok(); + if let Some(client) = spaces_client { + let logs = logs.expect("spaces enabled logs should be collected"); + let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); + client.finish_task(info).await.ok(); + } + }, + Ok(ExecOutcome::Task { exit_code, message }) => { + let task_summary = tracker.build_failed(exit_code, message).await; + callback + .send(match self.continue_on_error { + true => Ok(()), + false => Err(StopExecution), + }) + .ok(); + + match (spaces_client, self.continue_on_error) { + // Nothing to do + (None, true) => (), + // Shut down manager + (None, false) => self.manager.stop().await, + // Send task + (Some(client), true) => { + let logs = logs.expect("spaced enabled logs should be collected"); + let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); + client.finish_task(info).await.ok(); + }, + // Send task and shut down manager + (Some(client), false) => { + let logs = logs.unwrap_or_default(); + let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); + // Ignore spaces result as that indicates handler is shut down and we are + // unable to send information to spaces + let (_spaces_result, _) = + tokio::join!(client.finish_task(info), self.manager.stop()); + }, + } + }, + Ok(ExecOutcome::Shutdown) => { + tracker.cancel(); + callback.send(Err(StopExecution)).ok(); + // Probably overkill here, but we should make sure the process manager is + // stopped if we think we're shutting down. + self.manager.stop().await; + }, + Err(e) => { + tracker.cancel(); + callback.send(Err(StopExecution)).ok(); + self.manager.stop().await; + return Err(e); + }, + } + + Ok(()) + } + + fn prefixed_ui<'a, W:Write>( + &self, + output_client:&'a TaskOutput, + ) -> TaskCacheOutput> { + match output_client { + TaskOutput::Direct(client) => { + TaskCacheOutput::Direct(Visitor::prefixed_ui( + self.color_config, + self.is_github_actions, + client.stdout(), + client.stderr(), + self.pretty_prefix.clone(), + )) + }, + TaskOutput::UI(task) => TaskCacheOutput::UI(task.clone()), + } + } + + async fn execute_inner( + &mut self, + output_client:&TaskOutput, + telemetry:&PackageTaskEventBuilder, + ) -> Result { + let task_start = Instant::now(); + let mut prefixed_ui = self.prefixed_ui(output_client); + + if self.ui_mode.has_sender() { + if let TaskOutput::UI(task) = output_client { + let output_logs = self.task_cache.output_logs().into(); + task.start(output_logs); + } + } + + if !self.task_cache.is_caching_disabled() { + let missing_platform_env = self.platform_env.validate(&self.execution_env); + if let Some(warning) = TaskWarning::new(&self.task_id_for_display, missing_platform_env) + { + self.warnings.lock().expect("warnings lock poisoned").push(warning); + } + } + + match self.task_cache.restore_outputs(&mut prefixed_ui, telemetry).await { + Ok(Some(status)) => { + // we need to set expanded outputs + self.hash_tracker.insert_expanded_outputs( + self.task_id.clone(), + self.task_cache.expanded_outputs().to_vec(), + ); + self.hash_tracker.insert_cache_status(self.task_id.clone(), status); + return Ok(ExecOutcome::Success(SuccessOutcome::CacheHit)); + }, + Ok(None) => (), + Err(e) => { + telemetry.track_error(TrackedErrors::ErrorFetchingFromCache); + prefixed_ui.error(&format!("error fetching from cache: {e}")); + }, + } + + let cmd = self.cmd.clone(); + + let mut process = match self.manager.spawn(cmd, Duration::from_millis(500)) { + Some(Ok(child)) => child, + // Turbo was unable to spawn a process + Some(Err(e)) => { + // Note: we actually failed to spawn, but this matches the Go output + prefixed_ui.error(&format!("command finished with error: {e}")); + let error_string = e.to_string(); + self.errors + .lock() + .expect("lock poisoned") + .push(TaskError::from_spawn(self.task_id_for_display.clone(), e)); + return Ok(ExecOutcome::Task { exit_code:None, message:error_string }); + }, + // Turbo is shutting down + None => { + return Ok(ExecOutcome::Shutdown); + }, + }; + + if self.ui_mode.has_sender() && self.takes_input { + if let TaskOutput::UI(task) = output_client { + if let Some(stdin) = process.stdin() { + task.set_stdin(stdin); + } + } + } + + // Even if user does not have the TUI and cannot interact with a task, we keep + // stdin open for persistent tasks as some programs will shut down if stdin is + // closed. + if !self.takes_input && !self.manager.closing_stdin_ends_process() { + process.stdin(); + } + + let mut stdout_writer = + self.task_cache.output_writer(prefixed_ui.task_writer()).inspect_err(|_| { + telemetry.track_error(TrackedErrors::FailedToCaptureOutputs); + })?; + + let exit_status = match process.wait_with_piped_outputs(&mut stdout_writer).await { + Ok(Some(exit_status)) => exit_status, + Err(e) => { + telemetry.track_error(TrackedErrors::FailedToPipeOutputs); + return Err(e.into()); + }, + Ok(None) => { + // TODO: how can this happen? we only update the + // exit status with Some and it is only initialized with + // None. Is it still running? + telemetry.track_error(TrackedErrors::UnknownChildExit); + error!("unable to determine why child exited"); + return Err(InternalError::UnknownChildExit); + }, + }; + let task_duration = task_start.elapsed(); + + match exit_status { + ChildExit::Finished(Some(0)) => { + // Attempt to flush stdout_writer and log any errors encountered + if let Err(e) = stdout_writer.flush() { + error!("{e}"); + } else if self + .task_access + .can_cache(&self.task_hash, &self.task_id_for_display) + .unwrap_or(true) + { + if let Err(e) = self.task_cache.save_outputs(task_duration, telemetry).await { + error!("error caching output: {e}"); + return Err(e.into()); + } else { + // If no errors, update hash tracker with expanded outputs + self.hash_tracker.insert_expanded_outputs( + self.task_id.clone(), + self.task_cache.expanded_outputs().to_vec(), + ); + } + } + + // Return success outcome + Ok(ExecOutcome::Success(SuccessOutcome::Run)) + }, + ChildExit::Finished(Some(code)) => { + // If there was an error, flush the buffered output + if let Err(e) = stdout_writer.flush() { + error!("error flushing logs: {e}"); + } + if let Err(e) = self.task_cache.on_error(&mut prefixed_ui) { + error!("error reading logs: {e}"); + } + let error = TaskErrorCause::from_execution(process.label().to_string(), code); + let message = error.to_string(); + if self.continue_on_error { + prefixed_ui.warn("command finished with error, but continuing..."); + } else { + prefixed_ui.error(&format!("command finished with error: {error}")); + } + self.errors + .lock() + .expect("lock poisoned") + .push(TaskError::new(self.task_id_for_display.clone(), error)); + Ok(ExecOutcome::Task { exit_code:Some(code), message }) + }, + // The child exited in a way where we can't figure out how it finished so we assume it + // failed. + ChildExit::Finished(None) | ChildExit::Failed => Err(InternalError::UnknownChildExit), + // Something else killed the child + ChildExit::KilledExternal => Err(InternalError::ExternalKill), + // The child was killed by turbo indicating a shutdown + ChildExit::Killed => Ok(ExecOutcome::Shutdown), + } + } + + fn spaces_task_info( + &self, + task_id:TaskId<'static>, + execution_summary:TaskExecutionSummary, + logs:Vec, + ) -> SpacesTaskInformation { + let dependencies = self.engine.dependencies(&task_id); + let dependents = self.engine.dependents(&task_id); + let cache_status = self.hash_tracker.cache_status(&task_id); + SpacesTaskInformation { + task_id, + execution_summary, + logs, + hash:self.task_hash.clone(), + cache_status, + dependencies, + dependents, + } + } +} + +pub struct DryRunExecContext { + task_id:TaskId<'static>, + task_cache:TaskCache, + hash_tracker:TaskHashTracker, +} + +#[derive(Debug, thiserror::Error)] +pub enum InternalError { + #[error(transparent)] + Io(#[from] std::io::Error), + #[error("unable to determine why task exited")] + UnknownChildExit, + #[error("unable to find package manager binary: {0}")] + Which(#[from] which::Error), + #[error("external process killed a task")] + ExternalKill, + #[error("error writing logs: {0}")] + Logs(#[from] crate::run::CacheError), +} +impl DryRunExecContext { + pub async fn execute_dry_run(&self, tracker:TaskTracker<()>) -> Result<(), InternalError> { + // may also need to do framework & command stuff? + if let Ok(Some(status)) = self.task_cache.exists().await { + self.hash_tracker.insert_cache_status(self.task_id.clone(), status); + } + tracker.dry_run().await; + Ok(()) + } +} diff --git a/crates/turborepo-lib/src/task_graph/visitor/mod.rs b/crates/turborepo-lib/Source/task_graph/visitor/mod.rs similarity index 100% rename from crates/turborepo-lib/src/task_graph/visitor/mod.rs rename to crates/turborepo-lib/Source/task_graph/visitor/mod.rs diff --git a/crates/turborepo-lib/Source/task_graph/visitor/output.rs b/crates/turborepo-lib/Source/task_graph/visitor/output.rs new file mode 100644 index 0000000000000..5589cb3df121f --- /dev/null +++ b/crates/turborepo-lib/Source/task_graph/visitor/output.rs @@ -0,0 +1,140 @@ +use std::io::Write; + +use either::Either; +use turbopath::AbsoluteSystemPath; +use turborepo_ui::{ + OutputClient, + OutputWriter, + PrefixedUI, + sender::TaskSender, + tui::event::CacheResult, +}; + +use crate::run::CacheOutput; + +/// Small wrapper over our two output types that defines a shared interface for +/// interacting with them. +pub enum TaskOutput { + Direct(OutputClient), + UI(TaskSender), +} + +/// Struct for displaying information about task +impl TaskOutput { + pub fn finish(self, use_error:bool, is_cache_hit:bool) -> std::io::Result>> { + match self { + TaskOutput::Direct(client) => client.finish(use_error), + TaskOutput::UI(client) if use_error => Ok(Some(client.failed())), + TaskOutput::UI(client) => Ok(Some(client.succeeded(is_cache_hit))), + } + } + + pub fn stdout(&self) -> Either, TaskSender> { + match self { + TaskOutput::Direct(client) => Either::Left(client.stdout()), + TaskOutput::UI(client) => Either::Right(client.clone()), + } + } + + pub fn stderr(&self) -> Either, TaskSender> { + match self { + TaskOutput::Direct(client) => Either::Left(client.stderr()), + TaskOutput::UI(client) => Either::Right(client.clone()), + } + } + + pub fn task_logs(&self) -> Either, TaskSender> { + match self { + TaskOutput::Direct(client) => Either::Left(client.stdout()), + TaskOutput::UI(client) => Either::Right(client.clone()), + } + } +} + +/// Struct for displaying information about task's cache +pub enum TaskCacheOutput { + Direct(PrefixedUI), + UI(TaskSender), +} + +impl TaskCacheOutput { + pub fn task_writer(&mut self) -> Either, TaskSender> { + match self { + TaskCacheOutput::Direct(prefixed) => Either::Left(prefixed.output_prefixed_writer()), + TaskCacheOutput::UI(task) => Either::Right(task.clone()), + } + } + + pub fn warn(&mut self, message:impl std::fmt::Display) { + match self { + TaskCacheOutput::Direct(prefixed) => prefixed.warn(message), + TaskCacheOutput::UI(task) => { + let _ = write!(task, "\r\n{message}\r\n"); + }, + } + } +} + +impl CacheOutput for TaskCacheOutput { + fn status(&mut self, message:&str, result:CacheResult) { + match self { + TaskCacheOutput::Direct(direct) => direct.output(message), + TaskCacheOutput::UI(task) => task.status(message, result), + } + } + + fn error(&mut self, message:&str) { + match self { + TaskCacheOutput::Direct(prefixed) => prefixed.error(message), + TaskCacheOutput::UI(task) => { + let _ = write!(task, "{message}\r\n"); + }, + } + } + + fn replay_logs(&mut self, log_file:&AbsoluteSystemPath) -> Result<(), turborepo_ui::Error> { + match self { + TaskCacheOutput::Direct(direct) => { + let writer = direct.output_prefixed_writer(); + turborepo_ui::replay_logs(writer, log_file) + }, + TaskCacheOutput::UI(task) => turborepo_ui::replay_logs(task, log_file), + } + } +} + +// A tiny enum that allows us to use the same type for stdout and stderr without +// the use of Box +pub enum StdWriter { + Out(std::io::Stdout), + Err(std::io::Stderr), + Null(std::io::Sink), +} + +impl StdWriter { + fn writer(&mut self) -> &mut dyn std::io::Write { + match self { + StdWriter::Out(out) => out, + StdWriter::Err(err) => err, + StdWriter::Null(null) => null, + } + } +} + +impl From for StdWriter { + fn from(value:std::io::Stdout) -> Self { Self::Out(value) } +} + +impl From for StdWriter { + fn from(value:std::io::Stderr) -> Self { Self::Err(value) } +} + +impl From for StdWriter { + fn from(value:std::io::Sink) -> Self { Self::Null(value) } +} + +impl std::io::Write for StdWriter { + fn write(&mut self, buf:&[u8]) -> std::io::Result { self.writer().write(buf) } + + fn flush(&mut self) -> std::io::Result<()> { self.writer().flush() } +} diff --git a/crates/turborepo-lib/src/task_hash.rs b/crates/turborepo-lib/Source/task_hash.rs similarity index 100% rename from crates/turborepo-lib/src/task_hash.rs rename to crates/turborepo-lib/Source/task_hash.rs diff --git a/crates/turborepo-lib/Source/tracing.rs b/crates/turborepo-lib/Source/tracing.rs new file mode 100644 index 0000000000000..bd31ff5ebfdfb --- /dev/null +++ b/crates/turborepo-lib/Source/tracing.rs @@ -0,0 +1,345 @@ +use std::{io::Stderr, marker::PhantomData, path::Path, sync::Mutex}; + +use chrono::Local; +use owo_colors::{ + Color, + OwoColorize, + colors::{Black, Default, Red, Yellow}, +}; +use tracing::{Event, Level, Subscriber, field::Visit, metadata::LevelFilter, trace}; +use tracing_appender::{non_blocking::NonBlocking, rolling::RollingFileAppender}; +use tracing_chrome::ChromeLayer; +pub use tracing_subscriber::reload::Error; +use tracing_subscriber::{ + EnvFilter, + Layer, + Registry, + filter::Filtered, + fmt::{ + self, + FmtContext, + FormatEvent, + FormatFields, + MakeWriter, + format::{DefaultFields, Writer}, + }, + layer, + prelude::*, + registry::LookupSpan, + reload::{self, Handle}, +}; +use turborepo_ui::ColorConfig; + +// a lot of types to make sure we record the right relationships + +/// Note that we cannot express the type of `std::io::stderr` directly, so +/// use zero-size wrapper to call the function. +struct StdErrWrapper {} + +impl<'a> MakeWriter<'a> for StdErrWrapper { + type Writer = Stderr; + + fn make_writer(&'a self) -> Self::Writer { std::io::stderr() } +} + +/// A basic logger that logs to stderr using the TurboFormatter. +/// The first generic parameter refers to the previous layer, which +/// is in this case the default layer (`Registry`). +type StdErrLog = fmt::Layer; +/// We filter this using an EnvFilter. +type StdErrLogFiltered = Filtered; +/// When the `StdErrLogFiltered` is applied to the `Registry`, we get a +/// `StdErrLogLayered`, which forms the base for the next layer. +type StdErrLogLayered = layer::Layered; + +/// A logger that spits lines into a file, using the standard formatter. +/// It is applied on top of the `StdErrLogLayered` layer. +type DaemonLog = fmt::Layer; +/// This layer can be reloaded. `None` means the layer is disabled. +type DaemonReload = reload::Layer, StdErrLogLayered>; +/// We filter this using a custom filter that only logs events +/// - with evel `TRACE` or higher for the `turborepo` target +/// - with level `INFO` or higher for all other targets +type DaemonLogFiltered = Filtered; +/// When the `DaemonLogFiltered` is applied to the `StdErrLogLayered`, we get a +/// `DaemonLogLayered`, which forms the base for the next layer. +type DaemonLogLayered = layer::Layered; + +/// A logger that converts events to chrome tracing format and writes them +/// to a file. It is applied on top of the `DaemonLogLayered` layer. +type ChromeLog = ChromeLayer; +/// This layer can be reloaded. `None` means the layer is disabled. +type ChromeReload = reload::Layer, DaemonLogLayered>; +/// When the `ChromeLogFiltered` is applied to the `DaemonLogLayered`, we get a +/// `ChromeLogLayered`, which forms the base for the next layer. +type ChromeLogLayered = layer::Layered; + +pub struct TurboSubscriber { + daemon_update:Handle, StdErrLogLayered>, + + /// The non-blocking file logger only continues to log while this guard is + /// held. We keep it here so that it doesn't get dropped. + daemon_guard:Mutex>, + + chrome_update:Handle, DaemonLogLayered>, + chrome_guard:Mutex>, + + #[cfg(feature = "pprof")] + pprof_guard:pprof::ProfilerGuard<'static>, +} + +impl TurboSubscriber { + /// Sets up the tracing subscriber, with a default stderr layer using the + /// TurboFormatter. + /// + /// ## Logging behaviour: + /// - If stdout is a terminal, we use ansi colors. Otherwise, we do not. + /// - If the `TURBO_LOG_VERBOSITY` env var is set, it will be used to set + /// the verbosity level. Otherwise, the default is `WARN`. See the + /// documentation on the RUST_LOG env var for syntax. + /// - If the verbosity argument (usually determined by a flag) is provided, + /// it overrides the default global log level. This means it overrides the + /// `TURBO_LOG_VERBOSITY` global setting, but not per-module settings. + /// + /// `TurboSubscriber` has optional loggers that can be enabled later: + /// - `set_daemon_logger` enables logging to a file, using the standard + /// formatter. + /// - `enable_chrome_tracing` enables logging to a file, using the chrome + /// tracing formatter. + pub fn new_with_verbosity(verbosity:usize, color_config:&ColorConfig) -> Self { + let level_override = match verbosity { + 0 => None, + 1 => Some(LevelFilter::INFO), + 2 => Some(LevelFilter::DEBUG), + _ => Some(LevelFilter::TRACE), + }; + + let env_filter = |level:LevelFilter| { + let filter = EnvFilter::builder() + .with_default_directive(level.into()) + .with_env_var("TURBO_LOG_VERBOSITY") + .from_env_lossy() + .add_directive("reqwest=error".parse().unwrap()) + .add_directive("hyper=warn".parse().unwrap()) + .add_directive("h2=warn".parse().unwrap()); + + if let Some(max_level) = level_override { + filter.add_directive(max_level.into()) + } else { + filter + } + }; + + let stderr = fmt::layer() + .with_writer(StdErrWrapper {}) + .event_format(TurboFormatter::new_with_ansi(!color_config.should_strip_ansi)) + .with_filter(env_filter(LevelFilter::WARN)); + + // we set this layer to None to start with, effectively disabling it + let (logrotate, daemon_update) = reload::Layer::new(Option::::None); + let logrotate:DaemonLogFiltered = logrotate.with_filter(env_filter(LevelFilter::INFO)); + + let (chrome, chrome_update) = reload::Layer::new(Option::::None); + + let registry = Registry::default().with(stderr).with(logrotate).with(chrome); + + #[cfg(feature = "pprof")] + let pprof_guard = pprof::ProfilerGuardBuilder::default() + .frequency(1000) + .blocklist(&["libc", "libgcc", "pthread", "vdso"]) + .build() + .unwrap(); + + registry.init(); + + Self { + daemon_update, + daemon_guard:Mutex::new(None), + chrome_update, + chrome_guard:Mutex::new(None), + #[cfg(feature = "pprof")] + pprof_guard, + } + } + + /// Enables daemon logging with the specified rotation settings. + /// + /// Daemon logging uses the standard tracing formatter. + #[tracing::instrument(skip(self, appender))] + pub fn set_daemon_logger(&self, appender:RollingFileAppender) -> Result<(), Error> { + let (file_writer, guard) = tracing_appender::non_blocking(appender); + trace!("created non-blocking file writer"); + + let layer:DaemonLog = + tracing_subscriber::fmt::layer().with_writer(file_writer).with_ansi(false); + + self.daemon_update.reload(Some(layer))?; + self.daemon_guard.lock().expect("not poisoned").replace(guard); + + Ok(()) + } + + /// Enables chrome tracing. + #[tracing::instrument(skip(self, to_file))] + pub fn enable_chrome_tracing>( + &self, + to_file:P, + include_args:bool, + ) -> Result<(), Error> { + let (layer, guard) = tracing_chrome::ChromeLayerBuilder::new() + .file(to_file) + .include_args(include_args) + .include_locations(true) + .trace_style(tracing_chrome::TraceStyle::Async) + .build(); + + self.chrome_update.reload(Some(layer))?; + self.chrome_guard.lock().expect("not poisoned").replace(guard); + + Ok(()) + } +} + +impl Drop for TurboSubscriber { + fn drop(&mut self) { + // drop the guard so that the non-blocking file writer stops + #[cfg(feature = "pprof")] + if let Ok(report) = self.pprof_guard.report().build() { + use std::io::Write; // only import trait if we need it + + use prost::Message; + + let mut file = std::fs::File::create("pprof.pb").unwrap(); + let mut content = Vec::new(); + + let Ok(profile) = report.pprof() else { + tracing::error!("failed to generate pprof report"); + return; + }; + if let Err(e) = profile.encode(&mut content) { + tracing::error!("failed to encode pprof profile: {}", e); + }; + if let Err(e) = file.write_all(&content) { + tracing::error!("failed to write pprof profile: {}", e) + }; + } else { + tracing::error!("failed to generate pprof report") + } + } +} + +/// The formatter for TURBOREPO +/// +/// This is a port of the go formatter, which follows a few main rules: +/// - Errors are red +/// - Warnings are yellow +/// - Info is default +/// - Debug and trace are default, but with timestamp and level attached +/// +/// This formatter does not print any information about spans, and does +/// not print any event metadata other than the message set when you +/// call `debug!(...)` or `info!(...)` etc. +pub struct TurboFormatter { + is_ansi:bool, +} + +impl TurboFormatter { + pub fn new_with_ansi(is_ansi:bool) -> Self { Self { is_ansi } } +} + +impl FormatEvent for TurboFormatter +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, +{ + fn format_event( + &self, + _ctx:&FmtContext<'_, S, N>, + mut writer:Writer<'_>, + event:&Event<'_>, + ) -> std::fmt::Result { + let level = event.metadata().level(); + let target = event.metadata().target(); + + match *level { + Level::ERROR => { + // The padding spaces are necessary to match the formatting of Go + write_string::(writer.by_ref(), self.is_ansi, " ERROR ") + .and_then(|_| write_message::(writer, self.is_ansi, event)) + }, + Level::WARN => { + // The padding spaces are necessary to match the formatting of Go + write_string::(writer.by_ref(), self.is_ansi, " WARNING ") + .and_then(|_| write_message::(writer, self.is_ansi, event)) + }, + Level::INFO => write_message::(writer, self.is_ansi, event), + // trace and debug use the same style + _ => { + let now = Local::now(); + write!( + writer, + "{} [{}] {}: ", + // build our own timestamp to match the hashicorp/go-hclog format used by the + // go binary + now.format("%Y-%m-%dT%H:%M:%S.%3f%z"), + level, + target, + ) + .and_then(|_| write_message::(writer, self.is_ansi, event)) + }, + } + } +} + +/// A visitor that writes the message field of an event to the given writer. +/// +/// The FG and BG type parameters are the foreground and background colors +/// to use when writing the message. +struct MessageVisitor<'a, FG:Color, BG:Color> { + colorize:bool, + writer:Writer<'a>, + _fg:PhantomData, + _bg:PhantomData, +} + +impl<'a, FG:Color, BG:Color> Visit for MessageVisitor<'a, FG, BG> { + fn record_debug(&mut self, field:&tracing::field::Field, value:&dyn std::fmt::Debug) { + if field.name() == "message" { + if self.colorize { + let value = value.fg::().bg::(); + let _ = write!(self.writer, "{:?}", value); + } else { + let _ = write!(self.writer, "{:?}", value); + } + } + } +} + +fn write_string( + mut writer:Writer<'_>, + colorize:bool, + value:&str, +) -> Result<(), std::fmt::Error> { + if colorize { + let value = value.fg::().bg::(); + write!(writer, "{} ", value) + } else { + write!(writer, "{} ", value) + } +} + +/// Writes the message field of an event to the given writer. +fn write_message( + mut writer:Writer<'_>, + colorize:bool, + event:&Event, +) -> Result<(), std::fmt::Error> { + let mut visitor = MessageVisitor:: { + colorize, + writer:writer.by_ref(), + _fg:PhantomData, + _bg:PhantomData, + }; + event.record(&mut visitor); + writeln!(writer) +} diff --git a/crates/turborepo-lib/src/turbo_json/loader.rs b/crates/turborepo-lib/Source/turbo_json/loader.rs similarity index 100% rename from crates/turborepo-lib/src/turbo_json/loader.rs rename to crates/turborepo-lib/Source/turbo_json/loader.rs diff --git a/crates/turborepo-lib/src/turbo_json/mod.rs b/crates/turborepo-lib/Source/turbo_json/mod.rs similarity index 100% rename from crates/turborepo-lib/src/turbo_json/mod.rs rename to crates/turborepo-lib/Source/turbo_json/mod.rs diff --git a/crates/turborepo-lib/src/turbo_json/parser.rs b/crates/turborepo-lib/Source/turbo_json/parser.rs similarity index 100% rename from crates/turborepo-lib/src/turbo_json/parser.rs rename to crates/turborepo-lib/Source/turbo_json/parser.rs diff --git a/crates/turborepo-lib/build.rs b/crates/turborepo-lib/build.rs index eef97707179f7..678c730c2ce15 100644 --- a/crates/turborepo-lib/build.rs +++ b/crates/turborepo-lib/build.rs @@ -1,31 +1,28 @@ fn main() -> Result<(), Box> { - let tonic_build_result = tonic_build::configure() - .build_server(true) - .file_descriptor_set_path("src/daemon/file_descriptor_set.bin") - .compile( - &["./src/daemon/proto/turbod.proto"], - &["./src/daemon/proto"], - ); - let capnpc_result = capnpc::CompilerCommand::new() - .file("./src/hash/proto.capnp") - .default_parent_module(vec!["hash".to_string()]) - .run(); + let tonic_build_result = tonic_build::configure() + .build_server(true) + .file_descriptor_set_path("src/daemon/file_descriptor_set.bin") + .compile(&["./src/daemon/proto/turbod.proto"], &["./src/daemon/proto"]); + let capnpc_result = capnpc::CompilerCommand::new() + .file("./src/hash/proto.capnp") + .default_parent_module(vec!["hash".to_string()]) + .run(); - let invocation = std::env::var("RUSTC_WRAPPER").unwrap_or_default(); - if invocation.ends_with("rust-analyzer") { - if tonic_build_result.is_err() { - println!("cargo:warning=tonic_build failed, but continuing with rust-analyzer"); - } + let invocation = std::env::var("RUSTC_WRAPPER").unwrap_or_default(); + if invocation.ends_with("rust-analyzer") { + if tonic_build_result.is_err() { + println!("cargo:warning=tonic_build failed, but continuing with rust-analyzer"); + } - if capnpc_result.is_err() { - println!("cargo:warning=capnpc failed, but continuing with rust-analyzer"); - } + if capnpc_result.is_err() { + println!("cargo:warning=capnpc failed, but continuing with rust-analyzer"); + } - return Ok(()); - } else { - tonic_build_result.expect("tonic_build command"); - capnpc_result.expect("schema compiler command"); - } + return Ok(()); + } else { + tonic_build_result.expect("tonic_build command"); + capnpc_result.expect("schema compiler command"); + } - Ok(()) + Ok(()) } diff --git a/crates/turborepo-lib/fixtures/local_config/turbo.v1.json b/crates/turborepo-lib/fixtures/local_config/turbo.v1.json deleted file mode 100644 index 0baf1b96b32a4..0000000000000 --- a/crates/turborepo-lib/fixtures/local_config/turbo.v1.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - // some comments - "pipeline": { - "build": {"dependsOn": ["^build"]} - } -} diff --git a/crates/turborepo-lib/fixtures/local_config/turbo.v2.json b/crates/turborepo-lib/fixtures/local_config/turbo.v2.json deleted file mode 100644 index 6e03bbedd06ca..0000000000000 --- a/crates/turborepo-lib/fixtures/local_config/turbo.v2.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - // some comments - "tasks": { - "build": {"dependsOn": ["^build"]} - } -} diff --git a/crates/turborepo-lib/fixtures/local_config/turbov2.package-lock.json b/crates/turborepo-lib/fixtures/local_config/turbov2.package-lock.json deleted file mode 100644 index 0616f589f2cda..0000000000000 --- a/crates/turborepo-lib/fixtures/local_config/turbov2.package-lock.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "name": "pm-and-lockfile", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "pm-and-lockfile", - "workspaces": [ - "apps/*" - ], - "devDependencies": { - "turbo": "latest" - } - }, - "apps/web": {}, - "node_modules/turbo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.0.3.tgz", - "integrity": "sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==", - "dev": true, - "bin": { - "turbo": "bin/turbo" - }, - "optionalDependencies": { - "turbo-darwin-64": "2.0.3", - "turbo-darwin-arm64": "2.0.3", - "turbo-linux-64": "2.0.3", - "turbo-linux-arm64": "2.0.3", - "turbo-windows-64": "2.0.3", - "turbo-windows-arm64": "2.0.3" - } - }, - "node_modules/turbo-darwin-64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.0.3.tgz", - "integrity": "sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/turbo-darwin-arm64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.3.tgz", - "integrity": "sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/turbo-linux-64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.0.3.tgz", - "integrity": "sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/turbo-linux-arm64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.0.3.tgz", - "integrity": "sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/turbo-windows-64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.0.3.tgz", - "integrity": "sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/turbo-windows-arm64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.0.3.tgz", - "integrity": "sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/web": { - "resolved": "apps/web", - "link": true - } - } -} diff --git a/crates/turborepo-lib/src/child.rs b/crates/turborepo-lib/src/child.rs deleted file mode 100644 index 6eb6ece576484..0000000000000 --- a/crates/turborepo-lib/src/child.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::{io, process::Command, sync::Arc}; - -use shared_child::SharedChild; - -/// Spawns a child in a way where SIGINT is correctly forwarded to the child -pub fn spawn_child(mut command: Command) -> Result, io::Error> { - let shared_child = Arc::new(SharedChild::spawn(&mut command)?); - let handler_shared_child = shared_child.clone(); - - ctrlc::set_handler(move || { - // on windows, we can't send signals so just kill - // we are quitting anyways so just ignore - #[cfg(target_os = "windows")] - handler_shared_child.kill().ok(); - - // on unix, we should send a SIGTERM to the child - // so that go can gracefully shut down process groups - // SAFETY: we could pull in the nix crate to handle this - // 'safely' but nix::sys::signal::kill just calls libc::kill - #[cfg(not(target_os = "windows"))] - unsafe { - libc::kill(handler_shared_child.id() as i32, libc::SIGTERM); - } - }) - .expect("handler set"); - - Ok(shared_child) -} diff --git a/crates/turborepo-lib/src/commands/config.rs b/crates/turborepo-lib/src/commands/config.rs deleted file mode 100644 index b0c2873ff4b50..0000000000000 --- a/crates/turborepo-lib/src/commands/config.rs +++ /dev/null @@ -1,63 +0,0 @@ -use camino::Utf8Path; -use serde::Serialize; -use turbopath::AbsoluteSystemPathBuf; -use turborepo_repository::{package_graph::PackageGraph, package_json::PackageJson}; - -use crate::{cli, cli::EnvMode, commands::CommandBase, turbo_json::UIMode, Args}; - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct ConfigOutput<'a> { - api_url: &'a str, - login_url: &'a str, - team_slug: Option<&'a str>, - team_id: Option<&'a str>, - signature: bool, - preflight: bool, - timeout: u64, - upload_timeout: u64, - enabled: bool, - spaces_id: Option<&'a str>, - ui: UIMode, - package_manager: &'static str, - daemon: Option, - env_mode: EnvMode, - scm_base: Option<&'a str>, - scm_head: Option<&'a str>, - cache_dir: &'a Utf8Path, -} - -pub async fn run(repo_root: AbsoluteSystemPathBuf, args: Args) -> Result<(), cli::Error> { - let config = CommandBase::load_config(&repo_root, &args)?; - let root_package_json = PackageJson::load(&repo_root.join_component("package.json"))?; - - let package_graph = PackageGraph::builder(&repo_root, root_package_json) - .build() - .await?; - - let package_manager = package_graph.package_manager().name(); - - println!( - "{}", - serde_json::to_string_pretty(&ConfigOutput { - api_url: config.api_url(), - login_url: config.login_url(), - team_slug: config.team_slug(), - team_id: config.team_id(), - signature: config.signature(), - preflight: config.preflight(), - timeout: config.timeout(), - upload_timeout: config.upload_timeout(), - enabled: config.enabled(), - spaces_id: config.spaces_id(), - ui: config.ui(), - package_manager, - daemon: config.daemon, - env_mode: config.env_mode(), - scm_base: config.scm_base(), - scm_head: config.scm_head(), - cache_dir: config.cache_dir(), - })? - ); - Ok(()) -} diff --git a/crates/turborepo-lib/src/commands/daemon.rs b/crates/turborepo-lib/src/commands/daemon.rs deleted file mode 100644 index ce1ac1030b43f..0000000000000 --- a/crates/turborepo-lib/src/commands/daemon.rs +++ /dev/null @@ -1,332 +0,0 @@ -use std::time::Duration; - -use camino::Utf8PathBuf; -use futures::FutureExt; -use pidlock::PidlockError::AlreadyOwned; -use serde_json::json; -use time::{format_description, OffsetDateTime}; -use tokio::signal::ctrl_c; -use tracing::{trace, warn}; -use turbopath::AbsoluteSystemPath; -use turborepo_ui::{color, BOLD_GREEN, BOLD_RED, GREY}; -use which::which; - -use super::CommandBase; -use crate::{ - cli::DaemonCommand, - daemon::{ - endpoint::SocketOpenError, CloseReason, DaemonConnector, DaemonConnectorError, DaemonError, - Paths, - }, - tracing::TurboSubscriber, -}; - -const DAEMON_NOT_RUNNING_MESSAGE: &str = - "daemon is not running, run `turbo daemon start` to start it"; - -/// Runs the daemon command. -pub async fn daemon_client(command: &DaemonCommand, base: &CommandBase) -> Result<(), DaemonError> { - let (can_start_server, can_kill_server) = match command { - DaemonCommand::Status { .. } | DaemonCommand::Logs => (false, false), - DaemonCommand::Stop => (false, true), - DaemonCommand::Restart | DaemonCommand::Start => (true, true), - DaemonCommand::Clean { .. } => (false, true), - }; - - let connector = DaemonConnector::new(can_start_server, can_kill_server, &base.repo_root); - - match command { - DaemonCommand::Restart => { - let result: Result<_, DaemonError> = try { - let client = connector.clone().connect().await?; - client.restart().await? - }; - - if let Err(e) = result { - tracing::debug!("failed to restart the daemon: {:?}", e); - tracing::debug!("falling back to clean"); - clean(&connector.paths.pid_file, &connector.paths.sock_file)?; - tracing::debug!("connecting for second time"); - let _ = connector.connect().await?; - } - - println!( - "{} restarted daemon", - color!(base.color_config, BOLD_GREEN, "✓") - ); - } - DaemonCommand::Start => { - // We don't care about the client, but we do care that we can connect - // which ensures that daemon is started if it wasn't already. - let _ = connector.connect().await?; - println!( - "{} daemon is running", - color!(base.color_config, BOLD_GREEN, "✓") - ); - } - DaemonCommand::Stop => { - let client = match connector.connect().await { - Ok(client) => client, - Err(DaemonConnectorError::NotRunning) => { - println!( - "{} stopped daemon", - color!(base.color_config, BOLD_GREEN, "✓") - ); - return Ok(()); - } - Err(e) => { - return Err(e.into()); - } - }; - client.stop().await?; - println!( - "{} stopped daemon", - color!(base.color_config, BOLD_GREEN, "✓") - ); - } - DaemonCommand::Status { json } => { - let mut client = match connector.connect().await { - Ok(status) => status, - Err(DaemonConnectorError::NotRunning) if *json => { - println!("{}", json!({ "error": DAEMON_NOT_RUNNING_MESSAGE })); - return Ok(()); - } - Err(DaemonConnectorError::NotRunning) => { - println!( - "{} {}", - color!(base.color_config, BOLD_RED, "x"), - DAEMON_NOT_RUNNING_MESSAGE - ); - return Ok(()); - } - Err(e) => { - return Err(e.into()); - } - }; - let status = client.status().await?; - let log_file = log_filename(&status.log_file)?; - let paths = client.paths(); - let status = DaemonStatus { - uptime_ms: status.uptime_msec, - log_file: log_file.into(), - pid_file: paths.pid_file.to_owned(), - sock_file: paths.sock_file.to_owned(), - }; - - if *json { - println!("{}", serde_json::to_string_pretty(&status)?); - } else { - println!( - "{} daemon is running", - color!(base.color_config, BOLD_GREEN, "✓") - ); - println!( - "log file: {}", - color!(base.color_config, GREY, "{}", status.log_file) - ); - println!( - "uptime: {}", - color!( - base.color_config, - GREY, - "{}s", - humantime::format_duration(Duration::from_millis(status.uptime_ms)) - ) - ); - println!( - "pid file: {}", - color!(base.color_config, GREY, "{}", status.pid_file) - ); - println!( - "socket file: {}", - color!(base.color_config, GREY, "{}", status.sock_file) - ); - } - } - DaemonCommand::Logs => { - let log_file = if let Ok(log_file) = get_log_file_from_daemon(connector).await { - log_file - } else { - get_log_file_from_folder(base).await? - }; - - let tail = which("tail").map_err(|_| DaemonError::TailNotInstalled)?; - - std::process::Command::new(tail) - .arg("-f") - .arg(log_file) - .status() - .expect("failed to execute tail"); - } - DaemonCommand::Clean { - clean_logs: should_clean_logs, - } => { - // try to connect and shutdown the daemon - let paths = connector.paths.clone(); - let client = connector.connect().await; - match client { - Ok(client) => match client.stop().await { - Ok(_) => { - tracing::trace!("successfully stopped the daemon"); - } - Err(e) => { - tracing::trace!("unable to stop the daemon: {:?}", e); - } - }, - Err(e) => { - tracing::trace!("unable to connect to the daemon: {:?}", e); - } - } - clean(&paths.pid_file, &paths.sock_file)?; - if *should_clean_logs { - clean_logs(&paths.log_folder)?; - } - println!("Done"); - } - }; - - Ok(()) -} - -async fn get_log_file_from_daemon(connector: DaemonConnector) -> Result { - let mut client = connector.connect().await?; - let status = client.status().await?; - Ok(log_filename(&status.log_file)?) -} - -async fn get_log_file_from_folder(base: &CommandBase) -> Result { - warn!("couldn't connect to daemon, looking for old log files"); - let log_folder = base.repo_root.join_components(&[".turbo", "daemon"]); - let Ok(dir) = std::fs::read_dir(log_folder) else { - return Err(DaemonError::LogFileNotFound); - }; - - let (latest_file, _) = dir - .flatten() - .filter_map(|entry| { - let modified_time = entry.metadata().ok()?.modified().ok()?; - Some((entry, modified_time)) - }) - .max_by(|(_, mt1), (_, mt2)| mt1.cmp(mt2)) - .ok_or(DaemonError::LogFileNotFound)?; - - Ok(latest_file - .path() - .to_str() - .expect("log file should be utf-8") - .to_string()) -} - -fn clean(pid_file: &AbsoluteSystemPath, sock_file: &AbsoluteSystemPath) -> Result<(), DaemonError> { - // remove pid and sock files - let mut success = true; - trace!("cleaning up daemon files"); - // if the pid_file and sock_file still exist, remove them: - if pid_file.exists() { - let result = pid_file.remove_file(); - // ignore this error - if let Err(e) = result { - println!("Failed to remove pid file: {}", e); - println!("Please remove manually: {}", pid_file); - success = false; - } - } - if sock_file.exists() { - let result = sock_file.remove_file(); - // ignore this error - if let Err(e) = result { - println!("Failed to remove socket file: {}", e); - println!("Please remove manually: {}", sock_file); - success = false; - } - } - - if success { - Ok(()) - } else { - // return error - Err(DaemonError::CleanFailed) - } -} - -fn clean_logs(log_folder: &AbsoluteSystemPath) -> Result<(), DaemonError> { - trace!("cleaning up log files"); - // clear all files in the log folder. we want to keep the - // folder just remove the contents - // `remove_dir_all_recursive` is lifted from `std` - log_folder.remove_dir_all().map_err(|e| { - println!("Failed to remove log files: {}", e); - println!("Please remove manually: {}", log_folder); - DaemonError::CleanFailed - }) -} - -// log_filename matches the algorithm used by tracing_appender::Rotation::DAILY -// to generate the log filename. This is kind of a hack, but there didn't appear -// to be a simple way to grab the generated filename. -fn log_filename(base_filename: &str) -> Result { - let now = OffsetDateTime::now_utc(); - let format = format_description::parse("[year]-[month]-[day]")?; - let date = now.format(&format)?; - Ok(format!("{}.{}", base_filename, date)) -} - -#[tracing::instrument(skip(base, logging), fields(repo_root = %base.repo_root))] -pub async fn daemon_server( - base: &CommandBase, - idle_time: &String, - logging: &TurboSubscriber, -) -> Result<(), DaemonError> { - let paths = Paths::from_repo_root(&base.repo_root); - - tracing::trace!("logging to file: {:?}", paths.log_file); - if let Err(e) = logging.set_daemon_logger(tracing_appender::rolling::daily( - &paths.log_folder, - &paths.log_file, - )) { - // error here is not fatal, just log it - tracing::error!("failed to set file logger: {}", e); - } - - let timeout = go_parse_duration::parse_duration(idle_time) - .map_err(|_| DaemonError::InvalidTimeout(idle_time.to_owned())) - .map(|d| Duration::from_nanos(d as u64))?; - - let exit_signal = ctrl_c().map(|result| { - if let Err(e) = result { - tracing::error!("Error with signal handling: {}", e); - } - CloseReason::Interrupt - }); - let server = - crate::daemon::TurboGrpcService::new(base.repo_root.clone(), paths, timeout, exit_signal); - - let reason = server.serve().await?; - - match reason { - CloseReason::SocketOpenError(SocketOpenError::LockError(AlreadyOwned)) => { - warn!("daemon already running"); - } - CloseReason::SocketOpenError(e) => return Err(e.into()), - CloseReason::Interrupt - | CloseReason::ServerClosed - | CloseReason::WatcherClosed - | CloseReason::Timeout - | CloseReason::Shutdown => { - // these are all ok, just exit - trace!("shutting down daemon: {:?}", reason); - } - }; - - Ok(()) -} - -#[derive(serde::Serialize)] -pub struct DaemonStatus { - pub uptime_ms: u64, - // this comes from the daemon server, so we trust that - // it is correct - pub log_file: Utf8PathBuf, - pub pid_file: turbopath::AbsoluteSystemPathBuf, - pub sock_file: turbopath::AbsoluteSystemPathBuf, -} diff --git a/crates/turborepo-lib/src/commands/generate.rs b/crates/turborepo-lib/src/commands/generate.rs deleted file mode 100644 index 2269b87924cc2..0000000000000 --- a/crates/turborepo-lib/src/commands/generate.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::{ - io, - process::{Command, Stdio}, -}; - -use thiserror::Error; -use tracing::debug; -use turborepo_telemetry::events::command::CommandEventBuilder; -use which::which; - -use crate::{ - child::spawn_child, - cli::{GenerateCommand, GeneratorCustomArgs}, -}; - -#[derive(Debug, Error)] -pub enum Error { - #[error("Unable to run generate - missing requirements (npx): {0}")] - NpxNotFound(#[source] which::Error), - #[error("Failed to run npx: {0}")] - NpxFailed(#[source] io::Error), - #[error(transparent)] - Json(#[from] serde_json::Error), -} - -fn call_turbo_gen(command: &str, tag: &String, raw_args: &str) -> Result { - debug!( - "Running @turbo/gen@{} with command `{}` and args {:?}", - tag, command, raw_args - ); - let npx_path = which("npx").map_err(Error::NpxNotFound)?; - let mut npx = Command::new(npx_path); - npx.arg("--yes") - .arg(format!("@turbo/gen@{}", tag)) - .arg("raw") - .arg(command) - .args(["--json", raw_args]) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()); - - let child = spawn_child(npx).map_err(Error::NpxFailed)?; - let exit_code = child.wait().map_err(Error::NpxFailed)?.code().unwrap_or(2); - Ok(exit_code) -} - -pub fn run( - tag: &String, - command: &Option>, - args: &GeneratorCustomArgs, - telemetry: CommandEventBuilder, -) -> Result<(), Error> { - telemetry.track_generator_tag(tag); - // check if a subcommand was passed - if let Some(box GenerateCommand::Workspace(workspace_args)) = command { - let raw_args = serde_json::to_string(&workspace_args)?; - telemetry.track_generator_option("workspace"); - call_turbo_gen("workspace", tag, &raw_args)?; - } else { - // if no subcommand was passed, run the generate command as default - let raw_args = serde_json::to_string(&args)?; - telemetry.track_generator_option("run"); - call_turbo_gen("run", tag, &raw_args)?; - } - - Ok(()) -} diff --git a/crates/turborepo-lib/src/commands/login.rs b/crates/turborepo-lib/src/commands/login.rs deleted file mode 100644 index 7ffa54e81185f..0000000000000 --- a/crates/turborepo-lib/src/commands/login.rs +++ /dev/null @@ -1,148 +0,0 @@ -use turborepo_api_client::APIClient; -use turborepo_auth::{ - login as auth_login, sso_login as auth_sso_login, DefaultLoginServer, LoginOptions, Token, -}; -use turborepo_telemetry::events::command::{CommandEventBuilder, LoginMethod}; - -use crate::{cli::Error, commands::CommandBase, config, rewrite_json::set_path}; - -pub async fn sso_login( - base: &mut CommandBase, - sso_team: &str, - telemetry: CommandEventBuilder, - force: bool, -) -> Result<(), Error> { - telemetry.track_login_method(LoginMethod::SSO); - let api_client: APIClient = base.api_client()?; - let color_config = base.color_config; - let login_url_config = base.opts.api_client_opts.login_url.to_string(); - let options = LoginOptions { - existing_token: base.opts.api_client_opts.token.as_deref(), - sso_team: Some(sso_team), - force, - ..LoginOptions::new( - &color_config, - &login_url_config, - &api_client, - &DefaultLoginServer, - ) - }; - - let token = auth_sso_login(&options).await?; - - // Don't write to disk if the token is already there - if matches!(token, Token::Existing(..)) { - return Ok(()); - } - - let global_config_path = base.global_config_path()?; - let before = global_config_path - .read_existing_to_string() - .map_err(|e| config::Error::FailedToReadConfig { - config_path: global_config_path.clone(), - error: e, - })? - .unwrap_or_else(|| String::from("{}")); - - let after = set_path(&before, &["token"], &format!("\"{}\"", token.into_inner()))?; - - global_config_path - .ensure_dir() - .map_err(|e| config::Error::FailedToSetConfig { - config_path: global_config_path.clone(), - error: e, - })?; - - global_config_path - .create_with_contents(after) - .map_err(|e| config::Error::FailedToSetConfig { - config_path: global_config_path.clone(), - error: e, - })?; - - Ok(()) -} - -pub async fn login( - base: &mut CommandBase, - telemetry: CommandEventBuilder, - force: bool, -) -> Result<(), Error> { - let mut login_telemetry = LoginTelemetry::new(&telemetry, LoginMethod::Standard); - - let api_client: APIClient = base.api_client()?; - let color_config = base.color_config; - let login_url_config = base.opts.api_client_opts.login_url.to_string(); - let existing_token = base.opts.api_client_opts.token.as_deref(); - - let options = LoginOptions { - existing_token, - force, - ..LoginOptions::new( - &color_config, - &login_url_config, - &api_client, - &DefaultLoginServer, - ) - }; - - let token = auth_login(&options).await?; - - // Don't write to disk if the token is already there - if matches!(token, Token::Existing(..)) { - return Ok(()); - } - - let global_config_path = base.global_config_path()?; - let before = global_config_path - .read_existing_to_string() - .map_err(|e| config::Error::FailedToReadConfig { - config_path: global_config_path.clone(), - error: e, - })? - .unwrap_or_else(|| String::from("{}")); - let after = set_path(&before, &["token"], &format!("\"{}\"", token.into_inner()))?; - - global_config_path - .ensure_dir() - .map_err(|e| config::Error::FailedToSetConfig { - config_path: global_config_path.clone(), - error: e, - })?; - - global_config_path - .create_with_contents(after) - .map_err(|e| config::Error::FailedToSetConfig { - config_path: global_config_path.clone(), - error: e, - })?; - - login_telemetry.set_success(true); - Ok(()) -} - -struct LoginTelemetry<'a> { - telemetry: &'a CommandEventBuilder, - method: LoginMethod, - success: bool, -} -impl<'a> LoginTelemetry<'a> { - fn new(telemetry: &'a CommandEventBuilder, method: LoginMethod) -> Self { - Self { - telemetry, - method, - success: false, - } - } - fn set_success(&mut self, success: bool) { - self.success = success; - } -} -// If we get an early return, we still want to track the login attempt as a -// failure. -impl<'a> Drop for LoginTelemetry<'a> { - fn drop(&mut self) { - self.telemetry.track_login_method(self.method); - self.telemetry.track_login_success(self.success); - } -} diff --git a/crates/turborepo-lib/src/commands/logout.rs b/crates/turborepo-lib/src/commands/logout.rs deleted file mode 100644 index a9566c0f9cb32..0000000000000 --- a/crates/turborepo-lib/src/commands/logout.rs +++ /dev/null @@ -1,18 +0,0 @@ -use turborepo_auth::{logout as auth_logout, LogoutOptions}; -use turborepo_telemetry::events::command::CommandEventBuilder; - -use crate::{cli::Error, commands::CommandBase}; - -pub async fn logout( - base: &mut CommandBase, - invalidate: bool, - _telemetry: CommandEventBuilder, -) -> Result<(), Error> { - auth_logout(&LogoutOptions { - color_config: base.color_config, - api_client: base.api_client()?, - invalidate, - }) - .await - .map_err(Error::from) -} diff --git a/crates/turborepo-lib/src/commands/query.rs b/crates/turborepo-lib/src/commands/query.rs deleted file mode 100644 index 6b896d519406a..0000000000000 --- a/crates/turborepo-lib/src/commands/query.rs +++ /dev/null @@ -1,116 +0,0 @@ -use std::{fs, sync::Arc}; - -use async_graphql::{EmptyMutation, EmptySubscription, Request, Schema, ServerError, Variables}; -use camino::Utf8Path; -use miette::{Diagnostic, Report, SourceSpan}; -use thiserror::Error; -use turbopath::AbsoluteSystemPathBuf; -use turborepo_telemetry::events::command::CommandEventBuilder; - -use crate::{ - commands::{run::get_signal, CommandBase}, - query, - query::{Error, RepositoryQuery}, - run::builder::RunBuilder, - signal::SignalHandler, -}; - -#[derive(Debug, Diagnostic, Error)] -#[error("{message}")] -struct QueryError { - message: String, - #[source_code] - query: String, - #[label] - span: Option, - #[label] - span2: Option, - #[label] - span3: Option, -} - -impl QueryError { - fn get_index_from_row_column(query: &str, row: usize, column: usize) -> usize { - let mut index = 0; - for line in query.lines().take(row.saturating_sub(1)) { - index += line.len() + 1; - } - index + column - 1 - } - fn new(server_error: ServerError, query: String) -> Self { - let span: Option = server_error.locations.first().map(|location| { - let idx = - Self::get_index_from_row_column(query.as_ref(), location.line, location.column); - (idx, idx + 1).into() - }); - - QueryError { - message: server_error.message, - query, - span, - span2: None, - span3: None, - } - } -} - -pub async fn run( - base: CommandBase, - telemetry: CommandEventBuilder, - query: Option, - variables_path: Option<&Utf8Path>, -) -> Result { - let signal = get_signal()?; - let handler = SignalHandler::new(signal); - - let run_builder = RunBuilder::new(base)? - .add_all_tasks() - .do_not_validate_engine(); - let run = run_builder.build(&handler, telemetry).await?; - - if let Some(query) = query { - let trimmed_query = query.trim(); - // If the arg starts with "query" or "mutation", and ends in a bracket, it's - // likely a direct query If it doesn't, it's a file path, so we need to - // read it - let query = if (trimmed_query.starts_with("query") - || trimmed_query.starts_with("mutation") - || trimmed_query.starts_with('{')) - && trimmed_query.ends_with('}') - { - query - } else { - fs::read_to_string(AbsoluteSystemPathBuf::from_unknown(run.repo_root(), query))? - }; - - let schema = Schema::new( - RepositoryQuery::new(Arc::new(run)), - EmptyMutation, - EmptySubscription, - ); - - let variables: Variables = variables_path - .map(AbsoluteSystemPathBuf::from_cwd) - .transpose()? - .map(|path| path.read_to_string()) - .transpose()? - .map(|content| serde_json::from_str(&content)) - .transpose()? - .unwrap_or_default(); - - let request = Request::new(&query).variables(variables); - - let result = schema.execute(request).await; - println!("{}", serde_json::to_string_pretty(&result)?); - if !result.errors.is_empty() { - for error in result.errors { - let error = QueryError::new(error, query.clone()); - eprintln!("{:?}", Report::new(error)); - } - } - } else { - query::run_query_server(run, handler).await?; - } - - Ok(0) -} diff --git a/crates/turborepo-lib/src/commands/run.rs b/crates/turborepo-lib/src/commands/run.rs deleted file mode 100644 index b3b6e5dada7c9..0000000000000 --- a/crates/turborepo-lib/src/commands/run.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::{future::Future, sync::Arc}; - -use tracing::error; -use turborepo_telemetry::events::command::CommandEventBuilder; -use turborepo_ui::sender::UISender; - -use crate::{commands::CommandBase, run, run::builder::RunBuilder, signal::SignalHandler}; - -#[cfg(windows)] -pub fn get_signal() -> Result>, run::Error> { - let mut ctrl_c = tokio::signal::windows::ctrl_c().map_err(run::Error::SignalHandler)?; - Ok(async move { ctrl_c.recv().await }) -} - -#[cfg(not(windows))] -pub fn get_signal() -> Result>, run::Error> { - use tokio::signal::unix; - let mut sigint = - unix::signal(unix::SignalKind::interrupt()).map_err(run::Error::SignalHandler)?; - let mut sigterm = - unix::signal(unix::SignalKind::terminate()).map_err(run::Error::SignalHandler)?; - - Ok(async move { - tokio::select! { - res = sigint.recv() => { - res - } - res = sigterm.recv() => { - res - } - } - }) -} - -pub async fn run(base: CommandBase, telemetry: CommandEventBuilder) -> Result { - let signal = get_signal()?; - let handler = SignalHandler::new(signal); - - let run_builder = RunBuilder::new(base)?; - - let run_fut = async { - let (analytics_sender, analytics_handle) = run_builder.start_analytics(); - let run = Arc::new( - run_builder - .with_analytics_sender(analytics_sender) - .build(&handler, telemetry) - .await?, - ); - - let (sender, handle) = run.start_ui()?.unzip(); - - let result = run.run(sender.clone(), false).await; - - if let Some(analytics_handle) = analytics_handle { - analytics_handle.close_with_timeout().await; - } - - // We only stop if it's the TUI, for the web UI we don't need to stop - if let Some(UISender::Tui(sender)) = sender { - sender.stop().await; - } - - if let Some(handle) = handle { - if let Err(e) = handle.await.expect("render thread panicked") { - error!("error encountered rendering tui: {e}"); - } - } - - result - }; - - let handler_fut = handler.done(); - tokio::select! { - biased; - // If we get a handler exit at the same time as a run finishes we choose that - // future to display that we're respecting user input - _ = handler_fut => { - // We caught a signal, which already notified the subscribers - Ok(1) - } - result = run_fut => { - // Run finished so close the signal handler - handler.close().await; - result - }, - } -} diff --git a/crates/turborepo-lib/src/commands/scan.rs b/crates/turborepo-lib/src/commands/scan.rs deleted file mode 100644 index 65fd0a2c656ca..0000000000000 --- a/crates/turborepo-lib/src/commands/scan.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::{sync::LazyLock, time::Duration}; - -use console::{style, Style}; -use futures::StreamExt; -use tokio_stream::StreamMap; -use turborepo_ui::*; - -use super::CommandBase; -use crate::{diagnostics::*, DaemonPaths}; - -// can't use LazyCell since DialoguerTheme isn't Sync -static DIALOGUER_THEME: LazyLock = LazyLock::new(|| DialoguerTheme { - prompt_prefix: style(">>>".to_string()).bright().for_stderr(), - active_item_prefix: style(" â¯".to_string()).for_stderr().green(), - inactive_item_prefix: style(" ".to_string()).for_stderr(), - success_prefix: style(" ".to_string()).for_stderr(), - prompt_style: Style::new().for_stderr(), - ..Default::default() -}); - -/// diagnostics run in parallel however to prevent messages from appearing too -/// quickly we introduce a minimum delay between each message -const INTER_MESSAGE_DELAY: Duration = Duration::from_millis(30); - -/// Start a diagnostic session. This command will run a series of diagnostics to -/// help you identify potential performance bottlenecks in your monorepo. -/// -/// Note: all lints happen in parallel. For the purposes of displaying output, -/// we demultiplex the output and display it in a single stream, meaning -/// to the user, it looks like the lints are running serially. -pub async fn run(base: CommandBase) -> bool { - let paths = DaemonPaths::from_repo_root(&base.repo_root); - let color_config = base.color_config; - - println!("\n{}\n", color_config.rainbow(">>> TURBO SCAN")); - println!( - "Turborepo does a lot of work behind the scenes to make your monorepo fast, -however, there are some things you can do to make it even faster. {}\n", - color!(color_config, BOLD_GREEN, "Let's go!") - ); - - let mut all_events = StreamMap::new(); - - let d1 = Box::new(DaemonDiagnostic(paths.clone())); - let d2 = Box::new(LSPDiagnostic(paths)); - let d3 = Box::new(GitDaemonDiagnostic); - let d5 = Box::new(UpdateDiagnostic(base.repo_root.clone())); - let d4 = Box::new(RemoteCacheDiagnostic::new(base)); - - let diags: Vec> = vec![d1, d2, d3, d4, d5]; - let num_tasks: usize = diags.len(); - for diag in diags { - let name = diag.name(); - let (tx, rx) = DiagnosticChannel::new(); - diag.execute(tx); - let wrapper = tokio_stream::wrappers::ReceiverStream::new(rx); - all_events.insert(name, wrapper); - } - - let mut complete = 0; - let mut failed = 0; - let mut not_applicable = 0; - - while let Some((diag, message)) = all_events.next().await { - use DiagnosticMessage::*; - - let mut diag_events = all_events.remove(diag).expect("stream not found in map"); - - // the allowed opening message is 'started' - let human_name = match message { - Started(human_name) => human_name, - _other => { - panic!("this is a programming error, please report an issue"); - } - }; - - let bar = start_spinner(&human_name); - - while let Some(message) = diag_events.next().await { - match message { - Started(_) => {} // ignore duplicate start events - LogLine(line) => { - bar.println(color!(color_config, GREY, " {}", line).to_string()); - } - Request(prompt, mut options, chan) => { - let opt = bar.suspend(|| { - dialoguer::Select::with_theme(&*DIALOGUER_THEME) - .with_prompt(prompt) - .items(&options) - .default(0) - .interact() - .unwrap() - }); - - chan.send(options.swap_remove(opt)).unwrap(); - } - Suspend(stopped, resume) => { - let bar = bar.clone(); - let handle = tokio::task::spawn_blocking(move || { - bar.suspend(|| { - // sender is dropped, so we can unsuspend - resume.blocking_recv().ok(); - }); - }); - stopped.send(()).ok(); // suspender doesn't need to be notified so failing ok - handle.await.expect("panic in suspend task"); - } - Done(message) => { - bar.finish_with_message( - color!(color_config, BOLD_GREEN, "{}", message).to_string(), - ); - complete += 1; - } - Failed(message) => { - bar.finish_with_message( - color!(color_config, BOLD_RED, "{}", message).to_string(), - ); - failed += 1; - } - NotApplicable(name) => { - let n_a = color!(color_config, GREY, "n/a").to_string(); - let style = bar.style().tick_strings(&[&n_a, &n_a]); - bar.set_style(style); - bar.finish_with_message( - color!(color_config, BOLD_GREY, "{}", name).to_string(), - ); - not_applicable += 1; - } - }; - if complete + not_applicable + failed == num_tasks { - break; - } - tokio::time::sleep(INTER_MESSAGE_DELAY).await; - } - } - - if complete + not_applicable == num_tasks { - println!("\n\n{}", color_config.rainbow(">>> FULL TURBO")); - true - } else { - false - } -} diff --git a/crates/turborepo-lib/src/commands/telemetry.rs b/crates/turborepo-lib/src/commands/telemetry.rs deleted file mode 100644 index d00a03b1e1b0f..0000000000000 --- a/crates/turborepo-lib/src/commands/telemetry.rs +++ /dev/null @@ -1,80 +0,0 @@ -use turborepo_telemetry::{config::TelemetryConfig, events::command::CommandEventBuilder}; -use turborepo_ui::{color, BOLD, BOLD_GREEN, BOLD_RED}; - -use super::CommandBase; -use crate::cli::TelemetryCommand; - -fn log_status(config: TelemetryConfig, base: &CommandBase) { - let status = config.is_enabled(); - match status { - true => { - println!( - "\nStatus: {}", - base.color_config.apply(BOLD_GREEN.apply_to("Enabled")) - ); - println!("\nTurborepo telemetry is completely anonymous. Thank you for participating!"); - } - false => { - println!( - "\nStatus: {}", - base.color_config.apply(BOLD_RED.apply_to("Disabled")) - ); - println!( - "\nYou have opted-out of Turborepo anonymous telemetry. No data will be collected \ - from your machine." - ); - } - } - println!("Learn more: https://turbo.build/repo/docs/telemetry"); -} - -fn log_error(message: &str, error: &str, base: &CommandBase) { - println!( - "{}: {}", - color!(base.color_config, BOLD_RED, "{}", message), - color!(base.color_config, BOLD_RED, "{}", error) - ); -} - -pub fn configure( - command: &Option, - base: &mut CommandBase, - telemetry: CommandEventBuilder, -) { - let config = TelemetryConfig::with_default_config_path(); - let mut config = match config { - Ok(config) => config, - Err(e) => { - log_error("Failed to load telemetry config", &e.to_string(), base); - return; - } - }; - - match command { - Some(TelemetryCommand::Enable) => { - let result = config.enable(); - match result { - Ok(_) => { - println!("{}", color!(base.color_config, BOLD, "{}", "Success!")); - log_status(config, base); - telemetry.track_telemetry_config(true); - } - Err(e) => log_error("Failed to enable telemetry", &e.to_string(), base), - } - } - Some(TelemetryCommand::Disable) => { - let result = config.disable(); - match result { - Ok(_) => { - println!("{}", color!(base.color_config, BOLD, "{}", "Success!")); - log_status(config, base); - telemetry.track_telemetry_config(false); - } - Err(e) => log_error("Failed to disable telemetry", &e.to_string(), base), - } - } - _ => { - log_status(config, base); - } - } -} diff --git a/crates/turborepo-lib/src/commands/unlink.rs b/crates/turborepo-lib/src/commands/unlink.rs deleted file mode 100644 index c532103bf3a03..0000000000000 --- a/crates/turborepo-lib/src/commands/unlink.rs +++ /dev/null @@ -1,134 +0,0 @@ -use std::fs; - -use turborepo_ui::GREY; - -use crate::{ - cli, - cli::{Error, LinkTarget}, - commands::CommandBase, - config, - rewrite_json::unset_path, -}; - -enum UnlinkSpacesResult { - Unlinked, - NoSpacesFound, -} - -fn unlink_remote_caching(base: &mut CommandBase) -> Result<(), cli::Error> { - let needs_disabling = base.opts.api_client_opts.team_id.is_some() - || base.opts.api_client_opts.team_slug.is_some(); - - let output = if needs_disabling { - let local_config_path = base.local_config_path(); - - let before = local_config_path - .read_existing_to_string() - .map_err(|error| config::Error::FailedToReadConfig { - config_path: local_config_path.clone(), - error, - })? - .unwrap_or_else(|| String::from("{}")); - let no_id = unset_path(&before, &["teamid"], false)?.unwrap_or(before); - let no_slug = unset_path(&no_id, &["teamslug"], false)?.unwrap_or(no_id); - - local_config_path - .ensure_dir() - .map_err(|error| config::Error::FailedToSetConfig { - config_path: local_config_path.clone(), - error, - })?; - - local_config_path - .create_with_contents(no_slug) - .map_err(|error| config::Error::FailedToSetConfig { - config_path: local_config_path.clone(), - error, - })?; - - "> Disabled Remote Caching" - } else { - "> No Remote Caching config found" - }; - - println!("{}", base.color_config.apply(GREY.apply_to(output))); - - Ok(()) -} - -fn unlink_spaces(base: &mut CommandBase) -> Result<(), cli::Error> { - let needs_disabling = base.opts().api_client_opts.team_id.is_some() - || base.opts().api_client_opts.team_slug.is_some(); - - if needs_disabling { - let local_config_path = base.local_config_path(); - let before = local_config_path - .read_existing_to_string() - .map_err(|e| config::Error::FailedToReadConfig { - config_path: local_config_path.clone(), - error: e, - })? - .unwrap_or_else(|| String::from("{}")); - let no_id = unset_path(&before, &["teamid"], false)?.unwrap_or(before); - let no_slug = unset_path(&no_id, &["teamslug"], false)?.unwrap_or(no_id); - - local_config_path - .ensure_dir() - .map_err(|e| config::Error::FailedToSetConfig { - config_path: local_config_path.clone(), - error: e, - })?; - - local_config_path - .create_with_contents(no_slug) - .map_err(|e| config::Error::FailedToSetConfig { - config_path: local_config_path.clone(), - error: e, - })?; - } - - // Space config is _also_ in turbo.json. - let result = remove_spaces_from_turbo_json(base)?; - - let output = match (needs_disabling, result) { - (_, UnlinkSpacesResult::Unlinked) => "> Unlinked Spaces", - (true, _) => "> Unlinked Spaces", - (false, UnlinkSpacesResult::NoSpacesFound) => "> No Spaces config found", - }; - - println!("{}", base.color_config.apply(GREY.apply_to(output))); - - Ok(()) -} - -pub fn unlink(base: &mut CommandBase, target: LinkTarget) -> Result<(), cli::Error> { - match target { - LinkTarget::RemoteCache => { - unlink_remote_caching(base)?; - } - LinkTarget::Spaces => { - unlink_spaces(base)?; - } - } - Ok(()) -} - -fn remove_spaces_from_turbo_json(base: &CommandBase) -> Result { - let turbo_json_path = base.repo_root.join_component("turbo.json"); - let turbo_json = - fs::read_to_string(&turbo_json_path).map_err(|e| config::Error::FailedToReadConfig { - config_path: turbo_json_path.clone(), - error: e, - })?; - - let output = unset_path(&turbo_json, &["experimentalSpaces", "id"], true)?; - if let Some(output) = output { - fs::write(&turbo_json_path, output).map_err(|e| config::Error::FailedToSetConfig { - config_path: turbo_json_path.clone(), - error: e, - })?; - Ok(UnlinkSpacesResult::Unlinked) - } else { - Ok(UnlinkSpacesResult::NoSpacesFound) - } -} diff --git a/crates/turborepo-lib/src/config/file.rs b/crates/turborepo-lib/src/config/file.rs deleted file mode 100644 index d3f889bd293dc..0000000000000 --- a/crates/turborepo-lib/src/config/file.rs +++ /dev/null @@ -1,103 +0,0 @@ -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; -use turborepo_auth::{TURBO_TOKEN_DIR, TURBO_TOKEN_FILE, VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE}; -use turborepo_dirs::{config_dir, vercel_config_dir}; - -use super::{ConfigurationOptions, Error, ResolvedConfigurationOptions}; - -pub struct ConfigFile { - path: AbsoluteSystemPathBuf, -} - -impl ConfigFile { - pub fn global_config(override_path: Option) -> Result { - let path = override_path.map_or_else(global_config_path, Ok)?; - Ok(Self { path }) - } - - pub fn local_config(repo_root: &AbsoluteSystemPath) -> Self { - let path = repo_root.join_components(&[".turbo", "config.json"]); - Self { path } - } -} - -impl ResolvedConfigurationOptions for ConfigFile { - fn get_configuration_options( - &self, - _existing_config: &ConfigurationOptions, - ) -> Result { - let contents = self - .path - .read_existing_to_string() - .map_err(|error| Error::FailedToReadConfig { - config_path: self.path.clone(), - error, - })? - .filter(|s| !s.is_empty()); - - let global_config = contents - .as_deref() - .map_or_else(|| Ok(ConfigurationOptions::default()), serde_json::from_str)?; - Ok(global_config) - } -} - -pub struct AuthFile { - path: AbsoluteSystemPathBuf, -} - -impl AuthFile { - pub fn global_auth(override_path: Option) -> Result { - let path = override_path.map_or_else(global_auth_path, Ok)?; - Ok(Self { path }) - } -} - -impl ResolvedConfigurationOptions for AuthFile { - fn get_configuration_options( - &self, - _existing_config: &ConfigurationOptions, - ) -> Result { - let token = match turborepo_auth::Token::from_file(&self.path) { - Ok(token) => token, - // Multiple ways this can go wrong. Don't error out if we can't find the token - it - // just might not be there. - Err(e) => { - if matches!(e, turborepo_auth::Error::TokenNotFound) { - return Ok(ConfigurationOptions::default()); - } - - return Err(e.into()); - } - }; - - // No auth token found in either Vercel or Turbo config. - if token.into_inner().is_empty() { - return Ok(ConfigurationOptions::default()); - } - - let global_auth: ConfigurationOptions = ConfigurationOptions { - token: Some(token.into_inner().to_owned()), - ..Default::default() - }; - Ok(global_auth) - } -} - -fn global_config_path() -> Result { - let config_dir = config_dir()?.ok_or(Error::NoGlobalConfigPath)?; - - Ok(config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE])) -} - -fn global_auth_path() -> Result { - let vercel_config_dir = vercel_config_dir()?.ok_or(Error::NoGlobalConfigDir)?; - // Check for both Vercel and Turbo paths. Vercel takes priority. - let vercel_path = vercel_config_dir.join_components(&[VERCEL_TOKEN_DIR, VERCEL_TOKEN_FILE]); - if vercel_path.exists() { - return Ok(vercel_path); - } - - let turbo_config_dir = config_dir()?.ok_or(Error::NoGlobalConfigDir)?; - - Ok(turbo_config_dir.join_components(&[TURBO_TOKEN_DIR, TURBO_TOKEN_FILE])) -} diff --git a/crates/turborepo-lib/src/config/override_env.rs b/crates/turborepo-lib/src/config/override_env.rs deleted file mode 100644 index 9ae4f1f0b3b54..0000000000000 --- a/crates/turborepo-lib/src/config/override_env.rs +++ /dev/null @@ -1,446 +0,0 @@ -use std::{ - collections::HashMap, - ffi::{OsStr, OsString}, -}; - -use super::{env::truth_env_var, ConfigurationOptions, Error, ResolvedConfigurationOptions}; -use crate::turbo_json::UIMode; - -/* -Hi! If you're new here: -1. The general pattern is that: - - ConfigurationOptions.token corresponds to TURBO_TOKEN or VERCEL_ARTIFACTS_TOKEN - - ConfigurationOptions.team_id corresponds to TURBO_TEAMID or VERCEL_ARTIFACTS_OWNER - - ConfigurationOptions.team_slug corresponds to TURBO_TEAM -1. We're ultimately poking around the env vars looking for _pairs_ that make sense. - Since we presume that users are the only ones sending TURBO_* and Vercel is the only one sending VERCEL_*, we can make some assumptions. Namely, we assume that if we have one of VERCEL_ARTIFACTS_OWNER or VERCEL_ARTIFACTS_TOKEN we will always have both. -1. Watch out for mixing up `TURBO_TEAM` and `TURBO_TEAMID`. Same for ConfigurationOptions.team_id and ConfigurationOptions.team_slug. -*/ - -/// these correspond directly to the environment variables that this module -/// needs to do it's work -#[allow(non_snake_case)] -#[derive(Default, Debug, PartialEq)] -struct Input { - TURBO_TEAM: Option, - TURBO_TEAMID: Option, - TURBO_TOKEN: Option, - VERCEL_ARTIFACTS_OWNER: Option, - VERCEL_ARTIFACTS_TOKEN: Option, -} - -impl Input { - fn new() -> Self { - Self::default() - } -} - -impl<'a> TryFrom<&'a HashMap> for Input { - type Error = Error; - - fn try_from(environment: &'a HashMap) -> Result { - let get_value = |key: &str| -> Result, Error> { - let Some(value) = environment.get(OsStr::new(key)) else { - return Ok(None); - }; - let value = value - .to_str() - .ok_or_else(|| Error::Encoding(key.to_ascii_uppercase()))?; - Ok(Some(value.to_string())) - }; - Ok(Self { - TURBO_TEAM: get_value("turbo_team")?, - TURBO_TEAMID: get_value("turbo_teamid")?, - TURBO_TOKEN: get_value("turbo_token")?, - VERCEL_ARTIFACTS_OWNER: get_value("vercel_artifacts_owner")?, - VERCEL_ARTIFACTS_TOKEN: get_value("vercel_artifacts_token")?, - }) - } -} - -// this is an internal structure (that's a partial of ConfigurationOptions) that -// we use to store -struct Output { - /// maps to ConfigurationOptions.team_id - team_id: Option, - // maps to ConfigurationOptions.team_slug - team_slug: Option, - // maps to ConfigurationOptions.token - token: Option, -} - -impl Output { - fn new() -> Self { - Self { - team_id: None, - team_slug: None, - token: None, - } - } -} - -impl From for Output { - fn from(input: Input) -> Self { - // TURBO_TEAMID+TURBO_TOKEN or TURBO_TEAM+TURBO_TOKEN - if input.TURBO_TOKEN.is_some() - && (input.TURBO_TEAMID.is_some() || input.TURBO_TEAM.is_some()) - { - Output { - team_id: input.TURBO_TEAMID, - team_slug: input.TURBO_TEAM, - token: input.TURBO_TOKEN, - } - } - // if there's both Vercel items, we use those next - else if input.VERCEL_ARTIFACTS_TOKEN.is_some() && input.VERCEL_ARTIFACTS_OWNER.is_some() { - Output { - team_id: input.VERCEL_ARTIFACTS_OWNER, - team_slug: input.TURBO_TEAM, /* this may or may not be Some, but if it is we can - * pass it along too */ - token: input.VERCEL_ARTIFACTS_TOKEN, - } - } - // from this point below, there's no token we can do anything with - // ------------------------------------------------ - else { - Output { - // prefer TURBO_TEAMID to VERCEL_ARTIFACTS_OWNER - team_id: input.TURBO_TEAMID.or(input.VERCEL_ARTIFACTS_OWNER), - // No alternative source for team_slug so always use TURBO_TEAM - team_slug: input.TURBO_TEAM, - token: None, - } - } - } -} - -pub struct OverrideEnvVars<'a> { - environment: &'a HashMap, - output: Output, -} - -impl<'a> OverrideEnvVars<'a> { - pub fn new(environment: &'a HashMap) -> Result { - let input = Input::try_from(environment)?; - let output = Output::from(input); - - Ok(Self { - environment, - output, - }) - } - - fn ui(&self) -> Option { - let value = self - .environment - .get(OsStr::new("ci")) - .or_else(|| self.environment.get(OsStr::new("no_color")))?; - truth_env_var(value.to_str()?)?.then_some(UIMode::Stream) - } -} - -impl<'a> ResolvedConfigurationOptions for OverrideEnvVars<'a> { - fn get_configuration_options( - &self, - _existing_config: &ConfigurationOptions, - ) -> Result { - let output = ConfigurationOptions { - team_id: self.output.team_id.clone(), - token: self.output.token.clone(), - team_slug: self.output.team_slug.clone(), - ui: self.ui(), - ..Default::default() - }; - Ok(output) - } -} - -#[cfg(test)] -mod test { - use super::*; - - const VERCEL_ARTIFACTS_OWNER: &str = "valueof:VERCEL_ARTIFACTS_OWNER"; - const VERCEL_ARTIFACTS_TOKEN: &str = "valueof:VERCEL_ARTIFACTS_TOKEN"; - const TURBO_TEAMID: &str = "valueof:TURBO_TEAMID"; - const TURBO_TEAM: &str = "valueof:TURBO_TEAM"; - const TURBO_TOKEN: &str = "valueof:TURBO_TOKEN"; - - struct TestCase { - input: Input, - output: Output, - reason: &'static str, - } - - impl TestCase { - fn new() -> Self { - Self { - input: Input::new(), - output: Output::new(), - reason: "missing", - } - } - - fn reason(mut self, reason: &'static str) -> Self { - self.reason = reason; - self - } - - #[allow(non_snake_case)] - fn VERCEL_ARTIFACTS_OWNER(mut self) -> Self { - self.input.VERCEL_ARTIFACTS_OWNER = Some(VERCEL_ARTIFACTS_OWNER.into()); - self - } - - #[allow(non_snake_case)] - fn VERCEL_ARTIFACTS_TOKEN(mut self) -> Self { - self.input.VERCEL_ARTIFACTS_TOKEN = Some(VERCEL_ARTIFACTS_TOKEN.into()); - self - } - - #[allow(non_snake_case)] - fn TURBO_TEAMID(mut self) -> Self { - self.input.TURBO_TEAMID = Some(TURBO_TEAMID.into()); - self - } - - #[allow(non_snake_case)] - fn TURBO_TEAM(mut self) -> Self { - self.input.TURBO_TEAM = Some(TURBO_TEAM.into()); - self - } - - #[allow(non_snake_case)] - fn TURBO_TOKEN(mut self) -> Self { - self.input.TURBO_TOKEN = Some(TURBO_TOKEN.into()); - self - } - - fn team_id(mut self, value: &str) -> Self { - self.output.team_id = Some(value.into()); - self - } - - fn team_slug(mut self, value: &str) -> Self { - self.output.team_slug = Some(value.into()); - self - } - - fn token(mut self, value: &str) -> Self { - self.output.token = Some(value.into()); - self - } - } - - #[test] - fn test_all_the_combos() { - let cases: &[TestCase] = &[ - // - // Get nothing back - // ------------------------------ - TestCase::new().reason("no env vars set"), - TestCase::new() - .reason("just VERCEL_ARTIFACTS_TOKEN") - .VERCEL_ARTIFACTS_TOKEN(), - TestCase::new().reason("just TURBO_TOKEN").TURBO_TOKEN(), - // - // When 3rd Party Wins with all three - // ------------------------------ - TestCase::new() - .reason("we can use all of TURBO_TEAM, TURBO_TEAMID, and TURBO_TOKEN") - .TURBO_TEAM() - .TURBO_TEAMID() - .TURBO_TOKEN() - .team_id(TURBO_TEAMID) - .team_slug(TURBO_TEAM) - .token(TURBO_TOKEN), - TestCase::new() - .reason("if we have a 3rd party trifecta, that wins, even against a Vercel Pair") - .TURBO_TEAM() - .TURBO_TEAMID() - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_OWNER() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(TURBO_TEAMID) - .team_slug(TURBO_TEAM) - .token(TURBO_TOKEN), - TestCase::new() - .reason("a 3rd party trifecta wins against a partial Vercel (just artifacts token)") - .TURBO_TEAM() - .TURBO_TEAMID() - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(TURBO_TEAMID) - .team_slug(TURBO_TEAM) - .token(TURBO_TOKEN), - TestCase::new() - .reason("a 3rd party trifecta wins against a partial Vercel (just artifacts owner)") - .TURBO_TEAM() - .TURBO_TEAMID() - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_OWNER() - .team_id(TURBO_TEAMID) - .team_slug(TURBO_TEAM) - .token(TURBO_TOKEN), - // - // When 3rd Party Wins with team_slug - // ------------------------------ - TestCase::new() - .reason("golden path for 3rd party, not deployed on Vercel") - .TURBO_TEAM() - .TURBO_TOKEN() - .team_slug(TURBO_TEAM) - .token(TURBO_TOKEN), - TestCase::new() - .reason( - "a TURBO_TEAM+TURBO_TOKEN pair wins against an incomplete Vercel (just \ - artifacts token)", - ) - .TURBO_TEAM() - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_TOKEN() // disregarded - .team_slug(TURBO_TEAM) - .token(TURBO_TOKEN), - TestCase::new() - .reason("golden path for 3rd party, deployed on Vercel") - .TURBO_TEAM() - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_OWNER() // normally this would map to team_id, but not with a complete 3rd party pair - .VERCEL_ARTIFACTS_TOKEN() - .team_slug(TURBO_TEAM) - .token(TURBO_TOKEN), - // - // When 3rd Party Wins with team_id - // ------------------------------ - TestCase::new() - .reason("if they pass a TURBO_TEAMID and a TURBO_TOKEN, we use them") - .TURBO_TEAMID() - .TURBO_TOKEN() - .team_id(TURBO_TEAMID) - .token(TURBO_TOKEN), - TestCase::new() - .reason("a TURBO_TEAMID+TURBO_TOKEN pair will also win against a Vercel pair") - .TURBO_TEAMID() - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_OWNER() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(TURBO_TEAMID) - .token(TURBO_TOKEN), - TestCase::new() - .reason( - "a TURBO_TEAMID+TURBO_TOKEN pair wins against an incomplete Vercel (just \ - artifacts token)", - ) - .TURBO_TEAMID() - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(TURBO_TEAMID) - .token(TURBO_TOKEN), - // - // When Vercel Wins - // ------------------------------ - TestCase::new() - .reason("golden path on Vercel zero config") - .VERCEL_ARTIFACTS_OWNER() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(VERCEL_ARTIFACTS_OWNER) - .token(VERCEL_ARTIFACTS_TOKEN), - TestCase::new() - .reason("Vercel wins: disregard just TURBO_TOKEN") - .TURBO_TOKEN() - .VERCEL_ARTIFACTS_OWNER() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(VERCEL_ARTIFACTS_OWNER) - .token(VERCEL_ARTIFACTS_TOKEN), - TestCase::new() - .reason("Vercel wins: TURBO_TEAM can join in the fun if it wants") - .TURBO_TEAM() - .VERCEL_ARTIFACTS_OWNER() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(VERCEL_ARTIFACTS_OWNER) - .team_slug(TURBO_TEAM) - .token(VERCEL_ARTIFACTS_TOKEN), - TestCase::new() - .reason("Vercel wins: disregard just TURBO_TEAMID") - .TURBO_TEAMID() - .VERCEL_ARTIFACTS_OWNER() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(VERCEL_ARTIFACTS_OWNER) - .token(VERCEL_ARTIFACTS_TOKEN), - TestCase::new() - .reason("Vercel wins if TURBO_TOKEN is missing") - .TURBO_TEAM() - .TURBO_TEAMID() - .VERCEL_ARTIFACTS_OWNER() - .VERCEL_ARTIFACTS_TOKEN() - .team_id(VERCEL_ARTIFACTS_OWNER) - .team_slug(TURBO_TEAM) - .token(VERCEL_ARTIFACTS_TOKEN), - // - // Just get a team_id - // ------------------------------ - TestCase::new() - .reason("just VERCEL_ARTIFACTS_OWNER") - .VERCEL_ARTIFACTS_OWNER() - .team_id(VERCEL_ARTIFACTS_OWNER), - TestCase::new() - .reason("just TURBO_TEAMID") - .TURBO_TEAMID() - .team_id(TURBO_TEAMID), - // - // Just get a team_slug - // ------------------------------ - TestCase::new() - .reason("just TURBO_TEAM") - .TURBO_TEAM() - .team_slug(TURBO_TEAM), - // - // just team_slug and team_id - // ------------------------------ - TestCase::new() - .reason("if we just have TURBO_TEAM+TURBO_TEAMID, that's ok") - .TURBO_TEAM() - .TURBO_TEAMID() - .team_slug(TURBO_TEAM) - .team_id(TURBO_TEAMID), - // - // just set team_id and team_slug - // ------------------------------ - TestCase::new() - .reason("if we just have a TURBO_TEAM and TURBO_TEAMID we can use them both") - .TURBO_TEAM() - .TURBO_TEAMID() - .team_id(TURBO_TEAMID) - .team_slug(TURBO_TEAM), - ]; - - for case in cases { - let mut env: HashMap = HashMap::new(); - - if let Some(value) = &case.input.TURBO_TEAM { - env.insert("turbo_team".into(), value.into()); - } - if let Some(value) = &case.input.TURBO_TEAMID { - env.insert("turbo_teamid".into(), value.into()); - } - if let Some(value) = &case.input.TURBO_TOKEN { - env.insert("turbo_token".into(), value.into()); - } - if let Some(value) = &case.input.VERCEL_ARTIFACTS_OWNER { - env.insert("vercel_artifacts_owner".into(), value.into()); - } - if let Some(value) = &case.input.VERCEL_ARTIFACTS_TOKEN { - env.insert("vercel_artifacts_token".into(), value.into()); - } - - let actual_input = Input::try_from(&env).unwrap(); - assert_eq!(case.input, actual_input); - - let config = OverrideEnvVars::new(&env).unwrap(); - let reason = case.reason; - - assert_eq!(case.output.team_id, config.output.team_id, "{reason}"); - assert_eq!(case.output.team_slug, config.output.team_slug, "{reason}"); - assert_eq!(case.output.token, config.output.token, "{reason}"); - } - } -} diff --git a/crates/turborepo-lib/src/config/turbo_json.rs b/crates/turborepo-lib/src/config/turbo_json.rs deleted file mode 100644 index ccec280d991c2..0000000000000 --- a/crates/turborepo-lib/src/config/turbo_json.rs +++ /dev/null @@ -1,171 +0,0 @@ -use camino::Utf8PathBuf; -use turbopath::{AbsoluteSystemPath, RelativeUnixPath}; - -use super::{ConfigurationOptions, Error, ResolvedConfigurationOptions}; -use crate::turbo_json::RawTurboJson; - -pub struct TurboJsonReader<'a> { - repo_root: &'a AbsoluteSystemPath, -} - -impl<'a> TurboJsonReader<'a> { - pub fn new(repo_root: &'a AbsoluteSystemPath) -> Self { - Self { repo_root } - } - - fn turbo_json_to_config_options( - turbo_json: RawTurboJson, - ) -> Result { - let mut opts = if let Some(remote_cache_options) = &turbo_json.remote_cache { - remote_cache_options.into() - } else { - ConfigurationOptions::default() - }; - - let cache_dir = if let Some(cache_dir) = turbo_json.cache_dir { - let cache_dir_str: &str = &cache_dir; - let cache_dir_unix = RelativeUnixPath::new(cache_dir_str).map_err(|_| { - let (span, text) = cache_dir.span_and_text("turbo.json"); - Error::AbsoluteCacheDir { span, text } - })?; - // Convert the relative unix path to an anchored system path - // For unix/macos this is a no-op - let cache_dir_system = cache_dir_unix.to_anchored_system_path_buf(); - Some(Utf8PathBuf::from(cache_dir_system.to_string())) - } else { - None - }; - - // Don't allow token to be set for shared config. - opts.token = None; - opts.spaces_id = turbo_json - .experimental_spaces - .and_then(|spaces| spaces.id) - .map(|spaces_id| spaces_id.into()); - opts.ui = turbo_json.ui; - opts.allow_no_package_manager = turbo_json.allow_no_package_manager; - opts.daemon = turbo_json.daemon.map(|daemon| *daemon.as_inner()); - opts.env_mode = turbo_json.env_mode; - opts.cache_dir = cache_dir; - Ok(opts) - } -} - -impl<'a> ResolvedConfigurationOptions for TurboJsonReader<'a> { - fn get_configuration_options( - &self, - existing_config: &ConfigurationOptions, - ) -> Result { - let turbo_json_path = existing_config.root_turbo_json_path(self.repo_root); - let turbo_json = RawTurboJson::read(self.repo_root, &turbo_json_path).or_else(|e| { - if let Error::Io(e) = &e { - if matches!(e.kind(), std::io::ErrorKind::NotFound) { - return Ok(Default::default()); - } - } - - Err(e) - })?; - Self::turbo_json_to_config_options(turbo_json) - } -} - -#[cfg(test)] -mod test { - use serde_json::json; - use tempfile::tempdir; - - use super::*; - - #[test] - fn test_reads_from_default() { - let tmpdir = tempdir().unwrap(); - let repo_root = AbsoluteSystemPath::new(tmpdir.path().to_str().unwrap()).unwrap(); - - let existing_config = ConfigurationOptions { - ..Default::default() - }; - repo_root - .join_component("turbo.json") - .create_with_contents( - serde_json::to_string_pretty(&serde_json::json!({ - "daemon": false - })) - .unwrap(), - ) - .unwrap(); - - let reader = TurboJsonReader::new(repo_root); - let config = reader.get_configuration_options(&existing_config).unwrap(); - // Make sure we read the default turbo.json - assert_eq!(config.daemon(), Some(false)); - } - - #[test] - fn test_respects_root_turbo_json_config() { - let tmpdir = tempdir().unwrap(); - let tmpdir_path = AbsoluteSystemPath::new(tmpdir.path().to_str().unwrap()).unwrap(); - let root_turbo_json_path = tmpdir_path.join_component("yolo.json"); - let repo_root = AbsoluteSystemPath::new(if cfg!(windows) { - "C:\\my\\repo" - } else { - "/my/repo" - }) - .unwrap(); - let existing_config = ConfigurationOptions { - root_turbo_json_path: Some(root_turbo_json_path.to_owned()), - ..Default::default() - }; - root_turbo_json_path - .create_with_contents( - serde_json::to_string_pretty(&json!({ - "daemon": false - })) - .unwrap(), - ) - .unwrap(); - - let reader = TurboJsonReader::new(repo_root); - let config = reader.get_configuration_options(&existing_config).unwrap(); - // Make sure we read the correct turbo.json - assert_eq!(config.daemon(), Some(false)); - } - - #[test] - fn test_remote_cache_options() { - let timeout = 100; - let upload_timeout = 200; - let api_url = "localhost:3000"; - let login_url = "localhost:3001"; - let team_slug = "acme-packers"; - let team_id = "id-123"; - let turbo_json = RawTurboJson::parse( - &serde_json::to_string_pretty(&json!({ - "remoteCache": { - "enabled": true, - "timeout": timeout, - "uploadTimeout": upload_timeout, - "apiUrl": api_url, - "loginUrl": login_url, - "teamSlug": team_slug, - "teamId": team_id, - "signature": true, - "preflight": true - } - })) - .unwrap(), - "junk", - ) - .unwrap(); - let config = TurboJsonReader::turbo_json_to_config_options(turbo_json).unwrap(); - assert!(config.enabled()); - assert_eq!(config.timeout(), timeout); - assert_eq!(config.upload_timeout(), upload_timeout); - assert_eq!(config.api_url(), api_url); - assert_eq!(config.login_url(), login_url); - assert_eq!(config.team_slug(), Some(team_slug)); - assert_eq!(config.team_id(), Some(team_id)); - assert!(config.signature()); - assert!(config.preflight()); - } -} diff --git a/crates/turborepo-lib/src/daemon/bump_timeout.rs b/crates/turborepo-lib/src/daemon/bump_timeout.rs deleted file mode 100644 index f3a884d338460..0000000000000 --- a/crates/turborepo-lib/src/daemon/bump_timeout.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::{ - sync::atomic::{AtomicU64, Ordering}, - time::Duration, -}; - -use tokio::time::Instant; - -/// A timeout that can be bumped forward in time by calling reset. -/// -/// Calling reset with a new duration will change the deadline -/// to the current time plus the new duration. It is non-mutating -/// and can be called from multiple threads. -#[derive(Debug)] -pub struct BumpTimeout { - start: Instant, - increment: Duration, - deadline: AtomicU64, -} - -impl BumpTimeout { - #[allow(dead_code)] - pub fn new(increment: Duration) -> Self { - let start = Instant::now(); - let millis = increment.as_millis(); - Self { - start, - deadline: AtomicU64::new(millis as u64), - increment, - } - } - - pub fn duration(&self) -> Duration { - Duration::from_millis(self.deadline.load(Ordering::Relaxed)) - } - - #[allow(dead_code)] - pub fn deadline(&self) -> Instant { - self.start + self.duration() - } - - #[allow(dead_code)] - pub fn elapsed(&self) -> Duration { - self.start.elapsed() - } - - /// Resets the deadline to the current time plus the given duration. - pub fn reset(&self) { - let duration = self.start.elapsed() + self.increment; - self.deadline - .store(duration.as_millis() as u64, Ordering::Relaxed); - } - - #[allow(dead_code)] - pub fn as_instant(&self) -> Instant { - self.start + self.duration() - } - - /// Waits until the deadline is reached, but if the deadline is - /// changed while waiting, it will wait until the new deadline is reached. - #[allow(dead_code)] - pub async fn wait(&self) { - let mut deadline = self.as_instant(); - loop { - tokio::time::sleep_until(deadline).await; - let new_deadline = self.as_instant(); - - if new_deadline > deadline { - deadline = new_deadline; - } else { - break; - } - } - } -} diff --git a/crates/turborepo-lib/src/daemon/bump_timeout_layer.rs b/crates/turborepo-lib/src/daemon/bump_timeout_layer.rs deleted file mode 100644 index a3b1403bff1b9..0000000000000 --- a/crates/turborepo-lib/src/daemon/bump_timeout_layer.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! timeout_middleware -//! -//! This is middleware for tonic that integrates with bump_timeout to -//! continually reset the timeout when a request is received. - -use std::sync::Arc; - -use tonic::server::NamedService; -use tower::{Layer, Service}; - -use super::bump_timeout::BumpTimeout; - -/// A layer that resets a when a request is received. -pub struct BumpTimeoutLayer(Arc); - -impl BumpTimeoutLayer { - #[allow(dead_code)] - pub fn new(timeout: Arc) -> Self { - Self(timeout) - } -} - -impl Layer for BumpTimeoutLayer { - type Service = BumpTimeoutService; - - fn layer(&self, inner: S) -> Self::Service { - BumpTimeoutService { - inner, - timeout: self.0.clone(), - } - } -} - -#[derive(Clone)] -pub struct BumpTimeoutService { - inner: S, - timeout: Arc, -} - -impl Service for BumpTimeoutService -where - S: Service, -{ - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready( - &mut self, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, req: Request) -> Self::Future { - self.timeout.reset(); - self.inner.call(req) - } -} - -impl NamedService for BumpTimeoutService { - const NAME: &'static str = T::NAME; -} diff --git a/crates/turborepo-lib/src/daemon/client.rs b/crates/turborepo-lib/src/daemon/client.rs deleted file mode 100644 index c209abfc5fec7..0000000000000 --- a/crates/turborepo-lib/src/daemon/client.rs +++ /dev/null @@ -1,287 +0,0 @@ -use std::{io, time::Duration}; - -use globwalk::ValidatedGlob; -use miette::Diagnostic; -use thiserror::Error; -use tonic::{Code, IntoRequest, Status}; -use tracing::info; -use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPath}; - -use super::{ - connector::{DaemonConnector, DaemonConnectorError}, - endpoint::SocketOpenError, - proto::{DiscoverPackagesResponse, GetFileHashesResponse}, - Paths, -}; -use crate::{ - daemon::{proto, proto::PackageChangeEvent}, - globwatcher::HashGlobSetupError, -}; - -#[derive(Debug, Clone)] -pub struct DaemonClient { - client: proto::turbod_client::TurbodClient, - connect_settings: T, -} - -impl DaemonClient<()> { - pub fn new(client: proto::turbod_client::TurbodClient) -> Self { - Self { - client, - connect_settings: (), - } - } - - /// Augment the client with the connect settings, allowing it to be - /// restarted. - pub fn with_connect_settings( - self, - connect_settings: DaemonConnector, - ) -> DaemonClient { - DaemonClient { - client: self.client, - connect_settings, - } - } -} - -impl DaemonClient { - /// Interrogate the server for its version. - #[tracing::instrument(skip(self))] - pub(super) async fn handshake(&mut self) -> Result<(), DaemonError> { - let _ret = self - .client - .hello(proto::HelloRequest { - version: proto::VERSION.to_string(), - // minor version means that we need the daemon server to have at least the - // same features as us, but it can have more. it is unlikely that we will - // ever want to change the version range but we can tune it if, for example, - // we need to lock to a specific minor version. - supported_version_range: proto::VersionRange::Minor.into(), - // todo(arlyon): add session id - ..Default::default() - }) - .await?; - - Ok(()) - } - - /// Stops the daemon and closes the connection, returning - /// the connection settings that were used to connect. - pub async fn stop(mut self) -> Result { - info!("Stopping daemon"); - self.client.shutdown(proto::ShutdownRequest {}).await?; - Ok(self.connect_settings) - } - - pub async fn get_changed_outputs( - &mut self, - hash: String, - output_globs: &[ValidatedGlob], - ) -> Result, DaemonError> { - let output_globs = output_globs - .iter() - .map(|validated_glob| validated_glob.as_str().to_string()) - .collect(); - Ok(self - .client - .get_changed_outputs(proto::GetChangedOutputsRequest { hash, output_globs }) - .await? - .into_inner() - .changed_output_globs) - } - - pub async fn notify_outputs_written( - &mut self, - hash: String, - output_globs: &[ValidatedGlob], - output_exclusion_globs: &[ValidatedGlob], - time_saved: u64, - ) -> Result<(), DaemonError> { - let output_globs = output_globs - .iter() - .map(|validated_glob| validated_glob.as_str().to_string()) - .collect(); - let output_exclusion_globs = output_exclusion_globs - .iter() - .map(|validated_glob| validated_glob.as_str().to_string()) - .collect(); - self.client - .notify_outputs_written(proto::NotifyOutputsWrittenRequest { - hash, - output_globs, - output_exclusion_globs, - time_saved, - }) - .await?; - - Ok(()) - } - - /// Get the status of the daemon. - pub async fn status(&mut self) -> Result { - self.client - .status(proto::StatusRequest {}) - .await? - .into_inner() - .daemon_status - .ok_or(DaemonError::MalformedResponse) - } - - pub async fn discover_packages(&mut self) -> Result { - let req = proto::DiscoverPackagesRequest {}; - let mut req = req.into_request(); - req.set_timeout(Duration::from_millis(30)); - let response = self.client.discover_packages(req).await?.into_inner(); - - Ok(response) - } - - pub async fn discover_packages_blocking( - &mut self, - ) -> Result { - let response = self - .client - .discover_packages_blocking(proto::DiscoverPackagesRequest {}) - .await? - .into_inner(); - - Ok(response) - } - - pub async fn package_changes( - &mut self, - ) -> Result, DaemonError> { - let response = self - .client - .package_changes(proto::PackageChangesRequest {}) - .await? - .into_inner(); - Ok(response) - } - - pub async fn get_file_hashes( - &mut self, - package_path: &AnchoredSystemPath, - inputs: &[String], - ) -> Result { - let response = self - .client - .get_file_hashes(proto::GetFileHashesRequest { - package_path: package_path.to_string(), - input_globs: inputs.to_vec(), - }) - .await? - .into_inner(); - Ok(response) - } -} - -impl DaemonClient { - /// Stops the daemon, closes the connection, and opens a new connection. - pub async fn restart(self) -> Result, DaemonError> { - self.stop().await?.connect().await.map_err(Into::into) - } - - pub fn paths(&self) -> &Paths { - &self.connect_settings.paths - } -} - -fn format_repo_relative_glob(glob: &str) -> String { - #[cfg(windows)] - let glob = { - let glob = if let Some(idx) = glob.find(':') { - &glob[..idx] - } else { - glob - }; - glob.replace("\\", "/") - }; - glob.replace(':', "\\:") -} - -#[derive(Error, Debug, Diagnostic)] -pub enum DaemonError { - /// The server was connected but is now unavailable. - #[error("server is unavailable: {0}")] - Unavailable(String), - #[error("error opening socket: {0}")] - SocketOpen(#[from] SocketOpenError), - /// The server is running a different version of turborepo. - #[error("version mismatch: {0}")] - #[diagnostic(help("try restarting the daemon with `turbo daemon restart`."))] - VersionMismatch(String), - /// There is an issue with the underlying grpc transport. - #[error("bad grpc transport: {0}")] - GrpcTransport(#[from] tonic::transport::Error), - /// The daemon returned an unexpected status code. - #[error("bad grpc status code: {0}")] - GrpcFailure(tonic::Code), - /// The daemon returned a malformed response. - #[error("malformed response")] - MalformedResponse, - /// There was an issue connecting to the daemon. - #[error("unable to connect: {0}")] - DaemonConnect(#[from] DaemonConnectorError), - /// The timeout specified was invalid. - #[error("invalid timeout specified ({0})")] - #[allow(dead_code)] - InvalidTimeout(String), - /// The server is unable to start file watching. - #[error("unable to start file watching")] - SetupFileWatching(#[from] HashGlobSetupError), - - #[error("unable to display output: {0}")] - DisplayError(#[from] serde_json::Error), - - #[error("unable to construct log file name: {0}")] - InvalidLogFile(#[from] time::Error), - - #[error("unable to complete daemon clean")] - CleanFailed, - - #[error("failed to setup cookie dir {1}: {0}")] - CookieDir(io::Error, AbsoluteSystemPathBuf), - - #[error("failed to determine package manager: {0}")] - PackageManager(#[from] turborepo_repository::package_manager::Error), - - #[error("`tail` is not installed. Please install it to use this feature.")] - TailNotInstalled, - - #[error("could not find log file")] - LogFileNotFound, -} - -impl From for DaemonError { - fn from(status: Status) -> DaemonError { - match status.code() { - Code::FailedPrecondition => DaemonError::VersionMismatch(status.message().to_owned()), - Code::Unimplemented => { - DaemonError::VersionMismatch("rpc not implemented on daemon".to_string()) - } - Code::Unavailable => DaemonError::Unavailable(status.message().to_string()), - c => DaemonError::GrpcFailure(c), - } - } -} - -#[cfg(test)] -mod test { - use std::path::MAIN_SEPARATOR_STR; - - use crate::daemon::client::format_repo_relative_glob; - - #[test] - fn test_format_repo_relative_glob() { - let raw_glob = ["some", ".turbo", "turbo-foo:bar.log"].join(MAIN_SEPARATOR_STR); - #[cfg(windows)] - let expected = "some/.turbo/turbo-foo"; - #[cfg(not(windows))] - let expected = "some/.turbo/turbo-foo\\:bar.log"; - - let result = format_repo_relative_glob(&raw_glob); - assert_eq!(result, expected); - } -} diff --git a/crates/turborepo-lib/src/daemon/connector.rs b/crates/turborepo-lib/src/daemon/connector.rs deleted file mode 100644 index a5c941b7a2239..0000000000000 --- a/crates/turborepo-lib/src/daemon/connector.rs +++ /dev/null @@ -1,732 +0,0 @@ -use std::{ - ffi::OsStr, - process::Stdio, - sync::Arc, - time::{Duration, Instant}, -}; - -use command_group::AsyncCommandGroup; -use notify::{Config, Event, EventKind, Watcher}; -use pidlock::PidFileError; -use sysinfo::{Pid, ProcessExt, ProcessRefreshKind, RefreshKind, SystemExt}; -use thiserror::Error; -use tokio::{sync::mpsc, time::timeout}; -use tonic::transport::Endpoint; -use tracing::debug; -use turbopath::AbsoluteSystemPath; - -use super::{proto::turbod_client::TurbodClient, DaemonClient, Paths}; -use crate::daemon::DaemonError; - -#[derive(Error, Debug)] -pub enum DaemonConnectorError { - /// There was a problem when forking to start the daemon. - #[error("unable to fork")] - Fork(ForkError), - /// There was a problem reading the pid file. - #[error("the process in the pid is not the daemon ({0}) and still running ({1})")] - WrongPidProcess(Pid, Pid), - /// The daemon is not running and will not be started. - #[error("daemon is not running")] - NotRunning, - /// There was an issue connecting to the socket. - #[error("unable to connect to socket: {0}")] - Socket(#[from] tonic::transport::Error), - /// There was an issue performing the handshake. - #[error("unable to make handshake: {0}")] - Handshake(#[from] Box), - /// Waiting for the socket timed out. - #[error("timeout while watching directory: {0}")] - Timeout(#[from] tokio::time::error::Elapsed), - /// There was an issue in the file watcher. - #[error("unable to watch directory: {0}")] - Watcher(#[from] FileWaitError), - - #[error("unable to connect to daemon after {0} retries")] - ConnectRetriesExceeded(usize), - - #[error("unable to use pid file: {0}")] - PidFile(#[from] PidFileError), -} - -#[derive(Error, Debug)] -pub enum ForkError { - #[error("daemon exited before we could connect")] - Exited, - #[error("unable to spawn daemon: {0}")] - Spawn(#[from] std::io::Error), -} - -#[derive(Debug, Clone)] -pub struct DaemonConnector { - /// Whether the connector is allowed to start a daemon if it is not already - /// running. - pub can_start_server: bool, - /// Whether the connector is allowed to kill a running daemon (for example, - /// in the event of a version mismatch). - pub can_kill_server: bool, - pub paths: Paths, -} - -impl DaemonConnector { - pub fn new( - can_start_server: bool, - can_kill_server: bool, - repo_root: &AbsoluteSystemPath, - ) -> Self { - let paths = Paths::from_repo_root(repo_root); - Self { - can_start_server, - can_kill_server, - paths, - } - } - - const CONNECT_RETRY_MAX: usize = 3; - const CONNECT_TIMEOUT: Duration = Duration::from_secs(1); - const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(1); - const SOCKET_TIMEOUT: Duration = Duration::from_secs(1); - const SOCKET_ERROR_WAIT: Duration = Duration::from_millis(50); - - /// Attempt, with retries, to: - /// 1. find (or start) the daemon process - /// 2. locate its unix socket - /// 3. connect to the socket - /// 4. send the 'hello' message, negotiating versions - /// - /// A new server will be spawned (and the old one killed) if - /// dont_kill is unset and one of these cases is hit: - /// 1. the versions do not match - /// 2. the server is not running - /// 3. the server is unresponsive - #[tracing::instrument(skip(self))] - pub async fn connect(self) -> Result, DaemonConnectorError> { - let time = Instant::now(); - for _ in 0..Self::CONNECT_RETRY_MAX { - let pid = self.get_or_start_daemon().await?; - debug!("got daemon with pid: {}", pid); - - let conn = match self.get_connection(self.paths.sock_file.clone()).await { - Err(DaemonConnectorError::Watcher(_)) => continue, - Err(DaemonConnectorError::Socket(e)) => { - // assume the server is not yet ready - debug!("socket error: {}", e); - tokio::time::sleep(DaemonConnector::SOCKET_ERROR_WAIT).await; - continue; - } - rest => rest?, - }; - - let mut client = DaemonClient::new(conn); - - match client.handshake().await { - Ok(_) => { - return { - debug!("connected in {}µs", time.elapsed().as_micros()); - Ok(client.with_connect_settings(self)) - } - } - Err(DaemonError::VersionMismatch(_)) if self.can_kill_server => { - self.kill_live_server(client, pid).await? - } - Err(DaemonError::Unavailable(_)) => self.kill_dead_server(pid).await?, - Err(e) => return Err(DaemonConnectorError::Handshake(Box::new(e))), - }; - } - - Err(DaemonConnectorError::ConnectRetriesExceeded( - Self::CONNECT_RETRY_MAX, - )) - } - - /// Gets the PID of the daemon process. - /// - /// If a daemon is not running, it starts one. - async fn get_or_start_daemon(&self) -> Result { - debug!("looking for pid in lockfile: {:?}", self.paths.pid_file); - - let pidfile = self.pid_lock(); - - match pidfile.get_owner()? { - Some(pid) => { - debug!("found pid: {}", pid); - Ok(sysinfo::Pid::from(pid as usize)) - } - None if self.can_start_server => { - debug!("no pid found, starting daemon"); - Self::start_daemon().await - } - None => Err(DaemonConnectorError::NotRunning), - } - } - - /// Starts the daemon process, returning its PID. - async fn start_daemon() -> Result { - let binary_path = - std::env::current_exe().map_err(|e| DaemonConnectorError::Fork(e.into()))?; - // this creates a new process group for the given command - // in a cross platform way, directing all output to /dev/null - let mut group = tokio::process::Command::new(binary_path) - .arg("--skip-infer") - .arg("daemon") - .stderr(Stdio::null()) - .stdout(Stdio::null()) - .group() - .kill_on_drop(false) - .spawn() - .map_err(|e| DaemonConnectorError::Fork(e.into()))?; - - group - .inner() - .id() - .map(|id| sysinfo::Pid::from(id as usize)) - .ok_or(DaemonConnectorError::Fork(ForkError::Exited)) - } - - /// Gets a connection to given path - /// - /// On Windows the socket file cannot be interacted with via any filesystem - /// apis, due to this we need to just naively attempt to connect on that - /// platform and retry in case of error. - #[tracing::instrument(skip(self))] - async fn get_connection( - &self, - path: turbopath::AbsoluteSystemPathBuf, - ) -> Result, DaemonConnectorError> { - // windows doesn't treat sockets as files, so don't attempt to wait - #[cfg(not(target_os = "windows"))] - self.wait_for_socket().await?; - - debug!("connecting to socket: {}", path); - let path = Arc::new(path); - - #[cfg(not(target_os = "windows"))] - let make_service = move |_| { - // we clone the reference counter here and move it into the async closure - let path = path.clone(); - async move { tokio::net::UnixStream::connect(path.as_path()).await } - }; - - #[cfg(target_os = "windows")] - let make_service = move |_| { - let path = path.clone(); - async move { win(path) } - }; - - // note, this endpoint is just a placeholder. the actual path is passed in via - // make_service - Endpoint::try_from("http://[::]:50051") - .expect("this is a valid uri") - .timeout(Self::CONNECT_TIMEOUT) - .connect_with_connector(tower::service_fn(make_service)) - .await - .map(TurbodClient::new) - .map_err(DaemonConnectorError::Socket) - } - - /// Kills a currently active server by shutting it down and waiting for it - /// to exit. - #[tracing::instrument(skip(self, client))] - async fn kill_live_server( - &self, - client: DaemonClient<()>, - pid: sysinfo::Pid, - ) -> Result<(), DaemonConnectorError> { - if client.stop().await.is_err() { - self.kill_dead_server(pid).await?; - } - - match timeout( - Self::SHUTDOWN_TIMEOUT, - wait_for_file(&self.paths.pid_file, WaitAction::Deleted), - ) - .await? - { - Ok(_) => Ok(()), - Err(_) => self.kill_dead_server(pid).await, - } - } - - /// Kills a server that is not responding. - #[tracing::instrument(skip(self))] - async fn kill_dead_server(&self, pid: sysinfo::Pid) -> Result<(), DaemonConnectorError> { - let lock = self.pid_lock(); - - let system = sysinfo::System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::new()), - ); - - let owner = lock - .get_owner()? - .and_then(|p| system.process(sysinfo::Pid::from(p as usize))); - - // if the pidfile is owned by the same pid as the one we found, kill it - match owner { - Some(owner) if pid == owner.pid() => { - debug!("killing dead server with pid: {}", pid); - owner.kill(); - - Ok(()) - } - Some(owner) => { - debug!("pidfile is owned by another process, ignoring"); - Err(DaemonConnectorError::WrongPidProcess(pid, owner.pid())) - } - // pidfile has no owner and has been cleaned up so we're ok - None => Ok(()), - } - } - - #[tracing::instrument(skip(self))] - async fn wait_for_socket(&self) -> Result<(), DaemonConnectorError> { - // Note that we don't care if this is our daemon - // or not. We started a process, but someone else could beat - // use to listening. That's fine, we'll check the version - // later. However, we need to ensure that _some_ pid file - // exists to protect against stale .sock files - timeout( - Self::SOCKET_TIMEOUT, - wait_for_file(&self.paths.pid_file, WaitAction::Exists), - ) - .await??; - timeout( - Self::SOCKET_TIMEOUT, - wait_for_file(&self.paths.sock_file, WaitAction::Exists), - ) - .await? - .map_err(Into::into) - } - - fn pid_lock(&self) -> pidlock::Pidlock { - pidlock::Pidlock::new(self.paths.pid_file.clone().into()) - } -} - -#[cfg(target_os = "windows")] -fn win( - path: Arc, -) -> Result { - use tokio_util::compat::FuturesAsyncReadCompatExt; - uds_windows::UnixStream::connect(&*path) - .and_then(async_io::Async::new) - .map(FuturesAsyncReadCompatExt::compat) -} - -#[derive(Debug, Error)] -pub enum FileWaitError { - #[error("failed to register notifier {0}")] - Notify(#[from] notify::Error), - #[error("failed to wait for event {0}")] - Io(#[from] std::io::Error), - #[error("invalid path {0}")] - InvalidPath(turbopath::AbsoluteSystemPathBuf), -} - -/// Waits for a file at some path on the filesystem to be created or deleted. -/// -/// It does this by watching the parent directory of the path, and waiting for -/// events on that path. -#[tracing::instrument] -async fn wait_for_file( - path: &turbopath::AbsoluteSystemPathBuf, - action: WaitAction, -) -> Result<(), FileWaitError> { - let parent = path - .parent() - .ok_or_else(|| FileWaitError::InvalidPath(path.to_owned()))?; - - let file_name = path - .file_name() - .map(|f| f.to_owned()) - .ok_or_else(|| FileWaitError::InvalidPath(path.to_owned()))?; - - let (tx, mut rx) = mpsc::channel(1); - - let mut watcher = notify::PollWatcher::new( - move |res| match (res, action) { - ( - Ok(Event { - // for some reason, socket _creation_ is not detected, however, - // we can assume that any event except delete implies readiness - kind: EventKind::Access(_) | EventKind::Create(_) | EventKind::Modify(_), - paths, - .. - }), - WaitAction::Exists, - ) - | ( - Ok(Event { - kind: EventKind::Remove(_), - paths, - .. - }), - WaitAction::Deleted, - ) => { - if paths.iter().any(|p| { - p.file_name() - .map(|f| OsStr::new(&file_name).eq(f)) - .unwrap_or_default() - }) { - futures::executor::block_on(async { - // if the receiver is dropped, it is because the future has - // been cancelled, so we don't need to do anything - tx.send(()).await.ok(); - }) - } - } - _ => {} - }, - Config::default().with_poll_interval(Duration::from_millis(10)), - )?; - - debug!("creating {:?}", parent); - std::fs::create_dir_all(parent.as_path())?; - - debug!("watching {:?}", parent); - watcher.watch(parent.as_std_path(), notify::RecursiveMode::NonRecursive)?; - - match (action, path.exists()) { - (WaitAction::Exists, false) => {} - (WaitAction::Deleted, true) => {} - _ => return Ok(()), - }; - - // this can only fail if the channel has been closed, which will - // always happen either after this call ends, or after this future - // is cancelled - rx.recv().await.expect("will receive a message"); - - Ok(()) -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum WaitAction { - /// Wait for the file to exist. - Exists, - /// Wait for the file to be deleted. - Deleted, -} - -#[cfg(test)] -mod test { - use std::assert_matches::assert_matches; - - use tokio::{ - select, - sync::{oneshot::Sender, Mutex}, - }; - use tokio_stream::wrappers::ReceiverStream; - use tonic::{Request, Response, Status}; - use tower::ServiceBuilder; - use tracing::info; - use turbopath::AbsoluteSystemPathBuf; - - use super::*; - use crate::daemon::{ - default_timeout_layer::DefaultTimeoutLayer, - proto::{self, PackageChangesRequest}, - }; - - #[cfg(not(target_os = "windows"))] - const NODE_EXE: &str = "node"; - #[cfg(target_os = "windows")] - const NODE_EXE: &str = "node.exe"; - - #[tokio::test] - async fn handles_invalid_pid() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - - let connector = DaemonConnector::new(false, false, &repo_root); - connector.paths.pid_file.ensure_dir().unwrap(); - connector - .paths - .pid_file - .create_with_contents("not a pid") - .unwrap(); - - assert_matches!( - connector.get_or_start_daemon().await, - Err(DaemonConnectorError::PidFile(PidFileError::Invalid { .. })) - ); - } - - #[tokio::test] - async fn handles_missing_server_connect() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let connector = DaemonConnector::new(false, false, &repo_root); - - assert_matches!( - connector.connect().await, - Err(DaemonConnectorError::NotRunning) - ); - } - - #[tokio::test] - async fn handles_kill_dead_server_missing_pid() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let connector = DaemonConnector::new(false, false, &repo_root); - - assert_matches!( - connector.kill_dead_server(Pid::from(usize::MAX)).await, - Ok(()) - ); - } - - #[tokio::test] - async fn handles_kill_dead_server_missing_process() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let connector = DaemonConnector::new(false, false, &repo_root); - - connector.paths.pid_file.ensure_dir().unwrap(); - connector - .paths - .pid_file - .create_with_contents(i32::MAX.to_string()) - .unwrap(); - connector.paths.sock_file.ensure_dir().unwrap(); - connector.paths.sock_file.create_with_contents("").unwrap(); - - assert_matches!( - connector.kill_dead_server(Pid::from(usize::MAX)).await, - Ok(()) - ); - - assert!( - !connector.paths.pid_file.exists(), - "pid file should be cleaned up when getting the owner of a stale pid" - ); - } - - #[tokio::test] - async fn handles_kill_dead_server_wrong_process() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let connector = DaemonConnector::new(false, false, &repo_root); - - let proc = tokio::process::Command::new(NODE_EXE) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .arg("-e") - .arg("setInterval(() => {}, 1000)") - .spawn() - .unwrap(); - - connector.paths.pid_file.ensure_dir().unwrap(); - connector - .paths - .pid_file - .create_with_contents(proc.id().unwrap().to_string()) - .unwrap(); - connector.paths.sock_file.ensure_dir().unwrap(); - connector.paths.sock_file.create_with_contents("").unwrap(); - - let kill_pid = Pid::from(usize::MAX); - let proc_id = Pid::from(proc.id().unwrap() as usize); - - assert_matches!( - connector.kill_dead_server(kill_pid).await, - Err(DaemonConnectorError::WrongPidProcess(daemon, running)) if daemon == kill_pid && running == proc_id - ); - - assert!( - connector.paths.pid_file.exists(), - "pid file should still exist" - ); - } - - #[tokio::test] - async fn handles_kill_dead_server() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let connector = DaemonConnector::new(false, true, &repo_root); - - let proc = tokio::process::Command::new(NODE_EXE) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .arg("-e") - .arg("setInterval(() => {}, 1000)") - .spawn() - .unwrap(); - - connector.paths.pid_file.ensure_dir().unwrap(); - connector - .paths - .pid_file - .create_with_contents(proc.id().unwrap().to_string()) - .unwrap(); - connector.paths.sock_file.ensure_dir().unwrap(); - connector.paths.sock_file.create_with_contents("").unwrap(); - - assert_matches!( - connector - .kill_dead_server(Pid::from(proc.id().unwrap() as usize)) - .await, - Ok(()) - ); - - assert!( - connector.paths.pid_file.exists(), - "pid file should still exist" - ); - } - - struct DummyServer { - shutdown: Mutex>>, - } - - #[tonic::async_trait] - impl proto::turbod_server::Turbod for DummyServer { - async fn shutdown( - &self, - req: tonic::Request, - ) -> tonic::Result> { - info!("shutdown request: {:?}", req); - self.shutdown - .lock() - .await - .take() - .unwrap() - .send(true) - .unwrap(); - Ok(tonic::Response::new(proto::ShutdownResponse {})) - } - - async fn hello( - &self, - request: tonic::Request, - ) -> tonic::Result> { - let client_version = request.into_inner().version; - Err(tonic::Status::failed_precondition(format!( - "version mismatch. Client {} Server test-version", - client_version - ))) - } - - async fn status( - &self, - _req: tonic::Request, - ) -> tonic::Result> { - unimplemented!() - } - - async fn notify_outputs_written( - &self, - _req: tonic::Request, - ) -> tonic::Result> { - unimplemented!() - } - - async fn get_changed_outputs( - &self, - _req: tonic::Request, - ) -> tonic::Result> { - unimplemented!() - } - - async fn discover_packages( - &self, - _req: tonic::Request, - ) -> Result, tonic::Status> { - unimplemented!() - } - - async fn discover_packages_blocking( - &self, - _req: tonic::Request, - ) -> Result, tonic::Status> { - unimplemented!() - } - - type PackageChangesStream = ReceiverStream>; - async fn package_changes( - &self, - _req: Request, - ) -> Result, Status> { - unimplemented!() - } - - async fn get_file_hashes( - &self, - _req: tonic::Request, - ) -> Result, tonic::Status> { - unimplemented!() - } - } - - #[tokio::test] - async fn handles_kill_live_server() { - let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel(); - - let (tx, mut rx) = tokio::sync::mpsc::channel(1); - - // set up the server - let stream = async_stream::stream! { - while let Some(item) = rx.recv().await { - yield item; - } - }; - - let service = ServiceBuilder::new().layer(DefaultTimeoutLayer).service( - proto::turbod_server::TurbodServer::new(DummyServer { - shutdown: Mutex::new(Some(shutdown_tx)), - }), - ); - - let server_fut = tonic::transport::Server::builder() - .add_service(service) - .serve_with_incoming(stream); - - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let connector = DaemonConnector::new(false, false, &repo_root); - - let mut client = Endpoint::try_from("http://[::]:50051") - .expect("this is a valid uri") - .connect_with_connector(tower::service_fn(move |_| { - // when a connection is made, create a duplex stream and send it to the server - let tx = tx.clone(); - async move { - let (client, server) = tokio::io::duplex(1024); - let server: Result<_, anyhow::Error> = Ok(server); - let client: Result<_, anyhow::Error> = Ok(client); - tx.send(server).await.unwrap(); - client - } - })) - .await - .map(TurbodClient::new) - .unwrap(); - - // spawn the future for the server so that it responds to - // the hello request - let server_fut = tokio::spawn(server_fut); - - let hello_resp: DaemonError = client - .hello(proto::HelloRequest { - version: "version-mismatch".to_string(), - ..Default::default() - }) - .await - .unwrap_err() - .into(); - assert_matches!(hello_resp, DaemonError::VersionMismatch(_)); - let client = DaemonClient::new(client); - - let shutdown_fut = connector.kill_live_server(client, Pid::from(1000)); - - // drive the futures to completion - select! { - _ = shutdown_fut => {} - _ = server_fut => panic!("server should not have shut down first"), - } - - assert!( - shutdown_rx.await.is_ok(), - "shutdown should have been received" - ) - } -} diff --git a/crates/turborepo-lib/src/daemon/default_timeout_layer.rs b/crates/turborepo-lib/src/daemon/default_timeout_layer.rs deleted file mode 100644 index 60f6e55211f43..0000000000000 --- a/crates/turborepo-lib/src/daemon/default_timeout_layer.rs +++ /dev/null @@ -1,147 +0,0 @@ -//! default timeout layer -//! -//! This module provides some basic middleware that aims to -//! improve the flexibility of the daemon server by doing -//! two things: -//! -//! a) remove the server-wide timeout of 100ms in favour of -//! a less aggressive 30s. the way tonic works is the -//! lowest timeout (server vs request-specific) is always -//! used meaning clients' timeout requests were ignored -//! if set to >100ms -//! b) add a middleware to reinstate the timeout, if the -//! client does not specify it, defaulting to 100ms for -//! 'non-blocking' calls (requests in the hot path for -//! a run of turbo), and falling back to the server -//! limit for blocking ones (useful in cases like the -//! LSP) -//! -//! With this in place, it means that clients can specify -//! a timeout that it wants (as long as it is less than 30s), -//! and the server has sane defaults - -use std::time::Duration; - -use tonic::{codegen::http::Request, server::NamedService, transport::Body}; -use tower::{Layer, Service}; - -#[derive(Clone, Debug)] -pub struct DefaultTimeoutService { - inner: S, -} - -impl Service> for DefaultTimeoutService -where - S: Service>, -{ - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready( - &mut self, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, mut req: Request) -> Self::Future { - if !req.uri().path().ends_with("Blocking") { - req.headers_mut() - .entry("grpc-timeout") - .or_insert_with(move || { - let dur = Duration::from_millis(100); - tonic::codegen::http::HeaderValue::from_str(&format!("{}u", dur.as_micros())) - .expect("numbers are always valid ascii") - }); - }; - - self.inner.call(req) - } -} - -/// Provides a middleware that sets a default timeout for -/// non-blocking calls. See the module documentation for -/// more information. -#[derive(Clone, Debug)] -pub struct DefaultTimeoutLayer; - -impl Layer for DefaultTimeoutLayer { - type Service = DefaultTimeoutService; - - fn layer(&self, inner: S) -> Self::Service { - DefaultTimeoutService { inner } - } -} - -impl NamedService for DefaultTimeoutService { - const NAME: &'static str = T::NAME; -} - -#[cfg(test)] -mod test { - use std::{ - str::FromStr, - sync::{Arc, Mutex}, - }; - - use test_case::test_case; - use tonic::codegen::http::HeaderValue; - - use super::*; - - #[test_case("/ExampleBlocking", None, None ; "no default for blocking calls")] - #[test_case("/Example", None, Some("100000u") ; "default for non-blocking calls")] - #[test_case("/Example", Some("200u"), Some("200u") ; "respect client preference")] - #[tokio::test] - async fn overrides_timeout_for_non_blocking( - path: &str, - timeout: Option<&str>, - expected: Option<&str>, - ) { - #[derive(Clone, Debug)] - struct MockService(Arc>>); - - impl Service> for MockService { - type Response = (); - type Error = (); - type Future = impl std::future::Future>; - - fn poll_ready( - &mut self, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - std::task::Poll::Ready(Ok(())) - } - - fn call(&mut self, req: Request) -> Self::Future { - // get the content of the header - let header = self.0.clone(); - async move { - let mut header = header.lock().unwrap(); - *header = req - .headers() - .get("grpc-timeout") - .map(|h| h.to_str().unwrap().to_string()); - Ok(()) - } - } - } - - let inner = MockService(Arc::new(Mutex::new(None))); - let mut svc = DefaultTimeoutLayer.layer(inner.clone()); - let mut req = Request::new(Body::empty()); - let uri = req.uri_mut(); - *uri = tonic::codegen::http::Uri::from_str(path).unwrap(); - if let Some(timeout) = timeout { - req.headers_mut() - .insert("grpc-timeout", HeaderValue::from_str(timeout).unwrap()); - } - - svc.call(req).await.unwrap(); - - let header = inner.0.lock().unwrap(); - - assert_eq!(header.as_deref(), expected); - } -} diff --git a/crates/turborepo-lib/src/daemon/endpoint.rs b/crates/turborepo-lib/src/daemon/endpoint.rs deleted file mode 100644 index 178f992100dde..0000000000000 --- a/crates/turborepo-lib/src/daemon/endpoint.rs +++ /dev/null @@ -1,246 +0,0 @@ -use std::sync::{atomic::AtomicBool, Arc}; -#[cfg(windows)] -use std::{io::ErrorKind, sync::atomic::Ordering, time::Duration}; - -use futures::Stream; -use tokio::io::{AsyncRead, AsyncWrite}; -use tonic::transport::server::Connected; -use tracing::{debug, trace}; -use turbopath::AbsoluteSystemPath; - -#[derive(thiserror::Error, Debug)] -pub enum SocketOpenError { - /// Returned when there is an IO error opening the socket, - /// such as the path being too long, or the path being - /// invalid. - #[error("IO error: {0}")] - Io(#[from] std::io::Error), - #[error("pidlock error: {0}")] - LockError(#[from] pidlock::PidlockError), -} - -#[cfg(windows)] -const WINDOWS_POLL_DURATION: Duration = Duration::from_millis(1); - -/// Gets a stream of incoming connections from a Unix socket. -/// On windows, this will use the `uds_windows` crate, and -/// poll the result in another thread. -/// -/// note: the running param is used by the windows -/// code path to shut down the non-blocking polling -#[tracing::instrument] -pub async fn listen_socket( - pid_path: &AbsoluteSystemPath, - sock_path: &AbsoluteSystemPath, - #[allow(unused)] running: Arc, -) -> Result< - ( - pidlock::Pidlock, - impl Stream>, - ), - SocketOpenError, -> { - let mut lock = pidlock::Pidlock::new(pid_path.as_std_path().to_owned()); - - trace!("acquiring pidlock"); - // this will fail if the pid is already owned - // todo: make sure we fall back and handle this - lock.acquire()?; - sock_path.remove_file().ok(); - - debug!("pidlock acquired at {}", pid_path); - debug!("listening on socket at {}", sock_path); - - #[cfg(unix)] - { - Ok(( - lock, - tokio_stream::wrappers::UnixListenerStream::new(tokio::net::UnixListener::bind( - sock_path, - )?), - )) - } - - #[cfg(windows)] - { - use tokio_util::compat::FuturesAsyncReadCompatExt; - - let listener = Arc::new(uds_windows::UnixListener::bind(sock_path)?); - listener.set_nonblocking(true)?; - - let stream = futures::stream::unfold(listener, move |listener| { - let task_running = running.clone(); - async move { - // ensure the underlying thread is aborted on drop - let task_listener = listener.clone(); - let task = tokio::task::spawn_blocking(move || loop { - break match task_listener.accept() { - Err(e) if e.kind() == ErrorKind::WouldBlock => { - std::thread::sleep(WINDOWS_POLL_DURATION); - if !task_running.load(Ordering::SeqCst) { - None - } else { - continue; - } - } - res => Some(res), - }; - }); - - let result = task - .await - .expect("no panic")? - .map(|(stream, _)| stream) - .and_then(async_io::Async::new) - .map(FuturesAsyncReadCompatExt::compat) - .map(UdsWindowsStream); - - Some((result, listener)) - } - }); - - Ok((lock, stream)) - } -} - -/// An adaptor over uds_windows that implements AsyncRead and AsyncWrite. -/// -/// It utilizes structural pinning to forward async read and write -/// implementations onto the inner type. -#[cfg(windows)] -struct UdsWindowsStream(T); - -#[cfg(windows)] -impl UdsWindowsStream { - /// Project the (pinned) uds windows stream to get the inner (pinned) type - /// - /// SAFETY - /// - /// structural pinning requires a few invariants to hold which can be seen - /// here https://doc.rust-lang.org/std/pin/#pinning-is-structural-for-field - /// - /// in short: - /// - we cannot implement Unpin for UdsWindowsStream - /// - we cannot use repr packed - /// - we cannot move in the drop impl (the default impl doesn't) - /// - we must uphold the rust 'drop guarantee' - /// - we cannot offer any api to move data out of the pinned value (such as - /// Option::take) - fn project(self: std::pin::Pin<&mut Self>) -> std::pin::Pin<&mut T> { - unsafe { self.map_unchecked_mut(|s| &mut s.0) } - } -} - -#[cfg(windows)] -impl AsyncRead for UdsWindowsStream { - fn poll_read( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - buf: &mut tokio::io::ReadBuf<'_>, - ) -> std::task::Poll> { - self.project().poll_read(cx, buf) - } -} - -#[cfg(windows)] -impl AsyncWrite for UdsWindowsStream { - fn poll_write( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - buf: &[u8], - ) -> std::task::Poll> { - self.project().poll_write(cx, buf) - } - - fn poll_flush( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - self.project().poll_flush(cx) - } - - fn poll_shutdown( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - self.project().poll_shutdown(cx) - } -} - -#[cfg(windows)] -impl Connected for UdsWindowsStream { - type ConnectInfo = (); - fn connect_info(&self) -> Self::ConnectInfo {} -} - -#[cfg(test)] -mod test { - use std::{ - assert_matches::assert_matches, - process::Command, - sync::{atomic::AtomicBool, Arc}, - }; - - use pidlock::PidlockError; - use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; - - use super::listen_socket; - use crate::daemon::{endpoint::SocketOpenError, Paths}; - - fn pid_path(daemon_root: &AbsoluteSystemPath) -> AbsoluteSystemPathBuf { - daemon_root.join_component("turbod.pid") - } - - #[tokio::test] - async fn test_stale_pid() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let paths = Paths::from_repo_root(&repo_root); - paths.pid_file.ensure_dir().unwrap(); - // A pid that will never be running and is guaranteed not to be us - paths.pid_file.create_with_contents("100000").unwrap(); - - let running = Arc::new(AtomicBool::new(true)); - let result = listen_socket(&paths.pid_file, &paths.sock_file, running).await; - - assert!( - result.is_ok(), - "expected to clear stale pid file and connect" - ); - } - - #[tokio::test] - async fn test_existing_process() { - let tmp_dir = tempfile::tempdir().unwrap(); - let repo_root = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap(); - let paths = Paths::from_repo_root(&repo_root); - - #[cfg(windows)] - let node_bin = "node.exe"; - #[cfg(not(windows))] - let node_bin = "node"; - - let mut child = Command::new(node_bin).spawn().unwrap(); - paths.pid_file.ensure_dir().unwrap(); - paths - .pid_file - .create_with_contents(format!("{}", child.id())) - .unwrap(); - - let running = Arc::new(AtomicBool::new(true)); - let result = listen_socket(&paths.pid_file, &paths.sock_file, running).await; - - // Note: PidLock doesn't implement Debug, so we can't unwrap_err() - - // todo: update this test. we should delete the socket file first, remove the - // pid file, and start a new daemon. the old one should just time - // out, and this should not error. - if let Err(err) = result { - assert_matches!(err, SocketOpenError::LockError(PidlockError::AlreadyOwned)); - } else { - panic!("expected an error") - } - - child.kill().unwrap(); - } -} diff --git a/crates/turborepo-lib/src/daemon/mod.rs b/crates/turborepo-lib/src/daemon/mod.rs deleted file mode 100644 index ceb4f4eead4d0..0000000000000 --- a/crates/turborepo-lib/src/daemon/mod.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! The Turborepo daemon watches files and pre-computes data to speed up turbo's -//! execution. Each repository has a separate daemon instance. -//! -//! # Architecture -//! The daemon consists of a gRPC server that can be queried by a client. - -//! The server spins up a `FileWatching` struct, which contains a struct -//! responsible for watching the repository (`FileSystemWatcher`), and the -//! various consumers of that file change data such as `GlobWatcher` and -//! `PackageWatcher`. -//! -//! We use cookie files to ensure proper event synchronization, i.e. -//! that we don't get stale file system events while handling queries. -//! -//! # Naming Conventions -//! `recv` is a receiver of file system events. Structs such as `GlobWatcher` -//! or `PackageWatcher` consume these file system events and either derive state -//! or produce new events. -//! -//! `_tx`/`_rx` suffixes indicate that this variable is respectively a `Sender` -//! or `Receiver`. - -mod bump_timeout; -mod bump_timeout_layer; -mod client; -mod connector; -mod default_timeout_layer; -pub(crate) mod endpoint; -mod server; - -pub use client::{DaemonClient, DaemonError}; -pub use connector::{DaemonConnector, DaemonConnectorError}; -pub use server::{CloseReason, TurboGrpcService}; -use sha2::{Digest, Sha256}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; - -#[derive(Clone, Debug)] -pub struct Paths { - pub pid_file: AbsoluteSystemPathBuf, - pub lock_file: AbsoluteSystemPathBuf, - pub sock_file: AbsoluteSystemPathBuf, - pub lsp_pid_file: AbsoluteSystemPathBuf, - pub log_file: AbsoluteSystemPathBuf, - pub log_folder: AbsoluteSystemPathBuf, -} - -fn repo_hash(repo_root: &AbsoluteSystemPath) -> String { - let mut hasher = Sha256::new(); - hasher.update(repo_root.to_string().as_bytes()); - hex::encode(&hasher.finalize()[..8]) -} - -fn daemon_file_root(repo_hash: &str) -> AbsoluteSystemPathBuf { - AbsoluteSystemPathBuf::new(std::env::temp_dir().to_str().expect("UTF-8 path")) - .expect("temp dir is valid") - .join_component("turbod") - .join_component(repo_hash) -} - -fn daemon_log_file_and_folder( - repo_root: &AbsoluteSystemPath, - repo_hash: &str, -) -> (AbsoluteSystemPathBuf, AbsoluteSystemPathBuf) { - let log_folder = repo_root.join_components(&[".turbo", "daemon"]); - let log_file = log_folder.join_component(format!("{}-turbo.log", repo_hash).as_str()); - - (log_file, log_folder) -} - -impl Paths { - pub fn from_repo_root(repo_root: &AbsoluteSystemPath) -> Self { - let repo_hash = repo_hash(repo_root); - let daemon_root = daemon_file_root(&repo_hash); - let (log_file, log_folder) = daemon_log_file_and_folder(repo_root, &repo_hash); - Self { - pid_file: daemon_root.join_component("turbod.pid"), - lock_file: daemon_root.join_component("turbod.lock"), - sock_file: daemon_root.join_component("turbod.sock"), - lsp_pid_file: daemon_root.join_component("lsp.pid"), - log_file, - log_folder, - } - } -} - -pub(crate) mod proto { - - tonic::include_proto!("turbodprotocol"); - /// The version of the protocol that this library implements. - /// - /// Protocol buffers aim to be backward and forward compatible at a protocol - /// level, however that doesn't mean that our daemon will have the same - /// logical API. We may decide to change the API in the future, and this - /// version number will be used to indicate that. - /// - /// Changes are driven by the server changing its implementation. - /// - /// Guideline for bumping the daemon protocol version: - /// - Bump the major version if making backwards incompatible changes. - /// - Bump the minor version if adding new features, such that clients can - /// mandate at least some set of features on the target server. - /// - Bump the patch version if making backwards compatible bug fixes. - pub const VERSION: &str = "2.0.0"; - - impl From for turborepo_repository::package_manager::PackageManager { - fn from(pm: PackageManager) -> Self { - match pm { - PackageManager::Npm => Self::Npm, - PackageManager::Yarn => Self::Yarn, - PackageManager::Berry => Self::Berry, - PackageManager::Pnpm => Self::Pnpm, - PackageManager::Pnpm6 => Self::Pnpm6, - PackageManager::Pnpm9 => Self::Pnpm9, - PackageManager::Bun => Self::Bun, - } - } - } - - impl From for PackageManager { - fn from(pm: turborepo_repository::package_manager::PackageManager) -> Self { - match pm { - turborepo_repository::package_manager::PackageManager::Npm => Self::Npm, - turborepo_repository::package_manager::PackageManager::Yarn => Self::Yarn, - turborepo_repository::package_manager::PackageManager::Berry => Self::Berry, - turborepo_repository::package_manager::PackageManager::Pnpm => Self::Pnpm, - turborepo_repository::package_manager::PackageManager::Pnpm6 => Self::Pnpm6, - turborepo_repository::package_manager::PackageManager::Pnpm9 => Self::Pnpm9, - turborepo_repository::package_manager::PackageManager::Bun => Self::Bun, - } - } - } -} - -#[cfg(test)] -mod test { - use turbopath::AbsoluteSystemPathBuf; - - use super::repo_hash; - - #[test] - fn test_repo_hash() { - #[cfg(not(target_os = "windows"))] - let (path, expected_hash) = ("/tmp/turborepo", "6e0cfa616f75a61c"); - #[cfg(target_os = "windows")] - let (path, expected_hash) = ("C:\\\\tmp\\turborepo", "0103736e6883e35f"); - let repo_root = AbsoluteSystemPathBuf::new(path).unwrap(); - let hash = repo_hash(&repo_root); - - assert_eq!(hash, expected_hash); - assert_eq!(hash.len(), 16); - } -} diff --git a/crates/turborepo-lib/src/daemon/server.rs b/crates/turborepo-lib/src/daemon/server.rs deleted file mode 100644 index 923d31a797592..0000000000000 --- a/crates/turborepo-lib/src/daemon/server.rs +++ /dev/null @@ -1,910 +0,0 @@ -//! Daemon Server -//! -//! This module houses the daemon server. For more information, go to the -//! [daemon module](std::daemon). - -use std::{ - collections::{HashMap, HashSet}, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, Mutex, OnceLock, - }, - time::{Duration, Instant}, -}; - -use futures::Future; -use prost::DecodeError; -use semver::Version; -use thiserror::Error; -use tokio::{ - select, - sync::{broadcast::error::RecvError, mpsc, oneshot}, - task::JoinHandle, -}; -use tokio_stream::wrappers::ReceiverStream; -use tonic::{server::NamedService, transport::Server}; -use tower::ServiceBuilder; -use tracing::{error, info, trace, warn}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf, PathError}; -use turborepo_filewatch::{ - cookies::CookieWriter, - globwatcher::{Error as GlobWatcherError, GlobError, GlobSet, GlobWatcher}, - hash_watcher::{Error as HashWatcherError, HashSpec, HashWatcher, InputGlobs}, - package_watcher::{PackageWatchError, PackageWatcher}, - FileSystemWatcher, WatchError, -}; -use turborepo_repository::package_manager; -use turborepo_scm::SCM; - -use super::{bump_timeout::BumpTimeout, endpoint::SocketOpenError, proto}; -use crate::{ - daemon::{ - bump_timeout_layer::BumpTimeoutLayer, default_timeout_layer::DefaultTimeoutLayer, - endpoint::listen_socket, Paths, - }, - package_changes_watcher::{PackageChangeEvent, PackageChangesWatcher}, -}; - -#[derive(Debug)] -#[allow(dead_code)] -pub enum CloseReason { - Timeout, - Shutdown, - WatcherClosed, - ServerClosed, - Interrupt, - SocketOpenError(SocketOpenError), -} - -/// We may need to pass out references to a subset of these, so -/// we'll make them public Arcs. Eventually we can stabilize on -/// a general API and close this up. -#[derive(Clone)] -pub struct FileWatching { - repo_root: AbsoluteSystemPathBuf, - watcher: Arc, - pub glob_watcher: Arc, - pub package_watcher: Arc, - pub package_changes_watcher: OnceLock>, - pub hash_watcher: Arc, -} - -#[derive(Debug, Error)] -enum RpcError { - #[error("deadline exceeded")] - DeadlineExceeded, - #[error("invalid relative system path {0}: {1}")] - InvalidAnchoredPath(String, PathError), - #[error("invalid glob: {0}")] - InvalidGlob(#[from] GlobError), - #[error("globwatching failed: {0}")] - GlobWatching(#[from] GlobWatcherError), - #[error("filewatching unavailable")] - NoFileWatching, - #[error("file hashing failed: {0}")] - FileHashing(#[from] HashWatcherError), -} - -impl From for tonic::Status { - fn from(value: RpcError) -> Self { - match value { - RpcError::DeadlineExceeded => { - tonic::Status::deadline_exceeded("failed to load filewatching in time") - } - RpcError::InvalidGlob(e) => tonic::Status::invalid_argument(e.to_string()), - RpcError::GlobWatching(e) => tonic::Status::unavailable(e.to_string()), - RpcError::NoFileWatching => tonic::Status::unavailable("filewatching unavailable"), - RpcError::FileHashing(e) => { - tonic::Status::failed_precondition(format!("File hashing not available: {e}",)) - } - e @ RpcError::InvalidAnchoredPath(_, _) => { - tonic::Status::invalid_argument(e.to_string()) - } - } - } -} - -impl FileWatching { - /// This function is called in the constructor for the `TurboGrpcService` - /// and should defer ALL heavy computation to the background, making use - /// of `OptionalWatch` to ensure that the server can start up without - /// waiting for the filewatcher to be ready. Using `OptionalWatch`, - /// dependent services can wait for resources they need to become - /// available, and the server can start up without waiting for them. - pub fn new(repo_root: AbsoluteSystemPathBuf) -> Result { - let watcher = Arc::new(FileSystemWatcher::new_with_default_cookie_dir(&repo_root)?); - let recv = watcher.watch(); - - let cookie_writer = CookieWriter::new( - watcher.cookie_dir(), - Duration::from_millis(100), - recv.clone(), - ); - let glob_watcher = Arc::new(GlobWatcher::new( - repo_root.clone(), - cookie_writer.clone(), - recv.clone(), - )); - let package_watcher = Arc::new( - PackageWatcher::new(repo_root.clone(), recv.clone(), cookie_writer) - .map_err(|e| WatchError::Setup(format!("{:?}", e)))?, - ); - let scm = SCM::new(&repo_root); - let hash_watcher = Arc::new(HashWatcher::new( - repo_root.clone(), - package_watcher.watch_discovery(), - recv.clone(), - scm, - )); - - Ok(FileWatching { - repo_root, - watcher, - glob_watcher, - package_watcher, - package_changes_watcher: OnceLock::new(), - hash_watcher, - }) - } - - pub fn get_or_init_package_changes_watcher(&self) -> Arc { - self.package_changes_watcher - .get_or_init(|| { - let recv = self.watcher.watch(); - Arc::new(PackageChangesWatcher::new( - self.repo_root.clone(), - recv, - self.hash_watcher.clone(), - )) - }) - .clone() - } -} - -/// Timeout for every RPC the server handles -const REQUEST_TIMEOUT: Duration = Duration::from_secs(30); - -pub struct TurboGrpcService { - repo_root: AbsoluteSystemPathBuf, - paths: Paths, - timeout: Duration, - external_shutdown: S, -} - -impl TurboGrpcService -where - S: Future, -{ - /// Create a gRPC server providing the Turbod interface. external_shutdown - /// can be used to deliver a signal to shutdown the server. This is expected - /// to be wired to signal handling. By default, the server will set up a - /// file system watcher for the purposes of managing package discovery - /// state, and use a `LocalPackageDiscovery` instance to refresh the - /// state if the filewatcher encounters errors. - pub fn new( - repo_root: AbsoluteSystemPathBuf, - paths: Paths, - timeout: Duration, - external_shutdown: S, - ) -> Self { - // Run the actual service. It takes ownership of the struct given to it, - // so we use a private struct with just the pieces of state needed to handle - // RPCs. - TurboGrpcService { - repo_root, - paths, - timeout, - external_shutdown, - } - } - - pub async fn serve(self) -> Result { - let Self { - external_shutdown, - paths, - repo_root, - timeout, - } = self; - - // A channel to trigger the shutdown of the gRPC server. This is handed out - // to components internal to the server process such as root watching, as - // well as available to the gRPC server itself to handle the shutdown RPC. - let (trigger_shutdown, mut shutdown_signal) = mpsc::channel::<()>(1); - - let (service, exit_root_watch, watch_root_handle) = - TurboGrpcServiceInner::new(repo_root.clone(), trigger_shutdown, paths.log_file); - - let running = Arc::new(AtomicBool::new(true)); - let (_pid_lock, stream) = - match listen_socket(&paths.pid_file, &paths.sock_file, running.clone()).await { - Ok((pid_lock, stream)) => (pid_lock, stream), - Err(e) => return Ok(CloseReason::SocketOpenError(e)), - }; - trace!("acquired connection stream for socket"); - - let bump_timeout = Arc::new(BumpTimeout::new(timeout)); - let timeout_fut = bump_timeout.wait(); - - // when one of these futures complete, let the server gracefully shutdown - let (grpc_shutdown_tx, shutdown_reason) = oneshot::channel(); - let shutdown_fut = async move { - select! { - _ = shutdown_signal.recv() => grpc_shutdown_tx.send(CloseReason::Shutdown).ok(), - _ = timeout_fut => grpc_shutdown_tx.send(CloseReason::Timeout).ok(), - reason = external_shutdown => grpc_shutdown_tx.send(reason).ok(), - }; - }; - - let server_fut = { - let service = ServiceBuilder::new() - .layer(BumpTimeoutLayer::new(bump_timeout.clone())) - .layer(DefaultTimeoutLayer) - .service(crate::daemon::proto::turbod_server::TurbodServer::new( - service, - )); - - Server::builder() - // we respect the timeout specified by the client if it is set, but - // have a default timeout for non-blocking calls of 100ms, courtesy of - // `DefaultTimeoutLayer`. the REQUEST_TIMEOUT, however, is the - // maximum time we will wait for a response, regardless of the client's - // preferences. it cannot be exceeded. - .timeout(REQUEST_TIMEOUT) - .add_service(service) - .serve_with_incoming_shutdown(stream, shutdown_fut) - }; - // Wait for the server to exit. - // This can be triggered by timeout, root watcher, or an RPC - tracing::debug!("server started"); - let _ = server_fut.await; - tracing::debug!("server exited"); - // Ensure our timer will exit - running.store(false, Ordering::SeqCst); - // We expect to have a signal from the grpc server on what triggered the exit - let close_reason = shutdown_reason.await.unwrap_or(CloseReason::ServerClosed); - // Now that the server has exited, the TurboGrpcService instance should be - // dropped. The root watcher still has a reference to a receiver, keeping - // the filewatcher alive. Trigger the root watcher to exit. We don't care - // if we fail to send, root watching may have exited already - let _ = exit_root_watch.send(()); - let _ = watch_root_handle.await; - trace!("root watching exited"); - Ok(close_reason) - } -} - -struct TurboGrpcServiceInner { - shutdown: mpsc::Sender<()>, - file_watching: FileWatching, - times_saved: Arc>>, - start_time: Instant, - log_file: AbsoluteSystemPathBuf, - package_watcher: Arc, -} - -// we have a grpc service that uses watching package discovery, and where the -// watching package hasher also uses watching package discovery as well as -// falling back to a local package hasher -impl TurboGrpcServiceInner { - pub fn new( - repo_root: AbsoluteSystemPathBuf, - trigger_shutdown: mpsc::Sender<()>, - log_file: AbsoluteSystemPathBuf, - ) -> ( - Self, - oneshot::Sender<()>, - JoinHandle>, - ) { - let file_watching = FileWatching::new(repo_root.clone()).unwrap(); - - tracing::debug!("initing package discovery"); - // Note that we're cloning the Arc, not the package watcher itself - let package_watcher = Arc::clone(&file_watching.package_watcher); - - // exit_root_watch delivers a signal to the root watch loop to exit. - // In the event that the server shuts down via some other mechanism, this - // cleans up root watching task. - let (exit_root_watch, root_watch_exit_signal) = oneshot::channel(); - let watch_root_handle = tokio::task::spawn(watch_root( - file_watching.clone(), - repo_root.clone(), - trigger_shutdown.clone(), - root_watch_exit_signal, - )); - - ( - TurboGrpcServiceInner { - package_watcher, - shutdown: trigger_shutdown, - file_watching, - times_saved: Arc::new(Mutex::new(HashMap::new())), - start_time: Instant::now(), - log_file, - }, - exit_root_watch, - watch_root_handle, - ) - } - - async fn trigger_shutdown(&self) { - info!("triggering shutdown"); - let _ = self.shutdown.send(()).await; - } - - async fn watch_globs( - &self, - hash: String, - output_globs: Vec, - output_glob_exclusions: Vec, - time_saved: u64, - ) -> Result<(), RpcError> { - let glob_set = GlobSet::from_raw(output_globs, output_glob_exclusions)?; - self.file_watching - .glob_watcher - .watch_globs(hash.clone(), glob_set, REQUEST_TIMEOUT) - .await?; - { - let mut times_saved = self.times_saved.lock().expect("times saved lock poisoned"); - times_saved.insert(hash, time_saved); - } - Ok(()) - } - - async fn get_changed_outputs( - &self, - hash: String, - candidates: HashSet, - ) -> Result<(HashSet, u64), RpcError> { - let time_saved = { - let times_saved = self.times_saved.lock().expect("times saved lock poisoned"); - times_saved.get(hash.as_str()).copied().unwrap_or_default() - }; - let changed_globs = self - .file_watching - .glob_watcher - .get_changed_globs(hash, candidates, REQUEST_TIMEOUT) - .await?; - Ok((changed_globs, time_saved)) - } - - async fn get_file_hashes( - &self, - package_path: String, - inputs: Vec, - ) -> Result, RpcError> { - let inputs = InputGlobs::from_raw(inputs)?; - let package_path = AnchoredSystemPathBuf::try_from(package_path.as_str()) - .map_err(|e| RpcError::InvalidAnchoredPath(package_path, e))?; - let hash_spec = HashSpec { - package_path, - inputs, - }; - self.file_watching - .hash_watcher - .get_file_hashes(hash_spec) - .await - .map_err(RpcError::FileHashing) - .map(|hashes| { - hashes - .into_iter() - .map(|(path, hash)| (path.to_string(), hash)) - .collect() - }) - } -} - -async fn watch_root( - filewatching_access: FileWatching, - root: AbsoluteSystemPathBuf, - trigger_shutdown: mpsc::Sender<()>, - mut exit_signal: oneshot::Receiver<()>, -) -> Result<(), WatchError> { - let mut recv_events = filewatching_access - .watcher - .subscribe() - .await - // we can only encounter an error here if the file watcher is closed (a recv error) - .map_err(|_| WatchError::Setup("file watching shut down".to_string()))?; - - tracing::debug!("watching root: {:?}", root); - - loop { - // Ignore the outer layer of Result, if the sender has closed, filewatching has - // gone away and we can return. - select! { - _ = &mut exit_signal => break, - event = recv_events.recv() => { - let Ok(event) = event else { - break; - }; - tracing::debug!("root watcher received event: {:?}", event); - let should_trigger_shutdown = match event { - // filewatching can throw some weird events, so check that the root is actually gone - // before triggering a shutdown - Ok(event) if event.paths.iter().any(|p| p == (&root as &AbsoluteSystemPath)) => !root.exists(), - Ok(_) => false, - Err(_) => true - }; - if should_trigger_shutdown { - warn!("Root watcher triggering shutdown"); - // We don't care if a shutdown has already been triggered, - // so we can ignore the error. - let _ = trigger_shutdown.send(()).await; - break; - } - } - } - } - - tracing::debug!("no longer watching root"); - - Ok(()) -} - -#[tonic::async_trait] -impl proto::turbod_server::Turbod for TurboGrpcServiceInner { - async fn hello( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - let request = request.into_inner(); - - let client_version = request.version; - let server_version = proto::VERSION; - - let passes_version_check = match ( - proto::VersionRange::try_from(request.supported_version_range), - Version::parse(&client_version), - Version::parse(server_version), - ) { - // if we fail to parse, or the constraint is invalid, we have a version mismatch - (_, Err(_), _) | (_, _, Err(_)) | (Err(DecodeError { .. }), _, _) => false, - (Ok(range), Ok(client), Ok(server)) => compare_versions(client, server, range), - }; - - if passes_version_check { - Ok(tonic::Response::new(proto::HelloResponse {})) - } else { - Err(tonic::Status::failed_precondition(format!( - "version mismatch. Client {} Server {}", - client_version, server_version - ))) - } - } - - async fn shutdown( - &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - self.trigger_shutdown().await; - - // if Some(Ok), then the server is shutting down now - // if Some(Err), then the server is already shutting down - // if None, then someone has already called shutdown - Ok(tonic::Response::new(proto::ShutdownResponse {})) - } - - async fn status( - &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - Ok(tonic::Response::new(proto::StatusResponse { - daemon_status: Some(proto::DaemonStatus { - uptime_msec: self.start_time.elapsed().as_millis() as u64, - log_file: self.log_file.to_string(), - }), - })) - } - - async fn notify_outputs_written( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - let inner = request.into_inner(); - - self.watch_globs( - inner.hash, - inner.output_globs, - inner.output_exclusion_globs, - inner.time_saved, - ) - .await?; - Ok(tonic::Response::new(proto::NotifyOutputsWrittenResponse {})) - } - - async fn get_changed_outputs( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - let inner = request.into_inner(); - let (changed, time_saved) = self - .get_changed_outputs(inner.hash, HashSet::from_iter(inner.output_globs)) - .await?; - Ok(tonic::Response::new(proto::GetChangedOutputsResponse { - changed_output_globs: changed.into_iter().collect(), - time_saved, - })) - } - - // Note that this is implemented as a blocking call. We expect the default - // server timeout to apply, as well as whatever timeout the client may have - // set. - async fn get_file_hashes( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - let inner = request.into_inner(); - let file_hashes = self - .get_file_hashes(inner.package_path, inner.input_globs) - .await?; - Ok(tonic::Response::new(proto::GetFileHashesResponse { - file_hashes, - })) - } - - async fn discover_packages( - &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - match self.package_watcher.discover_packages().await { - Some(Ok(packages)) => Ok(tonic::Response::new(proto::DiscoverPackagesResponse { - package_files: packages - .workspaces - .into_iter() - .map(|d| proto::PackageFiles { - package_json: d.package_json.to_string(), - turbo_json: d.turbo_json.map(|t| t.to_string()), - }) - .collect(), - package_manager: proto::PackageManager::from(packages.package_manager).into(), - })), - None | Some(Err(PackageWatchError::Unavailable)) => { - Err(tonic::Status::unavailable("package discovery unavailable")) - } - Some(Err(PackageWatchError::InvalidState(reason))) => { - Err(tonic::Status::failed_precondition(reason)) - } - } - } - - async fn discover_packages_blocking( - &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - match self.package_watcher.discover_packages_blocking().await { - Ok(packages) => Ok(tonic::Response::new(proto::DiscoverPackagesResponse { - package_files: packages - .workspaces - .into_iter() - .map(|d| proto::PackageFiles { - package_json: d.package_json.to_string(), - turbo_json: d.turbo_json.map(|t| t.to_string()), - }) - .collect(), - package_manager: proto::PackageManager::from(packages.package_manager).into(), - })), - Err(PackageWatchError::Unavailable) => { - Err(tonic::Status::unavailable("package discovery unavailable")) - } - Err(PackageWatchError::InvalidState(reason)) => { - Err(tonic::Status::failed_precondition(reason)) - } - } - } - - type PackageChangesStream = ReceiverStream>; - - async fn package_changes( - &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - let mut package_changes_rx = self - .file_watching - .get_or_init_package_changes_watcher() - .package_changes() - .await; - - let (tx, rx) = mpsc::channel(4096); - - tx.send(Ok(proto::PackageChangeEvent { - event: Some(proto::package_change_event::Event::RediscoverPackages( - proto::RediscoverPackages {}, - )), - })) - .await - .map_err(|e| tonic::Status::unavailable(format!("{}", e)))?; - - tokio::spawn(async move { - loop { - let event = match package_changes_rx.recv().await { - Err(RecvError::Lagged(_)) => { - warn!("package changes stream lagged"); - proto::PackageChangeEvent { - event: Some(proto::package_change_event::Event::RediscoverPackages( - proto::RediscoverPackages {}, - )), - } - } - Err(err) => proto::PackageChangeEvent { - event: Some(proto::package_change_event::Event::Error( - proto::PackageChangeError { - message: err.to_string(), - }, - )), - }, - Ok(PackageChangeEvent::Package { name }) => proto::PackageChangeEvent { - event: Some(proto::package_change_event::Event::PackageChanged( - proto::PackageChanged { - package_name: name.to_string(), - }, - )), - }, - Ok(PackageChangeEvent::Rediscover) => proto::PackageChangeEvent { - event: Some(proto::package_change_event::Event::RediscoverPackages( - proto::RediscoverPackages {}, - )), - }, - }; - - if let Err(err) = tx.send(Ok(event)).await { - error!("package changes stream closed: {}", err); - break; - } - } - }); - - Ok(tonic::Response::new(ReceiverStream::new(rx))) - } -} - -/// Determine whether a server can serve a client's request based on its -/// version. -/// -/// When the `proto::VersionRange` is anything other than `Exact` it means that -/// the server's version must exceed the client's version. For example, if the -/// client is `1.2.3` and the server is `1.2.4`, then the client's request can -/// be served if the `proto::VersionRange` is `Patch`, `Minor`, or `Major`. -/// However, if the server is `1.3.0`, then the client's request can only be -/// served if the `proto::VersionRange` is `Minor` or `Major`. -fn compare_versions(client: Version, server: Version, constraint: proto::VersionRange) -> bool { - match constraint { - proto::VersionRange::Exact => client == server, - proto::VersionRange::Patch => { - client.major == server.major - && client.minor == server.minor - && client.patch <= server.patch - } - proto::VersionRange::Minor => client.major == server.major && client.minor <= server.minor, - // changes to major version is always incompatible - proto::VersionRange::Major => client.major == server.major, - } -} - -impl NamedService for TurboGrpcServiceInner { - const NAME: &'static str = "turborepo.Daemon"; -} - -#[cfg(test)] -mod test { - use std::{ - assert_matches::{self, assert_matches}, - time::{Duration, Instant}, - }; - - use futures::FutureExt; - use semver::Version; - use test_case::test_case; - use tokio::sync::oneshot; - use turbopath::AbsoluteSystemPathBuf; - use turborepo_repository::{ - discovery::{DiscoveryResponse, PackageDiscovery}, - package_manager::PackageManager, - }; - - use super::compare_versions; - use crate::daemon::{proto::VersionRange, CloseReason, Paths, TurboGrpcService}; - - #[test_case("1.2.3", "1.2.3", VersionRange::Exact, true ; "exact match")] - #[test_case("1.2.3", "1.2.3", VersionRange::Patch, true ; "patch match")] - #[test_case("1.2.3", "1.2.3", VersionRange::Minor, true ; "minor match")] - #[test_case("1.2.3", "1.2.3", VersionRange::Major, true ; "major match")] - #[test_case("1.2.3", "1.2.4", VersionRange::Exact, false ; "exact mismatch")] - #[test_case("1.2.3", "1.2.4", VersionRange::Patch, true ; "patch greater match")] - #[test_case("1.2.3", "1.2.4", VersionRange::Minor, true ; "minor greater match")] - #[test_case("1.2.3", "1.2.4", VersionRange::Major, true ; "major greater match")] - #[test_case("1.2.3", "1.2.2", VersionRange::Patch, false ; "patch lesser mismatch")] - #[test_case("1.2.3", "1.1.3", VersionRange::Patch, false ; "patch lesser minor mismatch")] - #[test_case("1.2.3", "1.1.0", VersionRange::Minor, false ; "minor lesser mismatch")] - #[test_case("1.2.3", "0.1.0", VersionRange::Major, false ; "major lesser mismatch")] - #[test_case("1.10.17-canary.0", "1.10.17-canary.1", VersionRange::Exact, false ; "canary mismatch")] - #[test_case("1.10.17-canary.0", "1.10.17-canary.1", VersionRange::Patch, true ; "canary match")] - #[test_case("1.0.0", "2.0.0", VersionRange::Major, false ; "major breaking changes")] - - fn version_match(a: &str, b: &str, constraint: VersionRange, expected: bool) { - assert_eq!( - compare_versions( - Version::parse(a).unwrap(), - Version::parse(b).unwrap(), - constraint - ), - expected - ) - } - - struct MockDiscovery; - impl PackageDiscovery for MockDiscovery { - async fn discover_packages( - &self, - ) -> Result< - turborepo_repository::discovery::DiscoveryResponse, - turborepo_repository::discovery::Error, - > { - Ok(DiscoveryResponse { - package_manager: PackageManager::Yarn, - workspaces: vec![], - }) - } - - async fn discover_packages_blocking( - &self, - ) -> Result< - turborepo_repository::discovery::DiscoveryResponse, - turborepo_repository::discovery::Error, - > { - self.discover_packages().await - } - } - - // the windows runner starts a new thread to accept uds requests, - // so we need a multi-threaded runtime - #[tokio::test(flavor = "multi_thread")] - #[tracing_test::traced_test] - async fn lifecycle() { - let tempdir = tempfile::tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tempdir.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let repo_root = path.join_component("repo"); - let paths = Paths::from_repo_root(&repo_root); - tracing::info!("start"); - - let (tx, rx) = oneshot::channel::(); - let exit_signal = rx.map(|_result| CloseReason::Interrupt); - - let service = TurboGrpcService::new( - repo_root.clone(), - paths.clone(), - Duration::from_secs(60 * 60), - exit_signal, - ); - - // the package watcher reads data from the package.json file - // so we need to create it - repo_root.create_dir_all().unwrap(); - let package_json = repo_root.join_component("package.json"); - package_json - .create_with_contents(r#"{"workspaces": ["packages/*"]}"#) - .unwrap(); - repo_root - .join_component("package-lock.json") - .create_with_contents("") - .unwrap(); - - let handle = tokio::task::spawn(service.serve()); - - tokio::time::sleep(Duration::from_millis(2000)).await; - assert!( - paths.pid_file.exists(), - "pid file must be present at {:?}", - paths.pid_file - ); - // signal server exit - tx.send(CloseReason::Interrupt).unwrap(); - handle.await.unwrap().unwrap(); - - // The serve future should be dropped here, closing the server. - tracing::info!("yay we are done"); - - assert!(!paths.pid_file.exists(), "pid file must be deleted"); - - tracing::info!("and files cleaned up"); - } - - // the windows runner starts a new thread to accept uds requests, - // so we need a multi-threaded runtime - #[tokio::test(flavor = "multi_thread")] - #[tracing_test::traced_test] - async fn timeout() { - let tempdir = tempfile::tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tempdir.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let repo_root = path.join_component("repo"); - let paths = Paths::from_repo_root(&repo_root); - - let now = Instant::now(); - let (_tx, rx) = oneshot::channel::(); - let exit_signal = rx.map(|_result| CloseReason::Interrupt); - - let server = TurboGrpcService::new( - repo_root.clone(), - paths.clone(), - Duration::from_millis(10), - exit_signal, - ); - - // the package watcher reads data from the package.json file - // so we need to create it - repo_root.create_dir_all().unwrap(); - let package_json = repo_root.join_component("package.json"); - package_json - .create_with_contents(r#"{"workspaces": ["packages/*"]}"#) - .unwrap(); - repo_root - .join_component("package-lock.json") - .create_with_contents("") - .unwrap(); - - let close_reason = server.serve().await; - - assert!( - now.elapsed() >= Duration::from_millis(10), - "must wait at least 5ms" - ); - assert_matches::assert_matches!( - close_reason, - Ok(CloseReason::Timeout), - "must close due to timeout" - ); - assert!(!paths.pid_file.exists(), "pid file must be deleted"); - } - - #[tokio::test(flavor = "multi_thread")] - #[tracing_test::traced_test] - async fn test_delete_root() { - let tempdir = tempfile::tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tempdir.path()) - .unwrap() - .to_realpath() - .unwrap(); - - let repo_root = path.join_component("repo"); - repo_root.create_dir_all().unwrap(); - let package_json = repo_root.join_component("package.json"); - package_json - .create_with_contents(r#"{"workspaces": ["packages/*"]}"#) - .unwrap(); - repo_root - .join_component("package-lock.json") - .create_with_contents("") - .unwrap(); - let paths = Paths::from_repo_root(&repo_root); - - let (_tx, rx) = oneshot::channel::(); - let exit_signal = rx.map(|_result| CloseReason::Interrupt); - - let server = TurboGrpcService::new( - repo_root.clone(), - paths, - Duration::from_secs(60 * 60), - exit_signal, - ); - - let handle = tokio::task::spawn(server.serve()); - - // give filewatching some time to bootstrap - tokio::time::sleep(Duration::from_secs(1)).await; - // Remove the root - repo_root.remove_dir_all().unwrap(); - - let close_reason = tokio::time::timeout(Duration::from_secs(1), handle) - .await - .expect("no timeout") - .expect("server exited"); - assert_matches!(close_reason, Ok(CloseReason::Shutdown)); - } -} diff --git a/crates/turborepo-lib/src/diagnostics.rs b/crates/turborepo-lib/src/diagnostics.rs deleted file mode 100644 index ed2780d4c3465..0000000000000 --- a/crates/turborepo-lib/src/diagnostics.rs +++ /dev/null @@ -1,551 +0,0 @@ -use std::{process::Stdio, sync::Arc, time::Duration}; - -use futures::future::join_all; -use tokio::{ - process::Command, - sync::{ - mpsc::{Receiver as MpscReceiver, Sender as MpscSender}, - oneshot::{self, Receiver, Sender}, - Mutex, - }, -}; -use turbo_updater::check_for_updates; -use turbopath::AbsoluteSystemPathBuf; -use turborepo_scm::Git; - -use crate::{ - commands::{ - link::{self, link}, - CommandBase, - }, - daemon::DaemonConnector, - get_version, DaemonPaths, -}; - -#[derive(Debug)] -pub enum DiagnosticMessage { - NotApplicable(String), - /// internal name of diag and human readable name - Started(String), - LogLine(String), - Done(String), - Failed(String), - /// a request to suspend terminal output. the renderer - /// will notify the diagnostic when it is safe to render - /// and the diagnostic notify in return when it is done - Suspend(Sender<()>, Receiver<()>), - /// a request to the user with options and a callback to send the response - Request(String, Vec, Sender), -} - -/// A light wrapper around a tokio channel with a must_use such that we ensure -/// the communication is always terminated and the diagnostic is always -/// notified, in absence of linear types. Unfortunately this lint is flaky -/// at best so while we can't solely rely on it to enforce the invariant, -/// it's better than nothing. -#[must_use] -#[derive(Clone)] -pub struct DiagnosticChannel(MpscSender); -impl DiagnosticChannel { - pub fn new() -> (Self, MpscReceiver) { - let (tx, rx) = tokio::sync::mpsc::channel(10); - (Self(tx), rx) - } - - async fn started(&self, message: String) { - self.send(DiagnosticMessage::Started(message)).await - } - - async fn log_line(&self, message: String) { - self.send(DiagnosticMessage::LogLine(message)).await - } - - /// prompts the user with a message and options - async fn request(&self, message: String, options: Vec) -> Option> { - let (tx, rx) = oneshot::channel(); - self.0 - .send(DiagnosticMessage::Request(message, options, tx)) - .await - .ok()?; // if the channel is closed, we can't request - Some(rx) - } - - /// suspends the terminal output and returns a pair of channels - /// - /// the first one signifies to the diagnostic when it is safe to render - /// and the second one is used by the diagnostic to notify the renderer - /// when it is done - async fn suspend(&self) -> Option<(Receiver<()>, Sender<()>)> { - let (stopped_tx, stopped_rx) = oneshot::channel(); - let (resume_tx, resume_rx) = oneshot::channel(); - - self.0 - .send(DiagnosticMessage::Suspend(stopped_tx, resume_rx)) - .await - .ok()?; // if the channel is closed, we can't suspend - - Some((stopped_rx, resume_tx)) - } - - // types of exit - - /// the diagnostic is done - async fn done(self, message: String) { - self.send(DiagnosticMessage::Done(message.to_string())) - .await - } - - /// the diagnostic failed - async fn failed(self, message: String) { - self.send(DiagnosticMessage::Failed(message.to_string())) - .await - } - - /// the diagnostic is not applicable - async fn not_applicable(self, message: String) { - self.send(DiagnosticMessage::NotApplicable(message.to_string())) - .await - } - - pub async fn send(&self, message: DiagnosticMessage) { - _ = self.0.send(message).await // channel closed, ignore - } -} - -// sadly, because we want to use this trait as a trait object, we can't use -// async fn in the trait definition since it desugars to associated types -// which aren't compatible with trait objects. we _can_ box the futures though, -// which is what async_trait does for us. rather than add a dep, lets just -// use the one we use for the daemon though tonic -#[tonic::async_trait] -pub trait Diagnostic { - // this needs to have a self param so it can be a trait object - fn name(&self) -> &'static str; - - /// Execute a diagnostic. You _must_ call `DiagnosticChannel::started` when - /// the diag has begun, and dispose of the channel by calling one of the - /// three exit methods identified by consuming `self`. - fn execute(&self, chan: DiagnosticChannel); -} - -pub struct GitDaemonDiagnostic; - -impl Diagnostic for GitDaemonDiagnostic { - fn name(&self) -> &'static str { - "git.daemon" - } - - fn execute(&self, chan: DiagnosticChannel) { - tokio::task::spawn(async move { - chan.started("Git FS Monitor".to_string()).await; - - if !(cfg!(target_os = "windows") || cfg!(target_os = "macos")) { - // the git daemon is not implemented on unix - chan.not_applicable("Git FS Monitor (not available on linux)".to_string()) - .await; - return; - } - - let commands: Result>, _> = join_all( - [ - &["--version"][..], - &["config", "--get", "core.fsmonitor"][..], - &["config", "--get", "core.untrackedcache"][..], - ] - .into_iter() - .map(|args| async move { - // get the current setting - let stdout = Stdio::piped(); - - let Ok(git_path) = Git::find_bin() else { - return Err("git not found"); - }; - - let command = Command::new(git_path.as_path()) - .args(args) - .stdout(stdout) - .stdin(Stdio::null()) - .spawn() - .expect("too many processes"); // this can only fail if we run out of processes on unix - - command - .wait_with_output() - .await - .map(|d| d.stdout) - .map_err(|_| "failed to get git metadata") - }), - ) - .await - .into_iter() - .collect(); // transpose - - chan.log_line("Collecting metadata".to_string()).await; - - match commands.as_ref().map(|v| v.as_slice()) { - Ok([version, fsmonitor, untrackedcache]) => { - let version = String::from_utf8_lossy(version); - let Some(version) = version.trim().strip_prefix("git version ") else { - chan.failed("Failed to get git version".to_string()).await; - return; - }; - - // attempt to split out the apple git suffix - let version = if let Some((version, _)) = version.split_once(" (Apple") { - version - } else { - version - }; - - let Ok(version) = semver::Version::parse(version) else { - chan.failed("Failed to parse git version".to_string()).await; - return; - }; - - if version.major == 2 && version.minor < 37 || version.major == 1 { - chan.not_applicable(format!( - "Git version {} is too old, please upgrade to 2.37 or newer", - version - )) - .await; - return; - } else { - chan.log_line( - format!("Using supported Git version - {}", version).to_string(), - ) - .await; - } - - let fsmonitor = String::from_utf8_lossy(fsmonitor); - let untrackedcache = String::from_utf8_lossy(untrackedcache); - - if fsmonitor.trim() != "true" || untrackedcache.trim() != "true" { - chan.log_line("Git FS Monitor not configured".to_string()) - .await; - chan.log_line( "For more information, see https://turbo.build/repo/docs/reference/command-line-reference/scan#fs-monitor".to_string()).await; - let Some(resp) = chan - .request( - "Configure it for this repo now?".to_string(), - vec!["Yes".to_string(), "No".to_string()], - ) - .await - else { - // the sender (terminal) was shut, ignore - return; - }; - match resp.await.as_ref().map(|s| s.as_str()) { - Ok("Yes") => { - chan.log_line("Setting Git FS Monitor settings".to_string()) - .await; - - let futures = [ - ("core.fsmonitor", fsmonitor), - ("core.untrackedcache", untrackedcache), - ] - .into_iter() - .filter(|(_, value)| value.trim() != "true") - .map(|(key, _)| async { - let stdout = Stdio::piped(); - - let command = Command::new("git") - .args(["config", key, "true"]) - .stdout(stdout) - .spawn() - .expect("too many processes"); // this can only fail if we run out of processes on unix - - command.wait_with_output().await - }); - - let results: Result, _> = - join_all(futures).await.into_iter().collect(); - - match results { - Ok(_) => { - chan.log_line("Git FS Monitor settings set".to_string()) - .await; - } - Err(e) => { - chan.failed(format!("Failed to set git settings: {}", e)) - .await; - return; - } - } - } - Ok("No") => { - chan.failed("Git FS Monitor not configured".to_string()) - .await; - return; - } - Ok(_) => unreachable!(), - Err(_) => { - // the sender (terminal) was shut, ignore - } - } - } else { - chan.log_line("Git FS Monitor settings set".to_string()) - .await; - } - } - Ok(_) => unreachable!(), // the vec of futures has exactly 3 elements - Err(e) => { - chan.failed(format!("Failed to get git version: {}", e)) - .await; - return; - } - } - - chan.done("Git FS Monitor enabled".to_string()).await; - }); - } -} - -pub struct DaemonDiagnostic(pub DaemonPaths); - -impl Diagnostic for DaemonDiagnostic { - fn name(&self) -> &'static str { - "turbo.daemon" - } - - fn execute(&self, chan: DiagnosticChannel) { - let paths = self.0.clone(); - tokio::task::spawn(async move { - chan.started("Turbo Daemon".to_string()).await; - chan.log_line("Connecting to daemon...".to_string()).await; - - let pid_path = paths.pid_file.as_std_path().to_owned(); - - let connector = DaemonConnector { - can_kill_server: false, - can_start_server: true, - paths, - }; - - let mut client = match connector.connect().await { - Ok(client) => client, - Err(e) => { - chan.failed(format!("Failed to connect to daemon: {}", e)) - .await; - return; - } - }; - - chan.log_line("Getting status...".to_string()).await; - - match client.status().await { - Ok(status) => { - chan.log_line(format!("Daemon up for {}ms", status.uptime_msec)) - .await; - let lock = pidlock::Pidlock::new(pid_path); - let pid = if let Ok(Some(owner)) = lock.get_owner() { - format!(" (pid {})", owner) - } else { - "".to_string() - }; - chan.done(format!("Daemon is running{}", pid)).await; - } - Err(e) => { - chan.failed(format!("Failed to get daemon status: {}", e)) - .await; - } - } - }); - } -} - -pub struct LSPDiagnostic(pub DaemonPaths); -impl Diagnostic for LSPDiagnostic { - fn name(&self) -> &'static str { - "turbo.lsp" - } - - fn execute(&self, chan: DiagnosticChannel) { - let lsp_root = self.0.lsp_pid_file.as_std_path().to_owned(); - tokio::task::spawn(async move { - chan.started("Turborepo Extension".to_string()).await; - chan.log_line("Checking if extension is running...".to_string()) - .await; - let pidlock = pidlock::Pidlock::new(lsp_root); - match pidlock.get_owner() { - Ok(Some(pid)) => { - chan.done(format!("Turborepo Extension is running (pid {})", pid)) - .await; - } - Ok(None) => { - chan.log_line("Unable to find LSP instance".to_string()) - .await; - chan.log_line( "For more information, see https://turbo.build/repo/docs/reference/command-line-reference/scan#lsp".to_string()).await; - chan.failed("Turborepo Extension is not running".to_string()) - .await; - } - Err(e) => { - chan.failed(format!("Failed to get LSP status: {}", e)) - .await; - } - } - }); - } -} - -/// a struct that checks and prompts the user to enable remote cache -pub struct RemoteCacheDiagnostic(pub Arc>); -impl RemoteCacheDiagnostic { - pub fn new(base: CommandBase) -> Self { - Self(Arc::new(Mutex::new(base))) - } -} - -impl Diagnostic for RemoteCacheDiagnostic { - fn name(&self) -> &'static str { - "vercel.auth" - } - - fn execute(&self, chan: DiagnosticChannel) { - let base = self.0.clone(); - tokio::task::spawn(async move { - chan.started("Remote Cache".to_string()).await; - - let (has_team_id, has_team_slug) = { - let base = base.lock().await; - ( - base.opts().api_client_opts.team_id.is_some(), - base.opts().api_client_opts.team_slug.is_some(), - ) - }; - - chan.log_line("Checking credentials".to_string()).await; - - if has_team_id || has_team_slug { - chan.done("Remote Cache enabled".to_string()).await; - return; - } - - let result = { - chan.log_line("Linking to remote cache".to_string()).await; - let mut base = base.lock().await; - let Some((stopped, resume)) = chan.suspend().await else { - // the sender (terminal) was shut, ignore - return; - }; - stopped.await.unwrap(); - let link_res = link( - &mut base, - None, - false, - false, - crate::cli::LinkTarget::RemoteCache, - ) - .await; - resume.send(()).unwrap(); - link_res - }; - - match result { - Ok(_) => { - chan.log_line("Linked".to_string()).await; - chan.done("Remote Cache enabled".to_string()).await - } - Err(link::Error::NotLinking) => { - chan.not_applicable("Remote Cache opted out".to_string()) - .await - } - Err(e) => { - chan.failed(format!("Failed to link: {}", e)).await; - } - } - }); - } -} - -pub struct UpdateDiagnostic(pub AbsoluteSystemPathBuf); - -impl Diagnostic for UpdateDiagnostic { - fn name(&self) -> &'static str { - "turbo.update" - } - - fn execute(&self, chan: DiagnosticChannel) { - let repo_root = self.0.clone(); - tokio::task::spawn(async move { - chan.started("Update Turborepo to latest version".to_string()) - .await; - chan.log_line("Checking for updates...".to_string()).await; - let version = tokio::task::spawn_blocking(|| { - check_for_updates( - "turbo", - get_version(), - None, - Some(Duration::from_secs(0)), // check every time - ) - .map_err(|e| e.to_string()) // not send - }) - .await; - - match version { - Ok(Ok(Some(version))) => { - chan.log_line(format!("Turborepo {} is available", version).to_string()) - .await; - - let Some(resp) = chan - .request( - "Would you like to run the codemod automatically?".to_string(), - vec!["Yes".to_string(), "No".to_string()], - ) - .await - else { - // the sender (terminal) was shut, ignore - return; - }; - - match resp.await.as_ref().map(|s| s.as_str()) { - Ok("Yes") => { - chan.log_line("Updating Turborepo...".to_string()).await; - let mut command = Command::new("npx"); - let command = command - .arg("--yes") - .arg("@turbo/codemod@latest") - .arg("update") - .arg("--force") - .arg(repo_root.as_path()) - .stdout(Stdio::piped()) - .stdin(Stdio::null()) - .spawn() - .expect("too many processes"); // this can only fail if we run out of processes on unix - - match command.wait_with_output().await { - Ok(output) if output.status.success() => { - chan.done("Turborepo on latest version".to_string()).await; - } - Ok(output) => { - chan.log_line( - String::from_utf8(output.stdout).unwrap_or_default(), - ) - .await; - chan.failed("Unable to update Turborepo".to_string()).await - } - Err(_) => { - chan.failed("Unable to update Turborepo".to_string()).await - } - } - } - Ok("No") => chan.failed("Turborepo on old version".to_string()).await, - Ok(_) => unreachable!(), // yes and no are the only options - Err(_) => { - // the sender (terminal) was shut, ignore - } - } - } - // no versions in the registry, just report success - Ok(Ok(None)) => { - chan.log_line("No updates available".to_string()).await; - chan.done("Turborepo on latest version".to_string()).await - } - Ok(Err(message)) => { - chan.failed(format!("Failed to check for updates: {}", message)) - .await; - } - Err(_) => { - chan.failed("Failed to check for updates".to_string()).await; - } - } - }); - } -} diff --git a/crates/turborepo-lib/src/engine/dot.rs b/crates/turborepo-lib/src/engine/dot.rs deleted file mode 100644 index ecd838ddaf613..0000000000000 --- a/crates/turborepo-lib/src/engine/dot.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::io; - -use petgraph::{visit::EdgeRef, Graph}; - -use super::{Built, Engine, TaskNode}; - -impl Engine { - pub fn dot_graph(&self, writer: W, is_single: bool) -> Result<(), io::Error> { - let display_node = match is_single { - true => |node: &TaskNode| match node { - TaskNode::Root => node.to_string(), - TaskNode::Task(task) => task.task().to_string(), - }, - false => |node: &TaskNode| node.to_string(), - }; - render_graph(&self.task_graph, display_node, writer) - } -} - -const GRAPH_PRELUDE: &str = "\ndigraph {\n\tcompound = \"true\" -\tnewrank = \"true\" -\tsubgraph \"root\" { -"; - -fn render_graph( - graph: &Graph, - mut display_node: impl FnMut(&N) -> String, - mut writer: impl io::Write, -) -> Result<(), io::Error> { - let mut get_node = |i| { - display_node( - graph - .node_weight(i) - .expect("node index should exist in graph"), - ) - }; - - // These are hardcoded writes from the Go side that we just copy - writer.write_all(GRAPH_PRELUDE.as_bytes())?; - - let mut edges = graph - .edge_references() - .map(|edge| { - let source = get_node(edge.source()); - let target = get_node(edge.target()); - format!("\t\t\"[root] {source}\" -> \"[root] {target}\"") - }) - .collect::>(); - edges.sort(); - - writer.write_all(edges.join("\n").as_bytes())?; - - writer.write_all("\n\t}\n}\n\n".as_bytes())?; - Ok(()) -} - -#[cfg(test)] -mod test { - use pretty_assertions::assert_eq; - - use super::*; - - #[test] - fn test_simple_graph_output() { - let mut bytes = Vec::new(); - let mut graph = Graph::new(); - let root = graph.add_node("___ROOT___"); - let build = graph.add_node("build"); - graph.add_edge(root, build, ()); - render_graph(&graph, |n| n.to_string(), &mut bytes).unwrap(); - assert_eq!( - String::from_utf8(bytes).unwrap(), - "\ndigraph { -\tcompound = \"true\" -\tnewrank = \"true\" -\tsubgraph \"root\" { -\t\t\"[root] ___ROOT___\" -> \"[root] build\" -\t} -}\n\n" - ); - } -} diff --git a/crates/turborepo-lib/src/engine/execute.rs b/crates/turborepo-lib/src/engine/execute.rs deleted file mode 100644 index e0fca435c1b42..0000000000000 --- a/crates/turborepo-lib/src/engine/execute.rs +++ /dev/null @@ -1,153 +0,0 @@ -use std::sync::{Arc, Mutex}; - -use futures::{stream::FuturesUnordered, StreamExt}; -use tokio::sync::{mpsc, oneshot, Semaphore}; -use tracing::log::debug; -use turborepo_graph_utils::Walker; - -use super::{Engine, TaskNode}; -use crate::run::task_id::TaskId; - -pub struct Message { - pub info: T, - pub callback: oneshot::Sender, -} - -// Type alias used just to make altering the data sent to the visitor easier in -// the future -type VisitorData = TaskId<'static>; -type VisitorResult = Result<(), StopExecution>; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct ExecutionOptions { - parallel: bool, - concurrency: usize, -} - -impl ExecutionOptions { - pub fn new(parallel: bool, concurrency: usize) -> Self { - Self { - parallel, - concurrency, - } - } -} - -#[derive(Debug, thiserror::Error)] -pub enum ExecuteError { - #[error("Semaphore closed before all tasks finished")] - Semaphore(#[from] tokio::sync::AcquireError), - #[error("Engine visitor closed channel before walk finished")] - Visitor, -} - -impl From>> for ExecuteError { - fn from( - _: mpsc::error::SendError, Result<(), StopExecution>>>, - ) -> Self { - ExecuteError::Visitor - } -} - -#[derive(Debug, Clone, Copy)] -pub struct StopExecution; - -impl Engine { - /// Execute a task graph by sending task ids to the visitor - /// while respecting concurrency limits. - /// The visitor is expected to handle any error handling on its end. - /// We enforce this by only allowing the returning of a sentinel error - /// type which will stop any further execution of tasks. - /// This will not stop any task which is currently running, simply it will - /// stop scheduling new tasks. - // (olszewski) The current impl requires that the visitor receiver is read until - // finish even once a task sends back the stop signal. This is suboptimal - // since it would mean the visitor would need to also track if - // it is cancelled :) - pub async fn execute( - self: Arc, - options: ExecutionOptions, - visitor: mpsc::Sender>, - ) -> Result<(), ExecuteError> { - let ExecutionOptions { - parallel, - concurrency, - } = options; - let sema = Arc::new(Semaphore::new(concurrency)); - let mut tasks: FuturesUnordered>> = - FuturesUnordered::new(); - - let (walker, mut nodes) = Walker::new(&self.task_graph).walk(); - let walker = Arc::new(Mutex::new(walker)); - - while let Some((node_id, done)) = nodes.recv().await { - let visitor = visitor.clone(); - let sema = sema.clone(); - let walker = walker.clone(); - let this = self.clone(); - - tasks.push(tokio::spawn(async move { - let TaskNode::Task(task_id) = this - .task_graph - .node_weight(node_id) - .expect("node id should be present") - else { - // Root task has nothing to do so we don't emit any event for it - if done.send(()).is_err() { - debug!( - "Graph walker done callback receiver was closed before done signal \ - could be sent" - ); - } - return Ok(()); - }; - - // Acquire the semaphore unless parallel - let _permit = match parallel { - false => Some(sema.acquire().await.expect( - "Graph concurrency semaphore closed while tasks are still attempting to \ - acquire permits", - )), - true => None, - }; - - let (message, result) = Message::new(task_id.clone()); - visitor.send(message).await?; - - if let Err(StopExecution) = result.await.unwrap_or_else(|_| { - // If the visitor doesn't send a callback, then we assume the task finished - tracing::trace!( - "Engine visitor dropped callback sender without sending result" - ); - Ok(()) - }) { - if walker - .lock() - .expect("Walker mutex poisoned") - .cancel() - .is_err() - { - debug!("Unable to cancel graph walk"); - } - } - if done.send(()).is_err() { - debug!("Graph walk done receiver closed before node was finished processing"); - } - Ok(()) - })); - } - - while let Some(res) = tasks.next().await { - res.expect("unable to join task")?; - } - - Ok(()) - } -} - -impl Message { - pub fn new(info: T) -> (Self, oneshot::Receiver) { - let (callback, receiver) = oneshot::channel(); - (Self { info, callback }, receiver) - } -} diff --git a/crates/turborepo-lib/src/engine/mermaid.rs b/crates/turborepo-lib/src/engine/mermaid.rs deleted file mode 100644 index d0720354ef016..0000000000000 --- a/crates/turborepo-lib/src/engine/mermaid.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::{collections::HashMap, io}; - -use itertools::Itertools; -use petgraph::{visit::EdgeRef, Graph}; -use rand::{distributions::Uniform, prelude::Distribution, Rng, SeedableRng}; - -use super::{Built, Engine, TaskNode}; - -struct CapitalLetters; - -impl Distribution for CapitalLetters { - fn sample(&self, rng: &mut R) -> char { - const RANGE: u32 = 26; - const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - let range = Uniform::new(0u32, GEN_ASCII_STR_CHARSET.len() as u32); - char::from_u32(GEN_ASCII_STR_CHARSET[range.sample(rng) as usize] as u32) - .expect("random number should be in bounds") - } -} - -fn generate_id(rng: &mut R) -> String { - CapitalLetters.sample_iter(rng).take(4).join("") -} - -impl Engine { - pub fn mermaid_graph(&self, writer: W, is_single: bool) -> Result<(), io::Error> { - render_graph(writer, &self.task_graph, is_single) - } -} - -fn render_graph( - mut writer: W, - graph: &Graph, - is_single: bool, -) -> Result<(), io::Error> { - // Chosen randomly. - // Pick a constant seed so that the same graph generates the same nodes every - // time. This is not a security-sensitive operation, it's just aliases for - // the graph nodes. - let mut rng = rand::rngs::SmallRng::seed_from_u64(4u64); - - let display_node = match is_single { - true => |node: &TaskNode| match node { - TaskNode::Root => node.to_string(), - TaskNode::Task(task) => task.task().to_string(), - }, - false => |node: &TaskNode| node.to_string(), - }; - - let mut edges = graph - .edge_references() - .map(|e| { - ( - display_node( - graph - .node_weight(e.source()) - .expect("node index should exist in graph"), - ), - display_node( - graph - .node_weight(e.target()) - .expect("node index should exist in graph"), - ), - ) - }) - .collect::>(); - edges.sort(); - - writeln!(writer, "graph TD")?; - let mut name_cache = HashMap::::new(); - for (src, target) in edges { - let src_name = name_cache - .entry(src.clone()) - .or_insert_with(|| generate_id(&mut rng)); - write!(writer, "\t{src_name}(\"{src}\") --> ")?; - let target_name = name_cache - .entry(target.clone()) - .or_insert_with(|| generate_id(&mut rng)); - writeln!(writer, "{target_name}(\"{target}\")")?; - } - Ok(()) -} diff --git a/crates/turborepo-lib/src/framework.rs b/crates/turborepo-lib/src/framework.rs deleted file mode 100644 index 59d22c51586d8..0000000000000 --- a/crates/turborepo-lib/src/framework.rs +++ /dev/null @@ -1,202 +0,0 @@ -use std::sync::OnceLock; - -use serde::Deserialize; -use turborepo_repository::package_graph::PackageInfo; - -#[derive(Debug, PartialEq, Deserialize)] -#[serde(rename_all = "camelCase")] -enum Strategy { - All, - Some, -} - -#[derive(Debug, PartialEq, Deserialize)] -#[serde(rename_all = "camelCase")] -struct Matcher { - strategy: Strategy, - dependencies: Vec, -} - -#[derive(Debug, PartialEq, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Framework { - slug: String, - env_wildcards: Vec, - dependency_match: Matcher, -} - -impl Framework { - pub fn slug(&self) -> String { - self.slug.clone() - } - - pub fn env_wildcards(&self) -> &[String] { - &self.env_wildcards - } -} - -static FRAMEWORKS: OnceLock> = OnceLock::new(); - -const FRAMEWORKS_JSON: &str = - include_str!("../../../packages/turbo-types/src/json/frameworks.json"); - -fn get_frameworks() -> &'static Vec { - FRAMEWORKS.get_or_init(|| { - serde_json::from_str(FRAMEWORKS_JSON).expect("Unable to parse embedded JSON") - }) -} - -impl Matcher { - pub fn test(&self, workspace: &PackageInfo, is_monorepo: bool) -> bool { - // In the case where we're not in a monorepo, i.e. single package mode - // `unresolved_external_dependencies` is not populated. In which - // case we should check `dependencies` instead. - let deps = if is_monorepo { - workspace.unresolved_external_dependencies.as_ref() - } else { - workspace.package_json.dependencies.as_ref() - }; - - match self.strategy { - Strategy::All => self - .dependencies - .iter() - .all(|dep| deps.is_some_and(|deps| deps.contains_key(dep))), - Strategy::Some => self - .dependencies - .iter() - .any(|dep| deps.is_some_and(|deps| deps.contains_key(dep))), - } - } -} - -pub fn infer_framework(workspace: &PackageInfo, is_monorepo: bool) -> Option<&Framework> { - let frameworks = get_frameworks(); - - frameworks - .iter() - .find(|framework| framework.dependency_match.test(workspace, is_monorepo)) -} - -#[cfg(test)] -mod tests { - use test_case::test_case; - use turborepo_repository::{package_graph::PackageInfo, package_json::PackageJson}; - - use crate::framework::{get_frameworks, infer_framework, Framework}; - - fn get_framework_by_slug(slug: &str) -> &Framework { - get_frameworks() - .iter() - .find(|framework| framework.slug == slug) - .expect("framework not found") - } - - #[test_case(PackageInfo::default(), None, true; "empty dependencies")] - #[test_case( - PackageInfo { - unresolved_external_dependencies: Some( - vec![("blitz".to_string(), "*".to_string())].into_iter().collect() - ), - ..Default::default() - }, - Some(get_framework_by_slug("blitzjs")), - true; - "blitz" - )] - #[test_case( - PackageInfo { - unresolved_external_dependencies: Some( - vec![("blitz", "*"), ("next", "*")] - .into_iter() - .map(|(s1, s2)| (s1.to_string(), s2.to_string())) - .collect() - ), - ..Default::default() - }, - Some(get_framework_by_slug("blitzjs")), - true; - "Order is preserved (returns blitz, not next)" - )] - #[test_case( - PackageInfo { - unresolved_external_dependencies: Some( - vec![("next", "*")] - .into_iter() - .map(|(s1, s2)| (s1.to_string(), s2.to_string())) - .collect() - ), - ..Default::default() - }, - Some(get_framework_by_slug("nextjs")), - true; - "Finds next without blitz" - )] - #[test_case( - PackageInfo { - unresolved_external_dependencies: Some( - vec![("solid-js", "*"), ("solid-start", "*")] - .into_iter() - .map(|(s1, s2)| (s1.to_string(), s2.to_string())) - .collect() - ), - ..Default::default() - }, - Some(get_framework_by_slug("solidstart")), - true; - "match all strategy works (solid)" - )] - #[test_case( - PackageInfo { - unresolved_external_dependencies: Some( - vec![("nuxt3", "*")] - .into_iter() - .map(|(s1, s2)| (s1.to_string(), s2.to_string())) - .collect() - ), - ..Default::default() - }, - Some(get_framework_by_slug("nuxtjs")), - true; - "match some strategy works (nuxt)" - )] - #[test_case( - PackageInfo { - unresolved_external_dependencies: Some( - vec![("react-scripts", "*")] - .into_iter() - .map(|(s1, s2)| (s1.to_string(), s2.to_string())) - .collect() - ), - ..Default::default() - }, - Some(get_framework_by_slug("create-react-app")), - true; - "match some strategy works (create-react-app)" - )] - #[test_case( - PackageInfo { - package_json: PackageJson { - dependencies: Some( - vec![("next", "*")] - .into_iter() - .map(|(s1, s2)| (s1.to_string(), s2.to_string())) - .collect() - ), - ..Default::default() - }, - ..Default::default() - }, - Some(get_framework_by_slug("nextjs")), - false; - "Finds next in non-monorepo" - )] - fn test_infer_framework( - workspace_info: PackageInfo, - expected: Option<&Framework>, - is_monorepo: bool, - ) { - let framework = infer_framework(&workspace_info, is_monorepo); - assert_eq!(framework, expected); - } -} diff --git a/crates/turborepo-lib/src/globwatcher/mod.rs b/crates/turborepo-lib/src/globwatcher/mod.rs deleted file mode 100644 index f1cf24dfa78d5..0000000000000 --- a/crates/turborepo-lib/src/globwatcher/mod.rs +++ /dev/null @@ -1,728 +0,0 @@ -use std::{ - collections::{hash_map::Entry, HashMap, HashSet}, - path::{Path, PathBuf}, - sync::{Arc, Mutex, MutexGuard}, - time::Duration, -}; - -use futures::{stream::iter, StreamExt}; -use globwatch::{ConfigError, GlobWatcher, StopToken, WatchConfig, WatchError, Watcher}; -use itertools::Itertools; -use notify::{EventKind, RecommendedWatcher}; -use thiserror::Error; -use tokio::time::timeout; -use tracing::{trace, warn}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathError}; -use wax::{Glob as WaxGlob, Program}; - -// these aliases are for readability, but they're just strings. it may make -// sense to use a newtype wrapper for these types in the future. -type Glob = Arc; -type Hash = Arc; - -/// timeout for flushing the watcher -const FLUSH_TIMEOUT: Duration = Duration::from_millis(500); - -/// Tracks changes for a given hash. A hash is a unique identifier for a set of -/// files. Given a hash and a set of globs to track, this will watch for file -/// changes and allow the user to query for changes. Once all globs for a -/// particular hash have changed, that hash is no longer tracked. -#[derive(Clone)] -pub struct HashGlobWatcher { - relative_to: PathBuf, - - /// maintains the list of to watch for a given hash - hash_globs: Arc>>, - - /// maps a glob to the hashes for which this glob hasn't changed - glob_statuses: Arc>>>, - - #[allow(dead_code)] - watcher: Arc>>, - config: WatchConfig, -} - -#[derive(Clone, Debug)] -pub struct GlobSet { - include: HashSet, - exclude: HashSet, -} - -#[derive(Debug, Error)] -pub enum HashGlobSetupError { - #[error("failed to start tracking hash-globs {0}")] - WatchError(#[from] WatchError), - #[error("failed to calculate relative path for hash-glob watching ({1}): {0}")] - PathError(PathError, AbsoluteSystemPathBuf), -} - -impl HashGlobWatcher { - #[tracing::instrument] - pub fn new( - relative_to: &AbsoluteSystemPath, - flush_folder: &AbsoluteSystemPath, - ) -> Result { - let (watcher, config) = GlobWatcher::new(flush_folder)?; - let relative_to = relative_to - .to_realpath() - .map_err(|e| HashGlobSetupError::PathError(e, relative_to.to_owned()))? - .as_std_path() - .to_owned(); - Ok(Self { - relative_to, - hash_globs: Default::default(), - glob_statuses: Default::default(), - watcher: Arc::new(Mutex::new(Some(watcher))), - config, - }) - } -} - -impl HashGlobWatcher { - /// Watches a given path, using the flush_folder as temporary storage to - /// make sure that file events are handled in the appropriate order. - #[tracing::instrument(skip(self, token))] - pub async fn watch(&self, token: StopToken) -> Result<(), ConfigError> { - let start_globs = { - let lock = self.hash_globs.lock().expect("only fails if poisoned"); - lock.iter() - .flat_map(|(_, g)| &g.include) - .cloned() - .collect::>() - }; - - let watcher = self.watcher.lock().expect("only fails if poisoned").take(); - let mut stream = match watcher { - Some(watcher) => watcher.into_stream(token), - None => { - warn!("watcher already consumed"); - return Err(ConfigError::WatchingAlready); - } - }; - - // watch the root of the repo to shut down if the folder is deleted - self.config.include_path(&self.relative_to).await?; - - // watch all the globs currently in the map - for glob in start_globs { - self.config.include(&self.relative_to, &glob).await.ok(); - } - - while let Some(Ok(result)) = stream.next().await { - let event = result?; - if event.paths.contains(&self.relative_to) && matches!(event.kind, EventKind::Remove(_)) - { - // if the root of the repo is deleted, we shut down - trace!("repo root was removed, shutting down"); - break; - } - - let repo_relative_paths = event - .paths - .iter() - .filter_map(|path| path.strip_prefix(&self.relative_to).ok()); - - // put these in a block so we can drop the locks before we await - let globs_to_exclude = { - let glob_statuses = self.glob_statuses.lock().expect("only fails if poisoned"); - let hash_globs = self.hash_globs.lock().expect("only fails if poisoned"); - - // hash globs is unlocked after this - let (hash_globs_to_clear, globs_to_exclude) = - populate_hash_globs(&glob_statuses, repo_relative_paths, hash_globs); - - // glob_statuses is unlocked after this - clear_hash_globs(glob_statuses, hash_globs_to_clear); - - globs_to_exclude - }; - - for glob in globs_to_exclude { - self.config.exclude(&self.relative_to, &glob).await; - } - } - - Ok(()) - } - - /// registers a hash with a set of globs to watch for changes - pub async fn watch_globs< - Iter: IntoIterator, - Iter2: IntoIterator, - >( - &self, - hash: Hash, - include: Iter, - exclude: Iter2, - ) -> Result<(), ConfigError> { - // wait for a the watcher to flush its events - // that will ensure that we have seen all filesystem writes - // *by the calling client*. Other tasks _could_ write to the - // same output directories, however we are relying on task - // execution dependencies to prevent that. - // - // this is a best effort, and times out after 500ms in - // case there is a lot of activity on the filesystem - match timeout(FLUSH_TIMEOUT, self.config.flush()).await { - Ok(Ok(())) => {} - Ok(Err(e)) => { - return Err(e); - } - Err(_) => { - trace!("timed out waiting for flush"); - } - } - - let include: HashSet<_> = include.into_iter().map(Arc::new).collect(); - let exclude = exclude.into_iter().map(Arc::new).collect(); - - let result: Vec<(Glob, ConfigError)> = iter(include.iter()) - .then(|glob| async move { - ( - glob.clone(), - self.config.include(self.relative_to.as_path(), glob).await, - ) - }) - .filter_map(|(glob, res)| async { - match res { - Ok(_) => None, - Err(err) => Some((glob, err)), - } - }) - .collect() - .await; - - { - let mut glob_statuses = self.glob_statuses.lock().expect("only fails if poisoned"); - for glob in include.iter() { - glob_statuses - .entry(glob.clone()) - .or_default() - .insert(hash.clone()); - } - } - - { - let mut hash_globs = self.hash_globs.lock().expect("only fails if poisoned"); - hash_globs.insert(hash.clone(), GlobSet { include, exclude }); - } - - if !result.is_empty() { - // we now 'undo' the failed watches if we encountered errors watching any - // globs, and return an error - - let hash_globs_to_clear = result - .iter() - .map(|(glob, _)| (hash.clone(), glob.clone())) - .collect(); - - let glob_statuses = self.glob_statuses.lock().expect("only fails if poisoned"); - // mutex is consumedd here - clear_hash_globs(glob_statuses, hash_globs_to_clear); - - use ConfigError::*; - Err(result - .into_iter() - .fold(WatchError(vec![]), |acc, (_, err)| { - // accumulate any watch errors, but override if the server stopped - match (acc, err) { - (WatchError(_), ServerStopped) => ServerStopped, - (WatchError(files), WatchError(files2)) => { - WatchError(files.into_iter().chain(files2).collect()) - } - (err, _) => err, - } - })) - } else { - Ok(()) - } - } - - /// given a hash and a set of candidates, return the subset of candidates - /// that have changed. - pub async fn changed_globs( - &self, - hash: &Hash, - mut candidates: HashSet, - ) -> Result, ConfigError> { - // wait for a the watcher to flush its events - // that will ensure that we have seen all filesystem writes - // *by the calling client*. Other tasks _could_ write to the - // same output directories, however we are relying on task - // execution dependencies to prevent that. - // - // this is a best effort, and times out after 500ms in - // case there is a lot of activity on the filesystem - match timeout(FLUSH_TIMEOUT, self.config.flush()).await { - Ok(Ok(())) => {} - Ok(Err(e)) => return Err(e), - Err(_) => { - trace!("timed out waiting for flush"); - } - } - - // hash_globs tracks all unchanged globs for a given hash. - // if a hash is not in globs, then either everything has changed - // or it was never registered. either way, we return all candidates - let hash_globs = self.hash_globs.lock().expect("only fails if poisoned"); - Ok(match hash_globs.get(hash) { - Some(glob) => { - candidates.retain(|c| !glob.include.contains(c)); - candidates - } - None => candidates, - }) - } -} - -/// iterate each path-glob pair and stop tracking globs whose files have -/// changed. if a path is not a valid utf8 string, it is ignored. this is -/// okay, because we don't register any paths that are not valid utf8, -/// since the source globs are valid utf8 -/// -/// returns a list of hash-glob pairs to clear, and a list of globs to exclude -/// -/// note: we take a mutex guard to make sure that the mutex is dropped -/// when the function returns -#[allow(dead_code)] -#[allow(clippy::type_complexity)] -fn populate_hash_globs<'a>( - glob_statuses: &MutexGuard>>, - repo_relative_paths: impl Iterator + Clone, - mut hash_globs: MutexGuard>, -) -> (Vec<(Arc, Arc)>, Vec>) { - let mut clear_glob_status = vec![]; - let mut exclude_globs = vec![]; - - // for every path, check to see if it matches any of the globs - // if it does, then we need to stop watching that glob - for ((glob, hash_status), path) in glob_statuses - .iter() - .cartesian_product(repo_relative_paths) - .filter(|((glob, _), path)| { - let glob = WaxGlob::new(glob).expect("only watch valid globs"); - glob.is_match(*path) - }) - { - let mut stop_watching = true; - - // for every hash that includes this glob, check to see if the glob - // has changed for that hash. if it has, then we need to stop watching - for hash in hash_status.iter() { - let globs = match hash_globs.get_mut(hash).filter(|globs| { - !globs.exclude.iter().any(|glob| { - let glob = WaxGlob::new(glob).expect("only watch valid globs"); - glob.is_match(path) - }) - }) { - Some(globs) => globs, - None => { - // if we get here, then the hash is excluded by a glob - // so we don't need to stop watching this glob - stop_watching = false; - continue; - } - }; - - // if we get here, we know that the glob has changed for every hash that - // included this glob and is not excluded by a hash's exclusion globs. - // So, we can delete this glob from every hash tracking it as well as stop - // watching this glob. To stop watching, we unref each of the - // directories corresponding to this glob - - // we can stop tracking that glob - globs.include.remove(glob); - if globs.include.is_empty() { - hash_globs.remove(hash); - } - - clear_glob_status.push((hash.clone(), glob.clone())); - } - - if stop_watching { - // store the hash and glob so we can remove it from the glob_status - exclude_globs.push(glob.to_owned()); - } - } - - (clear_glob_status, exclude_globs) -} - -/// given a list of hash-glob pairs to stop tracking, remove them from the -/// map and remove the entry if the set of globs for that hash is empty -/// -/// note: we take a mutex guard to make sure that the mutex is dropped -/// when the function returns -fn clear_hash_globs( - mut glob_status: MutexGuard>>, - hash_globs_to_clear: Vec<(Hash, Glob)>, -) { - for (hash, glob) in hash_globs_to_clear { - if let Entry::Occupied(mut o) = glob_status.entry(glob) { - let val = o.get_mut(); - val.remove(&hash); - if val.is_empty() { - o.remove(); - } - }; - } -} - -#[cfg(test)] -mod test { - use std::{sync::Arc, time::Duration}; - - use globwatch::StopSource; - use tokio::time::timeout; - use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, RelativeUnixPathBuf}; - - fn temp_dir() -> (AbsoluteSystemPathBuf, tempfile::TempDir) { - let tmp = tempfile::tempdir().unwrap(); - let path = AbsoluteSystemPathBuf::try_from(tmp.path()).unwrap(); - (path, tmp) - } - - fn setup(tmp: &AbsoluteSystemPath) { - let directories = ["my-pkg/dist/distChild", "my-pkg/.next/cache"]; - - let files = [ - "my-pkg/dist/distChild/dist-file", - "my-pkg/dist/dist-file", - "my-pkg/.next/next-file", - "my-pkg/irrelevant", - ]; - - for dir in directories.iter() { - let dir = RelativeUnixPathBuf::new(*dir).unwrap(); - tmp.join_unix_path(&dir).create_dir_all().unwrap(); - } - - for file in files.iter() { - let file = RelativeUnixPathBuf::new(*file).unwrap(); - tmp.join_unix_path(&file).create_with_contents("").unwrap(); - } - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn track_outputs() { - let (dir, _tmp_dir) = temp_dir(); - setup(&dir); - let (flush, _tmp_flush) = temp_dir(); - let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); - - let stop = StopSource::new(); - - let task_watcher = watcher.clone(); - let token = stop.token(); - - // dropped when the test ends - let _s = tokio::task::spawn(async move { task_watcher.watch(token).await }); - - let hash = Arc::new("the-hash".to_string()); - let include = ["my-pkg/dist/**".to_string(), "my-pkg/.next/**".to_string()]; - let exclude = ["my-pkg/.next/cache/**".to_string()]; - - println!("{:?} {:?}", include, exclude); - - watcher - .watch_globs(hash.clone(), include.clone(), exclude.clone()) - .await - .unwrap(); - - let changed = watcher - .changed_globs(&hash, include.clone().into_iter().collect()) - .await - .unwrap(); - - assert!( - changed.is_empty(), - "expected no changed globs, got {:?}", - changed - ); - - // change a file that is neither included nor excluded - - dir.join_components(&["my-pkg", "irrelevant2"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash, include.clone().into_iter().collect()) - .await - .unwrap(); - - assert!( - changed.is_empty(), - "expected no changed globs, got {:?}", - changed - ); - - // change a file that is excluded - - dir.join_components(&["my-pkg", ".next", "cache", "next-file2"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash, include.clone().into_iter().collect()) - .await - .unwrap(); - - assert!( - changed.is_empty(), - "expected no changed globs, got {:?}", - changed - ); - - // change a file that is included - - dir.join_components(&["my-pkg", "dist", "dist-file2"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash, include.clone().into_iter().collect()) - .await - .unwrap(); - - assert_eq!( - changed, - ["my-pkg/dist/**".to_string()].into_iter().collect(), - "expected one of the globs to have changed" - ); - - // change a file that is included but with a subdirectory that is excluded - // now both globs should be marked as changed - - dir.join_components(&["my-pkg", ".next", "next-file2"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash, include.clone().into_iter().collect()) - .await - .unwrap(); - - assert_eq!( - changed, - include.into_iter().collect(), - "expected both globs to have changed" - ); - - assert!( - watcher.hash_globs.lock().unwrap().is_empty(), - "we should no longer be watching any hashes" - ); - - assert!( - watcher.glob_statuses.lock().unwrap().is_empty(), - "we should no longer be watching any globs: {:?}", - watcher.glob_statuses.lock().unwrap() - ); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn test_multiple_hashes() { - let (dir, _tmp_dir) = temp_dir(); - setup(&dir); - let (flush, _tmp_flush) = temp_dir(); - let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); - - let stop = StopSource::new(); - - let task_watcher = watcher.clone(); - let token = stop.token(); - - // dropped when the test ends - let _s = tokio::task::spawn(async move { task_watcher.watch(token).await }); - - let hash1 = Arc::new("the-hash-1".to_string()); - let hash2 = Arc::new("the-hash-2".to_string()); - - let globs1_inclusion = ["my-pkg/dist/**".to_string(), "my-pkg/.next/**".to_string()]; - let globs2_inclusion = ["my-pkg/.next/**".to_string()]; - let globs2_exclusion = ["my-pkg/.next/cache/**".to_string()]; - - watcher - .watch_globs(hash1.clone(), globs1_inclusion.clone(), vec![]) - .await - .unwrap(); - - watcher - .watch_globs( - hash2.clone(), - globs2_inclusion.clone(), - globs2_exclusion.clone(), - ) - .await - .unwrap(); - - let changed = watcher - .changed_globs(&hash1, globs1_inclusion.clone().into_iter().collect()) - .await - .unwrap(); - - assert!( - changed.is_empty(), - "expected no changed globs, got {:?}", - changed - ); - - let changed = watcher - .changed_globs(&hash2, globs2_inclusion.clone().into_iter().collect()) - .await - .unwrap(); - - assert!( - changed.is_empty(), - "expected no changed globs, got {:?}", - changed - ); - - // make a change excluded in only one of the hashes - - dir.join_components(&["my-pkg", ".next", "cache", "next-file2"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash1, globs1_inclusion.clone().into_iter().collect()) - .await - .unwrap(); - - assert_eq!( - changed, - ["my-pkg/.next/**".to_string()].into_iter().collect(), - "expected one of the globs to have changed" - ); - - let changed = watcher - .changed_globs(&hash2, globs2_inclusion.clone().into_iter().collect()) - .await - .unwrap(); - - assert!( - changed.is_empty(), - "expected no changed globs, got {:?}", - changed - ); - - // make a change for the other hash - - dir.join_components(&["my-pkg", ".next", "next-file2"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash2, globs2_inclusion.clone().into_iter().collect()) - .await - .unwrap(); - - assert_eq!( - changed, - ["my-pkg/.next/**".to_string()].into_iter().collect(), - "expected one of the globs to have changed" - ); - - assert_eq!( - watcher.hash_globs.lock().unwrap().keys().len(), - 1, - "we should be watching one hash, got {:?}", - watcher.hash_globs.lock().unwrap() - ); - - assert_eq!( - watcher.glob_statuses.lock().unwrap().keys().len(), - 1, - "we should be watching one glob, got {:?}", - watcher.glob_statuses.lock().unwrap() - ); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn watch_single_file() { - let (dir, _tmp_dir) = temp_dir(); - setup(&dir); - let (flush, _tmp_flush) = temp_dir(); - let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); - - let stop = StopSource::new(); - - let task_watcher = watcher.clone(); - let token = stop.token(); - - // dropped when the test ends - let _s = tokio::task::spawn(async move { task_watcher.watch(token).await }); - - let hash = Arc::new("the-hash".to_string()); - let inclusions = ["my-pkg/.next/next-file".to_string()]; - - watcher - .watch_globs(hash.clone(), inclusions.clone(), vec![]) - .await - .unwrap(); - - dir.join_components(&["my-pkg", ".next", "irrelevant"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash, inclusions.clone().into_iter().collect()) - .await - .unwrap(); - - assert!( - changed.is_empty(), - "expected no changed globs, got {:?}", - changed - ); - - dir.join_components(&["my-pkg", ".next", "next-file"]) - .create_with_contents("") - .unwrap(); - let changed = watcher - .changed_globs(&hash, inclusions.clone().into_iter().collect()) - .await - .unwrap(); - - assert_eq!( - changed, - inclusions.clone().into_iter().collect(), - "expected one of the globs to have changed" - ); - - assert!( - watcher.hash_globs.lock().unwrap().is_empty(), - "we should no longer be watching any hashes" - ); - - assert!( - watcher.glob_statuses.lock().unwrap().is_empty(), - "we should no longer be watching any globs: {:?}", - watcher.glob_statuses.lock().unwrap() - ); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn delete_root_kill_daemon() { - let (dir, _tmp_dir) = temp_dir(); - setup(&dir); - let (flush, _tmp_flush) = temp_dir(); - let watcher = Arc::new(super::HashGlobWatcher::new(&dir, &flush).unwrap()); - - let stop = StopSource::new(); - - let task_watcher = watcher.clone(); - let token = stop.token(); - - // dropped when the test ends - let task = tokio::task::spawn(async move { task_watcher.watch(token).await }); - tokio::time::sleep(Duration::from_secs(3)).await; - watcher.config.flush().await.unwrap(); - dir.remove_dir_all().unwrap(); - - // it should shut down - match timeout(Duration::from_secs(60), task).await { - Err(e) => panic!("test timed out: {e}"), - Ok(Err(e)) => panic!("expected task to finish when root is deleted: {e}"), - _ => (), - } - } -} diff --git a/crates/turborepo-lib/src/hash/mod.rs b/crates/turborepo-lib/src/hash/mod.rs deleted file mode 100644 index 74fd46ccbd224..0000000000000 --- a/crates/turborepo-lib/src/hash/mod.rs +++ /dev/null @@ -1,496 +0,0 @@ -//! hash module -//! -//! This module contains the hash functions used by turborepo for certain -//! data-types. This is managed using capnproto for deterministic hashing across -//! languages and platforms. - -mod traits; - -use std::collections::HashMap; - -use capnp::message::{Builder, HeapAllocator}; -pub use traits::TurboHash; -use turborepo_env::EnvironmentVariablePairs; - -use crate::{cli::EnvMode, task_graph::TaskOutputs}; - -mod proto_capnp { - - use crate::cli::EnvMode; - - include!(concat!(env!("OUT_DIR"), "/src/hash/proto_capnp.rs")); - - impl From for global_hashable::EnvMode { - fn from(value: EnvMode) -> Self { - match value { - EnvMode::Loose => global_hashable::EnvMode::Loose, - EnvMode::Strict => global_hashable::EnvMode::Strict, - } - } - } - - impl From for task_hashable::EnvMode { - fn from(value: EnvMode) -> Self { - match value { - EnvMode::Loose => task_hashable::EnvMode::Loose, - EnvMode::Strict => task_hashable::EnvMode::Strict, - } - } - } -} - -#[derive(Debug)] -pub struct TaskHashable<'a> { - // hashes - pub(crate) global_hash: &'a str, - pub(crate) task_dependency_hashes: Vec, - pub(crate) hash_of_files: &'a str, - pub(crate) external_deps_hash: Option, - - // task - pub(crate) package_dir: Option, - pub(crate) task: &'a str, - pub(crate) outputs: TaskOutputs, - pub(crate) pass_through_args: &'a [String], - - // env - pub(crate) env: &'a [String], - pub(crate) resolved_env_vars: EnvVarPairs, - pub(crate) pass_through_env: &'a [String], - pub(crate) env_mode: EnvMode, -} - -#[derive(Debug, Clone)] -pub struct GlobalHashable<'a> { - pub global_cache_key: &'static str, - pub global_file_hash_map: &'a HashMap, - // These are None in single package mode - pub root_external_dependencies_hash: Option<&'a str>, - pub root_internal_dependencies_hash: Option<&'a str>, - pub engines: HashMap<&'a str, &'a str>, - pub env: &'a [String], - pub resolved_env_vars: EnvironmentVariablePairs, - pub pass_through_env: &'a [String], - pub env_mode: EnvMode, - pub framework_inference: bool, -} - -pub struct LockFilePackages(pub Vec); - -#[derive(Debug, Clone)] -pub struct FileHashes(pub HashMap); - -impl From for Builder { - fn from(value: TaskOutputs) -> Self { - let mut message = ::capnp::message::TypedBuilder::< - proto_capnp::task_outputs::Owned, - HeapAllocator, - >::new_default(); - let mut builder = message.init_root(); - - { - let mut inclusions = builder - .reborrow() - .init_inclusions(value.inclusions.len() as u32); - for (i, inclusion) in value.inclusions.iter().enumerate() { - inclusions.set(i as u32, inclusion); - } - } - - { - let mut exclusions = builder - .reborrow() - .init_exclusions(value.exclusions.len() as u32); - for (i, exclusion) in value.exclusions.iter().enumerate() { - exclusions.set(i as u32, exclusion); - } - } - - message.into_inner() - } -} - -impl From for Builder { - fn from(LockFilePackages(packages): LockFilePackages) -> Self { - let mut message = ::capnp::message::TypedBuilder::< - proto_capnp::lock_file_packages::Owned, - HeapAllocator, - >::new_default(); - let mut builder = message.init_root(); - - { - let mut packages_builder = builder.reborrow().init_packages(packages.len() as u32); - for (i, turborepo_lockfiles::Package { key, version }) in packages.iter().enumerate() { - let mut package = packages_builder.reborrow().get(i as u32); - package.set_key(key); - package.set_version(version); - // we don't track this in rust, set it to true - package.set_found(true); - } - } - - // We're okay to unwrap here because we haven't hit the nesting - // limit and the message will not have cycles. - let size = builder - .total_size() - .expect("unable to calculate total size") - .word_count - + 1; // + 1 to solve an off by one error inside capnp - let mut canon_builder = - Builder::new(HeapAllocator::default().first_segment_words(size as u32)); - canon_builder - .set_root_canonical(builder.reborrow_as_reader()) - .expect("can't fail"); - - canon_builder - } -} - -impl From for Builder { - fn from(FileHashes(file_hashes): FileHashes) -> Self { - let mut message = ::capnp::message::TypedBuilder::< - proto_capnp::file_hashes::Owned, - HeapAllocator, - >::new_default(); - let mut builder = message.init_root(); - - { - let mut entries = builder - .reborrow() - .init_file_hashes(file_hashes.len() as u32); - - // get a sorted iterator over keys and values of the hashmap - // and set the entries in the capnp message - - let mut hashable: Vec<_> = file_hashes.into_iter().collect(); - hashable.sort_by(|(path_a, _), (path_b, _)| path_a.cmp(path_b)); - - for (i, (key, value)) in hashable.iter().enumerate() { - let mut entry = entries.reborrow().get(i as u32); - entry.set_key(key.as_str()); - entry.set_value(value); - } - } - - // We're okay to unwrap here because we haven't hit the nesting - // limit and the message will not have cycles. - let size = builder - .total_size() - .expect("unable to calculate total size") - .word_count - + 1; // + 1 to solve an off by one error inside capnp - let mut canon_builder = - Builder::new(HeapAllocator::default().first_segment_words(size as u32)); - canon_builder - .set_root_canonical(builder.reborrow_as_reader()) - .expect("can't fail"); - - canon_builder - } -} - -type EnvVarPairs = Vec; - -impl From> for Builder { - fn from(task_hashable: TaskHashable) -> Self { - let mut message = - ::capnp::message::TypedBuilder::::new_default(); - let mut builder = message.init_root(); - - builder.set_global_hash(task_hashable.global_hash); - if let Some(package_dir) = task_hashable.package_dir { - builder.set_package_dir(&package_dir.to_string()); - } - - builder.set_hash_of_files(task_hashable.hash_of_files); - if let Some(external_deps_hash) = task_hashable.external_deps_hash { - builder.set_external_deps_hash(&external_deps_hash); - } - - builder.set_task(task_hashable.task); - builder.set_env_mode(task_hashable.env_mode.into()); - - { - let output_builder: Builder<_> = task_hashable.outputs.into(); - builder - .set_outputs(output_builder.get_root_as_reader().unwrap()) - .unwrap(); - } - - { - let mut task_dependency_hashes_builder = builder - .reborrow() - .init_task_dependency_hashes(task_hashable.task_dependency_hashes.len() as u32); - for (i, hash) in task_hashable.task_dependency_hashes.iter().enumerate() { - task_dependency_hashes_builder.set(i as u32, hash); - } - } - - { - let mut pass_through_args_builder = builder - .reborrow() - .init_pass_thru_args(task_hashable.pass_through_args.len() as u32); - for (i, arg) in task_hashable.pass_through_args.iter().enumerate() { - pass_through_args_builder.set(i as u32, arg); - } - } - - { - let mut env_builder = builder.reborrow().init_env(task_hashable.env.len() as u32); - for (i, env) in task_hashable.env.iter().enumerate() { - env_builder.set(i as u32, env); - } - } - - { - let mut pass_through_env_builder = builder - .reborrow() - .init_pass_thru_env(task_hashable.pass_through_env.len() as u32); - for (i, env) in task_hashable.pass_through_env.iter().enumerate() { - pass_through_env_builder.set(i as u32, env); - } - } - - { - let mut resolved_env_vars_builder = builder - .reborrow() - .init_resolved_env_vars(task_hashable.resolved_env_vars.len() as u32); - for (i, env) in task_hashable.resolved_env_vars.iter().enumerate() { - resolved_env_vars_builder.set(i as u32, env); - } - } - - // We're okay to unwrap here because we haven't hit the nesting - // limit and the message will not have cycles. - let size = builder - .total_size() - .expect("unable to calculate total size") - .word_count - + 1; // + 1 to solve an off by one error inside capnp - let mut canon_builder = - Builder::new(HeapAllocator::default().first_segment_words(size as u32)); - canon_builder - .set_root_canonical(builder.reborrow_as_reader()) - .expect("can't fail"); - - canon_builder - } -} - -impl From> for Builder { - fn from(hashable: GlobalHashable) -> Self { - let mut message = - ::capnp::message::TypedBuilder::::new_default(); - - let mut builder = message.init_root(); - - builder.set_global_cache_key(hashable.global_cache_key); - - { - let mut entries = builder - .reborrow() - .init_global_file_hash_map(hashable.global_file_hash_map.len() as u32); - - // get a sorted iterator over keys and values of the hashmap - // and set the entries in the capnp message - - let mut hashable: Vec<_> = hashable.global_file_hash_map.iter().collect(); - hashable.sort_by(|a, b| a.0.cmp(b.0)); - - for (i, (key, value)) in hashable.iter().enumerate() { - let mut entry = entries.reborrow().get(i as u32); - entry.set_key(key.as_str()); - entry.set_value(value); - } - } - - { - let mut entries = builder - .reborrow() - .init_engines(hashable.engines.len() as u32); - - // get a sorted iterator over keys and values of the hashmap - // and set the entries in the capnp message - - let mut hashable: Vec<_> = hashable.engines.iter().collect(); - hashable.sort_by(|a, b| a.0.cmp(b.0)); - - for (i, (key, value)) in hashable.iter().enumerate() { - let mut entry = entries.reborrow().get(i as u32); - entry.set_key(key); - entry.set_value(value); - } - } - - if let Some(root_external_dependencies_hash) = hashable.root_external_dependencies_hash { - builder.set_root_external_deps_hash(root_external_dependencies_hash); - } - - if let Some(root_internal_dependencies_hash) = hashable.root_internal_dependencies_hash { - builder.set_root_internal_deps_hash(root_internal_dependencies_hash); - } - - { - let mut entries = builder.reborrow().init_env(hashable.env.len() as u32); - for (i, env) in hashable.env.iter().enumerate() { - entries.set(i as u32, env); - } - } - - { - let mut resolved_env_vars = builder - .reborrow() - .init_resolved_env_vars(hashable.resolved_env_vars.len() as u32); - for (i, env) in hashable.resolved_env_vars.iter().enumerate() { - resolved_env_vars.set(i as u32, env); - } - } - - { - let mut pass_through_env = builder - .reborrow() - .init_pass_through_env(hashable.pass_through_env.len() as u32); - for (i, env) in hashable.pass_through_env.iter().enumerate() { - pass_through_env.set(i as u32, env); - } - } - - builder.set_env_mode(match hashable.env_mode { - EnvMode::Loose => proto_capnp::global_hashable::EnvMode::Loose, - EnvMode::Strict => proto_capnp::global_hashable::EnvMode::Strict, - }); - - builder.set_framework_inference(hashable.framework_inference); - - // We're okay to unwrap here because we haven't hit the nesting - // limit and the message will not have cycles. - let size = builder - .total_size() - .expect("unable to calculate total size") - .word_count - + 1; // + 1 to solve an off by one error inside capnp - let mut canon_builder = - Builder::new(HeapAllocator::default().first_segment_words(size as u32)); - canon_builder - .set_root_canonical(builder.reborrow_as_reader()) - .expect("can't fail"); - - canon_builder - } -} - -#[cfg(test)] -mod test { - use test_case::test_case; - use turborepo_lockfiles::Package; - - use super::{ - FileHashes, GlobalHashable, LockFilePackages, TaskHashable, TaskOutputs, TurboHash, - }; - use crate::cli::EnvMode; - - #[test] - fn task_hashable() { - let task_hashable = TaskHashable { - global_hash: "global_hash", - task_dependency_hashes: vec!["task_dependency_hash".to_string()], - package_dir: Some(turbopath::RelativeUnixPathBuf::new("package_dir").unwrap()), - hash_of_files: "hash_of_files", - external_deps_hash: Some("external_deps_hash".to_string()), - task: "task", - outputs: TaskOutputs { - inclusions: vec!["inclusions".to_string()], - exclusions: vec!["exclusions".to_string()], - }, - pass_through_args: &["pass_thru_args".to_string()], - env: &["env".to_string()], - resolved_env_vars: vec![], - pass_through_env: &["pass_thru_env".to_string()], - env_mode: EnvMode::Loose, - }; - - assert_eq!(task_hashable.hash(), "1f8b13161f57fca1"); - } - - #[test] - fn global_hashable() { - let global_file_hash_map = vec![( - turbopath::RelativeUnixPathBuf::new("global_file_hash_map").unwrap(), - "global_file_hash_map".to_string(), - )] - .into_iter() - .collect(); - - let global_hash = GlobalHashable { - global_cache_key: "global_cache_key", - global_file_hash_map: &global_file_hash_map, - root_external_dependencies_hash: Some("0000000000000000"), - root_internal_dependencies_hash: Some("0000000000000001"), - engines: Default::default(), - env: &["env".to_string()], - resolved_env_vars: vec![], - pass_through_env: &["pass_through_env".to_string()], - env_mode: EnvMode::Strict, - framework_inference: true, - }; - - assert_eq!(global_hash.hash(), "5072bd005ec02799"); - } - - #[test_case(vec![], "459c029558afe716" ; "empty")] - #[test_case(vec![Package { - key: "key".to_string(), - version: "version".to_string(), - }], "1b266409f3ae154e" ; "non-empty")] - #[test_case(vec![Package { - key: "key".to_string(), - version: "".to_string(), - }], "bde280722f61644a" ; "empty version")] - #[test_case(vec![Package { - key: "key".to_string(), - version: "version".to_string(), - }, Package { - key: "zey".to_string(), - version: "version".to_string(), - }], "6c0185544234b6dc" ; "multiple in-order")] - #[test_case(vec![Package { - key: "zey".to_string(), - version: "version".to_string(), - }, Package { - key: "key".to_string(), - version: "version".to_string(), - }], "26a67c9beeb0d16f" ; "care about order")] - fn lock_file_packages(vec: Vec, expected: &str) { - let packages = LockFilePackages(vec); - assert_eq!(packages.hash(), expected); - } - - #[test] - fn long_lock_file_packages() { - let packages = (0..100).map(|i| Package { - key: format!("key{}", i), - version: format!("version{}", i), - }); - - lock_file_packages(packages.collect(), "4fd770c37194168e"); - } - - #[test_case(vec![], "459c029558afe716" ; "empty")] - #[test_case(vec![ - ("a".to_string(), "b".to_string()), - ("c".to_string(), "d".to_string()), - ], "c9301c0bf1899c07" ; "non-empty")] - #[test_case(vec![ - ("c".to_string(), "d".to_string()), - ("a".to_string(), "b".to_string()), - ], "c9301c0bf1899c07" ; "order resistant")] - fn file_hashes(pairs: Vec<(String, String)>, expected: &str) { - let file_hashes = FileHashes( - pairs - .into_iter() - .map(|(a, b)| (turbopath::RelativeUnixPathBuf::new(a).unwrap(), b)) - .collect(), - ); - assert_eq!(file_hashes.hash(), expected); - } -} diff --git a/crates/turborepo-lib/src/hash/traits.rs b/crates/turborepo-lib/src/hash/traits.rs deleted file mode 100644 index 180f609f9188f..0000000000000 --- a/crates/turborepo-lib/src/hash/traits.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::hash::Hasher; - -use capnp::message::{Allocator, Builder}; - -pub trait Sealed {} - -pub trait TurboHash: Sealed { - fn hash(self) -> String; -} - -impl Sealed for T -where - T: Into>, - A: Allocator, -{ -} - -impl TurboHash for T -where - T: Into>, - A: Allocator, -{ - fn hash(self) -> String { - let message = self.into(); - - debug_assert_eq!( - message.get_segments_for_output().len(), - 1, - "message is not canonical" - ); - - let buf = message.get_segments_for_output()[0]; - - let mut hasher = twox_hash::XxHash64::with_seed(0); - hasher.write(buf); - let out = hasher.finish(); - - hex::encode(out.to_be_bytes()) - } -} diff --git a/crates/turborepo-lib/src/panic_handler.rs b/crates/turborepo-lib/src/panic_handler.rs deleted file mode 100644 index 7b59874c83473..0000000000000 --- a/crates/turborepo-lib/src/panic_handler.rs +++ /dev/null @@ -1,56 +0,0 @@ -use human_panic::report::{Method, Report}; - -use crate::get_version; - -const OPEN_ISSUE_MESSAGE: &str = - "Please open an issue at https://github.com/vercel/turborepo/issues/new/choose"; - -pub fn panic_handler(panic_info: &std::panic::PanicHookInfo) { - let cause = panic_info.to_string(); - - let explanation = match panic_info.location() { - Some(location) => format!("file '{}' at line {}\n", location.file(), location.line()), - None => "unknown.".to_string(), - }; - - let report = Report::new("turbo", get_version(), Method::Panic, explanation, cause); - // If we're in CI we don't persist the backtrace to a temp file as this is hard - // to retrieve. - let should_persist = !turborepo_ci::is_ci() && turborepo_ci::Vendor::infer().is_none(); - - let report_message = if should_persist { - match report.persist() { - Ok(f) => { - format!( - "A report has been written to {}\n\n{OPEN_ISSUE_MESSAGE} and include this file", - f.display() - ) - } - Err(e) => { - format!( - "An error has occurred while attempting to write a \ - report.\n\n{OPEN_ISSUE_MESSAGE} and include the following error in your \ - issue: {}", - e - ) - } - } - } else if let Some(backtrace) = report.serialize() { - format!( - "Caused by \n{backtrace}\n\n{OPEN_ISSUE_MESSAGE} and include this message in your \ - issue" - ) - } else { - format!( - "Unable to serialize backtrace.\n\n{OPEN_ISSUE_MESSAGE} and include this message in \ - your issue" - ) - }; - - eprintln!( - "Oops! Turbo has crashed. - -{}", - report_message - ); -} diff --git a/crates/turborepo-lib/src/process/command.rs b/crates/turborepo-lib/src/process/command.rs deleted file mode 100644 index a8814f8229871..0000000000000 --- a/crates/turborepo-lib/src/process/command.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::{ - collections::BTreeMap, - ffi::{OsStr, OsString}, - process::Stdio, -}; - -use itertools::Itertools; -use turbopath::AbsoluteSystemPathBuf; - -/// A command builder that can be used to build both regular -/// child processes and ones spawned hooked up to a PTY -#[derive(Debug, Clone)] -pub struct Command { - program: OsString, - args: Vec, - cwd: Option, - env: BTreeMap, - open_stdin: bool, - env_clear: bool, -} - -impl Command { - pub fn new(program: impl AsRef) -> Self { - let program = program.as_ref().to_os_string(); - Self { - program, - args: Vec::new(), - cwd: None, - env: BTreeMap::new(), - open_stdin: false, - env_clear: false, - } - } - - pub fn args(&mut self, args: I) -> &mut Self - where - I: IntoIterator, - S: AsRef, - { - self.args = args - .into_iter() - .map(|arg| arg.as_ref().to_os_string()) - .collect(); - self - } - - pub fn current_dir(&mut self, dir: AbsoluteSystemPathBuf) -> &mut Self { - self.cwd = Some(dir); - self - } - - pub fn envs(&mut self, vars: I) -> &mut Self - where - I: IntoIterator, - K: AsRef, - V: AsRef, - { - for (ref key, ref val) in vars { - self.env - .insert(key.as_ref().to_os_string(), val.as_ref().to_os_string()); - } - self - } - - pub fn env(&mut self, key: K, val: V) -> &mut Self - where - K: AsRef, - V: AsRef, - { - self.env - .insert(key.as_ref().to_os_string(), val.as_ref().to_os_string()); - self - } - - /// Configure the child process to spawn with a piped stdin - pub fn open_stdin(&mut self) -> &mut Self { - self.open_stdin = true; - self - } - - /// Clears the environment variables for the child process - pub fn env_clear(&mut self) -> &mut Self { - self.env_clear = true; - self.env.clear(); - self - } - - pub fn label(&self) -> String { - format!( - "({}) {} {}", - self.cwd - .as_deref() - .map(|dir| dir.as_str()) - .unwrap_or_default(), - self.program.to_string_lossy(), - self.args.iter().map(|s| s.to_string_lossy()).join(" ") - ) - } - - /// If stdin is expected to be opened - pub fn will_open_stdin(&self) -> bool { - self.open_stdin - } - - /// Program for the command - pub fn program(&self) -> &OsStr { - &self.program - } -} - -impl From for tokio::process::Command { - fn from(value: Command) -> Self { - let Command { - program, - args, - cwd, - env, - open_stdin, - env_clear, - } = value; - - let mut cmd = tokio::process::Command::new(program); - if env_clear { - cmd.env_clear(); - } - cmd.args(args) - .envs(env) - // We always pipe stdout/stderr to allow us to capture task output - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - // Only open stdin if configured to do so - .stdin(if open_stdin { - Stdio::piped() - } else { - Stdio::null() - }); - if let Some(cwd) = cwd { - cmd.current_dir(cwd.as_std_path()); - } - cmd - } -} - -impl From for portable_pty::CommandBuilder { - fn from(value: Command) -> Self { - let Command { - program, - args, - cwd, - env, - env_clear, - .. - } = value; - let mut cmd = portable_pty::CommandBuilder::new(program); - if env_clear { - cmd.env_clear(); - } - cmd.args(args); - if let Some(cwd) = cwd { - cmd.cwd(cwd.as_std_path()); - } else if let Ok(cwd) = std::env::current_dir() { - // portably_pty defaults to a users home directory instead of cwd if one isn't - // configured on the command builder. - // We explicitly set the cwd if one exists to avoid this behavior - cmd.cwd(&cwd); - } - for (key, value) in env { - cmd.env(key, value); - } - cmd - } -} diff --git a/crates/turborepo-lib/src/process/mod.rs b/crates/turborepo-lib/src/process/mod.rs deleted file mode 100644 index 5e1751a2be007..0000000000000 --- a/crates/turborepo-lib/src/process/mod.rs +++ /dev/null @@ -1,418 +0,0 @@ -//! `process` -//! -//! This module contains the code that is responsible for running the commands -//! that are queued by run. It consists of a set of child processes that are -//! spawned and managed by the manager. The manager is responsible for -//! running these processes to completion, forwarding signals, and closing -//! them when the manager is closed. -//! -//! As of now, the manager will execute futures in a random order, and -//! must be either `wait`ed on or `stop`ped to drive state. - -mod child; -mod command; - -use std::{ - io, - sync::{Arc, Mutex}, - time::Duration, -}; - -pub use command::Command; -use futures::Future; -use tokio::task::JoinSet; -use tracing::{debug, trace}; - -pub use self::child::{Child, ChildExit}; - -/// A process manager that is responsible for spawning and managing child -/// processes. When the manager is Open, new child processes can be spawned -/// using `spawn`. When the manager is Closed, all currently-running children -/// will be closed, and no new children can be spawned. -#[derive(Debug, Clone)] -pub struct ProcessManager { - state: Arc>, - use_pty: bool, -} - -#[derive(Debug)] -struct ProcessManagerInner { - is_closing: bool, - children: Vec, - size: Option, -} - -#[derive(Debug, Clone, Copy)] -pub struct PtySize { - rows: u16, - cols: u16, -} - -impl ProcessManager { - pub fn new(use_pty: bool) -> Self { - debug!("spawning children with pty: {use_pty}"); - Self { - state: Arc::new(Mutex::new(ProcessManagerInner { - is_closing: false, - children: Vec::new(), - size: None, - })), - use_pty, - } - } - - /// Construct a process manager and infer if pty should be used - pub fn infer() -> Self { - // Only use PTY if we're not on windows and we're currently hooked up to a - // in a TTY - let use_pty = !cfg!(windows) && atty::is(atty::Stream::Stdout); - Self::new(use_pty) - } - - /// Returns whether children will be spawned attached to a pseudoterminal - pub fn use_pty(&self) -> bool { - self.use_pty - } - - /// Returns whether or not closing a child's stdin will result in it - /// immediately exiting. - pub fn closing_stdin_ends_process(&self) -> bool { - // Processes spawned hooked up to ConPTY on Windows will immediately exit - // if their stdin is closed. We avoid closing stdin in this case. - cfg!(windows) && self.use_pty - } -} - -impl ProcessManager { - /// Spawn a new child process to run the given command. - /// - /// The handle of the child can be either waited or stopped by the caller, - /// as well as the entire process manager. - /// - /// If spawn returns None, the process manager is closed and the child - /// process was not spawned. If spawn returns Some(Err), the process - /// manager is open, but the child process failed to spawn. - pub fn spawn( - &self, - command: Command, - stop_timeout: Duration, - ) -> Option> { - let label = tracing::enabled!(tracing::Level::TRACE) - .then(|| command.label()) - .unwrap_or_default(); - trace!("acquiring lock for spawning {label}"); - let mut lock = self.state.lock().unwrap(); - trace!("acquired lock for spawning {label}"); - if lock.is_closing { - debug!("process manager closing"); - return None; - } - let pty_size = self.use_pty.then(|| lock.pty_size()).flatten(); - let child = child::Child::spawn( - command, - child::ShutdownStyle::Graceful(stop_timeout), - pty_size, - ); - if let Ok(child) = &child { - lock.children.push(child.clone()); - } - trace!("releasing lock for spawning {label}"); - Some(child) - } - - /// Stop the process manager, closing all child processes. On posix - /// systems this will send a SIGINT, and on windows it will just kill - /// the process immediately. - pub async fn stop(&self) { - self.close(|mut c| async move { c.stop().await }).await - } - - /// Stop the process manager, waiting for all child processes to exit. - /// - /// If you want to set a timeout, use `tokio::time::timeout` and - /// `Self::stop` if the timeout elapses. - pub async fn wait(&self) { - self.close(|mut c| async move { c.wait().await }).await - } - - /// Close the process manager, running the given callback on each child - /// - /// note: this is designed to be called multiple times, ie calling close - /// with two different strategies will propagate both signals to the child - /// processes. clearing the task queue and re-enabling spawning are both - /// idempotent operations - async fn close(&self, callback: F) - where - F: Fn(Child) -> C + Sync + Send + Copy + 'static, - C: Future> + Sync + Send + 'static, - { - let mut set = JoinSet::new(); - - { - let mut lock = self.state.lock().expect("not poisoned"); - lock.is_closing = true; - for child in lock.children.iter() { - let child = child.clone(); - set.spawn(async move { callback(child).await }); - } - } - - debug!("waiting for {} processes to exit", set.len()); - - while let Some(out) = set.join_next().await { - trace!("process exited: {:?}", out); - } - - { - let mut lock = self.state.lock().expect("not poisoned"); - - // just allocate a new vec rather than clearing the old one - lock.children = vec![]; - } - } - - pub fn set_pty_size(&self, rows: u16, cols: u16) { - self.state.lock().expect("not poisoned").size = Some(PtySize { rows, cols }); - } -} - -impl ProcessManagerInner { - fn pty_size(&mut self) -> Option { - if self.size.is_none() { - self.size = PtySize::from_tty(); - } - self.size - } -} - -impl PtySize { - fn from_tty() -> Option { - console::Term::stdout() - .size_checked() - .map(|(rows, cols)| Self { rows, cols }) - } -} - -impl Default for PtySize { - fn default() -> Self { - Self { rows: 24, cols: 80 } - } -} - -#[cfg(test)] -mod test { - use std::time::Instant; - - use futures::{stream::FuturesUnordered, StreamExt}; - use test_case::test_case; - use tokio::{join, time::sleep}; - use tracing_test::traced_test; - - use super::*; - - fn get_command() -> Command { - get_script_command("sleep_5_interruptable.js") - } - - fn get_script_command(script_name: &str) -> Command { - let mut cmd = Command::new("node"); - cmd.args([format!("./test/scripts/{script_name}")]); - cmd - } - - const STOPPED_EXIT: Option = Some(ChildExit::Killed); - - #[tokio::test] - async fn test_basic() { - let manager = ProcessManager::new(false); - let mut child = manager - .spawn(get_script_command("hello_world.js"), Duration::from_secs(2)) - .unwrap() - .unwrap(); - let mut out = Vec::new(); - let exit = child.wait_with_piped_outputs(&mut out).await.unwrap(); - assert_eq!(exit, Some(ChildExit::Finished(Some(0)))); - assert_eq!(out, b"hello world\n"); - } - - #[tokio::test] - async fn test_multiple() { - let manager = ProcessManager::new(false); - - let children = (0..2) - .map(|_| { - manager - .spawn(get_command(), Duration::from_secs(2)) - .unwrap() - .unwrap() - }) - .collect::>(); - - sleep(Duration::from_millis(100)).await; - - manager.stop().await; - - for mut child in children { - let exit = child.wait().await; - assert_eq!(exit, STOPPED_EXIT,); - } - } - - #[tokio::test] - async fn test_closed() { - let manager = ProcessManager::new(false); - let mut child = manager - .spawn(get_command(), Duration::from_secs(2)) - .unwrap() - .unwrap(); - let mut out = Vec::new(); - let (exit, _) = join! { - child.wait_with_piped_outputs(&mut out), - manager.stop(), - }; - let exit = exit.unwrap(); - assert_eq!(exit, STOPPED_EXIT,); - assert_eq!( - out, b"", - "child process should exit before output is printed" - ); - - // Verify that we can't start new child processes - assert!(manager - .spawn(get_command(), Duration::from_secs(2)) - .is_none()); - - manager.stop().await; - } - - #[tokio::test] - async fn test_exit_code() { - let manager = ProcessManager::new(false); - let mut child = manager - .spawn(get_script_command("hello_world.js"), Duration::from_secs(2)) - .unwrap() - .unwrap(); - - let code = child.wait().await; - assert_eq!(code, Some(ChildExit::Finished(Some(0)))); - - // TODO: maybe we should do some assertion that there was nothing to shut down - // and this is a noop? - manager.stop().await; - } - - #[tokio::test] - #[traced_test] - async fn test_message_after_stop() { - let manager = ProcessManager::new(false); - let mut child = manager - .spawn(get_script_command("hello_world.js"), Duration::from_secs(2)) - .unwrap() - .unwrap(); - - sleep(Duration::from_millis(100)).await; - - let exit = child.wait().await; - assert_eq!(exit, Some(ChildExit::Finished(Some(0)))); - - manager.stop().await; - - // this is idempotent, so calling it after the manager is stopped is ok - let kill_code = child.kill().await; - assert_eq!(kill_code, Some(ChildExit::Finished(Some(0)))); - - let code = child.wait().await; - assert_eq!(code, Some(ChildExit::Finished(Some(0)))); - } - - #[tokio::test] - async fn test_reuse_manager() { - let manager = ProcessManager::new(false); - manager.spawn(get_command(), Duration::from_secs(2)); - - sleep(Duration::from_millis(100)).await; - - manager.stop().await; - - assert!(manager.state.lock().unwrap().children.is_empty()); - - // TODO: actually do some check that this is idempotent - // idempotent - manager.stop().await; - } - - #[test_case("stop", "sleep_5_interruptable.js", STOPPED_EXIT)] - #[test_case("wait", "hello_world.js", Some(ChildExit::Finished(Some(0))))] - #[tokio::test] - async fn test_stop_multiple_tasks_shared( - strategy: &str, - script: &str, - expected: Option, - ) { - let manager = ProcessManager::new(false); - let tasks = FuturesUnordered::new(); - - for _ in 0..10 { - let manager = manager.clone(); - let command = get_script_command(script); - tasks.push(tokio::spawn(async move { - manager - .spawn(command, Duration::from_secs(1)) - .unwrap() - .unwrap() - .wait() - .await - })); - } - - // wait for tasks to start - tokio::time::sleep(Duration::from_millis(50)).await; - - match strategy { - "stop" => manager.stop().await, - "wait" => manager.wait().await, - _ => panic!("unknown strategy"), - } - - // tasks return proper exit code - assert!( - tasks.all(|v| async { v.unwrap() == expected }).await, - "not all tasks returned the correct code: {:?}", - expected - ); - } - - #[tokio::test] - async fn test_wait_multiple_tasks() { - let manager = ProcessManager::new(false); - - let mut out = Vec::new(); - let mut child = manager - .spawn(get_command(), Duration::from_secs(1)) - .unwrap() - .unwrap(); - - // let the task start - tokio::time::sleep(Duration::from_millis(50)).await; - - let start_time = Instant::now(); - - // we support 'close escalation'; someone can call - // stop even if others are waiting - let (exit, _, _) = join! { - child.wait_with_piped_outputs(&mut out), - manager.wait(), - manager.stop(), - }; - - assert_eq!(exit.unwrap(), STOPPED_EXIT); - assert_eq!( - out, b"", - "child process was stopped before any output was written" - ); - - let finish_time = Instant::now(); - - assert!((finish_time - start_time).lt(&Duration::from_secs(2))); - } -} diff --git a/crates/turborepo-lib/src/query/server.rs b/crates/turborepo-lib/src/query/server.rs deleted file mode 100644 index eefcb16829f7a..0000000000000 --- a/crates/turborepo-lib/src/query/server.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::sync::Arc; - -use async_graphql::{EmptyMutation, EmptySubscription, MergedObject, Schema}; -use async_graphql_axum::GraphQL; -use axum::{http::Method, routing::get, Router}; -use tokio::net::TcpListener; -use tower_http::cors::{Any, CorsLayer}; -use turborepo_ui::wui::query::SharedState; - -use crate::{query, query::graphiql, run::Run}; - -#[derive(MergedObject)] -struct Query(turborepo_ui::wui::RunQuery, query::RepositoryQuery); - -pub async fn run_server( - state: Option, - run: Arc, -) -> Result<(), turborepo_ui::Error> { - let cors = CorsLayer::new() - // allow `GET` and `POST` when accessing the resource - .allow_methods([Method::GET, Method::POST]) - .allow_headers(Any) - // allow requests from any origin - .allow_origin(Any); - - let web_ui_query = turborepo_ui::wui::RunQuery::new(state.clone()); - let turbo_query = query::RepositoryQuery::new(run); - let combined_query = Query(web_ui_query, turbo_query); - - let schema = Schema::new(combined_query, EmptyMutation, EmptySubscription); - let app = Router::new() - .route("/", get(graphiql).post_service(GraphQL::new(schema))) - .layer(cors); - - axum::serve( - TcpListener::bind("127.0.0.1:8000") - .await - .map_err(turborepo_ui::wui::Error::Server)?, - app, - ) - .await - .map_err(turborepo_ui::wui::Error::Server)?; - - Ok(()) -} diff --git a/crates/turborepo-lib/src/query/task.rs b/crates/turborepo-lib/src/query/task.rs deleted file mode 100644 index 72997203071ec..0000000000000 --- a/crates/turborepo-lib/src/query/task.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::sync::Arc; - -use async_graphql::Object; -use turborepo_errors::Spanned; - -use crate::{ - engine::TaskNode, - query::{package::Package, Array, Error}, - run::{task_id::TaskId, Run}, -}; - -pub struct RepositoryTask { - pub name: String, - pub package: Package, - pub script: Option>, -} - -impl RepositoryTask { - pub fn new(task_id: &TaskId, run: &Arc) -> Result { - let package = Package::new(run.clone(), task_id.package().into())?; - let script = package.get_tasks().get(task_id.task()).cloned(); - - Ok(RepositoryTask { - name: task_id.task().to_string(), - package, - script, - }) - } - - fn collect_and_sort<'a>( - &self, - task_id: &TaskId<'a>, - tasks: impl IntoIterator, - ) -> Result, Error> { - let mut tasks = tasks - .into_iter() - .filter_map(|task| match task { - TaskNode::Root => None, - TaskNode::Task(task) if task == task_id => None, - TaskNode::Task(task) => Some(RepositoryTask::new(task, self.package.run())), - }) - .collect::, _>>()?; - tasks.sort_by(|a, b| { - a.package - .get_name() - .cmp(b.package.get_name()) - .then_with(|| a.name.cmp(&b.name)) - }); - Ok(tasks) - } -} - -#[Object] -impl RepositoryTask { - async fn name(&self) -> String { - self.name.clone() - } - - async fn package(&self) -> Package { - self.package.clone() - } - - async fn full_name(&self) -> String { - format!("{}#{}", self.package.get_name(), self.name) - } - - async fn script(&self) -> Option { - self.script.as_ref().map(|script| script.value.to_string()) - } - - async fn direct_dependents(&self) -> Result, Error> { - let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); - - self.collect_and_sort( - &task_id, - self.package - .run() - .engine() - .dependents(&task_id) - .into_iter() - .flatten(), - ) - } - - async fn direct_dependencies(&self) -> Result, Error> { - let task_id = TaskId::new(self.package.get_name().as_ref(), &self.name); - - self.collect_and_sort( - &task_id, - self.package - .run() - .engine() - .dependencies(&task_id) - .into_iter() - .flatten(), - ) - } - - async fn indirect_dependents(&self) -> Result, Error> { - let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); - let direct_dependents = self - .package - .run() - .engine() - .dependencies(&task_id) - .unwrap_or_default(); - - self.collect_and_sort( - &task_id, - self.package - .run() - .engine() - .transitive_dependents(&task_id) - .into_iter() - .filter(|node| !direct_dependents.contains(node)), - ) - } - - async fn indirect_dependencies(&self) -> Result, Error> { - let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); - let direct_dependencies = self - .package - .run() - .engine() - .dependencies(&task_id) - .unwrap_or_default(); - let mut dependencies = self - .package - .run() - .engine() - .transitive_dependencies(&task_id) - .into_iter() - .filter(|node| !direct_dependencies.contains(node)) - .filter_map(|node| match node { - TaskNode::Root => None, - TaskNode::Task(task) if task == &task_id => None, - TaskNode::Task(task) => Some(RepositoryTask::new(task, self.package.run())), - }) - .collect::, _>>()?; - - dependencies.sort_by(|a, b| { - a.package - .get_name() - .cmp(b.package.get_name()) - .then_with(|| a.name.cmp(&b.name)) - }); - - Ok(dependencies) - } - - async fn all_dependents(&self) -> Result, Error> { - let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); - self.collect_and_sort( - &task_id, - self.package.run().engine().transitive_dependents(&task_id), - ) - } - - async fn all_dependencies(&self) -> Result, Error> { - let task_id = TaskId::from_static(self.package.get_name().to_string(), self.name.clone()); - self.collect_and_sort( - &task_id, - self.package - .run() - .engine() - .transitive_dependencies(&task_id), - ) - } -} diff --git a/crates/turborepo-lib/src/run/builder.rs b/crates/turborepo-lib/src/run/builder.rs deleted file mode 100644 index 50dd72810fb87..0000000000000 --- a/crates/turborepo-lib/src/run/builder.rs +++ /dev/null @@ -1,539 +0,0 @@ -use std::{ - collections::{HashMap, HashSet}, - io::{ErrorKind, IsTerminal}, - sync::Arc, - time::SystemTime, -}; - -use chrono::Local; -use tracing::debug; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; -use turborepo_analytics::{start_analytics, AnalyticsHandle, AnalyticsSender}; -use turborepo_api_client::{APIAuth, APIClient}; -use turborepo_cache::AsyncCache; -use turborepo_env::EnvironmentVariableMap; -use turborepo_errors::Spanned; -use turborepo_repository::{ - change_mapper::PackageInclusionReason, - package_graph::{PackageGraph, PackageName}, - package_json, - package_json::PackageJson, -}; -use turborepo_scm::SCM; -use turborepo_telemetry::events::{ - command::CommandEventBuilder, - generic::{DaemonInitStatus, GenericEventBuilder}, - repo::{RepoEventBuilder, RepoType}, - EventBuilder, TrackedErrors, -}; -use turborepo_ui::{ColorConfig, ColorSelector}; -#[cfg(feature = "daemon-package-discovery")] -use { - crate::run::package_discovery::DaemonPackageDiscovery, - std::time::Duration, - turborepo_repository::discovery::{ - Error as DiscoveryError, FallbackPackageDiscovery, LocalPackageDiscoveryBuilder, - PackageDiscoveryBuilder, - }, -}; - -use crate::{ - cli::DryRunMode, - commands::CommandBase, - engine::{Engine, EngineBuilder}, - microfrontends::MicrofrontendsConfigs, - opts::Opts, - process::ProcessManager, - run::{scope, task_access::TaskAccess, task_id::TaskName, Error, Run, RunCache}, - shim::TurboState, - signal::{SignalHandler, SignalSubscriber}, - turbo_json::{TurboJson, TurboJsonLoader, UIMode}, - DaemonConnector, -}; - -pub struct RunBuilder { - processes: ProcessManager, - opts: Opts, - api_auth: Option, - repo_root: AbsoluteSystemPathBuf, - color_config: ColorConfig, - version: &'static str, - api_client: APIClient, - analytics_sender: Option, - // In watch mode, we can have a changed package that we want to serve as an entrypoint. - // We will then prune away any tasks that do not depend on tasks inside - // this package. - entrypoint_packages: Option>, - should_print_prelude_override: Option, - // In query, we don't want to validate the engine. Defaults to `true` - should_validate_engine: bool, - // If true, we will add all tasks to the graph, even if they are not specified - add_all_tasks: bool, -} - -impl RunBuilder { - pub fn new(base: CommandBase) -> Result { - let api_client = base.api_client()?; - - let opts = base.opts(); - let api_auth = base.api_auth()?; - - let version = base.version(); - let processes = ProcessManager::new( - // We currently only use a pty if the following are met: - // - we're attached to a tty - atty::is(atty::Stream::Stdout) && - // - if we're on windows, we're using the UI - (!cfg!(windows) || matches!(opts.run_opts.ui_mode, UIMode::Tui)), - ); - - let CommandBase { - repo_root, - color_config: ui, - opts, - .. - } = base; - - Ok(Self { - processes, - opts, - api_client, - repo_root, - color_config: ui, - version, - api_auth, - analytics_sender: None, - entrypoint_packages: None, - should_print_prelude_override: None, - should_validate_engine: true, - add_all_tasks: false, - }) - } - - pub fn with_entrypoint_packages(mut self, entrypoint_packages: HashSet) -> Self { - self.entrypoint_packages = Some(entrypoint_packages); - self - } - - pub fn hide_prelude(mut self) -> Self { - self.should_print_prelude_override = Some(false); - self - } - - pub fn add_all_tasks(mut self) -> Self { - self.add_all_tasks = true; - self - } - - pub fn do_not_validate_engine(mut self) -> Self { - self.should_validate_engine = false; - self - } - - fn connect_process_manager(&self, signal_subscriber: SignalSubscriber) { - let manager = self.processes.clone(); - tokio::spawn(async move { - let _guard = signal_subscriber.listen().await; - manager.stop().await; - }); - } - - pub fn with_analytics_sender(mut self, analytics_sender: Option) -> Self { - self.analytics_sender = analytics_sender; - self - } - - pub fn calculate_filtered_packages( - repo_root: &AbsoluteSystemPath, - opts: &Opts, - pkg_dep_graph: &PackageGraph, - scm: &SCM, - root_turbo_json: &TurboJson, - ) -> Result, Error> { - let (mut filtered_pkgs, is_all_packages) = scope::resolve_packages( - &opts.scope_opts, - repo_root, - pkg_dep_graph, - scm, - root_turbo_json, - )?; - - if is_all_packages { - for target in opts.run_opts.tasks.iter() { - let mut task_name = TaskName::from(target.as_str()); - // If it's not a package task, we convert to a root task - if !task_name.is_package_task() { - task_name = task_name.into_root_task() - } - - if root_turbo_json.tasks.contains_key(&task_name) { - filtered_pkgs.insert( - PackageName::Root, - PackageInclusionReason::RootTask { - task: task_name.to_string(), - }, - ); - break; - } - } - }; - - Ok(filtered_pkgs) - } - - // Starts analytics and returns handle. This is not included in the main `build` - // function because we don't want the handle stored in the `Run` struct. - pub fn start_analytics(&self) -> (Option, Option) { - // If there's no API auth, we don't want to record analytics - let Some(api_auth) = self.api_auth.clone() else { - return (None, None); - }; - api_auth - .is_linked() - .then(|| start_analytics(api_auth, self.api_client.clone())) - .unzip() - } - - #[tracing::instrument(skip(self, signal_handler))] - pub async fn build( - mut self, - signal_handler: &SignalHandler, - telemetry: CommandEventBuilder, - ) -> Result { - tracing::trace!( - platform = %TurboState::platform_name(), - start_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).expect("system time after epoch").as_micros(), - turbo_version = %TurboState::version(), - numcpus = num_cpus::get(), - "performing run on {:?}", - TurboState::platform_name(), - ); - let start_at = Local::now(); - if let Some(subscriber) = signal_handler.subscribe() { - self.connect_process_manager(subscriber); - } - - let scm = { - let repo_root = self.repo_root.clone(); - tokio::task::spawn_blocking(move || SCM::new(&repo_root)) - }; - let package_json_path = self.repo_root.join_component("package.json"); - let root_package_json = PackageJson::load(&package_json_path)?; - let run_telemetry = GenericEventBuilder::new().with_parent(&telemetry); - let repo_telemetry = - RepoEventBuilder::new(&self.repo_root.to_string()).with_parent(&telemetry); - - // Pulled from initAnalyticsClient in run.go - let is_linked = turborepo_api_client::is_linked(&self.api_auth); - run_telemetry.track_is_linked(is_linked); - run_telemetry.track_arg_usage( - "dangerously_allow_missing_package_manager", - self.opts.repo_opts.allow_no_package_manager, - ); - // we only track the remote cache if we're linked because this defaults to - // Vercel - if is_linked { - run_telemetry.track_remote_cache(self.api_client.base_url()); - } - let _is_structured_output = self.opts.run_opts.graph.is_some() - || matches!(self.opts.run_opts.dry_run, Some(DryRunMode::Json)); - - let is_single_package = self.opts.run_opts.single_package; - repo_telemetry.track_type(if is_single_package { - RepoType::SinglePackage - } else { - RepoType::Monorepo - }); - - let is_ci_or_not_tty = turborepo_ci::is_ci() || !std::io::stdout().is_terminal(); - run_telemetry.track_ci(turborepo_ci::Vendor::get_name()); - - // Remove allow when daemon is flagged back on - let daemon = match (is_ci_or_not_tty, self.opts.run_opts.daemon) { - (true, None) => { - run_telemetry.track_daemon_init(DaemonInitStatus::Skipped); - debug!("skipping turbod since we appear to be in a non-interactive context"); - None - } - (_, Some(true)) | (false, None) => { - let can_start_server = true; - let can_kill_server = true; - let connector = - DaemonConnector::new(can_start_server, can_kill_server, &self.repo_root); - match (connector.connect().await, self.opts.run_opts.daemon) { - (Ok(client), _) => { - run_telemetry.track_daemon_init(DaemonInitStatus::Started); - debug!("running in daemon mode"); - Some(client) - } - (Err(e), Some(true)) => { - run_telemetry.track_daemon_init(DaemonInitStatus::Failed); - debug!("failed to connect to daemon when forced {e}, exiting"); - return Err(e.into()); - } - (Err(e), None) => { - run_telemetry.track_daemon_init(DaemonInitStatus::Failed); - debug!("failed to connect to daemon {e}"); - None - } - (_, Some(false)) => unreachable!(), - } - } - (_, Some(false)) => { - run_telemetry.track_daemon_init(DaemonInitStatus::Disabled); - debug!("skipping turbod since --no-daemon was passed"); - None - } - }; - - let mut pkg_dep_graph = { - let builder = PackageGraph::builder(&self.repo_root, root_package_json.clone()) - .with_single_package_mode(self.opts.run_opts.single_package) - .with_allow_no_package_manager(self.opts.repo_opts.allow_no_package_manager); - - // Daemon package discovery depends on packageManager existing in package.json - let graph = if cfg!(feature = "daemon-package-discovery") - && !self.opts.repo_opts.allow_no_package_manager - { - match (&daemon, self.opts.run_opts.daemon) { - (None, Some(true)) => { - // We've asked for the daemon, but it's not available. This is an error - return Err(turborepo_repository::package_graph::Error::Discovery( - DiscoveryError::Unavailable, - ) - .into()); - } - (Some(daemon), Some(true)) => { - // We have the daemon, and have explicitly asked to only use that - let daemon_discovery = DaemonPackageDiscovery::new(daemon.clone()); - builder - .with_package_discovery(daemon_discovery) - .build() - .await - } - (_, Some(false)) | (None, _) => { - // We have explicitly requested to not use the daemon, or we don't have it - // No change to default. - builder.build().await - } - (Some(daemon), None) => { - // We have the daemon, and it's not flagged off. Use the fallback strategy - let daemon_discovery = DaemonPackageDiscovery::new(daemon.clone()); - let local_discovery = LocalPackageDiscoveryBuilder::new( - self.repo_root.clone(), - None, - Some(root_package_json.clone()), - ) - .build()?; - let fallback_discover = FallbackPackageDiscovery::new( - daemon_discovery, - local_discovery, - Duration::from_millis(10), - ); - builder - .with_package_discovery(fallback_discover) - .build() - .await - } - } - } else { - builder.build().await - }; - - match graph { - Ok(graph) => graph, - // if we can't find the package.json, it is a bug, and we should report it. - // likely cause is that package discovery watching is not up to date. - // note: there _is_ a false positive from a race condition that can occur - // from toctou if the package.json is deleted, but we'd like to know - Err(turborepo_repository::package_graph::Error::PackageJson( - package_json::Error::Io(io), - )) if io.kind() == ErrorKind::NotFound => { - run_telemetry.track_error(TrackedErrors::InvalidPackageDiscovery); - return Err(turborepo_repository::package_graph::Error::PackageJson( - package_json::Error::Io(io), - ) - .into()); - } - Err(e) => return Err(e.into()), - } - }; - - repo_telemetry.track_package_manager(pkg_dep_graph.package_manager().name().to_string()); - repo_telemetry.track_size(pkg_dep_graph.len()); - run_telemetry.track_run_type(self.opts.run_opts.dry_run.is_some()); - let micro_frontend_configs = - MicrofrontendsConfigs::from_disk(&self.repo_root, &pkg_dep_graph)?; - - let scm = scm.await.expect("detecting scm panicked"); - let async_cache = AsyncCache::new( - &self.opts.cache_opts, - &self.repo_root, - self.api_client.clone(), - self.api_auth.clone(), - self.analytics_sender.take(), - )?; - - // restore config from task access trace if it's enabled - let task_access = TaskAccess::new(self.repo_root.clone(), async_cache.clone(), &scm); - task_access.restore_config().await; - - let mut turbo_json_loader = if task_access.is_enabled() { - TurboJsonLoader::task_access( - self.repo_root.clone(), - self.opts.repo_opts.root_turbo_json_path.clone(), - root_package_json.clone(), - ) - } else if is_single_package { - TurboJsonLoader::single_package( - self.repo_root.clone(), - self.opts.repo_opts.root_turbo_json_path.clone(), - root_package_json.clone(), - ) - } else if !self.opts.repo_opts.root_turbo_json_path.exists() && - // Infer a turbo.json if allowing no turbo.json is explicitly allowed or if MFE configs are discovered - (self.opts.repo_opts.allow_no_turbo_json || micro_frontend_configs.is_some()) - { - TurboJsonLoader::workspace_no_turbo_json( - self.repo_root.clone(), - pkg_dep_graph.packages(), - micro_frontend_configs.clone(), - ) - } else if let Some(micro_frontends) = µ_frontend_configs { - TurboJsonLoader::workspace_with_microfrontends( - self.repo_root.clone(), - self.opts.repo_opts.root_turbo_json_path.clone(), - pkg_dep_graph.packages(), - micro_frontends.clone(), - ) - } else { - TurboJsonLoader::workspace( - self.repo_root.clone(), - self.opts.repo_opts.root_turbo_json_path.clone(), - pkg_dep_graph.packages(), - ) - }; - - let root_turbo_json = turbo_json_loader.load(&PackageName::Root)?.clone(); - - pkg_dep_graph.validate()?; - - let filtered_pkgs = Self::calculate_filtered_packages( - &self.repo_root, - &self.opts, - &pkg_dep_graph, - &scm, - &root_turbo_json, - )?; - - let env_at_execution_start = EnvironmentVariableMap::infer(); - let mut engine = self.build_engine( - &pkg_dep_graph, - &root_turbo_json, - filtered_pkgs.keys(), - turbo_json_loader.clone(), - )?; - - if self.opts.run_opts.parallel { - pkg_dep_graph.remove_package_dependencies(); - engine = self.build_engine( - &pkg_dep_graph, - &root_turbo_json, - filtered_pkgs.keys(), - turbo_json_loader, - )?; - } - - let color_selector = ColorSelector::default(); - - let run_cache = Arc::new(RunCache::new( - async_cache, - &self.repo_root, - self.opts.runcache_opts, - &self.opts.cache_opts, - color_selector, - daemon.clone(), - self.color_config, - self.opts.run_opts.dry_run.is_some(), - )); - - let should_print_prelude = self.should_print_prelude_override.unwrap_or_else(|| { - self.opts.run_opts.dry_run.is_none() && self.opts.run_opts.graph.is_none() - }); - - Ok(Run { - version: self.version, - color_config: self.color_config, - start_at, - processes: self.processes, - run_telemetry, - task_access, - repo_root: self.repo_root, - opts: Arc::new(self.opts), - api_client: self.api_client, - api_auth: self.api_auth, - env_at_execution_start, - filtered_pkgs: filtered_pkgs.keys().cloned().collect(), - pkg_dep_graph: Arc::new(pkg_dep_graph), - root_turbo_json, - scm, - engine: Arc::new(engine), - run_cache, - signal_handler: signal_handler.clone(), - daemon, - should_print_prelude, - micro_frontend_configs, - }) - } - - fn build_engine<'a>( - &self, - pkg_dep_graph: &PackageGraph, - root_turbo_json: &TurboJson, - filtered_pkgs: impl Iterator, - turbo_json_loader: TurboJsonLoader, - ) -> Result { - let tasks = self.opts.run_opts.tasks.iter().map(|task| { - // TODO: Pull span info from command - Spanned::new(TaskName::from(task.as_str()).into_owned()) - }); - let mut builder = EngineBuilder::new( - &self.repo_root, - pkg_dep_graph, - turbo_json_loader, - self.opts.run_opts.single_package, - ) - .with_root_tasks(root_turbo_json.tasks.keys().cloned()) - .with_tasks_only(self.opts.run_opts.only) - .with_workspaces(filtered_pkgs.cloned().collect()) - .with_tasks(tasks); - - if self.add_all_tasks { - builder = builder.add_all_tasks(); - } - - if !self.should_validate_engine { - builder = builder.do_not_validate_engine(); - } - - let mut engine = builder.build()?; - - // If we have an initial task, we prune out the engine to only - // tasks that are reachable from that initial task. - if let Some(entrypoint_packages) = &self.entrypoint_packages { - engine = engine.create_engine_for_subgraph(entrypoint_packages); - } - - if !self.opts.run_opts.parallel && self.should_validate_engine { - engine - .validate( - pkg_dep_graph, - self.opts.run_opts.concurrency, - self.opts.run_opts.ui_mode, - ) - .map_err(Error::EngineValidation)?; - } - - Ok(engine) - } -} diff --git a/crates/turborepo-lib/src/run/package_discovery/mod.rs b/crates/turborepo-lib/src/run/package_discovery/mod.rs deleted file mode 100644 index 6be45cb24337b..0000000000000 --- a/crates/turborepo-lib/src/run/package_discovery/mod.rs +++ /dev/null @@ -1,73 +0,0 @@ -use turbopath::AbsoluteSystemPathBuf; -use turborepo_repository::discovery::{DiscoveryResponse, Error, PackageDiscovery, WorkspaceData}; - -use crate::daemon::{proto::PackageManager, DaemonClient}; - -#[derive(Debug)] -pub struct DaemonPackageDiscovery { - daemon: DaemonClient, -} - -impl DaemonPackageDiscovery { - pub fn new(daemon: DaemonClient) -> Self { - Self { daemon } - } -} - -impl PackageDiscovery for DaemonPackageDiscovery { - async fn discover_packages(&self) -> Result { - tracing::debug!("discovering packages using daemon"); - - // clone here so we can make concurrent requests - let mut daemon = self.daemon.clone(); - - let response = daemon - .discover_packages() - .await - .map_err(|e| Error::Failed(Box::new(e)))?; - - Ok(DiscoveryResponse { - workspaces: response - .package_files - .into_iter() - .map(|p| WorkspaceData { - package_json: AbsoluteSystemPathBuf::new(p.package_json).expect("absolute"), - turbo_json: p - .turbo_json - .map(|t| AbsoluteSystemPathBuf::new(t).expect("absolute")), - }) - .collect(), - package_manager: PackageManager::try_from(response.package_manager) - .expect("valid") - .into(), - }) - } - - async fn discover_packages_blocking(&self) -> Result { - tracing::debug!("discovering packages using daemon"); - - // clone here so we can make concurrent requests - let mut daemon = self.daemon.clone(); - - let response = daemon - .discover_packages_blocking() - .await - .map_err(|e| Error::Failed(Box::new(e)))?; - - Ok(DiscoveryResponse { - workspaces: response - .package_files - .into_iter() - .map(|p| WorkspaceData { - package_json: AbsoluteSystemPathBuf::new(p.package_json).expect("absolute"), - turbo_json: p - .turbo_json - .map(|t| AbsoluteSystemPathBuf::new(t).expect("absolute")), - }) - .collect(), - package_manager: PackageManager::try_from(response.package_manager) - .expect("valid") - .into(), - }) - } -} diff --git a/crates/turborepo-lib/src/run/scope/filter.rs b/crates/turborepo-lib/src/run/scope/filter.rs deleted file mode 100644 index d465b112807a4..0000000000000 --- a/crates/turborepo-lib/src/run/scope/filter.rs +++ /dev/null @@ -1,1387 +0,0 @@ -use std::{ - collections::{HashMap, HashSet}, - path::Path, - str::FromStr, -}; - -use miette::Diagnostic; -use tracing::debug; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; -use turborepo_repository::{ - change_mapper::{merge_changed_packages, ChangeMapError, PackageInclusionReason}, - package_graph::{self, PackageGraph, PackageName}, -}; -use turborepo_scm::SCM; -use wax::Program; - -use super::{ - change_detector::GitChangeDetector, - simple_glob::{Match, SimpleGlob}, - target_selector::{GitRange, InvalidSelectorError, TargetSelector}, -}; -use crate::{run::scope::change_detector::ScopeChangeDetector, turbo_json::TurboJson}; - -pub struct PackageInference { - package_name: Option, - directory_root: AnchoredSystemPathBuf, -} - -impl PackageInference { - // calculate, based on the directory that global turbo was invoked in, - // the pieces of a filter spec that we will infer. If turbo was invoked - // somewhere between the root and packages, scope turbo invocations to the - // packages below where turbo was invoked. If turbo was invoked at or within - // a particular package, scope the turbo invocation to just that package. - pub fn calculate( - turbo_root: &AbsoluteSystemPath, - pkg_inference_path: &AnchoredSystemPathBuf, - pkg_graph: &PackageGraph, - ) -> Self { - debug!( - "Using {} as a basis for selecting packages", - pkg_inference_path - ); - let full_inference_path = turbo_root.resolve(pkg_inference_path); - for (workspace_name, workspace_entry) in pkg_graph.packages() { - let pkg_path = turbo_root.resolve(workspace_entry.package_path()); - let inferred_path_is_below = pkg_path.contains(&full_inference_path); - // We skip over the root package as the inferred path will always be below it - if inferred_path_is_below && (&pkg_path as &AbsoluteSystemPath) != turbo_root { - // set both. The user might have set a parent directory filter, - // in which case we *should* fail to find any packages, but we should - // do so in a consistent manner - return Self { - package_name: Some(workspace_name.to_string()), - directory_root: workspace_entry.package_path().to_owned(), - }; - } - let inferred_path_is_between_root_and_pkg = full_inference_path.contains(&pkg_path); - if inferred_path_is_between_root_and_pkg { - // we've found *some* package below our inference directory. We can stop now and - // conclude that we're looking for all packages in a - // subdirectory - break; - } - } - Self { - package_name: None, - directory_root: pkg_inference_path.to_owned(), - } - } - - pub fn apply(&self, selector: &mut TargetSelector) { - // if the name pattern is provided, do not attempt inference - if !selector.name_pattern.is_empty() { - return; - }; - - if let Some(name) = &self.package_name { - selector.name_pattern.clone_from(name); - } - - if let Some(parent_dir) = selector.parent_dir.as_deref() { - let repo_relative_parent_dir = self.directory_root.join(parent_dir); - let clean_parent_dir = path_clean::clean(Path::new(repo_relative_parent_dir.as_path())) - .into_os_string() - .into_string() - .expect("path was valid utf8 before cleaning"); - selector.parent_dir = Some( - AnchoredSystemPathBuf::try_from(clean_parent_dir.as_str()) - .expect("path wasn't absolute before cleaning"), - ); - } else if self.package_name.is_none() { - // fallback: the user didn't set a parent directory and we didn't find a single - // package, so use the directory we inferred and select all subdirectories - let mut parent_dir = self.directory_root.clone(); - parent_dir.push("**"); - selector.parent_dir = Some(parent_dir); - } - } -} - -pub struct FilterResolver<'a, T: GitChangeDetector> { - pkg_graph: &'a PackageGraph, - turbo_root: &'a AbsoluteSystemPath, - inference: Option, - scm: &'a SCM, - change_detector: T, -} - -impl<'a> FilterResolver<'a, ScopeChangeDetector<'a>> { - pub(crate) fn new( - opts: &'a super::ScopeOpts, - pkg_graph: &'a PackageGraph, - turbo_root: &'a AbsoluteSystemPath, - inference: Option, - scm: &'a SCM, - root_turbo_json: &'a TurboJson, - ) -> Result { - let global_deps = opts - .global_deps - .iter() - .map(|s| s.as_str()) - .chain(root_turbo_json.global_deps.iter().map(|s| s.as_str())); - - let change_detector = - ScopeChangeDetector::new(turbo_root, scm, pkg_graph, global_deps, vec![])?; - - Ok(Self::new_with_change_detector( - pkg_graph, - turbo_root, - inference, - scm, - change_detector, - )) - } -} - -impl<'a, T: GitChangeDetector> FilterResolver<'a, T> { - pub(crate) fn new_with_change_detector( - pkg_graph: &'a PackageGraph, - turbo_root: &'a AbsoluteSystemPath, - inference: Option, - scm: &'a SCM, - change_detector: T, - ) -> Self { - Self { - pkg_graph, - turbo_root, - inference, - scm, - change_detector, - } - } - - /// Resolves a set of filter patterns into a set of packages, - /// based on the current state of the workspace. The result is - /// guaranteed to be a subset of the packages in the workspace, - /// and non-empty. If the filter is empty, none of the packages - /// in the workspace will be returned. - /// - /// It applies the following rules: - pub(crate) fn resolve( - &self, - affected: &Option<(Option, Option)>, - patterns: &[String], - ) -> Result<(HashMap, bool), ResolutionError> { - // inference is None only if we are in the root - let is_all_packages = patterns.is_empty() && self.inference.is_none() && affected.is_none(); - - let filter_patterns = if is_all_packages { - // return all packages in the workspace - self.pkg_graph - .packages() - .filter(|(name, _)| matches!(name, PackageName::Other(_))) - .map(|(name, _)| { - ( - name.to_owned(), - PackageInclusionReason::IncludedByFilter { - filters: patterns.to_vec(), - }, - ) - }) - .collect() - } else { - self.get_packages_from_patterns(affected, patterns)? - }; - - Ok((filter_patterns, is_all_packages)) - } - - fn get_packages_from_patterns( - &self, - affected: &Option<(Option, Option)>, - patterns: &[String], - ) -> Result, ResolutionError> { - let mut selectors = patterns - .iter() - .map(|pattern| TargetSelector::from_str(pattern)) - .collect::, _>>()?; - - if let Some((from_ref, to_ref)) = affected { - selectors.push(TargetSelector { - git_range: Some(GitRange { - from_ref: from_ref.clone(), - to_ref: to_ref.clone(), - include_uncommitted: true, - allow_unknown_objects: true, - merge_base: true, - }), - include_dependents: true, - ..Default::default() - }); - } - - self.get_filtered_packages(selectors) - } - - fn get_filtered_packages( - &self, - selectors: Vec, - ) -> Result, ResolutionError> { - let (_prod_selectors, all_selectors) = self - .apply_inference(selectors) - .into_iter() - .partition::, _>(|t| t.follow_prod_deps_only); - - if !all_selectors.is_empty() { - self.filter_graph(all_selectors) - } else { - Ok(Default::default()) - } - } - - fn apply_inference(&self, selectors: Vec) -> Vec { - let inference = match self.inference { - Some(ref inference) => inference, - None => return selectors, - }; - - // if there is no selector provided, synthesize one - let mut selectors = if selectors.is_empty() { - vec![Default::default()] - } else { - selectors - }; - - for selector in &mut selectors { - inference.apply(selector); - } - - selectors - } - - fn filter_graph( - &self, - selectors: Vec, - ) -> Result, ResolutionError> { - let (include_selectors, exclude_selectors) = - selectors.into_iter().partition::, _>(|t| !t.exclude); - - let mut include = if !include_selectors.is_empty() { - // TODO: add telemetry for each selector - self.filter_graph_with_selectors(include_selectors)? - } else { - self.pkg_graph - .packages() - // todo: a type-level way of dealing with non-root packages - .filter(|(name, _)| !PackageName::Root.eq(name)) // the root package has to be explicitly included - .map(|(name, _)| { - ( - name.to_owned(), - PackageInclusionReason::IncludedByFilter { - filters: exclude_selectors - .iter() - .map(|s| s.raw.to_string()) - .collect(), - }, - ) - }) - .collect() - }; - - // We want to just collect the names, not the reasons, so when we check for - // inclusion we don't need to check the reason - let exclude: HashSet = self - .filter_graph_with_selectors(exclude_selectors)? - .into_keys() - .collect(); - - include.retain(|i, _| !exclude.contains(i)); - - Ok(include) - } - - fn filter_graph_with_selectors( - &self, - selectors: Vec, - ) -> Result, ResolutionError> { - let mut unmatched_selectors = Vec::new(); - let mut walked_dependencies = HashMap::new(); - let mut walked_dependents = HashMap::new(); - let mut walked_dependent_dependencies = HashMap::new(); - let mut cherry_picked_packages = HashMap::new(); - - for selector in selectors { - let selector_packages = self.filter_graph_with_selector(&selector)?; - - if selector_packages.is_empty() { - unmatched_selectors.push(selector); - continue; - } - - for (package, reason) in selector_packages { - let node = package_graph::PackageNode::Workspace(package.clone()); - - if selector.include_dependencies { - let dependencies = self.pkg_graph.dependencies(&node); - let dependencies = dependencies - .iter() - .filter(|node| !matches!(node, package_graph::PackageNode::Root)) - .map(|i| { - ( - i.as_package_name().to_owned(), - // While we're adding dependencies, from their - // perspective, they were changed because - // of a *dependent* - PackageInclusionReason::DependentChanged { - dependent: package.to_owned(), - }, - ) - }) - .collect::>(); - - // flatmap through the option, the set, and then the optional package name - merge_changed_packages(&mut walked_dependencies, dependencies); - } - - if selector.include_dependents { - let dependents = self.pkg_graph.ancestors(&node); - for dependent in dependents.iter().map(|i| i.as_package_name()) { - walked_dependents.insert( - dependent.clone(), - // While we're adding dependents, from their - // perspective, they were changed because - // of a *dependency* - PackageInclusionReason::DependencyChanged { - dependency: package.to_owned(), - }, - ); - - // get the dependent's dependencies - if selector.include_dependencies { - let dependent_node = - package_graph::PackageNode::Workspace(dependent.to_owned()); - - let dependent_dependencies = - self.pkg_graph.dependencies(&dependent_node); - - let dependent_dependencies = dependent_dependencies - .iter() - .filter(|node| !matches!(node, package_graph::PackageNode::Root)) - .map(|i| { - ( - i.as_package_name().to_owned(), - PackageInclusionReason::DependencyChanged { - dependency: package.to_owned(), - }, - ) - }) - .collect::>(); - - merge_changed_packages( - &mut walked_dependent_dependencies, - dependent_dependencies, - ); - } - } - } - - if (selector.include_dependents || selector.include_dependencies) - && !selector.exclude_self - { - // if we are including dependents or dependencies, and we are not excluding - // ourselves, then we should add ourselves to the list of packages - walked_dependencies.insert(package, reason); - } else if !selector.include_dependencies && !selector.include_dependents { - // if we are neither including dependents or dependencies, then - // add to the list of cherry picked packages - cherry_picked_packages.insert(package, reason); - } - } - } - - let mut all_packages = HashMap::new(); - merge_changed_packages(&mut all_packages, walked_dependencies); - merge_changed_packages(&mut all_packages, walked_dependents); - merge_changed_packages(&mut all_packages, walked_dependent_dependencies); - merge_changed_packages(&mut all_packages, cherry_picked_packages); - - Ok(all_packages) - } - - fn filter_graph_with_selector( - &self, - selector: &TargetSelector, - ) -> Result, ResolutionError> { - if selector.match_dependencies { - self.filter_subtrees_with_selector(selector) - } else { - self.filter_nodes_with_selector(selector) - } - } - - /// returns the set of nodes where the node or any of its dependencies match - /// the selector. - /// - /// Example: - /// a -> b -> c - /// a -> d - /// - /// filter(b) = {a, b, c} - /// filter(d) = {a, d} - fn filter_subtrees_with_selector( - &self, - selector: &TargetSelector, - ) -> Result, ResolutionError> { - let mut entry_packages = HashMap::new(); - - for (name, info) in self.pkg_graph.packages() { - if let Some(parent_dir) = selector.parent_dir.as_deref() { - let path = parent_dir.to_unix(); - let parent_dir_matcher = wax::Glob::new(path.as_str())?; - let matches = parent_dir_matcher.is_match(info.package_path().as_path()); - - if matches { - entry_packages.insert( - name.to_owned(), - PackageInclusionReason::InFilteredDirectory { - directory: parent_dir.to_owned(), - }, - ); - } - } else { - entry_packages.insert( - name.to_owned(), - PackageInclusionReason::IncludedByFilter { - filters: vec![selector.raw.to_string()], - }, - ); - } - } - - // if we have a filter, use it to filter the entry packages - let filtered_entry_packages = if !selector.name_pattern.is_empty() { - match_package_names(&selector.name_pattern, &self.all_packages(), entry_packages)? - } else { - entry_packages - }; - - let mut roots = HashMap::new(); - let mut matched = HashSet::new(); - let changed_packages = if let Some(git_range) = selector.git_range.as_ref() { - self.packages_changed_in_range(git_range)? - } else { - HashMap::default() - }; - - for (package, reason) in filtered_entry_packages { - if matched.contains(&package) { - roots.insert(package, reason); - continue; - } - - let workspace_node = package_graph::PackageNode::Workspace(package.clone()); - let dependencies = self.pkg_graph.dependencies(&workspace_node); - - for changed_package in changed_packages.keys() { - if !selector.exclude_self && package.eq(changed_package) { - roots.insert(package, reason); - break; - } - - let changed_node = - package_graph::PackageNode::Workspace(changed_package.to_owned()); - - if dependencies.contains(&changed_node) { - roots.insert(package.clone(), reason); - matched.insert(package); - break; - } - } - } - - Ok(roots) - } - - fn filter_nodes_with_selector( - &self, - selector: &TargetSelector, - ) -> Result, ResolutionError> { - let mut entry_packages = HashMap::new(); - let mut selector_valid = false; - - let parent_dir_unix = selector.parent_dir.as_deref().map(|path| path.to_unix()); - let parent_dir_globber = parent_dir_unix - .as_deref() - .map(|path| { - wax::Glob::new(path.as_str()).map_err(|err| ResolutionError::InvalidDirectoryGlob { - glob: path.as_str().to_string(), - err: Box::new(err), - }) - }) - .transpose()?; - - if let Some(globber) = parent_dir_globber.clone() { - let (base, _) = globber.partition(); - // wax takes a unix-like glob, but partition will return a system path - // TODO: it would be more proper to use - // `AnchoredSystemPathBuf::from_system_path` but that function - // doesn't allow leading `.` or `..`. - let base = AnchoredSystemPathBuf::from_raw( - base.to_str().expect("glob base should be valid utf8"), - ) - .expect("partitioned glob gave absolute path"); - // need to join this with globbing's current dir :) - let path = self.turbo_root.resolve(&base); - if !path.exists() { - return Err(ResolutionError::DirectoryDoesNotExist(path)); - } - } - - if let Some(git_range) = selector.git_range.as_ref() { - selector_valid = true; - let changed_packages = self.packages_changed_in_range(git_range)?; - let package_path_lookup = self - .pkg_graph - .packages() - .map(|(name, entry)| (name, entry.package_path())) - .collect::>(); - - for (package, reason) in changed_packages { - if let Some(parent_dir_globber) = parent_dir_globber.as_ref() { - if package == PackageName::Root { - // The root package changed, only add it if - // the parentDir is equivalent to the root - if parent_dir_globber.matched(&Path::new(".").into()).is_some() { - entry_packages.insert(package, reason); - } - } else { - let path = package_path_lookup - .get(&package) - .ok_or(ResolutionError::MissingPackageInfo(package.to_string()))?; - - if parent_dir_globber.is_match(path.as_path()) { - entry_packages.insert(package, reason); - } - } - } else { - entry_packages.insert(package, reason); - } - } - } else if let Some((parent_dir, parent_dir_globber)) = selector - .parent_dir - .as_deref() - .zip(parent_dir_globber.as_ref()) - { - selector_valid = true; - if parent_dir == &*AnchoredSystemPathBuf::from_raw(".").expect("valid anchored") { - entry_packages.insert( - PackageName::Root, - PackageInclusionReason::InFilteredDirectory { - directory: parent_dir.to_owned(), - }, - ); - } else { - let packages = self.pkg_graph.packages(); - for (name, _) in packages.filter(|(_name, info)| { - let path = info.package_path().as_path(); - parent_dir_globber.is_match(path) - }) { - entry_packages.insert( - name.to_owned(), - PackageInclusionReason::InFilteredDirectory { - directory: parent_dir.to_owned(), - }, - ); - } - } - } - - if !selector.name_pattern.is_empty() { - if !selector_valid { - entry_packages = self - .all_packages() - .into_iter() - .map(|name| { - ( - name, - PackageInclusionReason::IncludedByFilter { - filters: vec![selector.raw.to_string()], - }, - ) - }) - .collect(); - selector_valid = true; - } - let all_packages = self.all_packages(); - entry_packages = - match_package_names(&selector.name_pattern, &all_packages, entry_packages)?; - } - - // if neither a name pattern, parent dir, or from ref is provided, then - // the selector is invalid - if !selector_valid { - Err(ResolutionError::InvalidSelector( - InvalidSelectorError::InvalidSelector(selector.raw.clone()), - )) - } else { - Ok(entry_packages) - } - } - - pub fn packages_changed_in_range( - &self, - git_range: &GitRange, - ) -> Result, ResolutionError> { - self.change_detector.changed_packages( - git_range.from_ref.as_deref(), - git_range.to_ref.as_deref(), - git_range.include_uncommitted, - git_range.allow_unknown_objects, - git_range.merge_base, - ) - } - - fn all_packages(&self) -> HashSet { - let mut packages = self - .pkg_graph - .packages() - .map(|(name, _)| name.to_owned()) - .collect::>(); - packages.insert(PackageName::Root); - packages - } -} - -/// match the provided name pattern against the provided set of packages -/// and return the set of packages that match the pattern -/// -/// the pattern is normalized, replacing `\*` with `.*` -fn match_package_names( - name_pattern: &str, - all_packages: &HashSet, - mut packages: HashMap, -) -> Result, ResolutionError> { - let matcher = SimpleGlob::new(name_pattern)?; - let matched_packages = all_packages - .iter() - .filter(|e| matcher.is_match(e.as_ref())) - .cloned() - .collect::>(); - - // If the pattern was an exact name and it matched no packages, then error - if matcher.is_exact() && matched_packages.is_empty() { - return Err(ResolutionError::NoPackagesMatchedWithName( - name_pattern.to_owned(), - )); - } - - packages.retain(|pkg, _| matched_packages.contains(pkg)); - - Ok(packages) -} - -#[derive(Debug, thiserror::Error, Diagnostic)] -pub enum ResolutionError { - #[error("missing info for package")] - MissingPackageInfo(String), - #[error("No packages matched the provided filter")] - NoPackagesMatched, - #[error("Multiple packages matched the provided filter")] - MultiplePackagesMatched, - #[error("The provided filter matched a package that is not in the workspace")] - PackageNotInWorkspace, - #[error("No package found with name '{0}' in workspace")] - NoPackagesMatchedWithName(String), - #[error("selector not used: {0}")] - InvalidSelector(#[from] InvalidSelectorError), - #[error("Invalid regex pattern")] - InvalidRegex(#[from] regex::Error), - #[error("Invalid glob pattern")] - InvalidGlob(#[from] wax::BuildError), - #[error("Unable to query SCM: {0}")] - Scm(#[from] turborepo_scm::Error), - #[error("Unable to calculate changes: {0}")] - ChangeDetectError(#[from] ChangeMapError), - #[error("'Invalid directory filter '{glob}': {err}")] - InvalidDirectoryGlob { - glob: String, - err: Box, - }, - #[error("Directory '{0}' specified in filter does not exist")] - DirectoryDoesNotExist(AbsoluteSystemPathBuf), - #[error("failed to construct glob for globalDependencies")] - GlobalDependenciesGlob(#[from] turborepo_repository::change_mapper::Error), -} - -#[cfg(test)] -mod test { - use std::collections::{HashMap, HashSet}; - - use pretty_assertions::assert_eq; - use tempfile::TempDir; - use test_case::test_case; - use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf, RelativeUnixPathBuf}; - use turborepo_repository::{ - change_mapper::PackageInclusionReason, - discovery::PackageDiscovery, - package_graph::{PackageGraph, PackageName, ROOT_PKG_NAME}, - package_json::PackageJson, - package_manager::PackageManager, - }; - - use super::{FilterResolver, PackageInference, TargetSelector}; - use crate::run::scope::{ - change_detector::GitChangeDetector, target_selector::GitRange, ResolutionError, - }; - - fn get_name(name: &str) -> (Option<&str>, &str) { - if let Some(idx) = name.rfind('/') { - // check if the rightmost slash has an @ - if let Some(idx) = name[..idx].find('@') { - return (Some(&name[..idx - 1]), &name[idx..]); - } - - return (Some(&name[..idx]), &name[idx + 1..]); - } - - (None, name) - } - - fn reverse(tuple: (T, U)) -> (U, T) { - let (a, b) = tuple; - (b, a) - } - - struct MockDiscovery; - impl PackageDiscovery for MockDiscovery { - async fn discover_packages( - &self, - ) -> Result< - turborepo_repository::discovery::DiscoveryResponse, - turborepo_repository::discovery::Error, - > { - Ok(turborepo_repository::discovery::DiscoveryResponse { - package_manager: PackageManager::Pnpm6, - workspaces: vec![], // we don't care about this - }) - } - - async fn discover_packages_blocking( - &self, - ) -> Result< - turborepo_repository::discovery::DiscoveryResponse, - turborepo_repository::discovery::Error, - > { - self.discover_packages().await - } - } - - /// Make a project resolver with the provided dependencies. Extras is for - /// packages that are not dependencies of any other package. - fn make_project( - dependencies: &[(&str, &str)], - extras: &[&str], - package_inference: Option, - change_detector: T, - ) -> (TempDir, super::FilterResolver<'static, T>) { - let temp_folder = tempfile::tempdir().unwrap(); - let turbo_root = Box::leak(Box::new( - AbsoluteSystemPathBuf::new(temp_folder.path().as_os_str().to_str().unwrap()).unwrap(), - )); - - let package_dirs = dependencies - .iter() - .flat_map(|(a, b)| vec![a, b]) - .chain(extras.iter()) - .collect::>(); - - let dependencies = - dependencies - .iter() - .fold(HashMap::<&str, Vec<&str>>::new(), |mut acc, (k, v)| { - let k = get_name(k).1; - let v = get_name(v).1; - acc.entry(k).or_default().push(v); - acc - }); - - let package_jsons = package_dirs - .iter() - .map(|package_path| { - let (_, name) = get_name(package_path); - ( - turbo_root.join_unix_path( - RelativeUnixPathBuf::new(format!("{package_path}/package.json")).unwrap(), - ), - PackageJson { - name: Some(name.to_string()), - dependencies: dependencies.get(name).map(|v| { - v.iter() - .map(|name| (name.to_string(), "*".to_string())) - .collect() - }), - ..Default::default() - }, - ) - }) - .collect::>(); - - for package_dir in package_jsons.keys() { - package_dir.ensure_dir().unwrap(); - } - - let graph = { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .unwrap(); - rt.block_on( - PackageGraph::builder(turbo_root, Default::default()) - .with_package_discovery(MockDiscovery) - .with_package_jsons(Some(package_jsons)) - .build(), - ) - .unwrap() - }; - - let pkg_graph = Box::leak(Box::new(graph)); - - let scm = Box::leak(Box::new(turborepo_scm::SCM::new(turbo_root))); - - let resolver = FilterResolver::<'static>::new_with_change_detector( - pkg_graph, - turbo_root, - package_inference, - scm, - change_detector, - ); - - // TempDir's drop implementation will mark the folder as ready for cleanup - // which can lead to non-deterministic test results if the folder is removed - // before the test finishes. - (temp_folder, resolver) - } - - #[test_case( - vec![ - TargetSelector { - name_pattern: ROOT_PKG_NAME.to_string(), - ..Default::default() - } - ], - None, - &[ROOT_PKG_NAME] ; - "select root package" - )] - #[test_case( - vec![ - TargetSelector { - exclude_self: true, - include_dependencies: true, - name_pattern: "project-1".to_string(), - ..Default::default() - } - ], - None, - &["project-2", "project-4"] ; - "select only package dependencies (excluding the package itself)" - )] - #[test_case( - vec![ - TargetSelector { - exclude_self: false, - include_dependencies: true, - name_pattern: "project-1".to_string(), - ..Default::default() - } - ], - None, - &["project-1", "project-2", "project-4"] ; - "select package with dependencies" - )] - #[test_case( - vec![ - TargetSelector { - exclude_self: false, - include_dependencies: true, - name_pattern: "project-0".to_string(), - ..Default::default() - } - ], - None, - &["project-0", "project-1", "project-2", "project-4", "project-5"] ; - "select package with transitive dependencies" - )] - #[test_case( - vec![ - TargetSelector { - exclude_self: true, - include_dependencies: true, - include_dependents: true, - name_pattern: "project-1".to_string(), - ..Default::default() - } - ], - None, - &["project-0", "project-1", "project-2", "project-4", "project-5"] ; - "select package with dependencies and dependents, including dependent - dependencies" )] - #[test_case( - vec![ - TargetSelector { - include_dependents: true, - name_pattern: "project-2".to_string(), - ..Default::default() - } - ], - None, - &["project-1", "project-2", "project-0"] ; - "select package with dependents" - )] - #[test_case( - vec![ - TargetSelector { - exclude_self: true, - include_dependents: true, - name_pattern: "project-2".to_string(), - ..Default::default() - } - ], - None, - &["project-0", "project-1"] ; - "select dependents excluding package itself" - )] - #[test_case( - vec![ - TargetSelector { - exclude_self: true, - include_dependents: true, - name_pattern: "project-2".to_string(), - ..Default::default() - }, - TargetSelector { - include_dependencies: true, - exclude_self: true, - name_pattern: "project-1".to_string(), - ..Default::default() - } - ], - None, - &["project-0", "project-1", "project-2", "project-4"] ; - "filter using two selectors: one selects dependencies another selects - dependents" )] - #[test_case( - vec![ - TargetSelector { - name_pattern: "project-2".to_string(), - ..Default::default() - } - ], - None, - &["project-2"] ; - "select just a package by name" - )] - #[test_case( - vec![ - TargetSelector { - parent_dir: - Some(AnchoredSystemPathBuf::try_from("packages/*").unwrap()), - ..Default::default() } - ], - None, - &["project-0", "project-1"] ; - "select by parentDir using glob" - )] - #[test_case( - vec![TargetSelector { - parent_dir: Some(AnchoredSystemPathBuf::try_from(if cfg!(windows) { "..\\packages\\*" } else { "../packages/*" }).unwrap()), - ..Default::default() - }], - Some(PackageInference{ - package_name: None, - directory_root: AnchoredSystemPathBuf::try_from("project-5").unwrap(), - }), - &["project-0", "project-1"] ; - "select sibling directory" - )] - #[test_case( - vec![ - TargetSelector { - parent_dir: - Some(AnchoredSystemPathBuf::try_from("project-5/**").unwrap()), - ..Default::default() } - ], - None, - &["project-5", "project-6"] ; - "select by parentDir using globstar" - )] - #[test_case( - vec![ - TargetSelector { - parent_dir: - Some(AnchoredSystemPathBuf::try_from("project-5").unwrap()), - ..Default::default() } - ], - None, - &["project-5"] ; - "select by parentDir with no glob" - )] - #[test_case( - vec![ - TargetSelector { - exclude: true, - name_pattern: "project-1".to_string(), - ..Default::default() - } - ], - None, - &["project-0", "project-2", "project-3", "project-4", "project-5", "project-6"] ; - "select all packages except one" - )] - #[test_case( - vec![ - TargetSelector { - parent_dir: Some(AnchoredSystemPathBuf::try_from("packages/*").unwrap()), - ..Default::default() - }, - TargetSelector { - exclude: true, - name_pattern: "*-1".to_string(), - ..Default::default() - } - ], - None, - &["project-0"] ; - "select by parentDir and exclude one package by pattern" - )] - #[test_case( - vec![ - TargetSelector { - parent_dir: Some(AnchoredSystemPathBuf::try_from(".").unwrap()), - ..Default::default() - } - ], - None, - &[ROOT_PKG_NAME] ; - "select root package by directory" - )] - #[test_case( - vec![], - Some(PackageInference{ - package_name: None, - directory_root: AnchoredSystemPathBuf::try_from("packages").unwrap(), - }), - &["project-0", "project-1"] ; - "select packages directory" - )] - #[test_case( - vec![], - Some(PackageInference{ - package_name: Some("project-0".to_string()), - directory_root: AnchoredSystemPathBuf::try_from("packages/project-0").unwrap(), - }), - &["project-0"] ; - "infer single package" - )] - #[test_case( - vec![], - Some(PackageInference{ - package_name: Some("project-0".to_string()), - directory_root: AnchoredSystemPathBuf::try_from("packages/project-0/src").unwrap(), - }), - &["project-0"] ; - "infer single package from subdirectory" - )] - fn filter( - selectors: Vec, - package_inference: Option, - expected: &[&str], - ) { - let (_tempdir, resolver) = make_project( - &[ - ("packages/project-0", "packages/project-1"), - ("packages/project-0", "project-5"), - ("packages/project-1", "project-2"), - ("packages/project-1", "project-4"), - ], - &["project-3", "project-5/packages/project-6"], - package_inference, - TestChangeDetector::new(&[]), - ); - - let packages = resolver.get_filtered_packages(selectors).unwrap(); - - assert_eq!( - packages.into_keys().collect::>(), - expected.iter().map(|s| PackageName::from(*s)).collect() - ); - } - - #[test] - fn match_exact() { - let (_tempdir, resolver) = make_project( - &[], - &["packages/@foo/bar", "packages/bar"], - None, - TestChangeDetector::new(&[]), - ); - let packages = resolver - .get_filtered_packages(vec![TargetSelector { - name_pattern: "bar".to_string(), - raw: "bar".to_string(), - ..Default::default() - }]) - .unwrap(); - - assert_eq!( - packages, - vec![( - PackageName::Other("bar".to_string()), - PackageInclusionReason::IncludedByFilter { - filters: vec!["bar".to_string()] - } - )] - .into_iter() - .collect() - ); - } - - #[test] - fn match_scoped_package() { - let (_tempdir, resolver) = make_project( - &[], - &["packages/bar/@foo/bar"], - None, - TestChangeDetector::new(&[]), - ); - let packages = resolver.get_filtered_packages(vec![TargetSelector { - name_pattern: "bar".to_string(), - raw: "bar".to_string(), - ..Default::default() - }]); - - assert!(packages.is_err(), "non existing package name should error",); - - let packages = resolver - .get_filtered_packages(vec![TargetSelector { - name_pattern: "@foo/bar".to_string(), - raw: "@foo/bar".to_string(), - ..Default::default() - }]) - .unwrap(); - - assert_eq!( - packages, - vec![( - PackageName::from("@foo/bar"), - PackageInclusionReason::IncludedByFilter { - filters: vec!["@foo/bar".to_string()] - } - )] - .into_iter() - .collect() - ); - } - - #[test] - fn test_no_matching_name() { - let (_tempdir, resolver) = make_project( - &[], - &["packages/bar/@foo/bar"], - None, - TestChangeDetector::new(&[]), - ); - let packages = resolver.get_filtered_packages(vec![TargetSelector { - name_pattern: "bar".to_string(), - ..Default::default() - }]); - - assert!(packages.is_err(), "non existing package name should error",); - - let packages = resolver - .get_filtered_packages(vec![TargetSelector { - name_pattern: "baz*".to_string(), - ..Default::default() - }]) - .unwrap(); - assert!( - packages.is_empty(), - "expected no matches, got {:?}", - packages - ); - } - - #[test] - fn test_no_directory() { - let (_tempdir, resolver) = make_project( - &[("packages/foo", "packages/bar")], - &[], - None, - TestChangeDetector::new(&[]), - ); - let packages = resolver.get_filtered_packages(vec![TargetSelector { - parent_dir: Some(AnchoredSystemPathBuf::try_from("pakcages/*").unwrap()), - ..Default::default() - }]); - - assert!(packages.is_err(), "non existing dir should error",); - } - - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), - ..Default::default() - } - ], - &["package-1", "package-2", ROOT_PKG_NAME] ; - "all changed packages" - )] - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), - parent_dir: Some(AnchoredSystemPathBuf::try_from(".").unwrap()), - ..Default::default() - } - ], - &[ROOT_PKG_NAME] ; - "all changed packages with parent dir exact match" - )] - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), - parent_dir: Some(AnchoredSystemPathBuf::try_from("package-2").unwrap()), - ..Default::default() - } - ], - &["package-2"] ; - "changed packages in directory" - )] - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), - name_pattern: "package-2*".to_string(), - ..Default::default() - } - ], - &["package-2"] ; - "changed packages matching pattern" - )] - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), - name_pattern: "package-1".to_string(), - match_dependencies: true, - ..Default::default() - } - ], - &["package-1"] ; - "changed package was requested scope, and we're matching dependencies" - )] - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~2".to_string()), to_ref: None, ..Default::default() }), - ..Default::default() - } - ], - &["package-1", "package-2", "package-3", ROOT_PKG_NAME] ; - "older commit" - )] - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~2".to_string()), to_ref: Some("HEAD~1".to_string()), ..Default::default() }), - ..Default::default() - } - ], - &["package-3"] ; - "commit range" - )] - #[test_case( - vec![ - TargetSelector { - git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), - parent_dir: Some(AnchoredSystemPathBuf::try_from("package-*").unwrap()), - match_dependencies: true, ..Default::default() - } - ], - &["package-1", "package-2"] ; - "match dependency subtree" - )] - #[test_case( - vec![ - TargetSelector { - name_pattern: "package-3".to_string(), - git_range: Some(GitRange { from_ref: Some("HEAD~1".to_string()), to_ref: None, ..Default::default() }), - ..Default::default() - } - ], - &[] ; - "gh 9096" - )] - fn scm(selectors: Vec, expected: &[&str]) { - let scm_resolver = TestChangeDetector::new(&[ - ("HEAD~1", None, &["package-1", "package-2", ROOT_PKG_NAME]), - ("HEAD~2", Some("HEAD~1"), &["package-3"]), - ( - "HEAD~2", - None, - &["package-1", "package-2", "package-3", ROOT_PKG_NAME], - ), - ]); - - let (_tempdir, resolver) = make_project( - &[("package-3", "package-20")], - &["package-1", "package-2"], - None, - scm_resolver, - ); - - let packages = resolver.get_filtered_packages(selectors).unwrap(); - assert_eq!( - packages.into_keys().collect::>(), - expected.iter().map(|s| PackageName::from(*s)).collect() - ); - } - - struct TestChangeDetector<'a>( - HashMap<(&'a str, Option<&'a str>), HashMap>, - ); - - impl<'a> TestChangeDetector<'a> { - fn new(pairs: &[(&'a str, Option<&'a str>, &[&'a str])]) -> Self { - let mut map = HashMap::new(); - for (from, to, changed) in pairs { - map.insert( - (*from, *to), - changed - .iter() - .map(|s| { - ( - PackageName::from(*s), - // This is just a random reason, - PackageInclusionReason::IncludedByFilter { filters: vec![] }, - ) - }) - .collect(), - ); - } - - Self(map) - } - } - - impl<'a> GitChangeDetector for TestChangeDetector<'a> { - fn changed_packages( - &self, - from: Option<&str>, - to: Option<&str>, - _include_uncommitted: bool, - _allow_unknown_objects: bool, - _merge_base: bool, - ) -> Result, ResolutionError> { - Ok(self - .0 - .get(&(from.expect("expected base branch"), to)) - .map(|h| h.to_owned()) - .expect("unsupported range")) - } - } -} diff --git a/crates/turborepo-lib/src/run/scope/mod.rs b/crates/turborepo-lib/src/run/scope/mod.rs deleted file mode 100644 index 7bed4b3b19f00..0000000000000 --- a/crates/turborepo-lib/src/run/scope/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod change_detector; -pub mod filter; -mod simple_glob; -pub mod target_selector; - -use std::collections::HashMap; - -use filter::{FilterResolver, PackageInference}; -use turbopath::AbsoluteSystemPath; -use turborepo_repository::{ - change_mapper::PackageInclusionReason, - package_graph::{PackageGraph, PackageName}, -}; -use turborepo_scm::SCM; - -pub use crate::run::scope::filter::ResolutionError; -use crate::{opts::ScopeOpts, turbo_json::TurboJson}; - -#[tracing::instrument(skip(opts, pkg_graph, scm))] -pub fn resolve_packages( - opts: &ScopeOpts, - turbo_root: &AbsoluteSystemPath, - pkg_graph: &PackageGraph, - scm: &SCM, - root_turbo_json: &TurboJson, -) -> Result<(HashMap, bool), ResolutionError> { - let pkg_inference = opts.pkg_inference_root.as_ref().map(|pkg_inference_path| { - PackageInference::calculate(turbo_root, pkg_inference_path, pkg_graph) - }); - - FilterResolver::new( - opts, - pkg_graph, - turbo_root, - pkg_inference, - scm, - root_turbo_json, - )? - .resolve(&opts.affected_range, &opts.get_filters()) -} diff --git a/crates/turborepo-lib/src/run/scope/simple_glob.rs b/crates/turborepo-lib/src/run/scope/simple_glob.rs deleted file mode 100644 index b0ccb4aae633d..0000000000000 --- a/crates/turborepo-lib/src/run/scope/simple_glob.rs +++ /dev/null @@ -1,91 +0,0 @@ -use regex::Regex; - -/// A simple glob-like pattern that supports a subset of -/// glob syntax for the purposes of string matching. -/// If you are matching paths, use `turborepo_wax::glob::Glob` instead. -pub enum SimpleGlob { - Regex(Regex), - String(String), - Any, -} - -pub trait Match { - fn is_match(&self, s: &str) -> bool; -} - -impl SimpleGlob { - pub fn new(pattern: &str) -> Result { - if pattern == "*" { - Ok(SimpleGlob::Any) - } else if pattern.contains('*') { - let regex = Regex::new(&format!("^{}$", pattern.replace('*', ".*")))?; - Ok(SimpleGlob::Regex(regex)) - } else { - Ok(SimpleGlob::String(pattern.to_string())) - } - } - - pub fn is_exact(&self) -> bool { - matches!(self, Self::String(_)) - } -} - -impl Match for SimpleGlob { - fn is_match(&self, s: &str) -> bool { - match self { - SimpleGlob::Regex(regex) => regex.is_match(s), - SimpleGlob::String(string) => string == s, - SimpleGlob::Any => true, - } - } -} - -pub struct AnyGlob(Vec); - -impl Match for AnyGlob { - fn is_match(&self, s: &str) -> bool { - self.0.iter().any(|glob| glob.is_match(s)) - } -} - -pub struct NotGlob(T); - -impl Match for NotGlob { - fn is_match(&self, s: &str) -> bool { - !self.0.is_match(s) - } -} - -pub struct IncludeExcludeGlob { - include: I, - exclude: E, -} - -impl IncludeExcludeGlob, AnyGlob> { - pub fn new_from_globs<'a>( - include: impl Iterator>, - exclude: impl Iterator>, - _include_default: bool, - _exclude_default: bool, - ) -> Self { - let include = AnyGlob( - include - .map(|glob| SimpleGlob::new(glob.as_ref()).unwrap()) - .collect(), - ); - - let exclude = AnyGlob( - exclude - .map(|glob| SimpleGlob::new(glob.as_ref()).unwrap()) - .collect(), - ); - - Self { include, exclude } - } -} - -impl Match for IncludeExcludeGlob { - fn is_match(&self, s: &str) -> bool { - self.include.is_match(s) && !self.exclude.is_match(s) - } -} diff --git a/crates/turborepo-lib/src/run/scope/target_selector.rs b/crates/turborepo-lib/src/run/scope/target_selector.rs deleted file mode 100644 index cae2e70fa6d57..0000000000000 --- a/crates/turborepo-lib/src/run/scope/target_selector.rs +++ /dev/null @@ -1,308 +0,0 @@ -use std::str::FromStr; - -use regex::Regex; -use thiserror::Error; -use turbopath::AnchoredSystemPathBuf; - -#[derive(Debug, Default, PartialEq)] -pub struct GitRange { - pub from_ref: Option, - pub to_ref: Option, - pub include_uncommitted: bool, - // Allow unknown objects to be included in the range, without returning an error. - // this is useful for shallow clones where objects may not exist. - // When this happens, we assume that everything has changed. - pub allow_unknown_objects: bool, - // Calculate diff between merge base of the two refs and the second ref - // (this is usually what you want for detecting changes) - pub merge_base: bool, -} - -#[derive(Debug, Default, PartialEq)] -pub struct TargetSelector { - pub include_dependencies: bool, - pub match_dependencies: bool, - pub include_dependents: bool, - pub exclude: bool, - pub exclude_self: bool, - pub follow_prod_deps_only: bool, - pub parent_dir: Option, - pub name_pattern: String, - pub git_range: Option, - pub raw: String, -} - -impl FromStr for TargetSelector { - type Err = InvalidSelectorError; - - fn from_str(raw_selector: &str) -> Result { - let selector = raw_selector.strip_prefix('!'); - let (exclude, selector) = match selector { - Some(selector) => (true, selector), - None => (false, raw_selector), - }; - - let mut exclude_self = false; - let include_dependencies = selector.strip_suffix("..."); - - let (include_dependencies, selector) = if let Some(selector) = include_dependencies { - ( - true, - if let Some(selector) = selector.strip_suffix('^') { - exclude_self = true; - selector - } else { - selector - }, - ) - } else { - (false, selector) - }; - - let include_dependents = selector.strip_prefix("..."); - let (include_dependents, selector) = if let Some(selector) = include_dependents { - ( - true, - if let Some(selector) = selector.strip_prefix('^') { - exclude_self = true; - selector - } else { - selector - }, - ) - } else { - (false, selector) - }; - - // We explicitly allow empty git ranges so we can return a more targeted error - // below - let re = Regex::new(r"^(?P[^.](?:[^{}\[\]]*[^{}\[\].])?)?(\{(?P[^}]*)})?(?P(?:\.{3})?\[[^\]]*\])?$").expect("valid"); - let captures = re.captures(selector); - - let captures = match captures { - Some(captures) => captures, - None => { - return if let Some(relative_path) = is_selector_by_location(selector) { - Ok(TargetSelector { - exclude, - include_dependencies, - include_dependents, - parent_dir: Some(relative_path?), - raw: raw_selector.to_string(), - ..Default::default() - }) - } else { - Ok(TargetSelector { - exclude, - exclude_self, - include_dependencies, - include_dependents, - name_pattern: selector.to_string(), - raw: raw_selector.to_string(), - ..Default::default() - }) - } - } - }; - - let mut pre_add_dependencies = false; - - let name_pattern = captures - .name("name") - .map_or(String::new(), |m| m.as_str().to_string()); - - let mut parent_dir = None; - - if let Some(directory) = captures.name("directory") { - let directory = directory.as_str().to_string(); - if directory.is_empty() { - return Err(InvalidSelectorError::EmptyPathSpecification); - } else { - let clean_directory = path_clean::clean(std::path::Path::new(directory.as_str())) - .into_os_string() - .into_string() - .expect("directory was valid utf8 before cleaning"); - parent_dir = Some( - AnchoredSystemPathBuf::try_from(clean_directory.as_str()) - .map_err(|_| InvalidSelectorError::InvalidAnchoredPath(directory))?, - ); - } - } - - let git_range = if let Some(commits) = captures.name("commits") { - let commits_str = if let Some(commits) = commits.as_str().strip_prefix("...") { - if parent_dir.is_none() && name_pattern.is_empty() { - return Err(InvalidSelectorError::CantMatchDependencies); - } - pre_add_dependencies = true; - commits - } else { - commits.as_str() - }; - - // strip the square brackets - let commits_str = commits_str - .strip_prefix('[') - .and_then(|s| s.strip_suffix(']')) - .expect("regex guarantees square brackets"); - if commits_str.is_empty() { - return Err(InvalidSelectorError::InvalidGitRange( - commits_str.to_string(), - )); - } - - let git_range = if let Some((a, b)) = commits_str.split_once("...") { - if a.is_empty() || b.is_empty() { - return Err(InvalidSelectorError::InvalidGitRange( - commits_str.to_string(), - )); - } - GitRange { - from_ref: Some(a.to_string()), - to_ref: Some(b.to_string()), - include_uncommitted: false, - allow_unknown_objects: false, - merge_base: true, - } - } else { - // If only the start of the range is specified, we assume that - // we want to include uncommitted changes - GitRange { - from_ref: Some(commits_str.to_string()), - to_ref: None, - include_uncommitted: true, - allow_unknown_objects: false, - merge_base: false, - } - }; - Some(git_range) - } else { - None - }; - - Ok(TargetSelector { - git_range, - exclude, - exclude_self, - include_dependencies, - include_dependents, - match_dependencies: pre_add_dependencies, - name_pattern, - parent_dir, - raw: raw_selector.to_string(), - ..Default::default() - }) - } -} - -#[derive(Debug, Error, PartialEq)] -pub enum InvalidSelectorError { - #[error("cannot use match dependencies without specifying either a directory or package")] - CantMatchDependencies, - #[error("invalid anchored path: {0}")] - InvalidAnchoredPath(String), - #[error("empty path specification")] - EmptyPathSpecification, - #[error("invalid git range selector: {0}")] - InvalidGitRange(String), - - #[error("selector \"{0}\" must have a reference, directory, or name pattern")] - InvalidSelector(String), -} - -/// checks if the selector is a filesystem path -pub fn is_selector_by_location( - raw_selector: &str, -) -> Option> { - let exact_matches = [".", ".."]; - let prefixes = ["./", ".\\", "../", "..\\"]; - - if exact_matches.contains(&raw_selector) - || prefixes - .iter() - .any(|prefix| raw_selector.starts_with(prefix)) - { - let cleaned_selector = path_clean::clean(std::path::Path::new(raw_selector)) - .into_os_string() - .into_string() - .expect("raw selector was valid utf8"); - Some( - AnchoredSystemPathBuf::try_from(cleaned_selector.as_str()) - .map_err(|_| InvalidSelectorError::InvalidAnchoredPath(raw_selector.to_string())), - ) - } else { - None - } -} - -#[cfg(test)] -mod test { - use std::str::FromStr; - - use pretty_assertions::assert_eq; - use test_case::test_case; - use turbopath::AnchoredSystemPathBuf; - - use super::TargetSelector; - use crate::run::scope::target_selector::GitRange; - - #[test_case("foo", TargetSelector { name_pattern: "foo".to_string(), raw: "foo".to_string(), ..Default::default() }; "foo")] - #[test_case("foo...", TargetSelector { name_pattern: "foo".to_string(), raw: "foo...".to_string(), include_dependencies: true, ..Default::default() }; "foo dot dot dot")] - #[test_case("...foo", TargetSelector { name_pattern: "foo".to_string(), raw: "...foo".to_string(), include_dependents: true, ..Default::default() }; "dot dot dot foo")] - #[test_case("...foo...", TargetSelector { name_pattern: "foo".to_string(), raw: "...foo...".to_string(), include_dependents: true, include_dependencies: true, ..Default::default() }; "dot dot dot foo dot dot dot")] - #[test_case("foo^...", TargetSelector { name_pattern: "foo".to_string(), raw: "foo^...".to_string(), include_dependencies: true, exclude_self: true, ..Default::default() }; "foo caret dot dot dot")] - #[test_case("...^foo", TargetSelector { name_pattern: "foo".to_string(), raw: "...^foo".to_string(), include_dependents: true, exclude_self: true, ..Default::default() }; "dot dot dot caret foo")] - #[test_case("../foo", TargetSelector { raw: "../foo".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from(if cfg!(windows) { "..\\foo" } else { "../foo" }).unwrap()), ..Default::default() }; "dot dot slash foo")] - #[test_case("./foo", TargetSelector { raw: "./foo".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), ..Default::default() }; "dot slash foo")] - #[test_case("./foo/*", TargetSelector { raw: "./foo/*".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from(if cfg!(windows) { "foo\\*" } else { "foo/*" }).unwrap()), ..Default::default() }; "dot slash foo star")] - #[test_case("...{./foo}", TargetSelector { raw: "...{./foo}".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), include_dependents: true, ..Default::default() }; "dot dot dot curly bracket foo")] - #[test_case(".", TargetSelector { raw: ".".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from(".").unwrap()), ..Default::default() }; "parent dir dot")] - #[test_case("..", TargetSelector { raw: "..".to_string(), parent_dir: Some(AnchoredSystemPathBuf::try_from("..").unwrap()), ..Default::default() }; "parent dir dot dot")] - #[test_case("[master]", TargetSelector { raw: "[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), ..Default::default() }; "square brackets master")] - #[test_case("[from...to]", TargetSelector { raw: "[from...to]".to_string(), git_range: Some(GitRange { from_ref: Some("from".to_string()), to_ref: Some("to".to_string()), merge_base: true, ..Default::default() }), ..Default::default() }; "[from...to]")] - #[test_case("{foo}[master]", TargetSelector { raw: "{foo}[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), ..Default::default() }; "{foo}[master]")] - #[test_case("pattern{foo}[master]", TargetSelector { raw: "pattern{foo}[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), name_pattern: "pattern".to_string(), ..Default::default() }; "pattern{foo}[master]")] - #[test_case("[master]...", TargetSelector { raw: "[master]...".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), include_dependencies: true, ..Default::default() }; "square brackets master dot dot dot")] - #[test_case("...[master]", TargetSelector { raw: "...[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), include_dependents: true, ..Default::default() }; "dot dot dot master square brackets")] - #[test_case("...[master]...", TargetSelector { raw: "...[master]...".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), include_dependencies: true, include_dependents: true, ..Default::default() }; "dot dot dot master square brackets dot dot dot")] - #[test_case("...[from...to]...", TargetSelector { raw: "...[from...to]...".to_string(), git_range: Some(GitRange { from_ref: Some("from".to_string()), to_ref: Some("to".to_string()), merge_base: true, ..Default::default() }), include_dependencies: true, include_dependents: true, ..Default::default() }; "dot dot dot [from...to] dot dot dot")] - #[test_case("foo...[master]", TargetSelector { raw: "foo...[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), name_pattern: "foo".to_string(), match_dependencies: true, ..Default::default() }; "foo...[master]")] - #[test_case("foo...[master]...", TargetSelector { raw: "foo...[master]...".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), name_pattern: "foo".to_string(), match_dependencies: true, include_dependencies: true, ..Default::default() }; "foo...[master] dot dot dot")] - #[test_case("{foo}...[master]", TargetSelector { raw: "{foo}...[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), parent_dir: Some(AnchoredSystemPathBuf::try_from("foo").unwrap()), match_dependencies: true, ..Default::default() }; " curly brackets foo...[master]")] - #[test_case("...@repo/pkg[master]", TargetSelector { raw: "...@repo/pkg[master]".to_string(), git_range: Some(GitRange { from_ref: Some("master".to_string()), to_ref: None, include_uncommitted: true, ..Default::default() }), name_pattern: "@repo/pkg".to_string(), include_dependents: true, ..Default::default() }; "gh 9096")] - fn parse_target_selector(raw_selector: &str, want: TargetSelector) { - let result = TargetSelector::from_str(raw_selector); - - match result { - Ok(got) => { - assert_eq!( - got, want, - "ParseTargetSelector() = {:?}, want {:?}", - got, want - ); - } - Err(e) => { - panic!("ParseTargetSelector() error = {:?}", e) - } - } - } - - #[test_case("{}" ; "curly brackets")] - #[test_case("......[master]" ; "......[master]")] - #[test_case("[]" ; "empty git range")] - #[test_case("[...some-ref]" ; "missing git range start")] - #[test_case("[some-ref...]" ; "missing git range end")] - #[test_case("[...]" ; "missing entire git range")] - fn parse_target_selector_invalid(raw_selector: &str) { - let result = TargetSelector::from_str(raw_selector); - - match result { - Ok(_got) => { - panic!("expected error when parsing {}", raw_selector); - } - Err(e) => { - println!("{:?}", e); - } - } - } -} diff --git a/crates/turborepo-lib/src/run/summary/duration.rs b/crates/turborepo-lib/src/run/summary/duration.rs deleted file mode 100644 index 5ef6e1bc6b10f..0000000000000 --- a/crates/turborepo-lib/src/run/summary/duration.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::fmt::{self, Formatter}; - -use chrono::{DateTime, Duration, Local, SubsecRound}; - -#[derive(Debug)] -pub struct TurboDuration(Duration); - -impl TurboDuration { - pub fn new(start_time: &DateTime, end_time: &DateTime) -> Self { - TurboDuration( - end_time - .trunc_subsecs(3) - .signed_duration_since(start_time.trunc_subsecs(3)), - ) - } -} - -impl From for TurboDuration { - fn from(duration: Duration) -> Self { - Self(duration) - } -} - -impl fmt::Display for TurboDuration { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let duration = &self.0; - - // If duration is less than a second, we print milliseconds - if duration.num_seconds() <= 0 { - let milliseconds = duration.num_milliseconds() - duration.num_seconds() * 1000; - return write!(f, "{}ms", milliseconds); - } - - if duration.num_hours() > 0 { - write!(f, "{}h", duration.num_hours(),)?; - } - - if duration.num_minutes() > 0 { - let minutes = duration.num_minutes() - duration.num_hours() * 60; - write!(f, "{}m", minutes)?; - } - - if duration.num_seconds() > 0 { - let seconds_in_ms = duration.num_milliseconds() - duration.num_minutes() * 60 * 1000; - let seconds = (seconds_in_ms as f64) / 1000.0; - write!(f, "{}s", seconds)?; - } - - Ok(()) - } -} - -#[cfg(test)] -mod test { - use pretty_assertions::assert_eq; - use test_case::test_case; - - use super::*; - - #[test_case(TurboDuration::from(Duration::milliseconds(120)), "120ms")] - #[test_case(TurboDuration::from(Duration::milliseconds(1500)), "1.5s")] - #[test_case(TurboDuration::from(Duration::milliseconds(1234)), "1.234s")] - #[test_case(TurboDuration::from(Duration::seconds(90)), "1m30s")] - fn duration_formatting(duration: TurboDuration, expected: &str) { - assert_eq!(duration.to_string(), expected); - } -} diff --git a/crates/turborepo-lib/src/run/summary/execution.rs b/crates/turborepo-lib/src/run/summary/execution.rs deleted file mode 100644 index cf4c719c0fe28..0000000000000 --- a/crates/turborepo-lib/src/run/summary/execution.rs +++ /dev/null @@ -1,544 +0,0 @@ -use std::fmt; - -use chrono::{DateTime, Local}; -use serde::Serialize; -use tokio::sync::mpsc; -use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPath}; -use turborepo_ui::{color, cprintln, ColorConfig, BOLD, BOLD_GREEN, BOLD_RED, MAGENTA, YELLOW}; - -use super::TurboDuration; -use crate::run::{summary::task::TaskSummary, task_id::TaskId}; - -// Just used to make changing the type that gets passed to the state management -// thread easy -type Message = TrackerMessage; - -// Should *not* be exposed outside of run summary module -/// Spawns task trackers and records the final state of all tasks -#[derive(Debug)] -pub struct ExecutionTracker { - // this thread handles the state management - state_thread: tokio::task::JoinHandle, - sender: mpsc::Sender, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ExecutionSummary<'a> { - // a synthesized turbo command to produce this invocation - command: String, - // the (possibly empty) path from the turborepo root to where the command was run - #[serde(rename = "repoPath")] - repo_path: &'a AnchoredSystemPath, - // number of tasks that exited successfully (does not include cache hits) - success: usize, - // number of tasks that exited with failure - failed: usize, - // number of tasks that had a cache hit - cached: usize, - // number of tasks that started - attempted: usize, - pub(crate) start_time: i64, - pub(crate) end_time: i64, - #[serde(skip)] - duration: TurboDuration, - pub(crate) exit_code: i32, -} - -impl<'a> ExecutionSummary<'a> { - pub fn new( - command: String, - state: SummaryState, - package_inference_root: Option<&'a AnchoredSystemPath>, - exit_code: i32, - start_time: DateTime, - end_time: DateTime, - ) -> Self { - let duration = TurboDuration::new(&start_time, &end_time); - Self { - command, - success: state.success, - failed: state.failed, - cached: state.cached, - attempted: state.attempted, - // We're either at some path in the repo, or at the root, which is an empty path - repo_path: package_inference_root.unwrap_or_else(|| AnchoredSystemPath::empty()), - start_time: start_time.timestamp_millis(), - end_time: end_time.timestamp_millis(), - duration, - exit_code, - } - } - - /// We implement this on `ExecutionSummary` and not `RunSummary` because - /// the `execution` field is nullable (due to normalize). - pub fn print( - &self, - ui: ColorConfig, - path: AbsoluteSystemPathBuf, - failed_tasks: Vec<&TaskSummary>, - ) { - let maybe_full_turbo = if self.cached == self.attempted && self.attempted > 0 { - match std::env::var("TERM_PROGRAM").as_deref() { - Ok("Apple_Terminal") => color!(ui, MAGENTA, ">>> FULL TURBO").to_string(), - _ => ui.rainbow(">>> FULL TURBO").to_string(), - } - } else { - String::new() - }; - - let mut line_data = vec![ - ( - "Tasks", - format!( - "{}, {} total", - color!(ui, BOLD_GREEN, "{} successful", self.successful()), - self.attempted - ), - ), - ( - "Cached", - format!( - "{}, {} total", - color!(ui, BOLD, "{} cached", self.cached), - self.attempted - ) - .to_string(), - ), - ( - "Time", - format!( - "{} {}", - color!(ui, BOLD, "{}", self.duration), - maybe_full_turbo - ), - ), - ]; - - if path.exists() { - line_data.push(("Summary", path.to_string())); - } - - if !failed_tasks.is_empty() { - let mut formatted: Vec<_> = failed_tasks - .iter() - .map(|task| color!(ui, BOLD_RED, "{}", task.task_id).to_string()) - .collect(); - formatted.sort(); - line_data.push(("Failed", formatted.join(", "))); - } - - let max_length = line_data - .iter() - .map(|(header, _)| header.len()) - .max() - .unwrap_or_default(); - - let lines: Vec<_> = line_data - .into_iter() - .map(|(header, trailer)| { - color!( - ui, - BOLD, - "{}{}: {}", - " ".repeat(max_length - header.len()), - header, - trailer - ) - }) - .collect(); - - if self.attempted == 0 { - println!(); - cprintln!(ui, YELLOW, "No tasks were executed as part of this run."); - } - - println!(); - for line in lines { - println!("{}", line); - } - - println!(); - } - - fn successful(&self) -> usize { - self.success + self.cached - } -} - -/// The final states of all task executions -#[derive(Debug, Default, Clone)] -pub struct SummaryState { - pub attempted: usize, - pub failed: usize, - pub cached: usize, - pub success: usize, - pub tasks: Vec, -} - -#[derive(Debug, Clone)] -pub struct TaskState { - pub task_id: TaskId<'static>, - pub execution: Option, -} - -impl SummaryState { - fn handle_event(&mut self, event: Event) { - match event { - Event::Building => self.attempted += 1, - Event::BuildFailed => self.failed += 1, - Event::Cached => self.cached += 1, - Event::Built => self.success += 1, - Event::Canceled => (), - } - } -} - -/// A tracker constructed for each task and used to communicate task events back -/// to the execution summary. -pub struct TaskTracker { - sender: mpsc::Sender, - started_at: T, - task_id: TaskId<'static>, -} - -#[derive(Debug, Clone)] -struct TrackerMessage { - event: Event, - // Only present if task is finished - state: Option, -} - -#[derive(Debug, Clone, Copy, Serialize)] -enum Event { - Building, - BuildFailed, - Cached, - Built, - // Canceled due to external signal or internal failure - Canceled, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TaskExecutionSummary { - pub start_time: i64, - pub end_time: i64, - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, - pub exit_code: Option, -} - -impl TaskExecutionSummary { - pub fn is_failure(&self) -> bool { - // We consider None as a failure as it indicates the task failed to start - // or was killed in a manner where we didn't collect an exit code. - !matches!(self.exit_code, Some(0)) - } -} - -impl ExecutionTracker { - pub fn new() -> Self { - // This buffer size is probably overkill, but since messages are only a byte - // it's worth the extra memory to avoid the channel filling up. - let (sender, mut receiver) = mpsc::channel::(128); - let state_thread = tokio::spawn(async move { - let mut state = SummaryState::default(); - while let Some(TrackerMessage { - event, - state: task_state, - }) = receiver.recv().await - { - state.handle_event(event); - if let Some(task_state) = task_state { - state.tasks.push(task_state); - } - } - state - }); - - Self { - state_thread, - sender, - } - } - - // Produce a tracker for the task - pub fn task_tracker(&self, task_id: TaskId<'static>) -> TaskTracker<()> { - TaskTracker { - sender: self.sender.clone(), - task_id, - started_at: (), - } - } - - pub async fn finish(self) -> Result { - let Self { - state_thread, - sender, - .. - } = self; - // We drop the sender so the channel closes once all trackers have finished. - // We don't explicitly close as that would cause running trackers to be unable - // to send their execution summary. - drop(sender); - - let summary_state = state_thread.await?; - - Ok(summary_state) - } -} - -impl TaskTracker<()> { - // Start the tracker - pub async fn start(self) -> TaskTracker> { - let TaskTracker { - sender, task_id, .. - } = self; - let started_at = Local::now(); - sender - .send(TrackerMessage { - event: Event::Building, - state: None, - }) - .await - .expect("execution summary state thread finished"); - TaskTracker { - sender, - started_at, - task_id, - } - } - - // Track that the task would be executed - pub async fn dry_run(self) { - let Self { - sender, task_id, .. - } = self; - - sender - .send(TrackerMessage { - event: Event::Canceled, - state: Some(TaskState { - task_id, - execution: None, - }), - }) - .await - .expect("execution summary state thread finished") - } -} - -impl TaskTracker> { - // In the case of a task getting canceled we send no information as there was an - // internal turbo error - pub fn cancel(self) {} - - pub async fn cached(self) -> TaskExecutionSummary { - let Self { - sender, - started_at, - task_id, - } = self; - - let ended_at = Local::now(); - let execution = TaskExecutionSummary { - start_time: started_at.timestamp_millis(), - end_time: ended_at.timestamp_millis(), - // Go synthesizes a zero exit code on cache hits - exit_code: Some(0), - error: None, - }; - - let state = TaskState { - task_id, - execution: Some(execution.clone()), - }; - sender - .send(TrackerMessage { - event: Event::Cached, - state: Some(state), - }) - .await - .expect("summary state thread finished"); - execution - } - - pub async fn build_succeeded(self, exit_code: i32) -> TaskExecutionSummary { - let Self { - sender, - started_at, - task_id, - } = self; - - let ended_at = Local::now(); - let execution = TaskExecutionSummary { - start_time: started_at.timestamp_millis(), - end_time: ended_at.timestamp_millis(), - exit_code: Some(exit_code), - error: None, - }; - - let state = TaskState { - task_id, - execution: Some(execution.clone()), - }; - sender - .send(TrackerMessage { - event: Event::Built, - state: Some(state), - }) - .await - .expect("summary state thread finished"); - execution - } - - pub async fn build_failed( - self, - exit_code: Option, - error: impl fmt::Display, - ) -> TaskExecutionSummary { - let Self { - sender, - started_at, - task_id, - } = self; - - let ended_at = Local::now(); - let execution = TaskExecutionSummary { - start_time: started_at.timestamp_millis(), - end_time: ended_at.timestamp_millis(), - exit_code, - error: Some(error.to_string()), - }; - - let state = TaskState { - task_id, - execution: Some(execution.clone()), - }; - sender - .send(TrackerMessage { - event: Event::BuildFailed, - state: Some(state), - }) - .await - .expect("summary state thread finished"); - execution - } -} - -#[cfg(test)] -mod test { - use chrono::Duration; - use serde_json::json; - use test_case::test_case; - - use super::*; - - #[tokio::test] - async fn test_multiple_tasks() { - let summary = ExecutionTracker::new(); - let foo = TaskId::new("foo", "build"); - let bar = TaskId::new("bar", "build"); - let baz = TaskId::new("baz", "build"); - let boo = TaskId::new("boo", "build"); - let mut tasks = Vec::new(); - { - let tracker = summary.task_tracker(foo.clone()); - tasks.push(tokio::spawn(async move { - let tracker = tracker.start().await; - tracker.build_succeeded(0).await; - })); - } - { - let tracker = summary.task_tracker(bar.clone()); - tasks.push(tokio::spawn(async move { - let tracker = tracker.start().await; - tracker.cached().await; - })); - } - { - let tracker = summary.task_tracker(baz.clone()); - tasks.push(tokio::spawn(async move { - let tracker = tracker.start().await; - tracker.build_failed(Some(1), "big bad error").await; - })); - } - { - let tracker = summary.task_tracker(boo.clone()); - tasks.push(tokio::spawn(async move { - let tracker = tracker.start().await; - tracker.cancel(); - })); - } - for task in tasks { - task.await.unwrap(); - } - - let state = summary.finish().await.unwrap(); - assert_eq!(state.attempted, 4); - assert_eq!(state.cached, 1); - assert_eq!(state.failed, 1); - assert_eq!(state.success, 1); - let foo_state = state.tasks.iter().find(|task| task.task_id == foo).unwrap(); - assert_eq!(foo_state.execution.as_ref().unwrap().exit_code, Some(0)); - let bar_state = state.tasks.iter().find(|task| task.task_id == bar).unwrap(); - assert_eq!(bar_state.execution.as_ref().unwrap().exit_code, Some(0)); - let baz_state = state.tasks.iter().find(|task| task.task_id == baz).unwrap(); - assert_eq!(baz_state.execution.as_ref().unwrap().exit_code, Some(1)); - let boo_state = state.tasks.iter().find(|task| task.task_id == boo); - assert!( - boo_state.is_none(), - "canceling doesn't produce execution data" - ); - } - - #[tokio::test] - async fn test_timing() { - let summary = ExecutionTracker::new(); - let tracker = summary.task_tracker(TaskId::new("foo", "build")); - let post_construction_time = Local::now().timestamp_millis(); - let sleep_duration = Duration::milliseconds(5); - tokio::time::sleep(sleep_duration.to_std().unwrap()).await; - - let tracker = tracker.start().await; - - tokio::time::sleep(sleep_duration.to_std().unwrap()).await; - tracker.build_succeeded(0).await; - let mut state = summary.finish().await.unwrap(); - assert_eq!(state.tasks.len(), 1); - let summary = state.tasks.pop().unwrap().execution.unwrap(); - assert!( - post_construction_time < summary.start_time, - "tracker start time should start when start is called" - ); - assert!( - summary.start_time + sleep_duration.num_milliseconds() <= summary.end_time, - "tracker end should be at least as long as the time between calls" - ); - } - - #[test_case( - TaskExecutionSummary { - start_time: 123, - end_time: 234, - exit_code: Some(0), - error: None - }, - json!({ "startTime": 123, "endTime": 234, "exitCode": 0 }) - ; "success" - )] - #[test_case( - TaskExecutionSummary { - start_time: 123, - end_time: 234, - exit_code: Some(1), - error: Some("cannot find anything".into()), - }, - json!({ "startTime": 123, "endTime": 234, "exitCode": 1, "error": "cannot find anything" }) - ; "failure" - )] - fn test_serialization(value: impl serde::Serialize, expected: serde_json::Value) { - assert_eq!(serde_json::to_value(value).unwrap(), expected); - } -} diff --git a/crates/turborepo-lib/src/run/summary/global_hash.rs b/crates/turborepo-lib/src/run/summary/global_hash.rs deleted file mode 100644 index 3f693308ae890..0000000000000 --- a/crates/turborepo-lib/src/run/summary/global_hash.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::collections::BTreeMap; - -use serde::Serialize; -use turbopath::RelativeUnixPathBuf; -use turborepo_env::EnvironmentVariablePairs; - -use crate::run::{global_hash::GlobalHashableInputs, summary::Error}; - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -// Contains the environment variable inputs for the global hash -pub struct GlobalEnvConfiguration<'a> { - pub env: &'a [String], - pub pass_through_env: Option<&'a [String]>, -} - -// Contains the environment variables that impacted the global hash -#[derive(Debug, Serialize)] -pub struct GlobalEnvVarSummary<'a> { - pub specified: GlobalEnvConfiguration<'a>, - - pub configured: Option, - pub inferred: Option, - #[serde(rename = "passthrough")] - pub pass_through: Option, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct GlobalHashSummary<'a> { - pub root_key: &'static str, - pub files: BTreeMap, - pub hash_of_external_dependencies: &'a str, - pub hash_of_internal_dependencies: &'a str, - pub environment_variables: GlobalEnvVarSummary<'a>, - pub engines: Option>, -} - -impl<'a> TryFrom> for GlobalHashSummary<'a> { - type Error = Error; - #[allow(clippy::too_many_arguments)] - fn try_from(global_hashable_inputs: GlobalHashableInputs<'a>) -> Result { - let GlobalHashableInputs { - global_cache_key, - global_file_hash_map, - root_external_dependencies_hash, - root_internal_dependencies_hash, - env, - resolved_env_vars, - pass_through_env, - env_at_execution_start, - engines, - .. - } = global_hashable_inputs; - - let pass_through = pass_through_env - .map( - |pass_through_env| -> Result { - Ok(env_at_execution_start - .from_wildcards(pass_through_env) - .map_err(Error::Env)? - .to_secret_hashable()) - }, - ) - .transpose()?; - - let engines = engines.map(|engines| engines.into_iter().collect()); - - Ok(Self { - root_key: global_cache_key, - files: global_file_hash_map.into_iter().collect(), - // This can be empty in single package mode - hash_of_external_dependencies: root_external_dependencies_hash.unwrap_or_default(), - hash_of_internal_dependencies: root_internal_dependencies_hash.unwrap_or_default(), - environment_variables: GlobalEnvVarSummary { - specified: GlobalEnvConfiguration { - env, - pass_through_env, - }, - configured: resolved_env_vars - .as_ref() - .map(|vars| vars.by_source.explicit.to_secret_hashable()), - inferred: resolved_env_vars - .as_ref() - .map(|vars| vars.by_source.matching.to_secret_hashable()), - pass_through, - }, - engines, - }) - } -} diff --git a/crates/turborepo-lib/src/run/summary/scm.rs b/crates/turborepo-lib/src/run/summary/scm.rs deleted file mode 100644 index a546b8c8063c2..0000000000000 --- a/crates/turborepo-lib/src/run/summary/scm.rs +++ /dev/null @@ -1,53 +0,0 @@ -use serde::{Deserialize, Serialize}; -use turbopath::AbsoluteSystemPath; -use turborepo_ci::Vendor; -use turborepo_env::EnvironmentVariableMap; -use turborepo_scm::SCM; - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "lowercase")] -enum SCMType { - Git, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub(crate) struct SCMState { - #[serde(rename = "type")] - ty: SCMType, - pub(crate) sha: Option, - pub(crate) branch: Option, -} - -impl SCMState { - pub fn get(env_vars: &EnvironmentVariableMap, scm: &SCM, dir: &AbsoluteSystemPath) -> Self { - let mut state = SCMState { - ty: SCMType::Git, - sha: None, - branch: None, - }; - - if turborepo_ci::is_ci() { - if let Some(vendor) = Vendor::infer() { - if let Some(sha_env_var) = vendor.sha_env_var { - state.sha = env_vars.get(sha_env_var).cloned() - } - - if let Some(branch_env_var) = vendor.branch_env_var { - state.branch = env_vars.get(branch_env_var).cloned() - } - } - } - - // Fall back to using `git` - if state.branch.is_none() && state.sha.is_none() { - if state.branch.is_none() { - state.branch = scm.get_current_branch(dir).ok(); - } - if state.sha.is_none() { - state.sha = scm.get_current_sha(dir).ok(); - } - } - - state - } -} diff --git a/crates/turborepo-lib/src/run/summary/task.rs b/crates/turborepo-lib/src/run/summary/task.rs deleted file mode 100644 index 145f4c0a4217a..0000000000000 --- a/crates/turborepo-lib/src/run/summary/task.rs +++ /dev/null @@ -1,389 +0,0 @@ -use std::collections::BTreeMap; - -use serde::Serialize; -use turbopath::{AnchoredSystemPathBuf, RelativeUnixPathBuf}; -use turborepo_cache::CacheHitMetadata; -use turborepo_env::{DetailedMap, EnvironmentVariableMap}; - -use super::{execution::TaskExecutionSummary, EnvMode}; -use crate::{ - cli::OutputLogsMode, - run::task_id::TaskId, - task_graph::{TaskDefinition, TaskOutputs}, -}; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TaskCacheSummary { - // Deprecated, but keeping around for --dry=json - pub local: bool, - // Deprecated, but keeping around for --dry=json - pub remote: bool, - status: CacheStatus, - // Present unless a cache miss - #[serde(skip_serializing_if = "Option::is_none")] - source: Option, - // 0 if a cache miss - time_saved: u64, -} - -#[derive(Debug, Serialize, Copy, Clone)] -#[serde(rename_all = "UPPERCASE")] -enum CacheStatus { - Hit, - Miss, -} - -#[derive(Debug, Serialize, Copy, Clone)] -#[serde(rename_all = "UPPERCASE")] -enum CacheSource { - Local, - Remote, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub(crate) struct TaskSummary { - pub task_id: TaskId<'static>, - pub task: String, - pub package: String, - #[serde(flatten)] - pub shared: SharedTaskSummary>, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub(crate) struct SinglePackageTaskSummary { - pub task_id: String, - pub task: String, - #[serde(flatten)] - pub shared: SharedTaskSummary, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub(crate) struct SharedTaskSummary { - pub hash: String, - pub inputs: BTreeMap, - pub hash_of_external_dependencies: String, - pub cache: TaskCacheSummary, - pub command: String, - pub cli_arguments: Vec, - pub outputs: Option>, - pub excluded_outputs: Option>, - pub log_file: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub directory: Option, - pub dependencies: Vec, - pub dependents: Vec, - pub resolved_task_definition: TaskSummaryTaskDefinition, - pub expanded_outputs: Vec, - pub framework: String, - pub env_mode: EnvMode, - pub environment_variables: TaskEnvVarSummary, - #[serde(skip_serializing_if = "Option::is_none")] - pub execution: Option, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TaskEnvConfiguration { - pub env: Vec, - pub pass_through_env: Option>, -} - -#[derive(Debug, Serialize, Clone, Default)] -#[serde(rename_all = "camelCase")] -pub struct TaskSummaryTaskDefinition { - outputs: Vec, - cache: bool, - depends_on: Vec, - inputs: Vec, - output_logs: OutputLogsMode, - persistent: bool, - interruptible: bool, - env: Vec, - pass_through_env: Option>, - interactive: bool, - #[serde(skip_serializing_if = "Option::is_none")] - env_mode: Option, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TaskEnvVarSummary { - pub specified: TaskEnvConfiguration, - pub configured: Vec, - pub inferred: Vec, - #[serde(rename = "passthrough")] - pub pass_through: Option>, -} - -impl TaskCacheSummary { - pub fn cache_miss() -> Self { - Self { - local: false, - remote: false, - status: CacheStatus::Miss, - time_saved: 0, - source: None, - } - } -} - -impl From> for TaskCacheSummary { - fn from(response: Option) -> Self { - match response { - Some(CacheHitMetadata { source, time_saved }) => { - let source = CacheSource::from(source); - // Assign these deprecated fields Local and Remote based on the information - // available in the itemStatus. Note that these fields are - // problematic, because an ItemStatus isn't always the composite - // of both local and remote caches. That means that an ItemStatus might say it - // was a local cache hit, and we return remote: false here. That's misleading - // because it does not mean that there is no remote cache hit, - // it _could_ mean that we never checked the remote cache. These - // fields are being deprecated for this reason. - let (local, remote) = match source { - CacheSource::Local => (true, false), - CacheSource::Remote => (false, true), - }; - Self { - local, - remote, - status: CacheStatus::Hit, - source: Some(source), - time_saved, - } - } - None => Self::cache_miss(), - } - } -} - -impl From for CacheSource { - fn from(value: turborepo_cache::CacheSource) -> Self { - match value { - turborepo_cache::CacheSource::Local => Self::Local, - turborepo_cache::CacheSource::Remote => Self::Remote, - } - } -} - -impl TaskEnvVarSummary { - pub fn new( - task_definition: &TaskDefinition, - env_vars: DetailedMap, - env_at_execution_start: &EnvironmentVariableMap, - ) -> Result { - // TODO: this operation differs from the actual env that gets passed in during - // task execution it should be unified, but first we should copy Go's - // behavior as we try to match the implementations - let pass_through = task_definition - .pass_through_env - .as_deref() - .map(|pass_through_env| -> Result<_, turborepo_env::Error> { - Ok(env_at_execution_start - .from_wildcards(pass_through_env)? - .to_secret_hashable()) - }) - .transpose()?; - - Ok(Self { - specified: TaskEnvConfiguration { - env: task_definition.env.clone(), - pass_through_env: task_definition.pass_through_env.clone(), - }, - configured: env_vars.by_source.explicit.to_secret_hashable(), - inferred: env_vars.by_source.matching.to_secret_hashable(), - pass_through, - }) - } -} - -impl From for SinglePackageTaskSummary { - fn from(value: TaskSummary) -> Self { - let TaskSummary { - task_id, shared, .. - } = value; - Self { - task_id: task_id.task().to_string(), - task: task_id.task().to_string(), - shared: shared.into(), - } - } -} - -impl From>> for SharedTaskSummary { - fn from(value: SharedTaskSummary>) -> Self { - let SharedTaskSummary { - hash, - inputs, - hash_of_external_dependencies, - cache, - command, - cli_arguments, - outputs, - excluded_outputs, - log_file, - expanded_outputs, - dependencies, - dependents, - resolved_task_definition, - framework, - execution, - env_mode, - environment_variables, - .. - } = value; - Self { - hash, - inputs, - hash_of_external_dependencies, - cache, - command, - cli_arguments, - outputs, - excluded_outputs, - log_file, - directory: None, - expanded_outputs, - dependencies: dependencies - .into_iter() - .map(|task_id| task_id.task().to_string()) - .collect(), - dependents: dependents - .into_iter() - .map(|task_id| task_id.task().to_string()) - .collect(), - resolved_task_definition, - framework, - execution, - env_mode, - environment_variables, - } - } -} - -impl From for TaskSummaryTaskDefinition { - fn from(value: TaskDefinition) -> Self { - let TaskDefinition { - outputs: - TaskOutputs { - inclusions, - exclusions, - }, - cache, - mut env, - pass_through_env, - topological_dependencies, - task_dependencies, - mut inputs, - output_logs, - persistent, - interruptible, - interactive, - env_mode, - siblings: _, - } = value; - - let mut outputs = inclusions; - for exclusion in exclusions { - outputs.push(format!("!{exclusion}")); - } - - let mut depends_on = - Vec::with_capacity(task_dependencies.len() + topological_dependencies.len()); - for task_dependency in task_dependencies { - depends_on.push(task_dependency.to_string()); - } - for topological_dependency in topological_dependencies { - depends_on.push(format!("^{}", topological_dependency.as_inner())); - } - - // These _should_ already be sorted when the TaskDefinition struct was - // unmarshaled, but we want to ensure they're sorted on the way out - // also, just in case something in the middle mutates the items. - depends_on.sort(); - outputs.sort(); - env.sort(); - inputs.sort(); - - Self { - outputs, - cache, - depends_on, - inputs, - output_logs, - persistent, - interruptible, - interactive, - env, - pass_through_env, - env_mode, - } - } -} - -#[cfg(test)] -mod test { - use serde_json::json; - use test_case::test_case; - - use super::*; - - #[test_case(CacheStatus::Hit, json!("HIT") ; "hit")] - #[test_case(CacheStatus::Miss, json!("MISS") ; "miss")] - #[test_case(CacheSource::Local, json!("LOCAL") ; "local")] - #[test_case(CacheSource::Remote, json!("REMOTE") ; "remote")] - #[test_case( - TaskCacheSummary::cache_miss(), - serde_json::json!({ - "local": false, - "remote": false, - "status": "MISS", - "timeSaved": 0, - }) - ; "cache miss" - )] - #[test_case( - TaskCacheSummary { - local: true, - remote: false, - status: CacheStatus::Hit, - source: Some(CacheSource::Local), - time_saved: 6, - }, - serde_json::json!({ - "local": true, - "remote": false, - "status": "HIT", - "source": "LOCAL", - "timeSaved": 6, - }) - ; "local cache hit" - )] - #[test_case( - TaskSummaryTaskDefinition { - outputs: vec!["foo".into()], - cache: true, - ..Default::default() - }, - json!({ - "outputs": ["foo"], - "cache": true, - "dependsOn": [], - "inputs": [], - "outputLogs": "full", - "persistent": false, - "interruptible": false, - "interactive": false, - "env": [], - "passThroughEnv": null, - }) - ; "resolved task definition" - )] - fn test_serialization(value: impl serde::Serialize, expected: serde_json::Value) { - assert_eq!(serde_json::to_value(value).unwrap(), expected); - } -} diff --git a/crates/turborepo-lib/src/run/task_access.rs b/crates/turborepo-lib/src/run/task_access.rs deleted file mode 100644 index c6fc7798e3275..0000000000000 --- a/crates/turborepo-lib/src/run/task_access.rs +++ /dev/null @@ -1,270 +0,0 @@ -use std::{ - collections::HashMap, - fs::{self, File}, - io::Write, - sync::{Arc, Mutex}, -}; - -use serde::Deserialize; -use tracing::{debug, error, warn}; -use turbopath::{AbsoluteSystemPathBuf, PathRelation}; -use turborepo_cache::AsyncCache; -use turborepo_scm::SCM; -use turborepo_unescape::UnescapedString; - -use super::ConfigCache; -use crate::{config::RawTurboJson, gitignore::ensure_turbo_is_gitignored}; - -// Environment variable key that will be used to enable, and set the expected -// trace location -const TASK_ACCESS_ENV_KEY: &str = "TURBOREPO_TRACE_FILE"; -/// File name where the task is expected to leave a trace result -const TASK_ACCESS_TRACE_NAME: &str = "trace.json"; -// Path to the config file that will be used to store the trace results -pub const TASK_ACCESS_CONFIG_PATH: [&str; 2] = [".turbo", "traced-config.json"]; -/// File name where the task is expected to leave a trace result -const TURBO_CONFIG_FILE: &str = "turbo.json"; - -#[derive(Debug, thiserror::Error)] -pub enum ToFileError { - #[error("Unable to serialize traced config: {0}")] - Serialize(#[from] serde_json::Error), - #[error("Unable to write traced config: {0}")] - IO(#[from] std::io::Error), - #[error("Unable to cache traced config: {0}")] - Cache(#[from] turborepo_cache::CacheError), -} - -#[derive(Debug, Deserialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TaskAccessTraceAccess { - pub network: bool, - pub file_paths: Vec, - pub env_var_keys: Vec, -} - -#[derive(Debug, Deserialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TaskAccessTraceFile { - pub accessed: TaskAccessTraceAccess, - pub outputs: Vec, -} - -#[derive(Deserialize, Debug)] -struct PackageJson { - scripts: Option>, -} - -pub fn trace_file_path( - repo_root: &AbsoluteSystemPathBuf, - task_hash: &str, -) -> AbsoluteSystemPathBuf { - repo_root.join_components(&[".turbo", task_hash, TASK_ACCESS_TRACE_NAME]) -} - -fn task_access_trace_enabled(repo_root: &AbsoluteSystemPathBuf) -> Result { - // TODO: use the existing config methods here - let root_turbo_json_path = &repo_root.join_component(TURBO_CONFIG_FILE); - if root_turbo_json_path.exists() { - return Ok(false); - } - - // read package.json at root - let package_json_path = repo_root.join_components(&["package.json"]); - let package_json_content = fs::read_to_string(package_json_path)?; - let package: PackageJson = serde_json::from_str(&package_json_content)?; - - if let Some(scripts) = package.scripts { - return match scripts.get("build") { - Some(script) => Ok(script == "next build"), - _ => Ok(false), - }; - } - - Ok(false) -} - -impl TaskAccessTraceFile { - pub fn read(repo_root: &AbsoluteSystemPathBuf, task_hash: &str) -> Option { - let trace_file = trace_file_path(repo_root, task_hash); - - let Ok(f) = trace_file.open() else { - return None; - }; - - match serde_json::from_reader(f) { - Ok(trace) => Some(trace), - Err(e) => { - warn!("failed to parse trace file {trace_file}: {e}"); - None - } - } - } - - pub fn can_cache(&self, repo_root: &AbsoluteSystemPathBuf) -> bool { - // network - if self.accessed.network { - warn!( - "skipping automatic task caching - detected network - access", - ); - return false; - } - - // file system - for unescaped_str in &self.accessed.file_paths { - match AbsoluteSystemPathBuf::new(unescaped_str.to_string()) { - Ok(path) => { - let relation = path.relation_to_path(repo_root); - // only paths within the repo can be automatically cached - if relation == PathRelation::Parent || relation == PathRelation::Divergent { - warn!( - "skipping automatic task caching - file accessed outside of repo root \ - ({})", - unescaped_str - ); - return false; - } - } - Err(e) => { - debug!("failed to parse path {unescaped_str}: {e}"); - } - } - } - - true - } -} - -#[derive(Clone)] -pub struct TaskAccess { - repo_root: AbsoluteSystemPathBuf, - trace_by_task: Arc>>, - config_cache: Option, - enabled: bool, -} - -impl TaskAccess { - pub fn new(repo_root: AbsoluteSystemPathBuf, cache: AsyncCache, scm: &SCM) -> Self { - let root = repo_root.clone(); - let enabled = task_access_trace_enabled(&root).unwrap_or(false); - let trace_by_task = Arc::new(Mutex::new(HashMap::::new())); - let mut config_cache = Option::::None; - - // we only want to setup the config cacher if task access tracing is enabled - if enabled { - // make sure .turbo is ignored - match ensure_turbo_is_gitignored(&repo_root) { - Ok(_) => debug!("Automatically added .turbo to .gitignore"), - Err(e) => { - error!("Failed to add .turbo to .gitignore. Caching will be disabled - {e}") - } - } - - let config_hash_result = ConfigCache::calculate_config_hash(scm, &root); - if let Ok(c_hash) = config_hash_result { - let c_cache = ConfigCache::new( - c_hash.to_string(), - root.clone(), - &TASK_ACCESS_CONFIG_PATH, - cache.clone(), - ); - - config_cache = Some(c_cache); - } - } - - Self { - repo_root, - trace_by_task, - enabled, - config_cache, - } - } - - pub fn is_enabled(&self) -> bool { - self.enabled - } - - pub async fn restore_config(&self) { - match (self.enabled, &self.config_cache) { - (true, Some(config_cache)) => match config_cache.restore().await { - Ok(_) => debug!( - "TASK ACCESS TRACE: config restored for {}", - config_cache.hash() - ), - Err(_) => debug!( - "TASK ACCESS TRACE: no config found for {}", - config_cache.hash() - ), - }, - _ => { - debug!("TASK ACCESS TRACE: unable to restore config from cache"); - } - } - } - - pub fn save_trace(&self, task_id: String, trace: TaskAccessTraceFile) { - let trace_by_task = self.trace_by_task.lock(); - match trace_by_task { - Ok(mut trace_by_task) => { - trace_by_task.insert(task_id, trace); - } - Err(e) => { - error!("Failed to save trace result - {e}"); - } - } - } - - pub fn get_env_var(&self, task_hash: &str) -> (String, AbsoluteSystemPathBuf) { - let trace_file_path = trace_file_path(&self.repo_root, task_hash); - (TASK_ACCESS_ENV_KEY.to_string(), trace_file_path) - } - - pub async fn save(&self) { - match self.to_file().await { - Ok(_) => (), - Err(e) => { - error!("Failed to write task access trace file - {e}"); - } - } - } - - // Whether we can cache the given task, returning None if task access isn't - // enabled or the trace can't be found - pub fn can_cache(&self, task_hash: &str, task_id: &str) -> Option { - if !self.is_enabled() { - return None; - } - let trace = TaskAccessTraceFile::read(&self.repo_root, task_hash)?; - if trace.can_cache(&self.repo_root) { - self.save_trace(task_id.to_string(), trace); - Some(true) - } else { - Some(false) - } - } - - async fn to_file(&self) -> Result<(), ToFileError> { - // if task access tracing is not enabled, we don't need to do anything - if !self.is_enabled() { - return Ok(()); - } - - if let Some(config_cache) = &self.config_cache { - let traced_config = - RawTurboJson::from_task_access_trace(&self.trace_by_task.lock().unwrap()); - if traced_config.is_some() { - // convert the traced_config to json and write the file to disk - let traced_config_json = serde_json::to_string_pretty(&traced_config)?; - let file_path = self.repo_root.join_components(&TASK_ACCESS_CONFIG_PATH); - let mut file = File::create(file_path)?; - write!(file, "{}", traced_config_json)?; - file.flush()?; - config_cache.save().await?; - } - } - - Ok(()) - } -} diff --git a/crates/turborepo-lib/src/run/task_id.rs b/crates/turborepo-lib/src/run/task_id.rs deleted file mode 100644 index 331724c296665..0000000000000 --- a/crates/turborepo-lib/src/run/task_id.rs +++ /dev/null @@ -1,304 +0,0 @@ -use std::{ - borrow::{Borrow, Cow}, - fmt, -}; - -use serde::{Deserialize, Serialize}; -use turborepo_repository::package_graph::{PackageName, ROOT_PKG_NAME}; - -pub const TASK_DELIMITER: &str = "#"; - -/// A task identifier as it will appear in the task graph -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize)] -#[serde(from = "String", into = "String")] -pub struct TaskId<'a> { - package: Cow<'a, str>, - task: Cow<'a, str>, -} - -/// A task name as it appears in a `turbo.json` it might be for all -/// workspaces or just one. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash)] -#[serde(try_from = "String", into = "String")] -pub struct TaskName<'a> { - package: Option>, - task: Cow<'a, str>, -} - -impl<'a> From> for TaskName<'a> { - fn from(value: TaskId<'a>) -> Self { - let TaskId { package, task } = value; - TaskName { - package: Some(package), - task, - } - } -} - -#[derive(Debug, thiserror::Error)] -#[error("No workspace found in task id '{input}'")] -pub struct TaskIdError<'a> { - input: &'a str, -} - -impl<'a> fmt::Display for TaskId<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!( - "{}{TASK_DELIMITER}{}", - self.package, self.task - )) - } -} - -impl<'a> From> for String { - fn from(value: TaskId<'a>) -> Self { - value.to_string() - } -} - -impl TaskId<'static> { - pub fn from_static(package: String, task: String) -> Self { - TaskId { - package: package.into(), - task: task.into(), - } - } -} - -impl<'a> TaskId<'a> { - pub fn new(package: &'a str, task: &'a str) -> Self { - TaskId::try_from(task).unwrap_or_else(|_| Self { - package: package.into(), - task: task.into(), - }) - } - - pub fn from_graph(workspace: &PackageName, task_name: &TaskName) -> TaskId<'static> { - task_name.task_id().map_or_else( - || { - let package = match workspace { - PackageName::Root => ROOT_PKG_NAME.into(), - PackageName::Other(workspace) => static_cow(workspace.as_str().into()), - }; - TaskId { - package, - task: static_cow(task_name.task().into()), - } - }, - |id| id.into_owned(), - ) - } - - pub fn package(&self) -> &str { - &self.package - } - - pub fn to_workspace_name(&self) -> PackageName { - match self.package.as_ref() { - ROOT_PKG_NAME => PackageName::Root, - package => PackageName::Other(package.into()), - } - } - - pub fn task(&self) -> &str { - &self.task - } - - pub fn as_non_workspace_task_name(&self) -> TaskName { - let task: &str = &self.task; - TaskName { - package: None, - task: task.into(), - } - } - - pub fn as_task_name(&self) -> TaskName { - let package: &str = &self.package; - let task: &str = &self.task; - TaskName { - package: Some(package.into()), - task: task.into(), - } - } - - pub fn into_owned(self) -> TaskId<'static> { - let TaskId { package, task } = self; - TaskId { - package: static_cow(package), - task: static_cow(task), - } - } - - /// Borrows a TaskId reference as a TaskId - pub fn as_borrowed(&self) -> TaskId { - let TaskId { package, task } = self; - let package = shorten_cow(package); - let task = shorten_cow(task); - TaskId { package, task } - } -} - -impl<'a> TryFrom<&'a str> for TaskId<'a> { - type Error = TaskIdError<'a>; - - fn try_from(value: &'a str) -> Result { - // We use split once here as the Go code will fail to find any task - // name that contains a '#' in the task graph. - // e.g. workspace#test#check can't run as we'll look for test and - // attempt to run test instead of test#check - match value.split_once(TASK_DELIMITER) { - None | Some(("", _)) => Err(TaskIdError { input: value }), - Some((package, task)) => Ok(TaskId { - package: package.into(), - task: task.into(), - }), - } - } -} - -impl<'a> From<&'a str> for TaskName<'a> { - fn from(value: &'a str) -> Self { - match value.split_once(TASK_DELIMITER) { - // Note we allow empty workspaces - // In the future we shouldn't allow this and throw when we encounter them - Some((package, task)) => Self { - package: Some(package.into()), - task: task.into(), - }, - None => Self { - package: None, - task: value.into(), - }, - } - } -} - -// Utility method changing the lifetime of an owned cow to reflect that it is -// owned -fn static_cow<'a, T: 'a + ToOwned + ?Sized>(cow: Cow<'a, T>) -> Cow<'static, T> { - match cow { - Cow::Borrowed(x) => Cow::Owned(x.to_owned()), - Cow::Owned(x) => Cow::Owned(x), - } -} - -// Utility method for changing &'a Cow<'b, T> to Cow<'a, T> -// 'b must outlive 'a -#[allow(clippy::ptr_arg)] -fn shorten_cow<'a, 'b: 'a, T: ToOwned + ?Sized>(cow: &'a Cow<'b, T>) -> Cow<'a, T> { - match cow { - Cow::Borrowed(x) => Cow::Borrowed(x), - Cow::Owned(x) => Cow::Borrowed(x.borrow()), - } -} - -impl From for TaskName<'static> { - fn from(value: String) -> Self { - let str = value.as_str(); - let TaskName { package, task } = TaskName::from(str); - let package = package.map(static_cow); - let task = static_cow(task); - Self { package, task } - } -} - -impl<'a> fmt::Display for TaskName<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.package { - Some(package) => f.write_fmt(format_args!("{package}{TASK_DELIMITER}{}", self.task)), - None => f.write_str(&self.task), - } - } -} - -impl<'a> From> for String { - fn from(value: TaskName<'a>) -> Self { - value.to_string() - } -} - -impl<'a> TaskName<'a> { - pub fn package(&self) -> Option<&str> { - let package: &str = self.package.as_ref()?; - Some(package) - } - - pub fn task(&self) -> &str { - &self.task - } - - pub fn into_non_workspace_task(self) -> Self { - let Self { task, .. } = self; - Self { - package: None, - task, - } - } - - // Makes a task a root workspace task - // e.g. build to //#build - pub fn into_root_task(self) -> TaskName<'static> { - let Self { task, .. } = self; - TaskName { - package: Some(ROOT_PKG_NAME.into()), - task: static_cow(task), - } - } - - pub fn task_id(&self) -> Option> { - let package: &str = self.package.as_deref()?; - let task: &str = &self.task; - Some(TaskId { - package: package.into(), - task: task.into(), - }) - } - - pub fn is_package_task(&self) -> bool { - self.package.is_some() - } - - pub fn in_workspace(&self, workspace: &str) -> bool { - self.task_id() - .map_or(true, |task_id| task_id.package() == workspace) - } - - pub fn into_owned(self) -> TaskName<'static> { - let TaskName { package, task } = self; - TaskName { - package: package.map(static_cow), - task: static_cow(task), - } - } -} - -#[cfg(test)] -mod test { - use test_case::test_case; - - use super::*; - - #[test_case("foo#build" ; "workspace task")] - #[test_case("//#root" ; "root task")] - #[test_case("@scope/foo#build" ; "workspace with scope")] - fn test_roundtrip(input: &str) { - assert_eq!(input, TaskId::try_from(input).unwrap().to_string()); - } - - #[test_case("foo", "build", "foo#build" ; "normal task")] - #[test_case("foo", "bar#build", "bar#build" ; "workspace specific task")] - #[test_case("foo", "//#build", "//#build" ; "root task")] - fn test_new_task_id(package_name: &str, task_name: &str, expected: &str) { - let expected = TaskId::try_from(expected).unwrap(); - let actual = TaskId::new(package_name, task_name); - assert_eq!(actual, expected); - } - - #[test_case("build" ; "global task")] - #[test_case("foo#build" ; "workspace task")] - #[test_case("//#build" ; "root task")] - #[test_case("#build" ; "empty workspace")] - fn test_task_name_roundtrip(input: &str) { - assert_eq!(input, TaskName::from(input).to_string()); - } -} diff --git a/crates/turborepo-lib/src/run/ui.rs b/crates/turborepo-lib/src/run/ui.rs deleted file mode 100644 index c998aa7e5fa6f..0000000000000 --- a/crates/turborepo-lib/src/run/ui.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::sync::Arc; - -use turborepo_ui::wui::{event::WebUIEvent, query::SharedState}; - -use crate::{query, run::Run}; - -pub async fn start_web_ui_server( - rx: tokio::sync::mpsc::UnboundedReceiver, - run: Arc, -) -> Result<(), turborepo_ui::Error> { - let state = SharedState::default(); - let subscriber = turborepo_ui::wui::subscriber::Subscriber::new(rx); - tokio::spawn(subscriber.watch(state.clone())); - - query::run_server(Some(state.clone()), run).await?; - - Ok(()) -} diff --git a/crates/turborepo-lib/src/shim/local_turbo_config.rs b/crates/turborepo-lib/src/shim/local_turbo_config.rs deleted file mode 100644 index 04764b2f3b5ef..0000000000000 --- a/crates/turborepo-lib/src/shim/local_turbo_config.rs +++ /dev/null @@ -1,214 +0,0 @@ -use std::env; - -use tracing::debug; -use turborepo_repository::{inference::RepoState, package_manager::PackageManager}; - -const TURBO_DOWNLOAD_LOCAL_ENABLED: &str = "TURBO_DOWNLOAD_LOCAL_ENABLED"; - -/// Struct containing information about the desired local turbo version -/// according to lockfiles, package.jsons, and if all else fails turbo.json -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct LocalTurboConfig { - turbo_version: String, -} - -fn is_env_var_truthy(env_var: &str) -> Option { - let value = env::var(env_var).ok()?; - match value.as_str() { - "1" | "true" => Some(true), - "0" | "false" => Some(false), - _ => None, - } -} - -impl LocalTurboConfig { - pub fn infer(repo_state: &RepoState) -> Option { - Self::infer_internal(repo_state, is_env_var_truthy(TURBO_DOWNLOAD_LOCAL_ENABLED)) - } - - // Used for testing when we want to manually set the controlling env var - fn infer_internal(repo_state: &RepoState, is_enabled: Option) -> Option { - // TODO: once we have properly communicated this functionality we should make - // this opt-out. - if !is_enabled.unwrap_or(false) { - debug!("downloading correct local version not enabled"); - return None; - } - let turbo_version = Self::turbo_version_from_lockfile(repo_state)?; - Some(Self { turbo_version }) - } - - pub fn turbo_version(&self) -> &str { - &self.turbo_version - } - - fn turbo_version_from_lockfile(repo_state: &RepoState) -> Option { - if let Ok(package_manager) = &repo_state.package_manager { - let lockfile = package_manager - .read_lockfile(&repo_state.root, &repo_state.root_package_json) - .ok()?; - return lockfile.turbo_version(); - } - - // If there isn't a package manager, just try to parse all known lockfiles - // This isn't the most efficient, but since we'll be hitting network to download - // the correct binary the unnecessary file reads aren't costly relative to the - // download. - PackageManager::supported_managers().iter().find_map(|pm| { - let lockfile = pm - .read_lockfile(&repo_state.root, &repo_state.root_package_json) - .ok()?; - lockfile.turbo_version() - }) - } -} - -#[cfg(test)] -mod test { - use tempfile::TempDir; - use turbopath::AbsoluteSystemPath; - use turborepo_repository::{ - inference::RepoMode, package_json::PackageJson, package_manager::Error, - }; - - use super::*; - - #[test] - fn test_package_manager_and_lockfile() { - let tmpdir = TempDir::with_prefix("local_config").unwrap(); - let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); - let repo = RepoState { - root: root.to_owned(), - mode: RepoMode::MultiPackage, - root_package_json: PackageJson::default(), - package_manager: Ok(PackageManager::Npm), - }; - let lockfile = root.join_component("package-lock.json"); - lockfile - .create_with_contents(include_bytes!( - "../../fixtures/local_config/turbov2.package-lock.json" - )) - .unwrap(); - - assert_eq!( - LocalTurboConfig::infer_internal(&repo, Some(true)), - Some(LocalTurboConfig { - turbo_version: "2.0.3".into() - }) - ); - } - - #[test] - fn test_just_lockfile() { - let tmpdir = TempDir::with_prefix("local_config").unwrap(); - let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); - let repo = RepoState { - root: root.to_owned(), - mode: RepoMode::MultiPackage, - root_package_json: PackageJson::default(), - package_manager: Err(Error::MissingPackageManager), - }; - let lockfile = root.join_component("package-lock.json"); - lockfile - .create_with_contents(include_bytes!( - "../../fixtures/local_config/turbov2.package-lock.json" - )) - .unwrap(); - - assert_eq!( - LocalTurboConfig::infer_internal(&repo, Some(true)), - Some(LocalTurboConfig { - turbo_version: "2.0.3".into() - }) - ); - } - - #[test] - fn test_package_json_dep() { - let tmpdir = TempDir::with_prefix("local_config").unwrap(); - let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); - let repo = RepoState { - root: root.to_owned(), - mode: RepoMode::MultiPackage, - root_package_json: PackageJson { - dependencies: Some( - vec![("turbo".into(), "^2.0.0".into())] - .into_iter() - .collect(), - ), - ..Default::default() - }, - package_manager: Err(Error::MissingPackageManager), - }; - - assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None,); - } - - #[test] - fn test_package_json_dev_dep() { - let tmpdir = TempDir::with_prefix("local_config").unwrap(); - let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); - let repo = RepoState { - root: root.to_owned(), - mode: RepoMode::MultiPackage, - root_package_json: PackageJson { - dev_dependencies: Some( - vec![("turbo".into(), "^2.0.0".into())] - .into_iter() - .collect(), - ), - ..Default::default() - }, - package_manager: Err(Error::MissingPackageManager), - }; - - assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None); - } - - #[test] - fn test_v1_schema() { - let tmpdir = TempDir::with_prefix("local_config").unwrap(); - let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); - let repo = RepoState { - root: root.to_owned(), - mode: RepoMode::MultiPackage, - root_package_json: PackageJson::default(), - package_manager: Err(Error::MissingPackageManager), - }; - let turbo_json = root.join_component("turbo.json"); - turbo_json - .create_with_contents(include_bytes!("../../fixtures/local_config/turbo.v1.json")) - .unwrap(); - assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None); - } - - #[test] - fn test_v2_schema() { - let tmpdir = TempDir::with_prefix("local_config").unwrap(); - let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); - let repo = RepoState { - root: root.to_owned(), - mode: RepoMode::MultiPackage, - root_package_json: PackageJson::default(), - package_manager: Err(Error::MissingPackageManager), - }; - let turbo_json = root.join_component("turbo.json"); - turbo_json - .create_with_contents(include_bytes!("../../fixtures/local_config/turbo.v2.json")) - .unwrap(); - assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None,); - } - - #[test] - fn nothing() { - let tmpdir = TempDir::with_prefix("local_config").unwrap(); - let root = AbsoluteSystemPath::from_std_path(tmpdir.path()).unwrap(); - let repo = RepoState { - root: root.to_owned(), - mode: RepoMode::MultiPackage, - root_package_json: PackageJson::default(), - package_manager: Err(Error::MissingPackageManager), - }; - assert_eq!(LocalTurboConfig::infer_internal(&repo, Some(true)), None,); - } -} diff --git a/crates/turborepo-lib/src/shim/local_turbo_state.rs b/crates/turborepo-lib/src/shim/local_turbo_state.rs deleted file mode 100644 index 760986fb212bf..0000000000000 --- a/crates/turborepo-lib/src/shim/local_turbo_state.rs +++ /dev/null @@ -1,223 +0,0 @@ -use std::{ - env, fs, - path::{Path, PathBuf}, -}; - -use camino::Utf8PathBuf; -use dunce::canonicalize as fs_canonicalize; -use semver::Version; -use serde::Deserialize; -use tracing::debug; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; -use turborepo_repository::package_json::PackageJson; - -use super::TurboState; - -/// Structure that holds information on an existing local turbo install -#[derive(Debug)] -pub struct LocalTurboState { - bin_path: PathBuf, - version: String, -} - -impl LocalTurboState { - pub fn version(&self) -> &str { - &self.version - } - - pub fn binary(&self) -> &Path { - &self.bin_path - } - // Hoisted strategy: - // - `bun install` - // - `npm install` - // - `yarn` - // - `yarn install --flat` - // - berry (nodeLinker: "node-modules") - // - // This also supports people directly depending upon the platform version. - fn generate_hoisted_path(root_path: &AbsoluteSystemPath) -> Option { - Some(root_path.join_component("node_modules")) - } - - // Nested strategy: - // - `npm install --install-strategy=shallow` (`npm install --global-style`) - // - `npm install --install-strategy=nested` (`npm install --legacy-bundling`) - // - berry (nodeLinker: "pnpm") - fn generate_nested_path(root_path: &AbsoluteSystemPath) -> Option { - Some(root_path.join_components(&["node_modules", "turbo", "node_modules"])) - } - - // Linked strategy: - // - `pnpm install` - // - `npm install --install-strategy=linked` - fn generate_linked_path(root_path: &AbsoluteSystemPath) -> Option { - // root_path/node_modules/turbo is a symlink. Canonicalize the symlink to what - // it points to. We do this _before_ traversing up to the parent, - // because on Windows, if you canonicalize a path that ends with `/..` - // it traverses to the parent directory before it follows the symlink, - // leading to the wrong place. We could separate the Windows - // implementation, but this workaround works for other platforms as - // well. - let canonical_path = - fs_canonicalize(root_path.as_path().join("node_modules").join("turbo")).ok()?; - - AbsoluteSystemPathBuf::try_from(canonical_path.parent()?).ok() - } - - // The unplugged directory doesn't have a fixed path. - fn get_unplugged_base_path(root_path: &AbsoluteSystemPath) -> Utf8PathBuf { - let yarn_rc_filename = - env::var("YARN_RC_FILENAME").unwrap_or_else(|_| String::from(".yarnrc.yml")); - let yarn_rc_filepath = root_path.as_path().join(yarn_rc_filename); - - let yarn_rc_yaml_string = fs::read_to_string(yarn_rc_filepath).unwrap_or_default(); - let yarn_rc: YarnRc = serde_yaml::from_str(&yarn_rc_yaml_string).unwrap_or_default(); - - root_path.as_path().join(yarn_rc.pnp_unplugged_folder) - } - - // Unplugged strategy: - // - berry 2.1+ - fn generate_unplugged_path(root_path: &AbsoluteSystemPath) -> Option { - let platform_package_name = TurboState::platform_package_name(); - let unplugged_base_path = Self::get_unplugged_base_path(root_path); - - unplugged_base_path - .read_dir_utf8() - .ok() - .and_then(|mut read_dir| { - // berry includes additional metadata in the filename. - // We actually have to find the platform package. - read_dir.find_map(|item| match item { - Ok(entry) => { - let file_name = entry.file_name(); - if file_name.starts_with(platform_package_name) { - AbsoluteSystemPathBuf::new( - unplugged_base_path.join(file_name).join("node_modules"), - ) - .ok() - } else { - None - } - } - Err(_) => None, - }) - }) - } - - // We support six per-platform packages and one `turbo` package which handles - // indirection. We identify the per-platform package and execute the appropriate - // binary directly. We can choose to operate this aggressively because the - // _worst_ outcome is that we run global `turbo`. - // - // In spite of that, the only known unsupported local invocation is Yarn/Berry < - // 2.1 PnP - pub fn infer(root_path: &AbsoluteSystemPath) -> Option { - let platform_package_name = TurboState::platform_package_name(); - let binary_name = TurboState::binary_name(); - - let platform_package_json_path_components = [platform_package_name, "package.json"]; - let platform_package_executable_path_components = - [platform_package_name, "bin", binary_name]; - - // These are lazy because the last two are more expensive. - let search_functions = [ - Self::generate_hoisted_path, - Self::generate_nested_path, - Self::generate_linked_path, - Self::generate_unplugged_path, - ]; - - // Detecting the package manager is more expensive than just doing an exhaustive - // search. - for root in search_functions - .iter() - .filter_map(|search_function| search_function(root_path)) - { - // Needs borrow because of the loop. - #[allow(clippy::needless_borrow)] - let bin_path = root.join_components(&platform_package_executable_path_components); - match fs_canonicalize(&bin_path) { - Ok(bin_path) => { - let resolved_package_json_path = - root.join_components(&platform_package_json_path_components); - let platform_package_json = - PackageJson::load(&resolved_package_json_path).ok()?; - let local_version = platform_package_json.version?; - - debug!("Local turbo path: {}", bin_path.display()); - debug!("Local turbo version: {}", &local_version); - return Some(Self { - bin_path, - version: local_version, - }); - } - Err(_) => debug!("No local turbo binary found at: {}", bin_path), - } - } - - None - } - - /// Check to see if the detected local executable is the one currently - /// running. - pub fn local_is_self(&self) -> bool { - std::env::current_exe().is_ok_and(|current_exe| { - fs_canonicalize(current_exe) - .is_ok_and(|canonical_current_exe| canonical_current_exe == self.bin_path) - }) - } -} - -#[derive(Debug, Clone, Deserialize)] -#[serde(rename_all = "camelCase")] -struct YarnRc { - pnp_unplugged_folder: Utf8PathBuf, -} - -impl Default for YarnRc { - fn default() -> Self { - Self { - pnp_unplugged_folder: [".yarn", "unplugged"].iter().collect(), - } - } -} - -pub fn turbo_version_has_shim(version: &str) -> bool { - if let Ok(version) = Version::parse(version) { - // only need to check major and minor (this will include canaries) - if version.major == 1 { - return version.minor >= 7; - } - version.major > 1 - } else { - // In the case that we don't get passed a valid semver we should avoid a panic. - // We shouldn't hit this we introduce back inferring package version from schema - // or package.json. - true - } -} - -#[cfg(test)] -mod test { - use test_case::test_case; - - use super::*; - - #[test_case("1.7.0-canary.0", true; "canary")] - #[test_case("1.7.0-canary.1", true; "newer_canary")] - #[test_case("1.7.1-canary.6", true; "newer_minor_canary")] - #[test_case("1.7.0", true; "release")] - #[test_case("1.6.3", false; "old")] - #[test_case("1.6.2-canary.1", false; "old_canary")] - #[test_case("1.8.0", true; "new")] - #[test_case("2.1.0", true; "new major")] - #[test_case("*", true; "star")] - #[test_case("2.0", true; "version 2 0")] - #[test_case("latest", true; "latest")] - #[test_case("canary", true; "canary tag")] - fn test_skip_infer_version_constraint(version: &str, expected: bool) { - assert_eq!(turbo_version_has_shim(version), expected); - } -} diff --git a/crates/turborepo-lib/src/shim/parser.rs b/crates/turborepo-lib/src/shim/parser.rs deleted file mode 100644 index 15bfaaba330a6..0000000000000 --- a/crates/turborepo-lib/src/shim/parser.rs +++ /dev/null @@ -1,475 +0,0 @@ -use std::{backtrace::Backtrace, env}; - -use itertools::Itertools; -use miette::{Diagnostic, SourceSpan}; -use turbopath::AbsoluteSystemPathBuf; -use turborepo_ui::ColorConfig; - -use super::Error; - -// all arguments that result in a stdout that much be directly parsable and -// should not be paired with additional output (from the update notifier for -// example) -static TURBO_PURE_OUTPUT_ARGS: [&str; 6] = [ - "--json", - "--dry", - "--dry-run", - "--dry=json", - "--graph", - "--dry-run=json", -]; - -static TURBO_SKIP_NOTIFIER_ARGS: [&str; 5] = - ["--help", "--h", "--version", "--v", "--no-update-notifier"]; - -#[derive(Debug, thiserror::Error, Diagnostic)] -#[error("cannot have multiple `--cwd` flags in command")] -#[diagnostic(code(turbo::shim::multiple_cwd))] -pub struct MultipleCwd { - #[backtrace] - backtrace: Backtrace, - #[source_code] - args_string: String, - #[label("first flag declared here")] - flag1: Option, - #[label("but second flag declared here")] - flag2: Option, - #[label("and here")] - flag3: Option, - // The user should get the idea after the first 4 examples. - #[label("and here")] - flag4: Option, -} - -#[derive(Debug, PartialEq, Eq)] -pub struct ShimArgs { - pub cwd: AbsoluteSystemPathBuf, - pub invocation_dir: AbsoluteSystemPathBuf, - pub skip_infer: bool, - pub verbosity: usize, - pub force_update_check: bool, - pub remaining_turbo_args: Vec, - pub forwarded_args: Vec, - pub color: bool, - pub no_color: bool, -} - -impl ShimArgs { - pub fn parse() -> Result { - let invocation_dir = AbsoluteSystemPathBuf::cwd()?; - Self::parse_from_iter(invocation_dir, std::env::args()) - } - - fn parse_from_iter( - invocation_dir: AbsoluteSystemPathBuf, - args: impl Iterator, - ) -> Result { - let mut cwd_flag_idx = None; - let mut cwds = Vec::new(); - let mut skip_infer = false; - let mut found_verbosity_flag = false; - let mut verbosity = 0; - let mut force_update_check = false; - let mut remaining_turbo_args = Vec::new(); - let mut forwarded_args = Vec::new(); - let mut is_forwarded_args = false; - let mut color = false; - let mut no_color = false; - - let args = args.skip(1); - for (idx, arg) in args.enumerate() { - // We've seen a `--` and therefore we do no parsing - if is_forwarded_args { - forwarded_args.push(arg); - } else if arg == "--skip-infer" { - skip_infer = true; - } else if arg == "--check-for-update" { - force_update_check = true; - } else if arg == "--" { - // If we've hit `--` we've reached the args forwarded to tasks. - is_forwarded_args = true; - } else if arg == "--verbosity" { - // If we see `--verbosity` we expect the next arg to be a number. - remaining_turbo_args.push(arg); - found_verbosity_flag = true - } else if arg.starts_with("--verbosity=") || found_verbosity_flag { - let verbosity_count = if found_verbosity_flag { - found_verbosity_flag = false; - &arg - } else { - arg.strip_prefix("--verbosity=").unwrap_or("0") - }; - - verbosity = verbosity_count.parse::().unwrap_or(0); - remaining_turbo_args.push(arg); - } else if arg == "-v" || arg.starts_with("-vv") { - verbosity = arg[1..].len(); - remaining_turbo_args.push(arg); - } else if cwd_flag_idx.is_some() { - // We've seen a `--cwd` and therefore add this to the cwds list along with - // the index of the `--cwd` (*not* the value) - cwds.push(( - AbsoluteSystemPathBuf::from_unknown(&invocation_dir, arg), - idx - 1, - )); - cwd_flag_idx = None; - } else if arg == "--cwd" { - // If we see a `--cwd` we expect the next arg to be a path. - cwd_flag_idx = Some(idx) - } else if let Some(cwd_arg) = arg.strip_prefix("--cwd=") { - // In the case where `--cwd` is passed as `--cwd=./path/to/foo`, that - // entire chunk is a single arg, so we need to split it up. - cwds.push(( - AbsoluteSystemPathBuf::from_unknown(&invocation_dir, cwd_arg), - idx, - )); - } else if arg == "--color" { - color = true; - } else if arg == "--no-color" { - no_color = true; - } else { - remaining_turbo_args.push(arg); - } - } - - if let Some(idx) = cwd_flag_idx { - let (spans, args_string) = - Self::get_spans_in_args_string(vec![idx], env::args().skip(1)); - - return Err(Error::EmptyCwd { - backtrace: Backtrace::capture(), - args_string, - flag_range: spans[0], - }); - } - - if cwds.len() > 1 { - let (indices, args_string) = Self::get_spans_in_args_string( - cwds.iter().map(|(_, idx)| *idx).collect(), - env::args().skip(1), - ); - - let mut flags = indices.into_iter(); - return Err(Error::MultipleCwd(Box::new(MultipleCwd { - backtrace: Backtrace::capture(), - args_string, - flag1: flags.next(), - flag2: flags.next(), - flag3: flags.next(), - flag4: flags.next(), - }))); - } - - let cwd = cwds - .pop() - .map(|(cwd, _)| cwd) - .unwrap_or_else(|| invocation_dir.clone()); - - Ok(ShimArgs { - cwd, - invocation_dir, - skip_infer, - verbosity, - force_update_check, - remaining_turbo_args, - forwarded_args, - color, - no_color, - }) - } - - /// Takes a list of indices into a Vec of arguments, i.e. ["--graph", "foo", - /// "--cwd"] and converts them into `SourceSpan`'s into the string of those - /// arguments, i.e. "-- graph foo --cwd". Returns the spans and the args - /// string - fn get_spans_in_args_string( - mut args_indices: Vec, - args: impl Iterator>, - ) -> (Vec, String) { - // Sort the indices to keep the invariant - // that if i > j then output[i] > output[j] - args_indices.sort(); - let mut indices_in_args_string = Vec::new(); - let mut i = 0; - let mut current_args_string_idx = 0; - - for (idx, arg) in args.enumerate() { - let Some(arg_idx) = args_indices.get(i) else { - break; - }; - - let arg = arg.into(); - - if idx == *arg_idx { - indices_in_args_string.push((current_args_string_idx, arg.len()).into()); - i += 1; - } - current_args_string_idx += arg.len() + 1; - } - - let args_string = env::args().skip(1).join(" "); - - (indices_in_args_string, args_string) - } - - // returns true if any flags result in pure json output to stdout - fn has_json_flags(&self) -> bool { - self.remaining_turbo_args - .iter() - .any(|arg| TURBO_PURE_OUTPUT_ARGS.contains(&arg.as_str())) - } - - // returns true if any flags should bypass the update notifier - fn has_notifier_skip_flags(&self) -> bool { - self.remaining_turbo_args - .iter() - .any(|arg| TURBO_SKIP_NOTIFIER_ARGS.contains(&arg.as_str())) - } - - pub fn should_check_for_update(&self) -> bool { - if self.force_update_check { - return true; - } - - if self.has_notifier_skip_flags() || self.has_json_flags() { - return false; - } - - true - } - - pub fn color_config(&self) -> ColorConfig { - if self.no_color { - ColorConfig::new(true) - } else if self.color { - // Do our best to enable ansi colors, but even if the terminal doesn't support - // still emit ansi escape sequences. - Self::supports_ansi(); - ColorConfig::new(false) - } else if Self::supports_ansi() { - // If the terminal supports ansi colors, then we can infer if we should emit - // colors - ColorConfig::infer() - } else { - ColorConfig::new(true) - } - } - - #[cfg(windows)] - fn supports_ansi() -> bool { - // This call has the side effect of setting ENABLE_VIRTUAL_TERMINAL_PROCESSING - // to true. https://learn.microsoft.com/en-us/windows/console/setconsolemode - crossterm::ansi_support::supports_ansi() - } - - #[cfg(not(windows))] - fn supports_ansi() -> bool { - true - } -} - -#[cfg(test)] -mod test { - use miette::SourceSpan; - use pretty_assertions::assert_eq; - use test_case::test_case; - use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; - - use super::ShimArgs; - - #[test_case(vec![3], vec!["--graph", "foo", "--cwd", "apple"], vec![(18, 5).into()])] - #[test_case(vec![0], vec!["--graph", "foo", "--cwd"], vec![(0, 7).into()])] - #[test_case(vec![0, 2], vec!["--graph", "foo", "--cwd"], vec![(0, 7).into(), (12, 5).into()])] - #[test_case(vec![], vec!["--cwd"], vec![])] - fn test_get_indices_in_arg_string( - arg_indices: Vec, - args: Vec<&'static str>, - expected_indices_in_arg_string: Vec, - ) { - let (indices_in_args_string, _) = - ShimArgs::get_spans_in_args_string(arg_indices, args.into_iter()); - assert_eq!(indices_in_args_string, expected_indices_in_arg_string); - } - - #[derive(Default)] - struct ExpectedArgs { - pub skip_infer: bool, - pub verbosity: usize, - pub force_update_check: bool, - pub remaining_turbo_args: &'static [&'static str], - pub forwarded_args: &'static [&'static str], - pub color: bool, - pub no_color: bool, - pub relative_cwd: Option<&'static [&'static str]>, - } - - impl ExpectedArgs { - fn build(self, invocation_dir: &AbsoluteSystemPath) -> ShimArgs { - let Self { - skip_infer, - verbosity, - force_update_check, - remaining_turbo_args, - forwarded_args, - color, - no_color, - relative_cwd, - } = self; - ShimArgs { - cwd: relative_cwd.map_or_else( - || invocation_dir.to_owned(), - |components| invocation_dir.join_components(components), - ), - invocation_dir: invocation_dir.to_owned(), - remaining_turbo_args: remaining_turbo_args - .iter() - .map(|arg| arg.to_string()) - .collect(), - forwarded_args: forwarded_args.iter().map(|arg| arg.to_string()).collect(), - skip_infer, - verbosity, - force_update_check, - color, - no_color, - } - } - } - - #[test_case( - &["turbo"], - ExpectedArgs { - ..Default::default() - } - ; "no args" - )] - #[test_case( - &["turbo", "-v"], - ExpectedArgs { - verbosity: 1, - remaining_turbo_args: &["-v"], - ..Default::default() - } - ; "verbosity count 1" - )] - #[test_case( - &["turbo", "-vv"], - ExpectedArgs { - verbosity: 2, - remaining_turbo_args: &["-vv"], - ..Default::default() - } - ; "verbosity count 2" - )] - #[test_case( - &["turbo", "--verbosity", "3"], - ExpectedArgs { - verbosity: 3, - remaining_turbo_args: &["--verbosity", "3"], - ..Default::default() - } - ; "verbosity flag 3" - )] - #[test_case( - &["turbo", "--verbosity=3"], - ExpectedArgs { - verbosity: 3, - remaining_turbo_args: &["--verbosity=3"], - ..Default::default() - } - ; "verbosity equals 3" - )] - #[test_case( - &["turbo", "--verbosity=3", "-vv"], - ExpectedArgs { - verbosity: 2, - remaining_turbo_args: &["--verbosity=3", "-vv"], - ..Default::default() - } - ; "multi verbosity" - )] - #[test_case( - &["turbo", "--color"], - ExpectedArgs { - color: true, - ..Default::default() - } - ; "color" - )] - #[test_case( - &["turbo", "--no-color"], - ExpectedArgs { - no_color: true, - ..Default::default() - } - ; "no color" - )] - #[test_case( - &["turbo", "--no-color", "--color"], - ExpectedArgs { - color: true, - no_color: true, - ..Default::default() - } - ; "confused color" - )] - #[test_case( - &["turbo", "--skip-infer"], - ExpectedArgs { - skip_infer: true, - ..Default::default() - } - ; "skip infer" - )] - #[test_case( - &["turbo", "--", "another", "--skip-infer"], - ExpectedArgs { - forwarded_args: &["another", "--skip-infer"], - ..Default::default() - } - ; "forwarded args" - )] - #[test_case( - &["turbo", "--check-for-update"], - ExpectedArgs { - force_update_check: true, - ..Default::default() - } - ; "check for update" - )] - #[test_case( - &["turbo", "--check-for-update=true"], - ExpectedArgs { - force_update_check: false, - remaining_turbo_args: &["--check-for-update=true"], - ..Default::default() - } - ; "check for update value" - )] - #[test_case( - &["turbo", "--cwd", "another-dir"], - ExpectedArgs { - relative_cwd: Some(&["another-dir"]), - ..Default::default() - } - ; "cwd value" - )] - #[test_case( - &["turbo", "--cwd=another-dir"], - ExpectedArgs { - relative_cwd: Some(&["another-dir"]), - ..Default::default() - } - ; "cwd equals" - )] - fn test_shim_parsing(args: &[&str], expected: ExpectedArgs) { - let cwd = AbsoluteSystemPathBuf::new(if cfg!(windows) { - "Z:\\some\\dir" - } else { - "/some/dir" - }) - .unwrap(); - let expected = expected.build(&cwd); - let actual = ShimArgs::parse_from_iter(cwd, args.iter().map(|s| s.to_string())).unwrap(); - assert_eq!(expected, actual); - } -} diff --git a/crates/turborepo-lib/src/shim/turbo_state.rs b/crates/turborepo-lib/src/shim/turbo_state.rs deleted file mode 100644 index 5ce14fec42e89..0000000000000 --- a/crates/turborepo-lib/src/shim/turbo_state.rs +++ /dev/null @@ -1,70 +0,0 @@ -use const_format::formatcp; - -/// Struct containing helper methods for querying information about the -/// currently running turbo binary. -#[derive(Debug)] -pub struct TurboState; - -impl TurboState { - pub const fn platform_name() -> &'static str { - const ARCH: &str = { - #[cfg(target_arch = "x86_64")] - { - "64" - } - #[cfg(target_arch = "aarch64")] - { - "arm64" - } - #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))] - { - "unknown" - } - }; - - const OS: &str = { - #[cfg(target_os = "macos")] - { - "darwin" - } - #[cfg(target_os = "windows")] - { - "windows" - } - #[cfg(target_os = "linux")] - { - "linux" - } - #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] - { - "unknown" - } - }; - - formatcp!("{}-{}", OS, ARCH) - } - - pub const fn platform_package_name() -> &'static str { - formatcp!("turbo-{}", TurboState::platform_name()) - } - - pub const fn binary_name() -> &'static str { - { - #[cfg(windows)] - { - "turbo.exe" - } - #[cfg(not(windows))] - { - "turbo" - } - } - } - - pub fn version() -> &'static str { - include_str!("../../../../version.txt") - .lines() - .next() - .expect("Failed to read version from version.txt") - } -} diff --git a/crates/turborepo-lib/src/signal.rs b/crates/turborepo-lib/src/signal.rs deleted file mode 100644 index 37cd735ef2fc2..0000000000000 --- a/crates/turborepo-lib/src/signal.rs +++ /dev/null @@ -1,214 +0,0 @@ -use std::{ - fmt::Debug, - future::Future, - sync::{Arc, Mutex}, -}; - -use futures::{stream::FuturesUnordered, StreamExt}; -use tokio::sync::{mpsc, oneshot}; - -/// SignalHandler provides a mechanism to subscribe to a future and get alerted -/// whenever the future completes or the handler gets a close message. -#[derive(Debug, Clone)] -pub struct SignalHandler { - state: Arc>, - close: mpsc::Sender<()>, -} - -#[derive(Debug, Default)] -struct HandlerState { - subscribers: Vec>>, - is_closing: bool, -} - -pub struct SignalSubscriber(oneshot::Receiver>); - -/// SubscriberGuard should be kept until a subscriber is done processing the -/// signal -pub struct SubscriberGuard(oneshot::Sender<()>); - -impl SignalHandler { - /// Construct a new SignalHandler that will alert any subscribers when - /// `signal_source` completes or `close` is called on it. - pub fn new(signal_source: impl Future> + Send + 'static) -> Self { - // think about channel size - let state = Arc::new(Mutex::new(HandlerState::default())); - let worker_state = state.clone(); - let (close, mut rx) = mpsc::channel::<()>(1); - tokio::spawn(async move { - tokio::select! { - // We don't care if we get a signal or if we are unable to receive signals - // Either way we start the shutdown. - _ = signal_source => {}, - // We don't care if a close message was sent or if all handlers are dropped. - // Either way start the shutdown process. - _ = rx.recv() => {} - } - - let mut callbacks = { - let mut state = worker_state.lock().expect("lock poisoned"); - // Mark ourselves as closing to prevent any additional subscribers from being - // added - state.is_closing = true; - state - .subscribers - .drain(..) - .filter_map(|callback| { - let (tx, rx) = oneshot::channel(); - // If the subscriber is no longer around we don't wait for the callback - callback.send(tx).ok()?; - Some(rx) - }) - .collect::>() - }; - - // We don't care if callback gets dropped or if the done signal is sent. - while let Some(_fut) = callbacks.next().await {} - }); - - Self { state, close } - } - - /// Register a new subscriber - /// Will return `None` if SignalHandler is in the process of shutting down - /// or if it has already shut down. - pub fn subscribe(&self) -> Option { - self.state - .lock() - .expect("poisoned lock") - .add_subscriber() - .map(SignalSubscriber) - } - - /// Send message to signal handler that it should shut down and alert - /// subscribers - pub async fn close(&self) { - if self.close.send(()).await.is_err() { - // watcher has already closed - return; - } - self.done().await; - } - - /// Wait until handler is finished and all subscribers finish their cleanup - /// work - pub async fn done(&self) { - // Receiver is dropped once the worker task completes - self.close.closed().await; - } - - // Check if the worker thread is done, only meant to be used for assertions in - // testing - #[cfg(test)] - fn is_done(&self) -> bool { - self.close.is_closed() - } -} - -impl SignalSubscriber { - /// Wait until signal is received by the signal handler - pub async fn listen(self) -> SubscriberGuard { - let callback = self - .0 - .await - .expect("signal handler worker thread exited without alerting subscribers"); - SubscriberGuard(callback) - } -} - -impl HandlerState { - fn add_subscriber(&mut self) -> Option>> { - (!self.is_closing).then(|| { - let (tx, rx) = oneshot::channel(); - self.subscribers.push(tx); - rx - }) - } -} - -#[cfg(test)] -mod test { - use std::{assert_matches::assert_matches, time::Duration}; - - use super::*; - - #[tokio::test] - async fn test_subscribers_triggered_from_signal() { - let (tx, rx) = oneshot::channel(); - let handler = SignalHandler::new(async move { rx.await.ok() }); - let subscriber = handler.subscribe().unwrap(); - // Send mocked SIGINT - tx.send(()).unwrap(); - - let (done, mut is_done) = oneshot::channel(); - let handler2 = handler.clone(); - tokio::spawn(async move { - handler2.done().await; - done.send(()).ok(); - }); - - let _guard = subscriber.listen().await; - assert_matches!( - is_done.try_recv(), - Err(oneshot::error::TryRecvError::Empty), - "done shouldn't be finished" - ); - drop(_guard); - tokio::time::sleep(Duration::from_millis(5)).await; - handler.done().await; - } - - #[tokio::test] - async fn test_subscribers_triggered_from_close() { - let (_tx, rx) = oneshot::channel::<()>(); - let handler = SignalHandler::new(async move { rx.await.ok() }); - let subscriber = handler.subscribe().unwrap(); - let (close_done, mut is_close_done) = oneshot::channel(); - - let h2 = handler.clone(); - let _handle = tokio::spawn(async move { - h2.close().await; - close_done.send(()).ok(); - }); - - let _guard = subscriber.listen().await; - assert_matches!( - is_close_done.try_recv(), - Err(oneshot::error::TryRecvError::Empty), - "close shouldn't be finished" - ); - drop(_guard); - handler.done().await; - } - - #[tokio::test] - async fn test_close_idempotent() { - let (_tx, rx) = oneshot::channel::<()>(); - let handler = SignalHandler::new(async move { rx.await.ok() }); - handler.close().await; - handler.close().await; - } - - #[tokio::test] - async fn test_subscribe_after_close() { - let (tx, rx) = oneshot::channel(); - let handler = SignalHandler::new(async move { rx.await.ok() }); - let subscriber = handler.subscribe().unwrap(); - - // Send SIGINT - tx.send(()).unwrap(); - // Do a quick yield to give the worker a chance to read the sigint - tokio::task::yield_now().await; - assert!( - !handler.is_done(), - "handler should not finish until subscriber finishes" - ); - assert!( - handler.subscribe().is_none(), - "handler that has received a signal should not accept new subscribers" - ); - let _guard = subscriber.listen().await; - drop(_guard); - handler.done().await; - } -} diff --git a/crates/turborepo-lib/src/task_graph/visitor/error.rs b/crates/turborepo-lib/src/task_graph/visitor/error.rs deleted file mode 100644 index f7823ba0d4c21..0000000000000 --- a/crates/turborepo-lib/src/task_graph/visitor/error.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Warning that comes from the execution of the task -#[derive(Debug, Clone)] -pub struct TaskWarning { - task_id: String, - missing_platform_env: Vec, -} - -// Error that comes from the execution of the task -#[derive(Debug, thiserror::Error, Clone)] -#[error("{task_id}: {cause}")] -pub struct TaskError { - task_id: String, - cause: TaskErrorCause, -} - -#[derive(Debug, thiserror::Error, Clone)] -pub enum TaskErrorCause { - #[error("unable to spawn child process: {msg}")] - // We eagerly serialize this in order to allow us to implement clone - Spawn { msg: String }, - #[error("command {command} exited ({exit_code})")] - Exit { command: String, exit_code: i32 }, - #[error("turbo has internal error processing task")] - Internal, -} - -impl TaskWarning { - /// Construct a new warning for a given task with the - /// Returns `None` if there are no missing platform environment variables - pub fn new(task_id: &str, missing_platform_env: Vec) -> Option { - if missing_platform_env.is_empty() { - return None; - } - Some(Self { - task_id: task_id.to_owned(), - missing_platform_env, - }) - } - - pub fn task_id(&self) -> &str { - &self.task_id - } - - /// All missing platform environment variables. - /// Guaranteed to have at least length 1 due to constructor validation. - pub fn missing_platform_env(&self) -> &[String] { - &self.missing_platform_env - } -} - -impl TaskError { - pub fn new(task_id: String, cause: TaskErrorCause) -> Self { - Self { task_id, cause } - } - - pub fn exit_code(&self) -> Option { - match self.cause { - TaskErrorCause::Exit { exit_code, .. } => Some(exit_code), - _ => None, - } - } - - pub fn from_spawn(task_id: String, err: std::io::Error) -> Self { - Self { - task_id, - cause: TaskErrorCause::Spawn { - msg: err.to_string(), - }, - } - } - - pub fn from_execution(task_id: String, command: String, exit_code: i32) -> Self { - Self { - task_id, - cause: TaskErrorCause::Exit { command, exit_code }, - } - } -} - -impl TaskErrorCause { - pub fn from_spawn(err: std::io::Error) -> Self { - TaskErrorCause::Spawn { - msg: err.to_string(), - } - } - - pub fn from_execution(command: String, exit_code: i32) -> Self { - TaskErrorCause::Exit { command, exit_code } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_warning_no_vars() { - let no_warning = TaskWarning::new("a-task", vec![]); - assert!(no_warning.is_none()); - } - - #[test] - fn test_warning_some_var() { - let warning = TaskWarning::new("a-task", vec!["MY_VAR".into()]); - assert!(warning.is_some()); - let warning = warning.unwrap(); - assert_eq!(warning.task_id(), "a-task"); - assert_eq!(warning.missing_platform_env(), &["MY_VAR".to_owned()]); - } -} diff --git a/crates/turborepo-lib/src/task_graph/visitor/exec.rs b/crates/turborepo-lib/src/task_graph/visitor/exec.rs deleted file mode 100644 index 9c5df8acb64d3..0000000000000 --- a/crates/turborepo-lib/src/task_graph/visitor/exec.rs +++ /dev/null @@ -1,536 +0,0 @@ -use std::{ - io::Write, - sync::{Arc, Mutex}, - time::{Duration, Instant}, -}; - -use console::StyledObject; -use tokio::sync::oneshot; -use tracing::{error, Instrument}; -use turborepo_env::{platform::PlatformEnv, EnvironmentVariableMap}; -use turborepo_repository::package_manager::PackageManager; -use turborepo_telemetry::events::{task::PackageTaskEventBuilder, TrackedErrors}; -use turborepo_ui::{ColorConfig, OutputWriter}; - -use super::{ - command::{CommandFactory, MicroFrontendProxyProvider, PackageGraphCommandProvider}, - error::{TaskError, TaskErrorCause, TaskWarning}, - output::TaskCacheOutput, - TaskOutput, Visitor, -}; -use crate::{ - config::UIMode, - engine::{Engine, StopExecution}, - process::{ChildExit, Command, ProcessManager}, - run::{ - summary::{SpacesTaskClient, SpacesTaskInformation, TaskExecutionSummary, TaskTracker}, - task_access::TaskAccess, - task_id::TaskId, - CacheOutput, TaskCache, - }, - task_hash::TaskHashTracker, -}; - -pub struct ExecContextFactory<'a> { - visitor: &'a Visitor<'a>, - errors: Arc>>, - manager: ProcessManager, - engine: &'a Arc, - command_factory: CommandFactory<'a>, -} - -impl<'a> ExecContextFactory<'a> { - pub fn new( - visitor: &'a Visitor<'a>, - errors: Arc>>, - manager: ProcessManager, - engine: &'a Arc, - ) -> Result { - let pkg_graph_provider = PackageGraphCommandProvider::new( - visitor.repo_root, - &visitor.package_graph, - visitor.run_opts.task_args(), - visitor.micro_frontends_configs, - ); - let mut command_factory = CommandFactory::new(); - if let Some(micro_frontends_configs) = visitor.micro_frontends_configs { - command_factory.add_provider(MicroFrontendProxyProvider::new( - visitor.repo_root, - &visitor.package_graph, - engine, - micro_frontends_configs, - )); - } - command_factory.add_provider(pkg_graph_provider); - - Ok(Self { - visitor, - errors, - manager, - engine, - command_factory, - }) - } - - #[allow(clippy::too_many_arguments)] - pub fn exec_context( - &self, - task_id: TaskId<'static>, - task_hash: String, - task_cache: TaskCache, - mut execution_env: EnvironmentVariableMap, - takes_input: bool, - task_access: TaskAccess, - ) -> Result, super::Error> { - let task_id_for_display = self.visitor.display_task_id(&task_id); - let task_id_string = &task_id.to_string(); - self.populate_env(&mut execution_env, &task_hash, &task_access); - let Some(cmd) = self - .command_factory - .command(&task_id, execution_env.clone())? - else { - return Ok(None); - }; - Ok(Some(ExecContext { - engine: self.engine.clone(), - ui_mode: self.visitor.run_opts.ui_mode, - color_config: self.visitor.color_config, - is_github_actions: self.visitor.run_opts.is_github_actions, - pretty_prefix: self - .visitor - .color_cache - .prefix_with_color(task_id_string, &self.visitor.prefix(&task_id)), - task_id, - task_id_for_display, - task_cache, - hash_tracker: self.visitor.task_hasher.task_hash_tracker(), - package_manager: self.visitor.package_graph.package_manager().clone(), - manager: self.manager.clone(), - task_hash, - execution_env, - continue_on_error: self.visitor.run_opts.continue_on_error, - errors: self.errors.clone(), - warnings: self.visitor.warnings.clone(), - takes_input, - task_access, - cmd, - platform_env: PlatformEnv::new(), - })) - } - - pub fn dry_run_exec_context( - &self, - task_id: TaskId<'static>, - task_cache: TaskCache, - ) -> DryRunExecContext { - DryRunExecContext { - task_id, - task_cache, - hash_tracker: self.visitor.task_hasher.task_hash_tracker(), - } - } - - // Add any env vars that `turbo` provides to the task environment - fn populate_env( - &self, - execution_env: &mut EnvironmentVariableMap, - task_hash: &str, - task_access: &TaskAccess, - ) { - // Always last to make sure it overwrites any user configured env var. - execution_env.insert("TURBO_HASH".to_owned(), task_hash.to_owned()); - - // Allow downstream tools to detect if the task is being ran with TUI - if self.visitor.run_opts.ui_mode.use_tui() { - execution_env.insert("TURBO_IS_TUI".to_owned(), "true".to_owned()); - } - - // enable task access tracing - // set the trace file env var - frameworks that support this can use it to - // write out a trace file that we will use to automatically cache the task - if task_access.is_enabled() { - let (task_access_trace_key, trace_file) = task_access.get_env_var(task_hash); - execution_env.insert(task_access_trace_key, trace_file.to_string()); - } - } -} - -pub struct ExecContext { - engine: Arc, - color_config: ColorConfig, - ui_mode: UIMode, - is_github_actions: bool, - pretty_prefix: StyledObject, - task_id: TaskId<'static>, - task_id_for_display: String, - task_cache: TaskCache, - hash_tracker: TaskHashTracker, - package_manager: PackageManager, - manager: ProcessManager, - task_hash: String, - execution_env: EnvironmentVariableMap, - continue_on_error: bool, - errors: Arc>>, - warnings: Arc>>, - takes_input: bool, - task_access: TaskAccess, - cmd: Command, - platform_env: PlatformEnv, -} - -enum ExecOutcome { - // All operations during execution succeeded - Success(SuccessOutcome), - // An error with the task execution - Task { - exit_code: Option, - message: String, - }, - // Task didn't execute normally due to a shutdown being initiated by another task - Shutdown, -} - -enum SuccessOutcome { - CacheHit, - Run, -} - -impl ExecContext { - pub async fn execute_dry_run(&mut self, tracker: TaskTracker<()>) { - if let Ok(Some(status)) = self.task_cache.exists().await { - self.hash_tracker - .insert_cache_status(self.task_id.clone(), status); - } - - tracker.dry_run().await; - } - pub async fn execute( - &mut self, - parent_span_id: Option, - tracker: TaskTracker<()>, - output_client: TaskOutput, - callback: oneshot::Sender>, - spaces_client: Option, - telemetry: &PackageTaskEventBuilder, - ) -> Result<(), InternalError> { - let tracker = tracker.start().await; - let span = tracing::debug_span!("execute_task", task = %self.task_id.task()); - span.follows_from(parent_span_id); - let mut result = self - .execute_inner(&output_client, telemetry) - .instrument(span) - .await; - - // If the task resulted in an error, do not group in order to better highlight - // the error. - let is_error = matches!(result, Ok(ExecOutcome::Task { .. })); - let is_cache_hit = matches!(result, Ok(ExecOutcome::Success(SuccessOutcome::CacheHit))); - let logs = match output_client.finish(is_error, is_cache_hit) { - Ok(logs) => logs, - Err(e) => { - telemetry.track_error(TrackedErrors::DaemonFailedToMarkOutputsAsCached); - error!("unable to flush output client: {e}"); - result = Err(InternalError::Io(e)); - None - } - }; - - match result { - Ok(ExecOutcome::Success(outcome)) => { - let task_summary = match outcome { - SuccessOutcome::CacheHit => tracker.cached().await, - SuccessOutcome::Run => tracker.build_succeeded(0).await, - }; - callback.send(Ok(())).ok(); - if let Some(client) = spaces_client { - let logs = logs.expect("spaces enabled logs should be collected"); - let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); - client.finish_task(info).await.ok(); - } - } - Ok(ExecOutcome::Task { exit_code, message }) => { - let task_summary = tracker.build_failed(exit_code, message).await; - callback - .send(match self.continue_on_error { - true => Ok(()), - false => Err(StopExecution), - }) - .ok(); - - match (spaces_client, self.continue_on_error) { - // Nothing to do - (None, true) => (), - // Shut down manager - (None, false) => self.manager.stop().await, - // Send task - (Some(client), true) => { - let logs = logs.expect("spaced enabled logs should be collected"); - let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); - client.finish_task(info).await.ok(); - } - // Send task and shut down manager - (Some(client), false) => { - let logs = logs.unwrap_or_default(); - let info = self.spaces_task_info(self.task_id.clone(), task_summary, logs); - // Ignore spaces result as that indicates handler is shut down and we are - // unable to send information to spaces - let (_spaces_result, _) = - tokio::join!(client.finish_task(info), self.manager.stop()); - } - } - } - Ok(ExecOutcome::Shutdown) => { - tracker.cancel(); - callback.send(Err(StopExecution)).ok(); - // Probably overkill here, but we should make sure the process manager is - // stopped if we think we're shutting down. - self.manager.stop().await; - } - Err(e) => { - tracker.cancel(); - callback.send(Err(StopExecution)).ok(); - self.manager.stop().await; - return Err(e); - } - } - - Ok(()) - } - - fn prefixed_ui<'a, W: Write>( - &self, - output_client: &'a TaskOutput, - ) -> TaskCacheOutput> { - match output_client { - TaskOutput::Direct(client) => TaskCacheOutput::Direct(Visitor::prefixed_ui( - self.color_config, - self.is_github_actions, - client.stdout(), - client.stderr(), - self.pretty_prefix.clone(), - )), - TaskOutput::UI(task) => TaskCacheOutput::UI(task.clone()), - } - } - - async fn execute_inner( - &mut self, - output_client: &TaskOutput, - telemetry: &PackageTaskEventBuilder, - ) -> Result { - let task_start = Instant::now(); - let mut prefixed_ui = self.prefixed_ui(output_client); - - if self.ui_mode.has_sender() { - if let TaskOutput::UI(task) = output_client { - let output_logs = self.task_cache.output_logs().into(); - task.start(output_logs); - } - } - - if !self.task_cache.is_caching_disabled() { - let missing_platform_env = self.platform_env.validate(&self.execution_env); - if let Some(warning) = TaskWarning::new(&self.task_id_for_display, missing_platform_env) - { - self.warnings - .lock() - .expect("warnings lock poisoned") - .push(warning); - } - } - - match self - .task_cache - .restore_outputs(&mut prefixed_ui, telemetry) - .await - { - Ok(Some(status)) => { - // we need to set expanded outputs - self.hash_tracker.insert_expanded_outputs( - self.task_id.clone(), - self.task_cache.expanded_outputs().to_vec(), - ); - self.hash_tracker - .insert_cache_status(self.task_id.clone(), status); - return Ok(ExecOutcome::Success(SuccessOutcome::CacheHit)); - } - Ok(None) => (), - Err(e) => { - telemetry.track_error(TrackedErrors::ErrorFetchingFromCache); - prefixed_ui.error(&format!("error fetching from cache: {e}")); - } - } - - let cmd = self.cmd.clone(); - - let mut process = match self.manager.spawn(cmd, Duration::from_millis(500)) { - Some(Ok(child)) => child, - // Turbo was unable to spawn a process - Some(Err(e)) => { - // Note: we actually failed to spawn, but this matches the Go output - prefixed_ui.error(&format!("command finished with error: {e}")); - let error_string = e.to_string(); - self.errors - .lock() - .expect("lock poisoned") - .push(TaskError::from_spawn(self.task_id_for_display.clone(), e)); - return Ok(ExecOutcome::Task { - exit_code: None, - message: error_string, - }); - } - // Turbo is shutting down - None => { - return Ok(ExecOutcome::Shutdown); - } - }; - - if self.ui_mode.has_sender() && self.takes_input { - if let TaskOutput::UI(task) = output_client { - if let Some(stdin) = process.stdin() { - task.set_stdin(stdin); - } - } - } - - // Even if user does not have the TUI and cannot interact with a task, we keep - // stdin open for persistent tasks as some programs will shut down if stdin is - // closed. - if !self.takes_input && !self.manager.closing_stdin_ends_process() { - process.stdin(); - } - - let mut stdout_writer = self - .task_cache - .output_writer(prefixed_ui.task_writer()) - .inspect_err(|_| { - telemetry.track_error(TrackedErrors::FailedToCaptureOutputs); - })?; - - let exit_status = match process.wait_with_piped_outputs(&mut stdout_writer).await { - Ok(Some(exit_status)) => exit_status, - Err(e) => { - telemetry.track_error(TrackedErrors::FailedToPipeOutputs); - return Err(e.into()); - } - Ok(None) => { - // TODO: how can this happen? we only update the - // exit status with Some and it is only initialized with - // None. Is it still running? - telemetry.track_error(TrackedErrors::UnknownChildExit); - error!("unable to determine why child exited"); - return Err(InternalError::UnknownChildExit); - } - }; - let task_duration = task_start.elapsed(); - - match exit_status { - ChildExit::Finished(Some(0)) => { - // Attempt to flush stdout_writer and log any errors encountered - if let Err(e) = stdout_writer.flush() { - error!("{e}"); - } else if self - .task_access - .can_cache(&self.task_hash, &self.task_id_for_display) - .unwrap_or(true) - { - if let Err(e) = self.task_cache.save_outputs(task_duration, telemetry).await { - error!("error caching output: {e}"); - return Err(e.into()); - } else { - // If no errors, update hash tracker with expanded outputs - self.hash_tracker.insert_expanded_outputs( - self.task_id.clone(), - self.task_cache.expanded_outputs().to_vec(), - ); - } - } - - // Return success outcome - Ok(ExecOutcome::Success(SuccessOutcome::Run)) - } - ChildExit::Finished(Some(code)) => { - // If there was an error, flush the buffered output - if let Err(e) = stdout_writer.flush() { - error!("error flushing logs: {e}"); - } - if let Err(e) = self.task_cache.on_error(&mut prefixed_ui) { - error!("error reading logs: {e}"); - } - let error = TaskErrorCause::from_execution(process.label().to_string(), code); - let message = error.to_string(); - if self.continue_on_error { - prefixed_ui.warn("command finished with error, but continuing..."); - } else { - prefixed_ui.error(&format!("command finished with error: {error}")); - } - self.errors - .lock() - .expect("lock poisoned") - .push(TaskError::new(self.task_id_for_display.clone(), error)); - Ok(ExecOutcome::Task { - exit_code: Some(code), - message, - }) - } - // The child exited in a way where we can't figure out how it finished so we assume it - // failed. - ChildExit::Finished(None) | ChildExit::Failed => Err(InternalError::UnknownChildExit), - // Something else killed the child - ChildExit::KilledExternal => Err(InternalError::ExternalKill), - // The child was killed by turbo indicating a shutdown - ChildExit::Killed => Ok(ExecOutcome::Shutdown), - } - } - - fn spaces_task_info( - &self, - task_id: TaskId<'static>, - execution_summary: TaskExecutionSummary, - logs: Vec, - ) -> SpacesTaskInformation { - let dependencies = self.engine.dependencies(&task_id); - let dependents = self.engine.dependents(&task_id); - let cache_status = self.hash_tracker.cache_status(&task_id); - SpacesTaskInformation { - task_id, - execution_summary, - logs, - hash: self.task_hash.clone(), - cache_status, - dependencies, - dependents, - } - } -} - -pub struct DryRunExecContext { - task_id: TaskId<'static>, - task_cache: TaskCache, - hash_tracker: TaskHashTracker, -} - -#[derive(Debug, thiserror::Error)] -pub enum InternalError { - #[error(transparent)] - Io(#[from] std::io::Error), - #[error("unable to determine why task exited")] - UnknownChildExit, - #[error("unable to find package manager binary: {0}")] - Which(#[from] which::Error), - #[error("external process killed a task")] - ExternalKill, - #[error("error writing logs: {0}")] - Logs(#[from] crate::run::CacheError), -} -impl DryRunExecContext { - pub async fn execute_dry_run(&self, tracker: TaskTracker<()>) -> Result<(), InternalError> { - // may also need to do framework & command stuff? - if let Ok(Some(status)) = self.task_cache.exists().await { - self.hash_tracker - .insert_cache_status(self.task_id.clone(), status); - } - tracker.dry_run().await; - Ok(()) - } -} diff --git a/crates/turborepo-lib/src/task_graph/visitor/output.rs b/crates/turborepo-lib/src/task_graph/visitor/output.rs deleted file mode 100644 index 958b94efa3667..0000000000000 --- a/crates/turborepo-lib/src/task_graph/visitor/output.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::io::Write; - -use either::Either; -use turbopath::AbsoluteSystemPath; -use turborepo_ui::{ - sender::TaskSender, tui::event::CacheResult, OutputClient, OutputWriter, PrefixedUI, -}; - -use crate::run::CacheOutput; - -/// Small wrapper over our two output types that defines a shared interface for -/// interacting with them. -pub enum TaskOutput { - Direct(OutputClient), - UI(TaskSender), -} - -/// Struct for displaying information about task -impl TaskOutput { - pub fn finish(self, use_error: bool, is_cache_hit: bool) -> std::io::Result>> { - match self { - TaskOutput::Direct(client) => client.finish(use_error), - TaskOutput::UI(client) if use_error => Ok(Some(client.failed())), - TaskOutput::UI(client) => Ok(Some(client.succeeded(is_cache_hit))), - } - } - - pub fn stdout(&self) -> Either, TaskSender> { - match self { - TaskOutput::Direct(client) => Either::Left(client.stdout()), - TaskOutput::UI(client) => Either::Right(client.clone()), - } - } - - pub fn stderr(&self) -> Either, TaskSender> { - match self { - TaskOutput::Direct(client) => Either::Left(client.stderr()), - TaskOutput::UI(client) => Either::Right(client.clone()), - } - } - - pub fn task_logs(&self) -> Either, TaskSender> { - match self { - TaskOutput::Direct(client) => Either::Left(client.stdout()), - TaskOutput::UI(client) => Either::Right(client.clone()), - } - } -} - -/// Struct for displaying information about task's cache -pub enum TaskCacheOutput { - Direct(PrefixedUI), - UI(TaskSender), -} - -impl TaskCacheOutput { - pub fn task_writer(&mut self) -> Either, TaskSender> { - match self { - TaskCacheOutput::Direct(prefixed) => Either::Left(prefixed.output_prefixed_writer()), - TaskCacheOutput::UI(task) => Either::Right(task.clone()), - } - } - - pub fn warn(&mut self, message: impl std::fmt::Display) { - match self { - TaskCacheOutput::Direct(prefixed) => prefixed.warn(message), - TaskCacheOutput::UI(task) => { - let _ = write!(task, "\r\n{message}\r\n"); - } - } - } -} - -impl CacheOutput for TaskCacheOutput { - fn status(&mut self, message: &str, result: CacheResult) { - match self { - TaskCacheOutput::Direct(direct) => direct.output(message), - TaskCacheOutput::UI(task) => task.status(message, result), - } - } - - fn error(&mut self, message: &str) { - match self { - TaskCacheOutput::Direct(prefixed) => prefixed.error(message), - TaskCacheOutput::UI(task) => { - let _ = write!(task, "{message}\r\n"); - } - } - } - - fn replay_logs(&mut self, log_file: &AbsoluteSystemPath) -> Result<(), turborepo_ui::Error> { - match self { - TaskCacheOutput::Direct(direct) => { - let writer = direct.output_prefixed_writer(); - turborepo_ui::replay_logs(writer, log_file) - } - TaskCacheOutput::UI(task) => turborepo_ui::replay_logs(task, log_file), - } - } -} - -// A tiny enum that allows us to use the same type for stdout and stderr without -// the use of Box -pub enum StdWriter { - Out(std::io::Stdout), - Err(std::io::Stderr), - Null(std::io::Sink), -} - -impl StdWriter { - fn writer(&mut self) -> &mut dyn std::io::Write { - match self { - StdWriter::Out(out) => out, - StdWriter::Err(err) => err, - StdWriter::Null(null) => null, - } - } -} - -impl From for StdWriter { - fn from(value: std::io::Stdout) -> Self { - Self::Out(value) - } -} - -impl From for StdWriter { - fn from(value: std::io::Stderr) -> Self { - Self::Err(value) - } -} - -impl From for StdWriter { - fn from(value: std::io::Sink) -> Self { - Self::Null(value) - } -} - -impl std::io::Write for StdWriter { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.writer().write(buf) - } - - fn flush(&mut self) -> std::io::Result<()> { - self.writer().flush() - } -} diff --git a/crates/turborepo-lib/src/tracing.rs b/crates/turborepo-lib/src/tracing.rs deleted file mode 100644 index a20ef9cfc7f78..0000000000000 --- a/crates/turborepo-lib/src/tracing.rs +++ /dev/null @@ -1,355 +0,0 @@ -use std::{io::Stderr, marker::PhantomData, path::Path, sync::Mutex}; - -use chrono::Local; -use owo_colors::{ - colors::{Black, Default, Red, Yellow}, - Color, OwoColorize, -}; -use tracing::{field::Visit, metadata::LevelFilter, trace, Event, Level, Subscriber}; -use tracing_appender::{non_blocking::NonBlocking, rolling::RollingFileAppender}; -use tracing_chrome::ChromeLayer; -pub use tracing_subscriber::reload::Error; -use tracing_subscriber::{ - filter::Filtered, - fmt::{ - self, - format::{DefaultFields, Writer}, - FmtContext, FormatEvent, FormatFields, MakeWriter, - }, - layer, - prelude::*, - registry::LookupSpan, - reload::{self, Handle}, - EnvFilter, Layer, Registry, -}; -use turborepo_ui::ColorConfig; - -// a lot of types to make sure we record the right relationships - -/// Note that we cannot express the type of `std::io::stderr` directly, so -/// use zero-size wrapper to call the function. -struct StdErrWrapper {} - -impl<'a> MakeWriter<'a> for StdErrWrapper { - type Writer = Stderr; - - fn make_writer(&'a self) -> Self::Writer { - std::io::stderr() - } -} - -/// A basic logger that logs to stderr using the TurboFormatter. -/// The first generic parameter refers to the previous layer, which -/// is in this case the default layer (`Registry`). -type StdErrLog = fmt::Layer; -/// We filter this using an EnvFilter. -type StdErrLogFiltered = Filtered; -/// When the `StdErrLogFiltered` is applied to the `Registry`, we get a -/// `StdErrLogLayered`, which forms the base for the next layer. -type StdErrLogLayered = layer::Layered; - -/// A logger that spits lines into a file, using the standard formatter. -/// It is applied on top of the `StdErrLogLayered` layer. -type DaemonLog = fmt::Layer; -/// This layer can be reloaded. `None` means the layer is disabled. -type DaemonReload = reload::Layer, StdErrLogLayered>; -/// We filter this using a custom filter that only logs events -/// - with evel `TRACE` or higher for the `turborepo` target -/// - with level `INFO` or higher for all other targets -type DaemonLogFiltered = Filtered; -/// When the `DaemonLogFiltered` is applied to the `StdErrLogLayered`, we get a -/// `DaemonLogLayered`, which forms the base for the next layer. -type DaemonLogLayered = layer::Layered; - -/// A logger that converts events to chrome tracing format and writes them -/// to a file. It is applied on top of the `DaemonLogLayered` layer. -type ChromeLog = ChromeLayer; -/// This layer can be reloaded. `None` means the layer is disabled. -type ChromeReload = reload::Layer, DaemonLogLayered>; -/// When the `ChromeLogFiltered` is applied to the `DaemonLogLayered`, we get a -/// `ChromeLogLayered`, which forms the base for the next layer. -type ChromeLogLayered = layer::Layered; - -pub struct TurboSubscriber { - daemon_update: Handle, StdErrLogLayered>, - - /// The non-blocking file logger only continues to log while this guard is - /// held. We keep it here so that it doesn't get dropped. - daemon_guard: Mutex>, - - chrome_update: Handle, DaemonLogLayered>, - chrome_guard: Mutex>, - - #[cfg(feature = "pprof")] - pprof_guard: pprof::ProfilerGuard<'static>, -} - -impl TurboSubscriber { - /// Sets up the tracing subscriber, with a default stderr layer using the - /// TurboFormatter. - /// - /// ## Logging behaviour: - /// - If stdout is a terminal, we use ansi colors. Otherwise, we do not. - /// - If the `TURBO_LOG_VERBOSITY` env var is set, it will be used to set - /// the verbosity level. Otherwise, the default is `WARN`. See the - /// documentation on the RUST_LOG env var for syntax. - /// - If the verbosity argument (usually determined by a flag) is provided, - /// it overrides the default global log level. This means it overrides the - /// `TURBO_LOG_VERBOSITY` global setting, but not per-module settings. - /// - /// `TurboSubscriber` has optional loggers that can be enabled later: - /// - `set_daemon_logger` enables logging to a file, using the standard - /// formatter. - /// - `enable_chrome_tracing` enables logging to a file, using the chrome - /// tracing formatter. - pub fn new_with_verbosity(verbosity: usize, color_config: &ColorConfig) -> Self { - let level_override = match verbosity { - 0 => None, - 1 => Some(LevelFilter::INFO), - 2 => Some(LevelFilter::DEBUG), - _ => Some(LevelFilter::TRACE), - }; - - let env_filter = |level: LevelFilter| { - let filter = EnvFilter::builder() - .with_default_directive(level.into()) - .with_env_var("TURBO_LOG_VERBOSITY") - .from_env_lossy() - .add_directive("reqwest=error".parse().unwrap()) - .add_directive("hyper=warn".parse().unwrap()) - .add_directive("h2=warn".parse().unwrap()); - - if let Some(max_level) = level_override { - filter.add_directive(max_level.into()) - } else { - filter - } - }; - - let stderr = fmt::layer() - .with_writer(StdErrWrapper {}) - .event_format(TurboFormatter::new_with_ansi( - !color_config.should_strip_ansi, - )) - .with_filter(env_filter(LevelFilter::WARN)); - - // we set this layer to None to start with, effectively disabling it - let (logrotate, daemon_update) = reload::Layer::new(Option::::None); - let logrotate: DaemonLogFiltered = logrotate.with_filter(env_filter(LevelFilter::INFO)); - - let (chrome, chrome_update) = reload::Layer::new(Option::::None); - - let registry = Registry::default() - .with(stderr) - .with(logrotate) - .with(chrome); - - #[cfg(feature = "pprof")] - let pprof_guard = pprof::ProfilerGuardBuilder::default() - .frequency(1000) - .blocklist(&["libc", "libgcc", "pthread", "vdso"]) - .build() - .unwrap(); - - registry.init(); - - Self { - daemon_update, - daemon_guard: Mutex::new(None), - chrome_update, - chrome_guard: Mutex::new(None), - #[cfg(feature = "pprof")] - pprof_guard, - } - } - - /// Enables daemon logging with the specified rotation settings. - /// - /// Daemon logging uses the standard tracing formatter. - #[tracing::instrument(skip(self, appender))] - pub fn set_daemon_logger(&self, appender: RollingFileAppender) -> Result<(), Error> { - let (file_writer, guard) = tracing_appender::non_blocking(appender); - trace!("created non-blocking file writer"); - - let layer: DaemonLog = tracing_subscriber::fmt::layer() - .with_writer(file_writer) - .with_ansi(false); - - self.daemon_update.reload(Some(layer))?; - self.daemon_guard - .lock() - .expect("not poisoned") - .replace(guard); - - Ok(()) - } - - /// Enables chrome tracing. - #[tracing::instrument(skip(self, to_file))] - pub fn enable_chrome_tracing>( - &self, - to_file: P, - include_args: bool, - ) -> Result<(), Error> { - let (layer, guard) = tracing_chrome::ChromeLayerBuilder::new() - .file(to_file) - .include_args(include_args) - .include_locations(true) - .trace_style(tracing_chrome::TraceStyle::Async) - .build(); - - self.chrome_update.reload(Some(layer))?; - self.chrome_guard - .lock() - .expect("not poisoned") - .replace(guard); - - Ok(()) - } -} - -impl Drop for TurboSubscriber { - fn drop(&mut self) { - // drop the guard so that the non-blocking file writer stops - #[cfg(feature = "pprof")] - if let Ok(report) = self.pprof_guard.report().build() { - use std::io::Write; // only import trait if we need it - - use prost::Message; - - let mut file = std::fs::File::create("pprof.pb").unwrap(); - let mut content = Vec::new(); - - let Ok(profile) = report.pprof() else { - tracing::error!("failed to generate pprof report"); - return; - }; - if let Err(e) = profile.encode(&mut content) { - tracing::error!("failed to encode pprof profile: {}", e); - }; - if let Err(e) = file.write_all(&content) { - tracing::error!("failed to write pprof profile: {}", e) - }; - } else { - tracing::error!("failed to generate pprof report") - } - } -} - -/// The formatter for TURBOREPO -/// -/// This is a port of the go formatter, which follows a few main rules: -/// - Errors are red -/// - Warnings are yellow -/// - Info is default -/// - Debug and trace are default, but with timestamp and level attached -/// -/// This formatter does not print any information about spans, and does -/// not print any event metadata other than the message set when you -/// call `debug!(...)` or `info!(...)` etc. -pub struct TurboFormatter { - is_ansi: bool, -} - -impl TurboFormatter { - pub fn new_with_ansi(is_ansi: bool) -> Self { - Self { is_ansi } - } -} - -impl FormatEvent for TurboFormatter -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, -{ - fn format_event( - &self, - _ctx: &FmtContext<'_, S, N>, - mut writer: Writer<'_>, - event: &Event<'_>, - ) -> std::fmt::Result { - let level = event.metadata().level(); - let target = event.metadata().target(); - - match *level { - Level::ERROR => { - // The padding spaces are necessary to match the formatting of Go - write_string::(writer.by_ref(), self.is_ansi, " ERROR ") - .and_then(|_| write_message::(writer, self.is_ansi, event)) - } - Level::WARN => { - // The padding spaces are necessary to match the formatting of Go - write_string::(writer.by_ref(), self.is_ansi, " WARNING ") - .and_then(|_| write_message::(writer, self.is_ansi, event)) - } - Level::INFO => write_message::(writer, self.is_ansi, event), - // trace and debug use the same style - _ => { - let now = Local::now(); - write!( - writer, - "{} [{}] {}: ", - // build our own timestamp to match the hashicorp/go-hclog format used by the - // go binary - now.format("%Y-%m-%dT%H:%M:%S.%3f%z"), - level, - target, - ) - .and_then(|_| write_message::(writer, self.is_ansi, event)) - } - } - } -} - -/// A visitor that writes the message field of an event to the given writer. -/// -/// The FG and BG type parameters are the foreground and background colors -/// to use when writing the message. -struct MessageVisitor<'a, FG: Color, BG: Color> { - colorize: bool, - writer: Writer<'a>, - _fg: PhantomData, - _bg: PhantomData, -} - -impl<'a, FG: Color, BG: Color> Visit for MessageVisitor<'a, FG, BG> { - fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) { - if field.name() == "message" { - if self.colorize { - let value = value.fg::().bg::(); - let _ = write!(self.writer, "{:?}", value); - } else { - let _ = write!(self.writer, "{:?}", value); - } - } - } -} - -fn write_string( - mut writer: Writer<'_>, - colorize: bool, - value: &str, -) -> Result<(), std::fmt::Error> { - if colorize { - let value = value.fg::().bg::(); - write!(writer, "{} ", value) - } else { - write!(writer, "{} ", value) - } -} - -/// Writes the message field of an event to the given writer. -fn write_message( - mut writer: Writer<'_>, - colorize: bool, - event: &Event, -) -> Result<(), std::fmt::Error> { - let mut visitor = MessageVisitor:: { - colorize, - writer: writer.by_ref(), - _fg: PhantomData, - _bg: PhantomData, - }; - event.record(&mut visitor); - writeln!(writer) -} diff --git a/crates/turborepo-lib/test/scripts/hello_no_line.js b/crates/turborepo-lib/test/scripts/hello_no_line.js deleted file mode 100644 index 1d6fbdbcffc46..0000000000000 --- a/crates/turborepo-lib/test/scripts/hello_no_line.js +++ /dev/null @@ -1,2 +0,0 @@ -const process = require("node:process"); -process.stdout.write("look ma, no newline!", () => {}); diff --git a/crates/turborepo-lib/test/scripts/hello_non_utf8.js b/crates/turborepo-lib/test/scripts/hello_non_utf8.js deleted file mode 100644 index e8f4389c3a199..0000000000000 --- a/crates/turborepo-lib/test/scripts/hello_non_utf8.js +++ /dev/null @@ -1,5 +0,0 @@ -const process = require("node:process"); -process.stdout.write(new Uint8Array([0, 159, 146, 150]), () => { - // Print newline - console.log(); -}); diff --git a/crates/turborepo-lib/test/scripts/hello_world.js b/crates/turborepo-lib/test/scripts/hello_world.js deleted file mode 100644 index 6b2b3db0f6520..0000000000000 --- a/crates/turborepo-lib/test/scripts/hello_world.js +++ /dev/null @@ -1 +0,0 @@ -console.log("hello world"); diff --git a/crates/turborepo-lib/test/scripts/hello_world_hello_moon.js b/crates/turborepo-lib/test/scripts/hello_world_hello_moon.js deleted file mode 100644 index 4e60d1aeff62d..0000000000000 --- a/crates/turborepo-lib/test/scripts/hello_world_hello_moon.js +++ /dev/null @@ -1,2 +0,0 @@ -console.log("hello world"); -console.warn("hello moon"); diff --git a/crates/turborepo-lib/test/scripts/sleep_5_ignore.js b/crates/turborepo-lib/test/scripts/sleep_5_ignore.js deleted file mode 100644 index cf871b886a83d..0000000000000 --- a/crates/turborepo-lib/test/scripts/sleep_5_ignore.js +++ /dev/null @@ -1,14 +0,0 @@ -process.on("SIGINT", () => { - console.log("received SIGINT, ignoring"); -}); - -function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)); -} - -async function run() { - await delay(5000); -} -// signal that our signal handler is registered -console.log("here"); -run(); diff --git a/crates/turborepo-lib/test/scripts/sleep_5_interruptable.js b/crates/turborepo-lib/test/scripts/sleep_5_interruptable.js deleted file mode 100644 index fbef2e53c720a..0000000000000 --- a/crates/turborepo-lib/test/scripts/sleep_5_interruptable.js +++ /dev/null @@ -1,10 +0,0 @@ -function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)); -} - -async function run() { - await delay(5000); - console.log("hello world"); -} - -run(); diff --git a/crates/turborepo-lib/test/scripts/stdin_stdout.js b/crates/turborepo-lib/test/scripts/stdin_stdout.js deleted file mode 100644 index 6aab6ee2e544c..0000000000000 --- a/crates/turborepo-lib/test/scripts/stdin_stdout.js +++ /dev/null @@ -1,5 +0,0 @@ -// read stdin and write to stdout - -process.stdin.on("data", (data) => { - process.stdout.write(data); -}); diff --git a/crates/turborepo-lockfiles/Cargo.toml b/crates/turborepo-lockfiles/Cargo.toml index de412cd79992b..262e3233d9a05 100644 --- a/crates/turborepo-lockfiles/Cargo.toml +++ b/crates/turborepo-lockfiles/Cargo.toml @@ -1,14 +1,3 @@ -[package] -name = "turborepo-lockfiles" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] nom = "7" pest = "2.7.9" @@ -20,10 +9,24 @@ serde = { version = "1.0.126", features = ["derive", "rc"] } serde_json = "1.0.86" serde_yaml = "0.9.27" thiserror = "1.0.38" -tracing.workspace = true turbopath = { path = "../turborepo-paths" } +[dependencies.tracing] +workspace = true + [dev-dependencies] itertools = { workspace = true } pretty_assertions = "1.3" test-case = "3.1.0" + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-lockfiles" +version = "0.1.0" diff --git a/crates/turborepo-lockfiles/src/berry/de.rs b/crates/turborepo-lockfiles/Source/berry/de.rs similarity index 100% rename from crates/turborepo-lockfiles/src/berry/de.rs rename to crates/turborepo-lockfiles/Source/berry/de.rs diff --git a/crates/turborepo-lockfiles/src/berry/identifiers.rs b/crates/turborepo-lockfiles/Source/berry/identifiers.rs similarity index 100% rename from crates/turborepo-lockfiles/src/berry/identifiers.rs rename to crates/turborepo-lockfiles/Source/berry/identifiers.rs diff --git a/crates/turborepo-lockfiles/src/berry/mod.rs b/crates/turborepo-lockfiles/Source/berry/mod.rs similarity index 100% rename from crates/turborepo-lockfiles/src/berry/mod.rs rename to crates/turborepo-lockfiles/Source/berry/mod.rs diff --git a/crates/turborepo-lockfiles/Source/berry/protocol_resolver.rs b/crates/turborepo-lockfiles/Source/berry/protocol_resolver.rs new file mode 100644 index 0000000000000..909bf454dbea9 --- /dev/null +++ b/crates/turborepo-lockfiles/Source/berry/protocol_resolver.rs @@ -0,0 +1,121 @@ +use std::collections::HashMap; + +use super::identifiers::{Descriptor, Ident}; + +/// A data structure for resolving descriptors when the protocol isn't known +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct DescriptorResolver { + mapping:HashMap, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Key { + ident:Ident<'static>, + range:String, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)] +struct Entry { + without:Option, + with:Option, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)] +struct RangeAndProtocol { + protocol:String, + range:String, +} + +impl DescriptorResolver { + /// Add a descriptor to the resolver + pub fn insert(&mut self, descriptor:&Descriptor) -> Option { + let key = Key::new(descriptor)?; + let entry = self.mapping.entry(key).or_default(); + entry.insert_descriptor(descriptor) + } + + /// If given a descriptor without a protocol it will return all matching + /// descriptors with a protocol + pub fn get(&self, descriptor:&Descriptor) -> Option<&str> { + let key = Key::new(descriptor)?; + self.mapping.get(&key).and_then(|e| e.get(descriptor)) + } +} + +impl Key { + fn new(desc:&Descriptor) -> Option { + let ident = desc.ident.to_owned(); + let range = Descriptor::strip_protocol(desc.range()?).to_string(); + Some(Key { ident, range }) + } +} + +impl Entry { + // Insert the given descriptor's range into the correct slot depending if it is + // with or without a protocol + fn insert_descriptor(&mut self, descriptor:&Descriptor) -> Option { + let range = descriptor.range()?.to_string(); + match descriptor.protocol() { + Some(protocol) => { + // Yarn 4 made the default npm protocol explicit in the lockfile. + // In order to return the more specific protocol we avoid overwriting other + // protocols with the now explicit npm protocol. + if protocol != "npm" || self.with.is_none() { + match self + .with + .replace(RangeAndProtocol { range, protocol:protocol.to_string() }) + { + // We only return an ejected range if the protocol isn't the default npm + // protocol + Some(RangeAndProtocol { range, protocol }) if protocol != "npm" => { + Some(range) + }, + _ => None, + } + } else { + None + } + }, + None => self.without.replace(range), + } + } + + fn get(&self, descriptor:&Descriptor) -> Option<&str> { + // We only return the without protocol range if `without` is present + // and the given descriptor is also without a protocol + if self.without.is_some() && descriptor.protocol().is_none() { + self.without.as_deref() + } else { + self.with.as_ref().map(|x| x.range.as_str()) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_descriptor_reconstruction() { + let mut resolver = DescriptorResolver::default(); + let babel_npm = Descriptor::new("@babel/core", "npm:^5.0.0").unwrap(); + let babel_file = Descriptor::new("@babel/core", "file:4.5.0").unwrap(); + assert!(resolver.insert(&babel_npm).is_none()); + assert!(resolver.insert(&babel_file).is_none()); + let babel_5 = Descriptor::new("@babel/core", "^5.0.0").unwrap(); + let babel_4 = Descriptor::new("@babel/core", "4.5.0").unwrap(); + assert_eq!(resolver.get(&babel_5), Some("npm:^5.0.0")); + assert_eq!(resolver.get(&babel_4), Some("file:4.5.0")); + } + + #[test] + fn test_descriptors_without_protocols() { + let mut resolver = DescriptorResolver::default(); + let workspace = Descriptor::new("internal-workspace", "*").unwrap(); + let workspace_with_protocol = Descriptor::new("internal-workspace", "workspace:*").unwrap(); + assert!(resolver.insert(&workspace).is_none()); + assert!(resolver.insert(&workspace_with_protocol).is_none()); + assert_eq!(resolver.get(&workspace), Some("*")); + assert_eq!(resolver.get(&workspace_with_protocol), Some("workspace:*")); + } +} diff --git a/crates/turborepo-lockfiles/src/berry/resolution.pest b/crates/turborepo-lockfiles/Source/berry/resolution.pest similarity index 100% rename from crates/turborepo-lockfiles/src/berry/resolution.pest rename to crates/turborepo-lockfiles/Source/berry/resolution.pest diff --git a/crates/turborepo-lockfiles/src/berry/resolution.rs b/crates/turborepo-lockfiles/Source/berry/resolution.rs similarity index 100% rename from crates/turborepo-lockfiles/src/berry/resolution.rs rename to crates/turborepo-lockfiles/Source/berry/resolution.rs diff --git a/crates/turborepo-lockfiles/Source/berry/ser.rs b/crates/turborepo-lockfiles/Source/berry/ser.rs new file mode 100644 index 0000000000000..8effbcbecc1ab --- /dev/null +++ b/crates/turborepo-lockfiles/Source/berry/ser.rs @@ -0,0 +1,266 @@ +use std::{borrow::Cow, fmt, sync::OnceLock}; + +use regex::Regex; + +use super::{BerryPackage, DependencyMeta, LockfileData, Metadata}; + +fn simple_string() -> &'static Regex { + static RE:OnceLock = OnceLock::new(); + RE.get_or_init(|| { + Regex::new(r#"^[^-?:,\]\[{}#&*!|>'"%@` \t\r\n]([ \t]*[^,\]\[{}:# \t\r\n])*$"#).unwrap() + }) +} + +const HEADER:&str = "# This file is generated by running \"yarn install\" inside your project. +# Manual changes might be lost - proceed with caution! +"; + +// We implement Display in order to produce a correctly serialized `yarn.lock` +// Since Berry is so particular about the contents we can't use the serde_yaml +// serializer without forking it and heavy modifications. Implementing Display +// is more honest than writing a Serializer implementation since the serializer +// would only support a single type. +impl fmt::Display for LockfileData { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{HEADER}\n{}\n", self.metadata)?; + + for (key, entry) in &self.packages { + let wrapped_key = wrap_string(key); + // Yaml 1.2 spec says that keys over 1024 characters need to be prefixed with ? + // and the : goes in a new line + let key_line = match wrapped_key.len() <= 1024 { + true => format!("{wrapped_key}:"), + false => format!("? {wrapped_key}\n:"), + }; + write!(f, "\n{}\n{}\n", key_line, entry)?; + } + + Ok(()) + } +} + +impl fmt::Display for Metadata { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "__metadata:\n version: {}", self.version,)?; + if let Some(cache_key) = &self.cache_key { + write!(f, "\n cacheKey: {}", wrap_string(cache_key))?; + } + Ok(()) + } +} + +const SPACE:char = ' '; +const NEWLINE:char = '\n'; +const INDENT:&str = " "; + +impl fmt::Display for BerryPackage { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { + // we only want to write a newline there was something before + let mut first = true; + let mut write_line = |field:&str, whitespace:char, value:&str| -> fmt::Result { + if !value.is_empty() { + if !first { + writeln!(f)?; + } + write!(f, " {field}:{whitespace}{}", value,)?; + first = false; + } + Ok(()) + }; + + write_line("version", SPACE, &wrap_string(self.version.as_ref()))?; + write_line("resolution", SPACE, &wrap_string(&self.resolution))?; + if let Some(deps) = &self.dependencies { + write_line("dependencies", NEWLINE, &stringify_dependencies(deps.iter()))?; + } + if let Some(peer_deps) = &self.peer_dependencies { + write_line("peerDependencies", NEWLINE, &stringify_dependencies(peer_deps.iter()))?; + } + if let Some(deps_meta) = &self.dependencies_meta { + write_line( + "dependenciesMeta", + NEWLINE, + &stringify_dependencies_meta(deps_meta.iter()), + )?; + } + if let Some(peer_deps_meta) = &self.peer_dependencies_meta { + write_line( + "peerDependenciesMeta", + NEWLINE, + &stringify_dependencies_meta(peer_deps_meta.iter()), + )?; + } + if let Some(bin) = &self.bin { + write_line("bin", NEWLINE, &stringify_dependencies(bin.iter()))?; + } + + if let Some(checksum) = &self.checksum { + write_line("checksum", SPACE, &wrap_string(checksum))?; + } + if let Some(conditions) = &self.conditions { + write_line("conditions", SPACE, &wrap_string(conditions))?; + } + if let Some(language_name) = &self.language_name { + write_line("languageName", SPACE, &wrap_string(language_name))?; + } + if let Some(link_type) = &self.link_type { + write_line("linkType", SPACE, &wrap_string(link_type))?; + } + + Ok(()) + } +} + +fn stringify_dependencies(entries:I) -> String +where + I: Iterator, + S1: AsRef, + S2: AsRef, { + let mut string = String::new(); + let mut first = true; + for (key, value) in entries { + let key = key.as_ref(); + let value = value.as_ref(); + + if !first { + string.push('\n'); + } + string.push_str(&format!(" {}: {}", wrap_string(key), wrap_string(value))); + first = false; + } + string +} + +fn stringify_dependencies_meta<'a, I, S>(metadata:I) -> String +where + I: Iterator, + S: AsRef, { + struct Builder { + s:String, + } + + impl Builder { + fn new() -> Self { Self { s:String::new() } } + + fn add_field(&mut self, field:&str, value:bool) { + if !self.s.is_empty() { + self.s.push('\n'); + } + self.s + .push_str(&format!("{INDENT}{INDENT}{INDENT}{}: {value}", wrap_string(field))); + } + + fn add_dependency(&mut self, dependency:&str) { + if !self.s.is_empty() { + self.s.push('\n'); + } + self.s.push_str(&format!("{INDENT}{INDENT}{}:", wrap_string(dependency),)); + } + } + + let mut builder = Builder::new(); + + for (dependency, meta) in metadata { + let dependency = dependency.as_ref(); + let mut first = true; + let mut add_line = |field:&str, value:bool| { + if first { + builder.add_dependency(dependency); + } + builder.add_field(field, value); + first = false; + }; + if let Some(optional) = meta.optional { + add_line("optional", optional); + } + if let Some(unplugged) = meta.unplugged { + add_line("unplugged", unplugged); + } + if let Some(built) = meta.built { + add_line("built", built); + } + } + + builder.s +} + +fn wrap_string(s:&str) -> Cow { + match simple_string().is_match(s) { + // Simple strings require no wrapping + true => Cow::from(s), + // Complex strings require wrapping + false => { + Cow::from(serde_json::to_string(s).unwrap_or_else(|_| panic!("Unable to encode '{s}'"))) + }, + } +} + +#[cfg(test)] +mod test { + use pretty_assertions::assert_eq; + + use super::*; + + #[test] + fn test_metadata_display() { + let metadata = Metadata { version:"6".into(), cache_key:Some("8c0".to_string()) }; + assert_eq!( + metadata.to_string(), + "__metadata: + version: 6 + cacheKey: 8c0" + ); + } + + #[test] + fn test_wrap_string() { + fn assert(input:&str, expected:&str) { + assert_eq!(wrap_string(input), expected); + } + assert("debug@4.3.4", "debug@4.3.4"); + assert("eslint-module-utils@npm:^2.7.3", "\"eslint-module-utils@npm:^2.7.3\""); + assert("@babel/core", "\"@babel/core\""); + } + + #[test] + fn test_long_key_gets_wrapped() { + let long_key = "a".repeat(1025); + let lockfile = LockfileData { + metadata:Metadata { version:"6".into(), cache_key:Some("8".into()) }, + packages:[( + long_key.clone(), + BerryPackage { version:"1.2.3".to_string(), ..Default::default() }, + )] + .iter() + .cloned() + .collect(), + }; + let serialized = lockfile.to_string(); + assert!(serialized.contains(&format!("? {long_key}\n"))); + } + + #[test] + fn test_stringify_dependencies_meta() { + let metadata = DependencyMeta { optional:Some(false), unplugged:None, built:Some(true) }; + assert_eq!( + stringify_dependencies_meta(Some(("turbo", &metadata)).into_iter()), + " turbo:\n optional: false\n built: true" + ); + } + + #[test] + fn test_stringify_dependencies_meta_multi() { + let foo = DependencyMeta { optional:Some(true), unplugged:None, built:None }; + let bar = DependencyMeta { optional:None, unplugged:None, built:Some(true) }; + assert_eq!( + stringify_dependencies_meta(vec![("foo", &foo), ("bar", &bar)].into_iter()), + " foo:\n optional: true\n bar:\n built: true" + ); + } + + #[test] + fn test_empty_dep_meta() { + let metadata = DependencyMeta { optional:None, unplugged:None, built:None }; + assert_eq!(stringify_dependencies_meta(Some(("turbo", &metadata)).into_iter()), ""); + } +} diff --git a/crates/turborepo-lockfiles/Source/bun/de.rs b/crates/turborepo-lockfiles/Source/bun/de.rs new file mode 100644 index 0000000000000..cb04e9b5fb90a --- /dev/null +++ b/crates/turborepo-lockfiles/Source/bun/de.rs @@ -0,0 +1,299 @@ +use std::sync::OnceLock; + +use nom::{ + IResult, + branch::alt, + bytes::complete::{escaped_transform, is_not, tag, take_till}, + character::complete::{anychar, char as nom_char, crlf, newline, none_of, satisfy, space1}, + combinator::{all_consuming, map, not, opt, peek, recognize, value}, + multi::{count, many0, many1}, + sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, +}; +use regex::Regex; +use serde_json::Value; + +// regex for trimming spaces from start and end +fn pseudostring_replace() -> &'static Regex { + static RE:OnceLock = OnceLock::new(); + RE.get_or_init(|| Regex::new(r"^ *| *$").unwrap()) +} + +pub fn parse_syml(input:&str) -> Result { + match all_consuming(property_statements(0))(input) { + Ok((_, value)) => Ok(value), + Err(e) => Err(super::Error::SymlParse(e.to_string())), + } +} + +// Array and map types +fn item_statements(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| map(many0(item_statement(level)), Value::Array)(i) +} + +fn item_statement(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| { + let (i, _) = indent(level)(i)?; + let (i, _) = nom_char('-')(i)?; + let (i, _) = blankspace(i)?; + expression(level)(i) + } +} + +fn property_statements(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| { + let (i, properties) = many0(property_statement(level))(i)?; + let mut map = serde_json::Map::new(); + for (key, value) in properties.into_iter().flatten() { + map.insert(key, value); + } + Ok((i, Value::Object(map))) + } +} + +fn property_statement(level:usize) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { + move |i:&str| { + alt(( + value( + vec![], + tuple(( + opt(blankspace), + opt(pair(nom_char('#'), many1(pair(not(eol), anychar)))), + many1(eol_any), + )), + ), + map( + preceded(indent(level), separated_pair(name, wrapped_colon, expression(level))), + |entry| vec![entry], + ), + // legacy names + map( + preceded( + indent(level), + separated_pair(legacy_name, wrapped_colon, expression(level)), + ), + |entry| vec![entry], + ), + // legacy prop without colon + map( + preceded( + indent(level), + separated_pair( + legacy_name, + blankspace, + terminated(legacy_literal, many1(eol_any)), + ), + ), + |entry| vec![entry], + ), + multikey_property_statement(level), + ))(i) + } +} + +fn multikey_property_statement( + level:usize, +) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { + move |i:&str| { + let (i, ()) = indent(level)(i)?; + let (i, property) = legacy_name(i)?; + let (i, others) = many1(preceded( + delimited(opt(blankspace), nom_char(','), opt(blankspace)), + legacy_name, + ))(i)?; + let (i, _) = wrapped_colon(i)?; + let (i, value) = expression(level)(i)?; + + Ok(( + i, + std::iter::once(property) + .chain(others) + .map(|key| (key, value.clone())) + .collect(), + )) + } +} + +fn wrapped_colon(i:&str) -> IResult<&str, char> { + delimited(opt(blankspace), nom_char(':'), opt(blankspace))(i) +} + +fn expression(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| { + alt(( + preceded( + tuple((peek(tuple((eol, indent(level + 1), nom_char('-'), blankspace))), eol_any)), + item_statements(level + 1), + ), + preceded(eol, property_statements(level + 1)), + terminated(literal, many1(eol_any)), + ))(i) + } +} + +fn indent(level:usize) -> impl Fn(&str) -> IResult<&str, ()> { + move |i:&str| { + let (i, _) = count(nom_char(' '), level * 2)(i)?; + Ok((i, ())) + } +} + +// Simple types + +fn name(i:&str) -> IResult<&str, String> { alt((string, pseudostring))(i) } + +fn legacy_name(i:&str) -> IResult<&str, String> { + alt((string, map(recognize(many1(pseudostring_legacy)), |s| s.to_string())))(i) +} + +fn literal(i:&str) -> IResult<&str, Value> { + alt(( + value(Value::Null, null), + map(boolean, Value::Bool), + map(string, Value::String), + map(pseudostring, Value::String), + ))(i) +} + +fn legacy_literal(i:&str) -> IResult<&str, Value> { + alt(( + value(Value::Null, null), + map(string, Value::String), + map(pseudostring_legacy, Value::String), + ))(i) +} + +fn pseudostring(i:&str) -> IResult<&str, String> { + let (i, pseudo) = recognize(pseudostring_inner)(i)?; + Ok((i, pseudostring_replace().replace_all(pseudo, "").into_owned())) +} + +fn pseudostring_inner(i:&str) -> IResult<&str, ()> { + let (i, _) = none_of("\r\n\t ?:,][{}#&*!|>'\"%@`-")(i)?; + let (i, _) = many0(tuple((opt(blankspace), none_of("\r\n\t ,][{}:#\"'"))))(i)?; + Ok((i, ())) +} + +fn pseudostring_legacy(i:&str) -> IResult<&str, String> { + let (i, pseudo) = recognize(pseudostring_legacy_inner)(i)?; + let replaced = pseudostring_replace().replace_all(pseudo, ""); + Ok((i, replaced.to_string())) +} + +fn pseudostring_legacy_inner(i:&str) -> IResult<&str, ()> { + let (i, _) = opt(tag("--"))(i)?; + let (i, _) = satisfy(|c| c.is_ascii_alphanumeric() || c == '/')(i)?; + let (i, _) = take_till(|c| "\r\n\t :,".contains(c))(i)?; + Ok((i, ())) +} + +// String parsing + +fn null(i:&str) -> IResult<&str, &str> { tag("null")(i) } + +fn boolean(i:&str) -> IResult<&str, bool> { + alt((value(true, tag("true")), value(false, tag("false"))))(i) +} + +fn string(i:&str) -> IResult<&str, String> { + alt((empty_string, delimited(tag("\""), syml_chars, tag("\""))))(i) +} + +fn empty_string(i:&str) -> IResult<&str, String> { + let (i, _) = tag(r#""""#)(i)?; + Ok((i, "".to_string())) +} + +fn syml_chars(i:&str) -> IResult<&str, String> { + // The SYML grammar provided by Yarn2+ includes escape sequences that weren't + // supported by the yarn1 parser. We diverge from the Yarn2+ provided + // grammar to match the actual parser used by yarn1. + escaped_transform( + is_not("\"\\"), + '\\', + alt(( + value("\"", tag("\"")), + value("\\", tag("\\")), + value("/", tag("/")), + value("\n", tag("n")), + value("\r", tag("r")), + value("\t", tag("t")), + )), + )(i) +} + +// Spaces +fn blankspace(i:&str) -> IResult<&str, &str> { space1(i) } + +fn eol_any(i:&str) -> IResult<&str, &str> { + recognize(tuple((eol, many0(tuple((opt(blankspace), eol))))))(i) +} + +fn eol(i:&str) -> IResult<&str, &str> { + alt((crlf, value("\n", newline), value("\r", nom_char('\r'))))(i) +} + +#[cfg(test)] +mod test { + use serde_json::json; + use test_case::test_case; + + use super::*; + + #[test_case("null", Value::Null ; "null")] + #[test_case("false", Value::Bool(false) ; "literal false")] + #[test_case("true", Value::Bool(true) ; "literal true")] + #[test_case("\"\"", Value::String("".into()) ; "empty string literal")] + #[test_case("\"foo\"", Value::String("foo".into()) ; "quoted string literal")] + #[test_case("foo", Value::String("foo".into()) ; "unquoted string literal")] + fn test_literal(input:&str, expected:Value) { + let (_, actual) = literal(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("name: foo", "name" ; "basic")] + #[test_case("technically a name: foo", "technically a name" ; "multiword name")] + fn test_name(input:&str, expected:&str) { + let (_, actual) = name(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("foo@1:", "foo@1" ; "name with colon terminator")] + #[test_case("\"foo@1\":", "foo@1" ; "qutoed name with colon terminator")] + #[test_case("name foo", "name" ; "name without colon terminator")] + fn test_legacy_name(input:&str, expected:&str) { + let (_, actual) = legacy_name(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("null\n", Value::Null ; "null")] + #[test_case("\"foo\"\n", json!("foo") ; "basic string")] + #[test_case("\n name: foo\n", json!({ "name": "foo" }) ; "basic object")] + fn test_expression(input:&str, expected:Value) { + let (_, actual) = expression(0)(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("# a comment\n", vec![] ; "comment")] + #[test_case("foo: null\n", vec![("foo".into(), Value::Null)] ; "single property")] + #[test_case("name foo\n", vec![("name".into(), json!("foo"))] ; "legacy property")] + fn test_property_statement(input:&str, expected:Vec<(String, Value)>) { + let (_, actual) = property_statement(0)(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("name: foo\n", json!({"name": "foo"}) ; "single property object")] + #[test_case("\"name\": foo\n", json!({"name": "foo"}) ; "single quoted property object")] + #[test_case("name foo\n", json!({"name": "foo"}) ; "single property without colon object")] + #[test_case("# comment\nname: foo\n", json!({"name": "foo"}) ; "comment doesn't affect object")] + #[test_case("name foo\nversion \"1.2.3\"\n", json!({"name": "foo", "version": "1.2.3"}) ; "multi-property object")] + #[test_case("foo:\n version \"1.2.3\"\n", json!({"foo": {"version": "1.2.3"}}) ; "nested object")] + #[test_case("foo, bar, baz:\n version \"1.2.3\"\n", json!({ + "foo": {"version": "1.2.3"}, + "bar": {"version": "1.2.3"}, + "baz": {"version": "1.2.3"}, + }) ; "multi-key object")] + fn test_property_statements(input:&str, expected:Value) { + let (_, actual) = property_statements(0)(input).unwrap(); + assert_eq!(actual, expected); + } +} diff --git a/crates/turborepo-lockfiles/src/bun/mod.rs b/crates/turborepo-lockfiles/Source/bun/mod.rs similarity index 100% rename from crates/turborepo-lockfiles/src/bun/mod.rs rename to crates/turborepo-lockfiles/Source/bun/mod.rs diff --git a/crates/turborepo-lockfiles/src/error.rs b/crates/turborepo-lockfiles/Source/error.rs similarity index 100% rename from crates/turborepo-lockfiles/src/error.rs rename to crates/turborepo-lockfiles/Source/error.rs diff --git a/crates/turborepo-lockfiles/src/lib.rs b/crates/turborepo-lockfiles/Source/lib.rs similarity index 100% rename from crates/turborepo-lockfiles/src/lib.rs rename to crates/turborepo-lockfiles/Source/lib.rs diff --git a/crates/turborepo-lockfiles/src/npm.rs b/crates/turborepo-lockfiles/Source/npm.rs similarity index 100% rename from crates/turborepo-lockfiles/src/npm.rs rename to crates/turborepo-lockfiles/Source/npm.rs diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/Source/pnpm/data.rs similarity index 100% rename from crates/turborepo-lockfiles/src/pnpm/data.rs rename to crates/turborepo-lockfiles/Source/pnpm/data.rs diff --git a/crates/turborepo-lockfiles/Source/pnpm/de.rs b/crates/turborepo-lockfiles/Source/pnpm/de.rs new file mode 100644 index 0000000000000..9cde5522d8c41 --- /dev/null +++ b/crates/turborepo-lockfiles/Source/pnpm/de.rs @@ -0,0 +1,29 @@ +use serde::Deserialize; + +use super::{LockfileVersion, VersionFormat}; + +impl From for LockfileVersion { + fn from(value:f32) -> Self { Self { version:value.to_string(), format:VersionFormat::Float } } +} + +impl From for LockfileVersion { + fn from(value:String) -> Self { Self { version:value, format:VersionFormat::String } } +} + +impl<'de> Deserialize<'de> for LockfileVersion { + fn deserialize(deserializer:D) -> Result + where + D: serde::Deserializer<'de>, { + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrNum { + Str(String), + Num(f32), + } + + Ok(match StringOrNum::deserialize(deserializer)? { + StringOrNum::Num(x) => LockfileVersion::from(x), + StringOrNum::Str(s) => LockfileVersion::from(s), + }) + } +} diff --git a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs b/crates/turborepo-lockfiles/Source/pnpm/dep_path.rs similarity index 100% rename from crates/turborepo-lockfiles/src/pnpm/dep_path.rs rename to crates/turborepo-lockfiles/Source/pnpm/dep_path.rs diff --git a/crates/turborepo-lockfiles/src/pnpm/mod.rs b/crates/turborepo-lockfiles/Source/pnpm/mod.rs similarity index 100% rename from crates/turborepo-lockfiles/src/pnpm/mod.rs rename to crates/turborepo-lockfiles/Source/pnpm/mod.rs diff --git a/crates/turborepo-lockfiles/Source/pnpm/ser.rs b/crates/turborepo-lockfiles/Source/pnpm/ser.rs new file mode 100644 index 0000000000000..4e69015165bcd --- /dev/null +++ b/crates/turborepo-lockfiles/Source/pnpm/ser.rs @@ -0,0 +1,18 @@ +use serde::Serialize; + +use super::{LockfileVersion, VersionFormat}; + +impl Serialize for LockfileVersion { + fn serialize(&self, serializer:S) -> Result + where + S: serde::Serializer, { + match self.format { + VersionFormat::String => serializer.serialize_str(&self.version), + VersionFormat::Float => { + serializer.serialize_f32( + self.version.parse().expect("Expected lockfile version to be valid f32"), + ) + }, + } + } +} diff --git a/crates/turborepo-lockfiles/Source/yarn1/de.rs b/crates/turborepo-lockfiles/Source/yarn1/de.rs new file mode 100644 index 0000000000000..cb04e9b5fb90a --- /dev/null +++ b/crates/turborepo-lockfiles/Source/yarn1/de.rs @@ -0,0 +1,299 @@ +use std::sync::OnceLock; + +use nom::{ + IResult, + branch::alt, + bytes::complete::{escaped_transform, is_not, tag, take_till}, + character::complete::{anychar, char as nom_char, crlf, newline, none_of, satisfy, space1}, + combinator::{all_consuming, map, not, opt, peek, recognize, value}, + multi::{count, many0, many1}, + sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, +}; +use regex::Regex; +use serde_json::Value; + +// regex for trimming spaces from start and end +fn pseudostring_replace() -> &'static Regex { + static RE:OnceLock = OnceLock::new(); + RE.get_or_init(|| Regex::new(r"^ *| *$").unwrap()) +} + +pub fn parse_syml(input:&str) -> Result { + match all_consuming(property_statements(0))(input) { + Ok((_, value)) => Ok(value), + Err(e) => Err(super::Error::SymlParse(e.to_string())), + } +} + +// Array and map types +fn item_statements(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| map(many0(item_statement(level)), Value::Array)(i) +} + +fn item_statement(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| { + let (i, _) = indent(level)(i)?; + let (i, _) = nom_char('-')(i)?; + let (i, _) = blankspace(i)?; + expression(level)(i) + } +} + +fn property_statements(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| { + let (i, properties) = many0(property_statement(level))(i)?; + let mut map = serde_json::Map::new(); + for (key, value) in properties.into_iter().flatten() { + map.insert(key, value); + } + Ok((i, Value::Object(map))) + } +} + +fn property_statement(level:usize) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { + move |i:&str| { + alt(( + value( + vec![], + tuple(( + opt(blankspace), + opt(pair(nom_char('#'), many1(pair(not(eol), anychar)))), + many1(eol_any), + )), + ), + map( + preceded(indent(level), separated_pair(name, wrapped_colon, expression(level))), + |entry| vec![entry], + ), + // legacy names + map( + preceded( + indent(level), + separated_pair(legacy_name, wrapped_colon, expression(level)), + ), + |entry| vec![entry], + ), + // legacy prop without colon + map( + preceded( + indent(level), + separated_pair( + legacy_name, + blankspace, + terminated(legacy_literal, many1(eol_any)), + ), + ), + |entry| vec![entry], + ), + multikey_property_statement(level), + ))(i) + } +} + +fn multikey_property_statement( + level:usize, +) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { + move |i:&str| { + let (i, ()) = indent(level)(i)?; + let (i, property) = legacy_name(i)?; + let (i, others) = many1(preceded( + delimited(opt(blankspace), nom_char(','), opt(blankspace)), + legacy_name, + ))(i)?; + let (i, _) = wrapped_colon(i)?; + let (i, value) = expression(level)(i)?; + + Ok(( + i, + std::iter::once(property) + .chain(others) + .map(|key| (key, value.clone())) + .collect(), + )) + } +} + +fn wrapped_colon(i:&str) -> IResult<&str, char> { + delimited(opt(blankspace), nom_char(':'), opt(blankspace))(i) +} + +fn expression(level:usize) -> impl Fn(&str) -> IResult<&str, Value> { + move |i:&str| { + alt(( + preceded( + tuple((peek(tuple((eol, indent(level + 1), nom_char('-'), blankspace))), eol_any)), + item_statements(level + 1), + ), + preceded(eol, property_statements(level + 1)), + terminated(literal, many1(eol_any)), + ))(i) + } +} + +fn indent(level:usize) -> impl Fn(&str) -> IResult<&str, ()> { + move |i:&str| { + let (i, _) = count(nom_char(' '), level * 2)(i)?; + Ok((i, ())) + } +} + +// Simple types + +fn name(i:&str) -> IResult<&str, String> { alt((string, pseudostring))(i) } + +fn legacy_name(i:&str) -> IResult<&str, String> { + alt((string, map(recognize(many1(pseudostring_legacy)), |s| s.to_string())))(i) +} + +fn literal(i:&str) -> IResult<&str, Value> { + alt(( + value(Value::Null, null), + map(boolean, Value::Bool), + map(string, Value::String), + map(pseudostring, Value::String), + ))(i) +} + +fn legacy_literal(i:&str) -> IResult<&str, Value> { + alt(( + value(Value::Null, null), + map(string, Value::String), + map(pseudostring_legacy, Value::String), + ))(i) +} + +fn pseudostring(i:&str) -> IResult<&str, String> { + let (i, pseudo) = recognize(pseudostring_inner)(i)?; + Ok((i, pseudostring_replace().replace_all(pseudo, "").into_owned())) +} + +fn pseudostring_inner(i:&str) -> IResult<&str, ()> { + let (i, _) = none_of("\r\n\t ?:,][{}#&*!|>'\"%@`-")(i)?; + let (i, _) = many0(tuple((opt(blankspace), none_of("\r\n\t ,][{}:#\"'"))))(i)?; + Ok((i, ())) +} + +fn pseudostring_legacy(i:&str) -> IResult<&str, String> { + let (i, pseudo) = recognize(pseudostring_legacy_inner)(i)?; + let replaced = pseudostring_replace().replace_all(pseudo, ""); + Ok((i, replaced.to_string())) +} + +fn pseudostring_legacy_inner(i:&str) -> IResult<&str, ()> { + let (i, _) = opt(tag("--"))(i)?; + let (i, _) = satisfy(|c| c.is_ascii_alphanumeric() || c == '/')(i)?; + let (i, _) = take_till(|c| "\r\n\t :,".contains(c))(i)?; + Ok((i, ())) +} + +// String parsing + +fn null(i:&str) -> IResult<&str, &str> { tag("null")(i) } + +fn boolean(i:&str) -> IResult<&str, bool> { + alt((value(true, tag("true")), value(false, tag("false"))))(i) +} + +fn string(i:&str) -> IResult<&str, String> { + alt((empty_string, delimited(tag("\""), syml_chars, tag("\""))))(i) +} + +fn empty_string(i:&str) -> IResult<&str, String> { + let (i, _) = tag(r#""""#)(i)?; + Ok((i, "".to_string())) +} + +fn syml_chars(i:&str) -> IResult<&str, String> { + // The SYML grammar provided by Yarn2+ includes escape sequences that weren't + // supported by the yarn1 parser. We diverge from the Yarn2+ provided + // grammar to match the actual parser used by yarn1. + escaped_transform( + is_not("\"\\"), + '\\', + alt(( + value("\"", tag("\"")), + value("\\", tag("\\")), + value("/", tag("/")), + value("\n", tag("n")), + value("\r", tag("r")), + value("\t", tag("t")), + )), + )(i) +} + +// Spaces +fn blankspace(i:&str) -> IResult<&str, &str> { space1(i) } + +fn eol_any(i:&str) -> IResult<&str, &str> { + recognize(tuple((eol, many0(tuple((opt(blankspace), eol))))))(i) +} + +fn eol(i:&str) -> IResult<&str, &str> { + alt((crlf, value("\n", newline), value("\r", nom_char('\r'))))(i) +} + +#[cfg(test)] +mod test { + use serde_json::json; + use test_case::test_case; + + use super::*; + + #[test_case("null", Value::Null ; "null")] + #[test_case("false", Value::Bool(false) ; "literal false")] + #[test_case("true", Value::Bool(true) ; "literal true")] + #[test_case("\"\"", Value::String("".into()) ; "empty string literal")] + #[test_case("\"foo\"", Value::String("foo".into()) ; "quoted string literal")] + #[test_case("foo", Value::String("foo".into()) ; "unquoted string literal")] + fn test_literal(input:&str, expected:Value) { + let (_, actual) = literal(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("name: foo", "name" ; "basic")] + #[test_case("technically a name: foo", "technically a name" ; "multiword name")] + fn test_name(input:&str, expected:&str) { + let (_, actual) = name(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("foo@1:", "foo@1" ; "name with colon terminator")] + #[test_case("\"foo@1\":", "foo@1" ; "qutoed name with colon terminator")] + #[test_case("name foo", "name" ; "name without colon terminator")] + fn test_legacy_name(input:&str, expected:&str) { + let (_, actual) = legacy_name(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("null\n", Value::Null ; "null")] + #[test_case("\"foo\"\n", json!("foo") ; "basic string")] + #[test_case("\n name: foo\n", json!({ "name": "foo" }) ; "basic object")] + fn test_expression(input:&str, expected:Value) { + let (_, actual) = expression(0)(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("# a comment\n", vec![] ; "comment")] + #[test_case("foo: null\n", vec![("foo".into(), Value::Null)] ; "single property")] + #[test_case("name foo\n", vec![("name".into(), json!("foo"))] ; "legacy property")] + fn test_property_statement(input:&str, expected:Vec<(String, Value)>) { + let (_, actual) = property_statement(0)(input).unwrap(); + assert_eq!(actual, expected); + } + + #[test_case("name: foo\n", json!({"name": "foo"}) ; "single property object")] + #[test_case("\"name\": foo\n", json!({"name": "foo"}) ; "single quoted property object")] + #[test_case("name foo\n", json!({"name": "foo"}) ; "single property without colon object")] + #[test_case("# comment\nname: foo\n", json!({"name": "foo"}) ; "comment doesn't affect object")] + #[test_case("name foo\nversion \"1.2.3\"\n", json!({"name": "foo", "version": "1.2.3"}) ; "multi-property object")] + #[test_case("foo:\n version \"1.2.3\"\n", json!({"foo": {"version": "1.2.3"}}) ; "nested object")] + #[test_case("foo, bar, baz:\n version \"1.2.3\"\n", json!({ + "foo": {"version": "1.2.3"}, + "bar": {"version": "1.2.3"}, + "baz": {"version": "1.2.3"}, + }) ; "multi-key object")] + fn test_property_statements(input:&str, expected:Value) { + let (_, actual) = property_statements(0)(input).unwrap(); + assert_eq!(actual, expected); + } +} diff --git a/crates/turborepo-lockfiles/src/yarn1/mod.rs b/crates/turborepo-lockfiles/Source/yarn1/mod.rs similarity index 100% rename from crates/turborepo-lockfiles/src/yarn1/mod.rs rename to crates/turborepo-lockfiles/Source/yarn1/mod.rs diff --git a/crates/turborepo-lockfiles/src/yarn1/ser.rs b/crates/turborepo-lockfiles/Source/yarn1/ser.rs similarity index 100% rename from crates/turborepo-lockfiles/src/yarn1/ser.rs rename to crates/turborepo-lockfiles/Source/yarn1/ser.rs diff --git a/crates/turborepo-lockfiles/examples/berry_resolutions.rs b/crates/turborepo-lockfiles/examples/berry_resolutions.rs index 9d510d8d38a5f..3bf1b462fd1c9 100644 --- a/crates/turborepo-lockfiles/examples/berry_resolutions.rs +++ b/crates/turborepo-lockfiles/examples/berry_resolutions.rs @@ -1,33 +1,33 @@ use turborepo_lockfiles::{BerryLockfile, BerryManifest, Lockfile, LockfileData}; fn main() { - let manifest = generate_manifest("foobar", 100); - let lockfile_bytes = include_bytes!("yarn.lock"); - let data = LockfileData::from_bytes(lockfile_bytes.as_slice()).unwrap(); - let lockfile = BerryLockfile::new(data, Some(manifest)).unwrap(); - let key = "debug@npm:3.2.7"; - println!( - "Dependencies of {key}: {}", - lockfile - .all_dependencies(key) - .unwrap() - .unwrap() - .into_iter() - .map(|(k, v)| format!("{k}@{v}")) - .collect::>() - .join(", ") - ); + let manifest = generate_manifest("foobar", 100); + let lockfile_bytes = include_bytes!("yarn.lock"); + let data = LockfileData::from_bytes(lockfile_bytes.as_slice()).unwrap(); + let lockfile = BerryLockfile::new(data, Some(manifest)).unwrap(); + let key = "debug@npm:3.2.7"; + println!( + "Dependencies of {key}: {}", + lockfile + .all_dependencies(key) + .unwrap() + .unwrap() + .into_iter() + .map(|(k, v)| format!("{k}@{v}")) + .collect::>() + .join(", ") + ); } -fn generate_manifest(prefix: &str, size: usize) -> BerryManifest { - let mut count = 0; - BerryManifest::with_resolutions(std::iter::from_fn(move || { - let cont = count < size; - count += 1; - if cont { - Some((format!("{prefix}{count}"), "1.0.0".to_string())) - } else { - None - } - })) +fn generate_manifest(prefix:&str, size:usize) -> BerryManifest { + let mut count = 0; + BerryManifest::with_resolutions(std::iter::from_fn(move || { + let cont = count < size; + count += 1; + if cont { + Some((format!("{prefix}{count}"), "1.0.0".to_string())) + } else { + None + } + })) } diff --git a/crates/turborepo-lockfiles/examples/yarn.lock b/crates/turborepo-lockfiles/examples/yarn.lock deleted file mode 100644 index edfb00578c99c..0000000000000 --- a/crates/turborepo-lockfiles/examples/yarn.lock +++ /dev/null @@ -1,4375 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"@aashutoshrathi/word-wrap@npm:^1.2.3": - version: 1.2.6 - resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" - checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd - languageName: node - linkType: hard - -"@babel/code-frame@npm:7.12.11": - version: 7.12.11 - resolution: "@babel/code-frame@npm:7.12.11" - dependencies: - "@babel/highlight": ^7.10.4 - checksum: 3963eff3ebfb0e091c7e6f99596ef4b258683e4ba8a134e4e95f77afe85be5c931e184fff6435fb4885d12eba04a5e25532f7fbc292ca13b48e7da943474e2f3 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-validator-identifier@npm:7.22.5" - checksum: 7f0f30113474a28298c12161763b49de5018732290ca4de13cdaefd4fd0d635a6fe3f6686c37a02905fb1e64f21a5ee2b55140cf7b070e729f1bd66866506aea - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.10.4": - version: 7.22.5 - resolution: "@babel/highlight@npm:7.22.5" - dependencies: - "@babel/helper-validator-identifier": ^7.22.5 - chalk: ^2.0.0 - js-tokens: ^4.0.0 - checksum: f61ae6de6ee0ea8d9b5bcf2a532faec5ab0a1dc0f7c640e5047fc61630a0edb88b18d8c92eb06566d30da7a27db841aca11820ecd3ebe9ce514c9350fbed39c4 - languageName: node - linkType: hard - -"@babel/runtime-corejs3@npm:^7.9.2": - version: 7.22.5 - resolution: "@babel/runtime-corejs3@npm:7.22.5" - dependencies: - core-js-pure: ^3.30.2 - regenerator-runtime: ^0.13.11 - checksum: cdeabaa6858cedb0ec47c1245195a09a8fd2de06f4545614acb574d150a81d0e27eb9c08d69787b2c1ad4a1fc57919a3f0599f60d14914227c200563cd595503 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.20.7": - version: 7.22.5 - resolution: "@babel/runtime@npm:7.22.5" - dependencies: - regenerator-runtime: ^0.13.11 - checksum: 12a50b7de2531beef38840d17af50c55a094253697600cee255311222390c68eed704829308d4fd305e1b3dfbce113272e428e9d9d45b1730e0fede997eaceb1 - languageName: node - linkType: hard - -"@cspotcode/source-map-support@npm:^0.8.0": - version: 0.8.1 - resolution: "@cspotcode/source-map-support@npm:0.8.1" - dependencies: - "@jridgewell/trace-mapping": 0.3.9 - checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa - languageName: node - linkType: hard - -"@eslint/eslintrc@npm:^0.4.3": - version: 0.4.3 - resolution: "@eslint/eslintrc@npm:0.4.3" - dependencies: - ajv: ^6.12.4 - debug: ^4.1.1 - espree: ^7.3.0 - globals: ^13.9.0 - ignore: ^4.0.6 - import-fresh: ^3.2.1 - js-yaml: ^3.13.1 - minimatch: ^3.0.4 - strip-json-comments: ^3.1.1 - checksum: 03a7704150b868c318aab6a94d87a33d30dc2ec579d27374575014f06237ba1370ae11178db772f985ef680d469dc237e7b16a1c5d8edaaeb8c3733e7a95a6d3 - languageName: node - linkType: hard - -"@humanwhocodes/config-array@npm:^0.5.0": - version: 0.5.0 - resolution: "@humanwhocodes/config-array@npm:0.5.0" - dependencies: - "@humanwhocodes/object-schema": ^1.2.0 - debug: ^4.1.1 - minimatch: ^3.0.4 - checksum: 44ee6a9f05d93dd9d5935a006b17572328ba9caff8002442f601736cbda79c580cc0f5a49ce9eb88fbacc5c3a6b62098357c2e95326cd17bb9f1a6c61d6e95e7 - languageName: node - linkType: hard - -"@humanwhocodes/object-schema@npm:^1.2.0": - version: 1.2.1 - resolution: "@humanwhocodes/object-schema@npm:1.2.1" - checksum: a824a1ec31591231e4bad5787641f59e9633827d0a2eaae131a288d33c9ef0290bd16fda8da6f7c0fcb014147865d12118df10db57f27f41e20da92369fcb3f1 - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:0.3.9": - version: 0.3.9 - resolution: "@jridgewell/trace-mapping@npm:0.3.9" - dependencies: - "@jridgewell/resolve-uri": ^3.0.3 - "@jridgewell/sourcemap-codec": ^1.4.10 - checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef - languageName: node - linkType: hard - -"@next/env@npm:13.4.7": - version: 13.4.7 - resolution: "@next/env@npm:13.4.7" - checksum: 5a2bba68fb8c80c87324025f10af7fe7319efdb15777247bfa8ff58e61bcc19b150bce4068396351e6c6df3344294cc06c03a2fb1bb0330659d230830a202c53 - languageName: node - linkType: hard - -"@next/eslint-plugin-next@npm:13.4.7": - version: 13.4.7 - resolution: "@next/eslint-plugin-next@npm:13.4.7" - dependencies: - glob: 7.1.7 - checksum: 7c9d6d3a44355dfda06982057a309502284add7d9e7a375782e24551f8faab726b7d4d260a053182f536f0928bf5b9c26b81267c437dc3e716a7acd70fd5b1a3 - languageName: node - linkType: hard - -"@next/swc-darwin-arm64@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-darwin-arm64@npm:13.4.7" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-darwin-x64@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-darwin-x64@npm:13.4.7" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@next/swc-linux-arm64-gnu@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-linux-arm64-gnu@npm:13.4.7" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-arm64-musl@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-linux-arm64-musl@npm:13.4.7" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-linux-x64-gnu@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-linux-x64-gnu@npm:13.4.7" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-x64-musl@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-linux-x64-musl@npm:13.4.7" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-win32-arm64-msvc@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-win32-arm64-msvc@npm:13.4.7" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-win32-ia32-msvc@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-win32-ia32-msvc@npm:13.4.7" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@next/swc-win32-x64-msvc@npm:13.4.7": - version: 13.4.7 - resolution: "@next/swc-win32-x64-msvc@npm:13.4.7" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@nodelib/fs.scandir@npm:2.1.5": - version: 2.1.5 - resolution: "@nodelib/fs.scandir@npm:2.1.5" - dependencies: - "@nodelib/fs.stat": 2.0.5 - run-parallel: ^1.1.9 - checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 - languageName: node - linkType: hard - -"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.5 - resolution: "@nodelib/fs.stat@npm:2.0.5" - checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 - languageName: node - linkType: hard - -"@nodelib/fs.walk@npm:^1.2.3": - version: 1.2.8 - resolution: "@nodelib/fs.walk@npm:1.2.8" - dependencies: - "@nodelib/fs.scandir": 2.1.5 - fastq: ^1.6.0 - checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 - languageName: node - linkType: hard - -"@pkgr/utils@npm:^2.3.1": - version: 2.4.1 - resolution: "@pkgr/utils@npm:2.4.1" - dependencies: - cross-spawn: ^7.0.3 - fast-glob: ^3.2.12 - is-glob: ^4.0.3 - open: ^9.1.0 - picocolors: ^1.0.0 - tslib: ^2.5.0 - checksum: 654682860272541a40485b01e0763b155ec31faeba85b2c51e38b59c4ff1f8918c37b87b5ecbda3ff482d8486eba086e92b991fe4a8ed62efbbbdf83c0f64409 - languageName: node - linkType: hard - -"@rushstack/eslint-patch@npm:^1.1.3": - version: 1.3.2 - resolution: "@rushstack/eslint-patch@npm:1.3.2" - checksum: 010c87ef2d901faaaf70ea1bf86fd3e7b74f24e23205f836e9a32790bca2076afe5de58ded03c35cb482f83691c8d22b1a0c34291b075bfe81afd26cfa5d14cc - languageName: node - linkType: hard - -"@swc/helpers@npm:0.5.1": - version: 0.5.1 - resolution: "@swc/helpers@npm:0.5.1" - dependencies: - tslib: ^2.4.0 - checksum: 71e0e27234590435e4c62b97ef5e796f88e786841a38c7116a5e27a3eafa7b9ead7cdec5249b32165902076de78446945311c973e59bddf77c1e24f33a8f272a - languageName: node - linkType: hard - -"@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df - languageName: node - linkType: hard - -"@tsconfig/node12@npm:^1.0.7": - version: 1.0.11 - resolution: "@tsconfig/node12@npm:1.0.11" - checksum: 5ce29a41b13e7897a58b8e2df11269c5395999e588b9a467386f99d1d26f6c77d1af2719e407621412520ea30517d718d5192a32403b8dfcc163bf33e40a338a - languageName: node - linkType: hard - -"@tsconfig/node14@npm:^1.0.0": - version: 1.0.3 - resolution: "@tsconfig/node14@npm:1.0.3" - checksum: 19275fe80c4c8d0ad0abed6a96dbf00642e88b220b090418609c4376e1cef81bf16237bf170ad1b341452feddb8115d8dd2e5acdfdea1b27422071163dc9ba9d - languageName: node - linkType: hard - -"@tsconfig/node16@npm:^1.0.2": - version: 1.0.4 - resolution: "@tsconfig/node16@npm:1.0.4" - checksum: 202319785901f942a6e1e476b872d421baec20cf09f4b266a1854060efbf78cde16a4d256e8bc949d31e6cd9a90f1e8ef8fb06af96a65e98338a2b6b0de0a0ff - languageName: node - linkType: hard - -"@turbo/gen@npm:^1.9.7": - version: 1.10.6 - resolution: "@turbo/gen@npm:1.10.6" - dependencies: - chalk: 2.4.2 - commander: ^10.0.0 - fs-extra: ^10.1.0 - inquirer: ^8.2.4 - minimatch: ^9.0.0 - node-plop: ^0.26.3 - semver: ^7.3.8 - ts-node: ^10.9.1 - update-check: ^1.5.4 - validate-npm-package-name: ^5.0.0 - bin: - gen: dist/cli.js - checksum: 458e5f48ce0b123ebc5b00e1ba19b3692ef07f47d8e2fbceba82f31c6bd8df40dfd9f49ed07335f560cef08469c9992778d6d14cee9eabfe4c9547fbfd335629 - languageName: node - linkType: hard - -"@types/glob@npm:^7.1.1": - version: 7.2.0 - resolution: "@types/glob@npm:7.2.0" - dependencies: - "@types/minimatch": "*" - "@types/node": "*" - checksum: 6ae717fedfdfdad25f3d5a568323926c64f52ef35897bcac8aca8e19bc50c0bd84630bbd063e5d52078b2137d8e7d3c26eabebd1a2f03ff350fff8a91e79fc19 - languageName: node - linkType: hard - -"@types/inquirer@npm:^6.5.0": - version: 6.5.0 - resolution: "@types/inquirer@npm:6.5.0" - dependencies: - "@types/through": "*" - rxjs: ^6.4.0 - checksum: d7da3ccc8efb6c5d40fc0c077cea4e4c26637693841ae32ba16c63195cac114654a644e5cd77343ddbc0aeab710157a3df15db72d2d32470eedc87e4b163b08c - languageName: node - linkType: hard - -"@types/json5@npm:^0.0.29": - version: 0.0.29 - resolution: "@types/json5@npm:0.0.29" - checksum: e60b153664572116dfea673c5bda7778dbff150498f44f998e34b5886d8afc47f16799280e4b6e241c0472aef1bc36add771c569c68fc5125fc2ae519a3eb9ac - languageName: node - linkType: hard - -"@types/minimatch@npm:*": - version: 5.1.2 - resolution: "@types/minimatch@npm:5.1.2" - checksum: 0391a282860c7cb6fe262c12b99564732401bdaa5e395bee9ca323c312c1a0f45efbf34dce974682036e857db59a5c9b1da522f3d6055aeead7097264c8705a8 - languageName: node - linkType: hard - -"@types/node@npm:*": - version: 20.3.2 - resolution: "@types/node@npm:20.3.2" - checksum: 5929ce2b9b12b1e2a2304a0921a953c72a81f5753ad39ac43b99ce6312fbb2b4fb5bc6b60d64a2550704e3223cd5de1299467d36085ac69888899db978f2653a - languageName: node - linkType: hard - -"@types/node@npm:^17.0.12": - version: 17.0.45 - resolution: "@types/node@npm:17.0.45" - checksum: aa04366b9103b7d6cfd6b2ef64182e0eaa7d4462c3f817618486ea0422984c51fc69fd0d436eae6c9e696ddfdbec9ccaa27a917f7c2e8c75c5d57827fe3d95e8 - languageName: node - linkType: hard - -"@types/prop-types@npm:*": - version: 15.7.5 - resolution: "@types/prop-types@npm:15.7.5" - checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 - languageName: node - linkType: hard - -"@types/react-dom@npm:^18.0.7, @types/react-dom@npm:^18.2.0": - version: 18.2.6 - resolution: "@types/react-dom@npm:18.2.6" - dependencies: - "@types/react": "*" - checksum: b56e42efab121a3a8013d2eb8c1688e6028a25ea6d33c4362d2846f0af3760b164b4d7c34846614024cfb8956cca70dd1743487f152e32ff89a00fe6fbd2be54 - languageName: node - linkType: hard - -"@types/react@npm:*, @types/react@npm:^18.0.22, @types/react@npm:^18.2.0": - version: 18.2.14 - resolution: "@types/react@npm:18.2.14" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: a6a5e8cc78f486b9020d1ad009aa6c56943c68c7c6376e0f8399e9cbcd950b7b8f5d73f00200f5379f5e58d31d57d8aed24357f301d8e86108cd438ce6c8b3dd - languageName: node - linkType: hard - -"@types/scheduler@npm:*": - version: 0.16.3 - resolution: "@types/scheduler@npm:0.16.3" - checksum: 2b0aec39c24268e3ce938c5db2f2e77f5c3dd280e05c262d9c2fe7d890929e4632a6b8e94334017b66b45e4f92a5aa42ba3356640c2a1175fa37bef2f5200767 - languageName: node - linkType: hard - -"@types/through@npm:*": - version: 0.0.30 - resolution: "@types/through@npm:0.0.30" - dependencies: - "@types/node": "*" - checksum: 9578470db0b527c26e246a1220ae9bffc6bf47f20f89c54aac467c083ab1f7e16c00d9a7b4bb6cb4e2dfae465027270827e5908a6236063f6214625e50585d78 - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^5.42.0": - version: 5.60.1 - resolution: "@typescript-eslint/parser@npm:5.60.1" - dependencies: - "@typescript-eslint/scope-manager": 5.60.1 - "@typescript-eslint/types": 5.60.1 - "@typescript-eslint/typescript-estree": 5.60.1 - debug: ^4.3.4 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 08f1552ab0da178524a8de3654d2fb7c8ecb9efdad8e771c9cbf4af555c42e77d17b2c182d139a531cc76c3cabd091d1d25024c2c215cb809dca8b147c8a493c - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:5.60.1": - version: 5.60.1 - resolution: "@typescript-eslint/scope-manager@npm:5.60.1" - dependencies: - "@typescript-eslint/types": 5.60.1 - "@typescript-eslint/visitor-keys": 5.60.1 - checksum: 32c0786123f12fbb861aba3527471134a2e9978c7f712e0d7650080651870903482aed72a55f81deba9493118c1ca3c57edaaaa75d7acd9892818e3e9cc341ef - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.60.1": - version: 5.60.1 - resolution: "@typescript-eslint/types@npm:5.60.1" - checksum: 766b6c857493b72a8f515e6a8e409476a317b7a7f0401fbcdf18f417839fca004dcaf06f58eb5ba00777e3ca9c68cd2f56fda79f3a8eb8a418095b5b1f625712 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.60.1": - version: 5.60.1 - resolution: "@typescript-eslint/typescript-estree@npm:5.60.1" - dependencies: - "@typescript-eslint/types": 5.60.1 - "@typescript-eslint/visitor-keys": 5.60.1 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.3.7 - tsutils: ^3.21.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 5bb9d08c3cbc303fc64647878cae37283c4cfa9e3ed00da02ee25dc2e46798a1ad6964c9f04086f0134716671357e6569a65ea0ae75f0f3ff94ae67666385c6f - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.60.1": - version: 5.60.1 - resolution: "@typescript-eslint/visitor-keys@npm:5.60.1" - dependencies: - "@typescript-eslint/types": 5.60.1 - eslint-visitor-keys: ^3.3.0 - checksum: 137f6a6f8efb398969087147b59f99f7d0deed044d89d7efce3631bb90bc32e3a13a5cee6a65e1c9830862c5c4402ac1a9b2c9e31fe46d1716602af2813bffae - languageName: node - linkType: hard - -"acorn-jsx@npm:^5.3.1": - version: 5.3.2 - resolution: "acorn-jsx@npm:5.3.2" - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 - languageName: node - linkType: hard - -"acorn-walk@npm:^8.1.1": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 - languageName: node - linkType: hard - -"acorn@npm:^7.4.0": - version: 7.4.1 - resolution: "acorn@npm:7.4.1" - bin: - acorn: bin/acorn - checksum: 1860f23c2107c910c6177b7b7be71be350db9e1080d814493fae143ae37605189504152d1ba8743ba3178d0b37269ce1ffc42b101547fdc1827078f82671e407 - languageName: node - linkType: hard - -"acorn@npm:^8.4.1": - version: 8.9.0 - resolution: "acorn@npm:8.9.0" - bin: - acorn: bin/acorn - checksum: 25dfb94952386ecfb847e61934de04a4e7c2dc21c2e700fc4e2ef27ce78cb717700c4c4f279cd630bb4774948633c3859fc16063ec8573bda4568e0a312e6744 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: ^2.0.0 - indent-string: ^4.0.0 - checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 - languageName: node - linkType: hard - -"ajv@npm:^6.10.0, ajv@npm:^6.12.4": - version: 6.12.6 - resolution: "ajv@npm:6.12.6" - dependencies: - fast-deep-equal: ^3.1.1 - fast-json-stable-stringify: ^2.0.0 - json-schema-traverse: ^0.4.1 - uri-js: ^4.2.2 - checksum: 874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 - languageName: node - linkType: hard - -"ajv@npm:^8.0.1": - version: 8.12.0 - resolution: "ajv@npm:8.12.0" - dependencies: - fast-deep-equal: ^3.1.1 - json-schema-traverse: ^1.0.0 - require-from-string: ^2.0.2 - uri-js: ^4.2.2 - checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 - languageName: node - linkType: hard - -"ansi-colors@npm:^4.1.1": - version: 4.1.3 - resolution: "ansi-colors@npm:4.1.3" - checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e - languageName: node - linkType: hard - -"ansi-escapes@npm:^4.2.1": - version: 4.3.2 - resolution: "ansi-escapes@npm:4.3.2" - dependencies: - type-fest: ^0.21.3 - checksum: 93111c42189c0a6bed9cdb4d7f2829548e943827ee8479c74d6e0b22ee127b2a21d3f8b5ca57723b8ef78ce011fbfc2784350eb2bde3ccfccf2f575fa8489815 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b - languageName: node - linkType: hard - -"ansi-styles@npm:^3.2.1": - version: 3.2.1 - resolution: "ansi-styles@npm:3.2.1" - dependencies: - color-convert: ^1.9.0 - checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: ^2.0.1 - checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 - languageName: node - linkType: hard - -"arg@npm:^4.1.0": - version: 4.1.3 - resolution: "arg@npm:4.1.3" - checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 - languageName: node - linkType: hard - -"argparse@npm:^1.0.7": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: ~1.0.2 - checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 - languageName: node - linkType: hard - -"aria-query@npm:^5.1.3": - version: 5.3.0 - resolution: "aria-query@npm:5.3.0" - dependencies: - dequal: ^2.0.3 - checksum: 305bd73c76756117b59aba121d08f413c7ff5e80fa1b98e217a3443fcddb9a232ee790e24e432b59ae7625aebcf4c47cb01c2cac872994f0b426f5bdfcd96ba9 - languageName: node - linkType: hard - -"array-buffer-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "array-buffer-byte-length@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - is-array-buffer: ^3.0.1 - checksum: 044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 - languageName: node - linkType: hard - -"array-includes@npm:^3.1.4, array-includes@npm:^3.1.6": - version: 3.1.6 - resolution: "array-includes@npm:3.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - get-intrinsic: ^1.1.3 - is-string: ^1.0.7 - checksum: f22f8cd8ba8a6448d91eebdc69f04e4e55085d09232b5216ee2d476dab3ef59984e8d1889e662c6a0ed939dcb1b57fd05b2c0209c3370942fc41b752c82a2ca5 - languageName: node - linkType: hard - -"array-union@npm:^2.1.0": - version: 2.1.0 - resolution: "array-union@npm:2.1.0" - checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d - languageName: node - linkType: hard - -"array.prototype.flat@npm:^1.3.1": - version: 1.3.1 - resolution: "array.prototype.flat@npm:1.3.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - checksum: 5a8415949df79bf6e01afd7e8839bbde5a3581300e8ad5d8449dea52639e9e59b26a467665622783697917b43bf39940a6e621877c7dd9b3d1c1f97484b9b88b - languageName: node - linkType: hard - -"array.prototype.flatmap@npm:^1.2.5, array.prototype.flatmap@npm:^1.3.1": - version: 1.3.1 - resolution: "array.prototype.flatmap@npm:1.3.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - checksum: 8c1c43a4995f12cf12523436da28515184c753807b3f0bc2ca6c075f71c470b099e2090cc67dba8e5280958fea401c1d0c59e1db0143272aef6cd1103921a987 - languageName: node - linkType: hard - -"array.prototype.tosorted@npm:^1.1.1": - version: 1.1.1 - resolution: "array.prototype.tosorted@npm:1.1.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.1.3 - checksum: 7923324a67e70a2fc0a6e40237405d92395e45ebd76f5cb89c2a5cf1e66b47aca6baacd0cd628ffd88830b90d47fff268071493d09c9ae123645613dac2c2ca3 - languageName: node - linkType: hard - -"ast-types-flow@npm:^0.0.7": - version: 0.0.7 - resolution: "ast-types-flow@npm:0.0.7" - checksum: a26dcc2182ffee111cad7c471759b0bda22d3b7ebacf27c348b22c55f16896b18ab0a4d03b85b4020dce7f3e634b8f00b593888f622915096ea1927fa51866c4 - languageName: node - linkType: hard - -"astral-regex@npm:^2.0.0": - version: 2.0.0 - resolution: "astral-regex@npm:2.0.0" - checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 - languageName: node - linkType: hard - -"available-typed-arrays@npm:^1.0.5": - version: 1.0.5 - resolution: "available-typed-arrays@npm:1.0.5" - checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a - languageName: node - linkType: hard - -"axe-core@npm:^4.6.2": - version: 4.7.2 - resolution: "axe-core@npm:4.7.2" - checksum: 5d86fa0f45213b0e54cbb5d713ce885c4a8fe3a72b92dd915a47aa396d6fd149c4a87fec53aa978511f6d941402256cfeb26f2db35129e370f25a453c688655a - languageName: node - linkType: hard - -"axobject-query@npm:^3.1.1": - version: 3.2.1 - resolution: "axobject-query@npm:3.2.1" - dependencies: - dequal: ^2.0.3 - checksum: a94047e702b57c91680e6a952ec4a1aaa2cfd0d80ead76bc8c954202980d8c51968a6ea18b4d8010e8e2cf95676533d8022a8ebba9abc1dfe25686721df26fd2 - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 - languageName: node - linkType: hard - -"base64-js@npm:^1.3.1": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 - languageName: node - linkType: hard - -"berry@workspace:.": - version: 0.0.0-use.local - resolution: "berry@workspace:." - dependencies: - "@turbo/gen": ^1.9.7 - eslint: ^7.32.0 - eslint-config-custom: "*" - prettier: ^2.5.1 - turbo: latest - languageName: unknown - linkType: soft - -"big-integer@npm:^1.6.44": - version: 1.6.51 - resolution: "big-integer@npm:1.6.51" - checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518 - languageName: node - linkType: hard - -"bl@npm:^4.1.0": - version: 4.1.0 - resolution: "bl@npm:4.1.0" - dependencies: - buffer: ^5.5.0 - inherits: ^2.0.4 - readable-stream: ^3.4.0 - checksum: 9e8521fa7e83aa9427c6f8ccdcba6e8167ef30cc9a22df26effcc5ab682ef91d2cbc23a239f945d099289e4bbcfae7a192e9c28c84c6202e710a0dfec3722662 - languageName: node - linkType: hard - -"bplist-parser@npm:^0.2.0": - version: 0.2.0 - resolution: "bplist-parser@npm:0.2.0" - dependencies: - big-integer: ^1.6.44 - checksum: d5339dd16afc51de6c88f88f58a45b72ed6a06aa31f5557d09877575f220b7c1d3fbe375da0b62e6a10d4b8ed80523567e351f24014f5bc886ad523758142cdd - languageName: node - linkType: hard - -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: ^1.0.0 - concat-map: 0.0.1 - checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: ^1.0.0 - checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 - languageName: node - linkType: hard - -"braces@npm:^3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" - dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 - languageName: node - linkType: hard - -"buffer@npm:^5.5.0": - version: 5.7.1 - resolution: "buffer@npm:5.7.1" - dependencies: - base64-js: ^1.3.1 - ieee754: ^1.1.13 - checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 - languageName: node - linkType: hard - -"builtins@npm:^5.0.0": - version: 5.0.1 - resolution: "builtins@npm:5.0.1" - dependencies: - semver: ^7.0.0 - checksum: 66d204657fe36522822a95b288943ad11b58f5eaede235b11d8c4edaa28ce4800087d44a2681524c340494aadb120a0068011acabe99d30e8f11a7d826d83515 - languageName: node - linkType: hard - -"bundle-name@npm:^3.0.0": - version: 3.0.0 - resolution: "bundle-name@npm:3.0.0" - dependencies: - run-applescript: ^5.0.0 - checksum: edf2b1fbe6096ed32e7566947ace2ea937ee427391744d7510a2880c4b9a5b3543d3f6c551236a29e5c87d3195f8e2912516290e638c15bcbede7b37cc375615 - languageName: node - linkType: hard - -"busboy@npm:1.6.0": - version: 1.6.0 - resolution: "busboy@npm:1.6.0" - dependencies: - streamsearch: ^1.1.0 - checksum: 32801e2c0164e12106bf236291a00795c3c4e4b709ae02132883fe8478ba2ae23743b11c5735a0aae8afe65ac4b6ca4568b91f0d9fed1fdbc32ede824a73746e - languageName: node - linkType: hard - -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind@npm:1.0.2" - dependencies: - function-bind: ^1.1.1 - get-intrinsic: ^1.0.2 - checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 - languageName: node - linkType: hard - -"callsites@npm:^3.0.0": - version: 3.1.0 - resolution: "callsites@npm:3.1.0" - checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 - languageName: node - linkType: hard - -"camel-case@npm:^3.0.0": - version: 3.0.0 - resolution: "camel-case@npm:3.0.0" - dependencies: - no-case: ^2.2.0 - upper-case: ^1.1.1 - checksum: 4190ed6ab8acf4f3f6e1a78ad4d0f3f15ce717b6bfa1b5686d58e4bcd29960f6e312dd746b5fa259c6d452f1413caef25aee2e10c9b9a580ac83e516533a961a - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001406": - version: 1.0.30001509 - resolution: "caniuse-lite@npm:1.0.30001509" - checksum: b08a98bf884182741d015569173162e5dfb804da22a14cb18c052be6b5f04e32312ff849b31f787b85091d1b1dfd58b128d9878c96e3bb632a1a0a8761548407 - languageName: node - linkType: hard - -"chalk@npm:2.4.2, chalk@npm:^2.0.0": - version: 2.4.2 - resolution: "chalk@npm:2.4.2" - dependencies: - ansi-styles: ^3.2.1 - escape-string-regexp: ^1.0.5 - supports-color: ^5.3.0 - checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 - languageName: node - linkType: hard - -"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.1": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc - languageName: node - linkType: hard - -"change-case@npm:^3.1.0": - version: 3.1.0 - resolution: "change-case@npm:3.1.0" - dependencies: - camel-case: ^3.0.0 - constant-case: ^2.0.0 - dot-case: ^2.1.0 - header-case: ^1.0.0 - is-lower-case: ^1.1.0 - is-upper-case: ^1.1.0 - lower-case: ^1.1.1 - lower-case-first: ^1.0.0 - no-case: ^2.3.2 - param-case: ^2.1.0 - pascal-case: ^2.0.0 - path-case: ^2.1.0 - sentence-case: ^2.1.0 - snake-case: ^2.1.0 - swap-case: ^1.1.0 - title-case: ^2.1.0 - upper-case: ^1.1.1 - upper-case-first: ^1.1.0 - checksum: d6f9f90a5f1d2a98294e06ea62f913fa0d7cfc289f188bf05662344da6128f5710b5c99ece83682c6a848db8d996b7348e09b2235dc3363afb6ae7142e7978e1 - languageName: node - linkType: hard - -"chardet@npm:^0.7.0": - version: 0.7.0 - resolution: "chardet@npm:0.7.0" - checksum: 6fd5da1f5d18ff5712c1e0aed41da200d7c51c28f11b36ee3c7b483f3696dabc08927fc6b227735eb8f0e1215c9a8abd8154637f3eff8cada5959df7f58b024d - languageName: node - linkType: hard - -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 - languageName: node - linkType: hard - -"cli-cursor@npm:^3.1.0": - version: 3.1.0 - resolution: "cli-cursor@npm:3.1.0" - dependencies: - restore-cursor: ^3.1.0 - checksum: 2692784c6cd2fd85cfdbd11f53aea73a463a6d64a77c3e098b2b4697a20443f430c220629e1ca3b195ea5ac4a97a74c2ee411f3807abf6df2b66211fec0c0a29 - languageName: node - linkType: hard - -"cli-spinners@npm:^2.5.0": - version: 2.9.0 - resolution: "cli-spinners@npm:2.9.0" - checksum: a9c56e1f44457d4a9f4f535364e729cb8726198efa9e98990cfd9eda9e220dfa4ba12f92808d1be5e29029cdfead781db82dc8549b97b31c907d55f96aa9b0e2 - languageName: node - linkType: hard - -"cli-width@npm:^3.0.0": - version: 3.0.0 - resolution: "cli-width@npm:3.0.0" - checksum: 4c94af3769367a70e11ed69aa6095f1c600c0ff510f3921ab4045af961820d57c0233acfa8b6396037391f31b4c397e1f614d234294f979ff61430a6c166c3f6 - languageName: node - linkType: hard - -"client-only@npm:0.0.1": - version: 0.0.1 - resolution: "client-only@npm:0.0.1" - checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8 - languageName: node - linkType: hard - -"clone@npm:^1.0.2": - version: 1.0.4 - resolution: "clone@npm:1.0.4" - checksum: d06418b7335897209e77bdd430d04f882189582e67bd1f75a04565f3f07f5b3f119a9d670c943b6697d0afb100f03b866b3b8a1f91d4d02d72c4ecf2bb64b5dd - languageName: node - linkType: hard - -"color-convert@npm:^1.9.0": - version: 1.9.3 - resolution: "color-convert@npm:1.9.3" - dependencies: - color-name: 1.1.3 - checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: ~1.1.4 - checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 - languageName: node - linkType: hard - -"color-name@npm:1.1.3": - version: 1.1.3 - resolution: "color-name@npm:1.1.3" - checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 - languageName: node - linkType: hard - -"commander@npm:^10.0.0": - version: 10.0.1 - resolution: "commander@npm:10.0.1" - checksum: 436901d64a818295803c1996cd856621a74f30b9f9e28a588e726b2b1670665bccd7c1a77007ebf328729f0139838a88a19265858a0fa7a8728c4656796db948 - languageName: node - linkType: hard - -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af - languageName: node - linkType: hard - -"constant-case@npm:^2.0.0": - version: 2.0.0 - resolution: "constant-case@npm:2.0.0" - dependencies: - snake-case: ^2.1.0 - upper-case: ^1.1.1 - checksum: 893c793a425ebcd0744061c7f12650c655aae259b89d5654fb8eda42d22c3690716a4988ed03f2abe370b1ee7bfec44f8e4395e76e2f1458a8921982b15410ba - languageName: node - linkType: hard - -"core-js-pure@npm:^3.30.2": - version: 3.31.0 - resolution: "core-js-pure@npm:3.31.0" - checksum: 2bc5d2f6c3c9732fd5c066529b8d41fae9c746206ddf7614712dc4120a9efd47bf894df4fc600fde8c04324171c1999869798b48b23fca128eff5f09f58cd2f6 - languageName: node - linkType: hard - -"create-require@npm:^1.1.0": - version: 1.1.1 - resolution: "create-require@npm:1.1.1" - checksum: a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: ^3.1.0 - shebang-command: ^2.0.0 - which: ^2.0.1 - checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 - languageName: node - linkType: hard - -"csstype@npm:^3.0.2": - version: 3.1.2 - resolution: "csstype@npm:3.1.2" - checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 - languageName: node - linkType: hard - -"damerau-levenshtein@npm:^1.0.8": - version: 1.0.8 - resolution: "damerau-levenshtein@npm:1.0.8" - checksum: d240b7757544460ae0586a341a53110ab0a61126570ef2d8c731e3eab3f0cb6e488e2609e6a69b46727635de49be20b071688698744417ff1b6c1d7ccd03e0de - languageName: node - linkType: hard - -"debug@npm:^3.2.7": - version: 3.2.7 - resolution: "debug@npm:3.2.7" - dependencies: - ms: ^2.1.1 - checksum: b3d8c5940799914d30314b7c3304a43305fd0715581a919dacb8b3176d024a782062368405b47491516d2091d6462d4d11f2f4974a405048094f8bfebfa3071c - languageName: node - linkType: hard - -"debug@npm:^4.0.1, debug@npm:^4.1.1, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" - dependencies: - ms: 2.1.2 - peerDependenciesMeta: - supports-color: - optional: true - checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 - languageName: node - linkType: hard - -"deep-extend@npm:^0.6.0": - version: 0.6.0 - resolution: "deep-extend@npm:0.6.0" - checksum: 7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 - languageName: node - linkType: hard - -"deep-is@npm:^0.1.3": - version: 0.1.4 - resolution: "deep-is@npm:0.1.4" - checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 - languageName: node - linkType: hard - -"default-browser-id@npm:^3.0.0": - version: 3.0.0 - resolution: "default-browser-id@npm:3.0.0" - dependencies: - bplist-parser: ^0.2.0 - untildify: ^4.0.0 - checksum: 279c7ad492542e5556336b6c254a4eaf31b2c63a5433265655ae6e47301197b6cfb15c595a6fdc6463b2ff8e1a1a1ed3cba56038a60e1527ba4ab1628c6b9941 - languageName: node - linkType: hard - -"default-browser@npm:^4.0.0": - version: 4.0.0 - resolution: "default-browser@npm:4.0.0" - dependencies: - bundle-name: ^3.0.0 - default-browser-id: ^3.0.0 - execa: ^7.1.1 - titleize: ^3.0.0 - checksum: 40c5af984799042b140300be5639c9742599bda76dc9eba5ac9ad5943c83dd36cebc4471eafcfddf8e0ec817166d5ba89d56f08e66a126c7c7908a179cead1a7 - languageName: node - linkType: hard - -"defaults@npm:^1.0.3": - version: 1.0.4 - resolution: "defaults@npm:1.0.4" - dependencies: - clone: ^1.0.2 - checksum: 3a88b7a587fc076b84e60affad8b85245c01f60f38fc1d259e7ac1d89eb9ce6abb19e27215de46b98568dd5bc48471730b327637e6f20b0f1bc85cf00440c80a - languageName: node - linkType: hard - -"define-lazy-prop@npm:^3.0.0": - version: 3.0.0 - resolution: "define-lazy-prop@npm:3.0.0" - checksum: 54884f94caac0791bf6395a3ec530ce901cf71c47b0196b8754f3fd17edb6c0e80149c1214429d851873bb0d689dbe08dcedbb2306dc45c8534a5934723851b6 - languageName: node - linkType: hard - -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4, define-properties@npm:^1.2.0": - version: 1.2.0 - resolution: "define-properties@npm:1.2.0" - dependencies: - has-property-descriptors: ^1.0.0 - object-keys: ^1.1.1 - checksum: e60aee6a19b102df4e2b1f301816804e81ab48bb91f00d0d935f269bf4b3f79c88b39e4f89eaa132890d23267335fd1140dfcd8d5ccd61031a0a2c41a54e33a6 - languageName: node - linkType: hard - -"del@npm:^5.1.0": - version: 5.1.0 - resolution: "del@npm:5.1.0" - dependencies: - globby: ^10.0.1 - graceful-fs: ^4.2.2 - is-glob: ^4.0.1 - is-path-cwd: ^2.2.0 - is-path-inside: ^3.0.1 - p-map: ^3.0.0 - rimraf: ^3.0.0 - slash: ^3.0.0 - checksum: d9e4ef2c1227230ed61291fc99bdcb084167c0fe580df5fa8b2524b511c09f0c51887edf7dc5ffaa6ecfb25c92a2ca185ec49d5233baf6c5fe50248ab1f13e57 - languageName: node - linkType: hard - -"dequal@npm:^2.0.3": - version: 2.0.3 - resolution: "dequal@npm:2.0.3" - checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90 - languageName: node - linkType: hard - -"diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d - languageName: node - linkType: hard - -"dir-glob@npm:^3.0.1": - version: 3.0.1 - resolution: "dir-glob@npm:3.0.1" - dependencies: - path-type: ^4.0.0 - checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 - languageName: node - linkType: hard - -"docs@workspace:apps/docs": - version: 0.0.0-use.local - resolution: "docs@workspace:apps/docs" - dependencies: - "@types/node": ^17.0.12 - "@types/react": ^18.0.22 - "@types/react-dom": ^18.0.7 - eslint-config-custom: "*" - next: ^13.4.1 - react: ^18.2.0 - react-dom: ^18.2.0 - tsconfig: "*" - typescript: ^4.5.3 - ui: "*" - languageName: unknown - linkType: soft - -"doctrine@npm:^2.1.0": - version: 2.1.0 - resolution: "doctrine@npm:2.1.0" - dependencies: - esutils: ^2.0.2 - checksum: a45e277f7feaed309fe658ace1ff286c6e2002ac515af0aaf37145b8baa96e49899638c7cd47dccf84c3d32abfc113246625b3ac8f552d1046072adee13b0dc8 - languageName: node - linkType: hard - -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: ^2.0.2 - checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce - languageName: node - linkType: hard - -"dot-case@npm:^2.1.0": - version: 2.1.1 - resolution: "dot-case@npm:2.1.1" - dependencies: - no-case: ^2.2.0 - checksum: 5c9d937245ff810a7ae788602e40c62e38cb515146ddf9b11c7f60cb02aae84859588761f1e8769d9e713609fae3c78dc99c8da9e0ee8e4d8b5c09a2fdf70328 - languageName: node - linkType: hard - -"dotenv@npm:16.0.3": - version: 16.0.3 - resolution: "dotenv@npm:16.0.3" - checksum: afcf03f373d7a6d62c7e9afea6328e62851d627a4e73f2e12d0a8deae1cd375892004f3021883f8aec85932cd2834b091f568ced92b4774625b321db83b827f8 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 - languageName: node - linkType: hard - -"enhanced-resolve@npm:^5.12.0": - version: 5.15.0 - resolution: "enhanced-resolve@npm:5.15.0" - dependencies: - graceful-fs: ^4.2.4 - tapable: ^2.2.0 - checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11 - languageName: node - linkType: hard - -"enquirer@npm:^2.3.5": - version: 2.3.6 - resolution: "enquirer@npm:2.3.6" - dependencies: - ansi-colors: ^4.1.1 - checksum: 1c0911e14a6f8d26721c91e01db06092a5f7675159f0261d69c403396a385afd13dd76825e7678f66daffa930cfaa8d45f506fb35f818a2788463d022af1b884 - languageName: node - linkType: hard - -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4": - version: 1.21.2 - resolution: "es-abstract@npm:1.21.2" - dependencies: - array-buffer-byte-length: ^1.0.0 - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - es-set-tostringtag: ^2.0.1 - es-to-primitive: ^1.2.1 - function.prototype.name: ^1.1.5 - get-intrinsic: ^1.2.0 - get-symbol-description: ^1.0.0 - globalthis: ^1.0.3 - gopd: ^1.0.1 - has: ^1.0.3 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 - has-symbols: ^1.0.3 - internal-slot: ^1.0.5 - is-array-buffer: ^3.0.2 - is-callable: ^1.2.7 - is-negative-zero: ^2.0.2 - is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 - is-string: ^1.0.7 - is-typed-array: ^1.1.10 - is-weakref: ^1.0.2 - object-inspect: ^1.12.3 - object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.4.3 - safe-regex-test: ^1.0.0 - string.prototype.trim: ^1.2.7 - string.prototype.trimend: ^1.0.6 - string.prototype.trimstart: ^1.0.6 - typed-array-length: ^1.0.4 - unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.9 - checksum: 037f55ee5e1cdf2e5edbab5524095a4f97144d95b94ea29e3611b77d852fd8c8a40e7ae7101fa6a759a9b9b1405f188c3c70928f2d3cd88d543a07fc0d5ad41a - languageName: node - linkType: hard - -"es-set-tostringtag@npm:^2.0.1": - version: 2.0.1 - resolution: "es-set-tostringtag@npm:2.0.1" - dependencies: - get-intrinsic: ^1.1.3 - has: ^1.0.3 - has-tostringtag: ^1.0.0 - checksum: ec416a12948cefb4b2a5932e62093a7cf36ddc3efd58d6c58ca7ae7064475ace556434b869b0bbeb0c365f1032a8ccd577211101234b69837ad83ad204fff884 - languageName: node - linkType: hard - -"es-shim-unscopables@npm:^1.0.0": - version: 1.0.0 - resolution: "es-shim-unscopables@npm:1.0.0" - dependencies: - has: ^1.0.3 - checksum: 83e95cadbb6ee44d3644dfad60dcad7929edbc42c85e66c3e99aefd68a3a5c5665f2686885cddb47dfeabfd77bd5ea5a7060f2092a955a729bbd8834f0d86fa1 - languageName: node - linkType: hard - -"es-to-primitive@npm:^1.2.1": - version: 1.2.1 - resolution: "es-to-primitive@npm:1.2.1" - dependencies: - is-callable: ^1.1.4 - is-date-object: ^1.0.1 - is-symbol: ^1.0.2 - checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed - languageName: node - linkType: hard - -"escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 - languageName: node - linkType: hard - -"eslint-config-custom@*, eslint-config-custom@workspace:packages/eslint-config-custom": - version: 0.0.0-use.local - resolution: "eslint-config-custom@workspace:packages/eslint-config-custom" - dependencies: - eslint-config-next: ^13.4.1 - eslint-config-prettier: ^8.3.0 - eslint-config-turbo: ^1.9.3 - eslint-plugin-react: 7.28.0 - languageName: unknown - linkType: soft - -"eslint-config-next@npm:^13.4.1": - version: 13.4.7 - resolution: "eslint-config-next@npm:13.4.7" - dependencies: - "@next/eslint-plugin-next": 13.4.7 - "@rushstack/eslint-patch": ^1.1.3 - "@typescript-eslint/parser": ^5.42.0 - eslint-import-resolver-node: ^0.3.6 - eslint-import-resolver-typescript: ^3.5.2 - eslint-plugin-import: ^2.26.0 - eslint-plugin-jsx-a11y: ^6.5.1 - eslint-plugin-react: ^7.31.7 - eslint-plugin-react-hooks: ^4.5.0 - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - typescript: ">=3.3.1" - peerDependenciesMeta: - typescript: - optional: true - checksum: fb86da6aaab337c87c202c5a35828f57adeaa9cf33ccd3530c20f196c4b103cc35e76318fab111b24b62a3c089214c8ed1df783e1c128152a88cd60130e050fc - languageName: node - linkType: hard - -"eslint-config-prettier@npm:^8.3.0": - version: 8.8.0 - resolution: "eslint-config-prettier@npm:8.8.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 1e94c3882c4d5e41e1dcfa2c368dbccbfe3134f6ac7d40101644d3bfbe3eb2f2ffac757f3145910b5eacf20c0e85e02b91293d3126d770cbf3dc390b3564681c - languageName: node - linkType: hard - -"eslint-config-turbo@npm:^1.9.3": - version: 1.10.6 - resolution: "eslint-config-turbo@npm:1.10.6" - dependencies: - eslint-plugin-turbo: 1.10.6 - peerDependencies: - eslint: ">6.6.0" - checksum: 3159c0290935bc039640a8e82eb8c04f945165d75cd3c250be97db8891d7244cec4793dd58064c258bce677a1301f7a92e6417770388c40b08b055746cb213c7 - languageName: node - linkType: hard - -"eslint-import-resolver-node@npm:^0.3.6, eslint-import-resolver-node@npm:^0.3.7": - version: 0.3.7 - resolution: "eslint-import-resolver-node@npm:0.3.7" - dependencies: - debug: ^3.2.7 - is-core-module: ^2.11.0 - resolve: ^1.22.1 - checksum: 3379aacf1d2c6952c1b9666c6fa5982c3023df695430b0d391c0029f6403a7775414873d90f397e98ba6245372b6c8960e16e74d9e4a3b0c0a4582f3bdbe3d6e - languageName: node - linkType: hard - -"eslint-import-resolver-typescript@npm:^3.5.2": - version: 3.5.5 - resolution: "eslint-import-resolver-typescript@npm:3.5.5" - dependencies: - debug: ^4.3.4 - enhanced-resolve: ^5.12.0 - eslint-module-utils: ^2.7.4 - get-tsconfig: ^4.5.0 - globby: ^13.1.3 - is-core-module: ^2.11.0 - is-glob: ^4.0.3 - synckit: ^0.8.5 - peerDependencies: - eslint: "*" - eslint-plugin-import: "*" - checksum: 27e6276fdff5d377c9036362ff736ac29852106e883ff589ea9092dc57d4bc2a67a82d75134221124f05045f9a7e2114a159b2c827d1f9f64d091f7afeab0f58 - languageName: node - linkType: hard - -"eslint-module-utils@npm:^2.7.4": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" - dependencies: - debug: ^3.2.7 - peerDependenciesMeta: - eslint: - optional: true - checksum: 74c6dfea7641ebcfe174be61168541a11a14aa8d72e515f5f09af55cd0d0862686104b0524aa4b8e0ce66418a44aa38a94d2588743db5fd07a6b49ffd16921d2 - languageName: node - linkType: hard - -"eslint-plugin-import@npm:^2.26.0": - version: 2.27.5 - resolution: "eslint-plugin-import@npm:2.27.5" - dependencies: - array-includes: ^3.1.6 - array.prototype.flat: ^1.3.1 - array.prototype.flatmap: ^1.3.1 - debug: ^3.2.7 - doctrine: ^2.1.0 - eslint-import-resolver-node: ^0.3.7 - eslint-module-utils: ^2.7.4 - has: ^1.0.3 - is-core-module: ^2.11.0 - is-glob: ^4.0.3 - minimatch: ^3.1.2 - object.values: ^1.1.6 - resolve: ^1.22.1 - semver: ^6.3.0 - tsconfig-paths: ^3.14.1 - peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: f500571a380167e25d72a4d925ef9a7aae8899eada57653e5f3051ec3d3c16d08271fcefe41a30a9a2f4fefc232f066253673ee4ea77b30dba65ae173dade85d - languageName: node - linkType: hard - -"eslint-plugin-jsx-a11y@npm:^6.5.1": - version: 6.7.1 - resolution: "eslint-plugin-jsx-a11y@npm:6.7.1" - dependencies: - "@babel/runtime": ^7.20.7 - aria-query: ^5.1.3 - array-includes: ^3.1.6 - array.prototype.flatmap: ^1.3.1 - ast-types-flow: ^0.0.7 - axe-core: ^4.6.2 - axobject-query: ^3.1.1 - damerau-levenshtein: ^1.0.8 - emoji-regex: ^9.2.2 - has: ^1.0.3 - jsx-ast-utils: ^3.3.3 - language-tags: =1.0.5 - minimatch: ^3.1.2 - object.entries: ^1.1.6 - object.fromentries: ^2.0.6 - semver: ^6.3.0 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: f166dd5fe7257c7b891c6692e6a3ede6f237a14043ae3d97581daf318fc5833ddc6b4871aa34ab7656187430170500f6d806895747ea17ecdf8231a666c3c2fd - languageName: node - linkType: hard - -"eslint-plugin-react-hooks@npm:^4.5.0": - version: 4.6.0 - resolution: "eslint-plugin-react-hooks@npm:4.6.0" - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 23001801f14c1d16bf0a837ca7970d9dd94e7b560384b41db378b49b6e32dc43d6e2790de1bd737a652a86f81a08d6a91f402525061b47719328f586a57e86c3 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:7.28.0": - version: 7.28.0 - resolution: "eslint-plugin-react@npm:7.28.0" - dependencies: - array-includes: ^3.1.4 - array.prototype.flatmap: ^1.2.5 - doctrine: ^2.1.0 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.0.4 - object.entries: ^1.1.5 - object.fromentries: ^2.0.5 - object.hasown: ^1.1.0 - object.values: ^1.1.5 - prop-types: ^15.7.2 - resolve: ^2.0.0-next.3 - semver: ^6.3.0 - string.prototype.matchall: ^4.0.6 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 90293d0fd53bb1f735ffd32141cdd211fb1120c9f7bbe5342f9e923261a39e52a2b2575d4e46c9cd77d257f42db4a99b8b339689fc5b5c1c26048929f69b1784 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:^7.31.7": - version: 7.32.2 - resolution: "eslint-plugin-react@npm:7.32.2" - dependencies: - array-includes: ^3.1.6 - array.prototype.flatmap: ^1.3.1 - array.prototype.tosorted: ^1.1.1 - doctrine: ^2.1.0 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.1.2 - object.entries: ^1.1.6 - object.fromentries: ^2.0.6 - object.hasown: ^1.1.2 - object.values: ^1.1.6 - prop-types: ^15.8.1 - resolve: ^2.0.0-next.4 - semver: ^6.3.0 - string.prototype.matchall: ^4.0.8 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 2232b3b8945aa50b7773919c15cd96892acf35d2f82503667a79e2f55def90f728ed4f0e496f0f157acbe1bd4397c5615b676ae7428fe84488a544ca53feb944 - languageName: node - linkType: hard - -"eslint-plugin-turbo@npm:1.10.6": - version: 1.10.6 - resolution: "eslint-plugin-turbo@npm:1.10.6" - dependencies: - dotenv: 16.0.3 - peerDependencies: - eslint: ">6.6.0" - checksum: b6c9ae6b25433f4d6621fcff2d07394b774fe3253f111785307539a28122ade7b52823870fc3c48e4bd549c716de89efcd8b94db36275a8eb0c1e8e4c2c02f4b - languageName: node - linkType: hard - -"eslint-scope@npm:^5.1.1": - version: 5.1.1 - resolution: "eslint-scope@npm:5.1.1" - dependencies: - esrecurse: ^4.3.0 - estraverse: ^4.1.1 - checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb - languageName: node - linkType: hard - -"eslint-utils@npm:^2.1.0": - version: 2.1.0 - resolution: "eslint-utils@npm:2.1.0" - dependencies: - eslint-visitor-keys: ^1.1.0 - checksum: 27500938f348da42100d9e6ad03ae29b3de19ba757ae1a7f4a087bdcf83ac60949bbb54286492ca61fac1f5f3ac8692dd21537ce6214240bf95ad0122f24d71d - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^1.1.0, eslint-visitor-keys@npm:^1.3.0": - version: 1.3.0 - resolution: "eslint-visitor-keys@npm:1.3.0" - checksum: 37a19b712f42f4c9027e8ba98c2b06031c17e0c0a4c696cd429bd9ee04eb43889c446f2cd545e1ff51bef9593fcec94ecd2c2ef89129fcbbf3adadbef520376a - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^2.0.0": - version: 2.1.0 - resolution: "eslint-visitor-keys@npm:2.1.0" - checksum: e3081d7dd2611a35f0388bbdc2f5da60b3a3c5b8b6e928daffff7391146b434d691577aa95064c8b7faad0b8a680266bcda0a42439c18c717b80e6718d7e267d - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.3.0": - version: 3.4.1 - resolution: "eslint-visitor-keys@npm:3.4.1" - checksum: f05121d868202736b97de7d750847a328fcfa8593b031c95ea89425333db59676ac087fa905eba438d0a3c5769632f828187e0c1a0d271832a2153c1d3661c2c - languageName: node - linkType: hard - -"eslint@npm:^7.32.0": - version: 7.32.0 - resolution: "eslint@npm:7.32.0" - dependencies: - "@babel/code-frame": 7.12.11 - "@eslint/eslintrc": ^0.4.3 - "@humanwhocodes/config-array": ^0.5.0 - ajv: ^6.10.0 - chalk: ^4.0.0 - cross-spawn: ^7.0.2 - debug: ^4.0.1 - doctrine: ^3.0.0 - enquirer: ^2.3.5 - escape-string-regexp: ^4.0.0 - eslint-scope: ^5.1.1 - eslint-utils: ^2.1.0 - eslint-visitor-keys: ^2.0.0 - espree: ^7.3.1 - esquery: ^1.4.0 - esutils: ^2.0.2 - fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 - functional-red-black-tree: ^1.0.1 - glob-parent: ^5.1.2 - globals: ^13.6.0 - ignore: ^4.0.6 - import-fresh: ^3.0.0 - imurmurhash: ^0.1.4 - is-glob: ^4.0.0 - js-yaml: ^3.13.1 - json-stable-stringify-without-jsonify: ^1.0.1 - levn: ^0.4.1 - lodash.merge: ^4.6.2 - minimatch: ^3.0.4 - natural-compare: ^1.4.0 - optionator: ^0.9.1 - progress: ^2.0.0 - regexpp: ^3.1.0 - semver: ^7.2.1 - strip-ansi: ^6.0.0 - strip-json-comments: ^3.1.0 - table: ^6.0.9 - text-table: ^0.2.0 - v8-compile-cache: ^2.0.3 - bin: - eslint: bin/eslint.js - checksum: cc85af9985a3a11085c011f3d27abe8111006d34cc274291b3c4d7bea51a4e2ff6135780249becd919ba7f6d6d1ecc38a6b73dacb6a7be08d38453b344dc8d37 - languageName: node - linkType: hard - -"espree@npm:^7.3.0, espree@npm:^7.3.1": - version: 7.3.1 - resolution: "espree@npm:7.3.1" - dependencies: - acorn: ^7.4.0 - acorn-jsx: ^5.3.1 - eslint-visitor-keys: ^1.3.0 - checksum: aa9b50dcce883449af2e23bc2b8d9abb77118f96f4cb313935d6b220f77137eaef7724a83c3f6243b96bc0e4ab14766198e60818caad99f9519ae5a336a39b45 - languageName: node - linkType: hard - -"esprima@npm:^4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 - languageName: node - linkType: hard - -"esquery@npm:^1.4.0": - version: 1.5.0 - resolution: "esquery@npm:1.5.0" - dependencies: - estraverse: ^5.1.0 - checksum: aefb0d2596c230118656cd4ec7532d447333a410a48834d80ea648b1e7b5c9bc9ed8b5e33a89cb04e487b60d622f44cf5713bf4abed7c97343edefdc84a35900 - languageName: node - linkType: hard - -"esrecurse@npm:^4.3.0": - version: 4.3.0 - resolution: "esrecurse@npm:4.3.0" - dependencies: - estraverse: ^5.2.0 - checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 - languageName: node - linkType: hard - -"estraverse@npm:^4.1.1": - version: 4.3.0 - resolution: "estraverse@npm:4.3.0" - checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 - languageName: node - linkType: hard - -"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": - version: 5.3.0 - resolution: "estraverse@npm:5.3.0" - checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b - languageName: node - linkType: hard - -"esutils@npm:^2.0.2": - version: 2.0.3 - resolution: "esutils@npm:2.0.3" - checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 - languageName: node - linkType: hard - -"execa@npm:^5.0.0": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - 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 - checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 - languageName: node - linkType: hard - -"execa@npm:^7.1.1": - version: 7.1.1 - resolution: "execa@npm:7.1.1" - dependencies: - cross-spawn: ^7.0.3 - get-stream: ^6.0.1 - human-signals: ^4.3.0 - is-stream: ^3.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^5.1.0 - onetime: ^6.0.0 - signal-exit: ^3.0.7 - strip-final-newline: ^3.0.0 - checksum: 21fa46fc69314ace4068cf820142bdde5b643a5d89831c2c9349479c1555bff137a291b8e749e7efca36535e4e0a8c772c11008ca2e84d2cbd6ca141a3c8f937 - languageName: node - linkType: hard - -"external-editor@npm:^3.0.3": - version: 3.1.0 - resolution: "external-editor@npm:3.1.0" - dependencies: - chardet: ^0.7.0 - iconv-lite: ^0.4.24 - tmp: ^0.0.33 - checksum: 1c2a616a73f1b3435ce04030261bed0e22d4737e14b090bb48e58865da92529c9f2b05b893de650738d55e692d071819b45e1669259b2b354bc3154d27a698c7 - languageName: node - linkType: hard - -"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": - version: 3.1.3 - resolution: "fast-deep-equal@npm:3.1.3" - checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d - languageName: node - linkType: hard - -"fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9": - version: 3.2.12 - resolution: "fast-glob@npm:3.2.12" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 0b1990f6ce831c7e28c4d505edcdaad8e27e88ab9fa65eedadb730438cfc7cde4910d6c975d6b7b8dc8a73da4773702ebcfcd6e3518e73938bb1383badfe01c2 - languageName: node - linkType: hard - -"fast-json-stable-stringify@npm:^2.0.0": - version: 2.1.0 - resolution: "fast-json-stable-stringify@npm:2.1.0" - checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb - languageName: node - linkType: hard - -"fast-levenshtein@npm:^2.0.6": - version: 2.0.6 - resolution: "fast-levenshtein@npm:2.0.6" - checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c - languageName: node - linkType: hard - -"fastq@npm:^1.6.0": - version: 1.15.0 - resolution: "fastq@npm:1.15.0" - dependencies: - reusify: ^1.0.4 - checksum: 0170e6bfcd5d57a70412440b8ef600da6de3b2a6c5966aeaf0a852d542daff506a0ee92d6de7679d1de82e644bce69d7a574a6c93f0b03964b5337eed75ada1a - languageName: node - linkType: hard - -"figures@npm:^3.0.0": - version: 3.2.0 - resolution: "figures@npm:3.2.0" - dependencies: - escape-string-regexp: ^1.0.5 - checksum: 85a6ad29e9aca80b49b817e7c89ecc4716ff14e3779d9835af554db91bac41c0f289c418923519392a1e582b4d10482ad282021330cd045bb7b80c84152f2a2b - languageName: node - linkType: hard - -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" - dependencies: - flat-cache: ^3.0.4 - checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 - languageName: node - linkType: hard - -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" - dependencies: - to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 - languageName: node - linkType: hard - -"flat-cache@npm:^3.0.4": - version: 3.0.4 - resolution: "flat-cache@npm:3.0.4" - dependencies: - flatted: ^3.1.0 - rimraf: ^3.0.2 - checksum: 4fdd10ecbcbf7d520f9040dd1340eb5dfe951e6f0ecf2252edeec03ee68d989ec8b9a20f4434270e71bcfd57800dc09b3344fca3966b2eb8f613072c7d9a2365 - languageName: node - linkType: hard - -"flatted@npm:^3.1.0": - version: 3.2.7 - resolution: "flatted@npm:3.2.7" - checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 - languageName: node - linkType: hard - -"for-each@npm:^0.3.3": - version: 0.3.3 - resolution: "for-each@npm:0.3.3" - dependencies: - is-callable: ^1.1.3 - checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 - languageName: node - linkType: hard - -"fs-extra@npm:^10.1.0": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" - dependencies: - graceful-fs: ^4.2.0 - jsonfile: ^6.0.1 - universalify: ^2.0.0 - checksum: dc94ab37096f813cc3ca12f0f1b5ad6744dfed9ed21e953d72530d103cea193c2f81584a39e9dee1bea36de5ee66805678c0dddc048e8af1427ac19c00fffc50 - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 - languageName: node - linkType: hard - -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a - languageName: node - linkType: hard - -"function.prototype.name@npm:^1.1.5": - version: 1.1.5 - resolution: "function.prototype.name@npm:1.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.0 - functions-have-names: ^1.2.2 - checksum: acd21d733a9b649c2c442f067567743214af5fa248dbeee69d8278ce7df3329ea5abac572be9f7470b4ec1cd4d8f1040e3c5caccf98ebf2bf861a0deab735c27 - languageName: node - linkType: hard - -"functional-red-black-tree@npm:^1.0.1": - version: 1.0.1 - resolution: "functional-red-black-tree@npm:1.0.1" - checksum: ca6c170f37640e2d94297da8bb4bf27a1d12bea3e00e6a3e007fd7aa32e37e000f5772acf941b4e4f3cf1c95c3752033d0c509af157ad8f526e7f00723b9eb9f - languageName: node - linkType: hard - -"functions-have-names@npm:^1.2.2, functions-have-names@npm:^1.2.3": - version: 1.2.3 - resolution: "functions-have-names@npm:1.2.3" - checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0": - version: 1.2.1 - resolution: "get-intrinsic@npm:1.2.1" - dependencies: - function-bind: ^1.1.1 - has: ^1.0.3 - has-proto: ^1.0.1 - has-symbols: ^1.0.3 - checksum: 5b61d88552c24b0cf6fa2d1b3bc5459d7306f699de060d76442cce49a4721f52b8c560a33ab392cf5575b7810277d54ded9d4d39a1ea61855619ebc005aa7e5f - languageName: node - linkType: hard - -"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad - languageName: node - linkType: hard - -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 - languageName: node - linkType: hard - -"get-tsconfig@npm:^4.5.0": - version: 4.6.2 - resolution: "get-tsconfig@npm:4.6.2" - dependencies: - resolve-pkg-maps: ^1.0.0 - checksum: e791e671a9b55e91efea3ca819ecd7a25beae679e31c83234bf3dd62ddd93df070c1b95ae7e29d206358ebb6408f6f79ac6d83a32a3bbd6a6d217babe23de077 - languageName: node - linkType: hard - -"glob-parent@npm:^5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: ^4.0.1 - checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e - languageName: node - linkType: hard - -"glob-to-regexp@npm:^0.4.1": - version: 0.4.1 - resolution: "glob-to-regexp@npm:0.4.1" - checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 - languageName: node - linkType: hard - -"glob@npm:7.1.7": - version: 7.1.7 - resolution: "glob@npm:7.1.7" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.0.4 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: b61f48973bbdcf5159997b0874a2165db572b368b931135832599875919c237fc05c12984e38fe828e69aa8a921eb0e8a4997266211c517c9cfaae8a93988bb8 - languageName: node - linkType: hard - -"glob@npm:^7.1.3": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.1.1 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 - languageName: node - linkType: hard - -"globals@npm:^13.6.0, globals@npm:^13.9.0": - version: 13.20.0 - resolution: "globals@npm:13.20.0" - dependencies: - type-fest: ^0.20.2 - checksum: ad1ecf914bd051325faad281d02ea2c0b1df5d01bd94d368dcc5513340eac41d14b3c61af325768e3c7f8d44576e72780ec0b6f2d366121f8eec6e03c3a3b97a - languageName: node - linkType: hard - -"globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" - dependencies: - define-properties: ^1.1.3 - checksum: fbd7d760dc464c886d0196166d92e5ffb4c84d0730846d6621a39fbbc068aeeb9c8d1421ad330e94b7bca4bb4ea092f5f21f3d36077812af5d098b4dc006c998 - languageName: node - linkType: hard - -"globby@npm:^10.0.1": - version: 10.0.2 - resolution: "globby@npm:10.0.2" - dependencies: - "@types/glob": ^7.1.1 - array-union: ^2.1.0 - dir-glob: ^3.0.1 - fast-glob: ^3.0.3 - glob: ^7.1.3 - ignore: ^5.1.1 - merge2: ^1.2.3 - slash: ^3.0.0 - checksum: 167cd067f2cdc030db2ec43232a1e835fa06217577d545709dbf29fd21631b30ff8258705172069c855dc4d5766c3b2690834e35b936fbff01ad0329fb95a26f - languageName: node - linkType: hard - -"globby@npm:^11.1.0": - version: 11.1.0 - resolution: "globby@npm:11.1.0" - dependencies: - array-union: ^2.1.0 - dir-glob: ^3.0.1 - fast-glob: ^3.2.9 - ignore: ^5.2.0 - merge2: ^1.4.1 - slash: ^3.0.0 - checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 - languageName: node - linkType: hard - -"globby@npm:^13.1.3": - version: 13.2.0 - resolution: "globby@npm:13.2.0" - dependencies: - dir-glob: ^3.0.1 - fast-glob: ^3.2.11 - ignore: ^5.2.0 - merge2: ^1.4.1 - slash: ^4.0.0 - checksum: 0a3dd786571788adef1c894f22112834cff5bbe061ae6e0a01c5118c39d44b3f1937ef1dae3f8b9bc24756eba84a0923e565b1ad9a4ec52831d7e2a04c035e75 - languageName: node - linkType: hard - -"gopd@npm:^1.0.1": - version: 1.0.1 - resolution: "gopd@npm:1.0.1" - dependencies: - get-intrinsic: ^1.1.3 - checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 - languageName: node - linkType: hard - -"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 - languageName: node - linkType: hard - -"handlebars@npm:^4.4.3": - version: 4.7.7 - resolution: "handlebars@npm:4.7.7" - dependencies: - minimist: ^1.2.5 - neo-async: ^2.6.0 - source-map: ^0.6.1 - uglify-js: ^3.1.4 - wordwrap: ^1.0.0 - dependenciesMeta: - uglify-js: - optional: true - bin: - handlebars: bin/handlebars - checksum: 1e79a43f5e18d15742977cb987923eab3e2a8f44f2d9d340982bcb69e1735ed049226e534d7c1074eaddaf37e4fb4f471a8adb71cddd5bc8cf3f894241df5cee - languageName: node - linkType: hard - -"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": - version: 1.0.2 - resolution: "has-bigints@npm:1.0.2" - checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b - languageName: node - linkType: hard - -"has-flag@npm:^3.0.0": - version: 3.0.0 - resolution: "has-flag@npm:3.0.0" - checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad - languageName: node - linkType: hard - -"has-property-descriptors@npm:^1.0.0": - version: 1.0.0 - resolution: "has-property-descriptors@npm:1.0.0" - dependencies: - get-intrinsic: ^1.1.1 - checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb - languageName: node - linkType: hard - -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": - version: 1.0.3 - resolution: "has-symbols@npm:1.0.3" - checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" - dependencies: - has-symbols: ^1.0.2 - checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c - languageName: node - linkType: hard - -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: ^1.1.1 - checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 - languageName: node - linkType: hard - -"header-case@npm:^1.0.0": - version: 1.0.1 - resolution: "header-case@npm:1.0.1" - dependencies: - no-case: ^2.2.0 - upper-case: ^1.1.3 - checksum: fe1cc9a555ec9aabc2de80f4dd961a81c534fc23951694fef34297e59b0dd60f26647148731bf0dd3fdb3a1c688089d3cd147d7038db850e25be7c0a5fabb022 - languageName: node - linkType: hard - -"human-signals@npm:^2.1.0": - version: 2.1.0 - resolution: "human-signals@npm:2.1.0" - checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 - languageName: node - linkType: hard - -"human-signals@npm:^4.3.0": - version: 4.3.1 - resolution: "human-signals@npm:4.3.1" - checksum: 6f12958df3f21b6fdaf02d90896c271df00636a31e2bbea05bddf817a35c66b38a6fdac5863e2df85bd52f34958997f1f50350ff97249e1dff8452865d5235d1 - languageName: node - linkType: hard - -"iconv-lite@npm:^0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" - dependencies: - safer-buffer: ">= 2.1.2 < 3" - checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 - languageName: node - linkType: hard - -"ieee754@npm:^1.1.13": - version: 1.2.1 - resolution: "ieee754@npm:1.2.1" - checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e - languageName: node - linkType: hard - -"ignore@npm:^4.0.6": - version: 4.0.6 - resolution: "ignore@npm:4.0.6" - checksum: 248f82e50a430906f9ee7f35e1158e3ec4c3971451dd9f99c9bc1548261b4db2b99709f60ac6c6cac9333494384176cc4cc9b07acbe42d52ac6a09cad734d800 - languageName: node - linkType: hard - -"ignore@npm:^5.1.1, ignore@npm:^5.2.0": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef - languageName: node - linkType: hard - -"import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" - dependencies: - parent-module: ^1.0.0 - resolve-from: ^4.0.0 - checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: ^1.3.0 - wrappy: 1 - checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd - languageName: node - linkType: hard - -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 - languageName: node - linkType: hard - -"ini@npm:~1.3.0": - version: 1.3.8 - resolution: "ini@npm:1.3.8" - checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 - languageName: node - linkType: hard - -"inquirer@npm:^7.1.0": - version: 7.3.3 - resolution: "inquirer@npm:7.3.3" - dependencies: - ansi-escapes: ^4.2.1 - chalk: ^4.1.0 - cli-cursor: ^3.1.0 - cli-width: ^3.0.0 - external-editor: ^3.0.3 - figures: ^3.0.0 - lodash: ^4.17.19 - mute-stream: 0.0.8 - run-async: ^2.4.0 - rxjs: ^6.6.0 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - through: ^2.3.6 - checksum: 4d387fc1eb6126acbd58cbdb9ad99d2887d181df86ab0c2b9abdf734e751093e2d5882c2b6dc7144d9ab16b7ab30a78a1d7f01fb6a2850a44aeb175d1e3f8778 - languageName: node - linkType: hard - -"inquirer@npm:^8.2.4": - version: 8.2.5 - resolution: "inquirer@npm:8.2.5" - dependencies: - ansi-escapes: ^4.2.1 - chalk: ^4.1.1 - cli-cursor: ^3.1.0 - cli-width: ^3.0.0 - external-editor: ^3.0.3 - figures: ^3.0.0 - lodash: ^4.17.21 - mute-stream: 0.0.8 - ora: ^5.4.1 - run-async: ^2.4.0 - rxjs: ^7.5.5 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - through: ^2.3.6 - wrap-ansi: ^7.0.0 - checksum: f13ee4c444187786fb393609dedf6b30870115a57b603f2e6424f29a99abc13446fd45ee22461c33c9c40a92a60a8df62d0d6b25d74fc6676fa4cb211de55b55 - languageName: node - linkType: hard - -"internal-slot@npm:^1.0.3, internal-slot@npm:^1.0.5": - version: 1.0.5 - resolution: "internal-slot@npm:1.0.5" - dependencies: - get-intrinsic: ^1.2.0 - has: ^1.0.3 - side-channel: ^1.0.4 - checksum: 97e84046bf9e7574d0956bd98d7162313ce7057883b6db6c5c7b5e5f05688864b0978ba07610c726d15d66544ffe4b1050107d93f8a39ebc59b15d8b429b497a - languageName: node - linkType: hard - -"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": - version: 3.0.2 - resolution: "is-array-buffer@npm:3.0.2" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.0 - is-typed-array: ^1.1.10 - checksum: dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 - languageName: node - linkType: hard - -"is-bigint@npm:^1.0.1": - version: 1.0.4 - resolution: "is-bigint@npm:1.0.4" - dependencies: - has-bigints: ^1.0.1 - checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 - languageName: node - linkType: hard - -"is-boolean-object@npm:^1.1.0": - version: 1.1.2 - resolution: "is-boolean-object@npm:1.1.2" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 - languageName: node - linkType: hard - -"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": - version: 1.2.7 - resolution: "is-callable@npm:1.2.7" - checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac - languageName: node - linkType: hard - -"is-core-module@npm:^2.11.0, is-core-module@npm:^2.12.0, is-core-module@npm:^2.9.0": - version: 2.12.1 - resolution: "is-core-module@npm:2.12.1" - dependencies: - has: ^1.0.3 - checksum: f04ea30533b5e62764e7b2e049d3157dc0abd95ef44275b32489ea2081176ac9746ffb1cdb107445cf1ff0e0dfcad522726ca27c27ece64dadf3795428b8e468 - languageName: node - linkType: hard - -"is-date-object@npm:^1.0.1": - version: 1.0.5 - resolution: "is-date-object@npm:1.0.5" - dependencies: - has-tostringtag: ^1.0.0 - checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc - languageName: node - linkType: hard - -"is-docker@npm:^2.0.0": - version: 2.2.1 - resolution: "is-docker@npm:2.2.1" - bin: - is-docker: cli.js - checksum: 3fef7ddbf0be25958e8991ad941901bf5922ab2753c46980b60b05c1bf9c9c2402d35e6dc32e4380b980ef5e1970a5d9d5e5aa2e02d77727c3b6b5e918474c56 - languageName: node - linkType: hard - -"is-docker@npm:^3.0.0": - version: 3.0.0 - resolution: "is-docker@npm:3.0.0" - bin: - is-docker: cli.js - checksum: b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90 - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 - languageName: node - linkType: hard - -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: ^2.1.1 - checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 - languageName: node - linkType: hard - -"is-inside-container@npm:^1.0.0": - version: 1.0.0 - resolution: "is-inside-container@npm:1.0.0" - dependencies: - is-docker: ^3.0.0 - bin: - is-inside-container: cli.js - checksum: c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03 - languageName: node - linkType: hard - -"is-interactive@npm:^1.0.0": - version: 1.0.0 - resolution: "is-interactive@npm:1.0.0" - checksum: 824808776e2d468b2916cdd6c16acacebce060d844c35ca6d82267da692e92c3a16fdba624c50b54a63f38bdc4016055b6f443ce57d7147240de4f8cdabaf6f9 - languageName: node - linkType: hard - -"is-lower-case@npm:^1.1.0": - version: 1.1.3 - resolution: "is-lower-case@npm:1.1.3" - dependencies: - lower-case: ^1.1.0 - checksum: 55a2a9fe384f669ab349985bb3d1b2ab99dff4ca6d898255786ed97722680ee407a2b2c9977e05157043fd48727d71a1ca15493b58710ab076b13820ee84eed0 - languageName: node - linkType: hard - -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a - languageName: node - linkType: hard - -"is-number-object@npm:^1.0.4": - version: 1.0.7 - resolution: "is-number-object@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a - languageName: node - linkType: hard - -"is-path-cwd@npm:^2.2.0": - version: 2.2.0 - resolution: "is-path-cwd@npm:2.2.0" - checksum: 46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048 - languageName: node - linkType: hard - -"is-path-inside@npm:^3.0.1": - version: 3.0.3 - resolution: "is-path-inside@npm:3.0.3" - checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 - languageName: node - linkType: hard - -"is-regex@npm:^1.1.4": - version: 1.1.4 - resolution: "is-regex@npm:1.1.4" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 - languageName: node - linkType: hard - -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a - languageName: node - linkType: hard - -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 - languageName: node - linkType: hard - -"is-stream@npm:^3.0.0": - version: 3.0.0 - resolution: "is-stream@npm:3.0.0" - checksum: 172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 - languageName: node - linkType: hard - -"is-string@npm:^1.0.5, is-string@npm:^1.0.7": - version: 1.0.7 - resolution: "is-string@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 - languageName: node - linkType: hard - -"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": - version: 1.0.4 - resolution: "is-symbol@npm:1.0.4" - dependencies: - has-symbols: ^1.0.2 - checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 - languageName: node - linkType: hard - -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.9": - version: 1.1.10 - resolution: "is-typed-array@npm:1.1.10" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - checksum: aac6ecb59d4c56a1cdeb69b1f129154ef462bbffe434cb8a8235ca89b42f258b7ae94073c41b3cb7bce37f6a1733ad4499f07882d5d5093a7ba84dfc4ebb8017 - languageName: node - linkType: hard - -"is-unicode-supported@npm:^0.1.0": - version: 0.1.0 - resolution: "is-unicode-supported@npm:0.1.0" - checksum: a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 - languageName: node - linkType: hard - -"is-upper-case@npm:^1.1.0": - version: 1.1.2 - resolution: "is-upper-case@npm:1.1.2" - dependencies: - upper-case: ^1.1.0 - checksum: c85805dfb9c5465f1db2492ce0feddd9273398a6dc0250b4d866f9bd23dbd92d0e2b57f4560ab195b2695b8403ff989265cf637f34b7443b706e0cd4d482b5ee - languageName: node - linkType: hard - -"is-weakref@npm:^1.0.2": - version: 1.0.2 - resolution: "is-weakref@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de - languageName: node - linkType: hard - -"is-wsl@npm:^2.2.0": - version: 2.2.0 - resolution: "is-wsl@npm:2.2.0" - dependencies: - is-docker: ^2.0.0 - checksum: 20849846ae414997d290b75e16868e5261e86ff5047f104027026fd61d8b5a9b0b3ade16239f35e1a067b3c7cc02f70183cb661010ed16f4b6c7c93dad1b19d8 - languageName: node - linkType: hard - -"isbinaryfile@npm:^4.0.2": - version: 4.0.10 - resolution: "isbinaryfile@npm:4.0.10" - checksum: a6b28db7e23ac7a77d3707567cac81356ea18bd602a4f21f424f862a31d0e7ab4f250759c98a559ece35ffe4d99f0d339f1ab884ffa9795172f632ab8f88e686 - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 - languageName: node - linkType: hard - -"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 - languageName: node - linkType: hard - -"js-yaml@npm:^3.13.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: ^1.0.7 - esprima: ^4.0.0 - bin: - js-yaml: bin/js-yaml.js - checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c - languageName: node - linkType: hard - -"json-schema-traverse@npm:^0.4.1": - version: 0.4.1 - resolution: "json-schema-traverse@npm:0.4.1" - checksum: 7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b - languageName: node - linkType: hard - -"json-schema-traverse@npm:^1.0.0": - version: 1.0.0 - resolution: "json-schema-traverse@npm:1.0.0" - checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad - languageName: node - linkType: hard - -"json-stable-stringify-without-jsonify@npm:^1.0.1": - version: 1.0.1 - resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" - checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 - languageName: node - linkType: hard - -"json5@npm:^1.0.2": - version: 1.0.2 - resolution: "json5@npm:1.0.2" - dependencies: - minimist: ^1.2.0 - bin: - json5: lib/cli.js - checksum: 866458a8c58a95a49bef3adba929c625e82532bcff1fe93f01d29cb02cac7c3fe1f4b79951b7792c2da9de0b32871a8401a6e3c5b36778ad852bf5b8a61165d7 - languageName: node - linkType: hard - -"jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" - dependencies: - graceful-fs: ^4.1.6 - universalify: ^2.0.0 - dependenciesMeta: - graceful-fs: - optional: true - checksum: 7af3b8e1ac8fe7f1eccc6263c6ca14e1966fcbc74b618d3c78a0a2075579487547b94f72b7a1114e844a1e15bb00d440e5d1720bfc4612d790a6f285d5ea8354 - languageName: node - linkType: hard - -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.3": - version: 3.3.4 - resolution: "jsx-ast-utils@npm:3.3.4" - dependencies: - array-includes: ^3.1.6 - array.prototype.flat: ^1.3.1 - object.assign: ^4.1.4 - object.values: ^1.1.6 - checksum: a6a00d324e38f0d47e04f973d79670248a663422a4dccdc02efd6f1caf1c00042fb0aafcff1023707c85dea6f013d435b90db67c1c6841bf345628f0a720d8b3 - languageName: node - linkType: hard - -"language-subtag-registry@npm:~0.3.2": - version: 0.3.22 - resolution: "language-subtag-registry@npm:0.3.22" - checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a - languageName: node - linkType: hard - -"language-tags@npm:=1.0.5": - version: 1.0.5 - resolution: "language-tags@npm:1.0.5" - dependencies: - language-subtag-registry: ~0.3.2 - checksum: c81b5d8b9f5f9cfd06ee71ada6ddfe1cf83044dd5eeefcd1e420ad491944da8957688db4a0a9bc562df4afdc2783425cbbdfd152c01d93179cf86888903123cf - languageName: node - linkType: hard - -"levn@npm:^0.4.1": - version: 0.4.1 - resolution: "levn@npm:0.4.1" - dependencies: - prelude-ls: ^1.2.1 - type-check: ~0.4.0 - checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 - languageName: node - linkType: hard - -"lodash.get@npm:^4.4.2": - version: 4.4.2 - resolution: "lodash.get@npm:4.4.2" - checksum: e403047ddb03181c9d0e92df9556570e2b67e0f0a930fcbbbd779370972368f5568e914f913e93f3b08f6d492abc71e14d4e9b7a18916c31fa04bd2306efe545 - languageName: node - linkType: hard - -"lodash.merge@npm:^4.6.2": - version: 4.6.2 - resolution: "lodash.merge@npm:4.6.2" - checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 - languageName: node - linkType: hard - -"lodash.truncate@npm:^4.4.2": - version: 4.4.2 - resolution: "lodash.truncate@npm:4.4.2" - checksum: b463d8a382cfb5f0e71c504dcb6f807a7bd379ff1ea216669aa42c52fc28c54e404bfbd96791aa09e6df0de2c1d7b8f1b7f4b1a61f324d38fe98bc535aeee4f5 - languageName: node - linkType: hard - -"lodash@npm:^4.17.19, lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 - languageName: node - linkType: hard - -"log-symbols@npm:^4.1.0": - version: 4.1.0 - resolution: "log-symbols@npm:4.1.0" - dependencies: - chalk: ^4.1.0 - is-unicode-supported: ^0.1.0 - checksum: fce1497b3135a0198803f9f07464165e9eb83ed02ceb2273930a6f8a508951178d8cf4f0378e9d28300a2ed2bc49050995d2bd5f53ab716bb15ac84d58c6ef74 - languageName: node - linkType: hard - -"loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" - dependencies: - js-tokens: ^3.0.0 || ^4.0.0 - bin: - loose-envify: cli.js - checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 - languageName: node - linkType: hard - -"lower-case-first@npm:^1.0.0": - version: 1.0.2 - resolution: "lower-case-first@npm:1.0.2" - dependencies: - lower-case: ^1.1.2 - checksum: 97eb5ce68998153552f3627d405f6821299a45dac90423f712ccd696f77fa96e9d707a5509970c8b61b99c08947eb1e70e35cddb67bc40ea64069c574edd4f78 - languageName: node - linkType: hard - -"lower-case@npm:^1.1.0, lower-case@npm:^1.1.1, lower-case@npm:^1.1.2": - version: 1.1.4 - resolution: "lower-case@npm:1.1.4" - checksum: 1ca9393b5eaef94a64e3f89e38b63d15bc7182a91171e6ad1550f51d710ec941540a065b274188f2e6b4576110cc2d11b50bc4bb7c603a040ddeb1db4ca95197 - languageName: node - linkType: hard - -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: ^4.0.0 - checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 - languageName: node - linkType: hard - -"make-error@npm:^1.1.1": - version: 1.3.6 - resolution: "make-error@npm:1.3.6" - checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 - languageName: node - linkType: hard - -"merge-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "merge-stream@npm:2.0.0" - checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 - languageName: node - linkType: hard - -"merge2@npm:^1.2.3, merge2@npm:^1.3.0, merge2@npm:^1.4.1": - version: 1.4.1 - resolution: "merge2@npm:1.4.1" - checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 - languageName: node - linkType: hard - -"micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" - dependencies: - braces: ^3.0.2 - picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc - languageName: node - linkType: hard - -"mimic-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "mimic-fn@npm:2.1.0" - checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a - languageName: node - linkType: hard - -"mimic-fn@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-fn@npm:4.0.0" - checksum: 995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: ^1.1.7 - checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a - languageName: node - linkType: hard - -"minimatch@npm:^9.0.0": - version: 9.0.2 - resolution: "minimatch@npm:9.0.2" - dependencies: - brace-expansion: ^2.0.1 - checksum: 2eb12e2047a062fdb973fb51b9803f2455e3a00977858c038d66646d303a5a15bbcbc6ed5a2fc403bc869b1309f829ed3acd881d3246faf044ea7a494974b924 - languageName: node - linkType: hard - -"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 - languageName: node - linkType: hard - -"mkdirp@npm:^0.5.1": - version: 0.5.6 - resolution: "mkdirp@npm:0.5.6" - dependencies: - minimist: ^1.2.6 - bin: - mkdirp: bin/cmd.js - checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 - languageName: node - linkType: hard - -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f - languageName: node - linkType: hard - -"ms@npm:^2.1.1": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d - languageName: node - linkType: hard - -"mute-stream@npm:0.0.8": - version: 0.0.8 - resolution: "mute-stream@npm:0.0.8" - checksum: ff48d251fc3f827e5b1206cda0ffdaec885e56057ee86a3155e1951bc940fd5f33531774b1cc8414d7668c10a8907f863f6561875ee6e8768931a62121a531a1 - languageName: node - linkType: hard - -"nanoid@npm:^3.3.4": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" - bin: - nanoid: bin/nanoid.cjs - checksum: 7d0eda657002738aa5206107bd0580aead6c95c460ef1bdd0b1a87a9c7ae6277ac2e9b945306aaa5b32c6dcb7feaf462d0f552e7f8b5718abfc6ead5c94a71b3 - languageName: node - linkType: hard - -"natural-compare@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare@npm:1.4.0" - checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d - languageName: node - linkType: hard - -"neo-async@npm:^2.6.0": - version: 2.6.2 - resolution: "neo-async@npm:2.6.2" - checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9 - languageName: node - linkType: hard - -"next@npm:^13.4.1": - version: 13.4.7 - resolution: "next@npm:13.4.7" - dependencies: - "@next/env": 13.4.7 - "@next/swc-darwin-arm64": 13.4.7 - "@next/swc-darwin-x64": 13.4.7 - "@next/swc-linux-arm64-gnu": 13.4.7 - "@next/swc-linux-arm64-musl": 13.4.7 - "@next/swc-linux-x64-gnu": 13.4.7 - "@next/swc-linux-x64-musl": 13.4.7 - "@next/swc-win32-arm64-msvc": 13.4.7 - "@next/swc-win32-ia32-msvc": 13.4.7 - "@next/swc-win32-x64-msvc": 13.4.7 - "@swc/helpers": 0.5.1 - busboy: 1.6.0 - caniuse-lite: ^1.0.30001406 - postcss: 8.4.14 - styled-jsx: 5.1.1 - watchpack: 2.4.0 - zod: 3.21.4 - peerDependencies: - "@opentelemetry/api": ^1.1.0 - fibers: ">= 3.1.0" - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - dependenciesMeta: - "@next/swc-darwin-arm64": - optional: true - "@next/swc-darwin-x64": - optional: true - "@next/swc-linux-arm64-gnu": - optional: true - "@next/swc-linux-arm64-musl": - optional: true - "@next/swc-linux-x64-gnu": - optional: true - "@next/swc-linux-x64-musl": - optional: true - "@next/swc-win32-arm64-msvc": - optional: true - "@next/swc-win32-ia32-msvc": - optional: true - "@next/swc-win32-x64-msvc": - optional: true - peerDependenciesMeta: - "@opentelemetry/api": - optional: true - fibers: - optional: true - sass: - optional: true - bin: - next: dist/bin/next - checksum: 76026a5def68c00064bc4860cd15a5f292220ccc73ff24245b3658a90a46f66c290d3543a59e1cb91310145141d4ad1238d7cf652f41f47cdf434ab8705af7d1 - languageName: node - linkType: hard - -"no-case@npm:^2.2.0, no-case@npm:^2.3.2": - version: 2.3.2 - resolution: "no-case@npm:2.3.2" - dependencies: - lower-case: ^1.1.1 - checksum: 856487731936fef44377ca74fdc5076464aba2e0734b56a4aa2b2a23d5b154806b591b9b2465faa59bb982e2b5c9391e3685400957fb4eeb38f480525adcf3dd - languageName: node - linkType: hard - -"node-plop@npm:^0.26.3": - version: 0.26.3 - resolution: "node-plop@npm:0.26.3" - dependencies: - "@babel/runtime-corejs3": ^7.9.2 - "@types/inquirer": ^6.5.0 - change-case: ^3.1.0 - del: ^5.1.0 - globby: ^10.0.1 - handlebars: ^4.4.3 - inquirer: ^7.1.0 - isbinaryfile: ^4.0.2 - lodash.get: ^4.4.2 - mkdirp: ^0.5.1 - resolve: ^1.12.0 - checksum: 4b29dd4f343155e7dc516b5055591135ab4e1366bb4c8720d430741ed1ffb0ce63aa3cedf9024c22117a005270aaaf67999784a91596939280ba38cca5c097b9 - languageName: node - linkType: hard - -"npm-run-path@npm:^4.0.1": - version: 4.0.1 - resolution: "npm-run-path@npm:4.0.1" - dependencies: - path-key: ^3.0.0 - checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 - languageName: node - linkType: hard - -"npm-run-path@npm:^5.1.0": - version: 5.1.0 - resolution: "npm-run-path@npm:5.1.0" - dependencies: - path-key: ^4.0.0 - checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66 - languageName: node - linkType: hard - -"object-assign@npm:^4.1.1": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f - languageName: node - linkType: hard - -"object-inspect@npm:^1.12.3, object-inspect@npm:^1.9.0": - version: 1.12.3 - resolution: "object-inspect@npm:1.12.3" - checksum: dabfd824d97a5f407e6d5d24810d888859f6be394d8b733a77442b277e0808860555176719c5905e765e3743a7cada6b8b0a3b85e5331c530fd418cc8ae991db - languageName: node - linkType: hard - -"object-keys@npm:^1.1.1": - version: 1.1.1 - resolution: "object-keys@npm:1.1.1" - checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a - languageName: node - linkType: hard - -"object.assign@npm:^4.1.4": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - has-symbols: ^1.0.3 - object-keys: ^1.1.1 - checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864 - languageName: node - linkType: hard - -"object.entries@npm:^1.1.5, object.entries@npm:^1.1.6": - version: 1.1.6 - resolution: "object.entries@npm:1.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 0f8c47517e6a9a980241eafe3b73de11e59511883173c2b93d67424a008e47e11b77c80e431ad1d8a806f6108b225a1cab9223e53e555776c612a24297117d28 - languageName: node - linkType: hard - -"object.fromentries@npm:^2.0.5, object.fromentries@npm:^2.0.6": - version: 2.0.6 - resolution: "object.fromentries@npm:2.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 453c6d694180c0c30df451b60eaf27a5b9bca3fb43c37908fd2b78af895803dc631242bcf05582173afa40d8d0e9c96e16e8874b39471aa53f3ac1f98a085d85 - languageName: node - linkType: hard - -"object.hasown@npm:^1.1.0, object.hasown@npm:^1.1.2": - version: 1.1.2 - resolution: "object.hasown@npm:1.1.2" - dependencies: - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: b936572536db0cdf38eb30afd2f1026a8b6f2cc5d2c4497c9d9bbb01eaf3e980dead4fd07580cfdd098e6383e5a9db8212d3ea0c6bdd2b5e68c60aa7e3b45566 - languageName: node - linkType: hard - -"object.values@npm:^1.1.5, object.values@npm:^1.1.6": - version: 1.1.6 - resolution: "object.values@npm:1.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: f6fff9fd817c24cfd8107f50fb33061d81cd11bacc4e3dbb3852e9ff7692fde4dbce823d4333ea27cd9637ef1b6690df5fbb61f1ed314fa2959598dc3ae23d8e - languageName: node - linkType: hard - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: 1 - checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 - languageName: node - linkType: hard - -"onetime@npm:^5.1.0, onetime@npm:^5.1.2": - version: 5.1.2 - resolution: "onetime@npm:5.1.2" - dependencies: - mimic-fn: ^2.1.0 - checksum: 2478859ef817fc5d4e9c2f9e5728512ddd1dbc9fb7829ad263765bb6d3b91ce699d6e2332eef6b7dff183c2f490bd3349f1666427eaba4469fba0ac38dfd0d34 - languageName: node - linkType: hard - -"onetime@npm:^6.0.0": - version: 6.0.0 - resolution: "onetime@npm:6.0.0" - dependencies: - mimic-fn: ^4.0.0 - checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 - languageName: node - linkType: hard - -"open@npm:^9.1.0": - version: 9.1.0 - resolution: "open@npm:9.1.0" - dependencies: - default-browser: ^4.0.0 - define-lazy-prop: ^3.0.0 - is-inside-container: ^1.0.0 - is-wsl: ^2.2.0 - checksum: 3993c0f61d51fed8ac290e99c9c3cf45d3b6cfb3e2aa2b74cafd312c3486c22fd81df16ac8f3ab91dd8a4e3e729a16fc2480cfc406c4833416cf908acf1ae7c9 - languageName: node - linkType: hard - -"optionator@npm:^0.9.1": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" - dependencies: - "@aashutoshrathi/word-wrap": ^1.2.3 - deep-is: ^0.1.3 - fast-levenshtein: ^2.0.6 - levn: ^0.4.1 - prelude-ls: ^1.2.1 - type-check: ^0.4.0 - checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a - languageName: node - linkType: hard - -"ora@npm:^5.4.1": - version: 5.4.1 - resolution: "ora@npm:5.4.1" - dependencies: - bl: ^4.1.0 - chalk: ^4.1.0 - cli-cursor: ^3.1.0 - cli-spinners: ^2.5.0 - is-interactive: ^1.0.0 - is-unicode-supported: ^0.1.0 - log-symbols: ^4.1.0 - strip-ansi: ^6.0.0 - wcwidth: ^1.0.1 - checksum: 28d476ee6c1049d68368c0dc922e7225e3b5600c3ede88fade8052837f9ed342625fdaa84a6209302587c8ddd9b664f71f0759833cbdb3a4cf81344057e63c63 - languageName: node - linkType: hard - -"os-tmpdir@npm:~1.0.2": - version: 1.0.2 - resolution: "os-tmpdir@npm:1.0.2" - checksum: 5666560f7b9f10182548bf7013883265be33620b1c1b4a4d405c25be2636f970c5488ff3e6c48de75b55d02bde037249fe5dbfbb4c0fb7714953d56aed062e6d - languageName: node - linkType: hard - -"p-map@npm:^3.0.0": - version: 3.0.0 - resolution: "p-map@npm:3.0.0" - dependencies: - aggregate-error: ^3.0.0 - checksum: 49b0fcbc66b1ef9cd379de1b4da07fa7a9f84b41509ea3f461c31903623aaba8a529d22f835e0d77c7cb9fcc16e4fae71e308fd40179aea514ba68f27032b5d5 - languageName: node - linkType: hard - -"param-case@npm:^2.1.0": - version: 2.1.1 - resolution: "param-case@npm:2.1.1" - dependencies: - no-case: ^2.2.0 - checksum: 3a63dcb8d8dc7995a612de061afdc7bb6fe7bd0e6db994db8d4cae999ed879859fd24389090e1a0d93f4c9207ebf8c048c870f468a3f4767161753e03cb9ab58 - languageName: node - linkType: hard - -"parent-module@npm:^1.0.0": - version: 1.0.1 - resolution: "parent-module@npm:1.0.1" - dependencies: - callsites: ^3.0.0 - checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff - languageName: node - linkType: hard - -"pascal-case@npm:^2.0.0": - version: 2.0.1 - resolution: "pascal-case@npm:2.0.1" - dependencies: - camel-case: ^3.0.0 - upper-case-first: ^1.1.0 - checksum: 4c539bf556572812f64a02fc6b544f3d2b51db12aed484e5162ed7f8ac2b366775d15e536091c890d71d82bdf9153128321f21574721b3a984bd85df9e519a35 - languageName: node - linkType: hard - -"path-case@npm:^2.1.0": - version: 2.1.1 - resolution: "path-case@npm:2.1.1" - dependencies: - no-case: ^2.2.0 - checksum: eb1da508c28378715cbe4ce054ee5f83a570c5010f041f4cfb439c811f7a78e36c46f26a8d59b2594c3882b53db06ef26195519c27f86523dc5d19c2e29f306d - languageName: node - linkType: hard - -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 - languageName: node - linkType: hard - -"path-key@npm:^3.0.0, path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 - languageName: node - linkType: hard - -"path-key@npm:^4.0.0": - version: 4.0.0 - resolution: "path-key@npm:4.0.0" - checksum: 8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a - languageName: node - linkType: hard - -"path-type@npm:^4.0.0": - version: 4.0.0 - resolution: "path-type@npm:4.0.0" - checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 - languageName: node - linkType: hard - -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 - languageName: node - linkType: hard - -"picomatch@npm:^2.3.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf - languageName: node - linkType: hard - -"postcss@npm:8.4.14": - version: 8.4.14 - resolution: "postcss@npm:8.4.14" - dependencies: - nanoid: ^3.3.4 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: fe58766ff32e4becf65a7d57678995cfd239df6deed2fe0557f038b47c94e4132e7e5f68b5aa820c13adfec32e523b693efaeb65798efb995ce49ccd83953816 - languageName: node - linkType: hard - -"prelude-ls@npm:^1.2.1": - version: 1.2.1 - resolution: "prelude-ls@npm:1.2.1" - checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a - languageName: node - linkType: hard - -"prettier@npm:^2.5.1": - version: 2.8.8 - resolution: "prettier@npm:2.8.8" - bin: - prettier: bin-prettier.js - checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 - languageName: node - linkType: hard - -"progress@npm:^2.0.0": - version: 2.0.3 - resolution: "progress@npm:2.0.3" - checksum: f67403fe7b34912148d9252cb7481266a354bd99ce82c835f79070643bb3c6583d10dbcfda4d41e04bbc1d8437e9af0fb1e1f2135727878f5308682a579429b7 - languageName: node - linkType: hard - -"prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": - version: 15.8.1 - resolution: "prop-types@npm:15.8.1" - dependencies: - loose-envify: ^1.4.0 - object-assign: ^4.1.1 - react-is: ^16.13.1 - checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0": - version: 2.3.0 - resolution: "punycode@npm:2.3.0" - checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200 - languageName: node - linkType: hard - -"queue-microtask@npm:^1.2.2": - version: 1.2.3 - resolution: "queue-microtask@npm:1.2.3" - checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 - languageName: node - linkType: hard - -"rc@npm:^1.0.1, rc@npm:^1.1.6": - version: 1.2.8 - resolution: "rc@npm:1.2.8" - dependencies: - deep-extend: ^0.6.0 - ini: ~1.3.0 - minimist: ^1.2.0 - strip-json-comments: ~2.0.1 - bin: - rc: ./cli.js - checksum: 2e26e052f8be2abd64e6d1dabfbd7be03f80ec18ccbc49562d31f617d0015fbdbcf0f9eed30346ea6ab789e0fdfe4337f033f8016efdbee0df5354751842080e - languageName: node - linkType: hard - -"react-dom@npm:^18.2.0": - version: 18.2.0 - resolution: "react-dom@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - scheduler: ^0.23.0 - peerDependencies: - react: ^18.2.0 - checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc - languageName: node - linkType: hard - -"react-is@npm:^16.13.1": - version: 16.13.1 - resolution: "react-is@npm:16.13.1" - checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f - languageName: node - linkType: hard - -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" - dependencies: - loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b - languageName: node - linkType: hard - -"react@npm:^18.2.0": - version: 18.2.0 - resolution: "react@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b - languageName: node - linkType: hard - -"readable-stream@npm:^3.4.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: ^2.0.3 - string_decoder: ^1.1.1 - util-deprecate: ^1.0.1 - checksum: bdcbe6c22e846b6af075e32cf8f4751c2576238c5043169a1c221c92ee2878458a816a4ea33f4c67623c0b6827c8a400409bfb3cf0bf3381392d0b1dfb52ac8d - languageName: node - linkType: hard - -"regenerator-runtime@npm:^0.13.11": - version: 0.13.11 - resolution: "regenerator-runtime@npm:0.13.11" - checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4 - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.4.3": - version: 1.5.0 - resolution: "regexp.prototype.flags@npm:1.5.0" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - functions-have-names: ^1.2.3 - checksum: c541687cdbdfff1b9a07f6e44879f82c66bbf07665f9a7544c5fd16acdb3ec8d1436caab01662d2fbcad403f3499d49ab0b77fbc7ef29ef961d98cc4bc9755b4 - languageName: node - linkType: hard - -"regexpp@npm:^3.1.0": - version: 3.2.0 - resolution: "regexpp@npm:3.2.0" - checksum: a78dc5c7158ad9ddcfe01aa9144f46e192ddbfa7b263895a70a5c6c73edd9ce85faf7c0430e59ac38839e1734e275b9c3de5c57ee3ab6edc0e0b1bdebefccef8 - languageName: node - linkType: hard - -"registry-auth-token@npm:3.3.2": - version: 3.3.2 - resolution: "registry-auth-token@npm:3.3.2" - dependencies: - rc: ^1.1.6 - safe-buffer: ^5.0.1 - checksum: c9d7ae160a738f1fa825556e3669e6c771d2c0239ce37679f7e8646157a97d0a76464738be075002a1f754ef9bfb913b689f4bbfd5296d28f136fbf98c8c2217 - languageName: node - linkType: hard - -"registry-url@npm:3.1.0": - version: 3.1.0 - resolution: "registry-url@npm:3.1.0" - dependencies: - rc: ^1.0.1 - checksum: 6d223da41b04e1824f5faa63905c6f2e43b216589d72794111573f017352b790aef42cd1f826463062f89d804abb2027e3d9665d2a9a0426a11eedd04d470af3 - languageName: node - linkType: hard - -"require-from-string@npm:^2.0.2": - version: 2.0.2 - resolution: "require-from-string@npm:2.0.2" - checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b - languageName: node - linkType: hard - -"resolve-from@npm:^4.0.0": - version: 4.0.0 - resolution: "resolve-from@npm:4.0.0" - checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f - languageName: node - linkType: hard - -"resolve-pkg-maps@npm:^1.0.0": - version: 1.0.0 - resolution: "resolve-pkg-maps@npm:1.0.0" - checksum: 1012afc566b3fdb190a6309cc37ef3b2dcc35dff5fa6683a9d00cd25c3247edfbc4691b91078c97adc82a29b77a2660c30d791d65dab4fc78bfc473f60289977 - languageName: node - linkType: hard - -"resolve@npm:^1.12.0, resolve@npm:^1.22.1": - version: 1.22.3 - resolution: "resolve@npm:1.22.3" - dependencies: - is-core-module: ^2.12.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: fb834b81348428cb545ff1b828a72ea28feb5a97c026a1cf40aa1008352c72811ff4d4e71f2035273dc536dcfcae20c13604ba6283c612d70fa0b6e44519c374 - languageName: node - linkType: hard - -"resolve@npm:^2.0.0-next.3, resolve@npm:^2.0.0-next.4": - version: 2.0.0-next.4 - resolution: "resolve@npm:2.0.0-next.4" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: c438ac9a650f2030fd074219d7f12ceb983b475da2d89ad3d6dd05fbf6b7a0a8cd37d4d10b43cb1f632bc19f22246ab7f36ebda54d84a29bfb2910a0680906d3 - languageName: node - linkType: hard - -"resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin": - version: 1.22.3 - resolution: "resolve@patch:resolve@npm%3A1.22.3#~builtin::version=1.22.3&hash=c3c19d" - dependencies: - is-core-module: ^2.12.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: ad59734723b596d0891321c951592ed9015a77ce84907f89c9d9307dd0c06e11a67906a3e628c4cae143d3e44898603478af0ddeb2bba3f229a9373efe342665 - languageName: node - linkType: hard - -"resolve@patch:resolve@^2.0.0-next.3#~builtin, resolve@patch:resolve@^2.0.0-next.4#~builtin": - version: 2.0.0-next.4 - resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin::version=2.0.0-next.4&hash=c3c19d" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 4bf9f4f8a458607af90518ff73c67a4bc1a38b5a23fef2bb0ccbd45e8be89820a1639b637b0ba377eb2be9eedfb1739a84cde24fe4cd670c8207d8fea922b011 - languageName: node - linkType: hard - -"restore-cursor@npm:^3.1.0": - version: 3.1.0 - resolution: "restore-cursor@npm:3.1.0" - dependencies: - onetime: ^5.1.0 - signal-exit: ^3.0.2 - checksum: f877dd8741796b909f2a82454ec111afb84eb45890eb49ac947d87991379406b3b83ff9673a46012fca0d7844bb989f45cc5b788254cf1a39b6b5a9659de0630 - languageName: node - linkType: hard - -"reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc - languageName: node - linkType: hard - -"rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: ^7.1.3 - bin: - rimraf: bin.js - checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 - languageName: node - linkType: hard - -"run-applescript@npm:^5.0.0": - version: 5.0.0 - resolution: "run-applescript@npm:5.0.0" - dependencies: - execa: ^5.0.0 - checksum: d00c2dbfa5b2d774de7451194b8b125f40f65fc183de7d9dcae97f57f59433586d3c39b9001e111c38bfa24c3436c99df1bb4066a2a0c90d39a8c4cd6889af77 - languageName: node - linkType: hard - -"run-async@npm:^2.4.0": - version: 2.4.1 - resolution: "run-async@npm:2.4.1" - checksum: a2c88aa15df176f091a2878eb840e68d0bdee319d8d97bbb89112223259cebecb94bc0defd735662b83c2f7a30bed8cddb7d1674eb48ae7322dc602b22d03797 - languageName: node - linkType: hard - -"run-parallel@npm:^1.1.9": - version: 1.2.0 - resolution: "run-parallel@npm:1.2.0" - dependencies: - queue-microtask: ^1.2.2 - checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d - languageName: node - linkType: hard - -"rxjs@npm:^6.4.0, rxjs@npm:^6.6.0": - version: 6.6.7 - resolution: "rxjs@npm:6.6.7" - dependencies: - tslib: ^1.9.0 - checksum: bc334edef1bb8bbf56590b0b25734ba0deaf8825b703256a93714308ea36dff8a11d25533671adf8e104e5e8f256aa6fdfe39b2e248cdbd7a5f90c260acbbd1b - languageName: node - linkType: hard - -"rxjs@npm:^7.5.5": - version: 7.8.1 - resolution: "rxjs@npm:7.8.1" - dependencies: - tslib: ^2.1.0 - checksum: de4b53db1063e618ec2eca0f7965d9137cabe98cf6be9272efe6c86b47c17b987383df8574861bcced18ebd590764125a901d5506082be84a8b8e364bf05f119 - languageName: node - linkType: hard - -"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 - languageName: node - linkType: hard - -"safe-regex-test@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-regex-test@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.3 - is-regex: ^1.1.4 - checksum: bc566d8beb8b43c01b94e67de3f070fd2781685e835959bbbaaec91cc53381145ca91f69bd837ce6ec244817afa0a5e974fc4e40a2957f0aca68ac3add1ddd34 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 - languageName: node - linkType: hard - -"scheduler@npm:^0.23.0": - version: 0.23.0 - resolution: "scheduler@npm:0.23.0" - dependencies: - loose-envify: ^1.1.0 - checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a - languageName: node - linkType: hard - -"semver@npm:^6.3.0": - version: 6.3.0 - resolution: "semver@npm:6.3.0" - bin: - semver: ./bin/semver.js - checksum: 1b26ecf6db9e8292dd90df4e781d91875c0dcc1b1909e70f5d12959a23c7eebb8f01ea581c00783bbee72ceeaad9505797c381756326073850dc36ed284b21b9 - languageName: node - linkType: hard - -"semver@npm:^7.0.0, semver@npm:^7.2.1, semver@npm:^7.3.7, semver@npm:^7.3.8": - version: 7.5.3 - resolution: "semver@npm:7.5.3" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: 9d58db16525e9f749ad0a696a1f27deabaa51f66e91d2fa2b0db3de3e9644e8677de3b7d7a03f4c15bc81521e0c3916d7369e0572dbde250d9bedf5194e2a8a7 - languageName: node - linkType: hard - -"sentence-case@npm:^2.1.0": - version: 2.1.1 - resolution: "sentence-case@npm:2.1.1" - dependencies: - no-case: ^2.2.0 - upper-case-first: ^1.1.2 - checksum: ce5ca48804051e056a6956ad75a1a7d833e5d8f5021a015d380a22d3cf04496d5238de2e5c876d9701a9218633052c3a65911ca1b6460d36a41ecad46e81d139 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: ^3.0.0 - checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 - languageName: node - linkType: hard - -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" - dependencies: - call-bind: ^1.0.0 - get-intrinsic: ^1.0.2 - object-inspect: ^1.9.0 - checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 - languageName: node - linkType: hard - -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 - languageName: node - linkType: hard - -"slash@npm:^3.0.0": - version: 3.0.0 - resolution: "slash@npm:3.0.0" - checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c - languageName: node - linkType: hard - -"slash@npm:^4.0.0": - version: 4.0.0 - resolution: "slash@npm:4.0.0" - checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d - languageName: node - linkType: hard - -"slice-ansi@npm:^4.0.0": - version: 4.0.0 - resolution: "slice-ansi@npm:4.0.0" - dependencies: - ansi-styles: ^4.0.0 - astral-regex: ^2.0.0 - is-fullwidth-code-point: ^3.0.0 - checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 - languageName: node - linkType: hard - -"snake-case@npm:^2.1.0": - version: 2.1.0 - resolution: "snake-case@npm:2.1.0" - dependencies: - no-case: ^2.2.0 - checksum: 7e42b4841103be4dd050b2f57f5cb423d5164524c1cb3d81efda9809265a82a2d02ddf44361beae37d75a239308e6414be85fe441dc48cd70c708cb975387d10 - languageName: node - linkType: hard - -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c - languageName: node - linkType: hard - -"source-map@npm:^0.6.1": - version: 0.6.1 - resolution: "source-map@npm:0.6.1" - checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 - languageName: node - linkType: hard - -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 - languageName: node - linkType: hard - -"streamsearch@npm:^1.1.0": - version: 1.1.0 - resolution: "streamsearch@npm:1.1.0" - checksum: 1cce16cea8405d7a233d32ca5e00a00169cc0e19fbc02aa839959985f267335d435c07f96e5e0edd0eadc6d39c98d5435fb5bbbdefc62c41834eadc5622ad942 - languageName: node - linkType: hard - -"string-width@npm:^4.1.0, string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: ^8.0.0 - is-fullwidth-code-point: ^3.0.0 - strip-ansi: ^6.0.1 - checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb - languageName: node - linkType: hard - -"string.prototype.matchall@npm:^4.0.6, string.prototype.matchall@npm:^4.0.8": - version: 4.0.8 - resolution: "string.prototype.matchall@npm:4.0.8" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - get-intrinsic: ^1.1.3 - has-symbols: ^1.0.3 - internal-slot: ^1.0.3 - regexp.prototype.flags: ^1.4.3 - side-channel: ^1.0.4 - checksum: 952da3a818de42ad1c10b576140a5e05b4de7b34b8d9dbf00c3ac8c1293e9c0f533613a39c5cda53e0a8221f2e710bc2150e730b1c2278d60004a8a35726efb6 - languageName: node - linkType: hard - -"string.prototype.trim@npm:^1.2.7": - version: 1.2.7 - resolution: "string.prototype.trim@npm:1.2.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 05b7b2d6af63648e70e44c4a8d10d8cc457536df78b55b9d6230918bde75c5987f6b8604438c4c8652eb55e4fc9725d2912789eb4ec457d6995f3495af190c09 - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimend@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 0fdc34645a639bd35179b5a08227a353b88dc089adf438f46be8a7c197fc3f22f8514c1c9be4629b3cd29c281582730a8cbbad6466c60f76b5f99cf2addb132e - languageName: node - linkType: hard - -"string.prototype.trimstart@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimstart@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 89080feef416621e6ef1279588994305477a7a91648d9436490d56010a1f7adc39167cddac7ce0b9884b8cdbef086987c4dcb2960209f2af8bac0d23ceff4f41 - languageName: node - linkType: hard - -"string_decoder@npm:^1.1.1": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: ~5.2.0 - checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 - languageName: node - linkType: hard - -"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: ^5.0.1 - checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c - languageName: node - linkType: hard - -"strip-bom@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-bom@npm:3.0.0" - checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b - languageName: node - linkType: hard - -"strip-final-newline@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-final-newline@npm:2.0.0" - checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 - languageName: node - linkType: hard - -"strip-final-newline@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-final-newline@npm:3.0.0" - checksum: 23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 - languageName: node - linkType: hard - -"strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 - languageName: node - linkType: hard - -"strip-json-comments@npm:~2.0.1": - version: 2.0.1 - resolution: "strip-json-comments@npm:2.0.1" - checksum: 1074ccb63270d32ca28edfb0a281c96b94dc679077828135141f27d52a5a398ef5e78bcf22809d23cadc2b81dfbe345eb5fd8699b385c8b1128907dec4a7d1e1 - languageName: node - linkType: hard - -"styled-jsx@npm:5.1.1": - version: 5.1.1 - resolution: "styled-jsx@npm:5.1.1" - dependencies: - client-only: 0.0.1 - peerDependencies: - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" - peerDependenciesMeta: - "@babel/core": - optional: true - babel-plugin-macros: - optional: true - checksum: 523a33b38603492547e861b98e29c873939b04e15fbe5ef16132c6f1e15958126647983c7d4675325038b428a5e91183d996e90141b18bdd1bbadf6e2c45b2fa - languageName: node - linkType: hard - -"supports-color@npm:^5.3.0": - version: 5.5.0 - resolution: "supports-color@npm:5.5.0" - dependencies: - has-flag: ^3.0.0 - checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac - languageName: node - linkType: hard - -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: ^4.0.0 - checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae - languageName: node - linkType: hard - -"swap-case@npm:^1.1.0": - version: 1.1.2 - resolution: "swap-case@npm:1.1.2" - dependencies: - lower-case: ^1.1.1 - upper-case: ^1.1.1 - checksum: 37b0c4988e12520fba54018f7fe259d62902e97349366209d2af9b1d5e741692c8f17da9d5e780c7bd1a56864bbb51d53eaf1a101a11afdfcae157912a3691d8 - languageName: node - linkType: hard - -"synckit@npm:^0.8.5": - version: 0.8.5 - resolution: "synckit@npm:0.8.5" - dependencies: - "@pkgr/utils": ^2.3.1 - tslib: ^2.5.0 - checksum: 8a9560e5d8f3d94dc3cf5f7b9c83490ffa30d320093560a37b88f59483040771fd1750e76b9939abfbb1b5a23fd6dfbae77f6b338abffe7cae7329cd9b9bb86b - languageName: node - linkType: hard - -"table@npm:^6.0.9": - version: 6.8.1 - resolution: "table@npm:6.8.1" - dependencies: - ajv: ^8.0.1 - lodash.truncate: ^4.4.2 - slice-ansi: ^4.0.0 - string-width: ^4.2.3 - strip-ansi: ^6.0.1 - checksum: 08249c7046125d9d0a944a6e96cfe9ec66908d6b8a9db125531be6eb05fa0de047fd5542e9d43b4f987057f00a093b276b8d3e19af162a9c40db2681058fd306 - languageName: node - linkType: hard - -"tapable@npm:^2.2.0": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 - languageName: node - linkType: hard - -"text-table@npm:^0.2.0": - version: 0.2.0 - resolution: "text-table@npm:0.2.0" - checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a - languageName: node - linkType: hard - -"through@npm:^2.3.6": - version: 2.3.8 - resolution: "through@npm:2.3.8" - checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd - languageName: node - linkType: hard - -"title-case@npm:^2.1.0": - version: 2.1.1 - resolution: "title-case@npm:2.1.1" - dependencies: - no-case: ^2.2.0 - upper-case: ^1.0.3 - checksum: e88ddfc4608a7fb18ed440139d9c42a5f8a50f916e07062be2aef5e2038720746ed51c4fdf9e7190d24a8cc10e6dec9773027fc44450b3a4a5e5c49b4a931fb1 - languageName: node - linkType: hard - -"titleize@npm:^3.0.0": - version: 3.0.0 - resolution: "titleize@npm:3.0.0" - checksum: 71fbbeabbfb36ccd840559f67f21e356e1d03da2915b32d2ae1a60ddcc13a124be2739f696d2feb884983441d159a18649e8d956648d591bdad35c430a6b6d28 - languageName: node - linkType: hard - -"tmp@npm:^0.0.33": - version: 0.0.33 - resolution: "tmp@npm:0.0.33" - dependencies: - os-tmpdir: ~1.0.2 - checksum: 902d7aceb74453ea02abbf58c203f4a8fc1cead89b60b31e354f74ed5b3fb09ea817f94fb310f884a5d16987dd9fa5a735412a7c2dd088dd3d415aa819ae3a28 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: ^7.0.0 - checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed - languageName: node - linkType: hard - -"ts-node@npm:^10.9.1": - version: 10.9.1 - resolution: "ts-node@npm:10.9.1" - 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 - 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 - 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 - checksum: 090adff1302ab20bd3486e6b4799e90f97726ed39e02b39e566f8ab674fd5bd5f727f43615debbfc580d33c6d9d1c6b1b3ce7d8e3cca3e20530a145ffa232c35 - languageName: node - linkType: hard - -"tsconfig-paths@npm:^3.14.1": - version: 3.14.2 - resolution: "tsconfig-paths@npm:3.14.2" - dependencies: - "@types/json5": ^0.0.29 - json5: ^1.0.2 - minimist: ^1.2.6 - strip-bom: ^3.0.0 - checksum: a6162eaa1aed680537f93621b82399c7856afd10ec299867b13a0675e981acac4e0ec00896860480efc59fc10fd0b16fdc928c0b885865b52be62cadac692447 - languageName: node - linkType: hard - -"tsconfig@*, tsconfig@workspace:packages/tsconfig": - version: 0.0.0-use.local - resolution: "tsconfig@workspace:packages/tsconfig" - languageName: unknown - linkType: soft - -"tslib@npm:^1.8.1, tslib@npm:^1.9.0": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd - languageName: node - linkType: hard - -"tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0": - version: 2.6.0 - resolution: "tslib@npm:2.6.0" - checksum: c01066038f950016a18106ddeca4649b4d76caa76ec5a31e2a26e10586a59fceb4ee45e96719bf6c715648e7c14085a81fee5c62f7e9ebee68e77a5396e5538f - languageName: node - linkType: hard - -"tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" - dependencies: - tslib: ^1.8.1 - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 1843f4c1b2e0f975e08c4c21caa4af4f7f65a12ac1b81b3b8489366826259323feb3fc7a243123453d2d1a02314205a7634e048d4a8009921da19f99755cdc48 - languageName: node - linkType: hard - -"turbo-darwin-64@npm:1.10.6": - version: 1.10.6 - resolution: "turbo-darwin-64@npm:1.10.6" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"turbo-darwin-arm64@npm:1.10.6": - version: 1.10.6 - resolution: "turbo-darwin-arm64@npm:1.10.6" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"turbo-linux-64@npm:1.10.6": - version: 1.10.6 - resolution: "turbo-linux-64@npm:1.10.6" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"turbo-linux-arm64@npm:1.10.6": - version: 1.10.6 - resolution: "turbo-linux-arm64@npm:1.10.6" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"turbo-windows-64@npm:1.10.6": - version: 1.10.6 - resolution: "turbo-windows-64@npm:1.10.6" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"turbo-windows-arm64@npm:1.10.6": - version: 1.10.6 - resolution: "turbo-windows-arm64@npm:1.10.6" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"turbo@npm:latest": - version: 1.10.6 - resolution: "turbo@npm:1.10.6" - dependencies: - turbo-darwin-64: 1.10.6 - turbo-darwin-arm64: 1.10.6 - turbo-linux-64: 1.10.6 - turbo-linux-arm64: 1.10.6 - turbo-windows-64: 1.10.6 - turbo-windows-arm64: 1.10.6 - dependenciesMeta: - turbo-darwin-64: - optional: true - turbo-darwin-arm64: - optional: true - turbo-linux-64: - optional: true - turbo-linux-arm64: - optional: true - turbo-windows-64: - optional: true - turbo-windows-arm64: - optional: true - bin: - turbo: bin/turbo - checksum: 920985d59b088e3e203450ee42446a4e0efa7de3a6455828146089e0e9efc4981e52998f7c13fcb730158e652d84bfc49149ebe33ab4a4cc033db7ab32934390 - languageName: node - linkType: hard - -"type-check@npm:^0.4.0, type-check@npm:~0.4.0": - version: 0.4.0 - resolution: "type-check@npm:0.4.0" - dependencies: - prelude-ls: ^1.2.1 - checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a - languageName: node - linkType: hard - -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 - languageName: node - linkType: hard - -"type-fest@npm:^0.21.3": - version: 0.21.3 - resolution: "type-fest@npm:0.21.3" - checksum: e6b32a3b3877f04339bae01c193b273c62ba7bfc9e325b8703c4ee1b32dc8fe4ef5dfa54bf78265e069f7667d058e360ae0f37be5af9f153b22382cd55a9afe0 - languageName: node - linkType: hard - -"typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" - dependencies: - call-bind: ^1.0.2 - for-each: ^0.3.3 - is-typed-array: ^1.1.9 - checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 - languageName: node - linkType: hard - -"typescript@npm:^4.5.2, typescript@npm:^4.5.3": - version: 4.9.5 - resolution: "typescript@npm:4.9.5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db - languageName: node - linkType: hard - -"typescript@patch:typescript@^4.5.2#~builtin, typescript@patch:typescript@^4.5.3#~builtin": - version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=289587" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 1f8f3b6aaea19f0f67cba79057674ba580438a7db55057eb89cc06950483c5d632115c14077f6663ea76fd09fce3c190e6414bb98582ec80aa5a4eaf345d5b68 - languageName: node - linkType: hard - -"uglify-js@npm:^3.1.4": - version: 3.17.4 - resolution: "uglify-js@npm:3.17.4" - bin: - uglifyjs: bin/uglifyjs - checksum: 7b3897df38b6fc7d7d9f4dcd658599d81aa2b1fb0d074829dd4e5290f7318dbca1f4af2f45acb833b95b1fe0ed4698662ab61b87e94328eb4c0a0d3435baf924 - languageName: node - linkType: hard - -"ui@*, ui@workspace:packages/ui": - version: 0.0.0-use.local - resolution: "ui@workspace:packages/ui" - dependencies: - "@types/react": ^18.2.0 - "@types/react-dom": ^18.2.0 - eslint: ^7.32.0 - eslint-config-custom: "*" - react: ^17.0.2 - tsconfig: "*" - typescript: ^4.5.2 - languageName: unknown - linkType: soft - -"unbox-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "unbox-primitive@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - has-bigints: ^1.0.2 - has-symbols: ^1.0.3 - which-boxed-primitive: ^1.0.2 - checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 - languageName: node - linkType: hard - -"universalify@npm:^2.0.0": - version: 2.0.0 - resolution: "universalify@npm:2.0.0" - checksum: 2406a4edf4a8830aa6813278bab1f953a8e40f2f63a37873ffa9a3bc8f9745d06cc8e88f3572cb899b7e509013f7f6fcc3e37e8a6d914167a5381d8440518c44 - languageName: node - linkType: hard - -"untildify@npm:^4.0.0": - version: 4.0.0 - resolution: "untildify@npm:4.0.0" - checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 - languageName: node - linkType: hard - -"update-check@npm:^1.5.4": - version: 1.5.4 - resolution: "update-check@npm:1.5.4" - dependencies: - registry-auth-token: 3.3.2 - registry-url: 3.1.0 - checksum: 2c9f7de6f030364c5ea02a341e5ae2dfe76da6559b32d40dd3b047b3ac0927408cf92d322c51cd8e009688210a85ccbf1eba449762a65a0d1b14f3cdf1ea5c48 - languageName: node - linkType: hard - -"upper-case-first@npm:^1.1.0, upper-case-first@npm:^1.1.2": - version: 1.1.2 - resolution: "upper-case-first@npm:1.1.2" - dependencies: - upper-case: ^1.1.1 - checksum: 7467267967de978316c26c64ca9a4b2fbe5ccb530dc2579b1078bfeb89723ba24bc20881de1d23db301f6e7e5e24b4084e6f5f7ddbb2275a55177d06d9a250b7 - languageName: node - linkType: hard - -"upper-case@npm:^1.0.3, upper-case@npm:^1.1.0, upper-case@npm:^1.1.1, upper-case@npm:^1.1.3": - version: 1.1.3 - resolution: "upper-case@npm:1.1.3" - checksum: 991c845de75fa56e5ad983f15e58494dd77b77cadd79d273cc11e8da400067e9881ae1a52b312aed79b3d754496e2e0712e08d22eae799e35c7f9ba6f3d8a85d - languageName: node - linkType: hard - -"uri-js@npm:^4.2.2": - version: 4.4.1 - resolution: "uri-js@npm:4.4.1" - dependencies: - punycode: ^2.1.0 - checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 - languageName: node - linkType: hard - -"util-deprecate@npm:^1.0.1": - version: 1.0.2 - resolution: "util-deprecate@npm:1.0.2" - checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 - languageName: node - linkType: hard - -"v8-compile-cache-lib@npm:^3.0.1": - version: 3.0.1 - resolution: "v8-compile-cache-lib@npm:3.0.1" - checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 - languageName: node - linkType: hard - -"v8-compile-cache@npm:^2.0.3": - version: 2.3.0 - resolution: "v8-compile-cache@npm:2.3.0" - checksum: adb0a271eaa2297f2f4c536acbfee872d0dd26ec2d76f66921aa7fc437319132773483344207bdbeee169225f4739016d8d2dbf0553913a52bb34da6d0334f8e - languageName: node - linkType: hard - -"validate-npm-package-name@npm:^5.0.0": - version: 5.0.0 - resolution: "validate-npm-package-name@npm:5.0.0" - dependencies: - builtins: ^5.0.0 - checksum: 5342a994986199b3c28e53a8452a14b2bb5085727691ea7aa0d284a6606b127c371e0925ae99b3f1ef7cc7d2c9de75f52eb61a3d1cc45e39bca1e3a9444cbb4e - languageName: node - linkType: hard - -"watchpack@npm:2.4.0": - version: 2.4.0 - resolution: "watchpack@npm:2.4.0" - dependencies: - glob-to-regexp: ^0.4.1 - graceful-fs: ^4.1.2 - checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 - languageName: node - linkType: hard - -"wcwidth@npm:^1.0.1": - version: 1.0.1 - resolution: "wcwidth@npm:1.0.1" - dependencies: - defaults: ^1.0.3 - checksum: 814e9d1ddcc9798f7377ffa448a5a3892232b9275ebb30a41b529607691c0491de47cba426e917a4d08ded3ee7e9ba2f3fe32e62ee3cd9c7d3bafb7754bd553c - languageName: node - linkType: hard - -"web@workspace:apps/web": - version: 0.0.0-use.local - resolution: "web@workspace:apps/web" - dependencies: - "@types/node": ^17.0.12 - "@types/react": ^18.0.22 - "@types/react-dom": ^18.0.7 - eslint-config-custom: "*" - next: ^13.4.1 - react: ^18.2.0 - react-dom: ^18.2.0 - tsconfig: "*" - typescript: ^4.5.3 - ui: "*" - languageName: unknown - linkType: soft - -"which-boxed-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "which-boxed-primitive@npm:1.0.2" - dependencies: - is-bigint: ^1.0.1 - is-boolean-object: ^1.1.0 - is-number-object: ^1.0.4 - is-string: ^1.0.5 - is-symbol: ^1.0.3 - checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.9": - version: 1.1.9 - resolution: "which-typed-array@npm:1.1.9" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - is-typed-array: ^1.1.10 - checksum: fe0178ca44c57699ca2c0e657b64eaa8d2db2372a4e2851184f568f98c478ae3dc3fdb5f7e46c384487046b0cf9e23241423242b277e03e8ba3dabc7c84c98ef - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: ^2.0.0 - bin: - node-which: ./bin/node-which - checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 - languageName: node - linkType: hard - -"wordwrap@npm:^1.0.0": - version: 1.0.0 - resolution: "wordwrap@npm:1.0.0" - checksum: 2a44b2788165d0a3de71fd517d4880a8e20ea3a82c080ce46e294f0b68b69a2e49cff5f99c600e275c698a90d12c5ea32aff06c311f0db2eb3f1201f3e7b2a04 - languageName: node - linkType: hard - -"wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: ^4.0.0 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 - languageName: node - linkType: hard - -"yn@npm:3.1.1": - version: 3.1.1 - resolution: "yn@npm:3.1.1" - checksum: 2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6 - languageName: node - linkType: hard - -"zod@npm:3.21.4": - version: 3.21.4 - resolution: "zod@npm:3.21.4" - checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f - languageName: node - linkType: hard diff --git a/crates/turborepo-lockfiles/fixtures/berry-builtin.lock b/crates/turborepo-lockfiles/fixtures/berry-builtin.lock deleted file mode 100644 index aa472d658f9c8..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/berry-builtin.lock +++ /dev/null @@ -1,103 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"a@workspace:packages/a": - version: 0.0.0-use.local - resolution: "a@workspace:packages/a" - dependencies: - c: "*" - resolve: ^1.22.2 - languageName: unknown - linkType: soft - -"b@workspace:packages/b": - version: 0.0.0-use.local - resolution: "b@workspace:packages/b" - dependencies: - c: "workspace:*" - resolve: 1.22.3 - languageName: unknown - linkType: soft - -"c@*, c@workspace:*, c@workspace:packages/c": - version: 0.0.0-use.local - resolution: "c@workspace:packages/c" - dependencies: - resolve: ^1.22.0 - languageName: unknown - linkType: soft - -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a - languageName: node - linkType: hard - -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: ^1.1.1 - checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 - languageName: node - linkType: hard - -"is-core-module@npm:^2.12.0": - version: 2.12.0 - resolution: "is-core-module@npm:2.12.0" - dependencies: - has: ^1.0.3 - checksum: f7f7eb2ab71fd769ee9fb2385c095d503aa4b5ce0028c04557de03f1e67a87c85e5bac1f215945fc3c955867a139a415a3ec4c4234a0bffdf715232660f440a6 - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a - languageName: node - linkType: hard - -"prune-edge@workspace:.": - version: 0.0.0-use.local - resolution: "prune-edge@workspace:." - languageName: unknown - linkType: soft - -"resolve@npm:1.22.3, resolve@npm:^1.22.0, resolve@npm:^1.22.2": - version: 1.22.3 - resolution: "resolve@npm:1.22.3" - dependencies: - is-core-module: ^2.12.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: fb834b81348428cb545ff1b828a72ea28feb5a97c026a1cf40aa1008352c72811ff4d4e71f2035273dc536dcfcae20c13604ba6283c612d70fa0b6e44519c374 - languageName: node - linkType: hard - -"resolve@patch:resolve@1.22.3#~builtin, resolve@patch:resolve@^1.22.0#~builtin, resolve@patch:resolve@^1.22.2#~builtin": - version: 1.22.3 - resolution: "resolve@patch:resolve@npm%3A1.22.3#~builtin::version=1.22.3&hash=c3c19d" - dependencies: - is-core-module: ^2.12.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: ad59734723b596d0891321c951592ed9015a77ce84907f89c9d9307dd0c06e11a67906a3e628c4cae143d3e44898603478af0ddeb2bba3f229a9373efe342665 - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae - languageName: node - linkType: hard diff --git a/crates/turborepo-lockfiles/fixtures/berry-protocol-collision.lock b/crates/turborepo-lockfiles/fixtures/berry-protocol-collision.lock deleted file mode 100644 index 0450964d02950..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/berry-protocol-collision.lock +++ /dev/null @@ -1,33 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - -"a@workspace:packages/a": - version: 0.0.0-use.local - resolution: "a@workspace:packages/a" - dependencies: - c: "*" - languageName: unknown - linkType: soft - -"b@workspace:packages/b": - version: 0.0.0-use.local - resolution: "b@workspace:packages/b" - dependencies: - c: "workspace:*" - languageName: unknown - linkType: soft - -"c@*, c@workspace:*, c@workspace:packages/c": - version: 0.0.0-use.local - resolution: "c@workspace:packages/c" - languageName: unknown - linkType: soft - -"prune-edge@workspace:.": - version: 0.0.0-use.local - resolution: "prune-edge@workspace:." - languageName: unknown - linkType: soft diff --git a/crates/turborepo-lockfiles/fixtures/berry.lock b/crates/turborepo-lockfiles/fixtures/berry.lock deleted file mode 100644 index 39bed787af265..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/berry.lock +++ /dev/null @@ -1,3284 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8c0 - -"@ampproject/remapping@npm:^2.1.0": - version: 2.2.0 - resolution: "@ampproject/remapping@npm:2.2.0" - dependencies: - "@jridgewell/gen-mapping": ^0.1.0 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: d74d170d06468913921d72430259424b7e4c826b5a7d39ff839a29d547efb97dc577caa8ba3fb5cf023624e9af9d09651afc3d4112a45e2050328abc9b3a2292 - languageName: node - linkType: hard - -"@babel/code-frame@npm:7.12.11": - version: 7.12.11 - resolution: "@babel/code-frame@npm:7.12.11" - dependencies: - "@babel/highlight": ^7.10.4 - checksum: 3963eff3ebfb0e091c7e6f99596ef4b258683e4ba8a134e4e95f77afe85be5c931e184fff6435fb4885d12eba04a5e25532f7fbc292ca13b48e7da943474e2f3 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/code-frame@npm:7.18.6" - dependencies: - "@babel/highlight": ^7.18.6 - checksum: 195e2be3172d7684bf95cff69ae3b7a15a9841ea9d27d3c843662d50cdd7d6470fd9c8e64be84d031117e4a4083486effba39f9aef6bbb2c89f7f21bcfba33ba - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/compat-data@npm:7.19.1" - checksum: f985887ea08a140e4af87a94d3fb17af0345491eb97f5a85b1840255c2e2a97429f32a8fd12a7aae9218af5f1024f1eb12a5cd280d2d69b2337583c17ea506ba - languageName: node - linkType: hard - -"@babel/core@npm:^7.0.0": - version: 7.19.1 - resolution: "@babel/core@npm:7.19.1" - dependencies: - "@ampproject/remapping": ^2.1.0 - "@babel/code-frame": ^7.18.6 - "@babel/generator": ^7.19.0 - "@babel/helper-compilation-targets": ^7.19.1 - "@babel/helper-module-transforms": ^7.19.0 - "@babel/helpers": ^7.19.0 - "@babel/parser": ^7.19.1 - "@babel/template": ^7.18.10 - "@babel/traverse": ^7.19.1 - "@babel/types": ^7.19.0 - convert-source-map: ^1.7.0 - debug: ^4.1.0 - gensync: ^1.0.0-beta.2 - json5: ^2.2.1 - semver: ^6.3.0 - checksum: 941c8c119b80bdba5fafc80bbaa424d51146b6d3c30b8fae35879358dd37c11d3d0926bc7e970a0861229656eedaa8c884d4a3a25cc904086eb73b827a2f1168 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/generator@npm:7.19.0" - dependencies: - "@babel/types": ^7.19.0 - "@jridgewell/gen-mapping": ^0.3.2 - jsesc: ^2.5.1 - checksum: aa3d5785cf8f8e81672dcc61aef351188efeadb20d9f66d79113d82cbcf3bbbdeb829989fa14582108572ddbc4e4027bdceb06ccaf5ec40fa93c2dda8fbcd4aa - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/helper-compilation-targets@npm:7.19.1" - dependencies: - "@babel/compat-data": ^7.19.1 - "@babel/helper-validator-option": ^7.18.6 - browserslist: ^4.21.3 - semver: ^6.3.0 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: c2d3039265e498b341a6b597f855f2fcef02659050fefedf36ad4e6815e6aafe1011a761214cc80d98260ed07ab15a8cbe959a0458e97bec5f05a450e1b1741b - languageName: node - linkType: hard - -"@babel/helper-environment-visitor@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/helper-environment-visitor@npm:7.18.9" - checksum: b25101f6162ddca2d12da73942c08ad203d7668e06663df685634a8fde54a98bc015f6f62938e8554457a592a024108d45b8f3e651fd6dcdb877275b73cc4420 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helper-function-name@npm:7.19.0" - dependencies: - "@babel/template": ^7.18.10 - "@babel/types": ^7.19.0 - checksum: eac1f5db428ba546270c2b8d750c24eb528b8fcfe50c81de2e0bdebf0e20f24bec688d4331533b782e4a907fad435244621ca2193cfcf80a86731299840e0f6e - languageName: node - linkType: hard - -"@babel/helper-hoist-variables@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-hoist-variables@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: fd9c35bb435fda802bf9ff7b6f2df06308a21277c6dec2120a35b09f9de68f68a33972e2c15505c1a1a04b36ec64c9ace97d4a9e26d6097b76b4396b7c5fa20f - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-module-imports@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: f393f8a3b3304b1b7a288a38c10989de754f01d29caf62ce7c4e5835daf0a27b81f3ac687d9d2780d39685aae7b55267324b512150e7b2be967b0c493b6a1def - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helper-module-transforms@npm:7.19.0" - dependencies: - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-module-imports": ^7.18.6 - "@babel/helper-simple-access": ^7.18.6 - "@babel/helper-split-export-declaration": ^7.18.6 - "@babel/helper-validator-identifier": ^7.18.6 - "@babel/template": ^7.18.10 - "@babel/traverse": ^7.19.0 - "@babel/types": ^7.19.0 - checksum: 4483276c66f56cf3b5b063634092ad9438c2593725de5c143ba277dda82f1501e6d73b311c1b28036f181dbe36eaeff29f24726cde37a599d4e735af294e5359 - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-simple-access@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: 37cd36eef199e0517845763c1e6ff6ea5e7876d6d707a6f59c9267c547a50aa0e84260ba9285d49acfaf2cfa0a74a772d92967f32ac1024c961517d40b6c16a5 - languageName: node - linkType: hard - -"@babel/helper-split-export-declaration@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-split-export-declaration@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: c6d3dede53878f6be1d869e03e9ffbbb36f4897c7cc1527dc96c56d127d834ffe4520a6f7e467f5b6f3c2843ea0e81a7819d66ae02f707f6ac057f3d57943a2b - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.18.10": - version: 7.18.10 - resolution: "@babel/helper-string-parser@npm:7.18.10" - checksum: d554a4393365b624916b5c00a4cc21c990c6617e7f3fe30be7d9731f107f12c33229a7a3db9d829bfa110d2eb9f04790745d421640e3bd245bb412dc0ea123c1 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.18.6": - version: 7.19.1 - resolution: "@babel/helper-validator-identifier@npm:7.19.1" - checksum: 0eca5e86a729162af569b46c6c41a63e18b43dbe09fda1d2a3c8924f7d617116af39cac5e4cd5d431bb760b4dca3c0970e0c444789b1db42bcf1fa41fbad0a3a - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-validator-option@npm:7.18.6" - checksum: f9cc6eb7cc5d759c5abf006402180f8d5e4251e9198197428a97e05d65eb2f8ae5a0ce73b1dfd2d35af41d0eb780627a64edf98a4e71f064eeeacef8de58f2cf - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helpers@npm:7.19.0" - dependencies: - "@babel/template": ^7.18.10 - "@babel/traverse": ^7.19.0 - "@babel/types": ^7.19.0 - checksum: e50e78e0dbb0435075fa3f85021a6bcae529589800bca0292721afd7f7c874bea54508d6dc57eca16e5b8224f8142c6b0e32e3b0140029dc09865da747da4623 - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.10.4, @babel/highlight@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/highlight@npm:7.18.6" - dependencies: - "@babel/helper-validator-identifier": ^7.18.6 - chalk: ^2.0.0 - js-tokens: ^4.0.0 - checksum: 92d8ee61549de5ff5120e945e774728e5ccd57fd3b2ed6eace020ec744823d4a98e242be1453d21764a30a14769ecd62170fba28539b211799bbaf232bbb2789 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.18.10, @babel/parser@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/parser@npm:7.19.1" - bin: - parser: ./bin/babel-parser.js - checksum: b1e0acb346b2a533c857e1e97ac0886cdcbd76aafef67835a2b23f760c10568eb53ad8a27dd5f862d8ba4e583742e6067f107281ccbd68959d61bc61e4ddaa51 - languageName: node - linkType: hard - -"@babel/runtime-corejs3@npm:^7.10.2": - version: 7.19.1 - resolution: "@babel/runtime-corejs3@npm:7.19.1" - dependencies: - core-js-pure: ^3.25.1 - regenerator-runtime: ^0.13.4 - checksum: 38a1e8fcd2ba1f76c951259c98a5a11052123923adbf30ec8b2fec202dbbe38c6db61658ef9398e00c30f799e2e54ea036e56a09f43229261918bf5ec1b7d03a - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.18.9": - version: 7.19.0 - resolution: "@babel/runtime@npm:7.19.0" - dependencies: - regenerator-runtime: ^0.13.4 - checksum: fa69c351bb05e1db3ceb9a02fdcf620c234180af68cdda02152d3561015f6d55277265d3109815992f96d910f3db709458cae4f8df1c3def66f32e0867d82294 - languageName: node - linkType: hard - -"@babel/template@npm:^7.18.10": - version: 7.18.10 - resolution: "@babel/template@npm:7.18.10" - dependencies: - "@babel/code-frame": ^7.18.6 - "@babel/parser": ^7.18.10 - "@babel/types": ^7.18.10 - checksum: 93a6aa094af5f355a72bd55f67fa1828a046c70e46f01b1606e6118fa1802b6df535ca06be83cc5a5e834022be95c7b714f0a268b5f20af984465a71e28f1473 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.19.0, @babel/traverse@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/traverse@npm:7.19.1" - dependencies: - "@babel/code-frame": ^7.18.6 - "@babel/generator": ^7.19.0 - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-function-name": ^7.19.0 - "@babel/helper-hoist-variables": ^7.18.6 - "@babel/helper-split-export-declaration": ^7.18.6 - "@babel/parser": ^7.19.1 - "@babel/types": ^7.19.0 - debug: ^4.1.0 - globals: ^11.1.0 - checksum: 9d782b5089ebc989e54c2406814ed1206cb745ed2734e6602dee3e23d4b6ebbb703ff86e536276630f8de83fda6cde99f0634e3c3d847ddb40572d0303ba8800 - languageName: node - linkType: hard - -"@babel/types@npm:^7.18.10, @babel/types@npm:^7.18.6, @babel/types@npm:^7.19.0, @babel/types@npm:^7.8.3": - version: 7.19.0 - resolution: "@babel/types@npm:7.19.0" - dependencies: - "@babel/helper-string-parser": ^7.18.10 - "@babel/helper-validator-identifier": ^7.18.6 - to-fast-properties: ^2.0.0 - checksum: 9b346715a68aeede70ba9c685a144b0b26c53bcd595d448e24c8fa8df4d5956a5712e56ebadb7c85dcc32f218ee42788e37b93d50d3295c992072224cb3ef3fe - languageName: node - linkType: hard - -"@eslint/eslintrc@npm:^0.4.3": - version: 0.4.3 - resolution: "@eslint/eslintrc@npm:0.4.3" - dependencies: - ajv: ^6.12.4 - debug: ^4.1.1 - espree: ^7.3.0 - globals: ^13.9.0 - ignore: ^4.0.6 - import-fresh: ^3.2.1 - js-yaml: ^3.13.1 - minimatch: ^3.0.4 - strip-json-comments: ^3.1.1 - checksum: 03a7704150b868c318aab6a94d87a33d30dc2ec579d27374575014f06237ba1370ae11178db772f985ef680d469dc237e7b16a1c5d8edaaeb8c3733e7a95a6d3 - languageName: node - linkType: hard - -"@humanwhocodes/config-array@npm:^0.5.0": - version: 0.5.0 - resolution: "@humanwhocodes/config-array@npm:0.5.0" - dependencies: - "@humanwhocodes/object-schema": ^1.2.0 - debug: ^4.1.1 - minimatch: ^3.0.4 - checksum: 44ee6a9f05d93dd9d5935a006b17572328ba9caff8002442f601736cbda79c580cc0f5a49ce9eb88fbacc5c3a6b62098357c2e95326cd17bb9f1a6c61d6e95e7 - languageName: node - linkType: hard - -"@humanwhocodes/object-schema@npm:^1.2.0": - version: 1.2.1 - resolution: "@humanwhocodes/object-schema@npm:1.2.1" - checksum: a824a1ec31591231e4bad5787641f59e9633827d0a2eaae131a288d33c9ef0290bd16fda8da6f7c0fcb014147865d12118df10db57f27f41e20da92369fcb3f1 - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.1.0": - version: 0.1.1 - resolution: "@jridgewell/gen-mapping@npm:0.1.1" - dependencies: - "@jridgewell/set-array": ^1.0.0 - "@jridgewell/sourcemap-codec": ^1.4.10 - checksum: 3bcc21fe786de6ffbf35c399a174faab05eb23ce6a03e8769569de28abbf4facc2db36a9ddb0150545ae23a8d35a7cf7237b2aa9e9356a7c626fb4698287d5cc - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.2 - resolution: "@jridgewell/gen-mapping@npm:0.3.2" - dependencies: - "@jridgewell/set-array": ^1.0.1 - "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 1832707a1c476afebe4d0fbbd4b9434fdb51a4c3e009ab1e9938648e21b7a97049fa6009393bdf05cab7504108413441df26d8a3c12193996e65493a4efb6882 - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.0 - resolution: "@jridgewell/resolve-uri@npm:3.1.0" - checksum: b5ceaaf9a110fcb2780d1d8f8d4a0bfd216702f31c988d8042e5f8fbe353c55d9b0f55a1733afdc64806f8e79c485d2464680ac48a0d9fcadb9548ee6b81d267 - languageName: node - linkType: hard - -"@jridgewell/set-array@npm:^1.0.0, @jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.14 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" - checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.15 - resolution: "@jridgewell/trace-mapping@npm:0.3.15" - dependencies: - "@jridgewell/resolve-uri": ^3.0.3 - "@jridgewell/sourcemap-codec": ^1.4.10 - checksum: 38917e9c2b014d469a9f51c016ed506acbe44dd16ec2f6f99b553ebf3764d22abadbf992f2367b6d2b3511f3eae8ed3a8963f6c1030093fda23efd35ecab2bae - languageName: node - linkType: hard - -"@next/env@npm:12.2.5": - version: 12.2.5 - resolution: "@next/env@npm:12.2.5" - checksum: a44939e59b46d5951831529a43dba9daa2e4e467e8680ea96e21ae127d1bf7f11757aaf3a6cff8a51273abfe7af782903e1304405a481361c7ba3e66d47e3238 - languageName: node - linkType: hard - -"@next/eslint-plugin-next@npm:12.3.0": - version: 12.3.0 - resolution: "@next/eslint-plugin-next@npm:12.3.0" - dependencies: - glob: 7.1.7 - checksum: f08582b36ff01a776183b3c33d6d81be3a110c1c3c39c81a33aff91277ea822aa4a952d4f2271a08ce56692ca5c58c9e958aaf4e08348c10cc45a85213b208f0 - languageName: node - linkType: hard - -"@next/swc-android-arm-eabi@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-android-arm-eabi@npm:12.2.5" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@next/swc-android-arm64@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-android-arm64@npm:12.2.5" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-darwin-arm64@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-darwin-arm64@npm:12.2.5" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-darwin-x64@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-darwin-x64@npm:12.2.5" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@next/swc-freebsd-x64@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-freebsd-x64@npm:12.2.5" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@next/swc-linux-arm-gnueabihf@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-linux-arm-gnueabihf@npm:12.2.5" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@next/swc-linux-arm64-gnu@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-linux-arm64-gnu@npm:12.2.5" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-arm64-musl@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-linux-arm64-musl@npm:12.2.5" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-linux-x64-gnu@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-linux-x64-gnu@npm:12.2.5" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-x64-musl@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-linux-x64-musl@npm:12.2.5" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-win32-arm64-msvc@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-win32-arm64-msvc@npm:12.2.5" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-win32-ia32-msvc@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-win32-ia32-msvc@npm:12.2.5" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@next/swc-win32-x64-msvc@npm:12.2.5": - version: 12.2.5 - resolution: "@next/swc-win32-x64-msvc@npm:12.2.5" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@nodelib/fs.scandir@npm:2.1.5": - version: 2.1.5 - resolution: "@nodelib/fs.scandir@npm:2.1.5" - dependencies: - "@nodelib/fs.stat": 2.0.5 - run-parallel: ^1.1.9 - checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 - languageName: node - linkType: hard - -"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.5 - resolution: "@nodelib/fs.stat@npm:2.0.5" - checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 - languageName: node - linkType: hard - -"@nodelib/fs.walk@npm:^1.2.3": - version: 1.2.8 - resolution: "@nodelib/fs.walk@npm:1.2.8" - dependencies: - "@nodelib/fs.scandir": 2.1.5 - fastq: ^1.6.0 - checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 - languageName: node - linkType: hard - -"@rushstack/eslint-patch@npm:^1.1.3": - version: 1.2.0 - resolution: "@rushstack/eslint-patch@npm:1.2.0" - checksum: faa749faae0e83c26ae9eb00ad36a897ac78f3cf27da8e8ff21c00bcf7973b598d823d8f2b3957ef66079288bcf577f94df831eae2d65f3f68d8ca32f18b6aff - languageName: node - linkType: hard - -"@swc/helpers@npm:0.4.3": - version: 0.4.3 - resolution: "@swc/helpers@npm:0.4.3" - dependencies: - tslib: ^2.4.0 - checksum: 5c2f173e950dd3929d84ae48b3586a274d5a874e7cf2013b3d8081e4f8c723fa3a4d4e63b263e84bb7f06431f87b640e91a12655410463c81a3dc2bbc15eceda - languageName: node - linkType: hard - -"@types/json5@npm:^0.0.29": - version: 0.0.29 - resolution: "@types/json5@npm:0.0.29" - checksum: e60b153664572116dfea673c5bda7778dbff150498f44f998e34b5886d8afc47f16799280e4b6e241c0472aef1bc36add771c569c68fc5125fc2ae519a3eb9ac - languageName: node - linkType: hard - -"@types/node@npm:^17.0.12": - version: 17.0.45 - resolution: "@types/node@npm:17.0.45" - checksum: aa04366b9103b7d6cfd6b2ef64182e0eaa7d4462c3f817618486ea0422984c51fc69fd0d436eae6c9e696ddfdbec9ccaa27a917f7c2e8c75c5d57827fe3d95e8 - languageName: node - linkType: hard - -"@types/prop-types@npm:*": - version: 15.7.5 - resolution: "@types/prop-types@npm:15.7.5" - checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 - languageName: node - linkType: hard - -"@types/react-dom@npm:^17.0.11": - version: 17.0.17 - resolution: "@types/react-dom@npm:17.0.17" - dependencies: - "@types/react": ^17 - checksum: 23caf98aa03e968811560f92a2c8f451694253ebe16b670929b24eaf0e7fa62ba549abe9db0ac028a9d8a9086acd6ab9c6c773f163fa21224845edbc00ba6232 - languageName: node - linkType: hard - -"@types/react@npm:18.0.17": - version: 18.0.17 - resolution: "@types/react@npm:18.0.17" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: 18cae64f5bfd6bb58fbd8ee2ba52ec82de844f114254e26de7b513e4b86621f643f9b71d7066958cd571b0d78cb86cbceda449c5289f9349ca573df29ab69252 - languageName: node - linkType: hard - -"@types/react@npm:^17, @types/react@npm:^17.0.37": - version: 17.0.50 - resolution: "@types/react@npm:17.0.50" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: b5629dff7c2f3e9fcba95a19b2b3bfd78d7cacc33ba5fc26413dba653d34afcac3b93ddabe563e8062382688a1eac7db68e93739bb8e712d27637a03aaafbbb8 - languageName: node - linkType: hard - -"@types/scheduler@npm:*": - version: 0.16.2 - resolution: "@types/scheduler@npm:0.16.2" - checksum: b6b4dcfeae6deba2e06a70941860fb1435730576d3689225a421280b7742318d1548b3d22c1f66ab68e414f346a9542f29240bc955b6332c5b11e561077583bc - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^5.21.0": - version: 5.37.0 - resolution: "@typescript-eslint/parser@npm:5.37.0" - dependencies: - "@typescript-eslint/scope-manager": 5.37.0 - "@typescript-eslint/types": 5.37.0 - "@typescript-eslint/typescript-estree": 5.37.0 - debug: ^4.3.4 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 33343e27c9602820d43ee12de9797365d97a5cf3f716e750fa44de760f2a2c6800f3bc4fa54931ac70c0e0ede77a92224f8151da7f30fed3bf692a029d6659af - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:5.37.0": - version: 5.37.0 - resolution: "@typescript-eslint/scope-manager@npm:5.37.0" - dependencies: - "@typescript-eslint/types": 5.37.0 - "@typescript-eslint/visitor-keys": 5.37.0 - checksum: 1c439e21ffa63ebaadb8c8363e9d668132a835a28203e5b779366bfa56772f332e5dedb50d63dffb836839b9d9c4e66aa9e3ea47b8c59465b18a0cbd063ec7a3 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.37.0": - version: 5.37.0 - resolution: "@typescript-eslint/types@npm:5.37.0" - checksum: 899e59e7775fa95c2d9fcac5cc02cc49d83af5f1ffc706df495046c3b3733f79d5489568b01bfaf8c9ae4636e057056866adc783113036f774580086d0189f21 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.37.0": - version: 5.37.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.37.0" - dependencies: - "@typescript-eslint/types": 5.37.0 - "@typescript-eslint/visitor-keys": 5.37.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.3.7 - tsutils: ^3.21.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 80365a50fa11ed39bf54d9ef06e264fbbf3bdbcc55b7d7d555ef0be915edae40ec30e98d08b3f6ef048e1874450cbcb1e7d9f429d4f420dacbbde45d3376a7bc - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.37.0": - version: 5.37.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.37.0" - dependencies: - "@typescript-eslint/types": 5.37.0 - eslint-visitor-keys: ^3.3.0 - checksum: d6193550f77413aead0cb267e058df80b80a488c8fb4e39beb5f0a70b971c41682a6391903fbc5f3dd859a872016288c434d631b8efc3ac5a04edbdb7b63b5f6 - languageName: node - linkType: hard - -"acorn-jsx@npm:^5.3.1": - version: 5.3.2 - resolution: "acorn-jsx@npm:5.3.2" - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 - languageName: node - linkType: hard - -"acorn@npm:^7.4.0": - version: 7.4.1 - resolution: "acorn@npm:7.4.1" - bin: - acorn: bin/acorn - checksum: 1860f23c2107c910c6177b7b7be71be350db9e1080d814493fae143ae37605189504152d1ba8743ba3178d0b37269ce1ffc42b101547fdc1827078f82671e407 - languageName: node - linkType: hard - -"ajv@npm:^6.10.0, ajv@npm:^6.12.4": - version: 6.12.6 - resolution: "ajv@npm:6.12.6" - dependencies: - fast-deep-equal: ^3.1.1 - fast-json-stable-stringify: ^2.0.0 - json-schema-traverse: ^0.4.1 - uri-js: ^4.2.2 - checksum: 874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 - languageName: node - linkType: hard - -"ajv@npm:^8.0.1": - version: 8.11.0 - resolution: "ajv@npm:8.11.0" - dependencies: - fast-deep-equal: ^3.1.1 - json-schema-traverse: ^1.0.0 - require-from-string: ^2.0.2 - uri-js: ^4.2.2 - checksum: 5e0ff226806763be73e93dd7805b634f6f5921e3e90ca04acdf8db81eed9d8d3f0d4c5f1213047f45ebbf8047ffe0c840fa1ef2ec42c3a644899f69aa72b5bef - languageName: node - linkType: hard - -"ansi-colors@npm:^4.1.1": - version: 4.1.3 - resolution: "ansi-colors@npm:4.1.3" - checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b - languageName: node - linkType: hard - -"ansi-styles@npm:^3.2.1": - version: 3.2.1 - resolution: "ansi-styles@npm:3.2.1" - dependencies: - color-convert: ^1.9.0 - checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: ^2.0.1 - checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 - languageName: node - linkType: hard - -"argparse@npm:^1.0.7": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: ~1.0.2 - checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 - languageName: node - linkType: hard - -"aria-query@npm:^4.2.2": - version: 4.2.2 - resolution: "aria-query@npm:4.2.2" - dependencies: - "@babel/runtime": ^7.10.2 - "@babel/runtime-corejs3": ^7.10.2 - checksum: 38401a9a400f26f3dcc24b84997461a16b32869a9893d323602bed8da40a8bcc0243b8d2880e942249a1496cea7a7de769e93d21c0baa439f01e1ee936fed665 - languageName: node - linkType: hard - -"array-includes@npm:^3.1.4, array-includes@npm:^3.1.5": - version: 3.1.5 - resolution: "array-includes@npm:3.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.19.5 - get-intrinsic: ^1.1.1 - is-string: ^1.0.7 - checksum: f6f24d834179604656b7bec3e047251d5cc87e9e87fab7c175c61af48e80e75acd296017abcde21fb52292ab6a2a449ab2ee37213ee48c8709f004d75983f9c5 - languageName: node - linkType: hard - -"array-union@npm:^2.1.0": - version: 2.1.0 - resolution: "array-union@npm:2.1.0" - checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d - languageName: node - linkType: hard - -"array.prototype.flat@npm:^1.2.5": - version: 1.3.0 - resolution: "array.prototype.flat@npm:1.3.0" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.2 - es-shim-unscopables: ^1.0.0 - checksum: 2a652b3e8dc0bebb6117e42a5ab5738af0203a14c27341d7bb2431467bdb4b348e2c5dc555dfcda8af0a5e4075c400b85311ded73861c87290a71a17c3e0a257 - languageName: node - linkType: hard - -"array.prototype.flatmap@npm:^1.3.0": - version: 1.3.0 - resolution: "array.prototype.flatmap@npm:1.3.0" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.2 - es-shim-unscopables: ^1.0.0 - checksum: 818538f39409c4045d874be85df0dbd195e1446b14d22f95bdcfefea44ae77db44e42dcd89a559254ec5a7c8b338cfc986cc6d641e3472f9a5326b21eb2976a2 - languageName: node - linkType: hard - -"ast-types-flow@npm:^0.0.7": - version: 0.0.7 - resolution: "ast-types-flow@npm:0.0.7" - checksum: a26dcc2182ffee111cad7c471759b0bda22d3b7ebacf27c348b22c55f16896b18ab0a4d03b85b4020dce7f3e634b8f00b593888f622915096ea1927fa51866c4 - languageName: node - linkType: hard - -"astral-regex@npm:^2.0.0": - version: 2.0.0 - resolution: "astral-regex@npm:2.0.0" - checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 - languageName: node - linkType: hard - -"axe-core@npm:^4.4.3": - version: 4.4.3 - resolution: "axe-core@npm:4.4.3" - checksum: c3ea000d9ace3ba0bc747c8feafc24b0de62a0f7d93021d0f77b19c73fca15341843510f6170da563d51535d6cfb7a46c5fc0ea36170549dbb44b170208450a2 - languageName: node - linkType: hard - -"axobject-query@npm:^2.2.0": - version: 2.2.0 - resolution: "axobject-query@npm:2.2.0" - checksum: 96b8c7d807ca525f41ad9b286186e2089b561ba63a6d36c3e7d73dc08150714660995c7ad19cda05784458446a0793b45246db45894631e13853f48c1aa3117f - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 - languageName: node - linkType: hard - -"berry-patch@workspace:.": - version: 0.0.0-use.local - resolution: "berry-patch@workspace:." - dependencies: - eslint-config-custom: "*" - prettier: latest - turbo: latest - languageName: unknown - linkType: soft - -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: ^1.0.0 - concat-map: 0.0.1 - checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 - languageName: node - linkType: hard - -"braces@npm:^3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" - dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 - languageName: node - linkType: hard - -"browserslist@npm:^4.21.3": - version: 4.21.4 - resolution: "browserslist@npm:4.21.4" - dependencies: - caniuse-lite: ^1.0.30001400 - electron-to-chromium: ^1.4.251 - node-releases: ^2.0.6 - update-browserslist-db: ^1.0.9 - bin: - browserslist: cli.js - checksum: 4af3793704dbb4615bcd29059ab472344dc7961c8680aa6c4bb84f05340e14038d06a5aead58724eae69455b8fade8b8c69f1638016e87e5578969d74c078b79 - languageName: node - linkType: hard - -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind@npm:1.0.2" - dependencies: - function-bind: ^1.1.1 - get-intrinsic: ^1.0.2 - checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 - languageName: node - linkType: hard - -"callsites@npm:^3.0.0": - version: 3.1.0 - resolution: "callsites@npm:3.1.0" - checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001332, caniuse-lite@npm:^1.0.30001400": - version: 1.0.30001400 - resolution: "caniuse-lite@npm:1.0.30001400" - checksum: 984e29d3c02fd02a59cc92ef4a5e9390fce250de3791056362347cf901f0d91041246961a57cfa8fed800538d03ee341bc4f7eaed19bf7be0ef8a181d94cd848 - languageName: node - linkType: hard - -"chalk@npm:^2.0.0": - version: 2.4.2 - resolution: "chalk@npm:2.4.2" - dependencies: - ansi-styles: ^3.2.1 - escape-string-regexp: ^1.0.5 - supports-color: ^5.3.0 - checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 - languageName: node - linkType: hard - -"chalk@npm:^4.0.0": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc - languageName: node - linkType: hard - -"color-convert@npm:^1.9.0": - version: 1.9.3 - resolution: "color-convert@npm:1.9.3" - dependencies: - color-name: 1.1.3 - checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: ~1.1.4 - checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 - languageName: node - linkType: hard - -"color-name@npm:1.1.3": - version: 1.1.3 - resolution: "color-name@npm:1.1.3" - checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 - languageName: node - linkType: hard - -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af - languageName: node - linkType: hard - -"convert-source-map@npm:^1.7.0": - version: 1.8.0 - resolution: "convert-source-map@npm:1.8.0" - dependencies: - safe-buffer: ~5.1.1 - checksum: 985d974a2d33e1a2543ada51c93e1ba2f73eaed608dc39f229afc78f71dcc4c8b7d7c684aa647e3c6a3a204027444d69e53e169ce94e8d1fa8d7dee80c9c8fed - languageName: node - linkType: hard - -"core-js-pure@npm:^3.25.1": - version: 3.25.1 - resolution: "core-js-pure@npm:3.25.1" - checksum: 0123131ec7ab3a1e56f0b4df4ae659de03d9c245ce281637d4d0f18f9839d8e0cfbfa989bd577ce1b67826f889a7dcc734421f697cf1bbe59f605f29c537a678 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.2": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: ^3.1.0 - shebang-command: ^2.0.0 - which: ^2.0.1 - checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 - languageName: node - linkType: hard - -"csstype@npm:^3.0.2": - version: 3.1.1 - resolution: "csstype@npm:3.1.1" - checksum: 1f7b4f5fdd955b7444b18ebdddf3f5c699159f13e9cf8ac9027ae4a60ae226aef9bbb14a6e12ca7dba3358b007cee6354b116e720262867c398de6c955ea451d - languageName: node - linkType: hard - -"damerau-levenshtein@npm:^1.0.8": - version: 1.0.8 - resolution: "damerau-levenshtein@npm:1.0.8" - checksum: d240b7757544460ae0586a341a53110ab0a61126570ef2d8c731e3eab3f0cb6e488e2609e6a69b46727635de49be20b071688698744417ff1b6c1d7ccd03e0de - languageName: node - linkType: hard - -"debug@npm:^2.6.9": - version: 2.6.9 - resolution: "debug@npm:2.6.9" - dependencies: - ms: 2.0.0 - checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 - languageName: node - linkType: hard - -"debug@npm:^3.2.7": - version: 3.2.7 - resolution: "debug@npm:3.2.7" - dependencies: - ms: ^2.1.1 - checksum: b3d8c5940799914d30314b7c3304a43305fd0715581a919dacb8b3176d024a782062368405b47491516d2091d6462d4d11f2f4974a405048094f8bfebfa3071c - languageName: node - linkType: hard - -"debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" - dependencies: - ms: 2.1.2 - peerDependenciesMeta: - supports-color: - optional: true - checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 - languageName: node - linkType: hard - -"deep-is@npm:^0.1.3": - version: 0.1.4 - resolution: "deep-is@npm:0.1.4" - checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 - languageName: node - linkType: hard - -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4": - version: 1.1.4 - resolution: "define-properties@npm:1.1.4" - dependencies: - has-property-descriptors: ^1.0.0 - object-keys: ^1.1.1 - checksum: ce0aef3f9eb193562b5cfb79b2d2c86b6a109dfc9fdcb5f45d680631a1a908c06824ddcdb72b7573b54e26ace07f0a23420aaba0d5c627b34d2c1de8ef527e2b - languageName: node - linkType: hard - -"dir-glob@npm:^3.0.1": - version: 3.0.1 - resolution: "dir-glob@npm:3.0.1" - dependencies: - path-type: ^4.0.0 - checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 - languageName: node - linkType: hard - -"docs@workspace:apps/docs": - version: 0.0.0-use.local - resolution: "docs@workspace:apps/docs" - dependencies: - "@babel/core": ^7.0.0 - "@types/node": ^17.0.12 - "@types/react": 18.0.17 - eslint: 7.32.0 - eslint-config-custom: "*" - lodash: ^4.17.21 - next: 12.2.5 - next-transpile-modules: 9.0.0 - react: 18.2.0 - react-dom: 18.2.0 - tsconfig: "*" - typescript: ^4.5.3 - ui: "*" - languageName: unknown - linkType: soft - -"doctrine@npm:^2.1.0": - version: 2.1.0 - resolution: "doctrine@npm:2.1.0" - dependencies: - esutils: ^2.0.2 - checksum: a45e277f7feaed309fe658ace1ff286c6e2002ac515af0aaf37145b8baa96e49899638c7cd47dccf84c3d32abfc113246625b3ac8f552d1046072adee13b0dc8 - languageName: node - linkType: hard - -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: ^2.0.2 - checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.4.251": - version: 1.4.251 - resolution: "electron-to-chromium@npm:1.4.251" - checksum: 470a04dfe1d34814f8bc7e1dde606851b6f787a6d78655a57df063844fc71feb64ce793c52a3a130ceac1fc368b8d3e25a4c55c847a1e9c02c3090f9dcbf40ac - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 - languageName: node - linkType: hard - -"enhanced-resolve@npm:^5.7.0": - version: 5.10.0 - resolution: "enhanced-resolve@npm:5.10.0" - dependencies: - graceful-fs: ^4.2.4 - tapable: ^2.2.0 - checksum: 0bb9830704db271610f900e8d79d70a740ea16f251263362b0c91af545576d09fe50103496606c1300a05e588372d6f9780a9bc2e30ce8ef9b827ec8f44687ff - languageName: node - linkType: hard - -"enquirer@npm:^2.3.5": - version: 2.3.6 - resolution: "enquirer@npm:2.3.6" - dependencies: - ansi-colors: ^4.1.1 - checksum: 1c0911e14a6f8d26721c91e01db06092a5f7675159f0261d69c403396a385afd13dd76825e7678f66daffa930cfaa8d45f506fb35f818a2788463d022af1b884 - languageName: node - linkType: hard - -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.1, es-abstract@npm:^1.19.2, es-abstract@npm:^1.19.5": - version: 1.20.2 - resolution: "es-abstract@npm:1.20.2" - dependencies: - call-bind: ^1.0.2 - es-to-primitive: ^1.2.1 - function-bind: ^1.1.1 - function.prototype.name: ^1.1.5 - get-intrinsic: ^1.1.2 - get-symbol-description: ^1.0.0 - has: ^1.0.3 - has-property-descriptors: ^1.0.0 - has-symbols: ^1.0.3 - internal-slot: ^1.0.3 - is-callable: ^1.2.4 - is-negative-zero: ^2.0.2 - is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 - is-string: ^1.0.7 - is-weakref: ^1.0.2 - object-inspect: ^1.12.2 - object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.4.3 - string.prototype.trimend: ^1.0.5 - string.prototype.trimstart: ^1.0.5 - unbox-primitive: ^1.0.2 - checksum: ab893dd1f849250f5a2da82656b4e21b511f76429b25a4aea5c8b2a3007ff01cb8e112987d0dd7693b9ad9e6399f8f7be133285d6196a5ebd1b13a4ee2258f70 - languageName: node - linkType: hard - -"es-shim-unscopables@npm:^1.0.0": - version: 1.0.0 - resolution: "es-shim-unscopables@npm:1.0.0" - dependencies: - has: ^1.0.3 - checksum: 83e95cadbb6ee44d3644dfad60dcad7929edbc42c85e66c3e99aefd68a3a5c5665f2686885cddb47dfeabfd77bd5ea5a7060f2092a955a729bbd8834f0d86fa1 - languageName: node - linkType: hard - -"es-to-primitive@npm:^1.2.1": - version: 1.2.1 - resolution: "es-to-primitive@npm:1.2.1" - dependencies: - is-callable: ^1.1.4 - is-date-object: ^1.0.1 - is-symbol: ^1.0.2 - checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed - languageName: node - linkType: hard - -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 - languageName: node - linkType: hard - -"eslint-config-custom@*, eslint-config-custom@workspace:packages/eslint-config-custom": - version: 0.0.0-use.local - resolution: "eslint-config-custom@workspace:packages/eslint-config-custom" - dependencies: - eslint: ^7.23.0 - eslint-config-next: ^12.0.8 - eslint-config-prettier: ^8.3.0 - eslint-config-turbo: latest - eslint-plugin-react: 7.31.7 - typescript: ^4.7.4 - languageName: unknown - linkType: soft - -"eslint-config-next@npm:^12.0.8": - version: 12.3.0 - resolution: "eslint-config-next@npm:12.3.0" - dependencies: - "@next/eslint-plugin-next": 12.3.0 - "@rushstack/eslint-patch": ^1.1.3 - "@typescript-eslint/parser": ^5.21.0 - eslint-import-resolver-node: ^0.3.6 - eslint-import-resolver-typescript: ^2.7.1 - eslint-plugin-import: ^2.26.0 - eslint-plugin-jsx-a11y: ^6.5.1 - eslint-plugin-react: ^7.29.4 - eslint-plugin-react-hooks: ^4.5.0 - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - typescript: ">=3.3.1" - peerDependenciesMeta: - typescript: - optional: true - checksum: 50a2e43c515350c689cd848973b953c1d058303b84e05ecba5b5bf0f8feffe3935011de3b574ba35d48de8a5d7d5c42567d21d1a17f02189a701edeb6d76a8e0 - languageName: node - linkType: hard - -"eslint-config-prettier@npm:^8.3.0": - version: 8.5.0 - resolution: "eslint-config-prettier@npm:8.5.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 0d0f5c32e7a0ad91249467ce71ca92394ccd343178277d318baf32063b79ea90216f4c81d1065d60f96366fdc60f151d4d68ae7811a58bd37228b84c2083f893 - languageName: node - linkType: hard - -eslint-config-turbo@latest: - version: 0.0.3 - resolution: "eslint-config-turbo@npm:0.0.3" - dependencies: - eslint-plugin-turbo: 0.0.3 - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - checksum: c92255e91dd0865faeebc857eb3a862e8ca2ccb37fc54ffce93b73cd41e95ad456826ae6634772450dfa9c705b67c288f476e8e413fab3d8194dc271754528e2 - languageName: node - linkType: hard - -"eslint-import-resolver-node@npm:^0.3.6": - version: 0.3.6 - resolution: "eslint-import-resolver-node@npm:0.3.6" - dependencies: - debug: ^3.2.7 - resolve: ^1.20.0 - checksum: 6266733af1e112970e855a5bcc2d2058fb5ae16ad2a6d400705a86b29552b36131ffc5581b744c23d550de844206fb55e9193691619ee4dbf225c4bde526b1c8 - languageName: node - linkType: hard - -"eslint-import-resolver-typescript@npm:^2.7.1": - version: 2.7.1 - resolution: "eslint-import-resolver-typescript@npm:2.7.1" - dependencies: - debug: ^4.3.4 - glob: ^7.2.0 - is-glob: ^4.0.3 - resolve: ^1.22.0 - tsconfig-paths: ^3.14.1 - peerDependencies: - eslint: "*" - eslint-plugin-import: "*" - checksum: 1d81b657b1f73bf95b8f0b745c0305574b91630c1db340318f3ca8918e206fce20a933b95e7c419338cc4452cb80bb2b2d92acaf01b6aa315c78a332d832545c - languageName: node - linkType: hard - -"eslint-module-utils@npm:^2.7.3": - version: 2.7.4 - resolution: "eslint-module-utils@npm:2.7.4" - dependencies: - debug: ^3.2.7 - dependenciesMeta: - debug@4.3.4: - unplugged: true - built: false - peerDependenciesMeta: - eslint: - optional: true - checksum: 5da13645daff145a5c922896b258f8bba560722c3767254e458d894ff5fbb505d6dfd945bffa932a5b0ae06714da2379bd41011c4c20d2d59cc83e23895360f7 - languageName: node - linkType: hard - -"eslint-plugin-import@npm:^2.26.0": - version: 2.26.0 - resolution: "eslint-plugin-import@npm:2.26.0" - dependencies: - array-includes: ^3.1.4 - array.prototype.flat: ^1.2.5 - debug: ^2.6.9 - doctrine: ^2.1.0 - eslint-import-resolver-node: ^0.3.6 - eslint-module-utils: ^2.7.3 - has: ^1.0.3 - is-core-module: ^2.8.1 - is-glob: ^4.0.3 - minimatch: ^3.1.2 - object.values: ^1.1.5 - resolve: ^1.22.0 - tsconfig-paths: ^3.14.1 - peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 0bf77ad80339554481eafa2b1967449e1f816b94c7a6f9614ce33fb4083c4e6c050f10d241dd50b4975d47922880a34de1e42ea9d8e6fd663ebb768baa67e655 - languageName: node - linkType: hard - -"eslint-plugin-jsx-a11y@npm:^6.5.1": - version: 6.6.1 - resolution: "eslint-plugin-jsx-a11y@npm:6.6.1" - dependencies: - "@babel/runtime": ^7.18.9 - aria-query: ^4.2.2 - array-includes: ^3.1.5 - ast-types-flow: ^0.0.7 - axe-core: ^4.4.3 - axobject-query: ^2.2.0 - damerau-levenshtein: ^1.0.8 - emoji-regex: ^9.2.2 - has: ^1.0.3 - jsx-ast-utils: ^3.3.2 - language-tags: ^1.0.5 - minimatch: ^3.1.2 - semver: ^6.3.0 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: baae7377f0e25a0cc9b34dc333a3dc6ead9ee8365e445451eff554c3ca267a0a6cb88127fe90395c578ab1b92cfed246aef7dc8d2b48b603389e10181799e144 - languageName: node - linkType: hard - -"eslint-plugin-react-hooks@npm:^4.5.0": - version: 4.6.0 - resolution: "eslint-plugin-react-hooks@npm:4.6.0" - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 23001801f14c1d16bf0a837ca7970d9dd94e7b560384b41db378b49b6e32dc43d6e2790de1bd737a652a86f81a08d6a91f402525061b47719328f586a57e86c3 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:7.31.7": - version: 7.31.7 - resolution: "eslint-plugin-react@npm:7.31.7" - dependencies: - array-includes: ^3.1.5 - array.prototype.flatmap: ^1.3.0 - doctrine: ^2.1.0 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.1.2 - object.entries: ^1.1.5 - object.fromentries: ^2.0.5 - object.hasown: ^1.1.1 - object.values: ^1.1.5 - prop-types: ^15.8.1 - resolve: ^2.0.0-next.3 - semver: ^6.3.0 - string.prototype.matchall: ^4.0.7 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 582d422f531d7d3894fc09ac941ef8b6ad595782cfca5e1d52af5895ce117def7a0ff8afeea0166bff7b6ceae8baec2313614b1571754f539575cfa9351cd2da - languageName: node - linkType: hard - -"eslint-plugin-react@npm:^7.29.4": - version: 7.31.8 - resolution: "eslint-plugin-react@npm:7.31.8" - dependencies: - array-includes: ^3.1.5 - array.prototype.flatmap: ^1.3.0 - doctrine: ^2.1.0 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.1.2 - object.entries: ^1.1.5 - object.fromentries: ^2.0.5 - object.hasown: ^1.1.1 - object.values: ^1.1.5 - prop-types: ^15.8.1 - resolve: ^2.0.0-next.3 - semver: ^6.3.0 - string.prototype.matchall: ^4.0.7 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 0683e2a624a4df6f08264a3f6bc614a81e8f961c83173bdf2d8d3523f84ed5d234cddc976dbc6815913e007c5984df742ba61be0c0592b27c3daabe0f68165a3 - languageName: node - linkType: hard - -"eslint-plugin-turbo@npm:0.0.3": - version: 0.0.3 - resolution: "eslint-plugin-turbo@npm:0.0.3" - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - checksum: 18e2b13ede03eee7635d0c67ca792cf46483e90443143bdc06555bf231045fb5f70b2f6f1d67492365b7fe47620408eea22f7548879f3afcb07ccc070aec5c15 - languageName: node - linkType: hard - -"eslint-scope@npm:^5.1.1": - version: 5.1.1 - resolution: "eslint-scope@npm:5.1.1" - dependencies: - esrecurse: ^4.3.0 - estraverse: ^4.1.1 - checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb - languageName: node - linkType: hard - -"eslint-utils@npm:^2.1.0": - version: 2.1.0 - resolution: "eslint-utils@npm:2.1.0" - dependencies: - eslint-visitor-keys: ^1.1.0 - checksum: 27500938f348da42100d9e6ad03ae29b3de19ba757ae1a7f4a087bdcf83ac60949bbb54286492ca61fac1f5f3ac8692dd21537ce6214240bf95ad0122f24d71d - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^1.1.0, eslint-visitor-keys@npm:^1.3.0": - version: 1.3.0 - resolution: "eslint-visitor-keys@npm:1.3.0" - checksum: 37a19b712f42f4c9027e8ba98c2b06031c17e0c0a4c696cd429bd9ee04eb43889c446f2cd545e1ff51bef9593fcec94ecd2c2ef89129fcbbf3adadbef520376a - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^2.0.0": - version: 2.1.0 - resolution: "eslint-visitor-keys@npm:2.1.0" - checksum: e3081d7dd2611a35f0388bbdc2f5da60b3a3c5b8b6e928daffff7391146b434d691577aa95064c8b7faad0b8a680266bcda0a42439c18c717b80e6718d7e267d - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.3.0": - version: 3.3.0 - resolution: "eslint-visitor-keys@npm:3.3.0" - checksum: d59e68a7c5a6d0146526b0eec16ce87fbf97fe46b8281e0d41384224375c4e52f5ffb9e16d48f4ea50785cde93f766b0c898e31ab89978d88b0e1720fbfb7808 - languageName: node - linkType: hard - -"eslint@npm:7.32.0, eslint@npm:^7.23.0, eslint@npm:^7.32.0": - version: 7.32.0 - resolution: "eslint@npm:7.32.0" - dependencies: - "@babel/code-frame": 7.12.11 - "@eslint/eslintrc": ^0.4.3 - "@humanwhocodes/config-array": ^0.5.0 - ajv: ^6.10.0 - chalk: ^4.0.0 - cross-spawn: ^7.0.2 - debug: ^4.0.1 - doctrine: ^3.0.0 - enquirer: ^2.3.5 - escape-string-regexp: ^4.0.0 - eslint-scope: ^5.1.1 - eslint-utils: ^2.1.0 - eslint-visitor-keys: ^2.0.0 - espree: ^7.3.1 - esquery: ^1.4.0 - esutils: ^2.0.2 - fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 - functional-red-black-tree: ^1.0.1 - glob-parent: ^5.1.2 - globals: ^13.6.0 - ignore: ^4.0.6 - import-fresh: ^3.0.0 - imurmurhash: ^0.1.4 - is-glob: ^4.0.0 - js-yaml: ^3.13.1 - json-stable-stringify-without-jsonify: ^1.0.1 - levn: ^0.4.1 - lodash.merge: ^4.6.2 - minimatch: ^3.0.4 - natural-compare: ^1.4.0 - optionator: ^0.9.1 - progress: ^2.0.0 - regexpp: ^3.1.0 - semver: ^7.2.1 - strip-ansi: ^6.0.0 - strip-json-comments: ^3.1.0 - table: ^6.0.9 - text-table: ^0.2.0 - v8-compile-cache: ^2.0.3 - bin: - eslint: bin/eslint.js - checksum: cc85af9985a3a11085c011f3d27abe8111006d34cc274291b3c4d7bea51a4e2ff6135780249becd919ba7f6d6d1ecc38a6b73dacb6a7be08d38453b344dc8d37 - languageName: node - linkType: hard - -"espree@npm:^7.3.0, espree@npm:^7.3.1": - version: 7.3.1 - resolution: "espree@npm:7.3.1" - dependencies: - acorn: ^7.4.0 - acorn-jsx: ^5.3.1 - eslint-visitor-keys: ^1.3.0 - checksum: aa9b50dcce883449af2e23bc2b8d9abb77118f96f4cb313935d6b220f77137eaef7724a83c3f6243b96bc0e4ab14766198e60818caad99f9519ae5a336a39b45 - languageName: node - linkType: hard - -"esprima@npm:^4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 - languageName: node - linkType: hard - -"esquery@npm:^1.4.0": - version: 1.4.0 - resolution: "esquery@npm:1.4.0" - dependencies: - estraverse: ^5.1.0 - checksum: a0807e17abd7fbe5fbd4fab673038d6d8a50675cdae6b04fbaa520c34581be0c5fa24582990e8acd8854f671dd291c78bb2efb9e0ed5b62f33bac4f9cf820210 - languageName: node - linkType: hard - -"esrecurse@npm:^4.3.0": - version: 4.3.0 - resolution: "esrecurse@npm:4.3.0" - dependencies: - estraverse: ^5.2.0 - checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 - languageName: node - linkType: hard - -"estraverse@npm:^4.1.1": - version: 4.3.0 - resolution: "estraverse@npm:4.3.0" - checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 - languageName: node - linkType: hard - -"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": - version: 5.3.0 - resolution: "estraverse@npm:5.3.0" - checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b - languageName: node - linkType: hard - -"esutils@npm:^2.0.2": - version: 2.0.3 - resolution: "esutils@npm:2.0.3" - checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 - languageName: node - linkType: hard - -"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": - version: 3.1.3 - resolution: "fast-deep-equal@npm:3.1.3" - checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d - languageName: node - linkType: hard - -"fast-glob@npm:^3.2.9": - version: 3.2.12 - resolution: "fast-glob@npm:3.2.12" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 0b1990f6ce831c7e28c4d505edcdaad8e27e88ab9fa65eedadb730438cfc7cde4910d6c975d6b7b8dc8a73da4773702ebcfcd6e3518e73938bb1383badfe01c2 - languageName: node - linkType: hard - -"fast-json-stable-stringify@npm:^2.0.0": - version: 2.1.0 - resolution: "fast-json-stable-stringify@npm:2.1.0" - checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb - languageName: node - linkType: hard - -"fast-levenshtein@npm:^2.0.6": - version: 2.0.6 - resolution: "fast-levenshtein@npm:2.0.6" - checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c - languageName: node - linkType: hard - -"fastq@npm:^1.6.0": - version: 1.13.0 - resolution: "fastq@npm:1.13.0" - dependencies: - reusify: ^1.0.4 - checksum: 32cf15c29afe622af187d12fc9cd93e160a0cb7c31a3bb6ace86b7dea3b28e7b72acde89c882663f307b2184e14782c6c664fa315973c03626c7d4bff070bb0b - languageName: node - linkType: hard - -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" - dependencies: - flat-cache: ^3.0.4 - checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 - languageName: node - linkType: hard - -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" - dependencies: - to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 - languageName: node - linkType: hard - -"flat-cache@npm:^3.0.4": - version: 3.0.4 - resolution: "flat-cache@npm:3.0.4" - dependencies: - flatted: ^3.1.0 - rimraf: ^3.0.2 - checksum: 4fdd10ecbcbf7d520f9040dd1340eb5dfe951e6f0ecf2252edeec03ee68d989ec8b9a20f4434270e71bcfd57800dc09b3344fca3966b2eb8f613072c7d9a2365 - languageName: node - linkType: hard - -"flatted@npm:^3.1.0": - version: 3.2.7 - resolution: "flatted@npm:3.2.7" - checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 - languageName: node - linkType: hard - -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a - languageName: node - linkType: hard - -"function.prototype.name@npm:^1.1.5": - version: 1.1.5 - resolution: "function.prototype.name@npm:1.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.0 - functions-have-names: ^1.2.2 - checksum: acd21d733a9b649c2c442f067567743214af5fa248dbeee69d8278ce7df3329ea5abac572be9f7470b4ec1cd4d8f1040e3c5caccf98ebf2bf861a0deab735c27 - languageName: node - linkType: hard - -"functional-red-black-tree@npm:^1.0.1": - version: 1.0.1 - resolution: "functional-red-black-tree@npm:1.0.1" - checksum: ca6c170f37640e2d94297da8bb4bf27a1d12bea3e00e6a3e007fd7aa32e37e000f5772acf941b4e4f3cf1c95c3752033d0c509af157ad8f526e7f00723b9eb9f - languageName: node - linkType: hard - -"functions-have-names@npm:^1.2.2": - version: 1.2.3 - resolution: "functions-have-names@npm:1.2.3" - checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 - languageName: node - linkType: hard - -"gensync@npm:^1.0.0-beta.2": - version: 1.0.0-beta.2 - resolution: "gensync@npm:1.0.0-beta.2" - checksum: a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.0, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.2": - version: 1.1.3 - resolution: "get-intrinsic@npm:1.1.3" - dependencies: - function-bind: ^1.1.1 - has: ^1.0.3 - has-symbols: ^1.0.3 - checksum: 152d79e87251d536cf880ba75cfc3d6c6c50e12b3a64e1ea960e73a3752b47c69f46034456eae1b0894359ce3bc64c55c186f2811f8a788b75b638b06fab228a - languageName: node - linkType: hard - -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 - languageName: node - linkType: hard - -"glob-parent@npm:^5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: ^4.0.1 - checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e - languageName: node - linkType: hard - -"glob@npm:7.1.7": - version: 7.1.7 - resolution: "glob@npm:7.1.7" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.0.4 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: b61f48973bbdcf5159997b0874a2165db572b368b931135832599875919c237fc05c12984e38fe828e69aa8a921eb0e8a4997266211c517c9cfaae8a93988bb8 - languageName: node - linkType: hard - -"glob@npm:^7.1.3, glob@npm:^7.2.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.1.1 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 - languageName: node - linkType: hard - -"globals@npm:^11.1.0": - version: 11.12.0 - resolution: "globals@npm:11.12.0" - checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e - languageName: node - linkType: hard - -"globals@npm:^13.6.0, globals@npm:^13.9.0": - version: 13.17.0 - resolution: "globals@npm:13.17.0" - dependencies: - type-fest: ^0.20.2 - checksum: fbaf4112e59b92c9f5575e85ce65e9e17c0b82711196ec5f58beb08599bbd92fd72703d6dfc9b080381fd35b644e1b11dcf25b38cc2341ec21df942594cbc8ce - languageName: node - linkType: hard - -"globby@npm:^11.1.0": - version: 11.1.0 - resolution: "globby@npm:11.1.0" - dependencies: - array-union: ^2.1.0 - dir-glob: ^3.0.1 - fast-glob: ^3.2.9 - ignore: ^5.2.0 - merge2: ^1.4.1 - slash: ^3.0.0 - checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.4": - version: 4.2.10 - resolution: "graceful-fs@npm:4.2.10" - checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da - languageName: node - linkType: hard - -"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": - version: 1.0.2 - resolution: "has-bigints@npm:1.0.2" - checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b - languageName: node - linkType: hard - -"has-flag@npm:^3.0.0": - version: 3.0.0 - resolution: "has-flag@npm:3.0.0" - checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad - languageName: node - linkType: hard - -"has-property-descriptors@npm:^1.0.0": - version: 1.0.0 - resolution: "has-property-descriptors@npm:1.0.0" - dependencies: - get-intrinsic: ^1.1.1 - checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": - version: 1.0.3 - resolution: "has-symbols@npm:1.0.3" - checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" - dependencies: - has-symbols: ^1.0.2 - checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c - languageName: node - linkType: hard - -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: ^1.1.1 - checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 - languageName: node - linkType: hard - -"ignore@npm:^4.0.6": - version: 4.0.6 - resolution: "ignore@npm:4.0.6" - checksum: 248f82e50a430906f9ee7f35e1158e3ec4c3971451dd9f99c9bc1548261b4db2b99709f60ac6c6cac9333494384176cc4cc9b07acbe42d52ac6a09cad734d800 - languageName: node - linkType: hard - -"ignore@npm:^5.2.0": - version: 5.2.0 - resolution: "ignore@npm:5.2.0" - checksum: 6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77 - languageName: node - linkType: hard - -"import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" - dependencies: - parent-module: ^1.0.0 - resolve-from: ^4.0.0 - checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: ^1.3.0 - wrappy: 1 - checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd - languageName: node - linkType: hard - -"inherits@npm:2": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 - languageName: node - linkType: hard - -"internal-slot@npm:^1.0.3": - version: 1.0.3 - resolution: "internal-slot@npm:1.0.3" - dependencies: - get-intrinsic: ^1.1.0 - has: ^1.0.3 - side-channel: ^1.0.4 - checksum: 1944f92e981e47aebc98a88ff0db579fd90543d937806104d0b96557b10c1f170c51fb777b97740a8b6ddeec585fca8c39ae99fd08a8e058dfc8ab70937238bf - languageName: node - linkType: hard - -"is-bigint@npm:^1.0.1": - version: 1.0.4 - resolution: "is-bigint@npm:1.0.4" - dependencies: - has-bigints: ^1.0.1 - checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 - languageName: node - linkType: hard - -"is-boolean-object@npm:^1.1.0": - version: 1.1.2 - resolution: "is-boolean-object@npm:1.1.2" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 - languageName: node - linkType: hard - -"is-callable@npm:^1.1.4, is-callable@npm:^1.2.4": - version: 1.2.6 - resolution: "is-callable@npm:1.2.6" - checksum: 7667d6a6be66df00741cfa18c657877c46a00139ea7ea7765251e9db0182745c9ee173506941a329d6914e34e59e9cc80029fb3f68bbf8c22a6c155ee6ea77b3 - languageName: node - linkType: hard - -"is-core-module@npm:^2.8.1, is-core-module@npm:^2.9.0": - version: 2.10.0 - resolution: "is-core-module@npm:2.10.0" - dependencies: - has: ^1.0.3 - checksum: 0f3f77811f430af3256fa7bbc806f9639534b140f8ee69476f632c3e1eb4e28a38be0b9d1b8ecf596179c841b53576129279df95e7051d694dac4ceb6f967593 - languageName: node - linkType: hard - -"is-date-object@npm:^1.0.1": - version: 1.0.5 - resolution: "is-date-object@npm:1.0.5" - dependencies: - has-tostringtag: ^1.0.0 - checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 - languageName: node - linkType: hard - -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: ^2.1.1 - checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 - languageName: node - linkType: hard - -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a - languageName: node - linkType: hard - -"is-number-object@npm:^1.0.4": - version: 1.0.7 - resolution: "is-number-object@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a - languageName: node - linkType: hard - -"is-regex@npm:^1.1.4": - version: 1.1.4 - resolution: "is-regex@npm:1.1.4" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 - languageName: node - linkType: hard - -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a - languageName: node - linkType: hard - -"is-string@npm:^1.0.5, is-string@npm:^1.0.7": - version: 1.0.7 - resolution: "is-string@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 - languageName: node - linkType: hard - -"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": - version: 1.0.4 - resolution: "is-symbol@npm:1.0.4" - dependencies: - has-symbols: ^1.0.2 - checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 - languageName: node - linkType: hard - -"is-weakref@npm:^1.0.2": - version: 1.0.2 - resolution: "is-weakref@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 - languageName: node - linkType: hard - -"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 - languageName: node - linkType: hard - -"js-yaml@npm:^3.13.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: ^1.0.7 - esprima: ^4.0.0 - bin: - js-yaml: bin/js-yaml.js - checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c - languageName: node - linkType: hard - -"jsesc@npm:^2.5.1": - version: 2.5.2 - resolution: "jsesc@npm:2.5.2" - bin: - jsesc: bin/jsesc - checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d - languageName: node - linkType: hard - -"json-schema-traverse@npm:^0.4.1": - version: 0.4.1 - resolution: "json-schema-traverse@npm:0.4.1" - checksum: 7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b - languageName: node - linkType: hard - -"json-schema-traverse@npm:^1.0.0": - version: 1.0.0 - resolution: "json-schema-traverse@npm:1.0.0" - checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad - languageName: node - linkType: hard - -"json-stable-stringify-without-jsonify@npm:^1.0.1": - version: 1.0.1 - resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" - checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 - languageName: node - linkType: hard - -"json5@npm:^1.0.1": - version: 1.0.1 - resolution: "json5@npm:1.0.1" - dependencies: - minimist: ^1.2.0 - bin: - json5: lib/cli.js - checksum: e76ea23dbb8fc1348c143da628134a98adf4c5a4e8ea2adaa74a80c455fc2cdf0e2e13e6398ef819bfe92306b610ebb2002668ed9fc1af386d593691ef346fc3 - languageName: node - linkType: hard - -"json5@npm:^2.2.1": - version: 2.2.1 - resolution: "json5@npm:2.2.1" - bin: - json5: lib/cli.js - checksum: 74b8a23b102a6f2bf2d224797ae553a75488b5adbaee9c9b6e5ab8b510a2fc6e38f876d4c77dea672d4014a44b2399e15f2051ac2b37b87f74c0c7602003543b - languageName: node - linkType: hard - -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.2": - version: 3.3.3 - resolution: "jsx-ast-utils@npm:3.3.3" - dependencies: - array-includes: ^3.1.5 - object.assign: ^4.1.3 - checksum: a2ed78cac49a0f0c4be8b1eafe3c5257a1411341d8e7f1ac740debae003de04e5f6372bfcfbd9d082e954ffd99aac85bcda85b7c6bc11609992483f4cdc0f745 - languageName: node - linkType: hard - -"language-subtag-registry@npm:~0.3.2": - version: 0.3.22 - resolution: "language-subtag-registry@npm:0.3.22" - checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a - languageName: node - linkType: hard - -"language-tags@npm:^1.0.5": - version: 1.0.5 - resolution: "language-tags@npm:1.0.5" - dependencies: - language-subtag-registry: ~0.3.2 - checksum: c81b5d8b9f5f9cfd06ee71ada6ddfe1cf83044dd5eeefcd1e420ad491944da8957688db4a0a9bc562df4afdc2783425cbbdfd152c01d93179cf86888903123cf - languageName: node - linkType: hard - -"levn@npm:^0.4.1": - version: 0.4.1 - resolution: "levn@npm:0.4.1" - dependencies: - prelude-ls: ^1.2.1 - type-check: ~0.4.0 - checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 - languageName: node - linkType: hard - -"lodash.merge@npm:^4.6.2": - version: 4.6.2 - resolution: "lodash.merge@npm:4.6.2" - checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 - languageName: node - linkType: hard - -"lodash.truncate@npm:^4.4.2": - version: 4.4.2 - resolution: "lodash.truncate@npm:4.4.2" - checksum: b463d8a382cfb5f0e71c504dcb6f807a7bd379ff1ea216669aa42c52fc28c54e404bfbd96791aa09e6df0de2c1d7b8f1b7f4b1a61f324d38fe98bc535aeee4f5 - languageName: node - linkType: hard - -"lodash@npm:4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 - languageName: node - linkType: hard - -"lodash@patch:lodash@npm%3A4.17.21#./.yarn/patches/lodash-npm-4.17.21-6382451519.patch::locator=berry-patch%40workspace%3A.": - version: 4.17.21 - resolution: "lodash@patch:lodash@npm%3A4.17.21#./.yarn/patches/lodash-npm-4.17.21-6382451519.patch::version=4.17.21&hash=2c6e9e&locator=berry-patch%40workspace%3A." - checksum: 0f54b5291a5cfa3322cc3cb85716df4e23503535b79a341f12a41231513baaa6285fd9808d9894100dcea8b36bf91644360c4f783db1814719a4e103a04f59f3 - languageName: node - linkType: hard - -"loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" - dependencies: - js-tokens: ^3.0.0 || ^4.0.0 - bin: - loose-envify: cli.js - checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 - languageName: node - linkType: hard - -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: ^4.0.0 - checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 - languageName: node - linkType: hard - -"merge2@npm:^1.3.0, merge2@npm:^1.4.1": - version: 1.4.1 - resolution: "merge2@npm:1.4.1" - checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 - languageName: node - linkType: hard - -"micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" - dependencies: - braces: ^3.0.2 - picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: ^1.1.7 - checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a - languageName: node - linkType: hard - -"minimist@npm:^1.2.0, minimist@npm:^1.2.6": - version: 1.2.6 - resolution: "minimist@npm:1.2.6" - checksum: d15428cd1e11eb14e1233bcfb88ae07ed7a147de251441d61158619dfb32c4d7e9061d09cab4825fdee18ecd6fce323228c8c47b5ba7cd20af378ca4048fb3fb - languageName: node - linkType: hard - -"ms@npm:2.0.0": - version: 2.0.0 - resolution: "ms@npm:2.0.0" - checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 - languageName: node - linkType: hard - -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f - languageName: node - linkType: hard - -"ms@npm:^2.1.1": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d - languageName: node - linkType: hard - -"nanoid@npm:^3.3.4": - version: 3.3.4 - resolution: "nanoid@npm:3.3.4" - bin: - nanoid: bin/nanoid.cjs - checksum: 2fddd6dee994b7676f008d3ffa4ab16035a754f4bb586c61df5a22cf8c8c94017aadd360368f47d653829e0569a92b129979152ff97af23a558331e47e37cd9c - languageName: node - linkType: hard - -"natural-compare@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare@npm:1.4.0" - checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d - languageName: node - linkType: hard - -"next-transpile-modules@npm:9.0.0": - version: 9.0.0 - resolution: "next-transpile-modules@npm:9.0.0" - dependencies: - enhanced-resolve: ^5.7.0 - escalade: ^3.1.1 - checksum: 9a5d86d80cedc2404b2b1d5bd4994f2f7bf60e5e20f24e8cc5cfec34da1418b4a439916f37a95ca336bcf6d81094c3647354ac6a0c6737b3df59e62b6380507d - languageName: node - linkType: hard - -"next@npm:12.2.5": - version: 12.2.5 - resolution: "next@npm:12.2.5" - dependencies: - "@next/env": 12.2.5 - "@next/swc-android-arm-eabi": 12.2.5 - "@next/swc-android-arm64": 12.2.5 - "@next/swc-darwin-arm64": 12.2.5 - "@next/swc-darwin-x64": 12.2.5 - "@next/swc-freebsd-x64": 12.2.5 - "@next/swc-linux-arm-gnueabihf": 12.2.5 - "@next/swc-linux-arm64-gnu": 12.2.5 - "@next/swc-linux-arm64-musl": 12.2.5 - "@next/swc-linux-x64-gnu": 12.2.5 - "@next/swc-linux-x64-musl": 12.2.5 - "@next/swc-win32-arm64-msvc": 12.2.5 - "@next/swc-win32-ia32-msvc": 12.2.5 - "@next/swc-win32-x64-msvc": 12.2.5 - "@swc/helpers": 0.4.3 - caniuse-lite: ^1.0.30001332 - postcss: 8.4.14 - styled-jsx: 5.0.4 - use-sync-external-store: 1.2.0 - peerDependencies: - fibers: ">= 3.1.0" - node-sass: ^6.0.0 || ^7.0.0 - react: ^17.0.2 || ^18.0.0-0 - react-dom: ^17.0.2 || ^18.0.0-0 - sass: ^1.3.0 - dependenciesMeta: - "@next/swc-android-arm-eabi": - optional: true - "@next/swc-android-arm64": - optional: true - "@next/swc-darwin-arm64": - optional: true - "@next/swc-darwin-x64": - optional: true - "@next/swc-freebsd-x64": - optional: true - "@next/swc-linux-arm-gnueabihf": - optional: true - "@next/swc-linux-arm64-gnu": - optional: true - "@next/swc-linux-arm64-musl": - optional: true - "@next/swc-linux-x64-gnu": - optional: true - "@next/swc-linux-x64-musl": - optional: true - "@next/swc-win32-arm64-msvc": - optional: true - "@next/swc-win32-ia32-msvc": - optional: true - "@next/swc-win32-x64-msvc": - optional: true - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - bin: - next: dist/bin/next - checksum: e8fcbd93d74fda81640fd174a9d380f22db404d3ce0893730db3db806317ae18c86d1dbb502e63e47c92fb21a93812de62639c2f1204330cb569fdac4d3d0573 - languageName: node - linkType: hard - -"node-releases@npm:^2.0.6": - version: 2.0.6 - resolution: "node-releases@npm:2.0.6" - checksum: e86a926dc9fbb3b41b4c4a89d998afdf140e20a4e8dbe6c0a807f7b2948b42ea97d7fd3ad4868041487b6e9ee98409829c6e4d84a734a4215dff060a7fbeb4bf - languageName: node - linkType: hard - -"object-assign@npm:^4.1.1": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f - languageName: node - linkType: hard - -"object-inspect@npm:^1.12.2, object-inspect@npm:^1.9.0": - version: 1.12.2 - resolution: "object-inspect@npm:1.12.2" - checksum: a534fc1b8534284ed71f25ce3a496013b7ea030f3d1b77118f6b7b1713829262be9e6243acbcb3ef8c626e2b64186112cb7f6db74e37b2789b9c789ca23048b2 - languageName: node - linkType: hard - -"object-keys@npm:^1.1.1": - version: 1.1.1 - resolution: "object-keys@npm:1.1.1" - checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a - languageName: node - linkType: hard - -"object.assign@npm:^4.1.3, object.assign@npm:^4.1.4": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - has-symbols: ^1.0.3 - object-keys: ^1.1.1 - checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864 - languageName: node - linkType: hard - -"object.entries@npm:^1.1.5": - version: 1.1.5 - resolution: "object.entries@npm:1.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.1 - checksum: d658696f74fd222060d8428d2a9fda2ce736b700cb06f6bdf4a16a1892d145afb746f453502b2fa55d1dca8ead6f14ddbcf66c545df45adadea757a6c4cd86c7 - languageName: node - linkType: hard - -"object.fromentries@npm:^2.0.5": - version: 2.0.5 - resolution: "object.fromentries@npm:2.0.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.1 - checksum: 61a0b565ded97b76df9e30b569729866e1824cce902f98e90bb106e84f378aea20163366f66dc75c9000e2aad2ed0caf65c6f530cb2abc4c0c0f6c982102db4b - languageName: node - linkType: hard - -"object.hasown@npm:^1.1.1": - version: 1.1.1 - resolution: "object.hasown@npm:1.1.1" - dependencies: - define-properties: ^1.1.4 - es-abstract: ^1.19.5 - checksum: d8ed4907ce57f48b93e3b53c418fd6787bf226a51e8d698c91e39b78e80fe5b124cb6282f6a9d5be21cf9e2c7829ab10206dcc6112b7748860eefe641880c793 - languageName: node - linkType: hard - -"object.values@npm:^1.1.5": - version: 1.1.5 - resolution: "object.values@npm:1.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.1 - checksum: 0f17e99741ebfbd0fa55ce942f6184743d3070c61bd39221afc929c8422c4907618c8da694c6915bc04a83ab3224260c779ba37fc07bb668bdc5f33b66a902a4 - languageName: node - linkType: hard - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: 1 - checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 - languageName: node - linkType: hard - -"optionator@npm:^0.9.1": - version: 0.9.1 - resolution: "optionator@npm:0.9.1" - dependencies: - deep-is: ^0.1.3 - fast-levenshtein: ^2.0.6 - levn: ^0.4.1 - prelude-ls: ^1.2.1 - type-check: ^0.4.0 - word-wrap: ^1.2.3 - checksum: dbc6fa065604b24ea57d734261914e697bd73b69eff7f18e967e8912aa2a40a19a9f599a507fa805be6c13c24c4eae8c71306c239d517d42d4c041c942f508a0 - languageName: node - linkType: hard - -"parent-module@npm:^1.0.0": - version: 1.0.1 - resolution: "parent-module@npm:1.0.1" - dependencies: - callsites: ^3.0.0 - checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff - languageName: node - linkType: hard - -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a - languageName: node - linkType: hard - -"path-type@npm:^4.0.0": - version: 4.0.0 - resolution: "path-type@npm:4.0.0" - checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 - languageName: node - linkType: hard - -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 - languageName: node - linkType: hard - -"picomatch@npm:^2.3.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf - languageName: node - linkType: hard - -"postcss@npm:8.4.14": - version: 8.4.14 - resolution: "postcss@npm:8.4.14" - dependencies: - nanoid: ^3.3.4 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: fe58766ff32e4becf65a7d57678995cfd239df6deed2fe0557f038b47c94e4132e7e5f68b5aa820c13adfec32e523b693efaeb65798efb995ce49ccd83953816 - languageName: node - linkType: hard - -"prelude-ls@npm:^1.2.1": - version: 1.2.1 - resolution: "prelude-ls@npm:1.2.1" - checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a - languageName: node - linkType: hard - -prettier@latest: - version: 2.7.1 - resolution: "prettier@npm:2.7.1" - bin: - prettier: bin-prettier.js - checksum: 55a4409182260866ab31284d929b3cb961e5fdb91fe0d2e099dac92eaecec890f36e524b4c19e6ceae839c99c6d7195817579cdffc8e2c80da0cb794463a748b - languageName: node - linkType: hard - -"progress@npm:^2.0.0": - version: 2.0.3 - resolution: "progress@npm:2.0.3" - checksum: f67403fe7b34912148d9252cb7481266a354bd99ce82c835f79070643bb3c6583d10dbcfda4d41e04bbc1d8437e9af0fb1e1f2135727878f5308682a579429b7 - languageName: node - linkType: hard - -"prop-types@npm:^15.8.1": - version: 15.8.1 - resolution: "prop-types@npm:15.8.1" - dependencies: - loose-envify: ^1.4.0 - object-assign: ^4.1.1 - react-is: ^16.13.1 - checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0": - version: 2.1.1 - resolution: "punycode@npm:2.1.1" - checksum: 823bf443c6dd14f669984dea25757b37993f67e8d94698996064035edd43bed8a5a17a9f12e439c2b35df1078c6bec05a6c86e336209eb1061e8025c481168e8 - languageName: node - linkType: hard - -"queue-microtask@npm:^1.2.2": - version: 1.2.3 - resolution: "queue-microtask@npm:1.2.3" - checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 - languageName: node - linkType: hard - -"react-dom@npm:18.2.0": - version: 18.2.0 - resolution: "react-dom@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - scheduler: ^0.23.0 - peerDependencies: - react: ^18.2.0 - checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc - languageName: node - linkType: hard - -"react-is@npm:^16.13.1": - version: 16.13.1 - resolution: "react-is@npm:16.13.1" - checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f - languageName: node - linkType: hard - -"react@npm:18.2.0, react@npm:^18.2.0": - version: 18.2.0 - resolution: "react@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b - languageName: node - linkType: hard - -"regenerator-runtime@npm:^0.13.4": - version: 0.13.9 - resolution: "regenerator-runtime@npm:0.13.9" - checksum: 65ed455fe5afd799e2897baf691ca21c2772e1a969d19bb0c4695757c2d96249eb74ee3553ea34a91062b2a676beedf630b4c1551cc6299afb937be1426ec55e - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.4.1, regexp.prototype.flags@npm:^1.4.3": - version: 1.4.3 - resolution: "regexp.prototype.flags@npm:1.4.3" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - functions-have-names: ^1.2.2 - checksum: 51228bae732592adb3ededd5e15426be25f289e9c4ef15212f4da73f4ec3919b6140806374b8894036a86020d054a8d2657d3fee6bb9b4d35d8939c20030b7a6 - languageName: node - linkType: hard - -"regexpp@npm:^3.1.0": - version: 3.2.0 - resolution: "regexpp@npm:3.2.0" - checksum: a78dc5c7158ad9ddcfe01aa9144f46e192ddbfa7b263895a70a5c6c73edd9ce85faf7c0430e59ac38839e1734e275b9c3de5c57ee3ab6edc0e0b1bdebefccef8 - languageName: node - linkType: hard - -"require-from-string@npm:^2.0.2": - version: 2.0.2 - resolution: "require-from-string@npm:2.0.2" - checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b - languageName: node - linkType: hard - -"resolve-from@npm:^4.0.0": - version: 4.0.0 - resolution: "resolve-from@npm:4.0.0" - checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f - languageName: node - linkType: hard - -"resolve@npm:^1.20.0, resolve@npm:^1.22.0": - version: 1.22.1 - resolution: "resolve@npm:1.22.1" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 07af5fc1e81aa1d866cbc9e9460fbb67318a10fa3c4deadc35c3ad8a898ee9a71a86a65e4755ac3195e0ea0cfbe201eb323ebe655ce90526fd61917313a34e4e - languageName: node - linkType: hard - -"resolve@npm:^2.0.0-next.3": - version: 2.0.0-next.4 - resolution: "resolve@npm:2.0.0-next.4" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: c438ac9a650f2030fd074219d7f12ceb983b475da2d89ad3d6dd05fbf6b7a0a8cd37d4d10b43cb1f632bc19f22246ab7f36ebda54d84a29bfb2910a0680906d3 - languageName: node - linkType: hard - -"resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin": - version: 1.22.1 - resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=07638b" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 5656f4d0bedcf8eb52685c1abdf8fbe73a1603bb1160a24d716e27a57f6cecbe2432ff9c89c2bd57542c3a7b9d14b1882b73bfe2e9d7849c9a4c0b8b39f02b8b - languageName: node - linkType: hard - -"resolve@patch:resolve@^2.0.0-next.3#~builtin": - version: 2.0.0-next.4 - resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin::version=2.0.0-next.4&hash=07638b" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 4bf9f4f8a458607af90518ff73c67a4bc1a38b5a23fef2bb0ccbd45e8be89820a1639b637b0ba377eb2be9eedfb1739a84cde24fe4cd670c8207d8fea922b011 - languageName: node - linkType: hard - -"reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc - languageName: node - linkType: hard - -"rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: ^7.1.3 - bin: - rimraf: bin.js - checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 - languageName: node - linkType: hard - -"run-parallel@npm:^1.1.9": - version: 1.2.0 - resolution: "run-parallel@npm:1.2.0" - dependencies: - queue-microtask: ^1.2.2 - checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d - languageName: node - linkType: hard - -"safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c - languageName: node - linkType: hard - -"scheduler@npm:^0.23.0": - version: 0.23.0 - resolution: "scheduler@npm:0.23.0" - dependencies: - loose-envify: ^1.1.0 - checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a - languageName: node - linkType: hard - -"semver@npm:^6.3.0": - version: 6.3.0 - resolution: "semver@npm:6.3.0" - bin: - semver: ./bin/semver.js - checksum: 1b26ecf6db9e8292dd90df4e781d91875c0dcc1b1909e70f5d12959a23c7eebb8f01ea581c00783bbee72ceeaad9505797c381756326073850dc36ed284b21b9 - languageName: node - linkType: hard - -"semver@npm:^7.2.1, semver@npm:^7.3.7": - version: 7.3.7 - resolution: "semver@npm:7.3.7" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: 2fa3e877568cd6ce769c75c211beaed1f9fce80b28338cadd9d0b6c40f2e2862bafd62c19a6cff42f3d54292b7c623277bcab8816a2b5521cf15210d43e75232 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: ^3.0.0 - checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 - languageName: node - linkType: hard - -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" - dependencies: - call-bind: ^1.0.0 - get-intrinsic: ^1.0.2 - object-inspect: ^1.9.0 - checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 - languageName: node - linkType: hard - -"slash@npm:^3.0.0": - version: 3.0.0 - resolution: "slash@npm:3.0.0" - checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c - languageName: node - linkType: hard - -"slice-ansi@npm:^4.0.0": - version: 4.0.0 - resolution: "slice-ansi@npm:4.0.0" - dependencies: - ansi-styles: ^4.0.0 - astral-regex: ^2.0.0 - is-fullwidth-code-point: ^3.0.0 - checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 - languageName: node - linkType: hard - -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c - languageName: node - linkType: hard - -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 - languageName: node - linkType: hard - -"string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: ^8.0.0 - is-fullwidth-code-point: ^3.0.0 - strip-ansi: ^6.0.1 - checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb - languageName: node - linkType: hard - -"string.prototype.matchall@npm:^4.0.7": - version: 4.0.7 - resolution: "string.prototype.matchall@npm:4.0.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.1 - get-intrinsic: ^1.1.1 - has-symbols: ^1.0.3 - internal-slot: ^1.0.3 - regexp.prototype.flags: ^1.4.1 - side-channel: ^1.0.4 - checksum: fc09f3ccbfb325de0472bcc87a6be0598a7499e0b4a31db5789676155b15754a4cc4bb83924f15fc9ed48934dac7366ee52c8b9bd160bed6fd072c93b489e75c - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.5": - version: 1.0.5 - resolution: "string.prototype.trimend@npm:1.0.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.19.5 - checksum: d44f543833112f57224e79182debadc9f4f3bf9d48a0414d6f0cbd2a86f2b3e8c0ca1f95c3f8e5b32ae83e91554d79d932fc746b411895f03f93d89ed3dfb6bc - languageName: node - linkType: hard - -"string.prototype.trimstart@npm:^1.0.5": - version: 1.0.5 - resolution: "string.prototype.trimstart@npm:1.0.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.19.5 - checksum: a4857c5399ad709d159a77371eeaa8f9cc284469a0b5e1bfe405de16f1fd4166a8ea6f4180e55032f348d1b679b1599fd4301fbc7a8b72bdb3e795e43f7b1048 - languageName: node - linkType: hard - -"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: ^5.0.1 - checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c - languageName: node - linkType: hard - -"strip-bom@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-bom@npm:3.0.0" - checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b - languageName: node - linkType: hard - -"strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 - languageName: node - linkType: hard - -"styled-jsx@npm:5.0.4": - version: 5.0.4 - resolution: "styled-jsx@npm:5.0.4" - peerDependencies: - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" - peerDependenciesMeta: - "@babel/core": - optional: true - babel-plugin-macros: - optional: true - checksum: db7530155626e5eebc9d80ca117ea5aed6219b0a65469196b0b5727550fbe743117d7eea1499d80511ccb312d31f4a1027a58d1f94a83f0986c9acfdcce8bdd1 - languageName: node - linkType: hard - -"supports-color@npm:^5.3.0": - version: 5.5.0 - resolution: "supports-color@npm:5.5.0" - dependencies: - has-flag: ^3.0.0 - checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac - languageName: node - linkType: hard - -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: ^4.0.0 - checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae - languageName: node - linkType: hard - -"table@npm:^6.0.9": - version: 6.8.0 - resolution: "table@npm:6.8.0" - dependencies: - ajv: ^8.0.1 - lodash.truncate: ^4.4.2 - slice-ansi: ^4.0.0 - string-width: ^4.2.3 - strip-ansi: ^6.0.1 - checksum: 5b07fe462ee03d2e1fac02cbb578efd2e0b55ac07e3d3db2e950aa9570ade5a4a2b8d3c15e9f25c89e4e50b646bc4269934601ee1eef4ca7968ad31960977690 - languageName: node - linkType: hard - -"tapable@npm:^2.2.0": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 - languageName: node - linkType: hard - -"text-table@npm:^0.2.0": - version: 0.2.0 - resolution: "text-table@npm:0.2.0" - checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a - languageName: node - linkType: hard - -"to-fast-properties@npm:^2.0.0": - version: 2.0.0 - resolution: "to-fast-properties@npm:2.0.0" - checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: ^7.0.0 - checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed - languageName: node - linkType: hard - -"tsconfig-paths@npm:^3.14.1": - version: 3.14.1 - resolution: "tsconfig-paths@npm:3.14.1" - dependencies: - "@types/json5": ^0.0.29 - json5: ^1.0.1 - minimist: ^1.2.6 - strip-bom: ^3.0.0 - checksum: 8afa01c673ebb4782ba53d3a12df97fa837ce524f8ad38ee4e2b2fd57f5ac79abc21c574e9e9eb014d93efe7fe8214001b96233b5c6ea75bd1ea82afe17a4c6d - languageName: node - linkType: hard - -"tsconfig@*, tsconfig@workspace:packages/tsconfig": - version: 0.0.0-use.local - resolution: "tsconfig@workspace:packages/tsconfig" - languageName: unknown - linkType: soft - -"tslib@npm:^1.8.1": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd - languageName: node - linkType: hard - -"tslib@npm:^2.4.0": - version: 2.4.0 - resolution: "tslib@npm:2.4.0" - checksum: 8c4aa6a3c5a754bf76aefc38026134180c053b7bd2f81338cb5e5ebf96fefa0f417bff221592bf801077f5bf990562f6264fecbc42cd3309b33872cb6fc3b113 - languageName: node - linkType: hard - -"tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" - dependencies: - tslib: ^1.8.1 - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 1843f4c1b2e0f975e08c4c21caa4af4f7f65a12ac1b81b3b8489366826259323feb3fc7a243123453d2d1a02314205a7634e048d4a8009921da19f99755cdc48 - languageName: node - linkType: hard - -"turbo-android-arm64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-android-arm64@npm:1.4.6" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"turbo-darwin-64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-darwin-64@npm:1.4.6" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"turbo-darwin-arm64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-darwin-arm64@npm:1.4.6" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"turbo-freebsd-64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-freebsd-64@npm:1.4.6" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"turbo-freebsd-arm64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-freebsd-arm64@npm:1.4.6" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"turbo-linux-32@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-linux-32@npm:1.4.6" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"turbo-linux-64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-linux-64@npm:1.4.6" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"turbo-linux-arm64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-linux-arm64@npm:1.4.6" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"turbo-linux-arm@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-linux-arm@npm:1.4.6" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"turbo-linux-mips64le@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-linux-mips64le@npm:1.4.6" - conditions: os=linux & cpu=mipsel - languageName: node - linkType: hard - -"turbo-linux-ppc64le@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-linux-ppc64le@npm:1.4.6" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"turbo-windows-32@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-windows-32@npm:1.4.6" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"turbo-windows-64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-windows-64@npm:1.4.6" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"turbo-windows-arm64@npm:1.4.6": - version: 1.4.6 - resolution: "turbo-windows-arm64@npm:1.4.6" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -turbo@latest: - version: 1.4.6 - resolution: "turbo@npm:1.4.6" - dependencies: - turbo-android-arm64: 1.4.6 - turbo-darwin-64: 1.4.6 - turbo-darwin-arm64: 1.4.6 - turbo-freebsd-64: 1.4.6 - turbo-freebsd-arm64: 1.4.6 - turbo-linux-32: 1.4.6 - turbo-linux-64: 1.4.6 - turbo-linux-arm: 1.4.6 - turbo-linux-arm64: 1.4.6 - turbo-linux-mips64le: 1.4.6 - turbo-linux-ppc64le: 1.4.6 - turbo-windows-32: 1.4.6 - turbo-windows-64: 1.4.6 - turbo-windows-arm64: 1.4.6 - dependenciesMeta: - turbo-android-arm64: - optional: true - turbo-darwin-64: - optional: true - turbo-darwin-arm64: - optional: true - turbo-freebsd-64: - optional: true - turbo-freebsd-arm64: - optional: true - turbo-linux-32: - optional: true - turbo-linux-64: - optional: true - turbo-linux-arm: - optional: true - turbo-linux-arm64: - optional: true - turbo-linux-mips64le: - optional: true - turbo-linux-ppc64le: - optional: true - turbo-windows-32: - optional: true - turbo-windows-64: - optional: true - turbo-windows-arm64: - optional: true - bin: - turbo: bin/turbo - checksum: f7191f36e0abddf6dc88eb9a83a007a8616ebed1edd44c37f9b19e0451f3ce90c4406699f6166a99c0a6f8d39cc1f24d96513b7ef16b21747863827538b9c966 - languageName: node - linkType: hard - -"type-check@npm:^0.4.0, type-check@npm:~0.4.0": - version: 0.4.0 - resolution: "type-check@npm:0.4.0" - dependencies: - prelude-ls: ^1.2.1 - checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a - languageName: node - linkType: hard - -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 - languageName: node - linkType: hard - -"typescript@npm:^4.5.2, typescript@npm:^4.5.3, typescript@npm:^4.7.4": - version: 4.8.3 - resolution: "typescript@npm:4.8.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 8286a5edcaf3d68e65c451aa1e7150ad1cf53ee0813c07ec35b7abdfdb10f355ecaa13c6a226a694ae7a67785fd7eeebf89f845da0b4f7e4a35561ddc459aba0 - languageName: node - linkType: hard - -"typescript@patch:typescript@^4.5.2#~builtin, typescript@patch:typescript@^4.5.3#~builtin, typescript@patch:typescript@^4.7.4#~builtin": - version: 4.8.3 - resolution: "typescript@patch:typescript@npm%3A4.8.3#~builtin::version=4.8.3&hash=a1c5e5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 2222d2382fb3146089b1d27ce2b55e9d1f99cc64118f1aba75809b693b856c5d3c324f052f60c75b577947fc538bc1c27bad0eb76cbdba9a63a253489504ba7e - languageName: node - linkType: hard - -"ui@*, ui@workspace:packages/ui": - version: 0.0.0-use.local - resolution: "ui@workspace:packages/ui" - dependencies: - "@types/react": ^17.0.37 - "@types/react-dom": ^17.0.11 - eslint: ^7.32.0 - eslint-config-custom: "*" - react: ^18.2.0 - tsconfig: "*" - typescript: ^4.5.2 - languageName: unknown - linkType: soft - -"unbox-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "unbox-primitive@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - has-bigints: ^1.0.2 - has-symbols: ^1.0.3 - which-boxed-primitive: ^1.0.2 - checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 - languageName: node - linkType: hard - -"update-browserslist-db@npm:^1.0.9": - version: 1.0.9 - resolution: "update-browserslist-db@npm:1.0.9" - dependencies: - escalade: ^3.1.1 - picocolors: ^1.0.0 - peerDependencies: - browserslist: ">= 4.21.0" - bin: - browserslist-lint: cli.js - checksum: f625899b236f6a4d7f62b56be1b8da230c5563d1fef84d3ef148f2e1a3f11a5a4b3be4fd7e3703e51274c116194017775b10afb4de09eb2c0d09d36b90f1f578 - languageName: node - linkType: hard - -"uri-js@npm:^4.2.2": - version: 4.4.1 - resolution: "uri-js@npm:4.4.1" - dependencies: - punycode: ^2.1.0 - checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 - languageName: node - linkType: hard - -"use-sync-external-store@npm:1.2.0": - version: 1.2.0 - resolution: "use-sync-external-store@npm:1.2.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a - languageName: node - linkType: hard - -"v8-compile-cache@npm:^2.0.3": - version: 2.3.0 - resolution: "v8-compile-cache@npm:2.3.0" - checksum: adb0a271eaa2297f2f4c536acbfee872d0dd26ec2d76f66921aa7fc437319132773483344207bdbeee169225f4739016d8d2dbf0553913a52bb34da6d0334f8e - languageName: node - linkType: hard - -"web@workspace:apps/web": - version: 0.0.0-use.local - resolution: "web@workspace:apps/web" - dependencies: - "@babel/core": ^7.0.0 - "@types/node": ^17.0.12 - "@types/react": 18.0.17 - eslint: 7.32.0 - eslint-config-custom: "*" - next: 12.2.5 - next-transpile-modules: 9.0.0 - react: 18.2.0 - react-dom: 18.2.0 - tsconfig: "*" - typescript: ^4.5.3 - ui: "*" - languageName: unknown - linkType: soft - -"which-boxed-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "which-boxed-primitive@npm:1.0.2" - dependencies: - is-bigint: ^1.0.1 - is-boolean-object: ^1.1.0 - is-number-object: ^1.0.4 - is-string: ^1.0.5 - is-symbol: ^1.0.3 - checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: ^2.0.0 - bin: - node-which: ./bin/node-which - checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 - languageName: node - linkType: hard - -"word-wrap@npm:^1.2.3": - version: 1.2.3 - resolution: "word-wrap@npm:1.2.3" - checksum: 30b48f91fcf12106ed3186ae4fa86a6a1842416df425be7b60485de14bec665a54a68e4b5156647dec3a70f25e84d270ca8bc8cd23182ed095f5c7206a938c1f - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 - languageName: node - linkType: hard diff --git a/crates/turborepo-lockfiles/fixtures/berry_semver.lock b/crates/turborepo-lockfiles/fixtures/berry_semver.lock deleted file mode 100644 index 0d3e01c24bf25..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/berry_semver.lock +++ /dev/null @@ -1,31 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"file-source@npm:2": - version: 2.6.1 - resolution: "file-source@npm:2.6.1" - dependencies: - stream-source: 0.10 - checksum: db27232df214b27ddd7026bbd202caf0bde31123811ebac0a9772d6a41735efdc3ee8050661f56d02d43811bde79938adb5ed8cbfe5f813c7cd09b86d19b6c84 - languageName: node - linkType: hard - -"foo@workspace:packages/foo": - version: 0.0.0-use.local - resolution: "foo@workspace:packages/foo" - dependencies: - file-source: 2 - languageName: unknown - linkType: soft - -"stream-source@npm:0.10": - version: 0.10.12 - resolution: "stream-source@npm:0.10.12" - checksum: 65a0e0a38014dcfa6e219e92d83bde5fe716cf16df339e9d7e951525c0d129771416de4d77c3389c38cdd20a43d9575f90cc91041d6fa0c2f053b989780e3591 - languageName: node - linkType: hard - diff --git a/crates/turborepo-lockfiles/fixtures/gh_8849.lock b/crates/turborepo-lockfiles/fixtures/gh_8849.lock deleted file mode 100644 index 9fde66b81238e..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/gh_8849.lock +++ /dev/null @@ -1,95 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -prettier@^3.2.5: - version "3.3.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" - integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== - -"string-width-cjs@npm:string-width@4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string-width@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -strip-ansi@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -turbo-darwin-64@2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.0.9.tgz#dc7bb92060a41b92155195dba5850c9669fa765a" - integrity sha512-owlGsOaExuVGBUfrnJwjkL1BWlvefjSKczEAcpLx4BI7Oh6ttakOi+JyomkPkFlYElRpjbvlR2gP8WIn6M/+xQ== - -turbo-darwin-arm64@2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.9.tgz#6e5ce2c0f03999c6ec0116d5525841107da3078b" - integrity sha512-XAXkKkePth5ZPPE/9G9tTnPQx0C8UTkGWmNGYkpmGgRr8NedW+HrPsi9N0HcjzzIH9A4TpNYvtiV+WcwdaEjKA== - -turbo-linux-64@2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.0.9.tgz#e00e5e1b1cffab23c58888e7c397e108dc24fe2f" - integrity sha512-l9wSgEjrCFM1aG16zItBsZ206ZlhSSx1owB8Cgskfv0XyIXRGHRkluihiaxkp+UeU5WoEfz4EN5toc+ICA0q0w== - -turbo-linux-arm64@2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.0.9.tgz#d240e4f0a784d03f1a79fd9e6c4e83abd9aa57c7" - integrity sha512-gRnjxXRne18B27SwxXMqL3fJu7jw/8kBrOBTBNRSmZZiG1Uu3nbnP7b4lgrA/bCku6C0Wligwqurvtpq6+nFHA== - -turbo-windows-64@2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.0.9.tgz#d52835302e722cc7de670b90aca55ce2b3516879" - integrity sha512-ZVo0apxUvaRq4Vm1qhsfqKKhtRgReYlBVf9MQvVU1O9AoyydEQvLDO1ryqpXDZWpcHoFxHAQc9msjAMtE5K2lA== - -turbo-windows-arm64@2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.0.9.tgz#45f0aa685514ec1cc753a559924e003b22b24bb7" - integrity sha512-sGRz7c5Pey6y7y9OKi8ypbWNuIRPF9y8xcMqL56OZifSUSo+X2EOsOleR9MKxQXVaqHPGOUKWsE6y8hxBi9pag== - -turbo@^2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.0.9.tgz#fa0ab576c4cb9a8fc9db648e9ac9adfe10a22ae5" - integrity sha512-QaLaUL1CqblSKKPgLrFW3lZWkWG4pGBQNW+q1ScJB5v1D/nFWtsrD/yZljW/bdawg90ihi4/ftQJ3h6fz1FamA== - optionalDependencies: - turbo-darwin-64 "2.0.9" - turbo-darwin-arm64 "2.0.9" - turbo-linux-64 "2.0.9" - turbo-linux-arm64 "2.0.9" - turbo-windows-64 "2.0.9" - turbo-windows-arm64 "2.0.9" - -typescript@^5.4.5: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== diff --git a/crates/turborepo-lockfiles/fixtures/minimal-berry-resolutions.lock b/crates/turborepo-lockfiles/fixtures/minimal-berry-resolutions.lock deleted file mode 100644 index 6533daca67fd1..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/minimal-berry-resolutions.lock +++ /dev/null @@ -1,50 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"a@workspace:packages/a": - version: 0.0.0-use.local - resolution: "a@workspace:packages/a" - languageName: unknown - linkType: soft - -"b@workspace:packages/b": - version: 0.0.0-use.local - resolution: "b@workspace:packages/b" - dependencies: - debug: ^4.3.4 - lodash: ^4.17.21 - languageName: unknown - linkType: soft - -"debug@npm:1.0.0": - version: 1.0.0 - resolution: "debug@npm:1.0.0" - dependencies: - ms: 0.6.2 - checksum: edfec8784737afbeea43cc78c3f56c33b88d3e751cc7220ae7a1c5370ff099e7352703275bdb56ea9967f92961231ce0625f8234d82259047303849671153f03 - languageName: node - linkType: hard - -"lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 - languageName: node - linkType: hard - -"ms@npm:0.6.0": - version: 0.6.0 - resolution: "ms@npm:0.6.0" - checksum: 4dee72321abe75382a9ba73cf69efca4484fd75f997ff74904eb5803437f47880e6b69b7db31b808040d9cd0276c34c263f9ca664e14027a1d71943cc8aeecff - languageName: node - linkType: hard - -"test@workspace:.": - version: 0.0.0-use.local - resolution: "test@workspace:." - languageName: unknown - linkType: soft diff --git a/crates/turborepo-lockfiles/fixtures/minimal-berry.lock b/crates/turborepo-lockfiles/fixtures/minimal-berry.lock deleted file mode 100644 index 3844ce3067698..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/minimal-berry.lock +++ /dev/null @@ -1,45 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8c8 - -"a@workspace:packages/a": - version: 0.0.0-use.local - resolution: "a@workspace:packages/a" - dependencies: - c: "*" - lodash: ^4.17.0 - peerDependencies: - lodash: ^3.0.0 || ^4.0.0 - languageName: unknown - linkType: soft - -"b@workspace:packages/b": - version: 0.0.0-use.local - resolution: "b@workspace:packages/b" - dependencies: - c: "*" - lodash: ^3.0.0 || ^4.0.0 - languageName: unknown - linkType: soft - -"c@*, c@workspace:packages/c": - version: 0.0.0-use.local - resolution: "c@workspace:packages/c" - languageName: unknown - linkType: soft - -"lodash@npm:^3.0.0 || ^4.0.0, lodash@npm:^4.17.0": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 - languageName: node - linkType: hard - -"minimal-berry@workspace:.": - version: 0.0.0-use.local - resolution: "minimal-berry@workspace:." - languageName: unknown - linkType: soft diff --git a/crates/turborepo-lockfiles/fixtures/npm-lock-workspace-variation.json b/crates/turborepo-lockfiles/fixtures/npm-lock-workspace-variation.json deleted file mode 100644 index 4dcfc2da8a18e..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/npm-lock-workspace-variation.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "name": "npm-prune-workspace-variation", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "npm-prune", - "version": "0.0.0", - "workspaces": { "packages": ["apps/*", "packages/*"] }, - "devDependencies": { - "eslint-config-custom": "*", - "prettier": "latest", - "turbo": "latest" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "apps/docs": { - "version": "0.0.0", - "dependencies": { - "lodash": "^3.0.0", - "next": "12.3.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "ui": "*" - }, - "devDependencies": { - "@babel/core": "^7.0.0", - "@types/node": "^17.0.12", - "@types/react": "18.0.17", - "eslint": "7.32.0", - "eslint-config-custom": "*", - "next-transpile-modules": "9.0.0", - "tsconfig": "*", - "typescript": "^4.5.3" - } - }, - "apps/web": { - "version": "0.0.0", - "dependencies": { - "lodash": "^4.17.21", - "next": "12.3.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "ui": "*" - }, - "devDependencies": { - "@babel/core": "^7.0.0", - "@types/node": "^17.0.12", - "@types/react": "18.0.17", - "eslint": "7.32.0", - "eslint-config-custom": "*", - "next-transpile-modules": "9.0.0", - "tsconfig": "*", - "typescript": "^4.5.3" - } - }, - "apps/web/node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "engines": ["node >= 0.8.0"] - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz", - "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz", - "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.19.3", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - } - } -} diff --git a/crates/turborepo-lockfiles/fixtures/npm-lock.json b/crates/turborepo-lockfiles/fixtures/npm-lock.json deleted file mode 100644 index c5607f1a72c72..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/npm-lock.json +++ /dev/null @@ -1,6472 +0,0 @@ -{ - "name": "npm-prune", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "npm-prune", - "version": "0.0.0", - "workspaces": ["apps/*", "packages/*"], - "devDependencies": { - "eslint-config-custom": "*", - "prettier": "latest", - "turbo": "latest" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "apps/docs": { - "version": "0.0.0", - "dependencies": { - "lodash": "^3.0.0", - "next": "12.3.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "ui": "*" - }, - "devDependencies": { - "@babel/core": "^7.0.0", - "@types/node": "^17.0.12", - "@types/react": "18.0.17", - "eslint": "7.32.0", - "eslint-config-custom": "*", - "next-transpile-modules": "9.0.0", - "tsconfig": "*", - "typescript": "^4.5.3" - } - }, - "apps/web": { - "version": "0.0.0", - "dependencies": { - "lodash": "^4.17.21", - "next": "12.3.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "ui": "*" - }, - "devDependencies": { - "@babel/core": "^7.0.0", - "@types/node": "^17.0.12", - "@types/react": "18.0.17", - "eslint": "7.32.0", - "eslint-config-custom": "*", - "next-transpile-modules": "9.0.0", - "tsconfig": "*", - "typescript": "^4.5.3" - } - }, - "apps/web/node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "engines": ["node >= 0.8.0"] - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz", - "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz", - "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.19.3", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", - "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz", - "integrity": "sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==", - "dependencies": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz", - "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.3", - "@babel/types": "^7.19.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz", - "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.18.10", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@next/env": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.0.tgz", - "integrity": "sha512-PTJpjAFVbzBQ9xXpzMTroShvD5YDIIy46jQ7d4LrWpY+/5a8H90Tm8hE3Hvkc5RBRspVo7kvEOnqQms0A+2Q6w==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.1.tgz", - "integrity": "sha512-sw+lTf6r6P0j+g/n9y4qdWWI2syPqZx+uc0+B/fRENqfR3KpSid6MIKqc9gNwGhJASazEQ5b3w8h4cAET213jw==", - "dependencies": { - "glob": "7.1.7" - } - }, - "node_modules/@next/swc-android-arm-eabi": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.0.tgz", - "integrity": "sha512-/PuirPnAKsYBw93w/7Q9hqy+KGOU9mjYprZ/faxMUJh/dc6v3rYLxkZKNG9nFPIW4QKNTCnhP40xF9hLnxO+xg==", - "cpu": ["arm"], - "optional": true, - "os": ["android"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-android-arm64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.0.tgz", - "integrity": "sha512-OaI+FhAM6P9B6Ybwbn0Zl8YwWido0lLwhDBi9WiYCh4RQmIXAyVIoIJPHo4fP05+mXaJ/k1trvDvuURvHOq2qw==", - "cpu": ["arm64"], - "optional": true, - "os": ["android"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.0.tgz", - "integrity": "sha512-9s4d3Mhii+WFce8o8Jok7WC3Bawkr9wEUU++SJRptjU1L5tsfYJMrSYCACHLhZujziNDLyExe4Hwwsccps1sfg==", - "cpu": ["arm64"], - "optional": true, - "os": ["darwin"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.0.tgz", - "integrity": "sha512-2scC4MqUTwGwok+wpVxP+zWp7WcCAVOtutki2E1n99rBOTnUOX6qXkgxSy083yBN6GqwuC/dzHeN7hIKjavfRA==", - "cpu": ["x64"], - "optional": true, - "os": ["darwin"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-freebsd-x64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.0.tgz", - "integrity": "sha512-xAlruUREij/bFa+qsE1tmsP28t7vz02N4ZDHt2lh3uJUniE0Ne9idyIDLc1Ed0IF2RjfgOp4ZVunuS3OM0sngw==", - "cpu": ["x64"], - "optional": true, - "os": ["freebsd"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm-gnueabihf": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.0.tgz", - "integrity": "sha512-jin2S4VT/cugc2dSZEUIabhYDJNgrUh7fufbdsaAezgcQzqfdfJqfxl4E9GuafzB4cbRPTaqA0V5uqbp0IyGkQ==", - "cpu": ["arm"], - "optional": true, - "os": ["linux"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.0.tgz", - "integrity": "sha512-RqJHDKe0WImeUrdR0kayTkRWgp4vD/MS7g0r6Xuf8+ellOFH7JAAJffDW3ayuVZeMYOa7RvgNFcOoWnrTUl9Nw==", - "cpu": ["arm64"], - "optional": true, - "os": ["linux"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.0.tgz", - "integrity": "sha512-nvNWoUieMjvDjpYJ/4SQe9lQs2xMj6ZRs8N+bmTrVu9leY2Fg3WD6W9p/1uU9hGO8u+OdF13wc4iRShu/WYIHg==", - "cpu": ["arm64"], - "optional": true, - "os": ["linux"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.0.tgz", - "integrity": "sha512-4ajhIuVU9PeQCMMhdDgZTLrHmjbOUFuIyg6J19hZqwEwDTSqQyrSLkbJs2Nd7IRiM6Ul/XyrtEFCpk4k+xD2+w==", - "cpu": ["x64"], - "optional": true, - "os": ["linux"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.0.tgz", - "integrity": "sha512-U092RBYbaGxoMAwpauePJEu2PuZSEoUCGJBvsptQr2/2XIMwAJDYM4c/M5NfYEsBr+yjvsYNsOpYfeQ88D82Yg==", - "cpu": ["x64"], - "optional": true, - "os": ["linux"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.0.tgz", - "integrity": "sha512-pzSzaxjDEJe67bUok9Nxf9rykbJfHXW0owICFsPBsqHyc+cr8vpF7g9e2APTCddtVhvjkga9ILoZJ9NxWS7Yiw==", - "cpu": ["arm64"], - "optional": true, - "os": ["win32"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.0.tgz", - "integrity": "sha512-MQGUpMbYhQmTZ06a9e0hPQJnxFMwETo2WtyAotY3GEzbNCQVbCGhsvqEKcl+ZEHgShlHXUWvSffq1ZscY6gK7A==", - "cpu": ["ia32"], - "optional": true, - "os": ["win32"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.0.tgz", - "integrity": "sha512-C/nw6OgQpEULWqs+wgMHXGvlJLguPRFFGqR2TAqWBerQ8J+Sg3z1ZTqwelkSi4FoqStGuZ2UdFHIDN1ySmR1xA==", - "cpu": ["x64"], - "optional": true, - "os": ["win32"], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", - "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" - }, - "node_modules/@swc/helpers": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz", - "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "dev": true - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.0.17", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz", - "integrity": "sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz", - "integrity": "sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==", - "dev": true, - "dependencies": { - "@types/react": "^17" - } - }, - "node_modules/@types/react-dom/node_modules/@types/react": { - "version": "17.0.50", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz", - "integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.39.0.tgz", - "integrity": "sha512-PhxLjrZnHShe431sBAGHaNe6BDdxAASDySgsBCGxcBecVCi8NQWxQZMcizNA4g0pN51bBAn/FUfkWG3SDVcGlA==", - "dependencies": { - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/typescript-estree": "5.39.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.39.0.tgz", - "integrity": "sha512-/I13vAqmG3dyqMVSZPjsbuNQlYS082Y7OMkwhCfLXYsmlI0ca4nkL7wJ/4gjX70LD4P8Hnw1JywUVVAwepURBw==", - "dependencies": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.39.0.tgz", - "integrity": "sha512-gQMZrnfEBFXK38hYqt8Lkwt8f4U6yq+2H5VDSgP/qiTzC8Nw8JO3OuSUOQ2qW37S/dlwdkHDntkZM6SQhKyPhw==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.39.0.tgz", - "integrity": "sha512-qLFQP0f398sdnogJoLtd43pUgB18Q50QSA+BTE5h3sUxySzbWDpTSdgt4UyxNSozY/oDK2ta6HVAzvGgq8JYnA==", - "dependencies": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.39.0.tgz", - "integrity": "sha512-yyE3RPwOG+XJBLrhvsxAidUgybJVQ/hG8BhiJo0k8JSAYfk/CshVcxf0HwP4Jt7WZZ6vLmxdo1p6EyN3tzFTkg==", - "dependencies": { - "@typescript-eslint/types": "5.39.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dependencies": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/array-includes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", - "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", - "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/axe-core": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", - "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001414", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz", - "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/core-js-pure": { - "version": "3.25.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.5.tgz", - "integrity": "sha512-oml3M22pHM+igfWHDfdLVq2ShWmjM2V4L+dQEBs0DWVIqEm9WHCwGAlZ6BmyBQGy5sFrJmcx+856D9lVKyGWYg==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", - "dev": true - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/docs": { - "resolved": "apps/docs", - "link": true - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.270", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz", - "integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/es-abstract": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", - "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.6", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-custom": { - "resolved": "packages/eslint-config-custom", - "link": true - }, - "node_modules/eslint-config-next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-12.3.1.tgz", - "integrity": "sha512-EN/xwKPU6jz1G0Qi6Bd/BqMnHLyRAL0VsaQaWA7F3KkjAgZHi4f1uL1JKGWNxdQpHTW/sdGONBd0bzxUka/DJg==", - "dependencies": { - "@next/eslint-plugin-next": "12.3.1", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.21.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-config-turbo": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-0.0.4.tgz", - "integrity": "sha512-HErPS/wfWkSdV9Yd2dDkhZt3W2B78Ih/aWPFfaHmCMjzPalh+5KxRRGTf8MOBQLCebcWJX0lP1Zvc1rZIHlXGg==", - "dependencies": { - "eslint-plugin-turbo": "0.0.4" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", - "dependencies": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz", - "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==", - "dependencies": { - "debug": "^4.3.4", - "glob": "^7.2.0", - "is-glob": "^4.0.3", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", - "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz", - "integrity": "sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==", - "dependencies": { - "@babel/runtime": "^7.18.9", - "aria-query": "^4.2.2", - "array-includes": "^3.1.5", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.4.3", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.2", - "language-tags": "^1.0.5", - "minimatch": "^3.1.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.31.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz", - "integrity": "sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==", - "dependencies": { - "array-includes": "^3.1.5", - "array.prototype.flatmap": "^1.3.0", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.1", - "object.values": "^1.1.5", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-turbo": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-0.0.4.tgz", - "integrity": "sha512-dfmYE/iPvoJInQq+5E/0mj140y/rYwKtzZkn3uVK8+nvwC5zmWKQ6ehMWrL4bYBkGzSgpOndZM+jOXhPQ2m8Cg==", - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/next": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/next/-/next-12.3.0.tgz", - "integrity": "sha512-GpzI6me9V1+XYtfK0Ae9WD0mKqHyzQlGq1xH1rzNIYMASo4Tkl4rTe9jSqtBpXFhOS33KohXs9ZY38Akkhdciw==", - "dependencies": { - "@next/env": "12.3.0", - "@swc/helpers": "0.4.11", - "caniuse-lite": "^1.0.30001332", - "postcss": "8.4.14", - "styled-jsx": "5.0.6", - "use-sync-external-store": "1.2.0" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=12.22.0" - }, - "optionalDependencies": { - "@next/swc-android-arm-eabi": "12.3.0", - "@next/swc-android-arm64": "12.3.0", - "@next/swc-darwin-arm64": "12.3.0", - "@next/swc-darwin-x64": "12.3.0", - "@next/swc-freebsd-x64": "12.3.0", - "@next/swc-linux-arm-gnueabihf": "12.3.0", - "@next/swc-linux-arm64-gnu": "12.3.0", - "@next/swc-linux-arm64-musl": "12.3.0", - "@next/swc-linux-x64-gnu": "12.3.0", - "@next/swc-linux-x64-musl": "12.3.0", - "@next/swc-win32-arm64-msvc": "12.3.0", - "@next/swc-win32-ia32-msvc": "12.3.0", - "@next/swc-win32-x64-msvc": "12.3.0" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^6.0.0 || ^7.0.0", - "react": "^17.0.2 || ^18.0.0-0", - "react-dom": "^17.0.2 || ^18.0.0-0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next-transpile-modules": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-9.0.0.tgz", - "integrity": "sha512-VCNFOazIAnXn1hvgYYSTYMnoWgKgwlYh4lm1pKbSfiB3kj5ZYLcKVhfh3jkPOg1cnd9DP+pte9yCUocdPEUBTQ==", - "dev": true, - "dependencies": { - "enhanced-resolve": "^5.7.0", - "escalade": "^3.1.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", - "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.hasown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", - "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", - "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "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/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", - "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.1", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.6.tgz", - "integrity": "sha512-xOeROtkK5MGMDimBQ3J6iPId8q0t/BDoG5XN6oKkZClVz9ISF/hihN8OCn2LggMU6N32aXnrXBdn3auSqNS9fA==", - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "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/table/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==" - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tsconfig": { - "resolved": "packages/tsconfig", - "link": true - }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/turbo": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.5.5.tgz", - "integrity": "sha512-PVQSDl0STC9WXIyHcYUWs9gXsf8JjQig/FuHfuB8N6+XlgCGB3mPbfMEE6zrChGz2hufH4/guKRX1XJuNL6XTA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "turbo": "bin/turbo" - }, - "optionalDependencies": { - "turbo-darwin-64": "1.5.5", - "turbo-darwin-arm64": "1.5.5", - "turbo-linux-64": "1.5.5", - "turbo-linux-arm64": "1.5.5", - "turbo-windows-64": "1.5.5", - "turbo-windows-arm64": "1.5.5" - } - }, - "node_modules/turbo-darwin-64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.5.5.tgz", - "integrity": "sha512-HvEn6P2B+NXDekq9LRpRgUjcT9/oygLTcK47U0qsAJZXRBSq/2hvD7lx4nAwgY/4W3rhYJeWtHTzbhoN6BXqGQ==", - "cpu": ["x64"], - "dev": true, - "optional": true, - "os": ["darwin"] - }, - "node_modules/turbo-darwin-arm64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.5.5.tgz", - "integrity": "sha512-Dmxr09IUy6M0nc7/xWod9galIO2DD500B75sJSkHeT+CCdJOWnlinux0ZPF8CSygNqymwYO8AO2l15/6yxcycg==", - "cpu": ["arm64"], - "dev": true, - "optional": true, - "os": ["darwin"] - }, - "node_modules/turbo-linux-64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.5.5.tgz", - "integrity": "sha512-wd07TZ4zXXWjzZE00FcFMLmkybQQK/NV9ff66vvAV0vdiuacSMBCNLrD6Mm4ncfrUPW/rwFW5kU/7hyuEqqtDw==", - "cpu": ["x64"], - "dev": true, - "optional": true, - "os": ["linux"] - }, - "node_modules/turbo-linux-arm64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.5.5.tgz", - "integrity": "sha512-q3q33tuo74R7gicnfvFbnZZvqmlq7Vakcvx0eshifnJw4PR+oMnTCb4w8ElVFx070zsb8DVTibq99y8NJH8T1Q==", - "cpu": ["arm64"], - "dev": true, - "optional": true, - "os": ["linux"] - }, - "node_modules/turbo-windows-64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.5.5.tgz", - "integrity": "sha512-lPp9kHonNFfqgovbaW+UAPO5cLmoAN+m3G3FzqcrRPnlzt97vXYsDhDd/4Zy3oAKoAcprtP4CGy0ddisqsKTVw==", - "cpu": ["x64"], - "dev": true, - "optional": true, - "os": ["win32"] - }, - "node_modules/turbo-windows-arm64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.5.5.tgz", - "integrity": "sha512-3AfGULKNZiZVrEzsIE+W79ZRW1+f5r4nM4wLlJ1PTBHyRxBZdD6KTH1tijGfy/uTlcV5acYnKHEkDc6Q9PAXGQ==", - "cpu": ["arm64"], - "dev": true, - "optional": true, - "os": ["win32"] - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/ui": { - "resolved": "packages/ui", - "link": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", - "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, - "node_modules/web": { - "resolved": "apps/web", - "link": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "packages/eslint-config-custom": { - "version": "0.0.0", - "license": "MIT", - "dependencies": { - "eslint": "^7.23.0", - "eslint-config-next": "^12.0.8", - "eslint-config-prettier": "^8.3.0", - "eslint-config-turbo": "latest", - "eslint-plugin-react": "7.31.8" - }, - "devDependencies": { - "typescript": "^4.7.4" - } - }, - "packages/tsconfig": { - "version": "0.0.0" - }, - "packages/ui": { - "version": "0.0.0", - "license": "MIT", - "devDependencies": { - "@types/react": "^17.0.37", - "@types/react-dom": "^17.0.11", - "eslint": "^7.32.0", - "eslint-config-custom": "*", - "react": "^18.2.0", - "tsconfig": "*", - "typescript": "^4.5.2" - } - }, - "packages/ui/node_modules/@types/react": { - "version": "17.0.50", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz", - "integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz", - "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==", - "dev": true - }, - "@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - } - }, - "@babel/generator": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz", - "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==", - "dev": true, - "requires": { - "@babel/types": "^7.19.3", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" - }, - "@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", - "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==", - "dev": true - }, - "@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz", - "integrity": "sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==", - "requires": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" - } - }, - "@babel/traverse": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz", - "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.3", - "@babel/types": "^7.19.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz", - "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.18.10", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "requires": { - "type-fest": "^0.20.2" - } - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@next/env": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.0.tgz", - "integrity": "sha512-PTJpjAFVbzBQ9xXpzMTroShvD5YDIIy46jQ7d4LrWpY+/5a8H90Tm8hE3Hvkc5RBRspVo7kvEOnqQms0A+2Q6w==" - }, - "@next/eslint-plugin-next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.1.tgz", - "integrity": "sha512-sw+lTf6r6P0j+g/n9y4qdWWI2syPqZx+uc0+B/fRENqfR3KpSid6MIKqc9gNwGhJASazEQ5b3w8h4cAET213jw==", - "requires": { - "glob": "7.1.7" - } - }, - "@next/swc-android-arm-eabi": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.0.tgz", - "integrity": "sha512-/PuirPnAKsYBw93w/7Q9hqy+KGOU9mjYprZ/faxMUJh/dc6v3rYLxkZKNG9nFPIW4QKNTCnhP40xF9hLnxO+xg==", - "optional": true - }, - "@next/swc-android-arm64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.0.tgz", - "integrity": "sha512-OaI+FhAM6P9B6Ybwbn0Zl8YwWido0lLwhDBi9WiYCh4RQmIXAyVIoIJPHo4fP05+mXaJ/k1trvDvuURvHOq2qw==", - "optional": true - }, - "@next/swc-darwin-arm64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.0.tgz", - "integrity": "sha512-9s4d3Mhii+WFce8o8Jok7WC3Bawkr9wEUU++SJRptjU1L5tsfYJMrSYCACHLhZujziNDLyExe4Hwwsccps1sfg==", - "optional": true - }, - "@next/swc-darwin-x64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.0.tgz", - "integrity": "sha512-2scC4MqUTwGwok+wpVxP+zWp7WcCAVOtutki2E1n99rBOTnUOX6qXkgxSy083yBN6GqwuC/dzHeN7hIKjavfRA==", - "optional": true - }, - "@next/swc-freebsd-x64": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.0.tgz", - "integrity": "sha512-xAlruUREij/bFa+qsE1tmsP28t7vz02N4ZDHt2lh3uJUniE0Ne9idyIDLc1Ed0IF2RjfgOp4ZVunuS3OM0sngw==", - "optional": true - }, - "@next/swc-linux-arm-gnueabihf": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.0.tgz", - "integrity": "sha512-jin2S4VT/cugc2dSZEUIabhYDJNgrUh7fufbdsaAezgcQzqfdfJqfxl4E9GuafzB4cbRPTaqA0V5uqbp0IyGkQ==", - "optional": true - }, - "@next/swc-linux-arm64-gnu": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.0.tgz", - "integrity": "sha512-RqJHDKe0WImeUrdR0kayTkRWgp4vD/MS7g0r6Xuf8+ellOFH7JAAJffDW3ayuVZeMYOa7RvgNFcOoWnrTUl9Nw==", - "optional": true - }, - "@next/swc-linux-arm64-musl": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.0.tgz", - "integrity": "sha512-nvNWoUieMjvDjpYJ/4SQe9lQs2xMj6ZRs8N+bmTrVu9leY2Fg3WD6W9p/1uU9hGO8u+OdF13wc4iRShu/WYIHg==", - "optional": true - }, - "@next/swc-linux-x64-gnu": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.0.tgz", - "integrity": "sha512-4ajhIuVU9PeQCMMhdDgZTLrHmjbOUFuIyg6J19hZqwEwDTSqQyrSLkbJs2Nd7IRiM6Ul/XyrtEFCpk4k+xD2+w==", - "optional": true - }, - "@next/swc-linux-x64-musl": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.0.tgz", - "integrity": "sha512-U092RBYbaGxoMAwpauePJEu2PuZSEoUCGJBvsptQr2/2XIMwAJDYM4c/M5NfYEsBr+yjvsYNsOpYfeQ88D82Yg==", - "optional": true - }, - "@next/swc-win32-arm64-msvc": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.0.tgz", - "integrity": "sha512-pzSzaxjDEJe67bUok9Nxf9rykbJfHXW0owICFsPBsqHyc+cr8vpF7g9e2APTCddtVhvjkga9ILoZJ9NxWS7Yiw==", - "optional": true - }, - "@next/swc-win32-ia32-msvc": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.0.tgz", - "integrity": "sha512-MQGUpMbYhQmTZ06a9e0hPQJnxFMwETo2WtyAotY3GEzbNCQVbCGhsvqEKcl+ZEHgShlHXUWvSffq1ZscY6gK7A==", - "optional": true - }, - "@next/swc-win32-x64-msvc": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.0.tgz", - "integrity": "sha512-C/nw6OgQpEULWqs+wgMHXGvlJLguPRFFGqR2TAqWBerQ8J+Sg3z1ZTqwelkSi4FoqStGuZ2UdFHIDN1ySmR1xA==", - "optional": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@rushstack/eslint-patch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", - "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" - }, - "@swc/helpers": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz", - "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==", - "requires": { - "tslib": "^2.4.0" - } - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "dev": true - }, - "@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true - }, - "@types/react": { - "version": "18.0.17", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz", - "integrity": "sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "@types/react-dom": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz", - "integrity": "sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==", - "dev": true, - "requires": { - "@types/react": "^17" - }, - "dependencies": { - "@types/react": { - "version": "17.0.50", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz", - "integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - } - } - }, - "@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true - }, - "@typescript-eslint/parser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.39.0.tgz", - "integrity": "sha512-PhxLjrZnHShe431sBAGHaNe6BDdxAASDySgsBCGxcBecVCi8NQWxQZMcizNA4g0pN51bBAn/FUfkWG3SDVcGlA==", - "requires": { - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/typescript-estree": "5.39.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.39.0.tgz", - "integrity": "sha512-/I13vAqmG3dyqMVSZPjsbuNQlYS082Y7OMkwhCfLXYsmlI0ca4nkL7wJ/4gjX70LD4P8Hnw1JywUVVAwepURBw==", - "requires": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0" - } - }, - "@typescript-eslint/types": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.39.0.tgz", - "integrity": "sha512-gQMZrnfEBFXK38hYqt8Lkwt8f4U6yq+2H5VDSgP/qiTzC8Nw8JO3OuSUOQ2qW37S/dlwdkHDntkZM6SQhKyPhw==" - }, - "@typescript-eslint/typescript-estree": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.39.0.tgz", - "integrity": "sha512-qLFQP0f398sdnogJoLtd43pUgB18Q50QSA+BTE5h3sUxySzbWDpTSdgt4UyxNSozY/oDK2ta6HVAzvGgq8JYnA==", - "requires": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.39.0.tgz", - "integrity": "sha512-yyE3RPwOG+XJBLrhvsxAidUgybJVQ/hG8BhiJo0k8JSAYfk/CshVcxf0HwP4Jt7WZZ6vLmxdo1p6EyN3tzFTkg==", - "requires": { - "@typescript-eslint/types": "5.39.0", - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==" - } - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==" - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, - "array-includes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", - "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, - "array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", - "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - } - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" - }, - "axe-core": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", - "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==" - }, - "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, - "caniuse-lite": { - "version": "1.0.30001414", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz", - "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "core-js-pure": { - "version": "3.25.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.5.tgz", - "integrity": "sha512-oml3M22pHM+igfWHDfdLVq2ShWmjM2V4L+dQEBs0DWVIqEm9WHCwGAlZ6BmyBQGy5sFrJmcx+856D9lVKyGWYg==" - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", - "dev": true - }, - "damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "requires": { - "path-type": "^4.0.0" - } - }, - "docs": { - "version": "file:apps/docs", - "requires": { - "@babel/core": "^7.0.0", - "@types/node": "^17.0.12", - "@types/react": "18.0.17", - "eslint": "7.32.0", - "eslint-config-custom": "*", - "lodash": "^3.0.0", - "next": "12.3.0", - "next-transpile-modules": "9.0.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "tsconfig": "*", - "typescript": "^4.5.3", - "ui": "*" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "requires": { - "esutils": "^2.0.2" - } - }, - "electron-to-chromium": { - "version": "1.4.270", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz", - "integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "es-abstract": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", - "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.6", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - } - }, - "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "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==" - }, - "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "eslint-config-custom": { - "version": "file:packages/eslint-config-custom", - "requires": { - "eslint": "^7.23.0", - "eslint-config-next": "^12.0.8", - "eslint-config-prettier": "^8.3.0", - "eslint-config-turbo": "latest", - "eslint-plugin-react": "7.31.8", - "typescript": "^4.7.4" - } - }, - "eslint-config-next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-12.3.1.tgz", - "integrity": "sha512-EN/xwKPU6jz1G0Qi6Bd/BqMnHLyRAL0VsaQaWA7F3KkjAgZHi4f1uL1JKGWNxdQpHTW/sdGONBd0bzxUka/DJg==", - "requires": { - "@next/eslint-plugin-next": "12.3.1", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.21.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0" - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "requires": {} - }, - "eslint-config-turbo": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-0.0.4.tgz", - "integrity": "sha512-HErPS/wfWkSdV9Yd2dDkhZt3W2B78Ih/aWPFfaHmCMjzPalh+5KxRRGTf8MOBQLCebcWJX0lP1Zvc1rZIHlXGg==", - "requires": { - "eslint-plugin-turbo": "0.0.4" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", - "requires": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-import-resolver-typescript": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz", - "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==", - "requires": { - "debug": "^4.3.4", - "glob": "^7.2.0", - "is-glob": "^4.0.3", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "requires": { - "esutils": "^2.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz", - "integrity": "sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==", - "requires": { - "@babel/runtime": "^7.18.9", - "aria-query": "^4.2.2", - "array-includes": "^3.1.5", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.4.3", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.2", - "language-tags": "^1.0.5", - "minimatch": "^3.1.2", - "semver": "^6.3.0" - } - }, - "eslint-plugin-react": { - "version": "7.31.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz", - "integrity": "sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==", - "requires": { - "array-includes": "^3.1.5", - "array.prototype.flatmap": "^1.3.0", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.1", - "object.values": "^1.1.5", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.7" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "requires": { - "esutils": "^2.0.2" - } - }, - "resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - } - } - }, - "eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "requires": {} - }, - "eslint-plugin-turbo": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-0.0.4.tgz", - "integrity": "sha512-dfmYE/iPvoJInQq+5E/0mj140y/rYwKtzZkn3uVK8+nvwC5zmWKQ6ehMWrL4bYBkGzSgpOndZM+jOXhPQ2m8Cg==", - "requires": {} - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - } - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" - } - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "dependencies": { - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" - } - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" - }, - "is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true - }, - "jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "requires": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - } - }, - "language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==" - }, - "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==" - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "next": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/next/-/next-12.3.0.tgz", - "integrity": "sha512-GpzI6me9V1+XYtfK0Ae9WD0mKqHyzQlGq1xH1rzNIYMASo4Tkl4rTe9jSqtBpXFhOS33KohXs9ZY38Akkhdciw==", - "requires": { - "@next/env": "12.3.0", - "@next/swc-android-arm-eabi": "12.3.0", - "@next/swc-android-arm64": "12.3.0", - "@next/swc-darwin-arm64": "12.3.0", - "@next/swc-darwin-x64": "12.3.0", - "@next/swc-freebsd-x64": "12.3.0", - "@next/swc-linux-arm-gnueabihf": "12.3.0", - "@next/swc-linux-arm64-gnu": "12.3.0", - "@next/swc-linux-arm64-musl": "12.3.0", - "@next/swc-linux-x64-gnu": "12.3.0", - "@next/swc-linux-x64-musl": "12.3.0", - "@next/swc-win32-arm64-msvc": "12.3.0", - "@next/swc-win32-ia32-msvc": "12.3.0", - "@next/swc-win32-x64-msvc": "12.3.0", - "@swc/helpers": "0.4.11", - "caniuse-lite": "^1.0.30001332", - "postcss": "8.4.14", - "styled-jsx": "5.0.6", - "use-sync-external-store": "1.2.0" - } - }, - "next-transpile-modules": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-9.0.0.tgz", - "integrity": "sha512-VCNFOazIAnXn1hvgYYSTYMnoWgKgwlYh4lm1pKbSfiB3kj5ZYLcKVhfh3jkPOg1cnd9DP+pte9yCUocdPEUBTQ==", - "dev": true, - "requires": { - "enhanced-resolve": "^5.7.0", - "escalade": "^3.1.1" - } - }, - "node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "object.fromentries": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", - "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "object.hasown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", - "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", - "requires": { - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "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==", - "requires": { - "callsites": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" - }, - "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "requires": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" - }, - "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==" - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "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==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - } - } - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "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==" - } - } - }, - "string.prototype.matchall": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", - "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.1", - "side-channel": "^1.0.4" - } - }, - "string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - }, - "styled-jsx": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.6.tgz", - "integrity": "sha512-xOeROtkK5MGMDimBQ3J6iPId8q0t/BDoG5XN6oKkZClVz9ISF/hihN8OCn2LggMU6N32aXnrXBdn3auSqNS9fA==", - "requires": {} - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "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==" - } - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "tsconfig": { - "version": "file:packages/tsconfig" - }, - "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "turbo": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.5.5.tgz", - "integrity": "sha512-PVQSDl0STC9WXIyHcYUWs9gXsf8JjQig/FuHfuB8N6+XlgCGB3mPbfMEE6zrChGz2hufH4/guKRX1XJuNL6XTA==", - "dev": true, - "requires": { - "turbo-darwin-64": "1.5.5", - "turbo-darwin-arm64": "1.5.5", - "turbo-linux-64": "1.5.5", - "turbo-linux-arm64": "1.5.5", - "turbo-windows-64": "1.5.5", - "turbo-windows-arm64": "1.5.5" - } - }, - "turbo-darwin-64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.5.5.tgz", - "integrity": "sha512-HvEn6P2B+NXDekq9LRpRgUjcT9/oygLTcK47U0qsAJZXRBSq/2hvD7lx4nAwgY/4W3rhYJeWtHTzbhoN6BXqGQ==", - "dev": true, - "optional": true - }, - "turbo-darwin-arm64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.5.5.tgz", - "integrity": "sha512-Dmxr09IUy6M0nc7/xWod9galIO2DD500B75sJSkHeT+CCdJOWnlinux0ZPF8CSygNqymwYO8AO2l15/6yxcycg==", - "dev": true, - "optional": true - }, - "turbo-linux-64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.5.5.tgz", - "integrity": "sha512-wd07TZ4zXXWjzZE00FcFMLmkybQQK/NV9ff66vvAV0vdiuacSMBCNLrD6Mm4ncfrUPW/rwFW5kU/7hyuEqqtDw==", - "dev": true, - "optional": true - }, - "turbo-linux-arm64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.5.5.tgz", - "integrity": "sha512-q3q33tuo74R7gicnfvFbnZZvqmlq7Vakcvx0eshifnJw4PR+oMnTCb4w8ElVFx070zsb8DVTibq99y8NJH8T1Q==", - "dev": true, - "optional": true - }, - "turbo-windows-64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.5.5.tgz", - "integrity": "sha512-lPp9kHonNFfqgovbaW+UAPO5cLmoAN+m3G3FzqcrRPnlzt97vXYsDhDd/4Zy3oAKoAcprtP4CGy0ddisqsKTVw==", - "dev": true, - "optional": true - }, - "turbo-windows-arm64": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.5.5.tgz", - "integrity": "sha512-3AfGULKNZiZVrEzsIE+W79ZRW1+f5r4nM4wLlJ1PTBHyRxBZdD6KTH1tijGfy/uTlcV5acYnKHEkDc6Q9PAXGQ==", - "dev": true, - "optional": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" - }, - "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==" - }, - "ui": { - "version": "file:packages/ui", - "requires": { - "@types/react": "^17.0.37", - "@types/react-dom": "^17.0.11", - "eslint": "^7.32.0", - "eslint-config-custom": "*", - "react": "^18.2.0", - "tsconfig": "*", - "typescript": "^4.5.2" - }, - "dependencies": { - "@types/react": { - "version": "17.0.50", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz", - "integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - } - } - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "update-browserslist-db": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", - "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "requires": {} - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, - "web": { - "version": "file:apps/web", - "requires": { - "@babel/core": "^7.0.0", - "@types/node": "^17.0.12", - "@types/react": "18.0.17", - "eslint": "7.32.0", - "eslint-config-custom": "*", - "lodash": "^4.17.21", - "next": "12.3.0", - "next-transpile-modules": "9.0.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "tsconfig": "*", - "typescript": "^4.5.3", - "ui": "*" - }, - "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - } - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } -} diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-absolute-v6.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-absolute-v6.yaml deleted file mode 100644 index dc5d0e626014a..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-absolute-v6.yaml +++ /dev/null @@ -1,18 +0,0 @@ -lockfileVersion: "6.0" -importers: - packages/a: - dependencies: - "@scope/parent": - specifier: ^1.0.0 - version: 1.0.0 - -packages: - /@scope/parent@1.0.0: - resolution: { integrity: junk } - dependencies: - child: /@scope/child@1.0.0 - dev: false - - /@scope/child@1.0.0: - resolution: { integrity: junk } - dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-absolute.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-absolute.yaml deleted file mode 100644 index d39f802da9e7b..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-absolute.yaml +++ /dev/null @@ -1,38 +0,0 @@ -lockfileVersion: 5.4 -importers: - packages/a: - specifiers: - another: ^1.0.0 - "@scope/parent": ^1.0.0 - special: npm:Special@1.2.3 - dependencies: - another: 1.0.0 - "@scope/parent": 1.0.0 - special: /Special/1.2.3 - -packages: - /@scope/parent/1.0.0: - resolution: { integrity: junk } - dependencies: - child: /@scope/child/1.0.0 - dev: false - - /@scope/child/1.0.0: - resolution: { integrity: junk } - dev: false - - /another/1.0.0: - resolution: { integrity: junk } - dev: false - dependencies: - foo: 1.0.0 - - /foo/1.0.0: - resolution: { integrity: junk } - dev: false - dependencies: - Special: 1.2.3 - - /Special/1.2.3: - resolution: { integrity: junk } - dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-override.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-override.yaml deleted file mode 100644 index 21021920f574e..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-override.yaml +++ /dev/null @@ -1,24 +0,0 @@ -lockfileVersion: 5.4 - -overrides: - "@nomiclabs/hardhat-ethers": npm:hardhat-deploy-ethers@^0.3.0-beta.13 - -importers: - config/hardhat: - specifiers: - "@nomiclabs/hardhat-ethers": npm:hardhat-deploy-ethers@^0.3.0-beta.13 - dependencies: - "@nomiclabs/hardhat-ethers": /hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy - -packages: - /hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy: - resolution: - { - integrity: sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw==, - } - peerDependencies: - ethers: ^5.0.0 - hardhat: ^2.0.0 - dependencies: - ethers: 5.7.2 - hardhat: 2.12.4_typescript@4.9.4 diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-patch-v6.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-patch-v6.yaml deleted file mode 100644 index b620472460d97..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-patch-v6.yaml +++ /dev/null @@ -1,40 +0,0 @@ -lockfileVersion: "6.0" - -patchedDependencies: - lodash@4.17.21: - hash: lgum37zgng4nfkynzh3cs7wdeq - path: patches/lodash@4.17.21.patch - "@babel/helper-string-parser@7.19.4": - hash: wjhgmpzh47qmycrzgpeyoyh3ce - path: patches/@babel__helper-string-parser@7.19.4.patch - -importers: - .: {} - - packages/a: - dependencies: - lodash: - specifier: ^4.17.21 - version: 4.17.21(patch_hash=lgum37zgng4nfkynzh3cs7wdeq) - - packages/b: - dependencies: - "@babel/helper-string-parser": - specifier: ^7.19.4 - version: 7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0) - -packages: - /@babel/helper-string-parser@7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0): - resolution: - { - integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==, - } - engines: { node: ">=6.9.0" } - dev: false - - /lodash@4.17.21(patch_hash=lgum37zgng4nfkynzh3cs7wdeq): - resolution: - { - integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, - } - dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-patch.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-patch.yaml deleted file mode 100644 index ea84d72043b7b..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-patch.yaml +++ /dev/null @@ -1,63 +0,0 @@ -lockfileVersion: 5.4 - -patchedDependencies: - is-odd@3.0.1: - hash: nrrwwz7lemethtlvvm75r5bmhq - path: patches/is-odd@3.0.1.patch - "@babel/core@7.20.12": - hash: 3hyn7hbvzkemudbydlwjmrb65y - path: patches/@babel__core@7.20.12.patch - moleculer@0.14.28: - hash: 5pk7ojv7qbqha75ozglk4y4f74 - path: patches/moleculer@0.14.28.patch - -importers: - .: - specifiers: {} - - packages/dependency: - specifiers: - is-odd: ^3.0.1 - "@babel/core": ^7.20.12 - dependencies: - is-odd: 3.0.1_nrrwwz7lemethtlvvm75r5bmhq - "@babel/core": 7.20.12_3hyn7hbvzkemudbydlwjmrb65y - -packages: - /@babel/core/7.20.12_3hyn7hbvzkemudbydlwjmrb65y: - resolution: - { - integrity: sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==, - } - engines: { node: ">=6.9.0" } - dev: false - - /is-number/6.0.0: - resolution: - { - integrity: sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==, - } - engines: { node: ">=0.10.0" } - dev: false - - /is-odd/3.0.1_nrrwwz7lemethtlvvm75r5bmhq: - resolution: - { - integrity: sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==, - } - engines: { node: ">=4" } - dependencies: - is-number: 6.0.0 - dev: false - patched: true - - /moleculer/0.14.28_5pk7ojv7qbqha75ozglk4y4f74_kumip57h7zlinbhp4gz3jrbqry: - resolution: - { - integrity: sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==, - } - engines: { node: ">=4" } - dependencies: - is-number: 6.0.0 - dev: false - patched: true diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-peer-v6.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-peer-v6.yaml deleted file mode 100644 index feddd0769b09f..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-peer-v6.yaml +++ /dev/null @@ -1,67 +0,0 @@ -lockfileVersion: "6.0" - -importers: - .: {} - - apps/web: - dependencies: - next: - specifier: 13.0.4 - version: 13.0.4(react-dom@18.2.0)(react@18.2.0) - react: - specifier: 18.2.0 - version: 18.2.0 - react-dom: - specifier: 18.2.0 - version: 18.2.0(react@18.2.0) - - packages/next-config: {} - - packages/package-for-ci: {} - - packages/tsconfig: {} - -packages: - /next@13.0.4: - resolution: - { - integrity: sha512-4P0MvbjPCI1E/UPL1GrTXtYlgFnbBbY3JQ+AMY8jYE2SwyvCWctEJySoRjveznAHjrl6TIjuAJeB8u1c2StYUQ==, - } - engines: { node: ">=14.6.0" } - hasBin: true - peerDependencies: - fibers: ">= 3.1.0" - node-sass: ^6.0.0 || ^7.0.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - dev: true - - /next@13.0.4(react-dom@18.2.0)(react@18.2.0): - resolution: - { - integrity: sha512-4P0MvbjPCI1E/UPL1GrTXtYlgFnbBbY3JQ+AMY8jYE2SwyvCWctEJySoRjveznAHjrl6TIjuAJeB8u1c2StYUQ==, - } - engines: { node: ">=14.6.0" } - hasBin: true - peerDependencies: - fibers: ">= 3.1.0" - node-sass: ^6.0.0 || ^7.0.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-top-level-dupe.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-top-level-dupe.yaml deleted file mode 100644 index 6837f223da853..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-top-level-dupe.yaml +++ /dev/null @@ -1,36 +0,0 @@ -lockfileVersion: 5.4 - -importers: - packages/a: - specifiers: - ci-info: ^2.0.0 - is-ci: ^3.0.1 - dependencies: - ci-info: 2.0.0 - is-ci: 3.0.1 - -packages: - /ci-info/2.0.0: - resolution: - { - integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==, - } - dev: false - - /ci-info/3.7.1: - resolution: - { - integrity: sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==, - } - engines: { node: ">=8" } - dev: false - - /is-ci/3.0.1: - resolution: - { - integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==, - } - hasBin: true - dependencies: - ci-info: 3.7.1 - dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-v6.1.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-v6.1.yaml deleted file mode 100644 index f175819c7cab0..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-v6.1.yaml +++ /dev/null @@ -1,22 +0,0 @@ -lockfileVersion: "6.1" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: {} - - packages/a: - dependencies: - c: - specifier: workspace:* - version: link:../c - - packages/b: - dependencies: - c: - specifier: workspace:* - version: link:../c - - packages/c: {} diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-v7-patch.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-v7-patch.yaml deleted file mode 100644 index 9507168599a1b..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-v7-patch.yaml +++ /dev/null @@ -1,121 +0,0 @@ -lockfileVersion: "7.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -patchedDependencies: - ajv-keywords@5.1.0: - hash: 5d3ekbiux3hfmrauqwpwb6chsq - path: patches/ajv-keywords@5.1.0.patch - -importers: - .: {} - - packages/a: - dependencies: - ajv: - specifier: ^8.12.0 - version: 8.12.0 - ajv-keywords: - specifier: ^5.1.0 - version: 5.1.0(patch_hash=5d3ekbiux3hfmrauqwpwb6chsq)(ajv@8.12.0) - - packages/b: - dependencies: - ajv: - specifier: 8.11.0 - version: 8.11.0 - ajv-keywords: - specifier: ^5.1.0 - version: 5.1.0(patch_hash=5d3ekbiux3hfmrauqwpwb6chsq)(ajv@8.11.0) - -packages: - ajv-keywords@5.1.0: - resolution: - { - integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==, - } - peerDependencies: - ajv: ^8.8.2 - - ajv@8.11.0: - resolution: - { - integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==, - } - - ajv@8.12.0: - resolution: - { - integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==, - } - - fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } - - json-schema-traverse@1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } - - punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, - } - engines: { node: ">=6" } - - require-from-string@2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: ">=0.10.0" } - - uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } - -snapshots: - ajv-keywords@5.1.0(patch_hash=5d3ekbiux3hfmrauqwpwb6chsq)(ajv@8.11.0): - dependencies: - ajv: 8.11.0 - fast-deep-equal: 3.1.3 - - ajv-keywords@5.1.0(patch_hash=5d3ekbiux3hfmrauqwpwb6chsq)(ajv@8.12.0): - dependencies: - ajv: 8.12.0 - fast-deep-equal: 3.1.3 - - ajv@8.11.0: - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - - ajv@8.12.0: - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - - fast-deep-equal@3.1.3: {} - - json-schema-traverse@1.0.0: {} - - punycode@2.3.1: {} - - require-from-string@2.0.2: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-v7-peer.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-v7-peer.yaml deleted file mode 100644 index 9cfd12f7a9c34..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-v7-peer.yaml +++ /dev/null @@ -1,116 +0,0 @@ -lockfileVersion: "7.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: {} - - packages/a: - dependencies: - ajv: - specifier: ^8.12.0 - version: 8.12.0 - ajv-keywords: - specifier: ^5.1.0 - version: 5.1.0(ajv@8.12.0) - - packages/b: - dependencies: - ajv: - specifier: 8.11.0 - version: 8.11.0 - ajv-keywords: - specifier: ^5.1.0 - version: 5.1.0(ajv@8.11.0) - -packages: - ajv-keywords@5.1.0: - resolution: - { - integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==, - } - peerDependencies: - ajv: ^8.8.2 - - ajv@8.11.0: - resolution: - { - integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==, - } - - ajv@8.12.0: - resolution: - { - integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==, - } - - fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } - - json-schema-traverse@1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } - - punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, - } - engines: { node: ">=6" } - - require-from-string@2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: ">=0.10.0" } - - uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } - -snapshots: - ajv-keywords@5.1.0(ajv@8.11.0): - dependencies: - ajv: 8.11.0 - fast-deep-equal: 3.1.3 - - ajv-keywords@5.1.0(ajv@8.12.0): - dependencies: - ajv: 8.12.0 - fast-deep-equal: 3.1.3 - - ajv@8.11.0: - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - - ajv@8.12.0: - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - - fast-deep-equal@3.1.3: {} - - json-schema-traverse@1.0.0: {} - - punycode@2.3.1: {} - - require-from-string@2.0.2: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-v7.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-v7.yaml deleted file mode 100644 index f06f1a046b00f..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-v7.yaml +++ /dev/null @@ -1,117 +0,0 @@ -lockfileVersion: "7.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: {} - - packages/a: - dependencies: - c: - specifier: workspace:* - version: link:../c - is-even: - specifier: ^1.0.0 - version: 1.0.0 - - packages/b: - dependencies: - c: - specifier: workspace:* - version: link:../c - is-negative: - specifier: github:kevva/is-negative#master - version: https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c - - packages/c: - dependencies: - is-odd: - specifier: ^3.0.1 - version: 3.0.1 - -packages: - is-buffer@1.1.6: - resolution: - { - integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==, - } - - is-even@1.0.0: - resolution: - { - integrity: sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==, - } - engines: { node: ">=0.10.0" } - - is-negative@https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c: - resolution: - { - tarball: https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c, - } - version: 2.1.0 - engines: { node: ">=0.10.0" } - - is-number@3.0.0: - resolution: - { - integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==, - } - engines: { node: ">=0.10.0" } - - is-number@6.0.0: - resolution: - { - integrity: sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==, - } - engines: { node: ">=0.10.0" } - - is-odd@0.1.2: - resolution: - { - integrity: sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==, - } - engines: { node: ">=0.10.0" } - - is-odd@3.0.1: - resolution: - { - integrity: sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==, - } - engines: { node: ">=4" } - - kind-of@3.2.2: - resolution: - { - integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==, - } - engines: { node: ">=0.10.0" } - -snapshots: - is-buffer@1.1.6: {} - - is-even@1.0.0: - dependencies: - is-odd: 0.1.2 - - is-number@3.0.0: - dependencies: - kind-of: 3.2.2 - - is-negative@https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c: - {} - - is-number@6.0.0: {} - - is-odd@0.1.2: - dependencies: - is-number: 3.0.0 - - is-odd@3.0.1: - dependencies: - is-number: 6.0.0 - - kind-of@3.2.2: - dependencies: - is-buffer: 1.1.6 diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-v9.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-v9.yaml deleted file mode 100644 index 862f8c8080e4b..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm-v9.yaml +++ /dev/null @@ -1,125 +0,0 @@ -lockfileVersion: "9.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: - devDependencies: - turbo: - specifier: canary - version: 1.13.3-canary.1 - - apps/apps-a: - dependencies: - pkg-a: - specifier: workspace:* - version: link:../../packages/pkg-a - tooling-config: - specifier: workspace:* - version: link:../../packages/tooling-config - - apps/apps-b: - dependencies: - tooling-config: - specifier: workspace:* - version: link:../../packages/tooling-config - - packages/pkg-a: - dependencies: - tooling-config: - specifier: workspace:* - version: link:../tooling-config - - packages/pkg-b: - dependencies: - tooling-config: - specifier: workspace:* - version: link:../tooling-config - - packages/tooling-config: {} - -packages: - turbo-darwin-64@1.13.3-canary.1: - resolution: - { - integrity: sha512-1xfKCf/d7mD7oGT1qBnD5pYsZfI43Wftlo/N0GTpBLDjKhfJifBvng9ns5grhs79wNiIdDxYYGt6pHOUzc+6YQ==, - } - cpu: [x64] - os: [darwin] - - turbo-darwin-arm64@1.13.3-canary.1: - resolution: - { - integrity: sha512-uNK9QnlDJBLuaR7l4/68AoKByQ+q+rT9OyvizzUV2KZ8r2u/Sv+f3GiV48qxtG1duYlWLlLnDGuEnUPKEq0WZg==, - } - cpu: [arm64] - os: [darwin] - - turbo-linux-64@1.13.3-canary.1: - resolution: - { - integrity: sha512-D/RRtqHch0I5q/Pod7mgLPGrvjcDpvBe95yp5hNy59+ZSyKHlkDrm/pQaA/+6mdjHEQB8eIL/18nrKx/B5qduA==, - } - cpu: [x64] - os: [linux] - - turbo-linux-arm64@1.13.3-canary.1: - resolution: - { - integrity: sha512-FXwgkadDZr6mPLN7lmlc0ESRZFfXDONEKTQbDV9h4n/7I0HOehMM0CrWZsptoekKEKFEqQDxZo5QXFDZON0cww==, - } - cpu: [arm64] - os: [linux] - - turbo-windows-64@1.13.3-canary.1: - resolution: - { - integrity: sha512-ce6TENLbCeFAWVrJtLMOjv7FkPCpfSNvczFpaolbOB9omPW3uO4hXMbpqk14hgsU8OsmMt61rLzI38L0miJuEw==, - } - cpu: [x64] - os: [win32] - - turbo-windows-arm64@1.13.3-canary.1: - resolution: - { - integrity: sha512-7sm8tZRqcmWo/D3Mb513/diVZuFC6rwz/ZaW8IGsEcLrUdqq6qSRlW6e7ZsfOMR7cO6geeGhuFsJg8ILOETTgw==, - } - cpu: [arm64] - os: [win32] - - turbo@1.13.3-canary.1: - resolution: - { - integrity: sha512-bxOFjIhBxwWiExjUyTV2KOP6P28M5TOHUaM6YKRR2oPtKoQpIGUmYP+DCxG+icjaLXviUJRHU4YxzEOaL9Bf6A==, - } - hasBin: true - -snapshots: - turbo-darwin-64@1.13.3-canary.1: - optional: true - - turbo-darwin-arm64@1.13.3-canary.1: - optional: true - - turbo-linux-64@1.13.3-canary.1: - optional: true - - turbo-linux-arm64@1.13.3-canary.1: - optional: true - - turbo-windows-64@1.13.3-canary.1: - optional: true - - turbo-windows-arm64@1.13.3-canary.1: - optional: true - - turbo@1.13.3-canary.1: - optionalDependencies: - turbo-darwin-64: 1.13.3-canary.1 - turbo-darwin-arm64: 1.13.3-canary.1 - turbo-linux-64: 1.13.3-canary.1 - turbo-linux-arm64: 1.13.3-canary.1 - turbo-windows-64: 1.13.3-canary.1 - turbo-windows-arm64: 1.13.3-canary.1 diff --git a/crates/turborepo-lockfiles/fixtures/pnpm6-workspace.yaml b/crates/turborepo-lockfiles/fixtures/pnpm6-workspace.yaml deleted file mode 100644 index daf92b79118b0..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm6-workspace.yaml +++ /dev/null @@ -1,1704 +0,0 @@ -lockfileVersion: 5.3 - -importers: - .: - specifiers: - "@pnpm/make-dedicated-lockfile": ^0.3.19 - devDependencies: - "@pnpm/make-dedicated-lockfile": 0.3.19 - - packages/a: - specifiers: - b: workspace:* - express: ^4.18.1 - dependencies: - b: link:../b - express: 4.18.1 - - packages/b: - specifiers: - c: workspace:* - lodash: ^4.17.21 - dependencies: - c: link:../c - lodash: 4.17.21 - - packages/c: - specifiers: - chalk: ^5.0.1 - dependencies: - chalk: 5.0.1 - -packages: - /@babel/code-frame/7.18.6: - resolution: - { - integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/highlight": 7.18.6 - dev: true - - /@babel/helper-validator-identifier/7.18.6: - resolution: - { - integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==, - } - engines: { node: ">=6.9.0" } - dev: true - - /@babel/highlight/7.18.6: - resolution: - { - integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/helper-validator-identifier": 7.18.6 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@pnpm/constants/6.1.0: - resolution: - { - integrity: sha512-L6AiU3OXv9kjKGTJN9j8n1TeJGDcLX9atQlZvAkthlvbXjvKc5SKNWESc/eXhr5nEfuMWhQhiKHDJCpYejmeCQ==, - } - engines: { node: ">=14.19" } - dev: true - - /@pnpm/crypto.base32-hash/1.0.1: - resolution: - { - integrity: sha512-pzAXNn6KxTA3kbcI3iEnYs4vtH51XEVqmK/1EiD18MaPKylhqy8UvMJK3zKG+jeP82cqQbozcTGm4yOQ8i3vNw==, - } - engines: { node: ">=14.6" } - dependencies: - rfc4648: 1.5.2 - dev: true - - /@pnpm/error/3.0.1: - resolution: - { - integrity: sha512-hMlbWbFcfcfolNfSjKjpeaZFow71kNg438LZ8rAd01swiVIYRUf/sRv8gGySru6AijYfz5UqslpIJRDbYBkgQA==, - } - engines: { node: ">=14.19" } - dependencies: - "@pnpm/constants": 6.1.0 - dev: true - - /@pnpm/exec/2.0.0: - resolution: - { - integrity: sha512-b5ALfWEOFQprWKntN7MF8XWCyslBk2c8u20GEDcDDQOs6c0HyHlWxX5lig8riQKdS000U6YyS4L4b32NOleXAQ==, - } - engines: { node: ">=10" } - dependencies: - "@pnpm/self-installer": 2.2.1 - command-exists: 1.2.9 - cross-spawn: 7.0.3 - dev: true - - /@pnpm/exportable-manifest/3.1.2: - resolution: - { - integrity: sha512-IvTBwt3n73pXsU6iS1Y4OipBg3GBN37I/mUR8t3q5N0c5TkVxj9xAsra5/m7mX4dsYCv9BPL6Rw+MuKSV5P1hA==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/error": 3.0.1 - "@pnpm/read-project-manifest": 3.0.9 - "@pnpm/types": 8.5.0 - ramda: /@pnpm/ramda/0.28.1 - dev: true - - /@pnpm/find-workspace-dir/4.0.2: - resolution: - { - integrity: sha512-gU7ycFSWuEGJh7RE/STa33Ch27geODTXIfc+ntiE1BietxfpJIAk34zz51kTUuCFthBkpHlO6yV7jgHD2Tuc3g==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/error": 3.0.1 - find-up: 5.0.0 - dev: true - - /@pnpm/git-utils/0.1.0: - resolution: - { - integrity: sha512-W3zsG9585cKL+FqgcT+IfTgZX5C+CbNkFjOnJN+qbysT1N30+BbvEByCcDMsTy7QDrAk6oS7WU1Rym3U2xlh2Q==, - } - engines: { node: ">=14.6" } - dependencies: - execa: /safe-execa/0.1.2 - dev: true - - /@pnpm/graceful-fs/2.0.0: - resolution: - { - integrity: sha512-ogUZCGf0/UILZt6d8PsO4gA4pXh7f0BumXeFkcCe4AQ65PXPKfAkHC0C30Lheh2EgFOpLZm3twDP1Eiww18gew==, - } - engines: { node: ">=14.19" } - dependencies: - graceful-fs: 4.2.10 - dev: true - - /@pnpm/lockfile-file/5.3.3_@pnpm+logger@4.0.0: - resolution: - { - integrity: sha512-IOvjeMRX+++osG9VsfSd7+hVa/sIzhqdrm/nFcL7AexFhC7wjXbWW3YMlN5Cw4v0fwm93fgRZlikIKJ7BmkBBA==, - } - engines: { node: ">=14.6" } - peerDependencies: - "@pnpm/logger": ^4.0.0 - dependencies: - "@pnpm/constants": 6.1.0 - "@pnpm/error": 3.0.1 - "@pnpm/git-utils": 0.1.0 - "@pnpm/lockfile-types": 4.3.1 - "@pnpm/logger": 4.0.0 - "@pnpm/merge-lockfile-changes": 3.0.9 - "@pnpm/types": 8.5.0 - "@zkochan/rimraf": 2.1.2 - comver-to-semver: 1.0.0 - js-yaml: /@zkochan/js-yaml/0.0.6 - normalize-path: 3.0.0 - ramda: /@pnpm/ramda/0.28.1 - semver: 7.3.7 - sort-keys: 4.2.0 - strip-bom: 4.0.0 - write-file-atomic: 3.0.3 - dev: true - - /@pnpm/lockfile-types/4.3.1: - resolution: - { - integrity: sha512-xoorF+CuuUvpjfi8Uw/xkf8LI9VDzs9W1gjSxkKS8UwK60zU5fu4agILJfVVGlHO1tnjJeGRuspBjp7UZ8ufMA==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/types": 8.5.0 - dev: true - - /@pnpm/logger/4.0.0: - resolution: - { - integrity: sha512-SIShw+k556e7S7tLZFVSIHjCdiVog1qWzcKW2RbLEHPItdisAFVNIe34kYd9fMSswTlSRLS/qRjw3ZblzWmJ9Q==, - } - engines: { node: ">=12.17" } - dependencies: - bole: 4.0.1 - ndjson: 2.0.0 - dev: true - - /@pnpm/make-dedicated-lockfile/0.3.19: - resolution: - { - integrity: sha512-VHllqMh5zviSHds2kOlWSiwmxos3LLGWCVIHpo+HX45D3TXx+oMOgE8k6WB0dSOTVIuGKduoCNTGeSW4p2bD2w==, - } - engines: { node: ">=14.6" } - hasBin: true - dependencies: - "@pnpm/error": 3.0.1 - "@pnpm/exec": 2.0.0 - "@pnpm/exportable-manifest": 3.1.2 - "@pnpm/find-workspace-dir": 4.0.2 - "@pnpm/lockfile-file": 5.3.3_@pnpm+logger@4.0.0 - "@pnpm/logger": 4.0.0 - "@pnpm/prune-lockfile": 4.0.14 - "@pnpm/read-project-manifest": 3.0.9 - "@pnpm/types": 8.5.0 - ramda: /@pnpm/ramda/0.28.1 - rename-overwrite: 4.0.2 - dev: true - - /@pnpm/merge-lockfile-changes/3.0.9: - resolution: - { - integrity: sha512-UOl3AYsi13R8bvQNJPNUml8sZYKBRns0xjAcPQomoX3WTU0dv+KzVyv86Iv86YlApP0aJj9MS8Vq++JOC10RKg==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/lockfile-types": 4.3.1 - comver-to-semver: 1.0.0 - ramda: /@pnpm/ramda/0.28.1 - semver: 7.3.7 - dev: true - - /@pnpm/prune-lockfile/4.0.14: - resolution: - { - integrity: sha512-lICCgm9j3e2Bu75zK4PA1FKjpu9pCcagRbZWruONBf44byyEkHcnTf8b8a9M1MvtoiArhmKOmyOVJ2OFyBBRyA==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/constants": 6.1.0 - "@pnpm/lockfile-types": 4.3.1 - "@pnpm/types": 8.5.0 - dependency-path: 9.2.4 - ramda: /@pnpm/ramda/0.28.1 - dev: true - - /@pnpm/ramda/0.28.1: - resolution: - { - integrity: sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==, - } - dev: true - - /@pnpm/read-project-manifest/3.0.9: - resolution: - { - integrity: sha512-27j40C48hA/tqsCiqk9ApJxp2g6WGrrj2RSs0NKhsSHynxAuA1tIvwatNISQbAiMjZiu1lfhzhq8m1QdblyNmA==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/error": 3.0.1 - "@pnpm/graceful-fs": 2.0.0 - "@pnpm/types": 8.5.0 - "@pnpm/write-project-manifest": 3.0.7 - detect-indent: 6.1.0 - fast-deep-equal: 3.1.3 - is-windows: 1.0.2 - json5: 2.2.1 - parse-json: 5.2.0 - read-yaml-file: 2.1.0 - sort-keys: 4.2.0 - strip-bom: 4.0.0 - dev: true - - /@pnpm/self-installer/2.2.1: - resolution: - { - integrity: sha512-aefLe96wAWghkx6q1PwbVS1Iz1iGE+HKwkTmtzWLFXeGhbknaIdG2voMwaBGIYGCSxm8sDKR1uLO4aRRAYuc+Q==, - } - engines: { node: ">=4" } - hasBin: true - dev: true - - /@pnpm/types/8.5.0: - resolution: - { - integrity: sha512-PSKnhkwgiZtp9dcWZR9mPz2W9UopmADr9o8FTqazo5kjUSh2xQmDUSJOJ/ZWcfNziO64Ix/VbcxKIZeplhog1Q==, - } - engines: { node: ">=14.6" } - dev: true - - /@pnpm/write-project-manifest/3.0.7: - resolution: - { - integrity: sha512-rMgIWR52asESg1D7Cp/vBi3dBsv18iUWPvvtYNynrcOjRdE3NsH5CAdfZP/XN6HJF6CSY8rS9W4YC5Q3JGtxiw==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/types": 8.5.0 - json5: 2.2.1 - write-file-atomic: 3.0.3 - write-yaml-file: 4.2.0 - dev: true - - /@zkochan/js-yaml/0.0.6: - resolution: - { - integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==, - } - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /@zkochan/rimraf/2.1.2: - resolution: - { - integrity: sha512-Lc2oK51J6aQWcLWTloobJun5ZF41BbTDdLvE+aMcexoVWFoFqvZmnZoyXR2IZk6NJEVoZW8tjgtvQLfTsmRs2Q==, - } - engines: { node: ">=12.10" } - dependencies: - rimraf: 3.0.2 - dev: true - - /@zkochan/which/2.0.3: - resolution: - { - integrity: sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==, - } - engines: { node: ">= 8" } - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /accepts/1.3.8: - resolution: - { - integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==, - } - engines: { node: ">= 0.6" } - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: false - - /ansi-styles/3.2.1: - resolution: - { - integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, - } - engines: { node: ">=4" } - dependencies: - color-convert: 1.9.3 - dev: true - - /argparse/2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, - } - dev: true - - /array-flatten/1.1.1: - resolution: - { - integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==, - } - dev: false - - /balanced-match/1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, - } - dev: true - - /body-parser/1.20.0: - resolution: - { - integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==, - } - engines: { node: ">= 0.8", npm: 1.2.8000 || >= 1.4.16 } - dependencies: - bytes: 3.1.2 - content-type: 1.0.4 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.10.3 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - dev: false - - /bole/4.0.1: - resolution: - { - integrity: sha512-42r0aSOJFJti2l6LasBHq2BuWJzohGs349olQnH/ETlJo87XnoWw7UT8pGE6UstjxzOKkwz7tjoFcmSr6L16vg==, - } - dependencies: - fast-safe-stringify: 2.1.1 - individual: 3.0.0 - dev: true - - /brace-expansion/1.1.11: - resolution: - { - integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==, - } - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /bytes/3.1.2: - resolution: - { - integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, - } - engines: { node: ">= 0.8" } - dev: false - - /call-bind/1.0.2: - resolution: - { - integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==, - } - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.1.2 - dev: false - - /chalk/2.4.2: - resolution: - { - integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==, - } - engines: { node: ">=4" } - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk/5.0.1: - resolution: - { - integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==, - } - engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } - dev: false - - /color-convert/1.9.3: - resolution: - { - integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, - } - dependencies: - color-name: 1.1.3 - dev: true - - /color-name/1.1.3: - resolution: - { - integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, - } - dev: true - - /command-exists/1.2.9: - resolution: - { - integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==, - } - dev: true - - /comver-to-semver/1.0.0: - resolution: - { - integrity: sha512-gcGtbRxjwROQOdXLUWH1fQAXqThUVRZ219aAwgtX3KfYw429/Zv6EIJRf5TBSzWdAGwePmqH7w70WTaX4MDqag==, - } - engines: { node: ">=12.17" } - dev: true - - /concat-map/0.0.1: - resolution: - { - integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, - } - dev: true - - /content-disposition/0.5.4: - resolution: - { - integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==, - } - engines: { node: ">= 0.6" } - dependencies: - safe-buffer: 5.2.1 - dev: false - - /content-type/1.0.4: - resolution: - { - integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==, - } - engines: { node: ">= 0.6" } - dev: false - - /cookie-signature/1.0.6: - resolution: - { - integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==, - } - dev: false - - /cookie/0.5.0: - resolution: - { - integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==, - } - engines: { node: ">= 0.6" } - dev: false - - /cross-spawn/7.0.3: - resolution: - { - integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==, - } - engines: { node: ">= 8" } - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /debug/2.6.9: - resolution: - { - integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, - } - dependencies: - ms: 2.0.0 - dev: false - - /depd/2.0.0: - resolution: - { - integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, - } - engines: { node: ">= 0.8" } - dev: false - - /dependency-path/9.2.4: - resolution: - { - integrity: sha512-bH29ZcKyo/i5nr4SgnVZGksuoZzroOWpHtKbq8fKdKgJDr0SdUIPu2EwjJkjzbw9SqRzWd912e0opHYJTkFf6w==, - } - engines: { node: ">=14.6" } - dependencies: - "@pnpm/crypto.base32-hash": 1.0.1 - "@pnpm/types": 8.5.0 - encode-registry: 3.0.0 - semver: 7.3.7 - dev: true - - /destroy/1.2.0: - resolution: - { - integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==, - } - engines: { node: ">= 0.8", npm: 1.2.8000 || >= 1.4.16 } - dev: false - - /detect-indent/6.1.0: - resolution: - { - integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==, - } - engines: { node: ">=8" } - dev: true - - /ee-first/1.1.1: - resolution: - { - integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, - } - dev: false - - /encode-registry/3.0.0: - resolution: - { - integrity: sha512-2fRYji8K6FwYuQ6EPBKR/J9mcqb7kIoNqt1vGvJr3NrvKfncRiNm00Oxo6gi/YJF8R5Sp2bNFSFdGKTG0rje1Q==, - } - engines: { node: ">=10" } - dependencies: - mem: 8.1.1 - dev: true - - /encodeurl/1.0.2: - resolution: - { - integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==, - } - engines: { node: ">= 0.8" } - dev: false - - /error-ex/1.3.2: - resolution: - { - integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==, - } - dependencies: - is-arrayish: 0.2.1 - dev: true - - /escape-html/1.0.3: - resolution: - { - integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, - } - dev: false - - /escape-string-regexp/1.0.5: - resolution: - { - integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, - } - engines: { node: ">=0.8.0" } - dev: true - - /etag/1.8.1: - resolution: - { - integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, - } - engines: { node: ">= 0.6" } - dev: false - - /execa/5.1.1: - resolution: - { - integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==, - } - engines: { node: ">=10" } - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /express/4.18.1: - resolution: - { - integrity: sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==, - } - engines: { node: ">= 0.10.0" } - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.0 - content-disposition: 0.5.4 - content-type: 1.0.4 - cookie: 0.5.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.10.3 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - dev: false - - /fast-deep-equal/3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } - dev: true - - /fast-safe-stringify/2.1.1: - resolution: - { - integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, - } - dev: true - - /finalhandler/1.2.0: - resolution: - { - integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==, - } - engines: { node: ">= 0.8" } - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - dev: false - - /find-up/5.0.0: - resolution: - { - integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, - } - engines: { node: ">=10" } - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /forwarded/0.2.0: - resolution: - { - integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, - } - engines: { node: ">= 0.6" } - dev: false - - /fresh/0.5.2: - resolution: - { - integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==, - } - engines: { node: ">= 0.6" } - dev: false - - /fs.realpath/1.0.0: - resolution: - { - integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, - } - dev: true - - /function-bind/1.1.1: - resolution: - { - integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, - } - dev: false - - /get-intrinsic/1.1.2: - resolution: - { - integrity: sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==, - } - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-symbols: 1.0.3 - dev: false - - /get-stream/6.0.1: - resolution: - { - integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, - } - engines: { node: ">=10" } - dev: true - - /glob/7.2.3: - resolution: - { - integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, - } - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /graceful-fs/4.2.10: - resolution: - { - integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, - } - dev: true - - /has-flag/3.0.0: - resolution: - { - integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, - } - engines: { node: ">=4" } - dev: true - - /has-symbols/1.0.3: - resolution: - { - integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==, - } - engines: { node: ">= 0.4" } - dev: false - - /has/1.0.3: - resolution: - { - integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, - } - engines: { node: ">= 0.4.0" } - dependencies: - function-bind: 1.1.1 - dev: false - - /http-errors/2.0.0: - resolution: - { - integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==, - } - engines: { node: ">= 0.8" } - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: false - - /human-signals/2.1.0: - resolution: - { - integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==, - } - engines: { node: ">=10.17.0" } - dev: true - - /iconv-lite/0.4.24: - resolution: - { - integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==, - } - engines: { node: ">=0.10.0" } - dependencies: - safer-buffer: 2.1.2 - dev: false - - /imurmurhash/0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, - } - engines: { node: ">=0.8.19" } - dev: true - - /individual/3.0.0: - resolution: - { - integrity: sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==, - } - dev: true - - /inflight/1.0.6: - resolution: - { - integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, - } - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits/2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } - dev: false - - /ipaddr.js/1.9.1: - resolution: - { - integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, - } - engines: { node: ">= 0.10" } - dev: false - - /is-arrayish/0.2.1: - resolution: - { - integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, - } - dev: true - - /is-plain-obj/2.1.0: - resolution: - { - integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==, - } - engines: { node: ">=8" } - dev: true - - /is-stream/2.0.1: - resolution: - { - integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, - } - engines: { node: ">=8" } - dev: true - - /is-typedarray/1.0.0: - resolution: - { - integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==, - } - dev: true - - /is-windows/1.0.2: - resolution: - { - integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==, - } - engines: { node: ">=0.10.0" } - dev: true - - /isexe/2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } - dev: true - - /js-tokens/4.0.0: - resolution: - { - integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, - } - dev: true - - /js-yaml/4.1.0: - resolution: - { - integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==, - } - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /json-parse-even-better-errors/2.3.1: - resolution: - { - integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, - } - dev: true - - /json-stringify-safe/5.0.1: - resolution: - { - integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==, - } - dev: true - - /json5/2.2.1: - resolution: - { - integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==, - } - engines: { node: ">=6" } - hasBin: true - dev: true - - /lines-and-columns/1.2.4: - resolution: - { - integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, - } - dev: true - - /locate-path/6.0.0: - resolution: - { - integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, - } - engines: { node: ">=10" } - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash/4.17.21: - resolution: - { - integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, - } - dev: false - - /lru-cache/6.0.0: - resolution: - { - integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, - } - engines: { node: ">=10" } - dependencies: - yallist: 4.0.0 - dev: true - - /map-age-cleaner/0.1.3: - resolution: - { - integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==, - } - engines: { node: ">=6" } - dependencies: - p-defer: 1.0.0 - dev: true - - /media-typer/0.3.0: - resolution: - { - integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==, - } - engines: { node: ">= 0.6" } - dev: false - - /mem/8.1.1: - resolution: - { - integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==, - } - engines: { node: ">=10" } - dependencies: - map-age-cleaner: 0.1.3 - mimic-fn: 3.1.0 - dev: true - - /merge-descriptors/1.0.1: - resolution: - { - integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==, - } - dev: false - - /merge-stream/2.0.0: - resolution: - { - integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, - } - dev: true - - /methods/1.1.2: - resolution: - { - integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==, - } - engines: { node: ">= 0.6" } - dev: false - - /mime-db/1.52.0: - resolution: - { - integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, - } - engines: { node: ">= 0.6" } - dev: false - - /mime-types/2.1.35: - resolution: - { - integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, - } - engines: { node: ">= 0.6" } - dependencies: - mime-db: 1.52.0 - dev: false - - /mime/1.6.0: - resolution: - { - integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==, - } - engines: { node: ">=4" } - hasBin: true - dev: false - - /mimic-fn/2.1.0: - resolution: - { - integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, - } - engines: { node: ">=6" } - dev: true - - /mimic-fn/3.1.0: - resolution: - { - integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==, - } - engines: { node: ">=8" } - dev: true - - /minimatch/3.1.2: - resolution: - { - integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, - } - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimist/1.2.6: - resolution: - { - integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==, - } - dev: true - - /ms/2.0.0: - resolution: - { - integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, - } - dev: false - - /ms/2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } - dev: false - - /ndjson/2.0.0: - resolution: - { - integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==, - } - engines: { node: ">=10" } - hasBin: true - dependencies: - json-stringify-safe: 5.0.1 - minimist: 1.2.6 - readable-stream: 3.6.0 - split2: 3.2.2 - through2: 4.0.2 - dev: true - - /negotiator/0.6.3: - resolution: - { - integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==, - } - engines: { node: ">= 0.6" } - dev: false - - /normalize-path/3.0.0: - resolution: - { - integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, - } - engines: { node: ">=0.10.0" } - dev: true - - /npm-run-path/4.0.1: - resolution: - { - integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==, - } - engines: { node: ">=8" } - dependencies: - path-key: 3.1.1 - dev: true - - /object-inspect/1.12.2: - resolution: - { - integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==, - } - dev: false - - /on-finished/2.4.1: - resolution: - { - integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, - } - engines: { node: ">= 0.8" } - dependencies: - ee-first: 1.1.1 - dev: false - - /once/1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime/5.1.2: - resolution: - { - integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, - } - engines: { node: ">=6" } - dependencies: - mimic-fn: 2.1.0 - dev: true - - /p-defer/1.0.0: - resolution: - { - integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==, - } - engines: { node: ">=4" } - dev: true - - /p-limit/3.1.0: - resolution: - { - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, - } - engines: { node: ">=10" } - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate/5.0.0: - resolution: - { - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, - } - engines: { node: ">=10" } - dependencies: - p-limit: 3.1.0 - dev: true - - /parse-json/5.2.0: - resolution: - { - integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, - } - engines: { node: ">=8" } - dependencies: - "@babel/code-frame": 7.18.6 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parseurl/1.3.3: - resolution: - { - integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, - } - engines: { node: ">= 0.8" } - dev: false - - /path-exists/4.0.0: - resolution: - { - integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, - } - engines: { node: ">=8" } - dev: true - - /path-is-absolute/1.0.1: - resolution: - { - integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, - } - engines: { node: ">=0.10.0" } - dev: true - - /path-key/3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } - dev: true - - /path-name/1.0.0: - resolution: - { - integrity: sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==, - } - dev: true - - /path-to-regexp/0.1.7: - resolution: - { - integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==, - } - dev: false - - /proxy-addr/2.0.7: - resolution: - { - integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, - } - engines: { node: ">= 0.10" } - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: false - - /qs/6.10.3: - resolution: - { - integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==, - } - engines: { node: ">=0.6" } - dependencies: - side-channel: 1.0.4 - dev: false - - /range-parser/1.2.1: - resolution: - { - integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==, - } - engines: { node: ">= 0.6" } - dev: false - - /raw-body/2.5.1: - resolution: - { - integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==, - } - engines: { node: ">= 0.8" } - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false - - /read-yaml-file/2.1.0: - resolution: - { - integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==, - } - engines: { node: ">=10.13" } - dependencies: - js-yaml: 4.1.0 - strip-bom: 4.0.0 - dev: true - - /readable-stream/3.6.0: - resolution: - { - integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==, - } - engines: { node: ">= 6" } - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /rename-overwrite/4.0.2: - resolution: - { - integrity: sha512-L1sgBgagVgOgb1Z6QZr1yJgSMHI4SXQqAH0l/UbeyHnLKxECvKIlyVEmBo4BqsCAZGg0SBSyjCh68lis5PgC7g==, - } - engines: { node: ">=12.10" } - dependencies: - "@zkochan/rimraf": 2.1.2 - dev: true - - /rfc4648/1.5.2: - resolution: - { - integrity: sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==, - } - dev: true - - /rimraf/3.0.2: - resolution: - { - integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, - } - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /safe-buffer/5.2.1: - resolution: - { - integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, - } - dev: false - - /safe-execa/0.1.2: - resolution: - { - integrity: sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==, - } - engines: { node: ">=12" } - dependencies: - "@zkochan/which": 2.0.3 - execa: 5.1.1 - path-name: 1.0.0 - dev: true - - /safer-buffer/2.1.2: - resolution: - { - integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, - } - dev: false - - /semver/7.3.7: - resolution: - { - integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==, - } - engines: { node: ">=10" } - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /send/0.18.0: - resolution: - { - integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==, - } - engines: { node: ">= 0.8.0" } - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - dev: false - - /serve-static/1.15.0: - resolution: - { - integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==, - } - engines: { node: ">= 0.8.0" } - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - dev: false - - /setprototypeof/1.2.0: - resolution: - { - integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, - } - dev: false - - /shebang-command/2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex/3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } - dev: true - - /side-channel/1.0.4: - resolution: - { - integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==, - } - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.2 - object-inspect: 1.12.2 - dev: false - - /signal-exit/3.0.7: - resolution: - { - integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, - } - dev: true - - /sort-keys/4.2.0: - resolution: - { - integrity: sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==, - } - engines: { node: ">=8" } - dependencies: - is-plain-obj: 2.1.0 - dev: true - - /split2/3.2.2: - resolution: - { - integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==, - } - dependencies: - readable-stream: 3.6.0 - dev: true - - /statuses/2.0.1: - resolution: - { - integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==, - } - engines: { node: ">= 0.8" } - dev: false - - /string_decoder/1.3.0: - resolution: - { - integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, - } - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-bom/4.0.0: - resolution: - { - integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==, - } - engines: { node: ">=8" } - dev: true - - /strip-final-newline/2.0.0: - resolution: - { - integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==, - } - engines: { node: ">=6" } - dev: true - - /supports-color/5.5.0: - resolution: - { - integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, - } - engines: { node: ">=4" } - dependencies: - has-flag: 3.0.0 - dev: true - - /through2/4.0.2: - resolution: - { - integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==, - } - dependencies: - readable-stream: 3.6.0 - dev: true - - /toidentifier/1.0.1: - resolution: - { - integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, - } - engines: { node: ">=0.6" } - dev: false - - /type-is/1.6.18: - resolution: - { - integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==, - } - engines: { node: ">= 0.6" } - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: false - - /typedarray-to-buffer/3.1.5: - resolution: - { - integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==, - } - dependencies: - is-typedarray: 1.0.0 - dev: true - - /unpipe/1.0.0: - resolution: - { - integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, - } - engines: { node: ">= 0.8" } - dev: false - - /util-deprecate/1.0.2: - resolution: - { - integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, - } - dev: true - - /utils-merge/1.0.1: - resolution: - { - integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==, - } - engines: { node: ">= 0.4.0" } - dev: false - - /vary/1.1.2: - resolution: - { - integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, - } - engines: { node: ">= 0.8" } - dev: false - - /which/2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wrappy/1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } - dev: true - - /write-file-atomic/3.0.3: - resolution: - { - integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==, - } - dependencies: - imurmurhash: 0.1.4 - is-typedarray: 1.0.0 - signal-exit: 3.0.7 - typedarray-to-buffer: 3.1.5 - dev: true - - /write-yaml-file/4.2.0: - resolution: - { - integrity: sha512-LwyucHy0uhWqbrOkh9cBluZBeNVxzHjDaE9mwepZG3n3ZlbM4v3ndrFw51zW/NXYFFqP+QWZ72ihtLWTh05e4Q==, - } - engines: { node: ">=10.13" } - dependencies: - js-yaml: 4.1.0 - write-file-atomic: 3.0.3 - dev: true - - /yallist/4.0.0: - resolution: - { - integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, - } - dev: true - - /yocto-queue/0.1.0: - resolution: - { - integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, - } - engines: { node: ">=10" } - dev: true diff --git a/crates/turborepo-lockfiles/fixtures/pnpm6turbo.yaml b/crates/turborepo-lockfiles/fixtures/pnpm6turbo.yaml deleted file mode 100644 index ca55831ab31c1..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm6turbo.yaml +++ /dev/null @@ -1,96 +0,0 @@ -lockfileVersion: "6.0" - -settings: - autoInstallPeers: false - excludeLinksFromLockfile: false - -importers: - .: - devDependencies: - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/web: {} - -packages: - /turbo-darwin-64@2.0.3: - resolution: - { - integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==, - } - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: - { - integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==, - } - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: - { - integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==, - } - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: - { - integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==, - } - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: - { - integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==, - } - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: - { - integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==, - } - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: - { - integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==, - } - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true diff --git a/crates/turborepo-lockfiles/fixtures/pnpm7-workspace.yaml b/crates/turborepo-lockfiles/fixtures/pnpm7-workspace.yaml deleted file mode 100644 index 2f7b66319bcbc..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm7-workspace.yaml +++ /dev/null @@ -1,3445 +0,0 @@ -lockfileVersion: 5.4 - -patchedDependencies: - lodash@4.17.21: - hash: ehchni3mpmovsvjxesffg2i5a4 - path: patches/lodash@4.17.21.patch - underscore@1.13.4: - hash: 3pbfs36izefyn2uycmknwkvuuy - path: patches/underscore@1.13.4.patch - -importers: - .: - specifiers: - eslint-config-custom: workspace:* - prettier: latest - turbo: latest - devDependencies: - eslint-config-custom: link:packages/eslint-config-custom - prettier: 2.7.1 - turbo: 1.4.6 - - apps/docs: - specifiers: - "@babel/core": ^7.0.0 - "@types/node": ^17.0.12 - "@types/react": 18.0.17 - dashboard-icons: github:peerigon/dashboard-icons - eslint: 7.32.0 - eslint-config-custom: workspace:* - next: 12.2.5 - next-transpile-modules: 9.0.0 - react: 18.2.0 - react-dom: 18.2.0 - tsconfig: workspace:* - typescript: ^4.5.3 - ui: workspace:* - underscore: ^1.13.4 - dependencies: - dashboard-icons: github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6 - next: 12.2.5_ir3quccc6i62x6qn6jjhyjjiey - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - ui: file:packages/ui - underscore: 1.13.4_3pbfs36izefyn2uycmknwkvuuy - devDependencies: - "@babel/core": 7.19.1 - "@types/node": 17.0.45 - "@types/react": 18.0.17 - eslint: 7.32.0 - eslint-config-custom: link:../../packages/eslint-config-custom - next-transpile-modules: 9.0.0 - tsconfig: link:../../packages/tsconfig - typescript: 4.8.3 - dependenciesMeta: - ui: - injected: true - - apps/web: - specifiers: - "@babel/core": ^7.0.0 - "@types/node": ^17.0.12 - "@types/react": 18.0.17 - eslint: 7.32.0 - eslint-config-custom: workspace:* - lodash: ^4.17.21 - next: 12.2.5 - next-transpile-modules: 9.0.0 - react: 18.2.0 - react-dom: 18.2.0 - tsconfig: workspace:* - typescript: ^4.5.3 - ui: workspace:* - dependencies: - lodash: 4.17.21_ehchni3mpmovsvjxesffg2i5a4 - next: 12.2.5_ir3quccc6i62x6qn6jjhyjjiey - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - ui: link:../../packages/ui - devDependencies: - "@babel/core": 7.19.1 - "@types/node": 17.0.45 - "@types/react": 18.0.17 - eslint: 7.32.0 - eslint-config-custom: link:../../packages/eslint-config-custom - next-transpile-modules: 9.0.0 - tsconfig: link:../../packages/tsconfig - typescript: 4.8.3 - - packages/eslint-config-custom: - specifiers: - eslint: ^7.23.0 - eslint-config-next: ^12.0.8 - eslint-config-prettier: ^8.3.0 - eslint-config-turbo: latest - eslint-plugin-react: 7.31.7 - typescript: ^4.7.4 - dependencies: - eslint: 7.32.0 - eslint-config-next: 12.3.0_dyxdave6dwjbccc5dgiifcmuza - eslint-config-prettier: 8.5.0_eslint@7.32.0 - eslint-config-turbo: 0.0.3_eslint@7.32.0 - eslint-plugin-react: 7.31.7_eslint@7.32.0 - devDependencies: - typescript: 4.8.3 - - packages/tsconfig: - specifiers: {} - - packages/ui: - specifiers: - "@types/react": ^18.0.17 - "@types/react-dom": ^18.0.6 - eslint: ^7.32.0 - eslint-config-custom: workspace:* - react: ^18.2.0 - tsconfig: workspace:* - typescript: ^4.5.2 - devDependencies: - "@types/react": 18.0.20 - "@types/react-dom": 18.0.6 - eslint: 7.32.0 - eslint-config-custom: link:../eslint-config-custom - react: 18.2.0 - tsconfig: link:../tsconfig - typescript: 4.8.3 - -packages: - /@ampproject/remapping/2.2.0: - resolution: - { - integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==, - } - engines: { node: ">=6.0.0" } - dependencies: - "@jridgewell/gen-mapping": 0.1.1 - "@jridgewell/trace-mapping": 0.3.15 - - /@babel/code-frame/7.12.11: - resolution: - { - integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==, - } - dependencies: - "@babel/highlight": 7.18.6 - - /@babel/code-frame/7.18.6: - resolution: - { - integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/highlight": 7.18.6 - - /@babel/compat-data/7.19.1: - resolution: - { - integrity: sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==, - } - engines: { node: ">=6.9.0" } - - /@babel/core/7.19.1: - resolution: - { - integrity: sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@ampproject/remapping": 2.2.0 - "@babel/code-frame": 7.18.6 - "@babel/generator": 7.19.0 - "@babel/helper-compilation-targets": 7.19.1_@babel+core@7.19.1 - "@babel/helper-module-transforms": 7.19.0 - "@babel/helpers": 7.19.0 - "@babel/parser": 7.19.1 - "@babel/template": 7.18.10 - "@babel/traverse": 7.19.1 - "@babel/types": 7.19.0 - convert-source-map: 1.8.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.1 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - - /@babel/generator/7.19.0: - resolution: - { - integrity: sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/types": 7.19.0 - "@jridgewell/gen-mapping": 0.3.2 - jsesc: 2.5.2 - - /@babel/helper-compilation-targets/7.19.1_@babel+core@7.19.1: - resolution: - { - integrity: sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - dependencies: - "@babel/compat-data": 7.19.1 - "@babel/core": 7.19.1 - "@babel/helper-validator-option": 7.18.6 - browserslist: 4.21.3 - semver: 6.3.0 - - /@babel/helper-environment-visitor/7.18.9: - resolution: - { - integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==, - } - engines: { node: ">=6.9.0" } - - /@babel/helper-function-name/7.19.0: - resolution: - { - integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/template": 7.18.10 - "@babel/types": 7.19.0 - - /@babel/helper-hoist-variables/7.18.6: - resolution: - { - integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/types": 7.19.0 - - /@babel/helper-module-imports/7.18.6: - resolution: - { - integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/types": 7.19.0 - - /@babel/helper-module-transforms/7.19.0: - resolution: - { - integrity: sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/helper-environment-visitor": 7.18.9 - "@babel/helper-module-imports": 7.18.6 - "@babel/helper-simple-access": 7.18.6 - "@babel/helper-split-export-declaration": 7.18.6 - "@babel/helper-validator-identifier": 7.19.1 - "@babel/template": 7.18.10 - "@babel/traverse": 7.19.1 - "@babel/types": 7.19.0 - transitivePeerDependencies: - - supports-color - - /@babel/helper-simple-access/7.18.6: - resolution: - { - integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/types": 7.19.0 - - /@babel/helper-split-export-declaration/7.18.6: - resolution: - { - integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/types": 7.19.0 - - /@babel/helper-string-parser/7.18.10: - resolution: - { - integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==, - } - engines: { node: ">=6.9.0" } - - /@babel/helper-validator-identifier/7.19.1: - resolution: - { - integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==, - } - engines: { node: ">=6.9.0" } - - /@babel/helper-validator-option/7.18.6: - resolution: - { - integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==, - } - engines: { node: ">=6.9.0" } - - /@babel/helpers/7.19.0: - resolution: - { - integrity: sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/template": 7.18.10 - "@babel/traverse": 7.19.1 - "@babel/types": 7.19.0 - transitivePeerDependencies: - - supports-color - - /@babel/highlight/7.18.6: - resolution: - { - integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/helper-validator-identifier": 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - - /@babel/parser/7.19.1: - resolution: - { - integrity: sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==, - } - engines: { node: ">=6.0.0" } - hasBin: true - dependencies: - "@babel/types": 7.19.0 - - /@babel/runtime-corejs3/7.19.1: - resolution: - { - integrity: sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==, - } - engines: { node: ">=6.9.0" } - dependencies: - core-js-pure: 3.25.1 - regenerator-runtime: 0.13.9 - dev: false - - /@babel/runtime/7.19.0: - resolution: - { - integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==, - } - engines: { node: ">=6.9.0" } - dependencies: - regenerator-runtime: 0.13.9 - dev: false - - /@babel/template/7.18.10: - resolution: - { - integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/code-frame": 7.18.6 - "@babel/parser": 7.19.1 - "@babel/types": 7.19.0 - - /@babel/traverse/7.19.1: - resolution: - { - integrity: sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/code-frame": 7.18.6 - "@babel/generator": 7.19.0 - "@babel/helper-environment-visitor": 7.18.9 - "@babel/helper-function-name": 7.19.0 - "@babel/helper-hoist-variables": 7.18.6 - "@babel/helper-split-export-declaration": 7.18.6 - "@babel/parser": 7.19.1 - "@babel/types": 7.19.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - /@babel/types/7.19.0: - resolution: - { - integrity: sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==, - } - engines: { node: ">=6.9.0" } - dependencies: - "@babel/helper-string-parser": 7.18.10 - "@babel/helper-validator-identifier": 7.19.1 - to-fast-properties: 2.0.0 - - /@eslint/eslintrc/0.4.3: - resolution: - { - integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==, - } - engines: { node: ^10.12.0 || >=12.0.0 } - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 7.3.1 - globals: 13.17.0 - ignore: 4.0.6 - import-fresh: 3.3.0 - js-yaml: 3.14.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - /@humanwhocodes/config-array/0.5.0: - resolution: - { - integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==, - } - engines: { node: ">=10.10.0" } - dependencies: - "@humanwhocodes/object-schema": 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - /@humanwhocodes/object-schema/1.2.1: - resolution: - { - integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==, - } - - /@jridgewell/gen-mapping/0.1.1: - resolution: - { - integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==, - } - engines: { node: ">=6.0.0" } - dependencies: - "@jridgewell/set-array": 1.1.2 - "@jridgewell/sourcemap-codec": 1.4.14 - - /@jridgewell/gen-mapping/0.3.2: - resolution: - { - integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==, - } - engines: { node: ">=6.0.0" } - dependencies: - "@jridgewell/set-array": 1.1.2 - "@jridgewell/sourcemap-codec": 1.4.14 - "@jridgewell/trace-mapping": 0.3.15 - - /@jridgewell/resolve-uri/3.1.0: - resolution: - { - integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==, - } - engines: { node: ">=6.0.0" } - - /@jridgewell/set-array/1.1.2: - resolution: - { - integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==, - } - engines: { node: ">=6.0.0" } - - /@jridgewell/sourcemap-codec/1.4.14: - resolution: - { - integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==, - } - - /@jridgewell/trace-mapping/0.3.15: - resolution: - { - integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==, - } - dependencies: - "@jridgewell/resolve-uri": 3.1.0 - "@jridgewell/sourcemap-codec": 1.4.14 - - /@next/env/12.2.5: - resolution: - { - integrity: sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw==, - } - dev: false - - /@next/eslint-plugin-next/12.3.0: - resolution: - { - integrity: sha512-jVdq1qYTNDjUtulnE8/hkPv0pHILV4jMg5La99iaY/FFm20WxVnsAZtbNnMvlPbf8dc010oO304SX9yXbg5PAw==, - } - dependencies: - glob: 7.1.7 - dev: false - - /@next/swc-android-arm-eabi/12.2.5: - resolution: - { - integrity: sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==, - } - engines: { node: ">= 10" } - cpu: [arm] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@next/swc-android-arm64/12.2.5: - resolution: - { - integrity: sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==, - } - engines: { node: ">= 10" } - cpu: [arm64] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-arm64/12.2.5: - resolution: - { - integrity: sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==, - } - engines: { node: ">= 10" } - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64/12.2.5: - resolution: - { - integrity: sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==, - } - engines: { node: ">= 10" } - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-freebsd-x64/12.2.5: - resolution: - { - integrity: sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==, - } - engines: { node: ">= 10" } - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm-gnueabihf/12.2.5: - resolution: - { - integrity: sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==, - } - engines: { node: ">= 10" } - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu/12.2.5: - resolution: - { - integrity: sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==, - } - engines: { node: ">= 10" } - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl/12.2.5: - resolution: - { - integrity: sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==, - } - engines: { node: ">= 10" } - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu/12.2.5: - resolution: - { - integrity: sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==, - } - engines: { node: ">= 10" } - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl/12.2.5: - resolution: - { - integrity: sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==, - } - engines: { node: ">= 10" } - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc/12.2.5: - resolution: - { - integrity: sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==, - } - engines: { node: ">= 10" } - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-ia32-msvc/12.2.5: - resolution: - { - integrity: sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==, - } - engines: { node: ">= 10" } - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc/12.2.5: - resolution: - { - integrity: sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==, - } - engines: { node: ">= 10" } - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@nodelib/fs.scandir/2.1.5: - resolution: - { - integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, - } - engines: { node: ">= 8" } - dependencies: - "@nodelib/fs.stat": 2.0.5 - run-parallel: 1.2.0 - dev: false - - /@nodelib/fs.stat/2.0.5: - resolution: - { - integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, - } - engines: { node: ">= 8" } - dev: false - - /@nodelib/fs.walk/1.2.8: - resolution: - { - integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, - } - engines: { node: ">= 8" } - dependencies: - "@nodelib/fs.scandir": 2.1.5 - fastq: 1.13.0 - dev: false - - /@rushstack/eslint-patch/1.1.4: - resolution: - { - integrity: sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==, - } - dev: false - - /@swc/helpers/0.4.3: - resolution: - { - integrity: sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==, - } - dependencies: - tslib: 2.4.0 - dev: false - - /@types/json5/0.0.29: - resolution: - { - integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==, - } - dev: false - - /@types/node/17.0.45: - resolution: - { - integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==, - } - dev: true - - /@types/prop-types/15.7.5: - resolution: - { - integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==, - } - dev: true - - /@types/react-dom/18.0.6: - resolution: - { - integrity: sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==, - } - dependencies: - "@types/react": 18.0.20 - dev: true - - /@types/react/18.0.17: - resolution: - { - integrity: sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==, - } - dependencies: - "@types/prop-types": 15.7.5 - "@types/scheduler": 0.16.2 - csstype: 3.1.1 - dev: true - - /@types/react/18.0.20: - resolution: - { - integrity: sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA==, - } - dependencies: - "@types/prop-types": 15.7.5 - "@types/scheduler": 0.16.2 - csstype: 3.1.1 - dev: true - - /@types/scheduler/0.16.2: - resolution: - { - integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==, - } - dev: true - - /@typescript-eslint/parser/5.37.0_dyxdave6dwjbccc5dgiifcmuza: - resolution: - { - integrity: sha512-01VzI/ipYKuaG5PkE5+qyJ6m02fVALmMPY3Qq5BHflDx3y4VobbLdHQkSMg9VPRS4KdNt4oYTMaomFoHonBGAw==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: "*" - peerDependenciesMeta: - typescript: - optional: true - dependencies: - "@typescript-eslint/scope-manager": 5.37.0 - "@typescript-eslint/types": 5.37.0 - "@typescript-eslint/typescript-estree": 5.37.0_typescript@4.8.3 - debug: 4.3.4 - eslint: 7.32.0 - typescript: 4.8.3 - transitivePeerDependencies: - - supports-color - dev: false - - /@typescript-eslint/scope-manager/5.37.0: - resolution: - { - integrity: sha512-F67MqrmSXGd/eZnujjtkPgBQzgespu/iCZ+54Ok9X5tALb9L2v3G+QBSoWkXG0p3lcTJsL+iXz5eLUEdSiJU9Q==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dependencies: - "@typescript-eslint/types": 5.37.0 - "@typescript-eslint/visitor-keys": 5.37.0 - dev: false - - /@typescript-eslint/types/5.37.0: - resolution: - { - integrity: sha512-3frIJiTa5+tCb2iqR/bf7XwU20lnU05r/sgPJnRpwvfZaqCJBrl8Q/mw9vr3NrNdB/XtVyMA0eppRMMBqdJ1bA==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dev: false - - /@typescript-eslint/typescript-estree/5.37.0_typescript@4.8.3: - resolution: - { - integrity: sha512-JkFoFIt/cx59iqEDSgIGnQpCTRv96MQnXCYvJi7QhBC24uyuzbD8wVbajMB1b9x4I0octYFJ3OwjAwNqk1AjDA==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - peerDependencies: - typescript: "*" - peerDependenciesMeta: - typescript: - optional: true - dependencies: - "@typescript-eslint/types": 5.37.0 - "@typescript-eslint/visitor-keys": 5.37.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.3.7 - tsutils: 3.21.0_typescript@4.8.3 - typescript: 4.8.3 - transitivePeerDependencies: - - supports-color - dev: false - - /@typescript-eslint/visitor-keys/5.37.0: - resolution: - { - integrity: sha512-Hp7rT4cENBPIzMwrlehLW/28EVCOcE9U1Z1BQTc8EA8v5qpr7GRGuG+U58V5tTY48zvUOA3KHvw3rA8tY9fbdA==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dependencies: - "@typescript-eslint/types": 5.37.0 - eslint-visitor-keys: 3.3.0 - dev: false - - /acorn-jsx/5.3.2_acorn@7.4.1: - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, - } - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 7.4.1 - - /acorn/7.4.1: - resolution: - { - integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==, - } - engines: { node: ">=0.4.0" } - hasBin: true - - /ajv/6.12.6: - resolution: - { - integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, - } - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - /ajv/8.11.0: - resolution: - { - integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==, - } - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - - /ansi-colors/4.1.3: - resolution: - { - integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==, - } - engines: { node: ">=6" } - - /ansi-regex/5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: ">=8" } - - /ansi-styles/3.2.1: - resolution: - { - integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, - } - engines: { node: ">=4" } - dependencies: - color-convert: 1.9.3 - - /ansi-styles/4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, - } - engines: { node: ">=8" } - dependencies: - color-convert: 2.0.1 - - /argparse/1.0.10: - resolution: - { - integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==, - } - dependencies: - sprintf-js: 1.0.3 - - /aria-query/4.2.2: - resolution: - { - integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==, - } - engines: { node: ">=6.0" } - dependencies: - "@babel/runtime": 7.19.0 - "@babel/runtime-corejs3": 7.19.1 - dev: false - - /array-includes/3.1.5: - resolution: - { - integrity: sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - get-intrinsic: 1.1.3 - is-string: 1.0.7 - dev: false - - /array-union/2.1.0: - resolution: - { - integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, - } - engines: { node: ">=8" } - dev: false - - /array.prototype.flat/1.3.0: - resolution: - { - integrity: sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - es-shim-unscopables: 1.0.0 - dev: false - - /array.prototype.flatmap/1.3.0: - resolution: - { - integrity: sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - es-shim-unscopables: 1.0.0 - dev: false - - /ast-types-flow/0.0.7: - resolution: - { - integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==, - } - dev: false - - /astral-regex/2.0.0: - resolution: - { - integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==, - } - engines: { node: ">=8" } - - /axe-core/4.4.3: - resolution: - { - integrity: sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==, - } - engines: { node: ">=4" } - dev: false - - /axobject-query/2.2.0: - resolution: - { - integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==, - } - dev: false - - /balanced-match/1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, - } - - /brace-expansion/1.1.11: - resolution: - { - integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==, - } - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - /braces/3.0.2: - resolution: - { - integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==, - } - engines: { node: ">=8" } - dependencies: - fill-range: 7.0.1 - dev: false - - /browserslist/4.21.3: - resolution: - { - integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==, - } - engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } - hasBin: true - dependencies: - caniuse-lite: 1.0.30001399 - electron-to-chromium: 1.4.249 - node-releases: 2.0.6 - update-browserslist-db: 1.0.9_browserslist@4.21.3 - - /call-bind/1.0.2: - resolution: - { - integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==, - } - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.1.3 - dev: false - - /callsites/3.1.0: - resolution: - { - integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, - } - engines: { node: ">=6" } - - /caniuse-lite/1.0.30001399: - resolution: - { - integrity: sha512-4vQ90tMKS+FkvuVWS5/QY1+d805ODxZiKFzsU8o/RsVJz49ZSRR8EjykLJbqhzdPgadbX6wB538wOzle3JniRA==, - } - - /chalk/2.4.2: - resolution: - { - integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==, - } - engines: { node: ">=4" } - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - /chalk/4.1.2: - resolution: - { - integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, - } - engines: { node: ">=10" } - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - /color-convert/1.9.3: - resolution: - { - integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, - } - dependencies: - color-name: 1.1.3 - - /color-convert/2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, - } - engines: { node: ">=7.0.0" } - dependencies: - color-name: 1.1.4 - - /color-name/1.1.3: - resolution: - { - integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, - } - - /color-name/1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, - } - - /concat-map/0.0.1: - resolution: - { - integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, - } - - /convert-source-map/1.8.0: - resolution: - { - integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==, - } - dependencies: - safe-buffer: 5.1.2 - - /core-js-pure/3.25.1: - resolution: - { - integrity: sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A==, - } - requiresBuild: true - dev: false - - /cross-spawn/7.0.3: - resolution: - { - integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==, - } - engines: { node: ">= 8" } - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - /csstype/3.1.1: - resolution: - { - integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==, - } - dev: true - - /damerau-levenshtein/1.0.8: - resolution: - { - integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==, - } - dev: false - - /debug/2.6.9: - resolution: - { - integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, - } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: false - - /debug/3.2.7: - resolution: - { - integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, - } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: false - - /debug/4.3.4: - resolution: - { - integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, - } - engines: { node: ">=6.0" } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /deep-is/0.1.4: - resolution: - { - integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, - } - - /define-properties/1.1.4: - resolution: - { - integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==, - } - engines: { node: ">= 0.4" } - dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - dev: false - - /dir-glob/3.0.1: - resolution: - { - integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==, - } - engines: { node: ">=8" } - dependencies: - path-type: 4.0.0 - dev: false - - /doctrine/2.1.0: - resolution: - { - integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==, - } - engines: { node: ">=0.10.0" } - dependencies: - esutils: 2.0.3 - dev: false - - /doctrine/3.0.0: - resolution: - { - integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==, - } - engines: { node: ">=6.0.0" } - dependencies: - esutils: 2.0.3 - - /electron-to-chromium/1.4.249: - resolution: - { - integrity: sha512-GMCxR3p2HQvIw47A599crTKYZprqihoBL4lDSAUmr7IYekXFK5t/WgEBrGJDCa2HWIZFQEkGuMqPCi05ceYqPQ==, - } - - /emoji-regex/8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } - - /emoji-regex/9.2.2: - resolution: - { - integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, - } - dev: false - - /enhanced-resolve/5.10.0: - resolution: - { - integrity: sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==, - } - engines: { node: ">=10.13.0" } - dependencies: - graceful-fs: 4.2.10 - tapable: 2.2.1 - dev: true - - /enquirer/2.3.6: - resolution: - { - integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==, - } - engines: { node: ">=8.6" } - dependencies: - ansi-colors: 4.1.3 - - /es-abstract/1.20.2: - resolution: - { - integrity: sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - es-to-primitive: 1.2.1 - function-bind: 1.1.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.1.3 - get-symbol-description: 1.0.0 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-symbols: 1.0.3 - internal-slot: 1.0.3 - is-callable: 1.2.5 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-weakref: 1.0.2 - object-inspect: 1.12.2 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.4.3 - string.prototype.trimend: 1.0.5 - string.prototype.trimstart: 1.0.5 - unbox-primitive: 1.0.2 - dev: false - - /es-shim-unscopables/1.0.0: - resolution: - { - integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==, - } - dependencies: - has: 1.0.3 - dev: false - - /es-to-primitive/1.2.1: - resolution: - { - integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==, - } - engines: { node: ">= 0.4" } - dependencies: - is-callable: 1.2.5 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: false - - /escalade/3.1.1: - resolution: - { - integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==, - } - engines: { node: ">=6" } - - /escape-string-regexp/1.0.5: - resolution: - { - integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, - } - engines: { node: ">=0.8.0" } - - /escape-string-regexp/4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: { node: ">=10" } - - /eslint-config-next/12.3.0_dyxdave6dwjbccc5dgiifcmuza: - resolution: - { - integrity: sha512-guHSkNyKnTBB8HU35COgAMeMV0E026BiYRYvyEVVaTOeFcnU3i1EI8/Da0Rl7H3Sgua5FEvoA0vYd2s8kdIUXg==, - } - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - typescript: ">=3.3.1" - peerDependenciesMeta: - typescript: - optional: true - dependencies: - "@next/eslint-plugin-next": 12.3.0 - "@rushstack/eslint-patch": 1.1.4 - "@typescript-eslint/parser": 5.37.0_dyxdave6dwjbccc5dgiifcmuza - eslint: 7.32.0 - eslint-import-resolver-node: 0.3.6 - eslint-import-resolver-typescript: 2.7.1_hpmu7kn6tcn2vnxpfzvv33bxmy - eslint-plugin-import: 2.26.0_xag76ci373f5hzfwsxolrbhy4a - eslint-plugin-jsx-a11y: 6.6.1_eslint@7.32.0 - eslint-plugin-react: 7.31.7_eslint@7.32.0 - eslint-plugin-react-hooks: 4.6.0_eslint@7.32.0 - typescript: 4.8.3 - transitivePeerDependencies: - - eslint-import-resolver-webpack - - supports-color - dev: false - - /eslint-config-prettier/8.5.0_eslint@7.32.0: - resolution: - { - integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==, - } - hasBin: true - peerDependencies: - eslint: ">=7.0.0" - dependencies: - eslint: 7.32.0 - dev: false - - /eslint-config-turbo/0.0.3_eslint@7.32.0: - resolution: - { - integrity: sha512-hK5MlxDugUWZV9ZKcyfNwLXrlMuM2wPgAUk51cUFBC3nXRCVmCA9uSRFBZsyAIurN1wH7mS7G1NBo5F8VkF7lQ==, - } - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - dependencies: - eslint: 7.32.0 - eslint-plugin-turbo: 0.0.3_eslint@7.32.0 - dev: false - - /eslint-import-resolver-node/0.3.6: - resolution: - { - integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==, - } - dependencies: - debug: 3.2.7 - resolve: 1.22.1 - transitivePeerDependencies: - - supports-color - dev: false - - /eslint-import-resolver-typescript/2.7.1_hpmu7kn6tcn2vnxpfzvv33bxmy: - resolution: - { - integrity: sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==, - } - engines: { node: ">=4" } - peerDependencies: - eslint: "*" - eslint-plugin-import: "*" - dependencies: - debug: 4.3.4 - eslint: 7.32.0 - eslint-plugin-import: 2.26.0_xag76ci373f5hzfwsxolrbhy4a - glob: 7.2.3 - is-glob: 4.0.3 - resolve: 1.22.1 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - supports-color - dev: false - - /eslint-module-utils/2.7.4_qk4u2ghovatg5ueomqmuln4u2e: - resolution: - { - integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==, - } - engines: { node: ">=4" } - peerDependencies: - "@typescript-eslint/parser": "*" - eslint: "*" - eslint-import-resolver-node: "*" - eslint-import-resolver-typescript: "*" - eslint-import-resolver-webpack: "*" - peerDependenciesMeta: - "@typescript-eslint/parser": - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - "@typescript-eslint/parser": 5.37.0_dyxdave6dwjbccc5dgiifcmuza - debug: 3.2.7 - eslint: 7.32.0 - eslint-import-resolver-node: 0.3.6 - eslint-import-resolver-typescript: 2.7.1_hpmu7kn6tcn2vnxpfzvv33bxmy - transitivePeerDependencies: - - supports-color - dev: false - - /eslint-plugin-import/2.26.0_xag76ci373f5hzfwsxolrbhy4a: - resolution: - { - integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==, - } - engines: { node: ">=4" } - peerDependencies: - "@typescript-eslint/parser": "*" - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - "@typescript-eslint/parser": - optional: true - dependencies: - "@typescript-eslint/parser": 5.37.0_dyxdave6dwjbccc5dgiifcmuza - array-includes: 3.1.5 - array.prototype.flat: 1.3.0 - debug: 2.6.9 - doctrine: 2.1.0 - eslint: 7.32.0 - eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.4_qk4u2ghovatg5ueomqmuln4u2e - has: 1.0.3 - is-core-module: 2.10.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.5 - resolve: 1.22.1 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: false - - /eslint-plugin-jsx-a11y/6.6.1_eslint@7.32.0: - resolution: - { - integrity: sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==, - } - engines: { node: ">=4.0" } - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - "@babel/runtime": 7.19.0 - aria-query: 4.2.2 - array-includes: 3.1.5 - ast-types-flow: 0.0.7 - axe-core: 4.4.3 - axobject-query: 2.2.0 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 7.32.0 - has: 1.0.3 - jsx-ast-utils: 3.3.3 - language-tags: 1.0.5 - minimatch: 3.1.2 - semver: 6.3.0 - dev: false - - /eslint-plugin-react-hooks/4.6.0_eslint@7.32.0: - resolution: - { - integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==, - } - engines: { node: ">=10" } - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 7.32.0 - dev: false - - /eslint-plugin-react/7.31.7_eslint@7.32.0: - resolution: - { - integrity: sha512-8NldBTeYp/kQoTV1uT0XF6HcmDqbgZ0lNPkN0wlRw8DJKXEnaWu+oh/6gt3xIhzvQ35wB2Y545fJhIbJSZ2NNw==, - } - engines: { node: ">=4" } - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.5 - array.prototype.flatmap: 1.3.0 - doctrine: 2.1.0 - eslint: 7.32.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.3 - minimatch: 3.1.2 - object.entries: 1.1.5 - object.fromentries: 2.0.5 - object.hasown: 1.1.1 - object.values: 1.1.5 - prop-types: 15.8.1 - resolve: 2.0.0-next.4 - semver: 6.3.0 - string.prototype.matchall: 4.0.7 - dev: false - - /eslint-plugin-turbo/0.0.3_eslint@7.32.0: - resolution: - { - integrity: sha512-QjidATGxWtaB9QUrD3NocUySmsgWKZlBMFlw4kX2IIjRLAxMPwukk90h3ZTaNXyRHuaQsrEgh7hhlCZoxP0TTw==, - } - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - dependencies: - eslint: 7.32.0 - dev: false - - /eslint-scope/5.1.1: - resolution: - { - integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==, - } - engines: { node: ">=8.0.0" } - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - - /eslint-utils/2.1.0: - resolution: - { - integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==, - } - engines: { node: ">=6" } - dependencies: - eslint-visitor-keys: 1.3.0 - - /eslint-visitor-keys/1.3.0: - resolution: - { - integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==, - } - engines: { node: ">=4" } - - /eslint-visitor-keys/2.1.0: - resolution: - { - integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==, - } - engines: { node: ">=10" } - - /eslint-visitor-keys/3.3.0: - resolution: - { - integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dev: false - - /eslint/7.32.0: - resolution: - { - integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==, - } - engines: { node: ^10.12.0 || >=12.0.0 } - hasBin: true - dependencies: - "@babel/code-frame": 7.12.11 - "@eslint/eslintrc": 0.4.3 - "@humanwhocodes/config-array": 0.5.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - enquirer: 2.3.6 - escape-string-regexp: 4.0.0 - eslint-scope: 5.1.1 - eslint-utils: 2.1.0 - eslint-visitor-keys: 2.1.0 - espree: 7.3.1 - esquery: 1.4.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - functional-red-black-tree: 1.0.1 - glob-parent: 5.1.2 - globals: 13.17.0 - ignore: 4.0.6 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - js-yaml: 3.14.1 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.1 - progress: 2.0.3 - regexpp: 3.2.0 - semver: 7.3.7 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - table: 6.8.0 - text-table: 0.2.0 - v8-compile-cache: 2.3.0 - transitivePeerDependencies: - - supports-color - - /espree/7.3.1: - resolution: - { - integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==, - } - engines: { node: ^10.12.0 || >=12.0.0 } - dependencies: - acorn: 7.4.1 - acorn-jsx: 5.3.2_acorn@7.4.1 - eslint-visitor-keys: 1.3.0 - - /esprima/4.0.1: - resolution: - { - integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, - } - engines: { node: ">=4" } - hasBin: true - - /esquery/1.4.0: - resolution: - { - integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==, - } - engines: { node: ">=0.10" } - dependencies: - estraverse: 5.3.0 - - /esrecurse/4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, - } - engines: { node: ">=4.0" } - dependencies: - estraverse: 5.3.0 - - /estraverse/4.3.0: - resolution: - { - integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==, - } - engines: { node: ">=4.0" } - - /estraverse/5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, - } - engines: { node: ">=4.0" } - - /esutils/2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, - } - engines: { node: ">=0.10.0" } - - /fast-deep-equal/3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } - - /fast-glob/3.2.12: - resolution: - { - integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==, - } - engines: { node: ">=8.6.0" } - dependencies: - "@nodelib/fs.stat": 2.0.5 - "@nodelib/fs.walk": 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: false - - /fast-json-stable-stringify/2.1.0: - resolution: - { - integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, - } - - /fast-levenshtein/2.0.6: - resolution: - { - integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, - } - - /fastq/1.13.0: - resolution: - { - integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==, - } - dependencies: - reusify: 1.0.4 - dev: false - - /file-entry-cache/6.0.1: - resolution: - { - integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==, - } - engines: { node: ^10.12.0 || >=12.0.0 } - dependencies: - flat-cache: 3.0.4 - - /fill-range/7.0.1: - resolution: - { - integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, - } - engines: { node: ">=8" } - dependencies: - to-regex-range: 5.0.1 - dev: false - - /flat-cache/3.0.4: - resolution: - { - integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==, - } - engines: { node: ^10.12.0 || >=12.0.0 } - dependencies: - flatted: 3.2.7 - rimraf: 3.0.2 - - /flatted/3.2.7: - resolution: - { - integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==, - } - - /fs.realpath/1.0.0: - resolution: - { - integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, - } - - /function-bind/1.1.1: - resolution: - { - integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, - } - dev: false - - /function.prototype.name/1.1.5: - resolution: - { - integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - functions-have-names: 1.2.3 - dev: false - - /functional-red-black-tree/1.0.1: - resolution: - { - integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==, - } - - /functions-have-names/1.2.3: - resolution: - { - integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, - } - dev: false - - /gensync/1.0.0-beta.2: - resolution: - { - integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, - } - engines: { node: ">=6.9.0" } - - /get-intrinsic/1.1.3: - resolution: - { - integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==, - } - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-symbols: 1.0.3 - dev: false - - /get-symbol-description/1.0.0: - resolution: - { - integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - dev: false - - /glob-parent/5.1.2: - resolution: - { - integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, - } - engines: { node: ">= 6" } - dependencies: - is-glob: 4.0.3 - - /glob/7.1.7: - resolution: - { - integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==, - } - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: false - - /glob/7.2.3: - resolution: - { - integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, - } - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - /globals/11.12.0: - resolution: - { - integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==, - } - engines: { node: ">=4" } - - /globals/13.17.0: - resolution: - { - integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==, - } - engines: { node: ">=8" } - dependencies: - type-fest: 0.20.2 - - /globby/11.1.0: - resolution: - { - integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==, - } - engines: { node: ">=10" } - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.2.12 - ignore: 5.2.0 - merge2: 1.4.1 - slash: 3.0.0 - dev: false - - /graceful-fs/4.2.10: - resolution: - { - integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, - } - dev: true - - /has-bigints/1.0.2: - resolution: - { - integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==, - } - dev: false - - /has-flag/3.0.0: - resolution: - { - integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, - } - engines: { node: ">=4" } - - /has-flag/4.0.0: - resolution: - { - integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, - } - engines: { node: ">=8" } - - /has-property-descriptors/1.0.0: - resolution: - { - integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==, - } - dependencies: - get-intrinsic: 1.1.3 - dev: false - - /has-symbols/1.0.3: - resolution: - { - integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==, - } - engines: { node: ">= 0.4" } - dev: false - - /has-tostringtag/1.0.0: - resolution: - { - integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==, - } - engines: { node: ">= 0.4" } - dependencies: - has-symbols: 1.0.3 - dev: false - - /has/1.0.3: - resolution: - { - integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, - } - engines: { node: ">= 0.4.0" } - dependencies: - function-bind: 1.1.1 - dev: false - - /ignore/4.0.6: - resolution: - { - integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==, - } - engines: { node: ">= 4" } - - /ignore/5.2.0: - resolution: - { - integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==, - } - engines: { node: ">= 4" } - dev: false - - /import-fresh/3.3.0: - resolution: - { - integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==, - } - engines: { node: ">=6" } - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - /imurmurhash/0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, - } - engines: { node: ">=0.8.19" } - - /inflight/1.0.6: - resolution: - { - integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, - } - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - /inherits/2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } - - /internal-slot/1.0.3: - resolution: - { - integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==, - } - engines: { node: ">= 0.4" } - dependencies: - get-intrinsic: 1.1.3 - has: 1.0.3 - side-channel: 1.0.4 - dev: false - - /is-bigint/1.0.4: - resolution: - { - integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==, - } - dependencies: - has-bigints: 1.0.2 - dev: false - - /is-boolean-object/1.1.2: - resolution: - { - integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: false - - /is-callable/1.2.5: - resolution: - { - integrity: sha512-ZIWRujF6MvYGkEuHMYtFRkL2wAtFw89EHfKlXrkPkjQZZRWeh9L1q3SV13NIfHnqxugjLvAOkEHx9mb1zcMnEw==, - } - engines: { node: ">= 0.4" } - dev: false - - /is-core-module/2.10.0: - resolution: - { - integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==, - } - dependencies: - has: 1.0.3 - dev: false - - /is-date-object/1.0.5: - resolution: - { - integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==, - } - engines: { node: ">= 0.4" } - dependencies: - has-tostringtag: 1.0.0 - dev: false - - /is-extglob/2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, - } - engines: { node: ">=0.10.0" } - - /is-fullwidth-code-point/3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: ">=8" } - - /is-glob/4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, - } - engines: { node: ">=0.10.0" } - dependencies: - is-extglob: 2.1.1 - - /is-negative-zero/2.0.2: - resolution: - { - integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==, - } - engines: { node: ">= 0.4" } - dev: false - - /is-number-object/1.0.7: - resolution: - { - integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==, - } - engines: { node: ">= 0.4" } - dependencies: - has-tostringtag: 1.0.0 - dev: false - - /is-number/7.0.0: - resolution: - { - integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, - } - engines: { node: ">=0.12.0" } - dev: false - - /is-regex/1.1.4: - resolution: - { - integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: false - - /is-shared-array-buffer/1.0.2: - resolution: - { - integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==, - } - dependencies: - call-bind: 1.0.2 - dev: false - - /is-string/1.0.7: - resolution: - { - integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==, - } - engines: { node: ">= 0.4" } - dependencies: - has-tostringtag: 1.0.0 - dev: false - - /is-symbol/1.0.4: - resolution: - { - integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==, - } - engines: { node: ">= 0.4" } - dependencies: - has-symbols: 1.0.3 - dev: false - - /is-weakref/1.0.2: - resolution: - { - integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==, - } - dependencies: - call-bind: 1.0.2 - dev: false - - /isexe/2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } - - /js-tokens/4.0.0: - resolution: - { - integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, - } - - /js-yaml/3.14.1: - resolution: - { - integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==, - } - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - /jsesc/2.5.2: - resolution: - { - integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==, - } - engines: { node: ">=4" } - hasBin: true - - /json-schema-traverse/0.4.1: - resolution: - { - integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, - } - - /json-schema-traverse/1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } - - /json-stable-stringify-without-jsonify/1.0.1: - resolution: - { - integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, - } - - /json5/1.0.1: - resolution: - { - integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==, - } - hasBin: true - dependencies: - minimist: 1.2.6 - dev: false - - /json5/2.2.1: - resolution: - { - integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==, - } - engines: { node: ">=6" } - hasBin: true - - /jsx-ast-utils/3.3.3: - resolution: - { - integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==, - } - engines: { node: ">=4.0" } - dependencies: - array-includes: 3.1.5 - object.assign: 4.1.4 - dev: false - - /language-subtag-registry/0.3.22: - resolution: - { - integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==, - } - dev: false - - /language-tags/1.0.5: - resolution: - { - integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==, - } - dependencies: - language-subtag-registry: 0.3.22 - dev: false - - /levn/0.4.1: - resolution: - { - integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, - } - engines: { node: ">= 0.8.0" } - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - /lodash.merge/4.6.2: - resolution: - { - integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, - } - - /lodash.truncate/4.4.2: - resolution: - { - integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==, - } - - /lodash/4.17.21_ehchni3mpmovsvjxesffg2i5a4: - resolution: - { - integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, - } - dev: false - patched: true - - /loose-envify/1.4.0: - resolution: - { - integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, - } - hasBin: true - dependencies: - js-tokens: 4.0.0 - - /lru-cache/6.0.0: - resolution: - { - integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, - } - engines: { node: ">=10" } - dependencies: - yallist: 4.0.0 - - /merge2/1.4.1: - resolution: - { - integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, - } - engines: { node: ">= 8" } - dev: false - - /micromatch/4.0.5: - resolution: - { - integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==, - } - engines: { node: ">=8.6" } - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: false - - /minimatch/3.1.2: - resolution: - { - integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, - } - dependencies: - brace-expansion: 1.1.11 - - /minimist/1.2.6: - resolution: - { - integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==, - } - dev: false - - /ms/2.0.0: - resolution: - { - integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, - } - dev: false - - /ms/2.1.2: - resolution: - { - integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, - } - - /ms/2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } - dev: false - - /nanoid/3.3.4: - resolution: - { - integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==, - } - engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } - hasBin: true - dev: false - - /natural-compare/1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, - } - - /next-transpile-modules/9.0.0: - resolution: - { - integrity: sha512-VCNFOazIAnXn1hvgYYSTYMnoWgKgwlYh4lm1pKbSfiB3kj5ZYLcKVhfh3jkPOg1cnd9DP+pte9yCUocdPEUBTQ==, - } - dependencies: - enhanced-resolve: 5.10.0 - escalade: 3.1.1 - dev: true - - /next/12.2.5_ir3quccc6i62x6qn6jjhyjjiey: - resolution: - { - integrity: sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==, - } - engines: { node: ">=12.22.0" } - hasBin: true - peerDependencies: - fibers: ">= 3.1.0" - node-sass: ^6.0.0 || ^7.0.0 - react: ^17.0.2 || ^18.0.0-0 - react-dom: ^17.0.2 || ^18.0.0-0 - sass: ^1.3.0 - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - dependencies: - "@next/env": 12.2.5 - "@swc/helpers": 0.4.3 - caniuse-lite: 1.0.30001399 - postcss: 8.4.14 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - styled-jsx: 5.0.4_3toe27fv7etiytxb5kxc7fxaw4 - use-sync-external-store: 1.2.0_react@18.2.0 - optionalDependencies: - "@next/swc-android-arm-eabi": 12.2.5 - "@next/swc-android-arm64": 12.2.5 - "@next/swc-darwin-arm64": 12.2.5 - "@next/swc-darwin-x64": 12.2.5 - "@next/swc-freebsd-x64": 12.2.5 - "@next/swc-linux-arm-gnueabihf": 12.2.5 - "@next/swc-linux-arm64-gnu": 12.2.5 - "@next/swc-linux-arm64-musl": 12.2.5 - "@next/swc-linux-x64-gnu": 12.2.5 - "@next/swc-linux-x64-musl": 12.2.5 - "@next/swc-win32-arm64-msvc": 12.2.5 - "@next/swc-win32-ia32-msvc": 12.2.5 - "@next/swc-win32-x64-msvc": 12.2.5 - transitivePeerDependencies: - - "@babel/core" - - babel-plugin-macros - dev: false - - /node-releases/2.0.6: - resolution: - { - integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==, - } - - /object-assign/4.1.1: - resolution: - { - integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, - } - engines: { node: ">=0.10.0" } - dev: false - - /object-inspect/1.12.2: - resolution: - { - integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==, - } - dev: false - - /object-keys/1.1.1: - resolution: - { - integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, - } - engines: { node: ">= 0.4" } - dev: false - - /object.assign/4.1.4: - resolution: - { - integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: false - - /object.entries/1.1.5: - resolution: - { - integrity: sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - dev: false - - /object.fromentries/2.0.5: - resolution: - { - integrity: sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - dev: false - - /object.hasown/1.1.1: - resolution: - { - integrity: sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==, - } - dependencies: - define-properties: 1.1.4 - es-abstract: 1.20.2 - dev: false - - /object.values/1.1.5: - resolution: - { - integrity: sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - dev: false - - /once/1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } - dependencies: - wrappy: 1.0.2 - - /optionator/0.9.1: - resolution: - { - integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==, - } - engines: { node: ">= 0.8.0" } - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.3 - - /parent-module/1.0.1: - resolution: - { - integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, - } - engines: { node: ">=6" } - dependencies: - callsites: 3.1.0 - - /path-is-absolute/1.0.1: - resolution: - { - integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, - } - engines: { node: ">=0.10.0" } - - /path-key/3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } - - /path-parse/1.0.7: - resolution: - { - integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, - } - dev: false - - /path-type/4.0.0: - resolution: - { - integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, - } - engines: { node: ">=8" } - dev: false - - /picocolors/1.0.0: - resolution: - { - integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==, - } - - /picomatch/2.3.1: - resolution: - { - integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, - } - engines: { node: ">=8.6" } - dev: false - - /postcss/8.4.14: - resolution: - { - integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==, - } - engines: { node: ^10 || ^12 || >=14 } - dependencies: - nanoid: 3.3.4 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: false - - /prelude-ls/1.2.1: - resolution: - { - integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, - } - engines: { node: ">= 0.8.0" } - - /prettier/2.7.1: - resolution: - { - integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==, - } - engines: { node: ">=10.13.0" } - hasBin: true - dev: true - - /progress/2.0.3: - resolution: - { - integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==, - } - engines: { node: ">=0.4.0" } - - /prop-types/15.8.1: - resolution: - { - integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, - } - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: false - - /punycode/2.1.1: - resolution: - { - integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==, - } - engines: { node: ">=6" } - - /queue-microtask/1.2.3: - resolution: - { - integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, - } - dev: false - - /react-dom/18.2.0_react@18.2.0: - resolution: - { - integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==, - } - peerDependencies: - react: ^18.2.0 - dependencies: - loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 - dev: false - - /react-is/16.13.1: - resolution: - { - integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, - } - dev: false - - /react/18.2.0: - resolution: - { - integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==, - } - engines: { node: ">=0.10.0" } - dependencies: - loose-envify: 1.4.0 - - /regenerator-runtime/0.13.9: - resolution: - { - integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==, - } - dev: false - - /regexp.prototype.flags/1.4.3: - resolution: - { - integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==, - } - engines: { node: ">= 0.4" } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - functions-have-names: 1.2.3 - dev: false - - /regexpp/3.2.0: - resolution: - { - integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==, - } - engines: { node: ">=8" } - - /require-from-string/2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: ">=0.10.0" } - - /resolve-from/4.0.0: - resolution: - { - integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, - } - engines: { node: ">=4" } - - /resolve/1.22.1: - resolution: - { - integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==, - } - hasBin: true - dependencies: - is-core-module: 2.10.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: false - - /resolve/2.0.0-next.4: - resolution: - { - integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==, - } - hasBin: true - dependencies: - is-core-module: 2.10.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: false - - /reusify/1.0.4: - resolution: - { - integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==, - } - engines: { iojs: ">=1.0.0", node: ">=0.10.0" } - dev: false - - /rimraf/3.0.2: - resolution: - { - integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, - } - hasBin: true - dependencies: - glob: 7.2.3 - - /run-parallel/1.2.0: - resolution: - { - integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, - } - dependencies: - queue-microtask: 1.2.3 - dev: false - - /safe-buffer/5.1.2: - resolution: - { - integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, - } - - /scheduler/0.23.0: - resolution: - { - integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==, - } - dependencies: - loose-envify: 1.4.0 - dev: false - - /semver/6.3.0: - resolution: - { - integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==, - } - hasBin: true - - /semver/7.3.7: - resolution: - { - integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==, - } - engines: { node: ">=10" } - hasBin: true - dependencies: - lru-cache: 6.0.0 - - /shebang-command/2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } - dependencies: - shebang-regex: 3.0.0 - - /shebang-regex/3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } - - /side-channel/1.0.4: - resolution: - { - integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==, - } - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - object-inspect: 1.12.2 - dev: false - - /slash/3.0.0: - resolution: - { - integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, - } - engines: { node: ">=8" } - dev: false - - /slice-ansi/4.0.0: - resolution: - { - integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==, - } - engines: { node: ">=10" } - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - - /source-map-js/1.0.2: - resolution: - { - integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==, - } - engines: { node: ">=0.10.0" } - dev: false - - /sprintf-js/1.0.3: - resolution: - { - integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, - } - - /string-width/4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: ">=8" } - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - /string.prototype.matchall/4.0.7: - resolution: - { - integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==, - } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - get-intrinsic: 1.1.3 - has-symbols: 1.0.3 - internal-slot: 1.0.3 - regexp.prototype.flags: 1.4.3 - side-channel: 1.0.4 - dev: false - - /string.prototype.trimend/1.0.5: - resolution: - { - integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==, - } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - dev: false - - /string.prototype.trimstart/1.0.5: - resolution: - { - integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==, - } - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.2 - dev: false - - /strip-ansi/6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: ">=8" } - dependencies: - ansi-regex: 5.0.1 - - /strip-bom/3.0.0: - resolution: - { - integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, - } - engines: { node: ">=4" } - dev: false - - /strip-json-comments/3.1.1: - resolution: - { - integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, - } - engines: { node: ">=8" } - - /styled-jsx/5.0.4_3toe27fv7etiytxb5kxc7fxaw4: - resolution: - { - integrity: sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==, - } - engines: { node: ">= 12.0.0" } - peerDependencies: - "@babel/core": "*" - babel-plugin-macros: "*" - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" - peerDependenciesMeta: - "@babel/core": - optional: true - babel-plugin-macros: - optional: true - dependencies: - "@babel/core": 7.19.1 - react: 18.2.0 - dev: false - - /supports-color/5.5.0: - resolution: - { - integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, - } - engines: { node: ">=4" } - dependencies: - has-flag: 3.0.0 - - /supports-color/7.2.0: - resolution: - { - integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, - } - engines: { node: ">=8" } - dependencies: - has-flag: 4.0.0 - - /supports-preserve-symlinks-flag/1.0.0: - resolution: - { - integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, - } - engines: { node: ">= 0.4" } - dev: false - - /table/6.8.0: - resolution: - { - integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==, - } - engines: { node: ">=10.0.0" } - dependencies: - ajv: 8.11.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /tapable/2.2.1: - resolution: - { - integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==, - } - engines: { node: ">=6" } - dev: true - - /text-table/0.2.0: - resolution: - { - integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==, - } - - /to-fast-properties/2.0.0: - resolution: - { - integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==, - } - engines: { node: ">=4" } - - /to-regex-range/5.0.1: - resolution: - { - integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, - } - engines: { node: ">=8.0" } - dependencies: - is-number: 7.0.0 - dev: false - - /tsconfig-paths/3.14.1: - resolution: - { - integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==, - } - dependencies: - "@types/json5": 0.0.29 - json5: 1.0.1 - minimist: 1.2.6 - strip-bom: 3.0.0 - dev: false - - /tslib/1.14.1: - resolution: - { - integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==, - } - dev: false - - /tslib/2.4.0: - resolution: - { - integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==, - } - dev: false - - /tsutils/3.21.0_typescript@4.8.3: - resolution: - { - integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==, - } - engines: { node: ">= 6" } - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - dependencies: - tslib: 1.14.1 - typescript: 4.8.3 - dev: false - - /turbo-android-arm64/1.4.6: - resolution: - { - integrity: sha512-YxSlHc64CF5J7yNUMiLBHkeLyzrpe75Oy7tivWb3z7ySG44BXPikk4HDJZPh0T1ELvukDwuPKkvDukJ2oCLJpA==, - } - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-64/1.4.6: - resolution: - { - integrity: sha512-f6uto7LLpjwZ6iZSF+8uaDpuiTji6xmnWDxNuW23DBE8iv5mxehHd+6Ys851uKDRrPb3QdCu9ctyigKTAla5Vg==, - } - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64/1.4.6: - resolution: - { - integrity: sha512-o9C6e5XyuMHQwE0fEhUxfpXxvNr2QXXWX8nxIjygxeF19AqKbk/s08vZBOEmXV6/gx/pRhZ1S2nf0PIUjKBD/Q==, - } - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-freebsd-64/1.4.6: - resolution: - { - integrity: sha512-Gg9VOUo6McXYKGevcYjGUSmMryZyZggvpdPh7Dw3QTcT8Tsy6OBtq6WnJ2O4kFDsMigyKtEOJPceD9vDMZt3yQ==, - } - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /turbo-freebsd-arm64/1.4.6: - resolution: - { - integrity: sha512-W7VrcneWFN1QENKt5cpAPSsf9ArYBBAm3VtPBZEO5tX8kuahGlah1SKdKJXrRxYOY82wyNxDagS/rHpBlrAAzw==, - } - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-32/1.4.6: - resolution: - { - integrity: sha512-76j/zsui6mWPX8pZVMGgF8eiKHPmKuGa2lo0A/Ja0HUvdYCOGUfHsWJGVVIeYbuEp3jsKyVt7OnMDeH9CqO6bg==, - } - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64/1.4.6: - resolution: - { - integrity: sha512-z4A37Xm7lZyO9ddtGnvQHWMrsAKX6vFBxdbtb9MY76VRblo7lWSuk4LwCeM+T+ZDJ9LBFiF7aD/diRShlLx9jA==, - } - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm/1.4.6: - resolution: - { - integrity: sha512-Uh/V3oaAdhyZW6FKPpKihAxQo3EbvLaVNnzzkBmBnvHRkqoDJHhpuG72V7nn8pzxVbJ1++NEVjvbc2kmKFvGjg==, - } - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64/1.4.6: - resolution: - { - integrity: sha512-FW1jmOpZfOoVVvml338N0MPnYjiMyYWTaMb4T+IosgGYymcUE3xJjfXJcqfU/9/uKTyY8zG0qr9/5rw2kpMS2Q==, - } - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-mips64le/1.4.6: - resolution: - { - integrity: sha512-iWaL3Pwj52BH3T2M8nXScmbSnq4+x47MYK7lJMG7FsZGAIoT5ToO1Wt1iX3GRHTcnIZYm/kCfJ1ptK/NCossLA==, - } - cpu: [mipsel] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-ppc64le/1.4.6: - resolution: - { - integrity: sha512-Af/KlUmpiORDyELxT7byXNWl3fefErGQMJfeqXEtAdhs8OCKQWuU+lchcZbiBZYNpL+lZoa3PAmP9Fpx7R4plA==, - } - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-32/1.4.6: - resolution: - { - integrity: sha512-NBd+XPlRSaR//lVN13Q9DOqK3CbowSvafIyGsO4jfvMsGTdyNDL6AYtFsvTKW91/G7ZhATmSEkPn2pZRuhP/DA==, - } - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64/1.4.6: - resolution: - { - integrity: sha512-86AbmG+CjzVTpn4RGtwU2CYy4zSyAc9bIQ4pDGLIpCJg6JlD11duaiMJh0SCU/HCqWLJjWDI4qD+f9WNbgPsyQ==, - } - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64/1.4.6: - resolution: - { - integrity: sha512-V+pWcqhTtmQQ3ew8qEjYtUwzyW6tO1RgvP+6OKzItYzTnMTr1Fe42Q21V+tqRNxuNfFDKsgVJdk2p5wB87bvyQ==, - } - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo/1.4.6: - resolution: - { - integrity: sha512-FKtBXlOJ7YjSK22yj4sJLCtDcHFElypt7xw9cZN7Wyv9x4XBrTmh5KP6RmcGnRR1/GJlTNwD2AY2T9QTPnHh+g==, - } - hasBin: true - requiresBuild: true - optionalDependencies: - turbo-android-arm64: 1.4.6 - turbo-darwin-64: 1.4.6 - turbo-darwin-arm64: 1.4.6 - turbo-freebsd-64: 1.4.6 - turbo-freebsd-arm64: 1.4.6 - turbo-linux-32: 1.4.6 - turbo-linux-64: 1.4.6 - turbo-linux-arm: 1.4.6 - turbo-linux-arm64: 1.4.6 - turbo-linux-mips64le: 1.4.6 - turbo-linux-ppc64le: 1.4.6 - turbo-windows-32: 1.4.6 - turbo-windows-64: 1.4.6 - turbo-windows-arm64: 1.4.6 - dev: true - - /type-check/0.4.0: - resolution: - { - integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, - } - engines: { node: ">= 0.8.0" } - dependencies: - prelude-ls: 1.2.1 - - /type-fest/0.20.2: - resolution: - { - integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==, - } - engines: { node: ">=10" } - - /typescript/4.8.3: - resolution: - { - integrity: sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==, - } - engines: { node: ">=4.2.0" } - hasBin: true - - /unbox-primitive/1.0.2: - resolution: - { - integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==, - } - dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: false - - /underscore/1.13.4_3pbfs36izefyn2uycmknwkvuuy: - resolution: - { - integrity: sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==, - } - dev: false - patched: true - - /update-browserslist-db/1.0.9_browserslist@4.21.3: - resolution: - { - integrity: sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==, - } - hasBin: true - peerDependencies: - browserslist: ">= 4.21.0" - dependencies: - browserslist: 4.21.3 - escalade: 3.1.1 - picocolors: 1.0.0 - - /uri-js/4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } - dependencies: - punycode: 2.1.1 - - /use-sync-external-store/1.2.0_react@18.2.0: - resolution: - { - integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==, - } - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - react: 18.2.0 - dev: false - - /v8-compile-cache/2.3.0: - resolution: - { - integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==, - } - - /which-boxed-primitive/1.0.2: - resolution: - { - integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==, - } - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: false - - /which/2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } - hasBin: true - dependencies: - isexe: 2.0.0 - - /word-wrap/1.2.3: - resolution: - { - integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==, - } - engines: { node: ">=0.10.0" } - - /wrappy/1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } - - /yallist/4.0.0: - resolution: - { - integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, - } - - file:packages/ui: - resolution: { directory: packages/ui, type: directory } - name: ui - version: 0.0.0 - dev: false - - github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6: - resolution: - { - tarball: https://codeload.github.com/peerigon/dashboard-icons/tar.gz/ce27ef933144e09cef3911025f3649040a8571b, - } - name: dashboard-icons - version: 1.0.0 - dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm8.yaml b/crates/turborepo-lockfiles/fixtures/pnpm8.yaml deleted file mode 100644 index d7d9e274d60fd..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm8.yaml +++ /dev/null @@ -1,107 +0,0 @@ -lockfileVersion: "6.0" - -patchedDependencies: - is-even@1.0.0: - hash: trwuddosrpxsvtoqztvint6pca - path: patches/is-even@1.0.0.patch - -importers: - .: {} - - packages/a: - dependencies: - c: - specifier: workspace:* - version: link:../c - is-odd: - specifier: ^3.0.1 - version: 3.0.1 - - packages/b: - dependencies: - c: - specifier: workspace:* - version: link:../c - is-even: - specifier: ^1.0.0 - version: 1.0.0_trwuddosrpxsvtoqztvint6pca - - packages/c: - dependencies: - lodash: - specifier: ^4.17.21 - version: 4.17.21 - -packages: - /is-buffer@1.1.6: - resolution: - { - integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==, - } - dev: false - - /is-even@1.0.0_trwuddosrpxsvtoqztvint6pca: - resolution: - { - integrity: sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==, - } - engines: { node: ">=0.10.0" } - dependencies: - is-odd: 0.1.2 - dev: false - patched: true - - /is-number@3.0.0: - resolution: - { - integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==, - } - engines: { node: ">=0.10.0" } - dependencies: - kind-of: 3.2.2 - dev: false - - /is-number@6.0.0: - resolution: - { - integrity: sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==, - } - engines: { node: ">=0.10.0" } - dev: false - - /is-odd@0.1.2: - resolution: - { - integrity: sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==, - } - engines: { node: ">=0.10.0" } - dependencies: - is-number: 3.0.0 - dev: false - - /is-odd@3.0.1: - resolution: - { - integrity: sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==, - } - engines: { node: ">=4" } - dependencies: - is-number: 6.0.0 - dev: false - - /kind-of@3.2.2: - resolution: - { - integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==, - } - engines: { node: ">=0.10.0" } - dependencies: - is-buffer: 1.1.6 - dev: false - - /lodash@4.17.21: - resolution: - { - integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, - } - dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm8turbo.yaml b/crates/turborepo-lockfiles/fixtures/pnpm8turbo.yaml deleted file mode 100644 index bbc4f50fd09b2..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/pnpm8turbo.yaml +++ /dev/null @@ -1,96 +0,0 @@ -lockfileVersion: "6.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: - devDependencies: - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/web: {} - -packages: - /turbo-darwin-64@2.0.3: - resolution: - { - integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==, - } - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: - { - integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==, - } - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: - { - integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==, - } - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: - { - integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==, - } - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: - { - integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==, - } - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: - { - integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==, - } - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: - { - integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==, - } - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true diff --git a/crates/turborepo-lockfiles/fixtures/robust-berry-resolutions.lock b/crates/turborepo-lockfiles/fixtures/robust-berry-resolutions.lock deleted file mode 100644 index cfab2c47d2593..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/robust-berry-resolutions.lock +++ /dev/null @@ -1,3160 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"@ampproject/remapping@npm:^2.1.0": - version: 2.2.0 - resolution: "@ampproject/remapping@npm:2.2.0" - dependencies: - "@jridgewell/gen-mapping": ^0.1.0 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: d74d170d06468913921d72430259424b7e4c826b5a7d39ff839a29d547efb97dc577caa8ba3fb5cf023624e9af9d09651afc3d4112a45e2050328abc9b3a2292 - languageName: node - linkType: hard - -"@babel/code-frame@npm:7.12.11": - version: 7.12.11 - resolution: "@babel/code-frame@npm:7.12.11" - dependencies: - "@babel/highlight": ^7.10.4 - checksum: 3963eff3ebfb0e091c7e6f99596ef4b258683e4ba8a134e4e95f77afe85be5c931e184fff6435fb4885d12eba04a5e25532f7fbc292ca13b48e7da943474e2f3 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/code-frame@npm:7.18.6" - dependencies: - "@babel/highlight": ^7.18.6 - checksum: 195e2be3172d7684bf95cff69ae3b7a15a9841ea9d27d3c843662d50cdd7d6470fd9c8e64be84d031117e4a4083486effba39f9aef6bbb2c89f7f21bcfba33ba - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.20.0": - version: 7.20.1 - resolution: "@babel/compat-data@npm:7.20.1" - checksum: 989b9b7a6fe43c547bb8329241bd0ba6983488b83d29cc59de35536272ee6bb4cc7487ba6c8a4bceebb3a57f8c5fea1434f80bbbe75202bc79bc1110f955ff25 - languageName: node - linkType: hard - -"@babel/core@npm:^7.0.0": - version: 7.20.2 - resolution: "@babel/core@npm:7.20.2" - dependencies: - "@ampproject/remapping": ^2.1.0 - "@babel/code-frame": ^7.18.6 - "@babel/generator": ^7.20.2 - "@babel/helper-compilation-targets": ^7.20.0 - "@babel/helper-module-transforms": ^7.20.2 - "@babel/helpers": ^7.20.1 - "@babel/parser": ^7.20.2 - "@babel/template": ^7.18.10 - "@babel/traverse": ^7.20.1 - "@babel/types": ^7.20.2 - convert-source-map: ^1.7.0 - debug: ^4.1.0 - gensync: ^1.0.0-beta.2 - json5: ^2.2.1 - semver: ^6.3.0 - checksum: 98faaaef26103a276a30a141b951a93bc8418d100d1f668bf7a69d12f3e25df57958e8b6b9100d95663f720db62da85ade736f6629a5ebb1e640251a1b43c0e4 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.20.1, @babel/generator@npm:^7.20.2": - version: 7.20.4 - resolution: "@babel/generator@npm:7.20.4" - dependencies: - "@babel/types": ^7.20.2 - "@jridgewell/gen-mapping": ^0.3.2 - jsesc: ^2.5.1 - checksum: 967b59f18e5ce999e5a741825bcecb2be4bbfc1824a92c21b47d0b5694e0eb09314a70f8b9142e9591c149c7fb83d51f73ae8fbd96d30a42666425889e51ceb1 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.20.0": - version: 7.20.0 - resolution: "@babel/helper-compilation-targets@npm:7.20.0" - dependencies: - "@babel/compat-data": ^7.20.0 - "@babel/helper-validator-option": ^7.18.6 - browserslist: ^4.21.3 - semver: ^6.3.0 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: bc183f2109648849c8fde0b3c5cf08adf2f7ad6dc617b546fd20f34c8ef574ee5ee293c8d1bd0ed0221212e8f5907cdc2c42097870f1dcc769a654107d82c95b - languageName: node - linkType: hard - -"@babel/helper-environment-visitor@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/helper-environment-visitor@npm:7.18.9" - checksum: b25101f6162ddca2d12da73942c08ad203d7668e06663df685634a8fde54a98bc015f6f62938e8554457a592a024108d45b8f3e651fd6dcdb877275b73cc4420 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helper-function-name@npm:7.19.0" - dependencies: - "@babel/template": ^7.18.10 - "@babel/types": ^7.19.0 - checksum: eac1f5db428ba546270c2b8d750c24eb528b8fcfe50c81de2e0bdebf0e20f24bec688d4331533b782e4a907fad435244621ca2193cfcf80a86731299840e0f6e - languageName: node - linkType: hard - -"@babel/helper-hoist-variables@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-hoist-variables@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: fd9c35bb435fda802bf9ff7b6f2df06308a21277c6dec2120a35b09f9de68f68a33972e2c15505c1a1a04b36ec64c9ace97d4a9e26d6097b76b4396b7c5fa20f - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-module-imports@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: f393f8a3b3304b1b7a288a38c10989de754f01d29caf62ce7c4e5835daf0a27b81f3ac687d9d2780d39685aae7b55267324b512150e7b2be967b0c493b6a1def - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.20.2": - version: 7.20.2 - resolution: "@babel/helper-module-transforms@npm:7.20.2" - dependencies: - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-module-imports": ^7.18.6 - "@babel/helper-simple-access": ^7.20.2 - "@babel/helper-split-export-declaration": ^7.18.6 - "@babel/helper-validator-identifier": ^7.19.1 - "@babel/template": ^7.18.10 - "@babel/traverse": ^7.20.1 - "@babel/types": ^7.20.2 - checksum: 33a60ca115f6fce2c9d98e2a2e5649498aa7b23e2ae3c18745d7a021487708fc311458c33542f299387a0da168afccba94116e077f2cce49ae9e5ab83399e8a2 - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.20.2": - version: 7.20.2 - resolution: "@babel/helper-simple-access@npm:7.20.2" - dependencies: - "@babel/types": ^7.20.2 - checksum: ad1e96ee2e5f654ffee2369a586e5e8d2722bf2d8b028a121b4c33ebae47253f64d420157b9f0a8927aea3a9e0f18c0103e74fdd531815cf3650a0a4adca11a1 - languageName: node - linkType: hard - -"@babel/helper-split-export-declaration@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-split-export-declaration@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: c6d3dede53878f6be1d869e03e9ffbbb36f4897c7cc1527dc96c56d127d834ffe4520a6f7e467f5b6f3c2843ea0e81a7819d66ae02f707f6ac057f3d57943a2b - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.19.4": - version: 7.19.4 - resolution: "@babel/helper-string-parser@npm:7.19.4" - checksum: b2f8a3920b30dfac81ec282ac4ad9598ea170648f8254b10f475abe6d944808fb006aab325d3eb5a8ad3bea8dfa888cfa6ef471050dae5748497c110ec060943 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.18.6, @babel/helper-validator-identifier@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/helper-validator-identifier@npm:7.19.1" - checksum: 0eca5e86a729162af569b46c6c41a63e18b43dbe09fda1d2a3c8924f7d617116af39cac5e4cd5d431bb760b4dca3c0970e0c444789b1db42bcf1fa41fbad0a3a - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-validator-option@npm:7.18.6" - checksum: f9cc6eb7cc5d759c5abf006402180f8d5e4251e9198197428a97e05d65eb2f8ae5a0ce73b1dfd2d35af41d0eb780627a64edf98a4e71f064eeeacef8de58f2cf - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.20.1": - version: 7.20.1 - resolution: "@babel/helpers@npm:7.20.1" - dependencies: - "@babel/template": ^7.18.10 - "@babel/traverse": ^7.20.1 - "@babel/types": ^7.20.0 - checksum: be35f78666bdab895775ed94dbeb098f7b4fa08ce4cfb0c3a9e69b7220cce56960dcdc2b14f5df9d3b80388d4bf7df155c97f6cf6768c0138f4e6931d0f44955 - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.10.4, @babel/highlight@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/highlight@npm:7.18.6" - dependencies: - "@babel/helper-validator-identifier": ^7.18.6 - chalk: ^2.0.0 - js-tokens: ^4.0.0 - checksum: 92d8ee61549de5ff5120e945e774728e5ccd57fd3b2ed6eace020ec744823d4a98e242be1453d21764a30a14769ecd62170fba28539b211799bbaf232bbb2789 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.18.10, @babel/parser@npm:^7.20.1, @babel/parser@npm:^7.20.2": - version: 7.20.3 - resolution: "@babel/parser@npm:7.20.3" - bin: - parser: ./bin/babel-parser.js - checksum: 33bcdb45de65a3cf27ed376cb34f32be3c3485a10e3252f8d0126f6a034efc3145c0d219e57fcd5a8956361552008bc30b9bae4a723823fb3633027071be8a45 - languageName: node - linkType: hard - -"@babel/runtime-corejs3@npm:^7.10.2": - version: 7.20.1 - resolution: "@babel/runtime-corejs3@npm:7.20.1" - dependencies: - core-js-pure: ^3.25.1 - regenerator-runtime: ^0.13.10 - checksum: bac1463304deb0e395f78aef2bf0e042d0ae303285b9f55e443d8ce4d3d05ccb92ac0aa5ca4bf83526695d21b12a239317537b00918d6ebf7a4132e5ec2f6f33 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.18.9": - version: 7.20.1 - resolution: "@babel/runtime@npm:7.20.1" - dependencies: - regenerator-runtime: ^0.13.10 - checksum: 00567a333d3357925742a6f5e39394dcc0af6e6029103fe188158bf7ae8b0b3ee3c6c0f68fccc217f0a6cfa455f6be252298baf56b3f5ff37b34313b170cd9f6 - languageName: node - linkType: hard - -"@babel/template@npm:^7.18.10": - version: 7.18.10 - resolution: "@babel/template@npm:7.18.10" - dependencies: - "@babel/code-frame": ^7.18.6 - "@babel/parser": ^7.18.10 - "@babel/types": ^7.18.10 - checksum: 93a6aa094af5f355a72bd55f67fa1828a046c70e46f01b1606e6118fa1802b6df535ca06be83cc5a5e834022be95c7b714f0a268b5f20af984465a71e28f1473 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.20.1": - version: 7.20.1 - resolution: "@babel/traverse@npm:7.20.1" - dependencies: - "@babel/code-frame": ^7.18.6 - "@babel/generator": ^7.20.1 - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-function-name": ^7.19.0 - "@babel/helper-hoist-variables": ^7.18.6 - "@babel/helper-split-export-declaration": ^7.18.6 - "@babel/parser": ^7.20.1 - "@babel/types": ^7.20.0 - debug: ^4.1.0 - globals: ^11.1.0 - checksum: 6696176d574b7ff93466848010bc7e94b250169379ec2a84f1b10da46a7cc2018ea5e3a520c3078487db51e3a4afab9ecff48f25d1dbad8c1319362f4148fb4b - languageName: node - linkType: hard - -"@babel/types@npm:^7.18.10, @babel/types@npm:^7.18.6, @babel/types@npm:^7.19.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.2, @babel/types@npm:^7.8.3": - version: 7.20.2 - resolution: "@babel/types@npm:7.20.2" - dependencies: - "@babel/helper-string-parser": ^7.19.4 - "@babel/helper-validator-identifier": ^7.19.1 - to-fast-properties: ^2.0.0 - checksum: 57e76e5f21876135f481bfd4010c87f2d38196bb0a2bc60a28d6e55e3afa90cdd9accf164e4cb71bdfb620517fa0a0cb5600cdce36c21d59fdaccfbb899c024c - languageName: node - linkType: hard - -"@eslint/eslintrc@npm:^0.4.3": - version: 0.4.3 - resolution: "@eslint/eslintrc@npm:0.4.3" - dependencies: - ajv: ^6.12.4 - debug: ^4.1.1 - espree: ^7.3.0 - globals: ^13.9.0 - ignore: ^4.0.6 - import-fresh: ^3.2.1 - js-yaml: ^3.13.1 - minimatch: ^3.0.4 - strip-json-comments: ^3.1.1 - checksum: 03a7704150b868c318aab6a94d87a33d30dc2ec579d27374575014f06237ba1370ae11178db772f985ef680d469dc237e7b16a1c5d8edaaeb8c3733e7a95a6d3 - languageName: node - linkType: hard - -"@humanwhocodes/config-array@npm:^0.5.0": - version: 0.5.0 - resolution: "@humanwhocodes/config-array@npm:0.5.0" - dependencies: - "@humanwhocodes/object-schema": ^1.2.0 - debug: ^4.1.1 - minimatch: ^3.0.4 - checksum: 44ee6a9f05d93dd9d5935a006b17572328ba9caff8002442f601736cbda79c580cc0f5a49ce9eb88fbacc5c3a6b62098357c2e95326cd17bb9f1a6c61d6e95e7 - languageName: node - linkType: hard - -"@humanwhocodes/object-schema@npm:^1.2.0": - version: 1.2.1 - resolution: "@humanwhocodes/object-schema@npm:1.2.1" - checksum: a824a1ec31591231e4bad5787641f59e9633827d0a2eaae131a288d33c9ef0290bd16fda8da6f7c0fcb014147865d12118df10db57f27f41e20da92369fcb3f1 - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.1.0": - version: 0.1.1 - resolution: "@jridgewell/gen-mapping@npm:0.1.1" - dependencies: - "@jridgewell/set-array": ^1.0.0 - "@jridgewell/sourcemap-codec": ^1.4.10 - checksum: 3bcc21fe786de6ffbf35c399a174faab05eb23ce6a03e8769569de28abbf4facc2db36a9ddb0150545ae23a8d35a7cf7237b2aa9e9356a7c626fb4698287d5cc - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.2 - resolution: "@jridgewell/gen-mapping@npm:0.3.2" - dependencies: - "@jridgewell/set-array": ^1.0.1 - "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 1832707a1c476afebe4d0fbbd4b9434fdb51a4c3e009ab1e9938648e21b7a97049fa6009393bdf05cab7504108413441df26d8a3c12193996e65493a4efb6882 - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:3.1.0": - version: 3.1.0 - resolution: "@jridgewell/resolve-uri@npm:3.1.0" - checksum: b5ceaaf9a110fcb2780d1d8f8d4a0bfd216702f31c988d8042e5f8fbe353c55d9b0f55a1733afdc64806f8e79c485d2464680ac48a0d9fcadb9548ee6b81d267 - languageName: node - linkType: hard - -"@jridgewell/set-array@npm:^1.0.0, @jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.14 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" - checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.17 - resolution: "@jridgewell/trace-mapping@npm:0.3.17" - dependencies: - "@jridgewell/resolve-uri": 3.1.0 - "@jridgewell/sourcemap-codec": 1.4.14 - checksum: 9d703b859cff5cd83b7308fd457a431387db5db96bd781a63bf48e183418dd9d3d44e76b9e4ae13237f6abeeb25d739ec9215c1d5bfdd08f66f750a50074a339 - languageName: node - linkType: hard - -"@next/env@npm:13.0.0": - version: 13.0.0 - resolution: "@next/env@npm:13.0.0" - checksum: 3146f10324366283c22bce0b700a8ae6c7dffad63cb81d698300c1795e7121d1fa0c2b6e0cbf7f7614117b0c3aa15556e88a7727a7b0e59aed054c2dfecb7d58 - languageName: node - linkType: hard - -"@next/eslint-plugin-next@npm:13.0.0": - version: 13.0.0 - resolution: "@next/eslint-plugin-next@npm:13.0.0" - dependencies: - glob: 7.1.7 - checksum: 03d3e359165e477978baa4862d88ffe6e4a1d0d944b7e3dc93c1d426b9769fdef6f115b1ac2933c95bdaa3d760667225935736523445330ed9c5b2d62bc055a5 - languageName: node - linkType: hard - -"@next/swc-android-arm-eabi@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-android-arm-eabi@npm:13.0.0" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@next/swc-android-arm64@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-android-arm64@npm:13.0.0" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-darwin-arm64@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-darwin-arm64@npm:13.0.0" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-darwin-x64@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-darwin-x64@npm:13.0.0" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@next/swc-freebsd-x64@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-freebsd-x64@npm:13.0.0" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@next/swc-linux-arm-gnueabihf@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-linux-arm-gnueabihf@npm:13.0.0" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@next/swc-linux-arm64-gnu@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-linux-arm64-gnu@npm:13.0.0" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-arm64-musl@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-linux-arm64-musl@npm:13.0.0" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-linux-x64-gnu@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-linux-x64-gnu@npm:13.0.0" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-x64-musl@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-linux-x64-musl@npm:13.0.0" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-win32-arm64-msvc@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-win32-arm64-msvc@npm:13.0.0" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-win32-ia32-msvc@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-win32-ia32-msvc@npm:13.0.0" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@next/swc-win32-x64-msvc@npm:13.0.0": - version: 13.0.0 - resolution: "@next/swc-win32-x64-msvc@npm:13.0.0" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@nodelib/fs.scandir@npm:2.1.5": - version: 2.1.5 - resolution: "@nodelib/fs.scandir@npm:2.1.5" - dependencies: - "@nodelib/fs.stat": 2.0.5 - run-parallel: ^1.1.9 - checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 - languageName: node - linkType: hard - -"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.5 - resolution: "@nodelib/fs.stat@npm:2.0.5" - checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 - languageName: node - linkType: hard - -"@nodelib/fs.walk@npm:^1.2.3": - version: 1.2.8 - resolution: "@nodelib/fs.walk@npm:1.2.8" - dependencies: - "@nodelib/fs.scandir": 2.1.5 - fastq: ^1.6.0 - checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 - languageName: node - linkType: hard - -"@rushstack/eslint-patch@npm:^1.1.3": - version: 1.2.0 - resolution: "@rushstack/eslint-patch@npm:1.2.0" - checksum: faa749faae0e83c26ae9eb00ad36a897ac78f3cf27da8e8ff21c00bcf7973b598d823d8f2b3957ef66079288bcf577f94df831eae2d65f3f68d8ca32f18b6aff - languageName: node - linkType: hard - -"@swc/helpers@npm:0.4.11": - version: 0.4.11 - resolution: "@swc/helpers@npm:0.4.11" - dependencies: - tslib: ^2.4.0 - checksum: 736857d524b41a8a4db81094e9b027f554004e0fa3e86325d85bdb38f7e6459ce022db079edb6c61ba0f46fe8583b3e663e95f7acbd13e51b8da6c34e45bba2e - languageName: node - linkType: hard - -"@types/json5@npm:^0.0.29": - version: 0.0.29 - resolution: "@types/json5@npm:0.0.29" - checksum: e60b153664572116dfea673c5bda7778dbff150498f44f998e34b5886d8afc47f16799280e4b6e241c0472aef1bc36add771c569c68fc5125fc2ae519a3eb9ac - languageName: node - linkType: hard - -"@types/node@npm:^17.0.12": - version: 17.0.45 - resolution: "@types/node@npm:17.0.45" - checksum: aa04366b9103b7d6cfd6b2ef64182e0eaa7d4462c3f817618486ea0422984c51fc69fd0d436eae6c9e696ddfdbec9ccaa27a917f7c2e8c75c5d57827fe3d95e8 - languageName: node - linkType: hard - -"@types/prop-types@npm:*": - version: 15.7.5 - resolution: "@types/prop-types@npm:15.7.5" - checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 - languageName: node - linkType: hard - -"@types/react-dom@npm:^17.0.11": - version: 17.0.18 - resolution: "@types/react-dom@npm:17.0.18" - dependencies: - "@types/react": ^17 - checksum: b74525b1a13a0e27fe20859ff7a7e8f7e4581fb9d45ed1b6447ad1534d86f813818353c39d0df2e28f9d2b9be2e3af1908c244b2214a979393d19f217665e614 - languageName: node - linkType: hard - -"@types/react-dom@npm:^18.0.7": - version: 18.0.9 - resolution: "@types/react-dom@npm:18.0.9" - dependencies: - "@types/react": "*" - checksum: e744e3feba25fc43733289d4df4d9c0e59fcca7f34e8c89d75f81a339accb2bd70236d69382d47d2c0ad06a1529b2e56aa6171fe175854d60e07156ddceedfcb - languageName: node - linkType: hard - -"@types/react@npm:*, @types/react@npm:^18.0.22": - version: 18.0.25 - resolution: "@types/react@npm:18.0.25" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: 231d658c45abdef044a716b4502774f1585d8336d73b2f5bd68f181acbfc874b7a457686ecd29b415b43ed0922c309bab7e2cf96832d188a3f4f1b02f2af760a - languageName: node - linkType: hard - -"@types/react@npm:^17, @types/react@npm:^17.0.37": - version: 17.0.52 - resolution: "@types/react@npm:17.0.52" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: a51b98dd87838d161278fdf9dd78e6a4ff8c018f406d6647f77963e144fb52a8beee40c89fd0e7e840eaeaa8bd9fe2f34519410540b1a52d43a6f8b4d2fbce33 - languageName: node - linkType: hard - -"@types/scheduler@npm:*": - version: 0.16.2 - resolution: "@types/scheduler@npm:0.16.2" - checksum: b6b4dcfeae6deba2e06a70941860fb1435730576d3689225a421280b7742318d1548b3d22c1f66ab68e414f346a9542f29240bc955b6332c5b11e561077583bc - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^5.21.0": - version: 5.44.0 - resolution: "@typescript-eslint/parser@npm:5.44.0" - dependencies: - "@typescript-eslint/scope-manager": 5.44.0 - "@typescript-eslint/types": 5.44.0 - "@typescript-eslint/typescript-estree": 5.44.0 - debug: ^4.3.4 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 2d09a1a1547a7ae3f76c9a33a54e11d79a194fbb9dbae69988e7aed3370bdf12bafde669211152769d89db822e0cdee4173affc126664fa6f17abba56daa7261 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:5.44.0": - version: 5.44.0 - resolution: "@typescript-eslint/scope-manager@npm:5.44.0" - dependencies: - "@typescript-eslint/types": 5.44.0 - "@typescript-eslint/visitor-keys": 5.44.0 - checksum: 4cfe4b55eb428eda740e6b967e3a87f3e1f9c4bbd8e1d6b8d64a11666abe33ffe7a21e4e614444ccde2da6930fa85f3e0ffca43d6e339943ff7a4fbccb09c8fc - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.44.0": - version: 5.44.0 - resolution: "@typescript-eslint/types@npm:5.44.0" - checksum: ced7d32abecfc62ccb67cf27e30c0785b9c153ec7b1a05153ced58fa5a2031ab3845bc2e477b83e4cebdcc5881c5845d23053c6739c62549d41ae6208e547e85 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.44.0": - version: 5.44.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.44.0" - dependencies: - "@typescript-eslint/types": 5.44.0 - "@typescript-eslint/visitor-keys": 5.44.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.3.7 - tsutils: ^3.21.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 758731108497cca7ff81cf0a78d086b5a85757a983979d6bb25ad8252b7acbc738c642ecb5f5df82f925a45926b9846e431d5cf9fee5ed2613300b4d0c5d6c3f - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.44.0": - version: 5.44.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.44.0" - dependencies: - "@typescript-eslint/types": 5.44.0 - eslint-visitor-keys: ^3.3.0 - checksum: a012c888209e1d6ae684b2a44fd460ae5a80f5faf07bca4bda6c9c0d8c063ad3297d4c53f7151ae86cf1a43dee09625dc3ee72183323c91089c7288fd573c6f4 - languageName: node - linkType: hard - -"acorn-jsx@npm:^5.3.1": - version: 5.3.2 - resolution: "acorn-jsx@npm:5.3.2" - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 - languageName: node - linkType: hard - -"acorn@npm:^7.4.0": - version: 7.4.1 - resolution: "acorn@npm:7.4.1" - bin: - acorn: bin/acorn - checksum: 1860f23c2107c910c6177b7b7be71be350db9e1080d814493fae143ae37605189504152d1ba8743ba3178d0b37269ce1ffc42b101547fdc1827078f82671e407 - languageName: node - linkType: hard - -"ajv@npm:^8": - version: 8.11.2 - resolution: "ajv@npm:8.11.2" - dependencies: - fast-deep-equal: ^3.1.1 - json-schema-traverse: ^1.0.0 - require-from-string: ^2.0.2 - uri-js: ^4.2.2 - checksum: 53435bf79ee7d1eabba8085962dba4c08d08593334b304db7772887f0b7beebc1b3d957432f7437ed4b60e53b5d966a57b439869890209c50fed610459999e3e - languageName: node - linkType: hard - -"ansi-colors@npm:^4.1.1": - version: 4.1.3 - resolution: "ansi-colors@npm:4.1.3" - checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b - languageName: node - linkType: hard - -"ansi-styles@npm:^3.2.1": - version: 3.2.1 - resolution: "ansi-styles@npm:3.2.1" - dependencies: - color-convert: ^1.9.0 - checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: ^2.0.1 - checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 - languageName: node - linkType: hard - -"argparse@npm:^1.0.7": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: ~1.0.2 - checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 - languageName: node - linkType: hard - -"aria-query@npm:^4.2.2": - version: 4.2.2 - resolution: "aria-query@npm:4.2.2" - dependencies: - "@babel/runtime": ^7.10.2 - "@babel/runtime-corejs3": ^7.10.2 - checksum: 38401a9a400f26f3dcc24b84997461a16b32869a9893d323602bed8da40a8bcc0243b8d2880e942249a1496cea7a7de769e93d21c0baa439f01e1ee936fed665 - languageName: node - linkType: hard - -"array-includes@npm:^3.1.4, array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": - version: 3.1.6 - resolution: "array-includes@npm:3.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - get-intrinsic: ^1.1.3 - is-string: ^1.0.7 - checksum: f22f8cd8ba8a6448d91eebdc69f04e4e55085d09232b5216ee2d476dab3ef59984e8d1889e662c6a0ed939dcb1b57fd05b2c0209c3370942fc41b752c82a2ca5 - languageName: node - linkType: hard - -"array-union@npm:^2.1.0": - version: 2.1.0 - resolution: "array-union@npm:2.1.0" - checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d - languageName: node - linkType: hard - -"array.prototype.flat@npm:^1.2.5": - version: 1.3.1 - resolution: "array.prototype.flat@npm:1.3.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - checksum: 5a8415949df79bf6e01afd7e8839bbde5a3581300e8ad5d8449dea52639e9e59b26a467665622783697917b43bf39940a6e621877c7dd9b3d1c1f97484b9b88b - languageName: node - linkType: hard - -"array.prototype.flatmap@npm:^1.3.0, array.prototype.flatmap@npm:^1.3.1": - version: 1.3.1 - resolution: "array.prototype.flatmap@npm:1.3.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - checksum: 8c1c43a4995f12cf12523436da28515184c753807b3f0bc2ca6c075f71c470b099e2090cc67dba8e5280958fea401c1d0c59e1db0143272aef6cd1103921a987 - languageName: node - linkType: hard - -"array.prototype.tosorted@npm:^1.1.1": - version: 1.1.1 - resolution: "array.prototype.tosorted@npm:1.1.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.1.3 - checksum: 7923324a67e70a2fc0a6e40237405d92395e45ebd76f5cb89c2a5cf1e66b47aca6baacd0cd628ffd88830b90d47fff268071493d09c9ae123645613dac2c2ca3 - languageName: node - linkType: hard - -"ast-types-flow@npm:^0.0.7": - version: 0.0.7 - resolution: "ast-types-flow@npm:0.0.7" - checksum: a26dcc2182ffee111cad7c471759b0bda22d3b7ebacf27c348b22c55f16896b18ab0a4d03b85b4020dce7f3e634b8f00b593888f622915096ea1927fa51866c4 - languageName: node - linkType: hard - -"astral-regex@npm:^2.0.0": - version: 2.0.0 - resolution: "astral-regex@npm:2.0.0" - checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 - languageName: node - linkType: hard - -"axe-core@npm:^4.4.3": - version: 4.5.2 - resolution: "axe-core@npm:4.5.2" - checksum: 4068f183b2ef1db7e5a75606032c238781abfaa34ab4c23177e17f7dff8cc83f175e887b52689d20d88d2d4f001cbf632bd98925850026fe1d9abc739cabcf16 - languageName: node - linkType: hard - -"axobject-query@npm:^2.2.0": - version: 2.2.0 - resolution: "axobject-query@npm:2.2.0" - checksum: 96b8c7d807ca525f41ad9b286186e2089b561ba63a6d36c3e7d73dc08150714660995c7ad19cda05784458446a0793b45246db45894631e13853f48c1aa3117f - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 - languageName: node - linkType: hard - -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: ^1.0.0 - concat-map: 0.0.1 - checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 - languageName: node - linkType: hard - -"braces@npm:^3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" - dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 - languageName: node - linkType: hard - -"browserslist@npm:^4.21.3": - version: 4.21.4 - resolution: "browserslist@npm:4.21.4" - dependencies: - caniuse-lite: ^1.0.30001400 - electron-to-chromium: ^1.4.251 - node-releases: ^2.0.6 - update-browserslist-db: ^1.0.9 - bin: - browserslist: cli.js - checksum: 4af3793704dbb4615bcd29059ab472344dc7961c8680aa6c4bb84f05340e14038d06a5aead58724eae69455b8fade8b8c69f1638016e87e5578969d74c078b79 - languageName: node - linkType: hard - -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind@npm:1.0.2" - dependencies: - function-bind: ^1.1.1 - get-intrinsic: ^1.0.2 - checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 - languageName: node - linkType: hard - -"callsites@npm:^3.0.0": - version: 3.1.0 - resolution: "callsites@npm:3.1.0" - checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001406": - version: 1.0.30001434 - resolution: "caniuse-lite@npm:1.0.30001434" - checksum: 7c9d2641e8e8f3ddf9af14c4ce47266a9d8fd1fc0243626049ff1b2eca4bf02938ff440813cc3feae3fa8d851ec8d1b9718044340c8d09bb4372d92d4f6b519c - languageName: node - linkType: hard - -"chalk@npm:^2.0.0": - version: 2.4.2 - resolution: "chalk@npm:2.4.2" - dependencies: - ansi-styles: ^3.2.1 - escape-string-regexp: ^1.0.5 - supports-color: ^5.3.0 - checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 - languageName: node - linkType: hard - -"chalk@npm:^4.0.0": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc - languageName: node - linkType: hard - -"client-only@npm:0.0.1": - version: 0.0.1 - resolution: "client-only@npm:0.0.1" - checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8 - languageName: node - linkType: hard - -"color-convert@npm:^1.9.0": - version: 1.9.3 - resolution: "color-convert@npm:1.9.3" - dependencies: - color-name: 1.1.3 - checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: ~1.1.4 - checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 - languageName: node - linkType: hard - -"color-name@npm:1.1.3": - version: 1.1.3 - resolution: "color-name@npm:1.1.3" - checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 - languageName: node - linkType: hard - -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af - languageName: node - linkType: hard - -"convert-source-map@npm:^1.7.0": - version: 1.9.0 - resolution: "convert-source-map@npm:1.9.0" - checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 - languageName: node - linkType: hard - -"core-js-pure@npm:^3.25.1": - version: 3.26.1 - resolution: "core-js-pure@npm:3.26.1" - checksum: d88c40e5e29e413c11d1ef991a8d5b6a63f00bd94707af0f649d3fc18b3524108b202f4ae75ce77620a1557d1ba340bc3362b4f25d590eccc37cf80fc75f7cd4 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.2": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: ^3.1.0 - shebang-command: ^2.0.0 - which: ^2.0.1 - checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 - languageName: node - linkType: hard - -"csstype@npm:^3.0.2": - version: 3.1.1 - resolution: "csstype@npm:3.1.1" - checksum: 1f7b4f5fdd955b7444b18ebdddf3f5c699159f13e9cf8ac9027ae4a60ae226aef9bbb14a6e12ca7dba3358b007cee6354b116e720262867c398de6c955ea451d - languageName: node - linkType: hard - -"damerau-levenshtein@npm:^1.0.8": - version: 1.0.8 - resolution: "damerau-levenshtein@npm:1.0.8" - checksum: d240b7757544460ae0586a341a53110ab0a61126570ef2d8c731e3eab3f0cb6e488e2609e6a69b46727635de49be20b071688698744417ff1b6c1d7ccd03e0de - languageName: node - linkType: hard - -"debug@npm:^2.6.9": - version: 2.6.9 - resolution: "debug@npm:2.6.9" - dependencies: - ms: 2.0.0 - checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 - languageName: node - linkType: hard - -"debug@npm:^3.2.7": - version: 3.2.7 - resolution: "debug@npm:3.2.7" - dependencies: - ms: ^2.1.1 - checksum: b3d8c5940799914d30314b7c3304a43305fd0715581a919dacb8b3176d024a782062368405b47491516d2091d6462d4d11f2f4974a405048094f8bfebfa3071c - languageName: node - linkType: hard - -"debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" - dependencies: - ms: 2.1.2 - peerDependenciesMeta: - supports-color: - optional: true - checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 - languageName: node - linkType: hard - -"deep-is@npm:^0.1.3": - version: 0.1.4 - resolution: "deep-is@npm:0.1.4" - checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 - languageName: node - linkType: hard - -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4": - version: 1.1.4 - resolution: "define-properties@npm:1.1.4" - dependencies: - has-property-descriptors: ^1.0.0 - object-keys: ^1.1.1 - checksum: ce0aef3f9eb193562b5cfb79b2d2c86b6a109dfc9fdcb5f45d680631a1a908c06824ddcdb72b7573b54e26ace07f0a23420aaba0d5c627b34d2c1de8ef527e2b - languageName: node - linkType: hard - -"dir-glob@npm:^3.0.1": - version: 3.0.1 - resolution: "dir-glob@npm:3.0.1" - dependencies: - path-type: ^4.0.0 - checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 - languageName: node - linkType: hard - -"docs@workspace:apps/docs": - version: 0.0.0-use.local - resolution: "docs@workspace:apps/docs" - dependencies: - "@babel/core": ^7.0.0 - "@types/node": ^17.0.12 - "@types/react": ^18.0.22 - "@types/react-dom": ^18.0.7 - eslint: 7.32.0 - eslint-config-custom: "*" - next: 13.0.0 - react: ^18.2.0 - react-dom: ^18.2.0 - tsconfig: "*" - typescript: ^4.5.3 - ui: "*" - languageName: unknown - linkType: soft - -"doctrine@npm:^2.1.0": - version: 2.1.0 - resolution: "doctrine@npm:2.1.0" - dependencies: - esutils: ^2.0.2 - checksum: a45e277f7feaed309fe658ace1ff286c6e2002ac515af0aaf37145b8baa96e49899638c7cd47dccf84c3d32abfc113246625b3ac8f552d1046072adee13b0dc8 - languageName: node - linkType: hard - -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: ^2.0.2 - checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.4.251": - version: 1.4.284 - resolution: "electron-to-chromium@npm:1.4.284" - checksum: be496e9dca6509dbdbb54dc32146fc99f8eb716d28a7ee8ccd3eba0066561df36fc51418d8bd7cf5a5891810bf56c0def3418e74248f51ea4a843d423603d10a - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 - languageName: node - linkType: hard - -"enquirer@npm:^2.3.5": - version: 2.3.6 - resolution: "enquirer@npm:2.3.6" - dependencies: - ansi-colors: ^4.1.1 - checksum: 1c0911e14a6f8d26721c91e01db06092a5f7675159f0261d69c403396a385afd13dd76825e7678f66daffa930cfaa8d45f506fb35f818a2788463d022af1b884 - languageName: node - linkType: hard - -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4": - version: 1.20.4 - resolution: "es-abstract@npm:1.20.4" - dependencies: - call-bind: ^1.0.2 - es-to-primitive: ^1.2.1 - function-bind: ^1.1.1 - function.prototype.name: ^1.1.5 - get-intrinsic: ^1.1.3 - get-symbol-description: ^1.0.0 - has: ^1.0.3 - has-property-descriptors: ^1.0.0 - has-symbols: ^1.0.3 - internal-slot: ^1.0.3 - is-callable: ^1.2.7 - is-negative-zero: ^2.0.2 - is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 - is-string: ^1.0.7 - is-weakref: ^1.0.2 - object-inspect: ^1.12.2 - object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.4.3 - safe-regex-test: ^1.0.0 - string.prototype.trimend: ^1.0.5 - string.prototype.trimstart: ^1.0.5 - unbox-primitive: ^1.0.2 - checksum: 89297cc785c31aedf961a603d5a07ed16471e435d3a1b6d070b54f157cf48454b95cda2ac55e4b86ff4fe3276e835fcffd2771578e6fa634337da49b26826141 - languageName: node - linkType: hard - -"es-shim-unscopables@npm:^1.0.0": - version: 1.0.0 - resolution: "es-shim-unscopables@npm:1.0.0" - dependencies: - has: ^1.0.3 - checksum: 83e95cadbb6ee44d3644dfad60dcad7929edbc42c85e66c3e99aefd68a3a5c5665f2686885cddb47dfeabfd77bd5ea5a7060f2092a955a729bbd8834f0d86fa1 - languageName: node - linkType: hard - -"es-to-primitive@npm:^1.2.1": - version: 1.2.1 - resolution: "es-to-primitive@npm:1.2.1" - dependencies: - is-callable: ^1.1.4 - is-date-object: ^1.0.1 - is-symbol: ^1.0.2 - checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed - languageName: node - linkType: hard - -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 - languageName: node - linkType: hard - -"eslint-config-custom@*, eslint-config-custom@workspace:packages/eslint-config-custom": - version: 0.0.0-use.local - resolution: "eslint-config-custom@workspace:packages/eslint-config-custom" - dependencies: - eslint: ^7.23.0 - eslint-config-next: 13.0.0 - eslint-config-prettier: ^8.3.0 - eslint-config-turbo: latest - eslint-plugin-react: 7.31.8 - typescript: ^4.7.4 - languageName: unknown - linkType: soft - -"eslint-config-next@npm:13.0.0": - version: 13.0.0 - resolution: "eslint-config-next@npm:13.0.0" - dependencies: - "@next/eslint-plugin-next": 13.0.0 - "@rushstack/eslint-patch": ^1.1.3 - "@typescript-eslint/parser": ^5.21.0 - eslint-import-resolver-node: ^0.3.6 - eslint-import-resolver-typescript: ^2.7.1 - eslint-plugin-import: ^2.26.0 - eslint-plugin-jsx-a11y: ^6.5.1 - eslint-plugin-react: ^7.31.7 - eslint-plugin-react-hooks: ^4.5.0 - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - typescript: ">=3.3.1" - peerDependenciesMeta: - typescript: - optional: true - checksum: 69f04df8d831aba78df30edec2ce7a7cc5779af89159bfdc42f015d2e038a26e8b2b6e8407873a3827098f5abd21b5657aace0ff014d345465ae98d133ddb285 - languageName: node - linkType: hard - -"eslint-config-prettier@npm:^8.3.0": - version: 8.5.0 - resolution: "eslint-config-prettier@npm:8.5.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 0d0f5c32e7a0ad91249467ce71ca92394ccd343178277d318baf32063b79ea90216f4c81d1065d60f96366fdc60f151d4d68ae7811a58bd37228b84c2083f893 - languageName: node - linkType: hard - -eslint-config-turbo@latest: - version: 0.0.4 - resolution: "eslint-config-turbo@npm:0.0.4" - dependencies: - eslint-plugin-turbo: 0.0.4 - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - checksum: 5f89b557c0ebefe558315fdb6c2a2b800084ecb8c1cd170998c3b29f359885c5b40f48393a1657c36a868b3b9d89cd23503c3d927103cd9ca58e4d3aaccb6888 - languageName: node - linkType: hard - -"eslint-import-resolver-node@npm:^0.3.6": - version: 0.3.6 - resolution: "eslint-import-resolver-node@npm:0.3.6" - dependencies: - debug: ^3.2.7 - resolve: ^1.20.0 - checksum: 6266733af1e112970e855a5bcc2d2058fb5ae16ad2a6d400705a86b29552b36131ffc5581b744c23d550de844206fb55e9193691619ee4dbf225c4bde526b1c8 - languageName: node - linkType: hard - -"eslint-import-resolver-typescript@npm:^2.7.1": - version: 2.7.1 - resolution: "eslint-import-resolver-typescript@npm:2.7.1" - dependencies: - debug: ^4.3.4 - glob: ^7.2.0 - is-glob: ^4.0.3 - resolve: ^1.22.0 - tsconfig-paths: ^3.14.1 - peerDependencies: - eslint: "*" - eslint-plugin-import: "*" - checksum: 1d81b657b1f73bf95b8f0b745c0305574b91630c1db340318f3ca8918e206fce20a933b95e7c419338cc4452cb80bb2b2d92acaf01b6aa315c78a332d832545c - languageName: node - linkType: hard - -"eslint-module-utils@npm:^2.7.3": - version: 2.7.4 - resolution: "eslint-module-utils@npm:2.7.4" - dependencies: - debug: ^3.2.7 - peerDependenciesMeta: - eslint: - optional: true - checksum: 5da13645daff145a5c922896b258f8bba560722c3767254e458d894ff5fbb505d6dfd945bffa932a5b0ae06714da2379bd41011c4c20d2d59cc83e23895360f7 - languageName: node - linkType: hard - -"eslint-plugin-import@npm:^2.26.0": - version: 2.26.0 - resolution: "eslint-plugin-import@npm:2.26.0" - dependencies: - array-includes: ^3.1.4 - array.prototype.flat: ^1.2.5 - debug: ^2.6.9 - doctrine: ^2.1.0 - eslint-import-resolver-node: ^0.3.6 - eslint-module-utils: ^2.7.3 - has: ^1.0.3 - is-core-module: ^2.8.1 - is-glob: ^4.0.3 - minimatch: ^3.1.2 - object.values: ^1.1.5 - resolve: ^1.22.0 - tsconfig-paths: ^3.14.1 - peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 0bf77ad80339554481eafa2b1967449e1f816b94c7a6f9614ce33fb4083c4e6c050f10d241dd50b4975d47922880a34de1e42ea9d8e6fd663ebb768baa67e655 - languageName: node - linkType: hard - -"eslint-plugin-jsx-a11y@npm:^6.5.1": - version: 6.6.1 - resolution: "eslint-plugin-jsx-a11y@npm:6.6.1" - dependencies: - "@babel/runtime": ^7.18.9 - aria-query: ^4.2.2 - array-includes: ^3.1.5 - ast-types-flow: ^0.0.7 - axe-core: ^4.4.3 - axobject-query: ^2.2.0 - damerau-levenshtein: ^1.0.8 - emoji-regex: ^9.2.2 - has: ^1.0.3 - jsx-ast-utils: ^3.3.2 - language-tags: ^1.0.5 - minimatch: ^3.1.2 - semver: ^6.3.0 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: baae7377f0e25a0cc9b34dc333a3dc6ead9ee8365e445451eff554c3ca267a0a6cb88127fe90395c578ab1b92cfed246aef7dc8d2b48b603389e10181799e144 - languageName: node - linkType: hard - -"eslint-plugin-react-hooks@npm:^4.5.0": - version: 4.6.0 - resolution: "eslint-plugin-react-hooks@npm:4.6.0" - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 23001801f14c1d16bf0a837ca7970d9dd94e7b560384b41db378b49b6e32dc43d6e2790de1bd737a652a86f81a08d6a91f402525061b47719328f586a57e86c3 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:7.31.8": - version: 7.31.8 - resolution: "eslint-plugin-react@npm:7.31.8" - dependencies: - array-includes: ^3.1.5 - array.prototype.flatmap: ^1.3.0 - doctrine: ^2.1.0 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.1.2 - object.entries: ^1.1.5 - object.fromentries: ^2.0.5 - object.hasown: ^1.1.1 - object.values: ^1.1.5 - prop-types: ^15.8.1 - resolve: ^2.0.0-next.3 - semver: ^6.3.0 - string.prototype.matchall: ^4.0.7 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 0683e2a624a4df6f08264a3f6bc614a81e8f961c83173bdf2d8d3523f84ed5d234cddc976dbc6815913e007c5984df742ba61be0c0592b27c3daabe0f68165a3 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:^7.31.7": - version: 7.31.11 - resolution: "eslint-plugin-react@npm:7.31.11" - dependencies: - array-includes: ^3.1.6 - array.prototype.flatmap: ^1.3.1 - array.prototype.tosorted: ^1.1.1 - doctrine: ^2.1.0 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.1.2 - object.entries: ^1.1.6 - object.fromentries: ^2.0.6 - object.hasown: ^1.1.2 - object.values: ^1.1.6 - prop-types: ^15.8.1 - resolve: ^2.0.0-next.3 - semver: ^6.3.0 - string.prototype.matchall: ^4.0.8 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: a3d612f6647bef33cf2a67c81a6b37b42c075300ed079cffecf5fb475c0d6ab855c1de340d1cbf361a0126429fb906dda597527235d2d12c4404453dbc712fc6 - languageName: node - linkType: hard - -"eslint-plugin-turbo@npm:0.0.4": - version: 0.0.4 - resolution: "eslint-plugin-turbo@npm:0.0.4" - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - checksum: c2a27226ae46b6cc4a747a6d82eefc7efa5df14542dcf84806e72564e11d1d76971284e73b44ee36e5bf33eb13519fe2b5d71b783c1789c185da1519caf54cb5 - languageName: node - linkType: hard - -"eslint-scope@npm:^5.1.1": - version: 5.1.1 - resolution: "eslint-scope@npm:5.1.1" - dependencies: - esrecurse: ^4.3.0 - estraverse: ^4.1.1 - checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb - languageName: node - linkType: hard - -"eslint-utils@npm:^2.1.0": - version: 2.1.0 - resolution: "eslint-utils@npm:2.1.0" - dependencies: - eslint-visitor-keys: ^1.1.0 - checksum: 27500938f348da42100d9e6ad03ae29b3de19ba757ae1a7f4a087bdcf83ac60949bbb54286492ca61fac1f5f3ac8692dd21537ce6214240bf95ad0122f24d71d - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^1.1.0, eslint-visitor-keys@npm:^1.3.0": - version: 1.3.0 - resolution: "eslint-visitor-keys@npm:1.3.0" - checksum: 37a19b712f42f4c9027e8ba98c2b06031c17e0c0a4c696cd429bd9ee04eb43889c446f2cd545e1ff51bef9593fcec94ecd2c2ef89129fcbbf3adadbef520376a - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^2.0.0": - version: 2.1.0 - resolution: "eslint-visitor-keys@npm:2.1.0" - checksum: e3081d7dd2611a35f0388bbdc2f5da60b3a3c5b8b6e928daffff7391146b434d691577aa95064c8b7faad0b8a680266bcda0a42439c18c717b80e6718d7e267d - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.3.0": - version: 3.3.0 - resolution: "eslint-visitor-keys@npm:3.3.0" - checksum: d59e68a7c5a6d0146526b0eec16ce87fbf97fe46b8281e0d41384224375c4e52f5ffb9e16d48f4ea50785cde93f766b0c898e31ab89978d88b0e1720fbfb7808 - languageName: node - linkType: hard - -"eslint@npm:7.32.0, eslint@npm:^7.23.0, eslint@npm:^7.32.0": - version: 7.32.0 - resolution: "eslint@npm:7.32.0" - dependencies: - "@babel/code-frame": 7.12.11 - "@eslint/eslintrc": ^0.4.3 - "@humanwhocodes/config-array": ^0.5.0 - ajv: ^6.10.0 - chalk: ^4.0.0 - cross-spawn: ^7.0.2 - debug: ^4.0.1 - doctrine: ^3.0.0 - enquirer: ^2.3.5 - escape-string-regexp: ^4.0.0 - eslint-scope: ^5.1.1 - eslint-utils: ^2.1.0 - eslint-visitor-keys: ^2.0.0 - espree: ^7.3.1 - esquery: ^1.4.0 - esutils: ^2.0.2 - fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 - functional-red-black-tree: ^1.0.1 - glob-parent: ^5.1.2 - globals: ^13.6.0 - ignore: ^4.0.6 - import-fresh: ^3.0.0 - imurmurhash: ^0.1.4 - is-glob: ^4.0.0 - js-yaml: ^3.13.1 - json-stable-stringify-without-jsonify: ^1.0.1 - levn: ^0.4.1 - lodash.merge: ^4.6.2 - minimatch: ^3.0.4 - natural-compare: ^1.4.0 - optionator: ^0.9.1 - progress: ^2.0.0 - regexpp: ^3.1.0 - semver: ^7.2.1 - strip-ansi: ^6.0.0 - strip-json-comments: ^3.1.0 - table: ^6.0.9 - text-table: ^0.2.0 - v8-compile-cache: ^2.0.3 - bin: - eslint: bin/eslint.js - checksum: cc85af9985a3a11085c011f3d27abe8111006d34cc274291b3c4d7bea51a4e2ff6135780249becd919ba7f6d6d1ecc38a6b73dacb6a7be08d38453b344dc8d37 - languageName: node - linkType: hard - -"espree@npm:^7.3.0, espree@npm:^7.3.1": - version: 7.3.1 - resolution: "espree@npm:7.3.1" - dependencies: - acorn: ^7.4.0 - acorn-jsx: ^5.3.1 - eslint-visitor-keys: ^1.3.0 - checksum: aa9b50dcce883449af2e23bc2b8d9abb77118f96f4cb313935d6b220f77137eaef7724a83c3f6243b96bc0e4ab14766198e60818caad99f9519ae5a336a39b45 - languageName: node - linkType: hard - -"esprima@npm:^4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 - languageName: node - linkType: hard - -"esquery@npm:^1.4.0": - version: 1.4.0 - resolution: "esquery@npm:1.4.0" - dependencies: - estraverse: ^5.1.0 - checksum: a0807e17abd7fbe5fbd4fab673038d6d8a50675cdae6b04fbaa520c34581be0c5fa24582990e8acd8854f671dd291c78bb2efb9e0ed5b62f33bac4f9cf820210 - languageName: node - linkType: hard - -"esrecurse@npm:^4.3.0": - version: 4.3.0 - resolution: "esrecurse@npm:4.3.0" - dependencies: - estraverse: ^5.2.0 - checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 - languageName: node - linkType: hard - -"estraverse@npm:^4.1.1": - version: 4.3.0 - resolution: "estraverse@npm:4.3.0" - checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 - languageName: node - linkType: hard - -"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": - version: 5.3.0 - resolution: "estraverse@npm:5.3.0" - checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b - languageName: node - linkType: hard - -"esutils@npm:^2.0.2": - version: 2.0.3 - resolution: "esutils@npm:2.0.3" - checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 - languageName: node - linkType: hard - -"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": - version: 3.1.3 - resolution: "fast-deep-equal@npm:3.1.3" - checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d - languageName: node - linkType: hard - -"fast-glob@npm:^3.2.9": - version: 3.2.12 - resolution: "fast-glob@npm:3.2.12" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 0b1990f6ce831c7e28c4d505edcdaad8e27e88ab9fa65eedadb730438cfc7cde4910d6c975d6b7b8dc8a73da4773702ebcfcd6e3518e73938bb1383badfe01c2 - languageName: node - linkType: hard - -"fast-levenshtein@npm:^2.0.6": - version: 2.0.6 - resolution: "fast-levenshtein@npm:2.0.6" - checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c - languageName: node - linkType: hard - -"fastq@npm:^1.6.0": - version: 1.13.0 - resolution: "fastq@npm:1.13.0" - dependencies: - reusify: ^1.0.4 - checksum: 32cf15c29afe622af187d12fc9cd93e160a0cb7c31a3bb6ace86b7dea3b28e7b72acde89c882663f307b2184e14782c6c664fa315973c03626c7d4bff070bb0b - languageName: node - linkType: hard - -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" - dependencies: - flat-cache: ^3.0.4 - checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 - languageName: node - linkType: hard - -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" - dependencies: - to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 - languageName: node - linkType: hard - -"flat-cache@npm:^3.0.4": - version: 3.0.4 - resolution: "flat-cache@npm:3.0.4" - dependencies: - flatted: ^3.1.0 - rimraf: ^3.0.2 - checksum: 4fdd10ecbcbf7d520f9040dd1340eb5dfe951e6f0ecf2252edeec03ee68d989ec8b9a20f4434270e71bcfd57800dc09b3344fca3966b2eb8f613072c7d9a2365 - languageName: node - linkType: hard - -"flatted@npm:^3.1.0": - version: 3.2.7 - resolution: "flatted@npm:3.2.7" - checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 - languageName: node - linkType: hard - -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a - languageName: node - linkType: hard - -"function.prototype.name@npm:^1.1.5": - version: 1.1.5 - resolution: "function.prototype.name@npm:1.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.0 - functions-have-names: ^1.2.2 - checksum: acd21d733a9b649c2c442f067567743214af5fa248dbeee69d8278ce7df3329ea5abac572be9f7470b4ec1cd4d8f1040e3c5caccf98ebf2bf861a0deab735c27 - languageName: node - linkType: hard - -"functional-red-black-tree@npm:^1.0.1": - version: 1.0.1 - resolution: "functional-red-black-tree@npm:1.0.1" - checksum: ca6c170f37640e2d94297da8bb4bf27a1d12bea3e00e6a3e007fd7aa32e37e000f5772acf941b4e4f3cf1c95c3752033d0c509af157ad8f526e7f00723b9eb9f - languageName: node - linkType: hard - -"functions-have-names@npm:^1.2.2": - version: 1.2.3 - resolution: "functions-have-names@npm:1.2.3" - checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 - languageName: node - linkType: hard - -"gensync@npm:^1.0.0-beta.2": - version: 1.0.0-beta.2 - resolution: "gensync@npm:1.0.0-beta.2" - checksum: a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.0, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3": - version: 1.1.3 - resolution: "get-intrinsic@npm:1.1.3" - dependencies: - function-bind: ^1.1.1 - has: ^1.0.3 - has-symbols: ^1.0.3 - checksum: 152d79e87251d536cf880ba75cfc3d6c6c50e12b3a64e1ea960e73a3752b47c69f46034456eae1b0894359ce3bc64c55c186f2811f8a788b75b638b06fab228a - languageName: node - linkType: hard - -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 - languageName: node - linkType: hard - -"glob-parent@npm:^5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: ^4.0.1 - checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e - languageName: node - linkType: hard - -"glob@npm:7.1.7": - version: 7.1.7 - resolution: "glob@npm:7.1.7" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.0.4 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: b61f48973bbdcf5159997b0874a2165db572b368b931135832599875919c237fc05c12984e38fe828e69aa8a921eb0e8a4997266211c517c9cfaae8a93988bb8 - languageName: node - linkType: hard - -"glob@npm:^7.1.3, glob@npm:^7.2.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.1.1 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 - languageName: node - linkType: hard - -"globals@npm:^11.1.0": - version: 11.12.0 - resolution: "globals@npm:11.12.0" - checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e - languageName: node - linkType: hard - -"globals@npm:^13.6.0, globals@npm:^13.9.0": - version: 13.18.0 - resolution: "globals@npm:13.18.0" - dependencies: - type-fest: ^0.20.2 - checksum: 9fdaa74cfd5d4ac91319662f512c29b11d1d2deb9c8a20d3998097671deba83d195f20730b2345887de3ddab958a6fa68952feed9ae836ee4594a82ace62fdb4 - languageName: node - linkType: hard - -"globby@npm:^11.1.0": - version: 11.1.0 - resolution: "globby@npm:11.1.0" - dependencies: - array-union: ^2.1.0 - dir-glob: ^3.0.1 - fast-glob: ^3.2.9 - ignore: ^5.2.0 - merge2: ^1.4.1 - slash: ^3.0.0 - checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 - languageName: node - linkType: hard - -"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": - version: 1.0.2 - resolution: "has-bigints@npm:1.0.2" - checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b - languageName: node - linkType: hard - -"has-flag@npm:^3.0.0": - version: 3.0.0 - resolution: "has-flag@npm:3.0.0" - checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad - languageName: node - linkType: hard - -"has-property-descriptors@npm:^1.0.0": - version: 1.0.0 - resolution: "has-property-descriptors@npm:1.0.0" - dependencies: - get-intrinsic: ^1.1.1 - checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": - version: 1.0.3 - resolution: "has-symbols@npm:1.0.3" - checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" - dependencies: - has-symbols: ^1.0.2 - checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c - languageName: node - linkType: hard - -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: ^1.1.1 - checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 - languageName: node - linkType: hard - -"ignore@npm:^4.0.6": - version: 4.0.6 - resolution: "ignore@npm:4.0.6" - checksum: 248f82e50a430906f9ee7f35e1158e3ec4c3971451dd9f99c9bc1548261b4db2b99709f60ac6c6cac9333494384176cc4cc9b07acbe42d52ac6a09cad734d800 - languageName: node - linkType: hard - -"ignore@npm:^5.2.0": - version: 5.2.0 - resolution: "ignore@npm:5.2.0" - checksum: 6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77 - languageName: node - linkType: hard - -"import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" - dependencies: - parent-module: ^1.0.0 - resolve-from: ^4.0.0 - checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: ^1.3.0 - wrappy: 1 - checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd - languageName: node - linkType: hard - -"inherits@npm:2": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 - languageName: node - linkType: hard - -"internal-slot@npm:^1.0.3": - version: 1.0.3 - resolution: "internal-slot@npm:1.0.3" - dependencies: - get-intrinsic: ^1.1.0 - has: ^1.0.3 - side-channel: ^1.0.4 - checksum: 1944f92e981e47aebc98a88ff0db579fd90543d937806104d0b96557b10c1f170c51fb777b97740a8b6ddeec585fca8c39ae99fd08a8e058dfc8ab70937238bf - languageName: node - linkType: hard - -"is-bigint@npm:^1.0.1": - version: 1.0.4 - resolution: "is-bigint@npm:1.0.4" - dependencies: - has-bigints: ^1.0.1 - checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 - languageName: node - linkType: hard - -"is-boolean-object@npm:^1.1.0": - version: 1.1.2 - resolution: "is-boolean-object@npm:1.1.2" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 - languageName: node - linkType: hard - -"is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": - version: 1.2.7 - resolution: "is-callable@npm:1.2.7" - checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac - languageName: node - linkType: hard - -"is-core-module@npm:^2.8.1, is-core-module@npm:^2.9.0": - version: 2.11.0 - resolution: "is-core-module@npm:2.11.0" - dependencies: - has: ^1.0.3 - checksum: f96fd490c6b48eb4f6d10ba815c6ef13f410b0ba6f7eb8577af51697de523e5f2cd9de1c441b51d27251bf0e4aebc936545e33a5d26d5d51f28d25698d4a8bab - languageName: node - linkType: hard - -"is-date-object@npm:^1.0.1": - version: 1.0.5 - resolution: "is-date-object@npm:1.0.5" - dependencies: - has-tostringtag: ^1.0.0 - checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 - languageName: node - linkType: hard - -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: ^2.1.1 - checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 - languageName: node - linkType: hard - -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a - languageName: node - linkType: hard - -"is-number-object@npm:^1.0.4": - version: 1.0.7 - resolution: "is-number-object@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a - languageName: node - linkType: hard - -"is-regex@npm:^1.1.4": - version: 1.1.4 - resolution: "is-regex@npm:1.1.4" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 - languageName: node - linkType: hard - -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a - languageName: node - linkType: hard - -"is-string@npm:^1.0.5, is-string@npm:^1.0.7": - version: 1.0.7 - resolution: "is-string@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 - languageName: node - linkType: hard - -"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": - version: 1.0.4 - resolution: "is-symbol@npm:1.0.4" - dependencies: - has-symbols: ^1.0.2 - checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 - languageName: node - linkType: hard - -"is-weakref@npm:^1.0.2": - version: 1.0.2 - resolution: "is-weakref@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 - languageName: node - linkType: hard - -"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 - languageName: node - linkType: hard - -"js-yaml@npm:^3.13.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: ^1.0.7 - esprima: ^4.0.0 - bin: - js-yaml: bin/js-yaml.js - checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c - languageName: node - linkType: hard - -"jsesc@npm:^2.5.1": - version: 2.5.2 - resolution: "jsesc@npm:2.5.2" - bin: - jsesc: bin/jsesc - checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d - languageName: node - linkType: hard - -"json-schema-traverse@npm:^1.0.0": - version: 1.0.0 - resolution: "json-schema-traverse@npm:1.0.0" - checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad - languageName: node - linkType: hard - -"json-stable-stringify-without-jsonify@npm:^1.0.1": - version: 1.0.1 - resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" - checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 - languageName: node - linkType: hard - -"json5@npm:^1.0.1": - version: 1.0.1 - resolution: "json5@npm:1.0.1" - dependencies: - minimist: ^1.2.0 - bin: - json5: lib/cli.js - checksum: e76ea23dbb8fc1348c143da628134a98adf4c5a4e8ea2adaa74a80c455fc2cdf0e2e13e6398ef819bfe92306b610ebb2002668ed9fc1af386d593691ef346fc3 - languageName: node - linkType: hard - -"json5@npm:^2.2.1": - version: 2.2.1 - resolution: "json5@npm:2.2.1" - bin: - json5: lib/cli.js - checksum: 74b8a23b102a6f2bf2d224797ae553a75488b5adbaee9c9b6e5ab8b510a2fc6e38f876d4c77dea672d4014a44b2399e15f2051ac2b37b87f74c0c7602003543b - languageName: node - linkType: hard - -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.2": - version: 3.3.3 - resolution: "jsx-ast-utils@npm:3.3.3" - dependencies: - array-includes: ^3.1.5 - object.assign: ^4.1.3 - checksum: a2ed78cac49a0f0c4be8b1eafe3c5257a1411341d8e7f1ac740debae003de04e5f6372bfcfbd9d082e954ffd99aac85bcda85b7c6bc11609992483f4cdc0f745 - languageName: node - linkType: hard - -"language-subtag-registry@npm:~0.3.2": - version: 0.3.22 - resolution: "language-subtag-registry@npm:0.3.22" - checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a - languageName: node - linkType: hard - -"language-tags@npm:^1.0.5": - version: 1.0.5 - resolution: "language-tags@npm:1.0.5" - dependencies: - language-subtag-registry: ~0.3.2 - checksum: c81b5d8b9f5f9cfd06ee71ada6ddfe1cf83044dd5eeefcd1e420ad491944da8957688db4a0a9bc562df4afdc2783425cbbdfd152c01d93179cf86888903123cf - languageName: node - linkType: hard - -"levn@npm:^0.4.1": - version: 0.4.1 - resolution: "levn@npm:0.4.1" - dependencies: - prelude-ls: ^1.2.1 - type-check: ~0.4.0 - checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 - languageName: node - linkType: hard - -"lodash.merge@npm:^4.6.2": - version: 4.6.2 - resolution: "lodash.merge@npm:4.6.2" - checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 - languageName: node - linkType: hard - -"lodash.truncate@npm:^4.4.2": - version: 4.4.2 - resolution: "lodash.truncate@npm:4.4.2" - checksum: b463d8a382cfb5f0e71c504dcb6f807a7bd379ff1ea216669aa42c52fc28c54e404bfbd96791aa09e6df0de2c1d7b8f1b7f4b1a61f324d38fe98bc535aeee4f5 - languageName: node - linkType: hard - -"loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" - dependencies: - js-tokens: ^3.0.0 || ^4.0.0 - bin: - loose-envify: cli.js - checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 - languageName: node - linkType: hard - -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: ^4.0.0 - checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 - languageName: node - linkType: hard - -"merge2@npm:^1.3.0, merge2@npm:^1.4.1": - version: 1.4.1 - resolution: "merge2@npm:1.4.1" - checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 - languageName: node - linkType: hard - -"micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" - dependencies: - braces: ^3.0.2 - picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: ^1.1.7 - checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a - languageName: node - linkType: hard - -"minimist@npm:^1.2.0, minimist@npm:^1.2.6": - version: 1.2.7 - resolution: "minimist@npm:1.2.7" - checksum: 7346574a1038ca23c32e02252f603801f09384dd1d78b69a943a4e8c2c28730b80e96193882d3d3b22a063445f460e48316b29b8a25addca2d7e5e8f75478bec - languageName: node - linkType: hard - -"monorepo@workspace:.": - version: 0.0.0-use.local - resolution: "monorepo@workspace:." - dependencies: - eslint-config-custom: "*" - prettier: latest - turbo: 1.6.3 - languageName: unknown - linkType: soft - -"ms@npm:2.0.0": - version: 2.0.0 - resolution: "ms@npm:2.0.0" - checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 - languageName: node - linkType: hard - -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f - languageName: node - linkType: hard - -"ms@npm:^2.1.1": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d - languageName: node - linkType: hard - -"nanoid@npm:^3.3.4": - version: 3.3.4 - resolution: "nanoid@npm:3.3.4" - bin: - nanoid: bin/nanoid.cjs - checksum: 2fddd6dee994b7676f008d3ffa4ab16035a754f4bb586c61df5a22cf8c8c94017aadd360368f47d653829e0569a92b129979152ff97af23a558331e47e37cd9c - languageName: node - linkType: hard - -"natural-compare@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare@npm:1.4.0" - checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d - languageName: node - linkType: hard - -"next@npm:13.0.0": - version: 13.0.0 - resolution: "next@npm:13.0.0" - dependencies: - "@next/env": 13.0.0 - "@next/swc-android-arm-eabi": 13.0.0 - "@next/swc-android-arm64": 13.0.0 - "@next/swc-darwin-arm64": 13.0.0 - "@next/swc-darwin-x64": 13.0.0 - "@next/swc-freebsd-x64": 13.0.0 - "@next/swc-linux-arm-gnueabihf": 13.0.0 - "@next/swc-linux-arm64-gnu": 13.0.0 - "@next/swc-linux-arm64-musl": 13.0.0 - "@next/swc-linux-x64-gnu": 13.0.0 - "@next/swc-linux-x64-musl": 13.0.0 - "@next/swc-win32-arm64-msvc": 13.0.0 - "@next/swc-win32-ia32-msvc": 13.0.0 - "@next/swc-win32-x64-msvc": 13.0.0 - "@swc/helpers": 0.4.11 - caniuse-lite: ^1.0.30001406 - postcss: 8.4.14 - styled-jsx: 5.1.0 - use-sync-external-store: 1.2.0 - peerDependencies: - fibers: ">= 3.1.0" - node-sass: ^6.0.0 || ^7.0.0 - react: ^18.0.0-0 - react-dom: ^18.0.0-0 - sass: ^1.3.0 - dependenciesMeta: - "@next/swc-android-arm-eabi": - optional: true - "@next/swc-android-arm64": - optional: true - "@next/swc-darwin-arm64": - optional: true - "@next/swc-darwin-x64": - optional: true - "@next/swc-freebsd-x64": - optional: true - "@next/swc-linux-arm-gnueabihf": - optional: true - "@next/swc-linux-arm64-gnu": - optional: true - "@next/swc-linux-arm64-musl": - optional: true - "@next/swc-linux-x64-gnu": - optional: true - "@next/swc-linux-x64-musl": - optional: true - "@next/swc-win32-arm64-msvc": - optional: true - "@next/swc-win32-ia32-msvc": - optional: true - "@next/swc-win32-x64-msvc": - optional: true - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - bin: - next: dist/bin/next - checksum: 7b5c84728783433c07e3eac65d5d85434f6c056a3e55c417c7636e08d8e1af2532d83f75b8448ddc5c9525145a6a7c93e8482744ee3f2d647841b152306da939 - languageName: node - linkType: hard - -"node-releases@npm:^2.0.6": - version: 2.0.6 - resolution: "node-releases@npm:2.0.6" - checksum: e86a926dc9fbb3b41b4c4a89d998afdf140e20a4e8dbe6c0a807f7b2948b42ea97d7fd3ad4868041487b6e9ee98409829c6e4d84a734a4215dff060a7fbeb4bf - languageName: node - linkType: hard - -"object-assign@npm:^4.1.1": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f - languageName: node - linkType: hard - -"object-inspect@npm:^1.12.2, object-inspect@npm:^1.9.0": - version: 1.12.2 - resolution: "object-inspect@npm:1.12.2" - checksum: a534fc1b8534284ed71f25ce3a496013b7ea030f3d1b77118f6b7b1713829262be9e6243acbcb3ef8c626e2b64186112cb7f6db74e37b2789b9c789ca23048b2 - languageName: node - linkType: hard - -"object-keys@npm:^1.1.1": - version: 1.1.1 - resolution: "object-keys@npm:1.1.1" - checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a - languageName: node - linkType: hard - -"object.assign@npm:^4.1.3, object.assign@npm:^4.1.4": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - has-symbols: ^1.0.3 - object-keys: ^1.1.1 - checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864 - languageName: node - linkType: hard - -"object.entries@npm:^1.1.5, object.entries@npm:^1.1.6": - version: 1.1.6 - resolution: "object.entries@npm:1.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 0f8c47517e6a9a980241eafe3b73de11e59511883173c2b93d67424a008e47e11b77c80e431ad1d8a806f6108b225a1cab9223e53e555776c612a24297117d28 - languageName: node - linkType: hard - -"object.fromentries@npm:^2.0.5, object.fromentries@npm:^2.0.6": - version: 2.0.6 - resolution: "object.fromentries@npm:2.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 453c6d694180c0c30df451b60eaf27a5b9bca3fb43c37908fd2b78af895803dc631242bcf05582173afa40d8d0e9c96e16e8874b39471aa53f3ac1f98a085d85 - languageName: node - linkType: hard - -"object.hasown@npm:^1.1.1, object.hasown@npm:^1.1.2": - version: 1.1.2 - resolution: "object.hasown@npm:1.1.2" - dependencies: - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: b936572536db0cdf38eb30afd2f1026a8b6f2cc5d2c4497c9d9bbb01eaf3e980dead4fd07580cfdd098e6383e5a9db8212d3ea0c6bdd2b5e68c60aa7e3b45566 - languageName: node - linkType: hard - -"object.values@npm:^1.1.5, object.values@npm:^1.1.6": - version: 1.1.6 - resolution: "object.values@npm:1.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: f6fff9fd817c24cfd8107f50fb33061d81cd11bacc4e3dbb3852e9ff7692fde4dbce823d4333ea27cd9637ef1b6690df5fbb61f1ed314fa2959598dc3ae23d8e - languageName: node - linkType: hard - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: 1 - checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 - languageName: node - linkType: hard - -"optionator@npm:^0.9.1": - version: 0.9.1 - resolution: "optionator@npm:0.9.1" - dependencies: - deep-is: ^0.1.3 - fast-levenshtein: ^2.0.6 - levn: ^0.4.1 - prelude-ls: ^1.2.1 - type-check: ^0.4.0 - word-wrap: ^1.2.3 - checksum: dbc6fa065604b24ea57d734261914e697bd73b69eff7f18e967e8912aa2a40a19a9f599a507fa805be6c13c24c4eae8c71306c239d517d42d4c041c942f508a0 - languageName: node - linkType: hard - -"parent-module@npm:^1.0.0": - version: 1.0.1 - resolution: "parent-module@npm:1.0.1" - dependencies: - callsites: ^3.0.0 - checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff - languageName: node - linkType: hard - -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a - languageName: node - linkType: hard - -"path-type@npm:^4.0.0": - version: 4.0.0 - resolution: "path-type@npm:4.0.0" - checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 - languageName: node - linkType: hard - -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 - languageName: node - linkType: hard - -"picomatch@npm:^2.3.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf - languageName: node - linkType: hard - -"postcss@npm:8.4.14": - version: 8.4.14 - resolution: "postcss@npm:8.4.14" - dependencies: - nanoid: ^3.3.4 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: fe58766ff32e4becf65a7d57678995cfd239df6deed2fe0557f038b47c94e4132e7e5f68b5aa820c13adfec32e523b693efaeb65798efb995ce49ccd83953816 - languageName: node - linkType: hard - -"prelude-ls@npm:^1.2.1": - version: 1.2.1 - resolution: "prelude-ls@npm:1.2.1" - checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a - languageName: node - linkType: hard - -prettier@latest: - version: 2.7.1 - resolution: "prettier@npm:2.7.1" - bin: - prettier: bin-prettier.js - checksum: 55a4409182260866ab31284d929b3cb961e5fdb91fe0d2e099dac92eaecec890f36e524b4c19e6ceae839c99c6d7195817579cdffc8e2c80da0cb794463a748b - languageName: node - linkType: hard - -"progress@npm:^2.0.0": - version: 2.0.3 - resolution: "progress@npm:2.0.3" - checksum: f67403fe7b34912148d9252cb7481266a354bd99ce82c835f79070643bb3c6583d10dbcfda4d41e04bbc1d8437e9af0fb1e1f2135727878f5308682a579429b7 - languageName: node - linkType: hard - -"prop-types@npm:^15.8.1": - version: 15.8.1 - resolution: "prop-types@npm:15.8.1" - dependencies: - loose-envify: ^1.4.0 - object-assign: ^4.1.1 - react-is: ^16.13.1 - checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0": - version: 2.1.1 - resolution: "punycode@npm:2.1.1" - checksum: 823bf443c6dd14f669984dea25757b37993f67e8d94698996064035edd43bed8a5a17a9f12e439c2b35df1078c6bec05a6c86e336209eb1061e8025c481168e8 - languageName: node - linkType: hard - -"queue-microtask@npm:^1.2.2": - version: 1.2.3 - resolution: "queue-microtask@npm:1.2.3" - checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 - languageName: node - linkType: hard - -"react-dom@npm:^18.2.0": - version: 18.2.0 - resolution: "react-dom@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - scheduler: ^0.23.0 - peerDependencies: - react: ^18.2.0 - checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc - languageName: node - linkType: hard - -"react-is@npm:^16.13.1": - version: 16.13.1 - resolution: "react-is@npm:16.13.1" - checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f - languageName: node - linkType: hard - -"react@npm:^18.2.0": - version: 18.2.0 - resolution: "react@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b - languageName: node - linkType: hard - -"regenerator-runtime@npm:^0.13.10": - version: 0.13.11 - resolution: "regenerator-runtime@npm:0.13.11" - checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4 - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.4.3": - version: 1.4.3 - resolution: "regexp.prototype.flags@npm:1.4.3" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - functions-have-names: ^1.2.2 - checksum: 51228bae732592adb3ededd5e15426be25f289e9c4ef15212f4da73f4ec3919b6140806374b8894036a86020d054a8d2657d3fee6bb9b4d35d8939c20030b7a6 - languageName: node - linkType: hard - -"regexpp@npm:^3.1.0": - version: 3.2.0 - resolution: "regexpp@npm:3.2.0" - checksum: a78dc5c7158ad9ddcfe01aa9144f46e192ddbfa7b263895a70a5c6c73edd9ce85faf7c0430e59ac38839e1734e275b9c3de5c57ee3ab6edc0e0b1bdebefccef8 - languageName: node - linkType: hard - -"require-from-string@npm:^2.0.2": - version: 2.0.2 - resolution: "require-from-string@npm:2.0.2" - checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b - languageName: node - linkType: hard - -"resolve-from@npm:^4.0.0": - version: 4.0.0 - resolution: "resolve-from@npm:4.0.0" - checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f - languageName: node - linkType: hard - -"resolve@npm:^1.20.0, resolve@npm:^1.22.0": - version: 1.22.1 - resolution: "resolve@npm:1.22.1" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 07af5fc1e81aa1d866cbc9e9460fbb67318a10fa3c4deadc35c3ad8a898ee9a71a86a65e4755ac3195e0ea0cfbe201eb323ebe655ce90526fd61917313a34e4e - languageName: node - linkType: hard - -"resolve@npm:^2.0.0-next.3": - version: 2.0.0-next.4 - resolution: "resolve@npm:2.0.0-next.4" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: c438ac9a650f2030fd074219d7f12ceb983b475da2d89ad3d6dd05fbf6b7a0a8cd37d4d10b43cb1f632bc19f22246ab7f36ebda54d84a29bfb2910a0680906d3 - languageName: node - linkType: hard - -"resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin": - version: 1.22.1 - resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=c3c19d" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 5656f4d0bedcf8eb52685c1abdf8fbe73a1603bb1160a24d716e27a57f6cecbe2432ff9c89c2bd57542c3a7b9d14b1882b73bfe2e9d7849c9a4c0b8b39f02b8b - languageName: node - linkType: hard - -"resolve@patch:resolve@^2.0.0-next.3#~builtin": - version: 2.0.0-next.4 - resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin::version=2.0.0-next.4&hash=c3c19d" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 4bf9f4f8a458607af90518ff73c67a4bc1a38b5a23fef2bb0ccbd45e8be89820a1639b637b0ba377eb2be9eedfb1739a84cde24fe4cd670c8207d8fea922b011 - languageName: node - linkType: hard - -"reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc - languageName: node - linkType: hard - -"rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: ^7.1.3 - bin: - rimraf: bin.js - checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 - languageName: node - linkType: hard - -"run-parallel@npm:^1.1.9": - version: 1.2.0 - resolution: "run-parallel@npm:1.2.0" - dependencies: - queue-microtask: ^1.2.2 - checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d - languageName: node - linkType: hard - -"safe-regex-test@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-regex-test@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.3 - is-regex: ^1.1.4 - checksum: bc566d8beb8b43c01b94e67de3f070fd2781685e835959bbbaaec91cc53381145ca91f69bd837ce6ec244817afa0a5e974fc4e40a2957f0aca68ac3add1ddd34 - languageName: node - linkType: hard - -"scheduler@npm:^0.23.0": - version: 0.23.0 - resolution: "scheduler@npm:0.23.0" - dependencies: - loose-envify: ^1.1.0 - checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a - languageName: node - linkType: hard - -"semver@npm:^6.3.0": - version: 6.3.0 - resolution: "semver@npm:6.3.0" - bin: - semver: ./bin/semver.js - checksum: 1b26ecf6db9e8292dd90df4e781d91875c0dcc1b1909e70f5d12959a23c7eebb8f01ea581c00783bbee72ceeaad9505797c381756326073850dc36ed284b21b9 - languageName: node - linkType: hard - -"semver@npm:^7.2.1, semver@npm:^7.3.7": - version: 7.3.8 - resolution: "semver@npm:7.3.8" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: ba9c7cbbf2b7884696523450a61fee1a09930d888b7a8d7579025ad93d459b2d1949ee5bbfeb188b2be5f4ac163544c5e98491ad6152df34154feebc2cc337c1 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: ^3.0.0 - checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 - languageName: node - linkType: hard - -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" - dependencies: - call-bind: ^1.0.0 - get-intrinsic: ^1.0.2 - object-inspect: ^1.9.0 - checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 - languageName: node - linkType: hard - -"slash@npm:^3.0.0": - version: 3.0.0 - resolution: "slash@npm:3.0.0" - checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c - languageName: node - linkType: hard - -"slice-ansi@npm:^4.0.0": - version: 4.0.0 - resolution: "slice-ansi@npm:4.0.0" - dependencies: - ansi-styles: ^4.0.0 - astral-regex: ^2.0.0 - is-fullwidth-code-point: ^3.0.0 - checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 - languageName: node - linkType: hard - -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c - languageName: node - linkType: hard - -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 - languageName: node - linkType: hard - -"string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: ^8.0.0 - is-fullwidth-code-point: ^3.0.0 - strip-ansi: ^6.0.1 - checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb - languageName: node - linkType: hard - -"string.prototype.matchall@npm:^4.0.7, string.prototype.matchall@npm:^4.0.8": - version: 4.0.8 - resolution: "string.prototype.matchall@npm:4.0.8" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - get-intrinsic: ^1.1.3 - has-symbols: ^1.0.3 - internal-slot: ^1.0.3 - regexp.prototype.flags: ^1.4.3 - side-channel: ^1.0.4 - checksum: 952da3a818de42ad1c10b576140a5e05b4de7b34b8d9dbf00c3ac8c1293e9c0f533613a39c5cda53e0a8221f2e710bc2150e730b1c2278d60004a8a35726efb6 - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.5": - version: 1.0.6 - resolution: "string.prototype.trimend@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 0fdc34645a639bd35179b5a08227a353b88dc089adf438f46be8a7c197fc3f22f8514c1c9be4629b3cd29c281582730a8cbbad6466c60f76b5f99cf2addb132e - languageName: node - linkType: hard - -"string.prototype.trimstart@npm:^1.0.5": - version: 1.0.6 - resolution: "string.prototype.trimstart@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 89080feef416621e6ef1279588994305477a7a91648d9436490d56010a1f7adc39167cddac7ce0b9884b8cdbef086987c4dcb2960209f2af8bac0d23ceff4f41 - languageName: node - linkType: hard - -"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: ^5.0.1 - checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c - languageName: node - linkType: hard - -"strip-bom@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-bom@npm:3.0.0" - checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b - languageName: node - linkType: hard - -"strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 - languageName: node - linkType: hard - -"styled-jsx@npm:5.1.0": - version: 5.1.0 - resolution: "styled-jsx@npm:5.1.0" - dependencies: - client-only: 0.0.1 - peerDependencies: - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" - peerDependenciesMeta: - "@babel/core": - optional: true - babel-plugin-macros: - optional: true - checksum: e5b70476fd9059147dfe35dd912e537e422a7f900cc88f80456c97da495c655598875d64de2199641d627770a7e55ed08be0fd82646bc386791fdb1d0e5af2b1 - languageName: node - linkType: hard - -"supports-color@npm:^5.3.0": - version: 5.5.0 - resolution: "supports-color@npm:5.5.0" - dependencies: - has-flag: ^3.0.0 - checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac - languageName: node - linkType: hard - -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: ^4.0.0 - checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae - languageName: node - linkType: hard - -"table@npm:^6.0.9": - version: 6.8.1 - resolution: "table@npm:6.8.1" - dependencies: - ajv: ^8.0.1 - lodash.truncate: ^4.4.2 - slice-ansi: ^4.0.0 - string-width: ^4.2.3 - strip-ansi: ^6.0.1 - checksum: 08249c7046125d9d0a944a6e96cfe9ec66908d6b8a9db125531be6eb05fa0de047fd5542e9d43b4f987057f00a093b276b8d3e19af162a9c40db2681058fd306 - languageName: node - linkType: hard - -"text-table@npm:^0.2.0": - version: 0.2.0 - resolution: "text-table@npm:0.2.0" - checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a - languageName: node - linkType: hard - -"to-fast-properties@npm:^2.0.0": - version: 2.0.0 - resolution: "to-fast-properties@npm:2.0.0" - checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: ^7.0.0 - checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed - languageName: node - linkType: hard - -"tsconfig-paths@npm:^3.14.1": - version: 3.14.1 - resolution: "tsconfig-paths@npm:3.14.1" - dependencies: - "@types/json5": ^0.0.29 - json5: ^1.0.1 - minimist: ^1.2.6 - strip-bom: ^3.0.0 - checksum: 8afa01c673ebb4782ba53d3a12df97fa837ce524f8ad38ee4e2b2fd57f5ac79abc21c574e9e9eb014d93efe7fe8214001b96233b5c6ea75bd1ea82afe17a4c6d - languageName: node - linkType: hard - -"tsconfig@*, tsconfig@workspace:packages/tsconfig": - version: 0.0.0-use.local - resolution: "tsconfig@workspace:packages/tsconfig" - languageName: unknown - linkType: soft - -"tslib@npm:^1.8.1": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd - languageName: node - linkType: hard - -"tslib@npm:^2.4.0": - version: 2.4.1 - resolution: "tslib@npm:2.4.1" - checksum: 19480d6e0313292bd6505d4efe096a6b31c70e21cf08b5febf4da62e95c265c8f571f7b36fcc3d1a17e068032f59c269fab3459d6cd3ed6949eafecf64315fca - languageName: node - linkType: hard - -"tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" - dependencies: - tslib: ^1.8.1 - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 1843f4c1b2e0f975e08c4c21caa4af4f7f65a12ac1b81b3b8489366826259323feb3fc7a243123453d2d1a02314205a7634e048d4a8009921da19f99755cdc48 - languageName: node - linkType: hard - -"turbo-darwin-64@npm:1.6.3": - version: 1.6.3 - resolution: "turbo-darwin-64@npm:1.6.3" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"turbo-darwin-arm64@npm:1.6.3": - version: 1.6.3 - resolution: "turbo-darwin-arm64@npm:1.6.3" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"turbo-linux-64@npm:1.6.3": - version: 1.6.3 - resolution: "turbo-linux-64@npm:1.6.3" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"turbo-linux-arm64@npm:1.6.3": - version: 1.6.3 - resolution: "turbo-linux-arm64@npm:1.6.3" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"turbo-windows-64@npm:1.6.3": - version: 1.6.3 - resolution: "turbo-windows-64@npm:1.6.3" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"turbo-windows-arm64@npm:1.6.3": - version: 1.6.3 - resolution: "turbo-windows-arm64@npm:1.6.3" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"turbo@npm:1.6.3": - version: 1.6.3 - resolution: "turbo@npm:1.6.3" - dependencies: - turbo-darwin-64: 1.6.3 - turbo-darwin-arm64: 1.6.3 - turbo-linux-64: 1.6.3 - turbo-linux-arm64: 1.6.3 - turbo-windows-64: 1.6.3 - turbo-windows-arm64: 1.6.3 - dependenciesMeta: - turbo-darwin-64: - optional: true - turbo-darwin-arm64: - optional: true - turbo-linux-64: - optional: true - turbo-linux-arm64: - optional: true - turbo-windows-64: - optional: true - turbo-windows-arm64: - optional: true - bin: - turbo: bin/turbo - checksum: 35195f4b7623014c25ba152c11a8cb23e51cbd75dc9266d0656692665f85b28faf3496dea8cecacf52795a917410668124186ffbdcf276325ccc3e11df9e9623 - languageName: node - linkType: hard - -"type-check@npm:^0.4.0, type-check@npm:~0.4.0": - version: 0.4.0 - resolution: "type-check@npm:0.4.0" - dependencies: - prelude-ls: ^1.2.1 - checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a - languageName: node - linkType: hard - -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 - languageName: node - linkType: hard - -"typescript@npm:^4.5.2, typescript@npm:^4.5.3, typescript@npm:^4.7.4": - version: 4.9.3 - resolution: "typescript@npm:4.9.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 17b8f816050b412403e38d48eef0e893deb6be522d6dc7caf105e54a72e34daf6835c447735fd2b28b66784e72bfbf87f627abb4818a8e43d1fa8106396128dc - languageName: node - linkType: hard - -"typescript@patch:typescript@^4.5.2#~builtin, typescript@patch:typescript@^4.5.3#~builtin, typescript@patch:typescript@^4.7.4#~builtin": - version: 4.9.3 - resolution: "typescript@patch:typescript@npm%3A4.9.3#~builtin::version=4.9.3&hash=d73830" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 67ca21a387c0572f1c04936e638dde7782c5aa520c3754aadc7cc9b7c915da9ebc3e27c601bfff4ccb7d7264e82dce6d277ada82ec09dc75024349e0ef64926d - languageName: node - linkType: hard - -"ui@*, ui@workspace:packages/ui": - version: 0.0.0-use.local - resolution: "ui@workspace:packages/ui" - dependencies: - "@types/react": ^17.0.37 - "@types/react-dom": ^17.0.11 - eslint: ^7.32.0 - eslint-config-custom: "*" - react: ^18.2.0 - tsconfig: "*" - typescript: ^4.5.2 - languageName: unknown - linkType: soft - -"unbox-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "unbox-primitive@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - has-bigints: ^1.0.2 - has-symbols: ^1.0.3 - which-boxed-primitive: ^1.0.2 - checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 - languageName: node - linkType: hard - -"update-browserslist-db@npm:^1.0.9": - version: 1.0.10 - resolution: "update-browserslist-db@npm:1.0.10" - dependencies: - escalade: ^3.1.1 - picocolors: ^1.0.0 - peerDependencies: - browserslist: ">= 4.21.0" - bin: - browserslist-lint: cli.js - checksum: 12db73b4f63029ac407b153732e7cd69a1ea8206c9100b482b7d12859cd3cd0bc59c602d7ae31e652706189f1acb90d42c53ab24a5ba563ed13aebdddc5561a0 - languageName: node - linkType: hard - -"uri-js@npm:^4.2.2": - version: 4.4.1 - resolution: "uri-js@npm:4.4.1" - dependencies: - punycode: ^2.1.0 - checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 - languageName: node - linkType: hard - -"use-sync-external-store@npm:1.2.0": - version: 1.2.0 - resolution: "use-sync-external-store@npm:1.2.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a - languageName: node - linkType: hard - -"v8-compile-cache@npm:^2.0.3": - version: 2.3.0 - resolution: "v8-compile-cache@npm:2.3.0" - checksum: adb0a271eaa2297f2f4c536acbfee872d0dd26ec2d76f66921aa7fc437319132773483344207bdbeee169225f4739016d8d2dbf0553913a52bb34da6d0334f8e - languageName: node - linkType: hard - -"web@workspace:apps/web": - version: 0.0.0-use.local - resolution: "web@workspace:apps/web" - dependencies: - "@babel/core": ^7.0.0 - "@types/node": ^17.0.12 - "@types/react": ^18.0.22 - "@types/react-dom": ^18.0.7 - eslint: 7.32.0 - eslint-config-custom: "*" - next: 13.0.0 - react: ^18.2.0 - react-dom: ^18.2.0 - tsconfig: "*" - typescript: ^4.5.3 - ui: "*" - languageName: unknown - linkType: soft - -"which-boxed-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "which-boxed-primitive@npm:1.0.2" - dependencies: - is-bigint: ^1.0.1 - is-boolean-object: ^1.1.0 - is-number-object: ^1.0.4 - is-string: ^1.0.5 - is-symbol: ^1.0.3 - checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: ^2.0.0 - bin: - node-which: ./bin/node-which - checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 - languageName: node - linkType: hard - -"word-wrap@npm:^1.2.3": - version: 1.2.3 - resolution: "word-wrap@npm:1.2.3" - checksum: 30b48f91fcf12106ed3186ae4fa86a6a1842416df425be7b60485de14bec665a54a68e4b5156647dec3a70f25e84d270ca8bc8cd23182ed095f5c7206a938c1f - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 - languageName: node - linkType: hard diff --git a/crates/turborepo-lockfiles/fixtures/workspace-peer-dependency.json b/crates/turborepo-lockfiles/fixtures/workspace-peer-dependency.json deleted file mode 100644 index 24f5eea0a5fd9..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/workspace-peer-dependency.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "name": "npm-test", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "npm-test", - "version": "1.0.0", - "license": "ISC", - "workspaces": ["packages/**"] - }, - "node_modules/a": { - "resolved": "packages/a", - "link": true - }, - "node_modules/b": { - "resolved": "packages/b", - "link": true - }, - "node_modules/eslint": { - "resolved": "packages/c", - "link": true - }, - "node_modules/eslint-plugin-turbo": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-1.9.3.tgz", - "integrity": "sha512-ZsRtksdzk3v+z5/I/K4E50E4lfZ7oYmLX395gkrUMBz4/spJlYbr+GC8hP9oVNLj9s5Pvnm9rLv/zoj5PVYaVw==", - "peerDependencies": { - "eslint": ">6.6.0" - } - }, - "packages/a": { - "dependencies": { - "eslint": "^0.0.0-workspace", - "eslint-plugin-turbo": "^1.9.3" - } - }, - "packages/b": { - "peerDependencies": { - "eslint": "*" - } - }, - "packages/c": { - "name": "eslint", - "version": "0.0.0-workspace" - } - }, - "dependencies": { - "a": { - "version": "file:packages/a", - "requires": { - "eslint": "^0.0.0-workspace", - "eslint-plugin-turbo": "^1.9.3" - } - }, - "b": { - "version": "file:packages/b", - "requires": {} - }, - "eslint": { - "version": "file:packages/c" - }, - "eslint-plugin-turbo": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-1.9.3.tgz", - "integrity": "sha512-ZsRtksdzk3v+z5/I/K4E50E4lfZ7oYmLX395gkrUMBz4/spJlYbr+GC8hP9oVNLj9s5Pvnm9rLv/zoj5PVYaVw==", - "requires": {} - } - } -} diff --git a/crates/turborepo-lockfiles/fixtures/yarn1.lock b/crates/turborepo-lockfiles/fixtures/yarn1.lock deleted file mode 100644 index fbfae8b3b786b..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/yarn1.lock +++ /dev/null @@ -1,50 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -nextjs@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/nextjs/-/nextjs-0.0.3.tgz#4f4d1d6a257be920d9b9649d4d9522c724a4e543" - integrity sha512-mYbDUo4/sRAZ8TqK63PCpYnFiLg7BICG/ot9+guOrUKd4/Fo71ZmEQ41IZbH6nqbQvG7SXTBuofJXAIWfNho0w== - -turbo-darwin-64@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.9.3.tgz#29470b902a1418dae8a88b2620caf917b27480bc" - integrity sha512-0dFc2cWXl82kRE4Z+QqPHhbEFEpUZho1msHXHWbz5+PqLxn8FY0lEVOHkq5tgKNNEd5KnGyj33gC/bHhpZOk5g== - -turbo-darwin-arm64@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.9.3.tgz#0eb404d6101ba69eab8522b16260a4eb50885e6c" - integrity sha512-1cYbjqLBA2zYE1nbf/qVnEkrHa4PkJJbLo7hnuMuGM0bPzh4+AnTNe98gELhqI1mkTWBu/XAEeF5u6dgz0jLNA== - -turbo-linux-64@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.9.3.tgz#dbce8fd50edee1319f17800ee38e7c4749ab0cb0" - integrity sha512-UuBPFefawEwpuxh5pM9Jqq3q4C8M0vYxVYlB3qea/nHQ80pxYq7ZcaLGEpb10SGnr3oMUUs1zZvkXWDNKCJb8Q== - -turbo-linux-arm64@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.9.3.tgz#636b77fde17c7a5cdef8a20616ff57f08c785345" - integrity sha512-vUrNGa3hyDtRh9W0MkO+l1dzP8Co2gKnOVmlJQW0hdpOlWlIh22nHNGGlICg+xFa2f9j4PbQlWTsc22c019s8Q== - -turbo-windows-64@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.9.3.tgz#c65625c222456161b0b4d000ec7f50e372332825" - integrity sha512-0BZ7YaHs6r+K4ksqWus1GKK3W45DuDqlmfjm/yuUbTEVc8szmMCs12vugU2Zi5GdrdJSYfoKfEJ/PeegSLIQGQ== - -turbo-windows-arm64@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-1.9.3.tgz#86e105692ad6ba935eff0284522bdf7728a2e517" - integrity sha512-QJUYLSsxdXOsR1TquiOmLdAgtYcQ/RuSRpScGvnZb1hY0oLc7JWU0llkYB81wVtWs469y8H9O0cxbKwCZGR4RQ== - -turbo@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.9.3.tgz#911012624f647f98d9788a08e25b98e38cdd48b2" - integrity sha512-ID7mxmaLUPKG/hVkp+h0VuucB1U99RPCJD9cEuSEOdIPoSIuomcIClEJtKamUsdPLhLCud+BvapBNnhgh58Nzw== - optionalDependencies: - turbo-darwin-64 "1.9.3" - turbo-darwin-arm64 "1.9.3" - turbo-linux-64 "1.9.3" - turbo-linux-arm64 "1.9.3" - turbo-windows-64 "1.9.3" - turbo-windows-arm64 "1.9.3" diff --git a/crates/turborepo-lockfiles/fixtures/yarn1full.lock b/crates/turborepo-lockfiles/fixtures/yarn1full.lock deleted file mode 100644 index f4272d1ee3047..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/yarn1full.lock +++ /dev/null @@ -1,2304 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== - dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/compat-data@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.0.tgz#2a592fd89bacb1fcde68de31bee4f2f2dacb0e86" - integrity sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw== - -"@babel/core@^7.0.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.0.tgz#d2f5f4f2033c00de8096be3c9f45772563e150c3" - integrity sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.0" - "@babel/helper-compilation-targets" "^7.19.0" - "@babel/helper-module-transforms" "^7.19.0" - "@babel/helpers" "^7.19.0" - "@babel/parser" "^7.19.0" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" - integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== - dependencies: - "@babel/types" "^7.19.0" - "@jridgewell/gen-mapping" "^0.3.2" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz#537ec8339d53e806ed422f1e06c8f17d55b96bb0" - integrity sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA== - dependencies: - "@babel/compat-data" "^7.19.0" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== - dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" - integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - -"@babel/helper-simple-access@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" - integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" - integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== - -"@babel/helper-validator-identifier@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" - integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helpers@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18" - integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.18.10", "@babel/parser@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.0.tgz#497fcafb1d5b61376959c1c338745ef0577aa02c" - integrity sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw== - -"@babel/runtime-corejs3@^7.10.2": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.19.0.tgz#0df75cb8e5ecba3ca9e658898694e5326d52397f" - integrity sha512-JyXXoCu1N8GLuKc2ii8y5RGma5FMpFeO2nAQIe0Yzrbq+rQnN+sFj47auLblR5ka6aHNGPDgv8G/iI2Grb0ldQ== - dependencies: - core-js-pure "^3.20.2" - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" - integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/traverse@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.0.tgz#eb9c561c7360005c592cc645abafe0c3c4548eed" - integrity sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.0" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.19.0" - "@babel/types" "^7.19.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" - integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA== - dependencies: - "@babel/helper-string-parser" "^7.18.10" - "@babel/helper-validator-identifier" "^7.18.6" - to-fast-properties "^2.0.0" - -"@eslint/eslintrc@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" - integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== - dependencies: - ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" - globals "^13.9.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" - integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== - dependencies: - "@humanwhocodes/object-schema" "^1.2.0" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/object-schema@^1.2.0": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" - integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@next/env@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.5.tgz#d908c57b35262b94db3e431e869b72ac3e1ad3e3" - integrity sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw== - -"@next/eslint-plugin-next@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.0.tgz#302c1f03618d5001ce92ea6826c329268759128e" - integrity sha512-jVdq1qYTNDjUtulnE8/hkPv0pHILV4jMg5La99iaY/FFm20WxVnsAZtbNnMvlPbf8dc010oO304SX9yXbg5PAw== - dependencies: - glob "7.1.7" - -"@next/swc-android-arm-eabi@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz#903a5479ab4c2705d9c08d080907475f7bacf94d" - integrity sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA== - -"@next/swc-android-arm64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz#2f9a98ec4166c7860510963b31bda1f57a77c792" - integrity sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg== - -"@next/swc-darwin-arm64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d" - integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg== - -"@next/swc-darwin-x64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz#2e44dd82b2b7fef88238d1bc4d3bead5884cedfd" - integrity sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A== - -"@next/swc-freebsd-x64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz#e24e75d8c2581bfebc75e4f08f6ddbd116ce9dbd" - integrity sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw== - -"@next/swc-linux-arm-gnueabihf@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz#46d8c514d834d2b5f67086013f0bd5e3081e10b9" - integrity sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg== - -"@next/swc-linux-arm64-gnu@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz#91f725ac217d3a1f4f9f53b553615ba582fd3d9f" - integrity sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ== - -"@next/swc-linux-arm64-musl@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz#e627e8c867920995810250303cd9b8e963598383" - integrity sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg== - -"@next/swc-linux-x64-gnu@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz#83a5e224fbc4d119ef2e0f29d0d79c40cc43887e" - integrity sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw== - -"@next/swc-linux-x64-musl@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz#be700d48471baac1ec2e9539396625584a317e95" - integrity sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g== - -"@next/swc-win32-arm64-msvc@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz#a93e958133ad3310373fda33a79aa10af2a0aa97" - integrity sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw== - -"@next/swc-win32-ia32-msvc@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz#4f5f7ba0a98ff89a883625d4af0125baed8b2e19" - integrity sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw== - -"@next/swc-win32-x64-msvc@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4" - integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@rushstack/eslint-patch@^1.1.3": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27" - integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA== - -"@swc/helpers@0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012" - integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA== - dependencies: - tslib "^2.4.0" - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/node@^17.0.12": - version "17.0.45" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" - integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== - -"@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== - -"@types/react-dom@^17.0.11": - version "17.0.17" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.17.tgz#2e3743277a793a96a99f1bf87614598289da68a1" - integrity sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg== - dependencies: - "@types/react" "^17" - -"@types/react@18.0.17": - version "18.0.17" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.17.tgz#4583d9c322d67efe4b39a935d223edcc7050ccf4" - integrity sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/react@^17", "@types/react@^17.0.37": - version "17.0.49" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.49.tgz#df87ba4ca8b7942209c3dc655846724539dc1049" - integrity sha512-CCBPMZaPhcKkYUTqFs/hOWqKjPxhTEmnZWjlHHgIMop67DsXywf9B5Os9Hz8KSacjNOgIdnZVJamwl232uxoPg== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== - -"@typescript-eslint/parser@^5.21.0": - version "5.36.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.36.2.tgz#3ddf323d3ac85a25295a55fcb9c7a49ab4680ddd" - integrity sha512-qS/Kb0yzy8sR0idFspI9Z6+t7mqk/oRjnAYfewG+VN73opAUvmYL3oPIMmgOX6CnQS6gmVIXGshlb5RY/R22pA== - dependencies: - "@typescript-eslint/scope-manager" "5.36.2" - "@typescript-eslint/types" "5.36.2" - "@typescript-eslint/typescript-estree" "5.36.2" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.36.2": - version "5.36.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.36.2.tgz#a75eb588a3879ae659514780831370642505d1cd" - integrity sha512-cNNP51L8SkIFSfce8B1NSUBTJTu2Ts4nWeWbFrdaqjmn9yKrAaJUBHkyTZc0cL06OFHpb+JZq5AUHROS398Orw== - dependencies: - "@typescript-eslint/types" "5.36.2" - "@typescript-eslint/visitor-keys" "5.36.2" - -"@typescript-eslint/types@5.36.2": - version "5.36.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.36.2.tgz#a5066e500ebcfcee36694186ccc57b955c05faf9" - integrity sha512-9OJSvvwuF1L5eS2EQgFUbECb99F0mwq501w0H0EkYULkhFa19Qq7WFbycdw1PexAc929asupbZcgjVIe6OK/XQ== - -"@typescript-eslint/typescript-estree@5.36.2": - version "5.36.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.2.tgz#0c93418b36c53ba0bc34c61fe9405c4d1d8fe560" - integrity sha512-8fyH+RfbKc0mTspfuEjlfqA4YywcwQK2Amcf6TDOwaRLg7Vwdu4bZzyvBZp4bjt1RRjQ5MDnOZahxMrt2l5v9w== - dependencies: - "@typescript-eslint/types" "5.36.2" - "@typescript-eslint/visitor-keys" "5.36.2" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/visitor-keys@5.36.2": - version "5.36.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.2.tgz#2f8f78da0a3bad3320d2ac24965791ac39dace5a" - integrity sha512-BtRvSR6dEdrNt7Net2/XDjbYKU5Ml6GqJgVfXT0CxTCJlnIqK7rAGreuWKMT2t8cFUT2Msv5oxw0GMRD7T5J7A== - dependencies: - "@typescript-eslint/types" "5.36.2" - eslint-visitor-keys "^3.3.0" - -acorn-jsx@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^7.4.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== - -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.1: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" - integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -aria-query@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" - integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== - dependencies: - "@babel/runtime" "^7.10.2" - "@babel/runtime-corejs3" "^7.10.2" - -array-includes@^3.1.4, array-includes@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" - integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - get-intrinsic "^1.1.1" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.flat@^1.2.5: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" - integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f" - integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" - es-shim-unscopables "^1.0.0" - -ast-types-flow@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -axe-core@^4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.3.tgz#11c74d23d5013c0fa5d183796729bc3482bd2f6f" - integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w== - -axobject-query@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" - integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.20.2: - version "4.21.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a" - integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ== - dependencies: - caniuse-lite "^1.0.30001370" - electron-to-chromium "^1.4.202" - node-releases "^2.0.6" - update-browserslist-db "^1.0.5" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -caniuse-lite@^1.0.30001332, caniuse-lite@^1.0.30001370: - version "1.0.30001393" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz#1aa161e24fe6af2e2ccda000fc2b94be0b0db356" - integrity sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA== - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -core-js-pure@^3.20.2: - version "3.25.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.1.tgz#79546518ae87cc362c991d9c2d211f45107991ee" - integrity sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A== - -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" - integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== - -damerau-levenshtein@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" - integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== - -debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -electron-to-chromium@^1.4.202: - version "1.4.244" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.244.tgz#ae9b56ed4ae2107e3a860dad80ed662c936e369e" - integrity sha512-E21saXLt2eTDaTxgUtiJtBUqanF9A32wZasAwDZ8gvrqXoxrBrbwtDCx7c/PQTLp81wj4X0OLDeoGQg7eMo3+w== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -enhanced-resolve@^5.7.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -enquirer@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5: - version "1.20.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.2.tgz#8495a07bc56d342a3b8ea3ab01bd986700c2ccb3" - integrity sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.2" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.2" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-shim-unscopables@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== - dependencies: - has "^1.0.3" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-next@^12.0.8: - version "12.3.0" - resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.0.tgz#d887ab2d143fe1a2b308e9321e932a613e610800" - integrity sha512-guHSkNyKnTBB8HU35COgAMeMV0E026BiYRYvyEVVaTOeFcnU3i1EI8/Da0Rl7H3Sgua5FEvoA0vYd2s8kdIUXg== - dependencies: - "@next/eslint-plugin-next" "12.3.0" - "@rushstack/eslint-patch" "^1.1.3" - "@typescript-eslint/parser" "^5.21.0" - eslint-import-resolver-node "^0.3.6" - eslint-import-resolver-typescript "^2.7.1" - eslint-plugin-import "^2.26.0" - eslint-plugin-jsx-a11y "^6.5.1" - eslint-plugin-react "^7.29.4" - eslint-plugin-react-hooks "^4.5.0" - -eslint-config-prettier@^8.3.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" - integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== - -eslint-config-turbo@latest: - version "0.0.3" - resolved "https://registry.yarnpkg.com/eslint-config-turbo/-/eslint-config-turbo-0.0.3.tgz#61a3b6fdc4186bb6832ab4b48bb6ed2d3bad57a8" - integrity sha512-hK5MlxDugUWZV9ZKcyfNwLXrlMuM2wPgAUk51cUFBC3nXRCVmCA9uSRFBZsyAIurN1wH7mS7G1NBo5F8VkF7lQ== - dependencies: - eslint-plugin-turbo "0.0.3" - -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== - dependencies: - debug "^3.2.7" - resolve "^1.20.0" - -eslint-import-resolver-typescript@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz#a90a4a1c80da8d632df25994c4c5fdcdd02b8751" - integrity sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ== - dependencies: - debug "^4.3.4" - glob "^7.2.0" - is-glob "^4.0.3" - resolve "^1.22.0" - tsconfig-paths "^3.14.1" - -eslint-module-utils@^2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" - integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== - dependencies: - debug "^3.2.7" - -eslint-plugin-import@^2.26.0: - version "2.26.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" - integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== - dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.3" - has "^1.0.3" - is-core-module "^2.8.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.values "^1.1.5" - resolve "^1.22.0" - tsconfig-paths "^3.14.1" - -eslint-plugin-jsx-a11y@^6.5.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz#93736fc91b83fdc38cc8d115deedfc3091aef1ff" - integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q== - dependencies: - "@babel/runtime" "^7.18.9" - aria-query "^4.2.2" - array-includes "^3.1.5" - ast-types-flow "^0.0.7" - axe-core "^4.4.3" - axobject-query "^2.2.0" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - has "^1.0.3" - jsx-ast-utils "^3.3.2" - language-tags "^1.0.5" - minimatch "^3.1.2" - semver "^6.3.0" - -eslint-plugin-react-hooks@^4.5.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - -eslint-plugin-react@7.31.7, eslint-plugin-react@^7.29.4: - version "7.31.7" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.7.tgz#36fb1c611a7db5f757fce09cbbcc01682f8b0fbb" - integrity sha512-8NldBTeYp/kQoTV1uT0XF6HcmDqbgZ0lNPkN0wlRw8DJKXEnaWu+oh/6gt3xIhzvQ35wB2Y545fJhIbJSZ2NNw== - dependencies: - array-includes "^3.1.5" - array.prototype.flatmap "^1.3.0" - doctrine "^2.1.0" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.5" - object.fromentries "^2.0.5" - object.hasown "^1.1.1" - object.values "^1.1.5" - prop-types "^15.8.1" - resolve "^2.0.0-next.3" - semver "^6.3.0" - string.prototype.matchall "^4.0.7" - -eslint-plugin-turbo@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-turbo/-/eslint-plugin-turbo-0.0.3.tgz#9d86895732f95b0c236d6363177a52368fffdc71" - integrity sha512-QjidATGxWtaB9QUrD3NocUySmsgWKZlBMFlw4kX2IIjRLAxMPwukk90h3ZTaNXyRHuaQsrEgh7hhlCZoxP0TTw== - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@7.32.0, eslint@^7.23.0, eslint@^7.32.0: - version "7.32.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" - integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== - dependencies: - "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.3" - "@humanwhocodes/config-array" "^0.5.0" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - enquirer "^2.3.5" - escape-string-regexp "^4.0.0" - eslint-scope "^5.1.1" - eslint-utils "^2.1.0" - eslint-visitor-keys "^2.0.0" - espree "^7.3.1" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.1.2" - globals "^13.6.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^6.0.9" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== - dependencies: - acorn "^7.4.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" - integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.3, glob@^7.2.0: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.6.0, globals@^13.9.0: - version "13.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" - integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -graceful-fs@^4.2.4: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-core-module@^2.8.1, is-core-module@^2.9.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" - integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== - dependencies: - array-includes "^3.1.5" - object.assign "^4.1.3" - -language-subtag-registry@~0.3.2: - version "0.3.22" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" - integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== - -language-tags@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== - dependencies: - language-subtag-registry "~0.3.2" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -next-transpile-modules@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/next-transpile-modules/-/next-transpile-modules-9.0.0.tgz#133b1742af082e61cc76b02a0f12ffd40ce2bf90" - integrity sha512-VCNFOazIAnXn1hvgYYSTYMnoWgKgwlYh4lm1pKbSfiB3kj5ZYLcKVhfh3jkPOg1cnd9DP+pte9yCUocdPEUBTQ== - dependencies: - enhanced-resolve "^5.7.0" - escalade "^3.1.1" - -next@12.2.5: - version "12.2.5" - resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717" - integrity sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA== - dependencies: - "@next/env" "12.2.5" - "@swc/helpers" "0.4.3" - caniuse-lite "^1.0.30001332" - postcss "8.4.14" - styled-jsx "5.0.4" - use-sync-external-store "1.2.0" - optionalDependencies: - "@next/swc-android-arm-eabi" "12.2.5" - "@next/swc-android-arm64" "12.2.5" - "@next/swc-darwin-arm64" "12.2.5" - "@next/swc-darwin-x64" "12.2.5" - "@next/swc-freebsd-x64" "12.2.5" - "@next/swc-linux-arm-gnueabihf" "12.2.5" - "@next/swc-linux-arm64-gnu" "12.2.5" - "@next/swc-linux-arm64-musl" "12.2.5" - "@next/swc-linux-x64-gnu" "12.2.5" - "@next/swc-linux-x64-musl" "12.2.5" - "@next/swc-win32-arm64-msvc" "12.2.5" - "@next/swc-win32-ia32-msvc" "12.2.5" - "@next/swc-win32-x64-msvc" "12.2.5" - -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.12.2, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.3, object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.entries@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" - integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -object.fromentries@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" - integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -object.hasown@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3" - integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A== - dependencies: - define-properties "^1.1.4" - es-abstract "^1.19.5" - -object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -postcss@8.4.14: - version "8.4.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" - integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== - dependencies: - nanoid "^3.3.4" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier@latest: - version "2.7.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" - integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -react-dom@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react@18.2.0, react@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve@^1.20.0, resolve@^1.22.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.3: - version "2.0.0-next.4" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" - integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.2.1, semver@^7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== - dependencies: - lru-cache "^6.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string.prototype.matchall@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d" - integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - regexp.prototype.flags "^1.4.1" - side-channel "^1.0.4" - -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -styled-jsx@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53" - integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -table@^6.0.9: - version "6.8.0" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" - integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - -tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tsconfig-paths@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" - integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.1" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -turbo-android-arm64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-android-arm64/-/turbo-android-arm64-1.4.6.tgz#2127110335a86a50856852c2728eb75f7f61b77b" - integrity sha512-YxSlHc64CF5J7yNUMiLBHkeLyzrpe75Oy7tivWb3z7ySG44BXPikk4HDJZPh0T1ELvukDwuPKkvDukJ2oCLJpA== - -turbo-darwin-64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.4.6.tgz#8b3d930ed0d0b8c358d87ed2347381496f4283dd" - integrity sha512-f6uto7LLpjwZ6iZSF+8uaDpuiTji6xmnWDxNuW23DBE8iv5mxehHd+6Ys851uKDRrPb3QdCu9ctyigKTAla5Vg== - -turbo-darwin-arm64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.4.6.tgz#7f045cbfbb1d6ac18ea28122b9a6a5fdc629488a" - integrity sha512-o9C6e5XyuMHQwE0fEhUxfpXxvNr2QXXWX8nxIjygxeF19AqKbk/s08vZBOEmXV6/gx/pRhZ1S2nf0PIUjKBD/Q== - -turbo-freebsd-64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.4.6.tgz#b16c5617f2e818a709627351f1e14d1fd8dcf0e7" - integrity sha512-Gg9VOUo6McXYKGevcYjGUSmMryZyZggvpdPh7Dw3QTcT8Tsy6OBtq6WnJ2O4kFDsMigyKtEOJPceD9vDMZt3yQ== - -turbo-freebsd-arm64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.4.6.tgz#462b8ba68cccac93d169c80cf458d221c662a770" - integrity sha512-W7VrcneWFN1QENKt5cpAPSsf9ArYBBAm3VtPBZEO5tX8kuahGlah1SKdKJXrRxYOY82wyNxDagS/rHpBlrAAzw== - -turbo-linux-32@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.4.6.tgz#0a0859be0941e4bcdc4bff81b97ee36f02cc1ffd" - integrity sha512-76j/zsui6mWPX8pZVMGgF8eiKHPmKuGa2lo0A/Ja0HUvdYCOGUfHsWJGVVIeYbuEp3jsKyVt7OnMDeH9CqO6bg== - -turbo-linux-64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.4.6.tgz#0a7d76fab78d7850c26d9d6b372c40ffca9835f8" - integrity sha512-z4A37Xm7lZyO9ddtGnvQHWMrsAKX6vFBxdbtb9MY76VRblo7lWSuk4LwCeM+T+ZDJ9LBFiF7aD/diRShlLx9jA== - -turbo-linux-arm64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.4.6.tgz#c66d3c6917ccbdb34cd7ce37c900613f4d690ebc" - integrity sha512-FW1jmOpZfOoVVvml338N0MPnYjiMyYWTaMb4T+IosgGYymcUE3xJjfXJcqfU/9/uKTyY8zG0qr9/5rw2kpMS2Q== - -turbo-linux-arm@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-linux-arm/-/turbo-linux-arm-1.4.6.tgz#9a9d73a722bdd6acb40276d0616c155168a32172" - integrity sha512-Uh/V3oaAdhyZW6FKPpKihAxQo3EbvLaVNnzzkBmBnvHRkqoDJHhpuG72V7nn8pzxVbJ1++NEVjvbc2kmKFvGjg== - -turbo-linux-mips64le@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-linux-mips64le/-/turbo-linux-mips64le-1.4.6.tgz#eb74c333c16ef03aa30dcb83fcc29d58218656e4" - integrity sha512-iWaL3Pwj52BH3T2M8nXScmbSnq4+x47MYK7lJMG7FsZGAIoT5ToO1Wt1iX3GRHTcnIZYm/kCfJ1ptK/NCossLA== - -turbo-linux-ppc64le@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.4.6.tgz#74597f4c30fe73c92ef8912e4bf25ccbe7c7ec7e" - integrity sha512-Af/KlUmpiORDyELxT7byXNWl3fefErGQMJfeqXEtAdhs8OCKQWuU+lchcZbiBZYNpL+lZoa3PAmP9Fpx7R4plA== - -turbo-windows-32@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-windows-32/-/turbo-windows-32-1.4.6.tgz#df1f3c25fea0bbccf7c5b44111ddbcd57f6fe547" - integrity sha512-NBd+XPlRSaR//lVN13Q9DOqK3CbowSvafIyGsO4jfvMsGTdyNDL6AYtFsvTKW91/G7ZhATmSEkPn2pZRuhP/DA== - -turbo-windows-64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.4.6.tgz#6a7d8897bb60234b6bc4b5d013adb00fac6f2beb" - integrity sha512-86AbmG+CjzVTpn4RGtwU2CYy4zSyAc9bIQ4pDGLIpCJg6JlD11duaiMJh0SCU/HCqWLJjWDI4qD+f9WNbgPsyQ== - -turbo-windows-arm64@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-1.4.6.tgz#4c80528c6670ef50129053ad8279c832190b7234" - integrity sha512-V+pWcqhTtmQQ3ew8qEjYtUwzyW6tO1RgvP+6OKzItYzTnMTr1Fe42Q21V+tqRNxuNfFDKsgVJdk2p5wB87bvyQ== - -turbo@latest: - version "1.4.6" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.4.6.tgz#c97c23cf898380bedabd04c5a91ab4eb9829bcdc" - integrity sha512-FKtBXlOJ7YjSK22yj4sJLCtDcHFElypt7xw9cZN7Wyv9x4XBrTmh5KP6RmcGnRR1/GJlTNwD2AY2T9QTPnHh+g== - optionalDependencies: - turbo-android-arm64 "1.4.6" - turbo-darwin-64 "1.4.6" - turbo-darwin-arm64 "1.4.6" - turbo-freebsd-64 "1.4.6" - turbo-freebsd-arm64 "1.4.6" - turbo-linux-32 "1.4.6" - turbo-linux-64 "1.4.6" - turbo-linux-arm "1.4.6" - turbo-linux-arm64 "1.4.6" - turbo-linux-mips64le "1.4.6" - turbo-linux-ppc64le "1.4.6" - turbo-windows-32 "1.4.6" - turbo-windows-64 "1.4.6" - turbo-windows-arm64 "1.4.6" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -typescript@^4.5.2, typescript@^4.5.3, typescript@^4.7.4: - version "4.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.3.tgz#d59344522c4bc464a65a730ac695007fdb66dd88" - integrity sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -update-browserslist-db@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz#16279639cff1d0f800b14792de43d97df2d11b7d" - integrity sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -use-sync-external-store@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== - -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/crates/turborepo-lockfiles/fixtures/yarn4-direct-and-indirect.lock b/crates/turborepo-lockfiles/fixtures/yarn4-direct-and-indirect.lock deleted file mode 100644 index d5637b6f38dac..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/yarn4-direct-and-indirect.lock +++ /dev/null @@ -1,78 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10 - -"a@workspace:packages/a": - version: 0.0.0-use.local - resolution: "a@workspace:packages/a" - dependencies: - is-odd: "patch:is-odd@npm%3A3.0.1#~/.yarn/patches/is-odd-npm-3.0.1-93c3c3f41b.patch" - languageName: unknown - linkType: soft - -"b@workspace:packages/b": - version: 0.0.0-use.local - resolution: "b@workspace:packages/b" - dependencies: - is-even: "npm:^1.0.0" - languageName: unknown - linkType: soft - -"is-even@npm:^1.0.0": - version: 1.0.0 - resolution: "is-even@npm:1.0.0" - dependencies: - is-odd: "npm:^0.1.2" - checksum: 0267545d7cb6724aee249e88942cf22f6263aa006cd9bf83c2ddbb2a1d47280e8c4d72b2d50e38bd3575df717c993904b44153cc1772a55dabca250ca40cc4f7 - languageName: node - linkType: hard - -"is-number@npm:^3.0.0": - version: 3.0.0 - resolution: "is-number@npm:3.0.0" - checksum: 0c62bf8e9d72c4dd203a74d8cfc751c746e75513380fef420cda8237e619a988ee43e678ddb23c87ac24d91ac0fe9f22e4ffb1301a50310c697e9d73ca3994e9 - languageName: node - linkType: hard - -"is-number@npm:^6.0.0": - version: 6.0.0 - resolution: "is-number@npm:6.0.0" - checksum: 8668b49747649ee0878e0a6d9e35e1c95bab58c5dd1a2b698df34989512ec553cfd090fa7af247d590afe4b12ec996e735b9a670c2cf0efbaefe7fb2c2457615 - languageName: node - linkType: hard - -"is-odd@npm:3.0.1": - version: 3.0.1 - resolution: "is-odd@npm:3.0.1" - dependencies: - is-number: "npm:^6.0.0" - checksum: c9d35c336c0c0ada0bfaf1f4564f354a222c4ffb9c3b42fac353767c9b8f0af844d3ddf16fbf7b12d6ecf57ee4d2fbeb9e456e8c9d68a78bb44e91bb43fdfd56 - languageName: node - linkType: hard - -"is-odd@npm:^0.1.2": - version: 0.1.2 - resolution: "is-odd@npm:0.1.2" - dependencies: - is-number: "npm:^3.0.0" - checksum: 146069d7622c991c75c17ca63bccf5470cd730c24082874e53e797a10ff38a896197d6ce34ad137a2f422dcc614b10ff24d31fe93dcdb29f0cb758f2d924f477 - languageName: node - linkType: hard - -"is-odd@patch:is-odd@npm%3A3.0.1#~/.yarn/patches/is-odd-npm-3.0.1-93c3c3f41b.patch": - version: 3.0.1 - resolution: "is-odd@patch:is-odd@npm%3A3.0.1#~/.yarn/patches/is-odd-npm-3.0.1-93c3c3f41b.patch::version=3.0.1&hash=496de7" - dependencies: - is-number: "npm:^6.0.0" - checksum: 8da62f4b41d59d4c15e90b7dc619b1312668421b982908c3792324bb0622128c1b8d484b96ccd15c05eab50dcdef64c169686c2dba92b925914c4c85ce4300f9 - languageName: node - linkType: hard - -"small-yarn4@workspace:.": - version: 0.0.0-use.local - resolution: "small-yarn4@workspace:." - languageName: unknown - linkType: soft diff --git a/crates/turborepo-lockfiles/fixtures/yarn4-mixed-protocol.lock b/crates/turborepo-lockfiles/fixtures/yarn4-mixed-protocol.lock deleted file mode 100644 index a537612228869..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/yarn4-mixed-protocol.lock +++ /dev/null @@ -1,34 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"a@workspace:pkgs/a": - version: 0.0.0-use.local - resolution: "a@workspace:pkgs/a" - dependencies: - c: "npm:*" - languageName: unknown - linkType: soft - -"b@workspace:pkgs/b": - version: 0.0.0-use.local - resolution: "b@workspace:pkgs/b" - dependencies: - c: "workspace:*" - languageName: unknown - linkType: soft - -"c@npm:*, c@workspace:*, c@workspace:pkgs/c": - version: 0.0.0-use.local - resolution: "c@workspace:pkgs/c" - languageName: unknown - linkType: soft - -"yarn4-test@workspace:.": - version: 0.0.0-use.local - resolution: "yarn4-test@workspace:." - languageName: unknown - linkType: soft diff --git a/crates/turborepo-lockfiles/fixtures/yarn4-patch.lock b/crates/turborepo-lockfiles/fixtures/yarn4-patch.lock deleted file mode 100644 index b6542f802f3d1..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/yarn4-patch.lock +++ /dev/null @@ -1,60 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"a@workspace:packages/a": - version: 0.0.0-use.local - resolution: "a@workspace:packages/a" - dependencies: - c: "workspace:*" - languageName: unknown - linkType: soft - -"b@workspace:packages/b": - version: 0.0.0-use.local - resolution: "b@workspace:packages/b" - dependencies: - c: "workspace:*" - is-odd: "patch:is-odd@npm%3A3.0.1#~/.yarn/patches/is-odd-npm-3.0.1-93c3c3f41b.patch" - languageName: unknown - linkType: soft - -"c@workspace:*, c@workspace:packages/c": - version: 0.0.0-use.local - resolution: "c@workspace:packages/c" - languageName: unknown - linkType: soft - -"is-number@npm:^6.0.0": - version: 6.0.0 - resolution: "is-number@npm:6.0.0" - checksum: 5da4c68401529675c575878d2760d66f18eaef4b014858577f6003daf66488d7fe4eae684b1e8574e3fa1bb447c6c6c56b8491d2b4b3239da2d32e5f6f218008 - languageName: node - linkType: hard - -"is-odd@npm:3.0.1": - version: 3.0.1 - resolution: "is-odd@npm:3.0.1" - dependencies: - is-number: "npm:^6.0.0" - checksum: 89ee2e353c5a3f3bd400c79db1c307a5b3506198ee8169d521e533a9b1d8a08fc95f21a919c084e98845b4286d7ffe309778da03744dfe66c3c1763ab1a030c6 - languageName: node - linkType: hard - -"is-odd@patch:is-odd@npm%3A3.0.1#~/.yarn/patches/is-odd-npm-3.0.1-93c3c3f41b.patch": - version: 3.0.1 - resolution: "is-odd@patch:is-odd@npm%3A3.0.1#~/.yarn/patches/is-odd-npm-3.0.1-93c3c3f41b.patch::version=3.0.1&hash=9b90ad" - dependencies: - is-number: "npm:^6.0.0" - checksum: 4cd944e688e02e147969d6c1784bad1156f6084edbbd4d688f6a37b5fc764671aa99679494fc0bfaf623919bea2779e724fffc31c6ee0432b7c91f174526e5fe - languageName: node - linkType: hard - -"yarn4-patch@workspace:.": - version: 0.0.0-use.local - resolution: "yarn4-patch@workspace:." - languageName: unknown - linkType: soft diff --git a/crates/turborepo-lockfiles/fixtures/yarn4-resolution.lock b/crates/turborepo-lockfiles/fixtures/yarn4-resolution.lock deleted file mode 100644 index 6d5efb0f4c184..0000000000000 --- a/crates/turborepo-lockfiles/fixtures/yarn4-resolution.lock +++ /dev/null @@ -1,47 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10 - -"@reproduce/something@workspace:packages/something": - version: 0.0.0-use.local - resolution: "@reproduce/something@workspace:packages/something" - dependencies: - react: "npm:^18.2.0" - languageName: unknown - linkType: soft - -"js-tokens@npm:^3.0.0 || ^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 10/af37d0d913fb56aec6dc0074c163cc71cd23c0b8aad5c2350747b6721d37ba118af35abdd8b33c47ec2800de07dedb16a527ca9c530ee004093e04958bd0cbf2 - languageName: node - linkType: hard - -"loose-envify@npm:^1.1.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" - dependencies: - js-tokens: "npm:^3.0.0 || ^4.0.0" - bin: - loose-envify: cli.js - checksum: 10/6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 - languageName: node - linkType: hard - -"react@npm:18.1.0": - version: 18.1.0 - resolution: "react@npm:18.1.0" - dependencies: - loose-envify: "npm:^1.1.0" - checksum: 10/d1ec025276096aa8b87cc4ee95f911612f21c4d54e08a3fdf5a9d3d2242f825142eef300b13f26e17a14a94adcb640f4278ae5b4fe0de3a912adc325434b9a2a - languageName: node - linkType: hard - -"reproduce@workspace:.": - version: 0.0.0-use.local - resolution: "reproduce@workspace:." - languageName: unknown - linkType: soft diff --git a/crates/turborepo-lockfiles/src/berry/protocol_resolver.rs b/crates/turborepo-lockfiles/src/berry/protocol_resolver.rs deleted file mode 100644 index 471229dac69ec..0000000000000 --- a/crates/turborepo-lockfiles/src/berry/protocol_resolver.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::collections::HashMap; - -use super::identifiers::{Descriptor, Ident}; - -/// A data structure for resolving descriptors when the protocol isn't known -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct DescriptorResolver { - mapping: HashMap, -} - -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -struct Key { - ident: Ident<'static>, - range: String, -} - -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)] -struct Entry { - without: Option, - with: Option, -} - -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)] -struct RangeAndProtocol { - protocol: String, - range: String, -} - -impl DescriptorResolver { - /// Add a descriptor to the resolver - pub fn insert(&mut self, descriptor: &Descriptor) -> Option { - let key = Key::new(descriptor)?; - let entry = self.mapping.entry(key).or_default(); - entry.insert_descriptor(descriptor) - } - - /// If given a descriptor without a protocol it will return all matching - /// descriptors with a protocol - pub fn get(&self, descriptor: &Descriptor) -> Option<&str> { - let key = Key::new(descriptor)?; - self.mapping.get(&key).and_then(|e| e.get(descriptor)) - } -} - -impl Key { - fn new(desc: &Descriptor) -> Option { - let ident = desc.ident.to_owned(); - let range = Descriptor::strip_protocol(desc.range()?).to_string(); - Some(Key { ident, range }) - } -} - -impl Entry { - // Insert the given descriptor's range into the correct slot depending if it is - // with or without a protocol - fn insert_descriptor(&mut self, descriptor: &Descriptor) -> Option { - let range = descriptor.range()?.to_string(); - match descriptor.protocol() { - Some(protocol) => { - // Yarn 4 made the default npm protocol explicit in the lockfile. - // In order to return the more specific protocol we avoid overwriting other - // protocols with the now explicit npm protocol. - if protocol != "npm" || self.with.is_none() { - match self.with.replace(RangeAndProtocol { - range, - protocol: protocol.to_string(), - }) { - // We only return an ejected range if the protocol isn't the default npm - // protocol - Some(RangeAndProtocol { range, protocol }) if protocol != "npm" => { - Some(range) - } - _ => None, - } - } else { - None - } - } - None => self.without.replace(range), - } - } - - fn get(&self, descriptor: &Descriptor) -> Option<&str> { - // We only return the without protocol range if `without` is present - // and the given descriptor is also without a protocol - if self.without.is_some() && descriptor.protocol().is_none() { - self.without.as_deref() - } else { - self.with.as_ref().map(|x| x.range.as_str()) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_descriptor_reconstruction() { - let mut resolver = DescriptorResolver::default(); - let babel_npm = Descriptor::new("@babel/core", "npm:^5.0.0").unwrap(); - let babel_file = Descriptor::new("@babel/core", "file:4.5.0").unwrap(); - assert!(resolver.insert(&babel_npm).is_none()); - assert!(resolver.insert(&babel_file).is_none()); - let babel_5 = Descriptor::new("@babel/core", "^5.0.0").unwrap(); - let babel_4 = Descriptor::new("@babel/core", "4.5.0").unwrap(); - assert_eq!(resolver.get(&babel_5), Some("npm:^5.0.0")); - assert_eq!(resolver.get(&babel_4), Some("file:4.5.0")); - } - - #[test] - fn test_descriptors_without_protocols() { - let mut resolver = DescriptorResolver::default(); - let workspace = Descriptor::new("internal-workspace", "*").unwrap(); - let workspace_with_protocol = Descriptor::new("internal-workspace", "workspace:*").unwrap(); - assert!(resolver.insert(&workspace).is_none()); - assert!(resolver.insert(&workspace_with_protocol).is_none()); - assert_eq!(resolver.get(&workspace), Some("*")); - assert_eq!(resolver.get(&workspace_with_protocol), Some("workspace:*")); - } -} diff --git a/crates/turborepo-lockfiles/src/berry/ser.rs b/crates/turborepo-lockfiles/src/berry/ser.rs deleted file mode 100644 index 65dce5eec9211..0000000000000 --- a/crates/turborepo-lockfiles/src/berry/ser.rs +++ /dev/null @@ -1,312 +0,0 @@ -use std::{borrow::Cow, fmt, sync::OnceLock}; - -use regex::Regex; - -use super::{BerryPackage, DependencyMeta, LockfileData, Metadata}; - -fn simple_string() -> &'static Regex { - static RE: OnceLock = OnceLock::new(); - RE.get_or_init(|| { - Regex::new(r#"^[^-?:,\]\[{}#&*!|>'"%@` \t\r\n]([ \t]*[^,\]\[{}:# \t\r\n])*$"#).unwrap() - }) -} - -const HEADER: &str = "# This file is generated by running \"yarn install\" inside your project. -# Manual changes might be lost - proceed with caution! -"; - -// We implement Display in order to produce a correctly serialized `yarn.lock` -// Since Berry is so particular about the contents we can't use the serde_yaml -// serializer without forking it and heavy modifications. Implementing Display -// is more honest than writing a Serializer implementation since the serializer -// would only support a single type. -impl fmt::Display for LockfileData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{HEADER}\n{}\n", self.metadata)?; - - for (key, entry) in &self.packages { - let wrapped_key = wrap_string(key); - // Yaml 1.2 spec says that keys over 1024 characters need to be prefixed with ? - // and the : goes in a new line - let key_line = match wrapped_key.len() <= 1024 { - true => format!("{wrapped_key}:"), - false => format!("? {wrapped_key}\n:"), - }; - write!(f, "\n{}\n{}\n", key_line, entry)?; - } - - Ok(()) - } -} - -impl fmt::Display for Metadata { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "__metadata:\n version: {}", self.version,)?; - if let Some(cache_key) = &self.cache_key { - write!(f, "\n cacheKey: {}", wrap_string(cache_key))?; - } - Ok(()) - } -} - -const SPACE: char = ' '; -const NEWLINE: char = '\n'; -const INDENT: &str = " "; - -impl fmt::Display for BerryPackage { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // we only want to write a newline there was something before - let mut first = true; - let mut write_line = |field: &str, whitespace: char, value: &str| -> fmt::Result { - if !value.is_empty() { - if !first { - writeln!(f)?; - } - write!(f, " {field}:{whitespace}{}", value,)?; - first = false; - } - Ok(()) - }; - - write_line("version", SPACE, &wrap_string(self.version.as_ref()))?; - write_line("resolution", SPACE, &wrap_string(&self.resolution))?; - if let Some(deps) = &self.dependencies { - write_line( - "dependencies", - NEWLINE, - &stringify_dependencies(deps.iter()), - )?; - } - if let Some(peer_deps) = &self.peer_dependencies { - write_line( - "peerDependencies", - NEWLINE, - &stringify_dependencies(peer_deps.iter()), - )?; - } - if let Some(deps_meta) = &self.dependencies_meta { - write_line( - "dependenciesMeta", - NEWLINE, - &stringify_dependencies_meta(deps_meta.iter()), - )?; - } - if let Some(peer_deps_meta) = &self.peer_dependencies_meta { - write_line( - "peerDependenciesMeta", - NEWLINE, - &stringify_dependencies_meta(peer_deps_meta.iter()), - )?; - } - if let Some(bin) = &self.bin { - write_line("bin", NEWLINE, &stringify_dependencies(bin.iter()))?; - } - - if let Some(checksum) = &self.checksum { - write_line("checksum", SPACE, &wrap_string(checksum))?; - } - if let Some(conditions) = &self.conditions { - write_line("conditions", SPACE, &wrap_string(conditions))?; - } - if let Some(language_name) = &self.language_name { - write_line("languageName", SPACE, &wrap_string(language_name))?; - } - if let Some(link_type) = &self.link_type { - write_line("linkType", SPACE, &wrap_string(link_type))?; - } - - Ok(()) - } -} - -fn stringify_dependencies(entries: I) -> String -where - I: Iterator, - S1: AsRef, - S2: AsRef, -{ - let mut string = String::new(); - let mut first = true; - for (key, value) in entries { - let key = key.as_ref(); - let value = value.as_ref(); - - if !first { - string.push('\n'); - } - string.push_str(&format!(" {}: {}", wrap_string(key), wrap_string(value))); - first = false; - } - string -} - -fn stringify_dependencies_meta<'a, I, S>(metadata: I) -> String -where - I: Iterator, - S: AsRef, -{ - struct Builder { - s: String, - } - - impl Builder { - fn new() -> Self { - Self { s: String::new() } - } - - fn add_field(&mut self, field: &str, value: bool) { - if !self.s.is_empty() { - self.s.push('\n'); - } - self.s.push_str(&format!( - "{INDENT}{INDENT}{INDENT}{}: {value}", - wrap_string(field) - )); - } - - fn add_dependency(&mut self, dependency: &str) { - if !self.s.is_empty() { - self.s.push('\n'); - } - self.s - .push_str(&format!("{INDENT}{INDENT}{}:", wrap_string(dependency),)); - } - } - - let mut builder = Builder::new(); - - for (dependency, meta) in metadata { - let dependency = dependency.as_ref(); - let mut first = true; - let mut add_line = |field: &str, value: bool| { - if first { - builder.add_dependency(dependency); - } - builder.add_field(field, value); - first = false; - }; - if let Some(optional) = meta.optional { - add_line("optional", optional); - } - if let Some(unplugged) = meta.unplugged { - add_line("unplugged", unplugged); - } - if let Some(built) = meta.built { - add_line("built", built); - } - } - - builder.s -} - -fn wrap_string(s: &str) -> Cow { - match simple_string().is_match(s) { - // Simple strings require no wrapping - true => Cow::from(s), - // Complex strings require wrapping - false => { - Cow::from(serde_json::to_string(s).unwrap_or_else(|_| panic!("Unable to encode '{s}'"))) - } - } -} - -#[cfg(test)] -mod test { - use pretty_assertions::assert_eq; - - use super::*; - - #[test] - fn test_metadata_display() { - let metadata = Metadata { - version: "6".into(), - cache_key: Some("8c0".to_string()), - }; - assert_eq!( - metadata.to_string(), - "__metadata: - version: 6 - cacheKey: 8c0" - ); - } - - #[test] - fn test_wrap_string() { - fn assert(input: &str, expected: &str) { - assert_eq!(wrap_string(input), expected); - } - assert("debug@4.3.4", "debug@4.3.4"); - assert( - "eslint-module-utils@npm:^2.7.3", - "\"eslint-module-utils@npm:^2.7.3\"", - ); - assert("@babel/core", "\"@babel/core\""); - } - - #[test] - fn test_long_key_gets_wrapped() { - let long_key = "a".repeat(1025); - let lockfile = LockfileData { - metadata: Metadata { - version: "6".into(), - cache_key: Some("8".into()), - }, - packages: [( - long_key.clone(), - BerryPackage { - version: "1.2.3".to_string(), - ..Default::default() - }, - )] - .iter() - .cloned() - .collect(), - }; - let serialized = lockfile.to_string(); - assert!(serialized.contains(&format!("? {long_key}\n"))); - } - - #[test] - fn test_stringify_dependencies_meta() { - let metadata = DependencyMeta { - optional: Some(false), - unplugged: None, - built: Some(true), - }; - assert_eq!( - stringify_dependencies_meta(Some(("turbo", &metadata)).into_iter()), - " turbo:\n optional: false\n built: true" - ); - } - - #[test] - fn test_stringify_dependencies_meta_multi() { - let foo = DependencyMeta { - optional: Some(true), - unplugged: None, - built: None, - }; - let bar = DependencyMeta { - optional: None, - unplugged: None, - built: Some(true), - }; - assert_eq!( - stringify_dependencies_meta(vec![("foo", &foo), ("bar", &bar)].into_iter()), - " foo:\n optional: true\n bar:\n built: true" - ); - } - - #[test] - fn test_empty_dep_meta() { - let metadata = DependencyMeta { - optional: None, - unplugged: None, - built: None, - }; - assert_eq!( - stringify_dependencies_meta(Some(("turbo", &metadata)).into_iter()), - "" - ); - } -} diff --git a/crates/turborepo-lockfiles/src/bun/de.rs b/crates/turborepo-lockfiles/src/bun/de.rs deleted file mode 100644 index b0da7d08e3089..0000000000000 --- a/crates/turborepo-lockfiles/src/bun/de.rs +++ /dev/null @@ -1,317 +0,0 @@ -use std::sync::OnceLock; - -use nom::{ - branch::alt, - bytes::complete::{escaped_transform, is_not, tag, take_till}, - character::complete::{anychar, char as nom_char, crlf, newline, none_of, satisfy, space1}, - combinator::{all_consuming, map, not, opt, peek, recognize, value}, - multi::{count, many0, many1}, - sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, - IResult, -}; -use regex::Regex; -use serde_json::Value; - -// regex for trimming spaces from start and end -fn pseudostring_replace() -> &'static Regex { - static RE: OnceLock = OnceLock::new(); - RE.get_or_init(|| Regex::new(r"^ *| *$").unwrap()) -} - -pub fn parse_syml(input: &str) -> Result { - match all_consuming(property_statements(0))(input) { - Ok((_, value)) => Ok(value), - Err(e) => Err(super::Error::SymlParse(e.to_string())), - } -} - -// Array and map types -fn item_statements(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| map(many0(item_statement(level)), Value::Array)(i) -} - -fn item_statement(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| { - let (i, _) = indent(level)(i)?; - let (i, _) = nom_char('-')(i)?; - let (i, _) = blankspace(i)?; - expression(level)(i) - } -} - -fn property_statements(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| { - let (i, properties) = many0(property_statement(level))(i)?; - let mut map = serde_json::Map::new(); - for (key, value) in properties.into_iter().flatten() { - map.insert(key, value); - } - Ok((i, Value::Object(map))) - } -} - -fn property_statement(level: usize) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { - move |i: &str| { - alt(( - value( - vec![], - tuple(( - opt(blankspace), - opt(pair(nom_char('#'), many1(pair(not(eol), anychar)))), - many1(eol_any), - )), - ), - map( - preceded( - indent(level), - separated_pair(name, wrapped_colon, expression(level)), - ), - |entry| vec![entry], - ), - // legacy names - map( - preceded( - indent(level), - separated_pair(legacy_name, wrapped_colon, expression(level)), - ), - |entry| vec![entry], - ), - // legacy prop without colon - map( - preceded( - indent(level), - separated_pair( - legacy_name, - blankspace, - terminated(legacy_literal, many1(eol_any)), - ), - ), - |entry| vec![entry], - ), - multikey_property_statement(level), - ))(i) - } -} - -fn multikey_property_statement( - level: usize, -) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { - move |i: &str| { - let (i, ()) = indent(level)(i)?; - let (i, property) = legacy_name(i)?; - let (i, others) = many1(preceded( - delimited(opt(blankspace), nom_char(','), opt(blankspace)), - legacy_name, - ))(i)?; - let (i, _) = wrapped_colon(i)?; - let (i, value) = expression(level)(i)?; - - Ok(( - i, - std::iter::once(property) - .chain(others) - .map(|key| (key, value.clone())) - .collect(), - )) - } -} - -fn wrapped_colon(i: &str) -> IResult<&str, char> { - delimited(opt(blankspace), nom_char(':'), opt(blankspace))(i) -} - -fn expression(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| { - alt(( - preceded( - tuple(( - peek(tuple((eol, indent(level + 1), nom_char('-'), blankspace))), - eol_any, - )), - item_statements(level + 1), - ), - preceded(eol, property_statements(level + 1)), - terminated(literal, many1(eol_any)), - ))(i) - } -} - -fn indent(level: usize) -> impl Fn(&str) -> IResult<&str, ()> { - move |i: &str| { - let (i, _) = count(nom_char(' '), level * 2)(i)?; - Ok((i, ())) - } -} - -// Simple types - -fn name(i: &str) -> IResult<&str, String> { - alt((string, pseudostring))(i) -} - -fn legacy_name(i: &str) -> IResult<&str, String> { - alt(( - string, - map(recognize(many1(pseudostring_legacy)), |s| s.to_string()), - ))(i) -} - -fn literal(i: &str) -> IResult<&str, Value> { - alt(( - value(Value::Null, null), - map(boolean, Value::Bool), - map(string, Value::String), - map(pseudostring, Value::String), - ))(i) -} - -fn legacy_literal(i: &str) -> IResult<&str, Value> { - alt(( - value(Value::Null, null), - map(string, Value::String), - map(pseudostring_legacy, Value::String), - ))(i) -} - -fn pseudostring(i: &str) -> IResult<&str, String> { - let (i, pseudo) = recognize(pseudostring_inner)(i)?; - Ok(( - i, - pseudostring_replace().replace_all(pseudo, "").into_owned(), - )) -} - -fn pseudostring_inner(i: &str) -> IResult<&str, ()> { - let (i, _) = none_of("\r\n\t ?:,][{}#&*!|>'\"%@`-")(i)?; - let (i, _) = many0(tuple((opt(blankspace), none_of("\r\n\t ,][{}:#\"'"))))(i)?; - Ok((i, ())) -} - -fn pseudostring_legacy(i: &str) -> IResult<&str, String> { - let (i, pseudo) = recognize(pseudostring_legacy_inner)(i)?; - let replaced = pseudostring_replace().replace_all(pseudo, ""); - Ok((i, replaced.to_string())) -} - -fn pseudostring_legacy_inner(i: &str) -> IResult<&str, ()> { - let (i, _) = opt(tag("--"))(i)?; - let (i, _) = satisfy(|c| c.is_ascii_alphanumeric() || c == '/')(i)?; - let (i, _) = take_till(|c| "\r\n\t :,".contains(c))(i)?; - Ok((i, ())) -} - -// String parsing - -fn null(i: &str) -> IResult<&str, &str> { - tag("null")(i) -} - -fn boolean(i: &str) -> IResult<&str, bool> { - alt((value(true, tag("true")), value(false, tag("false"))))(i) -} - -fn string(i: &str) -> IResult<&str, String> { - alt((empty_string, delimited(tag("\""), syml_chars, tag("\""))))(i) -} - -fn empty_string(i: &str) -> IResult<&str, String> { - let (i, _) = tag(r#""""#)(i)?; - Ok((i, "".to_string())) -} - -fn syml_chars(i: &str) -> IResult<&str, String> { - // The SYML grammar provided by Yarn2+ includes escape sequences that weren't - // supported by the yarn1 parser. We diverge from the Yarn2+ provided - // grammar to match the actual parser used by yarn1. - escaped_transform( - is_not("\"\\"), - '\\', - alt(( - value("\"", tag("\"")), - value("\\", tag("\\")), - value("/", tag("/")), - value("\n", tag("n")), - value("\r", tag("r")), - value("\t", tag("t")), - )), - )(i) -} - -// Spaces -fn blankspace(i: &str) -> IResult<&str, &str> { - space1(i) -} - -fn eol_any(i: &str) -> IResult<&str, &str> { - recognize(tuple((eol, many0(tuple((opt(blankspace), eol))))))(i) -} - -fn eol(i: &str) -> IResult<&str, &str> { - alt((crlf, value("\n", newline), value("\r", nom_char('\r'))))(i) -} - -#[cfg(test)] -mod test { - use serde_json::json; - use test_case::test_case; - - use super::*; - - #[test_case("null", Value::Null ; "null")] - #[test_case("false", Value::Bool(false) ; "literal false")] - #[test_case("true", Value::Bool(true) ; "literal true")] - #[test_case("\"\"", Value::String("".into()) ; "empty string literal")] - #[test_case("\"foo\"", Value::String("foo".into()) ; "quoted string literal")] - #[test_case("foo", Value::String("foo".into()) ; "unquoted string literal")] - fn test_literal(input: &str, expected: Value) { - let (_, actual) = literal(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("name: foo", "name" ; "basic")] - #[test_case("technically a name: foo", "technically a name" ; "multiword name")] - fn test_name(input: &str, expected: &str) { - let (_, actual) = name(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("foo@1:", "foo@1" ; "name with colon terminator")] - #[test_case("\"foo@1\":", "foo@1" ; "qutoed name with colon terminator")] - #[test_case("name foo", "name" ; "name without colon terminator")] - fn test_legacy_name(input: &str, expected: &str) { - let (_, actual) = legacy_name(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("null\n", Value::Null ; "null")] - #[test_case("\"foo\"\n", json!("foo") ; "basic string")] - #[test_case("\n name: foo\n", json!({ "name": "foo" }) ; "basic object")] - fn test_expression(input: &str, expected: Value) { - let (_, actual) = expression(0)(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("# a comment\n", vec![] ; "comment")] - #[test_case("foo: null\n", vec![("foo".into(), Value::Null)] ; "single property")] - #[test_case("name foo\n", vec![("name".into(), json!("foo"))] ; "legacy property")] - fn test_property_statement(input: &str, expected: Vec<(String, Value)>) { - let (_, actual) = property_statement(0)(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("name: foo\n", json!({"name": "foo"}) ; "single property object")] - #[test_case("\"name\": foo\n", json!({"name": "foo"}) ; "single quoted property object")] - #[test_case("name foo\n", json!({"name": "foo"}) ; "single property without colon object")] - #[test_case("# comment\nname: foo\n", json!({"name": "foo"}) ; "comment doesn't affect object")] - #[test_case("name foo\nversion \"1.2.3\"\n", json!({"name": "foo", "version": "1.2.3"}) ; "multi-property object")] - #[test_case("foo:\n version \"1.2.3\"\n", json!({"foo": {"version": "1.2.3"}}) ; "nested object")] - #[test_case("foo, bar, baz:\n version \"1.2.3\"\n", json!({ - "foo": {"version": "1.2.3"}, - "bar": {"version": "1.2.3"}, - "baz": {"version": "1.2.3"}, - }) ; "multi-key object")] - fn test_property_statements(input: &str, expected: Value) { - let (_, actual) = property_statements(0)(input).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/crates/turborepo-lockfiles/src/pnpm/de.rs b/crates/turborepo-lockfiles/src/pnpm/de.rs deleted file mode 100644 index 106ac6e7f42dc..0000000000000 --- a/crates/turborepo-lockfiles/src/pnpm/de.rs +++ /dev/null @@ -1,40 +0,0 @@ -use serde::Deserialize; - -use super::{LockfileVersion, VersionFormat}; - -impl From for LockfileVersion { - fn from(value: f32) -> Self { - Self { - version: value.to_string(), - format: VersionFormat::Float, - } - } -} - -impl From for LockfileVersion { - fn from(value: String) -> Self { - Self { - version: value, - format: VersionFormat::String, - } - } -} - -impl<'de> Deserialize<'de> for LockfileVersion { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - #[derive(Deserialize)] - #[serde(untagged)] - enum StringOrNum { - Str(String), - Num(f32), - } - - Ok(match StringOrNum::deserialize(deserializer)? { - StringOrNum::Num(x) => LockfileVersion::from(x), - StringOrNum::Str(s) => LockfileVersion::from(s), - }) - } -} diff --git a/crates/turborepo-lockfiles/src/pnpm/ser.rs b/crates/turborepo-lockfiles/src/pnpm/ser.rs deleted file mode 100644 index 632c91a7a3ccd..0000000000000 --- a/crates/turborepo-lockfiles/src/pnpm/ser.rs +++ /dev/null @@ -1,19 +0,0 @@ -use serde::Serialize; - -use super::{LockfileVersion, VersionFormat}; - -impl Serialize for LockfileVersion { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self.format { - VersionFormat::String => serializer.serialize_str(&self.version), - VersionFormat::Float => serializer.serialize_f32( - self.version - .parse() - .expect("Expected lockfile version to be valid f32"), - ), - } - } -} diff --git a/crates/turborepo-lockfiles/src/yarn1/de.rs b/crates/turborepo-lockfiles/src/yarn1/de.rs deleted file mode 100644 index b0da7d08e3089..0000000000000 --- a/crates/turborepo-lockfiles/src/yarn1/de.rs +++ /dev/null @@ -1,317 +0,0 @@ -use std::sync::OnceLock; - -use nom::{ - branch::alt, - bytes::complete::{escaped_transform, is_not, tag, take_till}, - character::complete::{anychar, char as nom_char, crlf, newline, none_of, satisfy, space1}, - combinator::{all_consuming, map, not, opt, peek, recognize, value}, - multi::{count, many0, many1}, - sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, - IResult, -}; -use regex::Regex; -use serde_json::Value; - -// regex for trimming spaces from start and end -fn pseudostring_replace() -> &'static Regex { - static RE: OnceLock = OnceLock::new(); - RE.get_or_init(|| Regex::new(r"^ *| *$").unwrap()) -} - -pub fn parse_syml(input: &str) -> Result { - match all_consuming(property_statements(0))(input) { - Ok((_, value)) => Ok(value), - Err(e) => Err(super::Error::SymlParse(e.to_string())), - } -} - -// Array and map types -fn item_statements(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| map(many0(item_statement(level)), Value::Array)(i) -} - -fn item_statement(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| { - let (i, _) = indent(level)(i)?; - let (i, _) = nom_char('-')(i)?; - let (i, _) = blankspace(i)?; - expression(level)(i) - } -} - -fn property_statements(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| { - let (i, properties) = many0(property_statement(level))(i)?; - let mut map = serde_json::Map::new(); - for (key, value) in properties.into_iter().flatten() { - map.insert(key, value); - } - Ok((i, Value::Object(map))) - } -} - -fn property_statement(level: usize) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { - move |i: &str| { - alt(( - value( - vec![], - tuple(( - opt(blankspace), - opt(pair(nom_char('#'), many1(pair(not(eol), anychar)))), - many1(eol_any), - )), - ), - map( - preceded( - indent(level), - separated_pair(name, wrapped_colon, expression(level)), - ), - |entry| vec![entry], - ), - // legacy names - map( - preceded( - indent(level), - separated_pair(legacy_name, wrapped_colon, expression(level)), - ), - |entry| vec![entry], - ), - // legacy prop without colon - map( - preceded( - indent(level), - separated_pair( - legacy_name, - blankspace, - terminated(legacy_literal, many1(eol_any)), - ), - ), - |entry| vec![entry], - ), - multikey_property_statement(level), - ))(i) - } -} - -fn multikey_property_statement( - level: usize, -) -> impl Fn(&str) -> IResult<&str, Vec<(String, Value)>> { - move |i: &str| { - let (i, ()) = indent(level)(i)?; - let (i, property) = legacy_name(i)?; - let (i, others) = many1(preceded( - delimited(opt(blankspace), nom_char(','), opt(blankspace)), - legacy_name, - ))(i)?; - let (i, _) = wrapped_colon(i)?; - let (i, value) = expression(level)(i)?; - - Ok(( - i, - std::iter::once(property) - .chain(others) - .map(|key| (key, value.clone())) - .collect(), - )) - } -} - -fn wrapped_colon(i: &str) -> IResult<&str, char> { - delimited(opt(blankspace), nom_char(':'), opt(blankspace))(i) -} - -fn expression(level: usize) -> impl Fn(&str) -> IResult<&str, Value> { - move |i: &str| { - alt(( - preceded( - tuple(( - peek(tuple((eol, indent(level + 1), nom_char('-'), blankspace))), - eol_any, - )), - item_statements(level + 1), - ), - preceded(eol, property_statements(level + 1)), - terminated(literal, many1(eol_any)), - ))(i) - } -} - -fn indent(level: usize) -> impl Fn(&str) -> IResult<&str, ()> { - move |i: &str| { - let (i, _) = count(nom_char(' '), level * 2)(i)?; - Ok((i, ())) - } -} - -// Simple types - -fn name(i: &str) -> IResult<&str, String> { - alt((string, pseudostring))(i) -} - -fn legacy_name(i: &str) -> IResult<&str, String> { - alt(( - string, - map(recognize(many1(pseudostring_legacy)), |s| s.to_string()), - ))(i) -} - -fn literal(i: &str) -> IResult<&str, Value> { - alt(( - value(Value::Null, null), - map(boolean, Value::Bool), - map(string, Value::String), - map(pseudostring, Value::String), - ))(i) -} - -fn legacy_literal(i: &str) -> IResult<&str, Value> { - alt(( - value(Value::Null, null), - map(string, Value::String), - map(pseudostring_legacy, Value::String), - ))(i) -} - -fn pseudostring(i: &str) -> IResult<&str, String> { - let (i, pseudo) = recognize(pseudostring_inner)(i)?; - Ok(( - i, - pseudostring_replace().replace_all(pseudo, "").into_owned(), - )) -} - -fn pseudostring_inner(i: &str) -> IResult<&str, ()> { - let (i, _) = none_of("\r\n\t ?:,][{}#&*!|>'\"%@`-")(i)?; - let (i, _) = many0(tuple((opt(blankspace), none_of("\r\n\t ,][{}:#\"'"))))(i)?; - Ok((i, ())) -} - -fn pseudostring_legacy(i: &str) -> IResult<&str, String> { - let (i, pseudo) = recognize(pseudostring_legacy_inner)(i)?; - let replaced = pseudostring_replace().replace_all(pseudo, ""); - Ok((i, replaced.to_string())) -} - -fn pseudostring_legacy_inner(i: &str) -> IResult<&str, ()> { - let (i, _) = opt(tag("--"))(i)?; - let (i, _) = satisfy(|c| c.is_ascii_alphanumeric() || c == '/')(i)?; - let (i, _) = take_till(|c| "\r\n\t :,".contains(c))(i)?; - Ok((i, ())) -} - -// String parsing - -fn null(i: &str) -> IResult<&str, &str> { - tag("null")(i) -} - -fn boolean(i: &str) -> IResult<&str, bool> { - alt((value(true, tag("true")), value(false, tag("false"))))(i) -} - -fn string(i: &str) -> IResult<&str, String> { - alt((empty_string, delimited(tag("\""), syml_chars, tag("\""))))(i) -} - -fn empty_string(i: &str) -> IResult<&str, String> { - let (i, _) = tag(r#""""#)(i)?; - Ok((i, "".to_string())) -} - -fn syml_chars(i: &str) -> IResult<&str, String> { - // The SYML grammar provided by Yarn2+ includes escape sequences that weren't - // supported by the yarn1 parser. We diverge from the Yarn2+ provided - // grammar to match the actual parser used by yarn1. - escaped_transform( - is_not("\"\\"), - '\\', - alt(( - value("\"", tag("\"")), - value("\\", tag("\\")), - value("/", tag("/")), - value("\n", tag("n")), - value("\r", tag("r")), - value("\t", tag("t")), - )), - )(i) -} - -// Spaces -fn blankspace(i: &str) -> IResult<&str, &str> { - space1(i) -} - -fn eol_any(i: &str) -> IResult<&str, &str> { - recognize(tuple((eol, many0(tuple((opt(blankspace), eol))))))(i) -} - -fn eol(i: &str) -> IResult<&str, &str> { - alt((crlf, value("\n", newline), value("\r", nom_char('\r'))))(i) -} - -#[cfg(test)] -mod test { - use serde_json::json; - use test_case::test_case; - - use super::*; - - #[test_case("null", Value::Null ; "null")] - #[test_case("false", Value::Bool(false) ; "literal false")] - #[test_case("true", Value::Bool(true) ; "literal true")] - #[test_case("\"\"", Value::String("".into()) ; "empty string literal")] - #[test_case("\"foo\"", Value::String("foo".into()) ; "quoted string literal")] - #[test_case("foo", Value::String("foo".into()) ; "unquoted string literal")] - fn test_literal(input: &str, expected: Value) { - let (_, actual) = literal(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("name: foo", "name" ; "basic")] - #[test_case("technically a name: foo", "technically a name" ; "multiword name")] - fn test_name(input: &str, expected: &str) { - let (_, actual) = name(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("foo@1:", "foo@1" ; "name with colon terminator")] - #[test_case("\"foo@1\":", "foo@1" ; "qutoed name with colon terminator")] - #[test_case("name foo", "name" ; "name without colon terminator")] - fn test_legacy_name(input: &str, expected: &str) { - let (_, actual) = legacy_name(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("null\n", Value::Null ; "null")] - #[test_case("\"foo\"\n", json!("foo") ; "basic string")] - #[test_case("\n name: foo\n", json!({ "name": "foo" }) ; "basic object")] - fn test_expression(input: &str, expected: Value) { - let (_, actual) = expression(0)(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("# a comment\n", vec![] ; "comment")] - #[test_case("foo: null\n", vec![("foo".into(), Value::Null)] ; "single property")] - #[test_case("name foo\n", vec![("name".into(), json!("foo"))] ; "legacy property")] - fn test_property_statement(input: &str, expected: Vec<(String, Value)>) { - let (_, actual) = property_statement(0)(input).unwrap(); - assert_eq!(actual, expected); - } - - #[test_case("name: foo\n", json!({"name": "foo"}) ; "single property object")] - #[test_case("\"name\": foo\n", json!({"name": "foo"}) ; "single quoted property object")] - #[test_case("name foo\n", json!({"name": "foo"}) ; "single property without colon object")] - #[test_case("# comment\nname: foo\n", json!({"name": "foo"}) ; "comment doesn't affect object")] - #[test_case("name foo\nversion \"1.2.3\"\n", json!({"name": "foo", "version": "1.2.3"}) ; "multi-property object")] - #[test_case("foo:\n version \"1.2.3\"\n", json!({"foo": {"version": "1.2.3"}}) ; "nested object")] - #[test_case("foo, bar, baz:\n version \"1.2.3\"\n", json!({ - "foo": {"version": "1.2.3"}, - "bar": {"version": "1.2.3"}, - "baz": {"version": "1.2.3"}, - }) ; "multi-key object")] - fn test_property_statements(input: &str, expected: Value) { - let (_, actual) = property_statements(0)(input).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/crates/turborepo-lsp/Cargo.toml b/crates/turborepo-lsp/Cargo.toml index 5b1f508321fb9..a1d4487b2dbd0 100644 --- a/crates/turborepo-lsp/Cargo.toml +++ b/crates/turborepo-lsp/Cargo.toml @@ -1,26 +1,33 @@ -[package] -name = "turborepo-lsp" -version = "0.1.0" -edition = "2021" -license = "MIT" - -[features] -default = ["rustls-tls"] -native-tls = ["turborepo-lib/native-tls"] -rustls-tls = ["turborepo-lib/rustls-tls"] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] crop = "0.4.0" -itertools.workspace = true jsonc-parser = "0.23.0" pidlock = { version = "0.1.4", path = "../turborepo-pidlock" } -serde_json.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros", "io-std"] } tokio-retry = "0.3.0" tower-lsp = "0.20.0" turbopath = { version = "0.1.0", path = "../turborepo-paths" } turborepo-lib = { version = "0.1.0", path = "../turborepo-lib" } turborepo-repository = { version = "0.1.0", path = "../turborepo-repository" } -wax.workspace = true + +[dependencies.itertools] +workspace = true + +[dependencies.serde_json] +workspace = true + +[dependencies.wax] +workspace = true + +[features] +default = ["rustls-tls"] +native-tls = ["turborepo-lib/native-tls"] +rustls-tls = ["turborepo-lib/rustls-tls"] + +[lib] +path = "Source/lib.rs" + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-lsp" +version = "0.1.0" diff --git a/crates/turborepo-lsp/Source/lib.rs b/crates/turborepo-lsp/Source/lib.rs new file mode 100644 index 0000000000000..8af0175725fd3 --- /dev/null +++ b/crates/turborepo-lsp/Source/lib.rs @@ -0,0 +1,931 @@ +//! Turbo LSP server +//! +//! This is the main entry point for the LSP server. It is responsible for +//! handling all LSP requests and responses. +//! +//! For more, see the [LSP specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/) +//! as well as the architecture documentation in `packages/turbo-vsc`. + +#![feature(box_patterns)] +#![deny(clippy::all)] +#![warn(clippy::unwrap_used)] + +use std::{ + borrow::Cow, + collections::{HashMap, HashSet}, + iter, + sync::{Arc, Mutex}, +}; + +use itertools::{Itertools, chain}; +use jsonc_parser::{ + CollectOptions, + ast::{ObjectPropName, StringLit}, +}; +use serde_json::Value; +use tokio::sync::watch::{Receiver, Sender}; +use tower_lsp::{ + Client, + LanguageServer, + jsonrpc::{Error, Result as LspResult}, + lsp_types::*, +}; +use turbopath::AbsoluteSystemPathBuf; +use turborepo_lib::{ + DaemonClient, + DaemonConnector, + DaemonConnectorError, + DaemonError, + DaemonPackageDiscovery, + DaemonPaths, +}; +use turborepo_repository::{ + discovery::{self, DiscoveryResponse, PackageDiscovery, WorkspaceData}, + package_json::PackageJson, +}; + +pub struct Backend { + client:Client, + repo_root:Arc>>, + files:Mutex>, + initializer:Sender>>, + daemon:Receiver>>, + + // this is only used for turbo optimize + pidlock:Mutex>, +} + +#[tower_lsp::async_trait] +impl LanguageServer for Backend { + async fn initialize(&self, params:InitializeParams) -> LspResult { + if let Some(uri) = params.root_uri { + if uri.scheme() != "file" { + return Err(Error::invalid_params("root is not a local file")); + } + + let repo_root = uri + .to_file_path() + .map_err(|_| Error::invalid_params("root is not a local file"))?; + let repo_root = repo_root + .as_os_str() + .to_str() + .ok_or(Error::invalid_params("root is not a valid utf-8 path"))?; + + // convert uri file:///absolute-path to AbsoluteSystemPathBuf + let repo_root = + AbsoluteSystemPathBuf::new(repo_root).expect("file is always an absolute path"); + + self.repo_root + .lock() + .expect("only fails if poisoned") + .replace(repo_root.clone()); + + let paths = DaemonPaths::from_repo_root(&repo_root); + + let (_, daemon) = tokio::join!( + self.client + .log_message(MessageType::INFO, format!("root uri: {}", paths.sock_file),), + tokio_retry::Retry::spawn( + tokio_retry::strategy::FixedInterval::from_millis(100).take(5), + || { + let can_start_server = true; + let can_kill_server = false; + let connector = + DaemonConnector::new(can_start_server, can_kill_server, &repo_root); + connector.connect() + }, + ) + ); + + let daemon = match daemon { + Ok(daemon) => daemon, + Err(DaemonConnectorError::Handshake(box DaemonError::VersionMismatch(message))) => { + self.client + .show_message( + MessageType::ERROR, + "Pre-2.0 versions of turborepo are not compatible with 2.0 or later \ + of the extension. If you do not plan to update to turbo 2.0, please \ + ensure you install the latest 1.0 version of the extension in this \ + workspace.", + ) + .await; + self.client + .log_message( + MessageType::ERROR, + format!("version mismatch when connecting to daemon: {}", message), + ) + .await; + + // in this case, just say we don't support any features + return Ok(InitializeResult { ..Default::default() }); + }, + Err(e) => { + self.client + .log_message( + MessageType::ERROR, + format!("failed to connect to daemon: {}", e), + ) + .await; + return Err(Error::internal_error()); + }, + }; + + self.initializer.send(Some(daemon)).expect("there is a receiver"); + + let mut lock = pidlock::Pidlock::new(paths.lsp_pid_file.as_std_path().to_owned()); + + if let Err(e) = lock.acquire() { + self.client + .log_message( + MessageType::ERROR, + format!( + "failed to acquire pidlock, is another lsp instance running? - {}", + e + ), + ) + .await; + return Err(Error::internal_error()); + } + + *self.pidlock.lock().expect("only fails if poisoned") = Some(lock); + } + + Ok(InitializeResult { + server_info:None, + capabilities:ServerCapabilities { + text_document_sync:Some(TextDocumentSyncCapability::Kind( + TextDocumentSyncKind::INCREMENTAL, + )), + completion_provider:Some(CompletionOptions { + resolve_provider:Some(false), + trigger_characters:Some(vec![".".to_string()]), + work_done_progress_options:Default::default(), + all_commit_characters:None, + ..Default::default() + }), + execute_command_provider:Some(ExecuteCommandOptions { + commands:vec![ + // "turbo.run".to_string(), + // todo: port these from JS land + // "turbo.daemon.start".to_string(), + // "turbo.daemon.status".to_string(), + // "turbo.daemon.stop".to_string(), + ], + work_done_progress_options:Default::default(), + }), + workspace:Some(WorkspaceServerCapabilities { + workspace_folders:Some(WorkspaceFoldersServerCapabilities { + supported:Some(true), + change_notifications:Some(OneOf::Left(true)), + }), + file_operations:None, + }), + code_lens_provider:Some(CodeLensOptions { resolve_provider:None }), + code_action_provider:Some(CodeActionProviderCapability::Options( + CodeActionOptions { + code_action_kinds:Some(vec![CodeActionKind::QUICKFIX]), + resolve_provider:None, + work_done_progress_options:WorkDoneProgressOptions { + work_done_progress:None, + }, + }, + )), + references_provider:Some(OneOf::Right(ReferencesOptions { + work_done_progress_options:WorkDoneProgressOptions { work_done_progress:None }, + })), + ..ServerCapabilities::default() + }, + }) + } + + /// Find which projects / scripts are affected by a given pipeline item + async fn references(&self, params:ReferenceParams) -> LspResult>> { + self.client.log_message(MessageType::INFO, "references!").await; + + let Some(referenced_task) = ({ + let rope = { + let map = self.files.lock().expect("only fails if poisoned"); + match map.get(¶ms.text_document_position.text_document.uri) { + Some(files) => files, + None => return Ok(None), + } + .to_owned() // cloning is cheap + }; + + let text = rope.chunks().join(""); + let parse = jsonc_parser::parse_to_ast( + &text, + &CollectOptions { comments:true, tokens:true }, + &Default::default(), + ); + + // iterate pipeline items, and see if any of their ranges intersect + // with the reference request's position + let parse = match parse { + Ok(parse) => parse, + Err(_err) => { + // if it is not a valid json, then there are no references + return Ok(None); + }, + }; + + parse + .value + .as_ref() + .and_then(|v| v.as_object()) + .and_then(|o| o.get_object("tasks")) + .map(|p| p.properties.iter()) + .into_iter() + .flatten() + .find_map(|task| { + let mut range = task.range; + range.start += 1; // account for quote + let key_range = range.start + task.name.as_str().len(); + range.end = key_range; + + // convert ast range to lsp range + let lsp_range = convert_ranges(&rope, range); + + if lsp_range.start < params.text_document_position.position + && lsp_range.end > params.text_document_position.position + { + Some(task.name.as_str().to_string()) + } else { + None + } + }) + }) else { + // no overlap with any task definitions, exit + return Ok(None); + }; + + self.client + .log_message(MessageType::INFO, format!("finding references for {:?}", referenced_task)) + .await; + + let repo_root = self.repo_root.lock().expect("only fails if poisoned").clone(); + + let repo_root = match repo_root { + Some(repo_root) => repo_root, + None => { + self.client + .log_message(MessageType::INFO, "received request before initialization") + .await; + return Ok(None); + }, + }; + + let packages = match self.package_discovery().await { + Ok(packages) => packages, + Err(e) => { + self.client.log_message(MessageType::WARNING, e.to_string()).await; + + // there aren't really any other errors we can return here, other than + // an internal error + let mut error = Error::internal_error(); + error.message = "failed to get package list from the daemon".into(); + return Err(error); + }, + }; + + let mut locations = vec![]; + for wd in packages.workspaces { + let data = match std::fs::read_to_string(&wd.package_json) { + Ok(data) => data, + // if we can't read a package.json, then we can't set up references to it + // so we just skip it and do a best effort + Err(_) => continue, + }; + let package_json = match PackageJson::load_from_str(&data, wd.package_json.as_str()) { + Ok(package_json) => package_json, + // if we can't parse a package.json, then we can't set up references to it + // so we just skip it and do a best effort + Err(_) => continue, + }; + let scripts = package_json.scripts.into_keys().collect::>(); + + // if in the root, the name should be '//' + let package_json_name = if repo_root.contains(&wd.package_json) { + Some("//") + } else { + package_json.name.as_deref() + }; + + // todo: use jsonc_ast instead of text search + let rope = crop::Rope::from(data.clone()); + + let (package, task) = referenced_task + .rsplit_once('#') + .map(|(p, t)| (Some(p), t)) + .unwrap_or((None, &referenced_task)); + + if let (Some(package), Some(package_name)) = (package, package_json_name) { + if package_name != package { + continue; + } + }; + + let Some(start) = data.find(&format!("\"{}\"", task)) else { + continue; + }; + let end = start + task.len() + 2; + + let start_line = rope.line_of_byte(start); + let end_line = rope.line_of_byte(end); + + let range = Range { + start:Position { + line:start_line as u32, + character:(start - rope.byte_of_line(start_line)) as u32, + }, + end:Position { + line:end_line as u32, + character:(end - rope.byte_of_line(end_line)) as u32, + }, + }; + + if scripts.contains(task) { + let location = Location::new( + Url::from_file_path(&wd.package_json).expect("only fails if path is relative"), + range, + ); + locations.push(location); + } + } + + Ok(Some(locations)) + } + + /// Add code lens items for running a particular task in the turbo.json + async fn code_lens(&self, params:CodeLensParams) -> LspResult>> { + self.client.log_message(MessageType::INFO, "code lens!").await; + + let rope = { + let map = self.files.lock().expect("only fails if poisoned"); + match map.get(¶ms.text_document.uri) { + Some(files) => files, + None => return Ok(None), + } + .to_owned() // cloning is cheap + }; + + let text = rope.chunks().join(""); + let parse = jsonc_parser::parse_to_ast( + &text, + &CollectOptions { comments:true, tokens:true }, + &Default::default(), + ); + + let parse = match parse { + Ok(parse) => parse, + Err(_err) => { + // todo: do we error here? + // self.client + // .log_message(MessageType::ERROR, format!("{:?}", err)) + // .await; + return Ok(None); + }, + }; + + let pipeline = parse + .value + .as_ref() + .and_then(|v| v.as_object()) + .and_then(|o| o.get_object("tasks")) + .map(|p| p.properties.iter()) + .into_iter() + .flatten(); + + let mut tasks = vec![]; + for task in pipeline { + let mut range = task.range; + range.start += 1; // account for quote + let key_range = range.start + task.name.as_str().len(); + range.end = key_range; + + tasks.push(CodeLens { + command:Some(Command { + title:format!("Run {}", task.name.as_str()), + command:"turbo.run".to_string(), + arguments:Some(vec![Value::String(task.name.as_str().to_string())]), + }), + range:convert_ranges(&rope, range), + data:None, + }); + } + + Ok(Some(tasks)) + } + + /// Given a list of diagnistics that we previously reported, produce code + /// actions that the user can run + async fn code_action(&self, params:CodeActionParams) -> LspResult> { + self.client.log_message(MessageType::INFO, format!("{:#?}", params)).await; + + let mut code_actions = vec![]; + + for diag in params.context.diagnostics { + match &diag.code { + Some(NumberOrString::String(s)) if s == "deprecated:env-var" => { + code_actions.push(CodeActionOrCommand::CodeAction(CodeAction { + title:"Apply codemod".to_string(), + command:Some(Command { + title:"Apply codemod".to_string(), + command:"turbo.codemod".to_string(), + arguments:Some(vec![Value::String( + "migrate-env-var-dependencies".to_string(), + )]), + }), + diagnostics:Some(vec![diag]), + kind:Some(CodeActionKind::QUICKFIX), + is_preferred:Some(true), + ..Default::default() + })) + }, + _ => {}, + } + } + + Ok(Some(code_actions)) + } + + async fn initialized(&self, _:InitializedParams) { + self.client.log_message(MessageType::INFO, "initialized!").await; + } + + async fn shutdown(&self) -> LspResult<()> { Ok(()) } + + async fn did_change_workspace_folders(&self, _:DidChangeWorkspaceFoldersParams) { + self.client.log_message(MessageType::INFO, "workspace folders changed!").await; + } + + async fn did_change_configuration(&self, _:DidChangeConfigurationParams) { + self.client.log_message(MessageType::INFO, "configuration changed!").await; + } + + async fn did_change_watched_files(&self, _:DidChangeWatchedFilesParams) { + self.client.log_message(MessageType::INFO, "watched files have changed!").await; + } + + async fn execute_command(&self, _:ExecuteCommandParams) -> LspResult> { + self.client.log_message(MessageType::INFO, "command executed!").await; + + match self.client.apply_edit(WorkspaceEdit::default()).await { + Ok(res) if res.applied => self.client.log_message(MessageType::INFO, "applied").await, + Ok(_) => self.client.log_message(MessageType::INFO, "rejected").await, + Err(err) => self.client.log_message(MessageType::ERROR, err).await, + } + + Ok(None) + } + + /// Add an entry to the list of ropes for a newly opened file + async fn did_open(&self, document:DidOpenTextDocumentParams) { + self.client.log_message(MessageType::INFO, "file opened!").await; + + let rope = crop::Rope::from(document.text_document.text); + + { + let mut map = self.files.lock().expect("only fails if poisoned"); + map.insert(document.text_document.uri.clone(), rope.clone()); + } + + self.handle_file_update(document.text_document.uri, Some(rope), None).await; + } + + /// Modify the rope that we have in memory to reflect the changes that were + /// made to the buffer in the editor + async fn did_change(&self, document:DidChangeTextDocumentParams) { + self.client.log_message(MessageType::INFO, "file changed!").await; + + let updated_rope = { + let mut map = self.files.lock().expect("only fails if poisoned"); + let rope = map.entry(document.text_document.uri.clone()).or_default(); + + for change in document.content_changes { + match change.range { + Some(range) => { + let start_offset = rope.byte_of_line(range.start.line as usize) + + range.start.character as usize; + let end_offset = rope.byte_of_line(range.end.line as usize) + + range.end.character as usize; + + rope.replace(start_offset..end_offset, change.text); + }, + None => *rope = crop::Rope::from(change.text), + } + } + + rope.clone() + }; + + self.handle_file_update( + document.text_document.uri, + Some(updated_rope), + Some(document.text_document.version), + ) + .await; + } + + async fn did_save(&self, _:DidSaveTextDocumentParams) { + self.client.log_message(MessageType::INFO, "file saved!").await; + } + + async fn did_close(&self, _:DidCloseTextDocumentParams) { + self.client.log_message(MessageType::INFO, "file closed!").await; + } + + /// Provide intellisense completions for package / task names + /// + /// - get all packages + /// - get all package jsons + /// - produce all unique script names + /// - flatmap producing all package#script combos + /// - chain them + async fn completion(&self, _:CompletionParams) -> LspResult> { + let packages = self.package_discovery().await.map_err(|_e| Error::internal_error())?; + + let package_jsons = packages + .workspaces + .into_iter() + .flat_map(|wd| PackageJson::load(&wd.package_json).ok()) // if we can't parse a package.json, then we can't infer its tasks + .collect::>(); + + let tasks = package_jsons.iter().flat_map(|p| p.scripts.keys()).unique().map(|s| { + CompletionItem { + label:s.to_owned(), + kind:Some(CompletionItemKind::FIELD), + ..Default::default() + } + }); + + let keys = package_jsons + .iter() + .flat_map(|p| p.scripts.keys().map(move |k| (p.name.clone(), k))) + .map(|(package, s)| { + CompletionItem { + label:format!("{}#{}", package.unwrap_or_default(), s), + kind:Some(CompletionItemKind::FIELD), + ..Default::default() + } + }); + + Ok(Some(CompletionResponse::Array(keys.chain(tasks).collect()))) + } +} + +impl Backend { + pub fn new(client:Client) -> Self { + let (rx, tx) = tokio::sync::watch::channel(None); + + Self { + client, + repo_root:Arc::new(Mutex::new(None)), + files:Mutex::new(HashMap::new()), + initializer:rx, + daemon:tx, + + pidlock:Mutex::new(None), + } + } + + pub async fn package_discovery(&self) -> Result { + let daemon = { + let mut daemon = self.daemon.clone(); + let daemon = daemon.wait_for(|d| d.is_some()).await; + let daemon = daemon.as_ref().expect("only fails if self is dropped"); + daemon.as_ref().expect("guaranteed to be some above").clone() + }; + + DaemonPackageDiscovery::new(daemon).discover_packages_blocking().await + } + + /// Handle a file update to a rope, emitting diagnostics if necessary. + async fn handle_file_update(&self, uri:Url, rope:Option, version:Option) { + let rope = match rope { + Some(rope) => rope, + None => { + match self.files.lock().expect("only fails if poisoned").get(&uri) { + Some(files) => files, + None => return, + } + .clone() + }, + }; + + let contents = rope.chunks().join(""); + + let repo_root = self.repo_root.lock().expect("only fails if poisoned").clone(); + + let repo_root = match repo_root { + Some(repo_root) => repo_root, + None => { + self.client + .log_message(MessageType::INFO, "received request before initialization") + .await; + return; + }, + }; + + let packages = self.package_discovery().await; + + // package discovery does not yield the root, so we must add it + let root_turbo_json = repo_root.join_component("turbo.json"); + let workspaces = packages.map(|p| { + chain( + p.workspaces.into_iter(), + iter::once(WorkspaceData { + package_json:repo_root.join_component("package.json"), + turbo_json:root_turbo_json.exists().then_some(root_turbo_json), + }), + ) + }); + + let tasks = workspaces.map(|workspaces| { + workspaces + .filter_map(|wd| { + let package_json = PackageJson::load(&wd.package_json).ok()?; // if we can't load a package.json, then we can't infer its tasks + let package_json_name = if (&*repo_root) + == wd.package_json.parent().expect("package.json is always in a directory") + { + Some("//".to_string()) + } else { + package_json.name + }; + Some( + package_json + .scripts + .into_keys() + .map(move |k| (k, package_json_name.clone())), + ) + }) + .flatten() + .into_group_map() + }); + + // we still want to emit diagnostics if we can't infer tasks + let tasks_and_packages = tasks.as_ref().map(|tasks| { + ( + tasks, + tasks + .values() + .flatten() + .flatten() + .map(|s| s.as_str()) + .unique() + .collect::>(), + ) + }); + + let mut diagnostics = vec![]; + + // ParseResult cannot be sent across threads, so we must ensure it is dropped + // before we send the diagnostics. easiest way is just to scope it + { + let parse = + jsonc_parser::parse_to_ast(&contents, &Default::default(), &Default::default()); + + let parse = match parse { + Ok(parse) => parse, + Err(_) => return, // if it is not a valid json, then there are no diagnostics + }; + + let object = parse.value.as_ref().and_then(|v| v.as_object()); + + let mut globs = vec![]; + + globs.extend( + object + .and_then(|o| o.get_array("globalDependencies")) + .map(|d| &d.elements) + .into_iter() + .flatten(), + ); + + let pipeline = object.and_then(|o| o.get_object("tasks")).map(|p| p.properties.iter()); + + for property in pipeline.into_iter().flatten() { + let mut object_range = property.range; + object_range.start += 1; // account for quote + let object_key_range = object_range.start + property.name.as_str().len(); + object_range.end = object_key_range; + + if let (Ok((tasks, packages)), ObjectPropName::String(name)) = + (&tasks_and_packages, &property.name) + { + report_invalid_packages_and_tasks( + tasks, + packages, + &rope, + &mut diagnostics, + name, + ); + } + + // inputs, outputs + globs.extend( + ["inputs", "outputs"] + .iter() + .filter_map(|s| { + property + .value + .as_object() + .and_then(|o| o.get_array(s)) + .map(|a| &a.elements) + }) + .flatten(), + ); + + // dependsOn + if let Some(array) = + property.value.as_object().and_then(|o| o.get_array("dependsOn")) + { + for depends_on in &array.elements { + if let Some(string) = depends_on.as_string_lit().cloned() { + let suffix = if let Some(suffix) = strip_lit_prefix(&string, "^") { + diagnostics.push(Diagnostic { + message:format!( + "The '^' means \"run the `{}` task in the package's \ + dependencies before this one\"", + &suffix.value, + ), + range:convert_ranges( + &rope, + collapse_string_range(string.range), + ), + severity:Some(DiagnosticSeverity::HINT), + ..Default::default() + }); + suffix + } else { + // prevent task from depending on itself, if it is not a '^' task + if string.value == property.name.as_str() { + diagnostics.push(Diagnostic { + message:"A task cannot depend on itself.".to_string(), + range:convert_ranges(&rope, string.range), + severity:Some(DiagnosticSeverity::ERROR), + code:Some(NumberOrString::String( + "turbo:self-dependency".to_string(), + )), + ..Default::default() + }); + continue; + } + + string + }; + + let suffix = if let Some(suffix) = strip_lit_prefix(&suffix, "$") { + diagnostics.push(Diagnostic { + message:"The $ syntax is deprecated. Please apply the codemod." + .to_string(), + range:convert_ranges( + &rope, + collapse_string_range(suffix.range), + ), + severity:Some(DiagnosticSeverity::ERROR), + code:Some(NumberOrString::String( + "deprecated:env-var".to_string(), + )), + ..Default::default() + }); + suffix + } else { + suffix + }; + + if let Ok((tasks, packages)) = &tasks_and_packages { + report_invalid_packages_and_tasks( + tasks, + packages, + &rope, + &mut diagnostics, + &suffix, + ); + } + } + } + } + } + + for glob in globs { + // read string and parse glob + if let Some(string) = glob.as_string_lit() { + let expression = string.value.strip_prefix('!').unwrap_or(&string.value); // strip the negation + if let Err(glob) = wax::Glob::new(expression) { + diagnostics.push(Diagnostic { + message:format!("Invalid glob: {}", glob), + range:convert_ranges(&rope, collapse_string_range(string.range)), + severity:Some(DiagnosticSeverity::ERROR), + ..Default::default() + }); + } + } + } + } + + self.client.publish_diagnostics(uri, diagnostics, version).await; + } +} + +fn convert_ranges(rope:&crop::Rope, range:jsonc_parser::common::Range) -> Range { + let start_line = rope.line_of_byte(range.start); + let end_line = rope.line_of_byte(range.end); + + Range { + start:Position { + line:start_line as u32, + character:(range.start - rope.byte_of_line(start_line)) as u32, + }, + end:Position { + line:end_line as u32, + character:(range.end - rope.byte_of_line(end_line)) as u32, + }, + } +} + +fn strip_lit_prefix<'a>(s:&'a StringLit<'a>, prefix:&str) -> Option> { + s.value.strip_prefix(prefix).map(Cow::Borrowed).map(|stripped| { + StringLit { + value:stripped, + range:jsonc_parser::common::Range { + start:s.range.start + prefix.len(), + end:s.range.end, + }, + } + }) +} + +/// remove quotes from a string range +fn collapse_string_range(range:jsonc_parser::common::Range) -> jsonc_parser::common::Range { + jsonc_parser::common::Range { start:range.start + 1, end:range.end - 1 } +} + +fn report_invalid_packages_and_tasks( + tasks:&HashMap>>, + packages:&HashSet<&str>, + rope:&crop::Rope, + diagnostics:&mut Vec, + package_task:&StringLit, +) { + let (package, task) = package_task + .value + .split_once('#') // turbo packages may not have # in them + .map(|(p, t)| (Some(p), t)) + .unwrap_or((None, &package_task.value)); + + let range = convert_ranges(rope, collapse_string_range(package_task.range)); + + match (tasks.get(task), package) { + // we specified a package, but that package doesn't exist + (_, Some(package)) if !packages.contains(&package) => { + diagnostics.push(Diagnostic { + message:format!("The package `{}` does not exist in {:?}", package, packages), + range, + severity:Some(DiagnosticSeverity::ERROR), + code:Some(NumberOrString::String("turbo:no-such-package".to_string())), + ..Default::default() + }); + }, + // that task exists, and we have a package defined, but the task + // doesn't exist in that + // package + (Some(list), Some(package)) + if !list.iter().filter_map(|s| s.as_ref().map(|s| s.as_str())).contains(&package) => + { + diagnostics.push(Diagnostic { + message:format!("The task `{}` does not exist in the package `{}`.", task, package), + range, + severity:Some(DiagnosticSeverity::ERROR), + code:Some(NumberOrString::String("turbo:no-such-task-in-package".to_string())), + ..Default::default() + }); + }, + // the task doesn't exist anywhere, so we have a problem + (None, None) => { + diagnostics.push(Diagnostic { + message:format!("The task `{}` does not exist.", task), + range, + severity:Some(DiagnosticSeverity::ERROR), + code:Some(NumberOrString::String("turbo:no-such-task".to_string())), + ..Default::default() + }); + }, + // we have specified a package, but the task doesn't exist at + // all + (None, Some(package)) => { + diagnostics.push(Diagnostic { + message:format!("The task `{}` does not exist in the package `{}`.", task, package), + range, + severity:Some(DiagnosticSeverity::ERROR), + code:Some(NumberOrString::String("turbo:no-such-task".to_string())), + ..Default::default() + }); + }, + // task exists in a given package, so we're good + (Some(_), Some(_)) => {}, + // the task exists and we haven't specified a package, so we're + // good + (Some(_), None) => {}, + } +} diff --git a/crates/turborepo-lsp/Source/main.rs b/crates/turborepo-lsp/Source/main.rs new file mode 100644 index 0000000000000..f02989b8a61b2 --- /dev/null +++ b/crates/turborepo-lsp/Source/main.rs @@ -0,0 +1,11 @@ +use tower_lsp::{LspService, Server}; +use turborepo_lsp::Backend; + +#[tokio::main] +async fn main() { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, socket) = LspService::new(Backend::new); + Server::new(stdin, stdout, socket).serve(service).await; +} diff --git a/crates/turborepo-lsp/readme.md b/crates/turborepo-lsp/readme.md deleted file mode 100644 index 547283bcb0d6a..0000000000000 --- a/crates/turborepo-lsp/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -# Turborepo LSP - -This crate is a dual binary / library that provides a language server for -turborepo. It is used by the `turborepo` binary to provide IDE support for -turborepo projects. diff --git a/crates/turborepo-lsp/src/lib.rs b/crates/turborepo-lsp/src/lib.rs deleted file mode 100644 index e24ca17907b24..0000000000000 --- a/crates/turborepo-lsp/src/lib.rs +++ /dev/null @@ -1,1011 +0,0 @@ -//! Turbo LSP server -//! -//! This is the main entry point for the LSP server. It is responsible for -//! handling all LSP requests and responses. -//! -//! For more, see the [LSP specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/) -//! as well as the architecture documentation in `packages/turbo-vsc`. - -#![feature(box_patterns)] -#![deny(clippy::all)] -#![warn(clippy::unwrap_used)] - -use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, - iter, - sync::{Arc, Mutex}, -}; - -use itertools::{chain, Itertools}; -use jsonc_parser::{ - ast::{ObjectPropName, StringLit}, - CollectOptions, -}; -use serde_json::Value; -use tokio::sync::watch::{Receiver, Sender}; -use tower_lsp::{ - jsonrpc::{Error, Result as LspResult}, - lsp_types::*, - Client, LanguageServer, -}; -use turbopath::AbsoluteSystemPathBuf; -use turborepo_lib::{ - DaemonClient, DaemonConnector, DaemonConnectorError, DaemonError, DaemonPackageDiscovery, - DaemonPaths, -}; -use turborepo_repository::{ - discovery::{self, DiscoveryResponse, PackageDiscovery, WorkspaceData}, - package_json::PackageJson, -}; - -pub struct Backend { - client: Client, - repo_root: Arc>>, - files: Mutex>, - initializer: Sender>>, - daemon: Receiver>>, - - // this is only used for turbo optimize - pidlock: Mutex>, -} - -#[tower_lsp::async_trait] -impl LanguageServer for Backend { - async fn initialize(&self, params: InitializeParams) -> LspResult { - if let Some(uri) = params.root_uri { - if uri.scheme() != "file" { - return Err(Error::invalid_params("root is not a local file")); - } - - let repo_root = uri - .to_file_path() - .map_err(|_| Error::invalid_params("root is not a local file"))?; - let repo_root = repo_root - .as_os_str() - .to_str() - .ok_or(Error::invalid_params("root is not a valid utf-8 path"))?; - - // convert uri file:///absolute-path to AbsoluteSystemPathBuf - let repo_root = - AbsoluteSystemPathBuf::new(repo_root).expect("file is always an absolute path"); - - self.repo_root - .lock() - .expect("only fails if poisoned") - .replace(repo_root.clone()); - - let paths = DaemonPaths::from_repo_root(&repo_root); - - let (_, daemon) = tokio::join!( - self.client - .log_message(MessageType::INFO, format!("root uri: {}", paths.sock_file),), - tokio_retry::Retry::spawn( - tokio_retry::strategy::FixedInterval::from_millis(100).take(5), - || { - let can_start_server = true; - let can_kill_server = false; - let connector = - DaemonConnector::new(can_start_server, can_kill_server, &repo_root); - connector.connect() - }, - ) - ); - - let daemon = match daemon { - Ok(daemon) => daemon, - Err(DaemonConnectorError::Handshake(box DaemonError::VersionMismatch(message))) => { - self.client - .show_message( - MessageType::ERROR, - "Pre-2.0 versions of turborepo are not compatible with 2.0 or later \ - of the extension. If you do not plan to update to turbo 2.0, please \ - ensure you install the latest 1.0 version of the extension in this \ - workspace.", - ) - .await; - self.client - .log_message( - MessageType::ERROR, - format!("version mismatch when connecting to daemon: {}", message), - ) - .await; - - // in this case, just say we don't support any features - return Ok(InitializeResult { - ..Default::default() - }); - } - Err(e) => { - self.client - .log_message( - MessageType::ERROR, - format!("failed to connect to daemon: {}", e), - ) - .await; - return Err(Error::internal_error()); - } - }; - - self.initializer - .send(Some(daemon)) - .expect("there is a receiver"); - - let mut lock = pidlock::Pidlock::new(paths.lsp_pid_file.as_std_path().to_owned()); - - if let Err(e) = lock.acquire() { - self.client - .log_message( - MessageType::ERROR, - format!( - "failed to acquire pidlock, is another lsp instance running? - {}", - e - ), - ) - .await; - return Err(Error::internal_error()); - } - - *self.pidlock.lock().expect("only fails if poisoned") = Some(lock); - } - - Ok(InitializeResult { - server_info: None, - capabilities: ServerCapabilities { - text_document_sync: Some(TextDocumentSyncCapability::Kind( - TextDocumentSyncKind::INCREMENTAL, - )), - completion_provider: Some(CompletionOptions { - resolve_provider: Some(false), - trigger_characters: Some(vec![".".to_string()]), - work_done_progress_options: Default::default(), - all_commit_characters: None, - ..Default::default() - }), - execute_command_provider: Some(ExecuteCommandOptions { - commands: vec![ - // "turbo.run".to_string(), - // todo: port these from JS land - // "turbo.daemon.start".to_string(), - // "turbo.daemon.status".to_string(), - // "turbo.daemon.stop".to_string(), - ], - work_done_progress_options: Default::default(), - }), - workspace: Some(WorkspaceServerCapabilities { - workspace_folders: Some(WorkspaceFoldersServerCapabilities { - supported: Some(true), - change_notifications: Some(OneOf::Left(true)), - }), - file_operations: None, - }), - code_lens_provider: Some(CodeLensOptions { - resolve_provider: None, - }), - code_action_provider: Some(CodeActionProviderCapability::Options( - CodeActionOptions { - code_action_kinds: Some(vec![CodeActionKind::QUICKFIX]), - resolve_provider: None, - work_done_progress_options: WorkDoneProgressOptions { - work_done_progress: None, - }, - }, - )), - references_provider: Some(OneOf::Right(ReferencesOptions { - work_done_progress_options: WorkDoneProgressOptions { - work_done_progress: None, - }, - })), - ..ServerCapabilities::default() - }, - }) - } - - /// Find which projects / scripts are affected by a given pipeline item - async fn references(&self, params: ReferenceParams) -> LspResult>> { - self.client - .log_message(MessageType::INFO, "references!") - .await; - - let Some(referenced_task) = ({ - let rope = { - let map = self.files.lock().expect("only fails if poisoned"); - match map.get(¶ms.text_document_position.text_document.uri) { - Some(files) => files, - None => return Ok(None), - } - .to_owned() // cloning is cheap - }; - - let text = rope.chunks().join(""); - let parse = jsonc_parser::parse_to_ast( - &text, - &CollectOptions { - comments: true, - tokens: true, - }, - &Default::default(), - ); - - // iterate pipeline items, and see if any of their ranges intersect - // with the reference request's position - let parse = match parse { - Ok(parse) => parse, - Err(_err) => { - // if it is not a valid json, then there are no references - return Ok(None); - } - }; - - parse - .value - .as_ref() - .and_then(|v| v.as_object()) - .and_then(|o| o.get_object("tasks")) - .map(|p| p.properties.iter()) - .into_iter() - .flatten() - .find_map(|task| { - let mut range = task.range; - range.start += 1; // account for quote - let key_range = range.start + task.name.as_str().len(); - range.end = key_range; - - // convert ast range to lsp range - let lsp_range = convert_ranges(&rope, range); - - if lsp_range.start < params.text_document_position.position - && lsp_range.end > params.text_document_position.position - { - Some(task.name.as_str().to_string()) - } else { - None - } - }) - }) else { - // no overlap with any task definitions, exit - return Ok(None); - }; - - self.client - .log_message( - MessageType::INFO, - format!("finding references for {:?}", referenced_task), - ) - .await; - - let repo_root = self - .repo_root - .lock() - .expect("only fails if poisoned") - .clone(); - - let repo_root = match repo_root { - Some(repo_root) => repo_root, - None => { - self.client - .log_message(MessageType::INFO, "received request before initialization") - .await; - return Ok(None); - } - }; - - let packages = match self.package_discovery().await { - Ok(packages) => packages, - Err(e) => { - self.client - .log_message(MessageType::WARNING, e.to_string()) - .await; - - // there aren't really any other errors we can return here, other than - // an internal error - let mut error = Error::internal_error(); - error.message = "failed to get package list from the daemon".into(); - return Err(error); - } - }; - - let mut locations = vec![]; - for wd in packages.workspaces { - let data = match std::fs::read_to_string(&wd.package_json) { - Ok(data) => data, - // if we can't read a package.json, then we can't set up references to it - // so we just skip it and do a best effort - Err(_) => continue, - }; - let package_json = match PackageJson::load_from_str(&data, wd.package_json.as_str()) { - Ok(package_json) => package_json, - // if we can't parse a package.json, then we can't set up references to it - // so we just skip it and do a best effort - Err(_) => continue, - }; - let scripts = package_json.scripts.into_keys().collect::>(); - - // if in the root, the name should be '//' - let package_json_name = if repo_root.contains(&wd.package_json) { - Some("//") - } else { - package_json.name.as_deref() - }; - - // todo: use jsonc_ast instead of text search - let rope = crop::Rope::from(data.clone()); - - let (package, task) = referenced_task - .rsplit_once('#') - .map(|(p, t)| (Some(p), t)) - .unwrap_or((None, &referenced_task)); - - if let (Some(package), Some(package_name)) = (package, package_json_name) { - if package_name != package { - continue; - } - }; - - let Some(start) = data.find(&format!("\"{}\"", task)) else { - continue; - }; - let end = start + task.len() + 2; - - let start_line = rope.line_of_byte(start); - let end_line = rope.line_of_byte(end); - - let range = Range { - start: Position { - line: start_line as u32, - character: (start - rope.byte_of_line(start_line)) as u32, - }, - end: Position { - line: end_line as u32, - character: (end - rope.byte_of_line(end_line)) as u32, - }, - }; - - if scripts.contains(task) { - let location = Location::new( - Url::from_file_path(&wd.package_json).expect("only fails if path is relative"), - range, - ); - locations.push(location); - } - } - - Ok(Some(locations)) - } - - /// Add code lens items for running a particular task in the turbo.json - async fn code_lens(&self, params: CodeLensParams) -> LspResult>> { - self.client - .log_message(MessageType::INFO, "code lens!") - .await; - - let rope = { - let map = self.files.lock().expect("only fails if poisoned"); - match map.get(¶ms.text_document.uri) { - Some(files) => files, - None => return Ok(None), - } - .to_owned() // cloning is cheap - }; - - let text = rope.chunks().join(""); - let parse = jsonc_parser::parse_to_ast( - &text, - &CollectOptions { - comments: true, - tokens: true, - }, - &Default::default(), - ); - - let parse = match parse { - Ok(parse) => parse, - Err(_err) => { - // todo: do we error here? - // self.client - // .log_message(MessageType::ERROR, format!("{:?}", err)) - // .await; - return Ok(None); - } - }; - - let pipeline = parse - .value - .as_ref() - .and_then(|v| v.as_object()) - .and_then(|o| o.get_object("tasks")) - .map(|p| p.properties.iter()) - .into_iter() - .flatten(); - - let mut tasks = vec![]; - for task in pipeline { - let mut range = task.range; - range.start += 1; // account for quote - let key_range = range.start + task.name.as_str().len(); - range.end = key_range; - - tasks.push(CodeLens { - command: Some(Command { - title: format!("Run {}", task.name.as_str()), - command: "turbo.run".to_string(), - arguments: Some(vec![Value::String(task.name.as_str().to_string())]), - }), - range: convert_ranges(&rope, range), - data: None, - }); - } - - Ok(Some(tasks)) - } - - /// Given a list of diagnistics that we previously reported, produce code - /// actions that the user can run - async fn code_action(&self, params: CodeActionParams) -> LspResult> { - self.client - .log_message(MessageType::INFO, format!("{:#?}", params)) - .await; - - let mut code_actions = vec![]; - - for diag in params.context.diagnostics { - match &diag.code { - Some(NumberOrString::String(s)) if s == "deprecated:env-var" => { - code_actions.push(CodeActionOrCommand::CodeAction(CodeAction { - title: "Apply codemod".to_string(), - command: Some(Command { - title: "Apply codemod".to_string(), - command: "turbo.codemod".to_string(), - arguments: Some(vec![Value::String( - "migrate-env-var-dependencies".to_string(), - )]), - }), - diagnostics: Some(vec![diag]), - kind: Some(CodeActionKind::QUICKFIX), - is_preferred: Some(true), - ..Default::default() - })) - } - _ => {} - } - } - - Ok(Some(code_actions)) - } - - async fn initialized(&self, _: InitializedParams) { - self.client - .log_message(MessageType::INFO, "initialized!") - .await; - } - - async fn shutdown(&self) -> LspResult<()> { - Ok(()) - } - - async fn did_change_workspace_folders(&self, _: DidChangeWorkspaceFoldersParams) { - self.client - .log_message(MessageType::INFO, "workspace folders changed!") - .await; - } - - async fn did_change_configuration(&self, _: DidChangeConfigurationParams) { - self.client - .log_message(MessageType::INFO, "configuration changed!") - .await; - } - - async fn did_change_watched_files(&self, _: DidChangeWatchedFilesParams) { - self.client - .log_message(MessageType::INFO, "watched files have changed!") - .await; - } - - async fn execute_command(&self, _: ExecuteCommandParams) -> LspResult> { - self.client - .log_message(MessageType::INFO, "command executed!") - .await; - - match self.client.apply_edit(WorkspaceEdit::default()).await { - Ok(res) if res.applied => self.client.log_message(MessageType::INFO, "applied").await, - Ok(_) => self.client.log_message(MessageType::INFO, "rejected").await, - Err(err) => self.client.log_message(MessageType::ERROR, err).await, - } - - Ok(None) - } - - /// Add an entry to the list of ropes for a newly opened file - async fn did_open(&self, document: DidOpenTextDocumentParams) { - self.client - .log_message(MessageType::INFO, "file opened!") - .await; - - let rope = crop::Rope::from(document.text_document.text); - - { - let mut map = self.files.lock().expect("only fails if poisoned"); - map.insert(document.text_document.uri.clone(), rope.clone()); - } - - self.handle_file_update(document.text_document.uri, Some(rope), None) - .await; - } - - /// Modify the rope that we have in memory to reflect the changes that were - /// made to the buffer in the editor - async fn did_change(&self, document: DidChangeTextDocumentParams) { - self.client - .log_message(MessageType::INFO, "file changed!") - .await; - - let updated_rope = { - let mut map = self.files.lock().expect("only fails if poisoned"); - let rope = map.entry(document.text_document.uri.clone()).or_default(); - - for change in document.content_changes { - match change.range { - Some(range) => { - let start_offset = rope.byte_of_line(range.start.line as usize) - + range.start.character as usize; - let end_offset = rope.byte_of_line(range.end.line as usize) - + range.end.character as usize; - - rope.replace(start_offset..end_offset, change.text); - } - None => *rope = crop::Rope::from(change.text), - } - } - - rope.clone() - }; - - self.handle_file_update( - document.text_document.uri, - Some(updated_rope), - Some(document.text_document.version), - ) - .await; - } - - async fn did_save(&self, _: DidSaveTextDocumentParams) { - self.client - .log_message(MessageType::INFO, "file saved!") - .await; - } - - async fn did_close(&self, _: DidCloseTextDocumentParams) { - self.client - .log_message(MessageType::INFO, "file closed!") - .await; - } - - /// Provide intellisense completions for package / task names - /// - /// - get all packages - /// - get all package jsons - /// - produce all unique script names - /// - flatmap producing all package#script combos - /// - chain them - async fn completion(&self, _: CompletionParams) -> LspResult> { - let packages = self - .package_discovery() - .await - .map_err(|_e| Error::internal_error())?; - - let package_jsons = packages - .workspaces - .into_iter() - .flat_map(|wd| PackageJson::load(&wd.package_json).ok()) // if we can't parse a package.json, then we can't infer its tasks - .collect::>(); - - let tasks = package_jsons - .iter() - .flat_map(|p| p.scripts.keys()) - .unique() - .map(|s| CompletionItem { - label: s.to_owned(), - kind: Some(CompletionItemKind::FIELD), - ..Default::default() - }); - - let keys = package_jsons - .iter() - .flat_map(|p| p.scripts.keys().map(move |k| (p.name.clone(), k))) - .map(|(package, s)| CompletionItem { - label: format!("{}#{}", package.unwrap_or_default(), s), - kind: Some(CompletionItemKind::FIELD), - ..Default::default() - }); - - Ok(Some(CompletionResponse::Array(keys.chain(tasks).collect()))) - } -} - -impl Backend { - pub fn new(client: Client) -> Self { - let (rx, tx) = tokio::sync::watch::channel(None); - - Self { - client, - repo_root: Arc::new(Mutex::new(None)), - files: Mutex::new(HashMap::new()), - initializer: rx, - daemon: tx, - - pidlock: Mutex::new(None), - } - } - - pub async fn package_discovery(&self) -> Result { - let daemon = { - let mut daemon = self.daemon.clone(); - let daemon = daemon.wait_for(|d| d.is_some()).await; - let daemon = daemon.as_ref().expect("only fails if self is dropped"); - daemon - .as_ref() - .expect("guaranteed to be some above") - .clone() - }; - - DaemonPackageDiscovery::new(daemon) - .discover_packages_blocking() - .await - } - - /// Handle a file update to a rope, emitting diagnostics if necessary. - async fn handle_file_update(&self, uri: Url, rope: Option, version: Option) { - let rope = match rope { - Some(rope) => rope, - None => match self.files.lock().expect("only fails if poisoned").get(&uri) { - Some(files) => files, - None => return, - } - .clone(), - }; - - let contents = rope.chunks().join(""); - - let repo_root = self - .repo_root - .lock() - .expect("only fails if poisoned") - .clone(); - - let repo_root = match repo_root { - Some(repo_root) => repo_root, - None => { - self.client - .log_message(MessageType::INFO, "received request before initialization") - .await; - return; - } - }; - - let packages = self.package_discovery().await; - - // package discovery does not yield the root, so we must add it - let root_turbo_json = repo_root.join_component("turbo.json"); - let workspaces = packages.map(|p| { - chain( - p.workspaces.into_iter(), - iter::once(WorkspaceData { - package_json: repo_root.join_component("package.json"), - turbo_json: root_turbo_json.exists().then_some(root_turbo_json), - }), - ) - }); - - let tasks = workspaces.map(|workspaces| { - workspaces - .filter_map(|wd| { - let package_json = PackageJson::load(&wd.package_json).ok()?; // if we can't load a package.json, then we can't infer its tasks - let package_json_name = if (&*repo_root) - == wd - .package_json - .parent() - .expect("package.json is always in a directory") - { - Some("//".to_string()) - } else { - package_json.name - }; - Some( - package_json - .scripts - .into_keys() - .map(move |k| (k, package_json_name.clone())), - ) - }) - .flatten() - .into_group_map() - }); - - // we still want to emit diagnostics if we can't infer tasks - let tasks_and_packages = tasks.as_ref().map(|tasks| { - ( - tasks, - tasks - .values() - .flatten() - .flatten() - .map(|s| s.as_str()) - .unique() - .collect::>(), - ) - }); - - let mut diagnostics = vec![]; - - // ParseResult cannot be sent across threads, so we must ensure it is dropped - // before we send the diagnostics. easiest way is just to scope it - { - let parse = - jsonc_parser::parse_to_ast(&contents, &Default::default(), &Default::default()); - - let parse = match parse { - Ok(parse) => parse, - Err(_) => return, // if it is not a valid json, then there are no diagnostics - }; - - let object = parse.value.as_ref().and_then(|v| v.as_object()); - - let mut globs = vec![]; - - globs.extend( - object - .and_then(|o| o.get_array("globalDependencies")) - .map(|d| &d.elements) - .into_iter() - .flatten(), - ); - - let pipeline = object - .and_then(|o| o.get_object("tasks")) - .map(|p| p.properties.iter()); - - for property in pipeline.into_iter().flatten() { - let mut object_range = property.range; - object_range.start += 1; // account for quote - let object_key_range = object_range.start + property.name.as_str().len(); - object_range.end = object_key_range; - - if let (Ok((tasks, packages)), ObjectPropName::String(name)) = - (&tasks_and_packages, &property.name) - { - report_invalid_packages_and_tasks( - tasks, - packages, - &rope, - &mut diagnostics, - name, - ); - } - - // inputs, outputs - globs.extend( - ["inputs", "outputs"] - .iter() - .filter_map(|s| { - property - .value - .as_object() - .and_then(|o| o.get_array(s)) - .map(|a| &a.elements) - }) - .flatten(), - ); - - // dependsOn - if let Some(array) = property - .value - .as_object() - .and_then(|o| o.get_array("dependsOn")) - { - for depends_on in &array.elements { - if let Some(string) = depends_on.as_string_lit().cloned() { - let suffix = if let Some(suffix) = strip_lit_prefix(&string, "^") { - diagnostics.push(Diagnostic { - message: format!( - "The '^' means \"run the `{}` task in the package's \ - dependencies before this one\"", - &suffix.value, - ), - range: convert_ranges( - &rope, - collapse_string_range(string.range), - ), - severity: Some(DiagnosticSeverity::HINT), - ..Default::default() - }); - suffix - } else { - // prevent task from depending on itself, if it is not a '^' task - if string.value == property.name.as_str() { - diagnostics.push(Diagnostic { - message: "A task cannot depend on itself.".to_string(), - range: convert_ranges(&rope, string.range), - severity: Some(DiagnosticSeverity::ERROR), - code: Some(NumberOrString::String( - "turbo:self-dependency".to_string(), - )), - ..Default::default() - }); - continue; - } - - string - }; - - let suffix = if let Some(suffix) = strip_lit_prefix(&suffix, "$") { - diagnostics.push(Diagnostic { - message: "The $ syntax is deprecated. Please apply the \ - codemod." - .to_string(), - range: convert_ranges( - &rope, - collapse_string_range(suffix.range), - ), - severity: Some(DiagnosticSeverity::ERROR), - code: Some(NumberOrString::String( - "deprecated:env-var".to_string(), - )), - ..Default::default() - }); - suffix - } else { - suffix - }; - - if let Ok((tasks, packages)) = &tasks_and_packages { - report_invalid_packages_and_tasks( - tasks, - packages, - &rope, - &mut diagnostics, - &suffix, - ); - } - } - } - } - } - - for glob in globs { - // read string and parse glob - if let Some(string) = glob.as_string_lit() { - let expression = string.value.strip_prefix('!').unwrap_or(&string.value); // strip the negation - if let Err(glob) = wax::Glob::new(expression) { - diagnostics.push(Diagnostic { - message: format!("Invalid glob: {}", glob), - range: convert_ranges(&rope, collapse_string_range(string.range)), - severity: Some(DiagnosticSeverity::ERROR), - ..Default::default() - }); - } - } - } - } - - self.client - .publish_diagnostics(uri, diagnostics, version) - .await; - } -} - -fn convert_ranges(rope: &crop::Rope, range: jsonc_parser::common::Range) -> Range { - let start_line = rope.line_of_byte(range.start); - let end_line = rope.line_of_byte(range.end); - - Range { - start: Position { - line: start_line as u32, - character: (range.start - rope.byte_of_line(start_line)) as u32, - }, - end: Position { - line: end_line as u32, - character: (range.end - rope.byte_of_line(end_line)) as u32, - }, - } -} - -fn strip_lit_prefix<'a>(s: &'a StringLit<'a>, prefix: &str) -> Option> { - s.value - .strip_prefix(prefix) - .map(Cow::Borrowed) - .map(|stripped| StringLit { - value: stripped, - range: jsonc_parser::common::Range { - start: s.range.start + prefix.len(), - end: s.range.end, - }, - }) -} - -/// remove quotes from a string range -fn collapse_string_range(range: jsonc_parser::common::Range) -> jsonc_parser::common::Range { - jsonc_parser::common::Range { - start: range.start + 1, - end: range.end - 1, - } -} - -fn report_invalid_packages_and_tasks( - tasks: &HashMap>>, - packages: &HashSet<&str>, - rope: &crop::Rope, - diagnostics: &mut Vec, - package_task: &StringLit, -) { - let (package, task) = package_task - .value - .split_once('#') // turbo packages may not have # in them - .map(|(p, t)| (Some(p), t)) - .unwrap_or((None, &package_task.value)); - - let range = convert_ranges(rope, collapse_string_range(package_task.range)); - - match (tasks.get(task), package) { - // we specified a package, but that package doesn't exist - (_, Some(package)) if !packages.contains(&package) => { - diagnostics.push(Diagnostic { - message: format!("The package `{}` does not exist in {:?}", package, packages), - range, - severity: Some(DiagnosticSeverity::ERROR), - code: Some(NumberOrString::String("turbo:no-such-package".to_string())), - ..Default::default() - }); - } - // that task exists, and we have a package defined, but the task - // doesn't exist in that - // package - (Some(list), Some(package)) - if !list - .iter() - .filter_map(|s| s.as_ref().map(|s| s.as_str())) - .contains(&package) => - { - diagnostics.push(Diagnostic { - message: format!( - "The task `{}` does not exist in the package `{}`.", - task, package - ), - range, - severity: Some(DiagnosticSeverity::ERROR), - code: Some(NumberOrString::String( - "turbo:no-such-task-in-package".to_string(), - )), - ..Default::default() - }); - } - // the task doesn't exist anywhere, so we have a problem - (None, None) => { - diagnostics.push(Diagnostic { - message: format!("The task `{}` does not exist.", task), - range, - severity: Some(DiagnosticSeverity::ERROR), - code: Some(NumberOrString::String("turbo:no-such-task".to_string())), - ..Default::default() - }); - } - // we have specified a package, but the task doesn't exist at - // all - (None, Some(package)) => { - diagnostics.push(Diagnostic { - message: format!( - "The task `{}` does not exist in the package `{}`.", - task, package - ), - range, - severity: Some(DiagnosticSeverity::ERROR), - code: Some(NumberOrString::String("turbo:no-such-task".to_string())), - ..Default::default() - }); - } - // task exists in a given package, so we're good - (Some(_), Some(_)) => {} - // the task exists and we haven't specified a package, so we're - // good - (Some(_), None) => {} - } -} diff --git a/crates/turborepo-lsp/src/main.rs b/crates/turborepo-lsp/src/main.rs deleted file mode 100644 index c2205686436dc..0000000000000 --- a/crates/turborepo-lsp/src/main.rs +++ /dev/null @@ -1,11 +0,0 @@ -use tower_lsp::{LspService, Server}; -use turborepo_lsp::Backend; - -#[tokio::main] -async fn main() { - let stdin = tokio::io::stdin(); - let stdout = tokio::io::stdout(); - - let (service, socket) = LspService::new(Backend::new); - Server::new(stdin, stdout, socket).serve(service).await; -} diff --git a/crates/turborepo-microfrontends/Cargo.toml b/crates/turborepo-microfrontends/Cargo.toml index 5c2208a644781..1d91288e40a9a 100644 --- a/crates/turborepo-microfrontends/Cargo.toml +++ b/crates/turborepo-microfrontends/Cargo.toml @@ -1,9 +1,3 @@ -[package] -name = "turborepo-microfrontends" -version = "0.1.0" -edition = "2021" -license = "MIT" - [dependencies] biome_deserialize = { workspace = true } biome_deserialize_macros = { workspace = true } @@ -22,5 +16,14 @@ pretty_assertions = { workspace = true } tempfile = { workspace = true } test-case = { workspace = true } +[lib] +path = "Source/lib.rs" + [lints] workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-microfrontends" +version = "0.1.0" diff --git a/crates/turborepo-microfrontends/src/configv1.rs b/crates/turborepo-microfrontends/Source/configv1.rs similarity index 100% rename from crates/turborepo-microfrontends/src/configv1.rs rename to crates/turborepo-microfrontends/Source/configv1.rs diff --git a/crates/turborepo-microfrontends/Source/configv2.rs b/crates/turborepo-microfrontends/Source/configv2.rs new file mode 100644 index 0000000000000..53063ce84cba7 --- /dev/null +++ b/crates/turborepo-microfrontends/Source/configv2.rs @@ -0,0 +1,112 @@ +use std::collections::BTreeMap; + +use biome_deserialize_macros::Deserializable; +use biome_json_parser::JsonParserOptions; +use serde::Serialize; + +use crate::Error; + +pub enum ParseResult { + Actual(ConfigV2), + Reference(String), +} + +#[derive(Debug, PartialEq, Eq, Serialize, Deserializable, Default)] +pub struct ConfigV2 { + version:String, + applications:BTreeMap, +} + +#[derive(Debug, PartialEq, Eq, Serialize, Deserializable, Default)] +struct ChildConfig { + part_of:String, +} + +#[derive(Debug, PartialEq, Eq, Serialize, Deserializable, Default)] +struct Application { + development:Option, +} + +#[derive(Debug, PartialEq, Eq, Serialize, Deserializable, Default)] +struct Development { + task:Option, +} + +impl ConfigV2 { + pub fn from_str(input:&str, source:&str) -> Result { + // attempt to parse a child, ignoring any errors + let (config, errs) = biome_deserialize::json::deserialize_from_json_str::( + input, + JsonParserOptions::default().with_allow_comments(), + source, + ) + .consume(); + + if let Some(ChildConfig { part_of }) = errs.is_empty().then_some(config).flatten() { + return Ok(ParseResult::Reference(part_of)); + } + // attempt to parse a real one + let (config, errs) = biome_deserialize::json::deserialize_from_json_str::( + input, + JsonParserOptions::default().with_allow_comments(), + source, + ) + .consume(); + + if let Some(config) = config { + if config.version == "2" { + Ok(ParseResult::Actual(config)) + } else { + Err(Error::InvalidVersion { expected:"2", actual:config.version }) + } + } else { + Err(Error::biome_error(errs)) + } + } + + pub fn development_tasks(&self) -> impl Iterator)> { + self.applications + .iter() + .map(|(application, config)| (application.as_str(), config.task())) + } +} + +impl Application { + fn task(&self) -> Option<&str> { self.development.as_ref()?.task.as_deref() } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_child_config_parse() { + let input = r#"{"partOf": "web"}"#; + let config = ConfigV2::from_str(input, "somewhere").unwrap(); + match config { + ParseResult::Actual(_config_v2) => panic!("expected to get reference to default app"), + ParseResult::Reference(default_app) => { + assert_eq!(default_app, "web"); + }, + } + } + + #[test] + fn test_root_config_parse() { + let input = r#"{ + "version": "2", + "applications": { + "web": {}, + "docs": {"development": {"task": "serve"}} + } + }"#; + let config = ConfigV2::from_str(input, "somewhere").unwrap(); + match config { + ParseResult::Actual(config_v2) => { + assert_eq!(config_v2.applications.get("web").unwrap().task(), None); + assert_eq!(config_v2.applications.get("docs").unwrap().task(), Some("serve")); + }, + ParseResult::Reference(_) => panic!("expected to get main config"), + } + } +} diff --git a/crates/turborepo-microfrontends/src/error.rs b/crates/turborepo-microfrontends/Source/error.rs similarity index 100% rename from crates/turborepo-microfrontends/src/error.rs rename to crates/turborepo-microfrontends/Source/error.rs diff --git a/crates/turborepo-microfrontends/src/lib.rs b/crates/turborepo-microfrontends/Source/lib.rs similarity index 100% rename from crates/turborepo-microfrontends/src/lib.rs rename to crates/turborepo-microfrontends/Source/lib.rs diff --git a/crates/turborepo-microfrontends/fixtures/sample.jsonc b/crates/turborepo-microfrontends/fixtures/sample.jsonc deleted file mode 100644 index 51307268fba35..0000000000000 --- a/crates/turborepo-microfrontends/fixtures/sample.jsonc +++ /dev/null @@ -1,116 +0,0 @@ -{ - "version": "1", - "applications": { - "main-site": { - "development": { - "local": { - "protocol": "http", - "host": "localhost", - "port": 3331 - }, - "fallback": { - "protocol": "https", - "host": "main-preview.sh" - } - }, - "production": { - "protocol": "https", - "host": "main.com" - }, - "vercel": { - "projectId": "id1" - } - }, - "vercel-marketing": { - "routing": [ - { - "group": "blog", - "paths": [ - "/blog", - "/blog/:slug*", - "/press", - "/changelog", - "/changelog/:slug*", - "/customers/:slug*" - ] - }, - { - "group": "navbar", - "paths": [ - "/", - "/contact", - "/pricing", - "/enterprise", - // Resources - "/customers", - "/solutions/composable-commerce" - ] - } - ], - "development": { - "local": { - "protocol": "http", - "host": "localhost", - "port": 3332 - }, - "fallback": { - "protocol": "https", - "host": "market-preview.sh" - } - }, - "production": { - "protocol": "https", - "host": "market.main.com" - }, - "vercel": { - "projectId": "id2" - } - }, - "foo-docs": { - "routing": [ - { - "paths": ["/foo/:path*"] - } - ], - "development": { - "fallback": { - "protocol": "https", - "host": "foo-preview.sh" - }, - "local": { - "protocol": "http", - "host": "localhost", - "port": 3333 - } - }, - "production": { - "protocol": "https", - "host": "foo.main.com" - }, - "vercel": { - "projectId": "id3" - } - }, - "docs": { - "routing": [], - "development": { - "fallback": { - "protocol": "https", - "host": "docs-preview.sh" - }, - "local": { - "protocol": "http", - "host": "localhost", - "port": 3334 - } - }, - "production": { - "protocol": "https", - "host": "docs.main.com" - }, - "vercel": { - "projectId": "id4" - } - } - } -} diff --git a/crates/turborepo-paths/Cargo.toml b/crates/turborepo-paths/Cargo.toml index 7830767a8299f..e6dd7be95b8d8 100644 --- a/crates/turborepo-paths/Cargo.toml +++ b/crates/turborepo-paths/Cargo.toml @@ -1,38 +1,16 @@ -[package] -name = "turbopath" -version = "0.1.0" -license = "MIT" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - -[features] -biome = [ - "dep:biome_deserialize", - "dep:biome_deserialize_macros", - "dep:biome_diagnostics", - "dep:biome_json_parser", - "dep:turborepo-unescape", -] - [dependencies] biome_deserialize = { workspace = true, optional = true } biome_deserialize_macros = { workspace = true, optional = true } biome_diagnostics = { workspace = true, optional = true } biome_json_parser = { workspace = true, optional = true } -turborepo-unescape = { workspace = true, optional = true } - camino = { workspace = true } dunce = { workspace = true } fs-err = "2.9.0" miette = { workspace = true } path-clean = "1.0.1" -# TODO: Make this a crate feature serde = { workspace = true } thiserror = { workspace = true } +turborepo-unescape = { workspace = true, optional = true } wax = { workspace = true } [dev-dependencies] @@ -40,3 +18,24 @@ anyhow = { workspace = true } serde_json = { workspace = true } tempfile = { workspace = true } test-case = { workspace = true } + +[features] +biome = [ + "dep:biome_deserialize", + "dep:biome_deserialize_macros", + "dep:biome_diagnostics", + "dep:biome_json_parser", + "dep:turborepo-unescape", +] + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turbopath" +version = "0.1.0" diff --git a/crates/turborepo-paths/src/absolute_system_path.rs b/crates/turborepo-paths/Source/absolute_system_path.rs similarity index 100% rename from crates/turborepo-paths/src/absolute_system_path.rs rename to crates/turborepo-paths/Source/absolute_system_path.rs diff --git a/crates/turborepo-paths/Source/absolute_system_path_buf.rs b/crates/turborepo-paths/Source/absolute_system_path_buf.rs new file mode 100644 index 0000000000000..2fd4369ced8b7 --- /dev/null +++ b/crates/turborepo-paths/Source/absolute_system_path_buf.rs @@ -0,0 +1,263 @@ +use std::{ + borrow::Borrow, + fmt, + io, + ops::Deref, + path::{Path, PathBuf}, +}; + +use camino::{Utf8Components, Utf8Path, Utf8PathBuf}; +use fs_err as fs; +use path_clean::PathClean; +use serde::Serialize; + +use crate::{AbsoluteSystemPath, AnchoredSystemPathBuf, PathError}; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize)] +pub struct AbsoluteSystemPathBuf(pub(crate) Utf8PathBuf); + +impl Borrow for AbsoluteSystemPathBuf { + fn borrow(&self) -> &AbsoluteSystemPath { + let path = self.as_path(); + unsafe { &*(path as *const Utf8Path as *const AbsoluteSystemPath) } + } +} + +impl AsRef for AbsoluteSystemPathBuf { + fn as_ref(&self) -> &AbsoluteSystemPath { self } +} + +impl Deref for AbsoluteSystemPathBuf { + type Target = AbsoluteSystemPath; + + fn deref(&self) -> &Self::Target { self.borrow() } +} + +impl AbsoluteSystemPathBuf { + /// Create a new AbsoluteSystemPathBuf from `unchecked_path`. + /// Confirms that `unchecked_path` is absolute. Does *not* convert + /// to system path, since that is generally undecidable (see module + /// documentation) + /// + /// # Arguments + /// + /// * `unchecked_path`: The path to be validated and converted to an + /// `AbsoluteSystemPathBuf`. + /// + /// returns: Result + /// + /// # Examples + /// + /// ``` + /// use std::path::{Path, PathBuf}; + /// + /// use camino::Utf8Path; + /// use turbopath::AbsoluteSystemPathBuf; + /// #[cfg(windows)] + /// let path = "C:/Users/user"; + /// #[cfg(not(windows))] + /// let path = "/Users/user"; + /// + /// let absolute_path = AbsoluteSystemPathBuf::new(path).unwrap(); + /// + /// #[cfg(windows)] + /// assert_eq!(absolute_path.as_path(), Utf8Path::new("C:\\Users\\user")); + /// #[cfg(not(windows))] + /// assert_eq!(absolute_path.as_path(), Utf8Path::new("/Users/user")); + /// ``` + pub fn new(unchecked_path:impl Into) -> Result { + let unchecked_path = unchecked_path.into(); + if !Path::new(&unchecked_path).is_absolute() { + return Err(PathError::NotAbsolute(unchecked_path)); + } + Ok(AbsoluteSystemPathBuf(unchecked_path.into())) + } + + /// Takes in a system path of unknown type. If it's absolute, returns the + /// path, If it's relative, appends it to the base after cleaning it. + pub fn from_unknown(base:&AbsoluteSystemPath, unknown:impl Into) -> Self { + // we have an absolute system path and an unknown kind of system path. + let unknown:Utf8PathBuf = unknown.into(); + if unknown.is_absolute() { + Self(unknown) + } else { + Self( + base.as_path() + .join(unknown) + .as_std_path() + .clean() + .try_into() + .expect("clean should produce valid UTF-8"), + ) + } + } + + pub fn from_cwd(unknown:impl Into) -> Result { + let cwd = Self::cwd()?; + Ok(Self::from_unknown(&cwd, unknown)) + } + + pub fn cwd() -> Result { + // TODO(errors): Unwrap current_dir() + Ok(Self(Utf8PathBuf::try_from(std::env::current_dir()?)?)) + } + + /// Anchors `path` at `self`. + /// + /// # Arguments + /// + /// * `path`: The path to be anchored at `self` + /// + /// returns: Result + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; + /// #[cfg(not(windows))] + /// { + /// let base = AbsoluteSystemPathBuf::new("/Users/user").unwrap(); + /// let anchored_path = AbsoluteSystemPathBuf::new("/Users/user/Documents").unwrap(); + /// let anchored_path = base.anchor(&anchored_path).unwrap(); + /// assert_eq!(anchored_path.as_str(), "Documents"); + /// } + /// + /// #[cfg(windows)] + /// { + /// let base = AbsoluteSystemPathBuf::new("C:\\Users\\user").unwrap(); + /// let anchored_path = AbsoluteSystemPathBuf::new("C:\\Users\\user\\Documents").unwrap(); + /// let anchored_path = base.anchor(&anchored_path).unwrap(); + /// assert_eq!(anchored_path.as_str(), "Documents"); + /// } + /// ``` + pub fn anchor( + &self, + path:impl AsRef, + ) -> Result { + AnchoredSystemPathBuf::new(self, path) + } + + pub fn as_path(&self) -> &Utf8Path { self.0.as_path() } + + pub fn components(&self) -> Utf8Components<'_> { self.0.components() } + + pub fn parent(&self) -> Option<&AbsoluteSystemPath> { + self.0.parent().map(AbsoluteSystemPath::new_unchecked) + } + + pub fn starts_with>(&self, base:P) -> bool { self.0.starts_with(base.as_ref()) } + + pub fn ends_with>(&self, child:P) -> bool { self.0.ends_with(child.as_ref()) } + + pub fn ensure_dir(&self) -> Result<(), io::Error> { + if let Some(parent) = self.0.parent() { + fs::create_dir_all(parent) + } else { + Ok(()) + } + } + + pub fn create_dir_all(&self) -> Result<(), io::Error> { fs::create_dir_all(self.0.as_path()) } + + pub fn remove(&self) -> Result<(), io::Error> { fs::remove_file(self.0.as_path()) } + + pub fn set_readonly(&self) -> Result<(), PathError> { + let metadata = fs::symlink_metadata(self)?; + let mut perms = metadata.permissions(); + perms.set_readonly(true); + fs::set_permissions(self.0.as_path(), perms)?; + Ok(()) + } + + pub fn is_readonly(&self) -> Result { + Ok(self.0.symlink_metadata()?.permissions().readonly()) + } + + pub fn as_str(&self) -> &str { self.0.as_str() } + + pub fn file_name(&self) -> Option<&str> { self.0.file_name() } + + pub fn extension(&self) -> Option<&str> { self.0.extension() } +} + +impl TryFrom for AbsoluteSystemPathBuf { + type Error = PathError; + + fn try_from(path:PathBuf) -> Result { + Self::new(Utf8PathBuf::try_from(path)?) + } +} + +impl TryFrom<&Path> for AbsoluteSystemPathBuf { + type Error = PathError; + + fn try_from(path:&Path) -> Result { + let utf8_path:&Utf8Path = path.try_into()?; + Self::new(utf8_path.to_owned()) + } +} + +impl TryFrom<&str> for AbsoluteSystemPathBuf { + type Error = PathError; + + fn try_from(value:&str) -> Result { Self::new(Utf8PathBuf::from(value)) } +} + +impl From for PathBuf { + fn from(path:AbsoluteSystemPathBuf) -> Self { path.0.into_std_path_buf() } +} + +impl fmt::Display for AbsoluteSystemPathBuf { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0.as_str()) } +} + +impl AsRef for AbsoluteSystemPathBuf { + fn as_ref(&self) -> &Path { self.0.as_std_path() } +} + +#[cfg(test)] +mod tests { + use std::assert_matches::assert_matches; + + use crate::{AbsoluteSystemPathBuf, PathError, RelativeUnixPathBuf}; + + #[cfg(not(windows))] + #[test] + fn test_absolute_system_path_buf_on_unix() { + assert!(AbsoluteSystemPathBuf::new("/Users/user").is_ok()); + assert_matches!( + AbsoluteSystemPathBuf::new("./Users/user/"), + Err(PathError::NotAbsolute(_)) + ); + + assert_matches!(AbsoluteSystemPathBuf::new("Users"), Err(PathError::NotAbsolute(_))); + + let tail = RelativeUnixPathBuf::new("../other").unwrap(); + + assert_eq!( + AbsoluteSystemPathBuf::new("/some/dir").unwrap().join_unix_path(tail), + AbsoluteSystemPathBuf::new("/some/other").unwrap(), + ); + } + + #[cfg(windows)] + #[test] + fn test_absolute_system_path_buf_on_windows() { + assert!(AbsoluteSystemPathBuf::new("C:\\Users\\user").is_ok()); + assert_matches!( + AbsoluteSystemPathBuf::new(".\\Users\\user\\"), + Err(PathError::NotAbsolute(_)) + ); + assert_matches!(AbsoluteSystemPathBuf::new("Users"), Err(PathError::NotAbsolute(_))); + assert_matches!(AbsoluteSystemPathBuf::new("/Users/home"), Err(PathError::NotAbsolute(_))); + + let tail = RelativeUnixPathBuf::new("../other").unwrap(); + + assert_eq!( + AbsoluteSystemPathBuf::new("C:\\some\\dir").unwrap().join_unix_path(&tail), + AbsoluteSystemPathBuf::new("C:\\some\\other").unwrap(), + ); + } +} diff --git a/crates/turborepo-paths/Source/anchored_system_path.rs b/crates/turborepo-paths/Source/anchored_system_path.rs new file mode 100644 index 0000000000000..6588426c7e395 --- /dev/null +++ b/crates/turborepo-paths/Source/anchored_system_path.rs @@ -0,0 +1,168 @@ +use std::{fmt, path::Path}; + +use camino::{Utf8Component, Utf8Path}; +use path_clean::PathClean; +use serde::Serialize; + +use crate::{AnchoredSystemPathBuf, PathError, PathRelation, RelativeUnixPathBuf}; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Hash)] +#[serde(transparent)] +pub struct AnchoredSystemPath(Utf8Path); + +impl ToOwned for AnchoredSystemPath { + type Owned = AnchoredSystemPathBuf; + + fn to_owned(&self) -> Self::Owned { AnchoredSystemPathBuf(self.0.to_owned()) } +} + +impl AsRef for AnchoredSystemPath { + fn as_ref(&self) -> &AnchoredSystemPath { self } +} + +impl fmt::Display for AnchoredSystemPath { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } +} + +impl AsRef for AnchoredSystemPath { + fn as_ref(&self) -> &Utf8Path { &self.0 } +} + +impl AsRef for AnchoredSystemPath { + fn as_ref(&self) -> &Path { self.0.as_ref() } +} + +const EMPTY:&str = ""; + +impl AnchoredSystemPath { + pub(crate) unsafe fn new_unchecked(path:&(impl AsRef + ?Sized)) -> &Self { + let path = path.as_ref(); + unsafe { &*(path as *const Path as *const Self) } + } + + pub fn new(path:&(impl AsRef + ?Sized)) -> Result<&Self, PathError> { + let path_str = path.as_ref(); + let path = Path::new(path_str); + if path.is_absolute() { + return Err(PathError::NotRelative(path_str.to_string())); + } + + Ok(unsafe { &*(path as *const Path as *const Self) }) + } + + pub fn empty() -> &'static Self { unsafe { Self::new_unchecked(EMPTY) } } + + pub fn as_str(&self) -> &str { self.0.as_str() } + + pub fn parent(&self) -> Option<&AnchoredSystemPath> { + self.0.parent().map(|path| unsafe { AnchoredSystemPath::new_unchecked(path) }) + } + + pub fn ancestors(&self) -> impl Iterator { + self.0 + .ancestors() + .map(|path| unsafe { AnchoredSystemPath::new_unchecked(path) }) + } + + pub fn components(&self) -> impl Iterator { self.0.components() } + + pub fn as_path(&self) -> &Path { self.0.as_std_path() } + + pub fn to_unix(&self) -> RelativeUnixPathBuf { + #[cfg(unix)] + let buf = RelativeUnixPathBuf::new(self.0.as_str()); + + #[cfg(not(unix))] + let buf = { + use crate::IntoUnix; + let unix_buf = self.0.into_unix(); + RelativeUnixPathBuf::new(unix_buf) + }; + + buf.unwrap_or_else(|_| panic!("anchored system path is relative: {}", self.0.as_str())) + } + + pub fn join_component(&self, segment:&str) -> AnchoredSystemPathBuf { + debug_assert!(!segment.contains(std::path::MAIN_SEPARATOR)); + AnchoredSystemPathBuf(self.0.join(segment)) + } + + pub fn join_components(&self, segments:&[&str]) -> AnchoredSystemPathBuf { + debug_assert!(!segments.iter().any(|segment| segment.contains(std::path::MAIN_SEPARATOR))); + AnchoredSystemPathBuf( + self.0 + .join(segments.join(std::path::MAIN_SEPARATOR_STR)) + .as_std_path() + .clean() + .try_into() + .unwrap(), + ) + } + + pub fn clean(&self) -> AnchoredSystemPathBuf { + AnchoredSystemPathBuf(self.0.as_std_path().clean().try_into().unwrap()) + } + + /// relation_to_path does a lexical comparison of path components to + /// determine how this path relates to the given path. In the event that + /// the paths are the same, we return `Parent`, much the way that `contains` + /// would return `true`. + pub fn relation_to_path(&self, other:&Self) -> PathRelation { + let mut self_components = self.components(); + let mut other_components = other.components(); + loop { + match (self_components.next(), other_components.next()) { + // Non-matching component, the paths diverge + (Some(self_component), Some(other_component)) + if self_component != other_component => + { + return PathRelation::Divergent; + }, + // A matching component, continue iterating + (Some(_), Some(_)) => {}, + // We've reached the end of a possible parent without hitting a + // non-matching component. Return Parent. + (None, _) => return PathRelation::Parent, + // We've hit the end of the other path without hitting the + // end of this path. Since we haven't hit a non-matching component, + // our path must be a child + (_, None) => return PathRelation::Child, + } + } + } + + // Note that this defers to Path::strip_prefix, which operates on components, + // and therefore enforces boundaries at path dividers. + pub fn strip_prefix(&self, other:&Self) -> Option { + self.0 + .strip_prefix(&other.0) + .ok() + .map(|path| AnchoredSystemPathBuf(path.to_owned())) + } +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + + use crate::{AnchoredSystemPathBuf, PathRelation}; + + #[test_case(&["a", "b"], &["a", "b"], PathRelation::Parent ; "equal paths return parent")] + #[test_case(&["a"], &["a", "b"], PathRelation::Parent ; "a is a parent of a/b")] + #[test_case(&["a", "b"], &["a"], PathRelation::Child ; "a/b is a child of a")] + #[test_case(&["a", "b"], &["a", "c"], PathRelation::Divergent ; "a/b and a/c are divergent")] + fn test_path_relation( + abs_path_components:&[&str], + other_components:&[&str], + expected:PathRelation, + ) { + let abs_path = AnchoredSystemPathBuf::try_from("") + .unwrap() + .join_components(abs_path_components); + let other_path = + AnchoredSystemPathBuf::try_from("").unwrap().join_components(other_components); + + let relation = abs_path.relation_to_path(&other_path); + assert_eq!(relation, expected); + } +} diff --git a/crates/turborepo-paths/src/anchored_system_path_buf.rs b/crates/turborepo-paths/Source/anchored_system_path_buf.rs similarity index 100% rename from crates/turborepo-paths/src/anchored_system_path_buf.rs rename to crates/turborepo-paths/Source/anchored_system_path_buf.rs diff --git a/crates/turborepo-paths/Source/lib.rs b/crates/turborepo-paths/Source/lib.rs new file mode 100644 index 0000000000000..050362e8cde77 --- /dev/null +++ b/crates/turborepo-paths/Source/lib.rs @@ -0,0 +1,268 @@ +#![feature(assert_matches)] +#![deny(clippy::all)] + +//! Turborepo's path handling library. +//! Defines distinct path types for the different uses of paths in Turborepo's +//! codebase. +//! +//! - `AbsoluteSystemPath(Buf)`: a path that is absolute and uses the system's +//! path separator. Used for interacting with the filesystem +//! - `RelativeUnixPath(Buf)`: a path that is relative and uses the unix path +//! separator, i.e. `/`. Used when saving to a cache as a platform-independent +//! path. +//! - `AnchoredSystemPath(Buf)`: a path that is relative to a specific directory +//! and uses the system's path separator. Used for handling files relative to +//! the repository root. +//! +//! NOTE: All paths contain UTF-8 strings. We use `camino` as the underlying +//! representation for system paths. For reasons why, see [the `camino` documentation](https://github.com/camino-rs/camino/). +//! +//! As in `std::path`, there are `Path` and `PathBuf` variants of each path +//! type, that indicate whether the path is borrowed or owned. +//! +//! # Validation +//! +//! When initializing a path type, it is highly recommended that you use a +//! method that validates the path. This will ensure that the path is in the +//! correct format. It's important to note that the validation will only +//! check for absolute or relative and valid Unicode. It will not check +//! if the path is system or unix, since that is not always decidable. +//! For example, is `foo\bar` a Windows system path or a Unix path? +//! It has a backslash, which is simultaneously a valid character in a +//! Unix file name and the Windows path delimiter. +//! +//! Therefore, it's very important to keep the context of the initialization +//! in mind. The only case where we do more in depth validation is for cache +//! restoration. See `AnchoredSystemPathBuf::from_system_path` for more details. +//! +//! The only case where initializing a path type without validation is +//! recommended is inside turbopath itself. But that unchecked initialization +//! should be considered unsafe +mod absolute_system_path; +mod absolute_system_path_buf; +mod anchored_system_path; +mod anchored_system_path_buf; +mod relative_unix_path; +mod relative_unix_path_buf; + +use std::io; + +pub use absolute_system_path::{AbsoluteSystemPath, PathRelation}; +pub use absolute_system_path_buf::AbsoluteSystemPathBuf; +pub use anchored_system_path::AnchoredSystemPath; +pub use anchored_system_path_buf::AnchoredSystemPathBuf; +use camino::{Utf8Path, Utf8PathBuf}; +use miette::Diagnostic; +pub use relative_unix_path::RelativeUnixPath; +pub use relative_unix_path_buf::{RelativeUnixPathBuf, RelativeUnixPathBufTestExt}; +use thiserror::Error; + +// Lets windows know that we're going to be reading this file sequentially +#[cfg(windows)] +pub const FILE_FLAG_SEQUENTIAL_SCAN:u32 = 0x08000000; + +#[derive(Debug, Error, Diagnostic)] +pub enum PathError { + #[error("Path is non-UTF-8: {0}")] + InvalidUnicode(String), + #[error("Failed to convert path")] + FromPathBufError(#[from] camino::FromPathBufError), + #[error("Failed to convert path")] + FromPathError(#[from] camino::FromPathError), + #[error("path is malformed: {0}")] + MalformedPath(String), + #[error("Path is not safe for windows: {0}")] + WindowsUnsafePath(String), + #[error("Path is not absolute: {0}")] + NotAbsolute(String), + #[error("Path is not relative: {0}")] + NotRelative(String), + #[error("Path {0} is not parent of {1}")] + NotParent(String, String), + #[error("IO Error {0}")] + IO(#[from] io::Error), + #[error("{0} is not a prefix for {1}")] + PrefixError(String, String), +} + +impl From for PathError { + fn from(value:std::string::FromUtf8Error) -> Self { + PathError::InvalidUnicode(value.utf8_error().to_string()) + } +} + +impl PathError { + pub fn is_io_error(&self, kind:io::ErrorKind) -> bool { + matches!(self, PathError::IO(err) if err.kind() == kind) + } +} + +pub trait IntoUnix { + fn into_unix(self) -> Utf8PathBuf; +} + +#[cfg(windows)] +fn convert_separator( + path:impl AsRef, + input_separator:char, + output_separator:char, +) -> Utf8PathBuf { + let path = path.as_ref(); + + Utf8PathBuf::from( + path.chars() + .map(|c| if c == input_separator { output_separator } else { c }) + .collect::(), + ) +} + +impl> IntoUnix for T { + /// NOTE: `into_unix` *only* converts Windows paths to Unix paths *on* a + /// Windows system. Do not pass a Windows path on a Unix system and + /// assume it'll be converted. + fn into_unix(self) -> Utf8PathBuf { + let output; + + #[cfg(windows)] + { + output = convert_separator(self, std::path::MAIN_SEPARATOR, '/') + } + + #[cfg(not(windows))] + { + output = Utf8PathBuf::from(self.as_ref()) + } + + output + } +} + +#[derive(Debug, PartialEq)] +struct PathValidation { + well_formed:bool, + windows_safe:bool, +} + +// Checks if path is well formed and safe for Windows. +pub(crate) fn check_path(name:&str) -> PathValidation { + if name.is_empty() { + return PathValidation { well_formed:false, windows_safe:false }; + } + + let mut well_formed = true; + let mut windows_safe = true; + + // Name is: + // - "." + // - ".." + if well_formed && (name == "." || name == "..") { + well_formed = false; + } + + // Name starts with: + // - `/` + // - `./` + // - `../` + if well_formed && (name.starts_with('/') || name.starts_with("./") || name.starts_with("../")) { + well_formed = false; + } + + // Name ends in: + // - `/.` + // - `/..` + if well_formed && (name.ends_with("/.") || name.ends_with("/..")) { + well_formed = false; + } + + // Name contains: + // - `//` + // - `/./` + // - `/../` + if well_formed && (name.contains("//") || name.contains("/./") || name.contains("/../")) { + well_formed = false; + } + + // Name contains: `\` + if name.contains('\\') { + windows_safe = false; + } + + PathValidation { well_formed, windows_safe } +} + +pub enum UnknownPathType { + Absolute(AbsoluteSystemPathBuf), + Anchored(AnchoredSystemPathBuf), +} + +/// Categorizes a path as either an `AbsoluteSystemPathBuf` or +/// an `AnchoredSystemPathBuf` depending on whether it +/// is absolute or relative. +pub fn categorize(path:&Utf8Path) -> UnknownPathType { + let path = Utf8PathBuf::try_from(path_clean::clean(path)) + .expect("path cleaning should preserve UTF-8"); + if path.is_absolute() { + UnknownPathType::Absolute(AbsoluteSystemPathBuf(path)) + } else { + UnknownPathType::Anchored(AnchoredSystemPathBuf(path)) + } +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + + use crate::{IntoUnix, PathValidation, check_path}; + + #[test] + fn test_into_unix() { + #[cfg(unix)] + { + assert_eq!("foo/bar".into_unix(), "foo/bar"); + assert_eq!("/foo/bar".into_unix(), "/foo/bar"); + assert_eq!("foo\\bar".into_unix(), "foo\\bar"); + } + + #[cfg(windows)] + { + assert_eq!("foo/bar".into_unix(), "foo/bar"); + assert_eq!("\\foo\\bar".into_unix(), "/foo/bar"); + assert_eq!("foo\\bar".into_unix(), "foo/bar"); + } + } + + #[test_case("", PathValidation { well_formed: false, windows_safe: false } ; "1")] + #[test_case(".", PathValidation { well_formed: false, windows_safe: true } ; "2")] + #[test_case("..", PathValidation { well_formed: false, windows_safe: true } ; "3")] + #[test_case("/", PathValidation { well_formed: false, windows_safe: true } ; "4")] + #[test_case("./", PathValidation { well_formed: false, windows_safe: true } ; "5")] + #[test_case("../", PathValidation { well_formed: false, windows_safe: true } ; "6")] + #[test_case("/a", PathValidation { well_formed: false, windows_safe: true } ; "7")] + #[test_case("./a", PathValidation { well_formed: false, windows_safe: true } ; "8")] + #[test_case("../a", PathValidation { well_formed: false, windows_safe: true } ; "9")] + #[test_case("/.", PathValidation { well_formed: false, windows_safe: true } ; "10")] + #[test_case("/..", PathValidation { well_formed: false, windows_safe: true } ; "11")] + #[test_case("a/.", PathValidation { well_formed: false, windows_safe: true } ; "12")] + #[test_case("a/..", PathValidation { well_formed: false, windows_safe: true } ; "13")] + #[test_case("//", PathValidation { well_formed: false, windows_safe: true } ; "14")] + #[test_case("/./", PathValidation { well_formed: false, windows_safe: true } ; "15")] + #[test_case("/../", PathValidation { well_formed: false, windows_safe: true } ; "16")] + #[test_case("a//", PathValidation { well_formed: false, windows_safe: true } ; "17")] + #[test_case("a/./", PathValidation { well_formed: false, windows_safe: true } ; "18")] + #[test_case("a/../", PathValidation { well_formed: false, windows_safe: true } ; "19")] + #[test_case("//a", PathValidation { well_formed: false, windows_safe: true } ; "20")] + #[test_case("/./a", PathValidation { well_formed: false, windows_safe: true } ; "21")] + #[test_case("/../a", PathValidation { well_formed: false, windows_safe: true } ; "22")] + #[test_case("a//a", PathValidation { well_formed: false, windows_safe: true } ; "23")] + #[test_case("a/./a", PathValidation { well_formed: false, windows_safe: true } ; "24")] + #[test_case("a/../a", PathValidation { well_formed: false, windows_safe: true } ; "25")] + #[test_case("...", PathValidation { well_formed: true, windows_safe: true } ; "26")] + #[test_case(".../a", PathValidation { well_formed: true, windows_safe: true } ; "27")] + #[test_case("a/...", PathValidation { well_formed: true, windows_safe: true } ; "28")] + #[test_case("a/.../a", PathValidation { well_formed: true, windows_safe: true } ; "29")] + #[test_case(".../...", PathValidation { well_formed: true, windows_safe: true } ; "30")] + fn test_check_path(path:&'static str, expected_output:PathValidation) { + let output = check_path(path); + assert_eq!(output, expected_output); + } +} diff --git a/crates/turborepo-paths/Source/relative_unix_path.rs b/crates/turborepo-paths/Source/relative_unix_path.rs new file mode 100644 index 0000000000000..0a0cae818438a --- /dev/null +++ b/crates/turborepo-paths/Source/relative_unix_path.rs @@ -0,0 +1,108 @@ +use std::{ + fmt, + fmt::{Display, Formatter}, +}; + +use camino::{Utf8Path, Utf8PathBuf}; + +use crate::{AnchoredSystemPathBuf, PathError, RelativeUnixPathBuf}; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct RelativeUnixPath(str); + +impl Display for RelativeUnixPath { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { write!(f, "{}", &self.0) } +} + +impl RelativeUnixPath { + pub fn new + ?Sized>(value:&P) -> Result<&Self, PathError> { + let path = value.as_ref(); + if path.starts_with('/') { + return Err(PathError::NotRelative(path.to_string())); + } + // copied from stdlib path.rs: relies on the representation of + // RelativeUnixPath being just a str, the same way Path relies on + // just being an OsStr + Ok(unsafe { &*(path as *const str as *const Self) }) + } + + pub(crate) fn to_system_path_buf(&self) -> Utf8PathBuf { + #[cfg(unix)] + { + // On unix, unix paths are already system paths. Copy the string + // but skip validation. + Utf8PathBuf::from(&self.0) + } + + #[cfg(windows)] + { + let system_path_string = self.0.replace('/', "\\"); + Utf8PathBuf::from(system_path_string) + } + } + + pub fn to_anchored_system_path_buf(&self) -> AnchoredSystemPathBuf { + AnchoredSystemPathBuf(self.to_system_path_buf()) + } + + pub fn is_empty(&self) -> bool { self.0.is_empty() } + + pub fn as_str(&self) -> &str { &self.0 } + + pub fn to_owned(&self) -> RelativeUnixPathBuf { RelativeUnixPathBuf(self.0.to_owned()) } + + pub fn strip_prefix( + &self, + prefix:impl AsRef, + ) -> Result<&RelativeUnixPath, PathError> { + let stripped_path = self + .0 + .strip_prefix(&prefix.as_ref().0) + .ok_or_else(|| PathError::NotParent(prefix.as_ref().to_string(), self.to_string()))?; + + // Remove leading '/' if present + let stripped_path = stripped_path.strip_prefix('/').unwrap_or(stripped_path); + + Ok(unsafe { &*(stripped_path as *const str as *const Self) }) + } + + // NOTE: This only applies to full path components. If you + // want to check a file extension, use `RelativeUnixPathBuf::extension`. + pub fn ends_with(&self, suffix:impl AsRef) -> bool { self.0.ends_with(suffix.as_ref()) } + + pub fn extension(&self) -> Option<&str> { Utf8Path::new(&self.0).extension() } + + pub fn join_component(&self, segment:&str) -> RelativeUnixPathBuf { + debug_assert!(!segment.contains('/')); + RelativeUnixPathBuf(format!("{}/{}", &self.0, segment)) + } +} + +impl AsRef for RelativeUnixPath { + fn as_ref(&self) -> &RelativeUnixPath { self } +} + +impl<'a> From<&'a RelativeUnixPath> for wax::CandidatePath<'a> { + fn from(path:&'a RelativeUnixPath) -> Self { path.0.into() } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::AnchoredSystemPath; + + #[test] + fn test_to_anchored_system_path_buf() { + let path = RelativeUnixPath::new("foo/bar/baz").unwrap(); + let expected = AnchoredSystemPath::new(if cfg!(windows) { + // Unix path separators should be converted + "foo\\bar\\baz" + } else { + // Unix paths already have correct separators + "foo/bar/baz" + }) + .unwrap(); + assert_eq!(&*path.to_anchored_system_path_buf(), expected); + } +} diff --git a/crates/turborepo-paths/Source/relative_unix_path_buf.rs b/crates/turborepo-paths/Source/relative_unix_path_buf.rs new file mode 100644 index 0000000000000..c1ad45d870bb8 --- /dev/null +++ b/crates/turborepo-paths/Source/relative_unix_path_buf.rs @@ -0,0 +1,224 @@ +use std::{ + borrow::Borrow, + fmt, + fmt::{Display, Formatter}, + ops::Deref, +}; + +use camino::Utf8Path; +use serde::{Deserialize, Serialize}; + +use crate::{PathError, RelativeUnixPath}; +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)] +// This is necessary to perform validation on the string during deserialization +#[serde(try_from = "String", into = "String")] +pub struct RelativeUnixPathBuf(pub(crate) String); + +#[cfg(feature = "biome")] +mod biome { + use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic}; + use turborepo_unescape::UnescapedString; + + use crate::RelativeUnixPathBuf; + + impl Deserializable for RelativeUnixPathBuf { + fn deserialize( + value:&impl DeserializableValue, + name:&str, + diagnostics:&mut Vec, + ) -> Option { + let path:String = UnescapedString::deserialize(value, name, diagnostics)?.into(); + match Self::new(path) { + Ok(path) => Some(path), + Err(e) => { + diagnostics.push( + DeserializationDiagnostic::new(e.to_string()).with_range(value.range()), + ); + None + }, + } + } + } +} + +impl Display for RelativeUnixPathBuf { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { Display::fmt(&self.0, f) } +} + +impl RelativeUnixPathBuf { + pub fn new(path:impl Into) -> Result { + let path_string = path.into(); + if path_string.starts_with('/') || Utf8Path::new(&path_string).is_absolute() { + return Err(PathError::NotRelative(path_string)); + } + + Ok(Self(path_string)) + } + + pub fn into_inner(self) -> String { self.0 } + + pub fn make_canonical_for_tar(&mut self, is_dir:bool) { + if is_dir && !self.0.ends_with('/') { + self.0.push('/'); + } + } + + pub fn strip_prefix(&self, prefix:&RelativeUnixPathBuf) -> Result { + let prefix_len = prefix.0.len(); + if prefix_len == 0 { + return Ok(self.clone()); + } + if !self.0.starts_with(&prefix.0) { + return Err(PathError::NotParent(prefix.0.to_string(), self.0.to_string())); + } + + // Handle the case where we are stripping the entire contents of this path + if self.0.len() == prefix.0.len() { + return Self::new(""); + } + + // We now know that this path starts with the prefix, and that this path's + // length is greater than the prefix's length + if self.0.as_bytes()[prefix_len] != b'/' { + let prefix_str = prefix.0.clone(); + let this = self.0.clone(); + return Err(PathError::PrefixError(prefix_str, this)); + } + + let tail_slice = &self.0[(prefix_len + 1)..]; + Self::new(tail_slice) + } +} + +pub trait RelativeUnixPathBufTestExt { + fn join(&self, tail:&RelativeUnixPathBuf) -> Self; +} + +impl RelativeUnixPathBufTestExt for RelativeUnixPathBuf { + // Marked as test-only because it doesn't automatically clean the resulting + // path. *If* we end up needing or wanting this method outside of tests, we + // will need to implement .clean() for the result. + fn join(&self, tail:&RelativeUnixPathBuf) -> Self { + if self.0.is_empty() { + return tail.clone(); + } + let mut joined = self.0.clone(); + joined.push('/'); + joined.push_str(&tail.0); + Self(joined) + } +} + +impl Borrow for RelativeUnixPathBuf { + fn borrow(&self) -> &RelativeUnixPath { + let inner:&str = self.0.borrow(); + unsafe { &*(inner as *const str as *const RelativeUnixPath) } + } +} + +impl AsRef for RelativeUnixPathBuf { + fn as_ref(&self) -> &RelativeUnixPath { self.borrow() } +} + +impl Deref for RelativeUnixPathBuf { + type Target = RelativeUnixPath; + + fn deref(&self) -> &Self::Target { self.borrow() } +} + +impl TryFrom for RelativeUnixPathBuf { + type Error = PathError; + + fn try_from(value:String) -> Result { Self::new(value) } +} + +// From should not be implemented for RelativeUnixPathBuf as validation +// may fail +#[allow(clippy::from_over_into)] +impl Into for RelativeUnixPathBuf { + fn into(self) -> String { self.0 } +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + use super::*; + + #[test] + fn test_relative_unix_path_buf() { + let path = RelativeUnixPathBuf::new("foo/bar").unwrap(); + assert_eq!(path.as_str(), "foo/bar"); + } + + #[test] + fn test_relative_unix_path_buf_with_extension() { + let path = RelativeUnixPathBuf::new("foo/bar.txt").unwrap(); + assert_eq!(path.as_str(), "foo/bar.txt"); + } + + #[test] + fn test_join() { + let head = RelativeUnixPathBuf::new("some/path").unwrap(); + let tail = RelativeUnixPathBuf::new("child/leaf").unwrap(); + let combined = head.join(&tail); + assert_eq!(combined.as_str(), "some/path/child/leaf"); + } + + #[test] + fn test_strip_prefix() { + let combined = RelativeUnixPathBuf::new("some/path/child/leaf").unwrap(); + let head = RelativeUnixPathBuf::new("some/path").unwrap(); + let expected = RelativeUnixPathBuf::new("child/leaf").unwrap(); + let tail = combined.strip_prefix(&head).unwrap(); + assert_eq!(tail, expected); + } + + #[test] + fn test_strip_entire_contents() { + let combined = RelativeUnixPathBuf::new("some/path").unwrap(); + let head = combined.clone(); + let expected = RelativeUnixPathBuf::new("").unwrap(); + let tail = combined.strip_prefix(&head).unwrap(); + assert_eq!(tail, expected); + } + + #[test] + fn test_strip_empty_prefix() { + let combined = RelativeUnixPathBuf::new("some/path").unwrap(); + let tail = combined.strip_prefix(&RelativeUnixPathBuf::new("").unwrap()).unwrap(); + assert_eq!(tail, combined); + } + + #[test] + fn test_relative_unix_path_buf_errors() { + assert!(RelativeUnixPathBuf::new("/foo/bar").is_err()); + // Note: this shouldn't be an error, this is a valid relative unix path + // #[cfg(windows)] + // assert!(RelativeUnixPathBuf::new(PathBuf::from("C:\\foo\\bar")). + // is_err()); + } + + #[derive(Debug, Serialize, Deserialize)] + struct TestSchema { + field:RelativeUnixPathBuf, + } + + #[test] + fn test_roundtrip() { + let path = "relative/unix/path\\evil"; + let value = json!({ "field": path }); + let foo:TestSchema = serde_json::from_value(value.clone()).unwrap(); + assert_eq!(foo.field.deref(), RelativeUnixPath::new(path).unwrap()); + assert_eq!(serde_json::to_value(foo).unwrap(), value); + } + + #[test] + fn test_deserialization_fails_on_absolute() { + let foo:Result = serde_json::from_value(json!({"field": "/absolute/path"})); + let Err(e) = foo else { + panic!("expected absolute path deserialization to fail") + }; + assert_eq!(e.to_string(), "Path is not relative: /absolute/path"); + } +} diff --git a/crates/turborepo-paths/src/absolute_system_path_buf.rs b/crates/turborepo-paths/src/absolute_system_path_buf.rs deleted file mode 100644 index 783a1c37eff1c..0000000000000 --- a/crates/turborepo-paths/src/absolute_system_path_buf.rs +++ /dev/null @@ -1,303 +0,0 @@ -use std::{ - borrow::Borrow, - fmt, io, - ops::Deref, - path::{Path, PathBuf}, -}; - -use camino::{Utf8Components, Utf8Path, Utf8PathBuf}; -use fs_err as fs; -use path_clean::PathClean; -use serde::Serialize; - -use crate::{AbsoluteSystemPath, AnchoredSystemPathBuf, PathError}; - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize)] -pub struct AbsoluteSystemPathBuf(pub(crate) Utf8PathBuf); - -impl Borrow for AbsoluteSystemPathBuf { - fn borrow(&self) -> &AbsoluteSystemPath { - let path = self.as_path(); - unsafe { &*(path as *const Utf8Path as *const AbsoluteSystemPath) } - } -} - -impl AsRef for AbsoluteSystemPathBuf { - fn as_ref(&self) -> &AbsoluteSystemPath { - self - } -} - -impl Deref for AbsoluteSystemPathBuf { - type Target = AbsoluteSystemPath; - - fn deref(&self) -> &Self::Target { - self.borrow() - } -} - -impl AbsoluteSystemPathBuf { - /// Create a new AbsoluteSystemPathBuf from `unchecked_path`. - /// Confirms that `unchecked_path` is absolute. Does *not* convert - /// to system path, since that is generally undecidable (see module - /// documentation) - /// - /// # Arguments - /// - /// * `unchecked_path`: The path to be validated and converted to an - /// `AbsoluteSystemPathBuf`. - /// - /// returns: Result - /// - /// # Examples - /// - /// ``` - /// use std::path::{Path, PathBuf}; - /// use camino::Utf8Path; - /// use turbopath::AbsoluteSystemPathBuf; - /// #[cfg(windows)] - /// let path = "C:/Users/user"; - /// #[cfg(not(windows))] - /// let path = "/Users/user"; - /// - /// let absolute_path = AbsoluteSystemPathBuf::new(path).unwrap(); - /// - /// #[cfg(windows)] - /// assert_eq!(absolute_path.as_path(), Utf8Path::new("C:\\Users\\user")); - /// #[cfg(not(windows))] - /// assert_eq!(absolute_path.as_path(), Utf8Path::new("/Users/user")); - /// ``` - pub fn new(unchecked_path: impl Into) -> Result { - let unchecked_path = unchecked_path.into(); - if !Path::new(&unchecked_path).is_absolute() { - return Err(PathError::NotAbsolute(unchecked_path)); - } - Ok(AbsoluteSystemPathBuf(unchecked_path.into())) - } - - /// Takes in a system path of unknown type. If it's absolute, returns the - /// path, If it's relative, appends it to the base after cleaning it. - pub fn from_unknown(base: &AbsoluteSystemPath, unknown: impl Into) -> Self { - // we have an absolute system path and an unknown kind of system path. - let unknown: Utf8PathBuf = unknown.into(); - if unknown.is_absolute() { - Self(unknown) - } else { - Self( - base.as_path() - .join(unknown) - .as_std_path() - .clean() - .try_into() - .expect("clean should produce valid UTF-8"), - ) - } - } - - pub fn from_cwd(unknown: impl Into) -> Result { - let cwd = Self::cwd()?; - Ok(Self::from_unknown(&cwd, unknown)) - } - - pub fn cwd() -> Result { - // TODO(errors): Unwrap current_dir() - Ok(Self(Utf8PathBuf::try_from(std::env::current_dir()?)?)) - } - - /// Anchors `path` at `self`. - /// - /// # Arguments - /// - /// * `path`: The path to be anchored at `self` - /// - /// returns: Result - /// - /// # Examples - /// - /// ``` - /// use std::path::Path; - /// use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; - /// #[cfg(not(windows))] - /// { - /// let base = AbsoluteSystemPathBuf::new("/Users/user").unwrap(); - /// let anchored_path = AbsoluteSystemPathBuf::new("/Users/user/Documents").unwrap(); - /// let anchored_path = base.anchor(&anchored_path).unwrap(); - /// assert_eq!(anchored_path.as_str(), "Documents"); - /// } - /// - /// #[cfg(windows)] - /// { - /// let base = AbsoluteSystemPathBuf::new("C:\\Users\\user").unwrap(); - /// let anchored_path = AbsoluteSystemPathBuf::new("C:\\Users\\user\\Documents").unwrap(); - /// let anchored_path = base.anchor(&anchored_path).unwrap(); - /// assert_eq!(anchored_path.as_str(), "Documents"); - /// } - /// ``` - pub fn anchor( - &self, - path: impl AsRef, - ) -> Result { - AnchoredSystemPathBuf::new(self, path) - } - - pub fn as_path(&self) -> &Utf8Path { - self.0.as_path() - } - - pub fn components(&self) -> Utf8Components<'_> { - self.0.components() - } - - pub fn parent(&self) -> Option<&AbsoluteSystemPath> { - self.0.parent().map(AbsoluteSystemPath::new_unchecked) - } - - pub fn starts_with>(&self, base: P) -> bool { - self.0.starts_with(base.as_ref()) - } - - pub fn ends_with>(&self, child: P) -> bool { - self.0.ends_with(child.as_ref()) - } - - pub fn ensure_dir(&self) -> Result<(), io::Error> { - if let Some(parent) = self.0.parent() { - fs::create_dir_all(parent) - } else { - Ok(()) - } - } - - pub fn create_dir_all(&self) -> Result<(), io::Error> { - fs::create_dir_all(self.0.as_path()) - } - - pub fn remove(&self) -> Result<(), io::Error> { - fs::remove_file(self.0.as_path()) - } - - pub fn set_readonly(&self) -> Result<(), PathError> { - let metadata = fs::symlink_metadata(self)?; - let mut perms = metadata.permissions(); - perms.set_readonly(true); - fs::set_permissions(self.0.as_path(), perms)?; - Ok(()) - } - - pub fn is_readonly(&self) -> Result { - Ok(self.0.symlink_metadata()?.permissions().readonly()) - } - - pub fn as_str(&self) -> &str { - self.0.as_str() - } - - pub fn file_name(&self) -> Option<&str> { - self.0.file_name() - } - - pub fn extension(&self) -> Option<&str> { - self.0.extension() - } -} - -impl TryFrom for AbsoluteSystemPathBuf { - type Error = PathError; - - fn try_from(path: PathBuf) -> Result { - Self::new(Utf8PathBuf::try_from(path)?) - } -} - -impl TryFrom<&Path> for AbsoluteSystemPathBuf { - type Error = PathError; - - fn try_from(path: &Path) -> Result { - let utf8_path: &Utf8Path = path.try_into()?; - Self::new(utf8_path.to_owned()) - } -} - -impl TryFrom<&str> for AbsoluteSystemPathBuf { - type Error = PathError; - - fn try_from(value: &str) -> Result { - Self::new(Utf8PathBuf::from(value)) - } -} - -impl From for PathBuf { - fn from(path: AbsoluteSystemPathBuf) -> Self { - path.0.into_std_path_buf() - } -} - -impl fmt::Display for AbsoluteSystemPathBuf { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.as_str()) - } -} - -impl AsRef for AbsoluteSystemPathBuf { - fn as_ref(&self) -> &Path { - self.0.as_std_path() - } -} - -#[cfg(test)] -mod tests { - use std::assert_matches::assert_matches; - - use crate::{AbsoluteSystemPathBuf, PathError, RelativeUnixPathBuf}; - - #[cfg(not(windows))] - #[test] - fn test_absolute_system_path_buf_on_unix() { - assert!(AbsoluteSystemPathBuf::new("/Users/user").is_ok()); - assert_matches!( - AbsoluteSystemPathBuf::new("./Users/user/"), - Err(PathError::NotAbsolute(_)) - ); - - assert_matches!( - AbsoluteSystemPathBuf::new("Users"), - Err(PathError::NotAbsolute(_)) - ); - - let tail = RelativeUnixPathBuf::new("../other").unwrap(); - - assert_eq!( - AbsoluteSystemPathBuf::new("/some/dir") - .unwrap() - .join_unix_path(tail), - AbsoluteSystemPathBuf::new("/some/other").unwrap(), - ); - } - - #[cfg(windows)] - #[test] - fn test_absolute_system_path_buf_on_windows() { - assert!(AbsoluteSystemPathBuf::new("C:\\Users\\user").is_ok()); - assert_matches!( - AbsoluteSystemPathBuf::new(".\\Users\\user\\"), - Err(PathError::NotAbsolute(_)) - ); - assert_matches!( - AbsoluteSystemPathBuf::new("Users"), - Err(PathError::NotAbsolute(_)) - ); - assert_matches!( - AbsoluteSystemPathBuf::new("/Users/home"), - Err(PathError::NotAbsolute(_)) - ); - - let tail = RelativeUnixPathBuf::new("../other").unwrap(); - - assert_eq!( - AbsoluteSystemPathBuf::new("C:\\some\\dir") - .unwrap() - .join_unix_path(&tail), - AbsoluteSystemPathBuf::new("C:\\some\\other").unwrap(), - ); - } -} diff --git a/crates/turborepo-paths/src/anchored_system_path.rs b/crates/turborepo-paths/src/anchored_system_path.rs deleted file mode 100644 index 4f9e379ce23bd..0000000000000 --- a/crates/turborepo-paths/src/anchored_system_path.rs +++ /dev/null @@ -1,191 +0,0 @@ -use std::{fmt, path::Path}; - -use camino::{Utf8Component, Utf8Path}; -use path_clean::PathClean; -use serde::Serialize; - -use crate::{AnchoredSystemPathBuf, PathError, PathRelation, RelativeUnixPathBuf}; - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Hash)] -#[serde(transparent)] -pub struct AnchoredSystemPath(Utf8Path); - -impl ToOwned for AnchoredSystemPath { - type Owned = AnchoredSystemPathBuf; - - fn to_owned(&self) -> Self::Owned { - AnchoredSystemPathBuf(self.0.to_owned()) - } -} - -impl AsRef for AnchoredSystemPath { - fn as_ref(&self) -> &AnchoredSystemPath { - self - } -} - -impl fmt::Display for AnchoredSystemPath { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -impl AsRef for AnchoredSystemPath { - fn as_ref(&self) -> &Utf8Path { - &self.0 - } -} - -impl AsRef for AnchoredSystemPath { - fn as_ref(&self) -> &Path { - self.0.as_ref() - } -} - -const EMPTY: &str = ""; - -impl AnchoredSystemPath { - pub(crate) unsafe fn new_unchecked(path: &(impl AsRef + ?Sized)) -> &Self { - let path = path.as_ref(); - unsafe { &*(path as *const Path as *const Self) } - } - - pub fn new(path: &(impl AsRef + ?Sized)) -> Result<&Self, PathError> { - let path_str = path.as_ref(); - let path = Path::new(path_str); - if path.is_absolute() { - return Err(PathError::NotRelative(path_str.to_string())); - } - - Ok(unsafe { &*(path as *const Path as *const Self) }) - } - - pub fn empty() -> &'static Self { - unsafe { Self::new_unchecked(EMPTY) } - } - - pub fn as_str(&self) -> &str { - self.0.as_str() - } - - pub fn parent(&self) -> Option<&AnchoredSystemPath> { - self.0 - .parent() - .map(|path| unsafe { AnchoredSystemPath::new_unchecked(path) }) - } - - pub fn ancestors(&self) -> impl Iterator { - self.0 - .ancestors() - .map(|path| unsafe { AnchoredSystemPath::new_unchecked(path) }) - } - - pub fn components(&self) -> impl Iterator { - self.0.components() - } - - pub fn as_path(&self) -> &Path { - self.0.as_std_path() - } - - pub fn to_unix(&self) -> RelativeUnixPathBuf { - #[cfg(unix)] - let buf = RelativeUnixPathBuf::new(self.0.as_str()); - - #[cfg(not(unix))] - let buf = { - use crate::IntoUnix; - let unix_buf = self.0.into_unix(); - RelativeUnixPathBuf::new(unix_buf) - }; - - buf.unwrap_or_else(|_| panic!("anchored system path is relative: {}", self.0.as_str())) - } - - pub fn join_component(&self, segment: &str) -> AnchoredSystemPathBuf { - debug_assert!(!segment.contains(std::path::MAIN_SEPARATOR)); - AnchoredSystemPathBuf(self.0.join(segment)) - } - - pub fn join_components(&self, segments: &[&str]) -> AnchoredSystemPathBuf { - debug_assert!(!segments - .iter() - .any(|segment| segment.contains(std::path::MAIN_SEPARATOR))); - AnchoredSystemPathBuf( - self.0 - .join(segments.join(std::path::MAIN_SEPARATOR_STR)) - .as_std_path() - .clean() - .try_into() - .unwrap(), - ) - } - - pub fn clean(&self) -> AnchoredSystemPathBuf { - AnchoredSystemPathBuf(self.0.as_std_path().clean().try_into().unwrap()) - } - - /// relation_to_path does a lexical comparison of path components to - /// determine how this path relates to the given path. In the event that - /// the paths are the same, we return `Parent`, much the way that `contains` - /// would return `true`. - pub fn relation_to_path(&self, other: &Self) -> PathRelation { - let mut self_components = self.components(); - let mut other_components = other.components(); - loop { - match (self_components.next(), other_components.next()) { - // Non-matching component, the paths diverge - (Some(self_component), Some(other_component)) - if self_component != other_component => - { - return PathRelation::Divergent - } - // A matching component, continue iterating - (Some(_), Some(_)) => {} - // We've reached the end of a possible parent without hitting a - // non-matching component. Return Parent. - (None, _) => return PathRelation::Parent, - // We've hit the end of the other path without hitting the - // end of this path. Since we haven't hit a non-matching component, - // our path must be a child - (_, None) => return PathRelation::Child, - } - } - } - - // Note that this defers to Path::strip_prefix, which operates on components, - // and therefore enforces boundaries at path dividers. - pub fn strip_prefix(&self, other: &Self) -> Option { - self.0 - .strip_prefix(&other.0) - .ok() - .map(|path| AnchoredSystemPathBuf(path.to_owned())) - } -} - -#[cfg(test)] -mod tests { - use test_case::test_case; - - use crate::{AnchoredSystemPathBuf, PathRelation}; - - #[test_case(&["a", "b"], &["a", "b"], PathRelation::Parent ; "equal paths return parent")] - #[test_case(&["a"], &["a", "b"], PathRelation::Parent ; "a is a parent of a/b")] - #[test_case(&["a", "b"], &["a"], PathRelation::Child ; "a/b is a child of a")] - #[test_case(&["a", "b"], &["a", "c"], PathRelation::Divergent ; "a/b and a/c are divergent")] - fn test_path_relation( - abs_path_components: &[&str], - other_components: &[&str], - expected: PathRelation, - ) { - let abs_path = AnchoredSystemPathBuf::try_from("") - .unwrap() - .join_components(abs_path_components); - let other_path = AnchoredSystemPathBuf::try_from("") - .unwrap() - .join_components(other_components); - - let relation = abs_path.relation_to_path(&other_path); - assert_eq!(relation, expected); - } -} diff --git a/crates/turborepo-paths/src/lib.rs b/crates/turborepo-paths/src/lib.rs deleted file mode 100644 index 8debe62150c87..0000000000000 --- a/crates/turborepo-paths/src/lib.rs +++ /dev/null @@ -1,280 +0,0 @@ -#![feature(assert_matches)] -#![deny(clippy::all)] - -//! Turborepo's path handling library. -//! Defines distinct path types for the different uses of paths in Turborepo's -//! codebase. -//! -//! - `AbsoluteSystemPath(Buf)`: a path that is absolute and uses the system's -//! path separator. Used for interacting with the filesystem -//! - `RelativeUnixPath(Buf)`: a path that is relative and uses the unix path -//! separator, i.e. `/`. Used when saving to a cache as a platform-independent -//! path. -//! - `AnchoredSystemPath(Buf)`: a path that is relative to a specific directory -//! and uses the system's path separator. Used for handling files relative to -//! the repository root. -//! -//! NOTE: All paths contain UTF-8 strings. We use `camino` as the underlying -//! representation for system paths. For reasons why, see [the `camino` documentation](https://github.com/camino-rs/camino/). -//! -//! As in `std::path`, there are `Path` and `PathBuf` variants of each path -//! type, that indicate whether the path is borrowed or owned. -//! -//! # Validation -//! -//! When initializing a path type, it is highly recommended that you use a -//! method that validates the path. This will ensure that the path is in the -//! correct format. It's important to note that the validation will only -//! check for absolute or relative and valid Unicode. It will not check -//! if the path is system or unix, since that is not always decidable. -//! For example, is `foo\bar` a Windows system path or a Unix path? -//! It has a backslash, which is simultaneously a valid character in a -//! Unix file name and the Windows path delimiter. -//! -//! Therefore, it's very important to keep the context of the initialization -//! in mind. The only case where we do more in depth validation is for cache -//! restoration. See `AnchoredSystemPathBuf::from_system_path` for more details. -//! -//! The only case where initializing a path type without validation is -//! recommended is inside turbopath itself. But that unchecked initialization -//! should be considered unsafe -mod absolute_system_path; -mod absolute_system_path_buf; -mod anchored_system_path; -mod anchored_system_path_buf; -mod relative_unix_path; -mod relative_unix_path_buf; - -use std::io; - -pub use absolute_system_path::{AbsoluteSystemPath, PathRelation}; -pub use absolute_system_path_buf::AbsoluteSystemPathBuf; -pub use anchored_system_path::AnchoredSystemPath; -pub use anchored_system_path_buf::AnchoredSystemPathBuf; -use camino::{Utf8Path, Utf8PathBuf}; -use miette::Diagnostic; -pub use relative_unix_path::RelativeUnixPath; -pub use relative_unix_path_buf::{RelativeUnixPathBuf, RelativeUnixPathBufTestExt}; -use thiserror::Error; - -// Lets windows know that we're going to be reading this file sequentially -#[cfg(windows)] -pub const FILE_FLAG_SEQUENTIAL_SCAN: u32 = 0x08000000; - -#[derive(Debug, Error, Diagnostic)] -pub enum PathError { - #[error("Path is non-UTF-8: {0}")] - InvalidUnicode(String), - #[error("Failed to convert path")] - FromPathBufError(#[from] camino::FromPathBufError), - #[error("Failed to convert path")] - FromPathError(#[from] camino::FromPathError), - #[error("path is malformed: {0}")] - MalformedPath(String), - #[error("Path is not safe for windows: {0}")] - WindowsUnsafePath(String), - #[error("Path is not absolute: {0}")] - NotAbsolute(String), - #[error("Path is not relative: {0}")] - NotRelative(String), - #[error("Path {0} is not parent of {1}")] - NotParent(String, String), - #[error("IO Error {0}")] - IO(#[from] io::Error), - #[error("{0} is not a prefix for {1}")] - PrefixError(String, String), -} - -impl From for PathError { - fn from(value: std::string::FromUtf8Error) -> Self { - PathError::InvalidUnicode(value.utf8_error().to_string()) - } -} - -impl PathError { - pub fn is_io_error(&self, kind: io::ErrorKind) -> bool { - matches!(self, PathError::IO(err) if err.kind() == kind) - } -} - -pub trait IntoUnix { - fn into_unix(self) -> Utf8PathBuf; -} - -#[cfg(windows)] -fn convert_separator( - path: impl AsRef, - input_separator: char, - output_separator: char, -) -> Utf8PathBuf { - let path = path.as_ref(); - - Utf8PathBuf::from( - path.chars() - .map(|c| { - if c == input_separator { - output_separator - } else { - c - } - }) - .collect::(), - ) -} - -impl> IntoUnix for T { - /// NOTE: `into_unix` *only* converts Windows paths to Unix paths *on* a - /// Windows system. Do not pass a Windows path on a Unix system and - /// assume it'll be converted. - fn into_unix(self) -> Utf8PathBuf { - let output; - - #[cfg(windows)] - { - output = convert_separator(self, std::path::MAIN_SEPARATOR, '/') - } - - #[cfg(not(windows))] - { - output = Utf8PathBuf::from(self.as_ref()) - } - - output - } -} - -#[derive(Debug, PartialEq)] -struct PathValidation { - well_formed: bool, - windows_safe: bool, -} - -// Checks if path is well formed and safe for Windows. -pub(crate) fn check_path(name: &str) -> PathValidation { - if name.is_empty() { - return PathValidation { - well_formed: false, - windows_safe: false, - }; - } - - let mut well_formed = true; - let mut windows_safe = true; - - // Name is: - // - "." - // - ".." - if well_formed && (name == "." || name == "..") { - well_formed = false; - } - - // Name starts with: - // - `/` - // - `./` - // - `../` - if well_formed && (name.starts_with('/') || name.starts_with("./") || name.starts_with("../")) { - well_formed = false; - } - - // Name ends in: - // - `/.` - // - `/..` - if well_formed && (name.ends_with("/.") || name.ends_with("/..")) { - well_formed = false; - } - - // Name contains: - // - `//` - // - `/./` - // - `/../` - if well_formed && (name.contains("//") || name.contains("/./") || name.contains("/../")) { - well_formed = false; - } - - // Name contains: `\` - if name.contains('\\') { - windows_safe = false; - } - - PathValidation { - well_formed, - windows_safe, - } -} - -pub enum UnknownPathType { - Absolute(AbsoluteSystemPathBuf), - Anchored(AnchoredSystemPathBuf), -} - -/// Categorizes a path as either an `AbsoluteSystemPathBuf` or -/// an `AnchoredSystemPathBuf` depending on whether it -/// is absolute or relative. -pub fn categorize(path: &Utf8Path) -> UnknownPathType { - let path = Utf8PathBuf::try_from(path_clean::clean(path)) - .expect("path cleaning should preserve UTF-8"); - if path.is_absolute() { - UnknownPathType::Absolute(AbsoluteSystemPathBuf(path)) - } else { - UnknownPathType::Anchored(AnchoredSystemPathBuf(path)) - } -} - -#[cfg(test)] -mod tests { - use test_case::test_case; - - use crate::{check_path, IntoUnix, PathValidation}; - - #[test] - fn test_into_unix() { - #[cfg(unix)] - { - assert_eq!("foo/bar".into_unix(), "foo/bar"); - assert_eq!("/foo/bar".into_unix(), "/foo/bar"); - assert_eq!("foo\\bar".into_unix(), "foo\\bar"); - } - - #[cfg(windows)] - { - assert_eq!("foo/bar".into_unix(), "foo/bar"); - assert_eq!("\\foo\\bar".into_unix(), "/foo/bar"); - assert_eq!("foo\\bar".into_unix(), "foo/bar"); - } - } - - #[test_case("", PathValidation { well_formed: false, windows_safe: false } ; "1")] - #[test_case(".", PathValidation { well_formed: false, windows_safe: true } ; "2")] - #[test_case("..", PathValidation { well_formed: false, windows_safe: true } ; "3")] - #[test_case("/", PathValidation { well_formed: false, windows_safe: true } ; "4")] - #[test_case("./", PathValidation { well_formed: false, windows_safe: true } ; "5")] - #[test_case("../", PathValidation { well_formed: false, windows_safe: true } ; "6")] - #[test_case("/a", PathValidation { well_formed: false, windows_safe: true } ; "7")] - #[test_case("./a", PathValidation { well_formed: false, windows_safe: true } ; "8")] - #[test_case("../a", PathValidation { well_formed: false, windows_safe: true } ; "9")] - #[test_case("/.", PathValidation { well_formed: false, windows_safe: true } ; "10")] - #[test_case("/..", PathValidation { well_formed: false, windows_safe: true } ; "11")] - #[test_case("a/.", PathValidation { well_formed: false, windows_safe: true } ; "12")] - #[test_case("a/..", PathValidation { well_formed: false, windows_safe: true } ; "13")] - #[test_case("//", PathValidation { well_formed: false, windows_safe: true } ; "14")] - #[test_case("/./", PathValidation { well_formed: false, windows_safe: true } ; "15")] - #[test_case("/../", PathValidation { well_formed: false, windows_safe: true } ; "16")] - #[test_case("a//", PathValidation { well_formed: false, windows_safe: true } ; "17")] - #[test_case("a/./", PathValidation { well_formed: false, windows_safe: true } ; "18")] - #[test_case("a/../", PathValidation { well_formed: false, windows_safe: true } ; "19")] - #[test_case("//a", PathValidation { well_formed: false, windows_safe: true } ; "20")] - #[test_case("/./a", PathValidation { well_formed: false, windows_safe: true } ; "21")] - #[test_case("/../a", PathValidation { well_formed: false, windows_safe: true } ; "22")] - #[test_case("a//a", PathValidation { well_formed: false, windows_safe: true } ; "23")] - #[test_case("a/./a", PathValidation { well_formed: false, windows_safe: true } ; "24")] - #[test_case("a/../a", PathValidation { well_formed: false, windows_safe: true } ; "25")] - #[test_case("...", PathValidation { well_formed: true, windows_safe: true } ; "26")] - #[test_case(".../a", PathValidation { well_formed: true, windows_safe: true } ; "27")] - #[test_case("a/...", PathValidation { well_formed: true, windows_safe: true } ; "28")] - #[test_case("a/.../a", PathValidation { well_formed: true, windows_safe: true } ; "29")] - #[test_case(".../...", PathValidation { well_formed: true, windows_safe: true } ; "30")] - fn test_check_path(path: &'static str, expected_output: PathValidation) { - let output = check_path(path); - assert_eq!(output, expected_output); - } -} diff --git a/crates/turborepo-paths/src/relative_unix_path.rs b/crates/turborepo-paths/src/relative_unix_path.rs deleted file mode 100644 index abf2a29b35bee..0000000000000 --- a/crates/turborepo-paths/src/relative_unix_path.rs +++ /dev/null @@ -1,124 +0,0 @@ -use std::{ - fmt, - fmt::{Display, Formatter}, -}; - -use camino::{Utf8Path, Utf8PathBuf}; - -use crate::{AnchoredSystemPathBuf, PathError, RelativeUnixPathBuf}; - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct RelativeUnixPath(str); - -impl Display for RelativeUnixPath { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", &self.0) - } -} - -impl RelativeUnixPath { - pub fn new + ?Sized>(value: &P) -> Result<&Self, PathError> { - let path = value.as_ref(); - if path.starts_with('/') { - return Err(PathError::NotRelative(path.to_string())); - } - // copied from stdlib path.rs: relies on the representation of - // RelativeUnixPath being just a str, the same way Path relies on - // just being an OsStr - Ok(unsafe { &*(path as *const str as *const Self) }) - } - - pub(crate) fn to_system_path_buf(&self) -> Utf8PathBuf { - #[cfg(unix)] - { - // On unix, unix paths are already system paths. Copy the string - // but skip validation. - Utf8PathBuf::from(&self.0) - } - - #[cfg(windows)] - { - let system_path_string = self.0.replace('/', "\\"); - Utf8PathBuf::from(system_path_string) - } - } - - pub fn to_anchored_system_path_buf(&self) -> AnchoredSystemPathBuf { - AnchoredSystemPathBuf(self.to_system_path_buf()) - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - pub fn as_str(&self) -> &str { - &self.0 - } - - pub fn to_owned(&self) -> RelativeUnixPathBuf { - RelativeUnixPathBuf(self.0.to_owned()) - } - - pub fn strip_prefix( - &self, - prefix: impl AsRef, - ) -> Result<&RelativeUnixPath, PathError> { - let stripped_path = self - .0 - .strip_prefix(&prefix.as_ref().0) - .ok_or_else(|| PathError::NotParent(prefix.as_ref().to_string(), self.to_string()))?; - - // Remove leading '/' if present - let stripped_path = stripped_path.strip_prefix('/').unwrap_or(stripped_path); - - Ok(unsafe { &*(stripped_path as *const str as *const Self) }) - } - - // NOTE: This only applies to full path components. If you - // want to check a file extension, use `RelativeUnixPathBuf::extension`. - pub fn ends_with(&self, suffix: impl AsRef) -> bool { - self.0.ends_with(suffix.as_ref()) - } - - pub fn extension(&self) -> Option<&str> { - Utf8Path::new(&self.0).extension() - } - - pub fn join_component(&self, segment: &str) -> RelativeUnixPathBuf { - debug_assert!(!segment.contains('/')); - RelativeUnixPathBuf(format!("{}/{}", &self.0, segment)) - } -} - -impl AsRef for RelativeUnixPath { - fn as_ref(&self) -> &RelativeUnixPath { - self - } -} - -impl<'a> From<&'a RelativeUnixPath> for wax::CandidatePath<'a> { - fn from(path: &'a RelativeUnixPath) -> Self { - path.0.into() - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::AnchoredSystemPath; - - #[test] - fn test_to_anchored_system_path_buf() { - let path = RelativeUnixPath::new("foo/bar/baz").unwrap(); - let expected = AnchoredSystemPath::new(if cfg!(windows) { - // Unix path separators should be converted - "foo\\bar\\baz" - } else { - // Unix paths already have correct separators - "foo/bar/baz" - }) - .unwrap(); - assert_eq!(&*path.to_anchored_system_path_buf(), expected); - } -} diff --git a/crates/turborepo-paths/src/relative_unix_path_buf.rs b/crates/turborepo-paths/src/relative_unix_path_buf.rs deleted file mode 100644 index 51657bf5e77ce..0000000000000 --- a/crates/turborepo-paths/src/relative_unix_path_buf.rs +++ /dev/null @@ -1,241 +0,0 @@ -use std::{ - borrow::Borrow, - fmt, - fmt::{Display, Formatter}, - ops::Deref, -}; - -use camino::Utf8Path; -use serde::{Deserialize, Serialize}; - -use crate::{PathError, RelativeUnixPath}; -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)] -// This is necessary to perform validation on the string during deserialization -#[serde(try_from = "String", into = "String")] -pub struct RelativeUnixPathBuf(pub(crate) String); - -#[cfg(feature = "biome")] -mod biome { - use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic}; - use turborepo_unescape::UnescapedString; - - use crate::RelativeUnixPathBuf; - - impl Deserializable for RelativeUnixPathBuf { - fn deserialize( - value: &impl DeserializableValue, - name: &str, - diagnostics: &mut Vec, - ) -> Option { - let path: String = UnescapedString::deserialize(value, name, diagnostics)?.into(); - match Self::new(path) { - Ok(path) => Some(path), - Err(e) => { - diagnostics.push( - DeserializationDiagnostic::new(e.to_string()).with_range(value.range()), - ); - None - } - } - } - } -} - -impl Display for RelativeUnixPathBuf { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - Display::fmt(&self.0, f) - } -} - -impl RelativeUnixPathBuf { - pub fn new(path: impl Into) -> Result { - let path_string = path.into(); - if path_string.starts_with('/') || Utf8Path::new(&path_string).is_absolute() { - return Err(PathError::NotRelative(path_string)); - } - - Ok(Self(path_string)) - } - - pub fn into_inner(self) -> String { - self.0 - } - - pub fn make_canonical_for_tar(&mut self, is_dir: bool) { - if is_dir && !self.0.ends_with('/') { - self.0.push('/'); - } - } - - pub fn strip_prefix(&self, prefix: &RelativeUnixPathBuf) -> Result { - let prefix_len = prefix.0.len(); - if prefix_len == 0 { - return Ok(self.clone()); - } - if !self.0.starts_with(&prefix.0) { - return Err(PathError::NotParent( - prefix.0.to_string(), - self.0.to_string(), - )); - } - - // Handle the case where we are stripping the entire contents of this path - if self.0.len() == prefix.0.len() { - return Self::new(""); - } - - // We now know that this path starts with the prefix, and that this path's - // length is greater than the prefix's length - if self.0.as_bytes()[prefix_len] != b'/' { - let prefix_str = prefix.0.clone(); - let this = self.0.clone(); - return Err(PathError::PrefixError(prefix_str, this)); - } - - let tail_slice = &self.0[(prefix_len + 1)..]; - Self::new(tail_slice) - } -} - -pub trait RelativeUnixPathBufTestExt { - fn join(&self, tail: &RelativeUnixPathBuf) -> Self; -} - -impl RelativeUnixPathBufTestExt for RelativeUnixPathBuf { - // Marked as test-only because it doesn't automatically clean the resulting - // path. *If* we end up needing or wanting this method outside of tests, we - // will need to implement .clean() for the result. - fn join(&self, tail: &RelativeUnixPathBuf) -> Self { - if self.0.is_empty() { - return tail.clone(); - } - let mut joined = self.0.clone(); - joined.push('/'); - joined.push_str(&tail.0); - Self(joined) - } -} - -impl Borrow for RelativeUnixPathBuf { - fn borrow(&self) -> &RelativeUnixPath { - let inner: &str = self.0.borrow(); - unsafe { &*(inner as *const str as *const RelativeUnixPath) } - } -} - -impl AsRef for RelativeUnixPathBuf { - fn as_ref(&self) -> &RelativeUnixPath { - self.borrow() - } -} - -impl Deref for RelativeUnixPathBuf { - type Target = RelativeUnixPath; - - fn deref(&self) -> &Self::Target { - self.borrow() - } -} - -impl TryFrom for RelativeUnixPathBuf { - type Error = PathError; - - fn try_from(value: String) -> Result { - Self::new(value) - } -} - -// From should not be implemented for RelativeUnixPathBuf as validation -// may fail -#[allow(clippy::from_over_into)] -impl Into for RelativeUnixPathBuf { - fn into(self) -> String { - self.0 - } -} - -#[cfg(test)] -mod tests { - use serde_json::json; - - use super::*; - - #[test] - fn test_relative_unix_path_buf() { - let path = RelativeUnixPathBuf::new("foo/bar").unwrap(); - assert_eq!(path.as_str(), "foo/bar"); - } - - #[test] - fn test_relative_unix_path_buf_with_extension() { - let path = RelativeUnixPathBuf::new("foo/bar.txt").unwrap(); - assert_eq!(path.as_str(), "foo/bar.txt"); - } - - #[test] - fn test_join() { - let head = RelativeUnixPathBuf::new("some/path").unwrap(); - let tail = RelativeUnixPathBuf::new("child/leaf").unwrap(); - let combined = head.join(&tail); - assert_eq!(combined.as_str(), "some/path/child/leaf"); - } - - #[test] - fn test_strip_prefix() { - let combined = RelativeUnixPathBuf::new("some/path/child/leaf").unwrap(); - let head = RelativeUnixPathBuf::new("some/path").unwrap(); - let expected = RelativeUnixPathBuf::new("child/leaf").unwrap(); - let tail = combined.strip_prefix(&head).unwrap(); - assert_eq!(tail, expected); - } - - #[test] - fn test_strip_entire_contents() { - let combined = RelativeUnixPathBuf::new("some/path").unwrap(); - let head = combined.clone(); - let expected = RelativeUnixPathBuf::new("").unwrap(); - let tail = combined.strip_prefix(&head).unwrap(); - assert_eq!(tail, expected); - } - - #[test] - fn test_strip_empty_prefix() { - let combined = RelativeUnixPathBuf::new("some/path").unwrap(); - let tail = combined - .strip_prefix(&RelativeUnixPathBuf::new("").unwrap()) - .unwrap(); - assert_eq!(tail, combined); - } - - #[test] - fn test_relative_unix_path_buf_errors() { - assert!(RelativeUnixPathBuf::new("/foo/bar").is_err()); - // Note: this shouldn't be an error, this is a valid relative unix path - // #[cfg(windows)] - // assert!(RelativeUnixPathBuf::new(PathBuf::from("C:\\foo\\bar")). - // is_err()); - } - - #[derive(Debug, Serialize, Deserialize)] - struct TestSchema { - field: RelativeUnixPathBuf, - } - - #[test] - fn test_roundtrip() { - let path = "relative/unix/path\\evil"; - let value = json!({ "field": path }); - let foo: TestSchema = serde_json::from_value(value.clone()).unwrap(); - assert_eq!(foo.field.deref(), RelativeUnixPath::new(path).unwrap()); - assert_eq!(serde_json::to_value(foo).unwrap(), value); - } - - #[test] - fn test_deserialization_fails_on_absolute() { - let foo: Result = serde_json::from_value(json!({"field": "/absolute/path"})); - let Err(e) = foo else { - panic!("expected absolute path deserialization to fail") - }; - assert_eq!(e.to_string(), "Path is not relative: /absolute/path"); - } -} diff --git a/crates/turborepo-pidlock/Cargo.toml b/crates/turborepo-pidlock/Cargo.toml index 97caca1399bbd..9dd43ba81a422 100644 --- a/crates/turborepo-pidlock/Cargo.toml +++ b/crates/turborepo-pidlock/Cargo.toml @@ -1,14 +1,27 @@ +[dependencies] +libc = "0.2.40" +log = "0.4.1" +thiserror = { workspace = true } + +[dev-dependencies] +rand = "0.8.2" +tempfile = { workspace = true } + +[features] +default = ["strict"] +strict = [] # Warnings are errors + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + [package] -name = "pidlock" -version = "0.1.4" authors = ["Paul Hummer "] -license = "MIT" -edition = "2021" -description = "A library for using pidfiles as resource locks" -repository = "https://github.com/rockstar/pidlock" -keywords = ["pidfile", "file", "filelock", "server", "lock"] categories = ["filesystem"] -readme = "README.md" +description = "A library for using pidfiles as resource locks" +edition = "2021" include = [ "src/*.rs", "Cargo.toml", @@ -16,25 +29,19 @@ include = [ "LICENSE-MIT", "LICENSE-APACHE", ] +keywords = ["pidfile", "file", "filelock", "server", "lock"] +license-file = "LICENSE" +name = "pidlock" +readme = "README.md" +repository = "https://github.com/rockstar/pidlock" +version = "0.1.4" -[features] -default = ["strict"] -strict = [] # Warnings are errors - -[lints] -workspace = true +[target] -[dependencies] -libc = "0.2.40" -log = "0.4.1" -thiserror = { workspace = true } +[target."cfg(windows)"] -[target.'cfg(windows)'.dependencies] +[target."cfg(windows)".dependencies] windows-sys = { version = "0.45.0", features = [ "Win32_System_Threading", "Win32_Foundation", ] } - -[dev-dependencies] -rand = "0.8.2" -tempfile = { workspace = true } diff --git a/crates/turborepo-pidlock/README.md b/crates/turborepo-pidlock/README.md deleted file mode 100644 index e12e99eba1607..0000000000000 --- a/crates/turborepo-pidlock/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# pidlock - -This is a vendored copy of https://github.com/rockstar/pidlock with some changes that are waiting to be upstreamed. - -A library for working with pidfiles, with a lock-like API. - -## Usage - -``` -extern crate pidlock; - -fn main() { - let mut lock = pidlock::Pidlock::new("/path/to/pidfile.pid".into()); - lock.acquire().unwrap(); - - ... - - lock.release().unwrap(); -} -``` - -## License - -pidlock is licensed under the MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) diff --git a/crates/turborepo-pidlock/Source/lib.rs b/crates/turborepo-pidlock/Source/lib.rs new file mode 100644 index 0000000000000..e8e3e96a334e6 --- /dev/null +++ b/crates/turborepo-pidlock/Source/lib.rs @@ -0,0 +1,390 @@ +#![deny(clippy::all)] +#![feature(assert_matches)] + +use std::{ + fs, + io::{self, Read, Write}, + num::TryFromIntError, + path::PathBuf, + process, +}; + +use log::warn; +use thiserror::Error; + +/// Errors that may occur during the `Pidlock` lifetime. +#[derive(Debug, Error)] +pub enum PidlockError { + /// A lock already exists + #[error("lock exists at \"{0}\", please remove it")] + LockExists(PathBuf), + /// An operation was attempted in the wrong state, e.g. releasing before + /// acquiring. + #[error("invalid state")] + InvalidState, + /// The lock is already owned by a running process + #[error("already owned")] + AlreadyOwned, + #[error("pid file error: {0}")] + File(#[from] PidFileError), +} + +/// Errors that can occur when dealing with the file +/// on disk. +#[derive(Debug, Error)] +pub enum PidFileError { + #[error("Error reading pid file {1}: {0}")] + IO(io::Error, String), + #[error("Invalid pid {contents} in file {file}: {error}")] + Invalid { error:String, contents:String, file:String }, + #[error("Failed to remove stale pid file {1}: {0}")] + FailedDelete(io::Error, String), +} + +/// A result from a Pidlock operation +type PidlockResult = Result<(), PidlockError>; + +/// States a Pidlock can be in during its lifetime. +#[derive(Debug, PartialEq)] +enum PidlockState { + /// A new pidlock, unacquired + New, + /// A lock is acquired + Acquired, + /// A lock is released + Released, +} + +/// Check whether a process exists, used to determine whether a pid file is +/// stale. +/// +/// # Safety +/// +/// This function uses unsafe methods to determine process existence. The +/// function itself is private, and the input is validated prior to call. +fn process_exists(pid:i32) -> bool { + #[cfg(target_os = "windows")] + unsafe { + // If GetExitCodeProcess returns STILL_ACTIVE, then the process + // doesn't have an exit code (...or exited with code 259) + use windows_sys::Win32::{ + Foundation::{CloseHandle, STILL_ACTIVE}, + System::Threading::{GetExitCodeProcess, OpenProcess, PROCESS_QUERY_INFORMATION}, + }; + let handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid as u32); + let mut code = 0; + GetExitCodeProcess(handle, &mut code); + CloseHandle(handle); + code == STILL_ACTIVE as u32 + } + + #[cfg(not(target_os = "windows"))] + unsafe { + // From the POSIX standard: If sig is 0 (the null signal), error checking + // is performed but no signal is actually sent. The null signal can be + // used to check the validity of pid. + let result = libc::kill(pid, 0); + result == 0 + } +} + +/// A pid-centered lock. A lock is considered "acquired" when a file exists on +/// disk at the path specified, containing the process id of the locking +/// process. +pub struct Pidlock { + /// The current process id + pid:u32, + /// A path to the lock file + path:PathBuf, + /// Current state of the Pidlock + state:PidlockState, +} + +impl Pidlock { + /// Create a new Pidlock at the provided path. + pub fn new(path:PathBuf) -> Self { + Pidlock { pid:process::id(), path, state:PidlockState::New } + } + + /// Acquire a lock. + pub fn acquire(&mut self) -> PidlockResult { + match self.state { + PidlockState::New => {}, + _ => { + return Err(PidlockError::InvalidState); + }, + } + + // acquiring something with a valid owner is an error + if self.get_owner()?.is_some() { + return Err(PidlockError::AlreadyOwned); + } + + if let Some(p) = self.path.parent() { + // even if this fails, the next call might not + std::fs::create_dir_all(p).ok(); + } + + let mut file = + match fs::OpenOptions::new().create_new(true).write(true).open(self.path.clone()) { + Ok(file) => file, + Err(_) => { + return Err(PidlockError::LockExists(self.path.clone())); + }, + }; + file.write_all(&format!("{}", self.pid).into_bytes()[..]).unwrap(); + + self.state = PidlockState::Acquired; + Ok(()) + } + + /// Returns true when the lock is in an acquired state. + pub fn locked(&self) -> bool { self.state == PidlockState::Acquired } + + /// Release the lock. + fn release(&mut self) -> PidlockResult { + match self.state { + PidlockState::Acquired => {}, + _ => { + return Err(PidlockError::InvalidState); + }, + } + + fs::remove_file(self.path.clone()).unwrap(); + + self.state = PidlockState::Released; + Ok(()) + } + + /// Gets the owner of this lockfile, returning the pid. If the lock file + /// doesn't exist, or the specified pid is not a valid process id on the + /// system, it clears it. + pub fn get_owner(&self) -> Result, PidFileError> { + let mut file = match fs::OpenOptions::new().read(true).open(self.path.clone()) { + Ok(file) => file, + Err(io_err) => { + // If the file doesn't exist, there's no owner. If, on the + // other hand, some other IO error occurred, we don't know + // the situation and need to return an error + if io_err.kind() == io::ErrorKind::NotFound { + return Ok(None); + } else { + return Err(PidFileError::IO(io_err, self.path.display().to_string())); + } + }, + }; + + let mut contents = String::new(); + if let Err(io_err) = file.read_to_string(&mut contents) { + warn!("corrupted/invalid pid file at {:?}: {}", self.path, io_err); + // Return an error, because None implies that we would succeed at + // creating a pid file, but we won't. We require the file to not + // exist if we're going to create it. + // TODO: should we instead try deleting the file like with stale pids? + return Err(PidFileError::IO(io_err, self.path.display().to_string())); + } + + match contents.trim().parse::() { + Ok(pid) if process_exists(pid) => { + let pid:u32 = pid.try_into().map_err(|e:TryFromIntError| { + PidFileError::Invalid { + error:e.to_string(), + contents, + file:self.path.display().to_string(), + } + })?; + Ok(Some(pid)) + }, + Ok(_) => { + warn!("stale pid file at {:?}", self.path); + if let Err(e) = fs::remove_file(&self.path) { + Err(PidFileError::FailedDelete(e, self.path.display().to_string())) + } else { + Ok(None) + } + }, + Err(e) => { + Err(PidFileError::Invalid { + error:e.to_string(), + contents, + file:self.path.display().to_string(), + }) + }, + } + } +} + +impl Drop for Pidlock { + fn drop(&mut self) { + if self.locked() { + self.release().ok(); + } + } +} + +#[cfg(test)] +mod tests { + use std::{assert_matches::assert_matches, fs, io::Write, path::PathBuf}; + + use rand::{Rng, distributions::Alphanumeric, thread_rng}; + + use super::{PidFileError, Pidlock, PidlockError, PidlockState}; + + // This was removed from the library itself, but retained here + // to assert backwards compatibility with std::process::id + fn getpid() -> u32 { unsafe { libc::getpid() as u32 } } + + fn make_pid_path() -> (tempfile::TempDir, PathBuf) { + let tmp = tempfile::TempDir::with_prefix("pidlock").unwrap(); + let path = tmp.path().join("pidfile"); + (tmp, path) + } + + #[test] + fn test_new() { + let (_tmp, pid_path) = make_pid_path(); + let pidfile = Pidlock::new(pid_path.clone()); + + assert_eq!(pidfile.pid, getpid()); + assert_eq!(pidfile.path, pid_path); + assert_eq!(pidfile.state, PidlockState::New); + } + + #[test] + fn test_acquire_and_release() { + let (_tmp, pid_path) = make_pid_path(); + let mut pidfile = Pidlock::new(pid_path); + pidfile.acquire().unwrap(); + + assert_eq!(pidfile.state, PidlockState::Acquired); + + pidfile.release().unwrap(); + + assert_eq!(pidfile.state, PidlockState::Released); + } + + #[test] + fn test_acquire_lock_exists() { + let (_tmp, pid_path) = make_pid_path(); + let mut orig_pidfile = Pidlock::new(pid_path); + orig_pidfile.acquire().unwrap(); + + let mut pidfile = Pidlock::new(orig_pidfile.path.clone()); + match pidfile.acquire() { + Err(err) => { + orig_pidfile.release().unwrap(); + assert_matches!(err, PidlockError::AlreadyOwned); + }, + _ => { + orig_pidfile.release().unwrap(); + panic!("Test failed"); + }, + } + } + + #[test] + fn test_acquire_already_acquired() { + let (_tmp, pid_path) = make_pid_path(); + let mut pidfile = Pidlock::new(pid_path); + pidfile.acquire().unwrap(); + match pidfile.acquire() { + Err(err) => { + pidfile.release().unwrap(); + assert_matches!(err, PidlockError::InvalidState); + }, + _ => { + pidfile.release().unwrap(); + panic!("Test failed"); + }, + } + } + + #[test] + fn test_release_bad_state() { + let (_tmp, pid_path) = make_pid_path(); + let mut pidfile = Pidlock::new(pid_path); + match pidfile.release() { + Err(err) => { + assert_matches!(err, PidlockError::InvalidState); + }, + _ => { + panic!("Test failed"); + }, + } + } + + #[test] + fn test_locked() { + let (_tmp, pid_path) = make_pid_path(); + let mut pidfile = Pidlock::new(pid_path); + pidfile.acquire().unwrap(); + assert!(pidfile.locked()); + } + + #[test] + fn test_locked_not_locked() { + let (_tmp, pid_path) = make_pid_path(); + let pidfile = Pidlock::new(pid_path); + assert!(!pidfile.locked()); + } + + #[test] + fn test_stale_pid() { + let (_tmp, path) = make_pid_path(); + let mut file = fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(path.clone()) + .expect("Could not open file for writing"); + + file.write_all(&format!("{}", thread_rng().gen::()).into_bytes()[..]) + .unwrap(); + + drop(file); + + // expect a stale pid file to be cleaned up + let mut pidfile = Pidlock::new(path.clone()); + // We clear stale pid files when acquiring them, we expect this to succeed + assert!(pidfile.acquire().is_ok()); + } + + #[test] + fn test_stale_pid_invalid_contents() { + let (_tmp, path) = make_pid_path(); + let contents:String = + thread_rng().sample_iter(&Alphanumeric).take(20).map(char::from).collect(); + let mut file = fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(path.clone()) + .expect("Could not open file for writing"); + + file.write_all(&contents.into_bytes()).unwrap(); + + drop(file); + + let mut pidfile = Pidlock::new(path.clone()); + // Contents are invalid + assert_matches!(pidfile.acquire(), Err(PidlockError::File(PidFileError::Invalid { .. }))); + } + + #[test] + fn test_stale_pid_corrupted_contents() { + let (_tmp, path) = make_pid_path(); + let mut file = fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(path.clone()) + .expect("Could not open file for writing"); + + let invalid_utf8 = vec![0xFF, 0xFF, 0xFF, 0xFF]; + file.write_all(&invalid_utf8).unwrap(); + + drop(file); + + let mut pidfile = Pidlock::new(path.clone()); + // We expect an IO error from trying to read as a utf8 string when it's just + // bytes + assert_matches!(pidfile.acquire(), Err(PidlockError::File(PidFileError::IO(..)))); + } +} diff --git a/crates/turborepo-pidlock/src/lib.rs b/crates/turborepo-pidlock/src/lib.rs deleted file mode 100644 index c57c86cd0a041..0000000000000 --- a/crates/turborepo-pidlock/src/lib.rs +++ /dev/null @@ -1,416 +0,0 @@ -#![deny(clippy::all)] -#![feature(assert_matches)] - -use std::{ - fs, - io::{self, Read, Write}, - num::TryFromIntError, - path::PathBuf, - process, -}; - -use log::warn; -use thiserror::Error; - -/// Errors that may occur during the `Pidlock` lifetime. -#[derive(Debug, Error)] -pub enum PidlockError { - /// A lock already exists - #[error("lock exists at \"{0}\", please remove it")] - LockExists(PathBuf), - /// An operation was attempted in the wrong state, e.g. releasing before - /// acquiring. - #[error("invalid state")] - InvalidState, - /// The lock is already owned by a running process - #[error("already owned")] - AlreadyOwned, - #[error("pid file error: {0}")] - File(#[from] PidFileError), -} - -/// Errors that can occur when dealing with the file -/// on disk. -#[derive(Debug, Error)] -pub enum PidFileError { - #[error("Error reading pid file {1}: {0}")] - IO(io::Error, String), - #[error("Invalid pid {contents} in file {file}: {error}")] - Invalid { - error: String, - contents: String, - file: String, - }, - #[error("Failed to remove stale pid file {1}: {0}")] - FailedDelete(io::Error, String), -} - -/// A result from a Pidlock operation -type PidlockResult = Result<(), PidlockError>; - -/// States a Pidlock can be in during its lifetime. -#[derive(Debug, PartialEq)] -enum PidlockState { - /// A new pidlock, unacquired - New, - /// A lock is acquired - Acquired, - /// A lock is released - Released, -} - -/// Check whether a process exists, used to determine whether a pid file is -/// stale. -/// -/// # Safety -/// -/// This function uses unsafe methods to determine process existence. The -/// function itself is private, and the input is validated prior to call. -fn process_exists(pid: i32) -> bool { - #[cfg(target_os = "windows")] - unsafe { - // If GetExitCodeProcess returns STILL_ACTIVE, then the process - // doesn't have an exit code (...or exited with code 259) - use windows_sys::Win32::{ - Foundation::{CloseHandle, STILL_ACTIVE}, - System::Threading::{GetExitCodeProcess, OpenProcess, PROCESS_QUERY_INFORMATION}, - }; - let handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid as u32); - let mut code = 0; - GetExitCodeProcess(handle, &mut code); - CloseHandle(handle); - code == STILL_ACTIVE as u32 - } - - #[cfg(not(target_os = "windows"))] - unsafe { - // From the POSIX standard: If sig is 0 (the null signal), error checking - // is performed but no signal is actually sent. The null signal can be - // used to check the validity of pid. - let result = libc::kill(pid, 0); - result == 0 - } -} - -/// A pid-centered lock. A lock is considered "acquired" when a file exists on -/// disk at the path specified, containing the process id of the locking -/// process. -pub struct Pidlock { - /// The current process id - pid: u32, - /// A path to the lock file - path: PathBuf, - /// Current state of the Pidlock - state: PidlockState, -} - -impl Pidlock { - /// Create a new Pidlock at the provided path. - pub fn new(path: PathBuf) -> Self { - Pidlock { - pid: process::id(), - path, - state: PidlockState::New, - } - } - - /// Acquire a lock. - pub fn acquire(&mut self) -> PidlockResult { - match self.state { - PidlockState::New => {} - _ => { - return Err(PidlockError::InvalidState); - } - } - - // acquiring something with a valid owner is an error - if self.get_owner()?.is_some() { - return Err(PidlockError::AlreadyOwned); - } - - if let Some(p) = self.path.parent() { - // even if this fails, the next call might not - std::fs::create_dir_all(p).ok(); - } - - let mut file = match fs::OpenOptions::new() - .create_new(true) - .write(true) - .open(self.path.clone()) - { - Ok(file) => file, - Err(_) => { - return Err(PidlockError::LockExists(self.path.clone())); - } - }; - file.write_all(&format!("{}", self.pid).into_bytes()[..]) - .unwrap(); - - self.state = PidlockState::Acquired; - Ok(()) - } - - /// Returns true when the lock is in an acquired state. - pub fn locked(&self) -> bool { - self.state == PidlockState::Acquired - } - - /// Release the lock. - fn release(&mut self) -> PidlockResult { - match self.state { - PidlockState::Acquired => {} - _ => { - return Err(PidlockError::InvalidState); - } - } - - fs::remove_file(self.path.clone()).unwrap(); - - self.state = PidlockState::Released; - Ok(()) - } - - /// Gets the owner of this lockfile, returning the pid. If the lock file - /// doesn't exist, or the specified pid is not a valid process id on the - /// system, it clears it. - pub fn get_owner(&self) -> Result, PidFileError> { - let mut file = match fs::OpenOptions::new().read(true).open(self.path.clone()) { - Ok(file) => file, - Err(io_err) => { - // If the file doesn't exist, there's no owner. If, on the - // other hand, some other IO error occurred, we don't know - // the situation and need to return an error - if io_err.kind() == io::ErrorKind::NotFound { - return Ok(None); - } else { - return Err(PidFileError::IO(io_err, self.path.display().to_string())); - } - } - }; - - let mut contents = String::new(); - if let Err(io_err) = file.read_to_string(&mut contents) { - warn!("corrupted/invalid pid file at {:?}: {}", self.path, io_err); - // Return an error, because None implies that we would succeed at - // creating a pid file, but we won't. We require the file to not - // exist if we're going to create it. - // TODO: should we instead try deleting the file like with stale pids? - return Err(PidFileError::IO(io_err, self.path.display().to_string())); - } - - match contents.trim().parse::() { - Ok(pid) if process_exists(pid) => { - let pid: u32 = - pid.try_into() - .map_err(|e: TryFromIntError| PidFileError::Invalid { - error: e.to_string(), - contents, - file: self.path.display().to_string(), - })?; - Ok(Some(pid)) - } - Ok(_) => { - warn!("stale pid file at {:?}", self.path); - if let Err(e) = fs::remove_file(&self.path) { - Err(PidFileError::FailedDelete( - e, - self.path.display().to_string(), - )) - } else { - Ok(None) - } - } - Err(e) => Err(PidFileError::Invalid { - error: e.to_string(), - contents, - file: self.path.display().to_string(), - }), - } - } -} - -impl Drop for Pidlock { - fn drop(&mut self) { - if self.locked() { - self.release().ok(); - } - } -} - -#[cfg(test)] -mod tests { - use std::{assert_matches::assert_matches, fs, io::Write, path::PathBuf}; - - use rand::{distributions::Alphanumeric, thread_rng, Rng}; - - use super::{PidFileError, Pidlock, PidlockError, PidlockState}; - - // This was removed from the library itself, but retained here - // to assert backwards compatibility with std::process::id - fn getpid() -> u32 { - unsafe { libc::getpid() as u32 } - } - - fn make_pid_path() -> (tempfile::TempDir, PathBuf) { - let tmp = tempfile::TempDir::with_prefix("pidlock").unwrap(); - let path = tmp.path().join("pidfile"); - (tmp, path) - } - - #[test] - fn test_new() { - let (_tmp, pid_path) = make_pid_path(); - let pidfile = Pidlock::new(pid_path.clone()); - - assert_eq!(pidfile.pid, getpid()); - assert_eq!(pidfile.path, pid_path); - assert_eq!(pidfile.state, PidlockState::New); - } - - #[test] - fn test_acquire_and_release() { - let (_tmp, pid_path) = make_pid_path(); - let mut pidfile = Pidlock::new(pid_path); - pidfile.acquire().unwrap(); - - assert_eq!(pidfile.state, PidlockState::Acquired); - - pidfile.release().unwrap(); - - assert_eq!(pidfile.state, PidlockState::Released); - } - - #[test] - fn test_acquire_lock_exists() { - let (_tmp, pid_path) = make_pid_path(); - let mut orig_pidfile = Pidlock::new(pid_path); - orig_pidfile.acquire().unwrap(); - - let mut pidfile = Pidlock::new(orig_pidfile.path.clone()); - match pidfile.acquire() { - Err(err) => { - orig_pidfile.release().unwrap(); - assert_matches!(err, PidlockError::AlreadyOwned); - } - _ => { - orig_pidfile.release().unwrap(); - panic!("Test failed"); - } - } - } - - #[test] - fn test_acquire_already_acquired() { - let (_tmp, pid_path) = make_pid_path(); - let mut pidfile = Pidlock::new(pid_path); - pidfile.acquire().unwrap(); - match pidfile.acquire() { - Err(err) => { - pidfile.release().unwrap(); - assert_matches!(err, PidlockError::InvalidState); - } - _ => { - pidfile.release().unwrap(); - panic!("Test failed"); - } - } - } - - #[test] - fn test_release_bad_state() { - let (_tmp, pid_path) = make_pid_path(); - let mut pidfile = Pidlock::new(pid_path); - match pidfile.release() { - Err(err) => { - assert_matches!(err, PidlockError::InvalidState); - } - _ => { - panic!("Test failed"); - } - } - } - - #[test] - fn test_locked() { - let (_tmp, pid_path) = make_pid_path(); - let mut pidfile = Pidlock::new(pid_path); - pidfile.acquire().unwrap(); - assert!(pidfile.locked()); - } - - #[test] - fn test_locked_not_locked() { - let (_tmp, pid_path) = make_pid_path(); - let pidfile = Pidlock::new(pid_path); - assert!(!pidfile.locked()); - } - - #[test] - fn test_stale_pid() { - let (_tmp, path) = make_pid_path(); - let mut file = fs::OpenOptions::new() - .create_new(true) - .write(true) - .open(path.clone()) - .expect("Could not open file for writing"); - - file.write_all(&format!("{}", thread_rng().gen::()).into_bytes()[..]) - .unwrap(); - - drop(file); - - // expect a stale pid file to be cleaned up - let mut pidfile = Pidlock::new(path.clone()); - // We clear stale pid files when acquiring them, we expect this to succeed - assert!(pidfile.acquire().is_ok()); - } - - #[test] - fn test_stale_pid_invalid_contents() { - let (_tmp, path) = make_pid_path(); - let contents: String = thread_rng() - .sample_iter(&Alphanumeric) - .take(20) - .map(char::from) - .collect(); - let mut file = fs::OpenOptions::new() - .create_new(true) - .write(true) - .open(path.clone()) - .expect("Could not open file for writing"); - - file.write_all(&contents.into_bytes()).unwrap(); - - drop(file); - - let mut pidfile = Pidlock::new(path.clone()); - // Contents are invalid - assert_matches!( - pidfile.acquire(), - Err(PidlockError::File(PidFileError::Invalid { .. })) - ); - } - - #[test] - fn test_stale_pid_corrupted_contents() { - let (_tmp, path) = make_pid_path(); - let mut file = fs::OpenOptions::new() - .create_new(true) - .write(true) - .open(path.clone()) - .expect("Could not open file for writing"); - - let invalid_utf8 = vec![0xff, 0xff, 0xff, 0xff]; - file.write_all(&invalid_utf8).unwrap(); - - drop(file); - - let mut pidfile = Pidlock::new(path.clone()); - // We expect an IO error from trying to read as a utf8 string when it's just - // bytes - assert_matches!( - pidfile.acquire(), - Err(PidlockError::File(PidFileError::IO(..))) - ); - } -} diff --git a/crates/turborepo-repository/Cargo.toml b/crates/turborepo-repository/Cargo.toml index c2f128f3f27c8..26d3e3b74879c 100644 --- a/crates/turborepo-repository/Cargo.toml +++ b/crates/turborepo-repository/Cargo.toml @@ -1,27 +1,16 @@ -[package] -name = "turborepo-repository" -version = "0.1.0" -edition = "2021" -license = "MIT" - -[lints] -workspace = true - [dependencies] anyhow = { workspace = true } async-once-cell = "0.5.3" - biome_deserialize = { workspace = true } biome_deserialize_macros = { workspace = true } biome_diagnostics = { workspace = true } biome_json_parser = { workspace = true } biome_json_syntax = { workspace = true } - globwalk = { version = "0.1.0", path = "../turborepo-globwalk" } itertools = { workspace = true } lazy-regex = "2.5.0" miette = { workspace = true } -node-semver = "2.1.0" +node-semver = "2.2.0" petgraph = { workspace = true } regex = { workspace = true } rust-ini = "0.20.0" @@ -30,8 +19,6 @@ serde_json = { workspace = true } serde_yaml = { workspace = true } thiserror = "1.0.38" tokio-stream = "0.1.14" -tokio.workspace = true -tracing.workspace = true turbopath = { workspace = true, features = ["biome"] } turborepo-errors = { workspace = true } turborepo-graph-utils = { path = "../turborepo-graph-utils" } @@ -40,7 +27,25 @@ turborepo-unescape = { workspace = true } wax = { workspace = true } which = { workspace = true } +[dependencies.tokio] +workspace = true + +[dependencies.tracing] +workspace = true + [dev-dependencies] pretty_assertions = { workspace = true } tempfile = { workspace = true } test-case = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-repository" +version = "0.1.0" diff --git a/crates/turborepo-repository/src/change_mapper/mod.rs b/crates/turborepo-repository/Source/change_mapper/mod.rs similarity index 100% rename from crates/turborepo-repository/src/change_mapper/mod.rs rename to crates/turborepo-repository/Source/change_mapper/mod.rs diff --git a/crates/turborepo-repository/src/change_mapper/package.rs b/crates/turborepo-repository/Source/change_mapper/package.rs similarity index 100% rename from crates/turborepo-repository/src/change_mapper/package.rs rename to crates/turborepo-repository/Source/change_mapper/package.rs diff --git a/crates/turborepo-repository/src/discovery.rs b/crates/turborepo-repository/Source/discovery.rs similarity index 100% rename from crates/turborepo-repository/src/discovery.rs rename to crates/turborepo-repository/Source/discovery.rs diff --git a/crates/turborepo-repository/src/inference.rs b/crates/turborepo-repository/Source/inference.rs similarity index 100% rename from crates/turborepo-repository/src/inference.rs rename to crates/turborepo-repository/Source/inference.rs diff --git a/crates/turborepo-repository/src/lib.rs b/crates/turborepo-repository/Source/lib.rs similarity index 100% rename from crates/turborepo-repository/src/lib.rs rename to crates/turborepo-repository/Source/lib.rs diff --git a/crates/turborepo-repository/src/package_graph/builder.rs b/crates/turborepo-repository/Source/package_graph/builder.rs similarity index 100% rename from crates/turborepo-repository/src/package_graph/builder.rs rename to crates/turborepo-repository/Source/package_graph/builder.rs diff --git a/crates/turborepo-repository/src/package_graph/dep_splitter.rs b/crates/turborepo-repository/Source/package_graph/dep_splitter.rs similarity index 100% rename from crates/turborepo-repository/src/package_graph/dep_splitter.rs rename to crates/turborepo-repository/Source/package_graph/dep_splitter.rs diff --git a/crates/turborepo-repository/src/package_graph/mod.rs b/crates/turborepo-repository/Source/package_graph/mod.rs similarity index 100% rename from crates/turborepo-repository/src/package_graph/mod.rs rename to crates/turborepo-repository/Source/package_graph/mod.rs diff --git a/crates/turborepo-repository/Source/package_graph/npmrc.rs b/crates/turborepo-repository/Source/package_graph/npmrc.rs new file mode 100644 index 0000000000000..d55b84b122ed9 --- /dev/null +++ b/crates/turborepo-repository/Source/package_graph/npmrc.rs @@ -0,0 +1,68 @@ +use std::io; + +use ini::Ini; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("encountered error parsing .npmrc: {0}")] + Ini(#[from] ini::Error), +} + +/// Representation of .npmrc used by both npm and pnpm to configure behavior +/// The representation is intentionally incomplete and is only intended to +/// contain settings that affect the package graph. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct NpmRc { + /// Used by pnpm to determine whether dependencies + /// declared without an explicit workspace protocol + /// can target a workspace package. + pub link_workspace_packages:Option, +} + +impl NpmRc { + pub fn from_reader(mut reader:impl io::Read) -> Result { + let ini = Ini::read_from(&mut reader)?; + Ok(Self::from_ini(ini)) + } + + // Private to avoid leaking the underlying ini parsing library we use + fn from_ini(ini:Ini) -> Self { + let link_workspace_packages = ini + .get_from::<&str>(None, "link-workspace-packages") + .and_then(parse_link_workspace_packages); + + Self { link_workspace_packages } + } +} + +fn parse_link_workspace_packages(value:&str) -> Option { + match value { + // "deep" changes the underlying linking strategy used by pnpm, but it still results + // in workspace packages being used over npm packages + "true" | "deep" => Some(true), + "false" => Some(false), + _ => None, + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_parse_empty_npmrc() { + let empty = NpmRc::from_reader(b"".as_slice()).unwrap(); + assert_eq!(empty, NpmRc { link_workspace_packages:None }); + } + + #[test] + fn test_example_pnpm_npmrc() { + let contents = b"auto-install-peers=true + enable-pre-post-scripts=true + link-workspace-packages=false + " + .as_slice(); + let example = NpmRc::from_reader(contents).unwrap(); + assert_eq!(example, NpmRc { link_workspace_packages:Some(false) }); + } +} diff --git a/crates/turborepo-repository/src/package_json.rs b/crates/turborepo-repository/Source/package_json.rs similarity index 100% rename from crates/turborepo-repository/src/package_json.rs rename to crates/turborepo-repository/Source/package_json.rs diff --git a/crates/turborepo-repository/src/package_manager/bun.rs b/crates/turborepo-repository/Source/package_manager/bun.rs similarity index 100% rename from crates/turborepo-repository/src/package_manager/bun.rs rename to crates/turborepo-repository/Source/package_manager/bun.rs diff --git a/crates/turborepo-repository/src/package_manager/mod.rs b/crates/turborepo-repository/Source/package_manager/mod.rs similarity index 100% rename from crates/turborepo-repository/src/package_manager/mod.rs rename to crates/turborepo-repository/Source/package_manager/mod.rs diff --git a/crates/turborepo-repository/src/package_manager/npm.rs b/crates/turborepo-repository/Source/package_manager/npm.rs similarity index 100% rename from crates/turborepo-repository/src/package_manager/npm.rs rename to crates/turborepo-repository/Source/package_manager/npm.rs diff --git a/crates/turborepo-repository/src/package_manager/npmrc.rs b/crates/turborepo-repository/Source/package_manager/npmrc.rs similarity index 100% rename from crates/turborepo-repository/src/package_manager/npmrc.rs rename to crates/turborepo-repository/Source/package_manager/npmrc.rs diff --git a/crates/turborepo-repository/src/package_manager/pnpm.rs b/crates/turborepo-repository/Source/package_manager/pnpm.rs similarity index 100% rename from crates/turborepo-repository/src/package_manager/pnpm.rs rename to crates/turborepo-repository/Source/package_manager/pnpm.rs diff --git a/crates/turborepo-repository/src/package_manager/yarn.rs b/crates/turborepo-repository/Source/package_manager/yarn.rs similarity index 100% rename from crates/turborepo-repository/src/package_manager/yarn.rs rename to crates/turborepo-repository/Source/package_manager/yarn.rs diff --git a/crates/turborepo-repository/src/package_manager/yarnrc.rs b/crates/turborepo-repository/Source/package_manager/yarnrc.rs similarity index 100% rename from crates/turborepo-repository/src/package_manager/yarnrc.rs rename to crates/turborepo-repository/Source/package_manager/yarnrc.rs diff --git a/crates/turborepo-repository/src/workspaces.rs b/crates/turborepo-repository/Source/workspaces.rs similarity index 100% rename from crates/turborepo-repository/src/workspaces.rs rename to crates/turborepo-repository/Source/workspaces.rs diff --git a/crates/turborepo-repository/src/package_manager/fixtures/package.json b/crates/turborepo-repository/src/package_manager/fixtures/package.json deleted file mode 100644 index 6b27f7ce1b17a..0000000000000 --- a/crates/turborepo-repository/src/package_manager/fixtures/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "fixture", - "workspaces": [ - "apps/*", - "packages/*" - ] -} diff --git a/crates/turborepo-repository/src/package_manager/fixtures/pnpm-patches.json b/crates/turborepo-repository/src/package_manager/fixtures/pnpm-patches.json deleted file mode 100644 index f772bc35ce483..0000000000000 --- a/crates/turborepo-repository/src/package_manager/fixtures/pnpm-patches.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "turborepo-prune-removes-patched", - "version": "1.0.0", - "packageManager": "pnpm@7.15.0", - "workspaces": ["packages/*"], - "pnpm": { - "patchedDependencies": { - "is-odd@3.0.1": "patches/is-odd@3.0.1.patch" - } - } -} diff --git a/crates/turborepo-repository/src/package_manager/fixtures/pnpm-workspace.yaml b/crates/turborepo-repository/src/package_manager/fixtures/pnpm-workspace.yaml deleted file mode 100644 index 7fbb7701da342..0000000000000 --- a/crates/turborepo-repository/src/package_manager/fixtures/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -packages: - - "packages/*" - - "!packages/skip" diff --git a/crates/turborepo-scm/Cargo.toml b/crates/turborepo-scm/Cargo.toml index dd854ee236c58..7d6a5ac6409c0 100644 --- a/crates/turborepo-scm/Cargo.toml +++ b/crates/turborepo-scm/Cargo.toml @@ -1,14 +1,3 @@ -[package] -name = "turborepo-scm" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] bstr = "1.4.0" git2 = { workspace = true, default-features = false } @@ -30,3 +19,15 @@ which = { workspace = true } [dev-dependencies] tempfile = { workspace = true } test-case = "3.1.0" + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-scm" +version = "0.1.0" diff --git a/crates/turborepo-scm/README.md b/crates/turborepo-scm/README.md deleted file mode 100644 index 476e90b875cda..0000000000000 --- a/crates/turborepo-scm/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Turborepo SCM - -Utilities for working with source control, e.g. git. Uses [git2](https://docs.rs/git2/latest/git2/) bindings diff --git a/crates/turborepo-scm/Source/git.rs b/crates/turborepo-scm/Source/git.rs new file mode 100644 index 0000000000000..efba742351c51 --- /dev/null +++ b/crates/turborepo-scm/Source/git.rs @@ -0,0 +1,1252 @@ +use std::{ + backtrace::Backtrace, + collections::HashSet, + env::{self, VarError}, + fs::{self}, + path::PathBuf, + process::Command, +}; + +use serde::Deserialize; +use tracing::warn; +use turbopath::{ + AbsoluteSystemPath, + AbsoluteSystemPathBuf, + AnchoredSystemPathBuf, + RelativeUnixPath, +}; +use turborepo_ci::Vendor; + +use crate::{Error, Git, SCM}; + +#[derive(Debug, PartialEq, Eq)] +pub struct InvalidRange { + pub from_ref:Option, + pub to_ref:Option, +} + +impl SCM { + pub fn get_current_branch(&self, path:&AbsoluteSystemPath) -> Result { + match self { + Self::Git(git) => git.get_current_branch(), + Self::Manual => Err(Error::GitRequired(path.to_owned())), + } + } + + pub fn get_current_sha(&self, path:&AbsoluteSystemPath) -> Result { + match self { + Self::Git(git) => git.get_current_sha(), + Self::Manual => Err(Error::GitRequired(path.to_owned())), + } + } + + pub fn changed_files( + &self, + turbo_root:&AbsoluteSystemPath, + from_commit:Option<&str>, + to_commit:Option<&str>, + include_uncommitted:bool, + allow_unknown_objects:bool, + merge_base:bool, + ) -> Result, InvalidRange>, Error> { + fn unable_to_detect_range( + error:impl std::error::Error, + from_ref:Option, + to_ref:Option, + ) -> Result, InvalidRange>, Error> { + warn!("unable to detect git range, assuming all files have changed: {}", error); + Ok(Err(InvalidRange { from_ref, to_ref })) + } + match self { + Self::Git(git) => { + match git.changed_files( + turbo_root, + from_commit, + to_commit, + include_uncommitted, + merge_base, + ) { + Ok(files) => Ok(Ok(files)), + Err(ref error @ Error::Git(ref message, _)) + if allow_unknown_objects + && (message.contains("no merge base") + || message.contains("bad object")) => + { + unable_to_detect_range( + error, + from_commit.map(|c| c.to_string()), + to_commit.map(|c| c.to_string()), + ) + }, + Err(Error::UnableToResolveRef) => { + unable_to_detect_range( + Error::UnableToResolveRef, + from_commit.map(|c| c.to_string()), + to_commit.map(|c| c.to_string()), + ) + }, + Err(e) => Err(e), + } + }, + Self::Manual => Err(Error::GitRequired(turbo_root.to_owned())), + } + } + + pub fn previous_content( + &self, + from_commit:Option<&str>, + file_path:&AbsoluteSystemPath, + ) -> Result, Error> { + match self { + Self::Git(git) => git.previous_content(from_commit, file_path), + Self::Manual => Err(Error::GitRequired(file_path.to_owned())), + } + } +} + +const UNKNOWN_SHA:&str = "0000000000000000000000000000000000000000"; + +#[derive(Debug, Deserialize, Clone)] +struct GitHubCommit { + id:String, +} + +#[derive(Debug, Deserialize, Default)] +struct GitHubEvent { + #[serde(default)] + before:String, + + #[serde(default)] + commits:Vec, + + #[serde(default)] + forced:bool, +} + +impl GitHubEvent { + fn get_parent_ref_of_first_commit(&self) -> Option { + if self.commits.is_empty() { + // commits can be empty when you push a branch with no commits + return None; + } + + if self.commits.len() >= 2048 { + // GitHub API limit for number of commits shown in this field + return None; + } + + // Extract the base ref from the push event + let first_commit = self.commits.first()?; + let id = &first_commit.id; + Some(format!("{id}^")) + } +} + +#[derive(Debug)] +pub struct CIEnv { + is_github_actions:bool, + github_base_ref:Result, + github_event_path:Result, +} + +impl Default for CIEnv { + fn default() -> Self { Self::new() } +} + +impl CIEnv { + pub fn new() -> Self { + Self { + is_github_actions:Vendor::is("GitHub Actions"), + github_base_ref:env::var("GITHUB_BASE_REF"), + github_event_path:env::var("GITHUB_EVENT_PATH"), + } + } + + pub fn none() -> Self { + Self { + is_github_actions:false, + github_base_ref:Err(VarError::NotPresent), + github_event_path:Err(VarError::NotPresent), + } + } +} + +impl Git { + fn get_current_branch(&self) -> Result { + let output = self.execute_git_command(&["branch", "--show-current"], "")?; + let output = String::from_utf8(output)?; + Ok(output.trim().to_owned()) + } + + fn get_current_sha(&self) -> Result { + let output = self.execute_git_command(&["rev-parse", "HEAD"], "")?; + let output = String::from_utf8(output)?; + Ok(output.trim().to_owned()) + } + + /// for GitHub Actions environment variables, see: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables + pub fn get_github_base_ref(base_ref_env:CIEnv) -> Option { + // make sure we're running in a CI environment + if !base_ref_env.is_github_actions { + return None; + } + + // The name of the base ref or target branch of the pull request in a + // workflow run. + // + // This variable only has a value when the event that triggers a workflow run + // is either `pull_request` or `pull_request_target`. + // For example, `main` + // + // So environment variable is empty in a regular commit + if let Ok(pr) = base_ref_env.github_base_ref { + if !pr.is_empty() { + return Some(pr); + } + } + + // we must be in a push event + // try reading from the GITHUB_EVENT_PATH file + if let Ok(event_path) = base_ref_env.github_event_path { + // Try to open the event file and read the contents + let data = fs::read_to_string(event_path).ok()?; + + // Parse the JSON data from the file + let json:GitHubEvent = serde_json::from_str(&data).ok()?; + + // Extract the base ref from the pull request event if available + let base_ref = &json.before; + + // the base_ref will be UNKNOWN_SHA on first push + // we also use this behavior in force pushes + if base_ref == UNKNOWN_SHA || json.forced { + return json.get_parent_ref_of_first_commit(); + } + + if base_ref.is_empty() { + return None; + } + + return Some(base_ref.to_string()); + } + None + } + + fn resolve_base(&self, base_override:Option<&str>, env:CIEnv) -> Result { + if let Some(valid_from) = base_override { + return Ok(valid_from.to_string()); + } + + if let Some(github_base_ref) = Self::get_github_base_ref(env) { + // we don't fall through to checking against main or master + // because at this point we know we're in a GITHUB CI environment + // and we should really know by now what the base ref is + // so it's better to just error if something went wrong + return match self.execute_git_command(&["rev-parse", &github_base_ref], "") { + Ok(_) => { + eprintln!("Resolved base ref from GitHub Actions event: {github_base_ref}"); + Ok(github_base_ref) + }, + Err(e) => { + eprintln!( + "Failed to resolve base ref '{github_base_ref}' from GitHub Actions \ + event: {e}" + ); + Err(Error::UnableToResolveRef) + }, + }; + } + + let main_result = self.execute_git_command(&["rev-parse", "main"], ""); + if main_result.is_ok() { + return Ok("main".to_string()); + } + + let master_result = self.execute_git_command(&["rev-parse", "master"], ""); + if master_result.is_ok() { + return Ok("master".to_string()); + } + Err(Error::UnableToResolveRef) + } + + fn changed_files( + &self, + turbo_root:&AbsoluteSystemPath, + from_commit:Option<&str>, + to_commit:Option<&str>, + include_uncommitted:bool, + merge_base:bool, + ) -> Result, Error> { + let turbo_root_relative_to_git_root = self.root.anchor(turbo_root)?; + let pathspec = turbo_root_relative_to_git_root.as_str(); + + let mut files = HashSet::new(); + + let valid_from = self.resolve_base(from_commit, CIEnv::new())?; + + // If a to commit is not specified for `diff-tree` it will change the comparison + // to be between the provided commit and it's parent + let to_commit = to_commit.unwrap_or("HEAD"); + let mut args = + vec!["diff-tree", "-r", "--name-only", "--no-commit-id", &valid_from, to_commit]; + + if merge_base { + args.push("--merge-base"); + } + + let output = self.execute_git_command(&args, pathspec)?; + self.add_files_from_stdout(&mut files, turbo_root, output); + + // We only care about non-tracked files if we haven't specified both ends up the + // comparison + if include_uncommitted { + // Add untracked files or unstaged changes, i.e. files that are not in git at + // all + let ls_files_output = self.execute_git_command( + &["ls-files", "--others", "--modified", "--exclude-standard"], + pathspec, + )?; + self.add_files_from_stdout(&mut files, turbo_root, ls_files_output); + // Include any files that have been staged, but not committed + let diff_output = + self.execute_git_command(&["diff", "--name-only", "--cached"], pathspec)?; + self.add_files_from_stdout(&mut files, turbo_root, diff_output); + } + + Ok(files) + } + + fn execute_git_command(&self, args:&[&str], pathspec:&str) -> Result, Error> { + let mut command = Command::new(self.bin.as_std_path()); + command.args(args).current_dir(&self.root).env("GIT_OPTIONAL_LOCKS", "0"); + + if !pathspec.is_empty() { + command.arg("--").arg(pathspec); + } + + let output = command.output()?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + Err(Error::Git(stderr, Backtrace::capture())) + } else { + Ok(output.stdout) + } + } + + fn add_files_from_stdout( + &self, + files:&mut HashSet, + turbo_root:&AbsoluteSystemPath, + stdout:Vec, + ) { + let stdout = String::from_utf8(stdout).unwrap(); + for line in stdout.lines() { + let path = RelativeUnixPath::new(line).unwrap(); + let anchored_to_turbo_root_file_path = + self.reanchor_path_from_git_root_to_turbo_root(turbo_root, path).unwrap(); + files.insert(anchored_to_turbo_root_file_path); + } + } + + fn reanchor_path_from_git_root_to_turbo_root( + &self, + turbo_root:&AbsoluteSystemPath, + path:&RelativeUnixPath, + ) -> Result { + let absolute_file_path = self.root.join_unix_path(path); + let anchored_to_turbo_root_file_path = turbo_root.anchor(&absolute_file_path)?; + Ok(anchored_to_turbo_root_file_path) + } + + fn previous_content( + &self, + from_commit:Option<&str>, + file_path:&AbsoluteSystemPath, + ) -> Result, Error> { + let anchored_file_path = self.root.anchor(file_path)?; + let valid_from = self.resolve_base(from_commit, CIEnv::new())?; + let arg = format!("{}:{}", valid_from, anchored_file_path.as_str()); + + self.execute_git_command(&["show", &arg], "") + } +} + +/// Finds the content of a file at a previous commit. Assumes file is in a git +/// repository +/// +/// # Arguments +/// +/// * `git_root`: The root of the repository +/// * `from_commit`: The commit hash to checkout +/// * `file_path`: The path to the file +/// +/// returns: Result +pub fn previous_content( + git_root:PathBuf, + from_commit:Option<&str>, + file_path:String, +) -> Result, Error> { + // If git root is not absolute, we error. + let git_root = AbsoluteSystemPathBuf::try_from(git_root)?; + let scm = SCM::new(&git_root); + + // However for file path we handle both absolute and relative paths + // Note that we assume any relative file path is relative to the git root + // FIXME: this is probably wrong. We should know the path to the lockfile + // exactly + let absolute_file_path = AbsoluteSystemPathBuf::from_unknown(&git_root, file_path); + + scm.previous_content(from_commit, &absolute_file_path) +} + +#[cfg(test)] +mod tests { + use std::{ + assert_matches::assert_matches, + collections::HashSet, + env::VarError, + fs, + path::{Path, PathBuf}, + process::Command, + }; + + use git2::{Oid, Repository, RepositoryInitOptions}; + use tempfile::{NamedTempFile, TempDir}; + use test_case::test_case; + use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathError}; + use which::which; + + use super::{CIEnv, InvalidRange, previous_content}; + use crate::{ + Error, + Git, + SCM, + git::{GitHubCommit, GitHubEvent}, + }; + + fn setup_repository( + init_opts:Option<&RepositoryInitOptions>, + ) -> Result<(TempDir, Repository), Error> { + let repo_root = tempfile::tempdir()?; + let repo = Repository::init_opts( + repo_root.path(), + init_opts.unwrap_or(&RepositoryInitOptions::new()), + ) + .unwrap(); + let mut config = repo.config().unwrap(); + config.set_str("user.name", "test").unwrap(); + config.set_str("user.email", "test@example.com").unwrap(); + + Ok((repo_root, repo)) + } + + fn changed_files( + git_root:PathBuf, + turbo_root:PathBuf, + from_commit:Option<&str>, + to_commit:Option<&str>, + include_uncommitted:bool, + ) -> Result, Error> { + let git_root = AbsoluteSystemPath::from_std_path(&git_root)?; + let scm = SCM::new(git_root); + + let turbo_root = AbsoluteSystemPathBuf::try_from(turbo_root.as_path())?; + // Replicating the `--filter` behavior where we only do a merge base + // if both ends of the git range are specified. + let merge_base = to_commit.is_some(); + let Ok(files) = scm.changed_files( + &turbo_root, + from_commit, + to_commit, + include_uncommitted, + false, + merge_base, + )? + else { + unreachable!("changed_files should always return Some"); + }; + + Ok(files.into_iter().map(|f| f.to_string()).collect::>()) + } + + fn commit_file(repo:&Repository, path:&Path, previous_commit:Option) -> Oid { + let mut index = repo.index().unwrap(); + index.add_path(path).unwrap(); + let tree_oid = index.write_tree().unwrap(); + index.write().unwrap(); + let tree = repo.find_tree(tree_oid).unwrap(); + let previous_commit = previous_commit.map(|oid| repo.find_commit(oid)).transpose().unwrap(); + + repo.commit( + Some("HEAD"), + &repo.signature().unwrap(), + &repo.signature().unwrap(), + "Commit", + &tree, + previous_commit.as_ref().as_ref().map(std::slice::from_ref).unwrap_or_default(), + ) + .unwrap() + } + + fn commit_delete(repo:&Repository, path:&Path, previous_commit:Oid) -> Oid { + let mut index = repo.index().unwrap(); + index.remove_path(path).unwrap(); + let tree_oid = index.write_tree().unwrap(); + index.write().unwrap(); + let tree = repo.find_tree(tree_oid).unwrap(); + let previous_commit = repo.find_commit(previous_commit).unwrap(); + + repo.commit( + Some("HEAD"), + &repo.signature().unwrap(), + &repo.signature().unwrap(), + "Commit", + &tree, + std::slice::from_ref(&&previous_commit), + ) + .unwrap() + } + + fn commit_rename(repo:&Repository, source:&Path, dest:&Path, previous_commit:Oid) -> Oid { + let mut index = repo.index().unwrap(); + index.remove_path(source).unwrap(); + index.add_path(dest).unwrap(); + let tree_oid = index.write_tree().unwrap(); + index.write().unwrap(); + let tree = repo.find_tree(tree_oid).unwrap(); + let previous_commit = repo.find_commit(previous_commit).unwrap(); + + repo.commit( + Some("HEAD"), + &repo.signature().unwrap(), + &repo.signature().unwrap(), + "Commit", + &tree, + std::slice::from_ref(&&previous_commit), + ) + .unwrap() + } + + #[test] + fn test_shallow_clone() -> Result<(), Error> { + let tmp_dir = tempfile::tempdir()?; + + let git_binary = which("git")?; + let output = Command::new(git_binary) + .args([ + "clone", + "--depth", + "2", + "https://github.com/vercel/app-playground.git", + tmp_dir.path().to_str().unwrap(), + ]) + .output()?; + assert!(output.status.success()); + + assert!( + changed_files( + tmp_dir.path().to_owned(), + tmp_dir.path().to_owned(), + Some("HEAD~1"), + Some("HEAD"), + false, + ) + .is_ok() + ); + + assert!( + changed_files( + tmp_dir.path().to_owned(), + tmp_dir.path().to_owned(), + Some("HEAD"), + None, + true, + ) + .is_ok() + ); + + Ok(()) + } + + #[test] + fn test_deleted_files() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + + let file = repo_root.path().join("foo.js"); + let file_path = Path::new("foo.js"); + fs::write(&file, "let z = 0;")?; + + let first_commit_oid = commit_file(&repo, file_path, None); + + fs::remove_file(&file)?; + let _second_commit_oid = commit_delete(&repo, file_path, first_commit_oid); + + let first_commit_sha = first_commit_oid.to_string(); + let git_root = repo_root.path().to_owned(); + let turborepo_root = repo_root.path().to_owned(); + let files = + changed_files(git_root, turborepo_root, Some(&first_commit_sha), Some("HEAD"), false)?; + + assert_eq!(files, HashSet::from(["foo.js".to_string()])); + Ok(()) + } + + #[test] + fn test_renamed_files() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + + let file = repo_root.path().join("foo.js"); + let file_path = Path::new("foo.js"); + fs::write(&file, "let z = 0;")?; + + let first_commit_oid = commit_file(&repo, file_path, None); + + fs::rename(file, repo_root.path().join("bar.js")).unwrap(); + + let new_file_path = Path::new("bar.js"); + let _second_commit_oid = commit_rename(&repo, file_path, new_file_path, first_commit_oid); + + let first_commit_sha = first_commit_oid.to_string(); + let git_root = repo_root.path().to_owned(); + let turborepo_root = repo_root.path().to_owned(); + let files = + changed_files(git_root, turborepo_root, Some(&first_commit_sha), Some("HEAD"), false)?; + + assert_eq!(files, HashSet::from(["foo.js".to_string(), "bar.js".to_string()])); + Ok(()) + } + #[test] + fn test_merge_base() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + let first_file = repo_root.path().join("foo.js"); + fs::write(first_file, "let z = 0;")?; + // Create a base commit. This will *not* be the merge base + let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); + + let second_file = repo_root.path().join("bar.js"); + fs::write(second_file, "let y = 1;")?; + // This commit will be the merge base + let second_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(first_commit_oid)); + + let third_file = repo_root.path().join("baz.js"); + fs::write(third_file, "let x = 2;")?; + // Create a first commit off of merge base + let third_commit_oid = commit_file(&repo, Path::new("baz.js"), Some(second_commit_oid)); + + // Move head back to merge base + repo.set_head_detached(second_commit_oid).unwrap(); + let fourth_file = repo_root.path().join("qux.js"); + fs::write(fourth_file, "let w = 3;")?; + // Create a second commit off of merge base + let fourth_commit_oid = commit_file(&repo, Path::new("qux.js"), Some(second_commit_oid)); + + repo.set_head_detached(third_commit_oid).unwrap(); + let merge_base = repo.merge_base(third_commit_oid, fourth_commit_oid).unwrap(); + + assert_eq!(merge_base, second_commit_oid); + + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some(&third_commit_oid.to_string()), + Some(&fourth_commit_oid.to_string()), + false, + )?; + + assert_eq!(files, HashSet::from(["qux.js".to_string(), "baz.js".to_string()])); + + Ok(()) + } + + #[test] + fn test_changed_files() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + let mut index = repo.index().unwrap(); + let turbo_root = repo_root.path(); + let file = repo_root.path().join("foo.js"); + fs::write(file, "let z = 0;")?; + + // First commit (we need a base commit to compare against) + let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); + + // Now change another file + let new_file = repo_root.path().join("bar.js"); + fs::write(new_file, "let y = 1;")?; + + // Test that uncommitted file is marked as changed + let files = changed_files( + repo_root.path().to_path_buf(), + turbo_root.to_path_buf(), + Some("HEAD"), + None, + true, + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + // Test that uncommitted file in index is not marked as changed when not + // checking uncommitted + let files = changed_files( + repo_root.path().to_path_buf(), + turbo_root.to_path_buf(), + Some("HEAD"), + None, + false, + )?; + assert_eq!(files, HashSet::new()); + + // Test that uncommitted file in index is marked as changed when + // checking uncommitted + let files = changed_files( + repo_root.path().to_path_buf(), + turbo_root.to_path_buf(), + Some("HEAD"), + None, + true, + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + // Add file to index + index.add_path(Path::new("bar.js")).unwrap(); + index.write().unwrap(); + + // Test that uncommitted file in index is not marked as changed when not + // checking uncommitted + let files = changed_files( + repo_root.path().to_path_buf(), + turbo_root.to_path_buf(), + Some("HEAD"), + None, + false, + )?; + assert_eq!(files, HashSet::new()); + + // Test that uncommitted file in index is still marked as changed + let files = changed_files( + repo_root.path().to_path_buf(), + turbo_root.to_path_buf(), + Some("HEAD"), + None, + true, + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + // Now commit file + let second_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(first_commit_oid)); + + // Test that only second file is marked as changed when we check commit range + let files = changed_files( + repo_root.path().to_path_buf(), + turbo_root.to_path_buf(), + Some(first_commit_oid.to_string().as_str()), + Some(second_commit_oid.to_string().as_str()), + false, + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + // Create a file nested in subdir + fs::create_dir_all(repo_root.path().join("subdir"))?; + let new_file = repo_root.path().join("subdir").join("baz.js"); + fs::write(new_file, "let x = 2;")?; + + // The new directory and files are not yet committed, they shouldn't show up. + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some(first_commit_oid.to_string().as_str()), + Some(second_commit_oid.to_string().as_str()), + false, + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + // Since we are only specifying the first commit, the new file should show up + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some(second_commit_oid.to_string().as_str()), + None, + true, + )?; + assert_eq!(files, HashSet::from([format!("subdir{}baz.js", std::path::MAIN_SEPARATOR)])); + + // Commit the new file so it shows up in the changed files + let third_commit_oid = + commit_file(&repo, &Path::new("subdir").join("baz.js"), Some(second_commit_oid)); + + // Test that `turbo_root` filters out files not in the specified directory + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().join("subdir"), + Some(first_commit_oid.to_string().as_str()), + Some(third_commit_oid.to_string().as_str()), + false, + )?; + assert_eq!(files, HashSet::from(["baz.js".to_string()])); + + Ok(()) + } + + #[test] + fn test_changed_files_with_root_as_relative() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + let file = repo_root.path().join("foo.js"); + fs::write(file, "let z = 0;")?; + + // First commit (we need a base commit to compare against) + commit_file(&repo, Path::new("foo.js"), None); + + // Now change another file + let new_file = repo_root.path().join("bar.js"); + fs::write(new_file, "let y = 1;")?; + + // Test that uncommitted file is marked as changed with the parameters that Go + // will pass + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some("HEAD"), + None, + true, + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + Ok(()) + } + + // Tests that we can use a subdir as the turbo_root path + // (occurs when the monorepo is nested inside a subdirectory of git repository) + #[test] + fn test_changed_files_with_subdir_as_turbo_root() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + + fs::create_dir(repo_root.path().join("subdir"))?; + // Create additional nested directory to test that we return a system path + // and not a normalized unix path + fs::create_dir(repo_root.path().join("subdir").join("src"))?; + + let file = repo_root.path().join("subdir").join("foo.js"); + fs::write(file, "let z = 0;")?; + let first_commit = commit_file(&repo, Path::new("subdir/foo.js"), None); + + let new_file = repo_root.path().join("subdir").join("src").join("bar.js"); + fs::write(new_file, "let y = 1;")?; + + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().join("subdir"), + Some("HEAD"), + None, + true, + )?; + + #[cfg(unix)] + { + assert_eq!(files, HashSet::from(["src/bar.js".to_string()])); + } + + #[cfg(windows)] + { + assert_eq!(files, HashSet::from(["src\\bar.js".to_string()])); + } + + commit_file(&repo, Path::new("subdir/src/bar.js"), Some(first_commit)); + + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().join("subdir"), + Some(first_commit.to_string().as_str()), + Some(repo.head().unwrap().peel_to_commit().unwrap().id().to_string().as_str()), + false, + )?; + + #[cfg(unix)] + { + assert_eq!(files, HashSet::from(["src/bar.js".to_string()])); + } + + #[cfg(windows)] + { + assert_eq!(files, HashSet::from(["src\\bar.js".to_string()])); + } + + Ok(()) + } + + #[test] + fn test_previous_content() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + + let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); + let file = root.join_component("foo.js"); + file.create_with_contents("let z = 0;")?; + + let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); + fs::write(&file, "let z = 1;")?; + let second_commit_oid = commit_file(&repo, Path::new("foo.js"), Some(first_commit_oid)); + + let content = previous_content( + repo_root.path().to_path_buf(), + Some(first_commit_oid.to_string().as_str()), + file.to_string(), + )?; + + assert_eq!(content, b"let z = 0;"); + + let content = previous_content( + repo_root.path().to_path_buf(), + Some(second_commit_oid.to_string().as_str()), + file.to_string(), + )?; + assert_eq!(content, b"let z = 1;"); + + let content = previous_content( + repo_root.path().to_path_buf(), + Some(second_commit_oid.to_string().as_str()), + "foo.js".to_string(), + )?; + assert_eq!(content, b"let z = 1;"); + + Ok(()) + } + + #[test] + fn test_revparse() -> Result<(), Error> { + let (repo_root, repo) = setup_repository(None)?; + let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); + + let file = root.join_component("foo.js"); + file.create_with_contents("let z = 0;")?; + + let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); + fs::write(&file, "let z = 1;")?; + let second_commit_oid = commit_file(&repo, Path::new("foo.js"), Some(first_commit_oid)); + + let revparsed_head = repo.revparse_single("HEAD").unwrap(); + assert_eq!(revparsed_head.id(), second_commit_oid); + let revparsed_head_minus_1 = repo.revparse_single("HEAD~1").unwrap(); + assert_eq!(revparsed_head_minus_1.id(), first_commit_oid); + + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some("HEAD^"), + Some("HEAD"), + false, + )?; + assert_eq!(files, HashSet::from(["foo.js".to_string()])); + + let content = + previous_content(repo_root.path().to_path_buf(), Some("HEAD^"), file.to_string())?; + assert_eq!(content, b"let z = 0;"); + + let new_file = repo_root.path().join("bar.js"); + fs::write(new_file, "let y = 0;")?; + let third_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(second_commit_oid)); + let third_commit = repo.find_commit(third_commit_oid).unwrap(); + repo.branch("release-1", &third_commit, false).unwrap(); + + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some("HEAD~1"), + Some("release-1"), + false, + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + Ok(()) + } + + #[test_case(vec!["main"], None, Some("main"))] + #[test_case(vec!["master"], None, Some("master"))] + #[test_case(vec!["ziltoid"], None, None)] + #[test_case(vec!["ziltoid", "main"], Some("ziltoid"), Some("ziltoid"))] + #[test_case(vec!["ziltoid", "main"], Some("main"), Some("main"))] + #[test_case(vec!["ziltoid", "main"], None, Some("main"))] + #[test_case(vec!["ziltoid", "master"], Some("ziltoid"), Some("ziltoid"))] + #[test_case(vec!["ziltoid", "master"], Some("master"), Some("master"))] + #[test_case(vec!["ziltoid", "master"], None, Some("master"))] + #[test_case(vec!["ziltoid", "master", "main"], Some("ziltoid"), Some("ziltoid"))] + #[test_case(vec!["ziltoid", "master", "main"], Some("master"), Some("master"))] + #[test_case(vec!["ziltoid", "master", "main"], Some("main"), Some("main"))] + #[test_case(vec!["ziltoid", "master", "main"], None, Some("main"))] + fn test_base_resolution( + branches_to_create:Vec<&str>, + target_branch:Option<&str>, + expected:Option<&str>, + ) -> Result<(), Error> { + let mut repo_opts = RepositoryInitOptions::new(); + + let (first_branch, remaining_branches) = branches_to_create.split_first().unwrap(); + + let repo_init = repo_opts.initial_head(first_branch); + let (repo_root, repo) = setup_repository(Some(repo_init))?; + let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); + + // WARNING: + // if you do not make a commit, git will show you that you have no branches. + let file = root.join_component("todo.txt"); + file.create_with_contents("1. make async Rust good")?; + let first_commit = commit_file(&repo, Path::new("todo.txt"), None); + let commit = repo.find_commit(first_commit).unwrap(); + + remaining_branches.iter().for_each(|branch| { + repo.branch(branch, &commit, true).unwrap(); + }); + + let thing = Git::find(&root).unwrap(); + let actual = thing.resolve_base(target_branch, CIEnv::none()).ok(); + + assert_eq!(actual.as_deref(), expected); + + Ok(()) + } + + #[test] + fn test_error_cases() -> Result<(), Error> { + let repo_dir = tempfile::tempdir()?; + let repo_does_not_exist = changed_files( + repo_dir.path().to_path_buf(), + repo_dir.path().to_path_buf(), + Some("HEAD"), + None, + true, + ); + + assert_matches!(repo_does_not_exist, Err(Error::GitRequired(_))); + + let (repo_root, _repo) = setup_repository(None)?; + let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); + + let commit_does_not_exist = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some("does-not-exist"), + None, + true, + ); + + assert_matches!(commit_does_not_exist, Err(Error::Git(_, _))); + + let file_does_not_exist = previous_content( + repo_root.path().to_path_buf(), + Some("HEAD"), + root.join_component("does-not-exist").to_string(), + ); + assert_matches!(file_does_not_exist, Err(Error::Git(_, _))); + + let turbo_root = tempfile::tempdir()?; + let turbo_root_is_not_subdir_of_git_root = changed_files( + repo_root.path().to_path_buf(), + turbo_root.path().to_path_buf(), + Some("HEAD"), + None, + true, + ); + + assert_matches!( + turbo_root_is_not_subdir_of_git_root, + Err(Error::Path(PathError::NotParent(_, _), _)) + ); + + Ok(()) + } + + #[test] + fn test_changed_files_no_base() -> Result<(), Error> { + let mut repo_opts = RepositoryInitOptions::new(); + + let repo_init = repo_opts.initial_head("my-main"); + let (repo_root, repo) = setup_repository(Some(repo_init))?; + let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); + + // WARNING: + // if you do not make a commit, git will show you that you have no branches. + let file = root.join_component("todo.txt"); + file.create_with_contents("1. explain why async Rust is good")?; + let _first_commit = commit_file(&repo, Path::new("todo.txt"), None); + + let scm = SCM::new(&root); + let actual = scm.changed_files(&root, None, Some("HEAD"), true, true, false).unwrap(); + + assert_eq!(actual, Err(InvalidRange { from_ref:None, to_ref:Some("HEAD".to_string()) })); + + Ok(()) + } + + struct TestCase { + env:CIEnv, + event_json:&'static str, + } + + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Err(VarError::NotPresent), + }, + event_json: r#""#, + }, + None + ; "GITHUB_BASE_REF and GITHUB_EVENT_PATH are not set" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Ok("".to_string()), + github_event_path: Err(VarError::NotPresent), + }, + event_json: r#""#, + }, + None + ; "GITHUB_BASE_REF is set to an empty string" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Ok("The choice is yours, and yours alone".to_string()), + github_event_path: Err(VarError::NotPresent), + }, + event_json: r#""#, + }, + Some("The choice is yours, and yours alone") + ; "GITHUB_BASE_REF is set to a non-empty string" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("Olmec refused to give up the location of the Shrine of the Silver Monkey".to_string()), + }, + event_json: r#""#, + }, + None + ; "GITHUB_EVENT_PATH is set, but the file fails to open" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("the_room_of_the_three_gargoyles.json".to_string()), + }, + event_json: r#"first you must pass the temple guards!"#, + }, + None + ; "GITHUB_EVENT_PATH is set, is not valid JSON" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("olmecs_temple.json".to_string()), + }, + event_json: r#"{}"#, + }, + None + ; "no 'before' key in the JSON" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("olmecs_temple.json".to_string()), + }, + event_json: r#"{"forced":true}"#, + }, + None + ; "force push" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), + }, + event_json: r#"{"before":"e83c5163316f89bfbde7d9ab23ca2e25604af290"}"#, + }, + Some("e83c5163316f89bfbde7d9ab23ca2e25604af290") + ; "found a valid 'before' key in the JSON" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), + }, + event_json: r#"{"before":"0000000000000000000000000000000000000000"}"#, + }, + None + ; "UNKNOWN_SHA but no commits found" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), + }, + event_json: r#"{"before":"0000000000000000000000000000000000000000","commits":[]}"#, + }, + None + ; "empty commits" + )] + #[test_case( + TestCase { + env: CIEnv { + is_github_actions: true, + github_base_ref: Err(VarError::NotPresent), + github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), + }, + event_json: r#"{"before":"0000000000000000000000000000000000000000","commits":[{"id":"yep"}]}"#, + }, + Some("yep^") + ; "first commit has a parent" + )] + fn test_get_github_base_ref(test_case:TestCase, expected:Option<&str>) -> Result<(), Error> { + // note: we must bind here because otherwise the temporary file will be dropped + let temp_file = if test_case.env.github_event_path.is_ok() { + let temp_file = NamedTempFile::new().expect("Failed to create temporary file"); + fs::write(temp_file.path(), test_case.event_json) + .expect("Failed to write to temporary file"); + Ok(temp_file) + } else { + Err(VarError::NotPresent) + }; + + let actual = Git::get_github_base_ref(CIEnv { + is_github_actions:test_case.env.is_github_actions, + github_base_ref:test_case.env.github_base_ref, + github_event_path:temp_file + .as_ref() + .map(|p| p.path().to_str().unwrap().to_string()) + .map_err(|e| e.clone()), + }); + assert_eq!(actual, expected.map(|s| s.to_string())); + + Ok(()) + } + + #[test] + fn test_thousands_of_commits() { + let commits = vec![ + GitHubCommit { + id: "insert-famous-sha-here".to_string(), + }; + 2049 // 2049 is one over the limit + ]; + + let github_event = GitHubEvent { before:"".to_string(), commits, forced:false }; + let actual = github_event.get_parent_ref_of_first_commit(); + + assert_eq!(None, actual); + } +} diff --git a/crates/turborepo-scm/Source/hash_object.rs b/crates/turborepo-scm/Source/hash_object.rs new file mode 100644 index 0000000000000..1a88aabee8d6f --- /dev/null +++ b/crates/turborepo-scm/Source/hash_object.rs @@ -0,0 +1,117 @@ +use tracing::Span; +use turbopath::{AbsoluteSystemPath, AnchoredSystemPathBuf, RelativeUnixPathBuf}; + +use crate::{Error, package_deps::GitHashes}; + +#[tracing::instrument(skip(git_root, hashes, to_hash))] +pub(crate) fn hash_objects( + git_root:&AbsoluteSystemPath, + pkg_path:&AbsoluteSystemPath, + to_hash:Vec, + hashes:&mut GitHashes, +) -> Result<(), Error> { + let parent = Span::current(); + for filename in to_hash { + let span = tracing::info_span!(parent: &parent, "hash_object", ?filename); + let _enter = span.enter(); + + let full_file_path = git_root.join_unix_path(filename); + match git2::Oid::hash_file(git2::ObjectType::Blob, &full_file_path) { + Ok(hash) => { + let package_relative_path = + AnchoredSystemPathBuf::relative_path_between(pkg_path, &full_file_path) + .to_unix(); + hashes.insert(package_relative_path, hash.to_string()); + }, + Err(e) => { + // FIXME: we currently do not hash symlinks. "git hash-object" cannot handle + // them, and the Go implementation errors on them, switches to + // manual, and then skips them. For now, we'll skip them too. + if e.class() == git2::ErrorClass::Os + && full_file_path.symlink_metadata().map(|md| md.is_symlink()).unwrap_or(false) + { + continue; + } else { + // For any other error, ensure we attach some context to it + return Err(Error::git2_error_context(e, full_file_path.to_string())); + } + }, + } + } + Ok(()) +} + +#[cfg(test)] +mod test { + use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf, RelativeUnixPathBufTestExt}; + + use super::hash_objects; + use crate::{find_git_root, package_deps::GitHashes}; + + #[test] + fn test_read_object_hashes() { + // Note that cwd can be different based on where the test suite is running from + // or if the test is launched in debug mode from VSCode + let cwd = std::env::current_dir().unwrap(); + let cwd = AbsoluteSystemPathBuf::try_from(cwd).unwrap(); + let git_root = find_git_root(&cwd).unwrap(); + let fixture_path = git_root.join_components(&[ + "crates", + "turborepo-scm", + "fixtures", + "01-git-hash-object", + ]); + + let fixture_child_path = fixture_path.join_component("child"); + let git_root = find_git_root(&fixture_path).unwrap(); + + // paths for files here are relative to the package path. + let tests:Vec<(Vec<(&str, &str)>, &AbsoluteSystemPathBuf)> = vec![ + (vec![], &fixture_path), + ( + vec![ + ("../root.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), + ("child.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), + ("grandchild/grandchild.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), + ], + &fixture_child_path, + ), + ]; + + for (to_hash, pkg_path) in tests { + let file_hashes:Vec<(RelativeUnixPathBuf, String)> = to_hash + .into_iter() + .map(|(raw, hash)| (RelativeUnixPathBuf::new(raw).unwrap(), String::from(hash))) + .collect(); + + let git_to_pkg_path = git_root.anchor(pkg_path).unwrap(); + let pkg_prefix = git_to_pkg_path.to_unix(); + + let expected_hashes = GitHashes::from_iter(file_hashes); + let mut hashes = GitHashes::new(); + let to_hash = expected_hashes.keys().map(|k| pkg_prefix.join(k)).collect(); + hash_objects(&git_root, pkg_path, to_hash, &mut hashes).unwrap(); + assert_eq!(hashes, expected_hashes); + } + + // paths for files here are relative to the package path. + let error_tests:Vec<(Vec<&str>, &AbsoluteSystemPathBuf)> = vec![ + // skipping test for outside of git repo, we now error earlier in the process + (vec!["nonexistent.json"], &fixture_path), + ]; + + for (to_hash, pkg_path) in error_tests { + let git_to_pkg_path = git_root.anchor(pkg_path).unwrap(); + let pkg_prefix = git_to_pkg_path.to_unix(); + + let to_hash = to_hash + .into_iter() + .map(|k| pkg_prefix.join(&RelativeUnixPathBuf::new(k).unwrap())) + .collect(); + + let mut hashes = GitHashes::new(); + let result = hash_objects(&git_root, pkg_path, to_hash, &mut hashes); + assert!(result.is_err()); + } + } +} diff --git a/crates/turborepo-scm/src/lib.rs b/crates/turborepo-scm/Source/lib.rs similarity index 100% rename from crates/turborepo-scm/src/lib.rs rename to crates/turborepo-scm/Source/lib.rs diff --git a/crates/turborepo-scm/Source/ls_tree.rs b/crates/turborepo-scm/Source/ls_tree.rs new file mode 100644 index 0000000000000..9891bcf8663fa --- /dev/null +++ b/crates/turborepo-scm/Source/ls_tree.rs @@ -0,0 +1,144 @@ +use std::{ + io::{BufRead, BufReader, Read}, + process::{Command, Stdio}, +}; + +use nom::Finish; +use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf}; + +use crate::{Error, Git, package_deps::GitHashes, wait_for_success}; + +impl Git { + #[tracing::instrument(skip(self))] + pub fn git_ls_tree(&self, root_path:&AbsoluteSystemPathBuf) -> Result { + let mut hashes = GitHashes::new(); + let mut git = Command::new(self.bin.as_std_path()) + .args(["ls-tree", "-r", "-z", "HEAD"]) + .env("GIT_OPTIONAL_LOCKS", "0") + .current_dir(root_path) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + + let stdout = git + .stdout + .as_mut() + .ok_or_else(|| Error::git_error("failed to get stdout for git ls-tree"))?; + let mut stderr = git + .stderr + .take() + .ok_or_else(|| Error::git_error("failed to get stderr for git ls-tree"))?; + let parse_result = read_ls_tree(stdout, &mut hashes); + wait_for_success(git, &mut stderr, "git ls-tree", root_path, parse_result)?; + Ok(hashes) + } +} + +fn read_ls_tree(reader:R, hashes:&mut GitHashes) -> Result<(), Error> { + let mut reader = BufReader::new(reader); + let mut buffer = Vec::new(); + while reader.read_until(b'\0', &mut buffer)? != 0 { + let entry = parse_ls_tree(&buffer)?; + let hash = String::from_utf8(entry.hash.to_vec())?; + let path = RelativeUnixPathBuf::new(String::from_utf8(entry.filename.to_vec())?)?; + hashes.insert(path, hash); + buffer.clear(); + } + Ok(()) +} + +struct LsTreeEntry<'a> { + filename:&'a [u8], + hash:&'a [u8], +} + +fn parse_ls_tree(i:&[u8]) -> Result, Error> { + let mut parser = nom::combinator::all_consuming(nom_parse_ls_tree); + match parser(i).finish() { + Ok((_, entry)) => Ok(entry), + Err(e) => { + Err(Error::git_error(format!( + "failed to parse git-ls-tree: {}", + String::from_utf8_lossy(e.input) + ))) + }, + } +} + +fn nom_parse_ls_tree(i:&[u8]) -> nom::IResult<&[u8], LsTreeEntry<'_>> { + let (i, _) = nom::bytes::complete::is_not(" ")(i)?; + let (i, _) = nom::character::complete::space1(i)?; + let (i, _) = nom::bytes::complete::is_not(" ")(i)?; + let (i, _) = nom::character::complete::space1(i)?; + let (i, hash) = nom::bytes::complete::take(40usize)(i)?; + let (i, _) = nom::bytes::complete::take(1usize)(i)?; + let (i, filename) = nom::bytes::complete::is_not("\0")(i)?; + // We explicitly support a missing terminator + let (i, _) = nom::combinator::opt(nom::bytes::complete::tag(b"\0"))(i)?; + Ok((i, LsTreeEntry { filename, hash })) +} + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use turbopath::RelativeUnixPathBuf; + + use crate::{ls_tree::read_ls_tree, package_deps::GitHashes}; + + fn to_hash_map(pairs:&[(&str, &str)]) -> GitHashes { + HashMap::from_iter( + pairs + .iter() + .map(|(path, hash)| (RelativeUnixPathBuf::new(*path).unwrap(), hash.to_string())), + ) + } + + #[test] + fn test_ls_tree() { + let tests:&[(&str, &[(&str, &str)])] = &[ + ( + "100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\tpackage.json\0", + &[("package.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")], + ), + ( + // missing nul byte + "100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\tpackage.json", + &[("package.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")], + ), + ( + // We aren't attempting to use octal escapes here, it just looks like it + #[allow(clippy::octal_escapes)] + "100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\t\t\000100644 blob \ + e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\t\"\000100644 blob \ + 5b999efa470b056e329b4c23a73904e0794bdc2f\t\n\000100644 blob \ + f44f57fff95196c5f7139dfa0b96875f1e9650a9\t.gitignore\000100644 blob \ + 33dbaf21275ca2a5f460249d941cbc27d5da3121\tREADME.md\000040000 tree \ + 7360f2d292aec95907cebdcbb412a6bf2bd10f8a\tapps\000100644 blob \ + 9ec2879b24ce2c817296eebe2cb3846f8e4751ea\tpackage.json\000040000 tree \ + 5759aadaea2cde55468a61e7104eb0a9d86c1d30\tpackages\000100644 blob \ + 33d0621ee2f4da4a2f6f6bdd51a42618d181e337\tturbo.json\000100644 blob \ + 579f273c9536d324c20b2e8f0d7fe4784ed0d9df\tfile with spaces\0", + &[ + ("\t", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), + ("\"", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), + ("\n", "5b999efa470b056e329b4c23a73904e0794bdc2f"), + (".gitignore", "f44f57fff95196c5f7139dfa0b96875f1e9650a9"), + ("README.md", "33dbaf21275ca2a5f460249d941cbc27d5da3121"), + ("apps", "7360f2d292aec95907cebdcbb412a6bf2bd10f8a"), + ("package.json", "9ec2879b24ce2c817296eebe2cb3846f8e4751ea"), + ("packages", "5759aadaea2cde55468a61e7104eb0a9d86c1d30"), + ("turbo.json", "33d0621ee2f4da4a2f6f6bdd51a42618d181e337"), + ("file with spaces", "579f273c9536d324c20b2e8f0d7fe4784ed0d9df"), + ], + ), + ]; + for (input, expected) in tests { + let input_bytes = input.as_bytes(); + let mut hashes = GitHashes::new(); + let expected = to_hash_map(expected); + read_ls_tree(input_bytes, &mut hashes).unwrap(); + assert_eq!(hashes, expected); + } + } +} diff --git a/crates/turborepo-scm/Source/manual.rs b/crates/turborepo-scm/Source/manual.rs new file mode 100644 index 0000000000000..d30f9cd88e1fb --- /dev/null +++ b/crates/turborepo-scm/Source/manual.rs @@ -0,0 +1,444 @@ +use std::io::{ErrorKind, Read}; + +use globwalk::fix_glob_pattern; +use hex::ToHex; +use ignore::WalkBuilder; +use sha1::{Digest, Sha1}; +use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, IntoUnix}; +use wax::{Glob, Program, any}; + +use crate::{Error, package_deps::GitHashes}; + +fn git_like_hash_file(path:&AbsoluteSystemPath) -> Result { + let mut hasher = Sha1::new(); + let mut f = path.open()?; + let mut buffer = Vec::new(); + // Note that read_to_end reads the target if f is a symlink. Currently, this can + // happen when we are hashing a specific set of files, which in turn only + // happens for handling dotEnv files. It is likely that in the future we + // will want to ensure that the target is better accounted for in the set of + // inputs to the task. Manual hashing, as well as global deps and other + // places that support globs all ignore symlinks. + let size = f.read_to_end(&mut buffer)?; + hasher.update("blob ".as_bytes()); + hasher.update(size.to_string().as_bytes()); + hasher.update([b'\0']); + hasher.update(buffer.as_slice()); + let result = hasher.finalize(); + Ok(result.encode_hex::()) +} + +fn to_glob(input:&str) -> Result { + let glob = fix_glob_pattern(input).into_unix(); + let g = Glob::new(glob.as_str()).map(|g| g.into_owned())?; + + Ok(g) +} + +pub(crate) fn hash_files( + root_path:&AbsoluteSystemPath, + files:impl Iterator>, + allow_missing:bool, +) -> Result { + let mut hashes = GitHashes::new(); + for file in files.into_iter() { + let path = root_path.resolve(file.as_ref()); + match git_like_hash_file(&path) { + Ok(hash) => hashes.insert(file.as_ref().to_unix(), hash), + Err(Error::Io(ref io_error, _)) + if allow_missing && io_error.kind() == ErrorKind::NotFound => + { + continue; + }, + Err(e) => return Err(e), + }; + } + Ok(hashes) +} + +pub(crate) fn get_package_file_hashes_without_git>( + turbo_root:&AbsoluteSystemPath, + package_path:&AnchoredSystemPath, + inputs:&[S], + include_default_files:bool, +) -> Result { + let full_package_path = turbo_root.resolve(package_path); + let mut hashes = GitHashes::new(); + let mut default_file_hashes = GitHashes::new(); + let mut excluded_file_hashes = GitHashes::new(); + + let mut walker_builder = WalkBuilder::new(&full_package_path); + let mut includes = Vec::new(); + let mut excludes = Vec::new(); + for pattern in inputs { + let pattern = pattern.as_ref(); + if let Some(exclusion) = pattern.strip_prefix('!') { + let g = to_glob(exclusion)?; + excludes.push(g); + } else { + let g = to_glob(pattern)?; + includes.push(g); + } + } + let include_pattern = if includes.is_empty() { + None + } else { + // Add in package.json and turbo.json to input patterns. Both file paths are + // relative to pkgPath + // + // - package.json is an input because if the `scripts` in the package.json + // change (i.e. the tasks that turbo executes), we want a cache miss, since + // any existing cache could be invalid. + // - turbo.json because it's the definition of the tasks themselves. The root + // turbo.json is similarly included in the global hash. This file may not + // exist in the workspace, but that is ok, because it will get ignored + // downstream. + let turbo_g = to_glob("package.json")?; + let package_g = to_glob("turbo.json")?; + includes.push(turbo_g); + includes.push(package_g); + + Some(any(includes)?) + }; + let exclude_pattern = if excludes.is_empty() { None } else { Some(any(excludes)?) }; + + let walker = walker_builder + .follow_links(false) + // if inputs have been provided manually, we shouldn't skip ignored files to mimic the + // regular behavior + .git_ignore(inputs.is_empty()) + .require_git(false) + .hidden(false) // this results in yielding hidden files (e.g. .gitignore) + .build(); + + for dirent in walker { + let dirent = dirent?; + let metadata = dirent.metadata()?; + // We need to do this here, rather than as a filter, because the root + // directory is always yielded and not subject to the supplied filter. + if metadata.is_dir() { + continue; + } + + let path = AbsoluteSystemPath::from_std_path(dirent.path())?; + let relative_path = full_package_path.anchor(path)?; + let relative_path = relative_path.to_unix(); + + // if we have includes, and this path doesn't match any of them, skip it + if let Some(include_pattern) = include_pattern.as_ref() { + if !include_pattern.is_match(relative_path.as_str()) { + continue; + } + } + + // if we have excludes, and this path matches one of them, skip it + if let Some(exclude_pattern) = exclude_pattern.as_ref() { + if exclude_pattern.is_match(relative_path.as_str()) { + continue; + } + } + + // FIXME: we don't hash symlinks... + if metadata.is_symlink() { + continue; + } + let hash = git_like_hash_file(path)?; + hashes.insert(relative_path, hash); + } + + // If we're including default files, we need to walk again, but this time with + // git_ignore enabled + if include_default_files { + let walker = walker_builder + .follow_links(false) + .git_ignore(true) + .require_git(false) + .hidden(false) // this results in yielding hidden files (e.g. .gitignore) + .build(); + + for dirent in walker { + let dirent = dirent?; + let metadata = dirent.metadata()?; + // We need to do this here, rather than as a filter, because the root + // directory is always yielded and not subject to the supplied filter. + if metadata.is_dir() { + continue; + } + + let path = AbsoluteSystemPath::from_std_path(dirent.path())?; + let relative_path = full_package_path.anchor(path)?; + let relative_path = relative_path.to_unix(); + + if let Some(exclude_pattern) = exclude_pattern.as_ref() { + if exclude_pattern.is_match(relative_path.as_str()) { + // track excludes so we can exclude them to the hash map later + if !metadata.is_symlink() { + let hash = git_like_hash_file(path)?; + excluded_file_hashes.insert(relative_path.clone(), hash); + } + } + } + + // FIXME: we don't hash symlinks... + if metadata.is_symlink() { + continue; + } + let hash = git_like_hash_file(path)?; + default_file_hashes.insert(relative_path, hash); + } + } + + // merge default with all hashes + hashes.extend(default_file_hashes); + // remove excluded files + hashes.retain(|key, _| !excluded_file_hashes.contains_key(key)); + + Ok(hashes) +} + +#[cfg(test)] +mod tests { + use std::assert_matches::assert_matches; + + use test_case::test_case; + use turbopath::{ + AbsoluteSystemPathBuf, + AnchoredSystemPathBuf, + RelativeUnixPath, + RelativeUnixPathBuf, + }; + + use super::*; + + fn tmp_dir() -> (tempfile::TempDir, AbsoluteSystemPathBuf) { + let tmp_dir = tempfile::tempdir().unwrap(); + let dir = AbsoluteSystemPathBuf::try_from(tmp_dir.path().to_path_buf()) + .unwrap() + .to_realpath() + .unwrap(); + (tmp_dir, dir) + } + + #[test_case(&["non-existent-file.txt"], true, false ; "allow_missing, all missing")] + #[test_case(&["non-existent-file.txt", "existing-file.txt"], true, false ; "allow_missing, some missing, some not")] + #[test_case(&["existing-file.txt"], true, false ; "allow_missing, none missing")] + #[test_case(&["non-existent-file.txt"], false, true ; "don't allow_missing, all missing")] + #[test_case(&["non-existent-file.txt", "existing-file.txt"], false, true ; "don't allow_missing, some missing, some not")] + #[test_case(&["existing-file.txt"], false, false ; "don't allow_missing, none missing")] + fn test_hash_files(files:&[&str], allow_missing:bool, want_err:bool) { + let (_tmp, turbo_root) = tmp_dir(); + let test_file = turbo_root.join_component("existing-file.txt"); + test_file.create_with_contents("").unwrap(); + + let expected = { + let mut expected = GitHashes::new(); + if files.contains(&"existing-file.txt") { + expected.insert( + RelativeUnixPathBuf::new("existing-file.txt").unwrap(), + "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391".to_string(), + ); + } + expected + }; + + let files = files.iter().map(|s| AnchoredSystemPathBuf::from_raw(s).unwrap()); + match hash_files(&turbo_root, files, allow_missing) { + Err(e) => assert!(want_err, "unexpected error {}", e), + Ok(hashes) => assert_eq!(hashes, expected), + } + } + + #[test] + fn test_hash_symlink() { + let (_tmp, turbo_root) = tmp_dir(); + let from_to_file = turbo_root.join_component("symlink-from-to-file"); + let from_to_dir = turbo_root.join_component("symlink-from-to-dir"); + let broken = turbo_root.join_component("symlink-broken"); + + let to_file = turbo_root.join_component("the-file-target"); + to_file.create_with_contents("contents").unwrap(); + + let to_dir = turbo_root.join_component("the-dir-target"); + to_dir.create_dir_all().unwrap(); + + from_to_file.symlink_to_file(to_file.to_string()).unwrap(); + from_to_dir.symlink_to_dir(to_dir.to_string()).unwrap(); + broken.symlink_to_file("does-not-exist").unwrap(); + + // Symlink to file. + let out = hash_files( + &turbo_root, + [AnchoredSystemPathBuf::from_raw("symlink-from-to-file").unwrap()].iter(), + true, + ) + .unwrap(); + let from_to_file_hash = + out.get(&RelativeUnixPathBuf::new("symlink-from-to-file").unwrap()).unwrap(); + assert_eq!(from_to_file_hash, "0839b2e9412b314cb8bb9a20f587aa13752ae310"); + + // Symlink to dir, allow_missing = true. + #[cfg(not(windows))] + { + let out = hash_files( + &turbo_root, + [AnchoredSystemPathBuf::from_raw("symlink-from-to-dir").unwrap()].iter(), + true, + ); + match out.err().unwrap() { + Error::Io(io_error, _) => assert_eq!(io_error.kind(), ErrorKind::IsADirectory), + _ => panic!("wrong error"), + }; + } + + // Symlink to dir, allow_missing = false. + let out = hash_files( + &turbo_root, + [AnchoredSystemPathBuf::from_raw("symlink-from-to-dir").unwrap()].iter(), + false, + ); + #[cfg(windows)] + let expected_err_kind = ErrorKind::PermissionDenied; + #[cfg(not(windows))] + let expected_err_kind = ErrorKind::IsADirectory; + assert_matches!(out.unwrap_err(), Error::Io(io_error, _) if io_error.kind() == expected_err_kind); + + // Broken symlink with allow_missing = true. + let out = hash_files( + &turbo_root, + [AnchoredSystemPathBuf::from_raw("symlink-broken").unwrap()].iter(), + true, + ) + .unwrap(); + let broken_hash = out.get(&RelativeUnixPathBuf::new("symlink-broken").unwrap()); + assert_eq!(broken_hash, None); + + // Broken symlink with allow_missing = false. + let out = hash_files( + &turbo_root, + [AnchoredSystemPathBuf::from_raw("symlink-broken").unwrap()].iter(), + false, + ); + match out.err().unwrap() { + Error::Io(io_error, _) => assert_eq!(io_error.kind(), ErrorKind::NotFound), + _ => panic!("wrong error"), + }; + } + + #[test] + fn test_get_package_file_hashes_from_processing_gitignore() { + let root_ignore_contents = ["ignoreme", "ignorethisdir/"].join("\n"); + let pkg_ignore_contents = ["pkgignoreme", "pkgignorethisdir/"].join("\n"); + + let (_tmp, turbo_root) = tmp_dir(); + + let pkg_path = AnchoredSystemPathBuf::from_raw("child-dir/libA").unwrap(); + let unix_pkg_path = pkg_path.to_unix(); + let mut file_hash:Vec<(&str, &str, Option<&str>)> = vec![ + ("turbo.json", "turbo.json-file-contents", None), + ("package.json", "root-package.json-file-contents", None), + ("top-level-file", "top-level-file-contents", None), + ("other-dir/other-dir-file", "other-dir-file-contents", None), + ("ignoreme", "anything", None), + ( + "child-dir/libA/turbo.json", + "lib-turbo.json-content", + Some("ca4dbb95c0829676756c6decae728252d4aa4911"), + ), + ( + "child-dir/libA/package.json", + "lib-package.json-content", + Some("55d57df9acc1b37d0cfc2c1c70379dab48f3f7e1"), + ), + ( + "child-dir/libA/some-file", + "some-file-contents", + Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), + ), + ( + "child-dir/libA/some-dir/other-file", + "some-file-contents", + Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), + ), + ( + "child-dir/libA/some-dir/another-one", + "some-file-contents", + Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), + ), + ( + "child-dir/libA/some-dir/excluded-file", + "some-file-contents", + Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), + ), + ("child-dir/libA/ignoreme", "anything", None), + ("child-dir/libA/ignorethisdir/anything", "anything", None), + ("child-dir/libA/pkgignoreme", "anything", None), + ("child-dir/libA/pkgignorethisdir/file", "anything", None), + ]; + + let root_ignore_file = turbo_root.join_component(".gitignore"); + root_ignore_file.create_with_contents(root_ignore_contents).unwrap(); + let pkg_ignore_file = turbo_root.resolve(&pkg_path).join_component(".gitignore"); + pkg_ignore_file.ensure_dir().unwrap(); + pkg_ignore_file.create_with_contents(pkg_ignore_contents).unwrap(); + + let mut expected = GitHashes::new(); + for (raw_unix_path, contents, expected_hash) in file_hash.iter() { + let unix_path = RelativeUnixPath::new(raw_unix_path).unwrap(); + let file_path = turbo_root.join_unix_path(unix_path); + file_path.ensure_dir().unwrap(); + file_path.create_with_contents(contents).unwrap(); + if let Some(hash) = expected_hash { + println!("unix_path: {}", unix_path); + println!("unix_pkg_path: {}", unix_pkg_path); + let unix_pkg_file_path = unix_path.strip_prefix(&unix_pkg_path).unwrap(); + println!("unix_pkg_file_path: {}", unix_pkg_file_path); + expected.insert(unix_pkg_file_path.to_owned(), (*hash).to_owned()); + } + } + expected.insert( + RelativeUnixPathBuf::new(".gitignore").unwrap(), + "3237694bc3312ded18386964a855074af7b066af".to_owned(), + ); + + let hashes = + get_package_file_hashes_without_git::<&str>(&turbo_root, &pkg_path, &[], false) + .unwrap(); + assert_eq!(hashes, expected); + + // set a hash for an ignored file + for (raw_unix_path, _, expected_hash) in file_hash.iter_mut() { + if *raw_unix_path == "child-dir/libA/pkgignorethisdir/file" { + *expected_hash = Some("67aed78ea231bdee3de45b6d47d8f32a0a792f6d"); + break; + } + } + + expected = GitHashes::new(); + for (raw_unix_path, contents, expected_hash) in file_hash.iter() { + let unix_path = RelativeUnixPath::new(raw_unix_path).unwrap(); + let file_path = turbo_root.join_unix_path(unix_path); + file_path.ensure_dir().unwrap(); + file_path.create_with_contents(contents).unwrap(); + if let Some(hash) = expected_hash { + let unix_pkg_file_path = unix_path.strip_prefix(&unix_pkg_path).unwrap(); + if (unix_pkg_file_path.ends_with("file") + || unix_pkg_file_path.ends_with("package.json") + || unix_pkg_file_path.ends_with("turbo.json")) + && !unix_pkg_file_path.ends_with("excluded-file") + { + expected.insert(unix_pkg_file_path.to_owned(), (*hash).to_owned()); + } + } + } + + let hashes = get_package_file_hashes_without_git( + &turbo_root, + &pkg_path, + &["**/*file", "!some-dir/excluded-file"], + false, + ) + .unwrap(); + + assert_eq!(hashes, expected); + } +} diff --git a/crates/turborepo-scm/Source/package_deps.rs b/crates/turborepo-scm/Source/package_deps.rs new file mode 100644 index 0000000000000..285b22fdd428c --- /dev/null +++ b/crates/turborepo-scm/Source/package_deps.rs @@ -0,0 +1,589 @@ +use std::{collections::HashMap, str::FromStr}; + +use globwalk::ValidatedGlob; +use tracing::debug; +use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, PathError, RelativeUnixPathBuf}; +use turborepo_telemetry::events::task::{FileHashMethod, PackageTaskEventBuilder}; + +use crate::{Error, Git, SCM, hash_object::hash_objects}; + +pub type GitHashes = HashMap; + +pub const INPUT_INCLUDE_DEFAULT_FILES:&str = "$TURBO_DEFAULT$"; + +impl SCM { + pub fn get_hashes_for_files( + &self, + turbo_root:&AbsoluteSystemPath, + files:&[impl AsRef], + allow_missing:bool, + ) -> Result { + if allow_missing { + self.hash_existing_of(turbo_root, files.iter()) + } else { + self.hash_files(turbo_root, files.iter()) + } + } + + #[tracing::instrument(skip(self, turbo_root, package_path, inputs))] + pub fn get_package_file_hashes>( + &self, + turbo_root:&AbsoluteSystemPath, + package_path:&AnchoredSystemPath, + inputs:&[S], + telemetry:Option, + ) -> Result { + // If the inputs contain "$TURBO_DEFAULT$", we need to include the "default" + // file hashes as well. NOTE: we intentionally don't remove + // "$TURBO_DEFAULT$" from the inputs if it exists in the off chance that + // the user has a file named "$TURBO_DEFAULT$" in their package (pls + // no). + let include_default_files = + inputs.iter().any(|input| input.as_ref() == INPUT_INCLUDE_DEFAULT_FILES); + + match self { + SCM::Manual => { + if let Some(telemetry) = telemetry { + telemetry.track_file_hash_method(FileHashMethod::Manual); + } + crate::manual::get_package_file_hashes_without_git( + turbo_root, + package_path, + inputs, + include_default_files, + ) + }, + SCM::Git(git) => { + let result = git.get_package_file_hashes( + turbo_root, + package_path, + inputs, + include_default_files, + ); + match result { + Ok(hashes) => { + if let Some(telemetry) = telemetry { + telemetry.track_file_hash_method(FileHashMethod::Git); + } + Ok(hashes) + }, + Err(err) => { + debug!("failed to use git to hash files: {}. Falling back to manual", err); + if let Some(telemetry) = telemetry { + telemetry.track_file_hash_method(FileHashMethod::Manual); + } + crate::manual::get_package_file_hashes_without_git( + turbo_root, + package_path, + inputs, + include_default_files, + ) + }, + } + }, + } + } + + pub fn hash_files( + &self, + turbo_root:&AbsoluteSystemPath, + files:impl Iterator>, + ) -> Result { + match self { + SCM::Manual => crate::manual::hash_files(turbo_root, files, false), + SCM::Git(git) => git.hash_files(turbo_root, files), + } + } + + // hash_existing_of takes a list of files to hash and returns the hashes for the + // files in that list that exist. Files in the list that do not exist are + // skipped. + pub fn hash_existing_of( + &self, + turbo_root:&AbsoluteSystemPath, + files:impl Iterator>, + ) -> Result { + crate::manual::hash_files(turbo_root, files, true) + } +} + +impl Git { + fn get_package_file_hashes>( + &self, + turbo_root:&AbsoluteSystemPath, + package_path:&AnchoredSystemPath, + inputs:&[S], + include_default_files:bool, + ) -> Result { + // no inputs, and no $TURBO_DEFAULT$ + if inputs.is_empty() { + return self.get_package_file_hashes_from_index(turbo_root, package_path); + } + + // we have inputs, but no $TURBO_DEFAULT$ + if !include_default_files { + return self.get_package_file_hashes_from_inputs( + turbo_root, + package_path, + inputs, + true, + ); + } + + // we have inputs, and $TURBO_DEFAULT$ + self.get_package_file_hashes_from_inputs_and_index(turbo_root, package_path, inputs) + } + + #[tracing::instrument(skip(self, turbo_root))] + fn get_package_file_hashes_from_index( + &self, + turbo_root:&AbsoluteSystemPath, + package_path:&AnchoredSystemPath, + ) -> Result { + let full_pkg_path = turbo_root.resolve(package_path); + let git_to_pkg_path = self.root.anchor(&full_pkg_path)?; + let pkg_prefix = git_to_pkg_path.to_unix(); + let mut hashes = self.git_ls_tree(&full_pkg_path)?; + // Note: to_hash is *git repo relative* + let to_hash = self.append_git_status(&full_pkg_path, &pkg_prefix, &mut hashes)?; + hash_objects(&self.root, &full_pkg_path, to_hash, &mut hashes)?; + Ok(hashes) + } + + fn hash_files( + &self, + process_relative_to:&AbsoluteSystemPath, + files:impl Iterator>, + ) -> Result { + let mut hashes = GitHashes::new(); + let to_hash = files + .map(|f| Ok(self.root.anchor(process_relative_to.resolve(f.as_ref()))?.to_unix())) + .collect::, PathError>>()?; + // Note: to_hash is *git repo relative* + hash_objects(&self.root, process_relative_to, to_hash, &mut hashes)?; + Ok(hashes) + } + + #[tracing::instrument(skip(self, turbo_root, inputs))] + fn get_package_file_hashes_from_inputs>( + &self, + turbo_root:&AbsoluteSystemPath, + package_path:&AnchoredSystemPath, + inputs:&[S], + include_configs:bool, + ) -> Result { + let full_pkg_path = turbo_root.resolve(package_path); + let package_unix_path_buf = package_path.to_unix(); + let package_unix_path = package_unix_path_buf.as_str(); + + let mut inputs = inputs.iter().map(|s| s.as_ref().to_string()).collect::>(); + + if include_configs { + // Add in package.json and turbo.json to input patterns. Both file paths are + // relative to pkgPath + // + // - package.json is an input because if the `scripts` in the package.json + // change (i.e. the tasks that turbo executes), we want a cache miss, since + // any existing cache could be invalid. + // - turbo.json because it's the definition of the tasks themselves. The root + // turbo.json is similarly included in the global hash. This file may not + // exist in the workspace, but that is ok, because it will get ignored + // downstream. + inputs.push("package.json".to_string()); + inputs.push("turbo.json".to_string()); + } + + // The input patterns are relative to the package. + // However, we need to change the globbing to be relative to the repo root. + // Prepend the package path to each of the input patterns. + // + // FIXME: we don't yet error on absolute unix paths being passed in as inputs, + // and instead tack them on as if they were relative paths. This should be an + // error further upstream, but since we haven't pulled the switch yet, + // we need to mimic the Go behavior here and trim leading `/` + // characters. + let mut inclusions = vec![]; + let mut exclusions = vec![]; + for raw_glob in inputs { + if let Some(exclusion) = raw_glob.strip_prefix('!') { + let glob_str = [package_unix_path, exclusion.trim_start_matches('/')].join("/"); + exclusions.push(ValidatedGlob::from_str(&glob_str)?); + } else { + let glob_str = [package_unix_path, raw_glob.trim_start_matches('/')].join("/"); + inclusions.push(ValidatedGlob::from_str(&glob_str)?); + } + } + let files = + globwalk::globwalk(turbo_root, &inclusions, &exclusions, globwalk::WalkType::Files)?; + let to_hash = files + .iter() + .map(|entry| { + let path = self.root.anchor(entry)?.to_unix(); + Ok(path) + }) + .collect::, Error>>()?; + let mut hashes = GitHashes::new(); + hash_objects(&self.root, &full_pkg_path, to_hash, &mut hashes)?; + Ok(hashes) + } + + #[tracing::instrument(skip(self, turbo_root, inputs))] + fn get_package_file_hashes_from_inputs_and_index>( + &self, + turbo_root:&AbsoluteSystemPath, + package_path:&AnchoredSystemPath, + inputs:&[S], + ) -> Result { + // collect the default files and the inputs + let default_file_hashes = + self.get_package_file_hashes_from_index(turbo_root, package_path)?; + + // we need to get hashes for excludes separately so we can remove them from the + // defaults later on + let mut includes = Vec::new(); + let mut excludes = Vec::new(); + for input in inputs { + let input_str = input.as_ref(); + if let Some(exclude) = input_str.strip_prefix('!') { + excludes.push(exclude); + } else { + includes.push(input_str); + } + } + // we have to always run the includes search because we add default files to the + // includes + let manual_includes_hashes = + self.get_package_file_hashes_from_inputs(turbo_root, package_path, &includes, true)?; + + // only run the excludes search if there are excludes + let manual_excludes_hashes = if !excludes.is_empty() { + self.get_package_file_hashes_from_inputs(turbo_root, package_path, &excludes, false)? + } else { + GitHashes::new() + }; + + // merge the two includes + let mut hashes = default_file_hashes; + hashes.extend(manual_includes_hashes); + + // remove the excludes + hashes.retain(|key, _| !manual_excludes_hashes.contains_key(key)); + + return Ok(hashes); + } +} + +#[cfg(test)] +mod tests { + use std::{assert_matches::assert_matches, process::Command}; + + use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; + + use super::*; + use crate::manual::get_package_file_hashes_without_git; + + fn tmp_dir() -> (tempfile::TempDir, AbsoluteSystemPathBuf) { + let tmp_dir = tempfile::tempdir().unwrap(); + let dir = AbsoluteSystemPathBuf::try_from(tmp_dir.path()).unwrap().to_realpath().unwrap(); + (tmp_dir, dir) + } + + fn require_git_cmd(repo_root:&AbsoluteSystemPathBuf, args:&[&str]) { + let mut cmd = Command::new("git"); + cmd.args(args).current_dir(repo_root); + assert!(cmd.output().unwrap().status.success()); + } + + fn setup_repository(repo_root:&AbsoluteSystemPathBuf) { + let cmds:&[&[&str]] = &[ + &["init", "."], + &["config", "--local", "user.name", "test"], + &["config", "--local", "user.email", "test@example.com"], + ]; + for cmd in cmds { + require_git_cmd(repo_root, cmd); + } + } + + fn commit_all(repo_root:&AbsoluteSystemPathBuf) { + let cmds:&[&[&str]] = &[&["add", "."], &["commit", "-m", "foo"]]; + for cmd in cmds { + require_git_cmd(repo_root, cmd); + } + } + + #[test] + fn test_hash_symlink() { + let (_, tmp_root) = tmp_dir(); + let git_root = tmp_root.join_component("actual_repo"); + git_root.create_dir_all().unwrap(); + setup_repository(&git_root); + git_root.join_component("inside").create_dir_all().unwrap(); + let link = git_root.join_component("link"); + link.symlink_to_dir("inside").unwrap(); + let to_hash = vec![RelativeUnixPathBuf::new("link").unwrap()]; + let mut hashes = GitHashes::new(); + // FIXME: This test verifies a bug: we don't hash symlinks. + // TODO: update this test to point at get_package_file_hashes + hash_objects(&git_root, &git_root, to_hash, &mut hashes).unwrap(); + assert!(hashes.is_empty()); + + let pkg_path = git_root.anchor(&git_root).unwrap(); + let manual_hashes = + get_package_file_hashes_without_git(&git_root, &pkg_path, &["l*"], false).unwrap(); + assert!(manual_hashes.is_empty()); + } + + #[test] + fn test_get_package_deps_fallback() { + let (_repo_root_tmp, repo_root) = tmp_dir(); + let my_pkg_dir = repo_root.join_component("my-pkg"); + my_pkg_dir.create_dir_all().unwrap(); + + // create file 1 + let committed_file_path = my_pkg_dir.join_component("committed-file"); + committed_file_path.create_with_contents("committed bytes").unwrap(); + + setup_repository(&repo_root); + commit_all(&repo_root); + let git = SCM::new(&repo_root); + assert_matches!(git, SCM::Git(_)); + // Remove the .git directory to trigger an error in git hashing + repo_root.join_component(".git").remove_dir_all().unwrap(); + let pkg_path = repo_root.anchor(&my_pkg_dir).unwrap(); + let hashes = git + .get_package_file_hashes::<&str>( + &repo_root, + &pkg_path, + &[], + Some(PackageTaskEventBuilder::new("my-pkg", "test")), + ) + .unwrap(); + let mut expected = GitHashes::new(); + expected.insert( + RelativeUnixPathBuf::new("committed-file").unwrap(), + "3a29e62ea9ba15c4a4009d1f605d391cdd262033".to_string(), + ); + assert_eq!(hashes, expected); + } + + #[test] + fn test_get_package_deps() -> Result<(), Error> { + // Directory structure: + // / + // package.json + // turbo.json + // .gitignore + // new-root-file <- new file not added to git + // my-pkg/ + // package.json + // turbo.json + // $TURBO_DEFAULT$ <- ignored by git + // committed-file + // deleted-file + // uncommitted-file <- new file not added to git + // dir/ + // nested-file + // ignored-file <- ignored by git + let (_repo_root_tmp, repo_root) = tmp_dir(); + + // create a root package.json + let root_pkg_json_path = repo_root.join_component("package.json"); + root_pkg_json_path.create_with_contents("{}")?; + + // create a root turbo.json + let root_turbo_json_path = repo_root.join_component("turbo.json"); + root_turbo_json_path.create_with_contents("{}")?; + + // create the package directory + let my_pkg_dir = repo_root.join_component("my-pkg"); + my_pkg_dir.create_dir_all()?; + + // create a gitignore file + let gitignore_path = repo_root.join_component(".gitignore"); + gitignore_path.create_with_contents("my-pkg/dir/ignored-file\nmy-pkg/$TURBO_DEFAULT$")?; + + // create file 1 + let committed_file_path = my_pkg_dir.join_component("committed-file"); + committed_file_path.create_with_contents("committed bytes")?; + + // create file 2 + let deleted_file_path = my_pkg_dir.join_component("deleted-file"); + deleted_file_path.create_with_contents("delete-me")?; + + // create file 3 + let nested_file_path = my_pkg_dir.join_components(&["dir", "nested-file"]); + nested_file_path.ensure_dir()?; + nested_file_path.create_with_contents("nested")?; + + // create a package package.json + let pkg_json_path = my_pkg_dir.join_component("package.json"); + pkg_json_path.create_with_contents("{}")?; + + // create a package turbo.json + let turbo_json_path = my_pkg_dir.join_component("turbo.json"); + turbo_json_path.create_with_contents("{}")?; + + setup_repository(&repo_root); + commit_all(&repo_root); + let git = SCM::new(&repo_root); + let SCM::Git(git) = git else { + panic!("expected git, found {:?}", git); + }; + + // remove a file + deleted_file_path.remove()?; + + // create another untracked file in git + let uncommitted_file_path = my_pkg_dir.join_component("uncommitted-file"); + uncommitted_file_path.create_with_contents("uncommitted bytes")?; + + // create an untracked file in git up a level + let root_file_path = repo_root.join_component("new-root-file"); + root_file_path.create_with_contents("new-root bytes")?; + + // create a file that will be ignored + let ignored_file_path = my_pkg_dir.join_components(&["dir", "ignored-file"]); + ignored_file_path.ensure_dir()?; + ignored_file_path.create_with_contents("ignored")?; + + // create a file that matches the $TURBO_DEFAULT$ token to test the edge case + let token_file_path = my_pkg_dir.join_components(&["$TURBO_DEFAULT$"]); + token_file_path.ensure_dir()?; + token_file_path.create_with_contents("maybe-rename?")?; + + let package_path = AnchoredSystemPathBuf::from_raw("my-pkg")?; + + let all_expected = to_hash_map(&[ + ("committed-file", "3a29e62ea9ba15c4a4009d1f605d391cdd262033"), + ("uncommitted-file", "4e56ad89387e6379e4e91ddfe9872cf6a72c9976"), + ("package.json", "9e26dfeeb6e641a33dae4961196235bdb965b21b"), + ("turbo.json", "9e26dfeeb6e641a33dae4961196235bdb965b21b"), + ("dir/nested-file", "bfe53d766e64d78f80050b73cd1c88095bc70abb"), + ]); + let hashes = git.get_package_file_hashes::<&str>(&repo_root, &package_path, &[], false)?; + assert_eq!(hashes, all_expected); + + // add the new root file as an option + let mut all_expected = all_expected.clone(); + all_expected.insert( + RelativeUnixPathBuf::new("../new-root-file").unwrap(), + "8906ddcdd634706188bd8ef1c98ac07b9be3425e".to_string(), + ); + all_expected.insert( + RelativeUnixPathBuf::new("dir/ignored-file").unwrap(), + "5537770d04ec8aaf7bae2d9ff78866de86df415c".to_string(), + ); + all_expected.insert( + RelativeUnixPathBuf::new("$TURBO_DEFAULT$").unwrap(), + "2f26c7b914476b3c519e4f0fbc0d16c52a60d178".to_string(), + ); + + let input_tests:&[(&[&str], &[&str])] = &[ + (&["uncommitted-file"], &["package.json", "turbo.json", "uncommitted-file"]), + ( + &["**/*-file"], + &[ + "committed-file", + "uncommitted-file", + "package.json", + "turbo.json", + "dir/nested-file", + "dir/ignored-file", + ], + ), + ( + &["../**/*-file"], + &[ + "committed-file", + "uncommitted-file", + "package.json", + "turbo.json", + "dir/nested-file", + "dir/ignored-file", + "../new-root-file", + ], + ), + ( + &["**/{uncommitted,committed}-file"], + &["committed-file", "uncommitted-file", "package.json", "turbo.json"], + ), + ( + &["../**/{new-root,uncommitted,committed}-file"], + &[ + "committed-file", + "uncommitted-file", + "package.json", + "turbo.json", + "../new-root-file", + ], + ), + ( + &["$TURBO_DEFAULT$"], + &[ + "committed-file", + "uncommitted-file", + "package.json", + "turbo.json", + "$TURBO_DEFAULT$", + "dir/nested-file", + ], + ), + ( + &["$TURBO_DEFAULT$", "!dir/*"], + &[ + "committed-file", + "uncommitted-file", + "package.json", + "turbo.json", + "$TURBO_DEFAULT$", + ], + ), + ( + &["$TURBO_DEFAULT$", "!committed-file", "dir/ignored-file"], + &[ + "uncommitted-file", + "package.json", + "turbo.json", + "dir/ignored-file", + "dir/nested-file", + "$TURBO_DEFAULT$", + ], + ), + ( + &["!committed-file", "$TURBO_DEFAULT$", "dir/ignored-file"], + &[ + "uncommitted-file", + "package.json", + "turbo.json", + "dir/ignored-file", + "dir/nested-file", + "$TURBO_DEFAULT$", + ], + ), + ]; + for (inputs, expected_files) in input_tests { + let expected:GitHashes = HashMap::from_iter(expected_files.iter().map(|key| { + let key = RelativeUnixPathBuf::new(*key).unwrap(); + let value = all_expected.get(&key).unwrap().clone(); + (key, value) + })); + let include_default_files = + inputs.iter().any(|input| input == &INPUT_INCLUDE_DEFAULT_FILES); + + let hashes = git + .get_package_file_hashes(&repo_root, &package_path, inputs, include_default_files) + .unwrap(); + assert_eq!(hashes, expected); + } + Ok(()) + } + + fn to_hash_map(pairs:&[(&str, &str)]) -> GitHashes { + HashMap::from_iter( + pairs + .iter() + .map(|(path, hash)| (RelativeUnixPathBuf::new(*path).unwrap(), hash.to_string())), + ) + } +} diff --git a/crates/turborepo-scm/Source/status.rs b/crates/turborepo-scm/Source/status.rs new file mode 100644 index 0000000000000..2a488084ba19b --- /dev/null +++ b/crates/turborepo-scm/Source/status.rs @@ -0,0 +1,141 @@ +use std::{ + io::{BufRead, BufReader, Read}, + process::{Command, Stdio}, +}; + +use nom::Finish; +use turbopath::{AbsoluteSystemPath, RelativeUnixPathBuf}; + +use crate::{Error, Git, package_deps::GitHashes, wait_for_success}; + +impl Git { + #[tracing::instrument(skip(self, root_path, hashes))] + pub(crate) fn append_git_status( + &self, + root_path:&AbsoluteSystemPath, + pkg_prefix:&RelativeUnixPathBuf, + hashes:&mut GitHashes, + ) -> Result, Error> { + let mut git = Command::new(self.bin.as_std_path()) + .args(["status", "--untracked-files", "--no-renames", "-z", "--", "."]) + .env("GIT_OPTIONAL_LOCKS", "0") + .current_dir(root_path) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + + let stdout = git + .stdout + .as_mut() + .ok_or_else(|| Error::git_error("failed to get stdout for git status"))?; + let mut stderr = git + .stderr + .take() + .ok_or_else(|| Error::git_error("failed to get stderr for git status"))?; + let parse_result = read_status(stdout, root_path, pkg_prefix, hashes); + wait_for_success(git, &mut stderr, "git status", root_path, parse_result) + } +} + +fn read_status( + reader:R, + root_path:&AbsoluteSystemPath, + pkg_prefix:&RelativeUnixPathBuf, + hashes:&mut GitHashes, +) -> Result, Error> { + let mut to_hash = Vec::new(); + let mut reader = BufReader::new(reader); + let mut buffer = Vec::new(); + while reader.read_until(b'\0', &mut buffer)? != 0 { + let entry = parse_status(&buffer)?; + let path = RelativeUnixPathBuf::new(String::from_utf8(entry.filename.to_owned())?)?; + if entry.is_delete { + let path = path.strip_prefix(pkg_prefix).map_err(|_| { + Error::git_error(format!( + "'git status --untracked-files --no-renames -z -- .' run in {} found a \ + deleted file {} that did not have the expected prefix: {}", + root_path, path, pkg_prefix + )) + })?; + hashes.remove(&path); + } else { + to_hash.push(path); + } + buffer.clear(); + } + Ok(to_hash) +} + +struct StatusEntry<'a> { + filename:&'a [u8], + is_delete:bool, +} + +fn parse_status(i:&[u8]) -> Result, Error> { + match nom::combinator::all_consuming(nom_parse_status)(i).finish() { + Ok((_, tup)) => Ok(tup), + Err(e) => { + Err(Error::git_error(format!( + "failed to parse git-status: {}", + String::from_utf8_lossy(e.input) + ))) + }, + } +} + +fn nom_parse_status(i:&[u8]) -> nom::IResult<&[u8], StatusEntry<'_>> { + let (i, x) = nom::bytes::complete::take(1usize)(i)?; + let (i, y) = nom::bytes::complete::take(1usize)(i)?; + let (i, _) = nom::character::complete::space1(i)?; + let (i, filename) = nom::bytes::complete::is_not("\0")(i)?; + // We explicitly support a missing terminator + let (i, _) = nom::combinator::opt(nom::bytes::complete::tag(b"\0"))(i)?; + Ok((i, StatusEntry { filename, is_delete:x[0] == b'D' || y[0] == b'D' })) +} + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf, RelativeUnixPathBufTestExt}; + + use super::read_status; + use crate::package_deps::GitHashes; + + #[test] + fn test_status() { + let root_path = AbsoluteSystemPathBuf::cwd().unwrap(); + let tests:&[(&str, &str, (&str, bool))] = &[ + ("AD my-pkg/package.json\0", "my-pkg", ("package.json", true)), + ( + // no trailing NUL + "AD some-pkg/package.json", + "some-pkg", + ("package.json", true), + ), + ("M package.json\0", "", ("package.json", false)), + ("A some-pkg/some-file\0", "some-pkg", ("some-file", false)), + ("M some-pkg/file with spaces\0", "some-pkg", ("file with spaces", false)), + ]; + for (input, prefix, (expected_filename, expect_delete)) in tests { + let prefix = RelativeUnixPathBuf::new(*prefix).unwrap(); + let mut hashes = to_hash_map(&[(expected_filename, "some-hash")]); + let to_hash = read_status(input.as_bytes(), &root_path, &prefix, &mut hashes).unwrap(); + if *expect_delete { + assert_eq!(hashes.len(), 0, "input: {}", input); + } else { + assert_eq!(to_hash.len(), 1, "input: {}", input); + let expected = prefix.join(&RelativeUnixPathBuf::new(*expected_filename).unwrap()); + assert_eq!(to_hash[0], expected); + } + } + } + + fn to_hash_map(pairs:&[(&str, &str)]) -> GitHashes { + HashMap::from_iter( + pairs + .iter() + .map(|(path, hash)| (RelativeUnixPathBuf::new(*path).unwrap(), hash.to_string())), + ) + } +} diff --git a/crates/turborepo-scm/fixtures/01-git-hash-object/.gitignore b/crates/turborepo-scm/fixtures/01-git-hash-object/.gitignore deleted file mode 100644 index d8e19507425ea..0000000000000 --- a/crates/turborepo-scm/fixtures/01-git-hash-object/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -"quote" -new*line diff --git a/crates/turborepo-scm/fixtures/01-git-hash-object/child/child.json b/crates/turborepo-scm/fixtures/01-git-hash-object/child/child.json deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/crates/turborepo-scm/fixtures/01-git-hash-object/child/grandchild/grandchild.json b/crates/turborepo-scm/fixtures/01-git-hash-object/child/grandchild/grandchild.json deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/crates/turborepo-scm/fixtures/01-git-hash-object/root.json b/crates/turborepo-scm/fixtures/01-git-hash-object/root.json deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/crates/turborepo-scm/src/git.rs b/crates/turborepo-scm/src/git.rs deleted file mode 100644 index c9f57e454f4d8..0000000000000 --- a/crates/turborepo-scm/src/git.rs +++ /dev/null @@ -1,1314 +0,0 @@ -use std::{ - backtrace::Backtrace, - collections::HashSet, - env::{self, VarError}, - fs::{self}, - path::PathBuf, - process::Command, -}; - -use serde::Deserialize; -use tracing::warn; -use turbopath::{ - AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPathBuf, RelativeUnixPath, -}; -use turborepo_ci::Vendor; - -use crate::{Error, Git, SCM}; - -#[derive(Debug, PartialEq, Eq)] -pub struct InvalidRange { - pub from_ref: Option, - pub to_ref: Option, -} - -impl SCM { - pub fn get_current_branch(&self, path: &AbsoluteSystemPath) -> Result { - match self { - Self::Git(git) => git.get_current_branch(), - Self::Manual => Err(Error::GitRequired(path.to_owned())), - } - } - - pub fn get_current_sha(&self, path: &AbsoluteSystemPath) -> Result { - match self { - Self::Git(git) => git.get_current_sha(), - Self::Manual => Err(Error::GitRequired(path.to_owned())), - } - } - - pub fn changed_files( - &self, - turbo_root: &AbsoluteSystemPath, - from_commit: Option<&str>, - to_commit: Option<&str>, - include_uncommitted: bool, - allow_unknown_objects: bool, - merge_base: bool, - ) -> Result, InvalidRange>, Error> { - fn unable_to_detect_range( - error: impl std::error::Error, - from_ref: Option, - to_ref: Option, - ) -> Result, InvalidRange>, Error> { - warn!( - "unable to detect git range, assuming all files have changed: {}", - error - ); - Ok(Err(InvalidRange { from_ref, to_ref })) - } - match self { - Self::Git(git) => { - match git.changed_files( - turbo_root, - from_commit, - to_commit, - include_uncommitted, - merge_base, - ) { - Ok(files) => Ok(Ok(files)), - Err(ref error @ Error::Git(ref message, _)) - if allow_unknown_objects - && (message.contains("no merge base") - || message.contains("bad object")) => - { - unable_to_detect_range( - error, - from_commit.map(|c| c.to_string()), - to_commit.map(|c| c.to_string()), - ) - } - Err(Error::UnableToResolveRef) => unable_to_detect_range( - Error::UnableToResolveRef, - from_commit.map(|c| c.to_string()), - to_commit.map(|c| c.to_string()), - ), - Err(e) => Err(e), - } - } - Self::Manual => Err(Error::GitRequired(turbo_root.to_owned())), - } - } - - pub fn previous_content( - &self, - from_commit: Option<&str>, - file_path: &AbsoluteSystemPath, - ) -> Result, Error> { - match self { - Self::Git(git) => git.previous_content(from_commit, file_path), - Self::Manual => Err(Error::GitRequired(file_path.to_owned())), - } - } -} - -const UNKNOWN_SHA: &str = "0000000000000000000000000000000000000000"; - -#[derive(Debug, Deserialize, Clone)] -struct GitHubCommit { - id: String, -} - -#[derive(Debug, Deserialize, Default)] -struct GitHubEvent { - #[serde(default)] - before: String, - - #[serde(default)] - commits: Vec, - - #[serde(default)] - forced: bool, -} - -impl GitHubEvent { - fn get_parent_ref_of_first_commit(&self) -> Option { - if self.commits.is_empty() { - // commits can be empty when you push a branch with no commits - return None; - } - - if self.commits.len() >= 2048 { - // GitHub API limit for number of commits shown in this field - return None; - } - - // Extract the base ref from the push event - let first_commit = self.commits.first()?; - let id = &first_commit.id; - Some(format!("{id}^")) - } -} - -#[derive(Debug)] -pub struct CIEnv { - is_github_actions: bool, - github_base_ref: Result, - github_event_path: Result, -} - -impl Default for CIEnv { - fn default() -> Self { - Self::new() - } -} - -impl CIEnv { - pub fn new() -> Self { - Self { - is_github_actions: Vendor::is("GitHub Actions"), - github_base_ref: env::var("GITHUB_BASE_REF"), - github_event_path: env::var("GITHUB_EVENT_PATH"), - } - } - pub fn none() -> Self { - Self { - is_github_actions: false, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Err(VarError::NotPresent), - } - } -} - -impl Git { - fn get_current_branch(&self) -> Result { - let output = self.execute_git_command(&["branch", "--show-current"], "")?; - let output = String::from_utf8(output)?; - Ok(output.trim().to_owned()) - } - - fn get_current_sha(&self) -> Result { - let output = self.execute_git_command(&["rev-parse", "HEAD"], "")?; - let output = String::from_utf8(output)?; - Ok(output.trim().to_owned()) - } - - /// for GitHub Actions environment variables, see: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables - pub fn get_github_base_ref(base_ref_env: CIEnv) -> Option { - // make sure we're running in a CI environment - if !base_ref_env.is_github_actions { - return None; - } - - /* - * The name of the base ref or target branch of the pull request in a - * workflow run. - * - * This variable only has a value when the event that triggers a workflow run - * is either `pull_request` or `pull_request_target`. - * For example, `main` - * - * So environment variable is empty in a regular commit - */ - if let Ok(pr) = base_ref_env.github_base_ref { - if !pr.is_empty() { - return Some(pr); - } - } - - // we must be in a push event - // try reading from the GITHUB_EVENT_PATH file - if let Ok(event_path) = base_ref_env.github_event_path { - // Try to open the event file and read the contents - let data = fs::read_to_string(event_path).ok()?; - - // Parse the JSON data from the file - let json: GitHubEvent = serde_json::from_str(&data).ok()?; - - // Extract the base ref from the pull request event if available - let base_ref = &json.before; - - // the base_ref will be UNKNOWN_SHA on first push - // we also use this behavior in force pushes - if base_ref == UNKNOWN_SHA || json.forced { - return json.get_parent_ref_of_first_commit(); - } - - if base_ref.is_empty() { - return None; - } - - return Some(base_ref.to_string()); - } - None - } - - fn resolve_base(&self, base_override: Option<&str>, env: CIEnv) -> Result { - if let Some(valid_from) = base_override { - return Ok(valid_from.to_string()); - } - - if let Some(github_base_ref) = Self::get_github_base_ref(env) { - // we don't fall through to checking against main or master - // because at this point we know we're in a GITHUB CI environment - // and we should really know by now what the base ref is - // so it's better to just error if something went wrong - return match self.execute_git_command(&["rev-parse", &github_base_ref], "") { - Ok(_) => { - eprintln!("Resolved base ref from GitHub Actions event: {github_base_ref}"); - Ok(github_base_ref) - } - Err(e) => { - eprintln!( - "Failed to resolve base ref '{github_base_ref}' from GitHub Actions \ - event: {e}" - ); - Err(Error::UnableToResolveRef) - } - }; - } - - let main_result = self.execute_git_command(&["rev-parse", "main"], ""); - if main_result.is_ok() { - return Ok("main".to_string()); - } - - let master_result = self.execute_git_command(&["rev-parse", "master"], ""); - if master_result.is_ok() { - return Ok("master".to_string()); - } - Err(Error::UnableToResolveRef) - } - - fn changed_files( - &self, - turbo_root: &AbsoluteSystemPath, - from_commit: Option<&str>, - to_commit: Option<&str>, - include_uncommitted: bool, - merge_base: bool, - ) -> Result, Error> { - let turbo_root_relative_to_git_root = self.root.anchor(turbo_root)?; - let pathspec = turbo_root_relative_to_git_root.as_str(); - - let mut files = HashSet::new(); - - let valid_from = self.resolve_base(from_commit, CIEnv::new())?; - - // If a to commit is not specified for `diff-tree` it will change the comparison - // to be between the provided commit and it's parent - let to_commit = to_commit.unwrap_or("HEAD"); - let mut args = vec![ - "diff-tree", - "-r", - "--name-only", - "--no-commit-id", - &valid_from, - to_commit, - ]; - - if merge_base { - args.push("--merge-base"); - } - - let output = self.execute_git_command(&args, pathspec)?; - self.add_files_from_stdout(&mut files, turbo_root, output); - - // We only care about non-tracked files if we haven't specified both ends up the - // comparison - if include_uncommitted { - // Add untracked files or unstaged changes, i.e. files that are not in git at - // all - let ls_files_output = self.execute_git_command( - &["ls-files", "--others", "--modified", "--exclude-standard"], - pathspec, - )?; - self.add_files_from_stdout(&mut files, turbo_root, ls_files_output); - // Include any files that have been staged, but not committed - let diff_output = - self.execute_git_command(&["diff", "--name-only", "--cached"], pathspec)?; - self.add_files_from_stdout(&mut files, turbo_root, diff_output); - } - - Ok(files) - } - - fn execute_git_command(&self, args: &[&str], pathspec: &str) -> Result, Error> { - let mut command = Command::new(self.bin.as_std_path()); - command - .args(args) - .current_dir(&self.root) - .env("GIT_OPTIONAL_LOCKS", "0"); - - if !pathspec.is_empty() { - command.arg("--").arg(pathspec); - } - - let output = command.output()?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - Err(Error::Git(stderr, Backtrace::capture())) - } else { - Ok(output.stdout) - } - } - - fn add_files_from_stdout( - &self, - files: &mut HashSet, - turbo_root: &AbsoluteSystemPath, - stdout: Vec, - ) { - let stdout = String::from_utf8(stdout).unwrap(); - for line in stdout.lines() { - let path = RelativeUnixPath::new(line).unwrap(); - let anchored_to_turbo_root_file_path = self - .reanchor_path_from_git_root_to_turbo_root(turbo_root, path) - .unwrap(); - files.insert(anchored_to_turbo_root_file_path); - } - } - - fn reanchor_path_from_git_root_to_turbo_root( - &self, - turbo_root: &AbsoluteSystemPath, - path: &RelativeUnixPath, - ) -> Result { - let absolute_file_path = self.root.join_unix_path(path); - let anchored_to_turbo_root_file_path = turbo_root.anchor(&absolute_file_path)?; - Ok(anchored_to_turbo_root_file_path) - } - - fn previous_content( - &self, - from_commit: Option<&str>, - file_path: &AbsoluteSystemPath, - ) -> Result, Error> { - let anchored_file_path = self.root.anchor(file_path)?; - let valid_from = self.resolve_base(from_commit, CIEnv::new())?; - let arg = format!("{}:{}", valid_from, anchored_file_path.as_str()); - - self.execute_git_command(&["show", &arg], "") - } -} - -/// Finds the content of a file at a previous commit. Assumes file is in a git -/// repository -/// -/// # Arguments -/// -/// * `git_root`: The root of the repository -/// * `from_commit`: The commit hash to checkout -/// * `file_path`: The path to the file -/// -/// returns: Result -pub fn previous_content( - git_root: PathBuf, - from_commit: Option<&str>, - file_path: String, -) -> Result, Error> { - // If git root is not absolute, we error. - let git_root = AbsoluteSystemPathBuf::try_from(git_root)?; - let scm = SCM::new(&git_root); - - // However for file path we handle both absolute and relative paths - // Note that we assume any relative file path is relative to the git root - // FIXME: this is probably wrong. We should know the path to the lockfile - // exactly - let absolute_file_path = AbsoluteSystemPathBuf::from_unknown(&git_root, file_path); - - scm.previous_content(from_commit, &absolute_file_path) -} - -#[cfg(test)] -mod tests { - use std::{ - assert_matches::assert_matches, - collections::HashSet, - env::VarError, - fs, - path::{Path, PathBuf}, - process::Command, - }; - - use git2::{Oid, Repository, RepositoryInitOptions}; - use tempfile::{NamedTempFile, TempDir}; - use test_case::test_case; - use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathError}; - use which::which; - - use super::{previous_content, CIEnv, InvalidRange}; - use crate::{ - git::{GitHubCommit, GitHubEvent}, - Error, Git, SCM, - }; - - fn setup_repository( - init_opts: Option<&RepositoryInitOptions>, - ) -> Result<(TempDir, Repository), Error> { - let repo_root = tempfile::tempdir()?; - let repo = Repository::init_opts( - repo_root.path(), - init_opts.unwrap_or(&RepositoryInitOptions::new()), - ) - .unwrap(); - let mut config = repo.config().unwrap(); - config.set_str("user.name", "test").unwrap(); - config.set_str("user.email", "test@example.com").unwrap(); - - Ok((repo_root, repo)) - } - - fn changed_files( - git_root: PathBuf, - turbo_root: PathBuf, - from_commit: Option<&str>, - to_commit: Option<&str>, - include_uncommitted: bool, - ) -> Result, Error> { - let git_root = AbsoluteSystemPath::from_std_path(&git_root)?; - let scm = SCM::new(git_root); - - let turbo_root = AbsoluteSystemPathBuf::try_from(turbo_root.as_path())?; - // Replicating the `--filter` behavior where we only do a merge base - // if both ends of the git range are specified. - let merge_base = to_commit.is_some(); - let Ok(files) = scm.changed_files( - &turbo_root, - from_commit, - to_commit, - include_uncommitted, - false, - merge_base, - )? - else { - unreachable!("changed_files should always return Some"); - }; - - Ok(files - .into_iter() - .map(|f| f.to_string()) - .collect::>()) - } - - fn commit_file(repo: &Repository, path: &Path, previous_commit: Option) -> Oid { - let mut index = repo.index().unwrap(); - index.add_path(path).unwrap(); - let tree_oid = index.write_tree().unwrap(); - index.write().unwrap(); - let tree = repo.find_tree(tree_oid).unwrap(); - let previous_commit = previous_commit - .map(|oid| repo.find_commit(oid)) - .transpose() - .unwrap(); - - repo.commit( - Some("HEAD"), - &repo.signature().unwrap(), - &repo.signature().unwrap(), - "Commit", - &tree, - previous_commit - .as_ref() - .as_ref() - .map(std::slice::from_ref) - .unwrap_or_default(), - ) - .unwrap() - } - - fn commit_delete(repo: &Repository, path: &Path, previous_commit: Oid) -> Oid { - let mut index = repo.index().unwrap(); - index.remove_path(path).unwrap(); - let tree_oid = index.write_tree().unwrap(); - index.write().unwrap(); - let tree = repo.find_tree(tree_oid).unwrap(); - let previous_commit = repo.find_commit(previous_commit).unwrap(); - - repo.commit( - Some("HEAD"), - &repo.signature().unwrap(), - &repo.signature().unwrap(), - "Commit", - &tree, - std::slice::from_ref(&&previous_commit), - ) - .unwrap() - } - - fn commit_rename(repo: &Repository, source: &Path, dest: &Path, previous_commit: Oid) -> Oid { - let mut index = repo.index().unwrap(); - index.remove_path(source).unwrap(); - index.add_path(dest).unwrap(); - let tree_oid = index.write_tree().unwrap(); - index.write().unwrap(); - let tree = repo.find_tree(tree_oid).unwrap(); - let previous_commit = repo.find_commit(previous_commit).unwrap(); - - repo.commit( - Some("HEAD"), - &repo.signature().unwrap(), - &repo.signature().unwrap(), - "Commit", - &tree, - std::slice::from_ref(&&previous_commit), - ) - .unwrap() - } - - #[test] - fn test_shallow_clone() -> Result<(), Error> { - let tmp_dir = tempfile::tempdir()?; - - let git_binary = which("git")?; - let output = Command::new(git_binary) - .args([ - "clone", - "--depth", - "2", - "https://github.com/vercel/app-playground.git", - tmp_dir.path().to_str().unwrap(), - ]) - .output()?; - assert!(output.status.success()); - - assert!(changed_files( - tmp_dir.path().to_owned(), - tmp_dir.path().to_owned(), - Some("HEAD~1"), - Some("HEAD"), - false, - ) - .is_ok()); - - assert!(changed_files( - tmp_dir.path().to_owned(), - tmp_dir.path().to_owned(), - Some("HEAD"), - None, - true, - ) - .is_ok()); - - Ok(()) - } - - #[test] - fn test_deleted_files() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - - let file = repo_root.path().join("foo.js"); - let file_path = Path::new("foo.js"); - fs::write(&file, "let z = 0;")?; - - let first_commit_oid = commit_file(&repo, file_path, None); - - fs::remove_file(&file)?; - let _second_commit_oid = commit_delete(&repo, file_path, first_commit_oid); - - let first_commit_sha = first_commit_oid.to_string(); - let git_root = repo_root.path().to_owned(); - let turborepo_root = repo_root.path().to_owned(); - let files = changed_files( - git_root, - turborepo_root, - Some(&first_commit_sha), - Some("HEAD"), - false, - )?; - - assert_eq!(files, HashSet::from(["foo.js".to_string()])); - Ok(()) - } - - #[test] - fn test_renamed_files() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - - let file = repo_root.path().join("foo.js"); - let file_path = Path::new("foo.js"); - fs::write(&file, "let z = 0;")?; - - let first_commit_oid = commit_file(&repo, file_path, None); - - fs::rename(file, repo_root.path().join("bar.js")).unwrap(); - - let new_file_path = Path::new("bar.js"); - let _second_commit_oid = commit_rename(&repo, file_path, new_file_path, first_commit_oid); - - let first_commit_sha = first_commit_oid.to_string(); - let git_root = repo_root.path().to_owned(); - let turborepo_root = repo_root.path().to_owned(); - let files = changed_files( - git_root, - turborepo_root, - Some(&first_commit_sha), - Some("HEAD"), - false, - )?; - - assert_eq!( - files, - HashSet::from(["foo.js".to_string(), "bar.js".to_string()]) - ); - Ok(()) - } - #[test] - fn test_merge_base() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - let first_file = repo_root.path().join("foo.js"); - fs::write(first_file, "let z = 0;")?; - // Create a base commit. This will *not* be the merge base - let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); - - let second_file = repo_root.path().join("bar.js"); - fs::write(second_file, "let y = 1;")?; - // This commit will be the merge base - let second_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(first_commit_oid)); - - let third_file = repo_root.path().join("baz.js"); - fs::write(third_file, "let x = 2;")?; - // Create a first commit off of merge base - let third_commit_oid = commit_file(&repo, Path::new("baz.js"), Some(second_commit_oid)); - - // Move head back to merge base - repo.set_head_detached(second_commit_oid).unwrap(); - let fourth_file = repo_root.path().join("qux.js"); - fs::write(fourth_file, "let w = 3;")?; - // Create a second commit off of merge base - let fourth_commit_oid = commit_file(&repo, Path::new("qux.js"), Some(second_commit_oid)); - - repo.set_head_detached(third_commit_oid).unwrap(); - let merge_base = repo - .merge_base(third_commit_oid, fourth_commit_oid) - .unwrap(); - - assert_eq!(merge_base, second_commit_oid); - - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().to_path_buf(), - Some(&third_commit_oid.to_string()), - Some(&fourth_commit_oid.to_string()), - false, - )?; - - assert_eq!( - files, - HashSet::from(["qux.js".to_string(), "baz.js".to_string()]) - ); - - Ok(()) - } - - #[test] - fn test_changed_files() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - let mut index = repo.index().unwrap(); - let turbo_root = repo_root.path(); - let file = repo_root.path().join("foo.js"); - fs::write(file, "let z = 0;")?; - - // First commit (we need a base commit to compare against) - let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); - - // Now change another file - let new_file = repo_root.path().join("bar.js"); - fs::write(new_file, "let y = 1;")?; - - // Test that uncommitted file is marked as changed - let files = changed_files( - repo_root.path().to_path_buf(), - turbo_root.to_path_buf(), - Some("HEAD"), - None, - true, - )?; - assert_eq!(files, HashSet::from(["bar.js".to_string()])); - - // Test that uncommitted file in index is not marked as changed when not - // checking uncommitted - let files = changed_files( - repo_root.path().to_path_buf(), - turbo_root.to_path_buf(), - Some("HEAD"), - None, - false, - )?; - assert_eq!(files, HashSet::new()); - - // Test that uncommitted file in index is marked as changed when - // checking uncommitted - let files = changed_files( - repo_root.path().to_path_buf(), - turbo_root.to_path_buf(), - Some("HEAD"), - None, - true, - )?; - assert_eq!(files, HashSet::from(["bar.js".to_string()])); - - // Add file to index - index.add_path(Path::new("bar.js")).unwrap(); - index.write().unwrap(); - - // Test that uncommitted file in index is not marked as changed when not - // checking uncommitted - let files = changed_files( - repo_root.path().to_path_buf(), - turbo_root.to_path_buf(), - Some("HEAD"), - None, - false, - )?; - assert_eq!(files, HashSet::new()); - - // Test that uncommitted file in index is still marked as changed - let files = changed_files( - repo_root.path().to_path_buf(), - turbo_root.to_path_buf(), - Some("HEAD"), - None, - true, - )?; - assert_eq!(files, HashSet::from(["bar.js".to_string()])); - - // Now commit file - let second_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(first_commit_oid)); - - // Test that only second file is marked as changed when we check commit range - let files = changed_files( - repo_root.path().to_path_buf(), - turbo_root.to_path_buf(), - Some(first_commit_oid.to_string().as_str()), - Some(second_commit_oid.to_string().as_str()), - false, - )?; - assert_eq!(files, HashSet::from(["bar.js".to_string()])); - - // Create a file nested in subdir - fs::create_dir_all(repo_root.path().join("subdir"))?; - let new_file = repo_root.path().join("subdir").join("baz.js"); - fs::write(new_file, "let x = 2;")?; - - // The new directory and files are not yet committed, they shouldn't show up. - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().to_path_buf(), - Some(first_commit_oid.to_string().as_str()), - Some(second_commit_oid.to_string().as_str()), - false, - )?; - assert_eq!(files, HashSet::from(["bar.js".to_string()])); - - // Since we are only specifying the first commit, the new file should show up - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().to_path_buf(), - Some(second_commit_oid.to_string().as_str()), - None, - true, - )?; - assert_eq!( - files, - HashSet::from([format!("subdir{}baz.js", std::path::MAIN_SEPARATOR)]) - ); - - // Commit the new file so it shows up in the changed files - let third_commit_oid = commit_file( - &repo, - &Path::new("subdir").join("baz.js"), - Some(second_commit_oid), - ); - - // Test that `turbo_root` filters out files not in the specified directory - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().join("subdir"), - Some(first_commit_oid.to_string().as_str()), - Some(third_commit_oid.to_string().as_str()), - false, - )?; - assert_eq!(files, HashSet::from(["baz.js".to_string()])); - - Ok(()) - } - - #[test] - fn test_changed_files_with_root_as_relative() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - let file = repo_root.path().join("foo.js"); - fs::write(file, "let z = 0;")?; - - // First commit (we need a base commit to compare against) - commit_file(&repo, Path::new("foo.js"), None); - - // Now change another file - let new_file = repo_root.path().join("bar.js"); - fs::write(new_file, "let y = 1;")?; - - // Test that uncommitted file is marked as changed with the parameters that Go - // will pass - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().to_path_buf(), - Some("HEAD"), - None, - true, - )?; - assert_eq!(files, HashSet::from(["bar.js".to_string()])); - - Ok(()) - } - - // Tests that we can use a subdir as the turbo_root path - // (occurs when the monorepo is nested inside a subdirectory of git repository) - #[test] - fn test_changed_files_with_subdir_as_turbo_root() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - - fs::create_dir(repo_root.path().join("subdir"))?; - // Create additional nested directory to test that we return a system path - // and not a normalized unix path - fs::create_dir(repo_root.path().join("subdir").join("src"))?; - - let file = repo_root.path().join("subdir").join("foo.js"); - fs::write(file, "let z = 0;")?; - let first_commit = commit_file(&repo, Path::new("subdir/foo.js"), None); - - let new_file = repo_root.path().join("subdir").join("src").join("bar.js"); - fs::write(new_file, "let y = 1;")?; - - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().join("subdir"), - Some("HEAD"), - None, - true, - )?; - - #[cfg(unix)] - { - assert_eq!(files, HashSet::from(["src/bar.js".to_string()])); - } - - #[cfg(windows)] - { - assert_eq!(files, HashSet::from(["src\\bar.js".to_string()])); - } - - commit_file(&repo, Path::new("subdir/src/bar.js"), Some(first_commit)); - - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().join("subdir"), - Some(first_commit.to_string().as_str()), - Some( - repo.head() - .unwrap() - .peel_to_commit() - .unwrap() - .id() - .to_string() - .as_str(), - ), - false, - )?; - - #[cfg(unix)] - { - assert_eq!(files, HashSet::from(["src/bar.js".to_string()])); - } - - #[cfg(windows)] - { - assert_eq!(files, HashSet::from(["src\\bar.js".to_string()])); - } - - Ok(()) - } - - #[test] - fn test_previous_content() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - - let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); - let file = root.join_component("foo.js"); - file.create_with_contents("let z = 0;")?; - - let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); - fs::write(&file, "let z = 1;")?; - let second_commit_oid = commit_file(&repo, Path::new("foo.js"), Some(first_commit_oid)); - - let content = previous_content( - repo_root.path().to_path_buf(), - Some(first_commit_oid.to_string().as_str()), - file.to_string(), - )?; - - assert_eq!(content, b"let z = 0;"); - - let content = previous_content( - repo_root.path().to_path_buf(), - Some(second_commit_oid.to_string().as_str()), - file.to_string(), - )?; - assert_eq!(content, b"let z = 1;"); - - let content = previous_content( - repo_root.path().to_path_buf(), - Some(second_commit_oid.to_string().as_str()), - "foo.js".to_string(), - )?; - assert_eq!(content, b"let z = 1;"); - - Ok(()) - } - - #[test] - fn test_revparse() -> Result<(), Error> { - let (repo_root, repo) = setup_repository(None)?; - let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); - - let file = root.join_component("foo.js"); - file.create_with_contents("let z = 0;")?; - - let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None); - fs::write(&file, "let z = 1;")?; - let second_commit_oid = commit_file(&repo, Path::new("foo.js"), Some(first_commit_oid)); - - let revparsed_head = repo.revparse_single("HEAD").unwrap(); - assert_eq!(revparsed_head.id(), second_commit_oid); - let revparsed_head_minus_1 = repo.revparse_single("HEAD~1").unwrap(); - assert_eq!(revparsed_head_minus_1.id(), first_commit_oid); - - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().to_path_buf(), - Some("HEAD^"), - Some("HEAD"), - false, - )?; - assert_eq!(files, HashSet::from(["foo.js".to_string()])); - - let content = previous_content( - repo_root.path().to_path_buf(), - Some("HEAD^"), - file.to_string(), - )?; - assert_eq!(content, b"let z = 0;"); - - let new_file = repo_root.path().join("bar.js"); - fs::write(new_file, "let y = 0;")?; - let third_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(second_commit_oid)); - let third_commit = repo.find_commit(third_commit_oid).unwrap(); - repo.branch("release-1", &third_commit, false).unwrap(); - - let files = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().to_path_buf(), - Some("HEAD~1"), - Some("release-1"), - false, - )?; - assert_eq!(files, HashSet::from(["bar.js".to_string()])); - - Ok(()) - } - - #[test_case(vec!["main"], None, Some("main"))] - #[test_case(vec!["master"], None, Some("master"))] - #[test_case(vec!["ziltoid"], None, None)] - #[test_case(vec!["ziltoid", "main"], Some("ziltoid"), Some("ziltoid"))] - #[test_case(vec!["ziltoid", "main"], Some("main"), Some("main"))] - #[test_case(vec!["ziltoid", "main"], None, Some("main"))] - #[test_case(vec!["ziltoid", "master"], Some("ziltoid"), Some("ziltoid"))] - #[test_case(vec!["ziltoid", "master"], Some("master"), Some("master"))] - #[test_case(vec!["ziltoid", "master"], None, Some("master"))] - #[test_case(vec!["ziltoid", "master", "main"], Some("ziltoid"), Some("ziltoid"))] - #[test_case(vec!["ziltoid", "master", "main"], Some("master"), Some("master"))] - #[test_case(vec!["ziltoid", "master", "main"], Some("main"), Some("main"))] - #[test_case(vec!["ziltoid", "master", "main"], None, Some("main"))] - fn test_base_resolution( - branches_to_create: Vec<&str>, - target_branch: Option<&str>, - expected: Option<&str>, - ) -> Result<(), Error> { - let mut repo_opts = RepositoryInitOptions::new(); - - let (first_branch, remaining_branches) = branches_to_create.split_first().unwrap(); - - let repo_init = repo_opts.initial_head(first_branch); - let (repo_root, repo) = setup_repository(Some(repo_init))?; - let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); - - // WARNING: - // if you do not make a commit, git will show you that you have no branches. - let file = root.join_component("todo.txt"); - file.create_with_contents("1. make async Rust good")?; - let first_commit = commit_file(&repo, Path::new("todo.txt"), None); - let commit = repo.find_commit(first_commit).unwrap(); - - remaining_branches.iter().for_each(|branch| { - repo.branch(branch, &commit, true).unwrap(); - }); - - let thing = Git::find(&root).unwrap(); - let actual = thing.resolve_base(target_branch, CIEnv::none()).ok(); - - assert_eq!(actual.as_deref(), expected); - - Ok(()) - } - - #[test] - fn test_error_cases() -> Result<(), Error> { - let repo_dir = tempfile::tempdir()?; - let repo_does_not_exist = changed_files( - repo_dir.path().to_path_buf(), - repo_dir.path().to_path_buf(), - Some("HEAD"), - None, - true, - ); - - assert_matches!(repo_does_not_exist, Err(Error::GitRequired(_))); - - let (repo_root, _repo) = setup_repository(None)?; - let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); - - let commit_does_not_exist = changed_files( - repo_root.path().to_path_buf(), - repo_root.path().to_path_buf(), - Some("does-not-exist"), - None, - true, - ); - - assert_matches!(commit_does_not_exist, Err(Error::Git(_, _))); - - let file_does_not_exist = previous_content( - repo_root.path().to_path_buf(), - Some("HEAD"), - root.join_component("does-not-exist").to_string(), - ); - assert_matches!(file_does_not_exist, Err(Error::Git(_, _))); - - let turbo_root = tempfile::tempdir()?; - let turbo_root_is_not_subdir_of_git_root = changed_files( - repo_root.path().to_path_buf(), - turbo_root.path().to_path_buf(), - Some("HEAD"), - None, - true, - ); - - assert_matches!( - turbo_root_is_not_subdir_of_git_root, - Err(Error::Path(PathError::NotParent(_, _), _)) - ); - - Ok(()) - } - - #[test] - fn test_changed_files_no_base() -> Result<(), Error> { - let mut repo_opts = RepositoryInitOptions::new(); - - let repo_init = repo_opts.initial_head("my-main"); - let (repo_root, repo) = setup_repository(Some(repo_init))?; - let root = AbsoluteSystemPathBuf::try_from(repo_root.path()).unwrap(); - - // WARNING: - // if you do not make a commit, git will show you that you have no branches. - let file = root.join_component("todo.txt"); - file.create_with_contents("1. explain why async Rust is good")?; - let _first_commit = commit_file(&repo, Path::new("todo.txt"), None); - - let scm = SCM::new(&root); - let actual = scm - .changed_files(&root, None, Some("HEAD"), true, true, false) - .unwrap(); - - assert_eq!( - actual, - Err(InvalidRange { - from_ref: None, - to_ref: Some("HEAD".to_string()), - }) - ); - - Ok(()) - } - - struct TestCase { - env: CIEnv, - event_json: &'static str, - } - - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Err(VarError::NotPresent), - }, - event_json: r#""#, - }, - None - ; "GITHUB_BASE_REF and GITHUB_EVENT_PATH are not set" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Ok("".to_string()), - github_event_path: Err(VarError::NotPresent), - }, - event_json: r#""#, - }, - None - ; "GITHUB_BASE_REF is set to an empty string" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Ok("The choice is yours, and yours alone".to_string()), - github_event_path: Err(VarError::NotPresent), - }, - event_json: r#""#, - }, - Some("The choice is yours, and yours alone") - ; "GITHUB_BASE_REF is set to a non-empty string" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("Olmec refused to give up the location of the Shrine of the Silver Monkey".to_string()), - }, - event_json: r#""#, - }, - None - ; "GITHUB_EVENT_PATH is set, but the file fails to open" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("the_room_of_the_three_gargoyles.json".to_string()), - }, - event_json: r#"first you must pass the temple guards!"#, - }, - None - ; "GITHUB_EVENT_PATH is set, is not valid JSON" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("olmecs_temple.json".to_string()), - }, - event_json: r#"{}"#, - }, - None - ; "no 'before' key in the JSON" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("olmecs_temple.json".to_string()), - }, - event_json: r#"{"forced":true}"#, - }, - None - ; "force push" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), - }, - event_json: r#"{"before":"e83c5163316f89bfbde7d9ab23ca2e25604af290"}"#, - }, - Some("e83c5163316f89bfbde7d9ab23ca2e25604af290") - ; "found a valid 'before' key in the JSON" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), - }, - event_json: r#"{"before":"0000000000000000000000000000000000000000"}"#, - }, - None - ; "UNKNOWN_SHA but no commits found" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), - }, - event_json: r#"{"before":"0000000000000000000000000000000000000000","commits":[]}"#, - }, - None - ; "empty commits" - )] - #[test_case( - TestCase { - env: CIEnv { - is_github_actions: true, - github_base_ref: Err(VarError::NotPresent), - github_event_path: Ok("shrine_of_the_silver_monkey.json".to_string()), - }, - event_json: r#"{"before":"0000000000000000000000000000000000000000","commits":[{"id":"yep"}]}"#, - }, - Some("yep^") - ; "first commit has a parent" - )] - fn test_get_github_base_ref(test_case: TestCase, expected: Option<&str>) -> Result<(), Error> { - // note: we must bind here because otherwise the temporary file will be dropped - let temp_file = if test_case.env.github_event_path.is_ok() { - let temp_file = NamedTempFile::new().expect("Failed to create temporary file"); - fs::write(temp_file.path(), test_case.event_json) - .expect("Failed to write to temporary file"); - Ok(temp_file) - } else { - Err(VarError::NotPresent) - }; - - let actual = Git::get_github_base_ref(CIEnv { - is_github_actions: test_case.env.is_github_actions, - github_base_ref: test_case.env.github_base_ref, - github_event_path: temp_file - .as_ref() - .map(|p| p.path().to_str().unwrap().to_string()) - .map_err(|e| e.clone()), - }); - assert_eq!(actual, expected.map(|s| s.to_string())); - - Ok(()) - } - - #[test] - fn test_thousands_of_commits() { - let commits = vec![ - GitHubCommit { - id: "insert-famous-sha-here".to_string(), - }; - 2049 // 2049 is one over the limit - ]; - - let github_event = GitHubEvent { - before: "".to_string(), - commits, - forced: false, - }; - let actual = github_event.get_parent_ref_of_first_commit(); - - assert_eq!(None, actual); - } -} diff --git a/crates/turborepo-scm/src/hash_object.rs b/crates/turborepo-scm/src/hash_object.rs deleted file mode 100644 index b849ba23186be..0000000000000 --- a/crates/turborepo-scm/src/hash_object.rs +++ /dev/null @@ -1,123 +0,0 @@ -use tracing::Span; -use turbopath::{AbsoluteSystemPath, AnchoredSystemPathBuf, RelativeUnixPathBuf}; - -use crate::{package_deps::GitHashes, Error}; - -#[tracing::instrument(skip(git_root, hashes, to_hash))] -pub(crate) fn hash_objects( - git_root: &AbsoluteSystemPath, - pkg_path: &AbsoluteSystemPath, - to_hash: Vec, - hashes: &mut GitHashes, -) -> Result<(), Error> { - let parent = Span::current(); - for filename in to_hash { - let span = tracing::info_span!(parent: &parent, "hash_object", ?filename); - let _enter = span.enter(); - - let full_file_path = git_root.join_unix_path(filename); - match git2::Oid::hash_file(git2::ObjectType::Blob, &full_file_path) { - Ok(hash) => { - let package_relative_path = - AnchoredSystemPathBuf::relative_path_between(pkg_path, &full_file_path) - .to_unix(); - hashes.insert(package_relative_path, hash.to_string()); - } - Err(e) => { - // FIXME: we currently do not hash symlinks. "git hash-object" cannot handle - // them, and the Go implementation errors on them, switches to - // manual, and then skips them. For now, we'll skip them too. - if e.class() == git2::ErrorClass::Os - && full_file_path - .symlink_metadata() - .map(|md| md.is_symlink()) - .unwrap_or(false) - { - continue; - } else { - // For any other error, ensure we attach some context to it - return Err(Error::git2_error_context(e, full_file_path.to_string())); - } - } - } - } - Ok(()) -} - -#[cfg(test)] -mod test { - use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf, RelativeUnixPathBufTestExt}; - - use super::hash_objects; - use crate::{find_git_root, package_deps::GitHashes}; - - #[test] - fn test_read_object_hashes() { - // Note that cwd can be different based on where the test suite is running from - // or if the test is launched in debug mode from VSCode - let cwd = std::env::current_dir().unwrap(); - let cwd = AbsoluteSystemPathBuf::try_from(cwd).unwrap(); - let git_root = find_git_root(&cwd).unwrap(); - let fixture_path = git_root.join_components(&[ - "crates", - "turborepo-scm", - "fixtures", - "01-git-hash-object", - ]); - - let fixture_child_path = fixture_path.join_component("child"); - let git_root = find_git_root(&fixture_path).unwrap(); - - // paths for files here are relative to the package path. - let tests: Vec<(Vec<(&str, &str)>, &AbsoluteSystemPathBuf)> = vec![ - (vec![], &fixture_path), - ( - vec![ - ("../root.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), - ("child.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), - ( - "grandchild/grandchild.json", - "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", - ), - ], - &fixture_child_path, - ), - ]; - - for (to_hash, pkg_path) in tests { - let file_hashes: Vec<(RelativeUnixPathBuf, String)> = to_hash - .into_iter() - .map(|(raw, hash)| (RelativeUnixPathBuf::new(raw).unwrap(), String::from(hash))) - .collect(); - - let git_to_pkg_path = git_root.anchor(pkg_path).unwrap(); - let pkg_prefix = git_to_pkg_path.to_unix(); - - let expected_hashes = GitHashes::from_iter(file_hashes); - let mut hashes = GitHashes::new(); - let to_hash = expected_hashes.keys().map(|k| pkg_prefix.join(k)).collect(); - hash_objects(&git_root, pkg_path, to_hash, &mut hashes).unwrap(); - assert_eq!(hashes, expected_hashes); - } - - // paths for files here are relative to the package path. - let error_tests: Vec<(Vec<&str>, &AbsoluteSystemPathBuf)> = vec![ - // skipping test for outside of git repo, we now error earlier in the process - (vec!["nonexistent.json"], &fixture_path), - ]; - - for (to_hash, pkg_path) in error_tests { - let git_to_pkg_path = git_root.anchor(pkg_path).unwrap(); - let pkg_prefix = git_to_pkg_path.to_unix(); - - let to_hash = to_hash - .into_iter() - .map(|k| pkg_prefix.join(&RelativeUnixPathBuf::new(k).unwrap())) - .collect(); - - let mut hashes = GitHashes::new(); - let result = hash_objects(&git_root, pkg_path, to_hash, &mut hashes); - assert!(result.is_err()); - } - } -} diff --git a/crates/turborepo-scm/src/ls_tree.rs b/crates/turborepo-scm/src/ls_tree.rs deleted file mode 100644 index fddf6f3e0f61d..0000000000000 --- a/crates/turborepo-scm/src/ls_tree.rs +++ /dev/null @@ -1,145 +0,0 @@ -use std::{ - io::{BufRead, BufReader, Read}, - process::{Command, Stdio}, -}; - -use nom::Finish; -use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf}; - -use crate::{package_deps::GitHashes, wait_for_success, Error, Git}; - -impl Git { - #[tracing::instrument(skip(self))] - pub fn git_ls_tree(&self, root_path: &AbsoluteSystemPathBuf) -> Result { - let mut hashes = GitHashes::new(); - let mut git = Command::new(self.bin.as_std_path()) - .args(["ls-tree", "-r", "-z", "HEAD"]) - .env("GIT_OPTIONAL_LOCKS", "0") - .current_dir(root_path) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - - let stdout = git - .stdout - .as_mut() - .ok_or_else(|| Error::git_error("failed to get stdout for git ls-tree"))?; - let mut stderr = git - .stderr - .take() - .ok_or_else(|| Error::git_error("failed to get stderr for git ls-tree"))?; - let parse_result = read_ls_tree(stdout, &mut hashes); - wait_for_success(git, &mut stderr, "git ls-tree", root_path, parse_result)?; - Ok(hashes) - } -} - -fn read_ls_tree(reader: R, hashes: &mut GitHashes) -> Result<(), Error> { - let mut reader = BufReader::new(reader); - let mut buffer = Vec::new(); - while reader.read_until(b'\0', &mut buffer)? != 0 { - let entry = parse_ls_tree(&buffer)?; - let hash = String::from_utf8(entry.hash.to_vec())?; - let path = RelativeUnixPathBuf::new(String::from_utf8(entry.filename.to_vec())?)?; - hashes.insert(path, hash); - buffer.clear(); - } - Ok(()) -} - -struct LsTreeEntry<'a> { - filename: &'a [u8], - hash: &'a [u8], -} - -fn parse_ls_tree(i: &[u8]) -> Result, Error> { - let mut parser = nom::combinator::all_consuming(nom_parse_ls_tree); - match parser(i).finish() { - Ok((_, entry)) => Ok(entry), - Err(e) => Err(Error::git_error(format!( - "failed to parse git-ls-tree: {}", - String::from_utf8_lossy(e.input) - ))), - } -} - -fn nom_parse_ls_tree(i: &[u8]) -> nom::IResult<&[u8], LsTreeEntry<'_>> { - let (i, _) = nom::bytes::complete::is_not(" ")(i)?; - let (i, _) = nom::character::complete::space1(i)?; - let (i, _) = nom::bytes::complete::is_not(" ")(i)?; - let (i, _) = nom::character::complete::space1(i)?; - let (i, hash) = nom::bytes::complete::take(40usize)(i)?; - let (i, _) = nom::bytes::complete::take(1usize)(i)?; - let (i, filename) = nom::bytes::complete::is_not("\0")(i)?; - // We explicitly support a missing terminator - let (i, _) = nom::combinator::opt(nom::bytes::complete::tag(b"\0"))(i)?; - Ok((i, LsTreeEntry { filename, hash })) -} - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - - use turbopath::RelativeUnixPathBuf; - - use crate::{ls_tree::read_ls_tree, package_deps::GitHashes}; - - fn to_hash_map(pairs: &[(&str, &str)]) -> GitHashes { - HashMap::from_iter( - pairs - .iter() - .map(|(path, hash)| (RelativeUnixPathBuf::new(*path).unwrap(), hash.to_string())), - ) - } - - #[test] - fn test_ls_tree() { - let tests: &[(&str, &[(&str, &str)])] = &[ - ( - "100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\tpackage.json\0", - &[("package.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")], - ), - ( - // missing nul byte - "100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\tpackage.json", - &[("package.json", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")], - ), - ( - // We aren't attempting to use octal escapes here, it just looks like it - #[allow(clippy::octal_escapes)] - "100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\t\t\000100644 blob \ - e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\t\"\000100644 blob \ - 5b999efa470b056e329b4c23a73904e0794bdc2f\t\n\000100644 blob \ - f44f57fff95196c5f7139dfa0b96875f1e9650a9\t.gitignore\000100644 blob \ - 33dbaf21275ca2a5f460249d941cbc27d5da3121\tREADME.md\000040000 tree \ - 7360f2d292aec95907cebdcbb412a6bf2bd10f8a\tapps\000100644 blob \ - 9ec2879b24ce2c817296eebe2cb3846f8e4751ea\tpackage.json\000040000 tree \ - 5759aadaea2cde55468a61e7104eb0a9d86c1d30\tpackages\000100644 blob \ - 33d0621ee2f4da4a2f6f6bdd51a42618d181e337\tturbo.json\000100644 blob \ - 579f273c9536d324c20b2e8f0d7fe4784ed0d9df\tfile with spaces\0", - &[ - ("\t", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), - ("\"", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"), - ("\n", "5b999efa470b056e329b4c23a73904e0794bdc2f"), - (".gitignore", "f44f57fff95196c5f7139dfa0b96875f1e9650a9"), - ("README.md", "33dbaf21275ca2a5f460249d941cbc27d5da3121"), - ("apps", "7360f2d292aec95907cebdcbb412a6bf2bd10f8a"), - ("package.json", "9ec2879b24ce2c817296eebe2cb3846f8e4751ea"), - ("packages", "5759aadaea2cde55468a61e7104eb0a9d86c1d30"), - ("turbo.json", "33d0621ee2f4da4a2f6f6bdd51a42618d181e337"), - ( - "file with spaces", - "579f273c9536d324c20b2e8f0d7fe4784ed0d9df", - ), - ], - ), - ]; - for (input, expected) in tests { - let input_bytes = input.as_bytes(); - let mut hashes = GitHashes::new(); - let expected = to_hash_map(expected); - read_ls_tree(input_bytes, &mut hashes).unwrap(); - assert_eq!(hashes, expected); - } - } -} diff --git a/crates/turborepo-scm/src/manual.rs b/crates/turborepo-scm/src/manual.rs deleted file mode 100644 index c554ebf711a7c..0000000000000 --- a/crates/turborepo-scm/src/manual.rs +++ /dev/null @@ -1,455 +0,0 @@ -use std::io::{ErrorKind, Read}; - -use globwalk::fix_glob_pattern; -use hex::ToHex; -use ignore::WalkBuilder; -use sha1::{Digest, Sha1}; -use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, IntoUnix}; -use wax::{any, Glob, Program}; - -use crate::{package_deps::GitHashes, Error}; - -fn git_like_hash_file(path: &AbsoluteSystemPath) -> Result { - let mut hasher = Sha1::new(); - let mut f = path.open()?; - let mut buffer = Vec::new(); - // Note that read_to_end reads the target if f is a symlink. Currently, this can - // happen when we are hashing a specific set of files, which in turn only - // happens for handling dotEnv files. It is likely that in the future we - // will want to ensure that the target is better accounted for in the set of - // inputs to the task. Manual hashing, as well as global deps and other - // places that support globs all ignore symlinks. - let size = f.read_to_end(&mut buffer)?; - hasher.update("blob ".as_bytes()); - hasher.update(size.to_string().as_bytes()); - hasher.update([b'\0']); - hasher.update(buffer.as_slice()); - let result = hasher.finalize(); - Ok(result.encode_hex::()) -} - -fn to_glob(input: &str) -> Result { - let glob = fix_glob_pattern(input).into_unix(); - let g = Glob::new(glob.as_str()).map(|g| g.into_owned())?; - - Ok(g) -} - -pub(crate) fn hash_files( - root_path: &AbsoluteSystemPath, - files: impl Iterator>, - allow_missing: bool, -) -> Result { - let mut hashes = GitHashes::new(); - for file in files.into_iter() { - let path = root_path.resolve(file.as_ref()); - match git_like_hash_file(&path) { - Ok(hash) => hashes.insert(file.as_ref().to_unix(), hash), - Err(Error::Io(ref io_error, _)) - if allow_missing && io_error.kind() == ErrorKind::NotFound => - { - continue - } - Err(e) => return Err(e), - }; - } - Ok(hashes) -} - -pub(crate) fn get_package_file_hashes_without_git>( - turbo_root: &AbsoluteSystemPath, - package_path: &AnchoredSystemPath, - inputs: &[S], - include_default_files: bool, -) -> Result { - let full_package_path = turbo_root.resolve(package_path); - let mut hashes = GitHashes::new(); - let mut default_file_hashes = GitHashes::new(); - let mut excluded_file_hashes = GitHashes::new(); - - let mut walker_builder = WalkBuilder::new(&full_package_path); - let mut includes = Vec::new(); - let mut excludes = Vec::new(); - for pattern in inputs { - let pattern = pattern.as_ref(); - if let Some(exclusion) = pattern.strip_prefix('!') { - let g = to_glob(exclusion)?; - excludes.push(g); - } else { - let g = to_glob(pattern)?; - includes.push(g); - } - } - let include_pattern = if includes.is_empty() { - None - } else { - // Add in package.json and turbo.json to input patterns. Both file paths are - // relative to pkgPath - // - // - package.json is an input because if the `scripts` in the package.json - // change (i.e. the tasks that turbo executes), we want a cache miss, since - // any existing cache could be invalid. - // - turbo.json because it's the definition of the tasks themselves. The root - // turbo.json is similarly included in the global hash. This file may not - // exist in the workspace, but that is ok, because it will get ignored - // downstream. - let turbo_g = to_glob("package.json")?; - let package_g = to_glob("turbo.json")?; - includes.push(turbo_g); - includes.push(package_g); - - Some(any(includes)?) - }; - let exclude_pattern = if excludes.is_empty() { - None - } else { - Some(any(excludes)?) - }; - - let walker = walker_builder - .follow_links(false) - // if inputs have been provided manually, we shouldn't skip ignored files to mimic the - // regular behavior - .git_ignore(inputs.is_empty()) - .require_git(false) - .hidden(false) // this results in yielding hidden files (e.g. .gitignore) - .build(); - - for dirent in walker { - let dirent = dirent?; - let metadata = dirent.metadata()?; - // We need to do this here, rather than as a filter, because the root - // directory is always yielded and not subject to the supplied filter. - if metadata.is_dir() { - continue; - } - - let path = AbsoluteSystemPath::from_std_path(dirent.path())?; - let relative_path = full_package_path.anchor(path)?; - let relative_path = relative_path.to_unix(); - - // if we have includes, and this path doesn't match any of them, skip it - if let Some(include_pattern) = include_pattern.as_ref() { - if !include_pattern.is_match(relative_path.as_str()) { - continue; - } - } - - // if we have excludes, and this path matches one of them, skip it - if let Some(exclude_pattern) = exclude_pattern.as_ref() { - if exclude_pattern.is_match(relative_path.as_str()) { - continue; - } - } - - // FIXME: we don't hash symlinks... - if metadata.is_symlink() { - continue; - } - let hash = git_like_hash_file(path)?; - hashes.insert(relative_path, hash); - } - - // If we're including default files, we need to walk again, but this time with - // git_ignore enabled - if include_default_files { - let walker = walker_builder - .follow_links(false) - .git_ignore(true) - .require_git(false) - .hidden(false) // this results in yielding hidden files (e.g. .gitignore) - .build(); - - for dirent in walker { - let dirent = dirent?; - let metadata = dirent.metadata()?; - // We need to do this here, rather than as a filter, because the root - // directory is always yielded and not subject to the supplied filter. - if metadata.is_dir() { - continue; - } - - let path = AbsoluteSystemPath::from_std_path(dirent.path())?; - let relative_path = full_package_path.anchor(path)?; - let relative_path = relative_path.to_unix(); - - if let Some(exclude_pattern) = exclude_pattern.as_ref() { - if exclude_pattern.is_match(relative_path.as_str()) { - // track excludes so we can exclude them to the hash map later - if !metadata.is_symlink() { - let hash = git_like_hash_file(path)?; - excluded_file_hashes.insert(relative_path.clone(), hash); - } - } - } - - // FIXME: we don't hash symlinks... - if metadata.is_symlink() { - continue; - } - let hash = git_like_hash_file(path)?; - default_file_hashes.insert(relative_path, hash); - } - } - - // merge default with all hashes - hashes.extend(default_file_hashes); - // remove excluded files - hashes.retain(|key, _| !excluded_file_hashes.contains_key(key)); - - Ok(hashes) -} - -#[cfg(test)] -mod tests { - use std::assert_matches::assert_matches; - - use test_case::test_case; - use turbopath::{ - AbsoluteSystemPathBuf, AnchoredSystemPathBuf, RelativeUnixPath, RelativeUnixPathBuf, - }; - - use super::*; - - fn tmp_dir() -> (tempfile::TempDir, AbsoluteSystemPathBuf) { - let tmp_dir = tempfile::tempdir().unwrap(); - let dir = AbsoluteSystemPathBuf::try_from(tmp_dir.path().to_path_buf()) - .unwrap() - .to_realpath() - .unwrap(); - (tmp_dir, dir) - } - - #[test_case(&["non-existent-file.txt"], true, false ; "allow_missing, all missing")] - #[test_case(&["non-existent-file.txt", "existing-file.txt"], true, false ; "allow_missing, some missing, some not")] - #[test_case(&["existing-file.txt"], true, false ; "allow_missing, none missing")] - #[test_case(&["non-existent-file.txt"], false, true ; "don't allow_missing, all missing")] - #[test_case(&["non-existent-file.txt", "existing-file.txt"], false, true ; "don't allow_missing, some missing, some not")] - #[test_case(&["existing-file.txt"], false, false ; "don't allow_missing, none missing")] - fn test_hash_files(files: &[&str], allow_missing: bool, want_err: bool) { - let (_tmp, turbo_root) = tmp_dir(); - let test_file = turbo_root.join_component("existing-file.txt"); - test_file.create_with_contents("").unwrap(); - - let expected = { - let mut expected = GitHashes::new(); - if files.contains(&"existing-file.txt") { - expected.insert( - RelativeUnixPathBuf::new("existing-file.txt").unwrap(), - "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391".to_string(), - ); - } - expected - }; - - let files = files - .iter() - .map(|s| AnchoredSystemPathBuf::from_raw(s).unwrap()); - match hash_files(&turbo_root, files, allow_missing) { - Err(e) => assert!(want_err, "unexpected error {}", e), - Ok(hashes) => assert_eq!(hashes, expected), - } - } - - #[test] - fn test_hash_symlink() { - let (_tmp, turbo_root) = tmp_dir(); - let from_to_file = turbo_root.join_component("symlink-from-to-file"); - let from_to_dir = turbo_root.join_component("symlink-from-to-dir"); - let broken = turbo_root.join_component("symlink-broken"); - - let to_file = turbo_root.join_component("the-file-target"); - to_file.create_with_contents("contents").unwrap(); - - let to_dir = turbo_root.join_component("the-dir-target"); - to_dir.create_dir_all().unwrap(); - - from_to_file.symlink_to_file(to_file.to_string()).unwrap(); - from_to_dir.symlink_to_dir(to_dir.to_string()).unwrap(); - broken.symlink_to_file("does-not-exist").unwrap(); - - // Symlink to file. - let out = hash_files( - &turbo_root, - [AnchoredSystemPathBuf::from_raw("symlink-from-to-file").unwrap()].iter(), - true, - ) - .unwrap(); - let from_to_file_hash = out - .get(&RelativeUnixPathBuf::new("symlink-from-to-file").unwrap()) - .unwrap(); - assert_eq!( - from_to_file_hash, - "0839b2e9412b314cb8bb9a20f587aa13752ae310" - ); - - // Symlink to dir, allow_missing = true. - #[cfg(not(windows))] - { - let out = hash_files( - &turbo_root, - [AnchoredSystemPathBuf::from_raw("symlink-from-to-dir").unwrap()].iter(), - true, - ); - match out.err().unwrap() { - Error::Io(io_error, _) => assert_eq!(io_error.kind(), ErrorKind::IsADirectory), - _ => panic!("wrong error"), - }; - } - - // Symlink to dir, allow_missing = false. - let out = hash_files( - &turbo_root, - [AnchoredSystemPathBuf::from_raw("symlink-from-to-dir").unwrap()].iter(), - false, - ); - #[cfg(windows)] - let expected_err_kind = ErrorKind::PermissionDenied; - #[cfg(not(windows))] - let expected_err_kind = ErrorKind::IsADirectory; - assert_matches!(out.unwrap_err(), Error::Io(io_error, _) if io_error.kind() == expected_err_kind); - - // Broken symlink with allow_missing = true. - let out = hash_files( - &turbo_root, - [AnchoredSystemPathBuf::from_raw("symlink-broken").unwrap()].iter(), - true, - ) - .unwrap(); - let broken_hash = out.get(&RelativeUnixPathBuf::new("symlink-broken").unwrap()); - assert_eq!(broken_hash, None); - - // Broken symlink with allow_missing = false. - let out = hash_files( - &turbo_root, - [AnchoredSystemPathBuf::from_raw("symlink-broken").unwrap()].iter(), - false, - ); - match out.err().unwrap() { - Error::Io(io_error, _) => assert_eq!(io_error.kind(), ErrorKind::NotFound), - _ => panic!("wrong error"), - }; - } - - #[test] - fn test_get_package_file_hashes_from_processing_gitignore() { - let root_ignore_contents = ["ignoreme", "ignorethisdir/"].join("\n"); - let pkg_ignore_contents = ["pkgignoreme", "pkgignorethisdir/"].join("\n"); - - let (_tmp, turbo_root) = tmp_dir(); - - let pkg_path = AnchoredSystemPathBuf::from_raw("child-dir/libA").unwrap(); - let unix_pkg_path = pkg_path.to_unix(); - let mut file_hash: Vec<(&str, &str, Option<&str>)> = vec![ - ("turbo.json", "turbo.json-file-contents", None), - ("package.json", "root-package.json-file-contents", None), - ("top-level-file", "top-level-file-contents", None), - ("other-dir/other-dir-file", "other-dir-file-contents", None), - ("ignoreme", "anything", None), - ( - "child-dir/libA/turbo.json", - "lib-turbo.json-content", - Some("ca4dbb95c0829676756c6decae728252d4aa4911"), - ), - ( - "child-dir/libA/package.json", - "lib-package.json-content", - Some("55d57df9acc1b37d0cfc2c1c70379dab48f3f7e1"), - ), - ( - "child-dir/libA/some-file", - "some-file-contents", - Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), - ), - ( - "child-dir/libA/some-dir/other-file", - "some-file-contents", - Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), - ), - ( - "child-dir/libA/some-dir/another-one", - "some-file-contents", - Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), - ), - ( - "child-dir/libA/some-dir/excluded-file", - "some-file-contents", - Some("7e59c6a6ea9098c6d3beb00e753e2c54ea502311"), - ), - ("child-dir/libA/ignoreme", "anything", None), - ("child-dir/libA/ignorethisdir/anything", "anything", None), - ("child-dir/libA/pkgignoreme", "anything", None), - ("child-dir/libA/pkgignorethisdir/file", "anything", None), - ]; - - let root_ignore_file = turbo_root.join_component(".gitignore"); - root_ignore_file - .create_with_contents(root_ignore_contents) - .unwrap(); - let pkg_ignore_file = turbo_root.resolve(&pkg_path).join_component(".gitignore"); - pkg_ignore_file.ensure_dir().unwrap(); - pkg_ignore_file - .create_with_contents(pkg_ignore_contents) - .unwrap(); - - let mut expected = GitHashes::new(); - for (raw_unix_path, contents, expected_hash) in file_hash.iter() { - let unix_path = RelativeUnixPath::new(raw_unix_path).unwrap(); - let file_path = turbo_root.join_unix_path(unix_path); - file_path.ensure_dir().unwrap(); - file_path.create_with_contents(contents).unwrap(); - if let Some(hash) = expected_hash { - println!("unix_path: {}", unix_path); - println!("unix_pkg_path: {}", unix_pkg_path); - let unix_pkg_file_path = unix_path.strip_prefix(&unix_pkg_path).unwrap(); - println!("unix_pkg_file_path: {}", unix_pkg_file_path); - expected.insert(unix_pkg_file_path.to_owned(), (*hash).to_owned()); - } - } - expected.insert( - RelativeUnixPathBuf::new(".gitignore").unwrap(), - "3237694bc3312ded18386964a855074af7b066af".to_owned(), - ); - - let hashes = - get_package_file_hashes_without_git::<&str>(&turbo_root, &pkg_path, &[], false) - .unwrap(); - assert_eq!(hashes, expected); - - // set a hash for an ignored file - for (raw_unix_path, _, expected_hash) in file_hash.iter_mut() { - if *raw_unix_path == "child-dir/libA/pkgignorethisdir/file" { - *expected_hash = Some("67aed78ea231bdee3de45b6d47d8f32a0a792f6d"); - break; - } - } - - expected = GitHashes::new(); - for (raw_unix_path, contents, expected_hash) in file_hash.iter() { - let unix_path = RelativeUnixPath::new(raw_unix_path).unwrap(); - let file_path = turbo_root.join_unix_path(unix_path); - file_path.ensure_dir().unwrap(); - file_path.create_with_contents(contents).unwrap(); - if let Some(hash) = expected_hash { - let unix_pkg_file_path = unix_path.strip_prefix(&unix_pkg_path).unwrap(); - if (unix_pkg_file_path.ends_with("file") - || unix_pkg_file_path.ends_with("package.json") - || unix_pkg_file_path.ends_with("turbo.json")) - && !unix_pkg_file_path.ends_with("excluded-file") - { - expected.insert(unix_pkg_file_path.to_owned(), (*hash).to_owned()); - } - } - } - - let hashes = get_package_file_hashes_without_git( - &turbo_root, - &pkg_path, - &["**/*file", "!some-dir/excluded-file"], - false, - ) - .unwrap(); - - assert_eq!(hashes, expected); - } -} diff --git a/crates/turborepo-scm/src/package_deps.rs b/crates/turborepo-scm/src/package_deps.rs deleted file mode 100644 index cfcf5baf5fd87..0000000000000 --- a/crates/turborepo-scm/src/package_deps.rs +++ /dev/null @@ -1,625 +0,0 @@ -use std::{collections::HashMap, str::FromStr}; - -use globwalk::ValidatedGlob; -use tracing::debug; -use turbopath::{AbsoluteSystemPath, AnchoredSystemPath, PathError, RelativeUnixPathBuf}; -use turborepo_telemetry::events::task::{FileHashMethod, PackageTaskEventBuilder}; - -use crate::{hash_object::hash_objects, Error, Git, SCM}; - -pub type GitHashes = HashMap; - -pub const INPUT_INCLUDE_DEFAULT_FILES: &str = "$TURBO_DEFAULT$"; - -impl SCM { - pub fn get_hashes_for_files( - &self, - turbo_root: &AbsoluteSystemPath, - files: &[impl AsRef], - allow_missing: bool, - ) -> Result { - if allow_missing { - self.hash_existing_of(turbo_root, files.iter()) - } else { - self.hash_files(turbo_root, files.iter()) - } - } - - #[tracing::instrument(skip(self, turbo_root, package_path, inputs))] - pub fn get_package_file_hashes>( - &self, - turbo_root: &AbsoluteSystemPath, - package_path: &AnchoredSystemPath, - inputs: &[S], - telemetry: Option, - ) -> Result { - // If the inputs contain "$TURBO_DEFAULT$", we need to include the "default" - // file hashes as well. NOTE: we intentionally don't remove - // "$TURBO_DEFAULT$" from the inputs if it exists in the off chance that - // the user has a file named "$TURBO_DEFAULT$" in their package (pls - // no). - let include_default_files = inputs - .iter() - .any(|input| input.as_ref() == INPUT_INCLUDE_DEFAULT_FILES); - - match self { - SCM::Manual => { - if let Some(telemetry) = telemetry { - telemetry.track_file_hash_method(FileHashMethod::Manual); - } - crate::manual::get_package_file_hashes_without_git( - turbo_root, - package_path, - inputs, - include_default_files, - ) - } - SCM::Git(git) => { - let result = git.get_package_file_hashes( - turbo_root, - package_path, - inputs, - include_default_files, - ); - match result { - Ok(hashes) => { - if let Some(telemetry) = telemetry { - telemetry.track_file_hash_method(FileHashMethod::Git); - } - Ok(hashes) - } - Err(err) => { - debug!( - "failed to use git to hash files: {}. Falling back to manual", - err - ); - if let Some(telemetry) = telemetry { - telemetry.track_file_hash_method(FileHashMethod::Manual); - } - crate::manual::get_package_file_hashes_without_git( - turbo_root, - package_path, - inputs, - include_default_files, - ) - } - } - } - } - } - - pub fn hash_files( - &self, - turbo_root: &AbsoluteSystemPath, - files: impl Iterator>, - ) -> Result { - match self { - SCM::Manual => crate::manual::hash_files(turbo_root, files, false), - SCM::Git(git) => git.hash_files(turbo_root, files), - } - } - - // hash_existing_of takes a list of files to hash and returns the hashes for the - // files in that list that exist. Files in the list that do not exist are - // skipped. - pub fn hash_existing_of( - &self, - turbo_root: &AbsoluteSystemPath, - files: impl Iterator>, - ) -> Result { - crate::manual::hash_files(turbo_root, files, true) - } -} - -impl Git { - fn get_package_file_hashes>( - &self, - turbo_root: &AbsoluteSystemPath, - package_path: &AnchoredSystemPath, - inputs: &[S], - include_default_files: bool, - ) -> Result { - // no inputs, and no $TURBO_DEFAULT$ - if inputs.is_empty() { - return self.get_package_file_hashes_from_index(turbo_root, package_path); - } - - // we have inputs, but no $TURBO_DEFAULT$ - if !include_default_files { - return self.get_package_file_hashes_from_inputs( - turbo_root, - package_path, - inputs, - true, - ); - } - - // we have inputs, and $TURBO_DEFAULT$ - self.get_package_file_hashes_from_inputs_and_index(turbo_root, package_path, inputs) - } - - #[tracing::instrument(skip(self, turbo_root))] - fn get_package_file_hashes_from_index( - &self, - turbo_root: &AbsoluteSystemPath, - package_path: &AnchoredSystemPath, - ) -> Result { - let full_pkg_path = turbo_root.resolve(package_path); - let git_to_pkg_path = self.root.anchor(&full_pkg_path)?; - let pkg_prefix = git_to_pkg_path.to_unix(); - let mut hashes = self.git_ls_tree(&full_pkg_path)?; - // Note: to_hash is *git repo relative* - let to_hash = self.append_git_status(&full_pkg_path, &pkg_prefix, &mut hashes)?; - hash_objects(&self.root, &full_pkg_path, to_hash, &mut hashes)?; - Ok(hashes) - } - - fn hash_files( - &self, - process_relative_to: &AbsoluteSystemPath, - files: impl Iterator>, - ) -> Result { - let mut hashes = GitHashes::new(); - let to_hash = files - .map(|f| { - Ok(self - .root - .anchor(process_relative_to.resolve(f.as_ref()))? - .to_unix()) - }) - .collect::, PathError>>()?; - // Note: to_hash is *git repo relative* - hash_objects(&self.root, process_relative_to, to_hash, &mut hashes)?; - Ok(hashes) - } - - #[tracing::instrument(skip(self, turbo_root, inputs))] - fn get_package_file_hashes_from_inputs>( - &self, - turbo_root: &AbsoluteSystemPath, - package_path: &AnchoredSystemPath, - inputs: &[S], - include_configs: bool, - ) -> Result { - let full_pkg_path = turbo_root.resolve(package_path); - let package_unix_path_buf = package_path.to_unix(); - let package_unix_path = package_unix_path_buf.as_str(); - - let mut inputs = inputs - .iter() - .map(|s| s.as_ref().to_string()) - .collect::>(); - - if include_configs { - // Add in package.json and turbo.json to input patterns. Both file paths are - // relative to pkgPath - // - // - package.json is an input because if the `scripts` in the package.json - // change (i.e. the tasks that turbo executes), we want a cache miss, since - // any existing cache could be invalid. - // - turbo.json because it's the definition of the tasks themselves. The root - // turbo.json is similarly included in the global hash. This file may not - // exist in the workspace, but that is ok, because it will get ignored - // downstream. - inputs.push("package.json".to_string()); - inputs.push("turbo.json".to_string()); - } - - // The input patterns are relative to the package. - // However, we need to change the globbing to be relative to the repo root. - // Prepend the package path to each of the input patterns. - // - // FIXME: we don't yet error on absolute unix paths being passed in as inputs, - // and instead tack them on as if they were relative paths. This should be an - // error further upstream, but since we haven't pulled the switch yet, - // we need to mimic the Go behavior here and trim leading `/` - // characters. - let mut inclusions = vec![]; - let mut exclusions = vec![]; - for raw_glob in inputs { - if let Some(exclusion) = raw_glob.strip_prefix('!') { - let glob_str = [package_unix_path, exclusion.trim_start_matches('/')].join("/"); - exclusions.push(ValidatedGlob::from_str(&glob_str)?); - } else { - let glob_str = [package_unix_path, raw_glob.trim_start_matches('/')].join("/"); - inclusions.push(ValidatedGlob::from_str(&glob_str)?); - } - } - let files = globwalk::globwalk( - turbo_root, - &inclusions, - &exclusions, - globwalk::WalkType::Files, - )?; - let to_hash = files - .iter() - .map(|entry| { - let path = self.root.anchor(entry)?.to_unix(); - Ok(path) - }) - .collect::, Error>>()?; - let mut hashes = GitHashes::new(); - hash_objects(&self.root, &full_pkg_path, to_hash, &mut hashes)?; - Ok(hashes) - } - - #[tracing::instrument(skip(self, turbo_root, inputs))] - fn get_package_file_hashes_from_inputs_and_index>( - &self, - turbo_root: &AbsoluteSystemPath, - package_path: &AnchoredSystemPath, - inputs: &[S], - ) -> Result { - // collect the default files and the inputs - let default_file_hashes = - self.get_package_file_hashes_from_index(turbo_root, package_path)?; - - // we need to get hashes for excludes separately so we can remove them from the - // defaults later on - let mut includes = Vec::new(); - let mut excludes = Vec::new(); - for input in inputs { - let input_str = input.as_ref(); - if let Some(exclude) = input_str.strip_prefix('!') { - excludes.push(exclude); - } else { - includes.push(input_str); - } - } - // we have to always run the includes search because we add default files to the - // includes - let manual_includes_hashes = - self.get_package_file_hashes_from_inputs(turbo_root, package_path, &includes, true)?; - - // only run the excludes search if there are excludes - let manual_excludes_hashes = if !excludes.is_empty() { - self.get_package_file_hashes_from_inputs(turbo_root, package_path, &excludes, false)? - } else { - GitHashes::new() - }; - - // merge the two includes - let mut hashes = default_file_hashes; - hashes.extend(manual_includes_hashes); - - // remove the excludes - hashes.retain(|key, _| !manual_excludes_hashes.contains_key(key)); - - return Ok(hashes); - } -} - -#[cfg(test)] -mod tests { - use std::{assert_matches::assert_matches, process::Command}; - - use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; - - use super::*; - use crate::manual::get_package_file_hashes_without_git; - - fn tmp_dir() -> (tempfile::TempDir, AbsoluteSystemPathBuf) { - let tmp_dir = tempfile::tempdir().unwrap(); - let dir = AbsoluteSystemPathBuf::try_from(tmp_dir.path()) - .unwrap() - .to_realpath() - .unwrap(); - (tmp_dir, dir) - } - - fn require_git_cmd(repo_root: &AbsoluteSystemPathBuf, args: &[&str]) { - let mut cmd = Command::new("git"); - cmd.args(args).current_dir(repo_root); - assert!(cmd.output().unwrap().status.success()); - } - - fn setup_repository(repo_root: &AbsoluteSystemPathBuf) { - let cmds: &[&[&str]] = &[ - &["init", "."], - &["config", "--local", "user.name", "test"], - &["config", "--local", "user.email", "test@example.com"], - ]; - for cmd in cmds { - require_git_cmd(repo_root, cmd); - } - } - - fn commit_all(repo_root: &AbsoluteSystemPathBuf) { - let cmds: &[&[&str]] = &[&["add", "."], &["commit", "-m", "foo"]]; - for cmd in cmds { - require_git_cmd(repo_root, cmd); - } - } - - #[test] - fn test_hash_symlink() { - let (_, tmp_root) = tmp_dir(); - let git_root = tmp_root.join_component("actual_repo"); - git_root.create_dir_all().unwrap(); - setup_repository(&git_root); - git_root.join_component("inside").create_dir_all().unwrap(); - let link = git_root.join_component("link"); - link.symlink_to_dir("inside").unwrap(); - let to_hash = vec![RelativeUnixPathBuf::new("link").unwrap()]; - let mut hashes = GitHashes::new(); - // FIXME: This test verifies a bug: we don't hash symlinks. - // TODO: update this test to point at get_package_file_hashes - hash_objects(&git_root, &git_root, to_hash, &mut hashes).unwrap(); - assert!(hashes.is_empty()); - - let pkg_path = git_root.anchor(&git_root).unwrap(); - let manual_hashes = - get_package_file_hashes_without_git(&git_root, &pkg_path, &["l*"], false).unwrap(); - assert!(manual_hashes.is_empty()); - } - - #[test] - fn test_get_package_deps_fallback() { - let (_repo_root_tmp, repo_root) = tmp_dir(); - let my_pkg_dir = repo_root.join_component("my-pkg"); - my_pkg_dir.create_dir_all().unwrap(); - - // create file 1 - let committed_file_path = my_pkg_dir.join_component("committed-file"); - committed_file_path - .create_with_contents("committed bytes") - .unwrap(); - - setup_repository(&repo_root); - commit_all(&repo_root); - let git = SCM::new(&repo_root); - assert_matches!(git, SCM::Git(_)); - // Remove the .git directory to trigger an error in git hashing - repo_root.join_component(".git").remove_dir_all().unwrap(); - let pkg_path = repo_root.anchor(&my_pkg_dir).unwrap(); - let hashes = git - .get_package_file_hashes::<&str>( - &repo_root, - &pkg_path, - &[], - Some(PackageTaskEventBuilder::new("my-pkg", "test")), - ) - .unwrap(); - let mut expected = GitHashes::new(); - expected.insert( - RelativeUnixPathBuf::new("committed-file").unwrap(), - "3a29e62ea9ba15c4a4009d1f605d391cdd262033".to_string(), - ); - assert_eq!(hashes, expected); - } - - #[test] - fn test_get_package_deps() -> Result<(), Error> { - // Directory structure: - // / - // package.json - // turbo.json - // .gitignore - // new-root-file <- new file not added to git - // my-pkg/ - // package.json - // turbo.json - // $TURBO_DEFAULT$ <- ignored by git - // committed-file - // deleted-file - // uncommitted-file <- new file not added to git - // dir/ - // nested-file - // ignored-file <- ignored by git - let (_repo_root_tmp, repo_root) = tmp_dir(); - - // create a root package.json - let root_pkg_json_path = repo_root.join_component("package.json"); - root_pkg_json_path.create_with_contents("{}")?; - - // create a root turbo.json - let root_turbo_json_path = repo_root.join_component("turbo.json"); - root_turbo_json_path.create_with_contents("{}")?; - - // create the package directory - let my_pkg_dir = repo_root.join_component("my-pkg"); - my_pkg_dir.create_dir_all()?; - - // create a gitignore file - let gitignore_path = repo_root.join_component(".gitignore"); - gitignore_path.create_with_contents("my-pkg/dir/ignored-file\nmy-pkg/$TURBO_DEFAULT$")?; - - // create file 1 - let committed_file_path = my_pkg_dir.join_component("committed-file"); - committed_file_path.create_with_contents("committed bytes")?; - - // create file 2 - let deleted_file_path = my_pkg_dir.join_component("deleted-file"); - deleted_file_path.create_with_contents("delete-me")?; - - // create file 3 - let nested_file_path = my_pkg_dir.join_components(&["dir", "nested-file"]); - nested_file_path.ensure_dir()?; - nested_file_path.create_with_contents("nested")?; - - // create a package package.json - let pkg_json_path = my_pkg_dir.join_component("package.json"); - pkg_json_path.create_with_contents("{}")?; - - // create a package turbo.json - let turbo_json_path = my_pkg_dir.join_component("turbo.json"); - turbo_json_path.create_with_contents("{}")?; - - setup_repository(&repo_root); - commit_all(&repo_root); - let git = SCM::new(&repo_root); - let SCM::Git(git) = git else { - panic!("expected git, found {:?}", git); - }; - - // remove a file - deleted_file_path.remove()?; - - // create another untracked file in git - let uncommitted_file_path = my_pkg_dir.join_component("uncommitted-file"); - uncommitted_file_path.create_with_contents("uncommitted bytes")?; - - // create an untracked file in git up a level - let root_file_path = repo_root.join_component("new-root-file"); - root_file_path.create_with_contents("new-root bytes")?; - - // create a file that will be ignored - let ignored_file_path = my_pkg_dir.join_components(&["dir", "ignored-file"]); - ignored_file_path.ensure_dir()?; - ignored_file_path.create_with_contents("ignored")?; - - // create a file that matches the $TURBO_DEFAULT$ token to test the edge case - let token_file_path = my_pkg_dir.join_components(&["$TURBO_DEFAULT$"]); - token_file_path.ensure_dir()?; - token_file_path.create_with_contents("maybe-rename?")?; - - let package_path = AnchoredSystemPathBuf::from_raw("my-pkg")?; - - let all_expected = to_hash_map(&[ - ("committed-file", "3a29e62ea9ba15c4a4009d1f605d391cdd262033"), - ( - "uncommitted-file", - "4e56ad89387e6379e4e91ddfe9872cf6a72c9976", - ), - ("package.json", "9e26dfeeb6e641a33dae4961196235bdb965b21b"), - ("turbo.json", "9e26dfeeb6e641a33dae4961196235bdb965b21b"), - ( - "dir/nested-file", - "bfe53d766e64d78f80050b73cd1c88095bc70abb", - ), - ]); - let hashes = git.get_package_file_hashes::<&str>(&repo_root, &package_path, &[], false)?; - assert_eq!(hashes, all_expected); - - // add the new root file as an option - let mut all_expected = all_expected.clone(); - all_expected.insert( - RelativeUnixPathBuf::new("../new-root-file").unwrap(), - "8906ddcdd634706188bd8ef1c98ac07b9be3425e".to_string(), - ); - all_expected.insert( - RelativeUnixPathBuf::new("dir/ignored-file").unwrap(), - "5537770d04ec8aaf7bae2d9ff78866de86df415c".to_string(), - ); - all_expected.insert( - RelativeUnixPathBuf::new("$TURBO_DEFAULT$").unwrap(), - "2f26c7b914476b3c519e4f0fbc0d16c52a60d178".to_string(), - ); - - let input_tests: &[(&[&str], &[&str])] = &[ - ( - &["uncommitted-file"], - &["package.json", "turbo.json", "uncommitted-file"], - ), - ( - &["**/*-file"], - &[ - "committed-file", - "uncommitted-file", - "package.json", - "turbo.json", - "dir/nested-file", - "dir/ignored-file", - ], - ), - ( - &["../**/*-file"], - &[ - "committed-file", - "uncommitted-file", - "package.json", - "turbo.json", - "dir/nested-file", - "dir/ignored-file", - "../new-root-file", - ], - ), - ( - &["**/{uncommitted,committed}-file"], - &[ - "committed-file", - "uncommitted-file", - "package.json", - "turbo.json", - ], - ), - ( - &["../**/{new-root,uncommitted,committed}-file"], - &[ - "committed-file", - "uncommitted-file", - "package.json", - "turbo.json", - "../new-root-file", - ], - ), - ( - &["$TURBO_DEFAULT$"], - &[ - "committed-file", - "uncommitted-file", - "package.json", - "turbo.json", - "$TURBO_DEFAULT$", - "dir/nested-file", - ], - ), - ( - &["$TURBO_DEFAULT$", "!dir/*"], - &[ - "committed-file", - "uncommitted-file", - "package.json", - "turbo.json", - "$TURBO_DEFAULT$", - ], - ), - ( - &["$TURBO_DEFAULT$", "!committed-file", "dir/ignored-file"], - &[ - "uncommitted-file", - "package.json", - "turbo.json", - "dir/ignored-file", - "dir/nested-file", - "$TURBO_DEFAULT$", - ], - ), - ( - &["!committed-file", "$TURBO_DEFAULT$", "dir/ignored-file"], - &[ - "uncommitted-file", - "package.json", - "turbo.json", - "dir/ignored-file", - "dir/nested-file", - "$TURBO_DEFAULT$", - ], - ), - ]; - for (inputs, expected_files) in input_tests { - let expected: GitHashes = HashMap::from_iter(expected_files.iter().map(|key| { - let key = RelativeUnixPathBuf::new(*key).unwrap(); - let value = all_expected.get(&key).unwrap().clone(); - (key, value) - })); - let include_default_files = inputs - .iter() - .any(|input| input == &INPUT_INCLUDE_DEFAULT_FILES); - - let hashes = git - .get_package_file_hashes(&repo_root, &package_path, inputs, include_default_files) - .unwrap(); - assert_eq!(hashes, expected); - } - Ok(()) - } - - fn to_hash_map(pairs: &[(&str, &str)]) -> GitHashes { - HashMap::from_iter( - pairs - .iter() - .map(|(path, hash)| (RelativeUnixPathBuf::new(*path).unwrap(), hash.to_string())), - ) - } -} diff --git a/crates/turborepo-scm/src/status.rs b/crates/turborepo-scm/src/status.rs deleted file mode 100644 index dc6d89e686590..0000000000000 --- a/crates/turborepo-scm/src/status.rs +++ /dev/null @@ -1,156 +0,0 @@ -use std::{ - io::{BufRead, BufReader, Read}, - process::{Command, Stdio}, -}; - -use nom::Finish; -use turbopath::{AbsoluteSystemPath, RelativeUnixPathBuf}; - -use crate::{package_deps::GitHashes, wait_for_success, Error, Git}; - -impl Git { - #[tracing::instrument(skip(self, root_path, hashes))] - pub(crate) fn append_git_status( - &self, - root_path: &AbsoluteSystemPath, - pkg_prefix: &RelativeUnixPathBuf, - hashes: &mut GitHashes, - ) -> Result, Error> { - let mut git = Command::new(self.bin.as_std_path()) - .args([ - "status", - "--untracked-files", - "--no-renames", - "-z", - "--", - ".", - ]) - .env("GIT_OPTIONAL_LOCKS", "0") - .current_dir(root_path) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - - let stdout = git - .stdout - .as_mut() - .ok_or_else(|| Error::git_error("failed to get stdout for git status"))?; - let mut stderr = git - .stderr - .take() - .ok_or_else(|| Error::git_error("failed to get stderr for git status"))?; - let parse_result = read_status(stdout, root_path, pkg_prefix, hashes); - wait_for_success(git, &mut stderr, "git status", root_path, parse_result) - } -} - -fn read_status( - reader: R, - root_path: &AbsoluteSystemPath, - pkg_prefix: &RelativeUnixPathBuf, - hashes: &mut GitHashes, -) -> Result, Error> { - let mut to_hash = Vec::new(); - let mut reader = BufReader::new(reader); - let mut buffer = Vec::new(); - while reader.read_until(b'\0', &mut buffer)? != 0 { - let entry = parse_status(&buffer)?; - let path = RelativeUnixPathBuf::new(String::from_utf8(entry.filename.to_owned())?)?; - if entry.is_delete { - let path = path.strip_prefix(pkg_prefix).map_err(|_| { - Error::git_error(format!( - "'git status --untracked-files --no-renames -z -- .' run in {} found a \ - deleted file {} that did not have the expected prefix: {}", - root_path, path, pkg_prefix - )) - })?; - hashes.remove(&path); - } else { - to_hash.push(path); - } - buffer.clear(); - } - Ok(to_hash) -} - -struct StatusEntry<'a> { - filename: &'a [u8], - is_delete: bool, -} - -fn parse_status(i: &[u8]) -> Result, Error> { - match nom::combinator::all_consuming(nom_parse_status)(i).finish() { - Ok((_, tup)) => Ok(tup), - Err(e) => Err(Error::git_error(format!( - "failed to parse git-status: {}", - String::from_utf8_lossy(e.input) - ))), - } -} - -fn nom_parse_status(i: &[u8]) -> nom::IResult<&[u8], StatusEntry<'_>> { - let (i, x) = nom::bytes::complete::take(1usize)(i)?; - let (i, y) = nom::bytes::complete::take(1usize)(i)?; - let (i, _) = nom::character::complete::space1(i)?; - let (i, filename) = nom::bytes::complete::is_not("\0")(i)?; - // We explicitly support a missing terminator - let (i, _) = nom::combinator::opt(nom::bytes::complete::tag(b"\0"))(i)?; - Ok(( - i, - StatusEntry { - filename, - is_delete: x[0] == b'D' || y[0] == b'D', - }, - )) -} - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - - use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf, RelativeUnixPathBufTestExt}; - - use super::read_status; - use crate::package_deps::GitHashes; - - #[test] - fn test_status() { - let root_path = AbsoluteSystemPathBuf::cwd().unwrap(); - let tests: &[(&str, &str, (&str, bool))] = &[ - ("AD my-pkg/package.json\0", "my-pkg", ("package.json", true)), - ( - // no trailing NUL - "AD some-pkg/package.json", - "some-pkg", - ("package.json", true), - ), - ("M package.json\0", "", ("package.json", false)), - ("A some-pkg/some-file\0", "some-pkg", ("some-file", false)), - ( - "M some-pkg/file with spaces\0", - "some-pkg", - ("file with spaces", false), - ), - ]; - for (input, prefix, (expected_filename, expect_delete)) in tests { - let prefix = RelativeUnixPathBuf::new(*prefix).unwrap(); - let mut hashes = to_hash_map(&[(expected_filename, "some-hash")]); - let to_hash = read_status(input.as_bytes(), &root_path, &prefix, &mut hashes).unwrap(); - if *expect_delete { - assert_eq!(hashes.len(), 0, "input: {}", input); - } else { - assert_eq!(to_hash.len(), 1, "input: {}", input); - let expected = prefix.join(&RelativeUnixPathBuf::new(*expected_filename).unwrap()); - assert_eq!(to_hash[0], expected); - } - } - } - - fn to_hash_map(pairs: &[(&str, &str)]) -> GitHashes { - HashMap::from_iter( - pairs - .iter() - .map(|(path, hash)| (RelativeUnixPathBuf::new(*path).unwrap(), hash.to_string())), - ) - } -} diff --git a/crates/turborepo-telemetry/Cargo.toml b/crates/turborepo-telemetry/Cargo.toml index a5013a16b439e..b5cdfb9748de5 100644 --- a/crates/turborepo-telemetry/Cargo.toml +++ b/crates/turborepo-telemetry/Cargo.toml @@ -1,20 +1,3 @@ -[package] -name = "turborepo-telemetry" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - -[dev-dependencies] -serde_json = { workspace = true } -tempfile = { workspace = true } -test-case = { workspace = true } -turborepo-vercel-api-mock = { workspace = true } - [dependencies] chrono = { workspace = true, features = ["serde"] } config = { version = "0.13.4", default-features = false, features = ["json"] } @@ -36,3 +19,21 @@ turborepo-ui = { workspace = true } turborepo-vercel-api = { workspace = true } url = { workspace = true } uuid = { version = "1.5.0", features = ["v4"] } + +[dev-dependencies] +serde_json = { workspace = true } +tempfile = { workspace = true } +test-case = { workspace = true } +turborepo-vercel-api-mock = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-telemetry" +version = "0.1.0" diff --git a/crates/turborepo-telemetry/README.md b/crates/turborepo-telemetry/README.md deleted file mode 100644 index a71a691c416ce..0000000000000 --- a/crates/turborepo-telemetry/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# turborepo-telemetry - -**NOTE**: -This crate has been ported to the [turbo-telemetry](https://github.com/vercel/turborepo/blob/main/crates/turborepo-telemetry) node package. -Any changes made here should also be made to that package as well. - -## Overview - -This crate provides a way to optionally record anonymous usage data. -This information is used to shape the Turborepo roadmap and prioritize features. You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the [documentation](https://turbo.build/repo/docs/telemetry): - -## Events - -All recorded events can be found by browsing the [events](./src/events) directory. diff --git a/crates/turborepo-telemetry/Source/config.rs b/crates/turborepo-telemetry/Source/config.rs new file mode 100644 index 0000000000000..ddb31f5cb158a --- /dev/null +++ b/crates/turborepo-telemetry/Source/config.rs @@ -0,0 +1,260 @@ +/// Configuration for telemetry. +/// +/// This module is responsible for reading and writing the telemetry +/// configuration file. +/// +/// NOTE: There is a port of this crate that is used to instrument node +/// projects. Any changes made here should be reflected there as well. +/// +/// https://github.com/vercel/turborepo/blob/main/packages/turbo-telemetry/src/config.ts +use std::env; + +use chrono::{DateTime, Utc}; +pub use config::{Config, ConfigError, File, FileFormat}; +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use tracing::{error, trace}; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; +use turborepo_dirs::config_dir; +use turborepo_ui::{BOLD, ColorConfig, GREY, UNDERLINE, color}; +use uuid::Uuid; + +static DEBUG_ENV_VAR:&str = "TURBO_TELEMETRY_DEBUG"; +static DISABLED_ENV_VAR:&str = "TURBO_TELEMETRY_DISABLED"; +static DISABLED_MESSAGE_ENV_VAR:&str = "TURBO_TELEMETRY_MESSAGE_DISABLED"; +static DO_NOT_TRACK_ENV_VAR:&str = "DO_NOT_TRACK"; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TelemetryConfigContents { + // whether or not telemetry is enabled + telemetry_enabled:bool, + // randomized and salted machine id - used for linking events together + telemetry_id:String, + // private salt used to anonymize event data (telemetry_id, task names, package names, etc.) - + // this is generated on first run and never leaves the machine + telemetry_salt:String, + + // when the alert was shown + #[serde(skip_serializing_if = "Option::is_none")] + telemetry_alerted:Option>, +} + +impl Default for TelemetryConfigContents { + fn default() -> Self { + let telemetry_salt = Uuid::new_v4().to_string(); + let raw_telemetry_id = Uuid::new_v4().to_string(); + let telemetry_id = one_way_hash_with_salt(&telemetry_salt, &raw_telemetry_id); + + TelemetryConfigContents { + telemetry_enabled:true, + telemetry_alerted:None, + telemetry_salt, + telemetry_id, + } + } +} + +#[derive(Debug)] +pub struct TelemetryConfig { + config_path:AbsoluteSystemPathBuf, + config:TelemetryConfigContents, +} + +impl TelemetryConfig { + pub fn with_default_config_path() -> Result { + let config_path = default_config_path()?; + TelemetryConfig::new(config_path) + } + + pub fn new(config_path:AbsoluteSystemPathBuf) -> Result { + trace!("Telemetry config path: {}", config_path); + if !config_path.exists() { + write_new_config(&config_path)?; + } + + let mut settings = Config::builder(); + settings = settings.add_source(File::new(config_path.as_str(), FileFormat::Json)); + let settings = settings.build(); + + // If this is a FileParse error, we assume something corrupted the file or + // its structure. In this case, because the telemetry config is intentionally + // isolated from other turborepo config, try to remove the entire config + // file and write a new one, otherwise return the error + let config = match settings { + Ok(settings) => settings.try_deserialize::()?, + Err(ConfigError::FileParse { .. }) => { + config_path.remove_file().map_err(|e| ConfigError::Message(e.to_string()))?; + write_new_config(&config_path)?; + return Err(settings.unwrap_err()); + }, + // Propagate other errors + Err(err) => return Err(err), + }; + + let config = TelemetryConfig { config_path, config }; + + Ok(config) + } + + fn write(&self) -> Result<(), ConfigError> { + let serialized = serde_json::to_string_pretty(&self.config) + .map_err(|e| ConfigError::Message(e.to_string()))?; + self.config_path + .create_with_contents(serialized) + .map_err(|e| ConfigError::Message(e.to_string()))?; + Ok(()) + } + + pub fn one_way_hash(input:&str) -> String { + match TelemetryConfig::with_default_config_path() { + Ok(config) => config.one_way_hash_with_config_salt(input), + Err(_) => TelemetryConfig::one_way_hash_with_tmp_salt(input), + } + } + + /// Obfuscate with the config salt - this is used for all sensitive event + /// data + fn one_way_hash_with_config_salt(&self, input:&str) -> String { + one_way_hash_with_salt(&self.config.telemetry_salt, input) + } + + /// Obfuscate with a temporary salt - this is used as a fallback when the + /// config salt is not available (e.g. config loading failed etc.) + /// + /// This is just as secure as the config salt, but it prevents us from + /// linking together events that include obfuscated data generated with + /// this method as each call will generate a new salt. + fn one_way_hash_with_tmp_salt(input:&str) -> String { + let tmp_salt = Uuid::new_v4().to_string(); + one_way_hash_with_salt(&tmp_salt, input) + } + + pub fn show_alert(&mut self, color_config:ColorConfig) { + if !self.has_seen_alert() && self.is_enabled() && Self::is_telemetry_warning_enabled() { + eprintln!( + "\n{}\n{}\n{}\n{}\n{}\n", + color!(color_config, BOLD, "{}", "Attention:"), + color!( + color_config, + GREY, + "{}", + "Turborepo now collects completely anonymous telemetry regarding usage." + ), + color!( + color_config, + GREY, + "{}", + "This information is used to shape the Turborepo roadmap and prioritize \ + features." + ), + color!( + color_config, + GREY, + "{}", + "You can learn more, including how to opt-out if you'd not like to \ + participate in this anonymous program, by visiting the following URL:" + ), + color!( + color_config, + UNDERLINE, + "{}", + color!(color_config, GREY, "{}", "https://turbo.build/repo/docs/telemetry") + ), + ); + + if let Err(err) = self.alert_shown() { + error!("Error saving seen alert event to telemetry config: {:?}", err); + } + } + } + + // getters + pub fn has_seen_alert(&self) -> bool { self.config.telemetry_alerted.is_some() } + + pub fn is_enabled(&self) -> bool { + let do_not_track = env::var(DO_NOT_TRACK_ENV_VAR).unwrap_or("0".to_string()); + let turbo_telemetry_disabled = env::var(DISABLED_ENV_VAR).unwrap_or("0".to_string()); + + if do_not_track == "1" + || do_not_track == "true" + || turbo_telemetry_disabled == "1" + || turbo_telemetry_disabled == "true" + { + return false; + } + + self.config.telemetry_enabled + } + + pub fn is_telemetry_warning_enabled() -> bool { + let turbo_telemetry_msg_disabled = + env::var(DISABLED_MESSAGE_ENV_VAR).unwrap_or("0".to_string()); + let is_disabled = + turbo_telemetry_msg_disabled == "1" || turbo_telemetry_msg_disabled == "true"; + + !is_disabled + } + + pub fn get_id(&self) -> &str { &self.config.telemetry_id } + + // setters + pub fn enable(&mut self) -> Result<&TelemetryConfigContents, ConfigError> { + self.config.telemetry_enabled = true; + self.write()?; + Ok(&self.config) + } + + pub fn disable(&mut self) -> Result<&TelemetryConfigContents, ConfigError> { + self.config.telemetry_enabled = false; + self.write()?; + Ok(&self.config) + } + + pub fn alert_shown(&mut self) -> Result<&TelemetryConfigContents, ConfigError> { + match self.has_seen_alert() { + true => Ok(&self.config), + false => { + self.config.telemetry_alerted = Some(Utc::now()); + self.write()?; + Ok(&self.config) + }, + } + } +} + +fn default_config_path() -> Result { + let config_dir = config_dir() + .map_err(|e| ConfigError::Message(format!("Invalid config directory: {}", e)))? + .ok_or(ConfigError::Message("Unable to find telemetry config directory".to_string()))?; + // stored as a sibling to the turbo global config + Ok(config_dir.join_components(&["turborepo", "telemetry.json"])) +} + +fn write_new_config(file_path:&AbsoluteSystemPath) -> Result<(), ConfigError> { + let serialized = serde_json::to_string_pretty(&TelemetryConfigContents::default()) + .map_err(|e| ConfigError::Message(e.to_string()))?; + + // Create the directory if it doesn't exist + file_path + .ensure_dir() + .map_err(|_| ConfigError::Message("Failed to create directory".to_string()))?; + + // Write the file + file_path + .create_with_contents(serialized) + .map_err(|e| ConfigError::Message(e.to_string()))?; + Ok(()) +} + +pub fn is_debug() -> bool { + let debug = env::var(DEBUG_ENV_VAR).unwrap_or("0".to_string()); + debug == "1" || debug == "true" +} + +fn one_way_hash_with_salt(salt:&str, input:&str) -> String { + let salted = format!("{}{}", salt, input); + let mut hasher = Sha256::new(); + hasher.update(salted.as_bytes()); + let generic = hasher.finalize(); + hex::encode(generic) +} diff --git a/crates/turborepo-telemetry/src/errors.rs b/crates/turborepo-telemetry/Source/errors.rs similarity index 100% rename from crates/turborepo-telemetry/src/errors.rs rename to crates/turborepo-telemetry/Source/errors.rs diff --git a/crates/turborepo-telemetry/src/events/command.rs b/crates/turborepo-telemetry/Source/events/command.rs similarity index 100% rename from crates/turborepo-telemetry/src/events/command.rs rename to crates/turborepo-telemetry/Source/events/command.rs diff --git a/crates/turborepo-telemetry/Source/events/generic.rs b/crates/turborepo-telemetry/Source/events/generic.rs new file mode 100644 index 0000000000000..b6c9251193d31 --- /dev/null +++ b/crates/turborepo-telemetry/Source/events/generic.rs @@ -0,0 +1,216 @@ +use std::fmt::Display; + +use serde::{Deserialize, Serialize}; +use turborepo_vercel_api::telemetry::{TelemetryEvent, TelemetryGenericEvent}; +use uuid::Uuid; + +use super::{Event, EventBuilder, EventType, Identifiable, TrackedErrors}; +use crate::{config::TelemetryConfig, telem}; + +// Remote cache URL's that will be passed through to the API without obfuscation +const RC_URL_ALLOWLIST:[&str; 1] = ["https://vercel.com/api"]; + +pub enum DaemonInitStatus { + // skipped due to context (running in CI etc) + Skipped, + /// daemon was started + Started, + /// daemon failed to start + Failed, + /// daemon was manually disabled by user + Disabled, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GenericEventBuilder { + id:String, + parent_id:Option, + is_ci:bool, +} + +impl Identifiable for GenericEventBuilder { + fn get_id(&self) -> &String { &self.id } +} + +impl EventBuilder for GenericEventBuilder { + fn with_parent(mut self, parent_event:&U) -> Self { + self.parent_id = Some(parent_event.get_id().clone()); + self + } + + fn track(&self, event:Event) { + if self.is_ci && !event.send_in_ci { + return; + } + + let val = match event.is_sensitive { + EventType::Sensitive => TelemetryConfig::one_way_hash(&event.value), + EventType::NonSensitive => event.value.to_string(), + }; + + telem(TelemetryEvent::Generic(TelemetryGenericEvent { + id:self.id.clone(), + parent_id:self.parent_id.clone(), + key:event.key, + value:val, + })); + } + + fn child(&self) -> Self { Self::new().with_parent(self) } +} + +impl Default for GenericEventBuilder { + fn default() -> Self { + Self { id:Uuid::new_v4().to_string(), parent_id:None, is_ci:turborepo_ci::is_ci() } + } +} + +// events +impl GenericEventBuilder { + pub fn new() -> Self { Self::default() } + + pub fn track_start(&self) -> &Self { + self.track(Event { + key:"execution".to_string(), + value:"started".to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } + + pub fn track_end(&self) -> &Self { + self.track(Event { + key:"execution".to_string(), + value:"ended".to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } + + pub fn track_platform(&self, platform:&str) -> &Self { + self.track(Event { + key:"platform".to_string(), + value:platform.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + pub fn track_cpus(&self, cpus:usize) -> &Self { + self.track(Event { + key:"cpu_count".to_string(), + value:cpus.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + pub fn track_version(&self, version:&str) -> &Self { + self.track(Event { + key:"turbo_version".to_string(), + value:version.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + // args + pub fn track_arg_usage(&self, arg:&str, is_set:bool) -> &Self { + self.track(Event { + key:format!("arg:{}", arg), + value:if is_set { "set" } else { "default" }.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + pub fn track_arg_value(&self, arg:&str, val:impl Display, is_sensitive:EventType) -> &Self { + self.track(Event { + key:format!("arg:{}", arg), + value:val.to_string(), + is_sensitive, + send_in_ci:true, + }); + self + } + + // run data + pub fn track_is_linked(&self, is_linked:bool) -> &Self { + self.track(Event { + key:"is_linked".to_string(), + value:if is_linked { "true" } else { "false" }.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + pub fn track_remote_cache(&self, cache_url:&str) -> &Self { + self.track(Event { + key:"remote_cache_url".to_string(), + value:cache_url.to_string(), + is_sensitive:if RC_URL_ALLOWLIST.contains(&cache_url) { + EventType::NonSensitive + } else { + EventType::Sensitive + }, + send_in_ci:true, + }); + self + } + + pub fn track_ci(&self, ci:Option<&'static str>) -> &Self { + if let Some(ci) = ci { + self.track(Event { + key:"ci".to_string(), + value:ci.to_string(), + is_sensitive:EventType::NonSensitive, + // yo dawg + send_in_ci:true, + }); + } + self + } + + pub fn track_run_type(&self, is_dry:bool) -> &Self { + self.track(Event { + key:"run_type".to_string(), + value:if is_dry { "dry" } else { "full" }.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + pub fn track_daemon_init(&self, status:DaemonInitStatus) -> &Self { + self.track(Event { + key:"daemon_status".to_string(), + value:match status { + DaemonInitStatus::Skipped => "skipped".to_string(), + DaemonInitStatus::Started => "started".to_string(), + DaemonInitStatus::Failed => "failed".to_string(), + DaemonInitStatus::Disabled => "disabled".to_string(), + }, + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } + + // errors + pub fn track_error(&self, error:TrackedErrors) -> &Self { + self.track(Event { + key:"error".to_string(), + value:error.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } +} diff --git a/crates/turborepo-telemetry/Source/events/mod.rs b/crates/turborepo-telemetry/Source/events/mod.rs new file mode 100644 index 0000000000000..28e8b76d49444 --- /dev/null +++ b/crates/turborepo-telemetry/Source/events/mod.rs @@ -0,0 +1,100 @@ +use std::fmt::Display; + +use serde::{Deserialize, Serialize}; + +// all event builders and their event methods +pub mod command; +pub mod generic; +pub mod repo; +pub mod task; + +/// All possible telemetry events must be included in this enum. +/// These events must be added to the backend (telemetry.vercel.com) +/// before they can be tracked - invalid or unknown events will be +/// ignored. +pub use turborepo_vercel_api::telemetry::TelemetryEvent; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum EventType { + Sensitive, + NonSensitive, +} + +/// Key-value pairs that are sent with each even - if the value is +/// sensitive, it will be hashed and anonymized before being sent +/// using the users private salt. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Event { + key:String, + value:String, + is_sensitive:EventType, + send_in_ci:bool, +} + +pub trait Identifiable { + fn get_id(&self) -> &String; +} + +/// Public trait that can be used for building telemetry events. +/// Supports connecting events via a parent-child relationship +/// to aid in connecting events together. +pub trait EventBuilder { + fn with_parent(self, parent_event:&U) -> Self; + fn track(&self, event:Event); + fn child(&self) -> Self; +} + +pub enum TrackedErrors { + // daemon errors + DaemonFailedToMarkOutputsAsCached, + DaemonSkipOutputRestoreCheckFailed, + // other + RecursiveError, + UnableToFlushOutputClient, + FailedToCaptureOutputs, + ErrorFetchingFromCache, + FailedToPipeOutputs, + UnknownChildExit, + /// Yielded when package discovery yields a + /// list of packages that fails downstream. + /// Currently only indicates a package being + /// reported when it does not exist. + InvalidPackageDiscovery, +} + +impl Display for TrackedErrors { + fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TrackedErrors::DaemonFailedToMarkOutputsAsCached => { + write!(f, "daemon:failed_to_mark_outputs_as_cached") + }, + TrackedErrors::DaemonSkipOutputRestoreCheckFailed => { + write!(f, "daemon:skip_output_restore_check_failed") + }, + TrackedErrors::RecursiveError => write!(f, "recursive_error"), + TrackedErrors::UnableToFlushOutputClient => write!(f, "unable_to_flush_output_client"), + TrackedErrors::FailedToCaptureOutputs => write!(f, "failed_to_capture_outputs"), + TrackedErrors::ErrorFetchingFromCache => write!(f, "error_fetching_from_cache"), + TrackedErrors::FailedToPipeOutputs => write!(f, "failed_to_pipe_outputs"), + TrackedErrors::UnknownChildExit => write!(f, "unknown_child_exit"), + TrackedErrors::InvalidPackageDiscovery => write!(f, "invalid_package_discovery"), + } + } +} + +#[macro_export] +macro_rules! track_usage { + ($tel:expr, $field:expr, $is_used:expr) => { + if $is_used($field) { + $tel.track_arg_usage( + stringify!($field) + .trim_start_matches("&") + .trim_start_matches("self.") + .replace("_", "-") + .as_str(), + true, + ); + } + }; +} diff --git a/crates/turborepo-telemetry/Source/events/repo.rs b/crates/turborepo-telemetry/Source/events/repo.rs new file mode 100644 index 0000000000000..deaa47772e389 --- /dev/null +++ b/crates/turborepo-telemetry/Source/events/repo.rs @@ -0,0 +1,92 @@ +use serde::{Deserialize, Serialize}; +use turborepo_vercel_api::telemetry::{TelemetryEvent, TelemetryRepoEvent}; +use uuid::Uuid; + +use super::{Event, EventBuilder, EventType, Identifiable}; +use crate::{config::TelemetryConfig, telem}; + +pub enum RepoType { + SinglePackage, + Monorepo, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RepoEventBuilder { + id:String, + repo:String, + parent_id:Option, + is_ci:bool, +} + +impl Identifiable for RepoEventBuilder { + fn get_id(&self) -> &String { &self.id } +} + +impl EventBuilder for RepoEventBuilder { + fn with_parent(mut self, parent_event:&U) -> Self { + self.parent_id = Some(parent_event.get_id().clone()); + self + } + + fn track(&self, event:Event) { + let val = match event.is_sensitive { + EventType::Sensitive => TelemetryConfig::one_way_hash(&event.value), + EventType::NonSensitive => event.value.to_string(), + }; + + telem(TelemetryEvent::Repo(TelemetryRepoEvent { + id:self.id.clone(), + repo:self.repo.clone(), + key:event.key, + value:val, + parent_id:self.parent_id.clone(), + })); + } + + fn child(&self) -> Self { Self::new(&self.repo).with_parent(self) } +} + +// events +impl RepoEventBuilder { + pub fn new(repo_identifier:&str) -> Self { + Self { + id:Uuid::new_v4().to_string(), + repo:TelemetryConfig::one_way_hash(repo_identifier), + parent_id:None, + is_ci:turborepo_ci::is_ci(), + } + } + + pub fn track_package_manager(&self, name:String) -> &Self { + self.track(Event { + key:"package_manager".to_string(), + value:name.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + pub fn track_type(&self, repo_type:RepoType) -> &Self { + self.track(Event { + key:"repo_type".to_string(), + value:match repo_type { + RepoType::SinglePackage => "single_package".to_string(), + RepoType::Monorepo => "monorepo".to_string(), + }, + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } + + pub fn track_size(&self, size:usize) -> &Self { + self.track(Event { + key:"workspace_count".to_string(), + value:size.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } +} diff --git a/crates/turborepo-telemetry/Source/events/task.rs b/crates/turborepo-telemetry/Source/events/task.rs new file mode 100644 index 0000000000000..050f0fc94ffa3 --- /dev/null +++ b/crates/turborepo-telemetry/Source/events/task.rs @@ -0,0 +1,146 @@ +use serde::{Deserialize, Serialize}; +use turborepo_vercel_api::telemetry::{TelemetryEvent, TelemetryTaskEvent}; +use uuid::Uuid; + +use super::{Event, EventBuilder, EventType, Identifiable, TrackedErrors}; +use crate::{config::TelemetryConfig, telem}; + +// task names that will be passed through to the API without obfuscation +const ALLOWLIST:[&str; 8] = [ + "build", + "test", + "lint", + "typecheck", + "checktypes", + "check-types", + "type-check", + "check", +]; + +pub enum FileHashMethod { + Git, + Manual, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PackageTaskEventBuilder { + id:String, + package:String, + task:String, + parent_id:Option, + is_ci:bool, +} + +impl Identifiable for PackageTaskEventBuilder { + fn get_id(&self) -> &String { &self.id } +} + +impl EventBuilder for PackageTaskEventBuilder { + fn with_parent(mut self, parent_event:&U) -> Self { + self.parent_id = Some(parent_event.get_id().clone()); + self + } + + fn track(&self, event:Event) { + if self.is_ci && !event.send_in_ci { + return; + } + + let val = match event.is_sensitive { + EventType::Sensitive => TelemetryConfig::one_way_hash(&event.value), + EventType::NonSensitive => event.value.to_string(), + }; + + telem(TelemetryEvent::Task(TelemetryTaskEvent { + id:self.id.clone(), + package:self.package.clone(), + task:self.task.clone(), + parent_id:self.parent_id.clone(), + key:event.key, + value:val, + })); + } + + fn child(&self) -> Self { Self::new(&self.package, &self.task).with_parent(self) } +} + +impl PackageTaskEventBuilder { + pub fn new(package:&str, task:&str) -> Self { + // don't obfuscate the package in development mode + let package = if cfg!(debug_assertions) { + package.to_string() + } else { + TelemetryConfig::one_way_hash(package) + }; + + // don't obfuscate the task in development mode or if it's in the allowlist + let task = if cfg!(debug_assertions) || ALLOWLIST.contains(&task) { + task.to_string() + } else { + TelemetryConfig::one_way_hash(task) + }; + + Self { + id:Uuid::new_v4().to_string(), + parent_id:None, + package, + task, + is_ci:turborepo_ci::is_ci(), + } + } + + // event methods + pub fn track_framework(&self, framework:String) -> &Self { + self.track(Event { + key:"framework".to_string(), + value:framework, + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } + + pub fn track_env_mode(&self, mode:&str) -> &Self { + self.track(Event { + key:"env_mode".to_string(), + value:mode.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } + + pub fn track_file_hash_method(&self, method:FileHashMethod) -> &Self { + self.track(Event { + key:"file_hash_method".to_string(), + value:match method { + FileHashMethod::Git => "git".to_string(), + FileHashMethod::Manual => "manual".to_string(), + }, + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } + + pub fn track_scm_mode(&self, method:&str) -> &Self { + self.track(Event { + key:"scm_mode".to_string(), + value:method.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:false, + }); + self + } + + // errors + pub fn track_error(&self, error:TrackedErrors) -> &Self { + self.track(Event { + key:"error".to_string(), + value:error.to_string(), + is_sensitive:EventType::NonSensitive, + send_in_ci:true, + }); + self + } +} diff --git a/crates/turborepo-telemetry/src/lib.rs b/crates/turborepo-telemetry/Source/lib.rs similarity index 100% rename from crates/turborepo-telemetry/src/lib.rs rename to crates/turborepo-telemetry/Source/lib.rs diff --git a/crates/turborepo-telemetry/src/config.rs b/crates/turborepo-telemetry/src/config.rs deleted file mode 100644 index 285019adb4ac9..0000000000000 --- a/crates/turborepo-telemetry/src/config.rs +++ /dev/null @@ -1,279 +0,0 @@ -/// Configuration for telemetry. -/// -/// This module is responsible for reading and writing the telemetry -/// configuration file. -/// -/// NOTE: There is a port of this crate that is used to instrument node -/// projects. Any changes made here should be reflected there as well. -/// -/// https://github.com/vercel/turborepo/blob/main/packages/turbo-telemetry/src/config.ts -use std::env; - -use chrono::{DateTime, Utc}; -pub use config::{Config, ConfigError, File, FileFormat}; -use serde::{Deserialize, Serialize}; -use sha2::{Digest, Sha256}; -use tracing::{error, trace}; -use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; -use turborepo_dirs::config_dir; -use turborepo_ui::{color, ColorConfig, BOLD, GREY, UNDERLINE}; -use uuid::Uuid; - -static DEBUG_ENV_VAR: &str = "TURBO_TELEMETRY_DEBUG"; -static DISABLED_ENV_VAR: &str = "TURBO_TELEMETRY_DISABLED"; -static DISABLED_MESSAGE_ENV_VAR: &str = "TURBO_TELEMETRY_MESSAGE_DISABLED"; -static DO_NOT_TRACK_ENV_VAR: &str = "DO_NOT_TRACK"; - -#[derive(Debug, Deserialize, Serialize)] -pub struct TelemetryConfigContents { - // whether or not telemetry is enabled - telemetry_enabled: bool, - // randomized and salted machine id - used for linking events together - telemetry_id: String, - // private salt used to anonymize event data (telemetry_id, task names, package names, etc.) - - // this is generated on first run and never leaves the machine - telemetry_salt: String, - - // when the alert was shown - #[serde(skip_serializing_if = "Option::is_none")] - telemetry_alerted: Option>, -} - -impl Default for TelemetryConfigContents { - fn default() -> Self { - let telemetry_salt = Uuid::new_v4().to_string(); - let raw_telemetry_id = Uuid::new_v4().to_string(); - let telemetry_id = one_way_hash_with_salt(&telemetry_salt, &raw_telemetry_id); - - TelemetryConfigContents { - telemetry_enabled: true, - telemetry_alerted: None, - telemetry_salt, - telemetry_id, - } - } -} - -#[derive(Debug)] -pub struct TelemetryConfig { - config_path: AbsoluteSystemPathBuf, - config: TelemetryConfigContents, -} - -impl TelemetryConfig { - pub fn with_default_config_path() -> Result { - let config_path = default_config_path()?; - TelemetryConfig::new(config_path) - } - - pub fn new(config_path: AbsoluteSystemPathBuf) -> Result { - trace!("Telemetry config path: {}", config_path); - if !config_path.exists() { - write_new_config(&config_path)?; - } - - let mut settings = Config::builder(); - settings = settings.add_source(File::new(config_path.as_str(), FileFormat::Json)); - let settings = settings.build(); - - // If this is a FileParse error, we assume something corrupted the file or - // its structure. In this case, because the telemetry config is intentionally - // isolated from other turborepo config, try to remove the entire config - // file and write a new one, otherwise return the error - let config = match settings { - Ok(settings) => settings.try_deserialize::()?, - Err(ConfigError::FileParse { .. }) => { - config_path - .remove_file() - .map_err(|e| ConfigError::Message(e.to_string()))?; - write_new_config(&config_path)?; - return Err(settings.unwrap_err()); - } - // Propagate other errors - Err(err) => return Err(err), - }; - - let config = TelemetryConfig { - config_path, - config, - }; - - Ok(config) - } - - fn write(&self) -> Result<(), ConfigError> { - let serialized = serde_json::to_string_pretty(&self.config) - .map_err(|e| ConfigError::Message(e.to_string()))?; - self.config_path - .create_with_contents(serialized) - .map_err(|e| ConfigError::Message(e.to_string()))?; - Ok(()) - } - - pub fn one_way_hash(input: &str) -> String { - match TelemetryConfig::with_default_config_path() { - Ok(config) => config.one_way_hash_with_config_salt(input), - Err(_) => TelemetryConfig::one_way_hash_with_tmp_salt(input), - } - } - - /// Obfuscate with the config salt - this is used for all sensitive event - /// data - fn one_way_hash_with_config_salt(&self, input: &str) -> String { - one_way_hash_with_salt(&self.config.telemetry_salt, input) - } - - /// Obfuscate with a temporary salt - this is used as a fallback when the - /// config salt is not available (e.g. config loading failed etc.) - /// - /// This is just as secure as the config salt, but it prevents us from - /// linking together events that include obfuscated data generated with - /// this method as each call will generate a new salt. - fn one_way_hash_with_tmp_salt(input: &str) -> String { - let tmp_salt = Uuid::new_v4().to_string(); - one_way_hash_with_salt(&tmp_salt, input) - } - - pub fn show_alert(&mut self, color_config: ColorConfig) { - if !self.has_seen_alert() && self.is_enabled() && Self::is_telemetry_warning_enabled() { - eprintln!( - "\n{}\n{}\n{}\n{}\n{}\n", - color!(color_config, BOLD, "{}", "Attention:"), - color!( - color_config, - GREY, - "{}", - "Turborepo now collects completely anonymous telemetry regarding usage." - ), - color!( - color_config, - GREY, - "{}", - "This information is used to shape the Turborepo roadmap and prioritize \ - features." - ), - color!( - color_config, - GREY, - "{}", - "You can learn more, including how to opt-out if you'd not like to \ - participate in this anonymous program, by visiting the following URL:" - ), - color!( - color_config, - UNDERLINE, - "{}", - color!( - color_config, - GREY, - "{}", - "https://turbo.build/repo/docs/telemetry" - ) - ), - ); - - if let Err(err) = self.alert_shown() { - error!( - "Error saving seen alert event to telemetry config: {:?}", - err - ); - } - } - } - - // getters - pub fn has_seen_alert(&self) -> bool { - self.config.telemetry_alerted.is_some() - } - - pub fn is_enabled(&self) -> bool { - let do_not_track = env::var(DO_NOT_TRACK_ENV_VAR).unwrap_or("0".to_string()); - let turbo_telemetry_disabled = env::var(DISABLED_ENV_VAR).unwrap_or("0".to_string()); - - if do_not_track == "1" - || do_not_track == "true" - || turbo_telemetry_disabled == "1" - || turbo_telemetry_disabled == "true" - { - return false; - } - - self.config.telemetry_enabled - } - - pub fn is_telemetry_warning_enabled() -> bool { - let turbo_telemetry_msg_disabled = - env::var(DISABLED_MESSAGE_ENV_VAR).unwrap_or("0".to_string()); - let is_disabled = - turbo_telemetry_msg_disabled == "1" || turbo_telemetry_msg_disabled == "true"; - - !is_disabled - } - - pub fn get_id(&self) -> &str { - &self.config.telemetry_id - } - - // setters - pub fn enable(&mut self) -> Result<&TelemetryConfigContents, ConfigError> { - self.config.telemetry_enabled = true; - self.write()?; - Ok(&self.config) - } - - pub fn disable(&mut self) -> Result<&TelemetryConfigContents, ConfigError> { - self.config.telemetry_enabled = false; - self.write()?; - Ok(&self.config) - } - - pub fn alert_shown(&mut self) -> Result<&TelemetryConfigContents, ConfigError> { - match self.has_seen_alert() { - true => Ok(&self.config), - false => { - self.config.telemetry_alerted = Some(Utc::now()); - self.write()?; - Ok(&self.config) - } - } - } -} - -fn default_config_path() -> Result { - let config_dir = config_dir() - .map_err(|e| ConfigError::Message(format!("Invalid config directory: {}", e)))? - .ok_or(ConfigError::Message( - "Unable to find telemetry config directory".to_string(), - ))?; - // stored as a sibling to the turbo global config - Ok(config_dir.join_components(&["turborepo", "telemetry.json"])) -} - -fn write_new_config(file_path: &AbsoluteSystemPath) -> Result<(), ConfigError> { - let serialized = serde_json::to_string_pretty(&TelemetryConfigContents::default()) - .map_err(|e| ConfigError::Message(e.to_string()))?; - - // Create the directory if it doesn't exist - file_path - .ensure_dir() - .map_err(|_| ConfigError::Message("Failed to create directory".to_string()))?; - - // Write the file - file_path - .create_with_contents(serialized) - .map_err(|e| ConfigError::Message(e.to_string()))?; - Ok(()) -} - -pub fn is_debug() -> bool { - let debug = env::var(DEBUG_ENV_VAR).unwrap_or("0".to_string()); - debug == "1" || debug == "true" -} - -fn one_way_hash_with_salt(salt: &str, input: &str) -> String { - let salted = format!("{}{}", salt, input); - let mut hasher = Sha256::new(); - hasher.update(salted.as_bytes()); - let generic = hasher.finalize(); - hex::encode(generic) -} diff --git a/crates/turborepo-telemetry/src/events/generic.rs b/crates/turborepo-telemetry/src/events/generic.rs deleted file mode 100644 index c561d066041e8..0000000000000 --- a/crates/turborepo-telemetry/src/events/generic.rs +++ /dev/null @@ -1,226 +0,0 @@ -use std::fmt::Display; - -use serde::{Deserialize, Serialize}; -use turborepo_vercel_api::telemetry::{TelemetryEvent, TelemetryGenericEvent}; -use uuid::Uuid; - -use super::{Event, EventBuilder, EventType, Identifiable, TrackedErrors}; -use crate::{config::TelemetryConfig, telem}; - -// Remote cache URL's that will be passed through to the API without obfuscation -const RC_URL_ALLOWLIST: [&str; 1] = ["https://vercel.com/api"]; - -pub enum DaemonInitStatus { - // skipped due to context (running in CI etc) - Skipped, - /// daemon was started - Started, - /// daemon failed to start - Failed, - /// daemon was manually disabled by user - Disabled, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct GenericEventBuilder { - id: String, - parent_id: Option, - is_ci: bool, -} - -impl Identifiable for GenericEventBuilder { - fn get_id(&self) -> &String { - &self.id - } -} - -impl EventBuilder for GenericEventBuilder { - fn with_parent(mut self, parent_event: &U) -> Self { - self.parent_id = Some(parent_event.get_id().clone()); - self - } - - fn track(&self, event: Event) { - if self.is_ci && !event.send_in_ci { - return; - } - - let val = match event.is_sensitive { - EventType::Sensitive => TelemetryConfig::one_way_hash(&event.value), - EventType::NonSensitive => event.value.to_string(), - }; - - telem(TelemetryEvent::Generic(TelemetryGenericEvent { - id: self.id.clone(), - parent_id: self.parent_id.clone(), - key: event.key, - value: val, - })); - } - - fn child(&self) -> Self { - Self::new().with_parent(self) - } -} - -impl Default for GenericEventBuilder { - fn default() -> Self { - Self { - id: Uuid::new_v4().to_string(), - parent_id: None, - is_ci: turborepo_ci::is_ci(), - } - } -} - -// events -impl GenericEventBuilder { - pub fn new() -> Self { - Self::default() - } - - pub fn track_start(&self) -> &Self { - self.track(Event { - key: "execution".to_string(), - value: "started".to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } - - pub fn track_end(&self) -> &Self { - self.track(Event { - key: "execution".to_string(), - value: "ended".to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } - - pub fn track_platform(&self, platform: &str) -> &Self { - self.track(Event { - key: "platform".to_string(), - value: platform.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - pub fn track_cpus(&self, cpus: usize) -> &Self { - self.track(Event { - key: "cpu_count".to_string(), - value: cpus.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - pub fn track_version(&self, version: &str) -> &Self { - self.track(Event { - key: "turbo_version".to_string(), - value: version.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - // args - pub fn track_arg_usage(&self, arg: &str, is_set: bool) -> &Self { - self.track(Event { - key: format!("arg:{}", arg), - value: if is_set { "set" } else { "default" }.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - pub fn track_arg_value(&self, arg: &str, val: impl Display, is_sensitive: EventType) -> &Self { - self.track(Event { - key: format!("arg:{}", arg), - value: val.to_string(), - is_sensitive, - send_in_ci: true, - }); - self - } - - // run data - pub fn track_is_linked(&self, is_linked: bool) -> &Self { - self.track(Event { - key: "is_linked".to_string(), - value: if is_linked { "true" } else { "false" }.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - pub fn track_remote_cache(&self, cache_url: &str) -> &Self { - self.track(Event { - key: "remote_cache_url".to_string(), - value: cache_url.to_string(), - is_sensitive: if RC_URL_ALLOWLIST.contains(&cache_url) { - EventType::NonSensitive - } else { - EventType::Sensitive - }, - send_in_ci: true, - }); - self - } - - pub fn track_ci(&self, ci: Option<&'static str>) -> &Self { - if let Some(ci) = ci { - self.track(Event { - key: "ci".to_string(), - value: ci.to_string(), - is_sensitive: EventType::NonSensitive, - // yo dawg - send_in_ci: true, - }); - } - self - } - - pub fn track_run_type(&self, is_dry: bool) -> &Self { - self.track(Event { - key: "run_type".to_string(), - value: if is_dry { "dry" } else { "full" }.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - pub fn track_daemon_init(&self, status: DaemonInitStatus) -> &Self { - self.track(Event { - key: "daemon_status".to_string(), - value: match status { - DaemonInitStatus::Skipped => "skipped".to_string(), - DaemonInitStatus::Started => "started".to_string(), - DaemonInitStatus::Failed => "failed".to_string(), - DaemonInitStatus::Disabled => "disabled".to_string(), - }, - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } - - // errors - pub fn track_error(&self, error: TrackedErrors) -> &Self { - self.track(Event { - key: "error".to_string(), - value: error.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } -} diff --git a/crates/turborepo-telemetry/src/events/mod.rs b/crates/turborepo-telemetry/src/events/mod.rs deleted file mode 100644 index fc2318a589c22..0000000000000 --- a/crates/turborepo-telemetry/src/events/mod.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::fmt::Display; - -use serde::{Deserialize, Serialize}; - -// all event builders and their event methods -pub mod command; -pub mod generic; -pub mod repo; -pub mod task; - -/// All possible telemetry events must be included in this enum. -/// These events must be added to the backend (telemetry.vercel.com) -/// before they can be tracked - invalid or unknown events will be -/// ignored. -pub use turborepo_vercel_api::telemetry::TelemetryEvent; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum EventType { - Sensitive, - NonSensitive, -} - -/// Key-value pairs that are sent with each even - if the value is -/// sensitive, it will be hashed and anonymized before being sent -/// using the users private salt. -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Event { - key: String, - value: String, - is_sensitive: EventType, - send_in_ci: bool, -} - -pub trait Identifiable { - fn get_id(&self) -> &String; -} - -/// Public trait that can be used for building telemetry events. -/// Supports connecting events via a parent-child relationship -/// to aid in connecting events together. -pub trait EventBuilder { - fn with_parent(self, parent_event: &U) -> Self; - fn track(&self, event: Event); - fn child(&self) -> Self; -} - -pub enum TrackedErrors { - // daemon errors - DaemonFailedToMarkOutputsAsCached, - DaemonSkipOutputRestoreCheckFailed, - // other - RecursiveError, - UnableToFlushOutputClient, - FailedToCaptureOutputs, - ErrorFetchingFromCache, - FailedToPipeOutputs, - UnknownChildExit, - /// Yielded when package discovery yields a - /// list of packages that fails downstream. - /// Currently only indicates a package being - /// reported when it does not exist. - InvalidPackageDiscovery, -} - -impl Display for TrackedErrors { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - TrackedErrors::DaemonFailedToMarkOutputsAsCached => { - write!(f, "daemon:failed_to_mark_outputs_as_cached") - } - TrackedErrors::DaemonSkipOutputRestoreCheckFailed => { - write!(f, "daemon:skip_output_restore_check_failed") - } - TrackedErrors::RecursiveError => write!(f, "recursive_error"), - TrackedErrors::UnableToFlushOutputClient => write!(f, "unable_to_flush_output_client"), - TrackedErrors::FailedToCaptureOutputs => write!(f, "failed_to_capture_outputs"), - TrackedErrors::ErrorFetchingFromCache => write!(f, "error_fetching_from_cache"), - TrackedErrors::FailedToPipeOutputs => write!(f, "failed_to_pipe_outputs"), - TrackedErrors::UnknownChildExit => write!(f, "unknown_child_exit"), - TrackedErrors::InvalidPackageDiscovery => write!(f, "invalid_package_discovery"), - } - } -} - -#[macro_export] -macro_rules! track_usage { - ($tel:expr, $field:expr, $is_used:expr) => { - if $is_used($field) { - $tel.track_arg_usage( - stringify!($field) - .trim_start_matches("&") - .trim_start_matches("self.") - .replace("_", "-") - .as_str(), - true, - ); - } - }; -} diff --git a/crates/turborepo-telemetry/src/events/repo.rs b/crates/turborepo-telemetry/src/events/repo.rs deleted file mode 100644 index 3a02df1ddd4a6..0000000000000 --- a/crates/turborepo-telemetry/src/events/repo.rs +++ /dev/null @@ -1,96 +0,0 @@ -use serde::{Deserialize, Serialize}; -use turborepo_vercel_api::telemetry::{TelemetryEvent, TelemetryRepoEvent}; -use uuid::Uuid; - -use super::{Event, EventBuilder, EventType, Identifiable}; -use crate::{config::TelemetryConfig, telem}; - -pub enum RepoType { - SinglePackage, - Monorepo, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RepoEventBuilder { - id: String, - repo: String, - parent_id: Option, - is_ci: bool, -} - -impl Identifiable for RepoEventBuilder { - fn get_id(&self) -> &String { - &self.id - } -} - -impl EventBuilder for RepoEventBuilder { - fn with_parent(mut self, parent_event: &U) -> Self { - self.parent_id = Some(parent_event.get_id().clone()); - self - } - - fn track(&self, event: Event) { - let val = match event.is_sensitive { - EventType::Sensitive => TelemetryConfig::one_way_hash(&event.value), - EventType::NonSensitive => event.value.to_string(), - }; - - telem(TelemetryEvent::Repo(TelemetryRepoEvent { - id: self.id.clone(), - repo: self.repo.clone(), - key: event.key, - value: val, - parent_id: self.parent_id.clone(), - })); - } - - fn child(&self) -> Self { - Self::new(&self.repo).with_parent(self) - } -} - -// events -impl RepoEventBuilder { - pub fn new(repo_identifier: &str) -> Self { - Self { - id: Uuid::new_v4().to_string(), - repo: TelemetryConfig::one_way_hash(repo_identifier), - parent_id: None, - is_ci: turborepo_ci::is_ci(), - } - } - - pub fn track_package_manager(&self, name: String) -> &Self { - self.track(Event { - key: "package_manager".to_string(), - value: name.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - pub fn track_type(&self, repo_type: RepoType) -> &Self { - self.track(Event { - key: "repo_type".to_string(), - value: match repo_type { - RepoType::SinglePackage => "single_package".to_string(), - RepoType::Monorepo => "monorepo".to_string(), - }, - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } - - pub fn track_size(&self, size: usize) -> &Self { - self.track(Event { - key: "workspace_count".to_string(), - value: size.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } -} diff --git a/crates/turborepo-telemetry/src/events/task.rs b/crates/turborepo-telemetry/src/events/task.rs deleted file mode 100644 index 17ab9302cc354..0000000000000 --- a/crates/turborepo-telemetry/src/events/task.rs +++ /dev/null @@ -1,150 +0,0 @@ -use serde::{Deserialize, Serialize}; -use turborepo_vercel_api::telemetry::{TelemetryEvent, TelemetryTaskEvent}; -use uuid::Uuid; - -use super::{Event, EventBuilder, EventType, Identifiable, TrackedErrors}; -use crate::{config::TelemetryConfig, telem}; - -// task names that will be passed through to the API without obfuscation -const ALLOWLIST: [&str; 8] = [ - "build", - "test", - "lint", - "typecheck", - "checktypes", - "check-types", - "type-check", - "check", -]; - -pub enum FileHashMethod { - Git, - Manual, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct PackageTaskEventBuilder { - id: String, - package: String, - task: String, - parent_id: Option, - is_ci: bool, -} - -impl Identifiable for PackageTaskEventBuilder { - fn get_id(&self) -> &String { - &self.id - } -} - -impl EventBuilder for PackageTaskEventBuilder { - fn with_parent(mut self, parent_event: &U) -> Self { - self.parent_id = Some(parent_event.get_id().clone()); - self - } - - fn track(&self, event: Event) { - if self.is_ci && !event.send_in_ci { - return; - } - - let val = match event.is_sensitive { - EventType::Sensitive => TelemetryConfig::one_way_hash(&event.value), - EventType::NonSensitive => event.value.to_string(), - }; - - telem(TelemetryEvent::Task(TelemetryTaskEvent { - id: self.id.clone(), - package: self.package.clone(), - task: self.task.clone(), - parent_id: self.parent_id.clone(), - key: event.key, - value: val, - })); - } - - fn child(&self) -> Self { - Self::new(&self.package, &self.task).with_parent(self) - } -} - -impl PackageTaskEventBuilder { - pub fn new(package: &str, task: &str) -> Self { - // don't obfuscate the package in development mode - let package = if cfg!(debug_assertions) { - package.to_string() - } else { - TelemetryConfig::one_way_hash(package) - }; - - // don't obfuscate the task in development mode or if it's in the allowlist - let task = if cfg!(debug_assertions) || ALLOWLIST.contains(&task) { - task.to_string() - } else { - TelemetryConfig::one_way_hash(task) - }; - - Self { - id: Uuid::new_v4().to_string(), - parent_id: None, - package, - task, - is_ci: turborepo_ci::is_ci(), - } - } - - // event methods - pub fn track_framework(&self, framework: String) -> &Self { - self.track(Event { - key: "framework".to_string(), - value: framework, - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } - - pub fn track_env_mode(&self, mode: &str) -> &Self { - self.track(Event { - key: "env_mode".to_string(), - value: mode.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } - - pub fn track_file_hash_method(&self, method: FileHashMethod) -> &Self { - self.track(Event { - key: "file_hash_method".to_string(), - value: match method { - FileHashMethod::Git => "git".to_string(), - FileHashMethod::Manual => "manual".to_string(), - }, - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } - - pub fn track_scm_mode(&self, method: &str) -> &Self { - self.track(Event { - key: "scm_mode".to_string(), - value: method.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: false, - }); - self - } - - // errors - pub fn track_error(&self, error: TrackedErrors) -> &Self { - self.track(Event { - key: "error".to_string(), - value: error.to_string(), - is_sensitive: EventType::NonSensitive, - send_in_ci: true, - }); - self - } -} diff --git a/crates/turborepo-ui/Cargo.toml b/crates/turborepo-ui/Cargo.toml index 0a2e0997b4eb3..fbf9b79efa80a 100644 --- a/crates/turborepo-ui/Cargo.toml +++ b/crates/turborepo-ui/Cargo.toml @@ -1,19 +1,3 @@ -[package] -name = "turborepo-ui" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dev-dependencies] -anyhow = { workspace = true } -indoc = { workspace = true } -tempfile = { workspace = true } -test-case = { workspace = true } - -[lints] -workspace = true - [dependencies] async-graphql = { workspace = true } async-graphql-axum = { workspace = true } @@ -28,7 +12,6 @@ crossterm = { version = "0.27.0", features = ["event-stream"] } dialoguer = { workspace = true } futures = { workspace = true } indicatif = { workspace = true } -itertools.workspace = true lazy_static = { workspace = true } nix = { version = "0.26.2", features = ["signal"] } ratatui = { workspace = true } @@ -43,6 +26,31 @@ turborepo-ci = { workspace = true } turborepo-vt100 = { workspace = true } which = { workspace = true } +[dependencies.itertools] +workspace = true + +[dev-dependencies] +anyhow = { workspace = true } +indoc = { workspace = true } +tempfile = { workspace = true } +test-case = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-ui" +version = "0.1.0" + +[target] + +[target."cfg(windows)"] + [target."cfg(windows)".dependencies] clipboard-win = "5.3.1" windows-sys = { version = "0.59", features = ["Win32_System_Console"] } diff --git a/crates/turborepo-ui/Source/color_selector.rs b/crates/turborepo-ui/Source/color_selector.rs new file mode 100644 index 0000000000000..ad476971d8647 --- /dev/null +++ b/crates/turborepo-ui/Source/color_selector.rs @@ -0,0 +1,117 @@ +use std::{ + collections::HashMap, + sync::{Arc, OnceLock, RwLock}, +}; + +use console::{Style, StyledObject}; + +static COLORS:OnceLock<[Style; 5]> = OnceLock::new(); + +pub fn get_terminal_package_colors() -> &'static [Style; 5] { + COLORS.get_or_init(|| { + [ + Style::new().cyan(), + Style::new().magenta(), + Style::new().green(), + Style::new().yellow(), + Style::new().blue(), + ] + }) +} + +/// Selects colors for tasks and caches accordingly. +/// Shared between tasks so allows for concurrent access. +#[derive(Default)] +pub struct ColorSelector { + inner:Arc>, +} + +#[derive(Default)] +struct ColorSelectorInner { + idx:usize, + cache:HashMap, +} + +impl ColorSelector { + pub fn color_for_key(&self, key:&str) -> &'static Style { + if let Some(style) = self.inner.read().expect("lock poisoned").color(key) { + return style; + } + + let color = { self.inner.write().expect("lock poisoned").insert_color(key.to_string()) }; + + color + } + + pub fn prefix_with_color(&self, cache_key:&str, prefix:&str) -> StyledObject { + if prefix.is_empty() { + return Style::new().apply_to(String::new()); + } + + let style = self.color_for_key(cache_key); + style.apply_to(format!("{}: ", prefix)) + } +} + +impl ColorSelectorInner { + fn color(&self, key:&str) -> Option<&'static Style> { self.cache.get(key).copied() } + + fn insert_color(&mut self, key:String) -> &'static Style { + let colors = get_terminal_package_colors(); + let chosen_color = &colors[self.idx % colors.len()]; + // A color might have been chosen by the time we get to inserting + self.cache.entry(key).or_insert_with(|| { + // If a color hasn't been chosen, then we increment the index + self.idx += 1; + chosen_color + }) + } +} + +#[cfg(test)] +mod tests { + use std::thread; + + #[test] + fn test_color_selector() { + let selector = super::ColorSelector::default(); + let color1 = selector.color_for_key("key1"); + let color2 = selector.color_for_key("key2"); + let color3 = selector.color_for_key("key1"); + assert_eq!(color1, color3); + assert_ne!(color1, color2); + } + + #[test] + fn test_multithreaded_selector() { + let selector = super::ColorSelector::default(); + thread::scope(|s| { + s.spawn(|| { + let color = selector.color_for_key("key1"); + assert_eq!(color, selector.color_for_key("key1")); + }); + s.spawn(|| { + let color = selector.color_for_key("key2"); + assert_eq!(color, selector.color_for_key("key2")); + }); + s.spawn(|| { + let color1 = selector.color_for_key("key1"); + let color2 = selector.color_for_key("key2"); + assert_eq!(color1, selector.color_for_key("key1")); + assert_eq!(color2, selector.color_for_key("key2")); + assert_ne!(color1, color2); + }); + }); + // We only inserted 2 keys so next index should be 2 + assert_eq!(selector.inner.read().unwrap().idx, 2); + } + + #[test] + fn test_color_selector_wraps_around() { + let selector = super::ColorSelector::default(); + for key in &["1", "2", "3", "4", "5", "6"] { + selector.color_for_key(key); + } + assert_eq!(selector.color_for_key("1"), selector.color_for_key("6")); + } +} diff --git a/crates/turborepo-ui/src/lib.rs b/crates/turborepo-ui/Source/lib.rs similarity index 100% rename from crates/turborepo-ui/src/lib.rs rename to crates/turborepo-ui/Source/lib.rs diff --git a/crates/turborepo-ui/Source/line.rs b/crates/turborepo-ui/Source/line.rs new file mode 100644 index 0000000000000..147cf4ae774b9 --- /dev/null +++ b/crates/turborepo-ui/Source/line.rs @@ -0,0 +1,38 @@ +use std::io::Write; + +/// Writer that will buffer writes so the underlying writer is only called with +/// writes that end in a newline +pub struct LineWriter { + writer:W, + buffer:Vec, +} + +impl LineWriter { + pub fn new(writer:W) -> Self { Self { writer, buffer:Vec::with_capacity(512) } } +} + +impl Write for LineWriter { + fn write(&mut self, buf:&[u8]) -> std::io::Result { + for line in buf.split_inclusive(|c| *c == b'\n') { + if line.ends_with(b"\n") { + if self.buffer.is_empty() { + self.writer.write_all(line)?; + } else { + self.buffer.extend_from_slice(line); + self.writer.write_all(&self.buffer)?; + self.buffer.clear(); + } + } else { + // This should only happen on the last chunk? + self.buffer.extend_from_slice(line) + } + } + + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + // We don't flush our buffer as that would lead to a write without a newline + self.writer.flush() + } +} diff --git a/crates/turborepo-ui/src/logs.rs b/crates/turborepo-ui/Source/logs.rs similarity index 100% rename from crates/turborepo-ui/src/logs.rs rename to crates/turborepo-ui/Source/logs.rs diff --git a/crates/turborepo-ui/src/output.rs b/crates/turborepo-ui/Source/output.rs similarity index 100% rename from crates/turborepo-ui/src/output.rs rename to crates/turborepo-ui/Source/output.rs diff --git a/crates/turborepo-ui/Source/prefixed.rs b/crates/turborepo-ui/Source/prefixed.rs new file mode 100644 index 0000000000000..6a6d2ff139ee2 --- /dev/null +++ b/crates/turborepo-ui/Source/prefixed.rs @@ -0,0 +1,263 @@ +use std::{ + fmt::{Debug, Display}, + io::Write, +}; + +use console::{Style, StyledObject}; +use tracing::error; + +use crate::{ColorConfig, LineWriter}; + +/// Writes messages with different prefixes, depending on log level. +/// +/// Note that this does output the prefix when message is empty, unlike the Go +/// implementation. We do this because this behavior is what we actually +/// want for replaying logs. +pub struct PrefixedUI { + color_config:ColorConfig, + output_prefix:Option>, + warn_prefix:Option>, + error_prefix:Option>, + out:W, + err:W, + default_prefix:StyledObject, +} + +impl PrefixedUI { + pub fn new(color_config:ColorConfig, out:W, err:W) -> Self { + Self { + color_config, + out, + err, + output_prefix:None, + warn_prefix:None, + error_prefix:None, + default_prefix:Style::new().apply_to(String::new()), + } + } + + pub fn with_output_prefix(mut self, output_prefix:StyledObject) -> Self { + self.output_prefix = Some(self.color_config.apply(output_prefix)); + self + } + + pub fn with_warn_prefix(mut self, warn_prefix:StyledObject) -> Self { + self.warn_prefix = Some(self.color_config.apply(warn_prefix)); + self + } + + pub fn with_error_prefix(mut self, error_prefix:StyledObject) -> Self { + self.error_prefix = Some(self.color_config.apply(error_prefix)); + self + } + + pub fn output(&mut self, message:impl Display) { self.write_line(message, Command::Output) } + + pub fn warn(&mut self, message:impl Display) { self.write_line(message, Command::Warn) } + + pub fn error(&mut self, message:impl Display) { self.write_line(message, Command::Error) } + + fn write_line(&mut self, message:impl Display, command:Command) { + let prefix = match command { + Command::Output => &self.output_prefix, + Command::Warn => &self.warn_prefix, + Command::Error => &self.error_prefix, + } + .as_ref() + .unwrap_or(&self.default_prefix); + let writer = match command { + Command::Output => &mut self.out, + Command::Warn | Command::Error => &mut self.err, + }; + + // There's no reason to propagate this error + // because we don't want our entire program to crash + // due to a log failure. + if let Err(err) = writeln!(writer, "{}{}", prefix, message) { + error!("cannot write to logs: {:?}", err); + } + } + + /// Construct a PrefixedWriter which will behave the same as `output`, but + /// without the requirement that messages be valid UTF-8 + pub fn output_prefixed_writer(&mut self) -> PrefixedWriter<&mut W> { + PrefixedWriter::new( + self.color_config, + self.output_prefix + .clone() + .unwrap_or_else(|| Style::new().apply_to(String::new())), + &mut self.out, + ) + } +} + +// +#[derive(Debug, Clone, Copy)] +enum Command { + Output, + Warn, + Error, +} + +/// Wraps a writer with a prefix before the actual message. +pub struct PrefixedWriter { + inner:LineWriter>, +} + +impl PrefixedWriter { + pub fn new(color_config:ColorConfig, prefix:StyledObject, writer:W) -> Self { + Self { inner:LineWriter::new(PrefixedWriterInner::new(color_config, prefix, writer)) } + } +} + +impl Write for PrefixedWriter { + fn write(&mut self, buf:&[u8]) -> std::io::Result { self.inner.write(buf) } + + fn flush(&mut self) -> std::io::Result<()> { self.inner.flush() } +} + +/// Wraps a writer so that a prefix will be added at the start of each line. +/// Expects to only be called with complete lines. +struct PrefixedWriterInner { + prefix:String, + writer:W, +} + +impl PrefixedWriterInner { + pub fn new(color_config:ColorConfig, prefix:StyledObject, writer:W) -> Self { + let prefix = color_config.apply(prefix).to_string(); + Self { prefix, writer } + } +} + +impl Write for PrefixedWriterInner { + fn write(&mut self, buf:&[u8]) -> std::io::Result { + let mut is_first = true; + for chunk in buf.split_inclusive(|c| *c == b'\r') { + // Before we write the chunk we write the prefix as either: + // - this is the first iteration and we haven't written the prefix + // - the previous chunk ended with a \r and the cursor is currently as the start + // of the line so we want to rewrite the prefix over the existing prefix in + // the line + // or if the last chunk is just a newline we can skip rewriting the prefix + if is_first || chunk != b"\n" { + self.writer.write_all(self.prefix.as_bytes())?; + } + self.writer.write_all(chunk)?; + is_first = false; + } + + // We do end up writing more bytes than this to the underlying writer, but we + // cannot report this to the callers as the amount of bytes we report + // written must be less than or equal to the number of bytes in the buffer. + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { self.writer.flush() } +} + +#[cfg(test)] +mod test { + use test_case::test_case; + + use super::*; + + fn prefixed_ui(out:W, err:W, color_config:ColorConfig) -> PrefixedUI { + let output_prefix = crate::BOLD.apply_to("output ".to_string()); + let warn_prefix = crate::MAGENTA.apply_to("warn ".to_string()); + PrefixedUI::new(color_config, out, err) + .with_output_prefix(output_prefix) + .with_warn_prefix(warn_prefix) + .with_error_prefix(crate::MAGENTA.apply_to("error ".to_string())) + } + + #[test_case(false, "\u{1b}[1moutput \u{1b}[0mall good\n", Command::Output)] + #[test_case(true, "output all good\n", Command::Output)] + #[test_case(false, "\u{1b}[35mwarn \u{1b}[0mbe careful!\n", Command::Warn)] + #[test_case(true, "warn be careful!\n", Command::Warn)] + #[test_case(false, "\u{1b}[35merror \u{1b}[0mit blew up\n", Command::Error)] + #[test_case(true, "error it blew up\n", Command::Error)] + fn test_prefix_ui_outputs(strip_ansi:bool, expected:&str, cmd:Command) { + let mut out = Vec::new(); + let mut err = Vec::new(); + + let mut prefixed_ui = prefixed_ui(&mut out, &mut err, ColorConfig::new(strip_ansi)); + match cmd { + Command::Output => prefixed_ui.output("all good"), + Command::Warn => prefixed_ui.warn("be careful!"), + Command::Error => prefixed_ui.error("it blew up"), + } + + let buffer = match cmd { + Command::Output => out, + Command::Warn | Command::Error => err, + }; + assert_eq!(String::from_utf8(buffer).unwrap(), expected); + } + + #[test_case(true, "foo#build: cool!")] + #[test_case(false, "\u{1b}[1mfoo#build: \u{1b}[0mcool!")] + fn test_prefixed_writer(strip_ansi:bool, expected:&str) { + let mut buffer = Vec::new(); + let mut writer = PrefixedWriterInner::new( + ColorConfig::new(strip_ansi), + crate::BOLD.apply_to("foo#build: "), + &mut buffer, + ); + writer.write_all(b"cool!").unwrap(); + assert_eq!(String::from_utf8(buffer).unwrap(), expected); + } + + #[test_case("\ra whole message \n", "turbo > \rturbo > a whole message \n" ; "basic prefix cr")] + #[test_case("no return", "turbo > no return" ; "no return")] + #[test_case("foo\rbar\rbaz", "turbo > foo\rturbo > bar\rturbo > baz" ; "multiple crs")] + #[test_case("foo\r", "turbo > foo\r" ; "trailing cr")] + #[test_case("foo\r\n", "turbo > foo\r\n" ; "no double write on crlf")] + #[test_case("\n", "turbo > \n" ; "leading new line")] + fn test_prefixed_writer_cr(input:&str, expected:&str) { + let mut buffer = Vec::new(); + let mut writer = PrefixedWriterInner::new( + ColorConfig::new(false), + Style::new().apply_to("turbo > "), + &mut buffer, + ); + + writer.write_all(input.as_bytes()).unwrap(); + assert_eq!(String::from_utf8(buffer).unwrap(), expected); + } + + #[test_case(&["foo"], "" ; "no newline")] + #[test_case(&["\n"], "\n" ; "one newline")] + #[test_case(&["foo\n"], "foo\n" ; "single newline")] + #[test_case(&["foo ", "bar ", "baz\n"], "foo bar baz\n" ; "building line")] + #[test_case(&["multiple\nlines\nin\none"], "multiple\nlines\nin\n" ; "multiple lines")] + fn test_line_writer(inputs:&[&str], expected:&str) { + let mut buffer = Vec::new(); + let mut writer = LineWriter::new(&mut buffer); + for input in inputs { + writer.write_all(input.as_bytes()).unwrap(); + } + + assert_eq!(String::from_utf8(buffer).unwrap(), expected); + } + + #[test] + fn test_prefixed_writer_split_lines() { + let mut buffer = Vec::new(); + let mut writer = PrefixedWriter::new( + ColorConfig::new(false), + Style::new().apply_to("turbo > "), + &mut buffer, + ); + + writer.write_all(b"not a line yet").unwrap(); + writer.write_all(b", now\nbut \ranother one starts").unwrap(); + writer.write_all(b" done\n").unwrap(); + writer.write_all(b"\n").unwrap(); + assert_eq!( + String::from_utf8(buffer).unwrap(), + "turbo > not a line yet, now\nturbo > but \rturbo > another one starts done\nturbo > \ + \n" + ); + } +} diff --git a/crates/turborepo-ui/Source/sender.rs b/crates/turborepo-ui/Source/sender.rs new file mode 100644 index 0000000000000..600c6b803d626 --- /dev/null +++ b/crates/turborepo-ui/Source/sender.rs @@ -0,0 +1,150 @@ +use std::sync::{Arc, Mutex}; + +use crate::{ + tui, + tui::event::{CacheResult, OutputLogs, PaneSize, TaskResult}, + wui::sender, +}; + +/// Enum to abstract over sending events to either the Tui or the Web UI +#[derive(Debug, Clone)] +pub enum UISender { + Tui(tui::TuiSender), + Wui(sender::WebUISender), +} + +impl UISender { + pub fn start_task(&self, task:String, output_logs:OutputLogs) { + match self { + UISender::Tui(sender) => sender.start_task(task, output_logs), + UISender::Wui(sender) => sender.start_task(task, output_logs), + } + } + + pub fn restart_tasks(&self, tasks:Vec) -> Result<(), crate::Error> { + match self { + UISender::Tui(sender) => sender.restart_tasks(tasks), + UISender::Wui(sender) => sender.restart_tasks(tasks), + } + } + + pub fn end_task(&self, task:String, result:TaskResult) { + match self { + UISender::Tui(sender) => sender.end_task(task, result), + UISender::Wui(sender) => sender.end_task(task, result), + } + } + + pub fn status(&self, task:String, status:String, result:CacheResult) { + match self { + UISender::Tui(sender) => sender.status(task, status, result), + UISender::Wui(sender) => sender.status(task, status, result), + } + } + + fn set_stdin(&self, task:String, stdin:Box) { + match self { + UISender::Tui(sender) => sender.set_stdin(task, stdin), + UISender::Wui(sender) => sender.set_stdin(task, stdin), + } + } + + pub fn output(&self, task:String, output:Vec) -> Result<(), crate::Error> { + match self { + UISender::Tui(sender) => sender.output(task, output), + UISender::Wui(sender) => sender.output(task, output), + } + } + + /// Construct a sender configured for a specific task + pub fn task(&self, task:String) -> TaskSender { + match self { + UISender::Tui(sender) => sender.task(task), + UISender::Wui(sender) => sender.task(task), + } + } + + pub async fn stop(&self) { + match self { + UISender::Tui(sender) => sender.stop().await, + UISender::Wui(sender) => sender.stop(), + } + } + + pub fn update_tasks(&self, tasks:Vec) -> Result<(), crate::Error> { + match self { + UISender::Tui(sender) => sender.update_tasks(tasks), + UISender::Wui(sender) => sender.update_tasks(tasks), + } + } + + pub async fn pane_size(&self) -> Option { + match self { + UISender::Tui(sender) => sender.pane_size().await, + // Not applicable to the web UI + UISender::Wui(_) => None, + } + } +} + +#[derive(Debug, Clone)] +pub struct TaskSender { + pub(crate) name:String, + pub(crate) handle:UISender, + pub(crate) logs:Arc>>, +} + +impl TaskSender { + /// Access the underlying UISender + pub fn as_app(&self) -> &UISender { &self.handle } + + /// Mark the task as started + pub fn start(&self, output_logs:OutputLogs) { + self.handle.start_task(self.name.clone(), output_logs); + } + + /// Mark the task as finished + pub fn succeeded(&self, is_cache_hit:bool) -> Vec { + if is_cache_hit { + self.finish(TaskResult::CacheHit) + } else { + self.finish(TaskResult::Success) + } + } + + /// Mark the task as finished + pub fn failed(&self) -> Vec { self.finish(TaskResult::Failure) } + + fn finish(&self, result:TaskResult) -> Vec { + self.handle.end_task(self.name.clone(), result); + self.logs.lock().expect("logs lock poisoned").clone() + } + + pub fn set_stdin(&self, stdin:Box) { + self.handle.set_stdin(self.name.clone(), stdin); + } + + pub fn status(&self, status:&str, result:CacheResult) { + // Since this will be rendered via ratatui we any ANSI escape codes will not be + // handled. + // TODO: prevent the status from having ANSI codes in this scenario + let status = console::strip_ansi_codes(status).into_owned(); + self.handle.status(self.name.clone(), status, result); + } +} + +impl std::io::Write for TaskSender { + fn write(&mut self, buf:&[u8]) -> std::io::Result { + let task = self.name.clone(); + { + self.logs.lock().expect("log lock poisoned").extend_from_slice(buf); + } + + self.handle + .output(task, buf.to_vec()) + .map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "receiver dropped"))?; + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { Ok(()) } +} diff --git a/crates/turborepo-ui/src/tui/app.rs b/crates/turborepo-ui/Source/tui/app.rs similarity index 100% rename from crates/turborepo-ui/src/tui/app.rs rename to crates/turborepo-ui/Source/tui/app.rs diff --git a/crates/turborepo-ui/src/tui/clipboard.rs b/crates/turborepo-ui/Source/tui/clipboard.rs similarity index 100% rename from crates/turborepo-ui/src/tui/clipboard.rs rename to crates/turborepo-ui/Source/tui/clipboard.rs diff --git a/crates/turborepo-ui/src/tui/debouncer.rs b/crates/turborepo-ui/Source/tui/debouncer.rs similarity index 100% rename from crates/turborepo-ui/src/tui/debouncer.rs rename to crates/turborepo-ui/Source/tui/debouncer.rs diff --git a/crates/turborepo-ui/Source/tui/event.rs b/crates/turborepo-ui/Source/tui/event.rs new file mode 100644 index 0000000000000..06ffdeb83dd7f --- /dev/null +++ b/crates/turborepo-ui/Source/tui/event.rs @@ -0,0 +1,85 @@ +use async_graphql::Enum; +use serde::Serialize; +use tokio::sync::oneshot; + +pub enum Event { + StartTask { task:String, output_logs:OutputLogs }, + TaskOutput { task:String, output:Vec }, + EndTask { task:String, result:TaskResult }, + Status { task:String, status:String, result:CacheResult }, + PaneSizeQuery(oneshot::Sender), + Stop(oneshot::Sender<()>), + // Stop initiated by the TUI itself + InternalStop, + Tick, + Up, + Down, + ScrollUp, + ScrollDown, + SetStdin { task:String, stdin:Box }, + EnterInteractive, + ExitInteractive, + Input { bytes:Vec }, + UpdateTasks { tasks:Vec }, + Mouse(crossterm::event::MouseEvent), + CopySelection, + RestartTasks { tasks:Vec }, + Resize { rows:u16, cols:u16 }, + ToggleSidebar, + ToggleHelpPopup, + TogglePinnedTask, + SearchEnter, + SearchExit { restore_scroll:bool }, + SearchScroll { direction:Direction }, + SearchEnterChar(char), + SearchBackspace, +} + +pub enum Direction { + Up, + Down, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Enum)] +pub enum TaskResult { + Success, + Failure, + CacheHit, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Enum)] +pub enum CacheResult { + Hit, + Miss, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Enum)] +pub enum OutputLogs { + // Entire task output is persisted after run + Full, + // None of a task output is persisted after run + None, + // Only the status line of a task is persisted + HashOnly, + // Output is only persisted if it is a cache miss + NewOnly, + // Output is only persisted if the task failed + ErrorsOnly, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct PaneSize { + pub rows:u16, + pub cols:u16, +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn assert_event_send() { + fn send_sync() {} + send_sync::(); + } +} diff --git a/crates/turborepo-ui/Source/tui/handle.rs b/crates/turborepo-ui/Source/tui/handle.rs new file mode 100644 index 0000000000000..8bfaa82182078 --- /dev/null +++ b/crates/turborepo-ui/Source/tui/handle.rs @@ -0,0 +1,113 @@ +use tokio::sync::{mpsc, oneshot}; + +use super::{ + Error, + Event, + TaskResult, + app::FRAMERATE, + event::{CacheResult, OutputLogs, PaneSize}, +}; +use crate::sender::{TaskSender, UISender}; + +/// Struct for sending app events to TUI rendering +#[derive(Debug, Clone)] +pub struct TuiSender { + primary:mpsc::UnboundedSender, +} + +/// Struct for receiving app events +pub struct AppReceiver { + primary:mpsc::UnboundedReceiver, +} + +impl TuiSender { + /// Create a new channel for sending app events. + /// + /// AppSender is meant to be held by the actual task runner + /// AppReceiver should be passed to `crate::tui::run_app` + pub fn new() -> (Self, AppReceiver) { + let (primary_tx, primary_rx) = mpsc::unbounded_channel(); + let tick_sender = primary_tx.clone(); + tokio::spawn(async move { + let mut interval = tokio::time::interval(FRAMERATE); + loop { + interval.tick().await; + if tick_sender.send(Event::Tick).is_err() { + break; + } + } + }); + (Self { primary:primary_tx }, AppReceiver { primary:primary_rx }) + } +} + +impl TuiSender { + pub fn start_task(&self, task:String, output_logs:OutputLogs) { + self.primary.send(Event::StartTask { task, output_logs }).ok(); + } + + pub fn end_task(&self, task:String, result:TaskResult) { + self.primary.send(Event::EndTask { task, result }).ok(); + } + + pub fn status(&self, task:String, status:String, result:CacheResult) { + self.primary.send(Event::Status { task, status, result }).ok(); + } + + pub fn set_stdin(&self, task:String, stdin:Box) { + self.primary.send(Event::SetStdin { task, stdin }).ok(); + } + + /// Construct a sender configured for a specific task + pub fn task(&self, task:String) -> TaskSender { + TaskSender { name:task, handle:UISender::Tui(self.clone()), logs:Default::default() } + } + + /// Stop rendering TUI and restore terminal to default configuration + pub async fn stop(&self) { + let (callback_tx, callback_rx) = oneshot::channel(); + // Send stop event, if receiver has dropped ignore error as + // it'll be a no-op. + self.primary.send(Event::Stop(callback_tx)).ok(); + // Wait for callback to be sent or the channel closed. + callback_rx.await.ok(); + } + + /// Update the list of tasks displayed in the TUI + pub fn update_tasks(&self, tasks:Vec) -> Result<(), crate::Error> { + Ok(self + .primary + .send(Event::UpdateTasks { tasks }) + .map_err(|err| Error::Mpsc(err.to_string()))?) + } + + pub fn output(&self, task:String, output:Vec) -> Result<(), crate::Error> { + Ok(self + .primary + .send(Event::TaskOutput { task, output }) + .map_err(|err| Error::Mpsc(err.to_string()))?) + } + + /// Restart the list of tasks displayed in the TUI + pub fn restart_tasks(&self, tasks:Vec) -> Result<(), crate::Error> { + Ok(self + .primary + .send(Event::RestartTasks { tasks }) + .map_err(|err| Error::Mpsc(err.to_string()))?) + } + + /// Fetches the size of the terminal pane + pub async fn pane_size(&self) -> Option { + let (callback_tx, callback_rx) = oneshot::channel(); + // Send query, if no receiver to handle the request return None + self.primary.send(Event::PaneSizeQuery(callback_tx)).ok()?; + // Wait for callback to be sent + callback_rx.await.ok() + } +} + +impl AppReceiver { + /// Receive an event, producing a tick event if no events are rec eived by + /// the deadline. + pub async fn recv(&mut self) -> Option { self.primary.recv().await } +} diff --git a/crates/turborepo-ui/src/tui/input.rs b/crates/turborepo-ui/Source/tui/input.rs similarity index 100% rename from crates/turborepo-ui/src/tui/input.rs rename to crates/turborepo-ui/Source/tui/input.rs diff --git a/crates/turborepo-ui/src/tui/mod.rs b/crates/turborepo-ui/Source/tui/mod.rs similarity index 100% rename from crates/turborepo-ui/src/tui/mod.rs rename to crates/turborepo-ui/Source/tui/mod.rs diff --git a/crates/turborepo-ui/src/tui/pane.rs b/crates/turborepo-ui/Source/tui/pane.rs similarity index 100% rename from crates/turborepo-ui/src/tui/pane.rs rename to crates/turborepo-ui/Source/tui/pane.rs diff --git a/crates/turborepo-ui/Source/tui/popup.rs b/crates/turborepo-ui/Source/tui/popup.rs new file mode 100644 index 0000000000000..f5aa55b7ffbc5 --- /dev/null +++ b/crates/turborepo-ui/Source/tui/popup.rs @@ -0,0 +1,70 @@ +use std::cmp::min; + +use ratatui::{ + layout::{Constraint, Flex, Layout, Rect}, + text::Line, + widgets::{Block, List, ListItem, Padding}, +}; + +const BIND_LIST:[&str; 12] = [ + "m - Toggle this help popup", + "↑ or j - Select previous task", + "↓ or k - Select next task", + "h - Toggle task list", + "p - Toggle pinned task selection", + "/ - Filter tasks to search term", + "ESC - Clear filter", + "i - Interact with task", + "Ctrl+z - Stop interacting with task", + "c - Copy logs selection (Only when logs are selected)", + "u - Scroll logs up", + "d - Scroll logs down", +]; + +pub fn popup_area(area:Rect) -> Rect { + let screen_width = area.width; + let screen_height = area.height; + + let popup_width = BIND_LIST.iter().map(|s| s.len().saturating_add(4)).max().unwrap_or(0) as u16; + let popup_height = min((BIND_LIST.len().saturating_add(4)) as u16, screen_height); + + let x = screen_width.saturating_sub(popup_width) / 2; + let y = screen_height.saturating_sub(popup_height) / 2; + + let vertical = Layout::vertical([Constraint::Percentage(100)]).flex(Flex::Center); + let horizontal = Layout::horizontal([Constraint::Percentage(100)]).flex(Flex::Center); + + let [vertical_area] = vertical.areas(Rect { x, y, width:popup_width, height:popup_height }); + + let [area] = horizontal.areas(vertical_area); + + area +} + +pub fn popup(area:Rect) -> List<'static> { + let available_height = area.height.saturating_sub(4) as usize; + + let items:Vec = BIND_LIST + .iter() + .take(available_height) + .map(|item| ListItem::new(Line::from(*item))) + .collect(); + + let title_bottom = if available_height < BIND_LIST.len() { + let binds_not_visible = BIND_LIST.len().saturating_sub(available_height); + + let pluralize = if binds_not_visible > 1 { "s" } else { "" }; + let message = + format!(" {} more bind{}. Make your terminal taller. ", binds_not_visible, pluralize); + Line::from(message) + } else { + Line::from("") + }; + + let outer = Block::bordered() + .title(" Keybinds ") + .title_bottom(title_bottom.to_string()) + .padding(Padding::uniform(1)); + + List::new(items).block(outer) +} diff --git a/crates/turborepo-ui/src/tui/preferences.rs b/crates/turborepo-ui/Source/tui/preferences.rs similarity index 100% rename from crates/turborepo-ui/src/tui/preferences.rs rename to crates/turborepo-ui/Source/tui/preferences.rs diff --git a/crates/turborepo-ui/Source/tui/search.rs b/crates/turborepo-ui/Source/tui/search.rs new file mode 100644 index 0000000000000..a94bcc23b3743 --- /dev/null +++ b/crates/turborepo-ui/Source/tui/search.rs @@ -0,0 +1,122 @@ +use std::{collections::HashSet, sync::Arc}; + +use super::task::TasksByStatus; + +#[derive(Debug, Clone)] +pub struct SearchResults { + query:String, + // We use Rc instead of String here for two reasons: + // - Rc for cheap clones since elements in `matches` will always be in `tasks` as well + // - Rc implements Borrow meaning we can query a `HashSet>` using a `&str` + // We do not modify the provided task names so we do not need the capabilities of String. + tasks:Vec>, + matches:HashSet>, +} + +impl SearchResults { + pub fn new(tasks:&TasksByStatus) -> Self { + Self { + tasks:tasks.task_names_in_displayed_order().map(Arc::from).collect(), + query:String::new(), + matches:HashSet::new(), + } + } + + /// Updates search results with new search body + pub fn update_tasks(&mut self, tasks:&TasksByStatus) { + self.tasks.clear(); + self.tasks.extend(tasks.task_names_in_displayed_order().map(Arc::from)); + self.update_matches(); + } + + /// Updates the query and the matches + pub fn modify_query(&mut self, modification:impl FnOnce(&mut String)) { + modification(&mut self.query); + self.update_matches(); + } + + fn update_matches(&mut self) { + self.matches.clear(); + if self.query.is_empty() { + return; + } + for task in self.tasks.iter().filter(|task| task.contains(&self.query)) { + self.matches.insert(task.clone()); + } + } + + /// Given an iterator it returns the first task that is in the search + /// results + pub fn first_match<'a>(&self, mut tasks:impl Iterator) -> Option<&'a str> { + tasks.find(|task| self.matches.contains(*task)) + } + + /// Returns if there are any matches for the query + pub fn has_matches(&self) -> bool { !self.matches.is_empty() } + + /// Returns query + pub fn query(&self) -> &str { &self.query } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::tui::task::Task; + + fn basic_task_list() -> TasksByStatus { + TasksByStatus { + planned:vec![ + Task::new("app-a".into()), + Task::new("app-b".into()), + Task::new("pkg-a".into()), + ], + ..Default::default() + } + } + + #[test] + fn test_no_query_no_matches() { + let task_list = basic_task_list(); + let results = SearchResults::new(&task_list); + assert!(!results.has_matches()); + } + + #[test] + fn test_matches_first_result() { + let task_list = basic_task_list(); + let mut results = SearchResults::new(&task_list); + results.modify_query(|s| s.push_str("app")); + let result = results.first_match(task_list.task_names_in_displayed_order()); + assert_eq!(result, Some("app-a")); + let result = results.first_match(task_list.task_names_in_displayed_order().skip(1)); + assert_eq!(result, Some("app-b")); + let result = results.first_match(task_list.task_names_in_displayed_order().skip(2)); + assert_eq!(result, None); + } + + #[test] + fn test_update_task_rebuilds_matches() { + let mut task_list = basic_task_list(); + let mut results = SearchResults::new(&task_list); + results.modify_query(|s| s.push_str("app")); + assert!(results.has_matches()); + task_list.planned.remove(0); + task_list.planned.push(Task::new("app-c".into())); + results.update_tasks(&task_list); + assert!(results.has_matches()); + let result = results.first_match(task_list.task_names_in_displayed_order()); + assert_eq!(result, Some("app-b")); + let result = results.first_match(task_list.task_names_in_displayed_order().skip(1)); + assert_eq!(result, Some("app-c")); + } + + #[test] + fn test_no_match_on_empty_list() { + let task_list = basic_task_list(); + let mut results = SearchResults::new(&task_list); + results.modify_query(|s| s.push_str("app")); + assert!(results.has_matches()); + let result = results.first_match(std::iter::empty()); + assert_eq!(result, None); + } +} diff --git a/crates/turborepo-ui/Source/tui/size.rs b/crates/turborepo-ui/Source/tui/size.rs new file mode 100644 index 0000000000000..512423d728d51 --- /dev/null +++ b/crates/turborepo-ui/Source/tui/size.rs @@ -0,0 +1,42 @@ +use crate::TaskTable; + +const PANE_SIZE_RATIO:f32 = 3.0 / 4.0; + +#[derive(Debug, Clone, Copy)] +pub struct SizeInfo { + task_width_hint:u16, + rows:u16, + cols:u16, +} + +impl SizeInfo { + pub fn new<'a>(rows:u16, cols:u16, tasks:impl Iterator) -> Self { + let task_width_hint = TaskTable::width_hint(tasks); + Self { rows, cols, task_width_hint } + } + + pub fn resize(&mut self, rows:u16, cols:u16) { + self.rows = rows; + self.cols = cols; + } + + pub fn pane_rows(&self) -> u16 { + self.rows + // Account for header and footer in layout + .saturating_sub(2) + // Always allocate at least one row as vt100 crashes if emulating a zero area terminal + .max(1) + } + + pub fn task_list_width(&self) -> u16 { self.cols - self.pane_cols() } + + pub fn pane_cols(&self) -> u16 { + // Want to maximize pane width + let ratio_pane_width = (f32::from(self.cols) * PANE_SIZE_RATIO) as u16; + let full_task_width = self.cols.saturating_sub(self.task_width_hint); + full_task_width + .max(ratio_pane_width) + // We need to account for the left border of the pane + .saturating_sub(1) + } +} diff --git a/crates/turborepo-ui/Source/tui/spinner.rs b/crates/turborepo-ui/Source/tui/spinner.rs new file mode 100644 index 0000000000000..84461403f315d --- /dev/null +++ b/crates/turborepo-ui/Source/tui/spinner.rs @@ -0,0 +1,63 @@ +use std::time::{Duration, Instant}; + +const SPINNER_FRAMES:&[&str] = ["»"].as_slice(); +// const SPINNER_FRAMES: &[&str] = ["â ‹", "â ™", "â ¹", "â ¸", "â ¼", "â ´", "â ¦", "â §", "â ‡", +// "â "].as_slice(); +const FRAMERATE:Duration = Duration::from_millis(80); + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct SpinnerState { + frame:usize, + last_render:Option, +} + +impl SpinnerState { + pub fn new() -> Self { Self { frame:0, last_render:None } } + + pub fn update(&mut self) { + if let Some(last_render) = self.last_render { + if last_render.elapsed() > FRAMERATE { + self.frame = (self.frame + 1) % SPINNER_FRAMES.len(); + self.last_render = Some(Instant::now()); + } + } else { + self.last_render = Some(Instant::now()); + } + } + + pub fn current(&self) -> &'static str { SPINNER_FRAMES[self.frame] } +} + +impl Default for SpinnerState { + fn default() -> Self { Self::new() } +} + +// Removed with iteration to double arrow symbol +// #[cfg(test)] +// mod test { +// use super::*; +// +// #[test] +// fn test_initial_update() { +// let mut spinner = SpinnerState::new(); +// assert!(spinner.last_render.is_none()); +// assert_eq!(spinner.frame, 0); +// spinner.update(); +// assert!(spinner.last_render.is_some()); +// assert_eq!(spinner.frame, 0, "initial update doesn't move frame"); +// } +// +// Removed with change to double arrow +// #[test] +// fn test_frame_update() { +// let mut spinner = SpinnerState::new(); +// // set last update to time that happened far before the spinner +// should increment let prev_render = Instant::now() - (FRAMERATE * 2); +// spinner.last_render = Some(prev_render); +// assert_eq!(spinner.frame, 0); +// spinner.update(); +// assert_eq!(spinner.frame, 1); +// let last_render = spinner.last_render.unwrap(); +// assert!(prev_render < last_render, "last render should be updated"); +// } +// } diff --git a/crates/turborepo-ui/Source/tui/state.rs b/crates/turborepo-ui/Source/tui/state.rs new file mode 100644 index 0000000000000..0de9400b8405b --- /dev/null +++ b/crates/turborepo-ui/Source/tui/state.rs @@ -0,0 +1,25 @@ +use std::time::Instant; + +enum Event { + Tick, +} + +struct State { + current_time:Instant, +} + +struct Focus { + task_id:String, + focus_type:FocusType, +} + +enum FocusType { + View, + Interact, +} + +struct DoneTask { + id:String, + start:Instant, + end:Instant, +} diff --git a/crates/turborepo-ui/Source/tui/table.rs b/crates/turborepo-ui/Source/tui/table.rs new file mode 100644 index 0000000000000..1172db50f26fb --- /dev/null +++ b/crates/turborepo-ui/Source/tui/table.rs @@ -0,0 +1,125 @@ +use ratatui::{ + layout::{Constraint, Rect}, + style::{Color, Modifier, Style, Stylize}, + text::Text, + widgets::{Block, Borders, Cell, Row, StatefulWidget, Table, TableState}, +}; + +use super::{event::TaskResult, spinner::SpinnerState, task::TasksByStatus}; + +/// A widget that renders a table of their tasks and their current status +/// +/// The tasks are ordered as follows: +/// - running tasks +/// - planned tasks +/// - finished tasks +/// - failed tasks +/// - successful tasks +/// - cached tasks +pub struct TaskTable<'b> { + tasks_by_type:&'b TasksByStatus, + spinner:SpinnerState, +} + +const TASK_NAVIGATE_INSTRUCTIONS:&str = "↑ ↓ - Select"; +const MORE_BINDS_INSTRUCTIONS:&str = "m - More binds"; + +impl<'b> TaskTable<'b> { + /// Construct a new table with all of the planned tasks + pub fn new(tasks_by_type:&'b TasksByStatus) -> Self { + Self { tasks_by_type, spinner:SpinnerState::default() } + } + + /// Provides a suggested width for the task table + pub fn width_hint<'a>(tasks:impl Iterator) -> u16 { + let task_name_width = tasks + .map(|task| task.len()) + .max() + .unwrap_or_default() + // Task column width should be large enough to fit "↑ ↓ to navigate instructions + // and truncate tasks with more than 40 chars. + .clamp(TASK_NAVIGATE_INSTRUCTIONS.len(), 40) as u16; + // Add space for column divider and status emoji + task_name_width + 1 + } + + /// Update the current time of the table + pub fn tick(&mut self) { self.spinner.update(); } + + fn finished_rows(&self) -> impl Iterator + '_ { + self.tasks_by_type.finished.iter().map(move |task| { + let name = if matches!(task.result(), TaskResult::CacheHit) { + Cell::new(Text::styled(task.name(), Style::default().italic())) + } else { + Cell::new(task.name()) + }; + + Row::new(vec![ + name, + match task.result() { + // matches Next.js (and many other CLI tools) https://github.com/vercel/next.js/blob/1a04d94aaec943d3cce93487fea3b8c8f8898f31/packages/next/src/build/output/log.ts + TaskResult::Success => { + Cell::new(Text::styled("✓", Style::default().green().bold())) + }, + TaskResult::CacheHit => { + Cell::new(Text::styled("⊙", Style::default().magenta())) + }, + TaskResult::Failure => { + Cell::new(Text::styled("⨯", Style::default().red().bold())) + }, + }, + ]) + }) + } + + fn running_rows(&self) -> impl Iterator + '_ { + let spinner = self.spinner.current(); + self.tasks_by_type + .running + .iter() + .map(move |task| Row::new(vec![Cell::new(task.name()), Cell::new(Text::raw(spinner))])) + } + + fn planned_rows(&self) -> impl Iterator + '_ { + self.tasks_by_type + .planned + .iter() + .map(move |task| Row::new(vec![Cell::new(task.name()), Cell::new(" ")])) + } +} + +impl<'a> StatefulWidget for &'a TaskTable<'a> { + type State = TableState; + + fn render(self, area:Rect, buf:&mut ratatui::prelude::Buffer, state:&mut Self::State) { + let table = Table::new( + self.running_rows().chain(self.planned_rows()).chain(self.finished_rows()), + [ + Constraint::Min(15), + // Status takes one cell to render + Constraint::Length(1), + ], + ) + .highlight_style(Style::default().fg(Color::Yellow)) + .column_spacing(0) + .block(Block::new().borders(Borders::RIGHT)) + .header( + vec![Text::styled("Tasks", Style::default().add_modifier(Modifier::DIM))] + .into_iter() + .map(Cell::from) + .collect::() + .height(1), + ) + .footer( + vec![Text::styled( + format!("{TASK_NAVIGATE_INSTRUCTIONS}\n{MORE_BINDS_INSTRUCTIONS}"), + Style::default().add_modifier(Modifier::DIM), + )] + .into_iter() + .map(Cell::from) + .collect::() + .height(2), + ); + StatefulWidget::render(table, area, buf, state); + } +} diff --git a/crates/turborepo-ui/src/tui/task.rs b/crates/turborepo-ui/Source/tui/task.rs similarity index 100% rename from crates/turborepo-ui/src/tui/task.rs rename to crates/turborepo-ui/Source/tui/task.rs diff --git a/crates/turborepo-ui/src/tui/term_output.rs b/crates/turborepo-ui/Source/tui/term_output.rs similarity index 100% rename from crates/turborepo-ui/src/tui/term_output.rs rename to crates/turborepo-ui/Source/tui/term_output.rs diff --git a/crates/turborepo-ui/Source/wui/event.rs b/crates/turborepo-ui/Source/wui/event.rs new file mode 100644 index 0000000000000..165c540f56dc9 --- /dev/null +++ b/crates/turborepo-ui/Source/wui/event.rs @@ -0,0 +1,17 @@ +use serde::Serialize; + +use crate::tui::event::{CacheResult, OutputLogs, TaskResult}; + +/// Specific events that the GraphQL server can send to the client, +/// not all the `Event` types from the TUI. +#[derive(Debug, Clone, Serialize)] +#[serde(tag = "type", content = "payload")] +pub enum WebUIEvent { + StartTask { task:String, output_logs:OutputLogs }, + TaskOutput { task:String, output:Vec }, + EndTask { task:String, result:TaskResult }, + CacheStatus { task:String, message:String, result:CacheResult }, + UpdateTasks { tasks:Vec }, + RestartTasks { tasks:Vec }, + Stop, +} diff --git a/crates/turborepo-ui/src/wui/mod.rs b/crates/turborepo-ui/Source/wui/mod.rs similarity index 100% rename from crates/turborepo-ui/src/wui/mod.rs rename to crates/turborepo-ui/Source/wui/mod.rs diff --git a/crates/turborepo-ui/Source/wui/query.rs b/crates/turborepo-ui/Source/wui/query.rs new file mode 100644 index 0000000000000..921d374a7afe8 --- /dev/null +++ b/crates/turborepo-ui/Source/wui/query.rs @@ -0,0 +1,58 @@ +use std::sync::Arc; + +use async_graphql::{Object, SimpleObject}; +use serde::Serialize; +use tokio::sync::Mutex; + +use crate::wui::subscriber::{TaskState, WebUIState}; + +#[derive(Debug, Clone, Serialize, SimpleObject)] +struct RunTask { + name:String, + state:TaskState, +} + +struct CurrentRun<'a> { + state:&'a SharedState, +} + +#[Object] +impl CurrentRun<'_> { + async fn tasks(&self) -> Vec { + self.state + .lock() + .await + .tasks() + .iter() + .map(|(task, state)| RunTask { + name: task.clone(), + state: state.clone(), + }) + .collect() + } +} + +/// We keep the state in a `Arc>>` so both `Subscriber` and +/// `Query` can access it, with `Subscriber` mutating it and `Query` only +/// reading it. +pub type SharedState = Arc>; + +/// The query for actively running tasks. +/// +/// (As opposed to the query for general repository state `RepositoryQuery` +/// in `turborepo_lib::query`) +/// This is `None` when we're not actually running a task (e.g. `turbo query`) +pub struct RunQuery { + state:Option, +} + +impl RunQuery { + pub fn new(state:Option) -> Self { Self { state } } +} + +#[Object] +impl RunQuery { + async fn current_run(&self) -> Option { + Some(CurrentRun { state:self.state.as_ref()? }) + } +} diff --git a/crates/turborepo-ui/Source/wui/sender.rs b/crates/turborepo-ui/Source/wui/sender.rs new file mode 100644 index 0000000000000..f6ae9c17f1b0b --- /dev/null +++ b/crates/turborepo-ui/Source/wui/sender.rs @@ -0,0 +1,59 @@ +use std::io::Write; + +use tracing::log::warn; + +use crate::{ + sender::{TaskSender, UISender}, + tui::event::{CacheResult, OutputLogs, TaskResult}, + wui::{Error, event::WebUIEvent}, +}; + +#[derive(Debug, Clone)] +pub struct WebUISender { + pub tx:tokio::sync::mpsc::UnboundedSender, +} + +impl WebUISender { + pub fn new(tx:tokio::sync::mpsc::UnboundedSender) -> Self { Self { tx } } + + pub fn start_task(&self, task:String, output_logs:OutputLogs) { + self.tx.send(WebUIEvent::StartTask { task, output_logs }).ok(); + } + + pub fn restart_tasks(&self, tasks:Vec) -> Result<(), crate::Error> { + self.tx.send(WebUIEvent::RestartTasks { tasks }).map_err(Error::Broadcast)?; + Ok(()) + } + + pub fn end_task(&self, task:String, result:TaskResult) { + self.tx.send(WebUIEvent::EndTask { task, result }).ok(); + } + + pub fn status(&self, task:String, message:String, result:CacheResult) { + self.tx.send(WebUIEvent::CacheStatus { task, message, result }).ok(); + } + + pub fn set_stdin(&self, _:String, _:Box) { + warn!("stdin is not supported (yet) in web ui"); + } + + pub fn task(&self, task:String) -> TaskSender { + TaskSender { name:task, handle:UISender::Wui(self.clone()), logs:Default::default() } + } + + pub fn stop(&self) { self.tx.send(WebUIEvent::Stop).ok(); } + + pub fn update_tasks(&self, tasks:Vec) -> Result<(), crate::Error> { + self.tx.send(WebUIEvent::UpdateTasks { tasks }).map_err(Error::Broadcast)?; + + Ok(()) + } + + pub fn output(&self, task:String, output:Vec) -> Result<(), crate::Error> { + self.tx + .send(WebUIEvent::TaskOutput { task, output }) + .map_err(Error::Broadcast)?; + + Ok(()) + } +} diff --git a/crates/turborepo-ui/Source/wui/subscriber.rs b/crates/turborepo-ui/Source/wui/subscriber.rs new file mode 100644 index 0000000000000..728a65349564c --- /dev/null +++ b/crates/turborepo-ui/Source/wui/subscriber.rs @@ -0,0 +1,249 @@ +use std::{collections::BTreeMap, sync::Arc}; + +use async_graphql::{Enum, SimpleObject}; +use serde::Serialize; +use tokio::sync::Mutex; + +use crate::{ + tui::event::{CacheResult, TaskResult}, + wui::{event::WebUIEvent, query::SharedState}, +}; + +/// Subscribes to the Web UI events and updates the state +pub struct Subscriber { + rx:tokio::sync::mpsc::UnboundedReceiver, +} + +impl Subscriber { + pub fn new(rx:tokio::sync::mpsc::UnboundedReceiver) -> Self { Self { rx } } + + pub async fn watch( + self, + // We use a tokio::sync::Mutex here because we want this future to be Send. + #[allow(clippy::type_complexity)] state:SharedState, + ) { + let mut rx = self.rx; + while let Some(event) = rx.recv().await { + Self::add_message(&state, event).await; + } + } + + async fn add_message(state:&Arc>, event:WebUIEvent) { + let mut state = state.lock().await; + + match event { + WebUIEvent::StartTask { task, output_logs: _ } => { + state.tasks.insert( + task, + TaskState { + output:Vec::new(), + status:TaskStatus::Running, + cache_result:None, + cache_message:None, + }, + ); + }, + WebUIEvent::TaskOutput { task, output } => { + state.tasks.get_mut(&task).unwrap().output.extend(output); + }, + WebUIEvent::EndTask { task, result } => { + state.tasks.get_mut(&task).unwrap().status = TaskStatus::from(result); + }, + WebUIEvent::CacheStatus { task, result, message } => { + if result == CacheResult::Hit { + state.tasks.get_mut(&task).unwrap().status = TaskStatus::Cached; + } + state.tasks.get_mut(&task).unwrap().cache_result = Some(result); + state.tasks.get_mut(&task).unwrap().cache_message = Some(message); + }, + WebUIEvent::Stop => { + // TODO: stop watching + }, + WebUIEvent::UpdateTasks { tasks } => { + state.tasks = tasks + .into_iter() + .map(|task| { + ( + task, + TaskState { + output:Vec::new(), + status:TaskStatus::Pending, + cache_result:None, + cache_message:None, + }, + ) + }) + .collect(); + }, + WebUIEvent::RestartTasks { tasks } => { + state.tasks = tasks + .into_iter() + .map(|task| { + ( + task, + TaskState { + output:Vec::new(), + status:TaskStatus::Running, + cache_result:None, + cache_message:None, + }, + ) + }) + .collect(); + }, + } + } +} + +#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Enum)] +pub enum TaskStatus { + Pending, + Running, + Cached, + Failed, + Succeeded, +} + +impl From for TaskStatus { + fn from(result:TaskResult) -> Self { + match result { + TaskResult::Success => Self::Succeeded, + TaskResult::CacheHit => Self::Cached, + TaskResult::Failure => Self::Failed, + } + } +} + +#[derive(Debug, Clone, Serialize, SimpleObject)] +pub struct TaskState { + output:Vec, + status:TaskStatus, + cache_result:Option, + /// The message for the cache status, i.e. `cache hit, replaying logs` + cache_message:Option, +} + +#[derive(Debug, Default, Clone, Serialize)] +pub struct WebUIState { + tasks:BTreeMap, +} + +impl WebUIState { + pub fn tasks(&self) -> &BTreeMap { &self.tasks } +} + +#[cfg(test)] +mod test { + use async_graphql::{EmptyMutation, EmptySubscription, Schema}; + + use super::*; + use crate::{ + tui::event::OutputLogs, + wui::{query::RunQuery, sender::WebUISender}, + }; + + #[tokio::test] + async fn test_web_ui_state() -> Result<(), crate::Error> { + let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); + let state = Arc::new(Mutex::new(WebUIState::default())); + let subscriber = Subscriber::new(rx); + + let sender = WebUISender::new(tx); + + // Start a successful task + sender.start_task("task".to_string(), OutputLogs::Full); + sender.output("task".to_string(), b"this is my output".to_vec())?; + sender.end_task("task".to_string(), TaskResult::Success); + + // Start a cached task + sender.start_task("task2".to_string(), OutputLogs::Full); + sender.status("task2".to_string(), "status".to_string(), CacheResult::Hit); + + // Start a failing task + sender.start_task("task3".to_string(), OutputLogs::Full); + sender.end_task("task3".to_string(), TaskResult::Failure); + + // Drop the sender so the subscriber can terminate + drop(sender); + + // Run the subscriber blocking + subscriber.watch(state.clone()).await; + + let state_handle = state.lock().await.clone(); + assert_eq!(state_handle.tasks().len(), 3); + assert_eq!(state_handle.tasks().get("task2").unwrap().status, TaskStatus::Cached); + assert_eq!(state_handle.tasks().get("task").unwrap().status, TaskStatus::Succeeded); + assert_eq!(state_handle.tasks().get("task").unwrap().output, b"this is my output"); + assert_eq!(state_handle.tasks().get("task3").unwrap().status, TaskStatus::Failed); + + // Now let's check with the GraphQL API + let schema = Schema::new(RunQuery::new(Some(state)), EmptyMutation, EmptySubscription); + let result = + schema.execute("query { currentRun { tasks { name state { status } } } }").await; + assert!(result.errors.is_empty()); + assert_eq!( + result.data, + async_graphql::Value::from_json(serde_json::json!({ + "currentRun": { + "tasks": [ + { + "name": "task", + "state": { + "status": "SUCCEEDED" + } + }, + { + "name": "task2", + "state": { + "status": "CACHED" + } + }, + { + "name": "task3", + "state": { + "status": "FAILED" + } + } + ] + } + })) + .unwrap() + ); + + Ok(()) + } + + #[tokio::test] + async fn test_restart_tasks() -> Result<(), crate::Error> { + let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); + let state = Arc::new(Mutex::new(WebUIState::default())); + let subscriber = Subscriber::new(rx); + + let sender = WebUISender::new(tx); + + // Start a successful task + sender.start_task("task".to_string(), OutputLogs::Full); + sender.output("task".to_string(), b"this is my output".to_vec())?; + sender.end_task("task".to_string(), TaskResult::Success); + + // Start a cached task + sender.start_task("task2".to_string(), OutputLogs::Full); + sender.status("task2".to_string(), "status".to_string(), CacheResult::Hit); + + // Restart a task + sender.restart_tasks(vec!["task".to_string()])?; + + // Drop the sender so the subscriber can terminate + drop(sender); + + // Run the subscriber blocking + subscriber.watch(state.clone()).await; + + let state_handle = state.lock().await.clone(); + assert_eq!(state_handle.tasks().len(), 1); + assert_eq!(state_handle.tasks().get("task").unwrap().status, TaskStatus::Running); + assert!(state_handle.tasks().get("task").unwrap().output.is_empty()); + + Ok(()) + } +} diff --git a/crates/turborepo-ui/examples/pane.rs b/crates/turborepo-ui/examples/pane.rs new file mode 100644 index 0000000000000..25416a41f9702 --- /dev/null +++ b/crates/turborepo-ui/examples/pane.rs @@ -0,0 +1,119 @@ +use std::{error::Error, io, sync::mpsc, time::Duration}; + +use crossterm::{ + event::KeyCode, + terminal::{disable_raw_mode, enable_raw_mode}, +}; +use ratatui::{ + Terminal, + TerminalOptions, + Viewport, + backend::{Backend, CrosstermBackend}, + text::Text, + widgets::Widget, +}; +use turborepo_ui::TerminalPane; + +fn main() -> Result<(), Box> { + enable_raw_mode()?; + let stdout = io::stdout(); + let backend = CrosstermBackend::new(stdout); + + let mut terminal = + Terminal::with_options(backend, TerminalOptions { viewport:Viewport::Inline(24) })?; + + terminal.insert_before(1, |buf| { + Text::raw("Press q to exit, use arrow keys to switch panes").render(buf.area, buf) + })?; + + let (tx, rx) = mpsc::sync_channel(1); + + std::thread::spawn(move || handle_input(tx)); + + let size = terminal.get_frame().size(); + + let pane = + TerminalPane::new(size.height, size.width, vec!["foo".into(), "bar".into(), "baz".into()]); + + run_app(&mut terminal, pane, rx)?; + + terminal.clear()?; + + // restore terminal + disable_raw_mode()?; + terminal.show_cursor()?; + println!(); + + Ok(()) +} + +fn run_app( + terminal:&mut Terminal, + mut pane:TerminalPane<()>, + rx:mpsc::Receiver, +) -> io::Result<()> { + let tasks = ["foo", "bar", "baz"]; + let mut idx:usize = 0; + pane.select("foo").unwrap(); + let mut tick = 0; + while let Ok(event) = rx.recv() { + match event { + Event::Up => { + idx = idx.saturating_sub(1); + let task = tasks[idx]; + pane.select(task).unwrap(); + }, + Event::Down => { + idx = (idx + 1).clamp(0, 2); + let task = tasks[idx]; + pane.select(task).unwrap(); + }, + Event::Stop => break, + Event::Tick => { + if tick % 3 == 0 { + let color = format!("\x1b[{}m", 30 + (tick % 10)); + for task in tasks { + pane.process_output( + task, + format!("{task}: {color}tick {tick}\x1b[0m\r\n").as_bytes(), + ) + .unwrap(); + } + } + }, + } + terminal.draw(|f| f.render_widget(&pane, f.size()))?; + tick += 1; + } + + Ok(()) +} +enum Event { + Up, + Down, + Stop, + Tick, +} + +fn handle_input(tx:mpsc::SyncSender) -> std::io::Result<()> { + loop { + if crossterm::event::poll(Duration::from_millis(20))? { + let event = crossterm::event::read()?; + if let crossterm::event::Event::Key(key_event) = event { + if let Some(event) = match key_event.code { + KeyCode::Up => Some(Event::Up), + KeyCode::Down => Some(Event::Down), + KeyCode::Char('q') => Some(Event::Stop), + _ => None, + } { + if tx.send(event).is_err() { + break; + } + } + } + } else if tx.send(Event::Tick).is_err() { + break; + } + } + Ok(()) +} diff --git a/crates/turborepo-ui/examples/table.rs b/crates/turborepo-ui/examples/table.rs new file mode 100644 index 0000000000000..e2613a90aa17a --- /dev/null +++ b/crates/turborepo-ui/examples/table.rs @@ -0,0 +1,127 @@ +use std::{error::Error, io, sync::mpsc, time::Duration}; + +use crossterm::{ + event::{KeyCode, KeyModifiers}, + terminal::{disable_raw_mode, enable_raw_mode}, +}; +use ratatui::prelude::*; +use turborepo_ui::{TaskTable, tui::event::TaskResult}; + +enum Event { + Tick(u64), + Start(&'static str), + Finish(&'static str), + Up, + Down, + Stop, +} + +fn main() -> Result<(), Box> { + enable_raw_mode()?; + let stdout = io::stdout(); + let backend = CrosstermBackend::new(stdout); + + let mut terminal = + Terminal::with_options(backend, TerminalOptions { viewport:Viewport::Inline(8) })?; + + let (tx, rx) = mpsc::sync_channel(1); + let input_tx = tx.clone(); + // Thread forwards user input + let input = std::thread::spawn(move || handle_input(input_tx)); + // Thread simulates starting/finishing of tasks + let events = std::thread::spawn(move || send_events(tx)); + + let table = TaskTable::new((0..6).map(|i| format!("task_{i}"))); + + run_app(&mut terminal, table, rx)?; + + events.join().expect("event thread panicked"); + input.join().expect("input thread panicked")?; + + // restore terminal + disable_raw_mode()?; + terminal.show_cursor()?; + println!(); + + Ok(()) +} + +fn run_app( + terminal:&mut Terminal, + mut table:TaskTable, + rx:mpsc::Receiver, +) -> io::Result<()> { + while let Ok(event) = rx.recv() { + match event { + Event::Tick(_) => { + table.tick(); + }, + Event::Start(task) => table.start_task(task).unwrap(), + Event::Finish(task) => table.finish_task(task, TaskResult::Success).unwrap(), + Event::Up => table.previous(), + Event::Down => table.next(), + Event::Stop => break, + } + terminal.draw(|f| table.stateful_render(f, f.size()))?; + } + + Ok(()) +} + +fn send_events(tx:mpsc::SyncSender) { + let mut events = vec![ + Event::Start("task_0"), + Event::Start("task_1"), + Event::Tick(10), + Event::Start("task_2"), + Event::Tick(30), + Event::Start("task_3"), + Event::Finish("task_2"), + Event::Tick(30), + Event::Start("task_4"), + Event::Finish("task_0"), + Event::Tick(10), + Event::Finish("task_1"), + Event::Start("task_5"), + Event::Tick(30), + Event::Finish("task_3"), + Event::Finish("task_4"), + Event::Tick(50), + Event::Finish("task_5"), + Event::Stop, + ]; + events.reverse(); + while let Some(event) = events.pop() { + if let Event::Tick(ticks) = event { + std::thread::sleep(Duration::from_millis(50 * ticks)); + } + if tx.send(event).is_err() { + break; + } + } +} + +fn handle_input(tx:mpsc::SyncSender) -> std::io::Result<()> { + loop { + if crossterm::event::poll(Duration::from_millis(10))? { + let event = crossterm::event::read()?; + if let crossterm::event::Event::Key(key_event) = event { + if let Some(event) = match key_event.code { + KeyCode::Up => Some(Event::Up), + KeyCode::Down => Some(Event::Down), + KeyCode::Char('c') if key_event.modifiers == KeyModifiers::CONTROL => { + Some(Event::Stop) + }, + _ => None, + } { + if tx.send(event).is_err() { + break; + } + } + } + } else if tx.send(Event::Tick(0)).is_err() { + break; + } + } + Ok(()) +} diff --git a/crates/turborepo-ui/src/color_selector.rs b/crates/turborepo-ui/src/color_selector.rs deleted file mode 100644 index b2db3c6e00c95..0000000000000 --- a/crates/turborepo-ui/src/color_selector.rs +++ /dev/null @@ -1,124 +0,0 @@ -use std::{ - collections::HashMap, - sync::{Arc, OnceLock, RwLock}, -}; - -use console::{Style, StyledObject}; - -static COLORS: OnceLock<[Style; 5]> = OnceLock::new(); - -pub fn get_terminal_package_colors() -> &'static [Style; 5] { - COLORS.get_or_init(|| { - [ - Style::new().cyan(), - Style::new().magenta(), - Style::new().green(), - Style::new().yellow(), - Style::new().blue(), - ] - }) -} - -/// Selects colors for tasks and caches accordingly. -/// Shared between tasks so allows for concurrent access. -#[derive(Default)] -pub struct ColorSelector { - inner: Arc>, -} - -#[derive(Default)] -struct ColorSelectorInner { - idx: usize, - cache: HashMap, -} - -impl ColorSelector { - pub fn color_for_key(&self, key: &str) -> &'static Style { - if let Some(style) = self.inner.read().expect("lock poisoned").color(key) { - return style; - } - - let color = { - self.inner - .write() - .expect("lock poisoned") - .insert_color(key.to_string()) - }; - - color - } - - pub fn prefix_with_color(&self, cache_key: &str, prefix: &str) -> StyledObject { - if prefix.is_empty() { - return Style::new().apply_to(String::new()); - } - - let style = self.color_for_key(cache_key); - style.apply_to(format!("{}: ", prefix)) - } -} - -impl ColorSelectorInner { - fn color(&self, key: &str) -> Option<&'static Style> { - self.cache.get(key).copied() - } - - fn insert_color(&mut self, key: String) -> &'static Style { - let colors = get_terminal_package_colors(); - let chosen_color = &colors[self.idx % colors.len()]; - // A color might have been chosen by the time we get to inserting - self.cache.entry(key).or_insert_with(|| { - // If a color hasn't been chosen, then we increment the index - self.idx += 1; - chosen_color - }) - } -} - -#[cfg(test)] -mod tests { - use std::thread; - - #[test] - fn test_color_selector() { - let selector = super::ColorSelector::default(); - let color1 = selector.color_for_key("key1"); - let color2 = selector.color_for_key("key2"); - let color3 = selector.color_for_key("key1"); - assert_eq!(color1, color3); - assert_ne!(color1, color2); - } - - #[test] - fn test_multithreaded_selector() { - let selector = super::ColorSelector::default(); - thread::scope(|s| { - s.spawn(|| { - let color = selector.color_for_key("key1"); - assert_eq!(color, selector.color_for_key("key1")); - }); - s.spawn(|| { - let color = selector.color_for_key("key2"); - assert_eq!(color, selector.color_for_key("key2")); - }); - s.spawn(|| { - let color1 = selector.color_for_key("key1"); - let color2 = selector.color_for_key("key2"); - assert_eq!(color1, selector.color_for_key("key1")); - assert_eq!(color2, selector.color_for_key("key2")); - assert_ne!(color1, color2); - }); - }); - // We only inserted 2 keys so next index should be 2 - assert_eq!(selector.inner.read().unwrap().idx, 2); - } - - #[test] - fn test_color_selector_wraps_around() { - let selector = super::ColorSelector::default(); - for key in &["1", "2", "3", "4", "5", "6"] { - selector.color_for_key(key); - } - assert_eq!(selector.color_for_key("1"), selector.color_for_key("6")); - } -} diff --git a/crates/turborepo-ui/src/line.rs b/crates/turborepo-ui/src/line.rs deleted file mode 100644 index ac96f3f850cc8..0000000000000 --- a/crates/turborepo-ui/src/line.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::io::Write; - -/// Writer that will buffer writes so the underlying writer is only called with -/// writes that end in a newline -pub struct LineWriter { - writer: W, - buffer: Vec, -} - -impl LineWriter { - pub fn new(writer: W) -> Self { - Self { - writer, - buffer: Vec::with_capacity(512), - } - } -} - -impl Write for LineWriter { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - for line in buf.split_inclusive(|c| *c == b'\n') { - if line.ends_with(b"\n") { - if self.buffer.is_empty() { - self.writer.write_all(line)?; - } else { - self.buffer.extend_from_slice(line); - self.writer.write_all(&self.buffer)?; - self.buffer.clear(); - } - } else { - // This should only happen on the last chunk? - self.buffer.extend_from_slice(line) - } - } - - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - // We don't flush our buffer as that would lead to a write without a newline - self.writer.flush() - } -} diff --git a/crates/turborepo-ui/src/prefixed.rs b/crates/turborepo-ui/src/prefixed.rs deleted file mode 100644 index f2f98a788fec4..0000000000000 --- a/crates/turborepo-ui/src/prefixed.rs +++ /dev/null @@ -1,279 +0,0 @@ -use std::{ - fmt::{Debug, Display}, - io::Write, -}; - -use console::{Style, StyledObject}; -use tracing::error; - -use crate::{ColorConfig, LineWriter}; - -/// Writes messages with different prefixes, depending on log level. -/// -/// Note that this does output the prefix when message is empty, unlike the Go -/// implementation. We do this because this behavior is what we actually -/// want for replaying logs. -pub struct PrefixedUI { - color_config: ColorConfig, - output_prefix: Option>, - warn_prefix: Option>, - error_prefix: Option>, - out: W, - err: W, - default_prefix: StyledObject, -} - -impl PrefixedUI { - pub fn new(color_config: ColorConfig, out: W, err: W) -> Self { - Self { - color_config, - out, - err, - output_prefix: None, - warn_prefix: None, - error_prefix: None, - default_prefix: Style::new().apply_to(String::new()), - } - } - - pub fn with_output_prefix(mut self, output_prefix: StyledObject) -> Self { - self.output_prefix = Some(self.color_config.apply(output_prefix)); - self - } - - pub fn with_warn_prefix(mut self, warn_prefix: StyledObject) -> Self { - self.warn_prefix = Some(self.color_config.apply(warn_prefix)); - self - } - - pub fn with_error_prefix(mut self, error_prefix: StyledObject) -> Self { - self.error_prefix = Some(self.color_config.apply(error_prefix)); - self - } - - pub fn output(&mut self, message: impl Display) { - self.write_line(message, Command::Output) - } - - pub fn warn(&mut self, message: impl Display) { - self.write_line(message, Command::Warn) - } - - pub fn error(&mut self, message: impl Display) { - self.write_line(message, Command::Error) - } - - fn write_line(&mut self, message: impl Display, command: Command) { - let prefix = match command { - Command::Output => &self.output_prefix, - Command::Warn => &self.warn_prefix, - Command::Error => &self.error_prefix, - } - .as_ref() - .unwrap_or(&self.default_prefix); - let writer = match command { - Command::Output => &mut self.out, - Command::Warn | Command::Error => &mut self.err, - }; - - // There's no reason to propagate this error - // because we don't want our entire program to crash - // due to a log failure. - if let Err(err) = writeln!(writer, "{}{}", prefix, message) { - error!("cannot write to logs: {:?}", err); - } - } - - /// Construct a PrefixedWriter which will behave the same as `output`, but - /// without the requirement that messages be valid UTF-8 - pub fn output_prefixed_writer(&mut self) -> PrefixedWriter<&mut W> { - PrefixedWriter::new( - self.color_config, - self.output_prefix - .clone() - .unwrap_or_else(|| Style::new().apply_to(String::new())), - &mut self.out, - ) - } -} - -// -#[derive(Debug, Clone, Copy)] -enum Command { - Output, - Warn, - Error, -} - -/// Wraps a writer with a prefix before the actual message. -pub struct PrefixedWriter { - inner: LineWriter>, -} - -impl PrefixedWriter { - pub fn new(color_config: ColorConfig, prefix: StyledObject, writer: W) -> Self { - Self { - inner: LineWriter::new(PrefixedWriterInner::new(color_config, prefix, writer)), - } - } -} - -impl Write for PrefixedWriter { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.inner.write(buf) - } - - fn flush(&mut self) -> std::io::Result<()> { - self.inner.flush() - } -} - -/// Wraps a writer so that a prefix will be added at the start of each line. -/// Expects to only be called with complete lines. -struct PrefixedWriterInner { - prefix: String, - writer: W, -} - -impl PrefixedWriterInner { - pub fn new(color_config: ColorConfig, prefix: StyledObject, writer: W) -> Self { - let prefix = color_config.apply(prefix).to_string(); - Self { prefix, writer } - } -} - -impl Write for PrefixedWriterInner { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - let mut is_first = true; - for chunk in buf.split_inclusive(|c| *c == b'\r') { - // Before we write the chunk we write the prefix as either: - // - this is the first iteration and we haven't written the prefix - // - the previous chunk ended with a \r and the cursor is currently as the start - // of the line so we want to rewrite the prefix over the existing prefix in - // the line - // or if the last chunk is just a newline we can skip rewriting the prefix - if is_first || chunk != b"\n" { - self.writer.write_all(self.prefix.as_bytes())?; - } - self.writer.write_all(chunk)?; - is_first = false; - } - - // We do end up writing more bytes than this to the underlying writer, but we - // cannot report this to the callers as the amount of bytes we report - // written must be less than or equal to the number of bytes in the buffer. - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - self.writer.flush() - } -} - -#[cfg(test)] -mod test { - use test_case::test_case; - - use super::*; - - fn prefixed_ui(out: W, err: W, color_config: ColorConfig) -> PrefixedUI { - let output_prefix = crate::BOLD.apply_to("output ".to_string()); - let warn_prefix = crate::MAGENTA.apply_to("warn ".to_string()); - PrefixedUI::new(color_config, out, err) - .with_output_prefix(output_prefix) - .with_warn_prefix(warn_prefix) - .with_error_prefix(crate::MAGENTA.apply_to("error ".to_string())) - } - - #[test_case(false, "\u{1b}[1moutput \u{1b}[0mall good\n", Command::Output)] - #[test_case(true, "output all good\n", Command::Output)] - #[test_case(false, "\u{1b}[35mwarn \u{1b}[0mbe careful!\n", Command::Warn)] - #[test_case(true, "warn be careful!\n", Command::Warn)] - #[test_case(false, "\u{1b}[35merror \u{1b}[0mit blew up\n", Command::Error)] - #[test_case(true, "error it blew up\n", Command::Error)] - fn test_prefix_ui_outputs(strip_ansi: bool, expected: &str, cmd: Command) { - let mut out = Vec::new(); - let mut err = Vec::new(); - - let mut prefixed_ui = prefixed_ui(&mut out, &mut err, ColorConfig::new(strip_ansi)); - match cmd { - Command::Output => prefixed_ui.output("all good"), - Command::Warn => prefixed_ui.warn("be careful!"), - Command::Error => prefixed_ui.error("it blew up"), - } - - let buffer = match cmd { - Command::Output => out, - Command::Warn | Command::Error => err, - }; - assert_eq!(String::from_utf8(buffer).unwrap(), expected); - } - - #[test_case(true, "foo#build: cool!")] - #[test_case(false, "\u{1b}[1mfoo#build: \u{1b}[0mcool!")] - fn test_prefixed_writer(strip_ansi: bool, expected: &str) { - let mut buffer = Vec::new(); - let mut writer = PrefixedWriterInner::new( - ColorConfig::new(strip_ansi), - crate::BOLD.apply_to("foo#build: "), - &mut buffer, - ); - writer.write_all(b"cool!").unwrap(); - assert_eq!(String::from_utf8(buffer).unwrap(), expected); - } - - #[test_case("\ra whole message \n", "turbo > \rturbo > a whole message \n" ; "basic prefix cr")] - #[test_case("no return", "turbo > no return" ; "no return")] - #[test_case("foo\rbar\rbaz", "turbo > foo\rturbo > bar\rturbo > baz" ; "multiple crs")] - #[test_case("foo\r", "turbo > foo\r" ; "trailing cr")] - #[test_case("foo\r\n", "turbo > foo\r\n" ; "no double write on crlf")] - #[test_case("\n", "turbo > \n" ; "leading new line")] - fn test_prefixed_writer_cr(input: &str, expected: &str) { - let mut buffer = Vec::new(); - let mut writer = PrefixedWriterInner::new( - ColorConfig::new(false), - Style::new().apply_to("turbo > "), - &mut buffer, - ); - - writer.write_all(input.as_bytes()).unwrap(); - assert_eq!(String::from_utf8(buffer).unwrap(), expected); - } - - #[test_case(&["foo"], "" ; "no newline")] - #[test_case(&["\n"], "\n" ; "one newline")] - #[test_case(&["foo\n"], "foo\n" ; "single newline")] - #[test_case(&["foo ", "bar ", "baz\n"], "foo bar baz\n" ; "building line")] - #[test_case(&["multiple\nlines\nin\none"], "multiple\nlines\nin\n" ; "multiple lines")] - fn test_line_writer(inputs: &[&str], expected: &str) { - let mut buffer = Vec::new(); - let mut writer = LineWriter::new(&mut buffer); - for input in inputs { - writer.write_all(input.as_bytes()).unwrap(); - } - - assert_eq!(String::from_utf8(buffer).unwrap(), expected); - } - - #[test] - fn test_prefixed_writer_split_lines() { - let mut buffer = Vec::new(); - let mut writer = PrefixedWriter::new( - ColorConfig::new(false), - Style::new().apply_to("turbo > "), - &mut buffer, - ); - - writer.write_all(b"not a line yet").unwrap(); - writer - .write_all(b", now\nbut \ranother one starts") - .unwrap(); - writer.write_all(b" done\n").unwrap(); - writer.write_all(b"\n").unwrap(); - assert_eq!( - String::from_utf8(buffer).unwrap(), - "turbo > not a line yet, now\nturbo > but \rturbo > another one starts done\nturbo > \ - \n" - ); - } -} diff --git a/crates/turborepo-ui/src/sender.rs b/crates/turborepo-ui/src/sender.rs deleted file mode 100644 index 0fd6f84690bb6..0000000000000 --- a/crates/turborepo-ui/src/sender.rs +++ /dev/null @@ -1,156 +0,0 @@ -use std::sync::{Arc, Mutex}; - -use crate::{ - tui, - tui::event::{CacheResult, OutputLogs, PaneSize, TaskResult}, - wui::sender, -}; - -/// Enum to abstract over sending events to either the Tui or the Web UI -#[derive(Debug, Clone)] -pub enum UISender { - Tui(tui::TuiSender), - Wui(sender::WebUISender), -} - -impl UISender { - pub fn start_task(&self, task: String, output_logs: OutputLogs) { - match self { - UISender::Tui(sender) => sender.start_task(task, output_logs), - UISender::Wui(sender) => sender.start_task(task, output_logs), - } - } - - pub fn restart_tasks(&self, tasks: Vec) -> Result<(), crate::Error> { - match self { - UISender::Tui(sender) => sender.restart_tasks(tasks), - UISender::Wui(sender) => sender.restart_tasks(tasks), - } - } - - pub fn end_task(&self, task: String, result: TaskResult) { - match self { - UISender::Tui(sender) => sender.end_task(task, result), - UISender::Wui(sender) => sender.end_task(task, result), - } - } - - pub fn status(&self, task: String, status: String, result: CacheResult) { - match self { - UISender::Tui(sender) => sender.status(task, status, result), - UISender::Wui(sender) => sender.status(task, status, result), - } - } - fn set_stdin(&self, task: String, stdin: Box) { - match self { - UISender::Tui(sender) => sender.set_stdin(task, stdin), - UISender::Wui(sender) => sender.set_stdin(task, stdin), - } - } - - pub fn output(&self, task: String, output: Vec) -> Result<(), crate::Error> { - match self { - UISender::Tui(sender) => sender.output(task, output), - UISender::Wui(sender) => sender.output(task, output), - } - } - - /// Construct a sender configured for a specific task - pub fn task(&self, task: String) -> TaskSender { - match self { - UISender::Tui(sender) => sender.task(task), - UISender::Wui(sender) => sender.task(task), - } - } - pub async fn stop(&self) { - match self { - UISender::Tui(sender) => sender.stop().await, - UISender::Wui(sender) => sender.stop(), - } - } - pub fn update_tasks(&self, tasks: Vec) -> Result<(), crate::Error> { - match self { - UISender::Tui(sender) => sender.update_tasks(tasks), - UISender::Wui(sender) => sender.update_tasks(tasks), - } - } - - pub async fn pane_size(&self) -> Option { - match self { - UISender::Tui(sender) => sender.pane_size().await, - // Not applicable to the web UI - UISender::Wui(_) => None, - } - } -} - -#[derive(Debug, Clone)] -pub struct TaskSender { - pub(crate) name: String, - pub(crate) handle: UISender, - pub(crate) logs: Arc>>, -} - -impl TaskSender { - /// Access the underlying UISender - pub fn as_app(&self) -> &UISender { - &self.handle - } - - /// Mark the task as started - pub fn start(&self, output_logs: OutputLogs) { - self.handle.start_task(self.name.clone(), output_logs); - } - - /// Mark the task as finished - pub fn succeeded(&self, is_cache_hit: bool) -> Vec { - if is_cache_hit { - self.finish(TaskResult::CacheHit) - } else { - self.finish(TaskResult::Success) - } - } - - /// Mark the task as finished - pub fn failed(&self) -> Vec { - self.finish(TaskResult::Failure) - } - - fn finish(&self, result: TaskResult) -> Vec { - self.handle.end_task(self.name.clone(), result); - self.logs.lock().expect("logs lock poisoned").clone() - } - - pub fn set_stdin(&self, stdin: Box) { - self.handle.set_stdin(self.name.clone(), stdin); - } - - pub fn status(&self, status: &str, result: CacheResult) { - // Since this will be rendered via ratatui we any ANSI escape codes will not be - // handled. - // TODO: prevent the status from having ANSI codes in this scenario - let status = console::strip_ansi_codes(status).into_owned(); - self.handle.status(self.name.clone(), status, result); - } -} - -impl std::io::Write for TaskSender { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - let task = self.name.clone(); - { - self.logs - .lock() - .expect("log lock poisoned") - .extend_from_slice(buf); - } - - self.handle - .output(task, buf.to_vec()) - .map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "receiver dropped"))?; - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} diff --git a/crates/turborepo-ui/src/tui/event.rs b/crates/turborepo-ui/src/tui/event.rs deleted file mode 100644 index 775a7ef4bcc17..0000000000000 --- a/crates/turborepo-ui/src/tui/event.rs +++ /dev/null @@ -1,114 +0,0 @@ -use async_graphql::Enum; -use serde::Serialize; -use tokio::sync::oneshot; - -pub enum Event { - StartTask { - task: String, - output_logs: OutputLogs, - }, - TaskOutput { - task: String, - output: Vec, - }, - EndTask { - task: String, - result: TaskResult, - }, - Status { - task: String, - status: String, - result: CacheResult, - }, - PaneSizeQuery(oneshot::Sender), - Stop(oneshot::Sender<()>), - // Stop initiated by the TUI itself - InternalStop, - Tick, - Up, - Down, - ScrollUp, - ScrollDown, - SetStdin { - task: String, - stdin: Box, - }, - EnterInteractive, - ExitInteractive, - Input { - bytes: Vec, - }, - UpdateTasks { - tasks: Vec, - }, - Mouse(crossterm::event::MouseEvent), - CopySelection, - RestartTasks { - tasks: Vec, - }, - Resize { - rows: u16, - cols: u16, - }, - ToggleSidebar, - ToggleHelpPopup, - TogglePinnedTask, - SearchEnter, - SearchExit { - restore_scroll: bool, - }, - SearchScroll { - direction: Direction, - }, - SearchEnterChar(char), - SearchBackspace, -} - -pub enum Direction { - Up, - Down, -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Enum)] -pub enum TaskResult { - Success, - Failure, - CacheHit, -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Enum)] -pub enum CacheResult { - Hit, - Miss, -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Enum)] -pub enum OutputLogs { - // Entire task output is persisted after run - Full, - // None of a task output is persisted after run - None, - // Only the status line of a task is persisted - HashOnly, - // Output is only persisted if it is a cache miss - NewOnly, - // Output is only persisted if the task failed - ErrorsOnly, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct PaneSize { - pub rows: u16, - pub cols: u16, -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn assert_event_send() { - fn send_sync() {} - send_sync::(); - } -} diff --git a/crates/turborepo-ui/src/tui/handle.rs b/crates/turborepo-ui/src/tui/handle.rs deleted file mode 100644 index f69c913cf0713..0000000000000 --- a/crates/turborepo-ui/src/tui/handle.rs +++ /dev/null @@ -1,132 +0,0 @@ -use tokio::sync::{mpsc, oneshot}; - -use super::{ - app::FRAMERATE, - event::{CacheResult, OutputLogs, PaneSize}, - Error, Event, TaskResult, -}; -use crate::sender::{TaskSender, UISender}; - -/// Struct for sending app events to TUI rendering -#[derive(Debug, Clone)] -pub struct TuiSender { - primary: mpsc::UnboundedSender, -} - -/// Struct for receiving app events -pub struct AppReceiver { - primary: mpsc::UnboundedReceiver, -} - -impl TuiSender { - /// Create a new channel for sending app events. - /// - /// AppSender is meant to be held by the actual task runner - /// AppReceiver should be passed to `crate::tui::run_app` - pub fn new() -> (Self, AppReceiver) { - let (primary_tx, primary_rx) = mpsc::unbounded_channel(); - let tick_sender = primary_tx.clone(); - tokio::spawn(async move { - let mut interval = tokio::time::interval(FRAMERATE); - loop { - interval.tick().await; - if tick_sender.send(Event::Tick).is_err() { - break; - } - } - }); - ( - Self { - primary: primary_tx, - }, - AppReceiver { - primary: primary_rx, - }, - ) - } -} - -impl TuiSender { - pub fn start_task(&self, task: String, output_logs: OutputLogs) { - self.primary - .send(Event::StartTask { task, output_logs }) - .ok(); - } - - pub fn end_task(&self, task: String, result: TaskResult) { - self.primary.send(Event::EndTask { task, result }).ok(); - } - - pub fn status(&self, task: String, status: String, result: CacheResult) { - self.primary - .send(Event::Status { - task, - status, - result, - }) - .ok(); - } - - pub fn set_stdin(&self, task: String, stdin: Box) { - self.primary.send(Event::SetStdin { task, stdin }).ok(); - } - - /// Construct a sender configured for a specific task - pub fn task(&self, task: String) -> TaskSender { - TaskSender { - name: task, - handle: UISender::Tui(self.clone()), - logs: Default::default(), - } - } - - /// Stop rendering TUI and restore terminal to default configuration - pub async fn stop(&self) { - let (callback_tx, callback_rx) = oneshot::channel(); - // Send stop event, if receiver has dropped ignore error as - // it'll be a no-op. - self.primary.send(Event::Stop(callback_tx)).ok(); - // Wait for callback to be sent or the channel closed. - callback_rx.await.ok(); - } - - /// Update the list of tasks displayed in the TUI - pub fn update_tasks(&self, tasks: Vec) -> Result<(), crate::Error> { - Ok(self - .primary - .send(Event::UpdateTasks { tasks }) - .map_err(|err| Error::Mpsc(err.to_string()))?) - } - - pub fn output(&self, task: String, output: Vec) -> Result<(), crate::Error> { - Ok(self - .primary - .send(Event::TaskOutput { task, output }) - .map_err(|err| Error::Mpsc(err.to_string()))?) - } - - /// Restart the list of tasks displayed in the TUI - pub fn restart_tasks(&self, tasks: Vec) -> Result<(), crate::Error> { - Ok(self - .primary - .send(Event::RestartTasks { tasks }) - .map_err(|err| Error::Mpsc(err.to_string()))?) - } - - /// Fetches the size of the terminal pane - pub async fn pane_size(&self) -> Option { - let (callback_tx, callback_rx) = oneshot::channel(); - // Send query, if no receiver to handle the request return None - self.primary.send(Event::PaneSizeQuery(callback_tx)).ok()?; - // Wait for callback to be sent - callback_rx.await.ok() - } -} - -impl AppReceiver { - /// Receive an event, producing a tick event if no events are rec eived by - /// the deadline. - pub async fn recv(&mut self) -> Option { - self.primary.recv().await - } -} diff --git a/crates/turborepo-ui/src/tui/popup.rs b/crates/turborepo-ui/src/tui/popup.rs deleted file mode 100644 index 6d11b51b14901..0000000000000 --- a/crates/turborepo-ui/src/tui/popup.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::cmp::min; - -use ratatui::{ - layout::{Constraint, Flex, Layout, Rect}, - text::Line, - widgets::{Block, List, ListItem, Padding}, -}; - -const BIND_LIST: [&str; 12] = [ - "m - Toggle this help popup", - "↑ or j - Select previous task", - "↓ or k - Select next task", - "h - Toggle task list", - "p - Toggle pinned task selection", - "/ - Filter tasks to search term", - "ESC - Clear filter", - "i - Interact with task", - "Ctrl+z - Stop interacting with task", - "c - Copy logs selection (Only when logs are selected)", - "u - Scroll logs up", - "d - Scroll logs down", -]; - -pub fn popup_area(area: Rect) -> Rect { - let screen_width = area.width; - let screen_height = area.height; - - let popup_width = BIND_LIST - .iter() - .map(|s| s.len().saturating_add(4)) - .max() - .unwrap_or(0) as u16; - let popup_height = min((BIND_LIST.len().saturating_add(4)) as u16, screen_height); - - let x = screen_width.saturating_sub(popup_width) / 2; - let y = screen_height.saturating_sub(popup_height) / 2; - - let vertical = Layout::vertical([Constraint::Percentage(100)]).flex(Flex::Center); - let horizontal = Layout::horizontal([Constraint::Percentage(100)]).flex(Flex::Center); - - let [vertical_area] = vertical.areas(Rect { - x, - y, - width: popup_width, - height: popup_height, - }); - - let [area] = horizontal.areas(vertical_area); - - area -} - -pub fn popup(area: Rect) -> List<'static> { - let available_height = area.height.saturating_sub(4) as usize; - - let items: Vec = BIND_LIST - .iter() - .take(available_height) - .map(|item| ListItem::new(Line::from(*item))) - .collect(); - - let title_bottom = if available_height < BIND_LIST.len() { - let binds_not_visible = BIND_LIST.len().saturating_sub(available_height); - - let pluralize = if binds_not_visible > 1 { "s" } else { "" }; - let message = format!( - " {} more bind{}. Make your terminal taller. ", - binds_not_visible, pluralize - ); - Line::from(message) - } else { - Line::from("") - }; - - let outer = Block::bordered() - .title(" Keybinds ") - .title_bottom(title_bottom.to_string()) - .padding(Padding::uniform(1)); - - List::new(items).block(outer) -} diff --git a/crates/turborepo-ui/src/tui/search.rs b/crates/turborepo-ui/src/tui/search.rs deleted file mode 100644 index 23044a5bc09b9..0000000000000 --- a/crates/turborepo-ui/src/tui/search.rs +++ /dev/null @@ -1,130 +0,0 @@ -use std::{collections::HashSet, sync::Arc}; - -use super::task::TasksByStatus; - -#[derive(Debug, Clone)] -pub struct SearchResults { - query: String, - // We use Rc instead of String here for two reasons: - // - Rc for cheap clones since elements in `matches` will always be in `tasks` as well - // - Rc implements Borrow meaning we can query a `HashSet>` using a `&str` - // We do not modify the provided task names so we do not need the capabilities of String. - tasks: Vec>, - matches: HashSet>, -} - -impl SearchResults { - pub fn new(tasks: &TasksByStatus) -> Self { - Self { - tasks: tasks - .task_names_in_displayed_order() - .map(Arc::from) - .collect(), - query: String::new(), - matches: HashSet::new(), - } - } - - /// Updates search results with new search body - pub fn update_tasks(&mut self, tasks: &TasksByStatus) { - self.tasks.clear(); - self.tasks - .extend(tasks.task_names_in_displayed_order().map(Arc::from)); - self.update_matches(); - } - - /// Updates the query and the matches - pub fn modify_query(&mut self, modification: impl FnOnce(&mut String)) { - modification(&mut self.query); - self.update_matches(); - } - - fn update_matches(&mut self) { - self.matches.clear(); - if self.query.is_empty() { - return; - } - for task in self.tasks.iter().filter(|task| task.contains(&self.query)) { - self.matches.insert(task.clone()); - } - } - - /// Given an iterator it returns the first task that is in the search - /// results - pub fn first_match<'a>(&self, mut tasks: impl Iterator) -> Option<&'a str> { - tasks.find(|task| self.matches.contains(*task)) - } - - /// Returns if there are any matches for the query - pub fn has_matches(&self) -> bool { - !self.matches.is_empty() - } - - /// Returns query - pub fn query(&self) -> &str { - &self.query - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::tui::task::Task; - - fn basic_task_list() -> TasksByStatus { - TasksByStatus { - planned: vec![ - Task::new("app-a".into()), - Task::new("app-b".into()), - Task::new("pkg-a".into()), - ], - ..Default::default() - } - } - - #[test] - fn test_no_query_no_matches() { - let task_list = basic_task_list(); - let results = SearchResults::new(&task_list); - assert!(!results.has_matches()); - } - - #[test] - fn test_matches_first_result() { - let task_list = basic_task_list(); - let mut results = SearchResults::new(&task_list); - results.modify_query(|s| s.push_str("app")); - let result = results.first_match(task_list.task_names_in_displayed_order()); - assert_eq!(result, Some("app-a")); - let result = results.first_match(task_list.task_names_in_displayed_order().skip(1)); - assert_eq!(result, Some("app-b")); - let result = results.first_match(task_list.task_names_in_displayed_order().skip(2)); - assert_eq!(result, None); - } - - #[test] - fn test_update_task_rebuilds_matches() { - let mut task_list = basic_task_list(); - let mut results = SearchResults::new(&task_list); - results.modify_query(|s| s.push_str("app")); - assert!(results.has_matches()); - task_list.planned.remove(0); - task_list.planned.push(Task::new("app-c".into())); - results.update_tasks(&task_list); - assert!(results.has_matches()); - let result = results.first_match(task_list.task_names_in_displayed_order()); - assert_eq!(result, Some("app-b")); - let result = results.first_match(task_list.task_names_in_displayed_order().skip(1)); - assert_eq!(result, Some("app-c")); - } - - #[test] - fn test_no_match_on_empty_list() { - let task_list = basic_task_list(); - let mut results = SearchResults::new(&task_list); - results.modify_query(|s| s.push_str("app")); - assert!(results.has_matches()); - let result = results.first_match(std::iter::empty()); - assert_eq!(result, None); - } -} diff --git a/crates/turborepo-ui/src/tui/size.rs b/crates/turborepo-ui/src/tui/size.rs deleted file mode 100644 index 27bb2dc3c6c79..0000000000000 --- a/crates/turborepo-ui/src/tui/size.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::TaskTable; - -const PANE_SIZE_RATIO: f32 = 3.0 / 4.0; - -#[derive(Debug, Clone, Copy)] -pub struct SizeInfo { - task_width_hint: u16, - rows: u16, - cols: u16, -} - -impl SizeInfo { - pub fn new<'a>(rows: u16, cols: u16, tasks: impl Iterator) -> Self { - let task_width_hint = TaskTable::width_hint(tasks); - Self { - rows, - cols, - task_width_hint, - } - } - - pub fn resize(&mut self, rows: u16, cols: u16) { - self.rows = rows; - self.cols = cols; - } - - pub fn pane_rows(&self) -> u16 { - self.rows - // Account for header and footer in layout - .saturating_sub(2) - // Always allocate at least one row as vt100 crashes if emulating a zero area terminal - .max(1) - } - - pub fn task_list_width(&self) -> u16 { - self.cols - self.pane_cols() - } - - pub fn pane_cols(&self) -> u16 { - // Want to maximize pane width - let ratio_pane_width = (f32::from(self.cols) * PANE_SIZE_RATIO) as u16; - let full_task_width = self.cols.saturating_sub(self.task_width_hint); - full_task_width - .max(ratio_pane_width) - // We need to account for the left border of the pane - .saturating_sub(1) - } -} diff --git a/crates/turborepo-ui/src/tui/spinner.rs b/crates/turborepo-ui/src/tui/spinner.rs deleted file mode 100644 index c7549414c075d..0000000000000 --- a/crates/turborepo-ui/src/tui/spinner.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::time::{Duration, Instant}; - -const SPINNER_FRAMES: &[&str] = ["»"].as_slice(); -// const SPINNER_FRAMES: &[&str] = ["â ‹", "â ™", "â ¹", "â ¸", "â ¼", "â ´", "â ¦", "â §", "â ‡", -// "â "].as_slice(); -const FRAMERATE: Duration = Duration::from_millis(80); - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct SpinnerState { - frame: usize, - last_render: Option, -} - -impl SpinnerState { - pub fn new() -> Self { - Self { - frame: 0, - last_render: None, - } - } - - pub fn update(&mut self) { - if let Some(last_render) = self.last_render { - if last_render.elapsed() > FRAMERATE { - self.frame = (self.frame + 1) % SPINNER_FRAMES.len(); - self.last_render = Some(Instant::now()); - } - } else { - self.last_render = Some(Instant::now()); - } - } - - pub fn current(&self) -> &'static str { - SPINNER_FRAMES[self.frame] - } -} - -impl Default for SpinnerState { - fn default() -> Self { - Self::new() - } -} - -// Removed with iteration to double arrow symbol -// #[cfg(test)] -// mod test { -// use super::*; -// -// #[test] -// fn test_initial_update() { -// let mut spinner = SpinnerState::new(); -// assert!(spinner.last_render.is_none()); -// assert_eq!(spinner.frame, 0); -// spinner.update(); -// assert!(spinner.last_render.is_some()); -// assert_eq!(spinner.frame, 0, "initial update doesn't move frame"); -// } -// -// Removed with change to double arrow -// #[test] -// fn test_frame_update() { -// let mut spinner = SpinnerState::new(); -// // set last update to time that happened far before the spinner -// should increment let prev_render = Instant::now() - (FRAMERATE * 2); -// spinner.last_render = Some(prev_render); -// assert_eq!(spinner.frame, 0); -// spinner.update(); -// assert_eq!(spinner.frame, 1); -// let last_render = spinner.last_render.unwrap(); -// assert!(prev_render < last_render, "last render should be updated"); -// } -// } diff --git a/crates/turborepo-ui/src/tui/state.rs b/crates/turborepo-ui/src/tui/state.rs deleted file mode 100644 index d7d7f1bfd1b98..0000000000000 --- a/crates/turborepo-ui/src/tui/state.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::time::Instant; - -enum Event { - Tick, -} - -struct State { - current_time: Instant, -} - -struct Focus { - task_id: String, - focus_type: FocusType, -} - -enum FocusType { - View, - Interact, -} - -struct DoneTask { - id: String, - start: Instant, - end: Instant, -} diff --git a/crates/turborepo-ui/src/tui/table.rs b/crates/turborepo-ui/src/tui/table.rs deleted file mode 100644 index 3490b36ab6e54..0000000000000 --- a/crates/turborepo-ui/src/tui/table.rs +++ /dev/null @@ -1,135 +0,0 @@ -use ratatui::{ - layout::{Constraint, Rect}, - style::{Color, Modifier, Style, Stylize}, - text::Text, - widgets::{Block, Borders, Cell, Row, StatefulWidget, Table, TableState}, -}; - -use super::{event::TaskResult, spinner::SpinnerState, task::TasksByStatus}; - -/// A widget that renders a table of their tasks and their current status -/// -/// The tasks are ordered as follows: -/// - running tasks -/// - planned tasks -/// - finished tasks -/// - failed tasks -/// - successful tasks -/// - cached tasks -pub struct TaskTable<'b> { - tasks_by_type: &'b TasksByStatus, - spinner: SpinnerState, -} - -const TASK_NAVIGATE_INSTRUCTIONS: &str = "↑ ↓ - Select"; -const MORE_BINDS_INSTRUCTIONS: &str = "m - More binds"; - -impl<'b> TaskTable<'b> { - /// Construct a new table with all of the planned tasks - pub fn new(tasks_by_type: &'b TasksByStatus) -> Self { - Self { - tasks_by_type, - spinner: SpinnerState::default(), - } - } - - /// Provides a suggested width for the task table - pub fn width_hint<'a>(tasks: impl Iterator) -> u16 { - let task_name_width = tasks - .map(|task| task.len()) - .max() - .unwrap_or_default() - // Task column width should be large enough to fit "↑ ↓ to navigate instructions - // and truncate tasks with more than 40 chars. - .clamp(TASK_NAVIGATE_INSTRUCTIONS.len(), 40) as u16; - // Add space for column divider and status emoji - task_name_width + 1 - } - - /// Update the current time of the table - pub fn tick(&mut self) { - self.spinner.update(); - } - - fn finished_rows(&self) -> impl Iterator + '_ { - self.tasks_by_type.finished.iter().map(move |task| { - let name = if matches!(task.result(), TaskResult::CacheHit) { - Cell::new(Text::styled(task.name(), Style::default().italic())) - } else { - Cell::new(task.name()) - }; - - Row::new(vec![ - name, - match task.result() { - // matches Next.js (and many other CLI tools) https://github.com/vercel/next.js/blob/1a04d94aaec943d3cce93487fea3b8c8f8898f31/packages/next/src/build/output/log.ts - TaskResult::Success => { - Cell::new(Text::styled("✓", Style::default().green().bold())) - } - TaskResult::CacheHit => { - Cell::new(Text::styled("⊙", Style::default().magenta())) - } - TaskResult::Failure => { - Cell::new(Text::styled("⨯", Style::default().red().bold())) - } - }, - ]) - }) - } - - fn running_rows(&self) -> impl Iterator + '_ { - let spinner = self.spinner.current(); - self.tasks_by_type - .running - .iter() - .map(move |task| Row::new(vec![Cell::new(task.name()), Cell::new(Text::raw(spinner))])) - } - - fn planned_rows(&self) -> impl Iterator + '_ { - self.tasks_by_type - .planned - .iter() - .map(move |task| Row::new(vec![Cell::new(task.name()), Cell::new(" ")])) - } -} - -impl<'a> StatefulWidget for &'a TaskTable<'a> { - type State = TableState; - - fn render(self, area: Rect, buf: &mut ratatui::prelude::Buffer, state: &mut Self::State) { - let table = Table::new( - self.running_rows() - .chain(self.planned_rows()) - .chain(self.finished_rows()), - [ - Constraint::Min(15), - // Status takes one cell to render - Constraint::Length(1), - ], - ) - .highlight_style(Style::default().fg(Color::Yellow)) - .column_spacing(0) - .block(Block::new().borders(Borders::RIGHT)) - .header( - vec![Text::styled( - "Tasks", - Style::default().add_modifier(Modifier::DIM), - )] - .into_iter() - .map(Cell::from) - .collect::() - .height(1), - ) - .footer( - vec![Text::styled( - format!("{TASK_NAVIGATE_INSTRUCTIONS}\n{MORE_BINDS_INSTRUCTIONS}"), - Style::default().add_modifier(Modifier::DIM), - )] - .into_iter() - .map(Cell::from) - .collect::() - .height(2), - ); - StatefulWidget::render(table, area, buf, state); - } -} diff --git a/crates/turborepo-ui/src/wui/event.rs b/crates/turborepo-ui/src/wui/event.rs deleted file mode 100644 index df9cb12eb2c53..0000000000000 --- a/crates/turborepo-ui/src/wui/event.rs +++ /dev/null @@ -1,34 +0,0 @@ -use serde::Serialize; - -use crate::tui::event::{CacheResult, OutputLogs, TaskResult}; - -/// Specific events that the GraphQL server can send to the client, -/// not all the `Event` types from the TUI. -#[derive(Debug, Clone, Serialize)] -#[serde(tag = "type", content = "payload")] -pub enum WebUIEvent { - StartTask { - task: String, - output_logs: OutputLogs, - }, - TaskOutput { - task: String, - output: Vec, - }, - EndTask { - task: String, - result: TaskResult, - }, - CacheStatus { - task: String, - message: String, - result: CacheResult, - }, - UpdateTasks { - tasks: Vec, - }, - RestartTasks { - tasks: Vec, - }, - Stop, -} diff --git a/crates/turborepo-ui/src/wui/query.rs b/crates/turborepo-ui/src/wui/query.rs deleted file mode 100644 index 9a2ebfef63c70..0000000000000 --- a/crates/turborepo-ui/src/wui/query.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::sync::Arc; - -use async_graphql::{Object, SimpleObject}; -use serde::Serialize; -use tokio::sync::Mutex; - -use crate::wui::subscriber::{TaskState, WebUIState}; - -#[derive(Debug, Clone, Serialize, SimpleObject)] -struct RunTask { - name: String, - state: TaskState, -} - -struct CurrentRun<'a> { - state: &'a SharedState, -} - -#[Object] -impl CurrentRun<'_> { - async fn tasks(&self) -> Vec { - self.state - .lock() - .await - .tasks() - .iter() - .map(|(task, state)| RunTask { - name: task.clone(), - state: state.clone(), - }) - .collect() - } -} - -/// We keep the state in a `Arc>>` so both `Subscriber` and -/// `Query` can access it, with `Subscriber` mutating it and `Query` only -/// reading it. -pub type SharedState = Arc>; - -/// The query for actively running tasks. -/// -/// (As opposed to the query for general repository state `RepositoryQuery` -/// in `turborepo_lib::query`) -/// This is `None` when we're not actually running a task (e.g. `turbo query`) -pub struct RunQuery { - state: Option, -} - -impl RunQuery { - pub fn new(state: Option) -> Self { - Self { state } - } -} - -#[Object] -impl RunQuery { - async fn current_run(&self) -> Option { - Some(CurrentRun { - state: self.state.as_ref()?, - }) - } -} diff --git a/crates/turborepo-ui/src/wui/sender.rs b/crates/turborepo-ui/src/wui/sender.rs deleted file mode 100644 index 80c0b0645caf6..0000000000000 --- a/crates/turborepo-ui/src/wui/sender.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::io::Write; - -use tracing::log::warn; - -use crate::{ - sender::{TaskSender, UISender}, - tui::event::{CacheResult, OutputLogs, TaskResult}, - wui::{event::WebUIEvent, Error}, -}; - -#[derive(Debug, Clone)] -pub struct WebUISender { - pub tx: tokio::sync::mpsc::UnboundedSender, -} - -impl WebUISender { - pub fn new(tx: tokio::sync::mpsc::UnboundedSender) -> Self { - Self { tx } - } - pub fn start_task(&self, task: String, output_logs: OutputLogs) { - self.tx - .send(WebUIEvent::StartTask { task, output_logs }) - .ok(); - } - - pub fn restart_tasks(&self, tasks: Vec) -> Result<(), crate::Error> { - self.tx - .send(WebUIEvent::RestartTasks { tasks }) - .map_err(Error::Broadcast)?; - Ok(()) - } - - pub fn end_task(&self, task: String, result: TaskResult) { - self.tx.send(WebUIEvent::EndTask { task, result }).ok(); - } - - pub fn status(&self, task: String, message: String, result: CacheResult) { - self.tx - .send(WebUIEvent::CacheStatus { - task, - message, - result, - }) - .ok(); - } - - pub fn set_stdin(&self, _: String, _: Box) { - warn!("stdin is not supported (yet) in web ui"); - } - - pub fn task(&self, task: String) -> TaskSender { - TaskSender { - name: task, - handle: UISender::Wui(self.clone()), - logs: Default::default(), - } - } - - pub fn stop(&self) { - self.tx.send(WebUIEvent::Stop).ok(); - } - - pub fn update_tasks(&self, tasks: Vec) -> Result<(), crate::Error> { - self.tx - .send(WebUIEvent::UpdateTasks { tasks }) - .map_err(Error::Broadcast)?; - - Ok(()) - } - - pub fn output(&self, task: String, output: Vec) -> Result<(), crate::Error> { - self.tx - .send(WebUIEvent::TaskOutput { task, output }) - .map_err(Error::Broadcast)?; - - Ok(()) - } -} diff --git a/crates/turborepo-ui/src/wui/subscriber.rs b/crates/turborepo-ui/src/wui/subscriber.rs deleted file mode 100644 index daff04e78f7dd..0000000000000 --- a/crates/turborepo-ui/src/wui/subscriber.rs +++ /dev/null @@ -1,276 +0,0 @@ -use std::{collections::BTreeMap, sync::Arc}; - -use async_graphql::{Enum, SimpleObject}; -use serde::Serialize; -use tokio::sync::Mutex; - -use crate::{ - tui::event::{CacheResult, TaskResult}, - wui::{event::WebUIEvent, query::SharedState}, -}; - -/// Subscribes to the Web UI events and updates the state -pub struct Subscriber { - rx: tokio::sync::mpsc::UnboundedReceiver, -} - -impl Subscriber { - pub fn new(rx: tokio::sync::mpsc::UnboundedReceiver) -> Self { - Self { rx } - } - - pub async fn watch( - self, - // We use a tokio::sync::Mutex here because we want this future to be Send. - #[allow(clippy::type_complexity)] state: SharedState, - ) { - let mut rx = self.rx; - while let Some(event) = rx.recv().await { - Self::add_message(&state, event).await; - } - } - - async fn add_message(state: &Arc>, event: WebUIEvent) { - let mut state = state.lock().await; - - match event { - WebUIEvent::StartTask { - task, - output_logs: _, - } => { - state.tasks.insert( - task, - TaskState { - output: Vec::new(), - status: TaskStatus::Running, - cache_result: None, - cache_message: None, - }, - ); - } - WebUIEvent::TaskOutput { task, output } => { - state.tasks.get_mut(&task).unwrap().output.extend(output); - } - WebUIEvent::EndTask { task, result } => { - state.tasks.get_mut(&task).unwrap().status = TaskStatus::from(result); - } - WebUIEvent::CacheStatus { - task, - result, - message, - } => { - if result == CacheResult::Hit { - state.tasks.get_mut(&task).unwrap().status = TaskStatus::Cached; - } - state.tasks.get_mut(&task).unwrap().cache_result = Some(result); - state.tasks.get_mut(&task).unwrap().cache_message = Some(message); - } - WebUIEvent::Stop => { - // TODO: stop watching - } - WebUIEvent::UpdateTasks { tasks } => { - state.tasks = tasks - .into_iter() - .map(|task| { - ( - task, - TaskState { - output: Vec::new(), - status: TaskStatus::Pending, - cache_result: None, - cache_message: None, - }, - ) - }) - .collect(); - } - WebUIEvent::RestartTasks { tasks } => { - state.tasks = tasks - .into_iter() - .map(|task| { - ( - task, - TaskState { - output: Vec::new(), - status: TaskStatus::Running, - cache_result: None, - cache_message: None, - }, - ) - }) - .collect(); - } - } - } -} - -#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Enum)] -pub enum TaskStatus { - Pending, - Running, - Cached, - Failed, - Succeeded, -} - -impl From for TaskStatus { - fn from(result: TaskResult) -> Self { - match result { - TaskResult::Success => Self::Succeeded, - TaskResult::CacheHit => Self::Cached, - TaskResult::Failure => Self::Failed, - } - } -} - -#[derive(Debug, Clone, Serialize, SimpleObject)] -pub struct TaskState { - output: Vec, - status: TaskStatus, - cache_result: Option, - /// The message for the cache status, i.e. `cache hit, replaying logs` - cache_message: Option, -} - -#[derive(Debug, Default, Clone, Serialize)] -pub struct WebUIState { - tasks: BTreeMap, -} - -impl WebUIState { - pub fn tasks(&self) -> &BTreeMap { - &self.tasks - } -} - -#[cfg(test)] -mod test { - use async_graphql::{EmptyMutation, EmptySubscription, Schema}; - - use super::*; - use crate::{ - tui::event::OutputLogs, - wui::{query::RunQuery, sender::WebUISender}, - }; - - #[tokio::test] - async fn test_web_ui_state() -> Result<(), crate::Error> { - let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - let state = Arc::new(Mutex::new(WebUIState::default())); - let subscriber = Subscriber::new(rx); - - let sender = WebUISender::new(tx); - - // Start a successful task - sender.start_task("task".to_string(), OutputLogs::Full); - sender.output("task".to_string(), b"this is my output".to_vec())?; - sender.end_task("task".to_string(), TaskResult::Success); - - // Start a cached task - sender.start_task("task2".to_string(), OutputLogs::Full); - sender.status("task2".to_string(), "status".to_string(), CacheResult::Hit); - - // Start a failing task - sender.start_task("task3".to_string(), OutputLogs::Full); - sender.end_task("task3".to_string(), TaskResult::Failure); - - // Drop the sender so the subscriber can terminate - drop(sender); - - // Run the subscriber blocking - subscriber.watch(state.clone()).await; - - let state_handle = state.lock().await.clone(); - assert_eq!(state_handle.tasks().len(), 3); - assert_eq!( - state_handle.tasks().get("task2").unwrap().status, - TaskStatus::Cached - ); - assert_eq!( - state_handle.tasks().get("task").unwrap().status, - TaskStatus::Succeeded - ); - assert_eq!( - state_handle.tasks().get("task").unwrap().output, - b"this is my output" - ); - assert_eq!( - state_handle.tasks().get("task3").unwrap().status, - TaskStatus::Failed - ); - - // Now let's check with the GraphQL API - let schema = Schema::new(RunQuery::new(Some(state)), EmptyMutation, EmptySubscription); - let result = schema - .execute("query { currentRun { tasks { name state { status } } } }") - .await; - assert!(result.errors.is_empty()); - assert_eq!( - result.data, - async_graphql::Value::from_json(serde_json::json!({ - "currentRun": { - "tasks": [ - { - "name": "task", - "state": { - "status": "SUCCEEDED" - } - }, - { - "name": "task2", - "state": { - "status": "CACHED" - } - }, - { - "name": "task3", - "state": { - "status": "FAILED" - } - } - ] - } - })) - .unwrap() - ); - - Ok(()) - } - - #[tokio::test] - async fn test_restart_tasks() -> Result<(), crate::Error> { - let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - let state = Arc::new(Mutex::new(WebUIState::default())); - let subscriber = Subscriber::new(rx); - - let sender = WebUISender::new(tx); - - // Start a successful task - sender.start_task("task".to_string(), OutputLogs::Full); - sender.output("task".to_string(), b"this is my output".to_vec())?; - sender.end_task("task".to_string(), TaskResult::Success); - - // Start a cached task - sender.start_task("task2".to_string(), OutputLogs::Full); - sender.status("task2".to_string(), "status".to_string(), CacheResult::Hit); - - // Restart a task - sender.restart_tasks(vec!["task".to_string()])?; - - // Drop the sender so the subscriber can terminate - drop(sender); - - // Run the subscriber blocking - subscriber.watch(state.clone()).await; - - let state_handle = state.lock().await.clone(); - assert_eq!(state_handle.tasks().len(), 1); - assert_eq!( - state_handle.tasks().get("task").unwrap().status, - TaskStatus::Running - ); - assert!(state_handle.tasks().get("task").unwrap().output.is_empty()); - - Ok(()) - } -} diff --git a/crates/turborepo-ui/tests/threads.rs b/crates/turborepo-ui/tests/threads.rs deleted file mode 100644 index 63cdb54c3cac5..0000000000000 --- a/crates/turborepo-ui/tests/threads.rs +++ /dev/null @@ -1,115 +0,0 @@ -use std::{ - io::{self, BufRead, BufReader, Write}, - process::{Command, Stdio}, -}; - -use console::Style; -use turbopath::AbsoluteSystemPath; -use turborepo_ui::{ - ColorConfig, LogWriter, OutputClient, OutputClientBehavior, OutputSink, PrefixedUI, - PrefixedWriter, -}; - -#[test] -fn test_can_write_from_threads() { - // Construct our output sink and clients - let mut out = Vec::new(); - let mut err = Vec::new(); - let sink = OutputSink::new(&mut out, &mut err); - - let task1_client = sink.logger(OutputClientBehavior::Grouped); - let task2_client = sink.logger(OutputClientBehavior::Grouped); - - // Setup the log files used by the tasks - let log_dir = tempfile::tempdir().unwrap(); - let abs_log_dir = AbsoluteSystemPath::from_std_path(log_dir.path()).unwrap(); - let task1_logfile = abs_log_dir.join_component("task1.txt"); - let task2_logfile = abs_log_dir.join_component("task2.txt"); - - // Spawn two tasks that will produce output - std::thread::scope(|s| { - let task1_logfile = &task1_logfile; - let task2_logfile = &task2_logfile; - s.spawn(move || echo_task("foo", task1_client, task1_logfile)); - s.spawn(move || echo_task("bar", task2_client, task2_logfile)); - }); - - assert!(err.is_empty(), "nothing wrote to stderr"); - assert_eq!( - String::from_utf8(task1_logfile.read().unwrap()) - .unwrap() - .trim(), - "hello from foo" - ); - assert_eq!( - String::from_utf8(task2_logfile.read().unwrap()) - .unwrap() - .trim(), - "hello from bar" - ); - - let output = String::from_utf8(out).unwrap(); - let lines = output.lines().collect::>(); - assert_eq!(lines.len(), 4, "the two tasks should output two lines each"); - - let first_task = lines[0].split(' ').next().unwrap(); - assert_eq!(lines[0], format!("{first_task} > running {first_task}")); - assert_eq!(lines[1], format!("{first_task} > hello from {first_task}")); - let second_task = lines[2].split(' ').next().unwrap(); - assert_eq!(lines[2], format!("{second_task} > running {second_task}")); - assert_eq!( - lines[3], - format!("{second_task} > hello from {second_task}") - ); -} - -fn echo_task( - task_name: &'static str, - client: OutputClient, - log_file: &AbsoluteSystemPath, -) -> io::Result<()> { - // Construct the prefix UI used by turbo to write output - // this output will not appear in a task's log file. - let output_prefix = Style::new().apply_to(format!("{task_name} > ")); - let warn_prefix = Style::new().apply_to(format!("{task_name} warning > ")); - let color_config = ColorConfig::new(true); - let mut prefix_ui = PrefixedUI::new(color_config, client.stdout(), client.stderr()) - .with_output_prefix(output_prefix.clone()) - .with_warn_prefix(warn_prefix); - - prefix_ui.output(format!("running {task_name}")); - - // Construct the task logger that will write to the output sink as well as the - // log file - let mut task_logger = LogWriter::default(); - task_logger.with_log_file(log_file).unwrap(); - task_logger.with_writer(PrefixedWriter::new( - color_config, - output_prefix, - client.stdout(), - )); - - let mut cmd = Command::new("echo"); - cmd.args(["hello", "from", task_name]); - cmd.stdout(Stdio::piped()); - - let mut process = cmd.spawn().unwrap(); - let stdout = process.stdout.take().unwrap(); - - // Read the process output and send it to the task logger - let mut buf = String::new(); - let mut reader = BufReader::new(stdout); - while let Ok(n) = reader.read_line(&mut buf) { - if n == 0 { - break; - } else { - write!(task_logger, "{buf}").unwrap(); - } - buf.clear(); - } - process.wait()?; - - client.finish(true)?; - - Ok(()) -} diff --git a/crates/turborepo-unescape/Cargo.toml b/crates/turborepo-unescape/Cargo.toml index 8a745f4bdea10..4dab82eba6479 100644 --- a/crates/turborepo-unescape/Cargo.toml +++ b/crates/turborepo-unescape/Cargo.toml @@ -1,14 +1,21 @@ -[package] -name = "turborepo-unescape" -version = "0.1.0" -edition = "2021" -license = "MPL-2.0" - [dependencies] biome_deserialize = { workspace = true } biome_diagnostics = { workspace = true } -serde.workspace = true -serde_json.workspace = true + +[dependencies.serde] +workspace = true + +[dependencies.serde_json] +workspace = true + +[lib] +path = "Source/lib.rs" [lints] workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-unescape" +version = "0.1.0" diff --git a/crates/turborepo-unescape/Source/lib.rs b/crates/turborepo-unescape/Source/lib.rs new file mode 100644 index 0000000000000..2f3e26c0e62fe --- /dev/null +++ b/crates/turborepo-unescape/Source/lib.rs @@ -0,0 +1,58 @@ +use std::{fmt, fmt::Display, ops::Deref}; + +use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic}; + +// We're using a newtype here because biome currently doesn't +// handle escapes and we can't override the String deserializer +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[serde(transparent)] +pub struct UnescapedString(String); + +impl Display for UnescapedString { + fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(&self.0) } +} + +impl AsRef for UnescapedString { + fn as_ref(&self) -> &str { &self.0 } +} + +impl Deref for UnescapedString { + type Target = str; + + fn deref(&self) -> &Self::Target { &self.0 } +} +fn unescape_str(s:String) -> Result { + let wrapped_s = format!("\"{}\"", s); + + serde_json::from_str(&wrapped_s) +} + +impl Deserializable for UnescapedString { + fn deserialize( + value:&impl DeserializableValue, + name:&str, + diagnostics:&mut Vec, + ) -> Option { + let str = String::deserialize(value, name, diagnostics)?; + + match unescape_str(str) { + Ok(s) => Some(Self(s)), + Err(e) => { + diagnostics.push(DeserializationDiagnostic::new(format!("{}", e))); + None + }, + } + } +} + +impl From for String { + fn from(value:UnescapedString) -> Self { value.0 } +} + +impl From for UnescapedString { + fn from(value:String) -> Self { Self(value) } +} +// For testing purposes +impl From<&'static str> for UnescapedString { + fn from(value:&'static str) -> Self { Self(value.to_owned()) } +} diff --git a/crates/turborepo-unescape/src/lib.rs b/crates/turborepo-unescape/src/lib.rs deleted file mode 100644 index bbffef4ac3a9d..0000000000000 --- a/crates/turborepo-unescape/src/lib.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::{fmt, fmt::Display, ops::Deref}; - -use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic}; - -// We're using a newtype here because biome currently doesn't -// handle escapes and we can't override the String deserializer -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, PartialOrd, Ord)] -#[serde(transparent)] -pub struct UnescapedString(String); - -impl Display for UnescapedString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0) - } -} - -impl AsRef for UnescapedString { - fn as_ref(&self) -> &str { - &self.0 - } -} - -impl Deref for UnescapedString { - type Target = str; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} -fn unescape_str(s: String) -> Result { - let wrapped_s = format!("\"{}\"", s); - - serde_json::from_str(&wrapped_s) -} - -impl Deserializable for UnescapedString { - fn deserialize( - value: &impl DeserializableValue, - name: &str, - diagnostics: &mut Vec, - ) -> Option { - let str = String::deserialize(value, name, diagnostics)?; - - match unescape_str(str) { - Ok(s) => Some(Self(s)), - Err(e) => { - diagnostics.push(DeserializationDiagnostic::new(format!("{}", e))); - None - } - } - } -} - -impl From for String { - fn from(value: UnescapedString) -> Self { - value.0 - } -} - -impl From for UnescapedString { - fn from(value: String) -> Self { - Self(value) - } -} -// For testing purposes -impl From<&'static str> for UnescapedString { - fn from(value: &'static str) -> Self { - Self(value.to_owned()) - } -} diff --git a/crates/turborepo-updater/Cargo.toml b/crates/turborepo-updater/Cargo.toml index c13725216ade1..36ca6d1b85410 100644 --- a/crates/turborepo-updater/Cargo.toml +++ b/crates/turborepo-updater/Cargo.toml @@ -1,20 +1,3 @@ -[package] -name = "turbo-updater" -version = "0.1.0" -edition = "2021" -description = "Minimal wrapper around update-informer to provide npm registry support and consistent UI" -license = "MIT" -publish = false - -[features] -# Allows configuring a specific tls backend for reqwest. -# See top level Cargo.toml for more details. -native-tls = ["reqwest/native-tls", "update-informer/native-tls"] -rustls-tls = ["reqwest/rustls-tls", "update-informer/rustls-tls"] - -[lints] -workspace = true - [dependencies] atty = { workspace = true } console = { workspace = true } @@ -25,3 +8,21 @@ thiserror = { workspace = true } update-informer = { git = "https://github.com/nicholaslyang/update-informer.git", default-features = false, features = [ "reqwest", ] } + +[features] +native-tls = ["reqwest/native-tls", "update-informer/native-tls"] +rustls-tls = ["reqwest/rustls-tls", "update-informer/rustls-tls"] + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +description = "Minimal wrapper around update-informer to provide npm registry support and consistent UI" +edition = "2021" +license-file = "LICENSE" +name = "turbo-updater" +publish = false +version = "0.1.0" diff --git a/crates/turborepo-updater/Source/lib.rs b/crates/turborepo-updater/Source/lib.rs new file mode 100644 index 0000000000000..09358995bda0f --- /dev/null +++ b/crates/turborepo-updater/Source/lib.rs @@ -0,0 +1,166 @@ +#![deny(clippy::all)] + +//! Turborepo's update notifier. Indicates to the user that there is a new +//! version of `turbo` available. + +use std::{fmt, time::Duration}; + +use console::style; +use semver::Version as SemVerVersion; +use serde::Deserialize; +use thiserror::Error as ThisError; +use update_informer::{ + Check, + Package, + Registry, + Result as UpdateResult, + Version, + http_client::{GenericHttpClient, HttpClient}, +}; + +mod ui; + +// 800ms +const DEFAULT_TIMEOUT:Duration = Duration::from_millis(800); +// 1 day +const DEFAULT_INTERVAL:Duration = Duration::from_secs(60 * 60 * 24); + +const NOTIFIER_DISABLE_VARS:[&str; 2] = ["NO_UPDATE_NOTIFIER", "TURBO_NO_UPDATE_NOTIFIER"]; +const ENVIRONMENTAL_DISABLE_VARS:[&str; 1] = ["CI"]; + +#[derive(ThisError, Debug)] +pub enum UpdateNotifierError { + #[error("Failed to write to terminal")] + RenderError(#[from] ui::utils::GetDisplayLengthError), + #[error("Failed to parse current version")] + VersionError(#[from] semver::Error), + #[error("Failed to check for updates")] + FetchError(#[from] Box), +} + +#[derive(Deserialize, Debug)] +struct NpmVersionData { + version:String, +} + +#[derive(Debug)] +enum VersionTag { + Latest, + Canary, +} + +impl fmt::Display for VersionTag { + fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result { + match self { + VersionTag::Latest => write!(f, "latest"), + VersionTag::Canary => write!(f, "canary"), + } + } +} + +struct NPMRegistry; + +impl Registry for NPMRegistry { + const NAME:&'static str = "npm-registry"; + + fn get_latest_version( + http:GenericHttpClient, + pkg:&Package, + ) -> UpdateResult> { + // determine tag to request + let tag = get_tag_from_version(&pkg.version().semver().pre); + // since we're overloading tag within name, we need to split it back out + let full_name = pkg.to_string(); + let split_name:Vec<&str> = full_name.split('/').collect(); + let name = split_name[1]; + let url = format!( + "https://turbo.build/api/binaries/version?name={name}&tag={tag}", + name = name, + tag = tag + ); + + let result:NpmVersionData = http.get(&url)?; + Ok(Some(result.version)) + } +} + +fn get_tag_from_version(pre:&semver::Prerelease) -> VersionTag { + match pre { + t if t.contains("canary") => VersionTag::Canary, + _ => VersionTag::Latest, + } +} + +fn should_skip_notification() -> bool { + NOTIFIER_DISABLE_VARS.iter().any(|var| std::env::var(var).is_ok()) + || ENVIRONMENTAL_DISABLE_VARS.iter().any(|var| std::env::var(var).is_ok()) + || !atty::is(atty::Stream::Stdout) +} + +pub fn display_update_check( + package_name:&str, + github_repo:&str, + footer:Option<&str>, + current_version:&str, + timeout:Option, + interval:Option, +) -> Result<(), UpdateNotifierError> { + // bail early if the user has disabled update notifications + if should_skip_notification() { + return Ok(()); + } + + let version = check_for_updates(package_name, current_version, timeout, interval); + + if let Ok(Some(version)) = version { + let latest_version = version.to_string(); + // TODO: make this package manager aware + let update_cmd = style("npx @turbo/codemod@latest update").cyan().bold(); + + let msg = format!( + " + Update available {version_prefix}{current_version} ≫ {latest_version} + Changelog: {github_repo}/releases/tag/{latest_version} + Run \"{update_cmd}\" to update + ", + version_prefix = style("v").dim(), + current_version = style(current_version).dim(), + latest_version = style(latest_version).green().bold(), + github_repo = github_repo, + update_cmd = update_cmd + ); + + if let Some(footer) = footer { + return ui::message(&format!("{}\n{}", msg, footer)); + } + + return ui::message(&msg); + } + + Ok(()) +} + +pub fn check_for_updates( + package_name:&str, + current_version:&str, + timeout:Option, + interval:Option, +) -> Result, UpdateNotifierError> { + // we want notifications per channel (latest, canary, etc) so we need to ensure + // we have one cached latest version per channel. UpdateInformer does not + // support this out of the box, so we hack it into the name by overloading + // owner (in the supported owner/name format) to be channel/name. + let parsed_version = SemVerVersion::parse(current_version)?; + let tag = get_tag_from_version(&parsed_version.pre); + let package_name = format!("{}/{}", tag, package_name); + + let timeout = timeout.unwrap_or(DEFAULT_TIMEOUT); + let interval = interval.unwrap_or(DEFAULT_INTERVAL); + let informer = update_informer::new(NPMRegistry, package_name, current_version) + .timeout(timeout) + .interval(interval); + + let data = informer.check_version().map_err(UpdateNotifierError::FetchError)?; + + Ok(data) +} diff --git a/crates/turborepo-updater/Source/ui/mod.rs b/crates/turborepo-updater/Source/ui/mod.rs new file mode 100644 index 0000000000000..be1c0fb479488 --- /dev/null +++ b/crates/turborepo-updater/Source/ui/mod.rs @@ -0,0 +1,44 @@ +use console::{Term, measure_text_width}; + +use crate::UpdateNotifierError; +pub mod utils; + +const DEFAULT_PADDING:usize = 8; + +pub fn message(text:&str) -> Result<(), UpdateNotifierError> { + let size = Term::stdout().size_checked(); + let lines:Vec<&str> = text.split('\n').map(|line| line.trim()).collect(); + + // get the display width of each line so we can center it within the box later + let lines_display_width = lines.iter().map(|line| measure_text_width(line)).collect::>(); + + // find the longest line to determine layout + let longest_line = lines_display_width.iter().max().copied().unwrap_or_default(); + let full_message_width = longest_line + DEFAULT_PADDING; + + // create a curried render function to reduce verbosity when calling + let render_at_layout = |layout:utils::Layout, width:usize| { + utils::render_message(layout, width, lines, lines_display_width, full_message_width) + }; + + // render differently depending on viewport + if let Some((_, num_cols)) = size { + // if possible, pad this value slightly + let term_width = if num_cols > 2 { usize::from(num_cols) - 2 } else { num_cols.into() }; + + let can_fit_box = term_width >= full_message_width; + let can_center_text = term_width >= longest_line; + + if can_fit_box { + render_at_layout(utils::Layout::Large, term_width); + } else if can_center_text { + render_at_layout(utils::Layout::Medium, term_width); + } else { + render_at_layout(utils::Layout::Small, term_width); + } + } else { + render_at_layout(utils::Layout::Unknown, 0); + } + + Ok(()) +} diff --git a/crates/turborepo-updater/Source/ui/utils.rs b/crates/turborepo-updater/Source/ui/utils.rs new file mode 100644 index 0000000000000..a30becfe0f985 --- /dev/null +++ b/crates/turborepo-updater/Source/ui/utils.rs @@ -0,0 +1,130 @@ +use std::{io::Error as IOError, string::FromUtf8Error}; + +use console::style; +use thiserror::Error as ThisError; + +pub enum BorderAlignment { + Divider, + Top, + Bottom, +} + +pub enum Layout { + Unknown, + Small, + Medium, + Large, +} + +const TOP_LEFT:&str = "â•­"; +const TOP_RIGHT:&str = "â•®"; +const BOTTOM_LEFT:&str = "â•°"; +const BOTTOM_RIGHT:&str = "╯"; +const HORIZONTAL:&str = "─"; +const VERTICAL:&str = "│"; +const SPACE:&str = " "; + +#[derive(ThisError, Debug)] +pub enum GetDisplayLengthError { + #[error("Could not strip ANSI escape codes from string")] + StripError(#[from] IOError), + #[error("Could not convert to string")] + ConvertError(#[from] FromUtf8Error), +} + +pub fn x_border(width:usize, position:BorderAlignment) { + let border = match position { + BorderAlignment::Top => { + format!("{}{}{}", TOP_LEFT, HORIZONTAL.repeat(width), TOP_RIGHT) + }, + BorderAlignment::Bottom => { + format!("{}{}{}", BOTTOM_LEFT, HORIZONTAL.repeat(width), BOTTOM_RIGHT) + }, + BorderAlignment::Divider => HORIZONTAL.repeat(width), + }; + println!("{}", style(border).yellow()) +} + +pub fn render_message( + layout:Layout, + width:usize, + lines:Vec<&str>, + lines_display_width:Vec, + full_message_width:usize, +) { + match layout { + // Left aligned text with no border. + // Used when term width is unknown. + Layout::Unknown => { + for line in lines.iter() { + println!("{}", line); + } + }, + + // Left aligned text with top and bottom border. + // Used when text cannot be centered without wrapping + Layout::Small => { + x_border(width, BorderAlignment::Divider); + for (line, line_display_width) in lines.iter().zip(lines_display_width.iter()) { + if *line_display_width == 0 { + println!("{}", SPACE.repeat(width)); + } else { + println!("{}", line); + } + } + x_border(width, BorderAlignment::Divider); + }, + + // Centered text with top and bottom border. + // Used when text can be centered without wrapping, but + // there isn't enough room to include the box with padding. + Layout::Medium => { + x_border(width, BorderAlignment::Divider); + for (line, line_display_width) in lines.iter().zip(lines_display_width.iter()) { + if *line_display_width == 0 { + println!("{}", SPACE.repeat(width)); + } else { + let line_padding = (width - line_display_width) / 2; + // for lines of odd length, tack the reminder to the end + let line_padding_remainder = width - (line_padding * 2) - line_display_width; + println!( + "{}{}{}", + SPACE.repeat(line_padding), + line, + SPACE.repeat(line_padding + line_padding_remainder), + ); + } + } + x_border(width, BorderAlignment::Divider); + }, + + // Centered text with border on all sides + Layout::Large => { + x_border(full_message_width, BorderAlignment::Top); + for (line, line_display_width) in lines.iter().zip(lines_display_width.iter()) { + if *line_display_width == 0 { + println!( + "{}{}{}", + style(VERTICAL).yellow(), + SPACE.repeat(full_message_width), + style(VERTICAL).yellow() + ); + } else { + let line_padding = (full_message_width - line_display_width) / 2; + // for lines of odd length, tack the reminder to the end + let line_padding_remainder = + full_message_width - (line_padding * 2) - line_display_width; + println!( + "{}{}{}{}{}", + style(VERTICAL).yellow(), + SPACE.repeat(line_padding), + line, + SPACE.repeat(line_padding + line_padding_remainder), + style(VERTICAL).yellow() + ); + } + } + x_border(full_message_width, BorderAlignment::Bottom); + }, + } +} diff --git a/crates/turborepo-updater/src/lib.rs b/crates/turborepo-updater/src/lib.rs deleted file mode 100644 index bafb47acd9897..0000000000000 --- a/crates/turborepo-updater/src/lib.rs +++ /dev/null @@ -1,167 +0,0 @@ -#![deny(clippy::all)] - -//! Turborepo's update notifier. Indicates to the user that there is a new -//! version of `turbo` available. - -use std::{fmt, time::Duration}; - -use console::style; -use semver::Version as SemVerVersion; -use serde::Deserialize; -use thiserror::Error as ThisError; -use update_informer::{ - http_client::{GenericHttpClient, HttpClient}, - Check, Package, Registry, Result as UpdateResult, Version, -}; - -mod ui; - -// 800ms -const DEFAULT_TIMEOUT: Duration = Duration::from_millis(800); -// 1 day -const DEFAULT_INTERVAL: Duration = Duration::from_secs(60 * 60 * 24); - -const NOTIFIER_DISABLE_VARS: [&str; 2] = ["NO_UPDATE_NOTIFIER", "TURBO_NO_UPDATE_NOTIFIER"]; -const ENVIRONMENTAL_DISABLE_VARS: [&str; 1] = ["CI"]; - -#[derive(ThisError, Debug)] -pub enum UpdateNotifierError { - #[error("Failed to write to terminal")] - RenderError(#[from] ui::utils::GetDisplayLengthError), - #[error("Failed to parse current version")] - VersionError(#[from] semver::Error), - #[error("Failed to check for updates")] - FetchError(#[from] Box), -} - -#[derive(Deserialize, Debug)] -struct NpmVersionData { - version: String, -} - -#[derive(Debug)] -enum VersionTag { - Latest, - Canary, -} - -impl fmt::Display for VersionTag { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - VersionTag::Latest => write!(f, "latest"), - VersionTag::Canary => write!(f, "canary"), - } - } -} - -struct NPMRegistry; - -impl Registry for NPMRegistry { - const NAME: &'static str = "npm-registry"; - fn get_latest_version( - http: GenericHttpClient, - pkg: &Package, - ) -> UpdateResult> { - // determine tag to request - let tag = get_tag_from_version(&pkg.version().semver().pre); - // since we're overloading tag within name, we need to split it back out - let full_name = pkg.to_string(); - let split_name: Vec<&str> = full_name.split('/').collect(); - let name = split_name[1]; - let url = format!( - "https://turbo.build/api/binaries/version?name={name}&tag={tag}", - name = name, - tag = tag - ); - - let result: NpmVersionData = http.get(&url)?; - Ok(Some(result.version)) - } -} - -fn get_tag_from_version(pre: &semver::Prerelease) -> VersionTag { - match pre { - t if t.contains("canary") => VersionTag::Canary, - _ => VersionTag::Latest, - } -} - -fn should_skip_notification() -> bool { - NOTIFIER_DISABLE_VARS - .iter() - .any(|var| std::env::var(var).is_ok()) - || ENVIRONMENTAL_DISABLE_VARS - .iter() - .any(|var| std::env::var(var).is_ok()) - || !atty::is(atty::Stream::Stdout) -} - -pub fn display_update_check( - package_name: &str, - github_repo: &str, - footer: Option<&str>, - current_version: &str, - timeout: Option, - interval: Option, -) -> Result<(), UpdateNotifierError> { - // bail early if the user has disabled update notifications - if should_skip_notification() { - return Ok(()); - } - - let version = check_for_updates(package_name, current_version, timeout, interval); - - if let Ok(Some(version)) = version { - let latest_version = version.to_string(); - // TODO: make this package manager aware - let update_cmd = style("npx @turbo/codemod@latest update").cyan().bold(); - - let msg = format!( - " - Update available {version_prefix}{current_version} ≫ {latest_version} - Changelog: {github_repo}/releases/tag/{latest_version} - Run \"{update_cmd}\" to update - ", - version_prefix = style("v").dim(), - current_version = style(current_version).dim(), - latest_version = style(latest_version).green().bold(), - github_repo = github_repo, - update_cmd = update_cmd - ); - - if let Some(footer) = footer { - return ui::message(&format!("{}\n{}", msg, footer)); - } - - return ui::message(&msg); - } - - Ok(()) -} - -pub fn check_for_updates( - package_name: &str, - current_version: &str, - timeout: Option, - interval: Option, -) -> Result, UpdateNotifierError> { - // we want notifications per channel (latest, canary, etc) so we need to ensure - // we have one cached latest version per channel. UpdateInformer does not - // support this out of the box, so we hack it into the name by overloading - // owner (in the supported owner/name format) to be channel/name. - let parsed_version = SemVerVersion::parse(current_version)?; - let tag = get_tag_from_version(&parsed_version.pre); - let package_name = format!("{}/{}", tag, package_name); - - let timeout = timeout.unwrap_or(DEFAULT_TIMEOUT); - let interval = interval.unwrap_or(DEFAULT_INTERVAL); - let informer = update_informer::new(NPMRegistry, package_name, current_version) - .timeout(timeout) - .interval(interval); - - let data = informer - .check_version() - .map_err(UpdateNotifierError::FetchError)?; - - Ok(data) -} diff --git a/crates/turborepo-updater/src/ui/mod.rs b/crates/turborepo-updater/src/ui/mod.rs deleted file mode 100644 index a7e21cff2f310..0000000000000 --- a/crates/turborepo-updater/src/ui/mod.rs +++ /dev/null @@ -1,61 +0,0 @@ -use console::{measure_text_width, Term}; - -use crate::UpdateNotifierError; -pub mod utils; - -const DEFAULT_PADDING: usize = 8; - -pub fn message(text: &str) -> Result<(), UpdateNotifierError> { - let size = Term::stdout().size_checked(); - let lines: Vec<&str> = text.split('\n').map(|line| line.trim()).collect(); - - // get the display width of each line so we can center it within the box later - let lines_display_width = lines - .iter() - .map(|line| measure_text_width(line)) - .collect::>(); - - // find the longest line to determine layout - let longest_line = lines_display_width - .iter() - .max() - .copied() - .unwrap_or_default(); - let full_message_width = longest_line + DEFAULT_PADDING; - - // create a curried render function to reduce verbosity when calling - let render_at_layout = |layout: utils::Layout, width: usize| { - utils::render_message( - layout, - width, - lines, - lines_display_width, - full_message_width, - ) - }; - - // render differently depending on viewport - if let Some((_, num_cols)) = size { - // if possible, pad this value slightly - let term_width = if num_cols > 2 { - usize::from(num_cols) - 2 - } else { - num_cols.into() - }; - - let can_fit_box = term_width >= full_message_width; - let can_center_text = term_width >= longest_line; - - if can_fit_box { - render_at_layout(utils::Layout::Large, term_width); - } else if can_center_text { - render_at_layout(utils::Layout::Medium, term_width); - } else { - render_at_layout(utils::Layout::Small, term_width); - } - } else { - render_at_layout(utils::Layout::Unknown, 0); - } - - Ok(()) -} diff --git a/crates/turborepo-updater/src/ui/utils.rs b/crates/turborepo-updater/src/ui/utils.rs deleted file mode 100644 index fb8f048b7fafd..0000000000000 --- a/crates/turborepo-updater/src/ui/utils.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::{io::Error as IOError, string::FromUtf8Error}; - -use console::style; -use thiserror::Error as ThisError; - -pub enum BorderAlignment { - Divider, - Top, - Bottom, -} - -pub enum Layout { - Unknown, - Small, - Medium, - Large, -} - -const TOP_LEFT: &str = "â•­"; -const TOP_RIGHT: &str = "â•®"; -const BOTTOM_LEFT: &str = "â•°"; -const BOTTOM_RIGHT: &str = "╯"; -const HORIZONTAL: &str = "─"; -const VERTICAL: &str = "│"; -const SPACE: &str = " "; - -#[derive(ThisError, Debug)] -pub enum GetDisplayLengthError { - #[error("Could not strip ANSI escape codes from string")] - StripError(#[from] IOError), - #[error("Could not convert to string")] - ConvertError(#[from] FromUtf8Error), -} - -pub fn x_border(width: usize, position: BorderAlignment) { - let border = match position { - BorderAlignment::Top => { - format!("{}{}{}", TOP_LEFT, HORIZONTAL.repeat(width), TOP_RIGHT) - } - BorderAlignment::Bottom => { - format!( - "{}{}{}", - BOTTOM_LEFT, - HORIZONTAL.repeat(width), - BOTTOM_RIGHT - ) - } - BorderAlignment::Divider => HORIZONTAL.repeat(width), - }; - println!("{}", style(border).yellow()) -} - -pub fn render_message( - layout: Layout, - width: usize, - lines: Vec<&str>, - lines_display_width: Vec, - full_message_width: usize, -) { - match layout { - // Left aligned text with no border. - // Used when term width is unknown. - Layout::Unknown => { - for line in lines.iter() { - println!("{}", line); - } - } - - // Left aligned text with top and bottom border. - // Used when text cannot be centered without wrapping - Layout::Small => { - x_border(width, BorderAlignment::Divider); - for (line, line_display_width) in lines.iter().zip(lines_display_width.iter()) { - if *line_display_width == 0 { - println!("{}", SPACE.repeat(width)); - } else { - println!("{}", line); - } - } - x_border(width, BorderAlignment::Divider); - } - - // Centered text with top and bottom border. - // Used when text can be centered without wrapping, but - // there isn't enough room to include the box with padding. - Layout::Medium => { - x_border(width, BorderAlignment::Divider); - for (line, line_display_width) in lines.iter().zip(lines_display_width.iter()) { - if *line_display_width == 0 { - println!("{}", SPACE.repeat(width)); - } else { - let line_padding = (width - line_display_width) / 2; - // for lines of odd length, tack the reminder to the end - let line_padding_remainder = width - (line_padding * 2) - line_display_width; - println!( - "{}{}{}", - SPACE.repeat(line_padding), - line, - SPACE.repeat(line_padding + line_padding_remainder), - ); - } - } - x_border(width, BorderAlignment::Divider); - } - - // Centered text with border on all sides - Layout::Large => { - x_border(full_message_width, BorderAlignment::Top); - for (line, line_display_width) in lines.iter().zip(lines_display_width.iter()) { - if *line_display_width == 0 { - println!( - "{}{}{}", - style(VERTICAL).yellow(), - SPACE.repeat(full_message_width), - style(VERTICAL).yellow() - ); - } else { - let line_padding = (full_message_width - line_display_width) / 2; - // for lines of odd length, tack the reminder to the end - let line_padding_remainder = - full_message_width - (line_padding * 2) - line_display_width; - println!( - "{}{}{}{}{}", - style(VERTICAL).yellow(), - SPACE.repeat(line_padding), - line, - SPACE.repeat(line_padding + line_padding_remainder), - style(VERTICAL).yellow() - ); - } - } - x_border(full_message_width, BorderAlignment::Bottom); - } - } -} diff --git a/crates/turborepo-vercel-api-mock/Cargo.toml b/crates/turborepo-vercel-api-mock/Cargo.toml index 76e876234f63f..ccdc562e28abb 100644 --- a/crates/turborepo-vercel-api-mock/Cargo.toml +++ b/crates/turborepo-vercel-api-mock/Cargo.toml @@ -1,14 +1,3 @@ -[package] -name = "turborepo-vercel-api-mock" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lints] -workspace = true - [dependencies] anyhow = { workspace = true } axum = { workspace = true } @@ -18,3 +7,15 @@ port_scanner = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true, features = ["full"] } turborepo-vercel-api = { workspace = true } + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-vercel-api-mock" +version = "0.1.0" diff --git a/crates/turborepo-vercel-api-mock/Source/lib.rs b/crates/turborepo-vercel-api-mock/Source/lib.rs new file mode 100644 index 0000000000000..f4bd526d2cfd8 --- /dev/null +++ b/crates/turborepo-vercel-api-mock/Source/lib.rs @@ -0,0 +1,308 @@ +#![deny(clippy::all)] + +use std::{collections::HashMap, fs::OpenOptions, io::Write, net::SocketAddr, sync::Arc}; + +use anyhow::Result; +use axum::{ + Json, + Router, + body::Body, + extract::Path, + http::{HeaderMap, HeaderValue, StatusCode, header::CONTENT_LENGTH}, + routing::{get, head, options, patch, post, put}, +}; +use futures_util::StreamExt; +use tokio::{net::TcpListener, sync::Mutex}; +use turborepo_vercel_api::{ + AnalyticsEvent, + CachingStatus, + CachingStatusResponse, + Membership, + Role, + Space, + SpaceRun, + SpacesResponse, + Team, + TeamsResponse, + User, + UserResponse, + VerificationResponse, +}; + +pub const EXPECTED_TOKEN:&str = "expected_token"; +pub const EXPECTED_USER_ID:&str = "expected_user_id"; +pub const EXPECTED_USERNAME:&str = "expected_username"; +pub const EXPECTED_EMAIL:&str = "expected_email"; +pub const EXPECTED_USER_CREATED_AT:Option = Some(0); + +pub const EXPECTED_TEAM_ID:&str = "expected_team_id"; +pub const EXPECTED_TEAM_SLUG:&str = "expected_team_slug"; +pub const EXPECTED_TEAM_NAME:&str = "expected_team_name"; +pub const EXPECTED_TEAM_CREATED_AT:u64 = 0; + +pub const EXPECTED_SPACE_ID:&str = "expected_space_id"; +pub const EXPECTED_SPACE_NAME:&str = "expected_space_name"; +pub const EXPECTED_SPACE_RUN_ID:&str = "expected_space_run_id"; +pub const EXPECTED_SPACE_RUN_URL:&str = "https://example.com"; + +pub const EXPECTED_SSO_TEAM_ID:&str = "expected_sso_team_id"; +pub const EXPECTED_SSO_TEAM_SLUG:&str = "expected_sso_team_slug"; + +pub async fn start_test_server(port:u16) -> Result<()> { + let get_durations_ref = Arc::new(Mutex::new(HashMap::new())); + let head_durations_ref = get_durations_ref.clone(); + let put_durations_ref = get_durations_ref.clone(); + let put_tempdir_ref = Arc::new(tempfile::tempdir()?); + let get_tempdir_ref = put_tempdir_ref.clone(); + + let get_analytics_events_ref = Arc::new(Mutex::new(Vec::new())); + let post_analytics_events_ref = get_analytics_events_ref.clone(); + + let app = Router::new() + .route( + "/v2/user", + get(|| { + async move { + Json(UserResponse { + user:User { + id:EXPECTED_USER_ID.to_string(), + username:EXPECTED_USERNAME.to_string(), + email:EXPECTED_EMAIL.to_string(), + name:None, + created_at:EXPECTED_USER_CREATED_AT, + }, + }) + } + }), + ) + .route( + "/v2/teams", + get(|| { + async move { + Json(TeamsResponse { + teams:vec![Team { + id:EXPECTED_TEAM_ID.to_string(), + slug:EXPECTED_TEAM_SLUG.to_string(), + name:EXPECTED_TEAM_NAME.to_string(), + created_at:EXPECTED_TEAM_CREATED_AT, + created:Default::default(), + membership:Membership::new(Role::Owner), + }], + }) + } + }), + ) + .route( + "/v0/spaces", + get(|| { + async move { + Json(SpacesResponse { + spaces:vec![Space { + id:EXPECTED_SPACE_ID.to_string(), + name:EXPECTED_SPACE_NAME.to_string(), + }], + }) + } + }), + ) + .route( + "/v0/spaces/:space_id/runs", + post(|Path(space_id):Path| { + async move { + if space_id != EXPECTED_SPACE_ID { + return (StatusCode::NOT_FOUND, Json(None)); + } + + ( + StatusCode::OK, + Json(Some(SpaceRun { + id:EXPECTED_SPACE_RUN_ID.to_string(), + url:EXPECTED_SPACE_RUN_URL.to_string(), + })), + ) + } + }), + ) + .route( + "/v0/spaces/:space_id/runs/:run_id", + patch(|Path((space_id, run_id)):Path<(String, String)>| { + async move { + if space_id != EXPECTED_SPACE_ID || run_id != EXPECTED_SPACE_RUN_ID { + return StatusCode::NOT_FOUND; + } + + StatusCode::OK + } + }), + ) + .route( + "/v0/spaces/:space_id/runs/:run_id/tasks", + post(|Path((space_id, run_id)):Path<(String, String)>| { + async move { + if space_id != EXPECTED_SPACE_ID || run_id != EXPECTED_SPACE_RUN_ID { + return StatusCode::NOT_FOUND; + } + + StatusCode::OK + } + }), + ) + .route( + "/v8/artifacts/status", + get(|| async { Json(CachingStatusResponse { status:CachingStatus::Enabled }) }), + ) + .route( + "/registration/verify", + get(|| { + async move { + Json(VerificationResponse { + token:EXPECTED_TOKEN.to_string(), + team_id:Some(EXPECTED_SSO_TEAM_ID.to_string()), + }) + } + }), + ) + .route( + "/v8/artifacts/:hash", + put(|Path(hash):Path, headers:HeaderMap, body:Body| { + async move { + let root_path = put_tempdir_ref.path(); + let file_path = root_path.join(&hash); + let mut file = + OpenOptions::new().append(true).create(true).open(&file_path).unwrap(); + + let duration = headers + .get("x-artifact-duration") + .and_then(|header_value| header_value.to_str().ok()) + .and_then(|duration| duration.parse::().ok()) + .expect("x-artifact-duration header is missing"); + + assert!( + headers.get(CONTENT_LENGTH).is_some(), + "expected to get content-length" + ); + + let mut durations_map = put_durations_ref.lock().await; + durations_map.insert(hash.clone(), duration); + + let mut body_stream = body.into_data_stream(); + while let Some(item) = body_stream.next().await { + let chunk = item.unwrap(); + file.write_all(&chunk).unwrap(); + } + + (StatusCode::CREATED, Json(hash)) + } + }), + ) + .route( + "/v8/artifacts/:hash", + get(|Path(hash):Path| { + async move { + let root_path = get_tempdir_ref.path(); + let file_path = root_path.join(&hash); + let Ok(buffer) = std::fs::read(file_path) else { + return (StatusCode::NOT_FOUND, HeaderMap::new(), Vec::new()); + }; + let duration = get_durations_ref.lock().await.get(&hash).cloned().unwrap_or(0); + let mut headers = HeaderMap::new(); + + headers.insert( + "x-artifact-duration", + HeaderValue::from_str(&duration.to_string()).unwrap(), + ); + + (StatusCode::FOUND, headers, buffer) + } + }), + ) + .route( + "/v8/artifacts/:hash", + head(|Path(hash):Path| { + async move { + let mut headers = HeaderMap::new(); + + let Some(duration) = head_durations_ref.lock().await.get(&hash).cloned() else { + return (StatusCode::NOT_FOUND, headers); + }; + + headers.insert( + "x-artifact-duration", + HeaderValue::from_str(&duration.to_string()).unwrap(), + ); + + (StatusCode::OK, headers) + } + }), + ) + .route( + "/v8/artifacts/events", + post(|Json(analytics_events):Json>| { + async move { + post_analytics_events_ref.lock().await.extend(analytics_events); + } + }), + ) + .route( + "/v8/artifacts/events", + get(|| async move { Json(get_analytics_events_ref.lock().await.clone()) }), + ) + .route( + "/preflight/absolute-location", + options(|| { + async { + let mut headers = HeaderMap::new(); + headers.insert("Location", "http://example.com/about".parse().unwrap()); + + headers + } + }), + ) + .route( + "/preflight/relative-location", + options(|| { + async { + let mut headers = HeaderMap::new(); + headers.insert("Location", "/about/me".parse().unwrap()); + + headers + } + }), + ) + .route( + "/preflight/allow-auth", + options(|| { + async { + let mut headers = HeaderMap::new(); + headers.insert( + "Access-Control-Allow-Headers", + "Authorization, Location, Access-Control-Allow-Headers".parse().unwrap(), + ); + + headers + } + }), + ) + .route( + "/preflight/no-allow-auth", + options(|| { + async { + let mut headers = HeaderMap::new(); + headers.insert( + "Access-Control-Allow-Headers", + "x-authorization-foo, Location".parse().unwrap(), + ); + + headers + } + }), + ); + + let addr = SocketAddr::from(([127, 0, 0, 1], port)); + let listener = TcpListener::bind(addr).await?; + // We print the port so integration tests can use it + println!("{}", port); + axum::serve(listener, app).await?; + + Ok(()) +} diff --git a/crates/turborepo-vercel-api-mock/Source/main.rs b/crates/turborepo-vercel-api-mock/Source/main.rs new file mode 100644 index 0000000000000..dad05f18d2c5b --- /dev/null +++ b/crates/turborepo-vercel-api-mock/Source/main.rs @@ -0,0 +1,9 @@ +use anyhow::Result; +use turborepo_vercel_api_mock::start_test_server; + +#[tokio::main] +async fn main() -> Result<()> { + let port = port_scanner::request_open_port().unwrap(); + tokio::task::block_in_place(|| start_test_server(port)).await?; + Ok(()) +} diff --git a/crates/turborepo-vercel-api-mock/src/lib.rs b/crates/turborepo-vercel-api-mock/src/lib.rs deleted file mode 100644 index 9d67f482e4534..0000000000000 --- a/crates/turborepo-vercel-api-mock/src/lib.rs +++ /dev/null @@ -1,291 +0,0 @@ -#![deny(clippy::all)] - -use std::{collections::HashMap, fs::OpenOptions, io::Write, net::SocketAddr, sync::Arc}; - -use anyhow::Result; -use axum::{ - body::Body, - extract::Path, - http::{header::CONTENT_LENGTH, HeaderMap, HeaderValue, StatusCode}, - routing::{get, head, options, patch, post, put}, - Json, Router, -}; -use futures_util::StreamExt; -use tokio::{net::TcpListener, sync::Mutex}; -use turborepo_vercel_api::{ - AnalyticsEvent, CachingStatus, CachingStatusResponse, Membership, Role, Space, SpaceRun, - SpacesResponse, Team, TeamsResponse, User, UserResponse, VerificationResponse, -}; - -pub const EXPECTED_TOKEN: &str = "expected_token"; -pub const EXPECTED_USER_ID: &str = "expected_user_id"; -pub const EXPECTED_USERNAME: &str = "expected_username"; -pub const EXPECTED_EMAIL: &str = "expected_email"; -pub const EXPECTED_USER_CREATED_AT: Option = Some(0); - -pub const EXPECTED_TEAM_ID: &str = "expected_team_id"; -pub const EXPECTED_TEAM_SLUG: &str = "expected_team_slug"; -pub const EXPECTED_TEAM_NAME: &str = "expected_team_name"; -pub const EXPECTED_TEAM_CREATED_AT: u64 = 0; - -pub const EXPECTED_SPACE_ID: &str = "expected_space_id"; -pub const EXPECTED_SPACE_NAME: &str = "expected_space_name"; -pub const EXPECTED_SPACE_RUN_ID: &str = "expected_space_run_id"; -pub const EXPECTED_SPACE_RUN_URL: &str = "https://example.com"; - -pub const EXPECTED_SSO_TEAM_ID: &str = "expected_sso_team_id"; -pub const EXPECTED_SSO_TEAM_SLUG: &str = "expected_sso_team_slug"; - -pub async fn start_test_server(port: u16) -> Result<()> { - let get_durations_ref = Arc::new(Mutex::new(HashMap::new())); - let head_durations_ref = get_durations_ref.clone(); - let put_durations_ref = get_durations_ref.clone(); - let put_tempdir_ref = Arc::new(tempfile::tempdir()?); - let get_tempdir_ref = put_tempdir_ref.clone(); - - let get_analytics_events_ref = Arc::new(Mutex::new(Vec::new())); - let post_analytics_events_ref = get_analytics_events_ref.clone(); - - let app = Router::new() - .route( - "/v2/user", - get(|| async move { - Json(UserResponse { - user: User { - id: EXPECTED_USER_ID.to_string(), - username: EXPECTED_USERNAME.to_string(), - email: EXPECTED_EMAIL.to_string(), - name: None, - created_at: EXPECTED_USER_CREATED_AT, - }, - }) - }), - ) - .route( - "/v2/teams", - get(|| async move { - Json(TeamsResponse { - teams: vec![Team { - id: EXPECTED_TEAM_ID.to_string(), - slug: EXPECTED_TEAM_SLUG.to_string(), - name: EXPECTED_TEAM_NAME.to_string(), - created_at: EXPECTED_TEAM_CREATED_AT, - created: Default::default(), - membership: Membership::new(Role::Owner), - }], - }) - }), - ) - .route( - "/v0/spaces", - get(|| async move { - Json(SpacesResponse { - spaces: vec![Space { - id: EXPECTED_SPACE_ID.to_string(), - name: EXPECTED_SPACE_NAME.to_string(), - }], - }) - }), - ) - .route( - "/v0/spaces/:space_id/runs", - post(|Path(space_id): Path| async move { - if space_id != EXPECTED_SPACE_ID { - return (StatusCode::NOT_FOUND, Json(None)); - } - - ( - StatusCode::OK, - Json(Some(SpaceRun { - id: EXPECTED_SPACE_RUN_ID.to_string(), - url: EXPECTED_SPACE_RUN_URL.to_string(), - })), - ) - }), - ) - .route( - "/v0/spaces/:space_id/runs/:run_id", - patch( - |Path((space_id, run_id)): Path<(String, String)>| async move { - if space_id != EXPECTED_SPACE_ID || run_id != EXPECTED_SPACE_RUN_ID { - return StatusCode::NOT_FOUND; - } - - StatusCode::OK - }, - ), - ) - .route( - "/v0/spaces/:space_id/runs/:run_id/tasks", - post( - |Path((space_id, run_id)): Path<(String, String)>| async move { - if space_id != EXPECTED_SPACE_ID || run_id != EXPECTED_SPACE_RUN_ID { - return StatusCode::NOT_FOUND; - } - - StatusCode::OK - }, - ), - ) - .route( - "/v8/artifacts/status", - get(|| async { - Json(CachingStatusResponse { - status: CachingStatus::Enabled, - }) - }), - ) - .route( - "/registration/verify", - get(|| async move { - Json(VerificationResponse { - token: EXPECTED_TOKEN.to_string(), - team_id: Some(EXPECTED_SSO_TEAM_ID.to_string()), - }) - }), - ) - .route( - "/v8/artifacts/:hash", - put( - |Path(hash): Path, headers: HeaderMap, body: Body| async move { - let root_path = put_tempdir_ref.path(); - let file_path = root_path.join(&hash); - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&file_path) - .unwrap(); - - let duration = headers - .get("x-artifact-duration") - .and_then(|header_value| header_value.to_str().ok()) - .and_then(|duration| duration.parse::().ok()) - .expect("x-artifact-duration header is missing"); - - assert!( - headers.get(CONTENT_LENGTH).is_some(), - "expected to get content-length" - ); - - let mut durations_map = put_durations_ref.lock().await; - durations_map.insert(hash.clone(), duration); - - let mut body_stream = body.into_data_stream(); - while let Some(item) = body_stream.next().await { - let chunk = item.unwrap(); - file.write_all(&chunk).unwrap(); - } - - (StatusCode::CREATED, Json(hash)) - }, - ), - ) - .route( - "/v8/artifacts/:hash", - get(|Path(hash): Path| async move { - let root_path = get_tempdir_ref.path(); - let file_path = root_path.join(&hash); - let Ok(buffer) = std::fs::read(file_path) else { - return (StatusCode::NOT_FOUND, HeaderMap::new(), Vec::new()); - }; - let duration = get_durations_ref - .lock() - .await - .get(&hash) - .cloned() - .unwrap_or(0); - let mut headers = HeaderMap::new(); - - headers.insert( - "x-artifact-duration", - HeaderValue::from_str(&duration.to_string()).unwrap(), - ); - - (StatusCode::FOUND, headers, buffer) - }), - ) - .route( - "/v8/artifacts/:hash", - head(|Path(hash): Path| async move { - let mut headers = HeaderMap::new(); - - let Some(duration) = head_durations_ref.lock().await.get(&hash).cloned() else { - return (StatusCode::NOT_FOUND, headers); - }; - - headers.insert( - "x-artifact-duration", - HeaderValue::from_str(&duration.to_string()).unwrap(), - ); - - (StatusCode::OK, headers) - }), - ) - .route( - "/v8/artifacts/events", - post( - |Json(analytics_events): Json>| async move { - post_analytics_events_ref - .lock() - .await - .extend(analytics_events); - }, - ), - ) - .route( - "/v8/artifacts/events", - get(|| async move { Json(get_analytics_events_ref.lock().await.clone()) }), - ) - .route( - "/preflight/absolute-location", - options(|| async { - let mut headers = HeaderMap::new(); - headers.insert("Location", "http://example.com/about".parse().unwrap()); - - headers - }), - ) - .route( - "/preflight/relative-location", - options(|| async { - let mut headers = HeaderMap::new(); - headers.insert("Location", "/about/me".parse().unwrap()); - - headers - }), - ) - .route( - "/preflight/allow-auth", - options(|| async { - let mut headers = HeaderMap::new(); - headers.insert( - "Access-Control-Allow-Headers", - "Authorization, Location, Access-Control-Allow-Headers" - .parse() - .unwrap(), - ); - - headers - }), - ) - .route( - "/preflight/no-allow-auth", - options(|| async { - let mut headers = HeaderMap::new(); - headers.insert( - "Access-Control-Allow-Headers", - "x-authorization-foo, Location".parse().unwrap(), - ); - - headers - }), - ); - - let addr = SocketAddr::from(([127, 0, 0, 1], port)); - let listener = TcpListener::bind(addr).await?; - // We print the port so integration tests can use it - println!("{}", port); - axum::serve(listener, app).await?; - - Ok(()) -} diff --git a/crates/turborepo-vercel-api-mock/src/main.rs b/crates/turborepo-vercel-api-mock/src/main.rs deleted file mode 100644 index 42c4ea5c29a34..0000000000000 --- a/crates/turborepo-vercel-api-mock/src/main.rs +++ /dev/null @@ -1,9 +0,0 @@ -use anyhow::Result; -use turborepo_vercel_api_mock::start_test_server; - -#[tokio::main] -async fn main() -> Result<()> { - let port = port_scanner::request_open_port().unwrap(); - tokio::task::block_in_place(|| start_test_server(port)).await?; - Ok(()) -} diff --git a/crates/turborepo-vercel-api/Cargo.toml b/crates/turborepo-vercel-api/Cargo.toml index 0a398bf56d824..212e65e2cc335 100644 --- a/crates/turborepo-vercel-api/Cargo.toml +++ b/crates/turborepo-vercel-api/Cargo.toml @@ -1,20 +1,21 @@ -[package] -name = "turborepo-vercel-api" -version = "0.1.0" -edition = "2021" -license = "MIT" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +chrono = { workspace = true, features = ["serde"] } +serde = { workspace = true } +url = { workspace = true } [dev-dependencies] insta = { workspace = true } serde_json = { workspace = true } test-case = { workspace = true } +[lib] +path = "Source/lib.rs" + [lints] workspace = true -[dependencies] -chrono = { workspace = true, features = ["serde"] } -serde = { workspace = true } -url = { workspace = true } +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-vercel-api" +version = "0.1.0" diff --git a/crates/turborepo-vercel-api/Source/lib.rs b/crates/turborepo-vercel-api/Source/lib.rs new file mode 100644 index 0000000000000..b4a918bb0c56b --- /dev/null +++ b/crates/turborepo-vercel-api/Source/lib.rs @@ -0,0 +1,200 @@ +//! Types for interacting with the Vercel API. Used for both +//! the client (`turborepo-api-client`) and for the +//! mock server (`turborepo-vercel-api-mock`) +use serde::{Deserialize, Serialize}; +use url::Url; +pub mod telemetry; +pub mod token; + +#[derive(Debug, Clone, Deserialize)] +pub struct VerifiedSsoUser { + pub token:String, + pub team_id:Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct VerificationResponse { + pub token:String, + pub team_id:Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum CachingStatus { + Disabled, + Enabled, + OverLimit, + Paused, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CachingStatusResponse { + pub status:CachingStatus, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ArtifactResponse { + pub duration:u64, + pub expected_tag:Option, + pub body:Vec, +} + +/// Membership is the relationship between the logged-in user and a particular +/// team +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Membership { + role:Role, +} + +impl Membership { + #[allow(dead_code)] + pub fn new(role:Role) -> Self { Self { role } } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "UPPERCASE")] +pub enum Role { + // ordered by access-level + Owner, + Admin, + Member, + Developer, + Contributor, + Billing, + Viewer, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Team { + pub id:String, + pub slug:String, + pub name:String, + #[serde(rename = "createdAt")] + pub created_at:u64, + pub created:chrono::DateTime, + pub membership:Membership, +} + +impl Team { + pub fn is_owner(&self) -> bool { matches!(self.membership.role, Role::Owner) } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Space { + pub id:String, + pub name:String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TeamsResponse { + pub teams:Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SpacesResponse { + pub spaces:Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SpaceRun { + pub id:String, + pub url:String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct User { + pub id:String, + pub username:String, + pub email:String, + pub name:Option, + #[serde(rename = "createdAt")] + pub created_at:Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct UserResponse { + pub user:User, +} + +#[derive(Debug)] +pub struct PreflightResponse { + pub location:Url, + pub allow_authorization_header:bool, +} + +#[derive(Deserialize)] +pub struct APIError { + pub code:String, + pub message:String, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "UPPERCASE")] +pub enum CacheSource { + Local, + Remote, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "UPPERCASE")] +pub enum CacheEvent { + Hit, + Miss, +} +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct AnalyticsEvent { + #[serde(skip_serializing_if = "Option::is_none")] + pub session_id:Option, + pub source:CacheSource, + pub event:CacheEvent, + pub hash:String, + pub duration:u64, +} + +impl AnalyticsEvent { + pub fn set_session_id(&mut self, id:String) { self.session_id = Some(id); } +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + + use crate::{AnalyticsEvent, CacheEvent, CacheSource}; + + #[test_case( + AnalyticsEvent { + session_id: Some("session-id".to_string()), + source: CacheSource::Local, + event: CacheEvent::Hit, + hash: "this-is-my-hash".to_string(), + duration: 58, + }, + "with-id-local-hit" + )] + #[test_case( + AnalyticsEvent { + session_id: Some("session-id".to_string()), + source: CacheSource::Remote, + event: CacheEvent::Miss, + hash: "this-is-my-hash-2".to_string(), + duration: 21, + }, + "with-id-remote-miss" + )] + #[test_case( + AnalyticsEvent { + session_id: None, + source: CacheSource::Remote, + event: CacheEvent::Miss, + hash: "this-is-my-hash-2".to_string(), + duration: 21, + }, + "without-id-remote-miss" + )] + fn test_serialize_analytics_event(event:AnalyticsEvent, name:&str) { + let json = serde_json::to_string(&event).unwrap(); + insta::assert_json_snapshot!(name, json); + } +} diff --git a/crates/turborepo-vercel-api/src/snapshots/turborepo_vercel_api__tests__with-id-local-hit.snap b/crates/turborepo-vercel-api/Source/snapshots/turborepo_vercel_api__tests__with-id-local-hit.snap similarity index 100% rename from crates/turborepo-vercel-api/src/snapshots/turborepo_vercel_api__tests__with-id-local-hit.snap rename to crates/turborepo-vercel-api/Source/snapshots/turborepo_vercel_api__tests__with-id-local-hit.snap diff --git a/crates/turborepo-vercel-api/src/snapshots/turborepo_vercel_api__tests__with-id-remote-miss.snap b/crates/turborepo-vercel-api/Source/snapshots/turborepo_vercel_api__tests__with-id-remote-miss.snap similarity index 100% rename from crates/turborepo-vercel-api/src/snapshots/turborepo_vercel_api__tests__with-id-remote-miss.snap rename to crates/turborepo-vercel-api/Source/snapshots/turborepo_vercel_api__tests__with-id-remote-miss.snap diff --git a/crates/turborepo-vercel-api/src/snapshots/turborepo_vercel_api__tests__without-id-remote-miss.snap b/crates/turborepo-vercel-api/Source/snapshots/turborepo_vercel_api__tests__without-id-remote-miss.snap similarity index 100% rename from crates/turborepo-vercel-api/src/snapshots/turborepo_vercel_api__tests__without-id-remote-miss.snap rename to crates/turborepo-vercel-api/Source/snapshots/turborepo_vercel_api__tests__without-id-remote-miss.snap diff --git a/crates/turborepo-vercel-api/Source/telemetry.rs b/crates/turborepo-vercel-api/Source/telemetry.rs new file mode 100644 index 0000000000000..aa785cd46fa57 --- /dev/null +++ b/crates/turborepo-vercel-api/Source/telemetry.rs @@ -0,0 +1,53 @@ +// telemetry events + +use serde::{Deserialize, Serialize}; + +/// All possible telemetry events must be included in this enum. +/// +/// These events must be added to the backend (telemetry.vercel.com) +/// before they can be tracked - invalid or unknown events will be +/// ignored. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum TelemetryEvent { + Task(TelemetryTaskEvent), + Command(TelemetryCommandEvent), + Repo(TelemetryRepoEvent), + Generic(TelemetryGenericEvent), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TelemetryCommandEvent { + pub id:String, + pub command:String, + pub key:String, + pub value:String, + pub parent_id:Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TelemetryRepoEvent { + pub id:String, + pub repo:String, + pub key:String, + pub value:String, + pub parent_id:Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TelemetryTaskEvent { + pub id:String, + pub package:String, + pub task:String, + pub key:String, + pub value:String, + pub parent_id:Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TelemetryGenericEvent { + pub id:String, + pub key:String, + pub value:String, + pub parent_id:Option, +} diff --git a/crates/turborepo-vercel-api/Source/token.rs b/crates/turborepo-vercel-api/Source/token.rs new file mode 100644 index 0000000000000..8670d24f3294d --- /dev/null +++ b/crates/turborepo-vercel-api/Source/token.rs @@ -0,0 +1,28 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ResponseTokenMetadata { + pub id:String, + pub name:String, + #[serde(rename = "type")] + pub token_type:String, + pub origin:String, + pub scopes:Vec, + #[serde(rename = "activeAt")] + pub active_at:u128, + #[serde(rename = "createdAt")] + pub created_at:u128, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Scope { + #[serde(rename = "type")] + pub scope_type:String, + pub origin:String, + #[serde(rename = "createdAt")] + pub created_at:u128, + #[serde(rename = "expiresAt")] + pub expires_at:Option, + #[serde(rename = "teamId")] + pub team_id:Option, +} diff --git a/crates/turborepo-vercel-api/src/lib.rs b/crates/turborepo-vercel-api/src/lib.rs deleted file mode 100644 index ba151b8d13299..0000000000000 --- a/crates/turborepo-vercel-api/src/lib.rs +++ /dev/null @@ -1,206 +0,0 @@ -//! Types for interacting with the Vercel API. Used for both -//! the client (`turborepo-api-client`) and for the -//! mock server (`turborepo-vercel-api-mock`) -use serde::{Deserialize, Serialize}; -use url::Url; -pub mod telemetry; -pub mod token; - -#[derive(Debug, Clone, Deserialize)] -pub struct VerifiedSsoUser { - pub token: String, - pub team_id: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct VerificationResponse { - pub token: String, - pub team_id: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum CachingStatus { - Disabled, - Enabled, - OverLimit, - Paused, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CachingStatusResponse { - pub status: CachingStatus, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ArtifactResponse { - pub duration: u64, - pub expected_tag: Option, - pub body: Vec, -} - -/// Membership is the relationship between the logged-in user and a particular -/// team -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Membership { - role: Role, -} - -impl Membership { - #[allow(dead_code)] - pub fn new(role: Role) -> Self { - Self { role } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "UPPERCASE")] -pub enum Role { - // ordered by access-level - Owner, - Admin, - Member, - Developer, - Contributor, - Billing, - Viewer, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Team { - pub id: String, - pub slug: String, - pub name: String, - #[serde(rename = "createdAt")] - pub created_at: u64, - pub created: chrono::DateTime, - pub membership: Membership, -} - -impl Team { - pub fn is_owner(&self) -> bool { - matches!(self.membership.role, Role::Owner) - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Space { - pub id: String, - pub name: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TeamsResponse { - pub teams: Vec, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SpacesResponse { - pub spaces: Vec, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SpaceRun { - pub id: String, - pub url: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct User { - pub id: String, - pub username: String, - pub email: String, - pub name: Option, - #[serde(rename = "createdAt")] - pub created_at: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct UserResponse { - pub user: User, -} - -#[derive(Debug)] -pub struct PreflightResponse { - pub location: Url, - pub allow_authorization_header: bool, -} - -#[derive(Deserialize)] -pub struct APIError { - pub code: String, - pub message: String, -} - -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -#[serde(rename_all = "UPPERCASE")] -pub enum CacheSource { - Local, - Remote, -} - -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -#[serde(rename_all = "UPPERCASE")] -pub enum CacheEvent { - Hit, - Miss, -} -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct AnalyticsEvent { - #[serde(skip_serializing_if = "Option::is_none")] - pub session_id: Option, - pub source: CacheSource, - pub event: CacheEvent, - pub hash: String, - pub duration: u64, -} - -impl AnalyticsEvent { - pub fn set_session_id(&mut self, id: String) { - self.session_id = Some(id); - } -} - -#[cfg(test)] -mod tests { - use test_case::test_case; - - use crate::{AnalyticsEvent, CacheEvent, CacheSource}; - - #[test_case( - AnalyticsEvent { - session_id: Some("session-id".to_string()), - source: CacheSource::Local, - event: CacheEvent::Hit, - hash: "this-is-my-hash".to_string(), - duration: 58, - }, - "with-id-local-hit" - )] - #[test_case( - AnalyticsEvent { - session_id: Some("session-id".to_string()), - source: CacheSource::Remote, - event: CacheEvent::Miss, - hash: "this-is-my-hash-2".to_string(), - duration: 21, - }, - "with-id-remote-miss" - )] - #[test_case( - AnalyticsEvent { - session_id: None, - source: CacheSource::Remote, - event: CacheEvent::Miss, - hash: "this-is-my-hash-2".to_string(), - duration: 21, - }, - "without-id-remote-miss" - )] - fn test_serialize_analytics_event(event: AnalyticsEvent, name: &str) { - let json = serde_json::to_string(&event).unwrap(); - insta::assert_json_snapshot!(name, json); - } -} diff --git a/crates/turborepo-vercel-api/src/telemetry.rs b/crates/turborepo-vercel-api/src/telemetry.rs deleted file mode 100644 index 834d69102f1bd..0000000000000 --- a/crates/turborepo-vercel-api/src/telemetry.rs +++ /dev/null @@ -1,53 +0,0 @@ -// telemetry events - -use serde::{Deserialize, Serialize}; - -/// All possible telemetry events must be included in this enum. -/// -/// These events must be added to the backend (telemetry.vercel.com) -/// before they can be tracked - invalid or unknown events will be -/// ignored. -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum TelemetryEvent { - Task(TelemetryTaskEvent), - Command(TelemetryCommandEvent), - Repo(TelemetryRepoEvent), - Generic(TelemetryGenericEvent), -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TelemetryCommandEvent { - pub id: String, - pub command: String, - pub key: String, - pub value: String, - pub parent_id: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TelemetryRepoEvent { - pub id: String, - pub repo: String, - pub key: String, - pub value: String, - pub parent_id: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TelemetryTaskEvent { - pub id: String, - pub package: String, - pub task: String, - pub key: String, - pub value: String, - pub parent_id: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TelemetryGenericEvent { - pub id: String, - pub key: String, - pub value: String, - pub parent_id: Option, -} diff --git a/crates/turborepo-vercel-api/src/token.rs b/crates/turborepo-vercel-api/src/token.rs deleted file mode 100644 index f9872eb2b2e23..0000000000000 --- a/crates/turborepo-vercel-api/src/token.rs +++ /dev/null @@ -1,28 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ResponseTokenMetadata { - pub id: String, - pub name: String, - #[serde(rename = "type")] - pub token_type: String, - pub origin: String, - pub scopes: Vec, - #[serde(rename = "activeAt")] - pub active_at: u128, - #[serde(rename = "createdAt")] - pub created_at: u128, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Scope { - #[serde(rename = "type")] - pub scope_type: String, - pub origin: String, - #[serde(rename = "createdAt")] - pub created_at: u128, - #[serde(rename = "expiresAt")] - pub expires_at: Option, - #[serde(rename = "teamId")] - pub team_id: Option, -} diff --git a/crates/turborepo-vt100/.rustfmt.toml b/crates/turborepo-vt100/.rustfmt.toml deleted file mode 100644 index 55b0b1447ab6b..0000000000000 --- a/crates/turborepo-vt100/.rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -edition = "2018" -max_width = 78 diff --git a/crates/turborepo-vt100/CHANGELOG.md b/crates/turborepo-vt100/CHANGELOG.md deleted file mode 100644 index 4652fa519b1c7..0000000000000 --- a/crates/turborepo-vt100/CHANGELOG.md +++ /dev/null @@ -1,364 +0,0 @@ -# Changelog - -## [Unreleased] - -### Added - -- `Parser::process_cb`, which works the same as `Parser::process` except that - it calls callbacks during parsing when it finds a terminal escape which is - potentially useful but not something that affects the screen itself. -- Support for xterm window resize request escape codes, via the new callback - mechanism. - -### Removed - -- `Screen::bells_diff`, `Screen::audible_bell_count`, - `Screen::visual_bell_count`, and `Screen::errors` have been removed in favor - of the new callback api described above. -- `Cell` no longer implements `Default`. -- `Screen` no longer implements `vte::Perform`. - -### Changed - -- `Parser::set_size` and `Parser::set_scrollback` have been moved to methods - on `Screen`, and `Parser::screen_mut` was added to get a mutable reference - to the screen. - -## [0.15.2] - 2023-02-05 - -### Changed - -- Bumped dependencies - -## [0.15.1] - 2021-12-21 - -### Changed - -- Removed a lot of unnecessary test data from the packaged crate, making - downloads faster - -## [0.15.0] - 2021-12-15 - -### Added - -- `Screen::errors` to track the number of parsing errors seen so far - -### Fixed - -- No longer generate spurious diffs in some cases where the cursor is past the - end of a row -- Fix restoring the cursor position when scrolled back - -### Changed - -- Various internal refactorings - -## [0.14.0] - 2021-12-06 - -### Changed - -- Unknown UTF-8 characters default to a width of 1, rather than 0 (except for - control characters, as mentioned below) - -### Fixed - -- Ignore C1 control characters rather than adding them to the cell data, since - they are non-printable - -## [0.13.2] - 2021-12-05 - -### Changed - -- Delay allocation of the alternate screen until it is used (saves a bit of - memory in basic cases) - -## [0.13.1] - 2021-12-04 - -### Fixed - -- Fixed various line wrapping state issues -- Fixed cursor positioning after writing zero width characters at the end of - the line -- Fixed `Screen::cursor_state_formatted` to draw the last character in a line - with the appropriate drawing attributes if it needs to redraw it - -## [0.13.0] - 2021-11-17 - -### Added - -- `Screen::alternate_screen` to determine if the alternate screen is in use -- `Screen::row_wrapped` to determine whether the row at the given index should - wrap its text -- `Screen::cursor_state_formatted` to set the cursor position and hidden state - (including internal state like the one-past-the-end state which isn't visible - in the return value of `cursor_position`) - -### Fixed - -- `Screen::rows_formatted` now outputs correct escape codes in some edge cases - at the beginning of a row when the previous row was wrapped -- VPA escape sequence can no longer position the cursor off the screen - -## [0.12.0] - 2021-03-09 - -### Added - -- `Screen::state_formatted` and `Screen::state_diff` convenience wrappers - -### Fixed - -- `Screen::attributes_formatted` now correctly resets previously set attributes - where necessary - -### Removed - -- Removed `Screen::attributes_diff`, since I can't actually think of any - situation where it does a thing that makes sense. - -## [0.11.1] - 2021-03-07 - -### Changed - -- Drop dependency on `enumset` - -## [0.11.0] - 2021-03-07 - -### Added - -- `Screen::attributes_formatted` and `Screen::attributes_diff` to retrieve the - current state of the drawing attributes as escape sequences -- `Screen::fgcolor`, `Screen::bgcolor`, `Screen::bold`, `Screen::italic`, - `Screen::underline`, and `Screen::inverse` to retrieve the current state of - the drawing attributes directly - -## [0.10.0] - 2021-03-06 - -### Added - -- Implementation of `std::io::Write` for `Parser` - -## [0.9.0] - 2021-03-05 - -### Added - -- `Screen::contents_between`, for returning the contents logically between two - given cells (for things like clipboard selection) -- Support SGR subparameters (so `\e[38:2:255:0:0m` behaves the same way as - `\e[38;2;255;0;0m`) - -### Fixed - -- Bump `enumset` to fix a dependency which fails to build - -## [0.8.1] - 2020-02-09 - -### Changed - -- Bumped `vte` dep to 0.6. - -## [0.8.0] - 2019-12-07 - -### Removed - -- Removed the unicode-normalization feature altogether - it turns out that it - still has a couple edge cases where it causes incorrect behavior, and fixing - those would be a lot more effort. - -### Fixed - -- Fix a couple more end-of-line/wrapping bugs, especially around cursor - positioning. -- Fix applying combining characters to wide characters. -- Ensure cells can't have contents with width zero (to avoid ambiguity). If an - empty cell gets a combining character applied to it, default that cell to a - (normal-width) space first. - -## [0.7.0] - 2019-11-23 - -### Added - -- New (default-on) cargo feature `unicode-normalization` which can be disabled - to disable normalizing cell contents to NFC - it's a pretty small edge case, - and the data tables required to support it are quite large, which affects - size-sensitive targets like wasm - -## [0.6.3] - 2019-11-20 - -### Fixed - -- Fix output of `contents_formatted` and `contents_diff` when the cursor - position ends at one past the end of a row. -- If the cursor position is one past the end of a row, any char, even a - combining char, needs to cause the cursor position to wrap. - -## [0.6.2] - 2019-11-13 - -### Fixed - -- Fix zero-width characters when the cursor is at the end of a row. - -## [0.6.1] - 2019-11-13 - -### Added - -- Add more debug logging for unhandled escape sequences. - -### Changed - -- Unhandled escape sequence warnings are now at the `debug` log level. - -## [0.6.0] - 2019-11-13 - -### Added - -- `Screen::input_mode_formatted` and `Screen::input_mode_diff` give escape - codes to set the current terminal input modes. -- `Screen::title_formatted` and `Screen::title_diff` give escape codes to set - the terminal window title. -- `Screen::bells_diff` gives escape codes to trigger any audible or visual - bells which have been seen since the previous state. - -### Changed - -- `Screen::contents_diff` no longer includes audible or visual bells (see - `Screen::bells_diff` instead). - -## [0.5.1] - 2019-11-12 - -### Fixed - -- `Screen::set_size` now actually resizes when requested (previously the - underlying storage was not being resized, leading to panics when writing - outside of the original screen). - -## [0.5.0] - 2019-11-12 - -### Added - -- Scrollback support. -- `Default` impl for `Parser` which creates an 80x24 terminal with no - scrollback. - -### Removed - -- `Parser::screen_mut` (and the `pub` `&mut self` methods on `Screen`). The few - things you can do to change the screen state directly are now exposed as - methods on `Parser` itself. - -### Changed - -- `Cell::contents` now returns a `String` instead of a `&str`. -- `Screen::check_audible_bell` and `Screen::check_visual_bell` have been - replaced with `Screen::audible_bell_count` and `Screen::visual_bell_count`. - You should keep track of the "since the last method call" state yourself - instead of having the screen track it for you. - -### Fixed - -- Lots of performance and output optimizations. -- Clearing a cell now sets all of that cell's attributes to the current - attribute set, since different terminals render different things for an empty - cell based on the attributes. -- `Screen::contents_diff` now includes audible and visual bells when - appropriate. - -## [0.4.0] - 2019-11-08 - -### Removed - -- `Screen::fgcolor`, `Screen::bgcolor`, `Screen::bold`, `Screen::italic`, - `Screen::underline`, `Screen::inverse`, and `Screen::alternate_screen`: - these are just implementation details that people shouldn't need to care - about. - -### Fixed - -- Fixed cursor movement when the cursor position is already outside of an - active scroll region. - -## [0.3.2] - 2019-11-08 - -### Fixed - -- Clearing cells now correctly sets the cell background color. -- Fixed a couple bugs in wide character handling in `contents_formatted` and - `contents_diff`. -- Fixed RI when the cursor is at the top of the screen (fixes scrolling up in - `less`, for instance). -- Fixed VPA incorrectly being clamped to the scroll region. -- Stop treating soft hyphen specially (as far as i can tell, no other terminals - do this, and i'm not sure why i thought it was necessary to begin with). -- `contents_formatted` now also resets attributes at the start, like - `contents_diff` does. - -## [0.3.1] - 2019-11-06 - -### Fixed - -- Make `contents_formatted` explicitly show the cursor when necessary, in case - the cursor was previously hidden. - -## [0.3.0] - 2019-11-06 - -### Added - -- `Screen::rows` which is like `Screen::contents` except that it returns the - data by row instead of all at once, and also allows you to restrict the - region returned to a subset of columns. -- `Screen::rows_formatted` which is like `Screen::rows`, but returns escape - sequences sufficient to draw the requested subset of each row. -- `Screen::contents_diff` and `Screen::rows_diff` which return escape sequences - sufficient to turn the visible state of one screen (or a subset of the screen - in the case of `rows_diff`) into another. - -### Changed - -- The screen is now exposed separately from the parser, and is cloneable. -- `contents_formatted` now returns `Vec` instead of `String`. -- `contents` and `contents_formatted` now only allow getting the contents of - the entire screen rather than a subset (but see the entry for `rows` and - `rows_formatted` above). - -### Removed - -- `Cell::new`, since there's not really any reason that this is useful for - someone to do from outside of the crate. - -### Fixed - -- `contents_formatted` now preserves the state of empty cells instead of - filling them with spaces. -- We now clear the row wrapping state when the number of columns in the - terminal is changed. -- `contents_formatted` now ensures that the cursor has the correct hidden state - and location. -- `contents_formatted` now clears the screen before starting to draw. - -## [0.2.0] - 2019-11-04 - -### Changed - -- Reimplemented in pure safe rust, with a much more accurate parser -- A bunch of minor API tweaks, some backwards-incompatible - -## [0.1.2] - 2016-06-04 - -### Fixed - -- Fix returning uninit memory in get_string_formatted/get_string_plaintext -- Handle emoji and zero width unicode characters properly -- Fix cursor positioning with regards to scroll regions and wrapping -- Fix parsing of (ignored) character set escapes -- Explicitly suppress status report escapes - -## [0.1.1] - 2016-04-28 - -### Fixed - -- Fix builds - -## [0.1.0] - 2016-04-28 - -### Added - -- Initial release diff --git a/crates/turborepo-vt100/Cargo.toml b/crates/turborepo-vt100/Cargo.toml index 4699e3c5bb60a..b2f9ff4e3cff3 100644 --- a/crates/turborepo-vt100/Cargo.toml +++ b/crates/turborepo-vt100/Cargo.toml @@ -1,22 +1,3 @@ -[package] -name = "turborepo-vt100" -version = "0.15.2" -authors = ["Jesse Luehrs "] -edition = "2021" - -description = "Library for parsing terminal data" -homepage = "https://github.com/doy/vt100-rust" -repository = "https://github.com/doy/vt100-rust" -readme = "README.md" -keywords = ["terminal", "vt100"] -categories = ["command-line-interface", "encoding"] -license = "MIT" -include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] - -[features] -default = ["tui-term"] -tui-term = ["dep:tui-term", "dep:ratatui"] - [dependencies] itoa = "1.0.9" log = "0.4.19" @@ -32,3 +13,24 @@ serde = { version = "1.0.182", features = ["derive"] } serde_json = "1.0.104" terminal_size = "0.2.6" vte = "0.11.1" + +[features] +default = ["tui-term"] +tui-term = ["dep:tui-term", "dep:ratatui"] + +[lib] +path = "Source/lib.rs" + +[package] +authors = ["Jesse Luehrs "] +categories = ["command-line-interface", "encoding"] +description = "Library for parsing terminal data" +edition = "2021" +homepage = "https://github.com/doy/vt100-rust" +include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] +keywords = ["terminal", "vt100"] +license-file = "LICENSE" +name = "turborepo-vt100" +readme = "README.md" +repository = "https://github.com/doy/vt100-rust" +version = "0.15.2" diff --git a/crates/turborepo-vt100/README.md b/crates/turborepo-vt100/README.md deleted file mode 100644 index cd81a795b185a..0000000000000 --- a/crates/turborepo-vt100/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# turborepo-vt100 - -This is a fork of vt100 modified for use by turborepo. -Most changes made can be upstreamed and hopefully one day we won't need to vendor the crate. - -## Changes - -This fork is based on commit `1e4014aa72a7552d2f69b81ad89d56e035354041` of `vt100`. -A few immediate changes made when vendoring: - -- Dropped fuzz tests as they require special setup -- Dropped scripts for helping with fuzz testing - -## Original README of vt100 - -This crate parses a terminal byte stream and provides an in-memory -representation of the rendered contents. - -### Overview - -This is essentially the terminal parser component of a graphical terminal -emulator pulled out into a separate crate. Although you can use this crate -to build a graphical terminal emulator, it also contains functionality -necessary for implementing terminal applications that want to run other -terminal applications - programs like `screen` or `tmux` for example. - -### Synopsis - -```rust -let mut parser = vt100::Parser::new(24, 80, 0); - -let screen = parser.screen().clone(); -parser.process(b"this text is \x1b[31mRED\x1b[m"); -assert_eq!( - parser.screen().cell(0, 13).unwrap().fgcolor(), - vt100::Color::Idx(1), -); - -let screen = parser.screen().clone(); -parser.process(b"\x1b[3D\x1b[32mGREEN"); -assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jthis text is \x1b[32mGREEN"[..], -); -assert_eq!( - parser.screen().contents_diff(&screen), - &b"\x1b[1;14H\x1b[32mGREEN"[..], -); -``` diff --git a/crates/turborepo-vt100/Source/attrs.rs b/crates/turborepo-vt100/Source/attrs.rs new file mode 100644 index 0000000000000..e58c3293fdb3e --- /dev/null +++ b/crates/turborepo-vt100/Source/attrs.rs @@ -0,0 +1,102 @@ +use crate::term::BufWrite as _; + +/// Represents a foreground or background color for cells. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum Color { + /// The default terminal color. + Default, + + /// An indexed terminal color. + Idx(u8), + + /// An RGB terminal color. The parameters are (red, green, blue). + Rgb(u8, u8, u8), +} + +impl Default for Color { + fn default() -> Self { Self::Default } +} + +const TEXT_MODE_BOLD:u8 = 0b0000_0001; +const TEXT_MODE_ITALIC:u8 = 0b0000_0010; +const TEXT_MODE_UNDERLINE:u8 = 0b0000_0100; +const TEXT_MODE_INVERSE:u8 = 0b0000_1000; + +#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)] +pub struct Attrs { + pub fgcolor:Color, + pub bgcolor:Color, + pub mode:u8, +} + +impl Attrs { + pub fn bold(&self) -> bool { self.mode & TEXT_MODE_BOLD != 0 } + + pub fn set_bold(&mut self, bold:bool) { + if bold { + self.mode |= TEXT_MODE_BOLD; + } else { + self.mode &= !TEXT_MODE_BOLD; + } + } + + pub fn italic(&self) -> bool { self.mode & TEXT_MODE_ITALIC != 0 } + + pub fn set_italic(&mut self, italic:bool) { + if italic { + self.mode |= TEXT_MODE_ITALIC; + } else { + self.mode &= !TEXT_MODE_ITALIC; + } + } + + pub fn underline(&self) -> bool { self.mode & TEXT_MODE_UNDERLINE != 0 } + + pub fn set_underline(&mut self, underline:bool) { + if underline { + self.mode |= TEXT_MODE_UNDERLINE; + } else { + self.mode &= !TEXT_MODE_UNDERLINE; + } + } + + pub fn inverse(&self) -> bool { self.mode & TEXT_MODE_INVERSE != 0 } + + pub fn set_inverse(&mut self, inverse:bool) { + if inverse { + self.mode |= TEXT_MODE_INVERSE; + } else { + self.mode &= !TEXT_MODE_INVERSE; + } + } + + pub fn write_escape_code_diff(&self, contents:&mut Vec, other:&Self) { + if self != other && self == &Self::default() { + crate::term::ClearAttrs.write_buf(contents); + return; + } + + let attrs = crate::term::Attrs::default(); + + let attrs = if self.fgcolor == other.fgcolor { attrs } else { attrs.fgcolor(self.fgcolor) }; + let attrs = if self.bgcolor == other.bgcolor { attrs } else { attrs.bgcolor(self.bgcolor) }; + let attrs = if self.bold() == other.bold() { attrs } else { attrs.bold(self.bold()) }; + let attrs = if self.italic() == other.italic() { + attrs + } else { + attrs.italic(self.italic()) + }; + let attrs = if self.underline() == other.underline() { + attrs + } else { + attrs.underline(self.underline()) + }; + let attrs = if self.inverse() == other.inverse() { + attrs + } else { + attrs.inverse(self.inverse()) + }; + + attrs.write_buf(contents); + } +} diff --git a/crates/turborepo-vt100/Source/callbacks.rs b/crates/turborepo-vt100/Source/callbacks.rs new file mode 100644 index 0000000000000..7fdb08da82164 --- /dev/null +++ b/crates/turborepo-vt100/Source/callbacks.rs @@ -0,0 +1,16 @@ +/// This trait is used with `Parser::process_cb` to handle extra escape +/// sequences that don't have an impact on the terminal screen directly. +pub trait Callbacks { + /// This callback is called when the terminal requests an audible bell + /// (typically with `^G`). + fn audible_bell(&mut self, _:&mut crate::Screen) {} + /// This callback is called when the terminal requests an visual bell + /// (typically with `\eg`). + fn visual_bell(&mut self, _:&mut crate::Screen) {} + /// This callback is called when the terminal requests a resize + /// (typically with `\e[8;;t`). + fn resize(&mut self, _:&mut crate::Screen, _request:(u16, u16)) {} + /// This callback is called when the terminal receives invalid input + /// (such as an invalid UTF-8 character or an unused control character). + fn error(&mut self, _:&mut crate::Screen) {} +} diff --git a/crates/turborepo-vt100/src/cell.rs b/crates/turborepo-vt100/Source/cell.rs similarity index 100% rename from crates/turborepo-vt100/src/cell.rs rename to crates/turborepo-vt100/Source/cell.rs diff --git a/crates/turborepo-vt100/Source/entire_screen.rs b/crates/turborepo-vt100/Source/entire_screen.rs new file mode 100644 index 0000000000000..5c8a71829747b --- /dev/null +++ b/crates/turborepo-vt100/Source/entire_screen.rs @@ -0,0 +1,67 @@ +use std::io::Write; + +use crate::term::BufWrite; + +pub struct EntireScreen<'a> { + screen:&'a crate::Screen, + size:(usize, u16), +} + +impl<'a> EntireScreen<'a> { + #[must_use] + pub fn new(screen:&'a crate::Screen) -> Self { + Self { size:screen.grid().size_with_contents(), screen } + } + + #[must_use] + pub fn cell(&self, row:u16, col:u16) -> Option<&crate::Cell> { + self.screen.grid().all_row(row).and_then(|r| r.get(col)) + } + + #[must_use] + pub fn contents(&self) -> String { + let mut s = String::new(); + self.screen.grid().write_full_contents(&mut s); + s + } + + /// Returns the formatted contents of the terminal by row, + /// restricted to the given subset of columns. + /// + /// Formatting information will be included inline as terminal escape + /// codes. The result will be suitable for feeding directly to a raw + /// terminal parser, and will result in the same visual output. + /// + /// You are responsible for positioning the cursor before printing each + /// row, and the final cursor position after displaying each row is + /// unspecified. + // the unwraps in this method shouldn't be reachable + #[allow(clippy::missing_panics_doc)] + pub fn rows_formatted(&self, start:u16, width:u16) -> impl Iterator> + '_ { + let mut wrapping = false; + let grid = self.screen.grid(); + let (rows, _) = self.size(); + let default = crate::attrs::Attrs::default(); + grid.all_rows().take(rows).enumerate().map(move |(i, row)| { + // number of rows in a grid is stored in a u16 (see Size), so + // visible_rows can never return enough rows to overflow here + let i = i.try_into().unwrap(); + let mut contents = vec![]; + // We don't need final cursor position as long as CRLF is used and not just LF + let (_pos, attrs) = + row.write_contents_formatted(&mut contents, start, width, i, wrapping, None, None); + if start == 0 && width == grid.size().cols { + wrapping = row.wrapped(); + } + // If the row ended in non-default attributes, then clear them + if attrs != default { + crate::term::ClearAttrs.write_buf(&mut contents); + } + contents + }) + } + + /// Size required to render all contents + #[must_use] + pub fn size(&self) -> (usize, u16) { self.size } +} diff --git a/crates/turborepo-vt100/src/grid.rs b/crates/turborepo-vt100/Source/grid.rs similarity index 100% rename from crates/turborepo-vt100/src/grid.rs rename to crates/turborepo-vt100/Source/grid.rs diff --git a/crates/turborepo-vt100/Source/lib.rs b/crates/turborepo-vt100/Source/lib.rs new file mode 100644 index 0000000000000..bd17f2e0f2aab --- /dev/null +++ b/crates/turborepo-vt100/Source/lib.rs @@ -0,0 +1,61 @@ +//! This crate parses a terminal byte stream and provides an in-memory +//! representation of the rendered contents. +//! +//! # Overview +//! +//! This is essentially the terminal parser component of a graphical terminal +//! emulator pulled out into a separate crate. Although you can use this crate +//! to build a graphical terminal emulator, it also contains functionality +//! necessary for implementing terminal applications that want to run other +//! terminal applications - programs like `screen` or `tmux` for example. +//! +//! # Synopsis +//! +//! ``` +//! let mut parser = turborepo_vt100::Parser::new(24, 80, 0); +//! +//! let screen = parser.screen().clone(); +//! parser.process(b"this text is \x1b[31mRED\x1b[m"); +//! assert_eq!(parser.screen().cell(0, 13).unwrap().fgcolor(), turborepo_vt100::Color::Idx(1),); +//! +//! let screen = parser.screen().clone(); +//! parser.process(b"\x1b[3D\x1b[32mGREEN"); +//! assert_eq!( +//! parser.screen().contents_formatted(), +//! &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jthis text is \x1b[32mGREEN"[..], +//! ); +//! assert_eq!(parser.screen().contents_diff(&screen), &b"\x1b[1;14H\x1b[32mGREEN"[..],); +//! ``` + +#![warn(clippy::pedantic)] +#![warn(clippy::nursery)] +#![warn(clippy::as_conversions)] +#![warn(clippy::get_unwrap)] +#![allow(clippy::cognitive_complexity)] +#![allow(clippy::missing_const_for_fn)] +#![allow(clippy::similar_names)] +#![allow(clippy::struct_excessive_bools)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::type_complexity)] +#![allow(unused_imports)] + +mod attrs; +mod callbacks; +mod cell; +mod entire_screen; +mod grid; +mod parser; +mod perform; +mod row; +mod screen; +mod term; +#[cfg(feature = "tui-term")] +mod tui_term; + +pub use attrs::Color; +pub use callbacks::Callbacks; +pub use cell::Cell; +pub use entire_screen::EntireScreen; +pub use parser::Parser; +pub use screen::{MouseProtocolEncoding, MouseProtocolMode, Screen}; diff --git a/crates/turborepo-vt100/Source/parser.rs b/crates/turborepo-vt100/Source/parser.rs new file mode 100644 index 0000000000000..31a98357cfb45 --- /dev/null +++ b/crates/turborepo-vt100/Source/parser.rs @@ -0,0 +1,69 @@ +/// A parser for terminal output which produces an in-memory representation of +/// the terminal contents. +pub struct Parser { + parser:vte::Parser, + screen:crate::perform::WrappedScreen, +} + +impl Parser { + /// Creates a new terminal parser of the given size and with the given + /// amount of scrollback. + #[must_use] + pub fn new(rows:u16, cols:u16, scrollback_len:usize) -> Self { + Self { + parser:vte::Parser::new(), + screen:crate::perform::WrappedScreen(crate::Screen::new( + crate::grid::Size { rows, cols }, + scrollback_len, + )), + } + } + + /// Processes the contents of the given byte string, and updates the + /// in-memory terminal state. + pub fn process(&mut self, bytes:&[u8]) { + for byte in bytes { + self.parser.advance(&mut self.screen, *byte); + } + } + + /// Processes the contents of the given byte string, and updates the + /// in-memory terminal state. Calls methods on the given `Callbacks` + /// object when relevant escape sequences are seen. + pub fn process_cb(&mut self, bytes:&[u8], callbacks:&mut impl crate::callbacks::Callbacks) { + let mut screen = + crate::perform::WrappedScreenWithCallbacks::new(&mut self.screen, callbacks); + for byte in bytes { + self.parser.advance(&mut screen, *byte); + } + } + + /// Returns a reference to a `Screen` object containing the terminal + /// state. + #[must_use] + pub fn screen(&self) -> &crate::Screen { &self.screen.0 } + + /// Returns a mutable reference to a `Screen` object containing the + /// terminal state. + #[must_use] + pub fn screen_mut(&mut self) -> &mut crate::Screen { &mut self.screen.0 } + + /// Returns a reference to an `EntireScreen` object containing the + /// terminal state where all contents including scrollback and displayed. + #[must_use] + pub fn entire_screen(&self) -> crate::EntireScreen { crate::EntireScreen::new(self.screen()) } +} + +impl Default for Parser { + /// Returns a parser with dimensions 80x24 and no scrollback. + fn default() -> Self { Self::new(24, 80, 0) } +} + +impl std::io::Write for Parser { + fn write(&mut self, buf:&[u8]) -> std::io::Result { + self.process(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { Ok(()) } +} diff --git a/crates/turborepo-vt100/src/perform.rs b/crates/turborepo-vt100/Source/perform.rs similarity index 100% rename from crates/turborepo-vt100/src/perform.rs rename to crates/turborepo-vt100/Source/perform.rs diff --git a/crates/turborepo-vt100/src/row.rs b/crates/turborepo-vt100/Source/row.rs similarity index 100% rename from crates/turborepo-vt100/src/row.rs rename to crates/turborepo-vt100/Source/row.rs diff --git a/crates/turborepo-vt100/src/screen.rs b/crates/turborepo-vt100/Source/screen.rs similarity index 100% rename from crates/turborepo-vt100/src/screen.rs rename to crates/turborepo-vt100/Source/screen.rs diff --git a/crates/turborepo-vt100/src/term.rs b/crates/turborepo-vt100/Source/term.rs similarity index 100% rename from crates/turborepo-vt100/src/term.rs rename to crates/turborepo-vt100/Source/term.rs diff --git a/crates/turborepo-vt100/src/tui_term.rs b/crates/turborepo-vt100/Source/tui_term.rs similarity index 100% rename from crates/turborepo-vt100/src/tui_term.rs rename to crates/turborepo-vt100/Source/tui_term.rs diff --git a/crates/turborepo-vt100/src/attrs.rs b/crates/turborepo-vt100/src/attrs.rs deleted file mode 100644 index e5ee3fbac20e9..0000000000000 --- a/crates/turborepo-vt100/src/attrs.rs +++ /dev/null @@ -1,128 +0,0 @@ -use crate::term::BufWrite as _; - -/// Represents a foreground or background color for cells. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum Color { - /// The default terminal color. - Default, - - /// An indexed terminal color. - Idx(u8), - - /// An RGB terminal color. The parameters are (red, green, blue). - Rgb(u8, u8, u8), -} - -impl Default for Color { - fn default() -> Self { - Self::Default - } -} - -const TEXT_MODE_BOLD: u8 = 0b0000_0001; -const TEXT_MODE_ITALIC: u8 = 0b0000_0010; -const TEXT_MODE_UNDERLINE: u8 = 0b0000_0100; -const TEXT_MODE_INVERSE: u8 = 0b0000_1000; - -#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)] -pub struct Attrs { - pub fgcolor: Color, - pub bgcolor: Color, - pub mode: u8, -} - -impl Attrs { - pub fn bold(&self) -> bool { - self.mode & TEXT_MODE_BOLD != 0 - } - - pub fn set_bold(&mut self, bold: bool) { - if bold { - self.mode |= TEXT_MODE_BOLD; - } else { - self.mode &= !TEXT_MODE_BOLD; - } - } - - pub fn italic(&self) -> bool { - self.mode & TEXT_MODE_ITALIC != 0 - } - - pub fn set_italic(&mut self, italic: bool) { - if italic { - self.mode |= TEXT_MODE_ITALIC; - } else { - self.mode &= !TEXT_MODE_ITALIC; - } - } - - pub fn underline(&self) -> bool { - self.mode & TEXT_MODE_UNDERLINE != 0 - } - - pub fn set_underline(&mut self, underline: bool) { - if underline { - self.mode |= TEXT_MODE_UNDERLINE; - } else { - self.mode &= !TEXT_MODE_UNDERLINE; - } - } - - pub fn inverse(&self) -> bool { - self.mode & TEXT_MODE_INVERSE != 0 - } - - pub fn set_inverse(&mut self, inverse: bool) { - if inverse { - self.mode |= TEXT_MODE_INVERSE; - } else { - self.mode &= !TEXT_MODE_INVERSE; - } - } - - pub fn write_escape_code_diff( - &self, - contents: &mut Vec, - other: &Self, - ) { - if self != other && self == &Self::default() { - crate::term::ClearAttrs.write_buf(contents); - return; - } - - let attrs = crate::term::Attrs::default(); - - let attrs = if self.fgcolor == other.fgcolor { - attrs - } else { - attrs.fgcolor(self.fgcolor) - }; - let attrs = if self.bgcolor == other.bgcolor { - attrs - } else { - attrs.bgcolor(self.bgcolor) - }; - let attrs = if self.bold() == other.bold() { - attrs - } else { - attrs.bold(self.bold()) - }; - let attrs = if self.italic() == other.italic() { - attrs - } else { - attrs.italic(self.italic()) - }; - let attrs = if self.underline() == other.underline() { - attrs - } else { - attrs.underline(self.underline()) - }; - let attrs = if self.inverse() == other.inverse() { - attrs - } else { - attrs.inverse(self.inverse()) - }; - - attrs.write_buf(contents); - } -} diff --git a/crates/turborepo-vt100/src/callbacks.rs b/crates/turborepo-vt100/src/callbacks.rs deleted file mode 100644 index 6262906337723..0000000000000 --- a/crates/turborepo-vt100/src/callbacks.rs +++ /dev/null @@ -1,16 +0,0 @@ -/// This trait is used with `Parser::process_cb` to handle extra escape -/// sequences that don't have an impact on the terminal screen directly. -pub trait Callbacks { - /// This callback is called when the terminal requests an audible bell - /// (typically with `^G`). - fn audible_bell(&mut self, _: &mut crate::Screen) {} - /// This callback is called when the terminal requests an visual bell - /// (typically with `\eg`). - fn visual_bell(&mut self, _: &mut crate::Screen) {} - /// This callback is called when the terminal requests a resize - /// (typically with `\e[8;;t`). - fn resize(&mut self, _: &mut crate::Screen, _request: (u16, u16)) {} - /// This callback is called when the terminal receives invalid input - /// (such as an invalid UTF-8 character or an unused control character). - fn error(&mut self, _: &mut crate::Screen) {} -} diff --git a/crates/turborepo-vt100/src/entire_screen.rs b/crates/turborepo-vt100/src/entire_screen.rs deleted file mode 100644 index 1938cf04170a9..0000000000000 --- a/crates/turborepo-vt100/src/entire_screen.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::term::BufWrite; -use std::io::Write; - -pub struct EntireScreen<'a> { - screen: &'a crate::Screen, - size: (usize, u16), -} - -impl<'a> EntireScreen<'a> { - #[must_use] - pub fn new(screen: &'a crate::Screen) -> Self { - Self { - size: screen.grid().size_with_contents(), - screen, - } - } - - #[must_use] - pub fn cell(&self, row: u16, col: u16) -> Option<&crate::Cell> { - self.screen.grid().all_row(row).and_then(|r| r.get(col)) - } - - #[must_use] - pub fn contents(&self) -> String { - let mut s = String::new(); - self.screen.grid().write_full_contents(&mut s); - s - } - - /// Returns the formatted contents of the terminal by row, - /// restricted to the given subset of columns. - /// - /// Formatting information will be included inline as terminal escape - /// codes. The result will be suitable for feeding directly to a raw - /// terminal parser, and will result in the same visual output. - /// - /// You are responsible for positioning the cursor before printing each - /// row, and the final cursor position after displaying each row is - /// unspecified. - // the unwraps in this method shouldn't be reachable - #[allow(clippy::missing_panics_doc)] - pub fn rows_formatted( - &self, - start: u16, - width: u16, - ) -> impl Iterator> + '_ { - let mut wrapping = false; - let grid = self.screen.grid(); - let (rows, _) = self.size(); - let default = crate::attrs::Attrs::default(); - grid.all_rows().take(rows).enumerate().map(move |(i, row)| { - // number of rows in a grid is stored in a u16 (see Size), so - // visible_rows can never return enough rows to overflow here - let i = i.try_into().unwrap(); - let mut contents = vec![]; - // We don't need final cursor position as long as CRLF is used and not just LF - let (_pos, attrs) = row.write_contents_formatted( - &mut contents, - start, - width, - i, - wrapping, - None, - None, - ); - if start == 0 && width == grid.size().cols { - wrapping = row.wrapped(); - } - // If the row ended in non-default attributes, then clear them - if attrs != default { - crate::term::ClearAttrs.write_buf(&mut contents); - } - contents - }) - } - - /// Size required to render all contents - #[must_use] - pub fn size(&self) -> (usize, u16) { - self.size - } -} diff --git a/crates/turborepo-vt100/src/lib.rs b/crates/turborepo-vt100/src/lib.rs deleted file mode 100644 index ea24ef28e59ec..0000000000000 --- a/crates/turborepo-vt100/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! This crate parses a terminal byte stream and provides an in-memory -//! representation of the rendered contents. -//! -//! # Overview -//! -//! This is essentially the terminal parser component of a graphical terminal -//! emulator pulled out into a separate crate. Although you can use this crate -//! to build a graphical terminal emulator, it also contains functionality -//! necessary for implementing terminal applications that want to run other -//! terminal applications - programs like `screen` or `tmux` for example. -//! -//! # Synopsis -//! -//! ``` -//! let mut parser = turborepo_vt100::Parser::new(24, 80, 0); -//! -//! let screen = parser.screen().clone(); -//! parser.process(b"this text is \x1b[31mRED\x1b[m"); -//! assert_eq!( -//! parser.screen().cell(0, 13).unwrap().fgcolor(), -//! turborepo_vt100::Color::Idx(1), -//! ); -//! -//! let screen = parser.screen().clone(); -//! parser.process(b"\x1b[3D\x1b[32mGREEN"); -//! assert_eq!( -//! parser.screen().contents_formatted(), -//! &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jthis text is \x1b[32mGREEN"[..], -//! ); -//! assert_eq!( -//! parser.screen().contents_diff(&screen), -//! &b"\x1b[1;14H\x1b[32mGREEN"[..], -//! ); -//! ``` - -#![warn(clippy::pedantic)] -#![warn(clippy::nursery)] -#![warn(clippy::as_conversions)] -#![warn(clippy::get_unwrap)] -#![allow(clippy::cognitive_complexity)] -#![allow(clippy::missing_const_for_fn)] -#![allow(clippy::similar_names)] -#![allow(clippy::struct_excessive_bools)] -#![allow(clippy::too_many_arguments)] -#![allow(clippy::too_many_lines)] -#![allow(clippy::type_complexity)] -#![allow(unused_imports)] - -mod attrs; -mod callbacks; -mod cell; -mod entire_screen; -mod grid; -mod parser; -mod perform; -mod row; -mod screen; -mod term; -#[cfg(feature = "tui-term")] -mod tui_term; - -pub use attrs::Color; -pub use callbacks::Callbacks; -pub use cell::Cell; -pub use entire_screen::EntireScreen; -pub use parser::Parser; -pub use screen::{MouseProtocolEncoding, MouseProtocolMode, Screen}; diff --git a/crates/turborepo-vt100/src/parser.rs b/crates/turborepo-vt100/src/parser.rs deleted file mode 100644 index 3a6706d572b00..0000000000000 --- a/crates/turborepo-vt100/src/parser.rs +++ /dev/null @@ -1,85 +0,0 @@ -/// A parser for terminal output which produces an in-memory representation of -/// the terminal contents. -pub struct Parser { - parser: vte::Parser, - screen: crate::perform::WrappedScreen, -} - -impl Parser { - /// Creates a new terminal parser of the given size and with the given - /// amount of scrollback. - #[must_use] - pub fn new(rows: u16, cols: u16, scrollback_len: usize) -> Self { - Self { - parser: vte::Parser::new(), - screen: crate::perform::WrappedScreen(crate::Screen::new( - crate::grid::Size { rows, cols }, - scrollback_len, - )), - } - } - - /// Processes the contents of the given byte string, and updates the - /// in-memory terminal state. - pub fn process(&mut self, bytes: &[u8]) { - for byte in bytes { - self.parser.advance(&mut self.screen, *byte); - } - } - - /// Processes the contents of the given byte string, and updates the - /// in-memory terminal state. Calls methods on the given `Callbacks` - /// object when relevant escape sequences are seen. - pub fn process_cb( - &mut self, - bytes: &[u8], - callbacks: &mut impl crate::callbacks::Callbacks, - ) { - let mut screen = crate::perform::WrappedScreenWithCallbacks::new( - &mut self.screen, - callbacks, - ); - for byte in bytes { - self.parser.advance(&mut screen, *byte); - } - } - - /// Returns a reference to a `Screen` object containing the terminal - /// state. - #[must_use] - pub fn screen(&self) -> &crate::Screen { - &self.screen.0 - } - - /// Returns a mutable reference to a `Screen` object containing the - /// terminal state. - #[must_use] - pub fn screen_mut(&mut self) -> &mut crate::Screen { - &mut self.screen.0 - } - - /// Returns a reference to an `EntireScreen` object containing the - /// terminal state where all contents including scrollback and displayed. - #[must_use] - pub fn entire_screen(&self) -> crate::EntireScreen { - crate::EntireScreen::new(self.screen()) - } -} - -impl Default for Parser { - /// Returns a parser with dimensions 80x24 and no scrollback. - fn default() -> Self { - Self::new(24, 80, 0) - } -} - -impl std::io::Write for Parser { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.process(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} diff --git a/crates/turborepo-vt100/tests/attr.rs b/crates/turborepo-vt100/tests/attr.rs deleted file mode 100644 index 0a1bf5fa3937d..0000000000000 --- a/crates/turborepo-vt100/tests/attr.rs +++ /dev/null @@ -1,23 +0,0 @@ -mod helpers; - -#[test] -fn colors() { - helpers::fixture("colors"); -} - -#[test] -fn attrs() { - helpers::fixture("attrs"); -} - -#[test] -fn attributes_formatted() { - let mut parser = turborepo_vt100::Parser::default(); - assert_eq!(parser.screen().attributes_formatted(), b"\x1b[m"); - parser.process(b"\x1b[32mfoo\x1b[41mbar\x1b[33mbaz"); - assert_eq!(parser.screen().attributes_formatted(), b"\x1b[m\x1b[33;41m"); - parser.process(b"\x1b[1m\x1b[39m"); - assert_eq!(parser.screen().attributes_formatted(), b"\x1b[m\x1b[41;1m"); - parser.process(b"\x1b[m"); - assert_eq!(parser.screen().attributes_formatted(), b"\x1b[m"); -} diff --git a/crates/turborepo-vt100/tests/basic.rs b/crates/turborepo-vt100/tests/basic.rs deleted file mode 100644 index b949a0471dcc7..0000000000000 --- a/crates/turborepo-vt100/tests/basic.rs +++ /dev/null @@ -1,120 +0,0 @@ -use turborepo_vt100 as vt100; - -#[test] -fn object_creation() { - let parser = vt100::Parser::default(); - assert_eq!(parser.screen().size(), (24, 80)); -} - -#[test] -fn process_text() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - parser.process(input); - assert_eq!(parser.screen().contents(), "foobar"); -} - -#[test] -fn set_size() { - let mut parser = vt100::Parser::default(); - assert_eq!(parser.screen().size(), (24, 80)); - assert_eq!(parser.screen().cursor_position(), (0, 0)); - - parser.screen_mut().set_size(34, 8); - assert_eq!(parser.screen().size(), (34, 8)); - assert_eq!(parser.screen().cursor_position(), (0, 0)); - - parser.process(b"\x1b[30;5H"); - assert_eq!(parser.screen().cursor_position(), (29, 4)); - - parser.screen_mut().set_size(24, 80); - assert_eq!(parser.screen().size(), (24, 80)); - assert_eq!(parser.screen().cursor_position(), (23, 4)); - - parser.screen_mut().set_size(34, 8); - assert_eq!(parser.screen().size(), (34, 8)); - assert_eq!(parser.screen().cursor_position(), (23, 4)); - - parser.process(b"\x1b[?1049h"); - assert_eq!(parser.screen().size(), (34, 8)); - assert_eq!(parser.screen().cursor_position(), (0, 0)); - - parser.screen_mut().set_size(24, 80); - assert_eq!(parser.screen().size(), (24, 80)); - assert_eq!(parser.screen().cursor_position(), (0, 0)); - - parser.process(b"\x1b[?1049l"); - assert_eq!(parser.screen().size(), (24, 80)); - assert_eq!(parser.screen().cursor_position(), (23, 4)); - - parser.screen_mut().set_size(34, 8); - parser.process(b"\x1bc01234567890123456789"); - assert_eq!(parser.screen().contents(), "01234567890123456789"); - - parser.screen_mut().set_size(24, 80); - assert_eq!(parser.screen().contents(), "01234567\n89012345\n6789"); - - parser.screen_mut().set_size(34, 8); - assert_eq!(parser.screen().contents(), "01234567\n89012345\n6789"); - - let mut parser = vt100::Parser::default(); - assert_eq!(parser.screen().size(), (24, 80)); - parser.screen_mut().set_size(30, 100); - assert_eq!(parser.screen().size(), (30, 100)); - parser.process(b"\x1b[75Cfoobar"); - assert_eq!(parser.screen().contents(), " foobar"); - - let mut parser = vt100::Parser::default(); - assert_eq!(parser.screen().size(), (24, 80)); - parser.screen_mut().set_size(30, 100); - assert_eq!(parser.screen().size(), (30, 100)); - parser.process(b"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\x1b[24;99Hfoobar"); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24 foobar"); -} - -#[test] -fn cell_contents() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - parser.process(input); - assert_eq!(parser.screen().cell(0, 0).unwrap().contents(), "f"); - assert_eq!(parser.screen().cell(0, 1).unwrap().contents(), "o"); - assert_eq!(parser.screen().cell(0, 2).unwrap().contents(), "o"); - assert_eq!(parser.screen().cell(0, 3).unwrap().contents(), "b"); - assert_eq!(parser.screen().cell(0, 4).unwrap().contents(), "a"); - assert_eq!(parser.screen().cell(0, 5).unwrap().contents(), "r"); - assert_eq!(parser.screen().cell(0, 6).unwrap().contents(), ""); -} - -#[test] -fn cell_colors() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - parser.process(input); - - assert_eq!( - parser.screen().cell(0, 0).unwrap().fgcolor(), - vt100::Color::Default - ); - assert_eq!( - parser.screen().cell(0, 3).unwrap().fgcolor(), - vt100::Color::Idx(2) - ); - assert_eq!( - parser.screen().cell(0, 4).unwrap().fgcolor(), - vt100::Color::Idx(2) - ); - assert_eq!( - parser.screen().cell(0, 4).unwrap().bgcolor(), - vt100::Color::Idx(2) - ); -} - -#[test] -fn cell_attrs() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - parser.process(input); - - assert!(parser.screen().cell(0, 4).unwrap().italic()); -} diff --git a/crates/turborepo-vt100/tests/control.rs b/crates/turborepo-vt100/tests/control.rs deleted file mode 100644 index 5ecc5a85cdc96..0000000000000 --- a/crates/turborepo-vt100/tests/control.rs +++ /dev/null @@ -1,75 +0,0 @@ -mod helpers; - -use turborepo_vt100 as vt100; - -#[test] -fn bel() { - struct State { - bel: usize, - } - - impl vt100::Callbacks for State { - fn audible_bell(&mut self, _: &mut vt100::Screen) { - self.bel += 1; - } - } - - let mut parser = vt100::Parser::default(); - let mut state = State { bel: 0 }; - assert_eq!(state.bel, 0); - - let screen = parser.screen().clone(); - parser.process_cb(b"\x07", &mut state); - assert_eq!(state.bel, 1); - assert_eq!(parser.screen().contents_diff(&screen), b""); - - let screen = parser.screen().clone(); - parser.process_cb(b"\x07", &mut state); - assert_eq!(state.bel, 2); - assert_eq!(parser.screen().contents_diff(&screen), b""); - - let screen = parser.screen().clone(); - parser.process_cb(b"\x07\x07\x07", &mut state); - assert_eq!(state.bel, 5); - assert_eq!(parser.screen().contents_diff(&screen), b""); - - let screen = parser.screen().clone(); - parser.process_cb(b"foo", &mut state); - assert_eq!(state.bel, 5); - assert_eq!(parser.screen().contents_diff(&screen), b"foo"); - - let screen = parser.screen().clone(); - parser.process_cb(b"ba\x07r", &mut state); - assert_eq!(state.bel, 6); - assert_eq!(parser.screen().contents_diff(&screen), b"bar"); -} - -#[test] -fn bs() { - helpers::fixture("bs"); -} - -#[test] -fn tab() { - helpers::fixture("tab"); -} - -#[test] -fn lf() { - helpers::fixture("lf"); -} - -#[test] -fn vt() { - helpers::fixture("vt"); -} - -#[test] -fn ff() { - helpers::fixture("ff"); -} - -#[test] -fn cr() { - helpers::fixture("cr"); -} diff --git a/crates/turborepo-vt100/tests/csi.rs b/crates/turborepo-vt100/tests/csi.rs deleted file mode 100644 index 8dd922ad50a00..0000000000000 --- a/crates/turborepo-vt100/tests/csi.rs +++ /dev/null @@ -1,88 +0,0 @@ -use turborepo_vt100 as vt100; - -mod helpers; - -#[test] -fn absolute_movement() { - helpers::fixture("absolute_movement"); -} - -#[test] -fn row_clamp() { - let mut vt = vt100::Parser::default(); - assert_eq!(vt.screen().cursor_position(), (0, 0)); - vt.process(b"\x1b[15d"); - assert_eq!(vt.screen().cursor_position(), (14, 0)); - vt.process(b"\x1b[150d"); - assert_eq!(vt.screen().cursor_position(), (23, 0)); -} - -#[test] -fn relative_movement() { - helpers::fixture("relative_movement"); -} - -#[test] -fn ed() { - helpers::fixture("ed"); -} - -#[test] -fn el() { - helpers::fixture("el"); -} - -#[test] -fn ich_dch_ech() { - helpers::fixture("ich_dch_ech"); -} - -#[test] -fn il_dl() { - helpers::fixture("il_dl"); -} - -#[test] -fn scroll() { - helpers::fixture("scroll"); -} - -#[test] -fn xtwinops() { - struct Callbacks; - impl vt100::Callbacks for Callbacks { - fn resize( - &mut self, - screen: &mut vt100::Screen, - (rows, cols): (u16, u16), - ) { - screen.set_size(rows, cols); - } - } - - let mut vt = vt100::Parser::default(); - assert_eq!(vt.screen().size(), (24, 80)); - vt.process_cb(b"\x1b[8;24;80t", &mut Callbacks); - assert_eq!(vt.screen().size(), (24, 80)); - vt.process_cb(b"\x1b[8t", &mut Callbacks); - assert_eq!(vt.screen().size(), (24, 80)); - vt.process_cb(b"\x1b[8;80;24t", &mut Callbacks); - assert_eq!(vt.screen().size(), (80, 24)); - vt.process_cb(b"\x1b[8;24t", &mut Callbacks); - assert_eq!(vt.screen().size(), (24, 24)); - - let mut vt = vt100::Parser::default(); - assert_eq!(vt.screen().size(), (24, 80)); - vt.process_cb(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", &mut Callbacks); - assert_eq!(vt.screen().rows(0, 80).next().unwrap(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - assert_eq!(vt.screen().rows(0, 80).nth(1).unwrap(), "aaaaaaaaaa"); - vt.process_cb( - b"\x1b[H\x1b[8;24;15tbbbbbbbbbbbbbbbbbbbb\x1b[8;24;80tcccccccccccccccccccc", - &mut Callbacks, - ); - assert_eq!(vt.screen().rows(0, 80).next().unwrap(), "bbbbbbbbbbbbbbb"); - assert_eq!( - vt.screen().rows(0, 80).nth(1).unwrap(), - "bbbbbcccccccccccccccccccc" - ); -} diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement.in b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement.in deleted file mode 100644 index ddfb4bee2c50c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement.in +++ /dev/null @@ -1,11 +0,0 @@ -\x1b[10;10H -\x1b[d -\x1b[15d -\x1b[150d -\x1b[H -\x1b[8H -\x1b[15G -\x1b[G -\x1b[0;0H -\x1b[1;1H -\x1b[500;500H diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/1.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/1.json deleted file mode 100644 index d42156dd23f6c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/1.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 9, - 9 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/1.typescript deleted file mode 100644 index ea814ea068281..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/1.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/10.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/10.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/10.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/10.typescript deleted file mode 100644 index 155097b5855de..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/10.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/11.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/11.json deleted file mode 100644 index d8db62cf2b1c2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/11.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 23, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/11.typescript deleted file mode 100644 index 0bb223ca03437..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/11.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/2.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/2.json deleted file mode 100644 index 326f75358a0be..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 9 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/2.typescript deleted file mode 100644 index e2f22ee7d10fc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/3.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/3.json deleted file mode 100644 index 01de7113acdd0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 14, - 9 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/3.typescript deleted file mode 100644 index ee332ed71c522..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/4.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/4.json deleted file mode 100644 index 41f875666ad1f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 23, - 9 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/4.typescript deleted file mode 100644 index c53442163628a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/5.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/5.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/5.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/5.typescript deleted file mode 100644 index 79743fd323cea..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/5.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/6.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/6.json deleted file mode 100644 index 69777cc554789..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/6.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 7, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/6.typescript deleted file mode 100644 index 45f0cd0856cca..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/7.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/7.json deleted file mode 100644 index cb39b6efde33d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/7.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 7, - 14 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/7.typescript deleted file mode 100644 index 03227f7d48f34..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/7.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/8.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/8.json deleted file mode 100644 index 69777cc554789..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/8.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 7, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/8.typescript deleted file mode 100644 index 257c040239e26..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/8.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/9.json b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/9.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/9.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/9.typescript deleted file mode 100644 index 314a127d0ffd4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/absolute_movement/9.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer.in b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer.in deleted file mode 100644 index 9f12ea47e5854..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer.in +++ /dev/null @@ -1,14 +0,0 @@ -\x1bc -\x1b[m\x1b[2J\x1b[H1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24 -\x1b[?47h -foobar -\x1b[?47l -\x1b[?47h -\x1b[?47l -\x1bc -\x1b[m\x1b[2J\x1b[H1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24 -\x1b[?1049h -foobar -\x1b[?1049l -\x1b[?1049h -\x1b[?1049l diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/1.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/1.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/1.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/1.typescript deleted file mode 100644 index c10be5482cd97..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/1.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/10.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/10.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/10.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/10.typescript deleted file mode 100644 index 0e5fd6296871c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/10.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1049h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/11.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/11.json deleted file mode 100644 index a2b6f4a77c92e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/11.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "foobar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b" - }, - "0,4": { - "contents": "a" - }, - "0,5": { - "contents": "r" - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/11.typescript deleted file mode 100644 index f6ea049518760..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/11.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/12.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/12.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/12.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/12.typescript deleted file mode 100644 index 0c90305a92e0b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/12.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1049l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/13.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/13.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/13.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/13.typescript deleted file mode 100644 index 0e5fd6296871c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/13.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1049h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/14.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/14.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/14.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/14.typescript deleted file mode 100644 index 0c90305a92e0b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/14.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1049l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/2.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/2.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/2.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/2.typescript deleted file mode 100644 index a1817811d27cb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/2.typescript +++ /dev/null @@ -1,24 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/3.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/3.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/3.typescript deleted file mode 100644 index 14ea16cbbee3e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/3.typescript +++ /dev/null @@ -1 +0,0 @@ -[?47h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/4.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/4.json deleted file mode 100644 index a2b6f4a77c92e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/4.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "foobar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b" - }, - "0,4": { - "contents": "a" - }, - "0,5": { - "contents": "r" - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/4.typescript deleted file mode 100644 index f6ea049518760..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/4.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/5.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/5.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/5.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/5.typescript deleted file mode 100644 index e628dda3e1de6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/5.typescript +++ /dev/null @@ -1 +0,0 @@ -[?47l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/6.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/6.json deleted file mode 100644 index a2b6f4a77c92e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/6.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "foobar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b" - }, - "0,4": { - "contents": "a" - }, - "0,5": { - "contents": "r" - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/6.typescript deleted file mode 100644 index 14ea16cbbee3e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/6.typescript +++ /dev/null @@ -1 +0,0 @@ -[?47h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/7.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/7.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/7.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/7.typescript deleted file mode 100644 index e628dda3e1de6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/7.typescript +++ /dev/null @@ -1 +0,0 @@ -[?47l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/8.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/8.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/8.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/8.typescript deleted file mode 100644 index c10be5482cd97..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/8.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/9.json b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/9.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/9.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/9.typescript deleted file mode 100644 index a1817811d27cb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/alternate_buffer/9.typescript +++ /dev/null @@ -1,24 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ascii.in b/crates/turborepo-vt100/tests/data/fixtures/ascii.in deleted file mode 100644 index 257cc5642cb1a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ascii.in +++ /dev/null @@ -1 +0,0 @@ -foo diff --git a/crates/turborepo-vt100/tests/data/fixtures/ascii/1.json b/crates/turborepo-vt100/tests/data/fixtures/ascii/1.json deleted file mode 100644 index 629899c6b9b56..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ascii/1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ascii/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/ascii/1.typescript deleted file mode 100644 index 19102815663d2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ascii/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs.in b/crates/turborepo-vt100/tests/data/fixtures/attrs.in deleted file mode 100644 index 47dce4764bb68..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs.in +++ /dev/null @@ -1,13 +0,0 @@ -f\x1b[1mo\x1b[3mo\x1b[4mo\x1b[7mo -\x1b[m -\x1b[2J\x1b[H -\x1b[1;4mf -\x1b[22mo\x1b[24mo -\x1b[1;3;4;7mo -\x1bcfoo -\x1b[1;2H\x1b[4;7mo\x1b[m -\x1b[1;1H\x1b[4;7m\x1b[X\x1b[m -\x1bc\x1b[1;79H\x1b[31mab -\x1bc\x1b[1;80H\x1b[41ma\n -\x1bc\x1b[1;80Hab\x1b[41m -c diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/1.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/1.json deleted file mode 100644 index daa6bb7b4bf8b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/1.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "contents": "foooo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o", - "bold": true - }, - "0,2": { - "contents": "o", - "bold": true, - "italic": true - }, - "0,3": { - "contents": "o", - "bold": true, - "italic": true, - "underline": true - }, - "0,4": { - "contents": "o", - "bold": true, - "italic": true, - "underline": true, - "inverse": true - } - }, - "cursor_position": [ - 0, - 5 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/1.typescript deleted file mode 100644 index 60f18f4c8176e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foooo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/10.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/10.json deleted file mode 100644 index b6cb478b4a479..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/10.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "contents": " ab", - "cells": { - "0,78": { - "contents": "a", - "fgcolor": "1" - }, - "0,79": { - "contents": "b", - "fgcolor": "1" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/10.typescript deleted file mode 100644 index ba2cb07d67c73..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/10.typescript +++ /dev/null @@ -1 +0,0 @@ -cab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/11.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/11.json deleted file mode 100644 index 915ae63362585..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/11.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,79": { - "contents": "a", - "bgcolor": "1" - } - }, - "cursor_position": [ - 1, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/11.typescript deleted file mode 100644 index 20008d65bf644..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/11.typescript +++ /dev/null @@ -1 +0,0 @@ -ca diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/12.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/12.json deleted file mode 100644 index a28d5bc200bfe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/12.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": " ab", - "cells": { - "0,79": { - "contents": "a" - }, - "1,0": { - "contents": "b" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/12.typescript deleted file mode 100644 index ce899fb8fbb6c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/12.typescript +++ /dev/null @@ -1 +0,0 @@ -cab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/13.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/13.json deleted file mode 100644 index ccb120da4caf4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/13.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "contents": " abc", - "cells": { - "0,79": { - "contents": "a" - }, - "1,0": { - "contents": "b" - }, - "1,1": { - "contents": "c", - "bgcolor": "1" - } - }, - "cursor_position": [ - 1, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/13.typescript deleted file mode 100644 index 3410062ba67c5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/13.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/2.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/2.json deleted file mode 100644 index daa6bb7b4bf8b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/2.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "contents": "foooo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o", - "bold": true - }, - "0,2": { - "contents": "o", - "bold": true, - "italic": true - }, - "0,3": { - "contents": "o", - "bold": true, - "italic": true, - "underline": true - }, - "0,4": { - "contents": "o", - "bold": true, - "italic": true, - "underline": true, - "inverse": true - } - }, - "cursor_position": [ - 0, - 5 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/2.typescript deleted file mode 100644 index 327aa11ac13af..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/3.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/3.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/3.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/4.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/4.json deleted file mode 100644 index 32ffae9064775..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/4.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "contents": "f", - "cells": { - "0,0": { - "contents": "f", - "bold": true, - "underline": true - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/4.typescript deleted file mode 100644 index 411646aaab4fd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/4.typescript +++ /dev/null @@ -1 +0,0 @@ -f \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/5.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/5.json deleted file mode 100644 index 0d604e0e06069..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/5.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f", - "bold": true, - "underline": true - }, - "0,1": { - "contents": "o", - "underline": true - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/5.typescript deleted file mode 100644 index 150db627d9a4a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/5.typescript +++ /dev/null @@ -1 +0,0 @@ -oo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/6.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/6.json deleted file mode 100644 index b9bb1368db284..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/6.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "contents": "fooo", - "cells": { - "0,0": { - "contents": "f", - "bold": true, - "underline": true - }, - "0,1": { - "contents": "o", - "underline": true - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "o", - "bold": true, - "italic": true, - "underline": true, - "inverse": true - } - }, - "cursor_position": [ - 0, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/6.typescript deleted file mode 100644 index d0c54d83822cf..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/6.typescript +++ /dev/null @@ -1 +0,0 @@ -o \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/7.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/7.json deleted file mode 100644 index 629899c6b9b56..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/7.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/7.typescript deleted file mode 100644 index cab9aaf840118..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/7.typescript +++ /dev/null @@ -1 +0,0 @@ -cfoo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/8.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/8.json deleted file mode 100644 index de236bad0441c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/8.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o", - "underline": true, - "inverse": true - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/8.typescript deleted file mode 100644 index 58adffdf89ddf..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/8.typescript +++ /dev/null @@ -1 +0,0 @@ -o \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/9.json b/crates/turborepo-vt100/tests/data/fixtures/attrs/9.json deleted file mode 100644 index fb9f7c5d7c15e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/9.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "contents": " oo", - "cells": { - "0,0": { - "contents": "", - "underline": true, - "inverse": true - }, - "0,1": { - "contents": "o", - "underline": true, - "inverse": true - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/attrs/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/attrs/9.typescript deleted file mode 100644 index de1f143403abc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/attrs/9.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/bs.in b/crates/turborepo-vt100/tests/data/fixtures/bs.in deleted file mode 100644 index 84974be874257..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/bs.in +++ /dev/null @@ -1,2 +0,0 @@ -foo\x08\x08aa -\r\nquux\x08\x08\x08\x08\x08\x08bar diff --git a/crates/turborepo-vt100/tests/data/fixtures/bs/1.json b/crates/turborepo-vt100/tests/data/fixtures/bs/1.json deleted file mode 100644 index 25ab48752f83a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/bs/1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "faa", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "a" - }, - "0,2": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/bs/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/bs/1.typescript deleted file mode 100644 index c84ba2c7641f5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/bs/1.typescript +++ /dev/null @@ -1 +0,0 @@ -fooaa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/bs/2.json b/crates/turborepo-vt100/tests/data/fixtures/bs/2.json deleted file mode 100644 index 37cc1d2c35f2a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/bs/2.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "faa\nbarx", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "a" - }, - "0,2": { - "contents": "a" - }, - "1,0": { - "contents": "b" - }, - "1,1": { - "contents": "a" - }, - "1,2": { - "contents": "r" - }, - "1,3": { - "contents": "x" - } - }, - "cursor_position": [ - 1, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/bs/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/bs/2.typescript deleted file mode 100644 index e23b077c19dc6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/bs/2.typescript +++ /dev/null @@ -1,2 +0,0 @@ - -quuxbar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors.in b/crates/turborepo-vt100/tests/data/fixtures/colors.in deleted file mode 100644 index 59da023d0a250..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors.in +++ /dev/null @@ -1,22 +0,0 @@ -foo\x1b[31mbar -\x1b[2D\x1b[45mab -\x1b[m -\x1b[15;15Hfoo\x1b[31mbar\x1b[m -\x1b[2D\x1b[45mab -\x1b[m\x1b[2J\x1b[H -a\x1b[38;5;123mb\x1b[48;5;158mc -\x1b[38;2;50;75;100md\x1b[48;2;125;150;175me -\x1b[m\x1b[2J\x1b[H -\x1b[32;47mfoo -\x1b[2J\x1b[H -\x1b[39mfoo -\x1b[2J\x1b[H -\x1b[49mfoo -\x1b[m\x1b[2J\x1b[H -\x1b[92;107mfoo -\x1bcfoo -\x1b[1;2H\x1b[41mo\x1b[m -\x1b[1;1H\x1b[41m\x1b[X\x1b[m -\x1b[m\x1b[2J\x1b[H -a\x1b[38:5:123mb\x1b[48:5:158mc -\x1b[38:2:50:75:100md\x1b[48:2:125:150:175me diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/1.json b/crates/turborepo-vt100/tests/data/fixtures/colors/1.json deleted file mode 100644 index a5928a7604111..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/1.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "foobar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b", - "fgcolor": "1" - }, - "0,4": { - "contents": "a", - "fgcolor": "1" - }, - "0,5": { - "contents": "r", - "fgcolor": "1" - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/1.typescript deleted file mode 100644 index c5b499555206c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/10.json b/crates/turborepo-vt100/tests/data/fixtures/colors/10.json deleted file mode 100644 index 09bd34c5475f9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/10.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,1": { - "contents": "o", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,2": { - "contents": "o", - "fgcolor": "2", - "bgcolor": "7" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/10.typescript deleted file mode 100644 index 33d399838bb4a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/10.typescript +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/11.json b/crates/turborepo-vt100/tests/data/fixtures/colors/11.json deleted file mode 100644 index dadb8c8ca6ff2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/11.json +++ /dev/null @@ -1,9609 +0,0 @@ -{ - "contents": "", - "cells": { - "0,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/11.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/11.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/12.json b/crates/turborepo-vt100/tests/data/fixtures/colors/12.json deleted file mode 100644 index 591b3b73a49c0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/12.json +++ /dev/null @@ -1,9606 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f", - "bgcolor": "7" - }, - "0,1": { - "contents": "o", - "bgcolor": "7" - }, - "0,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,2": { - "contents": "o", - "bgcolor": "7" - }, - "0,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "0,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "1,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "10,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "11,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "12,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "13,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "14,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "15,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "16,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "17,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "18,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "19,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "2,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "20,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "21,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "22,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "23,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "3,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "4,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "5,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "6,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "7,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "8,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,0": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,1": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,10": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,11": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,12": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,13": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,14": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,15": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,16": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,17": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,18": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,19": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,2": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,20": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,21": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,22": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,23": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,24": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,25": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,26": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,27": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,28": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,29": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,3": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,30": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,31": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,32": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,33": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,34": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,35": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,36": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,37": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,38": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,39": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,4": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,40": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,41": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,42": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,43": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,44": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,45": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,46": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,47": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,48": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,49": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,5": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,50": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,51": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,52": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,53": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,54": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,55": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,56": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,57": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,58": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,59": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,6": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,60": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,61": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,62": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,63": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,64": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,65": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,66": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,67": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,68": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,69": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,7": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,70": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,71": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,72": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,73": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,74": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,75": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,76": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,77": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,78": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,79": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,8": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - }, - "9,9": { - "contents": "", - "fgcolor": "2", - "bgcolor": "7" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/12.typescript deleted file mode 100644 index a415a0b5024a3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/12.typescript +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/13.json b/crates/turborepo-vt100/tests/data/fixtures/colors/13.json deleted file mode 100644 index 1544de0b2a946..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/13.json +++ /dev/null @@ -1,7689 +0,0 @@ -{ - "contents": "", - "cells": { - "0,0": { - "contents": "", - "bgcolor": "7" - }, - "0,1": { - "contents": "", - "bgcolor": "7" - }, - "0,10": { - "contents": "", - "bgcolor": "7" - }, - "0,11": { - "contents": "", - "bgcolor": "7" - }, - "0,12": { - "contents": "", - "bgcolor": "7" - }, - "0,13": { - "contents": "", - "bgcolor": "7" - }, - "0,14": { - "contents": "", - "bgcolor": "7" - }, - "0,15": { - "contents": "", - "bgcolor": "7" - }, - "0,16": { - "contents": "", - "bgcolor": "7" - }, - "0,17": { - "contents": "", - "bgcolor": "7" - }, - "0,18": { - "contents": "", - "bgcolor": "7" - }, - "0,19": { - "contents": "", - "bgcolor": "7" - }, - "0,2": { - "contents": "", - "bgcolor": "7" - }, - "0,20": { - "contents": "", - "bgcolor": "7" - }, - "0,21": { - "contents": "", - "bgcolor": "7" - }, - "0,22": { - "contents": "", - "bgcolor": "7" - }, - "0,23": { - "contents": "", - "bgcolor": "7" - }, - "0,24": { - "contents": "", - "bgcolor": "7" - }, - "0,25": { - "contents": "", - "bgcolor": "7" - }, - "0,26": { - "contents": "", - "bgcolor": "7" - }, - "0,27": { - "contents": "", - "bgcolor": "7" - }, - "0,28": { - "contents": "", - "bgcolor": "7" - }, - "0,29": { - "contents": "", - "bgcolor": "7" - }, - "0,3": { - "contents": "", - "bgcolor": "7" - }, - "0,30": { - "contents": "", - "bgcolor": "7" - }, - "0,31": { - "contents": "", - "bgcolor": "7" - }, - "0,32": { - "contents": "", - "bgcolor": "7" - }, - "0,33": { - "contents": "", - "bgcolor": "7" - }, - "0,34": { - "contents": "", - "bgcolor": "7" - }, - "0,35": { - "contents": "", - "bgcolor": "7" - }, - "0,36": { - "contents": "", - "bgcolor": "7" - }, - "0,37": { - "contents": "", - "bgcolor": "7" - }, - "0,38": { - "contents": "", - "bgcolor": "7" - }, - "0,39": { - "contents": "", - "bgcolor": "7" - }, - "0,4": { - "contents": "", - "bgcolor": "7" - }, - "0,40": { - "contents": "", - "bgcolor": "7" - }, - "0,41": { - "contents": "", - "bgcolor": "7" - }, - "0,42": { - "contents": "", - "bgcolor": "7" - }, - "0,43": { - "contents": "", - "bgcolor": "7" - }, - "0,44": { - "contents": "", - "bgcolor": "7" - }, - "0,45": { - "contents": "", - "bgcolor": "7" - }, - "0,46": { - "contents": "", - "bgcolor": "7" - }, - "0,47": { - "contents": "", - "bgcolor": "7" - }, - "0,48": { - "contents": "", - "bgcolor": "7" - }, - "0,49": { - "contents": "", - "bgcolor": "7" - }, - "0,5": { - "contents": "", - "bgcolor": "7" - }, - "0,50": { - "contents": "", - "bgcolor": "7" - }, - "0,51": { - "contents": "", - "bgcolor": "7" - }, - "0,52": { - "contents": "", - "bgcolor": "7" - }, - "0,53": { - "contents": "", - "bgcolor": "7" - }, - "0,54": { - "contents": "", - "bgcolor": "7" - }, - "0,55": { - "contents": "", - "bgcolor": "7" - }, - "0,56": { - "contents": "", - "bgcolor": "7" - }, - "0,57": { - "contents": "", - "bgcolor": "7" - }, - "0,58": { - "contents": "", - "bgcolor": "7" - }, - "0,59": { - "contents": "", - "bgcolor": "7" - }, - "0,6": { - "contents": "", - "bgcolor": "7" - }, - "0,60": { - "contents": "", - "bgcolor": "7" - }, - "0,61": { - "contents": "", - "bgcolor": "7" - }, - "0,62": { - "contents": "", - "bgcolor": "7" - }, - "0,63": { - "contents": "", - "bgcolor": "7" - }, - "0,64": { - "contents": "", - "bgcolor": "7" - }, - "0,65": { - "contents": "", - "bgcolor": "7" - }, - "0,66": { - "contents": "", - "bgcolor": "7" - }, - "0,67": { - "contents": "", - "bgcolor": "7" - }, - "0,68": { - "contents": "", - "bgcolor": "7" - }, - "0,69": { - "contents": "", - "bgcolor": "7" - }, - "0,7": { - "contents": "", - "bgcolor": "7" - }, - "0,70": { - "contents": "", - "bgcolor": "7" - }, - "0,71": { - "contents": "", - "bgcolor": "7" - }, - "0,72": { - "contents": "", - "bgcolor": "7" - }, - "0,73": { - "contents": "", - "bgcolor": "7" - }, - "0,74": { - "contents": "", - "bgcolor": "7" - }, - "0,75": { - "contents": "", - "bgcolor": "7" - }, - "0,76": { - "contents": "", - "bgcolor": "7" - }, - "0,77": { - "contents": "", - "bgcolor": "7" - }, - "0,78": { - "contents": "", - "bgcolor": "7" - }, - "0,79": { - "contents": "", - "bgcolor": "7" - }, - "0,8": { - "contents": "", - "bgcolor": "7" - }, - "0,9": { - "contents": "", - "bgcolor": "7" - }, - "1,0": { - "contents": "", - "bgcolor": "7" - }, - "1,1": { - "contents": "", - "bgcolor": "7" - }, - "1,10": { - "contents": "", - "bgcolor": "7" - }, - "1,11": { - "contents": "", - "bgcolor": "7" - }, - "1,12": { - "contents": "", - "bgcolor": "7" - }, - "1,13": { - "contents": "", - "bgcolor": "7" - }, - "1,14": { - "contents": "", - "bgcolor": "7" - }, - "1,15": { - "contents": "", - "bgcolor": "7" - }, - "1,16": { - "contents": "", - "bgcolor": "7" - }, - "1,17": { - "contents": "", - "bgcolor": "7" - }, - "1,18": { - "contents": "", - "bgcolor": "7" - }, - "1,19": { - "contents": "", - "bgcolor": "7" - }, - "1,2": { - "contents": "", - "bgcolor": "7" - }, - "1,20": { - "contents": "", - "bgcolor": "7" - }, - "1,21": { - "contents": "", - "bgcolor": "7" - }, - "1,22": { - "contents": "", - "bgcolor": "7" - }, - "1,23": { - "contents": "", - "bgcolor": "7" - }, - "1,24": { - "contents": "", - "bgcolor": "7" - }, - "1,25": { - "contents": "", - "bgcolor": "7" - }, - "1,26": { - "contents": "", - "bgcolor": "7" - }, - "1,27": { - "contents": "", - "bgcolor": "7" - }, - "1,28": { - "contents": "", - "bgcolor": "7" - }, - "1,29": { - "contents": "", - "bgcolor": "7" - }, - "1,3": { - "contents": "", - "bgcolor": "7" - }, - "1,30": { - "contents": "", - "bgcolor": "7" - }, - "1,31": { - "contents": "", - "bgcolor": "7" - }, - "1,32": { - "contents": "", - "bgcolor": "7" - }, - "1,33": { - "contents": "", - "bgcolor": "7" - }, - "1,34": { - "contents": "", - "bgcolor": "7" - }, - "1,35": { - "contents": "", - "bgcolor": "7" - }, - "1,36": { - "contents": "", - "bgcolor": "7" - }, - "1,37": { - "contents": "", - "bgcolor": "7" - }, - "1,38": { - "contents": "", - "bgcolor": "7" - }, - "1,39": { - "contents": "", - "bgcolor": "7" - }, - "1,4": { - "contents": "", - "bgcolor": "7" - }, - "1,40": { - "contents": "", - "bgcolor": "7" - }, - "1,41": { - "contents": "", - "bgcolor": "7" - }, - "1,42": { - "contents": "", - "bgcolor": "7" - }, - "1,43": { - "contents": "", - "bgcolor": "7" - }, - "1,44": { - "contents": "", - "bgcolor": "7" - }, - "1,45": { - "contents": "", - "bgcolor": "7" - }, - "1,46": { - "contents": "", - "bgcolor": "7" - }, - "1,47": { - "contents": "", - "bgcolor": "7" - }, - "1,48": { - "contents": "", - "bgcolor": "7" - }, - "1,49": { - "contents": "", - "bgcolor": "7" - }, - "1,5": { - "contents": "", - "bgcolor": "7" - }, - "1,50": { - "contents": "", - "bgcolor": "7" - }, - "1,51": { - "contents": "", - "bgcolor": "7" - }, - "1,52": { - "contents": "", - "bgcolor": "7" - }, - "1,53": { - "contents": "", - "bgcolor": "7" - }, - "1,54": { - "contents": "", - "bgcolor": "7" - }, - "1,55": { - "contents": "", - "bgcolor": "7" - }, - "1,56": { - "contents": "", - "bgcolor": "7" - }, - "1,57": { - "contents": "", - "bgcolor": "7" - }, - "1,58": { - "contents": "", - "bgcolor": "7" - }, - "1,59": { - "contents": "", - "bgcolor": "7" - }, - "1,6": { - "contents": "", - "bgcolor": "7" - }, - "1,60": { - "contents": "", - "bgcolor": "7" - }, - "1,61": { - "contents": "", - "bgcolor": "7" - }, - "1,62": { - "contents": "", - "bgcolor": "7" - }, - "1,63": { - "contents": "", - "bgcolor": "7" - }, - "1,64": { - "contents": "", - "bgcolor": "7" - }, - "1,65": { - "contents": "", - "bgcolor": "7" - }, - "1,66": { - "contents": "", - "bgcolor": "7" - }, - "1,67": { - "contents": "", - "bgcolor": "7" - }, - "1,68": { - "contents": "", - "bgcolor": "7" - }, - "1,69": { - "contents": "", - "bgcolor": "7" - }, - "1,7": { - "contents": "", - "bgcolor": "7" - }, - "1,70": { - "contents": "", - "bgcolor": "7" - }, - "1,71": { - "contents": "", - "bgcolor": "7" - }, - "1,72": { - "contents": "", - "bgcolor": "7" - }, - "1,73": { - "contents": "", - "bgcolor": "7" - }, - "1,74": { - "contents": "", - "bgcolor": "7" - }, - "1,75": { - "contents": "", - "bgcolor": "7" - }, - "1,76": { - "contents": "", - "bgcolor": "7" - }, - "1,77": { - "contents": "", - "bgcolor": "7" - }, - "1,78": { - "contents": "", - "bgcolor": "7" - }, - "1,79": { - "contents": "", - "bgcolor": "7" - }, - "1,8": { - "contents": "", - "bgcolor": "7" - }, - "1,9": { - "contents": "", - "bgcolor": "7" - }, - "10,0": { - "contents": "", - "bgcolor": "7" - }, - "10,1": { - "contents": "", - "bgcolor": "7" - }, - "10,10": { - "contents": "", - "bgcolor": "7" - }, - "10,11": { - "contents": "", - "bgcolor": "7" - }, - "10,12": { - "contents": "", - "bgcolor": "7" - }, - "10,13": { - "contents": "", - "bgcolor": "7" - }, - "10,14": { - "contents": "", - "bgcolor": "7" - }, - "10,15": { - "contents": "", - "bgcolor": "7" - }, - "10,16": { - "contents": "", - "bgcolor": "7" - }, - "10,17": { - "contents": "", - "bgcolor": "7" - }, - "10,18": { - "contents": "", - "bgcolor": "7" - }, - "10,19": { - "contents": "", - "bgcolor": "7" - }, - "10,2": { - "contents": "", - "bgcolor": "7" - }, - "10,20": { - "contents": "", - "bgcolor": "7" - }, - "10,21": { - "contents": "", - "bgcolor": "7" - }, - "10,22": { - "contents": "", - "bgcolor": "7" - }, - "10,23": { - "contents": "", - "bgcolor": "7" - }, - "10,24": { - "contents": "", - "bgcolor": "7" - }, - "10,25": { - "contents": "", - "bgcolor": "7" - }, - "10,26": { - "contents": "", - "bgcolor": "7" - }, - "10,27": { - "contents": "", - "bgcolor": "7" - }, - "10,28": { - "contents": "", - "bgcolor": "7" - }, - "10,29": { - "contents": "", - "bgcolor": "7" - }, - "10,3": { - "contents": "", - "bgcolor": "7" - }, - "10,30": { - "contents": "", - "bgcolor": "7" - }, - "10,31": { - "contents": "", - "bgcolor": "7" - }, - "10,32": { - "contents": "", - "bgcolor": "7" - }, - "10,33": { - "contents": "", - "bgcolor": "7" - }, - "10,34": { - "contents": "", - "bgcolor": "7" - }, - "10,35": { - "contents": "", - "bgcolor": "7" - }, - "10,36": { - "contents": "", - "bgcolor": "7" - }, - "10,37": { - "contents": "", - "bgcolor": "7" - }, - "10,38": { - "contents": "", - "bgcolor": "7" - }, - "10,39": { - "contents": "", - "bgcolor": "7" - }, - "10,4": { - "contents": "", - "bgcolor": "7" - }, - "10,40": { - "contents": "", - "bgcolor": "7" - }, - "10,41": { - "contents": "", - "bgcolor": "7" - }, - "10,42": { - "contents": "", - "bgcolor": "7" - }, - "10,43": { - "contents": "", - "bgcolor": "7" - }, - "10,44": { - "contents": "", - "bgcolor": "7" - }, - "10,45": { - "contents": "", - "bgcolor": "7" - }, - "10,46": { - "contents": "", - "bgcolor": "7" - }, - "10,47": { - "contents": "", - "bgcolor": "7" - }, - "10,48": { - "contents": "", - "bgcolor": "7" - }, - "10,49": { - "contents": "", - "bgcolor": "7" - }, - "10,5": { - "contents": "", - "bgcolor": "7" - }, - "10,50": { - "contents": "", - "bgcolor": "7" - }, - "10,51": { - "contents": "", - "bgcolor": "7" - }, - "10,52": { - "contents": "", - "bgcolor": "7" - }, - "10,53": { - "contents": "", - "bgcolor": "7" - }, - "10,54": { - "contents": "", - "bgcolor": "7" - }, - "10,55": { - "contents": "", - "bgcolor": "7" - }, - "10,56": { - "contents": "", - "bgcolor": "7" - }, - "10,57": { - "contents": "", - "bgcolor": "7" - }, - "10,58": { - "contents": "", - "bgcolor": "7" - }, - "10,59": { - "contents": "", - "bgcolor": "7" - }, - "10,6": { - "contents": "", - "bgcolor": "7" - }, - "10,60": { - "contents": "", - "bgcolor": "7" - }, - "10,61": { - "contents": "", - "bgcolor": "7" - }, - "10,62": { - "contents": "", - "bgcolor": "7" - }, - "10,63": { - "contents": "", - "bgcolor": "7" - }, - "10,64": { - "contents": "", - "bgcolor": "7" - }, - "10,65": { - "contents": "", - "bgcolor": "7" - }, - "10,66": { - "contents": "", - "bgcolor": "7" - }, - "10,67": { - "contents": "", - "bgcolor": "7" - }, - "10,68": { - "contents": "", - "bgcolor": "7" - }, - "10,69": { - "contents": "", - "bgcolor": "7" - }, - "10,7": { - "contents": "", - "bgcolor": "7" - }, - "10,70": { - "contents": "", - "bgcolor": "7" - }, - "10,71": { - "contents": "", - "bgcolor": "7" - }, - "10,72": { - "contents": "", - "bgcolor": "7" - }, - "10,73": { - "contents": "", - "bgcolor": "7" - }, - "10,74": { - "contents": "", - "bgcolor": "7" - }, - "10,75": { - "contents": "", - "bgcolor": "7" - }, - "10,76": { - "contents": "", - "bgcolor": "7" - }, - "10,77": { - "contents": "", - "bgcolor": "7" - }, - "10,78": { - "contents": "", - "bgcolor": "7" - }, - "10,79": { - "contents": "", - "bgcolor": "7" - }, - "10,8": { - "contents": "", - "bgcolor": "7" - }, - "10,9": { - "contents": "", - "bgcolor": "7" - }, - "11,0": { - "contents": "", - "bgcolor": "7" - }, - "11,1": { - "contents": "", - "bgcolor": "7" - }, - "11,10": { - "contents": "", - "bgcolor": "7" - }, - "11,11": { - "contents": "", - "bgcolor": "7" - }, - "11,12": { - "contents": "", - "bgcolor": "7" - }, - "11,13": { - "contents": "", - "bgcolor": "7" - }, - "11,14": { - "contents": "", - "bgcolor": "7" - }, - "11,15": { - "contents": "", - "bgcolor": "7" - }, - "11,16": { - "contents": "", - "bgcolor": "7" - }, - "11,17": { - "contents": "", - "bgcolor": "7" - }, - "11,18": { - "contents": "", - "bgcolor": "7" - }, - "11,19": { - "contents": "", - "bgcolor": "7" - }, - "11,2": { - "contents": "", - "bgcolor": "7" - }, - "11,20": { - "contents": "", - "bgcolor": "7" - }, - "11,21": { - "contents": "", - "bgcolor": "7" - }, - "11,22": { - "contents": "", - "bgcolor": "7" - }, - "11,23": { - "contents": "", - "bgcolor": "7" - }, - "11,24": { - "contents": "", - "bgcolor": "7" - }, - "11,25": { - "contents": "", - "bgcolor": "7" - }, - "11,26": { - "contents": "", - "bgcolor": "7" - }, - "11,27": { - "contents": "", - "bgcolor": "7" - }, - "11,28": { - "contents": "", - "bgcolor": "7" - }, - "11,29": { - "contents": "", - "bgcolor": "7" - }, - "11,3": { - "contents": "", - "bgcolor": "7" - }, - "11,30": { - "contents": "", - "bgcolor": "7" - }, - "11,31": { - "contents": "", - "bgcolor": "7" - }, - "11,32": { - "contents": "", - "bgcolor": "7" - }, - "11,33": { - "contents": "", - "bgcolor": "7" - }, - "11,34": { - "contents": "", - "bgcolor": "7" - }, - "11,35": { - "contents": "", - "bgcolor": "7" - }, - "11,36": { - "contents": "", - "bgcolor": "7" - }, - "11,37": { - "contents": "", - "bgcolor": "7" - }, - "11,38": { - "contents": "", - "bgcolor": "7" - }, - "11,39": { - "contents": "", - "bgcolor": "7" - }, - "11,4": { - "contents": "", - "bgcolor": "7" - }, - "11,40": { - "contents": "", - "bgcolor": "7" - }, - "11,41": { - "contents": "", - "bgcolor": "7" - }, - "11,42": { - "contents": "", - "bgcolor": "7" - }, - "11,43": { - "contents": "", - "bgcolor": "7" - }, - "11,44": { - "contents": "", - "bgcolor": "7" - }, - "11,45": { - "contents": "", - "bgcolor": "7" - }, - "11,46": { - "contents": "", - "bgcolor": "7" - }, - "11,47": { - "contents": "", - "bgcolor": "7" - }, - "11,48": { - "contents": "", - "bgcolor": "7" - }, - "11,49": { - "contents": "", - "bgcolor": "7" - }, - "11,5": { - "contents": "", - "bgcolor": "7" - }, - "11,50": { - "contents": "", - "bgcolor": "7" - }, - "11,51": { - "contents": "", - "bgcolor": "7" - }, - "11,52": { - "contents": "", - "bgcolor": "7" - }, - "11,53": { - "contents": "", - "bgcolor": "7" - }, - "11,54": { - "contents": "", - "bgcolor": "7" - }, - "11,55": { - "contents": "", - "bgcolor": "7" - }, - "11,56": { - "contents": "", - "bgcolor": "7" - }, - "11,57": { - "contents": "", - "bgcolor": "7" - }, - "11,58": { - "contents": "", - "bgcolor": "7" - }, - "11,59": { - "contents": "", - "bgcolor": "7" - }, - "11,6": { - "contents": "", - "bgcolor": "7" - }, - "11,60": { - "contents": "", - "bgcolor": "7" - }, - "11,61": { - "contents": "", - "bgcolor": "7" - }, - "11,62": { - "contents": "", - "bgcolor": "7" - }, - "11,63": { - "contents": "", - "bgcolor": "7" - }, - "11,64": { - "contents": "", - "bgcolor": "7" - }, - "11,65": { - "contents": "", - "bgcolor": "7" - }, - "11,66": { - "contents": "", - "bgcolor": "7" - }, - "11,67": { - "contents": "", - "bgcolor": "7" - }, - "11,68": { - "contents": "", - "bgcolor": "7" - }, - "11,69": { - "contents": "", - "bgcolor": "7" - }, - "11,7": { - "contents": "", - "bgcolor": "7" - }, - "11,70": { - "contents": "", - "bgcolor": "7" - }, - "11,71": { - "contents": "", - "bgcolor": "7" - }, - "11,72": { - "contents": "", - "bgcolor": "7" - }, - "11,73": { - "contents": "", - "bgcolor": "7" - }, - "11,74": { - "contents": "", - "bgcolor": "7" - }, - "11,75": { - "contents": "", - "bgcolor": "7" - }, - "11,76": { - "contents": "", - "bgcolor": "7" - }, - "11,77": { - "contents": "", - "bgcolor": "7" - }, - "11,78": { - "contents": "", - "bgcolor": "7" - }, - "11,79": { - "contents": "", - "bgcolor": "7" - }, - "11,8": { - "contents": "", - "bgcolor": "7" - }, - "11,9": { - "contents": "", - "bgcolor": "7" - }, - "12,0": { - "contents": "", - "bgcolor": "7" - }, - "12,1": { - "contents": "", - "bgcolor": "7" - }, - "12,10": { - "contents": "", - "bgcolor": "7" - }, - "12,11": { - "contents": "", - "bgcolor": "7" - }, - "12,12": { - "contents": "", - "bgcolor": "7" - }, - "12,13": { - "contents": "", - "bgcolor": "7" - }, - "12,14": { - "contents": "", - "bgcolor": "7" - }, - "12,15": { - "contents": "", - "bgcolor": "7" - }, - "12,16": { - "contents": "", - "bgcolor": "7" - }, - "12,17": { - "contents": "", - "bgcolor": "7" - }, - "12,18": { - "contents": "", - "bgcolor": "7" - }, - "12,19": { - "contents": "", - "bgcolor": "7" - }, - "12,2": { - "contents": "", - "bgcolor": "7" - }, - "12,20": { - "contents": "", - "bgcolor": "7" - }, - "12,21": { - "contents": "", - "bgcolor": "7" - }, - "12,22": { - "contents": "", - "bgcolor": "7" - }, - "12,23": { - "contents": "", - "bgcolor": "7" - }, - "12,24": { - "contents": "", - "bgcolor": "7" - }, - "12,25": { - "contents": "", - "bgcolor": "7" - }, - "12,26": { - "contents": "", - "bgcolor": "7" - }, - "12,27": { - "contents": "", - "bgcolor": "7" - }, - "12,28": { - "contents": "", - "bgcolor": "7" - }, - "12,29": { - "contents": "", - "bgcolor": "7" - }, - "12,3": { - "contents": "", - "bgcolor": "7" - }, - "12,30": { - "contents": "", - "bgcolor": "7" - }, - "12,31": { - "contents": "", - "bgcolor": "7" - }, - "12,32": { - "contents": "", - "bgcolor": "7" - }, - "12,33": { - "contents": "", - "bgcolor": "7" - }, - "12,34": { - "contents": "", - "bgcolor": "7" - }, - "12,35": { - "contents": "", - "bgcolor": "7" - }, - "12,36": { - "contents": "", - "bgcolor": "7" - }, - "12,37": { - "contents": "", - "bgcolor": "7" - }, - "12,38": { - "contents": "", - "bgcolor": "7" - }, - "12,39": { - "contents": "", - "bgcolor": "7" - }, - "12,4": { - "contents": "", - "bgcolor": "7" - }, - "12,40": { - "contents": "", - "bgcolor": "7" - }, - "12,41": { - "contents": "", - "bgcolor": "7" - }, - "12,42": { - "contents": "", - "bgcolor": "7" - }, - "12,43": { - "contents": "", - "bgcolor": "7" - }, - "12,44": { - "contents": "", - "bgcolor": "7" - }, - "12,45": { - "contents": "", - "bgcolor": "7" - }, - "12,46": { - "contents": "", - "bgcolor": "7" - }, - "12,47": { - "contents": "", - "bgcolor": "7" - }, - "12,48": { - "contents": "", - "bgcolor": "7" - }, - "12,49": { - "contents": "", - "bgcolor": "7" - }, - "12,5": { - "contents": "", - "bgcolor": "7" - }, - "12,50": { - "contents": "", - "bgcolor": "7" - }, - "12,51": { - "contents": "", - "bgcolor": "7" - }, - "12,52": { - "contents": "", - "bgcolor": "7" - }, - "12,53": { - "contents": "", - "bgcolor": "7" - }, - "12,54": { - "contents": "", - "bgcolor": "7" - }, - "12,55": { - "contents": "", - "bgcolor": "7" - }, - "12,56": { - "contents": "", - "bgcolor": "7" - }, - "12,57": { - "contents": "", - "bgcolor": "7" - }, - "12,58": { - "contents": "", - "bgcolor": "7" - }, - "12,59": { - "contents": "", - "bgcolor": "7" - }, - "12,6": { - "contents": "", - "bgcolor": "7" - }, - "12,60": { - "contents": "", - "bgcolor": "7" - }, - "12,61": { - "contents": "", - "bgcolor": "7" - }, - "12,62": { - "contents": "", - "bgcolor": "7" - }, - "12,63": { - "contents": "", - "bgcolor": "7" - }, - "12,64": { - "contents": "", - "bgcolor": "7" - }, - "12,65": { - "contents": "", - "bgcolor": "7" - }, - "12,66": { - "contents": "", - "bgcolor": "7" - }, - "12,67": { - "contents": "", - "bgcolor": "7" - }, - "12,68": { - "contents": "", - "bgcolor": "7" - }, - "12,69": { - "contents": "", - "bgcolor": "7" - }, - "12,7": { - "contents": "", - "bgcolor": "7" - }, - "12,70": { - "contents": "", - "bgcolor": "7" - }, - "12,71": { - "contents": "", - "bgcolor": "7" - }, - "12,72": { - "contents": "", - "bgcolor": "7" - }, - "12,73": { - "contents": "", - "bgcolor": "7" - }, - "12,74": { - "contents": "", - "bgcolor": "7" - }, - "12,75": { - "contents": "", - "bgcolor": "7" - }, - "12,76": { - "contents": "", - "bgcolor": "7" - }, - "12,77": { - "contents": "", - "bgcolor": "7" - }, - "12,78": { - "contents": "", - "bgcolor": "7" - }, - "12,79": { - "contents": "", - "bgcolor": "7" - }, - "12,8": { - "contents": "", - "bgcolor": "7" - }, - "12,9": { - "contents": "", - "bgcolor": "7" - }, - "13,0": { - "contents": "", - "bgcolor": "7" - }, - "13,1": { - "contents": "", - "bgcolor": "7" - }, - "13,10": { - "contents": "", - "bgcolor": "7" - }, - "13,11": { - "contents": "", - "bgcolor": "7" - }, - "13,12": { - "contents": "", - "bgcolor": "7" - }, - "13,13": { - "contents": "", - "bgcolor": "7" - }, - "13,14": { - "contents": "", - "bgcolor": "7" - }, - "13,15": { - "contents": "", - "bgcolor": "7" - }, - "13,16": { - "contents": "", - "bgcolor": "7" - }, - "13,17": { - "contents": "", - "bgcolor": "7" - }, - "13,18": { - "contents": "", - "bgcolor": "7" - }, - "13,19": { - "contents": "", - "bgcolor": "7" - }, - "13,2": { - "contents": "", - "bgcolor": "7" - }, - "13,20": { - "contents": "", - "bgcolor": "7" - }, - "13,21": { - "contents": "", - "bgcolor": "7" - }, - "13,22": { - "contents": "", - "bgcolor": "7" - }, - "13,23": { - "contents": "", - "bgcolor": "7" - }, - "13,24": { - "contents": "", - "bgcolor": "7" - }, - "13,25": { - "contents": "", - "bgcolor": "7" - }, - "13,26": { - "contents": "", - "bgcolor": "7" - }, - "13,27": { - "contents": "", - "bgcolor": "7" - }, - "13,28": { - "contents": "", - "bgcolor": "7" - }, - "13,29": { - "contents": "", - "bgcolor": "7" - }, - "13,3": { - "contents": "", - "bgcolor": "7" - }, - "13,30": { - "contents": "", - "bgcolor": "7" - }, - "13,31": { - "contents": "", - "bgcolor": "7" - }, - "13,32": { - "contents": "", - "bgcolor": "7" - }, - "13,33": { - "contents": "", - "bgcolor": "7" - }, - "13,34": { - "contents": "", - "bgcolor": "7" - }, - "13,35": { - "contents": "", - "bgcolor": "7" - }, - "13,36": { - "contents": "", - "bgcolor": "7" - }, - "13,37": { - "contents": "", - "bgcolor": "7" - }, - "13,38": { - "contents": "", - "bgcolor": "7" - }, - "13,39": { - "contents": "", - "bgcolor": "7" - }, - "13,4": { - "contents": "", - "bgcolor": "7" - }, - "13,40": { - "contents": "", - "bgcolor": "7" - }, - "13,41": { - "contents": "", - "bgcolor": "7" - }, - "13,42": { - "contents": "", - "bgcolor": "7" - }, - "13,43": { - "contents": "", - "bgcolor": "7" - }, - "13,44": { - "contents": "", - "bgcolor": "7" - }, - "13,45": { - "contents": "", - "bgcolor": "7" - }, - "13,46": { - "contents": "", - "bgcolor": "7" - }, - "13,47": { - "contents": "", - "bgcolor": "7" - }, - "13,48": { - "contents": "", - "bgcolor": "7" - }, - "13,49": { - "contents": "", - "bgcolor": "7" - }, - "13,5": { - "contents": "", - "bgcolor": "7" - }, - "13,50": { - "contents": "", - "bgcolor": "7" - }, - "13,51": { - "contents": "", - "bgcolor": "7" - }, - "13,52": { - "contents": "", - "bgcolor": "7" - }, - "13,53": { - "contents": "", - "bgcolor": "7" - }, - "13,54": { - "contents": "", - "bgcolor": "7" - }, - "13,55": { - "contents": "", - "bgcolor": "7" - }, - "13,56": { - "contents": "", - "bgcolor": "7" - }, - "13,57": { - "contents": "", - "bgcolor": "7" - }, - "13,58": { - "contents": "", - "bgcolor": "7" - }, - "13,59": { - "contents": "", - "bgcolor": "7" - }, - "13,6": { - "contents": "", - "bgcolor": "7" - }, - "13,60": { - "contents": "", - "bgcolor": "7" - }, - "13,61": { - "contents": "", - "bgcolor": "7" - }, - "13,62": { - "contents": "", - "bgcolor": "7" - }, - "13,63": { - "contents": "", - "bgcolor": "7" - }, - "13,64": { - "contents": "", - "bgcolor": "7" - }, - "13,65": { - "contents": "", - "bgcolor": "7" - }, - "13,66": { - "contents": "", - "bgcolor": "7" - }, - "13,67": { - "contents": "", - "bgcolor": "7" - }, - "13,68": { - "contents": "", - "bgcolor": "7" - }, - "13,69": { - "contents": "", - "bgcolor": "7" - }, - "13,7": { - "contents": "", - "bgcolor": "7" - }, - "13,70": { - "contents": "", - "bgcolor": "7" - }, - "13,71": { - "contents": "", - "bgcolor": "7" - }, - "13,72": { - "contents": "", - "bgcolor": "7" - }, - "13,73": { - "contents": "", - "bgcolor": "7" - }, - "13,74": { - "contents": "", - "bgcolor": "7" - }, - "13,75": { - "contents": "", - "bgcolor": "7" - }, - "13,76": { - "contents": "", - "bgcolor": "7" - }, - "13,77": { - "contents": "", - "bgcolor": "7" - }, - "13,78": { - "contents": "", - "bgcolor": "7" - }, - "13,79": { - "contents": "", - "bgcolor": "7" - }, - "13,8": { - "contents": "", - "bgcolor": "7" - }, - "13,9": { - "contents": "", - "bgcolor": "7" - }, - "14,0": { - "contents": "", - "bgcolor": "7" - }, - "14,1": { - "contents": "", - "bgcolor": "7" - }, - "14,10": { - "contents": "", - "bgcolor": "7" - }, - "14,11": { - "contents": "", - "bgcolor": "7" - }, - "14,12": { - "contents": "", - "bgcolor": "7" - }, - "14,13": { - "contents": "", - "bgcolor": "7" - }, - "14,14": { - "contents": "", - "bgcolor": "7" - }, - "14,15": { - "contents": "", - "bgcolor": "7" - }, - "14,16": { - "contents": "", - "bgcolor": "7" - }, - "14,17": { - "contents": "", - "bgcolor": "7" - }, - "14,18": { - "contents": "", - "bgcolor": "7" - }, - "14,19": { - "contents": "", - "bgcolor": "7" - }, - "14,2": { - "contents": "", - "bgcolor": "7" - }, - "14,20": { - "contents": "", - "bgcolor": "7" - }, - "14,21": { - "contents": "", - "bgcolor": "7" - }, - "14,22": { - "contents": "", - "bgcolor": "7" - }, - "14,23": { - "contents": "", - "bgcolor": "7" - }, - "14,24": { - "contents": "", - "bgcolor": "7" - }, - "14,25": { - "contents": "", - "bgcolor": "7" - }, - "14,26": { - "contents": "", - "bgcolor": "7" - }, - "14,27": { - "contents": "", - "bgcolor": "7" - }, - "14,28": { - "contents": "", - "bgcolor": "7" - }, - "14,29": { - "contents": "", - "bgcolor": "7" - }, - "14,3": { - "contents": "", - "bgcolor": "7" - }, - "14,30": { - "contents": "", - "bgcolor": "7" - }, - "14,31": { - "contents": "", - "bgcolor": "7" - }, - "14,32": { - "contents": "", - "bgcolor": "7" - }, - "14,33": { - "contents": "", - "bgcolor": "7" - }, - "14,34": { - "contents": "", - "bgcolor": "7" - }, - "14,35": { - "contents": "", - "bgcolor": "7" - }, - "14,36": { - "contents": "", - "bgcolor": "7" - }, - "14,37": { - "contents": "", - "bgcolor": "7" - }, - "14,38": { - "contents": "", - "bgcolor": "7" - }, - "14,39": { - "contents": "", - "bgcolor": "7" - }, - "14,4": { - "contents": "", - "bgcolor": "7" - }, - "14,40": { - "contents": "", - "bgcolor": "7" - }, - "14,41": { - "contents": "", - "bgcolor": "7" - }, - "14,42": { - "contents": "", - "bgcolor": "7" - }, - "14,43": { - "contents": "", - "bgcolor": "7" - }, - "14,44": { - "contents": "", - "bgcolor": "7" - }, - "14,45": { - "contents": "", - "bgcolor": "7" - }, - "14,46": { - "contents": "", - "bgcolor": "7" - }, - "14,47": { - "contents": "", - "bgcolor": "7" - }, - "14,48": { - "contents": "", - "bgcolor": "7" - }, - "14,49": { - "contents": "", - "bgcolor": "7" - }, - "14,5": { - "contents": "", - "bgcolor": "7" - }, - "14,50": { - "contents": "", - "bgcolor": "7" - }, - "14,51": { - "contents": "", - "bgcolor": "7" - }, - "14,52": { - "contents": "", - "bgcolor": "7" - }, - "14,53": { - "contents": "", - "bgcolor": "7" - }, - "14,54": { - "contents": "", - "bgcolor": "7" - }, - "14,55": { - "contents": "", - "bgcolor": "7" - }, - "14,56": { - "contents": "", - "bgcolor": "7" - }, - "14,57": { - "contents": "", - "bgcolor": "7" - }, - "14,58": { - "contents": "", - "bgcolor": "7" - }, - "14,59": { - "contents": "", - "bgcolor": "7" - }, - "14,6": { - "contents": "", - "bgcolor": "7" - }, - "14,60": { - "contents": "", - "bgcolor": "7" - }, - "14,61": { - "contents": "", - "bgcolor": "7" - }, - "14,62": { - "contents": "", - "bgcolor": "7" - }, - "14,63": { - "contents": "", - "bgcolor": "7" - }, - "14,64": { - "contents": "", - "bgcolor": "7" - }, - "14,65": { - "contents": "", - "bgcolor": "7" - }, - "14,66": { - "contents": "", - "bgcolor": "7" - }, - "14,67": { - "contents": "", - "bgcolor": "7" - }, - "14,68": { - "contents": "", - "bgcolor": "7" - }, - "14,69": { - "contents": "", - "bgcolor": "7" - }, - "14,7": { - "contents": "", - "bgcolor": "7" - }, - "14,70": { - "contents": "", - "bgcolor": "7" - }, - "14,71": { - "contents": "", - "bgcolor": "7" - }, - "14,72": { - "contents": "", - "bgcolor": "7" - }, - "14,73": { - "contents": "", - "bgcolor": "7" - }, - "14,74": { - "contents": "", - "bgcolor": "7" - }, - "14,75": { - "contents": "", - "bgcolor": "7" - }, - "14,76": { - "contents": "", - "bgcolor": "7" - }, - "14,77": { - "contents": "", - "bgcolor": "7" - }, - "14,78": { - "contents": "", - "bgcolor": "7" - }, - "14,79": { - "contents": "", - "bgcolor": "7" - }, - "14,8": { - "contents": "", - "bgcolor": "7" - }, - "14,9": { - "contents": "", - "bgcolor": "7" - }, - "15,0": { - "contents": "", - "bgcolor": "7" - }, - "15,1": { - "contents": "", - "bgcolor": "7" - }, - "15,10": { - "contents": "", - "bgcolor": "7" - }, - "15,11": { - "contents": "", - "bgcolor": "7" - }, - "15,12": { - "contents": "", - "bgcolor": "7" - }, - "15,13": { - "contents": "", - "bgcolor": "7" - }, - "15,14": { - "contents": "", - "bgcolor": "7" - }, - "15,15": { - "contents": "", - "bgcolor": "7" - }, - "15,16": { - "contents": "", - "bgcolor": "7" - }, - "15,17": { - "contents": "", - "bgcolor": "7" - }, - "15,18": { - "contents": "", - "bgcolor": "7" - }, - "15,19": { - "contents": "", - "bgcolor": "7" - }, - "15,2": { - "contents": "", - "bgcolor": "7" - }, - "15,20": { - "contents": "", - "bgcolor": "7" - }, - "15,21": { - "contents": "", - "bgcolor": "7" - }, - "15,22": { - "contents": "", - "bgcolor": "7" - }, - "15,23": { - "contents": "", - "bgcolor": "7" - }, - "15,24": { - "contents": "", - "bgcolor": "7" - }, - "15,25": { - "contents": "", - "bgcolor": "7" - }, - "15,26": { - "contents": "", - "bgcolor": "7" - }, - "15,27": { - "contents": "", - "bgcolor": "7" - }, - "15,28": { - "contents": "", - "bgcolor": "7" - }, - "15,29": { - "contents": "", - "bgcolor": "7" - }, - "15,3": { - "contents": "", - "bgcolor": "7" - }, - "15,30": { - "contents": "", - "bgcolor": "7" - }, - "15,31": { - "contents": "", - "bgcolor": "7" - }, - "15,32": { - "contents": "", - "bgcolor": "7" - }, - "15,33": { - "contents": "", - "bgcolor": "7" - }, - "15,34": { - "contents": "", - "bgcolor": "7" - }, - "15,35": { - "contents": "", - "bgcolor": "7" - }, - "15,36": { - "contents": "", - "bgcolor": "7" - }, - "15,37": { - "contents": "", - "bgcolor": "7" - }, - "15,38": { - "contents": "", - "bgcolor": "7" - }, - "15,39": { - "contents": "", - "bgcolor": "7" - }, - "15,4": { - "contents": "", - "bgcolor": "7" - }, - "15,40": { - "contents": "", - "bgcolor": "7" - }, - "15,41": { - "contents": "", - "bgcolor": "7" - }, - "15,42": { - "contents": "", - "bgcolor": "7" - }, - "15,43": { - "contents": "", - "bgcolor": "7" - }, - "15,44": { - "contents": "", - "bgcolor": "7" - }, - "15,45": { - "contents": "", - "bgcolor": "7" - }, - "15,46": { - "contents": "", - "bgcolor": "7" - }, - "15,47": { - "contents": "", - "bgcolor": "7" - }, - "15,48": { - "contents": "", - "bgcolor": "7" - }, - "15,49": { - "contents": "", - "bgcolor": "7" - }, - "15,5": { - "contents": "", - "bgcolor": "7" - }, - "15,50": { - "contents": "", - "bgcolor": "7" - }, - "15,51": { - "contents": "", - "bgcolor": "7" - }, - "15,52": { - "contents": "", - "bgcolor": "7" - }, - "15,53": { - "contents": "", - "bgcolor": "7" - }, - "15,54": { - "contents": "", - "bgcolor": "7" - }, - "15,55": { - "contents": "", - "bgcolor": "7" - }, - "15,56": { - "contents": "", - "bgcolor": "7" - }, - "15,57": { - "contents": "", - "bgcolor": "7" - }, - "15,58": { - "contents": "", - "bgcolor": "7" - }, - "15,59": { - "contents": "", - "bgcolor": "7" - }, - "15,6": { - "contents": "", - "bgcolor": "7" - }, - "15,60": { - "contents": "", - "bgcolor": "7" - }, - "15,61": { - "contents": "", - "bgcolor": "7" - }, - "15,62": { - "contents": "", - "bgcolor": "7" - }, - "15,63": { - "contents": "", - "bgcolor": "7" - }, - "15,64": { - "contents": "", - "bgcolor": "7" - }, - "15,65": { - "contents": "", - "bgcolor": "7" - }, - "15,66": { - "contents": "", - "bgcolor": "7" - }, - "15,67": { - "contents": "", - "bgcolor": "7" - }, - "15,68": { - "contents": "", - "bgcolor": "7" - }, - "15,69": { - "contents": "", - "bgcolor": "7" - }, - "15,7": { - "contents": "", - "bgcolor": "7" - }, - "15,70": { - "contents": "", - "bgcolor": "7" - }, - "15,71": { - "contents": "", - "bgcolor": "7" - }, - "15,72": { - "contents": "", - "bgcolor": "7" - }, - "15,73": { - "contents": "", - "bgcolor": "7" - }, - "15,74": { - "contents": "", - "bgcolor": "7" - }, - "15,75": { - "contents": "", - "bgcolor": "7" - }, - "15,76": { - "contents": "", - "bgcolor": "7" - }, - "15,77": { - "contents": "", - "bgcolor": "7" - }, - "15,78": { - "contents": "", - "bgcolor": "7" - }, - "15,79": { - "contents": "", - "bgcolor": "7" - }, - "15,8": { - "contents": "", - "bgcolor": "7" - }, - "15,9": { - "contents": "", - "bgcolor": "7" - }, - "16,0": { - "contents": "", - "bgcolor": "7" - }, - "16,1": { - "contents": "", - "bgcolor": "7" - }, - "16,10": { - "contents": "", - "bgcolor": "7" - }, - "16,11": { - "contents": "", - "bgcolor": "7" - }, - "16,12": { - "contents": "", - "bgcolor": "7" - }, - "16,13": { - "contents": "", - "bgcolor": "7" - }, - "16,14": { - "contents": "", - "bgcolor": "7" - }, - "16,15": { - "contents": "", - "bgcolor": "7" - }, - "16,16": { - "contents": "", - "bgcolor": "7" - }, - "16,17": { - "contents": "", - "bgcolor": "7" - }, - "16,18": { - "contents": "", - "bgcolor": "7" - }, - "16,19": { - "contents": "", - "bgcolor": "7" - }, - "16,2": { - "contents": "", - "bgcolor": "7" - }, - "16,20": { - "contents": "", - "bgcolor": "7" - }, - "16,21": { - "contents": "", - "bgcolor": "7" - }, - "16,22": { - "contents": "", - "bgcolor": "7" - }, - "16,23": { - "contents": "", - "bgcolor": "7" - }, - "16,24": { - "contents": "", - "bgcolor": "7" - }, - "16,25": { - "contents": "", - "bgcolor": "7" - }, - "16,26": { - "contents": "", - "bgcolor": "7" - }, - "16,27": { - "contents": "", - "bgcolor": "7" - }, - "16,28": { - "contents": "", - "bgcolor": "7" - }, - "16,29": { - "contents": "", - "bgcolor": "7" - }, - "16,3": { - "contents": "", - "bgcolor": "7" - }, - "16,30": { - "contents": "", - "bgcolor": "7" - }, - "16,31": { - "contents": "", - "bgcolor": "7" - }, - "16,32": { - "contents": "", - "bgcolor": "7" - }, - "16,33": { - "contents": "", - "bgcolor": "7" - }, - "16,34": { - "contents": "", - "bgcolor": "7" - }, - "16,35": { - "contents": "", - "bgcolor": "7" - }, - "16,36": { - "contents": "", - "bgcolor": "7" - }, - "16,37": { - "contents": "", - "bgcolor": "7" - }, - "16,38": { - "contents": "", - "bgcolor": "7" - }, - "16,39": { - "contents": "", - "bgcolor": "7" - }, - "16,4": { - "contents": "", - "bgcolor": "7" - }, - "16,40": { - "contents": "", - "bgcolor": "7" - }, - "16,41": { - "contents": "", - "bgcolor": "7" - }, - "16,42": { - "contents": "", - "bgcolor": "7" - }, - "16,43": { - "contents": "", - "bgcolor": "7" - }, - "16,44": { - "contents": "", - "bgcolor": "7" - }, - "16,45": { - "contents": "", - "bgcolor": "7" - }, - "16,46": { - "contents": "", - "bgcolor": "7" - }, - "16,47": { - "contents": "", - "bgcolor": "7" - }, - "16,48": { - "contents": "", - "bgcolor": "7" - }, - "16,49": { - "contents": "", - "bgcolor": "7" - }, - "16,5": { - "contents": "", - "bgcolor": "7" - }, - "16,50": { - "contents": "", - "bgcolor": "7" - }, - "16,51": { - "contents": "", - "bgcolor": "7" - }, - "16,52": { - "contents": "", - "bgcolor": "7" - }, - "16,53": { - "contents": "", - "bgcolor": "7" - }, - "16,54": { - "contents": "", - "bgcolor": "7" - }, - "16,55": { - "contents": "", - "bgcolor": "7" - }, - "16,56": { - "contents": "", - "bgcolor": "7" - }, - "16,57": { - "contents": "", - "bgcolor": "7" - }, - "16,58": { - "contents": "", - "bgcolor": "7" - }, - "16,59": { - "contents": "", - "bgcolor": "7" - }, - "16,6": { - "contents": "", - "bgcolor": "7" - }, - "16,60": { - "contents": "", - "bgcolor": "7" - }, - "16,61": { - "contents": "", - "bgcolor": "7" - }, - "16,62": { - "contents": "", - "bgcolor": "7" - }, - "16,63": { - "contents": "", - "bgcolor": "7" - }, - "16,64": { - "contents": "", - "bgcolor": "7" - }, - "16,65": { - "contents": "", - "bgcolor": "7" - }, - "16,66": { - "contents": "", - "bgcolor": "7" - }, - "16,67": { - "contents": "", - "bgcolor": "7" - }, - "16,68": { - "contents": "", - "bgcolor": "7" - }, - "16,69": { - "contents": "", - "bgcolor": "7" - }, - "16,7": { - "contents": "", - "bgcolor": "7" - }, - "16,70": { - "contents": "", - "bgcolor": "7" - }, - "16,71": { - "contents": "", - "bgcolor": "7" - }, - "16,72": { - "contents": "", - "bgcolor": "7" - }, - "16,73": { - "contents": "", - "bgcolor": "7" - }, - "16,74": { - "contents": "", - "bgcolor": "7" - }, - "16,75": { - "contents": "", - "bgcolor": "7" - }, - "16,76": { - "contents": "", - "bgcolor": "7" - }, - "16,77": { - "contents": "", - "bgcolor": "7" - }, - "16,78": { - "contents": "", - "bgcolor": "7" - }, - "16,79": { - "contents": "", - "bgcolor": "7" - }, - "16,8": { - "contents": "", - "bgcolor": "7" - }, - "16,9": { - "contents": "", - "bgcolor": "7" - }, - "17,0": { - "contents": "", - "bgcolor": "7" - }, - "17,1": { - "contents": "", - "bgcolor": "7" - }, - "17,10": { - "contents": "", - "bgcolor": "7" - }, - "17,11": { - "contents": "", - "bgcolor": "7" - }, - "17,12": { - "contents": "", - "bgcolor": "7" - }, - "17,13": { - "contents": "", - "bgcolor": "7" - }, - "17,14": { - "contents": "", - "bgcolor": "7" - }, - "17,15": { - "contents": "", - "bgcolor": "7" - }, - "17,16": { - "contents": "", - "bgcolor": "7" - }, - "17,17": { - "contents": "", - "bgcolor": "7" - }, - "17,18": { - "contents": "", - "bgcolor": "7" - }, - "17,19": { - "contents": "", - "bgcolor": "7" - }, - "17,2": { - "contents": "", - "bgcolor": "7" - }, - "17,20": { - "contents": "", - "bgcolor": "7" - }, - "17,21": { - "contents": "", - "bgcolor": "7" - }, - "17,22": { - "contents": "", - "bgcolor": "7" - }, - "17,23": { - "contents": "", - "bgcolor": "7" - }, - "17,24": { - "contents": "", - "bgcolor": "7" - }, - "17,25": { - "contents": "", - "bgcolor": "7" - }, - "17,26": { - "contents": "", - "bgcolor": "7" - }, - "17,27": { - "contents": "", - "bgcolor": "7" - }, - "17,28": { - "contents": "", - "bgcolor": "7" - }, - "17,29": { - "contents": "", - "bgcolor": "7" - }, - "17,3": { - "contents": "", - "bgcolor": "7" - }, - "17,30": { - "contents": "", - "bgcolor": "7" - }, - "17,31": { - "contents": "", - "bgcolor": "7" - }, - "17,32": { - "contents": "", - "bgcolor": "7" - }, - "17,33": { - "contents": "", - "bgcolor": "7" - }, - "17,34": { - "contents": "", - "bgcolor": "7" - }, - "17,35": { - "contents": "", - "bgcolor": "7" - }, - "17,36": { - "contents": "", - "bgcolor": "7" - }, - "17,37": { - "contents": "", - "bgcolor": "7" - }, - "17,38": { - "contents": "", - "bgcolor": "7" - }, - "17,39": { - "contents": "", - "bgcolor": "7" - }, - "17,4": { - "contents": "", - "bgcolor": "7" - }, - "17,40": { - "contents": "", - "bgcolor": "7" - }, - "17,41": { - "contents": "", - "bgcolor": "7" - }, - "17,42": { - "contents": "", - "bgcolor": "7" - }, - "17,43": { - "contents": "", - "bgcolor": "7" - }, - "17,44": { - "contents": "", - "bgcolor": "7" - }, - "17,45": { - "contents": "", - "bgcolor": "7" - }, - "17,46": { - "contents": "", - "bgcolor": "7" - }, - "17,47": { - "contents": "", - "bgcolor": "7" - }, - "17,48": { - "contents": "", - "bgcolor": "7" - }, - "17,49": { - "contents": "", - "bgcolor": "7" - }, - "17,5": { - "contents": "", - "bgcolor": "7" - }, - "17,50": { - "contents": "", - "bgcolor": "7" - }, - "17,51": { - "contents": "", - "bgcolor": "7" - }, - "17,52": { - "contents": "", - "bgcolor": "7" - }, - "17,53": { - "contents": "", - "bgcolor": "7" - }, - "17,54": { - "contents": "", - "bgcolor": "7" - }, - "17,55": { - "contents": "", - "bgcolor": "7" - }, - "17,56": { - "contents": "", - "bgcolor": "7" - }, - "17,57": { - "contents": "", - "bgcolor": "7" - }, - "17,58": { - "contents": "", - "bgcolor": "7" - }, - "17,59": { - "contents": "", - "bgcolor": "7" - }, - "17,6": { - "contents": "", - "bgcolor": "7" - }, - "17,60": { - "contents": "", - "bgcolor": "7" - }, - "17,61": { - "contents": "", - "bgcolor": "7" - }, - "17,62": { - "contents": "", - "bgcolor": "7" - }, - "17,63": { - "contents": "", - "bgcolor": "7" - }, - "17,64": { - "contents": "", - "bgcolor": "7" - }, - "17,65": { - "contents": "", - "bgcolor": "7" - }, - "17,66": { - "contents": "", - "bgcolor": "7" - }, - "17,67": { - "contents": "", - "bgcolor": "7" - }, - "17,68": { - "contents": "", - "bgcolor": "7" - }, - "17,69": { - "contents": "", - "bgcolor": "7" - }, - "17,7": { - "contents": "", - "bgcolor": "7" - }, - "17,70": { - "contents": "", - "bgcolor": "7" - }, - "17,71": { - "contents": "", - "bgcolor": "7" - }, - "17,72": { - "contents": "", - "bgcolor": "7" - }, - "17,73": { - "contents": "", - "bgcolor": "7" - }, - "17,74": { - "contents": "", - "bgcolor": "7" - }, - "17,75": { - "contents": "", - "bgcolor": "7" - }, - "17,76": { - "contents": "", - "bgcolor": "7" - }, - "17,77": { - "contents": "", - "bgcolor": "7" - }, - "17,78": { - "contents": "", - "bgcolor": "7" - }, - "17,79": { - "contents": "", - "bgcolor": "7" - }, - "17,8": { - "contents": "", - "bgcolor": "7" - }, - "17,9": { - "contents": "", - "bgcolor": "7" - }, - "18,0": { - "contents": "", - "bgcolor": "7" - }, - "18,1": { - "contents": "", - "bgcolor": "7" - }, - "18,10": { - "contents": "", - "bgcolor": "7" - }, - "18,11": { - "contents": "", - "bgcolor": "7" - }, - "18,12": { - "contents": "", - "bgcolor": "7" - }, - "18,13": { - "contents": "", - "bgcolor": "7" - }, - "18,14": { - "contents": "", - "bgcolor": "7" - }, - "18,15": { - "contents": "", - "bgcolor": "7" - }, - "18,16": { - "contents": "", - "bgcolor": "7" - }, - "18,17": { - "contents": "", - "bgcolor": "7" - }, - "18,18": { - "contents": "", - "bgcolor": "7" - }, - "18,19": { - "contents": "", - "bgcolor": "7" - }, - "18,2": { - "contents": "", - "bgcolor": "7" - }, - "18,20": { - "contents": "", - "bgcolor": "7" - }, - "18,21": { - "contents": "", - "bgcolor": "7" - }, - "18,22": { - "contents": "", - "bgcolor": "7" - }, - "18,23": { - "contents": "", - "bgcolor": "7" - }, - "18,24": { - "contents": "", - "bgcolor": "7" - }, - "18,25": { - "contents": "", - "bgcolor": "7" - }, - "18,26": { - "contents": "", - "bgcolor": "7" - }, - "18,27": { - "contents": "", - "bgcolor": "7" - }, - "18,28": { - "contents": "", - "bgcolor": "7" - }, - "18,29": { - "contents": "", - "bgcolor": "7" - }, - "18,3": { - "contents": "", - "bgcolor": "7" - }, - "18,30": { - "contents": "", - "bgcolor": "7" - }, - "18,31": { - "contents": "", - "bgcolor": "7" - }, - "18,32": { - "contents": "", - "bgcolor": "7" - }, - "18,33": { - "contents": "", - "bgcolor": "7" - }, - "18,34": { - "contents": "", - "bgcolor": "7" - }, - "18,35": { - "contents": "", - "bgcolor": "7" - }, - "18,36": { - "contents": "", - "bgcolor": "7" - }, - "18,37": { - "contents": "", - "bgcolor": "7" - }, - "18,38": { - "contents": "", - "bgcolor": "7" - }, - "18,39": { - "contents": "", - "bgcolor": "7" - }, - "18,4": { - "contents": "", - "bgcolor": "7" - }, - "18,40": { - "contents": "", - "bgcolor": "7" - }, - "18,41": { - "contents": "", - "bgcolor": "7" - }, - "18,42": { - "contents": "", - "bgcolor": "7" - }, - "18,43": { - "contents": "", - "bgcolor": "7" - }, - "18,44": { - "contents": "", - "bgcolor": "7" - }, - "18,45": { - "contents": "", - "bgcolor": "7" - }, - "18,46": { - "contents": "", - "bgcolor": "7" - }, - "18,47": { - "contents": "", - "bgcolor": "7" - }, - "18,48": { - "contents": "", - "bgcolor": "7" - }, - "18,49": { - "contents": "", - "bgcolor": "7" - }, - "18,5": { - "contents": "", - "bgcolor": "7" - }, - "18,50": { - "contents": "", - "bgcolor": "7" - }, - "18,51": { - "contents": "", - "bgcolor": "7" - }, - "18,52": { - "contents": "", - "bgcolor": "7" - }, - "18,53": { - "contents": "", - "bgcolor": "7" - }, - "18,54": { - "contents": "", - "bgcolor": "7" - }, - "18,55": { - "contents": "", - "bgcolor": "7" - }, - "18,56": { - "contents": "", - "bgcolor": "7" - }, - "18,57": { - "contents": "", - "bgcolor": "7" - }, - "18,58": { - "contents": "", - "bgcolor": "7" - }, - "18,59": { - "contents": "", - "bgcolor": "7" - }, - "18,6": { - "contents": "", - "bgcolor": "7" - }, - "18,60": { - "contents": "", - "bgcolor": "7" - }, - "18,61": { - "contents": "", - "bgcolor": "7" - }, - "18,62": { - "contents": "", - "bgcolor": "7" - }, - "18,63": { - "contents": "", - "bgcolor": "7" - }, - "18,64": { - "contents": "", - "bgcolor": "7" - }, - "18,65": { - "contents": "", - "bgcolor": "7" - }, - "18,66": { - "contents": "", - "bgcolor": "7" - }, - "18,67": { - "contents": "", - "bgcolor": "7" - }, - "18,68": { - "contents": "", - "bgcolor": "7" - }, - "18,69": { - "contents": "", - "bgcolor": "7" - }, - "18,7": { - "contents": "", - "bgcolor": "7" - }, - "18,70": { - "contents": "", - "bgcolor": "7" - }, - "18,71": { - "contents": "", - "bgcolor": "7" - }, - "18,72": { - "contents": "", - "bgcolor": "7" - }, - "18,73": { - "contents": "", - "bgcolor": "7" - }, - "18,74": { - "contents": "", - "bgcolor": "7" - }, - "18,75": { - "contents": "", - "bgcolor": "7" - }, - "18,76": { - "contents": "", - "bgcolor": "7" - }, - "18,77": { - "contents": "", - "bgcolor": "7" - }, - "18,78": { - "contents": "", - "bgcolor": "7" - }, - "18,79": { - "contents": "", - "bgcolor": "7" - }, - "18,8": { - "contents": "", - "bgcolor": "7" - }, - "18,9": { - "contents": "", - "bgcolor": "7" - }, - "19,0": { - "contents": "", - "bgcolor": "7" - }, - "19,1": { - "contents": "", - "bgcolor": "7" - }, - "19,10": { - "contents": "", - "bgcolor": "7" - }, - "19,11": { - "contents": "", - "bgcolor": "7" - }, - "19,12": { - "contents": "", - "bgcolor": "7" - }, - "19,13": { - "contents": "", - "bgcolor": "7" - }, - "19,14": { - "contents": "", - "bgcolor": "7" - }, - "19,15": { - "contents": "", - "bgcolor": "7" - }, - "19,16": { - "contents": "", - "bgcolor": "7" - }, - "19,17": { - "contents": "", - "bgcolor": "7" - }, - "19,18": { - "contents": "", - "bgcolor": "7" - }, - "19,19": { - "contents": "", - "bgcolor": "7" - }, - "19,2": { - "contents": "", - "bgcolor": "7" - }, - "19,20": { - "contents": "", - "bgcolor": "7" - }, - "19,21": { - "contents": "", - "bgcolor": "7" - }, - "19,22": { - "contents": "", - "bgcolor": "7" - }, - "19,23": { - "contents": "", - "bgcolor": "7" - }, - "19,24": { - "contents": "", - "bgcolor": "7" - }, - "19,25": { - "contents": "", - "bgcolor": "7" - }, - "19,26": { - "contents": "", - "bgcolor": "7" - }, - "19,27": { - "contents": "", - "bgcolor": "7" - }, - "19,28": { - "contents": "", - "bgcolor": "7" - }, - "19,29": { - "contents": "", - "bgcolor": "7" - }, - "19,3": { - "contents": "", - "bgcolor": "7" - }, - "19,30": { - "contents": "", - "bgcolor": "7" - }, - "19,31": { - "contents": "", - "bgcolor": "7" - }, - "19,32": { - "contents": "", - "bgcolor": "7" - }, - "19,33": { - "contents": "", - "bgcolor": "7" - }, - "19,34": { - "contents": "", - "bgcolor": "7" - }, - "19,35": { - "contents": "", - "bgcolor": "7" - }, - "19,36": { - "contents": "", - "bgcolor": "7" - }, - "19,37": { - "contents": "", - "bgcolor": "7" - }, - "19,38": { - "contents": "", - "bgcolor": "7" - }, - "19,39": { - "contents": "", - "bgcolor": "7" - }, - "19,4": { - "contents": "", - "bgcolor": "7" - }, - "19,40": { - "contents": "", - "bgcolor": "7" - }, - "19,41": { - "contents": "", - "bgcolor": "7" - }, - "19,42": { - "contents": "", - "bgcolor": "7" - }, - "19,43": { - "contents": "", - "bgcolor": "7" - }, - "19,44": { - "contents": "", - "bgcolor": "7" - }, - "19,45": { - "contents": "", - "bgcolor": "7" - }, - "19,46": { - "contents": "", - "bgcolor": "7" - }, - "19,47": { - "contents": "", - "bgcolor": "7" - }, - "19,48": { - "contents": "", - "bgcolor": "7" - }, - "19,49": { - "contents": "", - "bgcolor": "7" - }, - "19,5": { - "contents": "", - "bgcolor": "7" - }, - "19,50": { - "contents": "", - "bgcolor": "7" - }, - "19,51": { - "contents": "", - "bgcolor": "7" - }, - "19,52": { - "contents": "", - "bgcolor": "7" - }, - "19,53": { - "contents": "", - "bgcolor": "7" - }, - "19,54": { - "contents": "", - "bgcolor": "7" - }, - "19,55": { - "contents": "", - "bgcolor": "7" - }, - "19,56": { - "contents": "", - "bgcolor": "7" - }, - "19,57": { - "contents": "", - "bgcolor": "7" - }, - "19,58": { - "contents": "", - "bgcolor": "7" - }, - "19,59": { - "contents": "", - "bgcolor": "7" - }, - "19,6": { - "contents": "", - "bgcolor": "7" - }, - "19,60": { - "contents": "", - "bgcolor": "7" - }, - "19,61": { - "contents": "", - "bgcolor": "7" - }, - "19,62": { - "contents": "", - "bgcolor": "7" - }, - "19,63": { - "contents": "", - "bgcolor": "7" - }, - "19,64": { - "contents": "", - "bgcolor": "7" - }, - "19,65": { - "contents": "", - "bgcolor": "7" - }, - "19,66": { - "contents": "", - "bgcolor": "7" - }, - "19,67": { - "contents": "", - "bgcolor": "7" - }, - "19,68": { - "contents": "", - "bgcolor": "7" - }, - "19,69": { - "contents": "", - "bgcolor": "7" - }, - "19,7": { - "contents": "", - "bgcolor": "7" - }, - "19,70": { - "contents": "", - "bgcolor": "7" - }, - "19,71": { - "contents": "", - "bgcolor": "7" - }, - "19,72": { - "contents": "", - "bgcolor": "7" - }, - "19,73": { - "contents": "", - "bgcolor": "7" - }, - "19,74": { - "contents": "", - "bgcolor": "7" - }, - "19,75": { - "contents": "", - "bgcolor": "7" - }, - "19,76": { - "contents": "", - "bgcolor": "7" - }, - "19,77": { - "contents": "", - "bgcolor": "7" - }, - "19,78": { - "contents": "", - "bgcolor": "7" - }, - "19,79": { - "contents": "", - "bgcolor": "7" - }, - "19,8": { - "contents": "", - "bgcolor": "7" - }, - "19,9": { - "contents": "", - "bgcolor": "7" - }, - "2,0": { - "contents": "", - "bgcolor": "7" - }, - "2,1": { - "contents": "", - "bgcolor": "7" - }, - "2,10": { - "contents": "", - "bgcolor": "7" - }, - "2,11": { - "contents": "", - "bgcolor": "7" - }, - "2,12": { - "contents": "", - "bgcolor": "7" - }, - "2,13": { - "contents": "", - "bgcolor": "7" - }, - "2,14": { - "contents": "", - "bgcolor": "7" - }, - "2,15": { - "contents": "", - "bgcolor": "7" - }, - "2,16": { - "contents": "", - "bgcolor": "7" - }, - "2,17": { - "contents": "", - "bgcolor": "7" - }, - "2,18": { - "contents": "", - "bgcolor": "7" - }, - "2,19": { - "contents": "", - "bgcolor": "7" - }, - "2,2": { - "contents": "", - "bgcolor": "7" - }, - "2,20": { - "contents": "", - "bgcolor": "7" - }, - "2,21": { - "contents": "", - "bgcolor": "7" - }, - "2,22": { - "contents": "", - "bgcolor": "7" - }, - "2,23": { - "contents": "", - "bgcolor": "7" - }, - "2,24": { - "contents": "", - "bgcolor": "7" - }, - "2,25": { - "contents": "", - "bgcolor": "7" - }, - "2,26": { - "contents": "", - "bgcolor": "7" - }, - "2,27": { - "contents": "", - "bgcolor": "7" - }, - "2,28": { - "contents": "", - "bgcolor": "7" - }, - "2,29": { - "contents": "", - "bgcolor": "7" - }, - "2,3": { - "contents": "", - "bgcolor": "7" - }, - "2,30": { - "contents": "", - "bgcolor": "7" - }, - "2,31": { - "contents": "", - "bgcolor": "7" - }, - "2,32": { - "contents": "", - "bgcolor": "7" - }, - "2,33": { - "contents": "", - "bgcolor": "7" - }, - "2,34": { - "contents": "", - "bgcolor": "7" - }, - "2,35": { - "contents": "", - "bgcolor": "7" - }, - "2,36": { - "contents": "", - "bgcolor": "7" - }, - "2,37": { - "contents": "", - "bgcolor": "7" - }, - "2,38": { - "contents": "", - "bgcolor": "7" - }, - "2,39": { - "contents": "", - "bgcolor": "7" - }, - "2,4": { - "contents": "", - "bgcolor": "7" - }, - "2,40": { - "contents": "", - "bgcolor": "7" - }, - "2,41": { - "contents": "", - "bgcolor": "7" - }, - "2,42": { - "contents": "", - "bgcolor": "7" - }, - "2,43": { - "contents": "", - "bgcolor": "7" - }, - "2,44": { - "contents": "", - "bgcolor": "7" - }, - "2,45": { - "contents": "", - "bgcolor": "7" - }, - "2,46": { - "contents": "", - "bgcolor": "7" - }, - "2,47": { - "contents": "", - "bgcolor": "7" - }, - "2,48": { - "contents": "", - "bgcolor": "7" - }, - "2,49": { - "contents": "", - "bgcolor": "7" - }, - "2,5": { - "contents": "", - "bgcolor": "7" - }, - "2,50": { - "contents": "", - "bgcolor": "7" - }, - "2,51": { - "contents": "", - "bgcolor": "7" - }, - "2,52": { - "contents": "", - "bgcolor": "7" - }, - "2,53": { - "contents": "", - "bgcolor": "7" - }, - "2,54": { - "contents": "", - "bgcolor": "7" - }, - "2,55": { - "contents": "", - "bgcolor": "7" - }, - "2,56": { - "contents": "", - "bgcolor": "7" - }, - "2,57": { - "contents": "", - "bgcolor": "7" - }, - "2,58": { - "contents": "", - "bgcolor": "7" - }, - "2,59": { - "contents": "", - "bgcolor": "7" - }, - "2,6": { - "contents": "", - "bgcolor": "7" - }, - "2,60": { - "contents": "", - "bgcolor": "7" - }, - "2,61": { - "contents": "", - "bgcolor": "7" - }, - "2,62": { - "contents": "", - "bgcolor": "7" - }, - "2,63": { - "contents": "", - "bgcolor": "7" - }, - "2,64": { - "contents": "", - "bgcolor": "7" - }, - "2,65": { - "contents": "", - "bgcolor": "7" - }, - "2,66": { - "contents": "", - "bgcolor": "7" - }, - "2,67": { - "contents": "", - "bgcolor": "7" - }, - "2,68": { - "contents": "", - "bgcolor": "7" - }, - "2,69": { - "contents": "", - "bgcolor": "7" - }, - "2,7": { - "contents": "", - "bgcolor": "7" - }, - "2,70": { - "contents": "", - "bgcolor": "7" - }, - "2,71": { - "contents": "", - "bgcolor": "7" - }, - "2,72": { - "contents": "", - "bgcolor": "7" - }, - "2,73": { - "contents": "", - "bgcolor": "7" - }, - "2,74": { - "contents": "", - "bgcolor": "7" - }, - "2,75": { - "contents": "", - "bgcolor": "7" - }, - "2,76": { - "contents": "", - "bgcolor": "7" - }, - "2,77": { - "contents": "", - "bgcolor": "7" - }, - "2,78": { - "contents": "", - "bgcolor": "7" - }, - "2,79": { - "contents": "", - "bgcolor": "7" - }, - "2,8": { - "contents": "", - "bgcolor": "7" - }, - "2,9": { - "contents": "", - "bgcolor": "7" - }, - "20,0": { - "contents": "", - "bgcolor": "7" - }, - "20,1": { - "contents": "", - "bgcolor": "7" - }, - "20,10": { - "contents": "", - "bgcolor": "7" - }, - "20,11": { - "contents": "", - "bgcolor": "7" - }, - "20,12": { - "contents": "", - "bgcolor": "7" - }, - "20,13": { - "contents": "", - "bgcolor": "7" - }, - "20,14": { - "contents": "", - "bgcolor": "7" - }, - "20,15": { - "contents": "", - "bgcolor": "7" - }, - "20,16": { - "contents": "", - "bgcolor": "7" - }, - "20,17": { - "contents": "", - "bgcolor": "7" - }, - "20,18": { - "contents": "", - "bgcolor": "7" - }, - "20,19": { - "contents": "", - "bgcolor": "7" - }, - "20,2": { - "contents": "", - "bgcolor": "7" - }, - "20,20": { - "contents": "", - "bgcolor": "7" - }, - "20,21": { - "contents": "", - "bgcolor": "7" - }, - "20,22": { - "contents": "", - "bgcolor": "7" - }, - "20,23": { - "contents": "", - "bgcolor": "7" - }, - "20,24": { - "contents": "", - "bgcolor": "7" - }, - "20,25": { - "contents": "", - "bgcolor": "7" - }, - "20,26": { - "contents": "", - "bgcolor": "7" - }, - "20,27": { - "contents": "", - "bgcolor": "7" - }, - "20,28": { - "contents": "", - "bgcolor": "7" - }, - "20,29": { - "contents": "", - "bgcolor": "7" - }, - "20,3": { - "contents": "", - "bgcolor": "7" - }, - "20,30": { - "contents": "", - "bgcolor": "7" - }, - "20,31": { - "contents": "", - "bgcolor": "7" - }, - "20,32": { - "contents": "", - "bgcolor": "7" - }, - "20,33": { - "contents": "", - "bgcolor": "7" - }, - "20,34": { - "contents": "", - "bgcolor": "7" - }, - "20,35": { - "contents": "", - "bgcolor": "7" - }, - "20,36": { - "contents": "", - "bgcolor": "7" - }, - "20,37": { - "contents": "", - "bgcolor": "7" - }, - "20,38": { - "contents": "", - "bgcolor": "7" - }, - "20,39": { - "contents": "", - "bgcolor": "7" - }, - "20,4": { - "contents": "", - "bgcolor": "7" - }, - "20,40": { - "contents": "", - "bgcolor": "7" - }, - "20,41": { - "contents": "", - "bgcolor": "7" - }, - "20,42": { - "contents": "", - "bgcolor": "7" - }, - "20,43": { - "contents": "", - "bgcolor": "7" - }, - "20,44": { - "contents": "", - "bgcolor": "7" - }, - "20,45": { - "contents": "", - "bgcolor": "7" - }, - "20,46": { - "contents": "", - "bgcolor": "7" - }, - "20,47": { - "contents": "", - "bgcolor": "7" - }, - "20,48": { - "contents": "", - "bgcolor": "7" - }, - "20,49": { - "contents": "", - "bgcolor": "7" - }, - "20,5": { - "contents": "", - "bgcolor": "7" - }, - "20,50": { - "contents": "", - "bgcolor": "7" - }, - "20,51": { - "contents": "", - "bgcolor": "7" - }, - "20,52": { - "contents": "", - "bgcolor": "7" - }, - "20,53": { - "contents": "", - "bgcolor": "7" - }, - "20,54": { - "contents": "", - "bgcolor": "7" - }, - "20,55": { - "contents": "", - "bgcolor": "7" - }, - "20,56": { - "contents": "", - "bgcolor": "7" - }, - "20,57": { - "contents": "", - "bgcolor": "7" - }, - "20,58": { - "contents": "", - "bgcolor": "7" - }, - "20,59": { - "contents": "", - "bgcolor": "7" - }, - "20,6": { - "contents": "", - "bgcolor": "7" - }, - "20,60": { - "contents": "", - "bgcolor": "7" - }, - "20,61": { - "contents": "", - "bgcolor": "7" - }, - "20,62": { - "contents": "", - "bgcolor": "7" - }, - "20,63": { - "contents": "", - "bgcolor": "7" - }, - "20,64": { - "contents": "", - "bgcolor": "7" - }, - "20,65": { - "contents": "", - "bgcolor": "7" - }, - "20,66": { - "contents": "", - "bgcolor": "7" - }, - "20,67": { - "contents": "", - "bgcolor": "7" - }, - "20,68": { - "contents": "", - "bgcolor": "7" - }, - "20,69": { - "contents": "", - "bgcolor": "7" - }, - "20,7": { - "contents": "", - "bgcolor": "7" - }, - "20,70": { - "contents": "", - "bgcolor": "7" - }, - "20,71": { - "contents": "", - "bgcolor": "7" - }, - "20,72": { - "contents": "", - "bgcolor": "7" - }, - "20,73": { - "contents": "", - "bgcolor": "7" - }, - "20,74": { - "contents": "", - "bgcolor": "7" - }, - "20,75": { - "contents": "", - "bgcolor": "7" - }, - "20,76": { - "contents": "", - "bgcolor": "7" - }, - "20,77": { - "contents": "", - "bgcolor": "7" - }, - "20,78": { - "contents": "", - "bgcolor": "7" - }, - "20,79": { - "contents": "", - "bgcolor": "7" - }, - "20,8": { - "contents": "", - "bgcolor": "7" - }, - "20,9": { - "contents": "", - "bgcolor": "7" - }, - "21,0": { - "contents": "", - "bgcolor": "7" - }, - "21,1": { - "contents": "", - "bgcolor": "7" - }, - "21,10": { - "contents": "", - "bgcolor": "7" - }, - "21,11": { - "contents": "", - "bgcolor": "7" - }, - "21,12": { - "contents": "", - "bgcolor": "7" - }, - "21,13": { - "contents": "", - "bgcolor": "7" - }, - "21,14": { - "contents": "", - "bgcolor": "7" - }, - "21,15": { - "contents": "", - "bgcolor": "7" - }, - "21,16": { - "contents": "", - "bgcolor": "7" - }, - "21,17": { - "contents": "", - "bgcolor": "7" - }, - "21,18": { - "contents": "", - "bgcolor": "7" - }, - "21,19": { - "contents": "", - "bgcolor": "7" - }, - "21,2": { - "contents": "", - "bgcolor": "7" - }, - "21,20": { - "contents": "", - "bgcolor": "7" - }, - "21,21": { - "contents": "", - "bgcolor": "7" - }, - "21,22": { - "contents": "", - "bgcolor": "7" - }, - "21,23": { - "contents": "", - "bgcolor": "7" - }, - "21,24": { - "contents": "", - "bgcolor": "7" - }, - "21,25": { - "contents": "", - "bgcolor": "7" - }, - "21,26": { - "contents": "", - "bgcolor": "7" - }, - "21,27": { - "contents": "", - "bgcolor": "7" - }, - "21,28": { - "contents": "", - "bgcolor": "7" - }, - "21,29": { - "contents": "", - "bgcolor": "7" - }, - "21,3": { - "contents": "", - "bgcolor": "7" - }, - "21,30": { - "contents": "", - "bgcolor": "7" - }, - "21,31": { - "contents": "", - "bgcolor": "7" - }, - "21,32": { - "contents": "", - "bgcolor": "7" - }, - "21,33": { - "contents": "", - "bgcolor": "7" - }, - "21,34": { - "contents": "", - "bgcolor": "7" - }, - "21,35": { - "contents": "", - "bgcolor": "7" - }, - "21,36": { - "contents": "", - "bgcolor": "7" - }, - "21,37": { - "contents": "", - "bgcolor": "7" - }, - "21,38": { - "contents": "", - "bgcolor": "7" - }, - "21,39": { - "contents": "", - "bgcolor": "7" - }, - "21,4": { - "contents": "", - "bgcolor": "7" - }, - "21,40": { - "contents": "", - "bgcolor": "7" - }, - "21,41": { - "contents": "", - "bgcolor": "7" - }, - "21,42": { - "contents": "", - "bgcolor": "7" - }, - "21,43": { - "contents": "", - "bgcolor": "7" - }, - "21,44": { - "contents": "", - "bgcolor": "7" - }, - "21,45": { - "contents": "", - "bgcolor": "7" - }, - "21,46": { - "contents": "", - "bgcolor": "7" - }, - "21,47": { - "contents": "", - "bgcolor": "7" - }, - "21,48": { - "contents": "", - "bgcolor": "7" - }, - "21,49": { - "contents": "", - "bgcolor": "7" - }, - "21,5": { - "contents": "", - "bgcolor": "7" - }, - "21,50": { - "contents": "", - "bgcolor": "7" - }, - "21,51": { - "contents": "", - "bgcolor": "7" - }, - "21,52": { - "contents": "", - "bgcolor": "7" - }, - "21,53": { - "contents": "", - "bgcolor": "7" - }, - "21,54": { - "contents": "", - "bgcolor": "7" - }, - "21,55": { - "contents": "", - "bgcolor": "7" - }, - "21,56": { - "contents": "", - "bgcolor": "7" - }, - "21,57": { - "contents": "", - "bgcolor": "7" - }, - "21,58": { - "contents": "", - "bgcolor": "7" - }, - "21,59": { - "contents": "", - "bgcolor": "7" - }, - "21,6": { - "contents": "", - "bgcolor": "7" - }, - "21,60": { - "contents": "", - "bgcolor": "7" - }, - "21,61": { - "contents": "", - "bgcolor": "7" - }, - "21,62": { - "contents": "", - "bgcolor": "7" - }, - "21,63": { - "contents": "", - "bgcolor": "7" - }, - "21,64": { - "contents": "", - "bgcolor": "7" - }, - "21,65": { - "contents": "", - "bgcolor": "7" - }, - "21,66": { - "contents": "", - "bgcolor": "7" - }, - "21,67": { - "contents": "", - "bgcolor": "7" - }, - "21,68": { - "contents": "", - "bgcolor": "7" - }, - "21,69": { - "contents": "", - "bgcolor": "7" - }, - "21,7": { - "contents": "", - "bgcolor": "7" - }, - "21,70": { - "contents": "", - "bgcolor": "7" - }, - "21,71": { - "contents": "", - "bgcolor": "7" - }, - "21,72": { - "contents": "", - "bgcolor": "7" - }, - "21,73": { - "contents": "", - "bgcolor": "7" - }, - "21,74": { - "contents": "", - "bgcolor": "7" - }, - "21,75": { - "contents": "", - "bgcolor": "7" - }, - "21,76": { - "contents": "", - "bgcolor": "7" - }, - "21,77": { - "contents": "", - "bgcolor": "7" - }, - "21,78": { - "contents": "", - "bgcolor": "7" - }, - "21,79": { - "contents": "", - "bgcolor": "7" - }, - "21,8": { - "contents": "", - "bgcolor": "7" - }, - "21,9": { - "contents": "", - "bgcolor": "7" - }, - "22,0": { - "contents": "", - "bgcolor": "7" - }, - "22,1": { - "contents": "", - "bgcolor": "7" - }, - "22,10": { - "contents": "", - "bgcolor": "7" - }, - "22,11": { - "contents": "", - "bgcolor": "7" - }, - "22,12": { - "contents": "", - "bgcolor": "7" - }, - "22,13": { - "contents": "", - "bgcolor": "7" - }, - "22,14": { - "contents": "", - "bgcolor": "7" - }, - "22,15": { - "contents": "", - "bgcolor": "7" - }, - "22,16": { - "contents": "", - "bgcolor": "7" - }, - "22,17": { - "contents": "", - "bgcolor": "7" - }, - "22,18": { - "contents": "", - "bgcolor": "7" - }, - "22,19": { - "contents": "", - "bgcolor": "7" - }, - "22,2": { - "contents": "", - "bgcolor": "7" - }, - "22,20": { - "contents": "", - "bgcolor": "7" - }, - "22,21": { - "contents": "", - "bgcolor": "7" - }, - "22,22": { - "contents": "", - "bgcolor": "7" - }, - "22,23": { - "contents": "", - "bgcolor": "7" - }, - "22,24": { - "contents": "", - "bgcolor": "7" - }, - "22,25": { - "contents": "", - "bgcolor": "7" - }, - "22,26": { - "contents": "", - "bgcolor": "7" - }, - "22,27": { - "contents": "", - "bgcolor": "7" - }, - "22,28": { - "contents": "", - "bgcolor": "7" - }, - "22,29": { - "contents": "", - "bgcolor": "7" - }, - "22,3": { - "contents": "", - "bgcolor": "7" - }, - "22,30": { - "contents": "", - "bgcolor": "7" - }, - "22,31": { - "contents": "", - "bgcolor": "7" - }, - "22,32": { - "contents": "", - "bgcolor": "7" - }, - "22,33": { - "contents": "", - "bgcolor": "7" - }, - "22,34": { - "contents": "", - "bgcolor": "7" - }, - "22,35": { - "contents": "", - "bgcolor": "7" - }, - "22,36": { - "contents": "", - "bgcolor": "7" - }, - "22,37": { - "contents": "", - "bgcolor": "7" - }, - "22,38": { - "contents": "", - "bgcolor": "7" - }, - "22,39": { - "contents": "", - "bgcolor": "7" - }, - "22,4": { - "contents": "", - "bgcolor": "7" - }, - "22,40": { - "contents": "", - "bgcolor": "7" - }, - "22,41": { - "contents": "", - "bgcolor": "7" - }, - "22,42": { - "contents": "", - "bgcolor": "7" - }, - "22,43": { - "contents": "", - "bgcolor": "7" - }, - "22,44": { - "contents": "", - "bgcolor": "7" - }, - "22,45": { - "contents": "", - "bgcolor": "7" - }, - "22,46": { - "contents": "", - "bgcolor": "7" - }, - "22,47": { - "contents": "", - "bgcolor": "7" - }, - "22,48": { - "contents": "", - "bgcolor": "7" - }, - "22,49": { - "contents": "", - "bgcolor": "7" - }, - "22,5": { - "contents": "", - "bgcolor": "7" - }, - "22,50": { - "contents": "", - "bgcolor": "7" - }, - "22,51": { - "contents": "", - "bgcolor": "7" - }, - "22,52": { - "contents": "", - "bgcolor": "7" - }, - "22,53": { - "contents": "", - "bgcolor": "7" - }, - "22,54": { - "contents": "", - "bgcolor": "7" - }, - "22,55": { - "contents": "", - "bgcolor": "7" - }, - "22,56": { - "contents": "", - "bgcolor": "7" - }, - "22,57": { - "contents": "", - "bgcolor": "7" - }, - "22,58": { - "contents": "", - "bgcolor": "7" - }, - "22,59": { - "contents": "", - "bgcolor": "7" - }, - "22,6": { - "contents": "", - "bgcolor": "7" - }, - "22,60": { - "contents": "", - "bgcolor": "7" - }, - "22,61": { - "contents": "", - "bgcolor": "7" - }, - "22,62": { - "contents": "", - "bgcolor": "7" - }, - "22,63": { - "contents": "", - "bgcolor": "7" - }, - "22,64": { - "contents": "", - "bgcolor": "7" - }, - "22,65": { - "contents": "", - "bgcolor": "7" - }, - "22,66": { - "contents": "", - "bgcolor": "7" - }, - "22,67": { - "contents": "", - "bgcolor": "7" - }, - "22,68": { - "contents": "", - "bgcolor": "7" - }, - "22,69": { - "contents": "", - "bgcolor": "7" - }, - "22,7": { - "contents": "", - "bgcolor": "7" - }, - "22,70": { - "contents": "", - "bgcolor": "7" - }, - "22,71": { - "contents": "", - "bgcolor": "7" - }, - "22,72": { - "contents": "", - "bgcolor": "7" - }, - "22,73": { - "contents": "", - "bgcolor": "7" - }, - "22,74": { - "contents": "", - "bgcolor": "7" - }, - "22,75": { - "contents": "", - "bgcolor": "7" - }, - "22,76": { - "contents": "", - "bgcolor": "7" - }, - "22,77": { - "contents": "", - "bgcolor": "7" - }, - "22,78": { - "contents": "", - "bgcolor": "7" - }, - "22,79": { - "contents": "", - "bgcolor": "7" - }, - "22,8": { - "contents": "", - "bgcolor": "7" - }, - "22,9": { - "contents": "", - "bgcolor": "7" - }, - "23,0": { - "contents": "", - "bgcolor": "7" - }, - "23,1": { - "contents": "", - "bgcolor": "7" - }, - "23,10": { - "contents": "", - "bgcolor": "7" - }, - "23,11": { - "contents": "", - "bgcolor": "7" - }, - "23,12": { - "contents": "", - "bgcolor": "7" - }, - "23,13": { - "contents": "", - "bgcolor": "7" - }, - "23,14": { - "contents": "", - "bgcolor": "7" - }, - "23,15": { - "contents": "", - "bgcolor": "7" - }, - "23,16": { - "contents": "", - "bgcolor": "7" - }, - "23,17": { - "contents": "", - "bgcolor": "7" - }, - "23,18": { - "contents": "", - "bgcolor": "7" - }, - "23,19": { - "contents": "", - "bgcolor": "7" - }, - "23,2": { - "contents": "", - "bgcolor": "7" - }, - "23,20": { - "contents": "", - "bgcolor": "7" - }, - "23,21": { - "contents": "", - "bgcolor": "7" - }, - "23,22": { - "contents": "", - "bgcolor": "7" - }, - "23,23": { - "contents": "", - "bgcolor": "7" - }, - "23,24": { - "contents": "", - "bgcolor": "7" - }, - "23,25": { - "contents": "", - "bgcolor": "7" - }, - "23,26": { - "contents": "", - "bgcolor": "7" - }, - "23,27": { - "contents": "", - "bgcolor": "7" - }, - "23,28": { - "contents": "", - "bgcolor": "7" - }, - "23,29": { - "contents": "", - "bgcolor": "7" - }, - "23,3": { - "contents": "", - "bgcolor": "7" - }, - "23,30": { - "contents": "", - "bgcolor": "7" - }, - "23,31": { - "contents": "", - "bgcolor": "7" - }, - "23,32": { - "contents": "", - "bgcolor": "7" - }, - "23,33": { - "contents": "", - "bgcolor": "7" - }, - "23,34": { - "contents": "", - "bgcolor": "7" - }, - "23,35": { - "contents": "", - "bgcolor": "7" - }, - "23,36": { - "contents": "", - "bgcolor": "7" - }, - "23,37": { - "contents": "", - "bgcolor": "7" - }, - "23,38": { - "contents": "", - "bgcolor": "7" - }, - "23,39": { - "contents": "", - "bgcolor": "7" - }, - "23,4": { - "contents": "", - "bgcolor": "7" - }, - "23,40": { - "contents": "", - "bgcolor": "7" - }, - "23,41": { - "contents": "", - "bgcolor": "7" - }, - "23,42": { - "contents": "", - "bgcolor": "7" - }, - "23,43": { - "contents": "", - "bgcolor": "7" - }, - "23,44": { - "contents": "", - "bgcolor": "7" - }, - "23,45": { - "contents": "", - "bgcolor": "7" - }, - "23,46": { - "contents": "", - "bgcolor": "7" - }, - "23,47": { - "contents": "", - "bgcolor": "7" - }, - "23,48": { - "contents": "", - "bgcolor": "7" - }, - "23,49": { - "contents": "", - "bgcolor": "7" - }, - "23,5": { - "contents": "", - "bgcolor": "7" - }, - "23,50": { - "contents": "", - "bgcolor": "7" - }, - "23,51": { - "contents": "", - "bgcolor": "7" - }, - "23,52": { - "contents": "", - "bgcolor": "7" - }, - "23,53": { - "contents": "", - "bgcolor": "7" - }, - "23,54": { - "contents": "", - "bgcolor": "7" - }, - "23,55": { - "contents": "", - "bgcolor": "7" - }, - "23,56": { - "contents": "", - "bgcolor": "7" - }, - "23,57": { - "contents": "", - "bgcolor": "7" - }, - "23,58": { - "contents": "", - "bgcolor": "7" - }, - "23,59": { - "contents": "", - "bgcolor": "7" - }, - "23,6": { - "contents": "", - "bgcolor": "7" - }, - "23,60": { - "contents": "", - "bgcolor": "7" - }, - "23,61": { - "contents": "", - "bgcolor": "7" - }, - "23,62": { - "contents": "", - "bgcolor": "7" - }, - "23,63": { - "contents": "", - "bgcolor": "7" - }, - "23,64": { - "contents": "", - "bgcolor": "7" - }, - "23,65": { - "contents": "", - "bgcolor": "7" - }, - "23,66": { - "contents": "", - "bgcolor": "7" - }, - "23,67": { - "contents": "", - "bgcolor": "7" - }, - "23,68": { - "contents": "", - "bgcolor": "7" - }, - "23,69": { - "contents": "", - "bgcolor": "7" - }, - "23,7": { - "contents": "", - "bgcolor": "7" - }, - "23,70": { - "contents": "", - "bgcolor": "7" - }, - "23,71": { - "contents": "", - "bgcolor": "7" - }, - "23,72": { - "contents": "", - "bgcolor": "7" - }, - "23,73": { - "contents": "", - "bgcolor": "7" - }, - "23,74": { - "contents": "", - "bgcolor": "7" - }, - "23,75": { - "contents": "", - "bgcolor": "7" - }, - "23,76": { - "contents": "", - "bgcolor": "7" - }, - "23,77": { - "contents": "", - "bgcolor": "7" - }, - "23,78": { - "contents": "", - "bgcolor": "7" - }, - "23,79": { - "contents": "", - "bgcolor": "7" - }, - "23,8": { - "contents": "", - "bgcolor": "7" - }, - "23,9": { - "contents": "", - "bgcolor": "7" - }, - "3,0": { - "contents": "", - "bgcolor": "7" - }, - "3,1": { - "contents": "", - "bgcolor": "7" - }, - "3,10": { - "contents": "", - "bgcolor": "7" - }, - "3,11": { - "contents": "", - "bgcolor": "7" - }, - "3,12": { - "contents": "", - "bgcolor": "7" - }, - "3,13": { - "contents": "", - "bgcolor": "7" - }, - "3,14": { - "contents": "", - "bgcolor": "7" - }, - "3,15": { - "contents": "", - "bgcolor": "7" - }, - "3,16": { - "contents": "", - "bgcolor": "7" - }, - "3,17": { - "contents": "", - "bgcolor": "7" - }, - "3,18": { - "contents": "", - "bgcolor": "7" - }, - "3,19": { - "contents": "", - "bgcolor": "7" - }, - "3,2": { - "contents": "", - "bgcolor": "7" - }, - "3,20": { - "contents": "", - "bgcolor": "7" - }, - "3,21": { - "contents": "", - "bgcolor": "7" - }, - "3,22": { - "contents": "", - "bgcolor": "7" - }, - "3,23": { - "contents": "", - "bgcolor": "7" - }, - "3,24": { - "contents": "", - "bgcolor": "7" - }, - "3,25": { - "contents": "", - "bgcolor": "7" - }, - "3,26": { - "contents": "", - "bgcolor": "7" - }, - "3,27": { - "contents": "", - "bgcolor": "7" - }, - "3,28": { - "contents": "", - "bgcolor": "7" - }, - "3,29": { - "contents": "", - "bgcolor": "7" - }, - "3,3": { - "contents": "", - "bgcolor": "7" - }, - "3,30": { - "contents": "", - "bgcolor": "7" - }, - "3,31": { - "contents": "", - "bgcolor": "7" - }, - "3,32": { - "contents": "", - "bgcolor": "7" - }, - "3,33": { - "contents": "", - "bgcolor": "7" - }, - "3,34": { - "contents": "", - "bgcolor": "7" - }, - "3,35": { - "contents": "", - "bgcolor": "7" - }, - "3,36": { - "contents": "", - "bgcolor": "7" - }, - "3,37": { - "contents": "", - "bgcolor": "7" - }, - "3,38": { - "contents": "", - "bgcolor": "7" - }, - "3,39": { - "contents": "", - "bgcolor": "7" - }, - "3,4": { - "contents": "", - "bgcolor": "7" - }, - "3,40": { - "contents": "", - "bgcolor": "7" - }, - "3,41": { - "contents": "", - "bgcolor": "7" - }, - "3,42": { - "contents": "", - "bgcolor": "7" - }, - "3,43": { - "contents": "", - "bgcolor": "7" - }, - "3,44": { - "contents": "", - "bgcolor": "7" - }, - "3,45": { - "contents": "", - "bgcolor": "7" - }, - "3,46": { - "contents": "", - "bgcolor": "7" - }, - "3,47": { - "contents": "", - "bgcolor": "7" - }, - "3,48": { - "contents": "", - "bgcolor": "7" - }, - "3,49": { - "contents": "", - "bgcolor": "7" - }, - "3,5": { - "contents": "", - "bgcolor": "7" - }, - "3,50": { - "contents": "", - "bgcolor": "7" - }, - "3,51": { - "contents": "", - "bgcolor": "7" - }, - "3,52": { - "contents": "", - "bgcolor": "7" - }, - "3,53": { - "contents": "", - "bgcolor": "7" - }, - "3,54": { - "contents": "", - "bgcolor": "7" - }, - "3,55": { - "contents": "", - "bgcolor": "7" - }, - "3,56": { - "contents": "", - "bgcolor": "7" - }, - "3,57": { - "contents": "", - "bgcolor": "7" - }, - "3,58": { - "contents": "", - "bgcolor": "7" - }, - "3,59": { - "contents": "", - "bgcolor": "7" - }, - "3,6": { - "contents": "", - "bgcolor": "7" - }, - "3,60": { - "contents": "", - "bgcolor": "7" - }, - "3,61": { - "contents": "", - "bgcolor": "7" - }, - "3,62": { - "contents": "", - "bgcolor": "7" - }, - "3,63": { - "contents": "", - "bgcolor": "7" - }, - "3,64": { - "contents": "", - "bgcolor": "7" - }, - "3,65": { - "contents": "", - "bgcolor": "7" - }, - "3,66": { - "contents": "", - "bgcolor": "7" - }, - "3,67": { - "contents": "", - "bgcolor": "7" - }, - "3,68": { - "contents": "", - "bgcolor": "7" - }, - "3,69": { - "contents": "", - "bgcolor": "7" - }, - "3,7": { - "contents": "", - "bgcolor": "7" - }, - "3,70": { - "contents": "", - "bgcolor": "7" - }, - "3,71": { - "contents": "", - "bgcolor": "7" - }, - "3,72": { - "contents": "", - "bgcolor": "7" - }, - "3,73": { - "contents": "", - "bgcolor": "7" - }, - "3,74": { - "contents": "", - "bgcolor": "7" - }, - "3,75": { - "contents": "", - "bgcolor": "7" - }, - "3,76": { - "contents": "", - "bgcolor": "7" - }, - "3,77": { - "contents": "", - "bgcolor": "7" - }, - "3,78": { - "contents": "", - "bgcolor": "7" - }, - "3,79": { - "contents": "", - "bgcolor": "7" - }, - "3,8": { - "contents": "", - "bgcolor": "7" - }, - "3,9": { - "contents": "", - "bgcolor": "7" - }, - "4,0": { - "contents": "", - "bgcolor": "7" - }, - "4,1": { - "contents": "", - "bgcolor": "7" - }, - "4,10": { - "contents": "", - "bgcolor": "7" - }, - "4,11": { - "contents": "", - "bgcolor": "7" - }, - "4,12": { - "contents": "", - "bgcolor": "7" - }, - "4,13": { - "contents": "", - "bgcolor": "7" - }, - "4,14": { - "contents": "", - "bgcolor": "7" - }, - "4,15": { - "contents": "", - "bgcolor": "7" - }, - "4,16": { - "contents": "", - "bgcolor": "7" - }, - "4,17": { - "contents": "", - "bgcolor": "7" - }, - "4,18": { - "contents": "", - "bgcolor": "7" - }, - "4,19": { - "contents": "", - "bgcolor": "7" - }, - "4,2": { - "contents": "", - "bgcolor": "7" - }, - "4,20": { - "contents": "", - "bgcolor": "7" - }, - "4,21": { - "contents": "", - "bgcolor": "7" - }, - "4,22": { - "contents": "", - "bgcolor": "7" - }, - "4,23": { - "contents": "", - "bgcolor": "7" - }, - "4,24": { - "contents": "", - "bgcolor": "7" - }, - "4,25": { - "contents": "", - "bgcolor": "7" - }, - "4,26": { - "contents": "", - "bgcolor": "7" - }, - "4,27": { - "contents": "", - "bgcolor": "7" - }, - "4,28": { - "contents": "", - "bgcolor": "7" - }, - "4,29": { - "contents": "", - "bgcolor": "7" - }, - "4,3": { - "contents": "", - "bgcolor": "7" - }, - "4,30": { - "contents": "", - "bgcolor": "7" - }, - "4,31": { - "contents": "", - "bgcolor": "7" - }, - "4,32": { - "contents": "", - "bgcolor": "7" - }, - "4,33": { - "contents": "", - "bgcolor": "7" - }, - "4,34": { - "contents": "", - "bgcolor": "7" - }, - "4,35": { - "contents": "", - "bgcolor": "7" - }, - "4,36": { - "contents": "", - "bgcolor": "7" - }, - "4,37": { - "contents": "", - "bgcolor": "7" - }, - "4,38": { - "contents": "", - "bgcolor": "7" - }, - "4,39": { - "contents": "", - "bgcolor": "7" - }, - "4,4": { - "contents": "", - "bgcolor": "7" - }, - "4,40": { - "contents": "", - "bgcolor": "7" - }, - "4,41": { - "contents": "", - "bgcolor": "7" - }, - "4,42": { - "contents": "", - "bgcolor": "7" - }, - "4,43": { - "contents": "", - "bgcolor": "7" - }, - "4,44": { - "contents": "", - "bgcolor": "7" - }, - "4,45": { - "contents": "", - "bgcolor": "7" - }, - "4,46": { - "contents": "", - "bgcolor": "7" - }, - "4,47": { - "contents": "", - "bgcolor": "7" - }, - "4,48": { - "contents": "", - "bgcolor": "7" - }, - "4,49": { - "contents": "", - "bgcolor": "7" - }, - "4,5": { - "contents": "", - "bgcolor": "7" - }, - "4,50": { - "contents": "", - "bgcolor": "7" - }, - "4,51": { - "contents": "", - "bgcolor": "7" - }, - "4,52": { - "contents": "", - "bgcolor": "7" - }, - "4,53": { - "contents": "", - "bgcolor": "7" - }, - "4,54": { - "contents": "", - "bgcolor": "7" - }, - "4,55": { - "contents": "", - "bgcolor": "7" - }, - "4,56": { - "contents": "", - "bgcolor": "7" - }, - "4,57": { - "contents": "", - "bgcolor": "7" - }, - "4,58": { - "contents": "", - "bgcolor": "7" - }, - "4,59": { - "contents": "", - "bgcolor": "7" - }, - "4,6": { - "contents": "", - "bgcolor": "7" - }, - "4,60": { - "contents": "", - "bgcolor": "7" - }, - "4,61": { - "contents": "", - "bgcolor": "7" - }, - "4,62": { - "contents": "", - "bgcolor": "7" - }, - "4,63": { - "contents": "", - "bgcolor": "7" - }, - "4,64": { - "contents": "", - "bgcolor": "7" - }, - "4,65": { - "contents": "", - "bgcolor": "7" - }, - "4,66": { - "contents": "", - "bgcolor": "7" - }, - "4,67": { - "contents": "", - "bgcolor": "7" - }, - "4,68": { - "contents": "", - "bgcolor": "7" - }, - "4,69": { - "contents": "", - "bgcolor": "7" - }, - "4,7": { - "contents": "", - "bgcolor": "7" - }, - "4,70": { - "contents": "", - "bgcolor": "7" - }, - "4,71": { - "contents": "", - "bgcolor": "7" - }, - "4,72": { - "contents": "", - "bgcolor": "7" - }, - "4,73": { - "contents": "", - "bgcolor": "7" - }, - "4,74": { - "contents": "", - "bgcolor": "7" - }, - "4,75": { - "contents": "", - "bgcolor": "7" - }, - "4,76": { - "contents": "", - "bgcolor": "7" - }, - "4,77": { - "contents": "", - "bgcolor": "7" - }, - "4,78": { - "contents": "", - "bgcolor": "7" - }, - "4,79": { - "contents": "", - "bgcolor": "7" - }, - "4,8": { - "contents": "", - "bgcolor": "7" - }, - "4,9": { - "contents": "", - "bgcolor": "7" - }, - "5,0": { - "contents": "", - "bgcolor": "7" - }, - "5,1": { - "contents": "", - "bgcolor": "7" - }, - "5,10": { - "contents": "", - "bgcolor": "7" - }, - "5,11": { - "contents": "", - "bgcolor": "7" - }, - "5,12": { - "contents": "", - "bgcolor": "7" - }, - "5,13": { - "contents": "", - "bgcolor": "7" - }, - "5,14": { - "contents": "", - "bgcolor": "7" - }, - "5,15": { - "contents": "", - "bgcolor": "7" - }, - "5,16": { - "contents": "", - "bgcolor": "7" - }, - "5,17": { - "contents": "", - "bgcolor": "7" - }, - "5,18": { - "contents": "", - "bgcolor": "7" - }, - "5,19": { - "contents": "", - "bgcolor": "7" - }, - "5,2": { - "contents": "", - "bgcolor": "7" - }, - "5,20": { - "contents": "", - "bgcolor": "7" - }, - "5,21": { - "contents": "", - "bgcolor": "7" - }, - "5,22": { - "contents": "", - "bgcolor": "7" - }, - "5,23": { - "contents": "", - "bgcolor": "7" - }, - "5,24": { - "contents": "", - "bgcolor": "7" - }, - "5,25": { - "contents": "", - "bgcolor": "7" - }, - "5,26": { - "contents": "", - "bgcolor": "7" - }, - "5,27": { - "contents": "", - "bgcolor": "7" - }, - "5,28": { - "contents": "", - "bgcolor": "7" - }, - "5,29": { - "contents": "", - "bgcolor": "7" - }, - "5,3": { - "contents": "", - "bgcolor": "7" - }, - "5,30": { - "contents": "", - "bgcolor": "7" - }, - "5,31": { - "contents": "", - "bgcolor": "7" - }, - "5,32": { - "contents": "", - "bgcolor": "7" - }, - "5,33": { - "contents": "", - "bgcolor": "7" - }, - "5,34": { - "contents": "", - "bgcolor": "7" - }, - "5,35": { - "contents": "", - "bgcolor": "7" - }, - "5,36": { - "contents": "", - "bgcolor": "7" - }, - "5,37": { - "contents": "", - "bgcolor": "7" - }, - "5,38": { - "contents": "", - "bgcolor": "7" - }, - "5,39": { - "contents": "", - "bgcolor": "7" - }, - "5,4": { - "contents": "", - "bgcolor": "7" - }, - "5,40": { - "contents": "", - "bgcolor": "7" - }, - "5,41": { - "contents": "", - "bgcolor": "7" - }, - "5,42": { - "contents": "", - "bgcolor": "7" - }, - "5,43": { - "contents": "", - "bgcolor": "7" - }, - "5,44": { - "contents": "", - "bgcolor": "7" - }, - "5,45": { - "contents": "", - "bgcolor": "7" - }, - "5,46": { - "contents": "", - "bgcolor": "7" - }, - "5,47": { - "contents": "", - "bgcolor": "7" - }, - "5,48": { - "contents": "", - "bgcolor": "7" - }, - "5,49": { - "contents": "", - "bgcolor": "7" - }, - "5,5": { - "contents": "", - "bgcolor": "7" - }, - "5,50": { - "contents": "", - "bgcolor": "7" - }, - "5,51": { - "contents": "", - "bgcolor": "7" - }, - "5,52": { - "contents": "", - "bgcolor": "7" - }, - "5,53": { - "contents": "", - "bgcolor": "7" - }, - "5,54": { - "contents": "", - "bgcolor": "7" - }, - "5,55": { - "contents": "", - "bgcolor": "7" - }, - "5,56": { - "contents": "", - "bgcolor": "7" - }, - "5,57": { - "contents": "", - "bgcolor": "7" - }, - "5,58": { - "contents": "", - "bgcolor": "7" - }, - "5,59": { - "contents": "", - "bgcolor": "7" - }, - "5,6": { - "contents": "", - "bgcolor": "7" - }, - "5,60": { - "contents": "", - "bgcolor": "7" - }, - "5,61": { - "contents": "", - "bgcolor": "7" - }, - "5,62": { - "contents": "", - "bgcolor": "7" - }, - "5,63": { - "contents": "", - "bgcolor": "7" - }, - "5,64": { - "contents": "", - "bgcolor": "7" - }, - "5,65": { - "contents": "", - "bgcolor": "7" - }, - "5,66": { - "contents": "", - "bgcolor": "7" - }, - "5,67": { - "contents": "", - "bgcolor": "7" - }, - "5,68": { - "contents": "", - "bgcolor": "7" - }, - "5,69": { - "contents": "", - "bgcolor": "7" - }, - "5,7": { - "contents": "", - "bgcolor": "7" - }, - "5,70": { - "contents": "", - "bgcolor": "7" - }, - "5,71": { - "contents": "", - "bgcolor": "7" - }, - "5,72": { - "contents": "", - "bgcolor": "7" - }, - "5,73": { - "contents": "", - "bgcolor": "7" - }, - "5,74": { - "contents": "", - "bgcolor": "7" - }, - "5,75": { - "contents": "", - "bgcolor": "7" - }, - "5,76": { - "contents": "", - "bgcolor": "7" - }, - "5,77": { - "contents": "", - "bgcolor": "7" - }, - "5,78": { - "contents": "", - "bgcolor": "7" - }, - "5,79": { - "contents": "", - "bgcolor": "7" - }, - "5,8": { - "contents": "", - "bgcolor": "7" - }, - "5,9": { - "contents": "", - "bgcolor": "7" - }, - "6,0": { - "contents": "", - "bgcolor": "7" - }, - "6,1": { - "contents": "", - "bgcolor": "7" - }, - "6,10": { - "contents": "", - "bgcolor": "7" - }, - "6,11": { - "contents": "", - "bgcolor": "7" - }, - "6,12": { - "contents": "", - "bgcolor": "7" - }, - "6,13": { - "contents": "", - "bgcolor": "7" - }, - "6,14": { - "contents": "", - "bgcolor": "7" - }, - "6,15": { - "contents": "", - "bgcolor": "7" - }, - "6,16": { - "contents": "", - "bgcolor": "7" - }, - "6,17": { - "contents": "", - "bgcolor": "7" - }, - "6,18": { - "contents": "", - "bgcolor": "7" - }, - "6,19": { - "contents": "", - "bgcolor": "7" - }, - "6,2": { - "contents": "", - "bgcolor": "7" - }, - "6,20": { - "contents": "", - "bgcolor": "7" - }, - "6,21": { - "contents": "", - "bgcolor": "7" - }, - "6,22": { - "contents": "", - "bgcolor": "7" - }, - "6,23": { - "contents": "", - "bgcolor": "7" - }, - "6,24": { - "contents": "", - "bgcolor": "7" - }, - "6,25": { - "contents": "", - "bgcolor": "7" - }, - "6,26": { - "contents": "", - "bgcolor": "7" - }, - "6,27": { - "contents": "", - "bgcolor": "7" - }, - "6,28": { - "contents": "", - "bgcolor": "7" - }, - "6,29": { - "contents": "", - "bgcolor": "7" - }, - "6,3": { - "contents": "", - "bgcolor": "7" - }, - "6,30": { - "contents": "", - "bgcolor": "7" - }, - "6,31": { - "contents": "", - "bgcolor": "7" - }, - "6,32": { - "contents": "", - "bgcolor": "7" - }, - "6,33": { - "contents": "", - "bgcolor": "7" - }, - "6,34": { - "contents": "", - "bgcolor": "7" - }, - "6,35": { - "contents": "", - "bgcolor": "7" - }, - "6,36": { - "contents": "", - "bgcolor": "7" - }, - "6,37": { - "contents": "", - "bgcolor": "7" - }, - "6,38": { - "contents": "", - "bgcolor": "7" - }, - "6,39": { - "contents": "", - "bgcolor": "7" - }, - "6,4": { - "contents": "", - "bgcolor": "7" - }, - "6,40": { - "contents": "", - "bgcolor": "7" - }, - "6,41": { - "contents": "", - "bgcolor": "7" - }, - "6,42": { - "contents": "", - "bgcolor": "7" - }, - "6,43": { - "contents": "", - "bgcolor": "7" - }, - "6,44": { - "contents": "", - "bgcolor": "7" - }, - "6,45": { - "contents": "", - "bgcolor": "7" - }, - "6,46": { - "contents": "", - "bgcolor": "7" - }, - "6,47": { - "contents": "", - "bgcolor": "7" - }, - "6,48": { - "contents": "", - "bgcolor": "7" - }, - "6,49": { - "contents": "", - "bgcolor": "7" - }, - "6,5": { - "contents": "", - "bgcolor": "7" - }, - "6,50": { - "contents": "", - "bgcolor": "7" - }, - "6,51": { - "contents": "", - "bgcolor": "7" - }, - "6,52": { - "contents": "", - "bgcolor": "7" - }, - "6,53": { - "contents": "", - "bgcolor": "7" - }, - "6,54": { - "contents": "", - "bgcolor": "7" - }, - "6,55": { - "contents": "", - "bgcolor": "7" - }, - "6,56": { - "contents": "", - "bgcolor": "7" - }, - "6,57": { - "contents": "", - "bgcolor": "7" - }, - "6,58": { - "contents": "", - "bgcolor": "7" - }, - "6,59": { - "contents": "", - "bgcolor": "7" - }, - "6,6": { - "contents": "", - "bgcolor": "7" - }, - "6,60": { - "contents": "", - "bgcolor": "7" - }, - "6,61": { - "contents": "", - "bgcolor": "7" - }, - "6,62": { - "contents": "", - "bgcolor": "7" - }, - "6,63": { - "contents": "", - "bgcolor": "7" - }, - "6,64": { - "contents": "", - "bgcolor": "7" - }, - "6,65": { - "contents": "", - "bgcolor": "7" - }, - "6,66": { - "contents": "", - "bgcolor": "7" - }, - "6,67": { - "contents": "", - "bgcolor": "7" - }, - "6,68": { - "contents": "", - "bgcolor": "7" - }, - "6,69": { - "contents": "", - "bgcolor": "7" - }, - "6,7": { - "contents": "", - "bgcolor": "7" - }, - "6,70": { - "contents": "", - "bgcolor": "7" - }, - "6,71": { - "contents": "", - "bgcolor": "7" - }, - "6,72": { - "contents": "", - "bgcolor": "7" - }, - "6,73": { - "contents": "", - "bgcolor": "7" - }, - "6,74": { - "contents": "", - "bgcolor": "7" - }, - "6,75": { - "contents": "", - "bgcolor": "7" - }, - "6,76": { - "contents": "", - "bgcolor": "7" - }, - "6,77": { - "contents": "", - "bgcolor": "7" - }, - "6,78": { - "contents": "", - "bgcolor": "7" - }, - "6,79": { - "contents": "", - "bgcolor": "7" - }, - "6,8": { - "contents": "", - "bgcolor": "7" - }, - "6,9": { - "contents": "", - "bgcolor": "7" - }, - "7,0": { - "contents": "", - "bgcolor": "7" - }, - "7,1": { - "contents": "", - "bgcolor": "7" - }, - "7,10": { - "contents": "", - "bgcolor": "7" - }, - "7,11": { - "contents": "", - "bgcolor": "7" - }, - "7,12": { - "contents": "", - "bgcolor": "7" - }, - "7,13": { - "contents": "", - "bgcolor": "7" - }, - "7,14": { - "contents": "", - "bgcolor": "7" - }, - "7,15": { - "contents": "", - "bgcolor": "7" - }, - "7,16": { - "contents": "", - "bgcolor": "7" - }, - "7,17": { - "contents": "", - "bgcolor": "7" - }, - "7,18": { - "contents": "", - "bgcolor": "7" - }, - "7,19": { - "contents": "", - "bgcolor": "7" - }, - "7,2": { - "contents": "", - "bgcolor": "7" - }, - "7,20": { - "contents": "", - "bgcolor": "7" - }, - "7,21": { - "contents": "", - "bgcolor": "7" - }, - "7,22": { - "contents": "", - "bgcolor": "7" - }, - "7,23": { - "contents": "", - "bgcolor": "7" - }, - "7,24": { - "contents": "", - "bgcolor": "7" - }, - "7,25": { - "contents": "", - "bgcolor": "7" - }, - "7,26": { - "contents": "", - "bgcolor": "7" - }, - "7,27": { - "contents": "", - "bgcolor": "7" - }, - "7,28": { - "contents": "", - "bgcolor": "7" - }, - "7,29": { - "contents": "", - "bgcolor": "7" - }, - "7,3": { - "contents": "", - "bgcolor": "7" - }, - "7,30": { - "contents": "", - "bgcolor": "7" - }, - "7,31": { - "contents": "", - "bgcolor": "7" - }, - "7,32": { - "contents": "", - "bgcolor": "7" - }, - "7,33": { - "contents": "", - "bgcolor": "7" - }, - "7,34": { - "contents": "", - "bgcolor": "7" - }, - "7,35": { - "contents": "", - "bgcolor": "7" - }, - "7,36": { - "contents": "", - "bgcolor": "7" - }, - "7,37": { - "contents": "", - "bgcolor": "7" - }, - "7,38": { - "contents": "", - "bgcolor": "7" - }, - "7,39": { - "contents": "", - "bgcolor": "7" - }, - "7,4": { - "contents": "", - "bgcolor": "7" - }, - "7,40": { - "contents": "", - "bgcolor": "7" - }, - "7,41": { - "contents": "", - "bgcolor": "7" - }, - "7,42": { - "contents": "", - "bgcolor": "7" - }, - "7,43": { - "contents": "", - "bgcolor": "7" - }, - "7,44": { - "contents": "", - "bgcolor": "7" - }, - "7,45": { - "contents": "", - "bgcolor": "7" - }, - "7,46": { - "contents": "", - "bgcolor": "7" - }, - "7,47": { - "contents": "", - "bgcolor": "7" - }, - "7,48": { - "contents": "", - "bgcolor": "7" - }, - "7,49": { - "contents": "", - "bgcolor": "7" - }, - "7,5": { - "contents": "", - "bgcolor": "7" - }, - "7,50": { - "contents": "", - "bgcolor": "7" - }, - "7,51": { - "contents": "", - "bgcolor": "7" - }, - "7,52": { - "contents": "", - "bgcolor": "7" - }, - "7,53": { - "contents": "", - "bgcolor": "7" - }, - "7,54": { - "contents": "", - "bgcolor": "7" - }, - "7,55": { - "contents": "", - "bgcolor": "7" - }, - "7,56": { - "contents": "", - "bgcolor": "7" - }, - "7,57": { - "contents": "", - "bgcolor": "7" - }, - "7,58": { - "contents": "", - "bgcolor": "7" - }, - "7,59": { - "contents": "", - "bgcolor": "7" - }, - "7,6": { - "contents": "", - "bgcolor": "7" - }, - "7,60": { - "contents": "", - "bgcolor": "7" - }, - "7,61": { - "contents": "", - "bgcolor": "7" - }, - "7,62": { - "contents": "", - "bgcolor": "7" - }, - "7,63": { - "contents": "", - "bgcolor": "7" - }, - "7,64": { - "contents": "", - "bgcolor": "7" - }, - "7,65": { - "contents": "", - "bgcolor": "7" - }, - "7,66": { - "contents": "", - "bgcolor": "7" - }, - "7,67": { - "contents": "", - "bgcolor": "7" - }, - "7,68": { - "contents": "", - "bgcolor": "7" - }, - "7,69": { - "contents": "", - "bgcolor": "7" - }, - "7,7": { - "contents": "", - "bgcolor": "7" - }, - "7,70": { - "contents": "", - "bgcolor": "7" - }, - "7,71": { - "contents": "", - "bgcolor": "7" - }, - "7,72": { - "contents": "", - "bgcolor": "7" - }, - "7,73": { - "contents": "", - "bgcolor": "7" - }, - "7,74": { - "contents": "", - "bgcolor": "7" - }, - "7,75": { - "contents": "", - "bgcolor": "7" - }, - "7,76": { - "contents": "", - "bgcolor": "7" - }, - "7,77": { - "contents": "", - "bgcolor": "7" - }, - "7,78": { - "contents": "", - "bgcolor": "7" - }, - "7,79": { - "contents": "", - "bgcolor": "7" - }, - "7,8": { - "contents": "", - "bgcolor": "7" - }, - "7,9": { - "contents": "", - "bgcolor": "7" - }, - "8,0": { - "contents": "", - "bgcolor": "7" - }, - "8,1": { - "contents": "", - "bgcolor": "7" - }, - "8,10": { - "contents": "", - "bgcolor": "7" - }, - "8,11": { - "contents": "", - "bgcolor": "7" - }, - "8,12": { - "contents": "", - "bgcolor": "7" - }, - "8,13": { - "contents": "", - "bgcolor": "7" - }, - "8,14": { - "contents": "", - "bgcolor": "7" - }, - "8,15": { - "contents": "", - "bgcolor": "7" - }, - "8,16": { - "contents": "", - "bgcolor": "7" - }, - "8,17": { - "contents": "", - "bgcolor": "7" - }, - "8,18": { - "contents": "", - "bgcolor": "7" - }, - "8,19": { - "contents": "", - "bgcolor": "7" - }, - "8,2": { - "contents": "", - "bgcolor": "7" - }, - "8,20": { - "contents": "", - "bgcolor": "7" - }, - "8,21": { - "contents": "", - "bgcolor": "7" - }, - "8,22": { - "contents": "", - "bgcolor": "7" - }, - "8,23": { - "contents": "", - "bgcolor": "7" - }, - "8,24": { - "contents": "", - "bgcolor": "7" - }, - "8,25": { - "contents": "", - "bgcolor": "7" - }, - "8,26": { - "contents": "", - "bgcolor": "7" - }, - "8,27": { - "contents": "", - "bgcolor": "7" - }, - "8,28": { - "contents": "", - "bgcolor": "7" - }, - "8,29": { - "contents": "", - "bgcolor": "7" - }, - "8,3": { - "contents": "", - "bgcolor": "7" - }, - "8,30": { - "contents": "", - "bgcolor": "7" - }, - "8,31": { - "contents": "", - "bgcolor": "7" - }, - "8,32": { - "contents": "", - "bgcolor": "7" - }, - "8,33": { - "contents": "", - "bgcolor": "7" - }, - "8,34": { - "contents": "", - "bgcolor": "7" - }, - "8,35": { - "contents": "", - "bgcolor": "7" - }, - "8,36": { - "contents": "", - "bgcolor": "7" - }, - "8,37": { - "contents": "", - "bgcolor": "7" - }, - "8,38": { - "contents": "", - "bgcolor": "7" - }, - "8,39": { - "contents": "", - "bgcolor": "7" - }, - "8,4": { - "contents": "", - "bgcolor": "7" - }, - "8,40": { - "contents": "", - "bgcolor": "7" - }, - "8,41": { - "contents": "", - "bgcolor": "7" - }, - "8,42": { - "contents": "", - "bgcolor": "7" - }, - "8,43": { - "contents": "", - "bgcolor": "7" - }, - "8,44": { - "contents": "", - "bgcolor": "7" - }, - "8,45": { - "contents": "", - "bgcolor": "7" - }, - "8,46": { - "contents": "", - "bgcolor": "7" - }, - "8,47": { - "contents": "", - "bgcolor": "7" - }, - "8,48": { - "contents": "", - "bgcolor": "7" - }, - "8,49": { - "contents": "", - "bgcolor": "7" - }, - "8,5": { - "contents": "", - "bgcolor": "7" - }, - "8,50": { - "contents": "", - "bgcolor": "7" - }, - "8,51": { - "contents": "", - "bgcolor": "7" - }, - "8,52": { - "contents": "", - "bgcolor": "7" - }, - "8,53": { - "contents": "", - "bgcolor": "7" - }, - "8,54": { - "contents": "", - "bgcolor": "7" - }, - "8,55": { - "contents": "", - "bgcolor": "7" - }, - "8,56": { - "contents": "", - "bgcolor": "7" - }, - "8,57": { - "contents": "", - "bgcolor": "7" - }, - "8,58": { - "contents": "", - "bgcolor": "7" - }, - "8,59": { - "contents": "", - "bgcolor": "7" - }, - "8,6": { - "contents": "", - "bgcolor": "7" - }, - "8,60": { - "contents": "", - "bgcolor": "7" - }, - "8,61": { - "contents": "", - "bgcolor": "7" - }, - "8,62": { - "contents": "", - "bgcolor": "7" - }, - "8,63": { - "contents": "", - "bgcolor": "7" - }, - "8,64": { - "contents": "", - "bgcolor": "7" - }, - "8,65": { - "contents": "", - "bgcolor": "7" - }, - "8,66": { - "contents": "", - "bgcolor": "7" - }, - "8,67": { - "contents": "", - "bgcolor": "7" - }, - "8,68": { - "contents": "", - "bgcolor": "7" - }, - "8,69": { - "contents": "", - "bgcolor": "7" - }, - "8,7": { - "contents": "", - "bgcolor": "7" - }, - "8,70": { - "contents": "", - "bgcolor": "7" - }, - "8,71": { - "contents": "", - "bgcolor": "7" - }, - "8,72": { - "contents": "", - "bgcolor": "7" - }, - "8,73": { - "contents": "", - "bgcolor": "7" - }, - "8,74": { - "contents": "", - "bgcolor": "7" - }, - "8,75": { - "contents": "", - "bgcolor": "7" - }, - "8,76": { - "contents": "", - "bgcolor": "7" - }, - "8,77": { - "contents": "", - "bgcolor": "7" - }, - "8,78": { - "contents": "", - "bgcolor": "7" - }, - "8,79": { - "contents": "", - "bgcolor": "7" - }, - "8,8": { - "contents": "", - "bgcolor": "7" - }, - "8,9": { - "contents": "", - "bgcolor": "7" - }, - "9,0": { - "contents": "", - "bgcolor": "7" - }, - "9,1": { - "contents": "", - "bgcolor": "7" - }, - "9,10": { - "contents": "", - "bgcolor": "7" - }, - "9,11": { - "contents": "", - "bgcolor": "7" - }, - "9,12": { - "contents": "", - "bgcolor": "7" - }, - "9,13": { - "contents": "", - "bgcolor": "7" - }, - "9,14": { - "contents": "", - "bgcolor": "7" - }, - "9,15": { - "contents": "", - "bgcolor": "7" - }, - "9,16": { - "contents": "", - "bgcolor": "7" - }, - "9,17": { - "contents": "", - "bgcolor": "7" - }, - "9,18": { - "contents": "", - "bgcolor": "7" - }, - "9,19": { - "contents": "", - "bgcolor": "7" - }, - "9,2": { - "contents": "", - "bgcolor": "7" - }, - "9,20": { - "contents": "", - "bgcolor": "7" - }, - "9,21": { - "contents": "", - "bgcolor": "7" - }, - "9,22": { - "contents": "", - "bgcolor": "7" - }, - "9,23": { - "contents": "", - "bgcolor": "7" - }, - "9,24": { - "contents": "", - "bgcolor": "7" - }, - "9,25": { - "contents": "", - "bgcolor": "7" - }, - "9,26": { - "contents": "", - "bgcolor": "7" - }, - "9,27": { - "contents": "", - "bgcolor": "7" - }, - "9,28": { - "contents": "", - "bgcolor": "7" - }, - "9,29": { - "contents": "", - "bgcolor": "7" - }, - "9,3": { - "contents": "", - "bgcolor": "7" - }, - "9,30": { - "contents": "", - "bgcolor": "7" - }, - "9,31": { - "contents": "", - "bgcolor": "7" - }, - "9,32": { - "contents": "", - "bgcolor": "7" - }, - "9,33": { - "contents": "", - "bgcolor": "7" - }, - "9,34": { - "contents": "", - "bgcolor": "7" - }, - "9,35": { - "contents": "", - "bgcolor": "7" - }, - "9,36": { - "contents": "", - "bgcolor": "7" - }, - "9,37": { - "contents": "", - "bgcolor": "7" - }, - "9,38": { - "contents": "", - "bgcolor": "7" - }, - "9,39": { - "contents": "", - "bgcolor": "7" - }, - "9,4": { - "contents": "", - "bgcolor": "7" - }, - "9,40": { - "contents": "", - "bgcolor": "7" - }, - "9,41": { - "contents": "", - "bgcolor": "7" - }, - "9,42": { - "contents": "", - "bgcolor": "7" - }, - "9,43": { - "contents": "", - "bgcolor": "7" - }, - "9,44": { - "contents": "", - "bgcolor": "7" - }, - "9,45": { - "contents": "", - "bgcolor": "7" - }, - "9,46": { - "contents": "", - "bgcolor": "7" - }, - "9,47": { - "contents": "", - "bgcolor": "7" - }, - "9,48": { - "contents": "", - "bgcolor": "7" - }, - "9,49": { - "contents": "", - "bgcolor": "7" - }, - "9,5": { - "contents": "", - "bgcolor": "7" - }, - "9,50": { - "contents": "", - "bgcolor": "7" - }, - "9,51": { - "contents": "", - "bgcolor": "7" - }, - "9,52": { - "contents": "", - "bgcolor": "7" - }, - "9,53": { - "contents": "", - "bgcolor": "7" - }, - "9,54": { - "contents": "", - "bgcolor": "7" - }, - "9,55": { - "contents": "", - "bgcolor": "7" - }, - "9,56": { - "contents": "", - "bgcolor": "7" - }, - "9,57": { - "contents": "", - "bgcolor": "7" - }, - "9,58": { - "contents": "", - "bgcolor": "7" - }, - "9,59": { - "contents": "", - "bgcolor": "7" - }, - "9,6": { - "contents": "", - "bgcolor": "7" - }, - "9,60": { - "contents": "", - "bgcolor": "7" - }, - "9,61": { - "contents": "", - "bgcolor": "7" - }, - "9,62": { - "contents": "", - "bgcolor": "7" - }, - "9,63": { - "contents": "", - "bgcolor": "7" - }, - "9,64": { - "contents": "", - "bgcolor": "7" - }, - "9,65": { - "contents": "", - "bgcolor": "7" - }, - "9,66": { - "contents": "", - "bgcolor": "7" - }, - "9,67": { - "contents": "", - "bgcolor": "7" - }, - "9,68": { - "contents": "", - "bgcolor": "7" - }, - "9,69": { - "contents": "", - "bgcolor": "7" - }, - "9,7": { - "contents": "", - "bgcolor": "7" - }, - "9,70": { - "contents": "", - "bgcolor": "7" - }, - "9,71": { - "contents": "", - "bgcolor": "7" - }, - "9,72": { - "contents": "", - "bgcolor": "7" - }, - "9,73": { - "contents": "", - "bgcolor": "7" - }, - "9,74": { - "contents": "", - "bgcolor": "7" - }, - "9,75": { - "contents": "", - "bgcolor": "7" - }, - "9,76": { - "contents": "", - "bgcolor": "7" - }, - "9,77": { - "contents": "", - "bgcolor": "7" - }, - "9,78": { - "contents": "", - "bgcolor": "7" - }, - "9,79": { - "contents": "", - "bgcolor": "7" - }, - "9,8": { - "contents": "", - "bgcolor": "7" - }, - "9,9": { - "contents": "", - "bgcolor": "7" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/13.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/13.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/14.json b/crates/turborepo-vt100/tests/data/fixtures/colors/14.json deleted file mode 100644 index 5752edc6a8ef0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/14.json +++ /dev/null @@ -1,7686 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,10": { - "contents": "", - "bgcolor": "7" - }, - "0,11": { - "contents": "", - "bgcolor": "7" - }, - "0,12": { - "contents": "", - "bgcolor": "7" - }, - "0,13": { - "contents": "", - "bgcolor": "7" - }, - "0,14": { - "contents": "", - "bgcolor": "7" - }, - "0,15": { - "contents": "", - "bgcolor": "7" - }, - "0,16": { - "contents": "", - "bgcolor": "7" - }, - "0,17": { - "contents": "", - "bgcolor": "7" - }, - "0,18": { - "contents": "", - "bgcolor": "7" - }, - "0,19": { - "contents": "", - "bgcolor": "7" - }, - "0,2": { - "contents": "o" - }, - "0,20": { - "contents": "", - "bgcolor": "7" - }, - "0,21": { - "contents": "", - "bgcolor": "7" - }, - "0,22": { - "contents": "", - "bgcolor": "7" - }, - "0,23": { - "contents": "", - "bgcolor": "7" - }, - "0,24": { - "contents": "", - "bgcolor": "7" - }, - "0,25": { - "contents": "", - "bgcolor": "7" - }, - "0,26": { - "contents": "", - "bgcolor": "7" - }, - "0,27": { - "contents": "", - "bgcolor": "7" - }, - "0,28": { - "contents": "", - "bgcolor": "7" - }, - "0,29": { - "contents": "", - "bgcolor": "7" - }, - "0,3": { - "contents": "", - "bgcolor": "7" - }, - "0,30": { - "contents": "", - "bgcolor": "7" - }, - "0,31": { - "contents": "", - "bgcolor": "7" - }, - "0,32": { - "contents": "", - "bgcolor": "7" - }, - "0,33": { - "contents": "", - "bgcolor": "7" - }, - "0,34": { - "contents": "", - "bgcolor": "7" - }, - "0,35": { - "contents": "", - "bgcolor": "7" - }, - "0,36": { - "contents": "", - "bgcolor": "7" - }, - "0,37": { - "contents": "", - "bgcolor": "7" - }, - "0,38": { - "contents": "", - "bgcolor": "7" - }, - "0,39": { - "contents": "", - "bgcolor": "7" - }, - "0,4": { - "contents": "", - "bgcolor": "7" - }, - "0,40": { - "contents": "", - "bgcolor": "7" - }, - "0,41": { - "contents": "", - "bgcolor": "7" - }, - "0,42": { - "contents": "", - "bgcolor": "7" - }, - "0,43": { - "contents": "", - "bgcolor": "7" - }, - "0,44": { - "contents": "", - "bgcolor": "7" - }, - "0,45": { - "contents": "", - "bgcolor": "7" - }, - "0,46": { - "contents": "", - "bgcolor": "7" - }, - "0,47": { - "contents": "", - "bgcolor": "7" - }, - "0,48": { - "contents": "", - "bgcolor": "7" - }, - "0,49": { - "contents": "", - "bgcolor": "7" - }, - "0,5": { - "contents": "", - "bgcolor": "7" - }, - "0,50": { - "contents": "", - "bgcolor": "7" - }, - "0,51": { - "contents": "", - "bgcolor": "7" - }, - "0,52": { - "contents": "", - "bgcolor": "7" - }, - "0,53": { - "contents": "", - "bgcolor": "7" - }, - "0,54": { - "contents": "", - "bgcolor": "7" - }, - "0,55": { - "contents": "", - "bgcolor": "7" - }, - "0,56": { - "contents": "", - "bgcolor": "7" - }, - "0,57": { - "contents": "", - "bgcolor": "7" - }, - "0,58": { - "contents": "", - "bgcolor": "7" - }, - "0,59": { - "contents": "", - "bgcolor": "7" - }, - "0,6": { - "contents": "", - "bgcolor": "7" - }, - "0,60": { - "contents": "", - "bgcolor": "7" - }, - "0,61": { - "contents": "", - "bgcolor": "7" - }, - "0,62": { - "contents": "", - "bgcolor": "7" - }, - "0,63": { - "contents": "", - "bgcolor": "7" - }, - "0,64": { - "contents": "", - "bgcolor": "7" - }, - "0,65": { - "contents": "", - "bgcolor": "7" - }, - "0,66": { - "contents": "", - "bgcolor": "7" - }, - "0,67": { - "contents": "", - "bgcolor": "7" - }, - "0,68": { - "contents": "", - "bgcolor": "7" - }, - "0,69": { - "contents": "", - "bgcolor": "7" - }, - "0,7": { - "contents": "", - "bgcolor": "7" - }, - "0,70": { - "contents": "", - "bgcolor": "7" - }, - "0,71": { - "contents": "", - "bgcolor": "7" - }, - "0,72": { - "contents": "", - "bgcolor": "7" - }, - "0,73": { - "contents": "", - "bgcolor": "7" - }, - "0,74": { - "contents": "", - "bgcolor": "7" - }, - "0,75": { - "contents": "", - "bgcolor": "7" - }, - "0,76": { - "contents": "", - "bgcolor": "7" - }, - "0,77": { - "contents": "", - "bgcolor": "7" - }, - "0,78": { - "contents": "", - "bgcolor": "7" - }, - "0,79": { - "contents": "", - "bgcolor": "7" - }, - "0,8": { - "contents": "", - "bgcolor": "7" - }, - "0,9": { - "contents": "", - "bgcolor": "7" - }, - "1,0": { - "contents": "", - "bgcolor": "7" - }, - "1,1": { - "contents": "", - "bgcolor": "7" - }, - "1,10": { - "contents": "", - "bgcolor": "7" - }, - "1,11": { - "contents": "", - "bgcolor": "7" - }, - "1,12": { - "contents": "", - "bgcolor": "7" - }, - "1,13": { - "contents": "", - "bgcolor": "7" - }, - "1,14": { - "contents": "", - "bgcolor": "7" - }, - "1,15": { - "contents": "", - "bgcolor": "7" - }, - "1,16": { - "contents": "", - "bgcolor": "7" - }, - "1,17": { - "contents": "", - "bgcolor": "7" - }, - "1,18": { - "contents": "", - "bgcolor": "7" - }, - "1,19": { - "contents": "", - "bgcolor": "7" - }, - "1,2": { - "contents": "", - "bgcolor": "7" - }, - "1,20": { - "contents": "", - "bgcolor": "7" - }, - "1,21": { - "contents": "", - "bgcolor": "7" - }, - "1,22": { - "contents": "", - "bgcolor": "7" - }, - "1,23": { - "contents": "", - "bgcolor": "7" - }, - "1,24": { - "contents": "", - "bgcolor": "7" - }, - "1,25": { - "contents": "", - "bgcolor": "7" - }, - "1,26": { - "contents": "", - "bgcolor": "7" - }, - "1,27": { - "contents": "", - "bgcolor": "7" - }, - "1,28": { - "contents": "", - "bgcolor": "7" - }, - "1,29": { - "contents": "", - "bgcolor": "7" - }, - "1,3": { - "contents": "", - "bgcolor": "7" - }, - "1,30": { - "contents": "", - "bgcolor": "7" - }, - "1,31": { - "contents": "", - "bgcolor": "7" - }, - "1,32": { - "contents": "", - "bgcolor": "7" - }, - "1,33": { - "contents": "", - "bgcolor": "7" - }, - "1,34": { - "contents": "", - "bgcolor": "7" - }, - "1,35": { - "contents": "", - "bgcolor": "7" - }, - "1,36": { - "contents": "", - "bgcolor": "7" - }, - "1,37": { - "contents": "", - "bgcolor": "7" - }, - "1,38": { - "contents": "", - "bgcolor": "7" - }, - "1,39": { - "contents": "", - "bgcolor": "7" - }, - "1,4": { - "contents": "", - "bgcolor": "7" - }, - "1,40": { - "contents": "", - "bgcolor": "7" - }, - "1,41": { - "contents": "", - "bgcolor": "7" - }, - "1,42": { - "contents": "", - "bgcolor": "7" - }, - "1,43": { - "contents": "", - "bgcolor": "7" - }, - "1,44": { - "contents": "", - "bgcolor": "7" - }, - "1,45": { - "contents": "", - "bgcolor": "7" - }, - "1,46": { - "contents": "", - "bgcolor": "7" - }, - "1,47": { - "contents": "", - "bgcolor": "7" - }, - "1,48": { - "contents": "", - "bgcolor": "7" - }, - "1,49": { - "contents": "", - "bgcolor": "7" - }, - "1,5": { - "contents": "", - "bgcolor": "7" - }, - "1,50": { - "contents": "", - "bgcolor": "7" - }, - "1,51": { - "contents": "", - "bgcolor": "7" - }, - "1,52": { - "contents": "", - "bgcolor": "7" - }, - "1,53": { - "contents": "", - "bgcolor": "7" - }, - "1,54": { - "contents": "", - "bgcolor": "7" - }, - "1,55": { - "contents": "", - "bgcolor": "7" - }, - "1,56": { - "contents": "", - "bgcolor": "7" - }, - "1,57": { - "contents": "", - "bgcolor": "7" - }, - "1,58": { - "contents": "", - "bgcolor": "7" - }, - "1,59": { - "contents": "", - "bgcolor": "7" - }, - "1,6": { - "contents": "", - "bgcolor": "7" - }, - "1,60": { - "contents": "", - "bgcolor": "7" - }, - "1,61": { - "contents": "", - "bgcolor": "7" - }, - "1,62": { - "contents": "", - "bgcolor": "7" - }, - "1,63": { - "contents": "", - "bgcolor": "7" - }, - "1,64": { - "contents": "", - "bgcolor": "7" - }, - "1,65": { - "contents": "", - "bgcolor": "7" - }, - "1,66": { - "contents": "", - "bgcolor": "7" - }, - "1,67": { - "contents": "", - "bgcolor": "7" - }, - "1,68": { - "contents": "", - "bgcolor": "7" - }, - "1,69": { - "contents": "", - "bgcolor": "7" - }, - "1,7": { - "contents": "", - "bgcolor": "7" - }, - "1,70": { - "contents": "", - "bgcolor": "7" - }, - "1,71": { - "contents": "", - "bgcolor": "7" - }, - "1,72": { - "contents": "", - "bgcolor": "7" - }, - "1,73": { - "contents": "", - "bgcolor": "7" - }, - "1,74": { - "contents": "", - "bgcolor": "7" - }, - "1,75": { - "contents": "", - "bgcolor": "7" - }, - "1,76": { - "contents": "", - "bgcolor": "7" - }, - "1,77": { - "contents": "", - "bgcolor": "7" - }, - "1,78": { - "contents": "", - "bgcolor": "7" - }, - "1,79": { - "contents": "", - "bgcolor": "7" - }, - "1,8": { - "contents": "", - "bgcolor": "7" - }, - "1,9": { - "contents": "", - "bgcolor": "7" - }, - "10,0": { - "contents": "", - "bgcolor": "7" - }, - "10,1": { - "contents": "", - "bgcolor": "7" - }, - "10,10": { - "contents": "", - "bgcolor": "7" - }, - "10,11": { - "contents": "", - "bgcolor": "7" - }, - "10,12": { - "contents": "", - "bgcolor": "7" - }, - "10,13": { - "contents": "", - "bgcolor": "7" - }, - "10,14": { - "contents": "", - "bgcolor": "7" - }, - "10,15": { - "contents": "", - "bgcolor": "7" - }, - "10,16": { - "contents": "", - "bgcolor": "7" - }, - "10,17": { - "contents": "", - "bgcolor": "7" - }, - "10,18": { - "contents": "", - "bgcolor": "7" - }, - "10,19": { - "contents": "", - "bgcolor": "7" - }, - "10,2": { - "contents": "", - "bgcolor": "7" - }, - "10,20": { - "contents": "", - "bgcolor": "7" - }, - "10,21": { - "contents": "", - "bgcolor": "7" - }, - "10,22": { - "contents": "", - "bgcolor": "7" - }, - "10,23": { - "contents": "", - "bgcolor": "7" - }, - "10,24": { - "contents": "", - "bgcolor": "7" - }, - "10,25": { - "contents": "", - "bgcolor": "7" - }, - "10,26": { - "contents": "", - "bgcolor": "7" - }, - "10,27": { - "contents": "", - "bgcolor": "7" - }, - "10,28": { - "contents": "", - "bgcolor": "7" - }, - "10,29": { - "contents": "", - "bgcolor": "7" - }, - "10,3": { - "contents": "", - "bgcolor": "7" - }, - "10,30": { - "contents": "", - "bgcolor": "7" - }, - "10,31": { - "contents": "", - "bgcolor": "7" - }, - "10,32": { - "contents": "", - "bgcolor": "7" - }, - "10,33": { - "contents": "", - "bgcolor": "7" - }, - "10,34": { - "contents": "", - "bgcolor": "7" - }, - "10,35": { - "contents": "", - "bgcolor": "7" - }, - "10,36": { - "contents": "", - "bgcolor": "7" - }, - "10,37": { - "contents": "", - "bgcolor": "7" - }, - "10,38": { - "contents": "", - "bgcolor": "7" - }, - "10,39": { - "contents": "", - "bgcolor": "7" - }, - "10,4": { - "contents": "", - "bgcolor": "7" - }, - "10,40": { - "contents": "", - "bgcolor": "7" - }, - "10,41": { - "contents": "", - "bgcolor": "7" - }, - "10,42": { - "contents": "", - "bgcolor": "7" - }, - "10,43": { - "contents": "", - "bgcolor": "7" - }, - "10,44": { - "contents": "", - "bgcolor": "7" - }, - "10,45": { - "contents": "", - "bgcolor": "7" - }, - "10,46": { - "contents": "", - "bgcolor": "7" - }, - "10,47": { - "contents": "", - "bgcolor": "7" - }, - "10,48": { - "contents": "", - "bgcolor": "7" - }, - "10,49": { - "contents": "", - "bgcolor": "7" - }, - "10,5": { - "contents": "", - "bgcolor": "7" - }, - "10,50": { - "contents": "", - "bgcolor": "7" - }, - "10,51": { - "contents": "", - "bgcolor": "7" - }, - "10,52": { - "contents": "", - "bgcolor": "7" - }, - "10,53": { - "contents": "", - "bgcolor": "7" - }, - "10,54": { - "contents": "", - "bgcolor": "7" - }, - "10,55": { - "contents": "", - "bgcolor": "7" - }, - "10,56": { - "contents": "", - "bgcolor": "7" - }, - "10,57": { - "contents": "", - "bgcolor": "7" - }, - "10,58": { - "contents": "", - "bgcolor": "7" - }, - "10,59": { - "contents": "", - "bgcolor": "7" - }, - "10,6": { - "contents": "", - "bgcolor": "7" - }, - "10,60": { - "contents": "", - "bgcolor": "7" - }, - "10,61": { - "contents": "", - "bgcolor": "7" - }, - "10,62": { - "contents": "", - "bgcolor": "7" - }, - "10,63": { - "contents": "", - "bgcolor": "7" - }, - "10,64": { - "contents": "", - "bgcolor": "7" - }, - "10,65": { - "contents": "", - "bgcolor": "7" - }, - "10,66": { - "contents": "", - "bgcolor": "7" - }, - "10,67": { - "contents": "", - "bgcolor": "7" - }, - "10,68": { - "contents": "", - "bgcolor": "7" - }, - "10,69": { - "contents": "", - "bgcolor": "7" - }, - "10,7": { - "contents": "", - "bgcolor": "7" - }, - "10,70": { - "contents": "", - "bgcolor": "7" - }, - "10,71": { - "contents": "", - "bgcolor": "7" - }, - "10,72": { - "contents": "", - "bgcolor": "7" - }, - "10,73": { - "contents": "", - "bgcolor": "7" - }, - "10,74": { - "contents": "", - "bgcolor": "7" - }, - "10,75": { - "contents": "", - "bgcolor": "7" - }, - "10,76": { - "contents": "", - "bgcolor": "7" - }, - "10,77": { - "contents": "", - "bgcolor": "7" - }, - "10,78": { - "contents": "", - "bgcolor": "7" - }, - "10,79": { - "contents": "", - "bgcolor": "7" - }, - "10,8": { - "contents": "", - "bgcolor": "7" - }, - "10,9": { - "contents": "", - "bgcolor": "7" - }, - "11,0": { - "contents": "", - "bgcolor": "7" - }, - "11,1": { - "contents": "", - "bgcolor": "7" - }, - "11,10": { - "contents": "", - "bgcolor": "7" - }, - "11,11": { - "contents": "", - "bgcolor": "7" - }, - "11,12": { - "contents": "", - "bgcolor": "7" - }, - "11,13": { - "contents": "", - "bgcolor": "7" - }, - "11,14": { - "contents": "", - "bgcolor": "7" - }, - "11,15": { - "contents": "", - "bgcolor": "7" - }, - "11,16": { - "contents": "", - "bgcolor": "7" - }, - "11,17": { - "contents": "", - "bgcolor": "7" - }, - "11,18": { - "contents": "", - "bgcolor": "7" - }, - "11,19": { - "contents": "", - "bgcolor": "7" - }, - "11,2": { - "contents": "", - "bgcolor": "7" - }, - "11,20": { - "contents": "", - "bgcolor": "7" - }, - "11,21": { - "contents": "", - "bgcolor": "7" - }, - "11,22": { - "contents": "", - "bgcolor": "7" - }, - "11,23": { - "contents": "", - "bgcolor": "7" - }, - "11,24": { - "contents": "", - "bgcolor": "7" - }, - "11,25": { - "contents": "", - "bgcolor": "7" - }, - "11,26": { - "contents": "", - "bgcolor": "7" - }, - "11,27": { - "contents": "", - "bgcolor": "7" - }, - "11,28": { - "contents": "", - "bgcolor": "7" - }, - "11,29": { - "contents": "", - "bgcolor": "7" - }, - "11,3": { - "contents": "", - "bgcolor": "7" - }, - "11,30": { - "contents": "", - "bgcolor": "7" - }, - "11,31": { - "contents": "", - "bgcolor": "7" - }, - "11,32": { - "contents": "", - "bgcolor": "7" - }, - "11,33": { - "contents": "", - "bgcolor": "7" - }, - "11,34": { - "contents": "", - "bgcolor": "7" - }, - "11,35": { - "contents": "", - "bgcolor": "7" - }, - "11,36": { - "contents": "", - "bgcolor": "7" - }, - "11,37": { - "contents": "", - "bgcolor": "7" - }, - "11,38": { - "contents": "", - "bgcolor": "7" - }, - "11,39": { - "contents": "", - "bgcolor": "7" - }, - "11,4": { - "contents": "", - "bgcolor": "7" - }, - "11,40": { - "contents": "", - "bgcolor": "7" - }, - "11,41": { - "contents": "", - "bgcolor": "7" - }, - "11,42": { - "contents": "", - "bgcolor": "7" - }, - "11,43": { - "contents": "", - "bgcolor": "7" - }, - "11,44": { - "contents": "", - "bgcolor": "7" - }, - "11,45": { - "contents": "", - "bgcolor": "7" - }, - "11,46": { - "contents": "", - "bgcolor": "7" - }, - "11,47": { - "contents": "", - "bgcolor": "7" - }, - "11,48": { - "contents": "", - "bgcolor": "7" - }, - "11,49": { - "contents": "", - "bgcolor": "7" - }, - "11,5": { - "contents": "", - "bgcolor": "7" - }, - "11,50": { - "contents": "", - "bgcolor": "7" - }, - "11,51": { - "contents": "", - "bgcolor": "7" - }, - "11,52": { - "contents": "", - "bgcolor": "7" - }, - "11,53": { - "contents": "", - "bgcolor": "7" - }, - "11,54": { - "contents": "", - "bgcolor": "7" - }, - "11,55": { - "contents": "", - "bgcolor": "7" - }, - "11,56": { - "contents": "", - "bgcolor": "7" - }, - "11,57": { - "contents": "", - "bgcolor": "7" - }, - "11,58": { - "contents": "", - "bgcolor": "7" - }, - "11,59": { - "contents": "", - "bgcolor": "7" - }, - "11,6": { - "contents": "", - "bgcolor": "7" - }, - "11,60": { - "contents": "", - "bgcolor": "7" - }, - "11,61": { - "contents": "", - "bgcolor": "7" - }, - "11,62": { - "contents": "", - "bgcolor": "7" - }, - "11,63": { - "contents": "", - "bgcolor": "7" - }, - "11,64": { - "contents": "", - "bgcolor": "7" - }, - "11,65": { - "contents": "", - "bgcolor": "7" - }, - "11,66": { - "contents": "", - "bgcolor": "7" - }, - "11,67": { - "contents": "", - "bgcolor": "7" - }, - "11,68": { - "contents": "", - "bgcolor": "7" - }, - "11,69": { - "contents": "", - "bgcolor": "7" - }, - "11,7": { - "contents": "", - "bgcolor": "7" - }, - "11,70": { - "contents": "", - "bgcolor": "7" - }, - "11,71": { - "contents": "", - "bgcolor": "7" - }, - "11,72": { - "contents": "", - "bgcolor": "7" - }, - "11,73": { - "contents": "", - "bgcolor": "7" - }, - "11,74": { - "contents": "", - "bgcolor": "7" - }, - "11,75": { - "contents": "", - "bgcolor": "7" - }, - "11,76": { - "contents": "", - "bgcolor": "7" - }, - "11,77": { - "contents": "", - "bgcolor": "7" - }, - "11,78": { - "contents": "", - "bgcolor": "7" - }, - "11,79": { - "contents": "", - "bgcolor": "7" - }, - "11,8": { - "contents": "", - "bgcolor": "7" - }, - "11,9": { - "contents": "", - "bgcolor": "7" - }, - "12,0": { - "contents": "", - "bgcolor": "7" - }, - "12,1": { - "contents": "", - "bgcolor": "7" - }, - "12,10": { - "contents": "", - "bgcolor": "7" - }, - "12,11": { - "contents": "", - "bgcolor": "7" - }, - "12,12": { - "contents": "", - "bgcolor": "7" - }, - "12,13": { - "contents": "", - "bgcolor": "7" - }, - "12,14": { - "contents": "", - "bgcolor": "7" - }, - "12,15": { - "contents": "", - "bgcolor": "7" - }, - "12,16": { - "contents": "", - "bgcolor": "7" - }, - "12,17": { - "contents": "", - "bgcolor": "7" - }, - "12,18": { - "contents": "", - "bgcolor": "7" - }, - "12,19": { - "contents": "", - "bgcolor": "7" - }, - "12,2": { - "contents": "", - "bgcolor": "7" - }, - "12,20": { - "contents": "", - "bgcolor": "7" - }, - "12,21": { - "contents": "", - "bgcolor": "7" - }, - "12,22": { - "contents": "", - "bgcolor": "7" - }, - "12,23": { - "contents": "", - "bgcolor": "7" - }, - "12,24": { - "contents": "", - "bgcolor": "7" - }, - "12,25": { - "contents": "", - "bgcolor": "7" - }, - "12,26": { - "contents": "", - "bgcolor": "7" - }, - "12,27": { - "contents": "", - "bgcolor": "7" - }, - "12,28": { - "contents": "", - "bgcolor": "7" - }, - "12,29": { - "contents": "", - "bgcolor": "7" - }, - "12,3": { - "contents": "", - "bgcolor": "7" - }, - "12,30": { - "contents": "", - "bgcolor": "7" - }, - "12,31": { - "contents": "", - "bgcolor": "7" - }, - "12,32": { - "contents": "", - "bgcolor": "7" - }, - "12,33": { - "contents": "", - "bgcolor": "7" - }, - "12,34": { - "contents": "", - "bgcolor": "7" - }, - "12,35": { - "contents": "", - "bgcolor": "7" - }, - "12,36": { - "contents": "", - "bgcolor": "7" - }, - "12,37": { - "contents": "", - "bgcolor": "7" - }, - "12,38": { - "contents": "", - "bgcolor": "7" - }, - "12,39": { - "contents": "", - "bgcolor": "7" - }, - "12,4": { - "contents": "", - "bgcolor": "7" - }, - "12,40": { - "contents": "", - "bgcolor": "7" - }, - "12,41": { - "contents": "", - "bgcolor": "7" - }, - "12,42": { - "contents": "", - "bgcolor": "7" - }, - "12,43": { - "contents": "", - "bgcolor": "7" - }, - "12,44": { - "contents": "", - "bgcolor": "7" - }, - "12,45": { - "contents": "", - "bgcolor": "7" - }, - "12,46": { - "contents": "", - "bgcolor": "7" - }, - "12,47": { - "contents": "", - "bgcolor": "7" - }, - "12,48": { - "contents": "", - "bgcolor": "7" - }, - "12,49": { - "contents": "", - "bgcolor": "7" - }, - "12,5": { - "contents": "", - "bgcolor": "7" - }, - "12,50": { - "contents": "", - "bgcolor": "7" - }, - "12,51": { - "contents": "", - "bgcolor": "7" - }, - "12,52": { - "contents": "", - "bgcolor": "7" - }, - "12,53": { - "contents": "", - "bgcolor": "7" - }, - "12,54": { - "contents": "", - "bgcolor": "7" - }, - "12,55": { - "contents": "", - "bgcolor": "7" - }, - "12,56": { - "contents": "", - "bgcolor": "7" - }, - "12,57": { - "contents": "", - "bgcolor": "7" - }, - "12,58": { - "contents": "", - "bgcolor": "7" - }, - "12,59": { - "contents": "", - "bgcolor": "7" - }, - "12,6": { - "contents": "", - "bgcolor": "7" - }, - "12,60": { - "contents": "", - "bgcolor": "7" - }, - "12,61": { - "contents": "", - "bgcolor": "7" - }, - "12,62": { - "contents": "", - "bgcolor": "7" - }, - "12,63": { - "contents": "", - "bgcolor": "7" - }, - "12,64": { - "contents": "", - "bgcolor": "7" - }, - "12,65": { - "contents": "", - "bgcolor": "7" - }, - "12,66": { - "contents": "", - "bgcolor": "7" - }, - "12,67": { - "contents": "", - "bgcolor": "7" - }, - "12,68": { - "contents": "", - "bgcolor": "7" - }, - "12,69": { - "contents": "", - "bgcolor": "7" - }, - "12,7": { - "contents": "", - "bgcolor": "7" - }, - "12,70": { - "contents": "", - "bgcolor": "7" - }, - "12,71": { - "contents": "", - "bgcolor": "7" - }, - "12,72": { - "contents": "", - "bgcolor": "7" - }, - "12,73": { - "contents": "", - "bgcolor": "7" - }, - "12,74": { - "contents": "", - "bgcolor": "7" - }, - "12,75": { - "contents": "", - "bgcolor": "7" - }, - "12,76": { - "contents": "", - "bgcolor": "7" - }, - "12,77": { - "contents": "", - "bgcolor": "7" - }, - "12,78": { - "contents": "", - "bgcolor": "7" - }, - "12,79": { - "contents": "", - "bgcolor": "7" - }, - "12,8": { - "contents": "", - "bgcolor": "7" - }, - "12,9": { - "contents": "", - "bgcolor": "7" - }, - "13,0": { - "contents": "", - "bgcolor": "7" - }, - "13,1": { - "contents": "", - "bgcolor": "7" - }, - "13,10": { - "contents": "", - "bgcolor": "7" - }, - "13,11": { - "contents": "", - "bgcolor": "7" - }, - "13,12": { - "contents": "", - "bgcolor": "7" - }, - "13,13": { - "contents": "", - "bgcolor": "7" - }, - "13,14": { - "contents": "", - "bgcolor": "7" - }, - "13,15": { - "contents": "", - "bgcolor": "7" - }, - "13,16": { - "contents": "", - "bgcolor": "7" - }, - "13,17": { - "contents": "", - "bgcolor": "7" - }, - "13,18": { - "contents": "", - "bgcolor": "7" - }, - "13,19": { - "contents": "", - "bgcolor": "7" - }, - "13,2": { - "contents": "", - "bgcolor": "7" - }, - "13,20": { - "contents": "", - "bgcolor": "7" - }, - "13,21": { - "contents": "", - "bgcolor": "7" - }, - "13,22": { - "contents": "", - "bgcolor": "7" - }, - "13,23": { - "contents": "", - "bgcolor": "7" - }, - "13,24": { - "contents": "", - "bgcolor": "7" - }, - "13,25": { - "contents": "", - "bgcolor": "7" - }, - "13,26": { - "contents": "", - "bgcolor": "7" - }, - "13,27": { - "contents": "", - "bgcolor": "7" - }, - "13,28": { - "contents": "", - "bgcolor": "7" - }, - "13,29": { - "contents": "", - "bgcolor": "7" - }, - "13,3": { - "contents": "", - "bgcolor": "7" - }, - "13,30": { - "contents": "", - "bgcolor": "7" - }, - "13,31": { - "contents": "", - "bgcolor": "7" - }, - "13,32": { - "contents": "", - "bgcolor": "7" - }, - "13,33": { - "contents": "", - "bgcolor": "7" - }, - "13,34": { - "contents": "", - "bgcolor": "7" - }, - "13,35": { - "contents": "", - "bgcolor": "7" - }, - "13,36": { - "contents": "", - "bgcolor": "7" - }, - "13,37": { - "contents": "", - "bgcolor": "7" - }, - "13,38": { - "contents": "", - "bgcolor": "7" - }, - "13,39": { - "contents": "", - "bgcolor": "7" - }, - "13,4": { - "contents": "", - "bgcolor": "7" - }, - "13,40": { - "contents": "", - "bgcolor": "7" - }, - "13,41": { - "contents": "", - "bgcolor": "7" - }, - "13,42": { - "contents": "", - "bgcolor": "7" - }, - "13,43": { - "contents": "", - "bgcolor": "7" - }, - "13,44": { - "contents": "", - "bgcolor": "7" - }, - "13,45": { - "contents": "", - "bgcolor": "7" - }, - "13,46": { - "contents": "", - "bgcolor": "7" - }, - "13,47": { - "contents": "", - "bgcolor": "7" - }, - "13,48": { - "contents": "", - "bgcolor": "7" - }, - "13,49": { - "contents": "", - "bgcolor": "7" - }, - "13,5": { - "contents": "", - "bgcolor": "7" - }, - "13,50": { - "contents": "", - "bgcolor": "7" - }, - "13,51": { - "contents": "", - "bgcolor": "7" - }, - "13,52": { - "contents": "", - "bgcolor": "7" - }, - "13,53": { - "contents": "", - "bgcolor": "7" - }, - "13,54": { - "contents": "", - "bgcolor": "7" - }, - "13,55": { - "contents": "", - "bgcolor": "7" - }, - "13,56": { - "contents": "", - "bgcolor": "7" - }, - "13,57": { - "contents": "", - "bgcolor": "7" - }, - "13,58": { - "contents": "", - "bgcolor": "7" - }, - "13,59": { - "contents": "", - "bgcolor": "7" - }, - "13,6": { - "contents": "", - "bgcolor": "7" - }, - "13,60": { - "contents": "", - "bgcolor": "7" - }, - "13,61": { - "contents": "", - "bgcolor": "7" - }, - "13,62": { - "contents": "", - "bgcolor": "7" - }, - "13,63": { - "contents": "", - "bgcolor": "7" - }, - "13,64": { - "contents": "", - "bgcolor": "7" - }, - "13,65": { - "contents": "", - "bgcolor": "7" - }, - "13,66": { - "contents": "", - "bgcolor": "7" - }, - "13,67": { - "contents": "", - "bgcolor": "7" - }, - "13,68": { - "contents": "", - "bgcolor": "7" - }, - "13,69": { - "contents": "", - "bgcolor": "7" - }, - "13,7": { - "contents": "", - "bgcolor": "7" - }, - "13,70": { - "contents": "", - "bgcolor": "7" - }, - "13,71": { - "contents": "", - "bgcolor": "7" - }, - "13,72": { - "contents": "", - "bgcolor": "7" - }, - "13,73": { - "contents": "", - "bgcolor": "7" - }, - "13,74": { - "contents": "", - "bgcolor": "7" - }, - "13,75": { - "contents": "", - "bgcolor": "7" - }, - "13,76": { - "contents": "", - "bgcolor": "7" - }, - "13,77": { - "contents": "", - "bgcolor": "7" - }, - "13,78": { - "contents": "", - "bgcolor": "7" - }, - "13,79": { - "contents": "", - "bgcolor": "7" - }, - "13,8": { - "contents": "", - "bgcolor": "7" - }, - "13,9": { - "contents": "", - "bgcolor": "7" - }, - "14,0": { - "contents": "", - "bgcolor": "7" - }, - "14,1": { - "contents": "", - "bgcolor": "7" - }, - "14,10": { - "contents": "", - "bgcolor": "7" - }, - "14,11": { - "contents": "", - "bgcolor": "7" - }, - "14,12": { - "contents": "", - "bgcolor": "7" - }, - "14,13": { - "contents": "", - "bgcolor": "7" - }, - "14,14": { - "contents": "", - "bgcolor": "7" - }, - "14,15": { - "contents": "", - "bgcolor": "7" - }, - "14,16": { - "contents": "", - "bgcolor": "7" - }, - "14,17": { - "contents": "", - "bgcolor": "7" - }, - "14,18": { - "contents": "", - "bgcolor": "7" - }, - "14,19": { - "contents": "", - "bgcolor": "7" - }, - "14,2": { - "contents": "", - "bgcolor": "7" - }, - "14,20": { - "contents": "", - "bgcolor": "7" - }, - "14,21": { - "contents": "", - "bgcolor": "7" - }, - "14,22": { - "contents": "", - "bgcolor": "7" - }, - "14,23": { - "contents": "", - "bgcolor": "7" - }, - "14,24": { - "contents": "", - "bgcolor": "7" - }, - "14,25": { - "contents": "", - "bgcolor": "7" - }, - "14,26": { - "contents": "", - "bgcolor": "7" - }, - "14,27": { - "contents": "", - "bgcolor": "7" - }, - "14,28": { - "contents": "", - "bgcolor": "7" - }, - "14,29": { - "contents": "", - "bgcolor": "7" - }, - "14,3": { - "contents": "", - "bgcolor": "7" - }, - "14,30": { - "contents": "", - "bgcolor": "7" - }, - "14,31": { - "contents": "", - "bgcolor": "7" - }, - "14,32": { - "contents": "", - "bgcolor": "7" - }, - "14,33": { - "contents": "", - "bgcolor": "7" - }, - "14,34": { - "contents": "", - "bgcolor": "7" - }, - "14,35": { - "contents": "", - "bgcolor": "7" - }, - "14,36": { - "contents": "", - "bgcolor": "7" - }, - "14,37": { - "contents": "", - "bgcolor": "7" - }, - "14,38": { - "contents": "", - "bgcolor": "7" - }, - "14,39": { - "contents": "", - "bgcolor": "7" - }, - "14,4": { - "contents": "", - "bgcolor": "7" - }, - "14,40": { - "contents": "", - "bgcolor": "7" - }, - "14,41": { - "contents": "", - "bgcolor": "7" - }, - "14,42": { - "contents": "", - "bgcolor": "7" - }, - "14,43": { - "contents": "", - "bgcolor": "7" - }, - "14,44": { - "contents": "", - "bgcolor": "7" - }, - "14,45": { - "contents": "", - "bgcolor": "7" - }, - "14,46": { - "contents": "", - "bgcolor": "7" - }, - "14,47": { - "contents": "", - "bgcolor": "7" - }, - "14,48": { - "contents": "", - "bgcolor": "7" - }, - "14,49": { - "contents": "", - "bgcolor": "7" - }, - "14,5": { - "contents": "", - "bgcolor": "7" - }, - "14,50": { - "contents": "", - "bgcolor": "7" - }, - "14,51": { - "contents": "", - "bgcolor": "7" - }, - "14,52": { - "contents": "", - "bgcolor": "7" - }, - "14,53": { - "contents": "", - "bgcolor": "7" - }, - "14,54": { - "contents": "", - "bgcolor": "7" - }, - "14,55": { - "contents": "", - "bgcolor": "7" - }, - "14,56": { - "contents": "", - "bgcolor": "7" - }, - "14,57": { - "contents": "", - "bgcolor": "7" - }, - "14,58": { - "contents": "", - "bgcolor": "7" - }, - "14,59": { - "contents": "", - "bgcolor": "7" - }, - "14,6": { - "contents": "", - "bgcolor": "7" - }, - "14,60": { - "contents": "", - "bgcolor": "7" - }, - "14,61": { - "contents": "", - "bgcolor": "7" - }, - "14,62": { - "contents": "", - "bgcolor": "7" - }, - "14,63": { - "contents": "", - "bgcolor": "7" - }, - "14,64": { - "contents": "", - "bgcolor": "7" - }, - "14,65": { - "contents": "", - "bgcolor": "7" - }, - "14,66": { - "contents": "", - "bgcolor": "7" - }, - "14,67": { - "contents": "", - "bgcolor": "7" - }, - "14,68": { - "contents": "", - "bgcolor": "7" - }, - "14,69": { - "contents": "", - "bgcolor": "7" - }, - "14,7": { - "contents": "", - "bgcolor": "7" - }, - "14,70": { - "contents": "", - "bgcolor": "7" - }, - "14,71": { - "contents": "", - "bgcolor": "7" - }, - "14,72": { - "contents": "", - "bgcolor": "7" - }, - "14,73": { - "contents": "", - "bgcolor": "7" - }, - "14,74": { - "contents": "", - "bgcolor": "7" - }, - "14,75": { - "contents": "", - "bgcolor": "7" - }, - "14,76": { - "contents": "", - "bgcolor": "7" - }, - "14,77": { - "contents": "", - "bgcolor": "7" - }, - "14,78": { - "contents": "", - "bgcolor": "7" - }, - "14,79": { - "contents": "", - "bgcolor": "7" - }, - "14,8": { - "contents": "", - "bgcolor": "7" - }, - "14,9": { - "contents": "", - "bgcolor": "7" - }, - "15,0": { - "contents": "", - "bgcolor": "7" - }, - "15,1": { - "contents": "", - "bgcolor": "7" - }, - "15,10": { - "contents": "", - "bgcolor": "7" - }, - "15,11": { - "contents": "", - "bgcolor": "7" - }, - "15,12": { - "contents": "", - "bgcolor": "7" - }, - "15,13": { - "contents": "", - "bgcolor": "7" - }, - "15,14": { - "contents": "", - "bgcolor": "7" - }, - "15,15": { - "contents": "", - "bgcolor": "7" - }, - "15,16": { - "contents": "", - "bgcolor": "7" - }, - "15,17": { - "contents": "", - "bgcolor": "7" - }, - "15,18": { - "contents": "", - "bgcolor": "7" - }, - "15,19": { - "contents": "", - "bgcolor": "7" - }, - "15,2": { - "contents": "", - "bgcolor": "7" - }, - "15,20": { - "contents": "", - "bgcolor": "7" - }, - "15,21": { - "contents": "", - "bgcolor": "7" - }, - "15,22": { - "contents": "", - "bgcolor": "7" - }, - "15,23": { - "contents": "", - "bgcolor": "7" - }, - "15,24": { - "contents": "", - "bgcolor": "7" - }, - "15,25": { - "contents": "", - "bgcolor": "7" - }, - "15,26": { - "contents": "", - "bgcolor": "7" - }, - "15,27": { - "contents": "", - "bgcolor": "7" - }, - "15,28": { - "contents": "", - "bgcolor": "7" - }, - "15,29": { - "contents": "", - "bgcolor": "7" - }, - "15,3": { - "contents": "", - "bgcolor": "7" - }, - "15,30": { - "contents": "", - "bgcolor": "7" - }, - "15,31": { - "contents": "", - "bgcolor": "7" - }, - "15,32": { - "contents": "", - "bgcolor": "7" - }, - "15,33": { - "contents": "", - "bgcolor": "7" - }, - "15,34": { - "contents": "", - "bgcolor": "7" - }, - "15,35": { - "contents": "", - "bgcolor": "7" - }, - "15,36": { - "contents": "", - "bgcolor": "7" - }, - "15,37": { - "contents": "", - "bgcolor": "7" - }, - "15,38": { - "contents": "", - "bgcolor": "7" - }, - "15,39": { - "contents": "", - "bgcolor": "7" - }, - "15,4": { - "contents": "", - "bgcolor": "7" - }, - "15,40": { - "contents": "", - "bgcolor": "7" - }, - "15,41": { - "contents": "", - "bgcolor": "7" - }, - "15,42": { - "contents": "", - "bgcolor": "7" - }, - "15,43": { - "contents": "", - "bgcolor": "7" - }, - "15,44": { - "contents": "", - "bgcolor": "7" - }, - "15,45": { - "contents": "", - "bgcolor": "7" - }, - "15,46": { - "contents": "", - "bgcolor": "7" - }, - "15,47": { - "contents": "", - "bgcolor": "7" - }, - "15,48": { - "contents": "", - "bgcolor": "7" - }, - "15,49": { - "contents": "", - "bgcolor": "7" - }, - "15,5": { - "contents": "", - "bgcolor": "7" - }, - "15,50": { - "contents": "", - "bgcolor": "7" - }, - "15,51": { - "contents": "", - "bgcolor": "7" - }, - "15,52": { - "contents": "", - "bgcolor": "7" - }, - "15,53": { - "contents": "", - "bgcolor": "7" - }, - "15,54": { - "contents": "", - "bgcolor": "7" - }, - "15,55": { - "contents": "", - "bgcolor": "7" - }, - "15,56": { - "contents": "", - "bgcolor": "7" - }, - "15,57": { - "contents": "", - "bgcolor": "7" - }, - "15,58": { - "contents": "", - "bgcolor": "7" - }, - "15,59": { - "contents": "", - "bgcolor": "7" - }, - "15,6": { - "contents": "", - "bgcolor": "7" - }, - "15,60": { - "contents": "", - "bgcolor": "7" - }, - "15,61": { - "contents": "", - "bgcolor": "7" - }, - "15,62": { - "contents": "", - "bgcolor": "7" - }, - "15,63": { - "contents": "", - "bgcolor": "7" - }, - "15,64": { - "contents": "", - "bgcolor": "7" - }, - "15,65": { - "contents": "", - "bgcolor": "7" - }, - "15,66": { - "contents": "", - "bgcolor": "7" - }, - "15,67": { - "contents": "", - "bgcolor": "7" - }, - "15,68": { - "contents": "", - "bgcolor": "7" - }, - "15,69": { - "contents": "", - "bgcolor": "7" - }, - "15,7": { - "contents": "", - "bgcolor": "7" - }, - "15,70": { - "contents": "", - "bgcolor": "7" - }, - "15,71": { - "contents": "", - "bgcolor": "7" - }, - "15,72": { - "contents": "", - "bgcolor": "7" - }, - "15,73": { - "contents": "", - "bgcolor": "7" - }, - "15,74": { - "contents": "", - "bgcolor": "7" - }, - "15,75": { - "contents": "", - "bgcolor": "7" - }, - "15,76": { - "contents": "", - "bgcolor": "7" - }, - "15,77": { - "contents": "", - "bgcolor": "7" - }, - "15,78": { - "contents": "", - "bgcolor": "7" - }, - "15,79": { - "contents": "", - "bgcolor": "7" - }, - "15,8": { - "contents": "", - "bgcolor": "7" - }, - "15,9": { - "contents": "", - "bgcolor": "7" - }, - "16,0": { - "contents": "", - "bgcolor": "7" - }, - "16,1": { - "contents": "", - "bgcolor": "7" - }, - "16,10": { - "contents": "", - "bgcolor": "7" - }, - "16,11": { - "contents": "", - "bgcolor": "7" - }, - "16,12": { - "contents": "", - "bgcolor": "7" - }, - "16,13": { - "contents": "", - "bgcolor": "7" - }, - "16,14": { - "contents": "", - "bgcolor": "7" - }, - "16,15": { - "contents": "", - "bgcolor": "7" - }, - "16,16": { - "contents": "", - "bgcolor": "7" - }, - "16,17": { - "contents": "", - "bgcolor": "7" - }, - "16,18": { - "contents": "", - "bgcolor": "7" - }, - "16,19": { - "contents": "", - "bgcolor": "7" - }, - "16,2": { - "contents": "", - "bgcolor": "7" - }, - "16,20": { - "contents": "", - "bgcolor": "7" - }, - "16,21": { - "contents": "", - "bgcolor": "7" - }, - "16,22": { - "contents": "", - "bgcolor": "7" - }, - "16,23": { - "contents": "", - "bgcolor": "7" - }, - "16,24": { - "contents": "", - "bgcolor": "7" - }, - "16,25": { - "contents": "", - "bgcolor": "7" - }, - "16,26": { - "contents": "", - "bgcolor": "7" - }, - "16,27": { - "contents": "", - "bgcolor": "7" - }, - "16,28": { - "contents": "", - "bgcolor": "7" - }, - "16,29": { - "contents": "", - "bgcolor": "7" - }, - "16,3": { - "contents": "", - "bgcolor": "7" - }, - "16,30": { - "contents": "", - "bgcolor": "7" - }, - "16,31": { - "contents": "", - "bgcolor": "7" - }, - "16,32": { - "contents": "", - "bgcolor": "7" - }, - "16,33": { - "contents": "", - "bgcolor": "7" - }, - "16,34": { - "contents": "", - "bgcolor": "7" - }, - "16,35": { - "contents": "", - "bgcolor": "7" - }, - "16,36": { - "contents": "", - "bgcolor": "7" - }, - "16,37": { - "contents": "", - "bgcolor": "7" - }, - "16,38": { - "contents": "", - "bgcolor": "7" - }, - "16,39": { - "contents": "", - "bgcolor": "7" - }, - "16,4": { - "contents": "", - "bgcolor": "7" - }, - "16,40": { - "contents": "", - "bgcolor": "7" - }, - "16,41": { - "contents": "", - "bgcolor": "7" - }, - "16,42": { - "contents": "", - "bgcolor": "7" - }, - "16,43": { - "contents": "", - "bgcolor": "7" - }, - "16,44": { - "contents": "", - "bgcolor": "7" - }, - "16,45": { - "contents": "", - "bgcolor": "7" - }, - "16,46": { - "contents": "", - "bgcolor": "7" - }, - "16,47": { - "contents": "", - "bgcolor": "7" - }, - "16,48": { - "contents": "", - "bgcolor": "7" - }, - "16,49": { - "contents": "", - "bgcolor": "7" - }, - "16,5": { - "contents": "", - "bgcolor": "7" - }, - "16,50": { - "contents": "", - "bgcolor": "7" - }, - "16,51": { - "contents": "", - "bgcolor": "7" - }, - "16,52": { - "contents": "", - "bgcolor": "7" - }, - "16,53": { - "contents": "", - "bgcolor": "7" - }, - "16,54": { - "contents": "", - "bgcolor": "7" - }, - "16,55": { - "contents": "", - "bgcolor": "7" - }, - "16,56": { - "contents": "", - "bgcolor": "7" - }, - "16,57": { - "contents": "", - "bgcolor": "7" - }, - "16,58": { - "contents": "", - "bgcolor": "7" - }, - "16,59": { - "contents": "", - "bgcolor": "7" - }, - "16,6": { - "contents": "", - "bgcolor": "7" - }, - "16,60": { - "contents": "", - "bgcolor": "7" - }, - "16,61": { - "contents": "", - "bgcolor": "7" - }, - "16,62": { - "contents": "", - "bgcolor": "7" - }, - "16,63": { - "contents": "", - "bgcolor": "7" - }, - "16,64": { - "contents": "", - "bgcolor": "7" - }, - "16,65": { - "contents": "", - "bgcolor": "7" - }, - "16,66": { - "contents": "", - "bgcolor": "7" - }, - "16,67": { - "contents": "", - "bgcolor": "7" - }, - "16,68": { - "contents": "", - "bgcolor": "7" - }, - "16,69": { - "contents": "", - "bgcolor": "7" - }, - "16,7": { - "contents": "", - "bgcolor": "7" - }, - "16,70": { - "contents": "", - "bgcolor": "7" - }, - "16,71": { - "contents": "", - "bgcolor": "7" - }, - "16,72": { - "contents": "", - "bgcolor": "7" - }, - "16,73": { - "contents": "", - "bgcolor": "7" - }, - "16,74": { - "contents": "", - "bgcolor": "7" - }, - "16,75": { - "contents": "", - "bgcolor": "7" - }, - "16,76": { - "contents": "", - "bgcolor": "7" - }, - "16,77": { - "contents": "", - "bgcolor": "7" - }, - "16,78": { - "contents": "", - "bgcolor": "7" - }, - "16,79": { - "contents": "", - "bgcolor": "7" - }, - "16,8": { - "contents": "", - "bgcolor": "7" - }, - "16,9": { - "contents": "", - "bgcolor": "7" - }, - "17,0": { - "contents": "", - "bgcolor": "7" - }, - "17,1": { - "contents": "", - "bgcolor": "7" - }, - "17,10": { - "contents": "", - "bgcolor": "7" - }, - "17,11": { - "contents": "", - "bgcolor": "7" - }, - "17,12": { - "contents": "", - "bgcolor": "7" - }, - "17,13": { - "contents": "", - "bgcolor": "7" - }, - "17,14": { - "contents": "", - "bgcolor": "7" - }, - "17,15": { - "contents": "", - "bgcolor": "7" - }, - "17,16": { - "contents": "", - "bgcolor": "7" - }, - "17,17": { - "contents": "", - "bgcolor": "7" - }, - "17,18": { - "contents": "", - "bgcolor": "7" - }, - "17,19": { - "contents": "", - "bgcolor": "7" - }, - "17,2": { - "contents": "", - "bgcolor": "7" - }, - "17,20": { - "contents": "", - "bgcolor": "7" - }, - "17,21": { - "contents": "", - "bgcolor": "7" - }, - "17,22": { - "contents": "", - "bgcolor": "7" - }, - "17,23": { - "contents": "", - "bgcolor": "7" - }, - "17,24": { - "contents": "", - "bgcolor": "7" - }, - "17,25": { - "contents": "", - "bgcolor": "7" - }, - "17,26": { - "contents": "", - "bgcolor": "7" - }, - "17,27": { - "contents": "", - "bgcolor": "7" - }, - "17,28": { - "contents": "", - "bgcolor": "7" - }, - "17,29": { - "contents": "", - "bgcolor": "7" - }, - "17,3": { - "contents": "", - "bgcolor": "7" - }, - "17,30": { - "contents": "", - "bgcolor": "7" - }, - "17,31": { - "contents": "", - "bgcolor": "7" - }, - "17,32": { - "contents": "", - "bgcolor": "7" - }, - "17,33": { - "contents": "", - "bgcolor": "7" - }, - "17,34": { - "contents": "", - "bgcolor": "7" - }, - "17,35": { - "contents": "", - "bgcolor": "7" - }, - "17,36": { - "contents": "", - "bgcolor": "7" - }, - "17,37": { - "contents": "", - "bgcolor": "7" - }, - "17,38": { - "contents": "", - "bgcolor": "7" - }, - "17,39": { - "contents": "", - "bgcolor": "7" - }, - "17,4": { - "contents": "", - "bgcolor": "7" - }, - "17,40": { - "contents": "", - "bgcolor": "7" - }, - "17,41": { - "contents": "", - "bgcolor": "7" - }, - "17,42": { - "contents": "", - "bgcolor": "7" - }, - "17,43": { - "contents": "", - "bgcolor": "7" - }, - "17,44": { - "contents": "", - "bgcolor": "7" - }, - "17,45": { - "contents": "", - "bgcolor": "7" - }, - "17,46": { - "contents": "", - "bgcolor": "7" - }, - "17,47": { - "contents": "", - "bgcolor": "7" - }, - "17,48": { - "contents": "", - "bgcolor": "7" - }, - "17,49": { - "contents": "", - "bgcolor": "7" - }, - "17,5": { - "contents": "", - "bgcolor": "7" - }, - "17,50": { - "contents": "", - "bgcolor": "7" - }, - "17,51": { - "contents": "", - "bgcolor": "7" - }, - "17,52": { - "contents": "", - "bgcolor": "7" - }, - "17,53": { - "contents": "", - "bgcolor": "7" - }, - "17,54": { - "contents": "", - "bgcolor": "7" - }, - "17,55": { - "contents": "", - "bgcolor": "7" - }, - "17,56": { - "contents": "", - "bgcolor": "7" - }, - "17,57": { - "contents": "", - "bgcolor": "7" - }, - "17,58": { - "contents": "", - "bgcolor": "7" - }, - "17,59": { - "contents": "", - "bgcolor": "7" - }, - "17,6": { - "contents": "", - "bgcolor": "7" - }, - "17,60": { - "contents": "", - "bgcolor": "7" - }, - "17,61": { - "contents": "", - "bgcolor": "7" - }, - "17,62": { - "contents": "", - "bgcolor": "7" - }, - "17,63": { - "contents": "", - "bgcolor": "7" - }, - "17,64": { - "contents": "", - "bgcolor": "7" - }, - "17,65": { - "contents": "", - "bgcolor": "7" - }, - "17,66": { - "contents": "", - "bgcolor": "7" - }, - "17,67": { - "contents": "", - "bgcolor": "7" - }, - "17,68": { - "contents": "", - "bgcolor": "7" - }, - "17,69": { - "contents": "", - "bgcolor": "7" - }, - "17,7": { - "contents": "", - "bgcolor": "7" - }, - "17,70": { - "contents": "", - "bgcolor": "7" - }, - "17,71": { - "contents": "", - "bgcolor": "7" - }, - "17,72": { - "contents": "", - "bgcolor": "7" - }, - "17,73": { - "contents": "", - "bgcolor": "7" - }, - "17,74": { - "contents": "", - "bgcolor": "7" - }, - "17,75": { - "contents": "", - "bgcolor": "7" - }, - "17,76": { - "contents": "", - "bgcolor": "7" - }, - "17,77": { - "contents": "", - "bgcolor": "7" - }, - "17,78": { - "contents": "", - "bgcolor": "7" - }, - "17,79": { - "contents": "", - "bgcolor": "7" - }, - "17,8": { - "contents": "", - "bgcolor": "7" - }, - "17,9": { - "contents": "", - "bgcolor": "7" - }, - "18,0": { - "contents": "", - "bgcolor": "7" - }, - "18,1": { - "contents": "", - "bgcolor": "7" - }, - "18,10": { - "contents": "", - "bgcolor": "7" - }, - "18,11": { - "contents": "", - "bgcolor": "7" - }, - "18,12": { - "contents": "", - "bgcolor": "7" - }, - "18,13": { - "contents": "", - "bgcolor": "7" - }, - "18,14": { - "contents": "", - "bgcolor": "7" - }, - "18,15": { - "contents": "", - "bgcolor": "7" - }, - "18,16": { - "contents": "", - "bgcolor": "7" - }, - "18,17": { - "contents": "", - "bgcolor": "7" - }, - "18,18": { - "contents": "", - "bgcolor": "7" - }, - "18,19": { - "contents": "", - "bgcolor": "7" - }, - "18,2": { - "contents": "", - "bgcolor": "7" - }, - "18,20": { - "contents": "", - "bgcolor": "7" - }, - "18,21": { - "contents": "", - "bgcolor": "7" - }, - "18,22": { - "contents": "", - "bgcolor": "7" - }, - "18,23": { - "contents": "", - "bgcolor": "7" - }, - "18,24": { - "contents": "", - "bgcolor": "7" - }, - "18,25": { - "contents": "", - "bgcolor": "7" - }, - "18,26": { - "contents": "", - "bgcolor": "7" - }, - "18,27": { - "contents": "", - "bgcolor": "7" - }, - "18,28": { - "contents": "", - "bgcolor": "7" - }, - "18,29": { - "contents": "", - "bgcolor": "7" - }, - "18,3": { - "contents": "", - "bgcolor": "7" - }, - "18,30": { - "contents": "", - "bgcolor": "7" - }, - "18,31": { - "contents": "", - "bgcolor": "7" - }, - "18,32": { - "contents": "", - "bgcolor": "7" - }, - "18,33": { - "contents": "", - "bgcolor": "7" - }, - "18,34": { - "contents": "", - "bgcolor": "7" - }, - "18,35": { - "contents": "", - "bgcolor": "7" - }, - "18,36": { - "contents": "", - "bgcolor": "7" - }, - "18,37": { - "contents": "", - "bgcolor": "7" - }, - "18,38": { - "contents": "", - "bgcolor": "7" - }, - "18,39": { - "contents": "", - "bgcolor": "7" - }, - "18,4": { - "contents": "", - "bgcolor": "7" - }, - "18,40": { - "contents": "", - "bgcolor": "7" - }, - "18,41": { - "contents": "", - "bgcolor": "7" - }, - "18,42": { - "contents": "", - "bgcolor": "7" - }, - "18,43": { - "contents": "", - "bgcolor": "7" - }, - "18,44": { - "contents": "", - "bgcolor": "7" - }, - "18,45": { - "contents": "", - "bgcolor": "7" - }, - "18,46": { - "contents": "", - "bgcolor": "7" - }, - "18,47": { - "contents": "", - "bgcolor": "7" - }, - "18,48": { - "contents": "", - "bgcolor": "7" - }, - "18,49": { - "contents": "", - "bgcolor": "7" - }, - "18,5": { - "contents": "", - "bgcolor": "7" - }, - "18,50": { - "contents": "", - "bgcolor": "7" - }, - "18,51": { - "contents": "", - "bgcolor": "7" - }, - "18,52": { - "contents": "", - "bgcolor": "7" - }, - "18,53": { - "contents": "", - "bgcolor": "7" - }, - "18,54": { - "contents": "", - "bgcolor": "7" - }, - "18,55": { - "contents": "", - "bgcolor": "7" - }, - "18,56": { - "contents": "", - "bgcolor": "7" - }, - "18,57": { - "contents": "", - "bgcolor": "7" - }, - "18,58": { - "contents": "", - "bgcolor": "7" - }, - "18,59": { - "contents": "", - "bgcolor": "7" - }, - "18,6": { - "contents": "", - "bgcolor": "7" - }, - "18,60": { - "contents": "", - "bgcolor": "7" - }, - "18,61": { - "contents": "", - "bgcolor": "7" - }, - "18,62": { - "contents": "", - "bgcolor": "7" - }, - "18,63": { - "contents": "", - "bgcolor": "7" - }, - "18,64": { - "contents": "", - "bgcolor": "7" - }, - "18,65": { - "contents": "", - "bgcolor": "7" - }, - "18,66": { - "contents": "", - "bgcolor": "7" - }, - "18,67": { - "contents": "", - "bgcolor": "7" - }, - "18,68": { - "contents": "", - "bgcolor": "7" - }, - "18,69": { - "contents": "", - "bgcolor": "7" - }, - "18,7": { - "contents": "", - "bgcolor": "7" - }, - "18,70": { - "contents": "", - "bgcolor": "7" - }, - "18,71": { - "contents": "", - "bgcolor": "7" - }, - "18,72": { - "contents": "", - "bgcolor": "7" - }, - "18,73": { - "contents": "", - "bgcolor": "7" - }, - "18,74": { - "contents": "", - "bgcolor": "7" - }, - "18,75": { - "contents": "", - "bgcolor": "7" - }, - "18,76": { - "contents": "", - "bgcolor": "7" - }, - "18,77": { - "contents": "", - "bgcolor": "7" - }, - "18,78": { - "contents": "", - "bgcolor": "7" - }, - "18,79": { - "contents": "", - "bgcolor": "7" - }, - "18,8": { - "contents": "", - "bgcolor": "7" - }, - "18,9": { - "contents": "", - "bgcolor": "7" - }, - "19,0": { - "contents": "", - "bgcolor": "7" - }, - "19,1": { - "contents": "", - "bgcolor": "7" - }, - "19,10": { - "contents": "", - "bgcolor": "7" - }, - "19,11": { - "contents": "", - "bgcolor": "7" - }, - "19,12": { - "contents": "", - "bgcolor": "7" - }, - "19,13": { - "contents": "", - "bgcolor": "7" - }, - "19,14": { - "contents": "", - "bgcolor": "7" - }, - "19,15": { - "contents": "", - "bgcolor": "7" - }, - "19,16": { - "contents": "", - "bgcolor": "7" - }, - "19,17": { - "contents": "", - "bgcolor": "7" - }, - "19,18": { - "contents": "", - "bgcolor": "7" - }, - "19,19": { - "contents": "", - "bgcolor": "7" - }, - "19,2": { - "contents": "", - "bgcolor": "7" - }, - "19,20": { - "contents": "", - "bgcolor": "7" - }, - "19,21": { - "contents": "", - "bgcolor": "7" - }, - "19,22": { - "contents": "", - "bgcolor": "7" - }, - "19,23": { - "contents": "", - "bgcolor": "7" - }, - "19,24": { - "contents": "", - "bgcolor": "7" - }, - "19,25": { - "contents": "", - "bgcolor": "7" - }, - "19,26": { - "contents": "", - "bgcolor": "7" - }, - "19,27": { - "contents": "", - "bgcolor": "7" - }, - "19,28": { - "contents": "", - "bgcolor": "7" - }, - "19,29": { - "contents": "", - "bgcolor": "7" - }, - "19,3": { - "contents": "", - "bgcolor": "7" - }, - "19,30": { - "contents": "", - "bgcolor": "7" - }, - "19,31": { - "contents": "", - "bgcolor": "7" - }, - "19,32": { - "contents": "", - "bgcolor": "7" - }, - "19,33": { - "contents": "", - "bgcolor": "7" - }, - "19,34": { - "contents": "", - "bgcolor": "7" - }, - "19,35": { - "contents": "", - "bgcolor": "7" - }, - "19,36": { - "contents": "", - "bgcolor": "7" - }, - "19,37": { - "contents": "", - "bgcolor": "7" - }, - "19,38": { - "contents": "", - "bgcolor": "7" - }, - "19,39": { - "contents": "", - "bgcolor": "7" - }, - "19,4": { - "contents": "", - "bgcolor": "7" - }, - "19,40": { - "contents": "", - "bgcolor": "7" - }, - "19,41": { - "contents": "", - "bgcolor": "7" - }, - "19,42": { - "contents": "", - "bgcolor": "7" - }, - "19,43": { - "contents": "", - "bgcolor": "7" - }, - "19,44": { - "contents": "", - "bgcolor": "7" - }, - "19,45": { - "contents": "", - "bgcolor": "7" - }, - "19,46": { - "contents": "", - "bgcolor": "7" - }, - "19,47": { - "contents": "", - "bgcolor": "7" - }, - "19,48": { - "contents": "", - "bgcolor": "7" - }, - "19,49": { - "contents": "", - "bgcolor": "7" - }, - "19,5": { - "contents": "", - "bgcolor": "7" - }, - "19,50": { - "contents": "", - "bgcolor": "7" - }, - "19,51": { - "contents": "", - "bgcolor": "7" - }, - "19,52": { - "contents": "", - "bgcolor": "7" - }, - "19,53": { - "contents": "", - "bgcolor": "7" - }, - "19,54": { - "contents": "", - "bgcolor": "7" - }, - "19,55": { - "contents": "", - "bgcolor": "7" - }, - "19,56": { - "contents": "", - "bgcolor": "7" - }, - "19,57": { - "contents": "", - "bgcolor": "7" - }, - "19,58": { - "contents": "", - "bgcolor": "7" - }, - "19,59": { - "contents": "", - "bgcolor": "7" - }, - "19,6": { - "contents": "", - "bgcolor": "7" - }, - "19,60": { - "contents": "", - "bgcolor": "7" - }, - "19,61": { - "contents": "", - "bgcolor": "7" - }, - "19,62": { - "contents": "", - "bgcolor": "7" - }, - "19,63": { - "contents": "", - "bgcolor": "7" - }, - "19,64": { - "contents": "", - "bgcolor": "7" - }, - "19,65": { - "contents": "", - "bgcolor": "7" - }, - "19,66": { - "contents": "", - "bgcolor": "7" - }, - "19,67": { - "contents": "", - "bgcolor": "7" - }, - "19,68": { - "contents": "", - "bgcolor": "7" - }, - "19,69": { - "contents": "", - "bgcolor": "7" - }, - "19,7": { - "contents": "", - "bgcolor": "7" - }, - "19,70": { - "contents": "", - "bgcolor": "7" - }, - "19,71": { - "contents": "", - "bgcolor": "7" - }, - "19,72": { - "contents": "", - "bgcolor": "7" - }, - "19,73": { - "contents": "", - "bgcolor": "7" - }, - "19,74": { - "contents": "", - "bgcolor": "7" - }, - "19,75": { - "contents": "", - "bgcolor": "7" - }, - "19,76": { - "contents": "", - "bgcolor": "7" - }, - "19,77": { - "contents": "", - "bgcolor": "7" - }, - "19,78": { - "contents": "", - "bgcolor": "7" - }, - "19,79": { - "contents": "", - "bgcolor": "7" - }, - "19,8": { - "contents": "", - "bgcolor": "7" - }, - "19,9": { - "contents": "", - "bgcolor": "7" - }, - "2,0": { - "contents": "", - "bgcolor": "7" - }, - "2,1": { - "contents": "", - "bgcolor": "7" - }, - "2,10": { - "contents": "", - "bgcolor": "7" - }, - "2,11": { - "contents": "", - "bgcolor": "7" - }, - "2,12": { - "contents": "", - "bgcolor": "7" - }, - "2,13": { - "contents": "", - "bgcolor": "7" - }, - "2,14": { - "contents": "", - "bgcolor": "7" - }, - "2,15": { - "contents": "", - "bgcolor": "7" - }, - "2,16": { - "contents": "", - "bgcolor": "7" - }, - "2,17": { - "contents": "", - "bgcolor": "7" - }, - "2,18": { - "contents": "", - "bgcolor": "7" - }, - "2,19": { - "contents": "", - "bgcolor": "7" - }, - "2,2": { - "contents": "", - "bgcolor": "7" - }, - "2,20": { - "contents": "", - "bgcolor": "7" - }, - "2,21": { - "contents": "", - "bgcolor": "7" - }, - "2,22": { - "contents": "", - "bgcolor": "7" - }, - "2,23": { - "contents": "", - "bgcolor": "7" - }, - "2,24": { - "contents": "", - "bgcolor": "7" - }, - "2,25": { - "contents": "", - "bgcolor": "7" - }, - "2,26": { - "contents": "", - "bgcolor": "7" - }, - "2,27": { - "contents": "", - "bgcolor": "7" - }, - "2,28": { - "contents": "", - "bgcolor": "7" - }, - "2,29": { - "contents": "", - "bgcolor": "7" - }, - "2,3": { - "contents": "", - "bgcolor": "7" - }, - "2,30": { - "contents": "", - "bgcolor": "7" - }, - "2,31": { - "contents": "", - "bgcolor": "7" - }, - "2,32": { - "contents": "", - "bgcolor": "7" - }, - "2,33": { - "contents": "", - "bgcolor": "7" - }, - "2,34": { - "contents": "", - "bgcolor": "7" - }, - "2,35": { - "contents": "", - "bgcolor": "7" - }, - "2,36": { - "contents": "", - "bgcolor": "7" - }, - "2,37": { - "contents": "", - "bgcolor": "7" - }, - "2,38": { - "contents": "", - "bgcolor": "7" - }, - "2,39": { - "contents": "", - "bgcolor": "7" - }, - "2,4": { - "contents": "", - "bgcolor": "7" - }, - "2,40": { - "contents": "", - "bgcolor": "7" - }, - "2,41": { - "contents": "", - "bgcolor": "7" - }, - "2,42": { - "contents": "", - "bgcolor": "7" - }, - "2,43": { - "contents": "", - "bgcolor": "7" - }, - "2,44": { - "contents": "", - "bgcolor": "7" - }, - "2,45": { - "contents": "", - "bgcolor": "7" - }, - "2,46": { - "contents": "", - "bgcolor": "7" - }, - "2,47": { - "contents": "", - "bgcolor": "7" - }, - "2,48": { - "contents": "", - "bgcolor": "7" - }, - "2,49": { - "contents": "", - "bgcolor": "7" - }, - "2,5": { - "contents": "", - "bgcolor": "7" - }, - "2,50": { - "contents": "", - "bgcolor": "7" - }, - "2,51": { - "contents": "", - "bgcolor": "7" - }, - "2,52": { - "contents": "", - "bgcolor": "7" - }, - "2,53": { - "contents": "", - "bgcolor": "7" - }, - "2,54": { - "contents": "", - "bgcolor": "7" - }, - "2,55": { - "contents": "", - "bgcolor": "7" - }, - "2,56": { - "contents": "", - "bgcolor": "7" - }, - "2,57": { - "contents": "", - "bgcolor": "7" - }, - "2,58": { - "contents": "", - "bgcolor": "7" - }, - "2,59": { - "contents": "", - "bgcolor": "7" - }, - "2,6": { - "contents": "", - "bgcolor": "7" - }, - "2,60": { - "contents": "", - "bgcolor": "7" - }, - "2,61": { - "contents": "", - "bgcolor": "7" - }, - "2,62": { - "contents": "", - "bgcolor": "7" - }, - "2,63": { - "contents": "", - "bgcolor": "7" - }, - "2,64": { - "contents": "", - "bgcolor": "7" - }, - "2,65": { - "contents": "", - "bgcolor": "7" - }, - "2,66": { - "contents": "", - "bgcolor": "7" - }, - "2,67": { - "contents": "", - "bgcolor": "7" - }, - "2,68": { - "contents": "", - "bgcolor": "7" - }, - "2,69": { - "contents": "", - "bgcolor": "7" - }, - "2,7": { - "contents": "", - "bgcolor": "7" - }, - "2,70": { - "contents": "", - "bgcolor": "7" - }, - "2,71": { - "contents": "", - "bgcolor": "7" - }, - "2,72": { - "contents": "", - "bgcolor": "7" - }, - "2,73": { - "contents": "", - "bgcolor": "7" - }, - "2,74": { - "contents": "", - "bgcolor": "7" - }, - "2,75": { - "contents": "", - "bgcolor": "7" - }, - "2,76": { - "contents": "", - "bgcolor": "7" - }, - "2,77": { - "contents": "", - "bgcolor": "7" - }, - "2,78": { - "contents": "", - "bgcolor": "7" - }, - "2,79": { - "contents": "", - "bgcolor": "7" - }, - "2,8": { - "contents": "", - "bgcolor": "7" - }, - "2,9": { - "contents": "", - "bgcolor": "7" - }, - "20,0": { - "contents": "", - "bgcolor": "7" - }, - "20,1": { - "contents": "", - "bgcolor": "7" - }, - "20,10": { - "contents": "", - "bgcolor": "7" - }, - "20,11": { - "contents": "", - "bgcolor": "7" - }, - "20,12": { - "contents": "", - "bgcolor": "7" - }, - "20,13": { - "contents": "", - "bgcolor": "7" - }, - "20,14": { - "contents": "", - "bgcolor": "7" - }, - "20,15": { - "contents": "", - "bgcolor": "7" - }, - "20,16": { - "contents": "", - "bgcolor": "7" - }, - "20,17": { - "contents": "", - "bgcolor": "7" - }, - "20,18": { - "contents": "", - "bgcolor": "7" - }, - "20,19": { - "contents": "", - "bgcolor": "7" - }, - "20,2": { - "contents": "", - "bgcolor": "7" - }, - "20,20": { - "contents": "", - "bgcolor": "7" - }, - "20,21": { - "contents": "", - "bgcolor": "7" - }, - "20,22": { - "contents": "", - "bgcolor": "7" - }, - "20,23": { - "contents": "", - "bgcolor": "7" - }, - "20,24": { - "contents": "", - "bgcolor": "7" - }, - "20,25": { - "contents": "", - "bgcolor": "7" - }, - "20,26": { - "contents": "", - "bgcolor": "7" - }, - "20,27": { - "contents": "", - "bgcolor": "7" - }, - "20,28": { - "contents": "", - "bgcolor": "7" - }, - "20,29": { - "contents": "", - "bgcolor": "7" - }, - "20,3": { - "contents": "", - "bgcolor": "7" - }, - "20,30": { - "contents": "", - "bgcolor": "7" - }, - "20,31": { - "contents": "", - "bgcolor": "7" - }, - "20,32": { - "contents": "", - "bgcolor": "7" - }, - "20,33": { - "contents": "", - "bgcolor": "7" - }, - "20,34": { - "contents": "", - "bgcolor": "7" - }, - "20,35": { - "contents": "", - "bgcolor": "7" - }, - "20,36": { - "contents": "", - "bgcolor": "7" - }, - "20,37": { - "contents": "", - "bgcolor": "7" - }, - "20,38": { - "contents": "", - "bgcolor": "7" - }, - "20,39": { - "contents": "", - "bgcolor": "7" - }, - "20,4": { - "contents": "", - "bgcolor": "7" - }, - "20,40": { - "contents": "", - "bgcolor": "7" - }, - "20,41": { - "contents": "", - "bgcolor": "7" - }, - "20,42": { - "contents": "", - "bgcolor": "7" - }, - "20,43": { - "contents": "", - "bgcolor": "7" - }, - "20,44": { - "contents": "", - "bgcolor": "7" - }, - "20,45": { - "contents": "", - "bgcolor": "7" - }, - "20,46": { - "contents": "", - "bgcolor": "7" - }, - "20,47": { - "contents": "", - "bgcolor": "7" - }, - "20,48": { - "contents": "", - "bgcolor": "7" - }, - "20,49": { - "contents": "", - "bgcolor": "7" - }, - "20,5": { - "contents": "", - "bgcolor": "7" - }, - "20,50": { - "contents": "", - "bgcolor": "7" - }, - "20,51": { - "contents": "", - "bgcolor": "7" - }, - "20,52": { - "contents": "", - "bgcolor": "7" - }, - "20,53": { - "contents": "", - "bgcolor": "7" - }, - "20,54": { - "contents": "", - "bgcolor": "7" - }, - "20,55": { - "contents": "", - "bgcolor": "7" - }, - "20,56": { - "contents": "", - "bgcolor": "7" - }, - "20,57": { - "contents": "", - "bgcolor": "7" - }, - "20,58": { - "contents": "", - "bgcolor": "7" - }, - "20,59": { - "contents": "", - "bgcolor": "7" - }, - "20,6": { - "contents": "", - "bgcolor": "7" - }, - "20,60": { - "contents": "", - "bgcolor": "7" - }, - "20,61": { - "contents": "", - "bgcolor": "7" - }, - "20,62": { - "contents": "", - "bgcolor": "7" - }, - "20,63": { - "contents": "", - "bgcolor": "7" - }, - "20,64": { - "contents": "", - "bgcolor": "7" - }, - "20,65": { - "contents": "", - "bgcolor": "7" - }, - "20,66": { - "contents": "", - "bgcolor": "7" - }, - "20,67": { - "contents": "", - "bgcolor": "7" - }, - "20,68": { - "contents": "", - "bgcolor": "7" - }, - "20,69": { - "contents": "", - "bgcolor": "7" - }, - "20,7": { - "contents": "", - "bgcolor": "7" - }, - "20,70": { - "contents": "", - "bgcolor": "7" - }, - "20,71": { - "contents": "", - "bgcolor": "7" - }, - "20,72": { - "contents": "", - "bgcolor": "7" - }, - "20,73": { - "contents": "", - "bgcolor": "7" - }, - "20,74": { - "contents": "", - "bgcolor": "7" - }, - "20,75": { - "contents": "", - "bgcolor": "7" - }, - "20,76": { - "contents": "", - "bgcolor": "7" - }, - "20,77": { - "contents": "", - "bgcolor": "7" - }, - "20,78": { - "contents": "", - "bgcolor": "7" - }, - "20,79": { - "contents": "", - "bgcolor": "7" - }, - "20,8": { - "contents": "", - "bgcolor": "7" - }, - "20,9": { - "contents": "", - "bgcolor": "7" - }, - "21,0": { - "contents": "", - "bgcolor": "7" - }, - "21,1": { - "contents": "", - "bgcolor": "7" - }, - "21,10": { - "contents": "", - "bgcolor": "7" - }, - "21,11": { - "contents": "", - "bgcolor": "7" - }, - "21,12": { - "contents": "", - "bgcolor": "7" - }, - "21,13": { - "contents": "", - "bgcolor": "7" - }, - "21,14": { - "contents": "", - "bgcolor": "7" - }, - "21,15": { - "contents": "", - "bgcolor": "7" - }, - "21,16": { - "contents": "", - "bgcolor": "7" - }, - "21,17": { - "contents": "", - "bgcolor": "7" - }, - "21,18": { - "contents": "", - "bgcolor": "7" - }, - "21,19": { - "contents": "", - "bgcolor": "7" - }, - "21,2": { - "contents": "", - "bgcolor": "7" - }, - "21,20": { - "contents": "", - "bgcolor": "7" - }, - "21,21": { - "contents": "", - "bgcolor": "7" - }, - "21,22": { - "contents": "", - "bgcolor": "7" - }, - "21,23": { - "contents": "", - "bgcolor": "7" - }, - "21,24": { - "contents": "", - "bgcolor": "7" - }, - "21,25": { - "contents": "", - "bgcolor": "7" - }, - "21,26": { - "contents": "", - "bgcolor": "7" - }, - "21,27": { - "contents": "", - "bgcolor": "7" - }, - "21,28": { - "contents": "", - "bgcolor": "7" - }, - "21,29": { - "contents": "", - "bgcolor": "7" - }, - "21,3": { - "contents": "", - "bgcolor": "7" - }, - "21,30": { - "contents": "", - "bgcolor": "7" - }, - "21,31": { - "contents": "", - "bgcolor": "7" - }, - "21,32": { - "contents": "", - "bgcolor": "7" - }, - "21,33": { - "contents": "", - "bgcolor": "7" - }, - "21,34": { - "contents": "", - "bgcolor": "7" - }, - "21,35": { - "contents": "", - "bgcolor": "7" - }, - "21,36": { - "contents": "", - "bgcolor": "7" - }, - "21,37": { - "contents": "", - "bgcolor": "7" - }, - "21,38": { - "contents": "", - "bgcolor": "7" - }, - "21,39": { - "contents": "", - "bgcolor": "7" - }, - "21,4": { - "contents": "", - "bgcolor": "7" - }, - "21,40": { - "contents": "", - "bgcolor": "7" - }, - "21,41": { - "contents": "", - "bgcolor": "7" - }, - "21,42": { - "contents": "", - "bgcolor": "7" - }, - "21,43": { - "contents": "", - "bgcolor": "7" - }, - "21,44": { - "contents": "", - "bgcolor": "7" - }, - "21,45": { - "contents": "", - "bgcolor": "7" - }, - "21,46": { - "contents": "", - "bgcolor": "7" - }, - "21,47": { - "contents": "", - "bgcolor": "7" - }, - "21,48": { - "contents": "", - "bgcolor": "7" - }, - "21,49": { - "contents": "", - "bgcolor": "7" - }, - "21,5": { - "contents": "", - "bgcolor": "7" - }, - "21,50": { - "contents": "", - "bgcolor": "7" - }, - "21,51": { - "contents": "", - "bgcolor": "7" - }, - "21,52": { - "contents": "", - "bgcolor": "7" - }, - "21,53": { - "contents": "", - "bgcolor": "7" - }, - "21,54": { - "contents": "", - "bgcolor": "7" - }, - "21,55": { - "contents": "", - "bgcolor": "7" - }, - "21,56": { - "contents": "", - "bgcolor": "7" - }, - "21,57": { - "contents": "", - "bgcolor": "7" - }, - "21,58": { - "contents": "", - "bgcolor": "7" - }, - "21,59": { - "contents": "", - "bgcolor": "7" - }, - "21,6": { - "contents": "", - "bgcolor": "7" - }, - "21,60": { - "contents": "", - "bgcolor": "7" - }, - "21,61": { - "contents": "", - "bgcolor": "7" - }, - "21,62": { - "contents": "", - "bgcolor": "7" - }, - "21,63": { - "contents": "", - "bgcolor": "7" - }, - "21,64": { - "contents": "", - "bgcolor": "7" - }, - "21,65": { - "contents": "", - "bgcolor": "7" - }, - "21,66": { - "contents": "", - "bgcolor": "7" - }, - "21,67": { - "contents": "", - "bgcolor": "7" - }, - "21,68": { - "contents": "", - "bgcolor": "7" - }, - "21,69": { - "contents": "", - "bgcolor": "7" - }, - "21,7": { - "contents": "", - "bgcolor": "7" - }, - "21,70": { - "contents": "", - "bgcolor": "7" - }, - "21,71": { - "contents": "", - "bgcolor": "7" - }, - "21,72": { - "contents": "", - "bgcolor": "7" - }, - "21,73": { - "contents": "", - "bgcolor": "7" - }, - "21,74": { - "contents": "", - "bgcolor": "7" - }, - "21,75": { - "contents": "", - "bgcolor": "7" - }, - "21,76": { - "contents": "", - "bgcolor": "7" - }, - "21,77": { - "contents": "", - "bgcolor": "7" - }, - "21,78": { - "contents": "", - "bgcolor": "7" - }, - "21,79": { - "contents": "", - "bgcolor": "7" - }, - "21,8": { - "contents": "", - "bgcolor": "7" - }, - "21,9": { - "contents": "", - "bgcolor": "7" - }, - "22,0": { - "contents": "", - "bgcolor": "7" - }, - "22,1": { - "contents": "", - "bgcolor": "7" - }, - "22,10": { - "contents": "", - "bgcolor": "7" - }, - "22,11": { - "contents": "", - "bgcolor": "7" - }, - "22,12": { - "contents": "", - "bgcolor": "7" - }, - "22,13": { - "contents": "", - "bgcolor": "7" - }, - "22,14": { - "contents": "", - "bgcolor": "7" - }, - "22,15": { - "contents": "", - "bgcolor": "7" - }, - "22,16": { - "contents": "", - "bgcolor": "7" - }, - "22,17": { - "contents": "", - "bgcolor": "7" - }, - "22,18": { - "contents": "", - "bgcolor": "7" - }, - "22,19": { - "contents": "", - "bgcolor": "7" - }, - "22,2": { - "contents": "", - "bgcolor": "7" - }, - "22,20": { - "contents": "", - "bgcolor": "7" - }, - "22,21": { - "contents": "", - "bgcolor": "7" - }, - "22,22": { - "contents": "", - "bgcolor": "7" - }, - "22,23": { - "contents": "", - "bgcolor": "7" - }, - "22,24": { - "contents": "", - "bgcolor": "7" - }, - "22,25": { - "contents": "", - "bgcolor": "7" - }, - "22,26": { - "contents": "", - "bgcolor": "7" - }, - "22,27": { - "contents": "", - "bgcolor": "7" - }, - "22,28": { - "contents": "", - "bgcolor": "7" - }, - "22,29": { - "contents": "", - "bgcolor": "7" - }, - "22,3": { - "contents": "", - "bgcolor": "7" - }, - "22,30": { - "contents": "", - "bgcolor": "7" - }, - "22,31": { - "contents": "", - "bgcolor": "7" - }, - "22,32": { - "contents": "", - "bgcolor": "7" - }, - "22,33": { - "contents": "", - "bgcolor": "7" - }, - "22,34": { - "contents": "", - "bgcolor": "7" - }, - "22,35": { - "contents": "", - "bgcolor": "7" - }, - "22,36": { - "contents": "", - "bgcolor": "7" - }, - "22,37": { - "contents": "", - "bgcolor": "7" - }, - "22,38": { - "contents": "", - "bgcolor": "7" - }, - "22,39": { - "contents": "", - "bgcolor": "7" - }, - "22,4": { - "contents": "", - "bgcolor": "7" - }, - "22,40": { - "contents": "", - "bgcolor": "7" - }, - "22,41": { - "contents": "", - "bgcolor": "7" - }, - "22,42": { - "contents": "", - "bgcolor": "7" - }, - "22,43": { - "contents": "", - "bgcolor": "7" - }, - "22,44": { - "contents": "", - "bgcolor": "7" - }, - "22,45": { - "contents": "", - "bgcolor": "7" - }, - "22,46": { - "contents": "", - "bgcolor": "7" - }, - "22,47": { - "contents": "", - "bgcolor": "7" - }, - "22,48": { - "contents": "", - "bgcolor": "7" - }, - "22,49": { - "contents": "", - "bgcolor": "7" - }, - "22,5": { - "contents": "", - "bgcolor": "7" - }, - "22,50": { - "contents": "", - "bgcolor": "7" - }, - "22,51": { - "contents": "", - "bgcolor": "7" - }, - "22,52": { - "contents": "", - "bgcolor": "7" - }, - "22,53": { - "contents": "", - "bgcolor": "7" - }, - "22,54": { - "contents": "", - "bgcolor": "7" - }, - "22,55": { - "contents": "", - "bgcolor": "7" - }, - "22,56": { - "contents": "", - "bgcolor": "7" - }, - "22,57": { - "contents": "", - "bgcolor": "7" - }, - "22,58": { - "contents": "", - "bgcolor": "7" - }, - "22,59": { - "contents": "", - "bgcolor": "7" - }, - "22,6": { - "contents": "", - "bgcolor": "7" - }, - "22,60": { - "contents": "", - "bgcolor": "7" - }, - "22,61": { - "contents": "", - "bgcolor": "7" - }, - "22,62": { - "contents": "", - "bgcolor": "7" - }, - "22,63": { - "contents": "", - "bgcolor": "7" - }, - "22,64": { - "contents": "", - "bgcolor": "7" - }, - "22,65": { - "contents": "", - "bgcolor": "7" - }, - "22,66": { - "contents": "", - "bgcolor": "7" - }, - "22,67": { - "contents": "", - "bgcolor": "7" - }, - "22,68": { - "contents": "", - "bgcolor": "7" - }, - "22,69": { - "contents": "", - "bgcolor": "7" - }, - "22,7": { - "contents": "", - "bgcolor": "7" - }, - "22,70": { - "contents": "", - "bgcolor": "7" - }, - "22,71": { - "contents": "", - "bgcolor": "7" - }, - "22,72": { - "contents": "", - "bgcolor": "7" - }, - "22,73": { - "contents": "", - "bgcolor": "7" - }, - "22,74": { - "contents": "", - "bgcolor": "7" - }, - "22,75": { - "contents": "", - "bgcolor": "7" - }, - "22,76": { - "contents": "", - "bgcolor": "7" - }, - "22,77": { - "contents": "", - "bgcolor": "7" - }, - "22,78": { - "contents": "", - "bgcolor": "7" - }, - "22,79": { - "contents": "", - "bgcolor": "7" - }, - "22,8": { - "contents": "", - "bgcolor": "7" - }, - "22,9": { - "contents": "", - "bgcolor": "7" - }, - "23,0": { - "contents": "", - "bgcolor": "7" - }, - "23,1": { - "contents": "", - "bgcolor": "7" - }, - "23,10": { - "contents": "", - "bgcolor": "7" - }, - "23,11": { - "contents": "", - "bgcolor": "7" - }, - "23,12": { - "contents": "", - "bgcolor": "7" - }, - "23,13": { - "contents": "", - "bgcolor": "7" - }, - "23,14": { - "contents": "", - "bgcolor": "7" - }, - "23,15": { - "contents": "", - "bgcolor": "7" - }, - "23,16": { - "contents": "", - "bgcolor": "7" - }, - "23,17": { - "contents": "", - "bgcolor": "7" - }, - "23,18": { - "contents": "", - "bgcolor": "7" - }, - "23,19": { - "contents": "", - "bgcolor": "7" - }, - "23,2": { - "contents": "", - "bgcolor": "7" - }, - "23,20": { - "contents": "", - "bgcolor": "7" - }, - "23,21": { - "contents": "", - "bgcolor": "7" - }, - "23,22": { - "contents": "", - "bgcolor": "7" - }, - "23,23": { - "contents": "", - "bgcolor": "7" - }, - "23,24": { - "contents": "", - "bgcolor": "7" - }, - "23,25": { - "contents": "", - "bgcolor": "7" - }, - "23,26": { - "contents": "", - "bgcolor": "7" - }, - "23,27": { - "contents": "", - "bgcolor": "7" - }, - "23,28": { - "contents": "", - "bgcolor": "7" - }, - "23,29": { - "contents": "", - "bgcolor": "7" - }, - "23,3": { - "contents": "", - "bgcolor": "7" - }, - "23,30": { - "contents": "", - "bgcolor": "7" - }, - "23,31": { - "contents": "", - "bgcolor": "7" - }, - "23,32": { - "contents": "", - "bgcolor": "7" - }, - "23,33": { - "contents": "", - "bgcolor": "7" - }, - "23,34": { - "contents": "", - "bgcolor": "7" - }, - "23,35": { - "contents": "", - "bgcolor": "7" - }, - "23,36": { - "contents": "", - "bgcolor": "7" - }, - "23,37": { - "contents": "", - "bgcolor": "7" - }, - "23,38": { - "contents": "", - "bgcolor": "7" - }, - "23,39": { - "contents": "", - "bgcolor": "7" - }, - "23,4": { - "contents": "", - "bgcolor": "7" - }, - "23,40": { - "contents": "", - "bgcolor": "7" - }, - "23,41": { - "contents": "", - "bgcolor": "7" - }, - "23,42": { - "contents": "", - "bgcolor": "7" - }, - "23,43": { - "contents": "", - "bgcolor": "7" - }, - "23,44": { - "contents": "", - "bgcolor": "7" - }, - "23,45": { - "contents": "", - "bgcolor": "7" - }, - "23,46": { - "contents": "", - "bgcolor": "7" - }, - "23,47": { - "contents": "", - "bgcolor": "7" - }, - "23,48": { - "contents": "", - "bgcolor": "7" - }, - "23,49": { - "contents": "", - "bgcolor": "7" - }, - "23,5": { - "contents": "", - "bgcolor": "7" - }, - "23,50": { - "contents": "", - "bgcolor": "7" - }, - "23,51": { - "contents": "", - "bgcolor": "7" - }, - "23,52": { - "contents": "", - "bgcolor": "7" - }, - "23,53": { - "contents": "", - "bgcolor": "7" - }, - "23,54": { - "contents": "", - "bgcolor": "7" - }, - "23,55": { - "contents": "", - "bgcolor": "7" - }, - "23,56": { - "contents": "", - "bgcolor": "7" - }, - "23,57": { - "contents": "", - "bgcolor": "7" - }, - "23,58": { - "contents": "", - "bgcolor": "7" - }, - "23,59": { - "contents": "", - "bgcolor": "7" - }, - "23,6": { - "contents": "", - "bgcolor": "7" - }, - "23,60": { - "contents": "", - "bgcolor": "7" - }, - "23,61": { - "contents": "", - "bgcolor": "7" - }, - "23,62": { - "contents": "", - "bgcolor": "7" - }, - "23,63": { - "contents": "", - "bgcolor": "7" - }, - "23,64": { - "contents": "", - "bgcolor": "7" - }, - "23,65": { - "contents": "", - "bgcolor": "7" - }, - "23,66": { - "contents": "", - "bgcolor": "7" - }, - "23,67": { - "contents": "", - "bgcolor": "7" - }, - "23,68": { - "contents": "", - "bgcolor": "7" - }, - "23,69": { - "contents": "", - "bgcolor": "7" - }, - "23,7": { - "contents": "", - "bgcolor": "7" - }, - "23,70": { - "contents": "", - "bgcolor": "7" - }, - "23,71": { - "contents": "", - "bgcolor": "7" - }, - "23,72": { - "contents": "", - "bgcolor": "7" - }, - "23,73": { - "contents": "", - "bgcolor": "7" - }, - "23,74": { - "contents": "", - "bgcolor": "7" - }, - "23,75": { - "contents": "", - "bgcolor": "7" - }, - "23,76": { - "contents": "", - "bgcolor": "7" - }, - "23,77": { - "contents": "", - "bgcolor": "7" - }, - "23,78": { - "contents": "", - "bgcolor": "7" - }, - "23,79": { - "contents": "", - "bgcolor": "7" - }, - "23,8": { - "contents": "", - "bgcolor": "7" - }, - "23,9": { - "contents": "", - "bgcolor": "7" - }, - "3,0": { - "contents": "", - "bgcolor": "7" - }, - "3,1": { - "contents": "", - "bgcolor": "7" - }, - "3,10": { - "contents": "", - "bgcolor": "7" - }, - "3,11": { - "contents": "", - "bgcolor": "7" - }, - "3,12": { - "contents": "", - "bgcolor": "7" - }, - "3,13": { - "contents": "", - "bgcolor": "7" - }, - "3,14": { - "contents": "", - "bgcolor": "7" - }, - "3,15": { - "contents": "", - "bgcolor": "7" - }, - "3,16": { - "contents": "", - "bgcolor": "7" - }, - "3,17": { - "contents": "", - "bgcolor": "7" - }, - "3,18": { - "contents": "", - "bgcolor": "7" - }, - "3,19": { - "contents": "", - "bgcolor": "7" - }, - "3,2": { - "contents": "", - "bgcolor": "7" - }, - "3,20": { - "contents": "", - "bgcolor": "7" - }, - "3,21": { - "contents": "", - "bgcolor": "7" - }, - "3,22": { - "contents": "", - "bgcolor": "7" - }, - "3,23": { - "contents": "", - "bgcolor": "7" - }, - "3,24": { - "contents": "", - "bgcolor": "7" - }, - "3,25": { - "contents": "", - "bgcolor": "7" - }, - "3,26": { - "contents": "", - "bgcolor": "7" - }, - "3,27": { - "contents": "", - "bgcolor": "7" - }, - "3,28": { - "contents": "", - "bgcolor": "7" - }, - "3,29": { - "contents": "", - "bgcolor": "7" - }, - "3,3": { - "contents": "", - "bgcolor": "7" - }, - "3,30": { - "contents": "", - "bgcolor": "7" - }, - "3,31": { - "contents": "", - "bgcolor": "7" - }, - "3,32": { - "contents": "", - "bgcolor": "7" - }, - "3,33": { - "contents": "", - "bgcolor": "7" - }, - "3,34": { - "contents": "", - "bgcolor": "7" - }, - "3,35": { - "contents": "", - "bgcolor": "7" - }, - "3,36": { - "contents": "", - "bgcolor": "7" - }, - "3,37": { - "contents": "", - "bgcolor": "7" - }, - "3,38": { - "contents": "", - "bgcolor": "7" - }, - "3,39": { - "contents": "", - "bgcolor": "7" - }, - "3,4": { - "contents": "", - "bgcolor": "7" - }, - "3,40": { - "contents": "", - "bgcolor": "7" - }, - "3,41": { - "contents": "", - "bgcolor": "7" - }, - "3,42": { - "contents": "", - "bgcolor": "7" - }, - "3,43": { - "contents": "", - "bgcolor": "7" - }, - "3,44": { - "contents": "", - "bgcolor": "7" - }, - "3,45": { - "contents": "", - "bgcolor": "7" - }, - "3,46": { - "contents": "", - "bgcolor": "7" - }, - "3,47": { - "contents": "", - "bgcolor": "7" - }, - "3,48": { - "contents": "", - "bgcolor": "7" - }, - "3,49": { - "contents": "", - "bgcolor": "7" - }, - "3,5": { - "contents": "", - "bgcolor": "7" - }, - "3,50": { - "contents": "", - "bgcolor": "7" - }, - "3,51": { - "contents": "", - "bgcolor": "7" - }, - "3,52": { - "contents": "", - "bgcolor": "7" - }, - "3,53": { - "contents": "", - "bgcolor": "7" - }, - "3,54": { - "contents": "", - "bgcolor": "7" - }, - "3,55": { - "contents": "", - "bgcolor": "7" - }, - "3,56": { - "contents": "", - "bgcolor": "7" - }, - "3,57": { - "contents": "", - "bgcolor": "7" - }, - "3,58": { - "contents": "", - "bgcolor": "7" - }, - "3,59": { - "contents": "", - "bgcolor": "7" - }, - "3,6": { - "contents": "", - "bgcolor": "7" - }, - "3,60": { - "contents": "", - "bgcolor": "7" - }, - "3,61": { - "contents": "", - "bgcolor": "7" - }, - "3,62": { - "contents": "", - "bgcolor": "7" - }, - "3,63": { - "contents": "", - "bgcolor": "7" - }, - "3,64": { - "contents": "", - "bgcolor": "7" - }, - "3,65": { - "contents": "", - "bgcolor": "7" - }, - "3,66": { - "contents": "", - "bgcolor": "7" - }, - "3,67": { - "contents": "", - "bgcolor": "7" - }, - "3,68": { - "contents": "", - "bgcolor": "7" - }, - "3,69": { - "contents": "", - "bgcolor": "7" - }, - "3,7": { - "contents": "", - "bgcolor": "7" - }, - "3,70": { - "contents": "", - "bgcolor": "7" - }, - "3,71": { - "contents": "", - "bgcolor": "7" - }, - "3,72": { - "contents": "", - "bgcolor": "7" - }, - "3,73": { - "contents": "", - "bgcolor": "7" - }, - "3,74": { - "contents": "", - "bgcolor": "7" - }, - "3,75": { - "contents": "", - "bgcolor": "7" - }, - "3,76": { - "contents": "", - "bgcolor": "7" - }, - "3,77": { - "contents": "", - "bgcolor": "7" - }, - "3,78": { - "contents": "", - "bgcolor": "7" - }, - "3,79": { - "contents": "", - "bgcolor": "7" - }, - "3,8": { - "contents": "", - "bgcolor": "7" - }, - "3,9": { - "contents": "", - "bgcolor": "7" - }, - "4,0": { - "contents": "", - "bgcolor": "7" - }, - "4,1": { - "contents": "", - "bgcolor": "7" - }, - "4,10": { - "contents": "", - "bgcolor": "7" - }, - "4,11": { - "contents": "", - "bgcolor": "7" - }, - "4,12": { - "contents": "", - "bgcolor": "7" - }, - "4,13": { - "contents": "", - "bgcolor": "7" - }, - "4,14": { - "contents": "", - "bgcolor": "7" - }, - "4,15": { - "contents": "", - "bgcolor": "7" - }, - "4,16": { - "contents": "", - "bgcolor": "7" - }, - "4,17": { - "contents": "", - "bgcolor": "7" - }, - "4,18": { - "contents": "", - "bgcolor": "7" - }, - "4,19": { - "contents": "", - "bgcolor": "7" - }, - "4,2": { - "contents": "", - "bgcolor": "7" - }, - "4,20": { - "contents": "", - "bgcolor": "7" - }, - "4,21": { - "contents": "", - "bgcolor": "7" - }, - "4,22": { - "contents": "", - "bgcolor": "7" - }, - "4,23": { - "contents": "", - "bgcolor": "7" - }, - "4,24": { - "contents": "", - "bgcolor": "7" - }, - "4,25": { - "contents": "", - "bgcolor": "7" - }, - "4,26": { - "contents": "", - "bgcolor": "7" - }, - "4,27": { - "contents": "", - "bgcolor": "7" - }, - "4,28": { - "contents": "", - "bgcolor": "7" - }, - "4,29": { - "contents": "", - "bgcolor": "7" - }, - "4,3": { - "contents": "", - "bgcolor": "7" - }, - "4,30": { - "contents": "", - "bgcolor": "7" - }, - "4,31": { - "contents": "", - "bgcolor": "7" - }, - "4,32": { - "contents": "", - "bgcolor": "7" - }, - "4,33": { - "contents": "", - "bgcolor": "7" - }, - "4,34": { - "contents": "", - "bgcolor": "7" - }, - "4,35": { - "contents": "", - "bgcolor": "7" - }, - "4,36": { - "contents": "", - "bgcolor": "7" - }, - "4,37": { - "contents": "", - "bgcolor": "7" - }, - "4,38": { - "contents": "", - "bgcolor": "7" - }, - "4,39": { - "contents": "", - "bgcolor": "7" - }, - "4,4": { - "contents": "", - "bgcolor": "7" - }, - "4,40": { - "contents": "", - "bgcolor": "7" - }, - "4,41": { - "contents": "", - "bgcolor": "7" - }, - "4,42": { - "contents": "", - "bgcolor": "7" - }, - "4,43": { - "contents": "", - "bgcolor": "7" - }, - "4,44": { - "contents": "", - "bgcolor": "7" - }, - "4,45": { - "contents": "", - "bgcolor": "7" - }, - "4,46": { - "contents": "", - "bgcolor": "7" - }, - "4,47": { - "contents": "", - "bgcolor": "7" - }, - "4,48": { - "contents": "", - "bgcolor": "7" - }, - "4,49": { - "contents": "", - "bgcolor": "7" - }, - "4,5": { - "contents": "", - "bgcolor": "7" - }, - "4,50": { - "contents": "", - "bgcolor": "7" - }, - "4,51": { - "contents": "", - "bgcolor": "7" - }, - "4,52": { - "contents": "", - "bgcolor": "7" - }, - "4,53": { - "contents": "", - "bgcolor": "7" - }, - "4,54": { - "contents": "", - "bgcolor": "7" - }, - "4,55": { - "contents": "", - "bgcolor": "7" - }, - "4,56": { - "contents": "", - "bgcolor": "7" - }, - "4,57": { - "contents": "", - "bgcolor": "7" - }, - "4,58": { - "contents": "", - "bgcolor": "7" - }, - "4,59": { - "contents": "", - "bgcolor": "7" - }, - "4,6": { - "contents": "", - "bgcolor": "7" - }, - "4,60": { - "contents": "", - "bgcolor": "7" - }, - "4,61": { - "contents": "", - "bgcolor": "7" - }, - "4,62": { - "contents": "", - "bgcolor": "7" - }, - "4,63": { - "contents": "", - "bgcolor": "7" - }, - "4,64": { - "contents": "", - "bgcolor": "7" - }, - "4,65": { - "contents": "", - "bgcolor": "7" - }, - "4,66": { - "contents": "", - "bgcolor": "7" - }, - "4,67": { - "contents": "", - "bgcolor": "7" - }, - "4,68": { - "contents": "", - "bgcolor": "7" - }, - "4,69": { - "contents": "", - "bgcolor": "7" - }, - "4,7": { - "contents": "", - "bgcolor": "7" - }, - "4,70": { - "contents": "", - "bgcolor": "7" - }, - "4,71": { - "contents": "", - "bgcolor": "7" - }, - "4,72": { - "contents": "", - "bgcolor": "7" - }, - "4,73": { - "contents": "", - "bgcolor": "7" - }, - "4,74": { - "contents": "", - "bgcolor": "7" - }, - "4,75": { - "contents": "", - "bgcolor": "7" - }, - "4,76": { - "contents": "", - "bgcolor": "7" - }, - "4,77": { - "contents": "", - "bgcolor": "7" - }, - "4,78": { - "contents": "", - "bgcolor": "7" - }, - "4,79": { - "contents": "", - "bgcolor": "7" - }, - "4,8": { - "contents": "", - "bgcolor": "7" - }, - "4,9": { - "contents": "", - "bgcolor": "7" - }, - "5,0": { - "contents": "", - "bgcolor": "7" - }, - "5,1": { - "contents": "", - "bgcolor": "7" - }, - "5,10": { - "contents": "", - "bgcolor": "7" - }, - "5,11": { - "contents": "", - "bgcolor": "7" - }, - "5,12": { - "contents": "", - "bgcolor": "7" - }, - "5,13": { - "contents": "", - "bgcolor": "7" - }, - "5,14": { - "contents": "", - "bgcolor": "7" - }, - "5,15": { - "contents": "", - "bgcolor": "7" - }, - "5,16": { - "contents": "", - "bgcolor": "7" - }, - "5,17": { - "contents": "", - "bgcolor": "7" - }, - "5,18": { - "contents": "", - "bgcolor": "7" - }, - "5,19": { - "contents": "", - "bgcolor": "7" - }, - "5,2": { - "contents": "", - "bgcolor": "7" - }, - "5,20": { - "contents": "", - "bgcolor": "7" - }, - "5,21": { - "contents": "", - "bgcolor": "7" - }, - "5,22": { - "contents": "", - "bgcolor": "7" - }, - "5,23": { - "contents": "", - "bgcolor": "7" - }, - "5,24": { - "contents": "", - "bgcolor": "7" - }, - "5,25": { - "contents": "", - "bgcolor": "7" - }, - "5,26": { - "contents": "", - "bgcolor": "7" - }, - "5,27": { - "contents": "", - "bgcolor": "7" - }, - "5,28": { - "contents": "", - "bgcolor": "7" - }, - "5,29": { - "contents": "", - "bgcolor": "7" - }, - "5,3": { - "contents": "", - "bgcolor": "7" - }, - "5,30": { - "contents": "", - "bgcolor": "7" - }, - "5,31": { - "contents": "", - "bgcolor": "7" - }, - "5,32": { - "contents": "", - "bgcolor": "7" - }, - "5,33": { - "contents": "", - "bgcolor": "7" - }, - "5,34": { - "contents": "", - "bgcolor": "7" - }, - "5,35": { - "contents": "", - "bgcolor": "7" - }, - "5,36": { - "contents": "", - "bgcolor": "7" - }, - "5,37": { - "contents": "", - "bgcolor": "7" - }, - "5,38": { - "contents": "", - "bgcolor": "7" - }, - "5,39": { - "contents": "", - "bgcolor": "7" - }, - "5,4": { - "contents": "", - "bgcolor": "7" - }, - "5,40": { - "contents": "", - "bgcolor": "7" - }, - "5,41": { - "contents": "", - "bgcolor": "7" - }, - "5,42": { - "contents": "", - "bgcolor": "7" - }, - "5,43": { - "contents": "", - "bgcolor": "7" - }, - "5,44": { - "contents": "", - "bgcolor": "7" - }, - "5,45": { - "contents": "", - "bgcolor": "7" - }, - "5,46": { - "contents": "", - "bgcolor": "7" - }, - "5,47": { - "contents": "", - "bgcolor": "7" - }, - "5,48": { - "contents": "", - "bgcolor": "7" - }, - "5,49": { - "contents": "", - "bgcolor": "7" - }, - "5,5": { - "contents": "", - "bgcolor": "7" - }, - "5,50": { - "contents": "", - "bgcolor": "7" - }, - "5,51": { - "contents": "", - "bgcolor": "7" - }, - "5,52": { - "contents": "", - "bgcolor": "7" - }, - "5,53": { - "contents": "", - "bgcolor": "7" - }, - "5,54": { - "contents": "", - "bgcolor": "7" - }, - "5,55": { - "contents": "", - "bgcolor": "7" - }, - "5,56": { - "contents": "", - "bgcolor": "7" - }, - "5,57": { - "contents": "", - "bgcolor": "7" - }, - "5,58": { - "contents": "", - "bgcolor": "7" - }, - "5,59": { - "contents": "", - "bgcolor": "7" - }, - "5,6": { - "contents": "", - "bgcolor": "7" - }, - "5,60": { - "contents": "", - "bgcolor": "7" - }, - "5,61": { - "contents": "", - "bgcolor": "7" - }, - "5,62": { - "contents": "", - "bgcolor": "7" - }, - "5,63": { - "contents": "", - "bgcolor": "7" - }, - "5,64": { - "contents": "", - "bgcolor": "7" - }, - "5,65": { - "contents": "", - "bgcolor": "7" - }, - "5,66": { - "contents": "", - "bgcolor": "7" - }, - "5,67": { - "contents": "", - "bgcolor": "7" - }, - "5,68": { - "contents": "", - "bgcolor": "7" - }, - "5,69": { - "contents": "", - "bgcolor": "7" - }, - "5,7": { - "contents": "", - "bgcolor": "7" - }, - "5,70": { - "contents": "", - "bgcolor": "7" - }, - "5,71": { - "contents": "", - "bgcolor": "7" - }, - "5,72": { - "contents": "", - "bgcolor": "7" - }, - "5,73": { - "contents": "", - "bgcolor": "7" - }, - "5,74": { - "contents": "", - "bgcolor": "7" - }, - "5,75": { - "contents": "", - "bgcolor": "7" - }, - "5,76": { - "contents": "", - "bgcolor": "7" - }, - "5,77": { - "contents": "", - "bgcolor": "7" - }, - "5,78": { - "contents": "", - "bgcolor": "7" - }, - "5,79": { - "contents": "", - "bgcolor": "7" - }, - "5,8": { - "contents": "", - "bgcolor": "7" - }, - "5,9": { - "contents": "", - "bgcolor": "7" - }, - "6,0": { - "contents": "", - "bgcolor": "7" - }, - "6,1": { - "contents": "", - "bgcolor": "7" - }, - "6,10": { - "contents": "", - "bgcolor": "7" - }, - "6,11": { - "contents": "", - "bgcolor": "7" - }, - "6,12": { - "contents": "", - "bgcolor": "7" - }, - "6,13": { - "contents": "", - "bgcolor": "7" - }, - "6,14": { - "contents": "", - "bgcolor": "7" - }, - "6,15": { - "contents": "", - "bgcolor": "7" - }, - "6,16": { - "contents": "", - "bgcolor": "7" - }, - "6,17": { - "contents": "", - "bgcolor": "7" - }, - "6,18": { - "contents": "", - "bgcolor": "7" - }, - "6,19": { - "contents": "", - "bgcolor": "7" - }, - "6,2": { - "contents": "", - "bgcolor": "7" - }, - "6,20": { - "contents": "", - "bgcolor": "7" - }, - "6,21": { - "contents": "", - "bgcolor": "7" - }, - "6,22": { - "contents": "", - "bgcolor": "7" - }, - "6,23": { - "contents": "", - "bgcolor": "7" - }, - "6,24": { - "contents": "", - "bgcolor": "7" - }, - "6,25": { - "contents": "", - "bgcolor": "7" - }, - "6,26": { - "contents": "", - "bgcolor": "7" - }, - "6,27": { - "contents": "", - "bgcolor": "7" - }, - "6,28": { - "contents": "", - "bgcolor": "7" - }, - "6,29": { - "contents": "", - "bgcolor": "7" - }, - "6,3": { - "contents": "", - "bgcolor": "7" - }, - "6,30": { - "contents": "", - "bgcolor": "7" - }, - "6,31": { - "contents": "", - "bgcolor": "7" - }, - "6,32": { - "contents": "", - "bgcolor": "7" - }, - "6,33": { - "contents": "", - "bgcolor": "7" - }, - "6,34": { - "contents": "", - "bgcolor": "7" - }, - "6,35": { - "contents": "", - "bgcolor": "7" - }, - "6,36": { - "contents": "", - "bgcolor": "7" - }, - "6,37": { - "contents": "", - "bgcolor": "7" - }, - "6,38": { - "contents": "", - "bgcolor": "7" - }, - "6,39": { - "contents": "", - "bgcolor": "7" - }, - "6,4": { - "contents": "", - "bgcolor": "7" - }, - "6,40": { - "contents": "", - "bgcolor": "7" - }, - "6,41": { - "contents": "", - "bgcolor": "7" - }, - "6,42": { - "contents": "", - "bgcolor": "7" - }, - "6,43": { - "contents": "", - "bgcolor": "7" - }, - "6,44": { - "contents": "", - "bgcolor": "7" - }, - "6,45": { - "contents": "", - "bgcolor": "7" - }, - "6,46": { - "contents": "", - "bgcolor": "7" - }, - "6,47": { - "contents": "", - "bgcolor": "7" - }, - "6,48": { - "contents": "", - "bgcolor": "7" - }, - "6,49": { - "contents": "", - "bgcolor": "7" - }, - "6,5": { - "contents": "", - "bgcolor": "7" - }, - "6,50": { - "contents": "", - "bgcolor": "7" - }, - "6,51": { - "contents": "", - "bgcolor": "7" - }, - "6,52": { - "contents": "", - "bgcolor": "7" - }, - "6,53": { - "contents": "", - "bgcolor": "7" - }, - "6,54": { - "contents": "", - "bgcolor": "7" - }, - "6,55": { - "contents": "", - "bgcolor": "7" - }, - "6,56": { - "contents": "", - "bgcolor": "7" - }, - "6,57": { - "contents": "", - "bgcolor": "7" - }, - "6,58": { - "contents": "", - "bgcolor": "7" - }, - "6,59": { - "contents": "", - "bgcolor": "7" - }, - "6,6": { - "contents": "", - "bgcolor": "7" - }, - "6,60": { - "contents": "", - "bgcolor": "7" - }, - "6,61": { - "contents": "", - "bgcolor": "7" - }, - "6,62": { - "contents": "", - "bgcolor": "7" - }, - "6,63": { - "contents": "", - "bgcolor": "7" - }, - "6,64": { - "contents": "", - "bgcolor": "7" - }, - "6,65": { - "contents": "", - "bgcolor": "7" - }, - "6,66": { - "contents": "", - "bgcolor": "7" - }, - "6,67": { - "contents": "", - "bgcolor": "7" - }, - "6,68": { - "contents": "", - "bgcolor": "7" - }, - "6,69": { - "contents": "", - "bgcolor": "7" - }, - "6,7": { - "contents": "", - "bgcolor": "7" - }, - "6,70": { - "contents": "", - "bgcolor": "7" - }, - "6,71": { - "contents": "", - "bgcolor": "7" - }, - "6,72": { - "contents": "", - "bgcolor": "7" - }, - "6,73": { - "contents": "", - "bgcolor": "7" - }, - "6,74": { - "contents": "", - "bgcolor": "7" - }, - "6,75": { - "contents": "", - "bgcolor": "7" - }, - "6,76": { - "contents": "", - "bgcolor": "7" - }, - "6,77": { - "contents": "", - "bgcolor": "7" - }, - "6,78": { - "contents": "", - "bgcolor": "7" - }, - "6,79": { - "contents": "", - "bgcolor": "7" - }, - "6,8": { - "contents": "", - "bgcolor": "7" - }, - "6,9": { - "contents": "", - "bgcolor": "7" - }, - "7,0": { - "contents": "", - "bgcolor": "7" - }, - "7,1": { - "contents": "", - "bgcolor": "7" - }, - "7,10": { - "contents": "", - "bgcolor": "7" - }, - "7,11": { - "contents": "", - "bgcolor": "7" - }, - "7,12": { - "contents": "", - "bgcolor": "7" - }, - "7,13": { - "contents": "", - "bgcolor": "7" - }, - "7,14": { - "contents": "", - "bgcolor": "7" - }, - "7,15": { - "contents": "", - "bgcolor": "7" - }, - "7,16": { - "contents": "", - "bgcolor": "7" - }, - "7,17": { - "contents": "", - "bgcolor": "7" - }, - "7,18": { - "contents": "", - "bgcolor": "7" - }, - "7,19": { - "contents": "", - "bgcolor": "7" - }, - "7,2": { - "contents": "", - "bgcolor": "7" - }, - "7,20": { - "contents": "", - "bgcolor": "7" - }, - "7,21": { - "contents": "", - "bgcolor": "7" - }, - "7,22": { - "contents": "", - "bgcolor": "7" - }, - "7,23": { - "contents": "", - "bgcolor": "7" - }, - "7,24": { - "contents": "", - "bgcolor": "7" - }, - "7,25": { - "contents": "", - "bgcolor": "7" - }, - "7,26": { - "contents": "", - "bgcolor": "7" - }, - "7,27": { - "contents": "", - "bgcolor": "7" - }, - "7,28": { - "contents": "", - "bgcolor": "7" - }, - "7,29": { - "contents": "", - "bgcolor": "7" - }, - "7,3": { - "contents": "", - "bgcolor": "7" - }, - "7,30": { - "contents": "", - "bgcolor": "7" - }, - "7,31": { - "contents": "", - "bgcolor": "7" - }, - "7,32": { - "contents": "", - "bgcolor": "7" - }, - "7,33": { - "contents": "", - "bgcolor": "7" - }, - "7,34": { - "contents": "", - "bgcolor": "7" - }, - "7,35": { - "contents": "", - "bgcolor": "7" - }, - "7,36": { - "contents": "", - "bgcolor": "7" - }, - "7,37": { - "contents": "", - "bgcolor": "7" - }, - "7,38": { - "contents": "", - "bgcolor": "7" - }, - "7,39": { - "contents": "", - "bgcolor": "7" - }, - "7,4": { - "contents": "", - "bgcolor": "7" - }, - "7,40": { - "contents": "", - "bgcolor": "7" - }, - "7,41": { - "contents": "", - "bgcolor": "7" - }, - "7,42": { - "contents": "", - "bgcolor": "7" - }, - "7,43": { - "contents": "", - "bgcolor": "7" - }, - "7,44": { - "contents": "", - "bgcolor": "7" - }, - "7,45": { - "contents": "", - "bgcolor": "7" - }, - "7,46": { - "contents": "", - "bgcolor": "7" - }, - "7,47": { - "contents": "", - "bgcolor": "7" - }, - "7,48": { - "contents": "", - "bgcolor": "7" - }, - "7,49": { - "contents": "", - "bgcolor": "7" - }, - "7,5": { - "contents": "", - "bgcolor": "7" - }, - "7,50": { - "contents": "", - "bgcolor": "7" - }, - "7,51": { - "contents": "", - "bgcolor": "7" - }, - "7,52": { - "contents": "", - "bgcolor": "7" - }, - "7,53": { - "contents": "", - "bgcolor": "7" - }, - "7,54": { - "contents": "", - "bgcolor": "7" - }, - "7,55": { - "contents": "", - "bgcolor": "7" - }, - "7,56": { - "contents": "", - "bgcolor": "7" - }, - "7,57": { - "contents": "", - "bgcolor": "7" - }, - "7,58": { - "contents": "", - "bgcolor": "7" - }, - "7,59": { - "contents": "", - "bgcolor": "7" - }, - "7,6": { - "contents": "", - "bgcolor": "7" - }, - "7,60": { - "contents": "", - "bgcolor": "7" - }, - "7,61": { - "contents": "", - "bgcolor": "7" - }, - "7,62": { - "contents": "", - "bgcolor": "7" - }, - "7,63": { - "contents": "", - "bgcolor": "7" - }, - "7,64": { - "contents": "", - "bgcolor": "7" - }, - "7,65": { - "contents": "", - "bgcolor": "7" - }, - "7,66": { - "contents": "", - "bgcolor": "7" - }, - "7,67": { - "contents": "", - "bgcolor": "7" - }, - "7,68": { - "contents": "", - "bgcolor": "7" - }, - "7,69": { - "contents": "", - "bgcolor": "7" - }, - "7,7": { - "contents": "", - "bgcolor": "7" - }, - "7,70": { - "contents": "", - "bgcolor": "7" - }, - "7,71": { - "contents": "", - "bgcolor": "7" - }, - "7,72": { - "contents": "", - "bgcolor": "7" - }, - "7,73": { - "contents": "", - "bgcolor": "7" - }, - "7,74": { - "contents": "", - "bgcolor": "7" - }, - "7,75": { - "contents": "", - "bgcolor": "7" - }, - "7,76": { - "contents": "", - "bgcolor": "7" - }, - "7,77": { - "contents": "", - "bgcolor": "7" - }, - "7,78": { - "contents": "", - "bgcolor": "7" - }, - "7,79": { - "contents": "", - "bgcolor": "7" - }, - "7,8": { - "contents": "", - "bgcolor": "7" - }, - "7,9": { - "contents": "", - "bgcolor": "7" - }, - "8,0": { - "contents": "", - "bgcolor": "7" - }, - "8,1": { - "contents": "", - "bgcolor": "7" - }, - "8,10": { - "contents": "", - "bgcolor": "7" - }, - "8,11": { - "contents": "", - "bgcolor": "7" - }, - "8,12": { - "contents": "", - "bgcolor": "7" - }, - "8,13": { - "contents": "", - "bgcolor": "7" - }, - "8,14": { - "contents": "", - "bgcolor": "7" - }, - "8,15": { - "contents": "", - "bgcolor": "7" - }, - "8,16": { - "contents": "", - "bgcolor": "7" - }, - "8,17": { - "contents": "", - "bgcolor": "7" - }, - "8,18": { - "contents": "", - "bgcolor": "7" - }, - "8,19": { - "contents": "", - "bgcolor": "7" - }, - "8,2": { - "contents": "", - "bgcolor": "7" - }, - "8,20": { - "contents": "", - "bgcolor": "7" - }, - "8,21": { - "contents": "", - "bgcolor": "7" - }, - "8,22": { - "contents": "", - "bgcolor": "7" - }, - "8,23": { - "contents": "", - "bgcolor": "7" - }, - "8,24": { - "contents": "", - "bgcolor": "7" - }, - "8,25": { - "contents": "", - "bgcolor": "7" - }, - "8,26": { - "contents": "", - "bgcolor": "7" - }, - "8,27": { - "contents": "", - "bgcolor": "7" - }, - "8,28": { - "contents": "", - "bgcolor": "7" - }, - "8,29": { - "contents": "", - "bgcolor": "7" - }, - "8,3": { - "contents": "", - "bgcolor": "7" - }, - "8,30": { - "contents": "", - "bgcolor": "7" - }, - "8,31": { - "contents": "", - "bgcolor": "7" - }, - "8,32": { - "contents": "", - "bgcolor": "7" - }, - "8,33": { - "contents": "", - "bgcolor": "7" - }, - "8,34": { - "contents": "", - "bgcolor": "7" - }, - "8,35": { - "contents": "", - "bgcolor": "7" - }, - "8,36": { - "contents": "", - "bgcolor": "7" - }, - "8,37": { - "contents": "", - "bgcolor": "7" - }, - "8,38": { - "contents": "", - "bgcolor": "7" - }, - "8,39": { - "contents": "", - "bgcolor": "7" - }, - "8,4": { - "contents": "", - "bgcolor": "7" - }, - "8,40": { - "contents": "", - "bgcolor": "7" - }, - "8,41": { - "contents": "", - "bgcolor": "7" - }, - "8,42": { - "contents": "", - "bgcolor": "7" - }, - "8,43": { - "contents": "", - "bgcolor": "7" - }, - "8,44": { - "contents": "", - "bgcolor": "7" - }, - "8,45": { - "contents": "", - "bgcolor": "7" - }, - "8,46": { - "contents": "", - "bgcolor": "7" - }, - "8,47": { - "contents": "", - "bgcolor": "7" - }, - "8,48": { - "contents": "", - "bgcolor": "7" - }, - "8,49": { - "contents": "", - "bgcolor": "7" - }, - "8,5": { - "contents": "", - "bgcolor": "7" - }, - "8,50": { - "contents": "", - "bgcolor": "7" - }, - "8,51": { - "contents": "", - "bgcolor": "7" - }, - "8,52": { - "contents": "", - "bgcolor": "7" - }, - "8,53": { - "contents": "", - "bgcolor": "7" - }, - "8,54": { - "contents": "", - "bgcolor": "7" - }, - "8,55": { - "contents": "", - "bgcolor": "7" - }, - "8,56": { - "contents": "", - "bgcolor": "7" - }, - "8,57": { - "contents": "", - "bgcolor": "7" - }, - "8,58": { - "contents": "", - "bgcolor": "7" - }, - "8,59": { - "contents": "", - "bgcolor": "7" - }, - "8,6": { - "contents": "", - "bgcolor": "7" - }, - "8,60": { - "contents": "", - "bgcolor": "7" - }, - "8,61": { - "contents": "", - "bgcolor": "7" - }, - "8,62": { - "contents": "", - "bgcolor": "7" - }, - "8,63": { - "contents": "", - "bgcolor": "7" - }, - "8,64": { - "contents": "", - "bgcolor": "7" - }, - "8,65": { - "contents": "", - "bgcolor": "7" - }, - "8,66": { - "contents": "", - "bgcolor": "7" - }, - "8,67": { - "contents": "", - "bgcolor": "7" - }, - "8,68": { - "contents": "", - "bgcolor": "7" - }, - "8,69": { - "contents": "", - "bgcolor": "7" - }, - "8,7": { - "contents": "", - "bgcolor": "7" - }, - "8,70": { - "contents": "", - "bgcolor": "7" - }, - "8,71": { - "contents": "", - "bgcolor": "7" - }, - "8,72": { - "contents": "", - "bgcolor": "7" - }, - "8,73": { - "contents": "", - "bgcolor": "7" - }, - "8,74": { - "contents": "", - "bgcolor": "7" - }, - "8,75": { - "contents": "", - "bgcolor": "7" - }, - "8,76": { - "contents": "", - "bgcolor": "7" - }, - "8,77": { - "contents": "", - "bgcolor": "7" - }, - "8,78": { - "contents": "", - "bgcolor": "7" - }, - "8,79": { - "contents": "", - "bgcolor": "7" - }, - "8,8": { - "contents": "", - "bgcolor": "7" - }, - "8,9": { - "contents": "", - "bgcolor": "7" - }, - "9,0": { - "contents": "", - "bgcolor": "7" - }, - "9,1": { - "contents": "", - "bgcolor": "7" - }, - "9,10": { - "contents": "", - "bgcolor": "7" - }, - "9,11": { - "contents": "", - "bgcolor": "7" - }, - "9,12": { - "contents": "", - "bgcolor": "7" - }, - "9,13": { - "contents": "", - "bgcolor": "7" - }, - "9,14": { - "contents": "", - "bgcolor": "7" - }, - "9,15": { - "contents": "", - "bgcolor": "7" - }, - "9,16": { - "contents": "", - "bgcolor": "7" - }, - "9,17": { - "contents": "", - "bgcolor": "7" - }, - "9,18": { - "contents": "", - "bgcolor": "7" - }, - "9,19": { - "contents": "", - "bgcolor": "7" - }, - "9,2": { - "contents": "", - "bgcolor": "7" - }, - "9,20": { - "contents": "", - "bgcolor": "7" - }, - "9,21": { - "contents": "", - "bgcolor": "7" - }, - "9,22": { - "contents": "", - "bgcolor": "7" - }, - "9,23": { - "contents": "", - "bgcolor": "7" - }, - "9,24": { - "contents": "", - "bgcolor": "7" - }, - "9,25": { - "contents": "", - "bgcolor": "7" - }, - "9,26": { - "contents": "", - "bgcolor": "7" - }, - "9,27": { - "contents": "", - "bgcolor": "7" - }, - "9,28": { - "contents": "", - "bgcolor": "7" - }, - "9,29": { - "contents": "", - "bgcolor": "7" - }, - "9,3": { - "contents": "", - "bgcolor": "7" - }, - "9,30": { - "contents": "", - "bgcolor": "7" - }, - "9,31": { - "contents": "", - "bgcolor": "7" - }, - "9,32": { - "contents": "", - "bgcolor": "7" - }, - "9,33": { - "contents": "", - "bgcolor": "7" - }, - "9,34": { - "contents": "", - "bgcolor": "7" - }, - "9,35": { - "contents": "", - "bgcolor": "7" - }, - "9,36": { - "contents": "", - "bgcolor": "7" - }, - "9,37": { - "contents": "", - "bgcolor": "7" - }, - "9,38": { - "contents": "", - "bgcolor": "7" - }, - "9,39": { - "contents": "", - "bgcolor": "7" - }, - "9,4": { - "contents": "", - "bgcolor": "7" - }, - "9,40": { - "contents": "", - "bgcolor": "7" - }, - "9,41": { - "contents": "", - "bgcolor": "7" - }, - "9,42": { - "contents": "", - "bgcolor": "7" - }, - "9,43": { - "contents": "", - "bgcolor": "7" - }, - "9,44": { - "contents": "", - "bgcolor": "7" - }, - "9,45": { - "contents": "", - "bgcolor": "7" - }, - "9,46": { - "contents": "", - "bgcolor": "7" - }, - "9,47": { - "contents": "", - "bgcolor": "7" - }, - "9,48": { - "contents": "", - "bgcolor": "7" - }, - "9,49": { - "contents": "", - "bgcolor": "7" - }, - "9,5": { - "contents": "", - "bgcolor": "7" - }, - "9,50": { - "contents": "", - "bgcolor": "7" - }, - "9,51": { - "contents": "", - "bgcolor": "7" - }, - "9,52": { - "contents": "", - "bgcolor": "7" - }, - "9,53": { - "contents": "", - "bgcolor": "7" - }, - "9,54": { - "contents": "", - "bgcolor": "7" - }, - "9,55": { - "contents": "", - "bgcolor": "7" - }, - "9,56": { - "contents": "", - "bgcolor": "7" - }, - "9,57": { - "contents": "", - "bgcolor": "7" - }, - "9,58": { - "contents": "", - "bgcolor": "7" - }, - "9,59": { - "contents": "", - "bgcolor": "7" - }, - "9,6": { - "contents": "", - "bgcolor": "7" - }, - "9,60": { - "contents": "", - "bgcolor": "7" - }, - "9,61": { - "contents": "", - "bgcolor": "7" - }, - "9,62": { - "contents": "", - "bgcolor": "7" - }, - "9,63": { - "contents": "", - "bgcolor": "7" - }, - "9,64": { - "contents": "", - "bgcolor": "7" - }, - "9,65": { - "contents": "", - "bgcolor": "7" - }, - "9,66": { - "contents": "", - "bgcolor": "7" - }, - "9,67": { - "contents": "", - "bgcolor": "7" - }, - "9,68": { - "contents": "", - "bgcolor": "7" - }, - "9,69": { - "contents": "", - "bgcolor": "7" - }, - "9,7": { - "contents": "", - "bgcolor": "7" - }, - "9,70": { - "contents": "", - "bgcolor": "7" - }, - "9,71": { - "contents": "", - "bgcolor": "7" - }, - "9,72": { - "contents": "", - "bgcolor": "7" - }, - "9,73": { - "contents": "", - "bgcolor": "7" - }, - "9,74": { - "contents": "", - "bgcolor": "7" - }, - "9,75": { - "contents": "", - "bgcolor": "7" - }, - "9,76": { - "contents": "", - "bgcolor": "7" - }, - "9,77": { - "contents": "", - "bgcolor": "7" - }, - "9,78": { - "contents": "", - "bgcolor": "7" - }, - "9,79": { - "contents": "", - "bgcolor": "7" - }, - "9,8": { - "contents": "", - "bgcolor": "7" - }, - "9,9": { - "contents": "", - "bgcolor": "7" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/14.typescript deleted file mode 100644 index 45bc66e68269b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/14.typescript +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/15.json b/crates/turborepo-vt100/tests/data/fixtures/colors/15.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/15.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/15.typescript deleted file mode 100644 index c46ac5f306169..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/15.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/16.json b/crates/turborepo-vt100/tests/data/fixtures/colors/16.json deleted file mode 100644 index a46e94f0a9188..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/16.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f", - "fgcolor": "10", - "bgcolor": "15" - }, - "0,1": { - "contents": "o", - "fgcolor": "10", - "bgcolor": "15" - }, - "0,2": { - "contents": "o", - "fgcolor": "10", - "bgcolor": "15" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/16.typescript deleted file mode 100644 index 148d8e01c54c5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/16.typescript +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/17.json b/crates/turborepo-vt100/tests/data/fixtures/colors/17.json deleted file mode 100644 index 629899c6b9b56..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/17.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/17.typescript deleted file mode 100644 index cab9aaf840118..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/17.typescript +++ /dev/null @@ -1 +0,0 @@ -cfoo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/18.json b/crates/turborepo-vt100/tests/data/fixtures/colors/18.json deleted file mode 100644 index 186024f16bf8d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/18.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o", - "bgcolor": "1" - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/18.typescript deleted file mode 100644 index d64f3e3b40956..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/18.typescript +++ /dev/null @@ -1 +0,0 @@ -o \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/19.json b/crates/turborepo-vt100/tests/data/fixtures/colors/19.json deleted file mode 100644 index 5b0a770dcbdb2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/19.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contents": " oo", - "cells": { - "0,0": { - "contents": "", - "bgcolor": "1" - }, - "0,1": { - "contents": "o", - "bgcolor": "1" - }, - "0,2": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/19.typescript deleted file mode 100644 index 407609225d233..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/19.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/2.json b/crates/turborepo-vt100/tests/data/fixtures/colors/2.json deleted file mode 100644 index c220a24965eb9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/2.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "contents": "foobab", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b", - "fgcolor": "1" - }, - "0,4": { - "contents": "a", - "fgcolor": "1", - "bgcolor": "5" - }, - "0,5": { - "contents": "b", - "fgcolor": "1", - "bgcolor": "5" - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/2.typescript deleted file mode 100644 index 0f129dc798e3e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/2.typescript +++ /dev/null @@ -1 +0,0 @@ -ab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/20.json b/crates/turborepo-vt100/tests/data/fixtures/colors/20.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/20.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/20.typescript deleted file mode 100644 index c46ac5f306169..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/20.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/21.json b/crates/turborepo-vt100/tests/data/fixtures/colors/21.json deleted file mode 100644 index a7a7ec691aa6c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/21.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": "abc", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b", - "fgcolor": "123" - }, - "0,2": { - "contents": "c", - "fgcolor": "123", - "bgcolor": "158" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/21.typescript deleted file mode 100644 index b9ce48621804c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/21.typescript +++ /dev/null @@ -1 +0,0 @@ -a[38:5:123mb[48:5:158mc \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/22.json b/crates/turborepo-vt100/tests/data/fixtures/colors/22.json deleted file mode 100644 index f4fa9fbabde45..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/22.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "contents": "abcde", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b", - "fgcolor": "123" - }, - "0,2": { - "contents": "c", - "fgcolor": "123", - "bgcolor": "158" - }, - "0,3": { - "contents": "d", - "fgcolor": "#324b64", - "bgcolor": "158" - }, - "0,4": { - "contents": "e", - "fgcolor": "#324b64", - "bgcolor": "#7d96af" - } - }, - "cursor_position": [ - 0, - 5 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/22.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/22.typescript deleted file mode 100644 index 32ab7e423d001..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/22.typescript +++ /dev/null @@ -1 +0,0 @@ -[38:2:50:75:100md[48:2:125:150:175me \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/3.json b/crates/turborepo-vt100/tests/data/fixtures/colors/3.json deleted file mode 100644 index c220a24965eb9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/3.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "contents": "foobab", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b", - "fgcolor": "1" - }, - "0,4": { - "contents": "a", - "fgcolor": "1", - "bgcolor": "5" - }, - "0,5": { - "contents": "b", - "fgcolor": "1", - "bgcolor": "5" - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/3.typescript deleted file mode 100644 index 327aa11ac13af..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/4.json b/crates/turborepo-vt100/tests/data/fixtures/colors/4.json deleted file mode 100644 index f388f19b2dc45..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/4.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "contents": "foobab\n\n\n\n\n\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b", - "fgcolor": "1" - }, - "0,4": { - "contents": "a", - "fgcolor": "1", - "bgcolor": "5" - }, - "0,5": { - "contents": "b", - "fgcolor": "1", - "bgcolor": "5" - }, - "14,14": { - "contents": "f" - }, - "14,15": { - "contents": "o" - }, - "14,16": { - "contents": "o" - }, - "14,17": { - "contents": "b", - "fgcolor": "1" - }, - "14,18": { - "contents": "a", - "fgcolor": "1" - }, - "14,19": { - "contents": "r", - "fgcolor": "1" - } - }, - "cursor_position": [ - 14, - 20 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/4.typescript deleted file mode 100644 index 016e28a20b095..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/4.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/5.json b/crates/turborepo-vt100/tests/data/fixtures/colors/5.json deleted file mode 100644 index 96e408de18e77..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/5.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "contents": "foobab\n\n\n\n\n\n\n\n\n\n\n\n\n\n foobab", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b", - "fgcolor": "1" - }, - "0,4": { - "contents": "a", - "fgcolor": "1", - "bgcolor": "5" - }, - "0,5": { - "contents": "b", - "fgcolor": "1", - "bgcolor": "5" - }, - "14,14": { - "contents": "f" - }, - "14,15": { - "contents": "o" - }, - "14,16": { - "contents": "o" - }, - "14,17": { - "contents": "b", - "fgcolor": "1" - }, - "14,18": { - "contents": "a", - "bgcolor": "5" - }, - "14,19": { - "contents": "b", - "bgcolor": "5" - } - }, - "cursor_position": [ - 14, - 20 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/5.typescript deleted file mode 100644 index 0f129dc798e3e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/5.typescript +++ /dev/null @@ -1 +0,0 @@ -ab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/6.json b/crates/turborepo-vt100/tests/data/fixtures/colors/6.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/6.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/6.typescript deleted file mode 100644 index c46ac5f306169..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/7.json b/crates/turborepo-vt100/tests/data/fixtures/colors/7.json deleted file mode 100644 index a7a7ec691aa6c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/7.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": "abc", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b", - "fgcolor": "123" - }, - "0,2": { - "contents": "c", - "fgcolor": "123", - "bgcolor": "158" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/7.typescript deleted file mode 100644 index 9e9f16fe9a37b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/7.typescript +++ /dev/null @@ -1 +0,0 @@ -abc \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/8.json b/crates/turborepo-vt100/tests/data/fixtures/colors/8.json deleted file mode 100644 index f4fa9fbabde45..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/8.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "contents": "abcde", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b", - "fgcolor": "123" - }, - "0,2": { - "contents": "c", - "fgcolor": "123", - "bgcolor": "158" - }, - "0,3": { - "contents": "d", - "fgcolor": "#324b64", - "bgcolor": "158" - }, - "0,4": { - "contents": "e", - "fgcolor": "#324b64", - "bgcolor": "#7d96af" - } - }, - "cursor_position": [ - 0, - 5 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/8.typescript deleted file mode 100644 index 05065955a9df2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/8.typescript +++ /dev/null @@ -1 +0,0 @@ -de \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/9.json b/crates/turborepo-vt100/tests/data/fixtures/colors/9.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/9.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/colors/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/colors/9.typescript deleted file mode 100644 index c46ac5f306169..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/colors/9.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining.in b/crates/turborepo-vt100/tests/data/fixtures/combining.in deleted file mode 100644 index 5f6292050f0b1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining.in +++ /dev/null @@ -1,14 +0,0 @@ -a -\u{0301} -\x1bcabcdefg -\x1b[1;6H\u{0301} -\x1b[10;78Haaa -\r\n\u{0301} -\x1bcabcdefg\x1b[1;3H\u{0301} -\x1b[1;2Hb\x1b[1;8H -\x1bcabcdefg -\x1bcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -\u{0301} -\x1b[H\x1b[Jï½\u{0301} -\x1b[H\x1b[J\x1b[2C\u{0301} -\x1b[H\x1b[J\x1b[1;79Hï½\x08\u{301} diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/1.json b/crates/turborepo-vt100/tests/data/fixtures/combining/1.json deleted file mode 100644 index 14dbc432d92ca..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/1.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "a", - "cells": { - "0,0": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/1.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/1.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/10.json b/crates/turborepo-vt100/tests/data/fixtures/combining/10.json deleted file mode 100644 index b8306c78da9cd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/10.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "contents": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "a" - }, - "0,10": { - "contents": "a" - }, - "0,11": { - "contents": "a" - }, - "0,12": { - "contents": "a" - }, - "0,13": { - "contents": "a" - }, - "0,14": { - "contents": "a" - }, - "0,15": { - "contents": "a" - }, - "0,16": { - "contents": "a" - }, - "0,17": { - "contents": "a" - }, - "0,18": { - "contents": "a" - }, - "0,19": { - "contents": "a" - }, - "0,2": { - "contents": "a" - }, - "0,20": { - "contents": "a" - }, - "0,21": { - "contents": "a" - }, - "0,22": { - "contents": "a" - }, - "0,23": { - "contents": "a" - }, - "0,24": { - "contents": "a" - }, - "0,25": { - "contents": "a" - }, - "0,26": { - "contents": "a" - }, - "0,27": { - "contents": "a" - }, - "0,28": { - "contents": "a" - }, - "0,29": { - "contents": "a" - }, - "0,3": { - "contents": "a" - }, - "0,30": { - "contents": "a" - }, - "0,31": { - "contents": "a" - }, - "0,32": { - "contents": "a" - }, - "0,33": { - "contents": "a" - }, - "0,34": { - "contents": "a" - }, - "0,35": { - "contents": "a" - }, - "0,36": { - "contents": "a" - }, - "0,37": { - "contents": "a" - }, - "0,38": { - "contents": "a" - }, - "0,39": { - "contents": "a" - }, - "0,4": { - "contents": "a" - }, - "0,40": { - "contents": "a" - }, - "0,41": { - "contents": "a" - }, - "0,42": { - "contents": "a" - }, - "0,43": { - "contents": "a" - }, - "0,44": { - "contents": "a" - }, - "0,45": { - "contents": "a" - }, - "0,46": { - "contents": "a" - }, - "0,47": { - "contents": "a" - }, - "0,48": { - "contents": "a" - }, - "0,49": { - "contents": "a" - }, - "0,5": { - "contents": "a" - }, - "0,50": { - "contents": "a" - }, - "0,51": { - "contents": "a" - }, - "0,52": { - "contents": "a" - }, - "0,53": { - "contents": "a" - }, - "0,54": { - "contents": "a" - }, - "0,55": { - "contents": "a" - }, - "0,56": { - "contents": "a" - }, - "0,57": { - "contents": "a" - }, - "0,58": { - "contents": "a" - }, - "0,59": { - "contents": "a" - }, - "0,6": { - "contents": "a" - }, - "0,60": { - "contents": "a" - }, - "0,61": { - "contents": "a" - }, - "0,62": { - "contents": "a" - }, - "0,63": { - "contents": "a" - }, - "0,64": { - "contents": "a" - }, - "0,65": { - "contents": "a" - }, - "0,66": { - "contents": "a" - }, - "0,67": { - "contents": "a" - }, - "0,68": { - "contents": "a" - }, - "0,69": { - "contents": "a" - }, - "0,7": { - "contents": "a" - }, - "0,70": { - "contents": "a" - }, - "0,71": { - "contents": "a" - }, - "0,72": { - "contents": "a" - }, - "0,73": { - "contents": "a" - }, - "0,74": { - "contents": "a" - }, - "0,75": { - "contents": "a" - }, - "0,76": { - "contents": "a" - }, - "0,77": { - "contents": "a" - }, - "0,78": { - "contents": "a" - }, - "0,79": { - "contents": "a" - }, - "0,8": { - "contents": "a" - }, - "0,9": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/10.typescript deleted file mode 100644 index d22b9d6476ebd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/10.typescript +++ /dev/null @@ -1 +0,0 @@ -caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/11.json b/crates/turborepo-vt100/tests/data/fixtures/combining/11.json deleted file mode 100644 index 14822edd47c66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/11.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "contents": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaÌ", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "a" - }, - "0,10": { - "contents": "a" - }, - "0,11": { - "contents": "a" - }, - "0,12": { - "contents": "a" - }, - "0,13": { - "contents": "a" - }, - "0,14": { - "contents": "a" - }, - "0,15": { - "contents": "a" - }, - "0,16": { - "contents": "a" - }, - "0,17": { - "contents": "a" - }, - "0,18": { - "contents": "a" - }, - "0,19": { - "contents": "a" - }, - "0,2": { - "contents": "a" - }, - "0,20": { - "contents": "a" - }, - "0,21": { - "contents": "a" - }, - "0,22": { - "contents": "a" - }, - "0,23": { - "contents": "a" - }, - "0,24": { - "contents": "a" - }, - "0,25": { - "contents": "a" - }, - "0,26": { - "contents": "a" - }, - "0,27": { - "contents": "a" - }, - "0,28": { - "contents": "a" - }, - "0,29": { - "contents": "a" - }, - "0,3": { - "contents": "a" - }, - "0,30": { - "contents": "a" - }, - "0,31": { - "contents": "a" - }, - "0,32": { - "contents": "a" - }, - "0,33": { - "contents": "a" - }, - "0,34": { - "contents": "a" - }, - "0,35": { - "contents": "a" - }, - "0,36": { - "contents": "a" - }, - "0,37": { - "contents": "a" - }, - "0,38": { - "contents": "a" - }, - "0,39": { - "contents": "a" - }, - "0,4": { - "contents": "a" - }, - "0,40": { - "contents": "a" - }, - "0,41": { - "contents": "a" - }, - "0,42": { - "contents": "a" - }, - "0,43": { - "contents": "a" - }, - "0,44": { - "contents": "a" - }, - "0,45": { - "contents": "a" - }, - "0,46": { - "contents": "a" - }, - "0,47": { - "contents": "a" - }, - "0,48": { - "contents": "a" - }, - "0,49": { - "contents": "a" - }, - "0,5": { - "contents": "a" - }, - "0,50": { - "contents": "a" - }, - "0,51": { - "contents": "a" - }, - "0,52": { - "contents": "a" - }, - "0,53": { - "contents": "a" - }, - "0,54": { - "contents": "a" - }, - "0,55": { - "contents": "a" - }, - "0,56": { - "contents": "a" - }, - "0,57": { - "contents": "a" - }, - "0,58": { - "contents": "a" - }, - "0,59": { - "contents": "a" - }, - "0,6": { - "contents": "a" - }, - "0,60": { - "contents": "a" - }, - "0,61": { - "contents": "a" - }, - "0,62": { - "contents": "a" - }, - "0,63": { - "contents": "a" - }, - "0,64": { - "contents": "a" - }, - "0,65": { - "contents": "a" - }, - "0,66": { - "contents": "a" - }, - "0,67": { - "contents": "a" - }, - "0,68": { - "contents": "a" - }, - "0,69": { - "contents": "a" - }, - "0,7": { - "contents": "a" - }, - "0,70": { - "contents": "a" - }, - "0,71": { - "contents": "a" - }, - "0,72": { - "contents": "a" - }, - "0,73": { - "contents": "a" - }, - "0,74": { - "contents": "a" - }, - "0,75": { - "contents": "a" - }, - "0,76": { - "contents": "a" - }, - "0,77": { - "contents": "a" - }, - "0,78": { - "contents": "a" - }, - "0,79": { - "contents": "aÌ" - }, - "0,8": { - "contents": "a" - }, - "0,9": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/11.typescript deleted file mode 100644 index 7f2a378569147..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/11.typescript +++ /dev/null @@ -1 +0,0 @@ -Ì \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/12.json b/crates/turborepo-vt100/tests/data/fixtures/combining/12.json deleted file mode 100644 index c68dfd0f76297..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/12.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "contents": "ï½Ì", - "cells": { - "0,0": { - "contents": "ï½Ì", - "is_wide": true - }, - "0,1": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/12.typescript deleted file mode 100644 index bfa327b126cb9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/12.typescript +++ /dev/null @@ -1 +0,0 @@ -ï½Ì \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/13.json b/crates/turborepo-vt100/tests/data/fixtures/combining/13.json deleted file mode 100644 index e963384fff678..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/13.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": " Ì", - "cells": { - "0,1": { - "contents": " Ì" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/13.typescript deleted file mode 100644 index 966367960b655..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/13.typescript +++ /dev/null @@ -1 +0,0 @@ -Ì \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/14.json b/crates/turborepo-vt100/tests/data/fixtures/combining/14.json deleted file mode 100644 index bdc1fe26f5188..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/14.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "contents": " ï½Ì", - "cells": { - "0,78": { - "contents": "ï½Ì", - "is_wide": true - }, - "0,79": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/14.typescript deleted file mode 100644 index 513bc907a0b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/14.typescript +++ /dev/null @@ -1 +0,0 @@ -ï½Ì \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/2.json b/crates/turborepo-vt100/tests/data/fixtures/combining/2.json deleted file mode 100644 index 83172089520e5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/2.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "aÌ", - "cells": { - "0,0": { - "contents": "aÌ" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/2.typescript deleted file mode 100644 index 7f2a378569147..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/2.typescript +++ /dev/null @@ -1 +0,0 @@ -Ì \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/3.json b/crates/turborepo-vt100/tests/data/fixtures/combining/3.json deleted file mode 100644 index f95003e529553..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/3.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "abcdefg", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "d" - }, - "0,4": { - "contents": "e" - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "g" - } - }, - "cursor_position": [ - 0, - 7 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/3.typescript deleted file mode 100644 index cc9609c6f2f59..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/3.typescript +++ /dev/null @@ -1 +0,0 @@ -cabcdefg \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/4.json b/crates/turborepo-vt100/tests/data/fixtures/combining/4.json deleted file mode 100644 index 74a34b1d1dfac..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/4.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "abcdeÌfg", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "d" - }, - "0,4": { - "contents": "eÌ" - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "g" - } - }, - "cursor_position": [ - 0, - 5 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/4.typescript deleted file mode 100644 index 80ea857932421..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/4.typescript +++ /dev/null @@ -1 +0,0 @@ -Ì \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/5.json b/crates/turborepo-vt100/tests/data/fixtures/combining/5.json deleted file mode 100644 index f655d0f6f8958..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/5.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "contents": "abcdeÌfg\n\n\n\n\n\n\n\n\n aaa", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "d" - }, - "0,4": { - "contents": "eÌ" - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "g" - }, - "9,77": { - "contents": "a" - }, - "9,78": { - "contents": "a" - }, - "9,79": { - "contents": "a" - } - }, - "cursor_position": [ - 9, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/5.typescript deleted file mode 100644 index 844421a22496a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/5.typescript +++ /dev/null @@ -1 +0,0 @@ -aaa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/6.json b/crates/turborepo-vt100/tests/data/fixtures/combining/6.json deleted file mode 100644 index c0ed46595047f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/6.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "contents": "abcdeÌfg\n\n\n\n\n\n\n\n\n aaa", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "d" - }, - "0,4": { - "contents": "eÌ" - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "g" - }, - "9,77": { - "contents": "a" - }, - "9,78": { - "contents": "a" - }, - "9,79": { - "contents": "a" - } - }, - "cursor_position": [ - 10, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/6.typescript deleted file mode 100644 index 5160196ae2c47..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/6.typescript +++ /dev/null @@ -1,2 +0,0 @@ - -Ì \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/7.json b/crates/turborepo-vt100/tests/data/fixtures/combining/7.json deleted file mode 100644 index 151d517dd2109..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/7.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "abÌcdefg", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "bÌ" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "d" - }, - "0,4": { - "contents": "e" - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "g" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/7.typescript deleted file mode 100644 index bd18e8c671e31..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/7.typescript +++ /dev/null @@ -1 +0,0 @@ -cabcdefgÌ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/8.json b/crates/turborepo-vt100/tests/data/fixtures/combining/8.json deleted file mode 100644 index f95003e529553..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/8.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "abcdefg", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "d" - }, - "0,4": { - "contents": "e" - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "g" - } - }, - "cursor_position": [ - 0, - 7 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/8.typescript deleted file mode 100644 index f92dea95c504e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/8.typescript +++ /dev/null @@ -1 +0,0 @@ -b \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/9.json b/crates/turborepo-vt100/tests/data/fixtures/combining/9.json deleted file mode 100644 index f95003e529553..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/9.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "abcdefg", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "d" - }, - "0,4": { - "contents": "e" - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "g" - } - }, - "cursor_position": [ - 0, - 7 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/combining/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/combining/9.typescript deleted file mode 100644 index cc9609c6f2f59..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/combining/9.typescript +++ /dev/null @@ -1 +0,0 @@ -cabcdefg \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/cr.in b/crates/turborepo-vt100/tests/data/fixtures/cr.in deleted file mode 100644 index 927cf2b4541be..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/cr.in +++ /dev/null @@ -1 +0,0 @@ -fooo\rbar diff --git a/crates/turborepo-vt100/tests/data/fixtures/cr/1.json b/crates/turborepo-vt100/tests/data/fixtures/cr/1.json deleted file mode 100644 index 4491176620f59..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/cr/1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": "baro", - "cells": { - "0,0": { - "contents": "b" - }, - "0,1": { - "contents": "a" - }, - "0,2": { - "contents": "r" - }, - "0,3": { - "contents": "o" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/cr/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/cr/1.typescript deleted file mode 100644 index 4cb9fe1b6d34b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/cr/1.typescript +++ /dev/null @@ -1 +0,0 @@ -fooo bar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/deckpam.in b/crates/turborepo-vt100/tests/data/fixtures/deckpam.in deleted file mode 100644 index 62f751c24fb21..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/deckpam.in +++ /dev/null @@ -1,2 +0,0 @@ -\x1b= -\x1b> diff --git a/crates/turborepo-vt100/tests/data/fixtures/deckpam/1.json b/crates/turborepo-vt100/tests/data/fixtures/deckpam/1.json deleted file mode 100644 index 2c0890837967a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/deckpam/1.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/deckpam/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/deckpam/1.typescript deleted file mode 100644 index efa8c1976b93d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/deckpam/1.typescript +++ /dev/null @@ -1 +0,0 @@ -= \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/deckpam/2.json b/crates/turborepo-vt100/tests/data/fixtures/deckpam/2.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/deckpam/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/deckpam/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/deckpam/2.typescript deleted file mode 100644 index 989bcaf3eaa4d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/deckpam/2.typescript +++ /dev/null @@ -1 +0,0 @@ -> \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc.in b/crates/turborepo-vt100/tests/data/fixtures/decsc.in deleted file mode 100644 index e70d6f35f0004..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc.in +++ /dev/null @@ -1,8 +0,0 @@ -foo\x1b7\r\n\r\n\r\n bar\x1b8baz -\x1b[?47h\x1b[20;20H -\x1b8 -\x1b[?47l\x1b[20;20H -\x1b8 -\x1bc\x1b[31m\x1b[5;15r\x1b[?6hfoo\x1b7 -\x1b[32m\x1b[?6lbar -\x1b8\x1b[Hz diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/1.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/1.json deleted file mode 100644 index 32284d870226e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/1.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "contents": "foobaz\n\n\n bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b" - }, - "0,4": { - "contents": "a" - }, - "0,5": { - "contents": "z" - }, - "3,0": { - "contents": " " - }, - "3,1": { - "contents": " " - }, - "3,10": { - "contents": "a" - }, - "3,11": { - "contents": "r" - }, - "3,2": { - "contents": " " - }, - "3,3": { - "contents": " " - }, - "3,4": { - "contents": " " - }, - "3,5": { - "contents": " " - }, - "3,6": { - "contents": " " - }, - "3,7": { - "contents": " " - }, - "3,8": { - "contents": " " - }, - "3,9": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/1.typescript deleted file mode 100644 index 9add335c1eeff..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/1.typescript +++ /dev/null @@ -1,4 +0,0 @@ -foo7 - - - bar8baz \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/2.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/2.json deleted file mode 100644 index e4ca43f7663cd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 19, - 19 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/2.typescript deleted file mode 100644 index 78288a0255f93..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/2.typescript +++ /dev/null @@ -1 +0,0 @@ -[?47h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/3.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/3.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/3.typescript deleted file mode 100644 index d663f3baec9b5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/3.typescript +++ /dev/null @@ -1 +0,0 @@ -8 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/4.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/4.json deleted file mode 100644 index 61d9c006538b7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/4.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "contents": "foobaz\n\n\n bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b" - }, - "0,4": { - "contents": "a" - }, - "0,5": { - "contents": "z" - }, - "3,0": { - "contents": " " - }, - "3,1": { - "contents": " " - }, - "3,10": { - "contents": "a" - }, - "3,11": { - "contents": "r" - }, - "3,2": { - "contents": " " - }, - "3,3": { - "contents": " " - }, - "3,4": { - "contents": " " - }, - "3,5": { - "contents": " " - }, - "3,6": { - "contents": " " - }, - "3,7": { - "contents": " " - }, - "3,8": { - "contents": " " - }, - "3,9": { - "contents": "b" - } - }, - "cursor_position": [ - 19, - 19 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/4.typescript deleted file mode 100644 index c350ca480592d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/4.typescript +++ /dev/null @@ -1 +0,0 @@ -[?47l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/5.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/5.json deleted file mode 100644 index abf36acd9c5f8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/5.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "contents": "foobaz\n\n\n bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,3": { - "contents": "b" - }, - "0,4": { - "contents": "a" - }, - "0,5": { - "contents": "z" - }, - "3,0": { - "contents": " " - }, - "3,1": { - "contents": " " - }, - "3,10": { - "contents": "a" - }, - "3,11": { - "contents": "r" - }, - "3,2": { - "contents": " " - }, - "3,3": { - "contents": " " - }, - "3,4": { - "contents": " " - }, - "3,5": { - "contents": " " - }, - "3,6": { - "contents": " " - }, - "3,7": { - "contents": " " - }, - "3,8": { - "contents": " " - }, - "3,9": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/5.typescript deleted file mode 100644 index d663f3baec9b5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/5.typescript +++ /dev/null @@ -1 +0,0 @@ -8 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/6.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/6.json deleted file mode 100644 index 3b83db6113085..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/6.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": "\n\n\n\nfoo", - "cells": { - "4,0": { - "contents": "f", - "fgcolor": "1" - }, - "4,1": { - "contents": "o", - "fgcolor": "1" - }, - "4,2": { - "contents": "o", - "fgcolor": "1" - } - }, - "cursor_position": [ - 4, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/6.typescript deleted file mode 100644 index 1393eafc4d0e1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/6.typescript +++ /dev/null @@ -1 +0,0 @@ -c[?6hfoo7 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/7.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/7.json deleted file mode 100644 index f9e219e964267..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/7.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "contents": "bar\n\n\n\nfoo", - "cells": { - "0,0": { - "contents": "b", - "fgcolor": "2" - }, - "0,1": { - "contents": "a", - "fgcolor": "2" - }, - "0,2": { - "contents": "r", - "fgcolor": "2" - }, - "4,0": { - "contents": "f", - "fgcolor": "1" - }, - "4,1": { - "contents": "o", - "fgcolor": "1" - }, - "4,2": { - "contents": "o", - "fgcolor": "1" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/7.typescript deleted file mode 100644 index f93f99f8ec82e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/7.typescript +++ /dev/null @@ -1 +0,0 @@ -[?6lbar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/8.json b/crates/turborepo-vt100/tests/data/fixtures/decsc/8.json deleted file mode 100644 index e81b34461a3e5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/8.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "contents": "bar\n\n\n\nzoo", - "cells": { - "0,0": { - "contents": "b", - "fgcolor": "2" - }, - "0,1": { - "contents": "a", - "fgcolor": "2" - }, - "0,2": { - "contents": "r", - "fgcolor": "2" - }, - "4,0": { - "contents": "z", - "fgcolor": "1" - }, - "4,1": { - "contents": "o", - "fgcolor": "1" - }, - "4,2": { - "contents": "o", - "fgcolor": "1" - } - }, - "cursor_position": [ - 4, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decsc/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/decsc/8.typescript deleted file mode 100644 index 47ee51e364e55..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decsc/8.typescript +++ /dev/null @@ -1 +0,0 @@ -8z \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm.in b/crates/turborepo-vt100/tests/data/fixtures/decstbm.in deleted file mode 100644 index ac622516dc0ac..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm.in +++ /dev/null @@ -1,15 +0,0 @@ -\x1b[m\x1b[2J\x1b[H1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24 -\x1b[24;50H\n -\x1b[m\x1b[2J\x1b[H1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24 -\x1b[10;20r -\x1b[20;50H -\n -\x1b[B -\x1b[20A -\x1b[1;24r\x1b[m\x1b[2J\x1b[H1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24 -\x1b[10;20r\x1b[15;50H\x1b[2L -\x1b[10;50H\x1bM -\x1b[23d -\n -\x1bc -\x1b[10;15r\x1b[24;80Hab diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/1.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/1.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/1.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/1.typescript deleted file mode 100644 index a1817811d27cb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/1.typescript +++ /dev/null @@ -1,24 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/10.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/10.json deleted file mode 100644 index efd6bf51decac..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/10.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n\n\n15\n16\n17\n18\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "5" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "6" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "7" - }, - "19,0": { - "contents": "1" - }, - "19,1": { - "contents": "8" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 14, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/10.typescript deleted file mode 100644 index 75651933d08a2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/10.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/11.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/11.json deleted file mode 100644 index 33bc3cf3b55e2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/11.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n\n10\n11\n12\n13\n14\n\n\n15\n16\n17\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "0" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "1" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "2" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "3" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "4" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "5" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "6" - }, - "19,0": { - "contents": "1" - }, - "19,1": { - "contents": "7" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - } - }, - "cursor_position": [ - 9, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/11.typescript deleted file mode 100644 index 804a0b7111e25..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/11.typescript +++ /dev/null @@ -1 +0,0 @@ -M \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/12.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/12.json deleted file mode 100644 index 68a2fc65b4d50..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/12.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n\n10\n11\n12\n13\n14\n\n\n15\n16\n17\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "0" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "1" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "2" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "3" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "4" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "5" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "6" - }, - "19,0": { - "contents": "1" - }, - "19,1": { - "contents": "7" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - } - }, - "cursor_position": [ - 22, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/12.typescript deleted file mode 100644 index 634e556493496..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/12.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/13.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/13.json deleted file mode 100644 index c2f485493529e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/13.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n\n10\n11\n12\n13\n14\n\n\n15\n16\n17\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "0" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "1" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "2" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "3" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "4" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "5" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "6" - }, - "19,0": { - "contents": "1" - }, - "19,1": { - "contents": "7" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - } - }, - "cursor_position": [ - 23, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/14.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/14.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/14.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/14.typescript deleted file mode 100644 index c10be5482cd97..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/14.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/15.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/15.json deleted file mode 100644 index ce67a467cfb5b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/15.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nb a", - "cells": { - "23,0": { - "contents": "b" - }, - "23,79": { - "contents": "a" - } - }, - "cursor_position": [ - 23, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/15.typescript deleted file mode 100644 index 3b646b893c7b1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/15.typescript +++ /dev/null @@ -1 +0,0 @@ -ab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/2.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/2.json deleted file mode 100644 index ab552db317dcc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/2.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "contents": "2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "2" - }, - "1,0": { - "contents": "3" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "2" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "3" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "4" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "5" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "6" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "7" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "8" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "9" - }, - "18,0": { - "contents": "2" - }, - "18,1": { - "contents": "0" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "1" - }, - "2,0": { - "contents": "4" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "2" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "3" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "4" - }, - "3,0": { - "contents": "5" - }, - "4,0": { - "contents": "6" - }, - "5,0": { - "contents": "7" - }, - "6,0": { - "contents": "8" - }, - "7,0": { - "contents": "9" - }, - "8,0": { - "contents": "1" - }, - "8,1": { - "contents": "0" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "1" - } - }, - "cursor_position": [ - 23, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/2.typescript deleted file mode 100644 index 3c74c0f079b61..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/2.typescript +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/3.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/3.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/3.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/3.typescript deleted file mode 100644 index a1817811d27cb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/3.typescript +++ /dev/null @@ -1,24 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/4.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/4.json deleted file mode 100644 index 4c28a7f4d7f89..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/4.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 9, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/4.typescript deleted file mode 100644 index 437e867e5352a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/5.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/5.json deleted file mode 100644 index 9f22d4c1ac226..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/5.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 19, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/5.typescript deleted file mode 100644 index 34e60c8cc03f8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/5.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/6.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/6.json deleted file mode 100644 index e210507255e5a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/6.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "2" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "3" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "4" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "5" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "6" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "7" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "8" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "9" - }, - "18,0": { - "contents": "2" - }, - "18,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "1" - } - }, - "cursor_position": [ - 19, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/7.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/7.json deleted file mode 100644 index e210507255e5a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/7.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "2" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "3" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "4" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "5" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "6" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "7" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "8" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "9" - }, - "18,0": { - "contents": "2" - }, - "18,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "1" - } - }, - "cursor_position": [ - 19, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/7.typescript deleted file mode 100644 index 0513f6dcaaf10..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/7.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/8.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/8.json deleted file mode 100644 index bbbf401c93273..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/8.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "2" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "3" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "4" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "5" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "6" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "7" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "8" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "9" - }, - "18,0": { - "contents": "2" - }, - "18,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "1" - } - }, - "cursor_position": [ - 9, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/8.typescript deleted file mode 100644 index 3f72233403190..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/8.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/9.json b/crates/turborepo-vt100/tests/data/fixtures/decstbm/9.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/9.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/decstbm/9.typescript deleted file mode 100644 index 991b9816d8424..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/decstbm/9.typescript +++ /dev/null @@ -1,24 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed.in b/crates/turborepo-vt100/tests/data/fixtures/ed.in deleted file mode 100644 index dc58f7b515cd3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed.in +++ /dev/null @@ -1,21 +0,0 @@ -foo\x1b[5;5Hbar\x1b[10;10Hbaz\x1b[20;20Hquux -\x1b[10;12H\x1b[0J -\x1b[5;6H\x1b[1J -\x1b[7;7H\x1b[2J -\x1b[2J\x1b[H -foo\x1b[5;5Hbar\x1b[10;10Hbaz\x1b[20;20Hquux -\x1b[10;12H\x1b[J -\x1b[2J\x1b[H -foo\x1b[5;5Hbar\x1b[10;10Hbaz\x1b[20;20Hquux -\x1b[10;12H\x1b[?0J -\x1b[5;6H\x1b[?1J -\x1b[7;7H\x1b[?2J -\x1b[2J\x1b[H -foo\x1b[5;5Hbar\x1b[10;10Hbaz\x1b[20;20Hquux -\x1b[10;12H\x1b[?J -\x1bc\x1b[5;5H -\x1b[41m\x1b[J -\x1bc\x1b[5;5H -\x1b[41m\x1b[1J -\x1bc\x1b[5;5H -\x1b[41m\x1b[2J diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/1.json b/crates/turborepo-vt100/tests/data/fixtures/ed/1.json deleted file mode 100644 index 20eb131a98123..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/1.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 19, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/1.typescript deleted file mode 100644 index 40386b5b83af5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foobarbazquux \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/10.json b/crates/turborepo-vt100/tests/data/fixtures/ed/10.json deleted file mode 100644 index fe26558462bd5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/10.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n ba", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/10.typescript deleted file mode 100644 index 7b4b4403aed0b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/10.typescript +++ /dev/null @@ -1 +0,0 @@ -[?0J \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/11.json b/crates/turborepo-vt100/tests/data/fixtures/ed/11.json deleted file mode 100644 index 0b5f1154d1163..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/11.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "\n\n\n\n r\n\n\n\n\n ba", - "cells": { - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 4, - 5 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/11.typescript deleted file mode 100644 index 8ad852ffbb3cc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/11.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1J \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/12.json b/crates/turborepo-vt100/tests/data/fixtures/ed/12.json deleted file mode 100644 index 9ffb2f54c656b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/12.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 6, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/12.typescript deleted file mode 100644 index 83b2bb6d96951..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/12.typescript +++ /dev/null @@ -1 +0,0 @@ -[?2J \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/13.json b/crates/turborepo-vt100/tests/data/fixtures/ed/13.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/13.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/13.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/13.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/14.json b/crates/turborepo-vt100/tests/data/fixtures/ed/14.json deleted file mode 100644 index 20eb131a98123..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/14.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 19, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/14.typescript deleted file mode 100644 index 40386b5b83af5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/14.typescript +++ /dev/null @@ -1 +0,0 @@ -foobarbazquux \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/15.json b/crates/turborepo-vt100/tests/data/fixtures/ed/15.json deleted file mode 100644 index fe26558462bd5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/15.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n ba", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/15.typescript deleted file mode 100644 index ee0543578d4f1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/15.typescript +++ /dev/null @@ -1 +0,0 @@ -[?J \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/16.json b/crates/turborepo-vt100/tests/data/fixtures/ed/16.json deleted file mode 100644 index 2b060efecfe66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/16.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/16.typescript deleted file mode 100644 index 8adc44f0bdefe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/16.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/17.json b/crates/turborepo-vt100/tests/data/fixtures/ed/17.json deleted file mode 100644 index 66440051942de..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/17.json +++ /dev/null @@ -1,6393 +0,0 @@ -{ - "contents": "", - "cells": { - "10,0": { - "contents": "", - "bgcolor": "1" - }, - "10,1": { - "contents": "", - "bgcolor": "1" - }, - "10,10": { - "contents": "", - "bgcolor": "1" - }, - "10,11": { - "contents": "", - "bgcolor": "1" - }, - "10,12": { - "contents": "", - "bgcolor": "1" - }, - "10,13": { - "contents": "", - "bgcolor": "1" - }, - "10,14": { - "contents": "", - "bgcolor": "1" - }, - "10,15": { - "contents": "", - "bgcolor": "1" - }, - "10,16": { - "contents": "", - "bgcolor": "1" - }, - "10,17": { - "contents": "", - "bgcolor": "1" - }, - "10,18": { - "contents": "", - "bgcolor": "1" - }, - "10,19": { - "contents": "", - "bgcolor": "1" - }, - "10,2": { - "contents": "", - "bgcolor": "1" - }, - "10,20": { - "contents": "", - "bgcolor": "1" - }, - "10,21": { - "contents": "", - "bgcolor": "1" - }, - "10,22": { - "contents": "", - "bgcolor": "1" - }, - "10,23": { - "contents": "", - "bgcolor": "1" - }, - "10,24": { - "contents": "", - "bgcolor": "1" - }, - "10,25": { - "contents": "", - "bgcolor": "1" - }, - "10,26": { - "contents": "", - "bgcolor": "1" - }, - "10,27": { - "contents": "", - "bgcolor": "1" - }, - "10,28": { - "contents": "", - "bgcolor": "1" - }, - "10,29": { - "contents": "", - "bgcolor": "1" - }, - "10,3": { - "contents": "", - "bgcolor": "1" - }, - "10,30": { - "contents": "", - "bgcolor": "1" - }, - "10,31": { - "contents": "", - "bgcolor": "1" - }, - "10,32": { - "contents": "", - "bgcolor": "1" - }, - "10,33": { - "contents": "", - "bgcolor": "1" - }, - "10,34": { - "contents": "", - "bgcolor": "1" - }, - "10,35": { - "contents": "", - "bgcolor": "1" - }, - "10,36": { - "contents": "", - "bgcolor": "1" - }, - "10,37": { - "contents": "", - "bgcolor": "1" - }, - "10,38": { - "contents": "", - "bgcolor": "1" - }, - "10,39": { - "contents": "", - "bgcolor": "1" - }, - "10,4": { - "contents": "", - "bgcolor": "1" - }, - "10,40": { - "contents": "", - "bgcolor": "1" - }, - "10,41": { - "contents": "", - "bgcolor": "1" - }, - "10,42": { - "contents": "", - "bgcolor": "1" - }, - "10,43": { - "contents": "", - "bgcolor": "1" - }, - "10,44": { - "contents": "", - "bgcolor": "1" - }, - "10,45": { - "contents": "", - "bgcolor": "1" - }, - "10,46": { - "contents": "", - "bgcolor": "1" - }, - "10,47": { - "contents": "", - "bgcolor": "1" - }, - "10,48": { - "contents": "", - "bgcolor": "1" - }, - "10,49": { - "contents": "", - "bgcolor": "1" - }, - "10,5": { - "contents": "", - "bgcolor": "1" - }, - "10,50": { - "contents": "", - "bgcolor": "1" - }, - "10,51": { - "contents": "", - "bgcolor": "1" - }, - "10,52": { - "contents": "", - "bgcolor": "1" - }, - "10,53": { - "contents": "", - "bgcolor": "1" - }, - "10,54": { - "contents": "", - "bgcolor": "1" - }, - "10,55": { - "contents": "", - "bgcolor": "1" - }, - "10,56": { - "contents": "", - "bgcolor": "1" - }, - "10,57": { - "contents": "", - "bgcolor": "1" - }, - "10,58": { - "contents": "", - "bgcolor": "1" - }, - "10,59": { - "contents": "", - "bgcolor": "1" - }, - "10,6": { - "contents": "", - "bgcolor": "1" - }, - "10,60": { - "contents": "", - "bgcolor": "1" - }, - "10,61": { - "contents": "", - "bgcolor": "1" - }, - "10,62": { - "contents": "", - "bgcolor": "1" - }, - "10,63": { - "contents": "", - "bgcolor": "1" - }, - "10,64": { - "contents": "", - "bgcolor": "1" - }, - "10,65": { - "contents": "", - "bgcolor": "1" - }, - "10,66": { - "contents": "", - "bgcolor": "1" - }, - "10,67": { - "contents": "", - "bgcolor": "1" - }, - "10,68": { - "contents": "", - "bgcolor": "1" - }, - "10,69": { - "contents": "", - "bgcolor": "1" - }, - "10,7": { - "contents": "", - "bgcolor": "1" - }, - "10,70": { - "contents": "", - "bgcolor": "1" - }, - "10,71": { - "contents": "", - "bgcolor": "1" - }, - "10,72": { - "contents": "", - "bgcolor": "1" - }, - "10,73": { - "contents": "", - "bgcolor": "1" - }, - "10,74": { - "contents": "", - "bgcolor": "1" - }, - "10,75": { - "contents": "", - "bgcolor": "1" - }, - "10,76": { - "contents": "", - "bgcolor": "1" - }, - "10,77": { - "contents": "", - "bgcolor": "1" - }, - "10,78": { - "contents": "", - "bgcolor": "1" - }, - "10,79": { - "contents": "", - "bgcolor": "1" - }, - "10,8": { - "contents": "", - "bgcolor": "1" - }, - "10,9": { - "contents": "", - "bgcolor": "1" - }, - "11,0": { - "contents": "", - "bgcolor": "1" - }, - "11,1": { - "contents": "", - "bgcolor": "1" - }, - "11,10": { - "contents": "", - "bgcolor": "1" - }, - "11,11": { - "contents": "", - "bgcolor": "1" - }, - "11,12": { - "contents": "", - "bgcolor": "1" - }, - "11,13": { - "contents": "", - "bgcolor": "1" - }, - "11,14": { - "contents": "", - "bgcolor": "1" - }, - "11,15": { - "contents": "", - "bgcolor": "1" - }, - "11,16": { - "contents": "", - "bgcolor": "1" - }, - "11,17": { - "contents": "", - "bgcolor": "1" - }, - "11,18": { - "contents": "", - "bgcolor": "1" - }, - "11,19": { - "contents": "", - "bgcolor": "1" - }, - "11,2": { - "contents": "", - "bgcolor": "1" - }, - "11,20": { - "contents": "", - "bgcolor": "1" - }, - "11,21": { - "contents": "", - "bgcolor": "1" - }, - "11,22": { - "contents": "", - "bgcolor": "1" - }, - "11,23": { - "contents": "", - "bgcolor": "1" - }, - "11,24": { - "contents": "", - "bgcolor": "1" - }, - "11,25": { - "contents": "", - "bgcolor": "1" - }, - "11,26": { - "contents": "", - "bgcolor": "1" - }, - "11,27": { - "contents": "", - "bgcolor": "1" - }, - "11,28": { - "contents": "", - "bgcolor": "1" - }, - "11,29": { - "contents": "", - "bgcolor": "1" - }, - "11,3": { - "contents": "", - "bgcolor": "1" - }, - "11,30": { - "contents": "", - "bgcolor": "1" - }, - "11,31": { - "contents": "", - "bgcolor": "1" - }, - "11,32": { - "contents": "", - "bgcolor": "1" - }, - "11,33": { - "contents": "", - "bgcolor": "1" - }, - "11,34": { - "contents": "", - "bgcolor": "1" - }, - "11,35": { - "contents": "", - "bgcolor": "1" - }, - "11,36": { - "contents": "", - "bgcolor": "1" - }, - "11,37": { - "contents": "", - "bgcolor": "1" - }, - "11,38": { - "contents": "", - "bgcolor": "1" - }, - "11,39": { - "contents": "", - "bgcolor": "1" - }, - "11,4": { - "contents": "", - "bgcolor": "1" - }, - "11,40": { - "contents": "", - "bgcolor": "1" - }, - "11,41": { - "contents": "", - "bgcolor": "1" - }, - "11,42": { - "contents": "", - "bgcolor": "1" - }, - "11,43": { - "contents": "", - "bgcolor": "1" - }, - "11,44": { - "contents": "", - "bgcolor": "1" - }, - "11,45": { - "contents": "", - "bgcolor": "1" - }, - "11,46": { - "contents": "", - "bgcolor": "1" - }, - "11,47": { - "contents": "", - "bgcolor": "1" - }, - "11,48": { - "contents": "", - "bgcolor": "1" - }, - "11,49": { - "contents": "", - "bgcolor": "1" - }, - "11,5": { - "contents": "", - "bgcolor": "1" - }, - "11,50": { - "contents": "", - "bgcolor": "1" - }, - "11,51": { - "contents": "", - "bgcolor": "1" - }, - "11,52": { - "contents": "", - "bgcolor": "1" - }, - "11,53": { - "contents": "", - "bgcolor": "1" - }, - "11,54": { - "contents": "", - "bgcolor": "1" - }, - "11,55": { - "contents": "", - "bgcolor": "1" - }, - "11,56": { - "contents": "", - "bgcolor": "1" - }, - "11,57": { - "contents": "", - "bgcolor": "1" - }, - "11,58": { - "contents": "", - "bgcolor": "1" - }, - "11,59": { - "contents": "", - "bgcolor": "1" - }, - "11,6": { - "contents": "", - "bgcolor": "1" - }, - "11,60": { - "contents": "", - "bgcolor": "1" - }, - "11,61": { - "contents": "", - "bgcolor": "1" - }, - "11,62": { - "contents": "", - "bgcolor": "1" - }, - "11,63": { - "contents": "", - "bgcolor": "1" - }, - "11,64": { - "contents": "", - "bgcolor": "1" - }, - "11,65": { - "contents": "", - "bgcolor": "1" - }, - "11,66": { - "contents": "", - "bgcolor": "1" - }, - "11,67": { - "contents": "", - "bgcolor": "1" - }, - "11,68": { - "contents": "", - "bgcolor": "1" - }, - "11,69": { - "contents": "", - "bgcolor": "1" - }, - "11,7": { - "contents": "", - "bgcolor": "1" - }, - "11,70": { - "contents": "", - "bgcolor": "1" - }, - "11,71": { - "contents": "", - "bgcolor": "1" - }, - "11,72": { - "contents": "", - "bgcolor": "1" - }, - "11,73": { - "contents": "", - "bgcolor": "1" - }, - "11,74": { - "contents": "", - "bgcolor": "1" - }, - "11,75": { - "contents": "", - "bgcolor": "1" - }, - "11,76": { - "contents": "", - "bgcolor": "1" - }, - "11,77": { - "contents": "", - "bgcolor": "1" - }, - "11,78": { - "contents": "", - "bgcolor": "1" - }, - "11,79": { - "contents": "", - "bgcolor": "1" - }, - "11,8": { - "contents": "", - "bgcolor": "1" - }, - "11,9": { - "contents": "", - "bgcolor": "1" - }, - "12,0": { - "contents": "", - "bgcolor": "1" - }, - "12,1": { - "contents": "", - "bgcolor": "1" - }, - "12,10": { - "contents": "", - "bgcolor": "1" - }, - "12,11": { - "contents": "", - "bgcolor": "1" - }, - "12,12": { - "contents": "", - "bgcolor": "1" - }, - "12,13": { - "contents": "", - "bgcolor": "1" - }, - "12,14": { - "contents": "", - "bgcolor": "1" - }, - "12,15": { - "contents": "", - "bgcolor": "1" - }, - "12,16": { - "contents": "", - "bgcolor": "1" - }, - "12,17": { - "contents": "", - "bgcolor": "1" - }, - "12,18": { - "contents": "", - "bgcolor": "1" - }, - "12,19": { - "contents": "", - "bgcolor": "1" - }, - "12,2": { - "contents": "", - "bgcolor": "1" - }, - "12,20": { - "contents": "", - "bgcolor": "1" - }, - "12,21": { - "contents": "", - "bgcolor": "1" - }, - "12,22": { - "contents": "", - "bgcolor": "1" - }, - "12,23": { - "contents": "", - "bgcolor": "1" - }, - "12,24": { - "contents": "", - "bgcolor": "1" - }, - "12,25": { - "contents": "", - "bgcolor": "1" - }, - "12,26": { - "contents": "", - "bgcolor": "1" - }, - "12,27": { - "contents": "", - "bgcolor": "1" - }, - "12,28": { - "contents": "", - "bgcolor": "1" - }, - "12,29": { - "contents": "", - "bgcolor": "1" - }, - "12,3": { - "contents": "", - "bgcolor": "1" - }, - "12,30": { - "contents": "", - "bgcolor": "1" - }, - "12,31": { - "contents": "", - "bgcolor": "1" - }, - "12,32": { - "contents": "", - "bgcolor": "1" - }, - "12,33": { - "contents": "", - "bgcolor": "1" - }, - "12,34": { - "contents": "", - "bgcolor": "1" - }, - "12,35": { - "contents": "", - "bgcolor": "1" - }, - "12,36": { - "contents": "", - "bgcolor": "1" - }, - "12,37": { - "contents": "", - "bgcolor": "1" - }, - "12,38": { - "contents": "", - "bgcolor": "1" - }, - "12,39": { - "contents": "", - "bgcolor": "1" - }, - "12,4": { - "contents": "", - "bgcolor": "1" - }, - "12,40": { - "contents": "", - "bgcolor": "1" - }, - "12,41": { - "contents": "", - "bgcolor": "1" - }, - "12,42": { - "contents": "", - "bgcolor": "1" - }, - "12,43": { - "contents": "", - "bgcolor": "1" - }, - "12,44": { - "contents": "", - "bgcolor": "1" - }, - "12,45": { - "contents": "", - "bgcolor": "1" - }, - "12,46": { - "contents": "", - "bgcolor": "1" - }, - "12,47": { - "contents": "", - "bgcolor": "1" - }, - "12,48": { - "contents": "", - "bgcolor": "1" - }, - "12,49": { - "contents": "", - "bgcolor": "1" - }, - "12,5": { - "contents": "", - "bgcolor": "1" - }, - "12,50": { - "contents": "", - "bgcolor": "1" - }, - "12,51": { - "contents": "", - "bgcolor": "1" - }, - "12,52": { - "contents": "", - "bgcolor": "1" - }, - "12,53": { - "contents": "", - "bgcolor": "1" - }, - "12,54": { - "contents": "", - "bgcolor": "1" - }, - "12,55": { - "contents": "", - "bgcolor": "1" - }, - "12,56": { - "contents": "", - "bgcolor": "1" - }, - "12,57": { - "contents": "", - "bgcolor": "1" - }, - "12,58": { - "contents": "", - "bgcolor": "1" - }, - "12,59": { - "contents": "", - "bgcolor": "1" - }, - "12,6": { - "contents": "", - "bgcolor": "1" - }, - "12,60": { - "contents": "", - "bgcolor": "1" - }, - "12,61": { - "contents": "", - "bgcolor": "1" - }, - "12,62": { - "contents": "", - "bgcolor": "1" - }, - "12,63": { - "contents": "", - "bgcolor": "1" - }, - "12,64": { - "contents": "", - "bgcolor": "1" - }, - "12,65": { - "contents": "", - "bgcolor": "1" - }, - "12,66": { - "contents": "", - "bgcolor": "1" - }, - "12,67": { - "contents": "", - "bgcolor": "1" - }, - "12,68": { - "contents": "", - "bgcolor": "1" - }, - "12,69": { - "contents": "", - "bgcolor": "1" - }, - "12,7": { - "contents": "", - "bgcolor": "1" - }, - "12,70": { - "contents": "", - "bgcolor": "1" - }, - "12,71": { - "contents": "", - "bgcolor": "1" - }, - "12,72": { - "contents": "", - "bgcolor": "1" - }, - "12,73": { - "contents": "", - "bgcolor": "1" - }, - "12,74": { - "contents": "", - "bgcolor": "1" - }, - "12,75": { - "contents": "", - "bgcolor": "1" - }, - "12,76": { - "contents": "", - "bgcolor": "1" - }, - "12,77": { - "contents": "", - "bgcolor": "1" - }, - "12,78": { - "contents": "", - "bgcolor": "1" - }, - "12,79": { - "contents": "", - "bgcolor": "1" - }, - "12,8": { - "contents": "", - "bgcolor": "1" - }, - "12,9": { - "contents": "", - "bgcolor": "1" - }, - "13,0": { - "contents": "", - "bgcolor": "1" - }, - "13,1": { - "contents": "", - "bgcolor": "1" - }, - "13,10": { - "contents": "", - "bgcolor": "1" - }, - "13,11": { - "contents": "", - "bgcolor": "1" - }, - "13,12": { - "contents": "", - "bgcolor": "1" - }, - "13,13": { - "contents": "", - "bgcolor": "1" - }, - "13,14": { - "contents": "", - "bgcolor": "1" - }, - "13,15": { - "contents": "", - "bgcolor": "1" - }, - "13,16": { - "contents": "", - "bgcolor": "1" - }, - "13,17": { - "contents": "", - "bgcolor": "1" - }, - "13,18": { - "contents": "", - "bgcolor": "1" - }, - "13,19": { - "contents": "", - "bgcolor": "1" - }, - "13,2": { - "contents": "", - "bgcolor": "1" - }, - "13,20": { - "contents": "", - "bgcolor": "1" - }, - "13,21": { - "contents": "", - "bgcolor": "1" - }, - "13,22": { - "contents": "", - "bgcolor": "1" - }, - "13,23": { - "contents": "", - "bgcolor": "1" - }, - "13,24": { - "contents": "", - "bgcolor": "1" - }, - "13,25": { - "contents": "", - "bgcolor": "1" - }, - "13,26": { - "contents": "", - "bgcolor": "1" - }, - "13,27": { - "contents": "", - "bgcolor": "1" - }, - "13,28": { - "contents": "", - "bgcolor": "1" - }, - "13,29": { - "contents": "", - "bgcolor": "1" - }, - "13,3": { - "contents": "", - "bgcolor": "1" - }, - "13,30": { - "contents": "", - "bgcolor": "1" - }, - "13,31": { - "contents": "", - "bgcolor": "1" - }, - "13,32": { - "contents": "", - "bgcolor": "1" - }, - "13,33": { - "contents": "", - "bgcolor": "1" - }, - "13,34": { - "contents": "", - "bgcolor": "1" - }, - "13,35": { - "contents": "", - "bgcolor": "1" - }, - "13,36": { - "contents": "", - "bgcolor": "1" - }, - "13,37": { - "contents": "", - "bgcolor": "1" - }, - "13,38": { - "contents": "", - "bgcolor": "1" - }, - "13,39": { - "contents": "", - "bgcolor": "1" - }, - "13,4": { - "contents": "", - "bgcolor": "1" - }, - "13,40": { - "contents": "", - "bgcolor": "1" - }, - "13,41": { - "contents": "", - "bgcolor": "1" - }, - "13,42": { - "contents": "", - "bgcolor": "1" - }, - "13,43": { - "contents": "", - "bgcolor": "1" - }, - "13,44": { - "contents": "", - "bgcolor": "1" - }, - "13,45": { - "contents": "", - "bgcolor": "1" - }, - "13,46": { - "contents": "", - "bgcolor": "1" - }, - "13,47": { - "contents": "", - "bgcolor": "1" - }, - "13,48": { - "contents": "", - "bgcolor": "1" - }, - "13,49": { - "contents": "", - "bgcolor": "1" - }, - "13,5": { - "contents": "", - "bgcolor": "1" - }, - "13,50": { - "contents": "", - "bgcolor": "1" - }, - "13,51": { - "contents": "", - "bgcolor": "1" - }, - "13,52": { - "contents": "", - "bgcolor": "1" - }, - "13,53": { - "contents": "", - "bgcolor": "1" - }, - "13,54": { - "contents": "", - "bgcolor": "1" - }, - "13,55": { - "contents": "", - "bgcolor": "1" - }, - "13,56": { - "contents": "", - "bgcolor": "1" - }, - "13,57": { - "contents": "", - "bgcolor": "1" - }, - "13,58": { - "contents": "", - "bgcolor": "1" - }, - "13,59": { - "contents": "", - "bgcolor": "1" - }, - "13,6": { - "contents": "", - "bgcolor": "1" - }, - "13,60": { - "contents": "", - "bgcolor": "1" - }, - "13,61": { - "contents": "", - "bgcolor": "1" - }, - "13,62": { - "contents": "", - "bgcolor": "1" - }, - "13,63": { - "contents": "", - "bgcolor": "1" - }, - "13,64": { - "contents": "", - "bgcolor": "1" - }, - "13,65": { - "contents": "", - "bgcolor": "1" - }, - "13,66": { - "contents": "", - "bgcolor": "1" - }, - "13,67": { - "contents": "", - "bgcolor": "1" - }, - "13,68": { - "contents": "", - "bgcolor": "1" - }, - "13,69": { - "contents": "", - "bgcolor": "1" - }, - "13,7": { - "contents": "", - "bgcolor": "1" - }, - "13,70": { - "contents": "", - "bgcolor": "1" - }, - "13,71": { - "contents": "", - "bgcolor": "1" - }, - "13,72": { - "contents": "", - "bgcolor": "1" - }, - "13,73": { - "contents": "", - "bgcolor": "1" - }, - "13,74": { - "contents": "", - "bgcolor": "1" - }, - "13,75": { - "contents": "", - "bgcolor": "1" - }, - "13,76": { - "contents": "", - "bgcolor": "1" - }, - "13,77": { - "contents": "", - "bgcolor": "1" - }, - "13,78": { - "contents": "", - "bgcolor": "1" - }, - "13,79": { - "contents": "", - "bgcolor": "1" - }, - "13,8": { - "contents": "", - "bgcolor": "1" - }, - "13,9": { - "contents": "", - "bgcolor": "1" - }, - "14,0": { - "contents": "", - "bgcolor": "1" - }, - "14,1": { - "contents": "", - "bgcolor": "1" - }, - "14,10": { - "contents": "", - "bgcolor": "1" - }, - "14,11": { - "contents": "", - "bgcolor": "1" - }, - "14,12": { - "contents": "", - "bgcolor": "1" - }, - "14,13": { - "contents": "", - "bgcolor": "1" - }, - "14,14": { - "contents": "", - "bgcolor": "1" - }, - "14,15": { - "contents": "", - "bgcolor": "1" - }, - "14,16": { - "contents": "", - "bgcolor": "1" - }, - "14,17": { - "contents": "", - "bgcolor": "1" - }, - "14,18": { - "contents": "", - "bgcolor": "1" - }, - "14,19": { - "contents": "", - "bgcolor": "1" - }, - "14,2": { - "contents": "", - "bgcolor": "1" - }, - "14,20": { - "contents": "", - "bgcolor": "1" - }, - "14,21": { - "contents": "", - "bgcolor": "1" - }, - "14,22": { - "contents": "", - "bgcolor": "1" - }, - "14,23": { - "contents": "", - "bgcolor": "1" - }, - "14,24": { - "contents": "", - "bgcolor": "1" - }, - "14,25": { - "contents": "", - "bgcolor": "1" - }, - "14,26": { - "contents": "", - "bgcolor": "1" - }, - "14,27": { - "contents": "", - "bgcolor": "1" - }, - "14,28": { - "contents": "", - "bgcolor": "1" - }, - "14,29": { - "contents": "", - "bgcolor": "1" - }, - "14,3": { - "contents": "", - "bgcolor": "1" - }, - "14,30": { - "contents": "", - "bgcolor": "1" - }, - "14,31": { - "contents": "", - "bgcolor": "1" - }, - "14,32": { - "contents": "", - "bgcolor": "1" - }, - "14,33": { - "contents": "", - "bgcolor": "1" - }, - "14,34": { - "contents": "", - "bgcolor": "1" - }, - "14,35": { - "contents": "", - "bgcolor": "1" - }, - "14,36": { - "contents": "", - "bgcolor": "1" - }, - "14,37": { - "contents": "", - "bgcolor": "1" - }, - "14,38": { - "contents": "", - "bgcolor": "1" - }, - "14,39": { - "contents": "", - "bgcolor": "1" - }, - "14,4": { - "contents": "", - "bgcolor": "1" - }, - "14,40": { - "contents": "", - "bgcolor": "1" - }, - "14,41": { - "contents": "", - "bgcolor": "1" - }, - "14,42": { - "contents": "", - "bgcolor": "1" - }, - "14,43": { - "contents": "", - "bgcolor": "1" - }, - "14,44": { - "contents": "", - "bgcolor": "1" - }, - "14,45": { - "contents": "", - "bgcolor": "1" - }, - "14,46": { - "contents": "", - "bgcolor": "1" - }, - "14,47": { - "contents": "", - "bgcolor": "1" - }, - "14,48": { - "contents": "", - "bgcolor": "1" - }, - "14,49": { - "contents": "", - "bgcolor": "1" - }, - "14,5": { - "contents": "", - "bgcolor": "1" - }, - "14,50": { - "contents": "", - "bgcolor": "1" - }, - "14,51": { - "contents": "", - "bgcolor": "1" - }, - "14,52": { - "contents": "", - "bgcolor": "1" - }, - "14,53": { - "contents": "", - "bgcolor": "1" - }, - "14,54": { - "contents": "", - "bgcolor": "1" - }, - "14,55": { - "contents": "", - "bgcolor": "1" - }, - "14,56": { - "contents": "", - "bgcolor": "1" - }, - "14,57": { - "contents": "", - "bgcolor": "1" - }, - "14,58": { - "contents": "", - "bgcolor": "1" - }, - "14,59": { - "contents": "", - "bgcolor": "1" - }, - "14,6": { - "contents": "", - "bgcolor": "1" - }, - "14,60": { - "contents": "", - "bgcolor": "1" - }, - "14,61": { - "contents": "", - "bgcolor": "1" - }, - "14,62": { - "contents": "", - "bgcolor": "1" - }, - "14,63": { - "contents": "", - "bgcolor": "1" - }, - "14,64": { - "contents": "", - "bgcolor": "1" - }, - "14,65": { - "contents": "", - "bgcolor": "1" - }, - "14,66": { - "contents": "", - "bgcolor": "1" - }, - "14,67": { - "contents": "", - "bgcolor": "1" - }, - "14,68": { - "contents": "", - "bgcolor": "1" - }, - "14,69": { - "contents": "", - "bgcolor": "1" - }, - "14,7": { - "contents": "", - "bgcolor": "1" - }, - "14,70": { - "contents": "", - "bgcolor": "1" - }, - "14,71": { - "contents": "", - "bgcolor": "1" - }, - "14,72": { - "contents": "", - "bgcolor": "1" - }, - "14,73": { - "contents": "", - "bgcolor": "1" - }, - "14,74": { - "contents": "", - "bgcolor": "1" - }, - "14,75": { - "contents": "", - "bgcolor": "1" - }, - "14,76": { - "contents": "", - "bgcolor": "1" - }, - "14,77": { - "contents": "", - "bgcolor": "1" - }, - "14,78": { - "contents": "", - "bgcolor": "1" - }, - "14,79": { - "contents": "", - "bgcolor": "1" - }, - "14,8": { - "contents": "", - "bgcolor": "1" - }, - "14,9": { - "contents": "", - "bgcolor": "1" - }, - "15,0": { - "contents": "", - "bgcolor": "1" - }, - "15,1": { - "contents": "", - "bgcolor": "1" - }, - "15,10": { - "contents": "", - "bgcolor": "1" - }, - "15,11": { - "contents": "", - "bgcolor": "1" - }, - "15,12": { - "contents": "", - "bgcolor": "1" - }, - "15,13": { - "contents": "", - "bgcolor": "1" - }, - "15,14": { - "contents": "", - "bgcolor": "1" - }, - "15,15": { - "contents": "", - "bgcolor": "1" - }, - "15,16": { - "contents": "", - "bgcolor": "1" - }, - "15,17": { - "contents": "", - "bgcolor": "1" - }, - "15,18": { - "contents": "", - "bgcolor": "1" - }, - "15,19": { - "contents": "", - "bgcolor": "1" - }, - "15,2": { - "contents": "", - "bgcolor": "1" - }, - "15,20": { - "contents": "", - "bgcolor": "1" - }, - "15,21": { - "contents": "", - "bgcolor": "1" - }, - "15,22": { - "contents": "", - "bgcolor": "1" - }, - "15,23": { - "contents": "", - "bgcolor": "1" - }, - "15,24": { - "contents": "", - "bgcolor": "1" - }, - "15,25": { - "contents": "", - "bgcolor": "1" - }, - "15,26": { - "contents": "", - "bgcolor": "1" - }, - "15,27": { - "contents": "", - "bgcolor": "1" - }, - "15,28": { - "contents": "", - "bgcolor": "1" - }, - "15,29": { - "contents": "", - "bgcolor": "1" - }, - "15,3": { - "contents": "", - "bgcolor": "1" - }, - "15,30": { - "contents": "", - "bgcolor": "1" - }, - "15,31": { - "contents": "", - "bgcolor": "1" - }, - "15,32": { - "contents": "", - "bgcolor": "1" - }, - "15,33": { - "contents": "", - "bgcolor": "1" - }, - "15,34": { - "contents": "", - "bgcolor": "1" - }, - "15,35": { - "contents": "", - "bgcolor": "1" - }, - "15,36": { - "contents": "", - "bgcolor": "1" - }, - "15,37": { - "contents": "", - "bgcolor": "1" - }, - "15,38": { - "contents": "", - "bgcolor": "1" - }, - "15,39": { - "contents": "", - "bgcolor": "1" - }, - "15,4": { - "contents": "", - "bgcolor": "1" - }, - "15,40": { - "contents": "", - "bgcolor": "1" - }, - "15,41": { - "contents": "", - "bgcolor": "1" - }, - "15,42": { - "contents": "", - "bgcolor": "1" - }, - "15,43": { - "contents": "", - "bgcolor": "1" - }, - "15,44": { - "contents": "", - "bgcolor": "1" - }, - "15,45": { - "contents": "", - "bgcolor": "1" - }, - "15,46": { - "contents": "", - "bgcolor": "1" - }, - "15,47": { - "contents": "", - "bgcolor": "1" - }, - "15,48": { - "contents": "", - "bgcolor": "1" - }, - "15,49": { - "contents": "", - "bgcolor": "1" - }, - "15,5": { - "contents": "", - "bgcolor": "1" - }, - "15,50": { - "contents": "", - "bgcolor": "1" - }, - "15,51": { - "contents": "", - "bgcolor": "1" - }, - "15,52": { - "contents": "", - "bgcolor": "1" - }, - "15,53": { - "contents": "", - "bgcolor": "1" - }, - "15,54": { - "contents": "", - "bgcolor": "1" - }, - "15,55": { - "contents": "", - "bgcolor": "1" - }, - "15,56": { - "contents": "", - "bgcolor": "1" - }, - "15,57": { - "contents": "", - "bgcolor": "1" - }, - "15,58": { - "contents": "", - "bgcolor": "1" - }, - "15,59": { - "contents": "", - "bgcolor": "1" - }, - "15,6": { - "contents": "", - "bgcolor": "1" - }, - "15,60": { - "contents": "", - "bgcolor": "1" - }, - "15,61": { - "contents": "", - "bgcolor": "1" - }, - "15,62": { - "contents": "", - "bgcolor": "1" - }, - "15,63": { - "contents": "", - "bgcolor": "1" - }, - "15,64": { - "contents": "", - "bgcolor": "1" - }, - "15,65": { - "contents": "", - "bgcolor": "1" - }, - "15,66": { - "contents": "", - "bgcolor": "1" - }, - "15,67": { - "contents": "", - "bgcolor": "1" - }, - "15,68": { - "contents": "", - "bgcolor": "1" - }, - "15,69": { - "contents": "", - "bgcolor": "1" - }, - "15,7": { - "contents": "", - "bgcolor": "1" - }, - "15,70": { - "contents": "", - "bgcolor": "1" - }, - "15,71": { - "contents": "", - "bgcolor": "1" - }, - "15,72": { - "contents": "", - "bgcolor": "1" - }, - "15,73": { - "contents": "", - "bgcolor": "1" - }, - "15,74": { - "contents": "", - "bgcolor": "1" - }, - "15,75": { - "contents": "", - "bgcolor": "1" - }, - "15,76": { - "contents": "", - "bgcolor": "1" - }, - "15,77": { - "contents": "", - "bgcolor": "1" - }, - "15,78": { - "contents": "", - "bgcolor": "1" - }, - "15,79": { - "contents": "", - "bgcolor": "1" - }, - "15,8": { - "contents": "", - "bgcolor": "1" - }, - "15,9": { - "contents": "", - "bgcolor": "1" - }, - "16,0": { - "contents": "", - "bgcolor": "1" - }, - "16,1": { - "contents": "", - "bgcolor": "1" - }, - "16,10": { - "contents": "", - "bgcolor": "1" - }, - "16,11": { - "contents": "", - "bgcolor": "1" - }, - "16,12": { - "contents": "", - "bgcolor": "1" - }, - "16,13": { - "contents": "", - "bgcolor": "1" - }, - "16,14": { - "contents": "", - "bgcolor": "1" - }, - "16,15": { - "contents": "", - "bgcolor": "1" - }, - "16,16": { - "contents": "", - "bgcolor": "1" - }, - "16,17": { - "contents": "", - "bgcolor": "1" - }, - "16,18": { - "contents": "", - "bgcolor": "1" - }, - "16,19": { - "contents": "", - "bgcolor": "1" - }, - "16,2": { - "contents": "", - "bgcolor": "1" - }, - "16,20": { - "contents": "", - "bgcolor": "1" - }, - "16,21": { - "contents": "", - "bgcolor": "1" - }, - "16,22": { - "contents": "", - "bgcolor": "1" - }, - "16,23": { - "contents": "", - "bgcolor": "1" - }, - "16,24": { - "contents": "", - "bgcolor": "1" - }, - "16,25": { - "contents": "", - "bgcolor": "1" - }, - "16,26": { - "contents": "", - "bgcolor": "1" - }, - "16,27": { - "contents": "", - "bgcolor": "1" - }, - "16,28": { - "contents": "", - "bgcolor": "1" - }, - "16,29": { - "contents": "", - "bgcolor": "1" - }, - "16,3": { - "contents": "", - "bgcolor": "1" - }, - "16,30": { - "contents": "", - "bgcolor": "1" - }, - "16,31": { - "contents": "", - "bgcolor": "1" - }, - "16,32": { - "contents": "", - "bgcolor": "1" - }, - "16,33": { - "contents": "", - "bgcolor": "1" - }, - "16,34": { - "contents": "", - "bgcolor": "1" - }, - "16,35": { - "contents": "", - "bgcolor": "1" - }, - "16,36": { - "contents": "", - "bgcolor": "1" - }, - "16,37": { - "contents": "", - "bgcolor": "1" - }, - "16,38": { - "contents": "", - "bgcolor": "1" - }, - "16,39": { - "contents": "", - "bgcolor": "1" - }, - "16,4": { - "contents": "", - "bgcolor": "1" - }, - "16,40": { - "contents": "", - "bgcolor": "1" - }, - "16,41": { - "contents": "", - "bgcolor": "1" - }, - "16,42": { - "contents": "", - "bgcolor": "1" - }, - "16,43": { - "contents": "", - "bgcolor": "1" - }, - "16,44": { - "contents": "", - "bgcolor": "1" - }, - "16,45": { - "contents": "", - "bgcolor": "1" - }, - "16,46": { - "contents": "", - "bgcolor": "1" - }, - "16,47": { - "contents": "", - "bgcolor": "1" - }, - "16,48": { - "contents": "", - "bgcolor": "1" - }, - "16,49": { - "contents": "", - "bgcolor": "1" - }, - "16,5": { - "contents": "", - "bgcolor": "1" - }, - "16,50": { - "contents": "", - "bgcolor": "1" - }, - "16,51": { - "contents": "", - "bgcolor": "1" - }, - "16,52": { - "contents": "", - "bgcolor": "1" - }, - "16,53": { - "contents": "", - "bgcolor": "1" - }, - "16,54": { - "contents": "", - "bgcolor": "1" - }, - "16,55": { - "contents": "", - "bgcolor": "1" - }, - "16,56": { - "contents": "", - "bgcolor": "1" - }, - "16,57": { - "contents": "", - "bgcolor": "1" - }, - "16,58": { - "contents": "", - "bgcolor": "1" - }, - "16,59": { - "contents": "", - "bgcolor": "1" - }, - "16,6": { - "contents": "", - "bgcolor": "1" - }, - "16,60": { - "contents": "", - "bgcolor": "1" - }, - "16,61": { - "contents": "", - "bgcolor": "1" - }, - "16,62": { - "contents": "", - "bgcolor": "1" - }, - "16,63": { - "contents": "", - "bgcolor": "1" - }, - "16,64": { - "contents": "", - "bgcolor": "1" - }, - "16,65": { - "contents": "", - "bgcolor": "1" - }, - "16,66": { - "contents": "", - "bgcolor": "1" - }, - "16,67": { - "contents": "", - "bgcolor": "1" - }, - "16,68": { - "contents": "", - "bgcolor": "1" - }, - "16,69": { - "contents": "", - "bgcolor": "1" - }, - "16,7": { - "contents": "", - "bgcolor": "1" - }, - "16,70": { - "contents": "", - "bgcolor": "1" - }, - "16,71": { - "contents": "", - "bgcolor": "1" - }, - "16,72": { - "contents": "", - "bgcolor": "1" - }, - "16,73": { - "contents": "", - "bgcolor": "1" - }, - "16,74": { - "contents": "", - "bgcolor": "1" - }, - "16,75": { - "contents": "", - "bgcolor": "1" - }, - "16,76": { - "contents": "", - "bgcolor": "1" - }, - "16,77": { - "contents": "", - "bgcolor": "1" - }, - "16,78": { - "contents": "", - "bgcolor": "1" - }, - "16,79": { - "contents": "", - "bgcolor": "1" - }, - "16,8": { - "contents": "", - "bgcolor": "1" - }, - "16,9": { - "contents": "", - "bgcolor": "1" - }, - "17,0": { - "contents": "", - "bgcolor": "1" - }, - "17,1": { - "contents": "", - "bgcolor": "1" - }, - "17,10": { - "contents": "", - "bgcolor": "1" - }, - "17,11": { - "contents": "", - "bgcolor": "1" - }, - "17,12": { - "contents": "", - "bgcolor": "1" - }, - "17,13": { - "contents": "", - "bgcolor": "1" - }, - "17,14": { - "contents": "", - "bgcolor": "1" - }, - "17,15": { - "contents": "", - "bgcolor": "1" - }, - "17,16": { - "contents": "", - "bgcolor": "1" - }, - "17,17": { - "contents": "", - "bgcolor": "1" - }, - "17,18": { - "contents": "", - "bgcolor": "1" - }, - "17,19": { - "contents": "", - "bgcolor": "1" - }, - "17,2": { - "contents": "", - "bgcolor": "1" - }, - "17,20": { - "contents": "", - "bgcolor": "1" - }, - "17,21": { - "contents": "", - "bgcolor": "1" - }, - "17,22": { - "contents": "", - "bgcolor": "1" - }, - "17,23": { - "contents": "", - "bgcolor": "1" - }, - "17,24": { - "contents": "", - "bgcolor": "1" - }, - "17,25": { - "contents": "", - "bgcolor": "1" - }, - "17,26": { - "contents": "", - "bgcolor": "1" - }, - "17,27": { - "contents": "", - "bgcolor": "1" - }, - "17,28": { - "contents": "", - "bgcolor": "1" - }, - "17,29": { - "contents": "", - "bgcolor": "1" - }, - "17,3": { - "contents": "", - "bgcolor": "1" - }, - "17,30": { - "contents": "", - "bgcolor": "1" - }, - "17,31": { - "contents": "", - "bgcolor": "1" - }, - "17,32": { - "contents": "", - "bgcolor": "1" - }, - "17,33": { - "contents": "", - "bgcolor": "1" - }, - "17,34": { - "contents": "", - "bgcolor": "1" - }, - "17,35": { - "contents": "", - "bgcolor": "1" - }, - "17,36": { - "contents": "", - "bgcolor": "1" - }, - "17,37": { - "contents": "", - "bgcolor": "1" - }, - "17,38": { - "contents": "", - "bgcolor": "1" - }, - "17,39": { - "contents": "", - "bgcolor": "1" - }, - "17,4": { - "contents": "", - "bgcolor": "1" - }, - "17,40": { - "contents": "", - "bgcolor": "1" - }, - "17,41": { - "contents": "", - "bgcolor": "1" - }, - "17,42": { - "contents": "", - "bgcolor": "1" - }, - "17,43": { - "contents": "", - "bgcolor": "1" - }, - "17,44": { - "contents": "", - "bgcolor": "1" - }, - "17,45": { - "contents": "", - "bgcolor": "1" - }, - "17,46": { - "contents": "", - "bgcolor": "1" - }, - "17,47": { - "contents": "", - "bgcolor": "1" - }, - "17,48": { - "contents": "", - "bgcolor": "1" - }, - "17,49": { - "contents": "", - "bgcolor": "1" - }, - "17,5": { - "contents": "", - "bgcolor": "1" - }, - "17,50": { - "contents": "", - "bgcolor": "1" - }, - "17,51": { - "contents": "", - "bgcolor": "1" - }, - "17,52": { - "contents": "", - "bgcolor": "1" - }, - "17,53": { - "contents": "", - "bgcolor": "1" - }, - "17,54": { - "contents": "", - "bgcolor": "1" - }, - "17,55": { - "contents": "", - "bgcolor": "1" - }, - "17,56": { - "contents": "", - "bgcolor": "1" - }, - "17,57": { - "contents": "", - "bgcolor": "1" - }, - "17,58": { - "contents": "", - "bgcolor": "1" - }, - "17,59": { - "contents": "", - "bgcolor": "1" - }, - "17,6": { - "contents": "", - "bgcolor": "1" - }, - "17,60": { - "contents": "", - "bgcolor": "1" - }, - "17,61": { - "contents": "", - "bgcolor": "1" - }, - "17,62": { - "contents": "", - "bgcolor": "1" - }, - "17,63": { - "contents": "", - "bgcolor": "1" - }, - "17,64": { - "contents": "", - "bgcolor": "1" - }, - "17,65": { - "contents": "", - "bgcolor": "1" - }, - "17,66": { - "contents": "", - "bgcolor": "1" - }, - "17,67": { - "contents": "", - "bgcolor": "1" - }, - "17,68": { - "contents": "", - "bgcolor": "1" - }, - "17,69": { - "contents": "", - "bgcolor": "1" - }, - "17,7": { - "contents": "", - "bgcolor": "1" - }, - "17,70": { - "contents": "", - "bgcolor": "1" - }, - "17,71": { - "contents": "", - "bgcolor": "1" - }, - "17,72": { - "contents": "", - "bgcolor": "1" - }, - "17,73": { - "contents": "", - "bgcolor": "1" - }, - "17,74": { - "contents": "", - "bgcolor": "1" - }, - "17,75": { - "contents": "", - "bgcolor": "1" - }, - "17,76": { - "contents": "", - "bgcolor": "1" - }, - "17,77": { - "contents": "", - "bgcolor": "1" - }, - "17,78": { - "contents": "", - "bgcolor": "1" - }, - "17,79": { - "contents": "", - "bgcolor": "1" - }, - "17,8": { - "contents": "", - "bgcolor": "1" - }, - "17,9": { - "contents": "", - "bgcolor": "1" - }, - "18,0": { - "contents": "", - "bgcolor": "1" - }, - "18,1": { - "contents": "", - "bgcolor": "1" - }, - "18,10": { - "contents": "", - "bgcolor": "1" - }, - "18,11": { - "contents": "", - "bgcolor": "1" - }, - "18,12": { - "contents": "", - "bgcolor": "1" - }, - "18,13": { - "contents": "", - "bgcolor": "1" - }, - "18,14": { - "contents": "", - "bgcolor": "1" - }, - "18,15": { - "contents": "", - "bgcolor": "1" - }, - "18,16": { - "contents": "", - "bgcolor": "1" - }, - "18,17": { - "contents": "", - "bgcolor": "1" - }, - "18,18": { - "contents": "", - "bgcolor": "1" - }, - "18,19": { - "contents": "", - "bgcolor": "1" - }, - "18,2": { - "contents": "", - "bgcolor": "1" - }, - "18,20": { - "contents": "", - "bgcolor": "1" - }, - "18,21": { - "contents": "", - "bgcolor": "1" - }, - "18,22": { - "contents": "", - "bgcolor": "1" - }, - "18,23": { - "contents": "", - "bgcolor": "1" - }, - "18,24": { - "contents": "", - "bgcolor": "1" - }, - "18,25": { - "contents": "", - "bgcolor": "1" - }, - "18,26": { - "contents": "", - "bgcolor": "1" - }, - "18,27": { - "contents": "", - "bgcolor": "1" - }, - "18,28": { - "contents": "", - "bgcolor": "1" - }, - "18,29": { - "contents": "", - "bgcolor": "1" - }, - "18,3": { - "contents": "", - "bgcolor": "1" - }, - "18,30": { - "contents": "", - "bgcolor": "1" - }, - "18,31": { - "contents": "", - "bgcolor": "1" - }, - "18,32": { - "contents": "", - "bgcolor": "1" - }, - "18,33": { - "contents": "", - "bgcolor": "1" - }, - "18,34": { - "contents": "", - "bgcolor": "1" - }, - "18,35": { - "contents": "", - "bgcolor": "1" - }, - "18,36": { - "contents": "", - "bgcolor": "1" - }, - "18,37": { - "contents": "", - "bgcolor": "1" - }, - "18,38": { - "contents": "", - "bgcolor": "1" - }, - "18,39": { - "contents": "", - "bgcolor": "1" - }, - "18,4": { - "contents": "", - "bgcolor": "1" - }, - "18,40": { - "contents": "", - "bgcolor": "1" - }, - "18,41": { - "contents": "", - "bgcolor": "1" - }, - "18,42": { - "contents": "", - "bgcolor": "1" - }, - "18,43": { - "contents": "", - "bgcolor": "1" - }, - "18,44": { - "contents": "", - "bgcolor": "1" - }, - "18,45": { - "contents": "", - "bgcolor": "1" - }, - "18,46": { - "contents": "", - "bgcolor": "1" - }, - "18,47": { - "contents": "", - "bgcolor": "1" - }, - "18,48": { - "contents": "", - "bgcolor": "1" - }, - "18,49": { - "contents": "", - "bgcolor": "1" - }, - "18,5": { - "contents": "", - "bgcolor": "1" - }, - "18,50": { - "contents": "", - "bgcolor": "1" - }, - "18,51": { - "contents": "", - "bgcolor": "1" - }, - "18,52": { - "contents": "", - "bgcolor": "1" - }, - "18,53": { - "contents": "", - "bgcolor": "1" - }, - "18,54": { - "contents": "", - "bgcolor": "1" - }, - "18,55": { - "contents": "", - "bgcolor": "1" - }, - "18,56": { - "contents": "", - "bgcolor": "1" - }, - "18,57": { - "contents": "", - "bgcolor": "1" - }, - "18,58": { - "contents": "", - "bgcolor": "1" - }, - "18,59": { - "contents": "", - "bgcolor": "1" - }, - "18,6": { - "contents": "", - "bgcolor": "1" - }, - "18,60": { - "contents": "", - "bgcolor": "1" - }, - "18,61": { - "contents": "", - "bgcolor": "1" - }, - "18,62": { - "contents": "", - "bgcolor": "1" - }, - "18,63": { - "contents": "", - "bgcolor": "1" - }, - "18,64": { - "contents": "", - "bgcolor": "1" - }, - "18,65": { - "contents": "", - "bgcolor": "1" - }, - "18,66": { - "contents": "", - "bgcolor": "1" - }, - "18,67": { - "contents": "", - "bgcolor": "1" - }, - "18,68": { - "contents": "", - "bgcolor": "1" - }, - "18,69": { - "contents": "", - "bgcolor": "1" - }, - "18,7": { - "contents": "", - "bgcolor": "1" - }, - "18,70": { - "contents": "", - "bgcolor": "1" - }, - "18,71": { - "contents": "", - "bgcolor": "1" - }, - "18,72": { - "contents": "", - "bgcolor": "1" - }, - "18,73": { - "contents": "", - "bgcolor": "1" - }, - "18,74": { - "contents": "", - "bgcolor": "1" - }, - "18,75": { - "contents": "", - "bgcolor": "1" - }, - "18,76": { - "contents": "", - "bgcolor": "1" - }, - "18,77": { - "contents": "", - "bgcolor": "1" - }, - "18,78": { - "contents": "", - "bgcolor": "1" - }, - "18,79": { - "contents": "", - "bgcolor": "1" - }, - "18,8": { - "contents": "", - "bgcolor": "1" - }, - "18,9": { - "contents": "", - "bgcolor": "1" - }, - "19,0": { - "contents": "", - "bgcolor": "1" - }, - "19,1": { - "contents": "", - "bgcolor": "1" - }, - "19,10": { - "contents": "", - "bgcolor": "1" - }, - "19,11": { - "contents": "", - "bgcolor": "1" - }, - "19,12": { - "contents": "", - "bgcolor": "1" - }, - "19,13": { - "contents": "", - "bgcolor": "1" - }, - "19,14": { - "contents": "", - "bgcolor": "1" - }, - "19,15": { - "contents": "", - "bgcolor": "1" - }, - "19,16": { - "contents": "", - "bgcolor": "1" - }, - "19,17": { - "contents": "", - "bgcolor": "1" - }, - "19,18": { - "contents": "", - "bgcolor": "1" - }, - "19,19": { - "contents": "", - "bgcolor": "1" - }, - "19,2": { - "contents": "", - "bgcolor": "1" - }, - "19,20": { - "contents": "", - "bgcolor": "1" - }, - "19,21": { - "contents": "", - "bgcolor": "1" - }, - "19,22": { - "contents": "", - "bgcolor": "1" - }, - "19,23": { - "contents": "", - "bgcolor": "1" - }, - "19,24": { - "contents": "", - "bgcolor": "1" - }, - "19,25": { - "contents": "", - "bgcolor": "1" - }, - "19,26": { - "contents": "", - "bgcolor": "1" - }, - "19,27": { - "contents": "", - "bgcolor": "1" - }, - "19,28": { - "contents": "", - "bgcolor": "1" - }, - "19,29": { - "contents": "", - "bgcolor": "1" - }, - "19,3": { - "contents": "", - "bgcolor": "1" - }, - "19,30": { - "contents": "", - "bgcolor": "1" - }, - "19,31": { - "contents": "", - "bgcolor": "1" - }, - "19,32": { - "contents": "", - "bgcolor": "1" - }, - "19,33": { - "contents": "", - "bgcolor": "1" - }, - "19,34": { - "contents": "", - "bgcolor": "1" - }, - "19,35": { - "contents": "", - "bgcolor": "1" - }, - "19,36": { - "contents": "", - "bgcolor": "1" - }, - "19,37": { - "contents": "", - "bgcolor": "1" - }, - "19,38": { - "contents": "", - "bgcolor": "1" - }, - "19,39": { - "contents": "", - "bgcolor": "1" - }, - "19,4": { - "contents": "", - "bgcolor": "1" - }, - "19,40": { - "contents": "", - "bgcolor": "1" - }, - "19,41": { - "contents": "", - "bgcolor": "1" - }, - "19,42": { - "contents": "", - "bgcolor": "1" - }, - "19,43": { - "contents": "", - "bgcolor": "1" - }, - "19,44": { - "contents": "", - "bgcolor": "1" - }, - "19,45": { - "contents": "", - "bgcolor": "1" - }, - "19,46": { - "contents": "", - "bgcolor": "1" - }, - "19,47": { - "contents": "", - "bgcolor": "1" - }, - "19,48": { - "contents": "", - "bgcolor": "1" - }, - "19,49": { - "contents": "", - "bgcolor": "1" - }, - "19,5": { - "contents": "", - "bgcolor": "1" - }, - "19,50": { - "contents": "", - "bgcolor": "1" - }, - "19,51": { - "contents": "", - "bgcolor": "1" - }, - "19,52": { - "contents": "", - "bgcolor": "1" - }, - "19,53": { - "contents": "", - "bgcolor": "1" - }, - "19,54": { - "contents": "", - "bgcolor": "1" - }, - "19,55": { - "contents": "", - "bgcolor": "1" - }, - "19,56": { - "contents": "", - "bgcolor": "1" - }, - "19,57": { - "contents": "", - "bgcolor": "1" - }, - "19,58": { - "contents": "", - "bgcolor": "1" - }, - "19,59": { - "contents": "", - "bgcolor": "1" - }, - "19,6": { - "contents": "", - "bgcolor": "1" - }, - "19,60": { - "contents": "", - "bgcolor": "1" - }, - "19,61": { - "contents": "", - "bgcolor": "1" - }, - "19,62": { - "contents": "", - "bgcolor": "1" - }, - "19,63": { - "contents": "", - "bgcolor": "1" - }, - "19,64": { - "contents": "", - "bgcolor": "1" - }, - "19,65": { - "contents": "", - "bgcolor": "1" - }, - "19,66": { - "contents": "", - "bgcolor": "1" - }, - "19,67": { - "contents": "", - "bgcolor": "1" - }, - "19,68": { - "contents": "", - "bgcolor": "1" - }, - "19,69": { - "contents": "", - "bgcolor": "1" - }, - "19,7": { - "contents": "", - "bgcolor": "1" - }, - "19,70": { - "contents": "", - "bgcolor": "1" - }, - "19,71": { - "contents": "", - "bgcolor": "1" - }, - "19,72": { - "contents": "", - "bgcolor": "1" - }, - "19,73": { - "contents": "", - "bgcolor": "1" - }, - "19,74": { - "contents": "", - "bgcolor": "1" - }, - "19,75": { - "contents": "", - "bgcolor": "1" - }, - "19,76": { - "contents": "", - "bgcolor": "1" - }, - "19,77": { - "contents": "", - "bgcolor": "1" - }, - "19,78": { - "contents": "", - "bgcolor": "1" - }, - "19,79": { - "contents": "", - "bgcolor": "1" - }, - "19,8": { - "contents": "", - "bgcolor": "1" - }, - "19,9": { - "contents": "", - "bgcolor": "1" - }, - "20,0": { - "contents": "", - "bgcolor": "1" - }, - "20,1": { - "contents": "", - "bgcolor": "1" - }, - "20,10": { - "contents": "", - "bgcolor": "1" - }, - "20,11": { - "contents": "", - "bgcolor": "1" - }, - "20,12": { - "contents": "", - "bgcolor": "1" - }, - "20,13": { - "contents": "", - "bgcolor": "1" - }, - "20,14": { - "contents": "", - "bgcolor": "1" - }, - "20,15": { - "contents": "", - "bgcolor": "1" - }, - "20,16": { - "contents": "", - "bgcolor": "1" - }, - "20,17": { - "contents": "", - "bgcolor": "1" - }, - "20,18": { - "contents": "", - "bgcolor": "1" - }, - "20,19": { - "contents": "", - "bgcolor": "1" - }, - "20,2": { - "contents": "", - "bgcolor": "1" - }, - "20,20": { - "contents": "", - "bgcolor": "1" - }, - "20,21": { - "contents": "", - "bgcolor": "1" - }, - "20,22": { - "contents": "", - "bgcolor": "1" - }, - "20,23": { - "contents": "", - "bgcolor": "1" - }, - "20,24": { - "contents": "", - "bgcolor": "1" - }, - "20,25": { - "contents": "", - "bgcolor": "1" - }, - "20,26": { - "contents": "", - "bgcolor": "1" - }, - "20,27": { - "contents": "", - "bgcolor": "1" - }, - "20,28": { - "contents": "", - "bgcolor": "1" - }, - "20,29": { - "contents": "", - "bgcolor": "1" - }, - "20,3": { - "contents": "", - "bgcolor": "1" - }, - "20,30": { - "contents": "", - "bgcolor": "1" - }, - "20,31": { - "contents": "", - "bgcolor": "1" - }, - "20,32": { - "contents": "", - "bgcolor": "1" - }, - "20,33": { - "contents": "", - "bgcolor": "1" - }, - "20,34": { - "contents": "", - "bgcolor": "1" - }, - "20,35": { - "contents": "", - "bgcolor": "1" - }, - "20,36": { - "contents": "", - "bgcolor": "1" - }, - "20,37": { - "contents": "", - "bgcolor": "1" - }, - "20,38": { - "contents": "", - "bgcolor": "1" - }, - "20,39": { - "contents": "", - "bgcolor": "1" - }, - "20,4": { - "contents": "", - "bgcolor": "1" - }, - "20,40": { - "contents": "", - "bgcolor": "1" - }, - "20,41": { - "contents": "", - "bgcolor": "1" - }, - "20,42": { - "contents": "", - "bgcolor": "1" - }, - "20,43": { - "contents": "", - "bgcolor": "1" - }, - "20,44": { - "contents": "", - "bgcolor": "1" - }, - "20,45": { - "contents": "", - "bgcolor": "1" - }, - "20,46": { - "contents": "", - "bgcolor": "1" - }, - "20,47": { - "contents": "", - "bgcolor": "1" - }, - "20,48": { - "contents": "", - "bgcolor": "1" - }, - "20,49": { - "contents": "", - "bgcolor": "1" - }, - "20,5": { - "contents": "", - "bgcolor": "1" - }, - "20,50": { - "contents": "", - "bgcolor": "1" - }, - "20,51": { - "contents": "", - "bgcolor": "1" - }, - "20,52": { - "contents": "", - "bgcolor": "1" - }, - "20,53": { - "contents": "", - "bgcolor": "1" - }, - "20,54": { - "contents": "", - "bgcolor": "1" - }, - "20,55": { - "contents": "", - "bgcolor": "1" - }, - "20,56": { - "contents": "", - "bgcolor": "1" - }, - "20,57": { - "contents": "", - "bgcolor": "1" - }, - "20,58": { - "contents": "", - "bgcolor": "1" - }, - "20,59": { - "contents": "", - "bgcolor": "1" - }, - "20,6": { - "contents": "", - "bgcolor": "1" - }, - "20,60": { - "contents": "", - "bgcolor": "1" - }, - "20,61": { - "contents": "", - "bgcolor": "1" - }, - "20,62": { - "contents": "", - "bgcolor": "1" - }, - "20,63": { - "contents": "", - "bgcolor": "1" - }, - "20,64": { - "contents": "", - "bgcolor": "1" - }, - "20,65": { - "contents": "", - "bgcolor": "1" - }, - "20,66": { - "contents": "", - "bgcolor": "1" - }, - "20,67": { - "contents": "", - "bgcolor": "1" - }, - "20,68": { - "contents": "", - "bgcolor": "1" - }, - "20,69": { - "contents": "", - "bgcolor": "1" - }, - "20,7": { - "contents": "", - "bgcolor": "1" - }, - "20,70": { - "contents": "", - "bgcolor": "1" - }, - "20,71": { - "contents": "", - "bgcolor": "1" - }, - "20,72": { - "contents": "", - "bgcolor": "1" - }, - "20,73": { - "contents": "", - "bgcolor": "1" - }, - "20,74": { - "contents": "", - "bgcolor": "1" - }, - "20,75": { - "contents": "", - "bgcolor": "1" - }, - "20,76": { - "contents": "", - "bgcolor": "1" - }, - "20,77": { - "contents": "", - "bgcolor": "1" - }, - "20,78": { - "contents": "", - "bgcolor": "1" - }, - "20,79": { - "contents": "", - "bgcolor": "1" - }, - "20,8": { - "contents": "", - "bgcolor": "1" - }, - "20,9": { - "contents": "", - "bgcolor": "1" - }, - "21,0": { - "contents": "", - "bgcolor": "1" - }, - "21,1": { - "contents": "", - "bgcolor": "1" - }, - "21,10": { - "contents": "", - "bgcolor": "1" - }, - "21,11": { - "contents": "", - "bgcolor": "1" - }, - "21,12": { - "contents": "", - "bgcolor": "1" - }, - "21,13": { - "contents": "", - "bgcolor": "1" - }, - "21,14": { - "contents": "", - "bgcolor": "1" - }, - "21,15": { - "contents": "", - "bgcolor": "1" - }, - "21,16": { - "contents": "", - "bgcolor": "1" - }, - "21,17": { - "contents": "", - "bgcolor": "1" - }, - "21,18": { - "contents": "", - "bgcolor": "1" - }, - "21,19": { - "contents": "", - "bgcolor": "1" - }, - "21,2": { - "contents": "", - "bgcolor": "1" - }, - "21,20": { - "contents": "", - "bgcolor": "1" - }, - "21,21": { - "contents": "", - "bgcolor": "1" - }, - "21,22": { - "contents": "", - "bgcolor": "1" - }, - "21,23": { - "contents": "", - "bgcolor": "1" - }, - "21,24": { - "contents": "", - "bgcolor": "1" - }, - "21,25": { - "contents": "", - "bgcolor": "1" - }, - "21,26": { - "contents": "", - "bgcolor": "1" - }, - "21,27": { - "contents": "", - "bgcolor": "1" - }, - "21,28": { - "contents": "", - "bgcolor": "1" - }, - "21,29": { - "contents": "", - "bgcolor": "1" - }, - "21,3": { - "contents": "", - "bgcolor": "1" - }, - "21,30": { - "contents": "", - "bgcolor": "1" - }, - "21,31": { - "contents": "", - "bgcolor": "1" - }, - "21,32": { - "contents": "", - "bgcolor": "1" - }, - "21,33": { - "contents": "", - "bgcolor": "1" - }, - "21,34": { - "contents": "", - "bgcolor": "1" - }, - "21,35": { - "contents": "", - "bgcolor": "1" - }, - "21,36": { - "contents": "", - "bgcolor": "1" - }, - "21,37": { - "contents": "", - "bgcolor": "1" - }, - "21,38": { - "contents": "", - "bgcolor": "1" - }, - "21,39": { - "contents": "", - "bgcolor": "1" - }, - "21,4": { - "contents": "", - "bgcolor": "1" - }, - "21,40": { - "contents": "", - "bgcolor": "1" - }, - "21,41": { - "contents": "", - "bgcolor": "1" - }, - "21,42": { - "contents": "", - "bgcolor": "1" - }, - "21,43": { - "contents": "", - "bgcolor": "1" - }, - "21,44": { - "contents": "", - "bgcolor": "1" - }, - "21,45": { - "contents": "", - "bgcolor": "1" - }, - "21,46": { - "contents": "", - "bgcolor": "1" - }, - "21,47": { - "contents": "", - "bgcolor": "1" - }, - "21,48": { - "contents": "", - "bgcolor": "1" - }, - "21,49": { - "contents": "", - "bgcolor": "1" - }, - "21,5": { - "contents": "", - "bgcolor": "1" - }, - "21,50": { - "contents": "", - "bgcolor": "1" - }, - "21,51": { - "contents": "", - "bgcolor": "1" - }, - "21,52": { - "contents": "", - "bgcolor": "1" - }, - "21,53": { - "contents": "", - "bgcolor": "1" - }, - "21,54": { - "contents": "", - "bgcolor": "1" - }, - "21,55": { - "contents": "", - "bgcolor": "1" - }, - "21,56": { - "contents": "", - "bgcolor": "1" - }, - "21,57": { - "contents": "", - "bgcolor": "1" - }, - "21,58": { - "contents": "", - "bgcolor": "1" - }, - "21,59": { - "contents": "", - "bgcolor": "1" - }, - "21,6": { - "contents": "", - "bgcolor": "1" - }, - "21,60": { - "contents": "", - "bgcolor": "1" - }, - "21,61": { - "contents": "", - "bgcolor": "1" - }, - "21,62": { - "contents": "", - "bgcolor": "1" - }, - "21,63": { - "contents": "", - "bgcolor": "1" - }, - "21,64": { - "contents": "", - "bgcolor": "1" - }, - "21,65": { - "contents": "", - "bgcolor": "1" - }, - "21,66": { - "contents": "", - "bgcolor": "1" - }, - "21,67": { - "contents": "", - "bgcolor": "1" - }, - "21,68": { - "contents": "", - "bgcolor": "1" - }, - "21,69": { - "contents": "", - "bgcolor": "1" - }, - "21,7": { - "contents": "", - "bgcolor": "1" - }, - "21,70": { - "contents": "", - "bgcolor": "1" - }, - "21,71": { - "contents": "", - "bgcolor": "1" - }, - "21,72": { - "contents": "", - "bgcolor": "1" - }, - "21,73": { - "contents": "", - "bgcolor": "1" - }, - "21,74": { - "contents": "", - "bgcolor": "1" - }, - "21,75": { - "contents": "", - "bgcolor": "1" - }, - "21,76": { - "contents": "", - "bgcolor": "1" - }, - "21,77": { - "contents": "", - "bgcolor": "1" - }, - "21,78": { - "contents": "", - "bgcolor": "1" - }, - "21,79": { - "contents": "", - "bgcolor": "1" - }, - "21,8": { - "contents": "", - "bgcolor": "1" - }, - "21,9": { - "contents": "", - "bgcolor": "1" - }, - "22,0": { - "contents": "", - "bgcolor": "1" - }, - "22,1": { - "contents": "", - "bgcolor": "1" - }, - "22,10": { - "contents": "", - "bgcolor": "1" - }, - "22,11": { - "contents": "", - "bgcolor": "1" - }, - "22,12": { - "contents": "", - "bgcolor": "1" - }, - "22,13": { - "contents": "", - "bgcolor": "1" - }, - "22,14": { - "contents": "", - "bgcolor": "1" - }, - "22,15": { - "contents": "", - "bgcolor": "1" - }, - "22,16": { - "contents": "", - "bgcolor": "1" - }, - "22,17": { - "contents": "", - "bgcolor": "1" - }, - "22,18": { - "contents": "", - "bgcolor": "1" - }, - "22,19": { - "contents": "", - "bgcolor": "1" - }, - "22,2": { - "contents": "", - "bgcolor": "1" - }, - "22,20": { - "contents": "", - "bgcolor": "1" - }, - "22,21": { - "contents": "", - "bgcolor": "1" - }, - "22,22": { - "contents": "", - "bgcolor": "1" - }, - "22,23": { - "contents": "", - "bgcolor": "1" - }, - "22,24": { - "contents": "", - "bgcolor": "1" - }, - "22,25": { - "contents": "", - "bgcolor": "1" - }, - "22,26": { - "contents": "", - "bgcolor": "1" - }, - "22,27": { - "contents": "", - "bgcolor": "1" - }, - "22,28": { - "contents": "", - "bgcolor": "1" - }, - "22,29": { - "contents": "", - "bgcolor": "1" - }, - "22,3": { - "contents": "", - "bgcolor": "1" - }, - "22,30": { - "contents": "", - "bgcolor": "1" - }, - "22,31": { - "contents": "", - "bgcolor": "1" - }, - "22,32": { - "contents": "", - "bgcolor": "1" - }, - "22,33": { - "contents": "", - "bgcolor": "1" - }, - "22,34": { - "contents": "", - "bgcolor": "1" - }, - "22,35": { - "contents": "", - "bgcolor": "1" - }, - "22,36": { - "contents": "", - "bgcolor": "1" - }, - "22,37": { - "contents": "", - "bgcolor": "1" - }, - "22,38": { - "contents": "", - "bgcolor": "1" - }, - "22,39": { - "contents": "", - "bgcolor": "1" - }, - "22,4": { - "contents": "", - "bgcolor": "1" - }, - "22,40": { - "contents": "", - "bgcolor": "1" - }, - "22,41": { - "contents": "", - "bgcolor": "1" - }, - "22,42": { - "contents": "", - "bgcolor": "1" - }, - "22,43": { - "contents": "", - "bgcolor": "1" - }, - "22,44": { - "contents": "", - "bgcolor": "1" - }, - "22,45": { - "contents": "", - "bgcolor": "1" - }, - "22,46": { - "contents": "", - "bgcolor": "1" - }, - "22,47": { - "contents": "", - "bgcolor": "1" - }, - "22,48": { - "contents": "", - "bgcolor": "1" - }, - "22,49": { - "contents": "", - "bgcolor": "1" - }, - "22,5": { - "contents": "", - "bgcolor": "1" - }, - "22,50": { - "contents": "", - "bgcolor": "1" - }, - "22,51": { - "contents": "", - "bgcolor": "1" - }, - "22,52": { - "contents": "", - "bgcolor": "1" - }, - "22,53": { - "contents": "", - "bgcolor": "1" - }, - "22,54": { - "contents": "", - "bgcolor": "1" - }, - "22,55": { - "contents": "", - "bgcolor": "1" - }, - "22,56": { - "contents": "", - "bgcolor": "1" - }, - "22,57": { - "contents": "", - "bgcolor": "1" - }, - "22,58": { - "contents": "", - "bgcolor": "1" - }, - "22,59": { - "contents": "", - "bgcolor": "1" - }, - "22,6": { - "contents": "", - "bgcolor": "1" - }, - "22,60": { - "contents": "", - "bgcolor": "1" - }, - "22,61": { - "contents": "", - "bgcolor": "1" - }, - "22,62": { - "contents": "", - "bgcolor": "1" - }, - "22,63": { - "contents": "", - "bgcolor": "1" - }, - "22,64": { - "contents": "", - "bgcolor": "1" - }, - "22,65": { - "contents": "", - "bgcolor": "1" - }, - "22,66": { - "contents": "", - "bgcolor": "1" - }, - "22,67": { - "contents": "", - "bgcolor": "1" - }, - "22,68": { - "contents": "", - "bgcolor": "1" - }, - "22,69": { - "contents": "", - "bgcolor": "1" - }, - "22,7": { - "contents": "", - "bgcolor": "1" - }, - "22,70": { - "contents": "", - "bgcolor": "1" - }, - "22,71": { - "contents": "", - "bgcolor": "1" - }, - "22,72": { - "contents": "", - "bgcolor": "1" - }, - "22,73": { - "contents": "", - "bgcolor": "1" - }, - "22,74": { - "contents": "", - "bgcolor": "1" - }, - "22,75": { - "contents": "", - "bgcolor": "1" - }, - "22,76": { - "contents": "", - "bgcolor": "1" - }, - "22,77": { - "contents": "", - "bgcolor": "1" - }, - "22,78": { - "contents": "", - "bgcolor": "1" - }, - "22,79": { - "contents": "", - "bgcolor": "1" - }, - "22,8": { - "contents": "", - "bgcolor": "1" - }, - "22,9": { - "contents": "", - "bgcolor": "1" - }, - "23,0": { - "contents": "", - "bgcolor": "1" - }, - "23,1": { - "contents": "", - "bgcolor": "1" - }, - "23,10": { - "contents": "", - "bgcolor": "1" - }, - "23,11": { - "contents": "", - "bgcolor": "1" - }, - "23,12": { - "contents": "", - "bgcolor": "1" - }, - "23,13": { - "contents": "", - "bgcolor": "1" - }, - "23,14": { - "contents": "", - "bgcolor": "1" - }, - "23,15": { - "contents": "", - "bgcolor": "1" - }, - "23,16": { - "contents": "", - "bgcolor": "1" - }, - "23,17": { - "contents": "", - "bgcolor": "1" - }, - "23,18": { - "contents": "", - "bgcolor": "1" - }, - "23,19": { - "contents": "", - "bgcolor": "1" - }, - "23,2": { - "contents": "", - "bgcolor": "1" - }, - "23,20": { - "contents": "", - "bgcolor": "1" - }, - "23,21": { - "contents": "", - "bgcolor": "1" - }, - "23,22": { - "contents": "", - "bgcolor": "1" - }, - "23,23": { - "contents": "", - "bgcolor": "1" - }, - "23,24": { - "contents": "", - "bgcolor": "1" - }, - "23,25": { - "contents": "", - "bgcolor": "1" - }, - "23,26": { - "contents": "", - "bgcolor": "1" - }, - "23,27": { - "contents": "", - "bgcolor": "1" - }, - "23,28": { - "contents": "", - "bgcolor": "1" - }, - "23,29": { - "contents": "", - "bgcolor": "1" - }, - "23,3": { - "contents": "", - "bgcolor": "1" - }, - "23,30": { - "contents": "", - "bgcolor": "1" - }, - "23,31": { - "contents": "", - "bgcolor": "1" - }, - "23,32": { - "contents": "", - "bgcolor": "1" - }, - "23,33": { - "contents": "", - "bgcolor": "1" - }, - "23,34": { - "contents": "", - "bgcolor": "1" - }, - "23,35": { - "contents": "", - "bgcolor": "1" - }, - "23,36": { - "contents": "", - "bgcolor": "1" - }, - "23,37": { - "contents": "", - "bgcolor": "1" - }, - "23,38": { - "contents": "", - "bgcolor": "1" - }, - "23,39": { - "contents": "", - "bgcolor": "1" - }, - "23,4": { - "contents": "", - "bgcolor": "1" - }, - "23,40": { - "contents": "", - "bgcolor": "1" - }, - "23,41": { - "contents": "", - "bgcolor": "1" - }, - "23,42": { - "contents": "", - "bgcolor": "1" - }, - "23,43": { - "contents": "", - "bgcolor": "1" - }, - "23,44": { - "contents": "", - "bgcolor": "1" - }, - "23,45": { - "contents": "", - "bgcolor": "1" - }, - "23,46": { - "contents": "", - "bgcolor": "1" - }, - "23,47": { - "contents": "", - "bgcolor": "1" - }, - "23,48": { - "contents": "", - "bgcolor": "1" - }, - "23,49": { - "contents": "", - "bgcolor": "1" - }, - "23,5": { - "contents": "", - "bgcolor": "1" - }, - "23,50": { - "contents": "", - "bgcolor": "1" - }, - "23,51": { - "contents": "", - "bgcolor": "1" - }, - "23,52": { - "contents": "", - "bgcolor": "1" - }, - "23,53": { - "contents": "", - "bgcolor": "1" - }, - "23,54": { - "contents": "", - "bgcolor": "1" - }, - "23,55": { - "contents": "", - "bgcolor": "1" - }, - "23,56": { - "contents": "", - "bgcolor": "1" - }, - "23,57": { - "contents": "", - "bgcolor": "1" - }, - "23,58": { - "contents": "", - "bgcolor": "1" - }, - "23,59": { - "contents": "", - "bgcolor": "1" - }, - "23,6": { - "contents": "", - "bgcolor": "1" - }, - "23,60": { - "contents": "", - "bgcolor": "1" - }, - "23,61": { - "contents": "", - "bgcolor": "1" - }, - "23,62": { - "contents": "", - "bgcolor": "1" - }, - "23,63": { - "contents": "", - "bgcolor": "1" - }, - "23,64": { - "contents": "", - "bgcolor": "1" - }, - "23,65": { - "contents": "", - "bgcolor": "1" - }, - "23,66": { - "contents": "", - "bgcolor": "1" - }, - "23,67": { - "contents": "", - "bgcolor": "1" - }, - "23,68": { - "contents": "", - "bgcolor": "1" - }, - "23,69": { - "contents": "", - "bgcolor": "1" - }, - "23,7": { - "contents": "", - "bgcolor": "1" - }, - "23,70": { - "contents": "", - "bgcolor": "1" - }, - "23,71": { - "contents": "", - "bgcolor": "1" - }, - "23,72": { - "contents": "", - "bgcolor": "1" - }, - "23,73": { - "contents": "", - "bgcolor": "1" - }, - "23,74": { - "contents": "", - "bgcolor": "1" - }, - "23,75": { - "contents": "", - "bgcolor": "1" - }, - "23,76": { - "contents": "", - "bgcolor": "1" - }, - "23,77": { - "contents": "", - "bgcolor": "1" - }, - "23,78": { - "contents": "", - "bgcolor": "1" - }, - "23,79": { - "contents": "", - "bgcolor": "1" - }, - "23,8": { - "contents": "", - "bgcolor": "1" - }, - "23,9": { - "contents": "", - "bgcolor": "1" - }, - "4,10": { - "contents": "", - "bgcolor": "1" - }, - "4,11": { - "contents": "", - "bgcolor": "1" - }, - "4,12": { - "contents": "", - "bgcolor": "1" - }, - "4,13": { - "contents": "", - "bgcolor": "1" - }, - "4,14": { - "contents": "", - "bgcolor": "1" - }, - "4,15": { - "contents": "", - "bgcolor": "1" - }, - "4,16": { - "contents": "", - "bgcolor": "1" - }, - "4,17": { - "contents": "", - "bgcolor": "1" - }, - "4,18": { - "contents": "", - "bgcolor": "1" - }, - "4,19": { - "contents": "", - "bgcolor": "1" - }, - "4,20": { - "contents": "", - "bgcolor": "1" - }, - "4,21": { - "contents": "", - "bgcolor": "1" - }, - "4,22": { - "contents": "", - "bgcolor": "1" - }, - "4,23": { - "contents": "", - "bgcolor": "1" - }, - "4,24": { - "contents": "", - "bgcolor": "1" - }, - "4,25": { - "contents": "", - "bgcolor": "1" - }, - "4,26": { - "contents": "", - "bgcolor": "1" - }, - "4,27": { - "contents": "", - "bgcolor": "1" - }, - "4,28": { - "contents": "", - "bgcolor": "1" - }, - "4,29": { - "contents": "", - "bgcolor": "1" - }, - "4,30": { - "contents": "", - "bgcolor": "1" - }, - "4,31": { - "contents": "", - "bgcolor": "1" - }, - "4,32": { - "contents": "", - "bgcolor": "1" - }, - "4,33": { - "contents": "", - "bgcolor": "1" - }, - "4,34": { - "contents": "", - "bgcolor": "1" - }, - "4,35": { - "contents": "", - "bgcolor": "1" - }, - "4,36": { - "contents": "", - "bgcolor": "1" - }, - "4,37": { - "contents": "", - "bgcolor": "1" - }, - "4,38": { - "contents": "", - "bgcolor": "1" - }, - "4,39": { - "contents": "", - "bgcolor": "1" - }, - "4,4": { - "contents": "", - "bgcolor": "1" - }, - "4,40": { - "contents": "", - "bgcolor": "1" - }, - "4,41": { - "contents": "", - "bgcolor": "1" - }, - "4,42": { - "contents": "", - "bgcolor": "1" - }, - "4,43": { - "contents": "", - "bgcolor": "1" - }, - "4,44": { - "contents": "", - "bgcolor": "1" - }, - "4,45": { - "contents": "", - "bgcolor": "1" - }, - "4,46": { - "contents": "", - "bgcolor": "1" - }, - "4,47": { - "contents": "", - "bgcolor": "1" - }, - "4,48": { - "contents": "", - "bgcolor": "1" - }, - "4,49": { - "contents": "", - "bgcolor": "1" - }, - "4,5": { - "contents": "", - "bgcolor": "1" - }, - "4,50": { - "contents": "", - "bgcolor": "1" - }, - "4,51": { - "contents": "", - "bgcolor": "1" - }, - "4,52": { - "contents": "", - "bgcolor": "1" - }, - "4,53": { - "contents": "", - "bgcolor": "1" - }, - "4,54": { - "contents": "", - "bgcolor": "1" - }, - "4,55": { - "contents": "", - "bgcolor": "1" - }, - "4,56": { - "contents": "", - "bgcolor": "1" - }, - "4,57": { - "contents": "", - "bgcolor": "1" - }, - "4,58": { - "contents": "", - "bgcolor": "1" - }, - "4,59": { - "contents": "", - "bgcolor": "1" - }, - "4,6": { - "contents": "", - "bgcolor": "1" - }, - "4,60": { - "contents": "", - "bgcolor": "1" - }, - "4,61": { - "contents": "", - "bgcolor": "1" - }, - "4,62": { - "contents": "", - "bgcolor": "1" - }, - "4,63": { - "contents": "", - "bgcolor": "1" - }, - "4,64": { - "contents": "", - "bgcolor": "1" - }, - "4,65": { - "contents": "", - "bgcolor": "1" - }, - "4,66": { - "contents": "", - "bgcolor": "1" - }, - "4,67": { - "contents": "", - "bgcolor": "1" - }, - "4,68": { - "contents": "", - "bgcolor": "1" - }, - "4,69": { - "contents": "", - "bgcolor": "1" - }, - "4,7": { - "contents": "", - "bgcolor": "1" - }, - "4,70": { - "contents": "", - "bgcolor": "1" - }, - "4,71": { - "contents": "", - "bgcolor": "1" - }, - "4,72": { - "contents": "", - "bgcolor": "1" - }, - "4,73": { - "contents": "", - "bgcolor": "1" - }, - "4,74": { - "contents": "", - "bgcolor": "1" - }, - "4,75": { - "contents": "", - "bgcolor": "1" - }, - "4,76": { - "contents": "", - "bgcolor": "1" - }, - "4,77": { - "contents": "", - "bgcolor": "1" - }, - "4,78": { - "contents": "", - "bgcolor": "1" - }, - "4,79": { - "contents": "", - "bgcolor": "1" - }, - "4,8": { - "contents": "", - "bgcolor": "1" - }, - "4,9": { - "contents": "", - "bgcolor": "1" - }, - "5,0": { - "contents": "", - "bgcolor": "1" - }, - "5,1": { - "contents": "", - "bgcolor": "1" - }, - "5,10": { - "contents": "", - "bgcolor": "1" - }, - "5,11": { - "contents": "", - "bgcolor": "1" - }, - "5,12": { - "contents": "", - "bgcolor": "1" - }, - "5,13": { - "contents": "", - "bgcolor": "1" - }, - "5,14": { - "contents": "", - "bgcolor": "1" - }, - "5,15": { - "contents": "", - "bgcolor": "1" - }, - "5,16": { - "contents": "", - "bgcolor": "1" - }, - "5,17": { - "contents": "", - "bgcolor": "1" - }, - "5,18": { - "contents": "", - "bgcolor": "1" - }, - "5,19": { - "contents": "", - "bgcolor": "1" - }, - "5,2": { - "contents": "", - "bgcolor": "1" - }, - "5,20": { - "contents": "", - "bgcolor": "1" - }, - "5,21": { - "contents": "", - "bgcolor": "1" - }, - "5,22": { - "contents": "", - "bgcolor": "1" - }, - "5,23": { - "contents": "", - "bgcolor": "1" - }, - "5,24": { - "contents": "", - "bgcolor": "1" - }, - "5,25": { - "contents": "", - "bgcolor": "1" - }, - "5,26": { - "contents": "", - "bgcolor": "1" - }, - "5,27": { - "contents": "", - "bgcolor": "1" - }, - "5,28": { - "contents": "", - "bgcolor": "1" - }, - "5,29": { - "contents": "", - "bgcolor": "1" - }, - "5,3": { - "contents": "", - "bgcolor": "1" - }, - "5,30": { - "contents": "", - "bgcolor": "1" - }, - "5,31": { - "contents": "", - "bgcolor": "1" - }, - "5,32": { - "contents": "", - "bgcolor": "1" - }, - "5,33": { - "contents": "", - "bgcolor": "1" - }, - "5,34": { - "contents": "", - "bgcolor": "1" - }, - "5,35": { - "contents": "", - "bgcolor": "1" - }, - "5,36": { - "contents": "", - "bgcolor": "1" - }, - "5,37": { - "contents": "", - "bgcolor": "1" - }, - "5,38": { - "contents": "", - "bgcolor": "1" - }, - "5,39": { - "contents": "", - "bgcolor": "1" - }, - "5,4": { - "contents": "", - "bgcolor": "1" - }, - "5,40": { - "contents": "", - "bgcolor": "1" - }, - "5,41": { - "contents": "", - "bgcolor": "1" - }, - "5,42": { - "contents": "", - "bgcolor": "1" - }, - "5,43": { - "contents": "", - "bgcolor": "1" - }, - "5,44": { - "contents": "", - "bgcolor": "1" - }, - "5,45": { - "contents": "", - "bgcolor": "1" - }, - "5,46": { - "contents": "", - "bgcolor": "1" - }, - "5,47": { - "contents": "", - "bgcolor": "1" - }, - "5,48": { - "contents": "", - "bgcolor": "1" - }, - "5,49": { - "contents": "", - "bgcolor": "1" - }, - "5,5": { - "contents": "", - "bgcolor": "1" - }, - "5,50": { - "contents": "", - "bgcolor": "1" - }, - "5,51": { - "contents": "", - "bgcolor": "1" - }, - "5,52": { - "contents": "", - "bgcolor": "1" - }, - "5,53": { - "contents": "", - "bgcolor": "1" - }, - "5,54": { - "contents": "", - "bgcolor": "1" - }, - "5,55": { - "contents": "", - "bgcolor": "1" - }, - "5,56": { - "contents": "", - "bgcolor": "1" - }, - "5,57": { - "contents": "", - "bgcolor": "1" - }, - "5,58": { - "contents": "", - "bgcolor": "1" - }, - "5,59": { - "contents": "", - "bgcolor": "1" - }, - "5,6": { - "contents": "", - "bgcolor": "1" - }, - "5,60": { - "contents": "", - "bgcolor": "1" - }, - "5,61": { - "contents": "", - "bgcolor": "1" - }, - "5,62": { - "contents": "", - "bgcolor": "1" - }, - "5,63": { - "contents": "", - "bgcolor": "1" - }, - "5,64": { - "contents": "", - "bgcolor": "1" - }, - "5,65": { - "contents": "", - "bgcolor": "1" - }, - "5,66": { - "contents": "", - "bgcolor": "1" - }, - "5,67": { - "contents": "", - "bgcolor": "1" - }, - "5,68": { - "contents": "", - "bgcolor": "1" - }, - "5,69": { - "contents": "", - "bgcolor": "1" - }, - "5,7": { - "contents": "", - "bgcolor": "1" - }, - "5,70": { - "contents": "", - "bgcolor": "1" - }, - "5,71": { - "contents": "", - "bgcolor": "1" - }, - "5,72": { - "contents": "", - "bgcolor": "1" - }, - "5,73": { - "contents": "", - "bgcolor": "1" - }, - "5,74": { - "contents": "", - "bgcolor": "1" - }, - "5,75": { - "contents": "", - "bgcolor": "1" - }, - "5,76": { - "contents": "", - "bgcolor": "1" - }, - "5,77": { - "contents": "", - "bgcolor": "1" - }, - "5,78": { - "contents": "", - "bgcolor": "1" - }, - "5,79": { - "contents": "", - "bgcolor": "1" - }, - "5,8": { - "contents": "", - "bgcolor": "1" - }, - "5,9": { - "contents": "", - "bgcolor": "1" - }, - "6,0": { - "contents": "", - "bgcolor": "1" - }, - "6,1": { - "contents": "", - "bgcolor": "1" - }, - "6,10": { - "contents": "", - "bgcolor": "1" - }, - "6,11": { - "contents": "", - "bgcolor": "1" - }, - "6,12": { - "contents": "", - "bgcolor": "1" - }, - "6,13": { - "contents": "", - "bgcolor": "1" - }, - "6,14": { - "contents": "", - "bgcolor": "1" - }, - "6,15": { - "contents": "", - "bgcolor": "1" - }, - "6,16": { - "contents": "", - "bgcolor": "1" - }, - "6,17": { - "contents": "", - "bgcolor": "1" - }, - "6,18": { - "contents": "", - "bgcolor": "1" - }, - "6,19": { - "contents": "", - "bgcolor": "1" - }, - "6,2": { - "contents": "", - "bgcolor": "1" - }, - "6,20": { - "contents": "", - "bgcolor": "1" - }, - "6,21": { - "contents": "", - "bgcolor": "1" - }, - "6,22": { - "contents": "", - "bgcolor": "1" - }, - "6,23": { - "contents": "", - "bgcolor": "1" - }, - "6,24": { - "contents": "", - "bgcolor": "1" - }, - "6,25": { - "contents": "", - "bgcolor": "1" - }, - "6,26": { - "contents": "", - "bgcolor": "1" - }, - "6,27": { - "contents": "", - "bgcolor": "1" - }, - "6,28": { - "contents": "", - "bgcolor": "1" - }, - "6,29": { - "contents": "", - "bgcolor": "1" - }, - "6,3": { - "contents": "", - "bgcolor": "1" - }, - "6,30": { - "contents": "", - "bgcolor": "1" - }, - "6,31": { - "contents": "", - "bgcolor": "1" - }, - "6,32": { - "contents": "", - "bgcolor": "1" - }, - "6,33": { - "contents": "", - "bgcolor": "1" - }, - "6,34": { - "contents": "", - "bgcolor": "1" - }, - "6,35": { - "contents": "", - "bgcolor": "1" - }, - "6,36": { - "contents": "", - "bgcolor": "1" - }, - "6,37": { - "contents": "", - "bgcolor": "1" - }, - "6,38": { - "contents": "", - "bgcolor": "1" - }, - "6,39": { - "contents": "", - "bgcolor": "1" - }, - "6,4": { - "contents": "", - "bgcolor": "1" - }, - "6,40": { - "contents": "", - "bgcolor": "1" - }, - "6,41": { - "contents": "", - "bgcolor": "1" - }, - "6,42": { - "contents": "", - "bgcolor": "1" - }, - "6,43": { - "contents": "", - "bgcolor": "1" - }, - "6,44": { - "contents": "", - "bgcolor": "1" - }, - "6,45": { - "contents": "", - "bgcolor": "1" - }, - "6,46": { - "contents": "", - "bgcolor": "1" - }, - "6,47": { - "contents": "", - "bgcolor": "1" - }, - "6,48": { - "contents": "", - "bgcolor": "1" - }, - "6,49": { - "contents": "", - "bgcolor": "1" - }, - "6,5": { - "contents": "", - "bgcolor": "1" - }, - "6,50": { - "contents": "", - "bgcolor": "1" - }, - "6,51": { - "contents": "", - "bgcolor": "1" - }, - "6,52": { - "contents": "", - "bgcolor": "1" - }, - "6,53": { - "contents": "", - "bgcolor": "1" - }, - "6,54": { - "contents": "", - "bgcolor": "1" - }, - "6,55": { - "contents": "", - "bgcolor": "1" - }, - "6,56": { - "contents": "", - "bgcolor": "1" - }, - "6,57": { - "contents": "", - "bgcolor": "1" - }, - "6,58": { - "contents": "", - "bgcolor": "1" - }, - "6,59": { - "contents": "", - "bgcolor": "1" - }, - "6,6": { - "contents": "", - "bgcolor": "1" - }, - "6,60": { - "contents": "", - "bgcolor": "1" - }, - "6,61": { - "contents": "", - "bgcolor": "1" - }, - "6,62": { - "contents": "", - "bgcolor": "1" - }, - "6,63": { - "contents": "", - "bgcolor": "1" - }, - "6,64": { - "contents": "", - "bgcolor": "1" - }, - "6,65": { - "contents": "", - "bgcolor": "1" - }, - "6,66": { - "contents": "", - "bgcolor": "1" - }, - "6,67": { - "contents": "", - "bgcolor": "1" - }, - "6,68": { - "contents": "", - "bgcolor": "1" - }, - "6,69": { - "contents": "", - "bgcolor": "1" - }, - "6,7": { - "contents": "", - "bgcolor": "1" - }, - "6,70": { - "contents": "", - "bgcolor": "1" - }, - "6,71": { - "contents": "", - "bgcolor": "1" - }, - "6,72": { - "contents": "", - "bgcolor": "1" - }, - "6,73": { - "contents": "", - "bgcolor": "1" - }, - "6,74": { - "contents": "", - "bgcolor": "1" - }, - "6,75": { - "contents": "", - "bgcolor": "1" - }, - "6,76": { - "contents": "", - "bgcolor": "1" - }, - "6,77": { - "contents": "", - "bgcolor": "1" - }, - "6,78": { - "contents": "", - "bgcolor": "1" - }, - "6,79": { - "contents": "", - "bgcolor": "1" - }, - "6,8": { - "contents": "", - "bgcolor": "1" - }, - "6,9": { - "contents": "", - "bgcolor": "1" - }, - "7,0": { - "contents": "", - "bgcolor": "1" - }, - "7,1": { - "contents": "", - "bgcolor": "1" - }, - "7,10": { - "contents": "", - "bgcolor": "1" - }, - "7,11": { - "contents": "", - "bgcolor": "1" - }, - "7,12": { - "contents": "", - "bgcolor": "1" - }, - "7,13": { - "contents": "", - "bgcolor": "1" - }, - "7,14": { - "contents": "", - "bgcolor": "1" - }, - "7,15": { - "contents": "", - "bgcolor": "1" - }, - "7,16": { - "contents": "", - "bgcolor": "1" - }, - "7,17": { - "contents": "", - "bgcolor": "1" - }, - "7,18": { - "contents": "", - "bgcolor": "1" - }, - "7,19": { - "contents": "", - "bgcolor": "1" - }, - "7,2": { - "contents": "", - "bgcolor": "1" - }, - "7,20": { - "contents": "", - "bgcolor": "1" - }, - "7,21": { - "contents": "", - "bgcolor": "1" - }, - "7,22": { - "contents": "", - "bgcolor": "1" - }, - "7,23": { - "contents": "", - "bgcolor": "1" - }, - "7,24": { - "contents": "", - "bgcolor": "1" - }, - "7,25": { - "contents": "", - "bgcolor": "1" - }, - "7,26": { - "contents": "", - "bgcolor": "1" - }, - "7,27": { - "contents": "", - "bgcolor": "1" - }, - "7,28": { - "contents": "", - "bgcolor": "1" - }, - "7,29": { - "contents": "", - "bgcolor": "1" - }, - "7,3": { - "contents": "", - "bgcolor": "1" - }, - "7,30": { - "contents": "", - "bgcolor": "1" - }, - "7,31": { - "contents": "", - "bgcolor": "1" - }, - "7,32": { - "contents": "", - "bgcolor": "1" - }, - "7,33": { - "contents": "", - "bgcolor": "1" - }, - "7,34": { - "contents": "", - "bgcolor": "1" - }, - "7,35": { - "contents": "", - "bgcolor": "1" - }, - "7,36": { - "contents": "", - "bgcolor": "1" - }, - "7,37": { - "contents": "", - "bgcolor": "1" - }, - "7,38": { - "contents": "", - "bgcolor": "1" - }, - "7,39": { - "contents": "", - "bgcolor": "1" - }, - "7,4": { - "contents": "", - "bgcolor": "1" - }, - "7,40": { - "contents": "", - "bgcolor": "1" - }, - "7,41": { - "contents": "", - "bgcolor": "1" - }, - "7,42": { - "contents": "", - "bgcolor": "1" - }, - "7,43": { - "contents": "", - "bgcolor": "1" - }, - "7,44": { - "contents": "", - "bgcolor": "1" - }, - "7,45": { - "contents": "", - "bgcolor": "1" - }, - "7,46": { - "contents": "", - "bgcolor": "1" - }, - "7,47": { - "contents": "", - "bgcolor": "1" - }, - "7,48": { - "contents": "", - "bgcolor": "1" - }, - "7,49": { - "contents": "", - "bgcolor": "1" - }, - "7,5": { - "contents": "", - "bgcolor": "1" - }, - "7,50": { - "contents": "", - "bgcolor": "1" - }, - "7,51": { - "contents": "", - "bgcolor": "1" - }, - "7,52": { - "contents": "", - "bgcolor": "1" - }, - "7,53": { - "contents": "", - "bgcolor": "1" - }, - "7,54": { - "contents": "", - "bgcolor": "1" - }, - "7,55": { - "contents": "", - "bgcolor": "1" - }, - "7,56": { - "contents": "", - "bgcolor": "1" - }, - "7,57": { - "contents": "", - "bgcolor": "1" - }, - "7,58": { - "contents": "", - "bgcolor": "1" - }, - "7,59": { - "contents": "", - "bgcolor": "1" - }, - "7,6": { - "contents": "", - "bgcolor": "1" - }, - "7,60": { - "contents": "", - "bgcolor": "1" - }, - "7,61": { - "contents": "", - "bgcolor": "1" - }, - "7,62": { - "contents": "", - "bgcolor": "1" - }, - "7,63": { - "contents": "", - "bgcolor": "1" - }, - "7,64": { - "contents": "", - "bgcolor": "1" - }, - "7,65": { - "contents": "", - "bgcolor": "1" - }, - "7,66": { - "contents": "", - "bgcolor": "1" - }, - "7,67": { - "contents": "", - "bgcolor": "1" - }, - "7,68": { - "contents": "", - "bgcolor": "1" - }, - "7,69": { - "contents": "", - "bgcolor": "1" - }, - "7,7": { - "contents": "", - "bgcolor": "1" - }, - "7,70": { - "contents": "", - "bgcolor": "1" - }, - "7,71": { - "contents": "", - "bgcolor": "1" - }, - "7,72": { - "contents": "", - "bgcolor": "1" - }, - "7,73": { - "contents": "", - "bgcolor": "1" - }, - "7,74": { - "contents": "", - "bgcolor": "1" - }, - "7,75": { - "contents": "", - "bgcolor": "1" - }, - "7,76": { - "contents": "", - "bgcolor": "1" - }, - "7,77": { - "contents": "", - "bgcolor": "1" - }, - "7,78": { - "contents": "", - "bgcolor": "1" - }, - "7,79": { - "contents": "", - "bgcolor": "1" - }, - "7,8": { - "contents": "", - "bgcolor": "1" - }, - "7,9": { - "contents": "", - "bgcolor": "1" - }, - "8,0": { - "contents": "", - "bgcolor": "1" - }, - "8,1": { - "contents": "", - "bgcolor": "1" - }, - "8,10": { - "contents": "", - "bgcolor": "1" - }, - "8,11": { - "contents": "", - "bgcolor": "1" - }, - "8,12": { - "contents": "", - "bgcolor": "1" - }, - "8,13": { - "contents": "", - "bgcolor": "1" - }, - "8,14": { - "contents": "", - "bgcolor": "1" - }, - "8,15": { - "contents": "", - "bgcolor": "1" - }, - "8,16": { - "contents": "", - "bgcolor": "1" - }, - "8,17": { - "contents": "", - "bgcolor": "1" - }, - "8,18": { - "contents": "", - "bgcolor": "1" - }, - "8,19": { - "contents": "", - "bgcolor": "1" - }, - "8,2": { - "contents": "", - "bgcolor": "1" - }, - "8,20": { - "contents": "", - "bgcolor": "1" - }, - "8,21": { - "contents": "", - "bgcolor": "1" - }, - "8,22": { - "contents": "", - "bgcolor": "1" - }, - "8,23": { - "contents": "", - "bgcolor": "1" - }, - "8,24": { - "contents": "", - "bgcolor": "1" - }, - "8,25": { - "contents": "", - "bgcolor": "1" - }, - "8,26": { - "contents": "", - "bgcolor": "1" - }, - "8,27": { - "contents": "", - "bgcolor": "1" - }, - "8,28": { - "contents": "", - "bgcolor": "1" - }, - "8,29": { - "contents": "", - "bgcolor": "1" - }, - "8,3": { - "contents": "", - "bgcolor": "1" - }, - "8,30": { - "contents": "", - "bgcolor": "1" - }, - "8,31": { - "contents": "", - "bgcolor": "1" - }, - "8,32": { - "contents": "", - "bgcolor": "1" - }, - "8,33": { - "contents": "", - "bgcolor": "1" - }, - "8,34": { - "contents": "", - "bgcolor": "1" - }, - "8,35": { - "contents": "", - "bgcolor": "1" - }, - "8,36": { - "contents": "", - "bgcolor": "1" - }, - "8,37": { - "contents": "", - "bgcolor": "1" - }, - "8,38": { - "contents": "", - "bgcolor": "1" - }, - "8,39": { - "contents": "", - "bgcolor": "1" - }, - "8,4": { - "contents": "", - "bgcolor": "1" - }, - "8,40": { - "contents": "", - "bgcolor": "1" - }, - "8,41": { - "contents": "", - "bgcolor": "1" - }, - "8,42": { - "contents": "", - "bgcolor": "1" - }, - "8,43": { - "contents": "", - "bgcolor": "1" - }, - "8,44": { - "contents": "", - "bgcolor": "1" - }, - "8,45": { - "contents": "", - "bgcolor": "1" - }, - "8,46": { - "contents": "", - "bgcolor": "1" - }, - "8,47": { - "contents": "", - "bgcolor": "1" - }, - "8,48": { - "contents": "", - "bgcolor": "1" - }, - "8,49": { - "contents": "", - "bgcolor": "1" - }, - "8,5": { - "contents": "", - "bgcolor": "1" - }, - "8,50": { - "contents": "", - "bgcolor": "1" - }, - "8,51": { - "contents": "", - "bgcolor": "1" - }, - "8,52": { - "contents": "", - "bgcolor": "1" - }, - "8,53": { - "contents": "", - "bgcolor": "1" - }, - "8,54": { - "contents": "", - "bgcolor": "1" - }, - "8,55": { - "contents": "", - "bgcolor": "1" - }, - "8,56": { - "contents": "", - "bgcolor": "1" - }, - "8,57": { - "contents": "", - "bgcolor": "1" - }, - "8,58": { - "contents": "", - "bgcolor": "1" - }, - "8,59": { - "contents": "", - "bgcolor": "1" - }, - "8,6": { - "contents": "", - "bgcolor": "1" - }, - "8,60": { - "contents": "", - "bgcolor": "1" - }, - "8,61": { - "contents": "", - "bgcolor": "1" - }, - "8,62": { - "contents": "", - "bgcolor": "1" - }, - "8,63": { - "contents": "", - "bgcolor": "1" - }, - "8,64": { - "contents": "", - "bgcolor": "1" - }, - "8,65": { - "contents": "", - "bgcolor": "1" - }, - "8,66": { - "contents": "", - "bgcolor": "1" - }, - "8,67": { - "contents": "", - "bgcolor": "1" - }, - "8,68": { - "contents": "", - "bgcolor": "1" - }, - "8,69": { - "contents": "", - "bgcolor": "1" - }, - "8,7": { - "contents": "", - "bgcolor": "1" - }, - "8,70": { - "contents": "", - "bgcolor": "1" - }, - "8,71": { - "contents": "", - "bgcolor": "1" - }, - "8,72": { - "contents": "", - "bgcolor": "1" - }, - "8,73": { - "contents": "", - "bgcolor": "1" - }, - "8,74": { - "contents": "", - "bgcolor": "1" - }, - "8,75": { - "contents": "", - "bgcolor": "1" - }, - "8,76": { - "contents": "", - "bgcolor": "1" - }, - "8,77": { - "contents": "", - "bgcolor": "1" - }, - "8,78": { - "contents": "", - "bgcolor": "1" - }, - "8,79": { - "contents": "", - "bgcolor": "1" - }, - "8,8": { - "contents": "", - "bgcolor": "1" - }, - "8,9": { - "contents": "", - "bgcolor": "1" - }, - "9,0": { - "contents": "", - "bgcolor": "1" - }, - "9,1": { - "contents": "", - "bgcolor": "1" - }, - "9,10": { - "contents": "", - "bgcolor": "1" - }, - "9,11": { - "contents": "", - "bgcolor": "1" - }, - "9,12": { - "contents": "", - "bgcolor": "1" - }, - "9,13": { - "contents": "", - "bgcolor": "1" - }, - "9,14": { - "contents": "", - "bgcolor": "1" - }, - "9,15": { - "contents": "", - "bgcolor": "1" - }, - "9,16": { - "contents": "", - "bgcolor": "1" - }, - "9,17": { - "contents": "", - "bgcolor": "1" - }, - "9,18": { - "contents": "", - "bgcolor": "1" - }, - "9,19": { - "contents": "", - "bgcolor": "1" - }, - "9,2": { - "contents": "", - "bgcolor": "1" - }, - "9,20": { - "contents": "", - "bgcolor": "1" - }, - "9,21": { - "contents": "", - "bgcolor": "1" - }, - "9,22": { - "contents": "", - "bgcolor": "1" - }, - "9,23": { - "contents": "", - "bgcolor": "1" - }, - "9,24": { - "contents": "", - "bgcolor": "1" - }, - "9,25": { - "contents": "", - "bgcolor": "1" - }, - "9,26": { - "contents": "", - "bgcolor": "1" - }, - "9,27": { - "contents": "", - "bgcolor": "1" - }, - "9,28": { - "contents": "", - "bgcolor": "1" - }, - "9,29": { - "contents": "", - "bgcolor": "1" - }, - "9,3": { - "contents": "", - "bgcolor": "1" - }, - "9,30": { - "contents": "", - "bgcolor": "1" - }, - "9,31": { - "contents": "", - "bgcolor": "1" - }, - "9,32": { - "contents": "", - "bgcolor": "1" - }, - "9,33": { - "contents": "", - "bgcolor": "1" - }, - "9,34": { - "contents": "", - "bgcolor": "1" - }, - "9,35": { - "contents": "", - "bgcolor": "1" - }, - "9,36": { - "contents": "", - "bgcolor": "1" - }, - "9,37": { - "contents": "", - "bgcolor": "1" - }, - "9,38": { - "contents": "", - "bgcolor": "1" - }, - "9,39": { - "contents": "", - "bgcolor": "1" - }, - "9,4": { - "contents": "", - "bgcolor": "1" - }, - "9,40": { - "contents": "", - "bgcolor": "1" - }, - "9,41": { - "contents": "", - "bgcolor": "1" - }, - "9,42": { - "contents": "", - "bgcolor": "1" - }, - "9,43": { - "contents": "", - "bgcolor": "1" - }, - "9,44": { - "contents": "", - "bgcolor": "1" - }, - "9,45": { - "contents": "", - "bgcolor": "1" - }, - "9,46": { - "contents": "", - "bgcolor": "1" - }, - "9,47": { - "contents": "", - "bgcolor": "1" - }, - "9,48": { - "contents": "", - "bgcolor": "1" - }, - "9,49": { - "contents": "", - "bgcolor": "1" - }, - "9,5": { - "contents": "", - "bgcolor": "1" - }, - "9,50": { - "contents": "", - "bgcolor": "1" - }, - "9,51": { - "contents": "", - "bgcolor": "1" - }, - "9,52": { - "contents": "", - "bgcolor": "1" - }, - "9,53": { - "contents": "", - "bgcolor": "1" - }, - "9,54": { - "contents": "", - "bgcolor": "1" - }, - "9,55": { - "contents": "", - "bgcolor": "1" - }, - "9,56": { - "contents": "", - "bgcolor": "1" - }, - "9,57": { - "contents": "", - "bgcolor": "1" - }, - "9,58": { - "contents": "", - "bgcolor": "1" - }, - "9,59": { - "contents": "", - "bgcolor": "1" - }, - "9,6": { - "contents": "", - "bgcolor": "1" - }, - "9,60": { - "contents": "", - "bgcolor": "1" - }, - "9,61": { - "contents": "", - "bgcolor": "1" - }, - "9,62": { - "contents": "", - "bgcolor": "1" - }, - "9,63": { - "contents": "", - "bgcolor": "1" - }, - "9,64": { - "contents": "", - "bgcolor": "1" - }, - "9,65": { - "contents": "", - "bgcolor": "1" - }, - "9,66": { - "contents": "", - "bgcolor": "1" - }, - "9,67": { - "contents": "", - "bgcolor": "1" - }, - "9,68": { - "contents": "", - "bgcolor": "1" - }, - "9,69": { - "contents": "", - "bgcolor": "1" - }, - "9,7": { - "contents": "", - "bgcolor": "1" - }, - "9,70": { - "contents": "", - "bgcolor": "1" - }, - "9,71": { - "contents": "", - "bgcolor": "1" - }, - "9,72": { - "contents": "", - "bgcolor": "1" - }, - "9,73": { - "contents": "", - "bgcolor": "1" - }, - "9,74": { - "contents": "", - "bgcolor": "1" - }, - "9,75": { - "contents": "", - "bgcolor": "1" - }, - "9,76": { - "contents": "", - "bgcolor": "1" - }, - "9,77": { - "contents": "", - "bgcolor": "1" - }, - "9,78": { - "contents": "", - "bgcolor": "1" - }, - "9,79": { - "contents": "", - "bgcolor": "1" - }, - "9,8": { - "contents": "", - "bgcolor": "1" - }, - "9,9": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/17.typescript deleted file mode 100644 index 331e02e0166c9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/17.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/18.json b/crates/turborepo-vt100/tests/data/fixtures/ed/18.json deleted file mode 100644 index 2b060efecfe66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/18.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/18.typescript deleted file mode 100644 index 8adc44f0bdefe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/18.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/19.json b/crates/turborepo-vt100/tests/data/fixtures/ed/19.json deleted file mode 100644 index dfe1d6f61b73b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/19.json +++ /dev/null @@ -1,1309 +0,0 @@ -{ - "contents": "", - "cells": { - "0,0": { - "contents": "", - "bgcolor": "1" - }, - "0,1": { - "contents": "", - "bgcolor": "1" - }, - "0,10": { - "contents": "", - "bgcolor": "1" - }, - "0,11": { - "contents": "", - "bgcolor": "1" - }, - "0,12": { - "contents": "", - "bgcolor": "1" - }, - "0,13": { - "contents": "", - "bgcolor": "1" - }, - "0,14": { - "contents": "", - "bgcolor": "1" - }, - "0,15": { - "contents": "", - "bgcolor": "1" - }, - "0,16": { - "contents": "", - "bgcolor": "1" - }, - "0,17": { - "contents": "", - "bgcolor": "1" - }, - "0,18": { - "contents": "", - "bgcolor": "1" - }, - "0,19": { - "contents": "", - "bgcolor": "1" - }, - "0,2": { - "contents": "", - "bgcolor": "1" - }, - "0,20": { - "contents": "", - "bgcolor": "1" - }, - "0,21": { - "contents": "", - "bgcolor": "1" - }, - "0,22": { - "contents": "", - "bgcolor": "1" - }, - "0,23": { - "contents": "", - "bgcolor": "1" - }, - "0,24": { - "contents": "", - "bgcolor": "1" - }, - "0,25": { - "contents": "", - "bgcolor": "1" - }, - "0,26": { - "contents": "", - "bgcolor": "1" - }, - "0,27": { - "contents": "", - "bgcolor": "1" - }, - "0,28": { - "contents": "", - "bgcolor": "1" - }, - "0,29": { - "contents": "", - "bgcolor": "1" - }, - "0,3": { - "contents": "", - "bgcolor": "1" - }, - "0,30": { - "contents": "", - "bgcolor": "1" - }, - "0,31": { - "contents": "", - "bgcolor": "1" - }, - "0,32": { - "contents": "", - "bgcolor": "1" - }, - "0,33": { - "contents": "", - "bgcolor": "1" - }, - "0,34": { - "contents": "", - "bgcolor": "1" - }, - "0,35": { - "contents": "", - "bgcolor": "1" - }, - "0,36": { - "contents": "", - "bgcolor": "1" - }, - "0,37": { - "contents": "", - "bgcolor": "1" - }, - "0,38": { - "contents": "", - "bgcolor": "1" - }, - "0,39": { - "contents": "", - "bgcolor": "1" - }, - "0,4": { - "contents": "", - "bgcolor": "1" - }, - "0,40": { - "contents": "", - "bgcolor": "1" - }, - "0,41": { - "contents": "", - "bgcolor": "1" - }, - "0,42": { - "contents": "", - "bgcolor": "1" - }, - "0,43": { - "contents": "", - "bgcolor": "1" - }, - "0,44": { - "contents": "", - "bgcolor": "1" - }, - "0,45": { - "contents": "", - "bgcolor": "1" - }, - "0,46": { - "contents": "", - "bgcolor": "1" - }, - "0,47": { - "contents": "", - "bgcolor": "1" - }, - "0,48": { - "contents": "", - "bgcolor": "1" - }, - "0,49": { - "contents": "", - "bgcolor": "1" - }, - "0,5": { - "contents": "", - "bgcolor": "1" - }, - "0,50": { - "contents": "", - "bgcolor": "1" - }, - "0,51": { - "contents": "", - "bgcolor": "1" - }, - "0,52": { - "contents": "", - "bgcolor": "1" - }, - "0,53": { - "contents": "", - "bgcolor": "1" - }, - "0,54": { - "contents": "", - "bgcolor": "1" - }, - "0,55": { - "contents": "", - "bgcolor": "1" - }, - "0,56": { - "contents": "", - "bgcolor": "1" - }, - "0,57": { - "contents": "", - "bgcolor": "1" - }, - "0,58": { - "contents": "", - "bgcolor": "1" - }, - "0,59": { - "contents": "", - "bgcolor": "1" - }, - "0,6": { - "contents": "", - "bgcolor": "1" - }, - "0,60": { - "contents": "", - "bgcolor": "1" - }, - "0,61": { - "contents": "", - "bgcolor": "1" - }, - "0,62": { - "contents": "", - "bgcolor": "1" - }, - "0,63": { - "contents": "", - "bgcolor": "1" - }, - "0,64": { - "contents": "", - "bgcolor": "1" - }, - "0,65": { - "contents": "", - "bgcolor": "1" - }, - "0,66": { - "contents": "", - "bgcolor": "1" - }, - "0,67": { - "contents": "", - "bgcolor": "1" - }, - "0,68": { - "contents": "", - "bgcolor": "1" - }, - "0,69": { - "contents": "", - "bgcolor": "1" - }, - "0,7": { - "contents": "", - "bgcolor": "1" - }, - "0,70": { - "contents": "", - "bgcolor": "1" - }, - "0,71": { - "contents": "", - "bgcolor": "1" - }, - "0,72": { - "contents": "", - "bgcolor": "1" - }, - "0,73": { - "contents": "", - "bgcolor": "1" - }, - "0,74": { - "contents": "", - "bgcolor": "1" - }, - "0,75": { - "contents": "", - "bgcolor": "1" - }, - "0,76": { - "contents": "", - "bgcolor": "1" - }, - "0,77": { - "contents": "", - "bgcolor": "1" - }, - "0,78": { - "contents": "", - "bgcolor": "1" - }, - "0,79": { - "contents": "", - "bgcolor": "1" - }, - "0,8": { - "contents": "", - "bgcolor": "1" - }, - "0,9": { - "contents": "", - "bgcolor": "1" - }, - "1,0": { - "contents": "", - "bgcolor": "1" - }, - "1,1": { - "contents": "", - "bgcolor": "1" - }, - "1,10": { - "contents": "", - "bgcolor": "1" - }, - "1,11": { - "contents": "", - "bgcolor": "1" - }, - "1,12": { - "contents": "", - "bgcolor": "1" - }, - "1,13": { - "contents": "", - "bgcolor": "1" - }, - "1,14": { - "contents": "", - "bgcolor": "1" - }, - "1,15": { - "contents": "", - "bgcolor": "1" - }, - "1,16": { - "contents": "", - "bgcolor": "1" - }, - "1,17": { - "contents": "", - "bgcolor": "1" - }, - "1,18": { - "contents": "", - "bgcolor": "1" - }, - "1,19": { - "contents": "", - "bgcolor": "1" - }, - "1,2": { - "contents": "", - "bgcolor": "1" - }, - "1,20": { - "contents": "", - "bgcolor": "1" - }, - "1,21": { - "contents": "", - "bgcolor": "1" - }, - "1,22": { - "contents": "", - "bgcolor": "1" - }, - "1,23": { - "contents": "", - "bgcolor": "1" - }, - "1,24": { - "contents": "", - "bgcolor": "1" - }, - "1,25": { - "contents": "", - "bgcolor": "1" - }, - "1,26": { - "contents": "", - "bgcolor": "1" - }, - "1,27": { - "contents": "", - "bgcolor": "1" - }, - "1,28": { - "contents": "", - "bgcolor": "1" - }, - "1,29": { - "contents": "", - "bgcolor": "1" - }, - "1,3": { - "contents": "", - "bgcolor": "1" - }, - "1,30": { - "contents": "", - "bgcolor": "1" - }, - "1,31": { - "contents": "", - "bgcolor": "1" - }, - "1,32": { - "contents": "", - "bgcolor": "1" - }, - "1,33": { - "contents": "", - "bgcolor": "1" - }, - "1,34": { - "contents": "", - "bgcolor": "1" - }, - "1,35": { - "contents": "", - "bgcolor": "1" - }, - "1,36": { - "contents": "", - "bgcolor": "1" - }, - "1,37": { - "contents": "", - "bgcolor": "1" - }, - "1,38": { - "contents": "", - "bgcolor": "1" - }, - "1,39": { - "contents": "", - "bgcolor": "1" - }, - "1,4": { - "contents": "", - "bgcolor": "1" - }, - "1,40": { - "contents": "", - "bgcolor": "1" - }, - "1,41": { - "contents": "", - "bgcolor": "1" - }, - "1,42": { - "contents": "", - "bgcolor": "1" - }, - "1,43": { - "contents": "", - "bgcolor": "1" - }, - "1,44": { - "contents": "", - "bgcolor": "1" - }, - "1,45": { - "contents": "", - "bgcolor": "1" - }, - "1,46": { - "contents": "", - "bgcolor": "1" - }, - "1,47": { - "contents": "", - "bgcolor": "1" - }, - "1,48": { - "contents": "", - "bgcolor": "1" - }, - "1,49": { - "contents": "", - "bgcolor": "1" - }, - "1,5": { - "contents": "", - "bgcolor": "1" - }, - "1,50": { - "contents": "", - "bgcolor": "1" - }, - "1,51": { - "contents": "", - "bgcolor": "1" - }, - "1,52": { - "contents": "", - "bgcolor": "1" - }, - "1,53": { - "contents": "", - "bgcolor": "1" - }, - "1,54": { - "contents": "", - "bgcolor": "1" - }, - "1,55": { - "contents": "", - "bgcolor": "1" - }, - "1,56": { - "contents": "", - "bgcolor": "1" - }, - "1,57": { - "contents": "", - "bgcolor": "1" - }, - "1,58": { - "contents": "", - "bgcolor": "1" - }, - "1,59": { - "contents": "", - "bgcolor": "1" - }, - "1,6": { - "contents": "", - "bgcolor": "1" - }, - "1,60": { - "contents": "", - "bgcolor": "1" - }, - "1,61": { - "contents": "", - "bgcolor": "1" - }, - "1,62": { - "contents": "", - "bgcolor": "1" - }, - "1,63": { - "contents": "", - "bgcolor": "1" - }, - "1,64": { - "contents": "", - "bgcolor": "1" - }, - "1,65": { - "contents": "", - "bgcolor": "1" - }, - "1,66": { - "contents": "", - "bgcolor": "1" - }, - "1,67": { - "contents": "", - "bgcolor": "1" - }, - "1,68": { - "contents": "", - "bgcolor": "1" - }, - "1,69": { - "contents": "", - "bgcolor": "1" - }, - "1,7": { - "contents": "", - "bgcolor": "1" - }, - "1,70": { - "contents": "", - "bgcolor": "1" - }, - "1,71": { - "contents": "", - "bgcolor": "1" - }, - "1,72": { - "contents": "", - "bgcolor": "1" - }, - "1,73": { - "contents": "", - "bgcolor": "1" - }, - "1,74": { - "contents": "", - "bgcolor": "1" - }, - "1,75": { - "contents": "", - "bgcolor": "1" - }, - "1,76": { - "contents": "", - "bgcolor": "1" - }, - "1,77": { - "contents": "", - "bgcolor": "1" - }, - "1,78": { - "contents": "", - "bgcolor": "1" - }, - "1,79": { - "contents": "", - "bgcolor": "1" - }, - "1,8": { - "contents": "", - "bgcolor": "1" - }, - "1,9": { - "contents": "", - "bgcolor": "1" - }, - "2,0": { - "contents": "", - "bgcolor": "1" - }, - "2,1": { - "contents": "", - "bgcolor": "1" - }, - "2,10": { - "contents": "", - "bgcolor": "1" - }, - "2,11": { - "contents": "", - "bgcolor": "1" - }, - "2,12": { - "contents": "", - "bgcolor": "1" - }, - "2,13": { - "contents": "", - "bgcolor": "1" - }, - "2,14": { - "contents": "", - "bgcolor": "1" - }, - "2,15": { - "contents": "", - "bgcolor": "1" - }, - "2,16": { - "contents": "", - "bgcolor": "1" - }, - "2,17": { - "contents": "", - "bgcolor": "1" - }, - "2,18": { - "contents": "", - "bgcolor": "1" - }, - "2,19": { - "contents": "", - "bgcolor": "1" - }, - "2,2": { - "contents": "", - "bgcolor": "1" - }, - "2,20": { - "contents": "", - "bgcolor": "1" - }, - "2,21": { - "contents": "", - "bgcolor": "1" - }, - "2,22": { - "contents": "", - "bgcolor": "1" - }, - "2,23": { - "contents": "", - "bgcolor": "1" - }, - "2,24": { - "contents": "", - "bgcolor": "1" - }, - "2,25": { - "contents": "", - "bgcolor": "1" - }, - "2,26": { - "contents": "", - "bgcolor": "1" - }, - "2,27": { - "contents": "", - "bgcolor": "1" - }, - "2,28": { - "contents": "", - "bgcolor": "1" - }, - "2,29": { - "contents": "", - "bgcolor": "1" - }, - "2,3": { - "contents": "", - "bgcolor": "1" - }, - "2,30": { - "contents": "", - "bgcolor": "1" - }, - "2,31": { - "contents": "", - "bgcolor": "1" - }, - "2,32": { - "contents": "", - "bgcolor": "1" - }, - "2,33": { - "contents": "", - "bgcolor": "1" - }, - "2,34": { - "contents": "", - "bgcolor": "1" - }, - "2,35": { - "contents": "", - "bgcolor": "1" - }, - "2,36": { - "contents": "", - "bgcolor": "1" - }, - "2,37": { - "contents": "", - "bgcolor": "1" - }, - "2,38": { - "contents": "", - "bgcolor": "1" - }, - "2,39": { - "contents": "", - "bgcolor": "1" - }, - "2,4": { - "contents": "", - "bgcolor": "1" - }, - "2,40": { - "contents": "", - "bgcolor": "1" - }, - "2,41": { - "contents": "", - "bgcolor": "1" - }, - "2,42": { - "contents": "", - "bgcolor": "1" - }, - "2,43": { - "contents": "", - "bgcolor": "1" - }, - "2,44": { - "contents": "", - "bgcolor": "1" - }, - "2,45": { - "contents": "", - "bgcolor": "1" - }, - "2,46": { - "contents": "", - "bgcolor": "1" - }, - "2,47": { - "contents": "", - "bgcolor": "1" - }, - "2,48": { - "contents": "", - "bgcolor": "1" - }, - "2,49": { - "contents": "", - "bgcolor": "1" - }, - "2,5": { - "contents": "", - "bgcolor": "1" - }, - "2,50": { - "contents": "", - "bgcolor": "1" - }, - "2,51": { - "contents": "", - "bgcolor": "1" - }, - "2,52": { - "contents": "", - "bgcolor": "1" - }, - "2,53": { - "contents": "", - "bgcolor": "1" - }, - "2,54": { - "contents": "", - "bgcolor": "1" - }, - "2,55": { - "contents": "", - "bgcolor": "1" - }, - "2,56": { - "contents": "", - "bgcolor": "1" - }, - "2,57": { - "contents": "", - "bgcolor": "1" - }, - "2,58": { - "contents": "", - "bgcolor": "1" - }, - "2,59": { - "contents": "", - "bgcolor": "1" - }, - "2,6": { - "contents": "", - "bgcolor": "1" - }, - "2,60": { - "contents": "", - "bgcolor": "1" - }, - "2,61": { - "contents": "", - "bgcolor": "1" - }, - "2,62": { - "contents": "", - "bgcolor": "1" - }, - "2,63": { - "contents": "", - "bgcolor": "1" - }, - "2,64": { - "contents": "", - "bgcolor": "1" - }, - "2,65": { - "contents": "", - "bgcolor": "1" - }, - "2,66": { - "contents": "", - "bgcolor": "1" - }, - "2,67": { - "contents": "", - "bgcolor": "1" - }, - "2,68": { - "contents": "", - "bgcolor": "1" - }, - "2,69": { - "contents": "", - "bgcolor": "1" - }, - "2,7": { - "contents": "", - "bgcolor": "1" - }, - "2,70": { - "contents": "", - "bgcolor": "1" - }, - "2,71": { - "contents": "", - "bgcolor": "1" - }, - "2,72": { - "contents": "", - "bgcolor": "1" - }, - "2,73": { - "contents": "", - "bgcolor": "1" - }, - "2,74": { - "contents": "", - "bgcolor": "1" - }, - "2,75": { - "contents": "", - "bgcolor": "1" - }, - "2,76": { - "contents": "", - "bgcolor": "1" - }, - "2,77": { - "contents": "", - "bgcolor": "1" - }, - "2,78": { - "contents": "", - "bgcolor": "1" - }, - "2,79": { - "contents": "", - "bgcolor": "1" - }, - "2,8": { - "contents": "", - "bgcolor": "1" - }, - "2,9": { - "contents": "", - "bgcolor": "1" - }, - "3,0": { - "contents": "", - "bgcolor": "1" - }, - "3,1": { - "contents": "", - "bgcolor": "1" - }, - "3,10": { - "contents": "", - "bgcolor": "1" - }, - "3,11": { - "contents": "", - "bgcolor": "1" - }, - "3,12": { - "contents": "", - "bgcolor": "1" - }, - "3,13": { - "contents": "", - "bgcolor": "1" - }, - "3,14": { - "contents": "", - "bgcolor": "1" - }, - "3,15": { - "contents": "", - "bgcolor": "1" - }, - "3,16": { - "contents": "", - "bgcolor": "1" - }, - "3,17": { - "contents": "", - "bgcolor": "1" - }, - "3,18": { - "contents": "", - "bgcolor": "1" - }, - "3,19": { - "contents": "", - "bgcolor": "1" - }, - "3,2": { - "contents": "", - "bgcolor": "1" - }, - "3,20": { - "contents": "", - "bgcolor": "1" - }, - "3,21": { - "contents": "", - "bgcolor": "1" - }, - "3,22": { - "contents": "", - "bgcolor": "1" - }, - "3,23": { - "contents": "", - "bgcolor": "1" - }, - "3,24": { - "contents": "", - "bgcolor": "1" - }, - "3,25": { - "contents": "", - "bgcolor": "1" - }, - "3,26": { - "contents": "", - "bgcolor": "1" - }, - "3,27": { - "contents": "", - "bgcolor": "1" - }, - "3,28": { - "contents": "", - "bgcolor": "1" - }, - "3,29": { - "contents": "", - "bgcolor": "1" - }, - "3,3": { - "contents": "", - "bgcolor": "1" - }, - "3,30": { - "contents": "", - "bgcolor": "1" - }, - "3,31": { - "contents": "", - "bgcolor": "1" - }, - "3,32": { - "contents": "", - "bgcolor": "1" - }, - "3,33": { - "contents": "", - "bgcolor": "1" - }, - "3,34": { - "contents": "", - "bgcolor": "1" - }, - "3,35": { - "contents": "", - "bgcolor": "1" - }, - "3,36": { - "contents": "", - "bgcolor": "1" - }, - "3,37": { - "contents": "", - "bgcolor": "1" - }, - "3,38": { - "contents": "", - "bgcolor": "1" - }, - "3,39": { - "contents": "", - "bgcolor": "1" - }, - "3,4": { - "contents": "", - "bgcolor": "1" - }, - "3,40": { - "contents": "", - "bgcolor": "1" - }, - "3,41": { - "contents": "", - "bgcolor": "1" - }, - "3,42": { - "contents": "", - "bgcolor": "1" - }, - "3,43": { - "contents": "", - "bgcolor": "1" - }, - "3,44": { - "contents": "", - "bgcolor": "1" - }, - "3,45": { - "contents": "", - "bgcolor": "1" - }, - "3,46": { - "contents": "", - "bgcolor": "1" - }, - "3,47": { - "contents": "", - "bgcolor": "1" - }, - "3,48": { - "contents": "", - "bgcolor": "1" - }, - "3,49": { - "contents": "", - "bgcolor": "1" - }, - "3,5": { - "contents": "", - "bgcolor": "1" - }, - "3,50": { - "contents": "", - "bgcolor": "1" - }, - "3,51": { - "contents": "", - "bgcolor": "1" - }, - "3,52": { - "contents": "", - "bgcolor": "1" - }, - "3,53": { - "contents": "", - "bgcolor": "1" - }, - "3,54": { - "contents": "", - "bgcolor": "1" - }, - "3,55": { - "contents": "", - "bgcolor": "1" - }, - "3,56": { - "contents": "", - "bgcolor": "1" - }, - "3,57": { - "contents": "", - "bgcolor": "1" - }, - "3,58": { - "contents": "", - "bgcolor": "1" - }, - "3,59": { - "contents": "", - "bgcolor": "1" - }, - "3,6": { - "contents": "", - "bgcolor": "1" - }, - "3,60": { - "contents": "", - "bgcolor": "1" - }, - "3,61": { - "contents": "", - "bgcolor": "1" - }, - "3,62": { - "contents": "", - "bgcolor": "1" - }, - "3,63": { - "contents": "", - "bgcolor": "1" - }, - "3,64": { - "contents": "", - "bgcolor": "1" - }, - "3,65": { - "contents": "", - "bgcolor": "1" - }, - "3,66": { - "contents": "", - "bgcolor": "1" - }, - "3,67": { - "contents": "", - "bgcolor": "1" - }, - "3,68": { - "contents": "", - "bgcolor": "1" - }, - "3,69": { - "contents": "", - "bgcolor": "1" - }, - "3,7": { - "contents": "", - "bgcolor": "1" - }, - "3,70": { - "contents": "", - "bgcolor": "1" - }, - "3,71": { - "contents": "", - "bgcolor": "1" - }, - "3,72": { - "contents": "", - "bgcolor": "1" - }, - "3,73": { - "contents": "", - "bgcolor": "1" - }, - "3,74": { - "contents": "", - "bgcolor": "1" - }, - "3,75": { - "contents": "", - "bgcolor": "1" - }, - "3,76": { - "contents": "", - "bgcolor": "1" - }, - "3,77": { - "contents": "", - "bgcolor": "1" - }, - "3,78": { - "contents": "", - "bgcolor": "1" - }, - "3,79": { - "contents": "", - "bgcolor": "1" - }, - "3,8": { - "contents": "", - "bgcolor": "1" - }, - "3,9": { - "contents": "", - "bgcolor": "1" - }, - "4,0": { - "contents": "", - "bgcolor": "1" - }, - "4,1": { - "contents": "", - "bgcolor": "1" - }, - "4,2": { - "contents": "", - "bgcolor": "1" - }, - "4,3": { - "contents": "", - "bgcolor": "1" - }, - "4,4": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/19.typescript deleted file mode 100644 index b4dfc54dbcec5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/19.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/2.json b/crates/turborepo-vt100/tests/data/fixtures/ed/2.json deleted file mode 100644 index fe26558462bd5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/2.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n ba", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/2.typescript deleted file mode 100644 index 59dad8389ea23..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/20.json b/crates/turborepo-vt100/tests/data/fixtures/ed/20.json deleted file mode 100644 index 2b060efecfe66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/20.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/20.typescript deleted file mode 100644 index 8adc44f0bdefe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/20.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/21.json b/crates/turborepo-vt100/tests/data/fixtures/ed/21.json deleted file mode 100644 index 07070be316708..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/21.json +++ /dev/null @@ -1,7689 +0,0 @@ -{ - "contents": "", - "cells": { - "0,0": { - "contents": "", - "bgcolor": "1" - }, - "0,1": { - "contents": "", - "bgcolor": "1" - }, - "0,10": { - "contents": "", - "bgcolor": "1" - }, - "0,11": { - "contents": "", - "bgcolor": "1" - }, - "0,12": { - "contents": "", - "bgcolor": "1" - }, - "0,13": { - "contents": "", - "bgcolor": "1" - }, - "0,14": { - "contents": "", - "bgcolor": "1" - }, - "0,15": { - "contents": "", - "bgcolor": "1" - }, - "0,16": { - "contents": "", - "bgcolor": "1" - }, - "0,17": { - "contents": "", - "bgcolor": "1" - }, - "0,18": { - "contents": "", - "bgcolor": "1" - }, - "0,19": { - "contents": "", - "bgcolor": "1" - }, - "0,2": { - "contents": "", - "bgcolor": "1" - }, - "0,20": { - "contents": "", - "bgcolor": "1" - }, - "0,21": { - "contents": "", - "bgcolor": "1" - }, - "0,22": { - "contents": "", - "bgcolor": "1" - }, - "0,23": { - "contents": "", - "bgcolor": "1" - }, - "0,24": { - "contents": "", - "bgcolor": "1" - }, - "0,25": { - "contents": "", - "bgcolor": "1" - }, - "0,26": { - "contents": "", - "bgcolor": "1" - }, - "0,27": { - "contents": "", - "bgcolor": "1" - }, - "0,28": { - "contents": "", - "bgcolor": "1" - }, - "0,29": { - "contents": "", - "bgcolor": "1" - }, - "0,3": { - "contents": "", - "bgcolor": "1" - }, - "0,30": { - "contents": "", - "bgcolor": "1" - }, - "0,31": { - "contents": "", - "bgcolor": "1" - }, - "0,32": { - "contents": "", - "bgcolor": "1" - }, - "0,33": { - "contents": "", - "bgcolor": "1" - }, - "0,34": { - "contents": "", - "bgcolor": "1" - }, - "0,35": { - "contents": "", - "bgcolor": "1" - }, - "0,36": { - "contents": "", - "bgcolor": "1" - }, - "0,37": { - "contents": "", - "bgcolor": "1" - }, - "0,38": { - "contents": "", - "bgcolor": "1" - }, - "0,39": { - "contents": "", - "bgcolor": "1" - }, - "0,4": { - "contents": "", - "bgcolor": "1" - }, - "0,40": { - "contents": "", - "bgcolor": "1" - }, - "0,41": { - "contents": "", - "bgcolor": "1" - }, - "0,42": { - "contents": "", - "bgcolor": "1" - }, - "0,43": { - "contents": "", - "bgcolor": "1" - }, - "0,44": { - "contents": "", - "bgcolor": "1" - }, - "0,45": { - "contents": "", - "bgcolor": "1" - }, - "0,46": { - "contents": "", - "bgcolor": "1" - }, - "0,47": { - "contents": "", - "bgcolor": "1" - }, - "0,48": { - "contents": "", - "bgcolor": "1" - }, - "0,49": { - "contents": "", - "bgcolor": "1" - }, - "0,5": { - "contents": "", - "bgcolor": "1" - }, - "0,50": { - "contents": "", - "bgcolor": "1" - }, - "0,51": { - "contents": "", - "bgcolor": "1" - }, - "0,52": { - "contents": "", - "bgcolor": "1" - }, - "0,53": { - "contents": "", - "bgcolor": "1" - }, - "0,54": { - "contents": "", - "bgcolor": "1" - }, - "0,55": { - "contents": "", - "bgcolor": "1" - }, - "0,56": { - "contents": "", - "bgcolor": "1" - }, - "0,57": { - "contents": "", - "bgcolor": "1" - }, - "0,58": { - "contents": "", - "bgcolor": "1" - }, - "0,59": { - "contents": "", - "bgcolor": "1" - }, - "0,6": { - "contents": "", - "bgcolor": "1" - }, - "0,60": { - "contents": "", - "bgcolor": "1" - }, - "0,61": { - "contents": "", - "bgcolor": "1" - }, - "0,62": { - "contents": "", - "bgcolor": "1" - }, - "0,63": { - "contents": "", - "bgcolor": "1" - }, - "0,64": { - "contents": "", - "bgcolor": "1" - }, - "0,65": { - "contents": "", - "bgcolor": "1" - }, - "0,66": { - "contents": "", - "bgcolor": "1" - }, - "0,67": { - "contents": "", - "bgcolor": "1" - }, - "0,68": { - "contents": "", - "bgcolor": "1" - }, - "0,69": { - "contents": "", - "bgcolor": "1" - }, - "0,7": { - "contents": "", - "bgcolor": "1" - }, - "0,70": { - "contents": "", - "bgcolor": "1" - }, - "0,71": { - "contents": "", - "bgcolor": "1" - }, - "0,72": { - "contents": "", - "bgcolor": "1" - }, - "0,73": { - "contents": "", - "bgcolor": "1" - }, - "0,74": { - "contents": "", - "bgcolor": "1" - }, - "0,75": { - "contents": "", - "bgcolor": "1" - }, - "0,76": { - "contents": "", - "bgcolor": "1" - }, - "0,77": { - "contents": "", - "bgcolor": "1" - }, - "0,78": { - "contents": "", - "bgcolor": "1" - }, - "0,79": { - "contents": "", - "bgcolor": "1" - }, - "0,8": { - "contents": "", - "bgcolor": "1" - }, - "0,9": { - "contents": "", - "bgcolor": "1" - }, - "1,0": { - "contents": "", - "bgcolor": "1" - }, - "1,1": { - "contents": "", - "bgcolor": "1" - }, - "1,10": { - "contents": "", - "bgcolor": "1" - }, - "1,11": { - "contents": "", - "bgcolor": "1" - }, - "1,12": { - "contents": "", - "bgcolor": "1" - }, - "1,13": { - "contents": "", - "bgcolor": "1" - }, - "1,14": { - "contents": "", - "bgcolor": "1" - }, - "1,15": { - "contents": "", - "bgcolor": "1" - }, - "1,16": { - "contents": "", - "bgcolor": "1" - }, - "1,17": { - "contents": "", - "bgcolor": "1" - }, - "1,18": { - "contents": "", - "bgcolor": "1" - }, - "1,19": { - "contents": "", - "bgcolor": "1" - }, - "1,2": { - "contents": "", - "bgcolor": "1" - }, - "1,20": { - "contents": "", - "bgcolor": "1" - }, - "1,21": { - "contents": "", - "bgcolor": "1" - }, - "1,22": { - "contents": "", - "bgcolor": "1" - }, - "1,23": { - "contents": "", - "bgcolor": "1" - }, - "1,24": { - "contents": "", - "bgcolor": "1" - }, - "1,25": { - "contents": "", - "bgcolor": "1" - }, - "1,26": { - "contents": "", - "bgcolor": "1" - }, - "1,27": { - "contents": "", - "bgcolor": "1" - }, - "1,28": { - "contents": "", - "bgcolor": "1" - }, - "1,29": { - "contents": "", - "bgcolor": "1" - }, - "1,3": { - "contents": "", - "bgcolor": "1" - }, - "1,30": { - "contents": "", - "bgcolor": "1" - }, - "1,31": { - "contents": "", - "bgcolor": "1" - }, - "1,32": { - "contents": "", - "bgcolor": "1" - }, - "1,33": { - "contents": "", - "bgcolor": "1" - }, - "1,34": { - "contents": "", - "bgcolor": "1" - }, - "1,35": { - "contents": "", - "bgcolor": "1" - }, - "1,36": { - "contents": "", - "bgcolor": "1" - }, - "1,37": { - "contents": "", - "bgcolor": "1" - }, - "1,38": { - "contents": "", - "bgcolor": "1" - }, - "1,39": { - "contents": "", - "bgcolor": "1" - }, - "1,4": { - "contents": "", - "bgcolor": "1" - }, - "1,40": { - "contents": "", - "bgcolor": "1" - }, - "1,41": { - "contents": "", - "bgcolor": "1" - }, - "1,42": { - "contents": "", - "bgcolor": "1" - }, - "1,43": { - "contents": "", - "bgcolor": "1" - }, - "1,44": { - "contents": "", - "bgcolor": "1" - }, - "1,45": { - "contents": "", - "bgcolor": "1" - }, - "1,46": { - "contents": "", - "bgcolor": "1" - }, - "1,47": { - "contents": "", - "bgcolor": "1" - }, - "1,48": { - "contents": "", - "bgcolor": "1" - }, - "1,49": { - "contents": "", - "bgcolor": "1" - }, - "1,5": { - "contents": "", - "bgcolor": "1" - }, - "1,50": { - "contents": "", - "bgcolor": "1" - }, - "1,51": { - "contents": "", - "bgcolor": "1" - }, - "1,52": { - "contents": "", - "bgcolor": "1" - }, - "1,53": { - "contents": "", - "bgcolor": "1" - }, - "1,54": { - "contents": "", - "bgcolor": "1" - }, - "1,55": { - "contents": "", - "bgcolor": "1" - }, - "1,56": { - "contents": "", - "bgcolor": "1" - }, - "1,57": { - "contents": "", - "bgcolor": "1" - }, - "1,58": { - "contents": "", - "bgcolor": "1" - }, - "1,59": { - "contents": "", - "bgcolor": "1" - }, - "1,6": { - "contents": "", - "bgcolor": "1" - }, - "1,60": { - "contents": "", - "bgcolor": "1" - }, - "1,61": { - "contents": "", - "bgcolor": "1" - }, - "1,62": { - "contents": "", - "bgcolor": "1" - }, - "1,63": { - "contents": "", - "bgcolor": "1" - }, - "1,64": { - "contents": "", - "bgcolor": "1" - }, - "1,65": { - "contents": "", - "bgcolor": "1" - }, - "1,66": { - "contents": "", - "bgcolor": "1" - }, - "1,67": { - "contents": "", - "bgcolor": "1" - }, - "1,68": { - "contents": "", - "bgcolor": "1" - }, - "1,69": { - "contents": "", - "bgcolor": "1" - }, - "1,7": { - "contents": "", - "bgcolor": "1" - }, - "1,70": { - "contents": "", - "bgcolor": "1" - }, - "1,71": { - "contents": "", - "bgcolor": "1" - }, - "1,72": { - "contents": "", - "bgcolor": "1" - }, - "1,73": { - "contents": "", - "bgcolor": "1" - }, - "1,74": { - "contents": "", - "bgcolor": "1" - }, - "1,75": { - "contents": "", - "bgcolor": "1" - }, - "1,76": { - "contents": "", - "bgcolor": "1" - }, - "1,77": { - "contents": "", - "bgcolor": "1" - }, - "1,78": { - "contents": "", - "bgcolor": "1" - }, - "1,79": { - "contents": "", - "bgcolor": "1" - }, - "1,8": { - "contents": "", - "bgcolor": "1" - }, - "1,9": { - "contents": "", - "bgcolor": "1" - }, - "10,0": { - "contents": "", - "bgcolor": "1" - }, - "10,1": { - "contents": "", - "bgcolor": "1" - }, - "10,10": { - "contents": "", - "bgcolor": "1" - }, - "10,11": { - "contents": "", - "bgcolor": "1" - }, - "10,12": { - "contents": "", - "bgcolor": "1" - }, - "10,13": { - "contents": "", - "bgcolor": "1" - }, - "10,14": { - "contents": "", - "bgcolor": "1" - }, - "10,15": { - "contents": "", - "bgcolor": "1" - }, - "10,16": { - "contents": "", - "bgcolor": "1" - }, - "10,17": { - "contents": "", - "bgcolor": "1" - }, - "10,18": { - "contents": "", - "bgcolor": "1" - }, - "10,19": { - "contents": "", - "bgcolor": "1" - }, - "10,2": { - "contents": "", - "bgcolor": "1" - }, - "10,20": { - "contents": "", - "bgcolor": "1" - }, - "10,21": { - "contents": "", - "bgcolor": "1" - }, - "10,22": { - "contents": "", - "bgcolor": "1" - }, - "10,23": { - "contents": "", - "bgcolor": "1" - }, - "10,24": { - "contents": "", - "bgcolor": "1" - }, - "10,25": { - "contents": "", - "bgcolor": "1" - }, - "10,26": { - "contents": "", - "bgcolor": "1" - }, - "10,27": { - "contents": "", - "bgcolor": "1" - }, - "10,28": { - "contents": "", - "bgcolor": "1" - }, - "10,29": { - "contents": "", - "bgcolor": "1" - }, - "10,3": { - "contents": "", - "bgcolor": "1" - }, - "10,30": { - "contents": "", - "bgcolor": "1" - }, - "10,31": { - "contents": "", - "bgcolor": "1" - }, - "10,32": { - "contents": "", - "bgcolor": "1" - }, - "10,33": { - "contents": "", - "bgcolor": "1" - }, - "10,34": { - "contents": "", - "bgcolor": "1" - }, - "10,35": { - "contents": "", - "bgcolor": "1" - }, - "10,36": { - "contents": "", - "bgcolor": "1" - }, - "10,37": { - "contents": "", - "bgcolor": "1" - }, - "10,38": { - "contents": "", - "bgcolor": "1" - }, - "10,39": { - "contents": "", - "bgcolor": "1" - }, - "10,4": { - "contents": "", - "bgcolor": "1" - }, - "10,40": { - "contents": "", - "bgcolor": "1" - }, - "10,41": { - "contents": "", - "bgcolor": "1" - }, - "10,42": { - "contents": "", - "bgcolor": "1" - }, - "10,43": { - "contents": "", - "bgcolor": "1" - }, - "10,44": { - "contents": "", - "bgcolor": "1" - }, - "10,45": { - "contents": "", - "bgcolor": "1" - }, - "10,46": { - "contents": "", - "bgcolor": "1" - }, - "10,47": { - "contents": "", - "bgcolor": "1" - }, - "10,48": { - "contents": "", - "bgcolor": "1" - }, - "10,49": { - "contents": "", - "bgcolor": "1" - }, - "10,5": { - "contents": "", - "bgcolor": "1" - }, - "10,50": { - "contents": "", - "bgcolor": "1" - }, - "10,51": { - "contents": "", - "bgcolor": "1" - }, - "10,52": { - "contents": "", - "bgcolor": "1" - }, - "10,53": { - "contents": "", - "bgcolor": "1" - }, - "10,54": { - "contents": "", - "bgcolor": "1" - }, - "10,55": { - "contents": "", - "bgcolor": "1" - }, - "10,56": { - "contents": "", - "bgcolor": "1" - }, - "10,57": { - "contents": "", - "bgcolor": "1" - }, - "10,58": { - "contents": "", - "bgcolor": "1" - }, - "10,59": { - "contents": "", - "bgcolor": "1" - }, - "10,6": { - "contents": "", - "bgcolor": "1" - }, - "10,60": { - "contents": "", - "bgcolor": "1" - }, - "10,61": { - "contents": "", - "bgcolor": "1" - }, - "10,62": { - "contents": "", - "bgcolor": "1" - }, - "10,63": { - "contents": "", - "bgcolor": "1" - }, - "10,64": { - "contents": "", - "bgcolor": "1" - }, - "10,65": { - "contents": "", - "bgcolor": "1" - }, - "10,66": { - "contents": "", - "bgcolor": "1" - }, - "10,67": { - "contents": "", - "bgcolor": "1" - }, - "10,68": { - "contents": "", - "bgcolor": "1" - }, - "10,69": { - "contents": "", - "bgcolor": "1" - }, - "10,7": { - "contents": "", - "bgcolor": "1" - }, - "10,70": { - "contents": "", - "bgcolor": "1" - }, - "10,71": { - "contents": "", - "bgcolor": "1" - }, - "10,72": { - "contents": "", - "bgcolor": "1" - }, - "10,73": { - "contents": "", - "bgcolor": "1" - }, - "10,74": { - "contents": "", - "bgcolor": "1" - }, - "10,75": { - "contents": "", - "bgcolor": "1" - }, - "10,76": { - "contents": "", - "bgcolor": "1" - }, - "10,77": { - "contents": "", - "bgcolor": "1" - }, - "10,78": { - "contents": "", - "bgcolor": "1" - }, - "10,79": { - "contents": "", - "bgcolor": "1" - }, - "10,8": { - "contents": "", - "bgcolor": "1" - }, - "10,9": { - "contents": "", - "bgcolor": "1" - }, - "11,0": { - "contents": "", - "bgcolor": "1" - }, - "11,1": { - "contents": "", - "bgcolor": "1" - }, - "11,10": { - "contents": "", - "bgcolor": "1" - }, - "11,11": { - "contents": "", - "bgcolor": "1" - }, - "11,12": { - "contents": "", - "bgcolor": "1" - }, - "11,13": { - "contents": "", - "bgcolor": "1" - }, - "11,14": { - "contents": "", - "bgcolor": "1" - }, - "11,15": { - "contents": "", - "bgcolor": "1" - }, - "11,16": { - "contents": "", - "bgcolor": "1" - }, - "11,17": { - "contents": "", - "bgcolor": "1" - }, - "11,18": { - "contents": "", - "bgcolor": "1" - }, - "11,19": { - "contents": "", - "bgcolor": "1" - }, - "11,2": { - "contents": "", - "bgcolor": "1" - }, - "11,20": { - "contents": "", - "bgcolor": "1" - }, - "11,21": { - "contents": "", - "bgcolor": "1" - }, - "11,22": { - "contents": "", - "bgcolor": "1" - }, - "11,23": { - "contents": "", - "bgcolor": "1" - }, - "11,24": { - "contents": "", - "bgcolor": "1" - }, - "11,25": { - "contents": "", - "bgcolor": "1" - }, - "11,26": { - "contents": "", - "bgcolor": "1" - }, - "11,27": { - "contents": "", - "bgcolor": "1" - }, - "11,28": { - "contents": "", - "bgcolor": "1" - }, - "11,29": { - "contents": "", - "bgcolor": "1" - }, - "11,3": { - "contents": "", - "bgcolor": "1" - }, - "11,30": { - "contents": "", - "bgcolor": "1" - }, - "11,31": { - "contents": "", - "bgcolor": "1" - }, - "11,32": { - "contents": "", - "bgcolor": "1" - }, - "11,33": { - "contents": "", - "bgcolor": "1" - }, - "11,34": { - "contents": "", - "bgcolor": "1" - }, - "11,35": { - "contents": "", - "bgcolor": "1" - }, - "11,36": { - "contents": "", - "bgcolor": "1" - }, - "11,37": { - "contents": "", - "bgcolor": "1" - }, - "11,38": { - "contents": "", - "bgcolor": "1" - }, - "11,39": { - "contents": "", - "bgcolor": "1" - }, - "11,4": { - "contents": "", - "bgcolor": "1" - }, - "11,40": { - "contents": "", - "bgcolor": "1" - }, - "11,41": { - "contents": "", - "bgcolor": "1" - }, - "11,42": { - "contents": "", - "bgcolor": "1" - }, - "11,43": { - "contents": "", - "bgcolor": "1" - }, - "11,44": { - "contents": "", - "bgcolor": "1" - }, - "11,45": { - "contents": "", - "bgcolor": "1" - }, - "11,46": { - "contents": "", - "bgcolor": "1" - }, - "11,47": { - "contents": "", - "bgcolor": "1" - }, - "11,48": { - "contents": "", - "bgcolor": "1" - }, - "11,49": { - "contents": "", - "bgcolor": "1" - }, - "11,5": { - "contents": "", - "bgcolor": "1" - }, - "11,50": { - "contents": "", - "bgcolor": "1" - }, - "11,51": { - "contents": "", - "bgcolor": "1" - }, - "11,52": { - "contents": "", - "bgcolor": "1" - }, - "11,53": { - "contents": "", - "bgcolor": "1" - }, - "11,54": { - "contents": "", - "bgcolor": "1" - }, - "11,55": { - "contents": "", - "bgcolor": "1" - }, - "11,56": { - "contents": "", - "bgcolor": "1" - }, - "11,57": { - "contents": "", - "bgcolor": "1" - }, - "11,58": { - "contents": "", - "bgcolor": "1" - }, - "11,59": { - "contents": "", - "bgcolor": "1" - }, - "11,6": { - "contents": "", - "bgcolor": "1" - }, - "11,60": { - "contents": "", - "bgcolor": "1" - }, - "11,61": { - "contents": "", - "bgcolor": "1" - }, - "11,62": { - "contents": "", - "bgcolor": "1" - }, - "11,63": { - "contents": "", - "bgcolor": "1" - }, - "11,64": { - "contents": "", - "bgcolor": "1" - }, - "11,65": { - "contents": "", - "bgcolor": "1" - }, - "11,66": { - "contents": "", - "bgcolor": "1" - }, - "11,67": { - "contents": "", - "bgcolor": "1" - }, - "11,68": { - "contents": "", - "bgcolor": "1" - }, - "11,69": { - "contents": "", - "bgcolor": "1" - }, - "11,7": { - "contents": "", - "bgcolor": "1" - }, - "11,70": { - "contents": "", - "bgcolor": "1" - }, - "11,71": { - "contents": "", - "bgcolor": "1" - }, - "11,72": { - "contents": "", - "bgcolor": "1" - }, - "11,73": { - "contents": "", - "bgcolor": "1" - }, - "11,74": { - "contents": "", - "bgcolor": "1" - }, - "11,75": { - "contents": "", - "bgcolor": "1" - }, - "11,76": { - "contents": "", - "bgcolor": "1" - }, - "11,77": { - "contents": "", - "bgcolor": "1" - }, - "11,78": { - "contents": "", - "bgcolor": "1" - }, - "11,79": { - "contents": "", - "bgcolor": "1" - }, - "11,8": { - "contents": "", - "bgcolor": "1" - }, - "11,9": { - "contents": "", - "bgcolor": "1" - }, - "12,0": { - "contents": "", - "bgcolor": "1" - }, - "12,1": { - "contents": "", - "bgcolor": "1" - }, - "12,10": { - "contents": "", - "bgcolor": "1" - }, - "12,11": { - "contents": "", - "bgcolor": "1" - }, - "12,12": { - "contents": "", - "bgcolor": "1" - }, - "12,13": { - "contents": "", - "bgcolor": "1" - }, - "12,14": { - "contents": "", - "bgcolor": "1" - }, - "12,15": { - "contents": "", - "bgcolor": "1" - }, - "12,16": { - "contents": "", - "bgcolor": "1" - }, - "12,17": { - "contents": "", - "bgcolor": "1" - }, - "12,18": { - "contents": "", - "bgcolor": "1" - }, - "12,19": { - "contents": "", - "bgcolor": "1" - }, - "12,2": { - "contents": "", - "bgcolor": "1" - }, - "12,20": { - "contents": "", - "bgcolor": "1" - }, - "12,21": { - "contents": "", - "bgcolor": "1" - }, - "12,22": { - "contents": "", - "bgcolor": "1" - }, - "12,23": { - "contents": "", - "bgcolor": "1" - }, - "12,24": { - "contents": "", - "bgcolor": "1" - }, - "12,25": { - "contents": "", - "bgcolor": "1" - }, - "12,26": { - "contents": "", - "bgcolor": "1" - }, - "12,27": { - "contents": "", - "bgcolor": "1" - }, - "12,28": { - "contents": "", - "bgcolor": "1" - }, - "12,29": { - "contents": "", - "bgcolor": "1" - }, - "12,3": { - "contents": "", - "bgcolor": "1" - }, - "12,30": { - "contents": "", - "bgcolor": "1" - }, - "12,31": { - "contents": "", - "bgcolor": "1" - }, - "12,32": { - "contents": "", - "bgcolor": "1" - }, - "12,33": { - "contents": "", - "bgcolor": "1" - }, - "12,34": { - "contents": "", - "bgcolor": "1" - }, - "12,35": { - "contents": "", - "bgcolor": "1" - }, - "12,36": { - "contents": "", - "bgcolor": "1" - }, - "12,37": { - "contents": "", - "bgcolor": "1" - }, - "12,38": { - "contents": "", - "bgcolor": "1" - }, - "12,39": { - "contents": "", - "bgcolor": "1" - }, - "12,4": { - "contents": "", - "bgcolor": "1" - }, - "12,40": { - "contents": "", - "bgcolor": "1" - }, - "12,41": { - "contents": "", - "bgcolor": "1" - }, - "12,42": { - "contents": "", - "bgcolor": "1" - }, - "12,43": { - "contents": "", - "bgcolor": "1" - }, - "12,44": { - "contents": "", - "bgcolor": "1" - }, - "12,45": { - "contents": "", - "bgcolor": "1" - }, - "12,46": { - "contents": "", - "bgcolor": "1" - }, - "12,47": { - "contents": "", - "bgcolor": "1" - }, - "12,48": { - "contents": "", - "bgcolor": "1" - }, - "12,49": { - "contents": "", - "bgcolor": "1" - }, - "12,5": { - "contents": "", - "bgcolor": "1" - }, - "12,50": { - "contents": "", - "bgcolor": "1" - }, - "12,51": { - "contents": "", - "bgcolor": "1" - }, - "12,52": { - "contents": "", - "bgcolor": "1" - }, - "12,53": { - "contents": "", - "bgcolor": "1" - }, - "12,54": { - "contents": "", - "bgcolor": "1" - }, - "12,55": { - "contents": "", - "bgcolor": "1" - }, - "12,56": { - "contents": "", - "bgcolor": "1" - }, - "12,57": { - "contents": "", - "bgcolor": "1" - }, - "12,58": { - "contents": "", - "bgcolor": "1" - }, - "12,59": { - "contents": "", - "bgcolor": "1" - }, - "12,6": { - "contents": "", - "bgcolor": "1" - }, - "12,60": { - "contents": "", - "bgcolor": "1" - }, - "12,61": { - "contents": "", - "bgcolor": "1" - }, - "12,62": { - "contents": "", - "bgcolor": "1" - }, - "12,63": { - "contents": "", - "bgcolor": "1" - }, - "12,64": { - "contents": "", - "bgcolor": "1" - }, - "12,65": { - "contents": "", - "bgcolor": "1" - }, - "12,66": { - "contents": "", - "bgcolor": "1" - }, - "12,67": { - "contents": "", - "bgcolor": "1" - }, - "12,68": { - "contents": "", - "bgcolor": "1" - }, - "12,69": { - "contents": "", - "bgcolor": "1" - }, - "12,7": { - "contents": "", - "bgcolor": "1" - }, - "12,70": { - "contents": "", - "bgcolor": "1" - }, - "12,71": { - "contents": "", - "bgcolor": "1" - }, - "12,72": { - "contents": "", - "bgcolor": "1" - }, - "12,73": { - "contents": "", - "bgcolor": "1" - }, - "12,74": { - "contents": "", - "bgcolor": "1" - }, - "12,75": { - "contents": "", - "bgcolor": "1" - }, - "12,76": { - "contents": "", - "bgcolor": "1" - }, - "12,77": { - "contents": "", - "bgcolor": "1" - }, - "12,78": { - "contents": "", - "bgcolor": "1" - }, - "12,79": { - "contents": "", - "bgcolor": "1" - }, - "12,8": { - "contents": "", - "bgcolor": "1" - }, - "12,9": { - "contents": "", - "bgcolor": "1" - }, - "13,0": { - "contents": "", - "bgcolor": "1" - }, - "13,1": { - "contents": "", - "bgcolor": "1" - }, - "13,10": { - "contents": "", - "bgcolor": "1" - }, - "13,11": { - "contents": "", - "bgcolor": "1" - }, - "13,12": { - "contents": "", - "bgcolor": "1" - }, - "13,13": { - "contents": "", - "bgcolor": "1" - }, - "13,14": { - "contents": "", - "bgcolor": "1" - }, - "13,15": { - "contents": "", - "bgcolor": "1" - }, - "13,16": { - "contents": "", - "bgcolor": "1" - }, - "13,17": { - "contents": "", - "bgcolor": "1" - }, - "13,18": { - "contents": "", - "bgcolor": "1" - }, - "13,19": { - "contents": "", - "bgcolor": "1" - }, - "13,2": { - "contents": "", - "bgcolor": "1" - }, - "13,20": { - "contents": "", - "bgcolor": "1" - }, - "13,21": { - "contents": "", - "bgcolor": "1" - }, - "13,22": { - "contents": "", - "bgcolor": "1" - }, - "13,23": { - "contents": "", - "bgcolor": "1" - }, - "13,24": { - "contents": "", - "bgcolor": "1" - }, - "13,25": { - "contents": "", - "bgcolor": "1" - }, - "13,26": { - "contents": "", - "bgcolor": "1" - }, - "13,27": { - "contents": "", - "bgcolor": "1" - }, - "13,28": { - "contents": "", - "bgcolor": "1" - }, - "13,29": { - "contents": "", - "bgcolor": "1" - }, - "13,3": { - "contents": "", - "bgcolor": "1" - }, - "13,30": { - "contents": "", - "bgcolor": "1" - }, - "13,31": { - "contents": "", - "bgcolor": "1" - }, - "13,32": { - "contents": "", - "bgcolor": "1" - }, - "13,33": { - "contents": "", - "bgcolor": "1" - }, - "13,34": { - "contents": "", - "bgcolor": "1" - }, - "13,35": { - "contents": "", - "bgcolor": "1" - }, - "13,36": { - "contents": "", - "bgcolor": "1" - }, - "13,37": { - "contents": "", - "bgcolor": "1" - }, - "13,38": { - "contents": "", - "bgcolor": "1" - }, - "13,39": { - "contents": "", - "bgcolor": "1" - }, - "13,4": { - "contents": "", - "bgcolor": "1" - }, - "13,40": { - "contents": "", - "bgcolor": "1" - }, - "13,41": { - "contents": "", - "bgcolor": "1" - }, - "13,42": { - "contents": "", - "bgcolor": "1" - }, - "13,43": { - "contents": "", - "bgcolor": "1" - }, - "13,44": { - "contents": "", - "bgcolor": "1" - }, - "13,45": { - "contents": "", - "bgcolor": "1" - }, - "13,46": { - "contents": "", - "bgcolor": "1" - }, - "13,47": { - "contents": "", - "bgcolor": "1" - }, - "13,48": { - "contents": "", - "bgcolor": "1" - }, - "13,49": { - "contents": "", - "bgcolor": "1" - }, - "13,5": { - "contents": "", - "bgcolor": "1" - }, - "13,50": { - "contents": "", - "bgcolor": "1" - }, - "13,51": { - "contents": "", - "bgcolor": "1" - }, - "13,52": { - "contents": "", - "bgcolor": "1" - }, - "13,53": { - "contents": "", - "bgcolor": "1" - }, - "13,54": { - "contents": "", - "bgcolor": "1" - }, - "13,55": { - "contents": "", - "bgcolor": "1" - }, - "13,56": { - "contents": "", - "bgcolor": "1" - }, - "13,57": { - "contents": "", - "bgcolor": "1" - }, - "13,58": { - "contents": "", - "bgcolor": "1" - }, - "13,59": { - "contents": "", - "bgcolor": "1" - }, - "13,6": { - "contents": "", - "bgcolor": "1" - }, - "13,60": { - "contents": "", - "bgcolor": "1" - }, - "13,61": { - "contents": "", - "bgcolor": "1" - }, - "13,62": { - "contents": "", - "bgcolor": "1" - }, - "13,63": { - "contents": "", - "bgcolor": "1" - }, - "13,64": { - "contents": "", - "bgcolor": "1" - }, - "13,65": { - "contents": "", - "bgcolor": "1" - }, - "13,66": { - "contents": "", - "bgcolor": "1" - }, - "13,67": { - "contents": "", - "bgcolor": "1" - }, - "13,68": { - "contents": "", - "bgcolor": "1" - }, - "13,69": { - "contents": "", - "bgcolor": "1" - }, - "13,7": { - "contents": "", - "bgcolor": "1" - }, - "13,70": { - "contents": "", - "bgcolor": "1" - }, - "13,71": { - "contents": "", - "bgcolor": "1" - }, - "13,72": { - "contents": "", - "bgcolor": "1" - }, - "13,73": { - "contents": "", - "bgcolor": "1" - }, - "13,74": { - "contents": "", - "bgcolor": "1" - }, - "13,75": { - "contents": "", - "bgcolor": "1" - }, - "13,76": { - "contents": "", - "bgcolor": "1" - }, - "13,77": { - "contents": "", - "bgcolor": "1" - }, - "13,78": { - "contents": "", - "bgcolor": "1" - }, - "13,79": { - "contents": "", - "bgcolor": "1" - }, - "13,8": { - "contents": "", - "bgcolor": "1" - }, - "13,9": { - "contents": "", - "bgcolor": "1" - }, - "14,0": { - "contents": "", - "bgcolor": "1" - }, - "14,1": { - "contents": "", - "bgcolor": "1" - }, - "14,10": { - "contents": "", - "bgcolor": "1" - }, - "14,11": { - "contents": "", - "bgcolor": "1" - }, - "14,12": { - "contents": "", - "bgcolor": "1" - }, - "14,13": { - "contents": "", - "bgcolor": "1" - }, - "14,14": { - "contents": "", - "bgcolor": "1" - }, - "14,15": { - "contents": "", - "bgcolor": "1" - }, - "14,16": { - "contents": "", - "bgcolor": "1" - }, - "14,17": { - "contents": "", - "bgcolor": "1" - }, - "14,18": { - "contents": "", - "bgcolor": "1" - }, - "14,19": { - "contents": "", - "bgcolor": "1" - }, - "14,2": { - "contents": "", - "bgcolor": "1" - }, - "14,20": { - "contents": "", - "bgcolor": "1" - }, - "14,21": { - "contents": "", - "bgcolor": "1" - }, - "14,22": { - "contents": "", - "bgcolor": "1" - }, - "14,23": { - "contents": "", - "bgcolor": "1" - }, - "14,24": { - "contents": "", - "bgcolor": "1" - }, - "14,25": { - "contents": "", - "bgcolor": "1" - }, - "14,26": { - "contents": "", - "bgcolor": "1" - }, - "14,27": { - "contents": "", - "bgcolor": "1" - }, - "14,28": { - "contents": "", - "bgcolor": "1" - }, - "14,29": { - "contents": "", - "bgcolor": "1" - }, - "14,3": { - "contents": "", - "bgcolor": "1" - }, - "14,30": { - "contents": "", - "bgcolor": "1" - }, - "14,31": { - "contents": "", - "bgcolor": "1" - }, - "14,32": { - "contents": "", - "bgcolor": "1" - }, - "14,33": { - "contents": "", - "bgcolor": "1" - }, - "14,34": { - "contents": "", - "bgcolor": "1" - }, - "14,35": { - "contents": "", - "bgcolor": "1" - }, - "14,36": { - "contents": "", - "bgcolor": "1" - }, - "14,37": { - "contents": "", - "bgcolor": "1" - }, - "14,38": { - "contents": "", - "bgcolor": "1" - }, - "14,39": { - "contents": "", - "bgcolor": "1" - }, - "14,4": { - "contents": "", - "bgcolor": "1" - }, - "14,40": { - "contents": "", - "bgcolor": "1" - }, - "14,41": { - "contents": "", - "bgcolor": "1" - }, - "14,42": { - "contents": "", - "bgcolor": "1" - }, - "14,43": { - "contents": "", - "bgcolor": "1" - }, - "14,44": { - "contents": "", - "bgcolor": "1" - }, - "14,45": { - "contents": "", - "bgcolor": "1" - }, - "14,46": { - "contents": "", - "bgcolor": "1" - }, - "14,47": { - "contents": "", - "bgcolor": "1" - }, - "14,48": { - "contents": "", - "bgcolor": "1" - }, - "14,49": { - "contents": "", - "bgcolor": "1" - }, - "14,5": { - "contents": "", - "bgcolor": "1" - }, - "14,50": { - "contents": "", - "bgcolor": "1" - }, - "14,51": { - "contents": "", - "bgcolor": "1" - }, - "14,52": { - "contents": "", - "bgcolor": "1" - }, - "14,53": { - "contents": "", - "bgcolor": "1" - }, - "14,54": { - "contents": "", - "bgcolor": "1" - }, - "14,55": { - "contents": "", - "bgcolor": "1" - }, - "14,56": { - "contents": "", - "bgcolor": "1" - }, - "14,57": { - "contents": "", - "bgcolor": "1" - }, - "14,58": { - "contents": "", - "bgcolor": "1" - }, - "14,59": { - "contents": "", - "bgcolor": "1" - }, - "14,6": { - "contents": "", - "bgcolor": "1" - }, - "14,60": { - "contents": "", - "bgcolor": "1" - }, - "14,61": { - "contents": "", - "bgcolor": "1" - }, - "14,62": { - "contents": "", - "bgcolor": "1" - }, - "14,63": { - "contents": "", - "bgcolor": "1" - }, - "14,64": { - "contents": "", - "bgcolor": "1" - }, - "14,65": { - "contents": "", - "bgcolor": "1" - }, - "14,66": { - "contents": "", - "bgcolor": "1" - }, - "14,67": { - "contents": "", - "bgcolor": "1" - }, - "14,68": { - "contents": "", - "bgcolor": "1" - }, - "14,69": { - "contents": "", - "bgcolor": "1" - }, - "14,7": { - "contents": "", - "bgcolor": "1" - }, - "14,70": { - "contents": "", - "bgcolor": "1" - }, - "14,71": { - "contents": "", - "bgcolor": "1" - }, - "14,72": { - "contents": "", - "bgcolor": "1" - }, - "14,73": { - "contents": "", - "bgcolor": "1" - }, - "14,74": { - "contents": "", - "bgcolor": "1" - }, - "14,75": { - "contents": "", - "bgcolor": "1" - }, - "14,76": { - "contents": "", - "bgcolor": "1" - }, - "14,77": { - "contents": "", - "bgcolor": "1" - }, - "14,78": { - "contents": "", - "bgcolor": "1" - }, - "14,79": { - "contents": "", - "bgcolor": "1" - }, - "14,8": { - "contents": "", - "bgcolor": "1" - }, - "14,9": { - "contents": "", - "bgcolor": "1" - }, - "15,0": { - "contents": "", - "bgcolor": "1" - }, - "15,1": { - "contents": "", - "bgcolor": "1" - }, - "15,10": { - "contents": "", - "bgcolor": "1" - }, - "15,11": { - "contents": "", - "bgcolor": "1" - }, - "15,12": { - "contents": "", - "bgcolor": "1" - }, - "15,13": { - "contents": "", - "bgcolor": "1" - }, - "15,14": { - "contents": "", - "bgcolor": "1" - }, - "15,15": { - "contents": "", - "bgcolor": "1" - }, - "15,16": { - "contents": "", - "bgcolor": "1" - }, - "15,17": { - "contents": "", - "bgcolor": "1" - }, - "15,18": { - "contents": "", - "bgcolor": "1" - }, - "15,19": { - "contents": "", - "bgcolor": "1" - }, - "15,2": { - "contents": "", - "bgcolor": "1" - }, - "15,20": { - "contents": "", - "bgcolor": "1" - }, - "15,21": { - "contents": "", - "bgcolor": "1" - }, - "15,22": { - "contents": "", - "bgcolor": "1" - }, - "15,23": { - "contents": "", - "bgcolor": "1" - }, - "15,24": { - "contents": "", - "bgcolor": "1" - }, - "15,25": { - "contents": "", - "bgcolor": "1" - }, - "15,26": { - "contents": "", - "bgcolor": "1" - }, - "15,27": { - "contents": "", - "bgcolor": "1" - }, - "15,28": { - "contents": "", - "bgcolor": "1" - }, - "15,29": { - "contents": "", - "bgcolor": "1" - }, - "15,3": { - "contents": "", - "bgcolor": "1" - }, - "15,30": { - "contents": "", - "bgcolor": "1" - }, - "15,31": { - "contents": "", - "bgcolor": "1" - }, - "15,32": { - "contents": "", - "bgcolor": "1" - }, - "15,33": { - "contents": "", - "bgcolor": "1" - }, - "15,34": { - "contents": "", - "bgcolor": "1" - }, - "15,35": { - "contents": "", - "bgcolor": "1" - }, - "15,36": { - "contents": "", - "bgcolor": "1" - }, - "15,37": { - "contents": "", - "bgcolor": "1" - }, - "15,38": { - "contents": "", - "bgcolor": "1" - }, - "15,39": { - "contents": "", - "bgcolor": "1" - }, - "15,4": { - "contents": "", - "bgcolor": "1" - }, - "15,40": { - "contents": "", - "bgcolor": "1" - }, - "15,41": { - "contents": "", - "bgcolor": "1" - }, - "15,42": { - "contents": "", - "bgcolor": "1" - }, - "15,43": { - "contents": "", - "bgcolor": "1" - }, - "15,44": { - "contents": "", - "bgcolor": "1" - }, - "15,45": { - "contents": "", - "bgcolor": "1" - }, - "15,46": { - "contents": "", - "bgcolor": "1" - }, - "15,47": { - "contents": "", - "bgcolor": "1" - }, - "15,48": { - "contents": "", - "bgcolor": "1" - }, - "15,49": { - "contents": "", - "bgcolor": "1" - }, - "15,5": { - "contents": "", - "bgcolor": "1" - }, - "15,50": { - "contents": "", - "bgcolor": "1" - }, - "15,51": { - "contents": "", - "bgcolor": "1" - }, - "15,52": { - "contents": "", - "bgcolor": "1" - }, - "15,53": { - "contents": "", - "bgcolor": "1" - }, - "15,54": { - "contents": "", - "bgcolor": "1" - }, - "15,55": { - "contents": "", - "bgcolor": "1" - }, - "15,56": { - "contents": "", - "bgcolor": "1" - }, - "15,57": { - "contents": "", - "bgcolor": "1" - }, - "15,58": { - "contents": "", - "bgcolor": "1" - }, - "15,59": { - "contents": "", - "bgcolor": "1" - }, - "15,6": { - "contents": "", - "bgcolor": "1" - }, - "15,60": { - "contents": "", - "bgcolor": "1" - }, - "15,61": { - "contents": "", - "bgcolor": "1" - }, - "15,62": { - "contents": "", - "bgcolor": "1" - }, - "15,63": { - "contents": "", - "bgcolor": "1" - }, - "15,64": { - "contents": "", - "bgcolor": "1" - }, - "15,65": { - "contents": "", - "bgcolor": "1" - }, - "15,66": { - "contents": "", - "bgcolor": "1" - }, - "15,67": { - "contents": "", - "bgcolor": "1" - }, - "15,68": { - "contents": "", - "bgcolor": "1" - }, - "15,69": { - "contents": "", - "bgcolor": "1" - }, - "15,7": { - "contents": "", - "bgcolor": "1" - }, - "15,70": { - "contents": "", - "bgcolor": "1" - }, - "15,71": { - "contents": "", - "bgcolor": "1" - }, - "15,72": { - "contents": "", - "bgcolor": "1" - }, - "15,73": { - "contents": "", - "bgcolor": "1" - }, - "15,74": { - "contents": "", - "bgcolor": "1" - }, - "15,75": { - "contents": "", - "bgcolor": "1" - }, - "15,76": { - "contents": "", - "bgcolor": "1" - }, - "15,77": { - "contents": "", - "bgcolor": "1" - }, - "15,78": { - "contents": "", - "bgcolor": "1" - }, - "15,79": { - "contents": "", - "bgcolor": "1" - }, - "15,8": { - "contents": "", - "bgcolor": "1" - }, - "15,9": { - "contents": "", - "bgcolor": "1" - }, - "16,0": { - "contents": "", - "bgcolor": "1" - }, - "16,1": { - "contents": "", - "bgcolor": "1" - }, - "16,10": { - "contents": "", - "bgcolor": "1" - }, - "16,11": { - "contents": "", - "bgcolor": "1" - }, - "16,12": { - "contents": "", - "bgcolor": "1" - }, - "16,13": { - "contents": "", - "bgcolor": "1" - }, - "16,14": { - "contents": "", - "bgcolor": "1" - }, - "16,15": { - "contents": "", - "bgcolor": "1" - }, - "16,16": { - "contents": "", - "bgcolor": "1" - }, - "16,17": { - "contents": "", - "bgcolor": "1" - }, - "16,18": { - "contents": "", - "bgcolor": "1" - }, - "16,19": { - "contents": "", - "bgcolor": "1" - }, - "16,2": { - "contents": "", - "bgcolor": "1" - }, - "16,20": { - "contents": "", - "bgcolor": "1" - }, - "16,21": { - "contents": "", - "bgcolor": "1" - }, - "16,22": { - "contents": "", - "bgcolor": "1" - }, - "16,23": { - "contents": "", - "bgcolor": "1" - }, - "16,24": { - "contents": "", - "bgcolor": "1" - }, - "16,25": { - "contents": "", - "bgcolor": "1" - }, - "16,26": { - "contents": "", - "bgcolor": "1" - }, - "16,27": { - "contents": "", - "bgcolor": "1" - }, - "16,28": { - "contents": "", - "bgcolor": "1" - }, - "16,29": { - "contents": "", - "bgcolor": "1" - }, - "16,3": { - "contents": "", - "bgcolor": "1" - }, - "16,30": { - "contents": "", - "bgcolor": "1" - }, - "16,31": { - "contents": "", - "bgcolor": "1" - }, - "16,32": { - "contents": "", - "bgcolor": "1" - }, - "16,33": { - "contents": "", - "bgcolor": "1" - }, - "16,34": { - "contents": "", - "bgcolor": "1" - }, - "16,35": { - "contents": "", - "bgcolor": "1" - }, - "16,36": { - "contents": "", - "bgcolor": "1" - }, - "16,37": { - "contents": "", - "bgcolor": "1" - }, - "16,38": { - "contents": "", - "bgcolor": "1" - }, - "16,39": { - "contents": "", - "bgcolor": "1" - }, - "16,4": { - "contents": "", - "bgcolor": "1" - }, - "16,40": { - "contents": "", - "bgcolor": "1" - }, - "16,41": { - "contents": "", - "bgcolor": "1" - }, - "16,42": { - "contents": "", - "bgcolor": "1" - }, - "16,43": { - "contents": "", - "bgcolor": "1" - }, - "16,44": { - "contents": "", - "bgcolor": "1" - }, - "16,45": { - "contents": "", - "bgcolor": "1" - }, - "16,46": { - "contents": "", - "bgcolor": "1" - }, - "16,47": { - "contents": "", - "bgcolor": "1" - }, - "16,48": { - "contents": "", - "bgcolor": "1" - }, - "16,49": { - "contents": "", - "bgcolor": "1" - }, - "16,5": { - "contents": "", - "bgcolor": "1" - }, - "16,50": { - "contents": "", - "bgcolor": "1" - }, - "16,51": { - "contents": "", - "bgcolor": "1" - }, - "16,52": { - "contents": "", - "bgcolor": "1" - }, - "16,53": { - "contents": "", - "bgcolor": "1" - }, - "16,54": { - "contents": "", - "bgcolor": "1" - }, - "16,55": { - "contents": "", - "bgcolor": "1" - }, - "16,56": { - "contents": "", - "bgcolor": "1" - }, - "16,57": { - "contents": "", - "bgcolor": "1" - }, - "16,58": { - "contents": "", - "bgcolor": "1" - }, - "16,59": { - "contents": "", - "bgcolor": "1" - }, - "16,6": { - "contents": "", - "bgcolor": "1" - }, - "16,60": { - "contents": "", - "bgcolor": "1" - }, - "16,61": { - "contents": "", - "bgcolor": "1" - }, - "16,62": { - "contents": "", - "bgcolor": "1" - }, - "16,63": { - "contents": "", - "bgcolor": "1" - }, - "16,64": { - "contents": "", - "bgcolor": "1" - }, - "16,65": { - "contents": "", - "bgcolor": "1" - }, - "16,66": { - "contents": "", - "bgcolor": "1" - }, - "16,67": { - "contents": "", - "bgcolor": "1" - }, - "16,68": { - "contents": "", - "bgcolor": "1" - }, - "16,69": { - "contents": "", - "bgcolor": "1" - }, - "16,7": { - "contents": "", - "bgcolor": "1" - }, - "16,70": { - "contents": "", - "bgcolor": "1" - }, - "16,71": { - "contents": "", - "bgcolor": "1" - }, - "16,72": { - "contents": "", - "bgcolor": "1" - }, - "16,73": { - "contents": "", - "bgcolor": "1" - }, - "16,74": { - "contents": "", - "bgcolor": "1" - }, - "16,75": { - "contents": "", - "bgcolor": "1" - }, - "16,76": { - "contents": "", - "bgcolor": "1" - }, - "16,77": { - "contents": "", - "bgcolor": "1" - }, - "16,78": { - "contents": "", - "bgcolor": "1" - }, - "16,79": { - "contents": "", - "bgcolor": "1" - }, - "16,8": { - "contents": "", - "bgcolor": "1" - }, - "16,9": { - "contents": "", - "bgcolor": "1" - }, - "17,0": { - "contents": "", - "bgcolor": "1" - }, - "17,1": { - "contents": "", - "bgcolor": "1" - }, - "17,10": { - "contents": "", - "bgcolor": "1" - }, - "17,11": { - "contents": "", - "bgcolor": "1" - }, - "17,12": { - "contents": "", - "bgcolor": "1" - }, - "17,13": { - "contents": "", - "bgcolor": "1" - }, - "17,14": { - "contents": "", - "bgcolor": "1" - }, - "17,15": { - "contents": "", - "bgcolor": "1" - }, - "17,16": { - "contents": "", - "bgcolor": "1" - }, - "17,17": { - "contents": "", - "bgcolor": "1" - }, - "17,18": { - "contents": "", - "bgcolor": "1" - }, - "17,19": { - "contents": "", - "bgcolor": "1" - }, - "17,2": { - "contents": "", - "bgcolor": "1" - }, - "17,20": { - "contents": "", - "bgcolor": "1" - }, - "17,21": { - "contents": "", - "bgcolor": "1" - }, - "17,22": { - "contents": "", - "bgcolor": "1" - }, - "17,23": { - "contents": "", - "bgcolor": "1" - }, - "17,24": { - "contents": "", - "bgcolor": "1" - }, - "17,25": { - "contents": "", - "bgcolor": "1" - }, - "17,26": { - "contents": "", - "bgcolor": "1" - }, - "17,27": { - "contents": "", - "bgcolor": "1" - }, - "17,28": { - "contents": "", - "bgcolor": "1" - }, - "17,29": { - "contents": "", - "bgcolor": "1" - }, - "17,3": { - "contents": "", - "bgcolor": "1" - }, - "17,30": { - "contents": "", - "bgcolor": "1" - }, - "17,31": { - "contents": "", - "bgcolor": "1" - }, - "17,32": { - "contents": "", - "bgcolor": "1" - }, - "17,33": { - "contents": "", - "bgcolor": "1" - }, - "17,34": { - "contents": "", - "bgcolor": "1" - }, - "17,35": { - "contents": "", - "bgcolor": "1" - }, - "17,36": { - "contents": "", - "bgcolor": "1" - }, - "17,37": { - "contents": "", - "bgcolor": "1" - }, - "17,38": { - "contents": "", - "bgcolor": "1" - }, - "17,39": { - "contents": "", - "bgcolor": "1" - }, - "17,4": { - "contents": "", - "bgcolor": "1" - }, - "17,40": { - "contents": "", - "bgcolor": "1" - }, - "17,41": { - "contents": "", - "bgcolor": "1" - }, - "17,42": { - "contents": "", - "bgcolor": "1" - }, - "17,43": { - "contents": "", - "bgcolor": "1" - }, - "17,44": { - "contents": "", - "bgcolor": "1" - }, - "17,45": { - "contents": "", - "bgcolor": "1" - }, - "17,46": { - "contents": "", - "bgcolor": "1" - }, - "17,47": { - "contents": "", - "bgcolor": "1" - }, - "17,48": { - "contents": "", - "bgcolor": "1" - }, - "17,49": { - "contents": "", - "bgcolor": "1" - }, - "17,5": { - "contents": "", - "bgcolor": "1" - }, - "17,50": { - "contents": "", - "bgcolor": "1" - }, - "17,51": { - "contents": "", - "bgcolor": "1" - }, - "17,52": { - "contents": "", - "bgcolor": "1" - }, - "17,53": { - "contents": "", - "bgcolor": "1" - }, - "17,54": { - "contents": "", - "bgcolor": "1" - }, - "17,55": { - "contents": "", - "bgcolor": "1" - }, - "17,56": { - "contents": "", - "bgcolor": "1" - }, - "17,57": { - "contents": "", - "bgcolor": "1" - }, - "17,58": { - "contents": "", - "bgcolor": "1" - }, - "17,59": { - "contents": "", - "bgcolor": "1" - }, - "17,6": { - "contents": "", - "bgcolor": "1" - }, - "17,60": { - "contents": "", - "bgcolor": "1" - }, - "17,61": { - "contents": "", - "bgcolor": "1" - }, - "17,62": { - "contents": "", - "bgcolor": "1" - }, - "17,63": { - "contents": "", - "bgcolor": "1" - }, - "17,64": { - "contents": "", - "bgcolor": "1" - }, - "17,65": { - "contents": "", - "bgcolor": "1" - }, - "17,66": { - "contents": "", - "bgcolor": "1" - }, - "17,67": { - "contents": "", - "bgcolor": "1" - }, - "17,68": { - "contents": "", - "bgcolor": "1" - }, - "17,69": { - "contents": "", - "bgcolor": "1" - }, - "17,7": { - "contents": "", - "bgcolor": "1" - }, - "17,70": { - "contents": "", - "bgcolor": "1" - }, - "17,71": { - "contents": "", - "bgcolor": "1" - }, - "17,72": { - "contents": "", - "bgcolor": "1" - }, - "17,73": { - "contents": "", - "bgcolor": "1" - }, - "17,74": { - "contents": "", - "bgcolor": "1" - }, - "17,75": { - "contents": "", - "bgcolor": "1" - }, - "17,76": { - "contents": "", - "bgcolor": "1" - }, - "17,77": { - "contents": "", - "bgcolor": "1" - }, - "17,78": { - "contents": "", - "bgcolor": "1" - }, - "17,79": { - "contents": "", - "bgcolor": "1" - }, - "17,8": { - "contents": "", - "bgcolor": "1" - }, - "17,9": { - "contents": "", - "bgcolor": "1" - }, - "18,0": { - "contents": "", - "bgcolor": "1" - }, - "18,1": { - "contents": "", - "bgcolor": "1" - }, - "18,10": { - "contents": "", - "bgcolor": "1" - }, - "18,11": { - "contents": "", - "bgcolor": "1" - }, - "18,12": { - "contents": "", - "bgcolor": "1" - }, - "18,13": { - "contents": "", - "bgcolor": "1" - }, - "18,14": { - "contents": "", - "bgcolor": "1" - }, - "18,15": { - "contents": "", - "bgcolor": "1" - }, - "18,16": { - "contents": "", - "bgcolor": "1" - }, - "18,17": { - "contents": "", - "bgcolor": "1" - }, - "18,18": { - "contents": "", - "bgcolor": "1" - }, - "18,19": { - "contents": "", - "bgcolor": "1" - }, - "18,2": { - "contents": "", - "bgcolor": "1" - }, - "18,20": { - "contents": "", - "bgcolor": "1" - }, - "18,21": { - "contents": "", - "bgcolor": "1" - }, - "18,22": { - "contents": "", - "bgcolor": "1" - }, - "18,23": { - "contents": "", - "bgcolor": "1" - }, - "18,24": { - "contents": "", - "bgcolor": "1" - }, - "18,25": { - "contents": "", - "bgcolor": "1" - }, - "18,26": { - "contents": "", - "bgcolor": "1" - }, - "18,27": { - "contents": "", - "bgcolor": "1" - }, - "18,28": { - "contents": "", - "bgcolor": "1" - }, - "18,29": { - "contents": "", - "bgcolor": "1" - }, - "18,3": { - "contents": "", - "bgcolor": "1" - }, - "18,30": { - "contents": "", - "bgcolor": "1" - }, - "18,31": { - "contents": "", - "bgcolor": "1" - }, - "18,32": { - "contents": "", - "bgcolor": "1" - }, - "18,33": { - "contents": "", - "bgcolor": "1" - }, - "18,34": { - "contents": "", - "bgcolor": "1" - }, - "18,35": { - "contents": "", - "bgcolor": "1" - }, - "18,36": { - "contents": "", - "bgcolor": "1" - }, - "18,37": { - "contents": "", - "bgcolor": "1" - }, - "18,38": { - "contents": "", - "bgcolor": "1" - }, - "18,39": { - "contents": "", - "bgcolor": "1" - }, - "18,4": { - "contents": "", - "bgcolor": "1" - }, - "18,40": { - "contents": "", - "bgcolor": "1" - }, - "18,41": { - "contents": "", - "bgcolor": "1" - }, - "18,42": { - "contents": "", - "bgcolor": "1" - }, - "18,43": { - "contents": "", - "bgcolor": "1" - }, - "18,44": { - "contents": "", - "bgcolor": "1" - }, - "18,45": { - "contents": "", - "bgcolor": "1" - }, - "18,46": { - "contents": "", - "bgcolor": "1" - }, - "18,47": { - "contents": "", - "bgcolor": "1" - }, - "18,48": { - "contents": "", - "bgcolor": "1" - }, - "18,49": { - "contents": "", - "bgcolor": "1" - }, - "18,5": { - "contents": "", - "bgcolor": "1" - }, - "18,50": { - "contents": "", - "bgcolor": "1" - }, - "18,51": { - "contents": "", - "bgcolor": "1" - }, - "18,52": { - "contents": "", - "bgcolor": "1" - }, - "18,53": { - "contents": "", - "bgcolor": "1" - }, - "18,54": { - "contents": "", - "bgcolor": "1" - }, - "18,55": { - "contents": "", - "bgcolor": "1" - }, - "18,56": { - "contents": "", - "bgcolor": "1" - }, - "18,57": { - "contents": "", - "bgcolor": "1" - }, - "18,58": { - "contents": "", - "bgcolor": "1" - }, - "18,59": { - "contents": "", - "bgcolor": "1" - }, - "18,6": { - "contents": "", - "bgcolor": "1" - }, - "18,60": { - "contents": "", - "bgcolor": "1" - }, - "18,61": { - "contents": "", - "bgcolor": "1" - }, - "18,62": { - "contents": "", - "bgcolor": "1" - }, - "18,63": { - "contents": "", - "bgcolor": "1" - }, - "18,64": { - "contents": "", - "bgcolor": "1" - }, - "18,65": { - "contents": "", - "bgcolor": "1" - }, - "18,66": { - "contents": "", - "bgcolor": "1" - }, - "18,67": { - "contents": "", - "bgcolor": "1" - }, - "18,68": { - "contents": "", - "bgcolor": "1" - }, - "18,69": { - "contents": "", - "bgcolor": "1" - }, - "18,7": { - "contents": "", - "bgcolor": "1" - }, - "18,70": { - "contents": "", - "bgcolor": "1" - }, - "18,71": { - "contents": "", - "bgcolor": "1" - }, - "18,72": { - "contents": "", - "bgcolor": "1" - }, - "18,73": { - "contents": "", - "bgcolor": "1" - }, - "18,74": { - "contents": "", - "bgcolor": "1" - }, - "18,75": { - "contents": "", - "bgcolor": "1" - }, - "18,76": { - "contents": "", - "bgcolor": "1" - }, - "18,77": { - "contents": "", - "bgcolor": "1" - }, - "18,78": { - "contents": "", - "bgcolor": "1" - }, - "18,79": { - "contents": "", - "bgcolor": "1" - }, - "18,8": { - "contents": "", - "bgcolor": "1" - }, - "18,9": { - "contents": "", - "bgcolor": "1" - }, - "19,0": { - "contents": "", - "bgcolor": "1" - }, - "19,1": { - "contents": "", - "bgcolor": "1" - }, - "19,10": { - "contents": "", - "bgcolor": "1" - }, - "19,11": { - "contents": "", - "bgcolor": "1" - }, - "19,12": { - "contents": "", - "bgcolor": "1" - }, - "19,13": { - "contents": "", - "bgcolor": "1" - }, - "19,14": { - "contents": "", - "bgcolor": "1" - }, - "19,15": { - "contents": "", - "bgcolor": "1" - }, - "19,16": { - "contents": "", - "bgcolor": "1" - }, - "19,17": { - "contents": "", - "bgcolor": "1" - }, - "19,18": { - "contents": "", - "bgcolor": "1" - }, - "19,19": { - "contents": "", - "bgcolor": "1" - }, - "19,2": { - "contents": "", - "bgcolor": "1" - }, - "19,20": { - "contents": "", - "bgcolor": "1" - }, - "19,21": { - "contents": "", - "bgcolor": "1" - }, - "19,22": { - "contents": "", - "bgcolor": "1" - }, - "19,23": { - "contents": "", - "bgcolor": "1" - }, - "19,24": { - "contents": "", - "bgcolor": "1" - }, - "19,25": { - "contents": "", - "bgcolor": "1" - }, - "19,26": { - "contents": "", - "bgcolor": "1" - }, - "19,27": { - "contents": "", - "bgcolor": "1" - }, - "19,28": { - "contents": "", - "bgcolor": "1" - }, - "19,29": { - "contents": "", - "bgcolor": "1" - }, - "19,3": { - "contents": "", - "bgcolor": "1" - }, - "19,30": { - "contents": "", - "bgcolor": "1" - }, - "19,31": { - "contents": "", - "bgcolor": "1" - }, - "19,32": { - "contents": "", - "bgcolor": "1" - }, - "19,33": { - "contents": "", - "bgcolor": "1" - }, - "19,34": { - "contents": "", - "bgcolor": "1" - }, - "19,35": { - "contents": "", - "bgcolor": "1" - }, - "19,36": { - "contents": "", - "bgcolor": "1" - }, - "19,37": { - "contents": "", - "bgcolor": "1" - }, - "19,38": { - "contents": "", - "bgcolor": "1" - }, - "19,39": { - "contents": "", - "bgcolor": "1" - }, - "19,4": { - "contents": "", - "bgcolor": "1" - }, - "19,40": { - "contents": "", - "bgcolor": "1" - }, - "19,41": { - "contents": "", - "bgcolor": "1" - }, - "19,42": { - "contents": "", - "bgcolor": "1" - }, - "19,43": { - "contents": "", - "bgcolor": "1" - }, - "19,44": { - "contents": "", - "bgcolor": "1" - }, - "19,45": { - "contents": "", - "bgcolor": "1" - }, - "19,46": { - "contents": "", - "bgcolor": "1" - }, - "19,47": { - "contents": "", - "bgcolor": "1" - }, - "19,48": { - "contents": "", - "bgcolor": "1" - }, - "19,49": { - "contents": "", - "bgcolor": "1" - }, - "19,5": { - "contents": "", - "bgcolor": "1" - }, - "19,50": { - "contents": "", - "bgcolor": "1" - }, - "19,51": { - "contents": "", - "bgcolor": "1" - }, - "19,52": { - "contents": "", - "bgcolor": "1" - }, - "19,53": { - "contents": "", - "bgcolor": "1" - }, - "19,54": { - "contents": "", - "bgcolor": "1" - }, - "19,55": { - "contents": "", - "bgcolor": "1" - }, - "19,56": { - "contents": "", - "bgcolor": "1" - }, - "19,57": { - "contents": "", - "bgcolor": "1" - }, - "19,58": { - "contents": "", - "bgcolor": "1" - }, - "19,59": { - "contents": "", - "bgcolor": "1" - }, - "19,6": { - "contents": "", - "bgcolor": "1" - }, - "19,60": { - "contents": "", - "bgcolor": "1" - }, - "19,61": { - "contents": "", - "bgcolor": "1" - }, - "19,62": { - "contents": "", - "bgcolor": "1" - }, - "19,63": { - "contents": "", - "bgcolor": "1" - }, - "19,64": { - "contents": "", - "bgcolor": "1" - }, - "19,65": { - "contents": "", - "bgcolor": "1" - }, - "19,66": { - "contents": "", - "bgcolor": "1" - }, - "19,67": { - "contents": "", - "bgcolor": "1" - }, - "19,68": { - "contents": "", - "bgcolor": "1" - }, - "19,69": { - "contents": "", - "bgcolor": "1" - }, - "19,7": { - "contents": "", - "bgcolor": "1" - }, - "19,70": { - "contents": "", - "bgcolor": "1" - }, - "19,71": { - "contents": "", - "bgcolor": "1" - }, - "19,72": { - "contents": "", - "bgcolor": "1" - }, - "19,73": { - "contents": "", - "bgcolor": "1" - }, - "19,74": { - "contents": "", - "bgcolor": "1" - }, - "19,75": { - "contents": "", - "bgcolor": "1" - }, - "19,76": { - "contents": "", - "bgcolor": "1" - }, - "19,77": { - "contents": "", - "bgcolor": "1" - }, - "19,78": { - "contents": "", - "bgcolor": "1" - }, - "19,79": { - "contents": "", - "bgcolor": "1" - }, - "19,8": { - "contents": "", - "bgcolor": "1" - }, - "19,9": { - "contents": "", - "bgcolor": "1" - }, - "2,0": { - "contents": "", - "bgcolor": "1" - }, - "2,1": { - "contents": "", - "bgcolor": "1" - }, - "2,10": { - "contents": "", - "bgcolor": "1" - }, - "2,11": { - "contents": "", - "bgcolor": "1" - }, - "2,12": { - "contents": "", - "bgcolor": "1" - }, - "2,13": { - "contents": "", - "bgcolor": "1" - }, - "2,14": { - "contents": "", - "bgcolor": "1" - }, - "2,15": { - "contents": "", - "bgcolor": "1" - }, - "2,16": { - "contents": "", - "bgcolor": "1" - }, - "2,17": { - "contents": "", - "bgcolor": "1" - }, - "2,18": { - "contents": "", - "bgcolor": "1" - }, - "2,19": { - "contents": "", - "bgcolor": "1" - }, - "2,2": { - "contents": "", - "bgcolor": "1" - }, - "2,20": { - "contents": "", - "bgcolor": "1" - }, - "2,21": { - "contents": "", - "bgcolor": "1" - }, - "2,22": { - "contents": "", - "bgcolor": "1" - }, - "2,23": { - "contents": "", - "bgcolor": "1" - }, - "2,24": { - "contents": "", - "bgcolor": "1" - }, - "2,25": { - "contents": "", - "bgcolor": "1" - }, - "2,26": { - "contents": "", - "bgcolor": "1" - }, - "2,27": { - "contents": "", - "bgcolor": "1" - }, - "2,28": { - "contents": "", - "bgcolor": "1" - }, - "2,29": { - "contents": "", - "bgcolor": "1" - }, - "2,3": { - "contents": "", - "bgcolor": "1" - }, - "2,30": { - "contents": "", - "bgcolor": "1" - }, - "2,31": { - "contents": "", - "bgcolor": "1" - }, - "2,32": { - "contents": "", - "bgcolor": "1" - }, - "2,33": { - "contents": "", - "bgcolor": "1" - }, - "2,34": { - "contents": "", - "bgcolor": "1" - }, - "2,35": { - "contents": "", - "bgcolor": "1" - }, - "2,36": { - "contents": "", - "bgcolor": "1" - }, - "2,37": { - "contents": "", - "bgcolor": "1" - }, - "2,38": { - "contents": "", - "bgcolor": "1" - }, - "2,39": { - "contents": "", - "bgcolor": "1" - }, - "2,4": { - "contents": "", - "bgcolor": "1" - }, - "2,40": { - "contents": "", - "bgcolor": "1" - }, - "2,41": { - "contents": "", - "bgcolor": "1" - }, - "2,42": { - "contents": "", - "bgcolor": "1" - }, - "2,43": { - "contents": "", - "bgcolor": "1" - }, - "2,44": { - "contents": "", - "bgcolor": "1" - }, - "2,45": { - "contents": "", - "bgcolor": "1" - }, - "2,46": { - "contents": "", - "bgcolor": "1" - }, - "2,47": { - "contents": "", - "bgcolor": "1" - }, - "2,48": { - "contents": "", - "bgcolor": "1" - }, - "2,49": { - "contents": "", - "bgcolor": "1" - }, - "2,5": { - "contents": "", - "bgcolor": "1" - }, - "2,50": { - "contents": "", - "bgcolor": "1" - }, - "2,51": { - "contents": "", - "bgcolor": "1" - }, - "2,52": { - "contents": "", - "bgcolor": "1" - }, - "2,53": { - "contents": "", - "bgcolor": "1" - }, - "2,54": { - "contents": "", - "bgcolor": "1" - }, - "2,55": { - "contents": "", - "bgcolor": "1" - }, - "2,56": { - "contents": "", - "bgcolor": "1" - }, - "2,57": { - "contents": "", - "bgcolor": "1" - }, - "2,58": { - "contents": "", - "bgcolor": "1" - }, - "2,59": { - "contents": "", - "bgcolor": "1" - }, - "2,6": { - "contents": "", - "bgcolor": "1" - }, - "2,60": { - "contents": "", - "bgcolor": "1" - }, - "2,61": { - "contents": "", - "bgcolor": "1" - }, - "2,62": { - "contents": "", - "bgcolor": "1" - }, - "2,63": { - "contents": "", - "bgcolor": "1" - }, - "2,64": { - "contents": "", - "bgcolor": "1" - }, - "2,65": { - "contents": "", - "bgcolor": "1" - }, - "2,66": { - "contents": "", - "bgcolor": "1" - }, - "2,67": { - "contents": "", - "bgcolor": "1" - }, - "2,68": { - "contents": "", - "bgcolor": "1" - }, - "2,69": { - "contents": "", - "bgcolor": "1" - }, - "2,7": { - "contents": "", - "bgcolor": "1" - }, - "2,70": { - "contents": "", - "bgcolor": "1" - }, - "2,71": { - "contents": "", - "bgcolor": "1" - }, - "2,72": { - "contents": "", - "bgcolor": "1" - }, - "2,73": { - "contents": "", - "bgcolor": "1" - }, - "2,74": { - "contents": "", - "bgcolor": "1" - }, - "2,75": { - "contents": "", - "bgcolor": "1" - }, - "2,76": { - "contents": "", - "bgcolor": "1" - }, - "2,77": { - "contents": "", - "bgcolor": "1" - }, - "2,78": { - "contents": "", - "bgcolor": "1" - }, - "2,79": { - "contents": "", - "bgcolor": "1" - }, - "2,8": { - "contents": "", - "bgcolor": "1" - }, - "2,9": { - "contents": "", - "bgcolor": "1" - }, - "20,0": { - "contents": "", - "bgcolor": "1" - }, - "20,1": { - "contents": "", - "bgcolor": "1" - }, - "20,10": { - "contents": "", - "bgcolor": "1" - }, - "20,11": { - "contents": "", - "bgcolor": "1" - }, - "20,12": { - "contents": "", - "bgcolor": "1" - }, - "20,13": { - "contents": "", - "bgcolor": "1" - }, - "20,14": { - "contents": "", - "bgcolor": "1" - }, - "20,15": { - "contents": "", - "bgcolor": "1" - }, - "20,16": { - "contents": "", - "bgcolor": "1" - }, - "20,17": { - "contents": "", - "bgcolor": "1" - }, - "20,18": { - "contents": "", - "bgcolor": "1" - }, - "20,19": { - "contents": "", - "bgcolor": "1" - }, - "20,2": { - "contents": "", - "bgcolor": "1" - }, - "20,20": { - "contents": "", - "bgcolor": "1" - }, - "20,21": { - "contents": "", - "bgcolor": "1" - }, - "20,22": { - "contents": "", - "bgcolor": "1" - }, - "20,23": { - "contents": "", - "bgcolor": "1" - }, - "20,24": { - "contents": "", - "bgcolor": "1" - }, - "20,25": { - "contents": "", - "bgcolor": "1" - }, - "20,26": { - "contents": "", - "bgcolor": "1" - }, - "20,27": { - "contents": "", - "bgcolor": "1" - }, - "20,28": { - "contents": "", - "bgcolor": "1" - }, - "20,29": { - "contents": "", - "bgcolor": "1" - }, - "20,3": { - "contents": "", - "bgcolor": "1" - }, - "20,30": { - "contents": "", - "bgcolor": "1" - }, - "20,31": { - "contents": "", - "bgcolor": "1" - }, - "20,32": { - "contents": "", - "bgcolor": "1" - }, - "20,33": { - "contents": "", - "bgcolor": "1" - }, - "20,34": { - "contents": "", - "bgcolor": "1" - }, - "20,35": { - "contents": "", - "bgcolor": "1" - }, - "20,36": { - "contents": "", - "bgcolor": "1" - }, - "20,37": { - "contents": "", - "bgcolor": "1" - }, - "20,38": { - "contents": "", - "bgcolor": "1" - }, - "20,39": { - "contents": "", - "bgcolor": "1" - }, - "20,4": { - "contents": "", - "bgcolor": "1" - }, - "20,40": { - "contents": "", - "bgcolor": "1" - }, - "20,41": { - "contents": "", - "bgcolor": "1" - }, - "20,42": { - "contents": "", - "bgcolor": "1" - }, - "20,43": { - "contents": "", - "bgcolor": "1" - }, - "20,44": { - "contents": "", - "bgcolor": "1" - }, - "20,45": { - "contents": "", - "bgcolor": "1" - }, - "20,46": { - "contents": "", - "bgcolor": "1" - }, - "20,47": { - "contents": "", - "bgcolor": "1" - }, - "20,48": { - "contents": "", - "bgcolor": "1" - }, - "20,49": { - "contents": "", - "bgcolor": "1" - }, - "20,5": { - "contents": "", - "bgcolor": "1" - }, - "20,50": { - "contents": "", - "bgcolor": "1" - }, - "20,51": { - "contents": "", - "bgcolor": "1" - }, - "20,52": { - "contents": "", - "bgcolor": "1" - }, - "20,53": { - "contents": "", - "bgcolor": "1" - }, - "20,54": { - "contents": "", - "bgcolor": "1" - }, - "20,55": { - "contents": "", - "bgcolor": "1" - }, - "20,56": { - "contents": "", - "bgcolor": "1" - }, - "20,57": { - "contents": "", - "bgcolor": "1" - }, - "20,58": { - "contents": "", - "bgcolor": "1" - }, - "20,59": { - "contents": "", - "bgcolor": "1" - }, - "20,6": { - "contents": "", - "bgcolor": "1" - }, - "20,60": { - "contents": "", - "bgcolor": "1" - }, - "20,61": { - "contents": "", - "bgcolor": "1" - }, - "20,62": { - "contents": "", - "bgcolor": "1" - }, - "20,63": { - "contents": "", - "bgcolor": "1" - }, - "20,64": { - "contents": "", - "bgcolor": "1" - }, - "20,65": { - "contents": "", - "bgcolor": "1" - }, - "20,66": { - "contents": "", - "bgcolor": "1" - }, - "20,67": { - "contents": "", - "bgcolor": "1" - }, - "20,68": { - "contents": "", - "bgcolor": "1" - }, - "20,69": { - "contents": "", - "bgcolor": "1" - }, - "20,7": { - "contents": "", - "bgcolor": "1" - }, - "20,70": { - "contents": "", - "bgcolor": "1" - }, - "20,71": { - "contents": "", - "bgcolor": "1" - }, - "20,72": { - "contents": "", - "bgcolor": "1" - }, - "20,73": { - "contents": "", - "bgcolor": "1" - }, - "20,74": { - "contents": "", - "bgcolor": "1" - }, - "20,75": { - "contents": "", - "bgcolor": "1" - }, - "20,76": { - "contents": "", - "bgcolor": "1" - }, - "20,77": { - "contents": "", - "bgcolor": "1" - }, - "20,78": { - "contents": "", - "bgcolor": "1" - }, - "20,79": { - "contents": "", - "bgcolor": "1" - }, - "20,8": { - "contents": "", - "bgcolor": "1" - }, - "20,9": { - "contents": "", - "bgcolor": "1" - }, - "21,0": { - "contents": "", - "bgcolor": "1" - }, - "21,1": { - "contents": "", - "bgcolor": "1" - }, - "21,10": { - "contents": "", - "bgcolor": "1" - }, - "21,11": { - "contents": "", - "bgcolor": "1" - }, - "21,12": { - "contents": "", - "bgcolor": "1" - }, - "21,13": { - "contents": "", - "bgcolor": "1" - }, - "21,14": { - "contents": "", - "bgcolor": "1" - }, - "21,15": { - "contents": "", - "bgcolor": "1" - }, - "21,16": { - "contents": "", - "bgcolor": "1" - }, - "21,17": { - "contents": "", - "bgcolor": "1" - }, - "21,18": { - "contents": "", - "bgcolor": "1" - }, - "21,19": { - "contents": "", - "bgcolor": "1" - }, - "21,2": { - "contents": "", - "bgcolor": "1" - }, - "21,20": { - "contents": "", - "bgcolor": "1" - }, - "21,21": { - "contents": "", - "bgcolor": "1" - }, - "21,22": { - "contents": "", - "bgcolor": "1" - }, - "21,23": { - "contents": "", - "bgcolor": "1" - }, - "21,24": { - "contents": "", - "bgcolor": "1" - }, - "21,25": { - "contents": "", - "bgcolor": "1" - }, - "21,26": { - "contents": "", - "bgcolor": "1" - }, - "21,27": { - "contents": "", - "bgcolor": "1" - }, - "21,28": { - "contents": "", - "bgcolor": "1" - }, - "21,29": { - "contents": "", - "bgcolor": "1" - }, - "21,3": { - "contents": "", - "bgcolor": "1" - }, - "21,30": { - "contents": "", - "bgcolor": "1" - }, - "21,31": { - "contents": "", - "bgcolor": "1" - }, - "21,32": { - "contents": "", - "bgcolor": "1" - }, - "21,33": { - "contents": "", - "bgcolor": "1" - }, - "21,34": { - "contents": "", - "bgcolor": "1" - }, - "21,35": { - "contents": "", - "bgcolor": "1" - }, - "21,36": { - "contents": "", - "bgcolor": "1" - }, - "21,37": { - "contents": "", - "bgcolor": "1" - }, - "21,38": { - "contents": "", - "bgcolor": "1" - }, - "21,39": { - "contents": "", - "bgcolor": "1" - }, - "21,4": { - "contents": "", - "bgcolor": "1" - }, - "21,40": { - "contents": "", - "bgcolor": "1" - }, - "21,41": { - "contents": "", - "bgcolor": "1" - }, - "21,42": { - "contents": "", - "bgcolor": "1" - }, - "21,43": { - "contents": "", - "bgcolor": "1" - }, - "21,44": { - "contents": "", - "bgcolor": "1" - }, - "21,45": { - "contents": "", - "bgcolor": "1" - }, - "21,46": { - "contents": "", - "bgcolor": "1" - }, - "21,47": { - "contents": "", - "bgcolor": "1" - }, - "21,48": { - "contents": "", - "bgcolor": "1" - }, - "21,49": { - "contents": "", - "bgcolor": "1" - }, - "21,5": { - "contents": "", - "bgcolor": "1" - }, - "21,50": { - "contents": "", - "bgcolor": "1" - }, - "21,51": { - "contents": "", - "bgcolor": "1" - }, - "21,52": { - "contents": "", - "bgcolor": "1" - }, - "21,53": { - "contents": "", - "bgcolor": "1" - }, - "21,54": { - "contents": "", - "bgcolor": "1" - }, - "21,55": { - "contents": "", - "bgcolor": "1" - }, - "21,56": { - "contents": "", - "bgcolor": "1" - }, - "21,57": { - "contents": "", - "bgcolor": "1" - }, - "21,58": { - "contents": "", - "bgcolor": "1" - }, - "21,59": { - "contents": "", - "bgcolor": "1" - }, - "21,6": { - "contents": "", - "bgcolor": "1" - }, - "21,60": { - "contents": "", - "bgcolor": "1" - }, - "21,61": { - "contents": "", - "bgcolor": "1" - }, - "21,62": { - "contents": "", - "bgcolor": "1" - }, - "21,63": { - "contents": "", - "bgcolor": "1" - }, - "21,64": { - "contents": "", - "bgcolor": "1" - }, - "21,65": { - "contents": "", - "bgcolor": "1" - }, - "21,66": { - "contents": "", - "bgcolor": "1" - }, - "21,67": { - "contents": "", - "bgcolor": "1" - }, - "21,68": { - "contents": "", - "bgcolor": "1" - }, - "21,69": { - "contents": "", - "bgcolor": "1" - }, - "21,7": { - "contents": "", - "bgcolor": "1" - }, - "21,70": { - "contents": "", - "bgcolor": "1" - }, - "21,71": { - "contents": "", - "bgcolor": "1" - }, - "21,72": { - "contents": "", - "bgcolor": "1" - }, - "21,73": { - "contents": "", - "bgcolor": "1" - }, - "21,74": { - "contents": "", - "bgcolor": "1" - }, - "21,75": { - "contents": "", - "bgcolor": "1" - }, - "21,76": { - "contents": "", - "bgcolor": "1" - }, - "21,77": { - "contents": "", - "bgcolor": "1" - }, - "21,78": { - "contents": "", - "bgcolor": "1" - }, - "21,79": { - "contents": "", - "bgcolor": "1" - }, - "21,8": { - "contents": "", - "bgcolor": "1" - }, - "21,9": { - "contents": "", - "bgcolor": "1" - }, - "22,0": { - "contents": "", - "bgcolor": "1" - }, - "22,1": { - "contents": "", - "bgcolor": "1" - }, - "22,10": { - "contents": "", - "bgcolor": "1" - }, - "22,11": { - "contents": "", - "bgcolor": "1" - }, - "22,12": { - "contents": "", - "bgcolor": "1" - }, - "22,13": { - "contents": "", - "bgcolor": "1" - }, - "22,14": { - "contents": "", - "bgcolor": "1" - }, - "22,15": { - "contents": "", - "bgcolor": "1" - }, - "22,16": { - "contents": "", - "bgcolor": "1" - }, - "22,17": { - "contents": "", - "bgcolor": "1" - }, - "22,18": { - "contents": "", - "bgcolor": "1" - }, - "22,19": { - "contents": "", - "bgcolor": "1" - }, - "22,2": { - "contents": "", - "bgcolor": "1" - }, - "22,20": { - "contents": "", - "bgcolor": "1" - }, - "22,21": { - "contents": "", - "bgcolor": "1" - }, - "22,22": { - "contents": "", - "bgcolor": "1" - }, - "22,23": { - "contents": "", - "bgcolor": "1" - }, - "22,24": { - "contents": "", - "bgcolor": "1" - }, - "22,25": { - "contents": "", - "bgcolor": "1" - }, - "22,26": { - "contents": "", - "bgcolor": "1" - }, - "22,27": { - "contents": "", - "bgcolor": "1" - }, - "22,28": { - "contents": "", - "bgcolor": "1" - }, - "22,29": { - "contents": "", - "bgcolor": "1" - }, - "22,3": { - "contents": "", - "bgcolor": "1" - }, - "22,30": { - "contents": "", - "bgcolor": "1" - }, - "22,31": { - "contents": "", - "bgcolor": "1" - }, - "22,32": { - "contents": "", - "bgcolor": "1" - }, - "22,33": { - "contents": "", - "bgcolor": "1" - }, - "22,34": { - "contents": "", - "bgcolor": "1" - }, - "22,35": { - "contents": "", - "bgcolor": "1" - }, - "22,36": { - "contents": "", - "bgcolor": "1" - }, - "22,37": { - "contents": "", - "bgcolor": "1" - }, - "22,38": { - "contents": "", - "bgcolor": "1" - }, - "22,39": { - "contents": "", - "bgcolor": "1" - }, - "22,4": { - "contents": "", - "bgcolor": "1" - }, - "22,40": { - "contents": "", - "bgcolor": "1" - }, - "22,41": { - "contents": "", - "bgcolor": "1" - }, - "22,42": { - "contents": "", - "bgcolor": "1" - }, - "22,43": { - "contents": "", - "bgcolor": "1" - }, - "22,44": { - "contents": "", - "bgcolor": "1" - }, - "22,45": { - "contents": "", - "bgcolor": "1" - }, - "22,46": { - "contents": "", - "bgcolor": "1" - }, - "22,47": { - "contents": "", - "bgcolor": "1" - }, - "22,48": { - "contents": "", - "bgcolor": "1" - }, - "22,49": { - "contents": "", - "bgcolor": "1" - }, - "22,5": { - "contents": "", - "bgcolor": "1" - }, - "22,50": { - "contents": "", - "bgcolor": "1" - }, - "22,51": { - "contents": "", - "bgcolor": "1" - }, - "22,52": { - "contents": "", - "bgcolor": "1" - }, - "22,53": { - "contents": "", - "bgcolor": "1" - }, - "22,54": { - "contents": "", - "bgcolor": "1" - }, - "22,55": { - "contents": "", - "bgcolor": "1" - }, - "22,56": { - "contents": "", - "bgcolor": "1" - }, - "22,57": { - "contents": "", - "bgcolor": "1" - }, - "22,58": { - "contents": "", - "bgcolor": "1" - }, - "22,59": { - "contents": "", - "bgcolor": "1" - }, - "22,6": { - "contents": "", - "bgcolor": "1" - }, - "22,60": { - "contents": "", - "bgcolor": "1" - }, - "22,61": { - "contents": "", - "bgcolor": "1" - }, - "22,62": { - "contents": "", - "bgcolor": "1" - }, - "22,63": { - "contents": "", - "bgcolor": "1" - }, - "22,64": { - "contents": "", - "bgcolor": "1" - }, - "22,65": { - "contents": "", - "bgcolor": "1" - }, - "22,66": { - "contents": "", - "bgcolor": "1" - }, - "22,67": { - "contents": "", - "bgcolor": "1" - }, - "22,68": { - "contents": "", - "bgcolor": "1" - }, - "22,69": { - "contents": "", - "bgcolor": "1" - }, - "22,7": { - "contents": "", - "bgcolor": "1" - }, - "22,70": { - "contents": "", - "bgcolor": "1" - }, - "22,71": { - "contents": "", - "bgcolor": "1" - }, - "22,72": { - "contents": "", - "bgcolor": "1" - }, - "22,73": { - "contents": "", - "bgcolor": "1" - }, - "22,74": { - "contents": "", - "bgcolor": "1" - }, - "22,75": { - "contents": "", - "bgcolor": "1" - }, - "22,76": { - "contents": "", - "bgcolor": "1" - }, - "22,77": { - "contents": "", - "bgcolor": "1" - }, - "22,78": { - "contents": "", - "bgcolor": "1" - }, - "22,79": { - "contents": "", - "bgcolor": "1" - }, - "22,8": { - "contents": "", - "bgcolor": "1" - }, - "22,9": { - "contents": "", - "bgcolor": "1" - }, - "23,0": { - "contents": "", - "bgcolor": "1" - }, - "23,1": { - "contents": "", - "bgcolor": "1" - }, - "23,10": { - "contents": "", - "bgcolor": "1" - }, - "23,11": { - "contents": "", - "bgcolor": "1" - }, - "23,12": { - "contents": "", - "bgcolor": "1" - }, - "23,13": { - "contents": "", - "bgcolor": "1" - }, - "23,14": { - "contents": "", - "bgcolor": "1" - }, - "23,15": { - "contents": "", - "bgcolor": "1" - }, - "23,16": { - "contents": "", - "bgcolor": "1" - }, - "23,17": { - "contents": "", - "bgcolor": "1" - }, - "23,18": { - "contents": "", - "bgcolor": "1" - }, - "23,19": { - "contents": "", - "bgcolor": "1" - }, - "23,2": { - "contents": "", - "bgcolor": "1" - }, - "23,20": { - "contents": "", - "bgcolor": "1" - }, - "23,21": { - "contents": "", - "bgcolor": "1" - }, - "23,22": { - "contents": "", - "bgcolor": "1" - }, - "23,23": { - "contents": "", - "bgcolor": "1" - }, - "23,24": { - "contents": "", - "bgcolor": "1" - }, - "23,25": { - "contents": "", - "bgcolor": "1" - }, - "23,26": { - "contents": "", - "bgcolor": "1" - }, - "23,27": { - "contents": "", - "bgcolor": "1" - }, - "23,28": { - "contents": "", - "bgcolor": "1" - }, - "23,29": { - "contents": "", - "bgcolor": "1" - }, - "23,3": { - "contents": "", - "bgcolor": "1" - }, - "23,30": { - "contents": "", - "bgcolor": "1" - }, - "23,31": { - "contents": "", - "bgcolor": "1" - }, - "23,32": { - "contents": "", - "bgcolor": "1" - }, - "23,33": { - "contents": "", - "bgcolor": "1" - }, - "23,34": { - "contents": "", - "bgcolor": "1" - }, - "23,35": { - "contents": "", - "bgcolor": "1" - }, - "23,36": { - "contents": "", - "bgcolor": "1" - }, - "23,37": { - "contents": "", - "bgcolor": "1" - }, - "23,38": { - "contents": "", - "bgcolor": "1" - }, - "23,39": { - "contents": "", - "bgcolor": "1" - }, - "23,4": { - "contents": "", - "bgcolor": "1" - }, - "23,40": { - "contents": "", - "bgcolor": "1" - }, - "23,41": { - "contents": "", - "bgcolor": "1" - }, - "23,42": { - "contents": "", - "bgcolor": "1" - }, - "23,43": { - "contents": "", - "bgcolor": "1" - }, - "23,44": { - "contents": "", - "bgcolor": "1" - }, - "23,45": { - "contents": "", - "bgcolor": "1" - }, - "23,46": { - "contents": "", - "bgcolor": "1" - }, - "23,47": { - "contents": "", - "bgcolor": "1" - }, - "23,48": { - "contents": "", - "bgcolor": "1" - }, - "23,49": { - "contents": "", - "bgcolor": "1" - }, - "23,5": { - "contents": "", - "bgcolor": "1" - }, - "23,50": { - "contents": "", - "bgcolor": "1" - }, - "23,51": { - "contents": "", - "bgcolor": "1" - }, - "23,52": { - "contents": "", - "bgcolor": "1" - }, - "23,53": { - "contents": "", - "bgcolor": "1" - }, - "23,54": { - "contents": "", - "bgcolor": "1" - }, - "23,55": { - "contents": "", - "bgcolor": "1" - }, - "23,56": { - "contents": "", - "bgcolor": "1" - }, - "23,57": { - "contents": "", - "bgcolor": "1" - }, - "23,58": { - "contents": "", - "bgcolor": "1" - }, - "23,59": { - "contents": "", - "bgcolor": "1" - }, - "23,6": { - "contents": "", - "bgcolor": "1" - }, - "23,60": { - "contents": "", - "bgcolor": "1" - }, - "23,61": { - "contents": "", - "bgcolor": "1" - }, - "23,62": { - "contents": "", - "bgcolor": "1" - }, - "23,63": { - "contents": "", - "bgcolor": "1" - }, - "23,64": { - "contents": "", - "bgcolor": "1" - }, - "23,65": { - "contents": "", - "bgcolor": "1" - }, - "23,66": { - "contents": "", - "bgcolor": "1" - }, - "23,67": { - "contents": "", - "bgcolor": "1" - }, - "23,68": { - "contents": "", - "bgcolor": "1" - }, - "23,69": { - "contents": "", - "bgcolor": "1" - }, - "23,7": { - "contents": "", - "bgcolor": "1" - }, - "23,70": { - "contents": "", - "bgcolor": "1" - }, - "23,71": { - "contents": "", - "bgcolor": "1" - }, - "23,72": { - "contents": "", - "bgcolor": "1" - }, - "23,73": { - "contents": "", - "bgcolor": "1" - }, - "23,74": { - "contents": "", - "bgcolor": "1" - }, - "23,75": { - "contents": "", - "bgcolor": "1" - }, - "23,76": { - "contents": "", - "bgcolor": "1" - }, - "23,77": { - "contents": "", - "bgcolor": "1" - }, - "23,78": { - "contents": "", - "bgcolor": "1" - }, - "23,79": { - "contents": "", - "bgcolor": "1" - }, - "23,8": { - "contents": "", - "bgcolor": "1" - }, - "23,9": { - "contents": "", - "bgcolor": "1" - }, - "3,0": { - "contents": "", - "bgcolor": "1" - }, - "3,1": { - "contents": "", - "bgcolor": "1" - }, - "3,10": { - "contents": "", - "bgcolor": "1" - }, - "3,11": { - "contents": "", - "bgcolor": "1" - }, - "3,12": { - "contents": "", - "bgcolor": "1" - }, - "3,13": { - "contents": "", - "bgcolor": "1" - }, - "3,14": { - "contents": "", - "bgcolor": "1" - }, - "3,15": { - "contents": "", - "bgcolor": "1" - }, - "3,16": { - "contents": "", - "bgcolor": "1" - }, - "3,17": { - "contents": "", - "bgcolor": "1" - }, - "3,18": { - "contents": "", - "bgcolor": "1" - }, - "3,19": { - "contents": "", - "bgcolor": "1" - }, - "3,2": { - "contents": "", - "bgcolor": "1" - }, - "3,20": { - "contents": "", - "bgcolor": "1" - }, - "3,21": { - "contents": "", - "bgcolor": "1" - }, - "3,22": { - "contents": "", - "bgcolor": "1" - }, - "3,23": { - "contents": "", - "bgcolor": "1" - }, - "3,24": { - "contents": "", - "bgcolor": "1" - }, - "3,25": { - "contents": "", - "bgcolor": "1" - }, - "3,26": { - "contents": "", - "bgcolor": "1" - }, - "3,27": { - "contents": "", - "bgcolor": "1" - }, - "3,28": { - "contents": "", - "bgcolor": "1" - }, - "3,29": { - "contents": "", - "bgcolor": "1" - }, - "3,3": { - "contents": "", - "bgcolor": "1" - }, - "3,30": { - "contents": "", - "bgcolor": "1" - }, - "3,31": { - "contents": "", - "bgcolor": "1" - }, - "3,32": { - "contents": "", - "bgcolor": "1" - }, - "3,33": { - "contents": "", - "bgcolor": "1" - }, - "3,34": { - "contents": "", - "bgcolor": "1" - }, - "3,35": { - "contents": "", - "bgcolor": "1" - }, - "3,36": { - "contents": "", - "bgcolor": "1" - }, - "3,37": { - "contents": "", - "bgcolor": "1" - }, - "3,38": { - "contents": "", - "bgcolor": "1" - }, - "3,39": { - "contents": "", - "bgcolor": "1" - }, - "3,4": { - "contents": "", - "bgcolor": "1" - }, - "3,40": { - "contents": "", - "bgcolor": "1" - }, - "3,41": { - "contents": "", - "bgcolor": "1" - }, - "3,42": { - "contents": "", - "bgcolor": "1" - }, - "3,43": { - "contents": "", - "bgcolor": "1" - }, - "3,44": { - "contents": "", - "bgcolor": "1" - }, - "3,45": { - "contents": "", - "bgcolor": "1" - }, - "3,46": { - "contents": "", - "bgcolor": "1" - }, - "3,47": { - "contents": "", - "bgcolor": "1" - }, - "3,48": { - "contents": "", - "bgcolor": "1" - }, - "3,49": { - "contents": "", - "bgcolor": "1" - }, - "3,5": { - "contents": "", - "bgcolor": "1" - }, - "3,50": { - "contents": "", - "bgcolor": "1" - }, - "3,51": { - "contents": "", - "bgcolor": "1" - }, - "3,52": { - "contents": "", - "bgcolor": "1" - }, - "3,53": { - "contents": "", - "bgcolor": "1" - }, - "3,54": { - "contents": "", - "bgcolor": "1" - }, - "3,55": { - "contents": "", - "bgcolor": "1" - }, - "3,56": { - "contents": "", - "bgcolor": "1" - }, - "3,57": { - "contents": "", - "bgcolor": "1" - }, - "3,58": { - "contents": "", - "bgcolor": "1" - }, - "3,59": { - "contents": "", - "bgcolor": "1" - }, - "3,6": { - "contents": "", - "bgcolor": "1" - }, - "3,60": { - "contents": "", - "bgcolor": "1" - }, - "3,61": { - "contents": "", - "bgcolor": "1" - }, - "3,62": { - "contents": "", - "bgcolor": "1" - }, - "3,63": { - "contents": "", - "bgcolor": "1" - }, - "3,64": { - "contents": "", - "bgcolor": "1" - }, - "3,65": { - "contents": "", - "bgcolor": "1" - }, - "3,66": { - "contents": "", - "bgcolor": "1" - }, - "3,67": { - "contents": "", - "bgcolor": "1" - }, - "3,68": { - "contents": "", - "bgcolor": "1" - }, - "3,69": { - "contents": "", - "bgcolor": "1" - }, - "3,7": { - "contents": "", - "bgcolor": "1" - }, - "3,70": { - "contents": "", - "bgcolor": "1" - }, - "3,71": { - "contents": "", - "bgcolor": "1" - }, - "3,72": { - "contents": "", - "bgcolor": "1" - }, - "3,73": { - "contents": "", - "bgcolor": "1" - }, - "3,74": { - "contents": "", - "bgcolor": "1" - }, - "3,75": { - "contents": "", - "bgcolor": "1" - }, - "3,76": { - "contents": "", - "bgcolor": "1" - }, - "3,77": { - "contents": "", - "bgcolor": "1" - }, - "3,78": { - "contents": "", - "bgcolor": "1" - }, - "3,79": { - "contents": "", - "bgcolor": "1" - }, - "3,8": { - "contents": "", - "bgcolor": "1" - }, - "3,9": { - "contents": "", - "bgcolor": "1" - }, - "4,0": { - "contents": "", - "bgcolor": "1" - }, - "4,1": { - "contents": "", - "bgcolor": "1" - }, - "4,10": { - "contents": "", - "bgcolor": "1" - }, - "4,11": { - "contents": "", - "bgcolor": "1" - }, - "4,12": { - "contents": "", - "bgcolor": "1" - }, - "4,13": { - "contents": "", - "bgcolor": "1" - }, - "4,14": { - "contents": "", - "bgcolor": "1" - }, - "4,15": { - "contents": "", - "bgcolor": "1" - }, - "4,16": { - "contents": "", - "bgcolor": "1" - }, - "4,17": { - "contents": "", - "bgcolor": "1" - }, - "4,18": { - "contents": "", - "bgcolor": "1" - }, - "4,19": { - "contents": "", - "bgcolor": "1" - }, - "4,2": { - "contents": "", - "bgcolor": "1" - }, - "4,20": { - "contents": "", - "bgcolor": "1" - }, - "4,21": { - "contents": "", - "bgcolor": "1" - }, - "4,22": { - "contents": "", - "bgcolor": "1" - }, - "4,23": { - "contents": "", - "bgcolor": "1" - }, - "4,24": { - "contents": "", - "bgcolor": "1" - }, - "4,25": { - "contents": "", - "bgcolor": "1" - }, - "4,26": { - "contents": "", - "bgcolor": "1" - }, - "4,27": { - "contents": "", - "bgcolor": "1" - }, - "4,28": { - "contents": "", - "bgcolor": "1" - }, - "4,29": { - "contents": "", - "bgcolor": "1" - }, - "4,3": { - "contents": "", - "bgcolor": "1" - }, - "4,30": { - "contents": "", - "bgcolor": "1" - }, - "4,31": { - "contents": "", - "bgcolor": "1" - }, - "4,32": { - "contents": "", - "bgcolor": "1" - }, - "4,33": { - "contents": "", - "bgcolor": "1" - }, - "4,34": { - "contents": "", - "bgcolor": "1" - }, - "4,35": { - "contents": "", - "bgcolor": "1" - }, - "4,36": { - "contents": "", - "bgcolor": "1" - }, - "4,37": { - "contents": "", - "bgcolor": "1" - }, - "4,38": { - "contents": "", - "bgcolor": "1" - }, - "4,39": { - "contents": "", - "bgcolor": "1" - }, - "4,4": { - "contents": "", - "bgcolor": "1" - }, - "4,40": { - "contents": "", - "bgcolor": "1" - }, - "4,41": { - "contents": "", - "bgcolor": "1" - }, - "4,42": { - "contents": "", - "bgcolor": "1" - }, - "4,43": { - "contents": "", - "bgcolor": "1" - }, - "4,44": { - "contents": "", - "bgcolor": "1" - }, - "4,45": { - "contents": "", - "bgcolor": "1" - }, - "4,46": { - "contents": "", - "bgcolor": "1" - }, - "4,47": { - "contents": "", - "bgcolor": "1" - }, - "4,48": { - "contents": "", - "bgcolor": "1" - }, - "4,49": { - "contents": "", - "bgcolor": "1" - }, - "4,5": { - "contents": "", - "bgcolor": "1" - }, - "4,50": { - "contents": "", - "bgcolor": "1" - }, - "4,51": { - "contents": "", - "bgcolor": "1" - }, - "4,52": { - "contents": "", - "bgcolor": "1" - }, - "4,53": { - "contents": "", - "bgcolor": "1" - }, - "4,54": { - "contents": "", - "bgcolor": "1" - }, - "4,55": { - "contents": "", - "bgcolor": "1" - }, - "4,56": { - "contents": "", - "bgcolor": "1" - }, - "4,57": { - "contents": "", - "bgcolor": "1" - }, - "4,58": { - "contents": "", - "bgcolor": "1" - }, - "4,59": { - "contents": "", - "bgcolor": "1" - }, - "4,6": { - "contents": "", - "bgcolor": "1" - }, - "4,60": { - "contents": "", - "bgcolor": "1" - }, - "4,61": { - "contents": "", - "bgcolor": "1" - }, - "4,62": { - "contents": "", - "bgcolor": "1" - }, - "4,63": { - "contents": "", - "bgcolor": "1" - }, - "4,64": { - "contents": "", - "bgcolor": "1" - }, - "4,65": { - "contents": "", - "bgcolor": "1" - }, - "4,66": { - "contents": "", - "bgcolor": "1" - }, - "4,67": { - "contents": "", - "bgcolor": "1" - }, - "4,68": { - "contents": "", - "bgcolor": "1" - }, - "4,69": { - "contents": "", - "bgcolor": "1" - }, - "4,7": { - "contents": "", - "bgcolor": "1" - }, - "4,70": { - "contents": "", - "bgcolor": "1" - }, - "4,71": { - "contents": "", - "bgcolor": "1" - }, - "4,72": { - "contents": "", - "bgcolor": "1" - }, - "4,73": { - "contents": "", - "bgcolor": "1" - }, - "4,74": { - "contents": "", - "bgcolor": "1" - }, - "4,75": { - "contents": "", - "bgcolor": "1" - }, - "4,76": { - "contents": "", - "bgcolor": "1" - }, - "4,77": { - "contents": "", - "bgcolor": "1" - }, - "4,78": { - "contents": "", - "bgcolor": "1" - }, - "4,79": { - "contents": "", - "bgcolor": "1" - }, - "4,8": { - "contents": "", - "bgcolor": "1" - }, - "4,9": { - "contents": "", - "bgcolor": "1" - }, - "5,0": { - "contents": "", - "bgcolor": "1" - }, - "5,1": { - "contents": "", - "bgcolor": "1" - }, - "5,10": { - "contents": "", - "bgcolor": "1" - }, - "5,11": { - "contents": "", - "bgcolor": "1" - }, - "5,12": { - "contents": "", - "bgcolor": "1" - }, - "5,13": { - "contents": "", - "bgcolor": "1" - }, - "5,14": { - "contents": "", - "bgcolor": "1" - }, - "5,15": { - "contents": "", - "bgcolor": "1" - }, - "5,16": { - "contents": "", - "bgcolor": "1" - }, - "5,17": { - "contents": "", - "bgcolor": "1" - }, - "5,18": { - "contents": "", - "bgcolor": "1" - }, - "5,19": { - "contents": "", - "bgcolor": "1" - }, - "5,2": { - "contents": "", - "bgcolor": "1" - }, - "5,20": { - "contents": "", - "bgcolor": "1" - }, - "5,21": { - "contents": "", - "bgcolor": "1" - }, - "5,22": { - "contents": "", - "bgcolor": "1" - }, - "5,23": { - "contents": "", - "bgcolor": "1" - }, - "5,24": { - "contents": "", - "bgcolor": "1" - }, - "5,25": { - "contents": "", - "bgcolor": "1" - }, - "5,26": { - "contents": "", - "bgcolor": "1" - }, - "5,27": { - "contents": "", - "bgcolor": "1" - }, - "5,28": { - "contents": "", - "bgcolor": "1" - }, - "5,29": { - "contents": "", - "bgcolor": "1" - }, - "5,3": { - "contents": "", - "bgcolor": "1" - }, - "5,30": { - "contents": "", - "bgcolor": "1" - }, - "5,31": { - "contents": "", - "bgcolor": "1" - }, - "5,32": { - "contents": "", - "bgcolor": "1" - }, - "5,33": { - "contents": "", - "bgcolor": "1" - }, - "5,34": { - "contents": "", - "bgcolor": "1" - }, - "5,35": { - "contents": "", - "bgcolor": "1" - }, - "5,36": { - "contents": "", - "bgcolor": "1" - }, - "5,37": { - "contents": "", - "bgcolor": "1" - }, - "5,38": { - "contents": "", - "bgcolor": "1" - }, - "5,39": { - "contents": "", - "bgcolor": "1" - }, - "5,4": { - "contents": "", - "bgcolor": "1" - }, - "5,40": { - "contents": "", - "bgcolor": "1" - }, - "5,41": { - "contents": "", - "bgcolor": "1" - }, - "5,42": { - "contents": "", - "bgcolor": "1" - }, - "5,43": { - "contents": "", - "bgcolor": "1" - }, - "5,44": { - "contents": "", - "bgcolor": "1" - }, - "5,45": { - "contents": "", - "bgcolor": "1" - }, - "5,46": { - "contents": "", - "bgcolor": "1" - }, - "5,47": { - "contents": "", - "bgcolor": "1" - }, - "5,48": { - "contents": "", - "bgcolor": "1" - }, - "5,49": { - "contents": "", - "bgcolor": "1" - }, - "5,5": { - "contents": "", - "bgcolor": "1" - }, - "5,50": { - "contents": "", - "bgcolor": "1" - }, - "5,51": { - "contents": "", - "bgcolor": "1" - }, - "5,52": { - "contents": "", - "bgcolor": "1" - }, - "5,53": { - "contents": "", - "bgcolor": "1" - }, - "5,54": { - "contents": "", - "bgcolor": "1" - }, - "5,55": { - "contents": "", - "bgcolor": "1" - }, - "5,56": { - "contents": "", - "bgcolor": "1" - }, - "5,57": { - "contents": "", - "bgcolor": "1" - }, - "5,58": { - "contents": "", - "bgcolor": "1" - }, - "5,59": { - "contents": "", - "bgcolor": "1" - }, - "5,6": { - "contents": "", - "bgcolor": "1" - }, - "5,60": { - "contents": "", - "bgcolor": "1" - }, - "5,61": { - "contents": "", - "bgcolor": "1" - }, - "5,62": { - "contents": "", - "bgcolor": "1" - }, - "5,63": { - "contents": "", - "bgcolor": "1" - }, - "5,64": { - "contents": "", - "bgcolor": "1" - }, - "5,65": { - "contents": "", - "bgcolor": "1" - }, - "5,66": { - "contents": "", - "bgcolor": "1" - }, - "5,67": { - "contents": "", - "bgcolor": "1" - }, - "5,68": { - "contents": "", - "bgcolor": "1" - }, - "5,69": { - "contents": "", - "bgcolor": "1" - }, - "5,7": { - "contents": "", - "bgcolor": "1" - }, - "5,70": { - "contents": "", - "bgcolor": "1" - }, - "5,71": { - "contents": "", - "bgcolor": "1" - }, - "5,72": { - "contents": "", - "bgcolor": "1" - }, - "5,73": { - "contents": "", - "bgcolor": "1" - }, - "5,74": { - "contents": "", - "bgcolor": "1" - }, - "5,75": { - "contents": "", - "bgcolor": "1" - }, - "5,76": { - "contents": "", - "bgcolor": "1" - }, - "5,77": { - "contents": "", - "bgcolor": "1" - }, - "5,78": { - "contents": "", - "bgcolor": "1" - }, - "5,79": { - "contents": "", - "bgcolor": "1" - }, - "5,8": { - "contents": "", - "bgcolor": "1" - }, - "5,9": { - "contents": "", - "bgcolor": "1" - }, - "6,0": { - "contents": "", - "bgcolor": "1" - }, - "6,1": { - "contents": "", - "bgcolor": "1" - }, - "6,10": { - "contents": "", - "bgcolor": "1" - }, - "6,11": { - "contents": "", - "bgcolor": "1" - }, - "6,12": { - "contents": "", - "bgcolor": "1" - }, - "6,13": { - "contents": "", - "bgcolor": "1" - }, - "6,14": { - "contents": "", - "bgcolor": "1" - }, - "6,15": { - "contents": "", - "bgcolor": "1" - }, - "6,16": { - "contents": "", - "bgcolor": "1" - }, - "6,17": { - "contents": "", - "bgcolor": "1" - }, - "6,18": { - "contents": "", - "bgcolor": "1" - }, - "6,19": { - "contents": "", - "bgcolor": "1" - }, - "6,2": { - "contents": "", - "bgcolor": "1" - }, - "6,20": { - "contents": "", - "bgcolor": "1" - }, - "6,21": { - "contents": "", - "bgcolor": "1" - }, - "6,22": { - "contents": "", - "bgcolor": "1" - }, - "6,23": { - "contents": "", - "bgcolor": "1" - }, - "6,24": { - "contents": "", - "bgcolor": "1" - }, - "6,25": { - "contents": "", - "bgcolor": "1" - }, - "6,26": { - "contents": "", - "bgcolor": "1" - }, - "6,27": { - "contents": "", - "bgcolor": "1" - }, - "6,28": { - "contents": "", - "bgcolor": "1" - }, - "6,29": { - "contents": "", - "bgcolor": "1" - }, - "6,3": { - "contents": "", - "bgcolor": "1" - }, - "6,30": { - "contents": "", - "bgcolor": "1" - }, - "6,31": { - "contents": "", - "bgcolor": "1" - }, - "6,32": { - "contents": "", - "bgcolor": "1" - }, - "6,33": { - "contents": "", - "bgcolor": "1" - }, - "6,34": { - "contents": "", - "bgcolor": "1" - }, - "6,35": { - "contents": "", - "bgcolor": "1" - }, - "6,36": { - "contents": "", - "bgcolor": "1" - }, - "6,37": { - "contents": "", - "bgcolor": "1" - }, - "6,38": { - "contents": "", - "bgcolor": "1" - }, - "6,39": { - "contents": "", - "bgcolor": "1" - }, - "6,4": { - "contents": "", - "bgcolor": "1" - }, - "6,40": { - "contents": "", - "bgcolor": "1" - }, - "6,41": { - "contents": "", - "bgcolor": "1" - }, - "6,42": { - "contents": "", - "bgcolor": "1" - }, - "6,43": { - "contents": "", - "bgcolor": "1" - }, - "6,44": { - "contents": "", - "bgcolor": "1" - }, - "6,45": { - "contents": "", - "bgcolor": "1" - }, - "6,46": { - "contents": "", - "bgcolor": "1" - }, - "6,47": { - "contents": "", - "bgcolor": "1" - }, - "6,48": { - "contents": "", - "bgcolor": "1" - }, - "6,49": { - "contents": "", - "bgcolor": "1" - }, - "6,5": { - "contents": "", - "bgcolor": "1" - }, - "6,50": { - "contents": "", - "bgcolor": "1" - }, - "6,51": { - "contents": "", - "bgcolor": "1" - }, - "6,52": { - "contents": "", - "bgcolor": "1" - }, - "6,53": { - "contents": "", - "bgcolor": "1" - }, - "6,54": { - "contents": "", - "bgcolor": "1" - }, - "6,55": { - "contents": "", - "bgcolor": "1" - }, - "6,56": { - "contents": "", - "bgcolor": "1" - }, - "6,57": { - "contents": "", - "bgcolor": "1" - }, - "6,58": { - "contents": "", - "bgcolor": "1" - }, - "6,59": { - "contents": "", - "bgcolor": "1" - }, - "6,6": { - "contents": "", - "bgcolor": "1" - }, - "6,60": { - "contents": "", - "bgcolor": "1" - }, - "6,61": { - "contents": "", - "bgcolor": "1" - }, - "6,62": { - "contents": "", - "bgcolor": "1" - }, - "6,63": { - "contents": "", - "bgcolor": "1" - }, - "6,64": { - "contents": "", - "bgcolor": "1" - }, - "6,65": { - "contents": "", - "bgcolor": "1" - }, - "6,66": { - "contents": "", - "bgcolor": "1" - }, - "6,67": { - "contents": "", - "bgcolor": "1" - }, - "6,68": { - "contents": "", - "bgcolor": "1" - }, - "6,69": { - "contents": "", - "bgcolor": "1" - }, - "6,7": { - "contents": "", - "bgcolor": "1" - }, - "6,70": { - "contents": "", - "bgcolor": "1" - }, - "6,71": { - "contents": "", - "bgcolor": "1" - }, - "6,72": { - "contents": "", - "bgcolor": "1" - }, - "6,73": { - "contents": "", - "bgcolor": "1" - }, - "6,74": { - "contents": "", - "bgcolor": "1" - }, - "6,75": { - "contents": "", - "bgcolor": "1" - }, - "6,76": { - "contents": "", - "bgcolor": "1" - }, - "6,77": { - "contents": "", - "bgcolor": "1" - }, - "6,78": { - "contents": "", - "bgcolor": "1" - }, - "6,79": { - "contents": "", - "bgcolor": "1" - }, - "6,8": { - "contents": "", - "bgcolor": "1" - }, - "6,9": { - "contents": "", - "bgcolor": "1" - }, - "7,0": { - "contents": "", - "bgcolor": "1" - }, - "7,1": { - "contents": "", - "bgcolor": "1" - }, - "7,10": { - "contents": "", - "bgcolor": "1" - }, - "7,11": { - "contents": "", - "bgcolor": "1" - }, - "7,12": { - "contents": "", - "bgcolor": "1" - }, - "7,13": { - "contents": "", - "bgcolor": "1" - }, - "7,14": { - "contents": "", - "bgcolor": "1" - }, - "7,15": { - "contents": "", - "bgcolor": "1" - }, - "7,16": { - "contents": "", - "bgcolor": "1" - }, - "7,17": { - "contents": "", - "bgcolor": "1" - }, - "7,18": { - "contents": "", - "bgcolor": "1" - }, - "7,19": { - "contents": "", - "bgcolor": "1" - }, - "7,2": { - "contents": "", - "bgcolor": "1" - }, - "7,20": { - "contents": "", - "bgcolor": "1" - }, - "7,21": { - "contents": "", - "bgcolor": "1" - }, - "7,22": { - "contents": "", - "bgcolor": "1" - }, - "7,23": { - "contents": "", - "bgcolor": "1" - }, - "7,24": { - "contents": "", - "bgcolor": "1" - }, - "7,25": { - "contents": "", - "bgcolor": "1" - }, - "7,26": { - "contents": "", - "bgcolor": "1" - }, - "7,27": { - "contents": "", - "bgcolor": "1" - }, - "7,28": { - "contents": "", - "bgcolor": "1" - }, - "7,29": { - "contents": "", - "bgcolor": "1" - }, - "7,3": { - "contents": "", - "bgcolor": "1" - }, - "7,30": { - "contents": "", - "bgcolor": "1" - }, - "7,31": { - "contents": "", - "bgcolor": "1" - }, - "7,32": { - "contents": "", - "bgcolor": "1" - }, - "7,33": { - "contents": "", - "bgcolor": "1" - }, - "7,34": { - "contents": "", - "bgcolor": "1" - }, - "7,35": { - "contents": "", - "bgcolor": "1" - }, - "7,36": { - "contents": "", - "bgcolor": "1" - }, - "7,37": { - "contents": "", - "bgcolor": "1" - }, - "7,38": { - "contents": "", - "bgcolor": "1" - }, - "7,39": { - "contents": "", - "bgcolor": "1" - }, - "7,4": { - "contents": "", - "bgcolor": "1" - }, - "7,40": { - "contents": "", - "bgcolor": "1" - }, - "7,41": { - "contents": "", - "bgcolor": "1" - }, - "7,42": { - "contents": "", - "bgcolor": "1" - }, - "7,43": { - "contents": "", - "bgcolor": "1" - }, - "7,44": { - "contents": "", - "bgcolor": "1" - }, - "7,45": { - "contents": "", - "bgcolor": "1" - }, - "7,46": { - "contents": "", - "bgcolor": "1" - }, - "7,47": { - "contents": "", - "bgcolor": "1" - }, - "7,48": { - "contents": "", - "bgcolor": "1" - }, - "7,49": { - "contents": "", - "bgcolor": "1" - }, - "7,5": { - "contents": "", - "bgcolor": "1" - }, - "7,50": { - "contents": "", - "bgcolor": "1" - }, - "7,51": { - "contents": "", - "bgcolor": "1" - }, - "7,52": { - "contents": "", - "bgcolor": "1" - }, - "7,53": { - "contents": "", - "bgcolor": "1" - }, - "7,54": { - "contents": "", - "bgcolor": "1" - }, - "7,55": { - "contents": "", - "bgcolor": "1" - }, - "7,56": { - "contents": "", - "bgcolor": "1" - }, - "7,57": { - "contents": "", - "bgcolor": "1" - }, - "7,58": { - "contents": "", - "bgcolor": "1" - }, - "7,59": { - "contents": "", - "bgcolor": "1" - }, - "7,6": { - "contents": "", - "bgcolor": "1" - }, - "7,60": { - "contents": "", - "bgcolor": "1" - }, - "7,61": { - "contents": "", - "bgcolor": "1" - }, - "7,62": { - "contents": "", - "bgcolor": "1" - }, - "7,63": { - "contents": "", - "bgcolor": "1" - }, - "7,64": { - "contents": "", - "bgcolor": "1" - }, - "7,65": { - "contents": "", - "bgcolor": "1" - }, - "7,66": { - "contents": "", - "bgcolor": "1" - }, - "7,67": { - "contents": "", - "bgcolor": "1" - }, - "7,68": { - "contents": "", - "bgcolor": "1" - }, - "7,69": { - "contents": "", - "bgcolor": "1" - }, - "7,7": { - "contents": "", - "bgcolor": "1" - }, - "7,70": { - "contents": "", - "bgcolor": "1" - }, - "7,71": { - "contents": "", - "bgcolor": "1" - }, - "7,72": { - "contents": "", - "bgcolor": "1" - }, - "7,73": { - "contents": "", - "bgcolor": "1" - }, - "7,74": { - "contents": "", - "bgcolor": "1" - }, - "7,75": { - "contents": "", - "bgcolor": "1" - }, - "7,76": { - "contents": "", - "bgcolor": "1" - }, - "7,77": { - "contents": "", - "bgcolor": "1" - }, - "7,78": { - "contents": "", - "bgcolor": "1" - }, - "7,79": { - "contents": "", - "bgcolor": "1" - }, - "7,8": { - "contents": "", - "bgcolor": "1" - }, - "7,9": { - "contents": "", - "bgcolor": "1" - }, - "8,0": { - "contents": "", - "bgcolor": "1" - }, - "8,1": { - "contents": "", - "bgcolor": "1" - }, - "8,10": { - "contents": "", - "bgcolor": "1" - }, - "8,11": { - "contents": "", - "bgcolor": "1" - }, - "8,12": { - "contents": "", - "bgcolor": "1" - }, - "8,13": { - "contents": "", - "bgcolor": "1" - }, - "8,14": { - "contents": "", - "bgcolor": "1" - }, - "8,15": { - "contents": "", - "bgcolor": "1" - }, - "8,16": { - "contents": "", - "bgcolor": "1" - }, - "8,17": { - "contents": "", - "bgcolor": "1" - }, - "8,18": { - "contents": "", - "bgcolor": "1" - }, - "8,19": { - "contents": "", - "bgcolor": "1" - }, - "8,2": { - "contents": "", - "bgcolor": "1" - }, - "8,20": { - "contents": "", - "bgcolor": "1" - }, - "8,21": { - "contents": "", - "bgcolor": "1" - }, - "8,22": { - "contents": "", - "bgcolor": "1" - }, - "8,23": { - "contents": "", - "bgcolor": "1" - }, - "8,24": { - "contents": "", - "bgcolor": "1" - }, - "8,25": { - "contents": "", - "bgcolor": "1" - }, - "8,26": { - "contents": "", - "bgcolor": "1" - }, - "8,27": { - "contents": "", - "bgcolor": "1" - }, - "8,28": { - "contents": "", - "bgcolor": "1" - }, - "8,29": { - "contents": "", - "bgcolor": "1" - }, - "8,3": { - "contents": "", - "bgcolor": "1" - }, - "8,30": { - "contents": "", - "bgcolor": "1" - }, - "8,31": { - "contents": "", - "bgcolor": "1" - }, - "8,32": { - "contents": "", - "bgcolor": "1" - }, - "8,33": { - "contents": "", - "bgcolor": "1" - }, - "8,34": { - "contents": "", - "bgcolor": "1" - }, - "8,35": { - "contents": "", - "bgcolor": "1" - }, - "8,36": { - "contents": "", - "bgcolor": "1" - }, - "8,37": { - "contents": "", - "bgcolor": "1" - }, - "8,38": { - "contents": "", - "bgcolor": "1" - }, - "8,39": { - "contents": "", - "bgcolor": "1" - }, - "8,4": { - "contents": "", - "bgcolor": "1" - }, - "8,40": { - "contents": "", - "bgcolor": "1" - }, - "8,41": { - "contents": "", - "bgcolor": "1" - }, - "8,42": { - "contents": "", - "bgcolor": "1" - }, - "8,43": { - "contents": "", - "bgcolor": "1" - }, - "8,44": { - "contents": "", - "bgcolor": "1" - }, - "8,45": { - "contents": "", - "bgcolor": "1" - }, - "8,46": { - "contents": "", - "bgcolor": "1" - }, - "8,47": { - "contents": "", - "bgcolor": "1" - }, - "8,48": { - "contents": "", - "bgcolor": "1" - }, - "8,49": { - "contents": "", - "bgcolor": "1" - }, - "8,5": { - "contents": "", - "bgcolor": "1" - }, - "8,50": { - "contents": "", - "bgcolor": "1" - }, - "8,51": { - "contents": "", - "bgcolor": "1" - }, - "8,52": { - "contents": "", - "bgcolor": "1" - }, - "8,53": { - "contents": "", - "bgcolor": "1" - }, - "8,54": { - "contents": "", - "bgcolor": "1" - }, - "8,55": { - "contents": "", - "bgcolor": "1" - }, - "8,56": { - "contents": "", - "bgcolor": "1" - }, - "8,57": { - "contents": "", - "bgcolor": "1" - }, - "8,58": { - "contents": "", - "bgcolor": "1" - }, - "8,59": { - "contents": "", - "bgcolor": "1" - }, - "8,6": { - "contents": "", - "bgcolor": "1" - }, - "8,60": { - "contents": "", - "bgcolor": "1" - }, - "8,61": { - "contents": "", - "bgcolor": "1" - }, - "8,62": { - "contents": "", - "bgcolor": "1" - }, - "8,63": { - "contents": "", - "bgcolor": "1" - }, - "8,64": { - "contents": "", - "bgcolor": "1" - }, - "8,65": { - "contents": "", - "bgcolor": "1" - }, - "8,66": { - "contents": "", - "bgcolor": "1" - }, - "8,67": { - "contents": "", - "bgcolor": "1" - }, - "8,68": { - "contents": "", - "bgcolor": "1" - }, - "8,69": { - "contents": "", - "bgcolor": "1" - }, - "8,7": { - "contents": "", - "bgcolor": "1" - }, - "8,70": { - "contents": "", - "bgcolor": "1" - }, - "8,71": { - "contents": "", - "bgcolor": "1" - }, - "8,72": { - "contents": "", - "bgcolor": "1" - }, - "8,73": { - "contents": "", - "bgcolor": "1" - }, - "8,74": { - "contents": "", - "bgcolor": "1" - }, - "8,75": { - "contents": "", - "bgcolor": "1" - }, - "8,76": { - "contents": "", - "bgcolor": "1" - }, - "8,77": { - "contents": "", - "bgcolor": "1" - }, - "8,78": { - "contents": "", - "bgcolor": "1" - }, - "8,79": { - "contents": "", - "bgcolor": "1" - }, - "8,8": { - "contents": "", - "bgcolor": "1" - }, - "8,9": { - "contents": "", - "bgcolor": "1" - }, - "9,0": { - "contents": "", - "bgcolor": "1" - }, - "9,1": { - "contents": "", - "bgcolor": "1" - }, - "9,10": { - "contents": "", - "bgcolor": "1" - }, - "9,11": { - "contents": "", - "bgcolor": "1" - }, - "9,12": { - "contents": "", - "bgcolor": "1" - }, - "9,13": { - "contents": "", - "bgcolor": "1" - }, - "9,14": { - "contents": "", - "bgcolor": "1" - }, - "9,15": { - "contents": "", - "bgcolor": "1" - }, - "9,16": { - "contents": "", - "bgcolor": "1" - }, - "9,17": { - "contents": "", - "bgcolor": "1" - }, - "9,18": { - "contents": "", - "bgcolor": "1" - }, - "9,19": { - "contents": "", - "bgcolor": "1" - }, - "9,2": { - "contents": "", - "bgcolor": "1" - }, - "9,20": { - "contents": "", - "bgcolor": "1" - }, - "9,21": { - "contents": "", - "bgcolor": "1" - }, - "9,22": { - "contents": "", - "bgcolor": "1" - }, - "9,23": { - "contents": "", - "bgcolor": "1" - }, - "9,24": { - "contents": "", - "bgcolor": "1" - }, - "9,25": { - "contents": "", - "bgcolor": "1" - }, - "9,26": { - "contents": "", - "bgcolor": "1" - }, - "9,27": { - "contents": "", - "bgcolor": "1" - }, - "9,28": { - "contents": "", - "bgcolor": "1" - }, - "9,29": { - "contents": "", - "bgcolor": "1" - }, - "9,3": { - "contents": "", - "bgcolor": "1" - }, - "9,30": { - "contents": "", - "bgcolor": "1" - }, - "9,31": { - "contents": "", - "bgcolor": "1" - }, - "9,32": { - "contents": "", - "bgcolor": "1" - }, - "9,33": { - "contents": "", - "bgcolor": "1" - }, - "9,34": { - "contents": "", - "bgcolor": "1" - }, - "9,35": { - "contents": "", - "bgcolor": "1" - }, - "9,36": { - "contents": "", - "bgcolor": "1" - }, - "9,37": { - "contents": "", - "bgcolor": "1" - }, - "9,38": { - "contents": "", - "bgcolor": "1" - }, - "9,39": { - "contents": "", - "bgcolor": "1" - }, - "9,4": { - "contents": "", - "bgcolor": "1" - }, - "9,40": { - "contents": "", - "bgcolor": "1" - }, - "9,41": { - "contents": "", - "bgcolor": "1" - }, - "9,42": { - "contents": "", - "bgcolor": "1" - }, - "9,43": { - "contents": "", - "bgcolor": "1" - }, - "9,44": { - "contents": "", - "bgcolor": "1" - }, - "9,45": { - "contents": "", - "bgcolor": "1" - }, - "9,46": { - "contents": "", - "bgcolor": "1" - }, - "9,47": { - "contents": "", - "bgcolor": "1" - }, - "9,48": { - "contents": "", - "bgcolor": "1" - }, - "9,49": { - "contents": "", - "bgcolor": "1" - }, - "9,5": { - "contents": "", - "bgcolor": "1" - }, - "9,50": { - "contents": "", - "bgcolor": "1" - }, - "9,51": { - "contents": "", - "bgcolor": "1" - }, - "9,52": { - "contents": "", - "bgcolor": "1" - }, - "9,53": { - "contents": "", - "bgcolor": "1" - }, - "9,54": { - "contents": "", - "bgcolor": "1" - }, - "9,55": { - "contents": "", - "bgcolor": "1" - }, - "9,56": { - "contents": "", - "bgcolor": "1" - }, - "9,57": { - "contents": "", - "bgcolor": "1" - }, - "9,58": { - "contents": "", - "bgcolor": "1" - }, - "9,59": { - "contents": "", - "bgcolor": "1" - }, - "9,6": { - "contents": "", - "bgcolor": "1" - }, - "9,60": { - "contents": "", - "bgcolor": "1" - }, - "9,61": { - "contents": "", - "bgcolor": "1" - }, - "9,62": { - "contents": "", - "bgcolor": "1" - }, - "9,63": { - "contents": "", - "bgcolor": "1" - }, - "9,64": { - "contents": "", - "bgcolor": "1" - }, - "9,65": { - "contents": "", - "bgcolor": "1" - }, - "9,66": { - "contents": "", - "bgcolor": "1" - }, - "9,67": { - "contents": "", - "bgcolor": "1" - }, - "9,68": { - "contents": "", - "bgcolor": "1" - }, - "9,69": { - "contents": "", - "bgcolor": "1" - }, - "9,7": { - "contents": "", - "bgcolor": "1" - }, - "9,70": { - "contents": "", - "bgcolor": "1" - }, - "9,71": { - "contents": "", - "bgcolor": "1" - }, - "9,72": { - "contents": "", - "bgcolor": "1" - }, - "9,73": { - "contents": "", - "bgcolor": "1" - }, - "9,74": { - "contents": "", - "bgcolor": "1" - }, - "9,75": { - "contents": "", - "bgcolor": "1" - }, - "9,76": { - "contents": "", - "bgcolor": "1" - }, - "9,77": { - "contents": "", - "bgcolor": "1" - }, - "9,78": { - "contents": "", - "bgcolor": "1" - }, - "9,79": { - "contents": "", - "bgcolor": "1" - }, - "9,8": { - "contents": "", - "bgcolor": "1" - }, - "9,9": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/21.typescript deleted file mode 100644 index 7d0f7ca26a1f2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/21.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/3.json b/crates/turborepo-vt100/tests/data/fixtures/ed/3.json deleted file mode 100644 index 0b5f1154d1163..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/3.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "\n\n\n\n r\n\n\n\n\n ba", - "cells": { - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 4, - 5 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/3.typescript deleted file mode 100644 index 3d05d98079e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/4.json b/crates/turborepo-vt100/tests/data/fixtures/ed/4.json deleted file mode 100644 index 9ffb2f54c656b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 6, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/4.typescript deleted file mode 100644 index 58e2e071bdcbb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/5.json b/crates/turborepo-vt100/tests/data/fixtures/ed/5.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/5.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/5.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/5.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/6.json b/crates/turborepo-vt100/tests/data/fixtures/ed/6.json deleted file mode 100644 index 20eb131a98123..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/6.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 19, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/6.typescript deleted file mode 100644 index 40386b5b83af5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/6.typescript +++ /dev/null @@ -1 +0,0 @@ -foobarbazquux \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/7.json b/crates/turborepo-vt100/tests/data/fixtures/ed/7.json deleted file mode 100644 index fe26558462bd5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/7.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n ba", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/7.typescript deleted file mode 100644 index 522bc763ab2e5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/7.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/8.json b/crates/turborepo-vt100/tests/data/fixtures/ed/8.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/8.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/8.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/8.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/9.json b/crates/turborepo-vt100/tests/data/fixtures/ed/9.json deleted file mode 100644 index 20eb131a98123..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/9.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 19, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ed/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/ed/9.typescript deleted file mode 100644 index 40386b5b83af5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ed/9.typescript +++ /dev/null @@ -1 +0,0 @@ -foobarbazquux \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el.in b/crates/turborepo-vt100/tests/data/fixtures/el.in deleted file mode 100644 index 1c132bdd5b989..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el.in +++ /dev/null @@ -1,26 +0,0 @@ -foo\x1b[5;5Hbarbar\x1b[10;10Hbazbaz\x1b[20;20Hquux -\x1b[5;8H\x1b[0K -\x1b[10;12H\x1b[1K -\x1b[20;22H\x1b[2K -\x1b[1;2H\x1b[K -\x1b[2J\x1b[H -foo\x1b[5;5Hbarbar\x1b[10;10Hbazbaz\x1b[20;20Hquux -\x1b[5;8H\x1b[?0K -\x1b[10;12H\x1b[?1K -\x1b[20;22H\x1b[?2K -\x1b[1;2H\x1b[?K -\x1b[2J\x1b[H -1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -\x1b[1;21H\x1b[K -\x1b[1;10H\x1b[1K -\x1bc\x1b[5;5H -\x1b[41m\x1b[K -\x1bc\x1b[5;5H -\x1b[41m\x1b[1K -\x1bc\x1b[5;5H -\x1b[41m\x1b[2K -\x1bc\x1b[1;80H\x1b[41ma\x1b[1K -\x1bc\x1b[1;80H\x1b[41maa\x1b[1K -\x1bc\x1b[41m\x1b[2J\x1b[1;80Haa\x1b[1K -\x1bc\x1b[1;80Hab\x1b[1;80Hc -\x1b[2K diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/1.json b/crates/turborepo-vt100/tests/data/fixtures/el/1.json deleted file mode 100644 index 391f3aa1a1073..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/1.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "contents": "foo\n\n\n\n barbar\n\n\n\n\n bazbaz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "4,7": { - "contents": "b" - }, - "4,8": { - "contents": "a" - }, - "4,9": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 19, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/1.typescript deleted file mode 100644 index 2f06911866a49..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foobarbarbazbazquux \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/10.json b/crates/turborepo-vt100/tests/data/fixtures/el/10.json deleted file mode 100644 index 6893191049387..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/10.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - } - }, - "cursor_position": [ - 19, - 21 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/10.typescript deleted file mode 100644 index 36b14f396b414..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/10.typescript +++ /dev/null @@ -1 +0,0 @@ -[?2K \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/11.json b/crates/turborepo-vt100/tests/data/fixtures/el/11.json deleted file mode 100644 index f4b8e818c8fd6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/11.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "f\n\n\n\n bar\n\n\n\n\n baz", - "cells": { - "0,0": { - "contents": "f" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/11.typescript deleted file mode 100644 index 61cedca415c53..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/11.typescript +++ /dev/null @@ -1 +0,0 @@ -[?K \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/12.json b/crates/turborepo-vt100/tests/data/fixtures/el/12.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/12.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/12.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/12.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/13.json b/crates/turborepo-vt100/tests/data/fixtures/el/13.json deleted file mode 100644 index 9cbf17f4f4cd1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/13.json +++ /dev/null @@ -1,309 +0,0 @@ -{ - "contents": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", - "cells": { - "0,0": { - "contents": "1" - }, - "0,1": { - "contents": "2" - }, - "0,10": { - "contents": "1" - }, - "0,11": { - "contents": "2" - }, - "0,12": { - "contents": "3" - }, - "0,13": { - "contents": "4" - }, - "0,14": { - "contents": "5" - }, - "0,15": { - "contents": "6" - }, - "0,16": { - "contents": "7" - }, - "0,17": { - "contents": "8" - }, - "0,18": { - "contents": "9" - }, - "0,19": { - "contents": "0" - }, - "0,2": { - "contents": "3" - }, - "0,20": { - "contents": "1" - }, - "0,21": { - "contents": "2" - }, - "0,22": { - "contents": "3" - }, - "0,23": { - "contents": "4" - }, - "0,24": { - "contents": "5" - }, - "0,25": { - "contents": "6" - }, - "0,26": { - "contents": "7" - }, - "0,27": { - "contents": "8" - }, - "0,28": { - "contents": "9" - }, - "0,29": { - "contents": "0" - }, - "0,3": { - "contents": "4" - }, - "0,30": { - "contents": "1" - }, - "0,31": { - "contents": "2" - }, - "0,32": { - "contents": "3" - }, - "0,33": { - "contents": "4" - }, - "0,34": { - "contents": "5" - }, - "0,35": { - "contents": "6" - }, - "0,36": { - "contents": "7" - }, - "0,37": { - "contents": "8" - }, - "0,38": { - "contents": "9" - }, - "0,39": { - "contents": "0" - }, - "0,4": { - "contents": "5" - }, - "0,40": { - "contents": "1" - }, - "0,41": { - "contents": "2" - }, - "0,42": { - "contents": "3" - }, - "0,43": { - "contents": "4" - }, - "0,44": { - "contents": "5" - }, - "0,45": { - "contents": "6" - }, - "0,46": { - "contents": "7" - }, - "0,47": { - "contents": "8" - }, - "0,48": { - "contents": "9" - }, - "0,49": { - "contents": "0" - }, - "0,5": { - "contents": "6" - }, - "0,50": { - "contents": "1" - }, - "0,51": { - "contents": "2" - }, - "0,52": { - "contents": "3" - }, - "0,53": { - "contents": "4" - }, - "0,54": { - "contents": "5" - }, - "0,55": { - "contents": "6" - }, - "0,56": { - "contents": "7" - }, - "0,57": { - "contents": "8" - }, - "0,58": { - "contents": "9" - }, - "0,59": { - "contents": "0" - }, - "0,6": { - "contents": "7" - }, - "0,60": { - "contents": "1" - }, - "0,61": { - "contents": "2" - }, - "0,62": { - "contents": "3" - }, - "0,63": { - "contents": "4" - }, - "0,64": { - "contents": "5" - }, - "0,65": { - "contents": "6" - }, - "0,66": { - "contents": "7" - }, - "0,67": { - "contents": "8" - }, - "0,68": { - "contents": "9" - }, - "0,69": { - "contents": "0" - }, - "0,7": { - "contents": "8" - }, - "0,70": { - "contents": "1" - }, - "0,71": { - "contents": "2" - }, - "0,72": { - "contents": "3" - }, - "0,73": { - "contents": "4" - }, - "0,74": { - "contents": "5" - }, - "0,75": { - "contents": "6" - }, - "0,76": { - "contents": "7" - }, - "0,77": { - "contents": "8" - }, - "0,78": { - "contents": "9" - }, - "0,79": { - "contents": "0" - }, - "0,8": { - "contents": "9" - }, - "0,9": { - "contents": "0" - }, - "1,0": { - "contents": "1" - }, - "1,1": { - "contents": "2" - }, - "1,10": { - "contents": "1" - }, - "1,11": { - "contents": "2" - }, - "1,12": { - "contents": "3" - }, - "1,13": { - "contents": "4" - }, - "1,14": { - "contents": "5" - }, - "1,15": { - "contents": "6" - }, - "1,16": { - "contents": "7" - }, - "1,17": { - "contents": "8" - }, - "1,18": { - "contents": "9" - }, - "1,19": { - "contents": "0" - }, - "1,2": { - "contents": "3" - }, - "1,3": { - "contents": "4" - }, - "1,4": { - "contents": "5" - }, - "1,5": { - "contents": "6" - }, - "1,6": { - "contents": "7" - }, - "1,7": { - "contents": "8" - }, - "1,8": { - "contents": "9" - }, - "1,9": { - "contents": "0" - } - }, - "cursor_position": [ - 1, - 20 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/13.typescript deleted file mode 100644 index d6d9ec2cba526..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/13.typescript +++ /dev/null @@ -1 +0,0 @@ -1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/14.json b/crates/turborepo-vt100/tests/data/fixtures/el/14.json deleted file mode 100644 index 930e971b01cfa..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/14.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "contents": "12345678901234567890\n12345678901234567890", - "cells": { - "0,0": { - "contents": "1" - }, - "0,1": { - "contents": "2" - }, - "0,10": { - "contents": "1" - }, - "0,11": { - "contents": "2" - }, - "0,12": { - "contents": "3" - }, - "0,13": { - "contents": "4" - }, - "0,14": { - "contents": "5" - }, - "0,15": { - "contents": "6" - }, - "0,16": { - "contents": "7" - }, - "0,17": { - "contents": "8" - }, - "0,18": { - "contents": "9" - }, - "0,19": { - "contents": "0" - }, - "0,2": { - "contents": "3" - }, - "0,3": { - "contents": "4" - }, - "0,4": { - "contents": "5" - }, - "0,5": { - "contents": "6" - }, - "0,6": { - "contents": "7" - }, - "0,7": { - "contents": "8" - }, - "0,8": { - "contents": "9" - }, - "0,9": { - "contents": "0" - }, - "1,0": { - "contents": "1" - }, - "1,1": { - "contents": "2" - }, - "1,10": { - "contents": "1" - }, - "1,11": { - "contents": "2" - }, - "1,12": { - "contents": "3" - }, - "1,13": { - "contents": "4" - }, - "1,14": { - "contents": "5" - }, - "1,15": { - "contents": "6" - }, - "1,16": { - "contents": "7" - }, - "1,17": { - "contents": "8" - }, - "1,18": { - "contents": "9" - }, - "1,19": { - "contents": "0" - }, - "1,2": { - "contents": "3" - }, - "1,3": { - "contents": "4" - }, - "1,4": { - "contents": "5" - }, - "1,5": { - "contents": "6" - }, - "1,6": { - "contents": "7" - }, - "1,7": { - "contents": "8" - }, - "1,8": { - "contents": "9" - }, - "1,9": { - "contents": "0" - } - }, - "cursor_position": [ - 0, - 20 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/14.typescript deleted file mode 100644 index 258b850282cdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/14.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/15.json b/crates/turborepo-vt100/tests/data/fixtures/el/15.json deleted file mode 100644 index 70dbac3349e32..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/15.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "contents": " 1234567890\n12345678901234567890", - "cells": { - "0,10": { - "contents": "1" - }, - "0,11": { - "contents": "2" - }, - "0,12": { - "contents": "3" - }, - "0,13": { - "contents": "4" - }, - "0,14": { - "contents": "5" - }, - "0,15": { - "contents": "6" - }, - "0,16": { - "contents": "7" - }, - "0,17": { - "contents": "8" - }, - "0,18": { - "contents": "9" - }, - "0,19": { - "contents": "0" - }, - "1,0": { - "contents": "1" - }, - "1,1": { - "contents": "2" - }, - "1,10": { - "contents": "1" - }, - "1,11": { - "contents": "2" - }, - "1,12": { - "contents": "3" - }, - "1,13": { - "contents": "4" - }, - "1,14": { - "contents": "5" - }, - "1,15": { - "contents": "6" - }, - "1,16": { - "contents": "7" - }, - "1,17": { - "contents": "8" - }, - "1,18": { - "contents": "9" - }, - "1,19": { - "contents": "0" - }, - "1,2": { - "contents": "3" - }, - "1,3": { - "contents": "4" - }, - "1,4": { - "contents": "5" - }, - "1,5": { - "contents": "6" - }, - "1,6": { - "contents": "7" - }, - "1,7": { - "contents": "8" - }, - "1,8": { - "contents": "9" - }, - "1,9": { - "contents": "0" - } - }, - "cursor_position": [ - 0, - 9 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/15.typescript deleted file mode 100644 index 7b90d75427dd4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/15.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/16.json b/crates/turborepo-vt100/tests/data/fixtures/el/16.json deleted file mode 100644 index 2b060efecfe66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/16.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/16.typescript deleted file mode 100644 index 8adc44f0bdefe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/16.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/17.json b/crates/turborepo-vt100/tests/data/fixtures/el/17.json deleted file mode 100644 index e48c3fee77e31..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/17.json +++ /dev/null @@ -1,313 +0,0 @@ -{ - "contents": "", - "cells": { - "4,10": { - "contents": "", - "bgcolor": "1" - }, - "4,11": { - "contents": "", - "bgcolor": "1" - }, - "4,12": { - "contents": "", - "bgcolor": "1" - }, - "4,13": { - "contents": "", - "bgcolor": "1" - }, - "4,14": { - "contents": "", - "bgcolor": "1" - }, - "4,15": { - "contents": "", - "bgcolor": "1" - }, - "4,16": { - "contents": "", - "bgcolor": "1" - }, - "4,17": { - "contents": "", - "bgcolor": "1" - }, - "4,18": { - "contents": "", - "bgcolor": "1" - }, - "4,19": { - "contents": "", - "bgcolor": "1" - }, - "4,20": { - "contents": "", - "bgcolor": "1" - }, - "4,21": { - "contents": "", - "bgcolor": "1" - }, - "4,22": { - "contents": "", - "bgcolor": "1" - }, - "4,23": { - "contents": "", - "bgcolor": "1" - }, - "4,24": { - "contents": "", - "bgcolor": "1" - }, - "4,25": { - "contents": "", - "bgcolor": "1" - }, - "4,26": { - "contents": "", - "bgcolor": "1" - }, - "4,27": { - "contents": "", - "bgcolor": "1" - }, - "4,28": { - "contents": "", - "bgcolor": "1" - }, - "4,29": { - "contents": "", - "bgcolor": "1" - }, - "4,30": { - "contents": "", - "bgcolor": "1" - }, - "4,31": { - "contents": "", - "bgcolor": "1" - }, - "4,32": { - "contents": "", - "bgcolor": "1" - }, - "4,33": { - "contents": "", - "bgcolor": "1" - }, - "4,34": { - "contents": "", - "bgcolor": "1" - }, - "4,35": { - "contents": "", - "bgcolor": "1" - }, - "4,36": { - "contents": "", - "bgcolor": "1" - }, - "4,37": { - "contents": "", - "bgcolor": "1" - }, - "4,38": { - "contents": "", - "bgcolor": "1" - }, - "4,39": { - "contents": "", - "bgcolor": "1" - }, - "4,4": { - "contents": "", - "bgcolor": "1" - }, - "4,40": { - "contents": "", - "bgcolor": "1" - }, - "4,41": { - "contents": "", - "bgcolor": "1" - }, - "4,42": { - "contents": "", - "bgcolor": "1" - }, - "4,43": { - "contents": "", - "bgcolor": "1" - }, - "4,44": { - "contents": "", - "bgcolor": "1" - }, - "4,45": { - "contents": "", - "bgcolor": "1" - }, - "4,46": { - "contents": "", - "bgcolor": "1" - }, - "4,47": { - "contents": "", - "bgcolor": "1" - }, - "4,48": { - "contents": "", - "bgcolor": "1" - }, - "4,49": { - "contents": "", - "bgcolor": "1" - }, - "4,5": { - "contents": "", - "bgcolor": "1" - }, - "4,50": { - "contents": "", - "bgcolor": "1" - }, - "4,51": { - "contents": "", - "bgcolor": "1" - }, - "4,52": { - "contents": "", - "bgcolor": "1" - }, - "4,53": { - "contents": "", - "bgcolor": "1" - }, - "4,54": { - "contents": "", - "bgcolor": "1" - }, - "4,55": { - "contents": "", - "bgcolor": "1" - }, - "4,56": { - "contents": "", - "bgcolor": "1" - }, - "4,57": { - "contents": "", - "bgcolor": "1" - }, - "4,58": { - "contents": "", - "bgcolor": "1" - }, - "4,59": { - "contents": "", - "bgcolor": "1" - }, - "4,6": { - "contents": "", - "bgcolor": "1" - }, - "4,60": { - "contents": "", - "bgcolor": "1" - }, - "4,61": { - "contents": "", - "bgcolor": "1" - }, - "4,62": { - "contents": "", - "bgcolor": "1" - }, - "4,63": { - "contents": "", - "bgcolor": "1" - }, - "4,64": { - "contents": "", - "bgcolor": "1" - }, - "4,65": { - "contents": "", - "bgcolor": "1" - }, - "4,66": { - "contents": "", - "bgcolor": "1" - }, - "4,67": { - "contents": "", - "bgcolor": "1" - }, - "4,68": { - "contents": "", - "bgcolor": "1" - }, - "4,69": { - "contents": "", - "bgcolor": "1" - }, - "4,7": { - "contents": "", - "bgcolor": "1" - }, - "4,70": { - "contents": "", - "bgcolor": "1" - }, - "4,71": { - "contents": "", - "bgcolor": "1" - }, - "4,72": { - "contents": "", - "bgcolor": "1" - }, - "4,73": { - "contents": "", - "bgcolor": "1" - }, - "4,74": { - "contents": "", - "bgcolor": "1" - }, - "4,75": { - "contents": "", - "bgcolor": "1" - }, - "4,76": { - "contents": "", - "bgcolor": "1" - }, - "4,77": { - "contents": "", - "bgcolor": "1" - }, - "4,78": { - "contents": "", - "bgcolor": "1" - }, - "4,79": { - "contents": "", - "bgcolor": "1" - }, - "4,8": { - "contents": "", - "bgcolor": "1" - }, - "4,9": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/17.typescript deleted file mode 100644 index e40777ed0932b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/17.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/18.json b/crates/turborepo-vt100/tests/data/fixtures/el/18.json deleted file mode 100644 index 2b060efecfe66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/18.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/18.typescript deleted file mode 100644 index 8adc44f0bdefe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/18.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/19.json b/crates/turborepo-vt100/tests/data/fixtures/el/19.json deleted file mode 100644 index b40aae30a9dba..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/19.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "contents": "", - "cells": { - "4,0": { - "contents": "", - "bgcolor": "1" - }, - "4,1": { - "contents": "", - "bgcolor": "1" - }, - "4,2": { - "contents": "", - "bgcolor": "1" - }, - "4,3": { - "contents": "", - "bgcolor": "1" - }, - "4,4": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/19.typescript deleted file mode 100644 index aea336b2f69b4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/19.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/2.json b/crates/turborepo-vt100/tests/data/fixtures/el/2.json deleted file mode 100644 index ab8752fb15f2a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/2.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n bazbaz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 4, - 7 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/2.typescript deleted file mode 100644 index 86d7b68037ef9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/20.json b/crates/turborepo-vt100/tests/data/fixtures/el/20.json deleted file mode 100644 index 2b060efecfe66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/20.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/20.typescript deleted file mode 100644 index 8adc44f0bdefe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/20.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/21.json b/crates/turborepo-vt100/tests/data/fixtures/el/21.json deleted file mode 100644 index c5df4a0640122..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/21.json +++ /dev/null @@ -1,329 +0,0 @@ -{ - "contents": "", - "cells": { - "4,0": { - "contents": "", - "bgcolor": "1" - }, - "4,1": { - "contents": "", - "bgcolor": "1" - }, - "4,10": { - "contents": "", - "bgcolor": "1" - }, - "4,11": { - "contents": "", - "bgcolor": "1" - }, - "4,12": { - "contents": "", - "bgcolor": "1" - }, - "4,13": { - "contents": "", - "bgcolor": "1" - }, - "4,14": { - "contents": "", - "bgcolor": "1" - }, - "4,15": { - "contents": "", - "bgcolor": "1" - }, - "4,16": { - "contents": "", - "bgcolor": "1" - }, - "4,17": { - "contents": "", - "bgcolor": "1" - }, - "4,18": { - "contents": "", - "bgcolor": "1" - }, - "4,19": { - "contents": "", - "bgcolor": "1" - }, - "4,2": { - "contents": "", - "bgcolor": "1" - }, - "4,20": { - "contents": "", - "bgcolor": "1" - }, - "4,21": { - "contents": "", - "bgcolor": "1" - }, - "4,22": { - "contents": "", - "bgcolor": "1" - }, - "4,23": { - "contents": "", - "bgcolor": "1" - }, - "4,24": { - "contents": "", - "bgcolor": "1" - }, - "4,25": { - "contents": "", - "bgcolor": "1" - }, - "4,26": { - "contents": "", - "bgcolor": "1" - }, - "4,27": { - "contents": "", - "bgcolor": "1" - }, - "4,28": { - "contents": "", - "bgcolor": "1" - }, - "4,29": { - "contents": "", - "bgcolor": "1" - }, - "4,3": { - "contents": "", - "bgcolor": "1" - }, - "4,30": { - "contents": "", - "bgcolor": "1" - }, - "4,31": { - "contents": "", - "bgcolor": "1" - }, - "4,32": { - "contents": "", - "bgcolor": "1" - }, - "4,33": { - "contents": "", - "bgcolor": "1" - }, - "4,34": { - "contents": "", - "bgcolor": "1" - }, - "4,35": { - "contents": "", - "bgcolor": "1" - }, - "4,36": { - "contents": "", - "bgcolor": "1" - }, - "4,37": { - "contents": "", - "bgcolor": "1" - }, - "4,38": { - "contents": "", - "bgcolor": "1" - }, - "4,39": { - "contents": "", - "bgcolor": "1" - }, - "4,4": { - "contents": "", - "bgcolor": "1" - }, - "4,40": { - "contents": "", - "bgcolor": "1" - }, - "4,41": { - "contents": "", - "bgcolor": "1" - }, - "4,42": { - "contents": "", - "bgcolor": "1" - }, - "4,43": { - "contents": "", - "bgcolor": "1" - }, - "4,44": { - "contents": "", - "bgcolor": "1" - }, - "4,45": { - "contents": "", - "bgcolor": "1" - }, - "4,46": { - "contents": "", - "bgcolor": "1" - }, - "4,47": { - "contents": "", - "bgcolor": "1" - }, - "4,48": { - "contents": "", - "bgcolor": "1" - }, - "4,49": { - "contents": "", - "bgcolor": "1" - }, - "4,5": { - "contents": "", - "bgcolor": "1" - }, - "4,50": { - "contents": "", - "bgcolor": "1" - }, - "4,51": { - "contents": "", - "bgcolor": "1" - }, - "4,52": { - "contents": "", - "bgcolor": "1" - }, - "4,53": { - "contents": "", - "bgcolor": "1" - }, - "4,54": { - "contents": "", - "bgcolor": "1" - }, - "4,55": { - "contents": "", - "bgcolor": "1" - }, - "4,56": { - "contents": "", - "bgcolor": "1" - }, - "4,57": { - "contents": "", - "bgcolor": "1" - }, - "4,58": { - "contents": "", - "bgcolor": "1" - }, - "4,59": { - "contents": "", - "bgcolor": "1" - }, - "4,6": { - "contents": "", - "bgcolor": "1" - }, - "4,60": { - "contents": "", - "bgcolor": "1" - }, - "4,61": { - "contents": "", - "bgcolor": "1" - }, - "4,62": { - "contents": "", - "bgcolor": "1" - }, - "4,63": { - "contents": "", - "bgcolor": "1" - }, - "4,64": { - "contents": "", - "bgcolor": "1" - }, - "4,65": { - "contents": "", - "bgcolor": "1" - }, - "4,66": { - "contents": "", - "bgcolor": "1" - }, - "4,67": { - "contents": "", - "bgcolor": "1" - }, - "4,68": { - "contents": "", - "bgcolor": "1" - }, - "4,69": { - "contents": "", - "bgcolor": "1" - }, - "4,7": { - "contents": "", - "bgcolor": "1" - }, - "4,70": { - "contents": "", - "bgcolor": "1" - }, - "4,71": { - "contents": "", - "bgcolor": "1" - }, - "4,72": { - "contents": "", - "bgcolor": "1" - }, - "4,73": { - "contents": "", - "bgcolor": "1" - }, - "4,74": { - "contents": "", - "bgcolor": "1" - }, - "4,75": { - "contents": "", - "bgcolor": "1" - }, - "4,76": { - "contents": "", - "bgcolor": "1" - }, - "4,77": { - "contents": "", - "bgcolor": "1" - }, - "4,78": { - "contents": "", - "bgcolor": "1" - }, - "4,79": { - "contents": "", - "bgcolor": "1" - }, - "4,8": { - "contents": "", - "bgcolor": "1" - }, - "4,9": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 4, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/21.typescript deleted file mode 100644 index 45100a2064a7e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/21.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/22.json b/crates/turborepo-vt100/tests/data/fixtures/el/22.json deleted file mode 100644 index 908b9f0aa3e9f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/22.json +++ /dev/null @@ -1,329 +0,0 @@ -{ - "contents": "", - "cells": { - "0,0": { - "contents": "", - "bgcolor": "1" - }, - "0,1": { - "contents": "", - "bgcolor": "1" - }, - "0,10": { - "contents": "", - "bgcolor": "1" - }, - "0,11": { - "contents": "", - "bgcolor": "1" - }, - "0,12": { - "contents": "", - "bgcolor": "1" - }, - "0,13": { - "contents": "", - "bgcolor": "1" - }, - "0,14": { - "contents": "", - "bgcolor": "1" - }, - "0,15": { - "contents": "", - "bgcolor": "1" - }, - "0,16": { - "contents": "", - "bgcolor": "1" - }, - "0,17": { - "contents": "", - "bgcolor": "1" - }, - "0,18": { - "contents": "", - "bgcolor": "1" - }, - "0,19": { - "contents": "", - "bgcolor": "1" - }, - "0,2": { - "contents": "", - "bgcolor": "1" - }, - "0,20": { - "contents": "", - "bgcolor": "1" - }, - "0,21": { - "contents": "", - "bgcolor": "1" - }, - "0,22": { - "contents": "", - "bgcolor": "1" - }, - "0,23": { - "contents": "", - "bgcolor": "1" - }, - "0,24": { - "contents": "", - "bgcolor": "1" - }, - "0,25": { - "contents": "", - "bgcolor": "1" - }, - "0,26": { - "contents": "", - "bgcolor": "1" - }, - "0,27": { - "contents": "", - "bgcolor": "1" - }, - "0,28": { - "contents": "", - "bgcolor": "1" - }, - "0,29": { - "contents": "", - "bgcolor": "1" - }, - "0,3": { - "contents": "", - "bgcolor": "1" - }, - "0,30": { - "contents": "", - "bgcolor": "1" - }, - "0,31": { - "contents": "", - "bgcolor": "1" - }, - "0,32": { - "contents": "", - "bgcolor": "1" - }, - "0,33": { - "contents": "", - "bgcolor": "1" - }, - "0,34": { - "contents": "", - "bgcolor": "1" - }, - "0,35": { - "contents": "", - "bgcolor": "1" - }, - "0,36": { - "contents": "", - "bgcolor": "1" - }, - "0,37": { - "contents": "", - "bgcolor": "1" - }, - "0,38": { - "contents": "", - "bgcolor": "1" - }, - "0,39": { - "contents": "", - "bgcolor": "1" - }, - "0,4": { - "contents": "", - "bgcolor": "1" - }, - "0,40": { - "contents": "", - "bgcolor": "1" - }, - "0,41": { - "contents": "", - "bgcolor": "1" - }, - "0,42": { - "contents": "", - "bgcolor": "1" - }, - "0,43": { - "contents": "", - "bgcolor": "1" - }, - "0,44": { - "contents": "", - "bgcolor": "1" - }, - "0,45": { - "contents": "", - "bgcolor": "1" - }, - "0,46": { - "contents": "", - "bgcolor": "1" - }, - "0,47": { - "contents": "", - "bgcolor": "1" - }, - "0,48": { - "contents": "", - "bgcolor": "1" - }, - "0,49": { - "contents": "", - "bgcolor": "1" - }, - "0,5": { - "contents": "", - "bgcolor": "1" - }, - "0,50": { - "contents": "", - "bgcolor": "1" - }, - "0,51": { - "contents": "", - "bgcolor": "1" - }, - "0,52": { - "contents": "", - "bgcolor": "1" - }, - "0,53": { - "contents": "", - "bgcolor": "1" - }, - "0,54": { - "contents": "", - "bgcolor": "1" - }, - "0,55": { - "contents": "", - "bgcolor": "1" - }, - "0,56": { - "contents": "", - "bgcolor": "1" - }, - "0,57": { - "contents": "", - "bgcolor": "1" - }, - "0,58": { - "contents": "", - "bgcolor": "1" - }, - "0,59": { - "contents": "", - "bgcolor": "1" - }, - "0,6": { - "contents": "", - "bgcolor": "1" - }, - "0,60": { - "contents": "", - "bgcolor": "1" - }, - "0,61": { - "contents": "", - "bgcolor": "1" - }, - "0,62": { - "contents": "", - "bgcolor": "1" - }, - "0,63": { - "contents": "", - "bgcolor": "1" - }, - "0,64": { - "contents": "", - "bgcolor": "1" - }, - "0,65": { - "contents": "", - "bgcolor": "1" - }, - "0,66": { - "contents": "", - "bgcolor": "1" - }, - "0,67": { - "contents": "", - "bgcolor": "1" - }, - "0,68": { - "contents": "", - "bgcolor": "1" - }, - "0,69": { - "contents": "", - "bgcolor": "1" - }, - "0,7": { - "contents": "", - "bgcolor": "1" - }, - "0,70": { - "contents": "", - "bgcolor": "1" - }, - "0,71": { - "contents": "", - "bgcolor": "1" - }, - "0,72": { - "contents": "", - "bgcolor": "1" - }, - "0,73": { - "contents": "", - "bgcolor": "1" - }, - "0,74": { - "contents": "", - "bgcolor": "1" - }, - "0,75": { - "contents": "", - "bgcolor": "1" - }, - "0,76": { - "contents": "", - "bgcolor": "1" - }, - "0,77": { - "contents": "", - "bgcolor": "1" - }, - "0,78": { - "contents": "", - "bgcolor": "1" - }, - "0,79": { - "contents": "", - "bgcolor": "1" - }, - "0,8": { - "contents": "", - "bgcolor": "1" - }, - "0,9": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/22.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/22.typescript deleted file mode 100644 index c6d430765e111..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/22.typescript +++ /dev/null @@ -1 +0,0 @@ -ca \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/23.json b/crates/turborepo-vt100/tests/data/fixtures/el/23.json deleted file mode 100644 index f2490f0e6c447..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/23.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,79": { - "contents": "a", - "bgcolor": "1" - }, - "1,0": { - "contents": "", - "bgcolor": "1" - }, - "1,1": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/23.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/23.typescript deleted file mode 100644 index 022194cc154d4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/23.typescript +++ /dev/null @@ -1 +0,0 @@ -caa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/24.json b/crates/turborepo-vt100/tests/data/fixtures/el/24.json deleted file mode 100644 index f91081a059321..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/24.json +++ /dev/null @@ -1,7689 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,0": { - "contents": "", - "bgcolor": "1" - }, - "0,1": { - "contents": "", - "bgcolor": "1" - }, - "0,10": { - "contents": "", - "bgcolor": "1" - }, - "0,11": { - "contents": "", - "bgcolor": "1" - }, - "0,12": { - "contents": "", - "bgcolor": "1" - }, - "0,13": { - "contents": "", - "bgcolor": "1" - }, - "0,14": { - "contents": "", - "bgcolor": "1" - }, - "0,15": { - "contents": "", - "bgcolor": "1" - }, - "0,16": { - "contents": "", - "bgcolor": "1" - }, - "0,17": { - "contents": "", - "bgcolor": "1" - }, - "0,18": { - "contents": "", - "bgcolor": "1" - }, - "0,19": { - "contents": "", - "bgcolor": "1" - }, - "0,2": { - "contents": "", - "bgcolor": "1" - }, - "0,20": { - "contents": "", - "bgcolor": "1" - }, - "0,21": { - "contents": "", - "bgcolor": "1" - }, - "0,22": { - "contents": "", - "bgcolor": "1" - }, - "0,23": { - "contents": "", - "bgcolor": "1" - }, - "0,24": { - "contents": "", - "bgcolor": "1" - }, - "0,25": { - "contents": "", - "bgcolor": "1" - }, - "0,26": { - "contents": "", - "bgcolor": "1" - }, - "0,27": { - "contents": "", - "bgcolor": "1" - }, - "0,28": { - "contents": "", - "bgcolor": "1" - }, - "0,29": { - "contents": "", - "bgcolor": "1" - }, - "0,3": { - "contents": "", - "bgcolor": "1" - }, - "0,30": { - "contents": "", - "bgcolor": "1" - }, - "0,31": { - "contents": "", - "bgcolor": "1" - }, - "0,32": { - "contents": "", - "bgcolor": "1" - }, - "0,33": { - "contents": "", - "bgcolor": "1" - }, - "0,34": { - "contents": "", - "bgcolor": "1" - }, - "0,35": { - "contents": "", - "bgcolor": "1" - }, - "0,36": { - "contents": "", - "bgcolor": "1" - }, - "0,37": { - "contents": "", - "bgcolor": "1" - }, - "0,38": { - "contents": "", - "bgcolor": "1" - }, - "0,39": { - "contents": "", - "bgcolor": "1" - }, - "0,4": { - "contents": "", - "bgcolor": "1" - }, - "0,40": { - "contents": "", - "bgcolor": "1" - }, - "0,41": { - "contents": "", - "bgcolor": "1" - }, - "0,42": { - "contents": "", - "bgcolor": "1" - }, - "0,43": { - "contents": "", - "bgcolor": "1" - }, - "0,44": { - "contents": "", - "bgcolor": "1" - }, - "0,45": { - "contents": "", - "bgcolor": "1" - }, - "0,46": { - "contents": "", - "bgcolor": "1" - }, - "0,47": { - "contents": "", - "bgcolor": "1" - }, - "0,48": { - "contents": "", - "bgcolor": "1" - }, - "0,49": { - "contents": "", - "bgcolor": "1" - }, - "0,5": { - "contents": "", - "bgcolor": "1" - }, - "0,50": { - "contents": "", - "bgcolor": "1" - }, - "0,51": { - "contents": "", - "bgcolor": "1" - }, - "0,52": { - "contents": "", - "bgcolor": "1" - }, - "0,53": { - "contents": "", - "bgcolor": "1" - }, - "0,54": { - "contents": "", - "bgcolor": "1" - }, - "0,55": { - "contents": "", - "bgcolor": "1" - }, - "0,56": { - "contents": "", - "bgcolor": "1" - }, - "0,57": { - "contents": "", - "bgcolor": "1" - }, - "0,58": { - "contents": "", - "bgcolor": "1" - }, - "0,59": { - "contents": "", - "bgcolor": "1" - }, - "0,6": { - "contents": "", - "bgcolor": "1" - }, - "0,60": { - "contents": "", - "bgcolor": "1" - }, - "0,61": { - "contents": "", - "bgcolor": "1" - }, - "0,62": { - "contents": "", - "bgcolor": "1" - }, - "0,63": { - "contents": "", - "bgcolor": "1" - }, - "0,64": { - "contents": "", - "bgcolor": "1" - }, - "0,65": { - "contents": "", - "bgcolor": "1" - }, - "0,66": { - "contents": "", - "bgcolor": "1" - }, - "0,67": { - "contents": "", - "bgcolor": "1" - }, - "0,68": { - "contents": "", - "bgcolor": "1" - }, - "0,69": { - "contents": "", - "bgcolor": "1" - }, - "0,7": { - "contents": "", - "bgcolor": "1" - }, - "0,70": { - "contents": "", - "bgcolor": "1" - }, - "0,71": { - "contents": "", - "bgcolor": "1" - }, - "0,72": { - "contents": "", - "bgcolor": "1" - }, - "0,73": { - "contents": "", - "bgcolor": "1" - }, - "0,74": { - "contents": "", - "bgcolor": "1" - }, - "0,75": { - "contents": "", - "bgcolor": "1" - }, - "0,76": { - "contents": "", - "bgcolor": "1" - }, - "0,77": { - "contents": "", - "bgcolor": "1" - }, - "0,78": { - "contents": "", - "bgcolor": "1" - }, - "0,79": { - "contents": "a", - "bgcolor": "1" - }, - "0,8": { - "contents": "", - "bgcolor": "1" - }, - "0,9": { - "contents": "", - "bgcolor": "1" - }, - "1,0": { - "contents": "", - "bgcolor": "1" - }, - "1,1": { - "contents": "", - "bgcolor": "1" - }, - "1,10": { - "contents": "", - "bgcolor": "1" - }, - "1,11": { - "contents": "", - "bgcolor": "1" - }, - "1,12": { - "contents": "", - "bgcolor": "1" - }, - "1,13": { - "contents": "", - "bgcolor": "1" - }, - "1,14": { - "contents": "", - "bgcolor": "1" - }, - "1,15": { - "contents": "", - "bgcolor": "1" - }, - "1,16": { - "contents": "", - "bgcolor": "1" - }, - "1,17": { - "contents": "", - "bgcolor": "1" - }, - "1,18": { - "contents": "", - "bgcolor": "1" - }, - "1,19": { - "contents": "", - "bgcolor": "1" - }, - "1,2": { - "contents": "", - "bgcolor": "1" - }, - "1,20": { - "contents": "", - "bgcolor": "1" - }, - "1,21": { - "contents": "", - "bgcolor": "1" - }, - "1,22": { - "contents": "", - "bgcolor": "1" - }, - "1,23": { - "contents": "", - "bgcolor": "1" - }, - "1,24": { - "contents": "", - "bgcolor": "1" - }, - "1,25": { - "contents": "", - "bgcolor": "1" - }, - "1,26": { - "contents": "", - "bgcolor": "1" - }, - "1,27": { - "contents": "", - "bgcolor": "1" - }, - "1,28": { - "contents": "", - "bgcolor": "1" - }, - "1,29": { - "contents": "", - "bgcolor": "1" - }, - "1,3": { - "contents": "", - "bgcolor": "1" - }, - "1,30": { - "contents": "", - "bgcolor": "1" - }, - "1,31": { - "contents": "", - "bgcolor": "1" - }, - "1,32": { - "contents": "", - "bgcolor": "1" - }, - "1,33": { - "contents": "", - "bgcolor": "1" - }, - "1,34": { - "contents": "", - "bgcolor": "1" - }, - "1,35": { - "contents": "", - "bgcolor": "1" - }, - "1,36": { - "contents": "", - "bgcolor": "1" - }, - "1,37": { - "contents": "", - "bgcolor": "1" - }, - "1,38": { - "contents": "", - "bgcolor": "1" - }, - "1,39": { - "contents": "", - "bgcolor": "1" - }, - "1,4": { - "contents": "", - "bgcolor": "1" - }, - "1,40": { - "contents": "", - "bgcolor": "1" - }, - "1,41": { - "contents": "", - "bgcolor": "1" - }, - "1,42": { - "contents": "", - "bgcolor": "1" - }, - "1,43": { - "contents": "", - "bgcolor": "1" - }, - "1,44": { - "contents": "", - "bgcolor": "1" - }, - "1,45": { - "contents": "", - "bgcolor": "1" - }, - "1,46": { - "contents": "", - "bgcolor": "1" - }, - "1,47": { - "contents": "", - "bgcolor": "1" - }, - "1,48": { - "contents": "", - "bgcolor": "1" - }, - "1,49": { - "contents": "", - "bgcolor": "1" - }, - "1,5": { - "contents": "", - "bgcolor": "1" - }, - "1,50": { - "contents": "", - "bgcolor": "1" - }, - "1,51": { - "contents": "", - "bgcolor": "1" - }, - "1,52": { - "contents": "", - "bgcolor": "1" - }, - "1,53": { - "contents": "", - "bgcolor": "1" - }, - "1,54": { - "contents": "", - "bgcolor": "1" - }, - "1,55": { - "contents": "", - "bgcolor": "1" - }, - "1,56": { - "contents": "", - "bgcolor": "1" - }, - "1,57": { - "contents": "", - "bgcolor": "1" - }, - "1,58": { - "contents": "", - "bgcolor": "1" - }, - "1,59": { - "contents": "", - "bgcolor": "1" - }, - "1,6": { - "contents": "", - "bgcolor": "1" - }, - "1,60": { - "contents": "", - "bgcolor": "1" - }, - "1,61": { - "contents": "", - "bgcolor": "1" - }, - "1,62": { - "contents": "", - "bgcolor": "1" - }, - "1,63": { - "contents": "", - "bgcolor": "1" - }, - "1,64": { - "contents": "", - "bgcolor": "1" - }, - "1,65": { - "contents": "", - "bgcolor": "1" - }, - "1,66": { - "contents": "", - "bgcolor": "1" - }, - "1,67": { - "contents": "", - "bgcolor": "1" - }, - "1,68": { - "contents": "", - "bgcolor": "1" - }, - "1,69": { - "contents": "", - "bgcolor": "1" - }, - "1,7": { - "contents": "", - "bgcolor": "1" - }, - "1,70": { - "contents": "", - "bgcolor": "1" - }, - "1,71": { - "contents": "", - "bgcolor": "1" - }, - "1,72": { - "contents": "", - "bgcolor": "1" - }, - "1,73": { - "contents": "", - "bgcolor": "1" - }, - "1,74": { - "contents": "", - "bgcolor": "1" - }, - "1,75": { - "contents": "", - "bgcolor": "1" - }, - "1,76": { - "contents": "", - "bgcolor": "1" - }, - "1,77": { - "contents": "", - "bgcolor": "1" - }, - "1,78": { - "contents": "", - "bgcolor": "1" - }, - "1,79": { - "contents": "", - "bgcolor": "1" - }, - "1,8": { - "contents": "", - "bgcolor": "1" - }, - "1,9": { - "contents": "", - "bgcolor": "1" - }, - "10,0": { - "contents": "", - "bgcolor": "1" - }, - "10,1": { - "contents": "", - "bgcolor": "1" - }, - "10,10": { - "contents": "", - "bgcolor": "1" - }, - "10,11": { - "contents": "", - "bgcolor": "1" - }, - "10,12": { - "contents": "", - "bgcolor": "1" - }, - "10,13": { - "contents": "", - "bgcolor": "1" - }, - "10,14": { - "contents": "", - "bgcolor": "1" - }, - "10,15": { - "contents": "", - "bgcolor": "1" - }, - "10,16": { - "contents": "", - "bgcolor": "1" - }, - "10,17": { - "contents": "", - "bgcolor": "1" - }, - "10,18": { - "contents": "", - "bgcolor": "1" - }, - "10,19": { - "contents": "", - "bgcolor": "1" - }, - "10,2": { - "contents": "", - "bgcolor": "1" - }, - "10,20": { - "contents": "", - "bgcolor": "1" - }, - "10,21": { - "contents": "", - "bgcolor": "1" - }, - "10,22": { - "contents": "", - "bgcolor": "1" - }, - "10,23": { - "contents": "", - "bgcolor": "1" - }, - "10,24": { - "contents": "", - "bgcolor": "1" - }, - "10,25": { - "contents": "", - "bgcolor": "1" - }, - "10,26": { - "contents": "", - "bgcolor": "1" - }, - "10,27": { - "contents": "", - "bgcolor": "1" - }, - "10,28": { - "contents": "", - "bgcolor": "1" - }, - "10,29": { - "contents": "", - "bgcolor": "1" - }, - "10,3": { - "contents": "", - "bgcolor": "1" - }, - "10,30": { - "contents": "", - "bgcolor": "1" - }, - "10,31": { - "contents": "", - "bgcolor": "1" - }, - "10,32": { - "contents": "", - "bgcolor": "1" - }, - "10,33": { - "contents": "", - "bgcolor": "1" - }, - "10,34": { - "contents": "", - "bgcolor": "1" - }, - "10,35": { - "contents": "", - "bgcolor": "1" - }, - "10,36": { - "contents": "", - "bgcolor": "1" - }, - "10,37": { - "contents": "", - "bgcolor": "1" - }, - "10,38": { - "contents": "", - "bgcolor": "1" - }, - "10,39": { - "contents": "", - "bgcolor": "1" - }, - "10,4": { - "contents": "", - "bgcolor": "1" - }, - "10,40": { - "contents": "", - "bgcolor": "1" - }, - "10,41": { - "contents": "", - "bgcolor": "1" - }, - "10,42": { - "contents": "", - "bgcolor": "1" - }, - "10,43": { - "contents": "", - "bgcolor": "1" - }, - "10,44": { - "contents": "", - "bgcolor": "1" - }, - "10,45": { - "contents": "", - "bgcolor": "1" - }, - "10,46": { - "contents": "", - "bgcolor": "1" - }, - "10,47": { - "contents": "", - "bgcolor": "1" - }, - "10,48": { - "contents": "", - "bgcolor": "1" - }, - "10,49": { - "contents": "", - "bgcolor": "1" - }, - "10,5": { - "contents": "", - "bgcolor": "1" - }, - "10,50": { - "contents": "", - "bgcolor": "1" - }, - "10,51": { - "contents": "", - "bgcolor": "1" - }, - "10,52": { - "contents": "", - "bgcolor": "1" - }, - "10,53": { - "contents": "", - "bgcolor": "1" - }, - "10,54": { - "contents": "", - "bgcolor": "1" - }, - "10,55": { - "contents": "", - "bgcolor": "1" - }, - "10,56": { - "contents": "", - "bgcolor": "1" - }, - "10,57": { - "contents": "", - "bgcolor": "1" - }, - "10,58": { - "contents": "", - "bgcolor": "1" - }, - "10,59": { - "contents": "", - "bgcolor": "1" - }, - "10,6": { - "contents": "", - "bgcolor": "1" - }, - "10,60": { - "contents": "", - "bgcolor": "1" - }, - "10,61": { - "contents": "", - "bgcolor": "1" - }, - "10,62": { - "contents": "", - "bgcolor": "1" - }, - "10,63": { - "contents": "", - "bgcolor": "1" - }, - "10,64": { - "contents": "", - "bgcolor": "1" - }, - "10,65": { - "contents": "", - "bgcolor": "1" - }, - "10,66": { - "contents": "", - "bgcolor": "1" - }, - "10,67": { - "contents": "", - "bgcolor": "1" - }, - "10,68": { - "contents": "", - "bgcolor": "1" - }, - "10,69": { - "contents": "", - "bgcolor": "1" - }, - "10,7": { - "contents": "", - "bgcolor": "1" - }, - "10,70": { - "contents": "", - "bgcolor": "1" - }, - "10,71": { - "contents": "", - "bgcolor": "1" - }, - "10,72": { - "contents": "", - "bgcolor": "1" - }, - "10,73": { - "contents": "", - "bgcolor": "1" - }, - "10,74": { - "contents": "", - "bgcolor": "1" - }, - "10,75": { - "contents": "", - "bgcolor": "1" - }, - "10,76": { - "contents": "", - "bgcolor": "1" - }, - "10,77": { - "contents": "", - "bgcolor": "1" - }, - "10,78": { - "contents": "", - "bgcolor": "1" - }, - "10,79": { - "contents": "", - "bgcolor": "1" - }, - "10,8": { - "contents": "", - "bgcolor": "1" - }, - "10,9": { - "contents": "", - "bgcolor": "1" - }, - "11,0": { - "contents": "", - "bgcolor": "1" - }, - "11,1": { - "contents": "", - "bgcolor": "1" - }, - "11,10": { - "contents": "", - "bgcolor": "1" - }, - "11,11": { - "contents": "", - "bgcolor": "1" - }, - "11,12": { - "contents": "", - "bgcolor": "1" - }, - "11,13": { - "contents": "", - "bgcolor": "1" - }, - "11,14": { - "contents": "", - "bgcolor": "1" - }, - "11,15": { - "contents": "", - "bgcolor": "1" - }, - "11,16": { - "contents": "", - "bgcolor": "1" - }, - "11,17": { - "contents": "", - "bgcolor": "1" - }, - "11,18": { - "contents": "", - "bgcolor": "1" - }, - "11,19": { - "contents": "", - "bgcolor": "1" - }, - "11,2": { - "contents": "", - "bgcolor": "1" - }, - "11,20": { - "contents": "", - "bgcolor": "1" - }, - "11,21": { - "contents": "", - "bgcolor": "1" - }, - "11,22": { - "contents": "", - "bgcolor": "1" - }, - "11,23": { - "contents": "", - "bgcolor": "1" - }, - "11,24": { - "contents": "", - "bgcolor": "1" - }, - "11,25": { - "contents": "", - "bgcolor": "1" - }, - "11,26": { - "contents": "", - "bgcolor": "1" - }, - "11,27": { - "contents": "", - "bgcolor": "1" - }, - "11,28": { - "contents": "", - "bgcolor": "1" - }, - "11,29": { - "contents": "", - "bgcolor": "1" - }, - "11,3": { - "contents": "", - "bgcolor": "1" - }, - "11,30": { - "contents": "", - "bgcolor": "1" - }, - "11,31": { - "contents": "", - "bgcolor": "1" - }, - "11,32": { - "contents": "", - "bgcolor": "1" - }, - "11,33": { - "contents": "", - "bgcolor": "1" - }, - "11,34": { - "contents": "", - "bgcolor": "1" - }, - "11,35": { - "contents": "", - "bgcolor": "1" - }, - "11,36": { - "contents": "", - "bgcolor": "1" - }, - "11,37": { - "contents": "", - "bgcolor": "1" - }, - "11,38": { - "contents": "", - "bgcolor": "1" - }, - "11,39": { - "contents": "", - "bgcolor": "1" - }, - "11,4": { - "contents": "", - "bgcolor": "1" - }, - "11,40": { - "contents": "", - "bgcolor": "1" - }, - "11,41": { - "contents": "", - "bgcolor": "1" - }, - "11,42": { - "contents": "", - "bgcolor": "1" - }, - "11,43": { - "contents": "", - "bgcolor": "1" - }, - "11,44": { - "contents": "", - "bgcolor": "1" - }, - "11,45": { - "contents": "", - "bgcolor": "1" - }, - "11,46": { - "contents": "", - "bgcolor": "1" - }, - "11,47": { - "contents": "", - "bgcolor": "1" - }, - "11,48": { - "contents": "", - "bgcolor": "1" - }, - "11,49": { - "contents": "", - "bgcolor": "1" - }, - "11,5": { - "contents": "", - "bgcolor": "1" - }, - "11,50": { - "contents": "", - "bgcolor": "1" - }, - "11,51": { - "contents": "", - "bgcolor": "1" - }, - "11,52": { - "contents": "", - "bgcolor": "1" - }, - "11,53": { - "contents": "", - "bgcolor": "1" - }, - "11,54": { - "contents": "", - "bgcolor": "1" - }, - "11,55": { - "contents": "", - "bgcolor": "1" - }, - "11,56": { - "contents": "", - "bgcolor": "1" - }, - "11,57": { - "contents": "", - "bgcolor": "1" - }, - "11,58": { - "contents": "", - "bgcolor": "1" - }, - "11,59": { - "contents": "", - "bgcolor": "1" - }, - "11,6": { - "contents": "", - "bgcolor": "1" - }, - "11,60": { - "contents": "", - "bgcolor": "1" - }, - "11,61": { - "contents": "", - "bgcolor": "1" - }, - "11,62": { - "contents": "", - "bgcolor": "1" - }, - "11,63": { - "contents": "", - "bgcolor": "1" - }, - "11,64": { - "contents": "", - "bgcolor": "1" - }, - "11,65": { - "contents": "", - "bgcolor": "1" - }, - "11,66": { - "contents": "", - "bgcolor": "1" - }, - "11,67": { - "contents": "", - "bgcolor": "1" - }, - "11,68": { - "contents": "", - "bgcolor": "1" - }, - "11,69": { - "contents": "", - "bgcolor": "1" - }, - "11,7": { - "contents": "", - "bgcolor": "1" - }, - "11,70": { - "contents": "", - "bgcolor": "1" - }, - "11,71": { - "contents": "", - "bgcolor": "1" - }, - "11,72": { - "contents": "", - "bgcolor": "1" - }, - "11,73": { - "contents": "", - "bgcolor": "1" - }, - "11,74": { - "contents": "", - "bgcolor": "1" - }, - "11,75": { - "contents": "", - "bgcolor": "1" - }, - "11,76": { - "contents": "", - "bgcolor": "1" - }, - "11,77": { - "contents": "", - "bgcolor": "1" - }, - "11,78": { - "contents": "", - "bgcolor": "1" - }, - "11,79": { - "contents": "", - "bgcolor": "1" - }, - "11,8": { - "contents": "", - "bgcolor": "1" - }, - "11,9": { - "contents": "", - "bgcolor": "1" - }, - "12,0": { - "contents": "", - "bgcolor": "1" - }, - "12,1": { - "contents": "", - "bgcolor": "1" - }, - "12,10": { - "contents": "", - "bgcolor": "1" - }, - "12,11": { - "contents": "", - "bgcolor": "1" - }, - "12,12": { - "contents": "", - "bgcolor": "1" - }, - "12,13": { - "contents": "", - "bgcolor": "1" - }, - "12,14": { - "contents": "", - "bgcolor": "1" - }, - "12,15": { - "contents": "", - "bgcolor": "1" - }, - "12,16": { - "contents": "", - "bgcolor": "1" - }, - "12,17": { - "contents": "", - "bgcolor": "1" - }, - "12,18": { - "contents": "", - "bgcolor": "1" - }, - "12,19": { - "contents": "", - "bgcolor": "1" - }, - "12,2": { - "contents": "", - "bgcolor": "1" - }, - "12,20": { - "contents": "", - "bgcolor": "1" - }, - "12,21": { - "contents": "", - "bgcolor": "1" - }, - "12,22": { - "contents": "", - "bgcolor": "1" - }, - "12,23": { - "contents": "", - "bgcolor": "1" - }, - "12,24": { - "contents": "", - "bgcolor": "1" - }, - "12,25": { - "contents": "", - "bgcolor": "1" - }, - "12,26": { - "contents": "", - "bgcolor": "1" - }, - "12,27": { - "contents": "", - "bgcolor": "1" - }, - "12,28": { - "contents": "", - "bgcolor": "1" - }, - "12,29": { - "contents": "", - "bgcolor": "1" - }, - "12,3": { - "contents": "", - "bgcolor": "1" - }, - "12,30": { - "contents": "", - "bgcolor": "1" - }, - "12,31": { - "contents": "", - "bgcolor": "1" - }, - "12,32": { - "contents": "", - "bgcolor": "1" - }, - "12,33": { - "contents": "", - "bgcolor": "1" - }, - "12,34": { - "contents": "", - "bgcolor": "1" - }, - "12,35": { - "contents": "", - "bgcolor": "1" - }, - "12,36": { - "contents": "", - "bgcolor": "1" - }, - "12,37": { - "contents": "", - "bgcolor": "1" - }, - "12,38": { - "contents": "", - "bgcolor": "1" - }, - "12,39": { - "contents": "", - "bgcolor": "1" - }, - "12,4": { - "contents": "", - "bgcolor": "1" - }, - "12,40": { - "contents": "", - "bgcolor": "1" - }, - "12,41": { - "contents": "", - "bgcolor": "1" - }, - "12,42": { - "contents": "", - "bgcolor": "1" - }, - "12,43": { - "contents": "", - "bgcolor": "1" - }, - "12,44": { - "contents": "", - "bgcolor": "1" - }, - "12,45": { - "contents": "", - "bgcolor": "1" - }, - "12,46": { - "contents": "", - "bgcolor": "1" - }, - "12,47": { - "contents": "", - "bgcolor": "1" - }, - "12,48": { - "contents": "", - "bgcolor": "1" - }, - "12,49": { - "contents": "", - "bgcolor": "1" - }, - "12,5": { - "contents": "", - "bgcolor": "1" - }, - "12,50": { - "contents": "", - "bgcolor": "1" - }, - "12,51": { - "contents": "", - "bgcolor": "1" - }, - "12,52": { - "contents": "", - "bgcolor": "1" - }, - "12,53": { - "contents": "", - "bgcolor": "1" - }, - "12,54": { - "contents": "", - "bgcolor": "1" - }, - "12,55": { - "contents": "", - "bgcolor": "1" - }, - "12,56": { - "contents": "", - "bgcolor": "1" - }, - "12,57": { - "contents": "", - "bgcolor": "1" - }, - "12,58": { - "contents": "", - "bgcolor": "1" - }, - "12,59": { - "contents": "", - "bgcolor": "1" - }, - "12,6": { - "contents": "", - "bgcolor": "1" - }, - "12,60": { - "contents": "", - "bgcolor": "1" - }, - "12,61": { - "contents": "", - "bgcolor": "1" - }, - "12,62": { - "contents": "", - "bgcolor": "1" - }, - "12,63": { - "contents": "", - "bgcolor": "1" - }, - "12,64": { - "contents": "", - "bgcolor": "1" - }, - "12,65": { - "contents": "", - "bgcolor": "1" - }, - "12,66": { - "contents": "", - "bgcolor": "1" - }, - "12,67": { - "contents": "", - "bgcolor": "1" - }, - "12,68": { - "contents": "", - "bgcolor": "1" - }, - "12,69": { - "contents": "", - "bgcolor": "1" - }, - "12,7": { - "contents": "", - "bgcolor": "1" - }, - "12,70": { - "contents": "", - "bgcolor": "1" - }, - "12,71": { - "contents": "", - "bgcolor": "1" - }, - "12,72": { - "contents": "", - "bgcolor": "1" - }, - "12,73": { - "contents": "", - "bgcolor": "1" - }, - "12,74": { - "contents": "", - "bgcolor": "1" - }, - "12,75": { - "contents": "", - "bgcolor": "1" - }, - "12,76": { - "contents": "", - "bgcolor": "1" - }, - "12,77": { - "contents": "", - "bgcolor": "1" - }, - "12,78": { - "contents": "", - "bgcolor": "1" - }, - "12,79": { - "contents": "", - "bgcolor": "1" - }, - "12,8": { - "contents": "", - "bgcolor": "1" - }, - "12,9": { - "contents": "", - "bgcolor": "1" - }, - "13,0": { - "contents": "", - "bgcolor": "1" - }, - "13,1": { - "contents": "", - "bgcolor": "1" - }, - "13,10": { - "contents": "", - "bgcolor": "1" - }, - "13,11": { - "contents": "", - "bgcolor": "1" - }, - "13,12": { - "contents": "", - "bgcolor": "1" - }, - "13,13": { - "contents": "", - "bgcolor": "1" - }, - "13,14": { - "contents": "", - "bgcolor": "1" - }, - "13,15": { - "contents": "", - "bgcolor": "1" - }, - "13,16": { - "contents": "", - "bgcolor": "1" - }, - "13,17": { - "contents": "", - "bgcolor": "1" - }, - "13,18": { - "contents": "", - "bgcolor": "1" - }, - "13,19": { - "contents": "", - "bgcolor": "1" - }, - "13,2": { - "contents": "", - "bgcolor": "1" - }, - "13,20": { - "contents": "", - "bgcolor": "1" - }, - "13,21": { - "contents": "", - "bgcolor": "1" - }, - "13,22": { - "contents": "", - "bgcolor": "1" - }, - "13,23": { - "contents": "", - "bgcolor": "1" - }, - "13,24": { - "contents": "", - "bgcolor": "1" - }, - "13,25": { - "contents": "", - "bgcolor": "1" - }, - "13,26": { - "contents": "", - "bgcolor": "1" - }, - "13,27": { - "contents": "", - "bgcolor": "1" - }, - "13,28": { - "contents": "", - "bgcolor": "1" - }, - "13,29": { - "contents": "", - "bgcolor": "1" - }, - "13,3": { - "contents": "", - "bgcolor": "1" - }, - "13,30": { - "contents": "", - "bgcolor": "1" - }, - "13,31": { - "contents": "", - "bgcolor": "1" - }, - "13,32": { - "contents": "", - "bgcolor": "1" - }, - "13,33": { - "contents": "", - "bgcolor": "1" - }, - "13,34": { - "contents": "", - "bgcolor": "1" - }, - "13,35": { - "contents": "", - "bgcolor": "1" - }, - "13,36": { - "contents": "", - "bgcolor": "1" - }, - "13,37": { - "contents": "", - "bgcolor": "1" - }, - "13,38": { - "contents": "", - "bgcolor": "1" - }, - "13,39": { - "contents": "", - "bgcolor": "1" - }, - "13,4": { - "contents": "", - "bgcolor": "1" - }, - "13,40": { - "contents": "", - "bgcolor": "1" - }, - "13,41": { - "contents": "", - "bgcolor": "1" - }, - "13,42": { - "contents": "", - "bgcolor": "1" - }, - "13,43": { - "contents": "", - "bgcolor": "1" - }, - "13,44": { - "contents": "", - "bgcolor": "1" - }, - "13,45": { - "contents": "", - "bgcolor": "1" - }, - "13,46": { - "contents": "", - "bgcolor": "1" - }, - "13,47": { - "contents": "", - "bgcolor": "1" - }, - "13,48": { - "contents": "", - "bgcolor": "1" - }, - "13,49": { - "contents": "", - "bgcolor": "1" - }, - "13,5": { - "contents": "", - "bgcolor": "1" - }, - "13,50": { - "contents": "", - "bgcolor": "1" - }, - "13,51": { - "contents": "", - "bgcolor": "1" - }, - "13,52": { - "contents": "", - "bgcolor": "1" - }, - "13,53": { - "contents": "", - "bgcolor": "1" - }, - "13,54": { - "contents": "", - "bgcolor": "1" - }, - "13,55": { - "contents": "", - "bgcolor": "1" - }, - "13,56": { - "contents": "", - "bgcolor": "1" - }, - "13,57": { - "contents": "", - "bgcolor": "1" - }, - "13,58": { - "contents": "", - "bgcolor": "1" - }, - "13,59": { - "contents": "", - "bgcolor": "1" - }, - "13,6": { - "contents": "", - "bgcolor": "1" - }, - "13,60": { - "contents": "", - "bgcolor": "1" - }, - "13,61": { - "contents": "", - "bgcolor": "1" - }, - "13,62": { - "contents": "", - "bgcolor": "1" - }, - "13,63": { - "contents": "", - "bgcolor": "1" - }, - "13,64": { - "contents": "", - "bgcolor": "1" - }, - "13,65": { - "contents": "", - "bgcolor": "1" - }, - "13,66": { - "contents": "", - "bgcolor": "1" - }, - "13,67": { - "contents": "", - "bgcolor": "1" - }, - "13,68": { - "contents": "", - "bgcolor": "1" - }, - "13,69": { - "contents": "", - "bgcolor": "1" - }, - "13,7": { - "contents": "", - "bgcolor": "1" - }, - "13,70": { - "contents": "", - "bgcolor": "1" - }, - "13,71": { - "contents": "", - "bgcolor": "1" - }, - "13,72": { - "contents": "", - "bgcolor": "1" - }, - "13,73": { - "contents": "", - "bgcolor": "1" - }, - "13,74": { - "contents": "", - "bgcolor": "1" - }, - "13,75": { - "contents": "", - "bgcolor": "1" - }, - "13,76": { - "contents": "", - "bgcolor": "1" - }, - "13,77": { - "contents": "", - "bgcolor": "1" - }, - "13,78": { - "contents": "", - "bgcolor": "1" - }, - "13,79": { - "contents": "", - "bgcolor": "1" - }, - "13,8": { - "contents": "", - "bgcolor": "1" - }, - "13,9": { - "contents": "", - "bgcolor": "1" - }, - "14,0": { - "contents": "", - "bgcolor": "1" - }, - "14,1": { - "contents": "", - "bgcolor": "1" - }, - "14,10": { - "contents": "", - "bgcolor": "1" - }, - "14,11": { - "contents": "", - "bgcolor": "1" - }, - "14,12": { - "contents": "", - "bgcolor": "1" - }, - "14,13": { - "contents": "", - "bgcolor": "1" - }, - "14,14": { - "contents": "", - "bgcolor": "1" - }, - "14,15": { - "contents": "", - "bgcolor": "1" - }, - "14,16": { - "contents": "", - "bgcolor": "1" - }, - "14,17": { - "contents": "", - "bgcolor": "1" - }, - "14,18": { - "contents": "", - "bgcolor": "1" - }, - "14,19": { - "contents": "", - "bgcolor": "1" - }, - "14,2": { - "contents": "", - "bgcolor": "1" - }, - "14,20": { - "contents": "", - "bgcolor": "1" - }, - "14,21": { - "contents": "", - "bgcolor": "1" - }, - "14,22": { - "contents": "", - "bgcolor": "1" - }, - "14,23": { - "contents": "", - "bgcolor": "1" - }, - "14,24": { - "contents": "", - "bgcolor": "1" - }, - "14,25": { - "contents": "", - "bgcolor": "1" - }, - "14,26": { - "contents": "", - "bgcolor": "1" - }, - "14,27": { - "contents": "", - "bgcolor": "1" - }, - "14,28": { - "contents": "", - "bgcolor": "1" - }, - "14,29": { - "contents": "", - "bgcolor": "1" - }, - "14,3": { - "contents": "", - "bgcolor": "1" - }, - "14,30": { - "contents": "", - "bgcolor": "1" - }, - "14,31": { - "contents": "", - "bgcolor": "1" - }, - "14,32": { - "contents": "", - "bgcolor": "1" - }, - "14,33": { - "contents": "", - "bgcolor": "1" - }, - "14,34": { - "contents": "", - "bgcolor": "1" - }, - "14,35": { - "contents": "", - "bgcolor": "1" - }, - "14,36": { - "contents": "", - "bgcolor": "1" - }, - "14,37": { - "contents": "", - "bgcolor": "1" - }, - "14,38": { - "contents": "", - "bgcolor": "1" - }, - "14,39": { - "contents": "", - "bgcolor": "1" - }, - "14,4": { - "contents": "", - "bgcolor": "1" - }, - "14,40": { - "contents": "", - "bgcolor": "1" - }, - "14,41": { - "contents": "", - "bgcolor": "1" - }, - "14,42": { - "contents": "", - "bgcolor": "1" - }, - "14,43": { - "contents": "", - "bgcolor": "1" - }, - "14,44": { - "contents": "", - "bgcolor": "1" - }, - "14,45": { - "contents": "", - "bgcolor": "1" - }, - "14,46": { - "contents": "", - "bgcolor": "1" - }, - "14,47": { - "contents": "", - "bgcolor": "1" - }, - "14,48": { - "contents": "", - "bgcolor": "1" - }, - "14,49": { - "contents": "", - "bgcolor": "1" - }, - "14,5": { - "contents": "", - "bgcolor": "1" - }, - "14,50": { - "contents": "", - "bgcolor": "1" - }, - "14,51": { - "contents": "", - "bgcolor": "1" - }, - "14,52": { - "contents": "", - "bgcolor": "1" - }, - "14,53": { - "contents": "", - "bgcolor": "1" - }, - "14,54": { - "contents": "", - "bgcolor": "1" - }, - "14,55": { - "contents": "", - "bgcolor": "1" - }, - "14,56": { - "contents": "", - "bgcolor": "1" - }, - "14,57": { - "contents": "", - "bgcolor": "1" - }, - "14,58": { - "contents": "", - "bgcolor": "1" - }, - "14,59": { - "contents": "", - "bgcolor": "1" - }, - "14,6": { - "contents": "", - "bgcolor": "1" - }, - "14,60": { - "contents": "", - "bgcolor": "1" - }, - "14,61": { - "contents": "", - "bgcolor": "1" - }, - "14,62": { - "contents": "", - "bgcolor": "1" - }, - "14,63": { - "contents": "", - "bgcolor": "1" - }, - "14,64": { - "contents": "", - "bgcolor": "1" - }, - "14,65": { - "contents": "", - "bgcolor": "1" - }, - "14,66": { - "contents": "", - "bgcolor": "1" - }, - "14,67": { - "contents": "", - "bgcolor": "1" - }, - "14,68": { - "contents": "", - "bgcolor": "1" - }, - "14,69": { - "contents": "", - "bgcolor": "1" - }, - "14,7": { - "contents": "", - "bgcolor": "1" - }, - "14,70": { - "contents": "", - "bgcolor": "1" - }, - "14,71": { - "contents": "", - "bgcolor": "1" - }, - "14,72": { - "contents": "", - "bgcolor": "1" - }, - "14,73": { - "contents": "", - "bgcolor": "1" - }, - "14,74": { - "contents": "", - "bgcolor": "1" - }, - "14,75": { - "contents": "", - "bgcolor": "1" - }, - "14,76": { - "contents": "", - "bgcolor": "1" - }, - "14,77": { - "contents": "", - "bgcolor": "1" - }, - "14,78": { - "contents": "", - "bgcolor": "1" - }, - "14,79": { - "contents": "", - "bgcolor": "1" - }, - "14,8": { - "contents": "", - "bgcolor": "1" - }, - "14,9": { - "contents": "", - "bgcolor": "1" - }, - "15,0": { - "contents": "", - "bgcolor": "1" - }, - "15,1": { - "contents": "", - "bgcolor": "1" - }, - "15,10": { - "contents": "", - "bgcolor": "1" - }, - "15,11": { - "contents": "", - "bgcolor": "1" - }, - "15,12": { - "contents": "", - "bgcolor": "1" - }, - "15,13": { - "contents": "", - "bgcolor": "1" - }, - "15,14": { - "contents": "", - "bgcolor": "1" - }, - "15,15": { - "contents": "", - "bgcolor": "1" - }, - "15,16": { - "contents": "", - "bgcolor": "1" - }, - "15,17": { - "contents": "", - "bgcolor": "1" - }, - "15,18": { - "contents": "", - "bgcolor": "1" - }, - "15,19": { - "contents": "", - "bgcolor": "1" - }, - "15,2": { - "contents": "", - "bgcolor": "1" - }, - "15,20": { - "contents": "", - "bgcolor": "1" - }, - "15,21": { - "contents": "", - "bgcolor": "1" - }, - "15,22": { - "contents": "", - "bgcolor": "1" - }, - "15,23": { - "contents": "", - "bgcolor": "1" - }, - "15,24": { - "contents": "", - "bgcolor": "1" - }, - "15,25": { - "contents": "", - "bgcolor": "1" - }, - "15,26": { - "contents": "", - "bgcolor": "1" - }, - "15,27": { - "contents": "", - "bgcolor": "1" - }, - "15,28": { - "contents": "", - "bgcolor": "1" - }, - "15,29": { - "contents": "", - "bgcolor": "1" - }, - "15,3": { - "contents": "", - "bgcolor": "1" - }, - "15,30": { - "contents": "", - "bgcolor": "1" - }, - "15,31": { - "contents": "", - "bgcolor": "1" - }, - "15,32": { - "contents": "", - "bgcolor": "1" - }, - "15,33": { - "contents": "", - "bgcolor": "1" - }, - "15,34": { - "contents": "", - "bgcolor": "1" - }, - "15,35": { - "contents": "", - "bgcolor": "1" - }, - "15,36": { - "contents": "", - "bgcolor": "1" - }, - "15,37": { - "contents": "", - "bgcolor": "1" - }, - "15,38": { - "contents": "", - "bgcolor": "1" - }, - "15,39": { - "contents": "", - "bgcolor": "1" - }, - "15,4": { - "contents": "", - "bgcolor": "1" - }, - "15,40": { - "contents": "", - "bgcolor": "1" - }, - "15,41": { - "contents": "", - "bgcolor": "1" - }, - "15,42": { - "contents": "", - "bgcolor": "1" - }, - "15,43": { - "contents": "", - "bgcolor": "1" - }, - "15,44": { - "contents": "", - "bgcolor": "1" - }, - "15,45": { - "contents": "", - "bgcolor": "1" - }, - "15,46": { - "contents": "", - "bgcolor": "1" - }, - "15,47": { - "contents": "", - "bgcolor": "1" - }, - "15,48": { - "contents": "", - "bgcolor": "1" - }, - "15,49": { - "contents": "", - "bgcolor": "1" - }, - "15,5": { - "contents": "", - "bgcolor": "1" - }, - "15,50": { - "contents": "", - "bgcolor": "1" - }, - "15,51": { - "contents": "", - "bgcolor": "1" - }, - "15,52": { - "contents": "", - "bgcolor": "1" - }, - "15,53": { - "contents": "", - "bgcolor": "1" - }, - "15,54": { - "contents": "", - "bgcolor": "1" - }, - "15,55": { - "contents": "", - "bgcolor": "1" - }, - "15,56": { - "contents": "", - "bgcolor": "1" - }, - "15,57": { - "contents": "", - "bgcolor": "1" - }, - "15,58": { - "contents": "", - "bgcolor": "1" - }, - "15,59": { - "contents": "", - "bgcolor": "1" - }, - "15,6": { - "contents": "", - "bgcolor": "1" - }, - "15,60": { - "contents": "", - "bgcolor": "1" - }, - "15,61": { - "contents": "", - "bgcolor": "1" - }, - "15,62": { - "contents": "", - "bgcolor": "1" - }, - "15,63": { - "contents": "", - "bgcolor": "1" - }, - "15,64": { - "contents": "", - "bgcolor": "1" - }, - "15,65": { - "contents": "", - "bgcolor": "1" - }, - "15,66": { - "contents": "", - "bgcolor": "1" - }, - "15,67": { - "contents": "", - "bgcolor": "1" - }, - "15,68": { - "contents": "", - "bgcolor": "1" - }, - "15,69": { - "contents": "", - "bgcolor": "1" - }, - "15,7": { - "contents": "", - "bgcolor": "1" - }, - "15,70": { - "contents": "", - "bgcolor": "1" - }, - "15,71": { - "contents": "", - "bgcolor": "1" - }, - "15,72": { - "contents": "", - "bgcolor": "1" - }, - "15,73": { - "contents": "", - "bgcolor": "1" - }, - "15,74": { - "contents": "", - "bgcolor": "1" - }, - "15,75": { - "contents": "", - "bgcolor": "1" - }, - "15,76": { - "contents": "", - "bgcolor": "1" - }, - "15,77": { - "contents": "", - "bgcolor": "1" - }, - "15,78": { - "contents": "", - "bgcolor": "1" - }, - "15,79": { - "contents": "", - "bgcolor": "1" - }, - "15,8": { - "contents": "", - "bgcolor": "1" - }, - "15,9": { - "contents": "", - "bgcolor": "1" - }, - "16,0": { - "contents": "", - "bgcolor": "1" - }, - "16,1": { - "contents": "", - "bgcolor": "1" - }, - "16,10": { - "contents": "", - "bgcolor": "1" - }, - "16,11": { - "contents": "", - "bgcolor": "1" - }, - "16,12": { - "contents": "", - "bgcolor": "1" - }, - "16,13": { - "contents": "", - "bgcolor": "1" - }, - "16,14": { - "contents": "", - "bgcolor": "1" - }, - "16,15": { - "contents": "", - "bgcolor": "1" - }, - "16,16": { - "contents": "", - "bgcolor": "1" - }, - "16,17": { - "contents": "", - "bgcolor": "1" - }, - "16,18": { - "contents": "", - "bgcolor": "1" - }, - "16,19": { - "contents": "", - "bgcolor": "1" - }, - "16,2": { - "contents": "", - "bgcolor": "1" - }, - "16,20": { - "contents": "", - "bgcolor": "1" - }, - "16,21": { - "contents": "", - "bgcolor": "1" - }, - "16,22": { - "contents": "", - "bgcolor": "1" - }, - "16,23": { - "contents": "", - "bgcolor": "1" - }, - "16,24": { - "contents": "", - "bgcolor": "1" - }, - "16,25": { - "contents": "", - "bgcolor": "1" - }, - "16,26": { - "contents": "", - "bgcolor": "1" - }, - "16,27": { - "contents": "", - "bgcolor": "1" - }, - "16,28": { - "contents": "", - "bgcolor": "1" - }, - "16,29": { - "contents": "", - "bgcolor": "1" - }, - "16,3": { - "contents": "", - "bgcolor": "1" - }, - "16,30": { - "contents": "", - "bgcolor": "1" - }, - "16,31": { - "contents": "", - "bgcolor": "1" - }, - "16,32": { - "contents": "", - "bgcolor": "1" - }, - "16,33": { - "contents": "", - "bgcolor": "1" - }, - "16,34": { - "contents": "", - "bgcolor": "1" - }, - "16,35": { - "contents": "", - "bgcolor": "1" - }, - "16,36": { - "contents": "", - "bgcolor": "1" - }, - "16,37": { - "contents": "", - "bgcolor": "1" - }, - "16,38": { - "contents": "", - "bgcolor": "1" - }, - "16,39": { - "contents": "", - "bgcolor": "1" - }, - "16,4": { - "contents": "", - "bgcolor": "1" - }, - "16,40": { - "contents": "", - "bgcolor": "1" - }, - "16,41": { - "contents": "", - "bgcolor": "1" - }, - "16,42": { - "contents": "", - "bgcolor": "1" - }, - "16,43": { - "contents": "", - "bgcolor": "1" - }, - "16,44": { - "contents": "", - "bgcolor": "1" - }, - "16,45": { - "contents": "", - "bgcolor": "1" - }, - "16,46": { - "contents": "", - "bgcolor": "1" - }, - "16,47": { - "contents": "", - "bgcolor": "1" - }, - "16,48": { - "contents": "", - "bgcolor": "1" - }, - "16,49": { - "contents": "", - "bgcolor": "1" - }, - "16,5": { - "contents": "", - "bgcolor": "1" - }, - "16,50": { - "contents": "", - "bgcolor": "1" - }, - "16,51": { - "contents": "", - "bgcolor": "1" - }, - "16,52": { - "contents": "", - "bgcolor": "1" - }, - "16,53": { - "contents": "", - "bgcolor": "1" - }, - "16,54": { - "contents": "", - "bgcolor": "1" - }, - "16,55": { - "contents": "", - "bgcolor": "1" - }, - "16,56": { - "contents": "", - "bgcolor": "1" - }, - "16,57": { - "contents": "", - "bgcolor": "1" - }, - "16,58": { - "contents": "", - "bgcolor": "1" - }, - "16,59": { - "contents": "", - "bgcolor": "1" - }, - "16,6": { - "contents": "", - "bgcolor": "1" - }, - "16,60": { - "contents": "", - "bgcolor": "1" - }, - "16,61": { - "contents": "", - "bgcolor": "1" - }, - "16,62": { - "contents": "", - "bgcolor": "1" - }, - "16,63": { - "contents": "", - "bgcolor": "1" - }, - "16,64": { - "contents": "", - "bgcolor": "1" - }, - "16,65": { - "contents": "", - "bgcolor": "1" - }, - "16,66": { - "contents": "", - "bgcolor": "1" - }, - "16,67": { - "contents": "", - "bgcolor": "1" - }, - "16,68": { - "contents": "", - "bgcolor": "1" - }, - "16,69": { - "contents": "", - "bgcolor": "1" - }, - "16,7": { - "contents": "", - "bgcolor": "1" - }, - "16,70": { - "contents": "", - "bgcolor": "1" - }, - "16,71": { - "contents": "", - "bgcolor": "1" - }, - "16,72": { - "contents": "", - "bgcolor": "1" - }, - "16,73": { - "contents": "", - "bgcolor": "1" - }, - "16,74": { - "contents": "", - "bgcolor": "1" - }, - "16,75": { - "contents": "", - "bgcolor": "1" - }, - "16,76": { - "contents": "", - "bgcolor": "1" - }, - "16,77": { - "contents": "", - "bgcolor": "1" - }, - "16,78": { - "contents": "", - "bgcolor": "1" - }, - "16,79": { - "contents": "", - "bgcolor": "1" - }, - "16,8": { - "contents": "", - "bgcolor": "1" - }, - "16,9": { - "contents": "", - "bgcolor": "1" - }, - "17,0": { - "contents": "", - "bgcolor": "1" - }, - "17,1": { - "contents": "", - "bgcolor": "1" - }, - "17,10": { - "contents": "", - "bgcolor": "1" - }, - "17,11": { - "contents": "", - "bgcolor": "1" - }, - "17,12": { - "contents": "", - "bgcolor": "1" - }, - "17,13": { - "contents": "", - "bgcolor": "1" - }, - "17,14": { - "contents": "", - "bgcolor": "1" - }, - "17,15": { - "contents": "", - "bgcolor": "1" - }, - "17,16": { - "contents": "", - "bgcolor": "1" - }, - "17,17": { - "contents": "", - "bgcolor": "1" - }, - "17,18": { - "contents": "", - "bgcolor": "1" - }, - "17,19": { - "contents": "", - "bgcolor": "1" - }, - "17,2": { - "contents": "", - "bgcolor": "1" - }, - "17,20": { - "contents": "", - "bgcolor": "1" - }, - "17,21": { - "contents": "", - "bgcolor": "1" - }, - "17,22": { - "contents": "", - "bgcolor": "1" - }, - "17,23": { - "contents": "", - "bgcolor": "1" - }, - "17,24": { - "contents": "", - "bgcolor": "1" - }, - "17,25": { - "contents": "", - "bgcolor": "1" - }, - "17,26": { - "contents": "", - "bgcolor": "1" - }, - "17,27": { - "contents": "", - "bgcolor": "1" - }, - "17,28": { - "contents": "", - "bgcolor": "1" - }, - "17,29": { - "contents": "", - "bgcolor": "1" - }, - "17,3": { - "contents": "", - "bgcolor": "1" - }, - "17,30": { - "contents": "", - "bgcolor": "1" - }, - "17,31": { - "contents": "", - "bgcolor": "1" - }, - "17,32": { - "contents": "", - "bgcolor": "1" - }, - "17,33": { - "contents": "", - "bgcolor": "1" - }, - "17,34": { - "contents": "", - "bgcolor": "1" - }, - "17,35": { - "contents": "", - "bgcolor": "1" - }, - "17,36": { - "contents": "", - "bgcolor": "1" - }, - "17,37": { - "contents": "", - "bgcolor": "1" - }, - "17,38": { - "contents": "", - "bgcolor": "1" - }, - "17,39": { - "contents": "", - "bgcolor": "1" - }, - "17,4": { - "contents": "", - "bgcolor": "1" - }, - "17,40": { - "contents": "", - "bgcolor": "1" - }, - "17,41": { - "contents": "", - "bgcolor": "1" - }, - "17,42": { - "contents": "", - "bgcolor": "1" - }, - "17,43": { - "contents": "", - "bgcolor": "1" - }, - "17,44": { - "contents": "", - "bgcolor": "1" - }, - "17,45": { - "contents": "", - "bgcolor": "1" - }, - "17,46": { - "contents": "", - "bgcolor": "1" - }, - "17,47": { - "contents": "", - "bgcolor": "1" - }, - "17,48": { - "contents": "", - "bgcolor": "1" - }, - "17,49": { - "contents": "", - "bgcolor": "1" - }, - "17,5": { - "contents": "", - "bgcolor": "1" - }, - "17,50": { - "contents": "", - "bgcolor": "1" - }, - "17,51": { - "contents": "", - "bgcolor": "1" - }, - "17,52": { - "contents": "", - "bgcolor": "1" - }, - "17,53": { - "contents": "", - "bgcolor": "1" - }, - "17,54": { - "contents": "", - "bgcolor": "1" - }, - "17,55": { - "contents": "", - "bgcolor": "1" - }, - "17,56": { - "contents": "", - "bgcolor": "1" - }, - "17,57": { - "contents": "", - "bgcolor": "1" - }, - "17,58": { - "contents": "", - "bgcolor": "1" - }, - "17,59": { - "contents": "", - "bgcolor": "1" - }, - "17,6": { - "contents": "", - "bgcolor": "1" - }, - "17,60": { - "contents": "", - "bgcolor": "1" - }, - "17,61": { - "contents": "", - "bgcolor": "1" - }, - "17,62": { - "contents": "", - "bgcolor": "1" - }, - "17,63": { - "contents": "", - "bgcolor": "1" - }, - "17,64": { - "contents": "", - "bgcolor": "1" - }, - "17,65": { - "contents": "", - "bgcolor": "1" - }, - "17,66": { - "contents": "", - "bgcolor": "1" - }, - "17,67": { - "contents": "", - "bgcolor": "1" - }, - "17,68": { - "contents": "", - "bgcolor": "1" - }, - "17,69": { - "contents": "", - "bgcolor": "1" - }, - "17,7": { - "contents": "", - "bgcolor": "1" - }, - "17,70": { - "contents": "", - "bgcolor": "1" - }, - "17,71": { - "contents": "", - "bgcolor": "1" - }, - "17,72": { - "contents": "", - "bgcolor": "1" - }, - "17,73": { - "contents": "", - "bgcolor": "1" - }, - "17,74": { - "contents": "", - "bgcolor": "1" - }, - "17,75": { - "contents": "", - "bgcolor": "1" - }, - "17,76": { - "contents": "", - "bgcolor": "1" - }, - "17,77": { - "contents": "", - "bgcolor": "1" - }, - "17,78": { - "contents": "", - "bgcolor": "1" - }, - "17,79": { - "contents": "", - "bgcolor": "1" - }, - "17,8": { - "contents": "", - "bgcolor": "1" - }, - "17,9": { - "contents": "", - "bgcolor": "1" - }, - "18,0": { - "contents": "", - "bgcolor": "1" - }, - "18,1": { - "contents": "", - "bgcolor": "1" - }, - "18,10": { - "contents": "", - "bgcolor": "1" - }, - "18,11": { - "contents": "", - "bgcolor": "1" - }, - "18,12": { - "contents": "", - "bgcolor": "1" - }, - "18,13": { - "contents": "", - "bgcolor": "1" - }, - "18,14": { - "contents": "", - "bgcolor": "1" - }, - "18,15": { - "contents": "", - "bgcolor": "1" - }, - "18,16": { - "contents": "", - "bgcolor": "1" - }, - "18,17": { - "contents": "", - "bgcolor": "1" - }, - "18,18": { - "contents": "", - "bgcolor": "1" - }, - "18,19": { - "contents": "", - "bgcolor": "1" - }, - "18,2": { - "contents": "", - "bgcolor": "1" - }, - "18,20": { - "contents": "", - "bgcolor": "1" - }, - "18,21": { - "contents": "", - "bgcolor": "1" - }, - "18,22": { - "contents": "", - "bgcolor": "1" - }, - "18,23": { - "contents": "", - "bgcolor": "1" - }, - "18,24": { - "contents": "", - "bgcolor": "1" - }, - "18,25": { - "contents": "", - "bgcolor": "1" - }, - "18,26": { - "contents": "", - "bgcolor": "1" - }, - "18,27": { - "contents": "", - "bgcolor": "1" - }, - "18,28": { - "contents": "", - "bgcolor": "1" - }, - "18,29": { - "contents": "", - "bgcolor": "1" - }, - "18,3": { - "contents": "", - "bgcolor": "1" - }, - "18,30": { - "contents": "", - "bgcolor": "1" - }, - "18,31": { - "contents": "", - "bgcolor": "1" - }, - "18,32": { - "contents": "", - "bgcolor": "1" - }, - "18,33": { - "contents": "", - "bgcolor": "1" - }, - "18,34": { - "contents": "", - "bgcolor": "1" - }, - "18,35": { - "contents": "", - "bgcolor": "1" - }, - "18,36": { - "contents": "", - "bgcolor": "1" - }, - "18,37": { - "contents": "", - "bgcolor": "1" - }, - "18,38": { - "contents": "", - "bgcolor": "1" - }, - "18,39": { - "contents": "", - "bgcolor": "1" - }, - "18,4": { - "contents": "", - "bgcolor": "1" - }, - "18,40": { - "contents": "", - "bgcolor": "1" - }, - "18,41": { - "contents": "", - "bgcolor": "1" - }, - "18,42": { - "contents": "", - "bgcolor": "1" - }, - "18,43": { - "contents": "", - "bgcolor": "1" - }, - "18,44": { - "contents": "", - "bgcolor": "1" - }, - "18,45": { - "contents": "", - "bgcolor": "1" - }, - "18,46": { - "contents": "", - "bgcolor": "1" - }, - "18,47": { - "contents": "", - "bgcolor": "1" - }, - "18,48": { - "contents": "", - "bgcolor": "1" - }, - "18,49": { - "contents": "", - "bgcolor": "1" - }, - "18,5": { - "contents": "", - "bgcolor": "1" - }, - "18,50": { - "contents": "", - "bgcolor": "1" - }, - "18,51": { - "contents": "", - "bgcolor": "1" - }, - "18,52": { - "contents": "", - "bgcolor": "1" - }, - "18,53": { - "contents": "", - "bgcolor": "1" - }, - "18,54": { - "contents": "", - "bgcolor": "1" - }, - "18,55": { - "contents": "", - "bgcolor": "1" - }, - "18,56": { - "contents": "", - "bgcolor": "1" - }, - "18,57": { - "contents": "", - "bgcolor": "1" - }, - "18,58": { - "contents": "", - "bgcolor": "1" - }, - "18,59": { - "contents": "", - "bgcolor": "1" - }, - "18,6": { - "contents": "", - "bgcolor": "1" - }, - "18,60": { - "contents": "", - "bgcolor": "1" - }, - "18,61": { - "contents": "", - "bgcolor": "1" - }, - "18,62": { - "contents": "", - "bgcolor": "1" - }, - "18,63": { - "contents": "", - "bgcolor": "1" - }, - "18,64": { - "contents": "", - "bgcolor": "1" - }, - "18,65": { - "contents": "", - "bgcolor": "1" - }, - "18,66": { - "contents": "", - "bgcolor": "1" - }, - "18,67": { - "contents": "", - "bgcolor": "1" - }, - "18,68": { - "contents": "", - "bgcolor": "1" - }, - "18,69": { - "contents": "", - "bgcolor": "1" - }, - "18,7": { - "contents": "", - "bgcolor": "1" - }, - "18,70": { - "contents": "", - "bgcolor": "1" - }, - "18,71": { - "contents": "", - "bgcolor": "1" - }, - "18,72": { - "contents": "", - "bgcolor": "1" - }, - "18,73": { - "contents": "", - "bgcolor": "1" - }, - "18,74": { - "contents": "", - "bgcolor": "1" - }, - "18,75": { - "contents": "", - "bgcolor": "1" - }, - "18,76": { - "contents": "", - "bgcolor": "1" - }, - "18,77": { - "contents": "", - "bgcolor": "1" - }, - "18,78": { - "contents": "", - "bgcolor": "1" - }, - "18,79": { - "contents": "", - "bgcolor": "1" - }, - "18,8": { - "contents": "", - "bgcolor": "1" - }, - "18,9": { - "contents": "", - "bgcolor": "1" - }, - "19,0": { - "contents": "", - "bgcolor": "1" - }, - "19,1": { - "contents": "", - "bgcolor": "1" - }, - "19,10": { - "contents": "", - "bgcolor": "1" - }, - "19,11": { - "contents": "", - "bgcolor": "1" - }, - "19,12": { - "contents": "", - "bgcolor": "1" - }, - "19,13": { - "contents": "", - "bgcolor": "1" - }, - "19,14": { - "contents": "", - "bgcolor": "1" - }, - "19,15": { - "contents": "", - "bgcolor": "1" - }, - "19,16": { - "contents": "", - "bgcolor": "1" - }, - "19,17": { - "contents": "", - "bgcolor": "1" - }, - "19,18": { - "contents": "", - "bgcolor": "1" - }, - "19,19": { - "contents": "", - "bgcolor": "1" - }, - "19,2": { - "contents": "", - "bgcolor": "1" - }, - "19,20": { - "contents": "", - "bgcolor": "1" - }, - "19,21": { - "contents": "", - "bgcolor": "1" - }, - "19,22": { - "contents": "", - "bgcolor": "1" - }, - "19,23": { - "contents": "", - "bgcolor": "1" - }, - "19,24": { - "contents": "", - "bgcolor": "1" - }, - "19,25": { - "contents": "", - "bgcolor": "1" - }, - "19,26": { - "contents": "", - "bgcolor": "1" - }, - "19,27": { - "contents": "", - "bgcolor": "1" - }, - "19,28": { - "contents": "", - "bgcolor": "1" - }, - "19,29": { - "contents": "", - "bgcolor": "1" - }, - "19,3": { - "contents": "", - "bgcolor": "1" - }, - "19,30": { - "contents": "", - "bgcolor": "1" - }, - "19,31": { - "contents": "", - "bgcolor": "1" - }, - "19,32": { - "contents": "", - "bgcolor": "1" - }, - "19,33": { - "contents": "", - "bgcolor": "1" - }, - "19,34": { - "contents": "", - "bgcolor": "1" - }, - "19,35": { - "contents": "", - "bgcolor": "1" - }, - "19,36": { - "contents": "", - "bgcolor": "1" - }, - "19,37": { - "contents": "", - "bgcolor": "1" - }, - "19,38": { - "contents": "", - "bgcolor": "1" - }, - "19,39": { - "contents": "", - "bgcolor": "1" - }, - "19,4": { - "contents": "", - "bgcolor": "1" - }, - "19,40": { - "contents": "", - "bgcolor": "1" - }, - "19,41": { - "contents": "", - "bgcolor": "1" - }, - "19,42": { - "contents": "", - "bgcolor": "1" - }, - "19,43": { - "contents": "", - "bgcolor": "1" - }, - "19,44": { - "contents": "", - "bgcolor": "1" - }, - "19,45": { - "contents": "", - "bgcolor": "1" - }, - "19,46": { - "contents": "", - "bgcolor": "1" - }, - "19,47": { - "contents": "", - "bgcolor": "1" - }, - "19,48": { - "contents": "", - "bgcolor": "1" - }, - "19,49": { - "contents": "", - "bgcolor": "1" - }, - "19,5": { - "contents": "", - "bgcolor": "1" - }, - "19,50": { - "contents": "", - "bgcolor": "1" - }, - "19,51": { - "contents": "", - "bgcolor": "1" - }, - "19,52": { - "contents": "", - "bgcolor": "1" - }, - "19,53": { - "contents": "", - "bgcolor": "1" - }, - "19,54": { - "contents": "", - "bgcolor": "1" - }, - "19,55": { - "contents": "", - "bgcolor": "1" - }, - "19,56": { - "contents": "", - "bgcolor": "1" - }, - "19,57": { - "contents": "", - "bgcolor": "1" - }, - "19,58": { - "contents": "", - "bgcolor": "1" - }, - "19,59": { - "contents": "", - "bgcolor": "1" - }, - "19,6": { - "contents": "", - "bgcolor": "1" - }, - "19,60": { - "contents": "", - "bgcolor": "1" - }, - "19,61": { - "contents": "", - "bgcolor": "1" - }, - "19,62": { - "contents": "", - "bgcolor": "1" - }, - "19,63": { - "contents": "", - "bgcolor": "1" - }, - "19,64": { - "contents": "", - "bgcolor": "1" - }, - "19,65": { - "contents": "", - "bgcolor": "1" - }, - "19,66": { - "contents": "", - "bgcolor": "1" - }, - "19,67": { - "contents": "", - "bgcolor": "1" - }, - "19,68": { - "contents": "", - "bgcolor": "1" - }, - "19,69": { - "contents": "", - "bgcolor": "1" - }, - "19,7": { - "contents": "", - "bgcolor": "1" - }, - "19,70": { - "contents": "", - "bgcolor": "1" - }, - "19,71": { - "contents": "", - "bgcolor": "1" - }, - "19,72": { - "contents": "", - "bgcolor": "1" - }, - "19,73": { - "contents": "", - "bgcolor": "1" - }, - "19,74": { - "contents": "", - "bgcolor": "1" - }, - "19,75": { - "contents": "", - "bgcolor": "1" - }, - "19,76": { - "contents": "", - "bgcolor": "1" - }, - "19,77": { - "contents": "", - "bgcolor": "1" - }, - "19,78": { - "contents": "", - "bgcolor": "1" - }, - "19,79": { - "contents": "", - "bgcolor": "1" - }, - "19,8": { - "contents": "", - "bgcolor": "1" - }, - "19,9": { - "contents": "", - "bgcolor": "1" - }, - "2,0": { - "contents": "", - "bgcolor": "1" - }, - "2,1": { - "contents": "", - "bgcolor": "1" - }, - "2,10": { - "contents": "", - "bgcolor": "1" - }, - "2,11": { - "contents": "", - "bgcolor": "1" - }, - "2,12": { - "contents": "", - "bgcolor": "1" - }, - "2,13": { - "contents": "", - "bgcolor": "1" - }, - "2,14": { - "contents": "", - "bgcolor": "1" - }, - "2,15": { - "contents": "", - "bgcolor": "1" - }, - "2,16": { - "contents": "", - "bgcolor": "1" - }, - "2,17": { - "contents": "", - "bgcolor": "1" - }, - "2,18": { - "contents": "", - "bgcolor": "1" - }, - "2,19": { - "contents": "", - "bgcolor": "1" - }, - "2,2": { - "contents": "", - "bgcolor": "1" - }, - "2,20": { - "contents": "", - "bgcolor": "1" - }, - "2,21": { - "contents": "", - "bgcolor": "1" - }, - "2,22": { - "contents": "", - "bgcolor": "1" - }, - "2,23": { - "contents": "", - "bgcolor": "1" - }, - "2,24": { - "contents": "", - "bgcolor": "1" - }, - "2,25": { - "contents": "", - "bgcolor": "1" - }, - "2,26": { - "contents": "", - "bgcolor": "1" - }, - "2,27": { - "contents": "", - "bgcolor": "1" - }, - "2,28": { - "contents": "", - "bgcolor": "1" - }, - "2,29": { - "contents": "", - "bgcolor": "1" - }, - "2,3": { - "contents": "", - "bgcolor": "1" - }, - "2,30": { - "contents": "", - "bgcolor": "1" - }, - "2,31": { - "contents": "", - "bgcolor": "1" - }, - "2,32": { - "contents": "", - "bgcolor": "1" - }, - "2,33": { - "contents": "", - "bgcolor": "1" - }, - "2,34": { - "contents": "", - "bgcolor": "1" - }, - "2,35": { - "contents": "", - "bgcolor": "1" - }, - "2,36": { - "contents": "", - "bgcolor": "1" - }, - "2,37": { - "contents": "", - "bgcolor": "1" - }, - "2,38": { - "contents": "", - "bgcolor": "1" - }, - "2,39": { - "contents": "", - "bgcolor": "1" - }, - "2,4": { - "contents": "", - "bgcolor": "1" - }, - "2,40": { - "contents": "", - "bgcolor": "1" - }, - "2,41": { - "contents": "", - "bgcolor": "1" - }, - "2,42": { - "contents": "", - "bgcolor": "1" - }, - "2,43": { - "contents": "", - "bgcolor": "1" - }, - "2,44": { - "contents": "", - "bgcolor": "1" - }, - "2,45": { - "contents": "", - "bgcolor": "1" - }, - "2,46": { - "contents": "", - "bgcolor": "1" - }, - "2,47": { - "contents": "", - "bgcolor": "1" - }, - "2,48": { - "contents": "", - "bgcolor": "1" - }, - "2,49": { - "contents": "", - "bgcolor": "1" - }, - "2,5": { - "contents": "", - "bgcolor": "1" - }, - "2,50": { - "contents": "", - "bgcolor": "1" - }, - "2,51": { - "contents": "", - "bgcolor": "1" - }, - "2,52": { - "contents": "", - "bgcolor": "1" - }, - "2,53": { - "contents": "", - "bgcolor": "1" - }, - "2,54": { - "contents": "", - "bgcolor": "1" - }, - "2,55": { - "contents": "", - "bgcolor": "1" - }, - "2,56": { - "contents": "", - "bgcolor": "1" - }, - "2,57": { - "contents": "", - "bgcolor": "1" - }, - "2,58": { - "contents": "", - "bgcolor": "1" - }, - "2,59": { - "contents": "", - "bgcolor": "1" - }, - "2,6": { - "contents": "", - "bgcolor": "1" - }, - "2,60": { - "contents": "", - "bgcolor": "1" - }, - "2,61": { - "contents": "", - "bgcolor": "1" - }, - "2,62": { - "contents": "", - "bgcolor": "1" - }, - "2,63": { - "contents": "", - "bgcolor": "1" - }, - "2,64": { - "contents": "", - "bgcolor": "1" - }, - "2,65": { - "contents": "", - "bgcolor": "1" - }, - "2,66": { - "contents": "", - "bgcolor": "1" - }, - "2,67": { - "contents": "", - "bgcolor": "1" - }, - "2,68": { - "contents": "", - "bgcolor": "1" - }, - "2,69": { - "contents": "", - "bgcolor": "1" - }, - "2,7": { - "contents": "", - "bgcolor": "1" - }, - "2,70": { - "contents": "", - "bgcolor": "1" - }, - "2,71": { - "contents": "", - "bgcolor": "1" - }, - "2,72": { - "contents": "", - "bgcolor": "1" - }, - "2,73": { - "contents": "", - "bgcolor": "1" - }, - "2,74": { - "contents": "", - "bgcolor": "1" - }, - "2,75": { - "contents": "", - "bgcolor": "1" - }, - "2,76": { - "contents": "", - "bgcolor": "1" - }, - "2,77": { - "contents": "", - "bgcolor": "1" - }, - "2,78": { - "contents": "", - "bgcolor": "1" - }, - "2,79": { - "contents": "", - "bgcolor": "1" - }, - "2,8": { - "contents": "", - "bgcolor": "1" - }, - "2,9": { - "contents": "", - "bgcolor": "1" - }, - "20,0": { - "contents": "", - "bgcolor": "1" - }, - "20,1": { - "contents": "", - "bgcolor": "1" - }, - "20,10": { - "contents": "", - "bgcolor": "1" - }, - "20,11": { - "contents": "", - "bgcolor": "1" - }, - "20,12": { - "contents": "", - "bgcolor": "1" - }, - "20,13": { - "contents": "", - "bgcolor": "1" - }, - "20,14": { - "contents": "", - "bgcolor": "1" - }, - "20,15": { - "contents": "", - "bgcolor": "1" - }, - "20,16": { - "contents": "", - "bgcolor": "1" - }, - "20,17": { - "contents": "", - "bgcolor": "1" - }, - "20,18": { - "contents": "", - "bgcolor": "1" - }, - "20,19": { - "contents": "", - "bgcolor": "1" - }, - "20,2": { - "contents": "", - "bgcolor": "1" - }, - "20,20": { - "contents": "", - "bgcolor": "1" - }, - "20,21": { - "contents": "", - "bgcolor": "1" - }, - "20,22": { - "contents": "", - "bgcolor": "1" - }, - "20,23": { - "contents": "", - "bgcolor": "1" - }, - "20,24": { - "contents": "", - "bgcolor": "1" - }, - "20,25": { - "contents": "", - "bgcolor": "1" - }, - "20,26": { - "contents": "", - "bgcolor": "1" - }, - "20,27": { - "contents": "", - "bgcolor": "1" - }, - "20,28": { - "contents": "", - "bgcolor": "1" - }, - "20,29": { - "contents": "", - "bgcolor": "1" - }, - "20,3": { - "contents": "", - "bgcolor": "1" - }, - "20,30": { - "contents": "", - "bgcolor": "1" - }, - "20,31": { - "contents": "", - "bgcolor": "1" - }, - "20,32": { - "contents": "", - "bgcolor": "1" - }, - "20,33": { - "contents": "", - "bgcolor": "1" - }, - "20,34": { - "contents": "", - "bgcolor": "1" - }, - "20,35": { - "contents": "", - "bgcolor": "1" - }, - "20,36": { - "contents": "", - "bgcolor": "1" - }, - "20,37": { - "contents": "", - "bgcolor": "1" - }, - "20,38": { - "contents": "", - "bgcolor": "1" - }, - "20,39": { - "contents": "", - "bgcolor": "1" - }, - "20,4": { - "contents": "", - "bgcolor": "1" - }, - "20,40": { - "contents": "", - "bgcolor": "1" - }, - "20,41": { - "contents": "", - "bgcolor": "1" - }, - "20,42": { - "contents": "", - "bgcolor": "1" - }, - "20,43": { - "contents": "", - "bgcolor": "1" - }, - "20,44": { - "contents": "", - "bgcolor": "1" - }, - "20,45": { - "contents": "", - "bgcolor": "1" - }, - "20,46": { - "contents": "", - "bgcolor": "1" - }, - "20,47": { - "contents": "", - "bgcolor": "1" - }, - "20,48": { - "contents": "", - "bgcolor": "1" - }, - "20,49": { - "contents": "", - "bgcolor": "1" - }, - "20,5": { - "contents": "", - "bgcolor": "1" - }, - "20,50": { - "contents": "", - "bgcolor": "1" - }, - "20,51": { - "contents": "", - "bgcolor": "1" - }, - "20,52": { - "contents": "", - "bgcolor": "1" - }, - "20,53": { - "contents": "", - "bgcolor": "1" - }, - "20,54": { - "contents": "", - "bgcolor": "1" - }, - "20,55": { - "contents": "", - "bgcolor": "1" - }, - "20,56": { - "contents": "", - "bgcolor": "1" - }, - "20,57": { - "contents": "", - "bgcolor": "1" - }, - "20,58": { - "contents": "", - "bgcolor": "1" - }, - "20,59": { - "contents": "", - "bgcolor": "1" - }, - "20,6": { - "contents": "", - "bgcolor": "1" - }, - "20,60": { - "contents": "", - "bgcolor": "1" - }, - "20,61": { - "contents": "", - "bgcolor": "1" - }, - "20,62": { - "contents": "", - "bgcolor": "1" - }, - "20,63": { - "contents": "", - "bgcolor": "1" - }, - "20,64": { - "contents": "", - "bgcolor": "1" - }, - "20,65": { - "contents": "", - "bgcolor": "1" - }, - "20,66": { - "contents": "", - "bgcolor": "1" - }, - "20,67": { - "contents": "", - "bgcolor": "1" - }, - "20,68": { - "contents": "", - "bgcolor": "1" - }, - "20,69": { - "contents": "", - "bgcolor": "1" - }, - "20,7": { - "contents": "", - "bgcolor": "1" - }, - "20,70": { - "contents": "", - "bgcolor": "1" - }, - "20,71": { - "contents": "", - "bgcolor": "1" - }, - "20,72": { - "contents": "", - "bgcolor": "1" - }, - "20,73": { - "contents": "", - "bgcolor": "1" - }, - "20,74": { - "contents": "", - "bgcolor": "1" - }, - "20,75": { - "contents": "", - "bgcolor": "1" - }, - "20,76": { - "contents": "", - "bgcolor": "1" - }, - "20,77": { - "contents": "", - "bgcolor": "1" - }, - "20,78": { - "contents": "", - "bgcolor": "1" - }, - "20,79": { - "contents": "", - "bgcolor": "1" - }, - "20,8": { - "contents": "", - "bgcolor": "1" - }, - "20,9": { - "contents": "", - "bgcolor": "1" - }, - "21,0": { - "contents": "", - "bgcolor": "1" - }, - "21,1": { - "contents": "", - "bgcolor": "1" - }, - "21,10": { - "contents": "", - "bgcolor": "1" - }, - "21,11": { - "contents": "", - "bgcolor": "1" - }, - "21,12": { - "contents": "", - "bgcolor": "1" - }, - "21,13": { - "contents": "", - "bgcolor": "1" - }, - "21,14": { - "contents": "", - "bgcolor": "1" - }, - "21,15": { - "contents": "", - "bgcolor": "1" - }, - "21,16": { - "contents": "", - "bgcolor": "1" - }, - "21,17": { - "contents": "", - "bgcolor": "1" - }, - "21,18": { - "contents": "", - "bgcolor": "1" - }, - "21,19": { - "contents": "", - "bgcolor": "1" - }, - "21,2": { - "contents": "", - "bgcolor": "1" - }, - "21,20": { - "contents": "", - "bgcolor": "1" - }, - "21,21": { - "contents": "", - "bgcolor": "1" - }, - "21,22": { - "contents": "", - "bgcolor": "1" - }, - "21,23": { - "contents": "", - "bgcolor": "1" - }, - "21,24": { - "contents": "", - "bgcolor": "1" - }, - "21,25": { - "contents": "", - "bgcolor": "1" - }, - "21,26": { - "contents": "", - "bgcolor": "1" - }, - "21,27": { - "contents": "", - "bgcolor": "1" - }, - "21,28": { - "contents": "", - "bgcolor": "1" - }, - "21,29": { - "contents": "", - "bgcolor": "1" - }, - "21,3": { - "contents": "", - "bgcolor": "1" - }, - "21,30": { - "contents": "", - "bgcolor": "1" - }, - "21,31": { - "contents": "", - "bgcolor": "1" - }, - "21,32": { - "contents": "", - "bgcolor": "1" - }, - "21,33": { - "contents": "", - "bgcolor": "1" - }, - "21,34": { - "contents": "", - "bgcolor": "1" - }, - "21,35": { - "contents": "", - "bgcolor": "1" - }, - "21,36": { - "contents": "", - "bgcolor": "1" - }, - "21,37": { - "contents": "", - "bgcolor": "1" - }, - "21,38": { - "contents": "", - "bgcolor": "1" - }, - "21,39": { - "contents": "", - "bgcolor": "1" - }, - "21,4": { - "contents": "", - "bgcolor": "1" - }, - "21,40": { - "contents": "", - "bgcolor": "1" - }, - "21,41": { - "contents": "", - "bgcolor": "1" - }, - "21,42": { - "contents": "", - "bgcolor": "1" - }, - "21,43": { - "contents": "", - "bgcolor": "1" - }, - "21,44": { - "contents": "", - "bgcolor": "1" - }, - "21,45": { - "contents": "", - "bgcolor": "1" - }, - "21,46": { - "contents": "", - "bgcolor": "1" - }, - "21,47": { - "contents": "", - "bgcolor": "1" - }, - "21,48": { - "contents": "", - "bgcolor": "1" - }, - "21,49": { - "contents": "", - "bgcolor": "1" - }, - "21,5": { - "contents": "", - "bgcolor": "1" - }, - "21,50": { - "contents": "", - "bgcolor": "1" - }, - "21,51": { - "contents": "", - "bgcolor": "1" - }, - "21,52": { - "contents": "", - "bgcolor": "1" - }, - "21,53": { - "contents": "", - "bgcolor": "1" - }, - "21,54": { - "contents": "", - "bgcolor": "1" - }, - "21,55": { - "contents": "", - "bgcolor": "1" - }, - "21,56": { - "contents": "", - "bgcolor": "1" - }, - "21,57": { - "contents": "", - "bgcolor": "1" - }, - "21,58": { - "contents": "", - "bgcolor": "1" - }, - "21,59": { - "contents": "", - "bgcolor": "1" - }, - "21,6": { - "contents": "", - "bgcolor": "1" - }, - "21,60": { - "contents": "", - "bgcolor": "1" - }, - "21,61": { - "contents": "", - "bgcolor": "1" - }, - "21,62": { - "contents": "", - "bgcolor": "1" - }, - "21,63": { - "contents": "", - "bgcolor": "1" - }, - "21,64": { - "contents": "", - "bgcolor": "1" - }, - "21,65": { - "contents": "", - "bgcolor": "1" - }, - "21,66": { - "contents": "", - "bgcolor": "1" - }, - "21,67": { - "contents": "", - "bgcolor": "1" - }, - "21,68": { - "contents": "", - "bgcolor": "1" - }, - "21,69": { - "contents": "", - "bgcolor": "1" - }, - "21,7": { - "contents": "", - "bgcolor": "1" - }, - "21,70": { - "contents": "", - "bgcolor": "1" - }, - "21,71": { - "contents": "", - "bgcolor": "1" - }, - "21,72": { - "contents": "", - "bgcolor": "1" - }, - "21,73": { - "contents": "", - "bgcolor": "1" - }, - "21,74": { - "contents": "", - "bgcolor": "1" - }, - "21,75": { - "contents": "", - "bgcolor": "1" - }, - "21,76": { - "contents": "", - "bgcolor": "1" - }, - "21,77": { - "contents": "", - "bgcolor": "1" - }, - "21,78": { - "contents": "", - "bgcolor": "1" - }, - "21,79": { - "contents": "", - "bgcolor": "1" - }, - "21,8": { - "contents": "", - "bgcolor": "1" - }, - "21,9": { - "contents": "", - "bgcolor": "1" - }, - "22,0": { - "contents": "", - "bgcolor": "1" - }, - "22,1": { - "contents": "", - "bgcolor": "1" - }, - "22,10": { - "contents": "", - "bgcolor": "1" - }, - "22,11": { - "contents": "", - "bgcolor": "1" - }, - "22,12": { - "contents": "", - "bgcolor": "1" - }, - "22,13": { - "contents": "", - "bgcolor": "1" - }, - "22,14": { - "contents": "", - "bgcolor": "1" - }, - "22,15": { - "contents": "", - "bgcolor": "1" - }, - "22,16": { - "contents": "", - "bgcolor": "1" - }, - "22,17": { - "contents": "", - "bgcolor": "1" - }, - "22,18": { - "contents": "", - "bgcolor": "1" - }, - "22,19": { - "contents": "", - "bgcolor": "1" - }, - "22,2": { - "contents": "", - "bgcolor": "1" - }, - "22,20": { - "contents": "", - "bgcolor": "1" - }, - "22,21": { - "contents": "", - "bgcolor": "1" - }, - "22,22": { - "contents": "", - "bgcolor": "1" - }, - "22,23": { - "contents": "", - "bgcolor": "1" - }, - "22,24": { - "contents": "", - "bgcolor": "1" - }, - "22,25": { - "contents": "", - "bgcolor": "1" - }, - "22,26": { - "contents": "", - "bgcolor": "1" - }, - "22,27": { - "contents": "", - "bgcolor": "1" - }, - "22,28": { - "contents": "", - "bgcolor": "1" - }, - "22,29": { - "contents": "", - "bgcolor": "1" - }, - "22,3": { - "contents": "", - "bgcolor": "1" - }, - "22,30": { - "contents": "", - "bgcolor": "1" - }, - "22,31": { - "contents": "", - "bgcolor": "1" - }, - "22,32": { - "contents": "", - "bgcolor": "1" - }, - "22,33": { - "contents": "", - "bgcolor": "1" - }, - "22,34": { - "contents": "", - "bgcolor": "1" - }, - "22,35": { - "contents": "", - "bgcolor": "1" - }, - "22,36": { - "contents": "", - "bgcolor": "1" - }, - "22,37": { - "contents": "", - "bgcolor": "1" - }, - "22,38": { - "contents": "", - "bgcolor": "1" - }, - "22,39": { - "contents": "", - "bgcolor": "1" - }, - "22,4": { - "contents": "", - "bgcolor": "1" - }, - "22,40": { - "contents": "", - "bgcolor": "1" - }, - "22,41": { - "contents": "", - "bgcolor": "1" - }, - "22,42": { - "contents": "", - "bgcolor": "1" - }, - "22,43": { - "contents": "", - "bgcolor": "1" - }, - "22,44": { - "contents": "", - "bgcolor": "1" - }, - "22,45": { - "contents": "", - "bgcolor": "1" - }, - "22,46": { - "contents": "", - "bgcolor": "1" - }, - "22,47": { - "contents": "", - "bgcolor": "1" - }, - "22,48": { - "contents": "", - "bgcolor": "1" - }, - "22,49": { - "contents": "", - "bgcolor": "1" - }, - "22,5": { - "contents": "", - "bgcolor": "1" - }, - "22,50": { - "contents": "", - "bgcolor": "1" - }, - "22,51": { - "contents": "", - "bgcolor": "1" - }, - "22,52": { - "contents": "", - "bgcolor": "1" - }, - "22,53": { - "contents": "", - "bgcolor": "1" - }, - "22,54": { - "contents": "", - "bgcolor": "1" - }, - "22,55": { - "contents": "", - "bgcolor": "1" - }, - "22,56": { - "contents": "", - "bgcolor": "1" - }, - "22,57": { - "contents": "", - "bgcolor": "1" - }, - "22,58": { - "contents": "", - "bgcolor": "1" - }, - "22,59": { - "contents": "", - "bgcolor": "1" - }, - "22,6": { - "contents": "", - "bgcolor": "1" - }, - "22,60": { - "contents": "", - "bgcolor": "1" - }, - "22,61": { - "contents": "", - "bgcolor": "1" - }, - "22,62": { - "contents": "", - "bgcolor": "1" - }, - "22,63": { - "contents": "", - "bgcolor": "1" - }, - "22,64": { - "contents": "", - "bgcolor": "1" - }, - "22,65": { - "contents": "", - "bgcolor": "1" - }, - "22,66": { - "contents": "", - "bgcolor": "1" - }, - "22,67": { - "contents": "", - "bgcolor": "1" - }, - "22,68": { - "contents": "", - "bgcolor": "1" - }, - "22,69": { - "contents": "", - "bgcolor": "1" - }, - "22,7": { - "contents": "", - "bgcolor": "1" - }, - "22,70": { - "contents": "", - "bgcolor": "1" - }, - "22,71": { - "contents": "", - "bgcolor": "1" - }, - "22,72": { - "contents": "", - "bgcolor": "1" - }, - "22,73": { - "contents": "", - "bgcolor": "1" - }, - "22,74": { - "contents": "", - "bgcolor": "1" - }, - "22,75": { - "contents": "", - "bgcolor": "1" - }, - "22,76": { - "contents": "", - "bgcolor": "1" - }, - "22,77": { - "contents": "", - "bgcolor": "1" - }, - "22,78": { - "contents": "", - "bgcolor": "1" - }, - "22,79": { - "contents": "", - "bgcolor": "1" - }, - "22,8": { - "contents": "", - "bgcolor": "1" - }, - "22,9": { - "contents": "", - "bgcolor": "1" - }, - "23,0": { - "contents": "", - "bgcolor": "1" - }, - "23,1": { - "contents": "", - "bgcolor": "1" - }, - "23,10": { - "contents": "", - "bgcolor": "1" - }, - "23,11": { - "contents": "", - "bgcolor": "1" - }, - "23,12": { - "contents": "", - "bgcolor": "1" - }, - "23,13": { - "contents": "", - "bgcolor": "1" - }, - "23,14": { - "contents": "", - "bgcolor": "1" - }, - "23,15": { - "contents": "", - "bgcolor": "1" - }, - "23,16": { - "contents": "", - "bgcolor": "1" - }, - "23,17": { - "contents": "", - "bgcolor": "1" - }, - "23,18": { - "contents": "", - "bgcolor": "1" - }, - "23,19": { - "contents": "", - "bgcolor": "1" - }, - "23,2": { - "contents": "", - "bgcolor": "1" - }, - "23,20": { - "contents": "", - "bgcolor": "1" - }, - "23,21": { - "contents": "", - "bgcolor": "1" - }, - "23,22": { - "contents": "", - "bgcolor": "1" - }, - "23,23": { - "contents": "", - "bgcolor": "1" - }, - "23,24": { - "contents": "", - "bgcolor": "1" - }, - "23,25": { - "contents": "", - "bgcolor": "1" - }, - "23,26": { - "contents": "", - "bgcolor": "1" - }, - "23,27": { - "contents": "", - "bgcolor": "1" - }, - "23,28": { - "contents": "", - "bgcolor": "1" - }, - "23,29": { - "contents": "", - "bgcolor": "1" - }, - "23,3": { - "contents": "", - "bgcolor": "1" - }, - "23,30": { - "contents": "", - "bgcolor": "1" - }, - "23,31": { - "contents": "", - "bgcolor": "1" - }, - "23,32": { - "contents": "", - "bgcolor": "1" - }, - "23,33": { - "contents": "", - "bgcolor": "1" - }, - "23,34": { - "contents": "", - "bgcolor": "1" - }, - "23,35": { - "contents": "", - "bgcolor": "1" - }, - "23,36": { - "contents": "", - "bgcolor": "1" - }, - "23,37": { - "contents": "", - "bgcolor": "1" - }, - "23,38": { - "contents": "", - "bgcolor": "1" - }, - "23,39": { - "contents": "", - "bgcolor": "1" - }, - "23,4": { - "contents": "", - "bgcolor": "1" - }, - "23,40": { - "contents": "", - "bgcolor": "1" - }, - "23,41": { - "contents": "", - "bgcolor": "1" - }, - "23,42": { - "contents": "", - "bgcolor": "1" - }, - "23,43": { - "contents": "", - "bgcolor": "1" - }, - "23,44": { - "contents": "", - "bgcolor": "1" - }, - "23,45": { - "contents": "", - "bgcolor": "1" - }, - "23,46": { - "contents": "", - "bgcolor": "1" - }, - "23,47": { - "contents": "", - "bgcolor": "1" - }, - "23,48": { - "contents": "", - "bgcolor": "1" - }, - "23,49": { - "contents": "", - "bgcolor": "1" - }, - "23,5": { - "contents": "", - "bgcolor": "1" - }, - "23,50": { - "contents": "", - "bgcolor": "1" - }, - "23,51": { - "contents": "", - "bgcolor": "1" - }, - "23,52": { - "contents": "", - "bgcolor": "1" - }, - "23,53": { - "contents": "", - "bgcolor": "1" - }, - "23,54": { - "contents": "", - "bgcolor": "1" - }, - "23,55": { - "contents": "", - "bgcolor": "1" - }, - "23,56": { - "contents": "", - "bgcolor": "1" - }, - "23,57": { - "contents": "", - "bgcolor": "1" - }, - "23,58": { - "contents": "", - "bgcolor": "1" - }, - "23,59": { - "contents": "", - "bgcolor": "1" - }, - "23,6": { - "contents": "", - "bgcolor": "1" - }, - "23,60": { - "contents": "", - "bgcolor": "1" - }, - "23,61": { - "contents": "", - "bgcolor": "1" - }, - "23,62": { - "contents": "", - "bgcolor": "1" - }, - "23,63": { - "contents": "", - "bgcolor": "1" - }, - "23,64": { - "contents": "", - "bgcolor": "1" - }, - "23,65": { - "contents": "", - "bgcolor": "1" - }, - "23,66": { - "contents": "", - "bgcolor": "1" - }, - "23,67": { - "contents": "", - "bgcolor": "1" - }, - "23,68": { - "contents": "", - "bgcolor": "1" - }, - "23,69": { - "contents": "", - "bgcolor": "1" - }, - "23,7": { - "contents": "", - "bgcolor": "1" - }, - "23,70": { - "contents": "", - "bgcolor": "1" - }, - "23,71": { - "contents": "", - "bgcolor": "1" - }, - "23,72": { - "contents": "", - "bgcolor": "1" - }, - "23,73": { - "contents": "", - "bgcolor": "1" - }, - "23,74": { - "contents": "", - "bgcolor": "1" - }, - "23,75": { - "contents": "", - "bgcolor": "1" - }, - "23,76": { - "contents": "", - "bgcolor": "1" - }, - "23,77": { - "contents": "", - "bgcolor": "1" - }, - "23,78": { - "contents": "", - "bgcolor": "1" - }, - "23,79": { - "contents": "", - "bgcolor": "1" - }, - "23,8": { - "contents": "", - "bgcolor": "1" - }, - "23,9": { - "contents": "", - "bgcolor": "1" - }, - "3,0": { - "contents": "", - "bgcolor": "1" - }, - "3,1": { - "contents": "", - "bgcolor": "1" - }, - "3,10": { - "contents": "", - "bgcolor": "1" - }, - "3,11": { - "contents": "", - "bgcolor": "1" - }, - "3,12": { - "contents": "", - "bgcolor": "1" - }, - "3,13": { - "contents": "", - "bgcolor": "1" - }, - "3,14": { - "contents": "", - "bgcolor": "1" - }, - "3,15": { - "contents": "", - "bgcolor": "1" - }, - "3,16": { - "contents": "", - "bgcolor": "1" - }, - "3,17": { - "contents": "", - "bgcolor": "1" - }, - "3,18": { - "contents": "", - "bgcolor": "1" - }, - "3,19": { - "contents": "", - "bgcolor": "1" - }, - "3,2": { - "contents": "", - "bgcolor": "1" - }, - "3,20": { - "contents": "", - "bgcolor": "1" - }, - "3,21": { - "contents": "", - "bgcolor": "1" - }, - "3,22": { - "contents": "", - "bgcolor": "1" - }, - "3,23": { - "contents": "", - "bgcolor": "1" - }, - "3,24": { - "contents": "", - "bgcolor": "1" - }, - "3,25": { - "contents": "", - "bgcolor": "1" - }, - "3,26": { - "contents": "", - "bgcolor": "1" - }, - "3,27": { - "contents": "", - "bgcolor": "1" - }, - "3,28": { - "contents": "", - "bgcolor": "1" - }, - "3,29": { - "contents": "", - "bgcolor": "1" - }, - "3,3": { - "contents": "", - "bgcolor": "1" - }, - "3,30": { - "contents": "", - "bgcolor": "1" - }, - "3,31": { - "contents": "", - "bgcolor": "1" - }, - "3,32": { - "contents": "", - "bgcolor": "1" - }, - "3,33": { - "contents": "", - "bgcolor": "1" - }, - "3,34": { - "contents": "", - "bgcolor": "1" - }, - "3,35": { - "contents": "", - "bgcolor": "1" - }, - "3,36": { - "contents": "", - "bgcolor": "1" - }, - "3,37": { - "contents": "", - "bgcolor": "1" - }, - "3,38": { - "contents": "", - "bgcolor": "1" - }, - "3,39": { - "contents": "", - "bgcolor": "1" - }, - "3,4": { - "contents": "", - "bgcolor": "1" - }, - "3,40": { - "contents": "", - "bgcolor": "1" - }, - "3,41": { - "contents": "", - "bgcolor": "1" - }, - "3,42": { - "contents": "", - "bgcolor": "1" - }, - "3,43": { - "contents": "", - "bgcolor": "1" - }, - "3,44": { - "contents": "", - "bgcolor": "1" - }, - "3,45": { - "contents": "", - "bgcolor": "1" - }, - "3,46": { - "contents": "", - "bgcolor": "1" - }, - "3,47": { - "contents": "", - "bgcolor": "1" - }, - "3,48": { - "contents": "", - "bgcolor": "1" - }, - "3,49": { - "contents": "", - "bgcolor": "1" - }, - "3,5": { - "contents": "", - "bgcolor": "1" - }, - "3,50": { - "contents": "", - "bgcolor": "1" - }, - "3,51": { - "contents": "", - "bgcolor": "1" - }, - "3,52": { - "contents": "", - "bgcolor": "1" - }, - "3,53": { - "contents": "", - "bgcolor": "1" - }, - "3,54": { - "contents": "", - "bgcolor": "1" - }, - "3,55": { - "contents": "", - "bgcolor": "1" - }, - "3,56": { - "contents": "", - "bgcolor": "1" - }, - "3,57": { - "contents": "", - "bgcolor": "1" - }, - "3,58": { - "contents": "", - "bgcolor": "1" - }, - "3,59": { - "contents": "", - "bgcolor": "1" - }, - "3,6": { - "contents": "", - "bgcolor": "1" - }, - "3,60": { - "contents": "", - "bgcolor": "1" - }, - "3,61": { - "contents": "", - "bgcolor": "1" - }, - "3,62": { - "contents": "", - "bgcolor": "1" - }, - "3,63": { - "contents": "", - "bgcolor": "1" - }, - "3,64": { - "contents": "", - "bgcolor": "1" - }, - "3,65": { - "contents": "", - "bgcolor": "1" - }, - "3,66": { - "contents": "", - "bgcolor": "1" - }, - "3,67": { - "contents": "", - "bgcolor": "1" - }, - "3,68": { - "contents": "", - "bgcolor": "1" - }, - "3,69": { - "contents": "", - "bgcolor": "1" - }, - "3,7": { - "contents": "", - "bgcolor": "1" - }, - "3,70": { - "contents": "", - "bgcolor": "1" - }, - "3,71": { - "contents": "", - "bgcolor": "1" - }, - "3,72": { - "contents": "", - "bgcolor": "1" - }, - "3,73": { - "contents": "", - "bgcolor": "1" - }, - "3,74": { - "contents": "", - "bgcolor": "1" - }, - "3,75": { - "contents": "", - "bgcolor": "1" - }, - "3,76": { - "contents": "", - "bgcolor": "1" - }, - "3,77": { - "contents": "", - "bgcolor": "1" - }, - "3,78": { - "contents": "", - "bgcolor": "1" - }, - "3,79": { - "contents": "", - "bgcolor": "1" - }, - "3,8": { - "contents": "", - "bgcolor": "1" - }, - "3,9": { - "contents": "", - "bgcolor": "1" - }, - "4,0": { - "contents": "", - "bgcolor": "1" - }, - "4,1": { - "contents": "", - "bgcolor": "1" - }, - "4,10": { - "contents": "", - "bgcolor": "1" - }, - "4,11": { - "contents": "", - "bgcolor": "1" - }, - "4,12": { - "contents": "", - "bgcolor": "1" - }, - "4,13": { - "contents": "", - "bgcolor": "1" - }, - "4,14": { - "contents": "", - "bgcolor": "1" - }, - "4,15": { - "contents": "", - "bgcolor": "1" - }, - "4,16": { - "contents": "", - "bgcolor": "1" - }, - "4,17": { - "contents": "", - "bgcolor": "1" - }, - "4,18": { - "contents": "", - "bgcolor": "1" - }, - "4,19": { - "contents": "", - "bgcolor": "1" - }, - "4,2": { - "contents": "", - "bgcolor": "1" - }, - "4,20": { - "contents": "", - "bgcolor": "1" - }, - "4,21": { - "contents": "", - "bgcolor": "1" - }, - "4,22": { - "contents": "", - "bgcolor": "1" - }, - "4,23": { - "contents": "", - "bgcolor": "1" - }, - "4,24": { - "contents": "", - "bgcolor": "1" - }, - "4,25": { - "contents": "", - "bgcolor": "1" - }, - "4,26": { - "contents": "", - "bgcolor": "1" - }, - "4,27": { - "contents": "", - "bgcolor": "1" - }, - "4,28": { - "contents": "", - "bgcolor": "1" - }, - "4,29": { - "contents": "", - "bgcolor": "1" - }, - "4,3": { - "contents": "", - "bgcolor": "1" - }, - "4,30": { - "contents": "", - "bgcolor": "1" - }, - "4,31": { - "contents": "", - "bgcolor": "1" - }, - "4,32": { - "contents": "", - "bgcolor": "1" - }, - "4,33": { - "contents": "", - "bgcolor": "1" - }, - "4,34": { - "contents": "", - "bgcolor": "1" - }, - "4,35": { - "contents": "", - "bgcolor": "1" - }, - "4,36": { - "contents": "", - "bgcolor": "1" - }, - "4,37": { - "contents": "", - "bgcolor": "1" - }, - "4,38": { - "contents": "", - "bgcolor": "1" - }, - "4,39": { - "contents": "", - "bgcolor": "1" - }, - "4,4": { - "contents": "", - "bgcolor": "1" - }, - "4,40": { - "contents": "", - "bgcolor": "1" - }, - "4,41": { - "contents": "", - "bgcolor": "1" - }, - "4,42": { - "contents": "", - "bgcolor": "1" - }, - "4,43": { - "contents": "", - "bgcolor": "1" - }, - "4,44": { - "contents": "", - "bgcolor": "1" - }, - "4,45": { - "contents": "", - "bgcolor": "1" - }, - "4,46": { - "contents": "", - "bgcolor": "1" - }, - "4,47": { - "contents": "", - "bgcolor": "1" - }, - "4,48": { - "contents": "", - "bgcolor": "1" - }, - "4,49": { - "contents": "", - "bgcolor": "1" - }, - "4,5": { - "contents": "", - "bgcolor": "1" - }, - "4,50": { - "contents": "", - "bgcolor": "1" - }, - "4,51": { - "contents": "", - "bgcolor": "1" - }, - "4,52": { - "contents": "", - "bgcolor": "1" - }, - "4,53": { - "contents": "", - "bgcolor": "1" - }, - "4,54": { - "contents": "", - "bgcolor": "1" - }, - "4,55": { - "contents": "", - "bgcolor": "1" - }, - "4,56": { - "contents": "", - "bgcolor": "1" - }, - "4,57": { - "contents": "", - "bgcolor": "1" - }, - "4,58": { - "contents": "", - "bgcolor": "1" - }, - "4,59": { - "contents": "", - "bgcolor": "1" - }, - "4,6": { - "contents": "", - "bgcolor": "1" - }, - "4,60": { - "contents": "", - "bgcolor": "1" - }, - "4,61": { - "contents": "", - "bgcolor": "1" - }, - "4,62": { - "contents": "", - "bgcolor": "1" - }, - "4,63": { - "contents": "", - "bgcolor": "1" - }, - "4,64": { - "contents": "", - "bgcolor": "1" - }, - "4,65": { - "contents": "", - "bgcolor": "1" - }, - "4,66": { - "contents": "", - "bgcolor": "1" - }, - "4,67": { - "contents": "", - "bgcolor": "1" - }, - "4,68": { - "contents": "", - "bgcolor": "1" - }, - "4,69": { - "contents": "", - "bgcolor": "1" - }, - "4,7": { - "contents": "", - "bgcolor": "1" - }, - "4,70": { - "contents": "", - "bgcolor": "1" - }, - "4,71": { - "contents": "", - "bgcolor": "1" - }, - "4,72": { - "contents": "", - "bgcolor": "1" - }, - "4,73": { - "contents": "", - "bgcolor": "1" - }, - "4,74": { - "contents": "", - "bgcolor": "1" - }, - "4,75": { - "contents": "", - "bgcolor": "1" - }, - "4,76": { - "contents": "", - "bgcolor": "1" - }, - "4,77": { - "contents": "", - "bgcolor": "1" - }, - "4,78": { - "contents": "", - "bgcolor": "1" - }, - "4,79": { - "contents": "", - "bgcolor": "1" - }, - "4,8": { - "contents": "", - "bgcolor": "1" - }, - "4,9": { - "contents": "", - "bgcolor": "1" - }, - "5,0": { - "contents": "", - "bgcolor": "1" - }, - "5,1": { - "contents": "", - "bgcolor": "1" - }, - "5,10": { - "contents": "", - "bgcolor": "1" - }, - "5,11": { - "contents": "", - "bgcolor": "1" - }, - "5,12": { - "contents": "", - "bgcolor": "1" - }, - "5,13": { - "contents": "", - "bgcolor": "1" - }, - "5,14": { - "contents": "", - "bgcolor": "1" - }, - "5,15": { - "contents": "", - "bgcolor": "1" - }, - "5,16": { - "contents": "", - "bgcolor": "1" - }, - "5,17": { - "contents": "", - "bgcolor": "1" - }, - "5,18": { - "contents": "", - "bgcolor": "1" - }, - "5,19": { - "contents": "", - "bgcolor": "1" - }, - "5,2": { - "contents": "", - "bgcolor": "1" - }, - "5,20": { - "contents": "", - "bgcolor": "1" - }, - "5,21": { - "contents": "", - "bgcolor": "1" - }, - "5,22": { - "contents": "", - "bgcolor": "1" - }, - "5,23": { - "contents": "", - "bgcolor": "1" - }, - "5,24": { - "contents": "", - "bgcolor": "1" - }, - "5,25": { - "contents": "", - "bgcolor": "1" - }, - "5,26": { - "contents": "", - "bgcolor": "1" - }, - "5,27": { - "contents": "", - "bgcolor": "1" - }, - "5,28": { - "contents": "", - "bgcolor": "1" - }, - "5,29": { - "contents": "", - "bgcolor": "1" - }, - "5,3": { - "contents": "", - "bgcolor": "1" - }, - "5,30": { - "contents": "", - "bgcolor": "1" - }, - "5,31": { - "contents": "", - "bgcolor": "1" - }, - "5,32": { - "contents": "", - "bgcolor": "1" - }, - "5,33": { - "contents": "", - "bgcolor": "1" - }, - "5,34": { - "contents": "", - "bgcolor": "1" - }, - "5,35": { - "contents": "", - "bgcolor": "1" - }, - "5,36": { - "contents": "", - "bgcolor": "1" - }, - "5,37": { - "contents": "", - "bgcolor": "1" - }, - "5,38": { - "contents": "", - "bgcolor": "1" - }, - "5,39": { - "contents": "", - "bgcolor": "1" - }, - "5,4": { - "contents": "", - "bgcolor": "1" - }, - "5,40": { - "contents": "", - "bgcolor": "1" - }, - "5,41": { - "contents": "", - "bgcolor": "1" - }, - "5,42": { - "contents": "", - "bgcolor": "1" - }, - "5,43": { - "contents": "", - "bgcolor": "1" - }, - "5,44": { - "contents": "", - "bgcolor": "1" - }, - "5,45": { - "contents": "", - "bgcolor": "1" - }, - "5,46": { - "contents": "", - "bgcolor": "1" - }, - "5,47": { - "contents": "", - "bgcolor": "1" - }, - "5,48": { - "contents": "", - "bgcolor": "1" - }, - "5,49": { - "contents": "", - "bgcolor": "1" - }, - "5,5": { - "contents": "", - "bgcolor": "1" - }, - "5,50": { - "contents": "", - "bgcolor": "1" - }, - "5,51": { - "contents": "", - "bgcolor": "1" - }, - "5,52": { - "contents": "", - "bgcolor": "1" - }, - "5,53": { - "contents": "", - "bgcolor": "1" - }, - "5,54": { - "contents": "", - "bgcolor": "1" - }, - "5,55": { - "contents": "", - "bgcolor": "1" - }, - "5,56": { - "contents": "", - "bgcolor": "1" - }, - "5,57": { - "contents": "", - "bgcolor": "1" - }, - "5,58": { - "contents": "", - "bgcolor": "1" - }, - "5,59": { - "contents": "", - "bgcolor": "1" - }, - "5,6": { - "contents": "", - "bgcolor": "1" - }, - "5,60": { - "contents": "", - "bgcolor": "1" - }, - "5,61": { - "contents": "", - "bgcolor": "1" - }, - "5,62": { - "contents": "", - "bgcolor": "1" - }, - "5,63": { - "contents": "", - "bgcolor": "1" - }, - "5,64": { - "contents": "", - "bgcolor": "1" - }, - "5,65": { - "contents": "", - "bgcolor": "1" - }, - "5,66": { - "contents": "", - "bgcolor": "1" - }, - "5,67": { - "contents": "", - "bgcolor": "1" - }, - "5,68": { - "contents": "", - "bgcolor": "1" - }, - "5,69": { - "contents": "", - "bgcolor": "1" - }, - "5,7": { - "contents": "", - "bgcolor": "1" - }, - "5,70": { - "contents": "", - "bgcolor": "1" - }, - "5,71": { - "contents": "", - "bgcolor": "1" - }, - "5,72": { - "contents": "", - "bgcolor": "1" - }, - "5,73": { - "contents": "", - "bgcolor": "1" - }, - "5,74": { - "contents": "", - "bgcolor": "1" - }, - "5,75": { - "contents": "", - "bgcolor": "1" - }, - "5,76": { - "contents": "", - "bgcolor": "1" - }, - "5,77": { - "contents": "", - "bgcolor": "1" - }, - "5,78": { - "contents": "", - "bgcolor": "1" - }, - "5,79": { - "contents": "", - "bgcolor": "1" - }, - "5,8": { - "contents": "", - "bgcolor": "1" - }, - "5,9": { - "contents": "", - "bgcolor": "1" - }, - "6,0": { - "contents": "", - "bgcolor": "1" - }, - "6,1": { - "contents": "", - "bgcolor": "1" - }, - "6,10": { - "contents": "", - "bgcolor": "1" - }, - "6,11": { - "contents": "", - "bgcolor": "1" - }, - "6,12": { - "contents": "", - "bgcolor": "1" - }, - "6,13": { - "contents": "", - "bgcolor": "1" - }, - "6,14": { - "contents": "", - "bgcolor": "1" - }, - "6,15": { - "contents": "", - "bgcolor": "1" - }, - "6,16": { - "contents": "", - "bgcolor": "1" - }, - "6,17": { - "contents": "", - "bgcolor": "1" - }, - "6,18": { - "contents": "", - "bgcolor": "1" - }, - "6,19": { - "contents": "", - "bgcolor": "1" - }, - "6,2": { - "contents": "", - "bgcolor": "1" - }, - "6,20": { - "contents": "", - "bgcolor": "1" - }, - "6,21": { - "contents": "", - "bgcolor": "1" - }, - "6,22": { - "contents": "", - "bgcolor": "1" - }, - "6,23": { - "contents": "", - "bgcolor": "1" - }, - "6,24": { - "contents": "", - "bgcolor": "1" - }, - "6,25": { - "contents": "", - "bgcolor": "1" - }, - "6,26": { - "contents": "", - "bgcolor": "1" - }, - "6,27": { - "contents": "", - "bgcolor": "1" - }, - "6,28": { - "contents": "", - "bgcolor": "1" - }, - "6,29": { - "contents": "", - "bgcolor": "1" - }, - "6,3": { - "contents": "", - "bgcolor": "1" - }, - "6,30": { - "contents": "", - "bgcolor": "1" - }, - "6,31": { - "contents": "", - "bgcolor": "1" - }, - "6,32": { - "contents": "", - "bgcolor": "1" - }, - "6,33": { - "contents": "", - "bgcolor": "1" - }, - "6,34": { - "contents": "", - "bgcolor": "1" - }, - "6,35": { - "contents": "", - "bgcolor": "1" - }, - "6,36": { - "contents": "", - "bgcolor": "1" - }, - "6,37": { - "contents": "", - "bgcolor": "1" - }, - "6,38": { - "contents": "", - "bgcolor": "1" - }, - "6,39": { - "contents": "", - "bgcolor": "1" - }, - "6,4": { - "contents": "", - "bgcolor": "1" - }, - "6,40": { - "contents": "", - "bgcolor": "1" - }, - "6,41": { - "contents": "", - "bgcolor": "1" - }, - "6,42": { - "contents": "", - "bgcolor": "1" - }, - "6,43": { - "contents": "", - "bgcolor": "1" - }, - "6,44": { - "contents": "", - "bgcolor": "1" - }, - "6,45": { - "contents": "", - "bgcolor": "1" - }, - "6,46": { - "contents": "", - "bgcolor": "1" - }, - "6,47": { - "contents": "", - "bgcolor": "1" - }, - "6,48": { - "contents": "", - "bgcolor": "1" - }, - "6,49": { - "contents": "", - "bgcolor": "1" - }, - "6,5": { - "contents": "", - "bgcolor": "1" - }, - "6,50": { - "contents": "", - "bgcolor": "1" - }, - "6,51": { - "contents": "", - "bgcolor": "1" - }, - "6,52": { - "contents": "", - "bgcolor": "1" - }, - "6,53": { - "contents": "", - "bgcolor": "1" - }, - "6,54": { - "contents": "", - "bgcolor": "1" - }, - "6,55": { - "contents": "", - "bgcolor": "1" - }, - "6,56": { - "contents": "", - "bgcolor": "1" - }, - "6,57": { - "contents": "", - "bgcolor": "1" - }, - "6,58": { - "contents": "", - "bgcolor": "1" - }, - "6,59": { - "contents": "", - "bgcolor": "1" - }, - "6,6": { - "contents": "", - "bgcolor": "1" - }, - "6,60": { - "contents": "", - "bgcolor": "1" - }, - "6,61": { - "contents": "", - "bgcolor": "1" - }, - "6,62": { - "contents": "", - "bgcolor": "1" - }, - "6,63": { - "contents": "", - "bgcolor": "1" - }, - "6,64": { - "contents": "", - "bgcolor": "1" - }, - "6,65": { - "contents": "", - "bgcolor": "1" - }, - "6,66": { - "contents": "", - "bgcolor": "1" - }, - "6,67": { - "contents": "", - "bgcolor": "1" - }, - "6,68": { - "contents": "", - "bgcolor": "1" - }, - "6,69": { - "contents": "", - "bgcolor": "1" - }, - "6,7": { - "contents": "", - "bgcolor": "1" - }, - "6,70": { - "contents": "", - "bgcolor": "1" - }, - "6,71": { - "contents": "", - "bgcolor": "1" - }, - "6,72": { - "contents": "", - "bgcolor": "1" - }, - "6,73": { - "contents": "", - "bgcolor": "1" - }, - "6,74": { - "contents": "", - "bgcolor": "1" - }, - "6,75": { - "contents": "", - "bgcolor": "1" - }, - "6,76": { - "contents": "", - "bgcolor": "1" - }, - "6,77": { - "contents": "", - "bgcolor": "1" - }, - "6,78": { - "contents": "", - "bgcolor": "1" - }, - "6,79": { - "contents": "", - "bgcolor": "1" - }, - "6,8": { - "contents": "", - "bgcolor": "1" - }, - "6,9": { - "contents": "", - "bgcolor": "1" - }, - "7,0": { - "contents": "", - "bgcolor": "1" - }, - "7,1": { - "contents": "", - "bgcolor": "1" - }, - "7,10": { - "contents": "", - "bgcolor": "1" - }, - "7,11": { - "contents": "", - "bgcolor": "1" - }, - "7,12": { - "contents": "", - "bgcolor": "1" - }, - "7,13": { - "contents": "", - "bgcolor": "1" - }, - "7,14": { - "contents": "", - "bgcolor": "1" - }, - "7,15": { - "contents": "", - "bgcolor": "1" - }, - "7,16": { - "contents": "", - "bgcolor": "1" - }, - "7,17": { - "contents": "", - "bgcolor": "1" - }, - "7,18": { - "contents": "", - "bgcolor": "1" - }, - "7,19": { - "contents": "", - "bgcolor": "1" - }, - "7,2": { - "contents": "", - "bgcolor": "1" - }, - "7,20": { - "contents": "", - "bgcolor": "1" - }, - "7,21": { - "contents": "", - "bgcolor": "1" - }, - "7,22": { - "contents": "", - "bgcolor": "1" - }, - "7,23": { - "contents": "", - "bgcolor": "1" - }, - "7,24": { - "contents": "", - "bgcolor": "1" - }, - "7,25": { - "contents": "", - "bgcolor": "1" - }, - "7,26": { - "contents": "", - "bgcolor": "1" - }, - "7,27": { - "contents": "", - "bgcolor": "1" - }, - "7,28": { - "contents": "", - "bgcolor": "1" - }, - "7,29": { - "contents": "", - "bgcolor": "1" - }, - "7,3": { - "contents": "", - "bgcolor": "1" - }, - "7,30": { - "contents": "", - "bgcolor": "1" - }, - "7,31": { - "contents": "", - "bgcolor": "1" - }, - "7,32": { - "contents": "", - "bgcolor": "1" - }, - "7,33": { - "contents": "", - "bgcolor": "1" - }, - "7,34": { - "contents": "", - "bgcolor": "1" - }, - "7,35": { - "contents": "", - "bgcolor": "1" - }, - "7,36": { - "contents": "", - "bgcolor": "1" - }, - "7,37": { - "contents": "", - "bgcolor": "1" - }, - "7,38": { - "contents": "", - "bgcolor": "1" - }, - "7,39": { - "contents": "", - "bgcolor": "1" - }, - "7,4": { - "contents": "", - "bgcolor": "1" - }, - "7,40": { - "contents": "", - "bgcolor": "1" - }, - "7,41": { - "contents": "", - "bgcolor": "1" - }, - "7,42": { - "contents": "", - "bgcolor": "1" - }, - "7,43": { - "contents": "", - "bgcolor": "1" - }, - "7,44": { - "contents": "", - "bgcolor": "1" - }, - "7,45": { - "contents": "", - "bgcolor": "1" - }, - "7,46": { - "contents": "", - "bgcolor": "1" - }, - "7,47": { - "contents": "", - "bgcolor": "1" - }, - "7,48": { - "contents": "", - "bgcolor": "1" - }, - "7,49": { - "contents": "", - "bgcolor": "1" - }, - "7,5": { - "contents": "", - "bgcolor": "1" - }, - "7,50": { - "contents": "", - "bgcolor": "1" - }, - "7,51": { - "contents": "", - "bgcolor": "1" - }, - "7,52": { - "contents": "", - "bgcolor": "1" - }, - "7,53": { - "contents": "", - "bgcolor": "1" - }, - "7,54": { - "contents": "", - "bgcolor": "1" - }, - "7,55": { - "contents": "", - "bgcolor": "1" - }, - "7,56": { - "contents": "", - "bgcolor": "1" - }, - "7,57": { - "contents": "", - "bgcolor": "1" - }, - "7,58": { - "contents": "", - "bgcolor": "1" - }, - "7,59": { - "contents": "", - "bgcolor": "1" - }, - "7,6": { - "contents": "", - "bgcolor": "1" - }, - "7,60": { - "contents": "", - "bgcolor": "1" - }, - "7,61": { - "contents": "", - "bgcolor": "1" - }, - "7,62": { - "contents": "", - "bgcolor": "1" - }, - "7,63": { - "contents": "", - "bgcolor": "1" - }, - "7,64": { - "contents": "", - "bgcolor": "1" - }, - "7,65": { - "contents": "", - "bgcolor": "1" - }, - "7,66": { - "contents": "", - "bgcolor": "1" - }, - "7,67": { - "contents": "", - "bgcolor": "1" - }, - "7,68": { - "contents": "", - "bgcolor": "1" - }, - "7,69": { - "contents": "", - "bgcolor": "1" - }, - "7,7": { - "contents": "", - "bgcolor": "1" - }, - "7,70": { - "contents": "", - "bgcolor": "1" - }, - "7,71": { - "contents": "", - "bgcolor": "1" - }, - "7,72": { - "contents": "", - "bgcolor": "1" - }, - "7,73": { - "contents": "", - "bgcolor": "1" - }, - "7,74": { - "contents": "", - "bgcolor": "1" - }, - "7,75": { - "contents": "", - "bgcolor": "1" - }, - "7,76": { - "contents": "", - "bgcolor": "1" - }, - "7,77": { - "contents": "", - "bgcolor": "1" - }, - "7,78": { - "contents": "", - "bgcolor": "1" - }, - "7,79": { - "contents": "", - "bgcolor": "1" - }, - "7,8": { - "contents": "", - "bgcolor": "1" - }, - "7,9": { - "contents": "", - "bgcolor": "1" - }, - "8,0": { - "contents": "", - "bgcolor": "1" - }, - "8,1": { - "contents": "", - "bgcolor": "1" - }, - "8,10": { - "contents": "", - "bgcolor": "1" - }, - "8,11": { - "contents": "", - "bgcolor": "1" - }, - "8,12": { - "contents": "", - "bgcolor": "1" - }, - "8,13": { - "contents": "", - "bgcolor": "1" - }, - "8,14": { - "contents": "", - "bgcolor": "1" - }, - "8,15": { - "contents": "", - "bgcolor": "1" - }, - "8,16": { - "contents": "", - "bgcolor": "1" - }, - "8,17": { - "contents": "", - "bgcolor": "1" - }, - "8,18": { - "contents": "", - "bgcolor": "1" - }, - "8,19": { - "contents": "", - "bgcolor": "1" - }, - "8,2": { - "contents": "", - "bgcolor": "1" - }, - "8,20": { - "contents": "", - "bgcolor": "1" - }, - "8,21": { - "contents": "", - "bgcolor": "1" - }, - "8,22": { - "contents": "", - "bgcolor": "1" - }, - "8,23": { - "contents": "", - "bgcolor": "1" - }, - "8,24": { - "contents": "", - "bgcolor": "1" - }, - "8,25": { - "contents": "", - "bgcolor": "1" - }, - "8,26": { - "contents": "", - "bgcolor": "1" - }, - "8,27": { - "contents": "", - "bgcolor": "1" - }, - "8,28": { - "contents": "", - "bgcolor": "1" - }, - "8,29": { - "contents": "", - "bgcolor": "1" - }, - "8,3": { - "contents": "", - "bgcolor": "1" - }, - "8,30": { - "contents": "", - "bgcolor": "1" - }, - "8,31": { - "contents": "", - "bgcolor": "1" - }, - "8,32": { - "contents": "", - "bgcolor": "1" - }, - "8,33": { - "contents": "", - "bgcolor": "1" - }, - "8,34": { - "contents": "", - "bgcolor": "1" - }, - "8,35": { - "contents": "", - "bgcolor": "1" - }, - "8,36": { - "contents": "", - "bgcolor": "1" - }, - "8,37": { - "contents": "", - "bgcolor": "1" - }, - "8,38": { - "contents": "", - "bgcolor": "1" - }, - "8,39": { - "contents": "", - "bgcolor": "1" - }, - "8,4": { - "contents": "", - "bgcolor": "1" - }, - "8,40": { - "contents": "", - "bgcolor": "1" - }, - "8,41": { - "contents": "", - "bgcolor": "1" - }, - "8,42": { - "contents": "", - "bgcolor": "1" - }, - "8,43": { - "contents": "", - "bgcolor": "1" - }, - "8,44": { - "contents": "", - "bgcolor": "1" - }, - "8,45": { - "contents": "", - "bgcolor": "1" - }, - "8,46": { - "contents": "", - "bgcolor": "1" - }, - "8,47": { - "contents": "", - "bgcolor": "1" - }, - "8,48": { - "contents": "", - "bgcolor": "1" - }, - "8,49": { - "contents": "", - "bgcolor": "1" - }, - "8,5": { - "contents": "", - "bgcolor": "1" - }, - "8,50": { - "contents": "", - "bgcolor": "1" - }, - "8,51": { - "contents": "", - "bgcolor": "1" - }, - "8,52": { - "contents": "", - "bgcolor": "1" - }, - "8,53": { - "contents": "", - "bgcolor": "1" - }, - "8,54": { - "contents": "", - "bgcolor": "1" - }, - "8,55": { - "contents": "", - "bgcolor": "1" - }, - "8,56": { - "contents": "", - "bgcolor": "1" - }, - "8,57": { - "contents": "", - "bgcolor": "1" - }, - "8,58": { - "contents": "", - "bgcolor": "1" - }, - "8,59": { - "contents": "", - "bgcolor": "1" - }, - "8,6": { - "contents": "", - "bgcolor": "1" - }, - "8,60": { - "contents": "", - "bgcolor": "1" - }, - "8,61": { - "contents": "", - "bgcolor": "1" - }, - "8,62": { - "contents": "", - "bgcolor": "1" - }, - "8,63": { - "contents": "", - "bgcolor": "1" - }, - "8,64": { - "contents": "", - "bgcolor": "1" - }, - "8,65": { - "contents": "", - "bgcolor": "1" - }, - "8,66": { - "contents": "", - "bgcolor": "1" - }, - "8,67": { - "contents": "", - "bgcolor": "1" - }, - "8,68": { - "contents": "", - "bgcolor": "1" - }, - "8,69": { - "contents": "", - "bgcolor": "1" - }, - "8,7": { - "contents": "", - "bgcolor": "1" - }, - "8,70": { - "contents": "", - "bgcolor": "1" - }, - "8,71": { - "contents": "", - "bgcolor": "1" - }, - "8,72": { - "contents": "", - "bgcolor": "1" - }, - "8,73": { - "contents": "", - "bgcolor": "1" - }, - "8,74": { - "contents": "", - "bgcolor": "1" - }, - "8,75": { - "contents": "", - "bgcolor": "1" - }, - "8,76": { - "contents": "", - "bgcolor": "1" - }, - "8,77": { - "contents": "", - "bgcolor": "1" - }, - "8,78": { - "contents": "", - "bgcolor": "1" - }, - "8,79": { - "contents": "", - "bgcolor": "1" - }, - "8,8": { - "contents": "", - "bgcolor": "1" - }, - "8,9": { - "contents": "", - "bgcolor": "1" - }, - "9,0": { - "contents": "", - "bgcolor": "1" - }, - "9,1": { - "contents": "", - "bgcolor": "1" - }, - "9,10": { - "contents": "", - "bgcolor": "1" - }, - "9,11": { - "contents": "", - "bgcolor": "1" - }, - "9,12": { - "contents": "", - "bgcolor": "1" - }, - "9,13": { - "contents": "", - "bgcolor": "1" - }, - "9,14": { - "contents": "", - "bgcolor": "1" - }, - "9,15": { - "contents": "", - "bgcolor": "1" - }, - "9,16": { - "contents": "", - "bgcolor": "1" - }, - "9,17": { - "contents": "", - "bgcolor": "1" - }, - "9,18": { - "contents": "", - "bgcolor": "1" - }, - "9,19": { - "contents": "", - "bgcolor": "1" - }, - "9,2": { - "contents": "", - "bgcolor": "1" - }, - "9,20": { - "contents": "", - "bgcolor": "1" - }, - "9,21": { - "contents": "", - "bgcolor": "1" - }, - "9,22": { - "contents": "", - "bgcolor": "1" - }, - "9,23": { - "contents": "", - "bgcolor": "1" - }, - "9,24": { - "contents": "", - "bgcolor": "1" - }, - "9,25": { - "contents": "", - "bgcolor": "1" - }, - "9,26": { - "contents": "", - "bgcolor": "1" - }, - "9,27": { - "contents": "", - "bgcolor": "1" - }, - "9,28": { - "contents": "", - "bgcolor": "1" - }, - "9,29": { - "contents": "", - "bgcolor": "1" - }, - "9,3": { - "contents": "", - "bgcolor": "1" - }, - "9,30": { - "contents": "", - "bgcolor": "1" - }, - "9,31": { - "contents": "", - "bgcolor": "1" - }, - "9,32": { - "contents": "", - "bgcolor": "1" - }, - "9,33": { - "contents": "", - "bgcolor": "1" - }, - "9,34": { - "contents": "", - "bgcolor": "1" - }, - "9,35": { - "contents": "", - "bgcolor": "1" - }, - "9,36": { - "contents": "", - "bgcolor": "1" - }, - "9,37": { - "contents": "", - "bgcolor": "1" - }, - "9,38": { - "contents": "", - "bgcolor": "1" - }, - "9,39": { - "contents": "", - "bgcolor": "1" - }, - "9,4": { - "contents": "", - "bgcolor": "1" - }, - "9,40": { - "contents": "", - "bgcolor": "1" - }, - "9,41": { - "contents": "", - "bgcolor": "1" - }, - "9,42": { - "contents": "", - "bgcolor": "1" - }, - "9,43": { - "contents": "", - "bgcolor": "1" - }, - "9,44": { - "contents": "", - "bgcolor": "1" - }, - "9,45": { - "contents": "", - "bgcolor": "1" - }, - "9,46": { - "contents": "", - "bgcolor": "1" - }, - "9,47": { - "contents": "", - "bgcolor": "1" - }, - "9,48": { - "contents": "", - "bgcolor": "1" - }, - "9,49": { - "contents": "", - "bgcolor": "1" - }, - "9,5": { - "contents": "", - "bgcolor": "1" - }, - "9,50": { - "contents": "", - "bgcolor": "1" - }, - "9,51": { - "contents": "", - "bgcolor": "1" - }, - "9,52": { - "contents": "", - "bgcolor": "1" - }, - "9,53": { - "contents": "", - "bgcolor": "1" - }, - "9,54": { - "contents": "", - "bgcolor": "1" - }, - "9,55": { - "contents": "", - "bgcolor": "1" - }, - "9,56": { - "contents": "", - "bgcolor": "1" - }, - "9,57": { - "contents": "", - "bgcolor": "1" - }, - "9,58": { - "contents": "", - "bgcolor": "1" - }, - "9,59": { - "contents": "", - "bgcolor": "1" - }, - "9,6": { - "contents": "", - "bgcolor": "1" - }, - "9,60": { - "contents": "", - "bgcolor": "1" - }, - "9,61": { - "contents": "", - "bgcolor": "1" - }, - "9,62": { - "contents": "", - "bgcolor": "1" - }, - "9,63": { - "contents": "", - "bgcolor": "1" - }, - "9,64": { - "contents": "", - "bgcolor": "1" - }, - "9,65": { - "contents": "", - "bgcolor": "1" - }, - "9,66": { - "contents": "", - "bgcolor": "1" - }, - "9,67": { - "contents": "", - "bgcolor": "1" - }, - "9,68": { - "contents": "", - "bgcolor": "1" - }, - "9,69": { - "contents": "", - "bgcolor": "1" - }, - "9,7": { - "contents": "", - "bgcolor": "1" - }, - "9,70": { - "contents": "", - "bgcolor": "1" - }, - "9,71": { - "contents": "", - "bgcolor": "1" - }, - "9,72": { - "contents": "", - "bgcolor": "1" - }, - "9,73": { - "contents": "", - "bgcolor": "1" - }, - "9,74": { - "contents": "", - "bgcolor": "1" - }, - "9,75": { - "contents": "", - "bgcolor": "1" - }, - "9,76": { - "contents": "", - "bgcolor": "1" - }, - "9,77": { - "contents": "", - "bgcolor": "1" - }, - "9,78": { - "contents": "", - "bgcolor": "1" - }, - "9,79": { - "contents": "", - "bgcolor": "1" - }, - "9,8": { - "contents": "", - "bgcolor": "1" - }, - "9,9": { - "contents": "", - "bgcolor": "1" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/24.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/24.typescript deleted file mode 100644 index aba107d52e298..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/24.typescript +++ /dev/null @@ -1 +0,0 @@ -caa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/25.json b/crates/turborepo-vt100/tests/data/fixtures/el/25.json deleted file mode 100644 index 504426ce22697..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/25.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": " cb", - "cells": { - "0,79": { - "contents": "c" - }, - "1,0": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/25.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/25.typescript deleted file mode 100644 index 40224c4257062..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/25.typescript +++ /dev/null @@ -1 +0,0 @@ -cabc \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/26.json b/crates/turborepo-vt100/tests/data/fixtures/el/26.json deleted file mode 100644 index 661055f56aa7c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/26.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\nb", - "cells": { - "1,0": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/26.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/26.typescript deleted file mode 100644 index d2e06ee40fb4e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/26.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/3.json b/crates/turborepo-vt100/tests/data/fixtures/el/3.json deleted file mode 100644 index 58542554ada01..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/3.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/3.typescript deleted file mode 100644 index 8be9a9b45e8f6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/4.json b/crates/turborepo-vt100/tests/data/fixtures/el/4.json deleted file mode 100644 index 6893191049387..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/4.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - } - }, - "cursor_position": [ - 19, - 21 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/4.typescript deleted file mode 100644 index cbd05236c53b7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/5.json b/crates/turborepo-vt100/tests/data/fixtures/el/5.json deleted file mode 100644 index f4b8e818c8fd6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/5.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": "f\n\n\n\n bar\n\n\n\n\n baz", - "cells": { - "0,0": { - "contents": "f" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/5.typescript deleted file mode 100644 index 63e3288ac9a2c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/5.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/6.json b/crates/turborepo-vt100/tests/data/fixtures/el/6.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/6.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/6.typescript deleted file mode 100644 index 9d9954112aaeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/7.json b/crates/turborepo-vt100/tests/data/fixtures/el/7.json deleted file mode 100644 index 391f3aa1a1073..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/7.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "contents": "foo\n\n\n\n barbar\n\n\n\n\n bazbaz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "4,7": { - "contents": "b" - }, - "4,8": { - "contents": "a" - }, - "4,9": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 19, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/7.typescript deleted file mode 100644 index 2f06911866a49..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/7.typescript +++ /dev/null @@ -1 +0,0 @@ -foobarbarbazbazquux \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/8.json b/crates/turborepo-vt100/tests/data/fixtures/el/8.json deleted file mode 100644 index ab8752fb15f2a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/8.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n bazbaz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,10": { - "contents": "a" - }, - "9,11": { - "contents": "z" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - }, - "9,9": { - "contents": "b" - } - }, - "cursor_position": [ - 4, - 7 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/8.typescript deleted file mode 100644 index 28452bf14852e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/8.typescript +++ /dev/null @@ -1 +0,0 @@ -[?0K \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/9.json b/crates/turborepo-vt100/tests/data/fixtures/el/9.json deleted file mode 100644 index 58542554ada01..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/9.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contents": "foo\n\n\n\n bar\n\n\n\n\n baz\n\n\n\n\n\n\n\n\n\n quux", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "19,19": { - "contents": "q" - }, - "19,20": { - "contents": "u" - }, - "19,21": { - "contents": "u" - }, - "19,22": { - "contents": "x" - }, - "4,4": { - "contents": "b" - }, - "4,5": { - "contents": "a" - }, - "4,6": { - "contents": "r" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "z" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/el/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/el/9.typescript deleted file mode 100644 index 61525dafebd88..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/el/9.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1K \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff.in b/crates/turborepo-vt100/tests/data/fixtures/ff.in deleted file mode 100644 index 5a6f7222443a2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff.in +++ /dev/null @@ -1,5 +0,0 @@ -foo\x0cbar -\x1b[H\x1b[J\x1b[4;80H -a -\x0c -b diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/1.json b/crates/turborepo-vt100/tests/data/fixtures/ff/1.json deleted file mode 100644 index dbf43233a8793..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "foo\n bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "1,3": { - "contents": "b" - }, - "1,4": { - "contents": "a" - }, - "1,5": { - "contents": "r" - } - }, - "cursor_position": [ - 1, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/ff/1.typescript deleted file mode 100644 index a266d5706ec5a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foo bar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/2.json b/crates/turborepo-vt100/tests/data/fixtures/ff/2.json deleted file mode 100644 index 1c647493e9c57..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 3, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/ff/2.typescript deleted file mode 100644 index 0325a4a75982f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/3.json b/crates/turborepo-vt100/tests/data/fixtures/ff/3.json deleted file mode 100644 index 8d259dd82206a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/3.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n a", - "cells": { - "3,79": { - "contents": "a" - } - }, - "cursor_position": [ - 3, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/ff/3.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/3.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/4.json b/crates/turborepo-vt100/tests/data/fixtures/ff/4.json deleted file mode 100644 index 26ec66dfbf401..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/4.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n a", - "cells": { - "3,79": { - "contents": "a" - } - }, - "cursor_position": [ - 4, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/ff/4.typescript deleted file mode 100644 index 8214d0ee07991..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/5.json b/crates/turborepo-vt100/tests/data/fixtures/ff/5.json deleted file mode 100644 index a22356af1c167..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/5.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n a\n\nb", - "cells": { - "3,79": { - "contents": "a" - }, - "5,0": { - "contents": "b" - } - }, - "cursor_position": [ - 5, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ff/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/ff/5.typescript deleted file mode 100644 index 63d8dbd40c235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ff/5.typescript +++ /dev/null @@ -1 +0,0 @@ -b \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech.in b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech.in deleted file mode 100644 index b152d5b2ffd29..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech.in +++ /dev/null @@ -1,15 +0,0 @@ -\x1b[10;10Hfoobar -\x1b[10;12H\x1b[3@ -\x1b[4P -\x1b[100@ -obar -\x1b[10;12H\x1b[100P -obar -\x1b[10;13H\x1b[X -\x1b[10;11H\x1b[4X -\x1b[10;11H\x1b[400X -\x1b[1;80H \x1b[@ -\x1b[1;80H \x1b[X -\x1bc\x1b[1;78Hãƒab -\x1b[H\x1b[@ -\x1bc\x1b[1mデ\x08\x1b[@ diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/1.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/1.json deleted file mode 100644 index fbbb884af5235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,11": { - "contents": "o" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 15 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/1.typescript deleted file mode 100644 index c3d4ba4a0a49b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/10.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/10.json deleted file mode 100644 index 90681c5995051..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/10.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n f", - "cells": { - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 10 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/10.typescript deleted file mode 100644 index baecb62242fec..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/10.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/11.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/11.json deleted file mode 100644 index fc1e54f3d6e66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/11.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": " \n\n\n\n\n\n\n\n\n f", - "cells": { - "0,79": { - "contents": " " - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/11.typescript deleted file mode 100644 index d4e75c1775fd5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/11.typescript +++ /dev/null @@ -1 +0,0 @@ - [@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/12.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/12.json deleted file mode 100644 index fc1e54f3d6e66..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/12.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": " \n\n\n\n\n\n\n\n\n f", - "cells": { - "0,79": { - "contents": " " - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/12.typescript deleted file mode 100644 index 55039e7fe056e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/12.typescript +++ /dev/null @@ -1 +0,0 @@ -  \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/13.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/13.json deleted file mode 100644 index 3f67407e961d1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/13.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "contents": " ãƒab", - "cells": { - "0,77": { - "contents": "ãƒ", - "is_wide": true - }, - "0,78": { - "contents": "", - "is_wide_continuation": true - }, - "0,79": { - "contents": "a" - }, - "1,0": { - "contents": "b" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/13.typescript deleted file mode 100644 index dca42a7abfc48..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/13.typescript +++ /dev/null @@ -1 +0,0 @@ -cãƒab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/14.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/14.json deleted file mode 100644 index a8f912c0f61eb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/14.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contents": " ãƒ\nb", - "cells": { - "0,78": { - "contents": "ãƒ", - "is_wide": true - }, - "0,79": { - "contents": "", - "is_wide_continuation": true - }, - "1,0": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/14.typescript deleted file mode 100644 index f6122a6b0980b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/14.typescript +++ /dev/null @@ -1 +0,0 @@ -[@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/15.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/15.json deleted file mode 100644 index ec031324ed814..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/15.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "デ", - "cells": { - "0,0": { - "contents": "デ", - "is_wide": true, - "bold": true - }, - "0,1": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/15.typescript deleted file mode 100644 index 8c836092d343a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/15.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ[@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/2.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/2.json deleted file mode 100644 index 67970308a79c0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/2.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n fo obar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,14": { - "contents": "o" - }, - "9,15": { - "contents": "b" - }, - "9,16": { - "contents": "a" - }, - "9,17": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/2.typescript deleted file mode 100644 index a375169120725..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/2.typescript +++ /dev/null @@ -1 +0,0 @@ -[3@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/3.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/3.json deleted file mode 100644 index 27613f89ec4f4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/3.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n fobar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,11": { - "contents": "b" - }, - "9,12": { - "contents": "a" - }, - "9,13": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/3.typescript deleted file mode 100644 index 8e8dfc18c9308..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/4.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/4.json deleted file mode 100644 index b747c5dc87300..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/4.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n fo", - "cells": { - "9,10": { - "contents": "o" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/4.typescript deleted file mode 100644 index 41b8ff91beecc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/4.typescript +++ /dev/null @@ -1 +0,0 @@ -[100@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/5.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/5.json deleted file mode 100644 index fbbb884af5235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/5.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,11": { - "contents": "o" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 15 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/5.typescript deleted file mode 100644 index f8a992280f40e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/5.typescript +++ /dev/null @@ -1 +0,0 @@ -obar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/6.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/6.json deleted file mode 100644 index b747c5dc87300..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/6.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n fo", - "cells": { - "9,10": { - "contents": "o" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/6.typescript deleted file mode 100644 index ce2d65f4e3483..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/7.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/7.json deleted file mode 100644 index fbbb884af5235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/7.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,11": { - "contents": "o" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 15 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/7.typescript deleted file mode 100644 index f8a992280f40e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/7.typescript +++ /dev/null @@ -1 +0,0 @@ -obar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/8.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/8.json deleted file mode 100644 index 98e3f975b4711..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/8.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n foo ar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,11": { - "contents": "o" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/8.typescript deleted file mode 100644 index d0657fa83b0c5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/8.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/9.json b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/9.json deleted file mode 100644 index 5d5563672df11..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/9.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n f r", - "cells": { - "9,14": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 10 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/9.typescript deleted file mode 100644 index d176e17a49fad..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ich_dch_ech/9.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/icon_name.in b/crates/turborepo-vt100/tests/data/fixtures/icon_name.in deleted file mode 100644 index 455fdb616a724..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/icon_name.in +++ /dev/null @@ -1,2 +0,0 @@ -\x1b]1;it's an icon name\x07 -\x1b]1;\x07 diff --git a/crates/turborepo-vt100/tests/data/fixtures/icon_name/1.json b/crates/turborepo-vt100/tests/data/fixtures/icon_name/1.json deleted file mode 100644 index bb619c5137b55..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/icon_name/1.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "icon_name": "it's an icon name" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/icon_name/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/icon_name/1.typescript deleted file mode 100644 index e1764774e7100..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/icon_name/1.typescript +++ /dev/null @@ -1 +0,0 @@ -]1;it's an icon name \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/icon_name/2.json b/crates/turborepo-vt100/tests/data/fixtures/icon_name/2.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/icon_name/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/icon_name/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/icon_name/2.typescript deleted file mode 100644 index c1556757a0773..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/icon_name/2.typescript +++ /dev/null @@ -1 +0,0 @@ -]1; \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl.in b/crates/turborepo-vt100/tests/data/fixtures/il_dl.in deleted file mode 100644 index 3e2a3f2166019..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl.in +++ /dev/null @@ -1,24 +0,0 @@ -\x1b[10;10Hfoobar\x1b[3D -\x1b[L -\x1b[3L -\x1b[500L -\x1b[10;10Hfoobar\x1b[3D\x1b[6A -\x1b[M -\x1b[3M -\x1b[500M -\x1bc\x1b[1;80H -a -\x1b[L -bc -\x1bc\x1b[1;80H -a -b -\x1b[L -cd -\x1bc\na\x1b[1;80Hb\x1b[M -\x1bc\x1b[1;80Haaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x1b[H -\x1b[L -\x1bc\x1b[1;80H\x1b[1mab\x1b[M -\x1bc\x1b[23;80Hab\x1b[23H\x1b[L -\x1bc\x1b[1mb\x1b[1;80Ha\x1b[L\x1b[1;80Hab\x1b[H -\x1b[L diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/1.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/1.json deleted file mode 100644 index e707271ad6f22..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,11": { - "contents": "o" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/1.typescript deleted file mode 100644 index ed337e89025cb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/10.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/10.json deleted file mode 100644 index 59543cbe688b7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/10.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,79": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/10.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/10.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/11.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/11.json deleted file mode 100644 index f6ff7b8f3ddfc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/11.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n a", - "cells": { - "1,79": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/11.typescript deleted file mode 100644 index a330c08609c9c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/11.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/12.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/12.json deleted file mode 100644 index b8a636c407e5d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/12.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "\nbc a", - "cells": { - "1,0": { - "contents": "b" - }, - "1,1": { - "contents": "c" - }, - "1,79": { - "contents": "a" - } - }, - "cursor_position": [ - 1, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/12.typescript deleted file mode 100644 index e5d8f44be26db..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/12.typescript +++ /dev/null @@ -1 +0,0 @@ -bc \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/13.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/13.json deleted file mode 100644 index 5deb58bc170fa..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/13.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/13.typescript deleted file mode 100644 index fc29e5044a0ed..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/13.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/14.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/14.json deleted file mode 100644 index 59543cbe688b7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/14.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,79": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/14.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/14.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/15.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/15.json deleted file mode 100644 index a28d5bc200bfe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/15.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": " ab", - "cells": { - "0,79": { - "contents": "a" - }, - "1,0": { - "contents": "b" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/15.typescript deleted file mode 100644 index 63d8dbd40c235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/15.typescript +++ /dev/null @@ -1 +0,0 @@ -b \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/16.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/16.json deleted file mode 100644 index 25867816cf160..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/16.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": " a\n\nb", - "cells": { - "0,79": { - "contents": "a" - }, - "2,0": { - "contents": "b" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/16.typescript deleted file mode 100644 index a330c08609c9c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/16.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/17.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/17.json deleted file mode 100644 index 4b2e9008f3cd6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/17.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": " a cd\nb", - "cells": { - "0,79": { - "contents": "a" - }, - "1,1": { - "contents": "c" - }, - "1,2": { - "contents": "d" - }, - "2,0": { - "contents": "b" - } - }, - "cursor_position": [ - 1, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/17.typescript deleted file mode 100644 index 25038d7b62182..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/17.typescript +++ /dev/null @@ -1 +0,0 @@ -cd \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/18.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/18.json deleted file mode 100644 index 131a334d42833..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/18.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "a", - "cells": { - "0,0": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/18.typescript deleted file mode 100644 index 607e0b1c08509..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/18.typescript +++ /dev/null @@ -1,2 +0,0 @@ -c -ab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/19.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/19.json deleted file mode 100644 index 2f22274832375..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/19.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "contents": " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "cells": { - "0,79": { - "contents": "a" - }, - "1,0": { - "contents": "a" - }, - "1,1": { - "contents": "a" - }, - "1,10": { - "contents": "a" - }, - "1,11": { - "contents": "a" - }, - "1,12": { - "contents": "a" - }, - "1,13": { - "contents": "a" - }, - "1,14": { - "contents": "a" - }, - "1,15": { - "contents": "a" - }, - "1,16": { - "contents": "a" - }, - "1,17": { - "contents": "a" - }, - "1,18": { - "contents": "a" - }, - "1,19": { - "contents": "a" - }, - "1,2": { - "contents": "a" - }, - "1,20": { - "contents": "a" - }, - "1,21": { - "contents": "a" - }, - "1,22": { - "contents": "a" - }, - "1,23": { - "contents": "a" - }, - "1,24": { - "contents": "a" - }, - "1,25": { - "contents": "a" - }, - "1,26": { - "contents": "a" - }, - "1,27": { - "contents": "a" - }, - "1,28": { - "contents": "a" - }, - "1,29": { - "contents": "a" - }, - "1,3": { - "contents": "a" - }, - "1,30": { - "contents": "a" - }, - "1,31": { - "contents": "a" - }, - "1,32": { - "contents": "a" - }, - "1,33": { - "contents": "a" - }, - "1,34": { - "contents": "a" - }, - "1,35": { - "contents": "a" - }, - "1,36": { - "contents": "a" - }, - "1,37": { - "contents": "a" - }, - "1,38": { - "contents": "a" - }, - "1,39": { - "contents": "a" - }, - "1,4": { - "contents": "a" - }, - "1,40": { - "contents": "a" - }, - "1,41": { - "contents": "a" - }, - "1,42": { - "contents": "a" - }, - "1,43": { - "contents": "a" - }, - "1,44": { - "contents": "a" - }, - "1,45": { - "contents": "a" - }, - "1,46": { - "contents": "a" - }, - "1,47": { - "contents": "a" - }, - "1,48": { - "contents": "a" - }, - "1,49": { - "contents": "a" - }, - "1,5": { - "contents": "a" - }, - "1,50": { - "contents": "a" - }, - "1,51": { - "contents": "a" - }, - "1,52": { - "contents": "a" - }, - "1,53": { - "contents": "a" - }, - "1,54": { - "contents": "a" - }, - "1,55": { - "contents": "a" - }, - "1,56": { - "contents": "a" - }, - "1,57": { - "contents": "a" - }, - "1,58": { - "contents": "a" - }, - "1,59": { - "contents": "a" - }, - "1,6": { - "contents": "a" - }, - "1,60": { - "contents": "a" - }, - "1,61": { - "contents": "a" - }, - "1,62": { - "contents": "a" - }, - "1,63": { - "contents": "a" - }, - "1,64": { - "contents": "a" - }, - "1,65": { - "contents": "a" - }, - "1,66": { - "contents": "a" - }, - "1,67": { - "contents": "a" - }, - "1,68": { - "contents": "a" - }, - "1,69": { - "contents": "a" - }, - "1,7": { - "contents": "a" - }, - "1,70": { - "contents": "a" - }, - "1,71": { - "contents": "a" - }, - "1,72": { - "contents": "a" - }, - "1,73": { - "contents": "a" - }, - "1,74": { - "contents": "a" - }, - "1,75": { - "contents": "a" - }, - "1,76": { - "contents": "a" - }, - "1,77": { - "contents": "a" - }, - "1,78": { - "contents": "a" - }, - "1,79": { - "contents": "a" - }, - "1,8": { - "contents": "a" - }, - "1,9": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/19.typescript deleted file mode 100644 index bdb7b924d867e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/19.typescript +++ /dev/null @@ -1 +0,0 @@ -caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/2.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/2.json deleted file mode 100644 index e846eb368ae77..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/2.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "10,10": { - "contents": "o" - }, - "10,11": { - "contents": "o" - }, - "10,12": { - "contents": "b" - }, - "10,13": { - "contents": "a" - }, - "10,14": { - "contents": "r" - }, - "10,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/2.typescript deleted file mode 100644 index a330c08609c9c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/20.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/20.json deleted file mode 100644 index 04b71665e6517..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/20.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "contents": "\n aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "cells": { - "1,79": { - "contents": "a" - }, - "2,0": { - "contents": "a" - }, - "2,1": { - "contents": "a" - }, - "2,10": { - "contents": "a" - }, - "2,11": { - "contents": "a" - }, - "2,12": { - "contents": "a" - }, - "2,13": { - "contents": "a" - }, - "2,14": { - "contents": "a" - }, - "2,15": { - "contents": "a" - }, - "2,16": { - "contents": "a" - }, - "2,17": { - "contents": "a" - }, - "2,18": { - "contents": "a" - }, - "2,19": { - "contents": "a" - }, - "2,2": { - "contents": "a" - }, - "2,20": { - "contents": "a" - }, - "2,21": { - "contents": "a" - }, - "2,22": { - "contents": "a" - }, - "2,23": { - "contents": "a" - }, - "2,24": { - "contents": "a" - }, - "2,25": { - "contents": "a" - }, - "2,26": { - "contents": "a" - }, - "2,27": { - "contents": "a" - }, - "2,28": { - "contents": "a" - }, - "2,29": { - "contents": "a" - }, - "2,3": { - "contents": "a" - }, - "2,30": { - "contents": "a" - }, - "2,31": { - "contents": "a" - }, - "2,32": { - "contents": "a" - }, - "2,33": { - "contents": "a" - }, - "2,34": { - "contents": "a" - }, - "2,35": { - "contents": "a" - }, - "2,36": { - "contents": "a" - }, - "2,37": { - "contents": "a" - }, - "2,38": { - "contents": "a" - }, - "2,39": { - "contents": "a" - }, - "2,4": { - "contents": "a" - }, - "2,40": { - "contents": "a" - }, - "2,41": { - "contents": "a" - }, - "2,42": { - "contents": "a" - }, - "2,43": { - "contents": "a" - }, - "2,44": { - "contents": "a" - }, - "2,45": { - "contents": "a" - }, - "2,46": { - "contents": "a" - }, - "2,47": { - "contents": "a" - }, - "2,48": { - "contents": "a" - }, - "2,49": { - "contents": "a" - }, - "2,5": { - "contents": "a" - }, - "2,50": { - "contents": "a" - }, - "2,51": { - "contents": "a" - }, - "2,52": { - "contents": "a" - }, - "2,53": { - "contents": "a" - }, - "2,54": { - "contents": "a" - }, - "2,55": { - "contents": "a" - }, - "2,56": { - "contents": "a" - }, - "2,57": { - "contents": "a" - }, - "2,58": { - "contents": "a" - }, - "2,59": { - "contents": "a" - }, - "2,6": { - "contents": "a" - }, - "2,60": { - "contents": "a" - }, - "2,61": { - "contents": "a" - }, - "2,62": { - "contents": "a" - }, - "2,63": { - "contents": "a" - }, - "2,64": { - "contents": "a" - }, - "2,65": { - "contents": "a" - }, - "2,66": { - "contents": "a" - }, - "2,67": { - "contents": "a" - }, - "2,68": { - "contents": "a" - }, - "2,69": { - "contents": "a" - }, - "2,7": { - "contents": "a" - }, - "2,70": { - "contents": "a" - }, - "2,71": { - "contents": "a" - }, - "2,72": { - "contents": "a" - }, - "2,73": { - "contents": "a" - }, - "2,74": { - "contents": "a" - }, - "2,75": { - "contents": "a" - }, - "2,76": { - "contents": "a" - }, - "2,77": { - "contents": "a" - }, - "2,78": { - "contents": "a" - }, - "2,79": { - "contents": "a" - }, - "2,8": { - "contents": "a" - }, - "2,9": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/20.typescript deleted file mode 100644 index a330c08609c9c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/20.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/21.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/21.json deleted file mode 100644 index 6463e89ac893e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/21.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/21.typescript deleted file mode 100644 index 87fc71116973c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/21.typescript +++ /dev/null @@ -1 +0,0 @@ -cab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/22.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/22.json deleted file mode 100644 index d4b36d561077a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/22.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a", - "cells": { - "23,79": { - "contents": "a" - } - }, - "cursor_position": [ - 22, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/22.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/22.typescript deleted file mode 100644 index 791ffec2aca7d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/22.typescript +++ /dev/null @@ -1 +0,0 @@ -cab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/23.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/23.json deleted file mode 100644 index c60437bc8b7ff..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/23.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": " ab a", - "cells": { - "0,79": { - "contents": "a", - "bold": true - }, - "1,0": { - "contents": "b", - "bold": true - }, - "1,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/23.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/23.typescript deleted file mode 100644 index 352df3d42d2b9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/23.typescript +++ /dev/null @@ -1 +0,0 @@ -cbaab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/24.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/24.json deleted file mode 100644 index 20b474609f1ae..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/24.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": "\n ab a", - "cells": { - "1,79": { - "contents": "a", - "bold": true - }, - "2,0": { - "contents": "b", - "bold": true - }, - "2,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/24.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/24.typescript deleted file mode 100644 index a330c08609c9c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/24.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/3.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/3.json deleted file mode 100644 index 3685a77347e83..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/3.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "13,10": { - "contents": "o" - }, - "13,11": { - "contents": "o" - }, - "13,12": { - "contents": "b" - }, - "13,13": { - "contents": "a" - }, - "13,14": { - "contents": "r" - }, - "13,9": { - "contents": "f" - } - }, - "cursor_position": [ - 9, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/3.typescript deleted file mode 100644 index ddfbd7176fc9a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/4.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/4.json deleted file mode 100644 index 78ee9452652f9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 9, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/4.typescript deleted file mode 100644 index 97955ba2c9ab1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/5.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/5.json deleted file mode 100644 index 2da2f0713ca71..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/5.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n foobar", - "cells": { - "9,10": { - "contents": "o" - }, - "9,11": { - "contents": "o" - }, - "9,12": { - "contents": "b" - }, - "9,13": { - "contents": "a" - }, - "9,14": { - "contents": "r" - }, - "9,9": { - "contents": "f" - } - }, - "cursor_position": [ - 3, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/5.typescript deleted file mode 100644 index af4efaf76463b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/5.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/6.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/6.json deleted file mode 100644 index 64775c9541655..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/6.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n foobar", - "cells": { - "8,10": { - "contents": "o" - }, - "8,11": { - "contents": "o" - }, - "8,12": { - "contents": "b" - }, - "8,13": { - "contents": "a" - }, - "8,14": { - "contents": "r" - }, - "8,9": { - "contents": "f" - } - }, - "cursor_position": [ - 3, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/6.typescript deleted file mode 100644 index 891c6db87a0bd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/7.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/7.json deleted file mode 100644 index 2cf79ba80bbb4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/7.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "\n\n\n\n\n foobar", - "cells": { - "5,10": { - "contents": "o" - }, - "5,11": { - "contents": "o" - }, - "5,12": { - "contents": "b" - }, - "5,13": { - "contents": "a" - }, - "5,14": { - "contents": "r" - }, - "5,9": { - "contents": "f" - } - }, - "cursor_position": [ - 3, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/7.typescript deleted file mode 100644 index 7d79a2421ac47..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/7.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/8.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/8.json deleted file mode 100644 index 26a8beae3dcf0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/8.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 3, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/8.typescript deleted file mode 100644 index 01b3864e9a781..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/8.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/9.json b/crates/turborepo-vt100/tests/data/fixtures/il_dl/9.json deleted file mode 100644 index 5deb58bc170fa..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/9.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/il_dl/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/il_dl/9.typescript deleted file mode 100644 index fc29e5044a0ed..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/il_dl/9.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control.in b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control.in deleted file mode 100644 index d9cf2200c3953..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control.in +++ /dev/null @@ -1,4 +0,0 @@ -\x1b -[ -\n -C diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/1.json b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/1.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/1.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/1.typescript deleted file mode 100644 index 7b71c6e679738..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/1.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/2.json b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/2.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/2.typescript deleted file mode 100644 index 8e2f0bef135ba..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/2.typescript +++ /dev/null @@ -1 +0,0 @@ -[ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/3.json b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/3.json deleted file mode 100644 index 122e9895f5aeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 1, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/4.json b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/4.json deleted file mode 100644 index ffe88f6a24463..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/4.typescript deleted file mode 100644 index 96d80cd6c4e71..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/4.typescript +++ /dev/null @@ -1 +0,0 @@ -C \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf.in b/crates/turborepo-vt100/tests/data/fixtures/lf.in deleted file mode 100644 index 3704780226c46..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf.in +++ /dev/null @@ -1,5 +0,0 @@ -foo\nbar -\x1b[H\x1b[J\x1b[4;80H -a -\n -b diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/1.json b/crates/turborepo-vt100/tests/data/fixtures/lf/1.json deleted file mode 100644 index dbf43233a8793..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "foo\n bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "1,3": { - "contents": "b" - }, - "1,4": { - "contents": "a" - }, - "1,5": { - "contents": "r" - } - }, - "cursor_position": [ - 1, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/lf/1.typescript deleted file mode 100644 index a907ec3f431ee..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/1.typescript +++ /dev/null @@ -1,2 +0,0 @@ -foo -bar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/2.json b/crates/turborepo-vt100/tests/data/fixtures/lf/2.json deleted file mode 100644 index 1c647493e9c57..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 3, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/lf/2.typescript deleted file mode 100644 index 0325a4a75982f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/3.json b/crates/turborepo-vt100/tests/data/fixtures/lf/3.json deleted file mode 100644 index 8d259dd82206a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/3.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n a", - "cells": { - "3,79": { - "contents": "a" - } - }, - "cursor_position": [ - 3, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/lf/3.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/3.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/4.json b/crates/turborepo-vt100/tests/data/fixtures/lf/4.json deleted file mode 100644 index 26ec66dfbf401..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/4.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n a", - "cells": { - "3,79": { - "contents": "a" - } - }, - "cursor_position": [ - 4, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/lf/4.typescript deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/4.typescript +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/5.json b/crates/turborepo-vt100/tests/data/fixtures/lf/5.json deleted file mode 100644 index a22356af1c167..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/5.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n a\n\nb", - "cells": { - "3,79": { - "contents": "a" - }, - "5,0": { - "contents": "b" - } - }, - "cursor_position": [ - 5, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/lf/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/lf/5.typescript deleted file mode 100644 index 63d8dbd40c235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/lf/5.typescript +++ /dev/null @@ -1 +0,0 @@ -b \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes.in b/crates/turborepo-vt100/tests/data/fixtures/modes.in deleted file mode 100644 index 2ce1889dbf571..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes.in +++ /dev/null @@ -1,20 +0,0 @@ -\x1b[?1h -\x1b[?9h -\x1b[?25l -\x1b[?1000h -\x1b[?1002h -\x1b[?1003h -\x1b[?1005h -\x1b[?1006h -\x1b[?2004h -\x1b= -\x1b[?1l -\x1b[?9l -\x1b[?25h -\x1b[?1000l -\x1b[?1002l -\x1b[?1003l -\x1b[?1005l -\x1b[?1006l -\x1b[?2004l -\x1b> diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/1.json b/crates/turborepo-vt100/tests/data/fixtures/modes/1.json deleted file mode 100644 index edade8bf8a805..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/1.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/1.typescript deleted file mode 100644 index 38296fa007aab..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/1.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/10.json b/crates/turborepo-vt100/tests/data/fixtures/modes/10.json deleted file mode 100644 index e1665320a05a9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/10.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "application_cursor": true, - "hide_cursor": true, - "bracketed_paste": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/10.typescript deleted file mode 100644 index efa8c1976b93d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/10.typescript +++ /dev/null @@ -1 +0,0 @@ -= \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/11.json b/crates/turborepo-vt100/tests/data/fixtures/modes/11.json deleted file mode 100644 index e740897906a47..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/11.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "hide_cursor": true, - "bracketed_paste": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/11.typescript deleted file mode 100644 index c0c5ea47d0856..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/11.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/12.json b/crates/turborepo-vt100/tests/data/fixtures/modes/12.json deleted file mode 100644 index e740897906a47..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/12.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "hide_cursor": true, - "bracketed_paste": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/12.typescript deleted file mode 100644 index 83777d9826f7d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/12.typescript +++ /dev/null @@ -1 +0,0 @@ -[?9l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/13.json b/crates/turborepo-vt100/tests/data/fixtures/modes/13.json deleted file mode 100644 index 9a1f6a9d8cf89..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/13.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "bracketed_paste": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/13.typescript deleted file mode 100644 index da80427df4bf3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/13.typescript +++ /dev/null @@ -1 +0,0 @@ -[?25h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/14.json b/crates/turborepo-vt100/tests/data/fixtures/modes/14.json deleted file mode 100644 index 9a1f6a9d8cf89..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/14.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "bracketed_paste": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/14.typescript deleted file mode 100644 index fe30318ebdae3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/14.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1000l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/15.json b/crates/turborepo-vt100/tests/data/fixtures/modes/15.json deleted file mode 100644 index 9a1f6a9d8cf89..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/15.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "bracketed_paste": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/15.typescript deleted file mode 100644 index 92210b2a34788..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/15.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1002l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/16.json b/crates/turborepo-vt100/tests/data/fixtures/modes/16.json deleted file mode 100644 index 4aa968374f1c6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/16.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "bracketed_paste": true, - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/16.typescript deleted file mode 100644 index 23aef53905468..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/16.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1003l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/17.json b/crates/turborepo-vt100/tests/data/fixtures/modes/17.json deleted file mode 100644 index 4aa968374f1c6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/17.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "bracketed_paste": true, - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/17.typescript deleted file mode 100644 index 2ebc028acc9e9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/17.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1005l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/18.json b/crates/turborepo-vt100/tests/data/fixtures/modes/18.json deleted file mode 100644 index 08aa1663aed52..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/18.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true, - "bracketed_paste": true -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/18.typescript deleted file mode 100644 index daef3ccf9e3e5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/18.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1006l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/19.json b/crates/turborepo-vt100/tests/data/fixtures/modes/19.json deleted file mode 100644 index 2c0890837967a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/19.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_keypad": true -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/19.typescript deleted file mode 100644 index e318b5bf7c4a6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/19.typescript +++ /dev/null @@ -1 +0,0 @@ -[?2004l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/2.json b/crates/turborepo-vt100/tests/data/fixtures/modes/2.json deleted file mode 100644 index 27d3ca6303112..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/2.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "mouse_protocol_mode": "press" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/2.typescript deleted file mode 100644 index c6036f7449c92..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/2.typescript +++ /dev/null @@ -1 +0,0 @@ -[?9h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/20.json b/crates/turborepo-vt100/tests/data/fixtures/modes/20.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/20.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/20.typescript deleted file mode 100644 index 989bcaf3eaa4d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/20.typescript +++ /dev/null @@ -1 +0,0 @@ -> \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/3.json b/crates/turborepo-vt100/tests/data/fixtures/modes/3.json deleted file mode 100644 index ad57711ac19c8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/3.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "hide_cursor": true, - "mouse_protocol_mode": "press" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/3.typescript deleted file mode 100644 index 4f9e18b145ff0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/3.typescript +++ /dev/null @@ -1 +0,0 @@ -[?25l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/4.json b/crates/turborepo-vt100/tests/data/fixtures/modes/4.json deleted file mode 100644 index 28eda162a3ffc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/4.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "hide_cursor": true, - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/4.typescript deleted file mode 100644 index 260f85e0e2faa..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/4.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1000h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/5.json b/crates/turborepo-vt100/tests/data/fixtures/modes/5.json deleted file mode 100644 index 62b8b5d0ce3de..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/5.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "hide_cursor": true, - "mouse_protocol_mode": "button_motion" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/5.typescript deleted file mode 100644 index f8d0c1c21bd09..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/5.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1002h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/6.json b/crates/turborepo-vt100/tests/data/fixtures/modes/6.json deleted file mode 100644 index 026be926fc71d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/6.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "hide_cursor": true, - "mouse_protocol_mode": "any_motion" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/6.typescript deleted file mode 100644 index a47cbfeca7d28..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/6.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1003h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/7.json b/crates/turborepo-vt100/tests/data/fixtures/modes/7.json deleted file mode 100644 index fb7e311978118..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/7.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "hide_cursor": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "utf8" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/7.typescript deleted file mode 100644 index 1a9e3a9545446..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/7.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1005h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/8.json b/crates/turborepo-vt100/tests/data/fixtures/modes/8.json deleted file mode 100644 index 66247b5edc01b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/8.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "hide_cursor": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/8.typescript deleted file mode 100644 index 494ccd93eeb46..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/8.typescript +++ /dev/null @@ -1 +0,0 @@ -[?1006h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/9.json b/crates/turborepo-vt100/tests/data/fixtures/modes/9.json deleted file mode 100644 index 7f115fa7f3291..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/9.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "application_cursor": true, - "hide_cursor": true, - "bracketed_paste": true, - "mouse_protocol_mode": "any_motion", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/modes/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/modes/9.typescript deleted file mode 100644 index 70296b59e46db..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/modes/9.typescript +++ /dev/null @@ -1 +0,0 @@ -[?2004h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/newlines.in b/crates/turborepo-vt100/tests/data/fixtures/newlines.in deleted file mode 100644 index 296dc89d909d6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/newlines.in +++ /dev/null @@ -1 +0,0 @@ -f\r\noo\r\nood diff --git a/crates/turborepo-vt100/tests/data/fixtures/newlines/1.json b/crates/turborepo-vt100/tests/data/fixtures/newlines/1.json deleted file mode 100644 index 1bec781347241..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/newlines/1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "f\noo\nood", - "cells": { - "0,0": { - "contents": "f" - }, - "1,0": { - "contents": "o" - }, - "1,1": { - "contents": "o" - }, - "2,0": { - "contents": "o" - }, - "2,1": { - "contents": "o" - }, - "2,2": { - "contents": "d" - } - }, - "cursor_position": [ - 2, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/newlines/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/newlines/1.typescript deleted file mode 100644 index 418aff08ba08e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/newlines/1.typescript +++ /dev/null @@ -1,3 +0,0 @@ -f -oo -ood \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode.in b/crates/turborepo-vt100/tests/data/fixtures/origin_mode.in deleted file mode 100644 index d0600918eae5c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode.in +++ /dev/null @@ -1,9 +0,0 @@ -\x1b[5;15r -\x1b[10;50H -\x1b[?6h -\x1b[10;50H -\x1b[?6l -\x1b[10;50H -\x1b[?6h\x1b[?47h\x1b[6;16r\x1b[H -\x1b[?6h -\x1b[?47l\x1b[H diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/1.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/1.json deleted file mode 100644 index 7093214b0f039..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/1.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/1.typescript deleted file mode 100644 index f8c7ed6d9b07c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/1.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/2.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/2.json deleted file mode 100644 index af9c69d41fea1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 9, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/2.typescript deleted file mode 100644 index 3978087441a12..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/3.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/3.json deleted file mode 100644 index 7093214b0f039..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/3.typescript deleted file mode 100644 index 723bc4b22208c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/3.typescript +++ /dev/null @@ -1 +0,0 @@ -[?6h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/4.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/4.json deleted file mode 100644 index d40cc47f19245..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 13, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/4.typescript deleted file mode 100644 index 3978087441a12..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/5.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/5.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/5.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/5.typescript deleted file mode 100644 index 619beaad2a395..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/5.typescript +++ /dev/null @@ -1 +0,0 @@ -[?6l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/6.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/6.json deleted file mode 100644 index af9c69d41fea1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/6.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 9, - 49 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/6.typescript deleted file mode 100644 index 3978087441a12..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/7.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/7.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/7.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/7.typescript deleted file mode 100644 index 96ed02b427802..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/7.typescript +++ /dev/null @@ -1 +0,0 @@ -[?6h[?47h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/8.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/8.json deleted file mode 100644 index 89d7c25413dd8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/8.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 5, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/8.typescript deleted file mode 100644 index 723bc4b22208c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/8.typescript +++ /dev/null @@ -1 +0,0 @@ -[?6h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/9.json b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/9.json deleted file mode 100644 index 7093214b0f039..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/9.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 4, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/origin_mode/9.typescript deleted file mode 100644 index a33a18a081033..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/origin_mode/9.typescript +++ /dev/null @@ -1 +0,0 @@ -[?47l \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement.in b/crates/turborepo-vt100/tests/data/fixtures/relative_movement.in deleted file mode 100644 index f8339af29feef..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement.in +++ /dev/null @@ -1,21 +0,0 @@ -\x1b[C -\x1b[C -\x1b[20C -\x1b[D -\x1b[D -\x1b[9D -\x1b[500C -\x1b[500D -\x1b[B -\x1b[B -\x1b[20B -\x1b[A -\x1b[A -\x1b[9A -\x1b[500B -\x1b[500A -\x1b[24;80H\x1b[1ma\x1b[A -\x1b[5;5H\x1b[3F -\x1b[5;5H\x1b[F -\x1b[5;5H\x1b[3E -\x1b[5;5H\x1b[E diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/1.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/1.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/1.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/1.typescript deleted file mode 100644 index bd728d21a9dff..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/1.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/10.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/10.json deleted file mode 100644 index 50a4d9c74810f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/10.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 2, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/10.typescript deleted file mode 100644 index 0513f6dcaaf10..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/10.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/11.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/11.json deleted file mode 100644 index 6045d8f866010..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/11.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 22, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/11.typescript deleted file mode 100644 index 573ad97a72d78..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/11.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/12.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/12.json deleted file mode 100644 index eba37f1c65068..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/12.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 21, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/12.typescript deleted file mode 100644 index 2b07b94ac14a1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/12.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/13.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/13.json deleted file mode 100644 index c5b3fe52ed1c6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/13.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 20, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/13.typescript deleted file mode 100644 index 2b07b94ac14a1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/13.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/14.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/14.json deleted file mode 100644 index b8a0ef1e0e733..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/14.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 11, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/14.typescript deleted file mode 100644 index 31dd3dcdbea01..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/14.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/15.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/15.json deleted file mode 100644 index 54887714185cf..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/15.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 23, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/15.typescript deleted file mode 100644 index 08a6778a51104..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/15.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/16.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/16.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/16.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/16.typescript deleted file mode 100644 index 41be63778c333..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/16.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/17.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/17.json deleted file mode 100644 index b029aab9a00fa..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/17.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a", - "cells": { - "23,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 22, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/17.typescript deleted file mode 100644 index fa1477e65a027..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/17.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/18.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/18.json deleted file mode 100644 index 8dde9824bf239..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/18.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a", - "cells": { - "23,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 1, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/18.typescript deleted file mode 100644 index 300ac2ec92c7b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/18.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/19.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/19.json deleted file mode 100644 index f151bb2316112..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/19.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a", - "cells": { - "23,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 3, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/19.typescript deleted file mode 100644 index 6dfedc0d9ea56..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/19.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/2.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/2.json deleted file mode 100644 index f168fd1b1154c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/2.typescript deleted file mode 100644 index bd728d21a9dff..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/20.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/20.json deleted file mode 100644 index 479a1bd54c89e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/20.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a", - "cells": { - "23,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 7, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/20.typescript deleted file mode 100644 index 17d2b03810359..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/20.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/21.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/21.json deleted file mode 100644 index ab71e23026cf1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/21.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a", - "cells": { - "23,79": { - "contents": "a", - "bold": true - } - }, - "cursor_position": [ - 5, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/21.typescript deleted file mode 100644 index b704ed4d29d85..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/21.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/3.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/3.json deleted file mode 100644 index 696d5c60d31a5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 22 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/3.typescript deleted file mode 100644 index a181fa03ac006..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/4.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/4.json deleted file mode 100644 index 6a3356a851239..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 21 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/4.typescript deleted file mode 100644 index 7f45cbfa27d64..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/5.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/5.json deleted file mode 100644 index e8eea9ab524bb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/5.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 20 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/5.typescript deleted file mode 100644 index 7f45cbfa27d64..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/5.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/6.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/6.json deleted file mode 100644 index 944a2e30deaf3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/6.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/6.typescript deleted file mode 100644 index 4a51220307997..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/7.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/7.json deleted file mode 100644 index 5deb58bc170fa..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/7.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/7.typescript deleted file mode 100644 index 3e339b31c7433..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/7.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/8.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/8.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/8.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/8.typescript deleted file mode 100644 index 132f32193dc02..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/8.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/9.json b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/9.json deleted file mode 100644 index 122e9895f5aeb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/9.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 1, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/relative_movement/9.typescript deleted file mode 100644 index 0513f6dcaaf10..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/relative_movement/9.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri.in b/crates/turborepo-vt100/tests/data/fixtures/ri.in deleted file mode 100644 index 9e8d246c3cde6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri.in +++ /dev/null @@ -1,6 +0,0 @@ -foo\nbar\x1bMbaz -\x1bc1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24 -\x1b[H\x1bM -\x1bc -\x1b[1;80Ha\x7f\x1b[3Hb\x1b[H -\x1bM diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/1.json b/crates/turborepo-vt100/tests/data/fixtures/ri/1.json deleted file mode 100644 index b3e2889099ae6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/1.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "foo baz\n bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "0,6": { - "contents": "b" - }, - "0,7": { - "contents": "a" - }, - "0,8": { - "contents": "z" - }, - "1,3": { - "contents": "b" - }, - "1,4": { - "contents": "a" - }, - "1,5": { - "contents": "r" - } - }, - "cursor_position": [ - 0, - 9 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/ri/1.typescript deleted file mode 100644 index 96c111b20e365..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/1.typescript +++ /dev/null @@ -1,2 +0,0 @@ -foo -barMbaz \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/2.json b/crates/turborepo-vt100/tests/data/fixtures/ri/2.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/2.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/ri/2.typescript deleted file mode 100644 index 038a225d58d5f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/2.typescript +++ /dev/null @@ -1,24 +0,0 @@ -c1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/3.json b/crates/turborepo-vt100/tests/data/fixtures/ri/3.json deleted file mode 100644 index 481d6b17247bc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/3.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "contents": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23", - "cells": { - "1,0": { - "contents": "1" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "0" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "1" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "2" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "3" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "4" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "5" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "6" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "7" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "8" - }, - "19,0": { - "contents": "1" - }, - "19,1": { - "contents": "9" - }, - "2,0": { - "contents": "2" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "0" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "1" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "2" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "3" - }, - "3,0": { - "contents": "3" - }, - "4,0": { - "contents": "4" - }, - "5,0": { - "contents": "5" - }, - "6,0": { - "contents": "6" - }, - "7,0": { - "contents": "7" - }, - "8,0": { - "contents": "8" - }, - "9,0": { - "contents": "9" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/ri/3.typescript deleted file mode 100644 index 9efb3d5ff3c23..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/3.typescript +++ /dev/null @@ -1 +0,0 @@ -M \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/4.json b/crates/turborepo-vt100/tests/data/fixtures/ri/4.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/ri/4.typescript deleted file mode 100644 index c10be5482cd97..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/4.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/5.json b/crates/turborepo-vt100/tests/data/fixtures/ri/5.json deleted file mode 100644 index c4852e269b22d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/5.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": " a\n\nb", - "cells": { - "0,79": { - "contents": "a" - }, - "2,0": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/ri/5.typescript deleted file mode 100644 index 69d759dac9e25..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/5.typescript +++ /dev/null @@ -1 +0,0 @@ -ab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/6.json b/crates/turborepo-vt100/tests/data/fixtures/ri/6.json deleted file mode 100644 index 7bf46dbac54a4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/6.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n a\n\nb", - "cells": { - "1,79": { - "contents": "a" - }, - "3,0": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ri/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/ri/6.typescript deleted file mode 100644 index f963eedc18b18..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ri/6.typescript +++ /dev/null @@ -1 +0,0 @@ -M \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ris.in b/crates/turborepo-vt100/tests/data/fixtures/ris.in deleted file mode 100644 index d3271ea67e850..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ris.in +++ /dev/null @@ -1,2 +0,0 @@ -f\x1b[31m\x1b[47;1;3;4moo\x1b[7m\x1b[21;21H\x1b]2;window title\x07\x1b]1;window icon name\x07\x1b[?25l\x1b[?1h\x1b=\x1b[?9h\x1b[?1000h\x1b[?1006h\x1b[?2004h\x07\x1bg -\x1bc diff --git a/crates/turborepo-vt100/tests/data/fixtures/ris/1.json b/crates/turborepo-vt100/tests/data/fixtures/ris/1.json deleted file mode 100644 index 58b62c3cd160a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ris/1.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "foo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o", - "fgcolor": "1", - "bgcolor": "7", - "bold": true, - "italic": true, - "underline": true - }, - "0,2": { - "contents": "o", - "fgcolor": "1", - "bgcolor": "7", - "bold": true, - "italic": true, - "underline": true - } - }, - "cursor_position": [ - 20, - 20 - ], - "title": "window title", - "icon_name": "window icon name", - "application_keypad": true, - "application_cursor": true, - "hide_cursor": true, - "bracketed_paste": true, - "mouse_protocol_mode": "press_release", - "mouse_protocol_encoding": "sgr" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ris/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/ris/1.typescript deleted file mode 100644 index 80e8afc4c7935..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ris/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foo]2;window title]1;window icon name[?25l[?1h=[?9h[?1000h[?1006h[?2004hg \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ris/2.json b/crates/turborepo-vt100/tests/data/fixtures/ris/2.json deleted file mode 100644 index ac3f4c2707cee..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ris/2.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "title": "window title", - "icon_name": "window icon name" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/ris/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/ris/2.typescript deleted file mode 100644 index c10be5482cd97..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/ris/2.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll.in b/crates/turborepo-vt100/tests/data/fixtures/scroll.in deleted file mode 100644 index e523f227d33ee..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll.in +++ /dev/null @@ -1,6 +0,0 @@ -1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24 -\x1b[15;15H -\x1b[S -\x1b[3S -\x1b[T -\x1b[5T diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/1.json b/crates/turborepo-vt100/tests/data/fixtures/scroll/1.json deleted file mode 100644 index 178cb1dbe6fdb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/1.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 23, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/scroll/1.typescript deleted file mode 100644 index cd1b80ed3ec25..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/1.typescript +++ /dev/null @@ -1,24 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/2.json b/crates/turborepo-vt100/tests/data/fixtures/scroll/2.json deleted file mode 100644 index d812b41d0eebf..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/2.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "contents": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "1" - }, - "1,0": { - "contents": "2" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "1" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "2" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "3" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "4" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "5" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "6" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "7" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "8" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "9" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "0" - }, - "2,0": { - "contents": "3" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "1" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "2" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "3" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "4" - }, - "3,0": { - "contents": "4" - }, - "4,0": { - "contents": "5" - }, - "5,0": { - "contents": "6" - }, - "6,0": { - "contents": "7" - }, - "7,0": { - "contents": "8" - }, - "8,0": { - "contents": "9" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "0" - } - }, - "cursor_position": [ - 14, - 14 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/scroll/2.typescript deleted file mode 100644 index d5376ac4772c7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/3.json b/crates/turborepo-vt100/tests/data/fixtures/scroll/3.json deleted file mode 100644 index 17b643d46b3de..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/3.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "contents": "2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "2" - }, - "1,0": { - "contents": "3" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "2" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "3" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "4" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "5" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "6" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "7" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "8" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "9" - }, - "18,0": { - "contents": "2" - }, - "18,1": { - "contents": "0" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "1" - }, - "2,0": { - "contents": "4" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "2" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "3" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "4" - }, - "3,0": { - "contents": "5" - }, - "4,0": { - "contents": "6" - }, - "5,0": { - "contents": "7" - }, - "6,0": { - "contents": "8" - }, - "7,0": { - "contents": "9" - }, - "8,0": { - "contents": "1" - }, - "8,1": { - "contents": "0" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "1" - } - }, - "cursor_position": [ - 14, - 14 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/scroll/3.typescript deleted file mode 100644 index 799613f37ea7f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/4.json b/crates/turborepo-vt100/tests/data/fixtures/scroll/4.json deleted file mode 100644 index 3b53fa41633db..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/4.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "contents": "5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "0,0": { - "contents": "5" - }, - "1,0": { - "contents": "6" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "5" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "6" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "7" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "8" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "9" - }, - "15,0": { - "contents": "2" - }, - "15,1": { - "contents": "0" - }, - "16,0": { - "contents": "2" - }, - "16,1": { - "contents": "1" - }, - "17,0": { - "contents": "2" - }, - "17,1": { - "contents": "2" - }, - "18,0": { - "contents": "2" - }, - "18,1": { - "contents": "3" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "4" - }, - "2,0": { - "contents": "7" - }, - "3,0": { - "contents": "8" - }, - "4,0": { - "contents": "9" - }, - "5,0": { - "contents": "1" - }, - "5,1": { - "contents": "0" - }, - "6,0": { - "contents": "1" - }, - "6,1": { - "contents": "1" - }, - "7,0": { - "contents": "1" - }, - "7,1": { - "contents": "2" - }, - "8,0": { - "contents": "1" - }, - "8,1": { - "contents": "3" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "4" - } - }, - "cursor_position": [ - 14, - 14 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/scroll/4.typescript deleted file mode 100644 index 95a8fcc0b1430..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/5.json b/crates/turborepo-vt100/tests/data/fixtures/scroll/5.json deleted file mode 100644 index 1132aba4ccf69..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/5.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "contents": "\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24", - "cells": { - "1,0": { - "contents": "5" - }, - "10,0": { - "contents": "1" - }, - "10,1": { - "contents": "4" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "5" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "6" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "7" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "8" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "9" - }, - "16,0": { - "contents": "2" - }, - "16,1": { - "contents": "0" - }, - "17,0": { - "contents": "2" - }, - "17,1": { - "contents": "1" - }, - "18,0": { - "contents": "2" - }, - "18,1": { - "contents": "2" - }, - "19,0": { - "contents": "2" - }, - "19,1": { - "contents": "3" - }, - "2,0": { - "contents": "6" - }, - "20,0": { - "contents": "2" - }, - "20,1": { - "contents": "4" - }, - "3,0": { - "contents": "7" - }, - "4,0": { - "contents": "8" - }, - "5,0": { - "contents": "9" - }, - "6,0": { - "contents": "1" - }, - "6,1": { - "contents": "0" - }, - "7,0": { - "contents": "1" - }, - "7,1": { - "contents": "1" - }, - "8,0": { - "contents": "1" - }, - "8,1": { - "contents": "2" - }, - "9,0": { - "contents": "1" - }, - "9,1": { - "contents": "3" - } - }, - "cursor_position": [ - 14, - 14 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/scroll/5.typescript deleted file mode 100644 index fec28d1123d29..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/5.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/6.json b/crates/turborepo-vt100/tests/data/fixtures/scroll/6.json deleted file mode 100644 index 53fa0dedcac61..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/6.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22", - "cells": { - "10,0": { - "contents": "9" - }, - "11,0": { - "contents": "1" - }, - "11,1": { - "contents": "0" - }, - "12,0": { - "contents": "1" - }, - "12,1": { - "contents": "1" - }, - "13,0": { - "contents": "1" - }, - "13,1": { - "contents": "2" - }, - "14,0": { - "contents": "1" - }, - "14,1": { - "contents": "3" - }, - "15,0": { - "contents": "1" - }, - "15,1": { - "contents": "4" - }, - "16,0": { - "contents": "1" - }, - "16,1": { - "contents": "5" - }, - "17,0": { - "contents": "1" - }, - "17,1": { - "contents": "6" - }, - "18,0": { - "contents": "1" - }, - "18,1": { - "contents": "7" - }, - "19,0": { - "contents": "1" - }, - "19,1": { - "contents": "8" - }, - "20,0": { - "contents": "1" - }, - "20,1": { - "contents": "9" - }, - "21,0": { - "contents": "2" - }, - "21,1": { - "contents": "0" - }, - "22,0": { - "contents": "2" - }, - "22,1": { - "contents": "1" - }, - "23,0": { - "contents": "2" - }, - "23,1": { - "contents": "2" - }, - "6,0": { - "contents": "5" - }, - "7,0": { - "contents": "6" - }, - "8,0": { - "contents": "7" - }, - "9,0": { - "contents": "8" - } - }, - "cursor_position": [ - 14, - 14 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/scroll/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/scroll/6.typescript deleted file mode 100644 index 33b486f7f1e2f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/scroll/6.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences.in b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences.in deleted file mode 100644 index 763c79b6aae00..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences.in +++ /dev/null @@ -1,29 +0,0 @@ -abc -abc\x1b[12;24Hdef -\x1b -[ -1 -2 -; -2 -4 -H -\x1b -[ -? -1 -0 -0 -0 -h -\x1b -] -0 -; -a - -' -[ -] -_ -\x07 diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/1.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/1.json deleted file mode 100644 index 29b8f75c1d283..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "abc", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/1.typescript deleted file mode 100644 index f2ba8f84ab5c1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/1.typescript +++ /dev/null @@ -1 +0,0 @@ -abc \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/10.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/10.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/10.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/10.typescript deleted file mode 100644 index 8ac2eb5089569..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/10.typescript +++ /dev/null @@ -1 +0,0 @@ -H \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/11.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/11.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/11.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/11.typescript deleted file mode 100644 index 7b71c6e679738..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/11.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/12.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/12.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/12.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/12.typescript deleted file mode 100644 index 8e2f0bef135ba..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/12.typescript +++ /dev/null @@ -1 +0,0 @@ -[ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/13.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/13.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/13.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/13.typescript deleted file mode 100644 index 0d758c9c7bc06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/13.typescript +++ /dev/null @@ -1 +0,0 @@ -? \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/14.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/14.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/14.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/14.typescript deleted file mode 100644 index 56a6051ca2b02..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/14.typescript +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/15.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/15.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/15.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/15.typescript deleted file mode 100644 index c227083464fb9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/15.typescript +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/16.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/16.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/16.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/16.typescript deleted file mode 100644 index c227083464fb9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/16.typescript +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/17.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/17.json deleted file mode 100644 index e6c0b373213d0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/17.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/17.typescript deleted file mode 100644 index c227083464fb9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/17.typescript +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/18.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/18.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/18.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/18.typescript deleted file mode 100644 index be54354a9433a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/18.typescript +++ /dev/null @@ -1 +0,0 @@ -h \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/19.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/19.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/19.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/19.typescript deleted file mode 100644 index 7b71c6e679738..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/19.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/2.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/2.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/2.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/2.typescript deleted file mode 100644 index cb5b3889410b2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/2.typescript +++ /dev/null @@ -1 +0,0 @@ -abcdef \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/20.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/20.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/20.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/20.typescript deleted file mode 100644 index 54caf60b13678..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/20.typescript +++ /dev/null @@ -1 +0,0 @@ -] \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/21.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/21.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/21.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/21.typescript deleted file mode 100644 index c227083464fb9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/21.typescript +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/22.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/22.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/22.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/22.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/22.typescript deleted file mode 100644 index 1c8a0e7976207..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/22.typescript +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/23.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/23.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/23.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/23.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/23.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/23.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/24.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/24.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/24.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/24.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/24.typescript deleted file mode 100644 index 0519ecba6ea91..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/24.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/25.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/25.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/25.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/25.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/25.typescript deleted file mode 100644 index ad2823b48f78a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/25.typescript +++ /dev/null @@ -1 +0,0 @@ -' \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/26.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/26.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/26.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/26.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/26.typescript deleted file mode 100644 index 8e2f0bef135ba..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/26.typescript +++ /dev/null @@ -1 +0,0 @@ -[ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/27.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/27.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/27.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/27.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/27.typescript deleted file mode 100644 index 54caf60b13678..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/27.typescript +++ /dev/null @@ -1 +0,0 @@ -] \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/28.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/28.json deleted file mode 100644 index ad7cef9440b95..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/28.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/28.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/28.typescript deleted file mode 100644 index c9cdc63b07017..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/28.typescript +++ /dev/null @@ -1 +0,0 @@ -_ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/29.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/29.json deleted file mode 100644 index bb4aecc93f337..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/29.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 23 - ], - "title": "a '[]_", - "icon_name": "a '[]_", - "mouse_protocol_mode": "press_release" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/29.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/29.typescript deleted file mode 100644 index 303e398c82e88..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/29.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/3.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/3.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/3.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/3.typescript deleted file mode 100644 index 7b71c6e679738..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/3.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/4.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/4.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/4.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/4.typescript deleted file mode 100644 index 8e2f0bef135ba..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/4.typescript +++ /dev/null @@ -1 +0,0 @@ -[ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/5.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/5.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/5.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/5.typescript deleted file mode 100644 index 56a6051ca2b02..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/5.typescript +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/6.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/6.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/6.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/6.typescript deleted file mode 100644 index d8263ee986059..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/6.typescript +++ /dev/null @@ -1 +0,0 @@ -2 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/7.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/7.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/7.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/7.typescript deleted file mode 100644 index 1c8a0e7976207..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/7.typescript +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/8.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/8.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/8.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/8.typescript deleted file mode 100644 index d8263ee986059..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/8.typescript +++ /dev/null @@ -1 +0,0 @@ -2 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/9.json b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/9.json deleted file mode 100644 index e02fe90460e06..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/9.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "contents": "abcabc\n\n\n\n\n\n\n\n\n\n\n def", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "b" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "a" - }, - "0,4": { - "contents": "b" - }, - "0,5": { - "contents": "c" - }, - "11,23": { - "contents": "d" - }, - "11,24": { - "contents": "e" - }, - "11,25": { - "contents": "f" - } - }, - "cursor_position": [ - 11, - 26 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/9.typescript deleted file mode 100644 index bf0d87ab1b2b0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_escape_sequences/9.typescript +++ /dev/null @@ -1 +0,0 @@ -4 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8.in b/crates/turborepo-vt100/tests/data/fixtures/split_utf8.in deleted file mode 100644 index 460b4e833598b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8.in +++ /dev/null @@ -1,10 +0,0 @@ -a -\xc3 -\xa1 -\xe3 -\x82 -\xad -\xf0 -\x9f -\x92 -\xa9 diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/1.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/1.json deleted file mode 100644 index 14dbc432d92ca..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/1.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "a", - "cells": { - "0,0": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/1.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/1.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/10.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/10.json deleted file mode 100644 index 8e581cc5293b9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/10.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "contents": "aáキ💩", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - }, - "0,2": { - "contents": "ã‚­", - "is_wide": true - }, - "0,3": { - "contents": "", - "is_wide_continuation": true - }, - "0,4": { - "contents": "💩", - "is_wide": true - }, - "0,5": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/10.typescript deleted file mode 100644 index 8b43ca9ac41e8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/10.typescript +++ /dev/null @@ -1 +0,0 @@ -© \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/2.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/2.json deleted file mode 100644 index 14dbc432d92ca..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/2.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "a", - "cells": { - "0,0": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/2.typescript deleted file mode 100644 index 6b10f9584314d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/2.typescript +++ /dev/null @@ -1 +0,0 @@ -à \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/3.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/3.json deleted file mode 100644 index 8210079ba7601..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/3.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "aá", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/3.typescript deleted file mode 100644 index 57814dd0025fc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/3.typescript +++ /dev/null @@ -1 +0,0 @@ -¡ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/4.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/4.json deleted file mode 100644 index 8210079ba7601..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/4.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "aá", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/4.typescript deleted file mode 100644 index 2105af1f86eb4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/4.typescript +++ /dev/null @@ -1 +0,0 @@ -ã \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/5.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/5.json deleted file mode 100644 index 8210079ba7601..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/5.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "aá", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/5.typescript deleted file mode 100644 index 013d565bb4055..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/5.typescript +++ /dev/null @@ -1 +0,0 @@ -‚ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/6.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/6.json deleted file mode 100644 index 202f75b2bc76e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/6.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "contents": "aáキ", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - }, - "0,2": { - "contents": "ã‚­", - "is_wide": true - }, - "0,3": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/6.typescript deleted file mode 100644 index bd0fd35942234..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/6.typescript +++ /dev/null @@ -1 +0,0 @@ -­ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/7.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/7.json deleted file mode 100644 index 202f75b2bc76e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/7.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "contents": "aáキ", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - }, - "0,2": { - "contents": "ã‚­", - "is_wide": true - }, - "0,3": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/7.typescript deleted file mode 100644 index 04f7b5be6987d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/7.typescript +++ /dev/null @@ -1 +0,0 @@ -ð \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/8.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/8.json deleted file mode 100644 index 202f75b2bc76e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/8.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "contents": "aáキ", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - }, - "0,2": { - "contents": "ã‚­", - "is_wide": true - }, - "0,3": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/8.typescript deleted file mode 100644 index b1d81e79354c9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/8.typescript +++ /dev/null @@ -1 +0,0 @@ -Ÿ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/9.json b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/9.json deleted file mode 100644 index 202f75b2bc76e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/9.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "contents": "aáキ", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "á" - }, - "0,2": { - "contents": "ã‚­", - "is_wide": true - }, - "0,3": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/split_utf8/9.typescript deleted file mode 100644 index 3818ded670e4f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/split_utf8/9.typescript +++ /dev/null @@ -1 +0,0 @@ -’ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/tab.in b/crates/turborepo-vt100/tests/data/fixtures/tab.in deleted file mode 100644 index 376243b9e93fc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/tab.in +++ /dev/null @@ -1 +0,0 @@ -foo\tbar diff --git a/crates/turborepo-vt100/tests/data/fixtures/tab/1.json b/crates/turborepo-vt100/tests/data/fixtures/tab/1.json deleted file mode 100644 index 39430f65f67dd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/tab/1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "foo bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,10": { - "contents": "r" - }, - "0,2": { - "contents": "o" - }, - "0,8": { - "contents": "b" - }, - "0,9": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/tab/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/tab/1.typescript deleted file mode 100644 index 3710c4cb90b68..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/tab/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foo bar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title.in b/crates/turborepo-vt100/tests/data/fixtures/title.in deleted file mode 100644 index 1b23928e29a46..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title.in +++ /dev/null @@ -1,2 +0,0 @@ -\x1b]2;it's a title\x07 -\x1b]2;\x07 diff --git a/crates/turborepo-vt100/tests/data/fixtures/title/1.json b/crates/turborepo-vt100/tests/data/fixtures/title/1.json deleted file mode 100644 index eb4e511d98f3c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title/1.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "title": "it's a title" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/title/1.typescript deleted file mode 100644 index 51863055074b7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title/1.typescript +++ /dev/null @@ -1 +0,0 @@ -]2;it's a title \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title/2.json b/crates/turborepo-vt100/tests/data/fixtures/title/2.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/title/2.typescript deleted file mode 100644 index 65ecee2a9c5df..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title/2.typescript +++ /dev/null @@ -1 +0,0 @@ -]2; \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name.in b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name.in deleted file mode 100644 index e9a3a705bc845..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name.in +++ /dev/null @@ -1,5 +0,0 @@ -\x1b]0;it's both\x07 -\x1b]0;\x07 -\x1b]2;it's a title\x07\x1b]1;it's an icon name\x07 -\x1b]1;it's a title\x07 -\x1b]1;it's an icon name\x07 diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/1.json b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/1.json deleted file mode 100644 index 10af5006ef8ad..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/1.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "title": "it's both", - "icon_name": "it's both" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/1.typescript deleted file mode 100644 index b6a1e12619b23..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/1.typescript +++ /dev/null @@ -1 +0,0 @@ -]0;it's both \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/2.json b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/2.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/2.typescript deleted file mode 100644 index a2228420222cd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/2.typescript +++ /dev/null @@ -1 +0,0 @@ -]0; \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/3.json b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/3.json deleted file mode 100644 index 51d47fe79af9e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/3.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "title": "it's a title", - "icon_name": "it's an icon name" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/3.typescript deleted file mode 100644 index 54cd2f6455993..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/3.typescript +++ /dev/null @@ -1 +0,0 @@ -]2;it's a title]1;it's an icon name \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/4.json b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/4.json deleted file mode 100644 index b1eef59807662..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/4.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "title": "it's a title", - "icon_name": "it's a title" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/4.typescript deleted file mode 100644 index 7d093629c20b1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/4.typescript +++ /dev/null @@ -1 +0,0 @@ -]1;it's a title \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/5.json b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/5.json deleted file mode 100644 index 51d47fe79af9e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/5.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ], - "title": "it's a title", - "icon_name": "it's an icon name" -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/5.typescript deleted file mode 100644 index e1764774e7100..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/title_icon_name/5.typescript +++ /dev/null @@ -1 +0,0 @@ -]1;it's an icon name \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/unknown_osc.in b/crates/turborepo-vt100/tests/data/fixtures/unknown_osc.in deleted file mode 100644 index 37fae10b263ad..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/unknown_osc.in +++ /dev/null @@ -1 +0,0 @@ -\x1b]499;some long, long string?\x07 diff --git a/crates/turborepo-vt100/tests/data/fixtures/unknown_osc/1.json b/crates/turborepo-vt100/tests/data/fixtures/unknown_osc/1.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/unknown_osc/1.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/unknown_osc/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/unknown_osc/1.typescript deleted file mode 100644 index b6dae428af254..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/unknown_osc/1.typescript +++ /dev/null @@ -1 +0,0 @@ -]499;some long, long string? \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/utf8.in b/crates/turborepo-vt100/tests/data/fixtures/utf8.in deleted file mode 100644 index c7efa1e5bc54d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/utf8.in +++ /dev/null @@ -1,2 +0,0 @@ -café -\x1bc\xf0\x9d\x87\x80\xe1\x9c\x92 diff --git a/crates/turborepo-vt100/tests/data/fixtures/utf8/1.json b/crates/turborepo-vt100/tests/data/fixtures/utf8/1.json deleted file mode 100644 index cb54f32b115d5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/utf8/1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": "café", - "cells": { - "0,0": { - "contents": "c" - }, - "0,1": { - "contents": "a" - }, - "0,2": { - "contents": "f" - }, - "0,3": { - "contents": "é" - } - }, - "cursor_position": [ - 0, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/utf8/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/utf8/1.typescript deleted file mode 100644 index 1c2e52cfe7542..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/utf8/1.typescript +++ /dev/null @@ -1 +0,0 @@ -café \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/utf8/2.json b/crates/turborepo-vt100/tests/data/fixtures/utf8/2.json deleted file mode 100644 index faaa8242f484b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/utf8/2.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "ð‡€áœ’", - "cells": { - "0,0": { - "contents": "ð‡€áœ’" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/utf8/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/utf8/2.typescript deleted file mode 100644 index 14d4c1ffc688e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/utf8/2.typescript +++ /dev/null @@ -1 +0,0 @@ -cð‡€áœ’ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt.in b/crates/turborepo-vt100/tests/data/fixtures/vt.in deleted file mode 100644 index 37787fed8eb3c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt.in +++ /dev/null @@ -1,5 +0,0 @@ -foo\x0bbar -\x1b[H\x1b[J\x1b[4;80H -a -\x0b -b diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/1.json b/crates/turborepo-vt100/tests/data/fixtures/vt/1.json deleted file mode 100644 index dbf43233a8793..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "contents": "foo\n bar", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "1,3": { - "contents": "b" - }, - "1,4": { - "contents": "a" - }, - "1,5": { - "contents": "r" - } - }, - "cursor_position": [ - 1, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/vt/1.typescript deleted file mode 100644 index f7caf2d56febe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/1.typescript +++ /dev/null @@ -1 +0,0 @@ -foo bar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/2.json b/crates/turborepo-vt100/tests/data/fixtures/vt/2.json deleted file mode 100644 index 1c647493e9c57..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 3, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/vt/2.typescript deleted file mode 100644 index 0325a4a75982f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/3.json b/crates/turborepo-vt100/tests/data/fixtures/vt/3.json deleted file mode 100644 index 8d259dd82206a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/3.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n a", - "cells": { - "3,79": { - "contents": "a" - } - }, - "cursor_position": [ - 3, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/vt/3.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/3.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/4.json b/crates/turborepo-vt100/tests/data/fixtures/vt/4.json deleted file mode 100644 index 26ec66dfbf401..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/4.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\n\n a", - "cells": { - "3,79": { - "contents": "a" - } - }, - "cursor_position": [ - 4, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/vt/4.typescript deleted file mode 100644 index 2725bca0006db..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/5.json b/crates/turborepo-vt100/tests/data/fixtures/vt/5.json deleted file mode 100644 index a22356af1c167..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/5.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n a\n\nb", - "cells": { - "3,79": { - "contents": "a" - }, - "5,0": { - "contents": "b" - } - }, - "cursor_position": [ - 5, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/vt/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/vt/5.typescript deleted file mode 100644 index 63d8dbd40c235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/vt/5.typescript +++ /dev/null @@ -1 +0,0 @@ -b \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide.in b/crates/turborepo-vt100/tests/data/fixtures/wide.in deleted file mode 100644 index 25e405fbfb155..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide.in +++ /dev/null @@ -1,25 +0,0 @@ -aデbム-\x1b[1;1H\x1b[3Cc -\x1b[1;7Hfoobar -\x1b[1;1Hデcãƒfoobar\x1b[K -\x1b[1;1Haデcãƒfoobar\x1b[K -\x1b[1;1Hデcãƒfoobar\x1b[K -\x1bcデ\x08a -\x1bcデ\x08ム-\x1bcデ\x08\x1b[@ -\x1bcデ\x08\x1b[J -\x1bcaデ\x08\x08\x1b[1J -\x1bcデ\x08\x1b[K -\x1bcaデ\x08\x08\x1b[1K -\x1bcデ\x08\x1b[P -\x1bcデ\x08\x08\x1b[P -\x1bcaデ\x08\x08\x08\x1b[2P -\x1bcデãƒ\x08\x08\x08\x1b[P -\x1bcデãƒ\x08\x08\x08\x1b[2P -\x1bcデãƒa\x08\x08\x08\x08\x1b[P -\x1bcデãƒa\x08\x08\x08\x08\x1b[2P -\x1bcデ\x08\x1b[X -\x1bcデ\x08\x08\x1b[X -\x1bcaデ\rb\u{301} -\x1bc\x1b[1;79Hデ\x08ム-\x1bc\x1b[1;79Hデ\r\x1b[@ diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/1.json b/crates/turborepo-vt100/tests/data/fixtures/wide/1.json deleted file mode 100644 index d192911c7ae52..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/1.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "contents": "aデbãƒ", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "デ", - "is_wide": true - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - }, - "0,3": { - "contents": "b" - }, - "0,4": { - "contents": "ãƒ", - "is_wide": true - }, - "0,5": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 6 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/1.typescript deleted file mode 100644 index 33de4d4def39f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/1.typescript +++ /dev/null @@ -1 +0,0 @@ -aデbム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/10.json b/crates/turborepo-vt100/tests/data/fixtures/wide/10.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/10.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/10.typescript deleted file mode 100644 index d910cf6d3b82c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/10.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/11.json b/crates/turborepo-vt100/tests/data/fixtures/wide/11.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/11.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/11.typescript deleted file mode 100644 index 72241fda67e6b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/11.typescript +++ /dev/null @@ -1 +0,0 @@ -caデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/12.json b/crates/turborepo-vt100/tests/data/fixtures/wide/12.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/12.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/12.typescript deleted file mode 100644 index abc42a141dd44..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/12.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/13.json b/crates/turborepo-vt100/tests/data/fixtures/wide/13.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/13.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/13.typescript deleted file mode 100644 index 668eb2bda8ee6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/13.typescript +++ /dev/null @@ -1 +0,0 @@ -caデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/14.json b/crates/turborepo-vt100/tests/data/fixtures/wide/14.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/14.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/14.typescript deleted file mode 100644 index d284b2aea67e2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/14.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/15.json b/crates/turborepo-vt100/tests/data/fixtures/wide/15.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/15.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/15.typescript deleted file mode 100644 index 4af43c46746c9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/15.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/16.json b/crates/turborepo-vt100/tests/data/fixtures/wide/16.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/16.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/16.typescript deleted file mode 100644 index 294133646babb..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/16.typescript +++ /dev/null @@ -1 +0,0 @@ -caデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/17.json b/crates/turborepo-vt100/tests/data/fixtures/wide/17.json deleted file mode 100644 index 2a19c52def455..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/17.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "contents": " ãƒ", - "cells": { - "0,1": { - "contents": "ãƒ", - "is_wide": true - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/17.typescript deleted file mode 100644 index e432869f32530..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/17.typescript +++ /dev/null @@ -1 +0,0 @@ -cデム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/18.json b/crates/turborepo-vt100/tests/data/fixtures/wide/18.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/18.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/18.typescript deleted file mode 100644 index 678b116e1aac6..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/18.typescript +++ /dev/null @@ -1 +0,0 @@ -cデム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/19.json b/crates/turborepo-vt100/tests/data/fixtures/wide/19.json deleted file mode 100644 index 9edad5ba22a87..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/19.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contents": " ãƒa", - "cells": { - "0,1": { - "contents": "ãƒ", - "is_wide": true - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - }, - "0,3": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/19.typescript deleted file mode 100644 index bbb4b0d0f6739..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/19.typescript +++ /dev/null @@ -1 +0,0 @@ -cデãƒa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/2.json b/crates/turborepo-vt100/tests/data/fixtures/wide/2.json deleted file mode 100644 index a5ddff8c45d9c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/2.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "contents": "aデcãƒ", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "デ", - "is_wide": true - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - }, - "0,3": { - "contents": "c" - }, - "0,4": { - "contents": "ãƒ", - "is_wide": true - }, - "0,5": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 4 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/2.typescript deleted file mode 100644 index 9161ad9ee731d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/2.typescript +++ /dev/null @@ -1 +0,0 @@ -c \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/20.json b/crates/turborepo-vt100/tests/data/fixtures/wide/20.json deleted file mode 100644 index 93f8bbfedd479..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/20.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,2": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/20.typescript deleted file mode 100644 index 78cb7107a75da..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/20.typescript +++ /dev/null @@ -1 +0,0 @@ -cデãƒa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/21.json b/crates/turborepo-vt100/tests/data/fixtures/wide/21.json deleted file mode 100644 index f7dae311468e3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/21.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/21.typescript deleted file mode 100644 index c90dc0684a6ce..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/21.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/22.json b/crates/turborepo-vt100/tests/data/fixtures/wide/22.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/22.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/22.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/22.typescript deleted file mode 100644 index f21c15af8a34e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/22.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/23.json b/crates/turborepo-vt100/tests/data/fixtures/wide/23.json deleted file mode 100644 index 0c96e163b50f9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/23.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contents": "bÌデ", - "cells": { - "0,0": { - "contents": "bÌ" - }, - "0,1": { - "contents": "デ", - "is_wide": true - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/23.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/23.typescript deleted file mode 100644 index 89d66bea712bd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/23.typescript +++ /dev/null @@ -1 +0,0 @@ -caデ bÌ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/24.json b/crates/turborepo-vt100/tests/data/fixtures/wide/24.json deleted file mode 100644 index 23a61c7b77806..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/24.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "contents": " デãƒ", - "cells": { - "0,78": { - "contents": "デ", - "is_wide": true - }, - "0,79": { - "contents": "", - "is_wide_continuation": true - }, - "1,0": { - "contents": "ãƒ", - "is_wide": true - }, - "1,1": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 1, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/24.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/24.typescript deleted file mode 100644 index 29bb251ac5aff..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/24.typescript +++ /dev/null @@ -1 +0,0 @@ -cデム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/25.json b/crates/turborepo-vt100/tests/data/fixtures/wide/25.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/25.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/25.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/25.typescript deleted file mode 100644 index 0dd7e040e705b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/25.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ [@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/3.json b/crates/turborepo-vt100/tests/data/fixtures/wide/3.json deleted file mode 100644 index 05d41ca29a66f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/3.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "contents": "aデcãƒfoobar", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "デ", - "is_wide": true - }, - "0,10": { - "contents": "a" - }, - "0,11": { - "contents": "r" - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - }, - "0,3": { - "contents": "c" - }, - "0,4": { - "contents": "ãƒ", - "is_wide": true - }, - "0,5": { - "contents": "", - "is_wide_continuation": true - }, - "0,6": { - "contents": "f" - }, - "0,7": { - "contents": "o" - }, - "0,8": { - "contents": "o" - }, - "0,9": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/3.typescript deleted file mode 100644 index 333196bb177ad..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/3.typescript +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/4.json b/crates/turborepo-vt100/tests/data/fixtures/wide/4.json deleted file mode 100644 index e682e98fb3115..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/4.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "contents": "デcãƒfoobar", - "cells": { - "0,0": { - "contents": "デ", - "is_wide": true - }, - "0,1": { - "contents": "", - "is_wide_continuation": true - }, - "0,10": { - "contents": "r" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "ãƒ", - "is_wide": true - }, - "0,4": { - "contents": "", - "is_wide_continuation": true - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "o" - }, - "0,7": { - "contents": "o" - }, - "0,8": { - "contents": "b" - }, - "0,9": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/4.typescript deleted file mode 100644 index 449cb6b2afae3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/4.typescript +++ /dev/null @@ -1 +0,0 @@ -デcãƒfoobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/5.json b/crates/turborepo-vt100/tests/data/fixtures/wide/5.json deleted file mode 100644 index 05d41ca29a66f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/5.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "contents": "aデcãƒfoobar", - "cells": { - "0,0": { - "contents": "a" - }, - "0,1": { - "contents": "デ", - "is_wide": true - }, - "0,10": { - "contents": "a" - }, - "0,11": { - "contents": "r" - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - }, - "0,3": { - "contents": "c" - }, - "0,4": { - "contents": "ãƒ", - "is_wide": true - }, - "0,5": { - "contents": "", - "is_wide_continuation": true - }, - "0,6": { - "contents": "f" - }, - "0,7": { - "contents": "o" - }, - "0,8": { - "contents": "o" - }, - "0,9": { - "contents": "b" - } - }, - "cursor_position": [ - 0, - 12 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/5.typescript deleted file mode 100644 index aaeb0a8aa114d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/5.typescript +++ /dev/null @@ -1 +0,0 @@ -aデcãƒfoobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/6.json b/crates/turborepo-vt100/tests/data/fixtures/wide/6.json deleted file mode 100644 index e682e98fb3115..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/6.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "contents": "デcãƒfoobar", - "cells": { - "0,0": { - "contents": "デ", - "is_wide": true - }, - "0,1": { - "contents": "", - "is_wide_continuation": true - }, - "0,10": { - "contents": "r" - }, - "0,2": { - "contents": "c" - }, - "0,3": { - "contents": "ãƒ", - "is_wide": true - }, - "0,4": { - "contents": "", - "is_wide_continuation": true - }, - "0,5": { - "contents": "f" - }, - "0,6": { - "contents": "o" - }, - "0,7": { - "contents": "o" - }, - "0,8": { - "contents": "b" - }, - "0,9": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 11 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/6.typescript deleted file mode 100644 index 449cb6b2afae3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/6.typescript +++ /dev/null @@ -1 +0,0 @@ -デcãƒfoobar \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/7.json b/crates/turborepo-vt100/tests/data/fixtures/wide/7.json deleted file mode 100644 index 482c65b83c4f2..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/7.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": " a", - "cells": { - "0,1": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/7.typescript deleted file mode 100644 index 7773a89463d7b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/7.typescript +++ /dev/null @@ -1 +0,0 @@ -cデa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/8.json b/crates/turborepo-vt100/tests/data/fixtures/wide/8.json deleted file mode 100644 index 2ace374833247..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/8.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "contents": " ãƒ", - "cells": { - "0,1": { - "contents": "ãƒ", - "is_wide": true - }, - "0,2": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/8.typescript deleted file mode 100644 index 73ccb7e034947..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/8.typescript +++ /dev/null @@ -1 +0,0 @@ -cデム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/9.json b/crates/turborepo-vt100/tests/data/fixtures/wide/9.json deleted file mode 100644 index 4d6267caf58f0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/9.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "contents": "デ", - "cells": { - "0,0": { - "contents": "デ", - "is_wide": true - }, - "0,1": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 0, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wide/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/wide/9.typescript deleted file mode 100644 index 4aade7f8a4ee7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wide/9.typescript +++ /dev/null @@ -1 +0,0 @@ -cデ[@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap.in b/crates/turborepo-vt100/tests/data/fixtures/wrap.in deleted file mode 100644 index a1b7cea5fdb6b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap.in +++ /dev/null @@ -1,34 +0,0 @@ -0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -\x1b[5H01234567890123456789012345678901234567890123456789012345678901234567890123456789 -\x1b[6H01234567890123456789012345678901234567890123456789012345678901234567890123456789 -\x1b[H\x1b[J -0123456789012345678901234567890123456789012345678901234567890123456789012345678 -9 -a -b -\x1b[H\x1b[J -012345678901234567890123456789012345678901234567890123456789012345678901234567 -ム-a -\x1b[H\x1b[J -0123456789012345678901234567890123456789012345678901234567890123456789012345678 -ム-a -\x1b[H\x1b[J - -\n -\n - -\x1b[H\x1b[J -ãƒa\x1b[L\x1b[1;79Hbcd -\x1bc\x1b[1;79Habcd -\x1b[1;80H\x1b[X -\x1bc\x1b[1;79Habcd -\x1b[H\x1b[@ -\x1bc\x1b[1;80Haa\x1b[T\x1b[@ -\x1bc\na\x1b[1;79Hデ\n -\x1bc\x1b[1;79Hãƒa\x1b[1;79Hb -\x1bc\x1b[1;79Hãƒa\x1b[1;78Hム-\x1bc\x1b[24;80Hab -\x1bc\x1b[23;80Ha\x1b[24;80Ha -b diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/1.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/1.json deleted file mode 100644 index 194977ae10720..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/1.json +++ /dev/null @@ -1,309 +0,0 @@ -{ - "contents": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,79": { - "contents": "9" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "0" - }, - "1,1": { - "contents": "1" - }, - "1,10": { - "contents": "0" - }, - "1,11": { - "contents": "1" - }, - "1,12": { - "contents": "2" - }, - "1,13": { - "contents": "3" - }, - "1,14": { - "contents": "4" - }, - "1,15": { - "contents": "5" - }, - "1,16": { - "contents": "6" - }, - "1,17": { - "contents": "7" - }, - "1,18": { - "contents": "8" - }, - "1,19": { - "contents": "9" - }, - "1,2": { - "contents": "2" - }, - "1,3": { - "contents": "3" - }, - "1,4": { - "contents": "4" - }, - "1,5": { - "contents": "5" - }, - "1,6": { - "contents": "6" - }, - "1,7": { - "contents": "7" - }, - "1,8": { - "contents": "8" - }, - "1,9": { - "contents": "9" - } - }, - "cursor_position": [ - 1, - 20 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/1.typescript deleted file mode 100644 index edd4e96b75822..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/1.typescript +++ /dev/null @@ -1 +0,0 @@ -0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/10.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/10.json deleted file mode 100644 index 7031c27ca71ea..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/10.json +++ /dev/null @@ -1,243 +0,0 @@ -{ - "contents": "012345678901234567890123456789012345678901234567890123456789012345678901234567", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - } - }, - "cursor_position": [ - 0, - 78 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/10.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/10.typescript deleted file mode 100644 index a0cf6854f4453..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/10.typescript +++ /dev/null @@ -1 +0,0 @@ -012345678901234567890123456789012345678901234567890123456789012345678901234567 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/11.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/11.json deleted file mode 100644 index 681f6346a48ac..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/11.json +++ /dev/null @@ -1,251 +0,0 @@ -{ - "contents": "012345678901234567890123456789012345678901234567890123456789012345678901234567ãƒ", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "ãƒ", - "is_wide": true - }, - "0,79": { - "contents": "", - "is_wide_continuation": true - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/11.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/11.typescript deleted file mode 100644 index 14dfb508356c8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/11.typescript +++ /dev/null @@ -1 +0,0 @@ -ム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/12.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/12.json deleted file mode 100644 index 1742de921d9ad..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/12.json +++ /dev/null @@ -1,254 +0,0 @@ -{ - "contents": "012345678901234567890123456789012345678901234567890123456789012345678901234567ãƒa", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "ãƒ", - "is_wide": true - }, - "0,79": { - "contents": "", - "is_wide_continuation": true - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "a" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/12.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/12.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/12.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/13.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/13.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/13.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/13.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/13.typescript deleted file mode 100644 index 795264ae2c899..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/13.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/14.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/14.json deleted file mode 100644 index 09fb67b4d40e5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/14.json +++ /dev/null @@ -1,246 +0,0 @@ -{ - "contents": "0123456789012345678901234567890123456789012345678901234567890123456789012345678", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - } - }, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/14.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/14.typescript deleted file mode 100644 index 1f18cd95e9dd7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/14.typescript +++ /dev/null @@ -1 +0,0 @@ -0123456789012345678901234567890123456789012345678901234567890123456789012345678 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/15.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/15.json deleted file mode 100644 index 79ea22f7ccb36..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/15.json +++ /dev/null @@ -1,254 +0,0 @@ -{ - "contents": "0123456789012345678901234567890123456789012345678901234567890123456789012345678\nãƒ", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "ãƒ", - "is_wide": true - }, - "1,1": { - "contents": "", - "is_wide_continuation": true - } - }, - "cursor_position": [ - 1, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/15.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/15.typescript deleted file mode 100644 index 14dfb508356c8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/15.typescript +++ /dev/null @@ -1 +0,0 @@ -ム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/16.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/16.json deleted file mode 100644 index ce5dd87a43748..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/16.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "contents": "0123456789012345678901234567890123456789012345678901234567890123456789012345678\nãƒa", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "ãƒ", - "is_wide": true - }, - "1,1": { - "contents": "", - "is_wide_continuation": true - }, - "1,2": { - "contents": "a" - } - }, - "cursor_position": [ - 1, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/16.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/16.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/16.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/17.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/17.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/17.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/17.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/17.typescript deleted file mode 100644 index 795264ae2c899..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/17.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/18.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/18.json deleted file mode 100644 index 6fd56e8a9967b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/18.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "contents": " ", - "cells": { - "0,0": { - "contents": " " - }, - "0,1": { - "contents": " " - }, - "0,10": { - "contents": " " - }, - "0,11": { - "contents": " " - }, - "0,12": { - "contents": " " - }, - "0,13": { - "contents": " " - }, - "0,14": { - "contents": " " - }, - "0,15": { - "contents": " " - }, - "0,16": { - "contents": " " - }, - "0,17": { - "contents": " " - }, - "0,18": { - "contents": " " - }, - "0,19": { - "contents": " " - }, - "0,2": { - "contents": " " - }, - "0,20": { - "contents": " " - }, - "0,21": { - "contents": " " - }, - "0,22": { - "contents": " " - }, - "0,23": { - "contents": " " - }, - "0,24": { - "contents": " " - }, - "0,25": { - "contents": " " - }, - "0,26": { - "contents": " " - }, - "0,27": { - "contents": " " - }, - "0,28": { - "contents": " " - }, - "0,29": { - "contents": " " - }, - "0,3": { - "contents": " " - }, - "0,30": { - "contents": " " - }, - "0,31": { - "contents": " " - }, - "0,32": { - "contents": " " - }, - "0,33": { - "contents": " " - }, - "0,34": { - "contents": " " - }, - "0,35": { - "contents": " " - }, - "0,36": { - "contents": " " - }, - "0,37": { - "contents": " " - }, - "0,38": { - "contents": " " - }, - "0,39": { - "contents": " " - }, - "0,4": { - "contents": " " - }, - "0,40": { - "contents": " " - }, - "0,41": { - "contents": " " - }, - "0,42": { - "contents": " " - }, - "0,43": { - "contents": " " - }, - "0,44": { - "contents": " " - }, - "0,45": { - "contents": " " - }, - "0,46": { - "contents": " " - }, - "0,47": { - "contents": " " - }, - "0,48": { - "contents": " " - }, - "0,49": { - "contents": " " - }, - "0,5": { - "contents": " " - }, - "0,50": { - "contents": " " - }, - "0,51": { - "contents": " " - }, - "0,52": { - "contents": " " - }, - "0,53": { - "contents": " " - }, - "0,54": { - "contents": " " - }, - "0,55": { - "contents": " " - }, - "0,56": { - "contents": " " - }, - "0,57": { - "contents": " " - }, - "0,58": { - "contents": " " - }, - "0,59": { - "contents": " " - }, - "0,6": { - "contents": " " - }, - "0,60": { - "contents": " " - }, - "0,61": { - "contents": " " - }, - "0,62": { - "contents": " " - }, - "0,63": { - "contents": " " - }, - "0,64": { - "contents": " " - }, - "0,65": { - "contents": " " - }, - "0,66": { - "contents": " " - }, - "0,67": { - "contents": " " - }, - "0,68": { - "contents": " " - }, - "0,69": { - "contents": " " - }, - "0,7": { - "contents": " " - }, - "0,70": { - "contents": " " - }, - "0,71": { - "contents": " " - }, - "0,72": { - "contents": " " - }, - "0,73": { - "contents": " " - }, - "0,74": { - "contents": " " - }, - "0,75": { - "contents": " " - }, - "0,76": { - "contents": " " - }, - "0,77": { - "contents": " " - }, - "0,78": { - "contents": " " - }, - "0,79": { - "contents": " " - }, - "0,8": { - "contents": " " - }, - "0,9": { - "contents": " " - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/18.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/18.typescript deleted file mode 100644 index 45e9d8dbac721..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/18.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/19.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/19.json deleted file mode 100644 index 40459e74c188f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/19.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "contents": " ", - "cells": { - "0,0": { - "contents": " " - }, - "0,1": { - "contents": " " - }, - "0,10": { - "contents": " " - }, - "0,11": { - "contents": " " - }, - "0,12": { - "contents": " " - }, - "0,13": { - "contents": " " - }, - "0,14": { - "contents": " " - }, - "0,15": { - "contents": " " - }, - "0,16": { - "contents": " " - }, - "0,17": { - "contents": " " - }, - "0,18": { - "contents": " " - }, - "0,19": { - "contents": " " - }, - "0,2": { - "contents": " " - }, - "0,20": { - "contents": " " - }, - "0,21": { - "contents": " " - }, - "0,22": { - "contents": " " - }, - "0,23": { - "contents": " " - }, - "0,24": { - "contents": " " - }, - "0,25": { - "contents": " " - }, - "0,26": { - "contents": " " - }, - "0,27": { - "contents": " " - }, - "0,28": { - "contents": " " - }, - "0,29": { - "contents": " " - }, - "0,3": { - "contents": " " - }, - "0,30": { - "contents": " " - }, - "0,31": { - "contents": " " - }, - "0,32": { - "contents": " " - }, - "0,33": { - "contents": " " - }, - "0,34": { - "contents": " " - }, - "0,35": { - "contents": " " - }, - "0,36": { - "contents": " " - }, - "0,37": { - "contents": " " - }, - "0,38": { - "contents": " " - }, - "0,39": { - "contents": " " - }, - "0,4": { - "contents": " " - }, - "0,40": { - "contents": " " - }, - "0,41": { - "contents": " " - }, - "0,42": { - "contents": " " - }, - "0,43": { - "contents": " " - }, - "0,44": { - "contents": " " - }, - "0,45": { - "contents": " " - }, - "0,46": { - "contents": " " - }, - "0,47": { - "contents": " " - }, - "0,48": { - "contents": " " - }, - "0,49": { - "contents": " " - }, - "0,5": { - "contents": " " - }, - "0,50": { - "contents": " " - }, - "0,51": { - "contents": " " - }, - "0,52": { - "contents": " " - }, - "0,53": { - "contents": " " - }, - "0,54": { - "contents": " " - }, - "0,55": { - "contents": " " - }, - "0,56": { - "contents": " " - }, - "0,57": { - "contents": " " - }, - "0,58": { - "contents": " " - }, - "0,59": { - "contents": " " - }, - "0,6": { - "contents": " " - }, - "0,60": { - "contents": " " - }, - "0,61": { - "contents": " " - }, - "0,62": { - "contents": " " - }, - "0,63": { - "contents": " " - }, - "0,64": { - "contents": " " - }, - "0,65": { - "contents": " " - }, - "0,66": { - "contents": " " - }, - "0,67": { - "contents": " " - }, - "0,68": { - "contents": " " - }, - "0,69": { - "contents": " " - }, - "0,7": { - "contents": " " - }, - "0,70": { - "contents": " " - }, - "0,71": { - "contents": " " - }, - "0,72": { - "contents": " " - }, - "0,73": { - "contents": " " - }, - "0,74": { - "contents": " " - }, - "0,75": { - "contents": " " - }, - "0,76": { - "contents": " " - }, - "0,77": { - "contents": " " - }, - "0,78": { - "contents": " " - }, - "0,79": { - "contents": " " - }, - "0,8": { - "contents": " " - }, - "0,9": { - "contents": " " - } - }, - "cursor_position": [ - 1, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/19.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/19.typescript deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/19.typescript +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/2.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/2.json deleted file mode 100644 index 2ec6ed7c5d48a..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/2.json +++ /dev/null @@ -1,549 +0,0 @@ -{ - "contents": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\n\n01234567890123456789012345678901234567890123456789012345678901234567890123456789", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,79": { - "contents": "9" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "0" - }, - "1,1": { - "contents": "1" - }, - "1,10": { - "contents": "0" - }, - "1,11": { - "contents": "1" - }, - "1,12": { - "contents": "2" - }, - "1,13": { - "contents": "3" - }, - "1,14": { - "contents": "4" - }, - "1,15": { - "contents": "5" - }, - "1,16": { - "contents": "6" - }, - "1,17": { - "contents": "7" - }, - "1,18": { - "contents": "8" - }, - "1,19": { - "contents": "9" - }, - "1,2": { - "contents": "2" - }, - "1,3": { - "contents": "3" - }, - "1,4": { - "contents": "4" - }, - "1,5": { - "contents": "5" - }, - "1,6": { - "contents": "6" - }, - "1,7": { - "contents": "7" - }, - "1,8": { - "contents": "8" - }, - "1,9": { - "contents": "9" - }, - "4,0": { - "contents": "0" - }, - "4,1": { - "contents": "1" - }, - "4,10": { - "contents": "0" - }, - "4,11": { - "contents": "1" - }, - "4,12": { - "contents": "2" - }, - "4,13": { - "contents": "3" - }, - "4,14": { - "contents": "4" - }, - "4,15": { - "contents": "5" - }, - "4,16": { - "contents": "6" - }, - "4,17": { - "contents": "7" - }, - "4,18": { - "contents": "8" - }, - "4,19": { - "contents": "9" - }, - "4,2": { - "contents": "2" - }, - "4,20": { - "contents": "0" - }, - "4,21": { - "contents": "1" - }, - "4,22": { - "contents": "2" - }, - "4,23": { - "contents": "3" - }, - "4,24": { - "contents": "4" - }, - "4,25": { - "contents": "5" - }, - "4,26": { - "contents": "6" - }, - "4,27": { - "contents": "7" - }, - "4,28": { - "contents": "8" - }, - "4,29": { - "contents": "9" - }, - "4,3": { - "contents": "3" - }, - "4,30": { - "contents": "0" - }, - "4,31": { - "contents": "1" - }, - "4,32": { - "contents": "2" - }, - "4,33": { - "contents": "3" - }, - "4,34": { - "contents": "4" - }, - "4,35": { - "contents": "5" - }, - "4,36": { - "contents": "6" - }, - "4,37": { - "contents": "7" - }, - "4,38": { - "contents": "8" - }, - "4,39": { - "contents": "9" - }, - "4,4": { - "contents": "4" - }, - "4,40": { - "contents": "0" - }, - "4,41": { - "contents": "1" - }, - "4,42": { - "contents": "2" - }, - "4,43": { - "contents": "3" - }, - "4,44": { - "contents": "4" - }, - "4,45": { - "contents": "5" - }, - "4,46": { - "contents": "6" - }, - "4,47": { - "contents": "7" - }, - "4,48": { - "contents": "8" - }, - "4,49": { - "contents": "9" - }, - "4,5": { - "contents": "5" - }, - "4,50": { - "contents": "0" - }, - "4,51": { - "contents": "1" - }, - "4,52": { - "contents": "2" - }, - "4,53": { - "contents": "3" - }, - "4,54": { - "contents": "4" - }, - "4,55": { - "contents": "5" - }, - "4,56": { - "contents": "6" - }, - "4,57": { - "contents": "7" - }, - "4,58": { - "contents": "8" - }, - "4,59": { - "contents": "9" - }, - "4,6": { - "contents": "6" - }, - "4,60": { - "contents": "0" - }, - "4,61": { - "contents": "1" - }, - "4,62": { - "contents": "2" - }, - "4,63": { - "contents": "3" - }, - "4,64": { - "contents": "4" - }, - "4,65": { - "contents": "5" - }, - "4,66": { - "contents": "6" - }, - "4,67": { - "contents": "7" - }, - "4,68": { - "contents": "8" - }, - "4,69": { - "contents": "9" - }, - "4,7": { - "contents": "7" - }, - "4,70": { - "contents": "0" - }, - "4,71": { - "contents": "1" - }, - "4,72": { - "contents": "2" - }, - "4,73": { - "contents": "3" - }, - "4,74": { - "contents": "4" - }, - "4,75": { - "contents": "5" - }, - "4,76": { - "contents": "6" - }, - "4,77": { - "contents": "7" - }, - "4,78": { - "contents": "8" - }, - "4,79": { - "contents": "9" - }, - "4,8": { - "contents": "8" - }, - "4,9": { - "contents": "9" - } - }, - "cursor_position": [ - 4, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/2.typescript deleted file mode 100644 index 849826511dffd..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/2.typescript +++ /dev/null @@ -1 +0,0 @@ -01234567890123456789012345678901234567890123456789012345678901234567890123456789 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/20.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/20.json deleted file mode 100644 index 7f0cf4cae27d1..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/20.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "contents": " ", - "cells": { - "0,0": { - "contents": " " - }, - "0,1": { - "contents": " " - }, - "0,10": { - "contents": " " - }, - "0,11": { - "contents": " " - }, - "0,12": { - "contents": " " - }, - "0,13": { - "contents": " " - }, - "0,14": { - "contents": " " - }, - "0,15": { - "contents": " " - }, - "0,16": { - "contents": " " - }, - "0,17": { - "contents": " " - }, - "0,18": { - "contents": " " - }, - "0,19": { - "contents": " " - }, - "0,2": { - "contents": " " - }, - "0,20": { - "contents": " " - }, - "0,21": { - "contents": " " - }, - "0,22": { - "contents": " " - }, - "0,23": { - "contents": " " - }, - "0,24": { - "contents": " " - }, - "0,25": { - "contents": " " - }, - "0,26": { - "contents": " " - }, - "0,27": { - "contents": " " - }, - "0,28": { - "contents": " " - }, - "0,29": { - "contents": " " - }, - "0,3": { - "contents": " " - }, - "0,30": { - "contents": " " - }, - "0,31": { - "contents": " " - }, - "0,32": { - "contents": " " - }, - "0,33": { - "contents": " " - }, - "0,34": { - "contents": " " - }, - "0,35": { - "contents": " " - }, - "0,36": { - "contents": " " - }, - "0,37": { - "contents": " " - }, - "0,38": { - "contents": " " - }, - "0,39": { - "contents": " " - }, - "0,4": { - "contents": " " - }, - "0,40": { - "contents": " " - }, - "0,41": { - "contents": " " - }, - "0,42": { - "contents": " " - }, - "0,43": { - "contents": " " - }, - "0,44": { - "contents": " " - }, - "0,45": { - "contents": " " - }, - "0,46": { - "contents": " " - }, - "0,47": { - "contents": " " - }, - "0,48": { - "contents": " " - }, - "0,49": { - "contents": " " - }, - "0,5": { - "contents": " " - }, - "0,50": { - "contents": " " - }, - "0,51": { - "contents": " " - }, - "0,52": { - "contents": " " - }, - "0,53": { - "contents": " " - }, - "0,54": { - "contents": " " - }, - "0,55": { - "contents": " " - }, - "0,56": { - "contents": " " - }, - "0,57": { - "contents": " " - }, - "0,58": { - "contents": " " - }, - "0,59": { - "contents": " " - }, - "0,6": { - "contents": " " - }, - "0,60": { - "contents": " " - }, - "0,61": { - "contents": " " - }, - "0,62": { - "contents": " " - }, - "0,63": { - "contents": " " - }, - "0,64": { - "contents": " " - }, - "0,65": { - "contents": " " - }, - "0,66": { - "contents": " " - }, - "0,67": { - "contents": " " - }, - "0,68": { - "contents": " " - }, - "0,69": { - "contents": " " - }, - "0,7": { - "contents": " " - }, - "0,70": { - "contents": " " - }, - "0,71": { - "contents": " " - }, - "0,72": { - "contents": " " - }, - "0,73": { - "contents": " " - }, - "0,74": { - "contents": " " - }, - "0,75": { - "contents": " " - }, - "0,76": { - "contents": " " - }, - "0,77": { - "contents": " " - }, - "0,78": { - "contents": " " - }, - "0,79": { - "contents": " " - }, - "0,8": { - "contents": " " - }, - "0,9": { - "contents": " " - } - }, - "cursor_position": [ - 2, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/20.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/20.typescript deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/20.typescript +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/21.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/21.json deleted file mode 100644 index e7201c1ea7e8c..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/21.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "contents": " \n\n\n ", - "cells": { - "0,0": { - "contents": " " - }, - "0,1": { - "contents": " " - }, - "0,10": { - "contents": " " - }, - "0,11": { - "contents": " " - }, - "0,12": { - "contents": " " - }, - "0,13": { - "contents": " " - }, - "0,14": { - "contents": " " - }, - "0,15": { - "contents": " " - }, - "0,16": { - "contents": " " - }, - "0,17": { - "contents": " " - }, - "0,18": { - "contents": " " - }, - "0,19": { - "contents": " " - }, - "0,2": { - "contents": " " - }, - "0,20": { - "contents": " " - }, - "0,21": { - "contents": " " - }, - "0,22": { - "contents": " " - }, - "0,23": { - "contents": " " - }, - "0,24": { - "contents": " " - }, - "0,25": { - "contents": " " - }, - "0,26": { - "contents": " " - }, - "0,27": { - "contents": " " - }, - "0,28": { - "contents": " " - }, - "0,29": { - "contents": " " - }, - "0,3": { - "contents": " " - }, - "0,30": { - "contents": " " - }, - "0,31": { - "contents": " " - }, - "0,32": { - "contents": " " - }, - "0,33": { - "contents": " " - }, - "0,34": { - "contents": " " - }, - "0,35": { - "contents": " " - }, - "0,36": { - "contents": " " - }, - "0,37": { - "contents": " " - }, - "0,38": { - "contents": " " - }, - "0,39": { - "contents": " " - }, - "0,4": { - "contents": " " - }, - "0,40": { - "contents": " " - }, - "0,41": { - "contents": " " - }, - "0,42": { - "contents": " " - }, - "0,43": { - "contents": " " - }, - "0,44": { - "contents": " " - }, - "0,45": { - "contents": " " - }, - "0,46": { - "contents": " " - }, - "0,47": { - "contents": " " - }, - "0,48": { - "contents": " " - }, - "0,49": { - "contents": " " - }, - "0,5": { - "contents": " " - }, - "0,50": { - "contents": " " - }, - "0,51": { - "contents": " " - }, - "0,52": { - "contents": " " - }, - "0,53": { - "contents": " " - }, - "0,54": { - "contents": " " - }, - "0,55": { - "contents": " " - }, - "0,56": { - "contents": " " - }, - "0,57": { - "contents": " " - }, - "0,58": { - "contents": " " - }, - "0,59": { - "contents": " " - }, - "0,6": { - "contents": " " - }, - "0,60": { - "contents": " " - }, - "0,61": { - "contents": " " - }, - "0,62": { - "contents": " " - }, - "0,63": { - "contents": " " - }, - "0,64": { - "contents": " " - }, - "0,65": { - "contents": " " - }, - "0,66": { - "contents": " " - }, - "0,67": { - "contents": " " - }, - "0,68": { - "contents": " " - }, - "0,69": { - "contents": " " - }, - "0,7": { - "contents": " " - }, - "0,70": { - "contents": " " - }, - "0,71": { - "contents": " " - }, - "0,72": { - "contents": " " - }, - "0,73": { - "contents": " " - }, - "0,74": { - "contents": " " - }, - "0,75": { - "contents": " " - }, - "0,76": { - "contents": " " - }, - "0,77": { - "contents": " " - }, - "0,78": { - "contents": " " - }, - "0,79": { - "contents": " " - }, - "0,8": { - "contents": " " - }, - "0,9": { - "contents": " " - }, - "3,0": { - "contents": " " - } - }, - "cursor_position": [ - 3, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/21.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/21.typescript deleted file mode 100644 index 0519ecba6ea91..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/21.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/22.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/22.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/22.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/22.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/22.typescript deleted file mode 100644 index 795264ae2c899..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/22.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/23.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/23.json deleted file mode 100644 index ef04d5167b194..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/23.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contents": " bcd a", - "cells": { - "0,78": { - "contents": "b" - }, - "0,79": { - "contents": "c" - }, - "1,0": { - "contents": "d" - }, - "1,1": { - "contents": " " - }, - "1,2": { - "contents": "a" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/23.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/23.typescript deleted file mode 100644 index d162fb83b0596..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/23.typescript +++ /dev/null @@ -1 +0,0 @@ -ãƒabcd \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/24.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/24.json deleted file mode 100644 index a4d8d688df36e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/24.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": " abcd", - "cells": { - "0,78": { - "contents": "a" - }, - "0,79": { - "contents": "b" - }, - "1,0": { - "contents": "c" - }, - "1,1": { - "contents": "d" - } - }, - "cursor_position": [ - 1, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/24.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/24.typescript deleted file mode 100644 index 9e7bc4893f96f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/24.typescript +++ /dev/null @@ -1 +0,0 @@ -cabcd \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/25.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/25.json deleted file mode 100644 index 3f7250bbbc425..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/25.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": " a\ncd", - "cells": { - "0,78": { - "contents": "a" - }, - "1,0": { - "contents": "c" - }, - "1,1": { - "contents": "d" - } - }, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/25.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/25.typescript deleted file mode 100644 index 582fae175f2e8..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/25.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/26.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/26.json deleted file mode 100644 index a4d8d688df36e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/26.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "contents": " abcd", - "cells": { - "0,78": { - "contents": "a" - }, - "0,79": { - "contents": "b" - }, - "1,0": { - "contents": "c" - }, - "1,1": { - "contents": "d" - } - }, - "cursor_position": [ - 1, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/26.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/26.typescript deleted file mode 100644 index 9e7bc4893f96f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/26.typescript +++ /dev/null @@ -1 +0,0 @@ -cabcd \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/27.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/27.json deleted file mode 100644 index ac07fa24d2864..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/27.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": " a\ncd", - "cells": { - "0,79": { - "contents": "a" - }, - "1,0": { - "contents": "c" - }, - "1,1": { - "contents": "d" - } - }, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/27.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/27.typescript deleted file mode 100644 index f6122a6b0980b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/27.typescript +++ /dev/null @@ -1 +0,0 @@ -[@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/28.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/28.json deleted file mode 100644 index a50556673144e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/28.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "contents": "\n\na", - "cells": { - "2,0": { - "contents": "a" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/28.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/28.typescript deleted file mode 100644 index f760735078ff0..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/28.typescript +++ /dev/null @@ -1 +0,0 @@ -caa[@ \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/29.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/29.json deleted file mode 100644 index 7c0324dbc4830..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/29.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contents": " デ\na", - "cells": { - "0,78": { - "contents": "デ", - "is_wide": true - }, - "0,79": { - "contents": "", - "is_wide_continuation": true - }, - "1,0": { - "contents": "a" - } - }, - "cursor_position": [ - 1, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/29.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/29.typescript deleted file mode 100644 index 2248a918e7453..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/29.typescript +++ /dev/null @@ -1,2 +0,0 @@ -c -aデ diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/3.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/3.json deleted file mode 100644 index afa40a6441b6b..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/3.json +++ /dev/null @@ -1,789 +0,0 @@ -{ - "contents": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\n\n01234567890123456789012345678901234567890123456789012345678901234567890123456789\n01234567890123456789012345678901234567890123456789012345678901234567890123456789", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,79": { - "contents": "9" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "0" - }, - "1,1": { - "contents": "1" - }, - "1,10": { - "contents": "0" - }, - "1,11": { - "contents": "1" - }, - "1,12": { - "contents": "2" - }, - "1,13": { - "contents": "3" - }, - "1,14": { - "contents": "4" - }, - "1,15": { - "contents": "5" - }, - "1,16": { - "contents": "6" - }, - "1,17": { - "contents": "7" - }, - "1,18": { - "contents": "8" - }, - "1,19": { - "contents": "9" - }, - "1,2": { - "contents": "2" - }, - "1,3": { - "contents": "3" - }, - "1,4": { - "contents": "4" - }, - "1,5": { - "contents": "5" - }, - "1,6": { - "contents": "6" - }, - "1,7": { - "contents": "7" - }, - "1,8": { - "contents": "8" - }, - "1,9": { - "contents": "9" - }, - "4,0": { - "contents": "0" - }, - "4,1": { - "contents": "1" - }, - "4,10": { - "contents": "0" - }, - "4,11": { - "contents": "1" - }, - "4,12": { - "contents": "2" - }, - "4,13": { - "contents": "3" - }, - "4,14": { - "contents": "4" - }, - "4,15": { - "contents": "5" - }, - "4,16": { - "contents": "6" - }, - "4,17": { - "contents": "7" - }, - "4,18": { - "contents": "8" - }, - "4,19": { - "contents": "9" - }, - "4,2": { - "contents": "2" - }, - "4,20": { - "contents": "0" - }, - "4,21": { - "contents": "1" - }, - "4,22": { - "contents": "2" - }, - "4,23": { - "contents": "3" - }, - "4,24": { - "contents": "4" - }, - "4,25": { - "contents": "5" - }, - "4,26": { - "contents": "6" - }, - "4,27": { - "contents": "7" - }, - "4,28": { - "contents": "8" - }, - "4,29": { - "contents": "9" - }, - "4,3": { - "contents": "3" - }, - "4,30": { - "contents": "0" - }, - "4,31": { - "contents": "1" - }, - "4,32": { - "contents": "2" - }, - "4,33": { - "contents": "3" - }, - "4,34": { - "contents": "4" - }, - "4,35": { - "contents": "5" - }, - "4,36": { - "contents": "6" - }, - "4,37": { - "contents": "7" - }, - "4,38": { - "contents": "8" - }, - "4,39": { - "contents": "9" - }, - "4,4": { - "contents": "4" - }, - "4,40": { - "contents": "0" - }, - "4,41": { - "contents": "1" - }, - "4,42": { - "contents": "2" - }, - "4,43": { - "contents": "3" - }, - "4,44": { - "contents": "4" - }, - "4,45": { - "contents": "5" - }, - "4,46": { - "contents": "6" - }, - "4,47": { - "contents": "7" - }, - "4,48": { - "contents": "8" - }, - "4,49": { - "contents": "9" - }, - "4,5": { - "contents": "5" - }, - "4,50": { - "contents": "0" - }, - "4,51": { - "contents": "1" - }, - "4,52": { - "contents": "2" - }, - "4,53": { - "contents": "3" - }, - "4,54": { - "contents": "4" - }, - "4,55": { - "contents": "5" - }, - "4,56": { - "contents": "6" - }, - "4,57": { - "contents": "7" - }, - "4,58": { - "contents": "8" - }, - "4,59": { - "contents": "9" - }, - "4,6": { - "contents": "6" - }, - "4,60": { - "contents": "0" - }, - "4,61": { - "contents": "1" - }, - "4,62": { - "contents": "2" - }, - "4,63": { - "contents": "3" - }, - "4,64": { - "contents": "4" - }, - "4,65": { - "contents": "5" - }, - "4,66": { - "contents": "6" - }, - "4,67": { - "contents": "7" - }, - "4,68": { - "contents": "8" - }, - "4,69": { - "contents": "9" - }, - "4,7": { - "contents": "7" - }, - "4,70": { - "contents": "0" - }, - "4,71": { - "contents": "1" - }, - "4,72": { - "contents": "2" - }, - "4,73": { - "contents": "3" - }, - "4,74": { - "contents": "4" - }, - "4,75": { - "contents": "5" - }, - "4,76": { - "contents": "6" - }, - "4,77": { - "contents": "7" - }, - "4,78": { - "contents": "8" - }, - "4,79": { - "contents": "9" - }, - "4,8": { - "contents": "8" - }, - "4,9": { - "contents": "9" - }, - "5,0": { - "contents": "0" - }, - "5,1": { - "contents": "1" - }, - "5,10": { - "contents": "0" - }, - "5,11": { - "contents": "1" - }, - "5,12": { - "contents": "2" - }, - "5,13": { - "contents": "3" - }, - "5,14": { - "contents": "4" - }, - "5,15": { - "contents": "5" - }, - "5,16": { - "contents": "6" - }, - "5,17": { - "contents": "7" - }, - "5,18": { - "contents": "8" - }, - "5,19": { - "contents": "9" - }, - "5,2": { - "contents": "2" - }, - "5,20": { - "contents": "0" - }, - "5,21": { - "contents": "1" - }, - "5,22": { - "contents": "2" - }, - "5,23": { - "contents": "3" - }, - "5,24": { - "contents": "4" - }, - "5,25": { - "contents": "5" - }, - "5,26": { - "contents": "6" - }, - "5,27": { - "contents": "7" - }, - "5,28": { - "contents": "8" - }, - "5,29": { - "contents": "9" - }, - "5,3": { - "contents": "3" - }, - "5,30": { - "contents": "0" - }, - "5,31": { - "contents": "1" - }, - "5,32": { - "contents": "2" - }, - "5,33": { - "contents": "3" - }, - "5,34": { - "contents": "4" - }, - "5,35": { - "contents": "5" - }, - "5,36": { - "contents": "6" - }, - "5,37": { - "contents": "7" - }, - "5,38": { - "contents": "8" - }, - "5,39": { - "contents": "9" - }, - "5,4": { - "contents": "4" - }, - "5,40": { - "contents": "0" - }, - "5,41": { - "contents": "1" - }, - "5,42": { - "contents": "2" - }, - "5,43": { - "contents": "3" - }, - "5,44": { - "contents": "4" - }, - "5,45": { - "contents": "5" - }, - "5,46": { - "contents": "6" - }, - "5,47": { - "contents": "7" - }, - "5,48": { - "contents": "8" - }, - "5,49": { - "contents": "9" - }, - "5,5": { - "contents": "5" - }, - "5,50": { - "contents": "0" - }, - "5,51": { - "contents": "1" - }, - "5,52": { - "contents": "2" - }, - "5,53": { - "contents": "3" - }, - "5,54": { - "contents": "4" - }, - "5,55": { - "contents": "5" - }, - "5,56": { - "contents": "6" - }, - "5,57": { - "contents": "7" - }, - "5,58": { - "contents": "8" - }, - "5,59": { - "contents": "9" - }, - "5,6": { - "contents": "6" - }, - "5,60": { - "contents": "0" - }, - "5,61": { - "contents": "1" - }, - "5,62": { - "contents": "2" - }, - "5,63": { - "contents": "3" - }, - "5,64": { - "contents": "4" - }, - "5,65": { - "contents": "5" - }, - "5,66": { - "contents": "6" - }, - "5,67": { - "contents": "7" - }, - "5,68": { - "contents": "8" - }, - "5,69": { - "contents": "9" - }, - "5,7": { - "contents": "7" - }, - "5,70": { - "contents": "0" - }, - "5,71": { - "contents": "1" - }, - "5,72": { - "contents": "2" - }, - "5,73": { - "contents": "3" - }, - "5,74": { - "contents": "4" - }, - "5,75": { - "contents": "5" - }, - "5,76": { - "contents": "6" - }, - "5,77": { - "contents": "7" - }, - "5,78": { - "contents": "8" - }, - "5,79": { - "contents": "9" - }, - "5,8": { - "contents": "8" - }, - "5,9": { - "contents": "9" - } - }, - "cursor_position": [ - 5, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/3.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/3.typescript deleted file mode 100644 index faf807a14a041..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/3.typescript +++ /dev/null @@ -1 +0,0 @@ -01234567890123456789012345678901234567890123456789012345678901234567890123456789 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/30.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/30.json deleted file mode 100644 index 44351c6aa4909..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/30.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": " b a", - "cells": { - "0,78": { - "contents": "b" - }, - "0,79": { - "contents": " " - }, - "1,0": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/30.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/30.typescript deleted file mode 100644 index 73ac4d45a81cf..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/30.typescript +++ /dev/null @@ -1 +0,0 @@ -cãƒab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/31.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/31.json deleted file mode 100644 index 8be1892e20b2e..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/31.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contents": " ãƒ\na", - "cells": { - "0,77": { - "contents": "ãƒ", - "is_wide": true - }, - "0,78": { - "contents": "", - "is_wide_continuation": true - }, - "1,0": { - "contents": "a" - } - }, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/31.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/31.typescript deleted file mode 100644 index f435b65460bc9..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/31.typescript +++ /dev/null @@ -1 +0,0 @@ -cãƒaム\ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/32.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/32.json deleted file mode 100644 index cdfc959e79cf4..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/32.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n ab", - "cells": { - "22,79": { - "contents": "a" - }, - "23,0": { - "contents": "b" - } - }, - "cursor_position": [ - 23, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/32.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/32.typescript deleted file mode 100644 index c15369f259d49..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/32.typescript +++ /dev/null @@ -1 +0,0 @@ -cab \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/33.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/33.json deleted file mode 100644 index dd11a8a5c14af..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/33.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a\n a", - "cells": { - "22,79": { - "contents": "a" - }, - "23,79": { - "contents": "a" - } - }, - "cursor_position": [ - 23, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/33.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/33.typescript deleted file mode 100644 index 2f876277fd14f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/33.typescript +++ /dev/null @@ -1 +0,0 @@ -caa \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/34.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/34.json deleted file mode 100644 index df7881de76c4d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/34.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "contents": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n a\n ab", - "cells": { - "21,79": { - "contents": "a" - }, - "22,79": { - "contents": "a" - }, - "23,0": { - "contents": "b" - } - }, - "cursor_position": [ - 23, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/34.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/34.typescript deleted file mode 100644 index 63d8dbd40c235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/34.typescript +++ /dev/null @@ -1 +0,0 @@ -b \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/4.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/4.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/4.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/4.typescript deleted file mode 100644 index 795264ae2c899..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/4.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/5.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/5.json deleted file mode 100644 index 09fb67b4d40e5..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/5.json +++ /dev/null @@ -1,246 +0,0 @@ -{ - "contents": "0123456789012345678901234567890123456789012345678901234567890123456789012345678", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - } - }, - "cursor_position": [ - 0, - 79 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/5.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/5.typescript deleted file mode 100644 index 1f18cd95e9dd7..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/5.typescript +++ /dev/null @@ -1 +0,0 @@ -0123456789012345678901234567890123456789012345678901234567890123456789012345678 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/6.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/6.json deleted file mode 100644 index af45c83e5816f..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/6.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "contents": "01234567890123456789012345678901234567890123456789012345678901234567890123456789", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,79": { - "contents": "9" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - } - }, - "cursor_position": [ - 0, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/6.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/6.typescript deleted file mode 100644 index f11c82a4cb6cc..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/6.typescript +++ /dev/null @@ -1 +0,0 @@ -9 \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/7.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/7.json deleted file mode 100644 index 9d7ae8a7cf2cf..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/7.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "contents": "01234567890123456789012345678901234567890123456789012345678901234567890123456789a", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,79": { - "contents": "9" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "a" - } - }, - "cursor_position": [ - 1, - 1 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/7.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/7.typescript deleted file mode 100644 index 2e65efe2a145d..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/7.typescript +++ /dev/null @@ -1 +0,0 @@ -a \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/8.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/8.json deleted file mode 100644 index 0d96d63e9f537..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/8.json +++ /dev/null @@ -1,255 +0,0 @@ -{ - "contents": "01234567890123456789012345678901234567890123456789012345678901234567890123456789ab", - "cells": { - "0,0": { - "contents": "0" - }, - "0,1": { - "contents": "1" - }, - "0,10": { - "contents": "0" - }, - "0,11": { - "contents": "1" - }, - "0,12": { - "contents": "2" - }, - "0,13": { - "contents": "3" - }, - "0,14": { - "contents": "4" - }, - "0,15": { - "contents": "5" - }, - "0,16": { - "contents": "6" - }, - "0,17": { - "contents": "7" - }, - "0,18": { - "contents": "8" - }, - "0,19": { - "contents": "9" - }, - "0,2": { - "contents": "2" - }, - "0,20": { - "contents": "0" - }, - "0,21": { - "contents": "1" - }, - "0,22": { - "contents": "2" - }, - "0,23": { - "contents": "3" - }, - "0,24": { - "contents": "4" - }, - "0,25": { - "contents": "5" - }, - "0,26": { - "contents": "6" - }, - "0,27": { - "contents": "7" - }, - "0,28": { - "contents": "8" - }, - "0,29": { - "contents": "9" - }, - "0,3": { - "contents": "3" - }, - "0,30": { - "contents": "0" - }, - "0,31": { - "contents": "1" - }, - "0,32": { - "contents": "2" - }, - "0,33": { - "contents": "3" - }, - "0,34": { - "contents": "4" - }, - "0,35": { - "contents": "5" - }, - "0,36": { - "contents": "6" - }, - "0,37": { - "contents": "7" - }, - "0,38": { - "contents": "8" - }, - "0,39": { - "contents": "9" - }, - "0,4": { - "contents": "4" - }, - "0,40": { - "contents": "0" - }, - "0,41": { - "contents": "1" - }, - "0,42": { - "contents": "2" - }, - "0,43": { - "contents": "3" - }, - "0,44": { - "contents": "4" - }, - "0,45": { - "contents": "5" - }, - "0,46": { - "contents": "6" - }, - "0,47": { - "contents": "7" - }, - "0,48": { - "contents": "8" - }, - "0,49": { - "contents": "9" - }, - "0,5": { - "contents": "5" - }, - "0,50": { - "contents": "0" - }, - "0,51": { - "contents": "1" - }, - "0,52": { - "contents": "2" - }, - "0,53": { - "contents": "3" - }, - "0,54": { - "contents": "4" - }, - "0,55": { - "contents": "5" - }, - "0,56": { - "contents": "6" - }, - "0,57": { - "contents": "7" - }, - "0,58": { - "contents": "8" - }, - "0,59": { - "contents": "9" - }, - "0,6": { - "contents": "6" - }, - "0,60": { - "contents": "0" - }, - "0,61": { - "contents": "1" - }, - "0,62": { - "contents": "2" - }, - "0,63": { - "contents": "3" - }, - "0,64": { - "contents": "4" - }, - "0,65": { - "contents": "5" - }, - "0,66": { - "contents": "6" - }, - "0,67": { - "contents": "7" - }, - "0,68": { - "contents": "8" - }, - "0,69": { - "contents": "9" - }, - "0,7": { - "contents": "7" - }, - "0,70": { - "contents": "0" - }, - "0,71": { - "contents": "1" - }, - "0,72": { - "contents": "2" - }, - "0,73": { - "contents": "3" - }, - "0,74": { - "contents": "4" - }, - "0,75": { - "contents": "5" - }, - "0,76": { - "contents": "6" - }, - "0,77": { - "contents": "7" - }, - "0,78": { - "contents": "8" - }, - "0,79": { - "contents": "9" - }, - "0,8": { - "contents": "8" - }, - "0,9": { - "contents": "9" - }, - "1,0": { - "contents": "a" - }, - "1,1": { - "contents": "b" - } - }, - "cursor_position": [ - 1, - 2 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/8.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/8.typescript deleted file mode 100644 index 63d8dbd40c235..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/8.typescript +++ /dev/null @@ -1 +0,0 @@ -b \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/9.json b/crates/turborepo-vt100/tests/data/fixtures/wrap/9.json deleted file mode 100644 index bb83ae40cbc67..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/9.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "contents": "", - "cells": {}, - "cursor_position": [ - 0, - 0 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap/9.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap/9.typescript deleted file mode 100644 index 795264ae2c899..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap/9.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird.in b/crates/turborepo-vt100/tests/data/fixtures/wrap_weird.in deleted file mode 100644 index 208a565128a20..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird.in +++ /dev/null @@ -1,2 +0,0 @@ -foo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo\r\nfoo -\x1b[3;80H diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/1.json b/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/1.json deleted file mode 100644 index cab2f7ad14048..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/1.json +++ /dev/null @@ -1,225 +0,0 @@ -{ - "contents": "foo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "1,0": { - "contents": "f" - }, - "1,1": { - "contents": "o" - }, - "1,2": { - "contents": "o" - }, - "10,0": { - "contents": "f" - }, - "10,1": { - "contents": "o" - }, - "10,2": { - "contents": "o" - }, - "11,0": { - "contents": "f" - }, - "11,1": { - "contents": "o" - }, - "11,2": { - "contents": "o" - }, - "12,0": { - "contents": "f" - }, - "12,1": { - "contents": "o" - }, - "12,2": { - "contents": "o" - }, - "13,0": { - "contents": "f" - }, - "13,1": { - "contents": "o" - }, - "13,2": { - "contents": "o" - }, - "14,0": { - "contents": "f" - }, - "14,1": { - "contents": "o" - }, - "14,2": { - "contents": "o" - }, - "15,0": { - "contents": "f" - }, - "15,1": { - "contents": "o" - }, - "15,2": { - "contents": "o" - }, - "16,0": { - "contents": "f" - }, - "16,1": { - "contents": "o" - }, - "16,2": { - "contents": "o" - }, - "17,0": { - "contents": "f" - }, - "17,1": { - "contents": "o" - }, - "17,2": { - "contents": "o" - }, - "18,0": { - "contents": "f" - }, - "18,1": { - "contents": "o" - }, - "18,2": { - "contents": "o" - }, - "19,0": { - "contents": "f" - }, - "19,1": { - "contents": "o" - }, - "19,2": { - "contents": "o" - }, - "2,0": { - "contents": "f" - }, - "2,1": { - "contents": "o" - }, - "2,2": { - "contents": "o" - }, - "20,0": { - "contents": "f" - }, - "20,1": { - "contents": "o" - }, - "20,2": { - "contents": "o" - }, - "21,0": { - "contents": "f" - }, - "21,1": { - "contents": "o" - }, - "21,2": { - "contents": "o" - }, - "22,0": { - "contents": "f" - }, - "22,1": { - "contents": "o" - }, - "22,2": { - "contents": "o" - }, - "23,0": { - "contents": "f" - }, - "23,1": { - "contents": "o" - }, - "23,2": { - "contents": "o" - }, - "3,0": { - "contents": "f" - }, - "3,1": { - "contents": "o" - }, - "3,2": { - "contents": "o" - }, - "4,0": { - "contents": "f" - }, - "4,1": { - "contents": "o" - }, - "4,2": { - "contents": "o" - }, - "5,0": { - "contents": "f" - }, - "5,1": { - "contents": "o" - }, - "5,2": { - "contents": "o" - }, - "6,0": { - "contents": "f" - }, - "6,1": { - "contents": "o" - }, - "6,2": { - "contents": "o" - }, - "7,0": { - "contents": "f" - }, - "7,1": { - "contents": "o" - }, - "7,2": { - "contents": "o" - }, - "8,0": { - "contents": "f" - }, - "8,1": { - "contents": "o" - }, - "8,2": { - "contents": "o" - }, - "9,0": { - "contents": "f" - }, - "9,1": { - "contents": "o" - }, - "9,2": { - "contents": "o" - } - }, - "cursor_position": [ - 23, - 3 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/1.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/1.typescript deleted file mode 100644 index d851739d9f406..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/1.typescript +++ /dev/null @@ -1,24 +0,0 @@ -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo -foo \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/2.json b/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/2.json deleted file mode 100644 index d2c2e33d90ae3..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/2.json +++ /dev/null @@ -1,228 +0,0 @@ -{ - "contents": "foo\nfoo\nfoo \nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo\nfoo", - "cells": { - "0,0": { - "contents": "f" - }, - "0,1": { - "contents": "o" - }, - "0,2": { - "contents": "o" - }, - "1,0": { - "contents": "f" - }, - "1,1": { - "contents": "o" - }, - "1,2": { - "contents": "o" - }, - "10,0": { - "contents": "f" - }, - "10,1": { - "contents": "o" - }, - "10,2": { - "contents": "o" - }, - "11,0": { - "contents": "f" - }, - "11,1": { - "contents": "o" - }, - "11,2": { - "contents": "o" - }, - "12,0": { - "contents": "f" - }, - "12,1": { - "contents": "o" - }, - "12,2": { - "contents": "o" - }, - "13,0": { - "contents": "f" - }, - "13,1": { - "contents": "o" - }, - "13,2": { - "contents": "o" - }, - "14,0": { - "contents": "f" - }, - "14,1": { - "contents": "o" - }, - "14,2": { - "contents": "o" - }, - "15,0": { - "contents": "f" - }, - "15,1": { - "contents": "o" - }, - "15,2": { - "contents": "o" - }, - "16,0": { - "contents": "f" - }, - "16,1": { - "contents": "o" - }, - "16,2": { - "contents": "o" - }, - "17,0": { - "contents": "f" - }, - "17,1": { - "contents": "o" - }, - "17,2": { - "contents": "o" - }, - "18,0": { - "contents": "f" - }, - "18,1": { - "contents": "o" - }, - "18,2": { - "contents": "o" - }, - "19,0": { - "contents": "f" - }, - "19,1": { - "contents": "o" - }, - "19,2": { - "contents": "o" - }, - "2,0": { - "contents": "f" - }, - "2,1": { - "contents": "o" - }, - "2,2": { - "contents": "o" - }, - "2,79": { - "contents": " " - }, - "20,0": { - "contents": "f" - }, - "20,1": { - "contents": "o" - }, - "20,2": { - "contents": "o" - }, - "21,0": { - "contents": "f" - }, - "21,1": { - "contents": "o" - }, - "21,2": { - "contents": "o" - }, - "22,0": { - "contents": "f" - }, - "22,1": { - "contents": "o" - }, - "22,2": { - "contents": "o" - }, - "23,0": { - "contents": "f" - }, - "23,1": { - "contents": "o" - }, - "23,2": { - "contents": "o" - }, - "3,0": { - "contents": "f" - }, - "3,1": { - "contents": "o" - }, - "3,2": { - "contents": "o" - }, - "4,0": { - "contents": "f" - }, - "4,1": { - "contents": "o" - }, - "4,2": { - "contents": "o" - }, - "5,0": { - "contents": "f" - }, - "5,1": { - "contents": "o" - }, - "5,2": { - "contents": "o" - }, - "6,0": { - "contents": "f" - }, - "6,1": { - "contents": "o" - }, - "6,2": { - "contents": "o" - }, - "7,0": { - "contents": "f" - }, - "7,1": { - "contents": "o" - }, - "7,2": { - "contents": "o" - }, - "8,0": { - "contents": "f" - }, - "8,1": { - "contents": "o" - }, - "8,2": { - "contents": "o" - }, - "9,0": { - "contents": "f" - }, - "9,1": { - "contents": "o" - }, - "9,2": { - "contents": "o" - } - }, - "cursor_position": [ - 2, - 80 - ] -} \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/2.typescript b/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/2.typescript deleted file mode 100644 index 4eee0a4de4dac..0000000000000 --- a/crates/turborepo-vt100/tests/data/fixtures/wrap_weird/2.typescript +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/crates/turborepo-vt100/tests/data/weechat.typescript b/crates/turborepo-vt100/tests/data/weechat.typescript deleted file mode 100644 index 1082b1c4abcd3..0000000000000 --- a/crates/turborepo-vt100/tests/data/weechat.typescript +++ /dev/null @@ -1,35 +0,0 @@ -Script started on Sat 04 Jun 2016 01:31:36 AM EDT -Xander: Y'know, this might go a lot faster if you femmes actually picked up a shovel, too. -Giles: Hear, hear. -Buffy: Sorry, but I'm an old fashioned gal. I was raised to believe that men dig up the corpses and the women have the babies. - --Episode #2.2, "Some Assembly Required" -% ]0;doy@lance:~  (~) --------------------------------------------------------------------------------------------------------------------------------------------------------- {--<=======} doy@lance [01:31:36] -000 $(B [?2004hcchchachat[?2004l -[?1049h(B>[?25h[?1000l[?1002l[?1006l[?1005l]2;chat:0:WeeChat 1.5 - "WeeChat 1.5" [?25l 1(B#tw(B│(BBitlBee groupchat: "twitter/timeline". Please keep in mind that root-commands won't work here. Have fun! (B 2(B##c(B│(B │(B-- Chatters -----(B 3(B##c(B│(B01:12:56 <(Bgenehack(B>(B [(B70](B RT @wkamaubell: “I ain’t got no quarrel with them Viet Cong. No Viet Cong ever called me nigger.†│(Bgenehack(B (B 4(B##c(B│(B01:12:56 <(Bgenehack(B>(B - Muhammad Ali https://t.co/LEOnx2objr │(B-----------------(B 5(Bbit(B│(B01:14:08 <(Bgenehack(B>(B [(B71](B RT @AndyCole84: @mma_gifs_ Slowed down its' even more insane. https://t.co/uFxovzJVAO │(B@(Bdoy - 6(B&bi(B│(B01:15:06 <(Bgenehack(B>(B [(B72](B RT @postsecret: Muhammad Ali │(B@(Broot - 7(B?Se(B│(B01:15:06 <(Bgenehack(B>(B RIP GOAT https://t.co/eQUpWkyGND │ (B__upasana__ - 8(B?Ch(B│(B01:15:39 <(Bgenehack(B>(B [(B73](B RT @PenofUmar: White America hated Ali. Then loved him. A commitment to truth and justice attracts even the haters. #MuhammedAli #RIPAli │ (B_jak - 9(B?ge(B│(B01:16:11 <(Bgenehack(B>(B [(B74](B RT @owillis: lets also remember muhammad ali wasn't some apolitical santa claus figure either. https://t.co/tZyppQ3F0E │ (B_vhf -10(B?sa(B│(B │ (BAdrianFeniXx -11(B?th(B│(B01:16:27 <(Bgenehack(B>(B [(B75](B RT @BarefootBoomer: Hopefully you know at least one now. │ (Bamygdalama -12(B##c(B│(B01:16:27 <(Bgenehack(B>(B He was the greatest. │ (Bantifuchs -13(B##i(B│(B01:16:27 <(Bgenehack(B>(B #MuhammadAli https://t.co/xnuOgAnotJ │ (Banyharder -14(B?Pl(B│(B01:16:31 <(Bhypatiadotca(B>(B [(B76](B "Cassius Clay" was what my dad's childhood ski racing rivals called him, which I always thought was a gr8 lesson in saying "fuck the │ (Baphyr - │(B haters" │ (Bashedryden - │(B01:17:08 <(Bgenehack(B>(B [(B77](B RT @ChrisKorman: It's hard not to feel like maybe we lost Ali at precisely the moment when this country needs what he stood for more than │ (Bavibryant - │(B it ever has. │ (Bawwaiid - │(B01:18:33 <(Bgenehack(B>(B [(B78](B Jesus Fucking Christ. [@BuzzFeedAndrew: https://t.co/U0UJGT0BnF ] │ (Bb0rk - │(B01:19:27 <(Bgenehack(B>(B [(B79](B RT @brianwisti: Never been one for sports. Really not boxing. But since age 7 I knew who Ali was, and that he was a man to be respected. │ (Bballingt - │(B01:19:53 <(Bgenehack(B>(B [(B7a](B RT @BaltoSpectator: Legends live forever... #MyHeroes #MuhammadAli #MalcolmX https://t.co/ARfs2cqNgf │ (Bbrainwane - │(B01:20:22 <(Bgenehack(B>(B [(B7b](B RT @BeeJanay: Muhammad Ali, the black Muslim athlete to tell America "no." 💪🾠https://t.co/hIbAsVrFHy │ (Bchimeracoder - │(B01:21:50 <(Bgenehack(B>(B [(B7c](B RT @JamesPMorrison: https://t.co/DN8Ca1A5nI │ (Bcodexjourneys - │(B01:22:14 <(Bgenehack(B>(B [(B7d](B RT @tcarmody: Ali shows what's still true. Want to infuriate the most people? Refuse to pretend that their unfair world is fair, just │ (Bcollision - │(B because they say so. │ (Bcomonad - │(B01:22:44 <(Bgenehack(B>(B [(B7e](B RT @PaddydubPatrick: Let this sink in https://t.co/S8DhtV5onI │ (Bconnor_osborn - │(B01:26:58 <(Bgenehack(B>(B [(B7f](B Drinking a Sticky Hands by @block15brewing @ GenehackHomestead — https://t.co/fyF9cDKv1O #photo │ (Bcrawl_offtopic - │(B01:28:31 <(Bgenehack(B>(B [(B80](B RT @saladinahmed: pro-Black. │ (Bcrawlcode - │(B01:28:31 <(Bgenehack(B>(B anti-war. │ (BDanielleSucher - │(B01:28:31 <(Bgenehack(B>(B defiantly Muslim. │ (Bdewche_man - │(B01:28:31 <(Bgenehack(B>(B │ (Bdylan_hardison - │(B01:28:31 <(Bgenehack(B>(B don't let them sell you any other story. │ (Beronarn ++(B │[(B01:31](B [(Birc/(Bbitlbee](B 1(B:#twitter_doyster(B{(B105}(B (B │(B[(B@(Bdoy(B((BRs)](B - │-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------(B │(B01:31:12 4(B <Jorgrell(B> mahalanobis (L16 TrMo) reached level 4 of the Swamp. (Swamp:4)  │(B01:31:29 4(B <Rotatell(B> Nanomashoes (L27 MiFi) killed Dispater. (Dis:7)  │(B01:31:35 4(B <Rotatell(B> Nanomashoes (L27 MiFi) found an iron rune of Zot. (Dis:7)  diff --git a/crates/turborepo-vt100/tests/entire_screen.rs b/crates/turborepo-vt100/tests/entire_screen.rs deleted file mode 100644 index 2956eaad6f163..0000000000000 --- a/crates/turborepo-vt100/tests/entire_screen.rs +++ /dev/null @@ -1,33 +0,0 @@ -use turborepo_vt100 as vt100; - -#[test] -fn test_screen_includes_scrollback() { - let mut parser = vt100::Parser::new(2, 20, 100); - parser.process(b"foo\r\nbar\r\nbaz\r\n"); - let screen = parser.entire_screen(); - assert_eq!(screen.contents(), "foo\nbar\nbaz"); - assert_eq!(screen.size(), (3, 20)); -} - -#[test] -fn test_screen_trims_trailing_blank_lines() { - let mut parser = vt100::Parser::new(8, 20, 0); - parser.process(b"foo\r\nbar\r\n"); - let screen = parser.entire_screen(); - assert_eq!(screen.contents(), "foo\nbar"); - assert_eq!(screen.size(), (2, 20)); -} - -#[test] -fn test_wrapped_lines_size() { - let mut parser = vt100::Parser::new(8, 8, 10); - parser.process(b"one long line\r\nbar\r\n"); - let screen = parser.entire_screen(); - assert_eq!(screen.contents(), "one long line\nbar"); - assert_eq!(screen.size(), (3, 8)); - assert_eq!(screen.cell(0, 0).unwrap().contents(), "o"); - assert_eq!(screen.cell(1, 0).unwrap().contents(), " "); - // "one long line" - // ^ last char that fits on line, rest will appear on next row - assert_eq!(screen.cell(2, 0).unwrap().contents(), "b"); -} diff --git a/crates/turborepo-vt100/tests/escape.rs b/crates/turborepo-vt100/tests/escape.rs deleted file mode 100644 index b6877571c9316..0000000000000 --- a/crates/turborepo-vt100/tests/escape.rs +++ /dev/null @@ -1,65 +0,0 @@ -use turborepo_vt100 as vt100; - -mod helpers; - -#[test] -fn deckpam() { - helpers::fixture("deckpam"); -} - -#[test] -fn ri() { - helpers::fixture("ri"); -} - -#[test] -fn ris() { - helpers::fixture("ris"); -} - -#[test] -fn vb() { - struct State { - vb: usize, - } - - impl vt100::Callbacks for State { - fn visual_bell(&mut self, _: &mut vt100::Screen) { - self.vb += 1; - } - } - - let mut parser = vt100::Parser::default(); - let mut state = State { vb: 0 }; - assert_eq!(state.vb, 0); - - let screen = parser.screen().clone(); - parser.process_cb(b"\x1bg", &mut state); - assert_eq!(state.vb, 1); - assert_eq!(parser.screen().contents_diff(&screen), b""); - - let screen = parser.screen().clone(); - parser.process_cb(b"\x1bg", &mut state); - assert_eq!(state.vb, 2); - assert_eq!(parser.screen().contents_diff(&screen), b""); - - let screen = parser.screen().clone(); - parser.process_cb(b"\x1bg\x1bg\x1bg", &mut state); - assert_eq!(state.vb, 5); - assert_eq!(parser.screen().contents_diff(&screen), b""); - - let screen = parser.screen().clone(); - parser.process_cb(b"foo", &mut state); - assert_eq!(state.vb, 5); - assert_eq!(parser.screen().contents_diff(&screen), b"foo"); - - let screen = parser.screen().clone(); - parser.process_cb(b"ba\x1bgr", &mut state); - assert_eq!(state.vb, 6); - assert_eq!(parser.screen().contents_diff(&screen), b"bar"); -} - -#[test] -fn decsc() { - helpers::fixture("decsc"); -} diff --git a/crates/turborepo-vt100/tests/helpers/fixtures.rs b/crates/turborepo-vt100/tests/helpers/fixtures.rs deleted file mode 100644 index 381a1851b241d..0000000000000 --- a/crates/turborepo-vt100/tests/helpers/fixtures.rs +++ /dev/null @@ -1,319 +0,0 @@ -use turborepo_vt100 as vt100; - -use serde::de::Deserialize as _; -use std::io::Read as _; - -#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)] -pub struct FixtureCell { - contents: String, - #[serde(default, skip_serializing_if = "is_default")] - is_wide: bool, - #[serde(default, skip_serializing_if = "is_default")] - is_wide_continuation: bool, - #[serde( - default, - deserialize_with = "deserialize_color", - serialize_with = "serialize_color", - skip_serializing_if = "is_default" - )] - fgcolor: vt100::Color, - #[serde( - default, - deserialize_with = "deserialize_color", - serialize_with = "serialize_color", - skip_serializing_if = "is_default" - )] - bgcolor: vt100::Color, - #[serde(default, skip_serializing_if = "is_default")] - bold: bool, - #[serde(default, skip_serializing_if = "is_default")] - italic: bool, - #[serde(default, skip_serializing_if = "is_default")] - underline: bool, - #[serde(default, skip_serializing_if = "is_default")] - inverse: bool, -} - -impl FixtureCell { - #[allow(dead_code)] - pub fn from_cell(cell: &vt100::Cell) -> Self { - Self { - contents: cell.contents().to_string(), - is_wide: cell.is_wide(), - is_wide_continuation: cell.is_wide_continuation(), - fgcolor: cell.fgcolor(), - bgcolor: cell.bgcolor(), - bold: cell.bold(), - italic: cell.italic(), - underline: cell.underline(), - inverse: cell.inverse(), - } - } -} - -#[derive(Debug, serde::Deserialize, serde::Serialize)] -pub struct FixtureScreen { - contents: String, - cells: std::collections::BTreeMap, - cursor_position: (u16, u16), - #[serde(default, skip_serializing_if = "is_default")] - title: String, - #[serde(default, skip_serializing_if = "is_default")] - icon_name: String, - #[serde(default, skip_serializing_if = "is_default")] - application_keypad: bool, - #[serde(default, skip_serializing_if = "is_default")] - application_cursor: bool, - #[serde(default, skip_serializing_if = "is_default")] - hide_cursor: bool, - #[serde(default, skip_serializing_if = "is_default")] - bracketed_paste: bool, - #[serde( - default, - deserialize_with = "deserialize_mouse_protocol_mode", - serialize_with = "serialize_mouse_protocol_mode", - skip_serializing_if = "is_default" - )] - mouse_protocol_mode: vt100::MouseProtocolMode, - #[serde( - default, - deserialize_with = "deserialize_mouse_protocol_encoding", - serialize_with = "serialize_mouse_protocol_encoding", - skip_serializing_if = "is_default" - )] - mouse_protocol_encoding: vt100::MouseProtocolEncoding, -} - -impl FixtureScreen { - fn load(r: R) -> Self { - serde_json::from_reader(r).unwrap() - } - - #[allow(dead_code)] - pub fn from_screen(screen: &vt100::Screen) -> Self { - let empty_screen = vt100::Parser::default().screen().clone(); - let empty_cell = empty_screen.cell(0, 0).unwrap(); - let mut cells = std::collections::BTreeMap::new(); - let (rows, cols) = screen.size(); - for row in 0..rows { - for col in 0..cols { - let cell = screen.cell(row, col).unwrap(); - if cell != empty_cell { - cells.insert( - format!("{row},{col}"), - FixtureCell::from_cell(cell), - ); - } - } - } - Self { - contents: screen.contents(), - cells, - cursor_position: screen.cursor_position(), - title: screen.title().to_string(), - icon_name: screen.icon_name().to_string(), - application_keypad: screen.application_keypad(), - application_cursor: screen.application_cursor(), - hide_cursor: screen.hide_cursor(), - bracketed_paste: screen.bracketed_paste(), - mouse_protocol_mode: screen.mouse_protocol_mode(), - mouse_protocol_encoding: screen.mouse_protocol_encoding(), - } - } -} - -fn is_default(t: &T) -> bool { - t == &T::default() -} - -fn deserialize_color<'a, D>( - deserializer: D, -) -> std::result::Result -where - D: serde::de::Deserializer<'a>, -{ - let val = >::deserialize(deserializer)?; - match val { - None => Ok(vt100::Color::Default), - Some(x) if x.starts_with('#') => { - let x = x.as_bytes(); - if x.len() != 7 { - return Err(serde::de::Error::custom("invalid rgb color")); - } - let r = - super::hex(x[1], x[2]).map_err(serde::de::Error::custom)?; - let g = - super::hex(x[3], x[4]).map_err(serde::de::Error::custom)?; - let b = - super::hex(x[5], x[6]).map_err(serde::de::Error::custom)?; - Ok(vt100::Color::Rgb(r, g, b)) - } - Some(x) => Ok(vt100::Color::Idx( - x.parse().map_err(serde::de::Error::custom)?, - )), - } -} - -fn serialize_color( - color: &vt100::Color, - serializer: S, -) -> Result -where - S: serde::Serializer, -{ - let s = match color { - vt100::Color::Default => unreachable!(), - vt100::Color::Idx(n) => format!("{n}"), - vt100::Color::Rgb(r, g, b) => format!("#{r:02x}{g:02x}{b:02x}"), - }; - serializer.serialize_str(&s) -} - -fn deserialize_mouse_protocol_mode<'a, D>( - deserializer: D, -) -> std::result::Result -where - D: serde::de::Deserializer<'a>, -{ - let name = ::deserialize(deserializer)?; - match name.as_ref() { - "none" => Ok(vt100::MouseProtocolMode::None), - "press" => Ok(vt100::MouseProtocolMode::Press), - "press_release" => Ok(vt100::MouseProtocolMode::PressRelease), - "button_motion" => Ok(vt100::MouseProtocolMode::ButtonMotion), - "any_motion" => Ok(vt100::MouseProtocolMode::AnyMotion), - _ => unimplemented!(), - } -} - -fn serialize_mouse_protocol_mode( - mode: &vt100::MouseProtocolMode, - serializer: S, -) -> Result -where - S: serde::Serializer, -{ - let s = match mode { - vt100::MouseProtocolMode::None => "none", - vt100::MouseProtocolMode::Press => "press", - vt100::MouseProtocolMode::PressRelease => "press_release", - vt100::MouseProtocolMode::ButtonMotion => "button_motion", - vt100::MouseProtocolMode::AnyMotion => "any_motion", - }; - serializer.serialize_str(s) -} - -fn deserialize_mouse_protocol_encoding<'a, D>( - deserializer: D, -) -> std::result::Result -where - D: serde::de::Deserializer<'a>, -{ - let name = ::deserialize(deserializer)?; - match name.as_ref() { - "default" => Ok(vt100::MouseProtocolEncoding::Default), - "utf8" => Ok(vt100::MouseProtocolEncoding::Utf8), - "sgr" => Ok(vt100::MouseProtocolEncoding::Sgr), - _ => unimplemented!(), - } -} - -fn serialize_mouse_protocol_encoding( - encoding: &vt100::MouseProtocolEncoding, - serializer: S, -) -> Result -where - S: serde::Serializer, -{ - let s = match encoding { - vt100::MouseProtocolEncoding::Default => "default", - vt100::MouseProtocolEncoding::Utf8 => "utf8", - vt100::MouseProtocolEncoding::Sgr => "sgr", - }; - serializer.serialize_str(s) -} - -fn load_input(name: &str, i: usize) -> Option> { - let mut file = std::fs::File::open(format!( - "tests/data/fixtures/{name}/{i}.typescript" - )) - .ok()?; - let mut input = vec![]; - file.read_to_end(&mut input).unwrap(); - Some(input) -} - -fn load_screen(name: &str, i: usize) -> Option { - let mut file = - std::fs::File::open(format!("tests/data/fixtures/{name}/{i}.json")) - .ok()?; - Some(FixtureScreen::load(&mut file)) -} - -fn assert_produces(input: &[u8], expected: &FixtureScreen) { - let mut parser = vt100::Parser::default(); - parser.process(input); - - assert_eq!(parser.screen().contents(), expected.contents); - assert_eq!(parser.screen().cursor_position(), expected.cursor_position); - assert_eq!(parser.screen().title(), expected.title); - assert_eq!(parser.screen().icon_name(), expected.icon_name); - assert_eq!( - parser.screen().application_keypad(), - expected.application_keypad - ); - assert_eq!( - parser.screen().application_cursor(), - expected.application_cursor - ); - assert_eq!(parser.screen().hide_cursor(), expected.hide_cursor); - assert_eq!(parser.screen().bracketed_paste(), expected.bracketed_paste); - assert_eq!( - parser.screen().mouse_protocol_mode(), - expected.mouse_protocol_mode - ); - assert_eq!( - parser.screen().mouse_protocol_encoding(), - expected.mouse_protocol_encoding - ); - - let (rows, cols) = parser.screen().size(); - for row in 0..rows { - for col in 0..cols { - let expected_cell = expected - .cells - .get(&format!("{row},{col}")) - .cloned() - .unwrap_or_default(); - let got_cell = parser.screen().cell(row, col).unwrap(); - assert_eq!(got_cell.contents(), expected_cell.contents); - assert_eq!(got_cell.is_wide(), expected_cell.is_wide); - assert_eq!( - got_cell.is_wide_continuation(), - expected_cell.is_wide_continuation - ); - assert_eq!(got_cell.fgcolor(), expected_cell.fgcolor); - assert_eq!(got_cell.bgcolor(), expected_cell.bgcolor); - assert_eq!(got_cell.bold(), expected_cell.bold); - assert_eq!(got_cell.italic(), expected_cell.italic); - assert_eq!(got_cell.underline(), expected_cell.underline); - assert_eq!(got_cell.inverse(), expected_cell.inverse); - } - } -} - -#[allow(dead_code)] -pub fn fixture(name: &str) { - let mut i = 1; - let mut prev_input = vec![]; - while let Some(input) = load_input(name, i) { - super::assert_reproduces_state_from(&input, &prev_input); - prev_input.extend(input); - - let expected = load_screen(name, i).unwrap(); - assert_produces(&prev_input, &expected); - - i += 1; - } - assert!(i > 1, "couldn't find fixtures to test"); -} diff --git a/crates/turborepo-vt100/tests/helpers/mod.rs b/crates/turborepo-vt100/tests/helpers/mod.rs deleted file mode 100644 index b45dae43997ce..0000000000000 --- a/crates/turborepo-vt100/tests/helpers/mod.rs +++ /dev/null @@ -1,352 +0,0 @@ -#![allow(unused_imports)] -mod fixtures; -pub use fixtures::fixture; -pub use fixtures::FixtureScreen; - -use turborepo_vt100 as vt100; - -pub static mut QUIET: bool = false; - -macro_rules! is { - ($got:expr, $expected:expr) => { - if ($got) != ($expected) { - if !unsafe { QUIET } { - eprintln!( - "{} != {}:", - stringify!($got), - stringify!($expected) - ); - eprintln!(" got: {:?}", $got); - eprintln!("expected: {:?}", $expected); - } - return false; - } - }; -} -macro_rules! ok { - ($e:expr) => { - if !($e) { - if !unsafe { QUIET } { - eprintln!("!{}", stringify!($e)); - } - return false; - } - }; -} - -#[derive(Eq, PartialEq)] -struct Bytes<'a>(&'a [u8]); - -impl<'a> std::fmt::Debug for Bytes<'a> { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> Result<(), std::fmt::Error> { - f.write_str("b\"")?; - for c in self.0 { - match c { - 10 => f.write_str("\\n")?, - 13 => f.write_str("\\r")?, - 92 => f.write_str("\\\\")?, - 32..=126 => f.write_str(&char::from(*c).to_string())?, - _ => f.write_fmt(format_args!("\\x{c:02x}"))?, - } - } - f.write_str("\"")?; - Ok(()) - } -} - -pub fn compare_screens( - got: &vt100::Screen, - expected: &vt100::Screen, -) -> bool { - let (rows, cols) = got.size(); - - is!(got.contents(), expected.contents()); - is!( - Bytes(&got.contents_formatted()), - Bytes(&expected.contents_formatted()) - ); - for (got_row, expected_row) in - got.rows(0, cols).zip(expected.rows(0, cols)) - { - is!(got_row, expected_row); - } - for (got_row, expected_row) in got - .rows_formatted(0, cols) - .zip(expected.rows_formatted(0, cols)) - { - is!(Bytes(&got_row), Bytes(&expected_row)); - } - for i in 0..rows { - is!(got.row_wrapped(i), expected.row_wrapped(i)); - } - is!( - Bytes(&got.contents_diff(vt100::Parser::default().screen())), - Bytes(&expected.contents_diff(vt100::Parser::default().screen())) - ); - - is!(Bytes(&got.contents_diff(got)), Bytes(b"")); - - for row in 0..rows { - for col in 0..cols { - let expected_cell = expected.cell(row, col); - let got_cell = got.cell(row, col); - is!(got_cell, expected_cell); - } - } - - is!(got.cursor_position(), expected.cursor_position()); - ok!(got.cursor_position().0 <= rows); - ok!(expected.cursor_position().0 <= rows); - ok!(got.cursor_position().1 <= cols); - ok!(expected.cursor_position().1 <= cols); - - is!(got.title(), expected.title()); - is!(got.icon_name(), expected.icon_name()); - - is!(got.application_keypad(), expected.application_keypad()); - is!(got.application_cursor(), expected.application_cursor()); - is!(got.hide_cursor(), expected.hide_cursor()); - is!(got.bracketed_paste(), expected.bracketed_paste()); - is!(got.mouse_protocol_mode(), expected.mouse_protocol_mode()); - is!( - got.mouse_protocol_encoding(), - expected.mouse_protocol_encoding() - ); - - true -} - -pub fn contents_formatted_reproduces_state(input: &[u8]) -> bool { - let mut parser = vt100::Parser::default(); - parser.process(input); - contents_formatted_reproduces_screen(parser.screen()) -} - -pub fn rows_formatted_reproduces_state(input: &[u8]) -> bool { - let mut parser = vt100::Parser::default(); - parser.process(input); - rows_formatted_reproduces_screen(parser.screen()) -} - -pub fn contents_formatted_reproduces_screen(screen: &vt100::Screen) -> bool { - let mut new_input = screen.contents_formatted(); - new_input.extend(screen.input_mode_formatted()); - new_input.extend(screen.title_formatted()); - assert_eq!(new_input, screen.state_formatted()); - let mut new_parser = vt100::Parser::default(); - new_parser.process(&new_input); - let got_screen = new_parser.screen().clone(); - - compare_screens(&got_screen, screen) -} - -pub fn rows_formatted_reproduces_screen(screen: &vt100::Screen) -> bool { - let mut new_input = vec![]; - let mut wrapped = false; - for (idx, row) in screen.rows_formatted(0, 80).enumerate() { - new_input.extend(b"\x1b[m"); - if !wrapped { - new_input.extend(format!("\x1b[{}H", idx + 1).as_bytes()); - } - new_input.extend(row); - wrapped = screen.row_wrapped(idx.try_into().unwrap()); - } - new_input.extend(b"\x1b[m"); - new_input.extend(screen.cursor_state_formatted()); - new_input.extend(screen.attributes_formatted()); - new_input.extend(screen.input_mode_formatted()); - new_input.extend(screen.title_formatted()); - let mut new_parser = vt100::Parser::default(); - new_parser.process(&new_input); - let got_screen = new_parser.screen().clone(); - - compare_screens(&got_screen, screen) -} - -fn assert_contents_formatted_reproduces_state(input: &[u8]) { - assert!(contents_formatted_reproduces_state(input)); -} - -fn assert_rows_formatted_reproduces_state(input: &[u8]) { - assert!(rows_formatted_reproduces_state(input)); -} - -#[allow(dead_code)] -pub fn contents_diff_reproduces_state(input: &[u8]) -> bool { - contents_diff_reproduces_state_from(input, &[]) -} - -pub fn contents_diff_reproduces_state_from( - input: &[u8], - prev_input: &[u8], -) -> bool { - let mut parser = vt100::Parser::default(); - parser.process(prev_input); - let prev_screen = parser.screen().clone(); - parser.process(input); - - contents_diff_reproduces_state_from_screens(&prev_screen, parser.screen()) -} - -pub fn contents_diff_reproduces_state_from_screens( - prev_screen: &vt100::Screen, - screen: &vt100::Screen, -) -> bool { - let mut diff_input = screen.contents_diff(prev_screen); - diff_input.extend(screen.input_mode_diff(prev_screen)); - diff_input.extend(screen.title_diff(prev_screen)); - assert_eq!(diff_input, screen.state_diff(prev_screen)); - - let mut diff_prev_input = prev_screen.contents_formatted(); - diff_prev_input.extend(screen.input_mode_formatted()); - diff_prev_input.extend(screen.title_formatted()); - - let mut new_parser = vt100::Parser::default(); - new_parser.process(&diff_prev_input); - new_parser.process(&diff_input); - let got_screen = new_parser.screen().clone(); - - compare_screens(&got_screen, screen) -} - -#[allow(dead_code)] -pub fn assert_contents_diff_reproduces_state_from_screens( - prev_screen: &vt100::Screen, - screen: &vt100::Screen, -) { - assert!(contents_diff_reproduces_state_from_screens( - prev_screen, - screen, - )); -} - -fn assert_contents_diff_reproduces_state_from( - input: &[u8], - prev_input: &[u8], -) { - assert!(contents_diff_reproduces_state_from(input, prev_input)); -} - -#[allow(dead_code)] -pub fn assert_reproduces_state(input: &[u8]) { - assert_reproduces_state_from(input, &[]); -} - -pub fn assert_reproduces_state_from(input: &[u8], prev_input: &[u8]) { - let full_input: Vec<_> = - prev_input.iter().chain(input.iter()).copied().collect(); - assert_contents_formatted_reproduces_state(&full_input); - assert_rows_formatted_reproduces_state(&full_input); - assert_contents_diff_reproduces_state_from(input, prev_input); -} - -#[allow(dead_code)] -pub fn format_bytes(bytes: &[u8]) -> String { - let mut v = vec![]; - for b in bytes { - match *b { - 10 => v.extend(b"\\n"), - 13 => v.extend(b"\\r"), - 27 => v.extend(b"\\e"), - c if c < 32 || c == 127 => { - v.extend(format!("\\x{c:02x}").as_bytes()) - } - b => v.push(b), - } - } - String::from_utf8_lossy(&v).to_string() -} - -fn hex_char(c: u8) -> Result { - match c { - b'0' => Ok(0), - b'1' => Ok(1), - b'2' => Ok(2), - b'3' => Ok(3), - b'4' => Ok(4), - b'5' => Ok(5), - b'6' => Ok(6), - b'7' => Ok(7), - b'8' => Ok(8), - b'9' => Ok(9), - b'a' => Ok(10), - b'b' => Ok(11), - b'c' => Ok(12), - b'd' => Ok(13), - b'e' => Ok(14), - b'f' => Ok(15), - b'A' => Ok(10), - b'B' => Ok(11), - b'C' => Ok(12), - b'D' => Ok(13), - b'E' => Ok(14), - b'F' => Ok(15), - _ => Err("invalid hex char".to_string()), - } -} - -pub fn hex(upper: u8, lower: u8) -> Result { - Ok(hex_char(upper)? * 16 + hex_char(lower)?) -} - -#[allow(dead_code)] -pub fn unhex(s: &[u8]) -> Vec { - let mut ret = vec![]; - let mut i = 0; - while i < s.len() { - if s[i] == b'\\' { - match s[i + 1] { - b'\\' => { - ret.push(b'\\'); - i += 2; - } - b'x' => { - let upper = s[i + 2]; - let lower = s[i + 3]; - ret.push(hex(upper, lower).unwrap()); - i += 4; - } - b'u' => { - assert_eq!(s[i + 2], b'{'); - let mut digits = vec![]; - let mut j = i + 3; - while s[j] != b'}' { - digits.push(s[j]); - j += 1; - } - let digits: Vec<_> = digits - .iter() - .copied() - .skip_while(|x| x == &b'0') - .collect(); - let digits = String::from_utf8(digits).unwrap(); - let codepoint = u32::from_str_radix(&digits, 16).unwrap(); - let c = char::try_from(codepoint).unwrap(); - let mut bytes = [0; 4]; - ret.extend(c.encode_utf8(&mut bytes).bytes()); - i = j + 1; - } - b'r' => { - ret.push(0x0d); - i += 2; - } - b'n' => { - ret.push(0x0a); - i += 2; - } - b't' => { - ret.push(0x09); - i += 2; - } - _ => panic!("invalid escape"), - } - } else { - ret.push(s[i]); - i += 1; - } - } - ret -} diff --git a/crates/turborepo-vt100/tests/init.rs b/crates/turborepo-vt100/tests/init.rs deleted file mode 100644 index f144826e61b33..0000000000000 --- a/crates/turborepo-vt100/tests/init.rs +++ /dev/null @@ -1,39 +0,0 @@ -use turborepo_vt100 as vt100; - -#[test] -fn init() { - let parser = vt100::Parser::default(); - assert_eq!(parser.screen().size(), (24, 80)); - assert_eq!(parser.screen().cursor_position(), (0, 0)); - - let cell = parser.screen().cell(0, 0); - assert_eq!(cell.unwrap().contents(), ""); - let cell = parser.screen().cell(23, 79); - assert_eq!(cell.unwrap().contents(), ""); - let cell = parser.screen().cell(24, 0); - assert!(cell.is_none()); - let cell = parser.screen().cell(0, 80); - assert!(cell.is_none()); - - assert_eq!(parser.screen().contents(), ""); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J" - ); - - assert_eq!(parser.screen().title(), ""); - assert_eq!(parser.screen().icon_name(), ""); - - assert!(!parser.screen().application_keypad()); - assert!(!parser.screen().application_cursor()); - assert!(!parser.screen().hide_cursor()); - assert!(!parser.screen().bracketed_paste()); - assert_eq!( - parser.screen().mouse_protocol_mode(), - vt100::MouseProtocolMode::None - ); - assert_eq!( - parser.screen().mouse_protocol_encoding(), - vt100::MouseProtocolEncoding::Default - ); -} diff --git a/crates/turborepo-vt100/tests/mode.rs b/crates/turborepo-vt100/tests/mode.rs deleted file mode 100644 index d09054da8b15a..0000000000000 --- a/crates/turborepo-vt100/tests/mode.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod helpers; - -#[test] -fn modes() { - helpers::fixture("modes"); -} - -#[test] -fn alternate_buffer() { - helpers::fixture("alternate_buffer"); -} diff --git a/crates/turborepo-vt100/tests/osc.rs b/crates/turborepo-vt100/tests/osc.rs deleted file mode 100644 index 8a7ec429d1f13..0000000000000 --- a/crates/turborepo-vt100/tests/osc.rs +++ /dev/null @@ -1,21 +0,0 @@ -mod helpers; - -#[test] -fn title() { - helpers::fixture("title"); -} - -#[test] -fn icon_name() { - helpers::fixture("icon_name"); -} - -#[test] -fn title_icon_name() { - helpers::fixture("title_icon_name"); -} - -#[test] -fn unknown_osc() { - helpers::fixture("unknown_osc"); -} diff --git a/crates/turborepo-vt100/tests/processing.rs b/crates/turborepo-vt100/tests/processing.rs deleted file mode 100644 index f109e48c450ee..0000000000000 --- a/crates/turborepo-vt100/tests/processing.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod helpers; - -#[test] -fn split_escape_sequences() { - helpers::fixture("split_escape_sequences"); -} - -#[test] -fn split_utf8() { - helpers::fixture("split_utf8"); -} diff --git a/crates/turborepo-vt100/tests/quickcheck.rs b/crates/turborepo-vt100/tests/quickcheck.rs deleted file mode 100644 index 56109349a933d..0000000000000 --- a/crates/turborepo-vt100/tests/quickcheck.rs +++ /dev/null @@ -1,153 +0,0 @@ -use quickcheck::Arbitrary as _; - -mod helpers; - -#[derive(Clone, Debug)] -struct TerminalInput(Vec); - -fn gen_range(gen: &mut quickcheck::Gen, range: std::ops::Range) -> T -where - T: Copy, - T: quickcheck::Arbitrary, - T: std::ops::Add - + std::ops::Rem - + std::ops::Sub, -{ - T::arbitrary(gen) % (range.end - range.start) + range.start -} - -impl quickcheck::Arbitrary for TerminalInput { - fn arbitrary(g: &mut quickcheck::Gen) -> Self { - let size = { - let s = g.size(); - gen_range(g, 0..s) - }; - TerminalInput( - (0..size) - .flat_map(|_| choose_terminal_input_fragment(g)) - .collect(), - ) - } - - fn shrink(&self) -> Box> { - Box::new(self.0.shrink().map(TerminalInput)) - } -} - -fn choose_terminal_input_fragment(g: &mut quickcheck::Gen) -> Vec { - #[derive(Clone)] - enum Fragment { - Text, - Control, - Escape, - Csi, - #[allow(dead_code)] - Osc, - #[allow(dead_code)] - Dcs, - } - - impl quickcheck::Arbitrary for Fragment { - fn arbitrary(g: &mut quickcheck::Gen) -> Self { - match u8::arbitrary(g) { - 0u8..=231 => Fragment::Text, - 232..=239 => Fragment::Control, - 240..=247 => Fragment::Escape, - 248..=255 => Fragment::Csi, - } - } - } - - match Fragment::arbitrary(g) { - Fragment::Text => { - let mut u: u32 = gen_range(g, 32..(2u32.pow(20) - 2048)); - // surrogates aren't valid codepoints on their own - if u >= 0xD800 { - u += 2048; - } - let c: Result = std::convert::TryFrom::try_from(u); - let c = match c { - Ok(c) => c, - Err(e) => panic!("failed to create char from {u}: {e}"), - }; - let mut b = [0; 4]; - let s = c.encode_utf8(&mut b); - (*s).to_string().into_bytes() - } - Fragment::Control => vec![gen_range(g, 7..14)], - Fragment::Escape => { - let mut v = vec![0x1b]; - let c = gen_range(g, b'0'..b'~'); - v.push(c); - v - } - Fragment::Csi => { - let mut v = vec![0x1b, b'[']; - // TODO: params - let c = gen_range(g, b'@'..b'~'); - v.push(c); - v - } - Fragment::Osc => { - // TODO - unimplemented!() - } - Fragment::Dcs => { - // TODO - unimplemented!() - } - } - // TODO: sometimes add garbage in random places -} - -fn contents_formatted_reproduces_state_random(input: Vec) -> bool { - helpers::contents_formatted_reproduces_state(&input) -} - -fn contents_formatted_reproduces_state_structured( - input: TerminalInput, -) -> bool { - helpers::contents_formatted_reproduces_state(&input.0) -} - -#[test] -#[ignore] -fn qc_structured_long() { - let mut qc = quickcheck::QuickCheck::new() - .tests(1_000_000) - .max_tests(1_000_000); - qc.quickcheck( - contents_formatted_reproduces_state_structured - as fn(TerminalInput) -> bool, - ); -} - -#[test] -fn qc_structured_short() { - let mut qc = quickcheck::QuickCheck::new().tests(1_000).max_tests(1_000); - qc.quickcheck( - contents_formatted_reproduces_state_structured - as fn(TerminalInput) -> bool, - ); -} - -#[test] -#[ignore] -fn qc_random_long() { - let mut qc = quickcheck::QuickCheck::new() - .tests(10_000_000) - .max_tests(10_000_000); - qc.quickcheck( - contents_formatted_reproduces_state_random as fn(Vec) -> bool, - ); -} - -#[test] -fn qc_random_short() { - let mut qc = quickcheck::QuickCheck::new() - .tests(10_000) - .max_tests(10_000); - qc.quickcheck( - contents_formatted_reproduces_state_random as fn(Vec) -> bool, - ); -} diff --git a/crates/turborepo-vt100/tests/scroll.rs b/crates/turborepo-vt100/tests/scroll.rs deleted file mode 100644 index 0c957e4acdb44..0000000000000 --- a/crates/turborepo-vt100/tests/scroll.rs +++ /dev/null @@ -1,136 +0,0 @@ -use turborepo_vt100 as vt100; - -mod helpers; - -#[test] -fn scroll_regions() { - helpers::fixture("decstbm"); -} - -#[test] -fn origin_mode() { - helpers::fixture("origin_mode"); -} - -#[test] -fn scrollback() { - let mut parser = vt100::Parser::new(24, 80, 10); - - parser.process(b"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24"); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.process(b"\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30"); - assert_eq!(parser.screen().contents(), "7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30"); - - parser.screen_mut().set_scrollback(0); - assert_eq!(parser.screen().scrollback(), 0); - assert_eq!(parser.screen().contents(), "7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30"); - - parser.screen_mut().set_scrollback(1); - assert_eq!(parser.screen().scrollback(), 1); - assert_eq!(parser.screen().contents(), "6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"); - - parser.screen_mut().set_scrollback(3); - assert_eq!(parser.screen().scrollback(), 3); - assert_eq!(parser.screen().contents(), "4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27"); - - parser.screen_mut().set_scrollback(6); - assert_eq!(parser.screen().scrollback(), 6); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.screen_mut().set_scrollback(7); - assert_eq!(parser.screen().scrollback(), 6); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.screen_mut().set_scrollback(0); - assert_eq!(parser.screen().scrollback(), 0); - assert_eq!(parser.screen().contents(), "7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30"); - - parser.screen_mut().set_scrollback(7); - assert_eq!(parser.screen().scrollback(), 6); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.process(b"\r\n31"); - assert_eq!(parser.screen().scrollback(), 7); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.process(b"\r\n32"); - assert_eq!(parser.screen().scrollback(), 8); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.process(b"\r\n33"); - assert_eq!(parser.screen().scrollback(), 9); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.process(b"\r\n34"); - assert_eq!(parser.screen().scrollback(), 10); - assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24"); - - parser.process(b"\r\n35"); - assert_eq!(parser.screen().scrollback(), 10); - assert_eq!(parser.screen().contents(), "2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25"); - - parser.process(b"\r\n36"); - assert_eq!(parser.screen().scrollback(), 10); - assert_eq!(parser.screen().contents(), "3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26"); - - parser.screen_mut().set_scrollback(12); - assert_eq!(parser.screen().scrollback(), 10); - assert_eq!(parser.screen().contents(), "3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26"); - - parser.screen_mut().set_scrollback(0); - assert_eq!(parser.screen().scrollback(), 0); - assert_eq!(parser.screen().contents(), "13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36"); - - parser.process(b"\r\n37\r\n38"); - assert_eq!(parser.screen().scrollback(), 0); - assert_eq!(parser.screen().contents(), "15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38"); - - parser.screen_mut().set_scrollback(5); - assert_eq!(parser.screen().scrollback(), 5); - assert_eq!(parser.screen().contents(), "10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33"); - - parser.process(b"\r\n39\r\n40"); - assert_eq!(parser.screen().scrollback(), 7); - assert_eq!(parser.screen().contents(), "10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33"); -} - -#[test] -fn edge_of_screen() { - let mut parser = vt100::Parser::default(); - let screen = parser.screen().clone(); - - parser.process(b"\x1b[31m\x1b[24;75Hfooba\x08r\x08\x1b[1@a"); - assert_eq!(parser.screen().cursor_position(), (23, 79)); - assert_eq!(parser.screen().contents(), "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n foobar"); - assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[24;75H\x1b[31mfoobar\x1b[24;80H"[..] - ); - assert_eq!( - parser.screen().contents_diff(&screen), - b"\x1b[24;75H\x1b[31mfoobar\x1b[24;80H" - ); -} - -#[test] -fn scrollback_larger_than_rows() { - let mut parser = vt100::Parser::new(3, 20, 10); - - parser.process(gen_nums(1..=10, "\r\n").as_bytes()); - - // 1. Extra rows returned - parser.screen_mut().set_scrollback(4); - assert_eq!(parser.screen().contents(), gen_nums(4..=6, "\n")); - - // 2. Subtraction overflow - parser.screen_mut().set_scrollback(10); - assert_eq!(parser.screen().contents(), gen_nums(1..=3, "\n")); -} - -fn gen_nums(range: std::ops::RangeInclusive, join: &str) -> String { - range - .map(|num| num.to_string()) - .collect::>() - .join(join) -} diff --git a/crates/turborepo-vt100/tests/select.rs b/crates/turborepo-vt100/tests/select.rs deleted file mode 100644 index f75565af655b4..0000000000000 --- a/crates/turborepo-vt100/tests/select.rs +++ /dev/null @@ -1,139 +0,0 @@ -use turborepo_vt100 as vt100; - -mod helpers; - -// test setting selection -// test copying -// test scrolling with a selection - -#[test] -fn visible() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - // Make sure foo is off the screen - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().set_selection(0, 0, 0, 3); - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar")); - parser.screen_mut().clear_selection(); - assert!(parser.screen().selected_text().is_none()); -} - -#[test] -fn single_cell_selection() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - // Make sure foo is off the screen - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().set_selection(0, 0, 0, 0); - assert_eq!(parser.screen().selected_text().as_deref(), Some("b")); - parser.screen_mut().clear_selection(); - assert!(parser.screen().selected_text().is_none()); -} - -#[test] -fn multiline() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - // Make sure foo is off the screen - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().set_selection(0, 0, 1, 0); - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar\nb")); -} - -#[test] -fn scrolling_keeps_selection() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().set_selection(0, 0, 0, 3); - // Scroll so baz is off the screen - parser.screen_mut().set_scrollback(1); - // Bar should still be selected - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar")); -} - -#[test] -fn adding_keeps_selection() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar"); - parser.screen_mut().set_selection(1, 0, 1, 3); - parser.process(b"\r\nbaz"); - // Bar should still be selected - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar")); -} - -#[test] -fn backwards_selection() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().set_selection(1, 0, 0, 0); - // Bar was selected from below - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar\nb")); -} - -#[test] -fn too_large() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().set_selection(0, 0, 5, 0); - // Entire screen was selected, but nothing extra - assert_eq!( - parser.screen().selected_text().as_deref(), - Some("bar\nbaz\n") - ); -} - -#[test] -fn selection_inversed_display() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - // Make sure foo is off the screen - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().set_selection(0, 0, 0, 3); - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar")); - assert!(parser.screen().cell(0, 0).unwrap().inverse()); - assert!(parser.screen().cell(0, 1).unwrap().inverse()); - assert!(parser.screen().cell(0, 2).unwrap().inverse()); - assert!(parser.screen().cell(0, 3).unwrap().inverse()); -} - -#[test] -fn update_selection_visible() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - // Make sure foo is off the screen - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().update_selection(0, 0); - assert_eq!(parser.screen().selected_text().as_deref(), Some("b")); - parser.screen_mut().update_selection(0, 3); - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar")); - parser.screen_mut().clear_selection(); - assert!(parser.screen().selected_text().is_none()); -} - -#[test] -fn update_selection_scroll() { - let mut parser = vt100::Parser::new(2, 4, 10); - parser.process(b"foo\r\nbar\r\nbaz"); - - // Make sure foo is off the screen - assert_eq!(parser.screen().contents(), "bar\nbaz"); - parser.screen_mut().update_selection(0, 3); - assert_eq!(parser.screen().selected_text().as_deref(), Some("")); - parser.screen_mut().update_selection(0, 0); - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar")); - parser.screen_mut().set_scrollback(1); - assert_eq!(parser.screen().selected_text().as_deref(), Some("bar")); - parser.screen_mut().update_selection(0, 0); - assert_eq!(parser.screen().selected_text().as_deref(), Some("foo\nbar")); -} diff --git a/crates/turborepo-vt100/tests/split-escapes.rs b/crates/turborepo-vt100/tests/split-escapes.rs deleted file mode 100644 index d0eed201d14bd..0000000000000 --- a/crates/turborepo-vt100/tests/split-escapes.rs +++ /dev/null @@ -1,53 +0,0 @@ -use turborepo_vt100 as vt100; - -use std::io::Read as _; - -fn get_file_contents(name: &str) -> Vec { - let mut file = std::fs::File::open(name).unwrap(); - let mut buf = vec![]; - file.read_to_end(&mut buf).unwrap(); - buf -} - -fn write_to_parser(chunks: &mut [Vec]) -> (String, Vec) { - let mut parser = vt100::Parser::new(37, 193, 0); - for chunk in chunks.iter_mut() { - parser.process(chunk); - } - ( - parser.screen().contents(), - parser.screen().contents_formatted(), - ) -} - -fn test_splits(filename: &str, limit: Option) { - let bytes = get_file_contents(filename); - let len = bytes.len(); - let expected = write_to_parser(&mut [bytes.clone()]); - for i in 0..(len - 1) { - if let Some(limit) = limit { - if i > limit { - break; - } - } - let bytes_copy = bytes.clone(); - let (start, end) = bytes_copy.split_at(i); - let mut chunks = vec![start.to_vec(), end.to_vec()]; - let got = write_to_parser(&mut chunks); - assert!( - got == expected, - "failed to render {filename} when split at byte {i}" - ); - } -} - -#[test] -fn split_escapes_weechat() { - test_splits("tests/data/weechat.typescript", Some(500)); -} - -#[test] -#[ignore] -fn split_escapes_weechat_full() { - test_splits("tests/data/weechat.typescript", None); -} diff --git a/crates/turborepo-vt100/tests/text.rs b/crates/turborepo-vt100/tests/text.rs deleted file mode 100644 index e41310075ba68..0000000000000 --- a/crates/turborepo-vt100/tests/text.rs +++ /dev/null @@ -1,36 +0,0 @@ -mod helpers; - -#[test] -fn ascii() { - helpers::fixture("ascii"); -} - -#[test] -fn utf8() { - helpers::fixture("utf8"); -} - -#[test] -fn newlines() { - helpers::fixture("newlines"); -} - -#[test] -fn wide() { - helpers::fixture("wide"); -} - -#[test] -fn combining() { - helpers::fixture("combining"); -} - -#[test] -fn wrap() { - helpers::fixture("wrap"); -} - -#[test] -fn wrap_weird() { - helpers::fixture("wrap_weird"); -} diff --git a/crates/turborepo-vt100/tests/weird.rs b/crates/turborepo-vt100/tests/weird.rs deleted file mode 100644 index 092a2820360ed..0000000000000 --- a/crates/turborepo-vt100/tests/weird.rs +++ /dev/null @@ -1,17 +0,0 @@ -use turborepo_vt100 as vt100; - -mod helpers; - -#[test] -fn intermediate_control() { - helpers::fixture("intermediate_control"); -} - -#[test] -fn params() { - let mut parser = vt100::Parser::default(); - parser.process(b"\x1b[::::::::::::::::::::::::::::::::@"); - parser.process(b"\x1b[::::::::::::::::::::::::::::::::H"); - parser.process(b"\x1b[::::::::::::::::::::::::::::::::r"); - parser.process(b"a\x1b[8888888X"); -} diff --git a/crates/turborepo-vt100/tests/window_contents.rs b/crates/turborepo-vt100/tests/window_contents.rs deleted file mode 100644 index 185c100020fbd..0000000000000 --- a/crates/turborepo-vt100/tests/window_contents.rs +++ /dev/null @@ -1,544 +0,0 @@ -#![allow(unused_imports)] -use turborepo_vt100 as vt100; - -mod helpers; - -use std::io::Read as _; - -#[test] -fn formatted() { - let mut parser = vt100::Parser::default(); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J" - ); - - parser.process(b"foobar"); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert!(!parser.screen().cell(0, 2).unwrap().bold()); - assert!(!parser.screen().cell(0, 3).unwrap().bold()); - assert!(!parser.screen().cell(0, 4).unwrap().bold()); - assert!(!parser.screen().cell(0, 5).unwrap().bold()); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[Jfoobar" - ); - - parser.process(b"\x1b[1;4H\x1b[1;7m\x1b[33mb"); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert!(!parser.screen().cell(0, 2).unwrap().bold()); - assert!(parser.screen().cell(0, 3).unwrap().bold()); - assert!(!parser.screen().cell(0, 4).unwrap().bold()); - assert!(!parser.screen().cell(0, 5).unwrap().bold()); - assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jfoo\x1b[33;1;7mb\x1b[mar\x1b[1;5H\x1b[33;1;7m"[..] - ); - - parser.process(b"\x1b[1;5H\x1b[22;42ma"); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert!(!parser.screen().cell(0, 2).unwrap().bold()); - assert!(parser.screen().cell(0, 3).unwrap().bold()); - assert!(!parser.screen().cell(0, 4).unwrap().bold()); - assert!(!parser.screen().cell(0, 5).unwrap().bold()); - assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jfoo\x1b[33;1;7mb\x1b[42;22ma\x1b[mr\x1b[1;6H\x1b[33;42;7m" - [..] - ); - - parser.process(b"\x1b[1;6H\x1b[35mr\r\nquux"); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jfoo\x1b[33;1;7mb\x1b[42;22ma\x1b[35mr\r\nquux"[..] - ); - - parser.process(b"\x1b[2;1H\x1b[45mquux"); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jfoo\x1b[33;1;7mb\x1b[42;22ma\x1b[35mr\r\n\x1b[45mquux"[..] - ); - - parser - .process(b"\x1b[2;2H\x1b[38;2;123;213;231mu\x1b[38;5;254mu\x1b[39mx"); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert_eq!(parser.screen().contents_formatted(), &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jfoo\x1b[33;1;7mb\x1b[42;22ma\x1b[35mr\r\n\x1b[45mq\x1b[38;2;123;213;231mu\x1b[38;5;254mu\x1b[39mx"[..]); -} - -#[test] -fn empty_cells() { - let mut parser = vt100::Parser::default(); - parser.process(b"\x1b[5C\x1b[32m bar\x1b[H\x1b[31mfoo"); - helpers::contents_formatted_reproduces_screen(parser.screen()); - assert_eq!(parser.screen().contents(), "foo bar"); - assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[31mfoo\x1b[2C\x1b[32m bar\x1b[1;4H\x1b[31m"[..] - ); -} - -#[test] -fn cursor_positioning() { - let mut parser = vt100::Parser::default(); - - let screen = parser.screen().clone(); - parser.process(b":\x1b[K"); - assert_eq!(parser.screen().cursor_position(), (0, 1)); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J:" - ); - assert_eq!(parser.screen().contents_diff(&screen), b":"); - - let screen = parser.screen().clone(); - parser.process(b"a"); - assert_eq!(parser.screen().cursor_position(), (0, 2)); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J:a" - ); - assert_eq!(parser.screen().contents_diff(&screen), b"a"); - - let screen = parser.screen().clone(); - parser.process(b"\x1b[1;2H\x1b[K"); - assert_eq!(parser.screen().cursor_position(), (0, 1)); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J:" - ); - assert_eq!(parser.screen().contents_diff(&screen), b"\x1b[1;2H\x1b[K"); - - let screen = parser.screen().clone(); - parser.process(b"\x1b[H\x1b[J\x1b[4;80H"); - assert_eq!(parser.screen().cursor_position(), (3, 79)); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[4;80H" - ); - assert_eq!( - parser.screen().contents_diff(&screen), - b"\x1b[H\x1b[K\x1b[4;80H" - ); - - let screen = parser.screen().clone(); - parser.process(b"a"); - assert_eq!(parser.screen().cursor_position(), (3, 80)); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[4;80Ha" - ); - assert_eq!(parser.screen().contents_diff(&screen), b"a"); - - let screen = parser.screen().clone(); - parser.process(b"\n"); - assert_eq!(parser.screen().cursor_position(), (4, 80)); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[4;80Ha\n" - ); - assert_eq!(parser.screen().contents_diff(&screen), b"\n"); - - let screen = parser.screen().clone(); - parser.process(b"b"); - assert_eq!(parser.screen().cursor_position(), (5, 1)); - assert_eq!( - parser.screen().contents_formatted(), - b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[4;80Ha\x1b[6;1Hb" - ); - assert_eq!(parser.screen().contents_diff(&screen), b"\r\nb"); -} - -#[test] -fn rows() { - let mut parser = vt100::Parser::default(); - let screen1 = parser.screen().clone(); - assert_eq!( - screen1.rows(0, 80).collect::>(), - vec![ - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - ] - ); - assert_eq!(screen1.rows_formatted(0, 80).collect::>>(), { - let x: Vec> = vec![ - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - ]; - x - }); - assert_eq!( - screen1.rows(5, 15).collect::>(), - vec![ - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - ] - ); - assert_eq!(screen1.rows_formatted(5, 15).collect::>>(), { - let x: Vec> = vec![ - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - ]; - x - }); - - parser - .process(b"\x1b[31mfoo\x1b[10;10H\x1b[32mbar\x1b[20;20H\x1b[33mbaz"); - let screen2 = parser.screen().clone(); - assert_eq!( - screen2.rows(0, 80).collect::>(), - vec![ - "foo".to_string(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - " bar".to_string(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - " baz".to_string(), - String::new(), - String::new(), - String::new(), - String::new(), - ] - ); - assert_eq!( - screen2.rows_formatted(0, 80).collect::>>(), - vec![ - b"\x1b[31mfoo".to_vec(), - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - b"\x1b[9C\x1b[32mbar".to_vec(), - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - b"\x1b[19C\x1b[33mbaz".to_vec(), - vec![], - vec![], - vec![], - vec![], - ] - ); - assert_eq!( - screen2.rows(5, 15).collect::>(), - vec![ - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - " bar".to_string(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - String::new(), - " b".to_string(), - String::new(), - String::new(), - String::new(), - String::new(), - ] - ); - assert_eq!( - screen2.rows_formatted(5, 15).collect::>>(), - vec![ - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - b"\x1b[4C\x1b[32mbar".to_vec(), - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - b"\x1b[14C\x1b[33mb".to_vec(), - vec![], - vec![], - vec![], - vec![], - ] - ); - - assert_eq!( - screen2.rows_diff(&screen1, 0, 80).collect::>>(), - vec![ - b"\x1b[31mfoo".to_vec(), - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - b"\x1b[9C\x1b[32mbar".to_vec(), - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - b"\x1b[19C\x1b[33mbaz".to_vec(), - vec![], - vec![], - vec![], - vec![], - ] - ); - - parser.process(b"\x1b[10;11Ho"); - let screen3 = parser.screen().clone(); - assert_eq!( - screen3.rows_diff(&screen2, 0, 80).collect::>>(), - vec![ - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - b"\x1b[10C\x1b[33mo".to_vec(), - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - vec![], - ] - ); -} - -#[test] -fn contents_between() { - let mut parser = vt100::Parser::default(); - assert_eq!(parser.screen().contents_between(0, 0, 0, 0), ""); - assert_eq!(parser.screen().contents_between(0, 0, 5, 0), "\n\n\n\n\n"); - assert_eq!(parser.screen().contents_between(5, 0, 0, 0), ""); - - parser.process( - b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, \ - sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n\n\ - Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \ - nisi ut aliquip ex ea commodo consequat.\n\n\ - Duis aute irure dolor in reprehenderit in voluptate velit esse cillum \ - dolore eu fugiat nulla pariatur.\n\n\ - Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \ - officia deserunt mollit anim id est laborum.", - ); - assert_eq!(parser.screen().contents_between(0, 0, 0, 0), ""); - assert_eq!( - parser.screen().contents_between(0, 0, 0, 26), - "Lorem ipsum dolor sit amet" - ); - assert_eq!(parser.screen().contents_between(0, 26, 0, 0), ""); - assert_eq!( - parser.screen().contents_between(0, 57, 1, 43), - "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - ); - assert_eq!( - parser.screen().contents_between(0, 57, 2, 0), - "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n" - ); - assert_eq!(parser.screen().contents_between(2, 0, 0, 57), ""); -} - -#[test] -fn diff_basic() { - let mut parser = vt100::Parser::default(); - let screen1 = parser.screen().clone(); - parser.process(b"\x1b[5C\x1b[32m bar"); - let screen2 = parser.screen().clone(); - assert_eq!(screen2.contents_diff(&screen1), b"\x1b[5C\x1b[32m bar"); - helpers::assert_contents_diff_reproduces_state_from_screens( - &screen1, &screen2, - ); - - parser.process(b"\x1b[H\x1b[31mfoo"); - let screen3 = parser.screen().clone(); - assert_eq!(screen3.contents_diff(&screen2), b"\x1b[H\x1b[31mfoo"); - helpers::assert_contents_diff_reproduces_state_from_screens( - &screen2, &screen3, - ); - - parser.process(b"\x1b[1;7H\x1b[32mbaz"); - let screen4 = parser.screen().clone(); - assert_eq!(screen4.contents_diff(&screen3), b"\x1b[5C\x1b[32mz"); - helpers::assert_contents_diff_reproduces_state_from_screens( - &screen3, &screen4, - ); - - parser.process(b"\x1b[1;8H\x1b[X"); - let screen5 = parser.screen().clone(); - assert_eq!(screen5.contents_diff(&screen4), b"\x1b[1;8H\x1b[X"); - helpers::assert_contents_diff_reproduces_state_from_screens( - &screen4, &screen5, - ); -} - -#[test] -fn diff_erase() { - let mut parser = vt100::Parser::default(); - - let screen = parser.screen().clone(); - parser.process(b"foo\x1b[5;5Hbar"); - assert_eq!(parser.screen().contents_diff(&screen), b"foo\x1b[5;5Hbar"); - - let screen = parser.screen().clone(); - parser.process(b"\x1b[3D\x1b[2X"); - assert_eq!(parser.screen().contents_diff(&screen), b"\x1b[5;5H\x1b[2X"); - - let screen = parser.screen().clone(); - parser.process(b"\x1bcfoo\x1b[5;5Hbar"); - assert_eq!(parser.screen().contents_diff(&screen), b"ba\x1b[C"); - - let screen = parser.screen().clone(); - parser.process(b"\x1b[3D\x1b[3X"); - assert_eq!(parser.screen().contents_diff(&screen), b"\x1b[5;5H\x1b[K"); -} diff --git a/crates/turborepo-vt100/tests/write.rs b/crates/turborepo-vt100/tests/write.rs deleted file mode 100644 index c28a285ff43b1..0000000000000 --- a/crates/turborepo-vt100/tests/write.rs +++ /dev/null @@ -1,62 +0,0 @@ -use turborepo_vt100 as vt100; - -use std::io::Write as _; - -#[test] -fn write_text() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - let bytes = parser.write(input).unwrap(); - assert_eq!(bytes, input.len()); - assert_eq!(parser.screen().contents(), "foobar"); -} - -#[test] -fn cell_contents() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - let bytes = parser.write(input).unwrap(); - assert_eq!(bytes, input.len()); - assert_eq!(parser.screen().cell(0, 0).unwrap().contents(), "f"); - assert_eq!(parser.screen().cell(0, 1).unwrap().contents(), "o"); - assert_eq!(parser.screen().cell(0, 2).unwrap().contents(), "o"); - assert_eq!(parser.screen().cell(0, 3).unwrap().contents(), "b"); - assert_eq!(parser.screen().cell(0, 4).unwrap().contents(), "a"); - assert_eq!(parser.screen().cell(0, 5).unwrap().contents(), "r"); - assert_eq!(parser.screen().cell(0, 6).unwrap().contents(), ""); -} - -#[test] -fn cell_colors() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - let bytes = parser.write(input).unwrap(); - assert_eq!(bytes, input.len()); - - assert_eq!( - parser.screen().cell(0, 0).unwrap().fgcolor(), - vt100::Color::Default - ); - assert_eq!( - parser.screen().cell(0, 3).unwrap().fgcolor(), - vt100::Color::Idx(2) - ); - assert_eq!( - parser.screen().cell(0, 4).unwrap().fgcolor(), - vt100::Color::Idx(2) - ); - assert_eq!( - parser.screen().cell(0, 4).unwrap().bgcolor(), - vt100::Color::Idx(2) - ); -} - -#[test] -fn cell_attrs() { - let mut parser = vt100::Parser::default(); - let input = b"foo\x1b[31m\x1b[32mb\x1b[3;7;42ma\x1b[23mr"; - let bytes = parser.write(input).unwrap(); - assert_eq!(bytes, input.len()); - - assert!(parser.screen().cell(0, 4).unwrap().italic()); -} diff --git a/crates/turborepo-wax/Cargo.toml b/crates/turborepo-wax/Cargo.toml index f5cc1566f8279..2b8e0350ac42c 100644 --- a/crates/turborepo-wax/Cargo.toml +++ b/crates/turborepo-wax/Cargo.toml @@ -1,30 +1,3 @@ -[package] -name = "wax" -version = "0.6.0" -authors = ["Sean Olson "] -description = "Opinionated and portable globs that can be matched against paths and directory trees." -repository = "https://github.com/olson-sean-k/wax" -readme = "README.md" -edition = "2021" -rust-version = "1.66.1" -license = "MIT" -keywords = ["glob", "pattern", "regex"] -categories = ["filesystem"] - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "docsrs"] - -[features] -default = ["walk"] -# Integrates with `miette` and provides `Diagnostic` error types and reporting. -miette = ["dep:miette", "dep:tardar"] -# Provides APIs for matching globs against directory trees. -walk = ["dep:walkdir"] - -[lints] -workspace = true - [dependencies] const_format = "^0.2.0" itertools = "^0.11.0" @@ -32,26 +5,58 @@ nom = "^7.0.0" pori = "=0.0.0" thiserror = "^1.0.0" - [dependencies.miette] - default-features = false - optional = true - version = "^5.10.0" +[dependencies.miette] +default-features = false +optional = true +version = "7.5.0" - [dependencies.regex] - default-features = false - features = ["perf", "std", "unicode-case"] - version = "^1.9.0" +[dependencies.regex] +default-features = false +features = ["perf", "std", "unicode-case"] +version = "^1.9.0" - [dependencies.tardar] - optional = true - version = "^0.1.0" +[dependencies.tardar] +optional = true +version = "^0.2.0" - [dependencies.walkdir] - optional = true - version = "^2.4.0" +[dependencies.walkdir] +optional = true +version = "^2.4.0" [dev-dependencies] build-fs-tree = "^0.6.0" dunce = "^1.0.0" path-slash = "0.2.1" tempfile = "^3.8.0" + +[features] +default = ["walk"] +miette = ["dep:miette", "dep:tardar"] +walk = ["dep:walkdir"] + +[lib] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +authors = ["Sean Olson "] +categories = ["filesystem"] +description = "Opinionated and portable globs that can be matched against paths and directory trees." +edition = "2021" +keywords = ["glob", "pattern", "regex"] +license-file = "LICENSE" +name = "wax" +readme = "README.md" +repository = "https://github.com/olson-sean-k/wax" +rust-version = "1.66.1" +version = "0.6.0" + +[package.metadata] + +[package.metadata.docs] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/crates/turborepo-wax/README.md b/crates/turborepo-wax/README.md deleted file mode 100644 index 9881b261c8787..0000000000000 --- a/crates/turborepo-wax/README.md +++ /dev/null @@ -1,475 +0,0 @@ -
    - Wax -
    -
    - -**Wax** is a Rust library that provides opinionated and portable globs that can -be matched against file paths and directory trees. Globs use a familiar syntax -and support expressive features with semantics that emphasize component -boundaries. - -[![GitHub](https://img.shields.io/badge/GitHub-olson--sean--k/wax-8da0cb?logo=github&style=for-the-badge)](https://github.com/olson-sean-k/wax) -[![docs.rs](https://img.shields.io/badge/docs.rs-wax-66c2a5?logo=rust&style=for-the-badge)](https://docs.rs/wax) -[![crates.io](https://img.shields.io/crates/v/wax.svg?logo=rust&style=for-the-badge)](https://crates.io/crates/wax) - -## Basic Usage - -Match a path against a glob: - -```rust -use wax::{Glob, Program}; - -let glob = Glob::new("*.png").unwrap(); -assert!(glob.is_match("logo.png")); -``` - -Match a path against a glob with matched text (captures): - -```rust -use wax::{CandidatePath, Glob, Program}; - -let glob = Glob::new("**/{*.{go,rs}}").unwrap(); - -let path = CandidatePath::from("src/main.go"); -let matched = glob.matched(&path).unwrap(); - -assert_eq!("main.go", matched.get(2).unwrap()); -``` - -Match a directory tree against a glob: - -```rust -use wax::Glob; - -let glob = Glob::new("**/*.{md,txt}").unwrap(); -for entry in glob.walk("doc") { - let entry = entry.unwrap(); - // ... -} -``` - -Match a directory tree against a glob with negations: - -```rust -use wax::walk::{FileIterator, LinkBehavior}; -use wax::Glob; - -let glob = Glob::new("**/*.{md,txt}").unwrap(); -for entry in glob - .walk_with_behavior("doc", LinkBehavior::ReadTarget) - .not(["**/secret/**"]) - .unwrap() -{ - let entry = entry.unwrap(); - // ... -} -``` - -Match a path against multiple globs: - -```rust -use wax::{Glob, Program}; - -let any = wax::any([ - "src/**/*.rs", - "tests/**/*.rs", - "doc/**/*.md", - "pkg/**/PKGBUILD", -]).unwrap(); -assert!(any.is_match("src/token/mod.rs")); -``` - -See more details below. - -## Construction - -Globs are encoded as UTF-8 strings called glob expressions that resemble Unix -paths consisting of nominal components delimited by separators. The most -fundamental type in the Wax API is `Glob`, which is constructed from a glob -expression via inherent functions or standard conversion traits. Data is -borrowed where possible in most APIs, but can be copied into owned instances -using an `into_owned` method with most types. - -```rust -use wax::Glob; - -let glob = Glob::new("site/img/logo.svg").unwrap(); -``` - -Not only are APIs designed for portability, **but so too are glob expressions**. -Regardless of platform or operating system, globs support the same features and -use the same syntax. **Glob expressions are distinct from paths**, which [differ -in syntax and features](#schemes-and-prefixes) on each platform. - -In glob expressions, forward slash `/` is the only path component separator and -back slashes `\` are forbidden (back slash is used for escape sequences, but the -literal sequence `\\` is not supported). This means that it is impossible to -represent `\` in nominal path components, but this character is generally -forbidden as such and its disuse avoids confusion. - -Globs enforce various rules regarding meta-characters, patterns, and component -boundaries that reject [nonsense expressions](#errors-and-diagnostics). While -these rules can sometimes make glob expressions a bit more difficult to compose, -they also make glob expressions more consistent, easier to reason about, and -less prone to errors. - -## Patterns - -Globs resemble Unix paths, but additionally support patterns that can be matched -against paths and directory trees. Patterns use a syntax that resembles globbing -in Unix shells and tools like `git`, though there are some important -differences. - -```rust -use wax::Glob; - -let glob = Glob::new("**/*.{go,rs}").unwrap(); -assert!(glob.is_match("src/lib.rs")); -``` - -Patterns form captures that can be used to extract matched text (as seen in many -regular expression engines). In the above example, there are three patterns that -can be queried for matched text: `**/`, `*`, and `{go,rs}`. Every glob -expression has an implicit capture for the complete matched text. - -Globs use a consistent and opinionated format and patterns are **not** -configurable; the semantics of a particular glob are always the same. For -example, `*` **never** matches across component boundaries. Components are an -important part of paths and file system trees, and only the tree wildcard `**` -(see below) implicitly matches across them. - -### Wildcards - -Wildcards match some amount of arbitrary text in paths and are the most -fundamental pattern provided by globs (and likely the most familiar). - -The zero-or-more wildcards `*` and `$` match zero or more of any character -within a component (**never path separators**). Zero-or-more wildcards cannot be -adjacent to other zero-or-more wildcards. The `*` wildcard is eager and will -match the longest possible text while the `$` wildcard is lazy and will match -the shortest possible text. When followed by a literal, `*` stops at the last -occurrence of that literal while `$` stops at the first occurrence. - -The exactly-one wildcard `?` matches any single character within a component -(**never path separators**). Exactly-one wildcards do not group automatically, -so a pattern of contiguous wildcards such as `???` form distinct captures for -each `?` wildcard. [An alternative](#alternatives) can be used to group -exactly-one wildcards into a single capture, such as `{???}`. - -The tree wildcard `**` matches any characters across zero or more components. -**This is the only pattern that implicitly matches across arbitrary component -boundaries**; all other patterns do **not** implicitly match across component -boundaries. When a tree wildcard participates in a match and does not terminate -the pattern, its captured text includes the trailing separator. If a tree -wildcard does not participate in a match, then its captured text is an empty -string. - -Tree wildcards must be delimited by forward slashes or terminations (the -beginning and/or end of an expression). **Tree wildcards and path separators are -distinct** and any adjacent forward slashes that form a tree wildcard are parsed -together. Rooting forward slashes in tree wildcards are meaningful and the glob -expressions `**/*.txt` and `/**/*.txt` differ in that the former is relative -(has no root) and the latter has a root. - -If a glob expression consists solely of a tree wildcard, then it matches any and -all paths and the complete contents of any and all directory trees, including -the root. - -### Character Classes - -Character classes match any single character from a group of literals and ranges -within a component (**never path separators**). Classes are delimited by square -brackets `[...]`. Individual character literals are specified as is, such as -`[ab]` to match either `a` or `b`. Character ranges are formed from two -characters separated by a hyphen, such as `[x-z]` to match `x`, `y`, or `z`. -Character classes match characters exactly and are always case-sensitive, so the -expressions `[ab]` and `{a,b}` are not necessarily the same. - -Any number of character literals and ranges can be used within a single -character class. For example, `[qa-cX-Z]` matches any of `q`, `a`, `b`, `c`, -`X`, `Y`, or `Z`. - -Character classes may be negated by including an exclamation mark `!` at the -beginning of the class pattern. For example, `[!a]` matches any character except -for `a`. **These are the only patterns that support negation.** - -It is possible to escape meta-characters like `*`, `$`, etc., using character -classes though globs also support escaping via a backslash `\`. To match the -control characters `[`, `]`, and `-` within a character class, they must be -escaped via a backslash, such as `[a\-]` to match `a` or `-`. - -Character classes have notable platform-specific behavior, because they match -arbitrary characters in native paths but never match path separators. This means -that if a character class consists of **only** path separators on a given -platform, then the character class is considered empty and matches nothing. For -example, in the expression `a[/]b` the character class `[/]` matches nothing on -Unix and Windows. Such character classes are not rejected, because the role of -arbitrary characters depends on the platform. In practice, this is rarely a -concern, but **such patterns should be avoided**. - -Character classes have limited utility on their own, but compose well with -[repetitions](#repetitions). - -### Alternatives - -Alternatives match an arbitrary sequence of one or more comma separated -sub-globs delimited by curly braces `{...,...}`. For example, `{a?c,x?z,foo}` -matches any of the sub-globs `a?c`, `x?z`, or `foo`. Alternatives may be -arbitrarily nested and composed with [repetitions](#repetitions). - -Alternatives form a single capture group regardless of the contents of their -sub-globs. This capture is formed from the complete match of the sub-glob, so if -the alternative `{a?c,x?z}` matches `abc`, then the captured text will be `abc` -(**not** `b`). Alternatives can be used to group captures using a single -sub-glob, such as `{*.{go,rs}}` to capture an entire file name with a particular -extension or `{???}` to group a sequence of exactly-one wildcards. - -Alternatives must consider adjacency rules and neighboring patterns. For -example, `*{a,b*}` is allowed but `*{a,*b}` is not. Additionally, they may not -contain a sub-glob consisting of a singular tree wildcard `**` and cannot root a -glob expression as this could cause the expression to match or walk overlapping -trees. - -### Repetitions - -Repetitions match a sub-glob a specified number of times. Repetitions are -delimited by angle brackets with a separating colon `<...:...>` where a sub-glob -precedes the colon and an optional bounds specification follows it. For example, -`` matches the sub-glob `a*/` zero or more times. Though not implicit -like tree [wildcards](#wildcards), **repetitions can match across component -boundaries** (and can themselves include tree wildcards). Repetitions may be -arbitrarily nested and composed with [alternatives](#alternatives). - -Bound specifications are formed from inclusive lower and upper bounds separated -by a comma `,`, such as `:1,4` to match between one and four times. The upper -bound is optional and may be omitted. For example, `:1,` matches one or more -times (note the trailing comma `,`). A singular bound is convergent, so `:3` -matches exactly three times (both the lower and upper bounds are three). If no -lower or upper bound is specified, then the sub-glob matches one or more times, -so `` and `` are equivalent. Similarly, if the colon `:` is also -omitted, then the sub-glob matches zero or more times, so `
    ` and `` are -equivalent. - -Repetitions form a singular capture group regardless of the contents of their -sub-glob. The capture is formed from the complete match of the sub-glob. If the -repetition `` matches `abc/abc/`, then the captured text will be -`abc/abc/`. - -Repetitions compose well with [character classes](#character-classes). Most -often, a glob expression like `{????}` is sufficient, but the more specific -expression `<[0-9]:4>` further constrains the matched characters to digits, for -example. Repetitions may also be more terse, such as ``. Furthermore, -repetitions can form tree expressions that further constrain components, such as -`<[!.]*/>[!.]*` to match paths that contain no leading dots `.` in any -component. - -Repetitions must consider adjacency rules and neighboring patterns. For example, -`a/` is allowed but `/b` is not. Additionally, they may not -contain a sub-glob consisting of a singular separator `/`, a singular -zero-or-more wildcard `*` or `$`, nor a singular tree wildcard `**`. Repetitions -with a lower bound of zero may not root a glob expression, as this could cause -the expression to match or walk overlapping trees. - -## Combinators - -Glob patterns can be combined and matched together using the `any` combinator. -`any` accepts an `IntoIterator` of `Pattern`s, such as compiled `Program`s like -`Glob` or pattern text like `str` slices. The output is an `Any`, which -implements `Program` and efficiently matches any of its input patterns. - -```rust -use wax::{Glob, Program}; - -let any = wax::any(["**/*.txt", "src/**/*.rs"]).unwrap(); -assert!(any.is_match("src/lib.rs")); -``` - -Unlike [alternatives](#alternatives), `Any` supports patterns with overlapping -trees (rooted and unrooted expressions). However, combinators can only perform -logical matches and it is not possible to match an `Any` against a directory -tree (as with `Glob::walk`). - -## Flags and Case Sensitivity - -Flags toggle the matching behavior of globs. Importantly, flags are a part of a -glob expression rather than an API. Behaviors are toggled immediately following -flags in the order in which they appear in glob expressions. Flags are delimited -by parenthesis with a leading question mark `(?...)` and may appear anywhere -within a glob expression so long as they do not split tree wildcards (e.g., -`a/*(?i)*` is not allowed). Each flag is represented by a single character and -can be negated by preceding the corresponding character with a minus `-`. Flags -are toggled in the order in which they appear within `(?...)`. - -The only supported flag is the case-insensitivty flag `i`. By default, glob -expressions use the same case sensitivity as the target platforms's file system -APIs (case-sensitive on Unix and case-insensitive on Windows), but `i` can be -used to toggle this explicitly as needed. For example, -`(?-i)photos/**/*.(?i){jpg,jpeg}` matches file paths beneath a `photos` -directory with a case-**sensitive** base and a case-**insensitive** extension -`jpg` or `jpeg`. - -Wax considers literals, their configured case sensitivity, and the case -sensitivity of the target platform's file system APIs [when partitioning glob -expressions](#partitioning-and-semantic-literals) with `Glob::partition`. -Partitioning is unaffected in glob expressions with no flags. - -## Errors and Diagnostics - -The `GlobError` type represents error conditions that can occur when building a -pattern or walking a directory tree. `GlobError` and its sub-errors implement -the standard `Error` and `Display` traits via [`thiserror`][thiserror]. - -Wax optionally integrates with the [`miette`][miette] crate, which can be used -to capture and display diagnostics. This can be useful for reporting errors to -users that provide glob expressions. When enabled, error types implement the -`Diagnostic` trait. - -``` -Error: wax::glob::adjacent_zero_or_more - - x malformed glob expression: adjacent zero-or-more wildcards `*` or `$` - ,---- - 1 | doc/**/*{.md,.tex,*.txt} - : |^^^^^^^^|^^^^^^^ - : | | `-- here - : | `-- in this alternative - : `-- here - `---- -``` - -Wax also provides inspection APIs that allow code to query glob metadata, such -as captures and variance. - -```rust -use wax::Glob; - -let glob = Glob::new("videos/**/{*.{mp4,webm}}").unwrap(); -assert_eq!(2, glob.captures().count()); -``` - -## Cargo Features - -Wax provides some optional integrations and features that can be toggled via -the Cargo features described below. - -| Feature | Default | Dependencies | Description | -| -------- | ------- | ------------------ | ----------------------------------------------------------------------------- | -| `miette` | No | `miette`, `tardar` | Integrates with `miette` and provides `Diagnostic` error types and reporting. | -| `walk` | Yes | `walkdir` | Provides APIs for matching globs against directory trees. | - -Features can be configured in a crate's `Cargo.toml` manifest. - -```toml -[dependency.wax] -version = "^0.x.0" -default-features = false -features = [ - "miette", - "walk" -] -``` - -## Unsupported Path Features - -Any components not recognized as separators nor patterns are interpreted as -literals. In combination with strict rules, this means **some platform-specific -path features cannot be used directly in globs**. This limitation is by design -and additional code may be necessary to bridge this gap for some use cases. - -### Partitioning and Semantic Literals - -Globs support no notion of a current or parent directory. The path components -`.` and `..` are interpreted as literals and only match paths with the -corresponding components (even on Unix and Windows). For example, the glob -`src/../*.rs` matches the path `src/../lib.rs` but does **not** match the -semantically equivalent path `lib.rs`. - -Parent directory components have unclear meaning and far less utility when they -follow patterns in a glob. However, such components are intuitive and are often -important for escaping a working directory when they precede variant patterns -(i.e., as a prefix). For example, the glob `../src/**/*.rs` has more obvious -intended meaning than the glob `src/**/../*.rs`. As seen above though, the first -glob would only match the literal path component `..` and not paths that replace -this with a parent directory. - -`Glob::partition` can be used to isolate semantic components that precede -patterns and apply semantic path operations to them (namely `..`). -`Glob::partition` partitions a glob into an invariant `PathBuf` prefix and a -variant `Glob` postfix. Here, invariant means that the partition contains no -glob patterns that resolve differently than an equivalent native path using the -target platform's file system APIs. The prefix can be used as needed in -combination with the glob. - -```rust -use dunce; // Avoids UNC paths on Windows. -use std::path::Path; -use wax::{Glob, Program}; - -let path: &Path = /* ... */ // Candidate path. - -let directory = Path::new("."); // Working directory. -let (prefix, glob) = Glob::new("../../src/**").unwrap().partition(); -let prefix = dunce::canonicalize(directory.join(&prefix)).unwrap(); -if dunce::canonicalize(path) - .unwrap() - .strip_prefix(&prefix) - .map(|path| glob.is_match(path)) - .unwrap_or(false) -{ - // ... -} -``` - -Additionally, `Glob::has_semantic_literals` can be used to detect literal -components in a glob that have special semantics on the target platform. When -the `miette` feature is enabled, such literals are reported as warnings. - -```rust -use wax::Glob; - -let glob = Glob::new("../**/src/**/main.rs").unwrap(); -assert!(glob.has_semantic_literals()); -``` - -### Schemes and Prefixes - -While globs can be rooted, they cannot include schemes nor Windows path -prefixes. For example, the Windows UNC share path `\\server\share\src` cannot be -represented directly as a glob. - -This can be limiting, but the design of Wax explicitly forbids this: Windows -prefixes and other volume components are not portable. Instead, when this is -needed, an additional native path or working directory must be used, such as -[the `--tree` option provided by Nym][nym]. In most contexts, globs are applied -relative to some such working directory. - -### Non-nominal Constraints - -Globs are strictly nominal and do not support any non-nominal constraints. It is -not possible to directly filter or otherwise select paths or files based on -additional metadata (such as a modification timestamp) in a glob expression. -However, it is possible for user code to query any such metadata for a matching -path or efficiently apply such filtering when matching directory trees using -`FileIterator::filter_tree`. - -For such additional features, including metadata filters and transformations -using matched text, see [Nym][nym]. - -### Encoding - -Globs operate exclusively on UTF-8 encoded text. However, this encoding is not -used for paths on all platforms. Wax uses the `CandidatePath` type to re-encode -native paths via lossy conversions that use Unicode replacement codepoints -whenever a part of a path cannot be represented as valid UTF-8. In practice, -most paths can be losslessly encoded in UTF-8, but this means that Wax cannot -match nor capture some literal byte strings. - -## Stability - -At the time of writing, Wax is experimental and unstable. It is possible that -glob expression syntax and semantics may change between versions in the `0.y.z` -series without warning nor deprecation. - -[miette]: https://github.com/zkat/miette -[nym]: https://github.com/olson-sean-k/nym -[thiserror]: https://github.com/dtolnay/thiserror diff --git a/crates/turborepo-wax/Source/capture.rs b/crates/turborepo-wax/Source/capture.rs new file mode 100644 index 0000000000000..538e8ae3ffdb8 --- /dev/null +++ b/crates/turborepo-wax/Source/capture.rs @@ -0,0 +1,175 @@ +use std::str; + +use regex::Captures as BorrowedText; + +use crate::CandidatePath; + +#[derive(Clone, Debug)] +struct OwnedText { + matched:String, + ranges:Vec>, +} + +impl OwnedText { + pub fn get(&self, index:usize) -> Option<&str> { + if index == 0 { + Some(self.matched.as_ref()) + } else { + self.ranges + .get(index - 1) + .and_then(|range| range.map(|range| &self.matched[range.0..range.1])) + } + } +} + +impl<'t> From> for OwnedText { + fn from(captures:BorrowedText<'t>) -> Self { From::from(&captures) } +} + +impl<'m, 't> From<&'m BorrowedText<'t>> for OwnedText { + fn from(captures:&'m BorrowedText<'t>) -> Self { + let matched = captures.get(0).unwrap().as_str().into(); + let ranges = captures + .iter() + .skip(1) + .map(|capture| capture.map(|capture| (capture.start(), capture.end()))) + .collect(); + OwnedText { matched, ranges } + } +} + +#[derive(Debug)] +enum MaybeOwnedText<'t> { + Borrowed(BorrowedText<'t>), + Owned(OwnedText), +} + +impl<'t> MaybeOwnedText<'t> { + fn into_owned(self) -> MaybeOwnedText<'static> { + match self { + MaybeOwnedText::Borrowed(borrowed) => OwnedText::from(borrowed).into(), + MaybeOwnedText::Owned(owned) => owned.into(), + } + } + + // This conversion may appear to operate in place. + #[must_use] + fn to_owned(&self) -> MaybeOwnedText<'static> { + match self { + MaybeOwnedText::Borrowed(ref borrowed) => OwnedText::from(borrowed).into(), + MaybeOwnedText::Owned(ref owned) => owned.clone().into(), + } + } +} + +impl<'t> From> for MaybeOwnedText<'t> { + fn from(captures:BorrowedText<'t>) -> Self { MaybeOwnedText::Borrowed(captures) } +} + +impl From for MaybeOwnedText<'static> { + fn from(captures:OwnedText) -> Self { MaybeOwnedText::Owned(captures) } +} + +/// Text that has been matched by a [`Program`] and its captures. +/// +/// To match a [`Glob`] or other [`Program`] against a [`CandidatePath`] and get +/// the matched text, use the [`Program::matched`] function. +/// +/// All [`Program`]s provide an implicit capture of the complete text of a +/// match. This implicit capture has index zero, and is exposed via the +/// [`complete`] function as well as the [`get`] function using index zero. +/// Capturing tokens are indexed starting at one, and can be used to +/// isolate more specific sub-text. +/// +/// # Examples +/// +/// Capturing tokens and matched text can be used to isolate sub-text in a +/// match. For example, the file name of a match can be extracted using an +/// alternative to group patterns. +/// +/// ```rust +/// use wax::{CandidatePath, Glob, Program}; +/// +/// let glob = Glob::new("src/**/{*.{go,rs}}").unwrap(); +/// let candidate = CandidatePath::from("src/graph/link.rs"); +/// let matched = glob.matched(&candidate).unwrap(); +/// +/// assert_eq!("link.rs", matched.get(2).unwrap()); +/// ``` +/// +/// [`CandidatePath`]: crate::CandidatePath +/// [`complete`]: crate::MatchedText::complete +/// [`get`]: crate::MatchedText::get +/// [`Glob`]: crate::Glob +/// [`Program`]: crate::Program +/// [`Program::matched`]: crate::Program::matched +#[derive(Debug)] +pub struct MatchedText<'t> { + inner:MaybeOwnedText<'t>, +} + +impl<'t> MatchedText<'t> { + /// Clones any borrowed data into an owning instance. + pub fn into_owned(self) -> MatchedText<'static> { + let MatchedText { inner } = self; + MatchedText { inner:inner.into_owned() } + } + + /// Clones any borrowed data to an owning instance. + /// + /// This function is similar to [`into_owned`], but does not consume its + /// receiver. Due to a technical limitation, `MatchedText` cannot properly + /// implement [`Clone`], so this function is provided as a stop gap that + /// allows a distinct instance to be created that owns its data. + /// + /// [`Clone`]: std::clone::Clone + /// [`into_owned`]: crate::MatchedText::into_owned + // This conversion may appear to operate in place. + #[must_use] + pub fn to_owned(&self) -> MatchedText<'static> { MatchedText { inner:self.inner.to_owned() } } + + /// Gets the complete text of a match. + /// + /// All [`Program`]s have an implicit capture of the complete text at index + /// zero. This function is therefore equivalent to unwrapping the output + /// of the [`get`] function with index zero. + /// + /// [`get`]: crate::MatchedText::get + /// [`Program`]: crate::Program + pub fn complete(&self) -> &str { self.get(0).expect("match has no complete text") } + + /// Gets the matched text of a capture at the given index. + /// + /// All [`Program`]s have an implicit capture of the complete text at index + /// zero. Capturing tokens are indexed from one, so any capturing + /// sub-expression will be indexed after the implicit complete text. For + /// example, the sub-expression `*` in the glob expression `*.txt` is at + /// index one and will exclude the suffix `.txt` in its matched text. + /// + /// Alternative and repetition patterns group their sub-globs into a single + /// capture, so it is not possible to isolate matched text from their + /// sub-globs. This can be used to explicitly group matched text, such + /// as isolating an entire matched file name using an expression like + /// `{*.{go,rs}}`. + /// + /// [`Program`]: crate::Program + pub fn get(&self, index:usize) -> Option<&str> { + match self.inner { + MaybeOwnedText::Borrowed(ref captures) => { + captures.get(index).map(|capture| capture.as_str()) + }, + MaybeOwnedText::Owned(ref captures) => captures.get(index), + } + } + + pub fn to_candidate_path(&self) -> CandidatePath { CandidatePath::from(self.complete()) } +} + +// TODO: This probably shouldn't be part of the public API. +impl<'t> From> for MatchedText<'t> { + fn from(captures:BorrowedText<'t>) -> Self { MatchedText { inner:captures.into() } } +} + +impl From for MatchedText<'static> { + fn from(captures:OwnedText) -> Self { MatchedText { inner:captures.into() } } +} diff --git a/crates/turborepo-wax/Source/diagnostics/miette.rs b/crates/turborepo-wax/Source/diagnostics/miette.rs new file mode 100644 index 0000000000000..e2b61dba5de3d --- /dev/null +++ b/crates/turborepo-wax/Source/diagnostics/miette.rs @@ -0,0 +1,172 @@ +#![cfg(feature = "miette")] + +use std::borrow::Cow; + +use miette::{Diagnostic, SourceSpan}; +use tardar::{ + BoxedDiagnostic, + DiagnosticResult, + DiagnosticResultExt as _, + IteratorExt as _, + ResultExt as _, +}; +use thiserror::Error; + +use crate::{ + Checked, + Glob, + diagnostics::SpanExt as _, + rule, + token::{self, TokenKind, TokenTree, Tokenized}, +}; + +/// APIs for diagnosing globs. +impl<'t> Glob<'t> { + /// Constructs a [`Glob`] from a glob expression with diagnostics. + /// + /// This function is the same as [`Glob::new`], but additionally returns + /// detailed diagnostics on both success and failure. + /// + /// See [`Glob::diagnose`]. + /// + /// # Examples + /// + /// ```rust + /// use tardar::DiagnosticResultExt as _; + /// use wax::Glob; + /// + /// let result = Glob::diagnosed("(?i)readme.{md,mkd,markdown}"); + /// for diagnostic in result.diagnostics() { + /// eprintln!("{}", diagnostic); + /// } + /// if let Some(glob) = result.ok_output() { /* ... */ } + /// ``` + /// + /// [`Glob`]: crate::Glob + /// [`Glob::diagnose`]: crate::Glob::diagnose + /// [`Glob::new`]: crate::Glob::new + pub fn diagnosed(expression:&'t str) -> DiagnosticResult<'t, Self> { + parse_and_diagnose(expression).and_then_diagnose(|tree| { + Glob::compile(tree.as_ref().tokens()) + .into_error_diagnostic() + .map_output(|program| Glob { tree, program }) + }) + } + + /// Gets **non-error** [`Diagnostic`]s. + /// + /// This function requires a receiving [`Glob`] and so does not report + /// error-level [`Diagnostic`]s. It can be used to get non-error + /// diagnostics after constructing or [partitioning][`Glob::partition`] + /// a [`Glob`]. + /// + /// See [`Glob::diagnosed`]. + /// + /// [`Diagnostic`]: miette::Diagnostic + /// [`Glob`]: crate::Glob + /// [`Glob::diagnosed`]: crate::Glob::diagnosed + /// [`Glob::partition`]: crate::Glob::partition + pub fn diagnose(&self) -> impl Iterator> { + diagnose(self.tree.as_ref()) + } +} + +#[derive(Clone, Debug, Diagnostic, Error)] +#[diagnostic(code(wax::glob::semantic_literal), severity(warning))] +#[error("`{literal}` has been interpreted as a literal with no semantics")] +pub struct SemanticLiteralWarning<'t> { + #[source_code] + expression:Cow<'t, str>, + literal:Cow<'t, str>, + #[label("here")] + span:SourceSpan, +} + +#[derive(Clone, Debug, Diagnostic, Error)] +#[diagnostic(code(wax::glob::terminating_separator), severity(warning))] +#[error("terminating separator may discard matches")] +pub struct TerminatingSeparatorWarning<'t> { + #[source_code] + expression:Cow<'t, str>, + #[label("here")] + span:SourceSpan, +} + +fn parse_and_diagnose(expression:&str) -> DiagnosticResult> { + token::parse(expression) + .into_error_diagnostic() + .and_then_diagnose(|tokenized| rule::check(tokenized).into_error_diagnostic()) + .and_then_diagnose(|checked| { + // TODO: This should accept `&Checked`. + diagnose(checked.as_ref()).into_non_error_diagnostic().map_output(|_| checked) + }) +} + +fn diagnose<'i, 't>(tokenized:&'i Tokenized<'t>) -> impl 'i + Iterator> { + None.into_iter() + .chain( + token::literals(tokenized.tokens()) + .filter(|(_, literal)| literal.is_semantic_literal()) + .map(|(component, literal)| { + Box::new(SemanticLiteralWarning { + expression:tokenized.expression().clone(), + literal:literal.text().clone(), + span:component + .tokens() + .iter() + .map(|token| *token.annotation()) + .reduce(|left, right| left.union(&right)) + .map(SourceSpan::from) + .expect("no tokens in component"), + }) as BoxedDiagnostic + }), + ) + .chain( + tokenized + .tokens() + .last() + .into_iter() + .filter(|token| matches!(token.kind(), TokenKind::Separator(_))) + .map(|token| { + Box::new(TerminatingSeparatorWarning { + expression:tokenized.expression().clone(), + span:(*token.annotation()).into(), + }) as BoxedDiagnostic + }), + ) +} + +#[cfg(test)] +mod tests { + use crate::Glob; + + // It is non-trivial to downcast `&dyn Diagnostic`, so diagnostics are + // identified in tests by their code. + const CODE_SEMANTIC_LITERAL:&str = "wax::glob::semantic_literal"; + const CODE_TERMINATING_SEPARATOR:&str = "wax::glob::terminating_separator"; + + #[cfg(any(unix, windows))] + #[test] + fn diagnose_glob_semantic_literal_warning() { + let glob = Glob::new("../foo").unwrap(); + let diagnostics:Vec<_> = glob.diagnose().collect(); + + assert!(diagnostics.iter().any(|diagnostic| { + diagnostic + .code() + .map_or(false, |code| code.to_string() == CODE_SEMANTIC_LITERAL) + })); + } + + #[test] + fn diagnose_glob_terminating_separator_warning() { + let glob = Glob::new("**/foo/").unwrap(); + let diagnostics:Vec<_> = glob.diagnose().collect(); + + assert!(diagnostics.iter().any(|diagnostic| { + diagnostic + .code() + .map_or(false, |code| code.to_string() == CODE_TERMINATING_SEPARATOR) + })); + } +} diff --git a/crates/turborepo-wax/Source/diagnostics/mod.rs b/crates/turborepo-wax/Source/diagnostics/mod.rs new file mode 100644 index 0000000000000..4471c0882be92 --- /dev/null +++ b/crates/turborepo-wax/Source/diagnostics/mod.rs @@ -0,0 +1,150 @@ +mod miette; + +use std::{ + cmp, + fmt::{self, Display, Formatter}, +}; + +#[cfg(feature = "miette")] +use ::miette::LabeledSpan; + +/// Location and length of a token within a glob expression. +/// +/// Spans are encoded as a tuple of `usize`s, where the first element is the +/// location or position and the second element is the length. Both position and +/// length are measured in bytes and **not** code points, graphemes, etc. +/// +/// # Examples +/// +/// Spans can be used to isolate sub-expressions. +/// +/// ```rust +/// use wax::Glob; +/// +/// let expression = "**/*.txt"; +/// let glob = Glob::new(expression).unwrap(); +/// for token in glob.captures() { +/// let (start, n) = token.span(); +/// println!("capturing sub-expression: {}", &expression[start..][..n]); +/// } +/// ``` +pub type Span = (usize, usize); + +pub trait SpanExt { + fn union(&self, other:&Self) -> Self; +} + +impl SpanExt for Span { + fn union(&self, other:&Self) -> Self { + let start = cmp::min(self.0, other.0); + let end = cmp::max(self.0 + self.1, other.0 + other.1); + (start, end - start) + } +} + +/// Error associated with a [`Span`] within a glob expression. +/// +/// Located errors describe specific instances of an error within a glob +/// expression. Types that implement this trait provide a location within a glob +/// expression via the [`LocatedError::span`] function as well as a description +/// via the [`Display`] trait. See [`BuildError::locations`]. +/// +/// [`BuildError::locations`]: crate::BuildError::locations +/// [`Display`]: std::fmt::Display +/// [`LocatedError::span`]: crate::LocatedError::span +/// [`Span`]: crate::Span +pub trait LocatedError: Display { + /// Gets the span within the glob expression with which the error is + /// associated. + fn span(&self) -> Span; +} + +#[derive(Clone, Copy, Debug)] +pub struct CompositeSpan { + label:&'static str, + kind:CompositeSpanKind, +} + +impl CompositeSpan { + pub fn spanned(label:&'static str, span:Span) -> Self { + CompositeSpan { label, kind:CompositeSpanKind::Span(span) } + } + + pub fn correlated(label:&'static str, span:Span, correlated:CorrelatedSpan) -> Self { + CompositeSpan { label, kind:CompositeSpanKind::Correlated { span, correlated } } + } + + #[cfg(feature = "miette")] + pub fn labels(&self) -> Vec { + let label = Some(self.label.to_string()); + match self.kind { + CompositeSpanKind::Span(ref span) => vec![LabeledSpan::new_with_span(label, *span)], + CompositeSpanKind::Correlated { ref span, ref correlated } => { + Some(LabeledSpan::new_with_span(label, *span)) + .into_iter() + .chain(correlated.labels()) + .collect() + }, + } + } +} + +impl Display for CompositeSpan { + fn fmt(&self, f:&mut Formatter) -> fmt::Result { write!(f, "{}", self.label) } +} + +impl LocatedError for CompositeSpan { + fn span(&self) -> Span { + match self.kind { + CompositeSpanKind::Span(ref span) | CompositeSpanKind::Correlated { ref span, .. } => { + *span + }, + } + } +} + +#[derive(Clone, Copy, Debug)] +enum CompositeSpanKind { + Span(Span), + Correlated { + span:Span, + #[cfg_attr(not(feature = "miette"), allow(dead_code))] + correlated:CorrelatedSpan, + }, +} + +#[derive(Clone, Copy, Debug)] +pub enum CorrelatedSpan { + Contiguous(Span), + Split(Span, Span), +} + +impl CorrelatedSpan { + pub fn split_some(left:Option, right:Span) -> Self { + if let Some(left) = left { + CorrelatedSpan::Split(left, right) + } else { + CorrelatedSpan::Contiguous(right) + } + } + + #[cfg(feature = "miette")] + pub fn labels(&self) -> Vec { + let label = Some("here".to_string()); + match self { + CorrelatedSpan::Contiguous(ref span) => { + vec![LabeledSpan::new_with_span(label, *span)] + }, + CorrelatedSpan::Split(ref left, ref right) => { + vec![ + LabeledSpan::new_with_span(label.clone(), *left), + LabeledSpan::new_with_span(label, *right), + ] + }, + } + } +} + +impl From for CorrelatedSpan { + fn from(span:Span) -> Self { CorrelatedSpan::Contiguous(span) } +} diff --git a/crates/turborepo-wax/Source/encode.rs b/crates/turborepo-wax/Source/encode.rs new file mode 100644 index 0000000000000..c3168d78086c3 --- /dev/null +++ b/crates/turborepo-wax/Source/encode.rs @@ -0,0 +1,322 @@ +use std::borrow::{Borrow, Cow}; +#[cfg(feature = "miette")] +use std::fmt::Display; + +use const_format::formatcp; +use itertools::{Itertools as _, Position}; +#[cfg(feature = "miette")] +use miette::Diagnostic; +use regex::{Error as RegexError, Regex}; +use thiserror::Error; + +use crate::token::Token; + +/// A regular expression that never matches. +/// +/// This expression is formed from a character class that intersects completely +/// disjoint characters. Unlike an empty regular expression, which always +/// matches, this yields an empty character class, which never matches (even +/// against empty strings). +const NEVER_EXPRESSION:&str = "[a&&b]"; + +#[cfg(windows)] +const SEPARATOR_CLASS_EXPRESSION:&str = "/\\\\"; +#[cfg(unix)] +const SEPARATOR_CLASS_EXPRESSION:&str = "/"; + +// This only encodes the platform's main separator, so any additional separators +// will be missed. It may be better to have explicit platform support and invoke +// `compile_error!` on unsupported platforms, as this could cause very aberrant +// behavior. Then again, it seems that platforms using more than one separator +// are rare. GS/OS, OS/2, and Windows are likely the best known examples +// and of those only Windows is a supported Rust target at the time of writing +// (and is already supported by Wax). +#[cfg(not(any(windows, unix)))] +const SEPARATOR_CLASS_EXPRESSION:&str = main_separator_class_expression(); + +#[cfg(not(any(windows, unix)))] +const fn main_separator_class_expression() -> &'static str { + use std::path::MAIN_SEPARATOR; + + // TODO: This is based upon `regex_syntax::is_meta_character`, but that function + // is not `const`. Perhaps that can be changed upstream. + const fn escape(x:char) -> &'static str { + match x { + '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' + | '#' | '&' | '-' | '~' => "\\", + _ => "", + } + } + + formatcp!("{0}{1}", escape(MAIN_SEPARATOR), MAIN_SEPARATOR) +} + +macro_rules! sepexpr { + ($fmt:expr) => { + formatcp!($fmt, formatcp!("[{0}]", SEPARATOR_CLASS_EXPRESSION)) + }; +} + +macro_rules! nsepexpr { + ($fmt:expr) => { + formatcp!($fmt, formatcp!("[^{0}]", SEPARATOR_CLASS_EXPRESSION)) + }; +} + +/// Describes errors that occur when compiling a glob expression. +/// +/// **This error only occurs when the size of the compiled program is too +/// large.** All other compilation errors are considered internal bugs and will +/// panic. +#[derive(Clone, Debug, Error)] +#[error("failed to compile glob: {kind}")] +pub struct CompileError { + kind:CompileErrorKind, +} + +#[derive(Clone, Copy, Debug, Error)] +#[non_exhaustive] +enum CompileErrorKind { + #[error("oversized program")] + OversizedProgram, +} + +#[cfg(feature = "miette")] +#[cfg_attr(docsrs, doc(cfg(feature = "miette")))] +impl Diagnostic for CompileError { + fn code<'a>(&'a self) -> Option> { + Some(Box::new(String::from(match self.kind { + CompileErrorKind::OversizedProgram => "wax::glob::oversized_program", + }))) + } +} + +trait Escaped { + fn escaped(&self) -> String; +} + +impl Escaped for char { + fn escaped(&self) -> String { regex::escape(&self.to_string()) } +} + +impl Escaped for str { + fn escaped(&self) -> String { regex::escape(self) } +} + +#[derive(Clone, Copy, Debug)] +enum Grouping { + Capture, + NonCapture, +} + +impl Grouping { + pub fn push_str(&self, pattern:&mut String, encoding:&str) { + self.push_with(pattern, || encoding.into()); + } + + pub fn push_with<'p, F>(&self, pattern:&mut String, f:F) + where + F: Fn() -> Cow<'p, str>, { + match self { + Grouping::Capture => pattern.push('('), + Grouping::NonCapture => pattern.push_str("(?:"), + } + pattern.push_str(f().as_ref()); + pattern.push(')'); + } +} + +pub fn case_folded_eq(left:&str, right:&str) -> bool { + let regex = Regex::new(&format!("(?i){}", regex::escape(left))) + .expect("failed to compile literal regular expression"); + if let Some(matched) = regex.find(right) { + matched.start() == 0 && matched.end() == right.len() + } else { + false + } +} + +pub fn compile<'t, A, T>(tokens:impl IntoIterator) -> Result +where + T: Borrow>, { + let mut pattern = String::new(); + pattern.push('^'); + encode(Grouping::Capture, None, &mut pattern, tokens); + pattern.push('$'); + Regex::new(&pattern).map_err(|error| { + match error { + RegexError::CompiledTooBig(_) => { + CompileError { kind:CompileErrorKind::OversizedProgram } + }, + _ => panic!("failed to compile glob"), + } + }) +} + +// TODO: Some versions of `const_format` in `^0.2.0` fail this lint in +// `formatcp`. See https://github.com/rodrimati1992/const_format_crates/issues/38 +#[allow(clippy::double_parens)] +fn encode<'t, A, T>( + grouping:Grouping, + superposition:Option, + pattern:&mut String, + tokens:impl IntoIterator, +) where + T: Borrow>, { + use itertools::Position::{First, Last, Middle, Only}; + + use crate::token::{ + Archetype::{Character, Range}, + Evaluation::{Eager, Lazy}, + TokenKind::{Alternative, Class, Literal, Repetition, Separator, Wildcard}, + Wildcard::{One, Tree, ZeroOrMore}, + }; + + fn encode_intermediate_tree(grouping:Grouping, pattern:&mut String) { + pattern.push_str(sepexpr!("(?:{0}|{0}")); + grouping.push_str(pattern, sepexpr!(".*{0}")); + pattern.push(')'); + } + + // TODO: Use `Grouping` everywhere a group is encoded. For invariant groups that + // ignore `grouping`, construct a local `Grouping` instead. + for (position, token) in tokens.into_iter().with_position() { + match (position, token.borrow().kind()) { + (_, Literal(literal)) => { + // TODO: Only encode changes to casing flags. + // TODO: Should Unicode support also be toggled by casing flags? + if literal.is_case_insensitive() { + pattern.push_str("(?i)"); + } else { + pattern.push_str("(?-i)"); + } + pattern.push_str(&literal.text().escaped()); + }, + (_, Separator(_)) => pattern.push_str(sepexpr!("{0}")), + (position, Alternative(alternative)) => { + let encodings:Vec<_> = alternative + .branches() + .iter() + .map(|tokens| { + let mut pattern = String::new(); + pattern.push_str("(?:"); + encode( + Grouping::NonCapture, + superposition.or(Some(position)), + &mut pattern, + tokens.iter(), + ); + pattern.push(')'); + pattern + }) + .collect(); + grouping.push_str(pattern, &encodings.join("|")); + }, + (position, Repetition(repetition)) => { + let encoding = { + let (lower, upper) = repetition.bounds(); + let mut pattern = String::new(); + pattern.push_str("(?:"); + encode( + Grouping::NonCapture, + superposition.or(Some(position)), + &mut pattern, + repetition.tokens().iter(), + ); + pattern.push_str(&if let Some(upper) = upper { + format!("){{{},{}}}", lower, upper) + } else { + format!("){{{},}}", lower) + }); + pattern + }; + grouping.push_str(pattern, &encoding); + }, + (_, Class(class)) => { + grouping.push_with(pattern, || { + use crate::token::Class as ClassToken; + + fn encode_class_archetypes(class:&ClassToken, pattern:&mut String) { + for archetype in class.archetypes() { + match archetype { + Character(literal) => pattern.push_str(&literal.escaped()), + Range(left, right) => { + pattern.push_str(&left.escaped()); + pattern.push('-'); + pattern.push_str(&right.escaped()); + }, + } + } + } + + let mut pattern = String::new(); + pattern.push('['); + if class.is_negated() { + pattern.push('^'); + encode_class_archetypes(class, &mut pattern); + pattern.push_str(SEPARATOR_CLASS_EXPRESSION); + } else { + encode_class_archetypes(class, &mut pattern); + pattern.push_str(nsepexpr!("&&{0}")); + } + pattern.push(']'); + // TODO: The compiled `Regex` is discarded. Is there a way to check the + // correctness of the expression but do less work (i.e., don't build a + // complete `Regex`)? + // Compile the character class sub-expression. This may fail if the subtraction + // of the separator pattern yields an empty character class (meaning that the + // glob expression matches only separator characters on the target platform). + if Regex::new(&pattern).is_ok() { + pattern.into() + } else { + // If compilation fails, then use `NEVER_EXPRESSION`, which matches + // nothing. + NEVER_EXPRESSION.into() + } + }); + }, + (_, Wildcard(One)) => grouping.push_str(pattern, nsepexpr!("{0}")), + (_, Wildcard(ZeroOrMore(Eager))) => grouping.push_str(pattern, nsepexpr!("{0}*")), + (_, Wildcard(ZeroOrMore(Lazy))) => grouping.push_str(pattern, nsepexpr!("{0}*?")), + (First, Wildcard(Tree { has_root })) => { + if let Some(Middle | Last) = superposition { + encode_intermediate_tree(grouping, pattern); + } else if *has_root { + grouping.push_str(pattern, sepexpr!("{0}.*{0}?")); + } else { + pattern.push_str(sepexpr!("(?:{0}?|")); + grouping.push_str(pattern, sepexpr!(".*{0}")); + pattern.push(')'); + } + }, + (Middle, Wildcard(Tree { .. })) => { + encode_intermediate_tree(grouping, pattern); + }, + (Last, Wildcard(Tree { .. })) => { + if let Some(First | Middle) = superposition { + encode_intermediate_tree(grouping, pattern); + } else { + pattern.push_str(sepexpr!("(?:{0}?|{0}")); + grouping.push_str(pattern, ".*"); + pattern.push(')'); + } + }, + (Only, Wildcard(Tree { .. })) => grouping.push_str(pattern, ".*"), + } + } +} + +#[cfg(test)] +mod tests { + use crate::encode; + + #[test] + fn case_folded_eq() { + assert!(encode::case_folded_eq("a", "a")); + assert!(encode::case_folded_eq("a", "A")); + + assert!(!encode::case_folded_eq("a", "b")); + assert!(!encode::case_folded_eq("aa", "a")); + assert!(!encode::case_folded_eq("a", "aa")); + } +} diff --git a/crates/turborepo-wax/Source/lib.rs b/crates/turborepo-wax/Source/lib.rs new file mode 100644 index 0000000000000..381ea594a7961 --- /dev/null +++ b/crates/turborepo-wax/Source/lib.rs @@ -0,0 +1,1847 @@ +//! Wax provides opinionated and portable globs that can be matched against file +//! paths and directory trees. Globs use a familiar syntax and support +//! expressive features with semantics that emphasize component boundaries. +//! +//! See the [repository documentation](https://github.com/olson-sean-k/wax/blob/master/README.md) +//! for details about glob expressions and patterns. + +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc( + html_favicon_url = "https://raw.githubusercontent.com/olson-sean-k/wax/master/doc/wax-favicon.svg?sanitize=true" +)] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/olson-sean-k/wax/master/doc/wax.svg?sanitize=true" +)] +#![allow(clippy::all)] +#![deny( + clippy::cast_lossless, + clippy::checked_conversions, + clippy::cloned_instead_of_copied, + clippy::explicit_into_iter_loop, + clippy::filter_map_next, + clippy::flat_map_option, + clippy::from_iter_instead_of_collect, + clippy::if_not_else, + clippy::manual_ok_or, + clippy::map_unwrap_or, + clippy::match_same_arms, + clippy::redundant_closure_for_method_calls, + clippy::redundant_else, + clippy::unreadable_literal, + clippy::unused_self +)] + +mod capture; +mod diagnostics; +mod encode; +mod rule; +mod token; +pub mod walk; + +/// Re-exports of commonly used items. +/// +/// This module anonymously re-exports traits for matching [`Program`]s against +/// file paths and directory trees. A glob import of this module can be used +/// instead of individual imports of these traits. +/// +/// # Examples +/// +/// ```rust,no_run,ignore +/// use wax::prelude::*; +/// use wax::Glob; +/// +/// // This code requires the `Entry` and `FileIterator` traits. +/// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); +/// for entry in glob.walk("textures").not(["**/.*/**"]).unwrap().flatten() { +/// println!("JPEG: {:?}", entry.path()); +/// } +/// ``` +pub mod prelude { + #[cfg(feature = "walk")] + pub use crate::walk::{Entry as _, FileIterator as _, PathExt as _}; + pub use crate::{LocatedError as _, Program as _}; +} + +use std::{ + borrow::{Borrow, Cow}, + convert::Infallible, + ffi::OsStr, + fmt::{self, Debug, Display, Formatter}, + path::{Path, PathBuf}, + str::{self, FromStr}, +}; + +#[cfg(feature = "miette")] +use miette::Diagnostic; +use regex::Regex; +use thiserror::Error; + +#[cfg(feature = "walk")] +use crate::walk::WalkError; +pub use crate::{ + capture::MatchedText, + diagnostics::{LocatedError, Span}, +}; +use crate::{ + encode::CompileError, + rule::{Checked, RuleError}, + token::{InvariantText, ParseError, Token, TokenTree, Tokenized}, +}; + +#[cfg(windows)] +const PATHS_ARE_CASE_INSENSITIVE:bool = true; +#[cfg(not(windows))] +const PATHS_ARE_CASE_INSENSITIVE:bool = false; + +trait CharExt: Sized { + /// Returns `true` if the character (code point) has casing. + fn has_casing(self) -> bool; +} + +impl CharExt for char { + fn has_casing(self) -> bool { self.is_lowercase() != self.is_uppercase() } +} + +trait StrExt { + /// Returns `true` if any characters in the string have casing. + fn has_casing(&self) -> bool; +} + +impl StrExt for str { + fn has_casing(&self) -> bool { self.chars().any(CharExt::has_casing) } +} + +/// Token that captures matched text in a glob expression. +/// +/// # Examples +/// +/// `CapturingToken`s can be used to isolate sub-expressions. +/// +/// ```rust +/// use wax::Glob; +/// +/// let expression = "**/*.txt"; +/// let glob = Glob::new(expression).unwrap(); +/// for token in glob.captures() { +/// let (start, n) = token.span(); +/// println!("capturing sub-expression: {}", &expression[start..][..n]); +/// } +/// ``` +#[derive(Clone, Copy, Debug)] +pub struct CapturingToken { + index:usize, + span:Span, +} + +impl CapturingToken { + /// Gets the index of the capture. + /// + /// Captures are one-indexed and the index zero always represents the + /// implicit capture of the complete match, so the index of + /// `CapturingToken`s is always one or greater. See [`MatchedText`]. + /// + /// [`MatchedText`]: crate::MatchedText + pub fn index(&self) -> usize { self.index } + + /// Gets the span of the token's sub-expression. + pub fn span(&self) -> Span { self.span } +} + +// This type is similar to `token::Variance>`, but is +// simplified for the public API. Invariant text is always expressed as a path +// and no variant bounds are provided. +/// Variance of a [`Program`]. +/// +/// The variance of a pattern describes the kinds of paths it can match with +/// respect to the platform file system APIs. [`Program`]s are either variant or +/// invariant. +/// +/// An invariant [`Program`] can be represented and completely described by an +/// equivalent path using the platform's file system APIs. For example, the glob +/// expression `path/to/file.txt` resolves identically to the paths +/// `path/to/file.txt` and `path\to\file.txt` on Unix and Windows, respectively. +/// +/// A variant [`Program`] resolves differently than any particular path used +/// with the platform's file system APIs. Such an expression cannot be +/// represented by a single path. This is typically because the expression +/// matches multiple texts using a regular pattern, such as in the glob +/// expression `**/*.rs`. +/// +/// [`Program`]: crate::Program +/// [`Variance`]: crate::Variance +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub enum Variance { + /// A [`Program`] is invariant and equivalent to a path. + /// + /// Some non-literal expressions may be invariant, such as in the expression + /// `path/[t][o]/{file,file}.txt`, which is invariant on Unix (but not on + /// Windows, because the character class expressions do not match with + /// case folding). + /// + /// [`Program`]: crate::Program + Invariant( + /// An equivalent path that completely describes the invariant + /// [`Program`] with respect to platform file system APIs. + /// + /// [`Program`]: crate::Program + PathBuf, + ), + /// A [`Program`] is variant and cannot be completely described by a path. + /// + /// Variant expressions may be formed from literals or other **seemingly** + /// invariant expressions. For example, the variance of literals + /// considers the case sensitivity of the platform's file system APIs, + /// so the expression `(?i)path/to/file.txt` is variant on Unix + /// but not on Windows. Similarly, the expression `path/[t][o]/file.txt` is + /// variant on Windows but not on Unix. + /// + /// [`Program`]: crate::Program + Variant, +} + +impl Variance { + /// Gets the equivalent native path if invariant. + /// + /// Returns `None` if variant. + pub fn path(&self) -> Option<&Path> { + match self { + Variance::Invariant(ref path) => Some(path), + Variance::Variant => None, + } + } + + /// Returns `true` if invariant. + pub fn is_invariant(&self) -> bool { matches!(self, Variance::Invariant(_)) } + + /// Returns `true` if variant. + pub fn is_variant(&self) -> bool { matches!(self, Variance::Variant) } +} + +impl From>> for Variance { + fn from(variance:token::Variance>) -> Self { + match variance { + token::Variance::Invariant(text) => { + Variance::Invariant(PathBuf::from(text.to_string().into_owned())) + }, + token::Variance::Variant(_) => Variance::Variant, + } + } +} + +/// A compiled glob expression that can be inspected and matched against paths. +/// +/// Matching is a logical operation and does **not** interact with a file +/// system. To handle path operations, use [`Path`] and/or [`PathBuf`] and their +/// associated functions. See [`Glob::partition`] for more about globs and path +/// operations. +/// +/// [`Glob::partition`]: crate::Glob::partition +/// [`Path`]: std::path::Path +/// [`PathBuf`]: std::path::PathBuf +pub trait Program<'t>: Pattern<'t, Error = Infallible> { + /// Returns `true` if a path matches the pattern. + /// + /// The given path must be convertible into a [`CandidatePath`]. + /// + /// [`CandidatePath`]: crate::CandidatePath + fn is_match<'p>(&self, path:impl Into>) -> bool; + + /// Gets [matched text][`MatchedText`] in a [`CandidatePath`]. + /// + /// Returns `None` if the [`CandidatePath`] does not match the pattern. + /// + /// [`CandidatePath`]: crate::CandidatePath + /// [`MatchedText`]: crate::MatchedText + fn matched<'p>(&self, path:&'p CandidatePath<'_>) -> Option>; + + /// Gets the variance of the pattern. + /// + /// The variance of a pattern describes the kinds of paths it can match with + /// respect to the platform file system APIs. + fn variance(&self) -> Variance; + + /// Returns `true` if the pattern is exhaustive. + /// + /// A glob expression is exhaustive if its terminating component matches any + /// and all sub-trees, such as in the expressions `/home/**` and + /// `local/</>*`. + fn is_exhaustive(&self) -> bool; +} + +/// A glob expression representation that can be incorporated into a combinator. +/// +/// This trait is implemented by types that can be (fallibly) converted into a +/// [`Program`] and incorporated into a combinator. See [`any`]. +/// +/// [`any`]: crate::any +/// [`Program`]: crate::Program +pub trait Pattern<'t>: + TryInto, Error = >::Error> { + type Tokens: TokenTree<'t>; + type Error: Into; +} + +impl<'t> Pattern<'t> for &'t str { + type Error = BuildError; + type Tokens = Tokenized<'t>; +} + +/// General errors concerning [`Program`]s. +/// +/// This is the most general error and each of its variants exposes a particular +/// error type that describes the details of its associated error condition. +/// This error is not used in any Wax APIs directly, but can be used to +/// encapsulate the more specific errors that are. +/// +/// # Examples +/// +/// To encapsulate different errors in the Wax API behind a function, convert +/// them into a `GlobError` via `?`. +/// +/// ```rust,no_run,ignore +/// use std::path::PathBuf; +/// use wax::{Glob, GlobError}; +/// +/// fn read_all(directory: impl Into) -> Result, GlobError> { +/// let mut data = Vec::new(); +/// let glob = Glob::new("**/*.data.bin")?; +/// for entry in glob.walk(directory) { +/// let entry = entry?; +/// // ... +/// } +/// Ok(data) +/// } +/// ``` +/// +/// [`Program`]: crate::Program +#[cfg_attr(feature = "miette", derive(Diagnostic))] +#[derive(Debug, Error)] +#[error(transparent)] +pub enum GlobError { + #[cfg_attr(feature = "miette", diagnostic(transparent))] + Build(BuildError), + #[cfg(feature = "walk")] + #[cfg_attr(docsrs, doc(cfg(feature = "walk")))] + #[cfg_attr(feature = "miette", diagnostic(code = "wax::glob::walk"))] + Walk(WalkError), +} + +impl From for GlobError { + fn from(error:BuildError) -> Self { GlobError::Build(error) } +} + +#[cfg(feature = "walk")] +impl From for GlobError { + fn from(error:WalkError) -> Self { GlobError::Walk(error) } +} + +// TODO: `Diagnostic` is implemented with macros for brevity and to ensure +// complete coverage of features. However, this means that documentation +// does not annotate the implementation with a feature flag requirement. +// If possible, perhaps in a later version of Rust, close this gap. +/// Describes errors that occur when building a [`Program`] from a glob +/// expression. +/// +/// Glob expressions may fail to build if they cannot be parsed, violate rules, +/// or cannot be compiled. Parsing errors occur when a glob expression has +/// invalid syntax. Programs must also follow rules as described in the +/// [repository documentation](https://github.com/olson-sean-k/wax/blob/master/README.md), which are designed +/// to avoid nonsense expressions and ambiguity. Lastly, compilation errors +/// occur **only if the size of the compiled program is too large** (all other +/// compilation errors are considered internal bugs and will panic). +/// +/// When the `miette` feature is enabled, this and other error types implement +/// the [`Diagnostic`] trait. Due to a technical limitation, this may not be +/// properly annotated in API documentation. +/// +/// [`Diagnostic`]: miette::Diagnostic +/// [`Program`]: crate::Program +#[cfg_attr(feature = "miette", derive(Diagnostic))] +#[cfg_attr(feature = "miette", diagnostic(transparent))] +#[derive(Debug, Error)] +#[error(transparent)] +pub struct BuildError { + kind:BuildErrorKind, +} + +impl BuildError { + /// Gets [`LocatedError`]s detailing the errors within a glob expression. + /// + /// This function returns an [`Iterator`] over the [`LocatedError`]s that + /// detail where and why an error occurred when the error has associated + /// [`Span`]s within a glob expression. For errors with no such + /// associated information, the [`Iterator`] yields no items, such as + /// compilation errors. + /// + /// # Examples + /// + /// [`LocatedError`]s can be used to provide information to users about + /// which parts of a glob expression are associated with an error. + /// + /// ```rust + /// use wax::Glob; + /// + /// // This glob expression violates rules. The error handling code prints details about the + /// // alternative where the violation occurred. + /// let expression = "**/{foo,**/bar,baz}"; + /// match Glob::new(expression) { + /// Ok(glob) => { + /// // ... + /// }, + /// Err(error) => { + /// eprintln!("{}", error); + /// for error in error.locations() { + /// let (start, n) = error.span(); + /// let fragment = &expression[start..][..n]; + /// eprintln!("in sub-expression `{}`: {}", fragment, error); + /// } + /// }, + /// } + /// ``` + /// + /// [`Glob`]: crate::Glob + /// [`Glob::partition`]: crate::Glob::partition + /// [`Iterator`]: std::iter::Iterator + /// [`LocatedError`]: crate::LocatedError + /// [`Span`]: crate::Span + pub fn locations(&self) -> impl Iterator { + let locations:Vec<_> = match self.kind { + BuildErrorKind::Parse(ref error) => { + error.locations().iter().map(|location| location as &dyn LocatedError).collect() + }, + BuildErrorKind::Rule(ref error) => { + error.locations().iter().map(|location| location as &dyn LocatedError).collect() + }, + _ => vec![], + }; + locations.into_iter() + } +} + +impl From for BuildError { + fn from(kind:BuildErrorKind) -> Self { BuildError { kind } } +} + +impl From for BuildError { + fn from(error:CompileError) -> Self { BuildError { kind:BuildErrorKind::Compile(error) } } +} + +impl From for BuildError { + fn from(_:Infallible) -> Self { unreachable!() } +} + +impl<'t> From> for BuildError { + fn from(error:ParseError<'t>) -> Self { + BuildError { kind:BuildErrorKind::Parse(error.into_owned()) } + } +} + +impl<'t> From> for BuildError { + fn from(error:RuleError<'t>) -> Self { + BuildError { kind:BuildErrorKind::Rule(error.into_owned()) } + } +} + +#[derive(Debug, Error)] +#[non_exhaustive] +#[cfg_attr(feature = "miette", derive(Diagnostic))] +enum BuildErrorKind { + #[error(transparent)] + #[cfg_attr(feature = "miette", diagnostic(transparent))] + Compile(CompileError), + #[error(transparent)] + #[cfg_attr(feature = "miette", diagnostic(transparent))] + Parse(ParseError<'static>), + #[error(transparent)] + #[cfg_attr(feature = "miette", diagnostic(transparent))] + Rule(RuleError<'static>), +} + +/// Path that can be matched against a [`Program`]. +/// +/// `CandidatePath`s are always UTF-8 encoded. On some platforms this requires a +/// lossy conversion that uses Unicode replacement codepoints `�` whenever a +/// part of a path cannot be represented as valid UTF-8 (such as Windows). This +/// means that some byte sequences cannot be matched, though this is uncommon in +/// practice. +/// +/// [`Program`]: crate::Program +#[derive(Clone)] +pub struct CandidatePath<'b> { + text:Cow<'b, str>, +} + +impl<'b> CandidatePath<'b> { + /// Clones any borrowed data into an owning instance. + pub fn into_owned(self) -> CandidatePath<'static> { + CandidatePath { text:self.text.into_owned().into() } + } +} + +impl AsRef for CandidatePath<'_> { + fn as_ref(&self) -> &str { self.text.as_ref() } +} + +impl Debug for CandidatePath<'_> { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.text) } +} + +impl Display for CandidatePath<'_> { + fn fmt(&self, f:&mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.text) } +} + +impl<'b> From<&'b OsStr> for CandidatePath<'b> { + fn from(text:&'b OsStr) -> Self { CandidatePath { text:text.to_string_lossy() } } +} + +impl<'b> From<&'b Path> for CandidatePath<'b> { + fn from(path:&'b Path) -> Self { CandidatePath::from(path.as_os_str()) } +} + +impl<'b> From<&'b str> for CandidatePath<'b> { + fn from(text:&'b str) -> Self { CandidatePath { text:text.into() } } +} + +/// Program that can be matched against paths and directory trees. +/// +/// `Glob`s are constructed from strings called glob expressions that resemble +/// Unix paths consisting of nominal components delimited by separators. Glob +/// expressions support various patterns that match and capture specified text +/// in a path. These patterns can be used to logically match individual paths +/// and to semantically match and walk directory trees. +/// +/// # Examples +/// +/// A `Glob` can be used to determine if a path matches a pattern via the +/// [`Program`] trait. +/// +/// ```rust +/// use wax::{Glob, Program}; +/// +/// let glob = Glob::new("*.png").unwrap(); +/// assert!(glob.is_match("apple.png")); +/// ``` +/// +/// Patterns form captures, which can be used to isolate matching sub-text. +/// +/// ```rust +/// use wax::{CandidatePath, Glob, Program}; +/// +/// let glob = Glob::new("**/{*.{go,rs}}").unwrap(); +/// let candidate = CandidatePath::from("src/lib.rs"); +/// assert_eq!("lib.rs", glob.matched(&candidate).unwrap().get(2).unwrap()); +/// ``` +/// +/// To match a `Glob` against a directory tree, the [`walk`] function can be +/// used to get an iterator over matching paths. +/// +/// ```rust,no_run,ignore +/// use wax::walk::Entry; +/// use wax::Glob; +/// +/// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); +/// for entry in glob.walk("./Pictures") { +/// let entry = entry.unwrap(); +/// println!("JPEG: {:?}", entry.path()); +/// } +/// ``` +/// +/// [`Program`]: crate::Program +/// [`walk`]: crate::Glob::walk +#[derive(Clone, Debug)] +pub struct Glob<'t> { + tree:Checked>, + program:Regex, +} + +impl<'t> Glob<'t> { + fn compile(tokens:impl IntoIterator) -> Result + where + T: Borrow>, { + encode::compile(tokens) + } + + // TODO: Document pattern syntax in the crate documentation and refer to it + // here. + /// Constructs a [`Glob`] from a glob expression. + /// + /// A glob expression is UTF-8 encoded text that resembles a Unix path + /// consisting of nominal components delimited by separators and + /// patterns that can be matched against native paths. + /// + /// # Errors + /// + /// Returns an error if the glob expression fails to build. See + /// [`BuildError`]. + /// + /// [`Glob`]: crate::Glob + /// [`BuildError`]: crate::BuildError + pub fn new(expression:&'t str) -> Result { + let tree = parse_and_check(expression)?; + let program = Glob::compile(tree.as_ref().tokens())?; + Ok(Glob { tree, program }) + } + + /// Partitions a [`Glob`] into an invariant [`PathBuf`] prefix and variant + /// [`Glob`] postfix. + /// + /// The invariant prefix contains no glob patterns nor other variant + /// components and therefore can be interpreted as a native path. The + /// [`Glob`] postfix is variant and contains the remaining components + /// that follow the prefix. For example, the glob expression `.local/**/ + /// *.log` would produce the path `.local` and glob `**/*.log`. It is + /// possible for either partition to be empty. + /// + /// Literal components may be considered variant if they contain characters + /// with casing and the configured case sensitivity differs from the + /// target platform's file system. For example, the case-insensitive + /// literal expression `(?i)photos` is considered variant on Unix and + /// invariant on Windows, because the literal `photos` resolves differently + /// in Unix file system APIs. + /// + /// Partitioning a [`Glob`] allows any invariant prefix to be used as a + /// native path to establish a working directory or to interpret + /// semantic components that are not recognized by globs, such as parent + /// directory `..` components. + /// + /// Partitioned [`Glob`]s are never rooted. If the glob expression has a + /// root component, then it is always included in the invariant + /// [`PathBuf`] prefix. + /// + /// # Examples + /// + /// To match paths against a [`Glob`] while respecting semantic components, + /// the invariant prefix and candidate path can be canonicalized. The + /// following example canonicalizes both the working directory joined + /// with the prefix as well as the candidate path and then attempts to + /// match the [`Glob`] if the candidate path contains the prefix. + /// + /// ```rust,no_run + /// use dunce; // Avoids UNC paths on Windows. + /// use std::path::Path; + /// use wax::{Glob, Program}; + /// + /// let path: &Path = /* ... */ // Candidate path. + /// # Path::new(""); + /// + /// let directory = Path::new("."); // Working directory. + /// let (prefix, glob) = Glob::new("../../src/**").unwrap().partition(); + /// let prefix = dunce::canonicalize(directory.join(&prefix)).unwrap(); + /// if dunce::canonicalize(path) + /// .unwrap() + /// .strip_prefix(&prefix) + /// .map(|path| glob.is_match(path)) + /// .unwrap_or(false) + /// { + /// // ... + /// } + /// ``` + /// + /// [`Glob`]: crate::Glob + /// [`ParseError`]: crate::ParseError + /// [`PathBuf`]: std::path::PathBuf + /// [`RuleError`]: crate::RuleError + /// [`walk`]: crate::Glob::walk + pub fn partition(self) -> (PathBuf, Self) { + let Glob { tree, .. } = self; + let (prefix, tree) = tree.partition(); + let program = + Glob::compile(tree.as_ref().tokens()).expect("failed to compile partitioned glob"); + (prefix, Glob { tree, program }) + } + + /// Clones any borrowed data into an owning instance. + /// + /// # Examples + /// + /// `Glob`s borrow data in the corresponding glob expression. To move a + /// `Glob` beyond the scope of a glob expression, clone the data with + /// this function. + /// + /// ```rust + /// use wax::{BuildError, Glob}; + /// + /// fn local() -> Result, BuildError> { + /// let expression = String::from("**/*.txt"); + /// Glob::new(&expression).map(Glob::into_owned) + /// } + /// ``` + pub fn into_owned(self) -> Glob<'static> { + let Glob { tree, program } = self; + Glob { tree:tree.into_owned(), program } + } + + /// Gets metadata for capturing sub-expressions. + /// + /// This function returns an iterator over capturing tokens, which describe + /// the index and location of sub-expressions that capture [matched + /// text][`MatchedText`]. For example, in the expression `src/**/*.rs`, + /// both `**` and `*` form captures. + /// + /// [`MatchedText`]: crate::MatchedText + pub fn captures(&self) -> impl '_ + Clone + Iterator { + self.tree + .as_ref() + .tokens() + .iter() + .filter(|token| token.is_capturing()) + .enumerate() + .map(|(index, token)| CapturingToken { index:index + 1, span:*token.annotation() }) + } + + /// Returns `true` if the glob has a root. + /// + /// As with Unix paths, a glob expression has a root if it begins with a + /// separator `/`. Patterns other than separators may also root an + /// expression, such as `/**` or ``. + pub fn has_root(&self) -> bool { + self.tree.as_ref().tokens().first().map_or(false, Token::has_root) + } + + /// Returns `true` if the glob has literals that have non-nominal semantics + /// on the target platform. + /// + /// The most notable semantic literals are the relative path components `.` + /// and `..`, which refer to a current and parent directory on Unix and + /// Windows operating systems, respectively. These are interpreted as + /// literals in glob expressions, and so only logically match paths that + /// contain these exact nominal components (semantic meaning is lost). + /// + /// See [`Glob::partition`]. + /// + /// [`Glob::partition`]: crate::Glob::partition + pub fn has_semantic_literals(&self) -> bool { + token::literals(self.tree.as_ref().tokens()) + .any(|(_, literal)| literal.is_semantic_literal()) + } +} + +impl Display for Glob<'_> { + fn fmt(&self, f:&mut Formatter) -> fmt::Result { + write!(f, "{}", self.tree.as_ref().expression()) + } +} + +impl FromStr for Glob<'static> { + type Err = BuildError; + + fn from_str(expression:&str) -> Result { + Glob::new(expression).map(Glob::into_owned) + } +} + +impl<'t> Program<'t> for Glob<'t> { + fn is_match<'p>(&self, path:impl Into>) -> bool { + let path = path.into(); + self.program.is_match(path.as_ref()) + } + + fn matched<'p>(&self, path:&'p CandidatePath<'_>) -> Option> { + self.program.captures(path.as_ref()).map(From::from) + } + + fn variance(&self) -> Variance { self.tree.as_ref().variance().into() } + + fn is_exhaustive(&self) -> bool { token::is_exhaustive(self.tree.as_ref().tokens()) } +} + +impl<'t> TryFrom<&'t str> for Glob<'t> { + type Error = BuildError; + + fn try_from(expression:&'t str) -> Result { Glob::new(expression) } +} + +impl<'t> Pattern<'t> for Glob<'t> { + type Error = Infallible; + type Tokens = Tokenized<'t>; +} + +/// Combinator that matches any of its component [`Program`]s. +/// +/// An instance of `Any` is constructed using the [`any`] function, which +/// combines multiple [`Program`]s for more ergonomic and efficient matching. +/// +/// [`any`]: crate::any +/// [`Program`]: crate::Program +#[derive(Clone, Debug)] +pub struct Any<'t> { + tree:Checked>, + program:Regex, +} + +impl<'t> Any<'t> { + fn compile(token:&Token<'t, ()>) -> Result { encode::compile([token]) } +} + +impl<'t> Program<'t> for Any<'t> { + fn is_match<'p>(&self, path:impl Into>) -> bool { + let path = path.into(); + self.program.is_match(path.as_ref()) + } + + fn matched<'p>(&self, path:&'p CandidatePath<'_>) -> Option> { + self.program.captures(path.as_ref()).map(From::from) + } + + fn variance(&self) -> Variance { self.tree.as_ref().variance::().into() } + + fn is_exhaustive(&self) -> bool { token::is_exhaustive(Some(self.tree.as_ref())) } +} + +impl<'t> Pattern<'t> for Any<'t> { + type Error = Infallible; + type Tokens = Token<'t, ()>; +} + +// TODO: It may be useful to use dynamic dispatch via trait objects instead. +// This would allow for a variety of types to be composed in an `any` call +// and would be especially useful if additional combinators are +// introduced. +/// Constructs a combinator that matches if any of its input [`Program`]s match. +/// +/// This function accepts an [`IntoIterator`] with items that implement +/// [`Combine`], such as [`Glob`] and `&str`. The output [`Any`] implements +/// [`Program`] by matching its component [`Program`]s. [`Any`] is often more +/// ergonomic and efficient than matching individually against +/// multiple [`Program`]s. +/// +/// [`Any`] groups all captures and therefore only exposes the complete text of +/// a match. It is not possible to index a particular capturing token in the +/// component patterns. Combinators only support logical matching and cannot be +/// used to semantically match (walk) a directory tree. +/// +/// # Examples +/// +/// To match a path against multiple patterns, the patterns can first be +/// combined into an [`Any`]. +/// +/// ```rust +/// use wax::{Glob, Program}; +/// +/// let any = wax::any(["src/**/*.rs", "tests/**/*.rs", "doc/**/*.md", "pkg/**/PKGBUILD"]).unwrap(); +/// assert!(any.is_match("src/lib.rs")); +/// ``` +/// +/// [`Glob`]s and other compiled [`Program`]s can also be composed into an +/// [`Any`]. +/// +/// ```rust +/// use wax::{Glob, Program}; +/// +/// let red = Glob::new("**/red/**/*.txt").unwrap(); +/// let blue = Glob::new("**/*blue*.txt").unwrap(); +/// assert!(wax::any([red, blue]).unwrap().is_match("red/potion.txt")); +/// ``` +/// +/// This function can only combine patterns of the same type, but intermediate +/// combinators can be used to combine different types into a single combinator. +/// +/// ```rust +/// use wax::{Glob, Program}; +/// +/// # fn fallible() -> Result<(), wax::BuildError> { +/// let glob = Glob::new("**/*.txt")?; +/// +/// // ... +/// +/// #[rustfmt::skip] +/// let any = wax::any([ +/// wax::any([glob])?, +/// wax::any([ +/// "**/*.pdf", +/// "**/*.tex", +/// ])?, +/// ])?; +/// assert!(any.is_match("doc/lattice.tex")); +/// # Ok(()) +/// # } +/// ``` +/// +/// # Errors +/// +/// Returns an error if any of the inputs fail to build. If the inputs are a +/// compiled [`Program`] type such as [`Glob`], then this only occurs if the +/// compiled program is too large. +/// +/// [`Any`]: crate::Any +/// [`Combine`]: crate::Combine +/// [`Glob`]: crate::Glob +/// [`IntoIterator`]: std::iter::IntoIterator +/// [`Program`]: crate::Pattern +pub fn any<'t, I>(patterns:I) -> Result, BuildError> +where + I: IntoIterator, + I::Item: Pattern<'t>, { + let tree = Checked::any( + patterns + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .map_err(Into::into)?, + ); + let program = Any::compile(tree.as_ref())?; + Ok(Any { tree, program }) +} + +/// Escapes text as a literal glob expression. +/// +/// This function escapes any and all meta-characters in the given string, such +/// that all text is interpreted as a literal or separator when read as a glob +/// expression. +/// +/// # Examples +/// +/// This function can be used to escape opaque strings, such as a string +/// obtained from a user that must be interpreted literally. +/// +/// ```rust +/// use wax::Glob; +/// +/// // An opaque file name that this code does not construct. +/// let name:String = { +/// // ... +/// # String::from("file.txt") +/// }; +/// +/// // Do not allow patterns in `name`. +/// let expression = format!("{}{}", "**/", wax::escape(&name)); +/// if let Ok(glob) = Glob::new(&expression) { /* ... */ } +/// ``` +/// +/// Sometimes part of a path contains numerous meta-characters. This function +/// can be used to reliably escape them while making the unescaped part of the +/// expression a bit easier to read. +/// +/// ```rust +/// use wax::Glob; +/// +/// let expression = format!("{}{}", "logs/**/", wax::escape("ingest[01](L).txt")); +/// let glob = Glob::new(&expression).unwrap(); +/// ``` +// It is possible to call this function using a mutable reference, which may appear to mutate the +// parameter in place. +#[must_use] +pub fn escape(unescaped:&str) -> Cow { + const ESCAPE:char = '\\'; + + if unescaped.chars().any(is_meta_character) { + let mut escaped = String::new(); + for x in unescaped.chars() { + if is_meta_character(x) { + escaped.push(ESCAPE); + } + escaped.push(x); + } + escaped.into() + } else { + unescaped.into() + } +} + +// TODO: Is it possible for `:` and `,` to be contextual meta-characters? +/// Returns `true` if the given character is a meta-character. +/// +/// This function does **not** return `true` for contextual meta-characters that +/// may only be escaped in particular contexts, such as hyphens `-` in character +/// class expressions. To detect these characters, use +/// [`is_contextual_meta_character`]. +/// +/// [`is_contextual_meta_character`]: crate::is_contextual_meta_character +pub const fn is_meta_character(x:char) -> bool { + matches!(x, '?' | '*' | '$' | ':' | '<' | '>' | '(' | ')' | '[' | ']' | '{' | '}' | ',') +} + +/// Returns `true` if the given character is a contextual meta-character. +/// +/// Contextual meta-characters may only be escaped in particular contexts, such +/// as hyphens `-` in character class expressions. Elsewhere, they are +/// interpreted as literals. To detect non-contextual meta-characters, use +/// [`is_meta_character`]. +/// +/// [`is_meta_character`]: crate::is_meta_character +pub const fn is_contextual_meta_character(x:char) -> bool { matches!(x, '-') } + +fn parse_and_check(expression:&str) -> Result, BuildError> { + let tokenized = token::parse(expression)?; + let checked = rule::check(tokenized)?; + Ok(checked) +} + +// TODO: Construct paths from components in tests. In practice, using string +// literals works, but is technically specific to platforms that support +// `/` as a separator. +#[cfg(test)] +mod tests { + use std::path::Path; + + use crate::{BuildError, BuildErrorKind, CandidatePath, Glob, Program}; + + #[test] + fn escape() { + assert_eq!(crate::escape(""), ""); + assert_eq!(crate::escape("?*$:<>()[]{},"), "\\?\\*\\$\\:\\<\\>\\(\\)\\[\\]\\{\\}\\,",); + assert_eq!(crate::escape("/usr/local/lib"), "/usr/local/lib"); + assert_eq!(crate::escape("record[D00,00].txt"), "record\\[D00\\,00\\].txt",); + assert_eq!(crate::escape("Do You Remember Love?.mp4"), "Do You Remember Love\\?.mp4",); + assert_eq!(crate::escape("å·¦{}å³"), "å·¦\\{\\}å³"); + assert_eq!(crate::escape("*中*"), "\\*中\\*"); + } + + #[test] + fn build_glob_with_eager_zom_tokens() { + Glob::new("*").unwrap(); + Glob::new("a/*").unwrap(); + Glob::new("*a").unwrap(); + Glob::new("a*").unwrap(); + Glob::new("a*b").unwrap(); + Glob::new("/*").unwrap(); + } + + #[test] + fn build_glob_with_lazy_zom_tokens() { + Glob::new("$").unwrap(); + Glob::new("a/$").unwrap(); + Glob::new("$a").unwrap(); + Glob::new("a$").unwrap(); + Glob::new("a$b").unwrap(); + Glob::new("/$").unwrap(); + } + + #[test] + fn build_glob_with_one_tokens() { + Glob::new("?").unwrap(); + Glob::new("a/?").unwrap(); + Glob::new("?a").unwrap(); + Glob::new("a?").unwrap(); + Glob::new("a?b").unwrap(); + Glob::new("??a??b??").unwrap(); + Glob::new("/?").unwrap(); + } + + #[test] + fn build_glob_with_one_and_zom_tokens() { + Glob::new("?*").unwrap(); + Glob::new("*?").unwrap(); + Glob::new("*/?").unwrap(); + Glob::new("?*?").unwrap(); + Glob::new("/?*").unwrap(); + Glob::new("?$").unwrap(); + } + + #[test] + fn build_glob_with_tree_tokens() { + Glob::new("**").unwrap(); + Glob::new("**/").unwrap(); + Glob::new("/**").unwrap(); + Glob::new("**/a").unwrap(); + Glob::new("a/**").unwrap(); + Glob::new("**/a/**/b/**").unwrap(); + Glob::new("{**/a,b/c}").unwrap(); + Glob::new("{a/b,c/**}").unwrap(); + Glob::new("<**/a>").unwrap(); + Glob::new("").unwrap(); + } + + #[test] + fn build_glob_with_class_tokens() { + Glob::new("a/[xy]").unwrap(); + Glob::new("a/[x-z]").unwrap(); + Glob::new("a/[xyi-k]").unwrap(); + Glob::new("a/[i-kxy]").unwrap(); + Glob::new("a/[!xy]").unwrap(); + Glob::new("a/[!x-z]").unwrap(); + Glob::new("a/[^xy]").unwrap(); + Glob::new("a/[^x-z]").unwrap(); + Glob::new("a/[xy]b/c").unwrap(); + } + + #[test] + fn negative_match_does_not_traverse_folders() { + let glob = Glob::new("a[!b]c").unwrap(); + assert!(glob.is_match(Path::new("adc"))); + assert!(!glob.is_match(Path::new("a/c"))); + } + + #[test] + fn negative_match_does_not_traverse_folders_2() { + let glob = Glob::new("a[!b-z]c").unwrap(); + assert!(glob.is_match(Path::new("aac"))); + assert!(!glob.is_match(Path::new("a/c"))); + } + + #[test] + fn build_glob_with_alternative_tokens() { + Glob::new("a/{x?z,y$}b*").unwrap(); + Glob::new("a/{???,x$y,frob}b*").unwrap(); + Glob::new("a/{???,x$y,frob}b*").unwrap(); + Glob::new("a/{???,{x*z,y$}}b*").unwrap(); + Glob::new("a{/**/b/,/b/**/}ca{t,b/**}").unwrap(); + } + + #[test] + fn build_glob_with_repetition_tokens() { + Glob::new("").unwrap(); + Glob::new("").unwrap(); + Glob::new("").unwrap(); + Glob::new("").unwrap(); + Glob::new("").unwrap(); + Glob::new(":0,>").unwrap(); + // Rooted repetitions are accepted if the lower bound is one or greater. + Glob::new("").unwrap(); + Glob::new("<[!.]*/:0,>[!.]*").unwrap(); + } + + #[test] + fn build_glob_with_literal_escaped_wildcard_tokens() { + Glob::new("a/b\\?/c").unwrap(); + Glob::new("a/b\\$/c").unwrap(); + Glob::new("a/b\\*/c").unwrap(); + Glob::new("a/b\\*\\*/c").unwrap(); + } + + #[test] + fn build_glob_with_class_escaped_wildcard_tokens() { + Glob::new("a/b[?]/c").unwrap(); + Glob::new("a/b[$]/c").unwrap(); + Glob::new("a/b[*]/c").unwrap(); + Glob::new("a/b[*][*]/c").unwrap(); + } + + #[test] + fn build_glob_with_literal_escaped_alternative_tokens() { + Glob::new("a/\\{\\}/c").unwrap(); + Glob::new("a/{x,y\\,,z}/c").unwrap(); + } + + #[test] + fn build_glob_with_class_escaped_alternative_tokens() { + Glob::new("a/[{][}]/c").unwrap(); + Glob::new("a/{x,y[,],z}/c").unwrap(); + } + + #[test] + fn build_glob_with_literal_escaped_class_tokens() { + Glob::new("a/\\[a-z\\]/c").unwrap(); + Glob::new("a/[\\[]/c").unwrap(); + Glob::new("a/[\\]]/c").unwrap(); + Glob::new("a/[a\\-z]/c").unwrap(); + } + + #[test] + fn build_glob_with_flags() { + Glob::new("(?i)a/b/c").unwrap(); + Glob::new("(?-i)a/b/c").unwrap(); + Glob::new("a/(?-i)b/c").unwrap(); + Glob::new("a/b/(?-i)c").unwrap(); + Glob::new("(?i)a/(?-i)b/(?i)c").unwrap(); + } + + #[test] + fn build_any_combinator() { + crate::any([ + Glob::new("src/**/*.rs").unwrap(), + Glob::new("doc/**/*.md").unwrap(), + Glob::new("pkg/**/PKGBUILD").unwrap(), + ]) + .unwrap(); + crate::any(["src/**/*.rs", "doc/**/*.md", "pkg/**/PKGBUILD"]).unwrap(); + } + + #[test] + fn build_any_nested_combinator() { + crate::any([ + crate::any(["a/b", "c/d"]).unwrap(), + crate::any(["{e,f,g}", "{h,i}"]).unwrap(), + ]) + .unwrap(); + } + + #[test] + fn reject_glob_with_invalid_separator_tokens() { + assert!(Glob::new("//a").is_err()); + assert!(Glob::new("a//b").is_err()); + assert!(Glob::new("a/b//").is_err()); + assert!(Glob::new("a//**").is_err()); + assert!(Glob::new("{//}a").is_err()); + assert!(Glob::new("{**//}").is_err()); + } + + #[test] + fn reject_glob_with_adjacent_tree_or_zom_tokens() { + assert!(Glob::new("***").is_err()); + assert!(Glob::new("****").is_err()); + assert!(Glob::new("**/**").is_err()); + assert!(Glob::new("a{**/**,/b}").is_err()); + assert!(Glob::new("**/*/***").is_err()); + assert!(Glob::new("**$").is_err()); + assert!(Glob::new("**/$**").is_err()); + assert!(Glob::new("{*$}").is_err()); + assert!(Glob::new("<*$:1,>").is_err()); + } + + #[test] + fn reject_glob_with_tree_adjacent_literal_tokens() { + assert!(Glob::new("**a").is_err()); + assert!(Glob::new("a**").is_err()); + assert!(Glob::new("a**b").is_err()); + assert!(Glob::new("a*b**").is_err()); + assert!(Glob::new("**/**a/**").is_err()); + } + + #[test] + fn reject_glob_with_adjacent_one_tokens() { + assert!(Glob::new("**?").is_err()); + assert!(Glob::new("?**").is_err()); + assert!(Glob::new("?**?").is_err()); + assert!(Glob::new("?*?**").is_err()); + assert!(Glob::new("**/**?/**").is_err()); + } + + #[test] + fn reject_glob_with_unescaped_meta_characters_in_class_tokens() { + assert!(Glob::new("a/[a-z-]/c").is_err()); + assert!(Glob::new("a/[-a-z]/c").is_err()); + assert!(Glob::new("a/[-]/c").is_err()); + // NOTE: Without special attention to escaping and character parsing, this could + // be mistakenly interpreted as an empty range over the character + // `-`. This should be rejected. + assert!(Glob::new("a/[---]/c").is_err()); + assert!(Glob::new("a/[[]/c").is_err()); + assert!(Glob::new("a/[]]/c").is_err()); + } + + #[test] + fn reject_glob_with_invalid_alternative_zom_tokens() { + assert!(Glob::new("*{okay,*}").is_err()); + assert!(Glob::new("{okay,*}*").is_err()); + assert!(Glob::new("${okay,*error}").is_err()); + assert!(Glob::new("{okay,error*}$").is_err()); + assert!(Glob::new("{*,okay}{okay,*}").is_err()); + assert!(Glob::new("{okay,error*}{okay,*error}").is_err()); + } + + #[test] + fn reject_glob_with_invalid_alternative_tree_tokens() { + assert!(Glob::new("{**}").is_err()); + assert!(Glob::new("slash/{**/error}").is_err()); + assert!(Glob::new("{error/**}/slash").is_err()); + assert!(Glob::new("slash/{okay/**,**/error}").is_err()); + assert!(Glob::new("{**/okay,error/**}/slash").is_err()); + assert!(Glob::new("{**/okay,prefix{error/**}}/slash").is_err()); + assert!(Glob::new("{**/okay,slash/{**/error}}postfix").is_err()); + assert!(Glob::new("{error/**}{okay,**/error").is_err()); + } + + #[test] + fn reject_glob_with_invalid_alternative_separator_tokens() { + assert!(Glob::new("/slash/{okay,/error}").is_err()); + assert!(Glob::new("{okay,error/}/slash").is_err()); + assert!(Glob::new("slash/{okay,/error/,okay}/slash").is_err()); + assert!(Glob::new("{okay,error/}{okay,/error}").is_err()); + } + + #[test] + fn reject_glob_with_rooted_alternative_tokens() { + assert!(Glob::new("{okay,/}").is_err()); + assert!(Glob::new("{okay,/**}").is_err()); + assert!(Glob::new("{okay,/error}").is_err()); + assert!(Glob::new("{okay,/**/error}").is_err()); + } + + #[test] + fn reject_glob_with_invalid_repetition_bounds_tokens() { + assert!(Glob::new("").is_err()); + } + + #[test] + fn reject_glob_with_invalid_repetition_zom_tokens() { + assert!(Glob::new("<*:0,>").is_err()); + assert!(Glob::new("*").is_err()); + assert!(Glob::new("*<*a:0,>").is_err()); + } + + #[test] + fn reject_glob_with_invalid_repetition_tree_tokens() { + assert!(Glob::new("<**:0,>").is_err()); + assert!(Glob::new("").is_err()); + assert!(Glob::new("/").is_err()); + assert!(Glob::new("/**").is_err()); + } + + #[test] + fn reject_glob_with_invalid_repetition_separator_tokens() { + assert!(Glob::new("").is_err()); + assert!(Glob::new("").is_err()); + assert!(Glob::new("/").is_err()); + } + + // Rooted repetitions are rejected if their lower bound is zero; any other lower + // bound is accepted. + #[test] + fn reject_glob_with_rooted_repetition_tokens() { + assert!(Glob::new("maybe").is_err()); + assert!(Glob::new("").is_err()); + } + + #[test] + fn reject_glob_with_oversized_invariant_repetition_tokens() { + assert!(matches!( + Glob::new(""), + Err(BuildError { kind:BuildErrorKind::Rule(_), .. }), + )); + assert!(matches!( + Glob::new(""), + Err(BuildError { kind:BuildErrorKind::Rule(_), .. }), + )); + assert!(matches!( + Glob::new("ab"), + Err(BuildError { kind:BuildErrorKind::Rule(_), .. }), + )); + assert!(matches!( + Glob::new("{,}"), + Err(BuildError { kind:BuildErrorKind::Rule(_), .. }), + )); + } + + #[test] + fn reject_glob_with_invalid_flags() { + assert!(Glob::new("(?)a").is_err()); + assert!(Glob::new("(?-)a").is_err()); + assert!(Glob::new("()a").is_err()); + } + + #[test] + fn reject_glob_with_adjacent_tokens_through_flags() { + assert!(Glob::new("/(?i)/").is_err()); + assert!(Glob::new("$(?i)$").is_err()); + assert!(Glob::new("*(?i)*").is_err()); + assert!(Glob::new("**(?i)?").is_err()); + assert!(Glob::new("a(?i)**").is_err()); + assert!(Glob::new("**(?i)a").is_err()); + } + + #[test] + fn reject_glob_with_oversized_program() { + assert!(matches!( + Glob::new(""), + Err(BuildError { kind:BuildErrorKind::Compile(_), .. }), + )); + } + + #[test] + fn reject_any_combinator() { + assert!(crate::any(["{a,b,c}", "{d, e}", "f/{g,/error,h}",]).is_err()) + } + + #[test] + fn match_glob_with_empty_expression() { + let glob = Glob::new("").unwrap(); + + assert!(glob.is_match(Path::new(""))); + + assert!(!glob.is_match(Path::new("abc"))); + } + + #[test] + fn match_glob_with_only_invariant_tokens() { + let glob = Glob::new("a/b").unwrap(); + + assert!(glob.is_match(Path::new("a/b"))); + + assert!(!glob.is_match(Path::new("aa/b"))); + assert!(!glob.is_match(Path::new("a/bb"))); + assert!(!glob.is_match(Path::new("a/b/c"))); + + // There are no variant tokens with which to capture, but the matched text + // should always be available. + assert_eq!("a/b", glob.matched(&CandidatePath::from(Path::new("a/b"))).unwrap().complete(),); + } + + #[test] + fn match_glob_with_tree_tokens() { + let glob = Glob::new("a/**/b").unwrap(); + + assert!(glob.is_match(Path::new("a/b"))); + assert!(glob.is_match(Path::new("a/x/b"))); + assert!(glob.is_match(Path::new("a/x/y/z/b"))); + + assert!(!glob.is_match(Path::new("a"))); + assert!(!glob.is_match(Path::new("b/a"))); + + assert_eq!( + "x/y/z/", + glob.matched(&CandidatePath::from(Path::new("a/x/y/z/b"))) + .unwrap() + .get(1) + .unwrap(), + ); + } + + #[test] + fn match_glob_with_tree_and_zom_tokens() { + let glob = Glob::new("**/*.ext").unwrap(); + + assert!(glob.is_match(Path::new("file.ext"))); + assert!(glob.is_match(Path::new("a/file.ext"))); + assert!(glob.is_match(Path::new("a/b/file.ext"))); + + let path = CandidatePath::from(Path::new("a/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("a/", matched.get(1).unwrap()); + assert_eq!("file", matched.get(2).unwrap()); + } + + #[test] + fn match_glob_with_eager_and_lazy_zom_tokens() { + let glob = Glob::new("$-*.*").unwrap(); + + assert!(glob.is_match(Path::new("prefix-file.ext"))); + assert!(glob.is_match(Path::new("a-b-c.ext"))); + + let path = CandidatePath::from(Path::new("a-b-c.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("a", matched.get(1).unwrap()); + assert_eq!("b-c", matched.get(2).unwrap()); + assert_eq!("ext", matched.get(3).unwrap()); + } + + #[test] + fn match_glob_with_class_tokens() { + let glob = Glob::new("a/[xyi-k]/**").unwrap(); + + assert!(glob.is_match(Path::new("a/x/file.ext"))); + assert!(glob.is_match(Path::new("a/y/file.ext"))); + assert!(glob.is_match(Path::new("a/j/file.ext"))); + + assert!(!glob.is_match(Path::new("a/b/file.ext"))); + + let path = CandidatePath::from(Path::new("a/i/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("i", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_non_ascii_class_tokens() { + let glob = Glob::new("a/[金銀]/**").unwrap(); + + assert!(glob.is_match(Path::new("a/金/file.ext"))); + assert!(glob.is_match(Path::new("a/銀/file.ext"))); + + assert!(!glob.is_match(Path::new("a/銅/file.ext"))); + + let path = CandidatePath::from(Path::new("a/金/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("金", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_literal_escaped_class_tokens() { + let glob = Glob::new("a/[\\[\\]\\-]/**").unwrap(); + + assert!(glob.is_match(Path::new("a/[/file.ext"))); + assert!(glob.is_match(Path::new("a/]/file.ext"))); + assert!(glob.is_match(Path::new("a/-/file.ext"))); + + assert!(!glob.is_match(Path::new("a/b/file.ext"))); + + let path = CandidatePath::from(Path::new("a/[/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("[", matched.get(1).unwrap()); + } + + #[cfg(any(unix, windows))] + #[test] + fn match_glob_with_empty_class_tokens() { + // A character class is "empty" if it only matches separators on the target + // platform. Such a character class never matches anything. + let glob = Glob::new("a[/]b").unwrap(); + + assert!(!glob.is_match(Path::new("a/b"))); + assert!(!glob.is_match(Path::new("ab"))); + assert!(!glob.is_match(Path::new("a"))); + assert!(!glob.is_match(Path::new("b"))); + assert!(!glob.is_match(Path::new(""))); + } + + #[test] + fn match_glob_with_negated_class_tokens() { + let glob = Glob::new("a[!b]c").unwrap(); + + assert!(glob.is_match(Path::new("a-c"))); + assert!(glob.is_match(Path::new("axc"))); + + assert!(!glob.is_match(Path::new("abc"))); + assert!(!glob.is_match(Path::new("a/c"))); + + let glob = Glob::new("a[!0-4]b").unwrap(); + + assert!(glob.is_match(Path::new("a9b"))); + assert!(glob.is_match(Path::new("axb"))); + + assert!(!glob.is_match(Path::new("a0b"))); + assert!(!glob.is_match(Path::new("a4b"))); + assert!(!glob.is_match(Path::new("a/b"))); + } + + #[test] + fn match_glob_with_alternative_tokens() { + let glob = Glob::new("a/{x?z,y$}b/*").unwrap(); + + assert!(glob.is_match(Path::new("a/xyzb/file.ext"))); + assert!(glob.is_match(Path::new("a/yb/file.ext"))); + + assert!(!glob.is_match(Path::new("a/xyz/file.ext"))); + assert!(!glob.is_match(Path::new("a/y/file.ext"))); + assert!(!glob.is_match(Path::new("a/xyzub/file.ext"))); + + let path = CandidatePath::from(Path::new("a/xyzb/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("xyz", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_nested_alternative_tokens() { + let glob = Glob::new("a/{y$,{x?z,?z}}b/*").unwrap(); + + let path = CandidatePath::from(Path::new("a/xyzb/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("xyz", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_alternative_tree_tokens() { + let glob = Glob::new("a{/foo,/bar,/**/baz}/qux").unwrap(); + + assert!(glob.is_match(Path::new("a/foo/qux"))); + assert!(glob.is_match(Path::new("a/foo/baz/qux"))); + assert!(glob.is_match(Path::new("a/foo/bar/baz/qux"))); + + assert!(!glob.is_match(Path::new("a/foo/bar/qux"))); + } + + #[test] + fn match_glob_with_alternative_repetition_tokens() { + let glob = Glob::new("log-{<[0-9]:3>,<[0-9]:4>-<[0-9]:2>-<[0-9]:2>}.txt").unwrap(); + + assert!(glob.is_match(Path::new("log-000.txt"))); + assert!(glob.is_match(Path::new("log-1970-01-01.txt"))); + + assert!(!glob.is_match(Path::new("log-abc.txt"))); + assert!(!glob.is_match(Path::new("log-nope-no-no.txt"))); + } + + #[test] + fn match_glob_with_repetition_tokens() { + let glob = Glob::new("a/<[0-9]:6>/*").unwrap(); + + assert!(glob.is_match(Path::new("a/000000/file.ext"))); + assert!(glob.is_match(Path::new("a/123456/file.ext"))); + + assert!(!glob.is_match(Path::new("a/00000/file.ext"))); + assert!(!glob.is_match(Path::new("a/0000000/file.ext"))); + assert!(!glob.is_match(Path::new("a/bbbbbb/file.ext"))); + + let path = CandidatePath::from(Path::new("a/999999/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("999999", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_negative_repetition_tokens() { + let glob = Glob::new("<[!.]*/>[!.]*").unwrap(); + + assert!(glob.is_match(Path::new("a/b/file.ext"))); + + assert!(!glob.is_match(Path::new(".a/b/file.ext"))); + assert!(!glob.is_match(Path::new("a/.b/file.ext"))); + assert!(!glob.is_match(Path::new("a/b/.file.ext"))); + } + + #[test] + fn match_glob_with_nested_repetition_tokens() { + let glob = Glob::new("log<-<[0-9]:3>:1,2>.txt").unwrap(); + + assert!(glob.is_match(Path::new("log-000.txt"))); + assert!(glob.is_match(Path::new("log-123-456.txt"))); + + assert!(!glob.is_match(Path::new("log-abc.txt"))); + assert!(!glob.is_match(Path::new("log-123-456-789.txt"))); + + let path = CandidatePath::from(Path::new("log-987-654.txt")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("-987-654", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_repeated_alternative_tokens() { + let glob = Glob::new("<{a,b}:1,>/**").unwrap(); + + assert!(glob.is_match(Path::new("a/file.ext"))); + assert!(glob.is_match(Path::new("b/file.ext"))); + assert!(glob.is_match(Path::new("aaa/file.ext"))); + assert!(glob.is_match(Path::new("bbb/file.ext"))); + + assert!(!glob.is_match(Path::new("file.ext"))); + assert!(!glob.is_match(Path::new("c/file.ext"))); + + let path = CandidatePath::from(Path::new("aa/file.ext")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("aa", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_rooted_tree_token() { + let glob = Glob::new("/**/{var,.var}/**/*.log").unwrap(); + + assert!(glob.is_match(Path::new("/var/log/network.log"))); + assert!(glob.is_match(Path::new("/home/nobody/.var/network.log"))); + + assert!(!glob.is_match(Path::new("./var/cron.log"))); + assert!(!glob.is_match(Path::new("mnt/var/log/cron.log"))); + + let path = CandidatePath::from(Path::new("/var/log/network.log")); + let matched = glob.matched(&path).unwrap(); + assert_eq!("/", matched.get(1).unwrap()); + } + + #[test] + fn match_glob_with_flags() { + let glob = Glob::new("(?-i)photos/**/*.(?i){jpg,jpeg}").unwrap(); + + assert!(glob.is_match(Path::new("photos/flower.jpg"))); + assert!(glob.is_match(Path::new("photos/flower.JPEG"))); + + assert!(!glob.is_match(Path::new("Photos/flower.jpeg"))); + } + + #[test] + fn match_glob_with_escaped_flags() { + let glob = Glob::new("a\\(b\\)").unwrap(); + + assert!(glob.is_match(Path::new("a(b)"))); + } + + #[test] + fn match_any_combinator() { + let any = crate::any(["src/**/*.rs", "doc/**/*.md", "pkg/**/PKGBUILD"]).unwrap(); + + assert!(any.is_match("src/lib.rs")); + assert!(any.is_match("doc/api.md")); + assert!(any.is_match("pkg/arch/lib-git/PKGBUILD")); + + assert!(!any.is_match("img/icon.png")); + assert!(!any.is_match("doc/LICENSE.tex")); + assert!(!any.is_match("pkg/lib.rs")); + } + + #[test] + fn partition_glob_with_variant_and_invariant_parts() { + let (prefix, glob) = Glob::new("a/b/x?z/*.ext").unwrap().partition(); + + assert_eq!(prefix, Path::new("a/b")); + + assert!(glob.is_match(Path::new("xyz/file.ext"))); + assert!(glob.is_match(Path::new("a/b/xyz/file.ext").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_only_variant_wildcard_parts() { + let (prefix, glob) = Glob::new("x?z/*.ext").unwrap().partition(); + + assert_eq!(prefix, Path::new("")); + + assert!(glob.is_match(Path::new("xyz/file.ext"))); + assert!(glob.is_match(Path::new("xyz/file.ext").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_only_invariant_literal_parts() { + let (prefix, glob) = Glob::new("a/b").unwrap().partition(); + + assert_eq!(prefix, Path::new("a/b")); + + assert!(glob.is_match(Path::new(""))); + assert!(glob.is_match(Path::new("a/b").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_variant_alternative_parts() { + let (prefix, glob) = Glob::new("{x,z}/*.ext").unwrap().partition(); + + assert_eq!(prefix, Path::new("")); + + assert!(glob.is_match(Path::new("x/file.ext"))); + assert!(glob.is_match(Path::new("z/file.ext").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_invariant_alternative_parts() { + let (prefix, glob) = Glob::new("{a/b}/c").unwrap().partition(); + + assert_eq!(prefix, Path::new("a/b/c")); + + assert!(glob.is_match(Path::new(""))); + assert!(glob.is_match(Path::new("a/b/c").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_invariant_repetition_parts() { + let (prefix, glob) = Glob::new("/c").unwrap().partition(); + + assert_eq!(prefix, Path::new("/a/b/a/b/a/b/c")); + + assert!(glob.is_match(Path::new(""))); + assert!(glob.is_match(Path::new("/a/b/a/b/a/b/c").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_literal_dots_and_tree_tokens() { + let (prefix, glob) = Glob::new("../**/*.ext").unwrap().partition(); + + assert_eq!(prefix, Path::new("..")); + + assert!(glob.is_match(Path::new("xyz/file.ext"))); + assert!(glob.is_match(Path::new("../xyz/file.ext").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_rooted_tree_token() { + let (prefix, glob) = Glob::new("/**/*.ext").unwrap().partition(); + + assert_eq!(prefix, Path::new("/")); + assert!(!glob.has_root()); + + assert!(glob.is_match(Path::new("file.ext"))); + assert!(glob.is_match(Path::new("/root/file.ext").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_rooted_zom_token() { + let (prefix, glob) = Glob::new("/*/*.ext").unwrap().partition(); + + assert_eq!(prefix, Path::new("/")); + assert!(!glob.has_root()); + + assert!(glob.is_match(Path::new("root/file.ext"))); + assert!(glob.is_match(Path::new("/root/file.ext").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_rooted_literal_token() { + let (prefix, glob) = Glob::new("/root/**/*.ext").unwrap().partition(); + + assert_eq!(prefix, Path::new("/root")); + assert!(!glob.has_root()); + + assert!(glob.is_match(Path::new("file.ext"))); + assert!(glob.is_match(Path::new("/root/file.ext").strip_prefix(prefix).unwrap())); + } + + #[test] + fn partition_glob_with_invariant_expression_text() { + let (prefix, glob) = Glob::new("/root/file.ext").unwrap().partition(); + assert_eq!(prefix, Path::new("/root/file.ext")); + assert_eq!(format!("{}", glob), ""); + + let (prefix, glob) = Glob::new("/file.ext").unwrap().partition(); + assert_eq!(prefix, Path::new("aaa/file.ext")); + assert_eq!(format!("{}", glob), ""); + } + + #[test] + fn partition_glob_with_variant_expression_text() { + let (prefix, glob) = Glob::new("**/file.ext").unwrap().partition(); + assert_eq!(prefix, Path::new("")); + assert_eq!(format!("{}", glob), "**/file.ext"); + + let (prefix, glob) = Glob::new("/root/**/file.ext").unwrap().partition(); + assert_eq!(prefix, Path::new("/root")); + assert_eq!(format!("{}", glob), "**/file.ext"); + + let (prefix, glob) = Glob::new("/root/**").unwrap().partition(); + assert_eq!(prefix, Path::new("/root")); + assert_eq!(format!("{}", glob), "**"); + } + + #[test] + fn repartition_glob_with_variant_tokens() { + let (prefix, glob) = Glob::new("/root/**/file.ext").unwrap().partition(); + assert_eq!(prefix, Path::new("/root")); + assert_eq!(format!("{}", glob), "**/file.ext"); + + let (prefix, glob) = glob.partition(); + assert_eq!(prefix, Path::new("")); + assert_eq!(format!("{}", glob), "**/file.ext"); + } + + #[test] + fn query_glob_has_root() { + assert!(Glob::new("/root").unwrap().has_root()); + assert!(Glob::new("/**").unwrap().has_root()); + assert!(Glob::new("").unwrap().has_root()); + + assert!(!Glob::new("").unwrap().has_root()); + // This is not rooted, because character classes may not match separators. This + // example compiles an "empty" character class, which attempts to match + // `NUL` and so effectively matches nothing. + #[cfg(any(unix, windows))] + assert!(!Glob::new("[/]root").unwrap().has_root()); + // The leading forward slash in tree tokens is meaningful. When omitted, at the + // beginning of an expression, the resulting glob is not rooted. + assert!(!Glob::new("**/").unwrap().has_root()); + } + + #[cfg(any(unix, windows))] + #[test] + fn query_glob_has_semantic_literals() { + assert!(Glob::new("../src/**").unwrap().has_semantic_literals()); + assert!(Glob::new("*/a/../b.*").unwrap().has_semantic_literals()); + assert!(Glob::new("{a,..}").unwrap().has_semantic_literals()); + assert!(Glob::new("").unwrap().has_semantic_literals()); + assert!(Glob::new("").unwrap().has_semantic_literals()); + assert!(Glob::new("./*.txt").unwrap().has_semantic_literals()); + } + + #[test] + fn query_glob_capture_indices() { + let glob = Glob::new("**/{foo*,bar*}/???").unwrap(); + let indices:Vec<_> = glob.captures().map(|token| token.index()).collect(); + assert_eq!(&indices, &[1, 2, 3, 4, 5]); + } + + #[test] + fn query_glob_capture_spans() { + let glob = Glob::new("**/{foo*,bar*}/$").unwrap(); + let spans:Vec<_> = glob.captures().map(|token| token.span()).collect(); + assert_eq!(&spans, &[(0, 3), (3, 11), (15, 1)]); + } + + #[test] + fn query_glob_variance() { + assert!(Glob::new("").unwrap().variance().is_invariant()); + assert!(Glob::new("/a/file.ext").unwrap().variance().is_invariant()); + assert!(Glob::new("/a/{file.ext}").unwrap().variance().is_invariant()); + assert!(Glob::new("{a/b/file.ext}").unwrap().variance().is_invariant()); + assert!(Glob::new("{a,a}").unwrap().variance().is_invariant()); + #[cfg(windows)] + assert!(Glob::new("{a,A}").unwrap().variance().is_invariant()); + assert!(Glob::new("").unwrap().variance().is_invariant()); + #[cfg(unix)] + assert!(Glob::new("/[a]/file.ext").unwrap().variance().is_invariant()); + #[cfg(unix)] + assert!(Glob::new("/[a-a]/file.ext").unwrap().variance().is_invariant()); + #[cfg(unix)] + assert!(Glob::new("/[a-aaa-a]/file.ext").unwrap().variance().is_invariant()); + + assert!(Glob::new("/a/{b,c}").unwrap().variance().is_variant()); + assert!(Glob::new("").unwrap().variance().is_variant()); + assert!(Glob::new("/[ab]/file.ext").unwrap().variance().is_variant()); + assert!(Glob::new("**").unwrap().variance().is_variant()); + assert!(Glob::new("/a/*.ext").unwrap().variance().is_variant()); + assert!(Glob::new("/a/b*").unwrap().variance().is_variant()); + #[cfg(unix)] + assert!(Glob::new("/a/(?i)file.ext").unwrap().variance().is_variant()); + #[cfg(windows)] + assert!(Glob::new("/a/(?-i)file.ext").unwrap().variance().is_variant()); + } +} diff --git a/crates/turborepo-wax/Source/rule.rs b/crates/turborepo-wax/Source/rule.rs new file mode 100644 index 0000000000000..9f1421b12968c --- /dev/null +++ b/crates/turborepo-wax/Source/rule.rs @@ -0,0 +1,695 @@ +//! Rules and limitations for token sequences. +//! +//! This module provides the `check` function, which examines a token sequence +//! and emits an error if the sequence violates rules. Rules are invariants that +//! are difficult or impossible to enforce when parsing text and primarily +//! detect and reject token sequences that produce anomalous, meaningless, or +//! unexpected globs (regular expressions) when compiled. +//! +//! Most rules concern alternatives, which have complex interactions with +//! neighboring tokens. + +// TODO: The `check` function fails fast and either report no errors or exactly +// one error. To better support diagnostics, `check` should probably +// perform an exhaustive analysis and report zero or more errors. + +#[cfg(feature = "miette")] +use std::fmt::Display; +use std::{borrow::Cow, convert::Infallible, iter::Fuse, path::PathBuf, slice}; + +use itertools::Itertools as _; +#[cfg(feature = "miette")] +use miette::{Diagnostic, LabeledSpan, SourceCode}; +use thiserror::Error; + +use crate::{ + Any, + BuildError, + Glob, + Pattern, + diagnostics::{CompositeSpan, CorrelatedSpan, SpanExt as _}, + token::{self, InvariantSize, Token, TokenKind, TokenTree, Tokenized}, +}; + +/// Maximum invariant size. +/// +/// This size is equal to or greater than the maximum size of a path on +/// supported platforms. The primary purpose of this limit is to mitigate +/// malicious or mistaken expressions that encode very large invariant text, +/// namely via repetitions. +/// +/// This limit is independent of the back end encoding. This code does not rely +/// on errors in the encoder by design, such as size limitations. +const MAX_INVARIANT_SIZE:InvariantSize = InvariantSize::new(0x10000); + +trait IteratorExt: Iterator + Sized { + fn adjacent(self) -> Adjacent + where + Self::Item: Clone; +} + +impl IteratorExt for I +where + I: Iterator, +{ + fn adjacent(self) -> Adjacent + where + Self::Item: Clone, { + Adjacent::new(self) + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum Adjacency { + Only { item:T }, + First { item:T, right:T }, + Middle { left:T, item:T, right:T }, + Last { left:T, item:T }, +} + +impl Adjacency { + pub fn into_tuple(self) -> (Option, T, Option) { + match self { + Adjacency::Only { item } => (None, item, None), + Adjacency::First { item, right } => (None, item, Some(right)), + Adjacency::Middle { left, item, right } => (Some(left), item, Some(right)), + Adjacency::Last { left, item } => (Some(left), item, None), + } + } +} + +struct Adjacent +where + I: Iterator, { + input:Fuse, + adjacency:Option>, +} + +impl Adjacent +where + I: Iterator, +{ + fn new(input:I) -> Self { + let mut input = input.fuse(); + let adjacency = match (input.next(), input.next()) { + (Some(item), Some(right)) => Some(Adjacency::First { item, right }), + (Some(item), None) => Some(Adjacency::Only { item }), + (None, None) => None, + // The input iterator is fused, so this cannot occur. + (None, Some(_)) => unreachable!(), + }; + Adjacent { input, adjacency } + } +} + +impl Iterator for Adjacent +where + I: Iterator, + I::Item: Clone, +{ + type Item = Adjacency; + + fn next(&mut self) -> Option { + let next = self.input.next(); + self.adjacency.take().map(|adjacency| { + self.adjacency = match adjacency.clone() { + Adjacency::First { item: left, right: item } + | Adjacency::Middle { item: left, right: item, .. } => { + if let Some(right) = next { + Some(Adjacency::Middle { left, item, right }) + } else { + Some(Adjacency::Last { left, item }) + } + }, + Adjacency::Only { .. } | Adjacency::Last { .. } => None, + }; + adjacency + }) + } +} + +trait SliceExt { + fn terminals(&self) -> Option>; +} + +impl SliceExt for [T] { + fn terminals(&self) -> Option> { + match self.len() { + 0 => None, + 1 => Some(Terminals::Only(self.first().unwrap())), + _ => Some(Terminals::StartEnd(self.first().unwrap(), self.last().unwrap())), + } + } +} + +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +enum Terminals { + Only(T), + StartEnd(T, T), +} + +impl Terminals { + pub fn map(self, mut f:F) -> Terminals + where + F: FnMut(T) -> U, { + match self { + Terminals::Only(only) => Terminals::Only(f(only)), + Terminals::StartEnd(start, end) => Terminals::StartEnd(f(start), f(end)), + } + } +} + +/// Describes errors concerning rules and patterns in a glob expression. +/// +/// Patterns must follow rules described in the [repository +/// documentation](https://github.com/olson-sean-k/wax/blob/master/README.md). These rules are +/// designed to avoid nonsense glob expressions and ambiguity. If a glob +/// expression parses but violates these rules or is otherwise malformed, then +/// this error is returned by some APIs. +#[derive(Debug, Error)] +#[error("malformed glob expression: {kind}")] +pub struct RuleError<'t> { + expression:Cow<'t, str>, + kind:RuleErrorKind, + location:CompositeSpan, +} + +impl<'t> RuleError<'t> { + fn new(expression:Cow<'t, str>, kind:RuleErrorKind, location:CompositeSpan) -> Self { + RuleError { expression, kind, location } + } + + /// Clones any borrowed data into an owning instance. + pub fn into_owned(self) -> RuleError<'static> { + let RuleError { expression, kind, location } = self; + RuleError { expression:expression.into_owned().into(), kind, location } + } + + pub fn locations(&self) -> &[CompositeSpan] { slice::from_ref(&self.location) } + + /// Gets the glob expression that violated pattern rules. + pub fn expression(&self) -> &str { self.expression.as_ref() } +} + +#[cfg(feature = "miette")] +#[cfg_attr(docsrs, doc(cfg(feature = "miette")))] +impl Diagnostic for RuleError<'_> { + fn code<'a>(&'a self) -> Option> { + Some(Box::new(String::from(match self.kind { + RuleErrorKind::RootedSubGlob => "wax::glob::rooted_sub_glob", + RuleErrorKind::SingularTree => "wax::glob::singular_tree", + RuleErrorKind::SingularZeroOrMore => "wax::glob::singular_zero_or_more", + RuleErrorKind::AdjacentBoundary => "wax::glob::adjacent_boundary", + RuleErrorKind::AdjacentZeroOrMore => "wax::glob::adjacent_zero_or_more", + RuleErrorKind::OversizedInvariant => "wax::glob::oversized_invariant", + RuleErrorKind::IncompatibleBounds => "wax::glob::incompatible_bounds", + }))) + } + + fn help<'a>(&'a self) -> Option> { + match self.kind { + RuleErrorKind::OversizedInvariant => { + Some(Box::new(String::from( + "this error typically occurs when a repetition has a convergent bound that is \ + too large", + ))) + }, + _ => None, + } + } + + fn source_code(&self) -> Option<&dyn SourceCode> { Some(&self.expression) } + + fn labels(&self) -> Option>> { + Some(Box::new(self.location.labels().into_iter())) + } +} + +#[derive(Clone, Debug, Error)] +#[non_exhaustive] +enum RuleErrorKind { + #[error("rooted sub-glob in group")] + RootedSubGlob, + #[error("singular tree wildcard `**` in group")] + SingularTree, + #[error("singular zero-or-more wildcard `*` or `$` in group")] + SingularZeroOrMore, + #[error("adjacent component boundaries `/` or `**`")] + AdjacentBoundary, + #[error("adjacent zero-or-more wildcards `*` or `$`")] + AdjacentZeroOrMore, + #[error("oversized invariant expression")] + OversizedInvariant, + #[error("incompatible repetition bounds")] + IncompatibleBounds, +} + +#[derive(Clone, Copy, Debug)] +pub struct Checked { + inner:T, +} + +impl Checked { + pub fn release(self) -> T { self.inner } +} + +impl<'t> Checked> { + pub fn any(trees:I) -> Self + where + T: TokenTree<'t>, + I: IntoIterator>, { + Checked { + // `token::any` constructs an alternative from the input token trees. The alternative + // is not checked, but the `any` combinator is explicitly allowed to ignore the subset + // of rules that may be violated by this construction. In particular, branches may or + // may not have roots such that the alternative can match overlapping directory trees. + inner:token::any(trees.into_iter().map(Checked::release).map(TokenTree::into_tokens)), + } + } +} + +impl<'t, A> Checked> { + pub fn into_owned(self) -> Checked> { + Checked { inner:self.release().into_owned() } + } +} + +impl<'t, A> Checked> { + pub fn into_owned(self) -> Checked> { + Checked { inner:self.release().into_owned() } + } +} + +impl<'t> Checked> { + pub fn partition(self) -> (PathBuf, Self) { + let tokenized = self.release(); + // `Tokenized::partition` does not violate rules. + let (path, tokenized) = tokenized.partition(); + (path, Checked { inner:tokenized }) + } +} + +impl AsRef for Checked { + fn as_ref(&self) -> &T { &self.inner } +} + +impl<'t, T> Pattern<'t> for Checked +where + T: TokenTree<'t>, +{ + type Error = Infallible; + type Tokens = T; +} + +impl<'t> From> for Checked> { + fn from(any:Any<'t>) -> Self { + let Any { tree, .. } = any; + tree + } +} + +impl<'t> From> for Checked> { + fn from(glob:Glob<'t>) -> Self { + let Glob { tree, .. } = glob; + tree + } +} + +impl<'t> TryFrom<&'t str> for Checked> { + type Error = BuildError; + + fn try_from(expression:&'t str) -> Result { + crate::parse_and_check(expression) + } +} + +pub fn check(tokenized:Tokenized) -> Result, RuleError> { + boundary(&tokenized)?; + bounds(&tokenized)?; + group(&tokenized)?; + size(&tokenized)?; + Ok(Checked { inner:tokenized }) +} + +fn boundary<'t>(tokenized:&Tokenized<'t>) -> Result<(), RuleError<'t>> { + if let Some((left, right)) = tokenized + .walk() + .group_by(|(position, _)| *position) + .into_iter() + .flat_map(|(_, group)| { + group + .map(|(_, token)| token) + .tuple_windows::<(_, _)>() + .filter(|(left, right)| { + left.is_component_boundary() && right.is_component_boundary() + }) + .map(|(left, right)| (*left.annotation(), *right.annotation())) + }) + .next() + { + Err(RuleError::new( + tokenized.expression().clone(), + RuleErrorKind::AdjacentBoundary, + CompositeSpan::spanned("here", left.union(&right)), + )) + } else { + Ok(()) + } +} + +fn group<'t>(tokenized:&Tokenized<'t>) -> Result<(), RuleError<'t>> { + use Terminals::{Only, StartEnd}; + + use crate::token::{ + TokenKind::{Separator, Wildcard}, + Wildcard::{Tree, ZeroOrMore}, + }; + + struct CorrelatedError { + kind:RuleErrorKind, + location:CorrelatedSpan, + } + + impl CorrelatedError { + fn new(kind:RuleErrorKind, outer:Option<&Token>, inner:&Token) -> Self { + CorrelatedError { + kind, + location:CorrelatedSpan::split_some( + outer.map(Token::annotation).copied().map(From::from), + *inner.annotation(), + ), + } + } + } + + #[derive(Clone, Copy, Default)] + struct Outer<'i, 't> { + left:Option<&'i Token<'t>>, + right:Option<&'i Token<'t>>, + } + + impl<'i, 't> Outer<'i, 't> { + pub fn push(self, left:Option<&'i Token<'t>>, right:Option<&'i Token<'t>>) -> Self { + Outer { left:left.or(self.left), right:right.or(self.right) } + } + } + + fn has_starting_component_boundary<'t>(token:Option<&'t Token<'t>>) -> bool { + token.map_or(false, |token| { + token.walk().starting().any(|(_, token)| token.is_component_boundary()) + }) + } + + fn has_ending_component_boundary<'t>(token:Option<&'t Token<'t>>) -> bool { + token.map_or(false, |token| { + token.walk().ending().any(|(_, token)| token.is_component_boundary()) + }) + } + + fn has_starting_zom_token<'t>(token:Option<&'t Token<'t>>) -> bool { + token.map_or(false, |token| { + token + .walk() + .starting() + .any(|(_, token)| matches!(token.kind(), Wildcard(ZeroOrMore(_)))) + }) + } + + fn has_ending_zom_token<'t>(token:Option<&'t Token<'t>>) -> bool { + token.map_or(false, |token| { + token + .walk() + .ending() + .any(|(_, token)| matches!(token.kind(), Wildcard(ZeroOrMore(_)))) + }) + } + + fn diagnose<'i, 't>( + // This is a somewhat unusual API, but it allows the lifetime `'t` of the `Cow` to be + // properly forwarded to output values (`RuleError`). + #[allow(clippy::ptr_arg)] expression:&'i Cow<'t, str>, + token:&'i Token<'t>, + label:&'static str, + ) -> impl 'i + Copy + Fn(CorrelatedError) -> RuleError<'t> + where + 't:'i, { + move |CorrelatedError { kind, location }| { + RuleError::new( + expression.clone(), + kind, + CompositeSpan::correlated(label, *token.annotation(), location), + ) + } + } + + fn recurse<'i, 't, I>( + // This is a somewhat unusual API, but it allows the lifetime `'t` of the `Cow` to be + // properly forwarded to output values (`RuleError`). + #[allow(clippy::ptr_arg)] expression:&Cow<'t, str>, + tokens:I, + outer:Outer<'i, 't>, + ) -> Result<(), RuleError<'t>> + where + I: IntoIterator>, + 't:'i, { + for (left, token, right) in tokens.into_iter().adjacent().map(Adjacency::into_tuple) { + match token.kind() { + TokenKind::Alternative(ref alternative) => { + let outer = outer.push(left, right); + let diagnose = diagnose(expression, token, "in this alternative"); + for tokens in alternative.branches() { + if let Some(terminals) = tokens.terminals() { + check_group(terminals, outer).map_err(diagnose)?; + check_group_alternative(terminals, outer).map_err(diagnose)?; + } + recurse(expression, tokens.iter(), outer)?; + } + }, + TokenKind::Repetition(ref repetition) => { + let outer = outer.push(left, right); + let diagnose = diagnose(expression, token, "in this repetition"); + let tokens = repetition.tokens(); + if let Some(terminals) = tokens.terminals() { + check_group(terminals, outer).map_err(diagnose)?; + check_group_repetition(terminals, outer, repetition.bounds()) + .map_err(diagnose)?; + } + recurse(expression, tokens.iter(), outer)?; + }, + _ => {}, + } + } + Ok(()) + } + + fn check_group<'t>( + terminals:Terminals<&Token>, + outer:Outer<'t, 't>, + ) -> Result<(), CorrelatedError> { + let Outer { left, right } = outer; + match terminals.map(|token| (token, token.kind())) { + // The group is preceded by component boundaries; disallow leading separators. + // + // For example, `foo/{bar,/}`. + Only((inner, Separator(_))) | StartEnd((inner, Separator(_)), _) + if has_ending_component_boundary(left) => + { + Err(CorrelatedError::new(RuleErrorKind::AdjacentBoundary, left, inner)) + }, + // The group is followed by component boundaries; disallow trailing + // separators. + // + // For example, `{foo,/}/bar`. + Only((inner, Separator(_))) | StartEnd(_, (inner, Separator(_))) + if has_starting_component_boundary(right) => + { + Err(CorrelatedError::new(RuleErrorKind::AdjacentBoundary, right, inner)) + }, + // Disallow singular tree tokens. + // + // For example, `{foo,bar,**}`. + Only((inner, Wildcard(Tree { .. }))) => { + Err(CorrelatedError::new(RuleErrorKind::SingularTree, None, inner)) + }, + // The group is preceded by component boundaries; disallow leading tree tokens. + // + // For example, `foo/{bar,**/baz}`. + StartEnd((inner, Wildcard(Tree { .. })), _) if has_ending_component_boundary(left) => { + Err(CorrelatedError::new(RuleErrorKind::AdjacentBoundary, left, inner)) + }, + // The group is followed by component boundaries; disallow trailing + // tree tokens. + // + // For example, `{foo,bar/**}/baz`. + StartEnd(_, (inner, Wildcard(Tree { .. }))) + if has_starting_component_boundary(right) => + { + Err(CorrelatedError::new(RuleErrorKind::AdjacentBoundary, right, inner)) + }, + // The group is prefixed by a zero-or-more token; disallow leading + // zero-or-more tokens. + // + // For example, `foo*{bar,*,baz}`. + Only((inner, Wildcard(ZeroOrMore(_)))) + | StartEnd((inner, Wildcard(ZeroOrMore(_))), _) + if has_ending_zom_token(left) => + { + Err(CorrelatedError::new(RuleErrorKind::AdjacentZeroOrMore, left, inner)) + }, + // The group is followed by a zero-or-more token; disallow trailing + // zero-or-more tokens. + // + // For example, `{foo,*,bar}*baz`. + Only((inner, Wildcard(ZeroOrMore(_)))) + | StartEnd(_, (inner, Wildcard(ZeroOrMore(_)))) + if has_starting_zom_token(right) => + { + Err(CorrelatedError::new(RuleErrorKind::AdjacentZeroOrMore, right, inner)) + }, + _ => Ok(()), + } + } + + fn check_group_alternative<'t>( + terminals:Terminals<&Token>, + outer:Outer<'t, 't>, + ) -> Result<(), CorrelatedError> { + let Outer { left, .. } = outer; + match terminals.map(|token| (token, token.kind())) { + // The alternative is preceded by a termination; disallow rooted sub-globs. + // + // For example, `{foo,/}` or `{foo,/bar}`. + Only((inner, Separator(_))) | StartEnd((inner, Separator(_)), _) if left.is_none() => { + Err(CorrelatedError::new(RuleErrorKind::RootedSubGlob, left, inner)) + }, + // The alternative is preceded by a termination; disallow rooted + // sub-globs. + // + // For example, `{/**/foo,bar}`. + Only((inner, Wildcard(Tree { has_root: true }))) + | StartEnd((inner, Wildcard(Tree { has_root: true })), _) + if left.is_none() => + { + Err(CorrelatedError::new(RuleErrorKind::RootedSubGlob, left, inner)) + }, + _ => Ok(()), + } + } + + fn check_group_repetition<'t>( + terminals:Terminals<&Token>, + outer:Outer<'t, 't>, + bounds:(usize, Option), + ) -> Result<(), CorrelatedError> { + let Outer { left, .. } = outer; + let (lower, _) = bounds; + match terminals.map(|token| (token, token.kind())) { + // The repetition is preceded by a termination; disallow rooted sub-globs with a zero + // lower bound. + // + // For example, ``. + Only((inner, Separator(_))) | StartEnd((inner, Separator(_)), _) + if left.is_none() && lower == 0 => + { + Err(CorrelatedError::new(RuleErrorKind::RootedSubGlob, left, inner)) + }, + // The repetition is preceded by a termination; disallow rooted + // sub-globs with a zero lower bound. + // + // For example, ``. + Only((inner, Wildcard(Tree { has_root: true }))) + | StartEnd((inner, Wildcard(Tree { has_root: true })), _) + if left.is_none() && lower == 0 => + { + Err(CorrelatedError::new(RuleErrorKind::RootedSubGlob, left, inner)) + }, + // The repetition begins and ends with a separator. + // + // For example, ``. + StartEnd((left, _), (right, _)) + if left.is_component_boundary() && right.is_component_boundary() => + { + Err(CorrelatedError::new(RuleErrorKind::AdjacentBoundary, Some(left), right)) + }, + // The repetition is a singular separator. + // + // For example, ``. + Only((token, Separator(_))) => { + Err(CorrelatedError::new(RuleErrorKind::AdjacentBoundary, None, token)) + }, + // The repetition is a singular zero-or-more wildcard. + // + // For example, `<*:1,>`. + Only((token, Wildcard(ZeroOrMore(_)))) => { + Err(CorrelatedError::new(RuleErrorKind::SingularZeroOrMore, None, token)) + }, + _ => Ok(()), + } + } + + recurse(tokenized.expression(), tokenized.tokens(), Outer::default()) +} + +fn bounds<'t>(tokenized:&Tokenized<'t>) -> Result<(), RuleError<'t>> { + if let Some((_, token)) = tokenized.walk().find(|(_, token)| { + match token.kind() { + TokenKind::Repetition(ref repetition) => { + let (lower, upper) = repetition.bounds(); + upper.map_or(false, |upper| upper < lower || upper == 0) + }, + _ => false, + } + }) { + Err(RuleError::new( + tokenized.expression().clone(), + RuleErrorKind::IncompatibleBounds, + CompositeSpan::spanned("here", *token.annotation()), + )) + } else { + Ok(()) + } +} + +fn size<'t>(tokenized:&Tokenized<'t>) -> Result<(), RuleError<'t>> { + if let Some((_, token)) = tokenized + .walk() + // TODO: This is expensive. For each token tree encountered, the tree is traversed to + // determine its variance. If variant, the tree is traversed and queried again, + // revisiting the same tokens to recompute their local variance. + .find(|(_, token)| { + token + .variance::() + .as_invariance() + .map_or(false, |size| *size >= MAX_INVARIANT_SIZE) + }) + { + Err(RuleError::new( + tokenized.expression().clone(), + RuleErrorKind::OversizedInvariant, + CompositeSpan::spanned("here", *token.annotation()), + )) + } else { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::rule::{Adjacency, IteratorExt as _}; + + #[test] + fn adjacent() { + let mut adjacent = Option::::None.into_iter().adjacent(); + assert_eq!(adjacent.next(), None); + + let mut adjacent = Some(0i32).into_iter().adjacent(); + assert_eq!(adjacent.next(), Some(Adjacency::Only { item:0 })); + assert_eq!(adjacent.next(), None); + + let mut adjacent = (0i32..3).adjacent(); + assert_eq!(adjacent.next(), Some(Adjacency::First { item:0, right:1 })); + assert_eq!(adjacent.next(), Some(Adjacency::Middle { left:0, item:1, right:2 })); + assert_eq!(adjacent.next(), Some(Adjacency::Last { left:1, item:2 })); + assert_eq!(adjacent.next(), None); + } +} diff --git a/crates/turborepo-wax/Source/token/mod.rs b/crates/turborepo-wax/Source/token/mod.rs new file mode 100644 index 0000000000000..8e8c3940e81a9 --- /dev/null +++ b/crates/turborepo-wax/Source/token/mod.rs @@ -0,0 +1,963 @@ +mod parse; +mod variance; + +use std::{ + borrow::Cow, + cmp, + collections::VecDeque, + mem, + ops::Deref, + path::{MAIN_SEPARATOR, PathBuf}, + slice, + str, +}; + +use itertools::Itertools as _; + +pub use crate::token::{ + parse::{Annotation, ParseError, ROOT_SEPARATOR_EXPRESSION, parse}, + variance::{ + Boundedness, + InvariantSize, + InvariantText, + Variance, + invariant_text_prefix, + is_exhaustive, + }, +}; +use crate::{ + PATHS_ARE_CASE_INSENSITIVE, + StrExt as _, + token::variance::{ + CompositeBreadth, + CompositeDepth, + ConjunctiveVariance, + DisjunctiveVariance, + IntoInvariantText, + Invariance, + UnitBreadth, + UnitDepth, + UnitVariance, + }, +}; + +pub trait TokenTree<'t>: Sized { + type Annotation; + + fn into_tokens(self) -> Vec>; + + fn tokens(&self) -> &[Token<'t, Self::Annotation>]; +} + +#[derive(Clone, Debug)] +pub struct Tokenized<'t, A = Annotation> { + expression:Cow<'t, str>, + tokens:Vec>, +} + +impl<'t, A> Tokenized<'t, A> { + pub fn into_owned(self) -> Tokenized<'static, A> { + let Tokenized { expression, tokens } = self; + Tokenized { + expression:expression.into_owned().into(), + tokens:tokens.into_iter().map(Token::into_owned).collect(), + } + } + + pub fn expression(&self) -> &Cow<'t, str> { &self.expression } + + pub fn variance(&self) -> Variance + where + T: Invariance, + for<'i> &'i Token<'t, A>: UnitVariance, { + self.tokens().iter().conjunctive_variance() + } + + pub fn walk(&self) -> Walk<'_, 't, A> { Walk::from(&self.tokens) } +} + +impl<'t> Tokenized<'t, Annotation> { + pub fn partition(self) -> (PathBuf, Self) { + fn pop_expression_bytes(expression:&str, n:usize) -> &str { + let n = cmp::min(expression.len(), n); + str::from_utf8(&expression.as_bytes()[n..]) + .expect("span offset split UTF-8 byte sequence") + } + + let Tokenized { expression, mut tokens } = self; + + // Get the invariant prefix and its upper bound for the token sequence. + let prefix = variance::invariant_text_prefix(tokens.iter()).into(); + let n = variance::invariant_text_prefix_upper_bound(&tokens); + let mut offset:usize = tokens.iter().take(n).map(|token| token.annotation().1).sum(); + + // Drain invariant tokens from the beginning of the token sequence and unroot + // any tokens at the beginning of the variant sequence (tree wildcards). + // Finally, translate spans and discard the corresponding invariant + // bytes in the expression. + tokens.drain(0..n); + if tokens.first_mut().map_or(false, Token::unroot) { + // TODO: The relationship between roots, the unrooting operation, and the span + // in an expression that represents such a root (if any) is + // not captured by these APIs very well. Perhaps `unroot` + // should do more here? Pop additional bytes for the root separator + // expression if the initial token has lost a root. + offset += ROOT_SEPARATOR_EXPRESSION.len(); + } + for token in tokens.iter_mut() { + let start = token.annotation().0.saturating_sub(offset); + token.annotation.0 = start; + } + let expression = match expression { + Cow::Borrowed(expression) => pop_expression_bytes(expression, offset).into(), + Cow::Owned(expression) => { + String::from(pop_expression_bytes(&expression, offset)).into() + }, + }; + + (prefix, Tokenized { expression, tokens }) + } +} + +impl<'t, A> TokenTree<'t> for Tokenized<'t, A> { + type Annotation = A; + + fn into_tokens(self) -> Vec> { + let Tokenized { tokens, .. } = self; + tokens + } + + fn tokens(&self) -> &[Token<'t, Self::Annotation>] { &self.tokens } +} + +#[derive(Clone, Debug)] +pub struct Token<'t, A = Annotation> { + kind:TokenKind<'t, A>, + annotation:A, +} + +impl<'t, A> Token<'t, A> { + fn new(kind:TokenKind<'t, A>, annotation:A) -> Self { Token { kind, annotation } } + + pub fn into_owned(self) -> Token<'static, A> { + let Token { kind, annotation } = self; + Token { kind:kind.into_owned(), annotation } + } + + pub fn unannotate(self) -> Token<'t, ()> { + let Token { kind, .. } = self; + Token { kind:kind.unannotate(), annotation:() } + } + + pub fn unroot(&mut self) -> bool { self.kind.unroot() } + + pub fn kind(&self) -> &TokenKind<'t, A> { self.as_ref() } + + pub fn annotation(&self) -> &A { self.as_ref() } + + pub fn walk(&self) -> Walk<'_, 't, A> { Walk::from(self) } + + pub fn has_root(&self) -> bool { + self.walk().starting().any(|(_, token)| { + matches!( + token.kind(), + TokenKind::Separator(_) | TokenKind::Wildcard(Wildcard::Tree { has_root:true }), + ) + }) + } + + pub fn has_component_boundary(&self) -> bool { + self.walk().any(|(_, token)| token.is_component_boundary()) + } +} + +impl<'t, A> AsRef> for Token<'t, A> { + fn as_ref(&self) -> &TokenKind<'t, A> { &self.kind } +} + +impl<'t, A> AsRef for Token<'t, A> { + fn as_ref(&self) -> &A { &self.annotation } +} + +impl<'t, A> Deref for Token<'t, A> { + type Target = TokenKind<'t, A>; + + fn deref(&self) -> &Self::Target { self.as_ref() } +} + +impl<'t> From> for Token<'t, ()> { + fn from(kind:TokenKind<'t, ()>) -> Self { Token { kind, annotation:() } } +} + +impl<'t, A> TokenTree<'t> for Token<'t, A> { + type Annotation = A; + + fn into_tokens(self) -> Vec> { vec![self] } + + fn tokens(&self) -> &[Token<'t, Self::Annotation>] { slice::from_ref(self) } +} + +impl<'i, 't, A> UnitBreadth for &'i Token<'t, A> { + fn unit_breadth(self) -> Boundedness { self.kind.unit_breadth() } +} + +impl<'i, 't, A> UnitDepth for &'i Token<'t, A> { + fn unit_depth(self) -> Boundedness { self.kind.unit_depth() } +} + +impl<'i, 't, A, T> UnitVariance for &'i Token<'t, A> +where + &'i TokenKind<'t, A>: UnitVariance, + T: Invariance, +{ + fn unit_variance(self) -> Variance { self.kind.unit_variance() } +} + +#[derive(Clone, Debug)] +pub enum TokenKind<'t, A = ()> { + Alternative(Alternative<'t, A>), + Class(Class), + Literal(Literal<'t>), + Repetition(Repetition<'t, A>), + Separator(Separator), + Wildcard(Wildcard), +} + +impl<'t, A> TokenKind<'t, A> { + pub fn into_owned(self) -> TokenKind<'static, A> { + match self { + TokenKind::Alternative(alternative) => alternative.into_owned().into(), + TokenKind::Class(class) => TokenKind::Class(class), + TokenKind::Literal(Literal { text, is_case_insensitive }) => { + TokenKind::Literal(Literal { text:text.into_owned().into(), is_case_insensitive }) + }, + TokenKind::Repetition(repetition) => repetition.into_owned().into(), + TokenKind::Separator(_) => TokenKind::Separator(Separator), + TokenKind::Wildcard(wildcard) => TokenKind::Wildcard(wildcard), + } + } + + pub fn unannotate(self) -> TokenKind<'t, ()> { + match self { + TokenKind::Alternative(alternative) => TokenKind::Alternative(alternative.unannotate()), + TokenKind::Class(class) => TokenKind::Class(class), + TokenKind::Literal(literal) => TokenKind::Literal(literal), + TokenKind::Repetition(repetition) => TokenKind::Repetition(repetition.unannotate()), + TokenKind::Separator(_) => TokenKind::Separator(Separator), + TokenKind::Wildcard(wildcard) => TokenKind::Wildcard(wildcard), + } + } + + pub fn unroot(&mut self) -> bool { + match self { + TokenKind::Wildcard(Wildcard::Tree { ref mut has_root }) => { + mem::replace(has_root, false) + }, + _ => false, + } + } + + pub fn variance(&self) -> Variance + where + T: Invariance, + for<'i> &'i TokenKind<'t, A>: UnitVariance, { + self.unit_variance() + } + + pub fn has_sub_tokens(&self) -> bool { + // It is not necessary to detect empty branches or sub-expressions. + matches!(self, TokenKind::Alternative(_) | TokenKind::Repetition(_)) + } + + pub fn is_component_boundary(&self) -> bool { + matches!(self, TokenKind::Separator(_) | TokenKind::Wildcard(Wildcard::Tree { .. })) + } + + pub fn is_capturing(&self) -> bool { + use TokenKind::{Alternative, Class, Repetition, Wildcard}; + + matches!(self, Alternative(_) | Class(_) | Repetition(_) | Wildcard(_),) + } +} + +impl<'t, A> From> for TokenKind<'t, A> { + fn from(alternative:Alternative<'t, A>) -> Self { TokenKind::Alternative(alternative) } +} + +impl From for TokenKind<'_, A> { + fn from(class:Class) -> Self { TokenKind::Class(class) } +} + +impl<'t, A> From> for TokenKind<'t, A> { + fn from(repetition:Repetition<'t, A>) -> Self { TokenKind::Repetition(repetition) } +} + +impl From for TokenKind<'static, A> { + fn from(wildcard:Wildcard) -> Self { TokenKind::Wildcard(wildcard) } +} + +impl<'i, 't, A> UnitBreadth for &'i TokenKind<'t, A> { + fn unit_breadth(self) -> Boundedness { + match self { + TokenKind::Alternative(ref alternative) => alternative.unit_breadth(), + TokenKind::Class(ref class) => class.unit_breadth(), + TokenKind::Literal(ref literal) => literal.unit_breadth(), + TokenKind::Repetition(ref repetition) => repetition.unit_breadth(), + TokenKind::Separator(ref separator) => separator.unit_breadth(), + TokenKind::Wildcard(ref wildcard) => wildcard.unit_breadth(), + } + } +} + +impl<'i, 't, A> UnitDepth for &'i TokenKind<'t, A> { + fn unit_depth(self) -> Boundedness { + match self { + TokenKind::Alternative(ref alternative) => alternative.unit_depth(), + TokenKind::Class(ref class) => class.unit_depth(), + TokenKind::Literal(ref literal) => literal.unit_depth(), + TokenKind::Repetition(ref repetition) => repetition.unit_depth(), + TokenKind::Separator(ref separator) => separator.unit_depth(), + TokenKind::Wildcard(ref wildcard) => wildcard.unit_depth(), + } + } +} + +impl<'i, 't, A, T> UnitVariance for &'i TokenKind<'t, A> +where + &'i Class: UnitVariance, + &'i Literal<'t>: UnitVariance, + &'i Separator: UnitVariance, + T: Invariance, +{ + fn unit_variance(self) -> Variance { + match self { + TokenKind::Alternative(ref alternative) => alternative.unit_variance(), + TokenKind::Class(ref class) => class.unit_variance(), + TokenKind::Literal(ref literal) => literal.unit_variance(), + TokenKind::Repetition(ref repetition) => repetition.unit_variance(), + TokenKind::Separator(ref separator) => separator.unit_variance(), + TokenKind::Wildcard(_) => Variance::Variant(Boundedness::Open), + } + } +} + +#[derive(Clone, Debug)] +pub struct Alternative<'t, A = ()>(Vec>>); + +impl<'t, A> Alternative<'t, A> { + pub fn into_owned(self) -> Alternative<'static, A> { + Alternative( + self.0 + .into_iter() + .map(|tokens| tokens.into_iter().map(Token::into_owned).collect()) + .collect(), + ) + } + + pub fn unannotate(self) -> Alternative<'t, ()> { + let Alternative(branches) = self; + Alternative( + branches + .into_iter() + .map(|branch| branch.into_iter().map(Token::unannotate).collect()) + .collect(), + ) + } + + pub fn branches(&self) -> &Vec>> { &self.0 } +} + +impl<'t, A> From>>> for Alternative<'t, A> { + fn from(alternatives:Vec>>) -> Self { Alternative(alternatives) } +} + +impl<'i, 't, A> UnitBreadth for &'i Alternative<'t, A> { + fn unit_breadth(self) -> Boundedness { + self.branches() + .iter() + .map(|tokens| tokens.iter().composite_breadth()) + .composite_breadth() + } +} + +impl<'i, 't, A> UnitDepth for &'i Alternative<'t, A> { + fn unit_depth(self) -> Boundedness { + self.branches() + .iter() + .map(|tokens| tokens.iter().composite_depth()) + .composite_depth() + } +} + +impl<'i, 't, A, T> UnitVariance for &'i Alternative<'t, A> +where + T: Invariance, + &'i Token<'t, A>: UnitVariance, +{ + fn unit_variance(self) -> Variance { + self.branches() + .iter() + .map(|tokens| tokens.iter().conjunctive_variance()) + .disjunctive_variance() + } +} + +#[derive(Clone, Copy, Debug)] +pub enum Archetype { + Character(char), + Range(char, char), +} + +impl Archetype { + fn domain_variance(&self) -> Variance { + match self { + Archetype::Character(x) => { + if PATHS_ARE_CASE_INSENSITIVE { + Variance::Variant(Boundedness::Closed) + } else { + Variance::Invariant(*x) + } + }, + Archetype::Range(a, b) => { + if (a != b) || PATHS_ARE_CASE_INSENSITIVE { + Variance::Variant(Boundedness::Closed) + } else { + Variance::Invariant(*a) + } + }, + } + } +} + +impl From for Archetype { + fn from(literal:char) -> Self { Archetype::Character(literal) } +} + +impl From<(char, char)> for Archetype { + fn from(range:(char, char)) -> Self { Archetype::Range(range.0, range.1) } +} + +impl<'i, 't> UnitVariance> for &'i Archetype { + fn unit_variance(self) -> Variance> { + self.domain_variance() + .map_invariance(|invariance| invariance.to_string().into_nominal_text()) + } +} + +impl<'i> UnitVariance for &'i Archetype { + fn unit_variance(self) -> Variance { + // This is pessimistic and assumes that the code point will require four bytes + // when encoded as UTF-8. This is technically possible, but most + // commonly only one or two bytes will be required. + self.domain_variance().map_invariance(|_| 4.into()) + } +} + +#[derive(Clone, Debug)] +pub struct Class { + is_negated:bool, + archetypes:Vec, +} + +impl Class { + pub fn archetypes(&self) -> &[Archetype] { &self.archetypes } + + pub fn is_negated(&self) -> bool { self.is_negated } +} + +impl<'i> UnitBreadth for &'i Class {} + +impl<'i> UnitDepth for &'i Class {} + +impl<'i, T> UnitVariance for &'i Class +where + &'i Archetype: UnitVariance, + T: Invariance, +{ + fn unit_variance(self) -> Variance { + if self.is_negated { + // It is not feasible to encode a character class that matches all + // UTF-8 text and therefore nothing when negated, and so a character + // class must be variant if it is negated. + Variance::Variant(Boundedness::Closed) + } else { + // TODO: This ignores casing groups, such as in the pattern `[aA]`. + self.archetypes().iter().disjunctive_variance() + } + } +} + +#[derive(Clone, Copy, Debug)] +pub enum Evaluation { + Eager, + Lazy, +} + +#[derive(Clone, Debug)] +pub struct Literal<'t> { + text:Cow<'t, str>, + is_case_insensitive:bool, +} + +impl<'t> Literal<'t> { + pub fn text(&self) -> &str { self.text.as_ref() } + + fn domain_variance(&self) -> Variance<&Cow<'t, str>> { + if self.has_variant_casing() { + Variance::Variant(Boundedness::Closed) + } else { + Variance::Invariant(&self.text) + } + } + + pub fn is_case_insensitive(&self) -> bool { self.is_case_insensitive } + + pub fn has_variant_casing(&self) -> bool { + // If path case sensitivity agrees with the literal case sensitivity, then the + // literal is not variant. Otherwise, the literal is variant if it + // contains characters with casing. + (PATHS_ARE_CASE_INSENSITIVE != self.is_case_insensitive) && self.text.has_casing() + } +} + +impl<'i, 't> UnitBreadth for &'i Literal<'t> {} + +impl<'i, 't> UnitDepth for &'i Literal<'t> {} + +impl<'i, 't> UnitVariance> for &'i Literal<'t> { + fn unit_variance(self) -> Variance> { + self.domain_variance() + .map_invariance(|invariance| invariance.clone().into_nominal_text()) + } +} + +impl<'i, 't> UnitVariance for &'i Literal<'t> { + fn unit_variance(self) -> Variance { + self.domain_variance() + .map_invariance(|invariance| invariance.as_bytes().len().into()) + } +} + +#[derive(Clone, Debug)] +pub struct Repetition<'t, A = ()> { + tokens:Vec>, + lower:usize, + // This representation is not ideal, as it does not statically enforce the invariant that the + // upper bound is greater than or equal to the lower bound. For example, this field could + // instead be a summand. However, tokens must closely resemble their glob expression + // representations so that errors in expressions can be deferred and presented more clearly. + // Failures in the parser are difficult to describe. + upper:Option, +} + +impl<'t, A> Repetition<'t, A> { + pub fn into_owned(self) -> Repetition<'static, A> { + let Repetition { tokens, lower, upper } = self; + Repetition { tokens:tokens.into_iter().map(Token::into_owned).collect(), lower, upper } + } + + pub fn unannotate(self) -> Repetition<'t, ()> { + let Repetition { tokens, lower, upper } = self; + Repetition { tokens:tokens.into_iter().map(Token::unannotate).collect(), lower, upper } + } + + pub fn tokens(&self) -> &Vec> { &self.tokens } + + pub fn bounds(&self) -> (usize, Option) { (self.lower, self.upper) } + + pub fn is_converged(&self) -> bool { self.upper.map_or(false, |upper| self.lower == upper) } + + fn walk(&self) -> Walk<'_, 't, A> { Walk::from(&self.tokens) } +} + +impl<'i, 't, A> UnitBreadth for &'i Repetition<'t, A> { + fn unit_breadth(self) -> Boundedness { self.tokens().iter().composite_breadth() } +} + +impl<'i, 't, A> UnitDepth for &'i Repetition<'t, A> { + fn unit_depth(self) -> Boundedness { + let (_, upper) = self.bounds(); + if upper.is_none() && self.walk().any(|(_, token)| token.is_component_boundary()) { + Boundedness::Open + } else { + Boundedness::Closed + } + } +} + +impl<'i, 't, A, T> UnitVariance for &'i Repetition<'t, A> +where + T: Invariance, + &'i Token<'t, A>: UnitVariance, +{ + fn unit_variance(self) -> Variance { + use Boundedness::Open; + use TokenKind::Separator; + use Variance::Variant; + + let variance = self + .tokens() + .iter() + // Coalesce tokens with open variance with separators. This isn't destructive and + // doesn't affect invariance, because this only happens in the presence of open + // variance, which means that the repetition is variant (and has no invariant size or + // text). + .coalesce(|left, right| { + match ( + (left.kind(), left.unit_variance()), + (right.kind(), right.unit_variance()), + ) { + ((Separator(_), _), (_, Variant(Open))) => Ok(right), + ((_, Variant(Open)), (Separator(_), _)) => Ok(left), + _ => Err((left, right)), + } + }) + .conjunctive_variance(); + match self.upper { + // Repeating invariance can cause overflows, very large allocations, + // and very inefficient comparisons (e.g., comparing very large + // strings). This is detected by both `encode::compile` and + // `rule::check` (in distinct but similar ways). Querying token + // trees for their invariance must be done with care (after using + // these functions) to avoid expanding pathological invariant + // expressions like ``. + Some(_) if self.is_converged() => { + variance.map_invariance(|invariance| invariance * self.lower) + }, + _ => variance + Variant(Open), + } + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Separator; + +impl Separator { + pub fn invariant_text() -> String { MAIN_SEPARATOR.to_string() } +} + +impl<'i> UnitBreadth for &'i Separator {} + +impl<'i> UnitDepth for &'i Separator {} + +impl<'i, 't> UnitVariance> for &'i Separator { + fn unit_variance(self) -> Variance> { + Variance::Invariant(Separator::invariant_text().into_structural_text()) + } +} + +impl<'i> UnitVariance for &'i Separator { + fn unit_variance(self) -> Variance { + Variance::Invariant(Separator::invariant_text().as_bytes().len().into()) + } +} + +#[derive(Clone, Debug)] +pub enum Wildcard { + One, + ZeroOrMore(Evaluation), + Tree { has_root:bool }, +} + +impl<'i> UnitBreadth for &'i Wildcard { + fn unit_breadth(self) -> Boundedness { + match self { + Wildcard::One => Boundedness::Closed, + _ => Boundedness::Open, + } + } +} + +impl<'i> UnitDepth for &'i Wildcard { + fn unit_depth(self) -> Boundedness { + match self { + Wildcard::Tree { .. } => Boundedness::Open, + _ => Boundedness::Closed, + } + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum Position { + Conjunctive { depth:usize }, + Disjunctive { depth:usize, branch:usize }, +} + +impl Position { + pub fn depth(&self) -> usize { + match self { + Position::Conjunctive { ref depth } | Position::Disjunctive { ref depth, .. } => *depth, + } + } + + // This may appear to operate in place. + #[must_use] + fn converge(self) -> Self { + match self { + Position::Conjunctive { depth } | Position::Disjunctive { depth, .. } => { + Position::Conjunctive { depth:depth + 1 } + }, + } + } + + // This may appear to operate in place. + #[must_use] + fn diverge(self, branch:usize) -> Self { + match self { + Position::Conjunctive { depth } | Position::Disjunctive { depth, .. } => { + Position::Disjunctive { depth:depth + 1, branch } + }, + } + } +} + +impl Default for Position { + fn default() -> Self { Position::Conjunctive { depth:0 } } +} + +#[derive(Clone, Debug)] +pub struct Walk<'i, 't, A> { + buffer:VecDeque<(Position, &'i Token<'t, A>)>, +} + +impl<'i, 't, A> Walk<'i, 't, A> +where + 't:'i, + A: 't, +{ + pub fn starting(self) -> impl 'i + Iterator)> { + self.peekable().batching(|tokens| { + if let Some((position, token)) = tokens.next() { + tokens.peeking_take_while(|(next, _)| *next == position).for_each(drop); + Some((position, token)) + } else { + None + } + }) + } + + pub fn ending(self) -> impl 'i + Iterator)> { + self.peekable().batching(|tokens| { + if let Some((position, _)) = tokens.peek().copied() { + tokens.peeking_take_while(|(next, _)| *next == position).last() + } else { + None + } + }) + } +} + +impl<'i, 't, A> From<&'i Token<'t, A>> for Walk<'i, 't, A> { + fn from(token:&'i Token<'t, A>) -> Self { + Walk { buffer:Some((Position::default(), token)).into_iter().collect() } + } +} + +impl<'i, 't, A> From<&'i Vec>> for Walk<'i, 't, A> { + fn from(tokens:&'i Vec>) -> Self { + Walk { buffer:tokens.iter().map(|token| (Position::default(), token)).collect() } + } +} + +impl<'i, 't, A> Iterator for Walk<'i, 't, A> +where + 't:'i, + A: 't, +{ + type Item = (Position, &'i Token<'t, A>); + + fn next(&mut self) -> Option { + if let Some((position, token)) = self.buffer.pop_front() { + match token.kind() { + TokenKind::Alternative(ref alternative) => { + self.buffer.extend(alternative.branches().iter().enumerate().flat_map( + |(branch, tokens)| { + tokens.iter().map(move |token| (position.diverge(branch), token)) + }, + )); + }, + TokenKind::Repetition(ref repetition) => { + self.buffer.extend( + repetition.tokens().iter().map(|token| (position.converge(), token)), + ); + }, + _ => {}, + } + Some((position, token)) + } else { + None + } + } +} + +#[derive(Clone, Debug)] +pub struct LiteralSequence<'i, 't>(Vec<&'i Literal<'t>>); + +impl<'i, 't> LiteralSequence<'i, 't> { + pub fn literals(&self) -> &[&'i Literal<'t>] { self.0.as_ref() } + + pub fn text(&self) -> Cow<'t, str> { + if self.literals().len() == 1 { + self.literals().first().unwrap().text.clone() + } else { + self.literals().iter().map(|literal| &literal.text).join("").into() + } + } + + #[cfg(any(unix, windows))] + pub fn is_semantic_literal(&self) -> bool { matches!(self.text().as_ref(), "." | "..") } + + #[cfg(not(any(unix, windows)))] + pub fn is_semantic_literal(&self) -> bool { false } +} + +#[derive(Debug)] +pub struct Component<'i, 't, A = ()>(Vec<&'i Token<'t, A>>); + +impl<'i, 't, A> Component<'i, 't, A> { + pub fn tokens(&self) -> &[&'i Token<'t, A>] { self.0.as_ref() } + + pub fn literal(&self) -> Option> { + if self.0.is_empty() { + None + } else { + self.tokens() + .iter() + .all(|token| matches!(token.kind(), TokenKind::Literal(_))) + .then(|| { + LiteralSequence( + self.tokens() + .iter() + .map(|token| { + match token.kind() { + TokenKind::Literal(ref literal) => literal, + _ => unreachable!(), // See predicate above. + } + }) + .collect(), + ) + }) + } + } + + pub fn variance(&self) -> Variance + where + T: Invariance, + &'i Token<'t, A>: UnitVariance, { + self.0.iter().copied().conjunctive_variance() + } + + pub fn depth(&self) -> Boundedness { self.0.iter().copied().composite_depth() } +} + +impl<'i, 't, A> Clone for Component<'i, 't, A> { + fn clone(&self) -> Self { Component(self.0.clone()) } +} + +pub fn any<'t, A, I>(tokens:I) -> Token<'t, ()> +where + I: IntoIterator, + I::Item: IntoIterator>, { + Token { + kind:Alternative( + tokens + .into_iter() + .map(|tokens| tokens.into_iter().map(Token::unannotate).collect()) + .collect(), + ) + .into(), + annotation:(), + } +} + +pub fn components<'i, 't, A, I>(tokens:I) -> impl Iterator> +where + 't:'i, + A: 't, + I: IntoIterator>, { + tokens.into_iter().peekable().batching(|tokens| { + let mut first = tokens.next(); + while matches!(first.map(Token::kind), Some(TokenKind::Separator(_))) { + first = tokens.next(); + } + first.map(|first| { + match first.kind() { + TokenKind::Wildcard(Wildcard::Tree { .. }) => Component(vec![first]), + _ => { + Component( + Some(first) + .into_iter() + .chain( + tokens.peeking_take_while(|token| !token.is_component_boundary()), + ) + .collect(), + ) + }, + } + }) + }) +} + +// TODO: This implementation allocates many `Vec`s. +pub fn literals<'i, 't, A, I>( + tokens:I, +) -> impl Iterator, LiteralSequence<'i, 't>)> +where + 't:'i, + A: 't, + I: IntoIterator>, { + components(tokens).flat_map(|component| { + if let Some(literal) = component.literal() { + vec![(component, literal)] + } else { + component + .tokens() + .iter() + .filter_map(|token| { + match token.kind() { + TokenKind::Alternative(ref alternative) => { + Some( + alternative + .branches() + .iter() + .flat_map(literals) + .collect::>(), + ) + }, + TokenKind::Repetition(ref repetition) => { + Some(literals(repetition.tokens()).collect::>()) + }, + _ => None, + } + }) + .flatten() + .collect::>() + } + }) +} + +#[cfg(test)] +mod tests { + use crate::token::{self, TokenKind, TokenTree}; + + #[test] + fn literal_case_insensitivity() { + let tokenized = token::parse("(?-i)../foo/(?i)**/bar/**(?-i)/baz/*(?i)qux").unwrap(); + let literals:Vec<_> = tokenized + .tokens() + .iter() + .filter_map(|token| { + match token.kind { + TokenKind::Literal(ref literal) => Some(literal), + _ => None, + } + }) + .collect(); + + assert!(!literals[0].is_case_insensitive); // `..` + assert!(!literals[1].is_case_insensitive); // `foo` + assert!(literals[2].is_case_insensitive); // `bar` + assert!(!literals[3].is_case_insensitive); // `baz` + assert!(literals[4].is_case_insensitive); // `qux` + } +} diff --git a/crates/turborepo-wax/Source/token/parse.rs b/crates/turborepo-wax/Source/token/parse.rs new file mode 100644 index 0000000000000..da1572a8984e5 --- /dev/null +++ b/crates/turborepo-wax/Source/token/parse.rs @@ -0,0 +1,511 @@ +use std::{ + borrow::Cow, + fmt::{self, Display, Formatter}, + str::FromStr, +}; + +#[cfg(feature = "miette")] +use miette::{self, Diagnostic, LabeledSpan, SourceCode}; +use nom::error::{VerboseError as NomError, VerboseErrorKind as NomErrorKind}; +use pori::{Located, Location, Stateful}; +use thiserror::Error; + +use crate::{ + PATHS_ARE_CASE_INSENSITIVE, + diagnostics::{LocatedError, Span}, + token::{ + Alternative, + Archetype, + Class, + Evaluation, + Literal, + Repetition, + Separator, + Token, + TokenKind, + Tokenized, + Wildcard, + }, +}; + +pub type Annotation = Span; + +type Expression<'i> = Located<'i, str>; +type Input<'i> = Stateful, ParserState>; +type ErrorStack<'i> = NomError>; +type ErrorMode<'i> = nom::Err>; + +pub const ROOT_SEPARATOR_EXPRESSION:&str = "/"; + +#[derive(Clone, Debug)] +pub struct ErrorEntry<'t> { + fragment:Cow<'t, str>, + location:usize, + kind:NomErrorKind, +} + +impl<'t> ErrorEntry<'t> { + pub fn into_owned(self) -> ErrorEntry<'static> { + let ErrorEntry { fragment, location, kind } = self; + ErrorEntry { fragment:fragment.into_owned().into(), location, kind } + } +} + +impl<'t> From<(Input<'t>, NomErrorKind)> for ErrorEntry<'t> { + fn from((input, kind):(Input<'t>, NomErrorKind)) -> Self { + let location = input.location(); + ErrorEntry { fragment:input.into_data().into(), location, kind } + } +} + +#[cfg(feature = "miette")] +impl From> for LabeledSpan { + fn from(error:ErrorEntry<'_>) -> Self { + let span = error.span(); + LabeledSpan::new_with_span(Some(format!("{}", error)), span) + } +} + +impl Display for ErrorEntry<'_> { + fn fmt(&self, f:&mut Formatter) -> fmt::Result { + match self.kind { + NomErrorKind::Char(expected) => { + if let Some(got) = self.fragment.chars().next() { + write!(f, "expected `{}`, got `{}`", expected, got) + } else { + write!(f, "expected `{}`, got end of input", expected) + } + }, + NomErrorKind::Context(context) => write!(f, "in context `{}`", context), + NomErrorKind::Nom(parser) => write!(f, "in sub-parser `{:?}`", parser), + } + } +} + +impl LocatedError for ErrorEntry<'_> { + fn span(&self) -> Span { (self.location, 1) } +} + +/// Describes errors that occur when parsing a glob expression. +/// +/// Common examples of glob expressions that cannot be parsed are alternative +/// and repetition patterns with missing delimiters and ambiguous patterns, such +/// as `src/***/*.rs` or `{.local,.config/**/*.toml`. +#[derive(Clone, Debug, Error)] +#[error("failed to parse glob expression")] +pub struct ParseError<'t> { + expression:Cow<'t, str>, + locations:Vec>, +} + +impl<'t> ParseError<'t> { + fn new(expression:&'t str, error:ErrorMode<'t>) -> Self { + match error { + ErrorMode::Incomplete(_) => { + panic!("unexpected parse error: incomplete input") + }, + ErrorMode::Error(stack) | ErrorMode::Failure(stack) => { + ParseError { + expression:expression.into(), + locations:stack.errors.into_iter().map(From::from).collect(), + } + }, + } + } + + /// Clones any borrowed data into an owning instance. + pub fn into_owned(self) -> ParseError<'static> { + let ParseError { expression, locations } = self; + ParseError { + expression:expression.into_owned().into(), + locations:locations.into_iter().map(ErrorEntry::into_owned).collect(), + } + } + + pub fn locations(&self) -> &[ErrorEntry<'t>] { &self.locations } + + /// Gets the glob expression that failed to parse. + pub fn expression(&self) -> &str { self.expression.as_ref() } +} + +#[cfg(feature = "miette")] +#[cfg_attr(docsrs, doc(cfg(feature = "miette")))] +impl Diagnostic for ParseError<'_> { + fn code<'a>(&'a self) -> Option> { Some(Box::new("wax::glob::parse")) } + + fn source_code(&self) -> Option<&dyn SourceCode> { Some(&self.expression) } + + fn labels(&self) -> Option + '_>> { + Some(Box::new(self.locations.iter().cloned().map(From::from))) + } +} + +#[derive(Clone, Copy, Debug, Default)] +struct ParserState { + flags:FlagState, + subexpression:usize, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +struct FlagState { + is_case_insensitive:bool, +} + +impl Default for FlagState { + fn default() -> Self { FlagState { is_case_insensitive:PATHS_ARE_CASE_INSENSITIVE } } +} + +#[derive(Clone, Copy, Debug)] +enum FlagToggle { + CaseInsensitive(bool), +} + +pub fn parse(expression:&str) -> Result { + use nom::{ + IResult, + Parser, + branch, + bytes::complete as bytes, + character::complete as character, + combinator, + error, + multi, + sequence, + }; + + use crate::token::parse::FlagToggle::CaseInsensitive; + + type ParseResult<'i, O> = IResult, O, ErrorStack<'i>>; + + fn boe(input:Input) -> ParseResult { + if input.state.subexpression == input.location() { + Ok((input, input)) + } else { + Err(ErrorMode::Error(ErrorStack { + errors:vec![(input, NomErrorKind::Context("beginning of expression"))], + })) + } + } + + fn flags<'i, F>( + mut toggle:impl FnMut(FlagToggle) -> F, + ) -> impl FnMut(Input<'i>) -> ParseResult<'i, ()> + where + F: Parser, (), ErrorStack<'i>>, { + move |input| { + let (input, _) = multi::many0(sequence::delimited( + bytes::tag("(?"), + multi::many1(branch::alt(( + sequence::tuple((bytes::tag("i"), toggle(CaseInsensitive(true)))), + sequence::tuple((bytes::tag("-i"), toggle(CaseInsensitive(false)))), + ))), + bytes::tag(")"), + ))(input)?; + Ok((input, ())) + } + } + + // Explicit lifetimes prevent inference errors. + #[allow(clippy::needless_lifetimes)] + fn flags_with_state<'i>(input:Input<'i>) -> ParseResult<'i, ()> { + flags(move |toggle| { + move |mut input:Input<'i>| { + match toggle { + CaseInsensitive(toggle) => { + input.state.flags.is_case_insensitive = toggle; + }, + } + Ok((input, ())) + } + })(input) + } + + // Explicit lifetimes prevent inference errors. + #[allow(clippy::needless_lifetimes)] + fn flags_without_state<'i>(input:Input<'i>) -> ParseResult<'i, ()> { + flags(move |_| move |input:Input<'i>| Ok((input, ())))(input) + } + + fn literal(input:Input) -> ParseResult> { + combinator::map( + combinator::verify( + bytes::escaped_transform( + bytes::is_not("/?*$:<>()[]{},\\"), + '\\', + branch::alt(( + combinator::value("?", bytes::tag("?")), + combinator::value("*", bytes::tag("*")), + combinator::value("$", bytes::tag("$")), + combinator::value(":", bytes::tag(":")), + combinator::value("<", bytes::tag("<")), + combinator::value(">", bytes::tag(">")), + combinator::value("(", bytes::tag("(")), + combinator::value(")", bytes::tag(")")), + combinator::value("[", bytes::tag("[")), + combinator::value("]", bytes::tag("]")), + combinator::value("{", bytes::tag("{")), + combinator::value("}", bytes::tag("}")), + combinator::value(",", bytes::tag(",")), + )), + ), + |text:&str| !text.is_empty(), + ), + move |text| { + TokenKind::Literal(Literal { + text:text.into(), + is_case_insensitive:input.state.flags.is_case_insensitive, + }) + }, + )(input) + } + + fn separator(input:Input) -> ParseResult> { + combinator::value(TokenKind::Separator(Separator), bytes::tag("/"))(input) + } + + fn wildcard<'i>( + terminator:impl Clone + Parser, Input<'i>, ErrorStack<'i>>, + ) -> impl FnMut(Input<'i>) -> ParseResult<'i, TokenKind<'i, Annotation>> { + branch::alt(( + error::context( + "exactly-one", + combinator::map(bytes::tag("?"), |_| TokenKind::from(Wildcard::One)), + ), + error::context( + "tree", + combinator::map( + sequence::tuple(( + error::context( + "prefix", + combinator::map( + branch::alt(( + sequence::tuple(( + combinator::value(true, bytes::tag("/")), + flags_with_state, + )), + sequence::tuple(( + combinator::value(false, boe), + flags_with_state, + )), + )), + |(prefix, _)| prefix, + ), + ), + sequence::terminated( + bytes::tag("**"), + error::context( + "postfix", + branch::alt(( + combinator::map( + sequence::tuple((flags_with_state, bytes::tag("/"))), + |(_, postfix)| postfix, + ), + terminator.clone(), + )), + ), + ), + )), + |(has_root, _)| Wildcard::Tree { has_root }.into(), + ), + ), + error::context( + "zero-or-more", + combinator::map( + sequence::terminated( + bytes::tag("*"), + branch::alt(( + combinator::map( + combinator::peek(sequence::tuple(( + flags_without_state, + error::context("no terminating wildcard", bytes::is_not("*$")), + ))), + |(_, right)| right, + ), + terminator.clone(), + )), + ), + |_| Wildcard::ZeroOrMore(Evaluation::Eager).into(), + ), + ), + error::context( + "zero-or-more", + combinator::map( + sequence::terminated( + bytes::tag("$"), + branch::alt(( + combinator::map( + combinator::peek(sequence::tuple(( + flags_without_state, + error::context("no terminating wildcard", bytes::is_not("*$")), + ))), + |(_, right)| right, + ), + terminator, + )), + ), + |_| Wildcard::ZeroOrMore(Evaluation::Lazy).into(), + ), + ), + )) + } + + fn repetition(input:Input) -> ParseResult> { + fn bounds(input:Input) -> ParseResult<(usize, Option)> { + type BoundResult = Result::Err>; + + branch::alt(( + sequence::preceded( + bytes::tag(":"), + branch::alt(( + error::context( + "range", + combinator::map_res( + sequence::separated_pair( + character::digit1, + bytes::tag(","), + combinator::opt(character::digit1), + ), + |(lower, upper):(Input, Option<_>)| -> BoundResult<_> { + let lower = lower.parse::()?; + let upper = + upper.map(|upper| upper.parse::()).transpose()?; + Ok((lower, upper)) + }, + ), + ), + error::context( + "converged", + combinator::map_res(character::digit1, |n:Input| -> BoundResult<_> { + let n = n.parse::()?; + Ok((n, Some(n))) + }), + ), + combinator::success((1, None)), + )), + ), + combinator::success((0, None)), + ))(input) + } + + combinator::map( + sequence::delimited( + bytes::tag("<"), + sequence::tuple(( + error::context( + "sub-glob", + glob(move |input| { + combinator::peek(branch::alt((bytes::tag(":"), bytes::tag(">"))))(input) + }), + ), + error::context("bounds", bounds), + )), + bytes::tag(">"), + ), + |(tokens, (lower, upper))| Repetition { tokens, lower, upper }.into(), + )(input) + } + + fn class(input:Input) -> ParseResult> { + fn archetypes(input:Input) -> ParseResult> { + let escaped_character = |input| { + branch::alt(( + character::none_of("[]-\\"), + branch::alt(( + combinator::value('[', bytes::tag("\\[")), + combinator::value(']', bytes::tag("\\]")), + combinator::value('-', bytes::tag("\\-")), + )), + ))(input) + }; + + multi::many1(branch::alt(( + combinator::map( + sequence::separated_pair(escaped_character, bytes::tag("-"), escaped_character), + Archetype::from, + ), + combinator::map(escaped_character, Archetype::from), + )))(input) + } + + combinator::map( + sequence::delimited( + bytes::tag("["), + sequence::tuple((combinator::opt(bytes::tag("!").or(bytes::tag("^"))), archetypes)), + bytes::tag("]"), + ), + |(negation, archetypes)| Class { is_negated:negation.is_some(), archetypes }.into(), + )(input) + } + + fn alternative(input:Input) -> ParseResult> { + sequence::delimited( + bytes::tag("{"), + combinator::map( + multi::separated_list1( + bytes::tag(","), + error::context( + "sub-glob", + glob(move |input| { + combinator::peek(branch::alt((bytes::tag(","), bytes::tag("}"))))(input) + }), + ), + ), + |alternatives:Vec>| Alternative::from(alternatives).into(), + ), + bytes::tag("}"), + )(input) + } + + fn glob<'i>( + terminator:impl 'i + Clone + Parser, Input<'i>, ErrorStack<'i>>, + ) -> impl Parser, Vec>, ErrorStack<'i>> { + fn annotate<'i, F>( + parser:F, + ) -> impl FnMut(Input<'i>) -> ParseResult<'i, Token<'i, Annotation>> + where + F: 'i + Parser, TokenKind<'i, Annotation>, ErrorStack<'i>>, { + combinator::map(pori::span(parser), |(span, kind)| Token::new(kind, span)) + } + + move |mut input:Input<'i>| { + input.state.subexpression = input.location(); + sequence::terminated( + multi::many1(branch::alt(( + annotate(error::context( + "literal", + sequence::preceded(flags_with_state, literal), + )), + annotate(error::context( + "repetition", + sequence::preceded(flags_with_state, repetition), + )), + annotate(error::context( + "alternative", + sequence::preceded(flags_with_state, alternative), + )), + annotate(error::context( + "wildcard", + sequence::preceded(flags_with_state, wildcard(terminator.clone())), + )), + annotate(error::context("class", sequence::preceded(flags_with_state, class))), + annotate(error::context( + "separator", + sequence::preceded(flags_with_state, separator), + )), + ))), + terminator.clone(), + ) + .parse(input) + } + } + + if expression.is_empty() { + Ok(Tokenized { expression:expression.into(), tokens:vec![] }) + } else { + let input = Input::new(Expression::from(expression), ParserState::default()); + let tokens = combinator::all_consuming(glob(combinator::eof))(input) + .map(|(_, tokens)| tokens) + .map_err(|error| ParseError::new(expression, error))?; + Ok(Tokenized { expression:expression.into(), tokens }) + } +} diff --git a/crates/turborepo-wax/Source/token/variance.rs b/crates/turborepo-wax/Source/token/variance.rs new file mode 100644 index 0000000000000..44435e4c5751d --- /dev/null +++ b/crates/turborepo-wax/Source/token/variance.rs @@ -0,0 +1,580 @@ +use std::{ + borrow::Cow, + collections::VecDeque, + ops::{Add, Mul}, +}; + +use itertools::Itertools as _; + +use crate::{ + PATHS_ARE_CASE_INSENSITIVE, + encode, + token::{self, Separator, Token}, +}; + +pub trait Invariance: + Add + Eq + Mul + PartialEq + Sized { + fn empty() -> Self; +} + +pub trait UnitVariance { + fn unit_variance(self) -> Variance; +} + +impl UnitVariance for Variance { + fn unit_variance(self) -> Variance { self } +} + +pub trait ConjunctiveVariance: Iterator + Sized +where + Self::Item: UnitVariance, + T: Invariance, { + fn conjunctive_variance(self) -> Variance { + self.map(UnitVariance::unit_variance) + .reduce(Add::add) + .unwrap_or_else(|| Variance::Invariant(T::empty())) + } +} + +impl ConjunctiveVariance for I +where + I: Iterator, + I::Item: UnitVariance, + T: Invariance, +{ +} + +pub trait DisjunctiveVariance: Iterator + Sized +where + Self::Item: UnitVariance, + T: Invariance, { + fn disjunctive_variance(self) -> Variance { + // TODO: This implementation is incomplete. Unbounded variance (and + // unbounded depth) are "infectious" when disjunctive. If any unit + // variance is variant and unbounded (open), then the disjunctive + // variance should be the same. + // There are three distinct possibilities for disjunctive variance. + // + // - The iterator is empty and there are no unit variances to consider. The + // disjunctive variance is the empty invariant. + // - The iterator is non-empty and all unit variances are equal. The + // disjunctive variance is the same as any of the like unit variances. + // - The iterator is non-empty and the unit variances are **not** all equal. + // The disjunctive variance is variant and bounded (closed). + let mut variances = self.map(UnitVariance::unit_variance).fuse(); + let first = variances.next().unwrap_or_else(|| Variance::Invariant(T::empty())); + if variances.all(|variance| first == variance) { + first + } else { + Variance::Variant(Boundedness::Closed) + } + } +} + +impl DisjunctiveVariance for I +where + I: Iterator, + I::Item: UnitVariance, + T: Invariance, +{ +} + +pub trait UnitDepth: Sized { + fn unit_depth(self) -> Boundedness { Boundedness::Closed } +} + +impl UnitDepth for Boundedness { + fn unit_depth(self) -> Boundedness { self } +} + +pub trait CompositeDepth: Iterator + Sized { + fn composite_depth(self) -> Boundedness; +} + +impl CompositeDepth for I +where + I: Iterator, + I::Item: UnitDepth, +{ + fn composite_depth(self) -> Boundedness { + if self.map(UnitDepth::unit_depth).any(|depth| depth.is_open()) { + Boundedness::Open + } else { + Boundedness::Closed + } + } +} + +pub trait UnitBreadth: Sized { + fn unit_breadth(self) -> Boundedness { Boundedness::Closed } +} + +impl UnitBreadth for Boundedness { + fn unit_breadth(self) -> Boundedness { self } +} + +pub trait CompositeBreadth: Iterator + Sized { + fn composite_breadth(self) -> Boundedness; +} + +impl CompositeBreadth for I +where + I: Iterator, + I::Item: UnitBreadth, +{ + fn composite_breadth(self) -> Boundedness { + if self.map(UnitBreadth::unit_breadth).any(|breadth| breadth.is_open()) { + Boundedness::Open + } else { + Boundedness::Closed + } + } +} + +pub trait IntoInvariantText<'t> { + fn into_nominal_text(self) -> InvariantText<'t>; + + fn into_structural_text(self) -> InvariantText<'t>; +} + +impl<'t> IntoInvariantText<'t> for Cow<'t, str> { + fn into_nominal_text(self) -> InvariantText<'t> { InvariantFragment::Nominal(self).into() } + + fn into_structural_text(self) -> InvariantText<'t> { + InvariantFragment::Structural(self).into() + } +} + +impl IntoInvariantText<'static> for String { + fn into_nominal_text(self) -> InvariantText<'static> { + InvariantFragment::Nominal(self.into()).into() + } + + fn into_structural_text(self) -> InvariantText<'static> { + InvariantFragment::Structural(self.into()).into() + } +} + +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct InvariantSize(usize); + +impl InvariantSize { + pub const fn new(n:usize) -> Self { InvariantSize(n) } +} + +impl Add for InvariantSize { + type Output = Self; + + fn add(self, other:Self) -> Self::Output { InvariantSize(self.0 + other.0) } +} + +impl From for usize { + fn from(size:InvariantSize) -> Self { size.0 } +} + +impl From for InvariantSize { + fn from(n:usize) -> Self { InvariantSize(n) } +} + +impl Invariance for InvariantSize { + fn empty() -> Self { InvariantSize(0) } +} + +impl Mul for InvariantSize { + type Output = Self; + + fn mul(self, n:usize) -> Self::Output { + InvariantSize(self.0.checked_mul(n).expect("overflow determining invariant size")) + } +} + +// TODO: The derived `PartialEq` implementation is incomplete and does not +// detect contiguous like fragments that are equivalent to an aggregated +// fragment. This works, but relies on constructing `InvariantText` by +// consistently appending fragments. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct InvariantText<'t> { + fragments:VecDeque>, +} + +impl<'t> InvariantText<'t> { + pub fn new() -> Self { InvariantText { fragments:VecDeque::new() } } + + pub fn into_owned(self) -> InvariantText<'static> { + let InvariantText { fragments } = self; + InvariantText { + fragments:fragments.into_iter().map(InvariantFragment::into_owned).collect(), + } + } + + pub fn to_string(&self) -> Cow<'t, str> { + self.fragments + .iter() + .map(|fragment| fragment.as_string().clone()) + .reduce(|text, fragment| text + fragment) + .unwrap_or(Cow::Borrowed("")) + } + + pub fn repeat(self, n:usize) -> Self { + if n == 0 { + self + } else { + let InvariantText { fragments } = self; + let n = (n - 1) + .checked_mul(fragments.len()) + .expect("overflow determining invariant text"); + let first = fragments.clone(); + InvariantText { + fragments:first.into_iter().chain(fragments.into_iter().cycle().take(n)).collect(), + } + } + } +} + +impl<'t> Add for InvariantText<'t> { + type Output = Self; + + fn add(self, other:Self) -> Self::Output { + let InvariantText { fragments: mut left } = self; + let InvariantText { fragments: mut right } = other; + let end = left.pop_back(); + let start = right.pop_front(); + let InvariantText { fragments: middle } = match (end, start) { + (Some(left), Some(right)) => left + right, + (Some(middle), None) | (None, Some(middle)) => middle.into(), + (None, None) => InvariantText::new(), + }; + InvariantText { fragments:left.into_iter().chain(middle).chain(right).collect() } + } +} + +impl<'t> Add> for InvariantText<'t> { + type Output = Self; + + fn add(self, fragment:InvariantFragment<'t>) -> Self::Output { self + Self::from(fragment) } +} + +impl<'t> Default for InvariantText<'t> { + fn default() -> Self { Self::new() } +} + +impl<'t> From> for InvariantText<'t> { + fn from(fragment:InvariantFragment<'t>) -> Self { + InvariantText { fragments:[fragment].into_iter().collect() } + } +} + +impl<'t> Invariance for InvariantText<'t> { + fn empty() -> Self { InvariantText::new() } +} + +impl<'t> Mul for InvariantText<'t> { + type Output = Self; + + fn mul(self, n:usize) -> Self::Output { self.repeat(n) } +} + +#[derive(Clone, Debug, Eq)] +enum InvariantFragment<'t> { + Nominal(Cow<'t, str>), + Structural(Cow<'t, str>), +} + +impl<'t> InvariantFragment<'t> { + pub fn into_owned(self) -> InvariantFragment<'static> { + use InvariantFragment::{Nominal, Structural}; + + match self { + Nominal(text) => Nominal(text.into_owned().into()), + Structural(text) => Structural(text.into_owned().into()), + } + } + + pub fn as_string(&self) -> &Cow<'t, str> { + match self { + InvariantFragment::Nominal(ref text) | InvariantFragment::Structural(ref text) => text, + } + } +} + +impl<'t> Add for InvariantFragment<'t> { + type Output = InvariantText<'t>; + + fn add(self, other:Self) -> Self::Output { + use InvariantFragment::{Nominal, Structural}; + + match (self, other) { + (Nominal(left), Nominal(right)) => { + InvariantText { fragments:[Nominal(left + right)].into_iter().collect() } + }, + (Structural(left), Structural(right)) => { + InvariantText { fragments:[Structural(left + right)].into_iter().collect() } + }, + (left, right) => InvariantText { fragments:[left, right].into_iter().collect() }, + } + } +} + +impl<'t> PartialEq for InvariantFragment<'t> { + fn eq(&self, other:&Self) -> bool { + use InvariantFragment::{Nominal, Structural}; + + match (self, other) { + (Nominal(ref left), Nominal(ref right)) => { + if PATHS_ARE_CASE_INSENSITIVE { + // This comparison uses Unicode simple case folding. It + // would be better to use full case folding (and better + // still to use case folding appropriate for the language of + // the text), but this approach is used to have consistent + // results with the regular expression encoding of compiled + // globs. A more comprehensive alternative would be to use + // something like the `focaccia` crate. See also + // `CharExt::has_casing`. + encode::case_folded_eq(left.as_ref(), right.as_ref()) + } else { + left == right + } + }, + (Structural(ref left), Structural(ref right)) => left == right, + _ => false, + } + } +} + +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum Boundedness { + Closed, + Open, +} + +impl Boundedness { + pub fn is_closed(&self) -> bool { matches!(self, Boundedness::Closed) } + + pub fn is_open(&self) -> bool { matches!(self, Boundedness::Open) } +} + +#[derive(Clone, Debug, Eq)] +pub enum Variance { + Invariant(T), + // In this context, _boundedness_ refers to whether or not a variant token or expression is + // _constrained_ or _unconstrained_. For example, the expression `**` is unconstrained and + // matches _any and all_, while the expression `a*z` is constrained and matches _some_. Note + // that both expressions match an infinite number of components, but the constrained + // expression does *not* match any component. Boundedness does **not** consider length, + // only whether or not some part of an expression is constrained to a known set of + // matches. As such, both the expressions `?` and `*` are variant with open bounds. + Variant(Boundedness), +} + +impl Variance { + pub fn map_invariance(self, mut f:impl FnMut(T) -> U) -> Variance { + match self { + Variance::Invariant(invariant) => Variance::Invariant(f(invariant)), + Variance::Variant(boundedness) => Variance::Variant(boundedness), + } + } + + pub fn as_invariance(&self) -> Option<&T> { + match self { + Variance::Invariant(ref invariant) => Some(invariant), + _ => None, + } + } + + pub fn boundedness(&self) -> Boundedness { + match self { + Variance::Variant(ref boundedness) => *boundedness, + _ => Boundedness::Closed, + } + } + + pub fn is_invariant(&self) -> bool { matches!(self, Variance::Invariant(_)) } + + pub fn is_variant(&self) -> bool { matches!(self, Variance::Variant(_)) } +} + +impl Add for Variance +where + T: Add, +{ + type Output = Self; + + fn add(self, rhs:Self) -> Self::Output { + use Boundedness::{Closed, Open}; + use Variance::{Invariant, Variant}; + + match (self, rhs) { + (Invariant(left), Invariant(right)) => Invariant(left + right), + (Variant(Open), Variant(Open)) => Variant(Open), + (Invariant(_) | Variant(_), Variant(_)) | (Variant(_), Invariant(_)) => Variant(Closed), + } + } +} + +impl PartialEq for Variance +where + T: PartialEq, +{ + fn eq(&self, other:&Self) -> bool { + match (self, other) { + (Variance::Invariant(ref left), Variance::Invariant(ref right)) => left == right, + (Variance::Variant(ref left), Variance::Variant(ref right)) => left == right, + _ => false, + } + } +} + +// TODO: Is there some way to unify this with +// `invariant_text_prefix_upper_bound`? +pub fn invariant_text_prefix<'t, A, I>(tokens:I) -> String +where + A: 't, + I: IntoIterator>, { + let separator = &Separator::invariant_text(); + let mut tokens = tokens.into_iter().peekable(); + let mut prefix = String::new(); + if tokens.peek().map_or(false, |token| !token.has_sub_tokens() && token.has_root()) { + // Push a preceding separator if the first token has a root and is not a group. + // This ensures that initiating separators and tree wildcards express a + // root in invariant prefixes. + prefix.push_str(separator); + } + // TODO: Replace `map`, `take_while`, and `flatten` with `map_while` when it + // stabilizes. + prefix.push_str( + &token::components(tokens) + .map(|component| { + component + .variance::() + .as_invariance() + .map(InvariantText::to_string) + .map(Cow::into_owned) + }) + .take_while(Option::is_some) + .flatten() + .join(separator), + ); + prefix +} + +pub fn invariant_text_prefix_upper_bound<'t, A, I>(tokens:I) -> usize +where + A: 't, + I: IntoIterator>, { + use crate::token::{ + TokenKind::{Separator, Wildcard}, + Wildcard::Tree, + }; + + let mut m = 0usize; + let mut separator = None; + for (n, token) in tokens.into_iter().map(Token::kind).enumerate() { + m = n; + match token { + Separator(_) => { + separator = Some(n); + }, + Wildcard(Tree { .. }) => { + return n; + }, + _ => { + if token.variance::().is_invariant() { + continue; + } + return match separator { + Some(n) => n + 1, + None => 0, + }; + }, + } + } + m + 1 +} + +/// Returns `true` if the token tree is exhaustive. +/// +/// A glob expression and its token tree are exhaustive if the terminal +/// component has unbounded depth and unbounded variance. +pub fn is_exhaustive<'i, 't, A, I>(tokens:I) -> bool +where + 't:'i, + A: 't, + I: IntoIterator>, { + let component = token::components(tokens).last(); + matches!( + component.map(|component| { + (component.depth(), component.variance::().boundedness()) + }), + Some((Boundedness::Open, Boundedness::Open)), + ) +} + +#[cfg(test)] +mod tests { + use std::path::{Path, PathBuf}; + + use crate::token::{ + self, + TokenTree, + variance::{self, Boundedness, InvariantSize, Variance}, + }; + + #[test] + fn invariant_text_prefix() { + fn invariant_path_prefix(expression:&str) -> PathBuf { + variance::invariant_text_prefix(token::parse(expression).unwrap().tokens()).into() + } + + assert_eq!(invariant_path_prefix("/a/b"), Path::new("/a/b")); + assert_eq!(invariant_path_prefix("a/b"), Path::new("a/b")); + assert_eq!(invariant_path_prefix("a/*"), Path::new("a")); + assert_eq!(invariant_path_prefix("a/*b"), Path::new("a")); + assert_eq!(invariant_path_prefix("a/b*"), Path::new("a")); + assert_eq!(invariant_path_prefix("a/b/*/c"), Path::new("a/b")); + + #[cfg(any(unix, windows))] + let prefix = invariant_path_prefix("../foo/(?i)bar/(?-i)baz"); + #[cfg(unix)] + assert_eq!(prefix, Path::new("../foo")); + #[cfg(windows)] + assert_eq!(prefix, Path::new("../foo/bar")); + + assert_eq!(invariant_path_prefix("**"), Path::new("")); + assert_eq!(invariant_path_prefix("a*"), Path::new("")); + assert_eq!(invariant_path_prefix("*/b"), Path::new("")); + assert_eq!(invariant_path_prefix("a?/b"), Path::new("")); + } + + #[test] + fn tree_expression_variance() { + use Boundedness::{Closed, Open}; + use Variance::Variant; + + let tokenized = token::parse("**").unwrap(); + assert!(matches!(tokenized.variance::(), Variant(Open))); + let tokenized = token::parse("<*/>*").unwrap(); + assert!(matches!(tokenized.variance::(), Variant(Open))); + let tokenized = token::parse("</>*").unwrap(); + assert!(matches!(tokenized.variance::(), Variant(Open))); + + let tokenized = token::parse("foo/**").unwrap(); + assert!(matches!(tokenized.variance::(), Variant(Closed))); + let tokenized = token::parse("*").unwrap(); + assert!(matches!(tokenized.variance::(), Variant(Closed))); + } + + #[test] + fn exhaustiveness() { + assert!(token::is_exhaustive(token::parse("**").unwrap().tokens())); + assert!(token::is_exhaustive(token::parse("a/**").unwrap().tokens())); + assert!(token::is_exhaustive(token::parse("a/<*/>*").unwrap().tokens())); + assert!(token::is_exhaustive(token::parse("a/</>*").unwrap().tokens())); + + assert!(!token::is_exhaustive(token::parse("a/**/b").unwrap().tokens())); + assert!(!token::is_exhaustive(token::parse("a/*").unwrap().tokens())); + assert!(!token::is_exhaustive(token::parse("a/").unwrap().tokens())); + assert!(!token::is_exhaustive(token::parse("a").unwrap().tokens())); + assert!(!token::is_exhaustive(token::parse("**/a").unwrap().tokens())); + assert!(!token::is_exhaustive(token::parse("").unwrap().tokens())); + } +} diff --git a/crates/turborepo-wax/Source/walk/filter.rs b/crates/turborepo-wax/Source/walk/filter.rs new file mode 100644 index 0000000000000..1672e25dd48e4 --- /dev/null +++ b/crates/turborepo-wax/Source/walk/filter.rs @@ -0,0 +1,623 @@ +//! Separating filters that do not discard residue. +//! +//! This module provides APIs for separating filters that partition a feed +//! (input) into a filtrate and residue on a per-item basis. The primary API is +//! the [`SeparatingFilter`] trait, which behaves much like the standard +//! [`Iterator`] trait and is similarly composable via combinators. +//! +//! Unlike [`Iterator::filter`] and similar APIs, [`SeparatingFilter`]s do +//! **not** discard residue. Instead, both the filtrate and the residue is +//! present and can therefore be observed by composed filters. This is important +//! if combinators have side effects that depend on observing filtered data from +//! upstream filters. For example, [`HierarchicalIterator`] provides combinators +//! for filtering that can affect the traversal of a tree by discarding a +//! sub-tree. This behavior may need to be invoked regardless of whether or not +//! data is filtrate or residue. +//! +//! [`SeparatingFilter`]s may also be [`Iterator`]s, in which case only the +//! filtrate is typically exposed in the [`Iterator`] API (the associated `Item` +//! type is the `Filtrate` type of the filter's associated `Feed` type). +//! +//! [`Iterator`]: std::iter::Iterator +//! [`Iterator::filter`]: std::iter::Iterator::filter +//! [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter + +use std::{ + cmp::{Eq, PartialEq}, + hash::{Hash, Hasher}, + marker::PhantomData, +}; + +mod kind { + #[derive(Debug)] + pub enum FiltrateKind {} + #[derive(Debug)] + pub enum ResidueKind {} +} +use kind::*; + +#[derive(Debug)] +pub struct Product { + inner:T, + _phantom:PhantomData K>, +} + +impl Product { + pub(super) fn new(inner:T) -> Self { Product { inner, _phantom:PhantomData } } + + pub fn into_inner(self) -> T { self.inner } + + pub fn map(self, f:F) -> Product + where + F: FnOnce(T) -> U, { + Product::new(f(self.into_inner())) + } + + pub fn get(&self) -> &T { &self.inner } +} + +impl Product> { + pub fn transpose(self) -> Option> { self.inner.map(Product::new) } +} + +impl Product> { + pub fn transpose(self) -> Result, Product> { + self.inner.map(Product::new).map_err(Product::new) + } +} + +impl AsRef for Product { + fn as_ref(&self) -> &T { self.get() } +} + +impl Copy for Product where T: Copy {} + +impl Clone for Product +where + T: Clone, +{ + fn clone(&self) -> Self { Product::new(self.inner.clone()) } +} + +impl Eq for Product where T: Eq {} + +impl Hash for Product +where + T: Hash, +{ + fn hash(&self, state:&mut H) + where + H: Hasher, { + self.inner.hash(state); + } +} + +impl PartialEq for Product +where + T: PartialEq, +{ + fn eq(&self, other:&Self) -> bool { self.inner.eq(&other.inner) } +} + +pub type Filtrate = Product; +pub type Residue = Product; + +impl Filtrate { + pub fn filter(self) -> Residue { self.filter_map(From::from) } + + pub fn filter_map(self, f:F) -> Residue + where + F: FnOnce(T) -> R, { + Residue::new(f(self.into_inner())) + } + + pub fn filter_node(self) -> Residue> + where + R: From, { + self.filter_map_node(From::from) + } + + pub fn filter_map_node(self, f:F) -> Residue> + where + F: FnOnce(T) -> R, { + Residue::new(TreeResidue::Node(f(self.into_inner()))) + } + + pub fn filter_tree( + self, + cancellation:WalkCancellation<'_, I>, + ) -> Residue> + where + I: CancelWalk, + R: From, { + self.filter_map_tree(cancellation, From::from) + } + + pub fn filter_map_tree( + self, + cancellation:WalkCancellation<'_, I>, + f:F, + ) -> Residue> + where + I: CancelWalk, + F: FnOnce(T) -> R, { + cancellation.cancel_walk_tree(); + Residue::new(TreeResidue::Tree(f(self.into_inner()))) + } +} + +impl AsRef for Residue> { + fn as_ref(&self) -> &T { self.get().get() } +} + +/// Describes the input and output types of a [`SeparatingFilter`]. +/// +/// `Feed` types are typically represented as tuples of the filtrate and residue +/// types, in that order. +/// +/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter +pub trait Feed { + type Filtrate; + type Residue; +} + +impl Feed for (T, R) { + type Filtrate = T; + type Residue = R; +} + +/// A filter [`Feed`] wherein the filtrate and residue have or can produce a +/// substituent. +/// +/// A substituent is data that is common to both the filtrate and residue (that +/// is, the filtrate and residue are isomers). An `Isomeric` feed can be +/// filtered nominally on the basis of its substituent. See +/// [`Separation::filter_tree_by_substituent`] and +/// [`HierarchicalIterator::filter_tree_by_substituent`], for example. +/// +/// [`Feed`]: crate::walk::filter::Feed +/// [`HierarchicalIterator::filter_tree_by_substituent`]: crate::walk::filter::HierarchicalIterator::filter_tree_by_substituent +/// [`Separation::filter_tree_by_substituent`]: crate::walk::filter::Separation::filter_tree_by_substituent +pub trait Isomeric: Feed { + type Substituent<'a> + where + Self: 'a; + + fn substituent(separation:&Separation) -> Self::Substituent<'_>; +} + +// TODO: The derived trait implementations are likely incorrect and imply a +// bound on `S`. It just so happens that `S` is typically a tuple and +// tuples will implement these same traits if the composed types implement +// them. Instead, the bounds ought to be on the associated `Filtrate` and +// `Residue` types. +/// The separated output of a [`SeparatingFilter`] feed. +/// +/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum Separation +where + S: Feed + ?Sized, { + Filtrate(Filtrate), + Residue(Residue), +} + +impl Separation +where + S: Feed, +{ + fn from_inner_filtrate(filtrate:S::Filtrate) -> Self { + Separation::Filtrate(Filtrate::new(filtrate)) + } + + fn from_inner_residue(residue:S::Residue) -> Self { Separation::Residue(Residue::new(residue)) } + + pub fn filter_map(self, f:F) -> Self + where + F: FnOnce(S::Filtrate) -> S::Residue, { + match self { + Separation::Filtrate(filtrate) => { + Separation::from_inner_residue(f(filtrate.into_inner())) + }, + separation => separation, + } + } + + pub fn map_filtrate(self, f:F) -> Separation<(U, S::Residue)> + where + F: FnOnce(S::Filtrate) -> U, { + match self { + Separation::Filtrate(filtrate) => filtrate.map(f).into(), + Separation::Residue(residue) => residue.into(), + } + } + + pub fn map_residue(self, f:F) -> Separation<(S::Filtrate, U)> + where + F: FnOnce(S::Residue) -> U, { + match self { + Separation::Filtrate(filtrate) => filtrate.into(), + Separation::Residue(residue) => residue.map(f).into(), + } + } + + pub fn filtrate(self) -> Option> { + match self { + Separation::Filtrate(filtrate) => Some(filtrate), + _ => None, + } + } + + pub fn as_filtrate(&self) -> Option<&Filtrate> { + match self { + Separation::Filtrate(ref filtrate) => Some(filtrate), + _ => None, + } + } + + pub fn as_ref(&self) -> Separation<(&S::Filtrate, &S::Residue)> { + match self { + Separation::Filtrate(ref filtrate) => { + Separation::Filtrate(Filtrate::new(filtrate.as_ref())) + }, + Separation::Residue(ref residue) => Separation::Residue(Residue::new(residue.as_ref())), + } + } + + pub fn substituent(&self) -> S::Substituent<'_> + where + S: Isomeric, { + S::substituent(self) + } +} + +impl Separation +where + S: Feed>, +{ + pub fn filter_map_node(self, f:F) -> Self + where + F: FnOnce(T) -> R, { + self.filter_map(|filtrate| TreeResidue::Node(f(filtrate))) + } + + pub fn filter_map_tree(self, cancellation:WalkCancellation<'_, I>, f:F) -> Self + where + I: CancelWalk, + F: FnOnce(T) -> R, { + match self { + Separation::Filtrate(filtrate) => { + cancellation.cancel_walk_tree(); + Separation::from_inner_residue(TreeResidue::Node(f(filtrate.into_inner()))) + }, + Separation::Residue(residue) => { + match residue.into_inner() { + TreeResidue::Node(residue) => { + cancellation.cancel_walk_tree(); + Separation::from_inner_residue(TreeResidue::Tree(residue)) + }, + residue => Separation::from_inner_residue(residue), + } + }, + } + } + + pub fn filter_tree_by_substituent( + self, + cancellation:WalkCancellation<'_, I>, + f:F, + ) -> Self + where + S: Isomeric, + R: From, + I: CancelWalk, + F: FnOnce(S::Substituent<'_>) -> Option>, { + match f(self.substituent()) { + Some(TreeResidue::Tree(())) => self.filter_map_tree(cancellation, From::from), + Some(TreeResidue::Node(())) => self.filter_map_node(From::from), + _ => self, + } + } +} + +impl Separation<(Option, R)> { + pub fn transpose_filtrate(self) -> Option> { + match self { + Separation::Filtrate(filtrate) => { + filtrate.into_inner().map(Filtrate::new).map(From::from) + }, + Separation::Residue(residue) => Some(residue.into()), + } + } +} + +impl Separation<(Result, R)> { + pub fn transpose_filtrate(self) -> Result, Filtrate> { + match self { + Separation::Filtrate(filtrate) => { + match filtrate.into_inner() { + Ok(filtrate) => Ok(Filtrate::new(filtrate).into()), + Err(error) => Err(Filtrate::new(error)), + } + }, + Separation::Residue(residue) => Ok(residue.into()), + } + } +} + +impl From> for Separation +where + S: Feed, +{ + fn from(filtrate:Filtrate) -> Self { Separation::Filtrate(filtrate) } +} + +impl From> for Separation +where + S: Feed, +{ + fn from(residue:Residue) -> Self { Separation::Residue(residue) } +} + +pub trait SeparatingFilter { + type Feed: Feed; + + fn feed(&mut self) -> Option>; +} + +impl SeparatingFilter for I +where + I: SeparatingFilterInput, +{ + type Feed = ::Feed; + + fn feed(&mut self) -> Option> { + self.next().map(Separation::from_inner_filtrate) + } +} + +/// [`Iterator`] that provides filtrate input for [`SeparatingFilter`]s. +/// +/// **This trait provides the only API for implementing a +/// [`SeparatingFilter`].** [`Iterator`]s can implement this trait for a +/// transitive [`SeparatingFilter`] implementation that provides all items +/// as filtrate. This bridges [`Iterator`]s into the input of a separating +/// filter. See the [`filtrate`] function for the output analog. +/// +/// [`filtrate`]: crate::walk::filter::filtrate +/// [`Iterator`]: std::iter::Iterator +/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter +pub trait SeparatingFilterInput: Iterator { + type Feed: Feed; +} + +/// A tree traversing type that can cancel traversal into the most recently +/// visited node. +/// +/// See [`HierarchicalIterator`]. +/// +/// [`HierarchicalIterator`]: crate::walk::filter::HierarchicalIterator +pub trait CancelWalk { + fn cancel_walk_tree(&mut self); +} + +/// Cancels traversal into a sub-tree of a [`HierarchicalIterator`]. +/// +/// [`HierarchicalIterator`]: crate::walk::filter::HierarchicalIterator +#[derive(Debug)] +pub struct WalkCancellation<'i, I>(&'i mut I); + +impl<'i, I> WalkCancellation<'i, I> { + // TODO: This module should not allow this at all and `WalkCancellation`, much + // like `Product`, should not be possible to construct outside of the + // module. Instead, client code should rely solely on combinators, but + // this requires RPITIT to write combinators with arbitrary output + // types (like unnameable `FnMut`s). + // + // RPITIT is slated to land at the end of December of 2023. Remove this + // and implement iterators using pure combinators when that happens. + pub(in crate::walk) fn unchecked(tree:&'i mut I) -> Self { WalkCancellation(tree) } +} + +impl<'i, I> WalkCancellation<'i, I> +where + I: CancelWalk, +{ + fn cancel_walk_tree(self) { + // Client code is only able to move a `WalkCancellation` into + // `Separation::filter_map_tree`, at which point the filtered item should be the + // current item of the iterator. + self.0.cancel_walk_tree() + } +} + +/// Residue of a [`SeparatingFilter`] over a tree data structure. +/// +/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum TreeResidue { + Node(T), + Tree(T), +} + +impl TreeResidue { + pub fn map(self, f:F) -> TreeResidue + where + F: FnOnce(T) -> U, { + match self { + TreeResidue::Node(residue) => TreeResidue::Node(f(residue)), + TreeResidue::Tree(residue) => TreeResidue::Tree(f(residue)), + } + } + + pub fn as_ref(&self) -> TreeResidue<&T> { + match self { + TreeResidue::Node(ref residue) => TreeResidue::Node(residue), + TreeResidue::Tree(ref residue) => TreeResidue::Tree(residue), + } + } + + pub fn get(&self) -> &T { + match self { + TreeResidue::Node(ref residue) | TreeResidue::Tree(ref residue) => residue, + } + } +} + +/// Hierarchical iterator over items in a tree data structure. +/// +/// Here, _hierarchical_ means that the iterator traverses the tree in a manner +/// that never yields a node before its ancestors (e.g., a child node before its +/// parent node). Both pre-order DFS and BFS are examples of such a traversal. +/// +/// `HierarchicalIterator` allows client code to control tree traversal when +/// filtering items using a `WalkCancellation`, which discards a particular node +/// and cancels traversal to its child nodes (sub-tree). Filtering a sub-tree +/// completely discards that tree, and no filter separation is produced (no +/// filtrate nor residue). This is the only separating filter operation that +/// explicitly discards a retentate and no downstream filters can observe the +/// discarded sub-tree. +pub trait HierarchicalIterator: + CancelWalk + Iterator::Filtrate> + SeparatingFilter { + fn filter_tree_by_substituent(self, f:F) -> FilterTreeBySubstituent + where + Self: Sized, + Self::Feed: Isomeric, + F: FnMut(::Substituent<'_>) -> Option>, { + FilterTreeBySubstituent { input:self, f } + } + + fn filter_map_tree(self, f:F) -> FilterMapTree + where + Self: Sized, + S: Feed, + F: FnMut(WalkCancellation, Separation) -> Separation, { + FilterMapTree { input:self, f, _phantom:PhantomData } + } +} + +impl HierarchicalIterator for I +where + I: CancelWalk + Iterator::Filtrate> + SeparatingFilter, + I::Feed: Feed>, +{ +} + +#[derive(Clone, Debug)] +pub struct FilterTreeBySubstituent { + input:I, + f:F, +} + +impl CancelWalk for FilterTreeBySubstituent +where + I: CancelWalk, +{ + fn cancel_walk_tree(&mut self) { self.input.cancel_walk_tree() } +} + +impl SeparatingFilter for FilterTreeBySubstituent +where + R: From<::Filtrate>, + I: HierarchicalIterator, + I::Feed: Feed> + Isomeric, + F: FnMut(::Substituent<'_>) -> Option>, +{ + type Feed = I::Feed; + + fn feed(&mut self) -> Option> { + let separation = self.input.feed(); + separation.map(|separation| { + let substituent = separation.substituent(); + match (self.f)(substituent) { + None => separation, + Some(residue) => { + match residue { + TreeResidue::Node(_) => separation.filter_map_node(From::from), + TreeResidue::Tree(_) => { + separation.filter_map_tree(WalkCancellation(self), From::from) + }, + } + }, + } + }) + } +} + +impl Iterator for FilterTreeBySubstituent +where + R: From<::Filtrate>, + I: HierarchicalIterator, + I::Feed: Feed> + Isomeric, + F: FnMut(::Substituent<'_>) -> Option>, +{ + type Item = ::Filtrate; + + fn next(&mut self) -> Option { filtrate(self) } +} + +#[derive(Clone, Debug)] +pub struct FilterMapTree { + input:I, + f:F, + _phantom:PhantomData S>, +} + +impl CancelWalk for FilterMapTree +where + I: CancelWalk, +{ + fn cancel_walk_tree(&mut self) { self.input.cancel_walk_tree() } +} + +impl Iterator for FilterMapTree +where + I: SeparatingFilter, + I::Feed: Feed>, + S: Feed, + F: FnMut(WalkCancellation, Separation) -> Separation, +{ + type Item = <::Feed as Feed>::Filtrate; + + fn next(&mut self) -> Option { filtrate(self) } +} + +impl SeparatingFilter for FilterMapTree +where + I: SeparatingFilter, + I::Feed: Feed>, + S: Feed, + F: FnMut(WalkCancellation, Separation) -> Separation, +{ + type Feed = S; + + fn feed(&mut self) -> Option> { + let separation = self.input.feed(); + separation.map(|separation| (self.f)(WalkCancellation(&mut self.input), separation)) + } +} + +/// Feeds a [`SeparatingFilter`] and yields the next filtrate. +/// +/// This function can be used to implement [`Iterator`] for +/// [`SeparatingFilter`]s and bridges [`SeparatingFilter`]s into the output of +/// an iterator. See the [`SeparatingFilterInput`] trait for the input analog. +/// +/// [`Iterator`]: std::iter::Iterator +/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter +/// [`SeparatingFilterInput`]: crate::walk::filter::SeparatingFilterInput +pub fn filtrate(filter:&mut I) -> Option<::Filtrate> +where + I: SeparatingFilter, { + loop { + if let Some(separation) = filter.feed() { + return match separation.filtrate() { + None => { + continue; + }, + Some(filtrate) => Some(filtrate.into_inner()), + }; + } + return None; + } +} diff --git a/crates/turborepo-wax/Source/walk/glob.rs b/crates/turborepo-wax/Source/walk/glob.rs new file mode 100644 index 0000000000000..9c24d8dc8defa --- /dev/null +++ b/crates/turborepo-wax/Source/walk/glob.rs @@ -0,0 +1,650 @@ +use std::{ + fs::{FileType, Metadata}, + path::{Component, Path, PathBuf}, +}; + +use itertools::Itertools; +use regex::Regex; + +use super::SplitAtDepth; +use crate::{ + BuildError, + CandidatePath, + Glob, + Pattern, + capture::MatchedText, + encode::CompileError, + token::{self, Token, TokenTree}, + walk::{ + Entry, + EntryResidue, + FileIterator, + JoinAndGetDepth, + TreeEntry, + WalkBehavior, + WalkError, + WalkTree, + filter::{HierarchicalIterator, Separation}, + }, +}; + +/// APIs for matching globs against directory trees. +impl<'t> Glob<'t> { + /// Gets an iterator over matching file paths in a directory tree. + /// + /// This function matches a `Glob` against a directory tree, returning a + /// [`FileIterator`] that yields a [`GlobEntry`] for each matching file. + /// `Glob`s are the only [`Pattern`]s that support this semantic + /// operation; it is not possible to match combinators ([`Any`]) against + /// directory trees. + /// + /// As with [`Path::join`] and [`PathBuf::push`], the base directory can be + /// escaped or overridden by rooted `Glob`s. In many cases, the current + /// working directory `.` is an appropriate base directory and will be + /// intuitively ignored if the `Glob` is rooted, such as in `/mnt/media/ + /// **/*.mp4`. The [`has_root`] function can be used to check if a `Glob` is + /// rooted. + /// + /// The root directory is either the given directory or, if rooted, the + /// [invariant prefix][`Glob::partition`] of the `Glob`. Either way, + /// this function joins the given directory with any invariant prefix to + /// potentially begin the walk as far down the tree as possible. **The + /// prefix and any [semantic literals][`Glob::has_semantic_literals`] in + /// this prefix are interpreted semantically as a path**, so components + /// like `.` and `..` that precede variant patterns interact with the + /// base directory semantically. This means that expressions like + /// `../**` escape the base directory as expected on Unix and Windows, for + /// example. To query the root directory of the walk, see [`Glob::walker`]. + /// + /// This function uses the default [`WalkBehavior`]. To configure the + /// behavior of the traversal, see [`Glob::walk_with_behavior`]. + /// + /// Unlike functions in [`Pattern`], **this operation is semantic and + /// interacts with the file system**. + /// + /// # Examples + /// + /// ```rust,no_run + /// use wax::{Glob, walk::Entry}; + /// + /// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); + /// for entry in glob.walk("./Pictures") { + /// let entry = entry.unwrap(); + /// println!("JPEG: {:?}", entry.path()); + /// } + /// ``` + /// + /// Glob expressions do not support general negations, but the [`not`] + /// combinator can be used when walking a directory tree to filter + /// entries using patterns. **This should generally be preferred over + /// functions like [`Iterator::filter`], because it avoids unnecessary reads + /// of directory trees when matching [exhaustive + /// negations][`Pattern::is_exhaustive`].** + /// + /// ```rust,no_run + /// use wax::{ + /// Glob, + /// walk::{Entry, FileIterator}, + /// }; + /// + /// let glob = Glob::new("**/*.(?i){jpg,jpeg,png}").unwrap(); + /// for entry in glob + /// .walk("./Pictures") + /// .not(["**/(i?){background,wallpaper}/**"]) + /// .unwrap() + /// { + /// let entry = entry.unwrap(); + /// println!("{:?}", entry.path()); + /// } + /// ``` + /// + /// [`Any`]: crate::Any + /// [`Glob::walk_with_behavior`]: crate::Glob::walk_with_behavior + /// [`Glob::walker`]: crate::Glob::walker + /// [`GlobEntry`]: crate::walk::GlobEntry + /// [`has_root`]: crate::Glob::has_root + /// [`FileIterator`]: crate::walk::FileIterator + /// [`Iterator::filter`]: std::iter::Iterator::filter + /// [`not`]: crate::walk::FileIterator::not + /// [`Path::join`]: std::path::Path::join + /// [`PathBuf::push`]: std::path::PathBuf::push + /// [`Program`]: crate::Program + /// [`Program::is_exhaustive`]: crate::Program::is_exhaustive + /// [`WalkBehavior`]: crate::walk::WalkBehavior + pub fn walk( + &self, + directory:impl Into, + ) -> impl 'static + FileIterator { + self.walk_with_behavior(directory, WalkBehavior::default()) + } + + /// Gets an iterator over matching files in a directory tree. + /// + /// This function is the same as [`Glob::walk`], but it additionally accepts + /// a [`WalkBehavior`] that configures how the traversal interacts with + /// symbolic links, the maximum depth from the root, etc. + /// + /// Depth is relative to the root directory of the traversal, which is + /// determined by joining the given path and any [invariant + /// prefix][`Glob::partition`] of the `Glob`. + /// + /// See [`Glob::walk`] for more information. + /// + /// # Examples + /// + /// ```rust,no_run + /// use wax::{ + /// Glob, + /// walk::{Entry, WalkBehavior}, + /// }; + /// + /// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); + /// for entry in glob.walk_with_behavior("./Pictures", WalkBehavior::default()) { + /// let entry = entry.unwrap(); + /// println!("JPEG: {:?}", entry.path()); + /// } + /// ``` + /// + /// By default, symbolic links are read as normal files and their targets + /// are ignored. To follow symbolic links and traverse any directories + /// that they reference, specify a [`LinkBehavior`]. + /// + /// ```rust,no_run + /// use wax::{ + /// Glob, + /// walk::{Entry, LinkBehavior}, + /// }; + /// + /// let glob = Glob::new("**/*.txt").unwrap(); + /// for entry in glob.walk_with_behavior("/var/log", LinkBehavior::ReadTarget) { + /// let entry = entry.unwrap(); + /// println!("Log: {:?}", entry.path()); + /// } + /// ``` + /// + /// [`Glob::partition`]: crate::Glob::partition + /// [`Glob::walk`]: crate::Glob::walk + /// [`LinkBehavior`]: crate::walk::LinkBehavior + /// [`WalkBehavior`]: crate::walk::WalkBehavior + pub fn walk_with_behavior( + &self, + directory:impl Into, + behavior:impl Into, + ) -> impl 'static + FileIterator { + self.walker(directory).walk_with_behavior(behavior) + } + + /// Gets an iterator builder over matching files in a directory tree. + /// + /// This function gets an intermediate walker that describes iteration over + /// matching files and provides paths prior to iteration. In particular, + /// `walker` can be used when the root directory of the walk is needed. + /// **The root directory may differ from the directory passed to walking + /// functions.** + /// + /// See [`Glob::walk`]. + /// + /// # Examples + /// + /// ```rust,no_run + /// use wax::{Glob, walk::Entry}; + /// + /// let glob = Glob::new("**/*.{log,txt}").unwrap(); + /// let walker = glob.walker("/var/log"); + /// let root = walker.root_prefix_paths().0.to_path_buf(); + /// for entry in walker.walk() { + /// let entry = entry.unwrap(); + /// println!("Log: {:?}", entry.path()); + /// } + /// ``` + /// + /// [`Glob::walk`]: crate::Glob::walk + pub fn walker(&self, directory:impl Into) -> GlobWalker { + GlobWalker { anchor:self.anchor(directory), program:WalkProgram::from_glob(self) } + } + + fn anchor(&self, directory:impl Into) -> Anchor { + fn invariant_path_prefix<'t, A, I>(tokens:I, root:&Path) -> Option + where + A: 't, + I: IntoIterator>, { + let prefix = token::invariant_text_prefix(tokens); + if prefix.is_empty() { + None + } else { + // here, we don't know if the glob will be walked with or without symlinks, + // so we need to ensure that the invariant prefix optimisation doesn't cross a + // symlink todo: `anchor` knows nothing about the walk behaviour. if it did, we + // could probably skip this conditionally for a small perf bonus + let prefix:PathBuf = prefix.into(); + let mut curr_prefix = prefix.as_path(); + let mut last_symlink = None; + while let Some(parent) = curr_prefix.parent() { + // make sure we don't traverse out of the root + if curr_prefix == root { + break; + } + + if parent.is_symlink() { + last_symlink = Some(parent); + } + curr_prefix = parent; + } + // we found the last symlink, but we need the chance to + // filter it, so take the parent one more time + Some(last_symlink.and_then(Path::parent).map(Into::into).unwrap_or(prefix)) + } + } + + let directory = directory.into(); + // Establish the root directory and any prefix in that root path that is not a + // part of the glob expression. The directory tree is traversed from + // `root`, which may include an invariant prefix from the glob. The + // `prefix` is an integer that specifies how many components from the + // end of the root path must be popped to get the portion of the root + // path that is not present in the glob. The prefix may be empty or may be the + // entirety of `root` depending on `directory` and the glob. + // + // Note that a rooted glob, like in `Path::join`, replaces `directory` when + // establishing the root path. In this case, there is no prefix, as the + // entire root path is present in the glob expression. + let (root, prefix) = match invariant_path_prefix(self.tree.as_ref().tokens(), &directory) { + Some(prefix) => directory.join_and_get_depth(prefix), + _ => (directory, 0), + }; + Anchor { root, prefix } + } +} + +/// Root path and prefix of a `Glob` when walking a particular path. +#[derive(Clone, Debug)] +struct Anchor { + /// The root (starting) directory of the walk. + root:PathBuf, + // TODO: Is there a better name for this? This is a prefix w.r.t. a glob but is a suffix w.r.t. + // the root directory. This can be a bit confusing since either perspective is reasonable + // (and in some contexts one may be more intuitive than the other). + /// The number of components from the end of `root` that are present in the + /// `Glob`'s expression. + prefix:usize, +} + +impl Anchor { + pub fn root_prefix_paths(&self) -> (&Path, &Path) { self.root.split_at_depth(self.prefix) } + + pub fn walk_with_behavior(self, behavior:impl Into) -> WalkTree { + WalkTree::with_prefix_and_behavior(self.root, self.prefix, behavior) + } +} + +#[derive(Clone, Debug)] +struct WalkProgram { + complete:Regex, + components:Vec, +} + +impl WalkProgram { + fn compile<'t, I>(tokens:I) -> Result, CompileError> + where + I: IntoIterator>, + I::IntoIter: Clone, { + let mut regexes = Vec::new(); + for component in token::components(tokens) { + if component.tokens().iter().any(|token| token.has_component_boundary()) { + // Stop at component boundaries, such as tree wildcards or any boundary within a + // group token. + break; + } + regexes.push(Glob::compile(component.tokens().iter().copied())?); + } + Ok(regexes) + } + + fn from_glob(glob:&Glob<'_>) -> Self { + WalkProgram { + complete:glob.program.clone(), + components:WalkProgram::compile(glob.tree.as_ref().tokens()) + .expect("failed to compile glob sub-expressions"), + } + } +} + +/// Describes iteration over matching files in a directory tree. +/// +/// A walker provides the paths walked by a [`Glob`] prior to iteration, most +/// notably the [root path][`GlobWalker::root_prefix_paths`], which may differ +/// from the directory passed to walking functions. When ready, it can be +/// converted into an iterator over matching files. +/// +/// See [`Glob::walker`]. +/// +/// [`Glob`]: crate::Glob +/// [`Glob::walker`]: crate::Glob::walker +/// [`GlobWalker::root_prefix_paths`]: crate::walk::GlobWalker::root_prefix_paths +#[derive(Clone, Debug)] +pub struct GlobWalker { + anchor:Anchor, + program:WalkProgram, +} + +impl GlobWalker { + /// Gets the root and prefix paths. + /// + /// The root path is the path to the walked directory tree. **This path may + /// differ from the directory passed to walking functions like + /// [`Glob::walk`]**, because it may incorporate an invariant path + /// prefix from the glob expression. + /// + /// The prefix path is the invariant path prefix of the glob expression. + /// This path may be empty and is always a suffix of the root path. + /// + /// The following table describes some example paths when using + /// [`Glob::walk`]. + /// + /// | Glob Expression | Directory | Root | Prefix | + /// |---------------------------|--------------|--------------|------------| + /// | `**/*.txt` | `/home/user` | `/home/user` | | + /// | `projects/**/src/**/*.rs` | `.` | `./projects` | `projects` | + /// | `/var/log/**/*.log` | `.` | `/var/log` | `/var/log` | + /// + /// See also [`Entry::root_relative_paths`]. + /// + /// [`Entry::root_relative_paths`]: crate::walk::Entry::root_relative_paths + /// [`Glob::walk`]: crate::Glob::walk + pub fn root_prefix_paths(&self) -> (&Path, &Path) { self.anchor.root_prefix_paths() } + + /// Converts a walker into an iterator over matching files in its directory + /// tree. + /// + /// See [`Glob::walk`]. + /// + /// [`Glob::walk`]: crate::Glob::walk + pub fn walk(self) -> impl 'static + FileIterator { + self.walk_with_behavior(WalkBehavior::default()) + } + + /// Converts a walker into an iterator over matching files in its directory + /// tree. + /// + /// See [`Glob::walk_with_behavior`]. + /// + /// [`Glob::walk_with_behavior`]: crate::Glob::walk_with_behavior + pub fn walk_with_behavior( + self, + behavior:impl Into, + ) -> impl 'static + FileIterator { + self.anchor + .walk_with_behavior(behavior) + .filter_map_tree(move |cancellation, separation| { + use itertools::{ + EitherOrBoth::{Both, Left, Right}, + Position::{First, Last, Middle, Only}, + }; + + let filtrate = match separation.filtrate() { + Some(filtrate) => { + match filtrate.transpose() { + Ok(filtrate) => filtrate, + Err(error) => { + return Separation::from(error.map(Err)); + }, + } + }, + // `Path::walk_with_behavior` yields no residue. + _ => unreachable!(), + }; + let entry = filtrate.as_ref(); + let (_, path) = entry.root_relative_paths(); + let depth = entry.depth().saturating_sub(1); + for (position, candidate) in path + .components() + .filter_map(|component| { + match component { + Component::Normal(component) => Some(CandidatePath::from(component)), + Component::Prefix(prefix) => { + Some(CandidatePath::from(prefix.as_os_str())) + }, + _ => None, + } + }) + .skip(depth) + .zip_longest(self.program.components.iter().skip(depth)) + .with_position() + { + match (position, candidate) { + (First | Middle, Both(candidate, program)) => { + if !program.is_match(candidate.as_ref()) { + // Do not walk directories that do not match the corresponding + // component program. + return filtrate.filter_tree(cancellation).into(); + } + }, + (Last | Only, Both(candidate, program)) => { + return if program.is_match(candidate.as_ref()) { + let candidate = CandidatePath::from(path); + if let Some(matched) = self + .program + .complete + .captures(candidate.as_ref()) + .map(MatchedText::from) + .map(MatchedText::into_owned) + { + filtrate.map(|entry| Ok(GlobEntry { entry, matched })).into() + } else { + filtrate.filter_node().into() + } + } else { + // Do not walk directories that do not match the corresponding + // component program. + filtrate.filter_tree(cancellation).into() + }; + }, + (_, Left(_candidate)) => { + let candidate = CandidatePath::from(path); + return if let Some(matched) = self + .program + .complete + .captures(candidate.as_ref()) + .map(MatchedText::from) + .map(MatchedText::into_owned) + { + filtrate.map(|entry| Ok(GlobEntry { entry, matched })).into() + } else { + filtrate.filter_node().into() + }; + }, + (_, Right(_program)) => { + return filtrate.filter_node().into(); + }, + } + } + // If the component loop is not entered, then check for a match. This may + // indicate that the `Glob` is empty and a single invariant path + // may be matched. + let candidate = CandidatePath::from(path); + if let Some(matched) = self + .program + .complete + .captures(candidate.as_ref()) + .map(MatchedText::from) + .map(MatchedText::into_owned) + { + return filtrate.map(|entry| Ok(GlobEntry { entry, matched })).into(); + } + filtrate.filter_node().into() + }) + } +} + +#[derive(Clone, Debug)] +enum FilterAnyProgram { + Empty, + Exhaustive(Regex), + Nonexhaustive(Regex), + Partitioned { exhaustive:Regex, nonexhaustive:Regex }, +} + +impl FilterAnyProgram { + fn compile<'t, I>(tokens:I) -> Result, BuildError> + where + I: IntoIterator, + I::Item: Pattern<'t>, + I::IntoIter: ExactSizeIterator, { + let tokens = tokens.into_iter(); + if 0 == tokens.len() { + Ok(None) + } else { + crate::any(tokens).map(|any| Some(any.program)) + } + } + + fn from_partitions<'t, I>(exhaustive:I, nonexhaustive:I) -> Result + where + I: IntoIterator, + I::Item: Pattern<'t>, + I::IntoIter: ExactSizeIterator, { + use FilterAnyProgram::{Empty, Exhaustive, Nonexhaustive, Partitioned}; + + // It is important to distinguish between empty _partitions_ and empty + // _expressions_ here. `FilterAnyProgram::compile` discards empty + // partitions. When matching against an empty path, an explicit empty + // _expression_ must match but an empty _partition_ must not (such + // a partition must never match anything). + Ok( + match ( + FilterAnyProgram::compile(exhaustive)?, + FilterAnyProgram::compile(nonexhaustive)?, + ) { + (Some(exhaustive), Some(nonexhaustive)) => { + Partitioned { exhaustive, nonexhaustive } + }, + (Some(exhaustive), None) => Exhaustive(exhaustive), + (None, Some(nonexhaustive)) => Nonexhaustive(nonexhaustive), + (None, None) => Empty, + }, + ) + } + + pub fn residue(&self, candidate:CandidatePath<'_>) -> Option { + use FilterAnyProgram::{Exhaustive, Nonexhaustive, Partitioned}; + + match self { + Exhaustive(ref exhaustive) | Partitioned { ref exhaustive, .. } + if exhaustive.is_match(candidate.as_ref()) => + { + Some(EntryResidue::Tree) + }, + Nonexhaustive(ref nonexhaustive) | Partitioned { ref nonexhaustive, .. } + if nonexhaustive.is_match(candidate.as_ref()) => + { + Some(EntryResidue::File) + }, + _ => None, + } + } +} + +/// Negated glob combinator that efficiently filters file entries against +/// patterns. +#[derive(Clone, Debug)] +pub struct FilterAny { + program:FilterAnyProgram, +} + +impl FilterAny { + /// Combines patterns into a `FilterAny`. + /// + /// This function accepts an [`IntoIterator`] with items that implement + /// [`Pattern`], such as [`Glob`] and `&str`. + /// + /// # Errors + /// + /// Returns an error if any of the inputs fail to build. If the inputs are a + /// compiled [`Program`] type such as [`Glob`], then this only occurs if + /// the compiled program is too large. + /// + /// [`Glob`]: crate::Glob + /// [`IntoIterator`]: std::iter::IntoIterator + /// [`Pattern`]: crate::Pattern + /// [`Program`]: crate::Program + pub fn any<'t, I>(patterns:I) -> Result + where + I: IntoIterator, + I::Item: Pattern<'t>, { + let (exhaustive, nonexhaustive) = patterns + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .map_err(Into::into)? + .into_iter() + .partition::, _>(|tree| token::is_exhaustive(tree.as_ref().tokens())); + Ok(FilterAny { program:FilterAnyProgram::from_partitions(exhaustive, nonexhaustive)? }) + } + + /// Gets the appropriate [`EntryResidue`] for the given [`Entry`]. + /// + /// Notably, this function returns [`EntryResidue::Tree`] if the [`Entry`] + /// matches an [exhaustive glob expression][`Program::is_exhaustive`], + /// such as `secret/**`. + /// + /// [`Entry`]: crate::walk::Entry + /// [`EntryResidue`]: crate::walk::EntryResidue + /// [`EntryResidue::Tree`]: crate::walk::EntryResidue::Tree + /// [`Program::is_exhaustive`]: crate::Program::is_exhaustive + pub fn residue(&self, entry:&dyn Entry) -> Option { + let candidate = CandidatePath::from(entry.root_relative_paths().1); + self.program.residue(candidate) + } +} + +/// Describes a file with a path matching a [`Glob`] in a directory tree. +/// +/// See [`Glob::walk`]. +/// +/// [`Glob`]: crate::Glob +/// [`Glob::walk`]: crate::Glob::walk +#[derive(Debug)] +pub struct GlobEntry { + entry:TreeEntry, + matched:MatchedText<'static>, +} + +impl GlobEntry { + /// Converts the entry to the relative [`CandidatePath`]. + /// + /// **This differs from [`Entry::path`] and [`Entry::into_path`], which are + /// native paths and typically include the root path.** The + /// [`CandidatePath`] is always relative to [the root + /// path][`Entry::root_relative_paths`]. + /// + /// [`CandidatePath`]: crate::CandidatePath + /// [`Entry::into_path`]: crate::walk::Entry::into_path + /// [`Entry::path`]: crate::walk::Entry::path + /// [`matched`]: crate::walk::GlobEntry::matched + pub fn to_candidate_path(&self) -> CandidatePath<'_> { self.matched.to_candidate_path() } + + /// Gets the matched text in the path of the file. + pub fn matched(&self) -> &MatchedText<'static> { &self.matched } +} + +impl Entry for GlobEntry { + fn into_path(self) -> PathBuf { self.entry.into_path() } + + fn path(&self) -> &Path { self.entry.path() } + + fn root_relative_paths(&self) -> (&Path, &Path) { self.entry.root_relative_paths() } + + fn file_type(&self) -> FileType { self.entry.file_type() } + + fn metadata(&self) -> Result { + self.entry.metadata().map_err(WalkError::from) + } + + // TODO: This needs some work and requires some explanation when applied to + // globs. + fn depth(&self) -> usize { self.entry.depth() } +} + +impl From for TreeEntry { + fn from(entry:GlobEntry) -> Self { entry.entry } +} diff --git a/crates/turborepo-wax/src/walk/mod.rs b/crates/turborepo-wax/Source/walk/mod.rs similarity index 100% rename from crates/turborepo-wax/src/walk/mod.rs rename to crates/turborepo-wax/Source/walk/mod.rs diff --git a/crates/turborepo-wax/src/capture.rs b/crates/turborepo-wax/src/capture.rs deleted file mode 100644 index 5315e83efac16..0000000000000 --- a/crates/turborepo-wax/src/capture.rs +++ /dev/null @@ -1,199 +0,0 @@ -use std::str; - -use regex::Captures as BorrowedText; - -use crate::CandidatePath; - -#[derive(Clone, Debug)] -struct OwnedText { - matched: String, - ranges: Vec>, -} - -impl OwnedText { - pub fn get(&self, index: usize) -> Option<&str> { - if index == 0 { - Some(self.matched.as_ref()) - } else { - self.ranges - .get(index - 1) - .and_then(|range| range.map(|range| &self.matched[range.0..range.1])) - } - } -} - -impl<'t> From> for OwnedText { - fn from(captures: BorrowedText<'t>) -> Self { - From::from(&captures) - } -} - -impl<'m, 't> From<&'m BorrowedText<'t>> for OwnedText { - fn from(captures: &'m BorrowedText<'t>) -> Self { - let matched = captures.get(0).unwrap().as_str().into(); - let ranges = captures - .iter() - .skip(1) - .map(|capture| capture.map(|capture| (capture.start(), capture.end()))) - .collect(); - OwnedText { matched, ranges } - } -} - -#[derive(Debug)] -enum MaybeOwnedText<'t> { - Borrowed(BorrowedText<'t>), - Owned(OwnedText), -} - -impl<'t> MaybeOwnedText<'t> { - fn into_owned(self) -> MaybeOwnedText<'static> { - match self { - MaybeOwnedText::Borrowed(borrowed) => OwnedText::from(borrowed).into(), - MaybeOwnedText::Owned(owned) => owned.into(), - } - } - - // This conversion may appear to operate in place. - #[must_use] - fn to_owned(&self) -> MaybeOwnedText<'static> { - match self { - MaybeOwnedText::Borrowed(ref borrowed) => OwnedText::from(borrowed).into(), - MaybeOwnedText::Owned(ref owned) => owned.clone().into(), - } - } -} - -impl<'t> From> for MaybeOwnedText<'t> { - fn from(captures: BorrowedText<'t>) -> Self { - MaybeOwnedText::Borrowed(captures) - } -} - -impl From for MaybeOwnedText<'static> { - fn from(captures: OwnedText) -> Self { - MaybeOwnedText::Owned(captures) - } -} - -/// Text that has been matched by a [`Program`] and its captures. -/// -/// To match a [`Glob`] or other [`Program`] against a [`CandidatePath`] and get -/// the matched text, use the [`Program::matched`] function. -/// -/// All [`Program`]s provide an implicit capture of the complete text of a -/// match. This implicit capture has index zero, and is exposed via the -/// [`complete`] function as well as the [`get`] function using index zero. -/// Capturing tokens are indexed starting at one, and can be used to -/// isolate more specific sub-text. -/// -/// # Examples -/// -/// Capturing tokens and matched text can be used to isolate sub-text in a -/// match. For example, the file name of a match can be extracted using an -/// alternative to group patterns. -/// -/// ```rust -/// use wax::{CandidatePath, Glob, Program}; -/// -/// let glob = Glob::new("src/**/{*.{go,rs}}").unwrap(); -/// let candidate = CandidatePath::from("src/graph/link.rs"); -/// let matched = glob.matched(&candidate).unwrap(); -/// -/// assert_eq!("link.rs", matched.get(2).unwrap()); -/// ``` -/// -/// [`CandidatePath`]: crate::CandidatePath -/// [`complete`]: crate::MatchedText::complete -/// [`get`]: crate::MatchedText::get -/// [`Glob`]: crate::Glob -/// [`Program`]: crate::Program -/// [`Program::matched`]: crate::Program::matched -#[derive(Debug)] -pub struct MatchedText<'t> { - inner: MaybeOwnedText<'t>, -} - -impl<'t> MatchedText<'t> { - /// Clones any borrowed data into an owning instance. - pub fn into_owned(self) -> MatchedText<'static> { - let MatchedText { inner } = self; - MatchedText { - inner: inner.into_owned(), - } - } - - /// Clones any borrowed data to an owning instance. - /// - /// This function is similar to [`into_owned`], but does not consume its - /// receiver. Due to a technical limitation, `MatchedText` cannot properly - /// implement [`Clone`], so this function is provided as a stop gap that - /// allows a distinct instance to be created that owns its data. - /// - /// [`Clone`]: std::clone::Clone - /// [`into_owned`]: crate::MatchedText::into_owned - // This conversion may appear to operate in place. - #[must_use] - pub fn to_owned(&self) -> MatchedText<'static> { - MatchedText { - inner: self.inner.to_owned(), - } - } - - /// Gets the complete text of a match. - /// - /// All [`Program`]s have an implicit capture of the complete text at index - /// zero. This function is therefore equivalent to unwrapping the output - /// of the [`get`] function with index zero. - /// - /// [`get`]: crate::MatchedText::get - /// [`Program`]: crate::Program - pub fn complete(&self) -> &str { - self.get(0).expect("match has no complete text") - } - - /// Gets the matched text of a capture at the given index. - /// - /// All [`Program`]s have an implicit capture of the complete text at index - /// zero. Capturing tokens are indexed from one, so any capturing - /// sub-expression will be indexed after the implicit complete text. For - /// example, the sub-expression `*` in the glob expression `*.txt` is at - /// index one and will exclude the suffix `.txt` in its matched text. - /// - /// Alternative and repetition patterns group their sub-globs into a single - /// capture, so it is not possible to isolate matched text from their - /// sub-globs. This can be used to explicitly group matched text, such - /// as isolating an entire matched file name using an expression like - /// `{*.{go,rs}}`. - /// - /// [`Program`]: crate::Program - pub fn get(&self, index: usize) -> Option<&str> { - match self.inner { - MaybeOwnedText::Borrowed(ref captures) => { - captures.get(index).map(|capture| capture.as_str()) - } - MaybeOwnedText::Owned(ref captures) => captures.get(index), - } - } - - pub fn to_candidate_path(&self) -> CandidatePath { - CandidatePath::from(self.complete()) - } -} - -// TODO: This probably shouldn't be part of the public API. -impl<'t> From> for MatchedText<'t> { - fn from(captures: BorrowedText<'t>) -> Self { - MatchedText { - inner: captures.into(), - } - } -} - -impl From for MatchedText<'static> { - fn from(captures: OwnedText) -> Self { - MatchedText { - inner: captures.into(), - } - } -} diff --git a/crates/turborepo-wax/src/diagnostics/miette.rs b/crates/turborepo-wax/src/diagnostics/miette.rs deleted file mode 100644 index 7cd522d7e1e23..0000000000000 --- a/crates/turborepo-wax/src/diagnostics/miette.rs +++ /dev/null @@ -1,167 +0,0 @@ -#![cfg(feature = "miette")] - -use std::borrow::Cow; - -use miette::{Diagnostic, SourceSpan}; -use tardar::{ - BoxedDiagnostic, DiagnosticResult, DiagnosticResultExt as _, IteratorExt as _, ResultExt as _, -}; -use thiserror::Error; - -use crate::{ - diagnostics::SpanExt as _, - rule, - token::{self, TokenKind, TokenTree, Tokenized}, - Checked, Glob, -}; - -/// APIs for diagnosing globs. -impl<'t> Glob<'t> { - /// Constructs a [`Glob`] from a glob expression with diagnostics. - /// - /// This function is the same as [`Glob::new`], but additionally returns - /// detailed diagnostics on both success and failure. - /// - /// See [`Glob::diagnose`]. - /// - /// # Examples - /// - /// ```rust - /// use tardar::DiagnosticResultExt as _; - /// use wax::Glob; - /// - /// let result = Glob::diagnosed("(?i)readme.{md,mkd,markdown}"); - /// for diagnostic in result.diagnostics() { - /// eprintln!("{}", diagnostic); - /// } - /// if let Some(glob) = result.ok_output() { /* ... */ } - /// ``` - /// - /// [`Glob`]: crate::Glob - /// [`Glob::diagnose`]: crate::Glob::diagnose - /// [`Glob::new`]: crate::Glob::new - pub fn diagnosed(expression: &'t str) -> DiagnosticResult<'t, Self> { - parse_and_diagnose(expression).and_then_diagnose(|tree| { - Glob::compile(tree.as_ref().tokens()) - .into_error_diagnostic() - .map_output(|program| Glob { tree, program }) - }) - } - - /// Gets **non-error** [`Diagnostic`]s. - /// - /// This function requires a receiving [`Glob`] and so does not report - /// error-level [`Diagnostic`]s. It can be used to get non-error - /// diagnostics after constructing or [partitioning][`Glob::partition`] - /// a [`Glob`]. - /// - /// See [`Glob::diagnosed`]. - /// - /// [`Diagnostic`]: miette::Diagnostic - /// [`Glob`]: crate::Glob - /// [`Glob::diagnosed`]: crate::Glob::diagnosed - /// [`Glob::partition`]: crate::Glob::partition - pub fn diagnose(&self) -> impl Iterator> { - diagnose(self.tree.as_ref()) - } -} - -#[derive(Clone, Debug, Diagnostic, Error)] -#[diagnostic(code(wax::glob::semantic_literal), severity(warning))] -#[error("`{literal}` has been interpreted as a literal with no semantics")] -pub struct SemanticLiteralWarning<'t> { - #[source_code] - expression: Cow<'t, str>, - literal: Cow<'t, str>, - #[label("here")] - span: SourceSpan, -} - -#[derive(Clone, Debug, Diagnostic, Error)] -#[diagnostic(code(wax::glob::terminating_separator), severity(warning))] -#[error("terminating separator may discard matches")] -pub struct TerminatingSeparatorWarning<'t> { - #[source_code] - expression: Cow<'t, str>, - #[label("here")] - span: SourceSpan, -} - -fn parse_and_diagnose(expression: &str) -> DiagnosticResult> { - token::parse(expression) - .into_error_diagnostic() - .and_then_diagnose(|tokenized| rule::check(tokenized).into_error_diagnostic()) - .and_then_diagnose(|checked| { - // TODO: This should accept `&Checked`. - diagnose(checked.as_ref()) - .into_non_error_diagnostic() - .map_output(|_| checked) - }) -} - -fn diagnose<'i, 't>( - tokenized: &'i Tokenized<'t>, -) -> impl 'i + Iterator> { - None.into_iter() - .chain( - token::literals(tokenized.tokens()) - .filter(|(_, literal)| literal.is_semantic_literal()) - .map(|(component, literal)| { - Box::new(SemanticLiteralWarning { - expression: tokenized.expression().clone(), - literal: literal.text().clone(), - span: component - .tokens() - .iter() - .map(|token| *token.annotation()) - .reduce(|left, right| left.union(&right)) - .map(SourceSpan::from) - .expect("no tokens in component"), - }) as BoxedDiagnostic - }), - ) - .chain( - tokenized - .tokens() - .last() - .into_iter() - .filter(|token| matches!(token.kind(), TokenKind::Separator(_))) - .map(|token| { - Box::new(TerminatingSeparatorWarning { - expression: tokenized.expression().clone(), - span: (*token.annotation()).into(), - }) as BoxedDiagnostic - }), - ) -} - -#[cfg(test)] -mod tests { - use crate::Glob; - - // It is non-trivial to downcast `&dyn Diagnostic`, so diagnostics are - // identified in tests by their code. - const CODE_SEMANTIC_LITERAL: &str = "wax::glob::semantic_literal"; - const CODE_TERMINATING_SEPARATOR: &str = "wax::glob::terminating_separator"; - - #[cfg(any(unix, windows))] - #[test] - fn diagnose_glob_semantic_literal_warning() { - let glob = Glob::new("../foo").unwrap(); - let diagnostics: Vec<_> = glob.diagnose().collect(); - - assert!(diagnostics.iter().any(|diagnostic| diagnostic - .code() - .map_or(false, |code| code.to_string() == CODE_SEMANTIC_LITERAL))); - } - - #[test] - fn diagnose_glob_terminating_separator_warning() { - let glob = Glob::new("**/foo/").unwrap(); - let diagnostics: Vec<_> = glob.diagnose().collect(); - - assert!(diagnostics.iter().any(|diagnostic| diagnostic - .code() - .map_or(false, |code| code.to_string() == CODE_TERMINATING_SEPARATOR))); - } -} diff --git a/crates/turborepo-wax/src/diagnostics/mod.rs b/crates/turborepo-wax/src/diagnostics/mod.rs deleted file mode 100644 index 4a779c0cfaf9b..0000000000000 --- a/crates/turborepo-wax/src/diagnostics/mod.rs +++ /dev/null @@ -1,159 +0,0 @@ -mod miette; - -use std::{ - cmp, - fmt::{self, Display, Formatter}, -}; - -#[cfg(feature = "miette")] -use ::miette::LabeledSpan; - -/// Location and length of a token within a glob expression. -/// -/// Spans are encoded as a tuple of `usize`s, where the first element is the -/// location or position and the second element is the length. Both position and -/// length are measured in bytes and **not** code points, graphemes, etc. -/// -/// # Examples -/// -/// Spans can be used to isolate sub-expressions. -/// -/// ```rust -/// use wax::Glob; -/// -/// let expression = "**/*.txt"; -/// let glob = Glob::new(expression).unwrap(); -/// for token in glob.captures() { -/// let (start, n) = token.span(); -/// println!("capturing sub-expression: {}", &expression[start..][..n]); -/// } -/// ``` -pub type Span = (usize, usize); - -pub trait SpanExt { - fn union(&self, other: &Self) -> Self; -} - -impl SpanExt for Span { - fn union(&self, other: &Self) -> Self { - let start = cmp::min(self.0, other.0); - let end = cmp::max(self.0 + self.1, other.0 + other.1); - (start, end - start) - } -} - -/// Error associated with a [`Span`] within a glob expression. -/// -/// Located errors describe specific instances of an error within a glob -/// expression. Types that implement this trait provide a location within a glob -/// expression via the [`LocatedError::span`] function as well as a description -/// via the [`Display`] trait. See [`BuildError::locations`]. -/// -/// [`BuildError::locations`]: crate::BuildError::locations -/// [`Display`]: std::fmt::Display -/// [`LocatedError::span`]: crate::LocatedError::span -/// [`Span`]: crate::Span -pub trait LocatedError: Display { - /// Gets the span within the glob expression with which the error is - /// associated. - fn span(&self) -> Span; -} - -#[derive(Clone, Copy, Debug)] -pub struct CompositeSpan { - label: &'static str, - kind: CompositeSpanKind, -} - -impl CompositeSpan { - pub fn spanned(label: &'static str, span: Span) -> Self { - CompositeSpan { - label, - kind: CompositeSpanKind::Span(span), - } - } - - pub fn correlated(label: &'static str, span: Span, correlated: CorrelatedSpan) -> Self { - CompositeSpan { - label, - kind: CompositeSpanKind::Correlated { span, correlated }, - } - } - - #[cfg(feature = "miette")] - pub fn labels(&self) -> Vec { - let label = Some(self.label.to_string()); - match self.kind { - CompositeSpanKind::Span(ref span) => vec![LabeledSpan::new_with_span(label, *span)], - CompositeSpanKind::Correlated { - ref span, - ref correlated, - } => Some(LabeledSpan::new_with_span(label, *span)) - .into_iter() - .chain(correlated.labels()) - .collect(), - } - } -} - -impl Display for CompositeSpan { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.label) - } -} - -impl LocatedError for CompositeSpan { - fn span(&self) -> Span { - match self.kind { - CompositeSpanKind::Span(ref span) | CompositeSpanKind::Correlated { ref span, .. } => { - *span - } - } - } -} - -#[derive(Clone, Copy, Debug)] -enum CompositeSpanKind { - Span(Span), - Correlated { - span: Span, - #[cfg_attr(not(feature = "miette"), allow(dead_code))] - correlated: CorrelatedSpan, - }, -} - -#[derive(Clone, Copy, Debug)] -pub enum CorrelatedSpan { - Contiguous(Span), - Split(Span, Span), -} - -impl CorrelatedSpan { - pub fn split_some(left: Option, right: Span) -> Self { - if let Some(left) = left { - CorrelatedSpan::Split(left, right) - } else { - CorrelatedSpan::Contiguous(right) - } - } - - #[cfg(feature = "miette")] - pub fn labels(&self) -> Vec { - let label = Some("here".to_string()); - match self { - CorrelatedSpan::Contiguous(ref span) => { - vec![LabeledSpan::new_with_span(label, *span)] - } - CorrelatedSpan::Split(ref left, ref right) => vec![ - LabeledSpan::new_with_span(label.clone(), *left), - LabeledSpan::new_with_span(label, *right), - ], - } - } -} - -impl From for CorrelatedSpan { - fn from(span: Span) -> Self { - CorrelatedSpan::Contiguous(span) - } -} diff --git a/crates/turborepo-wax/src/encode.rs b/crates/turborepo-wax/src/encode.rs deleted file mode 100644 index 0d81b8fcd00ae..0000000000000 --- a/crates/turborepo-wax/src/encode.rs +++ /dev/null @@ -1,327 +0,0 @@ -use std::borrow::{Borrow, Cow}; -#[cfg(feature = "miette")] -use std::fmt::Display; - -use const_format::formatcp; -use itertools::{Itertools as _, Position}; -#[cfg(feature = "miette")] -use miette::Diagnostic; -use regex::{Error as RegexError, Regex}; -use thiserror::Error; - -use crate::token::Token; - -/// A regular expression that never matches. -/// -/// This expression is formed from a character class that intersects completely -/// disjoint characters. Unlike an empty regular expression, which always -/// matches, this yields an empty character class, which never matches (even -/// against empty strings). -const NEVER_EXPRESSION: &str = "[a&&b]"; - -#[cfg(windows)] -const SEPARATOR_CLASS_EXPRESSION: &str = "/\\\\"; -#[cfg(unix)] -const SEPARATOR_CLASS_EXPRESSION: &str = "/"; - -// This only encodes the platform's main separator, so any additional separators -// will be missed. It may be better to have explicit platform support and invoke -// `compile_error!` on unsupported platforms, as this could cause very aberrant -// behavior. Then again, it seems that platforms using more than one separator -// are rare. GS/OS, OS/2, and Windows are likely the best known examples -// and of those only Windows is a supported Rust target at the time of writing -// (and is already supported by Wax). -#[cfg(not(any(windows, unix)))] -const SEPARATOR_CLASS_EXPRESSION: &str = main_separator_class_expression(); - -#[cfg(not(any(windows, unix)))] -const fn main_separator_class_expression() -> &'static str { - use std::path::MAIN_SEPARATOR; - - // TODO: This is based upon `regex_syntax::is_meta_character`, but that function - // is not `const`. Perhaps that can be changed upstream. - const fn escape(x: char) -> &'static str { - match x { - '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' - | '#' | '&' | '-' | '~' => "\\", - _ => "", - } - } - - formatcp!("{0}{1}", escape(MAIN_SEPARATOR), MAIN_SEPARATOR) -} - -macro_rules! sepexpr { - ($fmt:expr) => { - formatcp!($fmt, formatcp!("[{0}]", SEPARATOR_CLASS_EXPRESSION)) - }; -} - -macro_rules! nsepexpr { - ($fmt:expr) => { - formatcp!($fmt, formatcp!("[^{0}]", SEPARATOR_CLASS_EXPRESSION)) - }; -} - -/// Describes errors that occur when compiling a glob expression. -/// -/// **This error only occurs when the size of the compiled program is too -/// large.** All other compilation errors are considered internal bugs and will -/// panic. -#[derive(Clone, Debug, Error)] -#[error("failed to compile glob: {kind}")] -pub struct CompileError { - kind: CompileErrorKind, -} - -#[derive(Clone, Copy, Debug, Error)] -#[non_exhaustive] -enum CompileErrorKind { - #[error("oversized program")] - OversizedProgram, -} - -#[cfg(feature = "miette")] -#[cfg_attr(docsrs, doc(cfg(feature = "miette")))] -impl Diagnostic for CompileError { - fn code<'a>(&'a self) -> Option> { - Some(Box::new(String::from(match self.kind { - CompileErrorKind::OversizedProgram => "wax::glob::oversized_program", - }))) - } -} - -trait Escaped { - fn escaped(&self) -> String; -} - -impl Escaped for char { - fn escaped(&self) -> String { - regex::escape(&self.to_string()) - } -} - -impl Escaped for str { - fn escaped(&self) -> String { - regex::escape(self) - } -} - -#[derive(Clone, Copy, Debug)] -enum Grouping { - Capture, - NonCapture, -} - -impl Grouping { - pub fn push_str(&self, pattern: &mut String, encoding: &str) { - self.push_with(pattern, || encoding.into()); - } - - pub fn push_with<'p, F>(&self, pattern: &mut String, f: F) - where - F: Fn() -> Cow<'p, str>, - { - match self { - Grouping::Capture => pattern.push('('), - Grouping::NonCapture => pattern.push_str("(?:"), - } - pattern.push_str(f().as_ref()); - pattern.push(')'); - } -} - -pub fn case_folded_eq(left: &str, right: &str) -> bool { - let regex = Regex::new(&format!("(?i){}", regex::escape(left))) - .expect("failed to compile literal regular expression"); - if let Some(matched) = regex.find(right) { - matched.start() == 0 && matched.end() == right.len() - } else { - false - } -} - -pub fn compile<'t, A, T>(tokens: impl IntoIterator) -> Result -where - T: Borrow>, -{ - let mut pattern = String::new(); - pattern.push('^'); - encode(Grouping::Capture, None, &mut pattern, tokens); - pattern.push('$'); - Regex::new(&pattern).map_err(|error| match error { - RegexError::CompiledTooBig(_) => CompileError { - kind: CompileErrorKind::OversizedProgram, - }, - _ => panic!("failed to compile glob"), - }) -} - -// TODO: Some versions of `const_format` in `^0.2.0` fail this lint in -// `formatcp`. See https://github.com/rodrimati1992/const_format_crates/issues/38 -#[allow(clippy::double_parens)] -fn encode<'t, A, T>( - grouping: Grouping, - superposition: Option, - pattern: &mut String, - tokens: impl IntoIterator, -) where - T: Borrow>, -{ - use itertools::Position::{First, Last, Middle, Only}; - - use crate::token::{ - Archetype::{Character, Range}, - Evaluation::{Eager, Lazy}, - TokenKind::{Alternative, Class, Literal, Repetition, Separator, Wildcard}, - Wildcard::{One, Tree, ZeroOrMore}, - }; - - fn encode_intermediate_tree(grouping: Grouping, pattern: &mut String) { - pattern.push_str(sepexpr!("(?:{0}|{0}")); - grouping.push_str(pattern, sepexpr!(".*{0}")); - pattern.push(')'); - } - - // TODO: Use `Grouping` everywhere a group is encoded. For invariant groups that - // ignore `grouping`, construct a local `Grouping` instead. - for (position, token) in tokens.into_iter().with_position() { - match (position, token.borrow().kind()) { - (_, Literal(literal)) => { - // TODO: Only encode changes to casing flags. - // TODO: Should Unicode support also be toggled by casing flags? - if literal.is_case_insensitive() { - pattern.push_str("(?i)"); - } else { - pattern.push_str("(?-i)"); - } - pattern.push_str(&literal.text().escaped()); - } - (_, Separator(_)) => pattern.push_str(sepexpr!("{0}")), - (position, Alternative(alternative)) => { - let encodings: Vec<_> = alternative - .branches() - .iter() - .map(|tokens| { - let mut pattern = String::new(); - pattern.push_str("(?:"); - encode( - Grouping::NonCapture, - superposition.or(Some(position)), - &mut pattern, - tokens.iter(), - ); - pattern.push(')'); - pattern - }) - .collect(); - grouping.push_str(pattern, &encodings.join("|")); - } - (position, Repetition(repetition)) => { - let encoding = { - let (lower, upper) = repetition.bounds(); - let mut pattern = String::new(); - pattern.push_str("(?:"); - encode( - Grouping::NonCapture, - superposition.or(Some(position)), - &mut pattern, - repetition.tokens().iter(), - ); - pattern.push_str(&if let Some(upper) = upper { - format!("){{{},{}}}", lower, upper) - } else { - format!("){{{},}}", lower) - }); - pattern - }; - grouping.push_str(pattern, &encoding); - } - (_, Class(class)) => { - grouping.push_with(pattern, || { - use crate::token::Class as ClassToken; - - fn encode_class_archetypes(class: &ClassToken, pattern: &mut String) { - for archetype in class.archetypes() { - match archetype { - Character(literal) => pattern.push_str(&literal.escaped()), - Range(left, right) => { - pattern.push_str(&left.escaped()); - pattern.push('-'); - pattern.push_str(&right.escaped()); - } - } - } - } - - let mut pattern = String::new(); - pattern.push('['); - if class.is_negated() { - pattern.push('^'); - encode_class_archetypes(class, &mut pattern); - pattern.push_str(SEPARATOR_CLASS_EXPRESSION); - } else { - encode_class_archetypes(class, &mut pattern); - pattern.push_str(nsepexpr!("&&{0}")); - } - pattern.push(']'); - // TODO: The compiled `Regex` is discarded. Is there a way to check the - // correctness of the expression but do less work (i.e., don't build a - // complete `Regex`)? - // Compile the character class sub-expression. This may fail if the subtraction - // of the separator pattern yields an empty character class (meaning that the - // glob expression matches only separator characters on the target platform). - if Regex::new(&pattern).is_ok() { - pattern.into() - } else { - // If compilation fails, then use `NEVER_EXPRESSION`, which matches - // nothing. - NEVER_EXPRESSION.into() - } - }); - } - (_, Wildcard(One)) => grouping.push_str(pattern, nsepexpr!("{0}")), - (_, Wildcard(ZeroOrMore(Eager))) => grouping.push_str(pattern, nsepexpr!("{0}*")), - (_, Wildcard(ZeroOrMore(Lazy))) => grouping.push_str(pattern, nsepexpr!("{0}*?")), - (First, Wildcard(Tree { has_root })) => { - if let Some(Middle | Last) = superposition { - encode_intermediate_tree(grouping, pattern); - } else if *has_root { - grouping.push_str(pattern, sepexpr!("{0}.*{0}?")); - } else { - pattern.push_str(sepexpr!("(?:{0}?|")); - grouping.push_str(pattern, sepexpr!(".*{0}")); - pattern.push(')'); - } - } - (Middle, Wildcard(Tree { .. })) => { - encode_intermediate_tree(grouping, pattern); - } - (Last, Wildcard(Tree { .. })) => { - if let Some(First | Middle) = superposition { - encode_intermediate_tree(grouping, pattern); - } else { - pattern.push_str(sepexpr!("(?:{0}?|{0}")); - grouping.push_str(pattern, ".*"); - pattern.push(')'); - } - } - (Only, Wildcard(Tree { .. })) => grouping.push_str(pattern, ".*"), - } - } -} - -#[cfg(test)] -mod tests { - use crate::encode; - - #[test] - fn case_folded_eq() { - assert!(encode::case_folded_eq("a", "a")); - assert!(encode::case_folded_eq("a", "A")); - - assert!(!encode::case_folded_eq("a", "b")); - assert!(!encode::case_folded_eq("aa", "a")); - assert!(!encode::case_folded_eq("a", "aa")); - } -} diff --git a/crates/turborepo-wax/src/lib.rs b/crates/turborepo-wax/src/lib.rs deleted file mode 100644 index f231d2b962bca..0000000000000 --- a/crates/turborepo-wax/src/lib.rs +++ /dev/null @@ -1,1981 +0,0 @@ -//! Wax provides opinionated and portable globs that can be matched against file -//! paths and directory trees. Globs use a familiar syntax and support -//! expressive features with semantics that emphasize component boundaries. -//! -//! See the [repository documentation](https://github.com/olson-sean-k/wax/blob/master/README.md) -//! for details about glob expressions and patterns. - -#![cfg_attr(docsrs, feature(doc_cfg))] -#![doc( - html_favicon_url = "https://raw.githubusercontent.com/olson-sean-k/wax/master/doc/wax-favicon.svg?sanitize=true" -)] -#![doc( - html_logo_url = "https://raw.githubusercontent.com/olson-sean-k/wax/master/doc/wax.svg?sanitize=true" -)] -#![allow(clippy::all)] -#![deny( - clippy::cast_lossless, - clippy::checked_conversions, - clippy::cloned_instead_of_copied, - clippy::explicit_into_iter_loop, - clippy::filter_map_next, - clippy::flat_map_option, - clippy::from_iter_instead_of_collect, - clippy::if_not_else, - clippy::manual_ok_or, - clippy::map_unwrap_or, - clippy::match_same_arms, - clippy::redundant_closure_for_method_calls, - clippy::redundant_else, - clippy::unreadable_literal, - clippy::unused_self -)] - -mod capture; -mod diagnostics; -mod encode; -mod rule; -mod token; -pub mod walk; - -/// Re-exports of commonly used items. -/// -/// This module anonymously re-exports traits for matching [`Program`]s against -/// file paths and directory trees. A glob import of this module can be used -/// instead of individual imports of these traits. -/// -/// # Examples -/// -/// ```rust,no_run,ignore -/// use wax::prelude::*; -/// use wax::Glob; -/// -/// // This code requires the `Entry` and `FileIterator` traits. -/// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); -/// for entry in glob.walk("textures").not(["**/.*/**"]).unwrap().flatten() { -/// println!("JPEG: {:?}", entry.path()); -/// } -/// ``` -pub mod prelude { - #[cfg(feature = "walk")] - pub use crate::walk::{Entry as _, FileIterator as _, PathExt as _}; - pub use crate::{LocatedError as _, Program as _}; -} - -use std::{ - borrow::{Borrow, Cow}, - convert::Infallible, - ffi::OsStr, - fmt::{self, Debug, Display, Formatter}, - path::{Path, PathBuf}, - str::{self, FromStr}, -}; - -#[cfg(feature = "miette")] -use miette::Diagnostic; -use regex::Regex; -use thiserror::Error; - -#[cfg(feature = "walk")] -use crate::walk::WalkError; -pub use crate::{ - capture::MatchedText, - diagnostics::{LocatedError, Span}, -}; -use crate::{ - encode::CompileError, - rule::{Checked, RuleError}, - token::{InvariantText, ParseError, Token, TokenTree, Tokenized}, -}; - -#[cfg(windows)] -const PATHS_ARE_CASE_INSENSITIVE: bool = true; -#[cfg(not(windows))] -const PATHS_ARE_CASE_INSENSITIVE: bool = false; - -trait CharExt: Sized { - /// Returns `true` if the character (code point) has casing. - fn has_casing(self) -> bool; -} - -impl CharExt for char { - fn has_casing(self) -> bool { - self.is_lowercase() != self.is_uppercase() - } -} - -trait StrExt { - /// Returns `true` if any characters in the string have casing. - fn has_casing(&self) -> bool; -} - -impl StrExt for str { - fn has_casing(&self) -> bool { - self.chars().any(CharExt::has_casing) - } -} - -/// Token that captures matched text in a glob expression. -/// -/// # Examples -/// -/// `CapturingToken`s can be used to isolate sub-expressions. -/// -/// ```rust -/// use wax::Glob; -/// -/// let expression = "**/*.txt"; -/// let glob = Glob::new(expression).unwrap(); -/// for token in glob.captures() { -/// let (start, n) = token.span(); -/// println!("capturing sub-expression: {}", &expression[start..][..n]); -/// } -/// ``` -#[derive(Clone, Copy, Debug)] -pub struct CapturingToken { - index: usize, - span: Span, -} - -impl CapturingToken { - /// Gets the index of the capture. - /// - /// Captures are one-indexed and the index zero always represents the - /// implicit capture of the complete match, so the index of - /// `CapturingToken`s is always one or greater. See [`MatchedText`]. - /// - /// [`MatchedText`]: crate::MatchedText - pub fn index(&self) -> usize { - self.index - } - - /// Gets the span of the token's sub-expression. - pub fn span(&self) -> Span { - self.span - } -} - -// This type is similar to `token::Variance>`, but is -// simplified for the public API. Invariant text is always expressed as a path -// and no variant bounds are provided. -/// Variance of a [`Program`]. -/// -/// The variance of a pattern describes the kinds of paths it can match with -/// respect to the platform file system APIs. [`Program`]s are either variant or -/// invariant. -/// -/// An invariant [`Program`] can be represented and completely described by an -/// equivalent path using the platform's file system APIs. For example, the glob -/// expression `path/to/file.txt` resolves identically to the paths -/// `path/to/file.txt` and `path\to\file.txt` on Unix and Windows, respectively. -/// -/// A variant [`Program`] resolves differently than any particular path used -/// with the platform's file system APIs. Such an expression cannot be -/// represented by a single path. This is typically because the expression -/// matches multiple texts using a regular pattern, such as in the glob -/// expression `**/*.rs`. -/// -/// [`Program`]: crate::Program -/// [`Variance`]: crate::Variance -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub enum Variance { - /// A [`Program`] is invariant and equivalent to a path. - /// - /// Some non-literal expressions may be invariant, such as in the expression - /// `path/[t][o]/{file,file}.txt`, which is invariant on Unix (but not on - /// Windows, because the character class expressions do not match with - /// case folding). - /// - /// [`Program`]: crate::Program - Invariant( - /// An equivalent path that completely describes the invariant - /// [`Program`] with respect to platform file system APIs. - /// - /// [`Program`]: crate::Program - PathBuf, - ), - /// A [`Program`] is variant and cannot be completely described by a path. - /// - /// Variant expressions may be formed from literals or other **seemingly** - /// invariant expressions. For example, the variance of literals - /// considers the case sensitivity of the platform's file system APIs, - /// so the expression `(?i)path/to/file.txt` is variant on Unix - /// but not on Windows. Similarly, the expression `path/[t][o]/file.txt` is - /// variant on Windows but not on Unix. - /// - /// [`Program`]: crate::Program - Variant, -} - -impl Variance { - /// Gets the equivalent native path if invariant. - /// - /// Returns `None` if variant. - pub fn path(&self) -> Option<&Path> { - match self { - Variance::Invariant(ref path) => Some(path), - Variance::Variant => None, - } - } - - /// Returns `true` if invariant. - pub fn is_invariant(&self) -> bool { - matches!(self, Variance::Invariant(_)) - } - - /// Returns `true` if variant. - pub fn is_variant(&self) -> bool { - matches!(self, Variance::Variant) - } -} - -impl From>> for Variance { - fn from(variance: token::Variance>) -> Self { - match variance { - token::Variance::Invariant(text) => { - Variance::Invariant(PathBuf::from(text.to_string().into_owned())) - } - token::Variance::Variant(_) => Variance::Variant, - } - } -} - -/// A compiled glob expression that can be inspected and matched against paths. -/// -/// Matching is a logical operation and does **not** interact with a file -/// system. To handle path operations, use [`Path`] and/or [`PathBuf`] and their -/// associated functions. See [`Glob::partition`] for more about globs and path -/// operations. -/// -/// [`Glob::partition`]: crate::Glob::partition -/// [`Path`]: std::path::Path -/// [`PathBuf`]: std::path::PathBuf -pub trait Program<'t>: Pattern<'t, Error = Infallible> { - /// Returns `true` if a path matches the pattern. - /// - /// The given path must be convertible into a [`CandidatePath`]. - /// - /// [`CandidatePath`]: crate::CandidatePath - fn is_match<'p>(&self, path: impl Into>) -> bool; - - /// Gets [matched text][`MatchedText`] in a [`CandidatePath`]. - /// - /// Returns `None` if the [`CandidatePath`] does not match the pattern. - /// - /// [`CandidatePath`]: crate::CandidatePath - /// [`MatchedText`]: crate::MatchedText - fn matched<'p>(&self, path: &'p CandidatePath<'_>) -> Option>; - - /// Gets the variance of the pattern. - /// - /// The variance of a pattern describes the kinds of paths it can match with - /// respect to the platform file system APIs. - fn variance(&self) -> Variance; - - /// Returns `true` if the pattern is exhaustive. - /// - /// A glob expression is exhaustive if its terminating component matches any - /// and all sub-trees, such as in the expressions `/home/**` and - /// `local/</>*`. - fn is_exhaustive(&self) -> bool; -} - -/// A glob expression representation that can be incorporated into a combinator. -/// -/// This trait is implemented by types that can be (fallibly) converted into a -/// [`Program`] and incorporated into a combinator. See [`any`]. -/// -/// [`any`]: crate::any -/// [`Program`]: crate::Program -pub trait Pattern<'t>: - TryInto, Error = >::Error> -{ - type Tokens: TokenTree<'t>; - type Error: Into; -} - -impl<'t> Pattern<'t> for &'t str { - type Tokens = Tokenized<'t>; - type Error = BuildError; -} - -/// General errors concerning [`Program`]s. -/// -/// This is the most general error and each of its variants exposes a particular -/// error type that describes the details of its associated error condition. -/// This error is not used in any Wax APIs directly, but can be used to -/// encapsulate the more specific errors that are. -/// -/// # Examples -/// -/// To encapsulate different errors in the Wax API behind a function, convert -/// them into a `GlobError` via `?`. -/// -/// ```rust,no_run,ignore -/// use std::path::PathBuf; -/// use wax::{Glob, GlobError}; -/// -/// fn read_all(directory: impl Into) -> Result, GlobError> { -/// let mut data = Vec::new(); -/// let glob = Glob::new("**/*.data.bin")?; -/// for entry in glob.walk(directory) { -/// let entry = entry?; -/// // ... -/// } -/// Ok(data) -/// } -/// ``` -/// -/// [`Program`]: crate::Program -#[cfg_attr(feature = "miette", derive(Diagnostic))] -#[derive(Debug, Error)] -#[error(transparent)] -pub enum GlobError { - #[cfg_attr(feature = "miette", diagnostic(transparent))] - Build(BuildError), - #[cfg(feature = "walk")] - #[cfg_attr(docsrs, doc(cfg(feature = "walk")))] - #[cfg_attr(feature = "miette", diagnostic(code = "wax::glob::walk"))] - Walk(WalkError), -} - -impl From for GlobError { - fn from(error: BuildError) -> Self { - GlobError::Build(error) - } -} - -#[cfg(feature = "walk")] -impl From for GlobError { - fn from(error: WalkError) -> Self { - GlobError::Walk(error) - } -} - -// TODO: `Diagnostic` is implemented with macros for brevity and to ensure -// complete coverage of features. However, this means that documentation -// does not annotate the implementation with a feature flag requirement. -// If possible, perhaps in a later version of Rust, close this gap. -/// Describes errors that occur when building a [`Program`] from a glob -/// expression. -/// -/// Glob expressions may fail to build if they cannot be parsed, violate rules, -/// or cannot be compiled. Parsing errors occur when a glob expression has -/// invalid syntax. Programs must also follow rules as described in the -/// [repository documentation](https://github.com/olson-sean-k/wax/blob/master/README.md), which are designed -/// to avoid nonsense expressions and ambiguity. Lastly, compilation errors -/// occur **only if the size of the compiled program is too large** (all other -/// compilation errors are considered internal bugs and will panic). -/// -/// When the `miette` feature is enabled, this and other error types implement -/// the [`Diagnostic`] trait. Due to a technical limitation, this may not be -/// properly annotated in API documentation. -/// -/// [`Diagnostic`]: miette::Diagnostic -/// [`Program`]: crate::Program -#[cfg_attr(feature = "miette", derive(Diagnostic))] -#[cfg_attr(feature = "miette", diagnostic(transparent))] -#[derive(Debug, Error)] -#[error(transparent)] -pub struct BuildError { - kind: BuildErrorKind, -} - -impl BuildError { - /// Gets [`LocatedError`]s detailing the errors within a glob expression. - /// - /// This function returns an [`Iterator`] over the [`LocatedError`]s that - /// detail where and why an error occurred when the error has associated - /// [`Span`]s within a glob expression. For errors with no such - /// associated information, the [`Iterator`] yields no items, such as - /// compilation errors. - /// - /// # Examples - /// - /// [`LocatedError`]s can be used to provide information to users about - /// which parts of a glob expression are associated with an error. - /// - /// ```rust - /// use wax::Glob; - /// - /// // This glob expression violates rules. The error handling code prints details about the - /// // alternative where the violation occurred. - /// let expression = "**/{foo,**/bar,baz}"; - /// match Glob::new(expression) { - /// Ok(glob) => { - /// // ... - /// }, - /// Err(error) => { - /// eprintln!("{}", error); - /// for error in error.locations() { - /// let (start, n) = error.span(); - /// let fragment = &expression[start..][..n]; - /// eprintln!("in sub-expression `{}`: {}", fragment, error); - /// } - /// }, - /// } - /// ``` - /// - /// [`Glob`]: crate::Glob - /// [`Glob::partition`]: crate::Glob::partition - /// [`Iterator`]: std::iter::Iterator - /// [`LocatedError`]: crate::LocatedError - /// [`Span`]: crate::Span - pub fn locations(&self) -> impl Iterator { - let locations: Vec<_> = match self.kind { - BuildErrorKind::Parse(ref error) => error - .locations() - .iter() - .map(|location| location as &dyn LocatedError) - .collect(), - BuildErrorKind::Rule(ref error) => error - .locations() - .iter() - .map(|location| location as &dyn LocatedError) - .collect(), - _ => vec![], - }; - locations.into_iter() - } -} - -impl From for BuildError { - fn from(kind: BuildErrorKind) -> Self { - BuildError { kind } - } -} - -impl From for BuildError { - fn from(error: CompileError) -> Self { - BuildError { - kind: BuildErrorKind::Compile(error), - } - } -} - -impl From for BuildError { - fn from(_: Infallible) -> Self { - unreachable!() - } -} - -impl<'t> From> for BuildError { - fn from(error: ParseError<'t>) -> Self { - BuildError { - kind: BuildErrorKind::Parse(error.into_owned()), - } - } -} - -impl<'t> From> for BuildError { - fn from(error: RuleError<'t>) -> Self { - BuildError { - kind: BuildErrorKind::Rule(error.into_owned()), - } - } -} - -#[derive(Debug, Error)] -#[non_exhaustive] -#[cfg_attr(feature = "miette", derive(Diagnostic))] -enum BuildErrorKind { - #[error(transparent)] - #[cfg_attr(feature = "miette", diagnostic(transparent))] - Compile(CompileError), - #[error(transparent)] - #[cfg_attr(feature = "miette", diagnostic(transparent))] - Parse(ParseError<'static>), - #[error(transparent)] - #[cfg_attr(feature = "miette", diagnostic(transparent))] - Rule(RuleError<'static>), -} - -/// Path that can be matched against a [`Program`]. -/// -/// `CandidatePath`s are always UTF-8 encoded. On some platforms this requires a -/// lossy conversion that uses Unicode replacement codepoints `�` whenever a -/// part of a path cannot be represented as valid UTF-8 (such as Windows). This -/// means that some byte sequences cannot be matched, though this is uncommon in -/// practice. -/// -/// [`Program`]: crate::Program -#[derive(Clone)] -pub struct CandidatePath<'b> { - text: Cow<'b, str>, -} - -impl<'b> CandidatePath<'b> { - /// Clones any borrowed data into an owning instance. - pub fn into_owned(self) -> CandidatePath<'static> { - CandidatePath { - text: self.text.into_owned().into(), - } - } -} - -impl AsRef for CandidatePath<'_> { - fn as_ref(&self) -> &str { - self.text.as_ref() - } -} - -impl Debug for CandidatePath<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self.text) - } -} - -impl Display for CandidatePath<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.text) - } -} - -impl<'b> From<&'b OsStr> for CandidatePath<'b> { - fn from(text: &'b OsStr) -> Self { - CandidatePath { - text: text.to_string_lossy(), - } - } -} - -impl<'b> From<&'b Path> for CandidatePath<'b> { - fn from(path: &'b Path) -> Self { - CandidatePath::from(path.as_os_str()) - } -} - -impl<'b> From<&'b str> for CandidatePath<'b> { - fn from(text: &'b str) -> Self { - CandidatePath { text: text.into() } - } -} - -/// Program that can be matched against paths and directory trees. -/// -/// `Glob`s are constructed from strings called glob expressions that resemble -/// Unix paths consisting of nominal components delimited by separators. Glob -/// expressions support various patterns that match and capture specified text -/// in a path. These patterns can be used to logically match individual paths -/// and to semantically match and walk directory trees. -/// -/// # Examples -/// -/// A `Glob` can be used to determine if a path matches a pattern via the -/// [`Program`] trait. -/// -/// ```rust -/// use wax::{Glob, Program}; -/// -/// let glob = Glob::new("*.png").unwrap(); -/// assert!(glob.is_match("apple.png")); -/// ``` -/// -/// Patterns form captures, which can be used to isolate matching sub-text. -/// -/// ```rust -/// use wax::{CandidatePath, Glob, Program}; -/// -/// let glob = Glob::new("**/{*.{go,rs}}").unwrap(); -/// let candidate = CandidatePath::from("src/lib.rs"); -/// assert_eq!("lib.rs", glob.matched(&candidate).unwrap().get(2).unwrap()); -/// ``` -/// -/// To match a `Glob` against a directory tree, the [`walk`] function can be -/// used to get an iterator over matching paths. -/// -/// ```rust,no_run,ignore -/// use wax::walk::Entry; -/// use wax::Glob; -/// -/// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); -/// for entry in glob.walk("./Pictures") { -/// let entry = entry.unwrap(); -/// println!("JPEG: {:?}", entry.path()); -/// } -/// ``` -/// -/// [`Program`]: crate::Program -/// [`walk`]: crate::Glob::walk -#[derive(Clone, Debug)] -pub struct Glob<'t> { - tree: Checked>, - program: Regex, -} - -impl<'t> Glob<'t> { - fn compile(tokens: impl IntoIterator) -> Result - where - T: Borrow>, - { - encode::compile(tokens) - } - - // TODO: Document pattern syntax in the crate documentation and refer to it - // here. - /// Constructs a [`Glob`] from a glob expression. - /// - /// A glob expression is UTF-8 encoded text that resembles a Unix path - /// consisting of nominal components delimited by separators and - /// patterns that can be matched against native paths. - /// - /// # Errors - /// - /// Returns an error if the glob expression fails to build. See - /// [`BuildError`]. - /// - /// [`Glob`]: crate::Glob - /// [`BuildError`]: crate::BuildError - pub fn new(expression: &'t str) -> Result { - let tree = parse_and_check(expression)?; - let program = Glob::compile(tree.as_ref().tokens())?; - Ok(Glob { tree, program }) - } - - /// Partitions a [`Glob`] into an invariant [`PathBuf`] prefix and variant - /// [`Glob`] postfix. - /// - /// The invariant prefix contains no glob patterns nor other variant - /// components and therefore can be interpreted as a native path. The - /// [`Glob`] postfix is variant and contains the remaining components - /// that follow the prefix. For example, the glob expression `.local/**/ - /// *.log` would produce the path `.local` and glob `**/*.log`. It is - /// possible for either partition to be empty. - /// - /// Literal components may be considered variant if they contain characters - /// with casing and the configured case sensitivity differs from the - /// target platform's file system. For example, the case-insensitive - /// literal expression `(?i)photos` is considered variant on Unix and - /// invariant on Windows, because the literal `photos` resolves differently - /// in Unix file system APIs. - /// - /// Partitioning a [`Glob`] allows any invariant prefix to be used as a - /// native path to establish a working directory or to interpret - /// semantic components that are not recognized by globs, such as parent - /// directory `..` components. - /// - /// Partitioned [`Glob`]s are never rooted. If the glob expression has a - /// root component, then it is always included in the invariant - /// [`PathBuf`] prefix. - /// - /// # Examples - /// - /// To match paths against a [`Glob`] while respecting semantic components, - /// the invariant prefix and candidate path can be canonicalized. The - /// following example canonicalizes both the working directory joined - /// with the prefix as well as the candidate path and then attempts to - /// match the [`Glob`] if the candidate path contains the prefix. - /// - /// ```rust,no_run - /// use dunce; // Avoids UNC paths on Windows. - /// use std::path::Path; - /// use wax::{Glob, Program}; - /// - /// let path: &Path = /* ... */ // Candidate path. - /// # Path::new(""); - /// - /// let directory = Path::new("."); // Working directory. - /// let (prefix, glob) = Glob::new("../../src/**").unwrap().partition(); - /// let prefix = dunce::canonicalize(directory.join(&prefix)).unwrap(); - /// if dunce::canonicalize(path) - /// .unwrap() - /// .strip_prefix(&prefix) - /// .map(|path| glob.is_match(path)) - /// .unwrap_or(false) - /// { - /// // ... - /// } - /// ``` - /// - /// [`Glob`]: crate::Glob - /// [`ParseError`]: crate::ParseError - /// [`PathBuf`]: std::path::PathBuf - /// [`RuleError`]: crate::RuleError - /// [`walk`]: crate::Glob::walk - pub fn partition(self) -> (PathBuf, Self) { - let Glob { tree, .. } = self; - let (prefix, tree) = tree.partition(); - let program = - Glob::compile(tree.as_ref().tokens()).expect("failed to compile partitioned glob"); - (prefix, Glob { tree, program }) - } - - /// Clones any borrowed data into an owning instance. - /// - /// # Examples - /// - /// `Glob`s borrow data in the corresponding glob expression. To move a - /// `Glob` beyond the scope of a glob expression, clone the data with - /// this function. - /// - /// ```rust - /// use wax::{BuildError, Glob}; - /// - /// fn local() -> Result, BuildError> { - /// let expression = String::from("**/*.txt"); - /// Glob::new(&expression).map(Glob::into_owned) - /// } - /// ``` - pub fn into_owned(self) -> Glob<'static> { - let Glob { tree, program } = self; - Glob { - tree: tree.into_owned(), - program, - } - } - - /// Gets metadata for capturing sub-expressions. - /// - /// This function returns an iterator over capturing tokens, which describe - /// the index and location of sub-expressions that capture [matched - /// text][`MatchedText`]. For example, in the expression `src/**/*.rs`, - /// both `**` and `*` form captures. - /// - /// [`MatchedText`]: crate::MatchedText - pub fn captures(&self) -> impl '_ + Clone + Iterator { - self.tree - .as_ref() - .tokens() - .iter() - .filter(|token| token.is_capturing()) - .enumerate() - .map(|(index, token)| CapturingToken { - index: index + 1, - span: *token.annotation(), - }) - } - - /// Returns `true` if the glob has a root. - /// - /// As with Unix paths, a glob expression has a root if it begins with a - /// separator `/`. Patterns other than separators may also root an - /// expression, such as `/**` or ``. - pub fn has_root(&self) -> bool { - self.tree - .as_ref() - .tokens() - .first() - .map_or(false, Token::has_root) - } - - /// Returns `true` if the glob has literals that have non-nominal semantics - /// on the target platform. - /// - /// The most notable semantic literals are the relative path components `.` - /// and `..`, which refer to a current and parent directory on Unix and - /// Windows operating systems, respectively. These are interpreted as - /// literals in glob expressions, and so only logically match paths that - /// contain these exact nominal components (semantic meaning is lost). - /// - /// See [`Glob::partition`]. - /// - /// [`Glob::partition`]: crate::Glob::partition - pub fn has_semantic_literals(&self) -> bool { - token::literals(self.tree.as_ref().tokens()) - .any(|(_, literal)| literal.is_semantic_literal()) - } -} - -impl Display for Glob<'_> { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.tree.as_ref().expression()) - } -} - -impl FromStr for Glob<'static> { - type Err = BuildError; - - fn from_str(expression: &str) -> Result { - Glob::new(expression).map(Glob::into_owned) - } -} - -impl<'t> Program<'t> for Glob<'t> { - fn is_match<'p>(&self, path: impl Into>) -> bool { - let path = path.into(); - self.program.is_match(path.as_ref()) - } - - fn matched<'p>(&self, path: &'p CandidatePath<'_>) -> Option> { - self.program.captures(path.as_ref()).map(From::from) - } - - fn variance(&self) -> Variance { - self.tree.as_ref().variance().into() - } - - fn is_exhaustive(&self) -> bool { - token::is_exhaustive(self.tree.as_ref().tokens()) - } -} - -impl<'t> TryFrom<&'t str> for Glob<'t> { - type Error = BuildError; - - fn try_from(expression: &'t str) -> Result { - Glob::new(expression) - } -} - -impl<'t> Pattern<'t> for Glob<'t> { - type Tokens = Tokenized<'t>; - type Error = Infallible; -} - -/// Combinator that matches any of its component [`Program`]s. -/// -/// An instance of `Any` is constructed using the [`any`] function, which -/// combines multiple [`Program`]s for more ergonomic and efficient matching. -/// -/// [`any`]: crate::any -/// [`Program`]: crate::Program -#[derive(Clone, Debug)] -pub struct Any<'t> { - tree: Checked>, - program: Regex, -} - -impl<'t> Any<'t> { - fn compile(token: &Token<'t, ()>) -> Result { - encode::compile([token]) - } -} - -impl<'t> Program<'t> for Any<'t> { - fn is_match<'p>(&self, path: impl Into>) -> bool { - let path = path.into(); - self.program.is_match(path.as_ref()) - } - - fn matched<'p>(&self, path: &'p CandidatePath<'_>) -> Option> { - self.program.captures(path.as_ref()).map(From::from) - } - - fn variance(&self) -> Variance { - self.tree.as_ref().variance::().into() - } - - fn is_exhaustive(&self) -> bool { - token::is_exhaustive(Some(self.tree.as_ref())) - } -} - -impl<'t> Pattern<'t> for Any<'t> { - type Tokens = Token<'t, ()>; - type Error = Infallible; -} - -// TODO: It may be useful to use dynamic dispatch via trait objects instead. -// This would allow for a variety of types to be composed in an `any` call -// and would be especially useful if additional combinators are -// introduced. -/// Constructs a combinator that matches if any of its input [`Program`]s match. -/// -/// This function accepts an [`IntoIterator`] with items that implement -/// [`Combine`], such as [`Glob`] and `&str`. The output [`Any`] implements -/// [`Program`] by matching its component [`Program`]s. [`Any`] is often more -/// ergonomic and efficient than matching individually against -/// multiple [`Program`]s. -/// -/// [`Any`] groups all captures and therefore only exposes the complete text of -/// a match. It is not possible to index a particular capturing token in the -/// component patterns. Combinators only support logical matching and cannot be -/// used to semantically match (walk) a directory tree. -/// -/// # Examples -/// -/// To match a path against multiple patterns, the patterns can first be -/// combined into an [`Any`]. -/// -/// ```rust -/// use wax::{Glob, Program}; -/// -/// let any = wax::any([ -/// "src/**/*.rs", -/// "tests/**/*.rs", -/// "doc/**/*.md", -/// "pkg/**/PKGBUILD", -/// ]) -/// .unwrap(); -/// assert!(any.is_match("src/lib.rs")); -/// ``` -/// -/// [`Glob`]s and other compiled [`Program`]s can also be composed into an -/// [`Any`]. -/// -/// ```rust -/// use wax::{Glob, Program}; -/// -/// let red = Glob::new("**/red/**/*.txt").unwrap(); -/// let blue = Glob::new("**/*blue*.txt").unwrap(); -/// assert!(wax::any([red, blue]).unwrap().is_match("red/potion.txt")); -/// ``` -/// -/// This function can only combine patterns of the same type, but intermediate -/// combinators can be used to combine different types into a single combinator. -/// -/// ```rust -/// use wax::{Glob, Program}; -/// -/// # fn fallible() -> Result<(), wax::BuildError> { -/// let glob = Glob::new("**/*.txt")?; -/// -/// // ... -/// -/// #[rustfmt::skip] -/// let any = wax::any([ -/// wax::any([glob])?, -/// wax::any([ -/// "**/*.pdf", -/// "**/*.tex", -/// ])?, -/// ])?; -/// assert!(any.is_match("doc/lattice.tex")); -/// # Ok(()) -/// # } -/// ``` -/// -/// # Errors -/// -/// Returns an error if any of the inputs fail to build. If the inputs are a -/// compiled [`Program`] type such as [`Glob`], then this only occurs if the -/// compiled program is too large. -/// -/// [`Any`]: crate::Any -/// [`Combine`]: crate::Combine -/// [`Glob`]: crate::Glob -/// [`IntoIterator`]: std::iter::IntoIterator -/// [`Program`]: crate::Pattern -pub fn any<'t, I>(patterns: I) -> Result, BuildError> -where - I: IntoIterator, - I::Item: Pattern<'t>, -{ - let tree = Checked::any( - patterns - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .map_err(Into::into)?, - ); - let program = Any::compile(tree.as_ref())?; - Ok(Any { tree, program }) -} - -/// Escapes text as a literal glob expression. -/// -/// This function escapes any and all meta-characters in the given string, such -/// that all text is interpreted as a literal or separator when read as a glob -/// expression. -/// -/// # Examples -/// -/// This function can be used to escape opaque strings, such as a string -/// obtained from a user that must be interpreted literally. -/// -/// ```rust -/// use wax::Glob; -/// -/// // An opaque file name that this code does not construct. -/// let name: String = { -/// /* ... */ -/// # String::from("file.txt") -/// }; -/// -/// // Do not allow patterns in `name`. -/// let expression = format!("{}{}", "**/", wax::escape(&name)); -/// if let Ok(glob) = Glob::new(&expression) { /* ... */ } -/// ``` -/// -/// Sometimes part of a path contains numerous meta-characters. This function -/// can be used to reliably escape them while making the unescaped part of the -/// expression a bit easier to read. -/// -/// ```rust -/// use wax::Glob; -/// -/// let expression = format!("{}{}", "logs/**/", wax::escape("ingest[01](L).txt")); -/// let glob = Glob::new(&expression).unwrap(); -/// ``` -// It is possible to call this function using a mutable reference, which may appear to mutate the -// parameter in place. -#[must_use] -pub fn escape(unescaped: &str) -> Cow { - const ESCAPE: char = '\\'; - - if unescaped.chars().any(is_meta_character) { - let mut escaped = String::new(); - for x in unescaped.chars() { - if is_meta_character(x) { - escaped.push(ESCAPE); - } - escaped.push(x); - } - escaped.into() - } else { - unescaped.into() - } -} - -// TODO: Is it possible for `:` and `,` to be contextual meta-characters? -/// Returns `true` if the given character is a meta-character. -/// -/// This function does **not** return `true` for contextual meta-characters that -/// may only be escaped in particular contexts, such as hyphens `-` in character -/// class expressions. To detect these characters, use -/// [`is_contextual_meta_character`]. -/// -/// [`is_contextual_meta_character`]: crate::is_contextual_meta_character -pub const fn is_meta_character(x: char) -> bool { - matches!( - x, - '?' | '*' | '$' | ':' | '<' | '>' | '(' | ')' | '[' | ']' | '{' | '}' | ',' - ) -} - -/// Returns `true` if the given character is a contextual meta-character. -/// -/// Contextual meta-characters may only be escaped in particular contexts, such -/// as hyphens `-` in character class expressions. Elsewhere, they are -/// interpreted as literals. To detect non-contextual meta-characters, use -/// [`is_meta_character`]. -/// -/// [`is_meta_character`]: crate::is_meta_character -pub const fn is_contextual_meta_character(x: char) -> bool { - matches!(x, '-') -} - -fn parse_and_check(expression: &str) -> Result, BuildError> { - let tokenized = token::parse(expression)?; - let checked = rule::check(tokenized)?; - Ok(checked) -} - -// TODO: Construct paths from components in tests. In practice, using string -// literals works, but is technically specific to platforms that support -// `/` as a separator. -#[cfg(test)] -mod tests { - use std::path::Path; - - use crate::{BuildError, BuildErrorKind, CandidatePath, Glob, Program}; - - #[test] - fn escape() { - assert_eq!(crate::escape(""), ""); - assert_eq!( - crate::escape("?*$:<>()[]{},"), - "\\?\\*\\$\\:\\<\\>\\(\\)\\[\\]\\{\\}\\,", - ); - assert_eq!(crate::escape("/usr/local/lib"), "/usr/local/lib"); - assert_eq!( - crate::escape("record[D00,00].txt"), - "record\\[D00\\,00\\].txt", - ); - assert_eq!( - crate::escape("Do You Remember Love?.mp4"), - "Do You Remember Love\\?.mp4", - ); - assert_eq!(crate::escape("å·¦{}å³"), "å·¦\\{\\}å³"); - assert_eq!(crate::escape("*中*"), "\\*中\\*"); - } - - #[test] - fn build_glob_with_eager_zom_tokens() { - Glob::new("*").unwrap(); - Glob::new("a/*").unwrap(); - Glob::new("*a").unwrap(); - Glob::new("a*").unwrap(); - Glob::new("a*b").unwrap(); - Glob::new("/*").unwrap(); - } - - #[test] - fn build_glob_with_lazy_zom_tokens() { - Glob::new("$").unwrap(); - Glob::new("a/$").unwrap(); - Glob::new("$a").unwrap(); - Glob::new("a$").unwrap(); - Glob::new("a$b").unwrap(); - Glob::new("/$").unwrap(); - } - - #[test] - fn build_glob_with_one_tokens() { - Glob::new("?").unwrap(); - Glob::new("a/?").unwrap(); - Glob::new("?a").unwrap(); - Glob::new("a?").unwrap(); - Glob::new("a?b").unwrap(); - Glob::new("??a??b??").unwrap(); - Glob::new("/?").unwrap(); - } - - #[test] - fn build_glob_with_one_and_zom_tokens() { - Glob::new("?*").unwrap(); - Glob::new("*?").unwrap(); - Glob::new("*/?").unwrap(); - Glob::new("?*?").unwrap(); - Glob::new("/?*").unwrap(); - Glob::new("?$").unwrap(); - } - - #[test] - fn build_glob_with_tree_tokens() { - Glob::new("**").unwrap(); - Glob::new("**/").unwrap(); - Glob::new("/**").unwrap(); - Glob::new("**/a").unwrap(); - Glob::new("a/**").unwrap(); - Glob::new("**/a/**/b/**").unwrap(); - Glob::new("{**/a,b/c}").unwrap(); - Glob::new("{a/b,c/**}").unwrap(); - Glob::new("<**/a>").unwrap(); - Glob::new("").unwrap(); - } - - #[test] - fn build_glob_with_class_tokens() { - Glob::new("a/[xy]").unwrap(); - Glob::new("a/[x-z]").unwrap(); - Glob::new("a/[xyi-k]").unwrap(); - Glob::new("a/[i-kxy]").unwrap(); - Glob::new("a/[!xy]").unwrap(); - Glob::new("a/[!x-z]").unwrap(); - Glob::new("a/[^xy]").unwrap(); - Glob::new("a/[^x-z]").unwrap(); - Glob::new("a/[xy]b/c").unwrap(); - } - - #[test] - fn negative_match_does_not_traverse_folders() { - let glob = Glob::new("a[!b]c").unwrap(); - assert!(glob.is_match(Path::new("adc"))); - assert!(!glob.is_match(Path::new("a/c"))); - } - - #[test] - fn negative_match_does_not_traverse_folders_2() { - let glob = Glob::new("a[!b-z]c").unwrap(); - assert!(glob.is_match(Path::new("aac"))); - assert!(!glob.is_match(Path::new("a/c"))); - } - - #[test] - fn build_glob_with_alternative_tokens() { - Glob::new("a/{x?z,y$}b*").unwrap(); - Glob::new("a/{???,x$y,frob}b*").unwrap(); - Glob::new("a/{???,x$y,frob}b*").unwrap(); - Glob::new("a/{???,{x*z,y$}}b*").unwrap(); - Glob::new("a{/**/b/,/b/**/}ca{t,b/**}").unwrap(); - } - - #[test] - fn build_glob_with_repetition_tokens() { - Glob::new("").unwrap(); - Glob::new("").unwrap(); - Glob::new("").unwrap(); - Glob::new("").unwrap(); - Glob::new("").unwrap(); - Glob::new(":0,>").unwrap(); - // Rooted repetitions are accepted if the lower bound is one or greater. - Glob::new("").unwrap(); - Glob::new("<[!.]*/:0,>[!.]*").unwrap(); - } - - #[test] - fn build_glob_with_literal_escaped_wildcard_tokens() { - Glob::new("a/b\\?/c").unwrap(); - Glob::new("a/b\\$/c").unwrap(); - Glob::new("a/b\\*/c").unwrap(); - Glob::new("a/b\\*\\*/c").unwrap(); - } - - #[test] - fn build_glob_with_class_escaped_wildcard_tokens() { - Glob::new("a/b[?]/c").unwrap(); - Glob::new("a/b[$]/c").unwrap(); - Glob::new("a/b[*]/c").unwrap(); - Glob::new("a/b[*][*]/c").unwrap(); - } - - #[test] - fn build_glob_with_literal_escaped_alternative_tokens() { - Glob::new("a/\\{\\}/c").unwrap(); - Glob::new("a/{x,y\\,,z}/c").unwrap(); - } - - #[test] - fn build_glob_with_class_escaped_alternative_tokens() { - Glob::new("a/[{][}]/c").unwrap(); - Glob::new("a/{x,y[,],z}/c").unwrap(); - } - - #[test] - fn build_glob_with_literal_escaped_class_tokens() { - Glob::new("a/\\[a-z\\]/c").unwrap(); - Glob::new("a/[\\[]/c").unwrap(); - Glob::new("a/[\\]]/c").unwrap(); - Glob::new("a/[a\\-z]/c").unwrap(); - } - - #[test] - fn build_glob_with_flags() { - Glob::new("(?i)a/b/c").unwrap(); - Glob::new("(?-i)a/b/c").unwrap(); - Glob::new("a/(?-i)b/c").unwrap(); - Glob::new("a/b/(?-i)c").unwrap(); - Glob::new("(?i)a/(?-i)b/(?i)c").unwrap(); - } - - #[test] - fn build_any_combinator() { - crate::any([ - Glob::new("src/**/*.rs").unwrap(), - Glob::new("doc/**/*.md").unwrap(), - Glob::new("pkg/**/PKGBUILD").unwrap(), - ]) - .unwrap(); - crate::any(["src/**/*.rs", "doc/**/*.md", "pkg/**/PKGBUILD"]).unwrap(); - } - - #[test] - fn build_any_nested_combinator() { - crate::any([ - crate::any(["a/b", "c/d"]).unwrap(), - crate::any(["{e,f,g}", "{h,i}"]).unwrap(), - ]) - .unwrap(); - } - - #[test] - fn reject_glob_with_invalid_separator_tokens() { - assert!(Glob::new("//a").is_err()); - assert!(Glob::new("a//b").is_err()); - assert!(Glob::new("a/b//").is_err()); - assert!(Glob::new("a//**").is_err()); - assert!(Glob::new("{//}a").is_err()); - assert!(Glob::new("{**//}").is_err()); - } - - #[test] - fn reject_glob_with_adjacent_tree_or_zom_tokens() { - assert!(Glob::new("***").is_err()); - assert!(Glob::new("****").is_err()); - assert!(Glob::new("**/**").is_err()); - assert!(Glob::new("a{**/**,/b}").is_err()); - assert!(Glob::new("**/*/***").is_err()); - assert!(Glob::new("**$").is_err()); - assert!(Glob::new("**/$**").is_err()); - assert!(Glob::new("{*$}").is_err()); - assert!(Glob::new("<*$:1,>").is_err()); - } - - #[test] - fn reject_glob_with_tree_adjacent_literal_tokens() { - assert!(Glob::new("**a").is_err()); - assert!(Glob::new("a**").is_err()); - assert!(Glob::new("a**b").is_err()); - assert!(Glob::new("a*b**").is_err()); - assert!(Glob::new("**/**a/**").is_err()); - } - - #[test] - fn reject_glob_with_adjacent_one_tokens() { - assert!(Glob::new("**?").is_err()); - assert!(Glob::new("?**").is_err()); - assert!(Glob::new("?**?").is_err()); - assert!(Glob::new("?*?**").is_err()); - assert!(Glob::new("**/**?/**").is_err()); - } - - #[test] - fn reject_glob_with_unescaped_meta_characters_in_class_tokens() { - assert!(Glob::new("a/[a-z-]/c").is_err()); - assert!(Glob::new("a/[-a-z]/c").is_err()); - assert!(Glob::new("a/[-]/c").is_err()); - // NOTE: Without special attention to escaping and character parsing, this could - // be mistakenly interpreted as an empty range over the character - // `-`. This should be rejected. - assert!(Glob::new("a/[---]/c").is_err()); - assert!(Glob::new("a/[[]/c").is_err()); - assert!(Glob::new("a/[]]/c").is_err()); - } - - #[test] - fn reject_glob_with_invalid_alternative_zom_tokens() { - assert!(Glob::new("*{okay,*}").is_err()); - assert!(Glob::new("{okay,*}*").is_err()); - assert!(Glob::new("${okay,*error}").is_err()); - assert!(Glob::new("{okay,error*}$").is_err()); - assert!(Glob::new("{*,okay}{okay,*}").is_err()); - assert!(Glob::new("{okay,error*}{okay,*error}").is_err()); - } - - #[test] - fn reject_glob_with_invalid_alternative_tree_tokens() { - assert!(Glob::new("{**}").is_err()); - assert!(Glob::new("slash/{**/error}").is_err()); - assert!(Glob::new("{error/**}/slash").is_err()); - assert!(Glob::new("slash/{okay/**,**/error}").is_err()); - assert!(Glob::new("{**/okay,error/**}/slash").is_err()); - assert!(Glob::new("{**/okay,prefix{error/**}}/slash").is_err()); - assert!(Glob::new("{**/okay,slash/{**/error}}postfix").is_err()); - assert!(Glob::new("{error/**}{okay,**/error").is_err()); - } - - #[test] - fn reject_glob_with_invalid_alternative_separator_tokens() { - assert!(Glob::new("/slash/{okay,/error}").is_err()); - assert!(Glob::new("{okay,error/}/slash").is_err()); - assert!(Glob::new("slash/{okay,/error/,okay}/slash").is_err()); - assert!(Glob::new("{okay,error/}{okay,/error}").is_err()); - } - - #[test] - fn reject_glob_with_rooted_alternative_tokens() { - assert!(Glob::new("{okay,/}").is_err()); - assert!(Glob::new("{okay,/**}").is_err()); - assert!(Glob::new("{okay,/error}").is_err()); - assert!(Glob::new("{okay,/**/error}").is_err()); - } - - #[test] - fn reject_glob_with_invalid_repetition_bounds_tokens() { - assert!(Glob::new("").is_err()); - } - - #[test] - fn reject_glob_with_invalid_repetition_zom_tokens() { - assert!(Glob::new("<*:0,>").is_err()); - assert!(Glob::new("*").is_err()); - assert!(Glob::new("*<*a:0,>").is_err()); - } - - #[test] - fn reject_glob_with_invalid_repetition_tree_tokens() { - assert!(Glob::new("<**:0,>").is_err()); - assert!(Glob::new("").is_err()); - assert!(Glob::new("/").is_err()); - assert!(Glob::new("/**").is_err()); - } - - #[test] - fn reject_glob_with_invalid_repetition_separator_tokens() { - assert!(Glob::new("").is_err()); - assert!(Glob::new("").is_err()); - assert!(Glob::new("/").is_err()); - } - - // Rooted repetitions are rejected if their lower bound is zero; any other lower - // bound is accepted. - #[test] - fn reject_glob_with_rooted_repetition_tokens() { - assert!(Glob::new("maybe").is_err()); - assert!(Glob::new("").is_err()); - } - - #[test] - fn reject_glob_with_oversized_invariant_repetition_tokens() { - assert!(matches!( - Glob::new(""), - Err(BuildError { - kind: BuildErrorKind::Rule(_), - .. - }), - )); - assert!(matches!( - Glob::new(""), - Err(BuildError { - kind: BuildErrorKind::Rule(_), - .. - }), - )); - assert!(matches!( - Glob::new("ab"), - Err(BuildError { - kind: BuildErrorKind::Rule(_), - .. - }), - )); - assert!(matches!( - Glob::new("{,}"), - Err(BuildError { - kind: BuildErrorKind::Rule(_), - .. - }), - )); - } - - #[test] - fn reject_glob_with_invalid_flags() { - assert!(Glob::new("(?)a").is_err()); - assert!(Glob::new("(?-)a").is_err()); - assert!(Glob::new("()a").is_err()); - } - - #[test] - fn reject_glob_with_adjacent_tokens_through_flags() { - assert!(Glob::new("/(?i)/").is_err()); - assert!(Glob::new("$(?i)$").is_err()); - assert!(Glob::new("*(?i)*").is_err()); - assert!(Glob::new("**(?i)?").is_err()); - assert!(Glob::new("a(?i)**").is_err()); - assert!(Glob::new("**(?i)a").is_err()); - } - - #[test] - fn reject_glob_with_oversized_program() { - assert!(matches!( - Glob::new(""), - Err(BuildError { - kind: BuildErrorKind::Compile(_), - .. - }), - )); - } - - #[test] - fn reject_any_combinator() { - assert!(crate::any(["{a,b,c}", "{d, e}", "f/{g,/error,h}",]).is_err()) - } - - #[test] - fn match_glob_with_empty_expression() { - let glob = Glob::new("").unwrap(); - - assert!(glob.is_match(Path::new(""))); - - assert!(!glob.is_match(Path::new("abc"))); - } - - #[test] - fn match_glob_with_only_invariant_tokens() { - let glob = Glob::new("a/b").unwrap(); - - assert!(glob.is_match(Path::new("a/b"))); - - assert!(!glob.is_match(Path::new("aa/b"))); - assert!(!glob.is_match(Path::new("a/bb"))); - assert!(!glob.is_match(Path::new("a/b/c"))); - - // There are no variant tokens with which to capture, but the matched text - // should always be available. - assert_eq!( - "a/b", - glob.matched(&CandidatePath::from(Path::new("a/b"))) - .unwrap() - .complete(), - ); - } - - #[test] - fn match_glob_with_tree_tokens() { - let glob = Glob::new("a/**/b").unwrap(); - - assert!(glob.is_match(Path::new("a/b"))); - assert!(glob.is_match(Path::new("a/x/b"))); - assert!(glob.is_match(Path::new("a/x/y/z/b"))); - - assert!(!glob.is_match(Path::new("a"))); - assert!(!glob.is_match(Path::new("b/a"))); - - assert_eq!( - "x/y/z/", - glob.matched(&CandidatePath::from(Path::new("a/x/y/z/b"))) - .unwrap() - .get(1) - .unwrap(), - ); - } - - #[test] - fn match_glob_with_tree_and_zom_tokens() { - let glob = Glob::new("**/*.ext").unwrap(); - - assert!(glob.is_match(Path::new("file.ext"))); - assert!(glob.is_match(Path::new("a/file.ext"))); - assert!(glob.is_match(Path::new("a/b/file.ext"))); - - let path = CandidatePath::from(Path::new("a/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("a/", matched.get(1).unwrap()); - assert_eq!("file", matched.get(2).unwrap()); - } - - #[test] - fn match_glob_with_eager_and_lazy_zom_tokens() { - let glob = Glob::new("$-*.*").unwrap(); - - assert!(glob.is_match(Path::new("prefix-file.ext"))); - assert!(glob.is_match(Path::new("a-b-c.ext"))); - - let path = CandidatePath::from(Path::new("a-b-c.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("a", matched.get(1).unwrap()); - assert_eq!("b-c", matched.get(2).unwrap()); - assert_eq!("ext", matched.get(3).unwrap()); - } - - #[test] - fn match_glob_with_class_tokens() { - let glob = Glob::new("a/[xyi-k]/**").unwrap(); - - assert!(glob.is_match(Path::new("a/x/file.ext"))); - assert!(glob.is_match(Path::new("a/y/file.ext"))); - assert!(glob.is_match(Path::new("a/j/file.ext"))); - - assert!(!glob.is_match(Path::new("a/b/file.ext"))); - - let path = CandidatePath::from(Path::new("a/i/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("i", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_non_ascii_class_tokens() { - let glob = Glob::new("a/[金銀]/**").unwrap(); - - assert!(glob.is_match(Path::new("a/金/file.ext"))); - assert!(glob.is_match(Path::new("a/銀/file.ext"))); - - assert!(!glob.is_match(Path::new("a/銅/file.ext"))); - - let path = CandidatePath::from(Path::new("a/金/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("金", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_literal_escaped_class_tokens() { - let glob = Glob::new("a/[\\[\\]\\-]/**").unwrap(); - - assert!(glob.is_match(Path::new("a/[/file.ext"))); - assert!(glob.is_match(Path::new("a/]/file.ext"))); - assert!(glob.is_match(Path::new("a/-/file.ext"))); - - assert!(!glob.is_match(Path::new("a/b/file.ext"))); - - let path = CandidatePath::from(Path::new("a/[/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("[", matched.get(1).unwrap()); - } - - #[cfg(any(unix, windows))] - #[test] - fn match_glob_with_empty_class_tokens() { - // A character class is "empty" if it only matches separators on the target - // platform. Such a character class never matches anything. - let glob = Glob::new("a[/]b").unwrap(); - - assert!(!glob.is_match(Path::new("a/b"))); - assert!(!glob.is_match(Path::new("ab"))); - assert!(!glob.is_match(Path::new("a"))); - assert!(!glob.is_match(Path::new("b"))); - assert!(!glob.is_match(Path::new(""))); - } - - #[test] - fn match_glob_with_negated_class_tokens() { - let glob = Glob::new("a[!b]c").unwrap(); - - assert!(glob.is_match(Path::new("a-c"))); - assert!(glob.is_match(Path::new("axc"))); - - assert!(!glob.is_match(Path::new("abc"))); - assert!(!glob.is_match(Path::new("a/c"))); - - let glob = Glob::new("a[!0-4]b").unwrap(); - - assert!(glob.is_match(Path::new("a9b"))); - assert!(glob.is_match(Path::new("axb"))); - - assert!(!glob.is_match(Path::new("a0b"))); - assert!(!glob.is_match(Path::new("a4b"))); - assert!(!glob.is_match(Path::new("a/b"))); - } - - #[test] - fn match_glob_with_alternative_tokens() { - let glob = Glob::new("a/{x?z,y$}b/*").unwrap(); - - assert!(glob.is_match(Path::new("a/xyzb/file.ext"))); - assert!(glob.is_match(Path::new("a/yb/file.ext"))); - - assert!(!glob.is_match(Path::new("a/xyz/file.ext"))); - assert!(!glob.is_match(Path::new("a/y/file.ext"))); - assert!(!glob.is_match(Path::new("a/xyzub/file.ext"))); - - let path = CandidatePath::from(Path::new("a/xyzb/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("xyz", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_nested_alternative_tokens() { - let glob = Glob::new("a/{y$,{x?z,?z}}b/*").unwrap(); - - let path = CandidatePath::from(Path::new("a/xyzb/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("xyz", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_alternative_tree_tokens() { - let glob = Glob::new("a{/foo,/bar,/**/baz}/qux").unwrap(); - - assert!(glob.is_match(Path::new("a/foo/qux"))); - assert!(glob.is_match(Path::new("a/foo/baz/qux"))); - assert!(glob.is_match(Path::new("a/foo/bar/baz/qux"))); - - assert!(!glob.is_match(Path::new("a/foo/bar/qux"))); - } - - #[test] - fn match_glob_with_alternative_repetition_tokens() { - let glob = Glob::new("log-{<[0-9]:3>,<[0-9]:4>-<[0-9]:2>-<[0-9]:2>}.txt").unwrap(); - - assert!(glob.is_match(Path::new("log-000.txt"))); - assert!(glob.is_match(Path::new("log-1970-01-01.txt"))); - - assert!(!glob.is_match(Path::new("log-abc.txt"))); - assert!(!glob.is_match(Path::new("log-nope-no-no.txt"))); - } - - #[test] - fn match_glob_with_repetition_tokens() { - let glob = Glob::new("a/<[0-9]:6>/*").unwrap(); - - assert!(glob.is_match(Path::new("a/000000/file.ext"))); - assert!(glob.is_match(Path::new("a/123456/file.ext"))); - - assert!(!glob.is_match(Path::new("a/00000/file.ext"))); - assert!(!glob.is_match(Path::new("a/0000000/file.ext"))); - assert!(!glob.is_match(Path::new("a/bbbbbb/file.ext"))); - - let path = CandidatePath::from(Path::new("a/999999/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("999999", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_negative_repetition_tokens() { - let glob = Glob::new("<[!.]*/>[!.]*").unwrap(); - - assert!(glob.is_match(Path::new("a/b/file.ext"))); - - assert!(!glob.is_match(Path::new(".a/b/file.ext"))); - assert!(!glob.is_match(Path::new("a/.b/file.ext"))); - assert!(!glob.is_match(Path::new("a/b/.file.ext"))); - } - - #[test] - fn match_glob_with_nested_repetition_tokens() { - let glob = Glob::new("log<-<[0-9]:3>:1,2>.txt").unwrap(); - - assert!(glob.is_match(Path::new("log-000.txt"))); - assert!(glob.is_match(Path::new("log-123-456.txt"))); - - assert!(!glob.is_match(Path::new("log-abc.txt"))); - assert!(!glob.is_match(Path::new("log-123-456-789.txt"))); - - let path = CandidatePath::from(Path::new("log-987-654.txt")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("-987-654", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_repeated_alternative_tokens() { - let glob = Glob::new("<{a,b}:1,>/**").unwrap(); - - assert!(glob.is_match(Path::new("a/file.ext"))); - assert!(glob.is_match(Path::new("b/file.ext"))); - assert!(glob.is_match(Path::new("aaa/file.ext"))); - assert!(glob.is_match(Path::new("bbb/file.ext"))); - - assert!(!glob.is_match(Path::new("file.ext"))); - assert!(!glob.is_match(Path::new("c/file.ext"))); - - let path = CandidatePath::from(Path::new("aa/file.ext")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("aa", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_rooted_tree_token() { - let glob = Glob::new("/**/{var,.var}/**/*.log").unwrap(); - - assert!(glob.is_match(Path::new("/var/log/network.log"))); - assert!(glob.is_match(Path::new("/home/nobody/.var/network.log"))); - - assert!(!glob.is_match(Path::new("./var/cron.log"))); - assert!(!glob.is_match(Path::new("mnt/var/log/cron.log"))); - - let path = CandidatePath::from(Path::new("/var/log/network.log")); - let matched = glob.matched(&path).unwrap(); - assert_eq!("/", matched.get(1).unwrap()); - } - - #[test] - fn match_glob_with_flags() { - let glob = Glob::new("(?-i)photos/**/*.(?i){jpg,jpeg}").unwrap(); - - assert!(glob.is_match(Path::new("photos/flower.jpg"))); - assert!(glob.is_match(Path::new("photos/flower.JPEG"))); - - assert!(!glob.is_match(Path::new("Photos/flower.jpeg"))); - } - - #[test] - fn match_glob_with_escaped_flags() { - let glob = Glob::new("a\\(b\\)").unwrap(); - - assert!(glob.is_match(Path::new("a(b)"))); - } - - #[test] - fn match_any_combinator() { - let any = crate::any(["src/**/*.rs", "doc/**/*.md", "pkg/**/PKGBUILD"]).unwrap(); - - assert!(any.is_match("src/lib.rs")); - assert!(any.is_match("doc/api.md")); - assert!(any.is_match("pkg/arch/lib-git/PKGBUILD")); - - assert!(!any.is_match("img/icon.png")); - assert!(!any.is_match("doc/LICENSE.tex")); - assert!(!any.is_match("pkg/lib.rs")); - } - - #[test] - fn partition_glob_with_variant_and_invariant_parts() { - let (prefix, glob) = Glob::new("a/b/x?z/*.ext").unwrap().partition(); - - assert_eq!(prefix, Path::new("a/b")); - - assert!(glob.is_match(Path::new("xyz/file.ext"))); - assert!(glob.is_match(Path::new("a/b/xyz/file.ext").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_only_variant_wildcard_parts() { - let (prefix, glob) = Glob::new("x?z/*.ext").unwrap().partition(); - - assert_eq!(prefix, Path::new("")); - - assert!(glob.is_match(Path::new("xyz/file.ext"))); - assert!(glob.is_match(Path::new("xyz/file.ext").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_only_invariant_literal_parts() { - let (prefix, glob) = Glob::new("a/b").unwrap().partition(); - - assert_eq!(prefix, Path::new("a/b")); - - assert!(glob.is_match(Path::new(""))); - assert!(glob.is_match(Path::new("a/b").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_variant_alternative_parts() { - let (prefix, glob) = Glob::new("{x,z}/*.ext").unwrap().partition(); - - assert_eq!(prefix, Path::new("")); - - assert!(glob.is_match(Path::new("x/file.ext"))); - assert!(glob.is_match(Path::new("z/file.ext").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_invariant_alternative_parts() { - let (prefix, glob) = Glob::new("{a/b}/c").unwrap().partition(); - - assert_eq!(prefix, Path::new("a/b/c")); - - assert!(glob.is_match(Path::new(""))); - assert!(glob.is_match(Path::new("a/b/c").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_invariant_repetition_parts() { - let (prefix, glob) = Glob::new("/c").unwrap().partition(); - - assert_eq!(prefix, Path::new("/a/b/a/b/a/b/c")); - - assert!(glob.is_match(Path::new(""))); - assert!(glob.is_match(Path::new("/a/b/a/b/a/b/c").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_literal_dots_and_tree_tokens() { - let (prefix, glob) = Glob::new("../**/*.ext").unwrap().partition(); - - assert_eq!(prefix, Path::new("..")); - - assert!(glob.is_match(Path::new("xyz/file.ext"))); - assert!(glob.is_match(Path::new("../xyz/file.ext").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_rooted_tree_token() { - let (prefix, glob) = Glob::new("/**/*.ext").unwrap().partition(); - - assert_eq!(prefix, Path::new("/")); - assert!(!glob.has_root()); - - assert!(glob.is_match(Path::new("file.ext"))); - assert!(glob.is_match(Path::new("/root/file.ext").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_rooted_zom_token() { - let (prefix, glob) = Glob::new("/*/*.ext").unwrap().partition(); - - assert_eq!(prefix, Path::new("/")); - assert!(!glob.has_root()); - - assert!(glob.is_match(Path::new("root/file.ext"))); - assert!(glob.is_match(Path::new("/root/file.ext").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_rooted_literal_token() { - let (prefix, glob) = Glob::new("/root/**/*.ext").unwrap().partition(); - - assert_eq!(prefix, Path::new("/root")); - assert!(!glob.has_root()); - - assert!(glob.is_match(Path::new("file.ext"))); - assert!(glob.is_match(Path::new("/root/file.ext").strip_prefix(prefix).unwrap())); - } - - #[test] - fn partition_glob_with_invariant_expression_text() { - let (prefix, glob) = Glob::new("/root/file.ext").unwrap().partition(); - assert_eq!(prefix, Path::new("/root/file.ext")); - assert_eq!(format!("{}", glob), ""); - - let (prefix, glob) = Glob::new("/file.ext").unwrap().partition(); - assert_eq!(prefix, Path::new("aaa/file.ext")); - assert_eq!(format!("{}", glob), ""); - } - - #[test] - fn partition_glob_with_variant_expression_text() { - let (prefix, glob) = Glob::new("**/file.ext").unwrap().partition(); - assert_eq!(prefix, Path::new("")); - assert_eq!(format!("{}", glob), "**/file.ext"); - - let (prefix, glob) = Glob::new("/root/**/file.ext").unwrap().partition(); - assert_eq!(prefix, Path::new("/root")); - assert_eq!(format!("{}", glob), "**/file.ext"); - - let (prefix, glob) = Glob::new("/root/**").unwrap().partition(); - assert_eq!(prefix, Path::new("/root")); - assert_eq!(format!("{}", glob), "**"); - } - - #[test] - fn repartition_glob_with_variant_tokens() { - let (prefix, glob) = Glob::new("/root/**/file.ext").unwrap().partition(); - assert_eq!(prefix, Path::new("/root")); - assert_eq!(format!("{}", glob), "**/file.ext"); - - let (prefix, glob) = glob.partition(); - assert_eq!(prefix, Path::new("")); - assert_eq!(format!("{}", glob), "**/file.ext"); - } - - #[test] - fn query_glob_has_root() { - assert!(Glob::new("/root").unwrap().has_root()); - assert!(Glob::new("/**").unwrap().has_root()); - assert!(Glob::new("").unwrap().has_root()); - - assert!(!Glob::new("").unwrap().has_root()); - // This is not rooted, because character classes may not match separators. This - // example compiles an "empty" character class, which attempts to match - // `NUL` and so effectively matches nothing. - #[cfg(any(unix, windows))] - assert!(!Glob::new("[/]root").unwrap().has_root()); - // The leading forward slash in tree tokens is meaningful. When omitted, at the - // beginning of an expression, the resulting glob is not rooted. - assert!(!Glob::new("**/").unwrap().has_root()); - } - - #[cfg(any(unix, windows))] - #[test] - fn query_glob_has_semantic_literals() { - assert!(Glob::new("../src/**").unwrap().has_semantic_literals()); - assert!(Glob::new("*/a/../b.*").unwrap().has_semantic_literals()); - assert!(Glob::new("{a,..}").unwrap().has_semantic_literals()); - assert!(Glob::new("").unwrap().has_semantic_literals()); - assert!(Glob::new("").unwrap().has_semantic_literals()); - assert!(Glob::new("./*.txt").unwrap().has_semantic_literals()); - } - - #[test] - fn query_glob_capture_indices() { - let glob = Glob::new("**/{foo*,bar*}/???").unwrap(); - let indices: Vec<_> = glob.captures().map(|token| token.index()).collect(); - assert_eq!(&indices, &[1, 2, 3, 4, 5]); - } - - #[test] - fn query_glob_capture_spans() { - let glob = Glob::new("**/{foo*,bar*}/$").unwrap(); - let spans: Vec<_> = glob.captures().map(|token| token.span()).collect(); - assert_eq!(&spans, &[(0, 3), (3, 11), (15, 1)]); - } - - #[test] - fn query_glob_variance() { - assert!(Glob::new("").unwrap().variance().is_invariant()); - assert!(Glob::new("/a/file.ext").unwrap().variance().is_invariant()); - assert!(Glob::new("/a/{file.ext}") - .unwrap() - .variance() - .is_invariant()); - assert!(Glob::new("{a/b/file.ext}") - .unwrap() - .variance() - .is_invariant()); - assert!(Glob::new("{a,a}").unwrap().variance().is_invariant()); - #[cfg(windows)] - assert!(Glob::new("{a,A}").unwrap().variance().is_invariant()); - assert!(Glob::new("").unwrap().variance().is_invariant()); - #[cfg(unix)] - assert!(Glob::new("/[a]/file.ext") - .unwrap() - .variance() - .is_invariant()); - #[cfg(unix)] - assert!(Glob::new("/[a-a]/file.ext") - .unwrap() - .variance() - .is_invariant()); - #[cfg(unix)] - assert!(Glob::new("/[a-aaa-a]/file.ext") - .unwrap() - .variance() - .is_invariant()); - - assert!(Glob::new("/a/{b,c}").unwrap().variance().is_variant()); - assert!(Glob::new("").unwrap().variance().is_variant()); - assert!(Glob::new("/[ab]/file.ext").unwrap().variance().is_variant()); - assert!(Glob::new("**").unwrap().variance().is_variant()); - assert!(Glob::new("/a/*.ext").unwrap().variance().is_variant()); - assert!(Glob::new("/a/b*").unwrap().variance().is_variant()); - #[cfg(unix)] - assert!(Glob::new("/a/(?i)file.ext") - .unwrap() - .variance() - .is_variant()); - #[cfg(windows)] - assert!(Glob::new("/a/(?-i)file.ext") - .unwrap() - .variance() - .is_variant()); - } -} diff --git a/crates/turborepo-wax/src/rule.rs b/crates/turborepo-wax/src/rule.rs deleted file mode 100644 index a4c67b5c1e995..0000000000000 --- a/crates/turborepo-wax/src/rule.rs +++ /dev/null @@ -1,804 +0,0 @@ -//! Rules and limitations for token sequences. -//! -//! This module provides the `check` function, which examines a token sequence -//! and emits an error if the sequence violates rules. Rules are invariants that -//! are difficult or impossible to enforce when parsing text and primarily -//! detect and reject token sequences that produce anomalous, meaningless, or -//! unexpected globs (regular expressions) when compiled. -//! -//! Most rules concern alternatives, which have complex interactions with -//! neighboring tokens. - -// TODO: The `check` function fails fast and either report no errors or exactly -// one error. To better support diagnostics, `check` should probably -// perform an exhaustive analysis and report zero or more errors. - -#[cfg(feature = "miette")] -use std::fmt::Display; -use std::{borrow::Cow, convert::Infallible, iter::Fuse, path::PathBuf, slice}; - -use itertools::Itertools as _; -#[cfg(feature = "miette")] -use miette::{Diagnostic, LabeledSpan, SourceCode}; -use thiserror::Error; - -use crate::{ - diagnostics::{CompositeSpan, CorrelatedSpan, SpanExt as _}, - token::{self, InvariantSize, Token, TokenKind, TokenTree, Tokenized}, - Any, BuildError, Glob, Pattern, -}; - -/// Maximum invariant size. -/// -/// This size is equal to or greater than the maximum size of a path on -/// supported platforms. The primary purpose of this limit is to mitigate -/// malicious or mistaken expressions that encode very large invariant text, -/// namely via repetitions. -/// -/// This limit is independent of the back end encoding. This code does not rely -/// on errors in the encoder by design, such as size limitations. -const MAX_INVARIANT_SIZE: InvariantSize = InvariantSize::new(0x10000); - -trait IteratorExt: Iterator + Sized { - fn adjacent(self) -> Adjacent - where - Self::Item: Clone; -} - -impl IteratorExt for I -where - I: Iterator, -{ - fn adjacent(self) -> Adjacent - where - Self::Item: Clone, - { - Adjacent::new(self) - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum Adjacency { - Only { item: T }, - First { item: T, right: T }, - Middle { left: T, item: T, right: T }, - Last { left: T, item: T }, -} - -impl Adjacency { - pub fn into_tuple(self) -> (Option, T, Option) { - match self { - Adjacency::Only { item } => (None, item, None), - Adjacency::First { item, right } => (None, item, Some(right)), - Adjacency::Middle { left, item, right } => (Some(left), item, Some(right)), - Adjacency::Last { left, item } => (Some(left), item, None), - } - } -} - -struct Adjacent -where - I: Iterator, -{ - input: Fuse, - adjacency: Option>, -} - -impl Adjacent -where - I: Iterator, -{ - fn new(input: I) -> Self { - let mut input = input.fuse(); - let adjacency = match (input.next(), input.next()) { - (Some(item), Some(right)) => Some(Adjacency::First { item, right }), - (Some(item), None) => Some(Adjacency::Only { item }), - (None, None) => None, - // The input iterator is fused, so this cannot occur. - (None, Some(_)) => unreachable!(), - }; - Adjacent { input, adjacency } - } -} - -impl Iterator for Adjacent -where - I: Iterator, - I::Item: Clone, -{ - type Item = Adjacency; - - fn next(&mut self) -> Option { - let next = self.input.next(); - self.adjacency.take().map(|adjacency| { - self.adjacency = match adjacency.clone() { - Adjacency::First { - item: left, - right: item, - } - | Adjacency::Middle { - item: left, - right: item, - .. - } => { - if let Some(right) = next { - Some(Adjacency::Middle { left, item, right }) - } else { - Some(Adjacency::Last { left, item }) - } - } - Adjacency::Only { .. } | Adjacency::Last { .. } => None, - }; - adjacency - }) - } -} - -trait SliceExt { - fn terminals(&self) -> Option>; -} - -impl SliceExt for [T] { - fn terminals(&self) -> Option> { - match self.len() { - 0 => None, - 1 => Some(Terminals::Only(self.first().unwrap())), - _ => Some(Terminals::StartEnd( - self.first().unwrap(), - self.last().unwrap(), - )), - } - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -enum Terminals { - Only(T), - StartEnd(T, T), -} - -impl Terminals { - pub fn map(self, mut f: F) -> Terminals - where - F: FnMut(T) -> U, - { - match self { - Terminals::Only(only) => Terminals::Only(f(only)), - Terminals::StartEnd(start, end) => Terminals::StartEnd(f(start), f(end)), - } - } -} - -/// Describes errors concerning rules and patterns in a glob expression. -/// -/// Patterns must follow rules described in the [repository -/// documentation](https://github.com/olson-sean-k/wax/blob/master/README.md). These rules are -/// designed to avoid nonsense glob expressions and ambiguity. If a glob -/// expression parses but violates these rules or is otherwise malformed, then -/// this error is returned by some APIs. -#[derive(Debug, Error)] -#[error("malformed glob expression: {kind}")] -pub struct RuleError<'t> { - expression: Cow<'t, str>, - kind: RuleErrorKind, - location: CompositeSpan, -} - -impl<'t> RuleError<'t> { - fn new(expression: Cow<'t, str>, kind: RuleErrorKind, location: CompositeSpan) -> Self { - RuleError { - expression, - kind, - location, - } - } - - /// Clones any borrowed data into an owning instance. - pub fn into_owned(self) -> RuleError<'static> { - let RuleError { - expression, - kind, - location, - } = self; - RuleError { - expression: expression.into_owned().into(), - kind, - location, - } - } - - pub fn locations(&self) -> &[CompositeSpan] { - slice::from_ref(&self.location) - } - - /// Gets the glob expression that violated pattern rules. - pub fn expression(&self) -> &str { - self.expression.as_ref() - } -} - -#[cfg(feature = "miette")] -#[cfg_attr(docsrs, doc(cfg(feature = "miette")))] -impl Diagnostic for RuleError<'_> { - fn code<'a>(&'a self) -> Option> { - Some(Box::new(String::from(match self.kind { - RuleErrorKind::RootedSubGlob => "wax::glob::rooted_sub_glob", - RuleErrorKind::SingularTree => "wax::glob::singular_tree", - RuleErrorKind::SingularZeroOrMore => "wax::glob::singular_zero_or_more", - RuleErrorKind::AdjacentBoundary => "wax::glob::adjacent_boundary", - RuleErrorKind::AdjacentZeroOrMore => "wax::glob::adjacent_zero_or_more", - RuleErrorKind::OversizedInvariant => "wax::glob::oversized_invariant", - RuleErrorKind::IncompatibleBounds => "wax::glob::incompatible_bounds", - }))) - } - - fn help<'a>(&'a self) -> Option> { - match self.kind { - RuleErrorKind::OversizedInvariant => Some(Box::new(String::from( - "this error typically occurs when a repetition has a convergent bound that is too \ - large", - ))), - _ => None, - } - } - - fn source_code(&self) -> Option<&dyn SourceCode> { - Some(&self.expression) - } - - fn labels(&self) -> Option>> { - Some(Box::new(self.location.labels().into_iter())) - } -} - -#[derive(Clone, Debug, Error)] -#[non_exhaustive] -enum RuleErrorKind { - #[error("rooted sub-glob in group")] - RootedSubGlob, - #[error("singular tree wildcard `**` in group")] - SingularTree, - #[error("singular zero-or-more wildcard `*` or `$` in group")] - SingularZeroOrMore, - #[error("adjacent component boundaries `/` or `**`")] - AdjacentBoundary, - #[error("adjacent zero-or-more wildcards `*` or `$`")] - AdjacentZeroOrMore, - #[error("oversized invariant expression")] - OversizedInvariant, - #[error("incompatible repetition bounds")] - IncompatibleBounds, -} - -#[derive(Clone, Copy, Debug)] -pub struct Checked { - inner: T, -} - -impl Checked { - pub fn release(self) -> T { - self.inner - } -} - -impl<'t> Checked> { - pub fn any(trees: I) -> Self - where - T: TokenTree<'t>, - I: IntoIterator>, - { - Checked { - // `token::any` constructs an alternative from the input token trees. The alternative - // is not checked, but the `any` combinator is explicitly allowed to ignore the subset - // of rules that may be violated by this construction. In particular, branches may or - // may not have roots such that the alternative can match overlapping directory trees. - inner: token::any( - trees - .into_iter() - .map(Checked::release) - .map(TokenTree::into_tokens), - ), - } - } -} - -impl<'t, A> Checked> { - pub fn into_owned(self) -> Checked> { - Checked { - inner: self.release().into_owned(), - } - } -} - -impl<'t, A> Checked> { - pub fn into_owned(self) -> Checked> { - Checked { - inner: self.release().into_owned(), - } - } -} - -impl<'t> Checked> { - pub fn partition(self) -> (PathBuf, Self) { - let tokenized = self.release(); - // `Tokenized::partition` does not violate rules. - let (path, tokenized) = tokenized.partition(); - (path, Checked { inner: tokenized }) - } -} - -impl AsRef for Checked { - fn as_ref(&self) -> &T { - &self.inner - } -} - -impl<'t, T> Pattern<'t> for Checked -where - T: TokenTree<'t>, -{ - type Tokens = T; - type Error = Infallible; -} - -impl<'t> From> for Checked> { - fn from(any: Any<'t>) -> Self { - let Any { tree, .. } = any; - tree - } -} - -impl<'t> From> for Checked> { - fn from(glob: Glob<'t>) -> Self { - let Glob { tree, .. } = glob; - tree - } -} - -impl<'t> TryFrom<&'t str> for Checked> { - type Error = BuildError; - - fn try_from(expression: &'t str) -> Result { - crate::parse_and_check(expression) - } -} - -pub fn check(tokenized: Tokenized) -> Result, RuleError> { - boundary(&tokenized)?; - bounds(&tokenized)?; - group(&tokenized)?; - size(&tokenized)?; - Ok(Checked { inner: tokenized }) -} - -fn boundary<'t>(tokenized: &Tokenized<'t>) -> Result<(), RuleError<'t>> { - if let Some((left, right)) = tokenized - .walk() - .group_by(|(position, _)| *position) - .into_iter() - .flat_map(|(_, group)| { - group - .map(|(_, token)| token) - .tuple_windows::<(_, _)>() - .filter(|(left, right)| { - left.is_component_boundary() && right.is_component_boundary() - }) - .map(|(left, right)| (*left.annotation(), *right.annotation())) - }) - .next() - { - Err(RuleError::new( - tokenized.expression().clone(), - RuleErrorKind::AdjacentBoundary, - CompositeSpan::spanned("here", left.union(&right)), - )) - } else { - Ok(()) - } -} - -fn group<'t>(tokenized: &Tokenized<'t>) -> Result<(), RuleError<'t>> { - use Terminals::{Only, StartEnd}; - - use crate::token::{ - TokenKind::{Separator, Wildcard}, - Wildcard::{Tree, ZeroOrMore}, - }; - - struct CorrelatedError { - kind: RuleErrorKind, - location: CorrelatedSpan, - } - - impl CorrelatedError { - fn new(kind: RuleErrorKind, outer: Option<&Token>, inner: &Token) -> Self { - CorrelatedError { - kind, - location: CorrelatedSpan::split_some( - outer.map(Token::annotation).copied().map(From::from), - *inner.annotation(), - ), - } - } - } - - #[derive(Clone, Copy, Default)] - struct Outer<'i, 't> { - left: Option<&'i Token<'t>>, - right: Option<&'i Token<'t>>, - } - - impl<'i, 't> Outer<'i, 't> { - pub fn push(self, left: Option<&'i Token<'t>>, right: Option<&'i Token<'t>>) -> Self { - Outer { - left: left.or(self.left), - right: right.or(self.right), - } - } - } - - fn has_starting_component_boundary<'t>(token: Option<&'t Token<'t>>) -> bool { - token.map_or(false, |token| { - token - .walk() - .starting() - .any(|(_, token)| token.is_component_boundary()) - }) - } - - fn has_ending_component_boundary<'t>(token: Option<&'t Token<'t>>) -> bool { - token.map_or(false, |token| { - token - .walk() - .ending() - .any(|(_, token)| token.is_component_boundary()) - }) - } - - fn has_starting_zom_token<'t>(token: Option<&'t Token<'t>>) -> bool { - token.map_or(false, |token| { - token - .walk() - .starting() - .any(|(_, token)| matches!(token.kind(), Wildcard(ZeroOrMore(_)))) - }) - } - - fn has_ending_zom_token<'t>(token: Option<&'t Token<'t>>) -> bool { - token.map_or(false, |token| { - token - .walk() - .ending() - .any(|(_, token)| matches!(token.kind(), Wildcard(ZeroOrMore(_)))) - }) - } - - fn diagnose<'i, 't>( - // This is a somewhat unusual API, but it allows the lifetime `'t` of the `Cow` to be - // properly forwarded to output values (`RuleError`). - #[allow(clippy::ptr_arg)] expression: &'i Cow<'t, str>, - token: &'i Token<'t>, - label: &'static str, - ) -> impl 'i + Copy + Fn(CorrelatedError) -> RuleError<'t> - where - 't: 'i, - { - move |CorrelatedError { kind, location }| { - RuleError::new( - expression.clone(), - kind, - CompositeSpan::correlated(label, *token.annotation(), location), - ) - } - } - - fn recurse<'i, 't, I>( - // This is a somewhat unusual API, but it allows the lifetime `'t` of the `Cow` to be - // properly forwarded to output values (`RuleError`). - #[allow(clippy::ptr_arg)] expression: &Cow<'t, str>, - tokens: I, - outer: Outer<'i, 't>, - ) -> Result<(), RuleError<'t>> - where - I: IntoIterator>, - 't: 'i, - { - for (left, token, right) in tokens.into_iter().adjacent().map(Adjacency::into_tuple) { - match token.kind() { - TokenKind::Alternative(ref alternative) => { - let outer = outer.push(left, right); - let diagnose = diagnose(expression, token, "in this alternative"); - for tokens in alternative.branches() { - if let Some(terminals) = tokens.terminals() { - check_group(terminals, outer).map_err(diagnose)?; - check_group_alternative(terminals, outer).map_err(diagnose)?; - } - recurse(expression, tokens.iter(), outer)?; - } - } - TokenKind::Repetition(ref repetition) => { - let outer = outer.push(left, right); - let diagnose = diagnose(expression, token, "in this repetition"); - let tokens = repetition.tokens(); - if let Some(terminals) = tokens.terminals() { - check_group(terminals, outer).map_err(diagnose)?; - check_group_repetition(terminals, outer, repetition.bounds()) - .map_err(diagnose)?; - } - recurse(expression, tokens.iter(), outer)?; - } - _ => {} - } - } - Ok(()) - } - - fn check_group<'t>( - terminals: Terminals<&Token>, - outer: Outer<'t, 't>, - ) -> Result<(), CorrelatedError> { - let Outer { left, right } = outer; - match terminals.map(|token| (token, token.kind())) { - // The group is preceded by component boundaries; disallow leading separators. - // - // For example, `foo/{bar,/}`. - Only((inner, Separator(_))) | StartEnd((inner, Separator(_)), _) - if has_ending_component_boundary(left) => - { - Err(CorrelatedError::new( - RuleErrorKind::AdjacentBoundary, - left, - inner, - )) - } - // The group is followed by component boundaries; disallow trailing - // separators. - // - // For example, `{foo,/}/bar`. - Only((inner, Separator(_))) | StartEnd(_, (inner, Separator(_))) - if has_starting_component_boundary(right) => - { - Err(CorrelatedError::new( - RuleErrorKind::AdjacentBoundary, - right, - inner, - )) - } - // Disallow singular tree tokens. - // - // For example, `{foo,bar,**}`. - Only((inner, Wildcard(Tree { .. }))) => Err(CorrelatedError::new( - RuleErrorKind::SingularTree, - None, - inner, - )), - // The group is preceded by component boundaries; disallow leading tree tokens. - // - // For example, `foo/{bar,**/baz}`. - StartEnd((inner, Wildcard(Tree { .. })), _) if has_ending_component_boundary(left) => { - Err(CorrelatedError::new( - RuleErrorKind::AdjacentBoundary, - left, - inner, - )) - } - // The group is followed by component boundaries; disallow trailing - // tree tokens. - // - // For example, `{foo,bar/**}/baz`. - StartEnd(_, (inner, Wildcard(Tree { .. }))) - if has_starting_component_boundary(right) => - { - Err(CorrelatedError::new( - RuleErrorKind::AdjacentBoundary, - right, - inner, - )) - } - // The group is prefixed by a zero-or-more token; disallow leading - // zero-or-more tokens. - // - // For example, `foo*{bar,*,baz}`. - Only((inner, Wildcard(ZeroOrMore(_)))) - | StartEnd((inner, Wildcard(ZeroOrMore(_))), _) - if has_ending_zom_token(left) => - { - Err(CorrelatedError::new( - RuleErrorKind::AdjacentZeroOrMore, - left, - inner, - )) - } - // The group is followed by a zero-or-more token; disallow trailing - // zero-or-more tokens. - // - // For example, `{foo,*,bar}*baz`. - Only((inner, Wildcard(ZeroOrMore(_)))) - | StartEnd(_, (inner, Wildcard(ZeroOrMore(_)))) - if has_starting_zom_token(right) => - { - Err(CorrelatedError::new( - RuleErrorKind::AdjacentZeroOrMore, - right, - inner, - )) - } - _ => Ok(()), - } - } - - fn check_group_alternative<'t>( - terminals: Terminals<&Token>, - outer: Outer<'t, 't>, - ) -> Result<(), CorrelatedError> { - let Outer { left, .. } = outer; - match terminals.map(|token| (token, token.kind())) { - // The alternative is preceded by a termination; disallow rooted sub-globs. - // - // For example, `{foo,/}` or `{foo,/bar}`. - Only((inner, Separator(_))) | StartEnd((inner, Separator(_)), _) if left.is_none() => { - Err(CorrelatedError::new( - RuleErrorKind::RootedSubGlob, - left, - inner, - )) - } - // The alternative is preceded by a termination; disallow rooted - // sub-globs. - // - // For example, `{/**/foo,bar}`. - Only((inner, Wildcard(Tree { has_root: true }))) - | StartEnd((inner, Wildcard(Tree { has_root: true })), _) - if left.is_none() => - { - Err(CorrelatedError::new( - RuleErrorKind::RootedSubGlob, - left, - inner, - )) - } - _ => Ok(()), - } - } - - fn check_group_repetition<'t>( - terminals: Terminals<&Token>, - outer: Outer<'t, 't>, - bounds: (usize, Option), - ) -> Result<(), CorrelatedError> { - let Outer { left, .. } = outer; - let (lower, _) = bounds; - match terminals.map(|token| (token, token.kind())) { - // The repetition is preceded by a termination; disallow rooted sub-globs with a zero - // lower bound. - // - // For example, ``. - Only((inner, Separator(_))) | StartEnd((inner, Separator(_)), _) - if left.is_none() && lower == 0 => - { - Err(CorrelatedError::new( - RuleErrorKind::RootedSubGlob, - left, - inner, - )) - } - // The repetition is preceded by a termination; disallow rooted - // sub-globs with a zero lower bound. - // - // For example, ``. - Only((inner, Wildcard(Tree { has_root: true }))) - | StartEnd((inner, Wildcard(Tree { has_root: true })), _) - if left.is_none() && lower == 0 => - { - Err(CorrelatedError::new( - RuleErrorKind::RootedSubGlob, - left, - inner, - )) - } - // The repetition begins and ends with a separator. - // - // For example, ``. - StartEnd((left, _), (right, _)) - if left.is_component_boundary() && right.is_component_boundary() => - { - Err(CorrelatedError::new( - RuleErrorKind::AdjacentBoundary, - Some(left), - right, - )) - } - // The repetition is a singular separator. - // - // For example, ``. - Only((token, Separator(_))) => Err(CorrelatedError::new( - RuleErrorKind::AdjacentBoundary, - None, - token, - )), - // The repetition is a singular zero-or-more wildcard. - // - // For example, `<*:1,>`. - Only((token, Wildcard(ZeroOrMore(_)))) => Err(CorrelatedError::new( - RuleErrorKind::SingularZeroOrMore, - None, - token, - )), - _ => Ok(()), - } - } - - recurse(tokenized.expression(), tokenized.tokens(), Outer::default()) -} - -fn bounds<'t>(tokenized: &Tokenized<'t>) -> Result<(), RuleError<'t>> { - if let Some((_, token)) = tokenized.walk().find(|(_, token)| match token.kind() { - TokenKind::Repetition(ref repetition) => { - let (lower, upper) = repetition.bounds(); - upper.map_or(false, |upper| upper < lower || upper == 0) - } - _ => false, - }) { - Err(RuleError::new( - tokenized.expression().clone(), - RuleErrorKind::IncompatibleBounds, - CompositeSpan::spanned("here", *token.annotation()), - )) - } else { - Ok(()) - } -} - -fn size<'t>(tokenized: &Tokenized<'t>) -> Result<(), RuleError<'t>> { - if let Some((_, token)) = tokenized - .walk() - // TODO: This is expensive. For each token tree encountered, the tree is traversed to - // determine its variance. If variant, the tree is traversed and queried again, - // revisiting the same tokens to recompute their local variance. - .find(|(_, token)| { - token - .variance::() - .as_invariance() - .map_or(false, |size| *size >= MAX_INVARIANT_SIZE) - }) - { - Err(RuleError::new( - tokenized.expression().clone(), - RuleErrorKind::OversizedInvariant, - CompositeSpan::spanned("here", *token.annotation()), - )) - } else { - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use crate::rule::{Adjacency, IteratorExt as _}; - - #[test] - fn adjacent() { - let mut adjacent = Option::::None.into_iter().adjacent(); - assert_eq!(adjacent.next(), None); - - let mut adjacent = Some(0i32).into_iter().adjacent(); - assert_eq!(adjacent.next(), Some(Adjacency::Only { item: 0 })); - assert_eq!(adjacent.next(), None); - - let mut adjacent = (0i32..3).adjacent(); - assert_eq!( - adjacent.next(), - Some(Adjacency::First { item: 0, right: 1 }) - ); - assert_eq!( - adjacent.next(), - Some(Adjacency::Middle { - left: 0, - item: 1, - right: 2 - }) - ); - assert_eq!(adjacent.next(), Some(Adjacency::Last { left: 1, item: 2 })); - assert_eq!(adjacent.next(), None); - } -} diff --git a/crates/turborepo-wax/src/token/mod.rs b/crates/turborepo-wax/src/token/mod.rs deleted file mode 100644 index 11e4a62e130c5..0000000000000 --- a/crates/turborepo-wax/src/token/mod.rs +++ /dev/null @@ -1,1091 +0,0 @@ -mod parse; -mod variance; - -use std::{ - borrow::Cow, - cmp, - collections::VecDeque, - mem, - ops::Deref, - path::{PathBuf, MAIN_SEPARATOR}, - slice, str, -}; - -use itertools::Itertools as _; - -pub use crate::token::{ - parse::{parse, Annotation, ParseError, ROOT_SEPARATOR_EXPRESSION}, - variance::{ - invariant_text_prefix, is_exhaustive, Boundedness, InvariantSize, InvariantText, Variance, - }, -}; -use crate::{ - token::variance::{ - CompositeBreadth, CompositeDepth, ConjunctiveVariance, DisjunctiveVariance, - IntoInvariantText, Invariance, UnitBreadth, UnitDepth, UnitVariance, - }, - StrExt as _, PATHS_ARE_CASE_INSENSITIVE, -}; - -pub trait TokenTree<'t>: Sized { - type Annotation; - - fn into_tokens(self) -> Vec>; - - fn tokens(&self) -> &[Token<'t, Self::Annotation>]; -} - -#[derive(Clone, Debug)] -pub struct Tokenized<'t, A = Annotation> { - expression: Cow<'t, str>, - tokens: Vec>, -} - -impl<'t, A> Tokenized<'t, A> { - pub fn into_owned(self) -> Tokenized<'static, A> { - let Tokenized { expression, tokens } = self; - Tokenized { - expression: expression.into_owned().into(), - tokens: tokens.into_iter().map(Token::into_owned).collect(), - } - } - - pub fn expression(&self) -> &Cow<'t, str> { - &self.expression - } - - pub fn variance(&self) -> Variance - where - T: Invariance, - for<'i> &'i Token<'t, A>: UnitVariance, - { - self.tokens().iter().conjunctive_variance() - } - - pub fn walk(&self) -> Walk<'_, 't, A> { - Walk::from(&self.tokens) - } -} - -impl<'t> Tokenized<'t, Annotation> { - pub fn partition(self) -> (PathBuf, Self) { - fn pop_expression_bytes(expression: &str, n: usize) -> &str { - let n = cmp::min(expression.len(), n); - str::from_utf8(&expression.as_bytes()[n..]) - .expect("span offset split UTF-8 byte sequence") - } - - let Tokenized { - expression, - mut tokens, - } = self; - - // Get the invariant prefix and its upper bound for the token sequence. - let prefix = variance::invariant_text_prefix(tokens.iter()).into(); - let n = variance::invariant_text_prefix_upper_bound(&tokens); - let mut offset: usize = tokens - .iter() - .take(n) - .map(|token| token.annotation().1) - .sum(); - - // Drain invariant tokens from the beginning of the token sequence and unroot - // any tokens at the beginning of the variant sequence (tree wildcards). - // Finally, translate spans and discard the corresponding invariant - // bytes in the expression. - tokens.drain(0..n); - if tokens.first_mut().map_or(false, Token::unroot) { - // TODO: The relationship between roots, the unrooting operation, and the span - // in an expression that represents such a root (if any) is - // not captured by these APIs very well. Perhaps `unroot` - // should do more here? Pop additional bytes for the root separator - // expression if the initial token has lost a root. - offset += ROOT_SEPARATOR_EXPRESSION.len(); - } - for token in tokens.iter_mut() { - let start = token.annotation().0.saturating_sub(offset); - token.annotation.0 = start; - } - let expression = match expression { - Cow::Borrowed(expression) => pop_expression_bytes(expression, offset).into(), - Cow::Owned(expression) => { - String::from(pop_expression_bytes(&expression, offset)).into() - } - }; - - (prefix, Tokenized { expression, tokens }) - } -} - -impl<'t, A> TokenTree<'t> for Tokenized<'t, A> { - type Annotation = A; - - fn into_tokens(self) -> Vec> { - let Tokenized { tokens, .. } = self; - tokens - } - - fn tokens(&self) -> &[Token<'t, Self::Annotation>] { - &self.tokens - } -} - -#[derive(Clone, Debug)] -pub struct Token<'t, A = Annotation> { - kind: TokenKind<'t, A>, - annotation: A, -} - -impl<'t, A> Token<'t, A> { - fn new(kind: TokenKind<'t, A>, annotation: A) -> Self { - Token { kind, annotation } - } - - pub fn into_owned(self) -> Token<'static, A> { - let Token { kind, annotation } = self; - Token { - kind: kind.into_owned(), - annotation, - } - } - - pub fn unannotate(self) -> Token<'t, ()> { - let Token { kind, .. } = self; - Token { - kind: kind.unannotate(), - annotation: (), - } - } - - pub fn unroot(&mut self) -> bool { - self.kind.unroot() - } - - pub fn kind(&self) -> &TokenKind<'t, A> { - self.as_ref() - } - - pub fn annotation(&self) -> &A { - self.as_ref() - } - - pub fn walk(&self) -> Walk<'_, 't, A> { - Walk::from(self) - } - - pub fn has_root(&self) -> bool { - self.walk().starting().any(|(_, token)| { - matches!( - token.kind(), - TokenKind::Separator(_) | TokenKind::Wildcard(Wildcard::Tree { has_root: true }), - ) - }) - } - - pub fn has_component_boundary(&self) -> bool { - self.walk().any(|(_, token)| token.is_component_boundary()) - } -} - -impl<'t, A> AsRef> for Token<'t, A> { - fn as_ref(&self) -> &TokenKind<'t, A> { - &self.kind - } -} - -impl<'t, A> AsRef for Token<'t, A> { - fn as_ref(&self) -> &A { - &self.annotation - } -} - -impl<'t, A> Deref for Token<'t, A> { - type Target = TokenKind<'t, A>; - - fn deref(&self) -> &Self::Target { - self.as_ref() - } -} - -impl<'t> From> for Token<'t, ()> { - fn from(kind: TokenKind<'t, ()>) -> Self { - Token { - kind, - annotation: (), - } - } -} - -impl<'t, A> TokenTree<'t> for Token<'t, A> { - type Annotation = A; - - fn into_tokens(self) -> Vec> { - vec![self] - } - - fn tokens(&self) -> &[Token<'t, Self::Annotation>] { - slice::from_ref(self) - } -} - -impl<'i, 't, A> UnitBreadth for &'i Token<'t, A> { - fn unit_breadth(self) -> Boundedness { - self.kind.unit_breadth() - } -} - -impl<'i, 't, A> UnitDepth for &'i Token<'t, A> { - fn unit_depth(self) -> Boundedness { - self.kind.unit_depth() - } -} - -impl<'i, 't, A, T> UnitVariance for &'i Token<'t, A> -where - &'i TokenKind<'t, A>: UnitVariance, - T: Invariance, -{ - fn unit_variance(self) -> Variance { - self.kind.unit_variance() - } -} - -#[derive(Clone, Debug)] -pub enum TokenKind<'t, A = ()> { - Alternative(Alternative<'t, A>), - Class(Class), - Literal(Literal<'t>), - Repetition(Repetition<'t, A>), - Separator(Separator), - Wildcard(Wildcard), -} - -impl<'t, A> TokenKind<'t, A> { - pub fn into_owned(self) -> TokenKind<'static, A> { - match self { - TokenKind::Alternative(alternative) => alternative.into_owned().into(), - TokenKind::Class(class) => TokenKind::Class(class), - TokenKind::Literal(Literal { - text, - is_case_insensitive, - }) => TokenKind::Literal(Literal { - text: text.into_owned().into(), - is_case_insensitive, - }), - TokenKind::Repetition(repetition) => repetition.into_owned().into(), - TokenKind::Separator(_) => TokenKind::Separator(Separator), - TokenKind::Wildcard(wildcard) => TokenKind::Wildcard(wildcard), - } - } - - pub fn unannotate(self) -> TokenKind<'t, ()> { - match self { - TokenKind::Alternative(alternative) => TokenKind::Alternative(alternative.unannotate()), - TokenKind::Class(class) => TokenKind::Class(class), - TokenKind::Literal(literal) => TokenKind::Literal(literal), - TokenKind::Repetition(repetition) => TokenKind::Repetition(repetition.unannotate()), - TokenKind::Separator(_) => TokenKind::Separator(Separator), - TokenKind::Wildcard(wildcard) => TokenKind::Wildcard(wildcard), - } - } - - pub fn unroot(&mut self) -> bool { - match self { - TokenKind::Wildcard(Wildcard::Tree { ref mut has_root }) => { - mem::replace(has_root, false) - } - _ => false, - } - } - - pub fn variance(&self) -> Variance - where - T: Invariance, - for<'i> &'i TokenKind<'t, A>: UnitVariance, - { - self.unit_variance() - } - - pub fn has_sub_tokens(&self) -> bool { - // It is not necessary to detect empty branches or sub-expressions. - matches!(self, TokenKind::Alternative(_) | TokenKind::Repetition(_)) - } - - pub fn is_component_boundary(&self) -> bool { - matches!( - self, - TokenKind::Separator(_) | TokenKind::Wildcard(Wildcard::Tree { .. }) - ) - } - - pub fn is_capturing(&self) -> bool { - use TokenKind::{Alternative, Class, Repetition, Wildcard}; - - matches!( - self, - Alternative(_) | Class(_) | Repetition(_) | Wildcard(_), - ) - } -} - -impl<'t, A> From> for TokenKind<'t, A> { - fn from(alternative: Alternative<'t, A>) -> Self { - TokenKind::Alternative(alternative) - } -} - -impl From for TokenKind<'_, A> { - fn from(class: Class) -> Self { - TokenKind::Class(class) - } -} - -impl<'t, A> From> for TokenKind<'t, A> { - fn from(repetition: Repetition<'t, A>) -> Self { - TokenKind::Repetition(repetition) - } -} - -impl From for TokenKind<'static, A> { - fn from(wildcard: Wildcard) -> Self { - TokenKind::Wildcard(wildcard) - } -} - -impl<'i, 't, A> UnitBreadth for &'i TokenKind<'t, A> { - fn unit_breadth(self) -> Boundedness { - match self { - TokenKind::Alternative(ref alternative) => alternative.unit_breadth(), - TokenKind::Class(ref class) => class.unit_breadth(), - TokenKind::Literal(ref literal) => literal.unit_breadth(), - TokenKind::Repetition(ref repetition) => repetition.unit_breadth(), - TokenKind::Separator(ref separator) => separator.unit_breadth(), - TokenKind::Wildcard(ref wildcard) => wildcard.unit_breadth(), - } - } -} - -impl<'i, 't, A> UnitDepth for &'i TokenKind<'t, A> { - fn unit_depth(self) -> Boundedness { - match self { - TokenKind::Alternative(ref alternative) => alternative.unit_depth(), - TokenKind::Class(ref class) => class.unit_depth(), - TokenKind::Literal(ref literal) => literal.unit_depth(), - TokenKind::Repetition(ref repetition) => repetition.unit_depth(), - TokenKind::Separator(ref separator) => separator.unit_depth(), - TokenKind::Wildcard(ref wildcard) => wildcard.unit_depth(), - } - } -} - -impl<'i, 't, A, T> UnitVariance for &'i TokenKind<'t, A> -where - &'i Class: UnitVariance, - &'i Literal<'t>: UnitVariance, - &'i Separator: UnitVariance, - T: Invariance, -{ - fn unit_variance(self) -> Variance { - match self { - TokenKind::Alternative(ref alternative) => alternative.unit_variance(), - TokenKind::Class(ref class) => class.unit_variance(), - TokenKind::Literal(ref literal) => literal.unit_variance(), - TokenKind::Repetition(ref repetition) => repetition.unit_variance(), - TokenKind::Separator(ref separator) => separator.unit_variance(), - TokenKind::Wildcard(_) => Variance::Variant(Boundedness::Open), - } - } -} - -#[derive(Clone, Debug)] -pub struct Alternative<'t, A = ()>(Vec>>); - -impl<'t, A> Alternative<'t, A> { - pub fn into_owned(self) -> Alternative<'static, A> { - Alternative( - self.0 - .into_iter() - .map(|tokens| tokens.into_iter().map(Token::into_owned).collect()) - .collect(), - ) - } - - pub fn unannotate(self) -> Alternative<'t, ()> { - let Alternative(branches) = self; - Alternative( - branches - .into_iter() - .map(|branch| branch.into_iter().map(Token::unannotate).collect()) - .collect(), - ) - } - - pub fn branches(&self) -> &Vec>> { - &self.0 - } -} - -impl<'t, A> From>>> for Alternative<'t, A> { - fn from(alternatives: Vec>>) -> Self { - Alternative(alternatives) - } -} - -impl<'i, 't, A> UnitBreadth for &'i Alternative<'t, A> { - fn unit_breadth(self) -> Boundedness { - self.branches() - .iter() - .map(|tokens| tokens.iter().composite_breadth()) - .composite_breadth() - } -} - -impl<'i, 't, A> UnitDepth for &'i Alternative<'t, A> { - fn unit_depth(self) -> Boundedness { - self.branches() - .iter() - .map(|tokens| tokens.iter().composite_depth()) - .composite_depth() - } -} - -impl<'i, 't, A, T> UnitVariance for &'i Alternative<'t, A> -where - T: Invariance, - &'i Token<'t, A>: UnitVariance, -{ - fn unit_variance(self) -> Variance { - self.branches() - .iter() - .map(|tokens| tokens.iter().conjunctive_variance()) - .disjunctive_variance() - } -} - -#[derive(Clone, Copy, Debug)] -pub enum Archetype { - Character(char), - Range(char, char), -} - -impl Archetype { - fn domain_variance(&self) -> Variance { - match self { - Archetype::Character(x) => { - if PATHS_ARE_CASE_INSENSITIVE { - Variance::Variant(Boundedness::Closed) - } else { - Variance::Invariant(*x) - } - } - Archetype::Range(a, b) => { - if (a != b) || PATHS_ARE_CASE_INSENSITIVE { - Variance::Variant(Boundedness::Closed) - } else { - Variance::Invariant(*a) - } - } - } - } -} - -impl From for Archetype { - fn from(literal: char) -> Self { - Archetype::Character(literal) - } -} - -impl From<(char, char)> for Archetype { - fn from(range: (char, char)) -> Self { - Archetype::Range(range.0, range.1) - } -} - -impl<'i, 't> UnitVariance> for &'i Archetype { - fn unit_variance(self) -> Variance> { - self.domain_variance() - .map_invariance(|invariance| invariance.to_string().into_nominal_text()) - } -} - -impl<'i> UnitVariance for &'i Archetype { - fn unit_variance(self) -> Variance { - // This is pessimistic and assumes that the code point will require four bytes - // when encoded as UTF-8. This is technically possible, but most - // commonly only one or two bytes will be required. - self.domain_variance().map_invariance(|_| 4.into()) - } -} - -#[derive(Clone, Debug)] -pub struct Class { - is_negated: bool, - archetypes: Vec, -} - -impl Class { - pub fn archetypes(&self) -> &[Archetype] { - &self.archetypes - } - - pub fn is_negated(&self) -> bool { - self.is_negated - } -} - -impl<'i> UnitBreadth for &'i Class {} - -impl<'i> UnitDepth for &'i Class {} - -impl<'i, T> UnitVariance for &'i Class -where - &'i Archetype: UnitVariance, - T: Invariance, -{ - fn unit_variance(self) -> Variance { - if self.is_negated { - // It is not feasible to encode a character class that matches all - // UTF-8 text and therefore nothing when negated, and so a character - // class must be variant if it is negated. - Variance::Variant(Boundedness::Closed) - } else { - // TODO: This ignores casing groups, such as in the pattern `[aA]`. - self.archetypes().iter().disjunctive_variance() - } - } -} - -#[derive(Clone, Copy, Debug)] -pub enum Evaluation { - Eager, - Lazy, -} - -#[derive(Clone, Debug)] -pub struct Literal<'t> { - text: Cow<'t, str>, - is_case_insensitive: bool, -} - -impl<'t> Literal<'t> { - pub fn text(&self) -> &str { - self.text.as_ref() - } - - fn domain_variance(&self) -> Variance<&Cow<'t, str>> { - if self.has_variant_casing() { - Variance::Variant(Boundedness::Closed) - } else { - Variance::Invariant(&self.text) - } - } - - pub fn is_case_insensitive(&self) -> bool { - self.is_case_insensitive - } - - pub fn has_variant_casing(&self) -> bool { - // If path case sensitivity agrees with the literal case sensitivity, then the - // literal is not variant. Otherwise, the literal is variant if it - // contains characters with casing. - (PATHS_ARE_CASE_INSENSITIVE != self.is_case_insensitive) && self.text.has_casing() - } -} - -impl<'i, 't> UnitBreadth for &'i Literal<'t> {} - -impl<'i, 't> UnitDepth for &'i Literal<'t> {} - -impl<'i, 't> UnitVariance> for &'i Literal<'t> { - fn unit_variance(self) -> Variance> { - self.domain_variance() - .map_invariance(|invariance| invariance.clone().into_nominal_text()) - } -} - -impl<'i, 't> UnitVariance for &'i Literal<'t> { - fn unit_variance(self) -> Variance { - self.domain_variance() - .map_invariance(|invariance| invariance.as_bytes().len().into()) - } -} - -#[derive(Clone, Debug)] -pub struct Repetition<'t, A = ()> { - tokens: Vec>, - lower: usize, - // This representation is not ideal, as it does not statically enforce the invariant that the - // upper bound is greater than or equal to the lower bound. For example, this field could - // instead be a summand. However, tokens must closely resemble their glob expression - // representations so that errors in expressions can be deferred and presented more clearly. - // Failures in the parser are difficult to describe. - upper: Option, -} - -impl<'t, A> Repetition<'t, A> { - pub fn into_owned(self) -> Repetition<'static, A> { - let Repetition { - tokens, - lower, - upper, - } = self; - Repetition { - tokens: tokens.into_iter().map(Token::into_owned).collect(), - lower, - upper, - } - } - - pub fn unannotate(self) -> Repetition<'t, ()> { - let Repetition { - tokens, - lower, - upper, - } = self; - Repetition { - tokens: tokens.into_iter().map(Token::unannotate).collect(), - lower, - upper, - } - } - - pub fn tokens(&self) -> &Vec> { - &self.tokens - } - - pub fn bounds(&self) -> (usize, Option) { - (self.lower, self.upper) - } - - pub fn is_converged(&self) -> bool { - self.upper.map_or(false, |upper| self.lower == upper) - } - - fn walk(&self) -> Walk<'_, 't, A> { - Walk::from(&self.tokens) - } -} - -impl<'i, 't, A> UnitBreadth for &'i Repetition<'t, A> { - fn unit_breadth(self) -> Boundedness { - self.tokens().iter().composite_breadth() - } -} - -impl<'i, 't, A> UnitDepth for &'i Repetition<'t, A> { - fn unit_depth(self) -> Boundedness { - let (_, upper) = self.bounds(); - if upper.is_none() && self.walk().any(|(_, token)| token.is_component_boundary()) { - Boundedness::Open - } else { - Boundedness::Closed - } - } -} - -impl<'i, 't, A, T> UnitVariance for &'i Repetition<'t, A> -where - T: Invariance, - &'i Token<'t, A>: UnitVariance, -{ - fn unit_variance(self) -> Variance { - use Boundedness::Open; - use TokenKind::Separator; - use Variance::Variant; - - let variance = self - .tokens() - .iter() - // Coalesce tokens with open variance with separators. This isn't destructive and - // doesn't affect invariance, because this only happens in the presence of open - // variance, which means that the repetition is variant (and has no invariant size or - // text). - .coalesce(|left, right| { - match ( - (left.kind(), left.unit_variance()), - (right.kind(), right.unit_variance()), - ) { - ((Separator(_), _), (_, Variant(Open))) => Ok(right), - ((_, Variant(Open)), (Separator(_), _)) => Ok(left), - _ => Err((left, right)), - } - }) - .conjunctive_variance(); - match self.upper { - // Repeating invariance can cause overflows, very large allocations, - // and very inefficient comparisons (e.g., comparing very large - // strings). This is detected by both `encode::compile` and - // `rule::check` (in distinct but similar ways). Querying token - // trees for their invariance must be done with care (after using - // these functions) to avoid expanding pathological invariant - // expressions like ``. - Some(_) if self.is_converged() => { - variance.map_invariance(|invariance| invariance * self.lower) - } - _ => variance + Variant(Open), - } - } -} - -#[derive(Clone, Copy, Debug)] -pub struct Separator; - -impl Separator { - pub fn invariant_text() -> String { - MAIN_SEPARATOR.to_string() - } -} - -impl<'i> UnitBreadth for &'i Separator {} - -impl<'i> UnitDepth for &'i Separator {} - -impl<'i, 't> UnitVariance> for &'i Separator { - fn unit_variance(self) -> Variance> { - Variance::Invariant(Separator::invariant_text().into_structural_text()) - } -} - -impl<'i> UnitVariance for &'i Separator { - fn unit_variance(self) -> Variance { - Variance::Invariant(Separator::invariant_text().as_bytes().len().into()) - } -} - -#[derive(Clone, Debug)] -pub enum Wildcard { - One, - ZeroOrMore(Evaluation), - Tree { has_root: bool }, -} - -impl<'i> UnitBreadth for &'i Wildcard { - fn unit_breadth(self) -> Boundedness { - match self { - Wildcard::One => Boundedness::Closed, - _ => Boundedness::Open, - } - } -} - -impl<'i> UnitDepth for &'i Wildcard { - fn unit_depth(self) -> Boundedness { - match self { - Wildcard::Tree { .. } => Boundedness::Open, - _ => Boundedness::Closed, - } - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Position { - Conjunctive { depth: usize }, - Disjunctive { depth: usize, branch: usize }, -} - -impl Position { - pub fn depth(&self) -> usize { - match self { - Position::Conjunctive { ref depth } | Position::Disjunctive { ref depth, .. } => *depth, - } - } - - // This may appear to operate in place. - #[must_use] - fn converge(self) -> Self { - match self { - Position::Conjunctive { depth } | Position::Disjunctive { depth, .. } => { - Position::Conjunctive { depth: depth + 1 } - } - } - } - - // This may appear to operate in place. - #[must_use] - fn diverge(self, branch: usize) -> Self { - match self { - Position::Conjunctive { depth } | Position::Disjunctive { depth, .. } => { - Position::Disjunctive { - depth: depth + 1, - branch, - } - } - } - } -} - -impl Default for Position { - fn default() -> Self { - Position::Conjunctive { depth: 0 } - } -} - -#[derive(Clone, Debug)] -pub struct Walk<'i, 't, A> { - buffer: VecDeque<(Position, &'i Token<'t, A>)>, -} - -impl<'i, 't, A> Walk<'i, 't, A> -where - 't: 'i, - A: 't, -{ - pub fn starting(self) -> impl 'i + Iterator)> { - self.peekable().batching(|tokens| { - if let Some((position, token)) = tokens.next() { - tokens - .peeking_take_while(|(next, _)| *next == position) - .for_each(drop); - Some((position, token)) - } else { - None - } - }) - } - - pub fn ending(self) -> impl 'i + Iterator)> { - self.peekable().batching(|tokens| { - if let Some((position, _)) = tokens.peek().copied() { - tokens - .peeking_take_while(|(next, _)| *next == position) - .last() - } else { - None - } - }) - } -} - -impl<'i, 't, A> From<&'i Token<'t, A>> for Walk<'i, 't, A> { - fn from(token: &'i Token<'t, A>) -> Self { - Walk { - buffer: Some((Position::default(), token)).into_iter().collect(), - } - } -} - -impl<'i, 't, A> From<&'i Vec>> for Walk<'i, 't, A> { - fn from(tokens: &'i Vec>) -> Self { - Walk { - buffer: tokens - .iter() - .map(|token| (Position::default(), token)) - .collect(), - } - } -} - -impl<'i, 't, A> Iterator for Walk<'i, 't, A> -where - 't: 'i, - A: 't, -{ - type Item = (Position, &'i Token<'t, A>); - - fn next(&mut self) -> Option { - if let Some((position, token)) = self.buffer.pop_front() { - match token.kind() { - TokenKind::Alternative(ref alternative) => { - self.buffer - .extend(alternative.branches().iter().enumerate().flat_map( - |(branch, tokens)| { - tokens - .iter() - .map(move |token| (position.diverge(branch), token)) - }, - )); - } - TokenKind::Repetition(ref repetition) => { - self.buffer.extend( - repetition - .tokens() - .iter() - .map(|token| (position.converge(), token)), - ); - } - _ => {} - } - Some((position, token)) - } else { - None - } - } -} - -#[derive(Clone, Debug)] -pub struct LiteralSequence<'i, 't>(Vec<&'i Literal<'t>>); - -impl<'i, 't> LiteralSequence<'i, 't> { - pub fn literals(&self) -> &[&'i Literal<'t>] { - self.0.as_ref() - } - - pub fn text(&self) -> Cow<'t, str> { - if self.literals().len() == 1 { - self.literals().first().unwrap().text.clone() - } else { - self.literals() - .iter() - .map(|literal| &literal.text) - .join("") - .into() - } - } - - #[cfg(any(unix, windows))] - pub fn is_semantic_literal(&self) -> bool { - matches!(self.text().as_ref(), "." | "..") - } - - #[cfg(not(any(unix, windows)))] - pub fn is_semantic_literal(&self) -> bool { - false - } -} - -#[derive(Debug)] -pub struct Component<'i, 't, A = ()>(Vec<&'i Token<'t, A>>); - -impl<'i, 't, A> Component<'i, 't, A> { - pub fn tokens(&self) -> &[&'i Token<'t, A>] { - self.0.as_ref() - } - - pub fn literal(&self) -> Option> { - if self.0.is_empty() { - None - } else { - self.tokens() - .iter() - .all(|token| matches!(token.kind(), TokenKind::Literal(_))) - .then(|| { - LiteralSequence( - self.tokens() - .iter() - .map(|token| match token.kind() { - TokenKind::Literal(ref literal) => literal, - _ => unreachable!(), // See predicate above. - }) - .collect(), - ) - }) - } - } - - pub fn variance(&self) -> Variance - where - T: Invariance, - &'i Token<'t, A>: UnitVariance, - { - self.0.iter().copied().conjunctive_variance() - } - - pub fn depth(&self) -> Boundedness { - self.0.iter().copied().composite_depth() - } -} - -impl<'i, 't, A> Clone for Component<'i, 't, A> { - fn clone(&self) -> Self { - Component(self.0.clone()) - } -} - -pub fn any<'t, A, I>(tokens: I) -> Token<'t, ()> -where - I: IntoIterator, - I::Item: IntoIterator>, -{ - Token { - kind: Alternative( - tokens - .into_iter() - .map(|tokens| tokens.into_iter().map(Token::unannotate).collect()) - .collect(), - ) - .into(), - annotation: (), - } -} - -pub fn components<'i, 't, A, I>(tokens: I) -> impl Iterator> -where - 't: 'i, - A: 't, - I: IntoIterator>, -{ - tokens.into_iter().peekable().batching(|tokens| { - let mut first = tokens.next(); - while matches!(first.map(Token::kind), Some(TokenKind::Separator(_))) { - first = tokens.next(); - } - first.map(|first| match first.kind() { - TokenKind::Wildcard(Wildcard::Tree { .. }) => Component(vec![first]), - _ => Component( - Some(first) - .into_iter() - .chain(tokens.peeking_take_while(|token| !token.is_component_boundary())) - .collect(), - ), - }) - }) -} - -// TODO: This implementation allocates many `Vec`s. -pub fn literals<'i, 't, A, I>( - tokens: I, -) -> impl Iterator, LiteralSequence<'i, 't>)> -where - 't: 'i, - A: 't, - I: IntoIterator>, -{ - components(tokens).flat_map(|component| { - if let Some(literal) = component.literal() { - vec![(component, literal)] - } else { - component - .tokens() - .iter() - .filter_map(|token| match token.kind() { - TokenKind::Alternative(ref alternative) => Some( - alternative - .branches() - .iter() - .flat_map(literals) - .collect::>(), - ), - TokenKind::Repetition(ref repetition) => { - Some(literals(repetition.tokens()).collect::>()) - } - _ => None, - }) - .flatten() - .collect::>() - } - }) -} - -#[cfg(test)] -mod tests { - use crate::token::{self, TokenKind, TokenTree}; - - #[test] - fn literal_case_insensitivity() { - let tokenized = token::parse("(?-i)../foo/(?i)**/bar/**(?-i)/baz/*(?i)qux").unwrap(); - let literals: Vec<_> = tokenized - .tokens() - .iter() - .filter_map(|token| match token.kind { - TokenKind::Literal(ref literal) => Some(literal), - _ => None, - }) - .collect(); - - assert!(!literals[0].is_case_insensitive); // `..` - assert!(!literals[1].is_case_insensitive); // `foo` - assert!(literals[2].is_case_insensitive); // `bar` - assert!(!literals[3].is_case_insensitive); // `baz` - assert!(literals[4].is_case_insensitive); // `qux` - } -} diff --git a/crates/turborepo-wax/src/token/parse.rs b/crates/turborepo-wax/src/token/parse.rs deleted file mode 100644 index a514c8c71fcd1..0000000000000 --- a/crates/turborepo-wax/src/token/parse.rs +++ /dev/null @@ -1,549 +0,0 @@ -use std::{ - borrow::Cow, - fmt::{self, Display, Formatter}, - str::FromStr, -}; - -#[cfg(feature = "miette")] -use miette::{self, Diagnostic, LabeledSpan, SourceCode}; -use nom::error::{VerboseError as NomError, VerboseErrorKind as NomErrorKind}; -use pori::{Located, Location, Stateful}; -use thiserror::Error; - -use crate::{ - diagnostics::{LocatedError, Span}, - token::{ - Alternative, Archetype, Class, Evaluation, Literal, Repetition, Separator, Token, - TokenKind, Tokenized, Wildcard, - }, - PATHS_ARE_CASE_INSENSITIVE, -}; - -pub type Annotation = Span; - -type Expression<'i> = Located<'i, str>; -type Input<'i> = Stateful, ParserState>; -type ErrorStack<'i> = NomError>; -type ErrorMode<'i> = nom::Err>; - -pub const ROOT_SEPARATOR_EXPRESSION: &str = "/"; - -#[derive(Clone, Debug)] -pub struct ErrorEntry<'t> { - fragment: Cow<'t, str>, - location: usize, - kind: NomErrorKind, -} - -impl<'t> ErrorEntry<'t> { - pub fn into_owned(self) -> ErrorEntry<'static> { - let ErrorEntry { - fragment, - location, - kind, - } = self; - ErrorEntry { - fragment: fragment.into_owned().into(), - location, - kind, - } - } -} - -impl<'t> From<(Input<'t>, NomErrorKind)> for ErrorEntry<'t> { - fn from((input, kind): (Input<'t>, NomErrorKind)) -> Self { - let location = input.location(); - ErrorEntry { - fragment: input.into_data().into(), - location, - kind, - } - } -} - -#[cfg(feature = "miette")] -impl From> for LabeledSpan { - fn from(error: ErrorEntry<'_>) -> Self { - let span = error.span(); - LabeledSpan::new_with_span(Some(format!("{}", error)), span) - } -} - -impl Display for ErrorEntry<'_> { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self.kind { - NomErrorKind::Char(expected) => { - if let Some(got) = self.fragment.chars().next() { - write!(f, "expected `{}`, got `{}`", expected, got) - } else { - write!(f, "expected `{}`, got end of input", expected) - } - } - NomErrorKind::Context(context) => write!(f, "in context `{}`", context), - NomErrorKind::Nom(parser) => write!(f, "in sub-parser `{:?}`", parser), - } - } -} - -impl LocatedError for ErrorEntry<'_> { - fn span(&self) -> Span { - (self.location, 1) - } -} - -/// Describes errors that occur when parsing a glob expression. -/// -/// Common examples of glob expressions that cannot be parsed are alternative -/// and repetition patterns with missing delimiters and ambiguous patterns, such -/// as `src/***/*.rs` or `{.local,.config/**/*.toml`. -#[derive(Clone, Debug, Error)] -#[error("failed to parse glob expression")] -pub struct ParseError<'t> { - expression: Cow<'t, str>, - locations: Vec>, -} - -impl<'t> ParseError<'t> { - fn new(expression: &'t str, error: ErrorMode<'t>) -> Self { - match error { - ErrorMode::Incomplete(_) => { - panic!("unexpected parse error: incomplete input") - } - ErrorMode::Error(stack) | ErrorMode::Failure(stack) => ParseError { - expression: expression.into(), - locations: stack.errors.into_iter().map(From::from).collect(), - }, - } - } - - /// Clones any borrowed data into an owning instance. - pub fn into_owned(self) -> ParseError<'static> { - let ParseError { - expression, - locations, - } = self; - ParseError { - expression: expression.into_owned().into(), - locations: locations.into_iter().map(ErrorEntry::into_owned).collect(), - } - } - - pub fn locations(&self) -> &[ErrorEntry<'t>] { - &self.locations - } - - /// Gets the glob expression that failed to parse. - pub fn expression(&self) -> &str { - self.expression.as_ref() - } -} - -#[cfg(feature = "miette")] -#[cfg_attr(docsrs, doc(cfg(feature = "miette")))] -impl Diagnostic for ParseError<'_> { - fn code<'a>(&'a self) -> Option> { - Some(Box::new("wax::glob::parse")) - } - - fn source_code(&self) -> Option<&dyn SourceCode> { - Some(&self.expression) - } - - fn labels(&self) -> Option + '_>> { - Some(Box::new(self.locations.iter().cloned().map(From::from))) - } -} - -#[derive(Clone, Copy, Debug, Default)] -struct ParserState { - flags: FlagState, - subexpression: usize, -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -struct FlagState { - is_case_insensitive: bool, -} - -impl Default for FlagState { - fn default() -> Self { - FlagState { - is_case_insensitive: PATHS_ARE_CASE_INSENSITIVE, - } - } -} - -#[derive(Clone, Copy, Debug)] -enum FlagToggle { - CaseInsensitive(bool), -} - -pub fn parse(expression: &str) -> Result { - use nom::{ - branch, bytes::complete as bytes, character::complete as character, combinator, error, - multi, sequence, IResult, Parser, - }; - - use crate::token::parse::FlagToggle::CaseInsensitive; - - type ParseResult<'i, O> = IResult, O, ErrorStack<'i>>; - - fn boe(input: Input) -> ParseResult { - if input.state.subexpression == input.location() { - Ok((input, input)) - } else { - Err(ErrorMode::Error(ErrorStack { - errors: vec![(input, NomErrorKind::Context("beginning of expression"))], - })) - } - } - - fn flags<'i, F>( - mut toggle: impl FnMut(FlagToggle) -> F, - ) -> impl FnMut(Input<'i>) -> ParseResult<'i, ()> - where - F: Parser, (), ErrorStack<'i>>, - { - move |input| { - let (input, _) = multi::many0(sequence::delimited( - bytes::tag("(?"), - multi::many1(branch::alt(( - sequence::tuple((bytes::tag("i"), toggle(CaseInsensitive(true)))), - sequence::tuple((bytes::tag("-i"), toggle(CaseInsensitive(false)))), - ))), - bytes::tag(")"), - ))(input)?; - Ok((input, ())) - } - } - - // Explicit lifetimes prevent inference errors. - #[allow(clippy::needless_lifetimes)] - fn flags_with_state<'i>(input: Input<'i>) -> ParseResult<'i, ()> { - flags(move |toggle| { - move |mut input: Input<'i>| { - match toggle { - CaseInsensitive(toggle) => { - input.state.flags.is_case_insensitive = toggle; - } - } - Ok((input, ())) - } - })(input) - } - - // Explicit lifetimes prevent inference errors. - #[allow(clippy::needless_lifetimes)] - fn flags_without_state<'i>(input: Input<'i>) -> ParseResult<'i, ()> { - flags(move |_| move |input: Input<'i>| Ok((input, ())))(input) - } - - fn literal(input: Input) -> ParseResult> { - combinator::map( - combinator::verify( - bytes::escaped_transform( - bytes::is_not("/?*$:<>()[]{},\\"), - '\\', - branch::alt(( - combinator::value("?", bytes::tag("?")), - combinator::value("*", bytes::tag("*")), - combinator::value("$", bytes::tag("$")), - combinator::value(":", bytes::tag(":")), - combinator::value("<", bytes::tag("<")), - combinator::value(">", bytes::tag(">")), - combinator::value("(", bytes::tag("(")), - combinator::value(")", bytes::tag(")")), - combinator::value("[", bytes::tag("[")), - combinator::value("]", bytes::tag("]")), - combinator::value("{", bytes::tag("{")), - combinator::value("}", bytes::tag("}")), - combinator::value(",", bytes::tag(",")), - )), - ), - |text: &str| !text.is_empty(), - ), - move |text| { - TokenKind::Literal(Literal { - text: text.into(), - is_case_insensitive: input.state.flags.is_case_insensitive, - }) - }, - )(input) - } - - fn separator(input: Input) -> ParseResult> { - combinator::value(TokenKind::Separator(Separator), bytes::tag("/"))(input) - } - - fn wildcard<'i>( - terminator: impl Clone + Parser, Input<'i>, ErrorStack<'i>>, - ) -> impl FnMut(Input<'i>) -> ParseResult<'i, TokenKind<'i, Annotation>> { - branch::alt(( - error::context( - "exactly-one", - combinator::map(bytes::tag("?"), |_| TokenKind::from(Wildcard::One)), - ), - error::context( - "tree", - combinator::map( - sequence::tuple(( - error::context( - "prefix", - combinator::map( - branch::alt(( - sequence::tuple(( - combinator::value(true, bytes::tag("/")), - flags_with_state, - )), - sequence::tuple(( - combinator::value(false, boe), - flags_with_state, - )), - )), - |(prefix, _)| prefix, - ), - ), - sequence::terminated( - bytes::tag("**"), - error::context( - "postfix", - branch::alt(( - combinator::map( - sequence::tuple((flags_with_state, bytes::tag("/"))), - |(_, postfix)| postfix, - ), - terminator.clone(), - )), - ), - ), - )), - |(has_root, _)| Wildcard::Tree { has_root }.into(), - ), - ), - error::context( - "zero-or-more", - combinator::map( - sequence::terminated( - bytes::tag("*"), - branch::alt(( - combinator::map( - combinator::peek(sequence::tuple(( - flags_without_state, - error::context("no terminating wildcard", bytes::is_not("*$")), - ))), - |(_, right)| right, - ), - terminator.clone(), - )), - ), - |_| Wildcard::ZeroOrMore(Evaluation::Eager).into(), - ), - ), - error::context( - "zero-or-more", - combinator::map( - sequence::terminated( - bytes::tag("$"), - branch::alt(( - combinator::map( - combinator::peek(sequence::tuple(( - flags_without_state, - error::context("no terminating wildcard", bytes::is_not("*$")), - ))), - |(_, right)| right, - ), - terminator, - )), - ), - |_| Wildcard::ZeroOrMore(Evaluation::Lazy).into(), - ), - ), - )) - } - - fn repetition(input: Input) -> ParseResult> { - fn bounds(input: Input) -> ParseResult<(usize, Option)> { - type BoundResult = Result::Err>; - - branch::alt(( - sequence::preceded( - bytes::tag(":"), - branch::alt(( - error::context( - "range", - combinator::map_res( - sequence::separated_pair( - character::digit1, - bytes::tag(","), - combinator::opt(character::digit1), - ), - |(lower, upper): (Input, Option<_>)| -> BoundResult<_> { - let lower = lower.parse::()?; - let upper = - upper.map(|upper| upper.parse::()).transpose()?; - Ok((lower, upper)) - }, - ), - ), - error::context( - "converged", - combinator::map_res(character::digit1, |n: Input| -> BoundResult<_> { - let n = n.parse::()?; - Ok((n, Some(n))) - }), - ), - combinator::success((1, None)), - )), - ), - combinator::success((0, None)), - ))(input) - } - - combinator::map( - sequence::delimited( - bytes::tag("<"), - sequence::tuple(( - error::context( - "sub-glob", - glob(move |input| { - combinator::peek(branch::alt((bytes::tag(":"), bytes::tag(">"))))(input) - }), - ), - error::context("bounds", bounds), - )), - bytes::tag(">"), - ), - |(tokens, (lower, upper))| { - Repetition { - tokens, - lower, - upper, - } - .into() - }, - )(input) - } - - fn class(input: Input) -> ParseResult> { - fn archetypes(input: Input) -> ParseResult> { - let escaped_character = |input| { - branch::alt(( - character::none_of("[]-\\"), - branch::alt(( - combinator::value('[', bytes::tag("\\[")), - combinator::value(']', bytes::tag("\\]")), - combinator::value('-', bytes::tag("\\-")), - )), - ))(input) - }; - - multi::many1(branch::alt(( - combinator::map( - sequence::separated_pair(escaped_character, bytes::tag("-"), escaped_character), - Archetype::from, - ), - combinator::map(escaped_character, Archetype::from), - )))(input) - } - - combinator::map( - sequence::delimited( - bytes::tag("["), - sequence::tuple(( - combinator::opt(bytes::tag("!").or(bytes::tag("^"))), - archetypes, - )), - bytes::tag("]"), - ), - |(negation, archetypes)| { - Class { - is_negated: negation.is_some(), - archetypes, - } - .into() - }, - )(input) - } - - fn alternative(input: Input) -> ParseResult> { - sequence::delimited( - bytes::tag("{"), - combinator::map( - multi::separated_list1( - bytes::tag(","), - error::context( - "sub-glob", - glob(move |input| { - combinator::peek(branch::alt((bytes::tag(","), bytes::tag("}"))))(input) - }), - ), - ), - |alternatives: Vec>| Alternative::from(alternatives).into(), - ), - bytes::tag("}"), - )(input) - } - - fn glob<'i>( - terminator: impl 'i + Clone + Parser, Input<'i>, ErrorStack<'i>>, - ) -> impl Parser, Vec>, ErrorStack<'i>> { - fn annotate<'i, F>( - parser: F, - ) -> impl FnMut(Input<'i>) -> ParseResult<'i, Token<'i, Annotation>> - where - F: 'i + Parser, TokenKind<'i, Annotation>, ErrorStack<'i>>, - { - combinator::map(pori::span(parser), |(span, kind)| Token::new(kind, span)) - } - - move |mut input: Input<'i>| { - input.state.subexpression = input.location(); - sequence::terminated( - multi::many1(branch::alt(( - annotate(error::context( - "literal", - sequence::preceded(flags_with_state, literal), - )), - annotate(error::context( - "repetition", - sequence::preceded(flags_with_state, repetition), - )), - annotate(error::context( - "alternative", - sequence::preceded(flags_with_state, alternative), - )), - annotate(error::context( - "wildcard", - sequence::preceded(flags_with_state, wildcard(terminator.clone())), - )), - annotate(error::context( - "class", - sequence::preceded(flags_with_state, class), - )), - annotate(error::context( - "separator", - sequence::preceded(flags_with_state, separator), - )), - ))), - terminator.clone(), - ) - .parse(input) - } - } - - if expression.is_empty() { - Ok(Tokenized { - expression: expression.into(), - tokens: vec![], - }) - } else { - let input = Input::new(Expression::from(expression), ParserState::default()); - let tokens = combinator::all_consuming(glob(combinator::eof))(input) - .map(|(_, tokens)| tokens) - .map_err(|error| ParseError::new(expression, error))?; - Ok(Tokenized { - expression: expression.into(), - tokens, - }) - } -} diff --git a/crates/turborepo-wax/src/token/variance.rs b/crates/turborepo-wax/src/token/variance.rs deleted file mode 100644 index bdd56fc3b069b..0000000000000 --- a/crates/turborepo-wax/src/token/variance.rs +++ /dev/null @@ -1,686 +0,0 @@ -use std::{ - borrow::Cow, - collections::VecDeque, - ops::{Add, Mul}, -}; - -use itertools::Itertools as _; - -use crate::{ - encode, - token::{self, Separator, Token}, - PATHS_ARE_CASE_INSENSITIVE, -}; - -pub trait Invariance: - Add + Eq + Mul + PartialEq + Sized -{ - fn empty() -> Self; -} - -pub trait UnitVariance { - fn unit_variance(self) -> Variance; -} - -impl UnitVariance for Variance { - fn unit_variance(self) -> Variance { - self - } -} - -pub trait ConjunctiveVariance: Iterator + Sized -where - Self::Item: UnitVariance, - T: Invariance, -{ - fn conjunctive_variance(self) -> Variance { - self.map(UnitVariance::unit_variance) - .reduce(Add::add) - .unwrap_or_else(|| Variance::Invariant(T::empty())) - } -} - -impl ConjunctiveVariance for I -where - I: Iterator, - I::Item: UnitVariance, - T: Invariance, -{ -} - -pub trait DisjunctiveVariance: Iterator + Sized -where - Self::Item: UnitVariance, - T: Invariance, -{ - fn disjunctive_variance(self) -> Variance { - // TODO: This implementation is incomplete. Unbounded variance (and - // unbounded depth) are "infectious" when disjunctive. If any unit - // variance is variant and unbounded (open), then the disjunctive - // variance should be the same. - // There are three distinct possibilities for disjunctive variance. - // - // - The iterator is empty and there are no unit variances to consider. The - // disjunctive variance is the empty invariant. - // - The iterator is non-empty and all unit variances are equal. The - // disjunctive variance is the same as any of the like unit variances. - // - The iterator is non-empty and the unit variances are **not** all equal. - // The disjunctive variance is variant and bounded (closed). - let mut variances = self.map(UnitVariance::unit_variance).fuse(); - let first = variances - .next() - .unwrap_or_else(|| Variance::Invariant(T::empty())); - if variances.all(|variance| first == variance) { - first - } else { - Variance::Variant(Boundedness::Closed) - } - } -} - -impl DisjunctiveVariance for I -where - I: Iterator, - I::Item: UnitVariance, - T: Invariance, -{ -} - -pub trait UnitDepth: Sized { - fn unit_depth(self) -> Boundedness { - Boundedness::Closed - } -} - -impl UnitDepth for Boundedness { - fn unit_depth(self) -> Boundedness { - self - } -} - -pub trait CompositeDepth: Iterator + Sized { - fn composite_depth(self) -> Boundedness; -} - -impl CompositeDepth for I -where - I: Iterator, - I::Item: UnitDepth, -{ - fn composite_depth(self) -> Boundedness { - if self.map(UnitDepth::unit_depth).any(|depth| depth.is_open()) { - Boundedness::Open - } else { - Boundedness::Closed - } - } -} - -pub trait UnitBreadth: Sized { - fn unit_breadth(self) -> Boundedness { - Boundedness::Closed - } -} - -impl UnitBreadth for Boundedness { - fn unit_breadth(self) -> Boundedness { - self - } -} - -pub trait CompositeBreadth: Iterator + Sized { - fn composite_breadth(self) -> Boundedness; -} - -impl CompositeBreadth for I -where - I: Iterator, - I::Item: UnitBreadth, -{ - fn composite_breadth(self) -> Boundedness { - if self - .map(UnitBreadth::unit_breadth) - .any(|breadth| breadth.is_open()) - { - Boundedness::Open - } else { - Boundedness::Closed - } - } -} - -pub trait IntoInvariantText<'t> { - fn into_nominal_text(self) -> InvariantText<'t>; - - fn into_structural_text(self) -> InvariantText<'t>; -} - -impl<'t> IntoInvariantText<'t> for Cow<'t, str> { - fn into_nominal_text(self) -> InvariantText<'t> { - InvariantFragment::Nominal(self).into() - } - - fn into_structural_text(self) -> InvariantText<'t> { - InvariantFragment::Structural(self).into() - } -} - -impl IntoInvariantText<'static> for String { - fn into_nominal_text(self) -> InvariantText<'static> { - InvariantFragment::Nominal(self.into()).into() - } - - fn into_structural_text(self) -> InvariantText<'static> { - InvariantFragment::Structural(self.into()).into() - } -} - -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct InvariantSize(usize); - -impl InvariantSize { - pub const fn new(n: usize) -> Self { - InvariantSize(n) - } -} - -impl Add for InvariantSize { - type Output = Self; - - fn add(self, other: Self) -> Self::Output { - InvariantSize(self.0 + other.0) - } -} - -impl From for usize { - fn from(size: InvariantSize) -> Self { - size.0 - } -} - -impl From for InvariantSize { - fn from(n: usize) -> Self { - InvariantSize(n) - } -} - -impl Invariance for InvariantSize { - fn empty() -> Self { - InvariantSize(0) - } -} - -impl Mul for InvariantSize { - type Output = Self; - - fn mul(self, n: usize) -> Self::Output { - InvariantSize( - self.0 - .checked_mul(n) - .expect("overflow determining invariant size"), - ) - } -} - -// TODO: The derived `PartialEq` implementation is incomplete and does not -// detect contiguous like fragments that are equivalent to an aggregated -// fragment. This works, but relies on constructing `InvariantText` by -// consistently appending fragments. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct InvariantText<'t> { - fragments: VecDeque>, -} - -impl<'t> InvariantText<'t> { - pub fn new() -> Self { - InvariantText { - fragments: VecDeque::new(), - } - } - - pub fn into_owned(self) -> InvariantText<'static> { - let InvariantText { fragments } = self; - InvariantText { - fragments: fragments - .into_iter() - .map(InvariantFragment::into_owned) - .collect(), - } - } - - pub fn to_string(&self) -> Cow<'t, str> { - self.fragments - .iter() - .map(|fragment| fragment.as_string().clone()) - .reduce(|text, fragment| text + fragment) - .unwrap_or(Cow::Borrowed("")) - } - - pub fn repeat(self, n: usize) -> Self { - if n == 0 { - self - } else { - let InvariantText { fragments } = self; - let n = (n - 1) - .checked_mul(fragments.len()) - .expect("overflow determining invariant text"); - let first = fragments.clone(); - InvariantText { - fragments: first - .into_iter() - .chain(fragments.into_iter().cycle().take(n)) - .collect(), - } - } - } -} - -impl<'t> Add for InvariantText<'t> { - type Output = Self; - - fn add(self, other: Self) -> Self::Output { - let InvariantText { - fragments: mut left, - } = self; - let InvariantText { - fragments: mut right, - } = other; - let end = left.pop_back(); - let start = right.pop_front(); - let InvariantText { fragments: middle } = match (end, start) { - (Some(left), Some(right)) => left + right, - (Some(middle), None) | (None, Some(middle)) => middle.into(), - (None, None) => InvariantText::new(), - }; - InvariantText { - fragments: left.into_iter().chain(middle).chain(right).collect(), - } - } -} - -impl<'t> Add> for InvariantText<'t> { - type Output = Self; - - fn add(self, fragment: InvariantFragment<'t>) -> Self::Output { - self + Self::from(fragment) - } -} - -impl<'t> Default for InvariantText<'t> { - fn default() -> Self { - Self::new() - } -} - -impl<'t> From> for InvariantText<'t> { - fn from(fragment: InvariantFragment<'t>) -> Self { - InvariantText { - fragments: [fragment].into_iter().collect(), - } - } -} - -impl<'t> Invariance for InvariantText<'t> { - fn empty() -> Self { - InvariantText::new() - } -} - -impl<'t> Mul for InvariantText<'t> { - type Output = Self; - - fn mul(self, n: usize) -> Self::Output { - self.repeat(n) - } -} - -#[derive(Clone, Debug, Eq)] -enum InvariantFragment<'t> { - Nominal(Cow<'t, str>), - Structural(Cow<'t, str>), -} - -impl<'t> InvariantFragment<'t> { - pub fn into_owned(self) -> InvariantFragment<'static> { - use InvariantFragment::{Nominal, Structural}; - - match self { - Nominal(text) => Nominal(text.into_owned().into()), - Structural(text) => Structural(text.into_owned().into()), - } - } - - pub fn as_string(&self) -> &Cow<'t, str> { - match self { - InvariantFragment::Nominal(ref text) | InvariantFragment::Structural(ref text) => text, - } - } -} - -impl<'t> Add for InvariantFragment<'t> { - type Output = InvariantText<'t>; - - fn add(self, other: Self) -> Self::Output { - use InvariantFragment::{Nominal, Structural}; - - match (self, other) { - (Nominal(left), Nominal(right)) => InvariantText { - fragments: [Nominal(left + right)].into_iter().collect(), - }, - (Structural(left), Structural(right)) => InvariantText { - fragments: [Structural(left + right)].into_iter().collect(), - }, - (left, right) => InvariantText { - fragments: [left, right].into_iter().collect(), - }, - } - } -} - -impl<'t> PartialEq for InvariantFragment<'t> { - fn eq(&self, other: &Self) -> bool { - use InvariantFragment::{Nominal, Structural}; - - match (self, other) { - (Nominal(ref left), Nominal(ref right)) => { - if PATHS_ARE_CASE_INSENSITIVE { - // This comparison uses Unicode simple case folding. It - // would be better to use full case folding (and better - // still to use case folding appropriate for the language of - // the text), but this approach is used to have consistent - // results with the regular expression encoding of compiled - // globs. A more comprehensive alternative would be to use - // something like the `focaccia` crate. See also - // `CharExt::has_casing`. - encode::case_folded_eq(left.as_ref(), right.as_ref()) - } else { - left == right - } - } - (Structural(ref left), Structural(ref right)) => left == right, - _ => false, - } - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum Boundedness { - Closed, - Open, -} - -impl Boundedness { - pub fn is_closed(&self) -> bool { - matches!(self, Boundedness::Closed) - } - - pub fn is_open(&self) -> bool { - matches!(self, Boundedness::Open) - } -} - -#[derive(Clone, Debug, Eq)] -pub enum Variance { - Invariant(T), - // In this context, _boundedness_ refers to whether or not a variant token or expression is - // _constrained_ or _unconstrained_. For example, the expression `**` is unconstrained and - // matches _any and all_, while the expression `a*z` is constrained and matches _some_. Note - // that both expressions match an infinite number of components, but the constrained - // expression does *not* match any component. Boundedness does **not** consider length, - // only whether or not some part of an expression is constrained to a known set of - // matches. As such, both the expressions `?` and `*` are variant with open bounds. - Variant(Boundedness), -} - -impl Variance { - pub fn map_invariance(self, mut f: impl FnMut(T) -> U) -> Variance { - match self { - Variance::Invariant(invariant) => Variance::Invariant(f(invariant)), - Variance::Variant(boundedness) => Variance::Variant(boundedness), - } - } - - pub fn as_invariance(&self) -> Option<&T> { - match self { - Variance::Invariant(ref invariant) => Some(invariant), - _ => None, - } - } - - pub fn boundedness(&self) -> Boundedness { - match self { - Variance::Variant(ref boundedness) => *boundedness, - _ => Boundedness::Closed, - } - } - - pub fn is_invariant(&self) -> bool { - matches!(self, Variance::Invariant(_)) - } - - pub fn is_variant(&self) -> bool { - matches!(self, Variance::Variant(_)) - } -} - -impl Add for Variance -where - T: Add, -{ - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - use Boundedness::{Closed, Open}; - use Variance::{Invariant, Variant}; - - match (self, rhs) { - (Invariant(left), Invariant(right)) => Invariant(left + right), - (Variant(Open), Variant(Open)) => Variant(Open), - (Invariant(_) | Variant(_), Variant(_)) | (Variant(_), Invariant(_)) => Variant(Closed), - } - } -} - -impl PartialEq for Variance -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Variance::Invariant(ref left), Variance::Invariant(ref right)) => left == right, - (Variance::Variant(ref left), Variance::Variant(ref right)) => left == right, - _ => false, - } - } -} - -// TODO: Is there some way to unify this with -// `invariant_text_prefix_upper_bound`? -pub fn invariant_text_prefix<'t, A, I>(tokens: I) -> String -where - A: 't, - I: IntoIterator>, -{ - let separator = &Separator::invariant_text(); - let mut tokens = tokens.into_iter().peekable(); - let mut prefix = String::new(); - if tokens - .peek() - .map_or(false, |token| !token.has_sub_tokens() && token.has_root()) - { - // Push a preceding separator if the first token has a root and is not a group. - // This ensures that initiating separators and tree wildcards express a - // root in invariant prefixes. - prefix.push_str(separator); - } - // TODO: Replace `map`, `take_while`, and `flatten` with `map_while` when it - // stabilizes. - prefix.push_str( - &token::components(tokens) - .map(|component| { - component - .variance::() - .as_invariance() - .map(InvariantText::to_string) - .map(Cow::into_owned) - }) - .take_while(Option::is_some) - .flatten() - .join(separator), - ); - prefix -} - -pub fn invariant_text_prefix_upper_bound<'t, A, I>(tokens: I) -> usize -where - A: 't, - I: IntoIterator>, -{ - use crate::token::{ - TokenKind::{Separator, Wildcard}, - Wildcard::Tree, - }; - - let mut m = 0usize; - let mut separator = None; - for (n, token) in tokens.into_iter().map(Token::kind).enumerate() { - m = n; - match token { - Separator(_) => { - separator = Some(n); - } - Wildcard(Tree { .. }) => { - return n; - } - _ => { - if token.variance::().is_invariant() { - continue; - } - return match separator { - Some(n) => n + 1, - None => 0, - }; - } - } - } - m + 1 -} - -/// Returns `true` if the token tree is exhaustive. -/// -/// A glob expression and its token tree are exhaustive if the terminal -/// component has unbounded depth and unbounded variance. -pub fn is_exhaustive<'i, 't, A, I>(tokens: I) -> bool -where - 't: 'i, - A: 't, - I: IntoIterator>, -{ - let component = token::components(tokens).last(); - matches!( - component.map(|component| { - ( - component.depth(), - component.variance::().boundedness(), - ) - }), - Some((Boundedness::Open, Boundedness::Open)), - ) -} - -#[cfg(test)] -mod tests { - use std::path::{Path, PathBuf}; - - use crate::token::{ - self, - variance::{self, Boundedness, InvariantSize, Variance}, - TokenTree, - }; - - #[test] - fn invariant_text_prefix() { - fn invariant_path_prefix(expression: &str) -> PathBuf { - variance::invariant_text_prefix(token::parse(expression).unwrap().tokens()).into() - } - - assert_eq!(invariant_path_prefix("/a/b"), Path::new("/a/b")); - assert_eq!(invariant_path_prefix("a/b"), Path::new("a/b")); - assert_eq!(invariant_path_prefix("a/*"), Path::new("a")); - assert_eq!(invariant_path_prefix("a/*b"), Path::new("a")); - assert_eq!(invariant_path_prefix("a/b*"), Path::new("a")); - assert_eq!(invariant_path_prefix("a/b/*/c"), Path::new("a/b")); - - #[cfg(any(unix, windows))] - let prefix = invariant_path_prefix("../foo/(?i)bar/(?-i)baz"); - #[cfg(unix)] - assert_eq!(prefix, Path::new("../foo")); - #[cfg(windows)] - assert_eq!(prefix, Path::new("../foo/bar")); - - assert_eq!(invariant_path_prefix("**"), Path::new("")); - assert_eq!(invariant_path_prefix("a*"), Path::new("")); - assert_eq!(invariant_path_prefix("*/b"), Path::new("")); - assert_eq!(invariant_path_prefix("a?/b"), Path::new("")); - } - - #[test] - fn tree_expression_variance() { - use Boundedness::{Closed, Open}; - use Variance::Variant; - - let tokenized = token::parse("**").unwrap(); - assert!(matches!( - tokenized.variance::(), - Variant(Open) - )); - let tokenized = token::parse("<*/>*").unwrap(); - assert!(matches!( - tokenized.variance::(), - Variant(Open) - )); - let tokenized = token::parse("</>*").unwrap(); - assert!(matches!( - tokenized.variance::(), - Variant(Open) - )); - - let tokenized = token::parse("foo/**").unwrap(); - assert!(matches!( - tokenized.variance::(), - Variant(Closed) - )); - let tokenized = token::parse("*").unwrap(); - assert!(matches!( - tokenized.variance::(), - Variant(Closed) - )); - } - - #[test] - fn exhaustiveness() { - assert!(token::is_exhaustive(token::parse("**").unwrap().tokens())); - assert!(token::is_exhaustive(token::parse("a/**").unwrap().tokens())); - assert!(token::is_exhaustive( - token::parse("a/<*/>*").unwrap().tokens() - )); - assert!(token::is_exhaustive( - token::parse("a/</>*").unwrap().tokens() - )); - - assert!(!token::is_exhaustive( - token::parse("a/**/b").unwrap().tokens() - )); - assert!(!token::is_exhaustive(token::parse("a/*").unwrap().tokens())); - assert!(!token::is_exhaustive( - token::parse("a/").unwrap().tokens() - )); - assert!(!token::is_exhaustive( - token::parse("a").unwrap().tokens() - )); - assert!(!token::is_exhaustive( - token::parse("**/a").unwrap().tokens() - )); - assert!(!token::is_exhaustive(token::parse("").unwrap().tokens())); - } -} diff --git a/crates/turborepo-wax/src/walk/filter.rs b/crates/turborepo-wax/src/walk/filter.rs deleted file mode 100644 index 32544a4ac49b2..0000000000000 --- a/crates/turborepo-wax/src/walk/filter.rs +++ /dev/null @@ -1,675 +0,0 @@ -//! Separating filters that do not discard residue. -//! -//! This module provides APIs for separating filters that partition a feed -//! (input) into a filtrate and residue on a per-item basis. The primary API is -//! the [`SeparatingFilter`] trait, which behaves much like the standard -//! [`Iterator`] trait and is similarly composable via combinators. -//! -//! Unlike [`Iterator::filter`] and similar APIs, [`SeparatingFilter`]s do -//! **not** discard residue. Instead, both the filtrate and the residue is -//! present and can therefore be observed by composed filters. This is important -//! if combinators have side effects that depend on observing filtered data from -//! upstream filters. For example, [`HierarchicalIterator`] provides combinators -//! for filtering that can affect the traversal of a tree by discarding a -//! sub-tree. This behavior may need to be invoked regardless of whether or not -//! data is filtrate or residue. -//! -//! [`SeparatingFilter`]s may also be [`Iterator`]s, in which case only the -//! filtrate is typically exposed in the [`Iterator`] API (the associated `Item` -//! type is the `Filtrate` type of the filter's associated `Feed` type). -//! -//! [`Iterator`]: std::iter::Iterator -//! [`Iterator::filter`]: std::iter::Iterator::filter -//! [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter - -use std::{ - cmp::{Eq, PartialEq}, - hash::{Hash, Hasher}, - marker::PhantomData, -}; - -mod kind { - #[derive(Debug)] - pub enum FiltrateKind {} - #[derive(Debug)] - pub enum ResidueKind {} -} -use kind::*; - -#[derive(Debug)] -pub struct Product { - inner: T, - _phantom: PhantomData K>, -} - -impl Product { - pub(super) fn new(inner: T) -> Self { - Product { - inner, - _phantom: PhantomData, - } - } - - pub fn into_inner(self) -> T { - self.inner - } - - pub fn map(self, f: F) -> Product - where - F: FnOnce(T) -> U, - { - Product::new(f(self.into_inner())) - } - - pub fn get(&self) -> &T { - &self.inner - } -} - -impl Product> { - pub fn transpose(self) -> Option> { - self.inner.map(Product::new) - } -} - -impl Product> { - pub fn transpose(self) -> Result, Product> { - self.inner.map(Product::new).map_err(Product::new) - } -} - -impl AsRef for Product { - fn as_ref(&self) -> &T { - self.get() - } -} - -impl Copy for Product where T: Copy {} - -impl Clone for Product -where - T: Clone, -{ - fn clone(&self) -> Self { - Product::new(self.inner.clone()) - } -} - -impl Eq for Product where T: Eq {} - -impl Hash for Product -where - T: Hash, -{ - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.inner.hash(state); - } -} - -impl PartialEq for Product -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - self.inner.eq(&other.inner) - } -} - -pub type Filtrate = Product; -pub type Residue = Product; - -impl Filtrate { - pub fn filter(self) -> Residue { - self.filter_map(From::from) - } - - pub fn filter_map(self, f: F) -> Residue - where - F: FnOnce(T) -> R, - { - Residue::new(f(self.into_inner())) - } - - pub fn filter_node(self) -> Residue> - where - R: From, - { - self.filter_map_node(From::from) - } - - pub fn filter_map_node(self, f: F) -> Residue> - where - F: FnOnce(T) -> R, - { - Residue::new(TreeResidue::Node(f(self.into_inner()))) - } - - pub fn filter_tree(self, cancellation: WalkCancellation<'_, I>) -> Residue> - where - I: CancelWalk, - R: From, - { - self.filter_map_tree(cancellation, From::from) - } - - pub fn filter_map_tree( - self, - cancellation: WalkCancellation<'_, I>, - f: F, - ) -> Residue> - where - I: CancelWalk, - F: FnOnce(T) -> R, - { - cancellation.cancel_walk_tree(); - Residue::new(TreeResidue::Tree(f(self.into_inner()))) - } -} - -impl AsRef for Residue> { - fn as_ref(&self) -> &T { - self.get().get() - } -} - -/// Describes the input and output types of a [`SeparatingFilter`]. -/// -/// `Feed` types are typically represented as tuples of the filtrate and residue -/// types, in that order. -/// -/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter -pub trait Feed { - type Filtrate; - type Residue; -} - -impl Feed for (T, R) { - type Filtrate = T; - type Residue = R; -} - -/// A filter [`Feed`] wherein the filtrate and residue have or can produce a -/// substituent. -/// -/// A substituent is data that is common to both the filtrate and residue (that -/// is, the filtrate and residue are isomers). An `Isomeric` feed can be -/// filtered nominally on the basis of its substituent. See -/// [`Separation::filter_tree_by_substituent`] and -/// [`HierarchicalIterator::filter_tree_by_substituent`], for example. -/// -/// [`Feed`]: crate::walk::filter::Feed -/// [`HierarchicalIterator::filter_tree_by_substituent`]: crate::walk::filter::HierarchicalIterator::filter_tree_by_substituent -/// [`Separation::filter_tree_by_substituent`]: crate::walk::filter::Separation::filter_tree_by_substituent -pub trait Isomeric: Feed { - type Substituent<'a> - where - Self: 'a; - - fn substituent(separation: &Separation) -> Self::Substituent<'_>; -} - -// TODO: The derived trait implementations are likely incorrect and imply a -// bound on `S`. It just so happens that `S` is typically a tuple and -// tuples will implement these same traits if the composed types implement -// them. Instead, the bounds ought to be on the associated `Filtrate` and -// `Residue` types. -/// The separated output of a [`SeparatingFilter`] feed. -/// -/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum Separation -where - S: Feed + ?Sized, -{ - Filtrate(Filtrate), - Residue(Residue), -} - -impl Separation -where - S: Feed, -{ - fn from_inner_filtrate(filtrate: S::Filtrate) -> Self { - Separation::Filtrate(Filtrate::new(filtrate)) - } - - fn from_inner_residue(residue: S::Residue) -> Self { - Separation::Residue(Residue::new(residue)) - } - - pub fn filter_map(self, f: F) -> Self - where - F: FnOnce(S::Filtrate) -> S::Residue, - { - match self { - Separation::Filtrate(filtrate) => { - Separation::from_inner_residue(f(filtrate.into_inner())) - } - separation => separation, - } - } - - pub fn map_filtrate(self, f: F) -> Separation<(U, S::Residue)> - where - F: FnOnce(S::Filtrate) -> U, - { - match self { - Separation::Filtrate(filtrate) => filtrate.map(f).into(), - Separation::Residue(residue) => residue.into(), - } - } - - pub fn map_residue(self, f: F) -> Separation<(S::Filtrate, U)> - where - F: FnOnce(S::Residue) -> U, - { - match self { - Separation::Filtrate(filtrate) => filtrate.into(), - Separation::Residue(residue) => residue.map(f).into(), - } - } - - pub fn filtrate(self) -> Option> { - match self { - Separation::Filtrate(filtrate) => Some(filtrate), - _ => None, - } - } - - pub fn as_filtrate(&self) -> Option<&Filtrate> { - match self { - Separation::Filtrate(ref filtrate) => Some(filtrate), - _ => None, - } - } - - pub fn as_ref(&self) -> Separation<(&S::Filtrate, &S::Residue)> { - match self { - Separation::Filtrate(ref filtrate) => { - Separation::Filtrate(Filtrate::new(filtrate.as_ref())) - } - Separation::Residue(ref residue) => Separation::Residue(Residue::new(residue.as_ref())), - } - } - - pub fn substituent(&self) -> S::Substituent<'_> - where - S: Isomeric, - { - S::substituent(self) - } -} - -impl Separation -where - S: Feed>, -{ - pub fn filter_map_node(self, f: F) -> Self - where - F: FnOnce(T) -> R, - { - self.filter_map(|filtrate| TreeResidue::Node(f(filtrate))) - } - - pub fn filter_map_tree(self, cancellation: WalkCancellation<'_, I>, f: F) -> Self - where - I: CancelWalk, - F: FnOnce(T) -> R, - { - match self { - Separation::Filtrate(filtrate) => { - cancellation.cancel_walk_tree(); - Separation::from_inner_residue(TreeResidue::Node(f(filtrate.into_inner()))) - } - Separation::Residue(residue) => match residue.into_inner() { - TreeResidue::Node(residue) => { - cancellation.cancel_walk_tree(); - Separation::from_inner_residue(TreeResidue::Tree(residue)) - } - residue => Separation::from_inner_residue(residue), - }, - } - } - - pub fn filter_tree_by_substituent( - self, - cancellation: WalkCancellation<'_, I>, - f: F, - ) -> Self - where - S: Isomeric, - R: From, - I: CancelWalk, - F: FnOnce(S::Substituent<'_>) -> Option>, - { - match f(self.substituent()) { - Some(TreeResidue::Tree(())) => self.filter_map_tree(cancellation, From::from), - Some(TreeResidue::Node(())) => self.filter_map_node(From::from), - _ => self, - } - } -} - -impl Separation<(Option, R)> { - pub fn transpose_filtrate(self) -> Option> { - match self { - Separation::Filtrate(filtrate) => { - filtrate.into_inner().map(Filtrate::new).map(From::from) - } - Separation::Residue(residue) => Some(residue.into()), - } - } -} - -impl Separation<(Result, R)> { - pub fn transpose_filtrate(self) -> Result, Filtrate> { - match self { - Separation::Filtrate(filtrate) => match filtrate.into_inner() { - Ok(filtrate) => Ok(Filtrate::new(filtrate).into()), - Err(error) => Err(Filtrate::new(error)), - }, - Separation::Residue(residue) => Ok(residue.into()), - } - } -} - -impl From> for Separation -where - S: Feed, -{ - fn from(filtrate: Filtrate) -> Self { - Separation::Filtrate(filtrate) - } -} - -impl From> for Separation -where - S: Feed, -{ - fn from(residue: Residue) -> Self { - Separation::Residue(residue) - } -} - -pub trait SeparatingFilter { - type Feed: Feed; - - fn feed(&mut self) -> Option>; -} - -impl SeparatingFilter for I -where - I: SeparatingFilterInput, -{ - type Feed = ::Feed; - - fn feed(&mut self) -> Option> { - self.next().map(Separation::from_inner_filtrate) - } -} - -/// [`Iterator`] that provides filtrate input for [`SeparatingFilter`]s. -/// -/// **This trait provides the only API for implementing a -/// [`SeparatingFilter`].** [`Iterator`]s can implement this trait for a -/// transitive [`SeparatingFilter`] implementation that provides all items -/// as filtrate. This bridges [`Iterator`]s into the input of a separating -/// filter. See the [`filtrate`] function for the output analog. -/// -/// [`filtrate`]: crate::walk::filter::filtrate -/// [`Iterator`]: std::iter::Iterator -/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter -pub trait SeparatingFilterInput: Iterator { - type Feed: Feed; -} - -/// A tree traversing type that can cancel traversal into the most recently -/// visited node. -/// -/// See [`HierarchicalIterator`]. -/// -/// [`HierarchicalIterator`]: crate::walk::filter::HierarchicalIterator -pub trait CancelWalk { - fn cancel_walk_tree(&mut self); -} - -/// Cancels traversal into a sub-tree of a [`HierarchicalIterator`]. -/// -/// [`HierarchicalIterator`]: crate::walk::filter::HierarchicalIterator -#[derive(Debug)] -pub struct WalkCancellation<'i, I>(&'i mut I); - -impl<'i, I> WalkCancellation<'i, I> { - // TODO: This module should not allow this at all and `WalkCancellation`, much - // like `Product`, should not be possible to construct outside of the - // module. Instead, client code should rely solely on combinators, but - // this requires RPITIT to write combinators with arbitrary output - // types (like unnameable `FnMut`s). - // - // RPITIT is slated to land at the end of December of 2023. Remove this - // and implement iterators using pure combinators when that happens. - pub(in crate::walk) fn unchecked(tree: &'i mut I) -> Self { - WalkCancellation(tree) - } -} - -impl<'i, I> WalkCancellation<'i, I> -where - I: CancelWalk, -{ - fn cancel_walk_tree(self) { - // Client code is only able to move a `WalkCancellation` into - // `Separation::filter_map_tree`, at which point the filtered item should be the - // current item of the iterator. - self.0.cancel_walk_tree() - } -} - -/// Residue of a [`SeparatingFilter`] over a tree data structure. -/// -/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum TreeResidue { - Node(T), - Tree(T), -} - -impl TreeResidue { - pub fn map(self, f: F) -> TreeResidue - where - F: FnOnce(T) -> U, - { - match self { - TreeResidue::Node(residue) => TreeResidue::Node(f(residue)), - TreeResidue::Tree(residue) => TreeResidue::Tree(f(residue)), - } - } - - pub fn as_ref(&self) -> TreeResidue<&T> { - match self { - TreeResidue::Node(ref residue) => TreeResidue::Node(residue), - TreeResidue::Tree(ref residue) => TreeResidue::Tree(residue), - } - } - - pub fn get(&self) -> &T { - match self { - TreeResidue::Node(ref residue) | TreeResidue::Tree(ref residue) => residue, - } - } -} - -/// Hierarchical iterator over items in a tree data structure. -/// -/// Here, _hierarchical_ means that the iterator traverses the tree in a manner -/// that never yields a node before its ancestors (e.g., a child node before its -/// parent node). Both pre-order DFS and BFS are examples of such a traversal. -/// -/// `HierarchicalIterator` allows client code to control tree traversal when -/// filtering items using a `WalkCancellation`, which discards a particular node -/// and cancels traversal to its child nodes (sub-tree). Filtering a sub-tree -/// completely discards that tree, and no filter separation is produced (no -/// filtrate nor residue). This is the only separating filter operation that -/// explicitly discards a retentate and no downstream filters can observe the -/// discarded sub-tree. -pub trait HierarchicalIterator: - CancelWalk + Iterator::Filtrate> + SeparatingFilter -{ - fn filter_tree_by_substituent(self, f: F) -> FilterTreeBySubstituent - where - Self: Sized, - Self::Feed: Isomeric, - F: FnMut(::Substituent<'_>) -> Option>, - { - FilterTreeBySubstituent { input: self, f } - } - - fn filter_map_tree(self, f: F) -> FilterMapTree - where - Self: Sized, - S: Feed, - F: FnMut(WalkCancellation, Separation) -> Separation, - { - FilterMapTree { - input: self, - f, - _phantom: PhantomData, - } - } -} - -impl HierarchicalIterator for I -where - I: CancelWalk + Iterator::Filtrate> + SeparatingFilter, - I::Feed: Feed>, -{ -} - -#[derive(Clone, Debug)] -pub struct FilterTreeBySubstituent { - input: I, - f: F, -} - -impl CancelWalk for FilterTreeBySubstituent -where - I: CancelWalk, -{ - fn cancel_walk_tree(&mut self) { - self.input.cancel_walk_tree() - } -} - -impl SeparatingFilter for FilterTreeBySubstituent -where - R: From<::Filtrate>, - I: HierarchicalIterator, - I::Feed: Feed> + Isomeric, - F: FnMut(::Substituent<'_>) -> Option>, -{ - type Feed = I::Feed; - - fn feed(&mut self) -> Option> { - let separation = self.input.feed(); - separation.map(|separation| { - let substituent = separation.substituent(); - match (self.f)(substituent) { - None => separation, - Some(residue) => match residue { - TreeResidue::Node(_) => separation.filter_map_node(From::from), - TreeResidue::Tree(_) => { - separation.filter_map_tree(WalkCancellation(self), From::from) - } - }, - } - }) - } -} - -impl Iterator for FilterTreeBySubstituent -where - R: From<::Filtrate>, - I: HierarchicalIterator, - I::Feed: Feed> + Isomeric, - F: FnMut(::Substituent<'_>) -> Option>, -{ - type Item = ::Filtrate; - - fn next(&mut self) -> Option { - filtrate(self) - } -} - -#[derive(Clone, Debug)] -pub struct FilterMapTree { - input: I, - f: F, - _phantom: PhantomData S>, -} - -impl CancelWalk for FilterMapTree -where - I: CancelWalk, -{ - fn cancel_walk_tree(&mut self) { - self.input.cancel_walk_tree() - } -} - -impl Iterator for FilterMapTree -where - I: SeparatingFilter, - I::Feed: Feed>, - S: Feed, - F: FnMut(WalkCancellation, Separation) -> Separation, -{ - type Item = <::Feed as Feed>::Filtrate; - - fn next(&mut self) -> Option { - filtrate(self) - } -} - -impl SeparatingFilter for FilterMapTree -where - I: SeparatingFilter, - I::Feed: Feed>, - S: Feed, - F: FnMut(WalkCancellation, Separation) -> Separation, -{ - type Feed = S; - - fn feed(&mut self) -> Option> { - let separation = self.input.feed(); - separation.map(|separation| (self.f)(WalkCancellation(&mut self.input), separation)) - } -} - -/// Feeds a [`SeparatingFilter`] and yields the next filtrate. -/// -/// This function can be used to implement [`Iterator`] for -/// [`SeparatingFilter`]s and bridges [`SeparatingFilter`]s into the output of -/// an iterator. See the [`SeparatingFilterInput`] trait for the input analog. -/// -/// [`Iterator`]: std::iter::Iterator -/// [`SeparatingFilter`]: crate::walk::filter::SeparatingFilter -/// [`SeparatingFilterInput`]: crate::walk::filter::SeparatingFilterInput -pub fn filtrate(filter: &mut I) -> Option<::Filtrate> -where - I: SeparatingFilter, -{ - loop { - if let Some(separation) = filter.feed() { - return match separation.filtrate() { - None => { - continue; - } - Some(filtrate) => Some(filtrate.into_inner()), - }; - } - return None; - } -} diff --git a/crates/turborepo-wax/src/walk/glob.rs b/crates/turborepo-wax/src/walk/glob.rs deleted file mode 100644 index f26ae4e4c5799..0000000000000 --- a/crates/turborepo-wax/src/walk/glob.rs +++ /dev/null @@ -1,679 +0,0 @@ -use std::{ - fs::{FileType, Metadata}, - path::{Component, Path, PathBuf}, -}; - -use itertools::Itertools; -use regex::Regex; - -use super::SplitAtDepth; -use crate::{ - capture::MatchedText, - encode::CompileError, - token::{self, Token, TokenTree}, - walk::{ - filter::{HierarchicalIterator, Separation}, - Entry, EntryResidue, FileIterator, JoinAndGetDepth, TreeEntry, WalkBehavior, WalkError, - WalkTree, - }, - BuildError, CandidatePath, Glob, Pattern, -}; - -/// APIs for matching globs against directory trees. -impl<'t> Glob<'t> { - /// Gets an iterator over matching file paths in a directory tree. - /// - /// This function matches a `Glob` against a directory tree, returning a - /// [`FileIterator`] that yields a [`GlobEntry`] for each matching file. - /// `Glob`s are the only [`Pattern`]s that support this semantic - /// operation; it is not possible to match combinators ([`Any`]) against - /// directory trees. - /// - /// As with [`Path::join`] and [`PathBuf::push`], the base directory can be - /// escaped or overridden by rooted `Glob`s. In many cases, the current - /// working directory `.` is an appropriate base directory and will be - /// intuitively ignored if the `Glob` is rooted, such as in `/mnt/media/ - /// **/*.mp4`. The [`has_root`] function can be used to check if a `Glob` is - /// rooted. - /// - /// The root directory is either the given directory or, if rooted, the - /// [invariant prefix][`Glob::partition`] of the `Glob`. Either way, - /// this function joins the given directory with any invariant prefix to - /// potentially begin the walk as far down the tree as possible. **The - /// prefix and any [semantic literals][`Glob::has_semantic_literals`] in - /// this prefix are interpreted semantically as a path**, so components - /// like `.` and `..` that precede variant patterns interact with the - /// base directory semantically. This means that expressions like - /// `../**` escape the base directory as expected on Unix and Windows, for - /// example. To query the root directory of the walk, see [`Glob::walker`]. - /// - /// This function uses the default [`WalkBehavior`]. To configure the - /// behavior of the traversal, see [`Glob::walk_with_behavior`]. - /// - /// Unlike functions in [`Pattern`], **this operation is semantic and - /// interacts with the file system**. - /// - /// # Examples - /// - /// ```rust,no_run - /// use wax::walk::Entry; - /// use wax::Glob; - /// - /// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); - /// for entry in glob.walk("./Pictures") { - /// let entry = entry.unwrap(); - /// println!("JPEG: {:?}", entry.path()); - /// } - /// ``` - /// - /// Glob expressions do not support general negations, but the [`not`] - /// combinator can be used when walking a directory tree to filter - /// entries using patterns. **This should generally be preferred over - /// functions like [`Iterator::filter`], because it avoids unnecessary reads - /// of directory trees when matching [exhaustive - /// negations][`Pattern::is_exhaustive`].** - /// - /// ```rust,no_run - /// use wax::walk::{Entry, FileIterator}; - /// use wax::Glob; - /// - /// let glob = Glob::new("**/*.(?i){jpg,jpeg,png}").unwrap(); - /// for entry in glob - /// .walk("./Pictures") - /// .not(["**/(i?){background,wallpaper}/**"]) - /// .unwrap() - /// { - /// let entry = entry.unwrap(); - /// println!("{:?}", entry.path()); - /// } - /// ``` - /// - /// [`Any`]: crate::Any - /// [`Glob::walk_with_behavior`]: crate::Glob::walk_with_behavior - /// [`Glob::walker`]: crate::Glob::walker - /// [`GlobEntry`]: crate::walk::GlobEntry - /// [`has_root`]: crate::Glob::has_root - /// [`FileIterator`]: crate::walk::FileIterator - /// [`Iterator::filter`]: std::iter::Iterator::filter - /// [`not`]: crate::walk::FileIterator::not - /// [`Path::join`]: std::path::Path::join - /// [`PathBuf::push`]: std::path::PathBuf::push - /// [`Program`]: crate::Program - /// [`Program::is_exhaustive`]: crate::Program::is_exhaustive - /// [`WalkBehavior`]: crate::walk::WalkBehavior - pub fn walk( - &self, - directory: impl Into, - ) -> impl 'static + FileIterator { - self.walk_with_behavior(directory, WalkBehavior::default()) - } - - /// Gets an iterator over matching files in a directory tree. - /// - /// This function is the same as [`Glob::walk`], but it additionally accepts - /// a [`WalkBehavior`] that configures how the traversal interacts with - /// symbolic links, the maximum depth from the root, etc. - /// - /// Depth is relative to the root directory of the traversal, which is - /// determined by joining the given path and any [invariant - /// prefix][`Glob::partition`] of the `Glob`. - /// - /// See [`Glob::walk`] for more information. - /// - /// # Examples - /// - /// ```rust,no_run - /// use wax::walk::{Entry, WalkBehavior}; - /// use wax::Glob; - /// - /// let glob = Glob::new("**/*.(?i){jpg,jpeg}").unwrap(); - /// for entry in glob.walk_with_behavior("./Pictures", WalkBehavior::default()) { - /// let entry = entry.unwrap(); - /// println!("JPEG: {:?}", entry.path()); - /// } - /// ``` - /// - /// By default, symbolic links are read as normal files and their targets - /// are ignored. To follow symbolic links and traverse any directories - /// that they reference, specify a [`LinkBehavior`]. - /// - /// ```rust,no_run - /// use wax::walk::{Entry, LinkBehavior}; - /// use wax::Glob; - /// - /// let glob = Glob::new("**/*.txt").unwrap(); - /// for entry in glob.walk_with_behavior("/var/log", LinkBehavior::ReadTarget) { - /// let entry = entry.unwrap(); - /// println!("Log: {:?}", entry.path()); - /// } - /// ``` - /// - /// [`Glob::partition`]: crate::Glob::partition - /// [`Glob::walk`]: crate::Glob::walk - /// [`LinkBehavior`]: crate::walk::LinkBehavior - /// [`WalkBehavior`]: crate::walk::WalkBehavior - pub fn walk_with_behavior( - &self, - directory: impl Into, - behavior: impl Into, - ) -> impl 'static + FileIterator { - self.walker(directory).walk_with_behavior(behavior) - } - - /// Gets an iterator builder over matching files in a directory tree. - /// - /// This function gets an intermediate walker that describes iteration over - /// matching files and provides paths prior to iteration. In particular, - /// `walker` can be used when the root directory of the walk is needed. - /// **The root directory may differ from the directory passed to walking - /// functions.** - /// - /// See [`Glob::walk`]. - /// - /// # Examples - /// - /// ```rust,no_run - /// use wax::walk::Entry; - /// use wax::Glob; - /// - /// let glob = Glob::new("**/*.{log,txt}").unwrap(); - /// let walker = glob.walker("/var/log"); - /// let root = walker.root_prefix_paths().0.to_path_buf(); - /// for entry in walker.walk() { - /// let entry = entry.unwrap(); - /// println!("Log: {:?}", entry.path()); - /// } - /// ``` - /// - /// [`Glob::walk`]: crate::Glob::walk - pub fn walker(&self, directory: impl Into) -> GlobWalker { - GlobWalker { - anchor: self.anchor(directory), - program: WalkProgram::from_glob(self), - } - } - - fn anchor(&self, directory: impl Into) -> Anchor { - fn invariant_path_prefix<'t, A, I>(tokens: I, root: &Path) -> Option - where - A: 't, - I: IntoIterator>, - { - let prefix = token::invariant_text_prefix(tokens); - if prefix.is_empty() { - None - } else { - // here, we don't know if the glob will be walked with or without symlinks, - // so we need to ensure that the invariant prefix optimisation doesn't cross a - // symlink todo: `anchor` knows nothing about the walk behaviour. if it did, we - // could probably skip this conditionally for a small perf bonus - let prefix: PathBuf = prefix.into(); - let mut curr_prefix = prefix.as_path(); - let mut last_symlink = None; - while let Some(parent) = curr_prefix.parent() { - // make sure we don't traverse out of the root - if curr_prefix == root { - break; - } - - if parent.is_symlink() { - last_symlink = Some(parent); - } - curr_prefix = parent; - } - // we found the last symlink, but we need the chance to - // filter it, so take the parent one more time - Some( - last_symlink - .and_then(Path::parent) - .map(Into::into) - .unwrap_or(prefix), - ) - } - } - - let directory = directory.into(); - // Establish the root directory and any prefix in that root path that is not a - // part of the glob expression. The directory tree is traversed from - // `root`, which may include an invariant prefix from the glob. The - // `prefix` is an integer that specifies how many components from the - // end of the root path must be popped to get the portion of the root - // path that is not present in the glob. The prefix may be empty or may be the - // entirety of `root` depending on `directory` and the glob. - // - // Note that a rooted glob, like in `Path::join`, replaces `directory` when - // establishing the root path. In this case, there is no prefix, as the - // entire root path is present in the glob expression. - let (root, prefix) = match invariant_path_prefix(self.tree.as_ref().tokens(), &directory) { - Some(prefix) => directory.join_and_get_depth(prefix), - _ => (directory, 0), - }; - Anchor { root, prefix } - } -} - -/// Root path and prefix of a `Glob` when walking a particular path. -#[derive(Clone, Debug)] -struct Anchor { - /// The root (starting) directory of the walk. - root: PathBuf, - // TODO: Is there a better name for this? This is a prefix w.r.t. a glob but is a suffix w.r.t. - // the root directory. This can be a bit confusing since either perspective is reasonable - // (and in some contexts one may be more intuitive than the other). - /// The number of components from the end of `root` that are present in the - /// `Glob`'s expression. - prefix: usize, -} - -impl Anchor { - pub fn root_prefix_paths(&self) -> (&Path, &Path) { - self.root.split_at_depth(self.prefix) - } - - pub fn walk_with_behavior(self, behavior: impl Into) -> WalkTree { - WalkTree::with_prefix_and_behavior(self.root, self.prefix, behavior) - } -} - -#[derive(Clone, Debug)] -struct WalkProgram { - complete: Regex, - components: Vec, -} - -impl WalkProgram { - fn compile<'t, I>(tokens: I) -> Result, CompileError> - where - I: IntoIterator>, - I::IntoIter: Clone, - { - let mut regexes = Vec::new(); - for component in token::components(tokens) { - if component - .tokens() - .iter() - .any(|token| token.has_component_boundary()) - { - // Stop at component boundaries, such as tree wildcards or any boundary within a - // group token. - break; - } - regexes.push(Glob::compile(component.tokens().iter().copied())?); - } - Ok(regexes) - } - - fn from_glob(glob: &Glob<'_>) -> Self { - WalkProgram { - complete: glob.program.clone(), - components: WalkProgram::compile(glob.tree.as_ref().tokens()) - .expect("failed to compile glob sub-expressions"), - } - } -} - -/// Describes iteration over matching files in a directory tree. -/// -/// A walker provides the paths walked by a [`Glob`] prior to iteration, most -/// notably the [root path][`GlobWalker::root_prefix_paths`], which may differ -/// from the directory passed to walking functions. When ready, it can be -/// converted into an iterator over matching files. -/// -/// See [`Glob::walker`]. -/// -/// [`Glob`]: crate::Glob -/// [`Glob::walker`]: crate::Glob::walker -/// [`GlobWalker::root_prefix_paths`]: crate::walk::GlobWalker::root_prefix_paths -#[derive(Clone, Debug)] -pub struct GlobWalker { - anchor: Anchor, - program: WalkProgram, -} - -impl GlobWalker { - /// Gets the root and prefix paths. - /// - /// The root path is the path to the walked directory tree. **This path may - /// differ from the directory passed to walking functions like - /// [`Glob::walk`]**, because it may incorporate an invariant path - /// prefix from the glob expression. - /// - /// The prefix path is the invariant path prefix of the glob expression. - /// This path may be empty and is always a suffix of the root path. - /// - /// The following table describes some example paths when using - /// [`Glob::walk`]. - /// - /// | Glob Expression | Directory | Root | Prefix | - /// |---------------------------|--------------|--------------|------------| - /// | `**/*.txt` | `/home/user` | `/home/user` | | - /// | `projects/**/src/**/*.rs` | `.` | `./projects` | `projects` | - /// | `/var/log/**/*.log` | `.` | `/var/log` | `/var/log` | - /// - /// See also [`Entry::root_relative_paths`]. - /// - /// [`Entry::root_relative_paths`]: crate::walk::Entry::root_relative_paths - /// [`Glob::walk`]: crate::Glob::walk - pub fn root_prefix_paths(&self) -> (&Path, &Path) { - self.anchor.root_prefix_paths() - } - - /// Converts a walker into an iterator over matching files in its directory - /// tree. - /// - /// See [`Glob::walk`]. - /// - /// [`Glob::walk`]: crate::Glob::walk - pub fn walk(self) -> impl 'static + FileIterator { - self.walk_with_behavior(WalkBehavior::default()) - } - - /// Converts a walker into an iterator over matching files in its directory - /// tree. - /// - /// See [`Glob::walk_with_behavior`]. - /// - /// [`Glob::walk_with_behavior`]: crate::Glob::walk_with_behavior - pub fn walk_with_behavior( - self, - behavior: impl Into, - ) -> impl 'static + FileIterator { - self.anchor - .walk_with_behavior(behavior) - .filter_map_tree(move |cancellation, separation| { - use itertools::{ - EitherOrBoth::{Both, Left, Right}, - Position::{First, Last, Middle, Only}, - }; - - let filtrate = match separation.filtrate() { - Some(filtrate) => match filtrate.transpose() { - Ok(filtrate) => filtrate, - Err(error) => { - return Separation::from(error.map(Err)); - } - }, - // `Path::walk_with_behavior` yields no residue. - _ => unreachable!(), - }; - let entry = filtrate.as_ref(); - let (_, path) = entry.root_relative_paths(); - let depth = entry.depth().saturating_sub(1); - for (position, candidate) in path - .components() - .filter_map(|component| match component { - Component::Normal(component) => Some(CandidatePath::from(component)), - Component::Prefix(prefix) => Some(CandidatePath::from(prefix.as_os_str())), - _ => None, - }) - .skip(depth) - .zip_longest(self.program.components.iter().skip(depth)) - .with_position() - { - match (position, candidate) { - (First | Middle, Both(candidate, program)) => { - if !program.is_match(candidate.as_ref()) { - // Do not walk directories that do not match the corresponding - // component program. - return filtrate.filter_tree(cancellation).into(); - } - } - (Last | Only, Both(candidate, program)) => { - return if program.is_match(candidate.as_ref()) { - let candidate = CandidatePath::from(path); - if let Some(matched) = self - .program - .complete - .captures(candidate.as_ref()) - .map(MatchedText::from) - .map(MatchedText::into_owned) - { - filtrate - .map(|entry| Ok(GlobEntry { entry, matched })) - .into() - } else { - filtrate.filter_node().into() - } - } else { - // Do not walk directories that do not match the corresponding - // component program. - filtrate.filter_tree(cancellation).into() - }; - } - (_, Left(_candidate)) => { - let candidate = CandidatePath::from(path); - return if let Some(matched) = self - .program - .complete - .captures(candidate.as_ref()) - .map(MatchedText::from) - .map(MatchedText::into_owned) - { - filtrate - .map(|entry| Ok(GlobEntry { entry, matched })) - .into() - } else { - filtrate.filter_node().into() - }; - } - (_, Right(_program)) => { - return filtrate.filter_node().into(); - } - } - } - // If the component loop is not entered, then check for a match. This may - // indicate that the `Glob` is empty and a single invariant path - // may be matched. - let candidate = CandidatePath::from(path); - if let Some(matched) = self - .program - .complete - .captures(candidate.as_ref()) - .map(MatchedText::from) - .map(MatchedText::into_owned) - { - return filtrate - .map(|entry| Ok(GlobEntry { entry, matched })) - .into(); - } - filtrate.filter_node().into() - }) - } -} - -#[derive(Clone, Debug)] -enum FilterAnyProgram { - Empty, - Exhaustive(Regex), - Nonexhaustive(Regex), - Partitioned { - exhaustive: Regex, - nonexhaustive: Regex, - }, -} - -impl FilterAnyProgram { - fn compile<'t, I>(tokens: I) -> Result, BuildError> - where - I: IntoIterator, - I::Item: Pattern<'t>, - I::IntoIter: ExactSizeIterator, - { - let tokens = tokens.into_iter(); - if 0 == tokens.len() { - Ok(None) - } else { - crate::any(tokens).map(|any| Some(any.program)) - } - } - - fn from_partitions<'t, I>(exhaustive: I, nonexhaustive: I) -> Result - where - I: IntoIterator, - I::Item: Pattern<'t>, - I::IntoIter: ExactSizeIterator, - { - use FilterAnyProgram::{Empty, Exhaustive, Nonexhaustive, Partitioned}; - - // It is important to distinguish between empty _partitions_ and empty - // _expressions_ here. `FilterAnyProgram::compile` discards empty - // partitions. When matching against an empty path, an explicit empty - // _expression_ must match but an empty _partition_ must not (such - // a partition must never match anything). - Ok( - match ( - FilterAnyProgram::compile(exhaustive)?, - FilterAnyProgram::compile(nonexhaustive)?, - ) { - (Some(exhaustive), Some(nonexhaustive)) => Partitioned { - exhaustive, - nonexhaustive, - }, - (Some(exhaustive), None) => Exhaustive(exhaustive), - (None, Some(nonexhaustive)) => Nonexhaustive(nonexhaustive), - (None, None) => Empty, - }, - ) - } - - pub fn residue(&self, candidate: CandidatePath<'_>) -> Option { - use FilterAnyProgram::{Exhaustive, Nonexhaustive, Partitioned}; - - match self { - Exhaustive(ref exhaustive) | Partitioned { ref exhaustive, .. } - if exhaustive.is_match(candidate.as_ref()) => - { - Some(EntryResidue::Tree) - } - Nonexhaustive(ref nonexhaustive) - | Partitioned { - ref nonexhaustive, .. - } if nonexhaustive.is_match(candidate.as_ref()) => Some(EntryResidue::File), - _ => None, - } - } -} - -/// Negated glob combinator that efficiently filters file entries against -/// patterns. -#[derive(Clone, Debug)] -pub struct FilterAny { - program: FilterAnyProgram, -} - -impl FilterAny { - /// Combines patterns into a `FilterAny`. - /// - /// This function accepts an [`IntoIterator`] with items that implement - /// [`Pattern`], such as [`Glob`] and `&str`. - /// - /// # Errors - /// - /// Returns an error if any of the inputs fail to build. If the inputs are a - /// compiled [`Program`] type such as [`Glob`], then this only occurs if - /// the compiled program is too large. - /// - /// [`Glob`]: crate::Glob - /// [`IntoIterator`]: std::iter::IntoIterator - /// [`Pattern`]: crate::Pattern - /// [`Program`]: crate::Program - pub fn any<'t, I>(patterns: I) -> Result - where - I: IntoIterator, - I::Item: Pattern<'t>, - { - let (exhaustive, nonexhaustive) = patterns - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .map_err(Into::into)? - .into_iter() - .partition::, _>(|tree| token::is_exhaustive(tree.as_ref().tokens())); - Ok(FilterAny { - program: FilterAnyProgram::from_partitions(exhaustive, nonexhaustive)?, - }) - } - - /// Gets the appropriate [`EntryResidue`] for the given [`Entry`]. - /// - /// Notably, this function returns [`EntryResidue::Tree`] if the [`Entry`] - /// matches an [exhaustive glob expression][`Program::is_exhaustive`], - /// such as `secret/**`. - /// - /// [`Entry`]: crate::walk::Entry - /// [`EntryResidue`]: crate::walk::EntryResidue - /// [`EntryResidue::Tree`]: crate::walk::EntryResidue::Tree - /// [`Program::is_exhaustive`]: crate::Program::is_exhaustive - pub fn residue(&self, entry: &dyn Entry) -> Option { - let candidate = CandidatePath::from(entry.root_relative_paths().1); - self.program.residue(candidate) - } -} - -/// Describes a file with a path matching a [`Glob`] in a directory tree. -/// -/// See [`Glob::walk`]. -/// -/// [`Glob`]: crate::Glob -/// [`Glob::walk`]: crate::Glob::walk -#[derive(Debug)] -pub struct GlobEntry { - entry: TreeEntry, - matched: MatchedText<'static>, -} - -impl GlobEntry { - /// Converts the entry to the relative [`CandidatePath`]. - /// - /// **This differs from [`Entry::path`] and [`Entry::into_path`], which are - /// native paths and typically include the root path.** The - /// [`CandidatePath`] is always relative to [the root - /// path][`Entry::root_relative_paths`]. - /// - /// [`CandidatePath`]: crate::CandidatePath - /// [`Entry::into_path`]: crate::walk::Entry::into_path - /// [`Entry::path`]: crate::walk::Entry::path - /// [`matched`]: crate::walk::GlobEntry::matched - pub fn to_candidate_path(&self) -> CandidatePath<'_> { - self.matched.to_candidate_path() - } - - /// Gets the matched text in the path of the file. - pub fn matched(&self) -> &MatchedText<'static> { - &self.matched - } -} - -impl Entry for GlobEntry { - fn into_path(self) -> PathBuf { - self.entry.into_path() - } - - fn path(&self) -> &Path { - self.entry.path() - } - - fn root_relative_paths(&self) -> (&Path, &Path) { - self.entry.root_relative_paths() - } - - fn file_type(&self) -> FileType { - self.entry.file_type() - } - - fn metadata(&self) -> Result { - self.entry.metadata().map_err(WalkError::from) - } - - // TODO: This needs some work and requires some explanation when applied to - // globs. - fn depth(&self) -> usize { - self.entry.depth() - } -} - -impl From for TreeEntry { - fn from(entry: GlobEntry) -> Self { - entry.entry - } -} diff --git a/crates/turborepo-wax/tests/walk.rs b/crates/turborepo-wax/tests/walk.rs deleted file mode 100644 index bb7c926a09e44..0000000000000 --- a/crates/turborepo-wax/tests/walk.rs +++ /dev/null @@ -1,268 +0,0 @@ -#![cfg(feature = "walk")] - -use std::{collections::HashSet, path::PathBuf}; - -use build_fs_tree::{dir, file, Build, FileSystemTree}; -use tempfile::TempDir; -use wax::{ - walk::{Entry, FileIterator, WalkBehavior}, - Glob, -}; - -// TODO: Rust's testing framework does not provide a mechanism for maintaining -// shared state. This means that tests that write to the file system must -// do so individually rather than writing before and after all tests have -// run. This should probably be avoided. - -/// Writes a testing directory tree to a temporary location on the file system. -fn temptree() -> (TempDir, PathBuf) { - let root = tempfile::tempdir().unwrap(); - let tree: FileSystemTree<&str, &str> = dir! { - "doc" => dir! { - "guide.md" => file!(""), - }, - "src" => dir! { - "glob.rs" => file!(""), - "lib.rs" => file!(""), - }, - "tests" => dir! { - "walk.rs" => file!(""), - }, - "README.md" => file!(""), - }; - let path = root.path().join("project"); - tree.build(&path).unwrap(); - (root, path) -} - -/// Writes a testing directory tree that includes a reentrant symbolic link to a -/// temporary location on the file system. -#[cfg(any(unix, windows))] -fn temptree_with_cyclic_link() -> (TempDir, PathBuf) { - use std::{io, path::Path}; - - #[cfg(unix)] - fn link(target: impl AsRef, link: impl AsRef) -> io::Result<()> { - std::os::unix::fs::symlink(target, link) - } - - #[cfg(windows)] - fn link(target: impl AsRef, link: impl AsRef) -> io::Result<()> { - std::os::windows::fs::symlink_dir(target, link) - } - - // Get a temporary tree and create a reentrant symbolic link. - let (root, path) = temptree(); - link(path.as_path(), path.join("tests/cycle")).unwrap(); - (root, path) -} - -#[test] -fn walk_with_tree() { - let (_root, path) = temptree(); - - let glob = Glob::new("**").unwrap(); - let paths: HashSet<_> = glob - .walk(&path) - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!( - paths, - [ - #[allow(clippy::redundant_clone)] - path.to_path_buf(), - path.join("doc"), - path.join("doc/guide.md"), - path.join("src"), - path.join("src/glob.rs"), - path.join("src/lib.rs"), - path.join("tests"), - path.join("tests/walk.rs"), - path.join("README.md"), - ] - .into_iter() - .collect(), - ); -} - -#[test] -fn walk_with_invariant_terminating_component() { - let (_root, path) = temptree(); - - let glob = Glob::new("**/*.md").unwrap(); - let paths: HashSet<_> = glob - .walk(&path) - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!( - paths, - IntoIterator::into_iter([path.join("doc/guide.md"), path.join("README.md"),]).collect(), - ); -} - -#[test] -fn walk_with_invariant_intermediate_component() { - let (_root, path) = temptree(); - - let glob = Glob::new("**/src/**/*.rs").unwrap(); - let paths: HashSet<_> = glob - .walk(&path) - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!( - paths, - IntoIterator::into_iter([path.join("src/glob.rs"), path.join("src/lib.rs"),]).collect(), - ); -} - -#[test] -fn walk_with_invariant_glob() { - let (_root, path) = temptree(); - - let glob = Glob::new("src/lib.rs").unwrap(); - let paths: HashSet<_> = glob - .walk(&path) - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!(paths, [path.join("src/lib.rs")].into_iter().collect(),); -} - -#[test] -fn walk_with_invariant_partitioned_glob() { - let (_root, path) = temptree(); - - let (prefix, glob) = Glob::new("src/lib.rs").unwrap().partition(); - let paths: HashSet<_> = glob - .walk(path.join(prefix)) - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!(paths, [path.join("src/lib.rs")].into_iter().collect(),); -} - -#[test] -fn walk_with_not() { - let (_root, path) = temptree(); - - let glob = Glob::new("**/*.{md,rs}").unwrap(); - let paths: HashSet<_> = glob - .walk(&path) - .not(["tests/**"]) - .unwrap() - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!( - paths, - [ - path.join("doc/guide.md"), - path.join("src/glob.rs"), - path.join("src/lib.rs"), - path.join("README.md"), - ] - .into_iter() - .collect(), - ); -} - -#[test] -fn walk_with_depth() { - let (_root, path) = temptree(); - - let glob = Glob::new("**").unwrap(); - let paths: HashSet<_> = glob - .walk_with_behavior( - &path, - WalkBehavior { - depth: 1, - ..Default::default() - }, - ) - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!( - paths, - [ - #[allow(clippy::redundant_clone)] - path.to_path_buf(), - path.join("doc"), - path.join("src"), - path.join("tests"), - path.join("README.md"), - ] - .into_iter() - .collect(), - ); -} - -#[test] -#[cfg(any(unix, windows))] -fn walk_with_cyclic_link_file() { - use wax::walk::LinkBehavior; - - let (_root, path) = temptree_with_cyclic_link(); - - let glob = Glob::new("**").unwrap(); - let paths: HashSet<_> = glob - .walk_with_behavior(&path, LinkBehavior::ReadFile) - .flatten() - .map(|entry| entry.into_path()) - .collect(); - assert_eq!( - paths, - [ - #[allow(clippy::redundant_clone)] - path.to_path_buf(), - path.join("README.md"), - path.join("doc"), - path.join("doc/guide.md"), - path.join("src"), - path.join("src/glob.rs"), - path.join("src/lib.rs"), - path.join("tests"), - path.join("tests/cycle"), - path.join("tests/walk.rs"), - ] - .into_iter() - .collect(), - ); -} - -#[test] -#[cfg(any(unix, windows))] -fn walk_with_cyclic_link_target() { - use wax::walk::LinkBehavior; - - let (_root, path) = temptree_with_cyclic_link(); - - // Collect paths into `Vec`s so that duplicates can be detected. - let expected = vec![ - #[allow(clippy::redundant_clone)] - path.to_path_buf(), - path.join("README.md"), - path.join("doc"), - path.join("doc/guide.md"), - path.join("src"), - path.join("src/glob.rs"), - path.join("src/lib.rs"), - path.join("tests"), - path.join("tests/walk.rs"), - ]; - let glob = Glob::new("**").unwrap(); - let mut paths: Vec<_> = glob - .walk_with_behavior(&path, LinkBehavior::ReadTarget) - .flatten() - // Take an additional item. This prevents an infinite loop if there is a - // problem with detecting the cycle while also introducing unexpected - // files so that the error can be detected. - .take(expected.len() + 1) - .map(|entry| entry.into_path()) - .collect(); - paths.sort_unstable(); - assert_eq!(paths, expected); -} diff --git a/crates/turborepo/Cargo.toml b/crates/turborepo/Cargo.toml index 7fc037007a345..f300fe1041a5e 100644 --- a/crates/turborepo/Cargo.toml +++ b/crates/turborepo/Cargo.toml @@ -1,23 +1,13 @@ -[package] -name = "turbo" -version = "0.1.0" -edition = "2021" -license = "MIT" - -[features] -# By default, we enable rustls-tls for reqwest via downstream transitive features. -# This is for the convenience of running daily dev workflows, i.e running -# `cargo xxx` without explicitly specifying features, not that we want to -# promote this as default backend. -default = ["rustls-tls", "turborepo-lib/daemon-package-discovery"] -native-tls = ["turborepo-lib/native-tls"] -rustls-tls = ["turborepo-lib/rustls-tls"] -pprof = ["turborepo-lib/pprof"] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] build-target = "0.4.0" +[dependencies] +anyhow = { workspace = true, features = ["backtrace"] } +turborepo-lib = { workspace = true, default-features = false } + +[dependencies.miette] +workspace = true + [dev-dependencies] assert_cmd = { workspace = true } camino = { workspace = true } @@ -29,11 +19,17 @@ tempfile = { workspace = true } turbopath = { workspace = true } which = { workspace = true } +[features] +default = ["rustls-tls", "turborepo-lib/daemon-package-discovery"] +native-tls = ["turborepo-lib/native-tls"] +pprof = ["turborepo-lib/pprof"] +rustls-tls = ["turborepo-lib/rustls-tls"] [lints] workspace = true -[dependencies] -anyhow = { workspace = true, features = ["backtrace"] } -miette.workspace = true -turborepo-lib = { workspace = true, default-features = false } +[package] +edition = "2021" +license-file = "LICENSE" +name = "turbo" +version = "0.1.0" diff --git a/crates/turborepo/README.md b/crates/turborepo/README.md deleted file mode 100644 index 378aec0222e68..0000000000000 --- a/crates/turborepo/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# turbo cli - -## Build Requirement - -1. Install `protobuf` and `golang` (note: Go must be pinned to v1.20.x, see https://github.com/vercel/turborepo/issues/5918 for details) - -- On macOS: `brew install protobuf protoc-gen-go protoc-gen-go-grpc go@1.20 capnp` -- On Windows: `choco install golang --version=1.20.7` and `choco install protoc make python3 mingw` -- On Ubuntu: `apt-get install golang golang-goprotobuf-dev` - -2. `go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.0` -3. `go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2.0` diff --git a/crates/turborepo/src/main.rs b/crates/turborepo/Source/main.rs similarity index 100% rename from crates/turborepo/src/main.rs rename to crates/turborepo/Source/main.rs diff --git a/crates/turborepo/tests/boundaries.rs b/crates/turborepo/tests/boundaries.rs deleted file mode 100644 index 69a1cedf96ef8..0000000000000 --- a/crates/turborepo/tests/boundaries.rs +++ /dev/null @@ -1,13 +0,0 @@ -mod common; - -#[test] -fn test_boundaries() -> Result<(), anyhow::Error> { - check_json!( - "boundaries", - "npm@10.5.0", - "query", - "get boundaries lints" => "query { boundaries { items { message import } } }", - ); - - Ok(()) -} diff --git a/crates/turborepo/tests/common/mod.rs b/crates/turborepo/tests/common/mod.rs deleted file mode 100644 index dd81ac178f7dc..0000000000000 --- a/crates/turborepo/tests/common/mod.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::{path::Path, process::Command}; - -use turbopath::AbsoluteSystemPath; -use which::which; - -pub fn setup_fixture( - fixture: &str, - package_manager: &str, - test_dir: &Path, -) -> Result<(), anyhow::Error> { - let script_path = AbsoluteSystemPath::new(env!("CARGO_MANIFEST_DIR"))?.join_components(&[ - "..", - "..", - "turborepo-tests", - "helpers", - "setup_integration_test.sh", - ]); - - let unix_script_path = if cfg!(windows) { - script_path.as_str().replace("\\", "/") - } else { - script_path.to_string() - }; - - let bash = which("bash")?; - - Command::new(bash) - .arg("-c") - .arg(format!( - "{} {} {}", - unix_script_path, fixture, package_manager - )) - .current_dir(test_dir) - .spawn()? - .wait()?; - - Ok(()) -} - -/// Executes a command and snapshots the output as JSON. -/// -/// Takes fixture, package manager, and command, and sets of arguments. -/// Creates a snapshot file for each set of arguments. -/// Note that the command must return valid JSON -#[macro_export] -macro_rules! check_json { - ($fixture:expr, $package_manager:expr, $command:expr, $($name:expr => $query:expr,)*) => { - { - let tempdir = tempfile::tempdir()?; - $crate::common::setup_fixture($fixture, $package_manager, tempdir.path())?; - $( - println!("Running command: `turbo {} {}` in {}", $command, $query, $fixture); - let output = assert_cmd::Command::cargo_bin("turbo")? - .arg($command) - .arg($query) - .current_dir(tempdir.path()) - .output()?; - - let stdout = String::from_utf8(output.stdout)?; - let stderr = String::from_utf8_lossy(&output.stderr); - - println!("stderr: {}", stderr); - - let query_output: serde_json::Value = serde_json::from_str(&stdout)?; - let test_name = format!( - "{}_{}_({})", - $fixture, - $name.replace(' ', "_"), - $package_manager - ); - insta::assert_json_snapshot!(test_name, query_output); - )* - } - } -} diff --git a/crates/turborepo/tests/query.rs b/crates/turborepo/tests/query.rs deleted file mode 100644 index 4bc695744e6df..0000000000000 --- a/crates/turborepo/tests/query.rs +++ /dev/null @@ -1,105 +0,0 @@ -mod common; - -#[test] -fn test_query() -> Result<(), anyhow::Error> { - check_json!( - "basic_monorepo", - "npm@10.5.0", - "query", - "get package that doesn't exist" => "query { package(name: \"doesnotexist\") { path } }", - "get packages with less than 1 dependents" => "query { packages(filter: {lessThan: {field: DIRECT_DEPENDENT_COUNT, value: 1}}) { items { name directDependents { length } } } }", - "get packages with more than 0 dependents" => "query { packages(filter: {greaterThan: {field: DIRECT_DEPENDENT_COUNT, value: 0}}) { items { name directDependents { length } } } }", - ); - - Ok(()) -} - -#[cfg(not(windows))] -#[test] -fn test_double_symlink() -> Result<(), anyhow::Error> { - check_json!( - "oxc_repro", - "npm@10.5.0", - "query", - "get_dependencies" => "query { - file(path: \"./index.js\") { - path - dependencies { - files { items { path } } - errors { items { message import } } - } - } - }", - ); - Ok(()) -} - -#[test] -fn test_ast() -> Result<(), anyhow::Error> { - // Separate because the `\\` -> `/` filter isn't compatible with ast - check_json!( - "turbo_trace", - "npm@10.5.0", - "query", - "get `main.ts` with ast" => "query { file(path: \"main.ts\") { path ast } }", - ); - - Ok(()) -} - -#[test] -fn test_trace() -> Result<(), anyhow::Error> { - insta::with_settings!({ filters => vec![(r"\\\\", "/")]}, { - check_json!( - "turbo_trace", - "npm@10.5.0", - "query", - "get `main.ts`" => "query { file(path: \"main.ts\") { path } }", - "get `main.ts` with dependencies" => "query { file(path: \"main.ts\") { path, dependencies { files { items { path } } } } }", - "get `button.tsx` with dependencies" => "query { file(path: \"button.tsx\") { path, dependencies { files { items { path } } } } }", - "get `circular.ts` with dependencies" => "query { file(path: \"circular.ts\") { path dependencies { files { items { path } } } } }", - "get `invalid.ts` with dependencies" => "query { file(path: \"invalid.ts\") { path dependencies { files { items { path } } errors { items { import } } } } }", - "get `main.ts` with depth = 0" => "query { file(path: \"main.ts\") { path dependencies(depth: 1) { files { items { path } } } } }", - "get `with_prefix.ts` with dependencies" => "query { file(path: \"with_prefix.ts\") { path dependencies { files { items { path } } } } }", - "get `import_value_and_type.ts` with all dependencies" => "query { file(path: \"import_value_and_type.ts\") { path dependencies(importType: ALL) { files { items { path } } } } }", - "get `import_value_and_type.ts` with type dependencies" => "query { file(path: \"import_value_and_type.ts\") { path dependencies(importType: TYPES) { files { items { path } } } } }", - "get `import_value_and_type.ts` with value dependencies" => "query { file(path: \"import_value_and_type.ts\") { path dependencies(importType: VALUES) { files { items { path } } } } }", - "get `incorrect_extension.mjs` with dependencies" => "query { file(path: \"incorrect_extension.mjs\") { path dependencies(depth: 1) { files { items { path } } } } }", - "get `export_all.js` with dependencies" => "query { file(path: \"export_all.js\") { path dependencies { files { items { path } } } } }", - "get `export_named.js` with dependencies" => "query { file(path: \"export_named.js\") { path dependencies { files { items { path } } } } }", - ); - - Ok(()) - }) -} - -#[test] -fn test_trace_on_monorepo() -> Result<(), anyhow::Error> { - insta::with_settings!({ filters => vec![(r"\\\\", "/")]}, { - check_json!( - "turbo_trace_monorepo", - "npm@10.5.0", - "query", - "get `apps/my-app/index.ts` with dependencies" => "query { file(path: \"apps/my-app/index.ts\") { path dependencies { files { items { path } } errors { items { message } } } } }", - "get `packages/utils/index.ts` with dependents" => "query { file(path: \"packages/utils/index.ts\") { path dependents { files { items { path } } errors { items { message } } } } }", - "get `packages/another/index.js` with dependents" => "query { file(path: \"packages/another/index.jsx\") { path dependents { files { items { path } } errors { items { message } } } } }", - ); - - Ok(()) - }) -} - -#[test] -fn test_reverse_trace() -> Result<(), anyhow::Error> { - check_json!( - "turbo_trace", - "npm@10.5.0", - "query", - "get `button.tsx` with dependents" => "query { file(path: \"button.tsx\") { path dependents { files { items { path } } } } }", - "get `link.tsx` with all dependents" => "query { file(path: \"link.tsx\") { path dependents(importType: ALL) { files { items { path } } } } }", - "get `link.tsx` with type dependents" => "query { file(path: \"link.tsx\") { path dependents(importType: TYPES) { files { items { path } } } } }", - "get `link.tsx` with value dependents" => "query { file(path: \"link.tsx\") { path dependents(importType: VALUES) { files { items { path } } } } }", - ); - - Ok(()) -} diff --git a/crates/turborepo/tests/snapshots/boundaries__boundaries_get_boundaries_lints_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/boundaries__boundaries_get_boundaries_lints_(npm@10.5.0).snap deleted file mode 100644 index d1dc57842e99e..0000000000000 --- a/crates/turborepo/tests/snapshots/boundaries__boundaries_get_boundaries_lints_(npm@10.5.0).snap +++ /dev/null @@ -1,28 +0,0 @@ ---- -source: crates/turborepo/tests/boundaries.rs -expression: query_output ---- -{ - "data": { - "boundaries": { - "items": [ - { - "message": "cannot import file `../../packages/another/index.jsx` because it leaves the package", - "import": "../../packages/another/index.jsx" - }, - { - "message": "importing from a type declaration package, but import is not declared as a type-only import", - "import": "ship" - }, - { - "message": "importing from a type declaration package, but import is not declared as a type-only import", - "import": "@types/ship" - }, - { - "message": "cannot import package `module-package` because it is not a dependency", - "import": "module-package" - } - ] - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_package_that_doesn't_exist_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__basic_monorepo_get_package_that_doesn't_exist_(npm@10.5.0).snap deleted file mode 100644 index d56fd0bb66ab4..0000000000000 --- a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_package_that_doesn't_exist_(npm@10.5.0).snap +++ /dev/null @@ -1,21 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": null, - "errors": [ - { - "message": "Package not found: doesnotexist", - "locations": [ - { - "line": 1, - "column": 9 - } - ], - "path": [ - "package" - ] - } - ] -} diff --git a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_less_than_1_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_less_than_1_dependents_(npm@10.5.0).snap deleted file mode 100644 index 8d061631ed3c2..0000000000000 --- a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_less_than_1_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,30 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "packages": { - "items": [ - { - "name": "//", - "directDependents": { - "length": 0 - } - }, - { - "name": "another", - "directDependents": { - "length": 0 - } - }, - { - "name": "my-app", - "directDependents": { - "length": 0 - } - } - ] - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_less_than_2_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_less_than_2_dependents_(npm@10.5.0).snap deleted file mode 100644 index 6f1ca882186d4..0000000000000 --- a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_less_than_2_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "packages": { - "items": [ - { - "name": "//", - "directDependents": { - "length": 0 - } - }, - { - "name": "another", - "directDependents": { - "length": 0 - } - }, - { - "name": "my-app", - "directDependents": { - "length": 0 - } - }, - { - "name": "util", - "directDependents": { - "length": 1 - } - } - ] - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_more_than_0_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_more_than_0_dependents_(npm@10.5.0).snap deleted file mode 100644 index b27137abb9d8f..0000000000000 --- a/crates/turborepo/tests/snapshots/query__basic_monorepo_get_packages_with_more_than_0_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "packages": { - "items": [ - { - "name": "util", - "directDependents": { - "length": 1 - } - } - ] - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__oxc_repro_get_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__oxc_repro_get_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 2e879b27d8d8f..0000000000000 --- a/crates/turborepo/tests/snapshots/query__oxc_repro_get_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "index.js", - "dependencies": { - "files": { - "items": [ - { - "path": "nm/index.js" - } - ] - }, - "errors": { - "items": [] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`button.tsx`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`button.tsx`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 570c87caee9d5..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`button.tsx`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "button.tsx", - "dependencies": { - "files": { - "items": [ - { - "path": "button.css" - }, - { - "path": "button.json" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`button.tsx`_with_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`button.tsx`_with_dependents_(npm@10.5.0).snap deleted file mode 100644 index e49db2b924ed6..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`button.tsx`_with_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "button.tsx", - "dependents": { - "files": { - "items": [ - { - "path": "invalid.ts" - }, - { - "path": "main.ts" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`circular.ts`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`circular.ts`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index e4950e2aa3f9d..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`circular.ts`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "circular.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "circular2.ts" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`export_all.js`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`export_all.js`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 9ce3db7acd226..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`export_all.js`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "export_all.js", - "dependencies": { - "files": { - "items": [ - { - "path": "bar.js" - }, - { - "path": "foo.js" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`export_named.js`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`export_named.js`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index c277688efbc9a..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`export_named.js`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "export_named.js", - "dependencies": { - "files": { - "items": [ - { - "path": "bar.js" - }, - { - "path": "foo.js" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_all_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_all_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 46eabec764c43..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_all_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "import_value_and_type.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "link.tsx" - }, - { - "path": "types.ts" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_type_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_type_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 04f12c8b158c3..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_type_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "import_value_and_type.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "types.ts" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_value_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_value_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 1cc31c9e9f2e3..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`import_value_and_type.ts`_with_value_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "import_value_and_type.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "link.tsx" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`incorrect_extension.mjs`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`incorrect_extension.mjs`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index ba1409b9dd8a2..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`incorrect_extension.mjs`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "incorrect_extension.mjs", - "dependencies": { - "files": { - "items": [ - { - "path": "bar.js" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`invalid.ts`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`invalid.ts`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 963d257ac7d21..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`invalid.ts`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,33 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "invalid.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "button.css" - }, - { - "path": "button.json" - }, - { - "path": "button.tsx" - } - ] - }, - "errors": { - "items": [ - { - "import": "import foo from \"./non-existent-file.js\";\nimport { Button } from \"./button.tsx\";\n" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_all_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_all_dependents_(npm@10.5.0).snap deleted file mode 100644 index c4355ebb18e29..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_all_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,26 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "link.tsx", - "dependents": { - "files": { - "items": [ - { - "path": "import_just_type.ts" - }, - { - "path": "import_just_value.ts" - }, - { - "path": "import_value_and_type.ts" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_type_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_type_dependents_(npm@10.5.0).snap deleted file mode 100644 index 5549ac43b44e1..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_type_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "link.tsx", - "dependents": { - "files": { - "items": [ - { - "path": "import_just_type.ts" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_value_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_value_dependents_(npm@10.5.0).snap deleted file mode 100644 index e25a771e6f9cb..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`link.tsx`_with_value_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "link.tsx", - "dependents": { - "files": { - "items": [ - { - "path": "import_just_value.ts" - }, - { - "path": "import_value_and_type.ts" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_(npm@10.5.0).snap deleted file mode 100644 index 41503d9c76a44..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_(npm@10.5.0).snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "main.ts" - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_ast_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_ast_(npm@10.5.0).snap deleted file mode 100644 index 411469777270d..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_ast_(npm@10.5.0).snap +++ /dev/null @@ -1,219 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "main.ts", - "ast": { - "type": "Module", - "span": { - "start": 1, - "end": 119 - }, - "body": [ - { - "type": "ImportDeclaration", - "span": { - "start": 1, - "end": 39 - }, - "specifiers": [ - { - "type": "ImportSpecifier", - "span": { - "start": 10, - "end": 16 - }, - "local": { - "type": "Identifier", - "span": { - "start": 10, - "end": 16 - }, - "ctxt": 0, - "value": "Button", - "optional": false - }, - "imported": null, - "isTypeOnly": false - } - ], - "source": { - "type": "StringLiteral", - "span": { - "start": 24, - "end": 38 - }, - "value": "./button.tsx", - "raw": "\"./button.tsx\"" - }, - "typeOnly": false, - "with": null, - "phase": "evaluation" - }, - { - "type": "ImportDeclaration", - "span": { - "start": 40, - "end": 64 - }, - "specifiers": [ - { - "type": "ImportDefaultSpecifier", - "span": { - "start": 47, - "end": 50 - }, - "local": { - "type": "Identifier", - "span": { - "start": 47, - "end": 50 - }, - "ctxt": 0, - "value": "foo", - "optional": false - } - } - ], - "source": { - "type": "StringLiteral", - "span": { - "start": 56, - "end": 63 - }, - "value": "./foo", - "raw": "\"./foo\"" - }, - "typeOnly": false, - "with": null, - "phase": "evaluation" - }, - { - "type": "VariableDeclaration", - "span": { - "start": 66, - "end": 94 - }, - "ctxt": 0, - "kind": "const", - "declare": false, - "declarations": [ - { - "type": "VariableDeclarator", - "span": { - "start": 72, - "end": 93 - }, - "id": { - "type": "Identifier", - "span": { - "start": 72, - "end": 78 - }, - "ctxt": 0, - "value": "button", - "optional": false, - "typeAnnotation": null - }, - "init": { - "type": "NewExpression", - "span": { - "start": 81, - "end": 93 - }, - "ctxt": 0, - "callee": { - "type": "Identifier", - "span": { - "start": 85, - "end": 91 - }, - "ctxt": 0, - "value": "Button", - "optional": false - }, - "arguments": [], - "typeArguments": null - }, - "definite": false - } - ] - }, - { - "type": "ExpressionStatement", - "span": { - "start": 96, - "end": 112 - }, - "expression": { - "type": "CallExpression", - "span": { - "start": 96, - "end": 111 - }, - "ctxt": 0, - "callee": { - "type": "MemberExpression", - "span": { - "start": 96, - "end": 109 - }, - "object": { - "type": "Identifier", - "span": { - "start": 96, - "end": 102 - }, - "ctxt": 0, - "value": "button", - "optional": false - }, - "property": { - "type": "Identifier", - "span": { - "start": 103, - "end": 109 - }, - "value": "render" - } - }, - "arguments": [], - "typeArguments": null - } - }, - { - "type": "ExpressionStatement", - "span": { - "start": 113, - "end": 119 - }, - "expression": { - "type": "CallExpression", - "span": { - "start": 113, - "end": 118 - }, - "ctxt": 0, - "callee": { - "type": "Identifier", - "span": { - "start": 113, - "end": 116 - }, - "ctxt": 0, - "value": "foo", - "optional": false - }, - "arguments": [], - "typeArguments": null - } - } - ], - "interpreter": null - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 8b647d5a2b9af..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "main.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "bar.js" - }, - { - "path": "button.css" - }, - { - "path": "button.json" - }, - { - "path": "button.tsx" - }, - { - "path": "foo.js" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_depth_=_0_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_depth_=_0_(npm@10.5.0).snap deleted file mode 100644 index 30ae77ff69475..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`main.ts`_with_depth_=_0_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "main.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "button.tsx" - }, - { - "path": "foo.js" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`with_prefix.ts`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_get_`with_prefix.ts`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 062887b12ac53..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_get_`with_prefix.ts`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "with_prefix.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "bar.js" - }, - { - "path": "foo.js" - } - ] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`apps__my-app__index.ts`_with_dependencies_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`apps__my-app__index.ts`_with_dependencies_(npm@10.5.0).snap deleted file mode 100644 index 08f519ad0fe36..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`apps__my-app__index.ts`_with_dependencies_(npm@10.5.0).snap +++ /dev/null @@ -1,44 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "apps/my-app/index.ts", - "dependencies": { - "files": { - "items": [ - { - "path": "apps/my-app/types.ts" - }, - { - "path": "packages/another/index.jsx" - }, - { - "path": "packages/module-package/my-module.mjs" - }, - { - "path": "packages/package-with-conditions/index.mjs" - }, - { - "path": "packages/ship-types/index.ts" - }, - { - "path": "packages/utils/index.ts" - }, - { - "path": "packages/utils/my-hook.ts" - }, - { - "path": "packages/utils/types.ts" - } - ] - }, - "errors": { - "items": [] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`packages__another__index.js`_with_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`packages__another__index.js`_with_dependents_(npm@10.5.0).snap deleted file mode 100644 index 2f3b09cc59c5f..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`packages__another__index.js`_with_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,26 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "packages/another/index.jsx", - "dependents": { - "files": { - "items": [ - { - "path": "apps/my-app/index.ts" - }, - { - "path": "apps/my-app/types.ts" - } - ] - }, - "errors": { - "items": [] - } - } - } - } -} diff --git a/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`packages__utils__index.ts`_with_dependents_(npm@10.5.0).snap b/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`packages__utils__index.ts`_with_dependents_(npm@10.5.0).snap deleted file mode 100644 index 963a95763e00e..0000000000000 --- a/crates/turborepo/tests/snapshots/query__turbo_trace_monorepo_get_`packages__utils__index.ts`_with_dependents_(npm@10.5.0).snap +++ /dev/null @@ -1,26 +0,0 @@ ---- -source: crates/turborepo/tests/query.rs -expression: query_output ---- -{ - "data": { - "file": { - "path": "packages/utils/index.ts", - "dependents": { - "files": { - "items": [ - { - "path": "apps/my-app/index.ts" - }, - { - "path": "packages/another/index.jsx" - } - ] - }, - "errors": { - "items": [] - } - } - } - } -} diff --git a/docs/README.MD b/docs/README.MD deleted file mode 100644 index e698f9100811d..0000000000000 --- a/docs/README.MD +++ /dev/null @@ -1,9 +0,0 @@ -# GitHub Action for Validating Documentation Links - -This action ensures that internal links in `.mdx` files in the `/docs/` directory are valid. It runs on every pull request that includes changes to these files. - -The action is triggered by the workflow defined in `.github/workflows/docs.yml`. - -## Usage - -pnpm check-links diff --git a/docs/src/markdown.ts b/docs/Source/markdown.ts similarity index 100% rename from docs/src/markdown.ts rename to docs/Source/markdown.ts diff --git a/docs/src/validate-docs-links.ts b/docs/Source/validate-docs-links.ts similarity index 100% rename from docs/src/validate-docs-links.ts rename to docs/Source/validate-docs-links.ts diff --git a/docs/pack-docs/core-concepts.mdx b/docs/pack-docs/core-concepts.mdx new file mode 100644 index 0000000000000..4f3cd94467ae5 --- /dev/null +++ b/docs/pack-docs/core-concepts.mdx @@ -0,0 +1,42 @@ +--- +title: Core Concepts +description: Learn about the innovative architecture that powers Turbopack's speed improvements. +--- + +Let’s dive deep into the internals of Turbopack to figure out why it’s so fast. + +## The Turbo engine + +Turbopack is so fast because it’s built on a reusable library for Rust which enables incremental computation known as the Turbo engine. Here’s how it works: + +### Function-level caching + +In a Turbo engine-powered program, you can mark certain functions as ‘to be remembered’. When these functions are called, the Turbo engine will remember **what they were called with**, and **what they returned**. It’ll then save it in an in-memory cache. + +Here’s a simplified example of what this might look like in a bundler: + +![](/images/docs/pack/turbo-engine-first-run.png) + +We start with calling `readFile` on two files, `api.ts` and `sdk.ts`. We then `bundle` those files, `concat` them together, and end up with the `fullBundle` at the end. The results of all of those function calls get saved in the cache for later. + +Let’s imagine that we’re running on a dev server. You save the `sdk.ts` file on your machine. Turbopack receives the file system event, and knows it needs to recompute `readFile("sdk.ts")`: + +![](/images/docs/pack/turbo-engine-second-run.png) + +Since the result of `sdk.ts` has changed, we need to `bundle` it again, which then needs to be concatenated again. + +Crucially, `api.ts` hasn’t changed. We read its result from the cache and pass that to `concat` instead. So we save time by not reading it and re-bundling it again. + +Now imagine this in a real bundler, with thousands of files to read and transformations to execute. The mental model is the same. You can save enormous amounts of work by remembering the result of function calls and not re-doing work that’s been done before. + +### The cache + +The Turbo engine currently stores its cache in memory. This means the cache will last as long as the process running it - which works well for a dev server. When you run `next dev --turbo` in Next.js 13+, you’ll start a cache with the Turbo engine. When you cancel your dev server, the cache gets cleared. + +In the future, we’re planning to persist this cache - either to the filesystem, or to a remote cache like Turborepo’s. This will mean that Turbopack could remember work done _across runs and machines._ + +### How does it help? + +This approach makes Turbopack extremely fast at computing incremental updates to your apps. This optimizes Turbopack for handling updates in development, meaning your dev server will always respond snappily to changes. + +In the future, a persistent cache will open the door to much faster production builds. By remembering work done _across runs_, new production builds could only rebuild changed files - potentially leading to enormous time savings. diff --git a/docs/package.json b/docs/package.json index 528a98a10e3bb..8b137891791fe 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,27 +1 @@ -{ - "private": true, - "type": "module", - "exports": "./dist/index.js", - "files": [ - "src" - ], - "scripts": { - "check-links": "tsx src/validate-docs-links.ts" - }, - "devDependencies": { - "@types/node": "22.7.8", - "tsx": "4.19.1", - "typescript": "5.5.4" - }, - "dependencies": { - "github-slugger": "2.0.0", - "gray-matter": "4.0.3", - "hast-util-select": "^6.0.3", - "rehype-parse": "^9.0.1", - "rehype-raw": "7.0.0", - "remark-parse": "11.0.0", - "remark-rehype": "11.1.1", - "unified": "11.0.5", - "unist-util-visit": "5.0.0" - } -} + diff --git a/docs/repo-docs/crafting-your-repository/structuring-a-repository.mdx b/docs/repo-docs/crafting-your-repository/structuring-a-repository.mdx index 3c0b49084f901..6e80fcb9c7f44 100644 --- a/docs/repo-docs/crafting-your-repository/structuring-a-repository.mdx +++ b/docs/repo-docs/crafting-your-repository/structuring-a-repository.mdx @@ -227,7 +227,7 @@ The root `package.json` is the base for your workspace. Below is a common exampl "devDependencies": { "turbo": "latest" }, - "packageManager": "pnpm@9.0.0" + "packageManager": "pnpm@10.2.1" } ``` diff --git a/docs/repo-docs/crafting-your-repository/upgrading.mdx b/docs/repo-docs/crafting-your-repository/upgrading.mdx index a4c43f9fc280f..2c851ddc1efdd 100644 --- a/docs/repo-docs/crafting-your-repository/upgrading.mdx +++ b/docs/repo-docs/crafting-your-repository/upgrading.mdx @@ -88,7 +88,7 @@ Turborepo 2.0 requires that your Workspace define this field as a way to improve ```diff title="./package.json" { -+ "packageManager": "pnpm@9.2.0" ++ "packageManager": "pnpm@10.2.1" } ``` diff --git a/docs/repo-docs/guides/migrating-from-nx.mdx b/docs/repo-docs/guides/migrating-from-nx.mdx index 777e0fb78df9a..2a27074eb3c2c 100644 --- a/docs/repo-docs/guides/migrating-from-nx.mdx +++ b/docs/repo-docs/guides/migrating-from-nx.mdx @@ -253,7 +253,7 @@ The root package.json needs to have the `packageManager` field. This ensures dev ```json title="./package.json" { - "packageManager": "pnpm@9.0.0" + "packageManager": "pnpm@10.2.1" } ``` diff --git a/examples/basic/README.md b/examples/basic/README.md deleted file mode 100644 index 4b760734cdec1..0000000000000 --- a/examples/basic/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Turborepo starter - -This Turborepo starter is maintained by the Turborepo core team. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [Next.js](https://nextjs.org/) app -- `web`: another [Next.js](https://nextjs.org/) app -- `@repo/ui`: a stub React component library shared by both `web` and `docs` applications -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Build - -To build all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm build -``` - -### Develop - -To develop all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm dev -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -``` -cd my-turborepo -npx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: - -``` -npx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/basic/apps/docs/README.md b/examples/basic/apps/docs/README.md deleted file mode 100644 index a98bfa8140e14..0000000000000 --- a/examples/basic/apps/docs/README.md +++ /dev/null @@ -1,36 +0,0 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/examples/basic/apps/docs/eslint.config.js b/examples/basic/apps/docs/eslint.config.js deleted file mode 100644 index e8759ff50fbca..0000000000000 --- a/examples/basic/apps/docs/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { nextJsConfig } from "@repo/eslint-config/next-js"; - -/** @type {import("eslint").Linter.Config} */ -export default nextJsConfig; diff --git a/examples/basic/apps/docs/next.config.mjs b/examples/basic/apps/docs/next.config.mjs new file mode 100644 index 0000000000000..4678774e6d606 --- /dev/null +++ b/examples/basic/apps/docs/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/examples/basic/apps/docs/package.json b/examples/basic/apps/docs/package.json index a5ea7f4c0acfa..7cd052b5af4d3 100644 --- a/examples/basic/apps/docs/package.json +++ b/examples/basic/apps/docs/package.json @@ -1,27 +1,18 @@ { - "name": "docs", - "version": "0.1.0", - "type": "module", - "private": true, - "scripts": { - "dev": "next dev --turbopack --port 3001", - "build": "next build", - "start": "next start", - "lint": "next lint --max-warnings 0", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@repo/ui": "workspace:*", - "next": "^15.1.6", - "react": "^19.0.0", - "react-dom": "^19.0.0" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/node": "^22", - "@types/react": "19.0.8", - "@types/react-dom": "19.0.3", - "typescript": "5.7.3" - } + "name": "docs", + "scripts": { + "build": "next build", + "check-types": "tsc --noEmit", + "dev": "next dev --turbopack --port 3001", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "workspace:*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22" + } } diff --git a/examples/basic/apps/web/README.md b/examples/basic/apps/web/README.md deleted file mode 100644 index a98bfa8140e14..0000000000000 --- a/examples/basic/apps/web/README.md +++ /dev/null @@ -1,36 +0,0 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/examples/basic/apps/web/eslint.config.js b/examples/basic/apps/web/eslint.config.js deleted file mode 100644 index e8759ff50fbca..0000000000000 --- a/examples/basic/apps/web/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { nextJsConfig } from "@repo/eslint-config/next-js"; - -/** @type {import("eslint").Linter.Config} */ -export default nextJsConfig; diff --git a/examples/basic/apps/web/next.config.mjs b/examples/basic/apps/web/next.config.mjs new file mode 100644 index 0000000000000..4678774e6d606 --- /dev/null +++ b/examples/basic/apps/web/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/examples/basic/apps/web/package.json b/examples/basic/apps/web/package.json index 9ddf17af5a852..7d09933957823 100644 --- a/examples/basic/apps/web/package.json +++ b/examples/basic/apps/web/package.json @@ -1,27 +1,18 @@ { - "name": "web", - "version": "0.1.0", - "type": "module", - "private": true, - "scripts": { - "dev": "next dev --turbopack --port 3000", - "build": "next build", - "start": "next start", - "lint": "next lint --max-warnings 0", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@repo/ui": "workspace:*", - "next": "^15.1.6", - "react": "^19.0.0", - "react-dom": "^19.0.0" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/node": "^22", - "@types/react": "19.0.8", - "@types/react-dom": "19.0.3", - "typescript": "5.7.3" - } + "name": "web", + "scripts": { + "build": "next build", + "check-types": "tsc --noEmit", + "dev": "next dev --turbopack --port 3000", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "workspace:*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22" + } } diff --git a/examples/basic/package.json b/examples/basic/package.json index 0adaea9f1af7f..8647edc8eecda 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -1,19 +1,11 @@ { - "name": "my-turborepo", - "private": true, - "scripts": { - "build": "turbo build", - "dev": "turbo dev", - "lint": "turbo lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "prettier": "^3.4.2", - "turbo": "^2.3.4", - "typescript": "5.7.3" - }, - "packageManager": "pnpm@9.0.0", - "engines": { - "node": ">=18" - } + "name": "my-turborepo", + "scripts": { + "build": "turbo build", + "dev": "turbo dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/basic/packages/eslint-config/README.md b/examples/basic/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/basic/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/basic/packages/eslint-config/library.js b/examples/basic/packages/eslint-config/library.js new file mode 100644 index 0000000000000..9b59cc0fcb2fc --- /dev/null +++ b/examples/basic/packages/eslint-config/library.js @@ -0,0 +1,34 @@ +const { resolve } = require("node:path"); + +const project = resolve(process.cwd(), "tsconfig.json"); + +/** @type {import("eslint").Linter.Config} */ +module.exports = { + extends: ["eslint:recommended", "prettier", "turbo"], + plugins: ["only-warn"], + globals: { + React: true, + JSX: true, + }, + env: { + node: true, + }, + settings: { + "import/resolver": { + typescript: { + project, + }, + }, + }, + ignorePatterns: [ + // Ignore dotfiles + ".*.js", + "node_modules/", + "dist/", + ], + overrides: [ + { + files: ["*.js?(x)", "*.ts?(x)"], + }, + ], +}; diff --git a/examples/basic/packages/eslint-config/package.json b/examples/basic/packages/eslint-config/package.json index 5edd31533287d..eb1ec636f5505 100644 --- a/examples/basic/packages/eslint-config/package.json +++ b/examples/basic/packages/eslint-config/package.json @@ -1,24 +1,13 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "type": "module", - "private": true, - "exports": { - "./base": "./base.js", - "./next-js": "./next.js", - "./react-internal": "./react-internal.js" - }, - "devDependencies": { - "@eslint/js": "^9.19.0", - "@next/eslint-plugin-next": "^15.1.6", - "eslint": "^9.19.0", - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-only-warn": "^1.1.0", - "eslint-plugin-react": "^7.37.4", - "eslint-plugin-react-hooks": "^5.1.0", - "eslint-plugin-turbo": "^2.3.4", - "globals": "^15.14.0", - "typescript": "^5.7.3", - "typescript-eslint": "^8.22.0" - } + "name": "@repo/eslint-config", + "exports": { + "./base": "./base.js", + "./next-js": "./next.js", + "./react-internal": "./react-internal.js" + }, + "devDependencies": { + "eslint-plugin-only-warn": "1.1.0", + "eslint-plugin-turbo": "2.4.2", + "globals": "15.15.0" + } } diff --git a/examples/basic/packages/typescript-config/package.json b/examples/basic/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/basic/packages/typescript-config/package.json +++ b/examples/basic/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/basic/packages/ui/src/button.tsx b/examples/basic/packages/ui/Source/button.tsx similarity index 100% rename from examples/basic/packages/ui/src/button.tsx rename to examples/basic/packages/ui/Source/button.tsx diff --git a/examples/basic/packages/ui/src/card.tsx b/examples/basic/packages/ui/Source/card.tsx similarity index 100% rename from examples/basic/packages/ui/src/card.tsx rename to examples/basic/packages/ui/Source/card.tsx diff --git a/examples/basic/packages/ui/src/code.tsx b/examples/basic/packages/ui/Source/code.tsx similarity index 100% rename from examples/basic/packages/ui/src/code.tsx rename to examples/basic/packages/ui/Source/code.tsx diff --git a/examples/basic/packages/ui/package.json b/examples/basic/packages/ui/package.json index dd9fa91128ecc..4f0d6b394bd38 100644 --- a/examples/basic/packages/ui/package.json +++ b/examples/basic/packages/ui/package.json @@ -15,14 +15,14 @@ "devDependencies": { "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@turbo/gen": "^2.3.4", - "@types/node": "^22.12.0", + "@turbo/gen": "2.4.2", + "@types/node": "22.13.1", "@types/react": "19.0.8", "@types/react-dom": "19.0.3", "typescript": "5.7.3" }, "dependencies": { - "react": "^19.0.0", - "react-dom": "^19.0.0" + "react": "19.0.0", + "react-dom": "19.0.0" } } diff --git a/examples/basic/packages/ui/tsconfig.lint.json b/examples/basic/packages/ui/tsconfig.lint.json new file mode 100644 index 0000000000000..df2762ee5f6a6 --- /dev/null +++ b/examples/basic/packages/ui/tsconfig.lint.json @@ -0,0 +1,8 @@ +{ + "extends": "@repo/typescript-config/react-library.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": ["src", "turbo"], + "exclude": ["node_modules", "dist"] +} diff --git a/examples/basic/pnpm-lock.yaml b/examples/basic/pnpm-lock.yaml deleted file mode 100644 index e9b2aab6ee8c2..0000000000000 --- a/examples/basic/pnpm-lock.yaml +++ /dev/null @@ -1,4364 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - prettier: - specifier: ^3.4.2 - version: 3.4.2 - turbo: - specifier: ^2.3.4 - version: 2.3.4 - typescript: - specifier: 5.7.3 - version: 5.7.3 - - apps/docs: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^15.1.6 - version: 15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/node': - specifier: ^22 - version: 22.12.0 - '@types/react': - specifier: 19.0.8 - version: 19.0.8 - '@types/react-dom': - specifier: 19.0.3 - version: 19.0.3(@types/react@19.0.8) - typescript: - specifier: 5.7.3 - version: 5.7.3 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^15.1.6 - version: 15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/node': - specifier: ^22 - version: 22.12.0 - '@types/react': - specifier: 19.0.8 - version: 19.0.8 - '@types/react-dom': - specifier: 19.0.3 - version: 19.0.3(@types/react@19.0.8) - typescript: - specifier: 5.7.3 - version: 5.7.3 - - packages/eslint-config: - devDependencies: - '@eslint/js': - specifier: ^9.19.0 - version: 9.19.0 - '@next/eslint-plugin-next': - specifier: ^15.1.6 - version: 15.1.6 - eslint: - specifier: ^9.19.0 - version: 9.19.0 - eslint-config-prettier: - specifier: ^10.0.1 - version: 10.0.1(eslint@9.19.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - eslint-plugin-react: - specifier: ^7.37.4 - version: 7.37.4(eslint@9.19.0) - eslint-plugin-react-hooks: - specifier: ^5.1.0 - version: 5.1.0(eslint@9.19.0) - eslint-plugin-turbo: - specifier: ^2.3.4 - version: 2.3.4(eslint@9.19.0)(turbo@2.3.4) - globals: - specifier: ^15.14.0 - version: 15.14.0 - typescript: - specifier: ^5.7.3 - version: 5.7.3 - typescript-eslint: - specifier: ^8.22.0 - version: 8.22.0(eslint@9.19.0)(typescript@5.7.3) - - packages/typescript-config: {} - - packages/ui: - dependencies: - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@turbo/gen': - specifier: ^2.3.4 - version: 2.3.4(@types/node@22.12.0)(typescript@5.7.3) - '@types/node': - specifier: ^22.12.0 - version: 22.12.0 - '@types/react': - specifier: 19.0.8 - version: 19.0.8 - '@types/react-dom': - specifier: 19.0.3 - version: 19.0.3(@types/react@19.0.8) - typescript: - specifier: 5.7.3 - version: 5.7.3 - -packages: - - '@babel/runtime-corejs3@7.26.7': - resolution: {integrity: sha512-55gRV8vGrCIYZnaQHQrD92Lo/hYE3Sj5tmbuf0hhHR7sj2CWhEhHU89hbq+UVDXvFG1zUVXJhUkEq1eAfqXtFw==} - engines: {node: '>=6.9.0'} - - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - - '@emnapi/runtime@1.3.1': - resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} - - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.19.1': - resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.10.0': - resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.2.0': - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.19.0': - resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.5': - resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.2.5': - resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - - '@humanwhocodes/retry@0.4.1': - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} - engines: {node: '>=18.18'} - - '@img/sharp-darwin-arm64@0.33.5': - resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - - '@img/sharp-darwin-x64@0.33.5': - resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-darwin-arm64@1.0.4': - resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} - cpu: [arm64] - os: [darwin] - - '@img/sharp-libvips-darwin-x64@1.0.4': - resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-linux-arm64@1.0.4': - resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linux-arm@1.0.5': - resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} - cpu: [arm] - os: [linux] - - '@img/sharp-libvips-linux-s390x@1.0.4': - resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} - cpu: [s390x] - os: [linux] - - '@img/sharp-libvips-linux-x64@1.0.4': - resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} - cpu: [x64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-x64@1.0.4': - resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} - cpu: [x64] - os: [linux] - - '@img/sharp-linux-arm64@0.33.5': - resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linux-arm@0.33.5': - resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm] - os: [linux] - - '@img/sharp-linux-s390x@0.33.5': - resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [s390x] - os: [linux] - - '@img/sharp-linux-x64@0.33.5': - resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-linuxmusl-arm64@0.33.5': - resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linuxmusl-x64@0.33.5': - resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-wasm32@0.33.5': - resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [wasm32] - - '@img/sharp-win32-ia32@0.33.5': - resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ia32] - os: [win32] - - '@img/sharp-win32-x64@0.33.5': - resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [win32] - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - - '@next/env@15.1.6': - resolution: {integrity: sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==} - - '@next/eslint-plugin-next@15.1.6': - resolution: {integrity: sha512-+slMxhTgILUntZDGNgsKEYHUvpn72WP1YTlkmEhS51vnVd7S9jEEy0n9YAMcI21vUG4akTw9voWH02lrClt/yw==} - - '@next/swc-darwin-arm64@15.1.6': - resolution: {integrity: sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@15.1.6': - resolution: {integrity: sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@15.1.6': - resolution: {integrity: sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-arm64-musl@15.1.6': - resolution: {integrity: sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-x64-gnu@15.1.6': - resolution: {integrity: sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-linux-x64-musl@15.1.6': - resolution: {integrity: sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-win32-arm64-msvc@15.1.6': - resolution: {integrity: sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-x64-msvc@15.1.6': - resolution: {integrity: sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - - '@tootallnate/quickjs-emscripten@0.23.0': - resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - - '@turbo/gen@2.3.4': - resolution: {integrity: sha512-HXBa2SW8LFFduVIFgHpz/M7U1670AJncQD3TC+Bt/xS3pyzp2KLebxq8EKNjbNZ8J86vhdqIg+AhXg5MfeMFZQ==} - hasBin: true - - '@turbo/workspaces@2.3.4': - resolution: {integrity: sha512-ffoap9R2AT29ZT9jFwBiOWHcd65Aio2L42P9DseESDOdC6Eke9nxUYrvSe+4AVjMqO3OXYyftIo5dX8F3jDRuw==} - hasBin: true - - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - '@types/glob@7.2.0': - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - - '@types/inquirer@6.5.0': - resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/minimatch@5.1.2': - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - - '@types/node@22.12.0': - resolution: {integrity: sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==} - - '@types/react-dom@19.0.3': - resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} - peerDependencies: - '@types/react': ^19.0.0 - - '@types/react@19.0.8': - resolution: {integrity: sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==} - - '@types/through@0.0.33': - resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} - - '@types/tinycolor2@1.4.6': - resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} - - '@typescript-eslint/eslint-plugin@8.22.0': - resolution: {integrity: sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/parser@8.22.0': - resolution: {integrity: sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/scope-manager@8.22.0': - resolution: {integrity: sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/type-utils@8.22.0': - resolution: {integrity: sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/types@8.22.0': - resolution: {integrity: sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.22.0': - resolution: {integrity: sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/utils@8.22.0': - resolution: {integrity: sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/visitor-keys@8.22.0': - resolution: {integrity: sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - - agent-base@7.1.3: - resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} - engines: {node: '>= 14'} - - aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - - array.prototype.flat@1.3.3: - resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} - engines: {node: '>= 0.4'} - - array.prototype.flatmap@1.3.3: - resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} - engines: {node: '>= 0.4'} - - array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - - arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} - - ast-types@0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - - async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - basic-ftp@5.0.5: - resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} - engines: {node: '>=10.0.0'} - - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - - busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - - call-bind-apply-helpers@1.0.1: - resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} - engines: {node: '>= 0.4'} - - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - - call-bound@1.0.3: - resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camel-case@3.0.0: - resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} - - caniuse-lite@1.0.30001695: - resolution: {integrity: sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==} - - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - - chalk@3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - change-case@3.1.0: - resolution: {integrity: sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==} - - chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - - clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - - cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - - cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - - cli-width@3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} - - client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - - clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - - commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - constant-case@2.0.0: - resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} - - core-js-pure@3.40.0: - resolution: {integrity: sha512-AtDzVIgRrmRKQai62yuSIN5vNiQjcJakJb4fbhVw3ehxx7Lohphvw9SGNWKhLFqSxC4ilD0g/L1huAYFQU3Q6A==} - - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - data-uri-to-buffer@6.0.2: - resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} - engines: {node: '>= 14'} - - data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} - - data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} - - data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} - - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - degenerator@5.0.1: - resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} - engines: {node: '>= 14'} - - del@5.1.0: - resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} - engines: {node: '>=8'} - - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - dot-case@2.1.1: - resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} - - dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - es-abstract@1.23.9: - resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} - engines: {node: '>= 0.4'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-iterator-helpers@1.2.1: - resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} - engines: {node: '>= 0.4'} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - - es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} - engines: {node: '>= 0.4'} - - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - - eslint-config-prettier@10.0.1: - resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - - eslint-plugin-react-hooks@5.1.0: - resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - - eslint-plugin-react@7.37.4: - resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - - eslint-plugin-turbo@2.3.4: - resolution: {integrity: sha512-9ncoUJkQGkC28NmlQiS17oB9mrE8XaSulRZiB5pv9vmRbYjOfUwyGhY3EIcoBRdww81igxOzXmAmvNNd6GFBPg==} - peerDependencies: - eslint: '>6.6.0' - turbo: '>2.0.0' - - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.19.0: - resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.18.0: - resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} - - figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - - get-intrinsic@1.2.7: - resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} - - get-uri@6.0.4: - resolution: {integrity: sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==} - engines: {node: '>= 14'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globals@15.14.0: - resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} - engines: {node: '>=18'} - - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - - globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - gradient-string@2.0.2: - resolution: {integrity: sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw==} - engines: {node: '>=10'} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - - has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} - - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - header-case@1.0.1: - resolution: {integrity: sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==} - - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} - - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - inquirer@7.3.3: - resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} - engines: {node: '>=8.0.0'} - - inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} - engines: {node: '>=12.0.0'} - - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - - ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - - is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - - is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} - - is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - - is-boolean-object@1.2.1: - resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} - engines: {node: '>= 0.4'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} - - is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} - engines: {node: '>= 0.4'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - - is-lower-case@1.1.3: - resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} - - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - - is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-path-cwd@2.2.0: - resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} - engines: {node: '>=6'} - - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - - is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - is-upper-case@1.1.2: - resolution: {integrity: sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==} - - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakref@1.1.0: - resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isbinaryfile@4.0.10: - resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} - engines: {node: '>= 8.0.0'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - iterator.prototype@1.1.5: - resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} - engines: {node: '>= 0.4'} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - - jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.get@4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - log-symbols@3.0.0: - resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==} - engines: {node: '>=8'} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - - lower-case-first@1.0.2: - resolution: {integrity: sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==} - - lower-case@1.1.4: - resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} - - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - - netmask@2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} - - next@15.1.6: - resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - - no-case@2.3.2: - resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} - - node-plop@0.26.3: - resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==} - engines: {node: '>=8.9.4'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} - engines: {node: '>= 0.4'} - - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - - object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - - object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.1: - resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} - engines: {node: '>= 0.4'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - ora@4.1.1: - resolution: {integrity: sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==} - engines: {node: '>=8'} - - ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - - os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - - own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-map@3.0.0: - resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} - engines: {node: '>=8'} - - pac-proxy-agent@7.1.0: - resolution: {integrity: sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==} - engines: {node: '>= 14'} - - pac-resolver@7.0.1: - resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} - engines: {node: '>= 14'} - - param-case@2.1.1: - resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - pascal-case@2.0.1: - resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} - - path-case@2.1.1: - resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - - postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} - engines: {node: '>=14'} - hasBin: true - - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - - proxy-agent@6.5.0: - resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} - engines: {node: '>= 14'} - - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - - react-dom@19.0.0: - resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} - peerDependencies: - react: ^19.0.0 - - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - react@19.0.0: - resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} - engines: {node: '>=0.10.0'} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - - registry-auth-token@3.3.2: - resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} - - registry-url@3.1.0: - resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} - engines: {node: '>=0.10.0'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - - resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - - restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - - run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - rxjs@6.6.7: - resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} - engines: {npm: '>=2.0.0'} - - rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - scheduler@0.25.0: - resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - semver@7.7.0: - resolution: {integrity: sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==} - engines: {node: '>=10'} - hasBin: true - - sentence-case@2.1.1: - resolution: {integrity: sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==} - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - - set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} - - sharp@0.33.5: - resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - snake-case@2.1.0: - resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} - - socks-proxy-agent@8.0.5: - resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} - engines: {node: '>= 14'} - - socks@2.8.3: - resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - - streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} - engines: {node: '>= 0.4'} - - string.prototype.repeat@1.0.0: - resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} - engines: {node: '>= 0.4'} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - styled-jsx@5.1.6: - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - swap-case@1.1.2: - resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - tinycolor2@1.6.0: - resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} - - tinygradient@1.1.5: - resolution: {integrity: sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==} - - title-case@2.1.1: - resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} - - tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - ts-api-utils@2.0.0: - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - - tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - turbo-darwin-64@2.3.4: - resolution: {integrity: sha512-uOi/cUIGQI7uakZygH+cZQ5D4w+aMLlVCN2KTGot+cmefatps2ZmRRufuHrEM0Rl63opdKD8/JIu+54s25qkfg==} - cpu: [x64] - os: [darwin] - - turbo-darwin-arm64@2.3.4: - resolution: {integrity: sha512-IIM1Lq5R+EGMtM1YFGl4x8Xkr0MWb4HvyU8N4LNoQ1Be5aycrOE+VVfH+cDg/Q4csn+8bxCOxhRp5KmUflrVTQ==} - cpu: [arm64] - os: [darwin] - - turbo-linux-64@2.3.4: - resolution: {integrity: sha512-1aD2EfR7NfjFXNH3mYU5gybLJEFi2IGOoKwoPLchAFRQ6OEJQj201/oNo9CDL75IIrQo64/NpEgVyZtoPlfhfA==} - cpu: [x64] - os: [linux] - - turbo-linux-arm64@2.3.4: - resolution: {integrity: sha512-MxTpdKwxCaA5IlybPxgGLu54fT2svdqTIxRd0TQmpRJIjM0s4kbM+7YiLk0mOh6dGqlWPUsxz/A0Mkn8Xr5o7Q==} - cpu: [arm64] - os: [linux] - - turbo-windows-64@2.3.4: - resolution: {integrity: sha512-yyCrWqcRGu1AOOlrYzRnizEtdkqi+qKP0MW9dbk9OsMDXaOI5jlWtTY/AtWMkLw/czVJ7yS9Ex1vi9DB6YsFvw==} - cpu: [x64] - os: [win32] - - turbo-windows-arm64@2.3.4: - resolution: {integrity: sha512-PggC3qH+njPfn1PDVwKrQvvQby8X09ufbqZ2Ha4uSu+5TvPorHHkAbZVHKYj2Y+tvVzxRzi4Sv6NdHXBS9Be5w==} - cpu: [arm64] - os: [win32] - - turbo@2.3.4: - resolution: {integrity: sha512-1kiLO5C0Okh5ay1DbHsxkPsw9Sjsbjzm6cF85CpWjR0BIyBFNDbKqtUyqGADRS1dbbZoQanJZVj4MS5kk8J42Q==} - hasBin: true - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} - - typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} - - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} - engines: {node: '>= 0.4'} - - typescript-eslint@8.22.0: - resolution: {integrity: sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} - engines: {node: '>=14.17'} - hasBin: true - - uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} - engines: {node: '>=0.8.0'} - hasBin: true - - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - update-check@1.5.4: - resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} - - upper-case-first@1.1.2: - resolution: {integrity: sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==} - - upper-case@1.1.3: - resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - - validate-npm-package-name@5.0.1: - resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - - which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - - which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - - which-typed-array@1.1.18: - resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} - engines: {node: '>= 0.4'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@babel/runtime-corejs3@7.26.7': - dependencies: - core-js-pure: 3.40.0 - regenerator-runtime: 0.14.1 - - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - - '@emnapi/runtime@1.3.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@eslint-community/eslint-utils@4.4.1(eslint@9.19.0)': - dependencies: - eslint: 9.19.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/config-array@0.19.1': - dependencies: - '@eslint/object-schema': 2.1.5 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/core@0.10.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.2.0': - dependencies: - ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.19.0': {} - - '@eslint/object-schema@2.1.5': {} - - '@eslint/plugin-kit@0.2.5': - dependencies: - '@eslint/core': 0.10.0 - levn: 0.4.1 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.6': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.3.1': {} - - '@humanwhocodes/retry@0.4.1': {} - - '@img/sharp-darwin-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.4 - optional: true - - '@img/sharp-darwin-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.0.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-darwin-x64@1.0.4': - optional: true - - '@img/sharp-libvips-linux-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-linux-arm@1.0.5': - optional: true - - '@img/sharp-libvips-linux-s390x@1.0.4': - optional: true - - '@img/sharp-libvips-linux-x64@1.0.4': - optional: true - - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-linuxmusl-x64@1.0.4': - optional: true - - '@img/sharp-linux-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.0.4 - optional: true - - '@img/sharp-linux-arm@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.0.5 - optional: true - - '@img/sharp-linux-s390x@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.0.4 - optional: true - - '@img/sharp-linux-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.0.4 - optional: true - - '@img/sharp-linuxmusl-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - optional: true - - '@img/sharp-linuxmusl-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - optional: true - - '@img/sharp-wasm32@0.33.5': - dependencies: - '@emnapi/runtime': 1.3.1 - optional: true - - '@img/sharp-win32-ia32@0.33.5': - optional: true - - '@img/sharp-win32-x64@0.33.5': - optional: true - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@next/env@15.1.6': {} - - '@next/eslint-plugin-next@15.1.6': - dependencies: - fast-glob: 3.3.1 - - '@next/swc-darwin-arm64@15.1.6': - optional: true - - '@next/swc-darwin-x64@15.1.6': - optional: true - - '@next/swc-linux-arm64-gnu@15.1.6': - optional: true - - '@next/swc-linux-arm64-musl@15.1.6': - optional: true - - '@next/swc-linux-x64-gnu@15.1.6': - optional: true - - '@next/swc-linux-x64-musl@15.1.6': - optional: true - - '@next/swc-win32-arm64-msvc@15.1.6': - optional: true - - '@next/swc-win32-x64-msvc@15.1.6': - optional: true - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.18.0 - - '@swc/counter@0.1.3': {} - - '@swc/helpers@0.5.15': - dependencies: - tslib: 2.8.1 - - '@tootallnate/quickjs-emscripten@0.23.0': {} - - '@tsconfig/node10@1.0.11': {} - - '@tsconfig/node12@1.0.11': {} - - '@tsconfig/node14@1.0.3': {} - - '@tsconfig/node16@1.0.4': {} - - '@turbo/gen@2.3.4(@types/node@22.12.0)(typescript@5.7.3)': - dependencies: - '@turbo/workspaces': 2.3.4 - commander: 10.0.1 - fs-extra: 10.1.0 - inquirer: 8.2.6 - minimatch: 9.0.5 - node-plop: 0.26.3 - picocolors: 1.0.1 - proxy-agent: 6.5.0 - ts-node: 10.9.2(@types/node@22.12.0)(typescript@5.7.3) - update-check: 1.5.4 - validate-npm-package-name: 5.0.1 - transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' - - '@types/node' - - supports-color - - typescript - - '@turbo/workspaces@2.3.4': - dependencies: - commander: 10.0.1 - execa: 5.1.1 - fast-glob: 3.3.3 - fs-extra: 10.1.0 - gradient-string: 2.0.2 - inquirer: 8.2.6 - js-yaml: 4.1.0 - ora: 4.1.1 - picocolors: 1.0.1 - semver: 7.6.2 - update-check: 1.5.4 - - '@types/estree@1.0.6': {} - - '@types/glob@7.2.0': - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 22.12.0 - - '@types/inquirer@6.5.0': - dependencies: - '@types/through': 0.0.33 - rxjs: 6.6.7 - - '@types/json-schema@7.0.15': {} - - '@types/minimatch@5.1.2': {} - - '@types/node@22.12.0': - dependencies: - undici-types: 6.20.0 - - '@types/react-dom@19.0.3(@types/react@19.0.8)': - dependencies: - '@types/react': 19.0.8 - - '@types/react@19.0.8': - dependencies: - csstype: 3.1.3 - - '@types/through@0.0.33': - dependencies: - '@types/node': 22.12.0 - - '@types/tinycolor2@1.4.6': {} - - '@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/type-utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - eslint: 9.19.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - - '@typescript-eslint/type-utils@8.22.0(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - debug: 4.4.0 - eslint: 9.19.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.22.0': {} - - '@typescript-eslint/typescript-estree@8.22.0(typescript@5.7.3)': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.22.0(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 - eslint-visitor-keys: 4.2.0 - - acorn-jsx@5.3.2(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn-walk@8.3.4: - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - - agent-base@7.1.3: {} - - aggregate-error@3.1.0: - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - - ansi-regex@5.0.1: {} - - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - arg@4.1.3: {} - - argparse@2.0.1: {} - - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.3 - is-array-buffer: 3.0.5 - - array-includes@3.1.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - is-string: 1.1.1 - - array-union@2.1.0: {} - - array.prototype.findlast@1.2.5: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-shim-unscopables: 1.0.2 - - array.prototype.flat@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - - array.prototype.flatmap@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - - array.prototype.tosorted@1.1.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - is-array-buffer: 3.0.5 - - ast-types@0.13.4: - dependencies: - tslib: 2.8.1 - - async-function@1.0.0: {} - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.0.0 - - balanced-match@1.0.2: {} - - base64-js@1.5.1: {} - - basic-ftp@5.0.5: {} - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - busboy@1.6.0: - dependencies: - streamsearch: 1.1.0 - - call-bind-apply-helpers@1.0.1: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - get-intrinsic: 1.2.7 - set-function-length: 1.2.2 - - call-bound@1.0.3: - dependencies: - call-bind-apply-helpers: 1.0.1 - get-intrinsic: 1.2.7 - - callsites@3.1.0: {} - - camel-case@3.0.0: - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - - caniuse-lite@1.0.30001695: {} - - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - chalk@3.0.0: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - change-case@3.1.0: - dependencies: - camel-case: 3.0.0 - constant-case: 2.0.0 - dot-case: 2.1.1 - header-case: 1.0.1 - is-lower-case: 1.1.3 - is-upper-case: 1.1.2 - lower-case: 1.1.4 - lower-case-first: 1.0.2 - no-case: 2.3.2 - param-case: 2.1.1 - pascal-case: 2.0.1 - path-case: 2.1.1 - sentence-case: 2.1.1 - snake-case: 2.1.0 - swap-case: 1.1.2 - title-case: 2.1.1 - upper-case: 1.1.3 - upper-case-first: 1.1.2 - - chardet@0.7.0: {} - - clean-stack@2.2.0: {} - - cli-cursor@3.1.0: - dependencies: - restore-cursor: 3.1.0 - - cli-spinners@2.9.2: {} - - cli-width@3.0.0: {} - - client-only@0.0.1: {} - - clone@1.0.4: {} - - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.3: {} - - color-name@1.1.4: {} - - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - optional: true - - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - optional: true - - commander@10.0.1: {} - - concat-map@0.0.1: {} - - constant-case@2.0.0: - dependencies: - snake-case: 2.1.0 - upper-case: 1.1.3 - - core-js-pure@3.40.0: {} - - create-require@1.1.1: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - csstype@3.1.3: {} - - data-uri-to-buffer@6.0.2: {} - - data-view-buffer@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-length@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-offset@1.0.1: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - debug@4.4.0: - dependencies: - ms: 2.1.3 - - deep-extend@0.6.0: {} - - deep-is@0.1.4: {} - - defaults@1.0.4: - dependencies: - clone: 1.0.4 - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - degenerator@5.0.1: - dependencies: - ast-types: 0.13.4 - escodegen: 2.1.0 - esprima: 4.0.1 - - del@5.1.0: - dependencies: - globby: 10.0.2 - graceful-fs: 4.2.11 - is-glob: 4.0.3 - is-path-cwd: 2.2.0 - is-path-inside: 3.0.3 - p-map: 3.0.0 - rimraf: 3.0.2 - slash: 3.0.0 - - detect-libc@2.0.3: - optional: true - - diff@4.0.2: {} - - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - dot-case@2.1.1: - dependencies: - no-case: 2.3.2 - - dotenv@16.0.3: {} - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - emoji-regex@8.0.0: {} - - es-abstract@1.23.9: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-regex: 1.2.1 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.0 - math-intrinsics: 1.1.0 - object-inspect: 1.13.3 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.1 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.18 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-iterator-helpers@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-set-tostringtag: 2.1.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - iterator.prototype: 1.1.5 - safe-array-concat: 1.1.3 - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - es-shim-unscopables@1.0.2: - dependencies: - hasown: 2.0.2 - - es-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - - escape-string-regexp@1.0.5: {} - - escape-string-regexp@4.0.0: {} - - escodegen@2.1.0: - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - - eslint-config-prettier@10.0.1(eslint@9.19.0): - dependencies: - eslint: 9.19.0 - - eslint-plugin-only-warn@1.1.0: {} - - eslint-plugin-react-hooks@5.1.0(eslint@9.19.0): - dependencies: - eslint: 9.19.0 - - eslint-plugin-react@7.37.4(eslint@9.19.0): - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.3 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.2.1 - eslint: 9.19.0 - estraverse: 5.3.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.values: 1.2.1 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.12 - string.prototype.repeat: 1.0.0 - - eslint-plugin-turbo@2.3.4(eslint@9.19.0)(turbo@2.3.4): - dependencies: - dotenv: 16.0.3 - eslint: 9.19.0 - turbo: 2.3.4 - - eslint-scope@8.2.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.0: {} - - eslint@9.19.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.1 - '@eslint/core': 0.10.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.19.0 - '@eslint/plugin-kit': 0.2.5 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - - espree@10.3.0: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - - esprima@4.0.1: {} - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - external-editor@3.1.0: - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.1: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.18.0: - dependencies: - reusify: 1.0.4 - - figures@3.2.0: - dependencies: - escape-string-regexp: 1.0.5 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - - flatted@3.3.2: {} - - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - - fs.realpath@1.0.0: {} - - function-bind@1.1.2: {} - - function.prototype.name@1.1.8: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - - functions-have-names@1.2.3: {} - - get-intrinsic@1.2.7: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-stream@6.0.1: {} - - get-symbol-description@1.1.0: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - - get-uri@6.0.4: - dependencies: - basic-ftp: 5.0.5 - data-uri-to-buffer: 6.0.2 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - globals@14.0.0: {} - - globals@15.14.0: {} - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - - globby@10.0.2: - dependencies: - '@types/glob': 7.2.0 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.3 - glob: 7.2.3 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - gradient-string@2.0.2: - dependencies: - chalk: 4.1.2 - tinygradient: 1.1.5 - - graphemer@1.4.0: {} - - handlebars@4.7.8: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - - has-bigints@1.1.0: {} - - has-flag@3.0.0: {} - - has-flag@4.0.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-proto@1.2.0: - dependencies: - dunder-proto: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - header-case@1.0.1: - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - - human-signals@2.1.0: {} - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - - ieee754@1.2.1: {} - - ignore@5.3.2: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - indent-string@4.0.0: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - ini@1.3.8: {} - - inquirer@7.3.3: - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - run-async: 2.4.1 - rxjs: 6.6.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - - inquirer@8.2.6: - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - ip-address@9.0.5: - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - - is-arrayish@0.3.2: - optional: true - - is-async-function@2.1.1: - dependencies: - async-function: 1.0.0 - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - - is-boolean-object@1.2.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-callable@1.2.7: {} - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-data-view@1.0.2: - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - is-typed-array: 1.1.15 - - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-extglob@2.1.1: {} - - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.3 - - is-fullwidth-code-point@3.0.0: {} - - is-generator-function@1.1.0: - dependencies: - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-interactive@1.0.0: {} - - is-lower-case@1.1.3: - dependencies: - lower-case: 1.1.4 - - is-map@2.0.3: {} - - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-number@7.0.0: {} - - is-path-cwd@2.2.0: {} - - is-path-inside@3.0.3: {} - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.3 - - is-stream@2.0.1: {} - - is-string@1.1.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.3 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.18 - - is-unicode-supported@0.1.0: {} - - is-upper-case@1.1.2: - dependencies: - upper-case: 1.1.3 - - is-weakmap@2.0.2: {} - - is-weakref@1.1.0: - dependencies: - call-bound: 1.0.3 - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - - isarray@2.0.5: {} - - isbinaryfile@4.0.10: {} - - isexe@2.0.0: {} - - iterator.prototype@1.1.5: - dependencies: - define-data-property: 1.1.4 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - has-symbols: 1.1.0 - set-function-name: 2.0.2 - - js-tokens@4.0.0: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - jsbn@1.1.0: {} - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - jsx-ast-utils@3.3.5: - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.3 - object.assign: 4.1.7 - object.values: 1.2.1 - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.get@4.4.2: {} - - lodash.merge@4.6.2: {} - - lodash@4.17.21: {} - - log-symbols@3.0.0: - dependencies: - chalk: 2.4.2 - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - - lower-case-first@1.0.2: - dependencies: - lower-case: 1.1.4 - - lower-case@1.1.4: {} - - lru-cache@7.18.3: {} - - make-error@1.3.6: {} - - math-intrinsics@1.1.0: {} - - merge-stream@2.0.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mimic-fn@2.1.0: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 - - minimist@1.2.8: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - ms@2.1.3: {} - - mute-stream@0.0.8: {} - - nanoid@3.3.8: {} - - natural-compare@1.4.0: {} - - neo-async@2.6.2: {} - - netmask@2.0.2: {} - - next@15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0): - dependencies: - '@next/env': 15.1.6 - '@swc/counter': 0.1.3 - '@swc/helpers': 0.5.15 - busboy: 1.6.0 - caniuse-lite: 1.0.30001695 - postcss: 8.4.31 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - styled-jsx: 5.1.6(react@19.0.0) - optionalDependencies: - '@next/swc-darwin-arm64': 15.1.6 - '@next/swc-darwin-x64': 15.1.6 - '@next/swc-linux-arm64-gnu': 15.1.6 - '@next/swc-linux-arm64-musl': 15.1.6 - '@next/swc-linux-x64-gnu': 15.1.6 - '@next/swc-linux-x64-musl': 15.1.6 - '@next/swc-win32-arm64-msvc': 15.1.6 - '@next/swc-win32-x64-msvc': 15.1.6 - sharp: 0.33.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - no-case@2.3.2: - dependencies: - lower-case: 1.1.4 - - node-plop@0.26.3: - dependencies: - '@babel/runtime-corejs3': 7.26.7 - '@types/inquirer': 6.5.0 - change-case: 3.1.0 - del: 5.1.0 - globby: 10.0.2 - handlebars: 4.7.8 - inquirer: 7.3.3 - isbinaryfile: 4.0.10 - lodash.get: 4.4.2 - mkdirp: 0.5.6 - resolve: 1.22.10 - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - object-assign@4.1.1: {} - - object-inspect@1.13.3: {} - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - - object.entries@1.1.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - object.fromentries@2.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - - object.values@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - ora@4.1.1: - dependencies: - chalk: 3.0.0 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - log-symbols: 3.0.0 - mute-stream: 0.0.8 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - - ora@5.4.1: - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - - os-tmpdir@1.0.2: {} - - own-keys@1.0.1: - dependencies: - get-intrinsic: 1.2.7 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - p-map@3.0.0: - dependencies: - aggregate-error: 3.1.0 - - pac-proxy-agent@7.1.0: - dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 - agent-base: 7.1.3 - debug: 4.4.0 - get-uri: 6.0.4 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - pac-resolver: 7.0.1 - socks-proxy-agent: 8.0.5 - transitivePeerDependencies: - - supports-color - - pac-resolver@7.0.1: - dependencies: - degenerator: 5.0.1 - netmask: 2.0.2 - - param-case@2.1.1: - dependencies: - no-case: 2.3.2 - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - pascal-case@2.0.1: - dependencies: - camel-case: 3.0.0 - upper-case-first: 1.1.2 - - path-case@2.1.1: - dependencies: - no-case: 2.3.2 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-parse@1.0.7: {} - - path-type@4.0.0: {} - - picocolors@1.0.1: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - possible-typed-array-names@1.0.0: {} - - postcss@8.4.31: - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - prettier@3.4.2: {} - - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - proxy-agent@6.5.0: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - lru-cache: 7.18.3 - pac-proxy-agent: 7.1.0 - proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.5 - transitivePeerDependencies: - - supports-color - - proxy-from-env@1.1.0: {} - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - react-dom@19.0.0(react@19.0.0): - dependencies: - react: 19.0.0 - scheduler: 0.25.0 - - react-is@16.13.1: {} - - react@19.0.0: {} - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - - regenerator-runtime@0.14.1: {} - - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - - registry-auth-token@3.3.2: - dependencies: - rc: 1.2.8 - safe-buffer: 5.2.1 - - registry-url@3.1.0: - dependencies: - rc: 1.2.8 - - resolve-from@4.0.0: {} - - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - resolve@2.0.0-next.5: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - restore-cursor@3.1.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - - reusify@1.0.4: {} - - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - - run-async@2.4.1: {} - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - rxjs@6.6.7: - dependencies: - tslib: 1.14.1 - - rxjs@7.8.1: - dependencies: - tslib: 2.8.1 - - safe-array-concat@1.1.3: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - has-symbols: 1.1.0 - isarray: 2.0.5 - - safe-buffer@5.2.1: {} - - safe-push-apply@1.0.0: - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-regex: 1.2.1 - - safer-buffer@2.1.2: {} - - scheduler@0.25.0: {} - - semver@6.3.1: {} - - semver@7.6.2: {} - - semver@7.6.3: - optional: true - - semver@7.7.0: {} - - sentence-case@2.1.1: - dependencies: - no-case: 2.3.2 - upper-case-first: 1.1.2 - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - set-proto@1.0.0: - dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - - sharp@0.33.5: - dependencies: - color: 4.2.3 - detect-libc: 2.0.3 - semver: 7.6.3 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.5 - '@img/sharp-darwin-x64': 0.33.5 - '@img/sharp-libvips-darwin-arm64': 1.0.4 - '@img/sharp-libvips-darwin-x64': 1.0.4 - '@img/sharp-libvips-linux-arm': 1.0.5 - '@img/sharp-libvips-linux-arm64': 1.0.4 - '@img/sharp-libvips-linux-s390x': 1.0.4 - '@img/sharp-libvips-linux-x64': 1.0.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - '@img/sharp-linux-arm': 0.33.5 - '@img/sharp-linux-arm64': 0.33.5 - '@img/sharp-linux-s390x': 0.33.5 - '@img/sharp-linux-x64': 0.33.5 - '@img/sharp-linuxmusl-arm64': 0.33.5 - '@img/sharp-linuxmusl-x64': 0.33.5 - '@img/sharp-wasm32': 0.33.5 - '@img/sharp-win32-ia32': 0.33.5 - '@img/sharp-win32-x64': 0.33.5 - optional: true - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - signal-exit@3.0.7: {} - - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 - optional: true - - slash@3.0.0: {} - - smart-buffer@4.2.0: {} - - snake-case@2.1.0: - dependencies: - no-case: 2.3.2 - - socks-proxy-agent@8.0.5: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - socks: 2.8.3 - transitivePeerDependencies: - - supports-color - - socks@2.8.3: - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - - source-map-js@1.2.1: {} - - source-map@0.6.1: {} - - sprintf-js@1.1.3: {} - - streamsearch@1.1.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string.prototype.matchall@4.0.12: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.4 - set-function-name: 2.0.2 - side-channel: 1.1.0 - - string.prototype.repeat@1.0.0: - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.9 - - string.prototype.trim@1.2.10: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - - string.prototype.trimend@1.0.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-final-newline@2.0.0: {} - - strip-json-comments@2.0.1: {} - - strip-json-comments@3.1.1: {} - - styled-jsx@5.1.6(react@19.0.0): - dependencies: - client-only: 0.0.1 - react: 19.0.0 - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - swap-case@1.1.2: - dependencies: - lower-case: 1.1.4 - upper-case: 1.1.3 - - through@2.3.8: {} - - tinycolor2@1.6.0: {} - - tinygradient@1.1.5: - dependencies: - '@types/tinycolor2': 1.4.6 - tinycolor2: 1.6.0 - - title-case@2.1.1: - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - ts-api-utils@2.0.0(typescript@5.7.3): - dependencies: - typescript: 5.7.3 - - ts-node@10.9.2(@types/node@22.12.0)(typescript@5.7.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.12.0 - acorn: 8.14.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.7.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - tslib@1.14.1: {} - - tslib@2.8.1: {} - - turbo-darwin-64@2.3.4: - optional: true - - turbo-darwin-arm64@2.3.4: - optional: true - - turbo-linux-64@2.3.4: - optional: true - - turbo-linux-arm64@2.3.4: - optional: true - - turbo-windows-64@2.3.4: - optional: true - - turbo-windows-arm64@2.3.4: - optional: true - - turbo@2.3.4: - optionalDependencies: - turbo-darwin-64: 2.3.4 - turbo-darwin-arm64: 2.3.4 - turbo-linux-64: 2.3.4 - turbo-linux-arm64: 2.3.4 - turbo-windows-64: 2.3.4 - turbo-windows-arm64: 2.3.4 - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-fest@0.21.3: {} - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typed-array-byte-length@1.0.3: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - - typed-array-byte-offset@1.0.4: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - - typed-array-length@1.0.7: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.0.0 - reflect.getprototypeof: 1.0.10 - - typescript-eslint@8.22.0(eslint@9.19.0)(typescript@5.7.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - typescript@5.7.3: {} - - uglify-js@3.19.3: - optional: true - - unbox-primitive@1.1.0: - dependencies: - call-bound: 1.0.3 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - - undici-types@6.20.0: {} - - universalify@2.0.1: {} - - update-check@1.5.4: - dependencies: - registry-auth-token: 3.3.2 - registry-url: 3.1.0 - - upper-case-first@1.1.2: - dependencies: - upper-case: 1.1.3 - - upper-case@1.1.3: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - util-deprecate@1.0.2: {} - - v8-compile-cache-lib@3.0.1: {} - - validate-npm-package-name@5.0.1: {} - - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.1 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-builtin-type@1.2.1: - dependencies: - call-bound: 1.0.3 - function.prototype.name: 1.1.8 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.0 - is-regex: 1.2.1 - is-weakref: 1.1.0 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.18 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - - which-typed-array@1.1.18: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - for-each: 0.3.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - word-wrap@1.2.5: {} - - wordwrap@1.0.0: {} - - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - yn@3.1.1: {} - - yocto-queue@0.1.0: {} diff --git a/examples/design-system/.changeset/README.md b/examples/design-system/.changeset/README.md deleted file mode 100644 index e5b6d8d6a67ad..0000000000000 --- a/examples/design-system/.changeset/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Changesets - -Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works -with multi-package repos, or single-package repos to help you version and publish your code. You can -find the full documentation for it [in our repository](https://github.com/changesets/changesets) - -We have a quick list of common questions to get you started engaging with this project in -[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/examples/design-system/.changeset/config.json b/examples/design-system/.changeset/config.json deleted file mode 100644 index a91a85d36b9b3..0000000000000 --- a/examples/design-system/.changeset/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", - "changelog": "@changesets/cli/changelog", - "commit": false, - "fixed": [], - "linked": [], - "access": "public", - "updateInternalDependencies": "patch", - "ignore": [ - "@repo/docs" - ] -} \ No newline at end of file diff --git a/examples/design-system/.github/workflows/release.yml b/examples/design-system/.github/workflows/release.yml deleted file mode 100644 index 47c54b31a1de3..0000000000000 --- a/examples/design-system/.github/workflows/release.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Release - -on: - push: - branches: - - main - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - - name: Setup Node.js 20.x - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Install Dependencies - run: yarn - - - name: Create Release Pull Request or Publish to npm - id: changesets - uses: changesets/action@v1 - with: - # This expects you to have a script called release which does a build for your packages and calls changeset publish - publish: yarn release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Send a Slack notification if a publish happens - if: steps.changesets.outputs.published == 'true' - # You can do something when a publish happens. - run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!" diff --git a/examples/design-system/README.md b/examples/design-system/README.md deleted file mode 100644 index 1f3f68fb3193c..0000000000000 --- a/examples/design-system/README.md +++ /dev/null @@ -1,208 +0,0 @@ -# Turborepo Design System Starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -This guide explains how to use a React design system starter powered by: - -- 🎠[Turborepo](https://turbo.build/repo) — High-performance build system for Monorepos -- 🚀 [React](https://reactjs.org/) — JavaScript library for user interfaces -- 🛠 [Tsup](https://github.com/egoist/tsup) — TypeScript bundler powered by esbuild -- 📖 [Storybook](https://storybook.js.org/) — UI component environment powered by Vite - -As well as a few others tools preconfigured: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting -- [Changesets](https://github.com/changesets/changesets) for managing versioning and changelogs -- [GitHub Actions](https://github.com/changesets/action) for fully automated package publishing - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e design-system -``` - -### Useful Commands - -- `pnpm build` - Build all packages, including the Storybook site -- `pnpm dev` - Run all packages locally and preview with Storybook -- `pnpm lint` - Lint all packages -- `pnpm changeset` - Generate a changeset -- `pnpm clean` - Clean up all `node_modules` and `dist` folders (runs each package's clean script) - -## Turborepo - -[Turborepo](https://turbo.build/repo) is a high-performance build system for JavaScript and TypeScript codebases. It was designed after the workflows used by massive software engineering organizations to ship code at scale. Turborepo abstracts the complex configuration needed for monorepos and provides fast, incremental builds with zero-configuration remote caching. - -Using Turborepo simplifies managing your design system monorepo, as you can have a single lint, build, test, and release process for all packages. [Learn more](https://vercel.com/blog/monorepos-are-changing-how-teams-build-software) about how monorepos improve your development workflow. - -## Apps & Packages - -This Turborepo includes the following packages and applications: - -- `apps/docs`: Component documentation site with Storybook -- `packages/ui`: Core React components -- `packages/typescript-config`: Shared `tsconfig.json`s used throughout the Turborepo -- `packages/eslint-config`: ESLint preset - -Each package and app is 100% [TypeScript](https://www.typescriptlang.org/). Workspaces enables us to "hoist" dependencies that are shared between packages to the root `package.json`. This means smaller `node_modules` folders and a better local dev experience. To install a dependency for the entire monorepo, use the `-w` workspaces flag with `pnpm add`. - -This example sets up your `.gitignore` to exclude all generated files, other folders like `node_modules` used to store your dependencies. - -### Compilation - -To make the ui library code work across all browsers, we need to compile the raw TypeScript and React code to plain JavaScript. We can accomplish this with `tsup`, which uses `esbuild` to greatly improve performance. - -Running `pnpm build` from the root of the Turborepo will run the `build` command defined in each package's `package.json` file. Turborepo runs each `build` in parallel and caches & hashes the output to speed up future builds. - -For `@acme/ui`, the `build` command is equivalent to the following: - -```bash -tsup src/*.tsx --format esm,cjs --dts --external react -``` - -`tsup` compiles all of the components in the design system individually, into both ES Modules and CommonJS formats as well as their TypeScript types. The `package.json` for `@acme/ui` then instructs the consumer to select the correct format: - -```json:ui/package.json -{ - "name": "@acme/ui", - "version": "0.0.0", - "sideEffects": false, - "exports":{ - "./button": { - "types": "./src/button.tsx", - "import": "./dist/button.mjs", - "require": "./dist/button.js" - } - } -} -``` - -Run `pnpm build` to confirm compilation is working correctly. You should see a folder `ui/dist` which contains the compiled output. - -```bash -ui -└── dist - ├── button.d.ts <-- Types - ├── button.js <-- CommonJS version - ├── button.mjs <-- ES Modules version - └── button.d.mts <-- ES Modules version with Types -``` - -## Components - -Each file inside of `ui/src` is a component inside our design system. For example: - -```tsx:ui/src/Button.tsx -import * as React from 'react'; - -export interface ButtonProps { - children: React.ReactNode; -} - -export function Button(props: ButtonProps) { - return ; -} - -Button.displayName = 'Button'; -``` - -When adding a new file, ensure that its specifier is defined in `package.json` file: - -```json:ui/package.json -{ - "name": "@acme/ui", - "version": "0.0.0", - "sideEffects": false, - "exports":{ - "./button": { - "types": "./src/button.tsx", - "import": "./dist/button.mjs", - "require": "./dist/button.js" - } - // Add new component exports here - } -} -``` - -## Storybook - -Storybook provides us with an interactive UI playground for our components. This allows us to preview our components in the browser and instantly see changes when developing locally. This example preconfigures Storybook to: - -- Use Vite to bundle stories instantly (in milliseconds) -- Automatically find any stories inside the `stories/` folder -- Support using module path aliases like `@acme/ui` for imports -- Write MDX for component documentation pages - -For example, here's the included Story for our `Button` component: - -```js:apps/docs/stories/button.stories.mdx -import { Button } from '@acme/ui/button'; -import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks'; - - - -# Button - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nisl eget consectetur tempor, nisl nunc egestas nisi, euismod aliquam nisl nunc euismod. - -## Props - - - -## Examples - - - - - - -``` - -This example includes a few helpful Storybook scripts: - -- `pnpm dev`: Starts Storybook in dev mode with hot reloading at `localhost:6006` -- `pnpm build`: Builds the Storybook UI and generates the static HTML files -- `pnpm preview-storybook`: Starts a local server to view the generated Storybook UI - -## Versioning & Publishing Packages - -This example uses [Changesets](https://github.com/changesets/changesets) to manage versions, create changelogs, and publish to npm. It's preconfigured so you can start publishing packages immediately. - -You'll need to create an `NPM_TOKEN` and `GITHUB_TOKEN` and add it to your GitHub repository settings to enable access to npm. It's also worth installing the [Changesets bot](https://github.com/apps/changeset-bot) on your repository. - -### Generating the Changelog - -To generate your changelog, run `pnpm changeset` locally: - -1. **Which packages would you like to include?** – This shows which packages and changed and which have remained the same. By default, no packages are included. Press `space` to select the packages you want to include in the `changeset`. -1. **Which packages should have a major bump?** – Press `space` to select the packages you want to bump versions for. -1. If doing the first major version, confirm you want to release. -1. Write a summary for the changes. -1. Confirm the changeset looks as expected. -1. A new Markdown file will be created in the `changeset` folder with the summary and a list of the packages included. - -### Releasing - -When you push your code to GitHub, the [GitHub Action](https://github.com/changesets/action) will run the `release` script defined in the root `package.json`: - -```bash -turbo run build --filter=docs^... && changeset publish -``` - -Turborepo runs the `build` script for all publishable packages (excluding docs) and publishes the packages to npm. By default, this example includes `acme` as the npm organization. To change this, do the following: - -- Rename folders in `packages/*` to replace `acme` with your desired scope -- Search and replace `acme` with your desired scope -- Re-run `pnpm install` - -To publish packages to a private npm organization scope, **remove** the following from each of the `package.json`'s - -```diff -- "publishConfig": { -- "access": "public" -- }, -``` diff --git a/examples/design-system/apps/docs/.eslintrc.cjs b/examples/design-system/apps/docs/.eslintrc.cjs deleted file mode 100644 index a38cd2237cea1..0000000000000 --- a/examples/design-system/apps/docs/.eslintrc.cjs +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ["@repo/eslint-config/storybook.js"], -}; diff --git a/examples/design-system/apps/docs/package.json b/examples/design-system/apps/docs/package.json index 3045aad4c2d6e..b31027185ecbc 100644 --- a/examples/design-system/apps/docs/package.json +++ b/examples/design-system/apps/docs/package.json @@ -1,33 +1,23 @@ { - "name": "docs", - "version": "0.0.0", - "type": "module", - "private": true, - "scripts": { - "dev": "storybook dev -p 6006", - "build": "storybook build --docs", - "preview-storybook": "serve storybook-static", - "clean": "rm -rf .turbo node_modules", - "lint": "eslint ./stories/*.stories.tsx --max-warnings 0" - }, - "dependencies": { - "@acme/ui": "workspace:*", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@storybook/addon-actions": "^8.2.6", - "@storybook/addon-essentials": "^8.2.6", - "@storybook/addon-links": "^8.2.6", - "@storybook/react": "^8.2.6", - "@storybook/react-vite": "^8.2.6", - "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.57.0", - "serve": "^14.2.1", - "storybook": "^8.2.6", - "@repo/typescript-config": "workspace:*", - "typescript": "5.5.4", - "vite": "^5.1.4" - } -} \ No newline at end of file + "name": "docs", + "scripts": { + "build": "storybook build --docs", + "clean": "rm -rf .turbo node_modules", + "dev": "storybook dev -p 6006", + "preview-storybook": "serve storybook-static" + }, + "dependencies": { + "@acme/ui": "workspace:*" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@storybook/addon-actions": "8.5.5", + "@storybook/addon-essentials": "8.5.5", + "@storybook/addon-links": "8.5.5", + "@storybook/react": "8.5.5", + "@storybook/react-vite": "8.5.5", + "serve": "14.2.4", + "storybook": "8.5.5" + } +} diff --git a/examples/design-system/package.json b/examples/design-system/package.json index 467027feca676..19b8a5c5e69e1 100644 --- a/examples/design-system/package.json +++ b/examples/design-system/package.json @@ -1,21 +1,17 @@ { - "private": true, - "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "clean": "turbo run clean && rm -rf node_modules", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "changeset": "changeset", - "version-packages": "changeset version", - "release": "turbo run build --filter=docs^... && changeset publish", - "preview-storybook": "turbo preview-storybook" - }, - "devDependencies": { - "@changesets/cli": "^2.27.1", - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "pnpm@8.15.6", - "name": "design-system" -} \ No newline at end of file + "name": "design-system", + "scripts": { + "build": "turbo run build", + "changeset": "changeset", + "clean": "turbo run clean && rm -rf node_modules", + "dev": "turbo run dev", + "preview-storybook": "turbo preview-storybook", + "release": "turbo run build --filter=docs^... && changeset publish", + "version-packages": "changeset version" + }, + "dependencies": {}, + "devDependencies": { + "@changesets/cli": "2.27.12", + "turbo": "2.4.2" + } +} diff --git a/examples/design-system/packages/eslint-config/README.md b/examples/design-system/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/design-system/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/design-system/packages/eslint-config/package.json b/examples/design-system/packages/eslint-config/package.json index e7a9fd6a4cb8a..110f9be3d27f1 100644 --- a/examples/design-system/packages/eslint-config/package.json +++ b/examples/design-system/packages/eslint-config/package.json @@ -1,17 +1,16 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "react.js", - "storybook.js" - ], - "devDependencies": { - "@vercel/style-guide": "^5.2.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-mdx": "^3.1.5", - "eslint-plugin-only-warn": "^1.1.0", - "eslint-plugin-storybook": "^0.8.0" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "react.js", + "storybook.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-mdx": "3.1.5", + "eslint-plugin-only-warn": "1.1.0", + "eslint-plugin-storybook": "0.11.2" + } } diff --git a/examples/design-system/packages/typescript-config/package.json b/examples/design-system/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/design-system/packages/typescript-config/package.json +++ b/examples/design-system/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/design-system/packages/ui/.eslintrc.js b/examples/design-system/packages/ui/.eslintrc.js deleted file mode 100644 index f075bfab4e2fd..0000000000000 --- a/examples/design-system/packages/ui/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ["@repo/eslint-config/react.js"], -}; diff --git a/examples/design-system/packages/ui/src/button.tsx b/examples/design-system/packages/ui/Source/button.tsx similarity index 100% rename from examples/design-system/packages/ui/src/button.tsx rename to examples/design-system/packages/ui/Source/button.tsx diff --git a/examples/design-system/packages/ui/package.json b/examples/design-system/packages/ui/package.json index 452514d1f3837..1e64f711e16e1 100644 --- a/examples/design-system/packages/ui/package.json +++ b/examples/design-system/packages/ui/package.json @@ -1,34 +1,22 @@ { - "name": "@acme/ui", - "version": "0.0.0", - "sideEffects": false, - "license": "MIT", - "exports": { - "./button": { - "types": "./src/button.tsx", - "import": "./dist/button.mjs", - "require": "./dist/button.js" - } - }, - "scripts": { - "build": "tsup", - "dev": "tsup --watch", - "lint": "eslint . --max-warnings 0", - "clean": "rm -rf .turbo node_modules dist" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "@repo/typescript-config": "workspace:*", - "tsup": "^8.0.2", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - }, - "publishConfig": { - "access": "public" - } -} \ No newline at end of file + "name": "@acme/ui", + "sideEffects": false, + "exports": { + "./button": { + "import": "./dist/button.mjs", + "require": "./dist/button.js", + "types": "./src/button.tsx" + } + }, + "scripts": { + "build": "tsup", + "clean": "rm -rf .turbo node_modules dist", + "dev": "tsup --watch" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "tsup": "8.3.6" + } +} diff --git a/examples/design-system/pnpm-lock.yaml b/examples/design-system/pnpm-lock.yaml deleted file mode 100644 index 9bd51b32fae53..0000000000000 --- a/examples/design-system/pnpm-lock.yaml +++ /dev/null @@ -1,9630 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@changesets/cli': - specifier: ^2.27.1 - version: 2.27.2 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/docs: - dependencies: - '@acme/ui': - specifier: workspace:* - version: link:../../packages/ui - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@storybook/addon-actions': - specifier: ^8.2.6 - version: 8.2.6(storybook@8.2.6) - '@storybook/addon-essentials': - specifier: ^8.2.6 - version: 8.2.6(storybook@8.2.6) - '@storybook/addon-links': - specifier: ^8.2.6 - version: 8.2.6(react@18.3.1)(storybook@8.2.6) - '@storybook/react': - specifier: ^8.2.6 - version: 8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6)(typescript@5.5.4) - '@storybook/react-vite': - specifier: ^8.2.6 - version: 8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6)(typescript@5.5.4)(vite@5.2.11) - '@vitejs/plugin-react': - specifier: ^4.2.1 - version: 4.2.1(vite@5.2.11) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - serve: - specifier: ^14.2.1 - version: 14.2.3 - storybook: - specifier: ^8.2.6 - version: 8.2.6 - typescript: - specifier: 5.5.4 - version: 5.5.4 - vite: - specifier: ^5.1.4 - version: 5.2.11 - - packages/eslint-config: - devDependencies: - '@vercel/style-guide': - specifier: ^5.2.0 - version: 5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4) - eslint-config-turbo: - specifier: ^2.0.0 - version: 2.0.0(eslint@8.57.0) - eslint-plugin-mdx: - specifier: ^3.1.5 - version: 3.1.5(eslint@8.57.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - eslint-plugin-storybook: - specifier: ^0.8.0 - version: 0.8.0(eslint@8.57.0)(typescript@5.5.4) - - packages/typescript-config: {} - - packages/ui: - dependencies: - react: - specifier: ^18.2.0 - version: 18.3.1 - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@types/react': - specifier: ^18.2.61 - version: 18.3.2 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.3.0 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - tsup: - specifier: ^8.0.2 - version: 8.0.2(typescript@5.5.4) - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@babel/code-frame@7.24.2: - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.5 - picocolors: 1.0.1 - dev: true - - /@babel/compat-data@7.24.4: - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.24.5: - resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helpers': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/eslint-parser@7.24.5(@babel/core@7.24.5)(eslint@8.57.0): - resolution: {integrity: sha512-gsUcqS/fPlgAw1kOtpss7uhY6E9SFFANQ6EFX5GTvzUwaV0+sGaZWk6xq22MOdeT9wfxyokW3ceCUvOiRtZciQ==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - dependencies: - '@babel/core': 7.24.5 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.24.5: - resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-create-class-features-plugin@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - semver: 6.3.1 - dev: true - - /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.5): - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - semver: 6.3.1 - dev: true - - /@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.24.5): - resolution: {integrity: sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-member-expression-to-functions@7.24.5: - resolution: {integrity: sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-module-imports@7.24.3: - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.24.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 - dev: true - - /@babel/helper-optimise-call-expression@7.22.5: - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-plugin-utils@7.24.5: - resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.24.5): - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.24.5 - dev: true - - /@babel/helper-replace-supers@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 - dev: true - - /@babel/helper-simple-access@7.24.5: - resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-skip-transparent-expression-wrappers@7.22.5: - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-split-export-declaration@7.24.5: - resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-string-parser@7.24.1: - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.24.5: - resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-wrap-function@7.24.5: - resolution: {integrity: sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.23.0 - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - dev: true - - /@babel/helpers@7.24.5: - resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.24.5: - resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.5 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.1 - dev: true - - /@babel/parser@7.24.5: - resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.5) - dev: true - - /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.5): - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - dev: true - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.5): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.5): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-import-assertions@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.5): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.5): - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-arrow-functions@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-async-generator-functions@7.24.3(@babel/core@7.24.5): - resolution: {integrity: sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.5) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-async-to-generator@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-block-scoped-functions@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-block-scoping@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-class-properties@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-class-static-block@7.24.4(@babel/core@7.24.5): - resolution: {integrity: sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-classes@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) - '@babel/helper-split-export-declaration': 7.24.5 - globals: 11.12.0 - dev: true - - /@babel/plugin-transform-computed-properties@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/template': 7.24.0 - dev: true - - /@babel/plugin-transform-destructuring@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-dotall-regex@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-duplicate-keys@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-dynamic-import@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-exponentiation-operator@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-export-namespace-from@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-flow-strip-types@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-flow': 7.24.1(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-for-of@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: true - - /@babel/plugin-transform-function-name@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-json-strings@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-literals@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-logical-assignment-operators@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-member-expression-literals@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-amd@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-simple-access': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-systemjs@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-umd@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.24.5): - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-new-target@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-nullish-coalescing-operator@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-numeric-separator@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-object-rest-spread@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-object-super@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-optional-catch-binding@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-optional-chaining@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-parameters@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-private-methods@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-private-property-in-object@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-property-literals@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-react-jsx-self@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-RtCJoUO2oYrYwFPtR1/jkoBEcFuI1ae9a9IMxeyAVa3a1Ap4AnxmyIKG2b2FaJKqkidw/0cxRbWN+HOs6ZWd1w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-react-jsx-source@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - regenerator-transform: 0.15.2 - dev: true - - /@babel/plugin-transform-reserved-words@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-shorthand-properties@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-spread@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: true - - /@babel/plugin-transform-sticky-regex@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-template-literals@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-typeof-symbol@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-typescript@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) - dev: true - - /@babel/plugin-transform-unicode-escapes@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-unicode-property-regex@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-unicode-regex@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-unicode-sets-regex@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/preset-env@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.5) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.5) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.5) - '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-async-generator-functions': 7.24.3(@babel/core@7.24.5) - '@babel/plugin-transform-async-to-generator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-block-scoping': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-class-static-block': 7.24.4(@babel/core@7.24.5) - '@babel/plugin-transform-classes': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-destructuring': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-dotall-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-duplicate-keys': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-dynamic-import': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-exponentiation-operator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-export-namespace-from': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-json-strings': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-logical-assignment-operators': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-amd': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-systemjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-umd': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.24.5) - '@babel/plugin-transform-new-target': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-numeric-separator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-object-rest-spread': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-optional-catch-binding': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-private-property-in-object': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-regenerator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-reserved-words': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-sticky-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-typeof-symbol': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-escapes': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-property-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-sets-regex': 7.24.1(@babel/core@7.24.5) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.5) - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.5) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.5) - babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.24.5) - core-js-compat: 3.37.1 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/preset-flow@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-transform-flow-strip-types': 7.24.1(@babel/core@7.24.5) - dev: true - - /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.5): - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/types': 7.24.5 - esutils: 2.0.3 - dev: true - - /@babel/preset-typescript@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-typescript': 7.24.5(@babel/core@7.24.5) - dev: true - - /@babel/register@7.23.7(@babel/core@7.24.5): - resolution: {integrity: sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - clone-deep: 4.0.1 - find-cache-dir: 2.1.0 - make-dir: 2.1.0 - pirates: 4.0.6 - source-map-support: 0.5.21 - dev: true - - /@babel/regjsgen@0.8.0: - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - dev: true - - /@babel/runtime@7.24.5: - resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - dev: true - - /@babel/traverse@7.24.5: - resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.24.5: - resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 - to-fast-properties: 2.0.0 - dev: true - - /@base2/pretty-print-object@1.0.1: - resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==} - dev: true - - /@changesets/apply-release-plan@7.0.1: - resolution: {integrity: sha512-aPdSq/R++HOyfEeBGjEe6LNG8gs0KMSyRETD/J2092OkNq8mOioAxyKjMbvVUdzgr/HTawzMOz7lfw339KnsCA==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/config': 3.0.0 - '@changesets/get-version-range-type': 0.4.0 - '@changesets/git': 3.0.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - detect-indent: 6.1.0 - fs-extra: 7.0.1 - lodash.startcase: 4.4.0 - outdent: 0.5.0 - prettier: 2.8.8 - resolve-from: 5.0.0 - semver: 7.6.2 - dev: true - - /@changesets/assemble-release-plan@6.0.0: - resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - semver: 7.6.2 - dev: true - - /@changesets/changelog-git@0.2.0: - resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} - dependencies: - '@changesets/types': 6.0.0 - dev: true - - /@changesets/cli@2.27.2: - resolution: {integrity: sha512-6/kADjKMOrlLwNr/Y5HAq7T9oGOA2Lq5A59AGtwQCCiXuSGp4EgszzdJFeBiF8pdz7Wn1HaLzSUBhAaNToEJqg==} - hasBin: true - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/apply-release-plan': 7.0.1 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.0 - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/get-release-plan': 4.0.0 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 - '@changesets/types': 6.0.0 - '@changesets/write': 0.3.1 - '@manypkg/get-packages': 1.1.3 - '@types/semver': 7.5.8 - ansi-colors: 4.1.3 - chalk: 2.4.2 - ci-info: 3.9.0 - enquirer: 2.4.1 - external-editor: 3.1.0 - fs-extra: 7.0.1 - human-id: 1.0.2 - meow: 6.1.1 - outdent: 0.5.0 - p-limit: 2.3.0 - preferred-pm: 3.1.3 - resolve-from: 5.0.0 - semver: 7.6.2 - spawndamnit: 2.0.0 - term-size: 2.2.1 - tty-table: 4.2.3 - dev: true - - /@changesets/config@3.0.0: - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} - dependencies: - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/logger': 0.1.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - micromatch: 4.0.5 - dev: true - - /@changesets/errors@0.2.0: - resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - dependencies: - extendable-error: 0.1.7 - dev: true - - /@changesets/get-dependents-graph@2.0.0: - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} - dependencies: - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - chalk: 2.4.2 - fs-extra: 7.0.1 - semver: 7.6.2 - dev: true - - /@changesets/get-release-plan@4.0.0: - resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/config': 3.0.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - dev: true - - /@changesets/get-version-range-type@0.4.0: - resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - dev: true - - /@changesets/git@3.0.0: - resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - is-subdir: 1.2.0 - micromatch: 4.0.5 - spawndamnit: 2.0.0 - dev: true - - /@changesets/logger@0.1.0: - resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} - dependencies: - chalk: 2.4.2 - dev: true - - /@changesets/parse@0.4.0: - resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} - dependencies: - '@changesets/types': 6.0.0 - js-yaml: 3.14.1 - dev: true - - /@changesets/pre@2.0.0: - resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - dev: true - - /@changesets/read@0.6.0: - resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/parse': 0.4.0 - '@changesets/types': 6.0.0 - chalk: 2.4.2 - fs-extra: 7.0.1 - p-filter: 2.1.0 - dev: true - - /@changesets/types@4.1.0: - resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - dev: true - - /@changesets/types@6.0.0: - resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - dev: true - - /@changesets/write@0.3.1: - resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/types': 6.0.0 - fs-extra: 7.0.1 - human-id: 1.0.2 - prettier: 2.8.8 - dev: true - - /@esbuild/aix-ppc64@0.19.12: - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/aix-ppc64@0.20.2: - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.19.12: - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.20.2: - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.19.12: - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.20.2: - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.19.12: - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.20.2: - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.19.12: - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.20.2: - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.19.12: - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.20.2: - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.19.12: - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.20.2: - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.19.12: - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.20.2: - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.19.12: - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.20.2: - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.19.12: - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.20.2: - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.19.12: - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.20.2: - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.19.12: - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.20.2: - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.19.12: - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.20.2: - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.19.12: - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.20.2: - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.19.12: - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.20.2: - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.19.12: - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.20.2: - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.19.12: - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.20.2: - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.19.12: - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.20.2: - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.19.12: - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.20.2: - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.19.12: - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.20.2: - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.19.12: - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.20.2: - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.19.12: - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.20.2: - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.19.12: - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.20.2: - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.4)(vite@5.2.11): - resolution: {integrity: sha512-pdoMZ9QaPnVlSM+SdU/wgg0nyD/8wQ7y90ttO2CMCyrrm7RxveYIJ5eNfjPaoMFqW41LZra7QO9j+xV4Y18Glw==} - peerDependencies: - typescript: '>= 4.3.x' - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - glob: 7.2.3 - glob-promise: 4.2.2(glob@7.2.3) - magic-string: 0.27.0 - react-docgen-typescript: 2.2.2(typescript@5.5.4) - typescript: 5.5.4 - vite: 5.2.11 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@manypkg/find-root@1.1.0: - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} - dependencies: - '@babel/runtime': 7.24.5 - '@types/node': 12.20.55 - find-up: 4.1.0 - fs-extra: 8.1.0 - dev: true - - /@manypkg/get-packages@1.1.3: - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - dependencies: - '@babel/runtime': 7.24.5 - '@changesets/types': 4.1.0 - '@manypkg/find-root': 1.1.0 - fs-extra: 8.1.0 - globby: 11.1.0 - read-yaml-file: 1.1.0 - dev: true - - /@mdx-js/react@3.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: {integrity: sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==} - peerDependencies: - '@types/react': '>=16' - react: '>=16' - dependencies: - '@types/mdx': 2.0.13 - '@types/react': 18.3.2 - react: 18.3.1 - dev: true - - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true - - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@npmcli/config@8.3.2: - resolution: {integrity: sha512-IMzf+fhRXibqh9mBwXK/QFIr97SAlZjfwsWPEz/2pST1cE9k9LcwznO7aDNXJoMrDjxPHZmb2bAAKASsa6EedA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/map-workspaces': 3.0.6 - ci-info: 4.0.0 - ini: 4.1.2 - nopt: 7.2.1 - proc-log: 4.2.0 - read-package-json-fast: 3.0.2 - semver: 7.6.2 - walk-up-path: 3.0.1 - dev: true - - /@npmcli/map-workspaces@3.0.6: - resolution: {integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - '@npmcli/name-from-folder': 2.0.0 - glob: 10.3.15 - minimatch: 9.0.4 - read-package-json-fast: 3.0.2 - dev: true - - /@npmcli/name-from-folder@2.0.0: - resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@pkgr/core@0.1.1: - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true - - /@rollup/pluginutils@5.1.0: - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - - /@rollup/rollup-android-arm-eabi@4.17.2: - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.17.2: - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.17.2: - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.17.2: - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.17.2: - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-musleabihf@4.17.2: - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.17.2: - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.17.2: - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-powerpc64le-gnu@4.17.2: - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.17.2: - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-s390x-gnu@4.17.2: - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.17.2: - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.17.2: - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.17.2: - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.17.2: - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.17.2: - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rushstack/eslint-patch@1.10.3: - resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} - dev: true - - /@sindresorhus/merge-streams@2.3.0: - resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} - engines: {node: '>=18'} - dev: true - - /@storybook/addon-actions@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-iCsf3V28/jJ95w2zd8aSvR4denoA2UYV3fpNCTGOURqICyKOG3cyVxvqKp8Hhcwn7trNOsK+HlL6q5gpv56ViA==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - '@storybook/global': 5.0.0 - '@types/uuid': 9.0.8 - dequal: 2.0.3 - polished: 4.3.1 - storybook: 8.2.6 - uuid: 9.0.1 - dev: true - - /@storybook/addon-backgrounds@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-61NFowA6EmCw+Eyzp0U4fat9MlPDdnT7aoDyzqSImLwWLITY9IvmWuTeo7XKJZN3fe22z1r7cZseKdYrtaHcKw==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - '@storybook/global': 5.0.0 - memoizerific: 1.11.3 - storybook: 8.2.6 - ts-dedent: 2.2.0 - dev: true - - /@storybook/addon-controls@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-EHUwHy+oZZv3pXzN7fuXWrS/meHFjqcELY3RBvOyEkGf21agl6co6R1tnf6d5N5QoYAGfIbDO7dkauSL2RfNAw==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - dequal: 2.0.3 - lodash: 4.17.21 - storybook: 8.2.6 - ts-dedent: 2.2.0 - dev: true - - /@storybook/addon-docs@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-qe7hxntaezqjKdU9QS+Q9NFL6i/uNdBxdvOnCKgPhBAY/zY6yhk5t3sOvonynPK5nkaNAowfSNPIzNxAXlJ1sA==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - '@babel/core': 7.24.5 - '@mdx-js/react': 3.0.1(@types/react@18.3.2)(react@18.3.1) - '@storybook/blocks': 8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6) - '@storybook/csf-plugin': 8.2.6(storybook@8.2.6) - '@storybook/global': 5.0.0 - '@storybook/react-dom-shim': 8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6) - '@types/react': 18.3.2 - fs-extra: 11.2.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - rehype-external-links: 3.0.0 - rehype-slug: 6.0.0 - storybook: 8.2.6 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-essentials@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-diGjGZcZNov+RCAVQBTm8JKP2kUtMRuJIQFBeXdPWpu6hYBk6lw1FlAf2GywWGCvdny1pJT90hfoD33qUMNuDg==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - '@storybook/addon-actions': 8.2.6(storybook@8.2.6) - '@storybook/addon-backgrounds': 8.2.6(storybook@8.2.6) - '@storybook/addon-controls': 8.2.6(storybook@8.2.6) - '@storybook/addon-docs': 8.2.6(storybook@8.2.6) - '@storybook/addon-highlight': 8.2.6(storybook@8.2.6) - '@storybook/addon-measure': 8.2.6(storybook@8.2.6) - '@storybook/addon-outline': 8.2.6(storybook@8.2.6) - '@storybook/addon-toolbars': 8.2.6(storybook@8.2.6) - '@storybook/addon-viewport': 8.2.6(storybook@8.2.6) - storybook: 8.2.6 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-highlight@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-03cV9USsfP3bS4wYV06DYcIaGPfoheQe53Q0Jr1B2yJUVyIPKvmO2nGjLBsqzeL3Wl7vSfLQn0/dUdxCcbqLsw==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - '@storybook/global': 5.0.0 - storybook: 8.2.6 - dev: true - - /@storybook/addon-links@8.2.6(react@18.3.1)(storybook@8.2.6): - resolution: {integrity: sha512-CUuU3nk8wyZ3bljCmOG/OCKazan+bPuNbCph8N763zyzdEx5M/CbBxV9d3pi3zjYpix7txlqrl2/YdMCejfyFw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.6 - peerDependenciesMeta: - react: - optional: true - dependencies: - '@storybook/csf': 0.1.11 - '@storybook/global': 5.0.0 - react: 18.3.1 - storybook: 8.2.6 - ts-dedent: 2.2.0 - dev: true - - /@storybook/addon-measure@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-neI8YeSOAtOmzasLxo6O8ZLr2ebMaD7XVF+kYatl5+SpyuwwvUGcP9NkKe5S+mB8V2zxFUIsXS74XrhmQhRoaQ==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - '@storybook/global': 5.0.0 - storybook: 8.2.6 - tiny-invariant: 1.3.3 - dev: true - - /@storybook/addon-outline@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-uAlPtqDWlq7MQQ4zJT80qdjbSdLF/zsvtPhidX6h9cjLKNPWAv79xJQ14AJHaMv+Hzy5xKnM4wdEhgPbzKabQg==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - '@storybook/global': 5.0.0 - storybook: 8.2.6 - ts-dedent: 2.2.0 - dev: true - - /@storybook/addon-toolbars@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-0JmRirMpxHS6VZzBk0kY871xWTpkk3TN4S1sxoFf5fcnCfVTHDjEJ5Ws/QWru1RJlIZHuJKRdQIA6Vuq5X+KfQ==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - storybook: 8.2.6 - dev: true - - /@storybook/addon-viewport@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-IAxH9H8tVFzSmZhKf5E+EALiAdkp19RzGqP/rWluD8LH7oW5HumQE/4oN0ZhVMy1RxYsCKFYjWyAp7AuxeMRSw==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - memoizerific: 1.11.3 - storybook: 8.2.6 - dev: true - - /@storybook/blocks@8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6): - resolution: {integrity: sha512-nMlZJjVTyfOJ6xwORptsNuS1AZZlDbJUVXc2R8uukGd5GIXxxCdrPk4NvUsjfQslMT9LhYuFld3z62FATsM2rw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.6 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/csf': 0.1.11 - '@storybook/global': 5.0.0 - '@storybook/icons': 1.2.9(react-dom@18.3.1)(react@18.3.1) - '@types/lodash': 4.17.4 - color-convert: 2.0.1 - dequal: 2.0.3 - lodash: 4.17.21 - markdown-to-jsx: 7.4.7(react@18.3.1) - memoizerific: 1.11.3 - polished: 4.3.1 - react: 18.3.1 - react-colorful: 5.6.1(react-dom@18.3.1)(react@18.3.1) - react-dom: 18.3.1(react@18.3.1) - storybook: 8.2.6 - telejson: 7.2.0 - ts-dedent: 2.2.0 - util-deprecate: 1.0.2 - dev: true - - /@storybook/builder-vite@8.2.6(storybook@8.2.6)(typescript@5.5.4)(vite@5.2.11): - resolution: {integrity: sha512-3PrsPZAedpQUbzRBEl23Fi1zG5bkQD76JsygVwmfiSm4Est4K8kW2AIB2ht9cIfKXh3mfQkyQlxXKHeQEHeQwQ==} - peerDependencies: - '@preact/preset-vite': '*' - storybook: ^8.2.6 - typescript: '>= 4.3.x' - vite: ^4.0.0 || ^5.0.0 - vite-plugin-glimmerx: '*' - peerDependenciesMeta: - '@preact/preset-vite': - optional: true - typescript: - optional: true - vite-plugin-glimmerx: - optional: true - dependencies: - '@storybook/csf-plugin': 8.2.6(storybook@8.2.6) - '@types/find-cache-dir': 3.2.1 - browser-assert: 1.2.1 - es-module-lexer: 1.5.4 - express: 4.19.2 - find-cache-dir: 3.3.2 - fs-extra: 11.2.0 - magic-string: 0.30.10 - storybook: 8.2.6 - ts-dedent: 2.2.0 - typescript: 5.5.4 - vite: 5.2.11 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/codemod@8.2.6: - resolution: {integrity: sha512-+mFJ6R+JhJLpU7VPDlXU5Yn6nqIBq745GaEosnIiFOdNo3jaxJ58wq/sGhbQvoCHPUxMA+sDQvR7pS62YFoLRQ==} - dependencies: - '@babel/core': 7.24.5 - '@babel/preset-env': 7.24.5(@babel/core@7.24.5) - '@babel/types': 7.24.5 - '@storybook/core': 8.2.6 - '@storybook/csf': 0.1.11 - '@types/cross-spawn': 6.0.6 - cross-spawn: 7.0.3 - globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.24.5) - lodash: 4.17.21 - prettier: 3.2.5 - recast: 0.23.7 - tiny-invariant: 1.3.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /@storybook/components@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-H8ckH1AnLkHtMtvJ3J8LxnmDtHxkJ7NJacGctHMRrsBIvdKTVwlT4su5nAVVJlan/PrEou+jESfw+OjjBYE5PA==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - storybook: 8.2.6 - dev: true - - /@storybook/core@8.2.6: - resolution: {integrity: sha512-XY71g3AcpD6IiER9k9Lt+vlUMYfPIYgWekd7e0Ggzz2gJkPuLunKEdQccLGDSHf5OFAobHhrTJc7ZsvWhmDMag==} - dependencies: - '@storybook/csf': 0.1.11 - '@types/express': 4.17.21 - '@types/node': 18.19.33 - browser-assert: 1.2.1 - esbuild: 0.20.2 - esbuild-register: 3.5.0(esbuild@0.20.2) - express: 4.19.2 - process: 0.11.10 - recast: 0.23.7 - util: 0.12.5 - ws: 8.17.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /@storybook/csf-plugin@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-USn7E/bMQYVqvFBuW6d9rKoSuCImjk0BAmc/0wIOuMQ/yQNp2Xze0m8eVkNHUIUDokyx0TXDjRjwq10Xxk16ag==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - storybook: 8.2.6 - unplugin: 1.10.1 - dev: true - - /@storybook/csf@0.0.1: - resolution: {integrity: sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==} - dependencies: - lodash: 4.17.21 - dev: true - - /@storybook/csf@0.1.11: - resolution: {integrity: sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==} - dependencies: - type-fest: 2.19.0 - dev: true - - /@storybook/global@5.0.0: - resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} - dev: true - - /@storybook/icons@1.2.9(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: true - - /@storybook/manager-api@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-uv36h/b5RhlajWtEg4cVPBYV8gZs6juux0nIE+6G9i7vt8Ild6gM9tW1KNabgZcaHFiyWJYCNWxJZoKjgUmXDg==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - storybook: 8.2.6 - dev: true - - /@storybook/preview-api@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-5vTj2ndX5ng4nDntZYe+r8UwLjCIGFymhq5/r2adAvRKL+Bo4zQDWGO7bhvGJk16do2THb2JvPz49ComW9LLZw==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - storybook: 8.2.6 - dev: true - - /@storybook/react-dom-shim@8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6): - resolution: {integrity: sha512-B+x8UAEQPDp1yhN3tMh09NvSL38QNfJB7PAyLgKrfE7xIAzvewq+RLW2DfGkoZCy+Zr7QSHm1p7NOgud8+sQCg==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.6 - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - storybook: 8.2.6 - dev: true - - /@storybook/react-vite@8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6)(typescript@5.5.4)(vite@5.2.11): - resolution: {integrity: sha512-BpbteaIzsJZL1QN3iR7uuslrPfdtbZYXPhcU9awpfl5pW5MOQThuvl7728mwT8V7KdANeikJPgsnlETOb/afDA==} - engines: {node: '>=18.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.6 - vite: ^4.0.0 || ^5.0.0 - dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.4)(vite@5.2.11) - '@rollup/pluginutils': 5.1.0 - '@storybook/builder-vite': 8.2.6(storybook@8.2.6)(typescript@5.5.4)(vite@5.2.11) - '@storybook/react': 8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6)(typescript@5.5.4) - find-up: 5.0.0 - magic-string: 0.30.10 - react: 18.3.1 - react-docgen: 7.0.3 - react-dom: 18.3.1(react@18.3.1) - resolve: 1.22.8 - storybook: 8.2.6 - tsconfig-paths: 4.2.0 - vite: 5.2.11 - transitivePeerDependencies: - - '@preact/preset-vite' - - rollup - - supports-color - - typescript - - vite-plugin-glimmerx - dev: true - - /@storybook/react@8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6)(typescript@5.5.4): - resolution: {integrity: sha512-awJlzfiAMrf8l9AgiLhjXEJ+HvS3VKPxNNQaRwBELGq/vigjJe656tMrhvg4OIlJXtlS+6XPshd2knLwjIWNLw==} - engines: {node: '>=18.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.6 - typescript: '>= 4.2.x' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@storybook/components': 8.2.6(storybook@8.2.6) - '@storybook/global': 5.0.0 - '@storybook/manager-api': 8.2.6(storybook@8.2.6) - '@storybook/preview-api': 8.2.6(storybook@8.2.6) - '@storybook/react-dom-shim': 8.2.6(react-dom@18.3.1)(react@18.3.1)(storybook@8.2.6) - '@storybook/theming': 8.2.6(storybook@8.2.6) - '@types/escodegen': 0.0.6 - '@types/estree': 0.0.51 - '@types/node': 18.19.33 - acorn: 7.4.1 - acorn-jsx: 5.3.2(acorn@7.4.1) - acorn-walk: 7.2.0 - escodegen: 2.1.0 - html-tags: 3.3.1 - lodash: 4.17.21 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-element-to-jsx-string: 15.0.0(react-dom@18.3.1)(react@18.3.1) - semver: 7.6.2 - storybook: 8.2.6 - ts-dedent: 2.2.0 - type-fest: 2.19.0 - typescript: 5.5.4 - util-deprecate: 1.0.2 - dev: true - - /@storybook/theming@8.2.6(storybook@8.2.6): - resolution: {integrity: sha512-ICnYuLIVsYifVCMQljdHgrp+5vAquNybHxDGWiPeOxBicotwHF8rLhTckD2CdVQbMp0jk6r6jetvjXbFJ2MbvQ==} - peerDependencies: - storybook: ^8.2.6 - dependencies: - storybook: 8.2.6 - dev: true - - /@types/acorn@4.0.6: - resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} - dependencies: - '@types/estree': 1.0.5 - dev: true - - /@types/babel__core@7.20.5: - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.5 - dev: true - - /@types/babel__generator@7.6.8: - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@types/babel__template@7.4.4: - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - dev: true - - /@types/babel__traverse@7.20.5: - resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.12.12 - dev: true - - /@types/concat-stream@2.0.3: - resolution: {integrity: sha512-3qe4oQAPNwVNwK4C9c8u+VJqv9kez+2MR4qJpoPFfXtgxxif1QbFusvXzK0/Wra2VX07smostI2VMmJNSpZjuQ==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/cross-spawn@6.0.6: - resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/debug@4.1.12: - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - dependencies: - '@types/ms': 0.7.34 - dev: true - - /@types/doctrine@0.0.9: - resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} - dev: true - - /@types/emscripten@1.39.12: - resolution: {integrity: sha512-AQImDBgudQfMqUBfrjZYilRxoHDzTBp+ejh+g1fY67eSMalwIKtBXofjpyI0JBgNpHGzxeGAR2QDya0wxW9zbA==} - dev: true - - /@types/escodegen@0.0.6: - resolution: {integrity: sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==} - dev: true - - /@types/estree-jsx@1.0.5: - resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - dependencies: - '@types/estree': 1.0.5 - dev: true - - /@types/estree@0.0.51: - resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} - dev: true - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/express-serve-static-core@4.19.0: - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} - dependencies: - '@types/node': 20.12.12 - '@types/qs': 6.9.15 - '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 - dev: true - - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 - '@types/qs': 6.9.15 - '@types/serve-static': 1.15.7 - dev: true - - /@types/find-cache-dir@3.2.1: - resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==} - dev: true - - /@types/glob@7.2.0: - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 20.12.12 - dev: true - - /@types/hast@3.0.4: - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - dependencies: - '@types/unist': 3.0.2 - dev: true - - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true - - /@types/is-empty@1.2.3: - resolution: {integrity: sha512-4J1l5d79hoIvsrKh5VUKVRA1aIdsOb10Hu5j3J2VfP/msDnfTdGPmNp2E1Wg+vs97Bktzo+MZePFFXSGoykYJw==} - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/lodash@4.17.4: - resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==} - dev: true - - /@types/mdast@3.0.15: - resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} - dependencies: - '@types/unist': 2.0.10 - dev: true - - /@types/mdast@4.0.4: - resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - dependencies: - '@types/unist': 3.0.2 - dev: true - - /@types/mdx@2.0.13: - resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} - dev: true - - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true - - /@types/minimatch@5.1.2: - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - dev: true - - /@types/minimist@1.2.5: - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - dev: true - - /@types/ms@0.7.34: - resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - dev: true - - /@types/node@12.20.55: - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - dev: true - - /@types/node@18.19.33: - resolution: {integrity: sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/node@20.12.12: - resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: true - - /@types/prop-types@15.7.12: - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - dev: true - - /@types/qs@6.9.15: - resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} - dev: true - - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true - - /@types/react-dom@18.3.0: - resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - dependencies: - '@types/react': 18.3.2 - dev: true - - /@types/react@18.3.2: - resolution: {integrity: sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==} - dependencies: - '@types/prop-types': 15.7.12 - csstype: 3.1.3 - dev: true - - /@types/resolve@1.20.6: - resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} - dev: true - - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true - - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.12.12 - dev: true - - /@types/serve-static@1.15.7: - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 20.12.12 - '@types/send': 0.17.4 - dev: true - - /@types/supports-color@8.1.3: - resolution: {integrity: sha512-Hy6UMpxhE3j1tLpl27exp1XqHD7n8chAiNPzWfz16LPZoMMoSc4dzLl6w9qijkEb/r5O1ozdu1CWGA2L83ZeZg==} - dev: true - - /@types/unist@2.0.10: - resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} - dev: true - - /@types/unist@3.0.2: - resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} - dev: true - - /@types/uuid@9.0.8: - resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} - dev: true - - /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - - /@typescript-eslint/scope-manager@6.21.0: - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - dev: true - - /@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@6.21.0: - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.4): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.2 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@6.21.0(typescript@5.5.4): - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.6.2 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.6.2 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@6.21.0: - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@vercel/style-guide@5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4): - resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} - engines: {node: '>=16'} - peerDependencies: - '@next/eslint-plugin-next': '>=12.3.0 <15' - eslint: '>=8.48.0 <9' - prettier: '>=3.0.0 <4' - typescript: '>=4.8.0 <6' - peerDependenciesMeta: - '@next/eslint-plugin-next': - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - dependencies: - '@babel/core': 7.24.5 - '@babel/eslint-parser': 7.24.5(@babel/core@7.24.5)(eslint@8.57.0) - '@rushstack/eslint-patch': 1.10.3 - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) - eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.1) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0) - eslint-plugin-react: 7.34.1(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) - eslint-plugin-testing-library: 6.2.2(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) - prettier: 3.2.5 - prettier-plugin-packagejson: 2.5.0(prettier@3.2.5) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /@vitejs/plugin-react@4.2.1(vite@5.2.11): - resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/plugin-transform-react-jsx-self': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.5) - '@types/babel__core': 7.20.5 - react-refresh: 0.14.2 - vite: 5.2.11 - transitivePeerDependencies: - - supports-color - dev: true - - /@yarnpkg/fslib@2.10.3: - resolution: {integrity: sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==} - engines: {node: '>=12 <14 || 14.2 - 14.9 || >14.10.0'} - dependencies: - '@yarnpkg/libzip': 2.3.0 - tslib: 1.14.1 - dev: true - - /@yarnpkg/libzip@2.3.0: - resolution: {integrity: sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==} - engines: {node: '>=12 <14 || 14.2 - 14.9 || >14.10.0'} - dependencies: - '@types/emscripten': 1.39.12 - tslib: 1.14.1 - dev: true - - /@zeit/schemas@2.36.0: - resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==} - dev: true - - /abbrev@2.0.0: - resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: true - - /acorn-jsx@5.3.2(acorn@7.4.1): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 7.4.1 - dev: true - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn-walk@7.2.0: - resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn@7.4.1: - resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - dependencies: - string-width: 4.2.3 - dev: true - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - dev: true - - /arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: true - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - dependencies: - dequal: 2.0.3 - dev: true - - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - dev: true - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: true - - /array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.toreversed@1.1.2: - resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.tosorted@1.1.3: - resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - dev: true - - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - dev: true - - /arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true - - /ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - dev: true - - /ast-types@0.16.1: - resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} - engines: {node: '>=4'} - dependencies: - tslib: 2.6.2 - dev: true - - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - dev: true - - /axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - dev: true - - /axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} - dependencies: - dequal: 2.0.3 - dev: true - - /babel-core@7.0.0-bridge.0(@babel/core@7.24.5): - resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - dev: true - - /babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.24.5): - resolution: {integrity: sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.5 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) - core-js-compat: 3.37.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.24.5): - resolution: {integrity: sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) - transitivePeerDependencies: - - supports-color - dev: true - - /bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - - /better-path-resolve@1.0.0: - resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} - engines: {node: '>=4'} - dependencies: - is-windows: 1.0.2 - dev: true - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: true - - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /boxen@7.0.0: - resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==} - engines: {node: '>=14.16'} - dependencies: - ansi-align: 3.0.1 - camelcase: 7.0.1 - chalk: 5.0.1 - cli-boxes: 3.0.0 - string-width: 5.1.2 - type-fest: 2.19.0 - widest-line: 4.0.1 - wrap-ansi: 8.1.0 - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /breakword@1.0.6: - resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} - dependencies: - wcwidth: 1.0.1 - dev: true - - /browser-assert@1.2.1: - resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} - dev: true - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001620 - electron-to-chromium: 1.4.774 - node-releases: 2.0.14 - update-browserslist-db: 1.0.16(browserslist@4.23.0) - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /bundle-require@4.1.0(esbuild@0.19.12): - resolution: {integrity: sha512-FeArRFM+ziGkRViKRnSTbHZc35dgmR9yNog05Kn0+ItI59pOAISGvnnIwW1WgFZQW59IxD9QpJnUPkdIPfZuXg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - peerDependencies: - esbuild: '>=0.17' - dependencies: - esbuild: 0.19.12 - load-tsconfig: 0.2.5 - dev: true - - /bytes@3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - dev: true - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: true - - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - dev: true - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /camelcase@7.0.1: - resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} - engines: {node: '>=14.16'} - dev: true - - /caniuse-lite@1.0.30001620: - resolution: {integrity: sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==} - dev: true - - /ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - dev: true - - /chalk-template@0.4.0: - resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} - engines: {node: '>=12'} - dependencies: - chalk: 4.1.2 - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk@5.0.1: - resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - - /character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - dev: true - - /character-entities-legacy@1.1.4: - resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} - dev: true - - /character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - dev: true - - /character-entities@1.2.4: - resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} - dev: true - - /character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - dev: true - - /character-reference-invalid@1.1.4: - resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} - dev: true - - /character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - dev: true - - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: true - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /ci-info@4.0.0: - resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} - engines: {node: '>=8'} - dev: true - - /citty@0.1.6: - resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - dependencies: - consola: 3.2.3 - dev: true - - /clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /cli-boxes@3.0.0: - resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} - engines: {node: '>=10'} - dev: true - - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: true - - /cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - dev: true - - /clipboardy@3.0.0: - resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - arch: 2.2.0 - execa: 5.1.1 - is-wsl: 2.2.0 - dev: true - - /cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - dev: true - - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - dev: true - - /commander@6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - dev: true - - /commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true - - /compressible@2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /compression@1.7.4: - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9 - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /concat-stream@2.0.0: - resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} - engines: {'0': node >= 6.0} - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 3.6.2 - typedarray: 0.0.6 - dev: true - - /consola@3.2.3: - resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} - engines: {node: ^14.18.0 || >=16.10.0} - dev: true - - /content-disposition@0.5.2: - resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==} - engines: {node: '>= 0.6'} - dev: true - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: true - - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - dev: true - - /core-js-compat@3.37.1: - resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} - dependencies: - browserslist: 4.23.0 - dev: true - - /cross-spawn@5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} - dependencies: - lru-cache: 4.1.5 - shebang-command: 1.2.0 - which: 1.3.1 - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /crypto-random-string@4.0.0: - resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} - engines: {node: '>=12'} - dependencies: - type-fest: 1.4.0 - dev: true - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - dev: true - - /csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - dev: true - - /csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - dev: true - - /csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - dev: true - - /csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} - dependencies: - csv-generate: 3.4.3 - csv-parse: 4.16.3 - csv-stringify: 5.6.5 - stream-transform: 2.1.3 - dev: true - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - dev: true - - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /decode-named-character-reference@1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - dependencies: - character-entities: 2.0.2 - dev: true - - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - dev: true - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true - - /defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: true - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true - - /detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - dev: true - - /detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - dev: true - - /detect-newline@4.0.1: - resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /devlop@1.1.0: - resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - dependencies: - dequal: 2.0.3 - dev: true - - /diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true - - /electron-to-chromium@1.4.774: - resolution: {integrity: sha512-132O1XCd7zcTkzS3FgkAzKmnBuNJjK8WjcTtNuoylj7MYbqw5eXehjQ5OK91g0zm7OTKIPeaAG4CPoRfD9M1Mg==} - dev: true - - /emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: true - - /enhanced-resolve@5.16.1: - resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - dev: true - - /envinfo@7.13.0: - resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.0 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 - globalthis: 1.0.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true - - /es-iterator-helpers@1.0.19: - resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-set-tostringtag: 2.0.3 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - globalthis: 1.0.4 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - iterator.prototype: 1.1.2 - safe-array-concat: 1.1.2 - dev: true - - /es-module-lexer@1.5.4: - resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} - dev: true - - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - dev: true - - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - dev: true - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.2 - dev: true - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /esbuild-register@3.5.0(esbuild@0.20.2): - resolution: {integrity: sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==} - peerDependencies: - esbuild: '>=0.12 <1' - dependencies: - debug: 4.3.4 - esbuild: 0.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 - dev: true - - /esbuild@0.20.2: - resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.20.2 - '@esbuild/android-arm': 0.20.2 - '@esbuild/android-arm64': 0.20.2 - '@esbuild/android-x64': 0.20.2 - '@esbuild/darwin-arm64': 0.20.2 - '@esbuild/darwin-x64': 0.20.2 - '@esbuild/freebsd-arm64': 0.20.2 - '@esbuild/freebsd-x64': 0.20.2 - '@esbuild/linux-arm': 0.20.2 - '@esbuild/linux-arm64': 0.20.2 - '@esbuild/linux-ia32': 0.20.2 - '@esbuild/linux-loong64': 0.20.2 - '@esbuild/linux-mips64el': 0.20.2 - '@esbuild/linux-ppc64': 0.20.2 - '@esbuild/linux-riscv64': 0.20.2 - '@esbuild/linux-s390x': 0.20.2 - '@esbuild/linux-x64': 0.20.2 - '@esbuild/netbsd-x64': 0.20.2 - '@esbuild/openbsd-x64': 0.20.2 - '@esbuild/sunos-x64': 0.20.2 - '@esbuild/win32-arm64': 0.20.2 - '@esbuild/win32-ia32': 0.20.2 - '@esbuild/win32-x64': 0.20.2 - dev: true - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: true - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-config-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-turbo: 2.0.0(eslint@8.57.0) - dev: true - - /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.1): - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - dependencies: - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - dev: true - - /eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): - resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.4 - enhanced-resolve: 5.16.1 - eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.7.5 - is-core-module: 2.13.1 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-mdx@3.1.5(eslint@8.57.0): - resolution: {integrity: sha512-ynztX0k7CQ3iDL7fDEIeg3g0O/d6QPv7IBI9fdYLhXp5fAp0fi8X22xF/D3+Pk0f90R27uwqa1clHpay6t0l8Q==} - engines: {node: '>=18.0.0'} - peerDependencies: - eslint: '>=8.0.0' - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint: 8.57.0 - espree: 9.6.1 - estree-util-visit: 2.0.0 - remark-mdx: 3.0.1 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - synckit: 0.9.0 - tslib: 2.6.2 - unified: 11.0.4 - unified-engine: 11.2.1 - unist-util-visit: 5.0.0 - uvu: 0.5.6 - vfile: 6.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): - resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} - engines: {node: '>=6.5.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - escape-string-regexp: 1.0.5 - eslint: 8.57.0 - ignore: 5.3.1 - dev: true - - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.24.5 - aria-query: 5.3.0 - array-includes: 3.1.8 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.19 - eslint: 8.57.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - dev: true - - /eslint-plugin-markdown@3.0.1(eslint@8.57.0): - resolution: {integrity: sha512-8rqoc148DWdGdmYF6WSQFT3uQ6PO7zXYgeBpHAOAakX/zpq+NvFYbDA/H7PYzHajwtmaOzAwfxyl++x0g1/N9A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - eslint: 8.57.0 - mdast-util-from-markdown: 0.8.5 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-mdx@3.1.5(eslint@8.57.0): - resolution: {integrity: sha512-lUE7tP7IrIRHU3gTtASDe5u4YM2SvQveYVJfuo82yn3MLh/B/v05FNySURCK4aIxIYF1QYo3IRemQG/lyQzpAg==} - engines: {node: '>=18.0.0'} - peerDependencies: - eslint: '>=8.0.0' - dependencies: - eslint: 8.57.0 - eslint-mdx: 3.1.5(eslint@8.57.0) - eslint-plugin-markdown: 3.0.1(eslint@8.57.0) - remark-mdx: 3.0.1 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - tslib: 2.6.2 - unified: 11.0.4 - vfile: 6.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0): - resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} - peerDependencies: - eslint: '>=7' - eslint-plugin-jest: '>=25' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - dependencies: - eslint: 8.57.0 - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - dev: true - - /eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): - resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react@7.34.1(eslint@8.57.0): - resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.2 - array.prototype.toreversed: 1.1.2 - array.prototype.tosorted: 1.1.3 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.19 - eslint: 8.57.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.hasown: 1.1.4 - object.values: 1.2.0 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.11 - dev: true - - /eslint-plugin-storybook@0.8.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==} - engines: {node: '>= 18'} - peerDependencies: - eslint: '>=6' - dependencies: - '@storybook/csf': 0.0.1 - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - requireindex: 1.2.0 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-testing-library@6.2.2(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true - - /eslint-plugin-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.0 - dev: true - - /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.44.0' - dependencies: - '@babel/helper-validator-identifier': 7.24.5 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - ci-info: 3.9.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.6.2 - strip-indent: 3.0.0 - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-util-is-identifier-name@3.0.0: - resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - dev: true - - /estree-util-visit@2.0.0: - resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/unist': 3.0.2 - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - dev: true - - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: true - - /extendable-error@0.1.7: - resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} - dev: true - - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fast-url-parser@1.1.3: - resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} - dependencies: - punycode: 1.4.1 - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /fd-package-json@1.2.0: - resolution: {integrity: sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==} - dependencies: - walk-up-path: 3.0.1 - dev: true - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /find-cache-dir@2.1.0: - resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} - engines: {node: '>=6'} - dependencies: - commondir: 1.0.1 - make-dir: 2.1.0 - pkg-dir: 3.0.0 - dev: true - - /find-cache-dir@3.3.2: - resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} - engines: {node: '>=8'} - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - dev: true - - /find-up@3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - dependencies: - locate-path: 3.0.0 - dev: true - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} - dependencies: - micromatch: 4.0.5 - pkg-dir: 4.2.0 - dev: true - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true - - /flow-parser@0.236.0: - resolution: {integrity: sha512-0OEk9Gr+Yj7wjDW2KgaNYUypKau71jAfFyeLQF5iVtxqc6uJHag/MT7pmaEApf4qM7u86DkBcd4ualddYMfbLw==} - engines: {node: '>=0.4.0'} - dev: true - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: true - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: true - - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - dev: true - - /get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - dev: true - - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - dev: true - - /get-tsconfig@4.7.5: - resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true - - /giget@1.2.3: - resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} - hasBin: true - dependencies: - citty: 0.1.6 - consola: 3.2.3 - defu: 6.1.4 - node-fetch-native: 1.6.4 - nypm: 0.3.8 - ohash: 1.1.3 - pathe: 1.1.2 - tar: 6.2.1 - dev: true - - /git-hooks-list@3.1.0: - resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} - dev: true - - /github-slugger@2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-promise@4.2.2(glob@7.2.3): - resolution: {integrity: sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==} - engines: {node: '>=12'} - peerDependencies: - glob: ^7.1.6 - dependencies: - '@types/glob': 7.2.0 - glob: 7.2.3 - dev: true - - /glob@10.3.15: - resolution: {integrity: sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==} - engines: {node: '>=16 || 14 >=14.18'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.1.1 - path-scurry: 1.11.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - gopd: 1.0.1 - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /globby@14.0.2: - resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==} - engines: {node: '>=18'} - dependencies: - '@sindresorhus/merge-streams': 2.3.0 - fast-glob: 3.3.2 - ignore: 5.3.1 - path-type: 5.0.0 - slash: 5.1.0 - unicorn-magic: 0.1.0 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true - - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: true - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /hast-util-heading-rank@3.0.0: - resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} - dependencies: - '@types/hast': 3.0.4 - dev: true - - /hast-util-is-element@3.0.0: - resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} - dependencies: - '@types/hast': 3.0.4 - dev: true - - /hast-util-to-string@3.0.0: - resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} - dependencies: - '@types/hast': 3.0.4 - dev: true - - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /html-tags@3.3.1: - resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} - engines: {node: '>=8'} - dev: true - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - - /human-id@1.0.2: - resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - dev: true - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /import-meta-resolve@4.1.0: - resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - - /ini@4.1.2: - resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - dev: true - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: true - - /is-absolute-url@4.0.1: - resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /is-alphabetical@1.0.4: - resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} - dev: true - - /is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - dev: true - - /is-alphanumerical@1.0.4: - resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} - dependencies: - is-alphabetical: 1.0.4 - is-decimal: 1.0.4 - dev: true - - /is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - dev: true - - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.2 - dev: true - - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - dependencies: - is-typed-array: 1.1.13 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-decimal@1.0.4: - resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} - dev: true - - /is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-empty@1.2.0: - resolution: {integrity: sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==} - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-hexadecimal@1.0.4: - resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} - dev: true - - /is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - dev: true - - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: true - - /is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - dev: true - - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: true - - /is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /is-plain-object@5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} - engines: {node: '>=0.10.0'} - dev: true - - /is-port-reachable@4.0.0: - resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - dev: true - - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-subdir@1.2.0: - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} - engines: {node: '>=4'} - dependencies: - better-path-resolve: 1.0.0 - dev: true - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.15 - dev: true - - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true - - /is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - dev: true - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-weakset@2.0.3: - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - dev: true - - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.6 - set-function-name: 2.0.2 - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - - /joycon@3.1.1: - resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} - engines: {node: '>=10'} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jscodeshift@0.15.2(@babel/preset-env@7.24.5): - resolution: {integrity: sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==} - hasBin: true - peerDependencies: - '@babel/preset-env': ^7.1.6 - peerDependenciesMeta: - '@babel/preset-env': - optional: true - dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.5) - '@babel/preset-env': 7.24.5(@babel/core@7.24.5) - '@babel/preset-flow': 7.24.1(@babel/core@7.24.5) - '@babel/preset-typescript': 7.24.1(@babel/core@7.24.5) - '@babel/register': 7.23.7(@babel/core@7.24.5) - babel-core: 7.0.0-bridge.0(@babel/core@7.24.5) - chalk: 4.1.2 - flow-parser: 0.236.0 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - neo-async: 2.6.2 - node-dir: 0.1.17 - recast: 0.23.7 - temp: 0.8.4 - write-file-atomic: 2.4.3 - transitivePeerDependencies: - - supports-color - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-parse-even-better-errors@3.0.2: - resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.2 - object.assign: 4.1.5 - object.values: 1.2.0 - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: true - - /language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} - dev: true - - /language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - dependencies: - language-subtag-registry: 0.3.22 - dev: true - - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lilconfig@3.1.1: - resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} - engines: {node: '>=14'} - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /lines-and-columns@2.0.4: - resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /load-plugin@6.0.3: - resolution: {integrity: sha512-kc0X2FEUZr145odl68frm+lMJuQ23+rTXYmR6TImqPtbpmXC4vVXbWKDQ9IzndA0HfyQamWfKLhzsqGSTxE63w==} - dependencies: - '@npmcli/config': 8.3.2 - import-meta-resolve: 4.1.0 - dev: true - - /load-tsconfig@0.2.5: - resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} - dependencies: - graceful-fs: 4.2.11 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 - dev: true - - /locate-path@3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash.sortby@4.7.0: - resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - dev: true - - /lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - - /longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - dev: true - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - - /lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} - dependencies: - pseudomap: 1.0.2 - yallist: 2.1.2 - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /magic-string@0.27.0: - resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /make-dir@2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - dependencies: - pify: 4.0.1 - semver: 5.7.2 - dev: true - - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.1 - dev: true - - /map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true - - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true - - /map-or-similar@1.5.0: - resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} - dev: true - - /markdown-to-jsx@7.4.7(react@18.3.1): - resolution: {integrity: sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==} - engines: {node: '>= 10'} - peerDependencies: - react: '>= 0.14.0' - dependencies: - react: 18.3.1 - dev: true - - /mdast-util-from-markdown@0.8.5: - resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} - dependencies: - '@types/mdast': 3.0.15 - mdast-util-to-string: 2.0.0 - micromark: 2.11.4 - parse-entities: 2.0.0 - unist-util-stringify-position: 2.0.3 - transitivePeerDependencies: - - supports-color - dev: true - - /mdast-util-from-markdown@2.0.0: - resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.2 - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - mdast-util-to-string: 4.0.0 - micromark: 4.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-decode-string: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - unist-util-stringify-position: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /mdast-util-mdx-expression@2.0.0: - resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /mdast-util-mdx-jsx@3.1.2: - resolution: {integrity: sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/unist': 3.0.2 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - parse-entities: 4.0.1 - stringify-entities: 4.0.4 - unist-util-remove-position: 5.0.0 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /mdast-util-mdx@3.0.0: - resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} - dependencies: - mdast-util-from-markdown: 2.0.0 - mdast-util-mdx-expression: 2.0.0 - mdast-util-mdx-jsx: 3.1.2 - mdast-util-mdxjs-esm: 2.0.1 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /mdast-util-mdxjs-esm@2.0.1: - resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /mdast-util-phrasing@4.1.0: - resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - dependencies: - '@types/mdast': 4.0.4 - unist-util-is: 6.0.0 - dev: true - - /mdast-util-to-markdown@2.1.0: - resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.2 - longest-streak: 3.1.0 - mdast-util-phrasing: 4.1.0 - mdast-util-to-string: 4.0.0 - micromark-util-decode-string: 2.0.0 - unist-util-visit: 5.0.0 - zwitch: 2.0.4 - dev: true - - /mdast-util-to-string@2.0.0: - resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} - dev: true - - /mdast-util-to-string@4.0.0: - resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - dependencies: - '@types/mdast': 4.0.4 - dev: true - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: true - - /memoizerific@1.11.3: - resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} - dependencies: - map-or-similar: 1.5.0 - dev: true - - /meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} - dependencies: - '@types/minimist': 1.2.5 - camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 2.5.0 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.13.1 - yargs-parser: 18.1.3 - dev: true - - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: true - - /micromark-core-commonmark@2.0.1: - resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} - dependencies: - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - micromark-factory-destination: 2.0.0 - micromark-factory-label: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-factory-title: 2.0.0 - micromark-factory-whitespace: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-html-tag-name: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-subtokenize: 2.0.1 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-extension-mdx-expression@3.0.0: - resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} - dependencies: - '@types/estree': 1.0.5 - devlop: 1.1.0 - micromark-factory-mdx-expression: 2.0.1 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-events-to-acorn: 2.0.2 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-extension-mdx-jsx@3.0.0: - resolution: {integrity: sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==} - dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.5 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - micromark-factory-mdx-expression: 2.0.1 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - vfile-message: 4.0.2 - dev: true - - /micromark-extension-mdx-md@2.0.0: - resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} - dependencies: - micromark-util-types: 2.0.0 - dev: true - - /micromark-extension-mdxjs-esm@3.0.0: - resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} - dependencies: - '@types/estree': 1.0.5 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.1 - micromark-util-character: 2.1.0 - micromark-util-events-to-acorn: 2.0.2 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.2 - dev: true - - /micromark-extension-mdxjs@3.0.0: - resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - micromark-extension-mdx-expression: 3.0.0 - micromark-extension-mdx-jsx: 3.0.0 - micromark-extension-mdx-md: 2.0.0 - micromark-extension-mdxjs-esm: 3.0.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-factory-destination@2.0.0: - resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-factory-label@2.0.0: - resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} - dependencies: - devlop: 1.1.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-factory-mdx-expression@2.0.1: - resolution: {integrity: sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==} - dependencies: - '@types/estree': 1.0.5 - devlop: 1.1.0 - micromark-util-character: 2.1.0 - micromark-util-events-to-acorn: 2.0.2 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.2 - dev: true - - /micromark-factory-space@2.0.0: - resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-factory-title@2.0.0: - resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} - dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-factory-whitespace@2.0.0: - resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} - dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-util-character@2.1.0: - resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} - dependencies: - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-util-chunked@2.0.0: - resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} - dependencies: - micromark-util-symbol: 2.0.0 - dev: true - - /micromark-util-classify-character@2.0.0: - resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-util-combine-extensions@2.0.0: - resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} - dependencies: - micromark-util-chunked: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-util-decode-numeric-character-reference@2.0.1: - resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} - dependencies: - micromark-util-symbol: 2.0.0 - dev: true - - /micromark-util-decode-string@2.0.0: - resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 2.1.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-symbol: 2.0.0 - dev: true - - /micromark-util-encode@2.0.0: - resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} - dev: true - - /micromark-util-events-to-acorn@2.0.2: - resolution: {integrity: sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==} - dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.5 - '@types/unist': 3.0.2 - devlop: 1.1.0 - estree-util-visit: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - vfile-message: 4.0.2 - dev: true - - /micromark-util-html-tag-name@2.0.0: - resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} - dev: true - - /micromark-util-normalize-identifier@2.0.0: - resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} - dependencies: - micromark-util-symbol: 2.0.0 - dev: true - - /micromark-util-resolve-all@2.0.0: - resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} - dependencies: - micromark-util-types: 2.0.0 - dev: true - - /micromark-util-sanitize-uri@2.0.0: - resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-encode: 2.0.0 - micromark-util-symbol: 2.0.0 - dev: true - - /micromark-util-subtokenize@2.0.1: - resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - - /micromark-util-symbol@2.0.0: - resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} - dev: true - - /micromark-util-types@2.0.0: - resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} - dev: true - - /micromark@2.11.4: - resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} - dependencies: - debug: 4.3.4 - parse-entities: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /micromark@4.0.0: - resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} - dependencies: - '@types/debug': 4.1.12 - debug: 4.3.4 - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.1 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-encode: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-subtokenize: 2.0.1 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime-db@1.33.0: - resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} - engines: {node: '>= 0.6'} - dev: true - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true - - /mime-types@2.1.18: - resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.33.0 - dev: true - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true - - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: true - - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - dev: true - - /minipass@7.1.1: - resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: true - - /mixme@0.5.10: - resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} - engines: {node: '>= 8.0.0'} - dev: true - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - dev: true - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /node-dir@0.1.17: - resolution: {integrity: sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==} - engines: {node: '>= 0.10.5'} - dependencies: - minimatch: 3.1.2 - dev: true - - /node-fetch-native@1.6.4: - resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} - dev: true - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true - - /nopt@7.2.1: - resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - abbrev: 2.0.0 - dev: true - - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - - /nypm@0.3.8: - resolution: {integrity: sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==} - engines: {node: ^14.16.0 || >=16.10.0} - hasBin: true - dependencies: - citty: 0.1.6 - consola: 3.2.3 - execa: 8.0.1 - pathe: 1.1.2 - ufo: 1.5.3 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - dev: true - - /object.hasown@1.1.4: - resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /ohash@1.1.3: - resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} - dev: true - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - - /on-headers@1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - - /optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - dev: true - - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /outdent@0.5.0: - resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - dev: true - - /p-filter@2.1.0: - resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} - engines: {node: '>=8'} - dependencies: - p-map: 2.1.0 - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-map@2.1.0: - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} - engines: {node: '>=6'} - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-entities@2.0.0: - resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} - dependencies: - character-entities: 1.2.4 - character-entities-legacy: 1.1.4 - character-reference-invalid: 1.1.4 - is-alphanumerical: 1.0.4 - is-decimal: 1.0.4 - is-hexadecimal: 1.0.4 - dev: true - - /parse-entities@4.0.1: - resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} - dependencies: - '@types/unist': 2.0.10 - character-entities: 2.0.2 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.0.2 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.24.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse-json@7.1.1: - resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==} - engines: {node: '>=16'} - dependencies: - '@babel/code-frame': 7.24.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 3.0.2 - lines-and-columns: 2.0.4 - type-fest: 3.13.1 - dev: true - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: true - - /path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-is-inside@1.0.2: - resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - dependencies: - lru-cache: 10.2.2 - minipass: 7.1.1 - dev: true - - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: true - - /path-to-regexp@2.2.1: - resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==} - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /path-type@5.0.0: - resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} - engines: {node: '>=12'} - dev: true - - /pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - dev: true - - /picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true - - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - dev: true - - /pkg-dir@3.0.0: - resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} - engines: {node: '>=6'} - dependencies: - find-up: 3.0.0 - dev: true - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /polished@4.3.1: - resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} - engines: {node: '>=10'} - dependencies: - '@babel/runtime': 7.24.5 - dev: true - - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: true - - /postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - dependencies: - lilconfig: 3.1.1 - yaml: 2.4.2 - dev: true - - /postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - dev: true - - /preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} - engines: {node: '>=10'} - dependencies: - find-up: 5.0.0 - find-yarn-workspace-root2: 1.2.16 - path-exists: 4.0.0 - which-pm: 2.0.0 - dev: true - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-plugin-packagejson@2.5.0(prettier@3.2.5): - resolution: {integrity: sha512-6XkH3rpin5QEQodBSVNg+rBo4r91g/1mCaRwS1YGdQJZ6jwqrg2UchBsIG9tpS1yK1kNBvOt84OILsX8uHzBGg==} - peerDependencies: - prettier: '>= 1.16.0' - peerDependenciesMeta: - prettier: - optional: true - dependencies: - prettier: 3.2.5 - sort-package-json: 2.10.0 - synckit: 0.9.0 - dev: true - - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /proc-log@4.2.0: - resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: true - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: true - - /pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - dev: true - - /punycode@1.4.1: - resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} - dev: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true - - /range-parser@1.2.0: - resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==} - engines: {node: '>= 0.6'} - dev: true - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: true - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true - - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - dev: true - - /react-colorful@5.6.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: true - - /react-docgen-typescript@2.2.2(typescript@5.5.4): - resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==} - peerDependencies: - typescript: '>= 4.3.x' - dependencies: - typescript: 5.5.4 - dev: true - - /react-docgen@7.0.3: - resolution: {integrity: sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==} - engines: {node: '>=16.14.0'} - dependencies: - '@babel/core': 7.24.5 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.5 - '@types/doctrine': 0.0.9 - '@types/resolve': 1.20.6 - doctrine: 3.0.0 - resolve: 1.22.8 - strip-indent: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /react-dom@18.3.1(react@18.3.1): - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - - /react-element-to-jsx-string@15.0.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==} - peerDependencies: - react: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 - react-dom: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 - dependencies: - '@base2/pretty-print-object': 1.0.1 - is-plain-object: 5.0.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 18.1.0 - dev: true - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /react-is@18.1.0: - resolution: {integrity: sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==} - dev: true - - /react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} - engines: {node: '>=0.10.0'} - dev: true - - /react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - - /read-package-json-fast@3.0.2: - resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - json-parse-even-better-errors: 3.0.2 - npm-normalize-package-bin: 3.0.1 - dev: true - - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /read-yaml-file@1.1.0: - resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} - engines: {node: '>=6'} - dependencies: - graceful-fs: 4.2.11 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /recast@0.23.7: - resolution: {integrity: sha512-MpQlLZVpqbbxYcqEjwpRWo88sGvjOYoXptySz710RuddNMHx+wPkoNX6YyLZJlXAh5VZr1qmPrTwcTuFMh0Lag==} - engines: {node: '>= 4'} - dependencies: - ast-types: 0.16.1 - esprima: 4.0.1 - source-map: 0.6.1 - tiny-invariant: 1.3.3 - tslib: 2.6.2 - dev: true - - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - dev: true - - /reflect.getprototypeof@1.0.6: - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - globalthis: 1.0.4 - which-builtin-type: 1.1.3 - dev: true - - /regenerate-unicode-properties@10.1.1: - resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} - engines: {node: '>=4'} - dependencies: - regenerate: 1.4.2 - dev: true - - /regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true - - /regenerator-transform@0.15.2: - resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - dependencies: - '@babel/runtime': 7.24.5 - dev: true - - /regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - hasBin: true - dev: true - - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - dev: true - - /regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} - engines: {node: '>=4'} - dependencies: - '@babel/regjsgen': 0.8.0 - regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.1 - regjsparser: 0.9.1 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 - dev: true - - /registry-auth-token@3.3.2: - resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} - dependencies: - rc: 1.2.8 - safe-buffer: 5.2.1 - dev: true - - /registry-url@3.1.0: - resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} - engines: {node: '>=0.10.0'} - dependencies: - rc: 1.2.8 - dev: true - - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /rehype-external-links@3.0.0: - resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==} - dependencies: - '@types/hast': 3.0.4 - '@ungap/structured-clone': 1.2.0 - hast-util-is-element: 3.0.0 - is-absolute-url: 4.0.1 - space-separated-tokens: 2.0.2 - unist-util-visit: 5.0.0 - dev: true - - /rehype-slug@6.0.0: - resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} - dependencies: - '@types/hast': 3.0.4 - github-slugger: 2.0.0 - hast-util-heading-rank: 3.0.0 - hast-util-to-string: 3.0.0 - unist-util-visit: 5.0.0 - dev: true - - /remark-mdx@3.0.1: - resolution: {integrity: sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==} - dependencies: - mdast-util-mdx: 3.0.0 - micromark-extension-mdxjs: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /remark-parse@11.0.0: - resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.0 - micromark-util-types: 2.0.0 - unified: 11.0.4 - transitivePeerDependencies: - - supports-color - dev: true - - /remark-stringify@11.0.0: - resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - dependencies: - '@types/mdast': 4.0.4 - mdast-util-to-markdown: 2.1.0 - unified: 11.0.4 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - - /require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true - - /requireindex@1.2.0: - resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} - engines: {node: '>=0.10.5'} - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@2.6.3: - resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 - fsevents: 2.3.3 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /sade@1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} - dependencies: - mri: 1.2.0 - dev: true - - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true - - /scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - dependencies: - loose-envify: 1.4.0 - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /serve-handler@6.1.5: - resolution: {integrity: sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==} - dependencies: - bytes: 3.0.0 - content-disposition: 0.5.2 - fast-url-parser: 1.1.3 - mime-types: 2.1.18 - minimatch: 3.1.2 - path-is-inside: 1.0.2 - path-to-regexp: 2.2.1 - range-parser: 1.2.0 - dev: true - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: true - - /serve@14.2.3: - resolution: {integrity: sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==} - engines: {node: '>= 14'} - hasBin: true - dependencies: - '@zeit/schemas': 2.36.0 - ajv: 8.12.0 - arg: 5.0.2 - boxen: 7.0.0 - chalk: 5.0.1 - chalk-template: 0.4.0 - clipboardy: 3.0.0 - compression: 1.7.4 - is-port-reachable: 4.0.0 - serve-handler: 6.1.5 - update-check: 1.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - dev: true - - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - - /shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - dependencies: - kind-of: 6.0.3 - dev: true - - /shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - dependencies: - shebang-regex: 1.0.0 - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /slash@5.1.0: - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} - engines: {node: '>=14.16'} - dev: true - - /smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true - dependencies: - array.prototype.flat: 1.3.2 - breakword: 1.0.6 - grapheme-splitter: 1.0.4 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 15.4.1 - dev: true - - /sort-object-keys@1.1.3: - resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - dev: true - - /sort-package-json@2.10.0: - resolution: {integrity: sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==} - hasBin: true - dependencies: - detect-indent: 7.0.1 - detect-newline: 4.0.1 - get-stdin: 9.0.0 - git-hooks-list: 3.1.0 - globby: 13.2.2 - is-plain-obj: 4.1.0 - semver: 7.6.2 - sort-object-keys: 1.1.3 - dev: true - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map@0.8.0-beta.0: - resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} - engines: {node: '>= 8'} - dependencies: - whatwg-url: 7.1.0 - dev: true - - /space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - dev: true - - /spawndamnit@2.0.0: - resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} - dependencies: - cross-spawn: 5.1.0 - signal-exit: 3.0.7 - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - dev: true - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - - /storybook@8.2.6: - resolution: {integrity: sha512-8j30wDxQmkcqI0fWcSYFsUCjErsY1yTWbTW+yjbwM8DyW18Cud6CwbFRCxjFsH+2M0CjP6Pqs/m1PGI0vcQscQ==} - hasBin: true - dependencies: - '@babel/core': 7.24.5 - '@babel/types': 7.24.5 - '@storybook/codemod': 8.2.6 - '@storybook/core': 8.2.6 - '@types/semver': 7.5.8 - '@yarnpkg/fslib': 2.10.3 - '@yarnpkg/libzip': 2.3.0 - chalk: 4.1.2 - commander: 6.2.1 - cross-spawn: 7.0.3 - detect-indent: 6.1.0 - envinfo: 7.13.0 - execa: 5.1.1 - fd-package-json: 1.2.0 - find-up: 5.0.0 - fs-extra: 11.2.0 - giget: 1.2.3 - globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.24.5) - leven: 3.1.0 - ora: 5.4.1 - prettier: 3.2.5 - prompts: 2.4.2 - semver: 7.6.2 - strip-json-comments: 3.1.1 - tempy: 3.1.0 - tiny-invariant: 1.3.3 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - '@babel/preset-env' - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} - dependencies: - mixme: 0.5.10 - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string-width@6.1.0: - resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} - engines: {node: '>=16'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 10.3.0 - strip-ansi: 7.1.0 - dev: true - - /string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.2 - side-channel: 1.0.6 - dev: true - - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /stringify-entities@4.0.4: - resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-indent@4.0.0: - resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} - engines: {node: '>=12'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - commander: 4.1.1 - glob: 10.3.15 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color@9.4.0: - resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} - engines: {node: '>=12'} - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /synckit@0.9.0: - resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.2 - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: true - - /telejson@7.2.0: - resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} - dependencies: - memoizerific: 1.11.3 - dev: true - - /temp-dir@3.0.0: - resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} - engines: {node: '>=14.16'} - dev: true - - /temp@0.8.4: - resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==} - engines: {node: '>=6.0.0'} - dependencies: - rimraf: 2.6.3 - dev: true - - /tempy@3.1.0: - resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} - engines: {node: '>=14.16'} - dependencies: - is-stream: 3.0.0 - temp-dir: 3.0.0 - type-fest: 2.19.0 - unique-string: 3.0.0 - dev: true - - /term-size@2.2.1: - resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} - engines: {node: '>=8'} - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: true - - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: true - - /tiny-invariant@1.3.3: - resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - dev: true - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true - - /tr46@1.0.1: - resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - dependencies: - punycode: 2.3.1 - dev: true - - /tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - dev: true - - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true - - /trough@2.2.0: - resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - dev: true - - /ts-api-utils@1.3.0(typescript@5.5.4): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /ts-dedent@2.2.0: - resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} - engines: {node: '>=6.10'} - dev: true - - /ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: true - - /tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tsconfig-paths@4.2.0: - resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} - engines: {node: '>=6'} - dependencies: - json5: 2.2.3 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true - - /tsup@8.0.2(typescript@5.5.4): - resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==} - engines: {node: '>=18'} - hasBin: true - peerDependencies: - '@microsoft/api-extractor': ^7.36.0 - '@swc/core': ^1 - postcss: ^8.4.12 - typescript: '>=4.5.0' - peerDependenciesMeta: - '@microsoft/api-extractor': - optional: true - '@swc/core': - optional: true - postcss: - optional: true - typescript: - optional: true - dependencies: - bundle-require: 4.1.0(esbuild@0.19.12) - cac: 6.7.14 - chokidar: 3.6.0 - debug: 4.3.4 - esbuild: 0.19.12 - execa: 5.1.1 - globby: 11.1.0 - joycon: 3.1.1 - postcss-load-config: 4.0.2 - resolve-from: 5.0.0 - rollup: 4.17.2 - source-map: 0.8.0-beta.0 - sucrase: 3.35.0 - tree-kill: 1.2.2 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - ts-node - dev: true - - /tsutils@3.21.0(typescript@5.5.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.4 - dev: true - - /tty-table@4.2.3: - resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} - engines: {node: '>=8.0.0'} - hasBin: true - dependencies: - chalk: 4.1.2 - csv: 5.5.3 - kleur: 4.1.5 - smartwrap: 2.0.2 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 17.7.2 - dev: true - - /turbo-darwin-64@2.0.3: - resolution: {integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: {integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: {integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: {integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: {integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: {integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: {integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - dev: true - - /type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - dev: true - - /type-fest@3.13.1: - resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} - engines: {node: '>=14.16'} - dev: true - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: true - - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 - dev: true - - /typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - dev: true - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /ufo@1.5.3: - resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} - dev: true - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} - engines: {node: '>=4'} - dev: true - - /unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 - unicode-property-aliases-ecmascript: 2.1.0 - dev: true - - /unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} - engines: {node: '>=4'} - dev: true - - /unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} - engines: {node: '>=4'} - dev: true - - /unicorn-magic@0.1.0: - resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} - engines: {node: '>=18'} - dev: true - - /unified-engine@11.2.1: - resolution: {integrity: sha512-xBAdZ8UY2X4R9Hm6X6kMne4Nz0PlpOc1oE6DPeqJnewr5Imkb8uT5Eyvy1h7xNekPL3PSWh3ZJyNrMW6jnNQBg==} - dependencies: - '@types/concat-stream': 2.0.3 - '@types/debug': 4.1.12 - '@types/is-empty': 1.2.3 - '@types/node': 20.12.12 - '@types/unist': 3.0.2 - concat-stream: 2.0.0 - debug: 4.3.4 - extend: 3.0.2 - glob: 10.3.15 - ignore: 5.3.1 - is-empty: 1.2.0 - is-plain-obj: 4.1.0 - load-plugin: 6.0.3 - parse-json: 7.1.1 - trough: 2.2.0 - unist-util-inspect: 8.0.0 - vfile: 6.0.1 - vfile-message: 4.0.2 - vfile-reporter: 8.1.1 - vfile-statistics: 3.0.0 - yaml: 2.4.2 - transitivePeerDependencies: - - supports-color - dev: true - - /unified@11.0.4: - resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} - dependencies: - '@types/unist': 3.0.2 - bail: 2.0.2 - devlop: 1.1.0 - extend: 3.0.2 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 6.0.1 - dev: true - - /unique-string@3.0.0: - resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} - engines: {node: '>=12'} - dependencies: - crypto-random-string: 4.0.0 - dev: true - - /unist-util-inspect@8.0.0: - resolution: {integrity: sha512-/3Wn/wU6/H6UEo4FoYUeo8KUePN8ERiZpQYFWYoihOsr1DoDuv80PeB0hobVZyYSvALa2e556bG1A1/AbwU4yg==} - dependencies: - '@types/unist': 3.0.2 - dev: true - - /unist-util-is@6.0.0: - resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} - dependencies: - '@types/unist': 3.0.2 - dev: true - - /unist-util-position-from-estree@2.0.0: - resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} - dependencies: - '@types/unist': 3.0.2 - dev: true - - /unist-util-remove-position@5.0.0: - resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} - dependencies: - '@types/unist': 3.0.2 - unist-util-visit: 5.0.0 - dev: true - - /unist-util-stringify-position@2.0.3: - resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} - dependencies: - '@types/unist': 2.0.10 - dev: true - - /unist-util-stringify-position@4.0.0: - resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - dependencies: - '@types/unist': 3.0.2 - dev: true - - /unist-util-visit-parents@6.0.1: - resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} - dependencies: - '@types/unist': 3.0.2 - unist-util-is: 6.0.0 - dev: true - - /unist-util-visit@5.0.0: - resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - dependencies: - '@types/unist': 3.0.2 - unist-util-is: 6.0.0 - unist-util-visit-parents: 6.0.1 - dev: true - - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: true - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: true - - /unplugin@1.10.1: - resolution: {integrity: sha512-d6Mhq8RJeGA8UfKCu54Um4lFA0eSaRa3XxdAJg8tIdxbu1ubW0hBCZUL7yI2uGyYCRndvbK8FLHzqy2XKfeMsg==} - engines: {node: '>=14.0.0'} - dependencies: - acorn: 8.11.3 - chokidar: 3.6.0 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.6.1 - dev: true - - /update-browserslist-db@1.0.16(browserslist@4.23.0): - resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.1 - dev: true - - /update-check@1.5.4: - resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} - dependencies: - registry-auth-token: 3.3.2 - registry-url: 3.1.0 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - dependencies: - inherits: 2.0.4 - is-arguments: 1.1.1 - is-generator-function: 1.0.10 - is-typed-array: 1.1.13 - which-typed-array: 1.1.15 - dev: true - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: true - - /uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} - hasBin: true - dev: true - - /uvu@0.5.6: - resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} - engines: {node: '>=8'} - hasBin: true - dependencies: - dequal: 2.0.3 - diff: 5.2.0 - kleur: 4.1.5 - sade: 1.8.1 - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: true - - /vfile-message@4.0.2: - resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} - dependencies: - '@types/unist': 3.0.2 - unist-util-stringify-position: 4.0.0 - dev: true - - /vfile-reporter@8.1.1: - resolution: {integrity: sha512-qxRZcnFSQt6pWKn3PAk81yLK2rO2i7CDXpy8v8ZquiEOMLSnPw6BMSi9Y1sUCwGGl7a9b3CJT1CKpnRF7pp66g==} - dependencies: - '@types/supports-color': 8.1.3 - string-width: 6.1.0 - supports-color: 9.4.0 - unist-util-stringify-position: 4.0.0 - vfile: 6.0.1 - vfile-message: 4.0.2 - vfile-sort: 4.0.0 - vfile-statistics: 3.0.0 - dev: true - - /vfile-sort@4.0.0: - resolution: {integrity: sha512-lffPI1JrbHDTToJwcq0rl6rBmkjQmMuXkAxsZPRS9DXbaJQvc642eCg6EGxcX2i1L+esbuhq+2l9tBll5v8AeQ==} - dependencies: - vfile: 6.0.1 - vfile-message: 4.0.2 - dev: true - - /vfile-statistics@3.0.0: - resolution: {integrity: sha512-/qlwqwWBWFOmpXujL/20P+Iuydil0rZZNglR+VNm6J0gpLHwuVM5s7g2TfVoswbXjZ4HuIhLMySEyIw5i7/D8w==} - dependencies: - vfile: 6.0.1 - vfile-message: 4.0.2 - dev: true - - /vfile@6.0.1: - resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} - dependencies: - '@types/unist': 3.0.2 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.2 - dev: true - - /vite@5.2.11: - resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.20.2 - postcss: 8.4.38 - rollup: 4.17.2 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /walk-up-path@3.0.1: - resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} - dev: true - - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - - /webidl-conversions@4.0.2: - resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - dev: true - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack-virtual-modules@0.6.1: - resolution: {integrity: sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==} - dev: true - - /whatwg-url@7.1.0: - resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - dev: true - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.2 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.3 - dev: true - - /which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - dev: true - - /which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} - dependencies: - load-yaml-file: 0.2.0 - path-exists: 4.0.0 - dev: true - - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.2 - dev: true - - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /widest-line@4.0.1: - resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - dev: true - - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /write-file-atomic@2.4.3: - resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} - dependencies: - graceful-fs: 4.2.11 - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - dev: true - - /ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yaml@2.4.2: - resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==} - engines: {node: '>= 14'} - hasBin: true - dev: true - - /yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - dev: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 18.1.3 - dev: true - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: true diff --git a/examples/kitchen-sink/README.md b/examples/kitchen-sink/README.md deleted file mode 100644 index a64ed9673729e..0000000000000 --- a/examples/kitchen-sink/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Turborepo kitchen sink starter - -This Turborepo starter is maintained by the Turborepo core team. - -This example also shows how to use [Workspace Configurations](https://turbo.build/repo/docs/core-concepts/monorepos/configuring-workspaces). - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e kitchen-sink -``` - -## What's inside? - -This Turborepo includes the following packages and apps: - -### Apps and Packages - -- `api`: an [Express](https://expressjs.com/) server -- `storefront`: a [Next.js](https://nextjs.org/) app -- `admin`: a [Vite](https://vitejs.dev/) single page app -- `blog`: a [Remix](https://remix.run/) blog -- `@repo/eslint-config`: ESLint configurations used throughout the monorepo -- `@repo/jest-presets`: Jest configurations -- `@repo/logger`: isomorphic logger (a small wrapper around console.log) -- `@repo/ui`: a dummy React UI library (which contains `` and `` components) -- `@repo/typescript-config`: tsconfig.json's used throughout the monorepo - -Each package and app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Jest](https://jestjs.io) test runner for all things JavaScript -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/kitchen-sink/apps/admin/src/app/index.tsx b/examples/kitchen-sink/apps/admin/Source/app/index.tsx similarity index 100% rename from examples/kitchen-sink/apps/admin/src/app/index.tsx rename to examples/kitchen-sink/apps/admin/Source/app/index.tsx diff --git a/examples/kitchen-sink/apps/admin/src/app/styles.css b/examples/kitchen-sink/apps/admin/Source/app/styles.css similarity index 100% rename from examples/kitchen-sink/apps/admin/src/app/styles.css rename to examples/kitchen-sink/apps/admin/Source/app/styles.css diff --git a/examples/kitchen-sink/apps/admin/src/index.css b/examples/kitchen-sink/apps/admin/Source/index.css similarity index 100% rename from examples/kitchen-sink/apps/admin/src/index.css rename to examples/kitchen-sink/apps/admin/Source/index.css diff --git a/examples/kitchen-sink/apps/admin/src/main.tsx b/examples/kitchen-sink/apps/admin/Source/main.tsx similarity index 100% rename from examples/kitchen-sink/apps/admin/src/main.tsx rename to examples/kitchen-sink/apps/admin/Source/main.tsx diff --git a/examples/kitchen-sink/apps/admin/eslint.config.js b/examples/kitchen-sink/apps/admin/eslint.config.js deleted file mode 100644 index 2b11f486e4bc0..0000000000000 --- a/examples/kitchen-sink/apps/admin/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -import { config } from "@repo/eslint-config"; - -export default config; diff --git a/examples/kitchen-sink/apps/admin/package.json b/examples/kitchen-sink/apps/admin/package.json index 67e49b4c4f4ad..692ec792e460e 100644 --- a/examples/kitchen-sink/apps/admin/package.json +++ b/examples/kitchen-sink/apps/admin/package.json @@ -11,16 +11,16 @@ }, "dependencies": { "@repo/ui": "workspace:*", - "react": "^18.3.1", - "react-dom": "^18.3.1" + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/react": "^18.3.18", - "@types/react-dom": "^18.3.5", - "@vitejs/plugin-react": "^4.3.4", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", + "@vitejs/plugin-react": "4.3.4", "typescript": "5.7.3", - "vite": "^5.4.14" + "vite": "6.1.0" } } diff --git a/examples/kitchen-sink/apps/api/src/index.ts b/examples/kitchen-sink/apps/api/Source/index.ts similarity index 100% rename from examples/kitchen-sink/apps/api/src/index.ts rename to examples/kitchen-sink/apps/api/Source/index.ts diff --git a/examples/kitchen-sink/apps/api/src/server.ts b/examples/kitchen-sink/apps/api/Source/server.ts similarity index 100% rename from examples/kitchen-sink/apps/api/src/server.ts rename to examples/kitchen-sink/apps/api/Source/server.ts diff --git a/examples/kitchen-sink/apps/api/eslint.config.js b/examples/kitchen-sink/apps/api/eslint.config.js deleted file mode 100644 index f6870b374423e..0000000000000 --- a/examples/kitchen-sink/apps/api/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { config } from "@repo/eslint-config"; - -/** @type {import("eslint").Linter.Config} */ -export default config; diff --git a/examples/kitchen-sink/apps/api/package.json b/examples/kitchen-sink/apps/api/package.json index 89e8448a26cc0..fb76e182c8909 100644 --- a/examples/kitchen-sink/apps/api/package.json +++ b/examples/kitchen-sink/apps/api/package.json @@ -16,25 +16,25 @@ }, "dependencies": { "@repo/logger": "workspace:*", - "body-parser": "^1.20.3", - "cors": "^2.8.5", - "express": "^5.0.1", - "morgan": "^1.10.0" + "body-parser": "1.20.3", + "cors": "2.8.5", + "express": "5.0.1", + "morgan": "1.10.0" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@repo/eslint-config": "workspace:*", "@repo/jest-presets": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/body-parser": "^1.19.5", - "@types/cors": "^2.8.17", - "@types/express": "4.17.17", - "@types/morgan": "^1.9.9", - "@types/node": "^22.12.0", - "@types/supertest": "^6.0.2", - "jest": "^29.7.0", - "supertest": "^7.0.0", - "tsup": "^8.3.6", + "@types/body-parser": "1.19.5", + "@types/cors": "2.8.17", + "@types/express": "5.0.0", + "@types/morgan": "1.9.9", + "@types/node": "22.13.1", + "@types/supertest": "6.0.2", + "jest": "29.7.0", + "supertest": "7.0.0", + "tsup": "8.3.6", "typescript": "5.7.3" } } diff --git a/examples/kitchen-sink/apps/api/src/__tests__/server.test.ts b/examples/kitchen-sink/apps/api/src/__tests__/server.test.ts deleted file mode 100644 index 8d0bb06b95ea2..0000000000000 --- a/examples/kitchen-sink/apps/api/src/__tests__/server.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import supertest from "supertest"; -import { describe, it, expect } from "@jest/globals"; -import { createServer } from "../server"; - -describe("Server", () => { - it("health check returns 200", async () => { - await supertest(createServer()) - .get("/status") - .expect(200) - .then((res) => { - expect(res.ok).toBe(true); - }); - }); - - it("message endpoint says hello", async () => { - await supertest(createServer()) - .get("/message/jared") - .expect(200) - .then((res) => { - expect(res.body).toEqual({ message: "hello jared" }); - }); - }); -}); diff --git a/examples/kitchen-sink/apps/blog/README.md b/examples/kitchen-sink/apps/blog/README.md deleted file mode 100644 index 78390d20d360a..0000000000000 --- a/examples/kitchen-sink/apps/blog/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Remix - -This directory is a brief example of a [Remix](https://remix.run/docs) site that can be deployed to Vercel with zero configuration. - -To get started, run the Remix cli with this template - -```sh -npx create-remix@latest --template vercel/vercel/examples/remix -``` - -## Deploy Your Own - -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/remix&template=remix) - -_Live Example: https://remix-run-template.vercel.app_ - -You can also deploy using the [Vercel CLI](https://vercel.com/docs/cli): - -```sh -npm i -g vercel -vercel -``` - -## Development - -To run your Remix app locally, make sure your project's local dependencies are installed: - -```sh -npm install -``` - -Afterwards, start the Remix development server like so: - -```sh -npm run dev -``` - -Open up [http://localhost:5173](http://localhost:5173) and you should be ready to go! diff --git a/examples/kitchen-sink/apps/blog/app/entry.client.tsx b/examples/kitchen-sink/apps/blog/app/entry.client.tsx new file mode 100644 index 0000000000000..60f6010725877 --- /dev/null +++ b/examples/kitchen-sink/apps/blog/app/entry.client.tsx @@ -0,0 +1,22 @@ +import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; + +function hydrate(): void { + startTransition(() => { + hydrateRoot( + document, + + + + ); + }); +} + +if (typeof requestIdleCallback === "function") { + requestIdleCallback(hydrate); +} else { + // Safari doesn't support requestIdleCallback + // https://caniuse.com/requestidlecallback + setTimeout(hydrate, 1); +} diff --git a/examples/kitchen-sink/apps/blog/app/entry.server.tsx b/examples/kitchen-sink/apps/blog/app/entry.server.tsx new file mode 100644 index 0000000000000..496e0da2be80d --- /dev/null +++ b/examples/kitchen-sink/apps/blog/app/entry.server.tsx @@ -0,0 +1,18 @@ +import handleRequest from "@vercel/remix-entry-server"; +import { RemixServer } from "@remix-run/react"; +import type { EntryContext } from "@remix-run/server-runtime"; + +export default function entry( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +): Promise { + const remixServer = ; + return handleRequest( + request, + responseStatusCode, + responseHeaders, + remixServer + ); +} diff --git a/examples/kitchen-sink/apps/blog/eslint.config.js b/examples/kitchen-sink/apps/blog/eslint.config.js deleted file mode 100644 index c1c3cfb3a1ee6..0000000000000 --- a/examples/kitchen-sink/apps/blog/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { config } from "@repo/eslint-config/react"; - -/** @type {import("eslint").Linter.Config} */ -export default config; diff --git a/examples/kitchen-sink/apps/blog/package.json b/examples/kitchen-sink/apps/blog/package.json index 5f0d97969529d..ec16ceffb7e95 100644 --- a/examples/kitchen-sink/apps/blog/package.json +++ b/examples/kitchen-sink/apps/blog/package.json @@ -11,28 +11,28 @@ "lint": "eslint app/ --max-warnings 0" }, "dependencies": { - "@remix-run/node": "^2.15.2", - "@remix-run/react": "^2.15.2", - "@remix-run/server-runtime": "^2.15.2", + "@remix-run/node": "2.15.3", + "@remix-run/react": "2.15.3", + "@remix-run/server-runtime": "2.15.3", "@repo/ui": "workspace:*", - "@vercel/analytics": "^1.4.1", - "@vercel/remix": "2.15.2", - "isbot": "^5.1.21", - "react": "^18.3.1", - "react-dom": "^18.3.1" + "@vercel/analytics": "1.5.0", + "@vercel/remix": "2.15.3", + "isbot": "5.1.22", + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { - "@remix-run/dev": "^2.15.2", - "@types/react": "^18.3.18", - "@types/react-dom": "^18.3.5", - "@typescript-eslint/eslint-plugin": "^8.22.0", - "@typescript-eslint/parser": "^8.22.0", - "@vercel/remix": "2.15.2", - "autoprefixer": "^10.4.20", - "eslint": "^9.19.0", + "@remix-run/dev": "2.15.3", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", + "@typescript-eslint/eslint-plugin": "8.24.0", + "@typescript-eslint/parser": "8.24.0", + "@vercel/remix": "2.15.3", + "autoprefixer": "10.4.20", + "eslint": "9.20.1", "typescript": "5.7.3", - "vite": "^5.4.14", - "vite-tsconfig-paths": "4.2.1" + "vite": "6.1.0", + "vite-tsconfig-paths": "5.1.4" }, "engines": { "node": ">=18.0.0" diff --git a/examples/kitchen-sink/apps/blog/remix.config.js b/examples/kitchen-sink/apps/blog/remix.config.js new file mode 100644 index 0000000000000..5bdbfd787d040 --- /dev/null +++ b/examples/kitchen-sink/apps/blog/remix.config.js @@ -0,0 +1,9 @@ +/** @type {import('@remix-run/dev').AppConfig} */ +module.exports = { + ignoredRouteFiles: ["**/.*"], + serverModuleFormat: "cjs", + // appDirectory: "app", + // assetsBuildDirectory: "public/build", + // serverBuildPath: "build/index.js", + // publicPath: "/build/", +}; diff --git a/examples/kitchen-sink/apps/blog/remix.env.d.ts b/examples/kitchen-sink/apps/blog/remix.env.d.ts new file mode 100644 index 0000000000000..5c938f1076f9e --- /dev/null +++ b/examples/kitchen-sink/apps/blog/remix.env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples/kitchen-sink/apps/blog/server.js b/examples/kitchen-sink/apps/blog/server.js new file mode 100644 index 0000000000000..3b02013aaa192 --- /dev/null +++ b/examples/kitchen-sink/apps/blog/server.js @@ -0,0 +1,4 @@ +import { createRequestHandler } from "@remix-run/server-runtime"; +import * as build from "@remix-run/dev/server-build"; + +export default createRequestHandler({ build, mode: process.env.NODE_ENV }); diff --git a/examples/kitchen-sink/apps/blog/turbo.json b/examples/kitchen-sink/apps/blog/turbo.json new file mode 100644 index 0000000000000..e96fb0bbd4b4e --- /dev/null +++ b/examples/kitchen-sink/apps/blog/turbo.json @@ -0,0 +1,13 @@ +{ + "extends": [ + "//" + ], + "tasks": { + "build": { + "outputs": [ + "build/**", + "public/build/**" + ] + } + } +} diff --git a/examples/kitchen-sink/apps/storefront/src/app/layout.tsx b/examples/kitchen-sink/apps/storefront/Source/app/layout.tsx similarity index 100% rename from examples/kitchen-sink/apps/storefront/src/app/layout.tsx rename to examples/kitchen-sink/apps/storefront/Source/app/layout.tsx diff --git a/examples/kitchen-sink/apps/storefront/src/app/page.tsx b/examples/kitchen-sink/apps/storefront/Source/app/page.tsx similarity index 100% rename from examples/kitchen-sink/apps/storefront/src/app/page.tsx rename to examples/kitchen-sink/apps/storefront/Source/app/page.tsx diff --git a/examples/kitchen-sink/apps/storefront/src/app/styles.css b/examples/kitchen-sink/apps/storefront/Source/app/styles.css similarity index 100% rename from examples/kitchen-sink/apps/storefront/src/app/styles.css rename to examples/kitchen-sink/apps/storefront/Source/app/styles.css diff --git a/examples/kitchen-sink/apps/storefront/eslint.config.js b/examples/kitchen-sink/apps/storefront/eslint.config.js deleted file mode 100644 index 75bc0458922e6..0000000000000 --- a/examples/kitchen-sink/apps/storefront/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { config } from "@repo/eslint-config/next"; - -/** @type {import("eslint").Linter.Config} */ -export default config; diff --git a/examples/kitchen-sink/apps/storefront/package.json b/examples/kitchen-sink/apps/storefront/package.json index 812b853355158..f4dac64914475 100644 --- a/examples/kitchen-sink/apps/storefront/package.json +++ b/examples/kitchen-sink/apps/storefront/package.json @@ -13,17 +13,17 @@ "dependencies": { "@repo/logger": "workspace:*", "@repo/ui": "workspace:*", - "next": "^15.1.6", - "react": "^18.3.1", - "react-dom": "^18.3.1" + "next": "15.1.7", + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { - "@next/eslint-plugin-next": "^15.1.6", + "@next/eslint-plugin-next": "15.1.7", "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/node": "^22.12.0", - "@types/react": "^18.3.18", - "@types/react-dom": "^18.3.5", + "@types/node": "22.13.1", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", "typescript": "5.7.3" } } diff --git a/examples/kitchen-sink/package.json b/examples/kitchen-sink/package.json index dfa148b502850..664470612300e 100644 --- a/examples/kitchen-sink/package.json +++ b/examples/kitchen-sink/package.json @@ -1,21 +1,12 @@ { - "name": "kitchen-sink", - "private": true, - "scripts": { - "build": "turbo run build", - "clean": "turbo run clean", - "dev": "turbo run dev", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "lint": "turbo run lint", - "test": "turbo run test", - "typecheck": "turbo run typecheck" - }, - "devDependencies": { - "prettier": "^3.4.2", - "turbo": "^2.3.4" - }, - "packageManager": "pnpm@8.15.6", - "engines": { - "node": ">=18" - } + "name": "kitchen-sink", + "scripts": { + "build": "turbo run build", + "clean": "turbo run clean", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/kitchen-sink/packages/config-eslint/README.md b/examples/kitchen-sink/packages/config-eslint/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/kitchen-sink/packages/config-eslint/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/kitchen-sink/packages/config-eslint/package.json b/examples/kitchen-sink/packages/config-eslint/package.json index 784c9e55bc314..0bb1609e85745 100644 --- a/examples/kitchen-sink/packages/config-eslint/package.json +++ b/examples/kitchen-sink/packages/config-eslint/package.json @@ -1,26 +1,16 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "type": "module", - "private": true, - "exports": { - ".": "./index.js", - "./next": "./next.js", - "./react": "./react.js", - "./remix": "./remix.js", - "./vite": "./vite.js" - }, - "devDependencies": { - "@eslint/js": "^9.19.0", - "@next/eslint-plugin-next": "^15.1.6", - "eslint": "^9.19.0", - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-only-warn": "^1.1.0", - "eslint-plugin-react": "^7.37.4", - "eslint-plugin-react-hooks": "^5.1.0", - "eslint-plugin-turbo": "^2.3.4", - "globals": "^15.14.0", - "typescript": "^5.7.3", - "typescript-eslint": "^8.22.0" - } + "name": "@repo/eslint-config", + "exports": { + ".": "./index.js", + "./next": "./next.js", + "./react": "./react.js", + "./remix": "./remix.js", + "./vite": "./vite.js" + }, + "dependencies": {}, + "devDependencies": { + "eslint-plugin-only-warn": "1.1.0", + "eslint-plugin-turbo": "2.4.2", + "globals": "15.15.0" + } } diff --git a/examples/kitchen-sink/packages/config-typescript/package.json b/examples/kitchen-sink/packages/config-typescript/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/kitchen-sink/packages/config-typescript/package.json +++ b/examples/kitchen-sink/packages/config-typescript/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/kitchen-sink/packages/jest-presets/browser/jest-preset.js b/examples/kitchen-sink/packages/jest-presets/browser/jest-preset.js new file mode 100644 index 0000000000000..3173ffd6fbac0 --- /dev/null +++ b/examples/kitchen-sink/packages/jest-presets/browser/jest-preset.js @@ -0,0 +1,14 @@ +module.exports = { + roots: [""], + testEnvironment: "jsdom", + transform: { + "^.+\\.tsx?$": "ts-jest", + }, + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: [ + "/test/__fixtures__", + "/node_modules", + "/dist", + ], + preset: "ts-jest", +}; diff --git a/examples/kitchen-sink/packages/jest-presets/node/jest-preset.js b/examples/kitchen-sink/packages/jest-presets/node/jest-preset.js new file mode 100644 index 0000000000000..b6c259304707f --- /dev/null +++ b/examples/kitchen-sink/packages/jest-presets/node/jest-preset.js @@ -0,0 +1,13 @@ +module.exports = { + roots: [""], + transform: { + "^.+\\.tsx?$": "ts-jest", + }, + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: [ + "/test/__fixtures__", + "/node_modules", + "/dist", + ], + preset: "ts-jest", +}; diff --git a/examples/kitchen-sink/packages/jest-presets/package.json b/examples/kitchen-sink/packages/jest-presets/package.json index e6567cc7dcd1b..664c08c224f0e 100644 --- a/examples/kitchen-sink/packages/jest-presets/package.json +++ b/examples/kitchen-sink/packages/jest-presets/package.json @@ -1,17 +1,11 @@ { - "name": "@repo/jest-presets", - "version": "0.0.0", - "private": true, - "license": "MIT", - "files": [ - "browser/jest-preset.ts", - "node/jest-preset.ts" - ], - "dependencies": { - "jest": "^29.7.0", - "ts-jest": "^29.2.5" - }, - "devDependencies": { - "jest-environment-jsdom": "^29.7.0" - } + "name": "@repo/jest-presets", + "files": [ + "browser/jest-preset.ts", + "node/jest-preset.ts" + ], + "dependencies": {}, + "devDependencies": { + "jest-environment-jsdom": "29.7.0" + } } diff --git a/examples/kitchen-sink/packages/logger/src/index.ts b/examples/kitchen-sink/packages/logger/Source/index.ts similarity index 100% rename from examples/kitchen-sink/packages/logger/src/index.ts rename to examples/kitchen-sink/packages/logger/Source/index.ts diff --git a/examples/kitchen-sink/packages/logger/eslint.config.js b/examples/kitchen-sink/packages/logger/eslint.config.js deleted file mode 100644 index f6870b374423e..0000000000000 --- a/examples/kitchen-sink/packages/logger/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { config } from "@repo/eslint-config"; - -/** @type {import("eslint").Linter.Config} */ -export default config; diff --git a/examples/kitchen-sink/packages/logger/package.json b/examples/kitchen-sink/packages/logger/package.json index 2a324462bb51e..dc81b7f353cb7 100644 --- a/examples/kitchen-sink/packages/logger/package.json +++ b/examples/kitchen-sink/packages/logger/package.json @@ -19,14 +19,14 @@ "preset": "@repo/jest-presets/node" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@repo/eslint-config": "workspace:*", "@repo/jest-presets": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/node": "^22.12.0", - "eslint": "^9.19.0", - "jest": "^29.7.0", - "tsup": "^8.3.6", + "@types/node": "22.13.1", + "eslint": "9.20.1", + "jest": "29.7.0", + "tsup": "8.3.6", "typescript": "5.7.3" } } diff --git a/examples/kitchen-sink/packages/logger/src/__tests__/log.test.ts b/examples/kitchen-sink/packages/logger/src/__tests__/log.test.ts deleted file mode 100644 index 55fd698fa28a9..0000000000000 --- a/examples/kitchen-sink/packages/logger/src/__tests__/log.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { describe, it, expect, jest } from "@jest/globals"; -import { log } from ".."; - -jest.spyOn(global.console, "log"); - -describe("@repo/logger", () => { - it("prints a message", () => { - log("hello"); - // eslint-disable-next-line no-console -- testing console - expect(console.log).toBeCalledWith("LOGGER: ", "hello"); - }); -}); diff --git a/examples/kitchen-sink/packages/ui/src/counter-button/index.test.tsx b/examples/kitchen-sink/packages/ui/Source/counter-button/index.test.tsx similarity index 100% rename from examples/kitchen-sink/packages/ui/src/counter-button/index.test.tsx rename to examples/kitchen-sink/packages/ui/Source/counter-button/index.test.tsx diff --git a/examples/kitchen-sink/packages/ui/src/counter-button/index.tsx b/examples/kitchen-sink/packages/ui/Source/counter-button/index.tsx similarity index 100% rename from examples/kitchen-sink/packages/ui/src/counter-button/index.tsx rename to examples/kitchen-sink/packages/ui/Source/counter-button/index.tsx diff --git a/examples/kitchen-sink/packages/ui/src/link/index.test.tsx b/examples/kitchen-sink/packages/ui/Source/link/index.test.tsx similarity index 100% rename from examples/kitchen-sink/packages/ui/src/link/index.test.tsx rename to examples/kitchen-sink/packages/ui/Source/link/index.test.tsx diff --git a/examples/kitchen-sink/packages/ui/src/link/index.tsx b/examples/kitchen-sink/packages/ui/Source/link/index.tsx similarity index 100% rename from examples/kitchen-sink/packages/ui/src/link/index.tsx rename to examples/kitchen-sink/packages/ui/Source/link/index.tsx diff --git a/examples/kitchen-sink/packages/ui/package.json b/examples/kitchen-sink/packages/ui/package.json index 52ff4c19c2321..d494d57fcc36c 100644 --- a/examples/kitchen-sink/packages/ui/package.json +++ b/examples/kitchen-sink/packages/ui/package.json @@ -30,17 +30,17 @@ "preset": "@repo/jest-presets/browser" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@repo/eslint-config": "workspace:*", "@repo/jest-presets": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/node": "^22.12.0", - "@types/react": "^18.3.18", - "@types/react-dom": "^18.3.5", - "jest": "^29.7.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "tsup": "^8.3.6", + "@types/node": "22.13.1", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", + "jest": "29.7.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "tsup": "8.3.6", "typescript": "5.7.3" } } diff --git a/examples/kitchen-sink/pnpm-lock.yaml b/examples/kitchen-sink/pnpm-lock.yaml deleted file mode 100644 index d5b631c2c2807..0000000000000 --- a/examples/kitchen-sink/pnpm-lock.yaml +++ /dev/null @@ -1,9124 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - prettier: - specifier: ^3.4.2 - version: 3.4.2 - turbo: - specifier: ^2.3.4 - version: 2.3.4 - - apps/admin: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - react: - specifier: ^18.3.1 - version: 18.3.1 - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/config-eslint - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/config-typescript - '@types/react': - specifier: ^18.3.18 - version: 18.3.18 - '@types/react-dom': - specifier: ^18.3.5 - version: 18.3.5(@types/react@18.3.18) - '@vitejs/plugin-react': - specifier: ^4.3.4 - version: 4.3.4(vite@5.4.14) - typescript: - specifier: 5.7.3 - version: 5.7.3 - vite: - specifier: ^5.4.14 - version: 5.4.14 - - apps/api: - dependencies: - '@repo/logger': - specifier: workspace:* - version: link:../../packages/logger - body-parser: - specifier: ^1.20.3 - version: 1.20.3 - cors: - specifier: ^2.8.5 - version: 2.8.5 - express: - specifier: ^5.0.1 - version: 5.0.1 - morgan: - specifier: ^1.10.0 - version: 1.10.0 - devDependencies: - '@jest/globals': - specifier: ^29.7.0 - version: 29.7.0 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/config-eslint - '@repo/jest-presets': - specifier: workspace:* - version: link:../../packages/jest-presets - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/config-typescript - '@types/body-parser': - specifier: ^1.19.5 - version: 1.19.5 - '@types/cors': - specifier: ^2.8.17 - version: 2.8.17 - '@types/express': - specifier: 4.17.17 - version: 4.17.17 - '@types/morgan': - specifier: ^1.9.9 - version: 1.9.9 - '@types/node': - specifier: ^22.12.0 - version: 22.12.0 - '@types/supertest': - specifier: ^6.0.2 - version: 6.0.2 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@22.12.0) - supertest: - specifier: ^7.0.0 - version: 7.0.0 - tsup: - specifier: ^8.3.6 - version: 8.3.6(typescript@5.7.3) - typescript: - specifier: 5.7.3 - version: 5.7.3 - - apps/blog: - dependencies: - '@remix-run/node': - specifier: ^2.15.2 - version: 2.15.2(typescript@5.7.3) - '@remix-run/react': - specifier: ^2.15.2 - version: 2.15.2(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3) - '@remix-run/server-runtime': - specifier: ^2.15.2 - version: 2.15.2(typescript@5.7.3) - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - '@vercel/analytics': - specifier: ^1.4.1 - version: 1.4.1(@remix-run/react@2.15.2)(react@18.3.1) - '@vercel/remix': - specifier: 2.15.2 - version: 2.15.2(@remix-run/dev@2.15.2)(@remix-run/node@2.15.2)(@remix-run/server-runtime@2.15.2)(react-dom@18.3.1)(react@18.3.1) - isbot: - specifier: ^5.1.21 - version: 5.1.22 - react: - specifier: ^18.3.1 - version: 18.3.1 - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - devDependencies: - '@remix-run/dev': - specifier: ^2.15.2 - version: 2.15.2(@remix-run/react@2.15.2)(typescript@5.7.3)(vite@5.4.14) - '@types/react': - specifier: ^18.3.18 - version: 18.3.18 - '@types/react-dom': - specifier: ^18.3.5 - version: 18.3.5(@types/react@18.3.18) - '@typescript-eslint/eslint-plugin': - specifier: ^8.22.0 - version: 8.22.0(@typescript-eslint/parser@8.22.0)(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/parser': - specifier: ^8.22.0 - version: 8.22.0(eslint@9.19.0)(typescript@5.7.3) - autoprefixer: - specifier: ^10.4.20 - version: 10.4.20(postcss@8.5.1) - eslint: - specifier: ^9.19.0 - version: 9.19.0 - typescript: - specifier: 5.7.3 - version: 5.7.3 - vite: - specifier: ^5.4.14 - version: 5.4.14 - vite-tsconfig-paths: - specifier: 4.2.1 - version: 4.2.1(typescript@5.7.3)(vite@5.4.14) - - apps/storefront: - dependencies: - '@repo/logger': - specifier: workspace:* - version: link:../../packages/logger - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^15.1.6 - version: 15.1.6(react-dom@18.3.1)(react@18.3.1) - react: - specifier: ^18.3.1 - version: 18.3.1 - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - devDependencies: - '@next/eslint-plugin-next': - specifier: ^15.1.6 - version: 15.1.6 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/config-eslint - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/config-typescript - '@types/node': - specifier: ^22.12.0 - version: 22.12.0 - '@types/react': - specifier: ^18.3.18 - version: 18.3.18 - '@types/react-dom': - specifier: ^18.3.5 - version: 18.3.5(@types/react@18.3.18) - typescript: - specifier: 5.7.3 - version: 5.7.3 - - packages/config-eslint: - devDependencies: - '@eslint/js': - specifier: ^9.19.0 - version: 9.19.0 - '@next/eslint-plugin-next': - specifier: ^15.1.6 - version: 15.1.6 - eslint: - specifier: ^9.19.0 - version: 9.19.0 - eslint-config-prettier: - specifier: ^10.0.1 - version: 10.0.1(eslint@9.19.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - eslint-plugin-react: - specifier: ^7.37.4 - version: 7.37.4(eslint@9.19.0) - eslint-plugin-react-hooks: - specifier: ^5.1.0 - version: 5.1.0(eslint@9.19.0) - eslint-plugin-turbo: - specifier: ^2.3.4 - version: 2.3.4(eslint@9.19.0)(turbo@2.3.4) - globals: - specifier: ^15.14.0 - version: 15.14.0 - typescript: - specifier: ^5.7.3 - version: 5.7.3 - typescript-eslint: - specifier: ^8.22.0 - version: 8.22.0(eslint@9.19.0)(typescript@5.7.3) - - packages/config-typescript: {} - - packages/jest-presets: - dependencies: - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@22.12.0) - ts-jest: - specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.26.7)(jest@29.7.0)(typescript@5.7.3) - devDependencies: - jest-environment-jsdom: - specifier: ^29.7.0 - version: 29.7.0 - - packages/logger: - devDependencies: - '@jest/globals': - specifier: ^29.7.0 - version: 29.7.0 - '@repo/eslint-config': - specifier: workspace:* - version: link:../config-eslint - '@repo/jest-presets': - specifier: workspace:* - version: link:../jest-presets - '@repo/typescript-config': - specifier: workspace:* - version: link:../config-typescript - '@types/node': - specifier: ^22.12.0 - version: 22.12.0 - eslint: - specifier: ^9.19.0 - version: 9.19.0 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@22.12.0) - tsup: - specifier: ^8.3.6 - version: 8.3.6(typescript@5.7.3) - typescript: - specifier: 5.7.3 - version: 5.7.3 - - packages/ui: - devDependencies: - '@jest/globals': - specifier: ^29.7.0 - version: 29.7.0 - '@repo/eslint-config': - specifier: workspace:* - version: link:../config-eslint - '@repo/jest-presets': - specifier: workspace:* - version: link:../jest-presets - '@repo/typescript-config': - specifier: workspace:* - version: link:../config-typescript - '@types/node': - specifier: ^22.12.0 - version: 22.12.0 - '@types/react': - specifier: ^18.3.18 - version: 18.3.18 - '@types/react-dom': - specifier: ^18.3.5 - version: 18.3.5(@types/react@18.3.18) - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@22.12.0) - react: - specifier: ^18.3.1 - version: 18.3.1 - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - tsup: - specifier: ^8.3.6 - version: 8.3.6(typescript@5.7.3) - typescript: - specifier: 5.7.3 - version: 5.7.3 - -packages: - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - - /@babel/code-frame@7.26.2: - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - /@babel/compat-data@7.26.5: - resolution: {integrity: sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==} - engines: {node: '>=6.9.0'} - - /@babel/core@7.26.7: - resolution: {integrity: sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.5 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.7) - '@babel/helpers': 7.26.7 - '@babel/parser': 7.26.7 - '@babel/template': 7.25.9 - '@babel/traverse': 7.26.7 - '@babel/types': 7.26.7 - convert-source-map: 2.0.0 - debug: 4.4.0 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /@babel/generator@7.26.5: - resolution: {integrity: sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/parser': 7.26.7 - '@babel/types': 7.26.7 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.0.2 - - /@babel/helper-annotate-as-pure@7.25.9: - resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.26.7 - - /@babel/helper-compilation-targets@7.26.5: - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.26.5 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.4 - lru-cache: 5.1.1 - semver: 6.3.1 - - /@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.7): - resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-member-expression-to-functions': 7.25.9 - '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.7) - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/traverse': 7.26.7 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /@babel/helper-member-expression-to-functions@7.25.9: - resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.26.7 - '@babel/types': 7.26.7 - transitivePeerDependencies: - - supports-color - - /@babel/helper-module-imports@7.25.9: - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.26.7 - '@babel/types': 7.26.7 - transitivePeerDependencies: - - supports-color - - /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.7): - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.7 - transitivePeerDependencies: - - supports-color - - /@babel/helper-optimise-call-expression@7.25.9: - resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.26.7 - - /@babel/helper-plugin-utils@7.26.5: - resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} - engines: {node: '>=6.9.0'} - - /@babel/helper-replace-supers@7.26.5(@babel/core@7.26.7): - resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-member-expression-to-functions': 7.25.9 - '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/traverse': 7.26.7 - transitivePeerDependencies: - - supports-color - - /@babel/helper-skip-transparent-expression-wrappers@7.25.9: - resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.26.7 - '@babel/types': 7.26.7 - transitivePeerDependencies: - - supports-color - - /@babel/helper-string-parser@7.25.9: - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-identifier@7.25.9: - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-option@7.25.9: - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - - /@babel/helpers@7.26.7: - resolution: {integrity: sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.7 - - /@babel/parser@7.26.7: - resolution: {integrity: sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.26.7 - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.7): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.7): - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.7): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.7): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.26.7): - resolution: {integrity: sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.7): - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.7): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.7): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.7): - resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.7): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.7): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.7): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.7): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.7): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.7): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.7): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.7): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.7): - resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - - /@babel/plugin-transform-modules-commonjs@7.26.3(@babel/core@7.26.7): - resolution: {integrity: sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.7) - '@babel/helper-plugin-utils': 7.26.5 - transitivePeerDependencies: - - supports-color - - /@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.7): - resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - dev: true - - /@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.7): - resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - dev: true - - /@babel/plugin-transform-typescript@7.26.7(@babel/core@7.26.7): - resolution: {integrity: sha512-5cJurntg+AT+cgelGP9Bt788DKiAw9gIMSMU2NJrLAilnj0m8WZWUNZPSLOmadYsujHutpgElO+50foX+ib/Wg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.7) - '@babel/helper-plugin-utils': 7.26.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.7) - transitivePeerDependencies: - - supports-color - - /@babel/preset-typescript@7.26.0(@babel/core@7.26.7): - resolution: {integrity: sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-plugin-utils': 7.26.5 - '@babel/helper-validator-option': 7.25.9 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.7) - '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.7) - '@babel/plugin-transform-typescript': 7.26.7(@babel/core@7.26.7) - transitivePeerDependencies: - - supports-color - - /@babel/runtime@7.26.7: - resolution: {integrity: sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - - /@babel/template@7.25.9: - resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.7 - '@babel/types': 7.26.7 - - /@babel/traverse@7.26.7: - resolution: {integrity: sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.5 - '@babel/parser': 7.26.7 - '@babel/template': 7.25.9 - '@babel/types': 7.26.7 - debug: 4.4.0 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - /@babel/types@7.26.7: - resolution: {integrity: sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - - /@bcoe/v8-coverage@0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - - /@emnapi/runtime@1.3.1: - resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} - requiresBuild: true - dependencies: - tslib: 2.8.1 - dev: false - optional: true - - /@emotion/hash@0.9.2: - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} - - /@esbuild/aix-ppc64@0.21.5: - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - optional: true - - /@esbuild/aix-ppc64@0.24.2: - resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.17.6: - resolution: {integrity: sha512-YnYSCceN/dUzUr5kdtUzB+wZprCafuD89Hs0Aqv9QSdwhYQybhXTaSTcrl6X/aWThn1a/j0eEpUBGOE7269REg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-arm64@0.21.5: - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-arm64@0.24.2: - resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.17.6: - resolution: {integrity: sha512-bSC9YVUjADDy1gae8RrioINU6e1lCkg3VGVwm0QQ2E1CWcC4gnMce9+B6RpxuSsrsXsk1yojn7sp1fnG8erE2g==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-arm@0.21.5: - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-arm@0.24.2: - resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.17.6: - resolution: {integrity: sha512-MVcYcgSO7pfu/x34uX9u2QIZHmXAB7dEiLQC5bBl5Ryqtpj9lT2sg3gNDEsrPEmimSJW2FXIaxqSQ501YLDsZQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-x64@0.21.5: - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-x64@0.24.2: - resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.17.6: - resolution: {integrity: sha512-bsDRvlbKMQMt6Wl08nHtFz++yoZHsyTOxnjfB2Q95gato+Yi4WnRl13oC2/PJJA9yLCoRv9gqT/EYX0/zDsyMA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-arm64@0.21.5: - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-arm64@0.24.2: - resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.17.6: - resolution: {integrity: sha512-xh2A5oPrYRfMFz74QXIQTQo8uA+hYzGWJFoeTE8EvoZGHb+idyV4ATaukaUvnnxJiauhs/fPx3vYhU4wiGfosg==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-x64@0.21.5: - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-x64@0.24.2: - resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.17.6: - resolution: {integrity: sha512-EnUwjRc1inT4ccZh4pB3v1cIhohE2S4YXlt1OvI7sw/+pD+dIE4smwekZlEPIwY6PhU6oDWwITrQQm5S2/iZgg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/freebsd-arm64@0.21.5: - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/freebsd-arm64@0.24.2: - resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.17.6: - resolution: {integrity: sha512-Uh3HLWGzH6FwpviUcLMKPCbZUAFzv67Wj5MTwK6jn89b576SR2IbEp+tqUHTr8DIl0iDmBAf51MVaP7pw6PY5Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/freebsd-x64@0.21.5: - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/freebsd-x64@0.24.2: - resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.17.6: - resolution: {integrity: sha512-bUR58IFOMJX523aDVozswnlp5yry7+0cRLCXDsxnUeQYJik1DukMY+apBsLOZJblpH+K7ox7YrKrHmJoWqVR9w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-arm64@0.21.5: - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-arm64@0.24.2: - resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.17.6: - resolution: {integrity: sha512-7YdGiurNt7lqO0Bf/U9/arrPWPqdPqcV6JCZda4LZgEn+PTQ5SMEI4MGR52Bfn3+d6bNEGcWFzlIxiQdS48YUw==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-arm@0.21.5: - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-arm@0.24.2: - resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.17.6: - resolution: {integrity: sha512-ujp8uoQCM9FRcbDfkqECoARsLnLfCUhKARTP56TFPog8ie9JG83D5GVKjQ6yVrEVdMie1djH86fm98eY3quQkQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-ia32@0.21.5: - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-ia32@0.24.2: - resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.17.6: - resolution: {integrity: sha512-y2NX1+X/Nt+izj9bLoiaYB9YXT/LoaQFYvCkVD77G/4F+/yuVXYCWz4SE9yr5CBMbOxOfBcy/xFL4LlOeNlzYQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-loong64@0.21.5: - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-loong64@0.24.2: - resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.17.6: - resolution: {integrity: sha512-09AXKB1HDOzXD+j3FdXCiL/MWmZP0Ex9eR8DLMBVcHorrWJxWmY8Nms2Nm41iRM64WVx7bA/JVHMv081iP2kUA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-mips64el@0.21.5: - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-mips64el@0.24.2: - resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.17.6: - resolution: {integrity: sha512-AmLhMzkM8JuqTIOhxnX4ubh0XWJIznEynRnZAVdA2mMKE6FAfwT2TWKTwdqMG+qEaeyDPtfNoZRpJbD4ZBv0Tg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-ppc64@0.21.5: - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-ppc64@0.24.2: - resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.17.6: - resolution: {integrity: sha512-Y4Ri62PfavhLQhFbqucysHOmRamlTVK10zPWlqjNbj2XMea+BOs4w6ASKwQwAiqf9ZqcY9Ab7NOU4wIgpxwoSQ==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-riscv64@0.21.5: - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-riscv64@0.24.2: - resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.17.6: - resolution: {integrity: sha512-SPUiz4fDbnNEm3JSdUW8pBJ/vkop3M1YwZAVwvdwlFLoJwKEZ9L98l3tzeyMzq27CyepDQ3Qgoba44StgbiN5Q==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-s390x@0.21.5: - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-s390x@0.24.2: - resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.17.6: - resolution: {integrity: sha512-a3yHLmOodHrzuNgdpB7peFGPx1iJ2x6m+uDvhP2CKdr2CwOaqEFMeSqYAHU7hG+RjCq8r2NFujcd/YsEsFgTGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-x64@0.21.5: - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-x64@0.24.2: - resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-arm64@0.24.2: - resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.17.6: - resolution: {integrity: sha512-EanJqcU/4uZIBreTrnbnre2DXgXSa+Gjap7ifRfllpmyAU7YMvaXmljdArptTHmjrkkKm9BK6GH5D5Yo+p6y5A==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - - /@esbuild/netbsd-x64@0.21.5: - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - - /@esbuild/netbsd-x64@0.24.2: - resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-arm64@0.24.2: - resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.17.6: - resolution: {integrity: sha512-xaxeSunhQRsTNGFanoOkkLtnmMn5QbA0qBhNet/XLVsc+OVkpIWPHcr3zTW2gxVU5YOHFbIHR9ODuaUdNza2Vw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - - /@esbuild/openbsd-x64@0.21.5: - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - - /@esbuild/openbsd-x64@0.24.2: - resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.17.6: - resolution: {integrity: sha512-gnMnMPg5pfMkZvhHee21KbKdc6W3GR8/JuE0Da1kjwpK6oiFU3nqfHuVPgUX2rsOx9N2SadSQTIYV1CIjYG+xw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - - /@esbuild/sunos-x64@0.21.5: - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - - /@esbuild/sunos-x64@0.24.2: - resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.17.6: - resolution: {integrity: sha512-G95n7vP1UnGJPsVdKXllAJPtqjMvFYbN20e8RK8LVLhlTiSOH1sd7+Gt7rm70xiG+I5tM58nYgwWrLs6I1jHqg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-arm64@0.21.5: - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-arm64@0.24.2: - resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.17.6: - resolution: {integrity: sha512-96yEFzLhq5bv9jJo5JhTs1gI+1cKQ83cUpyxHuGqXVwQtY5Eq54ZEsKs8veKtiKwlrNimtckHEkj4mRh4pPjsg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-ia32@0.21.5: - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-ia32@0.24.2: - resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.17.6: - resolution: {integrity: sha512-n6d8MOyUrNp6G4VSpRcgjs5xj4A91svJSaiwLIDWVWEsZtpN5FA9NlBbZHDmAJc2e8e6SF4tkBD3HAvPF+7igA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-x64@0.21.5: - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-x64@0.24.2: - resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.1(eslint@9.19.0): - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 9.19.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.12.1: - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/config-array@0.19.1: - resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@eslint/object-schema': 2.1.5 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/core@0.10.0: - resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@types/json-schema': 7.0.15 - dev: true - - /@eslint/eslintrc@3.2.0: - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@9.19.0: - resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@eslint/object-schema@2.1.5: - resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@eslint/plugin-kit@0.2.5: - resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@eslint/core': 0.10.0 - levn: 0.4.1 - dev: true - - /@humanfs/core@0.19.1: - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - dev: true - - /@humanfs/node@0.16.6: - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/retry@0.3.1: - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - dev: true - - /@humanwhocodes/retry@0.4.1: - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} - engines: {node: '>=18.18'} - dev: true - - /@img/sharp-darwin-arm64@0.33.5: - resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.4 - dev: false - optional: true - - /@img/sharp-darwin-x64@0.33.5: - resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [darwin] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.0.4 - dev: false - optional: true - - /@img/sharp-libvips-darwin-arm64@1.0.4: - resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-libvips-darwin-x64@1.0.4: - resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-libvips-linux-arm64@1.0.4: - resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-libvips-linux-arm@1.0.5: - resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-libvips-linux-s390x@1.0.4: - resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-libvips-linux-x64@1.0.4: - resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-libvips-linuxmusl-arm64@1.0.4: - resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-libvips-linuxmusl-x64@1.0.4: - resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-linux-arm64@0.33.5: - resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.0.4 - dev: false - optional: true - - /@img/sharp-linux-arm@0.33.5: - resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm] - os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.0.5 - dev: false - optional: true - - /@img/sharp-linux-s390x@0.33.5: - resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [s390x] - os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.0.4 - dev: false - optional: true - - /@img/sharp-linux-x64@0.33.5: - resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.0.4 - dev: false - optional: true - - /@img/sharp-linuxmusl-arm64@0.33.5: - resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - dev: false - optional: true - - /@img/sharp-linuxmusl-x64@0.33.5: - resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - dev: false - optional: true - - /@img/sharp-wasm32@0.33.5: - resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [wasm32] - requiresBuild: true - dependencies: - '@emnapi/runtime': 1.3.1 - dev: false - optional: true - - /@img/sharp-win32-ia32@0.33.5: - resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@img/sharp-win32-x64@0.33.5: - resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - - /@istanbuljs/load-nyc-config@1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - - /@istanbuljs/schema@0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - - /@jest/console@29.7.0: - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - - /@jest/core@29.7.0: - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.12.0) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - /@jest/environment@29.7.0: - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - jest-mock: 29.7.0 - - /@jest/expect-utils@29.7.0: - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - - /@jest/expect@29.7.0: - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - /@jest/fake-timers@29.7.0: - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.12.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - /@jest/globals@29.7.0: - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - /@jest/reporters@29.7.0: - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.12.0 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - - /@jest/schemas@29.6.3: - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - - /@jest/source-map@29.6.3: - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - /@jest/test-result@29.7.0: - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - - /@jest/test-sequencer@29.7.0: - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - - /@jest/transform@29.7.0: - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.26.7 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - - /@jest/types@29.6.3: - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 22.12.0 - '@types/yargs': 17.0.33 - chalk: 4.1.2 - - /@jridgewell/gen-mapping@0.3.8: - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - /@jridgewell/sourcemap-codec@1.5.0: - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - /@jspm/core@2.0.1: - resolution: {integrity: sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==} - - /@mdx-js/mdx@2.3.0: - resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/mdx': 2.0.13 - estree-util-build-jsx: 2.2.2 - estree-util-is-identifier-name: 2.1.0 - estree-util-to-js: 1.2.0 - estree-walker: 3.0.3 - hast-util-to-estree: 2.3.3 - markdown-extensions: 1.1.1 - periscopic: 3.1.0 - remark-mdx: 2.3.0 - remark-parse: 10.0.2 - remark-rehype: 10.1.0 - unified: 10.1.2 - unist-util-position-from-estree: 1.1.2 - unist-util-stringify-position: 3.0.3 - unist-util-visit: 4.1.2 - vfile: 5.3.7 - transitivePeerDependencies: - - supports-color - - /@next/env@15.1.6: - resolution: {integrity: sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==} - dev: false - - /@next/eslint-plugin-next@15.1.6: - resolution: {integrity: sha512-+slMxhTgILUntZDGNgsKEYHUvpn72WP1YTlkmEhS51vnVd7S9jEEy0n9YAMcI21vUG4akTw9voWH02lrClt/yw==} - dependencies: - fast-glob: 3.3.1 - dev: true - - /@next/swc-darwin-arm64@15.1.6: - resolution: {integrity: sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64@15.1.6: - resolution: {integrity: sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu@15.1.6: - resolution: {integrity: sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl@15.1.6: - resolution: {integrity: sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu@15.1.6: - resolution: {integrity: sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl@15.1.6: - resolution: {integrity: sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc@15.1.6: - resolution: {integrity: sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc@15.1.6: - resolution: {integrity: sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.18.0 - - /@npmcli/fs@3.1.1: - resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.7.0 - - /@npmcli/git@4.1.0: - resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - '@npmcli/promise-spawn': 6.0.2 - lru-cache: 7.18.3 - npm-pick-manifest: 8.0.2 - proc-log: 3.0.0 - promise-inflight: 1.0.1 - promise-retry: 2.0.1 - semver: 7.7.0 - which: 3.0.1 - transitivePeerDependencies: - - bluebird - - /@npmcli/package-json@4.0.1: - resolution: {integrity: sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - '@npmcli/git': 4.1.0 - glob: 10.4.5 - hosted-git-info: 6.1.3 - json-parse-even-better-errors: 3.0.2 - normalize-package-data: 5.0.0 - proc-log: 3.0.0 - semver: 7.7.0 - transitivePeerDependencies: - - bluebird - - /@npmcli/promise-spawn@6.0.2: - resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - which: 3.0.1 - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - optional: true - - /@remix-run/dev@2.15.2(@remix-run/react@2.15.2)(typescript@5.7.3)(vite@5.4.14): - resolution: {integrity: sha512-o8lix8t4GBhtXjo/G1IzwtHVW5GRMs7amtFtBHiR1bhSyK7VyX5qGtTDmJyny5QDv83pxaLOCiE0dUng2BCoyQ==} - engines: {node: '>=18.0.0'} - hasBin: true - peerDependencies: - '@remix-run/react': ^2.15.2 - '@remix-run/serve': ^2.15.2 - typescript: ^5.1.0 - vite: ^5.1.0 - wrangler: ^3.28.2 - peerDependenciesMeta: - '@remix-run/serve': - optional: true - typescript: - optional: true - vite: - optional: true - wrangler: - optional: true - dependencies: - '@babel/core': 7.26.7 - '@babel/generator': 7.26.5 - '@babel/parser': 7.26.7 - '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.26.7) - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.7) - '@babel/preset-typescript': 7.26.0(@babel/core@7.26.7) - '@babel/traverse': 7.26.7 - '@babel/types': 7.26.7 - '@mdx-js/mdx': 2.3.0 - '@npmcli/package-json': 4.0.1 - '@remix-run/node': 2.15.2(typescript@5.7.3) - '@remix-run/react': 2.15.2(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3) - '@remix-run/router': 1.21.0 - '@remix-run/server-runtime': 2.15.2(typescript@5.7.3) - '@types/mdx': 2.0.13 - '@vanilla-extract/integration': 6.5.0 - arg: 5.0.2 - cacache: 17.1.4 - chalk: 4.1.2 - chokidar: 3.6.0 - cross-spawn: 7.0.6 - dotenv: 16.4.7 - es-module-lexer: 1.6.0 - esbuild: 0.17.6 - esbuild-plugins-node-modules-polyfill: 1.6.8(esbuild@0.17.6) - execa: 5.1.1 - exit-hook: 2.2.1 - express: 4.21.2 - fs-extra: 10.1.0 - get-port: 5.1.1 - gunzip-maybe: 1.4.2 - jsesc: 3.0.2 - json5: 2.2.3 - lodash: 4.17.21 - lodash.debounce: 4.0.8 - minimatch: 9.0.5 - ora: 5.4.1 - picocolors: 1.1.1 - picomatch: 2.3.1 - pidtree: 0.6.0 - postcss: 8.5.1 - postcss-discard-duplicates: 5.1.0(postcss@8.5.1) - postcss-load-config: 4.0.2(postcss@8.5.1) - postcss-modules: 6.0.1(postcss@8.5.1) - prettier: 2.8.8 - pretty-ms: 7.0.1 - react-refresh: 0.14.2 - remark-frontmatter: 4.0.1 - remark-mdx-frontmatter: 1.1.1 - semver: 7.7.0 - set-cookie-parser: 2.7.1 - tar-fs: 2.1.2 - tsconfig-paths: 4.2.0 - typescript: 5.7.3 - valibot: 0.41.0(typescript@5.7.3) - vite: 5.4.14 - vite-node: 1.6.0 - ws: 7.5.10 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - bluebird - - bufferutil - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - ts-node - - utf-8-validate - - /@remix-run/node@2.15.2(typescript@5.7.3): - resolution: {integrity: sha512-NS/h5uxje7DYCNgcKqKAiUhf0r2HVnoYUBWLyIIMmCUP1ddWurBP6xTPcWzGhEvV/EvguniYi1wJZ5+X8sonWw==} - engines: {node: '>=18.0.0'} - peerDependencies: - typescript: ^5.1.0 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@remix-run/server-runtime': 2.15.2(typescript@5.7.3) - '@remix-run/web-fetch': 4.4.2 - '@web3-storage/multipart-parser': 1.0.0 - cookie-signature: 1.2.2 - source-map-support: 0.5.21 - stream-slice: 0.1.2 - typescript: 5.7.3 - undici: 6.21.1 - - /@remix-run/react@2.15.2(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3): - resolution: {integrity: sha512-NAAMsSgoC/sdOgovUewwRCE/RUm3F+MBxxZKfwu3POCNeHaplY5qGkH/y8PUXvdN1EBG7Z0Ko43dyzCfcEy5PA==} - engines: {node: '>=18.0.0'} - peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 - typescript: ^5.1.0 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@remix-run/router': 1.21.0 - '@remix-run/server-runtime': 2.15.2(typescript@5.7.3) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-router: 6.28.1(react@18.3.1) - react-router-dom: 6.28.1(react-dom@18.3.1)(react@18.3.1) - turbo-stream: 2.4.0 - typescript: 5.7.3 - - /@remix-run/router@1.21.0: - resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==} - engines: {node: '>=14.0.0'} - - /@remix-run/server-runtime@2.15.2(typescript@5.7.3): - resolution: {integrity: sha512-OqiPcvEnnU88B8b1LIWHHkQ3Tz2GDAmQ1RihFNQsbrFKpDsQLkw0lJlnfgKA/uHd0CEEacpfV7C9qqJT3V6Z2g==} - engines: {node: '>=18.0.0'} - peerDependencies: - typescript: ^5.1.0 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@remix-run/router': 1.21.0 - '@types/cookie': 0.6.0 - '@web3-storage/multipart-parser': 1.0.0 - cookie: 0.6.0 - set-cookie-parser: 2.7.1 - source-map: 0.7.4 - turbo-stream: 2.4.0 - typescript: 5.7.3 - - /@remix-run/web-blob@3.1.0: - resolution: {integrity: sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==} - dependencies: - '@remix-run/web-stream': 1.1.0 - web-encoding: 1.1.5 - - /@remix-run/web-fetch@4.4.2: - resolution: {integrity: sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==} - engines: {node: ^10.17 || >=12.3} - dependencies: - '@remix-run/web-blob': 3.1.0 - '@remix-run/web-file': 3.1.0 - '@remix-run/web-form-data': 3.1.0 - '@remix-run/web-stream': 1.1.0 - '@web3-storage/multipart-parser': 1.0.0 - abort-controller: 3.0.0 - data-uri-to-buffer: 3.0.1 - mrmime: 1.0.1 - - /@remix-run/web-file@3.1.0: - resolution: {integrity: sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==} - dependencies: - '@remix-run/web-blob': 3.1.0 - - /@remix-run/web-form-data@3.1.0: - resolution: {integrity: sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==} - dependencies: - web-encoding: 1.1.5 - - /@remix-run/web-stream@1.1.0: - resolution: {integrity: sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==} - dependencies: - web-streams-polyfill: 3.3.3 - - /@rollup/rollup-android-arm-eabi@4.32.1: - resolution: {integrity: sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - - /@rollup/rollup-android-arm64@4.32.1: - resolution: {integrity: sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - - /@rollup/rollup-darwin-arm64@4.32.1: - resolution: {integrity: sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@rollup/rollup-darwin-x64@4.32.1: - resolution: {integrity: sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@rollup/rollup-freebsd-arm64@4.32.1: - resolution: {integrity: sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - - /@rollup/rollup-freebsd-x64@4.32.1: - resolution: {integrity: sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.32.1: - resolution: {integrity: sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-arm-musleabihf@4.32.1: - resolution: {integrity: sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.32.1: - resolution: {integrity: sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.32.1: - resolution: {integrity: sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-loongarch64-gnu@4.32.1: - resolution: {integrity: sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-powerpc64le-gnu@4.32.1: - resolution: {integrity: sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.32.1: - resolution: {integrity: sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-s390x-gnu@4.32.1: - resolution: {integrity: sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.32.1: - resolution: {integrity: sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg==} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.32.1: - resolution: {integrity: sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA==} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.32.1: - resolution: {integrity: sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.32.1: - resolution: {integrity: sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.32.1: - resolution: {integrity: sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q==} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - - /@sinonjs/commons@3.0.1: - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - dependencies: - type-detect: 4.0.8 - - /@sinonjs/fake-timers@10.3.0: - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - dependencies: - '@sinonjs/commons': 3.0.1 - - /@swc/counter@0.1.3: - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - dev: false - - /@swc/helpers@0.5.15: - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - dependencies: - tslib: 2.8.1 - dev: false - - /@tootallnate/once@2.0.0: - resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} - engines: {node: '>= 10'} - dev: true - - /@ts-morph/common@0.11.1: - resolution: {integrity: sha512-7hWZS0NRpEsNV8vWJzg7FEz6V8MaLNeJOmwmghqUXTpzk16V1LLZhdo+4QvE/+zv4cVci0OviuJFnqhEfoV3+g==} - dependencies: - fast-glob: 3.3.3 - minimatch: 3.1.2 - mkdirp: 1.0.4 - path-browserify: 1.0.1 - dev: false - - /@types/acorn@4.0.6: - resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} - dependencies: - '@types/estree': 1.0.6 - - /@types/babel__core@7.20.5: - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - dependencies: - '@babel/parser': 7.26.7 - '@babel/types': 7.26.7 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 - - /@types/babel__generator@7.6.8: - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - dependencies: - '@babel/types': 7.26.7 - - /@types/babel__template@7.4.4: - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - dependencies: - '@babel/parser': 7.26.7 - '@babel/types': 7.26.7 - - /@types/babel__traverse@7.20.6: - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - dependencies: - '@babel/types': 7.26.7 - - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - dependencies: - '@types/connect': 3.4.38 - '@types/node': 22.12.0 - dev: true - - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - dependencies: - '@types/node': 22.12.0 - dev: true - - /@types/cookie@0.6.0: - resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} - - /@types/cookiejar@2.1.5: - resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} - dev: true - - /@types/cors@2.8.17: - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - dependencies: - '@types/node': 22.12.0 - dev: true - - /@types/debug@4.1.12: - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - dependencies: - '@types/ms': 2.1.0 - - /@types/estree-jsx@1.0.5: - resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - dependencies: - '@types/estree': 1.0.6 - - /@types/estree@1.0.6: - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - /@types/express-serve-static-core@4.19.6: - resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} - dependencies: - '@types/node': 22.12.0 - '@types/qs': 6.9.18 - '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 - dev: true - - /@types/express@4.17.17: - resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} - dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.6 - '@types/qs': 6.9.18 - '@types/serve-static': 1.15.7 - dev: true - - /@types/graceful-fs@4.1.9: - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - dependencies: - '@types/node': 22.12.0 - - /@types/hast@2.3.10: - resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} - dependencies: - '@types/unist': 2.0.11 - - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true - - /@types/istanbul-lib-coverage@2.0.6: - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - - /@types/istanbul-lib-report@3.0.3: - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - - /@types/istanbul-reports@3.0.4: - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - dependencies: - '@types/istanbul-lib-report': 3.0.3 - - /@types/jsdom@20.0.1: - resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} - dependencies: - '@types/node': 22.12.0 - '@types/tough-cookie': 4.0.5 - parse5: 7.2.1 - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - /@types/mdast@3.0.15: - resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} - dependencies: - '@types/unist': 2.0.11 - - /@types/mdx@2.0.13: - resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} - - /@types/methods@1.1.4: - resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} - dev: true - - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true - - /@types/morgan@1.9.9: - resolution: {integrity: sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==} - dependencies: - '@types/node': 22.12.0 - dev: true - - /@types/ms@2.1.0: - resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - - /@types/node@22.12.0: - resolution: {integrity: sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==} - dependencies: - undici-types: 6.20.0 - - /@types/prop-types@15.7.14: - resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} - dev: true - - /@types/qs@6.9.18: - resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} - dev: true - - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true - - /@types/react-dom@18.3.5(@types/react@18.3.18): - resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==} - peerDependencies: - '@types/react': ^18.0.0 - dependencies: - '@types/react': 18.3.18 - dev: true - - /@types/react@18.3.18: - resolution: {integrity: sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==} - dependencies: - '@types/prop-types': 15.7.14 - csstype: 3.1.3 - dev: true - - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - dependencies: - '@types/mime': 1.3.5 - '@types/node': 22.12.0 - dev: true - - /@types/serve-static@1.15.7: - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 22.12.0 - '@types/send': 0.17.4 - dev: true - - /@types/stack-utils@2.0.3: - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - - /@types/superagent@8.1.9: - resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} - dependencies: - '@types/cookiejar': 2.1.5 - '@types/methods': 1.1.4 - '@types/node': 22.12.0 - form-data: 4.0.1 - dev: true - - /@types/supertest@6.0.2: - resolution: {integrity: sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==} - dependencies: - '@types/methods': 1.1.4 - '@types/superagent': 8.1.9 - dev: true - - /@types/tough-cookie@4.0.5: - resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - dev: true - - /@types/unist@2.0.11: - resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - - /@types/yargs-parser@21.0.3: - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - /@types/yargs@17.0.33: - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - dependencies: - '@types/yargs-parser': 21.0.3 - - /@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0)(eslint@9.19.0)(typescript@5.7.3): - resolution: {integrity: sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/type-utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - eslint: 9.19.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3): - resolution: {integrity: sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - dependencies: - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@8.22.0: - resolution: {integrity: sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - dev: true - - /@typescript-eslint/type-utils@8.22.0(eslint@9.19.0)(typescript@5.7.3): - resolution: {integrity: sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - dependencies: - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - debug: 4.4.0 - eslint: 9.19.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@8.22.0: - resolution: {integrity: sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@typescript-eslint/typescript-estree@8.22.0(typescript@5.7.3): - resolution: {integrity: sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.8.0' - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@8.22.0(eslint@9.19.0)(typescript@5.7.3): - resolution: {integrity: sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/visitor-keys@8.22.0: - resolution: {integrity: sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@typescript-eslint/types': 8.22.0 - eslint-visitor-keys: 4.2.0 - dev: true - - /@vanilla-extract/babel-plugin-debug-ids@1.2.0: - resolution: {integrity: sha512-z5nx2QBnOhvmlmBKeRX5sPVLz437wV30u+GJL+Hzj1rGiJYVNvgIIlzUpRNjVQ0MgAgiQIqIUbqPnmMc6HmDlQ==} - dependencies: - '@babel/core': 7.26.7 - transitivePeerDependencies: - - supports-color - - /@vanilla-extract/css@1.17.0: - resolution: {integrity: sha512-W6FqVFDD+C71ZlKsuj0MxOXSvHb1tvQ9h/+79aYfi097wLsALrnnBzd0by8C///iurrpQ3S+SH74lXd7Lr9MvA==} - dependencies: - '@emotion/hash': 0.9.2 - '@vanilla-extract/private': 1.0.6 - css-what: 6.1.0 - cssesc: 3.0.0 - csstype: 3.1.3 - dedent: 1.5.3 - deep-object-diff: 1.1.9 - deepmerge: 4.3.1 - lru-cache: 10.4.3 - media-query-parser: 2.0.2 - modern-ahocorasick: 1.1.0 - picocolors: 1.1.1 - transitivePeerDependencies: - - babel-plugin-macros - - /@vanilla-extract/integration@6.5.0: - resolution: {integrity: sha512-E2YcfO8vA+vs+ua+gpvy1HRqvgWbI+MTlUpxA8FvatOvybuNcWAY0CKwQ/Gpj7rswYKtC6C7+xw33emM6/ImdQ==} - dependencies: - '@babel/core': 7.26.7 - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.7) - '@vanilla-extract/babel-plugin-debug-ids': 1.2.0 - '@vanilla-extract/css': 1.17.0 - esbuild: 0.17.6 - eval: 0.1.8 - find-up: 5.0.0 - javascript-stringify: 2.1.0 - lodash: 4.17.21 - mlly: 1.7.4 - outdent: 0.8.0 - vite: 5.4.14 - vite-node: 1.6.0 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - /@vanilla-extract/private@1.0.6: - resolution: {integrity: sha512-ytsG/JLweEjw7DBuZ/0JCN4WAQgM9erfSTdS1NQY778hFQSZ6cfCDEZZ0sgVm4k54uNz6ImKB33AYvSR//fjxw==} - - /@vercel/analytics@1.4.1(@remix-run/react@2.15.2)(react@18.3.1): - resolution: {integrity: sha512-ekpL4ReX2TH3LnrRZTUKjHHNpNy9S1I7QmS+g/RQXoSUQ8ienzosuX7T9djZ/s8zPhBx1mpHP/Rw5875N+zQIQ==} - peerDependencies: - '@remix-run/react': ^2 - '@sveltejs/kit': ^1 || ^2 - next: '>= 13' - react: ^18 || ^19 || ^19.0.0-rc - svelte: '>= 4' - vue: ^3 - vue-router: ^4 - peerDependenciesMeta: - '@remix-run/react': - optional: true - '@sveltejs/kit': - optional: true - next: - optional: true - react: - optional: true - svelte: - optional: true - vue: - optional: true - vue-router: - optional: true - dependencies: - '@remix-run/react': 2.15.2(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3) - react: 18.3.1 - dev: false - - /@vercel/remix@2.15.2(@remix-run/dev@2.15.2)(@remix-run/node@2.15.2)(@remix-run/server-runtime@2.15.2)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-JZJmuM/pZl5zLACRHzq2uOamzTOeiKRnco0o07A+hUxTKemhS1tqc2R9PdQ6Mf/8ZcXY5ZxW5tah3zjBea6D4w==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@remix-run/dev': 2.15.2 - '@remix-run/node': 2.15.2 - '@remix-run/server-runtime': 2.15.2 - react: '*' - react-dom: '*' - dependencies: - '@remix-run/dev': 2.15.2(@remix-run/react@2.15.2)(typescript@5.7.3)(vite@5.4.14) - '@remix-run/node': 2.15.2(typescript@5.7.3) - '@remix-run/server-runtime': 2.15.2(typescript@5.7.3) - '@vercel/static-config': 3.0.0 - isbot: 3.8.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - ts-morph: 12.0.0 - dev: false - - /@vercel/static-config@3.0.0: - resolution: {integrity: sha512-2qtvcBJ1bGY0dYGYh3iM7yGKkk971FujLEDXzuW5wcZsPr1GSEjO/w2iSr3qve6nDDtBImsGoDEnus5FI4+fIw==} - dependencies: - ajv: 8.6.3 - json-schema-to-ts: 1.6.4 - ts-morph: 12.0.0 - dev: false - - /@vitejs/plugin-react@4.3.4(vite@5.4.14): - resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 - dependencies: - '@babel/core': 7.26.7 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.7) - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.7) - '@types/babel__core': 7.20.5 - react-refresh: 0.14.2 - vite: 5.4.14 - transitivePeerDependencies: - - supports-color - dev: true - - /@web3-storage/multipart-parser@1.0.0: - resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==} - - /@zxing/text-encoding@0.9.0: - resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} - requiresBuild: true - optional: true - - /abab@2.0.6: - resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - deprecated: Use your platform's native atob() and btoa() methods instead - dev: true - - /abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - dependencies: - event-target-shim: 5.0.1 - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - - /accepts@2.0.0: - resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 3.0.0 - negotiator: 1.0.0 - dev: false - - /acorn-globals@7.0.1: - resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - dependencies: - acorn: 8.14.0 - acorn-walk: 8.3.4 - dev: true - - /acorn-jsx@5.3.2(acorn@8.14.0): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.14.0 - - /acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - dependencies: - acorn: 8.14.0 - dev: true - - /acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv@8.6.3: - resolution: {integrity: sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: false - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - /arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - /array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - is-array-buffer: 3.0.5 - dev: true - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - - /array-flatten@3.0.0: - resolution: {integrity: sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==} - dev: false - - /array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - is-string: 1.1.1 - dev: true - - /array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flat@1.3.3: - resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flatmap@1.3.3: - resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - dev: true - - /arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - is-array-buffer: 3.0.5 - dev: true - - /asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - dev: true - - /astring@1.9.0: - resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} - hasBin: true - - /async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - dev: true - - /async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - dev: false - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - - /autoprefixer@10.4.20(postcss@8.5.1): - resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.24.4 - caniuse-lite: 1.0.30001696 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.1.1 - postcss: 8.5.1 - postcss-value-parser: 4.2.0 - dev: true - - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - - /babel-jest@29.7.0(@babel/core@7.26.7): - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - dependencies: - '@babel/core': 7.26.7 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.26.7) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - - /babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.26.5 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - - /babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.7 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.6 - - /babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.7): - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.7 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.7) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.7) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.7) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.7) - '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.7) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.7) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.7) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.7) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.7) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.7) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.7) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.7) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.7) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.7) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.7) - - /babel-preset-jest@29.6.3(@babel/core@7.26.7): - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.7 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.7) - - /bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - /basic-auth@2.0.1: - resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} - engines: {node: '>= 0.8'} - dependencies: - safe-buffer: 5.1.2 - dev: false - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - /body-parser@1.20.3: - resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.13.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - /body-parser@2.0.2: - resolution: {integrity: sha512-SNMk0OONlQ01uk8EPeiBvTW7W4ovpL5b1O3t1sjpPgfxOQ6BqQJ6XjxinDPR79Z6HdcD5zBBwr5ssiTlgdNztQ==} - engines: {node: '>=18'} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 3.1.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.5.2 - on-finished: 2.4.1 - qs: 6.13.0 - raw-body: 3.0.0 - type-is: 1.6.18 - transitivePeerDependencies: - - supports-color - dev: false - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - - /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.1.1 - - /browserify-zlib@0.1.4: - resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} - dependencies: - pako: 0.2.9 - - /browserslist@4.24.4: - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001696 - electron-to-chromium: 1.5.88 - node-releases: 2.0.19 - update-browserslist-db: 1.1.2(browserslist@4.24.4) - - /bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - dependencies: - fast-json-stable-stringify: 2.1.0 - dev: false - - /bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - /bundle-require@5.1.0(esbuild@0.24.2): - resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - peerDependencies: - esbuild: '>=0.18' - dependencies: - esbuild: 0.24.2 - load-tsconfig: 0.2.5 - dev: true - - /busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - dev: false - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - /cacache@17.1.4: - resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - '@npmcli/fs': 3.1.1 - fs-minipass: 3.0.3 - glob: 10.4.5 - lru-cache: 7.18.3 - minipass: 7.1.2 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - p-map: 4.0.0 - ssri: 10.0.6 - tar: 6.2.1 - unique-filename: 3.0.0 - - /call-bind-apply-helpers@1.0.1: - resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - /call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - get-intrinsic: 1.2.7 - set-function-length: 1.2.2 - - /call-bound@1.0.3: - resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind-apply-helpers: 1.0.1 - get-intrinsic: 1.2.7 - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - /caniuse-lite@1.0.30001696: - resolution: {integrity: sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==} - - /ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - /char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - - /character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - - /character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - - /character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - - /character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - /chokidar@4.0.3: - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} - engines: {node: '>= 14.16.0'} - dependencies: - readdirp: 4.1.1 - dev: true - - /chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - /cjs-module-lexer@1.4.1: - resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} - - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - - /cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - - /client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - - /co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - - /code-block-writer@10.1.1: - resolution: {integrity: sha512-67ueh2IRGst/51p0n6FvPrnRjAGHY5F8xdjkgrYE7DDzpJe6qA07RYQ9VcoUeo5ATOjSOiWpSL3SWBRRbempMw==} - dev: false - - /collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - requiresBuild: true - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - dev: false - optional: true - - /color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - requiresBuild: true - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - dev: false - optional: true - - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - - /comma-separated-tokens@2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - dev: true - - /component-emitter@1.3.1: - resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - /confbox@0.1.8: - resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - - /consola@3.4.0: - resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} - engines: {node: ^14.18.0 || >=16.10.0} - dev: true - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - - /content-disposition@1.0.0: - resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - - /cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} - - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - - /cookie@0.7.1: - resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} - engines: {node: '>= 0.6'} - - /cookiejar@2.1.4: - resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - /cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - dev: false - - /create-jest@29.7.0(@types/node@22.12.0): - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.12.0) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - /cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - - /cssom@0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - dev: true - - /cssom@0.5.0: - resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - dev: true - - /cssstyle@2.3.0: - resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} - engines: {node: '>=8'} - dependencies: - cssom: 0.3.8 - dev: true - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - /data-uri-to-buffer@3.0.1: - resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} - engines: {node: '>= 6'} - - /data-urls@3.0.2: - resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} - engines: {node: '>=12'} - dependencies: - abab: 2.0.6 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - dev: true - - /data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - dev: true - - /data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - dev: true - - /data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - - /debug@3.1.0: - resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: false - - /debug@4.3.6: - resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: false - - /debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - - /decimal.js@10.5.0: - resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} - dev: true - - /decode-named-character-reference@1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - dependencies: - character-entities: 2.0.2 - - /dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /deep-object-diff@1.1.9: - resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==} - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - /detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - requiresBuild: true - dev: false - optional: true - - /detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - - /dezalgo@1.0.4: - resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} - dependencies: - asap: 2.0.6 - wrappy: 1.0.2 - dev: true - - /diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - /diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /domexception@4.0.0: - resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} - engines: {node: '>=12'} - deprecated: Use your platform's native DOMException instead - dependencies: - webidl-conversions: 7.0.0 - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /dotenv@16.4.7: - resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} - engines: {node: '>=12'} - - /dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - dependencies: - call-bind-apply-helpers: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - /duplexify@3.7.1: - resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} - dependencies: - end-of-stream: 1.4.4 - inherits: 2.0.4 - readable-stream: 2.3.8 - stream-shift: 1.0.3 - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - /ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - jake: 10.9.2 - dev: false - - /electron-to-chromium@1.5.88: - resolution: {integrity: sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw==} - - /emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - - /encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} - - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - dependencies: - once: 1.4.0 - - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: true - - /err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - - /es-abstract@1.23.9: - resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-regex: 1.2.1 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.0 - math-intrinsics: 1.1.0 - object-inspect: 1.13.3 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.1 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.18 - dev: true - - /es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - /es-iterator-helpers@1.2.1: - resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-set-tostringtag: 2.1.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - iterator.prototype: 1.1.5 - safe-array-concat: 1.1.3 - dev: true - - /es-module-lexer@1.6.0: - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - - /es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - - /es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - dev: true - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.2 - dev: true - - /es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - dev: true - - /esbuild-plugins-node-modules-polyfill@1.6.8(esbuild@0.17.6): - resolution: {integrity: sha512-bRB4qbgUDWrdY1eMk123KiaCSW9VzQ+QLZrmU7D//cCFkmksPd9mUMpmWoFK/rxjIeTfTSOpKCoGoimlvI+AWw==} - engines: {node: '>=14.0.0'} - peerDependencies: - esbuild: '>=0.14.0 <=0.24.x' - dependencies: - '@jspm/core': 2.0.1 - esbuild: 0.17.6 - local-pkg: 0.5.1 - resolve.exports: 2.0.3 - - /esbuild@0.17.6: - resolution: {integrity: sha512-TKFRp9TxrJDdRWfSsSERKEovm6v30iHnrjlcGhLBOtReE28Yp1VSBRfO3GTaOFMoxsNerx4TjrhzSuma9ha83Q==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.17.6 - '@esbuild/android-arm64': 0.17.6 - '@esbuild/android-x64': 0.17.6 - '@esbuild/darwin-arm64': 0.17.6 - '@esbuild/darwin-x64': 0.17.6 - '@esbuild/freebsd-arm64': 0.17.6 - '@esbuild/freebsd-x64': 0.17.6 - '@esbuild/linux-arm': 0.17.6 - '@esbuild/linux-arm64': 0.17.6 - '@esbuild/linux-ia32': 0.17.6 - '@esbuild/linux-loong64': 0.17.6 - '@esbuild/linux-mips64el': 0.17.6 - '@esbuild/linux-ppc64': 0.17.6 - '@esbuild/linux-riscv64': 0.17.6 - '@esbuild/linux-s390x': 0.17.6 - '@esbuild/linux-x64': 0.17.6 - '@esbuild/netbsd-x64': 0.17.6 - '@esbuild/openbsd-x64': 0.17.6 - '@esbuild/sunos-x64': 0.17.6 - '@esbuild/win32-arm64': 0.17.6 - '@esbuild/win32-ia32': 0.17.6 - '@esbuild/win32-x64': 0.17.6 - - /esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - /esbuild@0.24.2: - resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} - engines: {node: '>=18'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.24.2 - '@esbuild/android-arm': 0.24.2 - '@esbuild/android-arm64': 0.24.2 - '@esbuild/android-x64': 0.24.2 - '@esbuild/darwin-arm64': 0.24.2 - '@esbuild/darwin-x64': 0.24.2 - '@esbuild/freebsd-arm64': 0.24.2 - '@esbuild/freebsd-x64': 0.24.2 - '@esbuild/linux-arm': 0.24.2 - '@esbuild/linux-arm64': 0.24.2 - '@esbuild/linux-ia32': 0.24.2 - '@esbuild/linux-loong64': 0.24.2 - '@esbuild/linux-mips64el': 0.24.2 - '@esbuild/linux-ppc64': 0.24.2 - '@esbuild/linux-riscv64': 0.24.2 - '@esbuild/linux-s390x': 0.24.2 - '@esbuild/linux-x64': 0.24.2 - '@esbuild/netbsd-arm64': 0.24.2 - '@esbuild/netbsd-x64': 0.24.2 - '@esbuild/openbsd-arm64': 0.24.2 - '@esbuild/openbsd-x64': 0.24.2 - '@esbuild/sunos-x64': 0.24.2 - '@esbuild/win32-arm64': 0.24.2 - '@esbuild/win32-ia32': 0.24.2 - '@esbuild/win32-x64': 0.24.2 - dev: true - - /escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - /escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /eslint-config-prettier@10.0.1(eslint@9.19.0): - resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 9.19.0 - dev: true - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-react-hooks@5.1.0(eslint@9.19.0): - resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - dependencies: - eslint: 9.19.0 - dev: true - - /eslint-plugin-react@7.37.4(eslint@9.19.0): - resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.3 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.2.1 - eslint: 9.19.0 - estraverse: 5.3.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.values: 1.2.1 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.12 - string.prototype.repeat: 1.0.0 - dev: true - - /eslint-plugin-turbo@2.3.4(eslint@9.19.0)(turbo@2.3.4): - resolution: {integrity: sha512-9ncoUJkQGkC28NmlQiS17oB9mrE8XaSulRZiB5pv9vmRbYjOfUwyGhY3EIcoBRdww81igxOzXmAmvNNd6GFBPg==} - peerDependencies: - eslint: '>6.6.0' - turbo: '>2.0.0' - dependencies: - dotenv: 16.0.3 - eslint: 9.19.0 - turbo: 2.3.4 - dev: true - - /eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /eslint@9.19.0: - resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.1 - '@eslint/core': 0.10.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.19.0 - '@eslint/plugin-kit': 0.2.5 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - /esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-util-attach-comments@2.1.1: - resolution: {integrity: sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==} - dependencies: - '@types/estree': 1.0.6 - - /estree-util-build-jsx@2.2.2: - resolution: {integrity: sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==} - dependencies: - '@types/estree-jsx': 1.0.5 - estree-util-is-identifier-name: 2.1.0 - estree-walker: 3.0.3 - - /estree-util-is-identifier-name@1.1.0: - resolution: {integrity: sha512-OVJZ3fGGt9By77Ix9NhaRbzfbDV/2rx9EP7YIDJTmsZSEc5kYn2vWcNccYyahJL2uAQZK2a5Or2i0wtIKTPoRQ==} - - /estree-util-is-identifier-name@2.1.0: - resolution: {integrity: sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==} - - /estree-util-to-js@1.2.0: - resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==} - dependencies: - '@types/estree-jsx': 1.0.5 - astring: 1.9.0 - source-map: 0.7.4 - - /estree-util-value-to-estree@1.3.0: - resolution: {integrity: sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==} - engines: {node: '>=12.0.0'} - dependencies: - is-plain-obj: 3.0.0 - - /estree-util-visit@1.2.1: - resolution: {integrity: sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/unist': 2.0.11 - - /estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - dependencies: - '@types/estree': 1.0.6 - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - - /eval@0.1.8: - resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==} - engines: {node: '>= 0.8'} - dependencies: - '@types/node': 22.12.0 - require-like: 0.1.2 - - /event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - /exit-hook@2.2.1: - resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} - engines: {node: '>=6'} - - /exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - - /expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - - /express@4.21.2: - resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.3 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.7.1 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.3.1 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.3 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.12 - proxy-addr: 2.0.7 - qs: 6.13.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.19.0 - serve-static: 1.16.2 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - /express@5.0.1: - resolution: {integrity: sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==} - engines: {node: '>= 18'} - dependencies: - accepts: 2.0.0 - body-parser: 2.0.2 - content-disposition: 1.0.0 - content-type: 1.0.5 - cookie: 0.7.1 - cookie-signature: 1.2.2 - debug: 4.3.6 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 2.0.0 - fresh: 2.0.0 - http-errors: 2.0.0 - merge-descriptors: 2.0.0 - methods: 1.1.2 - mime-types: 3.0.0 - on-finished: 2.4.1 - once: 1.4.0 - parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.13.0 - range-parser: 1.2.1 - router: 2.0.0 - safe-buffer: 5.2.1 - send: 1.1.0 - serve-static: 2.1.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 2.0.0 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - /fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - dev: true - - /fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fast-safe-stringify@2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - dev: true - - /fastq@1.18.0: - resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} - dependencies: - reusify: 1.0.4 - - /fault@2.0.1: - resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} - dependencies: - format: 0.2.2 - - /fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - dependencies: - bser: 2.1.1 - - /fdir@6.4.3(picomatch@4.0.2): - resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - dependencies: - picomatch: 4.0.2 - dev: true - - /file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - dependencies: - flat-cache: 4.0.1 - dev: true - - /filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.6 - dev: false - - /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - - /finalhandler@1.3.1: - resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - /finalhandler@2.0.0: - resolution: {integrity: sha512-MX6Zo2adDViYh+GcxxB1dpO43eypOGUOL12rLCOTMQv/DfIbpSJUy4oQIIZhVZkH9e+bZWKMon0XHFEju16tkQ==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - /flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - dev: true - - /flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - dev: true - - /for-each@0.3.4: - resolution: {integrity: sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - - /foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - /form-data@4.0.1: - resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /format@0.2.2: - resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} - engines: {node: '>=0.4.x'} - - /formidable@3.5.2: - resolution: {integrity: sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==} - dependencies: - dezalgo: 1.0.4 - hexoid: 2.0.0 - once: 1.4.0 - dev: true - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: true - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - - /fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} - dev: false - - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - - /fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - - /fs-minipass@3.0.3: - resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.1.2 - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - /function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /generic-names@4.0.0: - resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} - dependencies: - loader-utils: 3.3.1 - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - /get-intrinsic@1.2.7: - resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - /get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - - /get-port@5.1.1: - resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} - engines: {node: '>=8'} - - /get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - /get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - dependencies: - foreground-child: 3.3.0 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - /globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - dev: true - - /globals@15.14.0: - resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} - engines: {node: '>=18'} - dev: true - - /globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - dev: true - - /globrex@0.1.2: - resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - dev: true - - /gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /gunzip-maybe@1.4.2: - resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==} - hasBin: true - dependencies: - browserify-zlib: 0.1.4 - is-deflate: 1.0.0 - is-gzip: 1.0.0 - peek-stream: 1.1.3 - pumpify: 1.5.1 - through2: 2.0.5 - - /has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.1 - - /has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} - dependencies: - dunder-proto: 1.0.1 - dev: true - - /has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.1.0 - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - - /hast-util-to-estree@2.3.3: - resolution: {integrity: sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==} - dependencies: - '@types/estree': 1.0.6 - '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/unist': 2.0.11 - comma-separated-tokens: 2.0.3 - estree-util-attach-comments: 2.1.1 - estree-util-is-identifier-name: 2.1.0 - hast-util-whitespace: 2.0.1 - mdast-util-mdx-expression: 1.3.2 - mdast-util-mdxjs-esm: 1.3.1 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - style-to-object: 0.4.4 - unist-util-position: 4.0.4 - zwitch: 2.0.4 - transitivePeerDependencies: - - supports-color - - /hast-util-whitespace@2.0.1: - resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} - - /hexoid@2.0.0: - resolution: {integrity: sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==} - engines: {node: '>=8'} - dev: true - - /hosted-git-info@6.1.3: - resolution: {integrity: sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - lru-cache: 7.18.3 - - /html-encoding-sniffer@3.0.0: - resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} - engines: {node: '>=12'} - dependencies: - whatwg-encoding: 2.0.0 - dev: true - - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - - /http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 2.0.0 - agent-base: 6.0.2 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - - /iconv-lite@0.5.2: - resolution: {integrity: sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: false - - /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - - /icss-utils@5.1.0(postcss@8.5.1): - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.5.1 - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - /ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /inline-style-parser@0.1.1: - resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} - - /internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - dev: true - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - - /is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - - /is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - - /is-arguments@1.2.0: - resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - /is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - /is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - requiresBuild: true - dev: false - optional: true - - /is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} - dependencies: - async-function: 1.0.0 - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - dev: true - - /is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - dependencies: - has-bigints: 1.1.0 - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - - /is-boolean-object@1.2.1: - resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - dev: true - - /is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - /is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - dependencies: - hasown: 2.0.2 - - /is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - is-typed-array: 1.1.15 - dev: true - - /is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - dev: true - - /is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - - /is-deflate@1.0.0: - resolution: {integrity: sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==} - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - /is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - /is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - - /is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - - /is-gzip@1.0.0: - resolution: {integrity: sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==} - engines: {node: '>=0.10.0'} - - /is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - - /is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - /is-plain-obj@3.0.0: - resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} - engines: {node: '>=10'} - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - - /is-potential-custom-element-name@1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - dev: true - - /is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - dev: false - - /is-reference@3.0.3: - resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} - dependencies: - '@types/estree': 1.0.6 - - /is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - /is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - dev: true - - /is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - /is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - dev: true - - /is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - dev: true - - /is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.18 - - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - /is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - dev: true - - /is-weakref@1.1.0: - resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - dev: true - - /is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - dev: true - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isbot@3.8.0: - resolution: {integrity: sha512-vne1mzQUTR+qsMLeCBL9+/tgnDXRyc2pygLGl/WsgA+EZKIiB5Ehu0CiVTHIIk30zhJ24uGz4M5Ppse37aR0Hg==} - engines: {node: '>=12'} - dev: false - - /isbot@5.1.22: - resolution: {integrity: sha512-RqCFY3cJy3c2y1I+rMn81cfzAR4XJwfPBC+M8kffUjbPzxApzyyv7Tbm1C/gXXq2dSCuD238pKFEWlQMTWsTFw==} - engines: {node: '>=18'} - dev: false - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - /istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - - /istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.26.7 - '@babel/parser': 7.26.7 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - dependencies: - '@babel/core': 7.26.7 - '@babel/parser': 7.26.7 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.7.0 - transitivePeerDependencies: - - supports-color - - /istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - - /istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.4.0 - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - - /istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - - /iterator.prototype@1.1.5: - resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - has-symbols: 1.1.0 - set-function-name: 2.0.2 - dev: true - - /jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - /jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: false - - /javascript-stringify@2.1.0: - resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} - - /jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - - /jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - /jest-cli@29.7.0(@types/node@22.12.0): - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.12.0) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.12.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - /jest-config@29.7.0(@types/node@22.12.0): - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - dependencies: - '@babel/core': 7.26.7 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - babel-jest: 29.7.0(@babel/core@7.26.7) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - /jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - /jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - detect-newline: 3.1.0 - - /jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - - /jest-environment-jsdom@29.7.0: - resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/jsdom': 20.0.1 - '@types/node': 22.12.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - jsdom: 20.0.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - /jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - /jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 22.12.0 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - /jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - /jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - /jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.26.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - /jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - jest-util: 29.7.0 - - /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: - jest-resolve: 29.7.0 - - /jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - /jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - /jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.10 - resolve.exports: 2.0.3 - slash: 3.0.0 - - /jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - /jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - chalk: 4.1.2 - cjs-module-lexer: 1.4.1 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - /jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.26.7 - '@babel/generator': 7.26.5 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.7) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.7) - '@babel/types': 7.26.7 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.7) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.7.0 - transitivePeerDependencies: - - supports-color - - /jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - - /jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - - /jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.12.0 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - - /jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@types/node': 22.12.0 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - /jest@29.7.0(@types/node@22.12.0): - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0 - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.12.0) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - /joycon@3.1.1: - resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} - engines: {node: '>=10'} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - - /jsdom@20.0.3: - resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} - engines: {node: '>=14'} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - dependencies: - abab: 2.0.6 - acorn: 8.14.0 - acorn-globals: 7.0.1 - cssom: 0.5.0 - cssstyle: 2.3.0 - data-urls: 3.0.2 - decimal.js: 10.5.0 - domexception: 4.0.0 - escodegen: 2.1.0 - form-data: 4.0.1 - html-encoding-sniffer: 3.0.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.16 - parse5: 7.2.1 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 4.1.4 - w3c-xmlserializer: 4.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 2.0.0 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - ws: 8.18.0 - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - /json-parse-even-better-errors@3.0.2: - resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - /json-schema-to-ts@1.6.4: - resolution: {integrity: sha512-pR4yQ9DHz6itqswtHCm26mw45FSNfQ9rEQjosaZErhn5J3J2sIViQiz8rDaezjKAhFGpmsoczYVBgGHzFw/stA==} - dependencies: - '@types/json-schema': 7.0.15 - ts-toolbelt: 6.15.5 - dev: false - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: false - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - /jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.3 - object.assign: 4.1.7 - object.values: 1.2.1 - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lilconfig@3.1.3: - resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} - engines: {node: '>=14'} - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - /load-tsconfig@0.2.5: - resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /loader-utils@3.3.1: - resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} - engines: {node: '>= 12.13.0'} - - /local-pkg@0.5.1: - resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} - engines: {node: '>=14'} - dependencies: - mlly: 1.7.4 - pkg-types: 1.3.1 - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - - /lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - - /lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - dev: false - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash.sortby@4.7.0: - resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - /longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - - /lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - - /lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - - /make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - dependencies: - semver: 7.7.0 - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: false - - /makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - dependencies: - tmpl: 1.0.5 - - /markdown-extensions@1.1.1: - resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} - engines: {node: '>=0.10.0'} - - /math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - /mdast-util-definitions@5.1.2: - resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} - dependencies: - '@types/mdast': 3.0.15 - '@types/unist': 2.0.11 - unist-util-visit: 4.1.2 - - /mdast-util-from-markdown@1.3.1: - resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} - dependencies: - '@types/mdast': 3.0.15 - '@types/unist': 2.0.11 - decode-named-character-reference: 1.0.2 - mdast-util-to-string: 3.2.0 - micromark: 3.2.0 - micromark-util-decode-numeric-character-reference: 1.1.0 - micromark-util-decode-string: 1.1.0 - micromark-util-normalize-identifier: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - unist-util-stringify-position: 3.0.3 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - - /mdast-util-frontmatter@1.0.1: - resolution: {integrity: sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw==} - dependencies: - '@types/mdast': 3.0.15 - mdast-util-to-markdown: 1.5.0 - micromark-extension-frontmatter: 1.1.1 - - /mdast-util-mdx-expression@1.3.2: - resolution: {integrity: sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-from-markdown: 1.3.1 - mdast-util-to-markdown: 1.5.0 - transitivePeerDependencies: - - supports-color - - /mdast-util-mdx-jsx@2.1.4: - resolution: {integrity: sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - '@types/unist': 2.0.11 - ccount: 2.0.1 - mdast-util-from-markdown: 1.3.1 - mdast-util-to-markdown: 1.5.0 - parse-entities: 4.0.2 - stringify-entities: 4.0.4 - unist-util-remove-position: 4.0.2 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 - transitivePeerDependencies: - - supports-color - - /mdast-util-mdx@2.0.1: - resolution: {integrity: sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==} - dependencies: - mdast-util-from-markdown: 1.3.1 - mdast-util-mdx-expression: 1.3.2 - mdast-util-mdx-jsx: 2.1.4 - mdast-util-mdxjs-esm: 1.3.1 - mdast-util-to-markdown: 1.5.0 - transitivePeerDependencies: - - supports-color - - /mdast-util-mdxjs-esm@1.3.1: - resolution: {integrity: sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-from-markdown: 1.3.1 - mdast-util-to-markdown: 1.5.0 - transitivePeerDependencies: - - supports-color - - /mdast-util-phrasing@3.0.1: - resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==} - dependencies: - '@types/mdast': 3.0.15 - unist-util-is: 5.2.1 - - /mdast-util-to-hast@12.3.0: - resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==} - dependencies: - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-definitions: 5.1.2 - micromark-util-sanitize-uri: 1.2.0 - trim-lines: 3.0.1 - unist-util-generated: 2.0.1 - unist-util-position: 4.0.4 - unist-util-visit: 4.1.2 - - /mdast-util-to-markdown@1.5.0: - resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==} - dependencies: - '@types/mdast': 3.0.15 - '@types/unist': 2.0.11 - longest-streak: 3.1.0 - mdast-util-phrasing: 3.0.1 - mdast-util-to-string: 3.2.0 - micromark-util-decode-string: 1.1.0 - unist-util-visit: 4.1.2 - zwitch: 2.0.4 - - /mdast-util-to-string@3.2.0: - resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} - dependencies: - '@types/mdast': 3.0.15 - - /media-query-parser@2.0.2: - resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==} - dependencies: - '@babel/runtime': 7.26.7 - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - - /media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} - engines: {node: '>= 0.8'} - dev: false - - /merge-descriptors@1.0.3: - resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} - - /merge-descriptors@2.0.0: - resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} - engines: {node: '>=18'} - dev: false - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - - /micromark-core-commonmark@1.1.0: - resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-factory-destination: 1.1.0 - micromark-factory-label: 1.1.0 - micromark-factory-space: 1.1.0 - micromark-factory-title: 1.1.0 - micromark-factory-whitespace: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-chunked: 1.1.0 - micromark-util-classify-character: 1.1.0 - micromark-util-html-tag-name: 1.2.0 - micromark-util-normalize-identifier: 1.1.0 - micromark-util-resolve-all: 1.1.0 - micromark-util-subtokenize: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - - /micromark-extension-frontmatter@1.1.1: - resolution: {integrity: sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ==} - dependencies: - fault: 2.0.1 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-extension-mdx-expression@1.0.8: - resolution: {integrity: sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==} - dependencies: - '@types/estree': 1.0.6 - micromark-factory-mdx-expression: 1.0.9 - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-events-to-acorn: 1.2.3 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - - /micromark-extension-mdx-jsx@1.0.5: - resolution: {integrity: sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==} - dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.6 - estree-util-is-identifier-name: 2.1.0 - micromark-factory-mdx-expression: 1.0.9 - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - vfile-message: 3.1.4 - - /micromark-extension-mdx-md@1.0.1: - resolution: {integrity: sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==} - dependencies: - micromark-util-types: 1.1.0 - - /micromark-extension-mdxjs-esm@1.0.5: - resolution: {integrity: sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==} - dependencies: - '@types/estree': 1.0.6 - micromark-core-commonmark: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-events-to-acorn: 1.2.3 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - unist-util-position-from-estree: 1.1.2 - uvu: 0.5.6 - vfile-message: 3.1.4 - - /micromark-extension-mdxjs@1.0.1: - resolution: {integrity: sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==} - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - micromark-extension-mdx-expression: 1.0.8 - micromark-extension-mdx-jsx: 1.0.5 - micromark-extension-mdx-md: 1.0.1 - micromark-extension-mdxjs-esm: 1.0.5 - micromark-util-combine-extensions: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-factory-destination@1.1.0: - resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==} - dependencies: - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-factory-label@1.1.0: - resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==} - dependencies: - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - - /micromark-factory-mdx-expression@1.0.9: - resolution: {integrity: sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==} - dependencies: - '@types/estree': 1.0.6 - micromark-util-character: 1.2.0 - micromark-util-events-to-acorn: 1.2.3 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - unist-util-position-from-estree: 1.1.2 - uvu: 0.5.6 - vfile-message: 3.1.4 - - /micromark-factory-space@1.1.0: - resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==} - dependencies: - micromark-util-character: 1.2.0 - micromark-util-types: 1.1.0 - - /micromark-factory-title@1.1.0: - resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==} - dependencies: - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-factory-whitespace@1.1.0: - resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==} - dependencies: - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-util-character@1.2.0: - resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==} - dependencies: - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-util-chunked@1.1.0: - resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==} - dependencies: - micromark-util-symbol: 1.1.0 - - /micromark-util-classify-character@1.1.0: - resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==} - dependencies: - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-util-combine-extensions@1.1.0: - resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==} - dependencies: - micromark-util-chunked: 1.1.0 - micromark-util-types: 1.1.0 - - /micromark-util-decode-numeric-character-reference@1.1.0: - resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==} - dependencies: - micromark-util-symbol: 1.1.0 - - /micromark-util-decode-string@1.1.0: - resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 1.2.0 - micromark-util-decode-numeric-character-reference: 1.1.0 - micromark-util-symbol: 1.1.0 - - /micromark-util-encode@1.1.0: - resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==} - - /micromark-util-events-to-acorn@1.2.3: - resolution: {integrity: sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==} - dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.6 - '@types/unist': 2.0.11 - estree-util-visit: 1.2.1 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - vfile-message: 3.1.4 - - /micromark-util-html-tag-name@1.2.0: - resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} - - /micromark-util-normalize-identifier@1.1.0: - resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==} - dependencies: - micromark-util-symbol: 1.1.0 - - /micromark-util-resolve-all@1.1.0: - resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==} - dependencies: - micromark-util-types: 1.1.0 - - /micromark-util-sanitize-uri@1.2.0: - resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==} - dependencies: - micromark-util-character: 1.2.0 - micromark-util-encode: 1.1.0 - micromark-util-symbol: 1.1.0 - - /micromark-util-subtokenize@1.1.0: - resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==} - dependencies: - micromark-util-chunked: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - - /micromark-util-symbol@1.1.0: - resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==} - - /micromark-util-types@1.1.0: - resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==} - - /micromark@3.2.0: - resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} - dependencies: - '@types/debug': 4.1.12 - debug: 4.4.0 - decode-named-character-reference: 1.0.2 - micromark-core-commonmark: 1.1.0 - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-chunked: 1.1.0 - micromark-util-combine-extensions: 1.1.0 - micromark-util-decode-numeric-character-reference: 1.1.0 - micromark-util-encode: 1.1.0 - micromark-util-normalize-identifier: 1.1.0 - micromark-util-resolve-all: 1.1.0 - micromark-util-sanitize-uri: 1.2.0 - micromark-util-subtokenize: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - - /micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - /mime-db@1.53.0: - resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} - engines: {node: '>= 0.6'} - dev: false - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - - /mime-types@3.0.0: - resolution: {integrity: sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.53.0 - dev: false - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - - /mime@2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: false - - /minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - /minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - - /minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - - /minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.6 - - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - - /minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - - /mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - - /mlly@1.7.4: - resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} - dependencies: - acorn: 8.14.0 - pathe: 2.0.2 - pkg-types: 1.3.1 - ufo: 1.5.4 - - /modern-ahocorasick@1.1.0: - resolution: {integrity: sha512-sEKPVl2rM+MNVkGQt3ChdmD8YsigmXdn5NifZn6jiwn9LRJpWm8F3guhaqrJT/JOat6pwpbXEk6kv+b9DMIjsQ==} - - /morgan@1.10.0: - resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} - engines: {node: '>= 0.8.0'} - dependencies: - basic-auth: 2.0.1 - debug: 2.6.9 - depd: 2.0.0 - on-finished: 2.3.0 - on-headers: 1.0.2 - transitivePeerDependencies: - - supports-color - dev: false - - /mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - - /mrmime@1.0.1: - resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} - engines: {node: '>=10'} - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: true - - /nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - - /negotiator@1.0.0: - resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} - engines: {node: '>= 0.6'} - dev: false - - /next@15.1.6(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - dependencies: - '@next/env': 15.1.6 - '@swc/counter': 0.1.3 - '@swc/helpers': 0.5.15 - busboy: 1.6.0 - caniuse-lite: 1.0.30001696 - postcss: 8.4.31 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.6(react@18.3.1) - optionalDependencies: - '@next/swc-darwin-arm64': 15.1.6 - '@next/swc-darwin-x64': 15.1.6 - '@next/swc-linux-arm64-gnu': 15.1.6 - '@next/swc-linux-arm64-musl': 15.1.6 - '@next/swc-linux-x64-gnu': 15.1.6 - '@next/swc-linux-x64-musl': 15.1.6 - '@next/swc-win32-arm64-msvc': 15.1.6 - '@next/swc-win32-x64-msvc': 15.1.6 - sharp: 0.33.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - - /node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - - /node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - - /normalize-package-data@5.0.0: - resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - hosted-git-info: 6.1.3 - is-core-module: 2.16.1 - semver: 7.7.0 - validate-npm-package-license: 3.0.4 - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-install-checks@6.3.0: - resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.7.0 - - /npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - /npm-package-arg@10.1.0: - resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - hosted-git-info: 6.1.3 - proc-log: 3.0.0 - semver: 7.7.0 - validate-npm-package-name: 5.0.1 - - /npm-pick-manifest@8.0.2: - resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - npm-install-checks: 6.3.0 - npm-normalize-package-bin: 3.0.1 - npm-package-arg: 10.1.0 - semver: 7.7.0 - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - - /nwsapi@2.2.16: - resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} - engines: {node: '>= 0.4'} - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - dev: true - - /object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - dev: true - - /object.values@1.2.1: - resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - dev: true - - /on-finished@2.3.0: - resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: false - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - - /on-headers@1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - dev: false - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - - /optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - dev: true - - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - - /outdent@0.8.0: - resolution: {integrity: sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==} - - /own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.7 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - /package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - /pako@0.2.9: - resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-entities@4.0.2: - resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - dependencies: - '@types/unist': 2.0.11 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.0.2 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.26.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - /parse-ms@2.1.0: - resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==} - engines: {node: '>=6'} - - /parse5@7.2.1: - resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} - dependencies: - entities: 4.5.0 - dev: true - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - - /path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - dev: false - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - /path-to-regexp@0.1.12: - resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} - - /path-to-regexp@8.2.0: - resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} - engines: {node: '>=16'} - dev: false - - /pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - - /pathe@2.0.2: - resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==} - - /peek-stream@1.1.3: - resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} - dependencies: - buffer-from: 1.1.2 - duplexify: 3.7.1 - through2: 2.0.5 - - /periscopic@3.1.0: - resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - dependencies: - '@types/estree': 1.0.6 - estree-walker: 3.0.3 - is-reference: 3.0.3 - - /picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - /picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} - engines: {node: '>=12'} - dev: true - - /pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - - /pkg-types@1.3.1: - resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - dependencies: - confbox: 0.1.8 - mlly: 1.7.4 - pathe: 2.0.2 - - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - - /postcss-discard-duplicates@5.1.0(postcss@8.5.1): - resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.5.1 - - /postcss-load-config@4.0.2(postcss@8.5.1): - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - dependencies: - lilconfig: 3.1.3 - postcss: 8.5.1 - yaml: 2.7.0 - - /postcss-load-config@6.0.1: - resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} - engines: {node: '>= 18'} - peerDependencies: - jiti: '>=1.21.0' - postcss: '>=8.0.9' - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - jiti: - optional: true - postcss: - optional: true - tsx: - optional: true - yaml: - optional: true - dependencies: - lilconfig: 3.1.3 - dev: true - - /postcss-modules-extract-imports@3.1.0(postcss@8.5.1): - resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.5.1 - - /postcss-modules-local-by-default@4.2.0(postcss@8.5.1): - resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.5.1) - postcss: 8.5.1 - postcss-selector-parser: 7.0.0 - postcss-value-parser: 4.2.0 - - /postcss-modules-scope@3.2.1(postcss@8.5.1): - resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.5.1 - postcss-selector-parser: 7.0.0 - - /postcss-modules-values@4.0.0(postcss@8.5.1): - resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.5.1) - postcss: 8.5.1 - - /postcss-modules@6.0.1(postcss@8.5.1): - resolution: {integrity: sha512-zyo2sAkVvuZFFy0gc2+4O+xar5dYlaVy/ebO24KT0ftk/iJevSNyPyQellsBLlnccwh7f6V6Y4GvuKRYToNgpQ==} - peerDependencies: - postcss: ^8.0.0 - dependencies: - generic-names: 4.0.0 - icss-utils: 5.1.0(postcss@8.5.1) - lodash.camelcase: 4.3.0 - postcss: 8.5.1 - postcss-modules-extract-imports: 3.1.0(postcss@8.5.1) - postcss-modules-local-by-default: 4.2.0(postcss@8.5.1) - postcss-modules-scope: 3.2.1(postcss@8.5.1) - postcss-modules-values: 4.0.0(postcss@8.5.1) - string-hash: 1.1.3 - - /postcss-selector-parser@7.0.0: - resolution: {integrity: sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - dev: false - - /postcss@8.5.1: - resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - - /prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - /pretty-ms@7.0.1: - resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==} - engines: {node: '>=10'} - dependencies: - parse-ms: 2.1.0 - - /proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - /promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - - /promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /property-information@6.5.0: - resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - - /psl@1.15.0: - resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} - dependencies: - punycode: 2.3.1 - dev: true - - /pump@2.0.1: - resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - - /pump@3.0.2: - resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - - /pumpify@1.5.1: - resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} - dependencies: - duplexify: 3.7.1 - inherits: 2.0.4 - pump: 2.0.1 - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - /pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - - /qs@6.13.0: - resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.1.0 - - /qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.1.0 - dev: true - - /querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - - /raw-body@3.0.0: - resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.6.3 - unpipe: 1.0.0 - dev: false - - /react-dom@18.3.1(react@18.3.1): - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - /react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} - engines: {node: '>=0.10.0'} - - /react-router-dom@6.28.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-YraE27C/RdjcZwl5UCqF/ffXnZDxpJdk9Q6jw38SZHjXs7NNdpViq2l2c7fO7+4uWaEfcwfGCv3RSg4e1By/fQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' - dependencies: - '@remix-run/router': 1.21.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-router: 6.28.1(react@18.3.1) - - /react-router@6.28.1(react@18.3.1): - resolution: {integrity: sha512-2omQTA3rkMljmrvvo6WtewGdVh45SpL9hGiCI9uUrwGGfNFDIvGK4gYJsKlJoNVi6AQZcopSCballL+QGOm7fA==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' - dependencies: - '@remix-run/router': 1.21.0 - react: 18.3.1 - - /react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - - /readdirp@4.1.1: - resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==} - engines: {node: '>= 14.18.0'} - dev: true - - /reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - dev: true - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - /regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - dev: true - - /remark-frontmatter@4.0.1: - resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} - dependencies: - '@types/mdast': 3.0.15 - mdast-util-frontmatter: 1.0.1 - micromark-extension-frontmatter: 1.1.1 - unified: 10.1.2 - - /remark-mdx-frontmatter@1.1.1: - resolution: {integrity: sha512-7teX9DW4tI2WZkXS4DBxneYSY7NHiXl4AKdWDO9LXVweULlCT8OPWsOjLEnMIXViN1j+QcY8mfbq3k0EK6x3uA==} - engines: {node: '>=12.2.0'} - dependencies: - estree-util-is-identifier-name: 1.1.0 - estree-util-value-to-estree: 1.3.0 - js-yaml: 4.1.0 - toml: 3.0.0 - - /remark-mdx@2.3.0: - resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==} - dependencies: - mdast-util-mdx: 2.0.1 - micromark-extension-mdxjs: 1.0.1 - transitivePeerDependencies: - - supports-color - - /remark-parse@10.0.2: - resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==} - dependencies: - '@types/mdast': 3.0.15 - mdast-util-from-markdown: 1.3.1 - unified: 10.1.2 - transitivePeerDependencies: - - supports-color - - /remark-rehype@10.1.0: - resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} - dependencies: - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-to-hast: 12.3.0 - unified: 10.1.2 - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: false - - /require-like@0.1.2: - resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} - - /requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - dev: true - - /resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - /resolve.exports@2.0.3: - resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} - engines: {node: '>=10'} - - /resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - /rollup@4.32.1: - resolution: {integrity: sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.6 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.32.1 - '@rollup/rollup-android-arm64': 4.32.1 - '@rollup/rollup-darwin-arm64': 4.32.1 - '@rollup/rollup-darwin-x64': 4.32.1 - '@rollup/rollup-freebsd-arm64': 4.32.1 - '@rollup/rollup-freebsd-x64': 4.32.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.32.1 - '@rollup/rollup-linux-arm-musleabihf': 4.32.1 - '@rollup/rollup-linux-arm64-gnu': 4.32.1 - '@rollup/rollup-linux-arm64-musl': 4.32.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.32.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.32.1 - '@rollup/rollup-linux-riscv64-gnu': 4.32.1 - '@rollup/rollup-linux-s390x-gnu': 4.32.1 - '@rollup/rollup-linux-x64-gnu': 4.32.1 - '@rollup/rollup-linux-x64-musl': 4.32.1 - '@rollup/rollup-win32-arm64-msvc': 4.32.1 - '@rollup/rollup-win32-ia32-msvc': 4.32.1 - '@rollup/rollup-win32-x64-msvc': 4.32.1 - fsevents: 2.3.3 - - /router@2.0.0: - resolution: {integrity: sha512-dIM5zVoG8xhC6rnSN8uoAgFARwTE7BQs8YwHEvK0VCmfxQXMaOuA1uiR1IPwsW7JyK5iTt7Od/TC9StasS2NPQ==} - engines: {node: '>= 0.10'} - dependencies: - array-flatten: 3.0.0 - is-promise: 4.0.0 - methods: 1.1.2 - parseurl: 1.3.3 - path-to-regexp: 8.2.0 - setprototypeof: 1.2.0 - utils-merge: 1.0.1 - dev: false - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - - /sade@1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} - dependencies: - mri: 1.2.0 - - /safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - has-symbols: 1.1.0 - isarray: 2.0.5 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - /safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - dev: true - - /safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-regex: 1.2.1 - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - /saxes@6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} - engines: {node: '>=v12.22.7'} - dependencies: - xmlchars: 2.2.0 - dev: true - - /scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - dependencies: - loose-envify: 1.4.0 - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - /semver@7.7.0: - resolution: {integrity: sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==} - engines: {node: '>=10'} - hasBin: true - - /send@0.19.0: - resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - - /send@1.1.0: - resolution: {integrity: sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==} - engines: {node: '>= 18'} - dependencies: - debug: 4.3.6 - destroy: 1.2.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime-types: 2.1.35 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /serve-static@1.16.2: - resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.19.0 - transitivePeerDependencies: - - supports-color - - /serve-static@2.1.0: - resolution: {integrity: sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==} - engines: {node: '>= 18'} - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 1.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /set-cookie-parser@2.7.1: - resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - - /set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} - dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - /sharp@0.33.5: - resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - requiresBuild: true - dependencies: - color: 4.2.3 - detect-libc: 2.0.3 - semver: 7.7.0 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.5 - '@img/sharp-darwin-x64': 0.33.5 - '@img/sharp-libvips-darwin-arm64': 1.0.4 - '@img/sharp-libvips-darwin-x64': 1.0.4 - '@img/sharp-libvips-linux-arm': 1.0.5 - '@img/sharp-libvips-linux-arm64': 1.0.4 - '@img/sharp-libvips-linux-s390x': 1.0.4 - '@img/sharp-libvips-linux-x64': 1.0.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - '@img/sharp-linux-arm': 0.33.5 - '@img/sharp-linux-arm64': 0.33.5 - '@img/sharp-linux-s390x': 0.33.5 - '@img/sharp-linux-x64': 0.33.5 - '@img/sharp-linuxmusl-arm64': 0.33.5 - '@img/sharp-linuxmusl-x64': 0.33.5 - '@img/sharp-wasm32': 0.33.5 - '@img/sharp-win32-ia32': 0.33.5 - '@img/sharp-win32-x64': 0.33.5 - dev: false - optional: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - /side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - - /side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - - /side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - side-channel-map: 1.0.1 - - /side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - /simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - requiresBuild: true - dependencies: - is-arrayish: 0.3.2 - dev: false - optional: true - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - /source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - /source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - /source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - - /source-map@0.8.0-beta.0: - resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} - engines: {node: '>= 8'} - dependencies: - whatwg-url: 7.1.0 - dev: true - - /space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.21 - - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.21 - - /spdx-license-ids@3.0.21: - resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - /ssri@10.0.6: - resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.1.2 - - /stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - - /stream-shift@1.0.3: - resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} - - /stream-slice@0.1.2: - resolution: {integrity: sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==} - - /streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - dev: false - - /string-hash@1.1.3: - resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} - - /string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - - /string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.4 - set-function-name: 2.0.2 - side-channel: 1.1.0 - dev: true - - /string.prototype.repeat@1.0.0: - resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.9 - dev: true - - /string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - dev: true - - /string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - dev: true - - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - - /stringify-entities@4.0.4: - resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.1.0 - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - /strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - /style-to-object@0.4.4: - resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} - dependencies: - inline-style-parser: 0.1.1 - - /styled-jsx@5.1.6(react@18.3.1): - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - client-only: 0.0.1 - react: 18.3.1 - dev: false - - /sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - commander: 4.1.1 - glob: 10.4.5 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - dev: true - - /superagent@9.0.2: - resolution: {integrity: sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==} - engines: {node: '>=14.18.0'} - dependencies: - component-emitter: 1.3.1 - cookiejar: 2.1.4 - debug: 4.4.0 - fast-safe-stringify: 2.1.1 - form-data: 4.0.1 - formidable: 3.5.2 - methods: 1.1.2 - mime: 2.6.0 - qs: 6.14.0 - transitivePeerDependencies: - - supports-color - dev: true - - /supertest@7.0.0: - resolution: {integrity: sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==} - engines: {node: '>=14.18.0'} - dependencies: - methods: 1.1.2 - superagent: 9.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - /symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - dev: true - - /tar-fs@2.1.2: - resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.2 - tar-stream: 2.2.0 - - /tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - - /tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: true - - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: true - - /through2@2.0.5: - resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} - dependencies: - readable-stream: 2.3.8 - xtend: 4.0.2 - - /tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - dev: true - - /tinyglobby@0.2.10: - resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} - engines: {node: '>=12.0.0'} - dependencies: - fdir: 6.4.3(picomatch@4.0.2) - picomatch: 4.0.2 - dev: true - - /tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - - /toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - - /tough-cookie@4.1.4: - resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} - engines: {node: '>=6'} - dependencies: - psl: 1.15.0 - punycode: 2.3.1 - universalify: 0.2.0 - url-parse: 1.5.10 - dev: true - - /tr46@1.0.1: - resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - dependencies: - punycode: 2.3.1 - dev: true - - /tr46@3.0.0: - resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} - engines: {node: '>=12'} - dependencies: - punycode: 2.3.1 - dev: true - - /tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - dev: true - - /trim-lines@3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - - /trough@2.2.0: - resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - - /ts-api-utils@2.0.0(typescript@5.7.3): - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - dependencies: - typescript: 5.7.3 - dev: true - - /ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: true - - /ts-jest@29.2.5(@babel/core@7.26.7)(jest@29.7.0)(typescript@5.7.3): - resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - dependencies: - '@babel/core': 7.26.7 - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.12.0) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.7.0 - typescript: 5.7.3 - yargs-parser: 21.1.1 - dev: false - - /ts-morph@12.0.0: - resolution: {integrity: sha512-VHC8XgU2fFW7yO1f/b3mxKDje1vmyzFXHWzOYmKEkCEwcLjDtbdLgBQviqj4ZwP4MJkQtRo6Ha2I29lq/B+VxA==} - dependencies: - '@ts-morph/common': 0.11.1 - code-block-writer: 10.1.1 - dev: false - - /ts-toolbelt@6.15.5: - resolution: {integrity: sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==} - dev: false - - /tsconfck@2.1.2(typescript@5.7.3): - resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==} - engines: {node: ^14.13.1 || ^16 || >=18} - hasBin: true - peerDependencies: - typescript: ^4.3.5 || ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 5.7.3 - dev: true - - /tsconfig-paths@4.2.0: - resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} - engines: {node: '>=6'} - dependencies: - json5: 2.2.3 - minimist: 1.2.8 - strip-bom: 3.0.0 - - /tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - dev: false - - /tsup@8.3.6(typescript@5.7.3): - resolution: {integrity: sha512-XkVtlDV/58S9Ye0JxUUTcrQk4S+EqlOHKzg6Roa62rdjL1nGWNUstG0xgI4vanHdfIpjP448J8vlN0oK6XOJ5g==} - engines: {node: '>=18'} - hasBin: true - peerDependencies: - '@microsoft/api-extractor': ^7.36.0 - '@swc/core': ^1 - postcss: ^8.4.12 - typescript: '>=4.5.0' - peerDependenciesMeta: - '@microsoft/api-extractor': - optional: true - '@swc/core': - optional: true - postcss: - optional: true - typescript: - optional: true - dependencies: - bundle-require: 5.1.0(esbuild@0.24.2) - cac: 6.7.14 - chokidar: 4.0.3 - consola: 3.4.0 - debug: 4.4.0 - esbuild: 0.24.2 - joycon: 3.1.1 - picocolors: 1.1.1 - postcss-load-config: 6.0.1 - resolve-from: 5.0.0 - rollup: 4.32.1 - source-map: 0.8.0-beta.0 - sucrase: 3.35.0 - tinyexec: 0.3.2 - tinyglobby: 0.2.10 - tree-kill: 1.2.2 - typescript: 5.7.3 - transitivePeerDependencies: - - jiti - - supports-color - - tsx - - yaml - dev: true - - /turbo-darwin-64@2.3.4: - resolution: {integrity: sha512-uOi/cUIGQI7uakZygH+cZQ5D4w+aMLlVCN2KTGot+cmefatps2ZmRRufuHrEM0Rl63opdKD8/JIu+54s25qkfg==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.3.4: - resolution: {integrity: sha512-IIM1Lq5R+EGMtM1YFGl4x8Xkr0MWb4HvyU8N4LNoQ1Be5aycrOE+VVfH+cDg/Q4csn+8bxCOxhRp5KmUflrVTQ==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.3.4: - resolution: {integrity: sha512-1aD2EfR7NfjFXNH3mYU5gybLJEFi2IGOoKwoPLchAFRQ6OEJQj201/oNo9CDL75IIrQo64/NpEgVyZtoPlfhfA==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.3.4: - resolution: {integrity: sha512-MxTpdKwxCaA5IlybPxgGLu54fT2svdqTIxRd0TQmpRJIjM0s4kbM+7YiLk0mOh6dGqlWPUsxz/A0Mkn8Xr5o7Q==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-stream@2.4.0: - resolution: {integrity: sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==} - - /turbo-windows-64@2.3.4: - resolution: {integrity: sha512-yyCrWqcRGu1AOOlrYzRnizEtdkqi+qKP0MW9dbk9OsMDXaOI5jlWtTY/AtWMkLw/czVJ7yS9Ex1vi9DB6YsFvw==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.3.4: - resolution: {integrity: sha512-PggC3qH+njPfn1PDVwKrQvvQby8X09ufbqZ2Ha4uSu+5TvPorHHkAbZVHKYj2Y+tvVzxRzi4Sv6NdHXBS9Be5w==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.3.4: - resolution: {integrity: sha512-1kiLO5C0Okh5ay1DbHsxkPsw9Sjsbjzm6cF85CpWjR0BIyBFNDbKqtUyqGADRS1dbbZoQanJZVj4MS5kk8J42Q==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.3.4 - turbo-darwin-arm64: 2.3.4 - turbo-linux-64: 2.3.4 - turbo-linux-arm64: 2.3.4 - turbo-windows-64: 2.3.4 - turbo-windows-arm64: 2.3.4 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - - /type-is@2.0.0: - resolution: {integrity: sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==} - engines: {node: '>= 0.6'} - dependencies: - content-type: 1.0.5 - media-typer: 1.1.0 - mime-types: 3.0.0 - dev: false - - /typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - dev: true - - /typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - for-each: 0.3.4 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - dev: true - - /typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - for-each: 0.3.4 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - dev: true - - /typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.8 - for-each: 0.3.4 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.0.0 - reflect.getprototypeof: 1.0.10 - dev: true - - /typescript-eslint@8.22.0(eslint@9.19.0)(typescript@5.7.3): - resolution: {integrity: sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - dependencies: - '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0)(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} - engines: {node: '>=14.17'} - hasBin: true - - /ufo@1.5.4: - resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - - /unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - dev: true - - /undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - - /undici@6.21.1: - resolution: {integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==} - engines: {node: '>=18.17'} - - /unified@10.1.2: - resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} - dependencies: - '@types/unist': 2.0.11 - bail: 2.0.2 - extend: 3.0.2 - is-buffer: 2.0.5 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 5.3.7 - - /unique-filename@3.0.0: - resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - unique-slug: 4.0.0 - - /unique-slug@4.0.0: - resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - imurmurhash: 0.1.4 - - /unist-util-generated@2.0.1: - resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==} - - /unist-util-is@5.2.1: - resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} - dependencies: - '@types/unist': 2.0.11 - - /unist-util-position-from-estree@1.1.2: - resolution: {integrity: sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==} - dependencies: - '@types/unist': 2.0.11 - - /unist-util-position@4.0.4: - resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} - dependencies: - '@types/unist': 2.0.11 - - /unist-util-remove-position@4.0.2: - resolution: {integrity: sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==} - dependencies: - '@types/unist': 2.0.11 - unist-util-visit: 4.1.2 - - /unist-util-stringify-position@3.0.3: - resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} - dependencies: - '@types/unist': 2.0.11 - - /unist-util-visit-parents@5.1.3: - resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} - dependencies: - '@types/unist': 2.0.11 - unist-util-is: 5.2.1 - - /unist-util-visit@4.1.2: - resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} - dependencies: - '@types/unist': 2.0.11 - unist-util-is: 5.2.1 - unist-util-visit-parents: 5.1.3 - - /universalify@0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - /update-browserslist-db@1.1.2(browserslist@4.24.4): - resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.24.4 - escalade: 3.2.0 - picocolors: 1.1.1 - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - - /url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - /util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - dependencies: - inherits: 2.0.4 - is-arguments: 1.2.0 - is-generator-function: 1.1.0 - is-typed-array: 1.1.15 - which-typed-array: 1.1.18 - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - - /uvu@0.5.6: - resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} - engines: {node: '>=8'} - hasBin: true - dependencies: - dequal: 2.0.3 - diff: 5.2.0 - kleur: 4.1.5 - sade: 1.8.1 - - /v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - - /valibot@0.41.0(typescript@5.7.3): - resolution: {integrity: sha512-igDBb8CTYr8YTQlOKgaN9nSS0Be7z+WRuaeYqGf3Cjz3aKmSnqEmYnkfVjzIuumGqfHpa3fLIvMEAfhrpqN8ng==} - peerDependencies: - typescript: '>=5' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 5.7.3 - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - - /validate-npm-package-name@5.0.1: - resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - - /vfile-message@3.1.4: - resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} - dependencies: - '@types/unist': 2.0.11 - unist-util-stringify-position: 3.0.3 - - /vfile@5.3.7: - resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} - dependencies: - '@types/unist': 2.0.11 - is-buffer: 2.0.5 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 - - /vite-node@1.6.0: - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.4.0 - pathe: 1.1.2 - picocolors: 1.1.1 - vite: 5.4.14 - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - /vite-tsconfig-paths@4.2.1(typescript@5.7.3)(vite@5.4.14): - resolution: {integrity: sha512-GNUI6ZgPqT3oervkvzU+qtys83+75N/OuDaQl7HmOqFTb0pjZsuARrRipsyJhJ3enqV8beI1xhGbToR4o78nSQ==} - peerDependencies: - vite: '*' - peerDependenciesMeta: - vite: - optional: true - dependencies: - debug: 4.4.0 - globrex: 0.1.2 - tsconfck: 2.1.2(typescript@5.7.3) - vite: 5.4.14 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /vite@5.4.14: - resolution: {integrity: sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.21.5 - postcss: 8.5.1 - rollup: 4.32.1 - optionalDependencies: - fsevents: 2.3.3 - - /w3c-xmlserializer@4.0.0: - resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} - engines: {node: '>=14'} - dependencies: - xml-name-validator: 4.0.0 - dev: true - - /walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - dependencies: - makeerror: 1.0.12 - - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - - /web-encoding@1.1.5: - resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} - dependencies: - util: 0.12.5 - optionalDependencies: - '@zxing/text-encoding': 0.9.0 - - /web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - - /webidl-conversions@4.0.2: - resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - dev: true - - /webidl-conversions@7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} - dev: true - - /whatwg-encoding@2.0.0: - resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} - engines: {node: '>=12'} - dependencies: - iconv-lite: 0.6.3 - dev: true - - /whatwg-mimetype@3.0.0: - resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} - engines: {node: '>=12'} - dev: true - - /whatwg-url@11.0.0: - resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} - engines: {node: '>=12'} - dependencies: - tr46: 3.0.0 - webidl-conversions: 7.0.0 - dev: true - - /whatwg-url@7.1.0: - resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - dev: true - - /which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.1 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - dev: true - - /which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} - dependencies: - call-bound: 1.0.3 - function.prototype.name: 1.1.8 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.0 - is-regex: 1.2.1 - is-weakref: 1.1.0 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.18 - dev: true - - /which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - dev: true - - /which-typed-array@1.1.18: - resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - for-each: 0.3.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - - /which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - isexe: 2.0.0 - - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - - /ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - /ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /xml-name-validator@4.0.0: - resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} - engines: {node: '>=12'} - dev: true - - /xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - dev: true - - /xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - /yaml@2.7.0: - resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} - engines: {node: '>= 14'} - hasBin: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - /zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} diff --git a/examples/non-monorepo/README.md b/examples/non-monorepo/README.md deleted file mode 100644 index 870b17fcec462..0000000000000 --- a/examples/non-monorepo/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# Turborepo non-monorepo starter - -This Turborepo starter is maintained by the Turborepo core team. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e non-monorepo -``` - -## What's inside? - -This Turborepo uses a single, non-monorepo project (in this case, a single Next.js application). - -### Tasks - -There are several Turborepo tasks already set up for you to use. - -#### Build the application - -``` -pnpm turbo build -``` - -#### Lint source code - -``` -pnpm turbo lint -``` - -#### Type check source code - -``` -pnpm turbo check-types -``` - -#### Run the application's development server - -``` -pnpm turbo dev -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/non-monorepo/package.json b/examples/non-monorepo/package.json index c83b72fd258e7..151a7235d7aeb 100644 --- a/examples/non-monorepo/package.json +++ b/examples/non-monorepo/package.json @@ -1,28 +1,16 @@ { - "name": "non-monorepo", - "version": "0.1.0", - "private": true, - "packageManager": "pnpm@8.14.0", - "scripts": { - "dev": "next dev --turbopack", - "build": "next build", - "start": "next start", - "check-types": "tsc --noEmit", - "lint": "next lint" - }, - "dependencies": { - "next": "15.1.6", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "turb": "^0.1.2" - }, - "devDependencies": { - "@eslint/eslintrc": "^3", - "@types/node": "^22", - "@types/react": "^19", - "@types/react-dom": "^19", - "eslint": "^9", - "eslint-config-next": "15.1.6", - "typescript": "^5" - } + "name": "non-monorepo", + "scripts": { + "build": "next build", + "check-types": "tsc --noEmit", + "dev": "next dev --turbopack", + "start": "next start" + }, + "dependencies": { + "next": "15.1.7", + "turb": "0.1.2" + }, + "devDependencies": { + "@types/node": "22" + } } diff --git a/examples/non-monorepo/pnpm-lock.yaml b/examples/non-monorepo/pnpm-lock.yaml deleted file mode 100644 index cd28ae1d4fd96..0000000000000 --- a/examples/non-monorepo/pnpm-lock.yaml +++ /dev/null @@ -1,3056 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - next: - specifier: 15.1.6 - version: 15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - turb: - specifier: ^0.1.2 - version: 0.1.2 - devDependencies: - '@eslint/eslintrc': - specifier: ^3 - version: 3.2.0 - '@types/node': - specifier: ^22 - version: 22.10.10 - '@types/react': - specifier: ^19 - version: 19.0.8 - '@types/react-dom': - specifier: ^19 - version: 19.0.3(@types/react@19.0.8) - eslint: - specifier: ^9 - version: 9.18.0 - eslint-config-next: - specifier: 15.1.6 - version: 15.1.6(eslint@9.18.0)(typescript@5.7.3) - typescript: - specifier: ^5 - version: 5.7.3 - -packages: - - '@emnapi/runtime@1.3.1': - resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} - - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.19.1': - resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.10.0': - resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.2.0': - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.18.0': - resolution: {integrity: sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.5': - resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.2.5': - resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - - '@humanwhocodes/retry@0.4.1': - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} - engines: {node: '>=18.18'} - - '@img/sharp-darwin-arm64@0.33.5': - resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - - '@img/sharp-darwin-x64@0.33.5': - resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-darwin-arm64@1.0.4': - resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} - cpu: [arm64] - os: [darwin] - - '@img/sharp-libvips-darwin-x64@1.0.4': - resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-linux-arm64@1.0.4': - resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linux-arm@1.0.5': - resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} - cpu: [arm] - os: [linux] - - '@img/sharp-libvips-linux-s390x@1.0.4': - resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} - cpu: [s390x] - os: [linux] - - '@img/sharp-libvips-linux-x64@1.0.4': - resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} - cpu: [x64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-x64@1.0.4': - resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} - cpu: [x64] - os: [linux] - - '@img/sharp-linux-arm64@0.33.5': - resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linux-arm@0.33.5': - resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm] - os: [linux] - - '@img/sharp-linux-s390x@0.33.5': - resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [s390x] - os: [linux] - - '@img/sharp-linux-x64@0.33.5': - resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-linuxmusl-arm64@0.33.5': - resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linuxmusl-x64@0.33.5': - resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-wasm32@0.33.5': - resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [wasm32] - - '@img/sharp-win32-ia32@0.33.5': - resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ia32] - os: [win32] - - '@img/sharp-win32-x64@0.33.5': - resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [win32] - - '@next/env@15.1.6': - resolution: {integrity: sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==} - - '@next/eslint-plugin-next@15.1.6': - resolution: {integrity: sha512-+slMxhTgILUntZDGNgsKEYHUvpn72WP1YTlkmEhS51vnVd7S9jEEy0n9YAMcI21vUG4akTw9voWH02lrClt/yw==} - - '@next/swc-darwin-arm64@15.1.6': - resolution: {integrity: sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@15.1.6': - resolution: {integrity: sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@15.1.6': - resolution: {integrity: sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-arm64-musl@15.1.6': - resolution: {integrity: sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-x64-gnu@15.1.6': - resolution: {integrity: sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-linux-x64-musl@15.1.6': - resolution: {integrity: sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-win32-arm64-msvc@15.1.6': - resolution: {integrity: sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-x64-msvc@15.1.6': - resolution: {integrity: sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@nolyfill/is-core-module@1.0.39': - resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} - engines: {node: '>=12.4.0'} - - '@rtsao/scc@1.1.0': - resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - - '@rushstack/eslint-patch@1.10.5': - resolution: {integrity: sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==} - - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/node@22.10.10': - resolution: {integrity: sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==} - - '@types/react-dom@19.0.3': - resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} - peerDependencies: - '@types/react': ^19.0.0 - - '@types/react@19.0.8': - resolution: {integrity: sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==} - - '@typescript-eslint/eslint-plugin@8.21.0': - resolution: {integrity: sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/parser@8.21.0': - resolution: {integrity: sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/scope-manager@8.21.0': - resolution: {integrity: sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/type-utils@8.21.0': - resolution: {integrity: sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/types@8.21.0': - resolution: {integrity: sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.21.0': - resolution: {integrity: sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/utils@8.21.0': - resolution: {integrity: sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/visitor-keys@8.21.0': - resolution: {integrity: sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - - array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - - array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} - engines: {node: '>= 0.4'} - - array.prototype.flat@1.3.3: - resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} - engines: {node: '>= 0.4'} - - array.prototype.flatmap@1.3.3: - resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} - engines: {node: '>= 0.4'} - - array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - - arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} - - ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - - async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - axe-core@4.10.2: - resolution: {integrity: sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==} - engines: {node: '>=4'} - - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - - call-bind-apply-helpers@1.0.1: - resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} - engines: {node: '>= 0.4'} - - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - - call-bound@1.0.3: - resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - caniuse-lite@1.0.30001695: - resolution: {integrity: sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - - data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} - - data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} - - data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} - - debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - enhanced-resolve@5.18.0: - resolution: {integrity: sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==} - engines: {node: '>=10.13.0'} - - es-abstract@1.23.9: - resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} - engines: {node: '>= 0.4'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-iterator-helpers@1.2.1: - resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} - engines: {node: '>= 0.4'} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - - es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} - engines: {node: '>= 0.4'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-config-next@15.1.6: - resolution: {integrity: sha512-Wd1uy6y7nBbXUSg9QAuQ+xYEKli5CgUhLjz1QHW11jLDis5vK5XB3PemL6jEmy7HrdhaRFDz+GTZ/3FoH+EUjg==} - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 - typescript: '>=3.3.1' - peerDependenciesMeta: - typescript: - optional: true - - eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - - eslint-import-resolver-typescript@3.7.0: - resolution: {integrity: sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - eslint-plugin-import-x: '*' - peerDependenciesMeta: - eslint-plugin-import: - optional: true - eslint-plugin-import-x: - optional: true - - eslint-module-utils@2.12.0: - resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - - eslint-plugin-import@2.31.0: - resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - - eslint-plugin-jsx-a11y@6.10.2: - resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - - eslint-plugin-react-hooks@5.1.0: - resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - - eslint-plugin-react@7.37.4: - resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.18.0: - resolution: {integrity: sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.18.0: - resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - - get-intrinsic@1.2.7: - resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} - - get-tsconfig@4.10.0: - resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - - is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - - is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} - - is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - - is-boolean-object@1.2.1: - resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} - engines: {node: '>= 0.4'} - - is-bun-module@1.3.0: - resolution: {integrity: sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} - - is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} - - is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} - engines: {node: '>= 0.4'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - - is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - - is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - - is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakref@1.1.0: - resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - iterator.prototype@1.1.5: - resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} - engines: {node: '>= 0.4'} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - - jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - language-subtag-registry@0.3.23: - resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} - - language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - next@15.1.6: - resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} - engines: {node: '>= 0.4'} - - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - - object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - - object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - - object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.1: - resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} - engines: {node: '>= 0.4'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - - postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-dom@19.0.0: - resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} - peerDependencies: - react: ^19.0.0 - - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - react@19.0.0: - resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} - engines: {node: '>=0.10.0'} - - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - - resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - - safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - - scheduler@0.25.0: - resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - - set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} - - sharp@0.33.5: - resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - stable-hash@0.0.4: - resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} - - streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - - string.prototype.includes@2.0.1: - resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} - engines: {node: '>= 0.4'} - - string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} - engines: {node: '>= 0.4'} - - string.prototype.repeat@1.0.0: - resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} - engines: {node: '>= 0.4'} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - styled-jsx@5.1.6: - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - ts-api-utils@2.0.0: - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - turb@0.1.2: - resolution: {integrity: sha512-CJct9otdtEEUJRs85pGwSwYdpP8OhD+Qov/rPSghdDmQYo0fL/7F+h27gF9TkoIh3I0/ACXZ6ymLxXF9TRv1rA==} - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} - - typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} - - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} - engines: {node: '>= 0.4'} - - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} - engines: {node: '>=14.17'} - hasBin: true - - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - - which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - - which-typed-array@1.1.18: - resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} - engines: {node: '>= 0.4'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@emnapi/runtime@1.3.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@eslint-community/eslint-utils@4.4.1(eslint@9.18.0)': - dependencies: - eslint: 9.18.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/config-array@0.19.1': - dependencies: - '@eslint/object-schema': 2.1.5 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/core@0.10.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.2.0': - dependencies: - ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.18.0': {} - - '@eslint/object-schema@2.1.5': {} - - '@eslint/plugin-kit@0.2.5': - dependencies: - '@eslint/core': 0.10.0 - levn: 0.4.1 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.6': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.3.1': {} - - '@humanwhocodes/retry@0.4.1': {} - - '@img/sharp-darwin-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.4 - optional: true - - '@img/sharp-darwin-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.0.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-darwin-x64@1.0.4': - optional: true - - '@img/sharp-libvips-linux-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-linux-arm@1.0.5': - optional: true - - '@img/sharp-libvips-linux-s390x@1.0.4': - optional: true - - '@img/sharp-libvips-linux-x64@1.0.4': - optional: true - - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-linuxmusl-x64@1.0.4': - optional: true - - '@img/sharp-linux-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.0.4 - optional: true - - '@img/sharp-linux-arm@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.0.5 - optional: true - - '@img/sharp-linux-s390x@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.0.4 - optional: true - - '@img/sharp-linux-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.0.4 - optional: true - - '@img/sharp-linuxmusl-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - optional: true - - '@img/sharp-linuxmusl-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - optional: true - - '@img/sharp-wasm32@0.33.5': - dependencies: - '@emnapi/runtime': 1.3.1 - optional: true - - '@img/sharp-win32-ia32@0.33.5': - optional: true - - '@img/sharp-win32-x64@0.33.5': - optional: true - - '@next/env@15.1.6': {} - - '@next/eslint-plugin-next@15.1.6': - dependencies: - fast-glob: 3.3.1 - - '@next/swc-darwin-arm64@15.1.6': - optional: true - - '@next/swc-darwin-x64@15.1.6': - optional: true - - '@next/swc-linux-arm64-gnu@15.1.6': - optional: true - - '@next/swc-linux-arm64-musl@15.1.6': - optional: true - - '@next/swc-linux-x64-gnu@15.1.6': - optional: true - - '@next/swc-linux-x64-musl@15.1.6': - optional: true - - '@next/swc-win32-arm64-msvc@15.1.6': - optional: true - - '@next/swc-win32-x64-msvc@15.1.6': - optional: true - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.18.0 - - '@nolyfill/is-core-module@1.0.39': {} - - '@rtsao/scc@1.1.0': {} - - '@rushstack/eslint-patch@1.10.5': {} - - '@swc/counter@0.1.3': {} - - '@swc/helpers@0.5.15': - dependencies: - tslib: 2.8.1 - - '@types/estree@1.0.6': {} - - '@types/json-schema@7.0.15': {} - - '@types/json5@0.0.29': {} - - '@types/node@22.10.10': - dependencies: - undici-types: 6.20.0 - - '@types/react-dom@19.0.3(@types/react@19.0.8)': - dependencies: - '@types/react': 19.0.8 - - '@types/react@19.0.8': - dependencies: - csstype: 3.1.3 - - '@typescript-eslint/eslint-plugin@8.21.0(@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.21.0(eslint@9.18.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.21.0 - '@typescript-eslint/type-utils': 8.21.0(eslint@9.18.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.21.0(eslint@9.18.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.21.0 - eslint: 9.18.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.21.0 - '@typescript-eslint/types': 8.21.0 - '@typescript-eslint/typescript-estree': 8.21.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.21.0 - debug: 4.4.0 - eslint: 9.18.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.21.0': - dependencies: - '@typescript-eslint/types': 8.21.0 - '@typescript-eslint/visitor-keys': 8.21.0 - - '@typescript-eslint/type-utils@8.21.0(eslint@9.18.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.21.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.21.0(eslint@9.18.0)(typescript@5.7.3) - debug: 4.4.0 - eslint: 9.18.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.21.0': {} - - '@typescript-eslint/typescript-estree@8.21.0(typescript@5.7.3)': - dependencies: - '@typescript-eslint/types': 8.21.0 - '@typescript-eslint/visitor-keys': 8.21.0 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.21.0(eslint@9.18.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.18.0) - '@typescript-eslint/scope-manager': 8.21.0 - '@typescript-eslint/types': 8.21.0 - '@typescript-eslint/typescript-estree': 8.21.0(typescript@5.7.3) - eslint: 9.18.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.21.0': - dependencies: - '@typescript-eslint/types': 8.21.0 - eslint-visitor-keys: 4.2.0 - - acorn-jsx@5.3.2(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - argparse@2.0.1: {} - - aria-query@5.3.2: {} - - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.3 - is-array-buffer: 3.0.5 - - array-includes@3.1.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - is-string: 1.1.1 - - array.prototype.findlast@1.2.5: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-shim-unscopables: 1.0.2 - - array.prototype.findlastindex@1.2.5: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-shim-unscopables: 1.0.2 - - array.prototype.flat@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - - array.prototype.flatmap@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - - array.prototype.tosorted@1.1.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - is-array-buffer: 3.0.5 - - ast-types-flow@0.0.8: {} - - async-function@1.0.0: {} - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.0.0 - - axe-core@4.10.2: {} - - axobject-query@4.1.0: {} - - balanced-match@1.0.2: {} - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - busboy@1.6.0: - dependencies: - streamsearch: 1.1.0 - - call-bind-apply-helpers@1.0.1: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - get-intrinsic: 1.2.7 - set-function-length: 1.2.2 - - call-bound@1.0.3: - dependencies: - call-bind-apply-helpers: 1.0.1 - get-intrinsic: 1.2.7 - - callsites@3.1.0: {} - - caniuse-lite@1.0.30001695: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - client-only@0.0.1: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - optional: true - - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - optional: true - - concat-map@0.0.1: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - csstype@3.1.3: {} - - damerau-levenshtein@1.0.8: {} - - data-view-buffer@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-length@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-offset@1.0.1: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - debug@3.2.7: - dependencies: - ms: 2.1.3 - - debug@4.4.0: - dependencies: - ms: 2.1.3 - - deep-is@0.1.4: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - detect-libc@2.0.3: - optional: true - - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - emoji-regex@9.2.2: {} - - enhanced-resolve@5.18.0: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - - es-abstract@1.23.9: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-regex: 1.2.1 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.0 - math-intrinsics: 1.1.0 - object-inspect: 1.13.3 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.1 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.18 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-iterator-helpers@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-set-tostringtag: 2.1.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - iterator.prototype: 1.1.5 - safe-array-concat: 1.1.3 - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - es-shim-unscopables@1.0.2: - dependencies: - hasown: 2.0.2 - - es-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - - escape-string-regexp@4.0.0: {} - - eslint-config-next@15.1.6(eslint@9.18.0)(typescript@5.7.3): - dependencies: - '@next/eslint-plugin-next': 15.1.6 - '@rushstack/eslint-patch': 1.10.5 - '@typescript-eslint/eslint-plugin': 8.21.0(@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3) - '@typescript-eslint/parser': 8.21.0(eslint@9.18.0)(typescript@5.7.3) - eslint: 9.18.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.18.0) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.18.0) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.18.0) - eslint-plugin-react: 7.37.4(eslint@9.18.0) - eslint-plugin-react-hooks: 5.1.0(eslint@9.18.0) - optionalDependencies: - typescript: 5.7.3 - transitivePeerDependencies: - - eslint-import-resolver-webpack - - eslint-plugin-import-x - - supports-color - - eslint-import-resolver-node@0.3.9: - dependencies: - debug: 3.2.7 - is-core-module: 2.16.1 - resolve: 1.22.10 - transitivePeerDependencies: - - supports-color - - eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.18.0): - dependencies: - '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.0 - enhanced-resolve: 5.18.0 - eslint: 9.18.0 - fast-glob: 3.3.3 - get-tsconfig: 4.10.0 - is-bun-module: 1.3.0 - is-glob: 4.0.3 - stable-hash: 0.0.4 - optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.18.0) - transitivePeerDependencies: - - supports-color - - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.18.0))(eslint@9.18.0): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 8.21.0(eslint@9.18.0)(typescript@5.7.3) - eslint: 9.18.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.18.0) - transitivePeerDependencies: - - supports-color - - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.18.0): - dependencies: - '@rtsao/scc': 1.1.0 - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.3 - array.prototype.flatmap: 1.3.3 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 9.18.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.21.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.18.0))(eslint@9.18.0) - hasown: 2.0.2 - is-core-module: 2.16.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.1 - semver: 6.3.1 - string.prototype.trimend: 1.0.9 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 8.21.0(eslint@9.18.0)(typescript@5.7.3) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - - eslint-plugin-jsx-a11y@6.10.2(eslint@9.18.0): - dependencies: - aria-query: 5.3.2 - array-includes: 3.1.8 - array.prototype.flatmap: 1.3.3 - ast-types-flow: 0.0.8 - axe-core: 4.10.2 - axobject-query: 4.1.0 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 9.18.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - safe-regex-test: 1.1.0 - string.prototype.includes: 2.0.1 - - eslint-plugin-react-hooks@5.1.0(eslint@9.18.0): - dependencies: - eslint: 9.18.0 - - eslint-plugin-react@7.37.4(eslint@9.18.0): - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.3 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.2.1 - eslint: 9.18.0 - estraverse: 5.3.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.values: 1.2.1 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.12 - string.prototype.repeat: 1.0.0 - - eslint-scope@8.2.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.0: {} - - eslint@9.18.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.18.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.1 - '@eslint/core': 0.10.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.18.0 - '@eslint/plugin-kit': 0.2.5 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - - espree@10.3.0: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.1: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.18.0: - dependencies: - reusify: 1.0.4 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - - flatted@3.3.2: {} - - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - - function-bind@1.1.2: {} - - function.prototype.name@1.1.8: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - - functions-have-names@1.2.3: {} - - get-intrinsic@1.2.7: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-symbol-description@1.1.0: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - - get-tsconfig@4.10.0: - dependencies: - resolve-pkg-maps: 1.0.0 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - globals@14.0.0: {} - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - graphemer@1.4.0: {} - - has-bigints@1.1.0: {} - - has-flag@4.0.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-proto@1.2.0: - dependencies: - dunder-proto: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - ignore@5.3.2: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - - is-arrayish@0.3.2: - optional: true - - is-async-function@2.1.1: - dependencies: - async-function: 1.0.0 - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - - is-boolean-object@1.2.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-bun-module@1.3.0: - dependencies: - semver: 7.6.3 - - is-callable@1.2.7: {} - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-data-view@1.0.2: - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - is-typed-array: 1.1.15 - - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-extglob@2.1.1: {} - - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.3 - - is-generator-function@1.1.0: - dependencies: - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-map@2.0.3: {} - - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-number@7.0.0: {} - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.3 - - is-string@1.1.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.3 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.18 - - is-weakmap@2.0.2: {} - - is-weakref@1.1.0: - dependencies: - call-bound: 1.0.3 - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - - isarray@2.0.5: {} - - isexe@2.0.0: {} - - iterator.prototype@1.1.5: - dependencies: - define-data-property: 1.1.4 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - has-symbols: 1.1.0 - set-function-name: 2.0.2 - - js-tokens@4.0.0: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@1.0.2: - dependencies: - minimist: 1.2.8 - - jsx-ast-utils@3.3.5: - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.3 - object.assign: 4.1.7 - object.values: 1.2.1 - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - language-subtag-registry@0.3.23: {} - - language-tags@1.0.9: - dependencies: - language-subtag-registry: 0.3.23 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.merge@4.6.2: {} - - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - - math-intrinsics@1.1.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 - - minimist@1.2.8: {} - - ms@2.1.3: {} - - nanoid@3.3.8: {} - - natural-compare@1.4.0: {} - - next@15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0): - dependencies: - '@next/env': 15.1.6 - '@swc/counter': 0.1.3 - '@swc/helpers': 0.5.15 - busboy: 1.6.0 - caniuse-lite: 1.0.30001695 - postcss: 8.4.31 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - styled-jsx: 5.1.6(react@19.0.0) - optionalDependencies: - '@next/swc-darwin-arm64': 15.1.6 - '@next/swc-darwin-x64': 15.1.6 - '@next/swc-linux-arm64-gnu': 15.1.6 - '@next/swc-linux-arm64-musl': 15.1.6 - '@next/swc-linux-x64-gnu': 15.1.6 - '@next/swc-linux-x64-musl': 15.1.6 - '@next/swc-win32-arm64-msvc': 15.1.6 - '@next/swc-win32-x64-msvc': 15.1.6 - sharp: 0.33.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - object-assign@4.1.1: {} - - object-inspect@1.13.3: {} - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - - object.entries@1.1.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - object.fromentries@2.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - - object.groupby@1.0.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - - object.values@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - own-keys@1.0.1: - dependencies: - get-intrinsic: 1.2.7 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - path-exists@4.0.0: {} - - path-key@3.1.1: {} - - path-parse@1.0.7: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - possible-typed-array-names@1.0.0: {} - - postcss@8.4.31: - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - react-dom@19.0.0(react@19.0.0): - dependencies: - react: 19.0.0 - scheduler: 0.25.0 - - react-is@16.13.1: {} - - react@19.0.0: {} - - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - - resolve-from@4.0.0: {} - - resolve-pkg-maps@1.0.0: {} - - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - resolve@2.0.0-next.5: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - reusify@1.0.4: {} - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-array-concat@1.1.3: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - has-symbols: 1.1.0 - isarray: 2.0.5 - - safe-push-apply@1.0.0: - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-regex: 1.2.1 - - scheduler@0.25.0: {} - - semver@6.3.1: {} - - semver@7.6.3: {} - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - set-proto@1.0.0: - dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - - sharp@0.33.5: - dependencies: - color: 4.2.3 - detect-libc: 2.0.3 - semver: 7.6.3 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.5 - '@img/sharp-darwin-x64': 0.33.5 - '@img/sharp-libvips-darwin-arm64': 1.0.4 - '@img/sharp-libvips-darwin-x64': 1.0.4 - '@img/sharp-libvips-linux-arm': 1.0.5 - '@img/sharp-libvips-linux-arm64': 1.0.4 - '@img/sharp-libvips-linux-s390x': 1.0.4 - '@img/sharp-libvips-linux-x64': 1.0.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - '@img/sharp-linux-arm': 0.33.5 - '@img/sharp-linux-arm64': 0.33.5 - '@img/sharp-linux-s390x': 0.33.5 - '@img/sharp-linux-x64': 0.33.5 - '@img/sharp-linuxmusl-arm64': 0.33.5 - '@img/sharp-linuxmusl-x64': 0.33.5 - '@img/sharp-wasm32': 0.33.5 - '@img/sharp-win32-ia32': 0.33.5 - '@img/sharp-win32-x64': 0.33.5 - optional: true - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 - optional: true - - source-map-js@1.2.1: {} - - stable-hash@0.0.4: {} - - streamsearch@1.1.0: {} - - string.prototype.includes@2.0.1: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - - string.prototype.matchall@4.0.12: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.4 - set-function-name: 2.0.2 - side-channel: 1.1.0 - - string.prototype.repeat@1.0.0: - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.9 - - string.prototype.trim@1.2.10: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - - string.prototype.trimend@1.0.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - strip-bom@3.0.0: {} - - strip-json-comments@3.1.1: {} - - styled-jsx@5.1.6(react@19.0.0): - dependencies: - client-only: 0.0.1 - react: 19.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - tapable@2.2.1: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - ts-api-utils@2.0.0(typescript@5.7.3): - dependencies: - typescript: 5.7.3 - - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - - tslib@2.8.1: {} - - turb@0.1.2: {} - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typed-array-byte-length@1.0.3: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - - typed-array-byte-offset@1.0.4: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - - typed-array-length@1.0.7: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.0.0 - reflect.getprototypeof: 1.0.10 - - typescript@5.7.3: {} - - unbox-primitive@1.1.0: - dependencies: - call-bound: 1.0.3 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - - undici-types@6.20.0: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.1 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-builtin-type@1.2.1: - dependencies: - call-bound: 1.0.3 - function.prototype.name: 1.1.8 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.0 - is-regex: 1.2.1 - is-weakref: 1.1.0 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.18 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - - which-typed-array@1.1.18: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - for-each: 0.3.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - word-wrap@1.2.5: {} - - yocto-queue@0.1.0: {} diff --git a/examples/package.json b/examples/package.json index 8a35f6a323fda..405ae84f675e9 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,9 +1,10 @@ { - "name": "turborepo-examples", - "scripts": { - "install-all": "tsx install-all.ts" - }, - "devDependencies": { - "tsx": "4.19.1" - } + "name": "turborepo-examples", + "scripts": { + "install-all": "tsx install-all.ts" + }, + "dependencies": {}, + "devDependencies": { + "tsx": "4.19.2" + } } diff --git a/examples/with-angular/.eslintrc.js b/examples/with-angular/.eslintrc.js deleted file mode 100644 index e928b8686408e..0000000000000 --- a/examples/with-angular/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -// This configuration only applies to the package manager root. -/** @type {import("eslint").Linter.Config} */ -module.exports = { - ignorePatterns: ["apps/**", "packages/**"], - extends: ["@repo/eslint-config/library.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-angular/.prettierignore b/examples/with-angular/.prettierignore deleted file mode 100644 index 3c5376bd60515..0000000000000 --- a/examples/with-angular/.prettierignore +++ /dev/null @@ -1,15 +0,0 @@ -.DS_Store -.svelte-kit -node_modules -/build -/package -.env -.env.* -!.env.example -vite.config.js* - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -pnpm-workspace.yaml -package-lock.json -yarn.lock diff --git a/examples/with-angular/.prettierrc b/examples/with-angular/.prettierrc deleted file mode 100644 index ab57af61080a2..0000000000000 --- a/examples/with-angular/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100 -} diff --git a/examples/with-angular/README.md b/examples/with-angular/README.md deleted file mode 100644 index 5f6621fa36f68..0000000000000 --- a/examples/with-angular/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Turborepo starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-angular -``` - -## What's inside? - -This Turborepo includes the following pckages/apps: - -### Apps and Packages - -- `docs` an [angular](https://angular.dev/) app -- `web` another [angular](https://angular.dev/) app -- `ui` a stub Angular component library shared by both `web` and `docs` application -- `eslint-config`: `eslint` configurations (based on [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint#readme)) - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io/) for code formatting diff --git a/examples/with-angular/apps/docs/.editorconfig b/examples/with-angular/apps/docs/.editorconfig deleted file mode 100644 index 59d9a3a3e73ff..0000000000000 --- a/examples/with-angular/apps/docs/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/examples/with-angular/apps/docs/.eslintrc.json b/examples/with-angular/apps/docs/.eslintrc.json deleted file mode 100644 index a19b0bf135655..0000000000000 --- a/examples/with-angular/apps/docs/.eslintrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "root": true, - "extends": "@repo/eslint-config/angular.js" -} diff --git a/examples/with-angular/apps/docs/.vscode/extensions.json b/examples/with-angular/apps/docs/.vscode/extensions.json deleted file mode 100644 index 77b374577de83..0000000000000 --- a/examples/with-angular/apps/docs/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 - "recommendations": ["angular.ng-template"] -} diff --git a/examples/with-angular/apps/docs/.vscode/launch.json b/examples/with-angular/apps/docs/.vscode/launch.json deleted file mode 100644 index 925af837050a4..0000000000000 --- a/examples/with-angular/apps/docs/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "ng serve", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: start", - "url": "http://localhost:4200/" - }, - { - "name": "ng test", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: test", - "url": "http://localhost:9876/debug.html" - } - ] -} diff --git a/examples/with-angular/apps/docs/.vscode/tasks.json b/examples/with-angular/apps/docs/.vscode/tasks.json deleted file mode 100644 index a298b5bd8796a..0000000000000 --- a/examples/with-angular/apps/docs/.vscode/tasks.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "start", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - }, - { - "type": "npm", - "script": "test", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - } - ] -} diff --git a/examples/with-angular/apps/docs/README.md b/examples/with-angular/apps/docs/README.md deleted file mode 100644 index f5ec4e1db9523..0000000000000 --- a/examples/with-angular/apps/docs/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Docs - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.7. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/examples/with-angular/apps/docs/src/app/app.component.css b/examples/with-angular/apps/docs/Source/app/app.component.css similarity index 100% rename from examples/with-angular/apps/docs/src/app/app.component.css rename to examples/with-angular/apps/docs/Source/app/app.component.css diff --git a/examples/with-angular/apps/docs/src/app/app.component.html b/examples/with-angular/apps/docs/Source/app/app.component.html similarity index 100% rename from examples/with-angular/apps/docs/src/app/app.component.html rename to examples/with-angular/apps/docs/Source/app/app.component.html diff --git a/examples/with-angular/apps/docs/src/app/app.component.ts b/examples/with-angular/apps/docs/Source/app/app.component.ts similarity index 100% rename from examples/with-angular/apps/docs/src/app/app.component.ts rename to examples/with-angular/apps/docs/Source/app/app.component.ts diff --git a/examples/with-angular/apps/docs/src/app/app.config.ts b/examples/with-angular/apps/docs/Source/app/app.config.ts similarity index 100% rename from examples/with-angular/apps/docs/src/app/app.config.ts rename to examples/with-angular/apps/docs/Source/app/app.config.ts diff --git a/examples/with-angular/apps/docs/src/app/app.routes.ts b/examples/with-angular/apps/docs/Source/app/app.routes.ts similarity index 100% rename from examples/with-angular/apps/docs/src/app/app.routes.ts rename to examples/with-angular/apps/docs/Source/app/app.routes.ts diff --git a/examples/with-angular/apps/web/src/assets/.gitkeep b/examples/with-angular/apps/docs/Source/assets/.gitkeep similarity index 100% rename from examples/with-angular/apps/web/src/assets/.gitkeep rename to examples/with-angular/apps/docs/Source/assets/.gitkeep diff --git a/examples/with-angular/apps/docs/src/favicon.ico b/examples/with-angular/apps/docs/Source/favicon.ico similarity index 100% rename from examples/with-angular/apps/docs/src/favicon.ico rename to examples/with-angular/apps/docs/Source/favicon.ico diff --git a/examples/with-angular/apps/docs/src/index.html b/examples/with-angular/apps/docs/Source/index.html similarity index 100% rename from examples/with-angular/apps/docs/src/index.html rename to examples/with-angular/apps/docs/Source/index.html diff --git a/examples/with-angular/apps/docs/src/main.ts b/examples/with-angular/apps/docs/Source/main.ts similarity index 100% rename from examples/with-angular/apps/docs/src/main.ts rename to examples/with-angular/apps/docs/Source/main.ts diff --git a/examples/with-angular/apps/docs/src/styles.css b/examples/with-angular/apps/docs/Source/styles.css similarity index 100% rename from examples/with-angular/apps/docs/src/styles.css rename to examples/with-angular/apps/docs/Source/styles.css diff --git a/examples/with-angular/apps/docs/package.json b/examples/with-angular/apps/docs/package.json index bd0560e323742..98fa0e3d853cc 100644 --- a/examples/with-angular/apps/docs/package.json +++ b/examples/with-angular/apps/docs/package.json @@ -1,50 +1,40 @@ { - "name": "docs", - "version": "1.0.0", - "private": true, - "scripts": { - "ng": "ng", - "start": "ng serve --host 0.0.0.0", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "lint": "eslint . --max-warnings 0", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .angular" - }, - "dependencies": { - "@angular/animations": "^17.3.0", - "@angular/common": "^17.3.0", - "@angular/compiler": "^17.3.0", - "@angular/core": "^17.3.0", - "@angular/forms": "^17.3.0", - "@angular/platform-browser": "^17.3.0", - "@angular/platform-browser-dynamic": "^17.3.0", - "@angular/router": "^17.3.0", - "@repo/ui": "workspace:*", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.14.3" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^17.3.7", - "@angular-eslint/builder": "17.4.0", - "@angular-eslint/eslint-plugin": "17.4.0", - "@angular-eslint/eslint-plugin-template": "17.4.0", - "@angular-eslint/schematics": "17.4.0", - "@angular-eslint/template-parser": "17.4.0", - "@angular/cli": "^17.3.7", - "@angular/compiler-cli": "^17.3.0", - "@repo/eslint-config": "workspace:*", - "@types/jasmine": "~5.1.0", - "@typescript-eslint/eslint-plugin": "7.8.0", - "@typescript-eslint/parser": "7.8.0", - "eslint": "^8.57.0", - "jasmine-core": "~5.1.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.4.2" - } + "name": "docs", + "scripts": { + "build": "ng build", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .angular", + "ng": "ng", + "start": "ng serve --host 0.0.0.0" + }, + "dependencies": { + "@angular/animations": "19.1.6", + "@angular/common": "19.1.6", + "@angular/compiler": "19.1.6", + "@angular/core": "19.1.6", + "@angular/forms": "19.1.6", + "@angular/platform-browser": "19.1.6", + "@angular/platform-browser-dynamic": "19.1.6", + "@angular/router": "19.1.6", + "@repo/ui": "workspace:*", + "rxjs": "7.8.1", + "tslib": "2.8.1", + "zone.js": "0.15.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "19.1.7", + "@angular-eslint/builder": "19.1.0", + "@angular-eslint/eslint-plugin": "19.1.0", + "@angular-eslint/eslint-plugin-template": "19.1.0", + "@angular-eslint/schematics": "19.1.0", + "@angular-eslint/template-parser": "19.1.0", + "@angular/cli": "19.1.7", + "@angular/compiler-cli": "19.1.6", + "@repo/eslint-config": "workspace:*", + "@types/jasmine": "5.1.5", + "jasmine-core": "5.6.0", + "karma": "6.4.4", + "karma-coverage": "2.2.1", + "karma-jasmine": "5.1.0", + "karma-jasmine-html-reporter": "2.1.0" + } } diff --git a/examples/with-angular/apps/docs/src/app/app.component.spec.ts b/examples/with-angular/apps/docs/src/app/app.component.spec.ts deleted file mode 100644 index 209c0d3097880..0000000000000 --- a/examples/with-angular/apps/docs/src/app/app.component.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [AppComponent] - }).compileComponents(); - }); - - it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app).toBeTruthy(); - }); - - it(`should have the 'docs' title`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('docs'); - }); - - it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain('Hello, docs'); - }); -}); diff --git a/examples/with-angular/apps/web/.editorconfig b/examples/with-angular/apps/web/.editorconfig deleted file mode 100644 index 59d9a3a3e73ff..0000000000000 --- a/examples/with-angular/apps/web/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/examples/with-angular/apps/web/.eslintrc.json b/examples/with-angular/apps/web/.eslintrc.json deleted file mode 100644 index 909a26b4e26b8..0000000000000 --- a/examples/with-angular/apps/web/.eslintrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "root": true, - "extends": ["@repo/eslint-config/angular.js"] -} diff --git a/examples/with-angular/apps/web/.vscode/extensions.json b/examples/with-angular/apps/web/.vscode/extensions.json deleted file mode 100644 index 77b374577de83..0000000000000 --- a/examples/with-angular/apps/web/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 - "recommendations": ["angular.ng-template"] -} diff --git a/examples/with-angular/apps/web/.vscode/launch.json b/examples/with-angular/apps/web/.vscode/launch.json deleted file mode 100644 index 925af837050a4..0000000000000 --- a/examples/with-angular/apps/web/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "ng serve", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: start", - "url": "http://localhost:4200/" - }, - { - "name": "ng test", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: test", - "url": "http://localhost:9876/debug.html" - } - ] -} diff --git a/examples/with-angular/apps/web/.vscode/tasks.json b/examples/with-angular/apps/web/.vscode/tasks.json deleted file mode 100644 index a298b5bd8796a..0000000000000 --- a/examples/with-angular/apps/web/.vscode/tasks.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "start", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - }, - { - "type": "npm", - "script": "test", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - } - ] -} diff --git a/examples/with-angular/apps/web/README.md b/examples/with-angular/apps/web/README.md deleted file mode 100644 index 06c065b8f687e..0000000000000 --- a/examples/with-angular/apps/web/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Web - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.7. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/examples/with-angular/apps/web/src/app/app.component.css b/examples/with-angular/apps/web/Source/app/app.component.css similarity index 100% rename from examples/with-angular/apps/web/src/app/app.component.css rename to examples/with-angular/apps/web/Source/app/app.component.css diff --git a/examples/with-angular/apps/web/src/app/app.component.html b/examples/with-angular/apps/web/Source/app/app.component.html similarity index 100% rename from examples/with-angular/apps/web/src/app/app.component.html rename to examples/with-angular/apps/web/Source/app/app.component.html diff --git a/examples/with-angular/apps/web/src/app/app.component.ts b/examples/with-angular/apps/web/Source/app/app.component.ts similarity index 100% rename from examples/with-angular/apps/web/src/app/app.component.ts rename to examples/with-angular/apps/web/Source/app/app.component.ts diff --git a/examples/with-angular/apps/web/src/app/app.config.ts b/examples/with-angular/apps/web/Source/app/app.config.ts similarity index 100% rename from examples/with-angular/apps/web/src/app/app.config.ts rename to examples/with-angular/apps/web/Source/app/app.config.ts diff --git a/examples/with-angular/apps/web/src/app/app.routes.ts b/examples/with-angular/apps/web/Source/app/app.routes.ts similarity index 100% rename from examples/with-angular/apps/web/src/app/app.routes.ts rename to examples/with-angular/apps/web/Source/app/app.routes.ts diff --git a/turborepo-tests/integration/fixtures/inference/has_workspaces/packages/ui-library/src/.gitkeep b/examples/with-angular/apps/web/Source/assets/.gitkeep similarity index 100% rename from turborepo-tests/integration/fixtures/inference/has_workspaces/packages/ui-library/src/.gitkeep rename to examples/with-angular/apps/web/Source/assets/.gitkeep diff --git a/examples/with-angular/apps/web/src/favicon.ico b/examples/with-angular/apps/web/Source/favicon.ico similarity index 100% rename from examples/with-angular/apps/web/src/favicon.ico rename to examples/with-angular/apps/web/Source/favicon.ico diff --git a/examples/with-angular/apps/web/src/index.html b/examples/with-angular/apps/web/Source/index.html similarity index 100% rename from examples/with-angular/apps/web/src/index.html rename to examples/with-angular/apps/web/Source/index.html diff --git a/examples/with-angular/apps/web/src/main.ts b/examples/with-angular/apps/web/Source/main.ts similarity index 100% rename from examples/with-angular/apps/web/src/main.ts rename to examples/with-angular/apps/web/Source/main.ts diff --git a/examples/with-angular/apps/web/src/styles.css b/examples/with-angular/apps/web/Source/styles.css similarity index 100% rename from examples/with-angular/apps/web/src/styles.css rename to examples/with-angular/apps/web/Source/styles.css diff --git a/examples/with-angular/apps/web/package.json b/examples/with-angular/apps/web/package.json index 828755afcb8e9..88f308674a52e 100644 --- a/examples/with-angular/apps/web/package.json +++ b/examples/with-angular/apps/web/package.json @@ -1,50 +1,40 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "ng": "ng", - "start": "ng serve --host 0.0.0.0 --port 4201", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "lint": "eslint . --max-warnings 0", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .angular" - }, - "dependencies": { - "@angular/animations": "^17.3.0", - "@angular/common": "^17.3.0", - "@angular/compiler": "^17.3.0", - "@angular/core": "^17.3.0", - "@angular/forms": "^17.3.0", - "@angular/platform-browser": "^17.3.0", - "@angular/platform-browser-dynamic": "^17.3.0", - "@angular/router": "^17.3.0", - "@repo/ui": "workspace:*", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.14.3" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^17.3.7", - "@angular-eslint/builder": "17.4.0", - "@angular-eslint/eslint-plugin": "17.4.0", - "@angular-eslint/eslint-plugin-template": "17.4.0", - "@angular-eslint/schematics": "17.4.0", - "@angular-eslint/template-parser": "17.4.0", - "@angular/cli": "^17.3.7", - "@angular/compiler-cli": "^17.3.0", - "@repo/eslint-config": "workspace:*", - "@types/jasmine": "~5.1.0", - "@typescript-eslint/eslint-plugin": "7.8.0", - "@typescript-eslint/parser": "7.8.0", - "eslint": "^8.57.0", - "jasmine-core": "~5.1.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.4.2" - } + "name": "web", + "scripts": { + "build": "ng build", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .angular", + "ng": "ng", + "start": "ng serve --host 0.0.0.0 --port 4201" + }, + "dependencies": { + "@angular/animations": "19.1.6", + "@angular/common": "19.1.6", + "@angular/compiler": "19.1.6", + "@angular/core": "19.1.6", + "@angular/forms": "19.1.6", + "@angular/platform-browser": "19.1.6", + "@angular/platform-browser-dynamic": "19.1.6", + "@angular/router": "19.1.6", + "@repo/ui": "workspace:*", + "rxjs": "7.8.1", + "tslib": "2.8.1", + "zone.js": "0.15.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "19.1.7", + "@angular-eslint/builder": "19.1.0", + "@angular-eslint/eslint-plugin": "19.1.0", + "@angular-eslint/eslint-plugin-template": "19.1.0", + "@angular-eslint/schematics": "19.1.0", + "@angular-eslint/template-parser": "19.1.0", + "@angular/cli": "19.1.7", + "@angular/compiler-cli": "19.1.6", + "@repo/eslint-config": "workspace:*", + "@types/jasmine": "5.1.5", + "jasmine-core": "5.6.0", + "karma": "6.4.4", + "karma-coverage": "2.2.1", + "karma-jasmine": "5.1.0", + "karma-jasmine-html-reporter": "2.1.0" + } } diff --git a/examples/with-angular/apps/web/src/app/app.component.spec.ts b/examples/with-angular/apps/web/src/app/app.component.spec.ts deleted file mode 100644 index cc7f295547634..0000000000000 --- a/examples/with-angular/apps/web/src/app/app.component.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [AppComponent] - }).compileComponents(); - }); - - it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app).toBeTruthy(); - }); - - it(`should have the 'web' title`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('web'); - }); - - it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain('Hello, web'); - }); -}); diff --git a/examples/with-angular/package.json b/examples/with-angular/package.json index 9cc8109b04bf5..a8f889db5f0b4 100644 --- a/examples/with-angular/package.json +++ b/examples/with-angular/package.json @@ -1,19 +1,11 @@ { - "name": "with-angular", - "private": true, - "scripts": { - "build": "turbo run build", - "lint": "turbo run lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "engines": { - "node": ">=18" - }, - "packageManager": "pnpm@8.14.0", - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "eslint": "^8.57.0", - "prettier": "^2.8.8", - "turbo": "^2.3.3" - } + "name": "with-angular", + "scripts": { + "build": "turbo run build" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "turbo": "2.4.2" + } } diff --git a/examples/with-angular/packages/eslint-config/README.md b/examples/with-angular/packages/eslint-config/README.md deleted file mode 100644 index 414e5e76a7e9c..0000000000000 --- a/examples/with-angular/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @turbo/eslint-config - -Collection of internal eslint configurations. diff --git a/examples/with-angular/packages/eslint-config/package.json b/examples/with-angular/packages/eslint-config/package.json index c9a779d4dcaef..0075d825b4883 100644 --- a/examples/with-angular/packages/eslint-config/package.json +++ b/examples/with-angular/packages/eslint-config/package.json @@ -1,18 +1,13 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "angular.js" - ], - "description": "", - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.9.0", - "@typescript-eslint/parser": "^7.9.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.3.3", - "eslint-plugin-only-warn": "^1.1.0", - "typescript": "~5.4.2" - } + "name": "@repo/eslint-config", + "description": "", + "files": [ + "library.js", + "angular.js" + ], + "dependencies": {}, + "devDependencies": { + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-angular/packages/ui/.editorconfig b/examples/with-angular/packages/ui/.editorconfig deleted file mode 100644 index 59d9a3a3e73ff..0000000000000 --- a/examples/with-angular/packages/ui/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/examples/with-angular/packages/ui/.eslintrc.js b/examples/with-angular/packages/ui/.eslintrc.js deleted file mode 100644 index 4d75081b226ab..0000000000000 --- a/examples/with-angular/packages/ui/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ['@repo/eslint-config/library.js'] -}; diff --git a/examples/with-angular/packages/ui/.vscode/extensions.json b/examples/with-angular/packages/ui/.vscode/extensions.json deleted file mode 100644 index 77b374577de83..0000000000000 --- a/examples/with-angular/packages/ui/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 - "recommendations": ["angular.ng-template"] -} diff --git a/examples/with-angular/packages/ui/.vscode/launch.json b/examples/with-angular/packages/ui/.vscode/launch.json deleted file mode 100644 index 925af837050a4..0000000000000 --- a/examples/with-angular/packages/ui/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "ng serve", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: start", - "url": "http://localhost:4200/" - }, - { - "name": "ng test", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: test", - "url": "http://localhost:9876/debug.html" - } - ] -} diff --git a/examples/with-angular/packages/ui/.vscode/tasks.json b/examples/with-angular/packages/ui/.vscode/tasks.json deleted file mode 100644 index a298b5bd8796a..0000000000000 --- a/examples/with-angular/packages/ui/.vscode/tasks.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "start", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - }, - { - "type": "npm", - "script": "test", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - } - ] -} diff --git a/examples/with-angular/packages/ui/README.md b/examples/with-angular/packages/ui/README.md deleted file mode 100644 index 8a8d26fe4f14e..0000000000000 --- a/examples/with-angular/packages/ui/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Ui - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.7. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/examples/with-angular/packages/ui/package.json b/examples/with-angular/packages/ui/package.json index 350eff342cb99..693484686f089 100644 --- a/examples/with-angular/packages/ui/package.json +++ b/examples/with-angular/packages/ui/package.json @@ -1,42 +1,35 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "private": true, - "main": "./dist/ui/fesm2022/ui.mjs", - "types": "./dist/ui/index.d.ts", - "scripts": { - "ng": "ng", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "lint": "eslint --max-warnings 0", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .angular" - }, - "dependencies": { - "@angular/animations": "^17.3.0", - "@angular/common": "^17.3.0", - "@angular/compiler": "^17.3.0", - "@angular/core": "^17.3.0", - "@angular/forms": "^17.3.0", - "@angular/platform-browser": "^17.3.0", - "@angular/platform-browser-dynamic": "^17.3.0", - "@angular/router": "^17.3.0", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.14.3" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^17.3.7", - "@angular/cli": "^17.3.7", - "@angular/compiler-cli": "^17.3.0", - "@types/jasmine": "~5.1.0", - "jasmine-core": "~5.1.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "ng-packagr": "^17.3.0", - "typescript": "~5.4.2" - } + "name": "@repo/ui", + "main": "./dist/ui/fesm2022/ui.mjs", + "types": "./dist/ui/index.d.ts", + "scripts": { + "build": "ng build", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .angular", + "ng": "ng" + }, + "dependencies": { + "@angular/animations": "19.1.6", + "@angular/common": "19.1.6", + "@angular/compiler": "19.1.6", + "@angular/core": "19.1.6", + "@angular/forms": "19.1.6", + "@angular/platform-browser": "19.1.6", + "@angular/platform-browser-dynamic": "19.1.6", + "@angular/router": "19.1.6", + "rxjs": "7.8.1", + "tslib": "2.8.1", + "zone.js": "0.15.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "19.1.7", + "@angular/cli": "19.1.7", + "@angular/compiler-cli": "19.1.6", + "@types/jasmine": "5.1.5", + "jasmine-core": "5.6.0", + "karma": "6.4.4", + "karma-coverage": "2.2.1", + "karma-jasmine": "5.1.0", + "karma-jasmine-html-reporter": "2.1.0", + "ng-packagr": "19.1.2" + } } diff --git a/examples/with-angular/packages/ui/projects/ui/README.md b/examples/with-angular/packages/ui/projects/ui/README.md deleted file mode 100644 index 4ee757d9a2799..0000000000000 --- a/examples/with-angular/packages/ui/projects/ui/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Ui - -This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.0. - -## Code scaffolding - -Run `ng generate component component-name --project ui` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ui`. - -> Note: Don't forget to add `--project ui` or else it will be added to the default project in your `angular.json` file. - -## Build - -Run `ng build ui` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Publishing - -After building your library with `ng build ui`, go to the dist folder `cd dist/ui` and run `npm publish`. - -## Running unit tests - -Run `ng test ui` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.css b/examples/with-angular/packages/ui/projects/ui/Source/lib/my-counter-button/my-counter-button.component.css similarity index 100% rename from examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.css rename to examples/with-angular/packages/ui/projects/ui/Source/lib/my-counter-button/my-counter-button.component.css diff --git a/examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.html b/examples/with-angular/packages/ui/projects/ui/Source/lib/my-counter-button/my-counter-button.component.html similarity index 100% rename from examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.html rename to examples/with-angular/packages/ui/projects/ui/Source/lib/my-counter-button/my-counter-button.component.html diff --git a/examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.ts b/examples/with-angular/packages/ui/projects/ui/Source/lib/my-counter-button/my-counter-button.component.ts similarity index 100% rename from examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.ts rename to examples/with-angular/packages/ui/projects/ui/Source/lib/my-counter-button/my-counter-button.component.ts diff --git a/examples/with-angular/packages/ui/projects/ui/src/public-api.ts b/examples/with-angular/packages/ui/projects/ui/Source/public-api.ts similarity index 100% rename from examples/with-angular/packages/ui/projects/ui/src/public-api.ts rename to examples/with-angular/packages/ui/projects/ui/Source/public-api.ts diff --git a/examples/with-angular/packages/ui/projects/ui/package.json b/examples/with-angular/packages/ui/projects/ui/package.json index 2f190f192dc36..1b4ec197ddbdd 100644 --- a/examples/with-angular/packages/ui/projects/ui/package.json +++ b/examples/with-angular/packages/ui/projects/ui/package.json @@ -1,12 +1,8 @@ { - "name": "ui", - "version": "0.0.1", - "peerDependencies": { - "@angular/common": "^17.3.0", - "@angular/core": "^17.3.0" - }, - "dependencies": { - "tslib": "^2.3.0" - }, - "sideEffects": false + "name": "ui", + "sideEffects": false, + "dependencies": { + "tslib": "2.8.1" + }, + "devDependencies": {} } diff --git a/examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.spec.ts b/examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.spec.ts deleted file mode 100644 index fb0797bbc6584..0000000000000 --- a/examples/with-angular/packages/ui/projects/ui/src/lib/my-counter-button/my-counter-button.component.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { MyCounterButtonComponent } from './my-counter-button.component'; - -describe('MyCounterButtonComponent', () => { - let component: MyCounterButtonComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [MyCounterButtonComponent] - }).compileComponents(); - - fixture = TestBed.createComponent(MyCounterButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/examples/with-angular/pnpm-lock.yaml b/examples/with-angular/pnpm-lock.yaml deleted file mode 100644 index 43270f433d3a8..0000000000000 --- a/examples/with-angular/pnpm-lock.yaml +++ /dev/null @@ -1,9587 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:packages/eslint-config - eslint: - specifier: ^8.57.0 - version: 8.57.0 - prettier: - specifier: ^2.8.8 - version: 2.8.8 - turbo: - specifier: ^2.3.3 - version: 2.3.3 - - apps/docs: - dependencies: - '@angular/animations': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8) - '@angular/common': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) - '@angular/compiler': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8) - '@angular/core': - specifier: ^17.3.0 - version: 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - '@angular/forms': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) - '@angular/platform-browser': - specifier: ^17.3.0 - version: 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) - '@angular/platform-browser-dynamic': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/compiler@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8) - '@angular/router': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - rxjs: - specifier: ~7.8.0 - version: 7.8.1 - tslib: - specifier: ^2.3.0 - version: 2.6.2 - zone.js: - specifier: ~0.14.3 - version: 0.14.5 - devDependencies: - '@angular-devkit/build-angular': - specifier: ^17.3.7 - version: 17.3.7(@angular/compiler-cli@17.3.8)(karma@6.4.3)(ng-packagr@17.3.0)(typescript@5.4.5) - '@angular-eslint/builder': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/eslint-plugin': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/eslint-plugin-template': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/schematics': - specifier: 17.4.0 - version: 17.4.0(@angular/cli@17.3.7)(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/template-parser': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular/cli': - specifier: ^17.3.7 - version: 17.3.7 - '@angular/compiler-cli': - specifier: ^17.3.0 - version: 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@types/jasmine': - specifier: ~5.1.0 - version: 5.1.4 - '@typescript-eslint/eslint-plugin': - specifier: 7.8.0 - version: 7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: 7.8.0 - version: 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - jasmine-core: - specifier: ~5.1.0 - version: 5.1.2 - karma: - specifier: ~6.4.0 - version: 6.4.3 - karma-chrome-launcher: - specifier: ~3.2.0 - version: 3.2.0 - karma-coverage: - specifier: ~2.2.0 - version: 2.2.1 - karma-jasmine: - specifier: ~5.1.0 - version: 5.1.0(karma@6.4.3) - karma-jasmine-html-reporter: - specifier: ~2.1.0 - version: 2.1.0(jasmine-core@5.1.2)(karma-jasmine@5.1.0)(karma@6.4.3) - typescript: - specifier: ~5.4.2 - version: 5.4.5 - - apps/web: - dependencies: - '@angular/animations': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8) - '@angular/common': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) - '@angular/compiler': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8) - '@angular/core': - specifier: ^17.3.0 - version: 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - '@angular/forms': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) - '@angular/platform-browser': - specifier: ^17.3.0 - version: 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) - '@angular/platform-browser-dynamic': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/compiler@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8) - '@angular/router': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - rxjs: - specifier: ~7.8.0 - version: 7.8.1 - tslib: - specifier: ^2.3.0 - version: 2.6.2 - zone.js: - specifier: ~0.14.3 - version: 0.14.5 - devDependencies: - '@angular-devkit/build-angular': - specifier: ^17.3.7 - version: 17.3.7(@angular/compiler-cli@17.3.8)(karma@6.4.3)(ng-packagr@17.3.0)(typescript@5.4.5) - '@angular-eslint/builder': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/eslint-plugin': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/eslint-plugin-template': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/schematics': - specifier: 17.4.0 - version: 17.4.0(@angular/cli@17.3.7)(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/template-parser': - specifier: 17.4.0 - version: 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular/cli': - specifier: ^17.3.7 - version: 17.3.7 - '@angular/compiler-cli': - specifier: ^17.3.0 - version: 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@types/jasmine': - specifier: ~5.1.0 - version: 5.1.4 - '@typescript-eslint/eslint-plugin': - specifier: 7.8.0 - version: 7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: 7.8.0 - version: 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - jasmine-core: - specifier: ~5.1.0 - version: 5.1.2 - karma: - specifier: ~6.4.0 - version: 6.4.3 - karma-chrome-launcher: - specifier: ~3.2.0 - version: 3.2.0 - karma-coverage: - specifier: ~2.2.0 - version: 2.2.1 - karma-jasmine: - specifier: ~5.1.0 - version: 5.1.0(karma@6.4.3) - karma-jasmine-html-reporter: - specifier: ~2.1.0 - version: 2.1.0(jasmine-core@5.1.2)(karma-jasmine@5.1.0)(karma@6.4.3) - typescript: - specifier: ~5.4.2 - version: 5.4.5 - - packages/eslint-config: - devDependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.9.0 - version: 7.9.0(@typescript-eslint/parser@7.9.0)(eslint@8.57.1)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^7.9.0 - version: 7.9.0(eslint@8.57.1)(typescript@5.4.5) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.1) - eslint-config-turbo: - specifier: ^2.3.3 - version: 2.3.3(eslint@8.57.1) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - typescript: - specifier: ~5.4.2 - version: 5.4.5 - - packages/ui: - dependencies: - '@angular/animations': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8) - '@angular/common': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) - '@angular/compiler': - specifier: ^17.3.0 - version: 17.3.8(@angular/core@17.3.8) - '@angular/core': - specifier: ^17.3.0 - version: 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - '@angular/forms': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) - '@angular/platform-browser': - specifier: ^17.3.0 - version: 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) - '@angular/platform-browser-dynamic': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/compiler@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8) - '@angular/router': - specifier: ^17.3.0 - version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) - rxjs: - specifier: ~7.8.0 - version: 7.8.1 - tslib: - specifier: ^2.3.0 - version: 2.6.2 - zone.js: - specifier: ~0.14.3 - version: 0.14.5 - devDependencies: - '@angular-devkit/build-angular': - specifier: ^17.3.7 - version: 17.3.7(@angular/compiler-cli@17.3.8)(karma@6.4.3)(ng-packagr@17.3.0)(typescript@5.4.5) - '@angular/cli': - specifier: ^17.3.7 - version: 17.3.7 - '@angular/compiler-cli': - specifier: ^17.3.0 - version: 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) - '@types/jasmine': - specifier: ~5.1.0 - version: 5.1.4 - jasmine-core: - specifier: ~5.1.0 - version: 5.1.2 - karma: - specifier: ~6.4.0 - version: 6.4.3 - karma-chrome-launcher: - specifier: ~3.2.0 - version: 3.2.0 - karma-coverage: - specifier: ~2.2.0 - version: 2.2.1 - karma-jasmine: - specifier: ~5.1.0 - version: 5.1.0(karma@6.4.3) - karma-jasmine-html-reporter: - specifier: ~2.1.0 - version: 2.1.0(jasmine-core@5.1.2)(karma-jasmine@5.1.0)(karma@6.4.3) - ng-packagr: - specifier: ^17.3.0 - version: 17.3.0(@angular/compiler-cli@17.3.8)(tslib@2.6.2)(typescript@5.4.5) - typescript: - specifier: ~5.4.2 - version: 5.4.5 - -packages: - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@angular-devkit/architect@0.1703.7: - resolution: {integrity: sha512-SwXbdsZqEE3JtvujCLChAii+FA20d1931VDjDYffrGWdQEViTBAr4NKtDr/kOv8KkgiL3fhGibPnRNUHTeAMtg==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - dependencies: - '@angular-devkit/core': 17.3.7 - rxjs: 7.8.1 - transitivePeerDependencies: - - chokidar - dev: true - - /@angular-devkit/build-angular@17.3.7(@angular/compiler-cli@17.3.8)(karma@6.4.3)(ng-packagr@17.3.0)(typescript@5.4.5): - resolution: {integrity: sha512-AsV80kiFMIPIhm3uzJgOHDj4u6JteUkZedPTKAFFFJC7CTat1luW5qx306vfF7wj62aMvUl5g9HFWaeLghTQGA==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - '@angular/compiler-cli': ^17.0.0 - '@angular/localize': ^17.0.0 - '@angular/platform-server': ^17.0.0 - '@angular/service-worker': ^17.0.0 - '@web/test-runner': ^0.18.0 - browser-sync: ^3.0.2 - jest: ^29.5.0 - jest-environment-jsdom: ^29.5.0 - karma: ^6.3.0 - ng-packagr: ^17.0.0 - protractor: ^7.0.0 - tailwindcss: ^2.0.0 || ^3.0.0 - typescript: '>=5.2 <5.5' - peerDependenciesMeta: - '@angular/localize': - optional: true - '@angular/platform-server': - optional: true - '@angular/service-worker': - optional: true - '@web/test-runner': - optional: true - browser-sync: - optional: true - jest: - optional: true - jest-environment-jsdom: - optional: true - karma: - optional: true - ng-packagr: - optional: true - protractor: - optional: true - tailwindcss: - optional: true - dependencies: - '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.1703.7 - '@angular-devkit/build-webpack': 0.1703.7(webpack-dev-server@4.15.1)(webpack@5.90.3) - '@angular-devkit/core': 17.3.7 - '@angular/compiler-cli': 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) - '@babel/core': 7.24.0 - '@babel/generator': 7.23.6 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/plugin-transform-async-generator-functions': 7.23.9(@babel/core@7.24.0) - '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-runtime': 7.24.0(@babel/core@7.24.0) - '@babel/preset-env': 7.24.0(@babel/core@7.24.0) - '@babel/runtime': 7.24.0 - '@discoveryjs/json-ext': 0.5.7 - '@ngtools/webpack': 17.3.7(@angular/compiler-cli@17.3.8)(typescript@5.4.5)(webpack@5.90.3) - '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.1.7) - ansi-colors: 4.1.3 - autoprefixer: 10.4.18(postcss@8.4.35) - babel-loader: 9.1.3(@babel/core@7.24.0)(webpack@5.90.3) - babel-plugin-istanbul: 6.1.1 - browserslist: 4.23.0 - copy-webpack-plugin: 11.0.0(webpack@5.90.3) - critters: 0.0.22 - css-loader: 6.10.0(webpack@5.90.3) - esbuild-wasm: 0.20.1 - fast-glob: 3.3.2 - http-proxy-middleware: 2.0.6(@types/express@4.17.21) - https-proxy-agent: 7.0.4 - inquirer: 9.2.15 - jsonc-parser: 3.2.1 - karma: 6.4.3 - karma-source-map-support: 1.4.0 - less: 4.2.0 - less-loader: 11.1.0(less@4.2.0)(webpack@5.90.3) - license-webpack-plugin: 4.0.2(webpack@5.90.3) - loader-utils: 3.2.1 - magic-string: 0.30.8 - mini-css-extract-plugin: 2.8.1(webpack@5.90.3) - mrmime: 2.0.0 - ng-packagr: 17.3.0(@angular/compiler-cli@17.3.8)(tslib@2.6.2)(typescript@5.4.5) - open: 8.4.2 - ora: 5.4.1 - parse5-html-rewriting-stream: 7.0.0 - picomatch: 4.0.1 - piscina: 4.4.0 - postcss: 8.4.35 - postcss-loader: 8.1.1(postcss@8.4.35)(typescript@5.4.5)(webpack@5.90.3) - resolve-url-loader: 5.0.0 - rxjs: 7.8.1 - sass: 1.71.1 - sass-loader: 14.1.1(sass@1.71.1)(webpack@5.90.3) - semver: 7.6.0 - source-map-loader: 5.0.0(webpack@5.90.3) - source-map-support: 0.5.21 - terser: 5.29.1 - tree-kill: 1.2.2 - tslib: 2.6.2 - typescript: 5.4.5 - undici: 6.11.1 - vite: 5.1.7(less@4.2.0)(sass@1.71.1)(terser@5.29.1) - watchpack: 2.4.0 - webpack: 5.90.3(esbuild@0.20.1) - webpack-dev-middleware: 6.1.2(webpack@5.90.3) - webpack-dev-server: 4.15.1(webpack@5.90.3) - webpack-merge: 5.10.0 - webpack-subresource-integrity: 5.1.0(webpack@5.90.3) - optionalDependencies: - esbuild: 0.20.1 - transitivePeerDependencies: - - '@rspack/core' - - '@swc/core' - - '@types/express' - - '@types/node' - - bufferutil - - chokidar - - debug - - html-webpack-plugin - - lightningcss - - node-sass - - sass-embedded - - stylus - - sugarss - - supports-color - - uglify-js - - utf-8-validate - - webpack-cli - dev: true - - /@angular-devkit/build-webpack@0.1703.7(webpack-dev-server@4.15.1)(webpack@5.90.3): - resolution: {integrity: sha512-gpt2Ia5I1gmdp3hdbtB7tkZTba5qWmKeVhlCYswa/LvbceKmkjedoeNRAoyr1UKM9GeGqt6Xl1B2eHzCH+ykrg==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - webpack: ^5.30.0 - webpack-dev-server: ^4.0.0 - dependencies: - '@angular-devkit/architect': 0.1703.7 - rxjs: 7.8.1 - webpack: 5.90.3(esbuild@0.20.1) - webpack-dev-server: 4.15.1(webpack@5.90.3) - transitivePeerDependencies: - - chokidar - dev: true - - /@angular-devkit/core@17.3.7: - resolution: {integrity: sha512-qpZ7BShyqS/Jqld36E7kL02cyb2pjn1Az1p9439SbP8nsvJgYlsyjwYK2Kmcn/Wi+TZGIKxkqxgBBw9vqGgeJw==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - chokidar: ^3.5.2 - peerDependenciesMeta: - chokidar: - optional: true - dependencies: - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - jsonc-parser: 3.2.1 - picomatch: 4.0.1 - rxjs: 7.8.1 - source-map: 0.7.4 - dev: true - - /@angular-devkit/schematics@17.3.7: - resolution: {integrity: sha512-d7NKSwstdxYLYmPsbcYO3GOFNfXxXwOyHxSqDa1JNKoSzMdbLj4tvlCpfXw0ThNM7gioMx8aLBaaH1ac+yk06Q==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - dependencies: - '@angular-devkit/core': 17.3.7 - jsonc-parser: 3.2.1 - magic-string: 0.30.8 - ora: 5.4.1 - rxjs: 7.8.1 - transitivePeerDependencies: - - chokidar - dev: true - - /@angular-eslint/builder@17.4.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-+3ujbi+ar/iqAAwnJ2bTdWzQpHh9iVEPgjHUOeQhrEM8gcaOLnZXMlUyZL7D+NlXg7aDoEIxETb73dgbIBm55A==} - peerDependencies: - eslint: ^7.20.0 || ^8.0.0 - typescript: '*' - dependencies: - '@nx/devkit': 18.3.4(nx@18.3.4) - eslint: 8.57.0 - nx: 18.3.4 - typescript: 5.4.5 - transitivePeerDependencies: - - '@swc-node/register' - - '@swc/core' - - debug - dev: true - - /@angular-eslint/bundled-angular-compiler@17.4.0: - resolution: {integrity: sha512-cYEJs4PO+QLDt1wfgWh9q8OjOphnoe1OTTFtMqm9lHl0AkBynPnFA6ghiiG5NaT03l7HXi2TQ23rLFlXl3JOBg==} - dev: true - - /@angular-eslint/eslint-plugin-template@17.4.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-o1Vb7rt3TpPChVzaxswOKBDWRboMcpC4qUUyoHfeSYa7sDuQHMeIQlCS5QXuykR/RYnIQJSKd89FOd28nGmmRw==} - peerDependencies: - eslint: ^7.20.0 || ^8.0.0 - typescript: '*' - dependencies: - '@angular-eslint/bundled-angular-compiler': 17.4.0 - '@angular-eslint/utils': 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/type-utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - aria-query: 5.3.0 - axobject-query: 4.0.0 - eslint: 8.57.0 - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@angular-eslint/eslint-plugin@17.4.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-E+/O83PXttQUACurGEskLDU+wboBqMMVqvo4T8C/iMcpLx+01M5UBzqpCmfz6ri609G96Au7uDbUEedU1hwqmQ==} - peerDependencies: - eslint: ^7.20.0 || ^8.0.0 - typescript: '*' - dependencies: - '@angular-eslint/bundled-angular-compiler': 17.4.0 - '@angular-eslint/utils': 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@angular-eslint/schematics@17.4.0(@angular/cli@17.3.7)(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-3WQQbwwBD1N3dZbbx1a1KY/jRujUQgz5778Ac21LU+AdCtvbjnmSpxRfsE3HH8MAreqr8Lv1kjLyiRzPTS5GQQ==} - peerDependencies: - '@angular/cli': '>= 17.0.0 < 18.0.0' - dependencies: - '@angular-eslint/eslint-plugin': 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular-eslint/eslint-plugin-template': 17.4.0(eslint@8.57.0)(typescript@5.4.5) - '@angular/cli': 17.3.7 - '@nx/devkit': 18.3.4(nx@18.3.4) - ignore: 5.3.1 - nx: 18.3.4 - strip-json-comments: 3.1.1 - tmp: 0.2.3 - transitivePeerDependencies: - - '@swc-node/register' - - '@swc/core' - - debug - - eslint - - supports-color - - typescript - dev: true - - /@angular-eslint/template-parser@17.4.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-vT/Tg8dl6Uy++MS9lPS0l37SynH3EaMcggDiTJqn15pIb4ePO65fafOIIKKYG+BN6R6iFe/g9mH/9nb8ohlzdQ==} - peerDependencies: - eslint: ^7.20.0 || ^8.0.0 - typescript: '*' - dependencies: - '@angular-eslint/bundled-angular-compiler': 17.4.0 - eslint: 8.57.0 - eslint-scope: 8.0.1 - typescript: 5.4.5 - dev: true - - /@angular-eslint/utils@17.4.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-lHgRXyT878fauDITygraICDM6RHLb51QAJ3gWNZLr7SXcywsZg5d3rxRPCjrCnjgdxNPU0fJ+VJZ5AMt5Ibn7w==} - peerDependencies: - eslint: ^7.20.0 || ^8.0.0 - typescript: '*' - dependencies: - '@angular-eslint/bundled-angular-compiler': 17.4.0 - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@angular/animations@17.3.8(@angular/core@17.3.8): - resolution: {integrity: sha512-ywT3dH0yZeAlo+Vu/6RpRozxzTbu4Bwqky6RgNfk/UMoyXZ5UiFStszDqO/HAyBGGCDHagm1XJkgsNZcStWq8A==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - '@angular/core': 17.3.8 - dependencies: - '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - tslib: 2.6.2 - dev: false - - /@angular/cli@17.3.7: - resolution: {integrity: sha512-JgCav3sdRCoJHwLXxmF/EMzArYjwbqB+AGUW/xIR98oZET8QxCB985bOFUAm02SkAEUVcMJvjxec+WCaa60m/A==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - hasBin: true - dependencies: - '@angular-devkit/architect': 0.1703.7 - '@angular-devkit/core': 17.3.7 - '@angular-devkit/schematics': 17.3.7 - '@schematics/angular': 17.3.7 - '@yarnpkg/lockfile': 1.1.0 - ansi-colors: 4.1.3 - ini: 4.1.2 - inquirer: 9.2.15 - jsonc-parser: 3.2.1 - npm-package-arg: 11.0.1 - npm-pick-manifest: 9.0.0 - open: 8.4.2 - ora: 5.4.1 - pacote: 17.0.6 - resolve: 1.22.8 - semver: 7.6.0 - symbol-observable: 4.0.0 - yargs: 17.7.2 - transitivePeerDependencies: - - bluebird - - chokidar - - supports-color - dev: true - - /@angular/common@17.3.8(@angular/core@17.3.8)(rxjs@7.8.1): - resolution: {integrity: sha512-HEhTibrsWmoKilyhvAFmqg4SH1hWBP3eV9Y689lmsxBQCTRAmRI2pMAoRKQ+dBcoYLE/FZhcmdHJUSl5jR7Isg==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - '@angular/core': 17.3.8 - rxjs: ^6.5.3 || ^7.4.0 - dependencies: - '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - rxjs: 7.8.1 - tslib: 2.6.2 - dev: false - - /@angular/compiler-cli@17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5): - resolution: {integrity: sha512-/TsbCmk7QJUEEZnRdNzi6znsPfoDJuy6vHDqcwWVEcw7y6W7DjirSFmtT9u1QwrV67KM6kOh22+RvPdGM8sPmg==} - engines: {node: ^18.13.0 || >=20.9.0} - hasBin: true - peerDependencies: - '@angular/compiler': 17.3.8 - typescript: '>=5.2 <5.5' - dependencies: - '@angular/compiler': 17.3.8(@angular/core@17.3.8) - '@babel/core': 7.23.9 - '@jridgewell/sourcemap-codec': 1.4.15 - chokidar: 3.6.0 - convert-source-map: 1.9.0 - reflect-metadata: 0.2.2 - semver: 7.6.2 - tslib: 2.6.2 - typescript: 5.4.5 - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@angular/compiler@17.3.8(@angular/core@17.3.8): - resolution: {integrity: sha512-7vZSh2Oa95lZdRR4MhE0icvZ7JUuYY+NSo3eTSOMZSlH5I9rtwQoSFqfoGW+35rXCzGFLOhQmZBbXkxDPDs97Q==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - '@angular/core': 17.3.8 - peerDependenciesMeta: - '@angular/core': - optional: true - dependencies: - '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - tslib: 2.6.2 - - /@angular/core@17.3.8(rxjs@7.8.1)(zone.js@0.14.5): - resolution: {integrity: sha512-+tUQ+B1yVvNbczzaWBCgJWWIgZ2z+GVJWu+UNOHHWzdqD8qpXjuIkDfnhyLNeGvvXgsqey4u6ApFf2SoFYLjuA==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - rxjs: ^6.5.3 || ^7.4.0 - zone.js: ~0.14.0 - dependencies: - rxjs: 7.8.1 - tslib: 2.6.2 - zone.js: 0.14.5 - - /@angular/forms@17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1): - resolution: {integrity: sha512-ZoPJMx3O1eKliK6oEUqtKJNqrLwwOLBC5x+zbCHrwJeBB3lbgWXrrnTrFvCXpp3QVERAboZTzZ3XBmHX1o6gmw==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - '@angular/common': 17.3.8 - '@angular/core': 17.3.8 - '@angular/platform-browser': 17.3.8 - rxjs: ^6.5.3 || ^7.4.0 - dependencies: - '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) - '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - '@angular/platform-browser': 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) - rxjs: 7.8.1 - tslib: 2.6.2 - dev: false - - /@angular/platform-browser-dynamic@17.3.8(@angular/common@17.3.8)(@angular/compiler@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8): - resolution: {integrity: sha512-uL6FPh+Pr9xzIjyiv3p66jteq/CytHP1+m5jOsIKa1LUwTXx0a2pmOYcZxXpNkQGR9Ir/dlbrYmKlSP3QZf7uw==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - '@angular/common': 17.3.8 - '@angular/compiler': 17.3.8 - '@angular/core': 17.3.8 - '@angular/platform-browser': 17.3.8 - dependencies: - '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) - '@angular/compiler': 17.3.8(@angular/core@17.3.8) - '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - '@angular/platform-browser': 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) - tslib: 2.6.2 - dev: false - - /@angular/platform-browser@17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8): - resolution: {integrity: sha512-UMGSV3TdJqMtf2xvhbW6fx8TKJLOoHQgFxohhy3y8GvxHBu+PUyrwhovb7r03bs+muY6u4ygGCMm7Mt1TFVwfQ==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - '@angular/animations': 17.3.8 - '@angular/common': 17.3.8 - '@angular/core': 17.3.8 - peerDependenciesMeta: - '@angular/animations': - optional: true - dependencies: - '@angular/animations': 17.3.8(@angular/core@17.3.8) - '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) - '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - tslib: 2.6.2 - dev: false - - /@angular/router@17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1): - resolution: {integrity: sha512-2JKTW1u1H+iNDfAmIjEiMJjQHfzb97TBk23/euIR0JuyGHjyywkrQ97HHiOEAJyy/Zpr0Vbem3HRqDqSfjTWvg==} - engines: {node: ^18.13.0 || >=20.9.0} - peerDependencies: - '@angular/common': 17.3.8 - '@angular/core': 17.3.8 - '@angular/platform-browser': 17.3.8 - rxjs: ^6.5.3 || ^7.4.0 - dependencies: - '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) - '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) - '@angular/platform-browser': 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) - rxjs: 7.8.1 - tslib: 2.6.2 - dev: false - - /@babel/code-frame@7.24.2: - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.5 - picocolors: 1.0.1 - dev: true - - /@babel/compat-data@7.24.4: - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.23.9: - resolution: {integrity: sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.23.9) - '@babel/helpers': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/core@7.24.0: - resolution: {integrity: sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.0) - '@babel/helpers': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/core@7.24.5: - resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helpers': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.23.6: - resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/generator@7.24.5: - resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-create-class-features-plugin@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - semver: 6.3.1 - dev: true - - /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.0): - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - semver: 6.3.1 - dev: true - - /@babel/helper-define-polyfill-provider@0.5.0(@babel/core@7.24.0): - resolution: {integrity: sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.24.0): - resolution: {integrity: sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-member-expression-to-functions@7.24.5: - resolution: {integrity: sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-module-imports@7.24.3: - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-module-transforms@7.24.5(@babel/core@7.23.9): - resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.24.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 - dev: true - - /@babel/helper-module-transforms@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.24.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 - dev: true - - /@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.24.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 - dev: true - - /@babel/helper-optimise-call-expression@7.22.5: - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-plugin-utils@7.24.5: - resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.24.0): - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.24.5 - dev: true - - /@babel/helper-replace-supers@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 - dev: true - - /@babel/helper-simple-access@7.24.5: - resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-skip-transparent-expression-wrappers@7.22.5: - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-split-export-declaration@7.24.5: - resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/helper-string-parser@7.24.1: - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.24.5: - resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-wrap-function@7.24.5: - resolution: {integrity: sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.23.0 - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - dev: true - - /@babel/helpers@7.24.5: - resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.24.5: - resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.5 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.1 - dev: true - - /@babel/parser@7.24.5: - resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.0) - dev: true - - /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.0): - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - dev: true - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.0): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.0): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.0): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.0): - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.0): - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-import-assertions@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.0): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.0): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.0): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.0): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.0): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.0): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.0): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.0): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.0): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.0): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.0): - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-arrow-functions@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-async-generator-functions@7.23.9(@babel/core@7.24.0): - resolution: {integrity: sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.24.0): - resolution: {integrity: sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-block-scoped-functions@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-block-scoping@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-class-properties@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-class-static-block@7.24.4(@babel/core@7.24.0): - resolution: {integrity: sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-classes@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.0) - '@babel/helper-split-export-declaration': 7.24.5 - globals: 11.12.0 - dev: true - - /@babel/plugin-transform-computed-properties@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/template': 7.24.0 - dev: true - - /@babel/plugin-transform-destructuring@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-dotall-regex@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-duplicate-keys@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-dynamic-import@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-exponentiation-operator@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-export-namespace-from@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-for-of@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: true - - /@babel/plugin-transform-function-name@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-json-strings@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-literals@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-logical-assignment-operators@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-member-expression-literals@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-amd@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-simple-access': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-systemjs@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 - dev: true - - /@babel/plugin-transform-modules-umd@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.24.0): - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-new-target@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-nullish-coalescing-operator@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-numeric-separator@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-object-rest-spread@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-object-super@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-optional-catch-binding@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-optional-chaining@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-parameters@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-private-methods@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-private-property-in-object@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.0) - dev: true - - /@babel/plugin-transform-property-literals@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - regenerator-transform: 0.15.2 - dev: true - - /@babel/plugin-transform-reserved-words@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-runtime@7.24.0(@babel/core@7.24.0): - resolution: {integrity: sha512-zc0GA5IitLKJrSfXlXmp8KDqLrnGECK7YRfQBmEKg1NmBOQ7e+KuclBEKJgzifQeUYLdNiAw4B4bjyvzWVLiSA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.5 - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.0) - babel-plugin-polyfill-corejs3: 0.9.0(@babel/core@7.24.0) - babel-plugin-polyfill-regenerator: 0.5.5(@babel/core@7.24.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-shorthand-properties@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-spread@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: true - - /@babel/plugin-transform-sticky-regex@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-template-literals@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-typeof-symbol@7.24.5(@babel/core@7.24.0): - resolution: {integrity: sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-unicode-escapes@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-unicode-property-regex@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-unicode-regex@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-transform-unicode-sets-regex@7.24.1(@babel/core@7.24.0): - resolution: {integrity: sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/preset-env@7.24.0(@babel/core@7.24.0): - resolution: {integrity: sha512-ZxPEzV9IgvGn73iK0E6VB9/95Nd7aMFpbE0l8KQFDG70cOV9IxRP7Y2FUPmlK0v6ImlLqYX50iuZ3ZTVhOF2lA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.0) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.0) - '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-async-generator-functions': 7.23.9(@babel/core@7.24.0) - '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-block-scoping': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-class-static-block': 7.24.4(@babel/core@7.24.0) - '@babel/plugin-transform-classes': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-destructuring': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-dotall-regex': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-duplicate-keys': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-dynamic-import': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-exponentiation-operator': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-export-namespace-from': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-json-strings': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-logical-assignment-operators': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-modules-amd': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-modules-systemjs': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-modules-umd': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.24.0) - '@babel/plugin-transform-new-target': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-numeric-separator': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-object-rest-spread': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-optional-catch-binding': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-private-property-in-object': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-regenerator': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-reserved-words': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-sticky-regex': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-typeof-symbol': 7.24.5(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-escapes': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-property-regex': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-regex': 7.24.1(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-sets-regex': 7.24.1(@babel/core@7.24.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.0) - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.0) - babel-plugin-polyfill-corejs3: 0.9.0(@babel/core@7.24.0) - babel-plugin-polyfill-regenerator: 0.5.5(@babel/core@7.24.0) - core-js-compat: 3.37.1 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.0): - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/types': 7.24.5 - esutils: 2.0.3 - dev: true - - /@babel/regjsgen@0.8.0: - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - dev: true - - /@babel/runtime@7.24.0: - resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - dev: true - - /@babel/traverse@7.24.5: - resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.24.5: - resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 - to-fast-properties: 2.0.0 - dev: true - - /@colors/colors@1.5.0: - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - dev: true - - /@discoveryjs/json-ext@0.5.7: - resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} - engines: {node: '>=10.0.0'} - dev: true - - /@esbuild/aix-ppc64@0.19.12: - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/aix-ppc64@0.20.1: - resolution: {integrity: sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/aix-ppc64@0.20.2: - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.19.12: - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.20.1: - resolution: {integrity: sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.20.2: - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.19.12: - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.20.1: - resolution: {integrity: sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.20.2: - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.19.12: - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.20.1: - resolution: {integrity: sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.20.2: - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.19.12: - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.20.1: - resolution: {integrity: sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.20.2: - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.19.12: - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.20.1: - resolution: {integrity: sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.20.2: - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.19.12: - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.20.1: - resolution: {integrity: sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.20.2: - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.19.12: - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.20.1: - resolution: {integrity: sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.20.2: - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.19.12: - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.20.1: - resolution: {integrity: sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.20.2: - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.19.12: - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.20.1: - resolution: {integrity: sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.20.2: - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.19.12: - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.20.1: - resolution: {integrity: sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.20.2: - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.19.12: - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.20.1: - resolution: {integrity: sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.20.2: - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.19.12: - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.20.1: - resolution: {integrity: sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.20.2: - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.19.12: - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.20.1: - resolution: {integrity: sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.20.2: - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.19.12: - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.20.1: - resolution: {integrity: sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.20.2: - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.19.12: - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.20.1: - resolution: {integrity: sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.20.2: - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.19.12: - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.20.1: - resolution: {integrity: sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.20.2: - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.19.12: - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.20.1: - resolution: {integrity: sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.20.2: - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.19.12: - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.20.1: - resolution: {integrity: sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.20.2: - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.19.12: - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.20.1: - resolution: {integrity: sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.20.2: - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.19.12: - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.20.1: - resolution: {integrity: sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.20.2: - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.19.12: - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.20.1: - resolution: {integrity: sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.20.2: - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.19.12: - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.20.1: - resolution: {integrity: sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.20.2: - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.1): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.1 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/eslint-utils@4.4.1(eslint@8.57.1): - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.1 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint-community/regexpp@4.12.1: - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@eslint/js@8.57.1: - resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/config-array@0.13.0: - resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@istanbuljs/load-nyc-config@1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - dev: true - - /@istanbuljs/schema@0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true - - /@jest/schemas@29.6.3: - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/source-map@0.3.6: - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@leichtgewicht/ip-codec@2.0.5: - resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} - dev: true - - /@ljharb/through@2.3.13: - resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - - /@ngtools/webpack@17.3.7(@angular/compiler-cli@17.3.8)(typescript@5.4.5)(webpack@5.90.3): - resolution: {integrity: sha512-kQNS68jsPQlaWAnKcVeFKNHp6K90uQANvq+9oXb/i+JnYWzuBsHzn2r8bVdMmvjd1HdBRiGtg767XRk3u+jgRw==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - '@angular/compiler-cli': ^17.0.0 - typescript: '>=5.2 <5.5' - webpack: ^5.54.0 - dependencies: - '@angular/compiler-cli': 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) - typescript: 5.4.5 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@npmcli/agent@2.2.2: - resolution: {integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - agent-base: 7.1.1 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.4 - lru-cache: 10.2.2 - socks-proxy-agent: 8.0.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@npmcli/fs@3.1.1: - resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.6.2 - dev: true - - /@npmcli/git@5.0.7: - resolution: {integrity: sha512-WaOVvto604d5IpdCRV2KjQu8PzkfE96d50CQGKgywXh2GxXmDeUO5EWcBC4V57uFyrNqx83+MewuJh3WTR3xPA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/promise-spawn': 7.0.2 - lru-cache: 10.2.2 - npm-pick-manifest: 9.0.0 - proc-log: 4.2.0 - promise-inflight: 1.0.1 - promise-retry: 2.0.1 - semver: 7.6.0 - which: 4.0.0 - transitivePeerDependencies: - - bluebird - dev: true - - /@npmcli/installed-package-contents@2.1.0: - resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - npm-bundled: 3.0.1 - npm-normalize-package-bin: 3.0.1 - dev: true - - /@npmcli/node-gyp@3.0.0: - resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /@npmcli/package-json@5.1.0: - resolution: {integrity: sha512-1aL4TuVrLS9sf8quCLerU3H9J4vtCtgu8VauYozrmEyU57i/EdKleCnsQ7vpnABIH6c9mnTxcH5sFkO3BlV8wQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/git': 5.0.7 - glob: 10.3.15 - hosted-git-info: 7.0.2 - json-parse-even-better-errors: 3.0.2 - normalize-package-data: 6.0.1 - proc-log: 4.2.0 - semver: 7.6.2 - transitivePeerDependencies: - - bluebird - dev: true - - /@npmcli/promise-spawn@7.0.2: - resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - which: 4.0.0 - dev: true - - /@npmcli/redact@1.1.0: - resolution: {integrity: sha512-PfnWuOkQgu7gCbnSsAisaX7hKOdZ4wSAhAzH3/ph5dSGau52kCRrMMGbiSQLwyTZpgldkZ49b0brkOr1AzGBHQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dev: true - - /@npmcli/run-script@7.0.4: - resolution: {integrity: sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/node-gyp': 3.0.0 - '@npmcli/package-json': 5.1.0 - '@npmcli/promise-spawn': 7.0.2 - node-gyp: 10.1.0 - which: 4.0.0 - transitivePeerDependencies: - - bluebird - - supports-color - dev: true - - /@nrwl/devkit@18.3.4(nx@18.3.4): - resolution: {integrity: sha512-Fty9Huqm12OYueU3uLJl3uvBUl5BvEyPfvw8+rLiNx9iftdEattM8C+268eAbIRRSLSOVXlWsJH4brlc6QZYYw==} - dependencies: - '@nx/devkit': 18.3.4(nx@18.3.4) - transitivePeerDependencies: - - nx - dev: true - - /@nrwl/tao@18.3.4: - resolution: {integrity: sha512-+7KsDYmGj1cvNaXZcjSYOPN1h17hsGFBtVX7MqnpJLLkQTUhKg2rQxqyluzshJ+RoDUVtYPGyHg1AizlB66RIA==} - hasBin: true - dependencies: - nx: 18.3.4 - tslib: 2.6.2 - transitivePeerDependencies: - - '@swc-node/register' - - '@swc/core' - - debug - dev: true - - /@nx/devkit@18.3.4(nx@18.3.4): - resolution: {integrity: sha512-M3htxl5WvlNKK5KNOndCAApbyBCZNTFFs+rtdwvudNZk5+84zAAPaWzSoX9C4XLAW78/f98LzF68/ch05aN12A==} - peerDependencies: - nx: '>= 16 <= 19' - dependencies: - '@nrwl/devkit': 18.3.4(nx@18.3.4) - ejs: 3.1.10 - enquirer: 2.3.6 - ignore: 5.3.1 - nx: 18.3.4 - semver: 7.6.2 - tmp: 0.2.3 - tslib: 2.6.2 - yargs-parser: 21.1.1 - dev: true - - /@nx/nx-darwin-arm64@18.3.4: - resolution: {integrity: sha512-MOGk9z4fIoOkJB68diH3bwoWrC8X9IzMNsz1mu0cbVfgCRAfIV3b+lMsiwQYzWal3UWW5DE5Rkss4F8whiV5Uw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-darwin-x64@18.3.4: - resolution: {integrity: sha512-tSzPRnNB3QdPM+KYiIuRCUtyCwcuIRC95FfP0ZB3WvfDeNxJChEAChNqmCMDE4iFvZhGuze8WqkJuIVdte+lyQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-freebsd-x64@18.3.4: - resolution: {integrity: sha512-bjSPak/d+bcR95/pxHMRhnnpHc6MnrQcG6f5AjX15Esm4JdrdQKPBmG1RybuK0WKSyD5wgVhkAGc/QQUom9l8g==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-linux-arm-gnueabihf@18.3.4: - resolution: {integrity: sha512-/1HnUL7jhH0S7PxJqf6R1pk3QlAU22GY89EQV9fd+RDUtp7IyzaTlkebijTIqfxlSjC4OO3bPizaxEaxdd3uKQ==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-linux-arm64-gnu@18.3.4: - resolution: {integrity: sha512-g/2IaB2bZTKaBNPEf9LxtIXb1XHdhh3VO9PnePIrwkkixPMLN0dTxT5Sttt75lvLP3EU1AUR5w3Aaz2Q1mYtWA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-linux-arm64-musl@18.3.4: - resolution: {integrity: sha512-MgfKLoEF6I1cCS+0ooFLEjJSSVdCYyCT9Q96IHRJntAEL8u/0GR2OUoBoLC+q1lnbIkJr/uqTJxA2Jh+sJTIbA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-linux-x64-gnu@18.3.4: - resolution: {integrity: sha512-vbHxv7m3gjthBvw50EYCtgyY0Zg5nVTaQtX+wRsmKybV2i7wHbw5zIe1aL4zHUm6TcPGbIQK+utVM+hyCqKHVA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-linux-x64-musl@18.3.4: - resolution: {integrity: sha512-qIJKJCYFRLVSALsvg3avjReOjuYk91Q0hFXMJ2KaEM1Y3tdzcFN0fKBiaHexgbFIUk8zJuS4dJObTqSYMXowbg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-win32-arm64-msvc@18.3.4: - resolution: {integrity: sha512-UxC8mRkFTPdZbKFprZkiBqVw8624xU38kI0xyooxKlFpt5lccTBwJ0B7+R8p1RoWyvh2DSyFI9VvfD7lczg1lA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@nx/nx-win32-x64-msvc@18.3.4: - resolution: {integrity: sha512-/RqEjNU9hxIBxRLafCNKoH3SaB2FShf+1ZnIYCdAoCZBxLJebDpnhiyrVs0lPnMj9248JbizEMdJj1+bs/bXig==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@rollup/plugin-json@6.1.0(rollup@4.29.1): - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.29.1) - rollup: 4.29.1 - dev: true - - /@rollup/plugin-node-resolve@15.2.3(rollup@4.29.1): - resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.29.1) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-builtin-module: 3.2.1 - is-module: 1.0.0 - resolve: 1.22.8 - rollup: 4.29.1 - dev: true - - /@rollup/pluginutils@5.1.0(rollup@4.29.1): - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 4.29.1 - dev: true - - /@rollup/rollup-android-arm-eabi@4.17.2: - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm-eabi@4.29.1: - resolution: {integrity: sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.17.2: - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.29.1: - resolution: {integrity: sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.17.2: - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.29.1: - resolution: {integrity: sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.17.2: - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.29.1: - resolution: {integrity: sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-freebsd-arm64@4.29.1: - resolution: {integrity: sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-freebsd-x64@4.29.1: - resolution: {integrity: sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.17.2: - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.29.1: - resolution: {integrity: sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-musleabihf@4.17.2: - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-musleabihf@4.29.1: - resolution: {integrity: sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.17.2: - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.29.1: - resolution: {integrity: sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.17.2: - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.29.1: - resolution: {integrity: sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-loongarch64-gnu@4.29.1: - resolution: {integrity: sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-powerpc64le-gnu@4.17.2: - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-powerpc64le-gnu@4.29.1: - resolution: {integrity: sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.17.2: - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.29.1: - resolution: {integrity: sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-s390x-gnu@4.17.2: - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-s390x-gnu@4.29.1: - resolution: {integrity: sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.17.2: - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.29.1: - resolution: {integrity: sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.17.2: - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.29.1: - resolution: {integrity: sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.17.2: - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.29.1: - resolution: {integrity: sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.17.2: - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.29.1: - resolution: {integrity: sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.17.2: - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.29.1: - resolution: {integrity: sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/wasm-node@4.17.2: - resolution: {integrity: sha512-4F6C3XaUn02XY/GJMQTXncWrLyCkRHdRZe4OyWuQUprWKmU2u+esISOtCYdr3Bp9AqCIo/X3So2Ik7N9dNDwow==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /@schematics/angular@17.3.7: - resolution: {integrity: sha512-HaJroKaberriP4wFefTTSVFrtU9GMvnG3I6ELbOteOyKMH7o2V91FXGJDJ5KnIiLRlBmC30G3r+9Ybc/rtAYkw==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - dependencies: - '@angular-devkit/core': 17.3.7 - '@angular-devkit/schematics': 17.3.7 - jsonc-parser: 3.2.1 - transitivePeerDependencies: - - chokidar - dev: true - - /@sigstore/bundle@2.3.1: - resolution: {integrity: sha512-eqV17lO3EIFqCWK3969Rz+J8MYrRZKw9IBHpSo6DEcEX2c+uzDFOgHE9f2MnyDpfs48LFO4hXmk9KhQ74JzU1g==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/protobuf-specs': 0.3.2 - dev: true - - /@sigstore/core@1.1.0: - resolution: {integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==} - engines: {node: ^16.14.0 || >=18.0.0} - dev: true - - /@sigstore/protobuf-specs@0.3.2: - resolution: {integrity: sha512-c6B0ehIWxMI8wiS/bj6rHMPqeFvngFV7cDU/MY+B16P9Z3Mp9k8L93eYZ7BYzSickzuqAQqAq0V956b3Ju6mLw==} - engines: {node: ^16.14.0 || >=18.0.0} - dev: true - - /@sigstore/sign@2.3.1: - resolution: {integrity: sha512-YZ71wKIOweC8ViUeZXboz0iPLqMkskxuoeN/D1CEpAyZvEepbX9oRMIoO6a/DxUqO1VEaqmcmmqzSiqtOsvSmw==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.3.1 - '@sigstore/core': 1.1.0 - '@sigstore/protobuf-specs': 0.3.2 - make-fetch-happen: 13.0.1 - proc-log: 4.2.0 - promise-retry: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@sigstore/tuf@2.3.3: - resolution: {integrity: sha512-agQhHNkIddXFslkudjV88vTXiAMEyUtso3at6ZHUNJ1agZb7Ze6VW/PddHipdWBu1t+8OWLW5X5yZOPiOnaWJQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/protobuf-specs': 0.3.2 - tuf-js: 2.2.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@sigstore/verify@1.2.0: - resolution: {integrity: sha512-hQF60nc9yab+Csi4AyoAmilGNfpXT+EXdBgFkP9OgPwIBPwyqVf7JAWPtmqrrrneTmAT6ojv7OlH1f6Ix5BG4Q==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.3.1 - '@sigstore/core': 1.1.0 - '@sigstore/protobuf-specs': 0.3.2 - dev: true - - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true - - /@socket.io/component-emitter@3.1.2: - resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - dev: true - - /@tufjs/canonical-json@2.0.0: - resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} - engines: {node: ^16.14.0 || >=18.0.0} - dev: true - - /@tufjs/models@2.0.1: - resolution: {integrity: sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@tufjs/canonical-json': 2.0.0 - minimatch: 9.0.4 - dev: true - - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.12.12 - dev: true - - /@types/bonjour@3.5.13: - resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/connect-history-api-fallback@1.5.4: - resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} - dependencies: - '@types/express-serve-static-core': 4.19.0 - '@types/node': 20.12.12 - dev: true - - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/cookie@0.4.1: - resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} - dev: true - - /@types/cors@2.8.17: - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/eslint-scope@3.7.7: - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - dependencies: - '@types/eslint': 8.56.10 - '@types/estree': 1.0.5 - dev: true - - /@types/eslint@8.56.10: - resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - dev: true - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/estree@1.0.6: - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - requiresBuild: true - dev: true - - /@types/express-serve-static-core@4.19.0: - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} - dependencies: - '@types/node': 20.12.12 - '@types/qs': 6.9.15 - '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 - dev: true - - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 - '@types/qs': 6.9.15 - '@types/serve-static': 1.15.7 - dev: true - - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true - - /@types/http-proxy@1.17.14: - resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/jasmine@5.1.4: - resolution: {integrity: sha512-px7OMFO/ncXxixDe1zR13V1iycqWae0MxTaw62RpFlksUi5QuNWgQJFkTQjIOvrmutJbI7Fp2Y2N1F6D2R4G6w==} - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true - - /@types/node-forge@1.3.11: - resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/node@20.12.12: - resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/qs@6.9.15: - resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} - dev: true - - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true - - /@types/resolve@1.20.2: - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - dev: true - - /@types/retry@0.12.0: - resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} - dev: true - - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true - - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.12.12 - dev: true - - /@types/serve-index@1.9.4: - resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} - dependencies: - '@types/express': 4.17.21 - dev: true - - /@types/serve-static@1.15.7: - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 20.12.12 - '@types/send': 0.17.4 - dev: true - - /@types/sockjs@0.3.36: - resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@types/ws@8.5.10: - resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} - dependencies: - '@types/node': 20.12.12 - dev: true - - /@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/type-utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/eslint-plugin@7.9.0(@typescript-eslint/parser@7.9.0)(eslint@8.57.1)(typescript@5.4.5): - resolution: {integrity: sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.9.0(eslint@8.57.1)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.9.0 - '@typescript-eslint/type-utils': 7.9.0(eslint@8.57.1)(typescript@5.4.5) - '@typescript-eslint/utils': 7.9.0(eslint@8.57.1)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.9.0 - eslint: 8.57.1 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.9.0(eslint@8.57.1)(typescript@5.4.5): - resolution: {integrity: sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.9.0 - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/typescript-estree': 7.9.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.9.0 - debug: 4.3.4 - eslint: 8.57.1 - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@7.8.0: - resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 - dev: true - - /@typescript-eslint/scope-manager@7.9.0: - resolution: {integrity: sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/visitor-keys': 7.9.0 - dev: true - - /@typescript-eslint/type-utils@7.8.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/type-utils@7.9.0(eslint@8.57.1)(typescript@5.4.5): - resolution: {integrity: sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.9.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.9.0(eslint@8.57.1)(typescript@5.4.5) - debug: 4.3.4 - eslint: 8.57.1 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@7.8.0: - resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} - engines: {node: ^18.18.0 || >=20.0.0} - dev: true - - /@typescript-eslint/types@7.9.0: - resolution: {integrity: sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==} - engines: {node: ^18.18.0 || >=20.0.0} - dev: true - - /@typescript-eslint/typescript-estree@7.8.0(typescript@5.4.5): - resolution: {integrity: sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@7.9.0(typescript@5.4.5): - resolution: {integrity: sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/visitor-keys': 7.9.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@7.8.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - eslint: 8.57.0 - semver: 7.6.2 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@7.9.0(eslint@8.57.1)(typescript@5.4.5): - resolution: {integrity: sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) - '@typescript-eslint/scope-manager': 7.9.0 - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/typescript-estree': 7.9.0(typescript@5.4.5) - eslint: 8.57.1 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@7.8.0: - resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.8.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.9.0: - resolution: {integrity: sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.9.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@ungap/structured-clone@1.2.1: - resolution: {integrity: sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==} - dev: true - - /@vitejs/plugin-basic-ssl@1.1.0(vite@5.1.7): - resolution: {integrity: sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==} - engines: {node: '>=14.6.0'} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - dependencies: - vite: 5.1.7(less@4.2.0)(sass@1.71.1)(terser@5.29.1) - dev: true - - /@webassemblyjs/ast@1.12.1: - resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} - dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - dev: true - - /@webassemblyjs/floating-point-hex-parser@1.11.6: - resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} - dev: true - - /@webassemblyjs/helper-api-error@1.11.6: - resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} - dev: true - - /@webassemblyjs/helper-buffer@1.12.1: - resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} - dev: true - - /@webassemblyjs/helper-numbers@1.11.6: - resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 - '@xtuc/long': 4.2.2 - dev: true - - /@webassemblyjs/helper-wasm-bytecode@1.11.6: - resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} - dev: true - - /@webassemblyjs/helper-wasm-section@1.12.1: - resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 - dev: true - - /@webassemblyjs/ieee754@1.11.6: - resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} - dependencies: - '@xtuc/ieee754': 1.2.0 - dev: true - - /@webassemblyjs/leb128@1.11.6: - resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} - dependencies: - '@xtuc/long': 4.2.2 - dev: true - - /@webassemblyjs/utf8@1.11.6: - resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} - dev: true - - /@webassemblyjs/wasm-edit@1.12.1: - resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 - dev: true - - /@webassemblyjs/wasm-gen@1.12.1: - resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - - /@webassemblyjs/wasm-opt@1.12.1: - resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - dev: true - - /@webassemblyjs/wasm-parser@1.12.1: - resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - - /@webassemblyjs/wast-printer@1.12.1: - resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@xtuc/long': 4.2.2 - dev: true - - /@xtuc/ieee754@1.2.0: - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - dev: true - - /@xtuc/long@4.2.2: - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - dev: true - - /@yarnpkg/lockfile@1.1.0: - resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} - dev: true - - /@yarnpkg/parsers@3.0.0-rc.46: - resolution: {integrity: sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==} - engines: {node: '>=14.15.0'} - dependencies: - js-yaml: 3.14.1 - tslib: 2.6.2 - dev: true - - /@zkochan/js-yaml@0.0.6: - resolution: {integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /abbrev@2.0.0: - resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: true - - /acorn-import-assertions@1.9.0(acorn@8.11.3): - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} - peerDependencies: - acorn: ^8 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /adjust-sourcemap-loader@4.0.0: - resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} - engines: {node: '>=8.9'} - dependencies: - loader-utils: 2.0.4 - regex-parser: 2.3.0 - dev: true - - /agent-base@7.1.1: - resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} - engines: {node: '>= 14'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /ajv-formats@2.1.1(ajv@8.12.0): - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - dependencies: - ajv: 8.12.0 - dev: true - - /ajv-keywords@3.5.2(ajv@6.12.6): - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - dependencies: - ajv: 6.12.6 - dev: true - - /ajv-keywords@5.1.0(ajv@8.12.0): - resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} - peerDependencies: - ajv: ^8.8.2 - dependencies: - ajv: 8.12.0 - fast-deep-equal: 3.1.3 - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-html-community@0.0.8: - resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} - engines: {'0': node >= 0.8.0} - hasBin: true - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - dependencies: - dequal: 2.0.3 - dev: true - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - dev: true - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - - /autoprefixer@10.4.18(postcss@8.4.35): - resolution: {integrity: sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001618 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.0.1 - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /axios@1.6.8: - resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} - dependencies: - follow-redirects: 1.15.6 - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - dev: true - - /axobject-query@4.0.0: - resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} - dependencies: - dequal: 2.0.3 - dev: true - - /babel-loader@9.1.3(@babel/core@7.24.0)(webpack@5.90.3): - resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} - engines: {node: '>= 14.15.0'} - peerDependencies: - '@babel/core': ^7.12.0 - webpack: '>=5' - dependencies: - '@babel/core': 7.24.0 - find-cache-dir: 4.0.0 - schema-utils: 4.2.0 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.24.5 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.24.0): - resolution: {integrity: sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.0 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-corejs3@0.9.0(@babel/core@7.24.0): - resolution: {integrity: sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-define-polyfill-provider': 0.5.0(@babel/core@7.24.0) - core-js-compat: 3.37.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-regenerator@0.5.5(@babel/core@7.24.0): - resolution: {integrity: sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-define-polyfill-provider': 0.5.0(@babel/core@7.24.0) - transitivePeerDependencies: - - supports-color - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - - /base64id@2.0.0: - resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} - engines: {node: ^4.5.0 || >= 5.9} - dev: true - - /batch@0.6.1: - resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} - dev: true - - /big.js@5.2.2: - resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - dev: true - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: true - - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /bonjour-service@1.2.1: - resolution: {integrity: sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==} - dependencies: - fast-deep-equal: 3.1.3 - multicast-dns: 7.2.5 - dev: true - - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001618 - electron-to-chromium: 1.4.767 - node-releases: 2.0.14 - update-browserslist-db: 1.0.16(browserslist@4.23.0) - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /bytes@3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - dev: true - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: true - - /cacache@18.0.3: - resolution: {integrity: sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/fs': 3.1.1 - fs-minipass: 3.0.3 - glob: 10.3.15 - lru-cache: 10.2.2 - minipass: 7.1.1 - minipass-collect: 2.0.1 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - p-map: 4.0.0 - ssri: 10.0.6 - tar: 6.2.1 - unique-filename: 3.0.0 - dev: true - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /caniuse-lite@1.0.30001618: - resolution: {integrity: sha512-p407+D1tIkDvsEAPS22lJxLQQaG8OTBEqo0KhzfABGk0TU4juBNDSfH0hyAp/HRyx+M8L17z/ltyhxh27FTfQg==} - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: true - - /chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} - engines: {node: '>=6.0'} - dev: true - - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true - - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: true - - /cli-spinners@2.6.1: - resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} - engines: {node: '>=6'} - dev: true - - /cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - dev: true - - /cli-width@4.1.0: - resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} - engines: {node: '>= 12'} - dev: true - - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - dev: true - - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true - - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - - /commander@12.0.0: - resolution: {integrity: sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==} - engines: {node: '>=18'} - dev: true - - /commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /common-path-prefix@3.0.0: - resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} - dev: true - - /commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true - - /compressible@2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /compression@1.7.4: - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9 - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /connect-history-api-fallback@2.0.0: - resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} - engines: {node: '>=0.8'} - dev: true - - /connect@3.7.0: - resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} - engines: {node: '>= 0.10.0'} - dependencies: - debug: 2.6.9 - finalhandler: 1.1.2 - parseurl: 1.3.3 - utils-merge: 1.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: true - - /convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: true - - /cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - dev: true - - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - dev: true - - /copy-anything@2.0.6: - resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} - dependencies: - is-what: 3.14.1 - dev: true - - /copy-webpack-plugin@11.0.0(webpack@5.90.3): - resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} - engines: {node: '>= 14.15.0'} - peerDependencies: - webpack: ^5.1.0 - dependencies: - fast-glob: 3.3.2 - glob-parent: 6.0.2 - globby: 13.2.2 - normalize-path: 3.0.0 - schema-utils: 4.2.0 - serialize-javascript: 6.0.2 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /core-js-compat@3.37.1: - resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} - dependencies: - browserslist: 4.23.0 - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - dev: true - - /cosmiconfig@9.0.0(typescript@5.4.5): - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - env-paths: 2.2.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - typescript: 5.4.5 - dev: true - - /critters@0.0.22: - resolution: {integrity: sha512-NU7DEcQZM2Dy8XTKFHxtdnIM/drE312j2T4PCVaSUcS0oBeyT/NImpRw/Ap0zOr/1SE7SgPK9tGPg1WK/sVakw==} - dependencies: - chalk: 4.1.2 - css-select: 5.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - htmlparser2: 8.0.2 - postcss: 8.4.38 - postcss-media-query-parser: 0.2.3 - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /css-loader@6.10.0(webpack@5.90.3): - resolution: {integrity: sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==} - engines: {node: '>= 12.13.0'} - peerDependencies: - '@rspack/core': 0.x || 1.x - webpack: ^5.0.0 - peerDependenciesMeta: - '@rspack/core': - optional: true - webpack: - optional: true - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.38) - postcss-modules-scope: 3.2.0(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) - postcss-value-parser: 4.2.0 - semver: 7.6.2 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.1.0 - nth-check: 2.1.1 - dev: true - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: true - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /custom-event@1.0.1: - resolution: {integrity: sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==} - dev: true - - /date-format@4.0.14: - resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} - engines: {node: '>=4.0'} - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true - - /default-gateway@6.0.3: - resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} - engines: {node: '>= 10'} - dependencies: - execa: 5.1.1 - dev: true - - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - dev: true - - /define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - dev: true - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true - - /depd@1.1.2: - resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} - engines: {node: '>= 0.6'} - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true - - /dependency-graph@1.0.0: - resolution: {integrity: sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==} - engines: {node: '>=4'} - dev: true - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: true - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true - - /detect-node@2.1.0: - resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - dev: true - - /di@0.0.1: - resolution: {integrity: sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==} - dev: true - - /diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /dns-packet@5.6.1: - resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} - engines: {node: '>=6'} - dependencies: - '@leichtgewicht/ip-codec': 2.0.5 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dom-serialize@2.2.1: - resolution: {integrity: sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==} - dependencies: - custom-event: 1.0.1 - ent: 2.2.0 - extend: 3.0.2 - void-elements: 2.0.1 - dev: true - - /dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - dev: true - - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true - - /domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: true - - /domutils@3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dev: true - - /dotenv-expand@10.0.0: - resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} - engines: {node: '>=12'} - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /dotenv@16.3.2: - resolution: {integrity: sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==} - engines: {node: '>=12'} - dev: true - - /duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true - - /ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - jake: 10.9.1 - dev: true - - /electron-to-chromium@1.4.767: - resolution: {integrity: sha512-nzzHfmQqBss7CE3apQHkHjXW77+8w3ubGCIoEijKCJebPufREaFETgGXWTkh32t259F3Kcq+R8MZdFdOJROgYw==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /emojis-list@3.0.0: - resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} - engines: {node: '>= 4'} - dev: true - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: true - - /encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - requiresBuild: true - dependencies: - iconv-lite: 0.6.3 - dev: true - optional: true - - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - dependencies: - once: 1.4.0 - dev: true - - /engine.io-parser@5.2.2: - resolution: {integrity: sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==} - engines: {node: '>=10.0.0'} - dev: true - - /engine.io@6.5.4: - resolution: {integrity: sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==} - engines: {node: '>=10.2.0'} - dependencies: - '@types/cookie': 0.4.1 - '@types/cors': 2.8.17 - '@types/node': 20.12.12 - accepts: 1.3.8 - base64id: 2.0.0 - cookie: 0.4.2 - cors: 2.8.5 - debug: 4.3.4 - engine.io-parser: 5.2.2 - ws: 8.11.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /enhanced-resolve@5.16.1: - resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /enquirer@2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - dev: true - - /ent@2.2.0: - resolution: {integrity: sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==} - dev: true - - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: true - - /env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - dev: true - - /err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - dev: true - - /errno@0.1.8: - resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} - hasBin: true - requiresBuild: true - dependencies: - prr: 1.0.1 - dev: true - optional: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true - - /es-module-lexer@1.5.2: - resolution: {integrity: sha512-l60ETUTmLqbVbVHv1J4/qj+M8nq7AwMzEcg3kmJDt9dCNrTk+yHcYFf/Kw75pMDwd9mPcIGCG5LcS20SxYRzFA==} - dev: true - - /esbuild-wasm@0.20.1: - resolution: {integrity: sha512-6v/WJubRsjxBbQdz6izgvx7LsVFvVaGmSdwrFHmEzoVgfXL89hkKPoQHsnVI2ngOkcBUQT9kmAM1hVL1k/Av4A==} - engines: {node: '>=12'} - hasBin: true - dev: true - - /esbuild-wasm@0.20.2: - resolution: {integrity: sha512-7o6nmsEqlcXJXMNqnx5K+M4w4OPx7yTFXQHcJyeP3SkXb8p2T8N9E1ayK4vd/qDBepH6fuPoZwiFvZm8x5qv+w==} - engines: {node: '>=12'} - hasBin: true - dev: true - - /esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 - dev: true - - /esbuild@0.20.1: - resolution: {integrity: sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.20.1 - '@esbuild/android-arm': 0.20.1 - '@esbuild/android-arm64': 0.20.1 - '@esbuild/android-x64': 0.20.1 - '@esbuild/darwin-arm64': 0.20.1 - '@esbuild/darwin-x64': 0.20.1 - '@esbuild/freebsd-arm64': 0.20.1 - '@esbuild/freebsd-x64': 0.20.1 - '@esbuild/linux-arm': 0.20.1 - '@esbuild/linux-arm64': 0.20.1 - '@esbuild/linux-ia32': 0.20.1 - '@esbuild/linux-loong64': 0.20.1 - '@esbuild/linux-mips64el': 0.20.1 - '@esbuild/linux-ppc64': 0.20.1 - '@esbuild/linux-riscv64': 0.20.1 - '@esbuild/linux-s390x': 0.20.1 - '@esbuild/linux-x64': 0.20.1 - '@esbuild/netbsd-x64': 0.20.1 - '@esbuild/openbsd-x64': 0.20.1 - '@esbuild/sunos-x64': 0.20.1 - '@esbuild/win32-arm64': 0.20.1 - '@esbuild/win32-ia32': 0.20.1 - '@esbuild/win32-x64': 0.20.1 - dev: true - - /esbuild@0.20.2: - resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.20.2 - '@esbuild/android-arm': 0.20.2 - '@esbuild/android-arm64': 0.20.2 - '@esbuild/android-x64': 0.20.2 - '@esbuild/darwin-arm64': 0.20.2 - '@esbuild/darwin-x64': 0.20.2 - '@esbuild/freebsd-arm64': 0.20.2 - '@esbuild/freebsd-x64': 0.20.2 - '@esbuild/linux-arm': 0.20.2 - '@esbuild/linux-arm64': 0.20.2 - '@esbuild/linux-ia32': 0.20.2 - '@esbuild/linux-loong64': 0.20.2 - '@esbuild/linux-mips64el': 0.20.2 - '@esbuild/linux-ppc64': 0.20.2 - '@esbuild/linux-riscv64': 0.20.2 - '@esbuild/linux-s390x': 0.20.2 - '@esbuild/linux-x64': 0.20.2 - '@esbuild/netbsd-x64': 0.20.2 - '@esbuild/openbsd-x64': 0.20.2 - '@esbuild/sunos-x64': 0.20.2 - '@esbuild/win32-arm64': 0.20.2 - '@esbuild/win32-ia32': 0.20.2 - '@esbuild/win32-x64': 0.20.2 - dev: true - optional: true - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: true - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /eslint-config-prettier@9.1.0(eslint@8.57.1): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.1 - dev: true - - /eslint-config-turbo@2.3.3(eslint@8.57.1): - resolution: {integrity: sha512-cM9wSBYowQIrjx2MPCzFE6jTnG4vpTPJKZ/O+Ps3CqrmGK/wtNOsY6WHGMwLtKY/nNbgRahAJH6jGVF6k2coOg==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.1 - eslint-plugin-turbo: 2.3.3(eslint@8.57.1) - dev: true - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-turbo@2.3.3(eslint@8.57.1): - resolution: {integrity: sha512-j8UEA0Z+NNCsjZep9G5u5soDQHcXq/x4amrwulk6eHF1U91H2qAjp5I4jQcvJewmccCJbVp734PkHHTRnosjpg==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.1 - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-scope@8.0.1: - resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint@8.57.1: - resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) - '@eslint-community/regexpp': 4.12.1 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.1 - '@humanwhocodes/config-array': 0.13.0 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.1 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: true - - /eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - dev: true - - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - dev: true - - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: true - - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /faye-websocket@0.11.4: - resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} - engines: {node: '>=0.8.0'} - dependencies: - websocket-driver: 0.7.4 - dev: true - - /figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: true - - /filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.6 - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /finalhandler@1.1.2: - resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.3.0 - parseurl: 1.3.3 - statuses: 1.5.0 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /find-cache-dir@3.3.2: - resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} - engines: {node: '>=8'} - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - dev: true - - /find-cache-dir@4.0.0: - resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} - engines: {node: '>=14.16'} - dependencies: - common-path-prefix: 3.0.0 - pkg-dir: 7.0.0 - dev: true - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@6.3.0: - resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - locate-path: 7.2.0 - path-exists: 5.0.0 - dev: true - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true - - /follow-redirects@1.15.6: - resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: true - - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: true - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: true - - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - dev: true - - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /fs-minipass@3.0.3: - resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.1.1 - dev: true - - /fs-monkey@1.0.6: - resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - dev: true - - /get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: true - - /glob@10.3.15: - resolution: {integrity: sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==} - engines: {node: '>=16 || 14 >=14.18'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.1.1 - path-scurry: 1.11.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /handle-thing@2.0.1: - resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: true - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /hosted-git-info@7.0.2: - resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - lru-cache: 10.2.2 - dev: true - - /hpack.js@2.1.6: - resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} - dependencies: - inherits: 2.0.4 - obuf: 1.1.2 - readable-stream: 2.3.8 - wbuf: 1.7.3 - dev: true - - /html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} - dev: true - - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true - - /htmlparser2@8.0.2: - resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.1.0 - entities: 4.5.0 - dev: true - - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: true - - /http-deceiver@1.2.7: - resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} - dev: true - - /http-errors@1.6.3: - resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} - engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.3 - setprototypeof: 1.1.0 - statuses: 1.5.0 - dev: true - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - - /http-parser-js@0.5.8: - resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} - dev: true - - /http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.1 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /http-proxy-middleware@2.0.6(@types/express@4.17.21): - resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/express': ^4.17.13 - peerDependenciesMeta: - '@types/express': - optional: true - dependencies: - '@types/express': 4.17.21 - '@types/http-proxy': 1.17.14 - http-proxy: 1.18.1 - is-glob: 4.0.3 - is-plain-obj: 3.0.0 - micromatch: 4.0.5 - transitivePeerDependencies: - - debug - dev: true - - /http-proxy@1.18.1: - resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} - engines: {node: '>=8.0.0'} - dependencies: - eventemitter3: 4.0.7 - follow-redirects: 1.15.6 - requires-port: 1.0.0 - transitivePeerDependencies: - - debug - dev: true - - /https-proxy-agent@7.0.4: - resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.1 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - requiresBuild: true - dependencies: - safer-buffer: 2.1.2 - dev: true - - /icss-utils@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - dev: true - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true - - /ignore-walk@6.0.5: - resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minimatch: 9.0.4 - dev: true - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - dev: true - - /image-size@0.5.5: - resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} - engines: {node: '>=0.10.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /immutable@4.3.6: - resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.3: - resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /ini@4.1.2: - resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /injection-js@2.4.0: - resolution: {integrity: sha512-6jiJt0tCAo9zjHbcwLiPL+IuNe9SQ6a9g0PEzafThW3fOQi0mrmiJGBJvDD6tmhPh8cQHIQtCOrJuBfQME4kPA==} - dependencies: - tslib: 2.6.2 - dev: true - - /inquirer@9.2.15: - resolution: {integrity: sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==} - engines: {node: '>=18'} - dependencies: - '@ljharb/through': 2.3.13 - ansi-escapes: 4.3.2 - chalk: 5.3.0 - cli-cursor: 3.1.0 - cli-width: 4.1.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 1.0.0 - ora: 5.4.1 - run-async: 3.0.0 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true - - /ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - dev: true - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: true - - /ipaddr.js@2.2.0: - resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} - engines: {node: '>= 10'} - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.2 - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: true - - /is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - dev: true - - /is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@3.0.0: - resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} - engines: {node: '>=10'} - dev: true - - /is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true - - /is-what@3.14.1: - resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} - dev: true - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - - /isbinaryfile@4.0.10: - resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} - engines: {node: '>= 8.0.0'} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /isexe@3.1.1: - resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} - engines: {node: '>=16'} - dev: true - - /isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - dev: true - - /istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - dev: true - - /istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - dev: true - - /istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.3.4 - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jake@10.9.1: - resolution: {integrity: sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==} - engines: {node: '>=10'} - hasBin: true - dependencies: - async: 3.2.5 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: true - - /jasmine-core@4.6.0: - resolution: {integrity: sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==} - dev: true - - /jasmine-core@5.1.2: - resolution: {integrity: sha512-2oIUMGn00FdUiqz6epiiJr7xcFyNYj3rDcfmnzfkBnHyBQ3cBQUs4mmyGsOb7TTLb9kxk7dBcmEmqhDKkBoDyA==} - dev: true - - /jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 20.12.12 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /jiti@1.21.0: - resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} - hasBin: true - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-parse-even-better-errors@3.0.2: - resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: true - - /jsonc-parser@3.2.1: - resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} - dev: true - - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - dev: true - - /karma-chrome-launcher@3.2.0: - resolution: {integrity: sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==} - dependencies: - which: 1.3.1 - dev: true - - /karma-coverage@2.2.1: - resolution: {integrity: sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==} - engines: {node: '>=10.0.0'} - dependencies: - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 5.2.1 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /karma-jasmine-html-reporter@2.1.0(jasmine-core@5.1.2)(karma-jasmine@5.1.0)(karma@6.4.3): - resolution: {integrity: sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==} - peerDependencies: - jasmine-core: ^4.0.0 || ^5.0.0 - karma: ^6.0.0 - karma-jasmine: ^5.0.0 - dependencies: - jasmine-core: 5.1.2 - karma: 6.4.3 - karma-jasmine: 5.1.0(karma@6.4.3) - dev: true - - /karma-jasmine@5.1.0(karma@6.4.3): - resolution: {integrity: sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==} - engines: {node: '>=12'} - peerDependencies: - karma: ^6.0.0 - dependencies: - jasmine-core: 4.6.0 - karma: 6.4.3 - dev: true - - /karma-source-map-support@1.4.0: - resolution: {integrity: sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==} - dependencies: - source-map-support: 0.5.21 - dev: true - - /karma@6.4.3: - resolution: {integrity: sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q==} - engines: {node: '>= 10'} - hasBin: true - dependencies: - '@colors/colors': 1.5.0 - body-parser: 1.20.2 - braces: 3.0.2 - chokidar: 3.6.0 - connect: 3.7.0 - di: 0.0.1 - dom-serialize: 2.2.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - http-proxy: 1.18.1 - isbinaryfile: 4.0.10 - lodash: 4.17.21 - log4js: 6.9.1 - mime: 2.6.0 - minimatch: 3.1.2 - mkdirp: 0.5.6 - qjobs: 1.2.0 - range-parser: 1.2.1 - rimraf: 3.0.2 - socket.io: 4.7.5 - source-map: 0.6.1 - tmp: 0.2.3 - ua-parser-js: 0.7.37 - yargs: 16.2.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /klona@2.0.6: - resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} - engines: {node: '>= 8'} - dev: true - - /launch-editor@2.6.1: - resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} - dependencies: - picocolors: 1.0.1 - shell-quote: 1.8.1 - dev: true - - /less-loader@11.1.0(less@4.2.0)(webpack@5.90.3): - resolution: {integrity: sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==} - engines: {node: '>= 14.15.0'} - peerDependencies: - less: ^3.5.0 || ^4.0.0 - webpack: ^5.0.0 - dependencies: - klona: 2.0.6 - less: 4.2.0 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /less@4.2.0: - resolution: {integrity: sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==} - engines: {node: '>=6'} - hasBin: true - dependencies: - copy-anything: 2.0.6 - parse-node-version: 1.0.1 - tslib: 2.6.2 - optionalDependencies: - errno: 0.1.8 - graceful-fs: 4.2.11 - image-size: 0.5.5 - make-dir: 2.1.0 - mime: 1.6.0 - needle: 3.3.1 - source-map: 0.6.1 - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /license-webpack-plugin@4.0.2(webpack@5.90.3): - resolution: {integrity: sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==} - peerDependencies: - webpack: '*' - peerDependenciesMeta: - webpack: - optional: true - webpack-sources: - optional: true - dependencies: - webpack: 5.90.3(esbuild@0.20.1) - webpack-sources: 3.2.3 - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /lines-and-columns@2.0.4: - resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} - engines: {node: '>=6.11.5'} - dev: true - - /loader-utils@2.0.4: - resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} - engines: {node: '>=8.9.0'} - dependencies: - big.js: 5.2.2 - emojis-list: 3.0.0 - json5: 2.2.3 - dev: true - - /loader-utils@3.2.1: - resolution: {integrity: sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==} - engines: {node: '>= 12.13.0'} - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /locate-path@7.2.0: - resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-locate: 6.0.0 - dev: true - - /lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - - /log4js@6.9.1: - resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} - engines: {node: '>=8.0'} - dependencies: - date-format: 4.0.14 - debug: 4.3.4 - flatted: 3.3.1 - rfdc: 1.3.1 - streamroller: 3.1.5 - transitivePeerDependencies: - - supports-color - dev: true - - /lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /magic-string@0.30.8: - resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /make-dir@2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - pify: 4.0.1 - semver: 5.7.2 - dev: true - optional: true - - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.1 - dev: true - - /make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - dependencies: - semver: 7.6.2 - dev: true - - /make-fetch-happen@13.0.1: - resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/agent': 2.2.2 - cacache: 18.0.3 - http-cache-semantics: 4.1.1 - is-lambda: 1.0.1 - minipass: 7.1.1 - minipass-fetch: 3.0.5 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.3 - proc-log: 4.2.0 - promise-retry: 2.0.1 - ssri: 10.0.6 - transitivePeerDependencies: - - supports-color - dev: true - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: true - - /memfs@3.5.3: - resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} - engines: {node: '>= 4.0.0'} - dependencies: - fs-monkey: 1.0.6 - dev: true - - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: true - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /mime@2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mini-css-extract-plugin@2.8.1(webpack@5.90.3): - resolution: {integrity: sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - dependencies: - schema-utils: 4.2.0 - tapable: 2.2.1 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - - /minipass-collect@2.0.1: - resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - minipass: 7.1.1 - dev: true - - /minipass-fetch@3.0.5: - resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.1.1 - minipass-sized: 1.0.3 - minizlib: 2.1.2 - optionalDependencies: - encoding: 0.1.13 - dev: true - - /minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass-json-stream@1.0.1: - resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} - dependencies: - jsonparse: 1.3.1 - minipass: 3.3.6 - dev: true - - /minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: true - - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - dev: true - - /minipass@7.1.1: - resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: true - - /mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /mrmime@2.0.0: - resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} - engines: {node: '>=10'} - dev: true - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /multicast-dns@7.2.5: - resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} - hasBin: true - dependencies: - dns-packet: 5.6.1 - thunky: 1.1.0 - dev: true - - /mute-stream@1.0.0: - resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /needle@3.3.1: - resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} - engines: {node: '>= 4.4.x'} - hasBin: true - requiresBuild: true - dependencies: - iconv-lite: 0.6.3 - sax: 1.3.0 - dev: true - optional: true - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /ng-packagr@17.3.0(@angular/compiler-cli@17.3.8)(tslib@2.6.2)(typescript@5.4.5): - resolution: {integrity: sha512-kMSqxeDgv88SWCoapWNRRN1UdBgwu9/Pw/j7u2WFGmzrIWUFivNWBBSSL94kMxr2La+Z9wMwiL8EwKNvmCpg2A==} - engines: {node: ^18.13.0 || >=20.9.0} - hasBin: true - peerDependencies: - '@angular/compiler-cli': ^17.0.0 || ^17.2.0-next.0 || ^17.3.0-next.0 - tailwindcss: ^2.0.0 || ^3.0.0 - tslib: ^2.3.0 - typescript: '>=5.2 <5.5' - peerDependenciesMeta: - tailwindcss: - optional: true - dependencies: - '@angular/compiler-cli': 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) - '@rollup/plugin-json': 6.1.0(rollup@4.29.1) - '@rollup/plugin-node-resolve': 15.2.3(rollup@4.29.1) - '@rollup/wasm-node': 4.17.2 - ajv: 8.12.0 - ansi-colors: 4.1.3 - browserslist: 4.23.0 - cacache: 18.0.3 - chokidar: 3.6.0 - commander: 12.0.0 - convert-source-map: 2.0.0 - dependency-graph: 1.0.0 - esbuild-wasm: 0.20.2 - fast-glob: 3.3.2 - find-cache-dir: 3.3.2 - injection-js: 2.4.0 - jsonc-parser: 3.2.1 - less: 4.2.0 - ora: 5.4.1 - piscina: 4.4.0 - postcss: 8.4.38 - rxjs: 7.8.1 - sass: 1.77.1 - tslib: 2.6.2 - typescript: 5.4.5 - optionalDependencies: - esbuild: 0.20.2 - rollup: 4.29.1 - dev: true - - /nice-napi@1.0.2: - resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} - os: ['!win32'] - requiresBuild: true - dependencies: - node-addon-api: 3.2.1 - node-gyp-build: 4.8.1 - dev: true - optional: true - - /node-addon-api@3.2.1: - resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} - requiresBuild: true - dev: true - optional: true - - /node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} - engines: {node: '>= 6.13.0'} - dev: true - - /node-gyp-build@4.8.1: - resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /node-gyp@10.1.0: - resolution: {integrity: sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==} - engines: {node: ^16.14.0 || >=18.0.0} - hasBin: true - dependencies: - env-paths: 2.2.1 - exponential-backoff: 3.1.1 - glob: 10.3.15 - graceful-fs: 4.2.11 - make-fetch-happen: 13.0.1 - nopt: 7.2.1 - proc-log: 3.0.0 - semver: 7.6.2 - tar: 6.2.1 - which: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /node-machine-id@1.1.12: - resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} - dev: true - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true - - /nopt@7.2.1: - resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - abbrev: 2.0.0 - dev: true - - /normalize-package-data@6.0.1: - resolution: {integrity: sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - hosted-git-info: 7.0.2 - is-core-module: 2.13.1 - semver: 7.6.2 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-bundled@3.0.1: - resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - npm-normalize-package-bin: 3.0.1 - dev: true - - /npm-install-checks@6.3.0: - resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.6.0 - dev: true - - /npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /npm-package-arg@11.0.1: - resolution: {integrity: sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - hosted-git-info: 7.0.2 - proc-log: 3.0.0 - semver: 7.6.2 - validate-npm-package-name: 5.0.1 - dev: true - - /npm-packlist@8.0.2: - resolution: {integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - ignore-walk: 6.0.5 - dev: true - - /npm-pick-manifest@9.0.0: - resolution: {integrity: sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - npm-install-checks: 6.3.0 - npm-normalize-package-bin: 3.0.1 - npm-package-arg: 11.0.1 - semver: 7.6.0 - dev: true - - /npm-registry-fetch@16.2.1: - resolution: {integrity: sha512-8l+7jxhim55S85fjiDGJ1rZXBWGtRLi1OSb4Z3BPLObPuIaeKRlPRiYMSHU4/81ck3t71Z+UwDDl47gcpmfQQA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/redact': 1.1.0 - make-fetch-happen: 13.0.1 - minipass: 7.1.1 - minipass-fetch: 3.0.5 - minipass-json-stream: 1.0.1 - minizlib: 2.1.2 - npm-package-arg: 11.0.1 - proc-log: 4.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - dependencies: - boolbase: 1.0.0 - dev: true - - /nx@18.3.4: - resolution: {integrity: sha512-7rOHRyxpnZGJ3pHnwmpoAMHt9hNuwibWhOhPBJDhJVcbQJtGfwcWWyV/iSEnVXwKZ2lfHVE3TwE+gXFdT/GFiw==} - hasBin: true - requiresBuild: true - peerDependencies: - '@swc-node/register': ^1.8.0 - '@swc/core': ^1.3.85 - peerDependenciesMeta: - '@swc-node/register': - optional: true - '@swc/core': - optional: true - dependencies: - '@nrwl/tao': 18.3.4 - '@yarnpkg/lockfile': 1.1.0 - '@yarnpkg/parsers': 3.0.0-rc.46 - '@zkochan/js-yaml': 0.0.6 - axios: 1.6.8 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.6.1 - cliui: 8.0.1 - dotenv: 16.3.2 - dotenv-expand: 10.0.0 - enquirer: 2.3.6 - figures: 3.2.0 - flat: 5.0.2 - fs-extra: 11.2.0 - ignore: 5.3.1 - jest-diff: 29.7.0 - js-yaml: 4.1.0 - jsonc-parser: 3.2.0 - lines-and-columns: 2.0.4 - minimatch: 9.0.3 - node-machine-id: 1.1.12 - npm-run-path: 4.0.1 - open: 8.4.2 - ora: 5.3.0 - semver: 7.6.2 - string-width: 4.2.3 - strong-log-transformer: 2.1.0 - tar-stream: 2.2.0 - tmp: 0.2.3 - tsconfig-paths: 4.2.0 - tslib: 2.6.2 - yargs: 17.7.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@nx/nx-darwin-arm64': 18.3.4 - '@nx/nx-darwin-x64': 18.3.4 - '@nx/nx-freebsd-x64': 18.3.4 - '@nx/nx-linux-arm-gnueabihf': 18.3.4 - '@nx/nx-linux-arm64-gnu': 18.3.4 - '@nx/nx-linux-arm64-musl': 18.3.4 - '@nx/nx-linux-x64-gnu': 18.3.4 - '@nx/nx-linux-x64-musl': 18.3.4 - '@nx/nx-win32-arm64-msvc': 18.3.4 - '@nx/nx-win32-x64-msvc': 18.3.4 - transitivePeerDependencies: - - debug - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true - - /obuf@1.1.2: - resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - dev: true - - /on-finished@2.3.0: - resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - - /on-headers@1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - - /optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - dev: true - - /ora@5.3.0: - resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - yocto-queue: 1.0.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-locate@6.0.0: - resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-limit: 4.0.0 - dev: true - - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: true - - /p-retry@4.6.2: - resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} - engines: {node: '>=8'} - dependencies: - '@types/retry': 0.12.0 - retry: 0.13.1 - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /pacote@17.0.6: - resolution: {integrity: sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==} - engines: {node: ^16.14.0 || >=18.0.0} - hasBin: true - dependencies: - '@npmcli/git': 5.0.7 - '@npmcli/installed-package-contents': 2.1.0 - '@npmcli/promise-spawn': 7.0.2 - '@npmcli/run-script': 7.0.4 - cacache: 18.0.3 - fs-minipass: 3.0.3 - minipass: 7.1.1 - npm-package-arg: 11.0.1 - npm-packlist: 8.0.2 - npm-pick-manifest: 9.0.0 - npm-registry-fetch: 16.2.1 - proc-log: 3.0.0 - promise-retry: 2.0.1 - read-package-json: 7.0.1 - read-package-json-fast: 3.0.2 - sigstore: 2.3.0 - ssri: 10.0.6 - tar: 6.2.1 - transitivePeerDependencies: - - bluebird - - supports-color - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.24.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse-node-version@1.0.1: - resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} - engines: {node: '>= 0.10'} - dev: true - - /parse5-html-rewriting-stream@7.0.0: - resolution: {integrity: sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==} - dependencies: - entities: 4.5.0 - parse5: 7.1.2 - parse5-sax-parser: 7.0.0 - dev: true - - /parse5-sax-parser@7.0.0: - resolution: {integrity: sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==} - dependencies: - parse5: 7.1.2 - dev: true - - /parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} - dependencies: - entities: 4.5.0 - dev: true - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-exists@5.0.0: - resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - dependencies: - lru-cache: 10.2.2 - minipass: 7.1.1 - dev: true - - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /picomatch@4.0.1: - resolution: {integrity: sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==} - engines: {node: '>=12'} - dev: true - - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - requiresBuild: true - dev: true - optional: true - - /piscina@4.4.0: - resolution: {integrity: sha512-+AQduEJefrOApE4bV7KRmp3N2JnnyErlVqq4P/jmko4FPz9Z877BCccl/iB3FdrWSUkvbGV9Kan/KllJgat3Vg==} - optionalDependencies: - nice-napi: 1.0.2 - dev: true - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /pkg-dir@7.0.0: - resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} - engines: {node: '>=14.16'} - dependencies: - find-up: 6.3.0 - dev: true - - /postcss-loader@8.1.1(postcss@8.4.35)(typescript@5.4.5)(webpack@5.90.3): - resolution: {integrity: sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==} - engines: {node: '>= 18.12.0'} - peerDependencies: - '@rspack/core': 0.x || 1.x - postcss: ^7.0.0 || ^8.0.1 - webpack: ^5.0.0 - peerDependenciesMeta: - '@rspack/core': - optional: true - webpack: - optional: true - dependencies: - cosmiconfig: 9.0.0(typescript@5.4.5) - jiti: 1.21.0 - postcss: 8.4.35 - semver: 7.6.2 - webpack: 5.90.3(esbuild@0.20.1) - transitivePeerDependencies: - - typescript - dev: true - - /postcss-media-query-parser@0.2.3: - resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} - dev: true - - /postcss-modules-extract-imports@3.1.0(postcss@8.4.38): - resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - dev: true - - /postcss-modules-local-by-default@4.0.5(postcss@8.4.38): - resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-modules-scope@3.2.0(postcss@8.4.38): - resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - dev: true - - /postcss-modules-values@4.0.0(postcss@8.4.38): - resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - dev: true - - /postcss-selector-parser@6.0.16: - resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: true - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true - - /postcss@8.4.35: - resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - dev: true - - /postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - dev: true - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - dev: true - - /proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /proc-log@4.2.0: - resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - - /promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - dev: true - - /promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - dev: true - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: true - - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true - - /prr@1.0.1: - resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - requiresBuild: true - dev: true - optional: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /qjobs@1.2.0: - resolution: {integrity: sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==} - engines: {node: '>=0.9'} - dev: true - - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: true - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true - - /react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - dev: true - - /read-package-json-fast@3.0.2: - resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - json-parse-even-better-errors: 3.0.2 - npm-normalize-package-bin: 3.0.1 - dev: true - - /read-package-json@7.0.1: - resolution: {integrity: sha512-8PcDiZ8DXUjLf687Ol4BR8Bpm2umR7vhoZOzNRt+uxD9GpBh/K+CAAALVIiYFknmvlmyg7hM7BSNUXPaCCqd0Q==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - glob: 10.3.15 - json-parse-even-better-errors: 3.0.2 - normalize-package-data: 6.0.1 - npm-normalize-package-bin: 3.0.1 - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /reflect-metadata@0.2.2: - resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} - dev: true - - /regenerate-unicode-properties@10.1.1: - resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} - engines: {node: '>=4'} - dependencies: - regenerate: 1.4.2 - dev: true - - /regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true - - /regenerator-transform@0.15.2: - resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - dependencies: - '@babel/runtime': 7.24.0 - dev: true - - /regex-parser@2.3.0: - resolution: {integrity: sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==} - dev: true - - /regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} - engines: {node: '>=4'} - dependencies: - '@babel/regjsgen': 0.8.0 - regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.1 - regjsparser: 0.9.1 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 - dev: true - - /regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - - /requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve-url-loader@5.0.0: - resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==} - engines: {node: '>=12'} - dependencies: - adjust-sourcemap-loader: 4.0.0 - convert-source-map: 1.9.0 - loader-utils: 2.0.4 - postcss: 8.4.38 - source-map: 0.6.1 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - dev: true - - /retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 - fsevents: 2.3.3 - dev: true - - /rollup@4.29.1: - resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - requiresBuild: true - dependencies: - '@types/estree': 1.0.6 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.29.1 - '@rollup/rollup-android-arm64': 4.29.1 - '@rollup/rollup-darwin-arm64': 4.29.1 - '@rollup/rollup-darwin-x64': 4.29.1 - '@rollup/rollup-freebsd-arm64': 4.29.1 - '@rollup/rollup-freebsd-x64': 4.29.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.29.1 - '@rollup/rollup-linux-arm-musleabihf': 4.29.1 - '@rollup/rollup-linux-arm64-gnu': 4.29.1 - '@rollup/rollup-linux-arm64-musl': 4.29.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.29.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.29.1 - '@rollup/rollup-linux-riscv64-gnu': 4.29.1 - '@rollup/rollup-linux-s390x-gnu': 4.29.1 - '@rollup/rollup-linux-x64-gnu': 4.29.1 - '@rollup/rollup-linux-x64-musl': 4.29.1 - '@rollup/rollup-win32-arm64-msvc': 4.29.1 - '@rollup/rollup-win32-ia32-msvc': 4.29.1 - '@rollup/rollup-win32-x64-msvc': 4.29.1 - fsevents: 2.3.3 - dev: true - - /run-async@3.0.0: - resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} - engines: {node: '>=0.12.0'} - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - dependencies: - tslib: 2.6.2 - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true - - /sass-loader@14.1.1(sass@1.71.1)(webpack@5.90.3): - resolution: {integrity: sha512-QX8AasDg75monlybel38BZ49JP5Z+uSKfKwF2rO7S74BywaRmGQMUBw9dtkS+ekyM/QnP+NOrRYq8ABMZ9G8jw==} - engines: {node: '>= 18.12.0'} - peerDependencies: - '@rspack/core': 0.x || 1.x - node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 - sass: ^1.3.0 - sass-embedded: '*' - webpack: ^5.0.0 - peerDependenciesMeta: - '@rspack/core': - optional: true - node-sass: - optional: true - sass: - optional: true - sass-embedded: - optional: true - webpack: - optional: true - dependencies: - neo-async: 2.6.2 - sass: 1.71.1 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /sass@1.71.1: - resolution: {integrity: sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==} - engines: {node: '>=14.0.0'} - hasBin: true - dependencies: - chokidar: 3.6.0 - immutable: 4.3.6 - source-map-js: 1.2.0 - dev: true - - /sass@1.77.1: - resolution: {integrity: sha512-OMEyfirt9XEfyvocduUIOlUSkWOXS/LAt6oblR/ISXCTukyavjex+zQNm51pPCOiFKY1QpWvEH1EeCkgyV3I6w==} - engines: {node: '>=14.0.0'} - hasBin: true - dependencies: - chokidar: 3.6.0 - immutable: 4.3.6 - source-map-js: 1.2.0 - dev: true - - /sax@1.3.0: - resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} - requiresBuild: true - dev: true - optional: true - - /schema-utils@3.3.0: - resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - dev: true - - /schema-utils@4.2.0: - resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} - engines: {node: '>= 12.13.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - ajv-keywords: 5.1.0(ajv@8.12.0) - dev: true - - /select-hose@2.0.0: - resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} - dev: true - - /selfsigned@2.4.1: - resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} - engines: {node: '>=10'} - dependencies: - '@types/node-forge': 1.3.11 - node-forge: 1.3.1 - dev: true - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - dependencies: - randombytes: 2.1.0 - dev: true - - /serve-index@1.9.1: - resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - batch: 0.6.1 - debug: 2.6.9 - escape-html: 1.0.3 - http-errors: 1.6.3 - mime-types: 2.1.35 - parseurl: 1.3.3 - transitivePeerDependencies: - - supports-color - dev: true - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: true - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - dev: true - - /setprototypeof@1.1.0: - resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - - /shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - dependencies: - kind-of: 6.0.3 - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /sigstore@2.3.0: - resolution: {integrity: sha512-q+o8L2ebiWD1AxD17eglf1pFrl9jtW7FHa0ygqY6EKvibK8JHyq9Z26v9MZXeDiw+RbfOJ9j2v70M10Hd6E06A==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.3.1 - '@sigstore/core': 1.1.0 - '@sigstore/protobuf-specs': 0.3.2 - '@sigstore/sign': 2.3.1 - '@sigstore/tuf': 2.3.3 - '@sigstore/verify': 1.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true - - /socket.io-adapter@2.5.4: - resolution: {integrity: sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==} - dependencies: - debug: 4.3.4 - ws: 8.11.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /socket.io-parser@4.2.4: - resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} - engines: {node: '>=10.0.0'} - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /socket.io@4.7.5: - resolution: {integrity: sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==} - engines: {node: '>=10.2.0'} - dependencies: - accepts: 1.3.8 - base64id: 2.0.0 - cors: 2.8.5 - debug: 4.3.4 - engine.io: 6.5.4 - socket.io-adapter: 2.5.4 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /sockjs@0.3.24: - resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} - dependencies: - faye-websocket: 0.11.4 - uuid: 8.3.2 - websocket-driver: 0.7.4 - dev: true - - /socks-proxy-agent@8.0.3: - resolution: {integrity: sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.1 - debug: 4.3.4 - socks: 2.8.3 - transitivePeerDependencies: - - supports-color - dev: true - - /socks@2.8.3: - resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - dev: true - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map-loader@5.0.0(webpack@5.90.3): - resolution: {integrity: sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==} - engines: {node: '>= 18.12.0'} - peerDependencies: - webpack: ^5.72.1 - dependencies: - iconv-lite: 0.6.3 - source-map-js: 1.2.0 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - dev: true - - /spdy-transport@3.0.0: - resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} - dependencies: - debug: 4.3.4 - detect-node: 2.1.0 - hpack.js: 2.1.6 - obuf: 1.1.2 - readable-stream: 3.6.2 - wbuf: 1.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /spdy@4.0.2: - resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} - engines: {node: '>=6.0.0'} - dependencies: - debug: 4.3.4 - handle-thing: 2.0.1 - http-deceiver: 1.2.7 - select-hose: 2.0.0 - spdy-transport: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - dev: true - - /ssri@10.0.6: - resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.1.1 - dev: true - - /statuses@1.5.0: - resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} - engines: {node: '>= 0.6'} - dev: true - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - - /streamroller@3.1.5: - resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} - engines: {node: '>=8.0'} - dependencies: - date-format: 4.0.14 - debug: 4.3.4 - fs-extra: 8.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /strong-log-transformer@2.1.0: - resolution: {integrity: sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==} - engines: {node: '>=4'} - hasBin: true - dependencies: - duplexer: 0.1.2 - minimist: 1.2.8 - through: 2.3.8 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /symbol-observable@4.0.0: - resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} - engines: {node: '>=0.10'} - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: true - - /tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: true - - /terser-webpack-plugin@5.3.10(esbuild@0.20.1)(webpack@5.90.3): - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - esbuild: 0.20.1 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.29.1 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /terser@5.29.1: - resolution: {integrity: sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true - - /thunky@1.1.0: - resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} - dev: true - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - - /tmp@0.2.3: - resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} - engines: {node: '>=14.14'} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true - - /tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - dev: true - - /ts-api-utils@1.3.0(typescript@5.4.5): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.4.5 - dev: true - - /tsconfig-paths@4.2.0: - resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} - engines: {node: '>=6'} - dependencies: - json5: 2.2.3 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - /tuf-js@2.2.1: - resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@tufjs/models': 2.0.1 - debug: 4.3.4 - make-fetch-happen: 13.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /turbo-darwin-64@2.3.3: - resolution: {integrity: sha512-bxX82xe6du/3rPmm4aCC5RdEilIN99VUld4HkFQuw+mvFg6darNBuQxyWSHZTtc25XgYjQrjsV05888w1grpaA==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.3.3: - resolution: {integrity: sha512-DYbQwa3NsAuWkCUYVzfOUBbSUBVQzH5HWUFy2Kgi3fGjIWVZOFk86ss+xsWu//rlEAfYwEmopigsPYSmW4X15A==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.3.3: - resolution: {integrity: sha512-eHj9OIB0dFaP6BxB88jSuaCLsOQSYWBgmhy2ErCu6D2GG6xW3b6e2UWHl/1Ho9FsTg4uVgo4DB9wGsKa5erjUA==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.3.3: - resolution: {integrity: sha512-NmDE/NjZoDj1UWBhMtOPmqFLEBKhzGS61KObfrDEbXvU3lekwHeoPvAMfcovzswzch+kN2DrtbNIlz+/rp8OCg==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.3.3: - resolution: {integrity: sha512-O2+BS4QqjK3dOERscXqv7N2GXNcqHr9hXumkMxDj/oGx9oCatIwnnwx34UmzodloSnJpgSqjl8iRWiY65SmYoQ==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.3.3: - resolution: {integrity: sha512-dW4ZK1r6XLPNYLIKjC4o87HxYidtRRcBeo/hZ9Wng2XM/MqqYkAyzJXJGgRMsc0MMEN9z4+ZIfnSNBrA0b08ag==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.3.3: - resolution: {integrity: sha512-DUHWQAcC8BTiUZDRzAYGvpSpGLiaOQPfYXlCieQbwUvmml/LRGIe3raKdrOPOoiX0DYlzxs2nH6BoWJoZrj8hA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.3.3 - turbo-darwin-arm64: 2.3.3 - turbo-linux-64: 2.3.3 - turbo-linux-arm64: 2.3.3 - turbo-windows-64: 2.3.3 - turbo-windows-arm64: 2.3.3 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: true - - /typed-assert@1.0.9: - resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==} - dev: true - - /typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /ua-parser-js@0.7.37: - resolution: {integrity: sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==} - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /undici@6.11.1: - resolution: {integrity: sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw==} - engines: {node: '>=18.0'} - dev: true - - /unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} - engines: {node: '>=4'} - dev: true - - /unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 - unicode-property-aliases-ecmascript: 2.1.0 - dev: true - - /unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} - engines: {node: '>=4'} - dev: true - - /unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} - engines: {node: '>=4'} - dev: true - - /unique-filename@3.0.0: - resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - unique-slug: 4.0.0 - dev: true - - /unique-slug@4.0.0: - resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - imurmurhash: 0.1.4 - dev: true - - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: true - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: true - - /update-browserslist-db@1.0.16(browserslist@4.23.0): - resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.1 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: true - - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /validate-npm-package-name@5.0.1: - resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: true - - /vite@5.1.7(less@4.2.0)(sass@1.71.1)(terser@5.29.1): - resolution: {integrity: sha512-sgnEEFTZYMui/sTlH1/XEnVNHMujOahPLGMxn1+5sIT45Xjng1Ec1K78jRP15dSmVgg5WBin9yO81j3o9OxofA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.19.12 - less: 4.2.0 - postcss: 8.4.38 - rollup: 4.17.2 - sass: 1.71.1 - terser: 5.29.1 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /void-elements@2.0.1: - resolution: {integrity: sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==} - engines: {node: '>=0.10.0'} - dev: true - - /watchpack@2.4.0: - resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} - engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - dev: true - - /wbuf@1.7.3: - resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} - dependencies: - minimalistic-assert: 1.0.1 - dev: true - - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - - /webpack-dev-middleware@5.3.4(webpack@5.90.3): - resolution: {integrity: sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - colorette: 2.0.20 - memfs: 3.5.3 - mime-types: 2.1.35 - range-parser: 1.2.1 - schema-utils: 4.2.0 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /webpack-dev-middleware@6.1.2(webpack@5.90.3): - resolution: {integrity: sha512-Wu+EHmX326YPYUpQLKmKbTyZZJIB8/n6R09pTmB03kJmnMsVPTo9COzHZFr01txwaCAuZvfBJE4ZCHRcKs5JaQ==} - engines: {node: '>= 14.15.0'} - peerDependencies: - webpack: ^5.0.0 - peerDependenciesMeta: - webpack: - optional: true - dependencies: - colorette: 2.0.20 - memfs: 3.5.3 - mime-types: 2.1.35 - range-parser: 1.2.1 - schema-utils: 4.2.0 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /webpack-dev-server@4.15.1(webpack@5.90.3): - resolution: {integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==} - engines: {node: '>= 12.13.0'} - hasBin: true - peerDependencies: - webpack: ^4.37.0 || ^5.0.0 - webpack-cli: '*' - peerDependenciesMeta: - webpack: - optional: true - webpack-cli: - optional: true - dependencies: - '@types/bonjour': 3.5.13 - '@types/connect-history-api-fallback': 1.5.4 - '@types/express': 4.17.21 - '@types/serve-index': 1.9.4 - '@types/serve-static': 1.15.7 - '@types/sockjs': 0.3.36 - '@types/ws': 8.5.10 - ansi-html-community: 0.0.8 - bonjour-service: 1.2.1 - chokidar: 3.6.0 - colorette: 2.0.20 - compression: 1.7.4 - connect-history-api-fallback: 2.0.0 - default-gateway: 6.0.3 - express: 4.19.2 - graceful-fs: 4.2.11 - html-entities: 2.5.2 - http-proxy-middleware: 2.0.6(@types/express@4.17.21) - ipaddr.js: 2.2.0 - launch-editor: 2.6.1 - open: 8.4.2 - p-retry: 4.6.2 - rimraf: 3.0.2 - schema-utils: 4.2.0 - selfsigned: 2.4.1 - serve-index: 1.9.1 - sockjs: 0.3.24 - spdy: 4.0.2 - webpack: 5.90.3(esbuild@0.20.1) - webpack-dev-middleware: 5.3.4(webpack@5.90.3) - ws: 8.17.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - dev: true - - /webpack-merge@5.10.0: - resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} - engines: {node: '>=10.0.0'} - dependencies: - clone-deep: 4.0.1 - flat: 5.0.2 - wildcard: 2.0.1 - dev: true - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack-subresource-integrity@5.1.0(webpack@5.90.3): - resolution: {integrity: sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==} - engines: {node: '>= 12'} - peerDependencies: - html-webpack-plugin: '>= 5.0.0-beta.1 < 6' - webpack: ^5.12.0 - peerDependenciesMeta: - html-webpack-plugin: - optional: true - dependencies: - typed-assert: 1.0.9 - webpack: 5.90.3(esbuild@0.20.1) - dev: true - - /webpack@5.90.3(esbuild@0.20.1): - resolution: {integrity: sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.1 - es-module-lexer: 1.5.2 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(esbuild@0.20.1)(webpack@5.90.3) - watchpack: 2.4.0 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - - /websocket-driver@0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} - engines: {node: '>=0.8.0'} - dependencies: - http-parser-js: 0.5.8 - safe-buffer: 5.2.1 - websocket-extensions: 0.1.4 - dev: true - - /websocket-extensions@0.1.4: - resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} - engines: {node: '>=0.8.0'} - dev: true - - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@4.0.0: - resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} - engines: {node: ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - isexe: 3.1.1 - dev: true - - /wildcard@2.0.1: - resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} - dev: true - - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /ws@8.11.0: - resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: true - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - dev: true - - /zone.js@0.14.5: - resolution: {integrity: sha512-9XYWZzY6PhHOSdkYryNcMm7L8EK7a4q+GbTvxbIA2a9lMdRUpGuyaYvLDcg8D6bdn+JomSsbPcilVKg6SmUx6w==} - dependencies: - tslib: 2.6.2 diff --git a/examples/with-berry/README.md b/examples/with-berry/README.md deleted file mode 100644 index 3ff531c164ce3..0000000000000 --- a/examples/with-berry/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Turborepo starter with berry (yarn v2+) - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-berry -``` - -## What's inside? - -This Turborepo uses [yarn v2+ (berry)](https://yarnpkg.com/) as a packages manager. It includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [Next.js](https://nextjs.org/) app -- `web`: another [Next.js](https://nextjs.org/) app -- `@repo/ui`: a stub React component library shared by both `web` and `docs` applications -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typesript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Build - -To build all apps and packages, run the following command: - -``` -cd my-turborepo -yarn build -``` - -### Develop - -To develop all apps and packages, run the following command: - -``` -cd my-turborepo -yarn dev -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -``` -cd my-turborepo -npx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your turborepo: - -``` -npx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/with-berry/apps/docs/.eslintrc.js b/examples/with-berry/apps/docs/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-berry/apps/docs/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-berry/apps/docs/README.md b/examples/with-berry/apps/docs/README.md deleted file mode 100644 index 4fae62aff6252..0000000000000 --- a/examples/with-berry/apps/docs/README.md +++ /dev/null @@ -1,30 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-berry/apps/docs/package.json b/examples/with-berry/apps/docs/package.json index 770199f0a41e2..2cd3cf7afbf3f 100644 --- a/examples/with-berry/apps/docs/package.json +++ b/examples/with-berry/apps/docs/package.json @@ -1,27 +1,17 @@ { - "name": "docs", - "version": "1.0.0", - "private": true, - "scripts": { - "build": "next build", - "dev": "next dev --port 3001", - "lint": "eslint . --max-warnings 0", - "start": "next start" - }, - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "docs", + "scripts": { + "build": "next build", + "dev": "next dev --port 3001", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-berry/apps/web/.eslintrc.js b/examples/with-berry/apps/web/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-berry/apps/web/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-berry/apps/web/README.md b/examples/with-berry/apps/web/README.md deleted file mode 100644 index 6d80fdc38b935..0000000000000 --- a/examples/with-berry/apps/web/README.md +++ /dev/null @@ -1,30 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -pnpm dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-berry/apps/web/package.json b/examples/with-berry/apps/web/package.json index 1a0afa021e01e..f5ce740cc1204 100644 --- a/examples/with-berry/apps/web/package.json +++ b/examples/with-berry/apps/web/package.json @@ -1,27 +1,17 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "build": "next build", - "dev": "next dev", - "lint": "eslint . --max-warnings 0", - "start": "next start" - }, - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-berry/package.json b/examples/with-berry/package.json index 8a0473e0b1960..10dd01a3575ec 100644 --- a/examples/with-berry/package.json +++ b/examples/with-berry/package.json @@ -1,23 +1,16 @@ { - "name": "with-berry", - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint" - }, - "devDependencies": { - "eslint": "8.57.0", - "eslint-config-custom": "*", - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "yarn@3.6.3", - "engines": { - "node": ">=18" - } + "name": "with-berry", + "workspaces": [ + "apps/*", + "packages/*" + ], + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "eslint-config-custom": "*", + "turbo": "2.4.2" + } } diff --git a/examples/with-berry/packages/eslint-config/README.md b/examples/with-berry/packages/eslint-config/README.md deleted file mode 100644 index b79474eaf968c..0000000000000 --- a/examples/with-berry/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@repo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-berry/packages/eslint-config/package.json b/examples/with-berry/packages/eslint-config/package.json index abe24eaf1e36f..dca64b8823b7a 100644 --- a/examples/with-berry/packages/eslint-config/package.json +++ b/examples/with-berry/packages/eslint-config/package.json @@ -1,19 +1,14 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js", - "react-internal.js" - ], - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@vercel/style-guide": "^5.2.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-only-warn": "^1.1.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "next.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-berry/packages/tsconfig/package.json b/examples/with-berry/packages/tsconfig/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-berry/packages/tsconfig/package.json +++ b/examples/with-berry/packages/tsconfig/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-berry/packages/ui/.eslintrc.js b/examples/with-berry/packages/ui/.eslintrc.js deleted file mode 100644 index 4cb7125da11b1..0000000000000 --- a/examples/with-berry/packages/ui/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-berry/packages/ui/src/Button.tsx b/examples/with-berry/packages/ui/Source/Button.tsx similarity index 100% rename from examples/with-berry/packages/ui/src/Button.tsx rename to examples/with-berry/packages/ui/Source/Button.tsx diff --git a/examples/with-berry/packages/ui/src/Header.tsx b/examples/with-berry/packages/ui/Source/Header.tsx similarity index 100% rename from examples/with-berry/packages/ui/src/Header.tsx rename to examples/with-berry/packages/ui/Source/Header.tsx diff --git a/examples/with-berry/packages/ui/package.json b/examples/with-berry/packages/ui/package.json index f3bacaf8dd58d..2269db2c0fb20 100644 --- a/examples/with-berry/packages/ui/package.json +++ b/examples/with-berry/packages/ui/package.json @@ -1,22 +1,13 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "exports": { - "./button": "./src/Button.tsx", - "./header": "./src/Header.tsx" - }, - "scripts": { - "lint": "eslint . --max-warnings 0" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - } + "name": "@repo/ui", + "exports": { + "./button": "./src/Button.tsx", + "./header": "./src/Header.tsx" + }, + "scripts": {}, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*" + } } diff --git a/examples/with-berry/yarn.lock b/examples/with-berry/yarn.lock deleted file mode 100644 index 676f4f39ce686..0000000000000 --- a/examples/with-berry/yarn.lock +++ /dev/null @@ -1,5346 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"@aashutoshrathi/word-wrap@npm:^1.2.3": - version: 1.2.6 - resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" - checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd - languageName: node - linkType: hard - -"@ampproject/remapping@npm:^2.2.0": - version: 2.2.1 - resolution: "@ampproject/remapping@npm:2.2.1" - dependencies: - "@jridgewell/gen-mapping": ^0.3.0 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 03c04fd526acc64a1f4df22651186f3e5ef0a9d6d6530ce4482ec9841269cf7a11dbb8af79237c282d721c5312024ff17529cd72cc4768c11e999b58e2302079 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/code-frame@npm:7.23.4" - dependencies: - "@babel/highlight": ^7.23.4 - chalk: ^2.4.2 - checksum: 29999d08c3dbd803f3c296dae7f4f40af1f9e381d6bbc76e5a75327c4b8b023bcb2e209843d292f5d71c3b5c845df1da959d415ed862d6a68e0ad6c5c9622d37 - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.22.9": - version: 7.23.3 - resolution: "@babel/compat-data@npm:7.23.3" - checksum: 52fff649d4e25b10e29e8a9b1c9ef117f44d354273c17b5ef056555f8e5db2429b35df4c38bdfb6865d23133e0fba92e558d31be87bb8457db4ac688646fdbf1 - languageName: node - linkType: hard - -"@babel/core@npm:^7.22.11": - version: 7.23.3 - resolution: "@babel/core@npm:7.23.3" - dependencies: - "@ampproject/remapping": ^2.2.0 - "@babel/code-frame": ^7.22.13 - "@babel/generator": ^7.23.3 - "@babel/helper-compilation-targets": ^7.22.15 - "@babel/helper-module-transforms": ^7.23.3 - "@babel/helpers": ^7.23.2 - "@babel/parser": ^7.23.3 - "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.3 - "@babel/types": ^7.23.3 - convert-source-map: ^2.0.0 - debug: ^4.1.0 - gensync: ^1.0.0-beta.2 - json5: ^2.2.3 - semver: ^6.3.1 - checksum: d306c1fa68972f4e085e9e7ad165aee80eb801ef331f6f07808c86309f03534d638b82ad00a3bc08f4d3de4860ccd38512b2790a39e6acc2caf9ea21e526afe7 - languageName: node - linkType: hard - -"@babel/eslint-parser@npm:^7.22.11": - version: 7.23.3 - resolution: "@babel/eslint-parser@npm:7.23.3" - dependencies: - "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 - eslint-visitor-keys: ^2.1.0 - semver: ^6.3.1 - peerDependencies: - "@babel/core": ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - checksum: 9573daebe21af5123c302c307be80cacf1c2bf236a9497068a14726d3944ef55e1282519d0ccf51882dfc369359a3442299c98cb22a419e209924db39d4030fd - languageName: node - linkType: hard - -"@babel/generator@npm:^7.23.3, @babel/generator@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/generator@npm:7.23.4" - dependencies: - "@babel/types": ^7.23.4 - "@jridgewell/gen-mapping": ^0.3.2 - "@jridgewell/trace-mapping": ^0.3.17 - jsesc: ^2.5.1 - checksum: 7403717002584eaeb58559f4d0de19b79e924ef2735711278f7cb5206d081428bf3960578566d6fa4102b7b30800d44f70acffea5ecef83f0cb62361c2a23062 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-compilation-targets@npm:7.22.15" - dependencies: - "@babel/compat-data": ^7.22.9 - "@babel/helper-validator-option": ^7.22.15 - browserslist: ^4.21.9 - lru-cache: ^5.1.1 - semver: ^6.3.1 - checksum: ce85196769e091ae54dd39e4a80c2a9df1793da8588e335c383d536d54f06baf648d0a08fc873044f226398c4ded15c4ae9120ee18e7dfd7c639a68e3cdc9980 - languageName: node - linkType: hard - -"@babel/helper-environment-visitor@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-environment-visitor@npm:7.22.20" - checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-function-name@npm:7.23.0" - dependencies: - "@babel/template": ^7.22.15 - "@babel/types": ^7.23.0 - checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 - languageName: node - linkType: hard - -"@babel/helper-hoist-variables@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-hoist-variables@npm:7.22.5" - dependencies: - "@babel/types": ^7.22.5 - checksum: 394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-module-imports@npm:7.22.15" - dependencies: - "@babel/types": ^7.22.15 - checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/helper-module-transforms@npm:7.23.3" - dependencies: - "@babel/helper-environment-visitor": ^7.22.20 - "@babel/helper-module-imports": ^7.22.15 - "@babel/helper-simple-access": ^7.22.5 - "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/helper-validator-identifier": ^7.22.20 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 5d0895cfba0e16ae16f3aa92fee108517023ad89a855289c4eb1d46f7aef4519adf8e6f971e1d55ac20c5461610e17213f1144097a8f932e768a9132e2278d71 - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-simple-access@npm:7.22.5" - dependencies: - "@babel/types": ^7.22.5 - checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 - languageName: node - linkType: hard - -"@babel/helper-split-export-declaration@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/helper-split-export-declaration@npm:7.22.6" - dependencies: - "@babel/types": ^7.22.5 - checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/helper-string-parser@npm:7.23.4" - checksum: c0641144cf1a7e7dc93f3d5f16d5327465b6cf5d036b48be61ecba41e1eece161b48f46b7f960951b67f8c3533ce506b16dece576baef4d8b3b49f8c65410f90 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.22.20, @babel/helper-validator-identifier@npm:^7.22.5": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-validator-option@npm:7.22.15" - checksum: 68da52b1e10002a543161494c4bc0f4d0398c8fdf361d5f7f4272e95c45d5b32d974896d44f6a0ea7378c9204988879d73613ca683e13bd1304e46d25ff67a8d - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.23.2": - version: 7.23.4 - resolution: "@babel/helpers@npm:7.23.4" - dependencies: - "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.4 - "@babel/types": ^7.23.4 - checksum: 85677834f2698d0a468db59c062b011ebdd65fc12bab96eeaae64084d3ce3268427ce2dbc23c2db2ddb8a305c79ea223c2c9f7bbd1fb3f6d2fa5e978c0eb1cea - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" - dependencies: - "@babel/helper-validator-identifier": ^7.22.20 - chalk: ^2.4.2 - js-tokens: ^4.0.0 - checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.3, @babel/parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/parser@npm:7.23.4" - bin: - parser: ./bin/babel-parser.js - checksum: 1d90e17d966085b8ea12f357ffcc76568969364481254f0ae3e7ed579e9421d31c7fd3876ccb3b215a5b2ada48251b0c2d0f21ba225ee194f0e18295b49085f2 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.23.2": - version: 7.23.4 - resolution: "@babel/runtime@npm:7.23.4" - dependencies: - regenerator-runtime: ^0.14.0 - checksum: 8eb6a6b2367f7d60e7f7dd83f477cc2e2fdb169e5460694d7614ce5c730e83324bcf29251b70940068e757ad1ee56ff8073a372260d90cad55f18a825caf97cd - languageName: node - linkType: hard - -"@babel/template@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/template@npm:7.22.15" - dependencies: - "@babel/code-frame": ^7.22.13 - "@babel/parser": ^7.22.15 - "@babel/types": ^7.22.15 - checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.23.3, @babel/traverse@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/traverse@npm:7.23.4" - dependencies: - "@babel/code-frame": ^7.23.4 - "@babel/generator": ^7.23.4 - "@babel/helper-environment-visitor": ^7.22.20 - "@babel/helper-function-name": ^7.23.0 - "@babel/helper-hoist-variables": ^7.22.5 - "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/parser": ^7.23.4 - "@babel/types": ^7.23.4 - debug: ^4.1.0 - globals: ^11.1.0 - checksum: e8c9cd92cfd6fec9cf3969604edea5a58c2d55275b88b9de06f0d94de43b64b04d57168554b617159d62c840a8700e6d4c7954d2e6ed69cfb918202ac01561e9 - languageName: node - linkType: hard - -"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.23.4, @babel/types@npm:^7.8.3": - version: 7.23.4 - resolution: "@babel/types@npm:7.23.4" - dependencies: - "@babel/helper-string-parser": ^7.23.4 - "@babel/helper-validator-identifier": ^7.22.20 - to-fast-properties: ^2.0.0 - checksum: 8a1ab20da663d202b1c090fdef4b157d3c7d8cb1cf60ea548f887d7b674935371409804d6cba52f870c22ced7685fcb41b0578d3edde720990de00cbb328da54 - languageName: node - linkType: hard - -"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": - version: 4.4.0 - resolution: "@eslint-community/eslint-utils@npm:4.4.0" - dependencies: - eslint-visitor-keys: ^3.3.0 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: cdfe3ae42b4f572cbfb46d20edafe6f36fc5fb52bf2d90875c58aefe226892b9677fef60820e2832caf864a326fe4fc225714c46e8389ccca04d5f9288aabd22 - languageName: node - linkType: hard - -"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b - languageName: node - linkType: hard - -"@eslint/eslintrc@npm:^2.1.4": - version: 2.1.4 - resolution: "@eslint/eslintrc@npm:2.1.4" - dependencies: - ajv: ^6.12.4 - debug: ^4.3.2 - espree: ^9.6.0 - globals: ^13.19.0 - ignore: ^5.2.0 - import-fresh: ^3.2.1 - js-yaml: ^4.1.0 - minimatch: ^3.1.2 - strip-json-comments: ^3.1.1 - checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 - languageName: node - linkType: hard - -"@eslint/js@npm:8.57.0": - version: 8.57.0 - resolution: "@eslint/js@npm:8.57.0" - checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb - languageName: node - linkType: hard - -"@humanwhocodes/config-array@npm:^0.11.14": - version: 0.11.14 - resolution: "@humanwhocodes/config-array@npm:0.11.14" - dependencies: - "@humanwhocodes/object-schema": ^2.0.2 - debug: ^4.3.1 - minimatch: ^3.0.5 - checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 - languageName: node - linkType: hard - -"@humanwhocodes/module-importer@npm:^1.0.1": - version: 1.0.1 - resolution: "@humanwhocodes/module-importer@npm:1.0.1" - checksum: 0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 - languageName: node - linkType: hard - -"@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: ^5.1.2 - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: ^7.0.1 - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: ^8.1.0 - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" - dependencies: - "@jridgewell/set-array": ^1.0.1 - "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.1.0": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 - languageName: node - linkType: hard - -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.20 - resolution: "@jridgewell/trace-mapping@npm:0.3.20" - dependencies: - "@jridgewell/resolve-uri": ^3.1.0 - "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: cd1a7353135f385909468ff0cf20bdd37e59f2ee49a13a966dedf921943e222082c583ade2b579ff6cd0d8faafcb5461f253e1bf2a9f48fec439211fdbe788f5 - languageName: node - linkType: hard - -"@microsoft/tsdoc-config@npm:0.16.2": - version: 0.16.2 - resolution: "@microsoft/tsdoc-config@npm:0.16.2" - dependencies: - "@microsoft/tsdoc": 0.14.2 - ajv: ~6.12.6 - jju: ~1.4.0 - resolve: ~1.19.0 - checksum: 12b0d703154076bcaac75ca42e804e4fc292672396441e54346d7eadd0d6b57f90980eda2b1bab89b224af86da34a2389f9054002e282011e795ca5919a4386f - languageName: node - linkType: hard - -"@microsoft/tsdoc@npm:0.14.2": - version: 0.14.2 - resolution: "@microsoft/tsdoc@npm:0.14.2" - checksum: b167c89e916ba73ee20b9c9d5dba6aa3a0de25ed3d50050e8a344dca7cd43cb2e1059bd515c820369b6e708901dd3fda476a42bc643ca74a35671ce77f724a3a - languageName: node - linkType: hard - -"@next/env@npm:14.1.1": - version: 14.1.1 - resolution: "@next/env@npm:14.1.1" - checksum: 9714e716ca26dd024b1680ca9c17be60adf4228a2bd7a1a9f71752cfd8989f005e805477453200cad0a5ed85439161563a248235fc897dc42f762cba742ec62a - languageName: node - linkType: hard - -"@next/eslint-plugin-next@npm:12.3.4": - version: 12.3.4 - resolution: "@next/eslint-plugin-next@npm:12.3.4" - dependencies: - glob: 7.1.7 - checksum: e4ae97062f3efe8f70904cf0da296ab501a2924423273352d01b18d8ffff1eb2e9a65c47dd6f9cfa0d696eada272486a3f519b2786918d0a9ab735b93f5ce4b3 - languageName: node - linkType: hard - -"@next/eslint-plugin-next@npm:^14.1.1": - version: 14.1.1 - resolution: "@next/eslint-plugin-next@npm:14.1.1" - dependencies: - glob: 10.3.10 - checksum: 3f30f56c8cdba99b40031eb82a037dbc80e1debaf2748f44ba45a433079e2492187a5f74c8878b7deeac11869bbb209a2a61ee9847caca0a7d515fbfd84a79b0 - languageName: node - linkType: hard - -"@next/swc-darwin-arm64@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-darwin-arm64@npm:14.1.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-darwin-x64@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-darwin-x64@npm:14.1.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@next/swc-linux-arm64-gnu@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-linux-arm64-gnu@npm:14.1.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-arm64-musl@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-linux-arm64-musl@npm:14.1.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-linux-x64-gnu@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-linux-x64-gnu@npm:14.1.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@next/swc-linux-x64-musl@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-linux-x64-musl@npm:14.1.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@next/swc-win32-arm64-msvc@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-win32-arm64-msvc@npm:14.1.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-win32-ia32-msvc@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-win32-ia32-msvc@npm:14.1.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@next/swc-win32-x64-msvc@npm:14.1.1": - version: 14.1.1 - resolution: "@next/swc-win32-x64-msvc@npm:14.1.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": - version: 5.1.1-v1 - resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" - dependencies: - eslint-scope: 5.1.1 - checksum: f2e3b2d6a6e2d9f163ca22105910c9f850dc4897af0aea3ef0a5886b63d8e1ba6505b71c99cb78a3bba24a09557d601eb21c8dede3f3213753fcfef364eb0e57 - languageName: node - linkType: hard - -"@nodelib/fs.scandir@npm:2.1.5": - version: 2.1.5 - resolution: "@nodelib/fs.scandir@npm:2.1.5" - dependencies: - "@nodelib/fs.stat": 2.0.5 - run-parallel: ^1.1.9 - checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 - languageName: node - linkType: hard - -"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.5 - resolution: "@nodelib/fs.stat@npm:2.0.5" - checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 - languageName: node - linkType: hard - -"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": - version: 1.2.8 - resolution: "@nodelib/fs.walk@npm:1.2.8" - dependencies: - "@nodelib/fs.scandir": 2.1.5 - fastq: ^1.6.0 - checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f - languageName: node - linkType: hard - -"@pkgr/utils@npm:^2.3.1": - version: 2.4.0 - resolution: "@pkgr/utils@npm:2.4.0" - dependencies: - cross-spawn: ^7.0.3 - fast-glob: ^3.2.12 - is-glob: ^4.0.3 - open: ^9.1.0 - picocolors: ^1.0.0 - tslib: ^2.5.0 - checksum: 2ed93a92fd58d612c7a7d04f91ce50c967d2e2d5c4f63802f62a882fcb7d91208cf89640bb3baad10ef7d42bea1e196fba956e7e36a68e9f94d2738e8974a24a - languageName: node - linkType: hard - -"@repo/eslint-config@*, @repo/eslint-config@workspace:packages/eslint-config": - version: 0.0.0-use.local - resolution: "@repo/eslint-config@workspace:packages/eslint-config" - dependencies: - "@typescript-eslint/eslint-plugin": ^7.1.0 - "@typescript-eslint/parser": ^7.1.0 - "@vercel/style-guide": ^5.2.0 - eslint-config-prettier: ^9.1.0 - eslint-config-turbo: ^2.0.0 - eslint-plugin-only-warn: ^1.1.0 - typescript: 5.5.4 - languageName: unknown - linkType: soft - -"@repo/typescript-config@*, @repo/typescript-config@workspace:packages/tsconfig": - version: 0.0.0-use.local - resolution: "@repo/typescript-config@workspace:packages/tsconfig" - languageName: unknown - linkType: soft - -"@repo/ui@*, @repo/ui@workspace:packages/ui": - version: 0.0.0-use.local - resolution: "@repo/ui@workspace:packages/ui" - dependencies: - "@repo/eslint-config": "*" - "@repo/typescript-config": "*" - "@types/react": ^18.2.61 - "@types/react-dom": ^18.2.19 - eslint: ^8.57.0 - react: ^18.2.0 - typescript: 5.5.4 - languageName: unknown - linkType: soft - -"@rushstack/eslint-patch@npm:^1.1.3": - version: 1.6.0 - resolution: "@rushstack/eslint-patch@npm:1.6.0" - checksum: 9fbc39e6070508139ac9ded5cc223780315a1e65ccb7612dd3dff07a0957fa9985a2b049bb5cae21d7eeed44ed315e2868b8755941500dc64ed9932c5760c80d - languageName: node - linkType: hard - -"@rushstack/eslint-patch@npm:^1.3.3": - version: 1.5.1 - resolution: "@rushstack/eslint-patch@npm:1.5.1" - checksum: e4c25322312dbaa29e835a7ab4fbac53c8731dd0da65e46646e38945e296429e7fb91c2ef3da5af5d5938d44b0cde1d5290438ebb3dcb015e02b80b5e2530d24 - languageName: node - linkType: hard - -"@swc/helpers@npm:0.5.2": - version: 0.5.2 - resolution: "@swc/helpers@npm:0.5.2" - dependencies: - tslib: ^2.4.0 - checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258 - languageName: node - linkType: hard - -"@types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.9": - version: 7.0.15 - resolution: "@types/json-schema@npm:7.0.15" - checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 - languageName: node - linkType: hard - -"@types/json5@npm:^0.0.29": - version: 0.0.29 - resolution: "@types/json5@npm:0.0.29" - checksum: e60b153664572116dfea673c5bda7778dbff150498f44f998e34b5886d8afc47f16799280e4b6e241c0472aef1bc36add771c569c68fc5125fc2ae519a3eb9ac - languageName: node - linkType: hard - -"@types/node@npm:^20.11.24": - version: 20.11.24 - resolution: "@types/node@npm:20.11.24" - dependencies: - undici-types: ~5.26.4 - checksum: b11a650e09e254f4725c94f226752b69949a9ac4a5e004e98f109437ac50b02df3ab4d12b2086722fedf2cb62e68b9e723abd3f358a7d7d90d741a0d3bee90c2 - languageName: node - linkType: hard - -"@types/normalize-package-data@npm:^2.4.0": - version: 2.4.4 - resolution: "@types/normalize-package-data@npm:2.4.4" - checksum: 65dff72b543997b7be8b0265eca7ace0e34b75c3e5fee31de11179d08fa7124a7a5587265d53d0409532ecb7f7fba662c2012807963e1f9b059653ec2c83ee05 - languageName: node - linkType: hard - -"@types/prop-types@npm:*": - version: 15.7.5 - resolution: "@types/prop-types@npm:15.7.5" - checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 - languageName: node - linkType: hard - -"@types/react-dom@npm:^18.2.19": - version: 18.2.19 - resolution: "@types/react-dom@npm:18.2.19" - dependencies: - "@types/react": "*" - checksum: 087a19d8e4c1c0900ec4ac5ddb749a811a38274b25683d233c11755d2895cc6e475e8bf9bea3dee36519769298e078d4c2feab9ab4bd13b26bc2a6170716437e - languageName: node - linkType: hard - -"@types/react@npm:*": - version: 18.2.5 - resolution: "@types/react@npm:18.2.5" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: 97c4534e849edf991be0820b0911d036e794b8e2599a1544f500c769acbcb4f443ccde1a3f22298f22ce368ee7757f746e4a529e889567fc142a627698e2de39 - languageName: node - linkType: hard - -"@types/react@npm:^18.2.61": - version: 18.2.61 - resolution: "@types/react@npm:18.2.61" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: a100c09bc0d6d1a0a42b3fa0944b71d209b5adea6515fc21109972ec3267185372cc416c0467b1998afce6b90fc80f4c0029b5d975afb0b3070d864c7a924a5e - languageName: node - linkType: hard - -"@types/scheduler@npm:*": - version: 0.16.3 - resolution: "@types/scheduler@npm:0.16.3" - checksum: 2b0aec39c24268e3ce938c5db2f2e77f5c3dd280e05c262d9c2fe7d890929e4632a6b8e94334017b66b45e4f92a5aa42ba3356640c2a1175fa37bef2f5200767 - languageName: node - linkType: hard - -"@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 - languageName: node - linkType: hard - -"@typescript-eslint/eslint-plugin@npm:^6.5.0": - version: 6.12.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.12.0" - dependencies: - "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.12.0 - "@typescript-eslint/type-utils": 6.12.0 - "@typescript-eslint/utils": 6.12.0 - "@typescript-eslint/visitor-keys": 6.12.0 - debug: ^4.3.4 - graphemer: ^1.4.0 - ignore: ^5.2.4 - natural-compare: ^1.4.0 - semver: ^7.5.4 - ts-api-utils: ^1.0.1 - peerDependencies: - "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: a791ebe432a6cac50a15c9e98502b62e874de0c7e35fd320b9bdca21afd4ae88c88cff45ee50a95362da14e98965d946e57b15965f5522f1153568a3fe45db8a - languageName: node - linkType: hard - -"@typescript-eslint/eslint-plugin@npm:^7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.1.0" - dependencies: - "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 7.1.0 - "@typescript-eslint/type-utils": 7.1.0 - "@typescript-eslint/utils": 7.1.0 - "@typescript-eslint/visitor-keys": 7.1.0 - debug: ^4.3.4 - graphemer: ^1.4.0 - ignore: ^5.2.4 - natural-compare: ^1.4.0 - semver: ^7.5.4 - ts-api-utils: ^1.0.1 - peerDependencies: - "@typescript-eslint/parser": ^7.0.0 - eslint: ^8.56.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 01d56d92560980fa8daaef2cb5b1e9b5231a766d6aa02697a87d079575399c90f3864e5d6032f889672329cece885faecf696683e380ce23a094fc6ef409572d - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^5.21.0": - version: 5.62.0 - resolution: "@typescript-eslint/parser@npm:5.62.0" - dependencies: - "@typescript-eslint/scope-manager": 5.62.0 - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/typescript-estree": 5.62.0 - debug: ^4.3.4 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: d168f4c7f21a7a63f47002e2d319bcbb6173597af5c60c1cf2de046b46c76b4930a093619e69faf2d30214c29ab27b54dcf1efc7046a6a6bd6f37f59a990e752 - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^6.5.0": - version: 6.12.0 - resolution: "@typescript-eslint/parser@npm:6.12.0" - dependencies: - "@typescript-eslint/scope-manager": 6.12.0 - "@typescript-eslint/types": 6.12.0 - "@typescript-eslint/typescript-estree": 6.12.0 - "@typescript-eslint/visitor-keys": 6.12.0 - debug: ^4.3.4 - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 92923b7ee61f52d6b74f515640fe6bbb6b0a922d20dabeb6b59bc73f3c132bf750a2b706bb40fbe6d233c6ecc1abe905c99aa062280bb78e5724334f5b6c4ac5 - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/parser@npm:7.1.0" - dependencies: - "@typescript-eslint/scope-manager": 7.1.0 - "@typescript-eslint/types": 7.1.0 - "@typescript-eslint/typescript-estree": 7.1.0 - "@typescript-eslint/visitor-keys": 7.1.0 - debug: ^4.3.4 - peerDependencies: - eslint: ^8.56.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 3c518414a0ccb7b16c17dfcf9bffe9e6dae1fe19640e265ce1fb2d896ea072fdb7e498c4f12f8b1517a0869f9660e64c33447d0ef7b2ce856a1d0d6d49ce2749 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/scope-manager@npm:5.62.0" - dependencies: - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/visitor-keys": 5.62.0 - checksum: 6062d6b797fe1ce4d275bb0d17204c827494af59b5eaf09d8a78cdd39dadddb31074dded4297aaf5d0f839016d601032857698b0e4516c86a41207de606e9573 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:6.12.0": - version: 6.12.0 - resolution: "@typescript-eslint/scope-manager@npm:6.12.0" - dependencies: - "@typescript-eslint/types": 6.12.0 - "@typescript-eslint/visitor-keys": 6.12.0 - checksum: 4cc4eb1bcd04ba7b0a1de4284521cde5f3f25f2530f78dfcb3f098396b142fd30a45f615a87dc7a3adddbd131a6255cb12b1df19aacff71a3f766992ddef183f - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/scope-manager@npm:7.1.0" - dependencies: - "@typescript-eslint/types": 7.1.0 - "@typescript-eslint/visitor-keys": 7.1.0 - checksum: 737c010cb60eedb2824038995150146a2099b09d0194ee0e7a2b730f29603775eba54b5260731a26e1056c4cdcc1847b5ea505228e9c240b6e31e3ed4b7a1d75 - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:6.12.0": - version: 6.12.0 - resolution: "@typescript-eslint/type-utils@npm:6.12.0" - dependencies: - "@typescript-eslint/typescript-estree": 6.12.0 - "@typescript-eslint/utils": 6.12.0 - debug: ^4.3.4 - ts-api-utils: ^1.0.1 - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: c345c45f1262eee4b9f6960a59b3aba960643d0004094a3d8fb9682ab79af2fae864695029246dc9e0d4fdb2f3d017a56b7dc034e551d263deba75c2ef048d39 - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/type-utils@npm:7.1.0" - dependencies: - "@typescript-eslint/typescript-estree": 7.1.0 - "@typescript-eslint/utils": 7.1.0 - debug: ^4.3.4 - ts-api-utils: ^1.0.1 - peerDependencies: - eslint: ^8.56.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 07c4261da12ac57a7f03064192e20bdc473074839057deb7a2d289ceb5f205f419fb5c753d81a2ed13493ae3cfe60d371348489a326474d9c4cb810c3dd96523 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/types@npm:5.62.0" - checksum: 48c87117383d1864766486f24de34086155532b070f6264e09d0e6139449270f8a9559cfef3c56d16e3bcfb52d83d42105d61b36743626399c7c2b5e0ac3b670 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:6.12.0": - version: 6.12.0 - resolution: "@typescript-eslint/types@npm:6.12.0" - checksum: d3b40f9d400f6455ce5ae610651597c9e9ec85d46ca6d3c1025597a76305c557ebc5b88340ec6db0e694c9c79f1299d375b87a1a5b9314b22231dbbb5ce54695 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/types@npm:7.1.0" - checksum: ad1e95ee83e9af7569c61260e62e4f4a42c8b82c57c33880c24dba44d1ab6792f5063e71ddf5176a1846b97158caba456805271787785250a937bba0e3df06d0 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" - dependencies: - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/visitor-keys": 5.62.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.3.7 - tsutils: ^3.21.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 3624520abb5807ed8f57b1197e61c7b1ed770c56dfcaca66372d584ff50175225798bccb701f7ef129d62c5989070e1ee3a0aa2d84e56d9524dcf011a2bb1a52 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:6.12.0": - version: 6.12.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.12.0" - dependencies: - "@typescript-eslint/types": 6.12.0 - "@typescript-eslint/visitor-keys": 6.12.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.5.4 - ts-api-utils: ^1.0.1 - peerDependenciesMeta: - typescript: - optional: true - checksum: 943f7ff2e164d812f6ae0a2d5096836aff00b1fda39937b03f126f266f03f3655794f5fc4643b49b71c312126d9422dfd764744bd1ba41ee6821a5bac1511aa2 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.1.0" - dependencies: - "@typescript-eslint/types": 7.1.0 - "@typescript-eslint/visitor-keys": 7.1.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - minimatch: 9.0.3 - semver: ^7.5.4 - ts-api-utils: ^1.0.1 - peerDependenciesMeta: - typescript: - optional: true - checksum: a4db9f2b5094f3fdeaa09ca93ffefe23a7cfab3924c870b7277d36d1f9e3e9e0bd4fb10d9a4bae75d4ce5c0d1a0193888742f080e7f43a9f1b6d105f05f570c0 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:6.12.0": - version: 6.12.0 - resolution: "@typescript-eslint/utils@npm:6.12.0" - dependencies: - "@eslint-community/eslint-utils": ^4.4.0 - "@types/json-schema": ^7.0.12 - "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.12.0 - "@typescript-eslint/types": 6.12.0 - "@typescript-eslint/typescript-estree": 6.12.0 - semver: ^7.5.4 - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - checksum: dad05bd0e4db7a88c2716f9ee83c7c28c30d71e57392e58dc0db66b5f5c4c86b9db14142c6a1a82cf1650da294d31980c56a118015d3a2a645acb8b8a5ebc315 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/utils@npm:7.1.0" - dependencies: - "@eslint-community/eslint-utils": ^4.4.0 - "@types/json-schema": ^7.0.12 - "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 7.1.0 - "@typescript-eslint/types": 7.1.0 - "@typescript-eslint/typescript-estree": 7.1.0 - semver: ^7.5.4 - peerDependencies: - eslint: ^8.56.0 - checksum: 9bf1be1fe7fad71412f5150d6ab74085b50da0f495e15a26f02239c9198a84b9376a827cbaa5ac0372ea914a5731168ac2e8a33190f0bbb84114aed27761959b - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.58.0": - version: 5.62.0 - resolution: "@typescript-eslint/utils@npm:5.62.0" - dependencies: - "@eslint-community/eslint-utils": ^4.2.0 - "@types/json-schema": ^7.0.9 - "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.62.0 - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/typescript-estree": 5.62.0 - eslint-scope: ^5.1.1 - semver: ^7.3.7 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: ee9398c8c5db6d1da09463ca7bf36ed134361e20131ea354b2da16a5fdb6df9ba70c62a388d19f6eebb421af1786dbbd79ba95ddd6ab287324fc171c3e28d931 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" - dependencies: - "@typescript-eslint/types": 5.62.0 - eslint-visitor-keys: ^3.3.0 - checksum: 976b05d103fe8335bef5c93ad3f76d781e3ce50329c0243ee0f00c0fcfb186c81df50e64bfdd34970148113f8ade90887f53e3c4938183afba830b4ba8e30a35 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:6.12.0": - version: 6.12.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.12.0" - dependencies: - "@typescript-eslint/types": 6.12.0 - eslint-visitor-keys: ^3.4.1 - checksum: 3d8dc74ae748a95fe60b48dbaecca8d9c0c8df344d8034e3843057251fba24f06a3d29dbb9f525c9540b538d8c24221d3cf119ac483e9de38149a978051c72f3 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.1.0" - dependencies: - "@typescript-eslint/types": 7.1.0 - eslint-visitor-keys: ^3.4.1 - checksum: 7ddac02dde4e16960ca87f0c05e5c5176fef6203bbf39d217ae15f8db498c262677a5799a258960a8d6bbcbc2ffbb799841e32276d2867f1e2f88bd988606092 - languageName: node - linkType: hard - -"@ungap/structured-clone@npm:^1.2.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 - languageName: node - linkType: hard - -"@vercel/style-guide@npm:^5.2.0": - version: 5.2.0 - resolution: "@vercel/style-guide@npm:5.2.0" - dependencies: - "@babel/core": ^7.22.11 - "@babel/eslint-parser": ^7.22.11 - "@rushstack/eslint-patch": ^1.3.3 - "@typescript-eslint/eslint-plugin": ^6.5.0 - "@typescript-eslint/parser": ^6.5.0 - eslint-config-prettier: ^9.0.0 - eslint-import-resolver-alias: ^1.1.2 - eslint-import-resolver-typescript: ^3.6.0 - eslint-plugin-eslint-comments: ^3.2.0 - eslint-plugin-import: ^2.28.1 - eslint-plugin-jest: ^27.2.3 - eslint-plugin-jsx-a11y: ^6.7.1 - eslint-plugin-playwright: ^0.16.0 - eslint-plugin-react: ^7.33.2 - eslint-plugin-react-hooks: ^4.6.0 - eslint-plugin-testing-library: ^6.0.1 - eslint-plugin-tsdoc: ^0.2.17 - eslint-plugin-unicorn: ^48.0.1 - prettier-plugin-packagejson: ^2.4.5 - peerDependencies: - "@next/eslint-plugin-next": ">=12.3.0 <15" - eslint: ">=8.48.0 <9" - prettier: ">=3.0.0 <4" - typescript: ">=4.8.0 <6" - peerDependenciesMeta: - "@next/eslint-plugin-next": - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - checksum: ae78cc95252f4b53b4ef38efd64c865428ace29f56945ef9a2c57ba4b2ed328b0f1f483c328bb0ac161aae9d87097acd741a70e57c005421694486fa3ea4ba9b - languageName: node - linkType: hard - -"acorn-jsx@npm:^5.3.2": - version: 5.3.2 - resolution: "acorn-jsx@npm:5.3.2" - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 - languageName: node - linkType: hard - -"acorn@npm:^8.9.0": - version: 8.11.2 - resolution: "acorn@npm:8.11.2" - bin: - acorn: bin/acorn - checksum: 818450408684da89423e3daae24e4dc9b68692db8ab49ea4569c7c5abb7a3f23669438bf129cc81dfdada95e1c9b944ee1bfca2c57a05a4dc73834a612fbf6a7 - languageName: node - linkType: hard - -"ajv@npm:^6.12.4, ajv@npm:~6.12.6": - version: 6.12.6 - resolution: "ajv@npm:6.12.6" - dependencies: - fast-deep-equal: ^3.1.1 - fast-json-stable-stringify: ^2.0.0 - json-schema-traverse: ^0.4.1 - uri-js: ^4.2.2 - checksum: 874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 - languageName: node - linkType: hard - -"ansi-styles@npm:^3.2.1": - version: 3.2.1 - resolution: "ansi-styles@npm:3.2.1" - dependencies: - color-convert: ^1.9.0 - checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: ^2.0.1 - checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 - languageName: node - linkType: hard - -"argparse@npm:^2.0.1": - version: 2.0.1 - resolution: "argparse@npm:2.0.1" - checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced - languageName: node - linkType: hard - -"aria-query@npm:^5.3.0": - version: 5.3.0 - resolution: "aria-query@npm:5.3.0" - dependencies: - dequal: ^2.0.3 - checksum: 305bd73c76756117b59aba121d08f413c7ff5e80fa1b98e217a3443fcddb9a232ee790e24e432b59ae7625aebcf4c47cb01c2cac872994f0b426f5bdfcd96ba9 - languageName: node - linkType: hard - -"array-buffer-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "array-buffer-byte-length@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - is-array-buffer: ^3.0.1 - checksum: 044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 - languageName: node - linkType: hard - -"array-includes@npm:^3.1.4, array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": - version: 3.1.6 - resolution: "array-includes@npm:3.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - get-intrinsic: ^1.1.3 - is-string: ^1.0.7 - checksum: f22f8cd8ba8a6448d91eebdc69f04e4e55085d09232b5216ee2d476dab3ef59984e8d1889e662c6a0ed939dcb1b57fd05b2c0209c3370942fc41b752c82a2ca5 - languageName: node - linkType: hard - -"array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - is-string: ^1.0.7 - checksum: 06f9e4598fac12a919f7c59a3f04f010ea07f0b7f0585465ed12ef528a60e45f374e79d1bddbb34cdd4338357d00023ddbd0ac18b0be36964f5e726e8965d7fc - languageName: node - linkType: hard - -"array-union@npm:^2.1.0": - version: 2.1.0 - resolution: "array-union@npm:2.1.0" - checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d - languageName: node - linkType: hard - -"array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.3 - resolution: "array.prototype.findlastindex@npm:1.2.3" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.2.1 - checksum: 31f35d7b370c84db56484618132041a9af401b338f51899c2e78ef7690fbba5909ee7ca3c59a7192085b328cc0c68c6fd1f6d1553db01a689a589ae510f3966e - languageName: node - linkType: hard - -"array.prototype.flat@npm:^1.3.1": - version: 1.3.1 - resolution: "array.prototype.flat@npm:1.3.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - checksum: 5a8415949df79bf6e01afd7e8839bbde5a3581300e8ad5d8449dea52639e9e59b26a467665622783697917b43bf39940a6e621877c7dd9b3d1c1f97484b9b88b - languageName: node - linkType: hard - -"array.prototype.flat@npm:^1.3.2": - version: 1.3.2 - resolution: "array.prototype.flat@npm:1.3.2" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - checksum: 5d6b4bf102065fb3f43764bfff6feb3295d372ce89591e6005df3d0ce388527a9f03c909af6f2a973969a4d178ab232ffc9236654149173e0e187ec3a1a6b87b - languageName: node - linkType: hard - -"array.prototype.flatmap@npm:^1.2.5, array.prototype.flatmap@npm:^1.3.1": - version: 1.3.1 - resolution: "array.prototype.flatmap@npm:1.3.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - checksum: 8c1c43a4995f12cf12523436da28515184c753807b3f0bc2ca6c075f71c470b099e2090cc67dba8e5280958fea401c1d0c59e1db0143272aef6cd1103921a987 - languageName: node - linkType: hard - -"array.prototype.flatmap@npm:^1.3.2": - version: 1.3.2 - resolution: "array.prototype.flatmap@npm:1.3.2" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - checksum: ce09fe21dc0bcd4f30271f8144083aa8c13d4639074d6c8dc82054b847c7fc9a0c97f857491f4da19d4003e507172a78f4bcd12903098adac8b9cd374f734be3 - languageName: node - linkType: hard - -"array.prototype.tosorted@npm:^1.1.1": - version: 1.1.1 - resolution: "array.prototype.tosorted@npm:1.1.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.1.3 - checksum: 7923324a67e70a2fc0a6e40237405d92395e45ebd76f5cb89c2a5cf1e66b47aca6baacd0cd628ffd88830b90d47fff268071493d09c9ae123645613dac2c2ca3 - languageName: node - linkType: hard - -"arraybuffer.prototype.slice@npm:^1.0.2": - version: 1.0.2 - resolution: "arraybuffer.prototype.slice@npm:1.0.2" - dependencies: - array-buffer-byte-length: ^1.0.0 - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - is-array-buffer: ^3.0.2 - is-shared-array-buffer: ^1.0.2 - checksum: c200faf437786f5b2c80d4564ff5481c886a16dee642ef02abdc7306c7edd523d1f01d1dd12b769c7eb42ac9bc53874510db19a92a2c035c0f6696172aafa5d3 - languageName: node - linkType: hard - -"ast-types-flow@npm:^0.0.8": - version: 0.0.8 - resolution: "ast-types-flow@npm:0.0.8" - checksum: 0a64706609a179233aac23817837abab614f3548c252a2d3d79ea1e10c74aa28a0846e11f466cf72771b6ed8713abc094dcf8c40c3ec4207da163efa525a94a8 - languageName: node - linkType: hard - -"asynciterator.prototype@npm:^1.0.0": - version: 1.0.0 - resolution: "asynciterator.prototype@npm:1.0.0" - dependencies: - has-symbols: ^1.0.3 - checksum: e8ebfd9493ac651cf9b4165e9d64030b3da1d17181bb1963627b59e240cdaf021d9b59d44b827dc1dde4e22387ec04c2d0f8720cf58a1c282e34e40cc12721b3 - languageName: node - linkType: hard - -"available-typed-arrays@npm:^1.0.5": - version: 1.0.5 - resolution: "available-typed-arrays@npm:1.0.5" - checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a - languageName: node - linkType: hard - -"axe-core@npm:=4.7.0": - version: 4.7.0 - resolution: "axe-core@npm:4.7.0" - checksum: f086bcab42be1761ba2b0b127dec350087f4c3a853bba8dd58f69d898cefaac31a1561da23146f6f3c07954c76171d1f2ce460e555e052d2b02cd79af628fa4a - languageName: node - linkType: hard - -"axobject-query@npm:^3.2.1": - version: 3.2.1 - resolution: "axobject-query@npm:3.2.1" - dependencies: - dequal: ^2.0.3 - checksum: a94047e702b57c91680e6a952ec4a1aaa2cfd0d80ead76bc8c954202980d8c51968a6ea18b4d8010e8e2cf95676533d8022a8ebba9abc1dfe25686721df26fd2 - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 - languageName: node - linkType: hard - -"big-integer@npm:^1.6.44": - version: 1.6.51 - resolution: "big-integer@npm:1.6.51" - checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518 - languageName: node - linkType: hard - -"bplist-parser@npm:^0.2.0": - version: 0.2.0 - resolution: "bplist-parser@npm:0.2.0" - dependencies: - big-integer: ^1.6.44 - checksum: d5339dd16afc51de6c88f88f58a45b72ed6a06aa31f5557d09877575f220b7c1d3fbe375da0b62e6a10d4b8ed80523567e351f24014f5bc886ad523758142cdd - languageName: node - linkType: hard - -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: ^1.0.0 - concat-map: 0.0.1 - checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: ^1.0.0 - checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 - languageName: node - linkType: hard - -"braces@npm:^3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" - dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 - languageName: node - linkType: hard - -"browserslist@npm:^4.21.9": - version: 4.22.1 - resolution: "browserslist@npm:4.22.1" - dependencies: - caniuse-lite: ^1.0.30001541 - electron-to-chromium: ^1.4.535 - node-releases: ^2.0.13 - update-browserslist-db: ^1.0.13 - bin: - browserslist: cli.js - checksum: 7e6b10c53f7dd5d83fd2b95b00518889096382539fed6403829d447e05df4744088de46a571071afb447046abc3c66ad06fbc790e70234ec2517452e32ffd862 - languageName: node - linkType: hard - -"builtin-modules@npm:^3.3.0": - version: 3.3.0 - resolution: "builtin-modules@npm:3.3.0" - checksum: db021755d7ed8be048f25668fe2117620861ef6703ea2c65ed2779c9e3636d5c3b82325bd912244293959ff3ae303afa3471f6a15bf5060c103e4cc3a839749d - languageName: node - linkType: hard - -"bundle-name@npm:^3.0.0": - version: 3.0.0 - resolution: "bundle-name@npm:3.0.0" - dependencies: - run-applescript: ^5.0.0 - checksum: edf2b1fbe6096ed32e7566947ace2ea937ee427391744d7510a2880c4b9a5b3543d3f6c551236a29e5c87d3195f8e2912516290e638c15bcbede7b37cc375615 - languageName: node - linkType: hard - -"busboy@npm:1.6.0": - version: 1.6.0 - resolution: "busboy@npm:1.6.0" - dependencies: - streamsearch: ^1.1.0 - checksum: 32801e2c0164e12106bf236291a00795c3c4e4b709ae02132883fe8478ba2ae23743b11c5735a0aae8afe65ac4b6ca4568b91f0d9fed1fdbc32ede824a73746e - languageName: node - linkType: hard - -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind@npm:1.0.2" - dependencies: - function-bind: ^1.1.1 - get-intrinsic: ^1.0.2 - checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 - languageName: node - linkType: hard - -"call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": - version: 1.0.5 - resolution: "call-bind@npm:1.0.5" - dependencies: - function-bind: ^1.1.2 - get-intrinsic: ^1.2.1 - set-function-length: ^1.1.1 - checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 - languageName: node - linkType: hard - -"callsites@npm:^3.0.0": - version: 3.1.0 - resolution: "callsites@npm:3.1.0" - checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001541": - version: 1.0.30001564 - resolution: "caniuse-lite@npm:1.0.30001564" - checksum: 5b53749a2e9057e74c5a129fc214fa4434d3f0c3faadbec176efa03b44e40f9c1ef8ceec979f0dd186f7a142476713129df9263e012a178351ba7807217f157a - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001579": - version: 1.0.30001593 - resolution: "caniuse-lite@npm:1.0.30001593" - checksum: 3e2b19075563c3222101c8d5e6ab2f6e1ba99c3ad03b8d2449f9ee7ed03e9d3dac0b1fb24c129e9a5d89fdde4abb97392280c0abb113c0c60250a2b49f378c60 - languageName: node - linkType: hard - -"chalk@npm:^2.4.2": - version: 2.4.2 - resolution: "chalk@npm:2.4.2" - dependencies: - ansi-styles: ^3.2.1 - escape-string-regexp: ^1.0.5 - supports-color: ^5.3.0 - checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 - languageName: node - linkType: hard - -"chalk@npm:^4.0.0": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc - languageName: node - linkType: hard - -"ci-info@npm:^3.8.0": - version: 3.9.0 - resolution: "ci-info@npm:3.9.0" - checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 - languageName: node - linkType: hard - -"clean-regexp@npm:^1.0.0": - version: 1.0.0 - resolution: "clean-regexp@npm:1.0.0" - dependencies: - escape-string-regexp: ^1.0.5 - checksum: 0b1ce281b07da2463c6882ea2e8409119b6cabbd9f687cdbdcee942c45b2b9049a2084f7b5f228c63ef9f21e722963ae0bfe56a735dbdbdd92512867625a7e40 - languageName: node - linkType: hard - -"client-only@npm:0.0.1": - version: 0.0.1 - resolution: "client-only@npm:0.0.1" - checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8 - languageName: node - linkType: hard - -"color-convert@npm:^1.9.0": - version: 1.9.3 - resolution: "color-convert@npm:1.9.3" - dependencies: - color-name: 1.1.3 - checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: ~1.1.4 - checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 - languageName: node - linkType: hard - -"color-name@npm:1.1.3": - version: 1.1.3 - resolution: "color-name@npm:1.1.3" - checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 - languageName: node - linkType: hard - -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af - languageName: node - linkType: hard - -"convert-source-map@npm:^2.0.0": - version: 2.0.0 - resolution: "convert-source-map@npm:2.0.0" - checksum: 63ae9933be5a2b8d4509daca5124e20c14d023c820258e484e32dc324d34c2754e71297c94a05784064ad27615037ef677e3f0c00469fb55f409d2bb21261035 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: ^3.1.0 - shebang-command: ^2.0.0 - which: ^2.0.1 - checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 - languageName: node - linkType: hard - -"csstype@npm:^3.0.2": - version: 3.1.2 - resolution: "csstype@npm:3.1.2" - checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 - languageName: node - linkType: hard - -"damerau-levenshtein@npm:^1.0.8": - version: 1.0.8 - resolution: "damerau-levenshtein@npm:1.0.8" - checksum: d240b7757544460ae0586a341a53110ab0a61126570ef2d8c731e3eab3f0cb6e488e2609e6a69b46727635de49be20b071688698744417ff1b6c1d7ccd03e0de - languageName: node - linkType: hard - -"debug@npm:^3.2.7": - version: 3.2.7 - resolution: "debug@npm:3.2.7" - dependencies: - ms: ^2.1.1 - checksum: b3d8c5940799914d30314b7c3304a43305fd0715581a919dacb8b3176d024a782062368405b47491516d2091d6462d4d11f2f4974a405048094f8bfebfa3071c - languageName: node - linkType: hard - -"debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" - dependencies: - ms: 2.1.2 - peerDependenciesMeta: - supports-color: - optional: true - checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 - languageName: node - linkType: hard - -"deep-is@npm:^0.1.3": - version: 0.1.4 - resolution: "deep-is@npm:0.1.4" - checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 - languageName: node - linkType: hard - -"default-browser-id@npm:^3.0.0": - version: 3.0.0 - resolution: "default-browser-id@npm:3.0.0" - dependencies: - bplist-parser: ^0.2.0 - untildify: ^4.0.0 - checksum: 279c7ad492542e5556336b6c254a4eaf31b2c63a5433265655ae6e47301197b6cfb15c595a6fdc6463b2ff8e1a1a1ed3cba56038a60e1527ba4ab1628c6b9941 - languageName: node - linkType: hard - -"default-browser@npm:^4.0.0": - version: 4.0.0 - resolution: "default-browser@npm:4.0.0" - dependencies: - bundle-name: ^3.0.0 - default-browser-id: ^3.0.0 - execa: ^7.1.1 - titleize: ^3.0.0 - checksum: 40c5af984799042b140300be5639c9742599bda76dc9eba5ac9ad5943c83dd36cebc4471eafcfddf8e0ec817166d5ba89d56f08e66a126c7c7908a179cead1a7 - languageName: node - linkType: hard - -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": - version: 1.1.1 - resolution: "define-data-property@npm:1.1.1" - dependencies: - get-intrinsic: ^1.2.1 - gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d - languageName: node - linkType: hard - -"define-lazy-prop@npm:^3.0.0": - version: 3.0.0 - resolution: "define-lazy-prop@npm:3.0.0" - checksum: 54884f94caac0791bf6395a3ec530ce901cf71c47b0196b8754f3fd17edb6c0e80149c1214429d851873bb0d689dbe08dcedbb2306dc45c8534a5934723851b6 - languageName: node - linkType: hard - -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4, define-properties@npm:^1.2.0": - version: 1.2.0 - resolution: "define-properties@npm:1.2.0" - dependencies: - has-property-descriptors: ^1.0.0 - object-keys: ^1.1.1 - checksum: e60aee6a19b102df4e2b1f301816804e81ab48bb91f00d0d935f269bf4b3f79c88b39e4f89eaa132890d23267335fd1140dfcd8d5ccd61031a0a2c41a54e33a6 - languageName: node - linkType: hard - -"define-properties@npm:^1.2.1": - version: 1.2.1 - resolution: "define-properties@npm:1.2.1" - dependencies: - define-data-property: ^1.0.1 - has-property-descriptors: ^1.0.0 - object-keys: ^1.1.1 - checksum: b4ccd00597dd46cb2d4a379398f5b19fca84a16f3374e2249201992f36b30f6835949a9429669ee6b41b6e837205a163eadd745e472069e70dfc10f03e5fcc12 - languageName: node - linkType: hard - -"dequal@npm:^2.0.3": - version: 2.0.3 - resolution: "dequal@npm:2.0.3" - checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90 - languageName: node - linkType: hard - -"detect-indent@npm:^7.0.1": - version: 7.0.1 - resolution: "detect-indent@npm:7.0.1" - checksum: cbf3f0b1c3c881934ca94428e1179b26ab2a587e0d719031d37a67fb506d49d067de54ff057cb1e772e75975fed5155c01cd4518306fee60988b1486e3fc7768 - languageName: node - linkType: hard - -"detect-newline@npm:^4.0.0": - version: 4.0.1 - resolution: "detect-newline@npm:4.0.1" - checksum: 0409ecdfb93419591ccff24fccfe2ddddad29b66637d1ed898872125b25af05014fdeedc9306339577060f69f59fe6e9830cdd80948597f136dfbffefa60599c - languageName: node - linkType: hard - -"dir-glob@npm:^3.0.1": - version: 3.0.1 - resolution: "dir-glob@npm:3.0.1" - dependencies: - path-type: ^4.0.0 - checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 - languageName: node - linkType: hard - -"docs@workspace:apps/docs": - version: 0.0.0-use.local - resolution: "docs@workspace:apps/docs" - dependencies: - "@next/eslint-plugin-next": ^14.1.1 - "@repo/eslint-config": "*" - "@repo/typescript-config": "*" - "@repo/ui": "*" - "@types/node": ^20.11.24 - "@types/react": ^18.2.61 - "@types/react-dom": ^18.2.19 - eslint: ^8.57.0 - next: ^14.1.1 - react: ^18.2.0 - react-dom: ^18.2.0 - typescript: 5.5.4 - languageName: unknown - linkType: soft - -"doctrine@npm:^2.1.0": - version: 2.1.0 - resolution: "doctrine@npm:2.1.0" - dependencies: - esutils: ^2.0.2 - checksum: a45e277f7feaed309fe658ace1ff286c6e2002ac515af0aaf37145b8baa96e49899638c7cd47dccf84c3d32abfc113246625b3ac8f552d1046072adee13b0dc8 - languageName: node - linkType: hard - -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: ^2.0.2 - checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce - languageName: node - linkType: hard - -"dotenv@npm:16.0.3": - version: 16.0.3 - resolution: "dotenv@npm:16.0.3" - checksum: afcf03f373d7a6d62c7e9afea6328e62851d627a4e73f2e12d0a8deae1cd375892004f3021883f8aec85932cd2834b091f568ced92b4774625b321db83b827f8 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.4.535": - version: 1.4.591 - resolution: "electron-to-chromium@npm:1.4.591" - checksum: 1deb319475acbf946fba94e1bb0dd06bbb27eadd6450c940952c0b36979b472f7dbd6150f3a7f20269373cf7d6bdfcb554f824441b18e0107edf977f08a23e51 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 - languageName: node - linkType: hard - -"enhanced-resolve@npm:^5.12.0": - version: 5.13.0 - resolution: "enhanced-resolve@npm:5.13.0" - dependencies: - graceful-fs: ^4.2.4 - tapable: ^2.2.0 - checksum: 76d6844c4393d76beed5b3ce6cf5a98dee3ad5c84a9887f49ccde1224e3b7af201dfbd5a57ebf2b49f623b74883df262d50ff480d3cc02fc2881fc58b84e1bbe - languageName: node - linkType: hard - -"error-ex@npm:^1.3.1": - version: 1.3.2 - resolution: "error-ex@npm:1.3.2" - dependencies: - is-arrayish: ^0.2.1 - checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 - languageName: node - linkType: hard - -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4": - version: 1.21.2 - resolution: "es-abstract@npm:1.21.2" - dependencies: - array-buffer-byte-length: ^1.0.0 - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - es-set-tostringtag: ^2.0.1 - es-to-primitive: ^1.2.1 - function.prototype.name: ^1.1.5 - get-intrinsic: ^1.2.0 - get-symbol-description: ^1.0.0 - globalthis: ^1.0.3 - gopd: ^1.0.1 - has: ^1.0.3 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 - has-symbols: ^1.0.3 - internal-slot: ^1.0.5 - is-array-buffer: ^3.0.2 - is-callable: ^1.2.7 - is-negative-zero: ^2.0.2 - is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 - is-string: ^1.0.7 - is-typed-array: ^1.1.10 - is-weakref: ^1.0.2 - object-inspect: ^1.12.3 - object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.4.3 - safe-regex-test: ^1.0.0 - string.prototype.trim: ^1.2.7 - string.prototype.trimend: ^1.0.6 - string.prototype.trimstart: ^1.0.6 - typed-array-length: ^1.0.4 - unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.9 - checksum: 037f55ee5e1cdf2e5edbab5524095a4f97144d95b94ea29e3611b77d852fd8c8a40e7ae7101fa6a759a9b9b1405f188c3c70928f2d3cd88d543a07fc0d5ad41a - languageName: node - linkType: hard - -"es-abstract@npm:^1.22.1": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" - dependencies: - array-buffer-byte-length: ^1.0.0 - arraybuffer.prototype.slice: ^1.0.2 - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.5 - es-set-tostringtag: ^2.0.1 - es-to-primitive: ^1.2.1 - function.prototype.name: ^1.1.6 - get-intrinsic: ^1.2.2 - get-symbol-description: ^1.0.0 - globalthis: ^1.0.3 - gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 - has-symbols: ^1.0.3 - hasown: ^2.0.0 - internal-slot: ^1.0.5 - is-array-buffer: ^3.0.2 - is-callable: ^1.2.7 - is-negative-zero: ^2.0.2 - is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 - is-string: ^1.0.7 - is-typed-array: ^1.1.12 - is-weakref: ^1.0.2 - object-inspect: ^1.13.1 - object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.5.1 - safe-array-concat: ^1.0.1 - safe-regex-test: ^1.0.0 - string.prototype.trim: ^1.2.8 - string.prototype.trimend: ^1.0.7 - string.prototype.trimstart: ^1.0.7 - typed-array-buffer: ^1.0.0 - typed-array-byte-length: ^1.0.0 - typed-array-byte-offset: ^1.0.0 - typed-array-length: ^1.0.4 - unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.13 - checksum: b1bdc962856836f6e72be10b58dc128282bdf33771c7a38ae90419d920fc3b36cc5d2b70a222ad8016e3fc322c367bf4e9e89fc2bc79b7e933c05b218e83d79a - languageName: node - linkType: hard - -"es-iterator-helpers@npm:^1.0.12, es-iterator-helpers@npm:^1.0.15": - version: 1.0.15 - resolution: "es-iterator-helpers@npm:1.0.15" - dependencies: - asynciterator.prototype: ^1.0.0 - call-bind: ^1.0.2 - define-properties: ^1.2.1 - es-abstract: ^1.22.1 - es-set-tostringtag: ^2.0.1 - function-bind: ^1.1.1 - get-intrinsic: ^1.2.1 - globalthis: ^1.0.3 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 - has-symbols: ^1.0.3 - internal-slot: ^1.0.5 - iterator.prototype: ^1.1.2 - safe-array-concat: ^1.0.1 - checksum: 50081ae5c549efe62e5c1d244df0194b40b075f7897fc2116b7e1aa437eb3c41f946d2afda18c33f9b31266ec544765932542765af839f76fa6d7b7855d1e0e1 - languageName: node - linkType: hard - -"es-set-tostringtag@npm:^2.0.1": - version: 2.0.1 - resolution: "es-set-tostringtag@npm:2.0.1" - dependencies: - get-intrinsic: ^1.1.3 - has: ^1.0.3 - has-tostringtag: ^1.0.0 - checksum: ec416a12948cefb4b2a5932e62093a7cf36ddc3efd58d6c58ca7ae7064475ace556434b869b0bbeb0c365f1032a8ccd577211101234b69837ad83ad204fff884 - languageName: node - linkType: hard - -"es-shim-unscopables@npm:^1.0.0": - version: 1.0.0 - resolution: "es-shim-unscopables@npm:1.0.0" - dependencies: - has: ^1.0.3 - checksum: 83e95cadbb6ee44d3644dfad60dcad7929edbc42c85e66c3e99aefd68a3a5c5665f2686885cddb47dfeabfd77bd5ea5a7060f2092a955a729bbd8834f0d86fa1 - languageName: node - linkType: hard - -"es-to-primitive@npm:^1.2.1": - version: 1.2.1 - resolution: "es-to-primitive@npm:1.2.1" - dependencies: - is-callable: ^1.1.4 - is-date-object: ^1.0.1 - is-symbol: ^1.0.2 - checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed - languageName: node - linkType: hard - -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 - languageName: node - linkType: hard - -"eslint-config-custom@npm:*": - version: 0.0.0 - resolution: "eslint-config-custom@npm:0.0.0" - dependencies: - eslint-config-next: ^12.0.8 - eslint-config-prettier: ^8.3.0 - eslint-plugin-react: 7.28.0 - checksum: 5547fc411e4deb779ecd293d6d40e552125a356e38762b0e5e96e4d4c8898ac588b396dddc47ce331ca9b363f9dc05286275e45e42d25791910b9a6d17e1d7bd - languageName: node - linkType: hard - -"eslint-config-next@npm:^12.0.8": - version: 12.3.4 - resolution: "eslint-config-next@npm:12.3.4" - dependencies: - "@next/eslint-plugin-next": 12.3.4 - "@rushstack/eslint-patch": ^1.1.3 - "@typescript-eslint/parser": ^5.21.0 - eslint-import-resolver-node: ^0.3.6 - eslint-import-resolver-typescript: ^2.7.1 - eslint-plugin-import: ^2.26.0 - eslint-plugin-jsx-a11y: ^6.5.1 - eslint-plugin-react: ^7.31.7 - eslint-plugin-react-hooks: ^4.5.0 - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - typescript: ">=3.3.1" - peerDependenciesMeta: - typescript: - optional: true - checksum: 53cd24d7b764fe382812a5e76571083fe59e892ac88ac5ccddf171e261f5a3ea36cb1c34283f97569c97a4bae51ece5252d5aa71fd130d31ada94310dc4147ee - languageName: node - linkType: hard - -"eslint-config-prettier@npm:^8.3.0": - version: 8.8.0 - resolution: "eslint-config-prettier@npm:8.8.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 1e94c3882c4d5e41e1dcfa2c368dbccbfe3134f6ac7d40101644d3bfbe3eb2f2ffac757f3145910b5eacf20c0e85e02b91293d3126d770cbf3dc390b3564681c - languageName: node - linkType: hard - -"eslint-config-prettier@npm:^9.0.0": - version: 9.0.0 - resolution: "eslint-config-prettier@npm:9.0.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 362e991b6cb343f79362bada2d97c202e5303e6865888918a7445c555fb75e4c078b01278e90be98aa98ae22f8597d8e93d48314bec6824f540f7efcab3ce451 - languageName: node - linkType: hard - -"eslint-config-prettier@npm:^9.1.0": - version: 9.1.0 - resolution: "eslint-config-prettier@npm:9.1.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 9229b768c879f500ee54ca05925f31b0c0bafff3d9f5521f98ff05127356de78c81deb9365c86a5ec4efa990cb72b74df8612ae15965b14136044c73e1f6a907 - languageName: node - linkType: hard - -"eslint-config-turbo@npm:^2.0.0": - version: 2.0.0 - resolution: "eslint-config-turbo@npm:2.0.0" - dependencies: - eslint-plugin-turbo: 2.0.0 - peerDependencies: - eslint: ">6.6.0" - checksum: d4cd50b4fdd19f285cfe5231800fd7165884eb42115363273fd7b8a5f7a9c5fbb8d926ccf84efc92e722d6cae4ccd87511a0b58e67df0bbcbcfd9f18fc05b13b - languageName: node - linkType: hard - -"eslint-import-resolver-alias@npm:^1.1.2": - version: 1.1.2 - resolution: "eslint-import-resolver-alias@npm:1.1.2" - peerDependencies: - eslint-plugin-import: ">=1.4.0" - checksum: 3fbb9aeda98335060bb438ed8446a060d282f80a365838a82edb1f8743b1d54c89303009c7717e3c915d5d722e57148082c5ada4455e811acdc8ed3a65059fa1 - languageName: node - linkType: hard - -"eslint-import-resolver-node@npm:^0.3.6": - version: 0.3.7 - resolution: "eslint-import-resolver-node@npm:0.3.7" - dependencies: - debug: ^3.2.7 - is-core-module: ^2.11.0 - resolve: ^1.22.1 - checksum: 3379aacf1d2c6952c1b9666c6fa5982c3023df695430b0d391c0029f6403a7775414873d90f397e98ba6245372b6c8960e16e74d9e4a3b0c0a4582f3bdbe3d6e - languageName: node - linkType: hard - -"eslint-import-resolver-node@npm:^0.3.9": - version: 0.3.9 - resolution: "eslint-import-resolver-node@npm:0.3.9" - dependencies: - debug: ^3.2.7 - is-core-module: ^2.13.0 - resolve: ^1.22.4 - checksum: 439b91271236b452d478d0522a44482e8c8540bf9df9bd744062ebb89ab45727a3acd03366a6ba2bdbcde8f9f718bab7fe8db64688aca75acf37e04eafd25e22 - languageName: node - linkType: hard - -"eslint-import-resolver-typescript@npm:^2.7.1": - version: 2.7.1 - resolution: "eslint-import-resolver-typescript@npm:2.7.1" - dependencies: - debug: ^4.3.4 - glob: ^7.2.0 - is-glob: ^4.0.3 - resolve: ^1.22.0 - tsconfig-paths: ^3.14.1 - peerDependencies: - eslint: "*" - eslint-plugin-import: "*" - checksum: 1d81b657b1f73bf95b8f0b745c0305574b91630c1db340318f3ca8918e206fce20a933b95e7c419338cc4452cb80bb2b2d92acaf01b6aa315c78a332d832545c - languageName: node - linkType: hard - -"eslint-import-resolver-typescript@npm:^3.6.0": - version: 3.6.1 - resolution: "eslint-import-resolver-typescript@npm:3.6.1" - dependencies: - debug: ^4.3.4 - enhanced-resolve: ^5.12.0 - eslint-module-utils: ^2.7.4 - fast-glob: ^3.3.1 - get-tsconfig: ^4.5.0 - is-core-module: ^2.11.0 - is-glob: ^4.0.3 - peerDependencies: - eslint: "*" - eslint-plugin-import: "*" - checksum: 454fa0646533050fb57f13d27daf8c71f51b0bb9156d6a461290ccb8576d892209fcc6702a89553f3f5ea8e5b407395ca2e5de169a952c953685f1f7c46b4496 - languageName: node - linkType: hard - -"eslint-module-utils@npm:^2.7.4, eslint-module-utils@npm:^2.8.0": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" - dependencies: - debug: ^3.2.7 - peerDependenciesMeta: - eslint: - optional: true - checksum: 74c6dfea7641ebcfe174be61168541a11a14aa8d72e515f5f09af55cd0d0862686104b0524aa4b8e0ce66418a44aa38a94d2588743db5fd07a6b49ffd16921d2 - languageName: node - linkType: hard - -"eslint-plugin-eslint-comments@npm:^3.2.0": - version: 3.2.0 - resolution: "eslint-plugin-eslint-comments@npm:3.2.0" - dependencies: - escape-string-regexp: ^1.0.5 - ignore: ^5.0.5 - peerDependencies: - eslint: ">=4.19.1" - checksum: c9fe273dd56699abdf7e416cfad0344eb50aa01564a5a9133e72d982defb89310bc2e9b0b148ce19c5190d7ff641223b0ba9e667a194bc48467c3dd0d471e657 - languageName: node - linkType: hard - -"eslint-plugin-import@npm:^2.26.0, eslint-plugin-import@npm:^2.28.1": - version: 2.29.0 - resolution: "eslint-plugin-import@npm:2.29.0" - dependencies: - array-includes: ^3.1.7 - array.prototype.findlastindex: ^1.2.3 - array.prototype.flat: ^1.3.2 - array.prototype.flatmap: ^1.3.2 - debug: ^3.2.7 - doctrine: ^2.1.0 - eslint-import-resolver-node: ^0.3.9 - eslint-module-utils: ^2.8.0 - hasown: ^2.0.0 - is-core-module: ^2.13.1 - is-glob: ^4.0.3 - minimatch: ^3.1.2 - object.fromentries: ^2.0.7 - object.groupby: ^1.0.1 - object.values: ^1.1.7 - semver: ^6.3.1 - tsconfig-paths: ^3.14.2 - peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 19ee541fb95eb7a796f3daebe42387b8d8262bbbcc4fd8a6e92f63a12035f3d2c6cb8bc0b6a70864fa14b1b50ed6b8e6eed5833e625e16cb6bb98b665beff269 - languageName: node - linkType: hard - -"eslint-plugin-jest@npm:^27.2.3": - version: 27.6.0 - resolution: "eslint-plugin-jest@npm:27.6.0" - dependencies: - "@typescript-eslint/utils": ^5.10.0 - peerDependencies: - "@typescript-eslint/eslint-plugin": ^5.0.0 || ^6.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: "*" - peerDependenciesMeta: - "@typescript-eslint/eslint-plugin": - optional: true - jest: - optional: true - checksum: 4c42641f9bf2d597761637028083e20b9f81762308e98baae40eb805d3e81ff8d837f06f4f0c1a2fd249e2be2fb24d33b7aafeaa8942de805c2b8d7c3b6fc4e4 - languageName: node - linkType: hard - -"eslint-plugin-jsx-a11y@npm:^6.5.1, eslint-plugin-jsx-a11y@npm:^6.7.1": - version: 6.8.0 - resolution: "eslint-plugin-jsx-a11y@npm:6.8.0" - dependencies: - "@babel/runtime": ^7.23.2 - aria-query: ^5.3.0 - array-includes: ^3.1.7 - array.prototype.flatmap: ^1.3.2 - ast-types-flow: ^0.0.8 - axe-core: =4.7.0 - axobject-query: ^3.2.1 - damerau-levenshtein: ^1.0.8 - emoji-regex: ^9.2.2 - es-iterator-helpers: ^1.0.15 - hasown: ^2.0.0 - jsx-ast-utils: ^3.3.5 - language-tags: ^1.0.9 - minimatch: ^3.1.2 - object.entries: ^1.1.7 - object.fromentries: ^2.0.7 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 3dec00e2a3089c4c61ac062e4196a70985fb7eda1fd67fe035363d92578debde92fdb8ed2e472321fc0d71e75f4a1e8888c6a3218c14dd93c8e8d19eb6f51554 - languageName: node - linkType: hard - -"eslint-plugin-only-warn@npm:^1.1.0": - version: 1.1.0 - resolution: "eslint-plugin-only-warn@npm:1.1.0" - checksum: d30ea3170db0c9c4347fbb4f0db3f74b9bdaeca28dc7d3a96346662942b50715131173be9467a5d53b06d46a29c5388790ae46e5404b88b2d4df3bbade0a68da - languageName: node - linkType: hard - -"eslint-plugin-playwright@npm:^0.16.0": - version: 0.16.0 - resolution: "eslint-plugin-playwright@npm:0.16.0" - peerDependencies: - eslint: ">=7" - eslint-plugin-jest: ">=25" - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - checksum: d01aed6fc5f089ba9592d9875e8d72f4966bca562e3478cb8aca815d911e7df1de40f23b41981d8b16f53dc90cd4ce1a58619195e3e1c049bf4be248b31e8045 - languageName: node - linkType: hard - -"eslint-plugin-react-hooks@npm:^4.5.0, eslint-plugin-react-hooks@npm:^4.6.0": - version: 4.6.0 - resolution: "eslint-plugin-react-hooks@npm:4.6.0" - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 23001801f14c1d16bf0a837ca7970d9dd94e7b560384b41db378b49b6e32dc43d6e2790de1bd737a652a86f81a08d6a91f402525061b47719328f586a57e86c3 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:7.28.0": - version: 7.28.0 - resolution: "eslint-plugin-react@npm:7.28.0" - dependencies: - array-includes: ^3.1.4 - array.prototype.flatmap: ^1.2.5 - doctrine: ^2.1.0 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.0.4 - object.entries: ^1.1.5 - object.fromentries: ^2.0.5 - object.hasown: ^1.1.0 - object.values: ^1.1.5 - prop-types: ^15.7.2 - resolve: ^2.0.0-next.3 - semver: ^6.3.0 - string.prototype.matchall: ^4.0.6 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 90293d0fd53bb1f735ffd32141cdd211fb1120c9f7bbe5342f9e923261a39e52a2b2575d4e46c9cd77d257f42db4a99b8b339689fc5b5c1c26048929f69b1784 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:^7.31.7, eslint-plugin-react@npm:^7.33.2": - version: 7.33.2 - resolution: "eslint-plugin-react@npm:7.33.2" - dependencies: - array-includes: ^3.1.6 - array.prototype.flatmap: ^1.3.1 - array.prototype.tosorted: ^1.1.1 - doctrine: ^2.1.0 - es-iterator-helpers: ^1.0.12 - estraverse: ^5.3.0 - jsx-ast-utils: ^2.4.1 || ^3.0.0 - minimatch: ^3.1.2 - object.entries: ^1.1.6 - object.fromentries: ^2.0.6 - object.hasown: ^1.1.2 - object.values: ^1.1.6 - prop-types: ^15.8.1 - resolve: ^2.0.0-next.4 - semver: ^6.3.1 - string.prototype.matchall: ^4.0.8 - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: b4c3d76390b0ae6b6f9fed78170604cc2c04b48e6778a637db339e8e3911ec9ef22510b0ae77c429698151d0f1b245f282177f384105b6830e7b29b9c9b26610 - languageName: node - linkType: hard - -"eslint-plugin-testing-library@npm:^6.0.1": - version: 6.2.0 - resolution: "eslint-plugin-testing-library@npm:6.2.0" - dependencies: - "@typescript-eslint/utils": ^5.58.0 - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - checksum: 7af7e0a1eee44c6ba65ce2ae99f8e46ce709a319f4cce778bb0af2dda5828d78f3a81e8989c7b691a8b9b9fef102b56136209aac700038b9e64794600b0d12db - languageName: node - linkType: hard - -"eslint-plugin-tsdoc@npm:^0.2.17": - version: 0.2.17 - resolution: "eslint-plugin-tsdoc@npm:0.2.17" - dependencies: - "@microsoft/tsdoc": 0.14.2 - "@microsoft/tsdoc-config": 0.16.2 - checksum: d143a5f1c5967812d75f246ae2776cb030f6e7966b981406c9df9352a9ab02b035f294cedb30054eac2c4a217ee4ab2ed9fb76292bdccda9438e54d2d7b0146e - languageName: node - linkType: hard - -"eslint-plugin-turbo@npm:2.0.0": - version: 2.0.0 - resolution: "eslint-plugin-turbo@npm:2.0.0" - dependencies: - dotenv: 16.0.3 - peerDependencies: - eslint: ">6.6.0" - checksum: 60bc0595877c85d3d4a67cedaa68c154125a724421c78360e1b207402d998bebdc7c9f639929fc948e5634d175e32de0659bf94b86bd412aecad198768839bbd - languageName: node - linkType: hard - -"eslint-plugin-unicorn@npm:^48.0.1": - version: 48.0.1 - resolution: "eslint-plugin-unicorn@npm:48.0.1" - dependencies: - "@babel/helper-validator-identifier": ^7.22.5 - "@eslint-community/eslint-utils": ^4.4.0 - ci-info: ^3.8.0 - clean-regexp: ^1.0.0 - esquery: ^1.5.0 - indent-string: ^4.0.0 - is-builtin-module: ^3.2.1 - jsesc: ^3.0.2 - lodash: ^4.17.21 - pluralize: ^8.0.0 - read-pkg-up: ^7.0.1 - regexp-tree: ^0.1.27 - regjsparser: ^0.10.0 - semver: ^7.5.4 - strip-indent: ^3.0.0 - peerDependencies: - eslint: ">=8.44.0" - checksum: e63112cbaa3a1347cbb427160d7b3c6a1f8cc8ef512075a0ab285c64761772356f4eb5f82c9fb1a8cde63d8794f8aa819eda02fa0a7c44bc9955c5113f87be78 - languageName: node - linkType: hard - -"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1": - version: 5.1.1 - resolution: "eslint-scope@npm:5.1.1" - dependencies: - esrecurse: ^4.3.0 - estraverse: ^4.1.1 - checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb - languageName: node - linkType: hard - -"eslint-scope@npm:^7.2.2": - version: 7.2.2 - resolution: "eslint-scope@npm:7.2.2" - dependencies: - esrecurse: ^4.3.0 - estraverse: ^5.2.0 - checksum: ec97dbf5fb04b94e8f4c5a91a7f0a6dd3c55e46bfc7bbcd0e3138c3a76977570e02ed89a1810c778dcd72072ff0e9621ba1379b4babe53921d71e2e4486fda3e - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^2.1.0": - version: 2.1.0 - resolution: "eslint-visitor-keys@npm:2.1.0" - checksum: e3081d7dd2611a35f0388bbdc2f5da60b3a3c5b8b6e928daffff7391146b434d691577aa95064c8b7faad0b8a680266bcda0a42439c18c717b80e6718d7e267d - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": - version: 3.4.3 - resolution: "eslint-visitor-keys@npm:3.4.3" - checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 - languageName: node - linkType: hard - -"eslint@npm:8.57.0, eslint@npm:^8.57.0": - version: 8.57.0 - resolution: "eslint@npm:8.57.0" - dependencies: - "@eslint-community/eslint-utils": ^4.2.0 - "@eslint-community/regexpp": ^4.6.1 - "@eslint/eslintrc": ^2.1.4 - "@eslint/js": 8.57.0 - "@humanwhocodes/config-array": ^0.11.14 - "@humanwhocodes/module-importer": ^1.0.1 - "@nodelib/fs.walk": ^1.2.8 - "@ungap/structured-clone": ^1.2.0 - ajv: ^6.12.4 - chalk: ^4.0.0 - cross-spawn: ^7.0.2 - debug: ^4.3.2 - doctrine: ^3.0.0 - escape-string-regexp: ^4.0.0 - eslint-scope: ^7.2.2 - eslint-visitor-keys: ^3.4.3 - espree: ^9.6.1 - esquery: ^1.4.2 - esutils: ^2.0.2 - fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 - find-up: ^5.0.0 - glob-parent: ^6.0.2 - globals: ^13.19.0 - graphemer: ^1.4.0 - ignore: ^5.2.0 - imurmurhash: ^0.1.4 - is-glob: ^4.0.0 - is-path-inside: ^3.0.3 - js-yaml: ^4.1.0 - json-stable-stringify-without-jsonify: ^1.0.1 - levn: ^0.4.1 - lodash.merge: ^4.6.2 - minimatch: ^3.1.2 - natural-compare: ^1.4.0 - optionator: ^0.9.3 - strip-ansi: ^6.0.1 - text-table: ^0.2.0 - bin: - eslint: bin/eslint.js - checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 - languageName: node - linkType: hard - -"espree@npm:^9.6.0, espree@npm:^9.6.1": - version: 9.6.1 - resolution: "espree@npm:9.6.1" - dependencies: - acorn: ^8.9.0 - acorn-jsx: ^5.3.2 - eslint-visitor-keys: ^3.4.1 - checksum: eb8c149c7a2a77b3f33a5af80c10875c3abd65450f60b8af6db1bfcfa8f101e21c1e56a561c6dc13b848e18148d43469e7cd208506238554fb5395a9ea5a1ab9 - languageName: node - linkType: hard - -"esquery@npm:^1.4.2, esquery@npm:^1.5.0": - version: 1.5.0 - resolution: "esquery@npm:1.5.0" - dependencies: - estraverse: ^5.1.0 - checksum: aefb0d2596c230118656cd4ec7532d447333a410a48834d80ea648b1e7b5c9bc9ed8b5e33a89cb04e487b60d622f44cf5713bf4abed7c97343edefdc84a35900 - languageName: node - linkType: hard - -"esrecurse@npm:^4.3.0": - version: 4.3.0 - resolution: "esrecurse@npm:4.3.0" - dependencies: - estraverse: ^5.2.0 - checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 - languageName: node - linkType: hard - -"estraverse@npm:^4.1.1": - version: 4.3.0 - resolution: "estraverse@npm:4.3.0" - checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 - languageName: node - linkType: hard - -"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": - version: 5.3.0 - resolution: "estraverse@npm:5.3.0" - checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b - languageName: node - linkType: hard - -"esutils@npm:^2.0.2": - version: 2.0.3 - resolution: "esutils@npm:2.0.3" - checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 - languageName: node - linkType: hard - -"execa@npm:^5.0.0": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - 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 - checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 - languageName: node - linkType: hard - -"execa@npm:^7.1.1": - version: 7.1.1 - resolution: "execa@npm:7.1.1" - dependencies: - cross-spawn: ^7.0.3 - get-stream: ^6.0.1 - human-signals: ^4.3.0 - is-stream: ^3.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^5.1.0 - onetime: ^6.0.0 - signal-exit: ^3.0.7 - strip-final-newline: ^3.0.0 - checksum: 21fa46fc69314ace4068cf820142bdde5b643a5d89831c2c9349479c1555bff137a291b8e749e7efca36535e4e0a8c772c11008ca2e84d2cbd6ca141a3c8f937 - languageName: node - linkType: hard - -"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": - version: 3.1.3 - resolution: "fast-deep-equal@npm:3.1.3" - checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d - languageName: node - linkType: hard - -"fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9": - version: 3.2.12 - resolution: "fast-glob@npm:3.2.12" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 0b1990f6ce831c7e28c4d505edcdaad8e27e88ab9fa65eedadb730438cfc7cde4910d6c975d6b7b8dc8a73da4773702ebcfcd6e3518e73938bb1383badfe01c2 - languageName: node - linkType: hard - -"fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 - languageName: node - linkType: hard - -"fast-json-stable-stringify@npm:^2.0.0": - version: 2.1.0 - resolution: "fast-json-stable-stringify@npm:2.1.0" - checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb - languageName: node - linkType: hard - -"fast-levenshtein@npm:^2.0.6": - version: 2.0.6 - resolution: "fast-levenshtein@npm:2.0.6" - checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c - languageName: node - linkType: hard - -"fastq@npm:^1.6.0": - version: 1.15.0 - resolution: "fastq@npm:1.15.0" - dependencies: - reusify: ^1.0.4 - checksum: 0170e6bfcd5d57a70412440b8ef600da6de3b2a6c5966aeaf0a852d542daff506a0ee92d6de7679d1de82e644bce69d7a574a6c93f0b03964b5337eed75ada1a - languageName: node - linkType: hard - -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" - dependencies: - flat-cache: ^3.0.4 - checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 - languageName: node - linkType: hard - -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" - dependencies: - to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 - languageName: node - linkType: hard - -"find-up@npm:^4.1.0": - version: 4.1.0 - resolution: "find-up@npm:4.1.0" - dependencies: - locate-path: ^5.0.0 - path-exists: ^4.0.0 - checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 - languageName: node - linkType: hard - -"find-up@npm:^5.0.0": - version: 5.0.0 - resolution: "find-up@npm:5.0.0" - dependencies: - locate-path: ^6.0.0 - path-exists: ^4.0.0 - checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 - languageName: node - linkType: hard - -"flat-cache@npm:^3.0.4": - version: 3.0.4 - resolution: "flat-cache@npm:3.0.4" - dependencies: - flatted: ^3.1.0 - rimraf: ^3.0.2 - checksum: 4fdd10ecbcbf7d520f9040dd1340eb5dfe951e6f0ecf2252edeec03ee68d989ec8b9a20f4434270e71bcfd57800dc09b3344fca3966b2eb8f613072c7d9a2365 - languageName: node - linkType: hard - -"flatted@npm:^3.1.0": - version: 3.2.7 - resolution: "flatted@npm:3.2.7" - checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 - languageName: node - linkType: hard - -"for-each@npm:^0.3.3": - version: 0.3.3 - resolution: "for-each@npm:0.3.3" - dependencies: - is-callable: ^1.1.3 - checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" - dependencies: - cross-spawn: ^7.0.0 - signal-exit: ^4.0.1 - checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 - languageName: node - linkType: hard - -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a - languageName: node - linkType: hard - -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 - languageName: node - linkType: hard - -"function.prototype.name@npm:^1.1.5": - version: 1.1.5 - resolution: "function.prototype.name@npm:1.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.0 - functions-have-names: ^1.2.2 - checksum: acd21d733a9b649c2c442f067567743214af5fa248dbeee69d8278ce7df3329ea5abac572be9f7470b4ec1cd4d8f1040e3c5caccf98ebf2bf861a0deab735c27 - languageName: node - linkType: hard - -"function.prototype.name@npm:^1.1.6": - version: 1.1.6 - resolution: "function.prototype.name@npm:1.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - functions-have-names: ^1.2.3 - checksum: 7a3f9bd98adab09a07f6e1f03da03d3f7c26abbdeaeee15223f6c04a9fb5674792bdf5e689dac19b97ac71de6aad2027ba3048a9b883aa1b3173eed6ab07f479 - languageName: node - linkType: hard - -"functions-have-names@npm:^1.2.2, functions-have-names@npm:^1.2.3": - version: 1.2.3 - resolution: "functions-have-names@npm:1.2.3" - checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 - languageName: node - linkType: hard - -"gensync@npm:^1.0.0-beta.2": - version: 1.0.0-beta.2 - resolution: "gensync@npm:1.0.0-beta.2" - checksum: a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0": - version: 1.2.0 - resolution: "get-intrinsic@npm:1.2.0" - dependencies: - function-bind: ^1.1.1 - has: ^1.0.3 - has-symbols: ^1.0.3 - checksum: 78fc0487b783f5c58cf2dccafc3ae656ee8d2d8062a8831ce4a95e7057af4587a1d4882246c033aca0a7b4965276f4802b45cc300338d1b77a73d3e3e3f4877d - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": - version: 1.2.2 - resolution: "get-intrinsic@npm:1.2.2" - dependencies: - function-bind: ^1.1.2 - has-proto: ^1.0.1 - has-symbols: ^1.0.3 - hasown: ^2.0.0 - checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 - languageName: node - linkType: hard - -"get-stdin@npm:^9.0.0": - version: 9.0.0 - resolution: "get-stdin@npm:9.0.0" - checksum: 5972bc34d05932b45512c8e2d67b040f1c1ca8afb95c56cbc480985f2d761b7e37fe90dc8abd22527f062cc5639a6930ff346e9952ae4c11a2d4275869459594 - languageName: node - linkType: hard - -"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad - languageName: node - linkType: hard - -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 - languageName: node - linkType: hard - -"get-tsconfig@npm:^4.5.0": - version: 4.5.0 - resolution: "get-tsconfig@npm:4.5.0" - checksum: 687ee2bd69a5a07db2e2edeb4d6c41c3debb38f6281a66beb643e3f5b520252e27fcbbb5702bdd9a5f05dcf8c1d2e0150a4d8a960ad75cbdea74e06a51e91b02 - languageName: node - linkType: hard - -"git-hooks-list@npm:^3.0.0": - version: 3.1.0 - resolution: "git-hooks-list@npm:3.1.0" - checksum: 05cbdb29e1e14f3b6fde78c876a34383e4476b1be32e8486ad03293f01add884c1a8df8c2dce2ca5d99119c94951b2ff9fa9cbd51d834ae6477b6813cefb998f - languageName: node - linkType: hard - -"glob-parent@npm:^5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: ^4.0.1 - checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e - languageName: node - linkType: hard - -"glob-parent@npm:^6.0.2": - version: 6.0.2 - resolution: "glob-parent@npm:6.0.2" - dependencies: - is-glob: ^4.0.3 - checksum: c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8 - languageName: node - linkType: hard - -"glob@npm:10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" - dependencies: - foreground-child: ^3.1.0 - jackspeak: ^2.3.5 - minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - path-scurry: ^1.10.1 - bin: - glob: dist/esm/bin.mjs - checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 - languageName: node - linkType: hard - -"glob@npm:7.1.7": - version: 7.1.7 - resolution: "glob@npm:7.1.7" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.0.4 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: b61f48973bbdcf5159997b0874a2165db572b368b931135832599875919c237fc05c12984e38fe828e69aa8a921eb0e8a4997266211c517c9cfaae8a93988bb8 - languageName: node - linkType: hard - -"glob@npm:^7.1.3, glob@npm:^7.2.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.1.1 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 - languageName: node - linkType: hard - -"globals@npm:^11.1.0": - version: 11.12.0 - resolution: "globals@npm:11.12.0" - checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e - languageName: node - linkType: hard - -"globals@npm:^13.19.0": - version: 13.23.0 - resolution: "globals@npm:13.23.0" - dependencies: - type-fest: ^0.20.2 - checksum: 194c97cf8d1ef6ba59417234c2386549c4103b6e5f24b1ff1952de61a4753e5d2069435ba629de711a6480b1b1d114a98e2ab27f85e966d5a10c319c3bbd3dc3 - languageName: node - linkType: hard - -"globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" - dependencies: - define-properties: ^1.1.3 - checksum: fbd7d760dc464c886d0196166d92e5ffb4c84d0730846d6621a39fbbc068aeeb9c8d1421ad330e94b7bca4bb4ea092f5f21f3d36077812af5d098b4dc006c998 - languageName: node - linkType: hard - -"globby@npm:^11.1.0": - version: 11.1.0 - resolution: "globby@npm:11.1.0" - dependencies: - array-union: ^2.1.0 - dir-glob: ^3.0.1 - fast-glob: ^3.2.9 - ignore: ^5.2.0 - merge2: ^1.4.1 - slash: ^3.0.0 - checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 - languageName: node - linkType: hard - -"globby@npm:^13.1.2": - version: 13.2.2 - resolution: "globby@npm:13.2.2" - dependencies: - dir-glob: ^3.0.1 - fast-glob: ^3.3.0 - ignore: ^5.2.4 - merge2: ^1.4.1 - slash: ^4.0.0 - checksum: f3d84ced58a901b4fcc29c846983108c426631fe47e94872868b65565495f7bee7b3defd68923bd480582771fd4bbe819217803a164a618ad76f1d22f666f41e - languageName: node - linkType: hard - -"gopd@npm:^1.0.1": - version: 1.0.1 - resolution: "gopd@npm:1.0.1" - dependencies: - get-intrinsic: ^1.1.3 - checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 - languageName: node - linkType: hard - -"graphemer@npm:^1.4.0": - version: 1.4.0 - resolution: "graphemer@npm:1.4.0" - checksum: bab8f0be9b568857c7bec9fda95a89f87b783546d02951c40c33f84d05bb7da3fd10f863a9beb901463669b6583173a8c8cc6d6b306ea2b9b9d5d3d943c3a673 - languageName: node - linkType: hard - -"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": - version: 1.0.2 - resolution: "has-bigints@npm:1.0.2" - checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b - languageName: node - linkType: hard - -"has-flag@npm:^3.0.0": - version: 3.0.0 - resolution: "has-flag@npm:3.0.0" - checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad - languageName: node - linkType: hard - -"has-property-descriptors@npm:^1.0.0": - version: 1.0.0 - resolution: "has-property-descriptors@npm:1.0.0" - dependencies: - get-intrinsic: ^1.1.1 - checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb - languageName: node - linkType: hard - -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": - version: 1.0.3 - resolution: "has-symbols@npm:1.0.3" - checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" - dependencies: - has-symbols: ^1.0.2 - checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c - languageName: node - linkType: hard - -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: ^1.1.1 - checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 - languageName: node - linkType: hard - -"hasown@npm:^2.0.0": - version: 2.0.0 - resolution: "hasown@npm:2.0.0" - dependencies: - function-bind: ^1.1.2 - checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 - languageName: node - linkType: hard - -"hosted-git-info@npm:^2.1.4": - version: 2.8.9 - resolution: "hosted-git-info@npm:2.8.9" - checksum: c955394bdab888a1e9bb10eb33029e0f7ce5a2ac7b3f158099dc8c486c99e73809dca609f5694b223920ca2174db33d32b12f9a2a47141dc59607c29da5a62dd - languageName: node - linkType: hard - -"human-signals@npm:^2.1.0": - version: 2.1.0 - resolution: "human-signals@npm:2.1.0" - checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 - languageName: node - linkType: hard - -"human-signals@npm:^4.3.0": - version: 4.3.1 - resolution: "human-signals@npm:4.3.1" - checksum: 6f12958df3f21b6fdaf02d90896c271df00636a31e2bbea05bddf817a35c66b38a6fdac5863e2df85bd52f34958997f1f50350ff97249e1dff8452865d5235d1 - languageName: node - linkType: hard - -"ignore@npm:^5.0.5, ignore@npm:^5.2.4": - version: 5.3.0 - resolution: "ignore@npm:5.3.0" - checksum: 2736da6621f14ced652785cb05d86301a66d70248597537176612bd0c8630893564bd5f6421f8806b09e8472e75c591ef01672ab8059c07c6eb2c09cefe04bf9 - languageName: node - linkType: hard - -"ignore@npm:^5.2.0": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef - languageName: node - linkType: hard - -"import-fresh@npm:^3.2.1": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" - dependencies: - parent-module: ^1.0.0 - resolve-from: ^4.0.0 - checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: ^1.3.0 - wrappy: 1 - checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd - languageName: node - linkType: hard - -"inherits@npm:2": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 - languageName: node - linkType: hard - -"internal-slot@npm:^1.0.3, internal-slot@npm:^1.0.5": - version: 1.0.5 - resolution: "internal-slot@npm:1.0.5" - dependencies: - get-intrinsic: ^1.2.0 - has: ^1.0.3 - side-channel: ^1.0.4 - checksum: 97e84046bf9e7574d0956bd98d7162313ce7057883b6db6c5c7b5e5f05688864b0978ba07610c726d15d66544ffe4b1050107d93f8a39ebc59b15d8b429b497a - languageName: node - linkType: hard - -"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": - version: 3.0.2 - resolution: "is-array-buffer@npm:3.0.2" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.0 - is-typed-array: ^1.1.10 - checksum: dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 - languageName: node - linkType: hard - -"is-arrayish@npm:^0.2.1": - version: 0.2.1 - resolution: "is-arrayish@npm:0.2.1" - checksum: eef4417e3c10e60e2c810b6084942b3ead455af16c4509959a27e490e7aee87cfb3f38e01bbde92220b528a0ee1a18d52b787e1458ee86174d8c7f0e58cd488f - languageName: node - linkType: hard - -"is-async-function@npm:^2.0.0": - version: 2.0.0 - resolution: "is-async-function@npm:2.0.0" - dependencies: - has-tostringtag: ^1.0.0 - checksum: e3471d95e6c014bf37cad8a93f2f4b6aac962178e0a5041e8903147166964fdc1c5c1d2ef87e86d77322c370ca18f2ea004fa7420581fa747bcaf7c223069dbd - languageName: node - linkType: hard - -"is-bigint@npm:^1.0.1": - version: 1.0.4 - resolution: "is-bigint@npm:1.0.4" - dependencies: - has-bigints: ^1.0.1 - checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 - languageName: node - linkType: hard - -"is-boolean-object@npm:^1.1.0": - version: 1.1.2 - resolution: "is-boolean-object@npm:1.1.2" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 - languageName: node - linkType: hard - -"is-builtin-module@npm:^3.2.1": - version: 3.2.1 - resolution: "is-builtin-module@npm:3.2.1" - dependencies: - builtin-modules: ^3.3.0 - checksum: e8f0ffc19a98240bda9c7ada84d846486365af88d14616e737d280d378695c8c448a621dcafc8332dbf0fcd0a17b0763b845400709963fa9151ddffece90ae88 - languageName: node - linkType: hard - -"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": - version: 1.2.7 - resolution: "is-callable@npm:1.2.7" - checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac - languageName: node - linkType: hard - -"is-core-module@npm:^2.1.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1": - version: 2.13.1 - resolution: "is-core-module@npm:2.13.1" - dependencies: - hasown: ^2.0.0 - checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c - languageName: node - linkType: hard - -"is-core-module@npm:^2.11.0, is-core-module@npm:^2.9.0": - version: 2.12.0 - resolution: "is-core-module@npm:2.12.0" - dependencies: - has: ^1.0.3 - checksum: f7f7eb2ab71fd769ee9fb2385c095d503aa4b5ce0028c04557de03f1e67a87c85e5bac1f215945fc3c955867a139a415a3ec4c4234a0bffdf715232660f440a6 - languageName: node - linkType: hard - -"is-date-object@npm:^1.0.1, is-date-object@npm:^1.0.5": - version: 1.0.5 - resolution: "is-date-object@npm:1.0.5" - dependencies: - has-tostringtag: ^1.0.0 - checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc - languageName: node - linkType: hard - -"is-docker@npm:^2.0.0": - version: 2.2.1 - resolution: "is-docker@npm:2.2.1" - bin: - is-docker: cli.js - checksum: 3fef7ddbf0be25958e8991ad941901bf5922ab2753c46980b60b05c1bf9c9c2402d35e6dc32e4380b980ef5e1970a5d9d5e5aa2e02d77727c3b6b5e918474c56 - languageName: node - linkType: hard - -"is-docker@npm:^3.0.0": - version: 3.0.0 - resolution: "is-docker@npm:3.0.0" - bin: - is-docker: cli.js - checksum: b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90 - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 - languageName: node - linkType: hard - -"is-finalizationregistry@npm:^1.0.2": - version: 1.0.2 - resolution: "is-finalizationregistry@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 4f243a8e06228cd45bdab8608d2cb7abfc20f6f0189c8ac21ea8d603f1f196eabd531ce0bb8e08cbab047e9845ef2c191a3761c9a17ad5cabf8b35499c4ad35d - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 - languageName: node - linkType: hard - -"is-generator-function@npm:^1.0.10": - version: 1.0.10 - resolution: "is-generator-function@npm:1.0.10" - dependencies: - has-tostringtag: ^1.0.0 - checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b - languageName: node - linkType: hard - -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: ^2.1.1 - checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 - languageName: node - linkType: hard - -"is-inside-container@npm:^1.0.0": - version: 1.0.0 - resolution: "is-inside-container@npm:1.0.0" - dependencies: - is-docker: ^3.0.0 - bin: - is-inside-container: cli.js - checksum: c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03 - languageName: node - linkType: hard - -"is-map@npm:^2.0.1": - version: 2.0.2 - resolution: "is-map@npm:2.0.2" - checksum: ace3d0ecd667bbdefdb1852de601268f67f2db725624b1958f279316e13fecb8fa7df91fd60f690d7417b4ec180712f5a7ee967008e27c65cfd475cc84337728 - languageName: node - linkType: hard - -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a - languageName: node - linkType: hard - -"is-number-object@npm:^1.0.4": - version: 1.0.7 - resolution: "is-number-object@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a - languageName: node - linkType: hard - -"is-path-inside@npm:^3.0.3": - version: 3.0.3 - resolution: "is-path-inside@npm:3.0.3" - checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 - languageName: node - linkType: hard - -"is-plain-obj@npm:^4.1.0": - version: 4.1.0 - resolution: "is-plain-obj@npm:4.1.0" - checksum: 6dc45da70d04a81f35c9310971e78a6a3c7a63547ef782e3a07ee3674695081b6ca4e977fbb8efc48dae3375e0b34558d2bcd722aec9bddfa2d7db5b041be8ce - languageName: node - linkType: hard - -"is-regex@npm:^1.1.4": - version: 1.1.4 - resolution: "is-regex@npm:1.1.4" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 - languageName: node - linkType: hard - -"is-set@npm:^2.0.1": - version: 2.0.2 - resolution: "is-set@npm:2.0.2" - checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57 - languageName: node - linkType: hard - -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a - languageName: node - linkType: hard - -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 - languageName: node - linkType: hard - -"is-stream@npm:^3.0.0": - version: 3.0.0 - resolution: "is-stream@npm:3.0.0" - checksum: 172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 - languageName: node - linkType: hard - -"is-string@npm:^1.0.5, is-string@npm:^1.0.7": - version: 1.0.7 - resolution: "is-string@npm:1.0.7" - dependencies: - has-tostringtag: ^1.0.0 - checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 - languageName: node - linkType: hard - -"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": - version: 1.0.4 - resolution: "is-symbol@npm:1.0.4" - dependencies: - has-symbols: ^1.0.2 - checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 - languageName: node - linkType: hard - -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.9": - version: 1.1.10 - resolution: "is-typed-array@npm:1.1.10" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - checksum: aac6ecb59d4c56a1cdeb69b1f129154ef462bbffe434cb8a8235ca89b42f258b7ae94073c41b3cb7bce37f6a1733ad4499f07882d5d5093a7ba84dfc4ebb8017 - languageName: node - linkType: hard - -"is-typed-array@npm:^1.1.12": - version: 1.1.12 - resolution: "is-typed-array@npm:1.1.12" - dependencies: - which-typed-array: ^1.1.11 - checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 - languageName: node - linkType: hard - -"is-weakmap@npm:^2.0.1": - version: 2.0.1 - resolution: "is-weakmap@npm:2.0.1" - checksum: 1222bb7e90c32bdb949226e66d26cb7bce12e1e28e3e1b40bfa6b390ba3e08192a8664a703dff2a00a84825f4e022f9cd58c4599ff9981ab72b1d69479f4f7f6 - languageName: node - linkType: hard - -"is-weakref@npm:^1.0.2": - version: 1.0.2 - resolution: "is-weakref@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de - languageName: node - linkType: hard - -"is-weakset@npm:^2.0.1": - version: 2.0.2 - resolution: "is-weakset@npm:2.0.2" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 5d8698d1fa599a0635d7ca85be9c26d547b317ed8fd83fc75f03efbe75d50001b5eececb1e9971de85fcde84f69ae6f8346bc92d20d55d46201d328e4c74a367 - languageName: node - linkType: hard - -"is-wsl@npm:^2.2.0": - version: 2.2.0 - resolution: "is-wsl@npm:2.2.0" - dependencies: - is-docker: ^2.0.0 - checksum: 20849846ae414997d290b75e16868e5261e86ff5047f104027026fd61d8b5a9b0b3ade16239f35e1a067b3c7cc02f70183cb661010ed16f4b6c7c93dad1b19d8 - languageName: node - linkType: hard - -"isarray@npm:^2.0.5": - version: 2.0.5 - resolution: "isarray@npm:2.0.5" - checksum: bd5bbe4104438c4196ba58a54650116007fa0262eccef13a4c55b2e09a5b36b59f1e75b9fcc49883dd9d4953892e6fc007eef9e9155648ceea036e184b0f930a - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 - languageName: node - linkType: hard - -"iterator.prototype@npm:^1.1.2": - version: 1.1.2 - resolution: "iterator.prototype@npm:1.1.2" - dependencies: - define-properties: ^1.2.1 - get-intrinsic: ^1.2.1 - has-symbols: ^1.0.3 - reflect.getprototypeof: ^1.0.4 - set-function-name: ^2.0.1 - checksum: d8a507e2ccdc2ce762e8a1d3f4438c5669160ac72b88b648e59a688eec6bc4e64b22338e74000518418d9e693faf2a092d2af21b9ec7dbf7763b037a54701168 - languageName: node - linkType: hard - -"jackspeak@npm:^2.3.5": - version: 2.3.6 - resolution: "jackspeak@npm:2.3.6" - dependencies: - "@isaacs/cliui": ^8.0.2 - "@pkgjs/parseargs": ^0.11.0 - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 - languageName: node - linkType: hard - -"jju@npm:~1.4.0": - version: 1.4.0 - resolution: "jju@npm:1.4.0" - checksum: 3790481bd2b7827dd6336e6e3dc2dcc6d425679ba7ebde7b679f61dceb4457ea0cda330972494de608571f4973c6dfb5f70fab6f3c5037dbab19ac449a60424f - languageName: node - linkType: hard - -"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 - languageName: node - linkType: hard - -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" - dependencies: - argparse: ^2.0.1 - bin: - js-yaml: bin/js-yaml.js - checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a - languageName: node - linkType: hard - -"jsesc@npm:^2.5.1": - version: 2.5.2 - resolution: "jsesc@npm:2.5.2" - bin: - jsesc: bin/jsesc - checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d - languageName: node - linkType: hard - -"jsesc@npm:^3.0.2": - version: 3.0.2 - resolution: "jsesc@npm:3.0.2" - bin: - jsesc: bin/jsesc - checksum: a36d3ca40574a974d9c2063bf68c2b6141c20da8f2a36bd3279fc802563f35f0527a6c828801295bdfb2803952cf2cf387786c2c90ed564f88d5782475abfe3c - languageName: node - linkType: hard - -"jsesc@npm:~0.5.0": - version: 0.5.0 - resolution: "jsesc@npm:0.5.0" - bin: - jsesc: bin/jsesc - checksum: b8b44cbfc92f198ad972fba706ee6a1dfa7485321ee8c0b25f5cedd538dcb20cde3197de16a7265430fce8277a12db066219369e3d51055038946039f6e20e17 - languageName: node - linkType: hard - -"json-parse-even-better-errors@npm:^2.3.0": - version: 2.3.1 - resolution: "json-parse-even-better-errors@npm:2.3.1" - checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f - languageName: node - linkType: hard - -"json-schema-traverse@npm:^0.4.1": - version: 0.4.1 - resolution: "json-schema-traverse@npm:0.4.1" - checksum: 7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b - languageName: node - linkType: hard - -"json-stable-stringify-without-jsonify@npm:^1.0.1": - version: 1.0.1 - resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" - checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 - languageName: node - linkType: hard - -"json5@npm:^1.0.2": - version: 1.0.2 - resolution: "json5@npm:1.0.2" - dependencies: - minimist: ^1.2.0 - bin: - json5: lib/cli.js - checksum: 866458a8c58a95a49bef3adba929c625e82532bcff1fe93f01d29cb02cac7c3fe1f4b79951b7792c2da9de0b32871a8401a6e3c5b36778ad852bf5b8a61165d7 - languageName: node - linkType: hard - -"json5@npm:^2.2.3": - version: 2.2.3 - resolution: "json5@npm:2.2.3" - bin: - json5: lib/cli.js - checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 - languageName: node - linkType: hard - -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0": - version: 3.3.3 - resolution: "jsx-ast-utils@npm:3.3.3" - dependencies: - array-includes: ^3.1.5 - object.assign: ^4.1.3 - checksum: a2ed78cac49a0f0c4be8b1eafe3c5257a1411341d8e7f1ac740debae003de04e5f6372bfcfbd9d082e954ffd99aac85bcda85b7c6bc11609992483f4cdc0f745 - languageName: node - linkType: hard - -"jsx-ast-utils@npm:^3.3.5": - version: 3.3.5 - resolution: "jsx-ast-utils@npm:3.3.5" - dependencies: - array-includes: ^3.1.6 - array.prototype.flat: ^1.3.1 - object.assign: ^4.1.4 - object.values: ^1.1.6 - checksum: f4b05fa4d7b5234230c905cfa88d36dc8a58a6666975a3891429b1a8cdc8a140bca76c297225cb7a499fad25a2c052ac93934449a2c31a44fc9edd06c773780a - languageName: node - linkType: hard - -"language-subtag-registry@npm:^0.3.20": - version: 0.3.22 - resolution: "language-subtag-registry@npm:0.3.22" - checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a - languageName: node - linkType: hard - -"language-tags@npm:^1.0.9": - version: 1.0.9 - resolution: "language-tags@npm:1.0.9" - dependencies: - language-subtag-registry: ^0.3.20 - checksum: 57c530796dc7179914dee71bc94f3747fd694612480241d0453a063777265dfe3a951037f7acb48f456bf167d6eb419d4c00263745326b3ba1cdcf4657070e78 - languageName: node - linkType: hard - -"levn@npm:^0.4.1": - version: 0.4.1 - resolution: "levn@npm:0.4.1" - dependencies: - prelude-ls: ^1.2.1 - type-check: ~0.4.0 - checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 - languageName: node - linkType: hard - -"lines-and-columns@npm:^1.1.6": - version: 1.2.4 - resolution: "lines-and-columns@npm:1.2.4" - checksum: 0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 - languageName: node - linkType: hard - -"locate-path@npm:^5.0.0": - version: 5.0.0 - resolution: "locate-path@npm:5.0.0" - dependencies: - p-locate: ^4.1.0 - checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 - languageName: node - linkType: hard - -"locate-path@npm:^6.0.0": - version: 6.0.0 - resolution: "locate-path@npm:6.0.0" - dependencies: - p-locate: ^5.0.0 - checksum: 72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a - languageName: node - linkType: hard - -"lodash.merge@npm:^4.6.2": - version: 4.6.2 - resolution: "lodash.merge@npm:4.6.2" - checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 - languageName: node - linkType: hard - -"lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 - languageName: node - linkType: hard - -"loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" - dependencies: - js-tokens: ^3.0.0 || ^4.0.0 - bin: - loose-envify: cli.js - checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 - languageName: node - linkType: hard - -"lru-cache@npm:^5.1.1": - version: 5.1.1 - resolution: "lru-cache@npm:5.1.1" - dependencies: - yallist: ^3.0.2 - checksum: c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb - languageName: node - linkType: hard - -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: ^4.0.0 - checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 - languageName: node - linkType: hard - -"lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.2.0 - resolution: "lru-cache@npm:10.2.0" - checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db - languageName: node - linkType: hard - -"merge-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "merge-stream@npm:2.0.0" - checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 - languageName: node - linkType: hard - -"merge2@npm:^1.3.0, merge2@npm:^1.4.1": - version: 1.4.1 - resolution: "merge2@npm:1.4.1" - checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 - languageName: node - linkType: hard - -"micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" - dependencies: - braces: ^3.0.2 - picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc - languageName: node - linkType: hard - -"mimic-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "mimic-fn@npm:2.1.0" - checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a - languageName: node - linkType: hard - -"mimic-fn@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-fn@npm:4.0.0" - checksum: 995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 - languageName: node - linkType: hard - -"min-indent@npm:^1.0.0": - version: 1.0.1 - resolution: "min-indent@npm:1.0.1" - checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 - languageName: node - linkType: hard - -"minimatch@npm:9.0.3, minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" - dependencies: - brace-expansion: ^2.0.1 - checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: ^1.1.7 - checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a - languageName: node - linkType: hard - -"minimist@npm:^1.2.0, minimist@npm:^1.2.6": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": - version: 7.0.4 - resolution: "minipass@npm:7.0.4" - checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 - languageName: node - linkType: hard - -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f - languageName: node - linkType: hard - -"ms@npm:^2.1.1": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d - languageName: node - linkType: hard - -"nanoid@npm:^3.3.6": - version: 3.3.7 - resolution: "nanoid@npm:3.3.7" - bin: - nanoid: bin/nanoid.cjs - checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 - languageName: node - linkType: hard - -"natural-compare@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare@npm:1.4.0" - checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d - languageName: node - linkType: hard - -"next@npm:^14.1.1": - version: 14.1.1 - resolution: "next@npm:14.1.1" - dependencies: - "@next/env": 14.1.1 - "@next/swc-darwin-arm64": 14.1.1 - "@next/swc-darwin-x64": 14.1.1 - "@next/swc-linux-arm64-gnu": 14.1.1 - "@next/swc-linux-arm64-musl": 14.1.1 - "@next/swc-linux-x64-gnu": 14.1.1 - "@next/swc-linux-x64-musl": 14.1.1 - "@next/swc-win32-arm64-msvc": 14.1.1 - "@next/swc-win32-ia32-msvc": 14.1.1 - "@next/swc-win32-x64-msvc": 14.1.1 - "@swc/helpers": 0.5.2 - busboy: 1.6.0 - caniuse-lite: ^1.0.30001579 - graceful-fs: ^4.2.11 - postcss: 8.4.31 - styled-jsx: 5.1.1 - peerDependencies: - "@opentelemetry/api": ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - dependenciesMeta: - "@next/swc-darwin-arm64": - optional: true - "@next/swc-darwin-x64": - optional: true - "@next/swc-linux-arm64-gnu": - optional: true - "@next/swc-linux-arm64-musl": - optional: true - "@next/swc-linux-x64-gnu": - optional: true - "@next/swc-linux-x64-musl": - optional: true - "@next/swc-win32-arm64-msvc": - optional: true - "@next/swc-win32-ia32-msvc": - optional: true - "@next/swc-win32-x64-msvc": - optional: true - peerDependenciesMeta: - "@opentelemetry/api": - optional: true - sass: - optional: true - bin: - next: dist/bin/next - checksum: 58c17bf9520648cb79c3341a0a011ce19e8e5368f23be7415b4a35787b3562519cfd0dd8e008a1ce0b49dfe79e4ab89127f412cf039cb854b35f79a457a9be22 - languageName: node - linkType: hard - -"node-releases@npm:^2.0.13": - version: 2.0.13 - resolution: "node-releases@npm:2.0.13" - checksum: 17ec8f315dba62710cae71a8dad3cd0288ba943d2ece43504b3b1aa8625bf138637798ab470b1d9035b0545996f63000a8a926e0f6d35d0996424f8b6d36dda3 - languageName: node - linkType: hard - -"normalize-package-data@npm:^2.5.0": - version: 2.5.0 - resolution: "normalize-package-data@npm:2.5.0" - dependencies: - hosted-git-info: ^2.1.4 - resolve: ^1.10.0 - semver: 2 || 3 || 4 || 5 - validate-npm-package-license: ^3.0.1 - checksum: 7999112efc35a6259bc22db460540cae06564aa65d0271e3bdfa86876d08b0e578b7b5b0028ee61b23f1cae9fc0e7847e4edc0948d3068a39a2a82853efc8499 - languageName: node - linkType: hard - -"npm-run-path@npm:^4.0.1": - version: 4.0.1 - resolution: "npm-run-path@npm:4.0.1" - dependencies: - path-key: ^3.0.0 - checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 - languageName: node - linkType: hard - -"npm-run-path@npm:^5.1.0": - version: 5.1.0 - resolution: "npm-run-path@npm:5.1.0" - dependencies: - path-key: ^4.0.0 - checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66 - languageName: node - linkType: hard - -"object-assign@npm:^4.1.1": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f - languageName: node - linkType: hard - -"object-inspect@npm:^1.12.3, object-inspect@npm:^1.9.0": - version: 1.12.3 - resolution: "object-inspect@npm:1.12.3" - checksum: dabfd824d97a5f407e6d5d24810d888859f6be394d8b733a77442b277e0808860555176719c5905e765e3743a7cada6b8b0a3b85e5331c530fd418cc8ae991db - languageName: node - linkType: hard - -"object-inspect@npm:^1.13.1": - version: 1.13.1 - resolution: "object-inspect@npm:1.13.1" - checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f - languageName: node - linkType: hard - -"object-keys@npm:^1.1.1": - version: 1.1.1 - resolution: "object-keys@npm:1.1.1" - checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a - languageName: node - linkType: hard - -"object.assign@npm:^4.1.3, object.assign@npm:^4.1.4": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - has-symbols: ^1.0.3 - object-keys: ^1.1.1 - checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864 - languageName: node - linkType: hard - -"object.entries@npm:^1.1.5, object.entries@npm:^1.1.6": - version: 1.1.6 - resolution: "object.entries@npm:1.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 0f8c47517e6a9a980241eafe3b73de11e59511883173c2b93d67424a008e47e11b77c80e431ad1d8a806f6108b225a1cab9223e53e555776c612a24297117d28 - languageName: node - linkType: hard - -"object.entries@npm:^1.1.7": - version: 1.1.7 - resolution: "object.entries@npm:1.1.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: da287d434e7e32989586cd734382364ba826a2527f2bc82e6acbf9f9bfafa35d51018b66ec02543ffdfa2a5ba4af2b6f1ca6e588c65030cb4fd9c67d6ced594c - languageName: node - linkType: hard - -"object.fromentries@npm:^2.0.5, object.fromentries@npm:^2.0.6": - version: 2.0.6 - resolution: "object.fromentries@npm:2.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 453c6d694180c0c30df451b60eaf27a5b9bca3fb43c37908fd2b78af895803dc631242bcf05582173afa40d8d0e9c96e16e8874b39471aa53f3ac1f98a085d85 - languageName: node - linkType: hard - -"object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 7341ce246e248b39a431b87a9ddd331ff52a454deb79afebc95609f94b1f8238966cf21f52188f2a353f0fdf83294f32f1ebf1f7826aae915ebad21fd0678065 - languageName: node - linkType: hard - -"object.groupby@npm:^1.0.1": - version: 1.0.1 - resolution: "object.groupby@npm:1.0.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - checksum: d7959d6eaaba358b1608066fc67ac97f23ce6f573dc8fc661f68c52be165266fcb02937076aedb0e42722fdda0bdc0bbf74778196ac04868178888e9fd3b78b5 - languageName: node - linkType: hard - -"object.hasown@npm:^1.1.0, object.hasown@npm:^1.1.2": - version: 1.1.2 - resolution: "object.hasown@npm:1.1.2" - dependencies: - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: b936572536db0cdf38eb30afd2f1026a8b6f2cc5d2c4497c9d9bbb01eaf3e980dead4fd07580cfdd098e6383e5a9db8212d3ea0c6bdd2b5e68c60aa7e3b45566 - languageName: node - linkType: hard - -"object.values@npm:^1.1.5, object.values@npm:^1.1.6": - version: 1.1.6 - resolution: "object.values@npm:1.1.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: f6fff9fd817c24cfd8107f50fb33061d81cd11bacc4e3dbb3852e9ff7692fde4dbce823d4333ea27cd9637ef1b6690df5fbb61f1ed314fa2959598dc3ae23d8e - languageName: node - linkType: hard - -"object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: f3e4ae4f21eb1cc7cebb6ce036d4c67b36e1c750428d7b7623c56a0db90edced63d08af8a316d81dfb7c41a3a5fa81b05b7cc9426e98d7da986b1682460f0777 - languageName: node - linkType: hard - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: 1 - checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 - languageName: node - linkType: hard - -"onetime@npm:^5.1.2": - version: 5.1.2 - resolution: "onetime@npm:5.1.2" - dependencies: - mimic-fn: ^2.1.0 - checksum: 2478859ef817fc5d4e9c2f9e5728512ddd1dbc9fb7829ad263765bb6d3b91ce699d6e2332eef6b7dff183c2f490bd3349f1666427eaba4469fba0ac38dfd0d34 - languageName: node - linkType: hard - -"onetime@npm:^6.0.0": - version: 6.0.0 - resolution: "onetime@npm:6.0.0" - dependencies: - mimic-fn: ^4.0.0 - checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 - languageName: node - linkType: hard - -"open@npm:^9.1.0": - version: 9.1.0 - resolution: "open@npm:9.1.0" - dependencies: - default-browser: ^4.0.0 - define-lazy-prop: ^3.0.0 - is-inside-container: ^1.0.0 - is-wsl: ^2.2.0 - checksum: 3993c0f61d51fed8ac290e99c9c3cf45d3b6cfb3e2aa2b74cafd312c3486c22fd81df16ac8f3ab91dd8a4e3e729a16fc2480cfc406c4833416cf908acf1ae7c9 - languageName: node - linkType: hard - -"optionator@npm:^0.9.3": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" - dependencies: - "@aashutoshrathi/word-wrap": ^1.2.3 - deep-is: ^0.1.3 - fast-levenshtein: ^2.0.6 - levn: ^0.4.1 - prelude-ls: ^1.2.1 - type-check: ^0.4.0 - checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a - languageName: node - linkType: hard - -"p-limit@npm:^2.2.0": - version: 2.3.0 - resolution: "p-limit@npm:2.3.0" - dependencies: - p-try: ^2.0.0 - checksum: 84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 - languageName: node - linkType: hard - -"p-limit@npm:^3.0.2": - version: 3.1.0 - resolution: "p-limit@npm:3.1.0" - dependencies: - yocto-queue: ^0.1.0 - checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 - languageName: node - linkType: hard - -"p-locate@npm:^4.1.0": - version: 4.1.0 - resolution: "p-locate@npm:4.1.0" - dependencies: - p-limit: ^2.2.0 - checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 - languageName: node - linkType: hard - -"p-locate@npm:^5.0.0": - version: 5.0.0 - resolution: "p-locate@npm:5.0.0" - dependencies: - p-limit: ^3.0.2 - checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 - languageName: node - linkType: hard - -"p-try@npm:^2.0.0": - version: 2.2.0 - resolution: "p-try@npm:2.2.0" - checksum: f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae - languageName: node - linkType: hard - -"parent-module@npm:^1.0.0": - version: 1.0.1 - resolution: "parent-module@npm:1.0.1" - dependencies: - callsites: ^3.0.0 - checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff - languageName: node - linkType: hard - -"parse-json@npm:^5.0.0": - version: 5.2.0 - resolution: "parse-json@npm:5.2.0" - 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 - checksum: 62085b17d64da57f40f6afc2ac1f4d95def18c4323577e1eced571db75d9ab59b297d1d10582920f84b15985cbfc6b6d450ccbf317644cfa176f3ed982ad87e2 - languageName: node - linkType: hard - -"path-exists@npm:^4.0.0": - version: 4.0.0 - resolution: "path-exists@npm:4.0.0" - checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 - languageName: node - linkType: hard - -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 - languageName: node - linkType: hard - -"path-key@npm:^3.0.0, path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 - languageName: node - linkType: hard - -"path-key@npm:^4.0.0": - version: 4.0.0 - resolution: "path-key@npm:4.0.0" - checksum: 8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 - languageName: node - linkType: hard - -"path-parse@npm:^1.0.6, path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a - languageName: node - linkType: hard - -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" - dependencies: - lru-cache: ^9.1.1 || ^10.0.0 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 - languageName: node - linkType: hard - -"path-type@npm:^4.0.0": - version: 4.0.0 - resolution: "path-type@npm:4.0.0" - checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 - languageName: node - linkType: hard - -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 - languageName: node - linkType: hard - -"picomatch@npm:^2.3.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf - languageName: node - linkType: hard - -"pluralize@npm:^8.0.0": - version: 8.0.0 - resolution: "pluralize@npm:8.0.0" - checksum: 08931d4a6a4a5561a7f94f67a31c17e6632cb21e459ab3ff4f6f629d9a822984cf8afef2311d2005fbea5d7ef26016ebb090db008e2d8bce39d0a9a9d218736e - languageName: node - linkType: hard - -"postcss@npm:8.4.31": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" - dependencies: - nanoid: ^3.3.6 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea - languageName: node - linkType: hard - -"prelude-ls@npm:^1.2.1": - version: 1.2.1 - resolution: "prelude-ls@npm:1.2.1" - checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a - languageName: node - linkType: hard - -"prettier-plugin-packagejson@npm:^2.4.5": - version: 2.4.6 - resolution: "prettier-plugin-packagejson@npm:2.4.6" - dependencies: - sort-package-json: 2.6.0 - synckit: 0.8.5 - peerDependencies: - prettier: ">= 1.16.0" - peerDependenciesMeta: - prettier: - optional: true - checksum: fc9063ea6723ded37ab7f171f9530371895af3f30369b3b97dd8d2da687fd51587e9630a019fc2b2b442c7b130ddb1e3a9c8dcdb414e29fa532f788fb9e4cd24 - languageName: node - linkType: hard - -"prettier@npm:^3.2.5": - version: 3.2.5 - resolution: "prettier@npm:3.2.5" - bin: - prettier: bin/prettier.cjs - checksum: 2ee4e1417572372afb7a13bb446b34f20f1bf1747db77cf6ccaf57a9be005f2f15c40f903d41a6b79eec3f57fff14d32a20fb6dee1f126da48908926fe43c311 - languageName: node - linkType: hard - -"prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": - version: 15.8.1 - resolution: "prop-types@npm:15.8.1" - dependencies: - loose-envify: ^1.4.0 - object-assign: ^4.1.1 - react-is: ^16.13.1 - checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0": - version: 2.3.0 - resolution: "punycode@npm:2.3.0" - checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200 - languageName: node - linkType: hard - -"queue-microtask@npm:^1.2.2": - version: 1.2.3 - resolution: "queue-microtask@npm:1.2.3" - checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 - languageName: node - linkType: hard - -"react-dom@npm:^18.2.0": - version: 18.2.0 - resolution: "react-dom@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - scheduler: ^0.23.0 - peerDependencies: - react: ^18.2.0 - checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc - languageName: node - linkType: hard - -"react-is@npm:^16.13.1": - version: 16.13.1 - resolution: "react-is@npm:16.13.1" - checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f - languageName: node - linkType: hard - -"react@npm:^18.2.0": - version: 18.2.0 - resolution: "react@npm:18.2.0" - dependencies: - loose-envify: ^1.1.0 - checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b - languageName: node - linkType: hard - -"read-pkg-up@npm:^7.0.1": - version: 7.0.1 - resolution: "read-pkg-up@npm:7.0.1" - dependencies: - find-up: ^4.1.0 - read-pkg: ^5.2.0 - type-fest: ^0.8.1 - checksum: e4e93ce70e5905b490ca8f883eb9e48b5d3cebc6cd4527c25a0d8f3ae2903bd4121c5ab9c5a3e217ada0141098eeb661313c86fa008524b089b8ed0b7f165e44 - languageName: node - linkType: hard - -"read-pkg@npm:^5.2.0": - version: 5.2.0 - resolution: "read-pkg@npm:5.2.0" - dependencies: - "@types/normalize-package-data": ^2.4.0 - normalize-package-data: ^2.5.0 - parse-json: ^5.0.0 - type-fest: ^0.6.0 - checksum: eb696e60528b29aebe10e499ba93f44991908c57d70f2d26f369e46b8b9afc208ef11b4ba64f67630f31df8b6872129e0a8933c8c53b7b4daf0eace536901222 - languageName: node - linkType: hard - -"reflect.getprototypeof@npm:^1.0.4": - version: 1.0.4 - resolution: "reflect.getprototypeof@npm:1.0.4" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - globalthis: ^1.0.3 - which-builtin-type: ^1.1.3 - checksum: 16e2361988dbdd23274b53fb2b1b9cefeab876c3941a2543b4cadac6f989e3db3957b07a44aac46cfceb3e06e2871785ec2aac992d824f76292f3b5ee87f66f2 - languageName: node - linkType: hard - -"regenerator-runtime@npm:^0.14.0": - version: 0.14.0 - resolution: "regenerator-runtime@npm:0.14.0" - checksum: 1c977ad82a82a4412e4f639d65d22be376d3ebdd30da2c003eeafdaaacd03fc00c2320f18120007ee700900979284fc78a9f00da7fb593f6e6eeebc673fba9a3 - languageName: node - linkType: hard - -"regexp-tree@npm:^0.1.27": - version: 0.1.27 - resolution: "regexp-tree@npm:0.1.27" - bin: - regexp-tree: bin/regexp-tree - checksum: 129aebb34dae22d6694ab2ac328be3f99105143737528ab072ef624d599afecbcfae1f5c96a166fa9e5f64fa1ecf30b411c4691e7924c3e11bbaf1712c260c54 - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.4.3": - version: 1.5.0 - resolution: "regexp.prototype.flags@npm:1.5.0" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - functions-have-names: ^1.2.3 - checksum: c541687cdbdfff1b9a07f6e44879f82c66bbf07665f9a7544c5fd16acdb3ec8d1436caab01662d2fbcad403f3499d49ab0b77fbc7ef29ef961d98cc4bc9755b4 - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.5.1": - version: 1.5.1 - resolution: "regexp.prototype.flags@npm:1.5.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - set-function-name: ^2.0.0 - checksum: 869edff00288442f8d7fa4c9327f91d85f3b3acf8cbbef9ea7a220345cf23e9241b6def9263d2c1ebcf3a316b0aa52ad26a43a84aa02baca3381717b3e307f47 - languageName: node - linkType: hard - -"regjsparser@npm:^0.10.0": - version: 0.10.0 - resolution: "regjsparser@npm:0.10.0" - dependencies: - jsesc: ~0.5.0 - bin: - regjsparser: bin/parser - checksum: 17550661f43ba792f8365fb95b3dbdb64e25f14e31ef7c2c11876c240a60e87b7bfc28c98589f4e76b7cf49307e45fb24d030f57d68dd0cc41c56b4d378e9254 - languageName: node - linkType: hard - -"resolve-from@npm:^4.0.0": - version: 4.0.0 - resolution: "resolve-from@npm:4.0.0" - checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f - languageName: node - linkType: hard - -"resolve@npm:^1.10.0, resolve@npm:^1.22.0, resolve@npm:^1.22.4": - version: 1.22.8 - resolution: "resolve@npm:1.22.8" - dependencies: - is-core-module: ^2.13.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c - languageName: node - linkType: hard - -"resolve@npm:^1.22.1": - version: 1.22.2 - resolution: "resolve@npm:1.22.2" - dependencies: - is-core-module: ^2.11.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 7e5df75796ebd429445d102d5824482ee7e567f0070b2b45897b29bb4f613dcbc262e0257b8aeedb3089330ccaea0d6a0464df1a77b2992cf331dcda0f4cb549 - languageName: node - linkType: hard - -"resolve@npm:^2.0.0-next.3, resolve@npm:^2.0.0-next.4": - version: 2.0.0-next.4 - resolution: "resolve@npm:2.0.0-next.4" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: c438ac9a650f2030fd074219d7f12ceb983b475da2d89ad3d6dd05fbf6b7a0a8cd37d4d10b43cb1f632bc19f22246ab7f36ebda54d84a29bfb2910a0680906d3 - languageName: node - linkType: hard - -"resolve@npm:~1.19.0": - version: 1.19.0 - resolution: "resolve@npm:1.19.0" - dependencies: - is-core-module: ^2.1.0 - path-parse: ^1.0.6 - checksum: a05b356e47b85ad3613d9e2a39a824f3c27f4fcad9c9ff6c7cc71a2e314c5904a90ab37481ad0069d03cab9eaaac6eb68aca1bc3355fdb05f1045cd50e2aacea - languageName: node - linkType: hard - -"resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin, resolve@patch:resolve@^1.22.4#~builtin": - version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=c3c19d" - dependencies: - is-core-module: ^2.13.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847 - languageName: node - linkType: hard - -"resolve@patch:resolve@^1.22.1#~builtin": - version: 1.22.2 - resolution: "resolve@patch:resolve@npm%3A1.22.2#~builtin::version=1.22.2&hash=c3c19d" - dependencies: - is-core-module: ^2.11.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 66cc788f13b8398de18eb4abb3aed90435c84bb8935953feafcf7231ba4cd191b2c10b4a87b1e9681afc34fb138c705f91f7330ff90bfa36f457e5584076a2b8 - languageName: node - linkType: hard - -"resolve@patch:resolve@^2.0.0-next.3#~builtin, resolve@patch:resolve@^2.0.0-next.4#~builtin": - version: 2.0.0-next.4 - resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin::version=2.0.0-next.4&hash=c3c19d" - dependencies: - is-core-module: ^2.9.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 4bf9f4f8a458607af90518ff73c67a4bc1a38b5a23fef2bb0ccbd45e8be89820a1639b637b0ba377eb2be9eedfb1739a84cde24fe4cd670c8207d8fea922b011 - languageName: node - linkType: hard - -"resolve@patch:resolve@~1.19.0#~builtin": - version: 1.19.0 - resolution: "resolve@patch:resolve@npm%3A1.19.0#~builtin::version=1.19.0&hash=c3c19d" - dependencies: - is-core-module: ^2.1.0 - path-parse: ^1.0.6 - checksum: 2443b94d347e6946c87c85faf13071f605e609e0b54784829b0ed2b917d050bfc1cbaf4ecc6453f224cfa7d0c5dcd97cbb273454cd210bee68e4af15c1a5abc9 - languageName: node - linkType: hard - -"reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc - languageName: node - linkType: hard - -"rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: ^7.1.3 - bin: - rimraf: bin.js - checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 - languageName: node - linkType: hard - -"run-applescript@npm:^5.0.0": - version: 5.0.0 - resolution: "run-applescript@npm:5.0.0" - dependencies: - execa: ^5.0.0 - checksum: d00c2dbfa5b2d774de7451194b8b125f40f65fc183de7d9dcae97f57f59433586d3c39b9001e111c38bfa24c3436c99df1bb4066a2a0c90d39a8c4cd6889af77 - languageName: node - linkType: hard - -"run-parallel@npm:^1.1.9": - version: 1.2.0 - resolution: "run-parallel@npm:1.2.0" - dependencies: - queue-microtask: ^1.2.2 - checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d - languageName: node - linkType: hard - -"safe-array-concat@npm:^1.0.1": - version: 1.0.1 - resolution: "safe-array-concat@npm:1.0.1" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.1 - has-symbols: ^1.0.3 - isarray: ^2.0.5 - checksum: 001ecf1d8af398251cbfabaf30ed66e3855127fbceee178179524b24160b49d15442f94ed6c0db0b2e796da76bb05b73bf3cc241490ec9c2b741b41d33058581 - languageName: node - linkType: hard - -"safe-regex-test@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-regex-test@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.3 - is-regex: ^1.1.4 - checksum: bc566d8beb8b43c01b94e67de3f070fd2781685e835959bbbaaec91cc53381145ca91f69bd837ce6ec244817afa0a5e974fc4e40a2957f0aca68ac3add1ddd34 - languageName: node - linkType: hard - -"scheduler@npm:^0.23.0": - version: 0.23.0 - resolution: "scheduler@npm:0.23.0" - dependencies: - loose-envify: ^1.1.0 - checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a - languageName: node - linkType: hard - -"semver@npm:2 || 3 || 4 || 5": - version: 5.7.2 - resolution: "semver@npm:5.7.2" - bin: - semver: bin/semver - checksum: fb4ab5e0dd1c22ce0c937ea390b4a822147a9c53dbd2a9a0132f12fe382902beef4fbf12cf51bb955248d8d15874ce8cd89532569756384f994309825f10b686 - languageName: node - linkType: hard - -"semver@npm:^6.3.0": - version: 6.3.0 - resolution: "semver@npm:6.3.0" - bin: - semver: ./bin/semver.js - checksum: 1b26ecf6db9e8292dd90df4e781d91875c0dcc1b1909e70f5d12959a23c7eebb8f01ea581c00783bbee72ceeaad9505797c381756326073850dc36ed284b21b9 - languageName: node - linkType: hard - -"semver@npm:^6.3.1": - version: 6.3.1 - resolution: "semver@npm:6.3.1" - bin: - semver: bin/semver.js - checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 - languageName: node - linkType: hard - -"semver@npm:^7.3.7, semver@npm:^7.5.4": - version: 7.5.4 - resolution: "semver@npm:7.5.4" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 - languageName: node - linkType: hard - -"set-function-length@npm:^1.1.1": - version: 1.1.1 - resolution: "set-function-length@npm:1.1.1" - dependencies: - define-data-property: ^1.1.1 - get-intrinsic: ^1.2.1 - gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - checksum: c131d7569cd7e110cafdfbfbb0557249b538477624dfac4fc18c376d879672fa52563b74029ca01f8f4583a8acb35bb1e873d573a24edb80d978a7ee607c6e06 - languageName: node - linkType: hard - -"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" - dependencies: - define-data-property: ^1.0.1 - functions-have-names: ^1.2.3 - has-property-descriptors: ^1.0.0 - checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: ^3.0.0 - checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 - languageName: node - linkType: hard - -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" - dependencies: - call-bind: ^1.0.0 - get-intrinsic: ^1.0.2 - object-inspect: ^1.9.0 - checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 - languageName: node - linkType: hard - -"signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 - languageName: node - linkType: hard - -"slash@npm:^3.0.0": - version: 3.0.0 - resolution: "slash@npm:3.0.0" - checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c - languageName: node - linkType: hard - -"slash@npm:^4.0.0": - version: 4.0.0 - resolution: "slash@npm:4.0.0" - checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d - languageName: node - linkType: hard - -"sort-object-keys@npm:^1.1.3": - version: 1.1.3 - resolution: "sort-object-keys@npm:1.1.3" - checksum: abea944d6722a1710a1aa6e4f9509da085d93d5fc0db23947cb411eedc7731f80022ce8fa68ed83a53dd2ac7441fcf72a3f38c09b3d9bbc4ff80546aa2e151ad - languageName: node - linkType: hard - -"sort-package-json@npm:2.6.0": - version: 2.6.0 - resolution: "sort-package-json@npm:2.6.0" - dependencies: - detect-indent: ^7.0.1 - detect-newline: ^4.0.0 - get-stdin: ^9.0.0 - git-hooks-list: ^3.0.0 - globby: ^13.1.2 - is-plain-obj: ^4.1.0 - sort-object-keys: ^1.1.3 - bin: - sort-package-json: cli.js - checksum: 78ca29fb3122858e0b141642d2415ef767e8a31e411d50a4904658f29e4f8172af15d6df73fe2fa3205b0e76c0ab15ec561ce2a630ea33485d8552bbdb111268 - languageName: node - linkType: hard - -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c - languageName: node - linkType: hard - -"spdx-correct@npm:^3.0.0": - version: 3.2.0 - resolution: "spdx-correct@npm:3.2.0" - dependencies: - spdx-expression-parse: ^3.0.0 - spdx-license-ids: ^3.0.0 - checksum: e9ae98d22f69c88e7aff5b8778dc01c361ef635580e82d29e5c60a6533cc8f4d820803e67d7432581af0cc4fb49973125076ee3b90df191d153e223c004193b2 - languageName: node - linkType: hard - -"spdx-exceptions@npm:^2.1.0": - version: 2.3.0 - resolution: "spdx-exceptions@npm:2.3.0" - checksum: cb69a26fa3b46305637123cd37c85f75610e8c477b6476fa7354eb67c08128d159f1d36715f19be6f9daf4b680337deb8c65acdcae7f2608ba51931540687ac0 - languageName: node - linkType: hard - -"spdx-expression-parse@npm:^3.0.0": - version: 3.0.1 - resolution: "spdx-expression-parse@npm:3.0.1" - dependencies: - spdx-exceptions: ^2.1.0 - spdx-license-ids: ^3.0.0 - checksum: a1c6e104a2cbada7a593eaa9f430bd5e148ef5290d4c0409899855ce8b1c39652bcc88a725259491a82601159d6dc790bedefc9016c7472f7de8de7361f8ccde - languageName: node - linkType: hard - -"spdx-license-ids@npm:^3.0.0": - version: 3.0.16 - resolution: "spdx-license-ids@npm:3.0.16" - checksum: 5cdaa85aaa24bd02f9353a2e357b4df0a4f205cb35655f3fd0a5674a4fb77081f28ffd425379214bc3be2c2b7593ce1215df6bcc75884aeee0a9811207feabe2 - languageName: node - linkType: hard - -"streamsearch@npm:^1.1.0": - version: 1.1.0 - resolution: "streamsearch@npm:1.1.0" - checksum: 1cce16cea8405d7a233d32ca5e00a00169cc0e19fbc02aa839959985f267335d435c07f96e5e0edd0eadc6d39c98d5435fb5bbbdefc62c41834eadc5622ad942 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: ^8.0.0 - is-fullwidth-code-point: ^3.0.0 - strip-ansi: ^6.0.1 - checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: ^0.2.0 - emoji-regex: ^9.2.2 - strip-ansi: ^7.0.1 - checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 - languageName: node - linkType: hard - -"string.prototype.matchall@npm:^4.0.6, string.prototype.matchall@npm:^4.0.8": - version: 4.0.8 - resolution: "string.prototype.matchall@npm:4.0.8" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - get-intrinsic: ^1.1.3 - has-symbols: ^1.0.3 - internal-slot: ^1.0.3 - regexp.prototype.flags: ^1.4.3 - side-channel: ^1.0.4 - checksum: 952da3a818de42ad1c10b576140a5e05b4de7b34b8d9dbf00c3ac8c1293e9c0f533613a39c5cda53e0a8221f2e710bc2150e730b1c2278d60004a8a35726efb6 - languageName: node - linkType: hard - -"string.prototype.trim@npm:^1.2.7": - version: 1.2.7 - resolution: "string.prototype.trim@npm:1.2.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 05b7b2d6af63648e70e44c4a8d10d8cc457536df78b55b9d6230918bde75c5987f6b8604438c4c8652eb55e4fc9725d2912789eb4ec457d6995f3495af190c09 - languageName: node - linkType: hard - -"string.prototype.trim@npm:^1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 49eb1a862a53aba73c3fb6c2a53f5463173cb1f4512374b623bcd6b43ad49dd559a06fb5789bdec771a40fc4d2a564411c0a75d35fb27e76bbe738c211ecff07 - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimend@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 0fdc34645a639bd35179b5a08227a353b88dc089adf438f46be8a7c197fc3f22f8514c1c9be4629b3cd29c281582730a8cbbad6466c60f76b5f99cf2addb132e - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 2375516272fd1ba75992f4c4aa88a7b5f3c7a9ca308d963bcd5645adf689eba6f8a04ebab80c33e30ec0aefc6554181a3a8416015c38da0aa118e60ec896310c - languageName: node - linkType: hard - -"string.prototype.trimstart@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimstart@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 89080feef416621e6ef1279588994305477a7a91648d9436490d56010a1f7adc39167cddac7ce0b9884b8cdbef086987c4dcb2960209f2af8bac0d23ceff4f41 - languageName: node - linkType: hard - -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 13d0c2cb0d5ff9e926fa0bec559158b062eed2b68cd5be777ffba782c96b2b492944e47057274e064549b94dd27cf81f48b27a31fee8af5b574cff253e7eb613 - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: ^5.0.1 - checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: ^6.0.1 - checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d - languageName: node - linkType: hard - -"strip-bom@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-bom@npm:3.0.0" - checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b - languageName: node - linkType: hard - -"strip-final-newline@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-final-newline@npm:2.0.0" - checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 - languageName: node - linkType: hard - -"strip-final-newline@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-final-newline@npm:3.0.0" - checksum: 23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 - languageName: node - linkType: hard - -"strip-indent@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-indent@npm:3.0.0" - dependencies: - min-indent: ^1.0.0 - checksum: 18f045d57d9d0d90cd16f72b2313d6364fd2cb4bf85b9f593523ad431c8720011a4d5f08b6591c9d580f446e78855c5334a30fb91aa1560f5d9f95ed1b4a0530 - languageName: node - linkType: hard - -"strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 - languageName: node - linkType: hard - -"styled-jsx@npm:5.1.1": - version: 5.1.1 - resolution: "styled-jsx@npm:5.1.1" - dependencies: - client-only: 0.0.1 - peerDependencies: - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" - peerDependenciesMeta: - "@babel/core": - optional: true - babel-plugin-macros: - optional: true - checksum: 523a33b38603492547e861b98e29c873939b04e15fbe5ef16132c6f1e15958126647983c7d4675325038b428a5e91183d996e90141b18bdd1bbadf6e2c45b2fa - languageName: node - linkType: hard - -"supports-color@npm:^5.3.0": - version: 5.5.0 - resolution: "supports-color@npm:5.5.0" - dependencies: - has-flag: ^3.0.0 - checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac - languageName: node - linkType: hard - -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: ^4.0.0 - checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae - languageName: node - linkType: hard - -"synckit@npm:0.8.5": - version: 0.8.5 - resolution: "synckit@npm:0.8.5" - dependencies: - "@pkgr/utils": ^2.3.1 - tslib: ^2.5.0 - checksum: 8a9560e5d8f3d94dc3cf5f7b9c83490ffa30d320093560a37b88f59483040771fd1750e76b9939abfbb1b5a23fd6dfbae77f6b338abffe7cae7329cd9b9bb86b - languageName: node - linkType: hard - -"tapable@npm:^2.2.0": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 - languageName: node - linkType: hard - -"text-table@npm:^0.2.0": - version: 0.2.0 - resolution: "text-table@npm:0.2.0" - checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a - languageName: node - linkType: hard - -"titleize@npm:^3.0.0": - version: 3.0.0 - resolution: "titleize@npm:3.0.0" - checksum: 71fbbeabbfb36ccd840559f67f21e356e1d03da2915b32d2ae1a60ddcc13a124be2739f696d2feb884983441d159a18649e8d956648d591bdad35c430a6b6d28 - languageName: node - linkType: hard - -"to-fast-properties@npm:^2.0.0": - version: 2.0.0 - resolution: "to-fast-properties@npm:2.0.0" - checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: ^7.0.0 - checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed - languageName: node - linkType: hard - -"ts-api-utils@npm:^1.0.1": - version: 1.0.3 - resolution: "ts-api-utils@npm:1.0.3" - peerDependencies: - typescript: ">=4.2.0" - checksum: 441cc4489d65fd515ae6b0f4eb8690057add6f3b6a63a36073753547fb6ce0c9ea0e0530220a0b282b0eec535f52c4dfc315d35f8a4c9a91c0def0707a714ca6 - languageName: node - linkType: hard - -"tsconfig-paths@npm:^3.14.1, tsconfig-paths@npm:^3.14.2": - version: 3.14.2 - resolution: "tsconfig-paths@npm:3.14.2" - dependencies: - "@types/json5": ^0.0.29 - json5: ^1.0.2 - minimist: ^1.2.6 - strip-bom: ^3.0.0 - checksum: a6162eaa1aed680537f93621b82399c7856afd10ec299867b13a0675e981acac4e0ec00896860480efc59fc10fd0b16fdc928c0b885865b52be62cadac692447 - languageName: node - linkType: hard - -"tslib@npm:^1.8.1": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd - languageName: node - linkType: hard - -"tslib@npm:^2.4.0, tslib@npm:^2.5.0": - version: 2.5.0 - resolution: "tslib@npm:2.5.0" - checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1 - languageName: node - linkType: hard - -"tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" - dependencies: - tslib: ^1.8.1 - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 1843f4c1b2e0f975e08c4c21caa4af4f7f65a12ac1b81b3b8489366826259323feb3fc7a243123453d2d1a02314205a7634e048d4a8009921da19f99755cdc48 - languageName: node - linkType: hard - -"turbo-darwin-64@npm:2.0.3": - version: 2.0.3 - resolution: "turbo-darwin-64@npm:2.0.3" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"turbo-darwin-arm64@npm:2.0.3": - version: 2.0.3 - resolution: "turbo-darwin-arm64@npm:2.0.3" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"turbo-linux-64@npm:2.0.3": - version: 2.0.3 - resolution: "turbo-linux-64@npm:2.0.3" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"turbo-linux-arm64@npm:2.0.3": - version: 2.0.3 - resolution: "turbo-linux-arm64@npm:2.0.3" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"turbo-windows-64@npm:2.0.3": - version: 2.0.3 - resolution: "turbo-windows-64@npm:2.0.3" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"turbo-windows-arm64@npm:2.0.3": - version: 2.0.3 - resolution: "turbo-windows-arm64@npm:2.0.3" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"turbo@npm:^2.0.3": - version: 2.0.3 - resolution: "turbo@npm:2.0.3" - dependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dependenciesMeta: - turbo-darwin-64: - optional: true - turbo-darwin-arm64: - optional: true - turbo-linux-64: - optional: true - turbo-linux-arm64: - optional: true - turbo-windows-64: - optional: true - turbo-windows-arm64: - optional: true - bin: - turbo: bin/turbo - checksum: deeddef5bbf1db454ebcc0d460f638506146f85724c5bb10c9b08009c3471798ce3594b4ef50fd03722313d9ef80552f9c93119e04c5859eac73225837caccac - languageName: node - linkType: hard - -"type-check@npm:^0.4.0, type-check@npm:~0.4.0": - version: 0.4.0 - resolution: "type-check@npm:0.4.0" - dependencies: - prelude-ls: ^1.2.1 - checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a - languageName: node - linkType: hard - -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 - languageName: node - linkType: hard - -"type-fest@npm:^0.6.0": - version: 0.6.0 - resolution: "type-fest@npm:0.6.0" - checksum: b2188e6e4b21557f6e92960ec496d28a51d68658018cba8b597bd3ef757721d1db309f120ae987abeeda874511d14b776157ff809f23c6d1ce8f83b9b2b7d60f - languageName: node - linkType: hard - -"type-fest@npm:^0.8.1": - version: 0.8.1 - resolution: "type-fest@npm:0.8.1" - checksum: d61c4b2eba24009033ae4500d7d818a94fd6d1b481a8111612ee141400d5f1db46f199c014766b9fa9b31a6a7374d96fc748c6d688a78a3ce5a33123839becb7 - languageName: node - linkType: hard - -"typed-array-buffer@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-buffer@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.1 - is-typed-array: ^1.1.10 - checksum: 3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3 - languageName: node - linkType: hard - -"typed-array-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-length@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: b03db16458322b263d87a702ff25388293f1356326c8a678d7515767ef563ef80e1e67ce648b821ec13178dd628eb2afdc19f97001ceae7a31acf674c849af94 - languageName: node - linkType: hard - -"typed-array-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-offset@npm:1.0.0" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: 04f6f02d0e9a948a95fbfe0d5a70b002191fae0b8fe0fe3130a9b2336f043daf7a3dda56a31333c35a067a97e13f539949ab261ca0f3692c41603a46a94e960b - languageName: node - linkType: hard - -"typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" - dependencies: - call-bind: ^1.0.2 - for-each: ^0.3.3 - is-typed-array: ^1.1.9 - checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 - languageName: node - linkType: hard - -"typescript@npm:5.5.4": - version: 5.5.4 - resolution: "typescript@npm:5.5.4" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: b309040f3a1cd91c68a5a58af6b9fdd4e849b8c42d837b2c2e73f9a4f96a98c4f1ed398a9aab576ee0a4748f5690cf594e6b99dbe61de7839da748c41e6d6ca8 - languageName: node - linkType: hard - -"typescript@patch:typescript@5.5.4#~builtin": - version: 5.5.4 - resolution: "typescript@patch:typescript@npm%3A5.5.4#~builtin::version=5.5.4&hash=f3b441" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: fc52962f31a5bcb716d4213bef516885e4f01f30cea797a831205fc9ef12b405a40561c40eae3127ab85ba1548e7df49df2bcdee6b84a94bfbe3a0d7eff16b14 - languageName: node - linkType: hard - -"unbox-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "unbox-primitive@npm:1.0.2" - dependencies: - call-bind: ^1.0.2 - has-bigints: ^1.0.2 - has-symbols: ^1.0.3 - which-boxed-primitive: ^1.0.2 - checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 - languageName: node - linkType: hard - -"undici-types@npm:~5.26.4": - version: 5.26.5 - resolution: "undici-types@npm:5.26.5" - checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 - languageName: node - linkType: hard - -"untildify@npm:^4.0.0": - version: 4.0.0 - resolution: "untildify@npm:4.0.0" - checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 - languageName: node - linkType: hard - -"update-browserslist-db@npm:^1.0.13": - version: 1.0.13 - resolution: "update-browserslist-db@npm:1.0.13" - dependencies: - escalade: ^3.1.1 - picocolors: ^1.0.0 - peerDependencies: - browserslist: ">= 4.21.0" - bin: - update-browserslist-db: cli.js - checksum: 1e47d80182ab6e4ad35396ad8b61008ae2a1330221175d0abd37689658bdb61af9b705bfc41057fd16682474d79944fb2d86767c5ed5ae34b6276b9bed353322 - languageName: node - linkType: hard - -"uri-js@npm:^4.2.2": - version: 4.4.1 - resolution: "uri-js@npm:4.4.1" - dependencies: - punycode: ^2.1.0 - checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 - languageName: node - linkType: hard - -"validate-npm-package-license@npm:^3.0.1": - version: 3.0.4 - resolution: "validate-npm-package-license@npm:3.0.4" - dependencies: - spdx-correct: ^3.0.0 - spdx-expression-parse: ^3.0.0 - checksum: 35703ac889d419cf2aceef63daeadbe4e77227c39ab6287eeb6c1b36a746b364f50ba22e88591f5d017bc54685d8137bc2d328d0a896e4d3fd22093c0f32a9ad - languageName: node - linkType: hard - -"web@workspace:apps/web": - version: 0.0.0-use.local - resolution: "web@workspace:apps/web" - dependencies: - "@next/eslint-plugin-next": ^14.1.1 - "@repo/eslint-config": "*" - "@repo/typescript-config": "*" - "@repo/ui": "*" - "@types/node": ^20.11.24 - "@types/react": ^18.2.61 - "@types/react-dom": ^18.2.19 - eslint: ^8.57.0 - next: ^14.1.1 - react: ^18.2.0 - react-dom: ^18.2.0 - typescript: 5.5.4 - languageName: unknown - linkType: soft - -"which-boxed-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "which-boxed-primitive@npm:1.0.2" - dependencies: - is-bigint: ^1.0.1 - is-boolean-object: ^1.1.0 - is-number-object: ^1.0.4 - is-string: ^1.0.5 - is-symbol: ^1.0.3 - checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e - languageName: node - linkType: hard - -"which-builtin-type@npm:^1.1.3": - version: 1.1.3 - resolution: "which-builtin-type@npm:1.1.3" - dependencies: - function.prototype.name: ^1.1.5 - has-tostringtag: ^1.0.0 - is-async-function: ^2.0.0 - is-date-object: ^1.0.5 - is-finalizationregistry: ^1.0.2 - is-generator-function: ^1.0.10 - is-regex: ^1.1.4 - is-weakref: ^1.0.2 - isarray: ^2.0.5 - which-boxed-primitive: ^1.0.2 - which-collection: ^1.0.1 - which-typed-array: ^1.1.9 - checksum: 43730f7d8660ff9e33d1d3f9f9451c4784265ee7bf222babc35e61674a11a08e1c2925019d6c03154fcaaca4541df43abe35d2720843b9b4cbcebdcc31408f36 - languageName: node - linkType: hard - -"which-collection@npm:^1.0.1": - version: 1.0.1 - resolution: "which-collection@npm:1.0.1" - dependencies: - is-map: ^2.0.1 - is-set: ^2.0.1 - is-weakmap: ^2.0.1 - is-weakset: ^2.0.1 - checksum: c815bbd163107ef9cb84f135e6f34453eaf4cca994e7ba85ddb0d27cea724c623fae2a473ceccfd5549c53cc65a5d82692de418166df3f858e1e5dc60818581c - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13": - version: 1.1.13 - resolution: "which-typed-array@npm:1.1.13" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.4 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - checksum: 3828a0d5d72c800e369d447e54c7620742a4cc0c9baf1b5e8c17e9b6ff90d8d861a3a6dd4800f1953dbf80e5e5cec954a289e5b4a223e3bee4aeb1f8c5f33309 - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.9": - version: 1.1.9 - resolution: "which-typed-array@npm:1.1.9" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - is-typed-array: ^1.1.10 - checksum: fe0178ca44c57699ca2c0e657b64eaa8d2db2372a4e2851184f568f98c478ae3dc3fdb5f7e46c384487046b0cf9e23241423242b277e03e8ba3dabc7c84c98ef - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: ^2.0.0 - bin: - node-which: ./bin/node-which - checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 - languageName: node - linkType: hard - -"with-berry@workspace:.": - version: 0.0.0-use.local - resolution: "with-berry@workspace:." - dependencies: - eslint: 8.57.0 - eslint-config-custom: "*" - prettier: ^3.2.5 - turbo: ^2.0.3 - languageName: unknown - linkType: soft - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: ^4.0.0 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: ^6.1.0 - string-width: ^5.0.1 - strip-ansi: ^7.0.1 - checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 - languageName: node - linkType: hard - -"yallist@npm:^3.0.2": - version: 3.1.1 - resolution: "yallist@npm:3.1.1" - checksum: 48f7bb00dc19fc635a13a39fe547f527b10c9290e7b3e836b9a8f1ca04d4d342e85714416b3c2ab74949c9c66f9cebb0473e6bc353b79035356103b47641285d - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 - languageName: node - linkType: hard - -"yocto-queue@npm:^0.1.0": - version: 0.1.0 - resolution: "yocto-queue@npm:0.1.0" - checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 - languageName: node - linkType: hard diff --git a/examples/with-changesets/.changeset/README.md b/examples/with-changesets/.changeset/README.md deleted file mode 100644 index e5b6d8d6a67ad..0000000000000 --- a/examples/with-changesets/.changeset/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Changesets - -Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works -with multi-package repos, or single-package repos to help you version and publish your code. You can -find the full documentation for it [in our repository](https://github.com/changesets/changesets) - -We have a quick list of common questions to get you started engaging with this project in -[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/examples/with-changesets/.changeset/config.json b/examples/with-changesets/.changeset/config.json deleted file mode 100644 index c5ec4a01c557d..0000000000000 --- a/examples/with-changesets/.changeset/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", - "changelog": "@changesets/cli/changelog", - "baseBranch": "main", - "commit": false, - "fixed": [], - "linked": [], - "access": "public", - "updateInternalDependencies": "patch", - "ignore": ["@acme/docs"] -} diff --git a/examples/with-changesets/.github/workflows/release.yml b/examples/with-changesets/.github/workflows/release.yml deleted file mode 100644 index 036fd6d80d277..0000000000000 --- a/examples/with-changesets/.github/workflows/release.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Release - -on: - push: - branches: - - main - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - - name: Setup pnpm 8 - uses: pnpm/action-setup@v3 - with: - version: 8 - - - name: Setup Node.js 20.x - uses: actions/setup-node@v4 - with: - node-version: 20.x - - - name: Install Dependencies - run: pnpm i - - - name: Create Release Pull Request or Publish to npm - id: changesets - uses: changesets/action@v1 - with: - # This expects you to have a script called release which does a build for your packages and calls changeset publish - publish: pnpm release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Send a Slack notification if a publish happens - if: steps.changesets.outputs.published == 'true' - # You can do something when a publish happens. - run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!" diff --git a/examples/with-changesets/README.md b/examples/with-changesets/README.md deleted file mode 100644 index f81d8d11f75ac..0000000000000 --- a/examples/with-changesets/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Turborepo Design System starter with Changesets - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-changesets -``` - -## What's inside? - -This Turborepo includes the following: - -### Apps and Packages - -- `docs`: A placeholder documentation site powered by [Next.js](https://nextjs.org/) -- `@acme/core`: core React components -- `@acme/utils`: shared React utilities -- `@acme/tsconfig`: shared `tsconfig.json`s used throughout the monorepo -- `@acme/eslint-config`: ESLint preset - -Each package and app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Useful commands - -- `yarn build` - Build all packages and the docs site -- `yarn dev` - Develop all packages and the docs site -- `yarn lint` - Lint all packages -- `yarn changeset` - Generate a changeset -- `yarn clean` - Clean up all `node_modules` and `dist` folders (runs each package's clean script) - -### Changing the npm organization scope - -The npm organization scope for this design system starter is `@acme`. To change this, it's a bit manual at the moment, but you'll need to do the following: - -- Rename folders in `packages/*` to replace `acme` with your desired scope -- Search and replace `acme` with your desired scope -- Re-run `yarn install` - -## Versioning and Publishing packages - -Package publishing has been configured using [Changesets](https://github.com/changesets/changesets). Please review their [documentation](https://github.com/changesets/changesets#documentation) to familiarize yourself with the workflow. - -This example comes with automated npm releases setup in a [GitHub Action](https://github.com/changesets/action). To get this working, you will need to create an `NPM_TOKEN` and `GITHUB_TOKEN` in your repository settings. You should also install the [Changesets bot](https://github.com/apps/changeset-bot) on your GitHub repository as well. - -For more information about this automation, refer to the official [changesets documentation](https://github.com/changesets/changesets/blob/main/docs/automating-changesets.md) - -### npm - -If you want to publish package to the public npm registry and make them publicly available, this is already setup. - -To publish packages to a private npm organization scope, **remove** the following from each of the `package.json`'s - -```diff -- "publishConfig": { -- "access": "public" -- }, -``` - -### GitHub Package Registry - -See [Working with the npm registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#publishing-a-package-using-publishconfig-in-the-packagejson-file) diff --git a/examples/with-changesets/apps/docs/.eslintrc.js b/examples/with-changesets/apps/docs/.eslintrc.js deleted file mode 100644 index 64ec785c4e65e..0000000000000 --- a/examples/with-changesets/apps/docs/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - root: true, - extends: ["@acme/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-changesets/apps/docs/src/app/layout.tsx b/examples/with-changesets/apps/docs/Source/app/layout.tsx similarity index 100% rename from examples/with-changesets/apps/docs/src/app/layout.tsx rename to examples/with-changesets/apps/docs/Source/app/layout.tsx diff --git a/examples/with-changesets/apps/docs/src/app/page.tsx b/examples/with-changesets/apps/docs/Source/app/page.tsx similarity index 100% rename from examples/with-changesets/apps/docs/src/app/page.tsx rename to examples/with-changesets/apps/docs/Source/app/page.tsx diff --git a/examples/with-changesets/apps/docs/package.json b/examples/with-changesets/apps/docs/package.json index c927e69464c79..b003b1f829abf 100644 --- a/examples/with-changesets/apps/docs/package.json +++ b/examples/with-changesets/apps/docs/package.json @@ -1,28 +1,19 @@ { - "name": "@acme/docs", - "version": "0.0.0", - "private": true, - "scripts": { - "build": "next build", - "start": "next start ", - "dev": "next dev -p 3002", - "lint": "next lint", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next" - }, - "dependencies": { - "@acme/core": "workspace:*", - "@acme/utils": "workspace:*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@acme/tsconfig": "workspace:*", - "@next/eslint-plugin-next": "^14.1.1", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "@acme/eslint-config": "workspace:*", - "typescript": "5.5.4" - } + "name": "@acme/docs", + "scripts": { + "build": "next build", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next", + "dev": "next dev -p 3002", + "start": "next start " + }, + "dependencies": { + "@acme/core": "workspace:*", + "@acme/utils": "workspace:*", + "next": "15.1.7" + }, + "devDependencies": { + "@acme/eslint-config": "workspace:*", + "@acme/tsconfig": "workspace:*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-changesets/package.json b/examples/with-changesets/package.json index 703fed30a72ff..784efcda49072 100644 --- a/examples/with-changesets/package.json +++ b/examples/with-changesets/package.json @@ -1,24 +1,16 @@ { - "private": true, - "scripts": { - "build": "turbo build", - "dev": "turbo dev", - "lint": "turbo lint", - "clean": "turbo clean && rm -rf node_modules", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "changeset": "changeset", - "version-packages": "changeset version", - "release": "turbo build --filter=docs^... && changeset publish" - }, - "devDependencies": { - "@changesets/cli": "^2.27.1", - "eslint": "^8.57.0", - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "pnpm@8.15.6", - "engines": { - "node": ">=18" - }, - "name": "with-changesets" + "name": "with-changesets", + "scripts": { + "build": "turbo build", + "changeset": "changeset", + "clean": "turbo clean && rm -rf node_modules", + "dev": "turbo dev", + "release": "turbo build --filter=docs^... && changeset publish", + "version-packages": "changeset version" + }, + "dependencies": {}, + "devDependencies": { + "@changesets/cli": "2.27.12", + "turbo": "2.4.2" + } } diff --git a/examples/with-changesets/packages/acme-core/.eslintrc.js b/examples/with-changesets/packages/acme-core/.eslintrc.js deleted file mode 100644 index 1d9ce63f5ccde..0000000000000 --- a/examples/with-changesets/packages/acme-core/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - root: true, - extends: ["@acme/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-changesets/packages/acme-core/src/Button.tsx b/examples/with-changesets/packages/acme-core/Source/Button.tsx similarity index 100% rename from examples/with-changesets/packages/acme-core/src/Button.tsx rename to examples/with-changesets/packages/acme-core/Source/Button.tsx diff --git a/examples/with-changesets/packages/acme-core/src/index.tsx b/examples/with-changesets/packages/acme-core/Source/index.tsx similarity index 100% rename from examples/with-changesets/packages/acme-core/src/index.tsx rename to examples/with-changesets/packages/acme-core/Source/index.tsx diff --git a/examples/with-changesets/packages/acme-core/package.json b/examples/with-changesets/packages/acme-core/package.json index 5d721d17f580d..33342cd2ccd81 100644 --- a/examples/with-changesets/packages/acme-core/package.json +++ b/examples/with-changesets/packages/acme-core/package.json @@ -1,33 +1,21 @@ { - "name": "@acme/core", - "version": "0.0.0", - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "sideEffects": false, - "license": "MIT", - "files": [ - "dist/**" - ], - "scripts": { - "build": "tsup src/index.tsx --format esm,cjs --dts --external react", - "dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react", - "lint": "eslint \"src/**/*.ts*\"", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" - }, - "devDependencies": { - "@acme/tsconfig": "workspace:*", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "@acme/eslint-config": "workspace:*", - "tsup": "^8.0.2", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - }, - "publishConfig": { - "access": "public" - } + "name": "@acme/core", + "sideEffects": false, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist/**" + ], + "scripts": { + "build": "tsup src/index.tsx --format esm,cjs --dts --external react", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", + "dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react" + }, + "dependencies": {}, + "devDependencies": { + "@acme/eslint-config": "workspace:*", + "@acme/tsconfig": "workspace:*", + "tsup": "8.3.6" + } } diff --git a/examples/with-changesets/packages/acme-tsconfig/package.json b/examples/with-changesets/packages/acme-tsconfig/package.json index fe468e08367e8..087455a32e2bc 100644 --- a/examples/with-changesets/packages/acme-tsconfig/package.json +++ b/examples/with-changesets/packages/acme-tsconfig/package.json @@ -1,9 +1,5 @@ { - "name": "@acme/tsconfig", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@acme/tsconfig", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-changesets/packages/acme-utils/.eslintrc.js b/examples/with-changesets/packages/acme-utils/.eslintrc.js deleted file mode 100644 index c5c153931b69e..0000000000000 --- a/examples/with-changesets/packages/acme-utils/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - root: true, - extends: ["@acme/eslint-config/library.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-changesets/packages/acme-utils/src/index.tsx b/examples/with-changesets/packages/acme-utils/Source/index.tsx similarity index 100% rename from examples/with-changesets/packages/acme-utils/src/index.tsx rename to examples/with-changesets/packages/acme-utils/Source/index.tsx diff --git a/examples/with-changesets/packages/acme-utils/src/toSlug.ts b/examples/with-changesets/packages/acme-utils/Source/toSlug.ts similarity index 100% rename from examples/with-changesets/packages/acme-utils/src/toSlug.ts rename to examples/with-changesets/packages/acme-utils/Source/toSlug.ts diff --git a/examples/with-changesets/packages/acme-utils/src/useIsomorphicLayoutEffect.tsx b/examples/with-changesets/packages/acme-utils/Source/useIsomorphicLayoutEffect.tsx similarity index 100% rename from examples/with-changesets/packages/acme-utils/src/useIsomorphicLayoutEffect.tsx rename to examples/with-changesets/packages/acme-utils/Source/useIsomorphicLayoutEffect.tsx diff --git a/examples/with-changesets/packages/acme-utils/src/usePrevious.tsx b/examples/with-changesets/packages/acme-utils/Source/usePrevious.tsx similarity index 100% rename from examples/with-changesets/packages/acme-utils/src/usePrevious.tsx rename to examples/with-changesets/packages/acme-utils/Source/usePrevious.tsx diff --git a/examples/with-changesets/packages/acme-utils/package.json b/examples/with-changesets/packages/acme-utils/package.json index d84c3ce87152b..55258f47fece8 100644 --- a/examples/with-changesets/packages/acme-utils/package.json +++ b/examples/with-changesets/packages/acme-utils/package.json @@ -1,33 +1,21 @@ { - "name": "@acme/utils", - "version": "0.0.0", - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "sideEffects": false, - "license": "MIT", - "files": [ - "dist/**" - ], - "scripts": { - "build": "tsup src/index.tsx --format esm,cjs --dts --external react", - "dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react", - "lint": "eslint \"src/**/*.ts*\"", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" - }, - "devDependencies": { - "@acme/tsconfig": "workspace:*", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "@acme/eslint-config": "workspace:*", - "tsup": "^8.0.2", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - }, - "publishConfig": { - "access": "public" - } + "name": "@acme/utils", + "sideEffects": false, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist/**" + ], + "scripts": { + "build": "tsup src/index.tsx --format esm,cjs --dts --external react", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", + "dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react" + }, + "dependencies": {}, + "devDependencies": { + "@acme/eslint-config": "workspace:*", + "@acme/tsconfig": "workspace:*", + "tsup": "8.3.6" + } } diff --git a/examples/with-changesets/packages/eslint-config/README.md b/examples/with-changesets/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-changesets/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-changesets/packages/eslint-config/package.json b/examples/with-changesets/packages/eslint-config/package.json index 0bf3ea7b4b14b..2f6fb80d5a364 100644 --- a/examples/with-changesets/packages/eslint-config/package.json +++ b/examples/with-changesets/packages/eslint-config/package.json @@ -1,20 +1,14 @@ { - "name": "@acme/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js", - "react-internal.js" - ], - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.4", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@vercel/style-guide": "^5.2.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-only-warn": "^1.1.0", - "typescript": "5.5.4" - } + "name": "@acme/eslint-config", + "files": [ + "library.js", + "next.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-changesets/pnpm-lock.yaml b/examples/with-changesets/pnpm-lock.yaml deleted file mode 100644 index a6e38724467e7..0000000000000 --- a/examples/with-changesets/pnpm-lock.yaml +++ /dev/null @@ -1,5213 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@changesets/cli': - specifier: ^2.27.1 - version: 2.27.1 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/docs: - dependencies: - '@acme/core': - specifier: workspace:* - version: link:../../packages/acme-core - '@acme/utils': - specifier: workspace:* - version: link:../../packages/acme-utils - next: - specifier: ^14.1.1 - version: 14.1.1(react-dom@18.2.0)(react@18.2.0) - react: - specifier: ^18.2.0 - version: 18.2.0 - react-dom: - specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) - devDependencies: - '@acme/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@acme/tsconfig': - specifier: workspace:* - version: link:../../packages/acme-tsconfig - '@next/eslint-plugin-next': - specifier: ^14.1.1 - version: 14.1.4 - '@types/node': - specifier: ^20.11.24 - version: 20.11.24 - '@types/react': - specifier: ^18.2.61 - version: 18.2.61 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.19 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/acme-core: - dependencies: - react: - specifier: ^18.2.0 - version: 18.2.0 - devDependencies: - '@acme/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@acme/tsconfig': - specifier: workspace:* - version: link:../acme-tsconfig - '@types/react': - specifier: ^18.2.61 - version: 18.2.61 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.19 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - tsup: - specifier: ^8.0.2 - version: 8.0.2(typescript@5.5.4) - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/acme-tsconfig: {} - - packages/acme-utils: - dependencies: - react: - specifier: ^18.2.0 - version: 18.2.0 - devDependencies: - '@acme/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@acme/tsconfig': - specifier: workspace:* - version: link:../acme-tsconfig - '@types/react': - specifier: ^18.2.61 - version: 18.2.61 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.19 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - tsup: - specifier: ^8.0.2 - version: 8.0.2(typescript@5.5.4) - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/eslint-config: - devDependencies: - '@next/eslint-plugin-next': - specifier: ^14.1.4 - version: 14.1.4 - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@vercel/style-guide': - specifier: ^5.2.0 - version: 5.2.0(@next/eslint-plugin-next@14.1.4)(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - eslint-config-turbo: - specifier: ^2.0.0 - version: 2.0.0(eslint@8.57.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - dev: true - - /@ampproject/remapping@2.2.1: - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 - dev: true - - /@babel/code-frame@7.23.5: - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.23.4 - chalk: 2.4.2 - dev: true - - /@babel/compat-data@7.23.3: - resolution: {integrity: sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.23.3: - resolution: {integrity: sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.4 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.3) - '@babel/helpers': 7.23.4 - '@babel/parser': 7.23.4 - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.4 - '@babel/types': 7.23.4 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/eslint-parser@7.23.3(@babel/core@7.23.3)(eslint@8.57.0): - resolution: {integrity: sha512-9bTuNlyx7oSstodm1cR1bECj4fkiknsDa1YniISkJemMY3DGhJNYBECbe6QD/q54mp2J8VO66jW3/7uP//iFCw==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@babel/core': 7.23.3 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.23.4: - resolution: {integrity: sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.4 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.22.15: - resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.23.3 - '@babel/helper-validator-option': 7.22.15 - browserslist: 4.22.1 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.15 - '@babel/types': 7.23.4 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.4 - dev: true - - /@babel/helper-module-imports@7.22.15: - resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.4 - dev: true - - /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.4 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.4 - dev: true - - /@babel/helper-string-parser@7.23.4: - resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.22.15: - resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.23.4: - resolution: {integrity: sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.4 - '@babel/types': 7.23.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.23.4: - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser@7.23.4: - resolution: {integrity: sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.23.4 - dev: true - - /@babel/runtime@7.23.7: - resolution: {integrity: sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - - /@babel/template@7.22.15: - resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/parser': 7.23.4 - '@babel/types': 7.23.4 - dev: true - - /@babel/traverse@7.23.4: - resolution: {integrity: sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.4 - '@babel/types': 7.23.4 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.23.4: - resolution: {integrity: sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - dev: true - - /@changesets/apply-release-plan@7.0.0: - resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/config': 3.0.0 - '@changesets/get-version-range-type': 0.4.0 - '@changesets/git': 3.0.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - detect-indent: 6.1.0 - fs-extra: 7.0.1 - lodash.startcase: 4.4.0 - outdent: 0.5.0 - prettier: 2.8.8 - resolve-from: 5.0.0 - semver: 7.5.4 - dev: true - - /@changesets/assemble-release-plan@6.0.0: - resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - semver: 7.5.4 - dev: true - - /@changesets/changelog-git@0.2.0: - resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} - dependencies: - '@changesets/types': 6.0.0 - dev: true - - /@changesets/cli@2.27.1: - resolution: {integrity: sha512-iJ91xlvRnnrJnELTp4eJJEOPjgpF3NOh4qeQehM6Ugiz9gJPRZ2t+TsXun6E3AMN4hScZKjqVXl0TX+C7AB3ZQ==} - hasBin: true - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/apply-release-plan': 7.0.0 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.0 - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/get-release-plan': 4.0.0 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 - '@changesets/types': 6.0.0 - '@changesets/write': 0.3.0 - '@manypkg/get-packages': 1.1.3 - '@types/semver': 7.5.6 - ansi-colors: 4.1.3 - chalk: 2.4.2 - ci-info: 3.9.0 - enquirer: 2.4.1 - external-editor: 3.1.0 - fs-extra: 7.0.1 - human-id: 1.0.2 - meow: 6.1.1 - outdent: 0.5.0 - p-limit: 2.3.0 - preferred-pm: 3.1.2 - resolve-from: 5.0.0 - semver: 7.5.4 - spawndamnit: 2.0.0 - term-size: 2.2.1 - tty-table: 4.2.3 - dev: true - - /@changesets/config@3.0.0: - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} - dependencies: - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/logger': 0.1.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - micromatch: 4.0.5 - dev: true - - /@changesets/errors@0.2.0: - resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - dependencies: - extendable-error: 0.1.7 - dev: true - - /@changesets/get-dependents-graph@2.0.0: - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} - dependencies: - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - chalk: 2.4.2 - fs-extra: 7.0.1 - semver: 7.5.4 - dev: true - - /@changesets/get-release-plan@4.0.0: - resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/config': 3.0.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - dev: true - - /@changesets/get-version-range-type@0.4.0: - resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - dev: true - - /@changesets/git@3.0.0: - resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - is-subdir: 1.2.0 - micromatch: 4.0.5 - spawndamnit: 2.0.0 - dev: true - - /@changesets/logger@0.1.0: - resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} - dependencies: - chalk: 2.4.2 - dev: true - - /@changesets/parse@0.4.0: - resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} - dependencies: - '@changesets/types': 6.0.0 - js-yaml: 3.14.1 - dev: true - - /@changesets/pre@2.0.0: - resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - dev: true - - /@changesets/read@0.6.0: - resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/parse': 0.4.0 - '@changesets/types': 6.0.0 - chalk: 2.4.2 - fs-extra: 7.0.1 - p-filter: 2.1.0 - dev: true - - /@changesets/types@4.1.0: - resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - dev: true - - /@changesets/types@6.0.0: - resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - dev: true - - /@changesets/write@0.3.0: - resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/types': 6.0.0 - fs-extra: 7.0.1 - human-id: 1.0.2 - prettier: 2.8.8 - dev: true - - /@esbuild/android-arm64@0.19.7: - resolution: {integrity: sha512-YEDcw5IT7hW3sFKZBkCAQaOCJQLONVcD4bOyTXMZz5fr66pTHnAet46XAtbXAkJRfIn2YVhdC6R9g4xa27jQ1w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.19.7: - resolution: {integrity: sha512-YGSPnndkcLo4PmVl2tKatEn+0mlVMr3yEpOOT0BeMria87PhvoJb5dg5f5Ft9fbCVgtAz4pWMzZVgSEGpDAlww==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.19.7: - resolution: {integrity: sha512-jhINx8DEjz68cChFvM72YzrqfwJuFbfvSxZAk4bebpngGfNNRm+zRl4rtT9oAX6N9b6gBcFaJHFew5Blf6CvUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.19.7: - resolution: {integrity: sha512-dr81gbmWN//3ZnBIm6YNCl4p3pjnabg1/ZVOgz2fJoUO1a3mq9WQ/1iuEluMs7mCL+Zwv7AY5e3g1hjXqQZ9Iw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.19.7: - resolution: {integrity: sha512-Lc0q5HouGlzQEwLkgEKnWcSazqr9l9OdV2HhVasWJzLKeOt0PLhHaUHuzb8s/UIya38DJDoUm74GToZ6Wc7NGQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.19.7: - resolution: {integrity: sha512-+y2YsUr0CxDFF7GWiegWjGtTUF6gac2zFasfFkRJPkMAuMy9O7+2EH550VlqVdpEEchWMynkdhC9ZjtnMiHImQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.19.7: - resolution: {integrity: sha512-CdXOxIbIzPJmJhrpmJTLx+o35NoiKBIgOvmvT+jeSadYiWJn0vFKsl+0bSG/5lwjNHoIDEyMYc/GAPR9jxusTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.19.7: - resolution: {integrity: sha512-inHqdOVCkUhHNvuQPT1oCB7cWz9qQ/Cz46xmVe0b7UXcuIJU3166aqSunsqkgSGMtUCWOZw3+KMwI6otINuC9g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.19.7: - resolution: {integrity: sha512-Y+SCmWxsJOdQtjcBxoacn/pGW9HDZpwsoof0ttL+2vGcHokFlfqV666JpfLCSP2xLxFpF1lj7T3Ox3sr95YXww==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.19.7: - resolution: {integrity: sha512-2BbiL7nLS5ZO96bxTQkdO0euGZIUQEUXMTrqLxKUmk/Y5pmrWU84f+CMJpM8+EHaBPfFSPnomEaQiG/+Gmh61g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.19.7: - resolution: {integrity: sha512-BVFQla72KXv3yyTFCQXF7MORvpTo4uTA8FVFgmwVrqbB/4DsBFWilUm1i2Oq6zN36DOZKSVUTb16jbjedhfSHw==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.19.7: - resolution: {integrity: sha512-DzAYckIaK+pS31Q/rGpvUKu7M+5/t+jI+cdleDgUwbU7KdG2eC3SUbZHlo6Q4P1CfVKZ1lUERRFP8+q0ob9i2w==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.19.7: - resolution: {integrity: sha512-JQ1p0SmUteNdUaaiRtyS59GkkfTW0Edo+e0O2sihnY4FoZLz5glpWUQEKMSzMhA430ctkylkS7+vn8ziuhUugQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.19.7: - resolution: {integrity: sha512-xGwVJ7eGhkprY/nB7L7MXysHduqjpzUl40+XoYDGC4UPLbnG+gsyS1wQPJ9lFPcxYAaDXbdRXd1ACs9AE9lxuw==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.19.7: - resolution: {integrity: sha512-U8Rhki5PVU0L0nvk+E8FjkV8r4Lh4hVEb9duR6Zl21eIEYEwXz8RScj4LZWA2i3V70V4UHVgiqMpszXvG0Yqhg==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.19.7: - resolution: {integrity: sha512-ZYZopyLhm4mcoZXjFt25itRlocKlcazDVkB4AhioiL9hOWhDldU9n38g62fhOI4Pth6vp+Mrd5rFKxD0/S+7aQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.19.7: - resolution: {integrity: sha512-/yfjlsYmT1O3cum3J6cmGG16Fd5tqKMcg5D+sBYLaOQExheAJhqr8xOAEIuLo8JYkevmjM5zFD9rVs3VBcsjtQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.19.7: - resolution: {integrity: sha512-MYDFyV0EW1cTP46IgUJ38OnEY5TaXxjoDmwiTXPjezahQgZd+j3T55Ht8/Q9YXBM0+T9HJygrSRGV5QNF/YVDQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.19.7: - resolution: {integrity: sha512-JcPvgzf2NN/y6X3UUSqP6jSS06V0DZAV/8q0PjsZyGSXsIGcG110XsdmuWiHM+pno7/mJF6fjH5/vhUz/vA9fw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.19.7: - resolution: {integrity: sha512-ZA0KSYti5w5toax5FpmfcAgu3ZNJxYSRm0AW/Dao5up0YV1hDVof1NvwLomjEN+3/GMtaWDI+CIyJOMTRSTdMw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.19.7: - resolution: {integrity: sha512-CTOnijBKc5Jpk6/W9hQMMvJnsSYRYgveN6O75DTACCY18RA2nqka8dTZR+x/JqXCRiKk84+5+bRKXUSbbwsS0A==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.19.7: - resolution: {integrity: sha512-gRaP2sk6hc98N734luX4VpF318l3w+ofrtTu9j5L8EQXF+FzQKV6alCOHMVoJJHvVK/mGbwBXfOL1HETQu9IGQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.2: - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@jridgewell/gen-mapping@0.3.3: - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.20 - dev: true - - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.20: - resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@manypkg/find-root@1.1.0: - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} - dependencies: - '@babel/runtime': 7.23.7 - '@types/node': 12.20.55 - find-up: 4.1.0 - fs-extra: 8.1.0 - dev: true - - /@manypkg/get-packages@1.1.3: - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - dependencies: - '@babel/runtime': 7.23.7 - '@changesets/types': 4.1.0 - '@manypkg/find-root': 1.1.0 - fs-extra: 8.1.0 - globby: 11.1.0 - read-yaml-file: 1.1.0 - dev: true - - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true - - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true - - /@next/env@14.1.1: - resolution: {integrity: sha512-7CnQyD5G8shHxQIIg3c7/pSeYFeMhsNbpU/bmvH7ZnDql7mNRgg8O2JZrhrc/soFnfBnKP4/xXNiiSIPn2w8gA==} - dev: false - - /@next/eslint-plugin-next@14.1.4: - resolution: {integrity: sha512-n4zYNLSyCo0Ln5b7qxqQeQ34OZKXwgbdcx6kmkQbywr+0k6M3Vinft0T72R6CDAcDrne2IAgSud4uWCzFgc5HA==} - dependencies: - glob: 10.3.10 - dev: true - - /@next/swc-darwin-arm64@14.1.1: - resolution: {integrity: sha512-yDjSFKQKTIjyT7cFv+DqQfW5jsD+tVxXTckSe1KIouKk75t1qZmj/mV3wzdmFb0XHVGtyRjDMulfVG8uCKemOQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64@14.1.1: - resolution: {integrity: sha512-KCQmBL0CmFmN8D64FHIZVD9I4ugQsDBBEJKiblXGgwn7wBCSe8N4Dx47sdzl4JAg39IkSN5NNrr8AniXLMb3aw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu@14.1.1: - resolution: {integrity: sha512-YDQfbWyW0JMKhJf/T4eyFr4b3tceTorQ5w2n7I0mNVTFOvu6CGEzfwT3RSAQGTi/FFMTFcuspPec/7dFHuP7Eg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl@14.1.1: - resolution: {integrity: sha512-fiuN/OG6sNGRN/bRFxRvV5LyzLB8gaL8cbDH5o3mEiVwfcMzyE5T//ilMmaTrnA8HLMS6hoz4cHOu6Qcp9vxgQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu@14.1.1: - resolution: {integrity: sha512-rv6AAdEXoezjbdfp3ouMuVqeLjE1Bin0AuE6qxE6V9g3Giz5/R3xpocHoAi7CufRR+lnkuUjRBn05SYJ83oKNQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl@14.1.1: - resolution: {integrity: sha512-YAZLGsaNeChSrpz/G7MxO3TIBLaMN8QWMr3X8bt6rCvKovwU7GqQlDu99WdvF33kI8ZahvcdbFsy4jAFzFX7og==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc@14.1.1: - resolution: {integrity: sha512-1L4mUYPBMvVDMZg1inUYyPvFSduot0g73hgfD9CODgbr4xiTYe0VOMTZzaRqYJYBA9mana0x4eaAaypmWo1r5A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-ia32-msvc@14.1.1: - resolution: {integrity: sha512-jvIE9tsuj9vpbbXlR5YxrghRfMuG0Qm/nZ/1KDHc+y6FpnZ/apsgh+G6t15vefU0zp3WSpTMIdXRUsNl/7RSuw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc@14.1.1: - resolution: {integrity: sha512-S6K6EHDU5+1KrBDLko7/c1MNy/Ya73pIAmvKeFwsF4RmBFJSO7/7YeD4FnZ4iBdzE69PpQ4sOMU9ORKeNuxe8A==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@pkgr/utils@2.3.1: - resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dependencies: - cross-spawn: 7.0.3 - is-glob: 4.0.3 - open: 8.4.0 - picocolors: 1.0.0 - tiny-glob: 0.2.9 - tslib: 2.6.2 - dev: true - - /@rollup/rollup-android-arm-eabi@4.5.1: - resolution: {integrity: sha512-YaN43wTyEBaMqLDYeze+gQ4ZrW5RbTEGtT5o1GVDkhpdNcsLTnLRcLccvwy3E9wiDKWg9RIhuoy3JQKDRBfaZA==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.5.1: - resolution: {integrity: sha512-n1bX+LCGlQVuPlCofO0zOKe1b2XkFozAVRoczT+yxWZPGnkEAKTTYVOGZz8N4sKuBnKMxDbfhUsB1uwYdup/sw==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.5.1: - resolution: {integrity: sha512-QqJBumdvfBqBBmyGHlKxje+iowZwrHna7pokj/Go3dV1PJekSKfmjKrjKQ/e6ESTGhkfPNLq3VXdYLAc+UtAQw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.5.1: - resolution: {integrity: sha512-RrkDNkR/P5AEQSPkxQPmd2ri8WTjSl0RYmuFOiEABkEY/FSg0a4riihWQGKDJ4LnV9gigWZlTMx2DtFGzUrYQw==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.5.1: - resolution: {integrity: sha512-ZFPxvUZmE+fkB/8D9y/SWl/XaDzNSaxd1TJUSE27XAKlRpQ2VNce/86bGd9mEUgL3qrvjJ9XTGwoX0BrJkYK/A==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.5.1: - resolution: {integrity: sha512-FEuAjzVIld5WVhu+M2OewLmjmbXWd3q7Zcx+Rwy4QObQCqfblriDMMS7p7+pwgjZoo9BLkP3wa9uglQXzsB9ww==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.5.1: - resolution: {integrity: sha512-f5Gs8WQixqGRtI0Iq/cMqvFYmgFzMinuJO24KRfnv7Ohi/HQclwrBCYkzQu1XfLEEt3DZyvveq9HWo4bLJf1Lw==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.5.1: - resolution: {integrity: sha512-CWPkPGrFfN2vj3mw+S7A/4ZaU3rTV7AkXUr08W9lNP+UzOvKLVf34tWCqrKrfwQ0NTk5GFqUr2XGpeR2p6R4gw==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.5.1: - resolution: {integrity: sha512-ZRETMFA0uVukUC9u31Ed1nx++29073goCxZtmZARwk5aF/ltuENaeTtRVsSQzFlzdd4J6L3qUm+EW8cbGt0CKQ==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.5.1: - resolution: {integrity: sha512-ihqfNJNb2XtoZMSCPeoo0cYMgU04ksyFIoOw5S0JUVbOhafLot+KD82vpKXOurE2+9o/awrqIxku9MRR9hozHQ==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.5.1: - resolution: {integrity: sha512-zK9MRpC8946lQ9ypFn4gLpdwr5a01aQ/odiIJeL9EbgZDMgbZjjT/XzTqJvDfTmnE1kHdbG20sAeNlpc91/wbg==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.5.1: - resolution: {integrity: sha512-5I3Nz4Sb9TYOtkRwlH0ow+BhMH2vnh38tZ4J4mggE48M/YyJyp/0sPSxhw1UeS1+oBgQ8q7maFtSeKpeRJu41Q==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rushstack/eslint-patch@1.5.1: - resolution: {integrity: sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==} - dev: true - - /@swc/helpers@0.5.2: - resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} - dependencies: - tslib: 2.6.2 - dev: false - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/minimist@1.2.5: - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - dev: true - - /@types/node@12.20.55: - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - dev: true - - /@types/node@20.11.24: - resolution: {integrity: sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: true - - /@types/prop-types@15.7.5: - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} - dev: true - - /@types/react-dom@18.2.19: - resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==} - dependencies: - '@types/react': 18.2.61 - dev: true - - /@types/react@18.2.61: - resolution: {integrity: sha512-NURTN0qNnJa7O/k4XUkEW2yfygA+NxS0V5h1+kp9jPwhzZy95q3ADoGMP0+JypMhrZBTTgjKAUlTctde1zzeQA==} - dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.2 - csstype: 3.1.1 - dev: true - - /@types/scheduler@0.16.2: - resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} - dev: true - - /@types/semver@7.5.6: - resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} - dev: true - - /@typescript-eslint/eslint-plugin@6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/type-utils': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/type-utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@6.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - - /@typescript-eslint/scope-manager@6.17.0: - resolution: {integrity: sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 - dev: true - - /@typescript-eslint/scope-manager@7.1.0: - resolution: {integrity: sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - dev: true - - /@typescript-eslint/type-utils@6.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/type-utils@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@6.17.0: - resolution: {integrity: sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/types@7.1.0: - resolution: {integrity: sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.4): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.5.4 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@6.17.0(typescript@5.5.4): - resolution: {integrity: sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@7.1.0(typescript@5.5.4): - resolution: {integrity: sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@6.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@6.17.0: - resolution: {integrity: sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.17.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.1.0: - resolution: {integrity: sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 7.1.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@vercel/style-guide@5.2.0(@next/eslint-plugin-next@14.1.4)(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4): - resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} - engines: {node: '>=16'} - peerDependencies: - '@next/eslint-plugin-next': '>=12.3.0 <15' - eslint: '>=8.48.0 <9' - prettier: '>=3.0.0 <4' - typescript: '>=4.8.0 <6' - peerDependenciesMeta: - '@next/eslint-plugin-next': - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - dependencies: - '@babel/core': 7.23.3 - '@babel/eslint-parser': 7.23.3(@babel/core@7.23.3)(eslint@8.57.0) - '@next/eslint-plugin-next': 14.1.4 - '@rushstack/eslint-patch': 1.5.1 - '@typescript-eslint/eslint-plugin': 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) - eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.0) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.17.0)(eslint-plugin-import@2.29.0)(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0) - eslint-plugin-jest: 27.6.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.6.0)(eslint@8.57.0) - eslint-plugin-react: 7.33.2(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) - eslint-plugin-testing-library: 6.2.0(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) - prettier: 3.2.5 - prettier-plugin-packagejson: 2.4.6(prettier@3.2.5) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - dependencies: - dequal: 2.0.3 - dev: true - - /array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} - dependencies: - call-bind: 1.0.5 - is-array-buffer: 3.0.2 - dev: true - - /array-includes@3.1.7: - resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - is-string: 1.0.7 - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array.prototype.findlastindex@1.2.3: - resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.2 - dev: true - - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.tosorted@1.1.1: - resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.2 - dev: true - - /arraybuffer.prototype.slice@1.0.2: - resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - is-array-buffer: 3.0.2 - is-shared-array-buffer: 1.0.2 - dev: true - - /arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true - - /ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - dev: true - - /asynciterator.prototype@1.0.0: - resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} - dependencies: - has-symbols: 1.0.3 - dev: true - - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: true - - /axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - dev: true - - /axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} - dependencies: - dequal: 2.0.3 - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /better-path-resolve@1.0.0: - resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} - engines: {node: '>=4'} - dependencies: - is-windows: 1.0.2 - dev: true - - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /breakword@1.0.6: - resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} - dependencies: - wcwidth: 1.0.1 - dev: true - - /browserslist@4.22.1: - resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001593 - electron-to-chromium: 1.4.591 - node-releases: 2.0.13 - update-browserslist-db: 1.0.13(browserslist@4.22.1) - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /bundle-require@4.0.2(esbuild@0.19.7): - resolution: {integrity: sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - peerDependencies: - esbuild: '>=0.17' - dependencies: - esbuild: 0.19.7 - load-tsconfig: 0.2.5 - dev: true - - /busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - dev: false - - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true - - /call-bind@1.0.5: - resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} - dependencies: - function-bind: 1.1.2 - get-intrinsic: 1.2.2 - set-function-length: 1.1.1 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - dev: true - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /caniuse-lite@1.0.30001593: - resolution: {integrity: sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==} - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true - - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - - /cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cross-spawn@5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} - dependencies: - lru-cache: 4.1.5 - shebang-command: 1.2.0 - which: 1.3.1 - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /csstype@3.1.1: - resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} - dev: true - - /csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - dev: true - - /csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - dev: true - - /csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - dev: true - - /csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} - dependencies: - csv-generate: 3.4.3 - csv-parse: 4.16.3 - csv-stringify: 5.6.5 - stream-transform: 2.1.3 - dev: true - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - dev: true - - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: true - - /define-data-property@1.1.1: - resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.2 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 - dev: true - - /define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - dev: true - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.1 - has-property-descriptors: 1.0.1 - object-keys: 1.1.1 - dev: true - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: true - - /detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - dev: true - - /detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - dev: true - - /detect-newline@4.0.1: - resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /electron-to-chromium@1.4.591: - resolution: {integrity: sha512-vLv/P7wwAPKQoY+CVMyyI6rsTp+A14KGtPXx92oz1FY41AAqa9l6Wkizcixg0LDuJgyeo8xgNN9+9hsnGp66UA==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /enhanced-resolve@5.12.0: - resolution: {integrity: sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-abstract@1.22.3: - resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - arraybuffer.prototype.slice: 1.0.2 - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 - es-set-tostringtag: 2.0.2 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.2 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - internal-slot: 1.0.6 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.12 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.1 - safe-array-concat: 1.0.1 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.8 - string.prototype.trimend: 1.0.7 - string.prototype.trimstart: 1.0.7 - typed-array-buffer: 1.0.0 - typed-array-byte-length: 1.0.0 - typed-array-byte-offset: 1.0.0 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.13 - dev: true - - /es-iterator-helpers@1.0.15: - resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} - dependencies: - asynciterator.prototype: 1.0.0 - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-set-tostringtag: 2.0.2 - function-bind: 1.1.2 - get-intrinsic: 1.2.2 - globalthis: 1.0.3 - has-property-descriptors: 1.0.1 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.6 - iterator.prototype: 1.1.2 - safe-array-concat: 1.0.1 - dev: true - - /es-set-tostringtag@2.0.2: - resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.2 - has-tostringtag: 1.0.0 - hasown: 2.0.0 - dev: true - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.0 - dev: true - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /esbuild@0.19.7: - resolution: {integrity: sha512-6brbTZVqxhqgbpqBR5MzErImcpA0SQdoKOkcWK/U30HtQxnokIpG3TX2r0IJqbFUzqLjhU/zC1S5ndgakObVCQ==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.19.7 - '@esbuild/android-arm64': 0.19.7 - '@esbuild/android-x64': 0.19.7 - '@esbuild/darwin-arm64': 0.19.7 - '@esbuild/darwin-x64': 0.19.7 - '@esbuild/freebsd-arm64': 0.19.7 - '@esbuild/freebsd-x64': 0.19.7 - '@esbuild/linux-arm': 0.19.7 - '@esbuild/linux-arm64': 0.19.7 - '@esbuild/linux-ia32': 0.19.7 - '@esbuild/linux-loong64': 0.19.7 - '@esbuild/linux-mips64el': 0.19.7 - '@esbuild/linux-ppc64': 0.19.7 - '@esbuild/linux-riscv64': 0.19.7 - '@esbuild/linux-s390x': 0.19.7 - '@esbuild/linux-x64': 0.19.7 - '@esbuild/netbsd-x64': 0.19.7 - '@esbuild/openbsd-x64': 0.19.7 - '@esbuild/sunos-x64': 0.19.7 - '@esbuild/win32-arm64': 0.19.7 - '@esbuild/win32-ia32': 0.19.7 - '@esbuild/win32-x64': 0.19.7 - dev: true - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-config-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-turbo: 2.0.0(eslint@8.57.0) - dev: true - - /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.0): - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - dependencies: - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0) - dev: true - - /eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.17.0)(eslint-plugin-import@2.29.0)(eslint@8.57.0): - resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.4 - enhanced-resolve: 5.12.0 - eslint: 8.57.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.7.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.17.0)(eslint-plugin-import@2.29.0)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils@2.8.0(@typescript-eslint/parser@7.1.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): - resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} - engines: {node: '>=6.5.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - escape-string-regexp: 1.0.5 - eslint: 8.57.0 - ignore: 5.3.1 - dev: true - - /eslint-plugin-import@2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0): - resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.7 - array.prototype.findlastindex: 1.2.3 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.0 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.7 - object.groupby: 1.0.1 - object.values: 1.1.7 - semver: 6.3.1 - tsconfig-paths: 3.14.2 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@27.6.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.23.7 - aria-query: 5.3.0 - array-includes: 3.1.7 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.15 - eslint: 8.57.0 - hasown: 2.0.0 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.entries: 1.1.7 - object.fromentries: 2.0.7 - dev: true - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.6.0)(eslint@8.57.0): - resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} - peerDependencies: - eslint: '>=7' - eslint-plugin-jest: '>=25' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - dependencies: - eslint: 8.57.0 - eslint-plugin-jest: 27.6.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - dev: true - - /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react@7.33.2(eslint@8.57.0): - resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.7 - array.prototype.flatmap: 1.3.2 - array.prototype.tosorted: 1.1.1 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.15 - eslint: 8.57.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.7 - object.fromentries: 2.0.7 - object.hasown: 1.1.2 - object.values: 1.1.7 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.8 - dev: true - - /eslint-plugin-testing-library@6.2.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true - - /eslint-plugin-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.0 - dev: true - - /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.44.0' - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - ci-info: 3.9.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.5.4 - strip-indent: 3.0.0 - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /extendable-error@0.1.7: - resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} - dev: true - - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} - dependencies: - micromatch: 4.0.5 - pkg-dir: 4.2.0 - dev: true - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-intrinsic@1.2.2: - resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} - dependencies: - function-bind: 1.1.2 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - dev: true - - /get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - dev: true - - /get-tsconfig@4.7.2: - resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true - - /git-hooks-list@3.1.0: - resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.2 - dev: true - - /glob@7.1.6: - resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - dev: true - - /globalyzer@0.1.0: - resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /globrex@0.1.2: - resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.2 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors@1.0.1: - resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} - dependencies: - get-intrinsic: 1.2.2 - dev: true - - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /human-id@1.0.2: - resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /internal-slot@1.0.6: - resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.2 - hasown: 2.0.0 - side-channel: 1.0.4 - dev: true - - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-typed-array: 1.1.12 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - has-tostringtag: 1.0.0 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.0 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.5 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-map@2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} - dev: true - - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: true - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - has-tostringtag: 1.0.0 - dev: true - - /is-set@2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - dev: true - - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.5 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-subdir@1.2.0: - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} - engines: {node: '>=4'} - dependencies: - better-path-resolve: 1.0.0 - dev: true - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array@1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.13 - dev: true - - /is-weakmap@2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} - dev: true - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.5 - dev: true - - /is-weakset@2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} - dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - dev: true - - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.2 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.4 - set-function-name: 2.0.1 - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - - /joycon@3.1.1: - resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} - engines: {node: '>=10'} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.7 - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.7 - array.prototype.flat: 1.3.2 - object.assign: 4.1.5 - object.values: 1.1.7 - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: true - - /language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} - dev: true - - /language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - dependencies: - language-subtag-registry: 0.3.22 - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} - engines: {node: '>=14'} - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /load-tsconfig@0.2.5: - resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} - dependencies: - graceful-fs: 4.2.11 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash.sortby@4.7.0: - resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - dev: true - - /lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} - dependencies: - pseudomap: 1.0.2 - yallist: 2.1.2 - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true - - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true - - /meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} - dependencies: - '@types/minimist': 1.2.5 - camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 2.5.0 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.13.1 - yargs-parser: 18.1.3 - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - dev: true - - /minimist@1.2.7: - resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} - dev: true - - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /mixme@0.5.10: - resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} - engines: {node: '>= 8.0.0'} - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: false - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /next@14.1.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-McrGJqlGSHeaz2yTRPkEucxQKe5Zq7uPwyeHNmJaZNY4wx9E9QdxmTp310agFRoMuIYgQrCrT3petg13fSVOww==} - engines: {node: '>=18.17.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - sass: - optional: true - dependencies: - '@next/env': 14.1.1 - '@swc/helpers': 0.5.2 - busboy: 1.6.0 - caniuse-lite: 1.0.30001593 - graceful-fs: 4.2.11 - postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(react@18.2.0) - optionalDependencies: - '@next/swc-darwin-arm64': 14.1.1 - '@next/swc-darwin-x64': 14.1.1 - '@next/swc-linux-arm64-gnu': 14.1.1 - '@next/swc-linux-arm64-musl': 14.1.1 - '@next/swc-linux-x64-gnu': 14.1.1 - '@next/swc-linux-x64-musl': 14.1.1 - '@next/swc-win32-arm64-msvc': 14.1.1 - '@next/swc-win32-ia32-msvc': 14.1.1 - '@next/swc-win32-x64-msvc': 14.1.1 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - - /node-releases@2.0.13: - resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} - dev: true - - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.7: - resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /object.fromentries@2.0.7: - resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /object.groupby@1.0.1: - resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - dev: true - - /object.hasown@1.1.2: - resolution: {integrity: sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /object.values@1.1.7: - resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /open@8.4.0: - resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} - engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /outdent@0.5.0: - resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - dev: true - - /p-filter@2.1.0: - resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} - engines: {node: '>=8'} - dependencies: - p-map: 2.1.0 - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-map@2.1.0: - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} - engines: {node: '>=6'} - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.23.5 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true - - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - dev: true - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - dependencies: - lilconfig: 3.0.0 - yaml: 2.3.4 - dev: true - - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: false - - /preferred-pm@3.1.2: - resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==} - engines: {node: '>=10'} - dependencies: - find-up: 5.0.0 - find-yarn-workspace-root2: 1.2.16 - path-exists: 4.0.0 - which-pm: 2.0.0 - dev: true - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-plugin-packagejson@2.4.6(prettier@3.2.5): - resolution: {integrity: sha512-5JGfzkJRL0DLNyhwmiAV9mV0hZLHDwddFCs2lc9CNxOChpoWUQVe8K4qTMktmevmDlMpok2uT10nvHUyU59sNw==} - peerDependencies: - prettier: '>= 1.16.0' - peerDependenciesMeta: - prettier: - optional: true - dependencies: - prettier: 3.2.5 - sort-package-json: 2.6.0 - synckit: 0.8.5 - dev: true - - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - dev: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true - - /react-dom@18.2.0(react@18.2.0): - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} - peerDependencies: - react: ^18.2.0 - dependencies: - loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 - dev: false - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - dev: false - - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /read-yaml-file@1.1.0: - resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} - engines: {node: '>=6'} - dependencies: - graceful-fs: 4.2.11 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - dev: true - - /reflect.getprototypeof@1.0.4: - resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - globalthis: 1.0.3 - which-builtin-type: 1.1.3 - dev: true - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true - - /regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - hasBin: true - dev: true - - /regexp.prototype.flags@1.5.1: - resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - set-function-name: 2.0.1 - dev: true - - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rollup@4.5.1: - resolution: {integrity: sha512-0EQribZoPKpb5z1NW/QYm3XSR//Xr8BeEXU49Lc/mQmpmVVG5jPUVrpc2iptup/0WMrY9mzas0fxH+TjYvG2CA==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.5.1 - '@rollup/rollup-android-arm64': 4.5.1 - '@rollup/rollup-darwin-arm64': 4.5.1 - '@rollup/rollup-darwin-x64': 4.5.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.5.1 - '@rollup/rollup-linux-arm64-gnu': 4.5.1 - '@rollup/rollup-linux-arm64-musl': 4.5.1 - '@rollup/rollup-linux-x64-gnu': 4.5.1 - '@rollup/rollup-linux-x64-musl': 4.5.1 - '@rollup/rollup-win32-arm64-msvc': 4.5.1 - '@rollup/rollup-win32-ia32-msvc': 4.5.1 - '@rollup/rollup-win32-x64-msvc': 4.5.1 - fsevents: 2.3.3 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /safe-array-concat@1.0.1: - resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-regex: 1.1.4 - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true - - /scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - - /set-function-length@1.1.1: - resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.1 - get-intrinsic: 1.2.2 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 - dev: true - - /set-function-name@2.0.1: - resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.1 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.1 - dev: true - - /shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - dependencies: - shebang-regex: 1.0.0 - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - object-inspect: 1.13.1 - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true - dependencies: - array.prototype.flat: 1.3.2 - breakword: 1.0.6 - grapheme-splitter: 1.0.4 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 15.4.1 - dev: true - - /sort-object-keys@1.1.3: - resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - dev: true - - /sort-package-json@2.6.0: - resolution: {integrity: sha512-XSQ+lY9bAYA8ZsoChcEoPlgcSMaheziEp1beox1JVxy1SV4F2jSq9+h2rJ+3mC/Dhu9Ius1DLnInD5AWcsDXZw==} - hasBin: true - dependencies: - detect-indent: 7.0.1 - detect-newline: 4.0.1 - get-stdin: 9.0.0 - git-hooks-list: 3.1.0 - globby: 13.2.2 - is-plain-obj: 4.1.0 - sort-object-keys: 1.1.3 - dev: true - - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: false - - /source-map@0.8.0-beta.0: - resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} - engines: {node: '>= 8'} - dependencies: - whatwg-url: 7.1.0 - dev: true - - /spawndamnit@2.0.0: - resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} - dependencies: - cross-spawn: 5.1.0 - signal-exit: 3.0.7 - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.16 - dev: true - - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.16 - dev: true - - /spdx-license-ids@3.0.16: - resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} - dev: true - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} - dependencies: - mixme: 0.5.10 - dev: true - - /streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - dev: false - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string.prototype.matchall@4.0.8: - resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - has-symbols: 1.0.3 - internal-slot: 1.0.6 - regexp.prototype.flags: 1.5.1 - side-channel: 1.0.4 - dev: true - - /string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /styled-jsx@5.1.1(react@18.2.0): - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - client-only: 0.0.1 - react: 18.2.0 - dev: false - - /sucrase@3.34.0: - resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} - engines: {node: '>=8'} - hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - commander: 4.1.1 - glob: 7.1.6 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /synckit@0.8.5: - resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/utils': 2.3.1 - tslib: 2.6.2 - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /term-size@2.2.1: - resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} - engines: {node: '>=8'} - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: true - - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: true - - /tiny-glob@0.2.9: - resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} - dependencies: - globalyzer: 0.1.0 - globrex: 0.1.2 - dev: true - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /tr46@1.0.1: - resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - dependencies: - punycode: 2.3.1 - dev: true - - /tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - dev: true - - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true - - /ts-api-utils@1.0.3(typescript@5.5.4): - resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} - engines: {node: '>=16.13.0'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: true - - /tsconfig-paths@3.14.2: - resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.7 - strip-bom: 3.0.0 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - /tsup@8.0.2(typescript@5.5.4): - resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==} - engines: {node: '>=18'} - hasBin: true - peerDependencies: - '@microsoft/api-extractor': ^7.36.0 - '@swc/core': ^1 - postcss: ^8.4.12 - typescript: '>=4.5.0' - peerDependenciesMeta: - '@microsoft/api-extractor': - optional: true - '@swc/core': - optional: true - postcss: - optional: true - typescript: - optional: true - dependencies: - bundle-require: 4.0.2(esbuild@0.19.7) - cac: 6.7.14 - chokidar: 3.5.3 - debug: 4.3.4 - esbuild: 0.19.7 - execa: 5.1.1 - globby: 11.1.0 - joycon: 3.1.1 - postcss-load-config: 4.0.2 - resolve-from: 5.0.0 - rollup: 4.5.1 - source-map: 0.8.0-beta.0 - sucrase: 3.34.0 - tree-kill: 1.2.2 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - ts-node - dev: true - - /tsutils@3.21.0(typescript@5.5.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.4 - dev: true - - /tty-table@4.2.3: - resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} - engines: {node: '>=8.0.0'} - hasBin: true - dependencies: - chalk: 4.1.2 - csv: 5.5.3 - kleur: 4.1.5 - smartwrap: 2.0.2 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 17.7.2 - dev: true - - /turbo-darwin-64@2.0.3: - resolution: {integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: {integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: {integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: {integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: {integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: {integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: {integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /typed-array-buffer@1.0.0: - resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-typed-array: 1.1.12 - dev: true - - /typed-array-byte-length@1.0.0: - resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 - dev: true - - /typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 - dev: true - - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} - dependencies: - call-bind: 1.0.5 - for-each: 0.3.3 - is-typed-array: 1.1.12 - dev: true - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.5 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /update-browserslist-db@1.0.13(browserslist@4.22.1): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.22.1 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - - /webidl-conversions@4.0.2: - resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - dev: true - - /whatwg-url@7.1.0: - resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - dev: true - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.0 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.13 - dev: true - - /which-collection@1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} - dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 - dev: true - - /which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - dev: true - - /which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} - dependencies: - load-yaml-file: 0.2.0 - path-exists: 4.0.0 - dev: true - - /which-typed-array@1.1.13: - resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: true - - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - dev: true - - /yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - dev: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 18.1.3 - dev: true - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - 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.8 - yargs-parser: 21.1.1 - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true diff --git a/examples/with-docker/README.md b/examples/with-docker/README.md deleted file mode 100644 index 7e95361cac609..0000000000000 --- a/examples/with-docker/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# Turborepo Docker starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-docker -``` - -## What's inside? - -This Turborepo includes the following: - -### Apps and Packages - -- `web`: a [Next.js](https://nextjs.org/) app -- `api`: an [Express](https://expressjs.com/) server -- `@repo/ui`: a React component library -- `@repo/logger`: Isomorphic logger (a small wrapper around console.log) -- `@repo/eslint-config`: ESLint presets -- `@repo/typescript-config`: tsconfig.json's used throughout the monorepo -- `@repo/jest-presets`: Jest configurations - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Docker - -This repo is configured to be built with Docker, and Docker compose. To build all apps in this repo: - -``` -# Install dependencies -yarn install - -# Create a network, which allows containers to communicate -# with each other, by using their container name as a hostname -docker network create app_network - -# Build prod using new BuildKit engine -COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.yml build - -# Start prod in detached mode -docker-compose -f docker-compose.yml up -d -``` - -Open http://localhost:3000. - -To shutdown all running containers: - -``` -# Stop all running containers -docker kill $(docker ps -q) && docker rm $(docker ps -a -q) -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -This example includes optional remote caching. In the Dockerfiles of the apps, uncomment the build arguments for `TURBO_TEAM` and `TURBO_TOKEN`. Then, pass these build arguments to your Docker build. - -You can test this behavior using a command like: - -`docker build -f apps/web/Dockerfile . --build-arg TURBO_TEAM=“your-team-name†--build-arg TURBO_TOKEN=“your-token“ --no-cache` - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Jest](https://jestjs.io) test runner for all things JavaScript -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/with-docker/apps/api/.eslintrc.js b/examples/with-docker/apps/api/.eslintrc.js deleted file mode 100644 index 5ae3cda27b390..0000000000000 --- a/examples/with-docker/apps/api/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/server.js"], -}; diff --git a/examples/with-docker/apps/api/src/index.ts b/examples/with-docker/apps/api/Source/index.ts similarity index 100% rename from examples/with-docker/apps/api/src/index.ts rename to examples/with-docker/apps/api/Source/index.ts diff --git a/examples/with-docker/apps/api/src/server.ts b/examples/with-docker/apps/api/Source/server.ts similarity index 100% rename from examples/with-docker/apps/api/src/server.ts rename to examples/with-docker/apps/api/Source/server.ts diff --git a/examples/with-docker/apps/api/package.json b/examples/with-docker/apps/api/package.json index f2a595d4d3a48..ee8c1a10eda62 100644 --- a/examples/with-docker/apps/api/package.json +++ b/examples/with-docker/apps/api/package.json @@ -1,42 +1,32 @@ { - "name": "api", - "version": "0.0.0", - "private": true, - "scripts": { - "build": "tsc", - "clean": "rm -rf dist", - "dev": "nodemon --exec \"node -r esbuild-register ./src/index.ts\" -e .ts", - "lint": "tsc --noEmit && eslint \"src/**/*.ts*\" --max-warnings 0", - "start": "node -r esbuild-register ./src/index.ts", - "test": "jest --detectOpenHandles" - }, - "jest": { - "preset": "@repo/jest-presets/node" - }, - "dependencies": { - "@repo/logger": "*", - "body-parser": "^1.20.2", - "cors": "^2.8.5", - "express": "^4.18.3", - "morgan": "^1.10.0" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@repo/eslint-config": "*", - "@repo/jest-presets": "*", - "@repo/typescript-config": "*", - "@types/body-parser": "^1.19.5", - "@types/cors": "^2.8.17", - "@types/express": "^4.17.21", - "@types/morgan": "^1.9.9", - "@types/node": "^20.11.24", - "@types/supertest": "^6.0.2", - "esbuild": "^0.20.1", - "esbuild-register": "^3.5.0", - "eslint": "^8.57.0", - "jest": "^29.7.0", - "nodemon": "^3.1.0", - "supertest": "^6.3.3", - "typescript": "5.5.4" - } + "name": "api", + "scripts": { + "build": "tsc", + "clean": "rm -rf dist", + "dev": "nodemon --exec \"node -r esbuild-register ./src/index.ts\" -e .ts", + "start": "node -r esbuild-register ./src/index.ts" + }, + "jest": { + "preset": "@repo/jest-presets/node" + }, + "dependencies": { + "@repo/logger": "*", + "body-parser": "1.20.3", + "cors": "2.8.5", + "morgan": "1.10.0" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/jest-presets": "*", + "@repo/typescript-config": "*", + "@types/body-parser": "1.19.5", + "@types/cors": "2.8.17", + "@types/morgan": "1.9.9", + "@types/node": "22.13.1", + "@types/supertest": "6.0.2", + "esbuild": "0.25.0", + "esbuild-register": "3.6.0", + "nodemon": "3.1.9", + "supertest": "7.0.0" + } } diff --git a/examples/with-docker/apps/api/src/__tests__/server.test.ts b/examples/with-docker/apps/api/src/__tests__/server.test.ts deleted file mode 100644 index 55503bd86e8b4..0000000000000 --- a/examples/with-docker/apps/api/src/__tests__/server.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import supertest from "supertest"; -import { describe, it, expect } from "@jest/globals"; -import { createServer } from "../server"; - -describe("server", () => { - it("status check returns 200", async () => { - await supertest(createServer()) - .get("/status") - .expect(200) - .then((res) => { - expect(res.body.ok).toBe(true); - }); - }); - - it("message endpoint says hello", async () => { - await supertest(createServer()) - .get("/message/jared") - .expect(200) - .then((res) => { - expect(res.body.message).toBe("hello jared"); - }); - }); -}); diff --git a/examples/with-docker/apps/web/.eslintrc.js b/examples/with-docker/apps/web/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-docker/apps/web/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-docker/apps/web/README.md b/examples/with-docker/apps/web/README.md deleted file mode 100644 index 4fae62aff6252..0000000000000 --- a/examples/with-docker/apps/web/README.md +++ /dev/null @@ -1,30 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-docker/apps/web/src/app/layout.tsx b/examples/with-docker/apps/web/Source/app/layout.tsx similarity index 100% rename from examples/with-docker/apps/web/src/app/layout.tsx rename to examples/with-docker/apps/web/Source/app/layout.tsx diff --git a/examples/with-docker/apps/web/src/app/page.tsx b/examples/with-docker/apps/web/Source/app/page.tsx similarity index 100% rename from examples/with-docker/apps/web/src/app/page.tsx rename to examples/with-docker/apps/web/Source/app/page.tsx diff --git a/examples/with-docker/apps/web/package.json b/examples/with-docker/apps/web/package.json index ffd2032fe5200..f5ce740cc1204 100644 --- a/examples/with-docker/apps/web/package.json +++ b/examples/with-docker/apps/web/package.json @@ -1,27 +1,17 @@ { - "name": "web", - "version": "0.0.0", - "private": true, - "scripts": { - "build": "next build", - "dev": "next dev", - "lint": "eslint . --max-warnings 0", - "start": "next start" - }, - "dependencies": { - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "@repo/ui": "*" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-docker/package.json b/examples/with-docker/package.json index 741de01fa3313..b4ae77b89be0c 100644 --- a/examples/with-docker/package.json +++ b/examples/with-docker/package.json @@ -1,27 +1,16 @@ { - "name": "with-docker", - "version": "0.0.0", - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build", - "clean": "turbo run clean", - "dev": "turbo run dev", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "lint": "turbo run lint", - "test": "turbo run test" - }, - "dependencies": {}, - "devDependencies": { - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "yarn@1.22.19", - "engines": { - "node": ">=14.0.0", - "npm": ">=7.0.0" - } + "name": "with-docker", + "workspaces": [ + "apps/*", + "packages/*" + ], + "scripts": { + "build": "turbo run build", + "clean": "turbo run clean", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-docker/packages/eslint-config/README.md b/examples/with-docker/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-docker/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-docker/packages/eslint-config/package.json b/examples/with-docker/packages/eslint-config/package.json index a2cae59891d57..f0c9ff14cbd59 100644 --- a/examples/with-docker/packages/eslint-config/package.json +++ b/examples/with-docker/packages/eslint-config/package.json @@ -1,20 +1,15 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js", - "react-internal.js", - "server.js" - ], - "devDependencies": { - "@vercel/style-guide": "^5.2.0", - "eslint-config-turbo": "^2.0.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-only-warn": "^1.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "next.js", + "react-internal.js", + "server.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-docker/packages/jest-presets/node/jest-preset.js b/examples/with-docker/packages/jest-presets/node/jest-preset.js new file mode 100644 index 0000000000000..b6c259304707f --- /dev/null +++ b/examples/with-docker/packages/jest-presets/node/jest-preset.js @@ -0,0 +1,13 @@ +module.exports = { + roots: [""], + transform: { + "^.+\\.tsx?$": "ts-jest", + }, + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: [ + "/test/__fixtures__", + "/node_modules", + "/dist", + ], + preset: "ts-jest", +}; diff --git a/examples/with-docker/packages/jest-presets/package.json b/examples/with-docker/packages/jest-presets/package.json index 6247a847d4a96..a0ff8264f2b79 100644 --- a/examples/with-docker/packages/jest-presets/package.json +++ b/examples/with-docker/packages/jest-presets/package.json @@ -1,13 +1,8 @@ { - "name": "@repo/jest-presets", - "version": "0.0.0", - "private": true, - "license": "MIT", - "files": [ - "node/jest-preset.ts" - ], - "dependencies": { - "jest": "^29.7.0", - "ts-jest": "^29.2.5" - } + "name": "@repo/jest-presets", + "files": [ + "node/jest-preset.ts" + ], + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-docker/packages/logger/.eslintrc.js b/examples/with-docker/packages/logger/.eslintrc.js deleted file mode 100644 index ed13da01cd4b3..0000000000000 --- a/examples/with-docker/packages/logger/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, - ignorePatterns: ["**/__tests__/"], -}; diff --git a/examples/with-docker/packages/logger/src/index.ts b/examples/with-docker/packages/logger/Source/index.ts similarity index 100% rename from examples/with-docker/packages/logger/src/index.ts rename to examples/with-docker/packages/logger/Source/index.ts diff --git a/examples/with-docker/packages/logger/package.json b/examples/with-docker/packages/logger/package.json index 7a82560e64572..3d5dfa316cd6f 100644 --- a/examples/with-docker/packages/logger/package.json +++ b/examples/with-docker/packages/logger/package.json @@ -1,30 +1,23 @@ { - "name": "@repo/logger", - "version": "0.0.0", - "private": true, - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "dist/**" - ], - "scripts": { - "build": "tsc", - "clean": "rm -rf dist", - "dev": "tsc -w", - "lint": "eslint \"src/**/*.ts*\" --max-warnings 0", - "test": "jest" - }, - "jest": { - "preset": "@repo/jest-presets/node" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@repo/eslint-config": "*", - "@repo/jest-presets": "*", - "@repo/typescript-config": "*", - "@types/node": "^20.11.24", - "eslint": "^8.57.0", - "jest": "^29.7.0", - "typescript": "5.5.4" - } + "name": "@repo/logger", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist/**" + ], + "scripts": { + "build": "tsc", + "clean": "rm -rf dist", + "dev": "tsc -w" + }, + "jest": { + "preset": "@repo/jest-presets/node" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/jest-presets": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-docker/packages/logger/src/__tests__/log.test.ts b/examples/with-docker/packages/logger/src/__tests__/log.test.ts deleted file mode 100644 index a31c4fc65c28d..0000000000000 --- a/examples/with-docker/packages/logger/src/__tests__/log.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, it, expect, jest } from "@jest/globals"; -import { log } from ".."; - -jest.spyOn(global.console, "log"); - -describe("@repo/logger", () => { - it("prints a message", () => { - log("hello"); - expect(console.log).toHaveBeenCalled(); - }); -}); diff --git a/examples/with-docker/packages/typescript-config/README.md b/examples/with-docker/packages/typescript-config/README.md deleted file mode 100644 index 0da79cf231837..0000000000000 --- a/examples/with-docker/packages/typescript-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `tsconfig` - -These are base shared `tsconfig.json`s from which all other `tsconfig.json`'s inherit from. diff --git a/examples/with-docker/packages/typescript-config/package.json b/examples/with-docker/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-docker/packages/typescript-config/package.json +++ b/examples/with-docker/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-docker/packages/ui/.eslintrc.js b/examples/with-docker/packages/ui/.eslintrc.js deleted file mode 100644 index 4cb7125da11b1..0000000000000 --- a/examples/with-docker/packages/ui/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-docker/packages/ui/src/button.tsx b/examples/with-docker/packages/ui/Source/button.tsx similarity index 100% rename from examples/with-docker/packages/ui/src/button.tsx rename to examples/with-docker/packages/ui/Source/button.tsx diff --git a/examples/with-docker/packages/ui/package.json b/examples/with-docker/packages/ui/package.json index b35959efb3c41..332cd1c37a838 100644 --- a/examples/with-docker/packages/ui/package.json +++ b/examples/with-docker/packages/ui/package.json @@ -1,21 +1,12 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "exports": { - "./button": "./src/button.tsx" - }, - "scripts": { - "lint": "eslint \"**/*.ts*\" --max-warnings 0" - }, - "devDependencies": { - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - } + "name": "@repo/ui", + "exports": { + "./button": "./src/button.tsx" + }, + "scripts": {}, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*" + } } diff --git a/examples/with-docker/yarn.lock b/examples/with-docker/yarn.lock deleted file mode 100644 index 506e7efcdc86f..0000000000000 --- a/examples/with-docker/yarn.lock +++ /dev/null @@ -1,5603 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== - dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" - -"@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== - -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.22.11": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" - integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.9" - "@babel/parser" "^7.23.9" - "@babel/template" "^7.23.9" - "@babel/traverse" "^7.23.9" - "@babel/types" "^7.23.9" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/eslint-parser@^7.22.11": - version "7.23.10" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz#2d4164842d6db798873b40e0c4238827084667a2" - integrity sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw== - dependencies: - "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" - eslint-visitor-keys "^2.1.0" - semver "^6.3.1" - -"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== - dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== - dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.22.5": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" - integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== - dependencies: - "@babel/template" "^7.23.9" - "@babel/traverse" "^7.23.9" - "@babel/types" "^7.23.9" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" - integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/runtime@^7.23.2": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" - integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.3.3": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" - integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.23.9" - "@babel/types" "^7.23.9" - -"@babel/traverse@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" - integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.9" - "@babel/types" "^7.23.9" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.3.3": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" - integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@esbuild/aix-ppc64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz#eafa8775019b3650a77e8310ba4dbd17ca7af6d5" - integrity sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA== - -"@esbuild/android-arm64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz#68791afa389550736f682c15b963a4f37ec2f5f6" - integrity sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A== - -"@esbuild/android-arm@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.1.tgz#38c91d8ee8d5196f7fbbdf4f0061415dde3a473a" - integrity sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw== - -"@esbuild/android-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.1.tgz#93f6190ce997b313669c20edbf3645fc6c8d8f22" - integrity sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA== - -"@esbuild/darwin-arm64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz#0d391f2e81fda833fe609182cc2fbb65e03a3c46" - integrity sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA== - -"@esbuild/darwin-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz#92504077424584684862f483a2242cfde4055ba2" - integrity sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA== - -"@esbuild/freebsd-arm64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz#a1646fa6ba87029c67ac8a102bb34384b9290774" - integrity sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw== - -"@esbuild/freebsd-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz#41c9243ab2b3254ea7fb512f71ffdb341562e951" - integrity sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg== - -"@esbuild/linux-arm64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz#f3c1e1269fbc9eedd9591a5bdd32bf707a883156" - integrity sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w== - -"@esbuild/linux-arm@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz#4503ca7001a8ee99589c072801ce9d7540717a21" - integrity sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw== - -"@esbuild/linux-ia32@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz#98c474e3e0cbb5bcbdd8561a6e65d18f5767ce48" - integrity sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw== - -"@esbuild/linux-loong64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz#a8097d28d14b9165c725fe58fc438f80decd2f33" - integrity sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA== - -"@esbuild/linux-mips64el@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz#c44f6f0d7d017c41ad3bb15bfdb69b690656b5ea" - integrity sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA== - -"@esbuild/linux-ppc64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz#0765a55389a99237b3c84227948c6e47eba96f0d" - integrity sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw== - -"@esbuild/linux-riscv64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz#e4153b032288e3095ddf4c8be07893781b309a7e" - integrity sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg== - -"@esbuild/linux-s390x@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz#b9ab8af6e4b73b26d63c1c426d7669a5d53eb5a7" - integrity sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ== - -"@esbuild/linux-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz#0b25da17ac38c3e11cdd06ca3691d4d6bef2755f" - integrity sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA== - -"@esbuild/netbsd-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz#3148e48406cd0d4f7ba1e0bf3f4d77d548c98407" - integrity sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg== - -"@esbuild/openbsd-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz#7b73e852986a9750192626d377ac96ac2b749b76" - integrity sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw== - -"@esbuild/sunos-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz#402a441cdac2eee98d8be378c7bc23e00c1861c5" - integrity sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q== - -"@esbuild/win32-arm64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz#36c4e311085806a6a0c5fc54d1ac4d7b27e94d7b" - integrity sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A== - -"@esbuild/win32-ia32@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz#0cf933be3fb9dc58b45d149559fe03e9e22b54fe" - integrity sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw== - -"@esbuild/win32-x64@0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz#77583b6ea54cee7c1410ebbd54051b6a3fcbd8ba" - integrity sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA== - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== - -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== - dependencies: - jest-get-type "^29.6.3" - -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== - dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" - -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" - -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== - dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== - dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - slash "^3.0.0" - -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.22" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" - integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@microsoft/tsdoc-config@0.16.2": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz#b786bb4ead00d54f53839a458ce626c8548d3adf" - integrity sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw== - dependencies: - "@microsoft/tsdoc" "0.14.2" - ajv "~6.12.6" - jju "~1.4.0" - resolve "~1.19.0" - -"@microsoft/tsdoc@0.14.2": - version "0.14.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" - integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== - -"@next/env@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.1.tgz#80150a8440eb0022a73ba353c6088d419b908bac" - integrity sha512-7CnQyD5G8shHxQIIg3c7/pSeYFeMhsNbpU/bmvH7ZnDql7mNRgg8O2JZrhrc/soFnfBnKP4/xXNiiSIPn2w8gA== - -"@next/eslint-plugin-next@^14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.1.tgz#123b8ca9d52fd54c343a787d4e0aa0737c4c7d97" - integrity sha512-NP1WoGFnFLpqqCWgGFjnn/sTwUExdPyjeFKRdQP1X/bL/tjAQ/TXDmYqw6vzGaP5NaZ2u6xzg+N/0nd7fOPOGQ== - dependencies: - glob "10.3.10" - -"@next/swc-darwin-arm64@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.1.tgz#b74ba7c14af7d05fa2848bdeb8ee87716c939b64" - integrity sha512-yDjSFKQKTIjyT7cFv+DqQfW5jsD+tVxXTckSe1KIouKk75t1qZmj/mV3wzdmFb0XHVGtyRjDMulfVG8uCKemOQ== - -"@next/swc-darwin-x64@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.1.tgz#82c3e67775e40094c66e76845d1a36cc29c9e78b" - integrity sha512-KCQmBL0CmFmN8D64FHIZVD9I4ugQsDBBEJKiblXGgwn7wBCSe8N4Dx47sdzl4JAg39IkSN5NNrr8AniXLMb3aw== - -"@next/swc-linux-arm64-gnu@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.1.tgz#4f4134457b90adc5c3d167d07dfb713c632c0caa" - integrity sha512-YDQfbWyW0JMKhJf/T4eyFr4b3tceTorQ5w2n7I0mNVTFOvu6CGEzfwT3RSAQGTi/FFMTFcuspPec/7dFHuP7Eg== - -"@next/swc-linux-arm64-musl@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.1.tgz#594bedafaeba4a56db23a48ffed2cef7cd09c31a" - integrity sha512-fiuN/OG6sNGRN/bRFxRvV5LyzLB8gaL8cbDH5o3mEiVwfcMzyE5T//ilMmaTrnA8HLMS6hoz4cHOu6Qcp9vxgQ== - -"@next/swc-linux-x64-gnu@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.1.tgz#cb4e75f1ff2b9bcadf2a50684605928ddfc58528" - integrity sha512-rv6AAdEXoezjbdfp3ouMuVqeLjE1Bin0AuE6qxE6V9g3Giz5/R3xpocHoAi7CufRR+lnkuUjRBn05SYJ83oKNQ== - -"@next/swc-linux-x64-musl@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.1.tgz#15f26800df941b94d06327f674819ab64b272e25" - integrity sha512-YAZLGsaNeChSrpz/G7MxO3TIBLaMN8QWMr3X8bt6rCvKovwU7GqQlDu99WdvF33kI8ZahvcdbFsy4jAFzFX7og== - -"@next/swc-win32-arm64-msvc@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.1.tgz#060c134fa7fa843666e3e8574972b2b723773dd9" - integrity sha512-1L4mUYPBMvVDMZg1inUYyPvFSduot0g73hgfD9CODgbr4xiTYe0VOMTZzaRqYJYBA9mana0x4eaAaypmWo1r5A== - -"@next/swc-win32-ia32-msvc@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.1.tgz#5c06889352b1f77e3807834a0d0afd7e2d2d1da2" - integrity sha512-jvIE9tsuj9vpbbXlR5YxrghRfMuG0Qm/nZ/1KDHc+y6FpnZ/apsgh+G6t15vefU0zp3WSpTMIdXRUsNl/7RSuw== - -"@next/swc-win32-x64-msvc@14.1.1": - version "14.1.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.1.tgz#d38c63a8f9b7f36c1470872797d3735b4a9c5c52" - integrity sha512-S6K6EHDU5+1KrBDLko7/c1MNy/Ya73pIAmvKeFwsF4RmBFJSO7/7YeD4FnZ4iBdzE69PpQ4sOMU9ORKeNuxe8A== - -"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": - version "5.1.1-v1" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" - integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== - dependencies: - eslint-scope "5.1.1" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@pkgr/core@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" - integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== - -"@rushstack/eslint-patch@^1.3.3": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz#2d4260033e199b3032a08b41348ac10de21c47e9" - integrity sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA== - -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - -"@sinonjs/commons@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@swc/helpers@0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d" - integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw== - dependencies: - tslib "^2.4.0" - -"@types/babel__core@^7.1.14": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== - dependencies: - "@babel/types" "^7.20.7" - -"@types/body-parser@*", "@types/body-parser@^1.19.5": - version "1.19.5" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" - integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/connect@*": - version "3.4.38" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" - integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== - dependencies: - "@types/node" "*" - -"@types/cookiejar@^2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.5.tgz#14a3e83fa641beb169a2dd8422d91c3c345a9a78" - integrity sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q== - -"@types/cors@^2.8.17": - version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" - integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== - dependencies: - "@types/node" "*" - -"@types/express-serve-static-core@^4.17.33": - version "4.17.42" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.42.tgz#2a276952acc73d1b8dc63fd4210647abbc553a71" - integrity sha512-ckM3jm2bf/MfB3+spLPWYPUH573plBFwpOhqQ2WottxYV85j1HQFlxmnTq57X1yHY9awZPig06hL/cLMgNWHIQ== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - -"@types/express@^4.17.21": - version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.33" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/graceful-fs@^4.1.3": - version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== - dependencies: - "@types/node" "*" - -"@types/http-errors@*": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" - integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/json-schema@^7.0.12", "@types/json-schema@^7.0.9": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/methods@^1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547" - integrity sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ== - -"@types/mime@*": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" - integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw== - -"@types/mime@^1": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" - integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== - -"@types/morgan@^1.9.9": - version "1.9.9" - resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.9.tgz#d60dec3979e16c203a000159daa07d3fb7270d7f" - integrity sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ== - dependencies: - "@types/node" "*" - -"@types/node@*", "@types/node@^20.11.24": - version "20.11.24" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.24.tgz#cc207511104694e84e9fb17f9a0c4c42d4517792" - integrity sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long== - dependencies: - undici-types "~5.26.4" - -"@types/normalize-package-data@^2.4.0": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== - -"@types/prop-types@*": - version "15.7.11" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" - integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== - -"@types/qs@*": - version "6.9.11" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda" - integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ== - -"@types/range-parser@*": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" - integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== - -"@types/react-dom@^18.2.19": - version "18.2.19" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.19.tgz#b84b7c30c635a6c26c6a6dfbb599b2da9788be58" - integrity sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@^18.2.61": - version "18.2.61" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.61.tgz#5607308495037436779939ec0348a5816c08799d" - integrity sha512-NURTN0qNnJa7O/k4XUkEW2yfygA+NxS0V5h1+kp9jPwhzZy95q3ADoGMP0+JypMhrZBTTgjKAUlTctde1zzeQA== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.8" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" - integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== - -"@types/semver@^7.3.12", "@types/semver@^7.5.0": - version "7.5.6" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" - integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== - -"@types/send@*": - version "0.17.4" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" - integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - -"@types/serve-static@*": - version "1.15.5" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033" - integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ== - dependencies: - "@types/http-errors" "*" - "@types/mime" "*" - "@types/node" "*" - -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/superagent@^8.1.0": - version "8.1.3" - resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-8.1.3.tgz#6222a466e89eac9c84ad8de11870d92097e6554a" - integrity sha512-R/CfN6w2XsixLb1Ii8INfn+BT9sGPvw74OavfkW4SwY+jeUcAwLZv2+bXLJkndnimxjEBm0RPHgcjW9pLCa8cw== - dependencies: - "@types/cookiejar" "^2.1.5" - "@types/methods" "^1.1.4" - "@types/node" "*" - -"@types/supertest@^6.0.2": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-6.0.2.tgz#2af1c466456aaf82c7c6106c6b5cbd73a5e86588" - integrity sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg== - dependencies: - "@types/methods" "^1.1.4" - "@types/superagent" "^8.1.0" - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^6.5.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz#9cf31546d2d5e884602626d89b0e0d2168ac25ed" - integrity sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.20.0" - "@typescript-eslint/type-utils" "6.20.0" - "@typescript-eslint/utils" "6.20.0" - "@typescript-eslint/visitor-keys" "6.20.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/eslint-plugin@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz#22bb999a8d59893c0ea07923e8a21f9d985ad740" - integrity sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "7.1.0" - "@typescript-eslint/type-utils" "7.1.0" - "@typescript-eslint/utils" "7.1.0" - "@typescript-eslint/visitor-keys" "7.1.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/parser@^6.5.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.20.0.tgz#17e314177304bdf498527e3c4b112e41287b7416" - integrity sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w== - dependencies: - "@typescript-eslint/scope-manager" "6.20.0" - "@typescript-eslint/types" "6.20.0" - "@typescript-eslint/typescript-estree" "6.20.0" - "@typescript-eslint/visitor-keys" "6.20.0" - debug "^4.3.4" - -"@typescript-eslint/parser@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.1.0.tgz#b89dab90840f7d2a926bf4c23b519576e8c31970" - integrity sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w== - dependencies: - "@typescript-eslint/scope-manager" "7.1.0" - "@typescript-eslint/types" "7.1.0" - "@typescript-eslint/typescript-estree" "7.1.0" - "@typescript-eslint/visitor-keys" "7.1.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - -"@typescript-eslint/scope-manager@6.20.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz#8a926e60f6c47feb5bab878246dc2ae465730151" - integrity sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA== - dependencies: - "@typescript-eslint/types" "6.20.0" - "@typescript-eslint/visitor-keys" "6.20.0" - -"@typescript-eslint/scope-manager@7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz#e4babaa39a3d612eff0e3559f3e99c720a2b4a54" - integrity sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A== - dependencies: - "@typescript-eslint/types" "7.1.0" - "@typescript-eslint/visitor-keys" "7.1.0" - -"@typescript-eslint/type-utils@6.20.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz#d395475cd0f3610dd80c7d8716fa0db767da3831" - integrity sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g== - dependencies: - "@typescript-eslint/typescript-estree" "6.20.0" - "@typescript-eslint/utils" "6.20.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/type-utils@7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz#372dfa470df181bcee0072db464dc778b75ed722" - integrity sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew== - dependencies: - "@typescript-eslint/typescript-estree" "7.1.0" - "@typescript-eslint/utils" "7.1.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/types@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== - -"@typescript-eslint/types@6.20.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.20.0.tgz#5ccd74c29011ae7714ae6973e4ec0c634708b448" - integrity sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ== - -"@typescript-eslint/types@7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.1.0.tgz#52a86d6236fda646e7e5fe61154991dc0dc433ef" - integrity sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA== - -"@typescript-eslint/typescript-estree@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/typescript-estree@6.20.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz#5b2d0975949e6bdd8d45ee1471461ef5fadc5542" - integrity sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g== - dependencies: - "@typescript-eslint/types" "6.20.0" - "@typescript-eslint/visitor-keys" "6.20.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/typescript-estree@7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz#419b1310f061feee6df676c5bed460537310c593" - integrity sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ== - dependencies: - "@typescript-eslint/types" "7.1.0" - "@typescript-eslint/visitor-keys" "7.1.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/utils@6.20.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.20.0.tgz#0e52afcfaa51af5656490ba4b7437cc3aa28633d" - integrity sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.20.0" - "@typescript-eslint/types" "6.20.0" - "@typescript-eslint/typescript-estree" "6.20.0" - semver "^7.5.4" - -"@typescript-eslint/utils@7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.1.0.tgz#710ecda62aff4a3c8140edabf3c5292d31111ddd" - integrity sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "7.1.0" - "@typescript-eslint/types" "7.1.0" - "@typescript-eslint/typescript-estree" "7.1.0" - semver "^7.5.4" - -"@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.58.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== - dependencies: - "@typescript-eslint/types" "5.62.0" - eslint-visitor-keys "^3.3.0" - -"@typescript-eslint/visitor-keys@6.20.0": - version "6.20.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz#f7ada27f2803de89df0edd9fd7be22c05ce6a498" - integrity sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw== - dependencies: - "@typescript-eslint/types" "6.20.0" - eslint-visitor-keys "^3.4.1" - -"@typescript-eslint/visitor-keys@7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz#576c4ad462ca1378135a55e2857d7aced96ce0a0" - integrity sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA== - dependencies: - "@typescript-eslint/types" "7.1.0" - eslint-visitor-keys "^3.4.1" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@vercel/style-guide@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@vercel/style-guide/-/style-guide-5.2.0.tgz#8e09fb48065bc6133add67ff2bc7a219d228fb46" - integrity sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g== - dependencies: - "@babel/core" "^7.22.11" - "@babel/eslint-parser" "^7.22.11" - "@rushstack/eslint-patch" "^1.3.3" - "@typescript-eslint/eslint-plugin" "^6.5.0" - "@typescript-eslint/parser" "^6.5.0" - eslint-config-prettier "^9.0.0" - eslint-import-resolver-alias "^1.1.2" - eslint-import-resolver-typescript "^3.6.0" - eslint-plugin-eslint-comments "^3.2.0" - eslint-plugin-import "^2.28.1" - eslint-plugin-jest "^27.2.3" - eslint-plugin-jsx-a11y "^6.7.1" - eslint-plugin-playwright "^0.16.0" - eslint-plugin-react "^7.33.2" - eslint-plugin-react-hooks "^4.6.0" - eslint-plugin-testing-library "^6.0.1" - eslint-plugin-tsdoc "^0.2.17" - eslint-plugin-unicorn "^48.0.1" - prettier-plugin-packagejson "^2.4.5" - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -ajv@^6.12.4, ajv@~6.12.6: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-query@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" - -array-buffer-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" - integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== - dependencies: - call-bind "^1.0.2" - is-array-buffer "^3.0.1" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -array-includes@^3.1.6, array-includes@^3.1.7: - version "3.1.7" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" - integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.findlastindex@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" - integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - get-intrinsic "^1.2.1" - -array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.1, array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.tosorted@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz#620eff7442503d66c799d95503f82b475745cefd" - integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - get-intrinsic "^1.2.1" - -arraybuffer.prototype.slice@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" - integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== - dependencies: - array-buffer-byte-length "^1.0.0" - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - is-array-buffer "^3.0.2" - is-shared-array-buffer "^1.0.2" - -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - -ast-types-flow@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" - integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== - -async@^3.2.3: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - -asynciterator.prototype@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" - integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== - dependencies: - has-symbols "^1.0.3" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -axe-core@=4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" - integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== - -axobject-query@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" - integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== - dependencies: - dequal "^2.0.3" - -babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== - dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -basic-auth@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" - integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== - dependencies: - safe-buffer "5.1.2" - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -body-parser@1.20.2, body-parser@^1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.22.2: - version "4.22.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6" - integrity sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A== - dependencies: - caniuse-lite "^1.0.30001580" - electron-to-chromium "^1.4.648" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -bs-logger@^0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -builtin-modules@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" - integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== - -busboy@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001580: - version "1.0.30001581" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz#0dfd4db9e94edbdca67d57348ebc070dece279f4" - integrity sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chokidar@^3.5.2: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -ci-info@^3.2.0, ci-info@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -cjs-module-lexer@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - -clean-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7" - integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw== - dependencies: - escape-string-regexp "^1.0.5" - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -component-emitter@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" - integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4, content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -cookiejar@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" - integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== - -cors@^2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -damerau-levenshtein@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" - integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -dedent@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" - integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -define-data-property@^1.0.1, define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -depd@2.0.0, depd@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-indent@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25" - integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -detect-newline@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-4.0.1.tgz#fcefdb5713e1fb8cb2839b8b6ee22e6716ab8f23" - integrity sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog== - -dezalgo@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" - integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== - dependencies: - asap "^2.0.0" - wrappy "1" - -diff-sequences@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dotenv@16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -ejs@^3.1.10: - version "3.1.10" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" - integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== - dependencies: - jake "^10.8.5" - -electron-to-chromium@^1.4.648: - version "1.4.652" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.652.tgz#1591c7542d43c990de786374c07a9d6ad2b63787" - integrity sha512-XvQaa8hVUAuEJtLw6VKQqvdOxTOfBLWfI10t2xWpezx4XXD3k8bdLweEKeItqaa0+OkJX5l0mP1W+JWobyIDrg== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -enhanced-resolve@^5.12.0: - version "5.15.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" - integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.22.1: - version "1.22.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" - integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== - dependencies: - array-buffer-byte-length "^1.0.0" - arraybuffer.prototype.slice "^1.0.2" - available-typed-arrays "^1.0.5" - call-bind "^1.0.5" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.2" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.12" - is-weakref "^1.0.2" - object-inspect "^1.13.1" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.1" - safe-array-concat "^1.0.1" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.8" - string.prototype.trimend "^1.0.7" - string.prototype.trimstart "^1.0.7" - typed-array-buffer "^1.0.0" - typed-array-byte-length "^1.0.0" - typed-array-byte-offset "^1.0.0" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.13" - -es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: - version "1.0.15" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" - integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== - dependencies: - asynciterator.prototype "^1.0.0" - call-bind "^1.0.2" - define-properties "^1.2.1" - es-abstract "^1.22.1" - es-set-tostringtag "^2.0.1" - function-bind "^1.1.1" - get-intrinsic "^1.2.1" - globalthis "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - iterator.prototype "^1.1.2" - safe-array-concat "^1.0.1" - -es-set-tostringtag@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" - integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== - dependencies: - get-intrinsic "^1.2.2" - has-tostringtag "^1.0.0" - hasown "^2.0.0" - -es-shim-unscopables@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== - dependencies: - hasown "^2.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -esbuild-register@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/esbuild-register/-/esbuild-register-3.5.0.tgz#449613fb29ab94325c722f560f800dd946dc8ea8" - integrity sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A== - dependencies: - debug "^4.3.4" - -esbuild@^0.20.1: - version "0.20.1" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.1.tgz#1e4cbb380ad1959db7609cb9573ee77257724a3e" - integrity sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA== - optionalDependencies: - "@esbuild/aix-ppc64" "0.20.1" - "@esbuild/android-arm" "0.20.1" - "@esbuild/android-arm64" "0.20.1" - "@esbuild/android-x64" "0.20.1" - "@esbuild/darwin-arm64" "0.20.1" - "@esbuild/darwin-x64" "0.20.1" - "@esbuild/freebsd-arm64" "0.20.1" - "@esbuild/freebsd-x64" "0.20.1" - "@esbuild/linux-arm" "0.20.1" - "@esbuild/linux-arm64" "0.20.1" - "@esbuild/linux-ia32" "0.20.1" - "@esbuild/linux-loong64" "0.20.1" - "@esbuild/linux-mips64el" "0.20.1" - "@esbuild/linux-ppc64" "0.20.1" - "@esbuild/linux-riscv64" "0.20.1" - "@esbuild/linux-s390x" "0.20.1" - "@esbuild/linux-x64" "0.20.1" - "@esbuild/netbsd-x64" "0.20.1" - "@esbuild/openbsd-x64" "0.20.1" - "@esbuild/sunos-x64" "0.20.1" - "@esbuild/win32-arm64" "0.20.1" - "@esbuild/win32-ia32" "0.20.1" - "@esbuild/win32-x64" "0.20.1" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-prettier@^9.0.0, eslint-config-prettier@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" - integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== - -eslint-config-turbo@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-turbo/-/eslint-config-turbo-2.0.0.tgz#d3ebda365821aef48895f94c62985ddf400bf892" - integrity sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw== - dependencies: - eslint-plugin-turbo "2.0.0" - -eslint-import-resolver-alias@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz#297062890e31e4d6651eb5eba9534e1f6e68fc97" - integrity sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w== - -eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-import-resolver-typescript@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" - integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== - dependencies: - debug "^4.3.4" - enhanced-resolve "^5.12.0" - eslint-module-utils "^2.7.4" - fast-glob "^3.3.1" - get-tsconfig "^4.5.0" - is-core-module "^2.11.0" - is-glob "^4.0.3" - -eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" - integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== - dependencies: - debug "^3.2.7" - -eslint-plugin-eslint-comments@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa" - integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== - dependencies: - escape-string-regexp "^1.0.5" - ignore "^5.0.5" - -eslint-plugin-import@^2.28.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-plugin-jest@^27.2.3: - version "27.6.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz#8acb8b1e45597fe1f4d4cf25163d90119efc12be" - integrity sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA== - dependencies: - "@typescript-eslint/utils" "^5.10.0" - -eslint-plugin-jsx-a11y@^6.7.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" - integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== - dependencies: - "@babel/runtime" "^7.23.2" - aria-query "^5.3.0" - array-includes "^3.1.7" - array.prototype.flatmap "^1.3.2" - ast-types-flow "^0.0.8" - axe-core "=4.7.0" - axobject-query "^3.2.1" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - es-iterator-helpers "^1.0.15" - hasown "^2.0.0" - jsx-ast-utils "^3.3.5" - language-tags "^1.0.9" - minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - -eslint-plugin-only-warn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-only-warn/-/eslint-plugin-only-warn-1.1.0.tgz#c6ddc37ddc4e72c121f07be565fcb7b6671fe78a" - integrity sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA== - -eslint-plugin-playwright@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-0.16.0.tgz#083c601a0704a7615509e63ac475bf7f0052d226" - integrity sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw== - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - -eslint-plugin-react@^7.33.2: - version "7.33.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" - integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== - dependencies: - array-includes "^3.1.6" - array.prototype.flatmap "^1.3.1" - array.prototype.tosorted "^1.1.1" - doctrine "^2.1.0" - es-iterator-helpers "^1.0.12" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.6" - object.fromentries "^2.0.6" - object.hasown "^1.1.2" - object.values "^1.1.6" - prop-types "^15.8.1" - resolve "^2.0.0-next.4" - semver "^6.3.1" - string.prototype.matchall "^4.0.8" - -eslint-plugin-testing-library@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.0.tgz#af3340b783c881eb19ec5ac6b3a4bfe8ab4a1f74" - integrity sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw== - dependencies: - "@typescript-eslint/utils" "^5.58.0" - -eslint-plugin-tsdoc@^0.2.17: - version "0.2.17" - resolved "https://registry.yarnpkg.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz#27789495bbd8778abbf92db1707fec2ed3dfe281" - integrity sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA== - dependencies: - "@microsoft/tsdoc" "0.14.2" - "@microsoft/tsdoc-config" "0.16.2" - -eslint-plugin-turbo@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-turbo/-/eslint-plugin-turbo-2.0.0.tgz#938b95acdedd19318212d8ccab2537d2dd924bc4" - integrity sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw== - dependencies: - dotenv "16.0.3" - -eslint-plugin-unicorn@^48.0.1: - version "48.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz#a6573bc1687ae8db7121fdd8f92394b6549a6959" - integrity sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw== - dependencies: - "@babel/helper-validator-identifier" "^7.22.5" - "@eslint-community/eslint-utils" "^4.4.0" - ci-info "^3.8.0" - clean-regexp "^1.0.0" - esquery "^1.5.0" - indent-string "^4.0.0" - is-builtin-module "^3.2.1" - jsesc "^3.0.2" - lodash "^4.17.21" - pluralize "^8.0.0" - read-pkg-up "^7.0.1" - regexp-tree "^0.1.27" - regjsparser "^0.10.0" - semver "^7.5.4" - strip-indent "^3.0.0" - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.2, esquery@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - 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" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== - -expect@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== - dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - -express@^4.18.3: - version "4.18.3" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.3.tgz#6870746f3ff904dee1819b82e4b51509afffb0d4" - integrity sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.5.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - -fastq@^1.6.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.0.tgz#ca5e1a90b5e68f97fc8b61330d5819b82f5fab03" - integrity sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -filelist@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" - integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== - dependencies: - minimatch "^5.0.1" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.2.9" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" - integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -formidable@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" - integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== - dependencies: - dezalgo "^1.0.4" - hexoid "^1.0.0" - once "^1.4.0" - qs "^6.11.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.1, function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - functions-have-names "^1.2.3" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== - dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stdin@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575" - integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -get-tsconfig@^4.5.0: - version "4.7.2" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce" - integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A== - dependencies: - resolve-pkg-maps "^1.0.0" - -git-hooks-list@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-3.1.0.tgz#386dc531dcc17474cf094743ff30987a3d3e70fc" - integrity sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - -glob@^7.1.3, glob@^7.1.4: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^13.1.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" - integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.3.0" - ignore "^5.2.4" - merge2 "^1.4.1" - slash "^4.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -hexoid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" - integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ignore-by-default@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== - -ignore@^5.0.5, ignore@^5.2.0, ignore@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" - integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== - dependencies: - get-intrinsic "^1.2.2" - hasown "^2.0.0" - side-channel "^1.0.4" - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-async-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" - integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== - dependencies: - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-builtin-module@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" - integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== - dependencies: - builtin-modules "^3.3.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.1.0, is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== - dependencies: - call-bind "^1.0.2" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-generator-function@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-map@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" - integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" - integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-set@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" - integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: - version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" - integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== - dependencies: - which-typed-array "^1.1.11" - -is-weakmap@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" - integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-weakset@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" - integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-instrument@^5.0.4: - version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-instrument@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" - integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" - integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -iterator.prototype@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" - integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== - dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" - -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jake@^10.8.5: - version "10.9.2" - resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" - integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== - dependencies: - async "^3.2.3" - chalk "^4.0.2" - filelist "^1.0.4" - minimatch "^3.1.2" - -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== - dependencies: - execa "^5.0.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - -jest-environment-node@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== - dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-pnp-resolver@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== - dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.7.0" - graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" - pretty-format "^29.7.0" - semver "^7.5.3" - -jest-util@^29.0.0, jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== - dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" - -jest-worker@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== - dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" - -jju@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" - integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" - integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: - version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" - integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - object.assign "^4.1.4" - object.values "^1.1.6" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -language-subtag-registry@^0.3.20: - version "0.3.22" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" - integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== - -language-tags@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" - integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== - dependencies: - language-subtag-registry "^0.3.20" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -"lru-cache@^9.1.1 || ^10.0.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" - integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== - -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - -make-error@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@^1.1.2, methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - -minimatch@9.0.3, minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.0.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" - integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== - -morgan@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" - integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== - dependencies: - basic-auth "~2.0.1" - debug "2.6.9" - depd "~2.0.0" - on-finished "~2.3.0" - on-headers "~1.0.2" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -nanoid@^3.3.6: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -next@^14.1.1: - version "14.1.1" - resolved "https://registry.yarnpkg.com/next/-/next-14.1.1.tgz#92bd603996c050422a738e90362dff758459a171" - integrity sha512-McrGJqlGSHeaz2yTRPkEucxQKe5Zq7uPwyeHNmJaZNY4wx9E9QdxmTp310agFRoMuIYgQrCrT3petg13fSVOww== - dependencies: - "@next/env" "14.1.1" - "@swc/helpers" "0.5.2" - busboy "1.6.0" - caniuse-lite "^1.0.30001579" - graceful-fs "^4.2.11" - postcss "8.4.31" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-darwin-arm64" "14.1.1" - "@next/swc-darwin-x64" "14.1.1" - "@next/swc-linux-arm64-gnu" "14.1.1" - "@next/swc-linux-arm64-musl" "14.1.1" - "@next/swc-linux-x64-gnu" "14.1.1" - "@next/swc-linux-x64-musl" "14.1.1" - "@next/swc-win32-arm64-msvc" "14.1.1" - "@next/swc-win32-ia32-msvc" "14.1.1" - "@next/swc-win32-x64-msvc" "14.1.1" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -nodemon@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.0.tgz#ff7394f2450eb6a5e96fe4180acd5176b29799c9" - integrity sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA== - dependencies: - chokidar "^3.5.2" - debug "^4" - ignore-by-default "^1.0.1" - minimatch "^3.1.2" - pstree.remy "^1.1.8" - semver "^7.5.3" - simple-update-notifier "^2.0.0" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.5" - -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== - dependencies: - abbrev "1" - -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-assign@^4, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.13.1, object-inspect@^1.9.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.entries@^1.1.6, object.entries@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" - integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -object.fromentries@^2.0.6, object.fromentries@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" - integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -object.groupby@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" - integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - -object.hasown@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.3.tgz#6a5f2897bb4d3668b8e79364f98ccf971bda55ae" - integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== - dependencies: - define-properties "^1.2.0" - es-abstract "^1.22.1" - -object.values@^1.1.6, object.values@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" - integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.0.0, parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - 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" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6, path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== - dependencies: - lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pluralize@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" - integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== - -postcss@8.4.31: - version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-plugin-packagejson@^2.4.5: - version "2.4.10" - resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.4.10.tgz#6ce4aac8d305102f1ff8354f33767f0f001fef0e" - integrity sha512-qFzOfQDHi1tzvVJRuZ2jh1j6IFV5MURh5m5WDt+qfEMOf4SSL5RpwSysiX8u0W1PJYsM0vKJGNULt43wwteKiQ== - dependencies: - sort-package-json "2.7.0" - synckit "0.9.0" - -prettier@^3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" - integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== - -pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== - dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -pstree.remy@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" - integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -pure-rand@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" - integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -qs@^6.11.0: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-dom@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -react@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reflect.getprototypeof@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" - integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regexp-tree@^0.1.27: - version "0.1.27" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" - integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== - -regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" - integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - set-function-name "^2.0.0" - -regjsparser@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.10.0.tgz#b1ed26051736b436f22fdec1c8f72635f9f44892" - integrity sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA== - dependencies: - jsesc "~0.5.0" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== - -resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.4: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.4: - version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" - integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@~1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-array-concat@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" - integrity sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg== - dependencies: - call-bind "^1.0.5" - get-intrinsic "^1.2.2" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-buffer@5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex-test@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.2.tgz#3ba32bdb3ea35f940ee87e5087c60ee786c3f6c5" - integrity sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ== - dependencies: - call-bind "^1.0.5" - get-intrinsic "^1.2.2" - is-regex "^1.1.4" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -semver@^7.6.3: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-function-length@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" - integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== - dependencies: - define-data-property "^1.1.1" - function-bind "^1.1.2" - get-intrinsic "^1.2.2" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -set-function-name@^2.0.0, set-function-name@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" - integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== - dependencies: - define-data-property "^1.0.1" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.0" - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.3, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -simple-update-notifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" - integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== - dependencies: - semver "^7.5.3" - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -sort-object-keys@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" - integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== - -sort-package-json@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.7.0.tgz#41b52710939d7e3a4e328eb92c2136db43a6407d" - integrity sha512-6AayF8bp6L+WROgpbhTMUtB9JSFmpGHjmW7DyaNPS1HwlTw2oSVlUUtlkHSEZmg5o89F3zvLBZNvMeZ1T4fjQg== - dependencies: - detect-indent "^7.0.1" - detect-newline "^4.0.0" - get-stdin "^9.0.0" - git-hooks-list "^3.0.0" - globby "^13.1.2" - is-plain-obj "^4.1.0" - sort-object-keys "^1.1.3" - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz#c07a4ede25b16e4f78e6707bbd84b15a45c19c1b" - integrity sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.16" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz#a14f64e0954f6e25cc6587bd4f392522db0d998f" - integrity sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.matchall@^4.0.8: - version "4.0.10" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" - integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - regexp.prototype.flags "^1.5.0" - set-function-name "^2.0.0" - side-channel "^1.0.4" - -string.prototype.trim@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" - integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -string.prototype.trimend@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" - integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -string.prototype.trimstart@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" - integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -superagent@^8.1.2: - version "8.1.2" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" - integrity sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.4" - debug "^4.3.4" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.1.2" - methods "^1.1.2" - mime "2.6.0" - qs "^6.11.0" - semver "^7.3.8" - -supertest@^6.3.3: - version "6.3.4" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.4.tgz#2145c250570c2ea5d337db3552dbfb78a2286218" - integrity sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw== - dependencies: - methods "^1.1.2" - superagent "^8.1.2" - -supports-color@^5.3.0, supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -synckit@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.0.tgz#5b33b458b3775e4466a5b377fba69c63572ae449" - integrity sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg== - dependencies: - "@pkgr/core" "^0.1.0" - tslib "^2.6.2" - -tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -touch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" - integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== - dependencies: - nopt "~1.0.10" - -ts-api-utils@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" - integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== - -ts-jest@^29.2.5: - version "29.2.5" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" - integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== - dependencies: - bs-logger "^0.2.6" - ejs "^3.1.10" - fast-json-stable-stringify "^2.1.0" - jest-util "^29.0.0" - json5 "^2.2.3" - lodash.memoize "^4.1.2" - make-error "^1.3.6" - semver "^7.6.3" - yargs-parser "^21.1.1" - -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.4.0, tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -turbo-darwin-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.0.3.tgz#52c5f79b4027dfd0184fb963da41bf989be4a00d" - integrity sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q== - -turbo-darwin-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.3.tgz#46fa54d0cd95782ac38015e3396d59cdbdeb1eb8" - integrity sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw== - -turbo-linux-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.0.3.tgz#17d6714b32381d474ef2ee5613343165f9bd75bc" - integrity sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q== - -turbo-linux-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.0.3.tgz#4f1bfe421dcecf2fb1164a1e223ba310d6e28b6f" - integrity sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A== - -turbo-windows-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.0.3.tgz#9d1b99aff361bcbf4e065029e9dfa6682a0c0b2d" - integrity sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w== - -turbo-windows-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.0.3.tgz#0e0641acda3325a4a3d28123ef21017a7aae8f38" - integrity sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg== - -turbo@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.0.3.tgz#789f64666d15dbc6fc85ce507a6c6888d70df88f" - integrity sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA== - optionalDependencies: - turbo-darwin-64 "2.0.3" - turbo-darwin-arm64 "2.0.3" - turbo-linux-64 "2.0.3" - turbo-linux-arm64 "2.0.3" - turbo-windows-64 "2.0.3" - turbo-windows-arm64 "2.0.3" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typed-array-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" - integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - is-typed-array "^1.1.10" - -typed-array-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" - integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" - -typed-array-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" - integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" - -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - is-typed-array "^1.1.9" - -typescript@5.5.4: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -undefsafe@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" - integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-builtin-type@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" - integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== - dependencies: - function.prototype.name "^1.1.5" - has-tostringtag "^1.0.0" - is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" - is-generator-function "^1.0.10" - is-regex "^1.1.4" - is-weakref "^1.0.2" - isarray "^2.0.5" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" - -which-collection@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" - integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== - dependencies: - is-map "^2.0.1" - is-set "^2.0.1" - is-weakmap "^2.0.1" - is-weakset "^2.0.1" - -which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.9: - version "1.1.13" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" - integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.4" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - 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" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/examples/with-gatsby/README.md b/examples/with-gatsby/README.md deleted file mode 100644 index 0a3b196152f4e..0000000000000 --- a/examples/with-gatsby/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Turborepo Gatsby.js starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-gatsby -``` - -## What's inside? - -This Turborepo includes the following packages and apps: - -### Apps and Packages - -- `docs`: a [Next.js](https://nextjs.org/) app -- `web`: a [Gatsby.js](https://www.gatsbyjs.com/docs) app -- `@repo/ui`: a stub React component library shared by both `web` and `docs` applications -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Build - -To build all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm run build -``` - -### Develop - -To develop all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm dev -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -``` -cd my-turborepo -pnpm dlx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your turborepo: - -``` -pnpm dlx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/with-gatsby/apps/docs/.eslintrc.js b/examples/with-gatsby/apps/docs/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-gatsby/apps/docs/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-gatsby/apps/docs/README.md b/examples/with-gatsby/apps/docs/README.md deleted file mode 100644 index 14e1db23b70dc..0000000000000 --- a/examples/with-gatsby/apps/docs/README.md +++ /dev/null @@ -1,30 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -turbo dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-gatsby/apps/docs/package.json b/examples/with-gatsby/apps/docs/package.json index bd3406279dcb5..0b9f3f3b7faef 100644 --- a/examples/with-gatsby/apps/docs/package.json +++ b/examples/with-gatsby/apps/docs/package.json @@ -1,27 +1,17 @@ { - "name": "docs", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "next dev --port 3001", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0" - }, - "dependencies": { - "@repo/ui": "workspace:*", - "next": "^14.1.1", - "react": "18.2.0", - "react-dom": "18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "docs", + "scripts": { + "build": "next build", + "dev": "next dev --port 3001", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "workspace:*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-gatsby/apps/web/.eslintrc.js b/examples/with-gatsby/apps/web/.eslintrc.js deleted file mode 100644 index dfa0d078e6b9c..0000000000000 --- a/examples/with-gatsby/apps/web/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ["@repo/eslint-config/gatsby.js"], - ignorePatterns: ["gatsby-types.d.ts"], -}; diff --git a/examples/with-gatsby/apps/web/README.md b/examples/with-gatsby/apps/web/README.md deleted file mode 100644 index b348ca3c60ace..0000000000000 --- a/examples/with-gatsby/apps/web/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## 🚀 Quick start - -1. **Start developing.** - - Navigate into your new site’s directory and start it up. - - ```bash - turbo dev - ``` - -2. **Open the code and start customizing!** - - Your site is now running at http://localhost:8000! - - Edit `src/pages/index.tsx` to see your site update in real-time! diff --git a/examples/with-gatsby/apps/web/src/pages/404.tsx b/examples/with-gatsby/apps/web/Source/pages/404.tsx similarity index 100% rename from examples/with-gatsby/apps/web/src/pages/404.tsx rename to examples/with-gatsby/apps/web/Source/pages/404.tsx diff --git a/examples/with-gatsby/apps/web/src/pages/index.tsx b/examples/with-gatsby/apps/web/Source/pages/index.tsx similarity index 100% rename from examples/with-gatsby/apps/web/src/pages/index.tsx rename to examples/with-gatsby/apps/web/Source/pages/index.tsx diff --git a/examples/with-gatsby/apps/web/package.json b/examples/with-gatsby/apps/web/package.json index d47994caa7630..2723562bc9577 100644 --- a/examples/with-gatsby/apps/web/package.json +++ b/examples/with-gatsby/apps/web/package.json @@ -1,28 +1,18 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "gatsby develop", - "build": "gatsby build", - "start": "gatsby develop", - "typecheck": "tsc --noEmit", - "lint": "eslint src/ --max-warnings 0" - }, - "dependencies": { - "gatsby": "^5.13.3", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "@repo/ui": "workspace:*" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "gatsby-plugin-compile-es6-packages": "^2.1.1", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "gatsby build", + "dev": "gatsby develop", + "start": "gatsby develop" + }, + "dependencies": { + "@repo/ui": "workspace:*", + "gatsby": "5.14.1" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1", + "gatsby-plugin-compile-es6-packages": "2.1.1" + } } diff --git a/examples/with-gatsby/package.json b/examples/with-gatsby/package.json index ff05daa25a612..373fdf3ee4078 100644 --- a/examples/with-gatsby/package.json +++ b/examples/with-gatsby/package.json @@ -1,19 +1,11 @@ { - "name": "with-gatsby", - "version": "0.0.0", - "private": true, - "scripts": { - "build": "turbo build", - "dev": "turbo dev", - "lint": "turbo lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "engines": { - "node": ">=18" - }, - "packageManager": "pnpm@8.15.6" + "name": "with-gatsby", + "scripts": { + "build": "turbo build", + "dev": "turbo dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-gatsby/packages/eslint-config/README.md b/examples/with-gatsby/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-gatsby/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-gatsby/packages/eslint-config/package.json b/examples/with-gatsby/packages/eslint-config/package.json index f5ee17cfa83d3..80bc80ad4a524 100644 --- a/examples/with-gatsby/packages/eslint-config/package.json +++ b/examples/with-gatsby/packages/eslint-config/package.json @@ -1,20 +1,15 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "gatsby.js", - "library.js", - "next.js", - "react-internal.js" - ], - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@vercel/style-guide": "^5.2.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-only-warn": "^1.1.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "gatsby.js", + "library.js", + "next.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-gatsby/packages/typescript-config/README.md b/examples/with-gatsby/packages/typescript-config/README.md deleted file mode 100644 index 0da79cf231837..0000000000000 --- a/examples/with-gatsby/packages/typescript-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `tsconfig` - -These are base shared `tsconfig.json`s from which all other `tsconfig.json`'s inherit from. diff --git a/examples/with-gatsby/packages/typescript-config/package.json b/examples/with-gatsby/packages/typescript-config/package.json index 500b180311fa8..ab389b35987ec 100644 --- a/examples/with-gatsby/packages/typescript-config/package.json +++ b/examples/with-gatsby/packages/typescript-config/package.json @@ -1,11 +1,11 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "files": [ - "base.json", - "nextjs.json", - "gatsby.json", - "react-library.json" - ] + "name": "@repo/typescript-config", + "files": [ + "base.json", + "nextjs.json", + "gatsby.json", + "react-library.json" + ], + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-gatsby/packages/ui/.eslintrc.js b/examples/with-gatsby/packages/ui/.eslintrc.js deleted file mode 100644 index 05f04d6241724..0000000000000 --- a/examples/with-gatsby/packages/ui/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-gatsby/packages/ui/src/button.tsx b/examples/with-gatsby/packages/ui/Source/button.tsx similarity index 100% rename from examples/with-gatsby/packages/ui/src/button.tsx rename to examples/with-gatsby/packages/ui/Source/button.tsx diff --git a/examples/with-gatsby/packages/ui/package.json b/examples/with-gatsby/packages/ui/package.json index 669960bc3c5de..0e8ec45d74836 100644 --- a/examples/with-gatsby/packages/ui/package.json +++ b/examples/with-gatsby/packages/ui/package.json @@ -1,21 +1,12 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "exports": { - "./button": "./src/button.tsx" - }, - "scripts": { - "lint": "eslint . --max-warnings 0" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - } + "name": "@repo/ui", + "exports": { + "./button": "./src/button.tsx" + }, + "scripts": {}, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*" + } } diff --git a/examples/with-gatsby/pnpm-lock.yaml b/examples/with-gatsby/pnpm-lock.yaml deleted file mode 100644 index 774b70b59cae3..0000000000000 --- a/examples/with-gatsby/pnpm-lock.yaml +++ /dev/null @@ -1,10853 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - prettier: - specifier: ^3.2.5 - version: 3.2.5 - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/docs: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^14.1.1 - version: 14.1.4(react-dom@18.2.0)(react@18.2.0) - react: - specifier: 18.2.0 - version: 18.2.0 - react-dom: - specifier: 18.2.0 - version: 18.2.0(react@18.2.0) - devDependencies: - '@next/eslint-plugin-next': - specifier: ^14.1.1 - version: 14.1.4 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/node': - specifier: ^20.11.24 - version: 20.12.5 - '@types/react': - specifier: ^18.2.61 - version: 18.2.74 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.24 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - gatsby: - specifier: ^5.13.3 - version: 5.13.3(babel-eslint@10.1.0)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.4) - react: - specifier: ^18.2.0 - version: 18.2.0 - react-dom: - specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/node': - specifier: ^20.11.24 - version: 20.12.5 - '@types/react': - specifier: ^18.2.61 - version: 18.2.74 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.24 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - gatsby-plugin-compile-es6-packages: - specifier: ^2.1.1 - version: 2.1.1(gatsby@5.13.3) - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/eslint-config: - devDependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.5.0(@typescript-eslint/parser@7.5.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.5.0(eslint@8.57.0)(typescript@5.5.4) - '@vercel/style-guide': - specifier: ^5.2.0 - version: 5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - eslint-config-turbo: - specifier: ^2.0.0 - version: 2.0.0(eslint@8.57.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/typescript-config: {} - - packages/ui: - dependencies: - react: - specifier: ^18.2.0 - version: 18.2.0 - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@types/react': - specifier: ^18.2.61 - version: 18.2.74 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.24 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - - /@ardatan/relay-compiler@12.0.0(graphql@16.8.1): - resolution: {integrity: sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==} - hasBin: true - peerDependencies: - graphql: '*' - dependencies: - '@babel/core': 7.24.4 - '@babel/generator': 7.24.4 - '@babel/parser': 7.24.4 - '@babel/runtime': 7.24.4 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - babel-preset-fbjs: 3.4.0(@babel/core@7.24.4) - chalk: 4.1.2 - fb-watchman: 2.0.2 - fbjs: 3.0.5 - glob: 7.2.3 - graphql: 16.8.1 - immutable: 3.7.6 - invariant: 2.2.4 - nullthrows: 1.1.1 - relay-runtime: 12.0.0 - signedsource: 1.0.0 - yargs: 15.4.1 - transitivePeerDependencies: - - encoding - - supports-color - - /@babel/code-frame@7.12.11: - resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} - dependencies: - '@babel/highlight': 7.24.2 - - /@babel/code-frame@7.24.2: - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.2 - picocolors: 1.0.0 - - /@babel/compat-data@7.24.4: - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} - engines: {node: '>=6.9.0'} - - /@babel/core@7.24.4: - resolution: {integrity: sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helpers': 7.24.4 - '@babel/parser': 7.24.4 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /@babel/eslint-parser@7.24.1(@babel/core@7.24.4)(eslint@7.32.0): - resolution: {integrity: sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 7.32.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - - /@babel/eslint-parser@7.24.1(@babel/core@7.24.4)(eslint@8.57.0): - resolution: {integrity: sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.24.4: - resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - - /@babel/helper-create-class-features-plugin@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.4) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - semver: 6.3.1 - - /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.4): - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - semver: 6.3.1 - - /@babel/helper-define-polyfill-provider@0.6.1(@babel/core@7.24.4): - resolution: {integrity: sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-member-expression-to-functions@7.23.0: - resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-module-imports@7.24.3: - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4): - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - - /@babel/helper-optimise-call-expression@7.22.5: - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-plugin-utils@7.24.0: - resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} - engines: {node: '>=6.9.0'} - - /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.24.4): - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.22.20 - - /@babel/helper-replace-supers@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-skip-transparent-expression-wrappers@7.22.5: - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/helper-string-parser@7.24.1: - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} - engines: {node: '>=6.9.0'} - - /@babel/helper-wrap-function@7.22.20: - resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.23.0 - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - - /@babel/helpers@7.24.4: - resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - transitivePeerDependencies: - - supports-color - - /@babel/highlight@7.24.2: - resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.0 - - /@babel/parser@7.24.4: - resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==} - engines: {node: '>=6.0.0'} - dependencies: - '@babel/types': 7.24.0 - - /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.24.1(@babel/core@7.24.4) - - /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.24.4): - resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.24.4): - resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.24.4): - resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) - - /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.24.4): - resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-transform-parameters': 7.24.1(@babel/core@7.24.4) - - /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.24.4): - resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.4): - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.4): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.4): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.4): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-import-assertions@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.4): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.4): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.4): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.4): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.4): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.4): - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-arrow-functions@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-async-generator-functions@7.24.3(@babel/core@7.24.4): - resolution: {integrity: sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.4) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4) - - /@babel/plugin-transform-async-to-generator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.4) - - /@babel/plugin-transform-block-scoped-functions@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-block-scoping@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-class-properties@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-class-static-block@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.4) - - /@babel/plugin-transform-classes@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.4) - '@babel/helper-split-export-declaration': 7.22.6 - globals: 11.12.0 - - /@babel/plugin-transform-computed-properties@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/template': 7.24.0 - - /@babel/plugin-transform-destructuring@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-dotall-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-duplicate-keys@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-dynamic-import@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-transform-exponentiation-operator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-export-namespace-from@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-transform-flow-strip-types@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-flow': 7.24.1(@babel/core@7.24.4) - - /@babel/plugin-transform-for-of@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - - /@babel/plugin-transform-function-name@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-json-strings@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-transform-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-logical-assignment-operators@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4) - - /@babel/plugin-transform-member-expression-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-modules-amd@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-simple-access': 7.22.5 - - /@babel/plugin-transform-modules-systemjs@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-validator-identifier': 7.22.20 - - /@babel/plugin-transform-modules-umd@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.24.4): - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-new-target@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-nullish-coalescing-operator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-transform-numeric-separator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) - - /@babel/plugin-transform-object-rest-spread@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-transform-parameters': 7.24.1(@babel/core@7.24.4) - - /@babel/plugin-transform-object-super@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.4) - - /@babel/plugin-transform-optional-catch-binding@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-transform-optional-chaining@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) - - /@babel/plugin-transform-parameters@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-private-methods@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-private-property-in-object@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.4) - - /@babel/plugin-transform-property-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-react-display-name@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.24.4): - resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.4) - - /@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4): - resolution: {integrity: sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/types': 7.24.0 - - /@babel/plugin-transform-react-pure-annotations@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - regenerator-transform: 0.15.2 - - /@babel/plugin-transform-reserved-words@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-runtime@7.24.3(@babel/core@7.24.4): - resolution: {integrity: sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.0 - babel-plugin-polyfill-corejs2: 0.4.10(@babel/core@7.24.4) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.4) - babel-plugin-polyfill-regenerator: 0.6.1(@babel/core@7.24.4) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /@babel/plugin-transform-shorthand-properties@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-spread@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - - /@babel/plugin-transform-sticky-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-template-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-typeof-symbol@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-typescript@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4) - - /@babel/plugin-transform-unicode-escapes@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-unicode-property-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-unicode-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/plugin-transform-unicode-sets-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - - /@babel/preset-env@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.4(@babel/core@7.24.4) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.4) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.4) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.4) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.4) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.4) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.4) - '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-async-generator-functions': 7.24.3(@babel/core@7.24.4) - '@babel/plugin-transform-async-to-generator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-block-scoping': 7.24.4(@babel/core@7.24.4) - '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-class-static-block': 7.24.4(@babel/core@7.24.4) - '@babel/plugin-transform-classes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-destructuring': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-dotall-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-duplicate-keys': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-dynamic-import': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-exponentiation-operator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-export-namespace-from': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-json-strings': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-logical-assignment-operators': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-amd': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-systemjs': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-umd': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.24.4) - '@babel/plugin-transform-new-target': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-numeric-separator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-object-rest-spread': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-optional-catch-binding': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-optional-chaining': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-parameters': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-private-property-in-object': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-regenerator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-reserved-words': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-sticky-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-typeof-symbol': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-escapes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-property-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-sets-regex': 7.24.1(@babel/core@7.24.4) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.4) - babel-plugin-polyfill-corejs2: 0.4.10(@babel/core@7.24.4) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.4) - babel-plugin-polyfill-regenerator: 0.6.1(@babel/core@7.24.4) - core-js-compat: 3.36.1 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.4): - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/types': 7.24.0 - esutils: 2.0.3 - - /@babel/preset-react@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-transform-react-display-name': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.4) - '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.4) - '@babel/plugin-transform-react-pure-annotations': 7.24.1(@babel/core@7.24.4) - - /@babel/preset-typescript@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-typescript': 7.24.4(@babel/core@7.24.4) - - /@babel/regjsgen@0.8.0: - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - - /@babel/runtime@7.24.4: - resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - - /@babel/traverse@7.24.1: - resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - /@babel/types@7.24.0: - resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - - /@builder.io/partytown@0.7.6: - resolution: {integrity: sha512-snXIGNiZpqjno3XYQN2lbBB+05hsQR/LSttbtIW1c0gmZ7Kh/DIo0YrxlDxCDulAMFPFM8J+4voLwvYepSj3sw==} - hasBin: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - /@eslint/eslintrc@0.4.3: - resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 7.3.1 - globals: 13.24.0 - ignore: 4.0.6 - import-fresh: 3.3.0 - js-yaml: 3.14.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - /@gatsbyjs/parcel-namer-relative-to-cwd@2.13.1(@parcel/core@2.8.3): - resolution: {integrity: sha512-ze0u/CAt6fKV2yQlExkBARi8oqA559lX6/GFWwdtD9S1J4h8Bje70Odl/bcIECvT/w9mWCCQEVtKLvqkraDopw==} - engines: {node: '>=18.0.0', parcel: 2.x} - dependencies: - '@babel/runtime': 7.24.4 - '@parcel/namer-default': 2.8.3(@parcel/core@2.8.3) - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - gatsby-core-utils: 4.13.1 - transitivePeerDependencies: - - '@parcel/core' - - /@gatsbyjs/reach-router@2.0.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-gmSZniS9/phwgEgpFARMpNg21PkYDZEpfgEzvkgpE/iku4uvXqCrxr86fXbTpI9mkrhKS1SCTYmLGe60VdHcdQ==} - peerDependencies: - react: 18.x - react-dom: 18.x - dependencies: - invariant: 2.2.4 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - - /@gatsbyjs/webpack-hot-middleware@2.25.3: - resolution: {integrity: sha512-ul17OZ8Dlw+ATRbnuU+kwxuAlq9lKbYz/2uBS1FLCdgoPTF1H2heP7HbUbgfMZbfRQNcCG2rMscMnr32ritCDw==} - dependencies: - ansi-html-community: 0.0.8 - html-entities: 2.5.2 - strip-ansi: 6.0.1 - - /@graphql-codegen/add@3.2.3(graphql@16.8.1): - resolution: {integrity: sha512-sQOnWpMko4JLeykwyjFTxnhqjd/3NOG2OyMuvK76Wnnwh8DRrNf2VEs2kmSvLl7MndMlOj7Kh5U154dVcvhmKQ==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.4.1 - - /@graphql-codegen/core@2.6.8(graphql@16.8.1): - resolution: {integrity: sha512-JKllNIipPrheRgl+/Hm/xuWMw9++xNQ12XJR/OHHgFopOg4zmN3TdlRSyYcv/K90hCFkkIwhlHFUQTfKrm8rxQ==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) - '@graphql-tools/schema': 9.0.19(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.4.1 - - /@graphql-codegen/plugin-helpers@2.7.2(graphql@16.8.1): - resolution: {integrity: sha512-kln2AZ12uii6U59OQXdjLk5nOlh1pHis1R98cDZGFnfaiAbX9V3fxcZ1MMJkB7qFUymTALzyjZoXXdyVmPMfRg==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-tools/utils': 8.13.1(graphql@16.8.1) - change-case-all: 1.0.14 - common-tags: 1.8.2 - graphql: 16.8.1 - import-from: 4.0.0 - lodash: 4.17.21 - tslib: 2.4.1 - - /@graphql-codegen/plugin-helpers@3.1.2(graphql@16.8.1): - resolution: {integrity: sha512-emOQiHyIliVOIjKVKdsI5MXj312zmRDwmHpyUTZMjfpvxq/UVAHUJIVdVf+lnjjrI+LXBTgMlTWTgHQfmICxjg==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - change-case-all: 1.0.15 - common-tags: 1.8.2 - graphql: 16.8.1 - import-from: 4.0.0 - lodash: 4.17.21 - tslib: 2.4.1 - - /@graphql-codegen/schema-ast@2.6.1(graphql@16.8.1): - resolution: {integrity: sha512-5TNW3b1IHJjCh07D2yQNGDQzUpUl2AD+GVe1Dzjqyx/d2Fn0TPMxLsHsKPS4Plg4saO8FK/QO70wLsP7fdbQ1w==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.4.1 - - /@graphql-codegen/typescript-operations@2.5.13(graphql@16.8.1): - resolution: {integrity: sha512-3vfR6Rx6iZU0JRt29GBkFlrSNTM6t+MSLF86ChvL4d/Jfo/JYAGuB3zNzPhirHYzJPCvLOAx2gy9ID1ltrpYiw==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) - '@graphql-codegen/typescript': 2.8.8(graphql@16.8.1) - '@graphql-codegen/visitor-plugin-common': 2.13.8(graphql@16.8.1) - auto-bind: 4.0.0 - graphql: 16.8.1 - tslib: 2.4.1 - transitivePeerDependencies: - - encoding - - supports-color - - /@graphql-codegen/typescript@2.8.8(graphql@16.8.1): - resolution: {integrity: sha512-A0oUi3Oy6+DormOlrTC4orxT9OBZkIglhbJBcDmk34jAKKUgesukXRd4yOhmTrnbchpXz2T8IAOFB3FWIaK4Rw==} - peerDependencies: - graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) - '@graphql-codegen/schema-ast': 2.6.1(graphql@16.8.1) - '@graphql-codegen/visitor-plugin-common': 2.13.8(graphql@16.8.1) - auto-bind: 4.0.0 - graphql: 16.8.1 - tslib: 2.4.1 - transitivePeerDependencies: - - encoding - - supports-color - - /@graphql-codegen/visitor-plugin-common@2.13.8(graphql@16.8.1): - resolution: {integrity: sha512-IQWu99YV4wt8hGxIbBQPtqRuaWZhkQRG2IZKbMoSvh0vGeWb3dB0n0hSgKaOOxDY+tljtOf9MTcUYvJslQucMQ==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) - '@graphql-tools/optimize': 1.4.0(graphql@16.8.1) - '@graphql-tools/relay-operation-optimizer': 6.5.18(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - auto-bind: 4.0.0 - change-case-all: 1.0.15 - dependency-graph: 0.11.0 - graphql: 16.8.1 - graphql-tag: 2.12.6(graphql@16.8.1) - parse-filepath: 1.0.2 - tslib: 2.4.1 - transitivePeerDependencies: - - encoding - - supports-color - - /@graphql-tools/code-file-loader@7.3.23(@babel/core@7.24.4)(graphql@16.8.1): - resolution: {integrity: sha512-8Wt1rTtyTEs0p47uzsPJ1vAtfAx0jmxPifiNdmo9EOCuUPyQGEbMaik/YkqZ7QUFIEYEQu+Vgfo8tElwOPtx5Q==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.24.4)(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - globby: 11.1.0 - graphql: 16.8.1 - tslib: 2.6.2 - unixify: 1.0.0 - transitivePeerDependencies: - - '@babel/core' - - supports-color - - /@graphql-tools/graphql-tag-pluck@7.5.2(@babel/core@7.24.4)(graphql@16.8.1): - resolution: {integrity: sha512-RW+H8FqOOLQw0BPXaahYepVSRjuOHw+7IL8Opaa5G5uYGOBxoXR7DceyQ7BcpMgktAOOmpDNQ2WtcboChOJSRA==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@babel/parser': 7.24.4 - '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.4) - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.6.2 - transitivePeerDependencies: - - '@babel/core' - - supports-color - - /@graphql-tools/load@7.8.14(graphql@16.8.1): - resolution: {integrity: sha512-ASQvP+snHMYm+FhIaLxxFgVdRaM0vrN9wW2BKInQpktwWTXVyk+yP5nQUCEGmn0RTdlPKrffBaigxepkEAJPrg==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@graphql-tools/schema': 9.0.19(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - p-limit: 3.1.0 - tslib: 2.6.2 - - /@graphql-tools/merge@8.4.2(graphql@16.8.1): - resolution: {integrity: sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.6.2 - - /@graphql-tools/optimize@1.4.0(graphql@16.8.1): - resolution: {integrity: sha512-dJs/2XvZp+wgHH8T5J2TqptT9/6uVzIYvA6uFACha+ufvdMBedkfR4b4GbT8jAKLRARiqRTxy3dctnwkTM2tdw==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - graphql: 16.8.1 - tslib: 2.6.2 - - /@graphql-tools/relay-operation-optimizer@6.5.18(graphql@16.8.1): - resolution: {integrity: sha512-mc5VPyTeV+LwiM+DNvoDQfPqwQYhPV/cl5jOBjTgSniyaq8/86aODfMkrE2OduhQ5E00hqrkuL2Fdrgk0w1QJg==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.6.2 - transitivePeerDependencies: - - encoding - - supports-color - - /@graphql-tools/schema@9.0.19(graphql@16.8.1): - resolution: {integrity: sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@graphql-tools/merge': 8.4.2(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.6.2 - value-or-promise: 1.0.12 - - /@graphql-tools/utils@8.13.1(graphql@16.8.1): - resolution: {integrity: sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - graphql: 16.8.1 - tslib: 2.6.2 - - /@graphql-tools/utils@9.2.1(graphql@16.8.1): - resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.6.2 - - /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): - resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - graphql: 16.8.1 - - /@hapi/hoek@9.3.0: - resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - - /@hapi/topo@5.1.0: - resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - dependencies: - '@hapi/hoek': 9.3.0 - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - /@humanwhocodes/config-array@0.5.0: - resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - /@humanwhocodes/object-schema@1.2.1: - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - /@jridgewell/source-map@0.3.6: - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - - /@lezer/common@1.2.1: - resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==} - - /@lezer/lr@1.4.0: - resolution: {integrity: sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==} - dependencies: - '@lezer/common': 1.2.1 - - /@lmdb/lmdb-darwin-arm64@2.5.2: - resolution: {integrity: sha512-+F8ioQIUN68B4UFiIBYu0QQvgb9FmlKw2ctQMSBfW2QBrZIxz9vD9jCGqTCPqZBRbPHAS/vG1zSXnKqnS2ch/A==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@lmdb/lmdb-darwin-arm64@2.5.3: - resolution: {integrity: sha512-RXwGZ/0eCqtCY8FLTM/koR60w+MXyvBUpToXiIyjOcBnC81tAlTUHrRUavCEWPI9zc9VgvpK3+cbumPyR8BSuA==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@lmdb/lmdb-darwin-x64@2.5.2: - resolution: {integrity: sha512-KvPH56KRLLx4KSfKBx0m1r7GGGUMXm0jrKmNE7plbHlesZMuPJICtn07HYgQhj1LNsK7Yqwuvnqh1QxhJnF1EA==} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@lmdb/lmdb-darwin-x64@2.5.3: - resolution: {integrity: sha512-337dNzh5yCdNCTk8kPfoU7jR3otibSlPDGW0vKZT97rKnQMb9tNdto3RtWoGPsQ8hKmlRZpojOJtmwjncq1MoA==} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@lmdb/lmdb-linux-arm64@2.5.2: - resolution: {integrity: sha512-aLl89VHL/wjhievEOlPocoefUyWdvzVrcQ/MHQYZm2JfV1jUsrbr/ZfkPPUFvZBf+VSE+Q0clWs9l29PCX1hTQ==} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@lmdb/lmdb-linux-arm64@2.5.3: - resolution: {integrity: sha512-VJw60Mdgb4n+L0fO1PqfB0C7TyEQolJAC8qpqvG3JoQwvyOv6LH7Ib/WE3wxEW9nuHmVz9jkK7lk5HfWWgoO1Q==} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@lmdb/lmdb-linux-arm@2.5.2: - resolution: {integrity: sha512-5kQAP21hAkfW5Bl+e0P57dV4dGYnkNIpR7f/GAh6QHlgXx+vp/teVj4PGRZaKAvt0GX6++N6hF8NnGElLDuIDw==} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@lmdb/lmdb-linux-arm@2.5.3: - resolution: {integrity: sha512-mU2HFJDGwECkoD9dHQEfeTG5mp8hNS2BCfwoiOpVPMeapjYpQz9Uw3FkUjRZ4dGHWKbin40oWHuL0bk2bCx+Sg==} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@lmdb/lmdb-linux-x64@2.5.2: - resolution: {integrity: sha512-xUdUfwDJLGjOUPH3BuPBt0NlIrR7f/QHKgu3GZIXswMMIihAekj2i97oI0iWG5Bok/b+OBjHPfa8IU9velnP/Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@lmdb/lmdb-linux-x64@2.5.3: - resolution: {integrity: sha512-qaReO5aV8griBDsBr8uBF/faO3ieGjY1RY4p8JvTL6Mu1ylLrTVvOONqKFlNaCwrmUjWw5jnf7VafxDAeQHTow==} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@lmdb/lmdb-win32-x64@2.5.2: - resolution: {integrity: sha512-zrBczSbXKxEyK2ijtbRdICDygRqWSRPpZMN5dD1T8VMEW5RIhIbwFWw2phDRXuBQdVDpSjalCIUMWMV2h3JaZA==} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@lmdb/lmdb-win32-x64@2.5.3: - resolution: {integrity: sha512-cK+Elf3RjEzrm3SerAhrFWL5oQAsZSJ/LmjL1joIpTfEP1etJJ9CTRvdaV6XLYAxaEkfdhk/9hOvHLbR9yIhCA==} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true - - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true - - /@mischnic/json-sourcemap@0.1.1: - resolution: {integrity: sha512-iA7+tyVqfrATAIsIRWQG+a7ZLLD0VaOCKV2Wd/v4mqIU3J9c4jx9p7S0nw1XH3gJCKNBOOwACOPYYSUu9pgT+w==} - engines: {node: '>=12.0.0'} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/lr': 1.4.0 - json5: 2.2.3 - - /@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.2: - resolution: {integrity: sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.2: - resolution: {integrity: sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.2: - resolution: {integrity: sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@msgpackr-extract/msgpackr-extract-linux-arm@3.0.2: - resolution: {integrity: sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@msgpackr-extract/msgpackr-extract-linux-x64@3.0.2: - resolution: {integrity: sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@msgpackr-extract/msgpackr-extract-win32-x64@3.0.2: - resolution: {integrity: sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@next/env@14.1.4: - resolution: {integrity: sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ==} - dev: false - - /@next/eslint-plugin-next@14.1.4: - resolution: {integrity: sha512-n4zYNLSyCo0Ln5b7qxqQeQ34OZKXwgbdcx6kmkQbywr+0k6M3Vinft0T72R6CDAcDrne2IAgSud4uWCzFgc5HA==} - dependencies: - glob: 10.3.10 - dev: true - - /@next/swc-darwin-arm64@14.1.4: - resolution: {integrity: sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64@14.1.4: - resolution: {integrity: sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu@14.1.4: - resolution: {integrity: sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl@14.1.4: - resolution: {integrity: sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu@14.1.4: - resolution: {integrity: sha512-BapIFZ3ZRnvQ1uWbmqEGJuPT9cgLwvKtxhK/L2t4QYO7l+/DxXuIGjvp1x8rvfa/x1FFSsipERZK70pewbtJtw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl@14.1.4: - resolution: {integrity: sha512-mqVxTwk4XuBl49qn2A5UmzFImoL1iLm0KQQwtdRJRKl21ylQwwGCxJtIYo2rbfkZHoSKlh/YgztY0qH3wG1xIg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc@14.1.4: - resolution: {integrity: sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-ia32-msvc@14.1.4: - resolution: {integrity: sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc@14.1.4: - resolution: {integrity: sha512-4Rto21sPfw555sZ/XNLqfxDUNeLhNYGO2dlPqsnuCg8N8a2a9u1ltqBOPQ4vj1Gf7eJC0W2hHG2eYUHuiXgY2w==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - - /@parcel/bundler-default@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-yJvRsNWWu5fVydsWk3O2L4yIy3UZiKWO2cPDukGOIWMgp/Vbpp+2Ct5IygVRtE22bnseW/E/oe0PV3d2IkEJGg==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/diagnostic': 2.8.3 - '@parcel/graph': 2.8.3 - '@parcel/hash': 2.8.3 - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - '@parcel/utils': 2.8.3 - nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/cache@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-k7xv5vSQrJLdXuglo+Hv3yF4BCSs1tQ/8Vbd6CHTkOhf7LcGg6CPtLw053R/KdMpd/4GPn0QrAsOLdATm1ELtQ==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@parcel/core': ^2.8.3 - dependencies: - '@parcel/core': 2.8.3 - '@parcel/fs': 2.8.3(@parcel/core@2.8.3) - '@parcel/logger': 2.8.3 - '@parcel/utils': 2.8.3 - lmdb: 2.5.2 - - /@parcel/codeframe@2.8.3: - resolution: {integrity: sha512-FE7sY53D6n/+2Pgg6M9iuEC6F5fvmyBkRE4d9VdnOoxhTXtkEqpqYgX7RJ12FAQwNlxKq4suBJQMgQHMF2Kjeg==} - engines: {node: '>= 12.0.0'} - dependencies: - chalk: 4.1.2 - - /@parcel/compressor-raw@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-bVDsqleBUxRdKMakWSlWC9ZjOcqDKE60BE+Gh3JSN6WJrycJ02P5wxjTVF4CStNP/G7X17U+nkENxSlMG77ySg==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/core@2.8.3: - resolution: {integrity: sha512-Euf/un4ZAiClnlUXqPB9phQlKbveU+2CotZv7m7i+qkgvFn5nAGnrV4h1OzQU42j9dpgOxWi7AttUDMrvkbhCQ==} - engines: {node: '>= 12.0.0'} - dependencies: - '@mischnic/json-sourcemap': 0.1.1 - '@parcel/cache': 2.8.3(@parcel/core@2.8.3) - '@parcel/diagnostic': 2.8.3 - '@parcel/events': 2.8.3 - '@parcel/fs': 2.8.3(@parcel/core@2.8.3) - '@parcel/graph': 2.8.3 - '@parcel/hash': 2.8.3 - '@parcel/logger': 2.8.3 - '@parcel/package-manager': 2.8.3(@parcel/core@2.8.3) - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - '@parcel/source-map': 2.1.1 - '@parcel/types': 2.8.3(@parcel/core@2.8.3) - '@parcel/utils': 2.8.3 - '@parcel/workers': 2.8.3(@parcel/core@2.8.3) - abortcontroller-polyfill: 1.7.5 - base-x: 3.0.9 - browserslist: 4.23.0 - clone: 2.1.2 - dotenv: 7.0.0 - dotenv-expand: 5.1.0 - json5: 2.2.3 - msgpackr: 1.10.1 - nullthrows: 1.1.1 - semver: 5.7.2 - - /@parcel/diagnostic@2.8.3: - resolution: {integrity: sha512-u7wSzuMhLGWZjVNYJZq/SOViS3uFG0xwIcqXw12w54Uozd6BH8JlhVtVyAsq9kqnn7YFkw6pXHqAo5Tzh4FqsQ==} - engines: {node: '>= 12.0.0'} - dependencies: - '@mischnic/json-sourcemap': 0.1.1 - nullthrows: 1.1.1 - - /@parcel/events@2.8.3: - resolution: {integrity: sha512-hoIS4tAxWp8FJk3628bsgKxEvR7bq2scCVYHSqZ4fTi/s0+VymEATrRCUqf+12e5H47uw1/ZjoqrGtBI02pz4w==} - engines: {node: '>= 12.0.0'} - - /@parcel/fs-search@2.8.3: - resolution: {integrity: sha512-DJBT2N8knfN7Na6PP2mett3spQLTqxFrvl0gv+TJRp61T8Ljc4VuUTb0hqBj+belaASIp3Q+e8+SgaFQu7wLiQ==} - engines: {node: '>= 12.0.0'} - dependencies: - detect-libc: 1.0.3 - - /@parcel/fs@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-y+i+oXbT7lP0e0pJZi/YSm1vg0LDsbycFuHZIL80pNwdEppUAtibfJZCp606B7HOjMAlNZOBo48e3hPG3d8jgQ==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@parcel/core': ^2.8.3 - dependencies: - '@parcel/core': 2.8.3 - '@parcel/fs-search': 2.8.3 - '@parcel/types': 2.8.3(@parcel/core@2.8.3) - '@parcel/utils': 2.8.3 - '@parcel/watcher': 2.4.1 - '@parcel/workers': 2.8.3(@parcel/core@2.8.3) - - /@parcel/graph@2.8.3: - resolution: {integrity: sha512-26GL8fYZPdsRhSXCZ0ZWliloK6DHlMJPWh6Z+3VVZ5mnDSbYg/rRKWmrkhnr99ZWmL9rJsv4G74ZwvDEXTMPBg==} - engines: {node: '>= 12.0.0'} - dependencies: - nullthrows: 1.1.1 - - /@parcel/hash@2.8.3: - resolution: {integrity: sha512-FVItqzjWmnyP4ZsVgX+G00+6U2IzOvqDtdwQIWisCcVoXJFCqZJDy6oa2qDDFz96xCCCynjRjPdQx2jYBCpfYw==} - engines: {node: '>= 12.0.0'} - dependencies: - detect-libc: 1.0.3 - xxhash-wasm: 0.4.2 - - /@parcel/logger@2.8.3: - resolution: {integrity: sha512-Kpxd3O/Vs7nYJIzkdmB6Bvp3l/85ydIxaZaPfGSGTYOfaffSOTkhcW9l6WemsxUrlts4za6CaEWcc4DOvaMOPA==} - engines: {node: '>= 12.0.0'} - dependencies: - '@parcel/diagnostic': 2.8.3 - '@parcel/events': 2.8.3 - - /@parcel/markdown-ansi@2.8.3: - resolution: {integrity: sha512-4v+pjyoh9f5zuU/gJlNvNFGEAb6J90sOBwpKJYJhdWXLZMNFCVzSigxrYO+vCsi8G4rl6/B2c0LcwIMjGPHmFQ==} - engines: {node: '>= 12.0.0'} - dependencies: - chalk: 4.1.2 - - /@parcel/namer-default@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-tJ7JehZviS5QwnxbARd8Uh63rkikZdZs1QOyivUhEvhN+DddSAVEdQLHGPzkl3YRk0tjFhbqo+Jci7TpezuAMw==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/diagnostic': 2.8.3 - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/node-resolver-core@2.8.3: - resolution: {integrity: sha512-12YryWcA5Iw2WNoEVr/t2HDjYR1iEzbjEcxfh1vaVDdZ020PiGw67g5hyIE/tsnG7SRJ0xdRx1fQ2hDgED+0Ww==} - engines: {node: '>= 12.0.0'} - dependencies: - '@parcel/diagnostic': 2.8.3 - '@parcel/utils': 2.8.3 - nullthrows: 1.1.1 - semver: 5.7.2 - - /@parcel/optimizer-terser@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-9EeQlN6zIeUWwzrzu6Q2pQSaYsYGah8MtiQ/hog9KEPlYTP60hBv/+utDyYEHSQhL7y5ym08tPX5GzBvwAD/dA==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/diagnostic': 2.8.3 - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - '@parcel/source-map': 2.1.1 - '@parcel/utils': 2.8.3 - nullthrows: 1.1.1 - terser: 5.30.3 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/package-manager@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-tIpY5pD2lH53p9hpi++GsODy6V3khSTX4pLEGuMpeSYbHthnOViobqIlFLsjni+QA1pfc8NNNIQwSNdGjYflVA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@parcel/core': ^2.8.3 - dependencies: - '@parcel/core': 2.8.3 - '@parcel/diagnostic': 2.8.3 - '@parcel/fs': 2.8.3(@parcel/core@2.8.3) - '@parcel/logger': 2.8.3 - '@parcel/types': 2.8.3(@parcel/core@2.8.3) - '@parcel/utils': 2.8.3 - '@parcel/workers': 2.8.3(@parcel/core@2.8.3) - semver: 5.7.2 - - /@parcel/packager-js@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-0pGKC3Ax5vFuxuZCRB+nBucRfFRz4ioie19BbDxYnvBxrd4M3FIu45njf6zbBYsI9eXqaDnL1b3DcZJfYqtIzw==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/diagnostic': 2.8.3 - '@parcel/hash': 2.8.3 - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - '@parcel/source-map': 2.1.1 - '@parcel/utils': 2.8.3 - globals: 13.24.0 - nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/packager-raw@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-BA6enNQo1RCnco9MhkxGrjOk59O71IZ9DPKu3lCtqqYEVd823tXff2clDKHK25i6cChmeHu6oB1Rb73hlPqhUA==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/plugin@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-jZ6mnsS4D9X9GaNnvrixDQwlUQJCohDX2hGyM0U0bY2NWU8Km97SjtoCpWjq+XBCx/gpC4g58+fk9VQeZq2vlw==} - engines: {node: '>= 12.0.0'} - dependencies: - '@parcel/types': 2.8.3(@parcel/core@2.8.3) - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/reporter-dev-server@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-Y8C8hzgzTd13IoWTj+COYXEyCkXfmVJs3//GDBsH22pbtSFMuzAZd+8J9qsCo0EWpiDow7V9f1LischvEh3FbQ==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - '@parcel/utils': 2.8.3 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/resolver-default@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-k0B5M/PJ+3rFbNj4xZSBr6d6HVIe6DH/P3dClLcgBYSXAvElNDfXgtIimbjCyItFkW9/BfcgOVKEEIZOeySH/A==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/node-resolver-core': 2.8.3 - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/runtime-js@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-IRja0vNKwvMtPgIqkBQh0QtRn0XcxNC8HU1jrgWGRckzu10qJWO+5ULgtOeR4pv9krffmMPqywGXw6l/gvJKYQ==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - '@parcel/utils': 2.8.3 - nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/source-map@2.1.1: - resolution: {integrity: sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==} - engines: {node: ^12.18.3 || >=14} - dependencies: - detect-libc: 1.0.3 - - /@parcel/transformer-js@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-9Qd6bib+sWRcpovvzvxwy/PdFrLUXGfmSW9XcVVG8pvgXsZPFaNjnNT8stzGQj1pQiougCoxMY4aTM5p1lGHEQ==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - peerDependencies: - '@parcel/core': ^2.8.3 - dependencies: - '@parcel/core': 2.8.3 - '@parcel/diagnostic': 2.8.3 - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - '@parcel/source-map': 2.1.1 - '@parcel/utils': 2.8.3 - '@parcel/workers': 2.8.3(@parcel/core@2.8.3) - '@swc/helpers': 0.4.36 - browserslist: 4.23.0 - detect-libc: 1.0.3 - nullthrows: 1.1.1 - regenerator-runtime: 0.13.11 - semver: 5.7.2 - - /@parcel/transformer-json@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-B7LmVq5Q7bZO4ERb6NHtRuUKWGysEeaj9H4zelnyBv+wLgpo4f5FCxSE1/rTNmP9u1qHvQ3scGdK6EdSSokGPg==} - engines: {node: '>= 12.0.0', parcel: ^2.8.3} - dependencies: - '@parcel/plugin': 2.8.3(@parcel/core@2.8.3) - json5: 2.2.3 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/types@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-FECA1FB7+0UpITKU0D6TgGBpGxYpVSMNEENZbSJxFSajNy3wrko+zwBKQmFOLOiPcEtnGikxNs+jkFWbPlUAtw==} - dependencies: - '@parcel/cache': 2.8.3(@parcel/core@2.8.3) - '@parcel/diagnostic': 2.8.3 - '@parcel/fs': 2.8.3(@parcel/core@2.8.3) - '@parcel/package-manager': 2.8.3(@parcel/core@2.8.3) - '@parcel/source-map': 2.1.1 - '@parcel/workers': 2.8.3(@parcel/core@2.8.3) - utility-types: 3.11.0 - transitivePeerDependencies: - - '@parcel/core' - - /@parcel/utils@2.8.3: - resolution: {integrity: sha512-IhVrmNiJ+LOKHcCivG5dnuLGjhPYxQ/IzbnF2DKNQXWBTsYlHkJZpmz7THoeLtLliGmSOZ3ZCsbR8/tJJKmxjA==} - engines: {node: '>= 12.0.0'} - dependencies: - '@parcel/codeframe': 2.8.3 - '@parcel/diagnostic': 2.8.3 - '@parcel/hash': 2.8.3 - '@parcel/logger': 2.8.3 - '@parcel/markdown-ansi': 2.8.3 - '@parcel/source-map': 2.1.1 - chalk: 4.1.2 - - /@parcel/watcher-android-arm64@2.4.1: - resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - - /@parcel/watcher-darwin-arm64@2.4.1: - resolution: {integrity: sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@parcel/watcher-darwin-x64@2.4.1: - resolution: {integrity: sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@parcel/watcher-freebsd-x64@2.4.1: - resolution: {integrity: sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /@parcel/watcher-linux-arm-glibc@2.4.1: - resolution: {integrity: sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==} - engines: {node: '>= 10.0.0'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@parcel/watcher-linux-arm64-glibc@2.4.1: - resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@parcel/watcher-linux-arm64-musl@2.4.1: - resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@parcel/watcher-linux-x64-glibc@2.4.1: - resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@parcel/watcher-linux-x64-musl@2.4.1: - resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@parcel/watcher-win32-arm64@2.4.1: - resolution: {integrity: sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@parcel/watcher-win32-ia32@2.4.1: - resolution: {integrity: sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==} - engines: {node: '>= 10.0.0'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@parcel/watcher-win32-x64@2.4.1: - resolution: {integrity: sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@parcel/watcher@2.4.1: - resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} - engines: {node: '>= 10.0.0'} - dependencies: - detect-libc: 1.0.3 - is-glob: 4.0.3 - micromatch: 4.0.5 - node-addon-api: 7.1.0 - optionalDependencies: - '@parcel/watcher-android-arm64': 2.4.1 - '@parcel/watcher-darwin-arm64': 2.4.1 - '@parcel/watcher-darwin-x64': 2.4.1 - '@parcel/watcher-freebsd-x64': 2.4.1 - '@parcel/watcher-linux-arm-glibc': 2.4.1 - '@parcel/watcher-linux-arm64-glibc': 2.4.1 - '@parcel/watcher-linux-arm64-musl': 2.4.1 - '@parcel/watcher-linux-x64-glibc': 2.4.1 - '@parcel/watcher-linux-x64-musl': 2.4.1 - '@parcel/watcher-win32-arm64': 2.4.1 - '@parcel/watcher-win32-ia32': 2.4.1 - '@parcel/watcher-win32-x64': 2.4.1 - - /@parcel/workers@2.8.3(@parcel/core@2.8.3): - resolution: {integrity: sha512-+AxBnKgjqVpUHBcHLWIHcjYgKIvHIpZjN33mG5LG9XXvrZiqdWvouEzqEXlVLq5VzzVbKIQQcmsvRy138YErkg==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@parcel/core': ^2.8.3 - dependencies: - '@parcel/core': 2.8.3 - '@parcel/diagnostic': 2.8.3 - '@parcel/logger': 2.8.3 - '@parcel/types': 2.8.3(@parcel/core@2.8.3) - '@parcel/utils': 2.8.3 - chrome-trace-event: 1.0.3 - nullthrows: 1.1.1 - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@pkgr/core@0.1.1: - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true - - /@pmmmwh/react-refresh-webpack-plugin@0.5.11(react-refresh@0.14.0)(webpack@5.91.0): - resolution: {integrity: sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ==} - engines: {node: '>= 10.13'} - peerDependencies: - '@types/webpack': 4.x || 5.x - react-refresh: '>=0.10.0 <1.0.0' - sockjs-client: ^1.4.0 - type-fest: '>=0.17.0 <5.0.0' - webpack: '>=4.43.0 <6.0.0' - webpack-dev-server: 3.x || 4.x - webpack-hot-middleware: 2.x - webpack-plugin-serve: 0.x || 1.x - peerDependenciesMeta: - '@types/webpack': - optional: true - sockjs-client: - optional: true - type-fest: - optional: true - webpack-dev-server: - optional: true - webpack-hot-middleware: - optional: true - webpack-plugin-serve: - optional: true - dependencies: - ansi-html-community: 0.0.8 - common-path-prefix: 3.0.0 - core-js-pure: 3.36.1 - error-stack-parser: 2.1.4 - find-up: 5.0.0 - html-entities: 2.5.2 - loader-utils: 2.0.4 - react-refresh: 0.14.0 - schema-utils: 3.3.0 - source-map: 0.7.4 - webpack: 5.91.0 - - /@pnpm/config.env-replace@1.1.0: - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} - - /@pnpm/network.ca-file@1.0.2: - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} - dependencies: - graceful-fs: 4.2.10 - - /@pnpm/npm-conf@2.2.2: - resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} - engines: {node: '>=12'} - dependencies: - '@pnpm/config.env-replace': 1.1.0 - '@pnpm/network.ca-file': 1.0.2 - config-chain: 1.1.13 - - /@rushstack/eslint-patch@1.10.1: - resolution: {integrity: sha512-S3Kq8e7LqxkA9s7HKLqXGTGck1uwis5vAXan3FnU5yw1Ec5hsSGnq4s/UCaSqABPOnOTg7zASLyst7+ohgWexg==} - dev: true - - /@sideway/address@4.1.5: - resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} - dependencies: - '@hapi/hoek': 9.3.0 - - /@sideway/formula@3.0.1: - resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} - - /@sideway/pinpoint@2.0.0: - resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - - /@sigmacomputing/babel-plugin-lodash@3.3.5: - resolution: {integrity: sha512-VFhaHjlNzWyBtBm3YdqOwP8GbQHK7sWzXKpSUBTLjl2Zz6/9PwCK4qXZXI5CHpDjmvbouHUDbjrZP2KU5h6VQg==} - dependencies: - '@babel/helper-module-imports': 7.24.3 - '@babel/types': 7.24.0 - glob: 7.2.3 - lodash: 4.17.21 - require-package-name: 2.0.1 - - /@sindresorhus/is@4.6.0: - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} - - /@sindresorhus/is@5.6.0: - resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} - engines: {node: '>=14.16'} - - /@sindresorhus/slugify@1.1.2: - resolution: {integrity: sha512-V9nR/W0Xd9TSGXpZ4iFUcFGhuOJtZX82Fzxj1YISlbSgKvIiNa7eLEZrT0vAraPOt++KHauIVNYgGRgjc13dXA==} - engines: {node: '>=10'} - dependencies: - '@sindresorhus/transliterate': 0.1.2 - escape-string-regexp: 4.0.0 - - /@sindresorhus/transliterate@0.1.2: - resolution: {integrity: sha512-5/kmIOY9FF32nicXH+5yLNTX4NJ4atl7jRgqAJuIn/iyDFXBktOKDxCvyGE/EzmF4ngSUvjXxQUQlQiZ5lfw+w==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - lodash.deburr: 4.1.0 - - /@socket.io/component-emitter@3.1.0: - resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} - - /@swc/helpers@0.4.14: - resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==} - dependencies: - tslib: 2.6.2 - - /@swc/helpers@0.4.36: - resolution: {integrity: sha512-5lxnyLEYFskErRPenYItLRSge5DjrJngYKdVjRSrWfza9G6KkgHEXi0vUZiyUeMU5JfXH1YnvXZzSp8ul88o2Q==} - dependencies: - legacy-swc-helpers: /@swc/helpers@0.4.14 - tslib: 2.6.2 - - /@swc/helpers@0.5.2: - resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} - dependencies: - tslib: 2.6.2 - dev: false - - /@szmarczak/http-timer@4.0.6: - resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} - engines: {node: '>=10'} - dependencies: - defer-to-connect: 2.0.1 - - /@szmarczak/http-timer@5.0.1: - resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} - engines: {node: '>=14.16'} - dependencies: - defer-to-connect: 2.0.1 - - /@tokenizer/token@0.3.0: - resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - - /@trysound/sax@0.2.0: - resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} - engines: {node: '>=10.13.0'} - - /@turist/fetch@7.2.0(node-fetch@2.7.0): - resolution: {integrity: sha512-2x7EGw+6OJ29phunsbGvtxlNmSfcuPcyYudkMbi8gARCP9eJ1CtuMvnVUHL//O9Ixi9SJiug8wNt6lj86pN8XQ==} - peerDependencies: - node-fetch: '2' - dependencies: - '@types/node-fetch': 2.6.11 - node-fetch: 2.7.0 - - /@turist/time@0.0.2: - resolution: {integrity: sha512-qLOvfmlG2vCVw5fo/oz8WAZYlpe5a5OurgTj3diIxJCdjRHpapC+vQCz3er9LV79Vcat+DifBjeAhOAdmndtDQ==} - - /@types/cacheable-request@6.0.3: - resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - dependencies: - '@types/http-cache-semantics': 4.0.4 - '@types/keyv': 3.1.4 - '@types/node': 20.12.5 - '@types/responselike': 1.0.3 - - /@types/common-tags@1.8.4: - resolution: {integrity: sha512-S+1hLDJPjWNDhcGxsxEbepzaxWqURP/o+3cP4aa2w7yBXgdcmKGQtZzP8JbyfOd0m+33nh+8+kvxYE2UJtBDkg==} - - /@types/configstore@2.1.1: - resolution: {integrity: sha512-YY+hm3afkDHeSM2rsFXxeZtu0garnusBWNG1+7MknmDWQHqcH2w21/xOU9arJUi8ch4qyFklidANLCu3ihhVwQ==} - - /@types/cookie@0.4.1: - resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} - - /@types/cors@2.8.17: - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - dependencies: - '@types/node': 20.12.5 - - /@types/debug@0.0.30: - resolution: {integrity: sha512-orGL5LXERPYsLov6CWs3Fh6203+dXzJkR7OnddIr2514Hsecwc8xRpzCapshBbKFImCsvS/mk6+FWiN5LyZJAQ==} - - /@types/eslint-scope@3.7.7: - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - dependencies: - '@types/eslint': 8.56.7 - '@types/estree': 1.0.5 - - /@types/eslint@7.29.0: - resolution: {integrity: sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - - /@types/eslint@8.56.7: - resolution: {integrity: sha512-SjDvI/x3zsZnOkYZ3lCt9lOZWZLB2jIlNKz+LBgCtDurK0JZcwucxYHn1w2BJkD34dgX9Tjnak0txtq4WTggEA==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - - /@types/get-port@3.2.0: - resolution: {integrity: sha512-TiNg8R1kjDde5Pub9F9vCwZA/BNW9HeXP5b9j7Qucqncy/McfPZ6xze/EyBdXS5FhMIGN6Fx3vg75l5KHy3V1Q==} - - /@types/glob@5.0.38: - resolution: {integrity: sha512-rTtf75rwyP9G2qO5yRpYtdJ6aU1QqEhWbtW55qEgquEDa6bXW0s2TWZfDm02GuppjEozOWG/F2UnPq5hAQb+gw==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 20.12.5 - - /@types/glob@8.1.0: - resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 20.12.5 - - /@types/http-cache-semantics@4.0.4: - resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - - /@types/http-proxy@1.17.14: - resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} - dependencies: - '@types/node': 20.12.5 - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - /@types/keyv@3.1.4: - resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - dependencies: - '@types/node': 20.12.5 - - /@types/lodash@4.17.0: - resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==} - - /@types/minimatch@5.1.2: - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - - /@types/mkdirp@0.5.2: - resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} - dependencies: - '@types/node': 20.12.5 - - /@types/node-fetch@2.6.11: - resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} - dependencies: - '@types/node': 20.12.5 - form-data: 4.0.0 - - /@types/node@20.12.5: - resolution: {integrity: sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==} - dependencies: - undici-types: 5.26.5 - - /@types/node@8.10.66: - resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} - - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: true - - /@types/parse-json@4.0.2: - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - - /@types/prop-types@15.7.12: - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - - /@types/reach__router@1.3.15: - resolution: {integrity: sha512-5WEHKGglRjq/Ae3F8UQxg+GYUIhTUEiyBT9GKPoOLU/vPTn8iZrRbdzxqvarOaGludIejJykHLMdOCdhgWqaxA==} - dependencies: - '@types/react': 18.2.74 - - /@types/react-dom@18.2.24: - resolution: {integrity: sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==} - dependencies: - '@types/react': 18.2.74 - dev: true - - /@types/react@18.2.74: - resolution: {integrity: sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==} - dependencies: - '@types/prop-types': 15.7.12 - csstype: 3.1.3 - - /@types/responselike@1.0.3: - resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} - dependencies: - '@types/node': 20.12.5 - - /@types/rimraf@2.0.5: - resolution: {integrity: sha512-YyP+VfeaqAyFmXoTh3HChxOQMyjByRMsHU7kc5KOJkSlXudhMhQIALbYV7rHh/l8d2lX3VUQzprrcAgWdRuU8g==} - dependencies: - '@types/glob': 8.1.0 - '@types/node': 20.12.5 - - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - - /@types/tmp@0.0.33: - resolution: {integrity: sha512-gVC1InwyVrO326wbBZw+AO3u2vRXz/iRWq9jYhpG4W8LXyIgDv3ZmcLQ5Q4Gs+gFMyqx+viFoFT+l3p61QFCmQ==} - - /@types/yoga-layout@1.9.2: - resolution: {integrity: sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==} - - /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare-lite: 1.4.0 - semver: 7.6.0 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/eslint-plugin@7.5.0(@typescript-eslint/parser@7.5.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.5.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 7.5.0 - '@typescript-eslint/type-utils': 7.5.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.5.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.5.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - /@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.5.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.5.0 - '@typescript-eslint/types': 7.5.0 - '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.5.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - - /@typescript-eslint/scope-manager@6.21.0: - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - dev: true - - /@typescript-eslint/scope-manager@7.5.0: - resolution: {integrity: sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.5.0 - '@typescript-eslint/visitor-keys': 7.5.0 - dev: true - - /@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - /@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/type-utils@7.5.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.5.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - /@typescript-eslint/types@6.21.0: - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/types@7.5.0: - resolution: {integrity: sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==} - engines: {node: ^18.18.0 || >=20.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.4): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.0 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - /@typescript-eslint/typescript-estree@6.21.0(typescript@5.5.4): - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@7.5.0(typescript@5.5.4): - resolution: {integrity: sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.5.0 - '@typescript-eslint/visitor-keys': 7.5.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - - /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@7.5.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.5.0 - '@typescript-eslint/types': 7.5.0 - '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - - /@typescript-eslint/visitor-keys@6.21.0: - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.5.0: - resolution: {integrity: sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.5.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - - /@vercel/style-guide@5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4): - resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} - engines: {node: '>=16'} - peerDependencies: - '@next/eslint-plugin-next': '>=12.3.0 <15' - eslint: '>=8.48.0 <9' - prettier: '>=3.0.0 <4' - typescript: '>=4.8.0 <6' - peerDependenciesMeta: - '@next/eslint-plugin-next': - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - dependencies: - '@babel/core': 7.24.4 - '@babel/eslint-parser': 7.24.1(@babel/core@7.24.4)(eslint@8.57.0) - '@rushstack/eslint-patch': 1.10.1 - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) - eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.1) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.5.0)(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0) - eslint-plugin-react: 7.34.1(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) - eslint-plugin-testing-library: 6.2.0(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) - prettier: 3.2.5 - prettier-plugin-packagejson: 2.4.14(prettier@3.2.5) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /@vercel/webpack-asset-relocator-loader@1.7.3: - resolution: {integrity: sha512-vizrI18v8Lcb1PmNNUBz7yxPxxXoOeuaVEjTG9MjvDrphjiSxFZrRJ5tIghk+qdLFRCXI5HBCshgobftbmrC5g==} - dependencies: - resolve: 1.22.8 - - /@webassemblyjs/ast@1.12.1: - resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} - dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - - /@webassemblyjs/floating-point-hex-parser@1.11.6: - resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} - - /@webassemblyjs/helper-api-error@1.11.6: - resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} - - /@webassemblyjs/helper-buffer@1.12.1: - resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} - - /@webassemblyjs/helper-numbers@1.11.6: - resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 - '@xtuc/long': 4.2.2 - - /@webassemblyjs/helper-wasm-bytecode@1.11.6: - resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} - - /@webassemblyjs/helper-wasm-section@1.12.1: - resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 - - /@webassemblyjs/ieee754@1.11.6: - resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} - dependencies: - '@xtuc/ieee754': 1.2.0 - - /@webassemblyjs/leb128@1.11.6: - resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} - dependencies: - '@xtuc/long': 4.2.2 - - /@webassemblyjs/utf8@1.11.6: - resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} - - /@webassemblyjs/wasm-edit@1.12.1: - resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 - - /@webassemblyjs/wasm-gen@1.12.1: - resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - - /@webassemblyjs/wasm-opt@1.12.1: - resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - - /@webassemblyjs/wasm-parser@1.12.1: - resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - - /@webassemblyjs/wast-printer@1.12.1: - resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@xtuc/long': 4.2.2 - - /@xtuc/ieee754@1.2.0: - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - - /@xtuc/long@4.2.2: - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - - /abortcontroller-polyfill@1.7.5: - resolution: {integrity: sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==} - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - - /acorn-import-assertions@1.9.0(acorn@8.11.3): - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} - peerDependencies: - acorn: ^8 - dependencies: - acorn: 8.11.3 - - /acorn-jsx@5.3.2(acorn@7.4.1): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 7.4.1 - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - - /acorn-loose@8.4.0: - resolution: {integrity: sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==} - engines: {node: '>=0.4.0'} - dependencies: - acorn: 8.11.3 - - /acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} - engines: {node: '>=0.4.0'} - - /acorn@6.4.2: - resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==} - engines: {node: '>=0.4.0'} - hasBin: true - - /acorn@7.4.1: - resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} - engines: {node: '>=0.4.0'} - hasBin: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - - /address@1.2.2: - resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} - engines: {node: '>= 10.0.0'} - - /ajv-keywords@3.5.2(ajv@6.12.6): - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - dependencies: - ajv: 6.12.6 - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - - /anser@2.1.1: - resolution: {integrity: sha512-nqLm4HxOTpeLOxcmB3QWmV5TcDFhW9y/fyQ+hivtDFcK4OQ+pQ5fzPnXHM1Mfcm0VkLtvVi1TCPr++Qy0Q/3EQ==} - - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - dependencies: - string-width: 4.2.3 - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - - /ansi-html-community@0.0.8: - resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} - engines: {'0': node >= 0.8.0} - hasBin: true - - /ansi-regex@2.1.1: - resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} - engines: {node: '>=0.10.0'} - - /ansi-regex@4.1.1: - resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} - engines: {node: '>=6'} - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - /append-field@1.0.0: - resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} - - /application-config-path@0.1.1: - resolution: {integrity: sha512-zy9cHePtMP0YhwG+CfHm0bgwdnga2X3gZexpdCwEj//dpb+TKajtiC8REEUJUSq6Ab4f9cgNy2l8ObXzCXFkEw==} - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - /aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - dependencies: - dequal: 2.0.3 - - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - - /array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - /array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - - /array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - - /array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - - /array.prototype.toreversed@1.1.2: - resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - - /array.prototype.tosorted@1.1.3: - resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - - /arrify@2.0.1: - resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} - engines: {node: '>=8'} - - /asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - - /ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - - /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - - /async@1.5.2: - resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - /at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - - /auto-bind@4.0.0: - resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} - engines: {node: '>=8'} - - /autoprefixer@10.4.19(postcss@8.4.38): - resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001607 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - - /axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - - /axios@0.21.4(debug@4.3.4): - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - dependencies: - follow-redirects: 1.15.6(debug@4.3.4) - transitivePeerDependencies: - - debug - - /axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} - dependencies: - dequal: 2.0.3 - - /b4a@1.6.6: - resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} - requiresBuild: true - - /babel-eslint@10.1.0(eslint@8.57.0): - resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==} - engines: {node: '>=6'} - deprecated: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. - peerDependencies: - eslint: '>= 4.12.1' - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.4 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - eslint: 8.57.0 - eslint-visitor-keys: 1.3.0 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - - /babel-jsx-utils@1.1.0: - resolution: {integrity: sha512-Mh1j/rw4xM9T3YICkw22aBQ78FhsHdsmlb9NEk4uVAFBOg+Ez9ZgXXHugoBPCZui3XLomk/7/JBBH4daJqTkQQ==} - - /babel-loader@8.3.0(@babel/core@7.24.4)(webpack@5.91.0): - resolution: {integrity: sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==} - engines: {node: '>= 8.9'} - peerDependencies: - '@babel/core': ^7.0.0 - webpack: '>=2' - dependencies: - '@babel/core': 7.24.4 - find-cache-dir: 3.3.2 - loader-utils: 2.0.4 - make-dir: 3.1.0 - schema-utils: 2.7.1 - webpack: 5.91.0 - - /babel-plugin-add-module-exports@1.0.4: - resolution: {integrity: sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg==} - - /babel-plugin-dynamic-import-node@2.3.3: - resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==} - dependencies: - object.assign: 4.1.5 - - /babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} - dependencies: - '@babel/runtime': 7.24.4 - cosmiconfig: 7.1.0 - resolve: 1.22.8 - - /babel-plugin-polyfill-corejs2@0.4.10(@babel/core@7.24.4): - resolution: {integrity: sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.4 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.4) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.4): - resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.4) - core-js-compat: 3.36.1 - transitivePeerDependencies: - - supports-color - - /babel-plugin-polyfill-regenerator@0.6.1(@babel/core@7.24.4): - resolution: {integrity: sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.4) - transitivePeerDependencies: - - supports-color - - /babel-plugin-remove-graphql-queries@5.13.1(@babel/core@7.24.4)(gatsby@5.13.3): - resolution: {integrity: sha512-yncJ/W6Un48aBRpK/rmdpQOMcr4+EmJ3oi2Wq1zXKu8WLlw+j93KTbejf7fg2msm8GUskb/+9Nnpz7oMCqO9aA==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@babel/core': ^7.0.0 - gatsby: ^5.0.0-next - dependencies: - '@babel/core': 7.24.4 - '@babel/runtime': 7.24.4 - '@babel/types': 7.24.0 - gatsby: 5.13.3(babel-eslint@10.1.0)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.4) - gatsby-core-utils: 4.13.1 - - /babel-plugin-syntax-trailing-function-commas@7.0.0-beta.0: - resolution: {integrity: sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==} - - /babel-plugin-transform-react-remove-prop-types@0.4.24: - resolution: {integrity: sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==} - - /babel-preset-fbjs@3.4.0(@babel/core@7.24.4): - resolution: {integrity: sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.24.4) - '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.24.4) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.4) - '@babel/plugin-syntax-flow': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-block-scoping': 7.24.4(@babel/core@7.24.4) - '@babel/plugin-transform-classes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-destructuring': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-flow-strip-types': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-parameters': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-react-display-name': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.4) - '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.4) - babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0 - - /babel-preset-gatsby@3.13.1(@babel/core@7.24.4)(core-js@3.36.1): - resolution: {integrity: sha512-JpWj9bkUZ2mlcu4Hc+8Yp8Bml5jmShW1IGVVCQyXrbiKHyBoTr77PhWqy00mvY9EPwlmfTPlgB6QrQBVONLqmw==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@babel/core': ^7.11.6 - core-js: ^3.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.24.4) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.24.4) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.24.4) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-transform-classes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-runtime': 7.24.3(@babel/core@7.24.4) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.4) - '@babel/preset-env': 7.24.4(@babel/core@7.24.4) - '@babel/preset-react': 7.24.1(@babel/core@7.24.4) - '@babel/runtime': 7.24.4 - babel-plugin-dynamic-import-node: 2.3.3 - babel-plugin-macros: 3.1.0 - babel-plugin-transform-react-remove-prop-types: 0.4.24 - core-js: 3.36.1 - gatsby-core-utils: 4.13.1 - gatsby-legacy-polyfills: 3.13.0 - transitivePeerDependencies: - - supports-color - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /bare-events@2.2.2: - resolution: {integrity: sha512-h7z00dWdG0PYOQEvChhOSWvOfkIKsdZGkWr083FgN/HyoQuebSew/cgirYqh9SCuy/hRvxc5Vy6Fw8xAmYHLkQ==} - requiresBuild: true - optional: true - - /bare-fs@2.2.3: - resolution: {integrity: sha512-amG72llr9pstfXOBOHve1WjiuKKAMnebcmMbPWDZ7BCevAoJLpugjuAPRsDINEyjT0a6tbaVx3DctkXIRbLuJw==} - requiresBuild: true - dependencies: - bare-events: 2.2.2 - bare-path: 2.1.1 - streamx: 2.16.1 - optional: true - - /bare-os@2.2.1: - resolution: {integrity: sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w==} - requiresBuild: true - optional: true - - /bare-path@2.1.1: - resolution: {integrity: sha512-OHM+iwRDRMDBsSW7kl3dO62JyHdBKO3B25FB9vNQBPcGHMo4+eA8Yj41Lfbk3pS/seDY+siNge0LdRTulAau/A==} - requiresBuild: true - dependencies: - bare-os: 2.2.1 - optional: true - - /base-x@3.0.9: - resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} - dependencies: - safe-buffer: 5.2.1 - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - requiresBuild: true - - /base64id@2.0.0: - resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} - engines: {node: ^4.5.0 || >= 5.9} - - /better-opn@2.1.1: - resolution: {integrity: sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==} - engines: {node: '>8.0.0'} - dependencies: - open: 7.4.2 - - /big.js@5.2.2: - resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - requiresBuild: true - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - /bluebird@3.7.2: - resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - - /body-parser@1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - - /boxen@5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} - dependencies: - ansi-align: 3.0.1 - camelcase: 6.3.0 - chalk: 4.1.2 - cli-boxes: 2.2.1 - string-width: 4.2.3 - type-fest: 0.20.2 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - dependencies: - caniuse-lite: 1.0.30001607 - electron-to-chromium: 1.4.729 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) - - /bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - requiresBuild: true - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - - /bytes@3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - /cache-manager@2.11.1: - resolution: {integrity: sha512-XhUuc9eYwkzpK89iNewFwtvcDYMUsvtwzHeyEOPJna/WsVsXcrzsA1ft2M0QqPNunEzLhNCYPo05tEfG+YuNow==} - dependencies: - async: 1.5.2 - lodash.clonedeep: 4.5.0 - lru-cache: 4.0.0 - - /cacheable-lookup@5.0.4: - resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} - engines: {node: '>=10.6.0'} - - /cacheable-lookup@7.0.0: - resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} - engines: {node: '>=14.16'} - - /cacheable-request@10.2.14: - resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} - engines: {node: '>=14.16'} - dependencies: - '@types/http-cache-semantics': 4.0.4 - get-stream: 6.0.1 - http-cache-semantics: 4.1.1 - keyv: 4.5.4 - mimic-response: 4.0.0 - normalize-url: 8.0.1 - responselike: 3.0.0 - - /cacheable-request@7.0.4: - resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} - engines: {node: '>=8'} - dependencies: - clone-response: 1.0.3 - get-stream: 5.2.0 - http-cache-semantics: 4.1.1 - keyv: 4.5.4 - lowercase-keys: 2.0.0 - normalize-url: 6.1.0 - responselike: 2.0.1 - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - /camel-case@4.1.2: - resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - dependencies: - pascal-case: 3.1.2 - tslib: 2.6.2 - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - /caniuse-api@3.0.0: - resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001607 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - - /caniuse-lite@1.0.30001607: - resolution: {integrity: sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==} - - /capital-case@1.0.4: - resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - upper-case-first: 2.0.2 - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - /change-case-all@1.0.14: - resolution: {integrity: sha512-CWVm2uT7dmSHdO/z1CXT/n47mWonyypzBbuCy5tN7uMg22BsfkhwT6oHmFCAk+gL1LOOxhdbB9SZz3J1KTY3gA==} - dependencies: - change-case: 4.1.2 - is-lower-case: 2.0.2 - is-upper-case: 2.0.2 - lower-case: 2.0.2 - lower-case-first: 2.0.2 - sponge-case: 1.0.1 - swap-case: 2.0.2 - title-case: 3.0.3 - upper-case: 2.0.2 - upper-case-first: 2.0.2 - - /change-case-all@1.0.15: - resolution: {integrity: sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==} - dependencies: - change-case: 4.1.2 - is-lower-case: 2.0.2 - is-upper-case: 2.0.2 - lower-case: 2.0.2 - lower-case-first: 2.0.2 - sponge-case: 1.0.1 - swap-case: 2.0.2 - title-case: 3.0.3 - upper-case: 2.0.2 - upper-case-first: 2.0.2 - - /change-case@4.1.2: - resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} - dependencies: - camel-case: 4.1.2 - capital-case: 1.0.4 - constant-case: 3.0.4 - dot-case: 3.0.4 - header-case: 2.0.4 - no-case: 3.0.4 - param-case: 3.0.4 - pascal-case: 3.1.2 - path-case: 3.0.4 - sentence-case: 3.0.4 - snake-case: 3.0.4 - tslib: 2.6.2 - - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - /chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - requiresBuild: true - - /chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} - engines: {node: '>=6.0'} - - /ci-info@2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /cli-boxes@2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} - - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - - /cli-width@3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} - - /client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - - /clipboardy@4.0.0: - resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} - engines: {node: '>=18'} - dependencies: - execa: 8.0.1 - is-wsl: 3.1.0 - is64bit: 2.0.0 - - /cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - - /clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - - /clone-response@1.0.3: - resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} - dependencies: - mimic-response: 1.0.1 - - /clone@2.1.2: - resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} - engines: {node: '>=0.8'} - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - requiresBuild: true - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - - /color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - requiresBuild: true - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - - /colord@2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - - /colorette@1.4.0: - resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} - - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - - /command-exists@1.2.9: - resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} - - /commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - - /commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - - /common-path-prefix@3.0.0: - resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} - - /common-tags@1.8.2: - resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} - engines: {node: '>=4.0.0'} - - /commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - - /compressible@2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - - /compression@1.7.4: - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9 - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - /concat-stream@1.6.2: - resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} - engines: {'0': node >= 0.8} - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 2.3.8 - typedarray: 0.0.6 - - /config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - dependencies: - ini: 1.3.8 - proto-list: 1.2.4 - - /configstore@5.0.1: - resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==} - engines: {node: '>=8'} - dependencies: - dot-prop: 5.3.0 - graceful-fs: 4.2.11 - make-dir: 3.1.0 - unique-string: 2.0.0 - write-file-atomic: 3.0.3 - xdg-basedir: 4.0.0 - - /confusing-browser-globals@1.0.11: - resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - - /constant-case@3.0.4: - resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - upper-case: 2.0.2 - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - - /convert-hrtime@3.0.0: - resolution: {integrity: sha512-7V+KqSvMiHp8yWDuwfww06XleMWVVB9b9tURBx+G7UTADuo5hYPuowKloz4OzOqbPezxgo+fdQ1522WzPG4OeA==} - engines: {node: '>=8'} - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - - /cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - - /core-js-compat@3.31.0: - resolution: {integrity: sha512-hM7YCu1cU6Opx7MXNu0NuumM0ezNeAeRKadixyiQELWY3vT3De9S4J5ZBMraWV2vZnrE1Cirl0GtFtDtMUXzPw==} - dependencies: - browserslist: 4.23.0 - - /core-js-compat@3.36.1: - resolution: {integrity: sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==} - dependencies: - browserslist: 4.23.0 - - /core-js-pure@3.36.1: - resolution: {integrity: sha512-NXCvHvSVYSrewP0L5OhltzXeWFJLo2AL2TYnj6iLV3Bw8mM62wAQMNgUCRI6EBu6hVVpbCxmOPlxh1Ikw2PfUA==} - requiresBuild: true - - /core-js@3.36.1: - resolution: {integrity: sha512-BTvUrwxVBezj5SZ3f10ImnX2oRByMxql3EimVqMysepbC9EeMUOpLwdy6Eoili2x6E4kf+ZUB5k/+Jv55alPfA==} - requiresBuild: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - /cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - - /cosmiconfig@6.0.0: - resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} - engines: {node: '>=8'} - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - - /cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - - /create-gatsby@3.13.1: - resolution: {integrity: sha512-CCg8Vz/iQs1cgMEzyRlVGMvNs8ivE/2w+TL6yS56FVe1JjOou8nKYHzxnWxRmBUtC7rTfjxVaTESIotuYBsltQ==} - hasBin: true - dependencies: - '@babel/runtime': 7.24.4 - - /cross-fetch@3.1.8: - resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - /crypto-random-string@2.0.0: - resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} - engines: {node: '>=8'} - - /css-declaration-sorter@6.4.1(postcss@8.4.38): - resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} - engines: {node: ^10 || ^12 || >=14} - peerDependencies: - postcss: ^8.0.9 - dependencies: - postcss: 8.4.38 - - /css-loader@5.2.7(webpack@5.91.0): - resolution: {integrity: sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.27.0 || ^5.0.0 - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - loader-utils: 2.0.4 - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.38) - postcss-modules-scope: 3.2.0(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) - postcss-value-parser: 4.2.0 - schema-utils: 3.3.0 - semver: 7.6.0 - webpack: 5.91.0 - - /css-minimizer-webpack-plugin@2.0.0(webpack@5.91.0): - resolution: {integrity: sha512-cG/uc94727tx5pBNtb1Sd7gvUPzwmcQi1lkpfqTpdkuNq75hJCw7bIVsCNijLm4dhDcr1atvuysl2rZqOG8Txw==} - engines: {node: '>= 10.13.0'} - peerDependencies: - clean-css: '*' - csso: '*' - webpack: ^5.0.0 - peerDependenciesMeta: - clean-css: - optional: true - csso: - optional: true - dependencies: - cssnano: 5.1.15(postcss@8.4.38) - jest-worker: 26.6.2 - p-limit: 3.1.0 - postcss: 8.4.38 - schema-utils: 3.3.0 - serialize-javascript: 5.0.1 - source-map: 0.6.1 - webpack: 5.91.0 - - /css-select@4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 4.3.1 - domutils: 2.8.0 - nth-check: 2.1.1 - - /css-tree@1.1.3: - resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} - engines: {node: '>=8.0.0'} - dependencies: - mdn-data: 2.0.14 - source-map: 0.6.1 - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - - /css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - - /cssnano-preset-default@5.2.14(postcss@8.4.38): - resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - css-declaration-sorter: 6.4.1(postcss@8.4.38) - cssnano-utils: 3.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-calc: 8.2.4(postcss@8.4.38) - postcss-colormin: 5.3.1(postcss@8.4.38) - postcss-convert-values: 5.1.3(postcss@8.4.38) - postcss-discard-comments: 5.1.2(postcss@8.4.38) - postcss-discard-duplicates: 5.1.0(postcss@8.4.38) - postcss-discard-empty: 5.1.1(postcss@8.4.38) - postcss-discard-overridden: 5.1.0(postcss@8.4.38) - postcss-merge-longhand: 5.1.7(postcss@8.4.38) - postcss-merge-rules: 5.1.4(postcss@8.4.38) - postcss-minify-font-values: 5.1.0(postcss@8.4.38) - postcss-minify-gradients: 5.1.1(postcss@8.4.38) - postcss-minify-params: 5.1.4(postcss@8.4.38) - postcss-minify-selectors: 5.2.1(postcss@8.4.38) - postcss-normalize-charset: 5.1.0(postcss@8.4.38) - postcss-normalize-display-values: 5.1.0(postcss@8.4.38) - postcss-normalize-positions: 5.1.1(postcss@8.4.38) - postcss-normalize-repeat-style: 5.1.1(postcss@8.4.38) - postcss-normalize-string: 5.1.0(postcss@8.4.38) - postcss-normalize-timing-functions: 5.1.0(postcss@8.4.38) - postcss-normalize-unicode: 5.1.1(postcss@8.4.38) - postcss-normalize-url: 5.1.0(postcss@8.4.38) - postcss-normalize-whitespace: 5.1.1(postcss@8.4.38) - postcss-ordered-values: 5.1.3(postcss@8.4.38) - postcss-reduce-initial: 5.1.2(postcss@8.4.38) - postcss-reduce-transforms: 5.1.0(postcss@8.4.38) - postcss-svgo: 5.1.0(postcss@8.4.38) - postcss-unique-selectors: 5.1.1(postcss@8.4.38) - - /cssnano-utils@3.1.0(postcss@8.4.38): - resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - - /cssnano@5.1.15(postcss@8.4.38): - resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - cssnano-preset-default: 5.2.14(postcss@8.4.38) - lilconfig: 2.1.0 - postcss: 8.4.38 - yaml: 1.10.2 - - /csso@4.2.0: - resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} - engines: {node: '>=8.0.0'} - dependencies: - css-tree: 1.1.3 - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - /d@1.0.2: - resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} - engines: {node: '>=0.12'} - dependencies: - es5-ext: 0.10.64 - type: 2.7.2 - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - - /date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} - dependencies: - '@babel/runtime': 7.24.4 - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - - /decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - - /decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - dependencies: - mimic-response: 3.1.0 - - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - requiresBuild: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - /defer-to-connect@2.0.1: - resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} - engines: {node: '>=10'} - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - - /define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - /dependency-graph@0.11.0: - resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} - engines: {node: '>= 0.6.0'} - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - /detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - dev: true - - /detect-libc@1.0.3: - resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} - engines: {node: '>=0.10'} - hasBin: true - - /detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - requiresBuild: true - - /detect-newline@4.0.1: - resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /detect-port-alt@1.1.6: - resolution: {integrity: sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==} - engines: {node: '>= 4.2.1'} - hasBin: true - dependencies: - address: 1.2.2 - debug: 2.6.9 - transitivePeerDependencies: - - supports-color - - /detect-port@1.5.1: - resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} - hasBin: true - dependencies: - address: 1.2.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - - /devcert@1.2.2: - resolution: {integrity: sha512-UsLqvtJGPiGwsIZnJINUnFYaWgK7CroreGRndWHZkRD58tPFr3pVbbSyHR8lbh41+azR4jKvuNZ+eCoBZGA5kA==} - dependencies: - '@types/configstore': 2.1.1 - '@types/debug': 0.0.30 - '@types/get-port': 3.2.0 - '@types/glob': 5.0.38 - '@types/lodash': 4.17.0 - '@types/mkdirp': 0.5.2 - '@types/node': 8.10.66 - '@types/rimraf': 2.0.5 - '@types/tmp': 0.0.33 - application-config-path: 0.1.1 - command-exists: 1.2.9 - debug: 3.2.7 - eol: 0.9.1 - get-port: 3.2.0 - glob: 7.2.3 - is-valid-domain: 0.1.6 - lodash: 4.17.21 - mkdirp: 0.5.6 - password-prompt: 1.1.3 - rimraf: 2.7.1 - sudo-prompt: 8.2.5 - tmp: 0.0.33 - tslib: 1.14.1 - transitivePeerDependencies: - - supports-color - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - - /dom-converter@0.2.0: - resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} - dependencies: - utila: 0.4.0 - - /dom-serializer@1.4.1: - resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - entities: 2.2.0 - - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - /domhandler@4.3.1: - resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - - /domutils@2.8.0: - resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - dependencies: - dom-serializer: 1.4.1 - domelementtype: 2.3.0 - domhandler: 4.3.1 - - /dot-case@3.0.4: - resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - - /dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} - dependencies: - is-obj: 2.0.0 - - /dotenv-expand@5.1.0: - resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /dotenv@7.0.0: - resolution: {integrity: sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==} - engines: {node: '>=6'} - - /dotenv@8.6.0: - resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} - engines: {node: '>=10'} - - /duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - /electron-to-chromium@1.4.729: - resolution: {integrity: sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA==} - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - /emojis-list@3.0.0: - resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} - engines: {node: '>= 4'} - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - requiresBuild: true - dependencies: - once: 1.4.0 - - /engine.io-client@6.5.3: - resolution: {integrity: sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==} - dependencies: - '@socket.io/component-emitter': 3.1.0 - debug: 4.3.4 - engine.io-parser: 5.2.2 - ws: 8.11.0 - xmlhttprequest-ssl: 2.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - /engine.io-parser@5.2.2: - resolution: {integrity: sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==} - engines: {node: '>=10.0.0'} - - /engine.io@6.5.4: - resolution: {integrity: sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==} - engines: {node: '>=10.2.0'} - dependencies: - '@types/cookie': 0.4.1 - '@types/cors': 2.8.17 - '@types/node': 20.12.5 - accepts: 1.3.8 - base64id: 2.0.0 - cookie: 0.4.2 - cors: 2.8.5 - debug: 4.3.4 - engine.io-parser: 5.2.2 - ws: 8.11.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - /enhanced-resolve@5.16.0: - resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - - /enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - - /entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - - /envinfo@7.12.0: - resolution: {integrity: sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg==} - engines: {node: '>=4'} - hasBin: true - - /eol@0.9.1: - resolution: {integrity: sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==} - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - - /error-stack-parser@2.1.4: - resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} - dependencies: - stackframe: 1.3.4 - - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.0 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 - globalthis: 1.0.3 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - /es-iterator-helpers@1.0.18: - resolution: {integrity: sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-set-tostringtag: 2.0.3 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - iterator.prototype: 1.1.2 - safe-array-concat: 1.1.2 - - /es-module-lexer@1.5.0: - resolution: {integrity: sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==} - - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.2 - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - - /es5-ext@0.10.64: - resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} - engines: {node: '>=0.10'} - requiresBuild: true - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.4 - esniff: 2.0.1 - next-tick: 1.1.0 - - /es6-iterator@2.0.3: - resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-symbol: 3.1.4 - - /es6-promise@4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - - /es6-symbol@3.1.4: - resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} - engines: {node: '>=0.12'} - dependencies: - d: 1.0.2 - ext: 1.7.0 - - /es6-weak-map@2.0.3: - resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-iterator: 2.0.3 - es6-symbol: 3.1.4 - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - /escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-config-react-app@6.0.0(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(babel-eslint@10.1.0)(eslint-plugin-flowtype@5.10.0)(eslint-plugin-import@2.29.1)(eslint-plugin-jsx-a11y@6.8.0)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.34.1)(eslint@7.32.0)(typescript@5.5.4): - resolution: {integrity: sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^4.0.0 - '@typescript-eslint/parser': ^4.0.0 - babel-eslint: ^10.0.0 - eslint: ^7.5.0 - eslint-plugin-flowtype: ^5.2.0 - eslint-plugin-import: ^2.22.0 - eslint-plugin-jest: ^24.0.0 - eslint-plugin-jsx-a11y: ^6.3.1 - eslint-plugin-react: ^7.20.3 - eslint-plugin-react-hooks: ^4.0.8 - eslint-plugin-testing-library: ^3.9.0 - typescript: '*' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - eslint-plugin-testing-library: - optional: true - typescript: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - babel-eslint: 10.1.0(eslint@8.57.0) - confusing-browser-globals: 1.0.11 - eslint: 7.32.0 - eslint-plugin-flowtype: 5.10.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.57.0) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-react: 7.34.1(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) - typescript: 5.5.4 - - /eslint-config-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-turbo: 2.0.0(eslint@8.57.0) - dev: true - - /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.1): - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - dependencies: - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.5.0)(eslint@8.57.0) - dev: true - - /eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): - resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.4 - enhanced-resolve: 5.16.0 - eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.5.0)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.7.3 - is-core-module: 2.13.1 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.5.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 7.5.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): - resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} - engines: {node: '>=6.5.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - escape-string-regexp: 1.0.5 - eslint: 8.57.0 - ignore: 5.3.1 - dev: true - - /eslint-plugin-flowtype@5.10.0(eslint@8.57.0): - resolution: {integrity: sha512-vcz32f+7TP+kvTUyMXZmCnNujBQZDNmcqPImw8b9PZ+16w1Qdm6ryRuYZYVaG9xRqqmAPr2Cs9FAX5gN+x/bjw==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - eslint: ^7.1.0 - dependencies: - eslint: 8.57.0 - lodash: 4.17.21 - string-natural-compare: 3.0.1 - - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.57.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.5.0)(eslint@8.57.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 7.5.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.5.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.24.4 - aria-query: 5.3.0 - array-includes: 3.1.8 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.18 - eslint: 8.57.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0): - resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} - peerDependencies: - eslint: '>=7' - eslint-plugin-jest: '>=25' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - dependencies: - eslint: 8.57.0 - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - dev: true - - /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - - /eslint-plugin-react@7.34.1(eslint@8.57.0): - resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.2 - array.prototype.toreversed: 1.1.2 - array.prototype.tosorted: 1.1.3 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.18 - eslint: 8.57.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.hasown: 1.1.4 - object.values: 1.2.0 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.11 - - /eslint-plugin-testing-library@6.2.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true - - /eslint-plugin-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.0 - dev: true - - /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.44.0' - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - ci-info: 3.9.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.6.0 - strip-indent: 3.0.0 - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - /eslint-utils@2.1.0: - resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} - engines: {node: '>=6'} - dependencies: - eslint-visitor-keys: 1.3.0 - - /eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - /eslint-webpack-plugin@2.7.0(eslint@7.32.0)(webpack@5.91.0): - resolution: {integrity: sha512-bNaVVUvU4srexGhVcayn/F4pJAz19CWBkKoMx7aSQ4wtTbZQCnG5O9LHCE42mM+JSKOUp7n6vd5CIwzj7lOVGA==} - engines: {node: '>= 10.13.0'} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - webpack: ^4.0.0 || ^5.0.0 - dependencies: - '@types/eslint': 7.29.0 - arrify: 2.0.1 - eslint: 7.32.0 - jest-worker: 27.5.1 - micromatch: 4.0.5 - normalize-path: 3.0.0 - schema-utils: 3.3.0 - webpack: 5.91.0 - - /eslint@7.32.0: - resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} - engines: {node: ^10.12.0 || >=12.0.0} - hasBin: true - dependencies: - '@babel/code-frame': 7.12.11 - '@eslint/eslintrc': 0.4.3 - '@humanwhocodes/config-array': 0.5.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - enquirer: 2.4.1 - escape-string-regexp: 4.0.0 - eslint-scope: 5.1.1 - eslint-utils: 2.1.0 - eslint-visitor-keys: 2.1.0 - espree: 7.3.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - functional-red-black-tree: 1.0.1 - glob-parent: 5.1.2 - globals: 13.24.0 - ignore: 4.0.6 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - js-yaml: 3.14.1 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - progress: 2.0.3 - regexpp: 3.2.0 - semver: 7.6.0 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - table: 6.8.2 - text-table: 0.2.0 - v8-compile-cache: 2.4.0 - transitivePeerDependencies: - - supports-color - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - /esniff@2.0.1: - resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} - engines: {node: '>=0.10'} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - event-emitter: 0.3.5 - type: 2.7.2 - - /espree@7.3.1: - resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - acorn: 7.4.1 - acorn-jsx: 5.3.2(acorn@7.4.1) - eslint-visitor-keys: 1.3.0 - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - - /event-emitter@0.3.5: - resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - - /event-source-polyfill@1.0.31: - resolution: {integrity: sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==} - - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - /expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - requiresBuild: true - - /express-http-proxy@1.6.3: - resolution: {integrity: sha512-/l77JHcOUrDUX8V67E287VEUQT0lbm71gdGVoodnlWBziarYKgMcpqT7xvh/HM8Jv52phw8Bd8tY+a7QjOr7Yg==} - engines: {node: '>=6.0.0'} - dependencies: - debug: 3.2.7 - es6-promise: 4.2.8 - raw-body: 2.5.2 - transitivePeerDependencies: - - supports-color - - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - /ext@1.7.0: - resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} - dependencies: - type: 2.7.2 - - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - /fast-fifo@1.3.2: - resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - requiresBuild: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - /fastest-levenshtein@1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - - /fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - dependencies: - bser: 2.1.1 - - /fbjs-css-vars@1.0.2: - resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} - - /fbjs@3.0.5: - resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} - dependencies: - cross-fetch: 3.1.8 - fbjs-css-vars: 1.0.2 - loose-envify: 1.4.0 - object-assign: 4.1.1 - promise: 7.3.1 - setimmediate: 1.0.5 - ua-parser-js: 1.0.37 - transitivePeerDependencies: - - encoding - - /figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - - /file-loader@6.2.0(webpack@5.91.0): - resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - loader-utils: 2.0.4 - schema-utils: 3.3.0 - webpack: 5.91.0 - - /file-type@16.5.4: - resolution: {integrity: sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==} - engines: {node: '>=10'} - dependencies: - readable-web-to-node-stream: 3.0.2 - strtok3: 6.3.0 - token-types: 4.2.1 - - /filesize@8.0.7: - resolution: {integrity: sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==} - engines: {node: '>= 0.4.0'} - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - - /filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - /find-cache-dir@3.3.2: - resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} - engines: {node: '>=8'} - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - - /find-up@3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - dependencies: - locate-path: 3.0.0 - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - - /follow-redirects@1.15.6(debug@4.3.4): - resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dependencies: - debug: 4.3.4 - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /fork-ts-checker-webpack-plugin@6.5.3(eslint@7.32.0)(typescript@5.5.4)(webpack@5.91.0): - resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} - engines: {node: '>=10', yarn: '>=1.0.0'} - peerDependencies: - eslint: '>= 6' - typescript: '>= 2.7' - vue-template-compiler: '*' - webpack: '>= 4' - peerDependenciesMeta: - eslint: - optional: true - vue-template-compiler: - optional: true - dependencies: - '@babel/code-frame': 7.24.2 - '@types/json-schema': 7.0.15 - chalk: 4.1.2 - chokidar: 3.6.0 - cosmiconfig: 6.0.0 - deepmerge: 4.3.1 - eslint: 7.32.0 - fs-extra: 9.1.0 - glob: 7.2.3 - memfs: 3.6.0 - minimatch: 3.1.2 - schema-utils: 2.7.0 - semver: 7.6.0 - tapable: 1.1.3 - typescript: 5.5.4 - webpack: 5.91.0 - - /form-data-encoder@2.1.4: - resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} - engines: {node: '>= 14.17'} - - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - requiresBuild: true - - /fs-exists-cached@1.0.0: - resolution: {integrity: sha512-kSxoARUDn4F2RPXX48UXnaFKwVU7Ivd/6qpzZL29MCDmr9sTvybv4gFCp+qaI4fM9m0z9fgz/yJvi56GAz+BZg==} - - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - - /fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - - /fs-monkey@1.0.5: - resolution: {integrity: sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==} - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - functions-have-names: 1.2.3 - - /functional-red-black-tree@1.0.1: - resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - - /gatsby-cli@5.13.2: - resolution: {integrity: sha512-Wxsfgfp5jDciXOR00aKQk9SQANXoYaftNZz6LGGkRZcwMFjhPal1LdCioyy3sOXrRvB0uUsACrGLS1ghXxd2QA==} - engines: {node: '>=18.0.0'} - hasBin: true - requiresBuild: true - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/core': 7.24.4 - '@babel/generator': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/preset-typescript': 7.24.1(@babel/core@7.24.4) - '@babel/runtime': 7.24.4 - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - '@jridgewell/trace-mapping': 0.3.25 - '@types/common-tags': 1.8.4 - better-opn: 2.1.1 - boxen: 5.1.2 - chalk: 4.1.2 - clipboardy: 4.0.0 - common-tags: 1.8.2 - convert-hrtime: 3.0.0 - create-gatsby: 3.13.1 - envinfo: 7.12.0 - execa: 5.1.1 - fs-exists-cached: 1.0.0 - fs-extra: 11.2.0 - gatsby-core-utils: 4.13.1 - gatsby-telemetry: 4.13.1 - hosted-git-info: 3.0.8 - is-valid-path: 0.1.1 - joi: 17.12.3 - lodash: 4.17.21 - node-fetch: 2.7.0 - opentracing: 0.14.7 - pretty-error: 2.1.2 - progress: 2.0.3 - prompts: 2.4.2 - redux: 4.2.1 - resolve-cwd: 3.0.0 - semver: 7.6.0 - signal-exit: 3.0.7 - stack-trace: 0.0.10 - strip-ansi: 6.0.1 - yargs: 15.4.1 - yoga-layout-prebuilt: 1.10.0 - yurnalist: 2.1.0 - transitivePeerDependencies: - - encoding - - supports-color - - /gatsby-core-utils@4.13.1: - resolution: {integrity: sha512-w7G6SsQr8T2q+AJ1MxvRNGocCt+wjc22MiRLj2Zi3Ijpjszbr818JxwI4+aPt8WOSHlKT5SYCHICnEvcYPm9gg==} - engines: {node: '>=18.0.0'} - dependencies: - '@babel/runtime': 7.24.4 - ci-info: 2.0.0 - configstore: 5.0.1 - fastq: 1.17.1 - file-type: 16.5.4 - fs-extra: 11.2.0 - got: 11.8.6 - hash-wasm: 4.11.0 - import-from: 4.0.0 - lmdb: 2.5.3 - lock: 1.1.0 - node-object-hash: 2.3.10 - proper-lockfile: 4.1.2 - resolve-from: 5.0.0 - tmp: 0.2.3 - xdg-basedir: 4.0.0 - - /gatsby-graphiql-explorer@3.13.1: - resolution: {integrity: sha512-WR6jv18OhKLwK/hGZ6ZGUd82GFtM6gHz+sOpgsJJx/+uqRjZwqcrH2LSrWRSWUCk7FoZY1rJuBSD1QkOODV01A==} - engines: {node: '>=14.15.0'} - - /gatsby-legacy-polyfills@3.13.0: - resolution: {integrity: sha512-nFZzq0+iv1+fGbDq1Pry2tFGOuj7VFXXTicxtWWaz0+vdE72Gp7HBGIjxlrcUPW709JUc4J2L7DTUG74sNWEFw==} - dependencies: - '@babel/runtime': 7.24.4 - core-js-compat: 3.31.0 - - /gatsby-link@5.13.1(@gatsbyjs/reach-router@2.0.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-naQxvgX/rd4Pj5ICL2DcqT30TAENk6wHttcLioxIqW9/UhwAXGkM9QsOJOyUmwbrp37UIKU3K92Ks/cMbRxwXA==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@gatsbyjs/reach-router': ^2.0.0 - react: ^18.0.0 || ^0.0.0 - react-dom: ^18.0.0 || ^0.0.0 - dependencies: - '@gatsbyjs/reach-router': 2.0.1(react-dom@18.2.0)(react@18.2.0) - '@types/reach__router': 1.3.15 - gatsby-page-utils: 3.13.1 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - - /gatsby-page-utils@3.13.1: - resolution: {integrity: sha512-+/V+ZKPn1Lv3KfeTBV/XUVljwTFQq5kg3T0esu9ygXEz3EVXjG5VjL/IX57awiDm9sLsEALqRuuYLoHpfNHg0A==} - engines: {node: '>=18.0.0'} - dependencies: - '@babel/runtime': 7.24.4 - bluebird: 3.7.2 - chokidar: 3.6.0 - fs-exists-cached: 1.0.0 - gatsby-core-utils: 4.13.1 - glob: 7.2.3 - lodash: 4.17.21 - micromatch: 4.0.5 - - /gatsby-parcel-config@1.13.1(@parcel/core@2.8.3): - resolution: {integrity: sha512-zEiDKnq1UQvDDireYQN2TmDsxDf9n2SHYXASHyUTipwsMlNMEi0nLav1vHRQAfzbjw4tabk9Z5kcknkJ6nLqOA==} - engines: {parcel: 2.x} - peerDependencies: - '@parcel/core': ^2.0.0 - dependencies: - '@gatsbyjs/parcel-namer-relative-to-cwd': 2.13.1(@parcel/core@2.8.3) - '@parcel/bundler-default': 2.8.3(@parcel/core@2.8.3) - '@parcel/compressor-raw': 2.8.3(@parcel/core@2.8.3) - '@parcel/core': 2.8.3 - '@parcel/namer-default': 2.8.3(@parcel/core@2.8.3) - '@parcel/optimizer-terser': 2.8.3(@parcel/core@2.8.3) - '@parcel/packager-js': 2.8.3(@parcel/core@2.8.3) - '@parcel/packager-raw': 2.8.3(@parcel/core@2.8.3) - '@parcel/reporter-dev-server': 2.8.3(@parcel/core@2.8.3) - '@parcel/resolver-default': 2.8.3(@parcel/core@2.8.3) - '@parcel/runtime-js': 2.8.3(@parcel/core@2.8.3) - '@parcel/transformer-js': 2.8.3(@parcel/core@2.8.3) - '@parcel/transformer-json': 2.8.3(@parcel/core@2.8.3) - - /gatsby-plugin-compile-es6-packages@2.1.1(gatsby@5.13.3): - resolution: {integrity: sha512-UfEbgiyI15yO2Kb+cAuSCIK/YyNz7baKBE/HhMuuLq+pyh1fhNW0x8swl/TZiH8QMqE8cgYGBGEUkdiFb1K6Lg==} - peerDependencies: - gatsby: '>2.0.0-alpha' - dependencies: - '@babel/runtime': 7.24.4 - gatsby: 5.13.3(babel-eslint@10.1.0)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.4) - regex-escape: 3.4.10 - dev: true - - /gatsby-plugin-page-creator@5.13.1(gatsby@5.13.3)(graphql@16.8.1): - resolution: {integrity: sha512-WBTQc0cFqaojS1Oh7MjBRSnLCOWWWl3L5t5LEsXwV+4L9OL6D5fLTz7K5xC34OVgfAIryuEKE/M2ZIEk3onVnw==} - engines: {node: '>=18.0.0'} - peerDependencies: - gatsby: ^5.0.0-next - dependencies: - '@babel/runtime': 7.24.4 - '@babel/traverse': 7.24.1 - '@sindresorhus/slugify': 1.1.2 - chokidar: 3.6.0 - fs-exists-cached: 1.0.0 - fs-extra: 11.2.0 - gatsby: 5.13.3(babel-eslint@10.1.0)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.4) - gatsby-core-utils: 4.13.1 - gatsby-page-utils: 3.13.1 - gatsby-plugin-utils: 4.13.1(gatsby@5.13.3)(graphql@16.8.1) - gatsby-telemetry: 4.13.1 - globby: 11.1.0 - lodash: 4.17.21 - transitivePeerDependencies: - - encoding - - graphql - - supports-color - - /gatsby-plugin-typescript@5.13.1(gatsby@5.13.3): - resolution: {integrity: sha512-FsTihoFKWTjzyIaUTndqktL39qMTAb0KyHj9kP+LxTY2FySqHIvFoYc1ycS5q52J76AoWUiGStJuuQLMNq66FQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - gatsby: ^5.0.0-next - dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.24.4) - '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.24.4) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.24.4) - '@babel/preset-typescript': 7.24.1(@babel/core@7.24.4) - '@babel/runtime': 7.24.4 - babel-plugin-remove-graphql-queries: 5.13.1(@babel/core@7.24.4)(gatsby@5.13.3) - gatsby: 5.13.3(babel-eslint@10.1.0)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.4) - transitivePeerDependencies: - - supports-color - - /gatsby-plugin-utils@4.13.1(gatsby@5.13.3)(graphql@16.8.1): - resolution: {integrity: sha512-dQ8cZyUENWHqZOOSBBYWCJ8yG3zSYnHYk0mKQbgZblUS30Sp7ZFM4r0/+lsvUkEYaBOnzFBQjSSQtTa0xu9QWA==} - engines: {node: '>=18.0.0'} - peerDependencies: - gatsby: ^5.0.0-next - graphql: ^16.0.0 - dependencies: - '@babel/runtime': 7.24.4 - fastq: 1.17.1 - fs-extra: 11.2.0 - gatsby: 5.13.3(babel-eslint@10.1.0)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.4) - gatsby-core-utils: 4.13.1 - gatsby-sharp: 1.13.0 - graphql: 16.8.1 - graphql-compose: 9.0.10(graphql@16.8.1) - import-from: 4.0.0 - joi: 17.12.3 - mime: 3.0.0 - - /gatsby-react-router-scroll@6.13.1(@gatsbyjs/reach-router@2.0.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-srBpg/ZHW4miwH/4OWOcspHqr8ZmKLE4DBNvckt0KO4giJerWiGoLj6qePwLFRWZPfV7txJr2kuUzACxarpL5g==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@gatsbyjs/reach-router': ^2.0.0 - react: ^18.0.0 || ^0.0.0 - react-dom: ^18.0.0 || ^0.0.0 - dependencies: - '@babel/runtime': 7.24.4 - '@gatsbyjs/reach-router': 2.0.1(react-dom@18.2.0)(react@18.2.0) - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - - /gatsby-script@2.13.0(@gatsbyjs/reach-router@2.0.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-TGNQGerf1NMJrgJkWxWrW6FFMAuC0L76WlyZgGXmhckPW/x7V1SxZrm0a2Q99kRHyoC59RYl2gTQWHaIwV+ZjA==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@gatsbyjs/reach-router': ^2.0.0 - react: ^18.0.0 || ^0.0.0 - react-dom: ^18.0.0 || ^0.0.0 - dependencies: - '@gatsbyjs/reach-router': 2.0.1(react-dom@18.2.0)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - - /gatsby-sharp@1.13.0: - resolution: {integrity: sha512-DviUtgm7tatSd1Hm54o/orHimOcyXBO9OJkSfzEchPFClvOza+2Qe/lqZShio0gFDxmG0Jgn0XCLzG7uH5VyJQ==} - engines: {node: '>=18.0.0'} - dependencies: - sharp: 0.32.6 - - /gatsby-telemetry@4.13.1: - resolution: {integrity: sha512-NstKs3N8LK9rwEli6SXO+ClNmewFbVzqS2yo6XZzQSXbymH6+Kkk+eqQivKhrD8PbQLLrdXkk1p47n91zc85XQ==} - engines: {node: '>=18.0.0'} - requiresBuild: true - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/runtime': 7.24.4 - '@turist/fetch': 7.2.0(node-fetch@2.7.0) - '@turist/time': 0.0.2 - boxen: 5.1.2 - configstore: 5.0.1 - fs-extra: 11.2.0 - gatsby-core-utils: 4.13.1 - git-up: 7.0.0 - is-docker: 2.2.1 - lodash: 4.17.21 - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - /gatsby-worker@2.13.1: - resolution: {integrity: sha512-CEm+5M2+3PzPcqTaJ0xjNuorQ3d1PfnKG1yqRRPfw8LFdPiycGhZAug/jqx0iTyVWXFHakEmddlykGFEbq54/Q==} - engines: {node: '>=18.0.0'} - dependencies: - '@babel/core': 7.24.4 - '@babel/runtime': 7.24.4 - fs-extra: 11.2.0 - signal-exit: 3.0.7 - transitivePeerDependencies: - - supports-color - - /gatsby@5.13.3(babel-eslint@10.1.0)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.4): - resolution: {integrity: sha512-SSnGpjswK20BQORcvTbtK8eI+W4QUG+u8rdVswB4suva6BfvTakW2wiktj7E2MdO4NjRvlgJjF5dUUncU5nldA==} - engines: {node: '>=18.0.0'} - hasBin: true - requiresBuild: true - peerDependencies: - react: ^18.0.0 || ^0.0.0 - react-dom: ^18.0.0 || ^0.0.0 - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/core': 7.24.4 - '@babel/eslint-parser': 7.24.1(@babel/core@7.24.4)(eslint@7.32.0) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/parser': 7.24.4 - '@babel/runtime': 7.24.4 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - '@builder.io/partytown': 0.7.6 - '@gatsbyjs/reach-router': 2.0.1(react-dom@18.2.0)(react@18.2.0) - '@gatsbyjs/webpack-hot-middleware': 2.25.3 - '@graphql-codegen/add': 3.2.3(graphql@16.8.1) - '@graphql-codegen/core': 2.6.8(graphql@16.8.1) - '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.8.1) - '@graphql-codegen/typescript': 2.8.8(graphql@16.8.1) - '@graphql-codegen/typescript-operations': 2.5.13(graphql@16.8.1) - '@graphql-tools/code-file-loader': 7.3.23(@babel/core@7.24.4)(graphql@16.8.1) - '@graphql-tools/load': 7.8.14(graphql@16.8.1) - '@jridgewell/trace-mapping': 0.3.25 - '@nodelib/fs.walk': 1.2.8 - '@parcel/cache': 2.8.3(@parcel/core@2.8.3) - '@parcel/core': 2.8.3 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.11(react-refresh@0.14.0)(webpack@5.91.0) - '@sigmacomputing/babel-plugin-lodash': 3.3.5 - '@types/http-proxy': 1.17.14 - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - '@vercel/webpack-asset-relocator-loader': 1.7.3 - acorn-loose: 8.4.0 - acorn-walk: 8.3.2 - address: 1.2.2 - anser: 2.1.1 - autoprefixer: 10.4.19(postcss@8.4.38) - axios: 0.21.4(debug@4.3.4) - babel-jsx-utils: 1.1.0 - babel-loader: 8.3.0(@babel/core@7.24.4)(webpack@5.91.0) - babel-plugin-add-module-exports: 1.0.4 - babel-plugin-dynamic-import-node: 2.3.3 - babel-plugin-remove-graphql-queries: 5.13.1(@babel/core@7.24.4)(gatsby@5.13.3) - babel-preset-gatsby: 3.13.1(@babel/core@7.24.4)(core-js@3.36.1) - better-opn: 2.1.1 - bluebird: 3.7.2 - body-parser: 1.20.1 - browserslist: 4.23.0 - cache-manager: 2.11.1 - chalk: 4.1.2 - chokidar: 3.6.0 - common-tags: 1.8.2 - compression: 1.7.4 - cookie: 0.5.0 - core-js: 3.36.1 - cors: 2.8.5 - css-loader: 5.2.7(webpack@5.91.0) - css-minimizer-webpack-plugin: 2.0.0(webpack@5.91.0) - css.escape: 1.5.1 - date-fns: 2.30.0 - debug: 4.3.4 - deepmerge: 4.3.1 - detect-port: 1.5.1 - devcert: 1.2.2 - dotenv: 8.6.0 - enhanced-resolve: 5.16.0 - error-stack-parser: 2.1.4 - eslint: 7.32.0 - eslint-config-react-app: 6.0.0(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(babel-eslint@10.1.0)(eslint-plugin-flowtype@5.10.0)(eslint-plugin-import@2.29.1)(eslint-plugin-jsx-a11y@6.8.0)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.34.1)(eslint@7.32.0)(typescript@5.5.4) - eslint-plugin-flowtype: 5.10.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.57.0) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-react: 7.34.1(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) - eslint-webpack-plugin: 2.7.0(eslint@7.32.0)(webpack@5.91.0) - event-source-polyfill: 1.0.31 - execa: 5.1.1 - express: 4.19.2 - express-http-proxy: 1.6.3 - fastest-levenshtein: 1.0.16 - fastq: 1.17.1 - file-loader: 6.2.0(webpack@5.91.0) - find-cache-dir: 3.3.2 - fs-exists-cached: 1.0.0 - fs-extra: 11.2.0 - gatsby-cli: 5.13.2 - gatsby-core-utils: 4.13.1 - gatsby-graphiql-explorer: 3.13.1 - gatsby-legacy-polyfills: 3.13.0 - gatsby-link: 5.13.1(@gatsbyjs/reach-router@2.0.1)(react-dom@18.2.0)(react@18.2.0) - gatsby-page-utils: 3.13.1 - gatsby-parcel-config: 1.13.1(@parcel/core@2.8.3) - gatsby-plugin-page-creator: 5.13.1(gatsby@5.13.3)(graphql@16.8.1) - gatsby-plugin-typescript: 5.13.1(gatsby@5.13.3) - gatsby-plugin-utils: 4.13.1(gatsby@5.13.3)(graphql@16.8.1) - gatsby-react-router-scroll: 6.13.1(@gatsbyjs/reach-router@2.0.1)(react-dom@18.2.0)(react@18.2.0) - gatsby-script: 2.13.0(@gatsbyjs/reach-router@2.0.1)(react-dom@18.2.0)(react@18.2.0) - gatsby-telemetry: 4.13.1 - gatsby-worker: 2.13.1 - glob: 7.2.3 - globby: 11.1.0 - got: 11.8.6 - graphql: 16.8.1 - graphql-compose: 9.0.10(graphql@16.8.1) - graphql-http: 1.22.0(graphql@16.8.1) - graphql-tag: 2.12.6(graphql@16.8.1) - hasha: 5.2.2 - invariant: 2.2.4 - is-relative: 1.0.0 - is-relative-url: 3.0.0 - joi: 17.12.3 - json-loader: 0.5.7 - latest-version: 7.0.0 - linkfs: 2.1.0 - lmdb: 2.5.3 - lodash: 4.17.21 - meant: 1.0.3 - memoizee: 0.4.15 - micromatch: 4.0.5 - mime: 3.0.0 - mini-css-extract-plugin: 1.6.2(webpack@5.91.0) - mitt: 1.2.0 - moment: 2.30.1 - multer: 1.4.5-lts.1 - node-fetch: 2.7.0 - node-html-parser: 5.4.2 - normalize-path: 3.0.0 - null-loader: 4.0.1(webpack@5.91.0) - opentracing: 0.14.7 - p-defer: 3.0.0 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - physical-cpu-count: 2.0.0 - platform: 1.3.6 - postcss: 8.4.38 - postcss-flexbugs-fixes: 5.0.2(postcss@8.4.38) - postcss-loader: 5.3.0(postcss@8.4.38)(webpack@5.91.0) - prompts: 2.4.2 - prop-types: 15.8.1 - query-string: 6.14.1 - raw-loader: 4.0.2(webpack@5.91.0) - react: 18.2.0 - react-dev-utils: 12.0.1(eslint@7.32.0)(typescript@5.5.4)(webpack@5.91.0) - react-dom: 18.2.0(react@18.2.0) - react-refresh: 0.14.0 - react-server-dom-webpack: 0.0.0-experimental-c8b778b7f-20220825(react@18.2.0)(webpack@5.91.0) - redux: 4.2.1 - redux-thunk: 2.4.2(redux@4.2.1) - resolve-from: 5.0.0 - semver: 7.6.0 - shallow-compare: 1.2.2 - signal-exit: 3.0.7 - slugify: 1.6.6 - socket.io: 4.7.1 - socket.io-client: 4.7.1 - stack-trace: 0.0.10 - string-similarity: 1.2.2 - strip-ansi: 6.0.1 - style-loader: 2.0.0(webpack@5.91.0) - style-to-object: 0.4.4 - terser-webpack-plugin: 5.3.10(webpack@5.91.0) - tmp: 0.2.3 - true-case-path: 2.2.1 - type-of: 2.0.1 - url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.91.0) - uuid: 8.3.2 - webpack: 5.91.0 - webpack-dev-middleware: 4.3.0(webpack@5.91.0) - webpack-merge: 5.10.0 - webpack-stats-plugin: 1.1.3 - webpack-virtual-modules: 0.5.0 - xstate: 4.38.3 - yaml-loader: 0.8.1 - optionalDependencies: - gatsby-sharp: 1.13.0 - transitivePeerDependencies: - - '@swc/core' - - '@types/webpack' - - babel-eslint - - bufferutil - - clean-css - - csso - - encoding - - esbuild - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - eslint-plugin-jest - - eslint-plugin-testing-library - - sockjs-client - - supports-color - - type-fest - - typescript - - uglify-js - - utf-8-validate - - vue-template-compiler - - webpack-cli - - webpack-dev-server - - webpack-hot-middleware - - webpack-plugin-serve - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - - /get-port@3.2.0: - resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} - engines: {node: '>=4'} - - /get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - dev: true - - /get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} - dependencies: - pump: 3.0.0 - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - - /get-tsconfig@4.7.3: - resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true - - /git-hooks-list@3.1.0: - resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} - dev: true - - /git-up@7.0.0: - resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} - dependencies: - is-ssh: 1.4.0 - parse-url: 8.1.0 - - /github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - requiresBuild: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - /global-modules@2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} - dependencies: - global-prefix: 3.0.0 - - /global-prefix@3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - - /got@11.8.6: - resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} - engines: {node: '>=10.19.0'} - dependencies: - '@sindresorhus/is': 4.6.0 - '@szmarczak/http-timer': 4.0.6 - '@types/cacheable-request': 6.0.3 - '@types/responselike': 1.0.3 - cacheable-lookup: 5.0.4 - cacheable-request: 7.0.4 - decompress-response: 6.0.0 - http2-wrapper: 1.0.3 - lowercase-keys: 2.0.0 - p-cancelable: 2.1.1 - responselike: 2.0.1 - - /got@12.6.1: - resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} - engines: {node: '>=14.16'} - dependencies: - '@sindresorhus/is': 5.6.0 - '@szmarczak/http-timer': 5.0.1 - cacheable-lookup: 7.0.0 - cacheable-request: 10.2.14 - decompress-response: 6.0.0 - form-data-encoder: 2.1.4 - get-stream: 6.0.1 - http2-wrapper: 2.2.1 - lowercase-keys: 3.0.0 - p-cancelable: 3.0.0 - responselike: 3.0.0 - - /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - /graphql-compose@9.0.10(graphql@16.8.1): - resolution: {integrity: sha512-UsVoxfi2+c8WbHl2pEB+teoRRZoY4mbWBoijeLDGpAZBSPChnqtSRjp+T9UcouLCwGr5ooNyOQLoI3OVzU1bPQ==} - peerDependencies: - graphql: ^14.2.0 || ^15.0.0 || ^16.0.0 - dependencies: - graphql: 16.8.1 - graphql-type-json: 0.3.2(graphql@16.8.1) - - /graphql-http@1.22.0(graphql@16.8.1): - resolution: {integrity: sha512-9RBUlGJWBFqz9LwfpmAbjJL/8j/HCNkZwPBU5+Bfmwez+1Ay43DocMNQYpIWsWqH0Ftv6PTNAh2aRnnMCBJgLw==} - engines: {node: '>=12'} - peerDependencies: - graphql: '>=0.11 <=16' - dependencies: - graphql: 16.8.1 - - /graphql-tag@2.12.6(graphql@16.8.1): - resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} - engines: {node: '>=10'} - peerDependencies: - graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - graphql: 16.8.1 - tslib: 2.6.2 - - /graphql-type-json@0.3.2(graphql@16.8.1): - resolution: {integrity: sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==} - peerDependencies: - graphql: '>=0.8.0' - dependencies: - graphql: 16.8.1 - - /graphql@16.8.1: - resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} - engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - - /gzip-size@6.0.0: - resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} - engines: {node: '>=10'} - dependencies: - duplexer: 0.1.2 - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - - /hash-wasm@4.11.0: - resolution: {integrity: sha512-HVusNXlVqHe0fzIzdQOGolnFN6mX/fqcrSAOcTBXdvzrXVHwTz11vXeKRmkR5gTuwVpvHZEIyKoePDvuAR+XwQ==} - - /hasha@5.2.2: - resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} - engines: {node: '>=8'} - dependencies: - is-stream: 2.0.1 - type-fest: 0.8.1 - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - /header-case@2.0.4: - resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} - dependencies: - capital-case: 1.0.4 - tslib: 2.6.2 - - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /hosted-git-info@3.0.8: - resolution: {integrity: sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==} - engines: {node: '>=10'} - dependencies: - lru-cache: 6.0.0 - - /html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} - - /htmlparser2@6.1.0: - resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - domutils: 2.8.0 - entities: 2.2.0 - - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - - /http2-wrapper@1.0.3: - resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} - engines: {node: '>=10.19.0'} - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - - /http2-wrapper@2.2.1: - resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} - engines: {node: '>=10.19.0'} - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - - /icss-utils@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - /ignore@4.0.6: - resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} - engines: {node: '>= 4'} - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - - /immer@9.0.21: - resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} - - /immutable@3.7.6: - resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} - engines: {node: '>=0.8.0'} - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - /import-from@4.0.0: - resolution: {integrity: sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==} - engines: {node: '>=12.2'} - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - /inline-style-parser@0.1.1: - resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} - - /inquirer@7.3.3: - resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} - engines: {node: '>=8.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - run-async: 2.4.1 - rxjs: 6.6.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - - /invariant@2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - dependencies: - loose-envify: 1.4.0 - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - - /is-absolute-url@3.0.3: - resolution: {integrity: sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==} - engines: {node: '>=8'} - - /is-absolute@1.0.0: - resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} - engines: {node: '>=0.10.0'} - dependencies: - is-relative: 1.0.0 - is-windows: 1.0.2 - - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - /is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - requiresBuild: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - /is-ci@2.0.0: - resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} - hasBin: true - dependencies: - ci-info: 2.0.0 - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.2 - - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - dependencies: - is-typed-array: 1.1.13 - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - - /is-extglob@1.0.0: - resolution: {integrity: sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==} - engines: {node: '>=0.10.0'} - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.7 - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - - /is-glob@2.0.1: - resolution: {integrity: sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 1.0.0 - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - dependencies: - is-docker: 3.0.0 - - /is-invalid-path@0.1.0: - resolution: {integrity: sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-glob: 2.0.1 - - /is-lower-case@2.0.2: - resolution: {integrity: sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==} - dependencies: - tslib: 2.6.2 - - /is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - /is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: true - - /is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - - /is-promise@2.2.2: - resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - - /is-relative-url@3.0.0: - resolution: {integrity: sha512-U1iSYRlY2GIMGuZx7gezlB5dp1Kheaym7zKzO1PV06mOihiWTXejLwm4poEJysPyXF+HtK/BEd0DVlcCh30pEA==} - engines: {node: '>=8'} - dependencies: - is-absolute-url: 3.0.3 - - /is-relative@1.0.0: - resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} - engines: {node: '>=0.10.0'} - dependencies: - is-unc-path: 1.0.0 - - /is-root@2.1.0: - resolution: {integrity: sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==} - engines: {node: '>=6'} - - /is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - - /is-ssh@1.4.0: - resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==} - dependencies: - protocols: 2.0.1 - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.15 - - /is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - - /is-unc-path@1.0.0: - resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} - engines: {node: '>=0.10.0'} - dependencies: - unc-path-regex: 0.1.2 - - /is-upper-case@2.0.2: - resolution: {integrity: sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==} - dependencies: - tslib: 2.6.2 - - /is-valid-domain@0.1.6: - resolution: {integrity: sha512-ZKtq737eFkZr71At8NxOFcP9O1K89gW3DkdrGMpp1upr/ueWjj+Weh4l9AI4rN0Gt8W2M1w7jrG2b/Yv83Ljpg==} - dependencies: - punycode: 2.3.1 - - /is-valid-path@0.1.1: - resolution: {integrity: sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==} - engines: {node: '>=0.10.0'} - dependencies: - is-invalid-path: 0.1.0 - - /is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - - /is-weakset@2.0.3: - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - - /is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} - dependencies: - is-inside-container: 1.0.0 - - /is64bit@2.0.0: - resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} - engines: {node: '>=18'} - dependencies: - system-architecture: 0.1.0 - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - /isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.6 - set-function-name: 2.0.2 - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /javascript-stringify@2.1.0: - resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} - - /jest-worker@26.6.2: - resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 20.12.5 - merge-stream: 2.0.0 - supports-color: 7.2.0 - - /jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 20.12.5 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - - /joi@17.12.3: - resolution: {integrity: sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==} - dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.5 - '@sideway/formula': 3.0.1 - '@sideway/pinpoint': 2.0.0 - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - dependencies: - argparse: 2.0.1 - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - /json-loader@0.5.7: - resolution: {integrity: sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==} - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - dependencies: - minimist: 1.2.8 - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - /jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.2 - object.assign: 4.1.5 - object.values: 1.2.0 - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - - /klona@2.0.6: - resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} - engines: {node: '>= 8'} - - /language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} - - /language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - dependencies: - language-subtag-registry: 0.3.22 - - /latest-version@7.0.0: - resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} - engines: {node: '>=14.16'} - dependencies: - package-json: 8.1.1 - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - /linkfs@2.1.0: - resolution: {integrity: sha512-kmsGcmpvjStZ0ATjuHycBujtNnXiZR28BTivEu0gAMDTT7GEyodcK6zSRtu6xsrdorrPZEIN380x7BD7xEYkew==} - - /lmdb@2.5.2: - resolution: {integrity: sha512-V5V5Xa2Hp9i2XsbDALkBTeHXnBXh/lEmk9p22zdr7jtuOIY9TGhjK6vAvTpOOx9IKU4hJkRWZxn/HsvR1ELLtA==} - requiresBuild: true - dependencies: - msgpackr: 1.10.1 - node-addon-api: 4.3.0 - node-gyp-build-optional-packages: 5.0.3 - ordered-binary: 1.5.1 - weak-lru-cache: 1.2.2 - optionalDependencies: - '@lmdb/lmdb-darwin-arm64': 2.5.2 - '@lmdb/lmdb-darwin-x64': 2.5.2 - '@lmdb/lmdb-linux-arm': 2.5.2 - '@lmdb/lmdb-linux-arm64': 2.5.2 - '@lmdb/lmdb-linux-x64': 2.5.2 - '@lmdb/lmdb-win32-x64': 2.5.2 - - /lmdb@2.5.3: - resolution: {integrity: sha512-iBA0cb13CobBSoGJLfZgnrykLlfJipDAnvtf+YwIqqzBEsTeQYsXrHaSBkaHd5wCWeabwrNvhjZoFMUrlo+eLw==} - requiresBuild: true - dependencies: - msgpackr: 1.10.1 - node-addon-api: 4.3.0 - node-gyp-build-optional-packages: 5.0.3 - ordered-binary: 1.5.1 - weak-lru-cache: 1.2.2 - optionalDependencies: - '@lmdb/lmdb-darwin-arm64': 2.5.3 - '@lmdb/lmdb-darwin-x64': 2.5.3 - '@lmdb/lmdb-linux-arm': 2.5.3 - '@lmdb/lmdb-linux-arm64': 2.5.3 - '@lmdb/lmdb-linux-x64': 2.5.3 - '@lmdb/lmdb-win32-x64': 2.5.3 - - /loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} - engines: {node: '>=6.11.5'} - - /loader-utils@2.0.4: - resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} - engines: {node: '>=8.9.0'} - dependencies: - big.js: 5.2.2 - emojis-list: 3.0.0 - json5: 2.2.3 - - /loader-utils@3.2.1: - resolution: {integrity: sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==} - engines: {node: '>= 12.13.0'} - - /locate-path@3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - - /lock@1.1.0: - resolution: {integrity: sha512-NZQIJJL5Rb9lMJ0Yl1JoVr9GSdo4HTPsUEWsSFzB8dE8DSoiLCVavWZPi7Rnlv/o73u6I24S/XYc/NmG4l8EKA==} - - /lodash.clonedeep@4.5.0: - resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} - - /lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - - /lodash.deburr@4.1.0: - resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==} - - /lodash.every@4.6.0: - resolution: {integrity: sha512-isF82d+65/sNvQ3aaQAW7LLHnnTxSN/2fm4rhYyuufLzA4VtHz6y6S5vFwe6PQVr2xdqUOyxBbTNKDpnmeu50w==} - - /lodash.flattendeep@4.4.0: - resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} - - /lodash.foreach@4.5.0: - resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==} - - /lodash.map@4.6.0: - resolution: {integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==} - - /lodash.maxby@4.6.0: - resolution: {integrity: sha512-QfTqQTwzmKxLy7VZlbx2M/ipWv8DCQ2F5BI/MRxLharOQ5V78yMSuB+JE+EuUM22txYfj09R2Q7hUlEYj7KdNg==} - - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - /lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - - /lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - dependencies: - js-tokens: 4.0.0 - - /lower-case-first@2.0.2: - resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} - dependencies: - tslib: 2.6.2 - - /lower-case@2.0.2: - resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - dependencies: - tslib: 2.6.2 - - /lowercase-keys@2.0.0: - resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} - engines: {node: '>=8'} - - /lowercase-keys@3.0.0: - resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@4.0.0: - resolution: {integrity: sha512-WKhDkjlLwzE8jAQdQlsxLUQTPXLCKX/4cJk6s5AlRtJkDBk0IKH5O51bVDH61K9N4bhbbyvLM6EiOuE8ovApPA==} - dependencies: - pseudomap: 1.0.2 - yallist: 2.1.2 - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - - /lru-queue@0.1.0: - resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} - dependencies: - es5-ext: 0.10.64 - - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.1 - - /map-age-cleaner@0.1.3: - resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} - engines: {node: '>=6'} - dependencies: - p-defer: 1.0.0 - - /map-cache@0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - - /mdn-data@2.0.14: - resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} - - /meant@1.0.3: - resolution: {integrity: sha512-88ZRGcNxAq4EH38cQ4D85PM57pikCwS8Z99EWHODxN7KBY+UuPiqzRTtZzS8KTXO/ywSWbdjjJST2Hly/EQxLw==} - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - - /mem@8.1.1: - resolution: {integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==} - engines: {node: '>=10'} - dependencies: - map-age-cleaner: 0.1.3 - mimic-fn: 3.1.0 - - /memfs@3.6.0: - resolution: {integrity: sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ==} - engines: {node: '>= 4.0.0'} - deprecated: this will be v4 - dependencies: - fs-monkey: 1.0.5 - - /memoizee@0.4.15: - resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-weak-map: 2.0.3 - event-emitter: 0.3.5 - is-promise: 2.2.2 - lru-queue: 0.1.0 - next-tick: 1.1.0 - timers-ext: 0.1.7 - - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - - /mime@3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - /mimic-fn@3.1.0: - resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} - engines: {node: '>=8'} - - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - /mimic-response@1.0.1: - resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} - engines: {node: '>=4'} - - /mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - /mimic-response@4.0.0: - resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /mini-css-extract-plugin@1.6.2(webpack@5.91.0): - resolution: {integrity: sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.4.0 || ^5.0.0 - dependencies: - loader-utils: 2.0.4 - schema-utils: 3.3.0 - webpack: 5.91.0 - webpack-sources: 1.4.3 - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /mitt@1.2.0: - resolution: {integrity: sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==} - - /mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - requiresBuild: true - - /mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.8 - - /moment@2.30.1: - resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - /msgpackr-extract@3.0.2: - resolution: {integrity: sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==} - hasBin: true - requiresBuild: true - dependencies: - node-gyp-build-optional-packages: 5.0.7 - optionalDependencies: - '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.2 - '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.2 - '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.2 - '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.2 - '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.2 - '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.2 - optional: true - - /msgpackr@1.10.1: - resolution: {integrity: sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==} - optionalDependencies: - msgpackr-extract: 3.0.2 - - /multer@1.4.5-lts.1: - resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==} - engines: {node: '>= 6.0.0'} - dependencies: - append-field: 1.0.0 - busboy: 1.6.0 - concat-stream: 1.6.2 - mkdirp: 0.5.6 - object-assign: 4.1.1 - type-is: 1.6.18 - xtend: 4.0.2 - - /mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - - /napi-build-utils@1.0.2: - resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} - requiresBuild: true - - /natural-compare-lite@1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - - /next-tick@1.1.0: - resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - - /next@14.1.4(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-1WTaXeSrUwlz/XcnhGTY7+8eiaFvdet5z9u3V2jb+Ek1vFo0VhHKSAIJvDWfQpttWjnyw14kBeq28TPq7bTeEQ==} - engines: {node: '>=18.17.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - sass: - optional: true - dependencies: - '@next/env': 14.1.4 - '@swc/helpers': 0.5.2 - busboy: 1.6.0 - caniuse-lite: 1.0.30001607 - graceful-fs: 4.2.11 - postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(react@18.2.0) - optionalDependencies: - '@next/swc-darwin-arm64': 14.1.4 - '@next/swc-darwin-x64': 14.1.4 - '@next/swc-linux-arm64-gnu': 14.1.4 - '@next/swc-linux-arm64-musl': 14.1.4 - '@next/swc-linux-x64-gnu': 14.1.4 - '@next/swc-linux-x64-musl': 14.1.4 - '@next/swc-win32-arm64-msvc': 14.1.4 - '@next/swc-win32-ia32-msvc': 14.1.4 - '@next/swc-win32-x64-msvc': 14.1.4 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - - /no-case@3.0.4: - resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - dependencies: - lower-case: 2.0.2 - tslib: 2.6.2 - - /node-abi@3.57.0: - resolution: {integrity: sha512-Dp+A9JWxRaKuHP35H77I4kCKesDy5HUDEmScia2FyncMTOXASMyg251F5PhFoDA5uqBrDDffiLpbqnrZmNXW+g==} - engines: {node: '>=10'} - requiresBuild: true - dependencies: - semver: 7.6.0 - - /node-addon-api@4.3.0: - resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} - - /node-addon-api@6.1.0: - resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} - requiresBuild: true - - /node-addon-api@7.1.0: - resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==} - engines: {node: ^16 || ^18 || >= 20} - - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - - /node-gyp-build-optional-packages@5.0.3: - resolution: {integrity: sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==} - hasBin: true - - /node-gyp-build-optional-packages@5.0.7: - resolution: {integrity: sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==} - hasBin: true - requiresBuild: true - optional: true - - /node-html-parser@5.4.2: - resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} - dependencies: - css-select: 4.3.0 - he: 1.2.0 - - /node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - - /node-object-hash@2.3.10: - resolution: {integrity: sha512-jY5dPJzw6NHd/KPSfPKJ+IHoFS81/tJ43r34ZeNMXGzCOM8jwQDCD12HYayKIB6MuznrnqIYy2e891NA2g0ibA==} - engines: {node: '>=0.10.0'} - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@2.1.1: - resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} - engines: {node: '>=0.10.0'} - dependencies: - remove-trailing-separator: 1.1.0 - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - - /normalize-url@6.1.0: - resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} - engines: {node: '>=10'} - - /normalize-url@8.0.1: - resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} - engines: {node: '>=14.16'} - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - - /npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - dependencies: - boolbase: 1.0.0 - - /null-loader@4.0.1(webpack@5.91.0): - resolution: {integrity: sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - loader-utils: 2.0.4 - schema-utils: 3.3.0 - webpack: 5.91.0 - - /nullthrows@1.1.1: - resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - - /object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - - /object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - - /object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - - /object.hasown@1.1.4: - resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - - /object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - - /on-headers@1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - - /open@7.4.2: - resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - is-wsl: 2.2.0 - - /open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - - /opentracing@0.14.7: - resolution: {integrity: sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q==} - engines: {node: '>=0.10'} - - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - - /ordered-binary@1.5.1: - resolution: {integrity: sha512-5VyHfHY3cd0iza71JepYG50My+YUbrFtGoUz2ooEydPyPM7Aai/JW098juLr+RG6+rDJuzNNTsEQu2DZa1A41A==} - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - - /p-cancelable@2.1.1: - resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} - engines: {node: '>=8'} - - /p-cancelable@3.0.0: - resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} - engines: {node: '>=12.20'} - - /p-defer@1.0.0: - resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} - engines: {node: '>=4'} - - /p-defer@3.0.0: - resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} - engines: {node: '>=8'} - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - - /p-locate@3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - dependencies: - p-limit: 2.3.0 - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - /package-json@8.1.1: - resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} - engines: {node: '>=14.16'} - dependencies: - got: 12.6.1 - registry-auth-token: 5.0.2 - registry-url: 6.0.1 - semver: 7.6.0 - - /param-case@3.0.4: - resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} - dependencies: - dot-case: 3.0.4 - tslib: 2.6.2 - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - - /parse-filepath@1.0.2: - resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} - engines: {node: '>=0.8'} - dependencies: - is-absolute: 1.0.0 - map-cache: 0.2.2 - path-root: 0.1.1 - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.24.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - /parse-path@7.0.0: - resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==} - dependencies: - protocols: 2.0.1 - - /parse-url@8.1.0: - resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} - dependencies: - parse-path: 7.0.0 - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - - /pascal-case@3.1.2: - resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - - /password-prompt@1.1.3: - resolution: {integrity: sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==} - dependencies: - ansi-escapes: 4.3.2 - cross-spawn: 7.0.3 - - /path-case@3.0.4: - resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} - dependencies: - dot-case: 3.0.4 - tslib: 2.6.2 - - /path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - /path-root-regex@0.1.2: - resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} - engines: {node: '>=0.10.0'} - - /path-root@0.1.1: - resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} - engines: {node: '>=0.10.0'} - dependencies: - path-root-regex: 0.1.2 - - /path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: true - - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - /peek-readable@4.1.0: - resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==} - engines: {node: '>=8'} - - /physical-cpu-count@2.0.0: - resolution: {integrity: sha512-rxJOljMuWtYlvREBmd6TZYanfcPhNUKtGDZBjBBS8WG1dpN2iwPsRJZgQqN/OtJuiQckdRFOfzogqJClTrsi7g==} - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - - /pkg-up@3.1.0: - resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} - engines: {node: '>=8'} - dependencies: - find-up: 3.0.0 - - /platform@1.3.6: - resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - - /postcss-calc@8.2.4(postcss@8.4.38): - resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} - peerDependencies: - postcss: ^8.2.2 - dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - postcss-value-parser: 4.2.0 - - /postcss-colormin@5.3.1(postcss@8.4.38): - resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.23.0 - caniuse-api: 3.0.0 - colord: 2.9.3 - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-convert-values@5.1.3(postcss@8.4.38): - resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.23.0 - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-discard-comments@5.1.2(postcss@8.4.38): - resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - - /postcss-discard-duplicates@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - - /postcss-discard-empty@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - - /postcss-discard-overridden@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - - /postcss-flexbugs-fixes@5.0.2(postcss@8.4.38): - resolution: {integrity: sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==} - peerDependencies: - postcss: ^8.1.4 - dependencies: - postcss: 8.4.38 - - /postcss-loader@5.3.0(postcss@8.4.38)(webpack@5.91.0): - resolution: {integrity: sha512-/+Z1RAmssdiSLgIZwnJHwBMnlABPgF7giYzTN2NOfr9D21IJZ4mQC1R2miwp80zno9M4zMD/umGI8cR+2EL5zw==} - engines: {node: '>= 10.13.0'} - peerDependencies: - postcss: ^7.0.0 || ^8.0.1 - webpack: ^5.0.0 - dependencies: - cosmiconfig: 7.1.0 - klona: 2.0.6 - postcss: 8.4.38 - semver: 7.6.0 - webpack: 5.91.0 - - /postcss-merge-longhand@5.1.7(postcss@8.4.38): - resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - stylehacks: 5.1.1(postcss@8.4.38) - - /postcss-merge-rules@5.1.4(postcss@8.4.38): - resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.23.0 - caniuse-api: 3.0.0 - cssnano-utils: 3.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - - /postcss-minify-font-values@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-minify-gradients@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - colord: 2.9.3 - cssnano-utils: 3.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-minify-params@5.1.4(postcss@8.4.38): - resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.23.0 - cssnano-utils: 3.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-minify-selectors@5.2.1(postcss@8.4.38): - resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - - /postcss-modules-extract-imports@3.1.0(postcss@8.4.38): - resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - - /postcss-modules-local-by-default@4.0.5(postcss@8.4.38): - resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - postcss-value-parser: 4.2.0 - - /postcss-modules-scope@3.2.0(postcss@8.4.38): - resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - - /postcss-modules-values@4.0.0(postcss@8.4.38): - resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - - /postcss-normalize-charset@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - - /postcss-normalize-display-values@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-normalize-positions@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-normalize-repeat-style@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-normalize-string@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-normalize-timing-functions@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-normalize-unicode@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.23.0 - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-normalize-url@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - normalize-url: 6.1.0 - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-normalize-whitespace@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-ordered-values@5.1.3(postcss@8.4.38): - resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - cssnano-utils: 3.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-reduce-initial@5.1.2(postcss@8.4.38): - resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.23.0 - caniuse-api: 3.0.0 - postcss: 8.4.38 - - /postcss-reduce-transforms@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - - /postcss-selector-parser@6.0.16: - resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - /postcss-svgo@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - svgo: 2.8.0 - - /postcss-unique-selectors@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.2.0 - dev: false - - /postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.2.0 - - /prebuild-install@7.1.2: - resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} - engines: {node: '>=10'} - hasBin: true - requiresBuild: true - dependencies: - detect-libc: 2.0.3 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 1.0.2 - node-abi: 3.57.0 - pump: 3.0.0 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.1 - tunnel-agent: 0.6.0 - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - /prettier-plugin-packagejson@2.4.14(prettier@3.2.5): - resolution: {integrity: sha512-sli+gV5tW7uxvzDZQscaBtSfbyAW2ToL6n/HGt51PipwX9vI7M54vefG0mKSfklVkT29TNGO6Mo6g8c6Z79gmw==} - peerDependencies: - prettier: '>= 1.16.0' - peerDependenciesMeta: - prettier: - optional: true - dependencies: - prettier: 3.2.5 - sort-package-json: 2.10.0 - synckit: 0.9.0 - dev: true - - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - dev: true - - /pretty-error@2.1.2: - resolution: {integrity: sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==} - dependencies: - lodash: 4.17.21 - renderkid: 2.0.7 - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - /progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - - /promise@7.3.1: - resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} - dependencies: - asap: 2.0.6 - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - /proper-lockfile@4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - dependencies: - graceful-fs: 4.2.11 - retry: 0.12.0 - signal-exit: 3.0.7 - - /proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - - /protocols@2.0.1: - resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - - /pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - - /pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - - /query-string@6.14.1: - resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} - engines: {node: '>=6'} - dependencies: - decode-uri-component: 0.2.2 - filter-obj: 1.1.0 - split-on-first: 1.1.0 - strict-uri-encode: 2.0.0 - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - /queue-tick@1.0.1: - resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} - requiresBuild: true - - /quick-lru@5.1.1: - resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} - engines: {node: '>=10'} - - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - /raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - - /raw-loader@4.0.2(webpack@5.91.0): - resolution: {integrity: sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - loader-utils: 2.0.4 - schema-utils: 3.3.0 - webpack: 5.91.0 - - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - /react-dev-utils@12.0.1(eslint@7.32.0)(typescript@5.5.4)(webpack@5.91.0): - resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=2.7' - webpack: '>=4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@babel/code-frame': 7.24.2 - address: 1.2.2 - browserslist: 4.23.0 - chalk: 4.1.2 - cross-spawn: 7.0.3 - detect-port-alt: 1.1.6 - escape-string-regexp: 4.0.0 - filesize: 8.0.7 - find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(eslint@7.32.0)(typescript@5.5.4)(webpack@5.91.0) - global-modules: 2.0.0 - globby: 11.1.0 - gzip-size: 6.0.0 - immer: 9.0.21 - is-root: 2.1.0 - loader-utils: 3.2.1 - open: 8.4.2 - pkg-up: 3.1.0 - prompts: 2.4.2 - react-error-overlay: 6.0.11 - recursive-readdir: 2.2.3 - shell-quote: 1.8.1 - strip-ansi: 6.0.1 - text-table: 0.2.0 - typescript: 5.5.4 - webpack: 5.91.0 - transitivePeerDependencies: - - eslint - - supports-color - - vue-template-compiler - - /react-dom@18.2.0(react@18.2.0): - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} - peerDependencies: - react: ^18.2.0 - dependencies: - loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 - - /react-error-overlay@6.0.11: - resolution: {integrity: sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==} - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - /react-refresh@0.14.0: - resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} - engines: {node: '>=0.10.0'} - - /react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825(react@18.2.0)(webpack@5.91.0): - resolution: {integrity: sha512-JyCjbp6ZvkH/T0EuVPdceYlC8u5WqWDSJr2KxDvc81H2eJ+7zYUN++IcEycnR2F+HmER8QVgxfotnIx352zi+w==} - engines: {node: '>=0.10.0'} - peerDependencies: - react: 0.0.0-experimental-c8b778b7f-20220825 - webpack: ^5.59.0 - dependencies: - acorn: 6.4.2 - loose-envify: 1.4.0 - neo-async: 2.6.2 - react: 18.2.0 - webpack: 5.91.0 - - /react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /read@1.0.7: - resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} - engines: {node: '>=0.8'} - dependencies: - mute-stream: 0.0.8 - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - /readable-web-to-node-stream@3.0.2: - resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==} - engines: {node: '>=8'} - dependencies: - readable-stream: 3.6.2 - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - - /recursive-readdir@2.2.3: - resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} - engines: {node: '>=6.0.0'} - dependencies: - minimatch: 3.1.2 - - /redux-thunk@2.4.2(redux@4.2.1): - resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==} - peerDependencies: - redux: ^4 - dependencies: - redux: 4.2.1 - - /redux@4.2.1: - resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} - dependencies: - '@babel/runtime': 7.24.4 - - /reflect.getprototypeof@1.0.6: - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 - which-builtin-type: 1.1.3 - - /regenerate-unicode-properties@10.1.1: - resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} - engines: {node: '>=4'} - dependencies: - regenerate: 1.4.2 - - /regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - - /regenerator-runtime@0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - /regenerator-transform@0.15.2: - resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - dependencies: - '@babel/runtime': 7.24.4 - - /regex-escape@3.4.10: - resolution: {integrity: sha512-qEqf7uzW+iYcKNLMDFnMkghhQBnGdivT6KqVQyKsyjSWnoFyooXVnxrw9dtv3AFLnD6VBGXxtZGAQNFGFTnCqA==} - dev: true - - /regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - dev: true - - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - - /regexpp@3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - - /regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} - engines: {node: '>=4'} - dependencies: - '@babel/regjsgen': 0.8.0 - regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.1 - regjsparser: 0.9.1 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 - - /registry-auth-token@5.0.2: - resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} - engines: {node: '>=14'} - dependencies: - '@pnpm/npm-conf': 2.2.2 - - /registry-url@6.0.1: - resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} - engines: {node: '>=12'} - dependencies: - rc: 1.2.8 - - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - dependencies: - jsesc: 0.5.0 - dev: true - - /regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} - hasBin: true - dependencies: - jsesc: 0.5.0 - - /relay-runtime@12.0.0: - resolution: {integrity: sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==} - dependencies: - '@babel/runtime': 7.24.4 - fbjs: 3.0.5 - invariant: 2.2.4 - transitivePeerDependencies: - - encoding - - /remove-trailing-separator@1.1.0: - resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} - - /renderkid@2.0.7: - resolution: {integrity: sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==} - dependencies: - css-select: 4.3.0 - dom-converter: 0.2.0 - htmlparser2: 6.1.0 - lodash: 4.17.21 - strip-ansi: 3.0.1 - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - /require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - - /require-package-name@2.0.1: - resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} - - /resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - - /resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - /responselike@2.0.1: - resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} - dependencies: - lowercase-keys: 2.0.0 - - /responselike@3.0.0: - resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} - engines: {node: '>=14.16'} - dependencies: - lowercase-keys: 3.0.0 - - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - /rimraf@2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - dependencies: - glob: 7.2.3 - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - dependencies: - glob: 7.2.3 - - /run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - - /rxjs@6.6.7: - resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} - engines: {npm: '>=2.0.0'} - dependencies: - tslib: 1.14.1 - - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - /scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} - dependencies: - loose-envify: 1.4.0 - - /schema-utils@2.7.0: - resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} - engines: {node: '>= 8.9.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - - /schema-utils@2.7.1: - resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} - engines: {node: '>= 8.9.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - - /schema-utils@3.3.0: - resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - dependencies: - lru-cache: 6.0.0 - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - - /sentence-case@3.0.4: - resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - upper-case-first: 2.0.2 - - /serialize-javascript@5.0.1: - resolution: {integrity: sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==} - dependencies: - randombytes: 2.1.0 - - /serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - dependencies: - randombytes: 2.1.0 - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - /setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - /shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - dependencies: - kind-of: 6.0.3 - - /shallow-compare@1.2.2: - resolution: {integrity: sha512-LUMFi+RppPlrHzbqmFnINTrazo0lPNwhcgzuAXVVcfy/mqPDrQmHAyz5bvV0gDAuRFrk804V0HpQ6u9sZ0tBeg==} - - /sharp@0.32.6: - resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} - engines: {node: '>=14.15.0'} - requiresBuild: true - dependencies: - color: 4.2.3 - detect-libc: 2.0.3 - node-addon-api: 6.1.0 - prebuild-install: 7.1.2 - semver: 7.6.0 - simple-get: 4.0.1 - tar-fs: 3.0.5 - tunnel-agent: 0.6.0 - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - /shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - /signedsource@1.0.0: - resolution: {integrity: sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==} - - /simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - requiresBuild: true - - /simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - requiresBuild: true - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - - /simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - requiresBuild: true - dependencies: - is-arrayish: 0.3.2 - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - - /slugify@1.6.6: - resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} - engines: {node: '>=8.0.0'} - - /snake-case@3.0.4: - resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} - dependencies: - dot-case: 3.0.4 - tslib: 2.6.2 - - /socket.io-adapter@2.5.4: - resolution: {integrity: sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==} - dependencies: - debug: 4.3.4 - ws: 8.11.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - /socket.io-client@4.7.1: - resolution: {integrity: sha512-Qk3Xj8ekbnzKu3faejo4wk2MzXA029XppiXtTF/PkbTg+fcwaTw1PlDrTrrrU4mKoYC4dvlApOnSeyLCKwek2w==} - engines: {node: '>=10.0.0'} - dependencies: - '@socket.io/component-emitter': 3.1.0 - debug: 4.3.4 - engine.io-client: 6.5.3 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - /socket.io-parser@4.2.4: - resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} - engines: {node: '>=10.0.0'} - dependencies: - '@socket.io/component-emitter': 3.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - - /socket.io@4.7.1: - resolution: {integrity: sha512-W+utHys2w//dhFjy7iQQu9sGd3eokCjGbl2r59tyLqNiJJBdIebn3GAKEXBr3osqHTObJi2die/25bCx2zsaaw==} - engines: {node: '>=10.0.0'} - dependencies: - accepts: 1.3.8 - base64id: 2.0.0 - cors: 2.8.5 - debug: 4.3.4 - engine.io: 6.5.4 - socket.io-adapter: 2.5.4 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - /sort-object-keys@1.1.3: - resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - dev: true - - /sort-package-json@2.10.0: - resolution: {integrity: sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==} - dependencies: - detect-indent: 7.0.1 - detect-newline: 4.0.1 - get-stdin: 9.0.0 - git-hooks-list: 3.1.0 - globby: 13.2.2 - is-plain-obj: 4.1.0 - semver: 7.6.0 - sort-object-keys: 1.1.3 - dev: true - - /source-list-map@2.0.1: - resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - /source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - dev: true - - /split-on-first@1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} - - /sponge-case@1.0.1: - resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==} - dependencies: - tslib: 2.6.2 - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - /stable@0.1.8: - resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} - deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' - - /stack-trace@0.0.10: - resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} - - /stackframe@1.3.4: - resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - - /streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - - /streamx@2.16.1: - resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==} - requiresBuild: true - dependencies: - fast-fifo: 1.3.2 - queue-tick: 1.0.1 - optionalDependencies: - bare-events: 2.2.2 - - /strict-uri-encode@2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} - - /string-natural-compare@3.0.1: - resolution: {integrity: sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==} - - /string-similarity@1.2.2: - resolution: {integrity: sha512-IoHUjcw3Srl8nsPlW04U3qwWPk3oG2ffLM0tN853d/E/JlIvcmZmDY2Kz5HzKp4lEi2T7QD7Zuvjq/1rDw+XcQ==} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - dependencies: - lodash.every: 4.6.0 - lodash.flattendeep: 4.4.0 - lodash.foreach: 4.5.0 - lodash.map: 4.6.0 - lodash.maxby: 4.6.0 - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.2 - side-channel: 1.0.6 - - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - requiresBuild: true - dependencies: - safe-buffer: 5.2.1 - - /strip-ansi@3.0.1: - resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} - engines: {node: '>=0.10.0'} - dependencies: - ansi-regex: 2.1.1 - - /strip-ansi@5.2.0: - resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} - engines: {node: '>=6'} - dependencies: - ansi-regex: 4.1.1 - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - requiresBuild: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - /strtok3@6.3.0: - resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} - engines: {node: '>=10'} - dependencies: - '@tokenizer/token': 0.3.0 - peek-readable: 4.1.0 - - /style-loader@2.0.0(webpack@5.91.0): - resolution: {integrity: sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - loader-utils: 2.0.4 - schema-utils: 3.3.0 - webpack: 5.91.0 - - /style-to-object@0.4.4: - resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} - dependencies: - inline-style-parser: 0.1.1 - - /styled-jsx@5.1.1(react@18.2.0): - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - client-only: 0.0.1 - react: 18.2.0 - dev: false - - /stylehacks@5.1.1(postcss@8.4.38): - resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.23.0 - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - - /sudo-prompt@8.2.5: - resolution: {integrity: sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==} - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - /svgo@2.8.0: - resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} - engines: {node: '>=10.13.0'} - hasBin: true - dependencies: - '@trysound/sax': 0.2.0 - commander: 7.2.0 - css-select: 4.3.0 - css-tree: 1.1.3 - csso: 4.2.0 - picocolors: 1.0.0 - stable: 0.1.8 - - /swap-case@2.0.2: - resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==} - dependencies: - tslib: 2.6.2 - - /synckit@0.9.0: - resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.2 - dev: true - - /system-architecture@0.1.0: - resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} - engines: {node: '>=18'} - - /table@6.8.2: - resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} - engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.12.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /tapable@1.1.3: - resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} - engines: {node: '>=6'} - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - - /tar-fs@2.1.1: - resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} - requiresBuild: true - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.0 - tar-stream: 2.2.0 - - /tar-fs@3.0.5: - resolution: {integrity: sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==} - requiresBuild: true - dependencies: - pump: 3.0.0 - tar-stream: 3.1.7 - optionalDependencies: - bare-fs: 2.2.3 - bare-path: 2.1.1 - - /tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - - /tar-stream@3.1.7: - resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} - requiresBuild: true - dependencies: - b4a: 1.6.6 - fast-fifo: 1.3.2 - streamx: 2.16.1 - - /terser-webpack-plugin@5.3.10(webpack@5.91.0): - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.30.3 - webpack: 5.91.0 - - /terser@5.30.3: - resolution: {integrity: sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 - commander: 2.20.3 - source-map-support: 0.5.21 - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - /timers-ext@0.1.7: - resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} - dependencies: - es5-ext: 0.10.64 - next-tick: 1.1.0 - - /title-case@3.0.3: - resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} - dependencies: - tslib: 2.6.2 - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - - /tmp@0.2.3: - resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} - engines: {node: '>=14.14'} - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - - /token-types@4.2.1: - resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==} - engines: {node: '>=10'} - dependencies: - '@tokenizer/token': 0.3.0 - ieee754: 1.2.1 - - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - /true-case-path@2.2.1: - resolution: {integrity: sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==} - - /ts-api-utils@1.3.0(typescript@5.5.4): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - - /tslib@2.4.1: - resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} - - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - /tsutils@3.21.0(typescript@5.5.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.4 - - /tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - requiresBuild: true - dependencies: - safe-buffer: 5.2.1 - - /turbo-darwin-64@2.0.3: - resolution: {integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: {integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: {integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: {integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: {integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: {integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: {integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - - /type-of@2.0.1: - resolution: {integrity: sha512-39wxbwHdQ2sTiBB8wAzKfQ9GN+om8w+sjNWzr+vZJR5AMD5J+J7Yc8AtXnU9r/r2c8XiDZ/smxutDmZehX/qpQ==} - - /type@2.7.2: - resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} - - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 - - /typedarray-to-buffer@3.1.5: - resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - dependencies: - is-typedarray: 1.0.0 - - /typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - - /ua-parser-js@1.0.37: - resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - - /unc-path-regex@0.1.2: - resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} - engines: {node: '>=0.10.0'} - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - /unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} - engines: {node: '>=4'} - - /unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 - unicode-property-aliases-ecmascript: 2.1.0 - - /unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} - engines: {node: '>=4'} - - /unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} - engines: {node: '>=4'} - - /unique-string@2.0.0: - resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} - engines: {node: '>=8'} - dependencies: - crypto-random-string: 2.0.0 - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - /unixify@1.0.0: - resolution: {integrity: sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==} - engines: {node: '>=0.10.0'} - dependencies: - normalize-path: 2.1.1 - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - /update-browserslist-db@1.0.13(browserslist@4.23.0): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.0 - - /upper-case-first@2.0.2: - resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} - dependencies: - tslib: 2.6.2 - - /upper-case@2.0.2: - resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} - dependencies: - tslib: 2.6.2 - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - - /url-loader@4.1.1(file-loader@6.2.0)(webpack@5.91.0): - resolution: {integrity: sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==} - engines: {node: '>= 10.13.0'} - peerDependencies: - file-loader: '*' - webpack: ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - file-loader: - optional: true - dependencies: - file-loader: 6.2.0(webpack@5.91.0) - loader-utils: 2.0.4 - mime-types: 2.1.35 - schema-utils: 3.3.0 - webpack: 5.91.0 - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - /utila@0.4.0: - resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} - - /utility-types@3.11.0: - resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==} - engines: {node: '>= 4'} - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - /v8-compile-cache@2.4.0: - resolution: {integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==} - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /value-or-promise@1.0.12: - resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} - engines: {node: '>=12'} - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - - /watchpack@2.4.1: - resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} - engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - - /weak-lru-cache@1.2.2: - resolution: {integrity: sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==} - - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - /webpack-dev-middleware@4.3.0(webpack@5.91.0): - resolution: {integrity: sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==} - engines: {node: '>= v10.23.3'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - colorette: 1.4.0 - mem: 8.1.1 - memfs: 3.6.0 - mime-types: 2.1.35 - range-parser: 1.2.1 - schema-utils: 3.3.0 - webpack: 5.91.0 - - /webpack-merge@5.10.0: - resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} - engines: {node: '>=10.0.0'} - dependencies: - clone-deep: 4.0.1 - flat: 5.0.2 - wildcard: 2.0.1 - - /webpack-sources@1.4.3: - resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} - dependencies: - source-list-map: 2.0.1 - source-map: 0.6.1 - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - - /webpack-stats-plugin@1.1.3: - resolution: {integrity: sha512-yUKYyy+e0iF/w31QdfioRKY+h3jDBRpthexBOWGKda99iu2l/wxYsI/XqdlP5IU58/0KB9CsJZgWNAl+/MPkRw==} - - /webpack-virtual-modules@0.5.0: - resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - - /webpack@5.91.0: - resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.0 - es-module-lexer: 1.5.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.91.0) - watchpack: 2.4.1 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.2 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.2 - which-typed-array: 1.1.15 - - /which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.3 - - /which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.2 - - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - dependencies: - isexe: 2.0.0 - - /widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} - dependencies: - string-width: 4.2.3 - - /wildcard@2.0.1: - resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} - - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /write-file-atomic@3.0.3: - resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - dependencies: - imurmurhash: 0.1.4 - is-typedarray: 1.0.0 - signal-exit: 3.0.7 - typedarray-to-buffer: 3.1.5 - - /ws@8.11.0: - resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - /xdg-basedir@4.0.0: - resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} - engines: {node: '>=8'} - - /xmlhttprequest-ssl@2.0.0: - resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} - engines: {node: '>=0.4.0'} - - /xstate@4.38.3: - resolution: {integrity: sha512-SH7nAaaPQx57dx6qvfcIgqKRXIh4L0A1iYEqim4s1u7c9VoCgzZc+63FY90AKU4ZzOC2cfJzTnpO4zK7fCUzzw==} - - /xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - - /xxhash-wasm@0.4.2: - resolution: {integrity: sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA==} - - /y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - - /yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - /yaml-loader@0.8.1: - resolution: {integrity: sha512-BCEndnUoi3BaZmePkwGGe93txRxLgMhBa/gE725v1/GHnura8QvNs7c4+4C1yyhhKoj3Dg63M7IqhA++15j6ww==} - engines: {node: '>= 14'} - dependencies: - javascript-stringify: 2.1.0 - loader-utils: 2.0.4 - yaml: 2.4.1 - - /yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - - /yaml@2.4.1: - resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} - engines: {node: '>= 14'} - hasBin: true - - /yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - - /yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 18.1.3 - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - /yoga-layout-prebuilt@1.10.0: - resolution: {integrity: sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==} - engines: {node: '>=8'} - dependencies: - '@types/yoga-layout': 1.9.2 - - /yurnalist@2.1.0: - resolution: {integrity: sha512-PgrBqosQLM3gN2xBFIMDLACRTV9c365VqityKKpSTWpwR+U4LAFR3rSVyEoscWlu3EzX9+Y0I86GXUKxpHFl6w==} - engines: {node: '>=4.0.0'} - dependencies: - chalk: 2.4.2 - inquirer: 7.3.3 - is-ci: 2.0.0 - read: 1.0.7 - strip-ansi: 5.2.0 diff --git a/examples/with-nestjs/.eslintrc.js b/examples/with-nestjs/.eslintrc.js deleted file mode 100644 index e928b8686408e..0000000000000 --- a/examples/with-nestjs/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -// This configuration only applies to the package manager root. -/** @type {import("eslint").Linter.Config} */ -module.exports = { - ignorePatterns: ["apps/**", "packages/**"], - extends: ["@repo/eslint-config/library.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-nestjs/.prettierrc.js b/examples/with-nestjs/.prettierrc.js deleted file mode 100644 index 56640d785bb52..0000000000000 --- a/examples/with-nestjs/.prettierrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("prettier").Config} */ -module.exports = { - ...require('@repo/eslint-config/prettier-base'), -}; diff --git a/examples/with-nestjs/README.md b/examples/with-nestjs/README.md deleted file mode 100644 index 9f25bd8f8ec43..0000000000000 --- a/examples/with-nestjs/README.md +++ /dev/null @@ -1,120 +0,0 @@ -# Turborepo starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```bash -npx create-turbo@latest -e with-nestjs -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - - . - ├── apps - │ ├── api # NestJS app (https://nestjs.com). - │ └── web # Next.js app (https://nextjs.org). - └── packages - ├── @repo/api # Shared `NestJS` resources. - ├── @repo/eslint-config # `eslint` configurations (includes `prettier`) - ├── @repo/jest-config # `jest` configurations - ├── @repo/typescript-config # `tsconfig.json`s used throughout the monorepo - └── @repo/ui # Shareable stub React component library. - -Each package and application are 100% [TypeScript](https://www.typescriptlang.org/) safe. - -### Utilities - -This `Turborepo` has some additional tools already set for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type-safety -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting -- [Jest](https://prettier.io) & [Playwright](https://playwright.dev/) for testing - -### Commands - -This `Turborepo` already configured useful commands for all your apps and packages. - -#### Build - -```bash -# Will build all the app & packages with the supported `build` script. -pnpm run build - -# â„¹ï¸ If you plan to only build apps individually, -# Please make sure you've built the packages first. -``` - -#### Develop - -```bash -# Will run the development server for all the app & packages with the supported `dev` script. -pnpm run dev -``` - -#### test - -```bash -# Will launch a test suites for all the app & packages with the supported `test` script. -pnpm run test - -# You can launch e2e testes with `test:e2e` -pnpm run test:e2e - -# See `@repo/jest-config` to customize the behavior. -``` - -#### Lint - -```bash -# Will lint all the app & packages with the supported `lint` script. -# See `@repo/eslint-config` to customize the behavior. -pnpm run lint -``` - -#### Format - -```bash -# Will format all the supported `.ts,.js,json,.tsx,.jsx` files. -# See `@repo/eslint-config/prettier-base.js` to customize the behavior. -pnpm format -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -```bash -npx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: - -```bash -npx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/with-nestjs/apps/api/.eslintrc.js b/examples/with-nestjs/apps/api/.eslintrc.js deleted file mode 100644 index 0ad04032784d2..0000000000000 --- a/examples/with-nestjs/apps/api/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ['@repo/eslint-config/nest.js'], - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - sourceType: 'module', - }, -}; diff --git a/examples/with-nestjs/apps/api/.prettierrc.js b/examples/with-nestjs/apps/api/.prettierrc.js deleted file mode 100644 index 56640d785bb52..0000000000000 --- a/examples/with-nestjs/apps/api/.prettierrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("prettier").Config} */ -module.exports = { - ...require('@repo/eslint-config/prettier-base'), -}; diff --git a/examples/with-nestjs/apps/api/README.md b/examples/with-nestjs/apps/api/README.md deleted file mode 100644 index 8560acd226524..0000000000000 --- a/examples/with-nestjs/apps/api/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# With-NestJs | API - -## Getting Started - -First, run the development server: - -```bash -pnpm run dev -``` - -By default, your server will run at [http://localhost:3000](http://localhost:3000). You can use your favorite API platform like [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/) to test your APIs - -You can start editing the demo **APIs** by modifying [linksService](./src/links/links.service.ts) provider. - -### âš ï¸ Note about build - -If you plan to only build this app. Please make sure you've built the packages first. - -## Learn More - -To learn more about NestJs, take a look at the following resources: - -- [Official Documentation](https://docs.nestjs.com) - A progressive Node.js framework for building efficient, reliable and scalable server-side applications. -- [Official NestJS Courses](https://courses.nestjs.com) - Learn everything you need to master NestJS and tackle modern backend applications at any scale. -- [GitHub Repo](https://github.com/nestjs/nest) diff --git a/examples/with-nestjs/apps/api/src/app.controller.ts b/examples/with-nestjs/apps/api/Source/app.controller.ts similarity index 100% rename from examples/with-nestjs/apps/api/src/app.controller.ts rename to examples/with-nestjs/apps/api/Source/app.controller.ts diff --git a/examples/with-nestjs/apps/api/src/app.module.ts b/examples/with-nestjs/apps/api/Source/app.module.ts similarity index 100% rename from examples/with-nestjs/apps/api/src/app.module.ts rename to examples/with-nestjs/apps/api/Source/app.module.ts diff --git a/examples/with-nestjs/apps/api/src/app.service.ts b/examples/with-nestjs/apps/api/Source/app.service.ts similarity index 100% rename from examples/with-nestjs/apps/api/src/app.service.ts rename to examples/with-nestjs/apps/api/Source/app.service.ts diff --git a/examples/with-nestjs/apps/api/src/links/links.controller.ts b/examples/with-nestjs/apps/api/Source/links/links.controller.ts similarity index 100% rename from examples/with-nestjs/apps/api/src/links/links.controller.ts rename to examples/with-nestjs/apps/api/Source/links/links.controller.ts diff --git a/examples/with-nestjs/apps/api/src/links/links.module.ts b/examples/with-nestjs/apps/api/Source/links/links.module.ts similarity index 100% rename from examples/with-nestjs/apps/api/src/links/links.module.ts rename to examples/with-nestjs/apps/api/Source/links/links.module.ts diff --git a/examples/with-nestjs/apps/api/src/links/links.service.ts b/examples/with-nestjs/apps/api/Source/links/links.service.ts similarity index 100% rename from examples/with-nestjs/apps/api/src/links/links.service.ts rename to examples/with-nestjs/apps/api/Source/links/links.service.ts diff --git a/examples/with-nestjs/apps/api/src/main.ts b/examples/with-nestjs/apps/api/Source/main.ts similarity index 100% rename from examples/with-nestjs/apps/api/src/main.ts rename to examples/with-nestjs/apps/api/Source/main.ts diff --git a/examples/with-nestjs/apps/api/package.json b/examples/with-nestjs/apps/api/package.json index 0832931d25226..d03a4612f440e 100644 --- a/examples/with-nestjs/apps/api/package.json +++ b/examples/with-nestjs/apps/api/package.json @@ -1,45 +1,35 @@ { - "name": "api", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "nest start --watch", - "build": "nest build", - "start": "nest start", - "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", - "test": "jest", - "test:watch": "jest --watch", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"" - }, - "dependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@repo/api": "workspace:*", - "reflect-metadata": "^0.2.0", - "rxjs": "^7.8.1" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@nestjs/cli": "^10.0.0", - "@nestjs/schematics": "^10.0.0", - "@nestjs/testing": "^10.0.0", - "@repo/eslint-config": "workspace:*", - "@repo/jest-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/express": "^4.17.17", - "@types/node": "^20.3.1", - "@types/supertest": "^6.0.0", - "jest": "^29.7.0", - "source-map-support": "^0.5.21", - "supertest": "^6.3.3", - "ts-jest": "^29.2.5", - "ts-loader": "^9.4.3", - "ts-node": "^10.9.2", - "tsconfig-paths": "^4.2.0", - "typescript": "5.5.4" - } + "name": "api", + "scripts": { + "build": "nest build", + "dev": "nest start --watch", + "start": "nest start", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json", + "test:watch": "jest --watch" + }, + "dependencies": { + "@nestjs/common": "11.0.9", + "@nestjs/core": "11.0.9", + "@nestjs/platform-express": "11.0.9", + "@repo/api": "workspace:*", + "reflect-metadata": "0.2.2", + "rxjs": "7.8.1" + }, + "devDependencies": { + "@nestjs/cli": "11.0.2", + "@nestjs/schematics": "11.0.0", + "@nestjs/testing": "11.0.9", + "@repo/eslint-config": "workspace:*", + "@repo/jest-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1", + "@types/supertest": "6.0.2", + "source-map-support": "0.5.21", + "supertest": "7.0.0", + "ts-loader": "9.5.2", + "tsconfig-paths": "4.2.0" + } } diff --git a/examples/with-nestjs/apps/api/src/app.controller.spec.ts b/examples/with-nestjs/apps/api/src/app.controller.spec.ts deleted file mode 100644 index 939c4ac913396..0000000000000 --- a/examples/with-nestjs/apps/api/src/app.controller.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { describe, it, expect, beforeEach } from '@jest/globals'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - - describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); -}); diff --git a/examples/with-nestjs/apps/api/src/links/links.controller.spec.ts b/examples/with-nestjs/apps/api/src/links/links.controller.spec.ts deleted file mode 100644 index 23368ce420c74..0000000000000 --- a/examples/with-nestjs/apps/api/src/links/links.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { describe, it, expect, beforeEach } from '@jest/globals'; - -import { LinksController } from './links.controller'; -import { LinksService } from './links.service'; - -describe('LinksController', () => { - let controller: LinksController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [LinksController], - providers: [LinksService], - }).compile(); - - controller = module.get(LinksController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/examples/with-nestjs/apps/api/src/links/links.service.spec.ts b/examples/with-nestjs/apps/api/src/links/links.service.spec.ts deleted file mode 100644 index 71cfcbccefb2f..0000000000000 --- a/examples/with-nestjs/apps/api/src/links/links.service.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { describe, it, expect, beforeEach } from '@jest/globals'; -import { LinksService } from './links.service'; - -describe('LinksService', () => { - let service: LinksService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [LinksService], - }).compile(); - - service = module.get(LinksService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/examples/with-nestjs/apps/api/test/app.e2e-spec.ts b/examples/with-nestjs/apps/api/test/app.e2e-spec.ts deleted file mode 100644 index 6e55bca0066b1..0000000000000 --- a/examples/with-nestjs/apps/api/test/app.e2e-spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import { describe, it, beforeEach } from '@jest/globals'; -import request from 'supertest'; -import { AppModule } from './../src/app.module'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); - }); -}); diff --git a/examples/with-nestjs/apps/api/test/jest-e2e.json b/examples/with-nestjs/apps/api/test/jest-e2e.json deleted file mode 100644 index e9d912f3e3cef..0000000000000 --- a/examples/with-nestjs/apps/api/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} diff --git a/examples/with-nestjs/apps/web/.eslintrc.js b/examples/with-nestjs/apps/web/.eslintrc.js deleted file mode 100644 index 67fb72393f941..0000000000000 --- a/examples/with-nestjs/apps/web/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ['@repo/eslint-config/next.js'], - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-nestjs/apps/web/.prettierrc.js b/examples/with-nestjs/apps/web/.prettierrc.js deleted file mode 100644 index 56640d785bb52..0000000000000 --- a/examples/with-nestjs/apps/web/.prettierrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("prettier").Config} */ -module.exports = { - ...require('@repo/eslint-config/prettier-base'), -}; diff --git a/examples/with-nestjs/apps/web/README.md b/examples/with-nestjs/apps/web/README.md deleted file mode 100644 index 44677a7b64535..0000000000000 --- a/examples/with-nestjs/apps/web/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# With-NestJs | Web - -## Getting Started - -> ðŸ This app depends on the [apps/api](../api/README.md) server. make sure your server is running at the port `3000` - -Run the development server: - -```bash -pnpm run dev -``` - -Open [localhost:3001](http://localhost:3001) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, as `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). - -### âš ï¸ Note about build - -If you plan to only build this app. Please make sure you've built the packages first. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-nestjs/apps/web/package.json b/examples/with-nestjs/apps/web/package.json index dd4403ecfb4e0..7ac2929e091a1 100644 --- a/examples/with-nestjs/apps/web/package.json +++ b/examples/with-nestjs/apps/web/package.json @@ -1,37 +1,22 @@ { - "name": "web", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "next dev --port 3001", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0", - "test": "jest", - "test:watch": "jest --watch", - "test:e2e": "playwright test" - }, - "dependencies": { - "@repo/ui": "workspace:*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@next/eslint-plugin-next": "^14.1.1", - "@playwright/test": "^1.44.0", - "@repo/api": "workspace:*", - "@repo/eslint-config": "workspace:*", - "@repo/jest-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@testing-library/jest-dom": "^6.4.5", - "@testing-library/react": "^15.0.7", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "jest": "^29.7.0", - "jest-environment-jsdom": "^29.7.0", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev --port 3001", + "start": "next start", + "test:e2e": "playwright test", + "test:watch": "jest --watch" + }, + "dependencies": { + "@repo/ui": "workspace:*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/api": "workspace:*", + "@repo/eslint-config": "workspace:*", + "@repo/jest-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1", + "jest-environment-jsdom": "29.7.0" + } } diff --git a/examples/with-nestjs/apps/web/test/e2e/page.e2e-spec.ts b/examples/with-nestjs/apps/web/test/e2e/page.e2e-spec.ts deleted file mode 100644 index 109d9f5c2d7a9..0000000000000 --- a/examples/with-nestjs/apps/web/test/e2e/page.e2e-spec.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test.describe('Root page', () => { - test('should reach the home page', async ({ page }) => { - const response = await page.request.get('/'); - - await expect(response).toBeOK(); - }); -}); diff --git a/examples/with-nestjs/apps/web/test/layout.spec.tsx b/examples/with-nestjs/apps/web/test/layout.spec.tsx deleted file mode 100644 index 82d6383e775ea..0000000000000 --- a/examples/with-nestjs/apps/web/test/layout.spec.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { metadata } from '../app/layout'; -import { describe, it, expect } from '@jest/globals'; - -describe('Root layout', () => { - describe('metadata', () => { - it('should be exported', () => { - expect(metadata).toBeDefined(); - }); - - it('should contain a `title` and `description`', () => { - expect(metadata).toHaveProperty('title'); - expect(metadata).toHaveProperty('description'); - }); - }); -}); diff --git a/examples/with-nestjs/apps/web/test/page.spec.tsx b/examples/with-nestjs/apps/web/test/page.spec.tsx deleted file mode 100644 index 56c1a40ee7fcc..0000000000000 --- a/examples/with-nestjs/apps/web/test/page.spec.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { render } from '@testing-library/react'; -import { describe, it, expect, jest, afterAll } from '@jest/globals'; - -import RootPage from '../app/page'; - -window.fetch = jest.fn().mockImplementation(() => - Promise.resolve({ - ok: true, - json: () => [], - }) -); - -describe('Root page', () => { - const { container, unmount } = render( - - ); - - it('should match the snapshot', () => { - expect(container).toMatchSnapshot(); - }); - - it('should have the correct tree parent', () => { - expect(container).toBeInstanceOf(HTMLDivElement); - }); - - afterAll(() => { - unmount(); - }); -}); diff --git a/examples/with-nestjs/package.json b/examples/with-nestjs/package.json index a6613f03914d0..acadb14928dfe 100644 --- a/examples/with-nestjs/package.json +++ b/examples/with-nestjs/package.json @@ -1,26 +1,15 @@ { - "name": "my-turborepo", - "version": "0.0.0", - "private": true, - "description": "", - "author": "", - "license": "UNLICENSED", - "scripts": { - "dev": "turbo dev", - "build": "turbo build", - "test": "turbo test", - "test:e2e": "turbo test:e2e", - "lint": "turbo lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "prettier": "^3.2.5", - "turbo": "^2.0.4" - }, - "packageManager": "pnpm@8.15.5", - "engines": { - "node": ">=18" - } + "name": "my-turborepo", + "description": "", + "scripts": { + "build": "turbo build", + "dev": "turbo dev", + "test:e2e": "turbo test:e2e" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "turbo": "2.4.2" + } } diff --git a/examples/with-nestjs/packages/api/.eslintrc.js b/examples/with-nestjs/packages/api/.eslintrc.js deleted file mode 100644 index 0ad04032784d2..0000000000000 --- a/examples/with-nestjs/packages/api/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ['@repo/eslint-config/nest.js'], - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - sourceType: 'module', - }, -}; diff --git a/examples/with-nestjs/packages/api/.prettierrc.js b/examples/with-nestjs/packages/api/.prettierrc.js deleted file mode 100644 index 56640d785bb52..0000000000000 --- a/examples/with-nestjs/packages/api/.prettierrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("prettier").Config} */ -module.exports = { - ...require('@repo/eslint-config/prettier-base'), -}; diff --git a/examples/with-nestjs/packages/api/src/index.ts b/examples/with-nestjs/packages/api/Source/index.ts similarity index 100% rename from examples/with-nestjs/packages/api/src/index.ts rename to examples/with-nestjs/packages/api/Source/index.ts diff --git a/examples/with-nestjs/packages/api/src/links/dto/create-link.dto.ts b/examples/with-nestjs/packages/api/Source/links/dto/create-link.dto.ts similarity index 100% rename from examples/with-nestjs/packages/api/src/links/dto/create-link.dto.ts rename to examples/with-nestjs/packages/api/Source/links/dto/create-link.dto.ts diff --git a/examples/with-nestjs/packages/api/src/links/dto/update-link.dto.ts b/examples/with-nestjs/packages/api/Source/links/dto/update-link.dto.ts similarity index 100% rename from examples/with-nestjs/packages/api/src/links/dto/update-link.dto.ts rename to examples/with-nestjs/packages/api/Source/links/dto/update-link.dto.ts diff --git a/examples/with-nestjs/packages/api/src/links/entities/link.entity.ts b/examples/with-nestjs/packages/api/Source/links/entities/link.entity.ts similarity index 100% rename from examples/with-nestjs/packages/api/src/links/entities/link.entity.ts rename to examples/with-nestjs/packages/api/Source/links/entities/link.entity.ts diff --git a/examples/with-nestjs/packages/api/package.json b/examples/with-nestjs/packages/api/package.json index 9b229d727326c..f8d5f56cb97b6 100644 --- a/examples/with-nestjs/packages/api/package.json +++ b/examples/with-nestjs/packages/api/package.json @@ -1,47 +1,38 @@ { - "name": "@repo/api", - "version": "0.0.0", - "private": true, - "license": "MIT", - "scripts": { - "dev": "pnpm build --watch", - "build": "tsc -b -v", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"" - }, - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "./dist/**" - ], - "publishConfig": { - "access": "public" - }, - "typesVersions": { - "*": { - "*": [ - "src/*" - ] - } - }, - "exports": { - ".": { - "import": "./dist/index.js", - "require": "./dist/index.js" - }, - "./*": { - "import": "./dist/*.js", - "require": "./dist/*.js" - } - }, - "dependencies": { - "@nestjs/mapped-types": "*" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/node": "^20.3.1", - "ts-loader": "^9.4.3", - "ts-node": "^10.9.2", - "typescript": "5.5.4" - } + "name": "@repo/api", + "exports": { + ".": { + "import": "./dist/index.js", + "require": "./dist/index.js" + }, + "./*": { + "import": "./dist/*.js", + "require": "./dist/*.js" + } + }, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "src/*" + ] + } + }, + "files": [ + "./dist/**" + ], + "scripts": { + "build": "tsc -b -v", + "dev": "pnpm build --watch" + }, + "dependencies": { + "@nestjs/mapped-types": "*" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1", + "ts-loader": "9.5.2" + } } diff --git a/examples/with-nestjs/packages/eslint-config/README.md b/examples/with-nestjs/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-nestjs/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-nestjs/packages/eslint-config/package.json b/examples/with-nestjs/packages/eslint-config/package.json index 453a95deebb94..b23b623aa0337 100644 --- a/examples/with-nestjs/packages/eslint-config/package.json +++ b/examples/with-nestjs/packages/eslint-config/package.json @@ -1,23 +1,17 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "base.js", - "library.js", - "nest.js", - "next.js", - "prettier-base.js", - "react-internal.js" - ], - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@vercel/style-guide": "^5.2.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-only-warn": "^1.1.0", - "eslint-plugin-prettier": "^5.1.3", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "base.js", + "library.js", + "nest.js", + "next.js", + "prettier-base.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-nestjs/packages/jest-config/package.json b/examples/with-nestjs/packages/jest-config/package.json index 4abb9616bbbc1..97a5e0e43b0f7 100644 --- a/examples/with-nestjs/packages/jest-config/package.json +++ b/examples/with-nestjs/packages/jest-config/package.json @@ -1,14 +1,8 @@ { - "name": "@repo/jest-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "devDependencies": { - "@jest/types": "^29.6.3", - "jest": "^29.7.0", - "next": "^14.1.1" - } + "name": "@repo/jest-config", + "dependencies": {}, + "devDependencies": { + "@jest/types": "29.6.3", + "next": "15.1.7" + } } diff --git a/examples/with-nestjs/packages/typescript-config/package.json b/examples/with-nestjs/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-nestjs/packages/typescript-config/package.json +++ b/examples/with-nestjs/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-nestjs/packages/ui/.eslintrc.js b/examples/with-nestjs/packages/ui/.eslintrc.js deleted file mode 100644 index 46464139c9406..0000000000000 --- a/examples/with-nestjs/packages/ui/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: "./tsconfig.lint.json", - tsconfigRootDir: __dirname, - }, -}; diff --git a/examples/with-nestjs/packages/ui/.prettierrc.js b/examples/with-nestjs/packages/ui/.prettierrc.js deleted file mode 100644 index 56640d785bb52..0000000000000 --- a/examples/with-nestjs/packages/ui/.prettierrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("prettier").Config} */ -module.exports = { - ...require('@repo/eslint-config/prettier-base'), -}; diff --git a/examples/with-nestjs/packages/ui/src/button.tsx b/examples/with-nestjs/packages/ui/Source/button.tsx similarity index 100% rename from examples/with-nestjs/packages/ui/src/button.tsx rename to examples/with-nestjs/packages/ui/Source/button.tsx diff --git a/examples/with-nestjs/packages/ui/src/card.tsx b/examples/with-nestjs/packages/ui/Source/card.tsx similarity index 100% rename from examples/with-nestjs/packages/ui/src/card.tsx rename to examples/with-nestjs/packages/ui/Source/card.tsx diff --git a/examples/with-nestjs/packages/ui/src/code.tsx b/examples/with-nestjs/packages/ui/Source/code.tsx similarity index 100% rename from examples/with-nestjs/packages/ui/src/code.tsx rename to examples/with-nestjs/packages/ui/Source/code.tsx diff --git a/examples/with-nestjs/packages/ui/package.json b/examples/with-nestjs/packages/ui/package.json index 19ad2dcafbb2d..27cb3025280e5 100644 --- a/examples/with-nestjs/packages/ui/package.json +++ b/examples/with-nestjs/packages/ui/package.json @@ -1,26 +1,18 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "private": true, - "exports": { - "./button": "./src/button.tsx", - "./card": "./src/card.tsx", - "./code": "./src/code.tsx" - }, - "scripts": { - "lint": "eslint . --max-warnings 0", - "generate:component": "turbo gen react-component" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@turbo/gen": "^1.12.4", - "@types/node": "^20.11.24", - "@types/eslint": "^8.56.5", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "react": "^18.2.0", - "typescript": "5.5.4" - } + "name": "@repo/ui", + "exports": { + "./button": "./src/button.tsx", + "./card": "./src/card.tsx", + "./code": "./src/code.tsx" + }, + "scripts": { + "generate:component": "turbo gen react-component" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@turbo/gen": "2.4.2", + "@types/node": "22.13.1" + } } diff --git a/examples/with-nestjs/pnpm-lock.yaml b/examples/with-nestjs/pnpm-lock.yaml deleted file mode 100644 index 2b1aec7d71c42..0000000000000 --- a/examples/with-nestjs/pnpm-lock.yaml +++ /dev/null @@ -1,8517 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:packages/typescript-config - prettier: - specifier: ^3.2.5 - version: 3.2.5 - turbo: - specifier: ^2.0.4 - version: 2.0.4 - - apps/api: - dependencies: - '@nestjs/common': - specifier: ^10.0.0 - version: 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/core': - specifier: ^10.0.0 - version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/platform-express': - specifier: ^10.0.0 - version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) - '@repo/api': - specifier: workspace:* - version: link:../../packages/api - reflect-metadata: - specifier: ^0.2.0 - version: 0.2.2 - rxjs: - specifier: ^7.8.1 - version: 7.8.1 - devDependencies: - '@jest/globals': - specifier: ^29.7.0 - version: 29.7.0 - '@nestjs/cli': - specifier: ^10.0.0 - version: 10.3.2 - '@nestjs/schematics': - specifier: ^10.0.0 - version: 10.1.1(typescript@5.5.4) - '@nestjs/testing': - specifier: ^10.0.0 - version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8)(@nestjs/platform-express@10.3.8) - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/jest-config': - specifier: workspace:* - version: link:../../packages/jest-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/express': - specifier: ^4.17.17 - version: 4.17.21 - '@types/node': - specifier: ^20.3.1 - version: 20.11.24 - '@types/supertest': - specifier: ^6.0.0 - version: 6.0.2 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - source-map-support: - specifier: ^0.5.21 - version: 0.5.21 - supertest: - specifier: ^6.3.3 - version: 6.3.4 - ts-jest: - specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.24.5)(jest@29.7.0)(typescript@5.5.4) - ts-loader: - specifier: ^9.4.3 - version: 9.5.1(typescript@5.5.4)(webpack@5.91.0) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.11.24)(typescript@5.5.4) - tsconfig-paths: - specifier: ^4.2.0 - version: 4.2.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^14.1.1 - version: 14.1.1(@babel/core@7.24.5)(react-dom@18.2.0)(react@18.2.0) - react: - specifier: ^18.2.0 - version: 18.2.0 - react-dom: - specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) - devDependencies: - '@jest/globals': - specifier: ^29.7.0 - version: 29.7.0 - '@next/eslint-plugin-next': - specifier: ^14.1.1 - version: 14.1.1 - '@playwright/test': - specifier: ^1.44.0 - version: 1.44.0 - '@repo/api': - specifier: workspace:* - version: link:../../packages/api - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/jest-config': - specifier: workspace:* - version: link:../../packages/jest-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@testing-library/jest-dom': - specifier: ^6.4.5 - version: 6.4.5(@jest/globals@29.7.0)(jest@29.7.0) - '@testing-library/react': - specifier: ^15.0.7 - version: 15.0.7(@types/react@18.2.61)(react-dom@18.2.0)(react@18.2.0) - '@types/node': - specifier: ^20.11.24 - version: 20.11.24 - '@types/react': - specifier: ^18.2.61 - version: 18.2.61 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.19 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - jest-environment-jsdom: - specifier: ^29.7.0 - version: 29.7.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/api: - dependencies: - '@nestjs/mapped-types': - specifier: '*' - version: 2.0.5(@nestjs/common@10.3.8)(reflect-metadata@0.2.2) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@types/node': - specifier: ^20.3.1 - version: 20.11.24 - ts-loader: - specifier: ^9.4.3 - version: 9.5.1(typescript@5.5.4)(webpack@5.91.0) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.11.24)(typescript@5.5.4) - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/eslint-config: - devDependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@vercel/style-guide': - specifier: ^5.2.0 - version: 5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - eslint-config-turbo: - specifier: ^2.0.0 - version: 2.0.4(eslint@8.57.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5) - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/jest-config: - devDependencies: - '@jest/types': - specifier: ^29.6.3 - version: 29.6.3 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - next: - specifier: ^14.1.1 - version: 14.1.1(@babel/core@7.24.5)(react-dom@18.2.0)(react@18.2.0) - - packages/typescript-config: {} - - packages/ui: - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@turbo/gen': - specifier: ^1.12.4 - version: 1.12.4(@types/node@20.11.24)(typescript@5.5.4) - '@types/eslint': - specifier: ^8.56.5 - version: 8.56.5 - '@types/node': - specifier: ^20.11.24 - version: 20.11.24 - '@types/react': - specifier: ^18.2.61 - version: 18.2.61 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.2.19 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - react: - specifier: ^18.2.0 - version: 18.2.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - dev: true - - /@adobe/css-tools@4.3.3: - resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} - dev: true - - /@ampproject/remapping@2.2.1: - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.25 - - /@angular-devkit/core@17.1.2(chokidar@3.6.0): - resolution: {integrity: sha512-ku+/W/HMCBacSWFppenr9y6Lx8mDuTuQvn1IkTyBLiJOpWnzgVbx9kHDeaDchGa1PwLlJUBBrv27t3qgJOIDPw==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - chokidar: ^3.5.2 - peerDependenciesMeta: - chokidar: - optional: true - dependencies: - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - chokidar: 3.6.0 - jsonc-parser: 3.2.0 - picomatch: 3.0.1 - rxjs: 7.8.1 - source-map: 0.7.4 - dev: true - - /@angular-devkit/schematics-cli@17.1.2(chokidar@3.6.0): - resolution: {integrity: sha512-bvXykYzSST05qFdlgIzUguNOb3z0hCa8HaTwtqdmQo9aFPf+P+/AC56I64t1iTchMjQtf3JrBQhYM25gUdcGbg==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - hasBin: true - dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) - ansi-colors: 4.1.3 - inquirer: 9.2.12 - symbol-observable: 4.0.0 - yargs-parser: 21.1.1 - transitivePeerDependencies: - - chokidar - dev: true - - /@angular-devkit/schematics@17.1.2(chokidar@3.6.0): - resolution: {integrity: sha512-8S9RuM8olFN/gwN+mjbuF1CwHX61f0i59EGXz9tXLnKRUTjsRR+8vVMTAmX0dvVAT5fJTG/T69X+HX7FeumdqA==} - engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - jsonc-parser: 3.2.0 - magic-string: 0.30.5 - ora: 5.4.1 - rxjs: 7.8.1 - transitivePeerDependencies: - - chokidar - dev: true - - /@babel/code-frame@7.24.2: - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.5 - picocolors: 1.0.0 - - /@babel/compat-data@7.24.4: - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} - engines: {node: '>=6.9.0'} - - /@babel/core@7.24.5: - resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helpers': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /@babel/eslint-parser@7.23.3(@babel/core@7.24.5)(eslint@8.57.0): - resolution: {integrity: sha512-9bTuNlyx7oSstodm1cR1bECj4fkiknsDa1YniISkJemMY3DGhJNYBECbe6QD/q54mp2J8VO66jW3/7uP//iFCw==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@babel/core': 7.24.5 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.24.5: - resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - - /@babel/helper-module-imports@7.24.3: - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - - /@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.24.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 - - /@babel/helper-plugin-utils@7.24.5: - resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-simple-access@7.24.5: - resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - - /@babel/helper-split-export-declaration@7.24.5: - resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.5 - - /@babel/helper-string-parser@7.24.1: - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-identifier@7.24.5: - resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} - engines: {node: '>=6.9.0'} - - /@babel/helpers@7.24.5: - resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - transitivePeerDependencies: - - supports-color - - /@babel/highlight@7.24.5: - resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.5 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.0 - - /@babel/parser@7.24.5: - resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.5 - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.5): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - dev: true - - /@babel/runtime-corejs3@7.22.10: - resolution: {integrity: sha512-IcixfV2Jl3UrqZX4c81+7lVg5++2ufYJyAFW3Aux/ZTvY6LVYYhJ9rMgnbX0zGVq6eqfVpnoatTjZdVki/GmWA==} - engines: {node: '>=6.9.0'} - dependencies: - core-js-pure: 3.32.1 - regenerator-runtime: 0.14.0 - dev: true - - /@babel/runtime@7.23.2: - resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.0 - dev: true - - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - - /@babel/traverse@7.24.5: - resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - /@babel/types@7.24.5: - resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 - to-fast-properties: 2.0.0 - - /@bcoe/v8-coverage@0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true - - /@colors/colors@1.5.0: - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - requiresBuild: true - dev: true - optional: true - - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.2: - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@istanbuljs/load-nyc-config@1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - dev: true - - /@istanbuljs/schema@0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true - - /@jest/console@29.7.0: - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - dev: true - - /@jest/core@29.7.0(ts-node@10.9.2): - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.5 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /@jest/environment@29.7.0: - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - jest-mock: 29.7.0 - dev: true - - /@jest/expect-utils@29.7.0: - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - dev: true - - /@jest/expect@29.7.0: - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/fake-timers@29.7.0: - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.11.24 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - - /@jest/globals@29.7.0: - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/reporters@29.7.0: - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.11.24 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.2 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/schemas@29.6.3: - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - dev: true - - /@jest/source-map@29.6.3: - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - dev: true - - /@jest/test-result@29.7.0: - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - dev: true - - /@jest/test-sequencer@29.7.0: - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - dev: true - - /@jest/transform@29.7.0: - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.24.5 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.5 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/types@29.6.3: - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.24 - '@types/yargs': 17.0.32 - chalk: 4.1.2 - dev: true - - /@jridgewell/gen-mapping@0.3.3: - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - /@jridgewell/source-map@0.3.6: - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@ljharb/through@2.3.13: - resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - - /@lukeed/csprng@1.1.0: - resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} - engines: {node: '>=8'} - - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true - - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true - - /@nestjs/cli@10.3.2: - resolution: {integrity: sha512-aWmD1GLluWrbuC4a1Iz/XBk5p74Uj6nIVZj6Ov03JbTfgtWqGFLtXuMetvzMiHxfrHehx/myt2iKAPRhKdZvTg==} - engines: {node: '>= 16.14'} - hasBin: true - peerDependencies: - '@swc/cli': ^0.1.62 || ^0.3.0 - '@swc/core': ^1.3.62 - peerDependenciesMeta: - '@swc/cli': - optional: true - '@swc/core': - optional: true - dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics-cli': 17.1.2(chokidar@3.6.0) - '@nestjs/schematics': 10.1.1(chokidar@3.6.0)(typescript@5.3.3) - chalk: 4.1.2 - chokidar: 3.6.0 - cli-table3: 0.6.3 - commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.90.1) - glob: 10.3.10 - inquirer: 8.2.6 - node-emoji: 1.11.0 - ora: 5.4.1 - rimraf: 4.4.1 - shelljs: 0.8.5 - source-map-support: 0.5.21 - tree-kill: 1.2.2 - tsconfig-paths: 4.2.0 - tsconfig-paths-webpack-plugin: 4.1.0 - typescript: 5.3.3 - webpack: 5.90.1 - webpack-node-externals: 3.0.0 - transitivePeerDependencies: - - esbuild - - uglify-js - - webpack-cli - dev: true - - /@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1): - resolution: {integrity: sha512-P+vPEIvqx2e+fonsYVlFXKvoChyJ8Tq+lfpqdVFqblovHbFr3kZ/nYX0cPs+XuW6bnRT8tz0SSR9XBGU43kJhw==} - peerDependencies: - class-transformer: '*' - class-validator: '*' - reflect-metadata: ^0.1.12 || ^0.2.0 - rxjs: ^7.1.0 - peerDependenciesMeta: - class-transformer: - optional: true - class-validator: - optional: true - dependencies: - iterare: 1.2.1 - reflect-metadata: 0.2.2 - rxjs: 7.8.1 - tslib: 2.6.2 - uid: 2.0.2 - - /@nestjs/core@10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1): - resolution: {integrity: sha512-AxF4tpYLDNn5Wfb3C4bNaaHJ4pREH5FJrSisR2A5zkYpQFORFs0Tc36lOFPMwBTy8Iv2wUwWLUVc5ftBnxEv4w==} - requiresBuild: true - peerDependencies: - '@nestjs/common': ^10.0.0 - '@nestjs/microservices': ^10.0.0 - '@nestjs/platform-express': ^10.0.0 - '@nestjs/websockets': ^10.0.0 - reflect-metadata: ^0.1.12 || ^0.2.0 - rxjs: ^7.1.0 - peerDependenciesMeta: - '@nestjs/microservices': - optional: true - '@nestjs/platform-express': - optional: true - '@nestjs/websockets': - optional: true - dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) - '@nuxtjs/opencollective': 0.3.2 - fast-safe-stringify: 2.1.1 - iterare: 1.2.1 - path-to-regexp: 3.2.0 - reflect-metadata: 0.2.2 - rxjs: 7.8.1 - tslib: 2.6.2 - uid: 2.0.2 - transitivePeerDependencies: - - encoding - - /@nestjs/mapped-types@2.0.5(@nestjs/common@10.3.8)(reflect-metadata@0.2.2): - resolution: {integrity: sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==} - peerDependencies: - '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 - class-transformer: ^0.4.0 || ^0.5.0 - class-validator: ^0.13.0 || ^0.14.0 - reflect-metadata: ^0.1.12 || ^0.2.0 - peerDependenciesMeta: - class-transformer: - optional: true - class-validator: - optional: true - dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) - reflect-metadata: 0.2.2 - dev: false - - /@nestjs/platform-express@10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8): - resolution: {integrity: sha512-sifLoxgEJvAgbim1UuW6wyScMfkS9SVQRH+lN33N/9ZvZSjO6NSDLOe+wxqsnZkia+QrjFC0qy0ITRAsggfqbg==} - peerDependencies: - '@nestjs/common': ^10.0.0 - '@nestjs/core': ^10.0.0 - dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) - body-parser: 1.20.2 - cors: 2.8.5 - express: 4.19.2 - multer: 1.4.4-lts.1 - tslib: 2.6.2 - transitivePeerDependencies: - - supports-color - - /@nestjs/schematics@10.1.1(chokidar@3.6.0)(typescript@5.3.3): - resolution: {integrity: sha512-o4lfCnEeIkfJhGBbLZxTuVWcGuqDCFwg5OrvpgRUBM7vI/vONvKKiB5riVNpO+JqXoH0I42NNeDb0m4V5RREig==} - peerDependencies: - typescript: '>=4.8.2' - dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) - comment-json: 4.2.3 - jsonc-parser: 3.2.1 - pluralize: 8.0.0 - typescript: 5.3.3 - transitivePeerDependencies: - - chokidar - dev: true - - /@nestjs/schematics@10.1.1(typescript@5.5.4): - resolution: {integrity: sha512-o4lfCnEeIkfJhGBbLZxTuVWcGuqDCFwg5OrvpgRUBM7vI/vONvKKiB5riVNpO+JqXoH0I42NNeDb0m4V5RREig==} - peerDependencies: - typescript: '>=4.8.2' - dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) - comment-json: 4.2.3 - jsonc-parser: 3.2.1 - pluralize: 8.0.0 - typescript: 5.5.4 - transitivePeerDependencies: - - chokidar - dev: true - - /@nestjs/testing@10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8)(@nestjs/platform-express@10.3.8): - resolution: {integrity: sha512-hpX9das2TdFTKQ4/2ojhjI6YgXtCfXRKui3A4Qaj54VVzc5+mtK502Jj18Vzji98o9MVS6skmYu+S/UvW3U6Fw==} - peerDependencies: - '@nestjs/common': ^10.0.0 - '@nestjs/core': ^10.0.0 - '@nestjs/microservices': ^10.0.0 - '@nestjs/platform-express': ^10.0.0 - peerDependenciesMeta: - '@nestjs/microservices': - optional: true - '@nestjs/platform-express': - optional: true - dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) - tslib: 2.6.2 - dev: true - - /@next/env@14.1.1: - resolution: {integrity: sha512-7CnQyD5G8shHxQIIg3c7/pSeYFeMhsNbpU/bmvH7ZnDql7mNRgg8O2JZrhrc/soFnfBnKP4/xXNiiSIPn2w8gA==} - - /@next/eslint-plugin-next@14.1.1: - resolution: {integrity: sha512-NP1WoGFnFLpqqCWgGFjnn/sTwUExdPyjeFKRdQP1X/bL/tjAQ/TXDmYqw6vzGaP5NaZ2u6xzg+N/0nd7fOPOGQ==} - dependencies: - glob: 10.3.10 - dev: true - - /@next/swc-darwin-arm64@14.1.1: - resolution: {integrity: sha512-yDjSFKQKTIjyT7cFv+DqQfW5jsD+tVxXTckSe1KIouKk75t1qZmj/mV3wzdmFb0XHVGtyRjDMulfVG8uCKemOQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@next/swc-darwin-x64@14.1.1: - resolution: {integrity: sha512-KCQmBL0CmFmN8D64FHIZVD9I4ugQsDBBEJKiblXGgwn7wBCSe8N4Dx47sdzl4JAg39IkSN5NNrr8AniXLMb3aw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@next/swc-linux-arm64-gnu@14.1.1: - resolution: {integrity: sha512-YDQfbWyW0JMKhJf/T4eyFr4b3tceTorQ5w2n7I0mNVTFOvu6CGEzfwT3RSAQGTi/FFMTFcuspPec/7dFHuP7Eg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-linux-arm64-musl@14.1.1: - resolution: {integrity: sha512-fiuN/OG6sNGRN/bRFxRvV5LyzLB8gaL8cbDH5o3mEiVwfcMzyE5T//ilMmaTrnA8HLMS6hoz4cHOu6Qcp9vxgQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-linux-x64-gnu@14.1.1: - resolution: {integrity: sha512-rv6AAdEXoezjbdfp3ouMuVqeLjE1Bin0AuE6qxE6V9g3Giz5/R3xpocHoAi7CufRR+lnkuUjRBn05SYJ83oKNQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-linux-x64-musl@14.1.1: - resolution: {integrity: sha512-YAZLGsaNeChSrpz/G7MxO3TIBLaMN8QWMr3X8bt6rCvKovwU7GqQlDu99WdvF33kI8ZahvcdbFsy4jAFzFX7og==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-win32-arm64-msvc@14.1.1: - resolution: {integrity: sha512-1L4mUYPBMvVDMZg1inUYyPvFSduot0g73hgfD9CODgbr4xiTYe0VOMTZzaRqYJYBA9mana0x4eaAaypmWo1r5A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@next/swc-win32-ia32-msvc@14.1.1: - resolution: {integrity: sha512-jvIE9tsuj9vpbbXlR5YxrghRfMuG0Qm/nZ/1KDHc+y6FpnZ/apsgh+G6t15vefU0zp3WSpTMIdXRUsNl/7RSuw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@next/swc-win32-x64-msvc@14.1.1: - resolution: {integrity: sha512-S6K6EHDU5+1KrBDLko7/c1MNy/Ya73pIAmvKeFwsF4RmBFJSO7/7YeD4FnZ4iBdzE69PpQ4sOMU9ORKeNuxe8A==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 - dev: true - - /@nuxtjs/opencollective@0.3.2: - resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==} - engines: {node: '>=8.0.0', npm: '>=5.0.0'} - hasBin: true - dependencies: - chalk: 4.1.2 - consola: 2.15.3 - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@pkgr/core@0.1.1: - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true - - /@pkgr/utils@2.4.2: - resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dependencies: - cross-spawn: 7.0.3 - fast-glob: 3.3.1 - is-glob: 4.0.3 - open: 9.1.0 - picocolors: 1.0.0 - tslib: 2.6.2 - dev: true - - /@playwright/test@1.44.0: - resolution: {integrity: sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==} - engines: {node: '>=16'} - hasBin: true - dependencies: - playwright: 1.44.0 - dev: true - - /@rushstack/eslint-patch@1.5.1: - resolution: {integrity: sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==} - dev: true - - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true - - /@sinonjs/commons@3.0.1: - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - dependencies: - type-detect: 4.0.8 - dev: true - - /@sinonjs/fake-timers@10.3.0: - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - dependencies: - '@sinonjs/commons': 3.0.1 - dev: true - - /@swc/helpers@0.5.2: - resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} - dependencies: - tslib: 2.6.2 - - /@testing-library/dom@10.1.0: - resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} - engines: {node: '>=18'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/runtime': 7.23.2 - '@types/aria-query': 5.0.4 - aria-query: 5.3.0 - chalk: 4.1.2 - dom-accessibility-api: 0.5.16 - lz-string: 1.5.0 - pretty-format: 27.5.1 - dev: true - - /@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(jest@29.7.0): - resolution: {integrity: sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==} - engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - peerDependencies: - '@jest/globals': '>= 28' - '@types/bun': latest - '@types/jest': '>= 28' - jest: '>= 28' - vitest: '>= 0.32' - peerDependenciesMeta: - '@jest/globals': - optional: true - '@types/bun': - optional: true - '@types/jest': - optional: true - jest: - optional: true - vitest: - optional: true - dependencies: - '@adobe/css-tools': 4.3.3 - '@babel/runtime': 7.23.2 - '@jest/globals': 29.7.0 - aria-query: 5.3.0 - chalk: 3.0.0 - css.escape: 1.5.1 - dom-accessibility-api: 0.6.3 - jest: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - lodash: 4.17.21 - redent: 3.0.0 - dev: true - - /@testing-library/react@15.0.7(@types/react@18.2.61)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==} - engines: {node: '>=18'} - peerDependencies: - '@types/react': ^18.0.0 - react: ^18.0.0 - react-dom: ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.23.2 - '@testing-library/dom': 10.1.0 - '@types/react': 18.2.61 - '@types/react-dom': 18.2.19 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: true - - /@tootallnate/once@2.0.0: - resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} - engines: {node: '>= 10'} - dev: true - - /@tootallnate/quickjs-emscripten@0.23.0: - resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - dev: true - - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true - - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true - - /@turbo/gen@1.12.4(@types/node@20.11.24)(typescript@5.5.4): - resolution: {integrity: sha512-3Z8KZ6Vnc2x6rr8sNJ4QNYpkAttLBfb91uPzDlFDY7vgJg+vfXT8YWyZznVL+19ZixF2C/F4Ucp4/YjG2e1drg==} - hasBin: true - dependencies: - '@turbo/workspaces': 1.12.4 - chalk: 2.4.2 - commander: 10.0.1 - fs-extra: 10.1.0 - inquirer: 8.2.6 - minimatch: 9.0.3 - node-plop: 0.26.3 - proxy-agent: 6.3.0 - ts-node: 10.9.2(@types/node@20.11.24)(typescript@5.5.4) - update-check: 1.5.4 - validate-npm-package-name: 5.0.0 - transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' - - '@types/node' - - supports-color - - typescript - dev: true - - /@turbo/workspaces@1.12.4: - resolution: {integrity: sha512-a1hF8Nr6MOeCpvlLR569dGTlzgRLj2Rxo6dTb4jtL+jhHwCb94A9kDPgcRnYGFr45mgulICarVaNZxDjw4/riQ==} - hasBin: true - dependencies: - chalk: 2.4.2 - commander: 10.0.1 - execa: 5.1.1 - fast-glob: 3.3.1 - fs-extra: 10.1.0 - gradient-string: 2.0.2 - inquirer: 8.2.6 - js-yaml: 4.1.0 - ora: 4.1.1 - rimraf: 3.0.2 - semver: 7.5.4 - update-check: 1.5.4 - dev: true - - /@types/aria-query@5.0.4: - resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - dev: true - - /@types/babel__core@7.20.5: - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.5 - dev: true - - /@types/babel__generator@7.6.8: - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@types/babel__template@7.4.4: - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - dev: true - - /@types/babel__traverse@7.20.5: - resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} - dependencies: - '@babel/types': 7.24.5 - dev: true - - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.11.24 - dev: true - - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - dependencies: - '@types/node': 20.11.24 - dev: true - - /@types/cookiejar@2.1.5: - resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} - dev: true - - /@types/eslint-scope@3.7.7: - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - dependencies: - '@types/eslint': 8.56.10 - '@types/estree': 1.0.5 - dev: true - - /@types/eslint@8.56.10: - resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.12 - dev: true - - /@types/eslint@8.56.5: - resolution: {integrity: sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.12 - dev: true - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/express-serve-static-core@4.19.0: - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} - dependencies: - '@types/node': 20.11.24 - '@types/qs': 6.9.15 - '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 - dev: true - - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 - '@types/qs': 6.9.15 - '@types/serve-static': 1.15.7 - dev: true - - /@types/glob@7.2.0: - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 20.11.24 - dev: true - - /@types/graceful-fs@4.1.9: - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - dependencies: - '@types/node': 20.11.24 - dev: true - - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true - - /@types/inquirer@6.5.0: - resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} - dependencies: - '@types/through': 0.0.30 - rxjs: 6.6.7 - dev: true - - /@types/istanbul-lib-coverage@2.0.6: - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - dev: true - - /@types/istanbul-lib-report@3.0.3: - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - dev: true - - /@types/istanbul-reports@3.0.4: - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - dependencies: - '@types/istanbul-lib-report': 3.0.3 - dev: true - - /@types/jsdom@20.0.1: - resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} - dependencies: - '@types/node': 20.11.24 - '@types/tough-cookie': 4.0.5 - parse5: 7.1.2 - dev: true - - /@types/json-schema@7.0.12: - resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} - dev: true - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/methods@1.1.4: - resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} - dev: true - - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true - - /@types/minimatch@5.1.2: - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - dev: true - - /@types/node@20.11.24: - resolution: {integrity: sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: true - - /@types/prop-types@15.7.5: - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} - dev: true - - /@types/qs@6.9.15: - resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} - dev: true - - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true - - /@types/react-dom@18.2.19: - resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==} - dependencies: - '@types/react': 18.2.61 - dev: true - - /@types/react@18.2.61: - resolution: {integrity: sha512-NURTN0qNnJa7O/k4XUkEW2yfygA+NxS0V5h1+kp9jPwhzZy95q3ADoGMP0+JypMhrZBTTgjKAUlTctde1zzeQA==} - dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.3 - csstype: 3.1.2 - dev: true - - /@types/scheduler@0.16.3: - resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} - dev: true - - /@types/semver@7.5.0: - resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} - dev: true - - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.11.24 - dev: true - - /@types/serve-static@1.15.7: - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 20.11.24 - '@types/send': 0.17.4 - dev: true - - /@types/stack-utils@2.0.3: - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - dev: true - - /@types/superagent@8.1.7: - resolution: {integrity: sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==} - dependencies: - '@types/cookiejar': 2.1.5 - '@types/methods': 1.1.4 - '@types/node': 20.11.24 - dev: true - - /@types/supertest@6.0.2: - resolution: {integrity: sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==} - dependencies: - '@types/methods': 1.1.4 - '@types/superagent': 8.1.7 - dev: true - - /@types/through@0.0.30: - resolution: {integrity: sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==} - dependencies: - '@types/node': 20.11.24 - dev: true - - /@types/tinycolor2@1.4.6: - resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} - dev: true - - /@types/tough-cookie@4.0.5: - resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - dev: true - - /@types/yargs-parser@21.0.3: - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - dev: true - - /@types/yargs@17.0.32: - resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - dependencies: - '@types/yargs-parser': 21.0.3 - dev: true - - /@typescript-eslint/eslint-plugin@6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/type-utils': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/type-utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@6.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - - /@typescript-eslint/scope-manager@6.17.0: - resolution: {integrity: sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 - dev: true - - /@typescript-eslint/scope-manager@7.1.0: - resolution: {integrity: sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - dev: true - - /@typescript-eslint/type-utils@6.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/type-utils@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@6.17.0: - resolution: {integrity: sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/types@7.1.0: - resolution: {integrity: sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.4): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.5.4 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@6.17.0(typescript@5.5.4): - resolution: {integrity: sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@7.1.0(typescript@5.5.4): - resolution: {integrity: sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@6.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@6.17.0: - resolution: {integrity: sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.17.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.1.0: - resolution: {integrity: sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 7.1.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@vercel/style-guide@5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4): - resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} - engines: {node: '>=16'} - peerDependencies: - '@next/eslint-plugin-next': '>=12.3.0 <15' - eslint: '>=8.48.0 <9' - prettier: '>=3.0.0 <4' - typescript: '>=4.8.0 <6' - peerDependenciesMeta: - '@next/eslint-plugin-next': - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - dependencies: - '@babel/core': 7.24.5 - '@babel/eslint-parser': 7.23.3(@babel/core@7.24.5)(eslint@8.57.0) - '@rushstack/eslint-patch': 1.5.1 - '@typescript-eslint/eslint-plugin': 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) - eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.0) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.17.0)(eslint-plugin-import@2.29.0)(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0) - eslint-plugin-jest: 27.6.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.6.0)(eslint@8.57.0) - eslint-plugin-react: 7.33.2(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) - eslint-plugin-testing-library: 6.1.2(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) - prettier: 3.2.5 - prettier-plugin-packagejson: 2.4.6(prettier@3.2.5) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /@webassemblyjs/ast@1.12.1: - resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} - dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - dev: true - - /@webassemblyjs/floating-point-hex-parser@1.11.6: - resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} - dev: true - - /@webassemblyjs/helper-api-error@1.11.6: - resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} - dev: true - - /@webassemblyjs/helper-buffer@1.12.1: - resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} - dev: true - - /@webassemblyjs/helper-numbers@1.11.6: - resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 - '@xtuc/long': 4.2.2 - dev: true - - /@webassemblyjs/helper-wasm-bytecode@1.11.6: - resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} - dev: true - - /@webassemblyjs/helper-wasm-section@1.12.1: - resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 - dev: true - - /@webassemblyjs/ieee754@1.11.6: - resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} - dependencies: - '@xtuc/ieee754': 1.2.0 - dev: true - - /@webassemblyjs/leb128@1.11.6: - resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} - dependencies: - '@xtuc/long': 4.2.2 - dev: true - - /@webassemblyjs/utf8@1.11.6: - resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} - dev: true - - /@webassemblyjs/wasm-edit@1.12.1: - resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 - dev: true - - /@webassemblyjs/wasm-gen@1.12.1: - resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - - /@webassemblyjs/wasm-opt@1.12.1: - resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - dev: true - - /@webassemblyjs/wasm-parser@1.12.1: - resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - - /@webassemblyjs/wast-printer@1.12.1: - resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@xtuc/long': 4.2.2 - dev: true - - /@xtuc/ieee754@1.2.0: - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - dev: true - - /@xtuc/long@4.2.2: - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - dev: true - - /abab@2.0.6: - resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - deprecated: Use your platform's native atob() and btoa() methods instead - dev: true - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - - /acorn-globals@7.0.1: - resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - dependencies: - acorn: 8.10.0 - acorn-walk: 8.2.0 - dev: true - - /acorn-import-assertions@1.9.0(acorn@8.10.0): - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} - peerDependencies: - acorn: ^8 - dependencies: - acorn: 8.10.0 - dev: true - - /acorn-jsx@5.3.2(acorn@8.10.0): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.10.0 - dev: true - - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /agent-base@7.1.0: - resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} - engines: {node: '>= 14'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /ajv-formats@2.1.1(ajv@8.12.0): - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - dependencies: - ajv: 8.12.0 - dev: true - - /ajv-keywords@3.5.2(ajv@6.12.6): - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - dependencies: - ajv: 6.12.6 - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /append-field@1.0.0: - resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} - - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - dependencies: - dequal: 2.0.3 - dev: true - - /array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.2 - dev: true - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - - /array-includes@3.1.7: - resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - dev: true - - /array-timsort@1.0.3: - resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array.prototype.findlastindex@1.2.3: - resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.4 - dev: true - - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.tosorted@1.1.2: - resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.4 - dev: true - - /arraybuffer.prototype.slice@1.0.2: - resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.2 - is-shared-array-buffer: 1.0.2 - dev: true - - /asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - dev: true - - /ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - dev: true - - /ast-types@0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - dependencies: - tslib: 2.6.2 - dev: true - - /async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - dev: true - - /asynciterator.prototype@1.0.0: - resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} - dependencies: - has-symbols: 1.0.3 - dev: true - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: true - - /axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - dev: true - - /axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} - dependencies: - dequal: 2.0.3 - dev: true - - /babel-jest@29.7.0(@babel/core@7.24.5): - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - dependencies: - '@babel/core': 7.24.5 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.24.5) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.24.5 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.5 - dev: true - - /babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.5): - resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) - dev: true - - /babel-preset-jest@29.6.3(@babel/core@7.24.5): - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.5 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - - /basic-ftp@5.0.3: - resolution: {integrity: sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==} - engines: {node: '>=10.0.0'} - dev: true - - /big-integer@1.6.51: - resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} - engines: {node: '>=0.6'} - dev: true - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: true - - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - /bplist-parser@0.2.0: - resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} - engines: {node: '>= 5.10.0'} - dependencies: - big-integer: 1.6.51 - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001593 - electron-to-chromium: 1.4.768 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) - - /bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - dependencies: - fast-json-stable-stringify: 2.1.0 - dev: true - - /bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /builtins@5.0.1: - resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} - dependencies: - semver: 7.5.4 - dev: true - - /bundle-name@3.0.0: - resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} - engines: {node: '>=12'} - dependencies: - run-applescript: 5.0.0 - dev: true - - /busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camel-case@3.0.0: - resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - dev: true - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /caniuse-lite@1.0.30001593: - resolution: {integrity: sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==} - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - /chalk@3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - - /change-case@3.1.0: - resolution: {integrity: sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==} - dependencies: - camel-case: 3.0.0 - constant-case: 2.0.0 - dot-case: 2.1.1 - header-case: 1.0.1 - is-lower-case: 1.1.3 - is-upper-case: 1.1.2 - lower-case: 1.1.4 - lower-case-first: 1.0.2 - no-case: 2.3.2 - param-case: 2.1.1 - pascal-case: 2.0.1 - path-case: 2.1.1 - sentence-case: 2.1.1 - snake-case: 2.1.0 - swap-case: 1.1.2 - title-case: 2.1.1 - upper-case: 1.1.3 - upper-case-first: 1.1.2 - dev: true - - /char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - dev: true - - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} - engines: {node: '>=6.0'} - dev: true - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /cjs-module-lexer@1.3.1: - resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} - dev: true - - /clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true - - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: true - - /cli-spinners@2.9.0: - resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} - engines: {node: '>=6'} - dev: true - - /cli-table3@0.6.3: - resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} - engines: {node: 10.* || >= 12.*} - dependencies: - string-width: 4.2.3 - optionalDependencies: - '@colors/colors': 1.5.0 - dev: true - - /cli-width@3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} - dev: true - - /cli-width@4.1.0: - resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} - engines: {node: '>= 12'} - dev: true - - /client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - - /co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - - /collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true - - /commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - dev: true - - /comment-json@4.2.3: - resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} - engines: {node: '>= 6'} - dependencies: - array-timsort: 1.0.3 - core-util-is: 1.0.3 - esprima: 4.0.1 - has-own-prop: 2.0.0 - repeat-string: 1.6.1 - dev: true - - /component-emitter@1.3.1: - resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /concat-stream@1.6.2: - resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} - engines: {'0': node >= 0.8} - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 2.3.8 - typedarray: 0.0.6 - - /consola@2.15.3: - resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} - - /constant-case@2.0.0: - resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} - dependencies: - snake-case: 2.1.0 - upper-case: 1.1.3 - dev: true - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - - /cookiejar@2.1.4: - resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} - dev: true - - /core-js-pure@3.32.1: - resolution: {integrity: sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ==} - requiresBuild: true - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - /cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - - /cosmiconfig@8.3.6(typescript@5.3.3): - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - path-type: 4.0.0 - typescript: 5.3.3 - dev: true - - /create-jest@29.7.0(@types/node@20.11.24)(ts-node@10.9.2): - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - dev: true - - /cssom@0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - dev: true - - /cssom@0.5.0: - resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - dev: true - - /cssstyle@2.3.0: - resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} - engines: {node: '>=8'} - dependencies: - cssom: 0.3.8 - dev: true - - /csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - dev: true - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /data-uri-to-buffer@5.0.1: - resolution: {integrity: sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==} - engines: {node: '>= 14'} - dev: true - - /data-urls@3.0.2: - resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} - engines: {node: '>=12'} - dependencies: - abab: 2.0.6 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /decimal.js@10.4.3: - resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - dev: true - - /dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - dev: true - - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true - - /default-browser-id@3.0.0: - resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} - engines: {node: '>=12'} - dependencies: - bplist-parser: 0.2.0 - untildify: 4.0.0 - dev: true - - /default-browser@4.0.0: - resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} - engines: {node: '>=14.16'} - dependencies: - bundle-name: 3.0.0 - default-browser-id: 3.0.0 - execa: 7.2.0 - titleize: 3.0.0 - dev: true - - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - - /define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - dev: true - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true - - /degenerator@5.0.1: - resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} - engines: {node: '>= 14'} - dependencies: - ast-types: 0.13.4 - escodegen: 2.1.0 - esprima: 4.0.1 - dev: true - - /del@5.1.0: - resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} - engines: {node: '>=8'} - dependencies: - globby: 10.0.2 - graceful-fs: 4.2.11 - is-glob: 4.0.3 - is-path-cwd: 2.2.0 - is-path-inside: 3.0.3 - p-map: 3.0.0 - rimraf: 3.0.2 - slash: 3.0.0 - dev: true - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: true - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - /detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - dev: true - - /detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - dev: true - - /detect-newline@4.0.1: - resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /dezalgo@1.0.4: - resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} - dependencies: - asap: 2.0.6 - wrappy: 1.0.2 - dev: true - - /diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dom-accessibility-api@0.5.16: - resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - dev: true - - /dom-accessibility-api@0.6.3: - resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dev: true - - /domexception@4.0.0: - resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} - engines: {node: '>=12'} - deprecated: Use your platform's native DOMException instead - dependencies: - webidl-conversions: 7.0.0 - dev: true - - /dot-case@2.1.1: - resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} - dependencies: - no-case: 2.3.2 - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - /ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - jake: 10.9.2 - dev: true - - /electron-to-chromium@1.4.768: - resolution: {integrity: sha512-z2U3QcvNuxdkk33YV7R1bVMNq7fL23vq3WfO5BHcqrm4TnDGReouBfYKLEFh5umoK1XACjEwp8mmnhXk2EJigw==} - - /emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - - /enhanced-resolve@5.16.1: - resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-abstract@1.22.3: - resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - arraybuffer.prototype.slice: 1.0.2 - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - es-set-tostringtag: 2.0.2 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - internal-slot: 1.0.6 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.12 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.1 - safe-array-concat: 1.0.1 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.8 - string.prototype.trimend: 1.0.7 - string.prototype.trimstart: 1.0.7 - typed-array-buffer: 1.0.0 - typed-array-byte-length: 1.0.0 - typed-array-byte-offset: 1.0.0 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.13 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - /es-iterator-helpers@1.0.15: - resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} - dependencies: - asynciterator.prototype: 1.0.0 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-set-tostringtag: 2.0.2 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 - has-property-descriptors: 1.0.2 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.6 - iterator.prototype: 1.1.2 - safe-array-concat: 1.0.1 - dev: true - - /es-module-lexer@1.5.2: - resolution: {integrity: sha512-l60ETUTmLqbVbVHv1J4/qj+M8nq7AwMzEcg3kmJDt9dCNrTk+yHcYFf/Kw75pMDwd9mPcIGCG5LcS20SxYRzFA==} - dev: true - - /es-set-tostringtag@2.0.2: - resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.0 - hasown: 2.0.0 - dev: true - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.0 - dev: true - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - /escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - dev: true - - /escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-config-turbo@2.0.4(eslint@8.57.0): - resolution: {integrity: sha512-zGvU+bxoNWVvSl0prGItrnH9FgeNzKEAjRmv8ruqql1psI37T8IoLF/XeOzT3CzzYzJxuI3wW1yb2agDFYQdHQ==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-turbo: 2.0.4(eslint@8.57.0) - dev: true - - /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.0): - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - dependencies: - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0) - dev: true - - /eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.17.0)(eslint-plugin-import@2.29.0)(eslint@8.57.0): - resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.4 - enhanced-resolve: 5.16.1 - eslint: 8.57.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0) - fast-glob: 3.3.1 - get-tsconfig: 4.7.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.17.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.17.0)(eslint-plugin-import@2.29.0)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils@2.8.0(@typescript-eslint/parser@7.1.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): - resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} - engines: {node: '>=6.5.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - escape-string-regexp: 1.0.5 - eslint: 8.57.0 - ignore: 5.3.1 - dev: true - - /eslint-plugin-import@2.29.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0): - resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.7 - array.prototype.findlastindex: 1.2.3 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.0 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.7 - object.groupby: 1.0.1 - object.values: 1.1.7 - semver: 6.3.1 - tsconfig-paths: 3.14.2 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@27.6.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.23.2 - aria-query: 5.3.0 - array-includes: 3.1.7 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.15 - eslint: 8.57.0 - hasown: 2.0.0 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.entries: 1.1.7 - object.fromentries: 2.0.7 - dev: true - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.6.0)(eslint@8.57.0): - resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} - peerDependencies: - eslint: '>=7' - eslint-plugin-jest: '>=25' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - dependencies: - eslint: 8.57.0 - eslint-plugin-jest: 27.6.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.57.0)(typescript@5.5.4) - dev: true - - /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5): - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '*' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true - dependencies: - eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) - prettier: 3.2.5 - prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 - dev: true - - /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react@7.33.2(eslint@8.57.0): - resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.7 - array.prototype.flatmap: 1.3.2 - array.prototype.tosorted: 1.1.2 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.15 - eslint: 8.57.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.7 - object.fromentries: 2.0.7 - object.hasown: 1.1.3 - object.values: 1.1.7 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.10 - dev: true - - /eslint-plugin-testing-library@6.1.2(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-Ra16FeBlonfbScOIdZEta9o+OxtwDqiUt+4UCpIM42TuatyLdtfU/SbwnIzPcAszrbl58PGwyZ9YGU9dwIo/tA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true - - /eslint-plugin-turbo@2.0.4(eslint@8.57.0): - resolution: {integrity: sha512-Ozn//vTXJeqIEvEkThM2vuuldMckPqAne7vg/S3GxF+BBY516cjdp7+dYpCU5Q0083hVm638c8542ubccNE+8w==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.0 - dev: true - - /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.44.0' - dependencies: - '@babel/helper-validator-identifier': 7.24.5 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - ci-info: 3.9.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.5.4 - strip-indent: 3.0.0 - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) - eslint-visitor-keys: 3.4.3 - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /execa@7.2.0: - resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 4.3.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.1.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 - dev: true - - /exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - dev: true - - /expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - dev: true - - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - dev: true - - /fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fast-safe-stringify@2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - - /fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - dependencies: - reusify: 1.0.4 - dev: true - - /fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - dependencies: - bser: 2.1.1 - dev: true - - /figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /figures@5.0.0: - resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} - engines: {node: '>=14'} - dependencies: - escape-string-regexp: 5.0.0 - is-unicode-supported: 1.3.0 - dev: true - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.0.4 - dev: true - - /filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.6 - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /flat-cache@3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.2.7 - rimraf: 3.0.2 - dev: true - - /flatted@3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} - dev: true - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.90.1): - resolution: {integrity: sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==} - engines: {node: '>=12.13.0', yarn: '>=1.0.0'} - peerDependencies: - typescript: '>3.6.0' - webpack: ^5.11.0 - dependencies: - '@babel/code-frame': 7.24.2 - chalk: 4.1.2 - chokidar: 3.6.0 - cosmiconfig: 8.3.6(typescript@5.3.3) - deepmerge: 4.3.1 - fs-extra: 10.1.0 - memfs: 3.5.3 - minimatch: 3.1.2 - node-abort-controller: 3.1.1 - schema-utils: 3.3.0 - semver: 7.5.4 - tapable: 2.2.1 - typescript: 5.3.3 - webpack: 5.90.1 - dev: true - - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /formidable@2.1.2: - resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==} - dependencies: - dezalgo: 1.0.4 - hexoid: 1.0.0 - once: 1.4.0 - qs: 6.12.1 - dev: true - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - - /fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: true - - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-monkey@1.0.6: - resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-intrinsic@1.2.2: - resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} - dependencies: - function-bind: 1.1.2 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - - /get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true - - /get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /get-tsconfig@4.7.2: - resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true - - /get-uri@6.0.1: - resolution: {integrity: sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==} - engines: {node: '>= 14'} - dependencies: - basic-ftp: 5.0.3 - data-uri-to-buffer: 5.0.1 - debug: 4.3.4 - fs-extra: 8.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /git-hooks-list@3.1.0: - resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: true - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob@9.3.5: - resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - fs.realpath: 1.0.0 - minimatch: 8.0.4 - minipass: 4.2.8 - path-scurry: 1.10.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - dev: true - - /globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} - dependencies: - '@types/glob': 7.2.0 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.1 - glob: 7.2.3 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.1 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.1 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.2 - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /gradient-string@2.0.2: - resolution: {integrity: sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - tinygradient: 1.1.5 - dev: true - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /has-own-prop@2.0.0: - resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - - /header-case@1.0.1: - resolution: {integrity: sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==} - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - dev: true - - /hexoid@1.0.0: - resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==} - engines: {node: '>=8'} - dev: true - - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /html-encoding-sniffer@3.0.0: - resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} - engines: {node: '>=12'} - dependencies: - whatwg-encoding: 2.0.0 - dev: true - - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - - /http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 2.0.0 - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /http-proxy-agent@7.0.0: - resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent@7.0.1: - resolution: {integrity: sha512-Eun8zV0kcYS1g19r78osiQLEFIRspRUDd9tIfBCTBPBeMieF/EsJNL8VI3xOIdYRDEkjQnqOYPsZ2DsWsVsFwQ==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - dev: true - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - - /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /import-local@3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} - engines: {node: '>=8'} - hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - - /inquirer@7.3.3: - resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} - engines: {node: '>=8.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - run-async: 2.4.1 - rxjs: 6.6.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - dev: true - - /inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} - engines: {node: '>=12.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 - dev: true - - /inquirer@9.2.12: - resolution: {integrity: sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==} - engines: {node: '>=14.18.0'} - dependencies: - '@ljharb/through': 2.3.13 - ansi-escapes: 4.3.2 - chalk: 5.3.0 - cli-cursor: 3.1.0 - cli-width: 4.1.0 - external-editor: 3.1.0 - figures: 5.0.0 - lodash: 4.17.21 - mute-stream: 1.0.0 - ora: 5.4.1 - run-async: 3.0.0 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true - - /internal-slot@1.0.6: - resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - hasown: 2.0.0 - side-channel: 1.0.6 - dev: true - - /interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - dev: true - - /ip@1.1.8: - resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} - dev: true - - /ip@2.0.0: - resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} - dev: true - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-typed-array: 1.1.12 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.0 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.0 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - dev: true - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - dependencies: - is-docker: 3.0.0 - dev: true - - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: true - - /is-lower-case@1.1.3: - resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} - dependencies: - lower-case: 1.1.4 - dev: true - - /is-map@2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} - dev: true - - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-cwd@2.2.0: - resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} - engines: {node: '>=6'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: true - - /is-potential-custom-element-name@1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - dev: true - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.0 - dev: true - - /is-set@2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - dev: true - - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array@1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.13 - dev: true - - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true - - /is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - dev: true - - /is-upper-case@1.1.2: - resolution: {integrity: sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==} - dependencies: - upper-case: 1.1.3 - dev: true - - /is-weakmap@2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} - dev: true - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-weakset@2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isbinaryfile@4.0.10: - resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} - engines: {node: '>= 8.0.0'} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - dev: true - - /istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-instrument@6.0.2: - resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} - engines: {node: '>=10'} - dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - dev: true - - /istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.3.4 - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - dev: true - - /iterare@1.2.1: - resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==} - engines: {node: '>=6'} - - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.4 - set-function-name: 2.0.1 - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: true - - /jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - dev: true - - /jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - - /jest-cli@29.7.0(@types/node@20.11.24)(ts-node@10.9.2): - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /jest-config@29.7.0(@types/node@20.11.24)(ts-node@10.9.2): - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - dependencies: - '@babel/core': 7.24.5 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - babel-jest: 29.7.0(@babel/core@7.24.5) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - ts-node: 10.9.2(@types/node@20.11.24)(typescript@5.5.4) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - - /jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - detect-newline: 3.1.0 - dev: true - - /jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - dev: true - - /jest-environment-jsdom@29.7.0: - resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/jsdom': 20.0.1 - '@types/node': 20.11.24 - jest-mock: 29.7.0 - jest-util: 29.7.0 - jsdom: 20.0.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - - /jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 20.11.24 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.5 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.24.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - dev: true - - /jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - jest-util: 29.7.0 - dev: true - - /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: - jest-resolve: 29.7.0 - dev: true - - /jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.8 - resolve.exports: 2.0.2 - slash: 3.0.0 - dev: true - - /jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - chalk: 4.1.2 - cjs-module-lexer: 1.3.1 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.24.5 - '@babel/generator': 7.24.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) - '@babel/types': 7.24.5 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - dev: true - - /jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - dev: true - - /jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.11.24 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - dev: true - - /jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 20.11.24 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@types/node': 20.11.24 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /jest@29.7.0(@types/node@20.11.24)(ts-node@10.9.2): - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) - '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsdom@20.0.3: - resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} - engines: {node: '>=14'} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - dependencies: - abab: 2.0.6 - acorn: 8.10.0 - acorn-globals: 7.0.1 - cssom: 0.5.0 - cssstyle: 2.3.0 - data-urls: 3.0.2 - decimal.js: 10.4.3 - domexception: 4.0.0 - escodegen: 2.1.0 - form-data: 4.0.0 - html-encoding-sniffer: 3.0.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.10 - parse5: 7.1.2 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 4.1.4 - w3c-xmlserializer: 4.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 2.0.0 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - ws: 8.17.0 - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: true - - /jsonc-parser@3.2.1: - resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} - dev: true - - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.0 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.7 - array.prototype.flat: 1.3.2 - object.assign: 4.1.4 - object.values: 1.1.7 - dev: true - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} - dev: true - - /language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - dependencies: - language-subtag-registry: 0.3.22 - dev: true - - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} - engines: {node: '>=6.11.5'} - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.get@4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - dev: true - - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /log-symbols@3.0.0: - resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==} - engines: {node: '>=8'} - dependencies: - chalk: 2.4.2 - dev: true - - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - dependencies: - js-tokens: 4.0.0 - - /lower-case-first@1.0.2: - resolution: {integrity: sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==} - dependencies: - lower-case: 1.1.4 - dev: true - - /lower-case@1.1.4: - resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} - dev: true - - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - dev: true - - /lz-string@1.5.0: - resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} - hasBin: true - dev: true - - /magic-string@0.30.5: - resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - dependencies: - semver: 7.5.4 - dev: true - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - dependencies: - tmpl: 1.0.5 - dev: true - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - - /memfs@3.5.3: - resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} - engines: {node: '>= 4.0.0'} - dependencies: - fs-monkey: 1.0.6 - dev: true - - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - - /mime@2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true - - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@8.0.4: - resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - /minipass@4.2.8: - resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} - engines: {node: '>=8'} - dev: true - - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.8 - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - /multer@1.4.4-lts.1: - resolution: {integrity: sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==} - engines: {node: '>= 6.0.0'} - dependencies: - append-field: 1.0.0 - busboy: 1.6.0 - concat-stream: 1.6.2 - mkdirp: 0.5.6 - object-assign: 4.1.1 - type-is: 1.6.18 - xtend: 4.0.2 - - /mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - dev: true - - /mute-stream@1.0.0: - resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /netmask@2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} - dev: true - - /next@14.1.1(@babel/core@7.24.5)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-McrGJqlGSHeaz2yTRPkEucxQKe5Zq7uPwyeHNmJaZNY4wx9E9QdxmTp310agFRoMuIYgQrCrT3petg13fSVOww==} - engines: {node: '>=18.17.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - sass: - optional: true - dependencies: - '@next/env': 14.1.1 - '@swc/helpers': 0.5.2 - busboy: 1.6.0 - caniuse-lite: 1.0.30001593 - graceful-fs: 4.2.11 - postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(@babel/core@7.24.5)(react@18.2.0) - optionalDependencies: - '@next/swc-darwin-arm64': 14.1.1 - '@next/swc-darwin-x64': 14.1.1 - '@next/swc-linux-arm64-gnu': 14.1.1 - '@next/swc-linux-arm64-musl': 14.1.1 - '@next/swc-linux-x64-gnu': 14.1.1 - '@next/swc-linux-x64-musl': 14.1.1 - '@next/swc-win32-arm64-msvc': 14.1.1 - '@next/swc-win32-ia32-msvc': 14.1.1 - '@next/swc-win32-x64-msvc': 14.1.1 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - /no-case@2.3.2: - resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} - dependencies: - lower-case: 1.1.4 - dev: true - - /node-abort-controller@3.1.1: - resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} - dev: true - - /node-emoji@1.11.0: - resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} - dependencies: - lodash: 4.17.21 - dev: true - - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - - /node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - dev: true - - /node-plop@0.26.3: - resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==} - engines: {node: '>=8.9.4'} - dependencies: - '@babel/runtime-corejs3': 7.22.10 - '@types/inquirer': 6.5.0 - change-case: 3.1.0 - del: 5.1.0 - globby: 10.0.2 - handlebars: 4.7.8 - inquirer: 7.3.3 - isbinaryfile: 4.0.10 - lodash.get: 4.4.2 - mkdirp: 0.5.6 - resolve: 1.22.8 - dev: true - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - - /nwsapi@2.2.10: - resolution: {integrity: sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==} - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.7: - resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /object.fromentries@2.0.7: - resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /object.groupby@1.0.1: - resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.4 - dev: true - - /object.hasown@1.1.3: - resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /object.values@1.1.7: - resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - - /open@9.1.0: - resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} - engines: {node: '>=14.16'} - dependencies: - default-browser: 4.0.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 2.2.0 - dev: true - - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /ora@4.1.1: - resolution: {integrity: sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==} - engines: {node: '>=8'} - dependencies: - chalk: 3.0.0 - cli-cursor: 3.1.0 - cli-spinners: 2.9.0 - is-interactive: 1.0.0 - log-symbols: 3.0.0 - mute-stream: 0.0.8 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.0 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-map@3.0.0: - resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} - engines: {node: '>=8'} - dependencies: - aggregate-error: 3.1.0 - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /pac-proxy-agent@7.0.0: - resolution: {integrity: sha512-t4tRAMx0uphnZrio0S0Jw9zg3oDbz1zVhQ/Vy18FjLfP1XOLNUEjaVxYCYRI6NS+BsMBXKIzV6cTLOkO9AtywA==} - engines: {node: '>= 14'} - dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 - agent-base: 7.1.0 - debug: 4.3.4 - get-uri: 6.0.1 - http-proxy-agent: 7.0.0 - https-proxy-agent: 7.0.1 - pac-resolver: 7.0.0 - socks-proxy-agent: 8.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /pac-resolver@7.0.0: - resolution: {integrity: sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==} - engines: {node: '>= 14'} - dependencies: - degenerator: 5.0.1 - ip: 1.1.8 - netmask: 2.0.2 - dev: true - - /param-case@2.1.1: - resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} - dependencies: - no-case: 2.3.2 - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.24.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} - dependencies: - entities: 4.5.0 - dev: true - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - - /pascal-case@2.0.1: - resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} - dependencies: - camel-case: 3.0.0 - upper-case-first: 1.1.2 - dev: true - - /path-case@2.1.1: - resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} - dependencies: - no-case: 2.3.2 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: true - - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - - /path-to-regexp@3.2.0: - resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==} - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /picomatch@3.0.1: - resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==} - engines: {node: '>=10'} - dev: true - - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - dev: true - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /playwright-core@1.44.0: - resolution: {integrity: sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==} - engines: {node: '>=16'} - hasBin: true - dev: true - - /playwright@1.44.0: - resolution: {integrity: sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==} - engines: {node: '>=16'} - hasBin: true - dependencies: - playwright-core: 1.44.0 - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - dependencies: - fast-diff: 1.3.0 - dev: true - - /prettier-plugin-packagejson@2.4.6(prettier@3.2.5): - resolution: {integrity: sha512-5JGfzkJRL0DLNyhwmiAV9mV0hZLHDwddFCs2lc9CNxOChpoWUQVe8K4qTMktmevmDlMpok2uT10nvHUyU59sNw==} - peerDependencies: - prettier: '>= 1.16.0' - peerDependenciesMeta: - prettier: - optional: true - dependencies: - prettier: 3.2.5 - sort-package-json: 2.6.0 - synckit: 0.8.5 - dev: true - - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - dev: true - - /pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - dev: true - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - - /proxy-agent@6.3.0: - resolution: {integrity: sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - http-proxy-agent: 7.0.0 - https-proxy-agent: 7.0.1 - lru-cache: 7.18.3 - pac-proxy-agent: 7.0.0 - proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true - - /psl@1.9.0: - resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} - dev: true - - /punycode@2.3.0: - resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} - engines: {node: '>=6'} - dev: true - - /pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - dev: true - - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - - /qs@6.12.1: - resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: true - - /querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - dev: true - - /react-dom@18.2.0(react@18.2.0): - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} - peerDependencies: - react: ^18.2.0 - dependencies: - loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - dev: true - - /react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - dev: true - - /react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - dependencies: - resolve: 1.22.8 - dev: true - - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - dev: true - - /reflect-metadata@0.2.2: - resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} - - /reflect.getprototypeof@1.0.4: - resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 - which-builtin-type: 1.1.3 - dev: true - - /regenerator-runtime@0.14.0: - resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} - dev: true - - /regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - hasBin: true - dev: true - - /regexp.prototype.flags@1.5.1: - resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - set-function-name: 2.0.1 - dev: true - - /registry-auth-token@3.3.2: - resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} - dependencies: - rc: 1.2.8 - safe-buffer: 5.2.1 - dev: true - - /registry-url@3.1.0: - resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} - engines: {node: '>=0.10.0'} - dependencies: - rc: 1.2.8 - dev: true - - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /repeat-string@1.6.1: - resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} - engines: {node: '>=0.10'} - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - - /requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - dev: true - - /resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - - /resolve.exports@2.0.2: - resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} - engines: {node: '>=10'} - dev: true - - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rimraf@4.4.1: - resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} - engines: {node: '>=14'} - hasBin: true - dependencies: - glob: 9.3.5 - dev: true - - /run-applescript@5.0.0: - resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} - engines: {node: '>=12'} - dependencies: - execa: 5.1.1 - dev: true - - /run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - dev: true - - /run-async@3.0.0: - resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} - engines: {node: '>=0.12.0'} - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /rxjs@6.6.7: - resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} - engines: {npm: '>=2.0.0'} - dependencies: - tslib: 1.14.1 - dev: true - - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - dependencies: - tslib: 2.6.2 - - /safe-array-concat@1.0.1: - resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-regex: 1.1.4 - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - /saxes@6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} - engines: {node: '>=v12.22.7'} - dependencies: - xmlchars: 2.2.0 - dev: true - - /scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} - dependencies: - loose-envify: 1.4.0 - - /schema-utils@3.3.0: - resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/json-schema': 7.0.12 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - dev: true - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - - /sentence-case@2.1.1: - resolution: {integrity: sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==} - dependencies: - no-case: 2.3.2 - upper-case-first: 1.1.2 - dev: true - - /serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - dependencies: - randombytes: 2.1.0 - dev: true - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - - /set-function-name@2.0.1: - resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true - - /snake-case@2.1.0: - resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} - dependencies: - no-case: 2.3.2 - dev: true - - /socks-proxy-agent@8.0.1: - resolution: {integrity: sha512-59EjPbbgg8U3x62hhKOFVAmySQUcfRQ4C7Q/D5sEHnZTQRrQlNKINks44DMR1gwXp0p4LaVIeccX2KHTTcHVqQ==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - socks: 2.7.1 - transitivePeerDependencies: - - supports-color - dev: true - - /socks@2.7.1: - resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} - engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} - dependencies: - ip: 2.0.0 - smart-buffer: 4.2.0 - dev: true - - /sort-object-keys@1.1.3: - resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - dev: true - - /sort-package-json@2.6.0: - resolution: {integrity: sha512-XSQ+lY9bAYA8ZsoChcEoPlgcSMaheziEp1beox1JVxy1SV4F2jSq9+h2rJ+3mC/Dhu9Ius1DLnInD5AWcsDXZw==} - hasBin: true - dependencies: - detect-indent: 7.0.1 - detect-newline: 4.0.1 - get-stdin: 9.0.0 - git-hooks-list: 3.1.0 - globby: 13.2.2 - is-plain-obj: 4.1.0 - sort-object-keys: 1.1.3 - dev: true - - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - - /source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.16 - dev: true - - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.16 - dev: true - - /spdx-license-ids@3.0.16: - resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} - dev: true - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - dev: true - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - - /streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - - /string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string.prototype.matchall@4.0.10: - resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - internal-slot: 1.0.6 - regexp.prototype.flags: 1.5.1 - set-function-name: 2.0.1 - side-channel: 1.0.6 - dev: true - - /string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.3 - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /styled-jsx@5.1.1(@babel/core@7.24.5)(react@18.2.0): - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - '@babel/core': 7.24.5 - client-only: 0.0.1 - react: 18.2.0 - - /superagent@8.1.2: - resolution: {integrity: sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==} - engines: {node: '>=6.4.0 <13 || >=14'} - deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net - dependencies: - component-emitter: 1.3.1 - cookiejar: 2.1.4 - debug: 4.3.4 - fast-safe-stringify: 2.1.1 - form-data: 4.0.0 - formidable: 2.1.2 - methods: 1.1.2 - mime: 2.6.0 - qs: 6.12.1 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /supertest@6.3.4: - resolution: {integrity: sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==} - engines: {node: '>=6.4.0'} - dependencies: - methods: 1.1.2 - superagent: 8.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /swap-case@1.1.2: - resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} - dependencies: - lower-case: 1.1.4 - upper-case: 1.1.3 - dev: true - - /symbol-observable@4.0.0: - resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} - engines: {node: '>=0.10'} - dev: true - - /symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - dev: true - - /synckit@0.8.5: - resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/utils': 2.4.2 - tslib: 2.6.2 - dev: true - - /synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.2 - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /terser-webpack-plugin@5.3.10(webpack@5.90.1): - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.31.0 - webpack: 5.90.1 - dev: true - - /terser-webpack-plugin@5.3.10(webpack@5.91.0): - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.31.0 - webpack: 5.91.0 - dev: true - - /terser@5.31.0: - resolution: {integrity: sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.10.0 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true - - /tinycolor2@1.6.0: - resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} - dev: true - - /tinygradient@1.1.5: - resolution: {integrity: sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==} - dependencies: - '@types/tinycolor2': 1.4.6 - tinycolor2: 1.6.0 - dev: true - - /title-case@2.1.1: - resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - dev: true - - /titleize@3.0.0: - resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} - engines: {node: '>=12'} - dev: true - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - - /tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - - /tough-cookie@4.1.4: - resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} - engines: {node: '>=6'} - dependencies: - psl: 1.9.0 - punycode: 2.3.0 - universalify: 0.2.0 - url-parse: 1.5.10 - dev: true - - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - /tr46@3.0.0: - resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} - engines: {node: '>=12'} - dependencies: - punycode: 2.3.0 - dev: true - - /tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - dev: true - - /ts-api-utils@1.0.2(typescript@5.5.4): - resolution: {integrity: sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==} - engines: {node: '>=16.13.0'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /ts-jest@29.2.5(@babel/core@7.24.5)(jest@29.7.0)(typescript@5.5.4): - resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - dependencies: - '@babel/core': 7.24.5 - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.11.24)(ts-node@10.9.2) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.3 - typescript: 5.5.4 - yargs-parser: 21.1.1 - dev: true - - /ts-loader@9.5.1(typescript@5.5.4)(webpack@5.91.0): - resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} - engines: {node: '>=12.0.0'} - peerDependencies: - typescript: '*' - webpack: ^5.0.0 - dependencies: - chalk: 4.1.2 - enhanced-resolve: 5.16.1 - micromatch: 4.0.5 - semver: 7.5.4 - source-map: 0.7.4 - typescript: 5.5.4 - webpack: 5.91.0 - dev: true - - /ts-node@10.9.2(@types/node@20.11.24)(typescript@5.5.4): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.11.24 - acorn: 8.10.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.5.4 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /tsconfig-paths-webpack-plugin@4.1.0: - resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==} - engines: {node: '>=10.13.0'} - dependencies: - chalk: 4.1.2 - enhanced-resolve: 5.16.1 - tsconfig-paths: 4.2.0 - dev: true - - /tsconfig-paths@3.14.2: - resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tsconfig-paths@4.2.0: - resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} - engines: {node: '>=6'} - dependencies: - json5: 2.2.3 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - /tsutils@3.21.0(typescript@5.5.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.4 - dev: true - - /turbo-darwin-64@2.0.4: - resolution: {integrity: sha512-x9mvmh4wudBstML8Z8IOmokLWglIhSfhQwnh2gBCSqabgVBKYvzl8Y+i+UCNPxheCGTgtsPepTcIaKBIyFIcvw==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.4: - resolution: {integrity: sha512-/B1Ih8zPRGVw5vw4SlclOf3C/woJ/2T6ieH6u54KT4wypoaVyaiyMqBcziIXycdObIYr7jQ+raHO7q3mhay9/A==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.4: - resolution: {integrity: sha512-6aG670e5zOWu6RczEYcB81nEl8EhiGJEvWhUrnAfNEUIMBEH1pR5SsMmG2ol5/m3PgiRM12r13dSqTxCLcHrVg==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.4: - resolution: {integrity: sha512-AXfVOjst+mCtPDFT4tCu08Qrfv12Nj7NDd33AjGwV79NYN1Y1rcFY59UQ4nO3ij3rbcvV71Xc+TZJ4csEvRCSg==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.4: - resolution: {integrity: sha512-QOnUR9hKl0T5gq5h1fAhVEqBSjpcBi/BbaO71YGQNgsr6pAnCQdbG8/r3MYXet53efM0KTdOhieWeO3KLNKybA==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.4: - resolution: {integrity: sha512-3v8WpdZy1AxZw0gha0q3caZmm+0gveBQ40OspD6mxDBIS+oBtO5CkxhIXkFJJW+jDKmDlM7wXDIGfMEq+QyNCQ==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.4: - resolution: {integrity: sha512-Ilme/2Q5kYw0AeRr+aw3s02+WrEYaY7U8vPnqSZU/jaDG/qd6jHVN6nRWyd/9KXvJGYM69vE6JImoGoyNjLwaw==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.4 - turbo-darwin-arm64: 2.0.4 - turbo-linux-64: 2.0.4 - turbo-linux-arm64: 2.0.4 - turbo-windows-64: 2.0.4 - turbo-windows-arm64: 2.0.4 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - - /typed-array-buffer@1.0.0: - resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-typed-array: 1.1.12 - dev: true - - /typed-array-byte-length@1.0.0: - resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 - dev: true - - /typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 - dev: true - - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - is-typed-array: 1.1.12 - dev: true - - /typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - - /typescript@5.3.3: - resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /uid@2.0.2: - resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} - engines: {node: '>=8'} - dependencies: - '@lukeed/csprng': 1.1.0 - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify@0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify@2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} - engines: {node: '>= 10.0.0'} - dev: true - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - /untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - dev: true - - /update-browserslist-db@1.0.13(browserslist@4.23.0): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.1 - picocolors: 1.0.0 - - /update-check@1.5.4: - resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} - dependencies: - registry-auth-token: 3.3.2 - registry-url: 3.1.0 - dev: true - - /upper-case-first@1.1.2: - resolution: {integrity: sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==} - dependencies: - upper-case: 1.1.3 - dev: true - - /upper-case@1.1.3: - resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.0 - dev: true - - /url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /v8-to-istanbul@9.2.0: - resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} - engines: {node: '>=10.12.0'} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /validate-npm-package-name@5.0.0: - resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - builtins: 5.0.1 - dev: true - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - - /w3c-xmlserializer@4.0.0: - resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} - engines: {node: '>=14'} - dependencies: - xml-name-validator: 4.0.0 - dev: true - - /walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - dependencies: - makeerror: 1.0.12 - dev: true - - /watchpack@2.4.1: - resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} - engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - dev: true - - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - /webidl-conversions@7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} - dev: true - - /webpack-node-externals@3.0.0: - resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==} - engines: {node: '>=6'} - dev: true - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack@5.90.1: - resolution: {integrity: sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.10.0 - acorn-import-assertions: 1.9.0(acorn@8.10.0) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.1 - es-module-lexer: 1.5.2 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.90.1) - watchpack: 2.4.1 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - - /webpack@5.91.0: - resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.10.0 - acorn-import-assertions: 1.9.0(acorn@8.10.0) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.1 - es-module-lexer: 1.5.2 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.91.0) - watchpack: 2.4.1 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - - /whatwg-encoding@2.0.0: - resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} - engines: {node: '>=12'} - dependencies: - iconv-lite: 0.6.3 - dev: true - - /whatwg-mimetype@3.0.0: - resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} - engines: {node: '>=12'} - dev: true - - /whatwg-url@11.0.0: - resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} - engines: {node: '>=12'} - dependencies: - tr46: 3.0.0 - webidl-conversions: 7.0.0 - dev: true - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.0 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.13 - dev: true - - /which-collection@1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} - dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 - dev: true - - /which-typed-array@1.1.13: - resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - dev: true - - /ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /xml-name-validator@4.0.0: - resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} - engines: {node: '>=12'} - dev: true - - /xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - dev: true - - /xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - 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.8 - yargs-parser: 21.1.1 - dev: true - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true diff --git a/examples/with-nextjs/README.md b/examples/with-nextjs/README.md deleted file mode 100644 index 3c27258371b99..0000000000000 --- a/examples/with-nextjs/README.md +++ /dev/null @@ -1,15 +0,0 @@ -The following turborepo examples contain [Next.js](https://nextjs.org/) applications: - -1. [basic](../basic/) -1. [kitchen-sink](../kitchen-sink/) -1. [non-monorepo](../non-monorepo/) -1. [with-changesets](../with-changesets/) -1. [with-docker](../with-docker/) -1. [with-prisma](../with-prisma) -1. [with-yarn](../with-yarn/) -1. [with-berry](../with-berry/) -1. [with-npm](../with-npm/) -1. [with-react-native-web](../with-react-native-web/) -1. [with-tailwind](../with-tailwind/) - - diff --git a/examples/with-npm/README.md b/examples/with-npm/README.md deleted file mode 100644 index 9657655014c45..0000000000000 --- a/examples/with-npm/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Turborepo starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-npm -``` - -## What's inside? - -This Turborepo uses [npm](https://www.npmjs.com/) as a packages manager. It includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [Next.js](https://nextjs.org/) app -- `web`: another [Next.js](https://nextjs.org/) app -- `@repo/ui`: a stub React component library shared by both `web` and `docs` applications -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Build - -To build all apps and packages, run the following command: - -``` -cd my-turborepo -npm run build -``` - -### Develop - -To develop all apps and packages, run the following command: - -``` -cd my-turborepo -npm run dev -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -``` -cd my-turborepo -npx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: - -``` -npx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/with-npm/apps/docs/.eslintrc.js b/examples/with-npm/apps/docs/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-npm/apps/docs/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-npm/apps/docs/README.md b/examples/with-npm/apps/docs/README.md deleted file mode 100644 index 705215d358273..0000000000000 --- a/examples/with-npm/apps/docs/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -npm run dev -``` - -Open [http://localhost:3001](http://localhost:3001) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-npm/apps/docs/package.json b/examples/with-npm/apps/docs/package.json index 7405043a42d9e..2cd3cf7afbf3f 100644 --- a/examples/with-npm/apps/docs/package.json +++ b/examples/with-npm/apps/docs/package.json @@ -1,28 +1,17 @@ { - "name": "docs", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev --port 3001", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0" - }, - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "docs", + "scripts": { + "build": "next build", + "dev": "next dev --port 3001", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-npm/apps/web/.eslintrc.js b/examples/with-npm/apps/web/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-npm/apps/web/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-npm/apps/web/README.md b/examples/with-npm/apps/web/README.md deleted file mode 100644 index c0f535cd4fa55..0000000000000 --- a/examples/with-npm/apps/web/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -npm run dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-npm/apps/web/package.json b/examples/with-npm/apps/web/package.json index bbbf678567c59..f5ce740cc1204 100644 --- a/examples/with-npm/apps/web/package.json +++ b/examples/with-npm/apps/web/package.json @@ -1,28 +1,17 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint --max-warnings 0" - }, - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-npm/package-lock.json b/examples/with-npm/package-lock.json deleted file mode 100644 index ab06f07c71e5f..0000000000000 --- a/examples/with-npm/package-lock.json +++ /dev/null @@ -1,8610 +0,0 @@ -{ - "name": "with-npm", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "with-npm", - "workspaces": [ - "apps/*", - "packages/*" - ], - "devDependencies": { - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "engines": { - "node": ">=18" - } - }, - "apps/docs": { - "version": "1.0.0", - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } - }, - "apps/web": { - "version": "1.0.0", - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", - "integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", - "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", - "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.3", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.3", - "@babel/types": "^7.23.3", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.3.tgz", - "integrity": "sha512-9bTuNlyx7oSstodm1cR1bECj4fkiknsDa1YniISkJemMY3DGhJNYBECbe6QD/q54mp2J8VO66jW3/7uP//iFCw==", - "dev": true, - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@babel/eslint-parser/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.4.tgz", - "integrity": "sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.4", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.4.tgz", - "integrity": "sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.4", - "@babel/types": "^7.23.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz", - "integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", - "integrity": "sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.4.tgz", - "integrity": "sha512-zQyB4MJGM+rvd4pM58n26kf3xbiitw9MHzL8oLiBMKb8MCtVDfV5nDzzJWWzLMtbvKI9wN6XwJYl479qF4JluQ==", - "dev": true, - "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.4.tgz", - "integrity": "sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.4", - "@babel/generator": "^7.23.4", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.4", - "@babel/types": "^7.23.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.4.tgz", - "integrity": "sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@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/@cspotcode/source-map-support/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/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "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.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", - "dev": true - }, - "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@next/env": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.1.tgz", - "integrity": "sha512-7CnQyD5G8shHxQIIg3c7/pSeYFeMhsNbpU/bmvH7ZnDql7mNRgg8O2JZrhrc/soFnfBnKP4/xXNiiSIPn2w8gA==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.1.tgz", - "integrity": "sha512-NP1WoGFnFLpqqCWgGFjnn/sTwUExdPyjeFKRdQP1X/bL/tjAQ/TXDmYqw6vzGaP5NaZ2u6xzg+N/0nd7fOPOGQ==", - "dev": true, - "dependencies": { - "glob": "10.3.10" - } - }, - "node_modules/@next/eslint-plugin-next/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.1.tgz", - "integrity": "sha512-yDjSFKQKTIjyT7cFv+DqQfW5jsD+tVxXTckSe1KIouKk75t1qZmj/mV3wzdmFb0XHVGtyRjDMulfVG8uCKemOQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.1.tgz", - "integrity": "sha512-KCQmBL0CmFmN8D64FHIZVD9I4ugQsDBBEJKiblXGgwn7wBCSe8N4Dx47sdzl4JAg39IkSN5NNrr8AniXLMb3aw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.1.tgz", - "integrity": "sha512-YDQfbWyW0JMKhJf/T4eyFr4b3tceTorQ5w2n7I0mNVTFOvu6CGEzfwT3RSAQGTi/FFMTFcuspPec/7dFHuP7Eg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.1.tgz", - "integrity": "sha512-fiuN/OG6sNGRN/bRFxRvV5LyzLB8gaL8cbDH5o3mEiVwfcMzyE5T//ilMmaTrnA8HLMS6hoz4cHOu6Qcp9vxgQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.1.tgz", - "integrity": "sha512-rv6AAdEXoezjbdfp3ouMuVqeLjE1Bin0AuE6qxE6V9g3Giz5/R3xpocHoAi7CufRR+lnkuUjRBn05SYJ83oKNQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.1.tgz", - "integrity": "sha512-YAZLGsaNeChSrpz/G7MxO3TIBLaMN8QWMr3X8bt6rCvKovwU7GqQlDu99WdvF33kI8ZahvcdbFsy4jAFzFX7og==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.1.tgz", - "integrity": "sha512-1L4mUYPBMvVDMZg1inUYyPvFSduot0g73hgfD9CODgbr4xiTYe0VOMTZzaRqYJYBA9mana0x4eaAaypmWo1r5A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.1.tgz", - "integrity": "sha512-jvIE9tsuj9vpbbXlR5YxrghRfMuG0Qm/nZ/1KDHc+y6FpnZ/apsgh+G6t15vefU0zp3WSpTMIdXRUsNl/7RSuw==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.1.tgz", - "integrity": "sha512-S6K6EHDU5+1KrBDLko7/c1MNy/Ya73pIAmvKeFwsF4RmBFJSO7/7YeD4FnZ4iBdzE69PpQ4sOMU9ORKeNuxe8A==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, - "dependencies": { - "eslint-scope": "5.1.1" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pkgr/utils": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", - "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.3.0", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@repo/eslint-config": { - "resolved": "packages/eslint-config", - "link": true - }, - "node_modules/@repo/typescript-config": { - "resolved": "packages/typescript-config", - "link": true - }, - "node_modules/@repo/ui": { - "resolved": "packages/ui", - "link": true - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz", - "integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==", - "dev": true - }, - "node_modules/@swc/helpers": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", - "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true - }, - "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/@turbo/gen": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/@turbo/gen/-/gen-1.12.4.tgz", - "integrity": "sha512-3Z8KZ6Vnc2x6rr8sNJ4QNYpkAttLBfb91uPzDlFDY7vgJg+vfXT8YWyZznVL+19ZixF2C/F4Ucp4/YjG2e1drg==", - "dev": true, - "dependencies": { - "@turbo/workspaces": "1.12.4", - "chalk": "2.4.2", - "commander": "^10.0.0", - "fs-extra": "^10.1.0", - "inquirer": "^8.2.4", - "minimatch": "^9.0.0", - "node-plop": "^0.26.3", - "proxy-agent": "^6.2.2", - "ts-node": "^10.9.1", - "update-check": "^1.5.4", - "validate-npm-package-name": "^5.0.0" - }, - "bin": { - "gen": "dist/cli.js" - } - }, - "node_modules/@turbo/workspaces": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/@turbo/workspaces/-/workspaces-1.12.4.tgz", - "integrity": "sha512-a1hF8Nr6MOeCpvlLR569dGTlzgRLj2Rxo6dTb4jtL+jhHwCb94A9kDPgcRnYGFr45mgulICarVaNZxDjw4/riQ==", - "dev": true, - "dependencies": { - "chalk": "2.4.2", - "commander": "^10.0.0", - "execa": "5.1.1", - "fast-glob": "^3.2.12", - "fs-extra": "^10.1.0", - "gradient-string": "^2.0.0", - "inquirer": "^8.0.0", - "js-yaml": "^4.1.0", - "ora": "4.1.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "update-check": "^1.5.4" - }, - "bin": { - "workspaces": "dist/cli.js" - } - }, - "node_modules/@types/eslint": { - "version": "8.56.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.5.tgz", - "integrity": "sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/inquirer": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-6.5.0.tgz", - "integrity": "sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==", - "dev": true, - "dependencies": { - "@types/through": "*", - "rxjs": "^6.4.0" - } - }, - "node_modules/@types/inquirer/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@types/inquirer/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true - }, - "node_modules/@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.2.61", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.61.tgz", - "integrity": "sha512-NURTN0qNnJa7O/k4XUkEW2yfygA+NxS0V5h1+kp9jPwhzZy95q3ADoGMP0+JypMhrZBTTgjKAUlTctde1zzeQA==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.2.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz", - "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", - "dev": true - }, - "node_modules/@types/through": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", - "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/tinycolor2": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.6.tgz", - "integrity": "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz", - "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.1.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vercel/style-guide": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@vercel/style-guide/-/style-guide-5.2.0.tgz", - "integrity": "sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==", - "dev": true, - "dependencies": { - "@babel/core": "^7.22.11", - "@babel/eslint-parser": "^7.22.11", - "@rushstack/eslint-patch": "^1.3.3", - "@typescript-eslint/eslint-plugin": "^6.5.0", - "@typescript-eslint/parser": "^6.5.0", - "eslint-config-prettier": "^9.0.0", - "eslint-import-resolver-alias": "^1.1.2", - "eslint-import-resolver-typescript": "^3.6.0", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jest": "^27.2.3", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-playwright": "^0.16.0", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-testing-library": "^6.0.1", - "eslint-plugin-tsdoc": "^0.2.17", - "eslint-plugin-unicorn": "^48.0.1", - "prettier-plugin-packagejson": "^2.4.5" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@next/eslint-plugin-next": ">=12.3.0 <15", - "eslint": ">=8.48.0 <9", - "prettier": ">=3.0.0 <4", - "typescript": ">=4.8.0 <6" - }, - "peerDependenciesMeta": { - "@next/eslint-plugin-next": { - "optional": true - }, - "eslint": { - "optional": true - }, - "prettier": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@vercel/style-guide/node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "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/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/basic-ftp": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", - "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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/camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001593", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001593.tgz", - "integrity": "sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/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/change-case": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.1.0.tgz", - "integrity": "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==", - "dev": true, - "dependencies": { - "camel-case": "^3.0.0", - "constant-case": "^2.0.0", - "dot-case": "^2.1.0", - "header-case": "^1.0.0", - "is-lower-case": "^1.1.0", - "is-upper-case": "^1.1.0", - "lower-case": "^1.1.1", - "lower-case-first": "^1.0.0", - "no-case": "^2.3.2", - "param-case": "^2.1.0", - "pascal-case": "^2.0.0", - "path-case": "^2.1.0", - "sentence-case": "^2.1.0", - "snake-case": "^2.1.0", - "swap-case": "^1.1.0", - "title-case": "^2.1.0", - "upper-case": "^1.1.1", - "upper-case-first": "^1.1.0" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/clean-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", - "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "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/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/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/constant-case": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz", - "integrity": "sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==", - "dev": true, - "dependencies": { - "snake-case": "^2.1.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/core-js-pure": { - "version": "3.33.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.33.3.tgz", - "integrity": "sha512-taJ00IDOP+XYQEA2dAe4ESkmHt1fL8wzYDo3mRWQey8uO9UojlBFMneA65kMyxfYP7106c6LzWaq7/haDT6BCQ==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "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/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", - "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-browser/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/default-browser/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/del": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", - "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", - "dev": true, - "dependencies": { - "globby": "^10.0.1", - "graceful-fs": "^4.2.2", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.1", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/del/node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", - "dev": true, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/detect-newline": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", - "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/docs": { - "resolved": "apps/docs", - "link": true - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dot-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz", - "integrity": "sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.592", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.592.tgz", - "integrity": "sha512-D3NOkROIlF+d5ixnz7pAf3Lu/AuWpd6AYgI9O67GQXMXTcCP1gJQRotOq35eQy5Sb4hez33XH1YdTtILA7Udww==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", - "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", - "dev": true, - "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.1", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.0.1" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-config-turbo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-2.0.0.tgz", - "integrity": "sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw==", - "dev": true, - "dependencies": { - "eslint-plugin-turbo": "2.0.0" - }, - "peerDependencies": { - "eslint": ">6.6.0" - } - }, - "node_modules/eslint-import-resolver-alias": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz", - "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==", - "dev": true, - "engines": { - "node": ">= 4" - }, - "peerDependencies": { - "eslint-plugin-import": ">=1.4.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-eslint-comments": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", - "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5", - "ignore": "^5.0.5" - }, - "engines": { - "node": ">=6.5.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-only-warn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-only-warn/-/eslint-plugin-only-warn-1.1.0.tgz", - "integrity": "sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-plugin-playwright": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.16.0.tgz", - "integrity": "sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==", - "dev": true, - "peerDependencies": { - "eslint": ">=7", - "eslint-plugin-jest": ">=25" - }, - "peerDependenciesMeta": { - "eslint-plugin-jest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "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/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-testing-library": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.0.tgz", - "integrity": "sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.58.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6" - }, - "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-tsdoc": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", - "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "0.16.2" - } - }, - "node_modules/eslint-plugin-turbo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-2.0.0.tgz", - "integrity": "sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw==", - "dev": true, - "dependencies": { - "dotenv": "16.0.3" - }, - "peerDependencies": { - "eslint": ">6.6.0" - } - }, - "node_modules/eslint-plugin-unicorn": { - "version": "48.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz", - "integrity": "sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "@eslint-community/eslint-utils": "^4.4.0", - "ci-info": "^3.8.0", - "clean-regexp": "^1.0.0", - "esquery": "^1.5.0", - "indent-string": "^4.0.0", - "is-builtin-module": "^3.2.1", - "jsesc": "^3.0.2", - "lodash": "^4.17.21", - "pluralize": "^8.0.0", - "read-pkg-up": "^7.0.1", - "regexp-tree": "^0.1.27", - "regjsparser": "^0.10.0", - "semver": "^7.5.4", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" - }, - "peerDependencies": { - "eslint": ">=8.44.0" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/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/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/get-uri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", - "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", - "dev": true, - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.0", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/get-uri/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/get-uri/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/get-uri/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/git-hooks-list": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", - "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", - "dev": true, - "funding": { - "url": "https://github.com/fisker/git-hooks-list?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/gradient-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/gradient-string/-/gradient-string-2.0.2.tgz", - "integrity": "sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.2", - "tinygradient": "^1.1.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gradient-string/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/gradient-string/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/gradient-string/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/gradient-string/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/gradient-string/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/gradient-string/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/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/header-case": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz", - "integrity": "sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.3" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "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/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "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/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/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/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/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/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/inquirer/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/inquirer/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/inquirer/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/inquirer/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/inquirer/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/inquirer/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inquirer/node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inquirer/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/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", - "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", - "dev": true - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "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-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lower-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", - "integrity": "sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==", - "dev": true, - "dependencies": { - "lower-case": "^1.1.0" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.11" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-upper-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", - "integrity": "sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==", - "dev": true, - "dependencies": { - "upper-case": "^1.1.0" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "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/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", - "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==" - }, - "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/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-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": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "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/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/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.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "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/log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", - "dev": true - }, - "node_modules/lower-case-first": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", - "integrity": "sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==", - "dev": true, - "dependencies": { - "lower-case": "^1.1.2" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "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/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/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/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/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/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/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/next": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/next/-/next-14.1.1.tgz", - "integrity": "sha512-McrGJqlGSHeaz2yTRPkEucxQKe5Zq7uPwyeHNmJaZNY4wx9E9QdxmTp310agFRoMuIYgQrCrT3petg13fSVOww==", - "dependencies": { - "@next/env": "14.1.1", - "@swc/helpers": "0.5.2", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", - "postcss": "8.4.31", - "styled-jsx": "5.1.1" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=18.17.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "14.1.1", - "@next/swc-darwin-x64": "14.1.1", - "@next/swc-linux-arm64-gnu": "14.1.1", - "@next/swc-linux-arm64-musl": "14.1.1", - "@next/swc-linux-x64-gnu": "14.1.1", - "@next/swc-linux-x64-musl": "14.1.1", - "@next/swc-win32-arm64-msvc": "14.1.1", - "@next/swc-win32-ia32-msvc": "14.1.1", - "@next/swc-win32-x64-msvc": "14.1.1" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/node-plop": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/node-plop/-/node-plop-0.26.3.tgz", - "integrity": "sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==", - "dev": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.9.2", - "@types/inquirer": "^6.5.0", - "change-case": "^3.1.0", - "del": "^5.1.0", - "globby": "^10.0.1", - "handlebars": "^4.4.3", - "inquirer": "^7.1.0", - "isbinaryfile": "^4.0.2", - "lodash.get": "^4.4.2", - "mkdirp": "^0.5.1", - "resolve": "^1.12.0" - }, - "engines": { - "node": ">=8.9.4" - } - }, - "node_modules/node-plop/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/node-plop/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/node-plop/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/node-plop/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/node-plop/node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-plop/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/node-plop/node_modules/inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/node-plop/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/node-plop/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/node-plop/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/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/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz", - "integrity": "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==", - "dev": true, - "dependencies": { - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.2.0", - "is-interactive": "^1.0.0", - "log-symbols": "^3.0.0", - "mute-stream": "0.0.8", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/pac-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", - "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", - "dev": true, - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "pac-resolver": "^7.0.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", - "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", - "dev": true, - "dependencies": { - "degenerator": "^5.0.0", - "ip": "^1.1.8", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "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/pascal-case": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", - "integrity": "sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==", - "dev": true, - "dependencies": { - "camel-case": "^3.0.0", - "upper-case-first": "^1.1.0" - } - }, - "node_modules/path-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz", - "integrity": "sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-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-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "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/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-packagejson": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.4.6.tgz", - "integrity": "sha512-5JGfzkJRL0DLNyhwmiAV9mV0hZLHDwddFCs2lc9CNxOChpoWUQVe8K4qTMktmevmDlMpok2uT10nvHUyU59sNw==", - "dev": true, - "dependencies": { - "sort-package-json": "2.6.0", - "synckit": "0.8.5" - }, - "peerDependencies": { - "prettier": ">= 1.16.0" - }, - "peerDependenciesMeta": { - "prettier": { - "optional": true - } - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true - }, - "node_modules/regexp-tree": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", - "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", - "dev": true, - "bin": { - "regexp-tree": "bin/regexp-tree" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", - "dev": true, - "dependencies": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", - "dev": true, - "dependencies": { - "rc": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regjsparser": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", - "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "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": "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/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "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/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/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/sentence-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz", - "integrity": "sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case-first": "^1.1.2" - } - }, - "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/snake-case": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", - "integrity": "sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "dev": true - }, - "node_modules/sort-object-keys": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", - "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", - "dev": true - }, - "node_modules/sort-package-json": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.6.0.tgz", - "integrity": "sha512-XSQ+lY9bAYA8ZsoChcEoPlgcSMaheziEp1beox1JVxy1SV4F2jSq9+h2rJ+3mC/Dhu9Ius1DLnInD5AWcsDXZw==", - "dev": true, - "dependencies": { - "detect-indent": "^7.0.1", - "detect-newline": "^4.0.0", - "get-stdin": "^9.0.0", - "git-hooks-list": "^3.0.0", - "globby": "^13.1.2", - "is-plain-obj": "^4.1.0", - "sort-object-keys": "^1.1.3" - }, - "bin": { - "sort-package-json": "cli.js" - } - }, - "node_modules/sort-package-json/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sort-package-json/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", - "dev": true - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.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/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "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/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/swap-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", - "integrity": "sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==", - "dev": true, - "dependencies": { - "lower-case": "^1.1.1", - "upper-case": "^1.1.1" - } - }, - "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dev": true, - "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/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/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "dev": true - }, - "node_modules/tinygradient": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/tinygradient/-/tinygradient-1.1.5.tgz", - "integrity": "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==", - "dev": true, - "dependencies": { - "@types/tinycolor2": "^1.4.0", - "tinycolor2": "^1.0.0" - } - }, - "node_modules/title-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", - "integrity": "sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.0.3" - } - }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", - "dev": true, - "engines": { - "node": ">=16.13.0" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "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/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/turbo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.0.3.tgz", - "integrity": "sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==", - "dev": true, - "bin": { - "turbo": "bin/turbo" - }, - "optionalDependencies": { - "turbo-darwin-64": "2.0.3", - "turbo-darwin-arm64": "2.0.3", - "turbo-linux-64": "2.0.3", - "turbo-linux-arm64": "2.0.3", - "turbo-windows-64": "2.0.3", - "turbo-windows-arm64": "2.0.3" - } - }, - "node_modules/turbo-darwin-64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.0.3.tgz", - "integrity": "sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/turbo-darwin-arm64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.3.tgz", - "integrity": "sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/turbo-linux-64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.0.3.tgz", - "integrity": "sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/turbo-linux-arm64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.0.3.tgz", - "integrity": "sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/turbo-windows-64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.0.3.tgz", - "integrity": "sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/turbo-windows-arm64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.0.3.tgz", - "integrity": "sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/update-check": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", - "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", - "dev": true, - "dependencies": { - "registry-auth-token": "3.3.2", - "registry-url": "3.1.0" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", - "dev": true - }, - "node_modules/upper-case-first": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", - "integrity": "sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==", - "dev": true, - "dependencies": { - "upper-case": "^1.1.1" - } - }, - "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/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web": { - "resolved": "apps/web", - "link": true - }, - "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/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "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" - } - }, - "packages/eslint-config": { - "name": "@repo/eslint-config", - "version": "0.0.0", - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^6.17.0", - "@typescript-eslint/parser": "^7.1.0", - "@vercel/style-guide": "^5.2.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-only-warn": "^1.1.0", - "typescript": "5.5.4" - } - }, - "packages/typescript-config": { - "name": "@repo/typescript-config", - "version": "0.0.0", - "license": "MIT" - }, - "packages/ui": { - "name": "@repo/ui", - "version": "0.0.0", - "dependencies": { - "react": "^18.2.0" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@turbo/gen": "^1.12.4", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } - } - } -} diff --git a/examples/with-npm/package.json b/examples/with-npm/package.json index 67ce33fdba927..6cf73191c3f3b 100644 --- a/examples/with-npm/package.json +++ b/examples/with-npm/package.json @@ -1,22 +1,15 @@ { - "name": "with-npm", - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "npm@10.5.0", - "engines": { - "node": ">=18" - } + "name": "with-npm", + "workspaces": [ + "apps/*", + "packages/*" + ], + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-npm/packages/eslint-config/README.md b/examples/with-npm/packages/eslint-config/README.md deleted file mode 100644 index b79474eaf968c..0000000000000 --- a/examples/with-npm/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@repo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-npm/packages/eslint-config/package.json b/examples/with-npm/packages/eslint-config/package.json index 7fcfe4885a9a5..dca64b8823b7a 100644 --- a/examples/with-npm/packages/eslint-config/package.json +++ b/examples/with-npm/packages/eslint-config/package.json @@ -1,19 +1,14 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js", - "react-internal.js" - ], - "devDependencies": { - "@vercel/style-guide": "^5.2.0", - "eslint-config-turbo": "^2.0.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-only-warn": "^1.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@typescript-eslint/eslint-plugin": "^6.17.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "next.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-npm/packages/typescript-config/package.json b/examples/with-npm/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-npm/packages/typescript-config/package.json +++ b/examples/with-npm/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-npm/packages/ui/.eslintrc.js b/examples/with-npm/packages/ui/.eslintrc.js deleted file mode 100644 index 53f7390e49fa6..0000000000000 --- a/examples/with-npm/packages/ui/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: "./tsconfig.lint.json", - tsconfigRootDir: __dirname, - }, -}; diff --git a/examples/with-npm/packages/ui/src/card.tsx b/examples/with-npm/packages/ui/Source/card.tsx similarity index 100% rename from examples/with-npm/packages/ui/src/card.tsx rename to examples/with-npm/packages/ui/Source/card.tsx diff --git a/examples/with-npm/packages/ui/src/code.tsx b/examples/with-npm/packages/ui/Source/code.tsx similarity index 100% rename from examples/with-npm/packages/ui/src/code.tsx rename to examples/with-npm/packages/ui/Source/code.tsx diff --git a/examples/with-npm/packages/ui/package.json b/examples/with-npm/packages/ui/package.json index 527dc756df1f7..63cc07ae9dec7 100644 --- a/examples/with-npm/packages/ui/package.json +++ b/examples/with-npm/packages/ui/package.json @@ -1,27 +1,17 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "private": true, - "exports": { - "./card": "./src/card.tsx", - "./code": "./src/code.tsx" - }, - "scripts": { - "lint": "eslint . --max-warnings 0", - "generate:component": "turbo gen react-component" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@turbo/gen": "^1.12.4", - "@types/node": "^20.11.24", - "@types/eslint": "^8.56.5", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - } + "name": "@repo/ui", + "exports": { + "./card": "./src/card.tsx", + "./code": "./src/code.tsx" + }, + "scripts": { + "generate:component": "turbo gen react-component" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@turbo/gen": "2.4.2", + "@types/node": "22.13.1" + } } diff --git a/examples/with-prisma/README.md b/examples/with-prisma/README.md deleted file mode 100644 index 84a6070f64daf..0000000000000 --- a/examples/with-prisma/README.md +++ /dev/null @@ -1,199 +0,0 @@ -# Turborepo + Prisma ORM starter - -This is a example designed to help you quickly set up a Turborepo monorepo with a Next.js app and Prisma ORM. This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## What's inside? - -This turborepo includes the following packages/apps: - -### Apps and packages - -- `web`: a [Next.js](https://nextjs.org/) app -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/database`: [Prisma ORM](https://prisma.io/) to manage & access your database -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting -- [Prisma ORM](https://prisma.io/) for accessing the database -- [Docker Compose](https://docs.docker.com/compose/) for a local MySQL database - -## Getting started - -Follow these steps to set up and run your Turborepo project with Prisma ORM: - -### 1. Create a Turborepo project - -Start by creating a new Turborepo project using the following command: - -```sh -npx create-turbo@latest -e with-prisma -``` - -Choose your desired package manager when prompted and a name for the app (e.g., `my-turborepo`). This will scaffold a new Turborepo project with Prisma ORM included and dependencies installed. - -Navigate to your project directory: - -```bash -cd ./my-turborepo -``` - -### 2. Setup a local database with Docker Compose - -We use [Prisma ORM](https://prisma.io/) to manage and access our database. As such you will need a database for this project, either locally or hosted in the cloud. - -To make this process easier, a [`docker-compose.yml` file](./docker-compose.yml) is included to setup a MySQL server locally with a new database named `turborepo`: - -Start the MySQL database using Docker Compose: - -```sh -docker-compose up -d -``` - -To change the default database name, update the `MYSQL_DATABASE` environment variable in the [`docker-compose.yml` file](/docker-compose.yml). - -### 3. Setup environment variables - -Once the database is ready, copy the `.env.example` file to the [`/packages/database`](./packages/database/) and [`/apps/web`](./apps/web/) directories as `.env`: - -```bash -cp .env.example ./packages/database/.env -cp .env.example ./apps/web/.env -``` - -This ensures Prisma has access to the `DATABASE_URL` environment variable, which is required to connect to your database. - -If you added a custom database name, or use a cloud based database, you will need to update the `DATABASE_URL` in your `.env` accordingly. - -### 4. Migrate your database - -Once your database is running, you’ll need to create and apply migrations to set up the necessary tables. Run the database migration command: - -```bash -# Using npm -npm run db:migrate:dev -``` - -
    - -Expand for yarn, pnpm or bun - -```bash -# Using yarn -yarn run db:migrate:dev - -# Using pnpm -pnpm run db:migrate:dev - -# Using bun -bun run db:migrate:dev -``` - -
    - -You’ll be prompted to name the migration. Once you provide a name, Prisma will create and apply the migration to your database. - -> Note: The `db:migrate:dev` script (located in [packages/database/package.json](/packages/database/package.json)) uses [Prisma Migrate](https://www.prisma.io/migrate) under the hood. - -For production environments, always push schema changes to your database using the [`prisma migrate deploy` command](https://www.prisma.io/docs/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate). You can find an example `db:migrate:deploy` script in the [`package.json` file](/packages/database/package.json) of the `database` package. - -### 5. Seed your database - -To populate your database with initial or fake data, use [Prisma's seeding functionality](https://www.prisma.io/docs/guides/database/seed-database). - -Update the seed script located at [`packages/database/src/seed.ts`](/packages/database/src/seed.ts) to include any additional data that you want to seed. Once edited, run the seed command: - -```bash -# Using npm -npm run db:seed -``` - -
    - -Expand for yarn, pnpm or bun - -```bash -# Using yarn -yarn run db:seed - -# Using pnpm -pnpm run db:seed - -# Using bun -bun run db:seed -``` - -
    - -### 6. Build your application - -To build all apps and packages in the monorepo, run: - -```bash -# Using npm -npm run build -``` - -
    - -Expand for yarn, pnpm or bun - -```bash -# Using yarn -yarn run build - -# Using pnpm -pnpm run build - -# Using bun -bun run build -``` - -
    - -### 7. Start the application - -Finally, start your application with: - -```bash -yarn run dev -``` - -
    - -Expand for yarn, pnpm or bun - -```bash -# Using yarn -yarn run dev - -# Using pnpm -pnpm run dev - -# Using bun -bun run dev -``` - -
    - -Your app will be running at `http://localhost:3000`. Open it in your browser to see it in action! - -You can also read the official [detailed step-by-step guide from Prisma ORM](https://pris.ly/guide/turborepo?utm_campaign=turborepo-example) to build a project from scratch using Turborepo and Prisma ORM. - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/with-prisma/apps/web/.eslintrc.js b/examples/with-prisma/apps/web/.eslintrc.js deleted file mode 100644 index 6582db49b5b60..0000000000000 --- a/examples/with-prisma/apps/web/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-prisma/apps/web/README.md b/examples/with-prisma/apps/web/README.md deleted file mode 100644 index 3d7b63af7dc79..0000000000000 --- a/examples/with-prisma/apps/web/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-prisma/apps/web/package.json b/examples/with-prisma/apps/web/package.json index 1d60e634e6ce9..4456da1a4c985 100644 --- a/examples/with-prisma/apps/web/package.json +++ b/examples/with-prisma/apps/web/package.json @@ -1,27 +1,17 @@ { - "private": true, - "name": "web", - "version": "1.0.0", - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0" - }, - "dependencies": { - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/database": "*", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "next": "15.1.7" + }, + "devDependencies": { + "@repo/database": "*", + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-prisma/package.json b/examples/with-prisma/package.json index fd7f6eced9745..fc02efe3a270f 100644 --- a/examples/with-prisma/package.json +++ b/examples/with-prisma/package.json @@ -1,36 +1,28 @@ { - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "prisma": { - "schema": "packages/database/prisma/schema.prisma", - "seed": "tsx packages/database/src/seed.ts" - }, - "scripts": { - "build": "turbo run build", - "db:migrate:deploy": "turbo run db:migrate:deploy", - "db:migrate:dev": "turbo run db:migrate:dev", - "db:push": "turbo run db:push", - "db:seed": "turbo run db:seed", - "dev": "turbo run dev", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "generate": "turbo run generate", - "lint": "turbo run lint" - }, - "devDependencies": { - "prettier": "^3.2.5", - "prisma": "latest", - "tsx": "4.19.1", - "turbo": "^2.0.3" - }, - "engines": { - "node": ">=18" - }, - "packageManager": "yarn@1.22.19", - "name": "with-prisma", - "dependencies": { - "@prisma/client": "latest" - } + "name": "with-prisma", + "workspaces": [ + "apps/*", + "packages/*" + ], + "scripts": { + "build": "turbo run build", + "db:migrate:deploy": "turbo run db:migrate:deploy", + "db:migrate:dev": "turbo run db:migrate:dev", + "db:push": "turbo run db:push", + "db:seed": "turbo run db:seed", + "dev": "turbo run dev", + "generate": "turbo run generate" + }, + "dependencies": { + "@prisma/client": "latest" + }, + "devDependencies": { + "prisma": "latest", + "tsx": "4.19.2", + "turbo": "2.4.2" + }, + "prisma": { + "schema": "packages/database/prisma/schema.prisma", + "seed": "tsx packages/database/src/seed.ts" + } } diff --git a/examples/with-prisma/packages/config-eslint/README.md b/examples/with-prisma/packages/config-eslint/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-prisma/packages/config-eslint/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-prisma/packages/config-eslint/package.json b/examples/with-prisma/packages/config-eslint/package.json index 01c8e124f5028..c4a0db612e165 100644 --- a/examples/with-prisma/packages/config-eslint/package.json +++ b/examples/with-prisma/packages/config-eslint/package.json @@ -1,18 +1,13 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js" - ], - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@vercel/style-guide": "^5.2.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-only-warn": "^1.1.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "next.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-prisma/packages/config-typescript/package.json b/examples/with-prisma/packages/config-typescript/package.json index bff20b7fa0c90..0b30de456c71c 100644 --- a/examples/with-prisma/packages/config-typescript/package.json +++ b/examples/with-prisma/packages/config-typescript/package.json @@ -1,8 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-prisma/packages/database/.eslintrc.js b/examples/with-prisma/packages/database/.eslintrc.js deleted file mode 100644 index d69a85871d981..0000000000000 --- a/examples/with-prisma/packages/database/.eslintrc.js +++ /dev/null @@ -1,16 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - extends: ["@repo/eslint-config/library.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, - rules: { - "turbo/no-undeclared-env-vars": [ - "error", - { - allowList: ["NODE_ENV"], - }, - ], - }, -}; diff --git a/examples/with-prisma/packages/database/src/client.ts b/examples/with-prisma/packages/database/Source/client.ts similarity index 100% rename from examples/with-prisma/packages/database/src/client.ts rename to examples/with-prisma/packages/database/Source/client.ts diff --git a/examples/with-prisma/packages/database/src/seed.ts b/examples/with-prisma/packages/database/Source/seed.ts similarity index 100% rename from examples/with-prisma/packages/database/src/seed.ts rename to examples/with-prisma/packages/database/Source/seed.ts diff --git a/examples/with-prisma/packages/database/package.json b/examples/with-prisma/packages/database/package.json index f2fd92ad81c3d..29bb65f37f0e5 100644 --- a/examples/with-prisma/packages/database/package.json +++ b/examples/with-prisma/packages/database/package.json @@ -1,33 +1,28 @@ { - "name": "@repo/database", - "version": "1.0.0", - "exports": { - ".": "./src/client.ts" - }, - "scripts": { - "db:migrate:deploy": "prisma migrate deploy", - "db:migrate:dev": "prisma migrate dev", - "db:push": "prisma db push", - "db:seed": "tsx src/seed.ts", - "dev": "tsup src/* --watch", - "format": "prisma format", - "generate": "prisma generate", - "lint": "eslint . --max-warnings 0", - "prebuild": "npm run generate", - "predev": "npm run generate", - "studio": "prisma studio" - }, - "dependencies": { - "@prisma/client": "latest" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "eslint": "^8.57.0", - "prisma": "latest", - "rimraf": "^5.0.5", - "tsup": "^8.0.2", - "tsx": "4.19.1", - "typescript": "5.5.4" - } + "name": "@repo/database", + "exports": { + ".": "./src/client.ts" + }, + "scripts": { + "db:migrate:deploy": "prisma migrate deploy", + "db:migrate:dev": "prisma migrate dev", + "db:push": "prisma db push", + "db:seed": "tsx src/seed.ts", + "predev": "npm run generate", + "dev": "tsup src/* --watch", + "generate": "prisma generate", + "prebuild": "npm run generate", + "studio": "prisma studio" + }, + "dependencies": { + "@prisma/client": "latest" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "prisma": "latest", + "rimraf": "6.0.1", + "tsup": "8.3.6", + "tsx": "4.19.2" + } } diff --git a/examples/with-prisma/yarn.lock b/examples/with-prisma/yarn.lock deleted file mode 100644 index faafc2111edb8..0000000000000 --- a/examples/with-prisma/yarn.lock +++ /dev/null @@ -1,4188 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" - integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== - dependencies: - "@babel/highlight" "^7.24.6" - picocolors "^1.0.0" - -"@babel/compat-data@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" - integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== - -"@babel/core@^7.22.11": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" - integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helpers" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/traverse" "^7.24.6" - "@babel/types" "^7.24.6" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/eslint-parser@^7.22.11": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.24.6.tgz#7f0ecc0f29307b8696e83ff6a9d8b4f3e0421ad2" - integrity sha512-Q1BfQX42zXHx732PLW0w4+Y3wJjoZKEMaatFUEAmQ7Z+jCXxinzeqX9bvv2Q8xNPes/H6F0I23oGkcgjaItmLw== - dependencies: - "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" - eslint-visitor-keys "^2.1.0" - semver "^6.3.1" - -"@babel/generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" - integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== - dependencies: - "@babel/types" "^7.24.6" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz#4a51d681f7680043d38e212715e2a7b1ad29cb51" - integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== - dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" - integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== - -"@babel/helper-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" - integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/helper-hoist-variables@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" - integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-module-imports@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz#65e54ffceed6a268dc4ce11f0433b82cfff57852" - integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-module-transforms@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz#22346ed9df44ce84dee850d7433c5b73fab1fe4e" - integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== - dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - -"@babel/helper-simple-access@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz#1d6e04d468bba4fc963b4906f6dac6286cfedff1" - integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-split-export-declaration@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" - integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-string-parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" - integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== - -"@babel/helper-validator-identifier@^7.22.5", "@babel/helper-validator-identifier@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" - integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== - -"@babel/helper-validator-option@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz#59d8e81c40b7d9109ab7e74457393442177f460a" - integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== - -"@babel/helpers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.6.tgz#cd124245299e494bd4e00edda0e4ea3545c2c176" - integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/highlight@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" - integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== - dependencies: - "@babel/helper-validator-identifier" "^7.24.6" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" - integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== - -"@babel/runtime@^7.23.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e" - integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" - integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/traverse@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.6.tgz#0941ec50cdeaeacad0911eb67ae227a4f8424edc" - integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" - integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== - dependencies: - "@babel/helper-string-parser" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - to-fast-properties "^2.0.0" - -"@esbuild/aix-ppc64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.4.tgz#f83eb142df3ca7b49531c1ed680b81e484316508" - integrity sha512-Zrm+B33R4LWPLjDEVnEqt2+SLTATlru1q/xYKVn8oVTbiRBGmK2VIMoIYGJDGyftnGaC788IuzGFAlb7IQ0Y8A== - -"@esbuild/aix-ppc64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353" - integrity sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ== - -"@esbuild/android-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.4.tgz#dd328039daccd6033b2d1e536c054914bfc92287" - integrity sha512-fYFnz+ObClJ3dNiITySBUx+oNalYUT18/AryMxfovLkYWbutXsct3Wz2ZWAcGGppp+RVVX5FiXeLYGi97umisA== - -"@esbuild/android-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018" - integrity sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw== - -"@esbuild/android-arm@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.4.tgz#76767a989720a97b206ea14c52af6e4589e48b0d" - integrity sha512-E7H/yTd8kGQfY4z9t3nRPk/hrhaCajfA3YSQSBrst8B+3uTcgsi8N+ZWYCaeIDsiVs6m65JPCaQN/DxBRclF3A== - -"@esbuild/android-arm@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee" - integrity sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ== - -"@esbuild/android-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.4.tgz#14a8ae3c35702d882086efb5a8f8d7b0038d8d35" - integrity sha512-mDqmlge3hFbEPbCWxp4fM6hqq7aZfLEHZAKGP9viq9wMUBVQx202aDIfc3l+d2cKhUJM741VrCXEzRFhPDKH3Q== - -"@esbuild/android-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517" - integrity sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg== - -"@esbuild/darwin-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.4.tgz#7e735046005e4c12e9139e0bdd1fa6a754430d57" - integrity sha512-72eaIrDZDSiWqpmCzVaBD58c8ea8cw/U0fq/PPOTqE3c53D0xVMRt2ooIABZ6/wj99Y+h4ksT/+I+srCDLU9TA== - -"@esbuild/darwin-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16" - integrity sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q== - -"@esbuild/darwin-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.4.tgz#db623553547a5fe3502a63aa88306e9023178482" - integrity sha512-uBsuwRMehGmw1JC7Vecu/upOjTsMhgahmDkWhGLWxIgUn2x/Y4tIwUZngsmVb6XyPSTXJYS4YiASKPcm9Zitag== - -"@esbuild/darwin-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931" - integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw== - -"@esbuild/freebsd-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.4.tgz#91cbad647c079bf932086fbd4749d7f563df67b8" - integrity sha512-8JfuSC6YMSAEIZIWNL3GtdUT5NhUA/CMUCpZdDRolUXNAXEE/Vbpe6qlGLpfThtY5NwXq8Hi4nJy4YfPh+TwAg== - -"@esbuild/freebsd-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc" - integrity sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA== - -"@esbuild/freebsd-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.4.tgz#723299b9859ccbe5532fecbadba3ac33019ba8e8" - integrity sha512-8d9y9eQhxv4ef7JmXny7591P/PYsDFc4+STaxC1GBv0tMyCdyWfXu2jBuqRsyhY8uL2HU8uPyscgE2KxCY9imQ== - -"@esbuild/freebsd-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730" - integrity sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g== - -"@esbuild/linux-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.4.tgz#531743f861e1ef6e50b874d6c784cda37aa5e685" - integrity sha512-/GLD2orjNU50v9PcxNpYZi+y8dJ7e7/LhQukN3S4jNDXCKkyyiyAz9zDw3siZ7Eh1tRcnCHAo/WcqKMzmi4eMQ== - -"@esbuild/linux-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383" - integrity sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g== - -"@esbuild/linux-arm@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.4.tgz#1144b5654764960dd97d90ddf0893a9afc63ad91" - integrity sha512-2rqFFefpYmpMs+FWjkzSgXg5vViocqpq5a1PSRgT0AvSgxoXmGF17qfGAzKedg6wAwyM7UltrKVo9kxaJLMF/g== - -"@esbuild/linux-arm@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771" - integrity sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ== - -"@esbuild/linux-ia32@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.4.tgz#c81b6f2ed3308d3b75ccefb5ac63bc4cf3a9d2e9" - integrity sha512-pNftBl7m/tFG3t2m/tSjuYeWIffzwAZT9m08+9DPLizxVOsUl8DdFzn9HvJrTQwe3wvJnwTdl92AonY36w/25g== - -"@esbuild/linux-ia32@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333" - integrity sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ== - -"@esbuild/linux-loong64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.4.tgz#87b6af7cd0f2551653955fc2dc465b7f4464af0a" - integrity sha512-cSD2gzCK5LuVX+hszzXQzlWya6c7hilO71L9h4KHwqI4qeqZ57bAtkgcC2YioXjsbfAv4lPn3qe3b00Zt+jIfQ== - -"@esbuild/linux-loong64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac" - integrity sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw== - -"@esbuild/linux-mips64el@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.4.tgz#fec73cd39490a0c45d052bef03e011a0ad366c06" - integrity sha512-qtzAd3BJh7UdbiXCrg6npWLYU0YpufsV9XlufKhMhYMJGJCdfX/G6+PNd0+v877X1JG5VmjBLUiFB0o8EUSicA== - -"@esbuild/linux-mips64el@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6" - integrity sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q== - -"@esbuild/linux-ppc64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.4.tgz#ea3b5e13b0fc8666bd4c6f7ea58bd1830f3e6e78" - integrity sha512-yB8AYzOTaL0D5+2a4xEy7OVvbcypvDR05MsB/VVPVA7nL4hc5w5Dyd/ddnayStDgJE59fAgNEOdLhBxjfx5+dg== - -"@esbuild/linux-ppc64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96" - integrity sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw== - -"@esbuild/linux-riscv64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.4.tgz#80d406f653fc6b193edaeb55ac88d4ac22c8f155" - integrity sha512-Y5AgOuVzPjQdgU59ramLoqSSiXddu7F3F+LI5hYy/d1UHN7K5oLzYBDZe23QmQJ9PIVUXwOdKJ/jZahPdxzm9w== - -"@esbuild/linux-riscv64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7" - integrity sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA== - -"@esbuild/linux-s390x@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.4.tgz#9cbd26854b5b12cf22fb54c96cd1adffaf6ace6f" - integrity sha512-Iqc/l/FFwtt8FoTK9riYv9zQNms7B8u+vAI/rxKuN10HgQIXaPzKZc479lZ0x6+vKVQbu55GdpYpeNWzjOhgbA== - -"@esbuild/linux-s390x@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f" - integrity sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw== - -"@esbuild/linux-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.4.tgz#44dfe1c5cad855362c830c604dba97fbb16fc114" - integrity sha512-Td9jv782UMAFsuLZINfUpoF5mZIbAj+jv1YVtE58rFtfvoKRiKSkRGQfHTgKamLVT/fO7203bHa3wU122V/Bdg== - -"@esbuild/linux-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24" - integrity sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ== - -"@esbuild/netbsd-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.4.tgz#89b97d823e1cc4bf8c4e5dc8f76c8d6ceb1c87f3" - integrity sha512-Awn38oSXxsPMQxaV0Ipb7W/gxZtk5Tx3+W+rAPdZkyEhQ6968r9NvtkjhnhbEgWXYbgV+JEONJ6PcdBS+nlcpA== - -"@esbuild/netbsd-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653" - integrity sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA== - -"@esbuild/openbsd-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz#05c5a1faf67b9881834758c69f3e51b7dee015d7" - integrity sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q== - -"@esbuild/openbsd-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.4.tgz#080715bb4981c326364320d7b56835608e2bd98d" - integrity sha512-IsUmQeCY0aU374R82fxIPu6vkOybWIMc3hVGZ3ChRwL9hA1TwY+tS0lgFWV5+F1+1ssuvvXt3HFqe8roCip8Hg== - -"@esbuild/openbsd-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273" - integrity sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA== - -"@esbuild/sunos-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.4.tgz#8d838a8ac80e211536490108b72fb0091a811626" - integrity sha512-hsKhgZ4teLUaDA6FG/QIu2q0rI6I36tZVfM4DBZv3BG0mkMIdEnMbhc4xwLvLJSS22uWmaVkFkqWgIS0gPIm+A== - -"@esbuild/sunos-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403" - integrity sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA== - -"@esbuild/win32-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.4.tgz#94afb4c2ac89b0f09791606d6d93fdab322f81c8" - integrity sha512-UUfMgMoXPoA/bvGUNfUBFLCh0gt9dxZYIx9W4rfJr7+hKe5jxxHmfOK8YSH4qsHLLN4Ck8JZ+v7Q5fIm1huErg== - -"@esbuild/win32-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2" - integrity sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A== - -"@esbuild/win32-ia32@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.4.tgz#822085cd52f2f1dd90eabb59346ffa779c0bab83" - integrity sha512-yIxbspZb5kGCAHWm8dexALQ9en1IYDfErzjSEq1KzXFniHv019VT3mNtTK7t8qdy4TwT6QYHI9sEZabONHg+aw== - -"@esbuild/win32-ia32@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac" - integrity sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ== - -"@esbuild/win32-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.4.tgz#11ef0398f9abee161193461910a507ef0d4c0c32" - integrity sha512-sywLRD3UK/qRJt0oBwdpYLBibk7KiRfbswmWRDabuncQYSlf8aLEEUor/oP6KRz8KEG+HoiVLBhPRD5JWjS8Sg== - -"@esbuild/win32-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699" - integrity sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg== - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.1.tgz#361461e5cb3845d874e61731c11cfedd664d83a0" - integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== - -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@microsoft/tsdoc-config@0.16.2": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz#b786bb4ead00d54f53839a458ce626c8548d3adf" - integrity sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw== - dependencies: - "@microsoft/tsdoc" "0.14.2" - ajv "~6.12.6" - jju "~1.4.0" - resolve "~1.19.0" - -"@microsoft/tsdoc@0.14.2": - version "0.14.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" - integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== - -"@next/env@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.3.tgz#d6def29d1c763c0afb397343a15a82e7d92353a0" - integrity sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA== - -"@next/eslint-plugin-next@^14.1.1": - version "14.2.4" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.4.tgz#c7f965cb76f0b454e726ef0f69157c4fb4e28f53" - integrity sha512-svSFxW9f3xDaZA3idQmlFw7SusOuWTpDTAeBlO3AEPDltrraV+lqs7mAc6A27YdnpQVVIA3sODqUAAHdWhVWsA== - dependencies: - glob "10.3.10" - -"@next/swc-darwin-arm64@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz#db1a05eb88c0224089b815ad10ac128ec79c2cdb" - integrity sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A== - -"@next/swc-darwin-x64@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz#a3f8af05b5f9a52ac3082e66ac29e125ab1d7b9c" - integrity sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA== - -"@next/swc-linux-arm64-gnu@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz#4e63f43879285b52554bfd39e6e0cc78a9b27bbf" - integrity sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA== - -"@next/swc-linux-arm64-musl@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz#ebdaed26214448b1e6f2c3e8b3cd29bfba387990" - integrity sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw== - -"@next/swc-linux-x64-gnu@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz#19e3bcc137c3b582a1ab867106817e5c90a20593" - integrity sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w== - -"@next/swc-linux-x64-musl@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz#794a539b98e064169cf0ff7741b2a4fb16adec7d" - integrity sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ== - -"@next/swc-win32-arm64-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz#eda9fa0fbf1ff9113e87ac2668ee67ce9e5add5a" - integrity sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A== - -"@next/swc-win32-ia32-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz#7c1190e3f640ab16580c6bdbd7d0e766b9920457" - integrity sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw== - -"@next/swc-win32-x64-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz#2be4e39ee25bfbd85be78eea17c0e7751dc4323c" - integrity sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA== - -"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": - version "5.1.1-v1" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" - integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== - dependencies: - eslint-scope "5.1.1" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@pkgr/core@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" - integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== - -"@prisma/client@latest": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-6.2.1.tgz#3d7d0c8669bba490247e1ffff67b93a516bd789f" - integrity sha512-msKY2iRLISN8t5X0Tj7hU0UWet1u0KuxSPHWuf3IRkB4J95mCvGpyQBfQ6ufcmvKNOMQSq90O2iUmJEN2e5fiA== - -"@prisma/debug@6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.2.1.tgz#887719967c4942d125262e48f6c47c45d17c1f61" - integrity sha512-0KItvt39CmQxWkEw6oW+RQMD6RZ43SJWgEUnzxN8VC9ixMysa7MzZCZf22LCK5DSooiLNf8vM3LHZm/I/Ni7bQ== - -"@prisma/engines-version@6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69": - version "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69.tgz#b84ce3fab44bfa13a22669da02752330b61745b2" - integrity sha512-7tw1qs/9GWSX6qbZs4He09TOTg1ff3gYsB3ubaVNN0Pp1zLm9NC5C5MZShtkz7TyQjx7blhpknB7HwEhlG+PrQ== - -"@prisma/engines@6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-6.2.1.tgz#14ef56bb780f02871a728667161d997a14aedb69" - integrity sha512-lTBNLJBCxVT9iP5I7Mn6GlwqAxTpS5qMERrhebkUhtXpGVkBNd/jHnNJBZQW4kGDCKaQg/r2vlJYkzOHnAb7ZQ== - dependencies: - "@prisma/debug" "6.2.1" - "@prisma/engines-version" "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69" - "@prisma/fetch-engine" "6.2.1" - "@prisma/get-platform" "6.2.1" - -"@prisma/fetch-engine@6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-6.2.1.tgz#cd7eb7428a407105e0f3761dba536aefd41fc7f7" - integrity sha512-OO7O9d6Mrx2F9i+Gu1LW+DGXXyUFkP7OE5aj9iBfA/2jjDXEJjqa9X0ZmM9NZNo8Uo7ql6zKm6yjDcbAcRrw1A== - dependencies: - "@prisma/debug" "6.2.1" - "@prisma/engines-version" "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69" - "@prisma/get-platform" "6.2.1" - -"@prisma/get-platform@6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-6.2.1.tgz#34313cd0ee3587798ad33a7b57b6342dc8e66426" - integrity sha512-zp53yvroPl5m5/gXYLz7tGCNG33bhG+JYCm74ohxOq1pPnrL47VQYFfF3RbTZ7TzGWCrR3EtoiYMywUBw7UK6Q== - dependencies: - "@prisma/debug" "6.2.1" - -"@rollup/rollup-android-arm-eabi@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" - integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ== - -"@rollup/rollup-android-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203" - integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA== - -"@rollup/rollup-darwin-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096" - integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== - -"@rollup/rollup-darwin-x64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c" - integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA== - -"@rollup/rollup-linux-arm-gnueabihf@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8" - integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA== - -"@rollup/rollup-linux-arm-musleabihf@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549" - integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A== - -"@rollup/rollup-linux-arm64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577" - integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw== - -"@rollup/rollup-linux-arm64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c" - integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ== - -"@rollup/rollup-linux-powerpc64le-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf" - integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA== - -"@rollup/rollup-linux-riscv64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9" - integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg== - -"@rollup/rollup-linux-s390x-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec" - integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg== - -"@rollup/rollup-linux-x64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942" - integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== - -"@rollup/rollup-linux-x64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d" - integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg== - -"@rollup/rollup-win32-arm64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf" - integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA== - -"@rollup/rollup-win32-ia32-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54" - integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg== - -"@rollup/rollup-win32-x64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4" - integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== - -"@rushstack/eslint-patch@^1.3.3": - version "1.10.3" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz#391d528054f758f81e53210f1a1eebcf1a8b1d20" - integrity sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg== - -"@swc/counter@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" - integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== - -"@swc/helpers@0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" - integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== - dependencies: - "@swc/counter" "^0.1.3" - tslib "^2.4.0" - -"@types/estree@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -"@types/json-schema@^7.0.12", "@types/json-schema@^7.0.9": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/node@^20.11.24": - version "20.14.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.1.tgz#2434dbcb1f039e31f2c0e9969da93f52cf6348f3" - integrity sha512-T2MzSGEu+ysB/FkWfqmhV3PLyQlowdptmmgD20C6QxsS8Fmv5SjpZ1ayXaEC0S21/h5UJ9iA6W/5vSNU5l00OA== - dependencies: - undici-types "~5.26.4" - -"@types/normalize-package-data@^2.4.0": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== - -"@types/prop-types@*": - version "15.7.12" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" - integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== - -"@types/react-dom@^18.2.19": - version "18.3.0" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" - integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@^18.2.61": - version "18.3.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" - integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/semver@^7.3.12", "@types/semver@^7.5.0": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - -"@typescript-eslint/eslint-plugin@^6.5.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" - integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/type-utils" "6.21.0" - "@typescript-eslint/utils" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/eslint-plugin@^7.1.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz#f87a32e8972b8a60024f2f8f12205e7c8108bc41" - integrity sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q== - dependencies: - "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.12.0" - "@typescript-eslint/type-utils" "7.12.0" - "@typescript-eslint/utils" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - graphemer "^1.4.0" - ignore "^5.3.1" - natural-compare "^1.4.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/parser@^6.5.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" - integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== - dependencies: - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - -"@typescript-eslint/parser@^7.1.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.12.0.tgz#8761df3345528b35049353db80010b385719b1c3" - integrity sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ== - dependencies: - "@typescript-eslint/scope-manager" "7.12.0" - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/typescript-estree" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - -"@typescript-eslint/scope-manager@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" - integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - -"@typescript-eslint/scope-manager@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz#259c014362de72dd34f995efe6bd8dda486adf58" - integrity sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg== - dependencies: - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - -"@typescript-eslint/type-utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" - integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== - dependencies: - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/utils" "6.21.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/type-utils@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz#9dfaaa1972952f395ec5be4f5bbfc4d3cdc63908" - integrity sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA== - dependencies: - "@typescript-eslint/typescript-estree" "7.12.0" - "@typescript-eslint/utils" "7.12.0" - debug "^4.3.4" - ts-api-utils "^1.3.0" - -"@typescript-eslint/types@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== - -"@typescript-eslint/types@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" - integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== - -"@typescript-eslint/types@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.12.0.tgz#bf208f971a8da1e7524a5d9ae2b5f15192a37981" - integrity sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg== - -"@typescript-eslint/typescript-estree@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/typescript-estree@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" - integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/typescript-estree@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz#e6c1074f248b3db6573ab6a7c47a39c4cd498ff9" - integrity sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ== - dependencies: - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" - integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - semver "^7.5.4" - -"@typescript-eslint/utils@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.12.0.tgz#c6e58fd7f724cdccc848f71e388ad80cbdb95dd0" - integrity sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.12.0" - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/typescript-estree" "7.12.0" - -"@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.58.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== - dependencies: - "@typescript-eslint/types" "5.62.0" - eslint-visitor-keys "^3.3.0" - -"@typescript-eslint/visitor-keys@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" - integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== - dependencies: - "@typescript-eslint/types" "6.21.0" - eslint-visitor-keys "^3.4.1" - -"@typescript-eslint/visitor-keys@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz#c053b55a996679528beeedd8e565710ce1ae1ad3" - integrity sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ== - dependencies: - "@typescript-eslint/types" "7.12.0" - eslint-visitor-keys "^3.4.3" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@vercel/style-guide@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@vercel/style-guide/-/style-guide-5.2.0.tgz#8e09fb48065bc6133add67ff2bc7a219d228fb46" - integrity sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g== - dependencies: - "@babel/core" "^7.22.11" - "@babel/eslint-parser" "^7.22.11" - "@rushstack/eslint-patch" "^1.3.3" - "@typescript-eslint/eslint-plugin" "^6.5.0" - "@typescript-eslint/parser" "^6.5.0" - eslint-config-prettier "^9.0.0" - eslint-import-resolver-alias "^1.1.2" - eslint-import-resolver-typescript "^3.6.0" - eslint-plugin-eslint-comments "^3.2.0" - eslint-plugin-import "^2.28.1" - eslint-plugin-jest "^27.2.3" - eslint-plugin-jsx-a11y "^6.7.1" - eslint-plugin-playwright "^0.16.0" - eslint-plugin-react "^7.33.2" - eslint-plugin-react-hooks "^4.6.0" - eslint-plugin-testing-library "^6.0.1" - eslint-plugin-tsdoc "^0.2.17" - eslint-plugin-unicorn "^48.0.1" - prettier-plugin-packagejson "^2.4.5" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -ajv@^6.12.4, ajv@~6.12.6: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -any-promise@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-query@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" - -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== - dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" - -array-includes@^3.1.6, array-includes@^3.1.7, array-includes@^3.1.8: - version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.findlast@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" - integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.findlastindex@^1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" - integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.toreversed@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" - integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.tosorted@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" - integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.3" - es-errors "^1.3.0" - es-shim-unscopables "^1.0.2" - -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" - is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" - -ast-types-flow@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" - integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -axe-core@=4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" - integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== - -axobject-query@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" - integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== - dependencies: - dequal "^2.0.3" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3, braces@~3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.22.2: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== - dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -builtin-modules@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" - integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== - -bundle-require@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-4.2.1.tgz#4c450a5807381d20ade987bde8ac391544257919" - integrity sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA== - dependencies: - load-tsconfig "^0.2.3" - -busboy@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -cac@^6.7.12: - version "6.7.14" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001587: - version "1.0.30001627" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001627.tgz#8071c42d468e06ed2fb2c545efe79a663fd326ab" - integrity sha512-4zgNiB8nTyV/tHhwZrFs88ryjls/lHiqFhrxCW4qSTeuRByBVnPYpDInchOIySWknznucaf31Z4KYqjfbrecVw== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chokidar@^3.5.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -ci-info@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -clean-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7" - integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw== - dependencies: - escape-string-regexp "^1.0.5" - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -damerau-levenshtein@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" - integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== - -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.2.0, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -detect-indent@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25" - integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g== - -detect-newline@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-4.0.1.tgz#fcefdb5713e1fb8cb2839b8b6ee22e6716ab8f23" - integrity sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dotenv@16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -electron-to-chromium@^1.4.668: - version "1.4.789" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.789.tgz#fec941cb753ee139da562a5a8ff31fc3e828b411" - integrity sha512-0VbyiaXoT++Fi2vHGo2ThOeS6X3vgRCWrjPeO2FeIAWL6ItiSJ9BqlH8LfCXe3X1IdcG+S0iLoNaxQWhfZoGzQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -enhanced-resolve@^5.12.0: - version "5.17.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" - integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== - dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" - is-callable "^1.2.7" - is-data-view "^1.0.1" - is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" - object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" - string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.2.1, es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.19: - version "1.0.19" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" - integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.3" - es-errors "^1.3.0" - es-set-tostringtag "^2.0.3" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - iterator.prototype "^1.1.2" - safe-array-concat "^1.1.2" - -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== - dependencies: - es-errors "^1.3.0" - -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== - dependencies: - get-intrinsic "^1.2.4" - has-tostringtag "^1.0.2" - hasown "^2.0.1" - -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== - dependencies: - hasown "^2.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -esbuild@^0.21.4: - version "0.21.4" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.4.tgz#ceb501def8edb12a5bfd9c55f3a96db698edf022" - integrity sha512-sFMcNNrj+Q0ZDolrp5pDhH0nRPN9hLIM3fRPwgbLYJeSHHgnXSnbV3xYgSVuOeLWH9c73VwmEverVzupIv5xuA== - optionalDependencies: - "@esbuild/aix-ppc64" "0.21.4" - "@esbuild/android-arm" "0.21.4" - "@esbuild/android-arm64" "0.21.4" - "@esbuild/android-x64" "0.21.4" - "@esbuild/darwin-arm64" "0.21.4" - "@esbuild/darwin-x64" "0.21.4" - "@esbuild/freebsd-arm64" "0.21.4" - "@esbuild/freebsd-x64" "0.21.4" - "@esbuild/linux-arm" "0.21.4" - "@esbuild/linux-arm64" "0.21.4" - "@esbuild/linux-ia32" "0.21.4" - "@esbuild/linux-loong64" "0.21.4" - "@esbuild/linux-mips64el" "0.21.4" - "@esbuild/linux-ppc64" "0.21.4" - "@esbuild/linux-riscv64" "0.21.4" - "@esbuild/linux-s390x" "0.21.4" - "@esbuild/linux-x64" "0.21.4" - "@esbuild/netbsd-x64" "0.21.4" - "@esbuild/openbsd-x64" "0.21.4" - "@esbuild/sunos-x64" "0.21.4" - "@esbuild/win32-arm64" "0.21.4" - "@esbuild/win32-ia32" "0.21.4" - "@esbuild/win32-x64" "0.21.4" - -esbuild@~0.23.0: - version "0.23.1" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.23.1.tgz#40fdc3f9265ec0beae6f59824ade1bd3d3d2dab8" - integrity sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg== - optionalDependencies: - "@esbuild/aix-ppc64" "0.23.1" - "@esbuild/android-arm" "0.23.1" - "@esbuild/android-arm64" "0.23.1" - "@esbuild/android-x64" "0.23.1" - "@esbuild/darwin-arm64" "0.23.1" - "@esbuild/darwin-x64" "0.23.1" - "@esbuild/freebsd-arm64" "0.23.1" - "@esbuild/freebsd-x64" "0.23.1" - "@esbuild/linux-arm" "0.23.1" - "@esbuild/linux-arm64" "0.23.1" - "@esbuild/linux-ia32" "0.23.1" - "@esbuild/linux-loong64" "0.23.1" - "@esbuild/linux-mips64el" "0.23.1" - "@esbuild/linux-ppc64" "0.23.1" - "@esbuild/linux-riscv64" "0.23.1" - "@esbuild/linux-s390x" "0.23.1" - "@esbuild/linux-x64" "0.23.1" - "@esbuild/netbsd-x64" "0.23.1" - "@esbuild/openbsd-arm64" "0.23.1" - "@esbuild/openbsd-x64" "0.23.1" - "@esbuild/sunos-x64" "0.23.1" - "@esbuild/win32-arm64" "0.23.1" - "@esbuild/win32-ia32" "0.23.1" - "@esbuild/win32-x64" "0.23.1" - -escalade@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-prettier@^9.0.0, eslint-config-prettier@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" - integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== - -eslint-config-turbo@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-turbo/-/eslint-config-turbo-2.0.0.tgz#d3ebda365821aef48895f94c62985ddf400bf892" - integrity sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw== - dependencies: - eslint-plugin-turbo "2.0.0" - -eslint-import-resolver-alias@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz#297062890e31e4d6651eb5eba9534e1f6e68fc97" - integrity sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w== - -eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-import-resolver-typescript@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" - integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== - dependencies: - debug "^4.3.4" - enhanced-resolve "^5.12.0" - eslint-module-utils "^2.7.4" - fast-glob "^3.3.1" - get-tsconfig "^4.5.0" - is-core-module "^2.11.0" - is-glob "^4.0.3" - -eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" - integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== - dependencies: - debug "^3.2.7" - -eslint-plugin-eslint-comments@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa" - integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== - dependencies: - escape-string-regexp "^1.0.5" - ignore "^5.0.5" - -eslint-plugin-import@^2.28.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-plugin-jest@^27.2.3: - version "27.9.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz#7c98a33605e1d8b8442ace092b60e9919730000b" - integrity sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug== - dependencies: - "@typescript-eslint/utils" "^5.10.0" - -eslint-plugin-jsx-a11y@^6.7.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" - integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== - dependencies: - "@babel/runtime" "^7.23.2" - aria-query "^5.3.0" - array-includes "^3.1.7" - array.prototype.flatmap "^1.3.2" - ast-types-flow "^0.0.8" - axe-core "=4.7.0" - axobject-query "^3.2.1" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - es-iterator-helpers "^1.0.15" - hasown "^2.0.0" - jsx-ast-utils "^3.3.5" - language-tags "^1.0.9" - minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - -eslint-plugin-only-warn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-only-warn/-/eslint-plugin-only-warn-1.1.0.tgz#c6ddc37ddc4e72c121f07be565fcb7b6671fe78a" - integrity sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA== - -eslint-plugin-playwright@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-0.16.0.tgz#083c601a0704a7615509e63ac475bf7f0052d226" - integrity sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw== - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" - integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== - -eslint-plugin-react@^7.33.2: - version "7.34.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz#2780a1a35a51aca379d86d29b9a72adc6bfe6b66" - integrity sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw== - dependencies: - array-includes "^3.1.8" - array.prototype.findlast "^1.2.5" - array.prototype.flatmap "^1.3.2" - array.prototype.toreversed "^1.1.2" - array.prototype.tosorted "^1.1.3" - doctrine "^2.1.0" - es-iterator-helpers "^1.0.19" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.8" - object.fromentries "^2.0.8" - object.hasown "^1.1.4" - object.values "^1.2.0" - prop-types "^15.8.1" - resolve "^2.0.0-next.5" - semver "^6.3.1" - string.prototype.matchall "^4.0.11" - -eslint-plugin-testing-library@^6.0.1: - version "6.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.2.tgz#67e84ff891a2b3a8078ced0afa95ee6f343c00c1" - integrity sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ== - dependencies: - "@typescript-eslint/utils" "^5.58.0" - -eslint-plugin-tsdoc@^0.2.17: - version "0.2.17" - resolved "https://registry.yarnpkg.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz#27789495bbd8778abbf92db1707fec2ed3dfe281" - integrity sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA== - dependencies: - "@microsoft/tsdoc" "0.14.2" - "@microsoft/tsdoc-config" "0.16.2" - -eslint-plugin-turbo@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-turbo/-/eslint-plugin-turbo-2.0.0.tgz#938b95acdedd19318212d8ccab2537d2dd924bc4" - integrity sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw== - dependencies: - dotenv "16.0.3" - -eslint-plugin-unicorn@^48.0.1: - version "48.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz#a6573bc1687ae8db7121fdd8f92394b6549a6959" - integrity sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw== - dependencies: - "@babel/helper-validator-identifier" "^7.22.5" - "@eslint-community/eslint-utils" "^4.4.0" - ci-info "^3.8.0" - clean-regexp "^1.0.0" - esquery "^1.5.0" - indent-string "^4.0.0" - is-builtin-module "^3.2.1" - jsesc "^3.0.2" - lodash "^4.17.21" - pluralize "^8.0.0" - read-pkg-up "^7.0.1" - regexp-tree "^0.1.27" - regjsparser "^0.10.0" - semver "^7.5.4" - strip-indent "^3.0.0" - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esquery@^1.4.2, esquery@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - 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" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@2.3.3, fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - functions-have-names "^1.2.3" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-stdin@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575" - integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== - dependencies: - call-bind "^1.0.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - -get-tsconfig@^4.5.0, get-tsconfig@^4.7.5: - version "4.7.5" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" - integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== - dependencies: - resolve-pkg-maps "^1.0.0" - -git-hooks-list@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-3.1.0.tgz#386dc531dcc17474cf094743ff30987a3d3e70fc" - integrity sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - -glob@^10.3.10, glob@^10.3.7: - version "10.4.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.1.tgz#0cfb01ab6a6b438177bfe6a58e2576f6efe909c2" - integrity sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - path-scurry "^1.11.1" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globalthis@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" - integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== - dependencies: - define-properties "^1.2.1" - gopd "^1.0.1" - -globby@^11.0.3, globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^13.1.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" - integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.3.0" - ignore "^5.2.4" - merge2 "^1.4.1" - slash "^4.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.2.11, graceful-fs@^4.2.4: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ignore@^5.0.5, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" - -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-async-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" - integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== - dependencies: - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-builtin-module@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" - integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== - dependencies: - builtin-modules "^3.3.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.1.0, is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== - dependencies: - is-typed-array "^1.1.13" - -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== - dependencies: - call-bind "^1.0.2" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-map@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" - integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== - -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" - integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-set@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" - integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== - -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== - dependencies: - call-bind "^1.0.7" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -is-weakmap@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" - integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-weakset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" - integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -iterator.prototype@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" - integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== - dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" - -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jackspeak@^3.1.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.2.4.tgz#c00dc8bb4f93d8c1a62432b0b7d4de33f1d7ae97" - integrity sha512-uQPMuJfoph+FuccNkxAH9u0wBeuhyvpBPPfsupJ/G5RZ9kUD/sDFfzApzwMv20yd3nj40Ekizmga8iNTU4iiyQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jju@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" - integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== - -joycon@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" - integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" - integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: - version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" - integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - object.assign "^4.1.4" - object.values "^1.1.6" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -language-subtag-registry@^0.3.20: - version "0.3.23" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" - integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== - -language-tags@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" - integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== - dependencies: - language-subtag-registry "^0.3.20" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lilconfig@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" - integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -load-tsconfig@^0.2.3: - version "0.2.5" - resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" - integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^10.2.0: - version "10.2.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" - integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^9.0.1, minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mz@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nanoid@^3.3.6: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -next@^14.1.1: - version "14.2.3" - resolved "https://registry.yarnpkg.com/next/-/next-14.2.3.tgz#f117dd5d5f20c307e7b8e4f9c1c97d961008925d" - integrity sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A== - dependencies: - "@next/env" "14.2.3" - "@swc/helpers" "0.5.5" - busboy "1.6.0" - caniuse-lite "^1.0.30001579" - graceful-fs "^4.2.11" - postcss "8.4.31" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-darwin-arm64" "14.2.3" - "@next/swc-darwin-x64" "14.2.3" - "@next/swc-linux-arm64-gnu" "14.2.3" - "@next/swc-linux-arm64-musl" "14.2.3" - "@next/swc-linux-x64-gnu" "14.2.3" - "@next/swc-linux-x64-musl" "14.2.3" - "@next/swc-win32-arm64-msvc" "14.2.3" - "@next/swc-win32-ia32-msvc" "14.2.3" - "@next/swc-win32-x64-msvc" "14.2.3" - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-assign@^4.0.1, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4, object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.entries@^1.1.7, object.entries@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" - integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -object.fromentries@^2.0.7, object.fromentries@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" - integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.groupby@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" - integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - -object.hasown@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" - integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== - dependencies: - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" - integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.3: - version "0.9.4" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.5" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - 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" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6, path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.10.1, path-scurry@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0, picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pirates@^4.0.1: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pluralize@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" - integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== - -possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== - -postcss-load-config@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" - integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== - dependencies: - lilconfig "^3.0.0" - yaml "^2.3.4" - -postcss@8.4.31: - version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-plugin-packagejson@^2.4.5: - version "2.5.0" - resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.0.tgz#23d2cb8b1f7840702d35e3a5078e564ea0bc63e0" - integrity sha512-6XkH3rpin5QEQodBSVNg+rBo4r91g/1mCaRwS1YGdQJZ6jwqrg2UchBsIG9tpS1yK1kNBvOt84OILsX8uHzBGg== - dependencies: - sort-package-json "2.10.0" - synckit "0.9.0" - -prettier@^3.2.5: - version "3.3.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.0.tgz#d173ea0524a691d4c0b1181752f2b46724328cdf" - integrity sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g== - -prisma@latest: - version "6.2.1" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-6.2.1.tgz#457b210326d66d0e6f583cc6f9cd2819b984408f" - integrity sha512-hhyM0H13pQleQ+br4CkzGizS5I0oInoeTw3JfLw1BRZduBSQxPILlJLwi+46wZzj9Je7ndyQEMGw/n5cN2fknA== - dependencies: - "@prisma/engines" "6.2.1" - optionalDependencies: - fsevents "2.3.3" - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -react-dom@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" - integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.2" - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== - dependencies: - loose-envify "^1.1.0" - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reflect.getprototypeof@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" - integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.1" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regexp-tree@^0.1.27: - version "0.1.27" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" - integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== - -regexp.prototype.flags@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== - dependencies: - call-bind "^1.0.6" - define-properties "^1.2.1" - es-errors "^1.3.0" - set-function-name "^2.0.1" - -regjsparser@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.10.0.tgz#b1ed26051736b436f22fdec1c8f72635f9f44892" - integrity sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA== - dependencies: - jsesc "~0.5.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve@^1.10.0, resolve@^1.22.4: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.5: - version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" - integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@~1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rimraf@^5.0.5: - version "5.0.7" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74" - integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg== - dependencies: - glob "^10.3.7" - -rollup@^4.0.2: - version "4.18.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.18.0.tgz#497f60f0c5308e4602cf41136339fbf87d5f5dda" - integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg== - dependencies: - "@types/estree" "1.0.5" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.18.0" - "@rollup/rollup-android-arm64" "4.18.0" - "@rollup/rollup-darwin-arm64" "4.18.0" - "@rollup/rollup-darwin-x64" "4.18.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.18.0" - "@rollup/rollup-linux-arm-musleabihf" "4.18.0" - "@rollup/rollup-linux-arm64-gnu" "4.18.0" - "@rollup/rollup-linux-arm64-musl" "4.18.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.18.0" - "@rollup/rollup-linux-riscv64-gnu" "4.18.0" - "@rollup/rollup-linux-s390x-gnu" "4.18.0" - "@rollup/rollup-linux-x64-gnu" "4.18.0" - "@rollup/rollup-linux-x64-musl" "4.18.0" - "@rollup/rollup-win32-arm64-msvc" "4.18.0" - "@rollup/rollup-win32-ia32-msvc" "4.18.0" - "@rollup/rollup-win32-x64-msvc" "4.18.0" - fsevents "~2.3.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-regex "^1.1.4" - -scheduler@^0.23.2: - version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== - dependencies: - loose-envify "^1.1.0" - -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.7, semver@^7.5.4, semver@^7.6.0: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.1, set-function-name@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -sort-object-keys@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" - integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== - -sort-package-json@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.10.0.tgz#6be07424bf3b7db9fbb1bdd69e7945f301026d8a" - integrity sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g== - dependencies: - detect-indent "^7.0.1" - detect-newline "^4.0.0" - get-stdin "^9.0.0" - git-hooks-list "^3.0.0" - globby "^13.1.2" - is-plain-obj "^4.1.0" - semver "^7.6.0" - sort-object-keys "^1.1.3" - -source-map-js@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - -source-map@0.8.0-beta.0: - version "0.8.0-beta.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" - integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== - dependencies: - whatwg-url "^7.0.0" - -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" - integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.18" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: - name string-width-cjs - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.matchall@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" - integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - regexp.prototype.flags "^1.5.2" - set-function-name "^2.0.2" - side-channel "^1.0.6" - -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-object-atoms "^1.0.0" - -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string.prototype.trimstart@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" - integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -sucrase@^3.20.3: - version "3.35.0" - resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" - integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== - dependencies: - "@jridgewell/gen-mapping" "^0.3.2" - commander "^4.0.0" - glob "^10.3.10" - lines-and-columns "^1.1.6" - mz "^2.7.0" - pirates "^4.0.1" - ts-interface-checker "^0.1.9" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -synckit@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.0.tgz#5b33b458b3775e4466a5b377fba69c63572ae449" - integrity sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg== - dependencies: - "@pkgr/core" "^0.1.0" - tslib "^2.6.2" - -tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -thenify-all@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.1" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" - integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== - dependencies: - any-promise "^1.0.0" - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== - dependencies: - punycode "^2.1.0" - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - -ts-interface-checker@^0.1.9: - version "0.1.13" - resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" - integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== - -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.4.0, tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -tsup@^8.0.2: - version "8.1.0" - resolved "https://registry.yarnpkg.com/tsup/-/tsup-8.1.0.tgz#354ce9def1721f5029564382ea2a42dc67fbb489" - integrity sha512-UFdfCAXukax+U6KzeTNO2kAARHcWxmKsnvSPXUcfA1D+kU05XDccCrkffCQpFaWDsZfV0jMyTsxU39VfCp6EOg== - dependencies: - bundle-require "^4.0.0" - cac "^6.7.12" - chokidar "^3.5.1" - debug "^4.3.1" - esbuild "^0.21.4" - execa "^5.0.0" - globby "^11.0.3" - joycon "^3.0.1" - postcss-load-config "^4.0.1" - resolve-from "^5.0.0" - rollup "^4.0.2" - source-map "0.8.0-beta.0" - sucrase "^3.20.3" - tree-kill "^1.2.2" - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -tsx@4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.19.1.tgz#b7bffdf4b565813e4dea14b90872af279cd0090b" - integrity sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA== - dependencies: - esbuild "~0.23.0" - get-tsconfig "^4.7.5" - optionalDependencies: - fsevents "~2.3.3" - -turbo-darwin-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.0.3.tgz#52c5f79b4027dfd0184fb963da41bf989be4a00d" - integrity sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q== - -turbo-darwin-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.3.tgz#46fa54d0cd95782ac38015e3396d59cdbdeb1eb8" - integrity sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw== - -turbo-linux-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.0.3.tgz#17d6714b32381d474ef2ee5613343165f9bd75bc" - integrity sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q== - -turbo-linux-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.0.3.tgz#4f1bfe421dcecf2fb1164a1e223ba310d6e28b6f" - integrity sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A== - -turbo-windows-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.0.3.tgz#9d1b99aff361bcbf4e065029e9dfa6682a0c0b2d" - integrity sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w== - -turbo-windows-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.0.3.tgz#0e0641acda3325a4a3d28123ef21017a7aae8f38" - integrity sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg== - -turbo@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.0.3.tgz#789f64666d15dbc6fc85ce507a6c6888d70df88f" - integrity sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA== - optionalDependencies: - turbo-darwin-64 "2.0.3" - turbo-darwin-arm64 "2.0.3" - turbo-linux-64 "2.0.3" - turbo-linux-arm64 "2.0.3" - turbo-windows-64 "2.0.3" - turbo-windows-arm64 "2.0.3" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-typed-array "^1.1.13" - -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - -typescript@5.5.4: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -update-browserslist-db@^1.0.13: - version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" - integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== - dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -whatwg-url@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" - integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-builtin-type@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" - integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== - dependencies: - function.prototype.name "^1.1.5" - has-tostringtag "^1.0.0" - is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" - is-generator-function "^1.0.10" - is-regex "^1.1.4" - is-weakref "^1.0.2" - isarray "^2.0.5" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" - -which-collection@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" - integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== - dependencies: - is-map "^2.0.3" - is-set "^2.0.3" - is-weakmap "^2.0.2" - is-weakset "^2.0.3" - -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.2" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yaml@^2.3.4: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.3.tgz#0777516b8c7880bcaa0f426a5410e8d6b0be1f3d" - integrity sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/examples/with-react-native-web/README.md b/examples/with-react-native-web/README.md deleted file mode 100644 index b9dcd63e331d6..0000000000000 --- a/examples/with-react-native-web/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Turborepo react-native starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-react-native-web -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `native`: a [react-native](https://reactnative.dev/) app built with [expo](https://docs.expo.dev/) -- `web`: a [Next.js](https://nextjs.org/) app built with [react-native-web](https://necolas.github.io/react-native-web/) -- `@repo/ui`: a stub [react-native](https://reactnative.dev/) component library shared by both `web` and `native` applications -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [Expo](https://docs.expo.dev/) for native development -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/with-react-native-web/apps/native/README.md b/examples/with-react-native-web/apps/native/README.md deleted file mode 100644 index be1fea0359dad..0000000000000 --- a/examples/with-react-native-web/apps/native/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Native - -A [react-native](https://reactnative.dev/) app built using [expo](https://docs.expo.dev/) diff --git a/examples/with-react-native-web/apps/native/package.json b/examples/with-react-native-web/apps/native/package.json index ba3f9028e663a..1b056eb9e83de 100644 --- a/examples/with-react-native-web/apps/native/package.json +++ b/examples/with-react-native-web/apps/native/package.json @@ -1,29 +1,21 @@ { - "name": "native", - "version": "1.0.0", - "private": true, - "main": "index.js", - "scripts": { - "dev": "expo start --web", - "android": "expo start --android", - "ios": "expo start --ios", - "web": "expo start --web", - "eject": "expo eject" - }, - "dependencies": { - "@repo/ui": "*", - "expo": "^49.0.21", - "expo-status-bar": "~1.7.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-native": "0.73.1", - "react-native-web": "^0.19.10" - }, - "devDependencies": { - "@babel/core": "^7.23.7", - "@expo/webpack-config": "^19.0.0", - "@types/react": "^18.2.46", - "@types/react-native": "^0.73.0", - "typescript": "5.5.4" - } + "name": "native", + "main": "index.js", + "scripts": { + "android": "expo start --android", + "dev": "expo start --web", + "eject": "expo eject", + "ios": "expo start --ios", + "web": "expo start --web" + }, + "dependencies": { + "@repo/ui": "*", + "expo": "52.0.33", + "expo-status-bar": "2.0.1", + "react-native-web": "0.19.13" + }, + "devDependencies": { + "@expo/webpack-config": "19.0.1", + "@types/react-native": "0.73.0" + } } diff --git a/examples/with-react-native-web/apps/web/.eslintrc.json b/examples/with-react-native-web/apps/web/.eslintrc.json deleted file mode 100644 index bffb357a71225..0000000000000 --- a/examples/with-react-native-web/apps/web/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/examples/with-react-native-web/apps/web/README.md b/examples/with-react-native-web/apps/web/README.md deleted file mode 100644 index 3d7b63af7dc79..0000000000000 --- a/examples/with-react-native-web/apps/web/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-react-native-web/apps/web/package.json b/examples/with-react-native-web/apps/web/package.json index b8c157c0a0dab..d270fe2039af0 100644 --- a/examples/with-react-native-web/apps/web/package.json +++ b/examples/with-react-native-web/apps/web/package.json @@ -1,28 +1,18 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@repo/ui": "*", - "next": "^14.0.4", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-native-web": "^0.19.10" - }, - "devDependencies": { - "@repo/typescript-config": "*", - "@types/node": "^20.10.6", - "@types/react": "^18.2.46", - "@types/react-dom": "^18.2.18", - "babel-plugin-react-native-web": "^0.19.10", - "eslint": "^8.56.0", - "eslint-config-next": "14.0.4", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7", + "react-native-web": "0.19.13" + }, + "devDependencies": { + "@repo/typescript-config": "*", + "@types/node": "22.13.1", + "babel-plugin-react-native-web": "0.19.13" + } } diff --git a/examples/with-react-native-web/package.json b/examples/with-react-native-web/package.json index aaefa78588790..2254cccac0dde 100644 --- a/examples/with-react-native-web/package.json +++ b/examples/with-react-native-web/package.json @@ -1,22 +1,16 @@ { - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "dev": "turbo run dev", - "build": "turbo run build", - "clean": "turbo run clean && rm -rf node_modules", - "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\" --ignore-path .gitignore" - }, - "devDependencies": { - "prettier": "^3.1.1", - "turbo": "^2.0.3" - }, - "packageManager": "yarn@1.22.19", - "engines": { - "node": ">=18" - }, - "name": "with-react-native-web" + "name": "with-react-native-web", + "workspaces": [ + "apps/*", + "packages/*" + ], + "scripts": { + "build": "turbo run build", + "clean": "turbo run clean && rm -rf node_modules", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-react-native-web/packages/typescript-config/package.json b/examples/with-react-native-web/packages/typescript-config/package.json index bff20b7fa0c90..0b30de456c71c 100644 --- a/examples/with-react-native-web/packages/typescript-config/package.json +++ b/examples/with-react-native-web/packages/typescript-config/package.json @@ -1,8 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-react-native-web/packages/ui/src/button.tsx b/examples/with-react-native-web/packages/ui/Source/button.tsx similarity index 100% rename from examples/with-react-native-web/packages/ui/src/button.tsx rename to examples/with-react-native-web/packages/ui/Source/button.tsx diff --git a/examples/with-react-native-web/packages/ui/src/index.tsx b/examples/with-react-native-web/packages/ui/Source/index.tsx similarity index 100% rename from examples/with-react-native-web/packages/ui/src/index.tsx rename to examples/with-react-native-web/packages/ui/Source/index.tsx diff --git a/examples/with-react-native-web/packages/ui/package.json b/examples/with-react-native-web/packages/ui/package.json index 72be039242fa5..28b1483d6ea63 100644 --- a/examples/with-react-native-web/packages/ui/package.json +++ b/examples/with-react-native-web/packages/ui/package.json @@ -1,22 +1,16 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "scripts": { - "build": "tsup", - "dev": "tsup --watch", - "clean": "rm -rf dist" - }, - "devDependencies": { - "@repo/typescript-config": "*", - "@types/react": "^18.2.46", - "@types/react-native": "^0.73.0", - "tsup": "^8.0.1", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0", - "react-native": "^0.73.1" - } + "name": "@repo/ui", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsup", + "clean": "rm -rf dist", + "dev": "tsup --watch" + }, + "dependencies": {}, + "devDependencies": { + "@repo/typescript-config": "*", + "@types/react-native": "0.73.0", + "tsup": "8.3.6" + } } diff --git a/examples/with-react-native-web/yarn.lock b/examples/with-react-native-web/yarn.lock deleted file mode 100644 index 93abc1dc7b5cd..0000000000000 --- a/examples/with-react-native-web/yarn.lock +++ /dev/null @@ -1,11261 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@0no-co/graphql.web@^1.0.5": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@0no-co/graphql.web/-/graphql.web-1.0.7.tgz#c7a762c887b3482a79ffa68f63de5e96059a62e4" - integrity sha512-E3Qku4mTzdrlwVWGPxklDnME5ANrEGetvYw4i2GCRlppWXXE4QD66j7pwb8HelZwS6LnqEChhrSOGCXpbiu6MQ== - -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@7.10.4", "@babel/code-frame@~7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" - integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== - dependencies: - "@babel/highlight" "^7.24.6" - picocolors "^1.0.0" - -"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" - integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== - -"@babel/core@^7.13.16", "@babel/core@^7.20.0", "@babel/core@^7.20.2", "@babel/core@^7.23.7": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" - integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helpers" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/traverse" "^7.24.6" - "@babel/types" "^7.24.6" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.20.0", "@babel/generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" - integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== - dependencies: - "@babel/types" "^7.24.6" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz#517af93abc77924f9b2514c407bbef527fb8938d" - integrity sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz#19e9089ee87b0d0928012c83961a8deef4b0223f" - integrity sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz#4a51d681f7680043d38e212715e2a7b1ad29cb51" - integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== - dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz#c50b86fa1c4ca9b7a890dc21884f097b6c4b5286" - integrity sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-member-expression-to-functions" "^7.24.6" - "@babel/helper-optimise-call-expression" "^7.24.6" - "@babel/helper-replace-supers" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - semver "^6.3.1" - -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz#47d382dec0d49e74ca1b6f7f3b81f5968022a3c8" - integrity sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - regexpu-core "^5.3.1" - semver "^6.3.1" - -"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" - integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - -"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" - integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== - -"@babel/helper-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" - integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/helper-hoist-variables@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" - integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-member-expression-to-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz#86084f3e0e4e2169a134754df3870bc7784db71e" - integrity sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-module-imports@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz#65e54ffceed6a268dc4ce11f0433b82cfff57852" - integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-module-transforms@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz#22346ed9df44ce84dee850d7433c5b73fab1fe4e" - integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== - dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - -"@babel/helper-optimise-call-expression@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz#f7836e3ccca3dfa02f15d2bc8b794efe75a5256e" - integrity sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.6", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz#fa02a32410a15a6e8f8185bcbf608f10528d2a24" - integrity sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg== - -"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz#c96ceb9846e877d806ce82a1521230ea7e0fc354" - integrity sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-wrap-function" "^7.24.6" - -"@babel/helper-replace-supers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz#3ea87405a2986a49ab052d10e540fe036d747c71" - integrity sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ== - dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-member-expression-to-functions" "^7.24.6" - "@babel/helper-optimise-call-expression" "^7.24.6" - -"@babel/helper-simple-access@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz#1d6e04d468bba4fc963b4906f6dac6286cfedff1" - integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz#c47e9b33b7ea50d1073e125ebc26661717cb7040" - integrity sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-split-export-declaration@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" - integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-string-parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" - integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== - -"@babel/helper-validator-identifier@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" - integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== - -"@babel/helper-validator-option@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz#59d8e81c40b7d9109ab7e74457393442177f460a" - integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== - -"@babel/helper-wrap-function@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz#c27af1006e310683fdc76b668a0a1f6003e36217" - integrity sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ== - dependencies: - "@babel/helper-function-name" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/helpers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.6.tgz#cd124245299e494bd4e00edda0e4ea3545c2c176" - integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" - integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== - dependencies: - "@babel/helper-validator-identifier" "^7.24.6" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.13.16", "@babel/parser@^7.20.0", "@babel/parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" - integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== - -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz#283a74ef365b1e954cda6b2724c678a978215e88" - integrity sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw== - dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz#f9f5ae4d6fb72f5950262cb6f0b2482c3bc684ef" - integrity sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz#ab9be6edfffa127bd5ec4317c76c5af0f8fc7e6c" - integrity sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - "@babel/plugin-transform-optional-chaining" "^7.24.6" - -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz#0faf879249ec622d7f1c42eaebf7d11197401b2c" - integrity sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ== - dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-proposal-async-generator-functions@^7.0.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" - integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-decorators@^7.12.9": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.6.tgz#20e7ed41c24d3f6a2d94af7b44ddd06d1f8a71a3" - integrity sha512-8DjR0/DzlBhz2SVi9a19/N2U5+C3y3rseXuyoKL9SP8vnbewscj1eHZtL6kpEn4UCuUmqEo0mvqyDYRFoN2gpA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-decorators" "^7.24.6" - -"@babel/plugin-proposal-export-default-from@^7.0.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.24.6.tgz#ad7567fdf43cecc00f5314cedd1db60fdee99c6a" - integrity sha512-qPPDbYs9j5IArMFqYi85QxatHURSzRyskKpIbjrVoVglDuGdhu1s7UTCmXvP/qR2aHa3EdJ8X3iZvQAHjmdHUw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-export-default-from" "^7.24.6" - -"@babel/plugin-proposal-export-namespace-from@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" - integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.18.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz#dfbcaa8f7b4d37b51e8bfb46d94a5aea2bb89d83" - integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.12.13", "@babel/plugin-proposal-object-rest-spread@^7.20.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" - integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== - dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.20.7" - -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.20.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" - integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": - version "7.21.0-placeholder-for-preset-env.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" - integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-decorators@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.6.tgz#904d53fc158e8fb9f0754c76071e0ce38fe318eb" - integrity sha512-gInH8LEqBp+wkwTVihCd/qf+4s28g81FZyvlIbAurHk9eSiItEKG7E0uNK2UdpgsD79aJVAW3R3c85h0YJ0jsw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.24.6.tgz#aaf9ed2300ad6f942d0ee3742634e6e895b6011f" - integrity sha512-Nzl7kZ4tjOM2LJpejBMPwZs7OJfc26++2HsMQuSrw6gxpqXGtZZ3Rj4Zt4Qm7vulMZL2gHIGGc2stnlQnHQCqA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.6.tgz#1102a710771326b8e2f0c85ac2aecb6f52eb601e" - integrity sha512-gNkksSdV8RbsCoHF9sjVYrHfYACMl/8U32UfUhJ9+84/ASXw8dlx+eHyyF0m6ncQJ9IBSxfuCkB36GJqYdXTOA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-syntax-import-assertions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz#52521c1c1698fc2dd9cf88f7a4dd86d4d041b9e1" - integrity sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-syntax-import-attributes@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz#12aba325534129584672920274fefa4dc2d5f68e" - integrity sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-syntax-import-meta@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz#bcca2964150437f88f65e3679e3d68762287b9c8" - integrity sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz#769daf2982d60308bc83d8936eaecb7582463c87" - integrity sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" - integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz#93607d1ef5b81c70af174aff3532d57216367492" - integrity sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-async-generator-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz#fa4a9e5c3a7f60f697ba36587b6c41b04f507d84" - integrity sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA== - dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-remap-async-to-generator" "^7.24.6" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-transform-async-to-generator@^7.20.0", "@babel/plugin-transform-async-to-generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz#eb11434b11d73d8c0cf9f71a6f4f1e6ba441df35" - integrity sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g== - dependencies: - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-remap-async-to-generator" "^7.24.6" - -"@babel/plugin-transform-block-scoped-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz#975555b5bfa9870b1218da536d1528735f1f8c56" - integrity sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz#a03ec8a4591c2b43cf7798bc633e698293fda179" - integrity sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-class-properties@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz#d9f394e97e88ef905d5a1e5e7a16238621b7982e" - integrity sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-class-static-block@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz#f43f29286f6f0dca33d18fd5033b817d6c3fa816" - integrity sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz#0cc198c02720d4eeb091004843477659c6b37977" - integrity sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-replace-supers" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz#7a1765c01cdfe59c320d2d0f37a4dc4aecd14df1" - integrity sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/template" "^7.24.6" - -"@babel/plugin-transform-destructuring@^7.20.0", "@babel/plugin-transform-destructuring@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz#bdd1a6c90ffb2bfd13b6007b13316eeafc97cb53" - integrity sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-dotall-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz#5a6b3148ec5f4f274ff48cebea90565087cad126" - integrity sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-duplicate-keys@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz#2716301227cf7cd4fdadcbe4353ce191f8b3dc8a" - integrity sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-dynamic-import@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz#b477177761d56b15a4ba42a83be31cf72d757acf" - integrity sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-transform-exponentiation-operator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz#011e9e1a429f91b024af572530873ca571f9ef06" - integrity sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-export-namespace-from@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz#b64ded74d9afb3db5d47d93996c4df69f15ac97c" - integrity sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.6.tgz#dfd9d1c90e74335bc68d82f41ad9224960a4de84" - integrity sha512-1l8b24NoCpaQ13Vi6FtLG1nv6kNoi8PWvQb1AYO7GHZDpFfBYc3lbXArx1lP2KRt8b4pej1eWc/zrRmsQTfOdQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-flow" "^7.24.6" - -"@babel/plugin-transform-for-of@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz#7f31780bd0c582b546372c0c0da9d9d56731e0a2" - integrity sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - -"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz#60d1de3f6fd816a3e3bf9538578a64527e1b9c97" - integrity sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q== - dependencies: - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-json-strings@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz#a84639180ea1f9001bb5e6dc01921235ab05ad8b" - integrity sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz#7f44f2871d7a4456030b0540858046f0b7bc6b18" - integrity sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-logical-assignment-operators@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz#9cc7baa5629866566562c159dc1eae7569810f33" - integrity sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-transform-member-expression-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz#5d3681ca201ac6909419cc51ac082a6ba4c5c756" - integrity sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-modules-amd@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz#09aeac7acb7913496aaaafdc64f40683e0db7e41" - integrity sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ== - dependencies: - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz#1b8269902f25bd91ca6427230d4735ddd1e1283e" - integrity sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw== - dependencies: - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" - -"@babel/plugin-transform-modules-systemjs@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz#c54eb53fe16f9b82d320abd76762d0320e3f9393" - integrity sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w== - dependencies: - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - -"@babel/plugin-transform-modules-umd@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz#c4ef8b6d4da230b8dc87e81cd66986728952f89b" - integrity sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg== - dependencies: - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.0.0", "@babel/plugin-transform-named-capturing-groups-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz#352ee2861ab8705320029f80238cf26a92ba65d5" - integrity sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-new-target@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz#fc024294714705113720d5e3dc0f9ad7abdbc289" - integrity sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-nullish-coalescing-operator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz#12b83b3cdfd1cd2066350e36e4fb912ab194545e" - integrity sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-transform-numeric-separator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz#d9115669cc85aa91fbfb15f88f2226332cf4946a" - integrity sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-transform-object-rest-spread@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz#68d763f69955f9e599c405c6c876f5be46b47d8a" - integrity sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg== - dependencies: - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.24.6" - -"@babel/plugin-transform-object-super@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz#9cbe6f995bed343a7ab8daf0416dac057a9c3e27" - integrity sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-replace-supers" "^7.24.6" - -"@babel/plugin-transform-optional-catch-binding@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz#c81e90a971aad898e56f2b75a358e6c4855aeba3" - integrity sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-transform-optional-chaining@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz#3d636b3ed8b5a506f93e4d4675fc95754d7594f5" - integrity sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz#7aee86dfedd2fc0136fecbe6f7649fc02d86ab22" - integrity sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-private-methods@^7.22.5", "@babel/plugin-transform-private-methods@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz#258e1f859a52ff7b30ad556598224c192defcda7" - integrity sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-private-property-in-object@^7.22.11", "@babel/plugin-transform-private-property-in-object@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz#59ff09a099f62213112cf348e96b6b11957d1f28" - integrity sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-transform-property-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz#243c4faabe811c405e9443059a58e834bf95dfd1" - integrity sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-react-display-name@^7.0.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.6.tgz#2a10c732c2c87a8f06e4413fb4a14e76e6c67a99" - integrity sha512-/3iiEEHDsJuj9QU09gbyWGSUxDboFcD7Nj6dnHIlboWSodxXAoaY/zlNMHeYAC0WsERMqgO9a7UaM77CsYgWcg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-react-jsx-self@^7.0.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.6.tgz#4fa4870d594d6840d724d2006d0f98b19be6f502" - integrity sha512-FfZfHXtQ5jYPQsCRyLpOv2GeLIIJhs8aydpNh39vRDjhD411XcfWDni5i7OjP/Rs8GAtTn7sWFFELJSHqkIxYg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-react-jsx-source@^7.0.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.6.tgz#4e1503f24ca5fccb1fc7f20c57426899d5ce5c1f" - integrity sha512-BQTBCXmFRreU3oTUXcGKuPOfXAGb1liNY4AvvFKsOBAJ89RKcTsIrSsnMYkj59fNa66OFKnSa4AJZfy5Y4B9WA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.12.17": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.6.tgz#4ca3660ca663d20095455571615d6263986cdfe4" - integrity sha512-pCtPHhpRZHfwdA5G1Gpk5mIzMA99hv0R8S/Ket50Rw+S+8hkt3wBWqdqHaPw0CuUYxdshUgsPiLQ5fAs4ASMhw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-jsx" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/plugin-transform-regenerator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz#ed10cf0c13619365e15459f88d1b915ac57ffc24" - integrity sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - regenerator-transform "^0.15.2" - -"@babel/plugin-transform-reserved-words@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz#9eb16cbf339fcea0a46677716c775afb5ef14245" - integrity sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-runtime@^7.0.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.6.tgz#1e3256246004c3724b8e07c7cb25e35913c4e373" - integrity sha512-W3gQydMb0SY99y/2lV0Okx2xg/8KzmZLQsLaiCmwNRl1kKomz14VurEm+2TossUb+sRvBCnGe+wx8KtIgDtBbQ== - dependencies: - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.1" - babel-plugin-polyfill-regenerator "^0.6.1" - semver "^6.3.1" - -"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz#ef734ebccc428d2174c7bb36015d0800faf5381e" - integrity sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz#a56cecbd8617675531d1b79f5b755b7613aa0822" - integrity sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - -"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz#1a78127731fea87d954bed193840986a38f04327" - integrity sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-template-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz#aaf2ae157acd0e5c9265dba8ac0a439f8d2a6303" - integrity sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-typeof-symbol@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz#3d02da23ebcc8f1982ddcd1f2581cf3ee4e58762" - integrity sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-typescript@^7.24.6", "@babel/plugin-transform-typescript@^7.5.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.6.tgz#339c6127a783c32e28a5b591e6c666f899b57db0" - integrity sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-typescript" "^7.24.6" - -"@babel/plugin-transform-unicode-escapes@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz#c8ddca8fd5bacece837a4e27bd3b7ed64580d1a8" - integrity sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-unicode-property-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz#e66297d5d452db0b0be56515e3d0e10b7d33fb32" - integrity sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz#2001e7d87ed709eea145e0b65fb5f93c3c0e225b" - integrity sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/plugin-transform-unicode-sets-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz#f18b7292222aee85c155258ceb345a146a070a46" - integrity sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - -"@babel/preset-env@^7.20.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.6.tgz#a5a55bc70e5ff1ed7f872067e2a9d65ff917ad6f" - integrity sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg== - dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.6" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.6" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.6" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.6" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.24.6" - "@babel/plugin-syntax-import-attributes" "^7.24.6" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.24.6" - "@babel/plugin-transform-async-generator-functions" "^7.24.6" - "@babel/plugin-transform-async-to-generator" "^7.24.6" - "@babel/plugin-transform-block-scoped-functions" "^7.24.6" - "@babel/plugin-transform-block-scoping" "^7.24.6" - "@babel/plugin-transform-class-properties" "^7.24.6" - "@babel/plugin-transform-class-static-block" "^7.24.6" - "@babel/plugin-transform-classes" "^7.24.6" - "@babel/plugin-transform-computed-properties" "^7.24.6" - "@babel/plugin-transform-destructuring" "^7.24.6" - "@babel/plugin-transform-dotall-regex" "^7.24.6" - "@babel/plugin-transform-duplicate-keys" "^7.24.6" - "@babel/plugin-transform-dynamic-import" "^7.24.6" - "@babel/plugin-transform-exponentiation-operator" "^7.24.6" - "@babel/plugin-transform-export-namespace-from" "^7.24.6" - "@babel/plugin-transform-for-of" "^7.24.6" - "@babel/plugin-transform-function-name" "^7.24.6" - "@babel/plugin-transform-json-strings" "^7.24.6" - "@babel/plugin-transform-literals" "^7.24.6" - "@babel/plugin-transform-logical-assignment-operators" "^7.24.6" - "@babel/plugin-transform-member-expression-literals" "^7.24.6" - "@babel/plugin-transform-modules-amd" "^7.24.6" - "@babel/plugin-transform-modules-commonjs" "^7.24.6" - "@babel/plugin-transform-modules-systemjs" "^7.24.6" - "@babel/plugin-transform-modules-umd" "^7.24.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.6" - "@babel/plugin-transform-new-target" "^7.24.6" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.6" - "@babel/plugin-transform-numeric-separator" "^7.24.6" - "@babel/plugin-transform-object-rest-spread" "^7.24.6" - "@babel/plugin-transform-object-super" "^7.24.6" - "@babel/plugin-transform-optional-catch-binding" "^7.24.6" - "@babel/plugin-transform-optional-chaining" "^7.24.6" - "@babel/plugin-transform-parameters" "^7.24.6" - "@babel/plugin-transform-private-methods" "^7.24.6" - "@babel/plugin-transform-private-property-in-object" "^7.24.6" - "@babel/plugin-transform-property-literals" "^7.24.6" - "@babel/plugin-transform-regenerator" "^7.24.6" - "@babel/plugin-transform-reserved-words" "^7.24.6" - "@babel/plugin-transform-shorthand-properties" "^7.24.6" - "@babel/plugin-transform-spread" "^7.24.6" - "@babel/plugin-transform-sticky-regex" "^7.24.6" - "@babel/plugin-transform-template-literals" "^7.24.6" - "@babel/plugin-transform-typeof-symbol" "^7.24.6" - "@babel/plugin-transform-unicode-escapes" "^7.24.6" - "@babel/plugin-transform-unicode-property-regex" "^7.24.6" - "@babel/plugin-transform-unicode-regex" "^7.24.6" - "@babel/plugin-transform-unicode-sets-regex" "^7.24.6" - "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.4" - babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.31.0" - semver "^6.3.1" - -"@babel/preset-flow@^7.13.13": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.24.6.tgz#df09ee46558577bea49bc71d597604c03c9bf7a6" - integrity sha512-huoe0T1Qs9fQhMWbmqE/NHUeZbqmHDsN6n/jYvPcUUHfuKiPV32C9i8tDhMbQ1DEKTjbBP7Rjm3nSLwlB2X05g== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - "@babel/plugin-transform-flow-strip-types" "^7.24.6" - -"@babel/preset-modules@0.1.6-no-external-plugins": - version "0.1.6-no-external-plugins" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" - integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/preset-typescript@^7.13.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.6.tgz#27057470fb981c31338bdb897fc3d9aa0cb7dab2" - integrity sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w== - dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - "@babel/plugin-syntax-jsx" "^7.24.6" - "@babel/plugin-transform-modules-commonjs" "^7.24.6" - "@babel/plugin-transform-typescript" "^7.24.6" - -"@babel/register@^7.13.16": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.24.6.tgz#59e21dcc79e1d04eed5377633b0f88029a6bef9e" - integrity sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w== - dependencies: - clone-deep "^4.0.1" - find-cache-dir "^2.0.0" - make-dir "^2.1.0" - pirates "^4.0.6" - source-map-support "^0.5.16" - -"@babel/regjsgen@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" - integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== - -"@babel/runtime@^7.0.0", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.8.4": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e" - integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.0.0", "@babel/template@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" - integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/traverse@^7.20.0", "@babel/traverse@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.6.tgz#0941ec50cdeaeacad0911eb67ae227a4f8424edc" - integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.20.0", "@babel/types@^7.24.6", "@babel/types@^7.4.4": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" - integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== - dependencies: - "@babel/helper-string-parser" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - to-fast-properties "^2.0.0" - -"@esbuild/aix-ppc64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.4.tgz#f83eb142df3ca7b49531c1ed680b81e484316508" - integrity sha512-Zrm+B33R4LWPLjDEVnEqt2+SLTATlru1q/xYKVn8oVTbiRBGmK2VIMoIYGJDGyftnGaC788IuzGFAlb7IQ0Y8A== - -"@esbuild/android-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.4.tgz#dd328039daccd6033b2d1e536c054914bfc92287" - integrity sha512-fYFnz+ObClJ3dNiITySBUx+oNalYUT18/AryMxfovLkYWbutXsct3Wz2ZWAcGGppp+RVVX5FiXeLYGi97umisA== - -"@esbuild/android-arm@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.4.tgz#76767a989720a97b206ea14c52af6e4589e48b0d" - integrity sha512-E7H/yTd8kGQfY4z9t3nRPk/hrhaCajfA3YSQSBrst8B+3uTcgsi8N+ZWYCaeIDsiVs6m65JPCaQN/DxBRclF3A== - -"@esbuild/android-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.4.tgz#14a8ae3c35702d882086efb5a8f8d7b0038d8d35" - integrity sha512-mDqmlge3hFbEPbCWxp4fM6hqq7aZfLEHZAKGP9viq9wMUBVQx202aDIfc3l+d2cKhUJM741VrCXEzRFhPDKH3Q== - -"@esbuild/darwin-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.4.tgz#7e735046005e4c12e9139e0bdd1fa6a754430d57" - integrity sha512-72eaIrDZDSiWqpmCzVaBD58c8ea8cw/U0fq/PPOTqE3c53D0xVMRt2ooIABZ6/wj99Y+h4ksT/+I+srCDLU9TA== - -"@esbuild/darwin-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.4.tgz#db623553547a5fe3502a63aa88306e9023178482" - integrity sha512-uBsuwRMehGmw1JC7Vecu/upOjTsMhgahmDkWhGLWxIgUn2x/Y4tIwUZngsmVb6XyPSTXJYS4YiASKPcm9Zitag== - -"@esbuild/freebsd-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.4.tgz#91cbad647c079bf932086fbd4749d7f563df67b8" - integrity sha512-8JfuSC6YMSAEIZIWNL3GtdUT5NhUA/CMUCpZdDRolUXNAXEE/Vbpe6qlGLpfThtY5NwXq8Hi4nJy4YfPh+TwAg== - -"@esbuild/freebsd-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.4.tgz#723299b9859ccbe5532fecbadba3ac33019ba8e8" - integrity sha512-8d9y9eQhxv4ef7JmXny7591P/PYsDFc4+STaxC1GBv0tMyCdyWfXu2jBuqRsyhY8uL2HU8uPyscgE2KxCY9imQ== - -"@esbuild/linux-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.4.tgz#531743f861e1ef6e50b874d6c784cda37aa5e685" - integrity sha512-/GLD2orjNU50v9PcxNpYZi+y8dJ7e7/LhQukN3S4jNDXCKkyyiyAz9zDw3siZ7Eh1tRcnCHAo/WcqKMzmi4eMQ== - -"@esbuild/linux-arm@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.4.tgz#1144b5654764960dd97d90ddf0893a9afc63ad91" - integrity sha512-2rqFFefpYmpMs+FWjkzSgXg5vViocqpq5a1PSRgT0AvSgxoXmGF17qfGAzKedg6wAwyM7UltrKVo9kxaJLMF/g== - -"@esbuild/linux-ia32@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.4.tgz#c81b6f2ed3308d3b75ccefb5ac63bc4cf3a9d2e9" - integrity sha512-pNftBl7m/tFG3t2m/tSjuYeWIffzwAZT9m08+9DPLizxVOsUl8DdFzn9HvJrTQwe3wvJnwTdl92AonY36w/25g== - -"@esbuild/linux-loong64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.4.tgz#87b6af7cd0f2551653955fc2dc465b7f4464af0a" - integrity sha512-cSD2gzCK5LuVX+hszzXQzlWya6c7hilO71L9h4KHwqI4qeqZ57bAtkgcC2YioXjsbfAv4lPn3qe3b00Zt+jIfQ== - -"@esbuild/linux-mips64el@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.4.tgz#fec73cd39490a0c45d052bef03e011a0ad366c06" - integrity sha512-qtzAd3BJh7UdbiXCrg6npWLYU0YpufsV9XlufKhMhYMJGJCdfX/G6+PNd0+v877X1JG5VmjBLUiFB0o8EUSicA== - -"@esbuild/linux-ppc64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.4.tgz#ea3b5e13b0fc8666bd4c6f7ea58bd1830f3e6e78" - integrity sha512-yB8AYzOTaL0D5+2a4xEy7OVvbcypvDR05MsB/VVPVA7nL4hc5w5Dyd/ddnayStDgJE59fAgNEOdLhBxjfx5+dg== - -"@esbuild/linux-riscv64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.4.tgz#80d406f653fc6b193edaeb55ac88d4ac22c8f155" - integrity sha512-Y5AgOuVzPjQdgU59ramLoqSSiXddu7F3F+LI5hYy/d1UHN7K5oLzYBDZe23QmQJ9PIVUXwOdKJ/jZahPdxzm9w== - -"@esbuild/linux-s390x@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.4.tgz#9cbd26854b5b12cf22fb54c96cd1adffaf6ace6f" - integrity sha512-Iqc/l/FFwtt8FoTK9riYv9zQNms7B8u+vAI/rxKuN10HgQIXaPzKZc479lZ0x6+vKVQbu55GdpYpeNWzjOhgbA== - -"@esbuild/linux-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.4.tgz#44dfe1c5cad855362c830c604dba97fbb16fc114" - integrity sha512-Td9jv782UMAFsuLZINfUpoF5mZIbAj+jv1YVtE58rFtfvoKRiKSkRGQfHTgKamLVT/fO7203bHa3wU122V/Bdg== - -"@esbuild/netbsd-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.4.tgz#89b97d823e1cc4bf8c4e5dc8f76c8d6ceb1c87f3" - integrity sha512-Awn38oSXxsPMQxaV0Ipb7W/gxZtk5Tx3+W+rAPdZkyEhQ6968r9NvtkjhnhbEgWXYbgV+JEONJ6PcdBS+nlcpA== - -"@esbuild/openbsd-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.4.tgz#080715bb4981c326364320d7b56835608e2bd98d" - integrity sha512-IsUmQeCY0aU374R82fxIPu6vkOybWIMc3hVGZ3ChRwL9hA1TwY+tS0lgFWV5+F1+1ssuvvXt3HFqe8roCip8Hg== - -"@esbuild/sunos-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.4.tgz#8d838a8ac80e211536490108b72fb0091a811626" - integrity sha512-hsKhgZ4teLUaDA6FG/QIu2q0rI6I36tZVfM4DBZv3BG0mkMIdEnMbhc4xwLvLJSS22uWmaVkFkqWgIS0gPIm+A== - -"@esbuild/win32-arm64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.4.tgz#94afb4c2ac89b0f09791606d6d93fdab322f81c8" - integrity sha512-UUfMgMoXPoA/bvGUNfUBFLCh0gt9dxZYIx9W4rfJr7+hKe5jxxHmfOK8YSH4qsHLLN4Ck8JZ+v7Q5fIm1huErg== - -"@esbuild/win32-ia32@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.4.tgz#822085cd52f2f1dd90eabb59346ffa779c0bab83" - integrity sha512-yIxbspZb5kGCAHWm8dexALQ9en1IYDfErzjSEq1KzXFniHv019VT3mNtTK7t8qdy4TwT6QYHI9sEZabONHg+aw== - -"@esbuild/win32-x64@0.21.4": - version "0.21.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.4.tgz#11ef0398f9abee161193461910a507ef0d4c0c32" - integrity sha512-sywLRD3UK/qRJt0oBwdpYLBibk7KiRfbswmWRDabuncQYSlf8aLEEUor/oP6KRz8KEG+HoiVLBhPRD5JWjS8Sg== - -"@eslint-community/eslint-utils@^4.2.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.6.1": - version "4.10.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.1.tgz#361461e5cb3845d874e61731c11cfedd664d83a0" - integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== - -"@expo/bunyan@4.0.0", "@expo/bunyan@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@expo/bunyan/-/bunyan-4.0.0.tgz#be0c1de943c7987a9fbd309ea0b1acd605890c7b" - integrity sha512-Ydf4LidRB/EBI+YrB+cVLqIseiRfjUI/AeHBgjGMtq3GroraDu81OV7zqophRgupngoL3iS3JUMDMnxO7g39qA== - dependencies: - uuid "^8.0.0" - optionalDependencies: - mv "~2" - safe-json-stringify "~1" - -"@expo/cli@0.10.17": - version "0.10.17" - resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.10.17.tgz#e7641950f29a7e14deb5c28dc2056199e12cb855" - integrity sha512-HkHDvHPzq4M244hIerwnsw2IdjOo7RSsMYWGhc7ZY7DQWIMUC88b7f5+0RtD4JQfXQrgKS5Tvqm/5E6kAH0rIA== - dependencies: - "@babel/runtime" "^7.20.0" - "@expo/code-signing-certificates" "0.0.5" - "@expo/config" "~8.1.0" - "@expo/config-plugins" "~7.2.0" - "@expo/dev-server" "0.5.5" - "@expo/devcert" "^1.0.0" - "@expo/env" "0.0.5" - "@expo/json-file" "^8.2.37" - "@expo/metro-config" "~0.10.0" - "@expo/osascript" "^2.0.31" - "@expo/package-manager" "~1.1.0" - "@expo/plist" "^0.0.20" - "@expo/prebuild-config" "6.2.6" - "@expo/rudder-sdk-node" "1.1.1" - "@expo/spawn-async" "1.5.0" - "@expo/xcpretty" "^4.2.1" - "@urql/core" "2.3.6" - "@urql/exchange-retry" "0.3.0" - accepts "^1.3.8" - arg "4.1.0" - better-opn "~3.0.2" - bplist-parser "^0.3.1" - cacache "^15.3.0" - chalk "^4.0.0" - ci-info "^3.3.0" - debug "^4.3.4" - env-editor "^0.4.1" - form-data "^3.0.1" - freeport-async "2.0.0" - fs-extra "~8.1.0" - getenv "^1.0.0" - graphql "15.8.0" - graphql-tag "^2.10.1" - https-proxy-agent "^5.0.1" - internal-ip "4.3.0" - js-yaml "^3.13.1" - json-schema-deref-sync "^0.13.0" - md5-file "^3.2.3" - md5hex "^1.0.0" - minipass "3.1.6" - node-fetch "^2.6.7" - node-forge "^1.3.1" - npm-package-arg "^7.0.0" - ora "3.4.0" - pretty-bytes "5.6.0" - progress "2.0.3" - prompts "^2.3.2" - qrcode-terminal "0.11.0" - require-from-string "^2.0.2" - requireg "^0.2.2" - resolve-from "^5.0.0" - semver "^7.5.3" - send "^0.18.0" - slugify "^1.3.4" - structured-headers "^0.4.1" - tar "^6.0.5" - tempy "^0.7.1" - terminal-link "^2.1.1" - text-table "^0.2.0" - url-join "4.0.0" - wrap-ansi "^7.0.0" - ws "^8.12.1" - -"@expo/code-signing-certificates@0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@expo/code-signing-certificates/-/code-signing-certificates-0.0.5.tgz#a693ff684fb20c4725dade4b88a6a9f96b02496c" - integrity sha512-BNhXkY1bblxKZpltzAx98G2Egj9g1Q+JRcvR7E99DOj862FTCX+ZPsAUtPTr7aHxwtrL7+fL3r0JSmM9kBm+Bw== - dependencies: - node-forge "^1.2.1" - nullthrows "^1.1.1" - -"@expo/config-plugins@7.2.5", "@expo/config-plugins@~7.2.0": - version "7.2.5" - resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.2.5.tgz#b15f22878975fdc4ddcfa8cdc971937ddc4c0249" - integrity sha512-w+5ccu1IxBHgyQk9CPFKLZOk8yZQEyTjbJwOzESK1eR7QwosbcsLkN1c1WWUZYiCXwORu3UTwJYll4+X2xxJhQ== - dependencies: - "@expo/config-types" "^49.0.0-alpha.1" - "@expo/json-file" "~8.2.37" - "@expo/plist" "^0.0.20" - "@expo/sdk-runtime-versions" "^1.0.0" - "@react-native/normalize-color" "^2.0.0" - chalk "^4.1.2" - debug "^4.3.1" - find-up "~5.0.0" - getenv "^1.0.0" - glob "7.1.6" - resolve-from "^5.0.0" - semver "^7.5.3" - slash "^3.0.0" - xcode "^3.0.1" - xml2js "0.6.0" - -"@expo/config-types@^49.0.0-alpha.1": - version "49.0.0" - resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-49.0.0.tgz#15ffef715285c06703f6fb7ec0cda853f645cc09" - integrity sha512-8eyREVi+K2acnMBe/rTIu1dOfyR2+AMnTLHlut+YpMV9OZPdeKV0Bs9BxAewGqBA2slslbQ9N39IS2CuTKpXkA== - -"@expo/config@8.1.2", "@expo/config@~8.1.0": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@expo/config/-/config-8.1.2.tgz#7fff28b3acefe39702e9f3ce1c9fd896a52caa80" - integrity sha512-4e7hzPj50mQIlsrzOH6XZ36O094mPfPTIDIH4yv49bWNMc7GFLTofB/lcT+QyxiLaJuC0Wlk9yOLB8DIqmtwug== - dependencies: - "@babel/code-frame" "~7.10.4" - "@expo/config-plugins" "~7.2.0" - "@expo/config-types" "^49.0.0-alpha.1" - "@expo/json-file" "^8.2.37" - getenv "^1.0.0" - glob "7.1.6" - require-from-string "^2.0.2" - resolve-from "^5.0.0" - semver "7.5.3" - slugify "^1.3.4" - sucrase "^3.20.0" - -"@expo/dev-server@0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@expo/dev-server/-/dev-server-0.5.5.tgz#33f9065e0cf5f36ac61944a92d11390cc71b7035" - integrity sha512-t0fT8xH1exwYsH5hh7bAt85VF+gXxg24qrbny2rR/iKoPTWFCd2JNQV8pvfLg51hvrywQ3YCBuT3lU1w7aZxFA== - dependencies: - "@expo/bunyan" "4.0.0" - "@expo/metro-config" "~0.10.0" - "@expo/osascript" "2.0.33" - "@expo/spawn-async" "^1.5.0" - body-parser "^1.20.1" - chalk "^4.0.0" - connect "^3.7.0" - fs-extra "9.0.0" - is-docker "^2.0.0" - is-wsl "^2.1.1" - node-fetch "^2.6.0" - open "^8.3.0" - resolve-from "^5.0.0" - serialize-error "6.0.0" - temp-dir "^2.0.0" - -"@expo/devcert@^1.0.0": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@expo/devcert/-/devcert-1.1.2.tgz#a4923b8ea5b34fde31d6e006a40d0f594096a0ed" - integrity sha512-FyWghLu7rUaZEZSTLt/XNRukm0c9GFfwP0iFaswoDWpV6alvVg+zRAfCLdIVQEz1SVcQ3zo1hMZFDrnKGvkCuQ== - dependencies: - application-config-path "^0.1.0" - command-exists "^1.2.4" - debug "^3.1.0" - eol "^0.9.1" - get-port "^3.2.0" - glob "^7.1.2" - lodash "^4.17.21" - mkdirp "^0.5.1" - password-prompt "^1.0.4" - rimraf "^2.6.2" - sudo-prompt "^8.2.0" - tmp "^0.0.33" - tslib "^2.4.0" - -"@expo/env@0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@expo/env/-/env-0.0.5.tgz#86526ed5c966fc39b2644341f7a10f4b855e59b8" - integrity sha512-UXuKAqyXfhMQC3gP0OyjXmFX08Z1fkVWiGBN7bYzfoX8LHatjeHrDtI6w5nDvd8XPxPvmqaZoEDw1lW3+dz3oQ== - dependencies: - chalk "^4.0.0" - debug "^4.3.4" - dotenv "~16.0.3" - dotenv-expand "~10.0.0" - getenv "^1.0.0" - -"@expo/image-utils@0.3.22": - version "0.3.22" - resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.3.22.tgz#3a45fb2e268d20fcc761c87bca3aca7fd8e24260" - integrity sha512-uzq+RERAtkWypOFOLssFnXXqEqKjNj9eXN7e97d/EXUAojNcLDoXc0sL+F5B1I4qtlsnhX01kcpoIBBZD8wZNQ== - dependencies: - "@expo/spawn-async" "1.5.0" - chalk "^4.0.0" - fs-extra "9.0.0" - getenv "^1.0.0" - jimp-compact "0.16.1" - mime "^2.4.4" - node-fetch "^2.6.0" - parse-png "^2.1.0" - resolve-from "^5.0.0" - semver "7.3.2" - tempy "0.3.0" - -"@expo/image-utils@0.3.23": - version "0.3.23" - resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.3.23.tgz#f14fd7e1f5ff6f8e4911a41e27dd274470665c3f" - integrity sha512-nhUVvW0TrRE4jtWzHQl8TR4ox7kcmrc2I0itaeJGjxF5A54uk7avgA0wRt7jP1rdvqQo1Ke1lXyLYREdhN9tPw== - dependencies: - "@expo/spawn-async" "1.5.0" - chalk "^4.0.0" - fs-extra "9.0.0" - getenv "^1.0.0" - jimp-compact "0.16.1" - mime "^2.4.4" - node-fetch "^2.6.0" - parse-png "^2.1.0" - resolve-from "^5.0.0" - semver "7.3.2" - tempy "0.3.0" - -"@expo/json-file@^8.2.37": - version "8.3.3" - resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.3.3.tgz#7926e3592f76030ce63d6b1308ac8f5d4d9341f4" - integrity sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A== - dependencies: - "@babel/code-frame" "~7.10.4" - json5 "^2.2.2" - write-file-atomic "^2.3.0" - -"@expo/json-file@~8.2.37": - version "8.2.37" - resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049" - integrity sha512-YaH6rVg11JoTS2P6LsW7ybS2CULjf40AbnAHw2F1eDPuheprNjARZMnyHFPkKv7GuxCy+B9GPcbOKgc4cgA80Q== - dependencies: - "@babel/code-frame" "~7.10.4" - json5 "^2.2.2" - write-file-atomic "^2.3.0" - -"@expo/metro-config@~0.10.0": - version "0.10.7" - resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.10.7.tgz#d1b91baffcb7feb52fc7e2e122450bfc5d01e7c1" - integrity sha512-uACymEiyX0447hI4unt+2cemLQkTZXKvTev936NhtsgVnql45EP0V0pzmo/0H0WlHaAGXgvOBZJl8wFqcJ3CbQ== - dependencies: - "@expo/config" "~8.1.0" - "@expo/env" "0.0.5" - "@expo/json-file" "~8.2.37" - chalk "^4.1.0" - debug "^4.3.2" - find-yarn-workspace-root "~2.0.0" - getenv "^1.0.0" - jsc-safe-url "^0.2.4" - lightningcss "~1.19.0" - postcss "~8.4.21" - resolve-from "^5.0.0" - sucrase "^3.20.0" - -"@expo/osascript@2.0.33": - version "2.0.33" - resolved "https://registry.yarnpkg.com/@expo/osascript/-/osascript-2.0.33.tgz#e9dcc8da54466c11939074aa71a006024ea884b1" - integrity sha512-FQinlwHrTlJbntp8a7NAlCKedVXe06Va/0DSLXRO8lZVtgbEMrYYSUZWQNcOlNtc58c2elNph6z9dMOYwSo3JQ== - dependencies: - "@expo/spawn-async" "^1.5.0" - exec-async "^2.2.0" - -"@expo/osascript@^2.0.31": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@expo/osascript/-/osascript-2.1.3.tgz#912b74825cb83f3b958cad81034df9e19f1f2808" - integrity sha512-aOEkhPzDsaAfolSswObGiYW0Pf0ROfR9J2NBRLQACdQ6uJlyAMiPF45DVEVknAU9juKh0y8ZyvC9LXqLEJYohA== - dependencies: - "@expo/spawn-async" "^1.7.2" - exec-async "^2.2.0" - -"@expo/package-manager@~1.1.0": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@expo/package-manager/-/package-manager-1.1.2.tgz#e58c9bed4cbb829ebf2cbb80b8542600a6609bd1" - integrity sha512-JI9XzrxB0QVXysyuJ996FPCJGDCYRkbUvgG4QmMTTMFA1T+mv8YzazC3T9C1pHQUAAveVCre1+Pqv0nZXN24Xg== - dependencies: - "@expo/json-file" "^8.2.37" - "@expo/spawn-async" "^1.5.0" - ansi-regex "^5.0.0" - chalk "^4.0.0" - find-up "^5.0.0" - find-yarn-workspace-root "~2.0.0" - js-yaml "^3.13.1" - micromatch "^4.0.2" - npm-package-arg "^7.0.0" - split "^1.0.1" - sudo-prompt "9.1.1" - -"@expo/plist@^0.0.20": - version "0.0.20" - resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.20.tgz#a6b3124438031c02b762bad5a47b70584d3c0072" - integrity sha512-UXQ4LXCfTZ580LDHGJ5q62jSTwJFFJ1GqBu8duQMThiHKWbMJ+gajJh6rsB6EJ3aLUr9wcauxneL5LVRFxwBEA== - dependencies: - "@xmldom/xmldom" "~0.7.7" - base64-js "^1.2.3" - xmlbuilder "^14.0.0" - -"@expo/prebuild-config@6.2.6": - version "6.2.6" - resolved "https://registry.yarnpkg.com/@expo/prebuild-config/-/prebuild-config-6.2.6.tgz#c5b4f8adcba4be00c874d6b24a8267d45c555261" - integrity sha512-uFVvDAm9dPg9p1qpnr4CVnpo2hmkZIL5FQz+VlIdXXJpe7ySh/qTGHtKWY/lWUshQkAJ0nwbKGPztGWdABns/Q== - dependencies: - "@expo/config" "~8.1.0" - "@expo/config-plugins" "~7.2.0" - "@expo/config-types" "^49.0.0-alpha.1" - "@expo/image-utils" "0.3.22" - "@expo/json-file" "^8.2.37" - debug "^4.3.1" - fs-extra "^9.0.0" - resolve-from "^5.0.0" - semver "7.5.3" - xml2js "0.6.0" - -"@expo/rudder-sdk-node@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@expo/rudder-sdk-node/-/rudder-sdk-node-1.1.1.tgz#6aa575f346833eb6290282118766d4919c808c6a" - integrity sha512-uy/hS/awclDJ1S88w9UGpc6Nm9XnNUjzOAAib1A3PVAnGQIwebg8DpFqOthFBTlZxeuV/BKbZ5jmTbtNZkp1WQ== - dependencies: - "@expo/bunyan" "^4.0.0" - "@segment/loosely-validate-event" "^2.0.0" - fetch-retry "^4.1.1" - md5 "^2.2.1" - node-fetch "^2.6.1" - remove-trailing-slash "^0.1.0" - uuid "^8.3.2" - -"@expo/sdk-runtime-versions@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz#d7ebd21b19f1c6b0395e50d78da4416941c57f7c" - integrity sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ== - -"@expo/spawn-async@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.5.0.tgz#799827edd8c10ef07eb1a2ff9dcfe081d596a395" - integrity sha512-LB7jWkqrHo+5fJHNrLAFdimuSXQ2MQ4lA7SQW5bf/HbsXuV2VrT/jN/M8f/KoWt0uJMGN4k/j7Opx4AvOOxSew== - dependencies: - cross-spawn "^6.0.5" - -"@expo/spawn-async@^1.5.0", "@expo/spawn-async@^1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.7.2.tgz#fcfe66c3e387245e72154b1a7eae8cada6a47f58" - integrity sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew== - dependencies: - cross-spawn "^7.0.3" - -"@expo/vector-icons@^13.0.0": - version "13.0.0" - resolved "https://registry.yarnpkg.com/@expo/vector-icons/-/vector-icons-13.0.0.tgz#e2989b85e95a82bce216f88cf8fb583ab050ec95" - integrity sha512-TI+l71+5aSKnShYclFa14Kum+hQMZ86b95SH6tQUG3qZEmLTarvWpKwqtTwQKqvlJSJrpFiSFu3eCuZokY6zWA== - -"@expo/webpack-config@^19.0.0": - version "19.0.1" - resolved "https://registry.yarnpkg.com/@expo/webpack-config/-/webpack-config-19.0.1.tgz#c54db7ecbe37cc8ae3d8cc4a7d8184ab4633827e" - integrity sha512-5bSxXTUd/DCF44+1dSyU23YKLOOYCr9pMJ+C5Vw7PAi6v6OEyNp4uOVMk2x5DAEpXtvOsJCxvNZdmtY/IqmO/A== - dependencies: - "@babel/core" "^7.20.2" - babel-loader "^8.3.0" - chalk "^4.0.0" - clean-webpack-plugin "^4.0.0" - copy-webpack-plugin "^10.2.0" - css-loader "^6.5.1" - css-minimizer-webpack-plugin "^3.4.1" - expo-pwa "0.0.127" - find-up "^5.0.0" - find-yarn-workspace-root "~2.0.0" - fs-extra "^11.2.0" - getenv "^1.0.0" - html-webpack-plugin "^5.5.0" - is-wsl "^2.0.0" - mini-css-extract-plugin "^2.5.2" - node-html-parser "^5.2.0" - semver "~7.5.4" - source-map-loader "^3.0.1" - style-loader "^3.3.1" - terser-webpack-plugin "^5.3.0" - webpack "^5.64.4" - webpack-dev-server "^4.11.1" - webpack-manifest-plugin "^4.1.1" - -"@expo/xcpretty@^4.2.1": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@expo/xcpretty/-/xcpretty-4.3.1.tgz#e0a6a92d1e46ab5ac5e90d9a8e66ac1a2a2f5920" - integrity sha512-sqXgo1SCv+j4VtYEwl/bukuOIBrVgx6euIoCat3Iyx5oeoXwEA2USCoeL0IPubflMxncA2INkqJ/Wr3NGrSgzw== - dependencies: - "@babel/code-frame" "7.10.4" - chalk "^4.1.0" - find-up "^5.0.0" - js-yaml "^4.1.0" - -"@gar/promisify@^1.0.1": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" - integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== - -"@graphql-typed-document-node/core@^3.1.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" - integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== - -"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" - integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== - -"@hapi/topo@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@isaacs/ttlcache@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2" - integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== - -"@jest/create-cache-key-function@^29.6.3": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" - integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== - dependencies: - "@jest/types" "^29.6.3" - -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - -"@jest/types@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" - integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^15.0.0" - chalk "^4.0.0" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/source-map@^0.3.3": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" - integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@leichtgewicht/ip-codec@^2.0.1": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" - integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== - -"@next/env@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.3.tgz#d6def29d1c763c0afb397343a15a82e7d92353a0" - integrity sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA== - -"@next/eslint-plugin-next@14.0.4": - version "14.0.4" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.4.tgz#474fd88d92209270021186043513fbdc4203f5ec" - integrity sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ== - dependencies: - glob "7.1.7" - -"@next/swc-darwin-arm64@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz#db1a05eb88c0224089b815ad10ac128ec79c2cdb" - integrity sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A== - -"@next/swc-darwin-x64@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz#a3f8af05b5f9a52ac3082e66ac29e125ab1d7b9c" - integrity sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA== - -"@next/swc-linux-arm64-gnu@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz#4e63f43879285b52554bfd39e6e0cc78a9b27bbf" - integrity sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA== - -"@next/swc-linux-arm64-musl@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz#ebdaed26214448b1e6f2c3e8b3cd29bfba387990" - integrity sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw== - -"@next/swc-linux-x64-gnu@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz#19e3bcc137c3b582a1ab867106817e5c90a20593" - integrity sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w== - -"@next/swc-linux-x64-musl@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz#794a539b98e064169cf0ff7741b2a4fb16adec7d" - integrity sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ== - -"@next/swc-win32-arm64-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz#eda9fa0fbf1ff9113e87ac2668ee67ce9e5add5a" - integrity sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A== - -"@next/swc-win32-ia32-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz#7c1190e3f640ab16580c6bdbd7d0e766b9920457" - integrity sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw== - -"@next/swc-win32-x64-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz#2be4e39ee25bfbd85be78eea17c0e7751dc4323c" - integrity sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@npmcli/fs@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" - integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== - dependencies: - "@gar/promisify" "^1.0.1" - semver "^7.3.5" - -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@react-native-community/cli-clean@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.0.tgz#667b32daa58b4d11d5b5ab9eb0a2e216d500c90b" - integrity sha512-iAgLCOWYRGh9ukr+eVQnhkV/OqN3V2EGd/in33Ggn/Mj4uO6+oUncXFwB+yjlyaUNz6FfjudhIz09yYGSF+9sg== - dependencies: - "@react-native-community/cli-tools" "12.3.0" - chalk "^4.1.2" - execa "^5.0.0" - -"@react-native-community/cli-clean@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.6.tgz#e8a7910bebc97266fd5068649013a03958021fc4" - integrity sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig== - dependencies: - "@react-native-community/cli-tools" "12.3.6" - chalk "^4.1.2" - execa "^5.0.0" - -"@react-native-community/cli-clean@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-13.6.8.tgz#95ce964047f005152ac100394b6dcd5d2cc2a474" - integrity sha512-B1uxlm1N4BQuWFvBL3yRl3LVvydjswsdbTi7tMrHMtSxfRio1p9HjcmDzlzKco09Y+8qBGgakm3jcMZGLbhXQQ== - dependencies: - "@react-native-community/cli-tools" "13.6.8" - chalk "^4.1.2" - execa "^5.0.0" - fast-glob "^3.3.2" - -"@react-native-community/cli-config@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-12.3.0.tgz#255b4e5391878937a25888f452f50a968d053e3e" - integrity sha512-BrTn5ndFD9uOxO8kxBQ32EpbtOvAsQExGPI7SokdI4Zlve70FziLtTq91LTlTUgMq1InVZn/jJb3VIDk6BTInQ== - dependencies: - "@react-native-community/cli-tools" "12.3.0" - chalk "^4.1.2" - cosmiconfig "^5.1.0" - deepmerge "^4.3.0" - glob "^7.1.3" - joi "^17.2.1" - -"@react-native-community/cli-config@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-12.3.6.tgz#5f0be68270217908a739c32e3155a0e354773251" - integrity sha512-JGWSYQ9EAK6m2v0abXwFLEfsqJ1zkhzZ4CV261QZF9MoUNB6h57a274h1MLQR9mG6Tsh38wBUuNfEPUvS1vYew== - dependencies: - "@react-native-community/cli-tools" "12.3.6" - chalk "^4.1.2" - cosmiconfig "^5.1.0" - deepmerge "^4.3.0" - glob "^7.1.3" - joi "^17.2.1" - -"@react-native-community/cli-config@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-13.6.8.tgz#6829ea7cdc237776c300be06f84c222bf17cf4c5" - integrity sha512-RabCkIsWdP4Ex/sf1uSP9qxc30utm+0uIJAjrZkNQynm7T4Lyqn/kT3LKm4yM6M0Qk61YxGguiaXF4601vAduw== - dependencies: - "@react-native-community/cli-tools" "13.6.8" - chalk "^4.1.2" - cosmiconfig "^5.1.0" - deepmerge "^4.3.0" - fast-glob "^3.3.2" - joi "^17.2.1" - -"@react-native-community/cli-debugger-ui@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.0.tgz#75bbb2082a369b3559e0dffa8bfeebf2a9107e3e" - integrity sha512-w3b0iwjQlk47GhZWHaeTG8kKH09NCMUJO729xSdMBXE8rlbm4kHpKbxQY9qKb6NlfWSJN4noGY+FkNZS2rRwnQ== - dependencies: - serve-static "^1.13.1" - -"@react-native-community/cli-debugger-ui@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.6.tgz#418027a1ae76850079684d309a732eb378c7f690" - integrity sha512-SjUKKsx5FmcK9G6Pb6UBFT0s9JexVStK5WInmANw75Hm7YokVvHEgtprQDz2Uvy5znX5g2ujzrkIU//T15KQzA== - dependencies: - serve-static "^1.13.1" - -"@react-native-community/cli-debugger-ui@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-13.6.8.tgz#d52fccd4b3e0860d96d75ff5b0ebb128bdc93dfd" - integrity sha512-2cS+MX/Su6sVSjqpDftFOXbK7EuPg98xzsPkdPhkQnkZwvXqodK9CAMuDMbx3lBHHtrPrpMbBCpFmPN8iVOnlA== - dependencies: - serve-static "^1.13.1" - -"@react-native-community/cli-doctor@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-12.3.0.tgz#420eb4e80d482f16d431c4df33fbc203862508af" - integrity sha512-BPCwNNesoQMkKsxB08Ayy6URgGQ8Kndv6mMhIvJSNdST3J1+x3ehBHXzG9B9Vfi+DrTKRb8lmEl/b/7VkDlPkA== - dependencies: - "@react-native-community/cli-config" "12.3.0" - "@react-native-community/cli-platform-android" "12.3.0" - "@react-native-community/cli-platform-ios" "12.3.0" - "@react-native-community/cli-tools" "12.3.0" - chalk "^4.1.2" - command-exists "^1.2.8" - deepmerge "^4.3.0" - envinfo "^7.10.0" - execa "^5.0.0" - hermes-profile-transformer "^0.0.6" - ip "^1.1.5" - node-stream-zip "^1.9.1" - ora "^5.4.1" - semver "^7.5.2" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - yaml "^2.2.1" - -"@react-native-community/cli-doctor@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-12.3.6.tgz#f68b51bbc6554ff4837269d98e9e405044e6f1b9" - integrity sha512-fvBDv2lTthfw4WOQKkdTop2PlE9GtfrlNnpjB818MhcdEnPjfQw5YaTUcnNEGsvGomdCs1MVRMgYXXwPSN6OvQ== - dependencies: - "@react-native-community/cli-config" "12.3.6" - "@react-native-community/cli-platform-android" "12.3.6" - "@react-native-community/cli-platform-ios" "12.3.6" - "@react-native-community/cli-tools" "12.3.6" - chalk "^4.1.2" - command-exists "^1.2.8" - deepmerge "^4.3.0" - envinfo "^7.10.0" - execa "^5.0.0" - hermes-profile-transformer "^0.0.6" - node-stream-zip "^1.9.1" - ora "^5.4.1" - semver "^7.5.2" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - yaml "^2.2.1" - -"@react-native-community/cli-doctor@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-13.6.8.tgz#05f696d94e975e4dcf7f9a1fde32fb43e4bb8a5f" - integrity sha512-/3Vdy9J3hyiu0y3nd/CU3kBqPlTRxnLXg7V6jrA1jbTOlZAMyV9imEkrqEaGK0SMOyMhh9Pipf98Ozhk0Nl4QA== - dependencies: - "@react-native-community/cli-config" "13.6.8" - "@react-native-community/cli-platform-android" "13.6.8" - "@react-native-community/cli-platform-apple" "13.6.8" - "@react-native-community/cli-platform-ios" "13.6.8" - "@react-native-community/cli-tools" "13.6.8" - chalk "^4.1.2" - command-exists "^1.2.8" - deepmerge "^4.3.0" - envinfo "^7.10.0" - execa "^5.0.0" - hermes-profile-transformer "^0.0.6" - node-stream-zip "^1.9.1" - ora "^5.4.1" - semver "^7.5.2" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - yaml "^2.2.1" - -"@react-native-community/cli-hermes@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-12.3.0.tgz#c302acbfb07e1f4e73e76e3150c32f0e4f54e9ed" - integrity sha512-G6FxpeZBO4AimKZwtWR3dpXRqTvsmEqlIkkxgwthdzn3LbVjDVIXKpVYU9PkR5cnT+KuAUxO0WwthrJ6Nmrrlg== - dependencies: - "@react-native-community/cli-platform-android" "12.3.0" - "@react-native-community/cli-tools" "12.3.0" - chalk "^4.1.2" - hermes-profile-transformer "^0.0.6" - ip "^1.1.5" - -"@react-native-community/cli-hermes@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-12.3.6.tgz#5ac2c9ee26c69e1ce6b5047ba0f399984a6dea16" - integrity sha512-sNGwfOCl8OAIjWCkwuLpP8NZbuO0dhDI/2W7NeOGDzIBsf4/c4MptTrULWtGIH9okVPLSPX0NnRyGQ+mSwWyuQ== - dependencies: - "@react-native-community/cli-platform-android" "12.3.6" - "@react-native-community/cli-tools" "12.3.6" - chalk "^4.1.2" - hermes-profile-transformer "^0.0.6" - -"@react-native-community/cli-hermes@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-13.6.8.tgz#85f10f663bc79f299146e749c48c06ebc4da9e29" - integrity sha512-lZi/OBFuZUj5cLK94oEgtrtmxGoqeYVRcnHXl/R5c4put9PDl+qH2bEMlGZkFiw57ae3UZKr3TMk+1s4jh3FYQ== - dependencies: - "@react-native-community/cli-platform-android" "13.6.8" - "@react-native-community/cli-tools" "13.6.8" - chalk "^4.1.2" - hermes-profile-transformer "^0.0.6" - -"@react-native-community/cli-platform-android@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.0.tgz#eafa5fb12ebc25f716aea18cd55039c19fbedca6" - integrity sha512-VU1NZw63+GLU2TnyQ919bEMThpHQ/oMFju9MCfrd3pyPJz4Sn+vc3NfnTDUVA5Z5yfLijFOkHIHr4vo/C9bjnw== - dependencies: - "@react-native-community/cli-tools" "12.3.0" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.2.4" - glob "^7.1.3" - logkitty "^0.7.1" - -"@react-native-community/cli-platform-android@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.6.tgz#e1103692c659ff0b72ee6f00b7c72578db7376ec" - integrity sha512-DeDDAB8lHpuGIAPXeeD9Qu2+/wDTFPo99c8uSW49L0hkmZJixzvvvffbGQAYk32H0TmaI7rzvzH+qzu7z3891g== - dependencies: - "@react-native-community/cli-tools" "12.3.6" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.2.4" - glob "^7.1.3" - logkitty "^0.7.1" - -"@react-native-community/cli-platform-android@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-13.6.8.tgz#a3672512a9b844f93d6050537c59dd58e1b12f17" - integrity sha512-vWrqeLRRTwp2kO33nbrAgbYn8HR2c2CpIfyVJY9Ckk7HGUSwDyxdcSu7YBvt2ShdfLZH0HctWFNXsgGrfg6BDw== - dependencies: - "@react-native-community/cli-tools" "13.6.8" - chalk "^4.1.2" - execa "^5.0.0" - fast-glob "^3.3.2" - fast-xml-parser "^4.2.4" - logkitty "^0.7.1" - -"@react-native-community/cli-platform-apple@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.8.tgz#4d46a2d6678a7b3264768f97393f082ed9afb264" - integrity sha512-1JPohnlXPqU44zns3ALEzIbH2cKRw6JtEDJERgLuEUbs2r2NeJgqDbKyZ7fTTO8o+pegDnn6+Rr7qGVVOuUzzg== - dependencies: - "@react-native-community/cli-tools" "13.6.8" - chalk "^4.1.2" - execa "^5.0.0" - fast-glob "^3.3.2" - fast-xml-parser "^4.0.12" - ora "^5.4.1" - -"@react-native-community/cli-platform-ios@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.0.tgz#42a9185bb51f35a7eb9c5818b2f0072846945ef5" - integrity sha512-H95Sgt3wT7L8V75V0syFJDtv4YgqK5zbu69ko4yrXGv8dv2EBi6qZP0VMmkqXDamoPm9/U7tDTdbcf26ctnLfg== - dependencies: - "@react-native-community/cli-tools" "12.3.0" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.0.12" - glob "^7.1.3" - ora "^5.4.1" - -"@react-native-community/cli-platform-ios@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.6.tgz#e7decb5ee764f5fdc7a6ad1ba5e15de8929d54a5" - integrity sha512-3eZ0jMCkKUO58wzPWlvAPRqezVKm9EPZyaPyHbRPWU8qw7JqkvnRlWIaYDGpjCJgVW4k2hKsEursLtYKb188tg== - dependencies: - "@react-native-community/cli-tools" "12.3.6" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.0.12" - glob "^7.1.3" - ora "^5.4.1" - -"@react-native-community/cli-platform-ios@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-13.6.8.tgz#2de1bd8529825781108c1cbba4f5b25cb062581c" - integrity sha512-/IIcIRM8qaoD7iZqsvtf6Qq1AwtChWYfB9sTn3mTiolZ5Zd5bXH37g+6liPfAICRkj2Ptq3iXmjrDVUQAxrOXw== - dependencies: - "@react-native-community/cli-platform-apple" "13.6.8" - -"@react-native-community/cli-plugin-metro@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.0.tgz#b4ea8da691d294aee98ccfcd1162bcd958cae834" - integrity sha512-tYNHIYnNmxrBcsqbE2dAnLMzlKI3Cp1p1xUgTrNaOMsGPDN1epzNfa34n6Nps3iwKElSL7Js91CzYNqgTalucA== - -"@react-native-community/cli-plugin-metro@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.6.tgz#ae62de18e998478db60a3fe10dc746162c272dbd" - integrity sha512-3jxSBQt4fkS+KtHCPSyB5auIT+KKIrPCv9Dk14FbvOaEh9erUWEm/5PZWmtboW1z7CYeNbFMeXm9fM2xwtVOpg== - -"@react-native-community/cli-server-api@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-12.3.0.tgz#0460472d44c121d1db8a98ad1df811200c074fb3" - integrity sha512-Rode8NrdyByC+lBKHHn+/W8Zu0c+DajJvLmOWbe2WY/ECvnwcd9MHHbu92hlT2EQaJ9LbLhGrSbQE3cQy9EOCw== - dependencies: - "@react-native-community/cli-debugger-ui" "12.3.0" - "@react-native-community/cli-tools" "12.3.0" - compression "^1.7.1" - connect "^3.6.5" - errorhandler "^1.5.1" - nocache "^3.0.1" - pretty-format "^26.6.2" - serve-static "^1.13.1" - ws "^7.5.1" - -"@react-native-community/cli-server-api@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-12.3.6.tgz#cd78122954a02d22c7821c365938635b51ddd1bd" - integrity sha512-80NIMzo8b2W+PL0Jd7NjiJW9mgaT8Y8wsIT/lh6mAvYH7mK0ecDJUYUTAAv79Tbo1iCGPAr3T295DlVtS8s4yQ== - dependencies: - "@react-native-community/cli-debugger-ui" "12.3.6" - "@react-native-community/cli-tools" "12.3.6" - compression "^1.7.1" - connect "^3.6.5" - errorhandler "^1.5.1" - nocache "^3.0.1" - pretty-format "^26.6.2" - serve-static "^1.13.1" - ws "^7.5.1" - -"@react-native-community/cli-server-api@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-13.6.8.tgz#fc654a2990a5f0b6f0b67ef04b25f699bee63f63" - integrity sha512-Lx664oWTzpVfbKUTy+3GIX7e+Mt5Zn+zdkM4ehllNdik/lbB3tM9Nrg8PSvOfI+tTXs2w55+nIydLfH+0FqJVg== - dependencies: - "@react-native-community/cli-debugger-ui" "13.6.8" - "@react-native-community/cli-tools" "13.6.8" - compression "^1.7.1" - connect "^3.6.5" - errorhandler "^1.5.1" - nocache "^3.0.1" - pretty-format "^26.6.2" - serve-static "^1.13.1" - ws "^6.2.2" - -"@react-native-community/cli-tools@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-12.3.0.tgz#d459a116e1a95034d3c9a6385069c9e2049fb2a6" - integrity sha512-2GafnCr8D88VdClwnm9KZfkEb+lzVoFdr/7ybqhdeYM0Vnt/tr2N+fM1EQzwI1DpzXiBzTYemw8GjRq+Utcz2Q== - dependencies: - appdirsjs "^1.2.4" - chalk "^4.1.2" - find-up "^5.0.0" - mime "^2.4.1" - node-fetch "^2.6.0" - open "^6.2.0" - ora "^5.4.1" - semver "^7.5.2" - shell-quote "^1.7.3" - sudo-prompt "^9.0.0" - -"@react-native-community/cli-tools@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-12.3.6.tgz#c39965982347635dfaf1daa7b3c0133b3bd45e64" - integrity sha512-FPEvZn19UTMMXUp/piwKZSh8cMEfO8G3KDtOwo53O347GTcwNrKjgZGtLSPELBX2gr+YlzEft3CoRv2Qmo83fQ== - dependencies: - appdirsjs "^1.2.4" - chalk "^4.1.2" - find-up "^5.0.0" - mime "^2.4.1" - node-fetch "^2.6.0" - open "^6.2.0" - ora "^5.4.1" - semver "^7.5.2" - shell-quote "^1.7.3" - sudo-prompt "^9.0.0" - -"@react-native-community/cli-tools@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-13.6.8.tgz#65a9f49ce66f0e639d855e745c8dfa7ae7b6c142" - integrity sha512-1MYlae9EkbjC7DBYOGMH5xF9yDoeNYUKgEdDjL6WAUBoF2gtwiZPM6igLKi/+dhb5sCtC7fiLrLi0Oevdf+RmQ== - dependencies: - appdirsjs "^1.2.4" - chalk "^4.1.2" - execa "^5.0.0" - find-up "^5.0.0" - mime "^2.4.1" - node-fetch "^2.6.0" - open "^6.2.0" - ora "^5.4.1" - semver "^7.5.2" - shell-quote "^1.7.3" - sudo-prompt "^9.0.0" - -"@react-native-community/cli-types@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-12.3.0.tgz#2d21a1f93aefbdb34a04311d68097aef0388704f" - integrity sha512-MgOkmrXH4zsGxhte4YqKL7d+N8ZNEd3w1wo56MZlhu5WabwCJh87wYpU5T8vyfujFLYOFuFK5jjlcbs8F4/WDw== - dependencies: - joi "^17.2.1" - -"@react-native-community/cli-types@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-12.3.6.tgz#239de348800fe1ffba3eb1fe0edbeb9306981e57" - integrity sha512-xPqTgcUtZowQ8WKOkI9TLGBwH2bGggOC4d2FFaIRST3gTcjrEeGRNeR5aXCzJFIgItIft8sd7p2oKEdy90+01Q== - dependencies: - joi "^17.2.1" - -"@react-native-community/cli-types@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-13.6.8.tgz#1c357d3290a48232e3e639d48e43e31e422ce436" - integrity sha512-C4mVByy0i+/NPuPhdMLBR7ubEVkjVS1VwoQu/BoG1crJFNE+167QXAzH01eFbXndsjZaMWmD4Gerx7TYc6lHfA== - dependencies: - joi "^17.2.1" - -"@react-native-community/cli@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-12.3.0.tgz#c89aacc3973943bf24002255d7d0859b511d88a1" - integrity sha512-XeQohi2E+S2+MMSz97QcEZ/bWpi8sfKiQg35XuYeJkc32Til2g0b97jRpn0/+fV0BInHoG1CQYWwHA7opMsrHg== - dependencies: - "@react-native-community/cli-clean" "12.3.0" - "@react-native-community/cli-config" "12.3.0" - "@react-native-community/cli-debugger-ui" "12.3.0" - "@react-native-community/cli-doctor" "12.3.0" - "@react-native-community/cli-hermes" "12.3.0" - "@react-native-community/cli-plugin-metro" "12.3.0" - "@react-native-community/cli-server-api" "12.3.0" - "@react-native-community/cli-tools" "12.3.0" - "@react-native-community/cli-types" "12.3.0" - chalk "^4.1.2" - commander "^9.4.1" - deepmerge "^4.3.0" - execa "^5.0.0" - find-up "^4.1.0" - fs-extra "^8.1.0" - graceful-fs "^4.1.3" - prompts "^2.4.2" - semver "^7.5.2" - -"@react-native-community/cli@12.3.6": - version "12.3.6" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-12.3.6.tgz#7a323b78725b959bb8a31cca1145918263ff3c8d" - integrity sha512-647OSi6xBb8FbwFqX9zsJxOzu685AWtrOUWHfOkbKD+5LOpGORw+GQo0F9rWZnB68rLQyfKUZWJeaD00pGv5fw== - dependencies: - "@react-native-community/cli-clean" "12.3.6" - "@react-native-community/cli-config" "12.3.6" - "@react-native-community/cli-debugger-ui" "12.3.6" - "@react-native-community/cli-doctor" "12.3.6" - "@react-native-community/cli-hermes" "12.3.6" - "@react-native-community/cli-plugin-metro" "12.3.6" - "@react-native-community/cli-server-api" "12.3.6" - "@react-native-community/cli-tools" "12.3.6" - "@react-native-community/cli-types" "12.3.6" - chalk "^4.1.2" - commander "^9.4.1" - deepmerge "^4.3.0" - execa "^5.0.0" - find-up "^4.1.0" - fs-extra "^8.1.0" - graceful-fs "^4.1.3" - prompts "^2.4.2" - semver "^7.5.2" - -"@react-native-community/cli@13.6.8": - version "13.6.8" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-13.6.8.tgz#d52c22620242e161bddcd2e0b6dbacd8743ca09b" - integrity sha512-0lRdgLNaXixWY4BfFRl1J6Ao9Lapo2z+++iE7TD4GAbuxOWJSyFi+KUA8XNfSDyML4jFO02MZgyBPxAWdaminQ== - dependencies: - "@react-native-community/cli-clean" "13.6.8" - "@react-native-community/cli-config" "13.6.8" - "@react-native-community/cli-debugger-ui" "13.6.8" - "@react-native-community/cli-doctor" "13.6.8" - "@react-native-community/cli-hermes" "13.6.8" - "@react-native-community/cli-server-api" "13.6.8" - "@react-native-community/cli-tools" "13.6.8" - "@react-native-community/cli-types" "13.6.8" - chalk "^4.1.2" - commander "^9.4.1" - deepmerge "^4.3.0" - execa "^5.0.0" - find-up "^4.1.0" - fs-extra "^8.1.0" - graceful-fs "^4.1.3" - prompts "^2.4.2" - semver "^7.5.2" - -"@react-native/assets-registry@0.73.1", "@react-native/assets-registry@^0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.73.1.tgz#e2a6b73b16c183a270f338dc69c36039b3946e85" - integrity sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg== - -"@react-native/assets-registry@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.74.84.tgz#aa472f82c1b7d8a30098c8ba22fad7b3dbb5be5f" - integrity sha512-dzUhwyaX04QosWZ8zyaaNB/WYZIdeDN1lcpfQbqiOhZJShRH+FLTDVONE/dqlMQrP+EO7lDqF0RrlIt9lnOCQQ== - -"@react-native/babel-plugin-codegen@0.73.4": - version "0.73.4" - resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz#8a2037d5585b41877611498ae66adbf1dddfec1b" - integrity sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ== - dependencies: - "@react-native/codegen" "0.73.3" - -"@react-native/babel-plugin-codegen@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.74.84.tgz#a3a72c188d875601704a421e395f6909fdec40f3" - integrity sha512-UR4uiii5szIJA84mSC6GJOfYKDq7/ThyetOQT62+BBcyGeHVtHlNLNRzgaMeLqIQaT8Fq4pccMI+7QqLOMXzdw== - dependencies: - "@react-native/codegen" "0.74.84" - -"@react-native/babel-preset@0.73.21": - version "0.73.21" - resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.73.21.tgz#174c16493fa4e311b2f5f0c58d4f3c6a5a68bbea" - integrity sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA== - dependencies: - "@babel/core" "^7.20.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-class-properties" "^7.18.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" - "@babel/plugin-proposal-numeric-separator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.20.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.18.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.20.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.20.0" - "@babel/plugin-transform-flow-strip-types" "^7.20.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-private-methods" "^7.22.5" - "@babel/plugin-transform-private-property-in-object" "^7.22.11" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-self" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.5.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - "@react-native/babel-plugin-codegen" "0.73.4" - babel-plugin-transform-flow-enums "^0.0.2" - react-refresh "^0.14.0" - -"@react-native/babel-preset@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.74.84.tgz#703ebfc810d82c9f51f033352abd5f9fa70d492b" - integrity sha512-WUfu6Y4aGuVdocQZvx33BJiQWFH6kRCHYbZfBn2psgFrSRLgQWEQrDCxqPFObNAVSayM0rNhp2FvI5K/Eyeqlg== - dependencies: - "@babel/core" "^7.20.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-class-properties" "^7.18.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-logical-assignment-operators" "^7.18.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" - "@babel/plugin-proposal-numeric-separator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.20.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.18.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.20.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.20.0" - "@babel/plugin-transform-flow-strip-types" "^7.20.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-private-methods" "^7.22.5" - "@babel/plugin-transform-private-property-in-object" "^7.22.11" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-self" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.5.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - "@react-native/babel-plugin-codegen" "0.74.84" - babel-plugin-transform-flow-enums "^0.0.2" - react-refresh "^0.14.0" - -"@react-native/codegen@0.73.3", "@react-native/codegen@^0.73.2": - version "0.73.3" - resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.73.3.tgz#cc984a8b17334d986cc600254a0d4b7fa7d68a94" - integrity sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg== - dependencies: - "@babel/parser" "^7.20.0" - flow-parser "^0.206.0" - glob "^7.1.1" - invariant "^2.2.4" - jscodeshift "^0.14.0" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - -"@react-native/codegen@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.74.84.tgz#d3425a510b7da558ef5088d9b0aa5e0b1c05c783" - integrity sha512-0hXlnu9i0o8v+gXKQi+x6T471L85kCDwW4WrJiYAeOheWrQdNNW6rC3g8+LL7HXAf7QcHGU/8/d57iYfdVK2BQ== - dependencies: - "@babel/parser" "^7.20.0" - glob "^7.1.1" - hermes-parser "0.19.1" - invariant "^2.2.4" - jscodeshift "^0.14.0" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - -"@react-native/community-cli-plugin@0.73.11": - version "0.73.11" - resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.11.tgz#8826cb81bb794408202e1ce7d87e45710eff1a9f" - integrity sha512-s0bprwljKS1Al8wOKathDDmRyF+70CcNE2G/aqZ7+L0NoOE0Uxxx/5P2BxlM2Mfht7O33B4SeMNiPdE/FqIubQ== - dependencies: - "@react-native-community/cli-server-api" "12.3.0" - "@react-native-community/cli-tools" "12.3.0" - "@react-native/dev-middleware" "^0.73.6" - "@react-native/metro-babel-transformer" "^0.73.12" - chalk "^4.0.0" - execa "^5.1.1" - metro "^0.80.0" - metro-config "^0.80.0" - metro-core "^0.80.0" - node-fetch "^2.2.0" - readline "^1.3.0" - -"@react-native/community-cli-plugin@0.73.17": - version "0.73.17" - resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.17.tgz#37b381a8b503a3296eaa6727e0c52ea8835add28" - integrity sha512-F3PXZkcHg+1ARIr6FRQCQiB7ZAA+MQXGmq051metRscoLvgYJwj7dgC8pvgy0kexzUkHu5BNKrZeySzUft3xuQ== - dependencies: - "@react-native-community/cli-server-api" "12.3.6" - "@react-native-community/cli-tools" "12.3.6" - "@react-native/dev-middleware" "0.73.8" - "@react-native/metro-babel-transformer" "0.73.15" - chalk "^4.0.0" - execa "^5.1.1" - metro "^0.80.3" - metro-config "^0.80.3" - metro-core "^0.80.3" - node-fetch "^2.2.0" - readline "^1.3.0" - -"@react-native/community-cli-plugin@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.74.84.tgz#223a0defe8118dc57c8ac852ddd13517ea10c4e2" - integrity sha512-GBKE+1sUh86fS2XXV46gMCNHMc1KetshMbYJ0AhDhldpaILZHqRBX50mdVsiYVvkzp4QjM0nmYqefuJ9NVwicQ== - dependencies: - "@react-native-community/cli-server-api" "13.6.8" - "@react-native-community/cli-tools" "13.6.8" - "@react-native/dev-middleware" "0.74.84" - "@react-native/metro-babel-transformer" "0.74.84" - chalk "^4.0.0" - execa "^5.1.1" - metro "^0.80.3" - metro-config "^0.80.3" - metro-core "^0.80.3" - node-fetch "^2.2.0" - querystring "^0.2.1" - readline "^1.3.0" - -"@react-native/debugger-frontend@0.73.3": - version "0.73.3" - resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz#033757614d2ada994c68a1deae78c1dd2ad33c2b" - integrity sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw== - -"@react-native/debugger-frontend@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.74.84.tgz#0bde122a988916b6a50f05a7c3ab1c5db029b149" - integrity sha512-YUEA03UNFbiYzHpYxlcS2D9+3eNT5YLGkl5yRg3nOSN6KbCc/OttGnNZme+tuSOJwjMN/vcvtDKYkTqjJw8U0A== - -"@react-native/dev-middleware@0.73.8", "@react-native/dev-middleware@^0.73.6": - version "0.73.8" - resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz#2e43722a00c7b8db753f747f40267cbad6caba4d" - integrity sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg== - dependencies: - "@isaacs/ttlcache" "^1.4.1" - "@react-native/debugger-frontend" "0.73.3" - chrome-launcher "^0.15.2" - chromium-edge-launcher "^1.0.0" - connect "^3.6.5" - debug "^2.2.0" - node-fetch "^2.2.0" - open "^7.0.3" - serve-static "^1.13.1" - temp-dir "^2.0.0" - ws "^6.2.2" - -"@react-native/dev-middleware@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.74.84.tgz#19ccfece791742f83f4c0a22a8c14593a45562a2" - integrity sha512-veYw/WmyrAOQHUiIeULzn2duJQnXDPiKq2jZ/lcmDo6jsLirpp+Q73lx09TYgy/oVoPRuV0nfmU3x9B6EV/7qQ== - dependencies: - "@isaacs/ttlcache" "^1.4.1" - "@react-native/debugger-frontend" "0.74.84" - "@rnx-kit/chromium-edge-launcher" "^1.0.0" - chrome-launcher "^0.15.2" - connect "^3.6.5" - debug "^2.2.0" - node-fetch "^2.2.0" - nullthrows "^1.1.1" - open "^7.0.3" - selfsigned "^2.4.1" - serve-static "^1.13.1" - temp-dir "^2.0.0" - ws "^6.2.2" - -"@react-native/gradle-plugin@0.73.4", "@react-native/gradle-plugin@^0.73.4": - version "0.73.4" - resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz#aa55784a8c2b471aa89934db38c090d331baf23b" - integrity sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg== - -"@react-native/gradle-plugin@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.74.84.tgz#6ff25fad5f78c276afde96ffc42e04e92d6d92b1" - integrity sha512-wYWC5WWXqzCCe4PDogz9pNc4xH5ZamahW5XGSbrrYJ5V3walZ+7z43V6iEBJkZbLjj9YBcSttkXYGr1Xh4veAg== - -"@react-native/js-polyfills@0.73.1", "@react-native/js-polyfills@^0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz#730b0a7aaab947ae6f8e5aa9d995e788977191ed" - integrity sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g== - -"@react-native/js-polyfills@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.74.84.tgz#edf0e8463616a2683269bbfe3957590f7ebd910c" - integrity sha512-+PgxuUjBw9JVlz6m4ECsIJMLbDopnr4rpLmsG32hQaJrg0wMuvHtsgAY/J/aVCSG2GNUXexfjrnhc+O9yGOZXQ== - -"@react-native/metro-babel-transformer@0.73.15", "@react-native/metro-babel-transformer@^0.73.12": - version "0.73.15" - resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz#c516584dde62d65a46668074084359c03e6a50f1" - integrity sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw== - dependencies: - "@babel/core" "^7.20.0" - "@react-native/babel-preset" "0.73.21" - hermes-parser "0.15.0" - nullthrows "^1.1.1" - -"@react-native/metro-babel-transformer@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.74.84.tgz#6c2c1632bdf557f176c9d489fbb676522ffb222a" - integrity sha512-YtVGq7jkgyUECv5yt4BOFbOXyW4ddUn8+dnwGGpJKdfhXYL5o5++AxNdE+2x+SZdkj3JUVekGKPwRabFECABaw== - dependencies: - "@babel/core" "^7.20.0" - "@react-native/babel-preset" "0.74.84" - hermes-parser "0.19.1" - nullthrows "^1.1.1" - -"@react-native/normalize-color@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.1.0.tgz#939b87a9849e81687d3640c5efa2a486ac266f91" - integrity sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA== - -"@react-native/normalize-colors@0.73.2", "@react-native/normalize-colors@^0.73.0", "@react-native/normalize-colors@^0.73.2": - version "0.73.2" - resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz#cc8e48fbae2bbfff53e12f209369e8d2e4cf34ec" - integrity sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w== - -"@react-native/normalize-colors@0.74.84", "@react-native/normalize-colors@^0.74.1": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.74.84.tgz#4764d59775c17a6ed193509cb01ae2f42dd5c045" - integrity sha512-Y5W6x8cC5RuakUcTVUFNAIhUZ/tYpuqHZlRBoAuakrTwVuoNHXfQki8lj1KsYU7rW6e3VWgdEx33AfOQpdNp6A== - -"@react-native/virtualized-lists@0.73.4", "@react-native/virtualized-lists@^0.73.4": - version "0.73.4" - resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz#640e594775806f63685435b5d9c3d05c378ccd8c" - integrity sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog== - dependencies: - invariant "^2.2.4" - nullthrows "^1.1.1" - -"@react-native/virtualized-lists@0.74.84": - version "0.74.84" - resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.74.84.tgz#cf32fffc93072942532c9c81bd7e4c01a2949626" - integrity sha512-XcV+qdqt2WihaY4iRm/M1FdSy+18lecU9mRXNmy9YK8g9Th/8XbNtmmKI0qWBx3KxyuXMH/zd0ps05YTrX16kw== - dependencies: - invariant "^2.2.4" - nullthrows "^1.1.1" - -"@rnx-kit/chromium-edge-launcher@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#c0df8ea00a902c7a417cd9655aab06de398b939c" - integrity sha512-lzD84av1ZQhYUS+jsGqJiCMaJO2dn9u+RTT9n9q6D3SaKVwWqv+7AoRKqBu19bkwyE+iFRl1ymr40QS90jVFYg== - dependencies: - "@types/node" "^18.0.0" - escape-string-regexp "^4.0.0" - is-wsl "^2.2.0" - lighthouse-logger "^1.0.0" - mkdirp "^1.0.4" - rimraf "^3.0.2" - -"@rollup/rollup-android-arm-eabi@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" - integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ== - -"@rollup/rollup-android-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203" - integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA== - -"@rollup/rollup-darwin-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096" - integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== - -"@rollup/rollup-darwin-x64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c" - integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA== - -"@rollup/rollup-linux-arm-gnueabihf@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8" - integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA== - -"@rollup/rollup-linux-arm-musleabihf@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549" - integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A== - -"@rollup/rollup-linux-arm64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577" - integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw== - -"@rollup/rollup-linux-arm64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c" - integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ== - -"@rollup/rollup-linux-powerpc64le-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf" - integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA== - -"@rollup/rollup-linux-riscv64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9" - integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg== - -"@rollup/rollup-linux-s390x-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec" - integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg== - -"@rollup/rollup-linux-x64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942" - integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== - -"@rollup/rollup-linux-x64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d" - integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg== - -"@rollup/rollup-win32-arm64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf" - integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA== - -"@rollup/rollup-win32-ia32-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54" - integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg== - -"@rollup/rollup-win32-x64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4" - integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== - -"@rushstack/eslint-patch@^1.3.3": - version "1.10.3" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz#391d528054f758f81e53210f1a1eebcf1a8b1d20" - integrity sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg== - -"@segment/loosely-validate-event@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681" - integrity sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw== - dependencies: - component-type "^1.2.1" - join-component "^1.1.0" - -"@sideway/address@^4.1.5": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" - integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@sideway/formula@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" - integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== - -"@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== - -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - -"@sinonjs/commons@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@swc/counter@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" - integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== - -"@swc/helpers@0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" - integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== - dependencies: - "@swc/counter" "^0.1.3" - tslib "^2.4.0" - -"@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== - -"@types/body-parser@*": - version "1.19.5" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" - integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/bonjour@^3.5.9": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" - integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== - dependencies: - "@types/node" "*" - -"@types/connect-history-api-fallback@^1.3.5": - version "1.5.4" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" - integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== - dependencies: - "@types/express-serve-static-core" "*" - "@types/node" "*" - -"@types/connect@*": - version "3.4.38" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" - integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== - dependencies: - "@types/node" "*" - -"@types/eslint-scope@^3.7.3": - version "3.7.7" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" - integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "8.56.10" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" - integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.19.3" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz#e469a13e4186c9e1c0418fb17be8bc8ff1b19a7a" - integrity sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - -"@types/express@*", "@types/express@^4.17.13": - version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.33" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/glob@^7.1.1": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== - -"@types/http-errors@*": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" - integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== - -"@types/http-proxy@^1.17.8": - version "1.17.14" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" - integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/mime@^1": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" - integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== - -"@types/minimatch@*": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - -"@types/node-forge@^1.3.0": - version "1.3.11" - resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" - integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== - dependencies: - "@types/node" "*" - -"@types/node@*", "@types/node@^20.10.6": - version "20.14.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.1.tgz#2434dbcb1f039e31f2c0e9969da93f52cf6348f3" - integrity sha512-T2MzSGEu+ysB/FkWfqmhV3PLyQlowdptmmgD20C6QxsS8Fmv5SjpZ1ayXaEC0S21/h5UJ9iA6W/5vSNU5l00OA== - dependencies: - undici-types "~5.26.4" - -"@types/node@^18.0.0": - version "18.19.34" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.34.tgz#c3fae2bbbdb94b4a52fe2d229d0dccce02ef3d27" - integrity sha512-eXF4pfBNV5DAMKGbI02NnDtWrQ40hAN558/2vvS4gMpMIxaf6JmD7YjnZbq0Q9TDSSkKBamime8ewRoomHdt4g== - dependencies: - undici-types "~5.26.4" - -"@types/prop-types@*": - version "15.7.12" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" - integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== - -"@types/qs@*": - version "6.9.15" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" - integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== - -"@types/range-parser@*": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" - integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== - -"@types/react-dom@^18.2.18": - version "18.3.0" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" - integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== - dependencies: - "@types/react" "*" - -"@types/react-native@^0.73.0": - version "0.73.0" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.73.0.tgz#b316be230745779814caa533360262140b0f5984" - integrity sha512-6ZRPQrYM72qYKGWidEttRe6M5DZBEV5F+MHMHqd4TTYx0tfkcdrUFGdef6CCxY0jXU7wldvd/zA/b0A/kTeJmA== - dependencies: - react-native "*" - -"@types/react@*", "@types/react@^18.2.46": - version "18.3.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" - integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== - -"@types/send@*": - version "0.17.4" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" - integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - -"@types/serve-index@^1.9.1": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" - integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== - dependencies: - "@types/express" "*" - -"@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.7" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" - integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== - dependencies: - "@types/http-errors" "*" - "@types/node" "*" - "@types/send" "*" - -"@types/sockjs@^0.3.33": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" - integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== - dependencies: - "@types/node" "*" - -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/ws@^8.5.5": - version "8.5.10" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" - integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== - dependencies: - "@types/node" "*" - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^15.0.0": - version "15.0.19" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.19.tgz#328fb89e46109ecbdb70c295d96ff2f46dfd01b9" - integrity sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA== - dependencies: - "@types/yargs-parser" "*" - -"@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/parser@^5.4.2 || ^6.0.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" - integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== - dependencies: - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" - integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - -"@typescript-eslint/types@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" - integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== - -"@typescript-eslint/typescript-estree@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" - integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/visitor-keys@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" - integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== - dependencies: - "@typescript-eslint/types" "6.21.0" - eslint-visitor-keys "^3.4.1" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@urql/core@2.3.6": - version "2.3.6" - resolved "https://registry.yarnpkg.com/@urql/core/-/core-2.3.6.tgz#ee0a6f8fde02251e9560c5f17dce5cd90f948552" - integrity sha512-PUxhtBh7/8167HJK6WqBv6Z0piuiaZHQGYbhwpNL9aIQmLROPEdaUYkY4wh45wPQXcTpnd11l0q3Pw+TI11pdw== - dependencies: - "@graphql-typed-document-node/core" "^3.1.0" - wonka "^4.0.14" - -"@urql/core@>=2.3.1": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@urql/core/-/core-5.0.3.tgz#80e390399f6aa32757c42733deb5f029bf0406ad" - integrity sha512-NZ3YqRr6IphbpFjGqujJOuVuV8/QegYxfjy1zdmOSWpYYFLpmMBfVtzZ/L8IiqPERVAEAIKjUsryLnVtXJQo4w== - dependencies: - "@0no-co/graphql.web" "^1.0.5" - wonka "^6.3.2" - -"@urql/exchange-retry@0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@urql/exchange-retry/-/exchange-retry-0.3.0.tgz#13252108b5a111aab45f9982f4db18d1a286e423" - integrity sha512-hHqer2mcdVC0eYnVNbWyi28AlGOPb2vjH3lP3/Bc8Lc8BjhMsDwFMm7WhoP5C1+cfbr/QJ6Er3H/L08wznXxfg== - dependencies: - "@urql/core" ">=2.3.1" - wonka "^4.0.14" - -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== - -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== - -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== - -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== - -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" - -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== - -"@webassemblyjs/wasm-edit@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" - -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@xtuc/long" "4.2.2" - -"@xmldom/xmldom@^0.8.8": - version "0.8.10" - resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" - integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== - -"@xmldom/xmldom@~0.7.7": - version "0.7.13" - resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.13.tgz#ff34942667a4e19a9f4a0996a76814daac364cf3" - integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g== - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -abab@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" - integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -accepts@^1.3.7, accepts@^1.3.8, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.0, ajv@^8.9.0: - version "8.15.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.15.0.tgz#d918c661e3e820bbbc65a320e182ee56a1aa978a" - integrity sha512-15BTtQUOsSrmHCy+B4VnAiJAJxJ8IFgu6fcjFQF3jQYZ78nLSQthlFg4ehp+NLIyfvFgOlxNsjKIEhydtFPVHQ== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^2.3.0" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - -anser@^1.4.9: - version "1.4.10" - resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" - integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== - -ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-fragments@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" - integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== - dependencies: - colorette "^1.0.7" - slice-ansi "^2.0.0" - strip-ansi "^5.0.0" - -ansi-html-community@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" - integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -ansi-regex@^5.0.0, ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -any-promise@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -appdirsjs@^1.2.4: - version "1.2.7" - resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3" - integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== - -application-config-path@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/application-config-path/-/application-config-path-0.1.1.tgz#8b5ac64ff6afdd9bd70ce69f6f64b6998f5f756e" - integrity sha512-zy9cHePtMP0YhwG+CfHm0bgwdnga2X3gZexpdCwEj//dpb+TKajtiC8REEUJUSq6Ab4f9cgNy2l8ObXzCXFkEw== - -arg@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0" - integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-query@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" - -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== - dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -array-includes@^3.1.6, array-includes@^3.1.7, array-includes@^3.1.8: - version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== - dependencies: - array-uniq "^1.0.1" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== - -array.prototype.findlast@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" - integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.findlastindex@^1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" - integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.toreversed@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" - integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.tosorted@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" - integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.3" - es-errors "^1.3.0" - es-shim-unscopables "^1.0.2" - -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" - is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" - -asap@~2.0.3, asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - -ast-types-flow@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" - integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== - -ast-types@0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.15.2.tgz#39ae4809393c4b16df751ee563411423e85fb49d" - integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg== - dependencies: - tslib "^2.0.1" - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -axe-core@=4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" - integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== - -axobject-query@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" - integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== - dependencies: - dequal "^2.0.3" - -babel-core@^7.0.0-bridge.0: - version "7.0.0-bridge.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" - integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== - -babel-loader@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" - integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^2.0.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-plugin-module-resolver@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.2.tgz#cdeac5d4aaa3b08dd1ac23ddbf516660ed2d293e" - integrity sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg== - dependencies: - find-babel-config "^2.1.1" - glob "^9.3.3" - pkg-up "^3.1.0" - reselect "^4.1.7" - resolve "^1.22.8" - -babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.11" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" - integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.2" - semver "^6.3.1" - -babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: - version "0.10.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" - integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" - core-js-compat "^3.36.1" - -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" - integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.2" - -babel-plugin-react-native-web@^0.19.10: - version "0.19.12" - resolved "https://registry.yarnpkg.com/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.19.12.tgz#90481ee72b515020b06cb644abe1e8a16590bd86" - integrity sha512-eYZ4+P6jNcB37lObWIg0pUbi7+3PKoU1Oie2j0C8UF3cXyXoR74tO2NBjI/FORb2LJyItJZEAmjU5pSaJYEL1w== - -babel-plugin-react-native-web@~0.18.10: - version "0.18.12" - resolved "https://registry.yarnpkg.com/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.18.12.tgz#3e9764484492ea612a16b40135b07c2d05b7969d" - integrity sha512-4djr9G6fMdwQoD6LQ7hOKAm39+y12flWgovAqS1k5O8f42YQ3A1FFMyV5kKfetZuGhZO5BmNmOdRRZQ1TixtDw== - -babel-plugin-transform-flow-enums@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz#d1d0cc9bdc799c850ca110d0ddc9f21b9ec3ef25" - integrity sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ== - dependencies: - "@babel/plugin-syntax-flow" "^7.12.1" - -babel-preset-expo@~9.5.2: - version "9.5.2" - resolved "https://registry.yarnpkg.com/babel-preset-expo/-/babel-preset-expo-9.5.2.tgz#5ed1756c8434ca972d7a940e4f13570a283641df" - integrity sha512-hU1G1TDiikuXV6UDZjPnX+WdbjbtidDiYhftMEVrZQSst45pDPVBWbM41TUKrpJMwv4FypsLzK+378gnMPRVWQ== - dependencies: - "@babel/plugin-proposal-decorators" "^7.12.9" - "@babel/plugin-proposal-export-namespace-from" "^7.18.9" - "@babel/plugin-proposal-object-rest-spread" "^7.12.13" - "@babel/plugin-transform-react-jsx" "^7.12.17" - "@babel/preset-env" "^7.20.0" - babel-plugin-module-resolver "^5.0.0" - babel-plugin-react-native-web "~0.18.10" - metro-react-native-babel-preset "0.76.8" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== - -better-opn@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817" - integrity sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ== - dependencies: - open "^8.0.4" - -big-integer@1.6.x: - version "1.6.52" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" - integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -bl@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -blueimp-md5@^2.10.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0" - integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w== - -body-parser@1.20.2, body-parser@^1.20.1: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -bonjour-service@^1.0.11: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" - integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== - dependencies: - fast-deep-equal "^3.1.3" - multicast-dns "^7.2.5" - -boolbase@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== - -bplist-creator@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.1.0.tgz#018a2d1b587f769e379ef5519103730f8963ba1e" - integrity sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg== - dependencies: - stream-buffers "2.2.x" - -bplist-parser@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.1.tgz#e1c90b2ca2a9f9474cc72f6862bbf3fee8341fd1" - integrity sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA== - dependencies: - big-integer "1.6.x" - -bplist-parser@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.2.tgz#3ac79d67ec52c4c107893e0237eb787cbacbced7" - integrity sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ== - dependencies: - big-integer "1.6.x" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3, braces@~3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.0.0, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.22.2, browserslist@^4.23.0: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== - dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== - -bundle-require@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-4.2.1.tgz#4c450a5807381d20ade987bde8ac391544257919" - integrity sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA== - dependencies: - load-tsconfig "^0.2.3" - -busboy@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -cac@^6.7.12: - version "6.7.14" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - -cacache@^15.3.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" - integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== - dependencies: - "@npmcli/fs" "^1.0.0" - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001587: - version "1.0.30001627" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001627.tgz#8071c42d468e06ed2fb2c545efe79a663fd326ab" - integrity sha512-4zgNiB8nTyV/tHhwZrFs88ryjls/lHiqFhrxCW4qSTeuRByBVnPYpDInchOIySWknznucaf31Z4KYqjfbrecVw== - -chalk@^2.0.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -charenc@0.0.2, charenc@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== - -chokidar@^3.5.1, chokidar@^3.5.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - -chrome-launcher@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" - integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== - dependencies: - "@types/node" "*" - escape-string-regexp "^4.0.0" - is-wsl "^2.2.0" - lighthouse-logger "^1.0.0" - -chrome-trace-event@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" - integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== - -chromium-edge-launcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#0443083074715a13c669530b35df7bfea33b1509" - integrity sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA== - dependencies: - "@types/node" "*" - escape-string-regexp "^4.0.0" - is-wsl "^2.2.0" - lighthouse-logger "^1.0.0" - mkdirp "^1.0.4" - rimraf "^3.0.2" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -ci-info@^3.2.0, ci-info@^3.3.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -clean-css@^5.2.2: - version "5.3.3" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" - integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -clean-webpack-plugin@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz#72947d4403d452f38ed61a9ff0ada8122aacd729" - integrity sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w== - dependencies: - del "^4.1.1" - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-spinners@^2.0.0, cli-spinners@^2.5.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" - integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== - -clone@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colord@^2.9.1: - version "2.9.3" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" - integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== - -colorette@^1.0.7: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - -colorette@^2.0.10: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -command-exists@^1.2.4, command-exists@^1.2.8: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - -commander@2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -commander@^9.4.1: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - -compare-versions@^3.4.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" - integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== - -component-type@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.2.tgz#4458ecc0c1871efc6288bfaff0cbdab08141d079" - integrity sha512-99VUHREHiN5cLeHm3YLq312p6v+HUEcwtLCAtelvUDI6+SH5g5Cr85oNR2S1o6ywzL0ykMbuwLzM2ANocjEOIA== - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.1, compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -connect-history-api-fallback@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" - integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== - -connect@^3.6.5, connect@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4, content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== - -copy-webpack-plugin@^10.2.0: - version "10.2.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" - integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== - dependencies: - fast-glob "^3.2.7" - glob-parent "^6.0.1" - globby "^12.0.2" - normalize-path "^3.0.0" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - -core-js-compat@^3.31.0, core-js-compat@^3.36.1: - version "3.37.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" - integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== - dependencies: - browserslist "^4.23.0" - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -cross-fetch@^3.1.5: - version "3.1.8" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" - integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== - dependencies: - node-fetch "^2.6.12" - -cross-spawn@^6.0.0, cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypt@0.0.2, crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== - -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg== - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -css-declaration-sorter@^6.3.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" - integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== - -css-in-js-utils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz#640ae6a33646d401fc720c54fc61c42cd76ae2bb" - integrity sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A== - dependencies: - hyphenate-style-name "^1.0.3" - -css-loader@^6.5.1: - version "6.11.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" - integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.33" - postcss-modules-extract-imports "^3.1.0" - postcss-modules-local-by-default "^4.0.5" - postcss-modules-scope "^3.2.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.5.4" - -css-minimizer-webpack-plugin@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== - dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - -css-select@^4.1.3, css-select@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" - integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== - dependencies: - boolbase "^1.0.0" - css-what "^6.0.1" - domhandler "^4.3.1" - domutils "^2.8.0" - nth-check "^2.0.1" - -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-default@^5.2.14: - version "5.2.14" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz#309def4f7b7e16d71ab2438052093330d9ab45d8" - integrity sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A== - dependencies: - css-declaration-sorter "^6.3.1" - cssnano-utils "^3.1.0" - postcss-calc "^8.2.3" - postcss-colormin "^5.3.1" - postcss-convert-values "^5.1.3" - postcss-discard-comments "^5.1.2" - postcss-discard-duplicates "^5.1.0" - postcss-discard-empty "^5.1.1" - postcss-discard-overridden "^5.1.0" - postcss-merge-longhand "^5.1.7" - postcss-merge-rules "^5.1.4" - postcss-minify-font-values "^5.1.0" - postcss-minify-gradients "^5.1.1" - postcss-minify-params "^5.1.4" - postcss-minify-selectors "^5.2.1" - postcss-normalize-charset "^5.1.0" - postcss-normalize-display-values "^5.1.0" - postcss-normalize-positions "^5.1.1" - postcss-normalize-repeat-style "^5.1.1" - postcss-normalize-string "^5.1.0" - postcss-normalize-timing-functions "^5.1.0" - postcss-normalize-unicode "^5.1.1" - postcss-normalize-url "^5.1.0" - postcss-normalize-whitespace "^5.1.1" - postcss-ordered-values "^5.1.3" - postcss-reduce-initial "^5.1.2" - postcss-reduce-transforms "^5.1.0" - postcss-svgo "^5.1.0" - postcss-unique-selectors "^5.1.1" - -cssnano-utils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" - integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== - -cssnano@^5.0.6: - version "5.1.15" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf" - integrity sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw== - dependencies: - cssnano-preset-default "^5.2.14" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -dag-map@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/dag-map/-/dag-map-1.0.2.tgz#e8379f041000ed561fc515475c1ed2c85eece8d7" - integrity sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw== - -damerau-levenshtein@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" - integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== - -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -dayjs@^1.8.15: - version "1.11.11" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" - integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== - -debug@2.6.9, debug@^2.2.0, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - -debug@^3.1.0, debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== - dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" - -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== - dependencies: - execa "^5.0.0" - -defaults@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" - integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== - dependencies: - clone "^1.0.2" - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -define-properties@^1.2.0, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" - -del@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" - integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== - dependencies: - globby "^11.0.1" - graceful-fs "^4.2.4" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.2" - p-map "^4.0.0" - rimraf "^3.0.2" - slash "^3.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -denodeify@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" - integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - -deprecated-react-native-prop-types@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz#02a12f090da7bd9e8c3ac53c31cf786a1315d302" - integrity sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ== - dependencies: - "@react-native/normalize-colors" "^0.73.0" - invariant "^2.2.4" - prop-types "^15.8.1" - -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dns-packet@^5.2.2: - version "5.6.1" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" - integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== - dependencies: - "@leichtgewicht/ip-codec" "^2.0.1" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@^1.0.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" - integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" - integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== - dependencies: - domelementtype "^2.2.0" - -domutils@^2.5.2, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dotenv-expand@~10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" - integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== - -dotenv@~16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.4.668: - version "1.4.789" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.789.tgz#fec941cb753ee139da562a5a8ff31fc3e828b411" - integrity sha512-0VbyiaXoT++Fi2vHGo2ThOeS6X3vgRCWrjPeO2FeIAWL6ItiSJ9BqlH8LfCXe3X1IdcG+S0iLoNaxQWhfZoGzQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^5.12.0, enhanced-resolve@^5.16.0: - version "5.17.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" - integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -env-editor@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/env-editor/-/env-editor-0.4.2.tgz#4e76568d0bd8f5c2b6d314a9412c8fe9aa3ae861" - integrity sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA== - -envinfo@^7.10.0: - version "7.13.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" - integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== - -eol@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -error-stack-parser@^2.0.6: - version "2.1.4" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" - integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== - dependencies: - stackframe "^1.3.4" - -errorhandler@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" - integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A== - dependencies: - accepts "~1.3.7" - escape-html "~1.0.3" - -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== - dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" - is-callable "^1.2.7" - is-data-view "^1.0.1" - is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" - object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" - string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.2.1, es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.19: - version "1.0.19" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" - integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.3" - es-errors "^1.3.0" - es-set-tostringtag "^2.0.3" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - iterator.prototype "^1.1.2" - safe-array-concat "^1.1.2" - -es-module-lexer@^1.2.1: - version "1.5.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.3.tgz#25969419de9c0b1fbe54279789023e8a9a788412" - integrity sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg== - -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== - dependencies: - es-errors "^1.3.0" - -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== - dependencies: - get-intrinsic "^1.2.4" - has-tostringtag "^1.0.2" - hasown "^2.0.1" - -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== - dependencies: - hasown "^2.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -esbuild@^0.21.4: - version "0.21.4" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.4.tgz#ceb501def8edb12a5bfd9c55f3a96db698edf022" - integrity sha512-sFMcNNrj+Q0ZDolrp5pDhH0nRPN9hLIM3fRPwgbLYJeSHHgnXSnbV3xYgSVuOeLWH9c73VwmEverVzupIv5xuA== - optionalDependencies: - "@esbuild/aix-ppc64" "0.21.4" - "@esbuild/android-arm" "0.21.4" - "@esbuild/android-arm64" "0.21.4" - "@esbuild/android-x64" "0.21.4" - "@esbuild/darwin-arm64" "0.21.4" - "@esbuild/darwin-x64" "0.21.4" - "@esbuild/freebsd-arm64" "0.21.4" - "@esbuild/freebsd-x64" "0.21.4" - "@esbuild/linux-arm" "0.21.4" - "@esbuild/linux-arm64" "0.21.4" - "@esbuild/linux-ia32" "0.21.4" - "@esbuild/linux-loong64" "0.21.4" - "@esbuild/linux-mips64el" "0.21.4" - "@esbuild/linux-ppc64" "0.21.4" - "@esbuild/linux-riscv64" "0.21.4" - "@esbuild/linux-s390x" "0.21.4" - "@esbuild/linux-x64" "0.21.4" - "@esbuild/netbsd-x64" "0.21.4" - "@esbuild/openbsd-x64" "0.21.4" - "@esbuild/sunos-x64" "0.21.4" - "@esbuild/win32-arm64" "0.21.4" - "@esbuild/win32-ia32" "0.21.4" - "@esbuild/win32-x64" "0.21.4" - -escalade@^3.1.1, escalade@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-next@14.0.4: - version "14.0.4" - resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.0.4.tgz#7cd2c0a3b310203d41cf0dbf9d31f9b0a6235b4a" - integrity sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ== - dependencies: - "@next/eslint-plugin-next" "14.0.4" - "@rushstack/eslint-patch" "^1.3.3" - "@typescript-eslint/parser" "^5.4.2 || ^6.0.0" - eslint-import-resolver-node "^0.3.6" - eslint-import-resolver-typescript "^3.5.2" - eslint-plugin-import "^2.28.1" - eslint-plugin-jsx-a11y "^6.7.1" - eslint-plugin-react "^7.33.2" - eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" - -eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-import-resolver-typescript@^3.5.2: - version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" - integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== - dependencies: - debug "^4.3.4" - enhanced-resolve "^5.12.0" - eslint-module-utils "^2.7.4" - fast-glob "^3.3.1" - get-tsconfig "^4.5.0" - is-core-module "^2.11.0" - is-glob "^4.0.3" - -eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" - integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== - dependencies: - debug "^3.2.7" - -eslint-plugin-import@^2.28.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-plugin-jsx-a11y@^6.7.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" - integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== - dependencies: - "@babel/runtime" "^7.23.2" - aria-query "^5.3.0" - array-includes "^3.1.7" - array.prototype.flatmap "^1.3.2" - ast-types-flow "^0.0.8" - axe-core "=4.7.0" - axobject-query "^3.2.1" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - es-iterator-helpers "^1.0.15" - hasown "^2.0.0" - jsx-ast-utils "^3.3.5" - language-tags "^1.0.9" - minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - -"eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": - version "4.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" - integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== - -eslint-plugin-react@^7.33.2: - version "7.34.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz#2780a1a35a51aca379d86d29b9a72adc6bfe6b66" - integrity sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw== - dependencies: - array-includes "^3.1.8" - array.prototype.findlast "^1.2.5" - array.prototype.flatmap "^1.3.2" - array.prototype.toreversed "^1.1.2" - array.prototype.tosorted "^1.1.3" - doctrine "^2.1.0" - es-iterator-helpers "^1.0.19" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.8" - object.fromentries "^2.0.8" - object.hasown "^1.1.4" - object.values "^1.2.0" - prop-types "^15.8.1" - resolve "^2.0.0-next.5" - semver "^6.3.1" - string.prototype.matchall "^4.0.11" - -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.56.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esprima@^4.0.0, esprima@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -event-target-shim@^5.0.0, event-target-shim@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -exec-async@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/exec-async/-/exec-async-2.2.0.tgz#c7c5ad2eef3478d38390c6dd3acfe8af0efc8301" - integrity sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw== - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^5.0.0, execa@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - 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" - -expo-application@~5.3.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/expo-application/-/expo-application-5.3.1.tgz#074bbfc6bb5d65ae74a67f5288fa3eb582237e53" - integrity sha512-HR2+K+Hm33vLw/TfbFaHrvUbRRNRco8R+3QaCKy7eJC2LFfT05kZ15ynGaKfB5DJ/oqPV3mxXVR/EfwmE++hoA== - -expo-asset@~8.10.1: - version "8.10.1" - resolved "https://registry.yarnpkg.com/expo-asset/-/expo-asset-8.10.1.tgz#a7e8cf1c555ab8f844599822cb084fee95a93644" - integrity sha512-5VMTESxgY9GBsspO/esY25SKEa7RyascVkLe/OcL1WgblNFm7xCCEEUIW8VWS1nHJQGYxpMZPr3bEfjMpdWdyA== - dependencies: - blueimp-md5 "^2.10.0" - expo-constants "~14.4.2" - expo-file-system "~15.4.0" - invariant "^2.2.4" - md5-file "^3.2.3" - path-browserify "^1.0.0" - url-parse "^1.5.9" - -expo-constants@~14.4.2: - version "14.4.2" - resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-14.4.2.tgz#cac5e8b524069545739b8d8595ce96cc5be6578c" - integrity sha512-nOB122DOAjk+KrJT69lFQAoYVQGQjFHSigCPVBzVdko9S1xGsfiOH9+X5dygTsZTIlVLpQJDdmZ7ONiv3i+26w== - dependencies: - "@expo/config" "~8.1.0" - uuid "^3.3.2" - -expo-file-system@~15.4.0, expo-file-system@~15.4.5: - version "15.4.5" - resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-15.4.5.tgz#3ef68583027ff0e2fb9eca7a22b3caff6cfc550d" - integrity sha512-xy61KaTaDgXhT/dllwYDHm3ch026EyO8j4eC6wSVr/yE12MMMxAC09yGwy4f7kkOs6ztGVQF5j7ldRzNLN4l0Q== - dependencies: - uuid "^3.4.0" - -expo-font@~11.4.0: - version "11.4.0" - resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-11.4.0.tgz#e2d31c0bb76ba3c37c2d84703a49aeafc3afef28" - integrity sha512-nkmezCFD7gR/I6R+e3/ry18uEfF8uYrr6h+PdBJu+3dawoLOpo+wFb/RG9bHUekU1/cPanR58LR7G5MEMKHR2w== - dependencies: - fontfaceobserver "^2.1.0" - -expo-keep-awake@~12.3.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz#c42449ae19c993274ddc43aafa618792b6aec408" - integrity sha512-ujiJg1p9EdCOYS05jh5PtUrfiZnK0yyLy+UewzqrjUqIT8eAGMQbkfOn3C3fHE7AKd5AefSMzJnS3lYZcZYHDw== - -expo-modules-autolinking@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-1.5.1.tgz#363f90c172769ce12bf56c7be9ca0897adfc7a81" - integrity sha512-yt5a1VCp2BF9CrsO689PCD5oXKP14MMhnOanQMvDn4BDpURYfzAlDVGC5fZrNQKtwn/eq3bcrxIwZ7D9QjVVRg== - dependencies: - "@expo/config" "~8.1.0" - chalk "^4.1.0" - commander "^7.2.0" - fast-glob "^3.2.5" - find-up "^5.0.0" - fs-extra "^9.1.0" - -expo-modules-core@1.5.13: - version "1.5.13" - resolved "https://registry.yarnpkg.com/expo-modules-core/-/expo-modules-core-1.5.13.tgz#abe00502b1b622ff8ef37bc7516180595a0fc4e3" - integrity sha512-cKRsiHKwpDPRkBgMW3XdUWmEUDzihEPWXAyeo629BXpJ6uX6a66Zbz63SEXhlgsbLq8FB77gvYku3ceBqb+hHg== - dependencies: - compare-versions "^3.4.0" - invariant "^2.2.4" - -expo-pwa@0.0.127: - version "0.0.127" - resolved "https://registry.yarnpkg.com/expo-pwa/-/expo-pwa-0.0.127.tgz#b8d2fd28efff408a24e0f2539bfb47e09f8e4ebe" - integrity sha512-8D9wEDkEXG9r6TPvAFpWt27IiP1cLm/4RWVRUHzFZflbWYLi8GkYArj5LHbbfokybRm1GVAanSrrYFEqHoIUiA== - dependencies: - "@expo/image-utils" "0.3.23" - chalk "^4.0.0" - commander "2.20.0" - update-check "1.5.3" - -expo-status-bar@~1.7.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/expo-status-bar/-/expo-status-bar-1.7.1.tgz#f2772a529187282eaa0741279ed8d525bdce54c4" - integrity sha512-Wkm9uCmuQQBSU+l/AekWAQ1d0FYw560yL116+OAKJDyKBOUpPURoWkFbabM1EDxv+5scTuSThr/CvsA0nsSCow== - -expo@^49.0.21: - version "49.0.23" - resolved "https://registry.yarnpkg.com/expo/-/expo-49.0.23.tgz#b8dc4daecdc2e912607a4bc63dede5506017976d" - integrity sha512-mFdBpWisPXBuocRGywC14nDai5vSUmvEyQpwvKH/xUo+m5/TUvfqV6YIewFpW22zn5WFGFiuJPhzNrqhBBinIw== - dependencies: - "@babel/runtime" "^7.20.0" - "@expo/cli" "0.10.17" - "@expo/config" "8.1.2" - "@expo/config-plugins" "7.2.5" - "@expo/vector-icons" "^13.0.0" - babel-preset-expo "~9.5.2" - expo-application "~5.3.0" - expo-asset "~8.10.1" - expo-constants "~14.4.2" - expo-file-system "~15.4.5" - expo-font "~11.4.0" - expo-keep-awake "~12.3.0" - expo-modules-autolinking "1.5.1" - expo-modules-core "1.5.13" - fbemitter "^3.0.0" - invariant "^2.2.4" - md5-file "^3.2.3" - node-fetch "^2.6.7" - pretty-format "^26.5.2" - uuid "^3.4.0" - -express@^4.17.3: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.6.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.5, fast-glob@^3.2.7, fast-glob@^3.2.9, fast-glob@^3.3.1, fast-glob@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-loops@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.3.tgz#ce96adb86d07e7bf9b4822ab9c6fac9964981f75" - integrity sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g== - -fast-uri@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.3.0.tgz#bdae493942483d299e7285dcb4627767d42e2793" - integrity sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw== - -fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.0.tgz#341cc98de71e9ba9e651a67f41f1752d1441a501" - integrity sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg== - dependencies: - strnum "^1.0.5" - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -fbemitter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3" - integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw== - dependencies: - fbjs "^3.0.0" - -fbjs-css-vars@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" - integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== - -fbjs@^3.0.0, fbjs@^3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.5.tgz#aa0edb7d5caa6340011790bd9249dbef8a81128d" - integrity sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg== - dependencies: - cross-fetch "^3.1.5" - fbjs-css-vars "^1.0.0" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^1.0.35" - -fetch-retry@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-4.1.1.tgz#fafe0bb22b54f4d0a9c788dff6dd7f8673ca63f3" - integrity sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA== - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-babel-config@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-2.1.1.tgz#93703fc8e068db5e4c57592900c5715dd04b7e5b" - integrity sha512-5Ji+EAysHGe1OipH7GN4qDjok5Z1uw5KAwDCbicU/4wyTZY7CqOCzcWbG7J5ad9mazq67k89fXlbc1MuIfl9uA== - dependencies: - json5 "^2.2.3" - path-exists "^4.0.0" - -find-cache-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-cache-dir@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0, find-up@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -find-yarn-workspace-root@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== - -flow-enums-runtime@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787" - integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== - -flow-parser@0.*: - version "0.237.2" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.237.2.tgz#f3e86ab582db57e4437796e7048632646a21a46f" - integrity sha512-mvI/kdfr3l1waaPbThPA8dJa77nHXrfZIun+SWvFwSwDjmeByU7mGJGRmv1+7guU6ccyLV8e1lqZA1lD4iMGnQ== - -flow-parser@^0.206.0: - version "0.206.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef" - integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== - -follow-redirects@^1.0.0: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - -fontfaceobserver@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz#5fb392116e75d5024b7ec8e4f2ce92106d1488c8" - integrity sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -form-data@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -freeport-async@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/freeport-async/-/freeport-async-2.0.0.tgz#6adf2ec0c629d11abff92836acd04b399135bab4" - integrity sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs-extra@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3" - integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^1.0.0" - -fs-extra@^11.2.0: - version "11.2.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" - integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^8.1.0, fs-extra@~8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^9.0.0, fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - -fs-monkey@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" - integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - functions-have-names "^1.2.3" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1, get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-port@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== - -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== - dependencies: - call-bind "^1.0.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - -get-tsconfig@^4.5.0: - version "4.7.5" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" - integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== - dependencies: - resolve-pkg-maps "^1.0.0" - -getenv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/getenv/-/getenv-1.0.0.tgz#874f2e7544fbca53c7a4738f37de8605c3fcfc31" - integrity sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1, glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^10.3.10: - version "10.4.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.1.tgz#0cfb01ab6a6b438177bfe6a58e2576f6efe909c2" - integrity sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - path-scurry "^1.11.1" - -glob@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^9.3.3: - version "9.3.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" - integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== - dependencies: - fs.realpath "^1.0.0" - minimatch "^8.0.2" - minipass "^4.2.4" - path-scurry "^1.6.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globalthis@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" - integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== - dependencies: - define-properties "^1.2.1" - gopd "^1.0.1" - -globby@^11.0.1, globby@^11.0.3, globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== - dependencies: - array-union "^3.0.1" - dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" - merge2 "^1.4.1" - slash "^4.0.0" - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw== - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -graphql-tag@^2.10.1: - version "2.12.6" - resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" - integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== - dependencies: - tslib "^2.1.0" - -graphql@15.8.0: - version "15.8.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" - integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -he@1.2.0, he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hermes-estree@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.15.0.tgz#e32f6210ab18c7b705bdcb375f7700f2db15d6ba" - integrity sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ== - -hermes-estree@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.19.1.tgz#d5924f5fac2bf0532547ae9f506d6db8f3c96392" - integrity sha512-daLGV3Q2MKk8w4evNMKwS8zBE/rcpA800nu1Q5kM08IKijoSnPe9Uo1iIxzPKRkn95IxxsgBMPeYHt3VG4ej2g== - -hermes-estree@0.20.1: - version "0.20.1" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.20.1.tgz#0b9a544cf883a779a8e1444b915fa365bef7f72d" - integrity sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg== - -hermes-parser@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.15.0.tgz#f611a297c2a2dbbfbce8af8543242254f604c382" - integrity sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q== - dependencies: - hermes-estree "0.15.0" - -hermes-parser@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.19.1.tgz#1044348097165b7c93dc198a80b04ed5130d6b1a" - integrity sha512-Vp+bXzxYJWrpEuJ/vXxUsLnt0+y4q9zyi4zUlkLqD8FKv4LjIfOvP69R/9Lty3dCyKh0E2BU7Eypqr63/rKT/A== - dependencies: - hermes-estree "0.19.1" - -hermes-parser@0.20.1: - version "0.20.1" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.20.1.tgz#ad10597b99f718b91e283f81cbe636c50c3cff92" - integrity sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA== - dependencies: - hermes-estree "0.20.1" - -hermes-profile-transformer@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" - integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== - dependencies: - source-map "^0.7.3" - -hosted-git-info@^3.0.2: - version "3.0.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d" - integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw== - dependencies: - lru-cache "^6.0.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -html-entities@^2.3.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" - integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== - -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== - dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.10.0" - -html-webpack-plugin@^5.5.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" - integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== - dependencies: - "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.8" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" - integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== - -http-proxy-middleware@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== - dependencies: - "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -https-proxy-agent@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -hyphenate-style-name@^1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.5.tgz#70b68605ee601b7142362239a0236159a8b2dc33" - integrity sha512-fedL7PRwmeVkgyhu9hLeTBaI6wcGk7JGJswdaRsa5aUbkXI1kr1xZwTPBtaYPpwf56878iDek6VbVnuWMebJmw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.1.9, ignore@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - -image-size@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.1.1.tgz#ddd67d4dc340e52ac29ce5f546a09f4e29e840ac" - integrity sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ== - dependencies: - queue "6.0.2" - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inline-style-prefixer@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz#4290ed453ab0e4441583284ad86e41ad88384f44" - integrity sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg== - dependencies: - css-in-js-utils "^3.1.0" - fast-loops "^1.1.3" - -internal-ip@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== - -ip@^1.1.5: - version "1.1.9" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" - integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== - -ipaddr.js@1.9.1, ipaddr.js@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -ipaddr.js@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" - integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== - -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-async-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" - integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== - dependencies: - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-buffer@~1.1.1, is-buffer@~1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== - dependencies: - is-typed-array "^1.1.13" - -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== - dependencies: - call-bind "^1.0.2" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg== - dependencies: - is-extglob "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - -is-invalid-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-invalid-path/-/is-invalid-path-0.1.0.tgz#307a855b3cf1a938b44ea70d2c61106053714f34" - integrity sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ== - dependencies: - is-glob "^2.0.0" - -is-map@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" - integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== - -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" - -is-path-inside@^3.0.2, is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-set@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" - integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== - -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== - dependencies: - call-bind "^1.0.7" - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-valid-path@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-valid-path/-/is-valid-path-0.1.1.tgz#110f9ff74c37f663e1ec7915eb451f2db93ac9df" - integrity sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A== - dependencies: - is-invalid-path "^0.1.0" - -is-weakmap@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" - integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-weakset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" - integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== - -is-wsl@^2.0.0, is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -iterator.prototype@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" - integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== - dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" - -jackspeak@^3.1.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.2.4.tgz#c00dc8bb4f93d8c1a62432b0b7d4de33f1d7ae97" - integrity sha512-uQPMuJfoph+FuccNkxAH9u0wBeuhyvpBPPfsupJ/G5RZ9kUD/sDFfzApzwMv20yd3nj40Ekizmga8iNTU4iiyQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jest-environment-node@^29.6.3: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.6.3: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - -jest-worker@^27.0.2, jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest-worker@^29.6.3: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jimp-compact@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/jimp-compact/-/jimp-compact-0.16.1.tgz#9582aea06548a2c1e04dd148d7c3ab92075aefa3" - integrity sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww== - -joi@^17.2.1: - version "17.13.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.1.tgz#9c7b53dc3b44dd9ae200255cc3b398874918a6ca" - integrity sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg== - dependencies: - "@hapi/hoek" "^9.3.0" - "@hapi/topo" "^5.1.0" - "@sideway/address" "^4.1.5" - "@sideway/formula" "^3.0.1" - "@sideway/pinpoint" "^2.0.0" - -join-component@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5" - integrity sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ== - -joycon@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" - integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsc-android@^250231.0.0: - version "250231.0.0" - resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262" - integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== - -jsc-safe-url@^0.2.2, jsc-safe-url@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz#141c14fbb43791e88d5dc64e85a374575a83477a" - integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q== - -jscodeshift@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.14.0.tgz#7542e6715d6d2e8bde0b4e883f0ccea358b46881" - integrity sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA== - dependencies: - "@babel/core" "^7.13.16" - "@babel/parser" "^7.13.16" - "@babel/plugin-proposal-class-properties" "^7.13.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" - "@babel/plugin-proposal-optional-chaining" "^7.13.12" - "@babel/plugin-transform-modules-commonjs" "^7.13.8" - "@babel/preset-flow" "^7.13.13" - "@babel/preset-typescript" "^7.13.0" - "@babel/register" "^7.13.16" - babel-core "^7.0.0-bridge.0" - chalk "^4.1.2" - flow-parser "0.*" - graceful-fs "^4.2.4" - micromatch "^4.0.4" - neo-async "^2.5.0" - node-dir "^0.1.17" - recast "^0.21.0" - temp "^0.8.4" - write-file-atomic "^2.3.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-deref-sync@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/json-schema-deref-sync/-/json-schema-deref-sync-0.13.0.tgz#cb08b4ff435a48b5a149652d7750fdd071009823" - integrity sha512-YBOEogm5w9Op337yb6pAT6ZXDqlxAsQCanM3grid8lMWNxRJO/zWEJi3ZzqDL8boWfwhTFym5EFrNgWwpqcBRg== - dependencies: - clone "^2.1.2" - dag-map "~1.0.0" - is-valid-path "^0.1.1" - lodash "^4.17.13" - md5 "~2.2.0" - memory-cache "~0.2.0" - traverse "~0.6.6" - valid-url "~1.0.9" - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2, json5@^2.2.2, json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: - version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" - integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - object.assign "^4.1.4" - object.values "^1.1.6" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -language-subtag-registry@^0.3.20: - version "0.3.23" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" - integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== - -language-tags@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" - integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== - dependencies: - language-subtag-registry "^0.3.20" - -launch-editor@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.1.tgz#f259c9ef95cbc9425620bbbd14b468fcdb4ffe3c" - integrity sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw== - dependencies: - picocolors "^1.0.0" - shell-quote "^1.8.1" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lighthouse-logger@^1.0.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz#aef90f9e97cd81db367c7634292ee22079280aaa" - integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g== - dependencies: - debug "^2.6.9" - marky "^1.2.2" - -lightningcss-darwin-arm64@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.19.0.tgz#56ab071e932f845dbb7667f44f5b78441175a343" - integrity sha512-wIJmFtYX0rXHsXHSr4+sC5clwblEMji7HHQ4Ub1/CznVRxtCFha6JIt5JZaNf8vQrfdZnBxLLC6R8pC818jXqg== - -lightningcss-darwin-x64@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz#c867308b88859ba61a2c46c82b1ca52ff73a1bd0" - integrity sha512-Lif1wD6P4poaw9c/4Uh2z+gmrWhw/HtXFoeZ3bEsv6Ia4tt8rOJBdkfVaUJ6VXmpKHALve+iTyP2+50xY1wKPw== - -lightningcss-linux-arm-gnueabihf@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.19.0.tgz#0f921dc45f2e5c3aea70fab98844ac0e5f2f81be" - integrity sha512-P15VXY5682mTXaiDtbnLYQflc8BYb774j2R84FgDLJTN6Qp0ZjWEFyN1SPqyfTj2B2TFjRHRUvQSSZ7qN4Weig== - -lightningcss-linux-arm64-gnu@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.19.0.tgz#027f9df9c7f4ffa127c37a71726245a5794d7ba2" - integrity sha512-zwXRjWqpev8wqO0sv0M1aM1PpjHz6RVIsBcxKszIG83Befuh4yNysjgHVplF9RTU7eozGe3Ts7r6we1+Qkqsww== - -lightningcss-linux-arm64-musl@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.19.0.tgz#85ea987da868524eac6db94f8e1eaa23d0b688a3" - integrity sha512-vSCKO7SDnZaFN9zEloKSZM5/kC5gbzUjoJQ43BvUpyTFUX7ACs/mDfl2Eq6fdz2+uWhUh7vf92c4EaaP4udEtA== - -lightningcss-linux-x64-gnu@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.19.0.tgz#02bec89579ab4153dccc0def755d1fd9e3ee7f3c" - integrity sha512-0AFQKvVzXf9byrXUq9z0anMGLdZJS+XSDqidyijI5njIwj6MdbvX2UZK/c4FfNmeRa2N/8ngTffoIuOUit5eIQ== - -lightningcss-linux-x64-musl@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.19.0.tgz#e36a5df8193ae961d22974635e4c100a1823bb8c" - integrity sha512-SJoM8CLPt6ECCgSuWe+g0qo8dqQYVcPiW2s19dxkmSI5+Uu1GIRzyKA0b7QqmEXolA+oSJhQqCmJpzjY4CuZAg== - -lightningcss-win32-x64-msvc@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.19.0.tgz#0854dbd153035eca1396e2227c708ad43655a61c" - integrity sha512-C+VuUTeSUOAaBZZOPT7Etn/agx/MatzJzGRkeV+zEABmPuntv1zihncsi+AyGmjkkzq3wVedEy7h0/4S84mUtg== - -lightningcss@~1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.19.0.tgz#fbbad0975de66252e38d96b5bdd2a62f2dd0ffbf" - integrity sha512-yV5UR7og+Og7lQC+70DA7a8ta1uiOPnWPJfxa0wnxylev5qfo4P+4iMpzWAdYWOca4jdNQZii+bDL/l+4hUXIA== - dependencies: - detect-libc "^1.0.3" - optionalDependencies: - lightningcss-darwin-arm64 "1.19.0" - lightningcss-darwin-x64 "1.19.0" - lightningcss-linux-arm-gnueabihf "1.19.0" - lightningcss-linux-arm64-gnu "1.19.0" - lightningcss-linux-arm64-musl "1.19.0" - lightningcss-linux-x64-gnu "1.19.0" - lightningcss-linux-x64-musl "1.19.0" - lightningcss-win32-x64-msvc "1.19.0" - -lilconfig@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== - -lilconfig@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" - integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -load-tsconfig@^0.2.3: - version "0.2.5" - resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" - integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== - -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== - -loader-utils@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" - integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== - -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== - -lodash@^4.17.13, lodash@^4.17.20, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -logkitty@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" - integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== - dependencies: - ansi-fragments "^0.2.1" - dayjs "^1.8.15" - yargs "^15.1.0" - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lru-cache@^10.2.0: - version "10.2.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" - integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -marky@^1.2.2: - version "1.2.5" - resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" - integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== - -md5-file@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-3.2.3.tgz#f9bceb941eca2214a4c0727f5e700314e770f06f" - integrity sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw== - dependencies: - buffer-alloc "^1.1.0" - -md5@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" - integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== - dependencies: - charenc "0.0.2" - crypt "0.0.2" - is-buffer "~1.1.6" - -md5@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ== - dependencies: - charenc "~0.0.1" - crypt "~0.0.1" - is-buffer "~1.1.1" - -md5hex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/md5hex/-/md5hex-1.0.0.tgz#ed74b477a2ee9369f75efee2f08d5915e52a42e8" - integrity sha512-c2YOUbp33+6thdCUi34xIyOU/a7bvGKj/3DB1iaPMTuPHf/Q2d5s4sn1FaCOO43XkXggnb08y5W2PU8UNYNLKQ== - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -memfs@^3.4.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" - integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== - dependencies: - fs-monkey "^1.0.4" - -memoize-one@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== - -memoize-one@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" - integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== - -memory-cache@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/memory-cache/-/memory-cache-0.2.0.tgz#7890b01d52c00c8ebc9d533e1f8eb17e3034871a" - integrity sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -metro-babel-transformer@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.80.9.tgz#7051ba377b7d2140abd23f4846bbbb1e81fea99b" - integrity sha512-d76BSm64KZam1nifRZlNJmtwIgAeZhZG3fi3K+EmPOlrR8rDtBxQHDSN3fSGeNB9CirdTyabTMQCkCup6BXFSQ== - dependencies: - "@babel/core" "^7.20.0" - hermes-parser "0.20.1" - nullthrows "^1.1.1" - -metro-cache-key@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.80.9.tgz#a04cbb0a7828509bb10dde9789ef761c0c60bc3d" - integrity sha512-hRcYGhEiWIdM87hU0fBlcGr+tHDEAT+7LYNCW89p5JhErFt/QaAkVx4fb5bW3YtXGv5BTV7AspWPERoIb99CXg== - -metro-cache@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.80.9.tgz#b914318a90dbcd51b4c27836184519c441ba5123" - integrity sha512-ujEdSI43QwI+Dj2xuNax8LMo8UgKuXJEdxJkzGPU6iIx42nYa1byQ+aADv/iPh5sh5a//h5FopraW5voXSgm2w== - dependencies: - metro-core "0.80.9" - rimraf "^3.0.2" - -metro-config@0.80.9, metro-config@^0.80.0, metro-config@^0.80.3: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.80.9.tgz#4eb6948b0ddc7c38d9d4ba8ddf22a67ca1c2bc06" - integrity sha512-28wW7CqS3eJrunRGnsibWldqgwRP9ywBEf7kg+uzUHkSFJNKPM1K3UNSngHmH0EZjomizqQA2Zi6/y6VdZMolg== - dependencies: - connect "^3.6.5" - cosmiconfig "^5.0.5" - jest-validate "^29.6.3" - metro "0.80.9" - metro-cache "0.80.9" - metro-core "0.80.9" - metro-runtime "0.80.9" - -metro-core@0.80.9, metro-core@^0.80.0, metro-core@^0.80.3: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.80.9.tgz#3af21d0b09d71ec9c0840f028bffb36bc3619727" - integrity sha512-tbltWQn+XTdULkGdzHIxlxk4SdnKxttvQQV3wpqqFbHDteR4gwCyTR2RyYJvxgU7HELfHtrVbqgqAdlPByUSbg== - dependencies: - lodash.throttle "^4.1.1" - metro-resolver "0.80.9" - -metro-file-map@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.80.9.tgz#ed8783f6e35dfc005794344c2a9fcd6e914885aa" - integrity sha512-sBUjVtQMHagItJH/wGU9sn3k2u0nrCl0CdR4SFMO1tksXLKbkigyQx4cbpcyPVOAmGTVuy3jyvBlELaGCAhplQ== - dependencies: - anymatch "^3.0.3" - debug "^2.2.0" - fb-watchman "^2.0.0" - graceful-fs "^4.2.4" - invariant "^2.2.4" - jest-worker "^29.6.3" - micromatch "^4.0.4" - node-abort-controller "^3.1.1" - nullthrows "^1.1.1" - walker "^1.0.7" - optionalDependencies: - fsevents "^2.3.2" - -metro-minify-terser@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.80.9.tgz#2b7798cba2bd4bd69cc5ce05a45bf66291542f83" - integrity sha512-FEeCeFbkvvPuhjixZ1FYrXtO0araTpV6UbcnGgDUpH7s7eR5FG/PiJz3TsuuPP/HwCK19cZtQydcA2QrCw446A== - dependencies: - terser "^5.15.0" - -metro-react-native-babel-preset@0.76.8: - version "0.76.8" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.76.8.tgz#7476efae14363cbdfeeec403b4f01d7348e6c048" - integrity sha512-Ptza08GgqzxEdK8apYsjTx2S8WDUlS2ilBlu9DR1CUcHmg4g3kOkFylZroogVAUKtpYQNYwAvdsjmrSdDNtiAg== - dependencies: - "@babel/core" "^7.20.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-class-properties" "^7.18.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" - "@babel/plugin-proposal-numeric-separator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.20.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.18.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.20.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.20.0" - "@babel/plugin-transform-flow-strip-types" "^7.20.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-self" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.5.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - babel-plugin-transform-flow-enums "^0.0.2" - react-refresh "^0.4.0" - -metro-resolver@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.9.tgz#bae9120a0553e0cb59da6429e83a7e97465cc1a8" - integrity sha512-wAPIjkN59BQN6gocVsAvvpZ1+LQkkqUaswlT++cJafE/e54GoVkMNCmrR4BsgQHr9DknZ5Um/nKueeN7kaEz9w== - -metro-runtime@0.80.9, metro-runtime@^0.80.0, metro-runtime@^0.80.3: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.80.9.tgz#665312bd4e4d38fea921b3153d6ab47846eb4f08" - integrity sha512-8PTVIgrVcyU+X/rVCy/9yxNlvXsBCk5JwwkbAm/Dm+Abo6NBGtNjWF0M1Xo/NWCb4phamNWcD7cHdR91HhbJvg== - dependencies: - "@babel/runtime" "^7.0.0" - -metro-source-map@0.80.9, metro-source-map@^0.80.0, metro-source-map@^0.80.3: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.80.9.tgz#df8f673137548f37ab9f9dcfa771b354a452cfab" - integrity sha512-RMn+XS4VTJIwMPOUSj61xlxgBvPeY4G6s5uIn6kt6HB6A/k9ekhr65UkkDD7WzHYs3a9o869qU8tvOZvqeQzgw== - dependencies: - "@babel/traverse" "^7.20.0" - "@babel/types" "^7.20.0" - invariant "^2.2.4" - metro-symbolicate "0.80.9" - nullthrows "^1.1.1" - ob1 "0.80.9" - source-map "^0.5.6" - vlq "^1.0.0" - -metro-symbolicate@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.80.9.tgz#8d1d19d26ebb36b9d13dbd29814fdd71d6009db7" - integrity sha512-Ykae12rdqSs98hg41RKEToojuIW85wNdmSe/eHUgMkzbvCFNVgcC0w3dKZEhSsqQOXapXRlLtHkaHLil0UD/EA== - dependencies: - invariant "^2.2.4" - metro-source-map "0.80.9" - nullthrows "^1.1.1" - source-map "^0.5.6" - through2 "^2.0.1" - vlq "^1.0.0" - -metro-transform-plugins@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.80.9.tgz#473a2c0a9e48043210547abe61cdeedb77725422" - integrity sha512-UlDk/uc8UdfLNJhPbF3tvwajyuuygBcyp+yBuS/q0z3QSuN/EbLllY3rK8OTD9n4h00qZ/qgxGv/lMFJkwP4vg== - dependencies: - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.20.0" - nullthrows "^1.1.1" - -metro-transform-worker@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.80.9.tgz#f1d8ef4f77228bb7e1d20d3c06934166e8ee3b28" - integrity sha512-c/IrzMUVnI0hSVVit4TXzt3A1GiUltGVlzCmLJWxNrBGHGrJhvgePj38+GXl1Xf4Fd4vx6qLUkKMQ3ux73bFLQ== - dependencies: - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/parser" "^7.20.0" - "@babel/types" "^7.20.0" - metro "0.80.9" - metro-babel-transformer "0.80.9" - metro-cache "0.80.9" - metro-cache-key "0.80.9" - metro-minify-terser "0.80.9" - metro-source-map "0.80.9" - metro-transform-plugins "0.80.9" - nullthrows "^1.1.1" - -metro@0.80.9, metro@^0.80.0, metro@^0.80.3: - version "0.80.9" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.80.9.tgz#de3c2011df62036520d51d040d2dde0d015aecb6" - integrity sha512-Bc57Xf3GO2Xe4UWQsBj/oW6YfLPABEu8jfDVDiNmJvoQW4CO34oDPuYKe4KlXzXhcuNsqOtSxpbjCRRVjhhREg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/parser" "^7.20.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.20.0" - "@babel/types" "^7.20.0" - accepts "^1.3.7" - chalk "^4.0.0" - ci-info "^2.0.0" - connect "^3.6.5" - debug "^2.2.0" - denodeify "^1.2.1" - error-stack-parser "^2.0.6" - graceful-fs "^4.2.4" - hermes-parser "0.20.1" - image-size "^1.0.2" - invariant "^2.2.4" - jest-worker "^29.6.3" - jsc-safe-url "^0.2.2" - lodash.throttle "^4.1.1" - metro-babel-transformer "0.80.9" - metro-cache "0.80.9" - metro-cache-key "0.80.9" - metro-config "0.80.9" - metro-core "0.80.9" - metro-file-map "0.80.9" - metro-resolver "0.80.9" - metro-runtime "0.80.9" - metro-source-map "0.80.9" - metro-symbolicate "0.80.9" - metro-transform-plugins "0.80.9" - metro-transform-worker "0.80.9" - mime-types "^2.1.27" - node-fetch "^2.2.0" - nullthrows "^1.1.1" - rimraf "^3.0.2" - serialize-error "^2.1.0" - source-map "^0.5.6" - strip-ansi "^6.0.0" - throat "^5.0.0" - ws "^7.5.1" - yargs "^17.6.2" - -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.4.1, mime@^2.4.4: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mini-css-extract-plugin@^2.5.2: - version "2.9.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz#c73a1327ccf466f69026ac22a8e8fd707b78a235" - integrity sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA== - dependencies: - schema-utils "^4.0.0" - tapable "^2.2.1" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^8.0.2: - version "8.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" - integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass@3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== - dependencies: - yallist "^4.0.0" - -minipass@^3.0.0, minipass@^3.1.1: - version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" - integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== - dependencies: - yallist "^4.0.0" - -minipass@^4.2.4: - version "4.2.8" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" - integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== - -minipass@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" - integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mkdirp@^1.0.3, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns@^7.2.5: - version "7.2.5" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" - integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== - dependencies: - dns-packet "^5.2.2" - thunky "^1.0.2" - -mv@~2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" - integrity sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg== - dependencies: - mkdirp "~0.5.1" - ncp "~2.0.0" - rimraf "~2.4.0" - -mz@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nanoid@^3.3.6, nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -ncp@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.5.0, neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nested-error-stacks@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz#d2cc9fc5235ddb371fc44d506234339c8e4b0a4b" - integrity sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A== - -next@^14.0.4: - version "14.2.3" - resolved "https://registry.yarnpkg.com/next/-/next-14.2.3.tgz#f117dd5d5f20c307e7b8e4f9c1c97d961008925d" - integrity sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A== - dependencies: - "@next/env" "14.2.3" - "@swc/helpers" "0.5.5" - busboy "1.6.0" - caniuse-lite "^1.0.30001579" - graceful-fs "^4.2.11" - postcss "8.4.31" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-darwin-arm64" "14.2.3" - "@next/swc-darwin-x64" "14.2.3" - "@next/swc-linux-arm64-gnu" "14.2.3" - "@next/swc-linux-arm64-musl" "14.2.3" - "@next/swc-linux-x64-gnu" "14.2.3" - "@next/swc-linux-x64-musl" "14.2.3" - "@next/swc-win32-arm64-msvc" "14.2.3" - "@next/swc-win32-ia32-msvc" "14.2.3" - "@next/swc-win32-x64-msvc" "14.2.3" - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -nocache@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.4.tgz#5b37a56ec6e09fc7d401dceaed2eab40c8bfdf79" - integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== - -node-abort-controller@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" - integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== - -node-dir@^0.1.17: - version "0.1.17" - resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" - integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== - dependencies: - minimatch "^3.0.2" - -node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-forge@^1, node-forge@^1.2.1, node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - -node-html-parser@^5.2.0: - version "5.4.2" - resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-5.4.2.tgz#93e004038c17af80226c942336990a0eaed8136a" - integrity sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw== - dependencies: - css-select "^4.2.1" - he "1.2.0" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -node-stream-zip@^1.9.1: - version "1.15.0" - resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" - integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -npm-package-arg@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-7.0.0.tgz#52cdf08b491c0c59df687c4c925a89102ef794a5" - integrity sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g== - dependencies: - hosted-git-info "^3.0.2" - osenv "^0.1.5" - semver "^5.6.0" - validate-npm-package-name "^3.0.0" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== - dependencies: - path-key "^2.0.0" - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nth-check@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" - integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== - dependencies: - boolbase "^1.0.0" - -nullthrows@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" - integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== - -ob1@0.80.9: - version "0.80.9" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.9.tgz#4ae3edd807536097674ff943509089f5d4e0649f" - integrity sha512-v9yOxowkZbxWhKOaaTyLjIm1aLy4ebMNcSn4NYJKOAI/Qv+SkfEfszpLr2GIxsccmb2Y2HA9qtsqiIJ80ucpVA== - -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4, object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.entries@^1.1.7, object.entries@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" - integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -object.fromentries@^2.0.7, object.fromentries@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" - integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.groupby@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" - integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - -object.hasown@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" - integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== - dependencies: - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" - integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - -onetime@^5.1.0, onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -open@^6.2.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" - integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== - dependencies: - is-wsl "^1.1.0" - -open@^7.0.3: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -open@^8.0.4, open@^8.0.9, open@^8.3.0: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - -optionator@^0.9.3: - version "0.9.4" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.5" - -ora@3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" - integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== - dependencies: - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-spinners "^2.0.0" - log-symbols "^2.2.0" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - -ora@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== - dependencies: - bl "^4.1.0" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.5.0" - is-interactive "^1.0.0" - is-unicode-supported "^0.1.0" - log-symbols "^4.1.0" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -osenv@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-retry@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== - dependencies: - "@types/retry" "0.12.0" - retry "^0.13.1" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-png@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/parse-png/-/parse-png-2.1.0.tgz#2a42ad719fedf90f81c59ebee7ae59b280d6b338" - integrity sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ== - dependencies: - pngjs "^3.3.0" - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -password-prompt@^1.0.4: - version "1.1.3" - resolved "https://registry.yarnpkg.com/password-prompt/-/password-prompt-1.1.3.tgz#05e539f4e7ca4d6c865d479313f10eb9db63ee5f" - integrity sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw== - dependencies: - ansi-escapes "^4.3.2" - cross-spawn "^7.0.3" - -path-browserify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.5, path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.11.1, path-scurry@^1.6.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0, picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== - -pirates@^4.0.1, pirates@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -plist@^3.0.5: - version "3.1.0" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9" - integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== - dependencies: - "@xmldom/xmldom" "^0.8.8" - base64-js "^1.5.1" - xmlbuilder "^15.1.1" - -pngjs@^3.3.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" - integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== - -possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== - -postcss-calc@^8.2.3: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== - dependencies: - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - -postcss-colormin@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f" - integrity sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - colord "^2.9.1" - postcss-value-parser "^4.2.0" - -postcss-convert-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" - integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== - dependencies: - browserslist "^4.21.4" - postcss-value-parser "^4.2.0" - -postcss-discard-comments@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" - integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== - -postcss-discard-duplicates@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" - integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== - -postcss-discard-empty@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" - integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== - -postcss-discard-overridden@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" - integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== - -postcss-load-config@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" - integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== - dependencies: - lilconfig "^3.0.0" - yaml "^2.3.4" - -postcss-merge-longhand@^5.1.7: - version "5.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" - integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^5.1.1" - -postcss-merge-rules@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c" - integrity sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - cssnano-utils "^3.1.0" - postcss-selector-parser "^6.0.5" - -postcss-minify-font-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" - integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-minify-gradients@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" - integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== - dependencies: - colord "^2.9.1" - cssnano-utils "^3.1.0" - postcss-value-parser "^4.2.0" - -postcss-minify-params@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" - integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== - dependencies: - browserslist "^4.21.4" - cssnano-utils "^3.1.0" - postcss-value-parser "^4.2.0" - -postcss-minify-selectors@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" - integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-modules-extract-imports@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" - integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== - -postcss-modules-local-by-default@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" - integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" - integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== - dependencies: - postcss-selector-parser "^6.0.4" - -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== - dependencies: - icss-utils "^5.0.0" - -postcss-normalize-charset@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" - integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== - -postcss-normalize-display-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" - integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-positions@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" - integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-repeat-style@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" - integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-string@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" - integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-timing-functions@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" - integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-unicode@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" - integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== - dependencies: - browserslist "^4.21.4" - postcss-value-parser "^4.2.0" - -postcss-normalize-url@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" - integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== - dependencies: - normalize-url "^6.0.1" - postcss-value-parser "^4.2.0" - -postcss-normalize-whitespace@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" - integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-ordered-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" - integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== - dependencies: - cssnano-utils "^3.1.0" - postcss-value-parser "^4.2.0" - -postcss-reduce-initial@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6" - integrity sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - -postcss-reduce-transforms@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" - integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" - integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-svgo@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" - integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== - dependencies: - postcss-value-parser "^4.2.0" - svgo "^2.7.0" - -postcss-unique-selectors@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" - integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -postcss@8.4.31: - version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -postcss@^8.3.5, postcss@^8.4.33, postcss@~8.4.21: - version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier@^3.1.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.0.tgz#d173ea0524a691d4c0b1181752f2b46724328cdf" - integrity sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g== - -pretty-bytes@5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" - integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== - -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== - dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" - -pretty-format@^26.5.2, pretty-format@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" - integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== - dependencies: - "@jest/types" "^26.6.2" - ansi-regex "^5.0.0" - ansi-styles "^4.0.0" - react-is "^17.0.1" - -pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== - dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -progress@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== - -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -promise@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" - integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== - dependencies: - asap "~2.0.6" - -prompts@^2.3.2, prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -qrcode-terminal@0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz#ffc6c28a2fc0bfb47052b47e23f4f446a5fbdb9e" - integrity sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -querystring@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" - integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== - -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -queue@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" - integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== - dependencies: - inherits "~2.0.3" - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.0.1, rc@^1.1.6, rc@~1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-devtools-core@^4.27.7: - version "4.28.5" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.5.tgz#c8442b91f068cdf0c899c543907f7f27d79c2508" - integrity sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA== - dependencies: - shell-quote "^1.6.1" - ws "^7" - -react-devtools-core@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-5.2.0.tgz#072ecd2d84d3653817cc11e4b16f60a3c2b705f9" - integrity sha512-vZK+/gvxxsieAoAyYaiRIVFxlajb7KXhgBDV7OsoMzaAE+IqGpoxusBjIgq5ibqA2IloKu0p9n7tE68z1xs18A== - dependencies: - shell-quote "^1.6.1" - ws "^7" - -react-dom@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" - integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.2" - -"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" - integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - -react-native-web@^0.19.10: - version "0.19.12" - resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.19.12.tgz#30d1fd70bdff7886f43c0c2698629d830fade6bc" - integrity sha512-o2T0oztoVDQjztt4YksO9S1XRjoH/AqcSvifgWLrPJgGVbMWsfhILgl6lfUdEamVZzZSVV/2gqDVMAk/qq7mZw== - dependencies: - "@babel/runtime" "^7.18.6" - "@react-native/normalize-colors" "^0.74.1" - fbjs "^3.0.4" - inline-style-prefixer "^6.0.1" - memoize-one "^6.0.0" - nullthrows "^1.1.1" - postcss-value-parser "^4.2.0" - styleq "^0.1.3" - -react-native@*: - version "0.74.2" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.74.2.tgz#172e64e4e79861e2b3da99b86999e4a4c55b8321" - integrity sha512-EBMBjPPL4/GjHMP4NqsZabT3gI5WU9cSmduABGAGrd8uIcmTZ5F2Ng9k6gFmRm7n8e8CULxDNu98ZpQfBjl7Bw== - dependencies: - "@jest/create-cache-key-function" "^29.6.3" - "@react-native-community/cli" "13.6.8" - "@react-native-community/cli-platform-android" "13.6.8" - "@react-native-community/cli-platform-ios" "13.6.8" - "@react-native/assets-registry" "0.74.84" - "@react-native/codegen" "0.74.84" - "@react-native/community-cli-plugin" "0.74.84" - "@react-native/gradle-plugin" "0.74.84" - "@react-native/js-polyfills" "0.74.84" - "@react-native/normalize-colors" "0.74.84" - "@react-native/virtualized-lists" "0.74.84" - abort-controller "^3.0.0" - anser "^1.4.9" - ansi-regex "^5.0.0" - base64-js "^1.5.1" - chalk "^4.0.0" - event-target-shim "^5.0.1" - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - jest-environment-node "^29.6.3" - jsc-android "^250231.0.0" - memoize-one "^5.0.0" - metro-runtime "^0.80.3" - metro-source-map "^0.80.3" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - pretty-format "^26.5.2" - promise "^8.3.0" - react-devtools-core "^5.0.0" - react-refresh "^0.14.0" - react-shallow-renderer "^16.15.0" - regenerator-runtime "^0.13.2" - scheduler "0.24.0-canary-efb381bbf-20230505" - stacktrace-parser "^0.1.10" - whatwg-fetch "^3.0.0" - ws "^6.2.2" - yargs "^17.6.2" - -react-native@0.73.1: - version "0.73.1" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.1.tgz#5eafaa7e54feeab8b55e8b8e4efc4d21052a4fff" - integrity sha512-nLl9O2yKRh1nMXwsk4SUiD0ddd19RqlKgNU9AU8bTK/zD2xwnVOG56YK1/22SN67niWyoeG83vVg1eTk+S6ReA== - dependencies: - "@jest/create-cache-key-function" "^29.6.3" - "@react-native-community/cli" "12.3.0" - "@react-native-community/cli-platform-android" "12.3.0" - "@react-native-community/cli-platform-ios" "12.3.0" - "@react-native/assets-registry" "^0.73.1" - "@react-native/codegen" "^0.73.2" - "@react-native/community-cli-plugin" "0.73.11" - "@react-native/gradle-plugin" "^0.73.4" - "@react-native/js-polyfills" "^0.73.1" - "@react-native/normalize-colors" "^0.73.2" - "@react-native/virtualized-lists" "^0.73.4" - abort-controller "^3.0.0" - anser "^1.4.9" - ansi-regex "^5.0.0" - base64-js "^1.5.1" - deprecated-react-native-prop-types "^5.0.0" - event-target-shim "^5.0.1" - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - jest-environment-node "^29.6.3" - jsc-android "^250231.0.0" - memoize-one "^5.0.0" - metro-runtime "^0.80.0" - metro-source-map "^0.80.0" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - pretty-format "^26.5.2" - promise "^8.3.0" - react-devtools-core "^4.27.7" - react-refresh "^0.14.0" - react-shallow-renderer "^16.15.0" - regenerator-runtime "^0.13.2" - scheduler "0.24.0-canary-efb381bbf-20230505" - stacktrace-parser "^0.1.10" - whatwg-fetch "^3.0.0" - ws "^6.2.2" - yargs "^17.6.2" - -react-native@^0.73.1: - version "0.73.8" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.8.tgz#e514bc3ecd466560b42e79c8844f356195aba5a3" - integrity sha512-EPURbV36NW5H0eVTmePtwuMJfxFvFokEgbaw61pCqdeOLeaGVxsU54RK8RIXpehzPuTGpQVVxTUKbvaM7F+TTw== - dependencies: - "@jest/create-cache-key-function" "^29.6.3" - "@react-native-community/cli" "12.3.6" - "@react-native-community/cli-platform-android" "12.3.6" - "@react-native-community/cli-platform-ios" "12.3.6" - "@react-native/assets-registry" "0.73.1" - "@react-native/codegen" "0.73.3" - "@react-native/community-cli-plugin" "0.73.17" - "@react-native/gradle-plugin" "0.73.4" - "@react-native/js-polyfills" "0.73.1" - "@react-native/normalize-colors" "0.73.2" - "@react-native/virtualized-lists" "0.73.4" - abort-controller "^3.0.0" - anser "^1.4.9" - ansi-regex "^5.0.0" - base64-js "^1.5.1" - chalk "^4.0.0" - deprecated-react-native-prop-types "^5.0.0" - event-target-shim "^5.0.1" - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - jest-environment-node "^29.6.3" - jsc-android "^250231.0.0" - memoize-one "^5.0.0" - metro-runtime "^0.80.3" - metro-source-map "^0.80.3" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - pretty-format "^26.5.2" - promise "^8.3.0" - react-devtools-core "^4.27.7" - react-refresh "^0.14.0" - react-shallow-renderer "^16.15.0" - regenerator-runtime "^0.13.2" - scheduler "0.24.0-canary-efb381bbf-20230505" - stacktrace-parser "^0.1.10" - whatwg-fetch "^3.0.0" - ws "^6.2.2" - yargs "^17.6.2" - -react-refresh@^0.14.0: - version "0.14.2" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" - integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== - -react-refresh@^0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" - integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== - -react-shallow-renderer@^16.15.0: - version "16.15.0" - resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" - integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== - dependencies: - object-assign "^4.1.1" - react-is "^16.12.0 || ^17.0.0 || ^18.0.0" - -react@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== - dependencies: - loose-envify "^1.1.0" - -readable-stream@^2.0.1, readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -readline@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" - integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== - -recast@^0.21.0: - version "0.21.5" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.21.5.tgz#e8cd22bb51bcd6130e54f87955d33a2b2e57b495" - integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg== - dependencies: - ast-types "0.15.2" - esprima "~4.0.0" - source-map "~0.6.1" - tslib "^2.0.1" - -reflect.getprototypeof@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" - integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.1" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" - -regenerate-unicode-properties@^10.1.0: - version "10.1.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" - integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.2: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== - dependencies: - "@babel/runtime" "^7.8.4" - -regexp.prototype.flags@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== - dependencies: - call-bind "^1.0.6" - define-properties "^1.2.1" - es-errors "^1.3.0" - set-function-name "^2.0.1" - -regexpu-core@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" - integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== - dependencies: - "@babel/regjsgen" "^0.8.0" - regenerate "^1.4.2" - regenerate-unicode-properties "^10.1.0" - regjsparser "^0.9.1" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.1.0" - -registry-auth-token@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" - integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA== - dependencies: - rc "^1.0.1" - -regjsparser@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" - integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== - dependencies: - jsesc "~0.5.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== - -remove-trailing-slash@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz#be2285a59f39c74d1bce4f825950061915e3780d" - integrity sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA== - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -requireg@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/requireg/-/requireg-0.2.2.tgz#437e77a5316a54c9bcdbbf5d1f755fe093089830" - integrity sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg== - dependencies: - nested-error-stacks "~2.0.1" - rc "~1.2.7" - resolve "~1.7.1" - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -reselect@^4.1.7: - version "4.1.8" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" - integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve@^1.14.2, resolve@^1.22.4, resolve@^1.22.8: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.5: - version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" - integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@~1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" - integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== - dependencies: - path-parse "^1.0.5" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^2.6.2, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rimraf@~2.4.0: - version "2.4.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" - integrity sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ== - dependencies: - glob "^6.0.1" - -rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rollup@^4.0.2: - version "4.18.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.18.0.tgz#497f60f0c5308e4602cf41136339fbf87d5f5dda" - integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg== - dependencies: - "@types/estree" "1.0.5" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.18.0" - "@rollup/rollup-android-arm64" "4.18.0" - "@rollup/rollup-darwin-arm64" "4.18.0" - "@rollup/rollup-darwin-x64" "4.18.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.18.0" - "@rollup/rollup-linux-arm-musleabihf" "4.18.0" - "@rollup/rollup-linux-arm64-gnu" "4.18.0" - "@rollup/rollup-linux-arm64-musl" "4.18.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.18.0" - "@rollup/rollup-linux-riscv64-gnu" "4.18.0" - "@rollup/rollup-linux-s390x-gnu" "4.18.0" - "@rollup/rollup-linux-x64-gnu" "4.18.0" - "@rollup/rollup-linux-x64-musl" "4.18.0" - "@rollup/rollup-win32-arm64-msvc" "4.18.0" - "@rollup/rollup-win32-ia32-msvc" "4.18.0" - "@rollup/rollup-win32-x64-msvc" "4.18.0" - fsevents "~2.3.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-json-stringify@~1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" - integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== - -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-regex "^1.1.4" - -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@>=0.6.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" - integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== - -scheduler@0.24.0-canary-efb381bbf-20230505: - version "0.24.0-canary-efb381bbf-20230505" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz#5dddc60e29f91cd7f8b983d7ce4a99c2202d178f" - integrity sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA== - dependencies: - loose-envify "^1.1.0" - -scheduler@^0.23.2: - version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== - dependencies: - loose-envify "^1.1.0" - -schema-utils@^2.6.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== - dependencies: - "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" - -schema-utils@^3.1.1, schema-utils@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -schema-utils@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" - integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== - dependencies: - "@types/json-schema" "^7.0.9" - ajv "^8.9.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.1.0" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== - -selfsigned@^2.1.1, selfsigned@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" - integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== - dependencies: - "@types/node-forge" "^1.3.0" - node-forge "^1" - -semver@7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - -semver@7.5.3: - version "7.5.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" - integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== - dependencies: - lru-cache "^6.0.0" - -semver@^5.5.0, semver@^5.6.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.0.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.5, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -semver@~7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -send@0.18.0, send@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serialize-error@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-6.0.0.tgz#ccfb887a1dd1c48d6d52d7863b92544331fd752b" - integrity sha512-3vmBkMZLQO+BR4RPHcyRGdE09XCF6cvxzk2N2qn8Er3F91cy8Qt7VvEbZBOpaL53qsBbe2cFOefU6tRY6WDelA== - dependencies: - type-fest "^0.12.0" - -serialize-error@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" - integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== - -serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.15.0, serve-static@^1.13.1: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.1, set-function-name@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.6.1, shell-quote@^1.7.3, shell-quote@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" - integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== - -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -simple-plist@^1.1.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.1.tgz#16e1d8f62c6c9b691b8383127663d834112fb017" - integrity sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw== - dependencies: - bplist-creator "0.1.0" - bplist-parser "0.3.1" - plist "^3.0.5" - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -slice-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -slugify@^1.3.4: - version "1.6.6" - resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b" - integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw== - -sockjs@^0.3.24: - version "0.3.24" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -source-list-map@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - -source-map-loader@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.2.tgz#af23192f9b344daa729f6772933194cc5fa54fee" - integrity sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg== - dependencies: - abab "^2.0.5" - iconv-lite "^0.6.3" - source-map-js "^1.0.1" - -source-map-support@^0.5.16, source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@0.8.0-beta.0: - version "0.8.0-beta.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" - integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== - dependencies: - whatwg-url "^7.0.0" - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.7.3: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -split@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -stackframe@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" - integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== - -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -"statuses@>= 1.4.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - -stream-buffers@2.2.x: - version "2.2.0" - resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" - integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.matchall@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" - integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - regexp.prototype.flags "^1.5.2" - set-function-name "^2.0.2" - side-channel "^1.0.6" - -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-object-atoms "^1.0.0" - -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string.prototype.trimstart@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" - integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^5.0.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -strnum@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== - -structured-headers@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/structured-headers/-/structured-headers-0.4.1.tgz#77abd9410622c6926261c09b9d16cf10592694d1" - integrity sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg== - -style-loader@^3.3.1: - version "3.3.4" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7" - integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -stylehacks@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" - integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== - dependencies: - browserslist "^4.21.4" - postcss-selector-parser "^6.0.4" - -styleq@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/styleq/-/styleq-0.1.3.tgz#8efb2892debd51ce7b31dc09c227ad920decab71" - integrity sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA== - -sucrase@^3.20.0, sucrase@^3.20.3: - version "3.35.0" - resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" - integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== - dependencies: - "@jridgewell/gen-mapping" "^0.3.2" - commander "^4.0.0" - glob "^10.3.10" - lines-and-columns "^1.1.6" - mz "^2.7.0" - pirates "^4.0.1" - ts-interface-checker "^0.1.9" - -sudo-prompt@9.1.1: - version "9.1.1" - resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.1.1.tgz#73853d729770392caec029e2470db9c221754db0" - integrity sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA== - -sudo-prompt@^8.2.0: - version "8.2.5" - resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-8.2.5.tgz#cc5ef3769a134bb94b24a631cc09628d4d53603e" - integrity sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw== - -sudo-prompt@^9.0.0: - version "9.2.1" - resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" - integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.0.0, supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-hyperlinks@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" - integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -svgo@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== - dependencies: - "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - picocolors "^1.0.0" - stable "^0.1.8" - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -tar@^6.0.2, tar@^6.0.5: - version "6.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" - integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^5.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - -temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== - -temp-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" - integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== - -temp@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" - integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== - dependencies: - rimraf "~2.6.2" - -tempy@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.3.0.tgz#6f6c5b295695a16130996ad5ab01a8bd726e8bf8" - integrity sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ== - dependencies: - temp-dir "^1.0.0" - type-fest "^0.3.1" - unique-string "^1.0.0" - -tempy@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.7.1.tgz#5a654e6dbd1747cdd561efb112350b55cd9c1d46" - integrity sha512-vXPxwOyaNVi9nyczO16mxmHGpl6ASC5/TVhRRHpqeYHvKQm58EaWNvZXxAhR0lYYnBOQFjXjhzeLsaXdjxLjRg== - dependencies: - del "^6.0.0" - is-stream "^2.0.0" - temp-dir "^2.0.0" - type-fest "^0.16.0" - unique-string "^2.0.0" - -terminal-link@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" - integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== - dependencies: - ansi-escapes "^4.2.1" - supports-hyperlinks "^2.0.0" - -terser-webpack-plugin@^5.3.0, terser-webpack-plugin@^5.3.10: - version "5.3.10" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" - integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.20" - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.26.0" - -terser@^5.10.0, terser@^5.15.0, terser@^5.26.0: - version "5.31.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.0.tgz#06eef86f17007dbad4593f11a574c7f5eb02c6a1" - integrity sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -thenify-all@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.1" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" - integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== - dependencies: - any-promise "^1.0.0" - -throat@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" - integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== - -through2@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@2: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== - dependencies: - punycode "^2.1.0" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -traverse@~0.6.6: - version "0.6.9" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.9.tgz#76cfdbacf06382d460b76f8b735a44a6209d8b81" - integrity sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg== - dependencies: - gopd "^1.0.1" - typedarray.prototype.slice "^1.0.3" - which-typed-array "^1.1.15" - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -ts-api-utils@^1.0.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - -ts-interface-checker@^0.1.9: - version "0.1.13" - resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" - integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== - -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -tsup@^8.0.1: - version "8.1.0" - resolved "https://registry.yarnpkg.com/tsup/-/tsup-8.1.0.tgz#354ce9def1721f5029564382ea2a42dc67fbb489" - integrity sha512-UFdfCAXukax+U6KzeTNO2kAARHcWxmKsnvSPXUcfA1D+kU05XDccCrkffCQpFaWDsZfV0jMyTsxU39VfCp6EOg== - dependencies: - bundle-require "^4.0.0" - cac "^6.7.12" - chokidar "^3.5.1" - debug "^4.3.1" - esbuild "^0.21.4" - execa "^5.0.0" - globby "^11.0.3" - joycon "^3.0.1" - postcss-load-config "^4.0.1" - resolve-from "^5.0.0" - rollup "^4.0.2" - source-map "0.8.0-beta.0" - sucrase "^3.20.3" - tree-kill "^1.2.2" - -turbo-darwin-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.0.3.tgz#52c5f79b4027dfd0184fb963da41bf989be4a00d" - integrity sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q== - -turbo-darwin-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.3.tgz#46fa54d0cd95782ac38015e3396d59cdbdeb1eb8" - integrity sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw== - -turbo-linux-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.0.3.tgz#17d6714b32381d474ef2ee5613343165f9bd75bc" - integrity sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q== - -turbo-linux-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.0.3.tgz#4f1bfe421dcecf2fb1164a1e223ba310d6e28b6f" - integrity sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A== - -turbo-windows-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.0.3.tgz#9d1b99aff361bcbf4e065029e9dfa6682a0c0b2d" - integrity sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w== - -turbo-windows-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.0.3.tgz#0e0641acda3325a4a3d28123ef21017a7aae8f38" - integrity sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg== - -turbo@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.0.3.tgz#789f64666d15dbc6fc85ce507a6c6888d70df88f" - integrity sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA== - optionalDependencies: - turbo-darwin-64 "2.0.3" - turbo-darwin-arm64 "2.0.3" - turbo-linux-64 "2.0.3" - turbo-linux-arm64 "2.0.3" - turbo-windows-64 "2.0.3" - turbo-windows-arm64 "2.0.3" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.12.0.tgz#f57a27ab81c68d136a51fd71467eff94157fa1ee" - integrity sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg== - -type-fest@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" - integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" - integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-typed-array "^1.1.13" - -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - -typedarray.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.3.tgz#bce2f685d3279f543239e4d595e0d021731d2d1a" - integrity sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-errors "^1.3.0" - typed-array-buffer "^1.0.2" - typed-array-byte-offset "^1.0.2" - -typescript@5.5.4: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== - -ua-parser-js@^1.0.35: - version "1.0.38" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2" - integrity sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" - integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" - integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg== - dependencies: - crypto-random-string "^1.0.0" - -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -universalify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" - integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== - -universalify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -update-browserslist-db@^1.0.13: - version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" - integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== - dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" - -update-check@1.5.3: - version "1.5.3" - resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.3.tgz#45240fcfb8755a7c7fa68bbdd9eda026a41639ed" - integrity sha512-6KLU4/dd0Tg/l0xwL+f9V7kEIPSL1vOIbnNnhSLiRDlj4AVG6Ks9Zoc9Jgt9kIgWFPZ/wp2AHgmG7xNf15TJOA== - dependencies: - registry-auth-token "3.3.2" - registry-url "3.1.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url-join@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a" - integrity sha512-EGXjXJZhIHiQMK2pQukuFcL303nskqIRzWvPvV5O8miOfwoUb9G+a/Cld60kUyeaybEI94wvVClT10DtfeAExA== - -url-parse@^1.5.9: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -uuid@^3.3.2, uuid@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" - integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== - -uuid@^8.0.0, uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -valid-url@~1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA== - -validate-npm-package-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw== - dependencies: - builtins "^1.0.3" - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -vlq@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" - integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== - -walker@^1.0.7: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -watchpack@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" - integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== - dependencies: - defaults "^1.0.3" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -webpack-dev-middleware@^5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" - integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== - dependencies: - colorette "^2.0.10" - memfs "^3.4.3" - mime-types "^2.1.31" - range-parser "^1.2.1" - schema-utils "^4.0.0" - -webpack-dev-server@^4.11.1: - version "4.15.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz#9e0c70a42a012560860adb186986da1248333173" - integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g== - dependencies: - "@types/bonjour" "^3.5.9" - "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" - "@types/serve-index" "^1.9.1" - "@types/serve-static" "^1.13.10" - "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.5" - ansi-html-community "^0.0.8" - bonjour-service "^1.0.11" - chokidar "^3.5.3" - colorette "^2.0.10" - compression "^1.7.4" - connect-history-api-fallback "^2.0.0" - default-gateway "^6.0.3" - express "^4.17.3" - graceful-fs "^4.2.6" - html-entities "^2.3.2" - http-proxy-middleware "^2.0.3" - ipaddr.js "^2.0.1" - launch-editor "^2.6.0" - open "^8.0.9" - p-retry "^4.5.0" - rimraf "^3.0.2" - schema-utils "^4.0.0" - selfsigned "^2.1.1" - serve-index "^1.9.1" - sockjs "^0.3.24" - spdy "^4.0.2" - webpack-dev-middleware "^5.3.4" - ws "^8.13.0" - -webpack-manifest-plugin@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz#10f8dbf4714ff93a215d5a45bcc416d80506f94f" - integrity sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow== - dependencies: - tapable "^2.0.0" - webpack-sources "^2.2.0" - -webpack-sources@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" - integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== - dependencies: - source-list-map "^2.0.1" - source-map "^0.6.1" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.64.4: - version "5.91.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" - integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.12.1" - "@webassemblyjs/wasm-edit" "^1.12.1" - "@webassemblyjs/wasm-parser" "^1.12.1" - acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.21.10" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.16.0" - es-module-lexer "^1.2.1" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.11" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.2.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.10" - watchpack "^2.4.1" - webpack-sources "^3.2.3" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -whatwg-fetch@^3.0.0: - version "3.6.20" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" - integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -whatwg-url@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" - integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-builtin-type@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" - integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== - dependencies: - function.prototype.name "^1.1.5" - has-tostringtag "^1.0.0" - is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" - is-generator-function "^1.0.10" - is-regex "^1.1.4" - is-weakref "^1.0.2" - isarray "^2.0.5" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" - -which-collection@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" - integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== - dependencies: - is-map "^2.0.3" - is-set "^2.0.3" - is-weakmap "^2.0.2" - is-weakset "^2.0.3" - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.2" - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wonka@^4.0.14: - version "4.0.15" - resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.15.tgz#9aa42046efa424565ab8f8f451fcca955bf80b89" - integrity sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg== - -wonka@^6.3.2: - version "6.3.4" - resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.3.4.tgz#76eb9316e3d67d7febf4945202b5bdb2db534594" - integrity sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg== - -word-wrap@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^2.3.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -ws@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" - integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== - dependencies: - async-limiter "~1.0.0" - -ws@^7, ws@^7.5.1: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -ws@^8.12.1, ws@^8.13.0: - version "8.17.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" - integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== - -xcode@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/xcode/-/xcode-3.0.1.tgz#3efb62aac641ab2c702458f9a0302696146aa53c" - integrity sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA== - dependencies: - simple-plist "^1.1.0" - uuid "^7.0.3" - -xml2js@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282" - integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-14.0.0.tgz#876b5aec4f05ffd5feb97b0a871c855d16fbeb8c" - integrity sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg== - -xmlbuilder@^15.1.1: - version "15.1.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" - integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - -xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yaml@^2.2.1, yaml@^2.3.4: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.3.tgz#0777516b8c7880bcaa0f426a5410e8d6b0be1f3d" - integrity sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^15.1.0: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -yargs@^17.6.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - 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" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/examples/with-rollup/README.md b/examples/with-rollup/README.md deleted file mode 100644 index f12727c201d15..0000000000000 --- a/examples/with-rollup/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# Turborepo starter with Rollup - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-rollup -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `web`: a [Next.js](https://nextjs.org) app -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo -- `@repo/ui`: a React component library used by the `web` application, compiled with Rollup - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Build - -To build all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm run build -``` - -### Develop - -To develop all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm run dev -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turborepo.org/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -``` -cd my-turborepo -npx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: - -``` -npx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Pipelines](https://turborepo.org/docs/core-concepts/pipelines) -- [Caching](https://turborepo.org/docs/core-concepts/caching) -- [Remote Caching](https://turborepo.org/docs/core-concepts/remote-caching) -- [Scoped Tasks](https://turborepo.org/docs/core-concepts/scopes) -- [Configuration Options](https://turborepo.org/docs/reference/configuration) -- [CLI Usage](https://turborepo.org/docs/reference/command-line-reference) diff --git a/examples/with-rollup/apps/web/.eslintrc.js b/examples/with-rollup/apps/web/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-rollup/apps/web/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-rollup/apps/web/README.md b/examples/with-rollup/apps/web/README.md deleted file mode 100644 index d712ce1a72676..0000000000000 --- a/examples/with-rollup/apps/web/README.md +++ /dev/null @@ -1,30 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -pnpm dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-rollup/apps/web/package.json b/examples/with-rollup/apps/web/package.json index f3efc14416b8f..58d6c1618b3e1 100644 --- a/examples/with-rollup/apps/web/package.json +++ b/examples/with-rollup/apps/web/package.json @@ -1,26 +1,17 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@repo/ui": "workspace:*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "workspace:*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-rollup/package.json b/examples/with-rollup/package.json index d2ad915cb0487..2052c0bd17315 100644 --- a/examples/with-rollup/package.json +++ b/examples/with-rollup/package.json @@ -1,16 +1,11 @@ { - "private": true, - "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "eslint": "^8.57.0", - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "pnpm@8.15.6", - "name": "with-rollup" + "name": "with-rollup", + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-rollup/packages/config-eslint/README.md b/examples/with-rollup/packages/config-eslint/README.md deleted file mode 100644 index b79474eaf968c..0000000000000 --- a/examples/with-rollup/packages/config-eslint/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@repo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-rollup/packages/config-eslint/package.json b/examples/with-rollup/packages/config-eslint/package.json index 821a73829bff4..dca64b8823b7a 100644 --- a/examples/with-rollup/packages/config-eslint/package.json +++ b/examples/with-rollup/packages/config-eslint/package.json @@ -1,19 +1,14 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js", - "react-internal.js" - ], - "devDependencies": { - "@vercel/style-guide": "^5.2.0", - "eslint-config-turbo": "^2.0.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-only-warn": "^1.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "next.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-rollup/packages/config-typescript/package.json b/examples/with-rollup/packages/config-typescript/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-rollup/packages/config-typescript/package.json +++ b/examples/with-rollup/packages/config-typescript/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-rollup/packages/ui/.eslintrc.cjs b/examples/with-rollup/packages/ui/.eslintrc.cjs deleted file mode 100644 index 4cb7125da11b1..0000000000000 --- a/examples/with-rollup/packages/ui/.eslintrc.cjs +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-rollup/packages/ui/package.json b/examples/with-rollup/packages/ui/package.json index a79b4fd0c3818..c02f451929dd9 100644 --- a/examples/with-rollup/packages/ui/package.json +++ b/examples/with-rollup/packages/ui/package.json @@ -1,33 +1,22 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "type": "module", - "exports": { - "./button": { - "types": "./Button.tsx", - "default": "./dist/button.js" - }, - "./header": { - "types": "./Header.tsx", - "default": "./dist/header.js" - } - }, - "scripts": { - "lint": "eslint *.ts*", - "build": "rollup --config", - "dev": "pnpm build --watch" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@rollup/plugin-typescript": "^11.1.6", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "rollup": "^4.12.0", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - } + "name": "@repo/ui", + "exports": { + "./button": { + "default": "./dist/button.js", + "types": "./Button.tsx" + }, + "./header": { + "default": "./dist/header.js", + "types": "./Header.tsx" + } + }, + "scripts": { + "build": "rollup --config", + "dev": "pnpm build --watch" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*" + } } diff --git a/examples/with-rollup/pnpm-lock.yaml b/examples/with-rollup/pnpm-lock.yaml deleted file mode 100644 index 9cd6cc5c54fb9..0000000000000 --- a/examples/with-rollup/pnpm-lock.yaml +++ /dev/null @@ -1,4020 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - eslint: - specifier: ^8.57.0 - version: 8.57.0 - prettier: - specifier: ^3.2.5 - version: 3.3.0 - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^14.1.1 - version: 14.2.3(react-dom@18.3.1)(react@18.3.1) - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - devDependencies: - '@next/eslint-plugin-next': - specifier: ^14.1.1 - version: 14.2.3 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/config-eslint - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/config-typescript - '@types/node': - specifier: ^20.11.24 - version: 20.14.0 - '@types/react': - specifier: ^18.2.61 - version: 18.3.3 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.3.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/config-eslint: - devDependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.12.0(@typescript-eslint/parser@7.12.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.12.0(eslint@8.57.0)(typescript@5.5.4) - '@vercel/style-guide': - specifier: ^5.2.0 - version: 5.2.0(eslint@8.57.0)(prettier@3.3.0)(typescript@5.5.4) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - eslint-config-turbo: - specifier: ^2.0.0 - version: 2.0.0(eslint@8.57.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/config-typescript: {} - - packages/ui: - dependencies: - react: - specifier: ^18.2.0 - version: 18.3.1 - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../config-eslint - '@repo/typescript-config': - specifier: workspace:* - version: link:../config-typescript - '@rollup/plugin-typescript': - specifier: ^11.1.6 - version: 11.1.6(rollup@4.18.0)(typescript@5.5.4) - '@types/react': - specifier: ^18.2.61 - version: 18.3.3 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.3.0 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - rollup: - specifier: ^4.12.0 - version: 4.18.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@babel/code-frame@7.24.6: - resolution: {integrity: sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.6 - picocolors: 1.0.1 - dev: true - - /@babel/compat-data@7.24.6: - resolution: {integrity: sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.24.6: - resolution: {integrity: sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.6 - '@babel/generator': 7.24.6 - '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-module-transforms': 7.24.6(@babel/core@7.24.6) - '@babel/helpers': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/template': 7.24.6 - '@babel/traverse': 7.24.6 - '@babel/types': 7.24.6 - convert-source-map: 2.0.0 - debug: 4.3.5 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/eslint-parser@7.24.6(@babel/core@7.24.6)(eslint@8.57.0): - resolution: {integrity: sha512-Q1BfQX42zXHx732PLW0w4+Y3wJjoZKEMaatFUEAmQ7Z+jCXxinzeqX9bvv2Q8xNPes/H6F0I23oGkcgjaItmLw==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - dependencies: - '@babel/core': 7.24.6 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.24.6: - resolution: {integrity: sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.6 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.24.6: - resolution: {integrity: sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.6 - '@babel/helper-validator-option': 7.24.6 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.24.6: - resolution: {integrity: sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.24.6: - resolution: {integrity: sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 - dev: true - - /@babel/helper-hoist-variables@7.24.6: - resolution: {integrity: sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.6 - dev: true - - /@babel/helper-module-imports@7.24.6: - resolution: {integrity: sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.6 - dev: true - - /@babel/helper-module-transforms@7.24.6(@babel/core@7.24.6): - resolution: {integrity: sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-module-imports': 7.24.6 - '@babel/helper-simple-access': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 - dev: true - - /@babel/helper-simple-access@7.24.6: - resolution: {integrity: sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.6 - dev: true - - /@babel/helper-split-export-declaration@7.24.6: - resolution: {integrity: sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.6 - dev: true - - /@babel/helper-string-parser@7.24.6: - resolution: {integrity: sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.24.6: - resolution: {integrity: sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.24.6: - resolution: {integrity: sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.24.6: - resolution: {integrity: sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 - dev: true - - /@babel/highlight@7.24.6: - resolution: {integrity: sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.6 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.1 - dev: true - - /@babel/parser@7.24.6: - resolution: {integrity: sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.6 - dev: true - - /@babel/runtime@7.24.6: - resolution: {integrity: sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - - /@babel/template@7.24.6: - resolution: {integrity: sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 - dev: true - - /@babel/traverse@7.24.6: - resolution: {integrity: sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.6 - '@babel/generator': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 - '@babel/helper-hoist-variables': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 - debug: 4.3.5 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.24.6: - resolution: {integrity: sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 - to-fast-properties: 2.0.0 - dev: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.10.1: - resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.5 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true - - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true - - /@next/env@14.2.3: - resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==} - dev: false - - /@next/eslint-plugin-next@14.2.3: - resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==} - dependencies: - glob: 10.3.10 - dev: true - - /@next/swc-darwin-arm64@14.2.3: - resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64@14.2.3: - resolution: {integrity: sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu@14.2.3: - resolution: {integrity: sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl@14.2.3: - resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu@14.2.3: - resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl@14.2.3: - resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc@14.2.3: - resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-ia32-msvc@14.2.3: - resolution: {integrity: sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc@14.2.3: - resolution: {integrity: sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@pkgr/core@0.1.1: - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true - - /@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(typescript@5.5.4): - resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.14.0||^3.0.0||^4.0.0 - tslib: '*' - typescript: '>=3.7.0' - peerDependenciesMeta: - rollup: - optional: true - tslib: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.18.0) - resolve: 1.22.8 - rollup: 4.18.0 - typescript: 5.5.4 - dev: true - - /@rollup/pluginutils@5.1.0(rollup@4.18.0): - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 4.18.0 - dev: true - - /@rollup/rollup-android-arm-eabi@4.18.0: - resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.18.0: - resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.18.0: - resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.18.0: - resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.18.0: - resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-musleabihf@4.18.0: - resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.18.0: - resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.18.0: - resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-powerpc64le-gnu@4.18.0: - resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.18.0: - resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-s390x-gnu@4.18.0: - resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.18.0: - resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.18.0: - resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.18.0: - resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.18.0: - resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.18.0: - resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rushstack/eslint-patch@1.10.3: - resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} - dev: true - - /@swc/counter@0.1.3: - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - dev: false - - /@swc/helpers@0.5.5: - resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} - dependencies: - '@swc/counter': 0.1.3 - tslib: 2.6.2 - dev: false - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/node@20.14.0: - resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: true - - /@types/prop-types@15.7.12: - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - dev: true - - /@types/react-dom@18.3.0: - resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - dependencies: - '@types/react': 18.3.3 - dev: true - - /@types/react@18.3.3: - resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} - dependencies: - '@types/prop-types': 15.7.12 - csstype: 3.1.3 - dev: true - - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true - - /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.1 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/eslint-plugin@7.12.0(@typescript-eslint/parser@7.12.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.1 - '@typescript-eslint/parser': 7.12.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 7.12.0 - '@typescript-eslint/type-utils': 7.12.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.12.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.12.0 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.12.0 - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.12.0 - debug: 4.3.5 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - - /@typescript-eslint/scope-manager@6.21.0: - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - dev: true - - /@typescript-eslint/scope-manager@7.12.0: - resolution: {integrity: sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/visitor-keys': 7.12.0 - dev: true - - /@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.5 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/type-utils@7.12.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.12.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.5 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@6.21.0: - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/types@7.12.0: - resolution: {integrity: sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==} - engines: {node: ^18.18.0 || >=20.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.4): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.2 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@6.21.0(typescript@5.5.4): - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@7.12.0(typescript@5.5.4): - resolution: {integrity: sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/visitor-keys': 7.12.0 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.6.2 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.6.2 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@7.12.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.12.0 - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@6.21.0: - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.12.0: - resolution: {integrity: sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.12.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@vercel/style-guide@5.2.0(eslint@8.57.0)(prettier@3.3.0)(typescript@5.5.4): - resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} - engines: {node: '>=16'} - peerDependencies: - '@next/eslint-plugin-next': '>=12.3.0 <15' - eslint: '>=8.48.0 <9' - prettier: '>=3.0.0 <4' - typescript: '>=4.8.0 <6' - peerDependenciesMeta: - '@next/eslint-plugin-next': - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - dependencies: - '@babel/core': 7.24.6 - '@babel/eslint-parser': 7.24.6(@babel/core@7.24.6)(eslint@8.57.0) - '@rushstack/eslint-patch': 1.10.3 - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) - eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.1) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.12.0)(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0) - eslint-plugin-react: 7.34.2(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) - eslint-plugin-testing-library: 6.2.2(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) - prettier: 3.3.0 - prettier-plugin-packagejson: 2.5.0(prettier@3.3.0) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - dependencies: - dequal: 2.0.3 - dev: true - - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - dev: true - - /array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.toreversed@1.1.2: - resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - dev: true - - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - dev: true - - /ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - dev: true - - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - dev: true - - /axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - dev: true - - /axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} - dependencies: - dequal: 2.0.3 - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.1.1 - dev: true - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001627 - electron-to-chromium: 1.4.788 - node-releases: 2.0.14 - update-browserslist-db: 1.0.16(browserslist@4.23.0) - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - dev: false - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /caniuse-lite@1.0.30001627: - resolution: {integrity: sha512-4zgNiB8nTyV/tHhwZrFs88ryjls/lHiqFhrxCW4qSTeuRByBVnPYpDInchOIySWknznucaf31Z4KYqjfbrecVw==} - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - dev: true - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug@4.3.5: - resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - dev: true - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: true - - /detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - dev: true - - /detect-newline@4.0.1: - resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /electron-to-chromium@1.4.788: - resolution: {integrity: sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /enhanced-resolve@5.16.1: - resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.0 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 - globalthis: 1.0.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true - - /es-iterator-helpers@1.0.19: - resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-set-tostringtag: 2.0.3 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - globalthis: 1.0.4 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - iterator.prototype: 1.1.2 - safe-array-concat: 1.1.2 - dev: true - - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - dev: true - - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - dev: true - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.2 - dev: true - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-config-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-turbo: 2.0.0(eslint@8.57.0) - dev: true - - /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.1): - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - dependencies: - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.12.0)(eslint@8.57.0) - dev: true - - /eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): - resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.5 - enhanced-resolve: 5.16.1 - eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.12.0)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.7.5 - is-core-module: 2.13.1 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.12.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 7.12.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): - resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} - engines: {node: '>=6.5.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - escape-string-regexp: 1.0.5 - eslint: 8.57.0 - ignore: 5.3.1 - dev: true - - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.12.0)(eslint@8.57.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 7.12.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.12.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.24.6 - aria-query: 5.3.0 - array-includes: 3.1.8 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.19 - eslint: 8.57.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - dev: true - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0): - resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} - peerDependencies: - eslint: '>=7' - eslint-plugin-jest: '>=25' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - dependencies: - eslint: 8.57.0 - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - dev: true - - /eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): - resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react@7.34.2(eslint@8.57.0): - resolution: {integrity: sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.2 - array.prototype.toreversed: 1.1.2 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.19 - eslint: 8.57.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.hasown: 1.1.4 - object.values: 1.2.0 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.11 - dev: true - - /eslint-plugin-testing-library@6.2.2(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true - - /eslint-plugin-turbo@2.0.0(eslint@8.57.0): - resolution: {integrity: sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.0 - dev: true - - /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.44.0' - dependencies: - '@babel/helper-validator-identifier': 7.24.6 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - ci-info: 3.9.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.6.2 - strip-indent: 3.0.0 - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.1 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.5 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.7 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: true - - /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - dev: true - - /get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - dev: true - - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - dev: true - - /get-tsconfig@4.7.5: - resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true - - /git-hooks-list@3.1.0: - resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.1.2 - path-scurry: 1.11.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - gopd: 1.0.1 - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: true - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - dev: true - - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.2 - dev: true - - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - dependencies: - is-typed-array: 1.1.13 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - dev: true - - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: true - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - dev: true - - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.15 - dev: true - - /is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - dev: true - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-weakset@2.0.3: - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.6 - set-function-name: 2.0.2 - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.2 - object.assign: 4.1.5 - object.values: 1.2.0 - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /language-subtag-registry@0.3.23: - resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} - dev: true - - /language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - dependencies: - language-subtag-registry: 0.3.23 - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - - /lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch@4.0.7: - resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - dev: true - - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - - /minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: false - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /next@14.2.3(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==} - engines: {node: '>=18.17.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - sass: - optional: true - dependencies: - '@next/env': 14.2.3 - '@swc/helpers': 0.5.5 - busboy: 1.6.0 - caniuse-lite: 1.0.30001627 - graceful-fs: 4.2.11 - postcss: 8.4.31 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(react@18.3.1) - optionalDependencies: - '@next/swc-darwin-arm64': 14.2.3 - '@next/swc-darwin-x64': 14.2.3 - '@next/swc-linux-arm64-gnu': 14.2.3 - '@next/swc-linux-arm64-musl': 14.2.3 - '@next/swc-linux-x64-gnu': 14.2.3 - '@next/swc-linux-x64-musl': 14.2.3 - '@next/swc-win32-arm64-msvc': 14.2.3 - '@next/swc-win32-ia32-msvc': 14.2.3 - '@next/swc-win32-x64-msvc': 14.2.3 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true - - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - dev: true - - /object.hasown@1.1.4: - resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.24.6 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - dependencies: - lru-cache: 10.2.2 - minipass: 7.1.2 - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: true - - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - dev: false - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-plugin-packagejson@2.5.0(prettier@3.3.0): - resolution: {integrity: sha512-6XkH3rpin5QEQodBSVNg+rBo4r91g/1mCaRwS1YGdQJZ6jwqrg2UchBsIG9tpS1yK1kNBvOt84OILsX8uHzBGg==} - peerDependencies: - prettier: '>= 1.16.0' - peerDependenciesMeta: - prettier: - optional: true - dependencies: - prettier: 3.3.0 - sort-package-json: 2.10.0 - synckit: 0.9.0 - dev: true - - /prettier@3.3.0: - resolution: {integrity: sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /react-dom@18.3.1(react@18.3.1): - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - dev: false - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - dev: false - - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /reflect.getprototypeof@1.0.6: - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - globalthis: 1.0.4 - which-builtin-type: 1.1.3 - dev: true - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true - - /regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - hasBin: true - dev: true - - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - dev: true - - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rollup@4.18.0: - resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.18.0 - '@rollup/rollup-android-arm64': 4.18.0 - '@rollup/rollup-darwin-arm64': 4.18.0 - '@rollup/rollup-darwin-x64': 4.18.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 - '@rollup/rollup-linux-arm-musleabihf': 4.18.0 - '@rollup/rollup-linux-arm64-gnu': 4.18.0 - '@rollup/rollup-linux-arm64-musl': 4.18.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 - '@rollup/rollup-linux-riscv64-gnu': 4.18.0 - '@rollup/rollup-linux-s390x-gnu': 4.18.0 - '@rollup/rollup-linux-x64-gnu': 4.18.0 - '@rollup/rollup-linux-x64-musl': 4.18.0 - '@rollup/rollup-win32-arm64-msvc': 4.18.0 - '@rollup/rollup-win32-ia32-msvc': 4.18.0 - '@rollup/rollup-win32-x64-msvc': 4.18.0 - fsevents: 2.3.3 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - dev: true - - /scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - dev: true - - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /sort-object-keys@1.1.3: - resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - dev: true - - /sort-package-json@2.10.0: - resolution: {integrity: sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==} - hasBin: true - dependencies: - detect-indent: 7.0.1 - detect-newline: 4.0.1 - get-stdin: 9.0.0 - git-hooks-list: 3.1.0 - globby: 13.2.2 - is-plain-obj: 4.1.0 - semver: 7.6.2 - sort-object-keys: 1.1.3 - dev: true - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - dev: false - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.18 - dev: true - - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.18 - dev: true - - /spdx-license-ids@3.0.18: - resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} - dev: true - - /streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - dev: false - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.2 - side-channel: 1.0.6 - dev: true - - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /styled-jsx@5.1.1(react@18.3.1): - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - client-only: 0.0.1 - react: 18.3.1 - dev: false - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /synckit@0.9.0: - resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.2 - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /ts-api-utils@1.3.0(typescript@5.5.4): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - /tsutils@3.21.0(typescript@5.5.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.4 - dev: true - - /turbo-darwin-64@2.0.3: - resolution: {integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: {integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: {integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: {integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: {integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: {integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: {integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 - dev: true - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /update-browserslist-db@1.0.16(browserslist@4.23.0): - resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.1 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.2 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.3 - dev: true - - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.2 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true diff --git a/examples/with-shell-commands/README.md b/examples/with-shell-commands/README.md deleted file mode 100644 index 3083e486d051c..0000000000000 --- a/examples/with-shell-commands/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Turborepo starter with shell commands - -This Turborepo starter is maintained by the Turborepo core team. This template is great for issue reproductions and exploring building task graphs without frameworks. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-shell-commands -``` - -### For bug reproductions - -Giving the Turborepo core team a minimal reproduction is the best way to create a tight feedback loop for a bug you'd like to report. - -Because most monorepos will rely on more tooling than Turborepo (frameworks, linters, formatters, etc.), it's often useful for us to have a reproduction that strips away all of this other tooling so we can focus _only_ on Turborepo's role in your repo. This example does exactly that, giving you a good starting point for creating a reproduction. - -- Feel free to rename/delete packages for your reproduction so that you can be confident it most closely matches your use case. -- If you need to use a different package manager to produce your bug, run `npx @turbo/workspaces convert` to switch package managers. -- It's possible that your bug really **does** have to do with the interaction of Turborepo and other tooling within your repository. If you find that your bug does not reproduce in this minimal example and you're confident Turborepo is still at fault, feel free to bring that other tooling into your reproduction. - -## What's inside? - -This Turborepo includes the following packages: - -### Apps and Packages - -- `app-a`: A final package that depends on all other packages in the graph and has no dependents. This could resemble an application in your monorepo that consumes everything in your monorepo through its topological tree. -- `app-b`: Another final package with many dependencies. No dependents, lots of dependencies. -- `pkg-a`: A package that has all scripts in the root `package.json`. -- `pkg-b`: A package with _almost_ all scripts in the root `package.json`. -- `tooling-config`: A package to simulate a common configuration used for all of your repository. This could resemble a configuration for tools like TypeScript or ESLint that are installed into all of your packages. - -### Some scripts to try - -If you haven't yet, [install global `turbo`](https://turbo.build/repo/docs/installing#install-globally) to run tasks. - -- `turbo build lint typecheck`: Runs all tasks in the default graph. -- `turbo build`: A basic command to build `app-a` and `app-b` in parallel. -- `turbo build --filter=app-a`: Building only `app-a` and its dependencies. -- `turbo lint`: A basic command for running lints in all packages in parallel. diff --git a/examples/with-shell-commands/apps/app-a/README.md b/examples/with-shell-commands/apps/app-a/README.md deleted file mode 100644 index e50bebae4451d..0000000000000 --- a/examples/with-shell-commands/apps/app-a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Top-level package - -We'll use this package as the final node of your [Task Graph](https://turbo.build/repo/docs/core-concepts/task-graph). You may want to think of it as the final application you're building (the most common use case for a Turborepo build pipeline). diff --git a/examples/with-shell-commands/apps/app-a/package.json b/examples/with-shell-commands/apps/app-a/package.json index 770491511d77c..56d6403b2907f 100644 --- a/examples/with-shell-commands/apps/app-a/package.json +++ b/examples/with-shell-commands/apps/app-a/package.json @@ -1,13 +1,13 @@ { - "name": "app-a", - "description": "An application that uses other Internal Packages", - "scripts": { - "build": "mkdir -p dist && echo \"Your application output!\" > dist/app-output.txt && echo \"Application A is built!\"", - "lint": "echo \"Linted!\"", - "type-check": "echo \"Types checked!\"" - }, - "dependencies": { - "pkg-a": "workspace:*", - "tooling-config": "workspace:*" - } + "name": "app-a", + "description": "An application that uses other Internal Packages", + "scripts": { + "build": "mkdir -p dist && echo \"Your application output!\" > dist/app-output.txt && echo \"Application A is built!\"", + "type-check": "echo \"Types checked!\"" + }, + "dependencies": { + "pkg-a": "workspace:*", + "tooling-config": "workspace:*" + }, + "devDependencies": {} } diff --git a/examples/with-shell-commands/apps/app-b/README.md b/examples/with-shell-commands/apps/app-b/README.md deleted file mode 100644 index 63dac941db0f5..0000000000000 --- a/examples/with-shell-commands/apps/app-b/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Top-level package - -We'll use this package as the end of your Task Graph. You may want to think of it as the final application you're building (the most common use case for a Turborepo build pipeline). diff --git a/examples/with-shell-commands/apps/app-b/package.json b/examples/with-shell-commands/apps/app-b/package.json index 9cb2e1941ece7..488251d6173df 100644 --- a/examples/with-shell-commands/apps/app-b/package.json +++ b/examples/with-shell-commands/apps/app-b/package.json @@ -1,12 +1,12 @@ { - "name": "app-b", - "description": "A workspace to use as a model for a final application that the rest of your dependencies are building towards.", - "scripts": { - "build": "mkdir -p dist && echo \"Your application output!\" > dist/app-output.txt && echo \"Application B is built!\"", - "lint": "echo \"Linted!\"", - "type-check": "echo \"Types checked!\"" - }, - "dependencies": { - "tooling-config": "workspace:*" - } + "name": "app-b", + "description": "A workspace to use as a model for a final application that the rest of your dependencies are building towards.", + "scripts": { + "build": "mkdir -p dist && echo \"Your application output!\" > dist/app-output.txt && echo \"Application B is built!\"", + "type-check": "echo \"Types checked!\"" + }, + "dependencies": { + "tooling-config": "workspace:*" + }, + "devDependencies": {} } diff --git a/examples/with-shell-commands/apps/apps-a/package.json b/examples/with-shell-commands/apps/apps-a/package.json new file mode 100644 index 0000000000000..56d6403b2907f --- /dev/null +++ b/examples/with-shell-commands/apps/apps-a/package.json @@ -0,0 +1,13 @@ +{ + "name": "app-a", + "description": "An application that uses other Internal Packages", + "scripts": { + "build": "mkdir -p dist && echo \"Your application output!\" > dist/app-output.txt && echo \"Application A is built!\"", + "type-check": "echo \"Types checked!\"" + }, + "dependencies": { + "pkg-a": "workspace:*", + "tooling-config": "workspace:*" + }, + "devDependencies": {} +} diff --git a/examples/with-shell-commands/apps/apps-b/package.json b/examples/with-shell-commands/apps/apps-b/package.json new file mode 100644 index 0000000000000..488251d6173df --- /dev/null +++ b/examples/with-shell-commands/apps/apps-b/package.json @@ -0,0 +1,12 @@ +{ + "name": "app-b", + "description": "A workspace to use as a model for a final application that the rest of your dependencies are building towards.", + "scripts": { + "build": "mkdir -p dist && echo \"Your application output!\" > dist/app-output.txt && echo \"Application B is built!\"", + "type-check": "echo \"Types checked!\"" + }, + "dependencies": { + "tooling-config": "workspace:*" + }, + "devDependencies": {} +} diff --git a/examples/with-shell-commands/package.json b/examples/with-shell-commands/package.json index 12dbbfd343ccb..764f4484b5a46 100644 --- a/examples/with-shell-commands/package.json +++ b/examples/with-shell-commands/package.json @@ -1,9 +1,8 @@ { - "name": "my-turborepo", - "description": "A barebones Turborepo example for working with Task Graphs.", - "private": true, - "packageManager": "pnpm@8.15.6", - "devDependencies": { - "turbo": "^2.3.4" - } + "name": "my-turborepo", + "description": "A barebones Turborepo example for working with Task Graphs.", + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-shell-commands/packages/pkg-a/README.md b/examples/with-shell-commands/packages/pkg-a/README.md deleted file mode 100644 index e464bf79c6b0c..0000000000000 --- a/examples/with-shell-commands/packages/pkg-a/README.md +++ /dev/null @@ -1 +0,0 @@ -Change me to miss cache! diff --git a/examples/with-shell-commands/packages/pkg-a/package.json b/examples/with-shell-commands/packages/pkg-a/package.json index 1d60de1da4eee..a156c906e044f 100644 --- a/examples/with-shell-commands/packages/pkg-a/package.json +++ b/examples/with-shell-commands/packages/pkg-a/package.json @@ -1,11 +1,11 @@ { - "name": "pkg-a", - "scripts": { - "build": "echo \"Building at the speed of Turbo.\" > output-file.txt && cat output-file.txt", - "lint": "echo \"Linted!\"", - "type-check": "echo \"Types checked!\"" - }, - "dependencies": { - "tooling-config": "workspace:*" - } + "name": "pkg-a", + "scripts": { + "build": "echo \"Building at the speed of Turbo.\" > output-file.txt && cat output-file.txt", + "type-check": "echo \"Types checked!\"" + }, + "dependencies": { + "tooling-config": "workspace:*" + }, + "devDependencies": {} } diff --git a/examples/with-shell-commands/packages/pkg-b/README.md b/examples/with-shell-commands/packages/pkg-b/README.md deleted file mode 100644 index e464bf79c6b0c..0000000000000 --- a/examples/with-shell-commands/packages/pkg-b/README.md +++ /dev/null @@ -1 +0,0 @@ -Change me to miss cache! diff --git a/examples/with-shell-commands/packages/pkg-b/package.json b/examples/with-shell-commands/packages/pkg-b/package.json index 01701e59eb66f..4460df200af81 100644 --- a/examples/with-shell-commands/packages/pkg-b/package.json +++ b/examples/with-shell-commands/packages/pkg-b/package.json @@ -1,11 +1,12 @@ { - "name": "pkg-b", - "scripts": { - "prebuild": "echo \"Executing pre-build step...\"", - "build": "echo \"Welcome to the Turboverse.\" > output-file.txt && cat output-file.txt", - "type-check": "echo \"Types checked!\"" - }, - "dependencies": { - "tooling-config": "workspace:*" - } + "name": "pkg-b", + "scripts": { + "prebuild": "echo \"Executing pre-build step...\"", + "build": "echo \"Welcome to the Turboverse.\" > output-file.txt && cat output-file.txt", + "type-check": "echo \"Types checked!\"" + }, + "dependencies": { + "tooling-config": "workspace:*" + }, + "devDependencies": {} } diff --git a/examples/with-shell-commands/packages/tooling-config/README.md b/examples/with-shell-commands/packages/tooling-config/README.md deleted file mode 100644 index f525f51eb5ced..0000000000000 --- a/examples/with-shell-commands/packages/tooling-config/README.md +++ /dev/null @@ -1 +0,0 @@ -Because this package is shared in every package in the monorepo, a source code change in this package will cause a cache miss for all tasks in all packages. diff --git a/examples/with-shell-commands/packages/tooling-config/package.json b/examples/with-shell-commands/packages/tooling-config/package.json index 34ca03a1c11b5..855a98545dc29 100644 --- a/examples/with-shell-commands/packages/tooling-config/package.json +++ b/examples/with-shell-commands/packages/tooling-config/package.json @@ -1,4 +1,6 @@ { - "name": "tooling-config", - "description": "A package used by every other package." + "name": "tooling-config", + "description": "A package used by every other package.", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-shell-commands/pnpm-lock.yaml b/examples/with-shell-commands/pnpm-lock.yaml deleted file mode 100644 index 9855f787f63a1..0000000000000 --- a/examples/with-shell-commands/pnpm-lock.yaml +++ /dev/null @@ -1,104 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - turbo: - specifier: ^2.3.4 - version: 2.3.4 - - apps/app-a: - dependencies: - pkg-a: - specifier: workspace:* - version: link:../../packages/pkg-a - tooling-config: - specifier: workspace:* - version: link:../../packages/tooling-config - - apps/app-b: - dependencies: - tooling-config: - specifier: workspace:* - version: link:../../packages/tooling-config - - packages/pkg-a: - dependencies: - tooling-config: - specifier: workspace:* - version: link:../tooling-config - - packages/pkg-b: - dependencies: - tooling-config: - specifier: workspace:* - version: link:../tooling-config - - packages/tooling-config: {} - -packages: - - /turbo-darwin-64@2.3.4: - resolution: {integrity: sha512-uOi/cUIGQI7uakZygH+cZQ5D4w+aMLlVCN2KTGot+cmefatps2ZmRRufuHrEM0Rl63opdKD8/JIu+54s25qkfg==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.3.4: - resolution: {integrity: sha512-IIM1Lq5R+EGMtM1YFGl4x8Xkr0MWb4HvyU8N4LNoQ1Be5aycrOE+VVfH+cDg/Q4csn+8bxCOxhRp5KmUflrVTQ==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.3.4: - resolution: {integrity: sha512-1aD2EfR7NfjFXNH3mYU5gybLJEFi2IGOoKwoPLchAFRQ6OEJQj201/oNo9CDL75IIrQo64/NpEgVyZtoPlfhfA==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.3.4: - resolution: {integrity: sha512-MxTpdKwxCaA5IlybPxgGLu54fT2svdqTIxRd0TQmpRJIjM0s4kbM+7YiLk0mOh6dGqlWPUsxz/A0Mkn8Xr5o7Q==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.3.4: - resolution: {integrity: sha512-yyCrWqcRGu1AOOlrYzRnizEtdkqi+qKP0MW9dbk9OsMDXaOI5jlWtTY/AtWMkLw/czVJ7yS9Ex1vi9DB6YsFvw==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.3.4: - resolution: {integrity: sha512-PggC3qH+njPfn1PDVwKrQvvQby8X09ufbqZ2Ha4uSu+5TvPorHHkAbZVHKYj2Y+tvVzxRzi4Sv6NdHXBS9Be5w==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.3.4: - resolution: {integrity: sha512-1kiLO5C0Okh5ay1DbHsxkPsw9Sjsbjzm6cF85CpWjR0BIyBFNDbKqtUyqGADRS1dbbZoQanJZVj4MS5kk8J42Q==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.3.4 - turbo-darwin-arm64: 2.3.4 - turbo-linux-64: 2.3.4 - turbo-linux-arm64: 2.3.4 - turbo-windows-64: 2.3.4 - turbo-windows-arm64: 2.3.4 - dev: true diff --git a/examples/with-svelte/.prettierignore b/examples/with-svelte/.prettierignore deleted file mode 100644 index 3c5376bd60515..0000000000000 --- a/examples/with-svelte/.prettierignore +++ /dev/null @@ -1,15 +0,0 @@ -.DS_Store -.svelte-kit -node_modules -/build -/package -.env -.env.* -!.env.example -vite.config.js* - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -pnpm-workspace.yaml -package-lock.json -yarn.lock diff --git a/examples/with-svelte/.prettierrc b/examples/with-svelte/.prettierrc deleted file mode 100644 index ab57af61080a2..0000000000000 --- a/examples/with-svelte/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100 -} diff --git a/examples/with-svelte/README.md b/examples/with-svelte/README.md deleted file mode 100644 index 016d2adf01ffb..0000000000000 --- a/examples/with-svelte/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Turborepo Svelte starter - -This Turborepo starter is maintained by the Turborepo core team. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-svelte -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [svelte-kit](https://kit.svelte.dev/) app -- `web`: another [svelte-kit](https://kit.svelte.dev/) app -- `ui`: a stub Svelte component library shared by both `web` and `docs` applications -- `eslint-config-custom`: `eslint` configurations (includes `eslint-plugin-svelte` and `eslint-config-prettier`) - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/with-svelte/apps/docs/.prettierignore b/examples/with-svelte/apps/docs/.prettierignore deleted file mode 100644 index 7438ef36043ff..0000000000000 --- a/examples/with-svelte/apps/docs/.prettierignore +++ /dev/null @@ -1,14 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock -vite.config.*.timestamp-* diff --git a/examples/with-svelte/apps/docs/.prettierrc b/examples/with-svelte/apps/docs/.prettierrc deleted file mode 100644 index 95730232b6b16..0000000000000 --- a/examples/with-svelte/apps/docs/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "useTabs": true, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100, - "plugins": ["prettier-plugin-svelte"], - "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] -} diff --git a/examples/with-svelte/apps/docs/README.md b/examples/with-svelte/apps/docs/README.md deleted file mode 100644 index 5c91169b0ca65..0000000000000 --- a/examples/with-svelte/apps/docs/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# create-svelte - -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). - -## Creating a project - -If you're seeing this, you've probably already done this step. Congrats! - -```bash -# create a new project in the current directory -npm create svelte@latest - -# create a new project in my-app -npm create svelte@latest my-app -``` - -## Developing - -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: - -```bash -npm run dev - -# or start the server and open the app in a new browser tab -npm run dev -- --open -``` - -## Building - -To create a production version of your app: - -```bash -npm run build -``` - -You can preview the production build with `npm run preview`. - -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/examples/with-svelte/apps/docs/src/app.d.ts b/examples/with-svelte/apps/docs/Source/app.d.ts similarity index 100% rename from examples/with-svelte/apps/docs/src/app.d.ts rename to examples/with-svelte/apps/docs/Source/app.d.ts diff --git a/examples/with-svelte/apps/docs/src/app.html b/examples/with-svelte/apps/docs/Source/app.html similarity index 100% rename from examples/with-svelte/apps/docs/src/app.html rename to examples/with-svelte/apps/docs/Source/app.html diff --git a/examples/with-svelte/apps/docs/src/lib/index.ts b/examples/with-svelte/apps/docs/Source/lib/index.ts similarity index 100% rename from examples/with-svelte/apps/docs/src/lib/index.ts rename to examples/with-svelte/apps/docs/Source/lib/index.ts diff --git a/examples/with-svelte/apps/docs/src/routes/+page.svelte b/examples/with-svelte/apps/docs/Source/routes/+page.svelte similarity index 100% rename from examples/with-svelte/apps/docs/src/routes/+page.svelte rename to examples/with-svelte/apps/docs/Source/routes/+page.svelte diff --git a/examples/with-svelte/apps/docs/eslint.config.js b/examples/with-svelte/apps/docs/eslint.config.js deleted file mode 100644 index 729e9cc9f9c8f..0000000000000 --- a/examples/with-svelte/apps/docs/eslint.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { config } from '@repo/eslint-config/index.js'; - -export default [ - ...config, - { - ignores: ['.svelte-kit/*'] - } -]; diff --git a/examples/with-svelte/apps/docs/package.json b/examples/with-svelte/apps/docs/package.json index f52d3f36d00ce..0ddeea87d5a28 100644 --- a/examples/with-svelte/apps/docs/package.json +++ b/examples/with-svelte/apps/docs/package.json @@ -1,17 +1,11 @@ { "name": "docs", - "version": "0.0.1", - "private": true, - "type": "module", "scripts": { - "dev": "vite dev", "build": "vite build", - "preview": "vite preview", - "test": "npm run test:integration && npm run test:unit", "check-types": "tsc --noEmit", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "eslint .", + "dev": "vite dev", + "preview": "vite preview", "test:integration": "playwright test", "test:unit": "vitest" }, @@ -21,16 +15,6 @@ "devDependencies": { "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@sveltejs/adapter-auto": "^3.3.1", - "@sveltejs/kit": "^2.16.0", - "@sveltejs/vite-plugin-svelte": "^3.1.2", - "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.3.3", - "svelte": "^4.2.19", - "svelte-check": "^3.8.6", - "tslib": "^2.8.1", - "typescript": "5.5.4", - "vite": "^5.4.13", - "vitest": "^1.6.0" + "tslib": "2.8.1" } } diff --git a/examples/with-svelte/apps/docs/src/index.test.ts b/examples/with-svelte/apps/docs/src/index.test.ts deleted file mode 100644 index e07cbbd72507c..0000000000000 --- a/examples/with-svelte/apps/docs/src/index.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -describe('sum test', () => { - it('adds 1 + 2 to equal 3', () => { - expect(1 + 2).toBe(3); - }); -}); diff --git a/examples/with-svelte/apps/web/.prettierignore b/examples/with-svelte/apps/web/.prettierignore deleted file mode 100644 index 7438ef36043ff..0000000000000 --- a/examples/with-svelte/apps/web/.prettierignore +++ /dev/null @@ -1,14 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock -vite.config.*.timestamp-* diff --git a/examples/with-svelte/apps/web/.prettierrc b/examples/with-svelte/apps/web/.prettierrc deleted file mode 100644 index 95730232b6b16..0000000000000 --- a/examples/with-svelte/apps/web/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "useTabs": true, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100, - "plugins": ["prettier-plugin-svelte"], - "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] -} diff --git a/examples/with-svelte/apps/web/README.md b/examples/with-svelte/apps/web/README.md deleted file mode 100644 index 5c91169b0ca65..0000000000000 --- a/examples/with-svelte/apps/web/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# create-svelte - -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). - -## Creating a project - -If you're seeing this, you've probably already done this step. Congrats! - -```bash -# create a new project in the current directory -npm create svelte@latest - -# create a new project in my-app -npm create svelte@latest my-app -``` - -## Developing - -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: - -```bash -npm run dev - -# or start the server and open the app in a new browser tab -npm run dev -- --open -``` - -## Building - -To create a production version of your app: - -```bash -npm run build -``` - -You can preview the production build with `npm run preview`. - -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/examples/with-svelte/apps/web/src/app.d.ts b/examples/with-svelte/apps/web/Source/app.d.ts similarity index 100% rename from examples/with-svelte/apps/web/src/app.d.ts rename to examples/with-svelte/apps/web/Source/app.d.ts diff --git a/examples/with-svelte/apps/web/src/app.html b/examples/with-svelte/apps/web/Source/app.html similarity index 100% rename from examples/with-svelte/apps/web/src/app.html rename to examples/with-svelte/apps/web/Source/app.html diff --git a/examples/with-svelte/apps/web/src/lib/index.ts b/examples/with-svelte/apps/web/Source/lib/index.ts similarity index 100% rename from examples/with-svelte/apps/web/src/lib/index.ts rename to examples/with-svelte/apps/web/Source/lib/index.ts diff --git a/examples/with-svelte/apps/web/src/routes/+page.svelte b/examples/with-svelte/apps/web/Source/routes/+page.svelte similarity index 100% rename from examples/with-svelte/apps/web/src/routes/+page.svelte rename to examples/with-svelte/apps/web/Source/routes/+page.svelte diff --git a/examples/with-svelte/apps/web/eslint.config.js b/examples/with-svelte/apps/web/eslint.config.js deleted file mode 100644 index 729e9cc9f9c8f..0000000000000 --- a/examples/with-svelte/apps/web/eslint.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { config } from '@repo/eslint-config/index.js'; - -export default [ - ...config, - { - ignores: ['.svelte-kit/*'] - } -]; diff --git a/examples/with-svelte/apps/web/package.json b/examples/with-svelte/apps/web/package.json index 3eac51f31d782..d8bb1d4c8e02c 100644 --- a/examples/with-svelte/apps/web/package.json +++ b/examples/with-svelte/apps/web/package.json @@ -1,17 +1,11 @@ { "name": "web", - "version": "0.0.1", - "private": true, - "type": "module", "scripts": { - "dev": "vite dev", "build": "vite build", - "preview": "vite preview", - "test": "npm run test:integration && npm run test:unit", "check-types": "tsc --noEmit", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "eslint .", + "dev": "vite dev", + "preview": "vite preview", "test:integration": "playwright test", "test:unit": "vitest" }, @@ -21,16 +15,6 @@ "devDependencies": { "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@sveltejs/adapter-auto": "^3.3.1", - "@sveltejs/kit": "^2.16.0", - "@sveltejs/vite-plugin-svelte": "^3.1.2", - "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.3.3", - "svelte": "^4.2.19", - "svelte-check": "^3.8.6", - "tslib": "^2.8.1", - "typescript": "5.5.4", - "vite": "^5.4.13", - "vitest": "^1.6.0" + "tslib": "2.8.1" } } diff --git a/examples/with-svelte/apps/web/src/index.test.ts b/examples/with-svelte/apps/web/src/index.test.ts deleted file mode 100644 index e07cbbd72507c..0000000000000 --- a/examples/with-svelte/apps/web/src/index.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -describe('sum test', () => { - it('adds 1 + 2 to equal 3', () => { - expect(1 + 2).toBe(3); - }); -}); diff --git a/examples/with-svelte/package.json b/examples/with-svelte/package.json index 4e187d05b2fe1..85d8a5b566c9a 100644 --- a/examples/with-svelte/package.json +++ b/examples/with-svelte/package.json @@ -1,19 +1,11 @@ { - "name": "with-svelte", - "private": true, - "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "format": "prettier --write ." - }, - "devDependencies": { - "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.3.3", - "turbo": "^2.3.4" - }, - "packageManager": "pnpm@8.15.6", - "engines": { - "node": ">=18" - } + "name": "with-svelte", + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-svelte/packages/eslint-config/package.json b/examples/with-svelte/packages/eslint-config/package.json index 7eb78300237db..ffcdd6181d7c6 100644 --- a/examples/with-svelte/packages/eslint-config/package.json +++ b/examples/with-svelte/packages/eslint-config/package.json @@ -1,17 +1,9 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "type": "module", - "publishConfig": { - "access": "public" - }, - "devDependencies": { - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.19.0", - "eslint-config-prettier": "^10.0.1", - "eslint-config-turbo": "^2.3.4", - "eslint-plugin-svelte": "^2.46.1", - "globals": "^15.14.0", - "typescript-eslint": "^8.22.0" - } + "name": "@repo/eslint-config", + "dependencies": {}, + "devDependencies": { + "eslint-config-turbo": "2.4.2", + "eslint-plugin-svelte": "2.46.1", + "globals": "15.15.0" + } } diff --git a/examples/with-svelte/packages/typescript-config/package.json b/examples/with-svelte/packages/typescript-config/package.json index f97a642ac6ea9..0b30de456c71c 100644 --- a/examples/with-svelte/packages/typescript-config/package.json +++ b/examples/with-svelte/packages/typescript-config/package.json @@ -1,10 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "type": "module", - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-svelte/packages/ui/eslint.config.js b/examples/with-svelte/packages/ui/eslint.config.js deleted file mode 100644 index 9cadde2d02f44..0000000000000 --- a/examples/with-svelte/packages/ui/eslint.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import { config } from '@repo/eslint-config/index.js'; - -export default config; diff --git a/examples/with-svelte/packages/ui/package.json b/examples/with-svelte/packages/ui/package.json index 7cf71aa5be1b8..333916c632ea0 100644 --- a/examples/with-svelte/packages/ui/package.json +++ b/examples/with-svelte/packages/ui/package.json @@ -1,20 +1,16 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "type": "module", - "module": "index.ts", - "main": "index.ts", - "exports": { - ".": { - "types": "./index.ts", - "svelte": "./index.ts" - } - }, - "scripts": { - "lint": "eslint ." - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "svelte": "^5.19.3" - } + "name": "@repo/ui", + "exports": { + ".": { + "svelte": "./index.ts", + "types": "./index.ts" + } + }, + "main": "index.ts", + "module": "index.ts", + "scripts": {}, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*" + } } diff --git a/examples/with-svelte/pnpm-lock.yaml b/examples/with-svelte/pnpm-lock.yaml deleted file mode 100644 index b5a1e5e9a3beb..0000000000000 --- a/examples/with-svelte/pnpm-lock.yaml +++ /dev/null @@ -1,2954 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - prettier: - specifier: ^3.4.2 - version: 3.4.2 - prettier-plugin-svelte: - specifier: ^3.3.3 - version: 3.3.3(prettier@3.4.2)(svelte@5.19.3) - turbo: - specifier: ^2.3.4 - version: 2.3.4 - - apps/docs: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@sveltejs/adapter-auto': - specifier: ^3.3.1 - version: 3.3.1(@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14)) - '@sveltejs/kit': - specifier: ^2.16.0 - version: 2.16.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14) - '@sveltejs/vite-plugin-svelte': - specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.19)(vite@5.4.14) - prettier: - specifier: ^3.4.2 - version: 3.4.2 - prettier-plugin-svelte: - specifier: ^3.3.3 - version: 3.3.3(prettier@3.4.2)(svelte@4.2.19) - svelte: - specifier: ^4.2.19 - version: 4.2.19 - svelte-check: - specifier: ^3.8.6 - version: 3.8.6(postcss-load-config@3.1.4(postcss@8.5.1))(postcss@8.5.1)(svelte@4.2.19) - tslib: - specifier: ^2.8.1 - version: 2.8.1 - typescript: - specifier: 5.5.4 - version: 5.5.4 - vite: - specifier: ^5.4.13 - version: 5.4.14 - vitest: - specifier: ^1.6.0 - version: 1.6.0 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@sveltejs/adapter-auto': - specifier: ^3.3.1 - version: 3.3.1(@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14)) - '@sveltejs/kit': - specifier: ^2.16.0 - version: 2.16.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14) - '@sveltejs/vite-plugin-svelte': - specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.19)(vite@5.4.14) - prettier: - specifier: ^3.4.2 - version: 3.4.2 - prettier-plugin-svelte: - specifier: ^3.3.3 - version: 3.3.3(prettier@3.4.2)(svelte@4.2.19) - svelte: - specifier: ^4.2.19 - version: 4.2.19 - svelte-check: - specifier: ^3.8.6 - version: 3.8.6(postcss-load-config@3.1.4(postcss@8.5.1))(postcss@8.5.1)(svelte@4.2.19) - tslib: - specifier: ^2.8.1 - version: 2.8.1 - typescript: - specifier: 5.5.4 - version: 5.5.4 - vite: - specifier: ^5.4.13 - version: 5.4.14 - vitest: - specifier: ^1.6.0 - version: 1.6.0 - - packages/eslint-config: - devDependencies: - '@eslint/eslintrc': - specifier: ^3.2.0 - version: 3.2.0 - '@eslint/js': - specifier: ^9.19.0 - version: 9.19.0 - eslint-config-prettier: - specifier: ^10.0.1 - version: 10.0.1(eslint@9.19.0) - eslint-config-turbo: - specifier: ^2.3.4 - version: 2.3.4(eslint@9.19.0)(turbo@2.3.4) - eslint-plugin-svelte: - specifier: ^2.46.1 - version: 2.46.1(eslint@9.19.0)(svelte@5.19.3) - globals: - specifier: ^15.14.0 - version: 15.14.0 - typescript-eslint: - specifier: ^8.22.0 - version: 8.22.0(eslint@9.19.0)(typescript@5.7.3) - - packages/typescript-config: {} - - packages/ui: - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - svelte: - specifier: ^5.19.3 - version: 5.19.3 - -packages: - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.19.1': - resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.10.0': - resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.2.0': - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.19.0': - resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.5': - resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.2.5': - resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - - '@humanwhocodes/retry@0.4.1': - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} - engines: {node: '>=18.18'} - - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@polka/url@1.0.0-next.28': - resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} - - '@rollup/rollup-android-arm-eabi@4.32.0': - resolution: {integrity: sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.32.0': - resolution: {integrity: sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.32.0': - resolution: {integrity: sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.32.0': - resolution: {integrity: sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.32.0': - resolution: {integrity: sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.32.0': - resolution: {integrity: sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.32.0': - resolution: {integrity: sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.32.0': - resolution: {integrity: sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.32.0': - resolution: {integrity: sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.32.0': - resolution: {integrity: sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-loongarch64-gnu@4.32.0': - resolution: {integrity: sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw==} - cpu: [loong64] - os: [linux] - - '@rollup/rollup-linux-powerpc64le-gnu@4.32.0': - resolution: {integrity: sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.32.0': - resolution: {integrity: sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.32.0': - resolution: {integrity: sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.32.0': - resolution: {integrity: sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.32.0': - resolution: {integrity: sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-win32-arm64-msvc@4.32.0': - resolution: {integrity: sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.32.0': - resolution: {integrity: sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.32.0': - resolution: {integrity: sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA==} - cpu: [x64] - os: [win32] - - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - - '@sveltejs/adapter-auto@3.3.1': - resolution: {integrity: sha512-5Sc7WAxYdL6q9j/+D0jJKjGREGlfIevDyHSQ2eNETHcB1TKlQWHcAo8AS8H1QdjNvSXpvOwNjykDUHPEAyGgdQ==} - peerDependencies: - '@sveltejs/kit': ^2.0.0 - - '@sveltejs/kit@2.16.1': - resolution: {integrity: sha512-2pF5sgGJx9brYZ/9nNDYnh5KX0JguPF14dnvvtf/MqrvlWrDj/e7Rk3LBJPecFLLK1GRs6ZniD24gFPqZm/NFw==} - engines: {node: '>=18.13'} - hasBin: true - peerDependencies: - '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.3 || ^6.0.0 - - '@sveltejs/vite-plugin-svelte-inspector@2.1.0': - resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} - engines: {node: ^18.0.0 || >=20} - peerDependencies: - '@sveltejs/vite-plugin-svelte': ^3.0.0 - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.0 - - '@sveltejs/vite-plugin-svelte@3.1.2': - resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} - engines: {node: ^18.0.0 || >=20} - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.0 - - '@types/cookie@0.6.0': - resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} - - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/pug@2.0.10': - resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} - - '@typescript-eslint/eslint-plugin@8.22.0': - resolution: {integrity: sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/parser@8.22.0': - resolution: {integrity: sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/scope-manager@8.22.0': - resolution: {integrity: sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/type-utils@8.22.0': - resolution: {integrity: sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/types@8.22.0': - resolution: {integrity: sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.22.0': - resolution: {integrity: sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/utils@8.22.0': - resolution: {integrity: sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/visitor-keys@8.22.0': - resolution: {integrity: sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@vitest/expect@1.6.0': - resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} - - '@vitest/runner@1.6.0': - resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} - - '@vitest/snapshot@1.6.0': - resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} - - '@vitest/spy@1.6.0': - resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} - - '@vitest/utils@1.6.0': - resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn-typescript@1.4.13: - resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} - peerDependencies: - acorn: '>=8.9.0' - - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - buffer-crc32@1.0.0: - resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} - engines: {node: '>=8.0.0'} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - chai@4.5.0: - resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - - code-red@1.0.4: - resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - confbox@0.1.8: - resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - - cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - - devalue@5.1.1: - resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} - - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - - es6-promise@3.3.1: - resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} - - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-compat-utils@0.5.1: - resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} - engines: {node: '>=12'} - peerDependencies: - eslint: '>=6.0.0' - - eslint-config-prettier@10.0.1: - resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-config-turbo@2.3.4: - resolution: {integrity: sha512-MxPl+IKkR7mRGcHoiZAMHYl+RZnjqBsxTLf+IGnx8BrJQe9/CoLT7oBlUxXGvh9bsd5MTaqCxly5h8BE1v/7AA==} - peerDependencies: - eslint: '>6.6.0' - turbo: '>2.0.0' - - eslint-plugin-svelte@2.46.1: - resolution: {integrity: sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==} - engines: {node: ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 - svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - svelte: - optional: true - - eslint-plugin-turbo@2.3.4: - resolution: {integrity: sha512-9ncoUJkQGkC28NmlQiS17oB9mrE8XaSulRZiB5pv9vmRbYjOfUwyGhY3EIcoBRdww81igxOzXmAmvNNd6GFBPg==} - peerDependencies: - eslint: '>6.6.0' - turbo: '>2.0.0' - - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.19.0: - resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - esm-env@1.2.2: - resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} - - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrap@1.4.3: - resolution: {integrity: sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.18.0: - resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globals@15.14.0: - resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} - engines: {node: '>=18'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - import-meta-resolve@4.1.0: - resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-reference@3.0.3: - resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} - - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - js-tokens@9.0.1: - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - - known-css-properties@0.35.0: - resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - - local-pkg@0.5.1: - resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} - engines: {node: '>=14'} - - locate-character@3.0.0: - resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - - mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mlly@1.7.4: - resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} - - mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - - mrmime@2.0.0: - resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} - engines: {node: '>=10'} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - - pathe@2.0.2: - resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==} - - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - periscopic@3.1.0: - resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pkg-types@1.3.1: - resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - - postcss-load-config@3.1.4: - resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} - engines: {node: '>= 10'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - - postcss-safe-parser@6.0.0: - resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.3.3 - - postcss-scss@4.0.9: - resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.4.29 - - postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} - engines: {node: '>=4'} - - postcss@8.5.1: - resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier-plugin-svelte@3.3.3: - resolution: {integrity: sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==} - peerDependencies: - prettier: ^3.0.0 - svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 - - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} - engines: {node: '>=14'} - hasBin: true - - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rimraf@2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - - rollup@4.32.0: - resolution: {integrity: sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - sade@1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} - - sander@0.5.1: - resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - set-cookie-parser@2.7.1: - resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - sirv@3.0.0: - resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==} - engines: {node: '>=18'} - - sorcery@0.11.1: - resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==} - hasBin: true - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@3.8.0: - resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - strip-literal@2.1.1: - resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - svelte-check@3.8.6: - resolution: {integrity: sha512-ij0u4Lw/sOTREP13BdWZjiXD/BlHE6/e2e34XzmVmsp5IN4kVa3PWP65NM32JAgwjZlwBg/+JtiNV1MM8khu0Q==} - hasBin: true - peerDependencies: - svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 - - svelte-eslint-parser@0.43.0: - resolution: {integrity: sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - svelte: - optional: true - - svelte-hmr@0.16.0: - resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} - engines: {node: ^12.20 || ^14.13.1 || >= 16} - peerDependencies: - svelte: ^3.19.0 || ^4.0.0 - - svelte-preprocess@5.1.4: - resolution: {integrity: sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==} - engines: {node: '>= 16.0.0'} - peerDependencies: - '@babel/core': ^7.10.2 - coffeescript: ^2.5.1 - less: ^3.11.3 || ^4.0.0 - postcss: ^7 || ^8 - postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 - pug: ^3.0.0 - sass: ^1.26.8 - stylus: ^0.55.0 - sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 - svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 - typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0' - peerDependenciesMeta: - '@babel/core': - optional: true - coffeescript: - optional: true - less: - optional: true - postcss: - optional: true - postcss-load-config: - optional: true - pug: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - typescript: - optional: true - - svelte@4.2.19: - resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} - engines: {node: '>=16'} - - svelte@5.19.3: - resolution: {integrity: sha512-rb/bkYG9jq67OCWikMvaPnfOobyGn0JizVDwHpdeBtLiNXPMcoA9GTFC3BhptP7xGNquUU8J5GiS7PlGlfDAFA==} - engines: {node: '>=18'} - - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} - engines: {node: '>=14.0.0'} - - tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} - engines: {node: '>=14.0.0'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - totalist@3.0.1: - resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} - engines: {node: '>=6'} - - ts-api-utils@2.0.0: - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - turbo-darwin-64@2.3.4: - resolution: {integrity: sha512-uOi/cUIGQI7uakZygH+cZQ5D4w+aMLlVCN2KTGot+cmefatps2ZmRRufuHrEM0Rl63opdKD8/JIu+54s25qkfg==} - cpu: [x64] - os: [darwin] - - turbo-darwin-arm64@2.3.4: - resolution: {integrity: sha512-IIM1Lq5R+EGMtM1YFGl4x8Xkr0MWb4HvyU8N4LNoQ1Be5aycrOE+VVfH+cDg/Q4csn+8bxCOxhRp5KmUflrVTQ==} - cpu: [arm64] - os: [darwin] - - turbo-linux-64@2.3.4: - resolution: {integrity: sha512-1aD2EfR7NfjFXNH3mYU5gybLJEFi2IGOoKwoPLchAFRQ6OEJQj201/oNo9CDL75IIrQo64/NpEgVyZtoPlfhfA==} - cpu: [x64] - os: [linux] - - turbo-linux-arm64@2.3.4: - resolution: {integrity: sha512-MxTpdKwxCaA5IlybPxgGLu54fT2svdqTIxRd0TQmpRJIjM0s4kbM+7YiLk0mOh6dGqlWPUsxz/A0Mkn8Xr5o7Q==} - cpu: [arm64] - os: [linux] - - turbo-windows-64@2.3.4: - resolution: {integrity: sha512-yyCrWqcRGu1AOOlrYzRnizEtdkqi+qKP0MW9dbk9OsMDXaOI5jlWtTY/AtWMkLw/czVJ7yS9Ex1vi9DB6YsFvw==} - cpu: [x64] - os: [win32] - - turbo-windows-arm64@2.3.4: - resolution: {integrity: sha512-PggC3qH+njPfn1PDVwKrQvvQby8X09ufbqZ2Ha4uSu+5TvPorHHkAbZVHKYj2Y+tvVzxRzi4Sv6NdHXBS9Be5w==} - cpu: [arm64] - os: [win32] - - turbo@2.3.4: - resolution: {integrity: sha512-1kiLO5C0Okh5ay1DbHsxkPsw9Sjsbjzm6cF85CpWjR0BIyBFNDbKqtUyqGADRS1dbbZoQanJZVj4MS5kk8J42Q==} - hasBin: true - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-detect@4.1.0: - resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} - engines: {node: '>=4'} - - typescript-eslint@8.22.0: - resolution: {integrity: sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} - engines: {node: '>=14.17'} - hasBin: true - - ufo@1.5.4: - resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - vite-node@1.6.0: - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - - vite@5.4.14: - resolution: {integrity: sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - vitefu@0.2.5: - resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - vite: - optional: true - - vitest@1.6.0: - resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.0 - '@vitest/ui': 1.6.0 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - yocto-queue@1.1.1: - resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} - engines: {node: '>=12.20'} - - zimmerframe@1.1.2: - resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} - -snapshots: - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/openbsd-x64@0.21.5': - optional: true - - '@esbuild/sunos-x64@0.21.5': - optional: true - - '@esbuild/win32-arm64@0.21.5': - optional: true - - '@esbuild/win32-ia32@0.21.5': - optional: true - - '@esbuild/win32-x64@0.21.5': - optional: true - - '@eslint-community/eslint-utils@4.4.1(eslint@9.19.0)': - dependencies: - eslint: 9.19.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/config-array@0.19.1': - dependencies: - '@eslint/object-schema': 2.1.5 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/core@0.10.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.2.0': - dependencies: - ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.19.0': {} - - '@eslint/object-schema@2.1.5': {} - - '@eslint/plugin-kit@0.2.5': - dependencies: - '@eslint/core': 0.10.0 - levn: 0.4.1 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.6': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.3.1': {} - - '@humanwhocodes/retry@0.4.1': {} - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - - '@jridgewell/gen-mapping@0.3.8': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.18.0 - - '@polka/url@1.0.0-next.28': {} - - '@rollup/rollup-android-arm-eabi@4.32.0': - optional: true - - '@rollup/rollup-android-arm64@4.32.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.32.0': - optional: true - - '@rollup/rollup-darwin-x64@4.32.0': - optional: true - - '@rollup/rollup-freebsd-arm64@4.32.0': - optional: true - - '@rollup/rollup-freebsd-x64@4.32.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.32.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.32.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.32.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.32.0': - optional: true - - '@rollup/rollup-linux-loongarch64-gnu@4.32.0': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.32.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.32.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.32.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.32.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.32.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.32.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.32.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.32.0': - optional: true - - '@sinclair/typebox@0.27.8': {} - - '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14))': - dependencies: - '@sveltejs/kit': 2.16.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14) - import-meta-resolve: 4.1.0 - - '@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14)': - dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.14) - '@types/cookie': 0.6.0 - cookie: 0.6.0 - devalue: 5.1.1 - esm-env: 1.2.2 - import-meta-resolve: 4.1.0 - kleur: 4.1.5 - magic-string: 0.30.17 - mrmime: 2.0.0 - sade: 1.8.1 - set-cookie-parser: 2.7.1 - sirv: 3.0.0 - svelte: 4.2.19 - vite: 5.4.14 - - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14)': - dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.14) - debug: 4.4.0 - svelte: 4.2.19 - vite: 5.4.14 - transitivePeerDependencies: - - supports-color - - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14)': - dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.14))(svelte@4.2.19)(vite@5.4.14) - debug: 4.4.0 - deepmerge: 4.3.1 - kleur: 4.1.5 - magic-string: 0.30.17 - svelte: 4.2.19 - svelte-hmr: 0.16.0(svelte@4.2.19) - vite: 5.4.14 - vitefu: 0.2.5(vite@5.4.14) - transitivePeerDependencies: - - supports-color - - '@types/cookie@0.6.0': {} - - '@types/estree@1.0.6': {} - - '@types/json-schema@7.0.15': {} - - '@types/pug@2.0.10': {} - - '@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/type-utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - eslint: 9.19.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - - '@typescript-eslint/type-utils@8.22.0(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - debug: 4.4.0 - eslint: 9.19.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.22.0': {} - - '@typescript-eslint/typescript-estree@8.22.0(typescript@5.7.3)': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.22.0(eslint@9.19.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 - eslint-visitor-keys: 4.2.0 - - '@vitest/expect@1.6.0': - dependencies: - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - chai: 4.5.0 - - '@vitest/runner@1.6.0': - dependencies: - '@vitest/utils': 1.6.0 - p-limit: 5.0.0 - pathe: 1.1.2 - - '@vitest/snapshot@1.6.0': - dependencies: - magic-string: 0.30.17 - pathe: 1.1.2 - pretty-format: 29.7.0 - - '@vitest/spy@1.6.0': - dependencies: - tinyspy: 2.2.1 - - '@vitest/utils@1.6.0': - dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 - - acorn-jsx@5.3.2(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn-typescript@1.4.13(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn-walk@8.3.4: - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - argparse@2.0.1: {} - - aria-query@5.3.2: {} - - assertion-error@1.1.0: {} - - axobject-query@4.1.0: {} - - balanced-match@1.0.2: {} - - binary-extensions@2.3.0: {} - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - buffer-crc32@1.0.0: {} - - cac@6.7.14: {} - - callsites@3.1.0: {} - - chai@4.5.0: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.1.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - clsx@2.1.1: {} - - code-red@1.0.4: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - acorn: 8.14.0 - estree-walker: 3.0.3 - periscopic: 3.1.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - concat-map@0.0.1: {} - - confbox@0.1.8: {} - - cookie@0.6.0: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - css-tree@2.3.1: - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.2.1 - - cssesc@3.0.0: {} - - debug@4.4.0: - dependencies: - ms: 2.1.3 - - deep-eql@4.1.4: - dependencies: - type-detect: 4.1.0 - - deep-is@0.1.4: {} - - deepmerge@4.3.1: {} - - detect-indent@6.1.0: {} - - devalue@5.1.1: {} - - diff-sequences@29.6.3: {} - - dotenv@16.0.3: {} - - es6-promise@3.3.1: {} - - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - escape-string-regexp@4.0.0: {} - - eslint-compat-utils@0.5.1(eslint@9.19.0): - dependencies: - eslint: 9.19.0 - semver: 7.6.3 - - eslint-config-prettier@10.0.1(eslint@9.19.0): - dependencies: - eslint: 9.19.0 - - eslint-config-turbo@2.3.4(eslint@9.19.0)(turbo@2.3.4): - dependencies: - eslint: 9.19.0 - eslint-plugin-turbo: 2.3.4(eslint@9.19.0)(turbo@2.3.4) - turbo: 2.3.4 - - eslint-plugin-svelte@2.46.1(eslint@9.19.0)(svelte@5.19.3): - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@jridgewell/sourcemap-codec': 1.5.0 - eslint: 9.19.0 - eslint-compat-utils: 0.5.1(eslint@9.19.0) - esutils: 2.0.3 - known-css-properties: 0.35.0 - postcss: 8.5.1 - postcss-load-config: 3.1.4(postcss@8.5.1) - postcss-safe-parser: 6.0.0(postcss@8.5.1) - postcss-selector-parser: 6.1.2 - semver: 7.6.3 - svelte-eslint-parser: 0.43.0(svelte@5.19.3) - optionalDependencies: - svelte: 5.19.3 - transitivePeerDependencies: - - ts-node - - eslint-plugin-turbo@2.3.4(eslint@9.19.0)(turbo@2.3.4): - dependencies: - dotenv: 16.0.3 - eslint: 9.19.0 - turbo: 2.3.4 - - eslint-scope@7.2.2: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-scope@8.2.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.0: {} - - eslint@9.19.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.1 - '@eslint/core': 0.10.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.19.0 - '@eslint/plugin-kit': 0.2.5 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - - esm-env@1.2.2: {} - - espree@10.3.0: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - - espree@9.6.1: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 3.4.3 - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrap@1.4.3: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.6 - - esutils@2.0.3: {} - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.18.0: - dependencies: - reusify: 1.0.4 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - - flatted@3.3.2: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - get-func-name@2.0.2: {} - - get-stream@8.0.1: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - globals@14.0.0: {} - - globals@15.14.0: {} - - graceful-fs@4.2.11: {} - - graphemer@1.4.0: {} - - has-flag@4.0.0: {} - - human-signals@5.0.0: {} - - ignore@5.3.2: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - import-meta-resolve@4.1.0: {} - - imurmurhash@0.1.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-reference@3.0.3: - dependencies: - '@types/estree': 1.0.6 - - is-stream@3.0.0: {} - - isexe@2.0.0: {} - - js-tokens@9.0.1: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - kleur@4.1.5: {} - - known-css-properties@0.35.0: {} - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lilconfig@2.1.0: {} - - local-pkg@0.5.1: - dependencies: - mlly: 1.7.4 - pkg-types: 1.3.1 - - locate-character@3.0.0: {} - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.merge@4.6.2: {} - - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - magic-string@0.30.17: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - mdn-data@2.0.30: {} - - merge-stream@2.0.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mimic-fn@4.0.0: {} - - min-indent@1.0.1: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 - - minimist@1.2.8: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mlly@1.7.4: - dependencies: - acorn: 8.14.0 - pathe: 2.0.2 - pkg-types: 1.3.1 - ufo: 1.5.4 - - mri@1.2.0: {} - - mrmime@2.0.0: {} - - ms@2.1.3: {} - - nanoid@3.3.8: {} - - natural-compare@1.4.0: {} - - normalize-path@3.0.0: {} - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-limit@5.0.0: - dependencies: - yocto-queue: 1.1.1 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-key@4.0.0: {} - - pathe@1.1.2: {} - - pathe@2.0.2: {} - - pathval@1.1.1: {} - - periscopic@3.1.0: - dependencies: - '@types/estree': 1.0.6 - estree-walker: 3.0.3 - is-reference: 3.0.3 - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - pkg-types@1.3.1: - dependencies: - confbox: 0.1.8 - mlly: 1.7.4 - pathe: 2.0.2 - - postcss-load-config@3.1.4(postcss@8.5.1): - dependencies: - lilconfig: 2.1.0 - yaml: 1.10.2 - optionalDependencies: - postcss: 8.5.1 - - postcss-safe-parser@6.0.0(postcss@8.5.1): - dependencies: - postcss: 8.5.1 - - postcss-scss@4.0.9(postcss@8.5.1): - dependencies: - postcss: 8.5.1 - - postcss-selector-parser@6.1.2: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss@8.5.1: - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - prettier-plugin-svelte@3.3.3(prettier@3.4.2)(svelte@4.2.19): - dependencies: - prettier: 3.4.2 - svelte: 4.2.19 - - prettier-plugin-svelte@3.3.3(prettier@3.4.2)(svelte@5.19.3): - dependencies: - prettier: 3.4.2 - svelte: 5.19.3 - - prettier@3.4.2: {} - - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - react-is@18.3.1: {} - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - resolve-from@4.0.0: {} - - reusify@1.0.4: {} - - rimraf@2.7.1: - dependencies: - glob: 7.2.3 - - rollup@4.32.0: - dependencies: - '@types/estree': 1.0.6 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.32.0 - '@rollup/rollup-android-arm64': 4.32.0 - '@rollup/rollup-darwin-arm64': 4.32.0 - '@rollup/rollup-darwin-x64': 4.32.0 - '@rollup/rollup-freebsd-arm64': 4.32.0 - '@rollup/rollup-freebsd-x64': 4.32.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.32.0 - '@rollup/rollup-linux-arm-musleabihf': 4.32.0 - '@rollup/rollup-linux-arm64-gnu': 4.32.0 - '@rollup/rollup-linux-arm64-musl': 4.32.0 - '@rollup/rollup-linux-loongarch64-gnu': 4.32.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.32.0 - '@rollup/rollup-linux-riscv64-gnu': 4.32.0 - '@rollup/rollup-linux-s390x-gnu': 4.32.0 - '@rollup/rollup-linux-x64-gnu': 4.32.0 - '@rollup/rollup-linux-x64-musl': 4.32.0 - '@rollup/rollup-win32-arm64-msvc': 4.32.0 - '@rollup/rollup-win32-ia32-msvc': 4.32.0 - '@rollup/rollup-win32-x64-msvc': 4.32.0 - fsevents: 2.3.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - sade@1.8.1: - dependencies: - mri: 1.2.0 - - sander@0.5.1: - dependencies: - es6-promise: 3.3.1 - graceful-fs: 4.2.11 - mkdirp: 0.5.6 - rimraf: 2.7.1 - - semver@7.6.3: {} - - set-cookie-parser@2.7.1: {} - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - siginfo@2.0.0: {} - - signal-exit@4.1.0: {} - - sirv@3.0.0: - dependencies: - '@polka/url': 1.0.0-next.28 - mrmime: 2.0.0 - totalist: 3.0.1 - - sorcery@0.11.1: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - buffer-crc32: 1.0.0 - minimist: 1.2.8 - sander: 0.5.1 - - source-map-js@1.2.1: {} - - stackback@0.0.2: {} - - std-env@3.8.0: {} - - strip-final-newline@3.0.0: {} - - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - - strip-json-comments@3.1.1: {} - - strip-literal@2.1.1: - dependencies: - js-tokens: 9.0.1 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - svelte-check@3.8.6(postcss-load-config@3.1.4(postcss@8.5.1))(postcss@8.5.1)(svelte@4.2.19): - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - chokidar: 3.6.0 - picocolors: 1.1.1 - sade: 1.8.1 - svelte: 4.2.19 - svelte-preprocess: 5.1.4(postcss-load-config@3.1.4(postcss@8.5.1))(postcss@8.5.1)(svelte@4.2.19)(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - '@babel/core' - - coffeescript - - less - - postcss - - postcss-load-config - - pug - - sass - - stylus - - sugarss - - svelte-eslint-parser@0.43.0(svelte@5.19.3): - dependencies: - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - postcss: 8.5.1 - postcss-scss: 4.0.9(postcss@8.5.1) - optionalDependencies: - svelte: 5.19.3 - - svelte-hmr@0.16.0(svelte@4.2.19): - dependencies: - svelte: 4.2.19 - - svelte-preprocess@5.1.4(postcss-load-config@3.1.4(postcss@8.5.1))(postcss@8.5.1)(svelte@4.2.19)(typescript@5.5.4): - dependencies: - '@types/pug': 2.0.10 - detect-indent: 6.1.0 - magic-string: 0.30.17 - sorcery: 0.11.1 - strip-indent: 3.0.0 - svelte: 4.2.19 - optionalDependencies: - postcss: 8.5.1 - postcss-load-config: 3.1.4(postcss@8.5.1) - typescript: 5.5.4 - - svelte@4.2.19: - dependencies: - '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - '@types/estree': 1.0.6 - acorn: 8.14.0 - aria-query: 5.3.2 - axobject-query: 4.1.0 - code-red: 1.0.4 - css-tree: 2.3.1 - estree-walker: 3.0.3 - is-reference: 3.0.3 - locate-character: 3.0.0 - magic-string: 0.30.17 - periscopic: 3.1.0 - - svelte@5.19.3: - dependencies: - '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - acorn: 8.14.0 - acorn-typescript: 1.4.13(acorn@8.14.0) - aria-query: 5.3.2 - axobject-query: 4.1.0 - clsx: 2.1.1 - esm-env: 1.2.2 - esrap: 1.4.3 - is-reference: 3.0.3 - locate-character: 3.0.0 - magic-string: 0.30.17 - zimmerframe: 1.1.2 - - tinybench@2.9.0: {} - - tinypool@0.8.4: {} - - tinyspy@2.2.1: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - totalist@3.0.1: {} - - ts-api-utils@2.0.0(typescript@5.7.3): - dependencies: - typescript: 5.7.3 - - tslib@2.8.1: {} - - turbo-darwin-64@2.3.4: - optional: true - - turbo-darwin-arm64@2.3.4: - optional: true - - turbo-linux-64@2.3.4: - optional: true - - turbo-linux-arm64@2.3.4: - optional: true - - turbo-windows-64@2.3.4: - optional: true - - turbo-windows-arm64@2.3.4: - optional: true - - turbo@2.3.4: - optionalDependencies: - turbo-darwin-64: 2.3.4 - turbo-darwin-arm64: 2.3.4 - turbo-linux-64: 2.3.4 - turbo-linux-arm64: 2.3.4 - turbo-windows-64: 2.3.4 - turbo-windows-arm64: 2.3.4 - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-detect@4.1.0: {} - - typescript-eslint@8.22.0(eslint@9.19.0)(typescript@5.7.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3) - eslint: 9.19.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - typescript@5.5.4: {} - - typescript@5.7.3: {} - - ufo@1.5.4: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - util-deprecate@1.0.2: {} - - vite-node@1.6.0: - dependencies: - cac: 6.7.14 - debug: 4.4.0 - pathe: 1.1.2 - picocolors: 1.1.1 - vite: 5.4.14 - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - vite@5.4.14: - dependencies: - esbuild: 0.21.5 - postcss: 8.5.1 - rollup: 4.32.0 - optionalDependencies: - fsevents: 2.3.3 - - vitefu@0.2.5(vite@5.4.14): - optionalDependencies: - vite: 5.4.14 - - vitest@1.6.0: - dependencies: - '@vitest/expect': 1.6.0 - '@vitest/runner': 1.6.0 - '@vitest/snapshot': 1.6.0 - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - acorn-walk: 8.3.4 - chai: 4.5.0 - debug: 4.4.0 - execa: 8.0.1 - local-pkg: 0.5.1 - magic-string: 0.30.17 - pathe: 1.1.2 - picocolors: 1.1.1 - std-env: 3.8.0 - strip-literal: 2.1.1 - tinybench: 2.9.0 - tinypool: 0.8.4 - vite: 5.4.14 - vite-node: 1.6.0 - why-is-node-running: 2.3.0 - transitivePeerDependencies: - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - - word-wrap@1.2.5: {} - - wrappy@1.0.2: {} - - yaml@1.10.2: {} - - yocto-queue@0.1.0: {} - - yocto-queue@1.1.1: {} - - zimmerframe@1.1.2: {} diff --git a/examples/with-tailwind/README.md b/examples/with-tailwind/README.md deleted file mode 100644 index aaeb2865901c7..0000000000000 --- a/examples/with-tailwind/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Turborepo Tailwind CSS starter - -This Turborepo starter is maintained by the Turborepo core team. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-tailwind -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [Next.js](https://nextjs.org/) app with [Tailwind CSS](https://tailwindcss.com/) -- `web`: another [Next.js](https://nextjs.org/) app with [Tailwind CSS](https://tailwindcss.com/) -- `ui`: a stub React component library with [Tailwind CSS](https://tailwindcss.com/) shared by both `web` and `docs` applications -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Building packages/ui - -This example is set up to produce compiled styles for `ui` components into the `dist` directory. The component `.tsx` files are consumed by the Next.js apps directly using `transpilePackages` in `next.config.js`. This was chosen for several reasons: - -- Make sharing one `tailwind.config.js` to apps and packages as easy as possible. -- Make package compilation simple by only depending on the Next.js Compiler and `tailwindcss`. -- Ensure Tailwind classes do not overwrite each other. The `ui` package uses a `ui-` prefix for it's classes. -- Maintain clear package export boundaries. - -Another option is to consume `packages/ui` directly from source without building. If using this option, you will need to update the `tailwind.config.js` in your apps to be aware of your package locations, so it can find all usages of the `tailwindcss` class names for CSS compilation. - -For example, in [tailwind.config.js](packages/tailwind-config/tailwind.config.js): - -```js - content: [ - // app content - `src/**/*.{js,ts,jsx,tsx}`, - // include packages if not transpiling - "../../packages/ui/*.{js,ts,jsx,tsx}", - ], -``` - -If you choose this strategy, you can remove the `tailwindcss` and `autoprefixer` dependencies from the `ui` package. - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [Tailwind CSS](https://tailwindcss.com/) for styles -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/with-tailwind/apps/docs/README.md b/examples/with-tailwind/apps/docs/README.md deleted file mode 100644 index 58dc3500fbb82..0000000000000 --- a/examples/with-tailwind/apps/docs/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3001](http://localhost:3001) with your browser to see the result. - -You can start editing the page by modifying `src/app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-tailwind/apps/docs/Source/app/favicon.ico b/examples/with-tailwind/apps/docs/Source/app/favicon.ico new file mode 100644 index 0000000000000..3f804c026c253 Binary files /dev/null and b/examples/with-tailwind/apps/docs/Source/app/favicon.ico differ diff --git a/examples/with-tailwind/apps/docs/Source/app/globals.css b/examples/with-tailwind/apps/docs/Source/app/globals.css new file mode 100644 index 0000000000000..0cfb74282659a --- /dev/null +++ b/examples/with-tailwind/apps/docs/Source/app/globals.css @@ -0,0 +1,25 @@ +@import "tailwindcss"; + +:root { + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + transparent, + rgb(var(--background-end-rgb)) + ) + rgb(var(--background-start-rgb)); +} diff --git a/examples/with-tailwind/apps/docs/Source/app/layout.tsx b/examples/with-tailwind/apps/docs/Source/app/layout.tsx new file mode 100644 index 0000000000000..dffb1cfe5ba8c --- /dev/null +++ b/examples/with-tailwind/apps/docs/Source/app/layout.tsx @@ -0,0 +1,23 @@ +import "./globals.css"; +import "@repo/ui/styles.css"; +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata: Metadata = { + title: "Create Turborepo", + description: "Generated by create turbo", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/examples/with-tailwind/apps/docs/Source/app/page.tsx b/examples/with-tailwind/apps/docs/Source/app/page.tsx new file mode 100644 index 0000000000000..00316ec212c9b --- /dev/null +++ b/examples/with-tailwind/apps/docs/Source/app/page.tsx @@ -0,0 +1,138 @@ +import Image from "next/image"; +import { Card } from "@repo/ui/card"; + +function Gradient({ + conic, + className, + small, +}: { + small?: boolean; + conic?: boolean; + className?: string; +}) { + return ( + + ); +} + +const LINKS = [ + { + title: "Docs", + href: "https://turbo.build/repo/docs", + description: "Find in-depth information about Turborepo features and API.", + }, + { + title: "Learn", + href: "https://turbo.build/repo/docs/handbook", + description: "Learn more about monorepos with our handbook.", + }, + { + title: "Templates", + href: "https://turbo.build/repo/docs/getting-started/from-example", + description: "Choose from over 15 examples and deploy with a single click.", + }, + { + title: "Deploy", + href: "https://vercel.com/new", + description: + "Instantly deploy your Turborepo to a shareable URL with Vercel.", + }, +]; + +export default function Page() { + return ( +
    + ); +} diff --git a/examples/with-tailwind/apps/docs/eslint.config.js b/examples/with-tailwind/apps/docs/eslint.config.js deleted file mode 100644 index e8759ff50fbca..0000000000000 --- a/examples/with-tailwind/apps/docs/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { nextJsConfig } from "@repo/eslint-config/next-js"; - -/** @type {import("eslint").Linter.Config} */ -export default nextJsConfig; diff --git a/examples/with-tailwind/apps/docs/package.json b/examples/with-tailwind/apps/docs/package.json index 043bd441b143f..d40e6e05e377f 100644 --- a/examples/with-tailwind/apps/docs/package.json +++ b/examples/with-tailwind/apps/docs/package.json @@ -12,21 +12,21 @@ }, "dependencies": { "@repo/ui": "workspace:*", - "next": "^15.1.6", - "react": "^19.0.0", - "react-dom": "^19.0.0" + "next": "15.1.7", + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { - "@next/eslint-plugin-next": "^15.1.6", + "@next/eslint-plugin-next": "15.1.7", "@repo/eslint-config": "workspace:*", "@repo/tailwind-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/node": "^22.12.0", - "@types/react": "^19.0.7", - "@types/react-dom": "^19.0.3", - "autoprefixer": "^10.4.20", - "postcss": "^8.5.1", - "tailwindcss": "^3.4.17", + "@types/node": "22.13.1", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", + "autoprefixer": "10.4.20", + "postcss": "8.5.2", + "tailwindcss": "3.4.17", "typescript": "5.7.3" } } diff --git a/examples/with-tailwind/apps/web/README.md b/examples/with-tailwind/apps/web/README.md deleted file mode 100644 index 04c1d97ba8efd..0000000000000 --- a/examples/with-tailwind/apps/web/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `src/app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-tailwind/apps/web/Source/app/favicon.ico b/examples/with-tailwind/apps/web/Source/app/favicon.ico new file mode 100644 index 0000000000000..3f804c026c253 Binary files /dev/null and b/examples/with-tailwind/apps/web/Source/app/favicon.ico differ diff --git a/examples/with-tailwind/apps/web/Source/app/globals.css b/examples/with-tailwind/apps/web/Source/app/globals.css new file mode 100644 index 0000000000000..0cfb74282659a --- /dev/null +++ b/examples/with-tailwind/apps/web/Source/app/globals.css @@ -0,0 +1,25 @@ +@import "tailwindcss"; + +:root { + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + transparent, + rgb(var(--background-end-rgb)) + ) + rgb(var(--background-start-rgb)); +} diff --git a/examples/with-tailwind/apps/web/Source/app/layout.tsx b/examples/with-tailwind/apps/web/Source/app/layout.tsx new file mode 100644 index 0000000000000..dffb1cfe5ba8c --- /dev/null +++ b/examples/with-tailwind/apps/web/Source/app/layout.tsx @@ -0,0 +1,23 @@ +import "./globals.css"; +import "@repo/ui/styles.css"; +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata: Metadata = { + title: "Create Turborepo", + description: "Generated by create turbo", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/examples/with-tailwind/apps/web/Source/app/page.tsx b/examples/with-tailwind/apps/web/Source/app/page.tsx new file mode 100644 index 0000000000000..7257dcec4222b --- /dev/null +++ b/examples/with-tailwind/apps/web/Source/app/page.tsx @@ -0,0 +1,138 @@ +import Image from "next/image"; +import { Card } from "@repo/ui/card"; + +function Gradient({ + conic, + className, + small, +}: { + small?: boolean; + conic?: boolean; + className?: string; +}) { + return ( + + ); +} + +const LINKS = [ + { + title: "Docs", + href: "https://turbo.build/repo/docs", + description: "Find in-depth information about Turborepo features and API.", + }, + { + title: "Learn", + href: "https://turbo.build/repo/docs/handbook", + description: "Learn more about monorepos with our handbook.", + }, + { + title: "Templates", + href: "https://turbo.build/repo/docs/getting-started/from-example", + description: "Choose from over 15 examples and deploy with a single click.", + }, + { + title: "Deploy", + href: "https://vercel.com/new", + description: + "Instantly deploy your Turborepo to a shareable URL with Vercel.", + }, +]; + +export default function Page() { + return ( +
    +
    +

    + examples/with-tailwind -  + docs +

    + +
    + +
    +
    +
    +
    + Turborepo +
    +
    + +
    + +
    + +
    +
    + +
    + + Turborepo logo + + + + + + + + + + +
    +
    +
    + +
    + {LINKS.map(({ title, href, description }) => ( + + {description} + + ))} +
    +
    + ); +} diff --git a/examples/with-tailwind/apps/web/eslint.config.js b/examples/with-tailwind/apps/web/eslint.config.js deleted file mode 100644 index e8759ff50fbca..0000000000000 --- a/examples/with-tailwind/apps/web/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { nextJsConfig } from "@repo/eslint-config/next-js"; - -/** @type {import("eslint").Linter.Config} */ -export default nextJsConfig; diff --git a/examples/with-tailwind/apps/web/package.json b/examples/with-tailwind/apps/web/package.json index 00a1f5b873c95..61fa6690cec8b 100644 --- a/examples/with-tailwind/apps/web/package.json +++ b/examples/with-tailwind/apps/web/package.json @@ -12,21 +12,21 @@ }, "dependencies": { "@repo/ui": "workspace:*", - "next": "^15.1.6", - "react": "^19.0.0", - "react-dom": "^19.0.0" + "next": "15.1.7", + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { - "@next/eslint-plugin-next": "^15.1.6", + "@next/eslint-plugin-next": "15.1.7", "@repo/eslint-config": "workspace:*", "@repo/tailwind-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/node": "^22.12.0", - "@types/react": "^19.0.7", - "@types/react-dom": "^19.0.3", - "autoprefixer": "^10.4.20", - "postcss": "^8.5.1", - "tailwindcss": "^3.4.17", + "@types/node": "22.13.1", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", + "autoprefixer": "10.4.20", + "postcss": "8.5.2", + "tailwindcss": "3.4.17", "typescript": "5.7.3" } } diff --git a/examples/with-tailwind/package.json b/examples/with-tailwind/package.json index dbdc2a0efe774..f9e165eef0dff 100644 --- a/examples/with-tailwind/package.json +++ b/examples/with-tailwind/package.json @@ -1,20 +1,12 @@ { - "name": "with-tailwind", - "private": true, - "scripts": { - "build": "turbo build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "check-types": "turbo check-types", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "prettier": "^3.4.2", - "prettier-plugin-tailwindcss": "^0.6.11", - "turbo": "^2.3.4" - }, - "packageManager": "pnpm@8.15.6", - "engines": { - "node": ">=18" - } + "name": "with-tailwind", + "scripts": { + "build": "turbo build", + "check-types": "turbo check-types", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-tailwind/packages/config-eslint/package.json b/examples/with-tailwind/packages/config-eslint/package.json new file mode 100644 index 0000000000000..d2cb6de7e597b --- /dev/null +++ b/examples/with-tailwind/packages/config-eslint/package.json @@ -0,0 +1,8 @@ +{ + "name": "@repo/eslint-config", + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2" + } +} diff --git a/examples/with-tailwind/packages/eslint-config/README.md b/examples/with-tailwind/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-tailwind/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-tailwind/packages/eslint-config/package.json b/examples/with-tailwind/packages/eslint-config/package.json index 5edd31533287d..22f39b7030624 100644 --- a/examples/with-tailwind/packages/eslint-config/package.json +++ b/examples/with-tailwind/packages/eslint-config/package.json @@ -9,16 +9,16 @@ "./react-internal": "./react-internal.js" }, "devDependencies": { - "@eslint/js": "^9.19.0", - "@next/eslint-plugin-next": "^15.1.6", - "eslint": "^9.19.0", - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-only-warn": "^1.1.0", - "eslint-plugin-react": "^7.37.4", - "eslint-plugin-react-hooks": "^5.1.0", - "eslint-plugin-turbo": "^2.3.4", - "globals": "^15.14.0", - "typescript": "^5.7.3", - "typescript-eslint": "^8.22.0" + "@eslint/js": "9.20.0", + "@next/eslint-plugin-next": "15.1.7", + "eslint": "9.20.1", + "eslint-config-prettier": "10.0.1", + "eslint-plugin-only-warn": "1.1.0", + "eslint-plugin-react": "7.37.4", + "eslint-plugin-react-hooks": "5.1.0", + "eslint-plugin-turbo": "2.4.2", + "globals": "15.15.0", + "typescript": "5.7.3", + "typescript-eslint": "8.24.0" } } diff --git a/examples/with-tailwind/packages/tailwind-config/package.json b/examples/with-tailwind/packages/tailwind-config/package.json index e1b280afb7561..0e086e6844a10 100644 --- a/examples/with-tailwind/packages/tailwind-config/package.json +++ b/examples/with-tailwind/packages/tailwind-config/package.json @@ -7,6 +7,6 @@ }, "devDependencies": { "@repo/typescript-config": "workspace:*", - "tailwindcss": "^3.4.17" - } + "tailwindcss": "3.4.17" + } } diff --git a/examples/with-tailwind/packages/typescript-config/package.json b/examples/with-tailwind/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-tailwind/packages/typescript-config/package.json +++ b/examples/with-tailwind/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-tailwind/packages/ui/src/card.tsx b/examples/with-tailwind/packages/ui/Source/card.tsx similarity index 100% rename from examples/with-tailwind/packages/ui/src/card.tsx rename to examples/with-tailwind/packages/ui/Source/card.tsx diff --git a/examples/with-tailwind/packages/ui/src/styles.css b/examples/with-tailwind/packages/ui/Source/styles.css similarity index 100% rename from examples/with-tailwind/packages/ui/src/styles.css rename to examples/with-tailwind/packages/ui/Source/styles.css diff --git a/examples/with-tailwind/packages/ui/package.json b/examples/with-tailwind/packages/ui/package.json index 309e51eccde3c..02f3cdd3a6245 100644 --- a/examples/with-tailwind/packages/ui/package.json +++ b/examples/with-tailwind/packages/ui/package.json @@ -19,16 +19,16 @@ "lint": "eslint src --max-warnings 0" }, "peerDependencies": { - "react": "^19" + "react": "19" }, "devDependencies": { "@repo/eslint-config": "workspace:*", "@repo/tailwind-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@types/react": "^19.0.7", - "autoprefixer": "^10.4.20", - "postcss": "^8.5.1", - "tailwindcss": "^3.4.17", + "@types/react": "19.0.8", + "autoprefixer": "10.4.20", + "postcss": "8.5.2", + "tailwindcss": "3.4.17", "typescript": "5.7.3" } } diff --git a/examples/with-tailwind/pnpm-lock.yaml b/examples/with-tailwind/pnpm-lock.yaml deleted file mode 100644 index 896c70c267d65..0000000000000 --- a/examples/with-tailwind/pnpm-lock.yaml +++ /dev/null @@ -1,3647 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - prettier: - specifier: ^3.4.2 - version: 3.4.2 - prettier-plugin-tailwindcss: - specifier: ^0.6.11 - version: 0.6.11(prettier@3.4.2) - turbo: - specifier: ^2.3.4 - version: 2.3.4 - - apps/docs: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^15.1.6 - version: 15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - devDependencies: - '@next/eslint-plugin-next': - specifier: ^15.1.6 - version: 15.1.6 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/tailwind-config': - specifier: workspace:* - version: link:../../packages/tailwind-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/node': - specifier: ^22.12.0 - version: 22.12.0 - '@types/react': - specifier: ^19.0.7 - version: 19.0.8 - '@types/react-dom': - specifier: ^19.0.3 - version: 19.0.3(@types/react@19.0.8) - autoprefixer: - specifier: ^10.4.20 - version: 10.4.20(postcss@8.5.1) - postcss: - specifier: ^8.5.1 - version: 8.5.1 - tailwindcss: - specifier: ^3.4.17 - version: 3.4.17 - typescript: - specifier: 5.7.3 - version: 5.7.3 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^15.1.6 - version: 15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - devDependencies: - '@next/eslint-plugin-next': - specifier: ^15.1.6 - version: 15.1.6 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/tailwind-config': - specifier: workspace:* - version: link:../../packages/tailwind-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/node': - specifier: ^22.12.0 - version: 22.12.0 - '@types/react': - specifier: ^19.0.7 - version: 19.0.8 - '@types/react-dom': - specifier: ^19.0.3 - version: 19.0.3(@types/react@19.0.8) - autoprefixer: - specifier: ^10.4.20 - version: 10.4.20(postcss@8.5.1) - postcss: - specifier: ^8.5.1 - version: 8.5.1 - tailwindcss: - specifier: ^3.4.17 - version: 3.4.17 - typescript: - specifier: 5.7.3 - version: 5.7.3 - - packages/eslint-config: - devDependencies: - '@eslint/js': - specifier: ^9.19.0 - version: 9.19.0 - '@next/eslint-plugin-next': - specifier: ^15.1.6 - version: 15.1.6 - eslint: - specifier: ^9.19.0 - version: 9.19.0(jiti@2.4.2) - eslint-config-prettier: - specifier: ^10.0.1 - version: 10.0.1(eslint@9.19.0(jiti@2.4.2)) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - eslint-plugin-react: - specifier: ^7.37.4 - version: 7.37.4(eslint@9.19.0(jiti@2.4.2)) - eslint-plugin-react-hooks: - specifier: ^5.1.0 - version: 5.1.0(eslint@9.19.0(jiti@2.4.2)) - eslint-plugin-turbo: - specifier: ^2.3.4 - version: 2.3.4(eslint@9.19.0(jiti@2.4.2))(turbo@2.3.4) - globals: - specifier: ^15.14.0 - version: 15.14.0 - typescript: - specifier: ^5.7.3 - version: 5.7.3 - typescript-eslint: - specifier: ^8.22.0 - version: 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - - packages/tailwind-config: - devDependencies: - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - tailwindcss: - specifier: ^3.4.17 - version: 3.4.17 - - packages/typescript-config: {} - - packages/ui: - dependencies: - react: - specifier: ^19 - version: 19.0.0 - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/tailwind-config': - specifier: workspace:* - version: link:../tailwind-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@types/react': - specifier: ^19.0.7 - version: 19.0.8 - autoprefixer: - specifier: ^10.4.20 - version: 10.4.20(postcss@8.5.1) - postcss: - specifier: ^8.5.1 - version: 8.5.1 - tailwindcss: - specifier: ^3.4.17 - version: 3.4.17 - typescript: - specifier: 5.7.3 - version: 5.7.3 - -packages: - - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - - '@emnapi/runtime@1.3.1': - resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} - - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.19.1': - resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.10.0': - resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.2.0': - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.19.0': - resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.5': - resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.2.5': - resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - - '@humanwhocodes/retry@0.4.1': - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} - engines: {node: '>=18.18'} - - '@img/sharp-darwin-arm64@0.33.5': - resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - - '@img/sharp-darwin-x64@0.33.5': - resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-darwin-arm64@1.0.4': - resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} - cpu: [arm64] - os: [darwin] - - '@img/sharp-libvips-darwin-x64@1.0.4': - resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-linux-arm64@1.0.4': - resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linux-arm@1.0.5': - resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} - cpu: [arm] - os: [linux] - - '@img/sharp-libvips-linux-s390x@1.0.4': - resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} - cpu: [s390x] - os: [linux] - - '@img/sharp-libvips-linux-x64@1.0.4': - resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} - cpu: [x64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-x64@1.0.4': - resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} - cpu: [x64] - os: [linux] - - '@img/sharp-linux-arm64@0.33.5': - resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linux-arm@0.33.5': - resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm] - os: [linux] - - '@img/sharp-linux-s390x@0.33.5': - resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [s390x] - os: [linux] - - '@img/sharp-linux-x64@0.33.5': - resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-linuxmusl-arm64@0.33.5': - resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linuxmusl-x64@0.33.5': - resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-wasm32@0.33.5': - resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [wasm32] - - '@img/sharp-win32-ia32@0.33.5': - resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ia32] - os: [win32] - - '@img/sharp-win32-x64@0.33.5': - resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [win32] - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@next/env@15.1.6': - resolution: {integrity: sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==} - - '@next/eslint-plugin-next@15.1.6': - resolution: {integrity: sha512-+slMxhTgILUntZDGNgsKEYHUvpn72WP1YTlkmEhS51vnVd7S9jEEy0n9YAMcI21vUG4akTw9voWH02lrClt/yw==} - - '@next/swc-darwin-arm64@15.1.6': - resolution: {integrity: sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@15.1.6': - resolution: {integrity: sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@15.1.6': - resolution: {integrity: sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-arm64-musl@15.1.6': - resolution: {integrity: sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-x64-gnu@15.1.6': - resolution: {integrity: sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-linux-x64-musl@15.1.6': - resolution: {integrity: sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-win32-arm64-msvc@15.1.6': - resolution: {integrity: sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-x64-msvc@15.1.6': - resolution: {integrity: sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/node@22.12.0': - resolution: {integrity: sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==} - - '@types/react-dom@19.0.3': - resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} - peerDependencies: - '@types/react': ^19.0.0 - - '@types/react@19.0.8': - resolution: {integrity: sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==} - - '@typescript-eslint/eslint-plugin@8.22.0': - resolution: {integrity: sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/parser@8.22.0': - resolution: {integrity: sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/scope-manager@8.22.0': - resolution: {integrity: sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/type-utils@8.22.0': - resolution: {integrity: sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/types@8.22.0': - resolution: {integrity: sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.22.0': - resolution: {integrity: sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/utils@8.22.0': - resolution: {integrity: sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/visitor-keys@8.22.0': - resolution: {integrity: sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - - array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - - array.prototype.flat@1.3.3: - resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} - engines: {node: '>= 0.4'} - - array.prototype.flatmap@1.3.3: - resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} - engines: {node: '>= 0.4'} - - array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - - arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} - - async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - - autoprefixer@10.4.20: - resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - browserslist@4.24.4: - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - - call-bind-apply-helpers@1.0.1: - resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} - engines: {node: '>= 0.4'} - - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - - call-bound@1.0.3: - resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - - caniuse-lite@1.0.30001695: - resolution: {integrity: sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - - commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} - - data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} - - data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} - - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - - didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - - dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - electron-to-chromium@1.5.86: - resolution: {integrity: sha512-/D7GAAaCRBQFBBcop6SfAAGH37djtpWkOuYhyAajw0l5vsfeSsUQYxaFPwr1c/mC/flARCDdKFo5gpFqNI+18w==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - es-abstract@1.23.9: - resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} - engines: {node: '>= 0.4'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-iterator-helpers@1.2.1: - resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} - engines: {node: '>= 0.4'} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - - es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} - engines: {node: '>= 0.4'} - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-config-prettier@10.0.1: - resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - - eslint-plugin-react-hooks@5.1.0: - resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - - eslint-plugin-react@7.37.4: - resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - - eslint-plugin-turbo@2.3.4: - resolution: {integrity: sha512-9ncoUJkQGkC28NmlQiS17oB9mrE8XaSulRZiB5pv9vmRbYjOfUwyGhY3EIcoBRdww81igxOzXmAmvNNd6GFBPg==} - peerDependencies: - eslint: '>6.6.0' - turbo: '>2.0.0' - - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.19.0: - resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.18.0: - resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - - foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} - engines: {node: '>=14'} - - fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - - get-intrinsic@1.2.7: - resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globals@15.14.0: - resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} - engines: {node: '>=18'} - - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - - is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - - is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} - - is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-boolean-object@1.2.1: - resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} - engines: {node: '>= 0.4'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} - - is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} - engines: {node: '>= 0.4'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - - is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - - is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - - is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakref@1.1.0: - resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - iterator.prototype@1.1.5: - resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} - engines: {node: '>= 0.4'} - - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jiti@1.21.7: - resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} - hasBin: true - - jiti@2.4.2: - resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} - hasBin: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lilconfig@3.1.3: - resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} - engines: {node: '>=14'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - next@15.1.6: - resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - - object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} - engines: {node: '>= 0.4'} - - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - - object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - - object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.1: - resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} - engines: {node: '>= 0.4'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - - pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - - possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - - postcss-import@15.1.0: - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 - - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - - postcss-nested@6.2.0: - resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 - - postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} - engines: {node: '>=4'} - - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - - postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - - postcss@8.5.1: - resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier-plugin-tailwindcss@0.6.11: - resolution: {integrity: sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==} - engines: {node: '>=14.21.3'} - peerDependencies: - '@ianvs/prettier-plugin-sort-imports': '*' - '@prettier/plugin-pug': '*' - '@shopify/prettier-plugin-liquid': '*' - '@trivago/prettier-plugin-sort-imports': '*' - '@zackad/prettier-plugin-twig': '*' - prettier: ^3.0 - prettier-plugin-astro: '*' - prettier-plugin-css-order: '*' - prettier-plugin-import-sort: '*' - prettier-plugin-jsdoc: '*' - prettier-plugin-marko: '*' - prettier-plugin-multiline-arrays: '*' - prettier-plugin-organize-attributes: '*' - prettier-plugin-organize-imports: '*' - prettier-plugin-sort-imports: '*' - prettier-plugin-style-order: '*' - prettier-plugin-svelte: '*' - peerDependenciesMeta: - '@ianvs/prettier-plugin-sort-imports': - optional: true - '@prettier/plugin-pug': - optional: true - '@shopify/prettier-plugin-liquid': - optional: true - '@trivago/prettier-plugin-sort-imports': - optional: true - '@zackad/prettier-plugin-twig': - optional: true - prettier-plugin-astro: - optional: true - prettier-plugin-css-order: - optional: true - prettier-plugin-import-sort: - optional: true - prettier-plugin-jsdoc: - optional: true - prettier-plugin-marko: - optional: true - prettier-plugin-multiline-arrays: - optional: true - prettier-plugin-organize-attributes: - optional: true - prettier-plugin-organize-imports: - optional: true - prettier-plugin-sort-imports: - optional: true - prettier-plugin-style-order: - optional: true - prettier-plugin-svelte: - optional: true - - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} - engines: {node: '>=14'} - hasBin: true - - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-dom@19.0.0: - resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} - peerDependencies: - react: ^19.0.0 - - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - react@19.0.0: - resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} - engines: {node: '>=0.10.0'} - - read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - - resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - - safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - - scheduler@0.25.0: - resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - semver@7.7.0: - resolution: {integrity: sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==} - engines: {node: '>=10'} - hasBin: true - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - - set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} - - sharp@0.33.5: - resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - - string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} - engines: {node: '>= 0.4'} - - string.prototype.repeat@1.0.0: - resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} - engines: {node: '>= 0.4'} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - styled-jsx@5.1.6: - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - - sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - tailwindcss@3.4.17: - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} - engines: {node: '>=14.0.0'} - hasBin: true - - thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - - thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - ts-api-utils@2.0.0: - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - - ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - turbo-darwin-64@2.3.4: - resolution: {integrity: sha512-uOi/cUIGQI7uakZygH+cZQ5D4w+aMLlVCN2KTGot+cmefatps2ZmRRufuHrEM0Rl63opdKD8/JIu+54s25qkfg==} - cpu: [x64] - os: [darwin] - - turbo-darwin-arm64@2.3.4: - resolution: {integrity: sha512-IIM1Lq5R+EGMtM1YFGl4x8Xkr0MWb4HvyU8N4LNoQ1Be5aycrOE+VVfH+cDg/Q4csn+8bxCOxhRp5KmUflrVTQ==} - cpu: [arm64] - os: [darwin] - - turbo-linux-64@2.3.4: - resolution: {integrity: sha512-1aD2EfR7NfjFXNH3mYU5gybLJEFi2IGOoKwoPLchAFRQ6OEJQj201/oNo9CDL75IIrQo64/NpEgVyZtoPlfhfA==} - cpu: [x64] - os: [linux] - - turbo-linux-arm64@2.3.4: - resolution: {integrity: sha512-MxTpdKwxCaA5IlybPxgGLu54fT2svdqTIxRd0TQmpRJIjM0s4kbM+7YiLk0mOh6dGqlWPUsxz/A0Mkn8Xr5o7Q==} - cpu: [arm64] - os: [linux] - - turbo-windows-64@2.3.4: - resolution: {integrity: sha512-yyCrWqcRGu1AOOlrYzRnizEtdkqi+qKP0MW9dbk9OsMDXaOI5jlWtTY/AtWMkLw/czVJ7yS9Ex1vi9DB6YsFvw==} - cpu: [x64] - os: [win32] - - turbo-windows-arm64@2.3.4: - resolution: {integrity: sha512-PggC3qH+njPfn1PDVwKrQvvQby8X09ufbqZ2Ha4uSu+5TvPorHHkAbZVHKYj2Y+tvVzxRzi4Sv6NdHXBS9Be5w==} - cpu: [arm64] - os: [win32] - - turbo@2.3.4: - resolution: {integrity: sha512-1kiLO5C0Okh5ay1DbHsxkPsw9Sjsbjzm6cF85CpWjR0BIyBFNDbKqtUyqGADRS1dbbZoQanJZVj4MS5kk8J42Q==} - hasBin: true - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} - - typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} - - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} - engines: {node: '>= 0.4'} - - typescript-eslint@8.22.0: - resolution: {integrity: sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} - engines: {node: '>=14.17'} - hasBin: true - - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - - update-browserslist-db@1.1.2: - resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - - which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - - which-typed-array@1.1.18: - resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} - engines: {node: '>= 0.4'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - - yaml@2.7.0: - resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} - engines: {node: '>= 14'} - hasBin: true - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@alloc/quick-lru@5.2.0': {} - - '@emnapi/runtime@1.3.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@eslint-community/eslint-utils@4.4.1(eslint@9.19.0(jiti@2.4.2))': - dependencies: - eslint: 9.19.0(jiti@2.4.2) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/config-array@0.19.1': - dependencies: - '@eslint/object-schema': 2.1.5 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/core@0.10.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.2.0': - dependencies: - ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.19.0': {} - - '@eslint/object-schema@2.1.5': {} - - '@eslint/plugin-kit@0.2.5': - dependencies: - '@eslint/core': 0.10.0 - levn: 0.4.1 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.6': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.3.1': {} - - '@humanwhocodes/retry@0.4.1': {} - - '@img/sharp-darwin-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.4 - optional: true - - '@img/sharp-darwin-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.0.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-darwin-x64@1.0.4': - optional: true - - '@img/sharp-libvips-linux-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-linux-arm@1.0.5': - optional: true - - '@img/sharp-libvips-linux-s390x@1.0.4': - optional: true - - '@img/sharp-libvips-linux-x64@1.0.4': - optional: true - - '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - optional: true - - '@img/sharp-libvips-linuxmusl-x64@1.0.4': - optional: true - - '@img/sharp-linux-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.0.4 - optional: true - - '@img/sharp-linux-arm@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.0.5 - optional: true - - '@img/sharp-linux-s390x@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.0.4 - optional: true - - '@img/sharp-linux-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.0.4 - optional: true - - '@img/sharp-linuxmusl-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - optional: true - - '@img/sharp-linuxmusl-x64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - optional: true - - '@img/sharp-wasm32@0.33.5': - dependencies: - '@emnapi/runtime': 1.3.1 - optional: true - - '@img/sharp-win32-ia32@0.33.5': - optional: true - - '@img/sharp-win32-x64@0.33.5': - optional: true - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@jridgewell/gen-mapping@0.3.8': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@next/env@15.1.6': {} - - '@next/eslint-plugin-next@15.1.6': - dependencies: - fast-glob: 3.3.1 - - '@next/swc-darwin-arm64@15.1.6': - optional: true - - '@next/swc-darwin-x64@15.1.6': - optional: true - - '@next/swc-linux-arm64-gnu@15.1.6': - optional: true - - '@next/swc-linux-arm64-musl@15.1.6': - optional: true - - '@next/swc-linux-x64-gnu@15.1.6': - optional: true - - '@next/swc-linux-x64-musl@15.1.6': - optional: true - - '@next/swc-win32-arm64-msvc@15.1.6': - optional: true - - '@next/swc-win32-x64-msvc@15.1.6': - optional: true - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.18.0 - - '@pkgjs/parseargs@0.11.0': - optional: true - - '@swc/counter@0.1.3': {} - - '@swc/helpers@0.5.15': - dependencies: - tslib: 2.8.1 - - '@types/estree@1.0.6': {} - - '@types/json-schema@7.0.15': {} - - '@types/node@22.12.0': - dependencies: - undici-types: 6.20.0 - - '@types/react-dom@19.0.3(@types/react@19.0.8)': - dependencies: - '@types/react': 19.0.8 - - '@types/react@19.0.8': - dependencies: - csstype: 3.1.3 - - '@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/type-utils': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - eslint: 9.19.0(jiti@2.4.2) - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - eslint: 9.19.0(jiti@2.4.2) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - - '@typescript-eslint/type-utils@8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - debug: 4.4.0 - eslint: 9.19.0(jiti@2.4.2) - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.22.0': {} - - '@typescript-eslint/typescript-estree@8.22.0(typescript@5.7.3)': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - eslint: 9.19.0(jiti@2.4.2) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 - eslint-visitor-keys: 4.2.0 - - acorn-jsx@5.3.2(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-regex@5.0.1: {} - - ansi-regex@6.1.0: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.1: {} - - any-promise@1.3.0: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - arg@5.0.2: {} - - argparse@2.0.1: {} - - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.3 - is-array-buffer: 3.0.5 - - array-includes@3.1.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - is-string: 1.1.1 - - array.prototype.findlast@1.2.5: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-shim-unscopables: 1.0.2 - - array.prototype.flat@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - - array.prototype.flatmap@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 - - array.prototype.tosorted@1.1.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - is-array-buffer: 3.0.5 - - async-function@1.0.0: {} - - autoprefixer@10.4.20(postcss@8.5.1): - dependencies: - browserslist: 4.24.4 - caniuse-lite: 1.0.30001695 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.1.1 - postcss: 8.5.1 - postcss-value-parser: 4.2.0 - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.0.0 - - balanced-match@1.0.2: {} - - binary-extensions@2.3.0: {} - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - browserslist@4.24.4: - dependencies: - caniuse-lite: 1.0.30001695 - electron-to-chromium: 1.5.86 - node-releases: 2.0.19 - update-browserslist-db: 1.1.2(browserslist@4.24.4) - - busboy@1.6.0: - dependencies: - streamsearch: 1.1.0 - - call-bind-apply-helpers@1.0.1: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - get-intrinsic: 1.2.7 - set-function-length: 1.2.2 - - call-bound@1.0.3: - dependencies: - call-bind-apply-helpers: 1.0.1 - get-intrinsic: 1.2.7 - - callsites@3.1.0: {} - - camelcase-css@2.0.1: {} - - caniuse-lite@1.0.30001695: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - client-only@0.0.1: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - optional: true - - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - optional: true - - commander@4.1.1: {} - - concat-map@0.0.1: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - cssesc@3.0.0: {} - - csstype@3.1.3: {} - - data-view-buffer@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-length@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-offset@1.0.1: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - debug@4.4.0: - dependencies: - ms: 2.1.3 - - deep-is@0.1.4: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - detect-libc@2.0.3: - optional: true - - didyoumean@1.2.2: {} - - dlv@1.1.3: {} - - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - dotenv@16.0.3: {} - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - eastasianwidth@0.2.0: {} - - electron-to-chromium@1.5.86: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - es-abstract@1.23.9: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-regex: 1.2.1 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.0 - math-intrinsics: 1.1.0 - object-inspect: 1.13.3 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.1 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.18 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-iterator-helpers@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-set-tostringtag: 2.1.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - iterator.prototype: 1.1.5 - safe-array-concat: 1.1.3 - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - es-shim-unscopables@1.0.2: - dependencies: - hasown: 2.0.2 - - es-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - - escalade@3.2.0: {} - - escape-string-regexp@4.0.0: {} - - eslint-config-prettier@10.0.1(eslint@9.19.0(jiti@2.4.2)): - dependencies: - eslint: 9.19.0(jiti@2.4.2) - - eslint-plugin-only-warn@1.1.0: {} - - eslint-plugin-react-hooks@5.1.0(eslint@9.19.0(jiti@2.4.2)): - dependencies: - eslint: 9.19.0(jiti@2.4.2) - - eslint-plugin-react@7.37.4(eslint@9.19.0(jiti@2.4.2)): - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.3 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.2.1 - eslint: 9.19.0(jiti@2.4.2) - estraverse: 5.3.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.values: 1.2.1 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.12 - string.prototype.repeat: 1.0.0 - - eslint-plugin-turbo@2.3.4(eslint@9.19.0(jiti@2.4.2))(turbo@2.3.4): - dependencies: - dotenv: 16.0.3 - eslint: 9.19.0(jiti@2.4.2) - turbo: 2.3.4 - - eslint-scope@8.2.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.0: {} - - eslint@9.19.0(jiti@2.4.2): - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0(jiti@2.4.2)) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.1 - '@eslint/core': 0.10.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.19.0 - '@eslint/plugin-kit': 0.2.5 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.4.2 - transitivePeerDependencies: - - supports-color - - espree@10.3.0: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.1: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.18.0: - dependencies: - reusify: 1.0.4 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - - flatted@3.3.2: {} - - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - - foreground-child@3.3.0: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - fraction.js@4.3.7: {} - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - function.prototype.name@1.1.8: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - - functions-have-names@1.2.3: {} - - get-intrinsic@1.2.7: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-symbol-description@1.1.0: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@10.4.5: - dependencies: - foreground-child: 3.3.0 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - globals@14.0.0: {} - - globals@15.14.0: {} - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - - gopd@1.2.0: {} - - graphemer@1.4.0: {} - - has-bigints@1.1.0: {} - - has-flag@4.0.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-proto@1.2.0: - dependencies: - dunder-proto: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - ignore@5.3.2: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - - is-arrayish@0.3.2: - optional: true - - is-async-function@2.1.1: - dependencies: - async-function: 1.0.0 - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-boolean-object@1.2.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-callable@1.2.7: {} - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-data-view@1.0.2: - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - is-typed-array: 1.1.15 - - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-extglob@2.1.1: {} - - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.3 - - is-fullwidth-code-point@3.0.0: {} - - is-generator-function@1.1.0: - dependencies: - call-bound: 1.0.3 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-map@2.0.3: {} - - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-number@7.0.0: {} - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.3 - - is-string@1.1.1: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.3 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.18 - - is-weakmap@2.0.2: {} - - is-weakref@1.1.0: - dependencies: - call-bound: 1.0.3 - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - - isarray@2.0.5: {} - - isexe@2.0.0: {} - - iterator.prototype@1.1.5: - dependencies: - define-data-property: 1.1.4 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - has-symbols: 1.1.0 - set-function-name: 2.0.2 - - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jiti@1.21.7: {} - - jiti@2.4.2: - optional: true - - js-tokens@4.0.0: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - jsx-ast-utils@3.3.5: - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.3 - object.assign: 4.1.7 - object.values: 1.2.1 - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lilconfig@3.1.3: {} - - lines-and-columns@1.2.4: {} - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.merge@4.6.2: {} - - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - - lru-cache@10.4.3: {} - - math-intrinsics@1.1.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 - - minipass@7.1.2: {} - - ms@2.1.3: {} - - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - - nanoid@3.3.8: {} - - natural-compare@1.4.0: {} - - next@15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0): - dependencies: - '@next/env': 15.1.6 - '@swc/counter': 0.1.3 - '@swc/helpers': 0.5.15 - busboy: 1.6.0 - caniuse-lite: 1.0.30001695 - postcss: 8.4.31 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - styled-jsx: 5.1.6(react@19.0.0) - optionalDependencies: - '@next/swc-darwin-arm64': 15.1.6 - '@next/swc-darwin-x64': 15.1.6 - '@next/swc-linux-arm64-gnu': 15.1.6 - '@next/swc-linux-arm64-musl': 15.1.6 - '@next/swc-linux-x64-gnu': 15.1.6 - '@next/swc-linux-x64-musl': 15.1.6 - '@next/swc-win32-arm64-msvc': 15.1.6 - '@next/swc-win32-x64-msvc': 15.1.6 - sharp: 0.33.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - node-releases@2.0.19: {} - - normalize-path@3.0.0: {} - - normalize-range@0.1.2: {} - - object-assign@4.1.1: {} - - object-hash@3.0.0: {} - - object-inspect@1.13.3: {} - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - - object.entries@1.1.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - object.fromentries@2.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - - object.values@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - own-keys@1.0.1: - dependencies: - get-intrinsic: 1.2.7 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - package-json-from-dist@1.0.1: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - path-exists@4.0.0: {} - - path-key@3.1.1: {} - - path-parse@1.0.7: {} - - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - pify@2.3.0: {} - - pirates@4.0.6: {} - - possible-typed-array-names@1.0.0: {} - - postcss-import@15.1.0(postcss@8.5.1): - dependencies: - postcss: 8.5.1 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.10 - - postcss-js@4.0.1(postcss@8.5.1): - dependencies: - camelcase-css: 2.0.1 - postcss: 8.5.1 - - postcss-load-config@4.0.2(postcss@8.5.1): - dependencies: - lilconfig: 3.1.3 - yaml: 2.7.0 - optionalDependencies: - postcss: 8.5.1 - - postcss-nested@6.2.0(postcss@8.5.1): - dependencies: - postcss: 8.5.1 - postcss-selector-parser: 6.1.2 - - postcss-selector-parser@6.1.2: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-value-parser@4.2.0: {} - - postcss@8.4.31: - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - postcss@8.5.1: - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - prettier-plugin-tailwindcss@0.6.11(prettier@3.4.2): - dependencies: - prettier: 3.4.2 - - prettier@3.4.2: {} - - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - react-dom@19.0.0(react@19.0.0): - dependencies: - react: 19.0.0 - scheduler: 0.25.0 - - react-is@16.13.1: {} - - react@19.0.0: {} - - read-cache@1.0.0: - dependencies: - pify: 2.3.0 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - - resolve-from@4.0.0: {} - - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - resolve@2.0.0-next.5: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - reusify@1.0.4: {} - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-array-concat@1.1.3: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - get-intrinsic: 1.2.7 - has-symbols: 1.1.0 - isarray: 2.0.5 - - safe-push-apply@1.0.0: - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-regex: 1.2.1 - - scheduler@0.25.0: {} - - semver@6.3.1: {} - - semver@7.6.3: - optional: true - - semver@7.7.0: {} - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - set-proto@1.0.0: - dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - - sharp@0.33.5: - dependencies: - color: 4.2.3 - detect-libc: 2.0.3 - semver: 7.6.3 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.5 - '@img/sharp-darwin-x64': 0.33.5 - '@img/sharp-libvips-darwin-arm64': 1.0.4 - '@img/sharp-libvips-darwin-x64': 1.0.4 - '@img/sharp-libvips-linux-arm': 1.0.5 - '@img/sharp-libvips-linux-arm64': 1.0.4 - '@img/sharp-libvips-linux-s390x': 1.0.4 - '@img/sharp-libvips-linux-x64': 1.0.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 - '@img/sharp-libvips-linuxmusl-x64': 1.0.4 - '@img/sharp-linux-arm': 0.33.5 - '@img/sharp-linux-arm64': 0.33.5 - '@img/sharp-linux-s390x': 0.33.5 - '@img/sharp-linux-x64': 0.33.5 - '@img/sharp-linuxmusl-arm64': 0.33.5 - '@img/sharp-linuxmusl-x64': 0.33.5 - '@img/sharp-wasm32': 0.33.5 - '@img/sharp-win32-ia32': 0.33.5 - '@img/sharp-win32-x64': 0.33.5 - optional: true - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.7 - object-inspect: 1.13.3 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - signal-exit@4.1.0: {} - - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 - optional: true - - source-map-js@1.2.1: {} - - streamsearch@1.1.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - - string.prototype.matchall@4.0.12: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 - gopd: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.4 - set-function-name: 2.0.2 - side-channel: 1.1.0 - - string.prototype.repeat@1.0.0: - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.9 - - string.prototype.trim@1.2.10: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - - string.prototype.trimend@1.0.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.3 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - - strip-json-comments@3.1.1: {} - - styled-jsx@5.1.6(react@19.0.0): - dependencies: - client-only: 0.0.1 - react: 19.0.0 - - sucrase@3.35.0: - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - commander: 4.1.1 - glob: 10.4.5 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - tailwindcss@3.4.17: - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.3 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.7 - lilconfig: 3.1.3 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.1 - postcss: 8.5.1 - postcss-import: 15.1.0(postcss@8.5.1) - postcss-js: 4.0.1(postcss@8.5.1) - postcss-load-config: 4.0.2(postcss@8.5.1) - postcss-nested: 6.2.0(postcss@8.5.1) - postcss-selector-parser: 6.1.2 - resolve: 1.22.10 - sucrase: 3.35.0 - transitivePeerDependencies: - - ts-node - - thenify-all@1.6.0: - dependencies: - thenify: 3.3.1 - - thenify@3.3.1: - dependencies: - any-promise: 1.3.0 - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - ts-api-utils@2.0.0(typescript@5.7.3): - dependencies: - typescript: 5.7.3 - - ts-interface-checker@0.1.13: {} - - tslib@2.8.1: {} - - turbo-darwin-64@2.3.4: - optional: true - - turbo-darwin-arm64@2.3.4: - optional: true - - turbo-linux-64@2.3.4: - optional: true - - turbo-linux-arm64@2.3.4: - optional: true - - turbo-windows-64@2.3.4: - optional: true - - turbo-windows-arm64@2.3.4: - optional: true - - turbo@2.3.4: - optionalDependencies: - turbo-darwin-64: 2.3.4 - turbo-darwin-arm64: 2.3.4 - turbo-linux-64: 2.3.4 - turbo-linux-arm64: 2.3.4 - turbo-windows-64: 2.3.4 - turbo-windows-arm64: 2.3.4 - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typed-array-byte-length@1.0.3: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - - typed-array-byte-offset@1.0.4: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - - typed-array-length@1.0.7: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.3 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.0.0 - reflect.getprototypeof: 1.0.10 - - typescript-eslint@8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/parser': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) - eslint: 9.19.0(jiti@2.4.2) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - typescript@5.7.3: {} - - unbox-primitive@1.1.0: - dependencies: - call-bound: 1.0.3 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - - undici-types@6.20.0: {} - - update-browserslist-db@1.1.2(browserslist@4.24.4): - dependencies: - browserslist: 4.24.4 - escalade: 3.2.0 - picocolors: 1.1.1 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - util-deprecate@1.0.2: {} - - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.1 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-builtin-type@1.2.1: - dependencies: - call-bound: 1.0.3 - function.prototype.name: 1.1.8 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.0 - is-regex: 1.2.1 - is-weakref: 1.1.0 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.18 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - - which-typed-array@1.1.18: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.3 - for-each: 0.3.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - word-wrap@1.2.5: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - - yaml@2.7.0: {} - - yocto-queue@0.1.0: {} diff --git a/examples/with-typeorm/README.md b/examples/with-typeorm/README.md deleted file mode 100644 index be0242a6ab93c..0000000000000 --- a/examples/with-typeorm/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# Turborepo with TypeORM - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [Next.js](https://nextjs.org/) app -- `web`: another [Next.js](https://nextjs.org/) app -- `ui`: a stub React component library shared by both `web` and `docs` applications -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo -- `@repo/typeorm-service`: contains the service layer with TypeORM integration to manage database entities and transactions. It utilizes **dependency injection** to provide services across different applications. - -## Dependency Injection - -The @repo/typeorm-service package demonstrates a sophisticated setup where services are defined using TypeORM repositories and injected into Next.js apps using a custom dependency injection mechanism. This approach emphasizes a clear separation of concerns and a modular architecture. - -```typescript -// root/packages/typeorm-service/domain/todo/todo.repository.ts -@Repository -export class TodoRepository {...} - -// root/packages/typeorm-service/domain/todo/todo.service.ts -@InjectAble -export class TodoService { - constructor(private todoRepo: TodoRepository) {} - ... -} -``` - -## Example Usage of the Service Layer - -This example demonstrates how to use the typeorm-service package to inject and use services within a Next.js app. The TodoService is injected into both page.tsx and API routes. - -```typescript -// root/apps/docs/app/page.tsx -import { inject, TodoService } from "@repo/typeorm-service"; - -export default async function Page(): Promise { - const todoService = inject(TodoService); - - const todoList = await todoService.findAll(); - - return ... -} -``` - -In the API route file, TodoService is injected to handle GET and POST requests. The GET request returns the list of todos, while the POST request adds a new todo. - -```typescript -// root/apps/web/app/api/todo/route.ts - -import { inject, type Todo, TodoService } from "@repo/typeorm-service"; - -const todoService = inject(TodoService); - -export async function GET() { - const list = await todoService.findAll(); - - return Response.json(list); -} - -export async function POST(req: Request) { - const res: Pick = await req.json(); - - const entity = await todoService.add(res.content); - - return Response.json(entity); -} -``` - -## Configuring the Database - -For managing the database settings such as the database type, username, password, and other configurations, refer to the orm-config.ts file located in the packages/typeorm-service/src directory. This file centralizes all database connection settings to ensure secure and efficient database management. Make sure to review and adjust these settings according to your environment to ensure optimal performance and security. - -```typescript -// packages/typeorm-service/src/orm-config.ts -import { DataSource } from "typeorm"; - -export const AppDataSource = new DataSource({ - type: "mysql", // or your database type - host: "localhost", - port: 3306, - username: "your_username", - password: "your_password", - database: "your_database_name", - synchronize: true, - logging: false, - entities: [...], - migrations: [...], -}); - -``` - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeORM](https://typeorm.io/) for service layer -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/with-typeorm/apps/docs/.eslintrc.js b/examples/with-typeorm/apps/docs/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-typeorm/apps/docs/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-typeorm/apps/docs/README.md b/examples/with-typeorm/apps/docs/README.md deleted file mode 100644 index d364535741404..0000000000000 --- a/examples/with-typeorm/apps/docs/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3001](http://localhost:3001) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-typeorm/apps/docs/package.json b/examples/with-typeorm/apps/docs/package.json index 66444e07a5bc2..3cebf29de93b6 100644 --- a/examples/with-typeorm/apps/docs/package.json +++ b/examples/with-typeorm/apps/docs/package.json @@ -1,30 +1,19 @@ { - "name": "docs", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev --port 3001", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0" - }, - "dependencies": { - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "@repo/ui": "workspace:*", - "typeorm": "^0.3.20", - "@repo/typeorm-service": "workspace:*" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "docs", + "scripts": { + "build": "next build", + "dev": "next dev --port 3001", + "start": "next start" + }, + "dependencies": { + "@repo/typeorm-service": "workspace:*", + "@repo/ui": "workspace:*", + "next": "15.1.7", + "typeorm": "0.3.20" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-typeorm/apps/web/.eslintrc.js b/examples/with-typeorm/apps/web/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-typeorm/apps/web/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-typeorm/apps/web/README.md b/examples/with-typeorm/apps/web/README.md deleted file mode 100644 index 3d7b63af7dc79..0000000000000 --- a/examples/with-typeorm/apps/web/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-typeorm/apps/web/package.json b/examples/with-typeorm/apps/web/package.json index 69711b97e1048..49ab7e297e397 100644 --- a/examples/with-typeorm/apps/web/package.json +++ b/examples/with-typeorm/apps/web/package.json @@ -1,30 +1,19 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0" - }, - "dependencies": { - "@repo/ui": "workspace:*", - "@repo/typeorm-service": "workspace:*", - "typeorm": "^0.3.20", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "@repo/typeorm-service": "workspace:*", + "@repo/ui": "workspace:*", + "next": "15.1.7", + "typeorm": "0.3.20" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-typeorm/package.json b/examples/with-typeorm/package.json index 2cb8c537487f4..2e9c7c6ba42df 100644 --- a/examples/with-typeorm/package.json +++ b/examples/with-typeorm/package.json @@ -1,21 +1,14 @@ { - "private": true, - "scripts": { - "build": "turbo build", - "dev": "turbo dev", - "lint": "turbo lint", - "type-check": "turbo type-check", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "pnpm@8.15.5", - "engines": { - "node": ">=18" - }, - "name": "with-typeorm" + "name": "with-typeorm", + "scripts": { + "build": "turbo build", + "dev": "turbo dev", + "type-check": "turbo type-check" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "turbo": "2.4.2" + } } diff --git a/examples/with-typeorm/packages/eslint-config/README.md b/examples/with-typeorm/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-typeorm/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-typeorm/packages/eslint-config/package.json b/examples/with-typeorm/packages/eslint-config/package.json index 821a73829bff4..dca64b8823b7a 100644 --- a/examples/with-typeorm/packages/eslint-config/package.json +++ b/examples/with-typeorm/packages/eslint-config/package.json @@ -1,19 +1,14 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js", - "react-internal.js" - ], - "devDependencies": { - "@vercel/style-guide": "^5.2.0", - "eslint-config-turbo": "^2.0.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-only-warn": "^1.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "next.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-typeorm/packages/typeorm-service/.eslintrc.js b/examples/with-typeorm/packages/typeorm-service/.eslintrc.js deleted file mode 100755 index 3ea20ebbf42ad..0000000000000 --- a/examples/with-typeorm/packages/typeorm-service/.eslintrc.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - extends: ["@repo/eslint-config/library.js"], - parser: "@typescript-eslint/parser", - env: { - es6: true, - node: true, - }, - parserOptions: { - project: true, - ecmaVersion: 2020, - - }, - rules: { - "@typescript-eslint/no-explicit-any": "off", - 'no-undef': 'off', - "no-unused-vars":'off', - }, - overrides: [ - { - files: ["*.entity.ts", "*.repository.ts", "*.service.ts"], - }, - ], -}; diff --git a/examples/with-typeorm/packages/typeorm-service/src/domain/todo/todo.entity.ts b/examples/with-typeorm/packages/typeorm-service/Source/domain/todo/todo.entity.ts old mode 100755 new mode 100644 similarity index 100% rename from examples/with-typeorm/packages/typeorm-service/src/domain/todo/todo.entity.ts rename to examples/with-typeorm/packages/typeorm-service/Source/domain/todo/todo.entity.ts diff --git a/examples/with-typeorm/packages/typeorm-service/src/domain/todo/todo.repository.ts b/examples/with-typeorm/packages/typeorm-service/Source/domain/todo/todo.repository.ts old mode 100755 new mode 100644 similarity index 100% rename from examples/with-typeorm/packages/typeorm-service/src/domain/todo/todo.repository.ts rename to examples/with-typeorm/packages/typeorm-service/Source/domain/todo/todo.repository.ts diff --git a/examples/with-typeorm/packages/typeorm-service/src/domain/todo/todo.service.ts b/examples/with-typeorm/packages/typeorm-service/Source/domain/todo/todo.service.ts old mode 100755 new mode 100644 similarity index 100% rename from examples/with-typeorm/packages/typeorm-service/src/domain/todo/todo.service.ts rename to examples/with-typeorm/packages/typeorm-service/Source/domain/todo/todo.service.ts diff --git a/examples/with-typeorm/packages/typeorm-service/src/helper/di-container.ts b/examples/with-typeorm/packages/typeorm-service/Source/helper/di-container.ts old mode 100755 new mode 100644 similarity index 100% rename from examples/with-typeorm/packages/typeorm-service/src/helper/di-container.ts rename to examples/with-typeorm/packages/typeorm-service/Source/helper/di-container.ts diff --git a/examples/with-typeorm/packages/typeorm-service/src/helper/reflect-factory.ts b/examples/with-typeorm/packages/typeorm-service/Source/helper/reflect-factory.ts old mode 100755 new mode 100644 similarity index 100% rename from examples/with-typeorm/packages/typeorm-service/src/helper/reflect-factory.ts rename to examples/with-typeorm/packages/typeorm-service/Source/helper/reflect-factory.ts diff --git a/examples/with-typeorm/packages/typeorm-service/src/index.ts b/examples/with-typeorm/packages/typeorm-service/Source/index.ts old mode 100755 new mode 100644 similarity index 100% rename from examples/with-typeorm/packages/typeorm-service/src/index.ts rename to examples/with-typeorm/packages/typeorm-service/Source/index.ts diff --git a/examples/with-typeorm/packages/typeorm-service/src/orm-config.ts b/examples/with-typeorm/packages/typeorm-service/Source/orm-config.ts old mode 100755 new mode 100644 similarity index 100% rename from examples/with-typeorm/packages/typeorm-service/src/orm-config.ts rename to examples/with-typeorm/packages/typeorm-service/Source/orm-config.ts diff --git a/examples/with-typeorm/packages/typeorm-service/__test__/todo-service.test.ts b/examples/with-typeorm/packages/typeorm-service/__test__/todo-service.test.ts deleted file mode 100644 index a6731f1d8d4e4..0000000000000 --- a/examples/with-typeorm/packages/typeorm-service/__test__/todo-service.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { suite, expect, it, beforeEach, vi } from "vitest"; -import { TodoService } from "../src/domain/todo/todo.service"; -import { TodoRepository } from "../src/domain/todo/todo.repository"; -import { Todo } from "../src/domain/todo/todo.entity"; - -suite("TodoService Unit Tests", () => { - let todoService: TodoService; - let mockTodoRepo: Partial; - let mockTodo: Todo; - - beforeEach(() => { - const now = new Date().toString(); - mockTodo = { - id: 1, - content: "Hello World", - complete: false, - createdAt: now, - updatedAt: now, - } as Todo; - mockTodoRepo = { - findById: vi.fn().mockResolvedValue(mockTodo), - findAll: vi.fn().mockResolvedValue([mockTodo]), - delete: vi.fn().mockResolvedValue({ affected: 1 }), - insert: vi.fn().mockResolvedValue(mockTodo), - update: vi.fn().mockResolvedValue({ ...mockTodo, complete: true }), - }; - todoService = new TodoService(mockTodoRepo as TodoRepository); - }); - - it("Insert", async () => { - const newTodo = await todoService.add("Hello World"); - - expect(newTodo.content).toBe("Hello World"); - expect(newTodo.complete).toBeFalsy(); - expect(mockTodoRepo.insert).toHaveBeenCalledWith("Hello World"); - }); - - it("Select", async () => { - const todo = await todoService.findById(1); - - expect(todo?.content).toBe("Hello World"); - expect(mockTodoRepo.findById).toHaveBeenCalledWith(1); - }); - - it("Update", async () => { - await todoService.complete(1); - - expect(mockTodoRepo.update).toHaveBeenCalledWith(1); - }); - - it("Delete", async () => { - await todoService.deleteById(1); - - expect(mockTodoRepo.delete).toHaveBeenCalledWith(1); - }); - - it("Find All", async () => { - const todoList = await todoService.findAll(); - - expect(todoList).toEqual([mockTodo]); - expect(mockTodoRepo.findAll).toHaveBeenCalled(); - }); -}); diff --git a/examples/with-typeorm/packages/typeorm-service/__test__/typeorm.test.ts b/examples/with-typeorm/packages/typeorm-service/__test__/typeorm.test.ts deleted file mode 100755 index 3b63db193f9d3..0000000000000 --- a/examples/with-typeorm/packages/typeorm-service/__test__/typeorm.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { suite, it, beforeEach, expect } from "vitest"; -import "reflect-metadata"; -import { - DataSource, - Repository, - Column, - Entity, - PrimaryGeneratedColumn, -} from "typeorm"; - -@Entity({ - name: "todo", -}) -class Todo { - @PrimaryGeneratedColumn() - id: number; - - @Column({ - nullable: false, - comment: "ë‚´ìš©", - length: 100, - }) - content: string; - - @Column() - complete: boolean; -} - -suite("typeorm with SQL.js", () => { - let dataSource: DataSource; - let todoRepo: Repository; - - beforeEach(async () => { - dataSource = new DataSource({ - type: "sqljs", - entities: [Todo], - synchronize: true, - autoSave: false, - dropSchema: true, - }); - - await dataSource.initialize(); - - todoRepo = dataSource.getRepository(Todo); - }); - - it("Insert", async () => { - const newTodo = await todoRepo.save({ - content: "Hello World", - complete: false, - }); - expect(newTodo.content).toBe("Hello World"); - expect(newTodo.complete).toBeFalsy(); - }); - - it("Select", async () => { - const newTodo = await todoRepo.save({ - content: "Hello World", - complete: false, - }); - const todo = await todoRepo.findOneBy({ id: newTodo.id }); - - expect(todo?.content).toBe("Hello World"); - }); - - it("Update", async () => { - const newTodo = await todoRepo.save({ - content: "Hello World", - complete: false, - }); - await todoRepo.update(newTodo.id, { complete: true }); - const todo = await todoRepo.findOneBy({ id: newTodo.id }); - expect(todo?.complete).toBeTruthy(); - }); - - it("Delete", async () => { - const newTodo = await todoRepo.save({ - content: "Hello World", - complete: false, - }); - await todoRepo.delete(newTodo.id); - - const exist = await todoRepo.existsBy({ id: newTodo.id }); - expect(exist).toBe(false); - }); -}); diff --git a/examples/with-typeorm/packages/typeorm-service/package.json b/examples/with-typeorm/packages/typeorm-service/package.json index 7e8551b4c54c2..f84eb98c094fc 100644 --- a/examples/with-typeorm/packages/typeorm-service/package.json +++ b/examples/with-typeorm/packages/typeorm-service/package.json @@ -1,31 +1,21 @@ { - "name": "@repo/typeorm-service", - "version": "0.0.0", - "private": true, - "exports": { - ".": "./src/index.ts" - }, - "scripts": { - "lint": "eslint src/ --max-warnings 0", - "test:watch": "vitest", - "test": "vitest run", - "type-check": "tsc --noEmit" - }, - "peerDependencies": { - "typeorm": "^0.3.20" - }, - "dependencies": { - "reflect-metadata": "^0.2.2", - "sql.js": "^1.10.3", - "typeorm": "^0.3.20" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/node": "^20.11.24", - "eslint": "^8.57.0", - "typescript": "5.5.4", - "unplugin-swc": "^1.4.5", - "vitest": "^1.5.0" - } + "name": "@repo/typeorm-service", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "test:watch": "vitest", + "type-check": "tsc --noEmit" + }, + "dependencies": { + "reflect-metadata": "0.2.2", + "sql.js": "1.12.0", + "typeorm": "0.3.20" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "22.13.1", + "unplugin-swc": "1.5.1" + } } diff --git a/examples/with-typeorm/packages/typescript-config/package.json b/examples/with-typeorm/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-typeorm/packages/typescript-config/package.json +++ b/examples/with-typeorm/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-typeorm/packages/ui/.eslintrc.js b/examples/with-typeorm/packages/ui/.eslintrc.js deleted file mode 100644 index 46464139c9406..0000000000000 --- a/examples/with-typeorm/packages/ui/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: "./tsconfig.lint.json", - tsconfigRootDir: __dirname, - }, -}; diff --git a/examples/with-typeorm/packages/ui/src/button.tsx b/examples/with-typeorm/packages/ui/Source/button.tsx similarity index 100% rename from examples/with-typeorm/packages/ui/src/button.tsx rename to examples/with-typeorm/packages/ui/Source/button.tsx diff --git a/examples/with-typeorm/packages/ui/src/card.tsx b/examples/with-typeorm/packages/ui/Source/card.tsx similarity index 100% rename from examples/with-typeorm/packages/ui/src/card.tsx rename to examples/with-typeorm/packages/ui/Source/card.tsx diff --git a/examples/with-typeorm/packages/ui/src/code.tsx b/examples/with-typeorm/packages/ui/Source/code.tsx similarity index 100% rename from examples/with-typeorm/packages/ui/src/code.tsx rename to examples/with-typeorm/packages/ui/Source/code.tsx diff --git a/examples/with-typeorm/packages/ui/package.json b/examples/with-typeorm/packages/ui/package.json index 44ae805dd5cb9..27cb3025280e5 100644 --- a/examples/with-typeorm/packages/ui/package.json +++ b/examples/with-typeorm/packages/ui/package.json @@ -1,28 +1,18 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "private": true, - "exports": { - "./button": "./src/button.tsx", - "./card": "./src/card.tsx", - "./code": "./src/code.tsx" - }, - "scripts": { - "lint": "eslint . --max-warnings 0", - "generate:component": "turbo gen react-component" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@turbo/gen": "^1.12.4", - "@types/node": "^20.11.24", - "@types/eslint": "^8.56.5", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - } + "name": "@repo/ui", + "exports": { + "./button": "./src/button.tsx", + "./card": "./src/card.tsx", + "./code": "./src/code.tsx" + }, + "scripts": { + "generate:component": "turbo gen react-component" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@turbo/gen": "2.4.2", + "@types/node": "22.13.1" + } } diff --git a/examples/with-typeorm/pnpm-lock.yaml b/examples/with-typeorm/pnpm-lock.yaml deleted file mode 100644 index 784d224b075b2..0000000000000 --- a/examples/with-typeorm/pnpm-lock.yaml +++ /dev/null @@ -1,6316 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:packages/typescript-config - prettier: - specifier: ^3.2.5 - version: 3.3.3 - turbo: - specifier: ^2.0.3 - version: 2.0.9 - - apps/docs: - dependencies: - '@repo/typeorm-service': - specifier: workspace:* - version: link:../../packages/typeorm-service - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^14.1.1 - version: 14.2.5(react-dom@18.3.1)(react@18.3.1) - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - typeorm: - specifier: ^0.3.20 - version: 0.3.20(sql.js@1.10.3) - devDependencies: - '@next/eslint-plugin-next': - specifier: ^14.1.1 - version: 14.2.5 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/eslint': - specifier: ^8.56.5 - version: 8.56.11 - '@types/node': - specifier: ^20.11.24 - version: 20.14.11 - '@types/react': - specifier: ^18.2.61 - version: 18.3.3 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.3.0 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - apps/web: - dependencies: - '@repo/typeorm-service': - specifier: workspace:* - version: link:../../packages/typeorm-service - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - next: - specifier: ^14.1.1 - version: 14.2.5(react-dom@18.3.1)(react@18.3.1) - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - typeorm: - specifier: ^0.3.20 - version: 0.3.20(sql.js@1.10.3) - devDependencies: - '@next/eslint-plugin-next': - specifier: ^14.1.1 - version: 14.2.5 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/eslint': - specifier: ^8.56.5 - version: 8.56.11 - '@types/node': - specifier: ^20.11.24 - version: 20.14.11 - '@types/react': - specifier: ^18.2.61 - version: 18.3.3 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.3.0 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/eslint-config: - devDependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.17.0(@typescript-eslint/parser@7.17.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.17.0(eslint@8.57.0)(typescript@5.5.4) - '@vercel/style-guide': - specifier: ^5.2.0 - version: 5.2.0(eslint@8.57.0)(prettier@3.3.3)(typescript@5.5.4) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - eslint-config-turbo: - specifier: ^2.0.0 - version: 2.0.9(eslint@8.57.0) - eslint-plugin-only-warn: - specifier: ^1.1.0 - version: 1.1.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/typeorm-service: - dependencies: - reflect-metadata: - specifier: ^0.2.2 - version: 0.2.2 - sql.js: - specifier: ^1.10.3 - version: 1.10.3 - typeorm: - specifier: ^0.3.20 - version: 0.3.20(sql.js@1.10.3) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@types/node': - specifier: ^20.11.24 - version: 20.14.11 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - unplugin-swc: - specifier: ^1.4.5 - version: 1.5.1(@swc/core@1.7.0) - vitest: - specifier: ^1.5.0 - version: 1.6.0(@types/node@20.14.11) - - packages/typescript-config: {} - - packages/ui: - dependencies: - react: - specifier: ^18.2.0 - version: 18.3.1 - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@turbo/gen': - specifier: ^1.12.4 - version: 1.13.4(@types/node@20.14.11)(typescript@5.5.4) - '@types/eslint': - specifier: ^8.56.5 - version: 8.56.11 - '@types/node': - specifier: ^20.11.24 - version: 20.14.11 - '@types/react': - specifier: ^18.2.61 - version: 18.3.3 - '@types/react-dom': - specifier: ^18.2.19 - version: 18.3.0 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@babel/code-frame@7.24.7: - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.0.1 - dev: true - - /@babel/compat-data@7.24.9: - resolution: {integrity: sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.24.9: - resolution: {integrity: sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.10 - '@babel/helper-compilation-targets': 7.24.8 - '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) - '@babel/helpers': 7.24.8 - '@babel/parser': 7.24.8 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 - convert-source-map: 2.0.0 - debug: 4.3.5 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/eslint-parser@7.24.8(@babel/core@7.24.9)(eslint@8.57.0): - resolution: {integrity: sha512-nYAikI4XTGokU2QX7Jx+v4rxZKhKivaQaREZjuW3mrJrbdWJ5yUfohnoUULge+zEEaKjPYNxhoRgUKktjXtbwA==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - dependencies: - '@babel/core': 7.24.9 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.24.10: - resolution: {integrity: sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.9 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.24.8: - resolution: {integrity: sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.9 - '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.2 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.24.7: - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.9 - dev: true - - /@babel/helper-function-name@7.24.7: - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.9 - dev: true - - /@babel/helper-hoist-variables@7.24.7: - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.9 - dev: true - - /@babel/helper-module-imports@7.24.7: - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-module-transforms@7.24.9(@babel/core@7.24.9): - resolution: {integrity: sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-simple-access@7.24.7: - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-split-export-declaration@7.24.7: - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.9 - dev: true - - /@babel/helper-string-parser@7.24.8: - resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.24.7: - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.24.8: - resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.24.8: - resolution: {integrity: sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.9 - dev: true - - /@babel/highlight@7.24.7: - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.1 - dev: true - - /@babel/parser@7.24.8: - resolution: {integrity: sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.9 - dev: true - - /@babel/runtime-corejs3@7.24.8: - resolution: {integrity: sha512-DXG/BhegtMHhnN7YPIvxWd303/9aXvYFD1TjNL3CD6tUrhI2LVsg3Lck0aql5TRH29n4sj3emcROypkZVUfSuA==} - engines: {node: '>=6.9.0'} - dependencies: - core-js-pure: 3.37.1 - regenerator-runtime: 0.14.1 - dev: true - - /@babel/template@7.24.7: - resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.24.8 - '@babel/types': 7.24.9 - dev: true - - /@babel/traverse@7.24.8: - resolution: {integrity: sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.10 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.24.8 - '@babel/types': 7.24.9 - debug: 4.3.5 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.24.9: - resolution: {integrity: sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 - dev: true - - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@esbuild/aix-ppc64@0.21.5: - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.21.5: - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.21.5: - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.21.5: - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.21.5: - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.21.5: - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.21.5: - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.21.5: - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.21.5: - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.21.5: - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.21.5: - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.21.5: - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.21.5: - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.21.5: - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.21.5: - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.21.5: - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.21.5: - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.21.5: - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.21.5: - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.21.5: - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.21.5: - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.21.5: - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.21.5: - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.11.0: - resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.5 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - - /@jest/schemas@29.6.3: - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.5.0: - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - dev: true - - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - dev: true - - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true - - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true - - /@next/env@14.2.5: - resolution: {integrity: sha512-/zZGkrTOsraVfYjGP8uM0p6r0BDT6xWpkjdVbcz66PJVSpwXX3yNiRycxAuDfBKGWBrZBXRuK/YVlkNgxHGwmA==} - dev: false - - /@next/eslint-plugin-next@14.2.5: - resolution: {integrity: sha512-LY3btOpPh+OTIpviNojDpUdIbHW9j0JBYBjsIp8IxtDFfYFyORvw3yNq6N231FVqQA7n7lwaf7xHbVJlA1ED7g==} - dependencies: - glob: 10.3.10 - dev: true - - /@next/swc-darwin-arm64@14.2.5: - resolution: {integrity: sha512-/9zVxJ+K9lrzSGli1///ujyRfon/ZneeZ+v4ptpiPoOU+GKZnm8Wj8ELWU1Pm7GHltYRBklmXMTUqM/DqQ99FQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64@14.2.5: - resolution: {integrity: sha512-vXHOPCwfDe9qLDuq7U1OYM2wUY+KQ4Ex6ozwsKxp26BlJ6XXbHleOUldenM67JRyBfVjv371oneEvYd3H2gNSA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu@14.2.5: - resolution: {integrity: sha512-vlhB8wI+lj8q1ExFW8lbWutA4M2ZazQNvMWuEDqZcuJJc78iUnLdPPunBPX8rC4IgT6lIx/adB+Cwrl99MzNaA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl@14.2.5: - resolution: {integrity: sha512-NpDB9NUR2t0hXzJJwQSGu1IAOYybsfeB+LxpGsXrRIb7QOrYmidJz3shzY8cM6+rO4Aojuef0N/PEaX18pi9OA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu@14.2.5: - resolution: {integrity: sha512-8XFikMSxWleYNryWIjiCX+gU201YS+erTUidKdyOVYi5qUQo/gRxv/3N1oZFCgqpesN6FPeqGM72Zve+nReVXQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl@14.2.5: - resolution: {integrity: sha512-6QLwi7RaYiQDcRDSU/os40r5o06b5ue7Jsk5JgdRBGGp8l37RZEh9JsLSM8QF0YDsgcosSeHjglgqi25+m04IQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc@14.2.5: - resolution: {integrity: sha512-1GpG2VhbspO+aYoMOQPQiqc/tG3LzmsdBH0LhnDS3JrtDx2QmzXe0B6mSZZiN3Bq7IOMXxv1nlsjzoS1+9mzZw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-ia32-msvc@14.2.5: - resolution: {integrity: sha512-Igh9ZlxwvCDsu6438FXlQTHlRno4gFpJzqPjSIBZooD22tKeI4fE/YMRoHVJHmrQ2P5YL1DoZ0qaOKkbeFWeMg==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc@14.2.5: - resolution: {integrity: sha512-tEQ7oinq1/CjSG9uSTerca3v4AZ+dFa+4Yu6ihaG8Ud8ddqLQgFGcnwYls13H5X5CPDPZJdYxyeMui6muOLd4g==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - optional: true - - /@pkgr/core@0.1.1: - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true - - /@rollup/pluginutils@5.1.0: - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - - /@rollup/rollup-android-arm-eabi@4.19.0: - resolution: {integrity: sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.19.0: - resolution: {integrity: sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.19.0: - resolution: {integrity: sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.19.0: - resolution: {integrity: sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.19.0: - resolution: {integrity: sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-musleabihf@4.19.0: - resolution: {integrity: sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.19.0: - resolution: {integrity: sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.19.0: - resolution: {integrity: sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-powerpc64le-gnu@4.19.0: - resolution: {integrity: sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.19.0: - resolution: {integrity: sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-s390x-gnu@4.19.0: - resolution: {integrity: sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.19.0: - resolution: {integrity: sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.19.0: - resolution: {integrity: sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.19.0: - resolution: {integrity: sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.19.0: - resolution: {integrity: sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.19.0: - resolution: {integrity: sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rushstack/eslint-patch@1.10.3: - resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} - dev: true - - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true - - /@sqltools/formatter@1.2.5: - resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} - dev: false - - /@swc/core-darwin-arm64@1.7.0: - resolution: {integrity: sha512-2ylhM7f0HwUwLrFYZAe/dse8PCbPsYcJS3Dt7Q8NT3PUn7vy6QOMxNcOPPuDrnmaXqQQO3oxdmRapguTxaat9g==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@swc/core-darwin-x64@1.7.0: - resolution: {integrity: sha512-SgVnN4gT1Rb9YfTkp4FCUITqSs7Yj0uB2SUciu5CV3HuGvS5YXCUzh+KrwpLFtx8NIgivISKcNnb41mJi98X8Q==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@swc/core-linux-arm-gnueabihf@1.7.0: - resolution: {integrity: sha512-+Z9Dayart1iKJQEJJ9N/KS4z5EdXJE3WPFikY0jonKTo4Dd8RuyVz5yLvqcIMeVdz/SwximATaL6iJXw7hZS9A==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@swc/core-linux-arm64-gnu@1.7.0: - resolution: {integrity: sha512-UnLrCiZ1EI4shznJn0xP6DLgsXUSwtfsdgHhGYCrvbgVBBve3S9iFgVFEB3SPl7Q/TdowNbrN4zHU0oChfiNfw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@swc/core-linux-arm64-musl@1.7.0: - resolution: {integrity: sha512-H724UANA+ptsfwKRr9mnaDa9cb5fw0oFysiGKTgb3DMYcgk3Od0jMTnXVPFSVpo7FlmyxeC9K8ueUPBOoOK6XA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@swc/core-linux-x64-gnu@1.7.0: - resolution: {integrity: sha512-SY3HA0K0Dpqt1HIfMLGpwL4hd4UaL2xHP5oZXPlRQPhUDZrbb4PbI3ZJnh66c63eL4ZR8EJ+HRFI0Alx5p69Zw==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@swc/core-linux-x64-musl@1.7.0: - resolution: {integrity: sha512-cEJ2ebtV1v/5Ilb55E05J6F5SrHKQWzUttIhR5Mkayyo+yvPslcpByuFC3D+J7X1ebziTOBpWuMpUdjLfh3SMQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@swc/core-win32-arm64-msvc@1.7.0: - resolution: {integrity: sha512-ecQOOmzEssz+m0pR4xDYCGuvn3E/l0nQ3tk5jp1NA1lsAy4bMV0YbYCHjptYvWL/UjhIerIp3IlCJ8x5DodSog==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@swc/core-win32-ia32-msvc@1.7.0: - resolution: {integrity: sha512-gz81seZkRn3zMnVOc7L5k6F4vQC82gIxmHiL+GedK+A37XI/X26AASU3zxvORnqQbwQYXQ+AEVckxBmFlz3v2g==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@swc/core-win32-x64-msvc@1.7.0: - resolution: {integrity: sha512-b5Fd1xEOw9uqBpj2lqsaR4Iq9UhiL84hNDcEsi6DQA7Y1l85waQAslTbS0E4/pJ1PISAs0jW0zIGLco1eaWBOg==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@swc/core@1.7.0: - resolution: {integrity: sha512-d4vMzH6ICllDwlPuhset2h8gu/USHdbyfJim+2hQEdxC0UONtfpmu38XBgNqRjStrji1Q5M10jfeUZL3cu1i8g==} - engines: {node: '>=10'} - requiresBuild: true - peerDependencies: - '@swc/helpers': '*' - peerDependenciesMeta: - '@swc/helpers': - optional: true - dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.12 - optionalDependencies: - '@swc/core-darwin-arm64': 1.7.0 - '@swc/core-darwin-x64': 1.7.0 - '@swc/core-linux-arm-gnueabihf': 1.7.0 - '@swc/core-linux-arm64-gnu': 1.7.0 - '@swc/core-linux-arm64-musl': 1.7.0 - '@swc/core-linux-x64-gnu': 1.7.0 - '@swc/core-linux-x64-musl': 1.7.0 - '@swc/core-win32-arm64-msvc': 1.7.0 - '@swc/core-win32-ia32-msvc': 1.7.0 - '@swc/core-win32-x64-msvc': 1.7.0 - dev: true - - /@swc/counter@0.1.3: - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - /@swc/helpers@0.5.5: - resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} - dependencies: - '@swc/counter': 0.1.3 - tslib: 2.6.3 - dev: false - - /@swc/types@0.1.12: - resolution: {integrity: sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==} - dependencies: - '@swc/counter': 0.1.3 - dev: true - - /@tootallnate/quickjs-emscripten@0.23.0: - resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - dev: true - - /@tsconfig/node10@1.0.11: - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - dev: true - - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true - - /@turbo/gen@1.13.4(@types/node@20.14.11)(typescript@5.5.4): - resolution: {integrity: sha512-PK38N1fHhDUyjLi0mUjv0RbX0xXGwDLQeRSGsIlLcVpP1B5fwodSIwIYXc9vJok26Yne94BX5AGjueYsUT3uUw==} - hasBin: true - dependencies: - '@turbo/workspaces': 1.13.4 - chalk: 2.4.2 - commander: 10.0.1 - fs-extra: 10.1.0 - inquirer: 8.2.6 - minimatch: 9.0.5 - node-plop: 0.26.3 - proxy-agent: 6.4.0 - ts-node: 10.9.2(@types/node@20.14.11)(typescript@5.5.4) - update-check: 1.5.4 - validate-npm-package-name: 5.0.1 - transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' - - '@types/node' - - supports-color - - typescript - dev: true - - /@turbo/workspaces@1.13.4: - resolution: {integrity: sha512-3uYg2b5TWCiupetbDFMbBFMHl33xQTvp5DNg0fZSYal73Z9AlFH9yWabHWMYw6ywmwM1evkYRpTVA2n7GgqT5A==} - hasBin: true - dependencies: - chalk: 2.4.2 - commander: 10.0.1 - execa: 5.1.1 - fast-glob: 3.3.2 - fs-extra: 10.1.0 - gradient-string: 2.0.2 - inquirer: 8.2.6 - js-yaml: 4.1.0 - ora: 4.1.1 - rimraf: 3.0.2 - semver: 7.6.3 - update-check: 1.5.4 - dev: true - - /@types/eslint@8.56.11: - resolution: {integrity: sha512-sVBpJMf7UPo/wGecYOpk2aQya2VUGeHhe38WG7/mN5FufNSubf5VT9Uh9Uyp8/eLJpu1/tuhJ/qTo4mhSB4V4Q==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - dev: true - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/glob@7.2.0: - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 20.14.11 - dev: true - - /@types/inquirer@6.5.0: - resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} - dependencies: - '@types/through': 0.0.33 - rxjs: 6.6.7 - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/minimatch@5.1.2: - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - dev: true - - /@types/node@20.14.11: - resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: true - - /@types/prop-types@15.7.12: - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - dev: true - - /@types/react-dom@18.3.0: - resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - dependencies: - '@types/react': 18.3.3 - dev: true - - /@types/react@18.3.3: - resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} - dependencies: - '@types/prop-types': 15.7.12 - csstype: 3.1.3 - dev: true - - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true - - /@types/through@0.0.33: - resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} - dependencies: - '@types/node': 20.14.11 - dev: true - - /@types/tinycolor2@1.4.6: - resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} - dev: true - - /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 7.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 7.17.0 - '@typescript-eslint/type-utils': 7.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.17.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.17.0 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.17.0 - '@typescript-eslint/types': 7.17.0 - '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.17.0 - debug: 4.3.5 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - - /@typescript-eslint/scope-manager@6.21.0: - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - dev: true - - /@typescript-eslint/scope-manager@7.17.0: - resolution: {integrity: sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.17.0 - '@typescript-eslint/visitor-keys': 7.17.0 - dev: true - - /@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.5 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/type-utils@7.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.17.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.5 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@6.21.0: - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/types@7.17.0: - resolution: {integrity: sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==} - engines: {node: ^18.18.0 || >=20.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.4): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.3 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@6.21.0(typescript@5.5.4): - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@7.17.0(typescript@5.5.4): - resolution: {integrity: sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.17.0 - '@typescript-eslint/visitor-keys': 7.17.0 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@7.17.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.17.0 - '@typescript-eslint/types': 7.17.0 - '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@6.21.0: - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.17.0: - resolution: {integrity: sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.17.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@vercel/style-guide@5.2.0(eslint@8.57.0)(prettier@3.3.3)(typescript@5.5.4): - resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} - engines: {node: '>=16'} - peerDependencies: - '@next/eslint-plugin-next': '>=12.3.0 <15' - eslint: '>=8.48.0 <9' - prettier: '>=3.0.0 <4' - typescript: '>=4.8.0 <6' - peerDependenciesMeta: - '@next/eslint-plugin-next': - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - dependencies: - '@babel/core': 7.24.9 - '@babel/eslint-parser': 7.24.8(@babel/core@7.24.9)(eslint@8.57.0) - '@rushstack/eslint-patch': 1.10.3 - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) - eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.1) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.17.0)(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0) - eslint-plugin-react: 7.35.0(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) - eslint-plugin-testing-library: 6.2.2(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) - prettier: 3.3.3 - prettier-plugin-packagejson: 2.5.1(prettier@3.3.3) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /@vitest/expect@1.6.0: - resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} - dependencies: - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - chai: 4.4.1 - dev: true - - /@vitest/runner@1.6.0: - resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} - dependencies: - '@vitest/utils': 1.6.0 - p-limit: 5.0.0 - pathe: 1.1.2 - dev: true - - /@vitest/snapshot@1.6.0: - resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} - dependencies: - magic-string: 0.30.10 - pathe: 1.1.2 - pretty-format: 29.7.0 - dev: true - - /@vitest/spy@1.6.0: - resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} - dependencies: - tinyspy: 2.2.1 - dev: true - - /@vitest/utils@1.6.0: - resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} - dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 - dev: true - - /acorn-jsx@5.3.2(acorn@8.12.1): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.12.1 - dev: true - - /acorn-walk@8.3.3: - resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} - engines: {node: '>=0.4.0'} - dependencies: - acorn: 8.12.1 - dev: true - - /acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base@7.1.1: - resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} - engines: {node: '>= 14'} - dependencies: - debug: 4.3.5 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: false - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /app-root-path@3.1.0: - resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==} - engines: {node: '>= 6.0.0'} - dev: false - - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.1.3: - resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} - dependencies: - deep-equal: 2.2.3 - dev: true - - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - dev: true - - /array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - dev: true - - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - dev: true - - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true - - /ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - dev: true - - /ast-types@0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - dependencies: - tslib: 2.6.3 - dev: true - - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - dev: true - - /axe-core@4.9.1: - resolution: {integrity: sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==} - engines: {node: '>=4'} - dev: true - - /axobject-query@3.1.1: - resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} - dependencies: - deep-equal: 2.2.3 - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - /basic-ftp@5.0.5: - resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} - engines: {node: '>=10.0.0'} - dev: true - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - - /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.1.1 - dev: true - - /browserslist@4.23.2: - resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001643 - electron-to-chromium: 1.5.0 - node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.2) - dev: true - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - - /buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: false - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - dev: false - - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camel-case@3.0.0: - resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - dev: true - - /caniuse-lite@1.0.30001643: - resolution: {integrity: sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==} - - /chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - /change-case@3.1.0: - resolution: {integrity: sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==} - dependencies: - camel-case: 3.0.0 - constant-case: 2.0.0 - dot-case: 2.1.1 - header-case: 1.0.1 - is-lower-case: 1.1.3 - is-upper-case: 1.1.2 - lower-case: 1.1.4 - lower-case-first: 1.0.2 - no-case: 2.3.2 - param-case: 2.1.1 - pascal-case: 2.0.1 - path-case: 2.1.1 - sentence-case: 2.1.1 - snake-case: 2.1.0 - swap-case: 1.1.2 - title-case: 2.1.1 - upper-case: 1.1.3 - upper-case-first: 1.1.2 - dev: true - - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true - - /check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - dependencies: - get-func-name: 2.0.2 - dev: true - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true - - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: true - - /cli-highlight@2.1.11: - resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} - engines: {node: '>=8.0.0', npm: '>=5.0.0'} - hasBin: true - dependencies: - chalk: 4.1.2 - highlight.js: 10.7.3 - mz: 2.7.0 - parse5: 5.1.1 - parse5-htmlparser2-tree-adapter: 6.0.1 - yargs: 16.2.0 - dev: false - - /cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - dev: true - - /cli-width@3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} - dev: true - - /client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /confbox@0.1.7: - resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} - dev: true - - /constant-case@2.0.0: - resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} - dependencies: - snake-case: 2.1.0 - upper-case: 1.1.3 - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /core-js-pure@3.37.1: - resolution: {integrity: sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA==} - requiresBuild: true - dev: true - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - dev: true - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /data-uri-to-buffer@6.0.2: - resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} - engines: {node: '>= 14'} - dev: true - - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /dayjs@1.11.12: - resolution: {integrity: sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==} - dev: false - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug@4.3.5: - resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - dependencies: - type-detect: 4.0.8 - dev: true - - /deep-equal@2.2.3: - resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - es-get-iterator: 1.1.3 - get-intrinsic: 1.2.4 - is-arguments: 1.1.1 - is-array-buffer: 3.0.4 - is-date-object: 1.0.5 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - isarray: 2.0.5 - object-is: 1.1.6 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - side-channel: 1.0.6 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - dev: true - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true - - /degenerator@5.0.1: - resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} - engines: {node: '>= 14'} - dependencies: - ast-types: 0.13.4 - escodegen: 2.1.0 - esprima: 4.0.1 - dev: true - - /del@5.1.0: - resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} - engines: {node: '>=8'} - dependencies: - globby: 10.0.2 - graceful-fs: 4.2.11 - is-glob: 4.0.3 - is-path-cwd: 2.2.0 - is-path-inside: 3.0.3 - p-map: 3.0.0 - rimraf: 3.0.2 - slash: 3.0.0 - dev: true - - /detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - dev: true - - /detect-newline@4.0.1: - resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dot-case@2.1.1: - resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} - dependencies: - no-case: 2.3.2 - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} - engines: {node: '>=12'} - dev: false - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - /electron-to-chromium@1.5.0: - resolution: {integrity: sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - /enhanced-resolve@5.17.0: - resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.0 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 - globalthis: 1.0.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.2 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true - - /es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - is-arguments: 1.1.1 - is-map: 2.0.3 - is-set: 2.0.3 - is-string: 1.0.7 - isarray: 2.0.5 - stop-iteration-iterator: 1.0.0 - dev: true - - /es-iterator-helpers@1.0.19: - resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-set-tostringtag: 2.0.3 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - globalthis: 1.0.4 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - iterator.prototype: 1.1.2 - safe-array-concat: 1.1.2 - dev: true - - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - dev: true - - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - dev: true - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.2 - dev: true - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - dev: true - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-config-turbo@2.0.9(eslint@8.57.0): - resolution: {integrity: sha512-FoIMElI8md/dR5DxjB5Om52KJfi7Qf7RInXeE+PGU6lN388rumppwyqEJsZ7vnR5GhGa9cLPt0vNZwEK9iXtKg==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-turbo: 2.0.9(eslint@8.57.0) - dev: true - - /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.1): - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - dependencies: - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.17.0)(eslint@8.57.0) - dev: true - - /eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - dependencies: - debug: 3.2.7 - is-core-module: 2.15.0 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): - resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.5 - enhanced-resolve: 5.17.0 - eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.17.0)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.7.6 - is-core-module: 2.15.0 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.17.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 7.17.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): - resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} - engines: {node: '>=6.5.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - escape-string-regexp: 1.0.5 - eslint: 8.57.0 - ignore: 5.3.1 - dev: true - - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0)(eslint@8.57.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 7.17.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.17.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.15.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.9.0(eslint@8.57.0): - resolution: {integrity: sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - aria-query: 5.1.3 - array-includes: 3.1.8 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.8 - axe-core: 4.9.1 - axobject-query: 3.1.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.19 - eslint: 8.57.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - safe-regex-test: 1.0.3 - string.prototype.includes: 2.0.0 - dev: true - - /eslint-plugin-only-warn@1.1.0: - resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} - engines: {node: '>=6'} - dev: true - - /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0): - resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} - peerDependencies: - eslint: '>=7' - eslint-plugin-jest: '>=25' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - dependencies: - eslint: 8.57.0 - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.5.4) - dev: true - - /eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): - resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react@7.35.0(eslint@8.57.0): - resolution: {integrity: sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.2 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.19 - eslint: 8.57.0 - estraverse: 5.3.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.values: 1.2.0 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.11 - string.prototype.repeat: 1.0.0 - dev: true - - /eslint-plugin-testing-library@6.2.2(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true - - /eslint-plugin-turbo@2.0.9(eslint@8.57.0): - resolution: {integrity: sha512-q4s4mg6JcXzz5zK4LC3c6FcWehGAWjGj7kIM76ZvG0KiR9Ks0znzjnAKW0NoiDP4s/gt3r4YPOpI357qWt167Q==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.0 - dev: true - - /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.44.0' - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - ci-info: 3.9.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - esquery: 1.6.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.6.3 - strip-indent: 3.0.0 - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.11.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.5 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 3.4.3 - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - dependencies: - '@types/estree': 1.0.5 - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - dev: true - - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.7 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: true - - /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /foreground-child@3.2.1: - resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - - /fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false - - /get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - dev: true - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - dev: true - - /get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - dev: true - - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - dev: true - - /get-tsconfig@4.7.6: - resolution: {integrity: sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true - - /get-uri@6.0.3: - resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==} - engines: {node: '>= 14'} - dependencies: - basic-ftp: 5.0.5 - data-uri-to-buffer: 6.0.2 - debug: 4.3.5 - fs-extra: 11.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /git-hooks-list@3.1.0: - resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.2.1 - jackspeak: 2.3.6 - minimatch: 9.0.5 - minipass: 7.1.2 - path-scurry: 1.11.1 - dev: true - - /glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - dependencies: - foreground-child: 3.2.1 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.0 - path-scurry: 1.11.1 - dev: false - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - gopd: 1.0.1 - dev: true - - /globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} - dependencies: - '@types/glob': 7.2.0 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - glob: 7.2.3 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /gradient-string@2.0.2: - resolution: {integrity: sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - tinygradient: 1.1.5 - dev: true - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.0 - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: true - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /header-case@1.0.1: - resolution: {integrity: sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==} - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - dev: true - - /highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - dev: false - - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.1 - debug: 4.3.5 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent@7.0.5: - resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.1 - debug: 4.3.5 - transitivePeerDependencies: - - supports-color - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - dev: true - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - - /inquirer@7.3.3: - resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} - engines: {node: '>=8.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - run-async: 2.4.1 - rxjs: 6.6.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - dev: true - - /inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} - engines: {node: '>=12.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 - dev: true - - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - dev: true - - /ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - dev: true - - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.15.0: - resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==} - engines: {node: '>= 0.4'} - dependencies: - hasown: 2.0.2 - dev: true - - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - dependencies: - is-typed-array: 1.1.13 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: true - - /is-lower-case@1.1.3: - resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} - dependencies: - lower-case: 1.1.4 - dev: true - - /is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - dev: true - - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-cwd@2.2.0: - resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} - engines: {node: '>=6'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: true - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - dev: true - - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.15 - dev: true - - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true - - /is-upper-case@1.1.2: - resolution: {integrity: sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==} - dependencies: - upper-case: 1.1.3 - dev: true - - /is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - dev: true - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-weakset@2.0.3: - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isbinaryfile@4.0.10: - resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} - engines: {node: '>= 8.0.0'} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.6 - set-function-name: 2.0.2 - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: false - - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-tokens@9.0.0: - resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.2 - object.assign: 4.1.5 - object.values: 1.2.0 - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /language-subtag-registry@0.3.23: - resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} - dev: true - - /language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - dependencies: - language-subtag-registry: 0.3.23 - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /load-tsconfig@0.2.5: - resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /local-pkg@0.5.0: - resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} - engines: {node: '>=14'} - dependencies: - mlly: 1.7.1 - pkg-types: 1.1.3 - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.get@4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /log-symbols@3.0.0: - resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==} - engines: {node: '>=8'} - dependencies: - chalk: 2.4.2 - dev: true - - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - - /loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - dependencies: - get-func-name: 2.0.2 - dev: true - - /lower-case-first@1.0.2: - resolution: {integrity: sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==} - dependencies: - lower-case: 1.1.4 - dev: true - - /lower-case@1.1.4: - resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} - dev: true - - /lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - dev: true - - /magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - dev: true - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch@4.0.7: - resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true - - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - - /minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - /mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /mkdirp@2.1.6: - resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} - engines: {node: '>=10'} - hasBin: true - dev: false - - /mlly@1.7.1: - resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} - dependencies: - acorn: 8.12.1 - pathe: 1.1.2 - pkg-types: 1.1.3 - ufo: 1.5.4 - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - dev: true - - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: false - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /netmask@2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} - dev: true - - /next@14.2.5(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-0f8aRfBVL+mpzfBjYfQuLWh2WyAwtJXCRfkPF4UJ5qd2YwrHczsrSzXU4tRMV0OAxR8ZJZWPFn6uhSC56UTsLA==} - engines: {node: '>=18.17.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - sass: - optional: true - dependencies: - '@next/env': 14.2.5 - '@swc/helpers': 0.5.5 - busboy: 1.6.0 - caniuse-lite: 1.0.30001643 - graceful-fs: 4.2.11 - postcss: 8.4.31 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(react@18.3.1) - optionalDependencies: - '@next/swc-darwin-arm64': 14.2.5 - '@next/swc-darwin-x64': 14.2.5 - '@next/swc-linux-arm64-gnu': 14.2.5 - '@next/swc-linux-arm64-musl': 14.2.5 - '@next/swc-linux-x64-gnu': 14.2.5 - '@next/swc-linux-x64-musl': 14.2.5 - '@next/swc-win32-arm64-msvc': 14.2.5 - '@next/swc-win32-ia32-msvc': 14.2.5 - '@next/swc-win32-x64-msvc': 14.2.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - - /no-case@2.3.2: - resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} - dependencies: - lower-case: 1.1.4 - dev: true - - /node-plop@0.26.3: - resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==} - engines: {node: '>=8.9.4'} - dependencies: - '@babel/runtime-corejs3': 7.24.8 - '@types/inquirer': 6.5.0 - change-case: 3.1.0 - del: 5.1.0 - globby: 10.0.2 - handlebars: 4.7.8 - inquirer: 7.3.3 - isbinaryfile: 4.0.10 - lodash.get: 4.4.2 - mkdirp: 0.5.6 - resolve: 1.22.8 - dev: true - - /node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - dev: true - - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-inspect@1.13.2: - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} - engines: {node: '>= 0.4'} - dev: true - - /object-is@1.1.6: - resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - dev: true - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - dev: true - - /object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - - /optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - dev: true - - /ora@4.1.1: - resolution: {integrity: sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==} - engines: {node: '>=8'} - dependencies: - chalk: 3.0.0 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - log-symbols: 3.0.0 - mute-stream: 0.0.8 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - dependencies: - yocto-queue: 1.1.1 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-map@3.0.0: - resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} - engines: {node: '>=8'} - dependencies: - aggregate-error: 3.1.0 - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /pac-proxy-agent@7.0.2: - resolution: {integrity: sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==} - engines: {node: '>= 14'} - dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 - agent-base: 7.1.1 - debug: 4.3.5 - get-uri: 6.0.3 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.5 - pac-resolver: 7.0.1 - socks-proxy-agent: 8.0.4 - transitivePeerDependencies: - - supports-color - dev: true - - /pac-resolver@7.0.1: - resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} - engines: {node: '>= 14'} - dependencies: - degenerator: 5.0.1 - netmask: 2.0.2 - dev: true - - /package-json-from-dist@1.0.0: - resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} - dev: false - - /param-case@2.1.1: - resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} - dependencies: - no-case: 2.3.2 - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.24.7 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse5-htmlparser2-tree-adapter@6.0.1: - resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} - dependencies: - parse5: 6.0.1 - dev: false - - /parse5@5.1.1: - resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} - dev: false - - /parse5@6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - dev: false - - /pascal-case@2.0.1: - resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} - dependencies: - camel-case: 3.0.0 - upper-case-first: 1.1.2 - dev: true - - /path-case@2.1.1: - resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} - dependencies: - no-case: 2.3.2 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - dev: true - - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true - - /picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pkg-types@1.1.3: - resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==} - dependencies: - confbox: 0.1.7 - mlly: 1.7.1 - pathe: 1.1.2 - dev: true - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: true - - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - dev: false - - /postcss@8.4.39: - resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - dev: true - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-plugin-packagejson@2.5.1(prettier@3.3.3): - resolution: {integrity: sha512-6i4PW1KxEA+VrokYNGeI/q8qQX3u5DNBc7eLr9GX4OrvWr9DMls1lhbuNopkKG7Li9rTNxerWnYQyjxoUO4ROA==} - peerDependencies: - prettier: '>= 1.16.0' - peerDependenciesMeta: - prettier: - optional: true - dependencies: - prettier: 3.3.3 - sort-package-json: 2.10.0 - synckit: 0.9.1 - dev: true - - /prettier@3.3.3: - resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - dev: true - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /proxy-agent@6.4.0: - resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.1 - debug: 4.3.5 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.5 - lru-cache: 7.18.3 - pac-proxy-agent: 7.0.2 - proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.4 - transitivePeerDependencies: - - supports-color - dev: true - - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - dev: true - - /react-dom@18.3.1(react@18.3.1): - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - dev: false - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - dev: true - - /react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - dev: false - - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /reflect-metadata@0.2.2: - resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} - dev: false - - /reflect.getprototypeof@1.0.6: - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - globalthis: 1.0.4 - which-builtin-type: 1.1.3 - dev: true - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true - - /regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - hasBin: true - dev: true - - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - dev: true - - /registry-auth-token@3.3.2: - resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} - dependencies: - rc: 1.2.8 - safe-buffer: 5.2.1 - dev: true - - /registry-url@3.1.0: - resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} - engines: {node: '>=0.10.0'} - dependencies: - rc: 1.2.8 - dev: true - - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: false - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.15.0 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.15.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.15.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rollup@4.19.0: - resolution: {integrity: sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.19.0 - '@rollup/rollup-android-arm64': 4.19.0 - '@rollup/rollup-darwin-arm64': 4.19.0 - '@rollup/rollup-darwin-x64': 4.19.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.19.0 - '@rollup/rollup-linux-arm-musleabihf': 4.19.0 - '@rollup/rollup-linux-arm64-gnu': 4.19.0 - '@rollup/rollup-linux-arm64-musl': 4.19.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.19.0 - '@rollup/rollup-linux-riscv64-gnu': 4.19.0 - '@rollup/rollup-linux-s390x-gnu': 4.19.0 - '@rollup/rollup-linux-x64-gnu': 4.19.0 - '@rollup/rollup-linux-x64-musl': 4.19.0 - '@rollup/rollup-win32-arm64-msvc': 4.19.0 - '@rollup/rollup-win32-ia32-msvc': 4.19.0 - '@rollup/rollup-win32-x64-msvc': 4.19.0 - fsevents: 2.3.3 - dev: true - - /run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /rxjs@6.6.7: - resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} - engines: {npm: '>=2.0.0'} - dependencies: - tslib: 1.14.1 - dev: true - - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - dependencies: - tslib: 2.6.3 - dev: true - - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true - - /scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /sentence-case@2.1.1: - resolution: {integrity: sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==} - dependencies: - no-case: 2.3.2 - upper-case-first: 1.1.2 - dev: true - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - dev: true - - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - - /sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: false - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.2 - dev: true - - /siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true - - /snake-case@2.1.0: - resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} - dependencies: - no-case: 2.3.2 - dev: true - - /socks-proxy-agent@8.0.4: - resolution: {integrity: sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.1 - debug: 4.3.5 - socks: 2.8.3 - transitivePeerDependencies: - - supports-color - dev: true - - /socks@2.8.3: - resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - dev: true - - /sort-object-keys@1.1.3: - resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - dev: true - - /sort-package-json@2.10.0: - resolution: {integrity: sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==} - hasBin: true - dependencies: - detect-indent: 7.0.1 - detect-newline: 4.0.1 - get-stdin: 9.0.0 - git-hooks-list: 3.1.0 - globby: 13.2.2 - is-plain-obj: 4.1.0 - semver: 7.6.3 - sort-object-keys: 1.1.3 - dev: true - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.18 - dev: true - - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.18 - dev: true - - /spdx-license-ids@3.0.18: - resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} - dev: true - - /sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - dev: true - - /sql.js@1.10.3: - resolution: {integrity: sha512-H46aWtQkdyjZwFQgraUruy5h/DyJBbAK3EA/WEMqiqF6PGPfKBSKBj/er3dVyYqVIoYfRf5TFM/loEjtQIrqJg==} - dev: false - - /stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - dev: true - - /std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - dev: true - - /stop-iteration-iterator@1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} - dependencies: - internal-slot: 1.0.7 - dev: true - - /streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - dev: false - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - - /string.prototype.includes@2.0.0: - resolution: {integrity: sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.3 - dev: true - - /string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.2 - side-channel: 1.0.6 - dev: true - - /string.prototype.repeat@1.0.0: - resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.3 - dev: true - - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /strip-literal@2.1.0: - resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} - dependencies: - js-tokens: 9.0.0 - dev: true - - /styled-jsx@5.1.1(react@18.3.1): - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - client-only: 0.0.1 - react: 18.3.1 - dev: false - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /swap-case@1.1.2: - resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} - dependencies: - lower-case: 1.1.4 - upper-case: 1.1.3 - dev: true - - /synckit@0.9.1: - resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.3 - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: false - - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: false - - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true - - /tinybench@2.8.0: - resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} - dev: true - - /tinycolor2@1.6.0: - resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} - dev: true - - /tinygradient@1.1.5: - resolution: {integrity: sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==} - dependencies: - '@types/tinycolor2': 1.4.6 - tinycolor2: 1.6.0 - dev: true - - /tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} - engines: {node: '>=14.0.0'} - dev: true - - /tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} - engines: {node: '>=14.0.0'} - dev: true - - /title-case@2.1.1: - resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} - dependencies: - no-case: 2.3.2 - upper-case: 1.1.3 - dev: true - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /ts-api-utils@1.3.0(typescript@5.5.4): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /ts-node@10.9.2(@types/node@20.14.11)(typescript@5.5.4): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.11 - acorn: 8.12.1 - acorn-walk: 8.3.3 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.5.4 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib@2.6.3: - resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} - - /tsutils@3.21.0(typescript@5.5.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.4 - dev: true - - /turbo-darwin-64@2.0.9: - resolution: {integrity: sha512-owlGsOaExuVGBUfrnJwjkL1BWlvefjSKczEAcpLx4BI7Oh6ttakOi+JyomkPkFlYElRpjbvlR2gP8WIn6M/+xQ==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.9: - resolution: {integrity: sha512-XAXkKkePth5ZPPE/9G9tTnPQx0C8UTkGWmNGYkpmGgRr8NedW+HrPsi9N0HcjzzIH9A4TpNYvtiV+WcwdaEjKA==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.9: - resolution: {integrity: sha512-l9wSgEjrCFM1aG16zItBsZ206ZlhSSx1owB8Cgskfv0XyIXRGHRkluihiaxkp+UeU5WoEfz4EN5toc+ICA0q0w==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.9: - resolution: {integrity: sha512-gRnjxXRne18B27SwxXMqL3fJu7jw/8kBrOBTBNRSmZZiG1Uu3nbnP7b4lgrA/bCku6C0Wligwqurvtpq6+nFHA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.9: - resolution: {integrity: sha512-ZVo0apxUvaRq4Vm1qhsfqKKhtRgReYlBVf9MQvVU1O9AoyydEQvLDO1ryqpXDZWpcHoFxHAQc9msjAMtE5K2lA==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.9: - resolution: {integrity: sha512-sGRz7c5Pey6y7y9OKi8ypbWNuIRPF9y8xcMqL56OZifSUSo+X2EOsOleR9MKxQXVaqHPGOUKWsE6y8hxBi9pag==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.9: - resolution: {integrity: sha512-QaLaUL1CqblSKKPgLrFW3lZWkWG4pGBQNW+q1ScJB5v1D/nFWtsrD/yZljW/bdawg90ihi4/ftQJ3h6fz1FamA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.9 - turbo-darwin-arm64: 2.0.9 - turbo-linux-64: 2.0.9 - turbo-linux-arm64: 2.0.9 - turbo-windows-64: 2.0.9 - turbo-windows-arm64: 2.0.9 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 - dev: true - - /typeorm@0.3.20(sql.js@1.10.3): - resolution: {integrity: sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==} - engines: {node: '>=16.13.0'} - hasBin: true - peerDependencies: - '@google-cloud/spanner': ^5.18.0 - '@sap/hana-client': ^2.12.25 - better-sqlite3: ^7.1.2 || ^8.0.0 || ^9.0.0 - hdb-pool: ^0.1.6 - ioredis: ^5.0.4 - mongodb: ^5.8.0 - mssql: ^9.1.1 || ^10.0.1 - mysql2: ^2.2.5 || ^3.0.1 - oracledb: ^6.3.0 - pg: ^8.5.1 - pg-native: ^3.0.0 - pg-query-stream: ^4.0.0 - redis: ^3.1.1 || ^4.0.0 - sql.js: ^1.4.0 - sqlite3: ^5.0.3 - ts-node: ^10.7.0 - typeorm-aurora-data-api-driver: ^2.0.0 - peerDependenciesMeta: - '@google-cloud/spanner': - optional: true - '@sap/hana-client': - optional: true - better-sqlite3: - optional: true - hdb-pool: - optional: true - ioredis: - optional: true - mongodb: - optional: true - mssql: - optional: true - mysql2: - optional: true - oracledb: - optional: true - pg: - optional: true - pg-native: - optional: true - pg-query-stream: - optional: true - redis: - optional: true - sql.js: - optional: true - sqlite3: - optional: true - ts-node: - optional: true - typeorm-aurora-data-api-driver: - optional: true - dependencies: - '@sqltools/formatter': 1.2.5 - app-root-path: 3.1.0 - buffer: 6.0.3 - chalk: 4.1.2 - cli-highlight: 2.1.11 - dayjs: 1.11.12 - debug: 4.3.5 - dotenv: 16.4.5 - glob: 10.4.5 - mkdirp: 2.1.6 - reflect-metadata: 0.2.2 - sha.js: 2.4.11 - sql.js: 1.10.3 - tslib: 2.6.3 - uuid: 9.0.1 - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - dev: false - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /ufo@1.5.4: - resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - dev: true - - /uglify-js@3.19.0: - resolution: {integrity: sha512-wNKHUY2hYYkf6oSFfhwwiHo4WCHzHmzcXsqXYTN9ja3iApYIFbb2U6ics9hBcYLHcYGQoAlwnZlTrf3oF+BL/Q==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: true - - /unplugin-swc@1.5.1(@swc/core@1.7.0): - resolution: {integrity: sha512-/ZLrPNjChhGx3Z95pxJ4tQgfI6rWqukgYHKflrNB4zAV1izOQuDhkTn55JWeivpBxDCoK7M/TStb2aS/14PS/g==} - peerDependencies: - '@swc/core': ^1.2.108 - dependencies: - '@rollup/pluginutils': 5.1.0 - '@swc/core': 1.7.0 - load-tsconfig: 0.2.5 - unplugin: 1.11.0 - transitivePeerDependencies: - - rollup - dev: true - - /unplugin@1.11.0: - resolution: {integrity: sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==} - engines: {node: '>=14.0.0'} - dependencies: - acorn: 8.12.1 - chokidar: 3.6.0 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.6.2 - dev: true - - /update-browserslist-db@1.1.0(browserslist@4.23.2): - resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.2 - escalade: 3.1.2 - picocolors: 1.0.1 - dev: true - - /update-check@1.5.4: - resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} - dependencies: - registry-auth-token: 3.3.2 - registry-url: 3.1.0 - dev: true - - /upper-case-first@1.1.2: - resolution: {integrity: sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==} - dependencies: - upper-case: 1.1.3 - dev: true - - /upper-case@1.1.3: - resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} - hasBin: true - dev: false - - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /validate-npm-package-name@5.0.1: - resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /vite-node@1.6.0(@types/node@20.14.11): - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.5 - pathe: 1.1.2 - picocolors: 1.0.1 - vite: 5.3.4(@types/node@20.14.11) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /vite@5.3.4(@types/node@20.14.11): - resolution: {integrity: sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 20.14.11 - esbuild: 0.21.5 - postcss: 8.4.39 - rollup: 4.19.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vitest@1.6.0(@types/node@20.14.11): - resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.0 - '@vitest/ui': 1.6.0 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - dependencies: - '@types/node': 20.14.11 - '@vitest/expect': 1.6.0 - '@vitest/runner': 1.6.0 - '@vitest/snapshot': 1.6.0 - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - acorn-walk: 8.3.3 - chai: 4.4.1 - debug: 4.3.5 - execa: 8.0.1 - local-pkg: 0.5.0 - magic-string: 0.30.10 - pathe: 1.1.2 - picocolors: 1.0.1 - std-env: 3.7.0 - strip-literal: 2.1.0 - tinybench: 2.8.0 - tinypool: 0.8.4 - vite: 5.3.4(@types/node@20.14.11) - vite-node: 1.6.0(@types/node@20.14.11) - why-is-node-running: 2.3.0 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack-virtual-modules@0.6.2: - resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - dev: true - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.2 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.3 - dev: true - - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.2 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - - /why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - dev: true - - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: false - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: false - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false - - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: false - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: false - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /yocto-queue@1.1.1: - resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} - engines: {node: '>=12.20'} - dev: true diff --git a/examples/with-vite-react/.eslintrc.js b/examples/with-vite-react/.eslintrc.js deleted file mode 100644 index 02f791d5efbc1..0000000000000 --- a/examples/with-vite-react/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/index.js"], -}; diff --git a/examples/with-vite-react/README.md b/examples/with-vite-react/README.md deleted file mode 100644 index dd4f5be62276e..0000000000000 --- a/examples/with-vite-react/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# `Turborepo` Vite starter - -This is an official starter Turborepo. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-vite-react -``` - -## What's inside? - -This Turborepo includes the following packages and apps: - -### Apps and Packages - -- `web`: react [vite](https://vitejs.dev) ts app -- `@repo/ui`: a stub component library shared by `web` application -- `@repo/eslint-config`: shared `eslint` configurations -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package and app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/with-vite-react/apps/web/.eslintrc.cjs b/examples/with-vite-react/apps/web/.eslintrc.cjs deleted file mode 100644 index 02f791d5efbc1..0000000000000 --- a/examples/with-vite-react/apps/web/.eslintrc.cjs +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/index.js"], -}; diff --git a/examples/with-vite-react/apps/web/src/main.tsx b/examples/with-vite-react/apps/web/Source/main.tsx similarity index 100% rename from examples/with-vite-react/apps/web/src/main.tsx rename to examples/with-vite-react/apps/web/Source/main.tsx diff --git a/examples/with-vite-react/apps/web/src/style.css b/examples/with-vite-react/apps/web/Source/style.css similarity index 100% rename from examples/with-vite-react/apps/web/src/style.css rename to examples/with-vite-react/apps/web/Source/style.css diff --git a/examples/with-vite-react/apps/web/src/vite-env.d.ts b/examples/with-vite-react/apps/web/Source/vite-env.d.ts similarity index 100% rename from examples/with-vite-react/apps/web/src/vite-env.d.ts rename to examples/with-vite-react/apps/web/Source/vite-env.d.ts diff --git a/examples/with-vite-react/apps/web/package.json b/examples/with-vite-react/apps/web/package.json index 4406b2e2424f3..757396b8fdaa5 100644 --- a/examples/with-vite-react/apps/web/package.json +++ b/examples/with-vite-react/apps/web/package.json @@ -1,27 +1,15 @@ { - "name": "web", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite --clearScreen false", - "build": "tsc && vite build", - "preview": "vite preview", - "lint": "eslint \"src/**/*.ts\"" - }, - "dependencies": { - "@repo/ui": "workspace:*", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "@types/react": "^19.0.1", - "@types/react-dom": "^19.0.2", - "@vitejs/plugin-react": "^3.1.0", - "eslint": "^8.57.0", - "typescript": "5.5.4", - "vite": "^5.1.4" - } + "name": "web", + "scripts": { + "build": "tsc && vite build", + "dev": "vite --clearScreen false", + "preview": "vite preview" + }, + "dependencies": { + "@repo/ui": "workspace:*" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*" + } } diff --git a/examples/with-vite-react/package.json b/examples/with-vite-react/package.json index c47b1cfe0b465..4f76cd6fcf365 100644 --- a/examples/with-vite-react/package.json +++ b/examples/with-vite-react/package.json @@ -1,16 +1,11 @@ { - "private": true, - "scripts": { - "build": "turbo build", - "dev": "turbo dev", - "lint": "turbo lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "eslint": "^8.57.0", - "prettier": "^3.2.5", - "turbo": "^2.3.3" - }, - "packageManager": "pnpm@8.15.6", - "name": "with-vite-react" + "name": "with-vite-react", + "scripts": { + "build": "turbo build", + "dev": "turbo dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-vite-react/packages/eslint-config/package.json b/examples/with-vite-react/packages/eslint-config/package.json index fc2acf1aadbab..d6e588b23ab4c 100644 --- a/examples/with-vite-react/packages/eslint-config/package.json +++ b/examples/with-vite-react/packages/eslint-config/package.json @@ -1,14 +1,6 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "main": "index.js", - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "eslint-config-prettier": "^9.1.0" - }, - "publishConfig": { - "access": "public" - } + "name": "@repo/eslint-config", + "main": "index.js", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-vite-react/packages/typescript-config/package.json b/examples/with-vite-react/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-vite-react/packages/typescript-config/package.json +++ b/examples/with-vite-react/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-vite-react/packages/ui/.eslintrc.cjs b/examples/with-vite-react/packages/ui/.eslintrc.cjs deleted file mode 100644 index 1ba520f7bf3f3..0000000000000 --- a/examples/with-vite-react/packages/ui/.eslintrc.cjs +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@repo/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-vite-react/packages/ui/package.json b/examples/with-vite-react/packages/ui/package.json index 991c4e6f34d0a..b106e28ea1716 100644 --- a/examples/with-vite-react/packages/ui/package.json +++ b/examples/with-vite-react/packages/ui/package.json @@ -1,26 +1,15 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "exports": { - ".": "./index.ts", - "./counter": "./components/counter.ts", - "./header": "./components/header.ts", - "./setup-counter": "./utils/counter.ts" - }, - "license": "MIT", - "scripts": { - "lint": "eslint \"**/*.ts\"" - }, - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/react": "^19.0.1", - "@types/react-dom": "^19.0.2", - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "@repo/ui", + "exports": { + ".": "./index.ts", + "./counter": "./components/counter.ts", + "./header": "./components/header.ts", + "./setup-counter": "./utils/counter.ts" + }, + "scripts": {}, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*" + } } diff --git a/examples/with-vite-react/pnpm-lock.yaml b/examples/with-vite-react/pnpm-lock.yaml deleted file mode 100644 index 14a94cbe7f953..0000000000000 --- a/examples/with-vite-react/pnpm-lock.yaml +++ /dev/null @@ -1,2091 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - eslint: - specifier: ^8.57.0 - version: 8.57.0 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - turbo: - specifier: ^2.3.3 - version: 2.3.3 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - '@types/react': - specifier: ^19.0.1 - version: 19.0.1 - '@types/react-dom': - specifier: ^19.0.2 - version: 19.0.2(@types/react@19.0.1) - '@vitejs/plugin-react': - specifier: ^3.1.0 - version: 3.1.0(vite@5.1.4) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - vite: - specifier: ^5.1.4 - version: 5.1.4 - - packages/eslint-config: - dependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.1.0(eslint@8.57.0)(typescript@5.5.4) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - - packages/typescript-config: {} - - packages/ui: - dependencies: - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - '@types/react': - specifier: ^19.0.1 - version: 19.0.1 - '@types/react-dom': - specifier: ^19.0.2 - version: 19.0.2(@types/react@19.0.1) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.26.3': - resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.26.0': - resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.26.3': - resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.25.9': - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.25.9': - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.26.0': - resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.26.3': - resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-transform-react-jsx-self@7.25.9': - resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.25.9': - resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/template@7.25.9': - resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.26.4': - resolution: {integrity: sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.26.3': - resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} - engines: {node: '>=6.9.0'} - - '@esbuild/android-arm64@0.19.7': - resolution: {integrity: sha512-YEDcw5IT7hW3sFKZBkCAQaOCJQLONVcD4bOyTXMZz5fr66pTHnAet46XAtbXAkJRfIn2YVhdC6R9g4xa27jQ1w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.19.7': - resolution: {integrity: sha512-YGSPnndkcLo4PmVl2tKatEn+0mlVMr3yEpOOT0BeMria87PhvoJb5dg5f5Ft9fbCVgtAz4pWMzZVgSEGpDAlww==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.19.7': - resolution: {integrity: sha512-jhINx8DEjz68cChFvM72YzrqfwJuFbfvSxZAk4bebpngGfNNRm+zRl4rtT9oAX6N9b6gBcFaJHFew5Blf6CvUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.19.7': - resolution: {integrity: sha512-dr81gbmWN//3ZnBIm6YNCl4p3pjnabg1/ZVOgz2fJoUO1a3mq9WQ/1iuEluMs7mCL+Zwv7AY5e3g1hjXqQZ9Iw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.19.7': - resolution: {integrity: sha512-Lc0q5HouGlzQEwLkgEKnWcSazqr9l9OdV2HhVasWJzLKeOt0PLhHaUHuzb8s/UIya38DJDoUm74GToZ6Wc7NGQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.19.7': - resolution: {integrity: sha512-+y2YsUr0CxDFF7GWiegWjGtTUF6gac2zFasfFkRJPkMAuMy9O7+2EH550VlqVdpEEchWMynkdhC9ZjtnMiHImQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.19.7': - resolution: {integrity: sha512-CdXOxIbIzPJmJhrpmJTLx+o35NoiKBIgOvmvT+jeSadYiWJn0vFKsl+0bSG/5lwjNHoIDEyMYc/GAPR9jxusTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.19.7': - resolution: {integrity: sha512-inHqdOVCkUhHNvuQPT1oCB7cWz9qQ/Cz46xmVe0b7UXcuIJU3166aqSunsqkgSGMtUCWOZw3+KMwI6otINuC9g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.19.7': - resolution: {integrity: sha512-Y+SCmWxsJOdQtjcBxoacn/pGW9HDZpwsoof0ttL+2vGcHokFlfqV666JpfLCSP2xLxFpF1lj7T3Ox3sr95YXww==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.19.7': - resolution: {integrity: sha512-2BbiL7nLS5ZO96bxTQkdO0euGZIUQEUXMTrqLxKUmk/Y5pmrWU84f+CMJpM8+EHaBPfFSPnomEaQiG/+Gmh61g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.19.7': - resolution: {integrity: sha512-BVFQla72KXv3yyTFCQXF7MORvpTo4uTA8FVFgmwVrqbB/4DsBFWilUm1i2Oq6zN36DOZKSVUTb16jbjedhfSHw==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.19.7': - resolution: {integrity: sha512-DzAYckIaK+pS31Q/rGpvUKu7M+5/t+jI+cdleDgUwbU7KdG2eC3SUbZHlo6Q4P1CfVKZ1lUERRFP8+q0ob9i2w==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.19.7': - resolution: {integrity: sha512-JQ1p0SmUteNdUaaiRtyS59GkkfTW0Edo+e0O2sihnY4FoZLz5glpWUQEKMSzMhA430ctkylkS7+vn8ziuhUugQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.19.7': - resolution: {integrity: sha512-xGwVJ7eGhkprY/nB7L7MXysHduqjpzUl40+XoYDGC4UPLbnG+gsyS1wQPJ9lFPcxYAaDXbdRXd1ACs9AE9lxuw==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.19.7': - resolution: {integrity: sha512-U8Rhki5PVU0L0nvk+E8FjkV8r4Lh4hVEb9duR6Zl21eIEYEwXz8RScj4LZWA2i3V70V4UHVgiqMpszXvG0Yqhg==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.19.7': - resolution: {integrity: sha512-ZYZopyLhm4mcoZXjFt25itRlocKlcazDVkB4AhioiL9hOWhDldU9n38g62fhOI4Pth6vp+Mrd5rFKxD0/S+7aQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.19.7': - resolution: {integrity: sha512-/yfjlsYmT1O3cum3J6cmGG16Fd5tqKMcg5D+sBYLaOQExheAJhqr8xOAEIuLo8JYkevmjM5zFD9rVs3VBcsjtQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-x64@0.19.7': - resolution: {integrity: sha512-MYDFyV0EW1cTP46IgUJ38OnEY5TaXxjoDmwiTXPjezahQgZd+j3T55Ht8/Q9YXBM0+T9HJygrSRGV5QNF/YVDQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.19.7': - resolution: {integrity: sha512-JcPvgzf2NN/y6X3UUSqP6jSS06V0DZAV/8q0PjsZyGSXsIGcG110XsdmuWiHM+pno7/mJF6fjH5/vhUz/vA9fw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.19.7': - resolution: {integrity: sha512-ZA0KSYti5w5toax5FpmfcAgu3ZNJxYSRm0AW/Dao5up0YV1hDVof1NvwLomjEN+3/GMtaWDI+CIyJOMTRSTdMw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.19.7': - resolution: {integrity: sha512-CTOnijBKc5Jpk6/W9hQMMvJnsSYRYgveN6O75DTACCY18RA2nqka8dTZR+x/JqXCRiKk84+5+bRKXUSbbwsS0A==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.19.7': - resolution: {integrity: sha512-gRaP2sk6hc98N734luX4VpF318l3w+ofrtTu9j5L8EQXF+FzQKV6alCOHMVoJJHvVK/mGbwBXfOL1HETQu9IGQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/object-schema@2.0.2': - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - deprecated: Use @eslint/object-schema instead - - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@rollup/rollup-android-arm-eabi@4.5.2': - resolution: {integrity: sha512-ee7BudTwwrglFYSc3UnqInDDjCLWHKrFmGNi4aK7jlEyg4CyPa1DCMrZfsN1O13YT76UFEqXz2CoN7BCGpUlJw==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.5.2': - resolution: {integrity: sha512-xOuhj9HHtn8128ir8veoQsBbAUBasDbHIBniYTEx02pAmu9EXL+ZjJqngnNEy6ZgZ4h1JwL33GMNu3yJL5Mzow==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.5.2': - resolution: {integrity: sha512-NTGJWoL8bKyqyWFn9/RzSv4hQ4wTbaAv0lHHRwf4OnpiiP4P8W0jiXbm8Nc5BCXKmWAwuvJY82mcIU2TayC20g==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.5.2': - resolution: {integrity: sha512-hlKqj7bpPvU15sZo4za14u185lpMzdwWLMc9raMqPK4wywt0wR23y1CaVQ4oAFXat3b5/gmRntyfpwWTKl+vvA==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-linux-arm-gnueabihf@4.5.2': - resolution: {integrity: sha512-7ZIZx8c3u+pfI0ohQsft/GywrXez0uR6dUP0JhBuCK3sFO5TfdLn/YApnVkvPxuTv3+YKPIZend9Mt7Cz6sS3Q==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.5.2': - resolution: {integrity: sha512-7Pk/5mO11JW/cH+a8lL/i0ZxmRGrbpYqN0VwO2DHhU+SJWWOH2zE1RAcPaj8KqiwC8DCDIJOSxjV9+9lLb6aeA==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.5.2': - resolution: {integrity: sha512-KrRnuG5phJx756e62wxvWH2e+TK84MP2IVuPwfge+GBvWqIUfVzFRn09TKruuQBXzZp52Vyma7FjMDkwlA9xpg==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.5.2': - resolution: {integrity: sha512-My+53GasPa2D2tU5dXiyHYwrELAUouSfkNlZ3bUKpI7btaztO5vpALEs3mvFjM7aKTvEbc7GQckuXeXIDKQ0fg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.5.2': - resolution: {integrity: sha512-/f0Q6Sc+Vw54Ws6N8fxaEe4R7at3b8pFyv+O/F2VaQ4hODUJcRUcCBJh6zuqtgQQt7w845VTkGLFgWZkP3tUoQ==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-win32-arm64-msvc@4.5.2': - resolution: {integrity: sha512-NCKuuZWLht6zj7s6EIFef4BxCRX1GMr83S2W4HPCA0RnJ4iHE4FS1695q6Ewoa6A9nFjJe1//yUu0kgBU07Edw==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.5.2': - resolution: {integrity: sha512-J5zL3riR4AOyU/J3M/i4k/zZ8eP1yT+nTmAKztCXJtnI36jYH0eepvob22mAQ/kLwfsK2TB6dbyVY1F8c/0H5A==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.5.2': - resolution: {integrity: sha512-pL0RXRHuuGLhvs7ayX/SAHph1hrDPXOM5anyYUQXWJEENxw3nfHkzv8FfVlEVcLyKPAEgDRkd6RKZq2SMqS/yg==} - cpu: [x64] - os: [win32] - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/react-dom@19.0.2': - resolution: {integrity: sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==} - peerDependencies: - '@types/react': ^19.0.0 - - '@types/react@19.0.1': - resolution: {integrity: sha512-YW6614BDhqbpR5KtUYzTA+zlA7nayzJRA9ljz9CQoxthR0sDisYZLuvSMsil36t4EH/uAt8T52Xb4sVw17G+SQ==} - - '@types/semver@7.5.6': - resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} - - '@typescript-eslint/eslint-plugin@7.1.0': - resolution: {integrity: sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/parser@7.1.0': - resolution: {integrity: sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/scope-manager@7.1.0': - resolution: {integrity: sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@typescript-eslint/type-utils@7.1.0': - resolution: {integrity: sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@7.1.0': - resolution: {integrity: sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@typescript-eslint/typescript-estree@7.1.0': - resolution: {integrity: sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@7.1.0': - resolution: {integrity: sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - - '@typescript-eslint/visitor-keys@7.1.0': - resolution: {integrity: sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - - '@vitejs/plugin-react@3.1.0': - resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.1.0-beta.0 - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - - browserslist@4.24.3: - resolution: {integrity: sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - caniuse-lite@1.0.30001688: - resolution: {integrity: sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - - electron-to-chromium@1.5.73: - resolution: {integrity: sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==} - - esbuild@0.19.7: - resolution: {integrity: sha512-6brbTZVqxhqgbpqBR5MzErImcpA0SQdoKOkcWK/U30HtQxnokIpG3TX2r0IJqbFUzqLjhU/zC1S5ndgakObVCQ==} - engines: {node: '>=12'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-config-prettier@9.1.0: - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. - hasBin: true - - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - - flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - - magic-string@0.27.0: - resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} - engines: {node: '>=12'} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - postcss@8.4.35: - resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-dom@18.3.1: - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - - react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} - engines: {node: '>=0.10.0'} - - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - - rollup@4.5.2: - resolution: {integrity: sha512-CRK1uoROBfkcqrZKyaFcqCcZWNsvJ6yVYZkqTlRocZhO2s5yER6Z3f/QaYtO8RGyloPnmhwgzuPQpNGeK210xQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - ts-api-utils@1.0.3: - resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} - engines: {node: '>=16.13.0'} - peerDependencies: - typescript: '>=4.2.0' - - turbo-darwin-64@2.3.3: - resolution: {integrity: sha512-bxX82xe6du/3rPmm4aCC5RdEilIN99VUld4HkFQuw+mvFg6darNBuQxyWSHZTtc25XgYjQrjsV05888w1grpaA==} - cpu: [x64] - os: [darwin] - - turbo-darwin-arm64@2.3.3: - resolution: {integrity: sha512-DYbQwa3NsAuWkCUYVzfOUBbSUBVQzH5HWUFy2Kgi3fGjIWVZOFk86ss+xsWu//rlEAfYwEmopigsPYSmW4X15A==} - cpu: [arm64] - os: [darwin] - - turbo-linux-64@2.3.3: - resolution: {integrity: sha512-eHj9OIB0dFaP6BxB88jSuaCLsOQSYWBgmhy2ErCu6D2GG6xW3b6e2UWHl/1Ho9FsTg4uVgo4DB9wGsKa5erjUA==} - cpu: [x64] - os: [linux] - - turbo-linux-arm64@2.3.3: - resolution: {integrity: sha512-NmDE/NjZoDj1UWBhMtOPmqFLEBKhzGS61KObfrDEbXvU3lekwHeoPvAMfcovzswzch+kN2DrtbNIlz+/rp8OCg==} - cpu: [arm64] - os: [linux] - - turbo-windows-64@2.3.3: - resolution: {integrity: sha512-O2+BS4QqjK3dOERscXqv7N2GXNcqHr9hXumkMxDj/oGx9oCatIwnnwx34UmzodloSnJpgSqjl8iRWiY65SmYoQ==} - cpu: [x64] - os: [win32] - - turbo-windows-arm64@2.3.3: - resolution: {integrity: sha512-dW4ZK1r6XLPNYLIKjC4o87HxYidtRRcBeo/hZ9Wng2XM/MqqYkAyzJXJGgRMsc0MMEN9z4+ZIfnSNBrA0b08ag==} - cpu: [arm64] - os: [win32] - - turbo@2.3.3: - resolution: {integrity: sha512-DUHWQAcC8BTiUZDRzAYGvpSpGLiaOQPfYXlCieQbwUvmml/LRGIe3raKdrOPOoiX0DYlzxs2nH6BoWJoZrj8hA==} - hasBin: true - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - - typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - vite@5.1.4: - resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@aashutoshrathi/word-wrap@1.2.6': {} - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.0.0 - - '@babel/compat-data@7.26.3': {} - - '@babel/core@7.26.0': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.3 - '@babel/template': 7.25.9 - '@babel/traverse': 7.26.4 - '@babel/types': 7.26.3 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.26.3': - dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.25.9': - dependencies: - '@babel/compat-data': 7.26.3 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.3 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-module-imports@7.25.9': - dependencies: - '@babel/traverse': 7.26.4 - '@babel/types': 7.26.3 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.4 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.25.9': {} - - '@babel/helper-string-parser@7.25.9': {} - - '@babel/helper-validator-identifier@7.25.9': {} - - '@babel/helper-validator-option@7.25.9': {} - - '@babel/helpers@7.26.0': - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - - '@babel/parser@7.26.3': - dependencies: - '@babel/types': 7.26.3 - - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/template@7.25.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 - - '@babel/traverse@7.26.4': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/parser': 7.26.3 - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.26.3': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - - '@esbuild/android-arm64@0.19.7': - optional: true - - '@esbuild/android-arm@0.19.7': - optional: true - - '@esbuild/android-x64@0.19.7': - optional: true - - '@esbuild/darwin-arm64@0.19.7': - optional: true - - '@esbuild/darwin-x64@0.19.7': - optional: true - - '@esbuild/freebsd-arm64@0.19.7': - optional: true - - '@esbuild/freebsd-x64@0.19.7': - optional: true - - '@esbuild/linux-arm64@0.19.7': - optional: true - - '@esbuild/linux-arm@0.19.7': - optional: true - - '@esbuild/linux-ia32@0.19.7': - optional: true - - '@esbuild/linux-loong64@0.19.7': - optional: true - - '@esbuild/linux-mips64el@0.19.7': - optional: true - - '@esbuild/linux-ppc64@0.19.7': - optional: true - - '@esbuild/linux-riscv64@0.19.7': - optional: true - - '@esbuild/linux-s390x@0.19.7': - optional: true - - '@esbuild/linux-x64@0.19.7': - optional: true - - '@esbuild/netbsd-x64@0.19.7': - optional: true - - '@esbuild/openbsd-x64@0.19.7': - optional: true - - '@esbuild/sunos-x64@0.19.7': - optional: true - - '@esbuild/win32-arm64@0.19.7': - optional: true - - '@esbuild/win32-ia32@0.19.7': - optional: true - - '@esbuild/win32-x64@0.19.7': - optional: true - - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.10.0': {} - - '@eslint/eslintrc@2.1.4': - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@8.57.0': {} - - '@humanwhocodes/config-array@0.11.14': - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/object-schema@2.0.2': {} - - '@jridgewell/gen-mapping@0.3.8': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - - '@rollup/rollup-android-arm-eabi@4.5.2': - optional: true - - '@rollup/rollup-android-arm64@4.5.2': - optional: true - - '@rollup/rollup-darwin-arm64@4.5.2': - optional: true - - '@rollup/rollup-darwin-x64@4.5.2': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.5.2': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.5.2': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.5.2': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.5.2': - optional: true - - '@rollup/rollup-linux-x64-musl@4.5.2': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.5.2': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.5.2': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.5.2': - optional: true - - '@types/json-schema@7.0.15': {} - - '@types/react-dom@19.0.2(@types/react@19.0.1)': - dependencies: - '@types/react': 19.0.1 - - '@types/react@19.0.1': - dependencies: - csstype: 3.1.3 - - '@types/semver@7.5.6': {} - - '@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4)': - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/type-utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.5.4)': - dependencies: - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - optionalDependencies: - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@7.1.0': - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - - '@typescript-eslint/type-utils@7.1.0(eslint@8.57.0)(typescript@5.5.4)': - dependencies: - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.0.3(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@7.1.0': {} - - '@typescript-eslint/typescript-estree@7.1.0(typescript@5.5.4)': - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@7.1.0(eslint@8.57.0)(typescript@5.5.4)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/visitor-keys@7.1.0': - dependencies: - '@typescript-eslint/types': 7.1.0 - eslint-visitor-keys: 3.4.3 - - '@ungap/structured-clone@1.2.0': {} - - '@vitejs/plugin-react@3.1.0(vite@5.1.4)': - dependencies: - '@babel/core': 7.26.0 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) - magic-string: 0.27.0 - react-refresh: 0.14.2 - vite: 5.1.4 - transitivePeerDependencies: - - supports-color - - acorn-jsx@5.3.2(acorn@8.11.3): - dependencies: - acorn: 8.11.3 - - acorn@8.11.3: {} - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - argparse@2.0.1: {} - - array-union@2.1.0: {} - - balanced-match@1.0.2: {} - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.2: - dependencies: - fill-range: 7.0.1 - - browserslist@4.24.3: - dependencies: - caniuse-lite: 1.0.30001688 - electron-to-chromium: 1.5.73 - node-releases: 2.0.19 - update-browserslist-db: 1.1.1(browserslist@4.24.3) - - callsites@3.1.0: {} - - caniuse-lite@1.0.30001688: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - concat-map@0.0.1: {} - - convert-source-map@2.0.0: {} - - cross-spawn@7.0.3: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - csstype@3.1.3: {} - - debug@4.3.4: - dependencies: - ms: 2.1.2 - - deep-is@0.1.4: {} - - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - - electron-to-chromium@1.5.73: {} - - esbuild@0.19.7: - optionalDependencies: - '@esbuild/android-arm': 0.19.7 - '@esbuild/android-arm64': 0.19.7 - '@esbuild/android-x64': 0.19.7 - '@esbuild/darwin-arm64': 0.19.7 - '@esbuild/darwin-x64': 0.19.7 - '@esbuild/freebsd-arm64': 0.19.7 - '@esbuild/freebsd-x64': 0.19.7 - '@esbuild/linux-arm': 0.19.7 - '@esbuild/linux-arm64': 0.19.7 - '@esbuild/linux-ia32': 0.19.7 - '@esbuild/linux-loong64': 0.19.7 - '@esbuild/linux-mips64el': 0.19.7 - '@esbuild/linux-ppc64': 0.19.7 - '@esbuild/linux-riscv64': 0.19.7 - '@esbuild/linux-s390x': 0.19.7 - '@esbuild/linux-x64': 0.19.7 - '@esbuild/netbsd-x64': 0.19.7 - '@esbuild/openbsd-x64': 0.19.7 - '@esbuild/sunos-x64': 0.19.7 - '@esbuild/win32-arm64': 0.19.7 - '@esbuild/win32-ia32': 0.19.7 - '@esbuild/win32-x64': 0.19.7 - - escalade@3.2.0: {} - - escape-string-regexp@4.0.0: {} - - eslint-config-prettier@9.1.0(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - - eslint-scope@7.2.2: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint@8.57.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - espree@9.6.1: - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - - esquery@1.5.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.2: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.17.1: - dependencies: - reusify: 1.0.4 - - file-entry-cache@6.0.1: - dependencies: - flat-cache: 3.2.0 - - fill-range@7.0.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@3.2.0: - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - - flatted@3.3.1: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - gensync@1.0.0-beta.2: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - globals@11.12.0: {} - - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - - globby@11.1.0: - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - - graphemer@1.4.0: {} - - has-flag@4.0.0: {} - - ignore@5.3.1: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-extglob@2.1.1: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-path-inside@3.0.3: {} - - isexe@2.0.0: {} - - js-tokens@4.0.0: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - jsesc@3.1.0: {} - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@2.2.3: {} - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.merge@4.6.2: {} - - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - - magic-string@0.27.0: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - merge2@1.4.1: {} - - micromatch@4.0.5: - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@9.0.3: - dependencies: - brace-expansion: 2.0.1 - - ms@2.1.2: {} - - nanoid@3.3.7: {} - - natural-compare@1.4.0: {} - - node-releases@2.0.19: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - optionator@0.9.3: - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-type@4.0.0: {} - - picocolors@1.0.0: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - postcss@8.4.35: - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - - prelude-ls@1.2.1: {} - - prettier@3.2.5: {} - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - react-dom@18.3.1(react@18.3.1): - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - - react-refresh@0.14.2: {} - - react@18.3.1: - dependencies: - loose-envify: 1.4.0 - - resolve-from@4.0.0: {} - - reusify@1.0.4: {} - - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - - rollup@4.5.2: - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.5.2 - '@rollup/rollup-android-arm64': 4.5.2 - '@rollup/rollup-darwin-arm64': 4.5.2 - '@rollup/rollup-darwin-x64': 4.5.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.5.2 - '@rollup/rollup-linux-arm64-gnu': 4.5.2 - '@rollup/rollup-linux-arm64-musl': 4.5.2 - '@rollup/rollup-linux-x64-gnu': 4.5.2 - '@rollup/rollup-linux-x64-musl': 4.5.2 - '@rollup/rollup-win32-arm64-msvc': 4.5.2 - '@rollup/rollup-win32-ia32-msvc': 4.5.2 - '@rollup/rollup-win32-x64-msvc': 4.5.2 - fsevents: 2.3.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - scheduler@0.23.2: - dependencies: - loose-envify: 1.4.0 - - semver@6.3.1: {} - - semver@7.5.4: - dependencies: - lru-cache: 6.0.0 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - slash@3.0.0: {} - - source-map-js@1.0.2: {} - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-json-comments@3.1.1: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - text-table@0.2.0: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - ts-api-utils@1.0.3(typescript@5.5.4): - dependencies: - typescript: 5.5.4 - - turbo-darwin-64@2.3.3: - optional: true - - turbo-darwin-arm64@2.3.3: - optional: true - - turbo-linux-64@2.3.3: - optional: true - - turbo-linux-arm64@2.3.3: - optional: true - - turbo-windows-64@2.3.3: - optional: true - - turbo-windows-arm64@2.3.3: - optional: true - - turbo@2.3.3: - optionalDependencies: - turbo-darwin-64: 2.3.3 - turbo-darwin-arm64: 2.3.3 - turbo-linux-64: 2.3.3 - turbo-linux-arm64: 2.3.3 - turbo-windows-64: 2.3.3 - turbo-windows-arm64: 2.3.3 - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-fest@0.20.2: {} - - typescript@5.5.4: {} - - update-browserslist-db@1.1.1(browserslist@4.24.3): - dependencies: - browserslist: 4.24.3 - escalade: 3.2.0 - picocolors: 1.1.1 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - vite@5.1.4: - dependencies: - esbuild: 0.19.7 - postcss: 8.4.35 - rollup: 4.5.2 - optionalDependencies: - fsevents: 2.3.3 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - wrappy@1.0.2: {} - - yallist@3.1.1: {} - - yallist@4.0.0: {} - - yocto-queue@0.1.0: {} diff --git a/examples/with-vite/.eslintrc.js b/examples/with-vite/.eslintrc.js deleted file mode 100644 index 02f791d5efbc1..0000000000000 --- a/examples/with-vite/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/index.js"], -}; diff --git a/examples/with-vite/README.md b/examples/with-vite/README.md deleted file mode 100644 index df10b9b43fc56..0000000000000 --- a/examples/with-vite/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# `Turborepo` Vite starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-vite -``` - -## What's inside? - -This Turborepo includes the following packages and apps: - -### Apps and Packages - -- `docs`: a vanilla [vite](https://vitejs.dev) ts app -- `web`: another vanilla [vite](https://vitejs.dev) ts app -- `@repo/ui`: a stub component & utility library shared by both `web` and `docs` applications -- `@repo/eslint-config`: shared `eslint` configurations -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package and app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting diff --git a/examples/with-vite/apps/docs/.eslintrc.cjs b/examples/with-vite/apps/docs/.eslintrc.cjs deleted file mode 100644 index 02f791d5efbc1..0000000000000 --- a/examples/with-vite/apps/docs/.eslintrc.cjs +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/index.js"], -}; diff --git a/examples/with-vite/apps/docs/src/main.ts b/examples/with-vite/apps/docs/Source/main.ts similarity index 100% rename from examples/with-vite/apps/docs/src/main.ts rename to examples/with-vite/apps/docs/Source/main.ts diff --git a/examples/with-vite/apps/docs/src/style.css b/examples/with-vite/apps/docs/Source/style.css similarity index 100% rename from examples/with-vite/apps/docs/src/style.css rename to examples/with-vite/apps/docs/Source/style.css diff --git a/examples/with-vite/apps/docs/src/vite-env.d.ts b/examples/with-vite/apps/docs/Source/vite-env.d.ts similarity index 100% rename from examples/with-vite/apps/docs/src/vite-env.d.ts rename to examples/with-vite/apps/docs/Source/vite-env.d.ts diff --git a/examples/with-vite/apps/docs/package.json b/examples/with-vite/apps/docs/package.json index c5739f8b7aef1..548c4c0bf439f 100644 --- a/examples/with-vite/apps/docs/package.json +++ b/examples/with-vite/apps/docs/package.json @@ -1,22 +1,15 @@ { - "name": "docs", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite --clearScreen false", - "build": "tsc && vite build", - "preview": "vite preview", - "lint": "eslint \"src/**/*.ts\"" - }, - "dependencies": { - "@repo/ui": "workspace:*" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "eslint": "^8.57.0", - "typescript": "5.5.4", - "vite": "^5.1.4" - } + "name": "docs", + "scripts": { + "build": "tsc && vite build", + "dev": "vite --clearScreen false", + "preview": "vite preview" + }, + "dependencies": { + "@repo/ui": "workspace:*" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*" + } } diff --git a/examples/with-vite/apps/web/.eslintrc.cjs b/examples/with-vite/apps/web/.eslintrc.cjs deleted file mode 100644 index 02f791d5efbc1..0000000000000 --- a/examples/with-vite/apps/web/.eslintrc.cjs +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/index.js"], -}; diff --git a/examples/with-vite/apps/web/src/main.ts b/examples/with-vite/apps/web/Source/main.ts similarity index 100% rename from examples/with-vite/apps/web/src/main.ts rename to examples/with-vite/apps/web/Source/main.ts diff --git a/examples/with-vite/apps/web/src/style.css b/examples/with-vite/apps/web/Source/style.css similarity index 100% rename from examples/with-vite/apps/web/src/style.css rename to examples/with-vite/apps/web/Source/style.css diff --git a/examples/with-vite/apps/web/src/vite-env.d.ts b/examples/with-vite/apps/web/Source/vite-env.d.ts similarity index 100% rename from examples/with-vite/apps/web/src/vite-env.d.ts rename to examples/with-vite/apps/web/Source/vite-env.d.ts diff --git a/examples/with-vite/apps/web/package.json b/examples/with-vite/apps/web/package.json index 875e12fcede83..757396b8fdaa5 100644 --- a/examples/with-vite/apps/web/package.json +++ b/examples/with-vite/apps/web/package.json @@ -1,22 +1,15 @@ { - "name": "web", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite --clearScreen false", - "build": "tsc && vite build", - "preview": "vite preview", - "lint": "eslint \"src/**/*.ts\"" - }, - "dependencies": { - "@repo/ui": "workspace:*" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "eslint": "^8.57.0", - "typescript": "5.5.4", - "vite": "^5.1.4" - } + "name": "web", + "scripts": { + "build": "tsc && vite build", + "dev": "vite --clearScreen false", + "preview": "vite preview" + }, + "dependencies": { + "@repo/ui": "workspace:*" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*" + } } diff --git a/examples/with-vite/package.json b/examples/with-vite/package.json index f9172458caf0c..3749ff9c7db14 100644 --- a/examples/with-vite/package.json +++ b/examples/with-vite/package.json @@ -1,16 +1,11 @@ { - "private": true, - "scripts": { - "build": "turbo build", - "dev": "turbo dev", - "lint": "turbo lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "eslint": "^8.57.0", - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "pnpm@8.15.6", - "name": "with-vite" + "name": "with-vite", + "scripts": { + "build": "turbo build", + "dev": "turbo dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-vite/packages/config-eslint/index.js b/examples/with-vite/packages/config-eslint/index.js new file mode 100644 index 0000000000000..9417d1c205c71 --- /dev/null +++ b/examples/with-vite/packages/config-eslint/index.js @@ -0,0 +1,19 @@ +module.exports = { + env: { + node: true, + }, + parser: "@typescript-eslint/parser", + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + ], + plugins: ["@typescript-eslint"], + parserOptions: { + sourceType: "module", + ecmaVersion: 2020, + }, + rules: { + "@typescript-eslint/no-non-null-assertion": "off", + }, +}; diff --git a/examples/with-vite/packages/config-eslint/package.json b/examples/with-vite/packages/config-eslint/package.json new file mode 100644 index 0000000000000..d6e588b23ab4c --- /dev/null +++ b/examples/with-vite/packages/config-eslint/package.json @@ -0,0 +1,6 @@ +{ + "name": "@repo/eslint-config", + "main": "index.js", + "dependencies": {}, + "devDependencies": {} +} diff --git a/examples/with-vite/packages/config-typescript/base.json b/examples/with-vite/packages/config-typescript/base.json new file mode 100644 index 0000000000000..52097698f3afa --- /dev/null +++ b/examples/with-vite/packages/config-typescript/base.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Default", + "compilerOptions": { + "composite": false, + "declaration": true, + "declarationMap": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "inlineSources": false, + "isolatedModules": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "noUnusedLocals": false, + "noUnusedParameters": false, + "preserveWatchOutput": true, + "skipLibCheck": true, + "strict": true + }, + "exclude": ["node_modules"] +} diff --git a/examples/with-vite/packages/config-typescript/package.json b/examples/with-vite/packages/config-typescript/package.json new file mode 100644 index 0000000000000..0b30de456c71c --- /dev/null +++ b/examples/with-vite/packages/config-typescript/package.json @@ -0,0 +1,5 @@ +{ + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} +} diff --git a/examples/with-vite/packages/config-typescript/vite.json b/examples/with-vite/packages/config-typescript/vite.json new file mode 100644 index 0000000000000..3c507eddb6b65 --- /dev/null +++ b/examples/with-vite/packages/config-typescript/vite.json @@ -0,0 +1,16 @@ +{ + "extends": "./base.json", + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "sourceMap": true, + "resolveJsonModule": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true + }, + "exclude": ["node_modules"] +} diff --git a/examples/with-vite/packages/eslint-config/package.json b/examples/with-vite/packages/eslint-config/package.json index fc2acf1aadbab..d6e588b23ab4c 100644 --- a/examples/with-vite/packages/eslint-config/package.json +++ b/examples/with-vite/packages/eslint-config/package.json @@ -1,14 +1,6 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "main": "index.js", - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "eslint-config-prettier": "^9.1.0" - }, - "publishConfig": { - "access": "public" - } + "name": "@repo/eslint-config", + "main": "index.js", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-vite/packages/typescript-config/package.json b/examples/with-vite/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-vite/packages/typescript-config/package.json +++ b/examples/with-vite/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-vite/packages/ui/.eslintrc.cjs b/examples/with-vite/packages/ui/.eslintrc.cjs deleted file mode 100644 index 1ba520f7bf3f3..0000000000000 --- a/examples/with-vite/packages/ui/.eslintrc.cjs +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@repo/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-vite/packages/ui/package.json b/examples/with-vite/packages/ui/package.json index 710075b579fb5..a5ea856d7e416 100644 --- a/examples/with-vite/packages/ui/package.json +++ b/examples/with-vite/packages/ui/package.json @@ -1,19 +1,14 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "exports": { - "./counter": "./components/counter.ts", - "./header": "./components/header.ts", - "./setup-counter": "./utils/counter.ts" - }, - "license": "MIT", - "scripts": { - "lint": "eslint \"**/*.ts\"" - }, - "devDependencies": { - "@repo/eslint-config": "workspace:*", - "@repo/typescript-config": "workspace:*", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "@repo/ui", + "exports": { + "./counter": "./components/counter.ts", + "./header": "./components/header.ts", + "./setup-counter": "./utils/counter.ts" + }, + "scripts": {}, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*" + } } diff --git a/examples/with-vite/pnpm-lock.yaml b/examples/with-vite/pnpm-lock.yaml deleted file mode 100644 index 6dfd64d963b75..0000000000000 --- a/examples/with-vite/pnpm-lock.yaml +++ /dev/null @@ -1,1411 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - eslint: - specifier: ^8.57.0 - version: 8.57.0 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/docs: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - vite: - specifier: ^5.1.4 - version: 5.1.4 - - apps/web: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - vite: - specifier: ^5.1.4 - version: 5.1.4 - - packages/eslint-config: - dependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.1.0(eslint@8.57.0)(typescript@5.5.4) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - - packages/typescript-config: {} - - packages/ui: - devDependencies: - '@repo/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@repo/typescript-config': - specifier: workspace:* - version: link:../typescript-config - eslint: - specifier: ^8.57.0 - version: 8.57.0 - typescript: - specifier: 5.5.4 - version: 5.5.4 - -packages: - - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - - /@esbuild/android-arm64@0.19.7: - resolution: {integrity: sha512-YEDcw5IT7hW3sFKZBkCAQaOCJQLONVcD4bOyTXMZz5fr66pTHnAet46XAtbXAkJRfIn2YVhdC6R9g4xa27jQ1w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.19.7: - resolution: {integrity: sha512-YGSPnndkcLo4PmVl2tKatEn+0mlVMr3yEpOOT0BeMria87PhvoJb5dg5f5Ft9fbCVgtAz4pWMzZVgSEGpDAlww==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.19.7: - resolution: {integrity: sha512-jhINx8DEjz68cChFvM72YzrqfwJuFbfvSxZAk4bebpngGfNNRm+zRl4rtT9oAX6N9b6gBcFaJHFew5Blf6CvUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.19.7: - resolution: {integrity: sha512-dr81gbmWN//3ZnBIm6YNCl4p3pjnabg1/ZVOgz2fJoUO1a3mq9WQ/1iuEluMs7mCL+Zwv7AY5e3g1hjXqQZ9Iw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.19.7: - resolution: {integrity: sha512-Lc0q5HouGlzQEwLkgEKnWcSazqr9l9OdV2HhVasWJzLKeOt0PLhHaUHuzb8s/UIya38DJDoUm74GToZ6Wc7NGQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.19.7: - resolution: {integrity: sha512-+y2YsUr0CxDFF7GWiegWjGtTUF6gac2zFasfFkRJPkMAuMy9O7+2EH550VlqVdpEEchWMynkdhC9ZjtnMiHImQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.19.7: - resolution: {integrity: sha512-CdXOxIbIzPJmJhrpmJTLx+o35NoiKBIgOvmvT+jeSadYiWJn0vFKsl+0bSG/5lwjNHoIDEyMYc/GAPR9jxusTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.19.7: - resolution: {integrity: sha512-inHqdOVCkUhHNvuQPT1oCB7cWz9qQ/Cz46xmVe0b7UXcuIJU3166aqSunsqkgSGMtUCWOZw3+KMwI6otINuC9g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.19.7: - resolution: {integrity: sha512-Y+SCmWxsJOdQtjcBxoacn/pGW9HDZpwsoof0ttL+2vGcHokFlfqV666JpfLCSP2xLxFpF1lj7T3Ox3sr95YXww==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.19.7: - resolution: {integrity: sha512-2BbiL7nLS5ZO96bxTQkdO0euGZIUQEUXMTrqLxKUmk/Y5pmrWU84f+CMJpM8+EHaBPfFSPnomEaQiG/+Gmh61g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.19.7: - resolution: {integrity: sha512-BVFQla72KXv3yyTFCQXF7MORvpTo4uTA8FVFgmwVrqbB/4DsBFWilUm1i2Oq6zN36DOZKSVUTb16jbjedhfSHw==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.19.7: - resolution: {integrity: sha512-DzAYckIaK+pS31Q/rGpvUKu7M+5/t+jI+cdleDgUwbU7KdG2eC3SUbZHlo6Q4P1CfVKZ1lUERRFP8+q0ob9i2w==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.19.7: - resolution: {integrity: sha512-JQ1p0SmUteNdUaaiRtyS59GkkfTW0Edo+e0O2sihnY4FoZLz5glpWUQEKMSzMhA430ctkylkS7+vn8ziuhUugQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.19.7: - resolution: {integrity: sha512-xGwVJ7eGhkprY/nB7L7MXysHduqjpzUl40+XoYDGC4UPLbnG+gsyS1wQPJ9lFPcxYAaDXbdRXd1ACs9AE9lxuw==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.19.7: - resolution: {integrity: sha512-U8Rhki5PVU0L0nvk+E8FjkV8r4Lh4hVEb9duR6Zl21eIEYEwXz8RScj4LZWA2i3V70V4UHVgiqMpszXvG0Yqhg==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.19.7: - resolution: {integrity: sha512-ZYZopyLhm4mcoZXjFt25itRlocKlcazDVkB4AhioiL9hOWhDldU9n38g62fhOI4Pth6vp+Mrd5rFKxD0/S+7aQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.19.7: - resolution: {integrity: sha512-/yfjlsYmT1O3cum3J6cmGG16Fd5tqKMcg5D+sBYLaOQExheAJhqr8xOAEIuLo8JYkevmjM5zFD9rVs3VBcsjtQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.19.7: - resolution: {integrity: sha512-MYDFyV0EW1cTP46IgUJ38OnEY5TaXxjoDmwiTXPjezahQgZd+j3T55Ht8/Q9YXBM0+T9HJygrSRGV5QNF/YVDQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.19.7: - resolution: {integrity: sha512-JcPvgzf2NN/y6X3UUSqP6jSS06V0DZAV/8q0PjsZyGSXsIGcG110XsdmuWiHM+pno7/mJF6fjH5/vhUz/vA9fw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.19.7: - resolution: {integrity: sha512-ZA0KSYti5w5toax5FpmfcAgu3ZNJxYSRm0AW/Dao5up0YV1hDVof1NvwLomjEN+3/GMtaWDI+CIyJOMTRSTdMw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.19.7: - resolution: {integrity: sha512-CTOnijBKc5Jpk6/W9hQMMvJnsSYRYgveN6O75DTACCY18RA2nqka8dTZR+x/JqXCRiKk84+5+bRKXUSbbwsS0A==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.19.7: - resolution: {integrity: sha512-gRaP2sk6hc98N734luX4VpF318l3w+ofrtTu9j5L8EQXF+FzQKV6alCOHMVoJJHvVK/mGbwBXfOL1HETQu9IGQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - /@humanwhocodes/object-schema@2.0.2: - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - - /@rollup/rollup-android-arm-eabi@4.5.2: - resolution: {integrity: sha512-ee7BudTwwrglFYSc3UnqInDDjCLWHKrFmGNi4aK7jlEyg4CyPa1DCMrZfsN1O13YT76UFEqXz2CoN7BCGpUlJw==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.5.2: - resolution: {integrity: sha512-xOuhj9HHtn8128ir8veoQsBbAUBasDbHIBniYTEx02pAmu9EXL+ZjJqngnNEy6ZgZ4h1JwL33GMNu3yJL5Mzow==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.5.2: - resolution: {integrity: sha512-NTGJWoL8bKyqyWFn9/RzSv4hQ4wTbaAv0lHHRwf4OnpiiP4P8W0jiXbm8Nc5BCXKmWAwuvJY82mcIU2TayC20g==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.5.2: - resolution: {integrity: sha512-hlKqj7bpPvU15sZo4za14u185lpMzdwWLMc9raMqPK4wywt0wR23y1CaVQ4oAFXat3b5/gmRntyfpwWTKl+vvA==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.5.2: - resolution: {integrity: sha512-7ZIZx8c3u+pfI0ohQsft/GywrXez0uR6dUP0JhBuCK3sFO5TfdLn/YApnVkvPxuTv3+YKPIZend9Mt7Cz6sS3Q==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.5.2: - resolution: {integrity: sha512-7Pk/5mO11JW/cH+a8lL/i0ZxmRGrbpYqN0VwO2DHhU+SJWWOH2zE1RAcPaj8KqiwC8DCDIJOSxjV9+9lLb6aeA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.5.2: - resolution: {integrity: sha512-KrRnuG5phJx756e62wxvWH2e+TK84MP2IVuPwfge+GBvWqIUfVzFRn09TKruuQBXzZp52Vyma7FjMDkwlA9xpg==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.5.2: - resolution: {integrity: sha512-My+53GasPa2D2tU5dXiyHYwrELAUouSfkNlZ3bUKpI7btaztO5vpALEs3mvFjM7aKTvEbc7GQckuXeXIDKQ0fg==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.5.2: - resolution: {integrity: sha512-/f0Q6Sc+Vw54Ws6N8fxaEe4R7at3b8pFyv+O/F2VaQ4hODUJcRUcCBJh6zuqtgQQt7w845VTkGLFgWZkP3tUoQ==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.5.2: - resolution: {integrity: sha512-NCKuuZWLht6zj7s6EIFef4BxCRX1GMr83S2W4HPCA0RnJ4iHE4FS1695q6Ewoa6A9nFjJe1//yUu0kgBU07Edw==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.5.2: - resolution: {integrity: sha512-J5zL3riR4AOyU/J3M/i4k/zZ8eP1yT+nTmAKztCXJtnI36jYH0eepvob22mAQ/kLwfsK2TB6dbyVY1F8c/0H5A==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.5.2: - resolution: {integrity: sha512-pL0RXRHuuGLhvs7ayX/SAHph1hrDPXOM5anyYUQXWJEENxw3nfHkzv8FfVlEVcLyKPAEgDRkd6RKZq2SMqS/yg==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: false - - /@types/semver@7.5.6: - resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} - dev: false - - /@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/type-utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: false - - /@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: false - - /@typescript-eslint/scope-manager@7.1.0: - resolution: {integrity: sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - dev: false - - /@typescript-eslint/type-utils@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: false - - /@typescript-eslint/types@7.1.0: - resolution: {integrity: sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: false - - /@typescript-eslint/typescript-estree@7.1.0(typescript@5.5.4): - resolution: {integrity: sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: false - - /@typescript-eslint/utils@7.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/types': 7.1.0 - '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: false - - /@typescript-eslint/visitor-keys@7.1.0: - resolution: {integrity: sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 7.1.0 - eslint-visitor-keys: 3.4.3 - dev: false - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: false - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: false - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: false - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: false - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - - /esbuild@0.19.7: - resolution: {integrity: sha512-6brbTZVqxhqgbpqBR5MzErImcpA0SQdoKOkcWK/U30HtQxnokIpG3TX2r0IJqbFUzqLjhU/zC1S5ndgakObVCQ==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.19.7 - '@esbuild/android-arm64': 0.19.7 - '@esbuild/android-x64': 0.19.7 - '@esbuild/darwin-arm64': 0.19.7 - '@esbuild/darwin-x64': 0.19.7 - '@esbuild/freebsd-arm64': 0.19.7 - '@esbuild/freebsd-x64': 0.19.7 - '@esbuild/linux-arm': 0.19.7 - '@esbuild/linux-arm64': 0.19.7 - '@esbuild/linux-ia32': 0.19.7 - '@esbuild/linux-loong64': 0.19.7 - '@esbuild/linux-mips64el': 0.19.7 - '@esbuild/linux-ppc64': 0.19.7 - '@esbuild/linux-riscv64': 0.19.7 - '@esbuild/linux-s390x': 0.19.7 - '@esbuild/linux-x64': 0.19.7 - '@esbuild/netbsd-x64': 0.19.7 - '@esbuild/openbsd-x64': 0.19.7 - '@esbuild/sunos-x64': 0.19.7 - '@esbuild/win32-arm64': 0.19.7 - '@esbuild/win32-ia32': 0.19.7 - '@esbuild/win32-x64': 0.19.7 - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: false - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: false - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: false - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: false - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: false - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: false - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: false - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: false - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: false - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: false - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: false - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: false - - /postcss@8.4.35: - resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: true - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - - /rollup@4.5.2: - resolution: {integrity: sha512-CRK1uoROBfkcqrZKyaFcqCcZWNsvJ6yVYZkqTlRocZhO2s5yER6Z3f/QaYtO8RGyloPnmhwgzuPQpNGeK210xQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.5.2 - '@rollup/rollup-android-arm64': 4.5.2 - '@rollup/rollup-darwin-arm64': 4.5.2 - '@rollup/rollup-darwin-x64': 4.5.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.5.2 - '@rollup/rollup-linux-arm64-gnu': 4.5.2 - '@rollup/rollup-linux-arm64-musl': 4.5.2 - '@rollup/rollup-linux-x64-gnu': 4.5.2 - '@rollup/rollup-linux-x64-musl': 4.5.2 - '@rollup/rollup-win32-arm64-msvc': 4.5.2 - '@rollup/rollup-win32-ia32-msvc': 4.5.2 - '@rollup/rollup-win32-x64-msvc': 4.5.2 - fsevents: 2.3.3 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: false - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: false - - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: false - - /ts-api-utils@1.0.3(typescript@5.5.4): - resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} - engines: {node: '>=16.13.0'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: false - - /turbo-darwin-64@2.0.3: - resolution: {integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: {integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: {integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: {integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: {integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: {integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: {integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - - /vite@5.1.4: - resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.19.7 - postcss: 8.4.35 - rollup: 4.5.2 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: false - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} diff --git a/examples/with-vue-nuxt/README.md b/examples/with-vue-nuxt/README.md deleted file mode 100644 index 11a4349e057f2..0000000000000 --- a/examples/with-vue-nuxt/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Turborepo VueJS/NuxtJS starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-vue-nuxt -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [Nuxt](https://nuxt.com/) app -- `web`: another [Vue3](https://vuejs.org/) app -- `ui`: a stub Vue component library shared by both `web` and `docs` applications -- `eslint-config-custom`: `eslint` configurations (includes `@nuxtjs/eslint-config-typescript` and `@vue/eslint-config-typescript`) -- `tsconfig`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Build - -To build all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm build -``` - -### Develop - -To develop all apps and packages, run the following command: - -``` -cd my-turborepo -pnpm dev -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -``` -cd my-turborepo -npx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: - -``` -npx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/with-vue-nuxt/apps/docs/.eslintrc.cjs b/examples/with-vue-nuxt/apps/docs/.eslintrc.cjs deleted file mode 100644 index 631f74037677f..0000000000000 --- a/examples/with-vue-nuxt/apps/docs/.eslintrc.cjs +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["custom/nuxt"], -}; diff --git a/examples/with-vue-nuxt/apps/docs/README.md b/examples/with-vue-nuxt/apps/docs/README.md deleted file mode 100644 index e4d7d70e2bbec..0000000000000 --- a/examples/with-vue-nuxt/apps/docs/README.md +++ /dev/null @@ -1,27 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -pnpm dev -``` - -Open [http://localhost:3001](http://localhost:3001) with your browser to see the result. - -You can start editing the page by modifying `app.vue`. The page auto-updates as you edit the file. - -To create [API routes](https://nuxt.com/docs/guide/directory-structure/server), add an `api/` or a `routes` directory to the `server/` directory and create `your-file.ts` which will contain your api logic. Like `server/api/hello.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello). - -> See the guide for more details -> [directory-structure/server](https://nuxt.com/docs/guide/directory-structure/server) - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [NuxtJs Official documentation](https://nuxt.com/docs/getting-started/introduction) - learn about Nuxt to create production-grade full-stack web apps and websites features and API. - -## Deploy on Vercel - -You can easily deploy your Nuxt app by using the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme). - -Check out our [Nuxt deployment documentation](https://vercel.com/docs/frameworks/nuxt) for more details. diff --git a/examples/with-vue-nuxt/apps/docs/package.json b/examples/with-vue-nuxt/apps/docs/package.json index 3ada48ec48851..540e435a7203c 100644 --- a/examples/with-vue-nuxt/apps/docs/package.json +++ b/examples/with-vue-nuxt/apps/docs/package.json @@ -1,27 +1,18 @@ { - "name": "docs", - "version": "0.0.0", - "private": true, - "type": "module", - "scripts": { - "build": "nuxt build", - "dev": "nuxt dev --port 3001", - "generate": "nuxt generate", - "preview": "nuxt preview", - "postinstall": "nuxt prepare", - "lint": "eslint ." - }, - "dependencies": { - "ui": "workspace:*" - }, - "devDependencies": { - "@nuxt/devtools": "latest", - "@nuxtjs/eslint-config-typescript": "^12.1.0", - "eslint": "^8.57.0", - "eslint-config-custom": "workspace:*", - "nuxt": "^3.10.3", - "tsconfig": "workspace:*", - "vue": "^3.4.21", - "vue-router": "^4.3.0" - } + "name": "docs", + "scripts": { + "build": "nuxt build", + "dev": "nuxt dev --port 3001", + "generate": "nuxt generate", + "preview": "nuxt preview" + }, + "dependencies": { + "ui": "workspace:*" + }, + "devDependencies": { + "@nuxtjs/eslint-config-typescript": "12.1.0", + "eslint-config-custom": "workspace:*", + "nuxt": "3.15.4", + "tsconfig": "workspace:*" + } } diff --git a/examples/with-vue-nuxt/apps/docs/pnpm-lock.yaml b/examples/with-vue-nuxt/apps/docs/pnpm-lock.yaml deleted file mode 100644 index c0c379d580212..0000000000000 --- a/examples/with-vue-nuxt/apps/docs/pnpm-lock.yaml +++ /dev/null @@ -1,5969 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -devDependencies: - '@nuxt/devtools': - specifier: latest - version: 1.0.1(nuxt@3.8.1)(vite@4.5.0) - nuxt: - specifier: ^3.8.1 - version: 3.8.1(vite@4.5.0) - vue: - specifier: ^3.3.8 - version: 3.3.8 - vue-router: - specifier: ^4.2.5 - version: 4.2.5(vue@3.3.8) - -packages: - - /@ampproject/remapping@2.2.1: - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 - dev: true - - /@antfu/utils@0.7.6: - resolution: {integrity: sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==} - dev: true - - /@babel/code-frame@7.22.13: - resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.20 - chalk: 2.4.2 - dev: true - - /@babel/compat-data@7.23.3: - resolution: {integrity: sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.23.3: - resolution: {integrity: sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.3 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.3) - '@babel/helpers': 7.23.2 - '@babel/parser': 7.23.3 - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.3 - '@babel/types': 7.23.3 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.23.3: - resolution: {integrity: sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 - jsesc: 2.5.2 - dev: true - - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-compilation-targets@7.22.15: - resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.23.3 - '@babel/helper-validator-option': 7.22.15 - browserslist: 4.22.1 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.23.3): - resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.3) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.15 - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-member-expression-to-functions@7.23.0: - resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-module-imports@7.22.15: - resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - - /@babel/helper-optimise-call-expression@7.22.5: - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-plugin-utils@7.22.5: - resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.3): - resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - dev: true - - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-skip-transparent-expression-wrappers@7.22.5: - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/helper-string-parser@7.22.5: - resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.22.15: - resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.23.2: - resolution: {integrity: sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.3 - '@babel/types': 7.23.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.22.20: - resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser@7.23.3: - resolution: {integrity: sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.23.3 - dev: true - - /@babel/plugin-proposal-decorators@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-u8SwzOcP0DYSsa++nHd/9exlHb0NAlHCb890qtZZbSwPX2bFv8LBEztxwN7Xg/dS8oAFFidhrI9PBcLBJSkGRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.3) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.3) - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/plugin-syntax-decorators': 7.23.3(@babel/core@7.23.3) - dev: true - - /@babel/plugin-syntax-decorators@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-cf7Niq4/+/juY67E0PbgH0TDhLQ5J7zS8C/Q5FFx+DWyrRa9sUQdTXkjqKu8zGvuqr7vw1muKiukseihU+PJDA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.3): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-transform-typescript@7.23.3(@babel/core@7.23.3): - resolution: {integrity: sha512-ogV0yWnq38CFwH20l2Afz0dfKuZBx9o/Y2Rmh5vuSS0YD1hswgEgTfyTzuSrT2q9btmHRSqYoSfwFUVaC1M1Jw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.3) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.3) - dev: true - - /@babel/standalone@7.23.3: - resolution: {integrity: sha512-ZfB6wyLVqr9ANl1F0l/0aqoNUE1/kcWlQHmk0wF9OTEKDK1whkXYLruRMt53zY556yS2+84EsOpr1hpjZISTRg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/template@7.22.15: - resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/parser': 7.23.3 - '@babel/types': 7.23.3 - dev: true - - /@babel/traverse@7.23.3: - resolution: {integrity: sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.3 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.3 - '@babel/types': 7.23.3 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.23.3: - resolution: {integrity: sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - dev: true - - /@cloudflare/kv-asset-handler@0.3.0: - resolution: {integrity: sha512-9CB/MKf/wdvbfkUdfrj+OkEwZ5b7rws0eogJ4293h+7b6KX5toPwym+VQKmILafNB9YiehqY0DlNrDcDhdWHSQ==} - dependencies: - mime: 3.0.0 - dev: true - - /@esbuild/android-arm64@0.18.20: - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.19.5: - resolution: {integrity: sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.18.20: - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.19.5: - resolution: {integrity: sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.18.20: - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.19.5: - resolution: {integrity: sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.18.20: - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.19.5: - resolution: {integrity: sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.18.20: - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.19.5: - resolution: {integrity: sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.18.20: - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.19.5: - resolution: {integrity: sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.18.20: - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.19.5: - resolution: {integrity: sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.18.20: - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.19.5: - resolution: {integrity: sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.18.20: - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.19.5: - resolution: {integrity: sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.18.20: - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.19.5: - resolution: {integrity: sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.18.20: - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.19.5: - resolution: {integrity: sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.18.20: - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.19.5: - resolution: {integrity: sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.18.20: - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.19.5: - resolution: {integrity: sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.18.20: - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.19.5: - resolution: {integrity: sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.18.20: - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.19.5: - resolution: {integrity: sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.18.20: - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.19.5: - resolution: {integrity: sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.18.20: - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.19.5: - resolution: {integrity: sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.18.20: - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.19.5: - resolution: {integrity: sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.18.20: - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.19.5: - resolution: {integrity: sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.18.20: - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.19.5: - resolution: {integrity: sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.18.20: - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.19.5: - resolution: {integrity: sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.18.20: - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.19.5: - resolution: {integrity: sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@fastify/busboy@2.0.0: - resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} - engines: {node: '>=14'} - dev: true - - /@ioredis/commands@1.2.0: - resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@jridgewell/gen-mapping@0.3.3: - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.20 - dev: true - - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/source-map@0.3.5: - resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.20: - resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@kwsites/file-exists@1.1.1: - resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@kwsites/promise-deferred@1.1.1: - resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - dev: true - - /@mapbox/node-pre-gyp@1.0.11: - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - dependencies: - detect-libc: 2.0.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.5.4 - tar: 6.2.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@netlify/functions@2.4.0: - resolution: {integrity: sha512-dIqhdj5u4Lu/8qbYwtYpn8NfvIyPHbSTV2lAP4ocL+iwC9As06AXT0wa/xOpO2vRWJa0IMxdZaqCPnkyHlHiyg==} - engines: {node: '>=14.0.0'} - dependencies: - '@netlify/serverless-functions-api': 1.11.0 - is-promise: 4.0.0 - dev: true - - /@netlify/node-cookies@0.1.0: - resolution: {integrity: sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g==} - engines: {node: ^14.16.0 || >=16.0.0} - dev: true - - /@netlify/serverless-functions-api@1.11.0: - resolution: {integrity: sha512-3splAsr2CekL7VTwgo6yTvzD2+f269/s+TJafYazonqMNNo31yzvFxD5HpLtni4DNE1ppymVKZ4X/rLN3yl0vQ==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@netlify/node-cookies': 0.1.0 - urlpattern-polyfill: 8.0.2 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 - dev: true - - /@npmcli/agent@2.2.0: - resolution: {integrity: sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - agent-base: 7.1.0 - http-proxy-agent: 7.0.0 - https-proxy-agent: 7.0.2 - lru-cache: 10.0.2 - socks-proxy-agent: 8.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@npmcli/fs@3.1.0: - resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.5.4 - dev: true - - /@npmcli/git@5.0.3: - resolution: {integrity: sha512-UZp9NwK+AynTrKvHn5k3KviW/hA5eENmFsu3iAPe7sWRt0lFUdsY/wXIYjpDFe7cdSNwOIzbObfwgt6eL5/2zw==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/promise-spawn': 7.0.0 - lru-cache: 10.0.2 - npm-pick-manifest: 9.0.0 - proc-log: 3.0.0 - promise-inflight: 1.0.1 - promise-retry: 2.0.1 - semver: 7.5.4 - which: 4.0.0 - transitivePeerDependencies: - - bluebird - dev: true - - /@npmcli/installed-package-contents@2.0.2: - resolution: {integrity: sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - npm-bundled: 3.0.0 - npm-normalize-package-bin: 3.0.1 - dev: true - - /@npmcli/node-gyp@3.0.0: - resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /@npmcli/promise-spawn@7.0.0: - resolution: {integrity: sha512-wBqcGsMELZna0jDblGd7UXgOby45TQaMWmbFwWX+SEotk4HV6zG2t6rT9siyLhPk4P6YYqgfL1UO8nMWDBVJXQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - which: 4.0.0 - dev: true - - /@npmcli/run-script@7.0.2: - resolution: {integrity: sha512-Omu0rpA8WXvcGeY6DDzyRoY1i5DkCBkzyJ+m2u7PD6quzb0TvSqdIPOkTn8ZBOj7LbbcbMfZ3c5skwSu6m8y2w==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/node-gyp': 3.0.0 - '@npmcli/promise-spawn': 7.0.0 - node-gyp: 10.0.1 - read-package-json-fast: 3.0.2 - which: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@nuxt/devalue@2.0.2: - resolution: {integrity: sha512-GBzP8zOc7CGWyFQS6dv1lQz8VVpz5C2yRszbXufwG/9zhStTIH50EtD87NmWbTMwXDvZLNg8GIpb1UFdH93JCA==} - dev: true - - /@nuxt/devtools-kit@1.0.1(nuxt@3.8.1)(vite@4.5.0): - resolution: {integrity: sha512-tR+9mqic2O76LWkmdH0q5xPEnrOo8DmHvKyXA99be7NQfkjf47roWfa+gvQbksqwNw3SZVw2fq9Lotk4vZj4RA==} - peerDependencies: - nuxt: ^3.7.4 - vite: '*' - dependencies: - '@nuxt/kit': 3.8.1 - '@nuxt/schema': 3.8.1 - execa: 7.2.0 - nuxt: 3.8.1(vite@4.5.0) - vite: 4.5.0 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/devtools-wizard@1.0.1: - resolution: {integrity: sha512-p44qhWWKR4aEy1cRHGkHQyNJ93rfpDUPhQoqrMBmGQNBWJxLCbZCrdhOWJi9kOlu2qSBbvz/4mOHEXQ2G8APsA==} - hasBin: true - dependencies: - consola: 3.2.3 - diff: 5.1.0 - execa: 7.2.0 - global-directory: 4.0.1 - magicast: 0.3.1 - pathe: 1.1.1 - pkg-types: 1.0.3 - prompts: 2.4.2 - rc9: 2.1.1 - semver: 7.5.4 - dev: true - - /@nuxt/devtools@1.0.1(nuxt@3.8.1)(vite@4.5.0): - resolution: {integrity: sha512-VwuX4g0QmKBE3GyDqVkLIt3xOz/aTFZbD1SxyT/ani4FfOAec2ksjbF4CQmGonfjL2lN1glvoew83zj4P5vi/g==} - hasBin: true - peerDependencies: - nuxt: ^3.7.4 - vite: '*' - dependencies: - '@antfu/utils': 0.7.6 - '@nuxt/devtools-kit': 1.0.1(nuxt@3.8.1)(vite@4.5.0) - '@nuxt/devtools-wizard': 1.0.1 - '@nuxt/kit': 3.8.1 - birpc: 0.2.14 - consola: 3.2.3 - destr: 2.0.2 - error-stack-parser-es: 0.1.1 - execa: 7.2.0 - fast-glob: 3.3.2 - flatted: 3.2.9 - get-port-please: 3.1.1 - h3: 1.8.2 - hookable: 5.5.3 - image-meta: 0.2.0 - is-installed-globally: 1.0.0 - launch-editor: 2.6.1 - local-pkg: 0.5.0 - magicast: 0.3.1 - nitropack: 2.7.2 - nuxt: 3.8.1(vite@4.5.0) - nypm: 0.3.3 - ofetch: 1.3.3 - ohash: 1.1.3 - pacote: 17.0.4 - pathe: 1.1.1 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - rc9: 2.1.1 - scule: 1.0.0 - semver: 7.5.4 - simple-git: 3.20.0 - sirv: 2.0.3 - unimport: 3.5.0(rollup@3.29.4) - vite: 4.5.0 - vite-plugin-inspect: 0.7.42(@nuxt/kit@3.8.1)(vite@4.5.0) - vite-plugin-vue-inspector: 4.0.0(vite@4.5.0) - which: 3.0.1 - ws: 8.14.2 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/kv' - - bluebird - - bufferutil - - encoding - - idb-keyval - - rollup - - supports-color - - utf-8-validate - - xml2js - dev: true - - /@nuxt/kit@3.8.1: - resolution: {integrity: sha512-DrhG1Z85iH68QOTkgfb0HVfM2g7+CfcMWrFWMDwck9ofyM2RXQUZyfmvMedwBnui1AjjpgpLO9078yZM+RqNUg==} - engines: {node: ^14.18.0 || >=16.10.0} - dependencies: - '@nuxt/schema': 3.8.1 - c12: 1.5.1 - consola: 3.2.3 - defu: 6.1.3 - globby: 13.2.2 - hash-sum: 2.0.0 - ignore: 5.2.4 - jiti: 1.21.0 - knitwork: 1.0.0 - mlly: 1.4.2 - pathe: 1.1.1 - pkg-types: 1.0.3 - scule: 1.0.0 - semver: 7.5.4 - ufo: 1.3.1 - unctx: 2.3.1 - unimport: 3.5.0(rollup@3.29.4) - untyped: 1.4.0 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/schema@3.8.1: - resolution: {integrity: sha512-fSaWRcI/2mUskfTZTGSnH6Ny0x05CRzylbVn6WFV0d6UEKIVy42Qd6n+h7yoFfp4cq4nji6u16PT4SqS1DEhsw==} - engines: {node: ^14.18.0 || >=16.10.0} - dependencies: - '@nuxt/ui-templates': 1.3.1 - consola: 3.2.3 - defu: 6.1.3 - hookable: 5.5.3 - pathe: 1.1.1 - pkg-types: 1.0.3 - std-env: 3.4.3 - ufo: 1.3.1 - unimport: 3.5.0(rollup@3.29.4) - untyped: 1.4.0 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/telemetry@2.5.2: - resolution: {integrity: sha512-kZ+rWq/5MZonMhp8KGFI5zMaR2VsiWpnlkOLJIuIX2WoJl0DkHvtxCtuFq2erAqMVruWLpKU+tgMC+1cno/QmA==} - hasBin: true - dependencies: - '@nuxt/kit': 3.8.1 - ci-info: 3.9.0 - consola: 3.2.3 - create-require: 1.1.1 - defu: 6.1.3 - destr: 2.0.2 - dotenv: 16.3.1 - git-url-parse: 13.1.1 - is-docker: 3.0.0 - jiti: 1.21.0 - mri: 1.2.0 - nanoid: 4.0.2 - ofetch: 1.3.3 - parse-git-config: 3.0.0 - pathe: 1.1.1 - rc9: 2.1.1 - std-env: 3.4.3 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/ui-templates@1.3.1: - resolution: {integrity: sha512-5gc02Pu1HycOVUWJ8aYsWeeXcSTPe8iX8+KIrhyEtEoOSkY0eMBuo0ssljB8wALuEmepv31DlYe5gpiRwkjESA==} - dev: true - - /@nuxt/vite-builder@3.8.1(vue@3.3.8): - resolution: {integrity: sha512-Ot/twGONxj22T9U4bxp771ibKVFlZxIiYDHY/e6mZsE4Blc0efKo6MzPPPo0W4/tXQbtKKEq41uINN3dMI3mag==} - engines: {node: ^14.18.0 || >=16.10.0} - peerDependencies: - vue: ^3.3.4 - dependencies: - '@nuxt/kit': 3.8.1 - '@rollup/plugin-replace': 5.0.5(rollup@3.29.4) - '@vitejs/plugin-vue': 4.4.1(vite@4.5.0)(vue@3.3.8) - '@vitejs/plugin-vue-jsx': 3.0.2(vite@4.5.0)(vue@3.3.8) - autoprefixer: 10.4.16(postcss@8.4.31) - clear: 0.1.0 - consola: 3.2.3 - cssnano: 6.0.1(postcss@8.4.31) - defu: 6.1.3 - esbuild: 0.19.5 - escape-string-regexp: 5.0.0 - estree-walker: 3.0.3 - externality: 1.0.2 - fs-extra: 11.1.1 - get-port-please: 3.1.1 - h3: 1.8.2 - knitwork: 1.0.0 - magic-string: 0.30.5 - mlly: 1.4.2 - ohash: 1.1.3 - pathe: 1.1.1 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - postcss: 8.4.31 - rollup-plugin-visualizer: 5.9.2(rollup@3.29.4) - std-env: 3.4.3 - strip-literal: 1.3.0 - ufo: 1.3.1 - unplugin: 1.5.0 - vite: 4.5.0 - vite-node: 0.33.0 - vite-plugin-checker: 0.6.2(vite@4.5.0) - vue: 3.3.8 - vue-bundle-renderer: 2.0.0 - transitivePeerDependencies: - - '@types/node' - - eslint - - less - - lightningcss - - meow - - optionator - - rollup - - sass - - stylelint - - stylus - - sugarss - - supports-color - - terser - - typescript - - vls - - vti - - vue-tsc - dev: true - - /@parcel/watcher-android-arm64@2.3.0: - resolution: {integrity: sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-darwin-arm64@2.3.0: - resolution: {integrity: sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-darwin-x64@2.3.0: - resolution: {integrity: sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-freebsd-x64@2.3.0: - resolution: {integrity: sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-arm-glibc@2.3.0: - resolution: {integrity: sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ==} - engines: {node: '>= 10.0.0'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-arm64-glibc@2.3.0: - resolution: {integrity: sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-arm64-musl@2.3.0: - resolution: {integrity: sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-x64-glibc@2.3.0: - resolution: {integrity: sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-x64-musl@2.3.0: - resolution: {integrity: sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-wasm@2.3.0: - resolution: {integrity: sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA==} - engines: {node: '>= 10.0.0'} - dependencies: - is-glob: 4.0.3 - micromatch: 4.0.5 - dev: true - bundledDependencies: - - napi-wasm - - /@parcel/watcher-win32-arm64@2.3.0: - resolution: {integrity: sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-win32-ia32@2.3.0: - resolution: {integrity: sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow==} - engines: {node: '>= 10.0.0'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-win32-x64@2.3.0: - resolution: {integrity: sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher@2.3.0: - resolution: {integrity: sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ==} - engines: {node: '>= 10.0.0'} - dependencies: - detect-libc: 1.0.3 - is-glob: 4.0.3 - micromatch: 4.0.5 - node-addon-api: 7.0.0 - optionalDependencies: - '@parcel/watcher-android-arm64': 2.3.0 - '@parcel/watcher-darwin-arm64': 2.3.0 - '@parcel/watcher-darwin-x64': 2.3.0 - '@parcel/watcher-freebsd-x64': 2.3.0 - '@parcel/watcher-linux-arm-glibc': 2.3.0 - '@parcel/watcher-linux-arm64-glibc': 2.3.0 - '@parcel/watcher-linux-arm64-musl': 2.3.0 - '@parcel/watcher-linux-x64-glibc': 2.3.0 - '@parcel/watcher-linux-x64-musl': 2.3.0 - '@parcel/watcher-win32-arm64': 2.3.0 - '@parcel/watcher-win32-ia32': 2.3.0 - '@parcel/watcher-win32-x64': 2.3.0 - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@polka/url@1.0.0-next.23: - resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==} - dev: true - - /@rollup/plugin-alias@5.0.1(rollup@3.29.4): - resolution: {integrity: sha512-JObvbWdOHoMy9W7SU0lvGhDtWq9PllP5mjpAy+TUslZG/WzOId9u80Hsqq1vCUn9pFJ0cxpdcnAv+QzU2zFH3Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - rollup: 3.29.4 - slash: 4.0.0 - dev: true - - /@rollup/plugin-commonjs@25.0.7(rollup@3.29.4): - resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.30.5 - rollup: 3.29.4 - dev: true - - /@rollup/plugin-inject@5.0.5(rollup@3.29.4): - resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - estree-walker: 2.0.2 - magic-string: 0.30.5 - rollup: 3.29.4 - dev: true - - /@rollup/plugin-json@6.0.1(rollup@3.29.4): - resolution: {integrity: sha512-RgVfl5hWMkxN1h/uZj8FVESvPuBJ/uf6ly6GTj0GONnkfoBN5KC0MSz+PN2OLDgYXMhtG0mWpTrkiOjoxAIevw==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - rollup: 3.29.4 - dev: true - - /@rollup/plugin-node-resolve@15.2.3(rollup@3.29.4): - resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-builtin-module: 3.2.1 - is-module: 1.0.0 - resolve: 1.22.8 - rollup: 3.29.4 - dev: true - - /@rollup/plugin-replace@5.0.5(rollup@3.29.4): - resolution: {integrity: sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - magic-string: 0.30.5 - rollup: 3.29.4 - dev: true - - /@rollup/plugin-terser@0.4.4(rollup@3.29.4): - resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - rollup: 3.29.4 - serialize-javascript: 6.0.1 - smob: 1.4.1 - terser: 5.24.0 - dev: true - - /@rollup/plugin-wasm@6.2.2(rollup@3.29.4): - resolution: {integrity: sha512-gpC4R1G9Ni92ZIRTexqbhX7U+9estZrbhP+9SRb0DW9xpB9g7j34r+J2hqrcW/lRI7dJaU84MxZM0Rt82tqYPQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - rollup: 3.29.4 - dev: true - - /@rollup/pluginutils@4.2.1: - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - - /@rollup/pluginutils@5.0.5(rollup@3.29.4): - resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 3.29.4 - dev: true - - /@sigstore/bundle@2.1.0: - resolution: {integrity: sha512-89uOo6yh/oxaU8AeOUnVrTdVMcGk9Q1hJa7Hkvalc6G3Z3CupWk4Xe9djSgJm9fMkH69s0P0cVHUoKSOemLdng==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/protobuf-specs': 0.2.1 - dev: true - - /@sigstore/protobuf-specs@0.2.1: - resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /@sigstore/sign@2.2.0: - resolution: {integrity: sha512-AAbmnEHDQv6CSfrWA5wXslGtzLPtAtHZleKOgxdQYvx/s76Fk6T6ZVt7w2IGV9j1UrFeBocTTQxaXG2oRrDhYA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.1.0 - '@sigstore/protobuf-specs': 0.2.1 - make-fetch-happen: 13.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@sigstore/tuf@2.2.0: - resolution: {integrity: sha512-KKATZ5orWfqd9ZG6MN8PtCIx4eevWSuGRKQvofnWXRpyMyUEpmrzg5M5BrCpjM+NfZ0RbNGOh5tCz/P2uoRqOA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/protobuf-specs': 0.2.1 - tuf-js: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@trysound/sax@0.2.0: - resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} - engines: {node: '>=10.13.0'} - dev: true - - /@tufjs/canonical-json@2.0.0: - resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} - engines: {node: ^16.14.0 || >=18.0.0} - dev: true - - /@tufjs/models@2.0.0: - resolution: {integrity: sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@tufjs/canonical-json': 2.0.0 - minimatch: 9.0.3 - dev: true - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/http-proxy@1.17.14: - resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} - dependencies: - '@types/node': 20.9.0 - dev: true - - /@types/node@20.9.0: - resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/resolve@1.20.2: - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - dev: true - - /@unhead/dom@1.8.3: - resolution: {integrity: sha512-rPj9PiRTDf+Qy7tSK/UCGxwKfsOOQ+YniANxQy9v2AhWsDy2amW7kbfgR9fVaSlOFdpsyuh2wLCbMcyj9Wn0Jw==} - dependencies: - '@unhead/schema': 1.8.3 - '@unhead/shared': 1.8.3 - dev: true - - /@unhead/schema@1.8.3: - resolution: {integrity: sha512-3XbcJzdlyLr/RV2TKaygI21YorlU6XPgHn/MoWjQvH4PYiHkH8PtTGg8Je6k3gvcUURSiDfucFKaGEYdJXAVqQ==} - dependencies: - hookable: 5.5.3 - zhead: 2.2.4 - dev: true - - /@unhead/shared@1.8.3: - resolution: {integrity: sha512-E1knEiAO0iENLzZd+LjWA4mUp8JRaSxo5V0vMjSENyf5hSVB/SxAVjDPmTIelLY7KrP5mJrNMen2ZmQrr/AZJw==} - dependencies: - '@unhead/schema': 1.8.3 - dev: true - - /@unhead/ssr@1.8.3: - resolution: {integrity: sha512-GSTkUCL4qymGkPU8BXiV74Epj0yyXJgmfTSJ3EqalpQTYyJHl910Mq2oDWk7Xyl5lHBrz2Bn0lzNXfSkS7Ao0Q==} - dependencies: - '@unhead/schema': 1.8.3 - '@unhead/shared': 1.8.3 - dev: true - - /@unhead/vue@1.8.3(vue@3.3.8): - resolution: {integrity: sha512-sj/1VosMreUQXd68rn5jDLdpgFVdN0mKrjW/8eZMWbomZkzbzs7FxyRUApd584xNjFVdtyWrTepmrNSKmEwKgg==} - peerDependencies: - vue: '>=2.7 || >=3' - dependencies: - '@unhead/schema': 1.8.3 - '@unhead/shared': 1.8.3 - hookable: 5.5.3 - unhead: 1.8.3 - vue: 3.3.8 - dev: true - - /@vercel/nft@0.24.3: - resolution: {integrity: sha512-IyBdIxmFAeGZnEfMgt4QrGK7XX4lWazlQj34HEi9dw04/WeDBJ7r1yaOIO5tTf9pbfvwUFodj9b0H+NDGGoOMg==} - engines: {node: '>=16'} - hasBin: true - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - '@rollup/pluginutils': 4.2.1 - acorn: 8.11.2 - async-sema: 3.1.1 - bindings: 1.5.0 - estree-walker: 2.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - node-gyp-build: 4.6.1 - resolve-from: 5.0.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@vitejs/plugin-vue-jsx@3.0.2(vite@4.5.0)(vue@3.3.8): - resolution: {integrity: sha512-obF26P2Z4Ogy3cPp07B4VaW6rpiu0ue4OT2Y15UxT5BZZ76haUY9guOsZV3uWh/I6xc+VeiW+ZVabRE82FyzWw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.0.0 - vue: ^3.0.0 - dependencies: - '@babel/core': 7.23.3 - '@babel/plugin-transform-typescript': 7.23.3(@babel/core@7.23.3) - '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.3) - vite: 4.5.0 - vue: 3.3.8 - transitivePeerDependencies: - - supports-color - dev: true - - /@vitejs/plugin-vue@4.4.1(vite@4.5.0)(vue@3.3.8): - resolution: {integrity: sha512-HCQG8VDFDM7YDAdcj5QI5DvUi+r6xvo9LgvYdk7LSkUNwdpempdB5horkMSZsbdey9Ywsf5aaU8kEPw9M5kREA==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.0.0 - vue: ^3.2.25 - dependencies: - vite: 4.5.0 - vue: 3.3.8 - dev: true - - /@vue-macros/common@1.8.0(vue@3.3.8): - resolution: {integrity: sha512-auDJJzE0z3uRe3867e0DsqcseKImktNf5ojCZgUKqiVxb2yTlwlgOVAYCgoep9oITqxkXQymSvFeKhedi8PhaA==} - engines: {node: '>=16.14.0'} - peerDependencies: - vue: ^2.7.0 || ^3.2.25 - peerDependenciesMeta: - vue: - optional: true - dependencies: - '@babel/types': 7.23.3 - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - '@vue/compiler-sfc': 3.3.8 - ast-kit: 0.11.2 - local-pkg: 0.4.3 - magic-string-ast: 0.3.0 - vue: 3.3.8 - transitivePeerDependencies: - - rollup - dev: true - - /@vue/babel-helper-vue-transform-on@1.1.5: - resolution: {integrity: sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==} - dev: true - - /@vue/babel-plugin-jsx@1.1.5(@babel/core@7.23.3): - resolution: {integrity: sha512-nKs1/Bg9U1n3qSWnsHhCVQtAzI6aQXqua8j/bZrau8ywT1ilXQbK4FwEJGmU8fV7tcpuFvWmmN7TMmV1OBma1g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/helper-module-imports': 7.22.15 - '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.3) - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.3 - '@babel/types': 7.23.3 - '@vue/babel-helper-vue-transform-on': 1.1.5 - camelcase: 6.3.0 - html-tags: 3.3.1 - svg-tags: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@vue/compiler-core@3.3.8: - resolution: {integrity: sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g==} - dependencies: - '@babel/parser': 7.23.3 - '@vue/shared': 3.3.8 - estree-walker: 2.0.2 - source-map-js: 1.0.2 - dev: true - - /@vue/compiler-dom@3.3.8: - resolution: {integrity: sha512-+PPtv+p/nWDd0AvJu3w8HS0RIm/C6VGBIRe24b9hSyNWOAPEUosFZ5diwawwP8ip5sJ8n0Pe87TNNNHnvjs0FQ==} - dependencies: - '@vue/compiler-core': 3.3.8 - '@vue/shared': 3.3.8 - dev: true - - /@vue/compiler-sfc@3.3.8: - resolution: {integrity: sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA==} - dependencies: - '@babel/parser': 7.23.3 - '@vue/compiler-core': 3.3.8 - '@vue/compiler-dom': 3.3.8 - '@vue/compiler-ssr': 3.3.8 - '@vue/reactivity-transform': 3.3.8 - '@vue/shared': 3.3.8 - estree-walker: 2.0.2 - magic-string: 0.30.5 - postcss: 8.4.31 - source-map-js: 1.0.2 - dev: true - - /@vue/compiler-ssr@3.3.8: - resolution: {integrity: sha512-hXCqQL/15kMVDBuoBYpUnSYT8doDNwsjvm3jTefnXr+ytn294ySnT8NlsFHmTgKNjwpuFy7XVV8yTeLtNl/P6w==} - dependencies: - '@vue/compiler-dom': 3.3.8 - '@vue/shared': 3.3.8 - dev: true - - /@vue/devtools-api@6.5.1: - resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==} - dev: true - - /@vue/reactivity-transform@3.3.8: - resolution: {integrity: sha512-49CvBzmZNtcHua0XJ7GdGifM8GOXoUMOX4dD40Y5DxI3R8OUhMlvf2nvgUAcPxaXiV5MQQ1Nwy09ADpnLQUqRw==} - dependencies: - '@babel/parser': 7.23.3 - '@vue/compiler-core': 3.3.8 - '@vue/shared': 3.3.8 - estree-walker: 2.0.2 - magic-string: 0.30.5 - dev: true - - /@vue/reactivity@3.3.8: - resolution: {integrity: sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw==} - dependencies: - '@vue/shared': 3.3.8 - dev: true - - /@vue/runtime-core@3.3.8: - resolution: {integrity: sha512-qurzOlb6q26KWQ/8IShHkMDOuJkQnQcTIp1sdP4I9MbCf9FJeGVRXJFr2mF+6bXh/3Zjr9TDgURXrsCr9bfjUw==} - dependencies: - '@vue/reactivity': 3.3.8 - '@vue/shared': 3.3.8 - dev: true - - /@vue/runtime-dom@3.3.8: - resolution: {integrity: sha512-Noy5yM5UIf9UeFoowBVgghyGGPIDPy1Qlqt0yVsUdAVbqI8eeMSsTqBtauaEoT2UFXUk5S64aWVNJN4MJ2vRdA==} - dependencies: - '@vue/runtime-core': 3.3.8 - '@vue/shared': 3.3.8 - csstype: 3.1.2 - dev: true - - /@vue/server-renderer@3.3.8(vue@3.3.8): - resolution: {integrity: sha512-zVCUw7RFskvPuNlPn/8xISbrf0zTWsTSdYTsUTN1ERGGZGVnRxM2QZ3x1OR32+vwkkCm0IW6HmJ49IsPm7ilLg==} - peerDependencies: - vue: 3.3.8 - dependencies: - '@vue/compiler-ssr': 3.3.8 - '@vue/shared': 3.3.8 - vue: 3.3.8 - dev: true - - /@vue/shared@3.3.8: - resolution: {integrity: sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw==} - dev: true - - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true - - /abbrev@2.0.0: - resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /acorn@8.11.2: - resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /agent-base@7.1.0: - resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} - engines: {node: '>= 14'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: true - - /arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - dev: true - - /archiver-utils@4.0.1: - resolution: {integrity: sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==} - engines: {node: '>= 12.0.0'} - dependencies: - glob: 8.1.0 - graceful-fs: 4.2.11 - lazystream: 1.0.1 - lodash: 4.17.21 - normalize-path: 3.0.0 - readable-stream: 3.6.2 - dev: true - - /archiver@6.0.1: - resolution: {integrity: sha512-CXGy4poOLBKptiZH//VlWdFuUC1RESbdZjGjILwBuZ73P7WkAUN0htfSfBq/7k6FRFlpu7bg4JOkj1vU9G6jcQ==} - engines: {node: '>= 12.0.0'} - dependencies: - archiver-utils: 4.0.1 - async: 3.2.5 - buffer-crc32: 0.2.13 - readable-stream: 3.6.2 - readdir-glob: 1.1.3 - tar-stream: 3.1.6 - zip-stream: 5.0.1 - dev: true - - /are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /ast-kit@0.11.2: - resolution: {integrity: sha512-Q0DjXK4ApbVoIf9GLyCo252tUH44iTnD/hiJ2TQaJeydYWSpKk0sI34+WMel8S9Wt5pbLgG02oJ+gkgX5DV3sQ==} - engines: {node: '>=16.14.0'} - dependencies: - '@babel/parser': 7.23.3 - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - pathe: 1.1.1 - transitivePeerDependencies: - - rollup - dev: true - - /ast-kit@0.9.5: - resolution: {integrity: sha512-kbL7ERlqjXubdDd+szuwdlQ1xUxEz9mCz1+m07ftNVStgwRb2RWw+U6oKo08PAvOishMxiqz1mlJyLl8yQx2Qg==} - engines: {node: '>=16.14.0'} - dependencies: - '@babel/parser': 7.23.3 - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - pathe: 1.1.1 - transitivePeerDependencies: - - rollup - dev: true - - /ast-walker-scope@0.5.0: - resolution: {integrity: sha512-NsyHMxBh4dmdEHjBo1/TBZvCKxffmZxRYhmclfu0PP6Aftre47jOHYaYaNqJcV0bxihxFXhDkzLHUwHc0ocd0Q==} - engines: {node: '>=16.14.0'} - dependencies: - '@babel/parser': 7.23.3 - ast-kit: 0.9.5 - transitivePeerDependencies: - - rollup - dev: true - - /async-sema@3.1.1: - resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} - dev: true - - /async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - dev: true - - /autoprefixer@10.4.16(postcss@8.4.31): - resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.22.1 - caniuse-lite: 1.0.30001561 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /b4a@1.6.4: - resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /big-integer@1.6.51: - resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} - engines: {node: '>=0.6'} - dev: true - - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true - - /bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - dependencies: - file-uri-to-path: 1.0.0 - dev: true - - /birpc@0.2.14: - resolution: {integrity: sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==} - dev: true - - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: true - - /bplist-parser@0.2.0: - resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} - engines: {node: '>= 5.10.0'} - dependencies: - big-integer: 1.6.51 - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /browserslist@4.22.1: - resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001561 - electron-to-chromium: 1.4.581 - node-releases: 2.0.13 - update-browserslist-db: 1.0.13(browserslist@4.22.1) - dev: true - - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /builtins@5.0.1: - resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} - dependencies: - semver: 7.5.4 - dev: true - - /bundle-name@3.0.0: - resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} - engines: {node: '>=12'} - dependencies: - run-applescript: 5.0.0 - dev: true - - /c12@1.5.1: - resolution: {integrity: sha512-BWZRJgDEveT8uI+cliCwvYSSSSvb4xKoiiu5S0jaDbKBopQLQF7E+bq9xKk1pTcG+mUa3yXuFO7bD9d8Lr9Xxg==} - dependencies: - chokidar: 3.5.3 - defu: 6.1.3 - dotenv: 16.3.1 - giget: 1.1.3 - jiti: 1.21.0 - mlly: 1.4.2 - ohash: 1.1.3 - pathe: 1.1.1 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - rc9: 2.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true - - /cacache@18.0.0: - resolution: {integrity: sha512-I7mVOPl3PUCeRub1U8YoGz2Lqv9WOBpobZ8RyWFXmReuILz+3OAyTa5oH3QPdtKZD7N0Yk00aLfzn0qvp8dZ1w==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/fs': 3.1.0 - fs-minipass: 3.0.3 - glob: 10.3.10 - lru-cache: 10.0.2 - minipass: 7.0.4 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - p-map: 4.0.0 - ssri: 10.0.5 - tar: 6.2.0 - unique-filename: 3.0.0 - dev: true - - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /caniuse-api@3.0.0: - resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - dependencies: - browserslist: 4.22.1 - caniuse-lite: 1.0.30001561 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - dev: true - - /caniuse-lite@1.0.30001561: - resolution: {integrity: sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==} - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: true - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /citty@0.1.4: - resolution: {integrity: sha512-Q3bK1huLxzQrvj7hImJ7Z1vKYJRPQCDnd0EjXfHMidcjecGOMuLrmuQmtWmFkuKLcMThlGh1yCKG8IEc6VeNXQ==} - dependencies: - consola: 3.2.3 - dev: true - - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true - - /clear@0.1.0: - resolution: {integrity: sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==} - dev: true - - /clipboardy@3.0.0: - resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - arch: 2.2.0 - execa: 5.1.1 - is-wsl: 2.2.0 - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /cluster-key-slot@1.1.2: - resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} - engines: {node: '>=0.10.0'} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: true - - /colord@2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - dev: true - - /colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true - - /commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - dev: true - - /commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: true - - /commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true - - /compress-commons@5.0.1: - resolution: {integrity: sha512-MPh//1cERdLtqwO3pOFLeXtpuai0Y2WCd5AhtKxznqM7WtaMYaOEMSgn45d9D10sIHSfIKE603HlOp8OPGrvag==} - engines: {node: '>= 12.0.0'} - dependencies: - crc-32: 1.2.2 - crc32-stream: 5.0.0 - normalize-path: 3.0.0 - readable-stream: 3.6.2 - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /consola@3.2.3: - resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} - engines: {node: ^14.18.0 || >=16.10.0} - dev: true - - /console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cookie-es@1.0.0: - resolution: {integrity: sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==} - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /crc-32@1.2.2: - resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} - engines: {node: '>=0.8'} - hasBin: true - dev: true - - /crc32-stream@5.0.0: - resolution: {integrity: sha512-B0EPa1UK+qnpBZpG+7FgPCu0J2ETLpXq09o9BkLkEAhdB6Z61Qo4pJ3JYu0c+Qi+/SAL7QThqnzS06pmSSyZaw==} - engines: {node: '>= 12.0.0'} - dependencies: - crc-32: 1.2.2 - readable-stream: 3.6.2 - dev: true - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /css-declaration-sorter@6.4.1(postcss@8.4.31): - resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} - engines: {node: ^10 || ^12 || >=14} - peerDependencies: - postcss: ^8.0.9 - dependencies: - postcss: 8.4.31 - dev: true - - /css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.1.0 - nth-check: 2.1.1 - dev: true - - /css-tree@2.2.1: - resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - dependencies: - mdn-data: 2.0.28 - source-map-js: 1.0.2 - dev: true - - /css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.0.2 - dev: true - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: true - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /cssnano-preset-default@6.0.1(postcss@8.4.31): - resolution: {integrity: sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - css-declaration-sorter: 6.4.1(postcss@8.4.31) - cssnano-utils: 4.0.0(postcss@8.4.31) - postcss: 8.4.31 - postcss-calc: 9.0.1(postcss@8.4.31) - postcss-colormin: 6.0.0(postcss@8.4.31) - postcss-convert-values: 6.0.0(postcss@8.4.31) - postcss-discard-comments: 6.0.0(postcss@8.4.31) - postcss-discard-duplicates: 6.0.0(postcss@8.4.31) - postcss-discard-empty: 6.0.0(postcss@8.4.31) - postcss-discard-overridden: 6.0.0(postcss@8.4.31) - postcss-merge-longhand: 6.0.0(postcss@8.4.31) - postcss-merge-rules: 6.0.1(postcss@8.4.31) - postcss-minify-font-values: 6.0.0(postcss@8.4.31) - postcss-minify-gradients: 6.0.0(postcss@8.4.31) - postcss-minify-params: 6.0.0(postcss@8.4.31) - postcss-minify-selectors: 6.0.0(postcss@8.4.31) - postcss-normalize-charset: 6.0.0(postcss@8.4.31) - postcss-normalize-display-values: 6.0.0(postcss@8.4.31) - postcss-normalize-positions: 6.0.0(postcss@8.4.31) - postcss-normalize-repeat-style: 6.0.0(postcss@8.4.31) - postcss-normalize-string: 6.0.0(postcss@8.4.31) - postcss-normalize-timing-functions: 6.0.0(postcss@8.4.31) - postcss-normalize-unicode: 6.0.0(postcss@8.4.31) - postcss-normalize-url: 6.0.0(postcss@8.4.31) - postcss-normalize-whitespace: 6.0.0(postcss@8.4.31) - postcss-ordered-values: 6.0.0(postcss@8.4.31) - postcss-reduce-initial: 6.0.0(postcss@8.4.31) - postcss-reduce-transforms: 6.0.0(postcss@8.4.31) - postcss-svgo: 6.0.0(postcss@8.4.31) - postcss-unique-selectors: 6.0.0(postcss@8.4.31) - dev: true - - /cssnano-utils@4.0.0(postcss@8.4.31): - resolution: {integrity: sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - dev: true - - /cssnano@6.0.1(postcss@8.4.31): - resolution: {integrity: sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - cssnano-preset-default: 6.0.1(postcss@8.4.31) - lilconfig: 2.1.0 - postcss: 8.4.31 - dev: true - - /csso@5.0.5: - resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - dependencies: - css-tree: 2.2.1 - dev: true - - /csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true - - /default-browser-id@3.0.0: - resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} - engines: {node: '>=12'} - dependencies: - bplist-parser: 0.2.0 - untildify: 4.0.0 - dev: true - - /default-browser@4.0.0: - resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} - engines: {node: '>=14.16'} - dependencies: - bundle-name: 3.0.0 - default-browser-id: 3.0.0 - execa: 7.2.0 - titleize: 3.0.0 - dev: true - - /define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - dev: true - - /define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - dev: true - - /defu@6.1.3: - resolution: {integrity: sha512-Vy2wmG3NTkmHNg/kzpuvHhkqeIx3ODWqasgCRbKtbXEN0G+HpEEv9BtJLp7ZG1CZloFaC41Ah3ZFbq7aqCqMeQ==} - dev: true - - /delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: true - - /denque@2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} - engines: {node: '>=0.10'} - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true - - /destr@2.0.2: - resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} - dev: true - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true - - /detect-libc@1.0.3: - resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} - engines: {node: '>=0.10'} - hasBin: true - dev: true - - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - dev: true - - /devalue@4.3.2: - resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} - dev: true - - /diff@5.1.0: - resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} - engines: {node: '>=0.3.1'} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - dev: true - - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true - - /domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: true - - /domutils@3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dev: true - - /dot-prop@8.0.2: - resolution: {integrity: sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==} - engines: {node: '>=16'} - dependencies: - type-fest: 3.13.1 - dev: true - - /dotenv@16.3.1: - resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} - engines: {node: '>=12'} - dev: true - - /duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true - - /electron-to-chromium@1.4.581: - resolution: {integrity: sha512-6uhqWBIapTJUxgPTCHH9sqdbxIMPt7oXl0VcAL1kOtlU6aECdcMncCrX5Z7sHQ/invtrC9jUQUef7+HhO8vVFw==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: true - - /encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - requiresBuild: true - dependencies: - iconv-lite: 0.6.3 - dev: true - optional: true - - /enhanced-resolve@5.15.0: - resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: true - - /env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - dev: true - - /err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - dev: true - - /error-stack-parser-es@0.1.1: - resolution: {integrity: sha512-g/9rfnvnagiNf+DRMHEVGuGuIBlCIMDFoTA616HaP2l9PlCjGjVhD98PNbVSJvmK4TttqT5mV5tInMhoFgi+aA==} - dev: true - - /esbuild@0.18.20: - resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.18.20 - '@esbuild/android-arm64': 0.18.20 - '@esbuild/android-x64': 0.18.20 - '@esbuild/darwin-arm64': 0.18.20 - '@esbuild/darwin-x64': 0.18.20 - '@esbuild/freebsd-arm64': 0.18.20 - '@esbuild/freebsd-x64': 0.18.20 - '@esbuild/linux-arm': 0.18.20 - '@esbuild/linux-arm64': 0.18.20 - '@esbuild/linux-ia32': 0.18.20 - '@esbuild/linux-loong64': 0.18.20 - '@esbuild/linux-mips64el': 0.18.20 - '@esbuild/linux-ppc64': 0.18.20 - '@esbuild/linux-riscv64': 0.18.20 - '@esbuild/linux-s390x': 0.18.20 - '@esbuild/linux-x64': 0.18.20 - '@esbuild/netbsd-x64': 0.18.20 - '@esbuild/openbsd-x64': 0.18.20 - '@esbuild/sunos-x64': 0.18.20 - '@esbuild/win32-arm64': 0.18.20 - '@esbuild/win32-ia32': 0.18.20 - '@esbuild/win32-x64': 0.18.20 - dev: true - - /esbuild@0.19.5: - resolution: {integrity: sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.19.5 - '@esbuild/android-arm64': 0.19.5 - '@esbuild/android-x64': 0.19.5 - '@esbuild/darwin-arm64': 0.19.5 - '@esbuild/darwin-x64': 0.19.5 - '@esbuild/freebsd-arm64': 0.19.5 - '@esbuild/freebsd-x64': 0.19.5 - '@esbuild/linux-arm': 0.19.5 - '@esbuild/linux-arm64': 0.19.5 - '@esbuild/linux-ia32': 0.19.5 - '@esbuild/linux-loong64': 0.19.5 - '@esbuild/linux-mips64el': 0.19.5 - '@esbuild/linux-ppc64': 0.19.5 - '@esbuild/linux-riscv64': 0.19.5 - '@esbuild/linux-s390x': 0.19.5 - '@esbuild/linux-x64': 0.19.5 - '@esbuild/netbsd-x64': 0.19.5 - '@esbuild/openbsd-x64': 0.19.5 - '@esbuild/sunos-x64': 0.19.5 - '@esbuild/win32-arm64': 0.19.5 - '@esbuild/win32-ia32': 0.19.5 - '@esbuild/win32-x64': 0.19.5 - dev: true - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: true - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - dependencies: - '@types/estree': 1.0.5 - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /execa@7.2.0: - resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 4.3.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.1.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 - dev: true - - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.1.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - dev: true - - /exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - dev: true - - /externality@1.0.2: - resolution: {integrity: sha512-LyExtJWKxtgVzmgtEHyQtLFpw1KFhQphF9nTG8TpAIVkiI/xQ3FJh75tRFLYl4hkn7BNIIdLJInuDAavX35pMw==} - dependencies: - enhanced-resolve: 5.15.0 - mlly: 1.4.2 - pathe: 1.1.1 - ufo: 1.3.1 - dev: true - - /fast-fifo@1.3.2: - resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - dependencies: - reusify: 1.0.4 - dev: true - - /file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: true - - /flatted@3.2.9: - resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: true - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: true - - /fs-extra@11.1.1: - resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /fs-minipass@3.0.3: - resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.0.4 - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-port-please@3.1.1: - resolution: {integrity: sha512-3UBAyM3u4ZBVYDsxOQfJDxEa6XTbpBDrOjp4mf7ExFRt5BKs/QywQQiJsh2B+hxcZLSapWqCRvElUe8DnKcFHA==} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - dev: true - - /giget@1.1.3: - resolution: {integrity: sha512-zHuCeqtfgqgDwvXlR84UNgnJDuUHQcNI5OqWqFxxuk2BshuKbYhJWdxBsEo4PvKqoGh23lUAIvBNpChMLv7/9Q==} - hasBin: true - dependencies: - colorette: 2.0.20 - defu: 6.1.3 - https-proxy-agent: 7.0.2 - mri: 1.2.0 - node-fetch-native: 1.4.1 - pathe: 1.1.1 - tar: 6.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /git-config-path@2.0.0: - resolution: {integrity: sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==} - engines: {node: '>=4'} - dev: true - - /git-up@7.0.0: - resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} - dependencies: - is-ssh: 1.4.0 - parse-url: 8.1.0 - dev: true - - /git-url-parse@13.1.1: - resolution: {integrity: sha512-PCFJyeSSdtnbfhSNRw9Wk96dDCNx+sogTe4YNXeXSJxt7xz5hvXekuRn9JX7m+Mf4OscCu8h+mtAl3+h5Fo8lQ==} - dependencies: - git-up: 7.0.0 - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - dev: true - - /global-directory@4.0.1: - resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} - engines: {node: '>=18'} - dependencies: - ini: 4.1.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.2.4 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true - - /gzip-size@7.0.0: - resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - duplexer: 0.1.2 - dev: true - - /h3@1.8.2: - resolution: {integrity: sha512-1Ca0orJJlCaiFY68BvzQtP2lKLk46kcLAxVM8JgYbtm2cUg6IY7pjpYgWMwUvDO9QI30N5JAukOKoT8KD3Q0PQ==} - dependencies: - cookie-es: 1.0.0 - defu: 6.1.3 - destr: 2.0.2 - iron-webcrypto: 0.10.1 - radix3: 1.1.0 - ufo: 1.3.1 - uncrypto: 0.1.3 - unenv: 1.7.4 - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: true - - /hash-sum@2.0.0: - resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} - dev: true - - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /hookable@5.5.3: - resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} - dev: true - - /hosted-git-info@7.0.1: - resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - lru-cache: 10.0.2 - dev: true - - /html-tags@3.3.1: - resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} - engines: {node: '>=8'} - dev: true - - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: true - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - - /http-proxy-agent@7.0.0: - resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /http-shutdown@1.2.2: - resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent@7.0.2: - resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /httpxy@0.1.5: - resolution: {integrity: sha512-hqLDO+rfststuyEUTWObQK6zHEEmZ/kaIP2/zclGGZn6X8h/ESTWg+WKecQ/e5k4nPswjzZD+q2VqZIbr15CoQ==} - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - dev: true - - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - dev: true - - /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - requiresBuild: true - dependencies: - safer-buffer: 2.1.2 - dev: true - optional: true - - /ignore-walk@6.0.3: - resolution: {integrity: sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minimatch: 9.0.3 - dev: true - - /ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - dev: true - - /image-meta@0.2.0: - resolution: {integrity: sha512-ZBGjl0ZMEMeOC3Ns0wUF/5UdUmr3qQhBSCniT0LxOgGGIRHiNFOkMtIHB7EOznRU47V2AxPgiVP+s+0/UCU0Hg==} - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - - /ini@4.1.1: - resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /ioredis@5.3.2: - resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==} - engines: {node: '>=12.22.0'} - dependencies: - '@ioredis/commands': 1.2.0 - cluster-key-slot: 1.1.2 - debug: 4.3.4 - denque: 2.1.0 - lodash.defaults: 4.2.0 - lodash.isarguments: 3.1.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /ip@2.0.0: - resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} - dev: true - - /iron-webcrypto@0.10.1: - resolution: {integrity: sha512-QGOS8MRMnj/UiOa+aMIgfyHcvkhqNUsUxb1XzskENvbo+rEfp6TOwqd1KPuDzXC4OnGHcMSVxDGRoilqB8ViqA==} - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.0 - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - dependencies: - is-docker: 3.0.0 - dev: true - - /is-installed-globally@1.0.0: - resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} - engines: {node: '>=18'} - dependencies: - global-directory: 4.0.1 - is-path-inside: 4.0.0 - dev: true - - /is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - dev: true - - /is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@4.0.0: - resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} - engines: {node: '>=12'} - dev: true - - /is-primitive@3.0.1: - resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==} - engines: {node: '>=0.10.0'} - dev: true - - /is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - dev: true - - /is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - dependencies: - '@types/estree': 1.0.5 - dev: true - - /is-ssh@1.4.0: - resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==} - dependencies: - protocols: 2.0.1 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /isexe@3.1.1: - resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} - engines: {node: '>=16'} - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jiti@1.21.0: - resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} - hasBin: true - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /json-parse-even-better-errors@3.0.0: - resolution: {integrity: sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - dev: true - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /klona@2.0.6: - resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} - engines: {node: '>= 8'} - dev: true - - /knitwork@1.0.0: - resolution: {integrity: sha512-dWl0Dbjm6Xm+kDxhPQJsCBTxrJzuGl0aP9rhr+TG8D3l+GL90N8O8lYUi7dTSAN2uuDqCtNgb6aEuQH5wsiV8Q==} - dev: true - - /kolorist@1.8.0: - resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - dev: true - - /launch-editor@2.6.1: - resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} - dependencies: - picocolors: 1.0.0 - shell-quote: 1.8.1 - dev: true - - /lazystream@1.0.1: - resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} - engines: {node: '>= 0.6.3'} - dependencies: - readable-stream: 2.3.8 - dev: true - - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - dev: true - - /listhen@1.5.5: - resolution: {integrity: sha512-LXe8Xlyh3gnxdv4tSjTjscD1vpr/2PRpzq8YIaMJgyKzRG8wdISlWVWnGThJfHnlJ6hmLt2wq1yeeix0TEbuoA==} - hasBin: true - dependencies: - '@parcel/watcher': 2.3.0 - '@parcel/watcher-wasm': 2.3.0 - citty: 0.1.4 - clipboardy: 3.0.0 - consola: 3.2.3 - defu: 6.1.3 - get-port-please: 3.1.1 - h3: 1.8.2 - http-shutdown: 1.2.2 - jiti: 1.21.0 - mlly: 1.4.2 - node-forge: 1.3.1 - pathe: 1.1.1 - std-env: 3.4.3 - ufo: 1.3.1 - untun: 0.1.2 - uqr: 0.1.2 - dev: true - - /local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} - engines: {node: '>=14'} - dev: true - - /local-pkg@0.5.0: - resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} - engines: {node: '>=14'} - dependencies: - mlly: 1.4.2 - pkg-types: 1.0.3 - dev: true - - /lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true - - /lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - dev: true - - /lodash.isarguments@3.1.0: - resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - dev: true - - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - dev: true - - /lodash.pick@4.4.0: - resolution: {integrity: sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==} - dev: true - - /lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /lru-cache@10.0.2: - resolution: {integrity: sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==} - engines: {node: 14 || >=16.14} - dependencies: - semver: 7.5.4 - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /magic-string-ast@0.3.0: - resolution: {integrity: sha512-0shqecEPgdFpnI3AP90epXyxZy9g6CRZ+SZ7BcqFwYmtFEnZ1jpevcV5HoyVnlDS9gCnc1UIg3Rsvp3Ci7r8OA==} - engines: {node: '>=16.14.0'} - dependencies: - magic-string: 0.30.5 - dev: true - - /magic-string@0.30.5: - resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /magicast@0.3.1: - resolution: {integrity: sha512-4OS+6e5iHr9VxOeA8TqWNudbdTmKvGNd6iCeOsIDwZn7iLLg3uV3BoQfsaXgFVK5x1fXPBx5X0f6w4sb6HYSQA==} - dependencies: - '@babel/parser': 7.23.3 - '@babel/types': 7.23.3 - source-map-js: 1.0.2 - dev: true - - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.1 - dev: true - - /make-fetch-happen@13.0.0: - resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/agent': 2.2.0 - cacache: 18.0.0 - http-cache-semantics: 4.1.1 - is-lambda: 1.0.1 - minipass: 7.0.4 - minipass-fetch: 3.0.4 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.3 - promise-retry: 2.0.1 - ssri: 10.0.5 - transitivePeerDependencies: - - supports-color - dev: true - - /mdn-data@2.0.28: - resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} - dev: true - - /mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /mime@3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass-fetch@3.0.4: - resolution: {integrity: sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.0.4 - minipass-sized: 1.0.3 - minizlib: 2.1.2 - optionalDependencies: - encoding: 0.1.13 - dev: true - - /minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass-json-stream@1.0.1: - resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} - dependencies: - jsonparse: 1.3.1 - minipass: 3.3.6 - dev: true - - /minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: true - - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - dev: true - - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: true - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /mlly@1.4.2: - resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} - dependencies: - acorn: 8.11.2 - pathe: 1.1.1 - pkg-types: 1.0.3 - ufo: 1.3.1 - dev: true - - /mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - dev: true - - /mrmime@1.0.1: - resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} - engines: {node: '>=10'} - dev: true - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true - - /nanoid@4.0.2: - resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} - engines: {node: ^14 || ^16 || >=18} - hasBin: true - dev: true - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true - - /nitropack@2.7.2: - resolution: {integrity: sha512-6vQbGdBNR20N8wTChzIQUZQmNVhWVDrjUdpOYD68u2hlyUiJembth2fQuoWw3KlsoNYWFvcyqL9X3DPjjnoEUQ==} - engines: {node: ^16.11.0 || >=17.0.0} - hasBin: true - peerDependencies: - xml2js: ^0.6.2 - peerDependenciesMeta: - xml2js: - optional: true - dependencies: - '@cloudflare/kv-asset-handler': 0.3.0 - '@netlify/functions': 2.4.0 - '@rollup/plugin-alias': 5.0.1(rollup@3.29.4) - '@rollup/plugin-commonjs': 25.0.7(rollup@3.29.4) - '@rollup/plugin-inject': 5.0.5(rollup@3.29.4) - '@rollup/plugin-json': 6.0.1(rollup@3.29.4) - '@rollup/plugin-node-resolve': 15.2.3(rollup@3.29.4) - '@rollup/plugin-replace': 5.0.5(rollup@3.29.4) - '@rollup/plugin-terser': 0.4.4(rollup@3.29.4) - '@rollup/plugin-wasm': 6.2.2(rollup@3.29.4) - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - '@types/http-proxy': 1.17.14 - '@vercel/nft': 0.24.3 - archiver: 6.0.1 - c12: 1.5.1 - chalk: 5.3.0 - chokidar: 3.5.3 - citty: 0.1.4 - consola: 3.2.3 - cookie-es: 1.0.0 - defu: 6.1.3 - destr: 2.0.2 - dot-prop: 8.0.2 - esbuild: 0.19.5 - escape-string-regexp: 5.0.0 - etag: 1.8.1 - fs-extra: 11.1.1 - globby: 13.2.2 - gzip-size: 7.0.0 - h3: 1.8.2 - hookable: 5.5.3 - httpxy: 0.1.5 - is-primitive: 3.0.1 - jiti: 1.21.0 - klona: 2.0.6 - knitwork: 1.0.0 - listhen: 1.5.5 - magic-string: 0.30.5 - mime: 3.0.0 - mlly: 1.4.2 - mri: 1.2.0 - node-fetch-native: 1.4.1 - ofetch: 1.3.3 - ohash: 1.1.3 - openapi-typescript: 6.7.1 - pathe: 1.1.1 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - pretty-bytes: 6.1.1 - radix3: 1.1.0 - rollup: 3.29.4 - rollup-plugin-visualizer: 5.9.2(rollup@3.29.4) - scule: 1.0.0 - semver: 7.5.4 - serve-placeholder: 2.0.1 - serve-static: 1.15.0 - std-env: 3.4.3 - ufo: 1.3.1 - uncrypto: 0.1.3 - unctx: 2.3.1 - unenv: 1.7.4 - unimport: 3.5.0(rollup@3.29.4) - unstorage: 1.9.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/kv' - - encoding - - idb-keyval - - supports-color - dev: true - - /node-addon-api@7.0.0: - resolution: {integrity: sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==} - dev: true - - /node-fetch-native@1.4.1: - resolution: {integrity: sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w==} - dev: true - - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true - - /node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} - engines: {node: '>= 6.13.0'} - dev: true - - /node-gyp-build@4.6.1: - resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==} - hasBin: true - dev: true - - /node-gyp@10.0.1: - resolution: {integrity: sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==} - engines: {node: ^16.14.0 || >=18.0.0} - hasBin: true - dependencies: - env-paths: 2.2.1 - exponential-backoff: 3.1.1 - glob: 10.3.10 - graceful-fs: 4.2.11 - make-fetch-happen: 13.0.0 - nopt: 7.2.0 - proc-log: 3.0.0 - semver: 7.5.4 - tar: 6.2.0 - which: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /node-releases@2.0.13: - resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} - dev: true - - /nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: true - - /nopt@7.2.0: - resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - abbrev: 2.0.0 - dev: true - - /normalize-package-data@6.0.0: - resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - hosted-git-info: 7.0.1 - is-core-module: 2.13.1 - semver: 7.5.4 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-bundled@3.0.0: - resolution: {integrity: sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - npm-normalize-package-bin: 3.0.1 - dev: true - - /npm-install-checks@6.3.0: - resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.5.4 - dev: true - - /npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /npm-package-arg@11.0.1: - resolution: {integrity: sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - hosted-git-info: 7.0.1 - proc-log: 3.0.0 - semver: 7.5.4 - validate-npm-package-name: 5.0.0 - dev: true - - /npm-packlist@8.0.0: - resolution: {integrity: sha512-ErAGFB5kJUciPy1mmx/C2YFbvxoJ0QJ9uwkCZOeR6CqLLISPZBOiFModAbSXnjjlwW5lOhuhXva+fURsSGJqyw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - ignore-walk: 6.0.3 - dev: true - - /npm-pick-manifest@9.0.0: - resolution: {integrity: sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - npm-install-checks: 6.3.0 - npm-normalize-package-bin: 3.0.1 - npm-package-arg: 11.0.1 - semver: 7.5.4 - dev: true - - /npm-registry-fetch@16.1.0: - resolution: {integrity: sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - make-fetch-happen: 13.0.0 - minipass: 7.0.4 - minipass-fetch: 3.0.4 - minipass-json-stream: 1.0.1 - minizlib: 2.1.2 - npm-package-arg: 11.0.1 - proc-log: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - - /npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: true - - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - dependencies: - boolbase: 1.0.0 - dev: true - - /nuxi@3.9.1: - resolution: {integrity: sha512-4R4tcC2uQ5QCnHxyKoX5nZm/YUesCcQM3bZBKYU/8ZWrWjK6aPG6Q5zOQG1aLPkAotyahNsqtSiU/CrRoenEgA==} - engines: {node: ^14.18.0 || >=16.10.0} - hasBin: true - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /nuxt@3.8.1(vite@4.5.0): - resolution: {integrity: sha512-RSGO56Gv0x2f6AXWw4o4GoBaVdsD0qkPCjrX7Ud/jzH3cRJoyYMPuq/9AOLvf2o1ecZWl39j5elqJ4QHmggyOA==} - engines: {node: ^14.18.0 || >=16.10.0} - hasBin: true - peerDependencies: - '@parcel/watcher': ^2.1.0 - '@types/node': ^14.18.0 || >=16.10.0 - peerDependenciesMeta: - '@parcel/watcher': - optional: true - '@types/node': - optional: true - dependencies: - '@nuxt/devalue': 2.0.2 - '@nuxt/devtools': 1.0.1(nuxt@3.8.1)(vite@4.5.0) - '@nuxt/kit': 3.8.1 - '@nuxt/schema': 3.8.1 - '@nuxt/telemetry': 2.5.2 - '@nuxt/ui-templates': 1.3.1 - '@nuxt/vite-builder': 3.8.1(vue@3.3.8) - '@unhead/dom': 1.8.3 - '@unhead/ssr': 1.8.3 - '@unhead/vue': 1.8.3(vue@3.3.8) - '@vue/shared': 3.3.8 - acorn: 8.11.2 - c12: 1.5.1 - chokidar: 3.5.3 - cookie-es: 1.0.0 - defu: 6.1.3 - destr: 2.0.2 - devalue: 4.3.2 - esbuild: 0.19.5 - escape-string-regexp: 5.0.0 - estree-walker: 3.0.3 - fs-extra: 11.1.1 - globby: 13.2.2 - h3: 1.8.2 - hookable: 5.5.3 - jiti: 1.21.0 - klona: 2.0.6 - knitwork: 1.0.0 - magic-string: 0.30.5 - mlly: 1.4.2 - nitropack: 2.7.2 - nuxi: 3.9.1 - nypm: 0.3.3 - ofetch: 1.3.3 - ohash: 1.1.3 - pathe: 1.1.1 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - radix3: 1.1.0 - scule: 1.0.0 - std-env: 3.4.3 - strip-literal: 1.3.0 - ufo: 1.3.1 - ultrahtml: 1.5.2 - uncrypto: 0.1.3 - unctx: 2.3.1 - unenv: 1.7.4 - unimport: 3.5.0(rollup@3.29.4) - unplugin: 1.5.0 - unplugin-vue-router: 0.7.0(vue-router@4.2.5)(vue@3.3.8) - untyped: 1.4.0 - vue: 3.3.8 - vue-bundle-renderer: 2.0.0 - vue-devtools-stub: 0.1.0 - vue-router: 4.2.5(vue@3.3.8) - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/kv' - - bluebird - - bufferutil - - encoding - - eslint - - idb-keyval - - less - - lightningcss - - meow - - optionator - - rollup - - sass - - stylelint - - stylus - - sugarss - - supports-color - - terser - - typescript - - utf-8-validate - - vite - - vls - - vti - - vue-tsc - - xml2js - dev: true - - /nypm@0.3.3: - resolution: {integrity: sha512-FHoxtTscAE723e80d2M9cJRb4YVjL82Ra+ZV+YqC6rfNZUWahi+ZhPF+krnR+bdMvibsfHCtgKXnZf5R6kmEPA==} - engines: {node: ^14.16.0 || >=16.10.0} - hasBin: true - dependencies: - citty: 0.1.4 - execa: 8.0.1 - pathe: 1.1.1 - ufo: 1.3.1 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /ofetch@1.3.3: - resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==} - dependencies: - destr: 2.0.2 - node-fetch-native: 1.4.1 - ufo: 1.3.1 - dev: true - - /ohash@1.1.3: - resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} - dev: true - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - - /open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - - /open@9.1.0: - resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} - engines: {node: '>=14.16'} - dependencies: - default-browser: 4.0.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 2.2.0 - dev: true - - /openapi-typescript@6.7.1: - resolution: {integrity: sha512-Q3Ltt0KUm2smcPrsaR8qKmSwQ1KM4yGDJVoQdpYa0yvKPeN8huDx5utMT7DvwvJastHHzUxajjivK3WN2+fobg==} - hasBin: true - dependencies: - ansi-colors: 4.1.3 - fast-glob: 3.3.2 - js-yaml: 4.1.0 - supports-color: 9.4.0 - undici: 5.27.2 - yargs-parser: 21.1.1 - dev: true - - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: true - - /pacote@17.0.4: - resolution: {integrity: sha512-eGdLHrV/g5b5MtD5cTPyss+JxOlaOloSMG3UwPMAvL8ywaLJ6beONPF40K4KKl/UI6q5hTKCJq5rCu8tkF+7Dg==} - engines: {node: ^16.14.0 || >=18.0.0} - hasBin: true - dependencies: - '@npmcli/git': 5.0.3 - '@npmcli/installed-package-contents': 2.0.2 - '@npmcli/promise-spawn': 7.0.0 - '@npmcli/run-script': 7.0.2 - cacache: 18.0.0 - fs-minipass: 3.0.3 - minipass: 7.0.4 - npm-package-arg: 11.0.1 - npm-packlist: 8.0.0 - npm-pick-manifest: 9.0.0 - npm-registry-fetch: 16.1.0 - proc-log: 3.0.0 - promise-retry: 2.0.1 - read-package-json: 7.0.0 - read-package-json-fast: 3.0.2 - sigstore: 2.1.0 - ssri: 10.0.5 - tar: 6.2.0 - transitivePeerDependencies: - - bluebird - - supports-color - dev: true - - /parse-git-config@3.0.0: - resolution: {integrity: sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA==} - engines: {node: '>=8'} - dependencies: - git-config-path: 2.0.0 - ini: 1.3.8 - dev: true - - /parse-path@7.0.0: - resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==} - dependencies: - protocols: 2.0.1 - dev: true - - /parse-url@8.1.0: - resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} - dependencies: - parse-path: 7.0.0 - dev: true - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.0.2 - minipass: 7.0.4 - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /pathe@1.1.1: - resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} - dev: true - - /perfect-debounce@1.0.0: - resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} - dev: true - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pkg-types@1.0.3: - resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} - dependencies: - jsonc-parser: 3.2.0 - mlly: 1.4.2 - pathe: 1.1.1 - dev: true - - /postcss-calc@9.0.1(postcss@8.4.31): - resolution: {integrity: sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.2 - dependencies: - postcss: 8.4.31 - postcss-selector-parser: 6.0.13 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-colormin@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.22.1 - caniuse-api: 3.0.0 - colord: 2.9.3 - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-convert-values@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.22.1 - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-discard-comments@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - dev: true - - /postcss-discard-duplicates@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - dev: true - - /postcss-discard-empty@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - dev: true - - /postcss-discard-overridden@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - dev: true - - /postcss-merge-longhand@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - stylehacks: 6.0.0(postcss@8.4.31) - dev: true - - /postcss-merge-rules@6.0.1(postcss@8.4.31): - resolution: {integrity: sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.22.1 - caniuse-api: 3.0.0 - cssnano-utils: 4.0.0(postcss@8.4.31) - postcss: 8.4.31 - postcss-selector-parser: 6.0.13 - dev: true - - /postcss-minify-font-values@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-minify-gradients@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - colord: 2.9.3 - cssnano-utils: 4.0.0(postcss@8.4.31) - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-minify-params@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.22.1 - cssnano-utils: 4.0.0(postcss@8.4.31) - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-minify-selectors@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-selector-parser: 6.0.13 - dev: true - - /postcss-normalize-charset@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - dev: true - - /postcss-normalize-display-values@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-positions@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-repeat-style@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-string@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-timing-functions@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-unicode@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.22.1 - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-url@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-whitespace@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-ordered-values@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - cssnano-utils: 4.0.0(postcss@8.4.31) - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-reduce-initial@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.22.1 - caniuse-api: 3.0.0 - postcss: 8.4.31 - dev: true - - /postcss-reduce-transforms@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-selector-parser@6.0.13: - resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: true - - /postcss-svgo@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==} - engines: {node: ^14 || ^16 || >= 18} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-value-parser: 4.2.0 - svgo: 3.0.3 - dev: true - - /postcss-unique-selectors@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - postcss: 8.4.31 - postcss-selector-parser: 6.0.13 - dev: true - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true - - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: true - - /pretty-bytes@6.1.1: - resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} - engines: {node: ^14.13.1 || >=16.0.0} - dev: true - - /proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - - /promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - dev: true - - /promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - dev: true - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /protocols@2.0.1: - resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /queue-tick@1.0.1: - resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} - dev: true - - /radix3@1.1.0: - resolution: {integrity: sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==} - dev: true - - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: true - - /rc9@2.1.1: - resolution: {integrity: sha512-lNeOl38Ws0eNxpO3+wD1I9rkHGQyj1NU1jlzv4go2CtEnEQEUfqnIvZG7W+bC/aXdJ27n5x/yUjb6RoT9tko+Q==} - dependencies: - defu: 6.1.3 - destr: 2.0.2 - flat: 5.0.2 - dev: true - - /read-package-json-fast@3.0.2: - resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - json-parse-even-better-errors: 3.0.0 - npm-normalize-package-bin: 3.0.1 - dev: true - - /read-package-json@7.0.0: - resolution: {integrity: sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - glob: 10.3.10 - json-parse-even-better-errors: 3.0.0 - normalize-package-data: 6.0.0 - npm-normalize-package-bin: 3.0.1 - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdir-glob@1.1.3: - resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} - dependencies: - minimatch: 5.1.6 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /redis-errors@1.2.0: - resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} - engines: {node: '>=4'} - dev: true - - /redis-parser@3.0.0: - resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} - engines: {node: '>=4'} - dependencies: - redis-errors: 1.2.0 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rollup-plugin-visualizer@5.9.2(rollup@3.29.4): - resolution: {integrity: sha512-waHktD5mlWrYFrhOLbti4YgQCn1uR24nYsNuXxg7LkPH8KdTXVWR9DNY1WU0QqokyMixVXJS4J04HNrVTMP01A==} - engines: {node: '>=14'} - hasBin: true - peerDependencies: - rollup: 2.x || 3.x - peerDependenciesMeta: - rollup: - optional: true - dependencies: - open: 8.4.2 - picomatch: 2.3.1 - rollup: 3.29.4 - source-map: 0.7.4 - yargs: 17.7.2 - dev: true - - /rollup@3.29.4: - resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /run-applescript@5.0.0: - resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} - engines: {node: '>=12'} - dependencies: - execa: 5.1.1 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - requiresBuild: true - dev: true - optional: true - - /scule@1.0.0: - resolution: {integrity: sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==} - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /serialize-javascript@6.0.1: - resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} - dependencies: - randombytes: 2.1.0 - dev: true - - /serve-placeholder@2.0.1: - resolution: {integrity: sha512-rUzLlXk4uPFnbEaIz3SW8VISTxMuONas88nYWjAWaM2W9VDbt9tyFOr3lq8RhVOFrT3XISoBw8vni5una8qMnQ==} - dependencies: - defu: 6.1.3 - dev: true - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: true - - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /sigstore@2.1.0: - resolution: {integrity: sha512-kPIj+ZLkyI3QaM0qX8V/nSsweYND3W448pwkDgS6CQ74MfhEkIR8ToK5Iyx46KJYRjseVcD3Rp9zAmUAj6ZjPw==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.1.0 - '@sigstore/protobuf-specs': 0.2.1 - '@sigstore/sign': 2.2.0 - '@sigstore/tuf': 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /simple-git@3.20.0: - resolution: {integrity: sha512-ozK8tl2hvLts8ijTs18iFruE+RoqmC/mqZhjs/+V7gS5W68JpJ3+FCTmLVqmR59MaUQ52MfGQuWsIqfsTbbJ0Q==} - dependencies: - '@kwsites/file-exists': 1.1.1 - '@kwsites/promise-deferred': 1.1.1 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /sirv@2.0.3: - resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==} - engines: {node: '>= 10'} - dependencies: - '@polka/url': 1.0.0-next.23 - mrmime: 1.0.1 - totalist: 3.0.1 - dev: true - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true - - /smob@1.4.1: - resolution: {integrity: sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==} - dev: true - - /socks-proxy-agent@8.0.2: - resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - socks: 2.7.1 - transitivePeerDependencies: - - supports-color - dev: true - - /socks@2.7.1: - resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} - engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} - dependencies: - ip: 2.0.0 - smart-buffer: 4.2.0 - dev: true - - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.16 - dev: true - - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.16 - dev: true - - /spdx-license-ids@3.0.16: - resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} - dev: true - - /ssri@10.0.5: - resolution: {integrity: sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.0.4 - dev: true - - /standard-as-callback@2.1.0: - resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - dev: true - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - - /std-env@3.4.3: - resolution: {integrity: sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==} - dev: true - - /streamx@2.15.4: - resolution: {integrity: sha512-uSXKl88bibiUCQ1eMpItRljCzDENcDx18rsfDmV79r0e/ThfrAwxG4Y2FarQZ2G4/21xcOKmFFd1Hue+ZIDwHw==} - dependencies: - fast-fifo: 1.3.2 - queue-tick: 1.0.1 - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true - - /strip-literal@1.3.0: - resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} - dependencies: - acorn: 8.11.2 - dev: true - - /stylehacks@6.0.0(postcss@8.4.31): - resolution: {integrity: sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.15 - dependencies: - browserslist: 4.22.1 - postcss: 8.4.31 - postcss-selector-parser: 6.0.13 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color@9.4.0: - resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} - engines: {node: '>=12'} - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /svg-tags@1.0.0: - resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} - dev: true - - /svgo@3.0.3: - resolution: {integrity: sha512-X4UZvLhOglD5Xrp834HzGHf8RKUW0Ahigg/08yRO1no9t2NxffOkMiQ0WmaMIbaGlVTlSst2zWANsdhz5ybXgA==} - engines: {node: '>=14.0.0'} - hasBin: true - dependencies: - '@trysound/sax': 0.2.0 - commander: 7.2.0 - css-select: 5.1.0 - css-tree: 2.3.1 - csso: 5.0.5 - picocolors: 1.0.0 - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /tar-stream@3.1.6: - resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} - dependencies: - b4a: 1.6.4 - fast-fifo: 1.3.2 - streamx: 2.15.4 - dev: true - - /tar@6.2.0: - resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: true - - /terser@5.24.0: - resolution: {integrity: sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.5 - acorn: 8.11.2 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - - /tiny-invariant@1.3.1: - resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} - dev: true - - /titleize@3.0.0: - resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} - engines: {node: '>=12'} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true - - /totalist@3.0.1: - resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} - engines: {node: '>=6'} - dev: true - - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true - - /tuf-js@2.1.0: - resolution: {integrity: sha512-eD7YPPjVlMzdggrOeE8zwoegUaG/rt6Bt3jwoQPunRiNVzgcCE009UDFJKJjG+Gk9wFu6W/Vi+P5d/5QpdD9jA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@tufjs/models': 2.0.0 - debug: 4.3.4 - make-fetch-happen: 13.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-fest@3.13.1: - resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} - engines: {node: '>=14.16'} - dev: true - - /ufo@1.3.1: - resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} - dev: true - - /ultrahtml@1.5.2: - resolution: {integrity: sha512-qh4mBffhlkiXwDAOxvSGxhL0QEQsTbnP9BozOK3OYPEGvPvdWzvAUaXNtUSMdNsKDtuyjEbyVUPFZ52SSLhLqw==} - dev: true - - /uncrypto@0.1.3: - resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} - dev: true - - /unctx@2.3.1: - resolution: {integrity: sha512-PhKke8ZYauiqh3FEMVNm7ljvzQiph0Mt3GBRve03IJm7ukfaON2OBK795tLwhbyfzknuRRkW0+Ze+CQUmzOZ+A==} - dependencies: - acorn: 8.11.2 - estree-walker: 3.0.3 - magic-string: 0.30.5 - unplugin: 1.5.0 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /undici@5.27.2: - resolution: {integrity: sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==} - engines: {node: '>=14.0'} - dependencies: - '@fastify/busboy': 2.0.0 - dev: true - - /unenv@1.7.4: - resolution: {integrity: sha512-fjYsXYi30It0YCQYqLOcT6fHfMXsBr2hw9XC7ycf8rTG7Xxpe3ZssiqUnD0khrjiZEmkBXWLwm42yCSCH46fMw==} - dependencies: - consola: 3.2.3 - defu: 6.1.3 - mime: 3.0.0 - node-fetch-native: 1.4.1 - pathe: 1.1.1 - dev: true - - /unhead@1.8.3: - resolution: {integrity: sha512-2/5NJs7nY1MgCkUNuyevALM9nSgGp2loRv5QPhYyZXUPdF+F76CpKvkqATEOEJ/1yDzWjCaWrNh4u5lS6BEioA==} - dependencies: - '@unhead/dom': 1.8.3 - '@unhead/schema': 1.8.3 - '@unhead/shared': 1.8.3 - hookable: 5.5.3 - dev: true - - /unimport@3.5.0(rollup@3.29.4): - resolution: {integrity: sha512-0Ei1iTeSYxs7oxxUf79/KaBc2dPjZxe7qdVpw7yIz5YcdTZjmBYO6ToLDW+fX9QOHiueZ3xtwb5Z/wqaSfXx6A==} - dependencies: - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - escape-string-regexp: 5.0.0 - fast-glob: 3.3.2 - local-pkg: 0.5.0 - magic-string: 0.30.5 - mlly: 1.4.2 - pathe: 1.1.1 - pkg-types: 1.0.3 - scule: 1.0.0 - strip-literal: 1.3.0 - unplugin: 1.5.0 - transitivePeerDependencies: - - rollup - dev: true - - /unique-filename@3.0.0: - resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - unique-slug: 4.0.0 - dev: true - - /unique-slug@4.0.0: - resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - imurmurhash: 0.1.4 - dev: true - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: true - - /unplugin-vue-router@0.7.0(vue-router@4.2.5)(vue@3.3.8): - resolution: {integrity: sha512-ddRreGq0t5vlSB7OMy4e4cfU1w2AwBQCwmvW3oP/0IHQiokzbx4hd3TpwBu3eIAFVuhX2cwNQwp1U32UybTVCw==} - peerDependencies: - vue-router: ^4.1.0 - peerDependenciesMeta: - vue-router: - optional: true - dependencies: - '@babel/types': 7.23.3 - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - '@vue-macros/common': 1.8.0(vue@3.3.8) - ast-walker-scope: 0.5.0 - chokidar: 3.5.3 - fast-glob: 3.3.2 - json5: 2.2.3 - local-pkg: 0.4.3 - mlly: 1.4.2 - pathe: 1.1.1 - scule: 1.0.0 - unplugin: 1.5.0 - vue-router: 4.2.5(vue@3.3.8) - yaml: 2.3.4 - transitivePeerDependencies: - - rollup - - vue - dev: true - - /unplugin@1.5.0: - resolution: {integrity: sha512-9ZdRwbh/4gcm1JTOkp9lAkIDrtOyOxgHmY7cjuwI8L/2RTikMcVG25GsZwNAgRuap3iDw2jeq7eoqtAsz5rW3A==} - dependencies: - acorn: 8.11.2 - chokidar: 3.5.3 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.5.0 - dev: true - - /unstorage@1.9.0: - resolution: {integrity: sha512-VpD8ZEYc/le8DZCrny3bnqKE4ZjioQxBRnWE+j5sGNvziPjeDlaS1NaFFHzl/kkXaO3r7UaF8MGQrs14+1B4pQ==} - peerDependencies: - '@azure/app-configuration': ^1.4.1 - '@azure/cosmos': ^3.17.3 - '@azure/data-tables': ^13.2.2 - '@azure/identity': ^3.2.3 - '@azure/keyvault-secrets': ^4.7.0 - '@azure/storage-blob': ^12.14.0 - '@capacitor/preferences': ^5.0.0 - '@planetscale/database': ^1.8.0 - '@upstash/redis': ^1.22.0 - '@vercel/kv': ^0.2.2 - idb-keyval: ^6.2.1 - peerDependenciesMeta: - '@azure/app-configuration': - optional: true - '@azure/cosmos': - optional: true - '@azure/data-tables': - optional: true - '@azure/identity': - optional: true - '@azure/keyvault-secrets': - optional: true - '@azure/storage-blob': - optional: true - '@capacitor/preferences': - optional: true - '@planetscale/database': - optional: true - '@upstash/redis': - optional: true - '@vercel/kv': - optional: true - idb-keyval: - optional: true - dependencies: - anymatch: 3.1.3 - chokidar: 3.5.3 - destr: 2.0.2 - h3: 1.8.2 - ioredis: 5.3.2 - listhen: 1.5.5 - lru-cache: 10.0.2 - mri: 1.2.0 - node-fetch-native: 1.4.1 - ofetch: 1.3.3 - ufo: 1.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - dev: true - - /untun@0.1.2: - resolution: {integrity: sha512-wLAMWvxfqyTiBODA1lg3IXHQtjggYLeTK7RnSfqtOXixWJ3bAa2kK/HHmOOg19upteqO3muLvN6O/icbyQY33Q==} - hasBin: true - dependencies: - citty: 0.1.4 - consola: 3.2.3 - pathe: 1.1.1 - dev: true - - /untyped@1.4.0: - resolution: {integrity: sha512-Egkr/s4zcMTEuulcIb7dgURS6QpN7DyqQYdf+jBtiaJvQ+eRsrtWUoX84SbvQWuLkXsOjM+8sJC9u6KoMK/U7Q==} - hasBin: true - dependencies: - '@babel/core': 7.23.3 - '@babel/standalone': 7.23.3 - '@babel/types': 7.23.3 - defu: 6.1.3 - jiti: 1.21.0 - mri: 1.2.0 - scule: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /update-browserslist-db@1.0.13(browserslist@4.22.1): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.22.1 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - - /uqr@0.1.2: - resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} - dev: true - - /urlpattern-polyfill@8.0.2: - resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /validate-npm-package-name@5.0.0: - resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - builtins: 5.0.1 - dev: true - - /vite-node@0.33.0: - resolution: {integrity: sha512-19FpHYbwWWxDr73ruNahC+vtEdza52kA90Qb3La98yZ0xULqV8A5JLNPUff0f5zID4984tW7l3DH2przTJUZSw==} - engines: {node: '>=v14.18.0'} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4 - mlly: 1.4.2 - pathe: 1.1.1 - picocolors: 1.0.0 - vite: 4.5.0 - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /vite-plugin-checker@0.6.2(vite@4.5.0): - resolution: {integrity: sha512-YvvvQ+IjY09BX7Ab+1pjxkELQsBd4rPhWNw8WLBeFVxu/E7O+n6VYAqNsKdK/a2luFlX/sMpoWdGFfg4HvwdJQ==} - engines: {node: '>=14.16'} - peerDependencies: - eslint: '>=7' - meow: ^9.0.0 - optionator: ^0.9.1 - stylelint: '>=13' - typescript: '*' - vite: '>=2.0.0' - vls: '*' - vti: '*' - vue-tsc: '>=1.3.9' - peerDependenciesMeta: - eslint: - optional: true - meow: - optional: true - optionator: - optional: true - stylelint: - optional: true - typescript: - optional: true - vls: - optional: true - vti: - optional: true - vue-tsc: - optional: true - dependencies: - '@babel/code-frame': 7.22.13 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - chokidar: 3.5.3 - commander: 8.3.0 - fast-glob: 3.3.2 - fs-extra: 11.1.1 - lodash.debounce: 4.0.8 - lodash.pick: 4.4.0 - npm-run-path: 4.0.1 - semver: 7.5.4 - strip-ansi: 6.0.1 - tiny-invariant: 1.3.1 - vite: 4.5.0 - vscode-languageclient: 7.0.0 - vscode-languageserver: 7.0.0 - vscode-languageserver-textdocument: 1.0.11 - vscode-uri: 3.0.8 - dev: true - - /vite-plugin-inspect@0.7.42(@nuxt/kit@3.8.1)(vite@4.5.0): - resolution: {integrity: sha512-JCyX86wr3siQc+p9Kd0t8VkFHAJag0RaQVIpdFGSv5FEaePEVB6+V/RGtz2dQkkGSXQzRWrPs4cU3dRKg32bXw==} - engines: {node: '>=14'} - peerDependencies: - '@nuxt/kit': '*' - vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 - peerDependenciesMeta: - '@nuxt/kit': - optional: true - dependencies: - '@antfu/utils': 0.7.6 - '@nuxt/kit': 3.8.1 - '@rollup/pluginutils': 5.0.5(rollup@3.29.4) - debug: 4.3.4 - error-stack-parser-es: 0.1.1 - fs-extra: 11.1.1 - open: 9.1.0 - picocolors: 1.0.0 - sirv: 2.0.3 - vite: 4.5.0 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /vite-plugin-vue-inspector@4.0.0(vite@4.5.0): - resolution: {integrity: sha512-xNjMbRj3YrebuuInTvlC8ghPtzT+3LjMIQPeeR/5CaFd+WcbA9wBnECZmlcP3GITCVED0SxGmTyoJ3iVKsK4vQ==} - peerDependencies: - vite: ^3.0.0-0 || ^4.0.0-0 - dependencies: - '@babel/core': 7.23.3 - '@babel/plugin-proposal-decorators': 7.23.3(@babel/core@7.23.3) - '@babel/plugin-syntax-import-attributes': 7.23.3(@babel/core@7.23.3) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.3) - '@babel/plugin-transform-typescript': 7.23.3(@babel/core@7.23.3) - '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.3) - '@vue/compiler-dom': 3.3.8 - kolorist: 1.8.0 - magic-string: 0.30.5 - vite: 4.5.0 - transitivePeerDependencies: - - supports-color - dev: true - - /vite@4.5.0: - resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.18.20 - postcss: 8.4.31 - rollup: 3.29.4 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vscode-jsonrpc@6.0.0: - resolution: {integrity: sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==} - engines: {node: '>=8.0.0 || >=10.0.0'} - dev: true - - /vscode-languageclient@7.0.0: - resolution: {integrity: sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==} - engines: {vscode: ^1.52.0} - dependencies: - minimatch: 3.1.2 - semver: 7.5.4 - vscode-languageserver-protocol: 3.16.0 - dev: true - - /vscode-languageserver-protocol@3.16.0: - resolution: {integrity: sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==} - dependencies: - vscode-jsonrpc: 6.0.0 - vscode-languageserver-types: 3.16.0 - dev: true - - /vscode-languageserver-textdocument@1.0.11: - resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} - dev: true - - /vscode-languageserver-types@3.16.0: - resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==} - dev: true - - /vscode-languageserver@7.0.0: - resolution: {integrity: sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==} - hasBin: true - dependencies: - vscode-languageserver-protocol: 3.16.0 - dev: true - - /vscode-uri@3.0.8: - resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} - dev: true - - /vue-bundle-renderer@2.0.0: - resolution: {integrity: sha512-oYATTQyh8XVkUWe2kaKxhxKVuuzK2Qcehe+yr3bGiaQAhK3ry2kYE4FWOfL+KO3hVFwCdLmzDQTzYhTi9C+R2A==} - dependencies: - ufo: 1.3.1 - dev: true - - /vue-devtools-stub@0.1.0: - resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==} - dev: true - - /vue-router@4.2.5(vue@3.3.8): - resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==} - peerDependencies: - vue: ^3.2.0 - dependencies: - '@vue/devtools-api': 6.5.1 - vue: 3.3.8 - dev: true - - /vue@3.3.8: - resolution: {integrity: sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@vue/compiler-dom': 3.3.8 - '@vue/compiler-sfc': 3.3.8 - '@vue/runtime-dom': 3.3.8 - '@vue/server-renderer': 3.3.8(vue@3.3.8) - '@vue/shared': 3.3.8 - dev: true - - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack-virtual-modules@0.5.0: - resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - dev: true - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@4.0.0: - resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} - engines: {node: ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - isexe: 3.1.1 - dev: true - - /wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - dependencies: - string-width: 4.2.3 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /ws@8.14.2: - resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - dev: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - 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.8 - yargs-parser: 21.1.1 - dev: true - - /zhead@2.2.4: - resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} - dev: true - - /zip-stream@5.0.1: - resolution: {integrity: sha512-UfZ0oa0C8LI58wJ+moL46BDIMgCQbnsb+2PoiJYtonhBsMh2bq1eRBVkvjfVsqbEHd9/EgKPUuL9saSSsec8OA==} - engines: {node: '>= 12.0.0'} - dependencies: - archiver-utils: 4.0.1 - compress-commons: 5.0.1 - readable-stream: 3.6.2 - dev: true diff --git a/examples/with-vue-nuxt/apps/web/.eslintrc.js b/examples/with-vue-nuxt/apps/web/.eslintrc.js deleted file mode 100644 index 9103af220c63e..0000000000000 --- a/examples/with-vue-nuxt/apps/web/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-env node */ -require("@rushstack/eslint-patch/modern-module-resolution"); - -module.exports = { - root: true, - extends: ["plugin:vue/vue3-essential", "custom/vue"], -}; diff --git a/examples/with-vue-nuxt/apps/web/README.md b/examples/with-vue-nuxt/apps/web/README.md deleted file mode 100644 index 8b8beb479b0de..0000000000000 --- a/examples/with-vue-nuxt/apps/web/README.md +++ /dev/null @@ -1,23 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -pnpm dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `src/app.vue`. The page auto-updates as you edit the file. - -## Learn More - -To learn more about Vue3, take a look at the following resources: - -- [Vue Official Documentation](https://vuejs.org/guide/) - learn about Vue framework for building web user interfaces. - -## Deploy on Vercel - -You can easily deploy your Vue app by using the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme). - -Check out our [Vite deployment documentation](https://vercel.com/docs/frameworks/vite) for more details. diff --git a/examples/with-vue-nuxt/apps/web/src/app.vue b/examples/with-vue-nuxt/apps/web/Source/app.vue similarity index 100% rename from examples/with-vue-nuxt/apps/web/src/app.vue rename to examples/with-vue-nuxt/apps/web/Source/app.vue diff --git a/examples/with-vue-nuxt/apps/web/src/main.ts b/examples/with-vue-nuxt/apps/web/Source/main.ts similarity index 100% rename from examples/with-vue-nuxt/apps/web/src/main.ts rename to examples/with-vue-nuxt/apps/web/Source/main.ts diff --git a/examples/with-vue-nuxt/apps/web/package.json b/examples/with-vue-nuxt/apps/web/package.json index c5040aedb2ecf..216b05bead926 100644 --- a/examples/with-vue-nuxt/apps/web/package.json +++ b/examples/with-vue-nuxt/apps/web/package.json @@ -1,31 +1,21 @@ { - "name": "web", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "vite --port 3000", - "build": "run-p type-check \"build-only {@}\" --", - "preview": "vite preview", - "build-only": "vite build", - "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false", - "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" - }, - "dependencies": { - "ui": "workspace:*", - "vue": "^3.4.21" - }, - "devDependencies": { - "@rushstack/eslint-patch": "^1.7.2", - "@tsconfig/node18": "^18.2.2", - "@types/node": "^20.11.24", - "@vitejs/plugin-vue": "^5.0.4", - "eslint": "^8.57.0", - "eslint-config-custom": "workspace:*", - "eslint-plugin-vue": "^9.22.0", - "npm-run-all2": "^6.1.2", - "tsconfig": "workspace:*", - "typescript": "5.5.4", - "vite": "^5.1.4", - "vue-tsc": "^2.0.4" - } + "name": "web", + "scripts": { + "build": "run-p type-check \"build-only {@}\" --", + "build-only": "vite build", + "dev": "vite --port 3000", + "preview": "vite preview", + "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false" + }, + "dependencies": { + "ui": "workspace:*" + }, + "devDependencies": { + "@rushstack/eslint-patch": "1.10.5", + "@tsconfig/node18": "18.2.4", + "@types/node": "22.13.1", + "eslint-config-custom": "workspace:*", + "npm-run-all2": "7.0.2", + "tsconfig": "workspace:*" + } } diff --git a/examples/with-vue-nuxt/package.json b/examples/with-vue-nuxt/package.json index 67e32d531c832..8ca67bc6a14df 100644 --- a/examples/with-vue-nuxt/package.json +++ b/examples/with-vue-nuxt/package.json @@ -1,15 +1,11 @@ { - "name": "with-vue-nuxt", - "private": true, - "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "pnpm@8.15.6" + "name": "with-vue-nuxt", + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-vue-nuxt/packages/eslint-config-custom/README.md b/examples/with-vue-nuxt/packages/eslint-config-custom/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-vue-nuxt/packages/eslint-config-custom/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-vue-nuxt/packages/eslint-config-custom/package.json b/examples/with-vue-nuxt/packages/eslint-config-custom/package.json index b7b0f56ebea9e..19aef101c235b 100644 --- a/examples/with-vue-nuxt/packages/eslint-config-custom/package.json +++ b/examples/with-vue-nuxt/packages/eslint-config-custom/package.json @@ -1,13 +1,10 @@ { - "name": "eslint-config-custom", - "license": "MIT", - "version": "0.0.0", - "private": true, - "devDependencies": { - "@nuxtjs/eslint-config-typescript": "^12.1.0", - "@vercel/style-guide": "^5.2.0", - "@vue/eslint-config-typescript": "^12.0.0", - "eslint-config-turbo": "^2.0.0", - "typescript": "5.5.4" - } + "name": "eslint-config-custom", + "dependencies": {}, + "devDependencies": { + "@nuxtjs/eslint-config-typescript": "12.1.0", + "@vercel/style-guide": "6.0.0", + "@vue/eslint-config-typescript": "14.4.0", + "eslint-config-turbo": "2.4.2" + } } diff --git a/examples/with-vue-nuxt/packages/tsconfig/package.json b/examples/with-vue-nuxt/packages/tsconfig/package.json index 040533755b8ea..ef0a6ab1bbadd 100644 --- a/examples/with-vue-nuxt/packages/tsconfig/package.json +++ b/examples/with-vue-nuxt/packages/tsconfig/package.json @@ -1,12 +1,5 @@ { - "name": "tsconfig", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "devDependencies": { - "@vue/tsconfig": "^0.5.1" - } + "name": "tsconfig", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-vue-nuxt/packages/ui/.eslintrc.js b/examples/with-vue-nuxt/packages/ui/.eslintrc.js deleted file mode 100644 index 260231c73e64b..0000000000000 --- a/examples/with-vue-nuxt/packages/ui/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["plugin:vue/vue3-essential", "custom/vue"], -}; diff --git a/examples/with-vue-nuxt/packages/ui/src/assets/circles.svg b/examples/with-vue-nuxt/packages/ui/Source/assets/circles.svg similarity index 100% rename from examples/with-vue-nuxt/packages/ui/src/assets/circles.svg rename to examples/with-vue-nuxt/packages/ui/Source/assets/circles.svg diff --git a/examples/with-vue-nuxt/packages/ui/src/assets/next.svg b/examples/with-vue-nuxt/packages/ui/Source/assets/next.svg similarity index 100% rename from examples/with-vue-nuxt/packages/ui/src/assets/next.svg rename to examples/with-vue-nuxt/packages/ui/Source/assets/next.svg diff --git a/examples/with-vue-nuxt/packages/ui/src/assets/turborepo.svg b/examples/with-vue-nuxt/packages/ui/Source/assets/turborepo.svg similarity index 100% rename from examples/with-vue-nuxt/packages/ui/src/assets/turborepo.svg rename to examples/with-vue-nuxt/packages/ui/Source/assets/turborepo.svg diff --git a/examples/with-vue-nuxt/packages/ui/src/assets/vercel.svg b/examples/with-vue-nuxt/packages/ui/Source/assets/vercel.svg similarity index 100% rename from examples/with-vue-nuxt/packages/ui/src/assets/vercel.svg rename to examples/with-vue-nuxt/packages/ui/Source/assets/vercel.svg diff --git a/examples/with-vue-nuxt/packages/ui/src/card.vue b/examples/with-vue-nuxt/packages/ui/Source/card.vue similarity index 100% rename from examples/with-vue-nuxt/packages/ui/src/card.vue rename to examples/with-vue-nuxt/packages/ui/Source/card.vue diff --git a/examples/with-vue-nuxt/packages/ui/src/gradient.vue b/examples/with-vue-nuxt/packages/ui/Source/gradient.vue similarity index 100% rename from examples/with-vue-nuxt/packages/ui/src/gradient.vue rename to examples/with-vue-nuxt/packages/ui/Source/gradient.vue diff --git a/examples/with-vue-nuxt/packages/ui/src/page.vue b/examples/with-vue-nuxt/packages/ui/Source/page.vue similarity index 100% rename from examples/with-vue-nuxt/packages/ui/src/page.vue rename to examples/with-vue-nuxt/packages/ui/Source/page.vue diff --git a/examples/with-vue-nuxt/packages/ui/package.json b/examples/with-vue-nuxt/packages/ui/package.json index 37f7caba4186a..b47ae0f35813e 100644 --- a/examples/with-vue-nuxt/packages/ui/package.json +++ b/examples/with-vue-nuxt/packages/ui/package.json @@ -1,15 +1,11 @@ { - "name": "ui", - "version": "0.0.0", - "private": true, - "main": "./index.ts", - "types": "./index.ts", - "scripts": { - "lint": "eslint ." - }, - "devDependencies": { - "eslint-config-custom": "workspace:*", - "tsconfig": "workspace:*", - "vue": "^3.4.21" - } + "name": "ui", + "main": "./index.ts", + "types": "./index.ts", + "scripts": {}, + "dependencies": {}, + "devDependencies": { + "eslint-config-custom": "workspace:*", + "tsconfig": "workspace:*" + } } diff --git a/examples/with-vue-nuxt/pnpm-lock.yaml b/examples/with-vue-nuxt/pnpm-lock.yaml deleted file mode 100644 index f0263cc13e1a3..0000000000000 --- a/examples/with-vue-nuxt/pnpm-lock.yaml +++ /dev/null @@ -1,8910 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - prettier: - specifier: ^3.2.5 - version: 3.2.5 - turbo: - specifier: ^2.0.3 - version: 2.0.3 - - apps/docs: - dependencies: - ui: - specifier: workspace:* - version: link:../../packages/ui - devDependencies: - '@nuxt/devtools': - specifier: latest - version: 1.0.8(nuxt@3.10.3)(vite@5.1.4) - '@nuxtjs/eslint-config-typescript': - specifier: ^12.1.0 - version: 12.1.0(eslint@8.57.0)(typescript@5.5.4) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - eslint-config-custom: - specifier: workspace:* - version: link:../../packages/eslint-config-custom - nuxt: - specifier: ^3.10.3 - version: 3.10.3(eslint@8.57.0)(typescript@5.5.4)(vite@5.1.4) - tsconfig: - specifier: workspace:* - version: link:../../packages/tsconfig - vue: - specifier: ^3.4.21 - version: 3.4.21(typescript@5.5.4) - vue-router: - specifier: ^4.3.0 - version: 4.3.0(vue@3.4.21) - - apps/web: - dependencies: - ui: - specifier: workspace:* - version: link:../../packages/ui - vue: - specifier: ^3.4.21 - version: 3.4.21(typescript@5.5.4) - devDependencies: - '@rushstack/eslint-patch': - specifier: ^1.7.2 - version: 1.7.2 - '@tsconfig/node18': - specifier: ^18.2.2 - version: 18.2.2 - '@types/node': - specifier: ^20.11.24 - version: 20.11.24 - '@vitejs/plugin-vue': - specifier: ^5.0.4 - version: 5.0.4(vite@5.1.4)(vue@3.4.21) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - eslint-config-custom: - specifier: workspace:* - version: link:../../packages/eslint-config-custom - eslint-plugin-vue: - specifier: ^9.22.0 - version: 9.22.0(eslint@8.57.0) - npm-run-all2: - specifier: ^6.1.2 - version: 6.1.2 - tsconfig: - specifier: workspace:* - version: link:../../packages/tsconfig - typescript: - specifier: 5.5.4 - version: 5.5.4 - vite: - specifier: ^5.1.4 - version: 5.1.4(@types/node@20.11.24) - vue-tsc: - specifier: ^2.0.4 - version: 2.0.4(typescript@5.5.4) - - packages/eslint-config-custom: - devDependencies: - '@nuxtjs/eslint-config-typescript': - specifier: ^12.1.0 - version: 12.1.0(eslint@8.57.0)(typescript@5.5.4) - '@vercel/style-guide': - specifier: ^5.2.0 - version: 5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4) - '@vue/eslint-config-typescript': - specifier: ^12.0.0 - version: 12.0.0(eslint-plugin-vue@9.22.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-config-turbo: - specifier: ^2.0.0 - version: 2.0.3(eslint@8.57.0) - typescript: - specifier: 5.5.4 - version: 5.5.4 - - packages/tsconfig: - devDependencies: - '@vue/tsconfig': - specifier: ^0.5.1 - version: 0.5.1 - - packages/ui: - devDependencies: - eslint-config-custom: - specifier: workspace:* - version: link:../eslint-config-custom - tsconfig: - specifier: workspace:* - version: link:../tsconfig - vue: - specifier: ^3.4.21 - version: 3.4.21(typescript@5.5.4) - -packages: - - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - dev: true - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@antfu/utils@0.7.7: - resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==} - dev: true - - /@babel/code-frame@7.23.5: - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.23.4 - chalk: 2.4.2 - dev: true - - /@babel/compat-data@7.23.5: - resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.24.0: - resolution: {integrity: sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) - '@babel/helpers': 7.24.0 - '@babel/parser': 7.24.0 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/eslint-parser@7.22.11(@babel/core@7.24.0)(eslint@8.57.0): - resolution: {integrity: sha512-YjOYZ3j7TjV8OhLW6NCtyg8G04uStATEUe5eiLuCZaXz2VSDQ3dsAtm2D+TuQyAqNMUK2WacGo0/uma9Pein1w==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@babel/core': 7.24.0 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.23.6: - resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.23.5 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-create-class-features-plugin@7.24.0(@babel/core@7.24.0): - resolution: {integrity: sha512-QAH+vfvts51BCsNZ2PhY6HAggnlS6omLLFTsIpeqZk/MmJ6cW7tgz5yRv0fMJThcr6FmbMrENh1RgrWPTYA76g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.24.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-member-expression-to-functions@7.23.0: - resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-imports@7.22.15: - resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.0): - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - - /@babel/helper-optimise-call-expression@7.22.5: - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-plugin-utils@7.24.0: - resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-replace-supers@7.22.20(@babel/core@7.24.0): - resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - dev: true - - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-skip-transparent-expression-wrappers@7.22.5: - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-string-parser@7.23.4: - resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.24.0: - resolution: {integrity: sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.23.4: - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser@7.24.0: - resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.0 - - /@babel/plugin-proposal-decorators@7.24.0(@babel/core@7.24.0): - resolution: {integrity: sha512-LiT1RqZWeij7X+wGxCoYh3/3b8nVOX6/7BZ9wiQgAIyjoeQWdROaodJCgT+dwtbjHaz0r7bEbHJzjSbVfcOyjQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-class-features-plugin': 7.24.0(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-decorators': 7.24.0(@babel/core@7.24.0) - dev: true - - /@babel/plugin-syntax-decorators@7.24.0(@babel/core@7.24.0): - resolution: {integrity: sha512-MXW3pQCu9gUiVGzqkGqsgiINDVYXoAnrY8FYF/rmb+OfufNF0zHMpHPN4ulRrinxYT8Vk/aZJxYqOKsDECjKAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.24.0): - resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.0): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.24.0): - resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.24.0): - resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-typescript@7.23.6(@babel/core@7.24.0): - resolution: {integrity: sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.0(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.24.0) - dev: true - - /@babel/runtime@7.21.5: - resolution: {integrity: sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.13.11 - dev: true - - /@babel/standalone@7.24.0: - resolution: {integrity: sha512-yIZ/X3EAASgX/MW1Bn8iZKxCwixgYJAUaIScoZ9C6Gapw5l3eKIbtVSgO/IGldQed9QXm22yurKVWyWj5/j+SQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 - dev: true - - /@babel/traverse@7.24.0: - resolution: {integrity: sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.24.0: - resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - - /@cloudflare/kv-asset-handler@0.3.0: - resolution: {integrity: sha512-9CB/MKf/wdvbfkUdfrj+OkEwZ5b7rws0eogJ4293h+7b6KX5toPwym+VQKmILafNB9YiehqY0DlNrDcDhdWHSQ==} - dependencies: - mime: 3.0.0 - dev: true - - /@esbuild/aix-ppc64@0.19.12: - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/aix-ppc64@0.20.1: - resolution: {integrity: sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.19.12: - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.20.1: - resolution: {integrity: sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.19.12: - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.20.1: - resolution: {integrity: sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.19.12: - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.20.1: - resolution: {integrity: sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.19.12: - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.20.1: - resolution: {integrity: sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.19.12: - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.20.1: - resolution: {integrity: sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.19.12: - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.20.1: - resolution: {integrity: sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.19.12: - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.20.1: - resolution: {integrity: sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.19.12: - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.20.1: - resolution: {integrity: sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.19.12: - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.20.1: - resolution: {integrity: sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.19.12: - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.20.1: - resolution: {integrity: sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.19.12: - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.20.1: - resolution: {integrity: sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.19.12: - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.20.1: - resolution: {integrity: sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.19.12: - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.20.1: - resolution: {integrity: sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.19.12: - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.20.1: - resolution: {integrity: sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.19.12: - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.20.1: - resolution: {integrity: sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.19.12: - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.20.1: - resolution: {integrity: sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.19.12: - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.20.1: - resolution: {integrity: sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.19.12: - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.20.1: - resolution: {integrity: sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.19.12: - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.20.1: - resolution: {integrity: sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.19.12: - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.20.1: - resolution: {integrity: sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.19.12: - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.20.1: - resolution: {integrity: sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.19.12: - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.20.1: - resolution: {integrity: sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@fastify/busboy@2.1.0: - resolution: {integrity: sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==} - engines: {node: '>=14'} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.2: - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - dev: true - - /@ioredis/commands@1.2.0: - resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/source-map@0.3.5: - resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@kwsites/file-exists@1.1.1: - resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@kwsites/promise-deferred@1.1.1: - resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - dev: true - - /@mapbox/node-pre-gyp@1.0.11: - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - dependencies: - detect-libc: 2.0.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.6.0 - tar: 6.2.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true - - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true - - /@netlify/functions@2.4.1: - resolution: {integrity: sha512-sRFYBaz6dJP1MdUtk/5QNmshhg5UDmB+DUssmH6v9WUG85MrwyExEfGfJA5eClXATjXm0coTvO5nLAlyCpK7QQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@netlify/serverless-functions-api': 1.12.3 - is-promise: 4.0.0 - dev: true - - /@netlify/node-cookies@0.1.0: - resolution: {integrity: sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g==} - engines: {node: ^14.16.0 || >=16.0.0} - dev: true - - /@netlify/serverless-functions-api@1.12.3: - resolution: {integrity: sha512-g1AZ78pCvMnalZtbnViVLGfG5ufjKyKoi3plLSUtZqh0wVuMR7ZGegeZHhOoY4wRfkkETVvWfhgfcpLMbGM5Lg==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@netlify/node-cookies': 0.1.0 - urlpattern-polyfill: 8.0.2 - dev: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@npmcli/agent@2.2.1: - resolution: {integrity: sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - agent-base: 7.1.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.4 - lru-cache: 10.2.0 - socks-proxy-agent: 8.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@npmcli/fs@3.1.0: - resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.6.0 - dev: true - - /@npmcli/git@5.0.4: - resolution: {integrity: sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/promise-spawn': 7.0.1 - lru-cache: 10.2.0 - npm-pick-manifest: 9.0.0 - proc-log: 3.0.0 - promise-inflight: 1.0.1 - promise-retry: 2.0.1 - semver: 7.6.0 - which: 4.0.0 - transitivePeerDependencies: - - bluebird - dev: true - - /@npmcli/installed-package-contents@2.0.2: - resolution: {integrity: sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - npm-bundled: 3.0.0 - npm-normalize-package-bin: 3.0.1 - dev: true - - /@npmcli/node-gyp@3.0.0: - resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /@npmcli/package-json@5.0.0: - resolution: {integrity: sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/git': 5.0.4 - glob: 10.3.10 - hosted-git-info: 7.0.1 - json-parse-even-better-errors: 3.0.1 - normalize-package-data: 6.0.0 - proc-log: 3.0.0 - semver: 7.6.0 - transitivePeerDependencies: - - bluebird - dev: true - - /@npmcli/promise-spawn@7.0.1: - resolution: {integrity: sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - which: 4.0.0 - dev: true - - /@npmcli/run-script@7.0.4: - resolution: {integrity: sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/node-gyp': 3.0.0 - '@npmcli/package-json': 5.0.0 - '@npmcli/promise-spawn': 7.0.1 - node-gyp: 10.0.1 - which: 4.0.0 - transitivePeerDependencies: - - bluebird - - supports-color - dev: true - - /@nuxt/devalue@2.0.2: - resolution: {integrity: sha512-GBzP8zOc7CGWyFQS6dv1lQz8VVpz5C2yRszbXufwG/9zhStTIH50EtD87NmWbTMwXDvZLNg8GIpb1UFdH93JCA==} - dev: true - - /@nuxt/devtools-kit@1.0.8(nuxt@3.10.3)(vite@5.1.4): - resolution: {integrity: sha512-j7bNZmoAXQ1a8qv6j6zk4c/aekrxYqYVQM21o/Hy4XHCUq4fajSgpoc8mjyWJSTfpkOmuLyEzMexpDWiIVSr6A==} - peerDependencies: - nuxt: ^3.9.0 - vite: '*' - dependencies: - '@nuxt/kit': 3.10.3 - '@nuxt/schema': 3.10.3 - execa: 7.2.0 - nuxt: 3.10.3(eslint@8.57.0)(typescript@5.5.4)(vite@5.1.4) - vite: 5.1.4(@types/node@20.11.24) - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/devtools-wizard@1.0.8: - resolution: {integrity: sha512-RxyOlM7Isk5npwXwDJ/rjm9ekX5sTNG0LS0VOBMdSx+D5nlRPMRr/r9yO+9WQDyzPLClLzHaXRHBWLPlRX3IMw==} - hasBin: true - dependencies: - consola: 3.2.3 - diff: 5.2.0 - execa: 7.2.0 - global-directory: 4.0.1 - magicast: 0.3.3 - pathe: 1.1.2 - pkg-types: 1.0.3 - prompts: 2.4.2 - rc9: 2.1.1 - semver: 7.6.0 - dev: true - - /@nuxt/devtools@1.0.8(nuxt@3.10.3)(vite@5.1.4): - resolution: {integrity: sha512-o6aBFEBxc8OgVHV4OPe2g0q9tFIe9HiTxRiJnlTJ+jHvOQsBLS651ArdVtwLChf9UdMouFlpLLJ1HteZqTbtsQ==} - hasBin: true - peerDependencies: - nuxt: ^3.9.0 - vite: '*' - dependencies: - '@antfu/utils': 0.7.7 - '@nuxt/devtools-kit': 1.0.8(nuxt@3.10.3)(vite@5.1.4) - '@nuxt/devtools-wizard': 1.0.8 - '@nuxt/kit': 3.10.3 - birpc: 0.2.17 - consola: 3.2.3 - destr: 2.0.3 - error-stack-parser-es: 0.1.1 - execa: 7.2.0 - fast-glob: 3.3.2 - flatted: 3.3.1 - get-port-please: 3.1.2 - hookable: 5.5.3 - image-meta: 0.2.0 - is-installed-globally: 1.0.0 - launch-editor: 2.6.1 - local-pkg: 0.5.0 - magicast: 0.3.3 - nuxt: 3.10.3(eslint@8.57.0)(typescript@5.5.4)(vite@5.1.4) - nypm: 0.3.8 - ohash: 1.1.3 - pacote: 17.0.6 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - rc9: 2.1.1 - scule: 1.3.0 - semver: 7.6.0 - simple-git: 3.22.0 - sirv: 2.0.4 - unimport: 3.7.1(rollup@4.12.0) - vite: 5.1.4(@types/node@20.11.24) - vite-plugin-inspect: 0.8.3(@nuxt/kit@3.10.3)(vite@5.1.4) - vite-plugin-vue-inspector: 4.0.2(vite@5.1.4) - which: 3.0.1 - ws: 8.16.0 - transitivePeerDependencies: - - bluebird - - bufferutil - - rollup - - supports-color - - utf-8-validate - dev: true - - /@nuxt/kit@3.10.3: - resolution: {integrity: sha512-PUjYB9Mvx0qD9H1QZBwwtY4fLlCLET+Mm9BVqUOtXCaGoXd6u6BE4e/dGFPk2UEKkIcDGrUMSbqkHYvsEuK9NQ==} - engines: {node: ^14.18.0 || >=16.10.0} - dependencies: - '@nuxt/schema': 3.10.3 - c12: 1.9.0 - consola: 3.2.3 - defu: 6.1.4 - globby: 14.0.1 - hash-sum: 2.0.0 - ignore: 5.3.1 - jiti: 1.21.0 - knitwork: 1.0.0 - mlly: 1.6.1 - pathe: 1.1.2 - pkg-types: 1.0.3 - scule: 1.3.0 - semver: 7.6.0 - ufo: 1.4.0 - unctx: 2.3.1 - unimport: 3.7.1(rollup@4.12.0) - untyped: 1.4.2 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/schema@3.10.3: - resolution: {integrity: sha512-a4cYbeskEVBPazgAhvUGkL/j7ho/iPWMK3vCEm6dRMjSqHVEITRosrj0aMfLbRrDpTrMjlRs0ZitxiaUfE/p5Q==} - engines: {node: ^14.18.0 || >=16.10.0} - dependencies: - '@nuxt/ui-templates': 1.3.1 - consola: 3.2.3 - defu: 6.1.4 - hookable: 5.5.3 - pathe: 1.1.2 - pkg-types: 1.0.3 - scule: 1.3.0 - std-env: 3.7.0 - ufo: 1.4.0 - unimport: 3.7.1(rollup@4.12.0) - untyped: 1.4.2 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/telemetry@2.5.3: - resolution: {integrity: sha512-Ghv2MgWbJcUM9G5Dy3oQP0cJkUwEgaiuQxEF61FXJdn0a69Q4StZEP/hLF0MWPM9m6EvAwI7orxkJHM7MrmtVg==} - hasBin: true - dependencies: - '@nuxt/kit': 3.10.3 - ci-info: 4.0.0 - consola: 3.2.3 - create-require: 1.1.1 - defu: 6.1.4 - destr: 2.0.3 - dotenv: 16.4.5 - git-url-parse: 13.1.1 - is-docker: 3.0.0 - jiti: 1.21.0 - mri: 1.2.0 - nanoid: 4.0.2 - ofetch: 1.3.3 - parse-git-config: 3.0.0 - pathe: 1.1.2 - rc9: 2.1.1 - std-env: 3.7.0 - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /@nuxt/ui-templates@1.3.1: - resolution: {integrity: sha512-5gc02Pu1HycOVUWJ8aYsWeeXcSTPe8iX8+KIrhyEtEoOSkY0eMBuo0ssljB8wALuEmepv31DlYe5gpiRwkjESA==} - dev: true - - /@nuxt/vite-builder@3.10.3(eslint@8.57.0)(typescript@5.5.4)(vue@3.4.21): - resolution: {integrity: sha512-BqkbrYkEk1AVUJleofbqTRV+ltf2p1CDjGDK78zENPCgrSABlj4F4oK8rze8vmRY5qoH7kMZxgMa2dXVXCp6OA==} - engines: {node: ^14.18.0 || >=16.10.0} - peerDependencies: - vue: ^3.3.4 - dependencies: - '@nuxt/kit': 3.10.3 - '@rollup/plugin-replace': 5.0.5(rollup@4.12.0) - '@vitejs/plugin-vue': 5.0.4(vite@5.1.4)(vue@3.4.21) - '@vitejs/plugin-vue-jsx': 3.1.0(vite@5.1.4)(vue@3.4.21) - autoprefixer: 10.4.18(postcss@8.4.35) - clear: 0.1.0 - consola: 3.2.3 - cssnano: 6.0.3(postcss@8.4.35) - defu: 6.1.4 - esbuild: 0.20.1 - escape-string-regexp: 5.0.0 - estree-walker: 3.0.3 - externality: 1.0.2 - fs-extra: 11.2.0 - get-port-please: 3.1.2 - h3: 1.11.1 - knitwork: 1.0.0 - magic-string: 0.30.8 - mlly: 1.6.1 - ohash: 1.1.3 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - postcss: 8.4.35 - rollup-plugin-visualizer: 5.12.0(rollup@4.12.0) - std-env: 3.7.0 - strip-literal: 2.0.0 - ufo: 1.4.0 - unenv: 1.9.0 - unplugin: 1.8.0 - vite: 5.1.4(@types/node@20.11.24) - vite-node: 1.3.1 - vite-plugin-checker: 0.6.4(eslint@8.57.0)(typescript@5.5.4)(vite@5.1.4) - vue: 3.4.21(typescript@5.5.4) - vue-bundle-renderer: 2.0.0 - transitivePeerDependencies: - - '@types/node' - - eslint - - less - - lightningcss - - meow - - optionator - - rollup - - sass - - stylelint - - stylus - - sugarss - - supports-color - - terser - - typescript - - uWebSockets.js - - vls - - vti - - vue-tsc - dev: true - - /@nuxtjs/eslint-config-typescript@12.1.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-l2fLouDYwdAvCZEEw7wGxOBj+i8TQcHFu3zMPTLqKuv1qu6WcZIr0uztkbaa8ND1uKZ9YPqKx6UlSOjM4Le69Q==} - peerDependencies: - eslint: ^8.48.0 - dependencies: - '@nuxtjs/eslint-config': 12.0.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - '@typescript-eslint/eslint-plugin': 6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.10.0)(eslint-plugin-import@2.28.1)(eslint@8.57.0) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - eslint-plugin-vue: 9.22.0(eslint@8.57.0) - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - - typescript - dev: true - - /@nuxtjs/eslint-config@12.0.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0): - resolution: {integrity: sha512-ewenelo75x0eYEUK+9EBXjc/OopQCvdkmYmlZuoHq5kub/vtiRpyZ/autppwokpHUq8tiVyl2ejMakoiHiDTrg==} - peerDependencies: - eslint: ^8.23.0 - dependencies: - eslint: 8.57.0 - eslint-config-standard: 17.1.0(eslint-plugin-import@2.28.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.57.0) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - eslint-plugin-n: 15.7.0(eslint@8.57.0) - eslint-plugin-node: 11.1.0(eslint@8.57.0) - eslint-plugin-promise: 6.1.1(eslint@8.57.0) - eslint-plugin-unicorn: 44.0.2(eslint@8.57.0) - eslint-plugin-vue: 9.22.0(eslint@8.57.0) - local-pkg: 0.4.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /@parcel/watcher-android-arm64@2.3.0: - resolution: {integrity: sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-darwin-arm64@2.3.0: - resolution: {integrity: sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-darwin-x64@2.3.0: - resolution: {integrity: sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-freebsd-x64@2.3.0: - resolution: {integrity: sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-arm-glibc@2.3.0: - resolution: {integrity: sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ==} - engines: {node: '>= 10.0.0'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-arm64-glibc@2.3.0: - resolution: {integrity: sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-arm64-musl@2.3.0: - resolution: {integrity: sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-x64-glibc@2.3.0: - resolution: {integrity: sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-linux-x64-musl@2.3.0: - resolution: {integrity: sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-wasm@2.3.0: - resolution: {integrity: sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA==} - engines: {node: '>= 10.0.0'} - dependencies: - is-glob: 4.0.3 - micromatch: 4.0.5 - napi-wasm: 1.1.0 - dev: true - bundledDependencies: - - napi-wasm - - /@parcel/watcher-win32-arm64@2.3.0: - resolution: {integrity: sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-win32-ia32@2.3.0: - resolution: {integrity: sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow==} - engines: {node: '>= 10.0.0'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher-win32-x64@2.3.0: - resolution: {integrity: sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@parcel/watcher@2.3.0: - resolution: {integrity: sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ==} - engines: {node: '>= 10.0.0'} - dependencies: - detect-libc: 1.0.3 - is-glob: 4.0.3 - micromatch: 4.0.5 - node-addon-api: 7.0.0 - optionalDependencies: - '@parcel/watcher-android-arm64': 2.3.0 - '@parcel/watcher-darwin-arm64': 2.3.0 - '@parcel/watcher-darwin-x64': 2.3.0 - '@parcel/watcher-freebsd-x64': 2.3.0 - '@parcel/watcher-linux-arm-glibc': 2.3.0 - '@parcel/watcher-linux-arm64-glibc': 2.3.0 - '@parcel/watcher-linux-arm64-musl': 2.3.0 - '@parcel/watcher-linux-x64-glibc': 2.3.0 - '@parcel/watcher-linux-x64-musl': 2.3.0 - '@parcel/watcher-win32-arm64': 2.3.0 - '@parcel/watcher-win32-ia32': 2.3.0 - '@parcel/watcher-win32-x64': 2.3.0 - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@pkgr/utils@2.4.0: - resolution: {integrity: sha512-2OCURAmRtdlL8iUDTypMrrxfwe8frXTeXaxGsVOaYtc/wrUyk8Z/0OBetM7cdlsy7ZFWlMX72VogKeh+A4Xcjw==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dependencies: - cross-spawn: 7.0.3 - fast-glob: 3.3.2 - is-glob: 4.0.3 - open: 9.1.0 - picocolors: 1.0.0 - tslib: 2.5.0 - dev: true - - /@polka/url@1.0.0-next.24: - resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} - dev: true - - /@rollup/plugin-alias@5.1.0(rollup@4.12.0): - resolution: {integrity: sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - rollup: 4.12.0 - slash: 4.0.0 - dev: true - - /@rollup/plugin-commonjs@25.0.7(rollup@4.12.0): - resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.30.8 - rollup: 4.12.0 - dev: true - - /@rollup/plugin-inject@5.0.5(rollup@4.12.0): - resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - estree-walker: 2.0.2 - magic-string: 0.30.8 - rollup: 4.12.0 - dev: true - - /@rollup/plugin-json@6.1.0(rollup@4.12.0): - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - rollup: 4.12.0 - dev: true - - /@rollup/plugin-node-resolve@15.2.3(rollup@4.12.0): - resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-builtin-module: 3.2.1 - is-module: 1.0.0 - resolve: 1.22.8 - rollup: 4.12.0 - dev: true - - /@rollup/plugin-replace@5.0.5(rollup@4.12.0): - resolution: {integrity: sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - magic-string: 0.30.8 - rollup: 4.12.0 - dev: true - - /@rollup/plugin-terser@0.4.4(rollup@4.12.0): - resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - rollup: 4.12.0 - serialize-javascript: 6.0.1 - smob: 1.4.1 - terser: 5.26.0 - dev: true - - /@rollup/plugin-wasm@6.2.2(rollup@4.12.0): - resolution: {integrity: sha512-gpC4R1G9Ni92ZIRTexqbhX7U+9estZrbhP+9SRb0DW9xpB9g7j34r+J2hqrcW/lRI7dJaU84MxZM0Rt82tqYPQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - rollup: 4.12.0 - dev: true - - /@rollup/pluginutils@4.2.1: - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - - /@rollup/pluginutils@5.1.0(rollup@4.12.0): - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 4.12.0 - dev: true - - /@rollup/rollup-android-arm-eabi@4.12.0: - resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.12.0: - resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.12.0: - resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.12.0: - resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.12.0: - resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.12.0: - resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.12.0: - resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.12.0: - resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.12.0: - resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.12.0: - resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.12.0: - resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.12.0: - resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.12.0: - resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rushstack/eslint-patch@1.7.2: - resolution: {integrity: sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==} - dev: true - - /@sigstore/bundle@2.2.0: - resolution: {integrity: sha512-5VI58qgNs76RDrwXNhpmyN/jKpq9evV/7f1XrcqcAfvxDl5SeVY/I5Rmfe96ULAV7/FK5dge9RBKGBJPhL1WsQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/protobuf-specs': 0.3.0 - dev: true - - /@sigstore/core@1.0.0: - resolution: {integrity: sha512-dW2qjbWLRKGu6MIDUTBuJwXCnR8zivcSpf5inUzk7y84zqy/dji0/uahppoIgMoKeR+6pUZucrwHfkQQtiG9Rw==} - engines: {node: ^16.14.0 || >=18.0.0} - dev: true - - /@sigstore/protobuf-specs@0.3.0: - resolution: {integrity: sha512-zxiQ66JFOjVvP9hbhGj/F/qNdsZfkGb/dVXSanNRNuAzMlr4MC95voPUBX8//ZNnmv3uSYzdfR/JSkrgvZTGxA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /@sigstore/sign@2.2.3: - resolution: {integrity: sha512-LqlA+ffyN02yC7RKszCdMTS6bldZnIodiox+IkT8B2f8oRYXCB3LQ9roXeiEL21m64CVH1wyveYAORfD65WoSw==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.2.0 - '@sigstore/core': 1.0.0 - '@sigstore/protobuf-specs': 0.3.0 - make-fetch-happen: 13.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@sigstore/tuf@2.3.1: - resolution: {integrity: sha512-9Iv40z652td/QbV0o5n/x25H9w6IYRt2pIGbTX55yFDYlApDQn/6YZomjz6+KBx69rXHLzHcbtTS586mDdFD+Q==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/protobuf-specs': 0.3.0 - tuf-js: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@sigstore/verify@1.1.0: - resolution: {integrity: sha512-1fTqnqyTBWvV7cftUUFtDcHPdSox0N3Ub7C0lRyReYx4zZUlNTZjCV+HPy4Lre+r45dV7Qx5JLKvqqsgxuyYfg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.2.0 - '@sigstore/core': 1.0.0 - '@sigstore/protobuf-specs': 0.3.0 - dev: true - - /@sindresorhus/merge-streams@2.3.0: - resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} - engines: {node: '>=18'} - dev: true - - /@trysound/sax@0.2.0: - resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} - engines: {node: '>=10.13.0'} - dev: true - - /@tsconfig/node18@18.2.2: - resolution: {integrity: sha512-d6McJeGsuoRlwWZmVIeE8CUA27lu6jLjvv1JzqmpsytOYYbVi1tHZEnwCNVOXnj4pyLvneZlFlpXUK+X9wBWyw==} - dev: true - - /@tufjs/canonical-json@2.0.0: - resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} - engines: {node: ^16.14.0 || >=18.0.0} - dev: true - - /@tufjs/models@2.0.0: - resolution: {integrity: sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@tufjs/canonical-json': 2.0.0 - minimatch: 9.0.3 - dev: true - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/http-proxy@1.17.14: - resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} - dependencies: - '@types/node': 20.11.24 - dev: true - - /@types/json-schema@7.0.12: - resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} - dev: true - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/node@20.11.24: - resolution: {integrity: sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/normalize-package-data@2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true - - /@types/resolve@1.20.2: - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - dev: true - - /@types/semver@7.5.0: - resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} - dev: true - - /@typescript-eslint/eslint-plugin@6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 6.10.0 - '@typescript-eslint/type-utils': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.10.0 - debug: 4.3.4 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@6.10.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.10.0 - '@typescript-eslint/types': 6.10.0 - '@typescript-eslint/typescript-estree': 6.10.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.10.0 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - - /@typescript-eslint/scope-manager@6.10.0: - resolution: {integrity: sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.10.0 - '@typescript-eslint/visitor-keys': 6.10.0 - dev: true - - /@typescript-eslint/type-utils@6.10.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.10.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@6.10.0: - resolution: {integrity: sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.4): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.0 - tsutils: 3.21.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@6.10.0(typescript@5.5.4): - resolution: {integrity: sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.10.0 - '@typescript-eslint/visitor-keys': 6.10.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.0 - ts-api-utils: 1.0.2(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@6.10.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.10.0 - '@typescript-eslint/types': 6.10.0 - '@typescript-eslint/typescript-estree': 6.10.0(typescript@5.5.4) - eslint: 8.57.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@6.10.0: - resolution: {integrity: sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.10.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@unhead/dom@1.8.11: - resolution: {integrity: sha512-B5Bae4Y+6/2oDlfNJwEuf1kApyM4pmZ01VReWcVDYAdZpkD7eZZoVZnF945MluaMb6SMvGIXejcSUXTH/BOWaQ==} - dependencies: - '@unhead/schema': 1.8.11 - '@unhead/shared': 1.8.11 - dev: true - - /@unhead/schema@1.8.11: - resolution: {integrity: sha512-Aok9sZcVznJxjBRF/v2LKaeoqgYU/9kuyknYhf3M13byrdp3dLD6qcUvnLC98PrPVy7CMfOov4kXHoI/DRY5MQ==} - dependencies: - hookable: 5.5.3 - zhead: 2.2.4 - dev: true - - /@unhead/shared@1.8.11: - resolution: {integrity: sha512-Mz3pAJUq160mPXYFNUalfyEDQ0a6eRIbMlJFQ7HNy8shM+4kbeKgInoaa2EaFF8zRrhYvuLJZhyLk5kFINSmBg==} - dependencies: - '@unhead/schema': 1.8.11 - dev: true - - /@unhead/ssr@1.8.11: - resolution: {integrity: sha512-5LI+uzcNu2FQp2IOoRQSaWWPDBQNXIuOvcZfxUDKzj0GMdqHRaugPdf44Jje7SmG7RsPhOR9DHKDtuCJ65zcaw==} - dependencies: - '@unhead/schema': 1.8.11 - '@unhead/shared': 1.8.11 - dev: true - - /@unhead/vue@1.8.11(vue@3.4.21): - resolution: {integrity: sha512-yEpQaBYQsqld3m6lexMP+Vf0+j2UdY/QIO98b7v2XBm200ruZmRvI4IJDMrI8cODVwSnwQWHDLF2upXlNeQ4Qg==} - peerDependencies: - vue: '>=2.7 || >=3' - dependencies: - '@unhead/schema': 1.8.11 - '@unhead/shared': 1.8.11 - hookable: 5.5.3 - unhead: 1.8.11 - vue: 3.4.21(typescript@5.5.4) - dev: true - - /@vercel/nft@0.24.4: - resolution: {integrity: sha512-KjYAZty7boH5fi5udp6p+lNu6nawgs++pHW+3koErMgbRkkHuToGX/FwjN5clV1FcaM3udfd4zW/sUapkMgpZw==} - engines: {node: '>=16'} - hasBin: true - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - '@rollup/pluginutils': 4.2.1 - acorn: 8.11.3 - async-sema: 3.1.1 - bindings: 1.5.0 - estree-walker: 2.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - node-gyp-build: 4.7.1 - resolve-from: 5.0.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@vercel/style-guide@5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.5.4): - resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} - engines: {node: '>=16'} - peerDependencies: - '@next/eslint-plugin-next': '>=12.3.0 <15' - eslint: '>=8.48.0 <9' - prettier: '>=3.0.0 <4' - typescript: '>=4.8.0 <6' - peerDependenciesMeta: - '@next/eslint-plugin-next': - optional: true - eslint: - optional: true - prettier: - optional: true - typescript: - optional: true - dependencies: - '@babel/core': 7.24.0 - '@babel/eslint-parser': 7.22.11(@babel/core@7.24.0)(eslint@8.57.0) - '@rushstack/eslint-patch': 1.7.2 - '@typescript-eslint/eslint-plugin': 6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-config-prettier: 9.0.0(eslint@8.57.0) - eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.28.1) - eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.10.0)(eslint-plugin-import@2.28.1)(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@6.10.0)(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-jsx-a11y: 6.7.1(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.2.3)(eslint@8.57.0) - eslint-plugin-react: 7.33.2(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) - eslint-plugin-testing-library: 6.0.1(eslint@8.57.0)(typescript@5.5.4) - eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) - prettier: 3.2.5 - prettier-plugin-packagejson: 2.4.5(prettier@3.2.5) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /@vitejs/plugin-vue-jsx@3.1.0(vite@5.1.4)(vue@3.4.21): - resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.0.0 || ^5.0.0 - vue: ^3.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.24.0) - '@vue/babel-plugin-jsx': 1.2.1(@babel/core@7.24.0) - vite: 5.1.4(@types/node@20.11.24) - vue: 3.4.21(typescript@5.5.4) - transitivePeerDependencies: - - supports-color - dev: true - - /@vitejs/plugin-vue@5.0.4(vite@5.1.4)(vue@3.4.21): - resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==} - engines: {node: ^18.0.0 || >=20.0.0} - peerDependencies: - vite: ^5.0.0 - vue: ^3.2.25 - dependencies: - vite: 5.1.4(@types/node@20.11.24) - vue: 3.4.21(typescript@5.5.4) - dev: true - - /@volar/language-core@2.1.0: - resolution: {integrity: sha512-BrYEgYHx92ocpt1OUxJs2x3TAXEjpPLxsQoARb96g2GdF62xnfRQUqCNBwiU7Z3MQ/0tOAdqdHNYNmrFtx6q4A==} - dependencies: - '@volar/source-map': 2.1.0 - dev: true - - /@volar/source-map@2.1.0: - resolution: {integrity: sha512-VPyi+DTv67cvUOkUewzsOQJY3VUhjOjQxigT487z/H7tEI8ZFd5RksC5afk3JelOK+a/3Y8LRDbKmYKu1dz87g==} - dependencies: - muggle-string: 0.4.1 - dev: true - - /@volar/typescript@2.1.0: - resolution: {integrity: sha512-2cicVoW4q6eU/omqfOBv+6r9JdrF5bBelujbJhayPNKiOj/xwotSJ/DM8IeMvTZvtkOZkm6suyOCLEokLY0w2w==} - dependencies: - '@volar/language-core': 2.1.0 - path-browserify: 1.0.1 - dev: true - - /@vue-macros/common@1.8.0(vue@3.4.21): - resolution: {integrity: sha512-auDJJzE0z3uRe3867e0DsqcseKImktNf5ojCZgUKqiVxb2yTlwlgOVAYCgoep9oITqxkXQymSvFeKhedi8PhaA==} - engines: {node: '>=16.14.0'} - peerDependencies: - vue: ^2.7.0 || ^3.2.25 - peerDependenciesMeta: - vue: - optional: true - dependencies: - '@babel/types': 7.24.0 - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - '@vue/compiler-sfc': 3.4.21 - ast-kit: 0.11.2 - local-pkg: 0.4.3 - magic-string-ast: 0.3.0 - vue: 3.4.21(typescript@5.5.4) - transitivePeerDependencies: - - rollup - dev: true - - /@vue/babel-helper-vue-transform-on@1.2.1: - resolution: {integrity: sha512-jtEXim+pfyHWwvheYwUwSXm43KwQo8nhOBDyjrUITV6X2tB7lJm6n/+4sqR8137UVZZul5hBzWHdZ2uStYpyRQ==} - dev: true - - /@vue/babel-plugin-jsx@1.2.1(@babel/core@7.24.0): - resolution: {integrity: sha512-Yy9qGktktXhB39QE99So/BO2Uwm/ZG+gpL9vMg51ijRRbINvgbuhyJEi4WYmGRMx/MSTfK0xjgZ3/MyY+iLCEg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - peerDependenciesMeta: - '@babel/core': - optional: true - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.24.0) - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 - '@vue/babel-helper-vue-transform-on': 1.2.1 - '@vue/babel-plugin-resolve-type': 1.2.1(@babel/core@7.24.0) - camelcase: 6.3.0 - html-tags: 3.3.1 - svg-tags: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@vue/babel-plugin-resolve-type@1.2.1(@babel/core@7.24.0): - resolution: {integrity: sha512-IOtnI7pHunUzHS/y+EG/yPABIAp0VN8QhQ0UCS09jeMVxgAnI9qdOzO85RXdQGxq+aWCdv8/+k3W0aYO6j/8fQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/core': 7.24.0 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/parser': 7.24.0 - '@vue/compiler-sfc': 3.4.21 - dev: true - - /@vue/compiler-core@3.4.21: - resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==} - dependencies: - '@babel/parser': 7.24.0 - '@vue/shared': 3.4.21 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.0.2 - - /@vue/compiler-dom@3.4.21: - resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==} - dependencies: - '@vue/compiler-core': 3.4.21 - '@vue/shared': 3.4.21 - - /@vue/compiler-sfc@3.4.21: - resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==} - dependencies: - '@babel/parser': 7.24.0 - '@vue/compiler-core': 3.4.21 - '@vue/compiler-dom': 3.4.21 - '@vue/compiler-ssr': 3.4.21 - '@vue/shared': 3.4.21 - estree-walker: 2.0.2 - magic-string: 0.30.8 - postcss: 8.4.35 - source-map-js: 1.0.2 - - /@vue/compiler-ssr@3.4.21: - resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==} - dependencies: - '@vue/compiler-dom': 3.4.21 - '@vue/shared': 3.4.21 - - /@vue/devtools-api@6.5.1: - resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==} - dev: true - - /@vue/eslint-config-typescript@12.0.0(eslint-plugin-vue@9.22.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==} - engines: {node: ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 - eslint-plugin-vue: ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-plugin-vue: 9.22.0(eslint@8.57.0) - typescript: 5.5.4 - vue-eslint-parser: 9.3.2(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /@vue/language-core@2.0.4(typescript@5.5.4): - resolution: {integrity: sha512-IYlVEICXKRWYjRQ4JyPlXhydU/p0C7uY5LpqXyJzzJHWo44LWHZtTP3USfWNQif3VAK5QZpdZKQ5HYIeQL3BJQ==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@volar/language-core': 2.1.0 - '@vue/compiler-dom': 3.4.21 - '@vue/shared': 3.4.21 - computeds: 0.0.1 - minimatch: 9.0.3 - path-browserify: 1.0.1 - typescript: 5.5.4 - vue-template-compiler: 2.7.15 - dev: true - - /@vue/reactivity@3.4.21: - resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==} - dependencies: - '@vue/shared': 3.4.21 - - /@vue/runtime-core@3.4.21: - resolution: {integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==} - dependencies: - '@vue/reactivity': 3.4.21 - '@vue/shared': 3.4.21 - - /@vue/runtime-dom@3.4.21: - resolution: {integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==} - dependencies: - '@vue/runtime-core': 3.4.21 - '@vue/shared': 3.4.21 - csstype: 3.1.3 - - /@vue/server-renderer@3.4.21(vue@3.4.21): - resolution: {integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==} - peerDependencies: - vue: 3.4.21 - dependencies: - '@vue/compiler-ssr': 3.4.21 - '@vue/shared': 3.4.21 - vue: 3.4.21(typescript@5.5.4) - - /@vue/shared@3.4.21: - resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} - - /@vue/tsconfig@0.5.1: - resolution: {integrity: sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==} - dev: true - - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true - - /abbrev@2.0.0: - resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /agent-base@7.1.0: - resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} - engines: {node: '>= 14'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: true - - /arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - dev: true - - /archiver-utils@4.0.1: - resolution: {integrity: sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==} - engines: {node: '>= 12.0.0'} - dependencies: - glob: 8.1.0 - graceful-fs: 4.2.11 - lazystream: 1.0.1 - lodash: 4.17.21 - normalize-path: 3.0.0 - readable-stream: 3.6.2 - dev: true - - /archiver@6.0.1: - resolution: {integrity: sha512-CXGy4poOLBKptiZH//VlWdFuUC1RESbdZjGjILwBuZ73P7WkAUN0htfSfBq/7k6FRFlpu7bg4JOkj1vU9G6jcQ==} - engines: {node: '>= 12.0.0'} - dependencies: - archiver-utils: 4.0.1 - async: 3.2.5 - buffer-crc32: 0.2.13 - readable-stream: 3.6.2 - readdir-glob: 1.1.3 - tar-stream: 3.1.6 - zip-stream: 5.0.1 - dev: true - - /are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.1.3: - resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} - dependencies: - deep-equal: 2.2.1 - dev: true - - /array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} - dependencies: - call-bind: 1.0.2 - is-array-buffer: 3.0.2 - dev: true - - /array-includes@3.1.6: - resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 - is-string: 1.0.7 - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array.prototype.findlastindex@1.2.2: - resolution: {integrity: sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.1 - dev: true - - /array.prototype.flat@1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 - dev: true - - /array.prototype.flatmap@1.3.1: - resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 - dev: true - - /array.prototype.tosorted@1.1.1: - resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.1 - dev: true - - /arraybuffer.prototype.slice@1.0.1: - resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - call-bind: 1.0.2 - define-properties: 1.2.0 - get-intrinsic: 1.2.1 - is-array-buffer: 3.0.2 - is-shared-array-buffer: 1.0.2 - dev: true - - /ast-kit@0.11.2: - resolution: {integrity: sha512-Q0DjXK4ApbVoIf9GLyCo252tUH44iTnD/hiJ2TQaJeydYWSpKk0sI34+WMel8S9Wt5pbLgG02oJ+gkgX5DV3sQ==} - engines: {node: '>=16.14.0'} - dependencies: - '@babel/parser': 7.24.0 - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - pathe: 1.1.2 - transitivePeerDependencies: - - rollup - dev: true - - /ast-kit@0.9.5: - resolution: {integrity: sha512-kbL7ERlqjXubdDd+szuwdlQ1xUxEz9mCz1+m07ftNVStgwRb2RWw+U6oKo08PAvOishMxiqz1mlJyLl8yQx2Qg==} - engines: {node: '>=16.14.0'} - dependencies: - '@babel/parser': 7.24.0 - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - pathe: 1.1.2 - transitivePeerDependencies: - - rollup - dev: true - - /ast-types-flow@0.0.7: - resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} - dev: true - - /ast-walker-scope@0.5.0: - resolution: {integrity: sha512-NsyHMxBh4dmdEHjBo1/TBZvCKxffmZxRYhmclfu0PP6Aftre47jOHYaYaNqJcV0bxihxFXhDkzLHUwHc0ocd0Q==} - engines: {node: '>=16.14.0'} - dependencies: - '@babel/parser': 7.24.0 - ast-kit: 0.9.5 - transitivePeerDependencies: - - rollup - dev: true - - /async-sema@3.1.1: - resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} - dev: true - - /async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - dev: true - - /asynciterator.prototype@1.0.0: - resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} - dependencies: - has-symbols: 1.0.3 - dev: true - - /autoprefixer@10.4.18(postcss@8.4.35): - resolution: {integrity: sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001593 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: true - - /axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - dev: true - - /axobject-query@3.1.1: - resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} - dependencies: - deep-equal: 2.2.1 - dev: true - - /b4a@1.6.4: - resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /big-integer@1.6.52: - resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} - engines: {node: '>=0.6'} - dev: true - - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true - - /bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - dependencies: - file-uri-to-path: 1.0.0 - dev: true - - /birpc@0.2.17: - resolution: {integrity: sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==} - dev: true - - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: true - - /bplist-parser@0.2.0: - resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} - engines: {node: '>= 5.10.0'} - dependencies: - big-integer: 1.6.52 - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001593 - electron-to-chromium: 1.4.690 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) - dev: true - - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /builtins@5.0.1: - resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} - dependencies: - semver: 7.6.0 - dev: true - - /bundle-name@3.0.0: - resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} - engines: {node: '>=12'} - dependencies: - run-applescript: 5.0.0 - dev: true - - /bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - dependencies: - run-applescript: 7.0.0 - dev: true - - /c12@1.9.0: - resolution: {integrity: sha512-7KTCZXdIbOA2hLRQ+1KzJ15Qp9Wn58one74dkihMVp2H6EzKTa3OYBy0BSfS1CCcmxYyqeX8L02m40zjQ+dstg==} - dependencies: - chokidar: 3.6.0 - confbox: 0.1.3 - defu: 6.1.4 - dotenv: 16.4.5 - giget: 1.2.1 - jiti: 1.21.0 - mlly: 1.6.1 - ohash: 1.1.3 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - rc9: 2.1.1 - dev: true - - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true - - /cacache@18.0.2: - resolution: {integrity: sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/fs': 3.1.0 - fs-minipass: 3.0.3 - glob: 10.3.10 - lru-cache: 10.2.0 - minipass: 7.0.4 - minipass-collect: 2.0.1 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - p-map: 4.0.0 - ssri: 10.0.5 - tar: 6.2.0 - unique-filename: 3.0.0 - dev: true - - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - dependencies: - function-bind: 1.1.2 - get-intrinsic: 1.2.1 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /caniuse-api@3.0.0: - resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001593 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - dev: true - - /caniuse-lite@1.0.30001593: - resolution: {integrity: sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==} - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: true - - /ci-info@3.8.0: - resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} - engines: {node: '>=8'} - dev: true - - /ci-info@4.0.0: - resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} - engines: {node: '>=8'} - dev: true - - /citty@0.1.6: - resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - dependencies: - consola: 3.2.3 - dev: true - - /clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true - - /clear@0.1.0: - resolution: {integrity: sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==} - dev: true - - /clipboardy@3.0.0: - resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - arch: 2.2.0 - execa: 5.1.1 - is-wsl: 2.2.0 - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /cluster-key-slot@1.1.2: - resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} - engines: {node: '>=0.10.0'} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: true - - /colord@2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - dev: true - - /commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - dev: true - - /commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: true - - /commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true - - /compress-commons@5.0.1: - resolution: {integrity: sha512-MPh//1cERdLtqwO3pOFLeXtpuai0Y2WCd5AhtKxznqM7WtaMYaOEMSgn45d9D10sIHSfIKE603HlOp8OPGrvag==} - engines: {node: '>= 12.0.0'} - dependencies: - crc-32: 1.2.2 - crc32-stream: 5.0.0 - normalize-path: 3.0.0 - readable-stream: 3.6.2 - dev: true - - /computeds@0.0.1: - resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /confbox@0.1.3: - resolution: {integrity: sha512-eH3ZxAihl1PhKfpr4VfEN6/vUd87fmgb6JkldHgg/YR6aEBhW63qUDgzP2Y6WM0UumdsYp5H3kibalXAdHfbgg==} - dev: true - - /consola@3.2.3: - resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} - engines: {node: ^14.18.0 || >=16.10.0} - dev: true - - /console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cookie-es@1.0.0: - resolution: {integrity: sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==} - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /crc-32@1.2.2: - resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} - engines: {node: '>=0.8'} - hasBin: true - dev: true - - /crc32-stream@5.0.0: - resolution: {integrity: sha512-B0EPa1UK+qnpBZpG+7FgPCu0J2ETLpXq09o9BkLkEAhdB6Z61Qo4pJ3JYu0c+Qi+/SAL7QThqnzS06pmSSyZaw==} - engines: {node: '>= 12.0.0'} - dependencies: - crc-32: 1.2.2 - readable-stream: 3.6.2 - dev: true - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /crossws@0.2.4: - resolution: {integrity: sha512-DAxroI2uSOgUKLz00NX6A8U/8EE3SZHmIND+10jkVSaypvyt57J5JEOxAQOL6lQxyzi/wZbTIwssU1uy69h5Vg==} - peerDependencies: - uWebSockets.js: '*' - peerDependenciesMeta: - uWebSockets.js: - optional: true - dev: true - - /css-declaration-sorter@7.1.1(postcss@8.4.35): - resolution: {integrity: sha512-dZ3bVTEEc1vxr3Bek9vGwfB5Z6ESPULhcRvO472mfjVnj8jRcTnKO8/JTczlvxM10Myb+wBM++1MtdO76eWcaQ==} - engines: {node: ^14 || ^16 || >=18} - peerDependencies: - postcss: ^8.0.9 - dependencies: - postcss: 8.4.35 - dev: true - - /css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.1.0 - nth-check: 2.1.1 - dev: true - - /css-tree@2.2.1: - resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - dependencies: - mdn-data: 2.0.28 - source-map-js: 1.0.2 - dev: true - - /css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.0.2 - dev: true - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: true - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /cssnano-preset-default@6.0.3(postcss@8.4.35): - resolution: {integrity: sha512-4y3H370aZCkT9Ev8P4SO4bZbt+AExeKhh8wTbms/X7OLDo5E7AYUUy6YPxa/uF5Grf+AJwNcCnxKhZynJ6luBA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - css-declaration-sorter: 7.1.1(postcss@8.4.35) - cssnano-utils: 4.0.1(postcss@8.4.35) - postcss: 8.4.35 - postcss-calc: 9.0.1(postcss@8.4.35) - postcss-colormin: 6.0.2(postcss@8.4.35) - postcss-convert-values: 6.0.2(postcss@8.4.35) - postcss-discard-comments: 6.0.1(postcss@8.4.35) - postcss-discard-duplicates: 6.0.1(postcss@8.4.35) - postcss-discard-empty: 6.0.1(postcss@8.4.35) - postcss-discard-overridden: 6.0.1(postcss@8.4.35) - postcss-merge-longhand: 6.0.2(postcss@8.4.35) - postcss-merge-rules: 6.0.3(postcss@8.4.35) - postcss-minify-font-values: 6.0.1(postcss@8.4.35) - postcss-minify-gradients: 6.0.1(postcss@8.4.35) - postcss-minify-params: 6.0.2(postcss@8.4.35) - postcss-minify-selectors: 6.0.2(postcss@8.4.35) - postcss-normalize-charset: 6.0.1(postcss@8.4.35) - postcss-normalize-display-values: 6.0.1(postcss@8.4.35) - postcss-normalize-positions: 6.0.1(postcss@8.4.35) - postcss-normalize-repeat-style: 6.0.1(postcss@8.4.35) - postcss-normalize-string: 6.0.1(postcss@8.4.35) - postcss-normalize-timing-functions: 6.0.1(postcss@8.4.35) - postcss-normalize-unicode: 6.0.2(postcss@8.4.35) - postcss-normalize-url: 6.0.1(postcss@8.4.35) - postcss-normalize-whitespace: 6.0.1(postcss@8.4.35) - postcss-ordered-values: 6.0.1(postcss@8.4.35) - postcss-reduce-initial: 6.0.2(postcss@8.4.35) - postcss-reduce-transforms: 6.0.1(postcss@8.4.35) - postcss-svgo: 6.0.2(postcss@8.4.35) - postcss-unique-selectors: 6.0.2(postcss@8.4.35) - dev: true - - /cssnano-utils@4.0.1(postcss@8.4.35): - resolution: {integrity: sha512-6qQuYDqsGoiXssZ3zct6dcMxiqfT6epy7x4R0TQJadd4LWO3sPR6JH6ZByOvVLoZ6EdwPGgd7+DR1EmX3tiXQQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - dev: true - - /cssnano@6.0.3(postcss@8.4.35): - resolution: {integrity: sha512-MRq4CIj8pnyZpcI2qs6wswoYoDD1t0aL28n+41c1Ukcpm56m1h6mCexIHBGjfZfnTqtGSSCP4/fB1ovxgjBOiw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - cssnano-preset-default: 6.0.3(postcss@8.4.35) - lilconfig: 3.0.0 - postcss: 8.4.35 - dev: true - - /csso@5.0.5: - resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - dependencies: - css-tree: 2.2.1 - dev: true - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /de-indent@1.0.2: - resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /deep-equal@2.2.1: - resolution: {integrity: sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==} - dependencies: - array-buffer-byte-length: 1.0.0 - call-bind: 1.0.2 - es-get-iterator: 1.1.3 - get-intrinsic: 1.2.1 - is-arguments: 1.1.1 - is-array-buffer: 3.0.2 - is-date-object: 1.0.5 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - isarray: 2.0.5 - object-is: 1.1.5 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 - side-channel: 1.0.4 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.11 - dev: true - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true - - /default-browser-id@3.0.0: - resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} - engines: {node: '>=12'} - dependencies: - bplist-parser: 0.2.0 - untildify: 4.0.0 - dev: true - - /default-browser-id@5.0.0: - resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} - engines: {node: '>=18'} - dev: true - - /default-browser@4.0.0: - resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} - engines: {node: '>=14.16'} - dependencies: - bundle-name: 3.0.0 - default-browser-id: 3.0.0 - execa: 7.2.0 - titleize: 3.0.0 - dev: true - - /default-browser@5.2.1: - resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} - engines: {node: '>=18'} - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.0 - dev: true - - /define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - dev: true - - /define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - dev: true - - /define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} - engines: {node: '>= 0.4'} - dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - dev: true - - /defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - dev: true - - /delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: true - - /denque@2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} - engines: {node: '>=0.10'} - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true - - /destr@2.0.3: - resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} - dev: true - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true - - /detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - dev: true - - /detect-libc@1.0.3: - resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} - engines: {node: '>=0.10'} - hasBin: true - dev: true - - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - dev: true - - /detect-newline@4.0.0: - resolution: {integrity: sha512-1aXUEPdfGdzVPFpzGJJNgq9o81bGg1s09uxTWsqBlo9PI332uyJRQq13+LK/UN4JfxJbFdCXonUFQ9R/p7yCtw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /devalue@4.3.2: - resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} - dev: true - - /diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - dev: true - - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true - - /domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: true - - /domutils@3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dev: true - - /dot-prop@8.0.2: - resolution: {integrity: sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==} - engines: {node: '>=16'} - dependencies: - type-fest: 3.13.1 - dev: true - - /dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} - engines: {node: '>=12'} - dev: true - - /duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true - - /electron-to-chromium@1.4.690: - resolution: {integrity: sha512-+2OAGjUx68xElQhydpcbqH50hE8Vs2K6TkAeLhICYfndb67CVH0UsZaijmRUE3rHlIxU1u0jxwhgVe6fK3YANA==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: true - - /encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - requiresBuild: true - dependencies: - iconv-lite: 0.6.3 - dev: true - optional: true - - /enhanced-resolve@5.15.0: - resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - - /env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - dev: true - - /err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /error-stack-parser-es@0.1.1: - resolution: {integrity: sha512-g/9rfnvnagiNf+DRMHEVGuGuIBlCIMDFoTA616HaP2l9PlCjGjVhD98PNbVSJvmK4TttqT5mV5tInMhoFgi+aA==} - dev: true - - /es-abstract@1.22.1: - resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - arraybuffer.prototype.slice: 1.0.1 - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.2.1 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.5 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.10 - is-weakref: 1.0.2 - object-inspect: 1.12.3 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 - safe-array-concat: 1.0.0 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.7 - string.prototype.trimend: 1.0.6 - string.prototype.trimstart: 1.0.6 - typed-array-buffer: 1.0.0 - typed-array-byte-length: 1.0.0 - typed-array-byte-offset: 1.0.0 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.11 - dev: true - - /es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - has-symbols: 1.0.3 - is-arguments: 1.1.1 - is-map: 2.0.2 - is-set: 2.0.2 - is-string: 1.0.7 - isarray: 2.0.5 - stop-iteration-iterator: 1.0.0 - dev: true - - /es-iterator-helpers@1.0.14: - resolution: {integrity: sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==} - dependencies: - asynciterator.prototype: 1.0.0 - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-set-tostringtag: 2.0.1 - function-bind: 1.1.2 - get-intrinsic: 1.2.1 - globalthis: 1.0.3 - has-property-descriptors: 1.0.0 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.5 - iterator.prototype: 1.1.0 - safe-array-concat: 1.0.0 - dev: true - - /es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - has-tostringtag: 1.0.0 - dev: true - - /es-shim-unscopables@1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} - dependencies: - has: 1.0.3 - dev: true - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 - dev: true - - /esbuild@0.20.1: - resolution: {integrity: sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.20.1 - '@esbuild/android-arm': 0.20.1 - '@esbuild/android-arm64': 0.20.1 - '@esbuild/android-x64': 0.20.1 - '@esbuild/darwin-arm64': 0.20.1 - '@esbuild/darwin-x64': 0.20.1 - '@esbuild/freebsd-arm64': 0.20.1 - '@esbuild/freebsd-x64': 0.20.1 - '@esbuild/linux-arm': 0.20.1 - '@esbuild/linux-arm64': 0.20.1 - '@esbuild/linux-ia32': 0.20.1 - '@esbuild/linux-loong64': 0.20.1 - '@esbuild/linux-mips64el': 0.20.1 - '@esbuild/linux-ppc64': 0.20.1 - '@esbuild/linux-riscv64': 0.20.1 - '@esbuild/linux-s390x': 0.20.1 - '@esbuild/linux-x64': 0.20.1 - '@esbuild/netbsd-x64': 0.20.1 - '@esbuild/openbsd-x64': 0.20.1 - '@esbuild/sunos-x64': 0.20.1 - '@esbuild/win32-arm64': 0.20.1 - '@esbuild/win32-ia32': 0.20.1 - '@esbuild/win32-x64': 0.20.1 - dev: true - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: true - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - dev: true - - /eslint-config-prettier@9.0.0(eslint@8.57.0): - resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-config-standard@17.1.0(eslint-plugin-import@2.28.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.57.0): - resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==} - engines: {node: '>=12.0.0'} - peerDependencies: - eslint: ^8.0.1 - eslint-plugin-import: ^2.25.2 - eslint-plugin-n: '^15.0.0 || ^16.0.0 ' - eslint-plugin-promise: ^6.0.0 - dependencies: - eslint: 8.57.0 - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - eslint-plugin-n: 15.7.0(eslint@8.57.0) - eslint-plugin-promise: 6.1.1(eslint@8.57.0) - dev: true - - /eslint-config-turbo@2.0.3(eslint@8.57.0): - resolution: {integrity: sha512-D1+lNOpTFEuAgPWJfRHXHjzvAfO+0TVmORfftmYQNw+uk2UIBjhelhwERBceYFy2oFJnckHsqt69dp/zIM6/0g==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-turbo: 2.0.3(eslint@8.57.0) - dev: true - - /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.28.1): - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - dependencies: - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - dev: true - - /eslint-import-resolver-node@0.3.7: - resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-import-resolver-typescript@3.6.0(@typescript-eslint/parser@6.10.0)(eslint-plugin-import@2.28.1)(eslint@8.57.0): - resolution: {integrity: sha512-QTHR9ddNnn35RTxlaEnx2gCxqFlF2SEN0SE2d17SqwyM7YOSI2GHWRYp5BiRkObTUNYPupC/3Fq2a0PpT+EKpg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.4 - enhanced-resolve: 5.15.0 - eslint: 8.57.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.5.0 - is-core-module: 2.13.1 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.10.0)(eslint-plugin-import@2.28.1)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-es@3.0.1(eslint@8.57.0): - resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - eslint: 8.57.0 - eslint-utils: 2.1.0 - regexpp: 3.2.0 - dev: true - - /eslint-plugin-es@4.1.0(eslint@8.57.0): - resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - eslint: 8.57.0 - eslint-utils: 2.1.0 - regexpp: 3.2.0 - dev: true - - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): - resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} - engines: {node: '>=6.5.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - escape-string-regexp: 1.0.5 - eslint: 8.57.0 - ignore: 5.3.1 - dev: true - - /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0): - resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 6.10.0(eslint@8.57.0)(typescript@5.5.4) - array-includes: 3.1.6 - array.prototype.findlastindex: 1.2.2 - array.prototype.flat: 1.3.1 - array.prototype.flatmap: 1.3.1 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.0) - has: 1.0.3 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.6 - object.groupby: 1.0.1 - object.values: 1.1.6 - semver: 6.3.1 - tsconfig-paths: 3.14.2 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.10.0)(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 - eslint: ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.7.1(eslint@8.57.0): - resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.21.5 - aria-query: 5.1.3 - array-includes: 3.1.6 - array.prototype.flatmap: 1.3.1 - ast-types-flow: 0.0.7 - axe-core: 4.7.0 - axobject-query: 3.1.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 8.57.0 - has: 1.0.3 - jsx-ast-utils: 3.3.3 - language-tags: 1.0.5 - minimatch: 3.1.2 - object.entries: 1.1.6 - object.fromentries: 2.0.6 - semver: 6.3.1 - dev: true - - /eslint-plugin-n@15.7.0(eslint@8.57.0): - resolution: {integrity: sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==} - engines: {node: '>=12.22.0'} - peerDependencies: - eslint: '>=7.0.0' - dependencies: - builtins: 5.0.1 - eslint: 8.57.0 - eslint-plugin-es: 4.1.0(eslint@8.57.0) - eslint-utils: 3.0.0(eslint@8.57.0) - ignore: 5.3.1 - is-core-module: 2.13.1 - minimatch: 3.1.2 - resolve: 1.22.8 - semver: 7.6.0 - dev: true - - /eslint-plugin-node@11.1.0(eslint@8.57.0): - resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=5.16.0' - dependencies: - eslint: 8.57.0 - eslint-plugin-es: 3.0.1(eslint@8.57.0) - eslint-utils: 2.1.0 - ignore: 5.3.1 - minimatch: 3.1.2 - resolve: 1.22.8 - semver: 6.3.1 - dev: true - - /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.2.3)(eslint@8.57.0): - resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} - peerDependencies: - eslint: '>=7' - eslint-plugin-jest: '>=25' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - dependencies: - eslint: 8.57.0 - eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@6.10.0)(eslint@8.57.0)(typescript@5.5.4) - dev: true - - /eslint-plugin-promise@6.1.1(eslint@8.57.0): - resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react@7.33.2(eslint@8.57.0): - resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.6 - array.prototype.flatmap: 1.3.1 - array.prototype.tosorted: 1.1.1 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.14 - eslint: 8.57.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.3 - minimatch: 3.1.2 - object.entries: 1.1.6 - object.fromentries: 2.0.6 - object.hasown: 1.1.2 - object.values: 1.1.6 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.8 - dev: true - - /eslint-plugin-testing-library@6.0.1(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-CEYtjpcF3hAaQtYsTZqciR7s5z+T0LCMTwJeW+pz6kBnGtc866wAKmhaiK2Gsjc2jWNP7Gt6zhNr2DE1ZW4e+g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true - - /eslint-plugin-turbo@2.0.3(eslint@8.57.0): - resolution: {integrity: sha512-mplP4nYaRvtTNuwF5QTLYKLu0/8LTRsHPgX4ARhaof+QZI2ttglONe1/iJpKB4pg0KqFp7WHziKoJL+s0+CJ1w==} - peerDependencies: - eslint: '>6.6.0' - dependencies: - dotenv: 16.0.3 - eslint: 8.57.0 - dev: true - - /eslint-plugin-unicorn@44.0.2(eslint@8.57.0): - resolution: {integrity: sha512-GLIDX1wmeEqpGaKcnMcqRvMVsoabeF0Ton0EX4Th5u6Kmf7RM9WBl705AXFEsns56ESkEs0uyelLuUTvz9Tr0w==} - engines: {node: '>=14.18'} - peerDependencies: - eslint: '>=8.23.1' - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - ci-info: 3.8.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - eslint-utils: 3.0.0(eslint@8.57.0) - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - safe-regex: 2.1.1 - semver: 7.6.0 - strip-indent: 3.0.0 - dev: true - - /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.44.0' - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - ci-info: 3.8.0 - clean-regexp: 1.0.0 - eslint: 8.57.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.6.0 - strip-indent: 3.0.0 - dev: true - - /eslint-plugin-vue@9.22.0(eslint@8.57.0): - resolution: {integrity: sha512-7wCXv5zuVnBtZE/74z4yZ0CM8AjH6bk4MQGm7hZjUC2DBppKU5ioeOk5LGSg/s9a1ZJnIsdPLJpXnu1Rc+cVHg==} - engines: {node: ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - eslint: 8.57.0 - natural-compare: 1.4.0 - nth-check: 2.1.1 - postcss-selector-parser: 6.0.15 - semver: 7.6.0 - vue-eslint-parser: 9.4.2(eslint@8.57.0) - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-utils@2.1.0: - resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} - engines: {node: '>=6'} - dependencies: - eslint-visitor-keys: 1.3.0 - dev: true - - /eslint-utils@3.0.0(eslint@8.57.0): - resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} - engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} - peerDependencies: - eslint: '>=5' - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - dev: true - - /eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - - /estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - dependencies: - '@types/estree': 1.0.5 - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /execa@7.2.0: - resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 4.3.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 - dev: true - - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - dev: true - - /exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - dev: true - - /externality@1.0.2: - resolution: {integrity: sha512-LyExtJWKxtgVzmgtEHyQtLFpw1KFhQphF9nTG8TpAIVkiI/xQ3FJh75tRFLYl4hkn7BNIIdLJInuDAavX35pMw==} - dependencies: - enhanced-resolve: 5.15.0 - mlly: 1.6.1 - pathe: 1.1.2 - ufo: 1.4.0 - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-fifo@1.3.2: - resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: true - - /file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: true - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: true - - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /fs-minipass@3.0.3: - resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.0.4 - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /function.prototype.name@1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} - dependencies: - function-bind: 1.1.2 - has: 1.0.3 - has-proto: 1.0.1 - has-symbols: 1.0.3 - dev: true - - /get-port-please@3.1.2: - resolution: {integrity: sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==} - dev: true - - /get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - dev: true - - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - dev: true - - /get-tsconfig@4.5.0: - resolution: {integrity: sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==} - dev: true - - /giget@1.2.1: - resolution: {integrity: sha512-4VG22mopWtIeHwogGSy1FViXVo0YT+m6BrqZfz0JJFwbSsePsCdOzdLIIli5BtMp7Xe8f/o2OmBpQX2NBOC24g==} - hasBin: true - dependencies: - citty: 0.1.6 - consola: 3.2.3 - defu: 6.1.4 - node-fetch-native: 1.6.2 - nypm: 0.3.8 - ohash: 1.1.3 - pathe: 1.1.2 - tar: 6.2.0 - dev: true - - /git-config-path@2.0.0: - resolution: {integrity: sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==} - engines: {node: '>=4'} - dev: true - - /git-hooks-list@3.1.0: - resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} - dev: true - - /git-up@7.0.0: - resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} - dependencies: - is-ssh: 1.4.0 - parse-url: 8.1.0 - dev: true - - /git-url-parse@13.1.1: - resolution: {integrity: sha512-PCFJyeSSdtnbfhSNRw9Wk96dDCNx+sogTe4YNXeXSJxt7xz5hvXekuRn9JX7m+Mf4OscCu8h+mtAl3+h5Fo8lQ==} - dependencies: - git-up: 7.0.0 - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - dev: true - - /global-directory@4.0.1: - resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} - engines: {node: '>=18'} - dependencies: - ini: 4.1.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.0 - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - - /globby@14.0.1: - resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==} - engines: {node: '>=18'} - dependencies: - '@sindresorhus/merge-streams': 2.3.0 - fast-glob: 3.3.2 - ignore: 5.3.1 - path-type: 5.0.0 - slash: 5.1.0 - unicorn-magic: 0.1.0 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.1 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /gzip-size@7.0.0: - resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - duplexer: 0.1.2 - dev: true - - /h3@1.11.1: - resolution: {integrity: sha512-AbaH6IDnZN6nmbnJOH72y3c5Wwh9P97soSVdGSBbcDACRdkC0FEWf25pzx4f/NuOCK6quHmW18yF2Wx+G4Zi1A==} - dependencies: - cookie-es: 1.0.0 - crossws: 0.2.4 - defu: 6.1.4 - destr: 2.0.3 - iron-webcrypto: 1.0.0 - ohash: 1.1.3 - radix3: 1.1.0 - ufo: 1.4.0 - uncrypto: 0.1.3 - unenv: 1.9.0 - transitivePeerDependencies: - - uWebSockets.js - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} - dependencies: - get-intrinsic: 1.2.1 - dev: true - - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: true - - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.2 - dev: true - - /hash-sum@2.0.0: - resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} - dev: true - - /hasown@2.0.1: - resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true - - /hookable@5.5.3: - resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} - dev: true - - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /hosted-git-info@7.0.1: - resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - lru-cache: 10.2.0 - dev: true - - /html-tags@3.3.1: - resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} - engines: {node: '>=8'} - dev: true - - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: true - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - - /http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /http-shutdown@1.2.2: - resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent@7.0.4: - resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /httpxy@0.1.5: - resolution: {integrity: sha512-hqLDO+rfststuyEUTWObQK6zHEEmZ/kaIP2/zclGGZn6X8h/ESTWg+WKecQ/e5k4nPswjzZD+q2VqZIbr15CoQ==} - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - dev: true - - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - dev: true - - /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - requiresBuild: true - dependencies: - safer-buffer: 2.1.2 - dev: true - optional: true - - /ignore-walk@6.0.4: - resolution: {integrity: sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minimatch: 9.0.3 - dev: true - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /image-meta@0.2.0: - resolution: {integrity: sha512-ZBGjl0ZMEMeOC3Ns0wUF/5UdUmr3qQhBSCniT0LxOgGGIRHiNFOkMtIHB7EOznRU47V2AxPgiVP+s+0/UCU0Hg==} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - - /ini@4.1.1: - resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - side-channel: 1.0.4 - dev: true - - /ioredis@5.3.2: - resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==} - engines: {node: '>=12.22.0'} - dependencies: - '@ioredis/commands': 1.2.0 - cluster-key-slot: 1.1.2 - debug: 4.3.4 - denque: 2.1.0 - lodash.defaults: 4.2.0 - lodash.isarguments: 3.1.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - dev: true - - /iron-webcrypto@1.0.0: - resolution: {integrity: sha512-anOK1Mktt8U1Xi7fCM3RELTuYbnFikQY5VtrDj7kPgpejV7d43tWKhzgioO0zpkazLEL/j/iayRqnJhrGfqUsg==} - dev: true - - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-typed-array: 1.1.10 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.1 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.2 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - dependencies: - is-docker: 3.0.0 - dev: true - - /is-installed-globally@1.0.0: - resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} - engines: {node: '>=18'} - dependencies: - global-directory: 4.0.1 - is-path-inside: 4.0.0 - dev: true - - /is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - dev: true - - /is-map@2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} - dev: true - - /is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - dev: true - - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-path-inside@4.0.0: - resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} - engines: {node: '>=12'} - dev: true - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: true - - /is-primitive@3.0.1: - resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==} - engines: {node: '>=0.10.0'} - dev: true - - /is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - dev: true - - /is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - dependencies: - '@types/estree': 1.0.5 - dev: true - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-set@2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - dev: true - - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.2 - dev: true - - /is-ssh@1.4.0: - resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==} - dependencies: - protocols: 2.0.1 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array@1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: true - - /is-weakmap@2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} - dev: true - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.2 - dev: true - - /is-weakset@2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - dev: true - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - - /is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} - dependencies: - is-inside-container: 1.0.0 - dev: true - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /isexe@3.1.1: - resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} - engines: {node: '>=16'} - dev: true - - /iterator.prototype@1.1.0: - resolution: {integrity: sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==} - dependencies: - define-properties: 1.2.0 - get-intrinsic: 1.2.1 - has-symbols: 1.0.3 - has-tostringtag: 1.0.0 - reflect.getprototypeof: 1.0.3 - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jiti@1.21.0: - resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} - hasBin: true - dev: true - - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-tokens@8.0.3: - resolution: {integrity: sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==} - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-parse-even-better-errors@3.0.1: - resolution: {integrity: sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonc-parser@3.2.1: - resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - dev: true - - /jsx-ast-utils@3.3.3: - resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.6 - object.assign: 4.1.4 - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /klona@2.0.6: - resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} - engines: {node: '>= 8'} - dev: true - - /knitwork@1.0.0: - resolution: {integrity: sha512-dWl0Dbjm6Xm+kDxhPQJsCBTxrJzuGl0aP9rhr+TG8D3l+GL90N8O8lYUi7dTSAN2uuDqCtNgb6aEuQH5wsiV8Q==} - dev: true - - /kolorist@1.8.0: - resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - dev: true - - /language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} - dev: true - - /language-tags@1.0.5: - resolution: {integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==} - dependencies: - language-subtag-registry: 0.3.22 - dev: true - - /launch-editor@2.6.1: - resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} - dependencies: - picocolors: 1.0.0 - shell-quote: 1.8.1 - dev: true - - /lazystream@1.0.1: - resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} - engines: {node: '>= 0.6.3'} - dependencies: - readable-stream: 2.3.8 - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} - engines: {node: '>=14'} - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /listhen@1.5.5: - resolution: {integrity: sha512-LXe8Xlyh3gnxdv4tSjTjscD1vpr/2PRpzq8YIaMJgyKzRG8wdISlWVWnGThJfHnlJ6hmLt2wq1yeeix0TEbuoA==} - hasBin: true - dependencies: - '@parcel/watcher': 2.3.0 - '@parcel/watcher-wasm': 2.3.0 - citty: 0.1.6 - clipboardy: 3.0.0 - consola: 3.2.3 - defu: 6.1.4 - get-port-please: 3.1.2 - h3: 1.11.1 - http-shutdown: 1.2.2 - jiti: 1.21.0 - mlly: 1.6.1 - node-forge: 1.3.1 - pathe: 1.1.2 - std-env: 3.7.0 - ufo: 1.4.0 - untun: 0.1.3 - uqr: 0.1.2 - transitivePeerDependencies: - - uWebSockets.js - dev: true - - /local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} - engines: {node: '>=14'} - dev: true - - /local-pkg@0.5.0: - resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} - engines: {node: '>=14'} - dependencies: - mlly: 1.6.1 - pkg-types: 1.0.3 - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - dev: true - - /lodash.isarguments@3.1.0: - resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - dev: true - - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - dev: true - - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /magic-string-ast@0.3.0: - resolution: {integrity: sha512-0shqecEPgdFpnI3AP90epXyxZy9g6CRZ+SZ7BcqFwYmtFEnZ1jpevcV5HoyVnlDS9gCnc1UIg3Rsvp3Ci7r8OA==} - engines: {node: '>=16.14.0'} - dependencies: - magic-string: 0.30.8 - dev: true - - /magic-string@0.30.8: - resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - - /magicast@0.3.3: - resolution: {integrity: sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw==} - dependencies: - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 - source-map-js: 1.0.2 - dev: true - - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.1 - dev: true - - /make-fetch-happen@13.0.0: - resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@npmcli/agent': 2.2.1 - cacache: 18.0.2 - http-cache-semantics: 4.1.1 - is-lambda: 1.0.1 - minipass: 7.0.4 - minipass-fetch: 3.0.4 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.3 - promise-retry: 2.0.1 - ssri: 10.0.5 - transitivePeerDependencies: - - supports-color - dev: true - - /mdn-data@2.0.28: - resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} - dev: true - - /mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - dev: true - - /memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /mime@3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true - - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - - /minipass-collect@2.0.1: - resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - minipass: 7.0.4 - dev: true - - /minipass-fetch@3.0.4: - resolution: {integrity: sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.0.4 - minipass-sized: 1.0.3 - minizlib: 2.1.2 - optionalDependencies: - encoding: 0.1.13 - dev: true - - /minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass-json-stream@1.0.1: - resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} - dependencies: - jsonparse: 1.3.1 - minipass: 3.3.6 - dev: true - - /minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.6 - dev: true - - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: true - - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - dev: true - - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: true - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /mlly@1.6.1: - resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} - dependencies: - acorn: 8.11.3 - pathe: 1.1.2 - pkg-types: 1.0.3 - ufo: 1.4.0 - dev: true - - /mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - dev: true - - /mrmime@2.0.0: - resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} - engines: {node: '>=10'} - dev: true - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /muggle-string@0.4.1: - resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - /nanoid@4.0.2: - resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} - engines: {node: ^14 || ^16 || >=18} - hasBin: true - dev: true - - /napi-wasm@1.1.0: - resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==} - dev: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true - - /nitropack@2.8.1: - resolution: {integrity: sha512-pODv2kEEzZSDQR+1UMXbGyNgMedUDq/qUomtiAnQKQvLy52VGlecXO1xDfH3i0kP1yKEcKTnWsx1TAF5gHM7xQ==} - engines: {node: ^16.11.0 || >=17.0.0} - hasBin: true - peerDependencies: - xml2js: ^0.6.2 - peerDependenciesMeta: - xml2js: - optional: true - dependencies: - '@cloudflare/kv-asset-handler': 0.3.0 - '@netlify/functions': 2.4.1 - '@rollup/plugin-alias': 5.1.0(rollup@4.12.0) - '@rollup/plugin-commonjs': 25.0.7(rollup@4.12.0) - '@rollup/plugin-inject': 5.0.5(rollup@4.12.0) - '@rollup/plugin-json': 6.1.0(rollup@4.12.0) - '@rollup/plugin-node-resolve': 15.2.3(rollup@4.12.0) - '@rollup/plugin-replace': 5.0.5(rollup@4.12.0) - '@rollup/plugin-terser': 0.4.4(rollup@4.12.0) - '@rollup/plugin-wasm': 6.2.2(rollup@4.12.0) - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - '@types/http-proxy': 1.17.14 - '@vercel/nft': 0.24.4 - archiver: 6.0.1 - c12: 1.9.0 - chalk: 5.3.0 - chokidar: 3.6.0 - citty: 0.1.6 - consola: 3.2.3 - cookie-es: 1.0.0 - defu: 6.1.4 - destr: 2.0.3 - dot-prop: 8.0.2 - esbuild: 0.19.12 - escape-string-regexp: 5.0.0 - estree-walker: 3.0.3 - etag: 1.8.1 - fs-extra: 11.2.0 - globby: 14.0.1 - gzip-size: 7.0.0 - h3: 1.11.1 - hookable: 5.5.3 - httpxy: 0.1.5 - is-primitive: 3.0.1 - jiti: 1.21.0 - klona: 2.0.6 - knitwork: 1.0.0 - listhen: 1.5.5 - magic-string: 0.30.8 - mime: 3.0.0 - mlly: 1.6.1 - mri: 1.2.0 - node-fetch-native: 1.6.2 - ofetch: 1.3.3 - ohash: 1.1.3 - openapi-typescript: 6.7.3 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - pretty-bytes: 6.1.1 - radix3: 1.1.0 - rollup: 4.12.0 - rollup-plugin-visualizer: 5.12.0(rollup@4.12.0) - scule: 1.3.0 - semver: 7.6.0 - serve-placeholder: 2.0.1 - serve-static: 1.15.0 - std-env: 3.7.0 - ufo: 1.4.0 - uncrypto: 0.1.3 - unctx: 2.3.1 - unenv: 1.9.0 - unimport: 3.7.1(rollup@4.12.0) - unstorage: 1.10.1 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/kv' - - encoding - - idb-keyval - - supports-color - - uWebSockets.js - dev: true - - /node-addon-api@7.0.0: - resolution: {integrity: sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==} - dev: true - - /node-fetch-native@1.6.2: - resolution: {integrity: sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==} - dev: true - - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true - - /node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} - engines: {node: '>= 6.13.0'} - dev: true - - /node-gyp-build@4.7.1: - resolution: {integrity: sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==} - hasBin: true - dev: true - - /node-gyp@10.0.1: - resolution: {integrity: sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==} - engines: {node: ^16.14.0 || >=18.0.0} - hasBin: true - dependencies: - env-paths: 2.2.1 - exponential-backoff: 3.1.1 - glob: 10.3.10 - graceful-fs: 4.2.11 - make-fetch-happen: 13.0.0 - nopt: 7.2.0 - proc-log: 3.0.0 - semver: 7.6.0 - tar: 6.2.0 - which: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true - - /nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: true - - /nopt@7.2.0: - resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - abbrev: 2.0.0 - dev: true - - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-package-data@6.0.0: - resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - hosted-git-info: 7.0.1 - is-core-module: 2.13.1 - semver: 7.6.0 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-bundled@3.0.0: - resolution: {integrity: sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - npm-normalize-package-bin: 3.0.1 - dev: true - - /npm-install-checks@6.3.0: - resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - semver: 7.6.0 - dev: true - - /npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /npm-package-arg@11.0.1: - resolution: {integrity: sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - hosted-git-info: 7.0.1 - proc-log: 3.0.0 - semver: 7.6.0 - validate-npm-package-name: 5.0.0 - dev: true - - /npm-packlist@8.0.2: - resolution: {integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - ignore-walk: 6.0.4 - dev: true - - /npm-pick-manifest@9.0.0: - resolution: {integrity: sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - npm-install-checks: 6.3.0 - npm-normalize-package-bin: 3.0.1 - npm-package-arg: 11.0.1 - semver: 7.6.0 - dev: true - - /npm-registry-fetch@16.1.0: - resolution: {integrity: sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - make-fetch-happen: 13.0.0 - minipass: 7.0.4 - minipass-fetch: 3.0.4 - minipass-json-stream: 1.0.1 - minizlib: 2.1.2 - npm-package-arg: 11.0.1 - proc-log: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /npm-run-all2@6.1.2: - resolution: {integrity: sha512-WwwnS8Ft+RpXve6T2EIEVpFLSqN+ORHRvgNk3H9N62SZXjmzKoRhMFg3I17TK3oMaAEr+XFbRirWS2Fn3BCPSg==} - engines: {node: ^14.18.0 || >=16.0.0, npm: '>= 8'} - hasBin: true - dependencies: - ansi-styles: 6.2.1 - cross-spawn: 7.0.3 - memorystream: 0.3.1 - minimatch: 9.0.3 - pidtree: 0.6.0 - read-package-json-fast: 3.0.2 - shell-quote: 1.8.1 - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - - /npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: true - - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - dependencies: - boolbase: 1.0.0 - dev: true - - /nuxi@3.10.1: - resolution: {integrity: sha512-ZNt858+FOZDIiKKFJkXO7uJAnALytDdn1XbLgtZAqbtWNMayHbOnWcnxh+WSOE4H9uOi2+loWXEqKElmNWLgcQ==} - engines: {node: ^14.18.0 || >=16.10.0} - hasBin: true - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /nuxt@3.10.3(eslint@8.57.0)(typescript@5.5.4)(vite@5.1.4): - resolution: {integrity: sha512-NchGNiiz9g/ErJAb462W/lpX2NqcXYb9hugySKWvLXNdrjeAPiJ2/7mhgwUSiZA9MpjuQg3saiEajr1zlRIOCg==} - engines: {node: ^14.18.0 || >=16.10.0} - hasBin: true - peerDependencies: - '@parcel/watcher': ^2.1.0 - '@types/node': ^14.18.0 || >=16.10.0 - peerDependenciesMeta: - '@parcel/watcher': - optional: true - '@types/node': - optional: true - dependencies: - '@nuxt/devalue': 2.0.2 - '@nuxt/devtools': 1.0.8(nuxt@3.10.3)(vite@5.1.4) - '@nuxt/kit': 3.10.3 - '@nuxt/schema': 3.10.3 - '@nuxt/telemetry': 2.5.3 - '@nuxt/ui-templates': 1.3.1 - '@nuxt/vite-builder': 3.10.3(eslint@8.57.0)(typescript@5.5.4)(vue@3.4.21) - '@unhead/dom': 1.8.11 - '@unhead/ssr': 1.8.11 - '@unhead/vue': 1.8.11(vue@3.4.21) - '@vue/shared': 3.4.21 - acorn: 8.11.3 - c12: 1.9.0 - chokidar: 3.6.0 - cookie-es: 1.0.0 - defu: 6.1.4 - destr: 2.0.3 - devalue: 4.3.2 - esbuild: 0.20.1 - escape-string-regexp: 5.0.0 - estree-walker: 3.0.3 - fs-extra: 11.2.0 - globby: 14.0.1 - h3: 1.11.1 - hookable: 5.5.3 - jiti: 1.21.0 - klona: 2.0.6 - knitwork: 1.0.0 - magic-string: 0.30.8 - mlly: 1.6.1 - nitropack: 2.8.1 - nuxi: 3.10.1 - nypm: 0.3.8 - ofetch: 1.3.3 - ohash: 1.1.3 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.0.3 - radix3: 1.1.0 - scule: 1.3.0 - std-env: 3.7.0 - strip-literal: 2.0.0 - ufo: 1.4.0 - ultrahtml: 1.5.3 - uncrypto: 0.1.3 - unctx: 2.3.1 - unenv: 1.9.0 - unimport: 3.7.1(rollup@4.12.0) - unplugin: 1.8.0 - unplugin-vue-router: 0.7.0(vue-router@4.3.0)(vue@3.4.21) - untyped: 1.4.2 - vue: 3.4.21(typescript@5.5.4) - vue-bundle-renderer: 2.0.0 - vue-devtools-stub: 0.1.0 - vue-router: 4.3.0(vue@3.4.21) - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/kv' - - bluebird - - bufferutil - - encoding - - eslint - - idb-keyval - - less - - lightningcss - - meow - - optionator - - rollup - - sass - - stylelint - - stylus - - sugarss - - supports-color - - terser - - typescript - - uWebSockets.js - - utf-8-validate - - vite - - vls - - vti - - vue-tsc - - xml2js - dev: true - - /nypm@0.3.8: - resolution: {integrity: sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==} - engines: {node: ^14.16.0 || >=16.10.0} - hasBin: true - dependencies: - citty: 0.1.6 - consola: 3.2.3 - execa: 8.0.1 - pathe: 1.1.2 - ufo: 1.4.0 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: true - - /object-is@1.1.5: - resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - dev: true - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.6: - resolution: {integrity: sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - dev: true - - /object.fromentries@2.0.6: - resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - dev: true - - /object.groupby@1.0.1: - resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 - dev: true - - /object.hasown@1.1.2: - resolution: {integrity: sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==} - dependencies: - define-properties: 1.2.0 - es-abstract: 1.22.1 - dev: true - - /object.values@1.1.6: - resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - dev: true - - /ofetch@1.3.3: - resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==} - dependencies: - destr: 2.0.3 - node-fetch-native: 1.6.2 - ufo: 1.4.0 - dev: true - - /ohash@1.1.3: - resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} - dev: true - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - - /open@10.0.4: - resolution: {integrity: sha512-oujJ/FFr7ra6/7gJuQ4ZJJ8Gf2VHM0J3J/W7IvH++zaqEzacWVxzK++NiVY5NLHTTj7u/jNH5H3Ei9biL31Lng==} - engines: {node: '>=18'} - dependencies: - default-browser: 5.2.1 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 3.1.0 - dev: true - - /open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - - /open@9.1.0: - resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} - engines: {node: '>=14.16'} - dependencies: - default-browser: 4.0.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 2.2.0 - dev: true - - /openapi-typescript@6.7.3: - resolution: {integrity: sha512-es3mGcDXV6TKPo6n3aohzHm0qxhLyR39MhF6mkD1FwFGjhxnqMqfSIgM0eCpInZvqatve4CxmXcMZw3jnnsaXw==} - hasBin: true - dependencies: - ansi-colors: 4.1.3 - fast-glob: 3.3.2 - js-yaml: 4.1.0 - supports-color: 9.4.0 - undici: 5.28.2 - yargs-parser: 21.1.1 - dev: true - - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /pacote@17.0.6: - resolution: {integrity: sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==} - engines: {node: ^16.14.0 || >=18.0.0} - hasBin: true - dependencies: - '@npmcli/git': 5.0.4 - '@npmcli/installed-package-contents': 2.0.2 - '@npmcli/promise-spawn': 7.0.1 - '@npmcli/run-script': 7.0.4 - cacache: 18.0.2 - fs-minipass: 3.0.3 - minipass: 7.0.4 - npm-package-arg: 11.0.1 - npm-packlist: 8.0.2 - npm-pick-manifest: 9.0.0 - npm-registry-fetch: 16.1.0 - proc-log: 3.0.0 - promise-retry: 2.0.1 - read-package-json: 7.0.0 - read-package-json-fast: 3.0.2 - sigstore: 2.2.2 - ssri: 10.0.5 - tar: 6.2.0 - transitivePeerDependencies: - - bluebird - - supports-color - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-git-config@3.0.0: - resolution: {integrity: sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA==} - engines: {node: '>=8'} - dependencies: - git-config-path: 2.0.0 - ini: 1.3.8 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.23.5 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse-path@7.0.0: - resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==} - dependencies: - protocols: 2.0.1 - dev: true - - /parse-url@8.1.0: - resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} - dependencies: - parse-path: 7.0.0 - dev: true - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: true - - /path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /path-type@5.0.0: - resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} - engines: {node: '>=12'} - dev: true - - /pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - dev: true - - /perfect-debounce@1.0.0: - resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} - dev: true - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - dev: true - - /pkg-types@1.0.3: - resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} - dependencies: - jsonc-parser: 3.2.1 - mlly: 1.6.1 - pathe: 1.1.2 - dev: true - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /postcss-calc@9.0.1(postcss@8.4.35): - resolution: {integrity: sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.2.2 - dependencies: - postcss: 8.4.35 - postcss-selector-parser: 6.0.15 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-colormin@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-TXKOxs9LWcdYo5cgmcSHPkyrLAh86hX1ijmyy6J8SbOhyv6ua053M3ZAM/0j44UsnQNIWdl8gb5L7xX2htKeLw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - browserslist: 4.23.0 - caniuse-api: 3.0.0 - colord: 2.9.3 - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-convert-values@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-aeBmaTnGQ+NUSVQT8aY0sKyAD/BaLJenEKZ03YK0JnDE1w1Rr8XShoxdal2V2H26xTJKr3v5haByOhJuyT4UYw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - browserslist: 4.23.0 - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-discard-comments@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-f1KYNPtqYLUeZGCHQPKzzFtsHaRuECe6jLakf/RjSRqvF5XHLZnM2+fXLhb8Qh/HBFHs3M4cSLb1k3B899RYIg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - dev: true - - /postcss-discard-duplicates@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-1hvUs76HLYR8zkScbwyJ8oJEugfPV+WchpnA+26fpJ7Smzs51CzGBHC32RS03psuX/2l0l0UKh2StzNxOrKCYg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - dev: true - - /postcss-discard-empty@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-yitcmKwmVWtNsrrRqGJ7/C0YRy53i0mjexBDQ9zYxDwTWVBgbU4+C9jIZLmQlTDT9zhml+u0OMFJh8+31krmOg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - dev: true - - /postcss-discard-overridden@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-qs0ehZMMZpSESbRkw1+inkf51kak6OOzNRaoLd/U7Fatp0aN2HQ1rxGOrJvYcRAN9VpX8kUF13R2ofn8OlvFVA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - dev: true - - /postcss-merge-longhand@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-+yfVB7gEM8SrCo9w2lCApKIEzrTKl5yS1F4yGhV3kSim6JzbfLGJyhR1B6X+6vOT0U33Mgx7iv4X9MVWuaSAfw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - stylehacks: 6.0.2(postcss@8.4.35) - dev: true - - /postcss-merge-rules@6.0.3(postcss@8.4.35): - resolution: {integrity: sha512-yfkDqSHGohy8sGYIJwBmIGDv4K4/WrJPX355XrxQb/CSsT4Kc/RxDi6akqn5s9bap85AWgv21ArcUWwWdGNSHA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - browserslist: 4.23.0 - caniuse-api: 3.0.0 - cssnano-utils: 4.0.1(postcss@8.4.35) - postcss: 8.4.35 - postcss-selector-parser: 6.0.15 - dev: true - - /postcss-minify-font-values@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-tIwmF1zUPoN6xOtA/2FgVk1ZKrLcCvE0dpZLtzyyte0j9zUeB8RTbCqrHZGjJlxOvNWKMYtunLrrl7HPOiR46w==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-minify-gradients@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-M1RJWVjd6IOLPl1hYiOd5HQHgpp6cvJVLrieQYS9y07Yo8itAr6jaekzJphaJFR0tcg4kRewCk3kna9uHBxn/w==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - colord: 2.9.3 - cssnano-utils: 4.0.1(postcss@8.4.35) - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-minify-params@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-zwQtbrPEBDj+ApELZ6QylLf2/c5zmASoOuA4DzolyVGdV38iR2I5QRMsZcHkcdkZzxpN8RS4cN7LPskOkTwTZw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - browserslist: 4.23.0 - cssnano-utils: 4.0.1(postcss@8.4.35) - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-minify-selectors@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-0b+m+w7OAvZejPQdN2GjsXLv5o0jqYHX3aoV0e7RBKPCsB7TYG5KKWBFhGnB/iP3213Ts8c5H4wLPLMm7z28Sg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-selector-parser: 6.0.15 - dev: true - - /postcss-normalize-charset@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-aW5LbMNRZ+oDV57PF9K+WI1Z8MPnF+A8qbajg/T8PP126YrGX1f9IQx21GI2OlGz7XFJi/fNi0GTbY948XJtXg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - dev: true - - /postcss-normalize-display-values@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-mc3vxp2bEuCb4LgCcmG1y6lKJu1Co8T+rKHrcbShJwUmKJiEl761qb/QQCfFwlrvSeET3jksolCR/RZuMURudw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-positions@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-HRsq8u/0unKNvm0cvwxcOUEcakFXqZ41fv3FOdPn916XFUrympjr+03oaLkuZENz3HE9RrQE9yU0Xv43ThWjQg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-repeat-style@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-Gbb2nmCy6tTiA7Sh2MBs3fj9W8swonk6lw+dFFeQT68B0Pzwp1kvisJQkdV6rbbMSd9brMlS8I8ts52tAGWmGQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-string@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-5Fhx/+xzALJD9EI26Aq23hXwmv97Zfy2VFrt5PLT8lAhnBIZvmaT5pQk+NuJ/GWj/QWaKSKbnoKDGLbV6qnhXg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-timing-functions@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-4zcczzHqmCU7L5dqTB9rzeqPWRMc0K2HoR+Bfl+FSMbqGBUcP5LRfgcH4BdRtLuzVQK1/FHdFoGT3F7rkEnY+g==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-unicode@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-Ff2VdAYCTGyMUwpevTZPZ4w0+mPjbZzLLyoLh/RMpqUqeQKZ+xMm31hkxBavDcGKcxm6ACzGk0nBfZ8LZkStKA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - browserslist: 4.23.0 - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-url@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-jEXL15tXSvbjm0yzUV7FBiEXwhIa9H88JOXDGQzmcWoB4mSjZIsmtto066s2iW9FYuIrIF4k04HA2BKAOpbsaQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-normalize-whitespace@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-76i3NpWf6bB8UHlVuLRxG4zW2YykF9CTEcq/9LGAiz2qBuX5cBStadkk0jSkg9a9TCIXbMQz7yzrygKoCW9JuA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-ordered-values@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-XXbb1O/MW9HdEhnBxitZpPFbIvDgbo9NK4c/5bOfiKpnIGZDoL2xd7/e6jW5DYLsWxBbs+1nZEnVgnjnlFViaA==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - cssnano-utils: 4.0.1(postcss@8.4.35) - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-reduce-initial@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-YGKalhNlCLcjcLvjU5nF8FyeCTkCO5UtvJEt0hrPZVCTtRLSOH4z00T1UntQPj4dUmIYZgMj8qK77JbSX95hSw==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - browserslist: 4.23.0 - caniuse-api: 3.0.0 - postcss: 8.4.35 - dev: true - - /postcss-reduce-transforms@6.0.1(postcss@8.4.35): - resolution: {integrity: sha512-fUbV81OkUe75JM+VYO1gr/IoA2b/dRiH6HvMwhrIBSUrxq3jNZQZitSnugcTLDi1KkQh1eR/zi+iyxviUNBkcQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-selector-parser@6.0.15: - resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: true - - /postcss-svgo@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-IH5R9SjkTkh0kfFOQDImyy1+mTCb+E830+9SV1O+AaDcoHTvfsvt6WwJeo7KwcHbFnevZVCsXhDmjFiGVuwqFQ==} - engines: {node: ^14 || ^16 || >= 18} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-value-parser: 4.2.0 - svgo: 3.2.0 - dev: true - - /postcss-unique-selectors@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-8IZGQ94nechdG7Y9Sh9FlIY2b4uS8/k8kdKRX040XHsS3B6d1HrJAkXrBSsSu4SuARruSsUjW3nlSw8BHkaAYQ==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - postcss: 8.4.35 - postcss-selector-parser: 6.0.15 - dev: true - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true - - /postcss@8.4.35: - resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-plugin-packagejson@2.4.5(prettier@3.2.5): - resolution: {integrity: sha512-glG71jE1gO3y5+JNAhC8X+4yrlN28rub6Aj461SKbaPie9RgMiHKcInH2Moi2VGOfkTXaEHBhg4uVMBqa+kBUA==} - peerDependencies: - prettier: '>= 1.16.0' - peerDependenciesMeta: - prettier: - optional: true - dependencies: - prettier: 3.2.5 - sort-package-json: 2.5.1 - synckit: 0.8.5 - dev: true - - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /pretty-bytes@6.1.1: - resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} - engines: {node: ^14.13.1 || >=16.0.0} - dev: true - - /proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - - /promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - dev: true - - /promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - dev: true - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /protocols@2.0.1: - resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} - dev: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /queue-tick@1.0.1: - resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} - dev: true - - /radix3@1.1.0: - resolution: {integrity: sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==} - dev: true - - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: true - - /rc9@2.1.1: - resolution: {integrity: sha512-lNeOl38Ws0eNxpO3+wD1I9rkHGQyj1NU1jlzv4go2CtEnEQEUfqnIvZG7W+bC/aXdJ27n5x/yUjb6RoT9tko+Q==} - dependencies: - defu: 6.1.4 - destr: 2.0.3 - flat: 5.0.2 - dev: true - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /read-package-json-fast@3.0.2: - resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - json-parse-even-better-errors: 3.0.1 - npm-normalize-package-bin: 3.0.1 - dev: true - - /read-package-json@7.0.0: - resolution: {integrity: sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - glob: 10.3.10 - json-parse-even-better-errors: 3.0.1 - normalize-package-data: 6.0.0 - npm-normalize-package-bin: 3.0.1 - dev: true - - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.1 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdir-glob@1.1.3: - resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} - dependencies: - minimatch: 5.1.6 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /redis-errors@1.2.0: - resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} - engines: {node: '>=4'} - dev: true - - /redis-parser@3.0.0: - resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} - engines: {node: '>=4'} - dependencies: - redis-errors: 1.2.0 - dev: true - - /reflect.getprototypeof@1.0.3: - resolution: {integrity: sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 - globalthis: 1.0.3 - which-builtin-type: 1.1.3 - dev: true - - /regenerator-runtime@0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - dev: true - - /regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - hasBin: true - dev: true - - /regexp.prototype.flags@1.5.0: - resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - functions-have-names: 1.2.3 - dev: true - - /regexpp@3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - dev: true - - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rollup-plugin-visualizer@5.12.0(rollup@4.12.0): - resolution: {integrity: sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==} - engines: {node: '>=14'} - hasBin: true - peerDependencies: - rollup: 2.x || 3.x || 4.x - peerDependenciesMeta: - rollup: - optional: true - dependencies: - open: 8.4.2 - picomatch: 2.3.1 - rollup: 4.12.0 - source-map: 0.7.4 - yargs: 17.7.2 - dev: true - - /rollup@4.12.0: - resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.12.0 - '@rollup/rollup-android-arm64': 4.12.0 - '@rollup/rollup-darwin-arm64': 4.12.0 - '@rollup/rollup-darwin-x64': 4.12.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.12.0 - '@rollup/rollup-linux-arm64-gnu': 4.12.0 - '@rollup/rollup-linux-arm64-musl': 4.12.0 - '@rollup/rollup-linux-riscv64-gnu': 4.12.0 - '@rollup/rollup-linux-x64-gnu': 4.12.0 - '@rollup/rollup-linux-x64-musl': 4.12.0 - '@rollup/rollup-win32-arm64-msvc': 4.12.0 - '@rollup/rollup-win32-ia32-msvc': 4.12.0 - '@rollup/rollup-win32-x64-msvc': 4.12.0 - fsevents: 2.3.3 - dev: true - - /run-applescript@5.0.0: - resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} - engines: {node: '>=12'} - dependencies: - execa: 5.1.1 - dev: true - - /run-applescript@7.0.0: - resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} - engines: {node: '>=18'} - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /safe-array-concat@1.0.0: - resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-regex: 1.1.4 - dev: true - - /safe-regex@2.1.1: - resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} - dependencies: - regexp-tree: 0.1.27 - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - requiresBuild: true - dev: true - optional: true - - /scule@1.3.0: - resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} - dev: true - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /serialize-javascript@6.0.1: - resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} - dependencies: - randombytes: 2.1.0 - dev: true - - /serve-placeholder@2.0.1: - resolution: {integrity: sha512-rUzLlXk4uPFnbEaIz3SW8VISTxMuONas88nYWjAWaM2W9VDbt9tyFOr3lq8RhVOFrT3XISoBw8vni5una8qMnQ==} - dependencies: - defu: 6.1.4 - dev: true - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: true - - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - dev: true - - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /sigstore@2.2.2: - resolution: {integrity: sha512-2A3WvXkQurhuMgORgT60r6pOWiCOO5LlEqY2ADxGBDGVYLSo5HN0uLtb68YpVpuL/Vi8mLTe7+0Dx2Fq8lLqEg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@sigstore/bundle': 2.2.0 - '@sigstore/core': 1.0.0 - '@sigstore/protobuf-specs': 0.3.0 - '@sigstore/sign': 2.2.3 - '@sigstore/tuf': 2.3.1 - '@sigstore/verify': 1.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /simple-git@3.22.0: - resolution: {integrity: sha512-6JujwSs0ac82jkGjMHiCnTifvf1crOiY/+tfs/Pqih6iow7VrpNKRRNdWm6RtaXpvvv/JGNYhlUtLhGFqHF+Yw==} - dependencies: - '@kwsites/file-exists': 1.1.1 - '@kwsites/promise-deferred': 1.1.1 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /sirv@2.0.4: - resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} - engines: {node: '>= 10'} - dependencies: - '@polka/url': 1.0.0-next.24 - mrmime: 2.0.0 - totalist: 3.0.1 - dev: true - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - - /slash@5.1.0: - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} - engines: {node: '>=14.16'} - dev: true - - /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true - - /smob@1.4.1: - resolution: {integrity: sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==} - dev: true - - /socks-proxy-agent@8.0.2: - resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} - engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4 - socks: 2.8.1 - transitivePeerDependencies: - - supports-color - dev: true - - /socks@2.8.1: - resolution: {integrity: sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - dev: true - - /sort-object-keys@1.1.3: - resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - dev: true - - /sort-package-json@2.5.1: - resolution: {integrity: sha512-vx/KoZxm8YNMUqdlw7SGTfqR5pqZ/sUfgOuRtDILiOy/3AvzhAibyUe2cY3OpLs3oRSow9up4yLVtQaM24rbDQ==} - hasBin: true - dependencies: - detect-indent: 7.0.1 - detect-newline: 4.0.0 - get-stdin: 9.0.0 - git-hooks-list: 3.1.0 - globby: 13.2.2 - is-plain-obj: 4.1.0 - sort-object-keys: 1.1.3 - dev: true - - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 - dev: true - - /spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - dev: true - - /sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - dev: true - - /ssri@10.0.5: - resolution: {integrity: sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - minipass: 7.0.4 - dev: true - - /standard-as-callback@2.1.0: - resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - dev: true - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - - /std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - dev: true - - /stop-iteration-iterator@1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} - dependencies: - internal-slot: 1.0.5 - dev: true - - /streamx@2.15.6: - resolution: {integrity: sha512-q+vQL4AAz+FdfT137VF69Cc/APqUbxy+MDOImRrMvchJpigHj9GksgDU2LYbO9rx7RX6osWgxJB2WxhYv4SZAw==} - dependencies: - fast-fifo: 1.3.2 - queue-tick: 1.0.1 - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string.prototype.matchall@4.0.8: - resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 - has-symbols: 1.0.3 - internal-slot: 1.0.5 - regexp.prototype.flags: 1.5.0 - side-channel: 1.0.4 - dev: true - - /string.prototype.trim@1.2.7: - resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - dev: true - - /string.prototype.trimend@1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - dev: true - - /string.prototype.trimstart@1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /strip-literal@1.3.0: - resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} - dependencies: - acorn: 8.11.3 - dev: true - - /strip-literal@2.0.0: - resolution: {integrity: sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==} - dependencies: - js-tokens: 8.0.3 - dev: true - - /stylehacks@6.0.2(postcss@8.4.35): - resolution: {integrity: sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg==} - engines: {node: ^14 || ^16 || >=18.0} - peerDependencies: - postcss: ^8.4.31 - dependencies: - browserslist: 4.23.0 - postcss: 8.4.35 - postcss-selector-parser: 6.0.15 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color@9.4.0: - resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} - engines: {node: '>=12'} - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /svg-tags@1.0.0: - resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} - dev: true - - /svgo@3.2.0: - resolution: {integrity: sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==} - engines: {node: '>=14.0.0'} - hasBin: true - dependencies: - '@trysound/sax': 0.2.0 - commander: 7.2.0 - css-select: 5.1.0 - css-tree: 2.3.1 - css-what: 6.1.0 - csso: 5.0.5 - picocolors: 1.0.0 - dev: true - - /synckit@0.8.5: - resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/utils': 2.4.0 - tslib: 2.5.0 - dev: true - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /tar-stream@3.1.6: - resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} - dependencies: - b4a: 1.6.4 - fast-fifo: 1.3.2 - streamx: 2.15.6 - dev: true - - /tar@6.2.0: - resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: true - - /terser@5.26.0: - resolution: {integrity: sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.5 - acorn: 8.11.3 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /tiny-invariant@1.3.1: - resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} - dev: true - - /titleize@3.0.0: - resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} - engines: {node: '>=12'} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true - - /totalist@3.0.1: - resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} - engines: {node: '>=6'} - dev: true - - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true - - /ts-api-utils@1.0.2(typescript@5.5.4): - resolution: {integrity: sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==} - engines: {node: '>=16.13.0'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /tsconfig-paths@3.14.2: - resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib@2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - dev: true - - /tsutils@3.21.0(typescript@5.5.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.4 - dev: true - - /tuf-js@2.2.0: - resolution: {integrity: sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg==} - engines: {node: ^16.14.0 || >=18.0.0} - dependencies: - '@tufjs/models': 2.0.0 - debug: 4.3.4 - make-fetch-happen: 13.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /turbo-darwin-64@2.0.3: - resolution: {integrity: sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-darwin-arm64@2.0.3: - resolution: {integrity: sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-64@2.0.3: - resolution: {integrity: sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-linux-arm64@2.0.3: - resolution: {integrity: sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-64@2.0.3: - resolution: {integrity: sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo-windows-arm64@2.0.3: - resolution: {integrity: sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /turbo@2.0.3: - resolution: {integrity: sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA==} - hasBin: true - optionalDependencies: - turbo-darwin-64: 2.0.3 - turbo-darwin-arm64: 2.0.3 - turbo-linux-64: 2.0.3 - turbo-linux-arm64: 2.0.3 - turbo-windows-64: 2.0.3 - turbo-windows-arm64: 2.0.3 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /type-fest@3.13.1: - resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} - engines: {node: '>=14.16'} - dev: true - - /typed-array-buffer@1.0.0: - resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-typed-array: 1.1.10 - dev: true - - /typed-array-byte-length@1.0.0: - resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.10 - dev: true - - /typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.10 - dev: true - - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} - dependencies: - call-bind: 1.0.2 - for-each: 0.3.3 - is-typed-array: 1.1.10 - dev: true - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - - /ufo@1.4.0: - resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==} - dev: true - - /ultrahtml@1.5.3: - resolution: {integrity: sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==} - dev: true - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /uncrypto@0.1.3: - resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} - dev: true - - /unctx@2.3.1: - resolution: {integrity: sha512-PhKke8ZYauiqh3FEMVNm7ljvzQiph0Mt3GBRve03IJm7ukfaON2OBK795tLwhbyfzknuRRkW0+Ze+CQUmzOZ+A==} - dependencies: - acorn: 8.11.3 - estree-walker: 3.0.3 - magic-string: 0.30.8 - unplugin: 1.8.0 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /undici@5.28.2: - resolution: {integrity: sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==} - engines: {node: '>=14.0'} - dependencies: - '@fastify/busboy': 2.1.0 - dev: true - - /unenv@1.9.0: - resolution: {integrity: sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==} - dependencies: - consola: 3.2.3 - defu: 6.1.4 - mime: 3.0.0 - node-fetch-native: 1.6.2 - pathe: 1.1.2 - dev: true - - /unhead@1.8.11: - resolution: {integrity: sha512-g1coK+pRv+RbeD4+hK76FV6Y++i5jY99CftKyP1ARQcLCbz0ri6+vBpWMS4d+h7x0DfWSCGm/wWkPQ1WXWHfRA==} - dependencies: - '@unhead/dom': 1.8.11 - '@unhead/schema': 1.8.11 - '@unhead/shared': 1.8.11 - hookable: 5.5.3 - dev: true - - /unicorn-magic@0.1.0: - resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} - engines: {node: '>=18'} - dev: true - - /unimport@3.7.1(rollup@4.12.0): - resolution: {integrity: sha512-V9HpXYfsZye5bPPYUgs0Otn3ODS1mDUciaBlXljI4C2fTwfFpvFZRywmlOu943puN9sncxROMZhsZCjNXEpzEQ==} - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - acorn: 8.11.3 - escape-string-regexp: 5.0.0 - estree-walker: 3.0.3 - fast-glob: 3.3.2 - local-pkg: 0.5.0 - magic-string: 0.30.8 - mlly: 1.6.1 - pathe: 1.1.2 - pkg-types: 1.0.3 - scule: 1.3.0 - strip-literal: 1.3.0 - unplugin: 1.8.0 - transitivePeerDependencies: - - rollup - dev: true - - /unique-filename@3.0.0: - resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - unique-slug: 4.0.0 - dev: true - - /unique-slug@4.0.0: - resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - imurmurhash: 0.1.4 - dev: true - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: true - - /unplugin-vue-router@0.7.0(vue-router@4.3.0)(vue@3.4.21): - resolution: {integrity: sha512-ddRreGq0t5vlSB7OMy4e4cfU1w2AwBQCwmvW3oP/0IHQiokzbx4hd3TpwBu3eIAFVuhX2cwNQwp1U32UybTVCw==} - peerDependencies: - vue-router: ^4.1.0 - peerDependenciesMeta: - vue-router: - optional: true - dependencies: - '@babel/types': 7.24.0 - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - '@vue-macros/common': 1.8.0(vue@3.4.21) - ast-walker-scope: 0.5.0 - chokidar: 3.6.0 - fast-glob: 3.3.2 - json5: 2.2.3 - local-pkg: 0.4.3 - mlly: 1.6.1 - pathe: 1.1.2 - scule: 1.3.0 - unplugin: 1.8.0 - vue-router: 4.3.0(vue@3.4.21) - yaml: 2.3.4 - transitivePeerDependencies: - - rollup - - vue - dev: true - - /unplugin@1.8.0: - resolution: {integrity: sha512-yGEQsodWICmgt7asHF7QzqDZYeEP9h14vyd9Lul98UnYf29pLZZLwI09z2QdTjwU/FCkum1SRvsK7cx232X8NA==} - dependencies: - acorn: 8.11.3 - chokidar: 3.6.0 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.6.1 - dev: true - - /unstorage@1.10.1: - resolution: {integrity: sha512-rWQvLRfZNBpF+x8D3/gda5nUCQL2PgXy2jNG4U7/Rc9BGEv9+CAJd0YyGCROUBKs9v49Hg8huw3aih5Bf5TAVw==} - peerDependencies: - '@azure/app-configuration': ^1.4.1 - '@azure/cosmos': ^4.0.0 - '@azure/data-tables': ^13.2.2 - '@azure/identity': ^3.3.2 - '@azure/keyvault-secrets': ^4.7.0 - '@azure/storage-blob': ^12.16.0 - '@capacitor/preferences': ^5.0.6 - '@netlify/blobs': ^6.2.0 - '@planetscale/database': ^1.11.0 - '@upstash/redis': ^1.23.4 - '@vercel/kv': ^0.2.3 - idb-keyval: ^6.2.1 - peerDependenciesMeta: - '@azure/app-configuration': - optional: true - '@azure/cosmos': - optional: true - '@azure/data-tables': - optional: true - '@azure/identity': - optional: true - '@azure/keyvault-secrets': - optional: true - '@azure/storage-blob': - optional: true - '@capacitor/preferences': - optional: true - '@netlify/blobs': - optional: true - '@planetscale/database': - optional: true - '@upstash/redis': - optional: true - '@vercel/kv': - optional: true - idb-keyval: - optional: true - dependencies: - anymatch: 3.1.3 - chokidar: 3.6.0 - destr: 2.0.3 - h3: 1.11.1 - ioredis: 5.3.2 - listhen: 1.5.5 - lru-cache: 10.2.0 - mri: 1.2.0 - node-fetch-native: 1.6.2 - ofetch: 1.3.3 - ufo: 1.4.0 - transitivePeerDependencies: - - supports-color - - uWebSockets.js - dev: true - - /untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - dev: true - - /untun@0.1.3: - resolution: {integrity: sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==} - hasBin: true - dependencies: - citty: 0.1.6 - consola: 3.2.3 - pathe: 1.1.2 - dev: true - - /untyped@1.4.2: - resolution: {integrity: sha512-nC5q0DnPEPVURPhfPQLahhSTnemVtPzdx7ofiRxXpOB2SYnb3MfdU3DVGyJdS8Lx+tBWeAePO8BfU/3EgksM7Q==} - hasBin: true - dependencies: - '@babel/core': 7.24.0 - '@babel/standalone': 7.24.0 - '@babel/types': 7.24.0 - defu: 6.1.4 - jiti: 1.21.0 - mri: 1.2.0 - scule: 1.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /update-browserslist-db@1.0.13(browserslist@4.23.0): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.0 - dev: true - - /uqr@0.1.2: - resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /urlpattern-polyfill@8.0.2: - resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - - /validate-npm-package-name@5.0.0: - resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dependencies: - builtins: 5.0.1 - dev: true - - /vite-node@1.3.1: - resolution: {integrity: sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4 - pathe: 1.1.2 - picocolors: 1.0.0 - vite: 5.1.4(@types/node@20.11.24) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /vite-plugin-checker@0.6.4(eslint@8.57.0)(typescript@5.5.4)(vite@5.1.4): - resolution: {integrity: sha512-2zKHH5oxr+ye43nReRbC2fny1nyARwhxdm0uNYp/ERy4YvU9iZpNOsueoi/luXw5gnpqRSvjcEPxXbS153O2wA==} - engines: {node: '>=14.16'} - peerDependencies: - eslint: '>=7' - meow: ^9.0.0 - optionator: ^0.9.1 - stylelint: '>=13' - typescript: '*' - vite: '>=2.0.0' - vls: '*' - vti: '*' - vue-tsc: '>=1.3.9' - peerDependenciesMeta: - eslint: - optional: true - meow: - optional: true - optionator: - optional: true - stylelint: - optional: true - typescript: - optional: true - vls: - optional: true - vti: - optional: true - vue-tsc: - optional: true - dependencies: - '@babel/code-frame': 7.23.5 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - chokidar: 3.6.0 - commander: 8.3.0 - eslint: 8.57.0 - fast-glob: 3.3.2 - fs-extra: 11.2.0 - npm-run-path: 4.0.1 - semver: 7.6.0 - strip-ansi: 6.0.1 - tiny-invariant: 1.3.1 - typescript: 5.5.4 - vite: 5.1.4(@types/node@20.11.24) - vscode-languageclient: 7.0.0 - vscode-languageserver: 7.0.0 - vscode-languageserver-textdocument: 1.0.11 - vscode-uri: 3.0.8 - dev: true - - /vite-plugin-inspect@0.8.3(@nuxt/kit@3.10.3)(vite@5.1.4): - resolution: {integrity: sha512-SBVzOIdP/kwe6hjkt7LSW4D0+REqqe58AumcnCfRNw4Kt3mbS9pEBkch+nupu2PBxv2tQi69EQHQ1ZA1vgB/Og==} - engines: {node: '>=14'} - peerDependencies: - '@nuxt/kit': '*' - vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 - peerDependenciesMeta: - '@nuxt/kit': - optional: true - dependencies: - '@antfu/utils': 0.7.7 - '@nuxt/kit': 3.10.3 - '@rollup/pluginutils': 5.1.0(rollup@4.12.0) - debug: 4.3.4 - error-stack-parser-es: 0.1.1 - fs-extra: 11.2.0 - open: 10.0.4 - perfect-debounce: 1.0.0 - picocolors: 1.0.0 - sirv: 2.0.4 - vite: 5.1.4(@types/node@20.11.24) - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /vite-plugin-vue-inspector@4.0.2(vite@5.1.4): - resolution: {integrity: sha512-KPvLEuafPG13T7JJuQbSm5PwSxKFnVS965+MP1we2xGw9BPkkc/+LPix5MMWenpKWqtjr0ws8THrR+KuoDC8hg==} - peerDependencies: - vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 - dependencies: - '@babel/core': 7.24.0 - '@babel/plugin-proposal-decorators': 7.24.0(@babel/core@7.24.0) - '@babel/plugin-syntax-import-attributes': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.0) - '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.24.0) - '@vue/babel-plugin-jsx': 1.2.1(@babel/core@7.24.0) - '@vue/compiler-dom': 3.4.21 - kolorist: 1.8.0 - magic-string: 0.30.8 - vite: 5.1.4(@types/node@20.11.24) - transitivePeerDependencies: - - supports-color - dev: true - - /vite@5.1.4(@types/node@20.11.24): - resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 20.11.24 - esbuild: 0.19.12 - postcss: 8.4.35 - rollup: 4.12.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vscode-jsonrpc@6.0.0: - resolution: {integrity: sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==} - engines: {node: '>=8.0.0 || >=10.0.0'} - dev: true - - /vscode-languageclient@7.0.0: - resolution: {integrity: sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==} - engines: {vscode: ^1.52.0} - dependencies: - minimatch: 3.1.2 - semver: 7.6.0 - vscode-languageserver-protocol: 3.16.0 - dev: true - - /vscode-languageserver-protocol@3.16.0: - resolution: {integrity: sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==} - dependencies: - vscode-jsonrpc: 6.0.0 - vscode-languageserver-types: 3.16.0 - dev: true - - /vscode-languageserver-textdocument@1.0.11: - resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} - dev: true - - /vscode-languageserver-types@3.16.0: - resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==} - dev: true - - /vscode-languageserver@7.0.0: - resolution: {integrity: sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==} - hasBin: true - dependencies: - vscode-languageserver-protocol: 3.16.0 - dev: true - - /vscode-uri@3.0.8: - resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} - dev: true - - /vue-bundle-renderer@2.0.0: - resolution: {integrity: sha512-oYATTQyh8XVkUWe2kaKxhxKVuuzK2Qcehe+yr3bGiaQAhK3ry2kYE4FWOfL+KO3hVFwCdLmzDQTzYhTi9C+R2A==} - dependencies: - ufo: 1.4.0 - dev: true - - /vue-devtools-stub@0.1.0: - resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==} - dev: true - - /vue-eslint-parser@9.3.2(eslint@8.57.0): - resolution: {integrity: sha512-q7tWyCVaV9f8iQyIA5Mkj/S6AoJ9KBN8IeUSf3XEmBrOtxOZnfTg5s4KClbZBCK3GtnT/+RyCLZyDHuZwTuBjg==} - engines: {node: ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '>=6.0.0' - dependencies: - debug: 4.3.4 - eslint: 8.57.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - lodash: 4.17.21 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - dev: true - - /vue-eslint-parser@9.4.2(eslint@8.57.0): - resolution: {integrity: sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==} - engines: {node: ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '>=6.0.0' - dependencies: - debug: 4.3.4 - eslint: 8.57.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - lodash: 4.17.21 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - dev: true - - /vue-router@4.3.0(vue@3.4.21): - resolution: {integrity: sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==} - peerDependencies: - vue: ^3.2.0 - dependencies: - '@vue/devtools-api': 6.5.1 - vue: 3.4.21(typescript@5.5.4) - dev: true - - /vue-template-compiler@2.7.15: - resolution: {integrity: sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==} - dependencies: - de-indent: 1.0.2 - he: 1.2.0 - dev: true - - /vue-tsc@2.0.4(typescript@5.5.4): - resolution: {integrity: sha512-FJk+F1QhqROr6DK8raTuWk5ezNw1/kZ+7TYhc08k+cpvb1fmi7wguPZHX0svIhT4bAxCGDtF8534It8fiAkScg==} - hasBin: true - peerDependencies: - typescript: '*' - dependencies: - '@volar/typescript': 2.1.0 - '@vue/language-core': 2.0.4(typescript@5.5.4) - semver: 7.6.0 - typescript: 5.5.4 - dev: true - - /vue@3.4.21(typescript@5.5.4): - resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@vue/compiler-dom': 3.4.21 - '@vue/compiler-sfc': 3.4.21 - '@vue/runtime-dom': 3.4.21 - '@vue/server-renderer': 3.4.21(vue@3.4.21) - '@vue/shared': 3.4.21 - typescript: 5.5.4 - - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack-virtual-modules@0.6.1: - resolution: {integrity: sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==} - dev: true - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: true - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.5 - has-tostringtag: 1.0.0 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.11 - dev: true - - /which-collection@1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} - dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 - dev: true - - /which-typed-array@1.1.11: - resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@4.0.0: - resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} - engines: {node: ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - isexe: 3.1.1 - dev: true - - /wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - dependencies: - string-width: 4.2.3 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /ws@8.16.0: - resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /xml-name-validator@4.0.0: - resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} - engines: {node: '>=12'} - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - dev: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /zhead@2.2.4: - resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} - dev: true - - /zip-stream@5.0.1: - resolution: {integrity: sha512-UfZ0oa0C8LI58wJ+moL46BDIMgCQbnsb+2PoiJYtonhBsMh2bq1eRBVkvjfVsqbEHd9/EgKPUuL9saSSsec8OA==} - engines: {node: '>= 12.0.0'} - dependencies: - archiver-utils: 4.0.1 - compress-commons: 5.0.1 - readable-stream: 3.6.2 - dev: true diff --git a/examples/with-yarn/README.md b/examples/with-yarn/README.md deleted file mode 100644 index 2f223eb5e5938..0000000000000 --- a/examples/with-yarn/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Turborepo starter - -This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed. - -## Using this example - -Run the following command: - -```sh -npx create-turbo@latest -e with-yarn -``` - -## What's inside? - -This Turborepo includes the following packages/apps: - -### Apps and Packages - -- `docs`: a [Next.js](https://nextjs.org/) app -- `web`: another [Next.js](https://nextjs.org/) app -- `@repo/ui`: a stub React component library shared by both `web` and `docs` applications -- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) -- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo - -Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). - -### Utilities - -This Turborepo has some additional tools already setup for you: - -- [TypeScript](https://www.typescriptlang.org/) for static type checking -- [ESLint](https://eslint.org/) for code linting -- [Prettier](https://prettier.io) for code formatting - -### Build - -To build all apps and packages, run the following command: - -``` -cd my-turborepo -yarn build -``` - -### Develop - -To develop all apps and packages, run the following command: - -``` -cd my-turborepo -yarn dev -``` - -### Remote Caching - -> [!TIP] -> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache). - -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. - -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands: - -``` -cd my-turborepo -npx turbo login -``` - -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). - -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: - -``` -npx turbo link -``` - -## Useful Links - -Learn more about the power of Turborepo: - -- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) -- [Caching](https://turbo.build/repo/docs/core-concepts/caching) -- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) -- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) -- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) -- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/examples/with-yarn/apps/docs/.eslintrc.js b/examples/with-yarn/apps/docs/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-yarn/apps/docs/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-yarn/apps/docs/README.md b/examples/with-yarn/apps/docs/README.md deleted file mode 100644 index d364535741404..0000000000000 --- a/examples/with-yarn/apps/docs/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3001](http://localhost:3001) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-yarn/apps/docs/package.json b/examples/with-yarn/apps/docs/package.json index 7405043a42d9e..2cd3cf7afbf3f 100644 --- a/examples/with-yarn/apps/docs/package.json +++ b/examples/with-yarn/apps/docs/package.json @@ -1,28 +1,17 @@ { - "name": "docs", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev --port 3001", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0" - }, - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "docs", + "scripts": { + "build": "next build", + "dev": "next dev --port 3001", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-yarn/apps/web/.eslintrc.js b/examples/with-yarn/apps/web/.eslintrc.js deleted file mode 100644 index 7d644a4ca0ea3..0000000000000 --- a/examples/with-yarn/apps/web/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/next.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/examples/with-yarn/apps/web/README.md b/examples/with-yarn/apps/web/README.md deleted file mode 100644 index 3d7b63af7dc79..0000000000000 --- a/examples/with-yarn/apps/web/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -yarn dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-yarn/apps/web/package.json b/examples/with-yarn/apps/web/package.json index bd304a2d27d85..f5ce740cc1204 100644 --- a/examples/with-yarn/apps/web/package.json +++ b/examples/with-yarn/apps/web/package.json @@ -1,28 +1,17 @@ { - "name": "web", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "eslint . --max-warnings 0" - }, - "dependencies": { - "@repo/ui": "*", - "next": "^14.1.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.1.1", - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - } + "name": "web", + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start" + }, + "dependencies": { + "@repo/ui": "*", + "next": "15.1.7" + }, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/node": "22.13.1" + } } diff --git a/examples/with-yarn/package.json b/examples/with-yarn/package.json index 9a30e5c684c4d..31a8c03f71103 100644 --- a/examples/with-yarn/package.json +++ b/examples/with-yarn/package.json @@ -1,22 +1,15 @@ { - "name": "with-yarn", - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "devDependencies": { - "prettier": "^3.2.5", - "turbo": "^2.0.3" - }, - "packageManager": "yarn@1.22.22", - "engines": { - "node": ">=18" - } + "name": "with-yarn", + "workspaces": [ + "apps/*", + "packages/*" + ], + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev" + }, + "dependencies": {}, + "devDependencies": { + "turbo": "2.4.2" + } } diff --git a/examples/with-yarn/packages/eslint-config/README.md b/examples/with-yarn/packages/eslint-config/README.md deleted file mode 100644 index 8b42d901b0e8d..0000000000000 --- a/examples/with-yarn/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/examples/with-yarn/packages/eslint-config/package.json b/examples/with-yarn/packages/eslint-config/package.json index abe24eaf1e36f..dca64b8823b7a 100644 --- a/examples/with-yarn/packages/eslint-config/package.json +++ b/examples/with-yarn/packages/eslint-config/package.json @@ -1,19 +1,14 @@ { - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "library.js", - "next.js", - "react-internal.js" - ], - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "@vercel/style-guide": "^5.2.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-turbo": "^2.0.0", - "eslint-plugin-only-warn": "^1.1.0", - "typescript": "5.5.4" - } + "name": "@repo/eslint-config", + "files": [ + "library.js", + "next.js", + "react-internal.js" + ], + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0", + "eslint-config-turbo": "2.4.2", + "eslint-plugin-only-warn": "1.1.0" + } } diff --git a/examples/with-yarn/packages/typescript-config/package.json b/examples/with-yarn/packages/typescript-config/package.json index 27c0e60436aac..0b30de456c71c 100644 --- a/examples/with-yarn/packages/typescript-config/package.json +++ b/examples/with-yarn/packages/typescript-config/package.json @@ -1,9 +1,5 @@ { - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } + "name": "@repo/typescript-config", + "dependencies": {}, + "devDependencies": {} } diff --git a/examples/with-yarn/packages/ui/.eslintrc.js b/examples/with-yarn/packages/ui/.eslintrc.js deleted file mode 100644 index 46464139c9406..0000000000000 --- a/examples/with-yarn/packages/ui/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - root: true, - extends: ["@repo/eslint-config/react-internal.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: "./tsconfig.lint.json", - tsconfigRootDir: __dirname, - }, -}; diff --git a/examples/with-yarn/packages/ui/src/card.tsx b/examples/with-yarn/packages/ui/Source/card.tsx similarity index 100% rename from examples/with-yarn/packages/ui/src/card.tsx rename to examples/with-yarn/packages/ui/Source/card.tsx diff --git a/examples/with-yarn/packages/ui/src/code.tsx b/examples/with-yarn/packages/ui/Source/code.tsx similarity index 100% rename from examples/with-yarn/packages/ui/src/code.tsx rename to examples/with-yarn/packages/ui/Source/code.tsx diff --git a/examples/with-yarn/packages/ui/package.json b/examples/with-yarn/packages/ui/package.json index 270b5472564c4..63cc07ae9dec7 100644 --- a/examples/with-yarn/packages/ui/package.json +++ b/examples/with-yarn/packages/ui/package.json @@ -1,27 +1,17 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "private": true, - "exports": { - "./card": "./src/card.tsx", - "./code": "./src/code.tsx" - }, - "scripts": { - "lint": "eslint . --max-warnings 0", - "generate:component": "turbo gen react-component" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@turbo/gen": "^1.12.4", - "@types/eslint": "^8.56.5", - "@types/node": "^20.11.24", - "@types/react": "^18.2.61", - "@types/react-dom": "^18.2.19", - "eslint": "^8.57.0", - "typescript": "5.5.4" - }, - "dependencies": { - "react": "^18.2.0" - } + "name": "@repo/ui", + "exports": { + "./card": "./src/card.tsx", + "./code": "./src/code.tsx" + }, + "scripts": { + "generate:component": "turbo gen react-component" + }, + "dependencies": {}, + "devDependencies": { + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@turbo/gen": "2.4.2", + "@types/node": "22.13.1" + } } diff --git a/examples/with-yarn/yarn.lock b/examples/with-yarn/yarn.lock deleted file mode 100644 index 2cafef03faf55..0000000000000 --- a/examples/with-yarn/yarn.lock +++ /dev/null @@ -1,4532 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" - integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== - dependencies: - "@babel/highlight" "^7.24.6" - picocolors "^1.0.0" - -"@babel/compat-data@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" - integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== - -"@babel/core@^7.22.11": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" - integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helpers" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/traverse" "^7.24.6" - "@babel/types" "^7.24.6" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/eslint-parser@^7.22.11": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.24.6.tgz#7f0ecc0f29307b8696e83ff6a9d8b4f3e0421ad2" - integrity sha512-Q1BfQX42zXHx732PLW0w4+Y3wJjoZKEMaatFUEAmQ7Z+jCXxinzeqX9bvv2Q8xNPes/H6F0I23oGkcgjaItmLw== - dependencies: - "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" - eslint-visitor-keys "^2.1.0" - semver "^6.3.1" - -"@babel/generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" - integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== - dependencies: - "@babel/types" "^7.24.6" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz#4a51d681f7680043d38e212715e2a7b1ad29cb51" - integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== - dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" - integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== - -"@babel/helper-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" - integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/helper-hoist-variables@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" - integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-module-imports@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz#65e54ffceed6a268dc4ce11f0433b82cfff57852" - integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-module-transforms@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz#22346ed9df44ce84dee850d7433c5b73fab1fe4e" - integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== - dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - -"@babel/helper-simple-access@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz#1d6e04d468bba4fc963b4906f6dac6286cfedff1" - integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-split-export-declaration@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" - integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-string-parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" - integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== - -"@babel/helper-validator-identifier@^7.22.5", "@babel/helper-validator-identifier@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" - integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== - -"@babel/helper-validator-option@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz#59d8e81c40b7d9109ab7e74457393442177f460a" - integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== - -"@babel/helpers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.6.tgz#cd124245299e494bd4e00edda0e4ea3545c2c176" - integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/highlight@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" - integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== - dependencies: - "@babel/helper-validator-identifier" "^7.24.6" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" - integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== - -"@babel/runtime-corejs3@^7.9.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.24.6.tgz#0992564ee78234639ba2ed711b93d25586727272" - integrity sha512-tbC3o8uHK9xMgMsvUm9qGqxVpbv6yborMBLbDteHIc7JDNHsTV0vDMQ5j1O1NXvO+BDELtL9KgoWYaUVIVGt8w== - dependencies: - core-js-pure "^3.30.2" - regenerator-runtime "^0.14.0" - -"@babel/runtime@^7.23.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e" - integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" - integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/traverse@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.6.tgz#0941ec50cdeaeacad0911eb67ae227a4f8424edc" - integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" - integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== - dependencies: - "@babel/helper-string-parser" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - to-fast-properties "^2.0.0" - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.1.tgz#361461e5cb3845d874e61731c11cfedd664d83a0" - integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== - -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@microsoft/tsdoc-config@0.16.2": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz#b786bb4ead00d54f53839a458ce626c8548d3adf" - integrity sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw== - dependencies: - "@microsoft/tsdoc" "0.14.2" - ajv "~6.12.6" - jju "~1.4.0" - resolve "~1.19.0" - -"@microsoft/tsdoc@0.14.2": - version "0.14.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" - integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== - -"@next/env@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.3.tgz#d6def29d1c763c0afb397343a15a82e7d92353a0" - integrity sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA== - -"@next/eslint-plugin-next@^14.1.1": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.3.tgz#287ad8620e7061ba01e8d3313d464db6d217b6df" - integrity sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw== - dependencies: - glob "10.3.10" - -"@next/swc-darwin-arm64@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz#db1a05eb88c0224089b815ad10ac128ec79c2cdb" - integrity sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A== - -"@next/swc-darwin-x64@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz#a3f8af05b5f9a52ac3082e66ac29e125ab1d7b9c" - integrity sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA== - -"@next/swc-linux-arm64-gnu@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz#4e63f43879285b52554bfd39e6e0cc78a9b27bbf" - integrity sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA== - -"@next/swc-linux-arm64-musl@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz#ebdaed26214448b1e6f2c3e8b3cd29bfba387990" - integrity sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw== - -"@next/swc-linux-x64-gnu@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz#19e3bcc137c3b582a1ab867106817e5c90a20593" - integrity sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w== - -"@next/swc-linux-x64-musl@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz#794a539b98e064169cf0ff7741b2a4fb16adec7d" - integrity sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ== - -"@next/swc-win32-arm64-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz#eda9fa0fbf1ff9113e87ac2668ee67ce9e5add5a" - integrity sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A== - -"@next/swc-win32-ia32-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz#7c1190e3f640ab16580c6bdbd7d0e766b9920457" - integrity sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw== - -"@next/swc-win32-x64-msvc@14.2.3": - version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz#2be4e39ee25bfbd85be78eea17c0e7751dc4323c" - integrity sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA== - -"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": - version "5.1.1-v1" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" - integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== - dependencies: - eslint-scope "5.1.1" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@pkgr/core@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" - integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== - -"@rushstack/eslint-patch@^1.3.3": - version "1.10.3" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz#391d528054f758f81e53210f1a1eebcf1a8b1d20" - integrity sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg== - -"@swc/counter@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" - integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== - -"@swc/helpers@0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" - integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== - dependencies: - "@swc/counter" "^0.1.3" - tslib "^2.4.0" - -"@tootallnate/quickjs-emscripten@^0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" - integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA== - -"@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@turbo/gen@^1.12.4": - version "1.13.4" - resolved "https://registry.yarnpkg.com/@turbo/gen/-/gen-1.13.4.tgz#9bb634229906a7cf616b27245cde536d296fba46" - integrity sha512-PK38N1fHhDUyjLi0mUjv0RbX0xXGwDLQeRSGsIlLcVpP1B5fwodSIwIYXc9vJok26Yne94BX5AGjueYsUT3uUw== - dependencies: - "@turbo/workspaces" "1.13.4" - chalk "2.4.2" - commander "^10.0.0" - fs-extra "^10.1.0" - inquirer "^8.2.4" - minimatch "^9.0.0" - node-plop "^0.26.3" - proxy-agent "^6.2.2" - ts-node "^10.9.1" - update-check "^1.5.4" - validate-npm-package-name "^5.0.0" - -"@turbo/workspaces@1.13.4": - version "1.13.4" - resolved "https://registry.yarnpkg.com/@turbo/workspaces/-/workspaces-1.13.4.tgz#16051156f50c8ccf8ebccd3e1f15118cf18c92b6" - integrity sha512-3uYg2b5TWCiupetbDFMbBFMHl33xQTvp5DNg0fZSYal73Z9AlFH9yWabHWMYw6ywmwM1evkYRpTVA2n7GgqT5A== - dependencies: - chalk "2.4.2" - commander "^10.0.0" - execa "5.1.1" - fast-glob "^3.2.12" - fs-extra "^10.1.0" - gradient-string "^2.0.0" - inquirer "^8.0.0" - js-yaml "^4.1.0" - ora "4.1.1" - rimraf "^3.0.2" - semver "^7.3.5" - update-check "^1.5.4" - -"@types/eslint@^8.56.5": - version "8.56.10" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" - integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -"@types/glob@^7.1.1": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/inquirer@^6.5.0": - version "6.5.0" - resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-6.5.0.tgz#b83b0bf30b88b8be7246d40e51d32fe9d10e09be" - integrity sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw== - dependencies: - "@types/through" "*" - rxjs "^6.4.0" - -"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.9": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/minimatch@*": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - -"@types/node@*", "@types/node@^20.11.24": - version "20.14.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.1.tgz#2434dbcb1f039e31f2c0e9969da93f52cf6348f3" - integrity sha512-T2MzSGEu+ysB/FkWfqmhV3PLyQlowdptmmgD20C6QxsS8Fmv5SjpZ1ayXaEC0S21/h5UJ9iA6W/5vSNU5l00OA== - dependencies: - undici-types "~5.26.4" - -"@types/normalize-package-data@^2.4.0": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== - -"@types/prop-types@*": - version "15.7.12" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" - integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== - -"@types/react-dom@^18.2.19": - version "18.3.0" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" - integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@^18.2.61": - version "18.3.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" - integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/semver@^7.3.12", "@types/semver@^7.5.0": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - -"@types/through@*": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.33.tgz#14ebf599320e1c7851e7d598149af183c6b9ea56" - integrity sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ== - dependencies: - "@types/node" "*" - -"@types/tinycolor2@^1.4.0": - version "1.4.6" - resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.6.tgz#670cbc0caf4e58dd61d1e3a6f26386e473087f06" - integrity sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw== - -"@typescript-eslint/eslint-plugin@^6.5.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" - integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/type-utils" "6.21.0" - "@typescript-eslint/utils" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/eslint-plugin@^7.1.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz#f87a32e8972b8a60024f2f8f12205e7c8108bc41" - integrity sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q== - dependencies: - "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.12.0" - "@typescript-eslint/type-utils" "7.12.0" - "@typescript-eslint/utils" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - graphemer "^1.4.0" - ignore "^5.3.1" - natural-compare "^1.4.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/parser@^6.5.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" - integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== - dependencies: - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - -"@typescript-eslint/parser@^7.1.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.12.0.tgz#8761df3345528b35049353db80010b385719b1c3" - integrity sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ== - dependencies: - "@typescript-eslint/scope-manager" "7.12.0" - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/typescript-estree" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - -"@typescript-eslint/scope-manager@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" - integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - -"@typescript-eslint/scope-manager@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz#259c014362de72dd34f995efe6bd8dda486adf58" - integrity sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg== - dependencies: - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - -"@typescript-eslint/type-utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" - integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== - dependencies: - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/utils" "6.21.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/type-utils@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz#9dfaaa1972952f395ec5be4f5bbfc4d3cdc63908" - integrity sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA== - dependencies: - "@typescript-eslint/typescript-estree" "7.12.0" - "@typescript-eslint/utils" "7.12.0" - debug "^4.3.4" - ts-api-utils "^1.3.0" - -"@typescript-eslint/types@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== - -"@typescript-eslint/types@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" - integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== - -"@typescript-eslint/types@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.12.0.tgz#bf208f971a8da1e7524a5d9ae2b5f15192a37981" - integrity sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg== - -"@typescript-eslint/typescript-estree@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/typescript-estree@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" - integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/typescript-estree@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz#e6c1074f248b3db6573ab6a7c47a39c4cd498ff9" - integrity sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ== - dependencies: - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/visitor-keys" "7.12.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" - integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - semver "^7.5.4" - -"@typescript-eslint/utils@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.12.0.tgz#c6e58fd7f724cdccc848f71e388ad80cbdb95dd0" - integrity sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.12.0" - "@typescript-eslint/types" "7.12.0" - "@typescript-eslint/typescript-estree" "7.12.0" - -"@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.58.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== - dependencies: - "@typescript-eslint/types" "5.62.0" - eslint-visitor-keys "^3.3.0" - -"@typescript-eslint/visitor-keys@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" - integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== - dependencies: - "@typescript-eslint/types" "6.21.0" - eslint-visitor-keys "^3.4.1" - -"@typescript-eslint/visitor-keys@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz#c053b55a996679528beeedd8e565710ce1ae1ad3" - integrity sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ== - dependencies: - "@typescript-eslint/types" "7.12.0" - eslint-visitor-keys "^3.4.3" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@vercel/style-guide@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@vercel/style-guide/-/style-guide-5.2.0.tgz#8e09fb48065bc6133add67ff2bc7a219d228fb46" - integrity sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g== - dependencies: - "@babel/core" "^7.22.11" - "@babel/eslint-parser" "^7.22.11" - "@rushstack/eslint-patch" "^1.3.3" - "@typescript-eslint/eslint-plugin" "^6.5.0" - "@typescript-eslint/parser" "^6.5.0" - eslint-config-prettier "^9.0.0" - eslint-import-resolver-alias "^1.1.2" - eslint-import-resolver-typescript "^3.6.0" - eslint-plugin-eslint-comments "^3.2.0" - eslint-plugin-import "^2.28.1" - eslint-plugin-jest "^27.2.3" - eslint-plugin-jsx-a11y "^6.7.1" - eslint-plugin-playwright "^0.16.0" - eslint-plugin-react "^7.33.2" - eslint-plugin-react-hooks "^4.6.0" - eslint-plugin-testing-library "^6.0.1" - eslint-plugin-tsdoc "^0.2.17" - eslint-plugin-unicorn "^48.0.1" - prettier-plugin-packagejson "^2.4.5" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.1.1: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== - -acorn@^8.4.1, acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -agent-base@^7.0.2, agent-base@^7.1.0, agent-base@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" - integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== - dependencies: - debug "^4.3.4" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv@^6.12.4, ajv@~6.12.6: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-query@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" - -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== - dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" - -array-includes@^3.1.6, array-includes@^3.1.7, array-includes@^3.1.8: - version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.findlast@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" - integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.findlastindex@^1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" - integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.toreversed@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" - integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.tosorted@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" - integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.3" - es-errors "^1.3.0" - es-shim-unscopables "^1.0.2" - -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" - is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" - -ast-types-flow@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" - integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== - -ast-types@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" - integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== - dependencies: - tslib "^2.0.1" - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -axe-core@=4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" - integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== - -axobject-query@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" - integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== - dependencies: - dequal "^2.0.3" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -basic-ftp@^5.0.2: - version "5.0.5" - resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.5.tgz#14a474f5fffecca1f4f406f1c26b18f800225ac0" - integrity sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg== - -bl@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.22.2: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== - dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -builtin-modules@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" - integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== - -busboy@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w== - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - -caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001587: - version "1.0.30001627" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001627.tgz#8071c42d468e06ed2fb2c545efe79a663fd326ab" - integrity sha512-4zgNiB8nTyV/tHhwZrFs88ryjls/lHiqFhrxCW4qSTeuRByBVnPYpDInchOIySWknznucaf31Z4KYqjfbrecVw== - -chalk@2.4.2, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -change-case@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.1.0.tgz#0e611b7edc9952df2e8513b27b42de72647dd17e" - integrity sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw== - dependencies: - camel-case "^3.0.0" - constant-case "^2.0.0" - dot-case "^2.1.0" - header-case "^1.0.0" - is-lower-case "^1.1.0" - is-upper-case "^1.1.0" - lower-case "^1.1.1" - lower-case-first "^1.0.0" - no-case "^2.3.2" - param-case "^2.1.0" - pascal-case "^2.0.0" - path-case "^2.1.0" - sentence-case "^2.1.0" - snake-case "^2.1.0" - swap-case "^1.1.0" - title-case "^2.1.0" - upper-case "^1.1.1" - upper-case-first "^1.1.0" - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -ci-info@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -clean-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7" - integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw== - dependencies: - escape-string-regexp "^1.0.5" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-spinners@^2.2.0, cli-spinners@^2.5.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" - integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -constant-case@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46" - integrity sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ== - dependencies: - snake-case "^2.1.0" - upper-case "^1.1.1" - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -core-js-pure@^3.30.2: - version "3.37.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.37.1.tgz#2b4b34281f54db06c9a9a5bd60105046900553bd" - integrity sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -damerau-levenshtein@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" - integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== - -data-uri-to-buffer@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz#8a58bb67384b261a38ef18bea1810cb01badd28b" - integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== - -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -defaults@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" - integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== - dependencies: - clone "^1.0.2" - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.2.0, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -degenerator@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" - integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ== - dependencies: - ast-types "^0.13.4" - escodegen "^2.1.0" - esprima "^4.0.1" - -del@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" - integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== - dependencies: - globby "^10.0.1" - graceful-fs "^4.2.2" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.1" - p-map "^3.0.0" - rimraf "^3.0.0" - slash "^3.0.0" - -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -detect-indent@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25" - integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g== - -detect-newline@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-4.0.1.tgz#fcefdb5713e1fb8cb2839b8b6ee22e6716ab8f23" - integrity sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dot-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee" - integrity sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug== - dependencies: - no-case "^2.2.0" - -dotenv@16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -electron-to-chromium@^1.4.668: - version "1.4.789" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.789.tgz#fec941cb753ee139da562a5a8ff31fc3e828b411" - integrity sha512-0VbyiaXoT++Fi2vHGo2ThOeS6X3vgRCWrjPeO2FeIAWL6ItiSJ9BqlH8LfCXe3X1IdcG+S0iLoNaxQWhfZoGzQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -enhanced-resolve@^5.12.0: - version "5.17.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" - integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== - dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" - is-callable "^1.2.7" - is-data-view "^1.0.1" - is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" - object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" - string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.2.1, es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.19: - version "1.0.19" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" - integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.3" - es-errors "^1.3.0" - es-set-tostringtag "^2.0.3" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - iterator.prototype "^1.1.2" - safe-array-concat "^1.1.2" - -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== - dependencies: - es-errors "^1.3.0" - -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== - dependencies: - get-intrinsic "^1.2.4" - has-tostringtag "^1.0.2" - hasown "^2.0.1" - -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== - dependencies: - hasown "^2.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escalade@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -escodegen@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" - integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionalDependencies: - source-map "~0.6.1" - -eslint-config-prettier@^9.0.0, eslint-config-prettier@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" - integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== - -eslint-config-turbo@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-turbo/-/eslint-config-turbo-2.0.0.tgz#d3ebda365821aef48895f94c62985ddf400bf892" - integrity sha512-EtdL8t3iuj6JFHq8nESXwnu0U7K/ug7dkxTsYNctuR6udOudjLMZz3A0P131Bz5ZFmPoFmkdHjlRYwocGgLbOw== - dependencies: - eslint-plugin-turbo "2.0.0" - -eslint-import-resolver-alias@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz#297062890e31e4d6651eb5eba9534e1f6e68fc97" - integrity sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w== - -eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-import-resolver-typescript@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" - integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== - dependencies: - debug "^4.3.4" - enhanced-resolve "^5.12.0" - eslint-module-utils "^2.7.4" - fast-glob "^3.3.1" - get-tsconfig "^4.5.0" - is-core-module "^2.11.0" - is-glob "^4.0.3" - -eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" - integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== - dependencies: - debug "^3.2.7" - -eslint-plugin-eslint-comments@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa" - integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== - dependencies: - escape-string-regexp "^1.0.5" - ignore "^5.0.5" - -eslint-plugin-import@^2.28.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-plugin-jest@^27.2.3: - version "27.9.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz#7c98a33605e1d8b8442ace092b60e9919730000b" - integrity sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug== - dependencies: - "@typescript-eslint/utils" "^5.10.0" - -eslint-plugin-jsx-a11y@^6.7.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" - integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== - dependencies: - "@babel/runtime" "^7.23.2" - aria-query "^5.3.0" - array-includes "^3.1.7" - array.prototype.flatmap "^1.3.2" - ast-types-flow "^0.0.8" - axe-core "=4.7.0" - axobject-query "^3.2.1" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - es-iterator-helpers "^1.0.15" - hasown "^2.0.0" - jsx-ast-utils "^3.3.5" - language-tags "^1.0.9" - minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - -eslint-plugin-only-warn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-only-warn/-/eslint-plugin-only-warn-1.1.0.tgz#c6ddc37ddc4e72c121f07be565fcb7b6671fe78a" - integrity sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA== - -eslint-plugin-playwright@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-0.16.0.tgz#083c601a0704a7615509e63ac475bf7f0052d226" - integrity sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw== - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" - integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== - -eslint-plugin-react@^7.33.2: - version "7.34.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz#2780a1a35a51aca379d86d29b9a72adc6bfe6b66" - integrity sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw== - dependencies: - array-includes "^3.1.8" - array.prototype.findlast "^1.2.5" - array.prototype.flatmap "^1.3.2" - array.prototype.toreversed "^1.1.2" - array.prototype.tosorted "^1.1.3" - doctrine "^2.1.0" - es-iterator-helpers "^1.0.19" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.8" - object.fromentries "^2.0.8" - object.hasown "^1.1.4" - object.values "^1.2.0" - prop-types "^15.8.1" - resolve "^2.0.0-next.5" - semver "^6.3.1" - string.prototype.matchall "^4.0.11" - -eslint-plugin-testing-library@^6.0.1: - version "6.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.2.tgz#67e84ff891a2b3a8078ced0afa95ee6f343c00c1" - integrity sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ== - dependencies: - "@typescript-eslint/utils" "^5.58.0" - -eslint-plugin-tsdoc@^0.2.17: - version "0.2.17" - resolved "https://registry.yarnpkg.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz#27789495bbd8778abbf92db1707fec2ed3dfe281" - integrity sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA== - dependencies: - "@microsoft/tsdoc" "0.14.2" - "@microsoft/tsdoc-config" "0.16.2" - -eslint-plugin-turbo@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-turbo/-/eslint-plugin-turbo-2.0.0.tgz#938b95acdedd19318212d8ccab2537d2dd924bc4" - integrity sha512-31tZqfGbjBn6BzXVsmW50c2m8NDra6mOS2us/qHxUwN4YrHI/uYSpyItAw4qdVrxk7RmilvmnJ5WXFwtnfuLqw== - dependencies: - dotenv "16.0.3" - -eslint-plugin-unicorn@^48.0.1: - version "48.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz#a6573bc1687ae8db7121fdd8f92394b6549a6959" - integrity sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw== - dependencies: - "@babel/helper-validator-identifier" "^7.22.5" - "@eslint-community/eslint-utils" "^4.4.0" - ci-info "^3.8.0" - clean-regexp "^1.0.0" - esquery "^1.5.0" - indent-string "^4.0.0" - is-builtin-module "^3.2.1" - jsesc "^3.0.2" - lodash "^4.17.21" - pluralize "^8.0.0" - read-pkg-up "^7.0.1" - regexp-tree "^0.1.27" - regjsparser "^0.10.0" - semver "^7.5.4" - strip-indent "^3.0.0" - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.2, esquery@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -execa@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - 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" - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^11.2.0: - version "11.2.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" - integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - functions-have-names "^1.2.3" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-stdin@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575" - integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== - dependencies: - call-bind "^1.0.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - -get-tsconfig@^4.5.0: - version "4.7.5" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" - integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== - dependencies: - resolve-pkg-maps "^1.0.0" - -get-uri@^6.0.1: - version "6.0.3" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.3.tgz#0d26697bc13cf91092e519aa63aa60ee5b6f385a" - integrity sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw== - dependencies: - basic-ftp "^5.0.2" - data-uri-to-buffer "^6.0.2" - debug "^4.3.4" - fs-extra "^11.2.0" - -git-hooks-list@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-3.1.0.tgz#386dc531dcc17474cf094743ff30987a3d3e70fc" - integrity sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA== - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globalthis@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" - integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== - dependencies: - define-properties "^1.2.1" - gopd "^1.0.1" - -globby@^10.0.1: - version "10.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" - integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^13.1.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" - integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.3.0" - ignore "^5.2.4" - merge2 "^1.4.1" - slash "^4.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.2, graceful-fs@^4.2.4: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -gradient-string@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/gradient-string/-/gradient-string-2.0.2.tgz#a90402618990ec993ecbb72a56bd7e6598f45c0e" - integrity sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw== - dependencies: - chalk "^4.1.2" - tinygradient "^1.1.5" - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -handlebars@^4.4.3: - version "4.7.8" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" - integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.2" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -header-case@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d" - integrity sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ== - dependencies: - no-case "^2.2.0" - upper-case "^1.1.3" - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" - integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== - dependencies: - agent-base "^7.1.0" - debug "^4.3.4" - -https-proxy-agent@^7.0.2, https-proxy-agent@^7.0.3: - version "7.0.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" - integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== - dependencies: - agent-base "^7.0.2" - debug "4" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.0.5, ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3, inherits@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inquirer@^7.1.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - -inquirer@^8.0.0, inquirer@^8.2.4: - version "8.2.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" - integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.1" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.21" - mute-stream "0.0.8" - ora "^5.4.1" - run-async "^2.4.0" - rxjs "^7.5.5" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - wrap-ansi "^6.0.1" - -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" - -ip-address@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" - integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== - dependencies: - jsbn "1.1.0" - sprintf-js "^1.1.3" - -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-async-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" - integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== - dependencies: - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-builtin-module@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" - integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== - dependencies: - builtin-modules "^3.3.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.1.0, is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== - dependencies: - is-typed-array "^1.1.13" - -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== - dependencies: - call-bind "^1.0.2" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - -is-lower-case@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393" - integrity sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA== - dependencies: - lower-case "^1.1.0" - -is-map@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" - integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== - -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-inside@^3.0.1, is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" - integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-set@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" - integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== - -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== - dependencies: - call-bind "^1.0.7" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-upper-case@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f" - integrity sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw== - dependencies: - upper-case "^1.1.0" - -is-weakmap@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" - integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-weakset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" - integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isbinaryfile@^4.0.2: - version "4.0.10" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" - integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -iterator.prototype@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" - integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== - dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" - -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jju@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" - integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsbn@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" - integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" - integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: - version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" - integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - object.assign "^4.1.4" - object.values "^1.1.6" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -language-subtag-registry@^0.3.20: - version "0.3.23" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" - integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== - -language-tags@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" - integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== - dependencies: - language-subtag-registry "^0.3.20" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash@^4.17.19, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case-first@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1" - integrity sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA== - dependencies: - lower-case "^1.1.2" - -lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA== - -lru-cache@^10.2.0: - version "10.2.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" - integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^7.14.1: - version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" - integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -mkdirp@^0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -nanoid@^3.3.6: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -netmask@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" - integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== - -next@^14.1.1: - version "14.2.3" - resolved "https://registry.yarnpkg.com/next/-/next-14.2.3.tgz#f117dd5d5f20c307e7b8e4f9c1c97d961008925d" - integrity sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A== - dependencies: - "@next/env" "14.2.3" - "@swc/helpers" "0.5.5" - busboy "1.6.0" - caniuse-lite "^1.0.30001579" - graceful-fs "^4.2.11" - postcss "8.4.31" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-darwin-arm64" "14.2.3" - "@next/swc-darwin-x64" "14.2.3" - "@next/swc-linux-arm64-gnu" "14.2.3" - "@next/swc-linux-arm64-musl" "14.2.3" - "@next/swc-linux-x64-gnu" "14.2.3" - "@next/swc-linux-x64-musl" "14.2.3" - "@next/swc-win32-arm64-msvc" "14.2.3" - "@next/swc-win32-ia32-msvc" "14.2.3" - "@next/swc-win32-x64-msvc" "14.2.3" - -no-case@^2.2.0, no-case@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== - dependencies: - lower-case "^1.1.1" - -node-plop@^0.26.3: - version "0.26.3" - resolved "https://registry.yarnpkg.com/node-plop/-/node-plop-0.26.3.tgz#d6fa7e71393c8b940513ba8c4868f8aaa6dea9df" - integrity sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q== - dependencies: - "@babel/runtime-corejs3" "^7.9.2" - "@types/inquirer" "^6.5.0" - change-case "^3.1.0" - del "^5.1.0" - globby "^10.0.1" - handlebars "^4.4.3" - inquirer "^7.1.0" - isbinaryfile "^4.0.2" - lodash.get "^4.4.2" - mkdirp "^0.5.1" - resolve "^1.12.0" - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4, object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.entries@^1.1.7, object.entries@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" - integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -object.fromentries@^2.0.7, object.fromentries@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" - integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.groupby@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" - integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - -object.hasown@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" - integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== - dependencies: - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" - integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.0, onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.3: - version "0.9.4" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.5" - -ora@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-4.1.1.tgz#566cc0348a15c36f5f0e979612842e02ba9dddbc" - integrity sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A== - dependencies: - chalk "^3.0.0" - cli-cursor "^3.1.0" - cli-spinners "^2.2.0" - is-interactive "^1.0.0" - log-symbols "^3.0.0" - mute-stream "0.0.8" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - -ora@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== - dependencies: - bl "^4.1.0" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.5.0" - is-interactive "^1.0.0" - is-unicode-supported "^0.1.0" - log-symbols "^4.1.0" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" - integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== - dependencies: - aggregate-error "^3.0.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pac-proxy-agent@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz#6b9ddc002ec3ff0ba5fdf4a8a21d363bcc612d75" - integrity sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A== - dependencies: - "@tootallnate/quickjs-emscripten" "^0.23.0" - agent-base "^7.0.2" - debug "^4.3.4" - get-uri "^6.0.1" - http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.2" - pac-resolver "^7.0.0" - socks-proxy-agent "^8.0.2" - -pac-resolver@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6" - integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg== - dependencies: - degenerator "^5.0.0" - netmask "^2.0.2" - -param-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w== - dependencies: - no-case "^2.2.0" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - 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" - -pascal-case@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e" - integrity sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ== - dependencies: - camel-case "^3.0.0" - upper-case-first "^1.1.0" - -path-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5" - integrity sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q== - dependencies: - no-case "^2.2.0" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6, path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.10.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0, picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pluralize@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" - integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== - -possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== - -postcss@8.4.31: - version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-plugin-packagejson@^2.4.5: - version "2.5.0" - resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.0.tgz#23d2cb8b1f7840702d35e3a5078e564ea0bc63e0" - integrity sha512-6XkH3rpin5QEQodBSVNg+rBo4r91g/1mCaRwS1YGdQJZ6jwqrg2UchBsIG9tpS1yK1kNBvOt84OILsX8uHzBGg== - dependencies: - sort-package-json "2.10.0" - synckit "0.9.0" - -prettier@^3.2.5: - version "3.3.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.0.tgz#d173ea0524a691d4c0b1181752f2b46724328cdf" - integrity sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g== - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -proxy-agent@^6.2.2: - version "6.4.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.4.0.tgz#b4e2dd51dee2b377748aef8d45604c2d7608652d" - integrity sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ== - dependencies: - agent-base "^7.0.2" - debug "^4.3.4" - http-proxy-agent "^7.0.1" - https-proxy-agent "^7.0.3" - lru-cache "^7.14.1" - pac-proxy-agent "^7.0.1" - proxy-from-env "^1.1.0" - socks-proxy-agent "^8.0.2" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -rc@^1.0.1, rc@^1.1.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-dom@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" - integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.2" - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== - dependencies: - loose-envify "^1.1.0" - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -reflect.getprototypeof@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" - integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.1" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regexp-tree@^0.1.27: - version "0.1.27" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" - integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== - -regexp.prototype.flags@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== - dependencies: - call-bind "^1.0.6" - define-properties "^1.2.1" - es-errors "^1.3.0" - set-function-name "^2.0.1" - -registry-auth-token@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" - integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA== - dependencies: - rc "^1.0.1" - -regjsparser@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.10.0.tgz#b1ed26051736b436f22fdec1c8f72635f9f44892" - integrity sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA== - dependencies: - jsesc "~0.5.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.22.4: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.5: - version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" - integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@~1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.0, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rxjs@^6.4.0, rxjs@^6.6.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - -rxjs@^7.5.5: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-buffer@^5.0.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-regex "^1.1.4" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -scheduler@^0.23.2: - version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== - dependencies: - loose-envify "^1.1.0" - -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.5, semver@^7.3.7, semver@^7.5.4, semver@^7.6.0: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -sentence-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4" - integrity sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ== - dependencies: - no-case "^2.2.0" - upper-case-first "^1.1.2" - -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.1, set-function-name@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -snake-case@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f" - integrity sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q== - dependencies: - no-case "^2.2.0" - -socks-proxy-agent@^8.0.2: - version "8.0.3" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz#6b2da3d77364fde6292e810b496cb70440b9b89d" - integrity sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A== - dependencies: - agent-base "^7.1.1" - debug "^4.3.4" - socks "^2.7.1" - -socks@^2.7.1: - version "2.8.3" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.3.tgz#1ebd0f09c52ba95a09750afe3f3f9f724a800cb5" - integrity sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw== - dependencies: - ip-address "^9.0.5" - smart-buffer "^4.2.0" - -sort-object-keys@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" - integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== - -sort-package-json@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.10.0.tgz#6be07424bf3b7db9fbb1bdd69e7945f301026d8a" - integrity sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g== - dependencies: - detect-indent "^7.0.1" - detect-newline "^4.0.0" - get-stdin "^9.0.0" - git-hooks-list "^3.0.0" - globby "^13.1.2" - is-plain-obj "^4.1.0" - semver "^7.6.0" - sort-object-keys "^1.1.3" - -source-map-js@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - -source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" - integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.18" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== - -sprintf-js@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" - integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.matchall@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" - integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - regexp.prototype.flags "^1.5.2" - set-function-name "^2.0.2" - side-channel "^1.0.6" - -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-object-atoms "^1.0.0" - -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string.prototype.trimstart@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" - integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -swap-case@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3" - integrity sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ== - dependencies: - lower-case "^1.1.1" - upper-case "^1.1.1" - -synckit@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.0.tgz#5b33b458b3775e4466a5b377fba69c63572ae449" - integrity sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg== - dependencies: - "@pkgr/core" "^0.1.0" - tslib "^2.6.2" - -tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -tinycolor2@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" - integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== - -tinygradient@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/tinygradient/-/tinygradient-1.1.5.tgz#0fb855ceb18d96b21ba780b51a8012033b2530ef" - integrity sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw== - dependencies: - "@types/tinycolor2" "^1.4.0" - tinycolor2 "^1.0.0" - -title-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" - integrity sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q== - dependencies: - no-case "^2.2.0" - upper-case "^1.0.3" - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - -ts-node@^10.9.1: - version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - 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" - -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^1.8.1, tslib@^1.9.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -turbo-darwin-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.0.3.tgz#52c5f79b4027dfd0184fb963da41bf989be4a00d" - integrity sha512-v7ztJ8sxdHw3SLfO2MhGFeeU4LQhFii1hIGs9uBiXns/0YTGOvxLeifnfGqhfSrAIIhrCoByXO7nR9wlm10n3Q== - -turbo-darwin-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.3.tgz#46fa54d0cd95782ac38015e3396d59cdbdeb1eb8" - integrity sha512-LUcqvkV9Bxtng6QHbevp8IK8zzwbIxM6HMjCE7FEW6yJBN1KwvTtRtsGBwwmTxaaLO0wD1Jgl3vgkXAmQ4fqUw== - -turbo-linux-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.0.3.tgz#17d6714b32381d474ef2ee5613343165f9bd75bc" - integrity sha512-xpdY1suXoEbsQsu0kPep2zrB8ijv/S5aKKrntGuQ62hCiwDFoDcA/Z7FZ8IHQ2u+dpJARa7yfiByHmizFE0r5Q== - -turbo-linux-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.0.3.tgz#4f1bfe421dcecf2fb1164a1e223ba310d6e28b6f" - integrity sha512-MBACTcSR874L1FtLL7gkgbI4yYJWBUCqeBN/iE29D+8EFe0d3fAyviFlbQP4K/HaDYet1i26xkkOiWr0z7/V9A== - -turbo-windows-64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.0.3.tgz#9d1b99aff361bcbf4e065029e9dfa6682a0c0b2d" - integrity sha512-zi3YuKPkM9JxMTshZo3excPk37hUrj5WfnCqh4FjI26ux6j/LJK+Dh3SebMHd9mR7wP9CMam4GhmLCT+gDfM+w== - -turbo-windows-arm64@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.0.3.tgz#0e0641acda3325a4a3d28123ef21017a7aae8f38" - integrity sha512-wmed4kkenLvRbidi7gISB4PU77ujBuZfgVGDZ4DXTFslE/kYpINulwzkVwJIvNXsJtHqyOq0n6jL8Zwl3BrwDg== - -turbo@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.0.3.tgz#789f64666d15dbc6fc85ce507a6c6888d70df88f" - integrity sha512-jF1K0tTUyryEWmgqk1V0ALbSz3VdeZ8FXUo6B64WsPksCMCE48N5jUezGOH2MN0+epdaRMH8/WcPU0QQaVfeLA== - optionalDependencies: - turbo-darwin-64 "2.0.3" - turbo-darwin-arm64 "2.0.3" - turbo-linux-64 "2.0.3" - turbo-linux-arm64 "2.0.3" - turbo-windows-64 "2.0.3" - turbo-windows-arm64 "2.0.3" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-typed-array "^1.1.13" - -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - -typescript@5.5.4: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== - -uglify-js@^3.1.4: - version "3.17.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -universalify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== - -update-browserslist-db@^1.0.13: - version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" - integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== - dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" - -update-check@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.4.tgz#5b508e259558f1ad7dbc8b4b0457d4c9d28c8743" - integrity sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ== - dependencies: - registry-auth-token "3.3.2" - registry-url "3.1.0" - -upper-case-first@^1.1.0, upper-case-first@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115" - integrity sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ== - dependencies: - upper-case "^1.1.1" - -upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -validate-npm-package-name@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" - integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== - dependencies: - defaults "^1.0.3" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-builtin-type@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" - integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== - dependencies: - function.prototype.name "^1.1.5" - has-tostringtag "^1.0.0" - is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" - is-generator-function "^1.0.10" - is-regex "^1.1.4" - is-weakref "^1.0.2" - isarray "^2.0.5" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" - -which-collection@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" - integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== - dependencies: - is-map "^2.0.3" - is-set "^2.0.3" - is-weakmap "^2.0.2" - is-weakset "^2.0.3" - -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.2" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/package.json b/package.json index 93e872dc32078..3f4e5baa42cac 100644 --- a/package.json +++ b/package.json @@ -1,46 +1,35 @@ { - "name": "turbo-monorepo", - "version": "0.0.0", - "private": true, - "scripts": { - "build": "pnpm -- turbo run build", - "build:turbo": "pnpm run --filter=cli build", - "build:ts": "tsc -b tsconfig.project.json", - "lint:prettier": "turbo run lint:prettier", - "check:toml": "taplo format --check", - "turbo": "pnpm run build:turbo && node turbow.js", - "turbo-prebuilt": "node turbow.js", - "prepare": "husky install", - "test": "turbo run test", - "test:integration": "pnpm --filter turborepo-tests-integration exec prysk", - "rustdoc": "RUSTDOCFLAGS=\"-Z unstable-options --enable-index-page\" cargo doc --workspace --no-deps --keep-going || true", - "rustdoc:open": "RUSTDOCFLAGS=\"-Z unstable-options --enable-index-page\" cargo doc --workspace --no-deps --keep-going --open" - }, - "devDependencies": { - "@taplo/cli": "^0.5.2", - "eslint": "^8.55.0", - "husky": "^8.0.0", - "lint-staged": "^13.1.0", - "prettier": "^2.8.7", - "semver": "^7.3.8", - "typescript": "5.5.4" - }, - "lint-staged": { - "*.{js,jsx,ts,tsx}": [ - "prettier --write" - ], - "*.{md,mdx,mjs,yml,yaml,css}": [ - "prettier --write" - ], - "*.toml": [ - "taplo format" - ], - "*.rs": [ - "cargo fmt --" - ] - }, - "packageManager": "pnpm@8.14.0", - "engines": { - "node": "20.x" - } + "name": "turbo-monorepo", + "scripts": { + "build": "pnpm -- turbo run build", + "build:ts": "tsc -b tsconfig.project.json", + "build:turbo": "pnpm run --filter=cli build", + "check:toml": "taplo format --check", + "prepare": "husky install", + "rustdoc": "RUSTDOCFLAGS=\"-Z unstable-options --enable-index-page\" cargo doc --workspace --no-deps --keep-going || true", + "rustdoc:open": "RUSTDOCFLAGS=\"-Z unstable-options --enable-index-page\" cargo doc --workspace --no-deps --keep-going --open", + "test:integration": "pnpm --filter turborepo-tests-integration exec prysk", + "turbo": "pnpm run build:turbo && node turbow.js", + "turbo-prebuilt": "node turbow.js" + }, + "lint-staged": { + "*.rs": [ + "cargo fmt --" + ], + "*.toml": [ + "taplo format" + ], + "*.{js,jsx,ts,tsx}": [ + "prettier --write" + ], + "*.{md,mdx,mjs,yml,yaml,css}": [ + "prettier --write" + ] + }, + "dependencies": {}, + "devDependencies": { + "@taplo/cli": "0.7.0", + "lint-staged": "15.4.3", + "semver": "7.7.1" + } } diff --git a/packages/create-turbo/.eslintrc.js b/packages/create-turbo/.eslintrc.js deleted file mode 100644 index 4ca761e2f8eb5..0000000000000 --- a/packages/create-turbo/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], -}; diff --git a/packages/create-turbo/README.md b/packages/create-turbo/README.md deleted file mode 100644 index 51e26c90a4205..0000000000000 --- a/packages/create-turbo/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Welcome to Turborepo - -[Turborepo](https://turbo.build/repo) is a high-performance monorepo build-system for modern JavaScript and TypeScript codebases. - -To get started, open a new shell and run: - -```sh -npx create-turbo@latest -``` - -Then follow the prompts you see in your terminal. - -For more information about Turborepo, [visit turbo.build/repo](https://turbo.build/repo) and follow us on X ([@turborepo](https://x.com/turborepo))! - -## Contributing - -If you're working on updating the `basic` example that `create-turbo` uses and would like to test the end-to-end workflow, you'll need to follow a few steps: - -1. Push your code updates for `basic` to a branch on GitHub. -2. Run `./dist/cli.js -e [GITHUB_BRANCH]/examples/basic`. diff --git a/packages/create-turbo/src/cli.ts b/packages/create-turbo/Source/cli.ts similarity index 100% rename from packages/create-turbo/src/cli.ts rename to packages/create-turbo/Source/cli.ts diff --git a/packages/create-turbo/src/commands/create/index.ts b/packages/create-turbo/Source/commands/create/index.ts similarity index 100% rename from packages/create-turbo/src/commands/create/index.ts rename to packages/create-turbo/Source/commands/create/index.ts diff --git a/packages/create-turbo/src/commands/create/prompts.ts b/packages/create-turbo/Source/commands/create/prompts.ts similarity index 100% rename from packages/create-turbo/src/commands/create/prompts.ts rename to packages/create-turbo/Source/commands/create/prompts.ts diff --git a/packages/create-turbo/src/commands/create/types.ts b/packages/create-turbo/Source/commands/create/types.ts similarity index 100% rename from packages/create-turbo/src/commands/create/types.ts rename to packages/create-turbo/Source/commands/create/types.ts diff --git a/packages/create-turbo/src/commands/index.ts b/packages/create-turbo/Source/commands/index.ts similarity index 100% rename from packages/create-turbo/src/commands/index.ts rename to packages/create-turbo/Source/commands/index.ts diff --git a/packages/create-turbo/src/transforms/errors.ts b/packages/create-turbo/Source/transforms/errors.ts similarity index 100% rename from packages/create-turbo/src/transforms/errors.ts rename to packages/create-turbo/Source/transforms/errors.ts diff --git a/packages/create-turbo/src/transforms/git-ignore.ts b/packages/create-turbo/Source/transforms/git-ignore.ts similarity index 100% rename from packages/create-turbo/src/transforms/git-ignore.ts rename to packages/create-turbo/Source/transforms/git-ignore.ts diff --git a/packages/create-turbo/src/transforms/index.ts b/packages/create-turbo/Source/transforms/index.ts similarity index 100% rename from packages/create-turbo/src/transforms/index.ts rename to packages/create-turbo/Source/transforms/index.ts diff --git a/packages/create-turbo/src/transforms/official-starter.ts b/packages/create-turbo/Source/transforms/official-starter.ts similarity index 100% rename from packages/create-turbo/src/transforms/official-starter.ts rename to packages/create-turbo/Source/transforms/official-starter.ts diff --git a/packages/create-turbo/src/transforms/package-manager.ts b/packages/create-turbo/Source/transforms/package-manager.ts similarity index 100% rename from packages/create-turbo/src/transforms/package-manager.ts rename to packages/create-turbo/Source/transforms/package-manager.ts diff --git a/packages/create-turbo/src/transforms/pnpm-eslint.ts b/packages/create-turbo/Source/transforms/pnpm-eslint.ts similarity index 100% rename from packages/create-turbo/src/transforms/pnpm-eslint.ts rename to packages/create-turbo/Source/transforms/pnpm-eslint.ts diff --git a/packages/create-turbo/src/transforms/types.ts b/packages/create-turbo/Source/transforms/types.ts similarity index 100% rename from packages/create-turbo/src/transforms/types.ts rename to packages/create-turbo/Source/transforms/types.ts diff --git a/packages/create-turbo/src/utils/git.ts b/packages/create-turbo/Source/utils/git.ts similarity index 100% rename from packages/create-turbo/src/utils/git.ts rename to packages/create-turbo/Source/utils/git.ts diff --git a/packages/create-turbo/src/utils/isDefaultExample.ts b/packages/create-turbo/Source/utils/isDefaultExample.ts similarity index 100% rename from packages/create-turbo/src/utils/isDefaultExample.ts rename to packages/create-turbo/Source/utils/isDefaultExample.ts diff --git a/packages/create-turbo/src/utils/isOnline.ts b/packages/create-turbo/Source/utils/isOnline.ts similarity index 100% rename from packages/create-turbo/src/utils/isOnline.ts rename to packages/create-turbo/Source/utils/isOnline.ts diff --git a/packages/create-turbo/src/utils/notifyUpdate.ts b/packages/create-turbo/Source/utils/notifyUpdate.ts similarity index 100% rename from packages/create-turbo/src/utils/notifyUpdate.ts rename to packages/create-turbo/Source/utils/notifyUpdate.ts diff --git a/packages/create-turbo/__tests__/git.test.ts b/packages/create-turbo/__tests__/git.test.ts deleted file mode 100644 index a78698f60d0cf..0000000000000 --- a/packages/create-turbo/__tests__/git.test.ts +++ /dev/null @@ -1,246 +0,0 @@ -import path from "node:path"; -import childProcess from "node:child_process"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { - DEFAULT_IGNORE, - GIT_REPO_COMMAND, - HG_REPO_COMMAND, - isInGitRepository, - isInMercurialRepository, - tryGitInit, -} from "../src/utils/git"; - -describe("git", () => { - // just to make sure this doesn't get lost - it("default .gitignore includes .turbo", async () => { - expect(DEFAULT_IGNORE).toContain(".turbo"); - }); - - describe("isInGitRepository", () => { - it("returns true when in a repo", async () => { - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockReturnValue("true"); - - const result = isInGitRepository(); - expect(result).toBe(true); - - expect(mockExecSync).toHaveBeenCalledWith(GIT_REPO_COMMAND, { - stdio: "ignore", - }); - mockExecSync.mockRestore(); - }); - - it("returns false when not in a repo", async () => { - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementation(() => { - throw new Error( - "fatal: not a git repository (or any of the parent directories): .git" - ); - }); - - const result = isInGitRepository(); - expect(result).toBe(false); - - expect(mockExecSync).toHaveBeenCalledWith(GIT_REPO_COMMAND, { - stdio: "ignore", - }); - mockExecSync.mockRestore(); - }); - - it("returns false on error", async () => { - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementation(() => { - throw new Error("unknown error"); - }); - - const result = isInGitRepository(); - expect(result).toBe(false); - - expect(mockExecSync).toHaveBeenCalledWith(GIT_REPO_COMMAND, { - stdio: "ignore", - }); - mockExecSync.mockRestore(); - }); - }); - - describe("isInMercurialRepository", () => { - it("returns true when in a repo", async () => { - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockReturnValue("true"); - - const result = isInMercurialRepository(); - expect(result).toBe(true); - - expect(mockExecSync).toHaveBeenCalledWith(HG_REPO_COMMAND, { - stdio: "ignore", - }); - mockExecSync.mockRestore(); - }); - - it("returns false when not in a repo", async () => { - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementation(() => { - throw new Error("abort: no repository found (.hg not found)"); - }); - - const result = isInMercurialRepository(); - expect(result).toBe(false); - - expect(mockExecSync).toHaveBeenCalledWith(HG_REPO_COMMAND, { - stdio: "ignore", - }); - mockExecSync.mockRestore(); - }); - - it("returns false on error", async () => { - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementation(() => { - throw new Error("unknown error"); - }); - - const result = isInMercurialRepository(); - expect(result).toBe(false); - - expect(mockExecSync).toHaveBeenCalledWith(HG_REPO_COMMAND, { - stdio: "ignore", - }); - mockExecSync.mockRestore(); - }); - }); - - describe("tryGitInit", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - options: { emptyFixture: true }, - }); - - it("inits a repo successfully", async () => { - const { root } = useFixture({ fixture: `git` }); - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementationOnce(() => { - throw new Error( - "fatal: not a git repository (or any of the parent directories): .git" - ); - }) - .mockImplementationOnce(() => { - throw new Error("abort: no repository found (.hg not found)"); - }) - .mockReturnValue("success"); - - const result = tryGitInit(root, "test commit"); - expect(result).toBe(true); - - const calls = [ - "git init", - "git checkout -b main", - "git add -A", - 'git commit --author="Turbobot " -am "test commit"', - ]; - expect(mockExecSync).toHaveBeenCalledTimes(calls.length + 2); - calls.forEach((call) => { - expect(mockExecSync).toHaveBeenCalledWith(call, { - stdio: "ignore", - }); - }); - mockExecSync.mockRestore(); - }); - - it("skips init if already in a repo", async () => { - const { root } = useFixture({ - fixture: `git`, - }); - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockReturnValueOnce("true") - .mockReturnValue("success"); - - const result = tryGitInit(root, "test commit"); - expect(result).toBe(false); - - const calls: string[] = []; - - // 1 call for isInGitRepository - expect(mockExecSync).toHaveBeenCalledTimes(calls.length + 1); - calls.forEach((call) => { - expect(mockExecSync).toHaveBeenCalledWith(call, { - stdio: "ignore", - }); - }); - mockExecSync.mockRestore(); - }); - - it("returns false on unexpected error", async () => { - const { root } = useFixture({ fixture: `git` }); - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementationOnce(() => { - throw new Error( - "fatal: not a git repository (or any of the parent directories): .git" - ); - }) - .mockImplementationOnce(() => { - throw new Error("abort: no repository found (.hg not found)"); - }) - .mockImplementationOnce(() => { - throw new Error("fatal: 128"); - }); - - const result = tryGitInit(root, "test commit"); - expect(result).toBe(false); - - const calls: string[] = [GIT_REPO_COMMAND, HG_REPO_COMMAND, "git init"]; - - expect(mockExecSync).toHaveBeenCalledTimes(calls.length); - calls.forEach((call) => { - expect(mockExecSync).toHaveBeenCalledWith(call, { - stdio: "ignore", - }); - }); - mockExecSync.mockRestore(); - }); - - it("cleans up from partial init on failure", async () => { - const { root } = useFixture({ fixture: `git` }); - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementationOnce(() => { - throw new Error( - "fatal: not a git repository (or any of the parent directories): .git" - ); - }) - .mockImplementationOnce(() => { - throw new Error("abort: no repository found (.hg not found)"); - }) - .mockReturnValueOnce("success") - .mockReturnValueOnce("success") - .mockImplementationOnce(() => { - throw new Error("fatal: could not add files"); - }); - - const result = tryGitInit(root, "test commit"); - expect(result).toBe(false); - - const calls = [ - "git rev-parse --is-inside-work-tree", - "hg --cwd . root", - "git init", - ]; - - expect(mockExecSync).toHaveBeenCalledTimes(calls.length + 2); - calls.forEach((call) => { - expect(mockExecSync).toHaveBeenCalledWith(call, { - stdio: "ignore", - }); - }); - mockExecSync.mockRestore(); - }); - }); -}); diff --git a/packages/create-turbo/__tests__/index.test.ts b/packages/create-turbo/__tests__/index.test.ts deleted file mode 100644 index ff33e849754f1..0000000000000 --- a/packages/create-turbo/__tests__/index.test.ts +++ /dev/null @@ -1,278 +0,0 @@ -import path from "node:path"; -import childProcess from "node:child_process"; -import picocolors from "picocolors"; -import { setupTestFixtures, spyConsole, spyExit } from "@turbo/test-utils"; -import { logger } from "@turbo/utils"; -import type { PackageManager } from "@turbo/utils"; -// imports for mocks -import * as turboWorkspaces from "@turbo/workspaces"; -import { CreateTurboTelemetry, TelemetryConfig } from "@turbo/telemetry"; -import * as turboUtils from "@turbo/utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import type { CreateCommandArgument } from "../src/commands/create/types"; -import { create } from "../src/commands/create"; -import { getWorkspaceDetailsMockReturnValue } from "./test-utils"; - -jest.mock("@turbo/workspaces", () => ({ - __esModule: true, - ...jest.requireActual("@turbo/workspaces"), -})); - -describe("create-turbo", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - options: { emptyFixture: true }, - }); - - const mockConsole = spyConsole(); - const mockExit = spyExit(); - const telemetry = new CreateTurboTelemetry({ - api: "https://example.com", - packageInfo: { - name: "create-turbo", - version: "1.0.0", - }, - config: new TelemetryConfig({ - configPath: "test-config-path", - config: { - telemetry_enabled: false, - telemetry_id: "telemetry-test-id", - telemetry_salt: "telemetry-salt", - }, - }), - }); - - it.each<{ packageManager: PackageManager }>([ - { packageManager: "yarn" }, - { packageManager: "npm" }, - { packageManager: "pnpm" }, - { packageManager: "bun" }, - ])( - "outputs expected console messages when using $packageManager (option)", - async ({ packageManager }) => { - const { root } = useFixture({ fixture: "create-turbo" }); - - const availableScripts = ["build", "test", "dev"]; - - const mockAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - npm: "8.19.2", - yarn: "1.22.10", - pnpm: "7.22.2", - bun: "1.0.1", - }); - - const mockCreateProject = jest - .spyOn(turboUtils, "createProject") - .mockResolvedValue({ - cdPath: "", - hasPackageJson: true, - availableScripts, - }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementation(() => { - return "success"; - }); - - await create(root as CreateCommandArgument, { - packageManager, - skipInstall: true, - example: "default", - telemetry, - }); - - const expected = `${picocolors.bold( - logger.turboGradient(">>> Success!") - )} Created your Turborepo at ${picocolors.green( - path.relative(process.cwd(), root) - )}`; - expect(mockConsole.log).toHaveBeenCalledWith(expected); - expect(mockConsole.log).toHaveBeenCalledWith(); - expect(mockConsole.log).toHaveBeenCalledWith( - picocolors.bold("To get started:") - ); - - expect(mockConsole.log).toHaveBeenCalledWith( - picocolors.cyan("Library packages") - ); - - expect(mockConsole.log).toHaveBeenCalledWith( - "- Run commands with Turborepo:" - ); - - availableScripts.forEach((script) => { - expect(mockConsole.log).toHaveBeenCalledWith( - expect.stringContaining( - picocolors.cyan(`${packageManager} run ${script}`) - ) - ); - }); - - expect(mockConsole.log).toHaveBeenCalledWith( - "- Run a command twice to hit cache" - ); - - mockAvailablePackageManagers.mockRestore(); - mockCreateProject.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - mockExecSync.mockRestore(); - } - ); - - it.each<{ packageManager: PackageManager }>([ - { packageManager: "yarn" }, - { packageManager: "npm" }, - { packageManager: "pnpm" }, - { packageManager: "bun" }, - ])( - "outputs expected console messages when using $packageManager (arg)", - async ({ packageManager }) => { - const { root } = useFixture({ fixture: "create-turbo" }); - - const availableScripts = ["build", "test", "dev"]; - - const mockAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - npm: "8.19.2", - yarn: "1.22.10", - pnpm: "7.22.2", - bun: "1.0.1", - }); - - const mockCreateProject = jest - .spyOn(turboUtils, "createProject") - .mockResolvedValue({ - cdPath: "", - hasPackageJson: true, - availableScripts, - }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementation(() => { - return "success"; - }); - - await create(root as CreateCommandArgument, { - packageManager, - skipInstall: true, - example: "default", - telemetry, - }); - - const expected = `${picocolors.bold( - logger.turboGradient(">>> Success!") - )} Created your Turborepo at ${picocolors.green( - path.relative(process.cwd(), root) - )}`; - expect(mockConsole.log).toHaveBeenCalledWith(expected); - expect(mockConsole.log).toHaveBeenCalledWith(); - expect(mockConsole.log).toHaveBeenCalledWith( - picocolors.bold("To get started:") - ); - - expect(mockConsole.log).toHaveBeenCalledWith( - picocolors.cyan("Library packages") - ); - - expect(mockConsole.log).toHaveBeenCalledWith( - "- Run commands with Turborepo:" - ); - - availableScripts.forEach((script) => { - expect(mockConsole.log).toHaveBeenCalledWith( - expect.stringContaining( - picocolors.cyan(`${packageManager} run ${script}`) - ) - ); - }); - - expect(mockConsole.log).toHaveBeenCalledWith( - "- Run a command twice to hit cache" - ); - mockAvailablePackageManagers.mockRestore(); - mockCreateProject.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - mockExecSync.mockRestore(); - } - ); - - it("throws correct error message when a download error is encountered", async () => { - const { root } = useFixture({ fixture: "create-turbo" }); - const packageManager = "pnpm"; - const mockAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - npm: "8.19.2", - yarn: "1.22.10", - pnpm: "7.22.2", - bun: "1.0.1", - }); - - const mockCreateProject = jest - .spyOn(turboUtils, "createProject") - .mockRejectedValue(new turboUtils.DownloadError("Could not connect")); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - const mockExecSync = jest - .spyOn(childProcess, "execSync") - .mockImplementation(() => { - return "success"; - }); - - await create(root as CreateCommandArgument, { - packageManager, - skipInstall: true, - example: "default", - telemetry, - }); - - expect(mockConsole.error).toHaveBeenCalledTimes(2); - expect(mockConsole.error).toHaveBeenNthCalledWith( - 1, - logger.turboRed(picocolors.bold(">>>")), - picocolors.red("Unable to download template from GitHub") - ); - expect(mockConsole.error).toHaveBeenNthCalledWith( - 2, - logger.turboRed(picocolors.bold(">>>")), - picocolors.red("Could not connect") - ); - expect(mockExit.exit).toHaveBeenCalledWith(1); - - mockAvailablePackageManagers.mockRestore(); - mockCreateProject.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - mockExecSync.mockRestore(); - }); -}); diff --git a/packages/create-turbo/__tests__/test-utils.ts b/packages/create-turbo/__tests__/test-utils.ts deleted file mode 100644 index f5a4802cba4cd..0000000000000 --- a/packages/create-turbo/__tests__/test-utils.ts +++ /dev/null @@ -1,34 +0,0 @@ -import path from "path"; -import type { PackageManager } from "@turbo/utils"; - -export function getWorkspaceDetailsMockReturnValue({ - root, - packageManager = "npm", -}: { - root: string; - packageManager: PackageManager; -}) { - return { - name: "mock-project", - packageManager, - paths: { - root, - packageJson: path.join(root, "package.json"), - lockfile: path.join(root, "yarn.lock"), - nodeModules: path.join(root, "node_modules"), - }, - workspaceData: { - globs: ["packages/*"], - workspaces: [ - { - name: "packages/mock-package", - paths: { - root: path.join(root, "packages/mock-package"), - packageJson: path.join(root, "packages/mock-package/package.json"), - nodeModules: path.join(root, "packages/mock-package/node_modules"), - }, - }, - ], - }, - }; -} diff --git a/packages/create-turbo/jest.config.js b/packages/create-turbo/jest.config.js new file mode 100644 index 0000000000000..f81b1d034970b --- /dev/null +++ b/packages/create-turbo/jest.config.js @@ -0,0 +1,12 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: "ts-jest/presets/js-with-ts", + testEnvironment: "node", + testPathIgnorePatterns: ["/__fixtures__/", "/__tests__/test-utils.ts"], + coveragePathIgnorePatterns: ["/__fixtures__/", "/__tests__/test-utils.ts"], + transformIgnorePatterns: ["node_modules/*", "packages/turbo-workspaces/*"], + modulePathIgnorePatterns: ["/node_modules", "/dist"], + collectCoverage: true, + verbose: process.env.RUNNER_DEBUG === "1", + silent: process.env.RUNNER_DEBUG !== "1", +}; diff --git a/packages/create-turbo/package.json b/packages/create-turbo/package.json index 870679b2aefec..c11fd12b11e9f 100644 --- a/packages/create-turbo/package.json +++ b/packages/create-turbo/package.json @@ -23,30 +23,30 @@ "lint:prettier": "prettier -c . --cache --ignore-path=../../.prettierignore" }, "dependencies": { - "commander": "^11.0.0", - "fs-extra": "^11.1.1", - "inquirer": "^8.0.0", - "picocolors": "1.0.1", - "proxy-agent": "^6.2.2", - "semver": "^7.3.8", - "update-check": "^1.5.4" + "commander": "13.1.0", + "fs-extra": "11.3.0", + "inquirer": "12.4.1", + "picocolors": "1.1.1", + "proxy-agent": "6.5.0", + "semver": "7.7.1", + "update-check": "1.5.4" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@turbo/eslint-config": "workspace:*", "@turbo/telemetry": "workspace:*", "@turbo/test-utils": "workspace:*", "@turbo/tsconfig": "workspace:*", "@turbo/utils": "workspace:*", "@turbo/workspaces": "workspace:*", - "@types/fs-extra": "^9.0.13", - "@types/inquirer": "^7.3.1", - "@types/node": "^18.17.2", - "@types/semver": "^7.3.9", - "jest": "^29.7.0", - "ts-jest": "^29.2.5", - "tsup": "^6.7.0", - "typescript": "5.5.4" + "@types/fs-extra": "11.0.4", + "@types/inquirer": "9.0.7", + "@types/node": "22.13.1", + "@types/semver": "7.5.8", + "jest": "29.7.0", + "ts-jest": "29.2.5", + "tsup": "8.3.6", + "typescript": "5.7.3" }, "files": [ "dist" diff --git a/packages/devlow-bench/Source/browser.ts b/packages/devlow-bench/Source/browser.ts new file mode 100644 index 0000000000000..1a6ca8e86d669 --- /dev/null +++ b/packages/devlow-bench/Source/browser.ts @@ -0,0 +1,370 @@ +import type { + Browser, + BrowserContext, + ConsoleMessage, + Page, + Request, + Response, +} from "playwright-chromium"; +import { chromium } from "playwright-chromium"; +import { measureTime, reportMeasurement } from "./index.js"; + +interface BrowserSession { + close(): Promise; + hardNavigation(metricName: string, url: string): Promise; + softNavigationByClick(metricName: string, selector: string): Promise; + reload(metricName: string): Promise; +} + +const browserOutput = Boolean(process.env.BROWSER_OUTPUT); + +async function withRequestMetrics( + metricName: string, + page: Page, + fn: () => Promise +): Promise { + const activePromises: Array> = []; + const sizeByExtension = new Map(); + const requestsByExtension = new Map(); + const responseHandler = (response: Response) => { + activePromises.push( + (async () => { + const url = response.request().url(); + const status = response.status(); + const extension = + // eslint-disable-next-line prefer-named-capture-group -- TODO: address lint + /^[^?#]+\.([a-z0-9]+)(?:[?#]|$)/i.exec(url)?.[1] ?? "none"; + const currentRequests = requestsByExtension.get(extension) ?? 0; + requestsByExtension.set(extension, currentRequests + 1); + if (status >= 200 && status < 300) { + let body; + try { + body = await response.body(); + } catch { + // empty + } + if (body) { + const size = body.length; + const current = sizeByExtension.get(extension) ?? 0; + sizeByExtension.set(extension, current + size); + } + } + })() + ); + }; + let errorCount = 0; + let warningCount = 0; + let logCount = 0; + const consoleHandler = (message: ConsoleMessage) => { + const type = message.type(); + if (type === "error") { + errorCount++; + } else if (type === "warning") { + warningCount++; + } else { + logCount++; + } + if (browserOutput) { + activePromises.push( + (async () => { + const args = []; + try { + const text = message.text(); + for (const arg of message.args()) { + args.push(await arg.jsonValue()); + } + console.log(`[${type}] ${text}`, ...args); + } catch { + // Ignore + } + })() + ); + } + }; + let uncaughtCount = 0; + const exceptionHandler = (error: Error) => { + uncaughtCount++; + if (browserOutput) { + console.error(`[UNCAUGHT]`, error); + } + }; + try { + page.on("response", responseHandler); + page.on("console", consoleHandler); + page.on("pageerror", exceptionHandler); + await fn(); + await Promise.all(activePromises); + let totalDownload = 0; + for (const [extension, size] of sizeByExtension.entries()) { + await reportMeasurement( + `${metricName}/responseSizes/${extension}`, + size, + "bytes" + ); + totalDownload += size; + } + await reportMeasurement( + `${metricName}/responseSizes`, + totalDownload, + "bytes" + ); + let totalRequests = 0; + for (const [extension, count] of requestsByExtension.entries()) { + await reportMeasurement( + `${metricName}/requests/${extension}`, + count, + "requests" + ); + totalRequests += count; + } + await reportMeasurement( + `${metricName}/requests`, + totalRequests, + "requests" + ); + await reportMeasurement(`${metricName}/console/logs`, logCount, "messages"); + await reportMeasurement( + `${metricName}/console/warnings`, + warningCount, + "messages" + ); + await reportMeasurement( + `${metricName}/console/errors`, + errorCount, + "messages" + ); + await reportMeasurement( + `${metricName}/console/uncaught`, + uncaughtCount, + "messages" + ); + await reportMeasurement( + `${metricName}/console`, + logCount + warningCount + errorCount + uncaughtCount, + "messages" + ); + } finally { + page.off("response", responseHandler); + } +} + +/** + * Waits until network requests have all been resolved + * @param page - Playwright page object + * @param delayMs - Amount of time in ms to wait after the last request resolves before cleaning up + * @param timeoutMs - Amount of time to wait before continuing. In case of timeout, this function resolves + * @returns + */ +function networkIdle( + page: Page, + delayMs = 300, + timeoutMs = 180000 +): Promise { + return new Promise((resolve) => { + const cleanup = () => { + page.off("request", requestHandler); + page.off("requestfailed", requestFinishedHandler); + page.off("requestfinished", requestFinishedHandler); + clearTimeout(fullTimeout); + if (timeout) { + clearTimeout(timeout); + } + }; + + const requests = new Map(); + const start = Date.now(); + let lastRequest: number; + let timeout: NodeJS.Timeout | null = null; + + const fullTimeout = setTimeout(() => { + cleanup(); + // eslint-disable-next-line no-console -- logging + console.error( + `Timeout while waiting for network idle. These requests are still pending: ${Array.from( + requests + ).join(", ")}} time is ${lastRequest - start}` + ); + resolve(Date.now() - lastRequest); + }, timeoutMs); + + const requestFilter = (request: Request) => { + return request.headers().accept !== "text/event-stream"; + }; + + const requestHandler = (request: Request) => { + requests.set(request.url(), (requests.get(request.url()) ?? 0) + 1); + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + // Avoid tracking some requests, but we only know this after awaiting + // so we need to do this weird stunt to ensure that + if (!requestFilter(request)) { + requestFinishedInternal(request); + } + }; + + const requestFinishedHandler = (request: Request) => { + if (requestFilter(request)) { + requestFinishedInternal(request); + } + }; + + const requestFinishedInternal = (request: Request) => { + lastRequest = Date.now(); + const currentCount = requests.get(request.url()); + if (currentCount === undefined) { + // eslint-disable-next-line no-console -- basic logging + console.error( + `Unexpected untracked but completed request ${request.url()}` + ); + return; + } + + if (currentCount === 1) { + requests.delete(request.url()); + } else { + requests.set(request.url(), currentCount - 1); + } + + if (requests.size === 0) { + timeout = setTimeout(() => { + cleanup(); + resolve(Date.now() - lastRequest); + }, delayMs); + } + }; + + page.on("request", requestHandler); + page.on("requestfailed", requestFinishedHandler); + page.on("requestfinished", requestFinishedHandler); + }); +} + +class BrowserSessionImpl implements BrowserSession { + private browser: Browser; + private context: BrowserContext; + private page: Page | null; + constructor(browser: Browser, context: BrowserContext) { + this.browser = browser; + this.context = context; + this.page = null; + } + + async close() { + if (this.page) { + await this.page.close(); + } + await this.context.close(); + await this.browser.close(); + } + + async hardNavigation(metricName: string, url: string) { + this.page = this.page ?? (await this.context.newPage()); + + const page = this.page; + await withRequestMetrics(metricName, page, async () => { + await measureTime(`${metricName}/start`); + const idle = networkIdle(page, 3000); + await page.goto(url, { + waitUntil: "commit", + }); + await measureTime(`${metricName}/html`, { + relativeTo: `${metricName}/start`, + }); + await page.waitForLoadState("domcontentloaded"); + await measureTime(`${metricName}/dom`, { + relativeTo: `${metricName}/start`, + }); + await page.waitForLoadState("load"); + await measureTime(`${metricName}/load`, { + relativeTo: `${metricName}/start`, + }); + const offset = await idle; + await measureTime(`${metricName}`, { + offset, + relativeTo: `${metricName}/start`, + }); + }); + return page; + } + + async softNavigationByClick(metricName: string, selector: string) { + const page = this.page; + if (!page) { + throw new Error( + "softNavigationByClick() must be called after hardNavigation()" + ); + } + await withRequestMetrics(metricName, page, async () => { + await measureTime(`${metricName}/start`); + const firstResponse = new Promise((resolve) => { + page.once("response", () => { + resolve(); + }); + }); + const idle = networkIdle(page, 3000); + await page.click(selector); + await firstResponse; + await measureTime(`${metricName}/firstResponse`, { + relativeTo: `${metricName}/start`, + }); + await idle; + await measureTime(`${metricName}`, { + offset: 3000, + relativeTo: `${metricName}/start`, + }); + }); + } + + async reload(metricName: string) { + const page = this.page; + if (!page) { + throw new Error("reload() must be called after hardNavigation()"); + } + await withRequestMetrics(metricName, page, async () => { + await measureTime(`${metricName}/start`); + const idle = networkIdle(page, 3000); + await page.reload({ + waitUntil: "commit", + }); + await measureTime(`${metricName}/html`, { + relativeTo: `${metricName}/start`, + }); + await page.waitForLoadState("domcontentloaded"); + await measureTime(`${metricName}/dom`, { + relativeTo: `${metricName}/start`, + }); + await page.waitForLoadState("load"); + await measureTime(`${metricName}/load`, { + relativeTo: `${metricName}/start`, + }); + await idle; + await measureTime(`${metricName}`, { + offset: 3000, + relativeTo: `${metricName}/start`, + }); + }); + } +} + +export async function newBrowserSession(options: { + headless?: boolean; + devtools?: boolean; + baseURL?: string; +}): Promise { + const browser = await chromium.launch({ + headless: options.headless ?? process.env.HEADLESS !== "false", + devtools: true, + timeout: 60000, + }); + const context = await browser.newContext({ + baseURL: options.baseURL ?? "http://localhost:3000", + viewport: { width: 1280, height: 720 }, + }); + context.setDefaultTimeout(120000); + context.setDefaultNavigationTimeout(120000); + return new BrowserSessionImpl(browser, context); +} + +// see next.js/test/lib/browsers/playwright.ts diff --git a/packages/devlow-bench/Source/cli.ts b/packages/devlow-bench/Source/cli.ts new file mode 100644 index 0000000000000..76f1a0afbbb3c --- /dev/null +++ b/packages/devlow-bench/Source/cli.ts @@ -0,0 +1,114 @@ +import minimist from "minimist"; +import { setCurrentScenarios } from "./describe.js"; +import { join } from "path"; +import { Scenario, ScenarioVariant, runScenarios } from "./index.js"; +import compose from "./interfaces/compose.js"; +import { pathToFileURL } from "url"; + +(async () => { + const knownArgs = new Set([ + "scenario", + "s", + "json", + "j", + "console", + "datadog", + "interactive", + "i", + "help", + "h", + "?", + "_", + ]); + const args = minimist(process.argv.slice(2), { + alias: { + s: "scenario", + j: "json", + i: "interactive", + "?": "help", + h: "help", + }, + }); + + if (args.help || (Object.keys(args).length === 1 && args._.length === 0)) { + console.log("Usage: devlow-bench [options] "); + console.log("## Selecting scenarios"); + console.log( + " --scenario=, -s= Only run the scenario with the given name" + ); + console.log( + " --interactive, -i Select scenarios and variants interactively" + ); + console.log( + " --= Filter by any variant property defined in scenarios" + ); + console.log("## Output"); + console.log( + " --json=, -j= Write the results to the given path as JSON" + ); + console.log( + " --console Print the results to the console" + ); + console.log( + " --datadog[=] Upload the results to Datadog" + ); + console.log( + " (requires DATADOG_API_KEY environment variables)" + ); + console.log("## Help"); + console.log(" --help, -h, -? Show this help"); + } + + const scenarios: Scenario[] = []; + setCurrentScenarios(scenarios); + + for (const path of args._) { + await import(pathToFileURL(join(process.cwd(), path)).toString()); + } + + setCurrentScenarios(null); + + const cliIface = { + filterScenarios: async (scenarios: Scenario[]) => { + if (args.scenario) { + const filter = [].concat(args.scenario); + return scenarios.filter((s) => + filter.some((filter) => s.name.includes(filter)) + ); + } + return scenarios; + }, + filterScenarioVariants: async (variants: ScenarioVariant[]) => { + const propEntries = Object.entries(args).filter( + ([key]) => !knownArgs.has(key) + ); + if (propEntries.length === 0) return variants; + for (const [key, value] of propEntries) { + const values = (Array.isArray(value) ? value : [value]).map((v) => + v.toString() + ); + variants = variants.filter((variant) => { + const prop = variant.props[key]; + if (typeof prop === "undefined") return false; + const str = prop.toString(); + return values.some((v) => str.includes(v)); + }); + } + return variants; + }, + }; + let ifaces = [ + cliIface, + args.interactive && (await import("./interfaces/interactive.js")).default(), + args.json && (await import("./interfaces/json.js")).default(args.json), + args.datadog && + (await import("./interfaces/datadog.js")).default( + typeof args.datadog === "string" ? { host: args.datadog } : undefined + ), + args.console !== false && + (await import("./interfaces/console.js")).default(), + ].filter((x) => x); + await runScenarios(scenarios, compose(...ifaces)); +})().catch((e) => { + console.error(e.stack); +}); diff --git a/packages/devlow-bench/Source/describe.ts b/packages/devlow-bench/Source/describe.ts new file mode 100644 index 0000000000000..ec691f6c95c7b --- /dev/null +++ b/packages/devlow-bench/Source/describe.ts @@ -0,0 +1,182 @@ +import type { + ConfigFor, + CurrentScenario, + Interface, + Scenario, +} from "./index.js"; +import compose from "./interfaces/compose.js"; +import { runScenarios } from "./runner.js"; + +let currentScenarios: Scenario[] | null = null; + +export function setCurrentScenarios(scenarios: Scenario[] | null): void { + currentScenarios = scenarios; +} + +export function describe

    ( + name: string, + config: ConfigFor

    , + fn: (props: P) => Promise +): void { + if (currentScenarios === null) { + const scenarios = (currentScenarios = []); + + Promise.resolve().then(async () => { + const ifaceNames = process.env.INTERFACE || "interactive,console"; + const ifaces = []; + for (const ifaceName of ifaceNames.split(",").map((s) => s.trim())) { + let iface: unknown; + try { + iface = await import(`./interfaces/${ifaceName}.js`); + } catch (e) { + iface = await import(ifaceName); + } + iface = (iface && (iface as any).default) || iface; + if (typeof iface === "function") { + iface = await iface(); + } + if (!iface) { + throw new Error(`Interface ${ifaceName} is not a valid interface`); + } + ifaces.push(iface as Interface); + } + runScenarios(scenarios, compose(...ifaces)); + }); + } + const normalizedConfig: Record = + Object.fromEntries( + Object.entries(config).map(([key, value]) => [ + key, + typeof value === "boolean" + ? [value, !value] + : (value as (string | number | boolean)[]), + ]) + ); + currentScenarios!.push({ + name, + config: normalizedConfig, + only: false, + fn: fn as ( + props: Record + ) => Promise, + }); +} + +describe.only = function describeOnly

    ( + name: string, + config: ConfigFor

    , + fn: (props: P) => Promise +): void { + describe(name, config, fn); + currentScenarios![currentScenarios!.length - 1].only = true; +}; + +let currentScenario: CurrentScenario | null = null; + +export function withCurrent( + current: CurrentScenario, + fn: () => Promise +): Promise { + const prev = currentScenario; + currentScenario = current; + return fn().finally(() => { + currentScenario = prev; + }); +} + +export const PREVIOUS = Symbol("previous measurement with that unit"); + +export async function measureTime( + name: string, + options: { + relativeTo?: string | typeof PREVIOUS; + scenario?: string; + props?: Record; + offset?: number; + } = {} +) { + const end = Date.now() - (options.offset || 0); + await reportMeasurement(name, end, "ms", { + relativeTo: PREVIOUS, + ...options, + }); +} + +export async function reportMeasurement( + name: string, + value: number, + unit: string, + options: { + relativeTo?: string | typeof PREVIOUS; + scenario?: string; + props?: Record; + } = {} +) { + if (!currentScenario) { + throw new Error("reportMeasurement() must be called inside of describe()"); + } + if (typeof name !== "string") { + throw new Error( + "reportMeasurement() must be called with a name that is a string" + ); + } + if (typeof value !== "number") { + throw new Error( + "reportMeasurement() must be called with a value that is a number" + ); + } + if (isNaN(value)) { + throw new Error( + "reportMeasurement() must be called with a value that is not NaN" + ); + } + if (!isFinite(value)) { + throw new Error( + "reportMeasurement() must be called with a value that is finite" + ); + } + if (typeof unit !== "string") { + throw new Error( + "reportMeasurement() must be called with a unit that is a string" + ); + } + let { relativeTo, scenario, props } = options; + if (relativeTo === PREVIOUS) { + relativeTo = "previous"; + for (const [prevName, prev] of currentScenario.measurements) { + if (prev.unit === unit) { + relativeTo = prevName; + } + } + } + currentScenario.measurements.set(name, { + value, + unit, + }); + let reportedValue = value; + if (relativeTo) { + const prev = currentScenario.measurements.get(relativeTo); + if (!prev) { + throw new Error(`No measurement named ${relativeTo} found`); + } + if (prev.unit !== unit) { + throw new Error( + `Measurement ${relativeTo} is not a "${unit}" measurement` + ); + } + reportedValue -= prev.value; + } + await currentScenario.iface.measurement( + scenario ?? currentScenario.scenario.scenario.name, + props + ? { + ...currentScenario.scenario.props, + ...props, + } + : currentScenario.scenario.props, + name, + reportedValue, + unit, + relativeTo + ); +} diff --git a/packages/devlow-bench/Source/file.ts b/packages/devlow-bench/Source/file.ts new file mode 100644 index 0000000000000..2f50b75e84240 --- /dev/null +++ b/packages/devlow-bench/Source/file.ts @@ -0,0 +1,59 @@ +import { watch } from "fs"; +import { access, constants } from "fs/promises"; +import { dirname } from "path"; + +export async function waitForFile( + path: string, + timeout: number +): Promise { + let currentAction = ""; + let timeoutRef; + const timeoutPromise = new Promise((resolve, reject) => { + timeoutRef = setTimeout(() => { + reject( + new Error(`Timed out waiting for file ${path} (${currentAction}))`) + ); + }, timeout || 60000); + }); + const elements = []; + let current = path; + while (true) { + elements.push(current); + const parent = dirname(current); + if (parent === current) { + break; + } + current = parent; + } + elements.reverse(); + try { + for (const path of elements) { + const checkAccess = () => + access(path, constants.F_OK) + .then(() => true) + .catch(() => false); + if (!(await checkAccess())) { + let resolveCheckAgain = () => {}; + const watcher = watch(dirname(path), () => { + resolveCheckAgain(); + }); + currentAction = `waiting for ${path}`; + let checkAgainPromise = new Promise((resolve) => { + resolveCheckAgain = resolve; + }); + try { + do { + await Promise.race([timeoutPromise, checkAgainPromise]); + checkAgainPromise = new Promise((resolve) => { + resolveCheckAgain = resolve; + }); + } while (!(await checkAccess())); + } finally { + watcher.close(); + } + } + } + } finally { + clearTimeout(timeoutRef); + } +} diff --git a/packages/devlow-bench/Source/index.ts b/packages/devlow-bench/Source/index.ts new file mode 100644 index 0000000000000..e87fd8a368bf5 --- /dev/null +++ b/packages/devlow-bench/Source/index.ts @@ -0,0 +1,89 @@ +export type ConfigFor

    = { + [K in keyof P]: P[K] extends string + ? string[] + : P[K] extends number + ? number[] + : P[K] extends boolean + ? boolean[] | boolean + : never; +}; + +export interface Scenario { + name: string; + config: Record; + only: boolean; + fn: (props: Record) => Promise; +} + +export interface ScenarioVariant { + scenario: Scenario; + props: Record; +} + +export interface CurrentScenario { + scenario: ScenarioVariant; + iface: FullInterface; + + measurements: Map< + string, + { + value: number; + unit: string; + } + >; +} + +export type Interface = Partial; + +export interface FullInterface { + filterScenarios(scenarios: Scenario[]): Promise; + filterScenarioVariants( + scenarioVariants: ScenarioVariant[] + ): Promise; + + start( + scenario: string, + props: Record + ): Promise; + measurement( + scenario: string, + props: Record, + name: string, + value: number, + unit: string, + relativeTo?: string + ): Promise; + end( + scenario: string, + props: Record + ): Promise; + error( + scenario: string, + props: Record, + error: unknown + ): Promise; + + finish(): Promise; +} + +export function intoFullInterface(iface: Interface): FullInterface { + return { + filterScenarios: iface.filterScenarios ?? (async (scenarios) => scenarios), + filterScenarioVariants: + iface.filterScenarioVariants ?? + (async (scenarioVariants) => scenarioVariants), + start: iface.start ?? (async () => {}), + measurement: iface.measurement ?? (async () => {}), + end: iface.end ?? (async () => {}), + error: iface.error ?? (async () => {}), + finish: iface.finish ?? (async () => {}), + }; +} + +export { + describe, + measureTime, + reportMeasurement, + PREVIOUS, +} from "./describe.js"; +export { runScenarios } from "./runner.js"; diff --git a/packages/devlow-bench/Source/interfaces/compose.ts b/packages/devlow-bench/Source/interfaces/compose.ts new file mode 100644 index 0000000000000..dac157c7f34d1 --- /dev/null +++ b/packages/devlow-bench/Source/interfaces/compose.ts @@ -0,0 +1,34 @@ +import { Interface } from "../index.js"; + +export default function compose(...ifaces: Interface[]): Interface { + const allKeys = new Set(); + for (const iface of ifaces) { + for (const key of Object.keys(iface)) { + allKeys.add(key as keyof Interface); + } + } + const composed: any = {}; + for (const key of allKeys) { + if (key.startsWith("filter")) { + composed[key] = async (items: any, ...args: any[]) => { + for (const iface of ifaces) { + const anyIface = iface as any; + if (anyIface[key]) { + items = await anyIface[key](items, ...args); + } + } + return items; + }; + } else { + composed[key] = async (...args: any[]) => { + for (const iface of ifaces) { + const anyIface = iface as any; + if (anyIface[key]) { + await anyIface[key](...args); + } + } + }; + } + } + return composed; +} diff --git a/packages/devlow-bench/Source/interfaces/console.ts b/packages/devlow-bench/Source/interfaces/console.ts new file mode 100644 index 0000000000000..6e845eaed1e5e --- /dev/null +++ b/packages/devlow-bench/Source/interfaces/console.ts @@ -0,0 +1,36 @@ +import { Interface, Scenario, ScenarioVariant } from "../index.js"; +import inquirer from "inquirer"; +import chalk from "chalk"; +import { formatUnit } from "../units.js"; +import { formatVariant } from "../utils.js"; + +export default function createInterface(): Interface { + const iface: Interface = { + start: async (scenario, props) => { + console.log( + chalk.bold.underline(`Running ${formatVariant(scenario, props)}...`) + ); + }, + measurement: async (scenario, props, name, value, unit, relativeTo) => { + console.log( + chalk.bgCyan.bold.magenta( + `${formatVariant(scenario, props)}: ${name} = ${formatUnit( + value, + unit + )}${relativeTo ? ` (from ${relativeTo})` : ""}` + ) + ); + }, + error: async (scenario, props, error) => { + console.log( + chalk.bold.red( + `${formatVariant(scenario, props)}: ${ + (error && (error as any).stack) || error + }` + ) + ); + }, + }; + + return iface; +} diff --git a/packages/devlow-bench/Source/interfaces/datadog.ts b/packages/devlow-bench/Source/interfaces/datadog.ts new file mode 100644 index 0000000000000..e18a36982c2d0 --- /dev/null +++ b/packages/devlow-bench/Source/interfaces/datadog.ts @@ -0,0 +1,89 @@ +import type { + DistributionPointsSeries, + MetricMetadata, +} from "@datadog/datadog-api-client/dist/packages/datadog-api-client-v1/index.js"; +import type { Interface } from "../index.js"; +import datadogApiClient from "@datadog/datadog-api-client"; +import os from "os"; + +function toIdentifier(str: string) { + return str.replace(/\//g, ".").replace(/ /g, "_"); +} + +const UNIT_MAPPING: Record = { + ms: "millisecond", + requests: "request", + bytes: "byte", +}; + +export default function createInterface({ + apiKey = process.env.DATADOG_API_KEY, + appKey = process.env.DATADOG_APP_KEY, + host = process.env.DATADOG_HOST || os.hostname(), +}: { apiKey?: string; appKey?: string; host?: string } = {}): Interface { + if (!apiKey) + throw new Error("Datadog API key is required (set DATADOG_API_KEY)"); + const commonTags = [ + `ci:${!!process.env.CI || "false"}`, + `os:${process.platform}`, + `os_release:${os.release()}`, + `cpus:${os.cpus().length}`, + `cpu_model:${os.cpus()[0].model}`, + `user:${os.userInfo().username}`, + `arch:${os.arch()}`, + `total_memory:${Math.round(os.totalmem() / 1024 / 1024 / 1024)}`, + `node_version:${process.version}`, + ]; + const configuration = datadogApiClient.client.createConfiguration({ + authMethods: { + apiKeyAuth: apiKey, + appKeyAuth: appKey, + }, + }); + const api = new datadogApiClient.v1.MetricsApi(configuration); + const dataPoints: DistributionPointsSeries[] = []; + const metricMetadata: Record = {}; + const iface: Interface = { + measurement: async (scenario, props, name, value, unit, relativeTo) => { + const ts = Math.round(Date.now() / 1000); + const metric = toIdentifier(`devlow_bench/${scenario}/${name}`); + if (UNIT_MAPPING[unit]) { + metricMetadata[metric] = { + unit: UNIT_MAPPING[unit], + }; + } + dataPoints.push({ + metric, + type: "distribution", + host, + tags: Object.entries(props) + .filter(([, value]) => value !== null) + .map( + ([key, value]) => + `${toIdentifier(key)}:${toIdentifier(value!.toString())}` + ) + .concat(commonTags), + points: [[ts, [value]]], + }); + }, + end: async (scenario, props) => { + await api.submitDistributionPoints({ + body: { + series: dataPoints, + }, + }); + dataPoints.length = 0; + }, + finish: async () => { + if (appKey) { + for (const [metric, metadata] of Object.entries(metricMetadata)) { + await api.updateMetricMetadata({ + metricName: metric, + body: metadata, + }); + } + } + }, + }; + return iface; +} diff --git a/packages/devlow-bench/Source/interfaces/interactive.ts b/packages/devlow-bench/Source/interfaces/interactive.ts new file mode 100644 index 0000000000000..dc77fa195f62f --- /dev/null +++ b/packages/devlow-bench/Source/interfaces/interactive.ts @@ -0,0 +1,46 @@ +import { Interface, Scenario, ScenarioVariant } from "../index.js"; +import inquirer from "inquirer"; +import chalk from "chalk"; +import { formatUnit } from "../units.js"; +import { formatVariant } from "../utils.js"; + +export default function createInterface(): Interface { + const iface: Interface = { + filterScenarios: async (scenarios) => { + if (scenarios.length === 1) { + return scenarios; + } + let answer = await inquirer.prompt({ + type: "checkbox", + name: "scenarios", + default: scenarios.slice(), + message: "Choose scenarios to run", + choices: scenarios.map((scenario) => ({ + name: scenario.name, + value: scenario, + })), + }); + return answer.scenarios; + }, + filterScenarioVariants: async (variants) => { + if (variants.length === 1) { + return variants; + } + let answer = await inquirer.prompt({ + type: "checkbox", + name: "variants", + default: variants.slice(), + message: "Choose variants to run", + choices: variants.map((variant) => { + return { + name: formatVariant(variant.scenario.name, variant.props), + value: variant, + }; + }), + }); + return answer.variants; + }, + }; + + return iface; +} diff --git a/packages/devlow-bench/Source/interfaces/json.ts b/packages/devlow-bench/Source/interfaces/json.ts new file mode 100644 index 0000000000000..0e3dbee99ee6e --- /dev/null +++ b/packages/devlow-bench/Source/interfaces/json.ts @@ -0,0 +1,83 @@ +import { Interface, Scenario, ScenarioVariant } from "../index.js"; +import inquirer from "inquirer"; +import chalk from "chalk"; +import { formatUnit } from "../units.js"; +import { formatVariant } from "../utils.js"; +import { writeFile } from "fs/promises"; + +function filterProp( + prop: Record +): Record { + const filteredProp: Record = {}; + for (const [key, value] of Object.entries(prop)) { + if (value !== null) { + filteredProp[key] = value; + } + } + return filteredProp; +} + +export default function createInterface( + file: string = (() => { + const file = process.env.JSON_OUTPUT_FILE; + if (!file) { + throw new Error("env var JSON_OUTPUT_FILE is not set"); + } + return file; + })() +): Interface { + const metrics = new Map< + string, + { + key: Record; + value: number; + unit: string; + count: number; + relativeTo?: string; + } + >(); + const iface: Interface = { + measurement: async (scenario, props, name, value, unit, relativeTo) => { + const keyObject = { + scenario: scenario, + ...filterProp(props), + name: name, + }; + const key = JSON.stringify(keyObject); + const current = metrics.get(key); + if (current) { + current.value += value; + current.count++; + } else { + metrics.set(key, { + key: keyObject, + value, + unit: unit, + count: 1, + relativeTo, + }); + } + }, + finish: async () => { + await writeFile( + file, + JSON.stringify( + [...metrics.values()].map( + ({ key, value, unit, count, relativeTo }) => { + return { + key, + value: value / count, + unit, + text: formatUnit(value / count, unit), + datapoints: count, + relativeTo, + }; + } + ) + ) + ); + }, + }; + + return iface; +} diff --git a/packages/devlow-bench/Source/runner.ts b/packages/devlow-bench/Source/runner.ts new file mode 100644 index 0000000000000..62d753d4ffe8f --- /dev/null +++ b/packages/devlow-bench/Source/runner.ts @@ -0,0 +1,64 @@ +import { withCurrent } from "./describe.js"; +import { Interface, Scenario, intoFullInterface } from "./index.js"; + +export async function runScenarios( + scenarios: Scenario[], + iface: Interface +): Promise { + const fullIface = intoFullInterface(iface); + if (scenarios.some((scenario) => scenario.only)) { + scenarios = scenarios.filter((scenario) => scenario.only); + } + scenarios = await fullIface.filterScenarios(scenarios); + let variants = []; + for (const scenario of scenarios) { + let props = [{}]; + for (const [key, options] of Object.entries(scenario.config)) { + const newProps = []; + for (const prop of props) { + if (prop === "scenario" || prop === "name") + throw new Error("Cannot use 'scenario' or 'name' as a property name"); + for (const value of options) { + newProps.push({ + ...prop, + [key]: value, + }); + } + } + props = newProps; + } + variants.push( + ...props.map((props) => ({ + scenario, + props, + })) + ); + } + variants = await fullIface.filterScenarioVariants(variants); + + for (const variant of variants) { + try { + const measurements = new Map(); + await withCurrent( + { + iface: fullIface, + measurements, + scenario: variant, + }, + async () => { + await fullIface.start(variant.scenario.name, variant.props); + measurements.set("start", { + value: Date.now(), + unit: "ms", + }); + await variant.scenario.fn(variant.props); + await fullIface.end(variant.scenario.name, variant.props); + } + ); + } catch (e) { + await fullIface.error(variant.scenario.name, variant.props, e); + } + } + + await fullIface.finish(); +} diff --git a/packages/devlow-bench/Source/shell.ts b/packages/devlow-bench/Source/shell.ts new file mode 100644 index 0000000000000..09d5433d5a5d3 --- /dev/null +++ b/packages/devlow-bench/Source/shell.ts @@ -0,0 +1,156 @@ +import { ChildProcess, spawn } from "child_process"; +import split2 from "split2"; +import treeKill from "tree-kill"; +import pidusage from "pidusage-tree"; +import { PREVIOUS, reportMeasurement } from "./describe.js"; + +export interface Command { + ok(): Promise; + kill(): Promise; + end(): Promise; + waitForOutput(regex: RegExp): Promise; + reportMemUsage( + metricName: string, + options: { + relativeTo?: string | typeof PREVIOUS; + scenario?: string; + props?: Record; + } + ): Promise; + stdout: string; + stderr: string; + output: string; +} + +const shellOutput = !!process.env.SHELL_OUTPUT; + +class CommandImpl { + stdout: string = ""; + stderr: string = ""; + output: string = ""; + exitPromise: Promise; + waitingForOutput: (() => void)[] = []; + constructor(private process: ChildProcess) { + process.stdout?.pipe(split2()).on("data", (data) => { + const str = data.toString(); + this.stdout += str + "\n"; + this.output += str + "\n"; + if (shellOutput) { + console.log(`[STDOUT] ${str}`); + } + if (this.waitingForOutput.length !== 0) { + const waitingForOutput = this.waitingForOutput; + this.waitingForOutput = []; + for (const fn of waitingForOutput) { + fn(); + } + } + }); + process.stderr?.pipe(split2()).on("data", (data) => { + const str = data.toString(); + this.stderr += str + "\n"; + this.output += str + "\n"; + if (shellOutput) { + console.log(`[STDERR] ${str}`); + } + if (this.waitingForOutput.length !== 0) { + const waitingForOutput = this.waitingForOutput; + this.waitingForOutput = []; + for (const fn of waitingForOutput) { + fn(); + } + } + }); + this.exitPromise = new Promise((resolve, reject) => { + process.on("error", reject); + process.on("exit", resolve); + }); + } + + async ok() { + const exitCode = await this.exitPromise; + if (exitCode !== 0) { + throw new Error( + `Command exited with code ${exitCode}\n\nOutput:\n${this.output}` + ); + } + } + + async end() { + return await this.exitPromise; + } + + async kill() { + const pid = this.process.pid!; + await new Promise((resolve, reject) => + treeKill(pid, (err) => { + if (err) reject(err); + else resolve(); + }) + ); + await this.exitPromise; + } + + async waitForOutput(regex: RegExp) { + let start = this.output.length; + while (true) { + const match = this.output.slice(start).match(regex); + if (match) { + return match; + } + const waitResult = await Promise.race([ + this.exitPromise, + new Promise((resolve) => { + this.waitingForOutput.push(resolve); + }).then(() => "output"), + ]); + if (waitResult !== "output") { + throw new Error( + `Command exited with code ${waitResult}\n\nOutput:\n${this.output}` + ); + } + } + } + + async reportMemUsage( + metricName: string, + options: { + relativeTo?: string | typeof PREVIOUS; + scenario?: string; + props?: Record; + } = {} + ) { + try { + const pid = this.process.pid!; + const report = await pidusage(pid); + const memUsage = Object.values(report) + .filter((x) => x) + .map((x) => (x as any).memory) + .reduce((a, b) => a + b, 0); + await reportMeasurement(metricName, memUsage, "bytes", options); + } catch (e) { + // ignore + } + } +} + +export function command( + command: string, + args: string[], + options: { + env?: Record; + cwd?: string; + } = {} +): Command { + const process = spawn(command, args, { + shell: true, + ...options, + stdio: ["ignore", "pipe", "pipe"], + }); + if (shellOutput) { + console.log( + `[SHELL] ${command} ${args.join(" ")} ${JSON.stringify(options)}` + ); + } + return new CommandImpl(process); +} diff --git a/packages/devlow-bench/Source/table.ts b/packages/devlow-bench/Source/table.ts new file mode 100644 index 0000000000000..2321958974699 --- /dev/null +++ b/packages/devlow-bench/Source/table.ts @@ -0,0 +1,129 @@ +import { readFile } from "fs/promises"; +import minimist from "minimist"; + +(async () => { + const args = minimist(process.argv.slice(2), { + alias: { + r: "row", + c: "column", + "?": "help", + h: "help", + }, + }); + + const knownArgs = new Set(["row", "r", "column", "c", "help", "h", "?", "_"]); + if (args.help || (Object.keys(args).length === 1 && args._.length === 0)) { + console.log("Usage: devlow-table "); + console.log(" --row= Key to show as row"); + console.log(" --column= Key to show as column"); + console.log(" --= Filter values"); + console.log(" --help, -h, -? Show this help"); + } + + let data = JSON.parse(await readFile(args._[0], "utf-8")) as any[]; + + const getValue = ( + data: any, + name: string | string[], + includeKey: boolean + ): string => { + if (name === "value") { + return data.text as string; + } + if (Array.isArray(name)) { + return name + .map((n) => getValue(data, n, true)) + .filter((x) => x) + .join(" "); + } + const value = data.key[name]; + if (value === undefined) return ""; + if (value === true) return includeKey ? name : "true"; + if (value === false) return includeKey ? "" : "false"; + if (value === null) return ""; + if (includeKey) return `${name}=${value}`; + return value + ""; + }; + + for (const [key, value] of Object.entries(args)) { + if (knownArgs.has(key)) continue; + const values = (Array.isArray(value) ? value : [value]).map((v) => + v.toString() + ); + data = data.filter((item) => { + const itemValue = getValue(item, key, false); + if (itemValue === "") return false; + return values.some((v) => itemValue === v); + }); + } + + if (data.length === 0) { + console.log("No data"); + return; + } + + const row = args.row || "name"; + const column = args.column || "scenario"; + const getRow = (data: any) => getValue(data, row, false); + const getColumn = (data: any) => getValue(data, column, false); + + const allRows = new Set(data.map(getRow)); + const allColumns = new Set(data.map(getColumn)); + + const table = []; + const columnSizes = [...allColumns].map((c) => c.length); + for (const row of allRows) { + const rowData: string[] = []; + let i = 0; + for (const column of allColumns) { + let items = data + .filter((d: any) => getRow(d) === row && getColumn(d) === column) + .map((i) => i.text); + rowData.push(items.join(", ")); + columnSizes[i] = Math.max(columnSizes[i], rowData[i].length); + i++; + } + table.push(rowData); + } + + const pad = (str: string, size: number) => { + return " ".repeat(size - str.length) + str; + }; + + const firstColumnSize = Math.max(...[...allRows].map((r) => r.length)); + + // Header + { + let row = "| "; + let sepRow = "|:"; + row += " ".repeat(firstColumnSize); + sepRow += "-".repeat(firstColumnSize); + const allColumnsArray = [...allColumns]; + for (let i = 0; i < columnSizes.length; i++) { + row += " | "; + row += pad(allColumnsArray[i], columnSizes[i]); + sepRow += ":|-"; + sepRow += "-".repeat(columnSizes[i]); + } + row += " |"; + sepRow += ":|"; + console.log(row); + console.log(sepRow); + } + + // Separator + let r = 0; + for (const rowName of allRows) { + let row = "| "; + row += pad(rowName, firstColumnSize); + for (let i = 0; i < columnSizes.length; i++) { + row += " | "; + row += pad(table[r][i], columnSizes[i]); + } + row += " |"; + console.log(row); + r++; + } +})().catch((e) => { + console.error(e.stack); +}); diff --git a/packages/devlow-bench/Source/types.d.ts b/packages/devlow-bench/Source/types.d.ts new file mode 100644 index 0000000000000..ba169651fbe50 --- /dev/null +++ b/packages/devlow-bench/Source/types.d.ts @@ -0,0 +1,2 @@ +declare module "chalk"; +declare module "pidusage-tree"; diff --git a/packages/devlow-bench/Source/units.ts b/packages/devlow-bench/Source/units.ts new file mode 100644 index 0000000000000..610a136c4147b --- /dev/null +++ b/packages/devlow-bench/Source/units.ts @@ -0,0 +1,25 @@ +const UNITS: Record> = { + ms: { + " s": 1000, + }, + bytes: { + " GB": 1024 * 1024 * 1024, + " MB": 1024 * 1024, + " KB": 1024, + }, + requests: { + "K requests": 1000, + }, +}; + +export function formatUnit(value: number, unit: string) { + const conversion = UNITS[unit]; + if (conversion) { + for (const [name, factor] of Object.entries(conversion)) { + if (value >= factor) { + return `${(value / factor).toFixed(2)}${name}`; + } + } + } + return `${value.toFixed(2).replace(/\.00$/, "")} ${unit}`; +} diff --git a/packages/devlow-bench/Source/utils.ts b/packages/devlow-bench/Source/utils.ts new file mode 100644 index 0000000000000..6fe0e543b637b --- /dev/null +++ b/packages/devlow-bench/Source/utils.ts @@ -0,0 +1,14 @@ +import { ScenarioVariant } from "./index.js"; + +export function formatVariant( + scenario: string, + props: Record +): string { + const keys = Object.keys(props) + .filter((key) => props[key] !== false && props[key] !== null) + .map((key) => (props[key] === true ? key : `${key}=${props[key]}`)); + if (keys.length === 0) { + return scenario; + } + return `${scenario} ${keys.join(" ")}`; +} diff --git a/packages/devlow-bench/package.json b/packages/devlow-bench/package.json new file mode 100644 index 0000000000000..72e7ee286abc0 --- /dev/null +++ b/packages/devlow-bench/package.json @@ -0,0 +1,40 @@ +{ + "name": "@vercel/devlow-bench", + "description": "Benchmarking tool for the developer workflow", + "exports": { + ".": "./dist/index.js", + "./browser": "./dist/browser.js", + "./file": "./dist/file.js", + "./interfaces/compose": "./dist/interfaces/compose.js", + "./interfaces/console": "./dist/interfaces/console.js", + "./interfaces/interactive": "./dist/interfaces/interactive.js", + "./interfaces/json": "./dist/interfaces/json.js", + "./shell": "./dist/shell.js" + }, + "main": "dist/index.js", + "bin": "dist/cli.js", + "files": [ + "dist" + ], + "scripts": { + "build:ts": "tsc", + "prerelease": "pnpm run build:ts" + }, + "dependencies": { + "@datadog/datadog-api-client": "1.32.0", + "chalk": "5.4.1", + "inquirer": "12.4.1", + "minimist": "1.2.8", + "pidusage-tree": "2.0.5", + "playwright-chromium": "1.50.1", + "split2": "4.2.0", + "tree-kill": "1.2.2" + }, + "devDependencies": { + "@turbo/eslint-config": "workspace:*", + "@types/inquirer": "9.0.7", + "@types/minimist": "1.2.5", + "@types/node": "22.13.1", + "@types/split2": "4.2.3" + } +} diff --git a/packages/devlow-bench/tsconfig.json b/packages/devlow-bench/tsconfig.json new file mode 100644 index 0000000000000..4fafbade9abcd --- /dev/null +++ b/packages/devlow-bench/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ES2020", + "module": "NodeNext", + "types": ["node"], + "outDir": "dist", + "declaration": true, + "declarationDir": "dist" + }, + "include": ["src/**/*"] +} diff --git a/packages/eslint-config-turbo/.eslintrc.js b/packages/eslint-config-turbo/.eslintrc.js deleted file mode 100644 index 4ca761e2f8eb5..0000000000000 --- a/packages/eslint-config-turbo/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], -}; diff --git a/packages/eslint-config-turbo/README.md b/packages/eslint-config-turbo/README.md deleted file mode 100644 index fac8e1dd81f7e..0000000000000 --- a/packages/eslint-config-turbo/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# `eslint-config-turbo` - -Ease configuration for Turborepo - -## Installation - -1. You'll first need to install [ESLint](https://eslint.org/): - -```sh -npm install eslint --save-dev -``` - -2. Next, install `eslint-config-turbo`: - -```sh -npm install eslint-config-turbo --save-dev -``` - -## Usage (Flat Config `eslint.config.js`) - -```js -import turboConfig from "eslint-config-turbo/flat"; - -export default [ - ...turboConfig, - // Other configuration -]; -``` - -You can also configure rules available in the configuration: - -```js -import turboConfig from "eslint-config-turbo/flat"; - -export default [ - ...turboConfig, - // Other configuration - { - rules: { - "turbo/no-undeclared-env-vars": [ - "error", - { - allowList: ["^ENV_[A-Z]+$"], - }, - ], - }, - }, -]; -``` - -## Usage (Legacy `eslintrc*`) - -Add `turbo` to the extends section of your eslint configuration file. You can omit the `eslint-config-` prefix: - -```json -{ - "extends": ["turbo"] -} -``` - -You can also configure rules available in the configuration: - -```json -{ - "plugins": ["turbo"], - "rules": { - "turbo/no-undeclared-env-vars": [ - "error", - { - "allowList": ["^ENV_[A-Z]+$"] - } - ] - } -} -``` diff --git a/packages/eslint-config-turbo/package.json b/packages/eslint-config-turbo/package.json index 140ce5189d439..d569b0d60f1f7 100644 --- a/packages/eslint-config-turbo/package.json +++ b/packages/eslint-config-turbo/package.json @@ -31,12 +31,12 @@ "eslint-plugin-turbo": "workspace:*" }, "peerDependencies": { - "eslint": ">6.6.0", - "turbo": ">2.0.0" + "eslint": ">=9.20.1", + "turbo": ">=2.4.2" }, "license": "MIT", "devDependencies": { "@turbo/eslint-config": "workspace:*", - "@types/eslint": "^8.44.2" + "@types/eslint": "9.6.1" } } diff --git a/packages/eslint-config/README.md b/packages/eslint-config/README.md deleted file mode 100644 index c21c2d8f85765..0000000000000 --- a/packages/eslint-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations shared between [turborepo/packages/](https://github.com/vercel/turborepo/tree/main/packages) diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 081bc3fb4b12a..3f532ea55c863 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,8 +1,7 @@ { - "name": "@turbo/eslint-config", - "version": "0.0.0", - "private": true, - "devDependencies": { - "@vercel/style-guide": "^5.1.0" - } + "name": "@turbo/eslint-config", + "dependencies": {}, + "devDependencies": { + "@vercel/style-guide": "6.0.0" + } } diff --git a/packages/eslint-plugin-turbo/.eslintrc.js b/packages/eslint-plugin-turbo/.eslintrc.js deleted file mode 100644 index 28e9f376d291a..0000000000000 --- a/packages/eslint-plugin-turbo/.eslintrc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], - rules: { - "import/no-default-export": "off", - }, -}; diff --git a/packages/eslint-plugin-turbo/.vscode/launch.json b/packages/eslint-plugin-turbo/.vscode/launch.json deleted file mode 100644 index e67b2ddd4e727..0000000000000 --- a/packages/eslint-plugin-turbo/.vscode/launch.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "1.0.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "test", - "program": "${workspaceFolder}/node_modules/jest/bin/jest.js", - "args": ["${workspaceFolder}", "--run-in-band"], - "console": "integratedTerminal" - } - ] -} diff --git a/packages/eslint-plugin-turbo/README.md b/packages/eslint-plugin-turbo/README.md deleted file mode 100644 index cc8f6367ffdb4..0000000000000 --- a/packages/eslint-plugin-turbo/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# `eslint-plugin-turbo` - -Easy ESLint configuration for Turborepo - -## Installation - -1. You'll first need to install [ESLint](https://eslint.org/): - -```sh -npm install eslint --save-dev -``` - -2. Next, install `eslint-plugin-turbo`: - -```sh -npm install eslint-plugin-turbo --save-dev -``` - -## Usage (Flat Config `eslint.config.js`) - -ESLint v9 uses the Flat Config format seen below: - -```js -import turbo from "eslint-plugin-turbo"; - -export default [turbo.configs["flat/recommended"]]; -``` - -Otherwise, you may configure the rules you want to use under the rules section. - -```js -import turbo from "eslint-plugin-turbo"; - -export default [ - { - plugins: { - turbo, - }, - rules: { - "turbo/no-undeclared-env-vars": "error", - }, - }, -]; -``` - -## Example (Flat Config `eslint.config.js`) - -```js -import turbo from "eslint-plugin-turbo"; - -export default [ - { - plugins: { - turbo, - }, - rules: { - "turbo/no-undeclared-env-vars": [ - "error", - { - allowList: ["^ENV_[A-Z]+$"], - }, - ], - }, - }, -]; -``` - -## Usage (Legacy `eslintrc*`) - -Add `turbo` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix: - -```json -{ - "plugins": ["turbo"] -} -``` - -Then configure the rules you want to use under the rules section. - -```json -{ - "rules": { - "turbo/no-undeclared-env-vars": "error" - } -} -``` - -## Example (Legacy `eslintrc*`) - -```json -{ - "plugins": ["turbo"], - "rules": { - "turbo/no-undeclared-env-vars": [ - "error", - { - "allowList": ["^ENV_[A-Z]+$"] - } - ] - } -} -``` diff --git a/packages/eslint-plugin-turbo/__fixtures__/configs/single/package.json b/packages/eslint-plugin-turbo/__fixtures__/configs/single/package.json index 0967ef424bce6..8b137891791fe 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/configs/single/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/configs/single/package.json @@ -1 +1 @@ -{} + diff --git a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/.eslintrc.js b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/.eslintrc.js deleted file mode 100644 index 8dc66dca7067c..0000000000000 --- a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["plugin:turbo/recommended"], -}; diff --git a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/kitchen-sink/package.json b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/kitchen-sink/package.json index 86930291d732c..e24f367a03494 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/kitchen-sink/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/kitchen-sink/package.json @@ -1,19 +1,17 @@ { - "name": "nextjs", - "dependencies": { - "next": "*", - "blitz": "*", - "react": "*", - "left-pad": "*", - "event-stream": "*", - "gatsby": "*", - "is-promise": "*", - "@faker-js/faker": "*", - "ua-parser-js": "*", - "nitropack": "*" - }, - "devDependencies": { - "eslint": "8.57.0", - "eslint-plugin-turbo": "../../../../" - } + "name": "nextjs", + "dependencies": { + "@faker-js/faker": "*", + "blitz": "*", + "event-stream": "*", + "gatsby": "*", + "is-promise": "*", + "left-pad": "*", + "next": "*", + "nitropack": "*", + "ua-parser-js": "*" + }, + "devDependencies": { + "eslint-plugin-turbo": "../../../../" + } } diff --git a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/nextjs/package.json b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/nextjs/package.json index 513d44b4c8d2e..b01d763db55ff 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/nextjs/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/nextjs/package.json @@ -1,10 +1,9 @@ { - "name": "nextjs", - "dependencies": { - "next": "*" - }, - "devDependencies": { - "eslint": "8.57.0", - "eslint-plugin-turbo": "../../../../" - } + "name": "nextjs", + "dependencies": { + "next": "*" + }, + "devDependencies": { + "eslint-plugin-turbo": "../../../../" + } } diff --git a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/vite/package.json b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/vite/package.json index fba50b3f190e6..e0aba4fd5ab8d 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/vite/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/apps/vite/package.json @@ -1,10 +1,7 @@ { - "name": "vite", - "dependencies": { - "vite": "*" - }, - "devDependencies": { - "eslint": "8.57.0", - "eslint-plugin-turbo": "../../../../" - } + "name": "vite", + "dependencies": {}, + "devDependencies": { + "eslint-plugin-turbo": "../../../../" + } } diff --git a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/package.json b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/package.json index ecd2d11d6222a..b90bef54af60a 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/framework-inference/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/framework-inference/package.json @@ -1,7 +1,7 @@ { - "name": "framework-inference", - "devDependencies": { - "eslint": "8.57.0", - "eslint-plugin-turbo": "../../" - } + "name": "framework-inference", + "dependencies": {}, + "devDependencies": { + "eslint-plugin-turbo": "../../" + } } diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/package.json index 82f9a44736f00..a95984fb3f175 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/package.json @@ -1,4 +1,5 @@ { - "name": "docs", - "version": "1.0.0" + "name": "docs", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/package.json index d8a83edbd32a1..6dc872312103a 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/package.json @@ -1,4 +1,5 @@ { - "name": "web", - "version": "1.0.0" + "name": "web", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/package.json index c6616a615d2d5..8b137891791fe 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/package.json @@ -1,14 +1 @@ -{ - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} + diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/package.json index 7cb7cf17345dc..d1ba3c544165d 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/package.json @@ -1,4 +1,5 @@ { - "name": "ui", - "version": "1.0.0" + "name": "ui", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace/.eslintrc.js b/packages/eslint-plugin-turbo/__fixtures__/workspace/.eslintrc.js deleted file mode 100644 index 8dc66dca7067c..0000000000000 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["plugin:turbo/recommended"], -}; diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace/eslint.config.js b/packages/eslint-plugin-turbo/__fixtures__/workspace/eslint.config.js deleted file mode 100644 index c4460d5e152f6..0000000000000 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace/eslint.config.js +++ /dev/null @@ -1,3 +0,0 @@ -const turbo = require("eslint-plugin-turbo"); - -module.exports = [turbo.configs["flat/recommended"]]; diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace/package-lock.json b/packages/eslint-plugin-turbo/__fixtures__/workspace/package-lock.json deleted file mode 100644 index 136760f7f1289..0000000000000 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace/package-lock.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "workspace", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "dependencies": { - "eslint-plugin-turbo": "../../" - } - }, - "../..": { - "version": "1.9.0", - "license": "MPL-2.0", - "devDependencies": { - "@turbo/test-utils": "workspace:*", - "@turbo/tsconfig": "workspace:*", - "@turbo/types": "workspace:*", - "@turbo/utils": "workspace:*", - "@types/eslint": "^8.4.5", - "@types/estree": "^1.0.0", - "@types/jest": "^29.5.13", - "@types/node": "^16.11.12", - "jest": "^29.7.0", - "json5": "^2.2.1", - "ts-jest": "^29.2.5", - "tsup": "^6.2.0", - "typescript": "5.3.3" - }, - "peerDependencies": { - "eslint": ">6.6.0" - } - }, - "node_modules/eslint-plugin-turbo": { - "resolved": "../..", - "link": true - } - }, - "dependencies": { - "eslint-plugin-turbo": { - "version": "file:../..", - "requires": { - "@turbo/test-utils": "workspace:*", - "@turbo/tsconfig": "workspace:*", - "@turbo/types": "workspace:*", - "@turbo/utils": "workspace:*", - "@types/eslint": "^8.4.5", - "@types/estree": "^1.0.0", - "@types/jest": "^29.5.13", - "@types/node": "^16.11.12", - "jest": "^29.7.0", - "json5": "^2.2.1", - "ts-jest": "^29.2.5", - "tsup": "^6.2.0", - "typescript": "5.3.3" - } - } - } -} diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace/package.json index 4dca370603c1b..8b137891791fe 100644 --- a/packages/eslint-plugin-turbo/__fixtures__/workspace/package.json +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace/package.json @@ -1,6 +1 @@ -{ - "devDependencies": { - "eslint": "8.57.0", - "eslint-plugin-turbo": "../../" - } -} + diff --git a/packages/eslint-plugin-turbo/__tests__/cwd.test.ts b/packages/eslint-plugin-turbo/__tests__/cwd.test.ts deleted file mode 100644 index f559711127149..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/cwd.test.ts +++ /dev/null @@ -1,188 +0,0 @@ -import path from "node:path"; -import { execSync } from "node:child_process"; -import { type Schema } from "@turbo/types"; -import { parse, stringify } from "json5"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; - -const env: NodeJS.ProcessEnv = { - ...process.env, - ESLINT_USE_FLAT_CONFIG: "false", -}; - -describe("eslint settings check", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - }); - - it("does the right thing for peers", () => { - const { root: cwd } = useFixture({ fixture: "workspace" }); - execSync(`npm install`, { cwd }); - - const configString = execSync(`npm exec eslint -- --print-config peer.js`, { - cwd, - encoding: "utf8", - env, - }); - const configJson: Record = parse(configString); - - expect(configJson.settings).toEqual({ - turbo: { - cacheKey: { - global: { - legacyConfig: [], - env: ["CI", "UNORDERED"], - passThroughEnv: null, - dotEnv: { - filePaths: [".env", "missing.env"], - hashes: { - ".env": "9ad6c5fd4d5bbe7c00e1f2b358ac7ef2aa3521d0", - }, - }, - }, - globalTasks: { - build: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - test: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - lint: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - deploy: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - }, - workspaceTasks: {}, - }, - }, - }); - }); - - it("does the right thing for child dirs", () => { - const { root } = useFixture({ fixture: "workspace" }); - execSync(`npm install`, { cwd: root }); - - const cwd = path.join(root, "child"); - const configString = execSync( - `npm exec eslint -- --print-config child.js`, - { - cwd, - encoding: "utf8", - env, - } - ); - const configJson: Record = parse(configString); - - expect(configJson.settings).toEqual({ - turbo: { - cacheKey: { - global: { - legacyConfig: [], - env: ["CI", "UNORDERED"], - passThroughEnv: null, - dotEnv: { - filePaths: [".env", "missing.env"], - hashes: { - ".env": "9ad6c5fd4d5bbe7c00e1f2b358ac7ef2aa3521d0", - }, - }, - }, - globalTasks: { - build: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - test: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - lint: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - deploy: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - }, - workspaceTasks: {}, - }, - }, - }); - }); -}); - -describe("eslint cache is busted", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - }); - - it("catches a lint error after changing config", () => { - expect.assertions(2); - - // ensure that we populate the cache with a failure. - const { root, readJson, write } = useFixture({ fixture: "workspace" }); - execSync(`npm install`, { cwd: root }); - - const cwd = path.join(root, "child"); - try { - execSync(`npm exec eslint -- --format=json child.js`, { - cwd, - encoding: "utf8", - env, - }); - } catch (error: unknown) { - const outputJson: Record = parse( - (error as { stdout: string }).stdout - ); - expect(outputJson).toMatchObject([ - { - messages: [ - { - message: - "NONEXISTENT is not listed as a dependency in turbo.json", - }, - ], - }, - ]); - } - - // change the configuration - const turboJson = readJson("turbo.json"); - if (turboJson && "globalEnv" in turboJson) { - turboJson.globalEnv = ["CI", "NONEXISTENT"]; - write("turbo.json", stringify(turboJson, null, 2)); - } - - // test that we invalidated the eslint cache - const output = execSync(`npm exec eslint -- --format=json child.js`, { - cwd, - encoding: "utf8", - env, - }); - const outputJson: Record = parse(output); - expect(outputJson).toMatchObject([{ errorCount: 0 }]); - }); -}); diff --git a/packages/eslint-plugin-turbo/__tests__/cwdFlat.test.ts b/packages/eslint-plugin-turbo/__tests__/cwdFlat.test.ts deleted file mode 100644 index 09e7fbe5f84cc..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/cwdFlat.test.ts +++ /dev/null @@ -1,188 +0,0 @@ -import path from "node:path"; -import { execSync } from "node:child_process"; -import { type Schema } from "@turbo/types"; -import { parse, stringify } from "json5"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; - -const env: NodeJS.ProcessEnv = { - ...process.env, - ESLINT_USE_FLAT_CONFIG: "true", -}; - -describe("flat eslint settings check", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - }); - - it("does the right thing for peers", () => { - const { root: cwd } = useFixture({ fixture: "workspace" }); - execSync(`npm install`, { cwd }); - - const configString = execSync(`npm exec eslint -- --print-config peer.js`, { - cwd, - encoding: "utf8", - env, - }); - const configJson: Record = parse(configString); - - expect(configJson.settings).toEqual({ - turbo: { - cacheKey: { - global: { - legacyConfig: [], - env: ["CI", "UNORDERED"], - passThroughEnv: null, - dotEnv: { - filePaths: [".env", "missing.env"], - hashes: { - ".env": "9ad6c5fd4d5bbe7c00e1f2b358ac7ef2aa3521d0", - }, - }, - }, - globalTasks: { - build: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - test: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - lint: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - deploy: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - }, - workspaceTasks: {}, - }, - }, - }); - }); - - it("does the right thing for child dirs", () => { - const { root } = useFixture({ fixture: "workspace" }); - execSync(`npm install`, { cwd: root }); - - const cwd = path.join(root, "child"); - const configString = execSync( - `npm exec eslint -- --print-config child.js`, - { - cwd, - encoding: "utf8", - env, - } - ); - const configJson: Record = parse(configString); - - expect(configJson.settings).toEqual({ - turbo: { - cacheKey: { - global: { - legacyConfig: [], - env: ["CI", "UNORDERED"], - passThroughEnv: null, - dotEnv: { - filePaths: [".env", "missing.env"], - hashes: { - ".env": "9ad6c5fd4d5bbe7c00e1f2b358ac7ef2aa3521d0", - }, - }, - }, - globalTasks: { - build: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - test: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - lint: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - deploy: { - legacyConfig: [], - env: [], - passThroughEnv: null, - dotEnv: null, - }, - }, - workspaceTasks: {}, - }, - }, - }); - }); -}); - -describe("flat eslint cache is busted", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - }); - - it("catches a lint error after changing config", () => { - expect.assertions(2); - - // ensure that we populate the cache with a failure. - const { root, readJson, write } = useFixture({ fixture: "workspace" }); - execSync(`npm install`, { cwd: root }); - - const cwd = path.join(root, "child"); - try { - execSync(`npm exec eslint -- --format=json child.js`, { - cwd, - encoding: "utf8", - env, - }); - } catch (error: unknown) { - const outputJson: Record = parse( - (error as { stdout: string }).stdout - ); - expect(outputJson).toMatchObject([ - { - messages: [ - { - message: - "NONEXISTENT is not listed as a dependency in turbo.json", - }, - ], - }, - ]); - } - - // change the configuration - const turboJson = readJson("turbo.json"); - if (turboJson && "globalEnv" in turboJson) { - turboJson.globalEnv = ["CI", "NONEXISTENT"]; - write("turbo.json", stringify(turboJson, null, 2)); - } - - // test that we invalidated the eslint cache - const output = execSync(`npm exec eslint -- --format=json child.js`, { - cwd, - encoding: "utf8", - env, - }); - const outputJson: Record = parse(output); - expect(outputJson).toMatchObject([{ errorCount: 0 }]); - }); -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/configs/no-undeclared-env-vars.commonjs.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/configs/no-undeclared-env-vars.commonjs.test.ts deleted file mode 100644 index b778eb2688895..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/configs/no-undeclared-env-vars.commonjs.test.ts +++ /dev/null @@ -1,306 +0,0 @@ -import path from "node:path"; -import { RuleTester } from "eslint"; -import { RULES } from "../../../../lib/constants"; -import rule from "../../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020 }, -}); - -const cwd = path.join(__dirname, "../../../../__fixtures__/configs/single"); -const options = (extra: Record = {}) => ({ - options: [ - { - cwd, - ...extra, - }, - ], -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: ` - const { TASK_ENV_KEY, ANOTHER_ENV_KEY } = process.env; - `, - ...options(), - }, - { - code: ` - const { NEW_STYLE_ENV_KEY, TASK_ENV_KEY } = process.env; - `, - ...options(), - }, - { - code: ` - const { NEW_STYLE_GLOBAL_ENV_KEY, TASK_ENV_KEY } = process.env; - `, - ...options(), - }, - { - code: ` - const val = process.env["NEW_STYLE_GLOBAL_ENV_KEY"]; - `, - ...options(), - }, - { - code: ` - const { TASK_ENV_KEY, ANOTHER_ENV_KEY } = process.env; - `, - ...options(), - }, - { - code: ` - const x = process.env.GLOBAL_ENV_KEY; - const { TASK_ENV_KEY, GLOBAL_ENV_KEY: renamedX } = process.env; - `, - ...options(), - }, - { - code: "var x = process.env.GLOBAL_ENV_KEY;", - ...options(), - }, - { - code: "let x = process.env.TASK_ENV_KEY;", - ...options(), - }, - { - code: "const x = process.env.ANOTHER_KEY_VALUE;", - ...options({ - allowList: ["^ANOTHER_KEY_[A-Z]+$"], - }), - }, - { - code: ` - var x = process.env.ENV_VAR_ONE; - var y = process.env.ENV_VAR_TWO; - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - var x = process.env.ENV_VAR_ONE; - var y = process.env.ENV_VAR_TWO; - `, - ...options({ - allowList: ["^ENV_VAR_O[A-Z]+$", "ENV_VAR_TWO"], - }), - }, - { - code: ` - var globalOrTask = process.env.TASK_ENV_KEY || process.env.GLOBAL_ENV_KEY; - var oneOrTwo = process.env.ENV_VAR_ONE || process.env.ENV_VAR_TWO; - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - () => { return process.env.GLOBAL_ENV_KEY } - () => { return process.env.TASK_ENV_KEY } - () => { return process.env.ENV_VAR_ALLOWED } - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - var foo = process?.env.GLOBAL_ENV_KEY - var foo = process?.env.TASK_ENV_KEY - var foo = process?.env.ENV_VAR_ALLOWED - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - function test(arg1 = process.env.GLOBAL_ENV_KEY) {}; - function test(arg1 = process.env.TASK_ENV_KEY) {}; - function test(arg1 = process.env.ENV_VAR_ALLOWED) {}; - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - (arg1 = process.env.GLOBAL_ENV_KEY) => {} - (arg1 = process.env.TASK_ENV_KEY) => {} - (arg1 = process.env.ENV_VAR_ALLOWED) => {} - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: "const getEnv = (key) => process.env[key];", - ...options(), - }, - { - code: "function getEnv(key) { return process.env[key]; }", - ...options(), - }, - { - code: "for (let x of ['ONE', 'TWO', 'THREE']) { console.log(process.env[x]); }", - ...options(), - }, - ], - invalid: [ - { - code: "let { X } = process.env;", - ...options(), - errors: [{ message: "X is not listed as a dependency in turbo.json" }], - }, - { - code: "const { X, Y, Z } = process.env;", - ...options(), - errors: [ - { message: "X is not listed as a dependency in turbo.json" }, - { message: "Y is not listed as a dependency in turbo.json" }, - { message: "Z is not listed as a dependency in turbo.json" }, - ], - }, - { - code: "const { X, Y: NewName, Z } = process.env;", - ...options(), - errors: [ - { message: "X is not listed as a dependency in turbo.json" }, - { message: "Y is not listed as a dependency in turbo.json" }, - { message: "Z is not listed as a dependency in turbo.json" }, - ], - }, - { - code: "var x = process.env.NOT_THERE;", - ...options(), - errors: [ - { - message: "NOT_THERE is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: "var x = process.env.KEY;", - ...options({ - allowList: ["^ANOTHER_KEY_[A-Z]+$"], - }), - - errors: [{ message: "KEY is not listed as a dependency in turbo.json" }], - }, - { - code: ` - var globalOrTask = process.env.TASK_ENV_KEY_NEW || process.env.GLOBAL_ENV_KEY_NEW; - var oneOrTwo = process.env.ENV_VAR_ONE || process.env.ENV_VAR_TWO; - `, - ...options(), - errors: [ - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: "ENV_VAR_ONE is not listed as a dependency in turbo.json", - }, - { - message: "ENV_VAR_TWO is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - () => { return process.env.GLOBAL_ENV_KEY_NEW } - () => { return process.env.TASK_ENV_KEY_NEW } - () => { return process.env.ENV_VAR_NOT_ALLOWED } - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - var foo = process?.env.GLOBAL_ENV_KEY_NEW - var foo = process?.env.TASK_ENV_KEY_NEW - var foo = process?.env.ENV_VAR_NOT_ALLOWED - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - function test(arg1 = process.env.GLOBAL_ENV_KEY_NEW) {}; - function test(arg1 = process.env.TASK_ENV_KEY_NEW) {}; - function test(arg1 = process.env.ENV_VAR_NOT_ALLOWED) {}; - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - (arg1 = process.env.GLOBAL_ENV_KEY_NEW) => {} - (arg1 = process.env.TASK_ENV_KEY_NEW) => {} - (arg1 = process.env.ENV_VAR_NOT_ALLOWED) => {} - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - ], -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/configs/no-undeclared-env-vars.module.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/configs/no-undeclared-env-vars.module.test.ts deleted file mode 100644 index f6d58306b4b55..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/configs/no-undeclared-env-vars.module.test.ts +++ /dev/null @@ -1,306 +0,0 @@ -import path from "node:path"; -import { RuleTester } from "eslint"; -import { RULES } from "../../../../lib/constants"; -import rule from "../../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020, sourceType: "module" }, -}); - -const cwd = path.join(__dirname, "../../../../__fixtures__/configs/single"); -const options = (extra: Record = {}) => ({ - options: [ - { - cwd, - ...extra, - }, - ], -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: ` - const { TASK_ENV_KEY, ANOTHER_ENV_KEY } = import.meta.env; - `, - ...options(), - }, - { - code: ` - const { NEW_STYLE_ENV_KEY, TASK_ENV_KEY } = import.meta.env; - `, - ...options(), - }, - { - code: ` - const { NEW_STYLE_GLOBAL_ENV_KEY, TASK_ENV_KEY } = import.meta.env; - `, - ...options(), - }, - { - code: ` - const val = import.meta.env["NEW_STYLE_GLOBAL_ENV_KEY"]; - `, - ...options(), - }, - { - code: ` - const { TASK_ENV_KEY, ANOTHER_ENV_KEY } = import.meta.env; - `, - ...options(), - }, - { - code: ` - const x = import.meta.env.GLOBAL_ENV_KEY; - const { TASK_ENV_KEY, GLOBAL_ENV_KEY: renamedX } = import.meta.env; - `, - ...options(), - }, - { - code: "var x = import.meta.env.GLOBAL_ENV_KEY;", - ...options(), - }, - { - code: "let x = import.meta.env.TASK_ENV_KEY;", - ...options(), - }, - { - code: "const x = import.meta.env.ANOTHER_KEY_VALUE;", - ...options({ - allowList: ["^ANOTHER_KEY_[A-Z]+$"], - }), - }, - { - code: ` - var x = import.meta.env.ENV_VAR_ONE; - var y = import.meta.env.ENV_VAR_TWO; - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - var x = import.meta.env.ENV_VAR_ONE; - var y = import.meta.env.ENV_VAR_TWO; - `, - ...options({ - allowList: ["^ENV_VAR_O[A-Z]+$", "ENV_VAR_TWO"], - }), - }, - { - code: ` - var globalOrTask = import.meta.env.TASK_ENV_KEY || import.meta.env.GLOBAL_ENV_KEY; - var oneOrTwo = import.meta.env.ENV_VAR_ONE || import.meta.env.ENV_VAR_TWO; - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - () => { return import.meta.env.GLOBAL_ENV_KEY } - () => { return import.meta.env.TASK_ENV_KEY } - () => { return import.meta.env.ENV_VAR_ALLOWED } - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - var foo = process?.env.GLOBAL_ENV_KEY - var foo = process?.env.TASK_ENV_KEY - var foo = process?.env.ENV_VAR_ALLOWED - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - function test1(arg1 = import.meta.env.GLOBAL_ENV_KEY) {}; - function test2(arg1 = import.meta.env.TASK_ENV_KEY) {}; - function test3(arg1 = import.meta.env.ENV_VAR_ALLOWED) {}; - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: ` - (arg1 = import.meta.env.GLOBAL_ENV_KEY) => {} - (arg1 = import.meta.env.TASK_ENV_KEY) => {} - (arg1 = import.meta.env.ENV_VAR_ALLOWED) => {} - `, - ...options({ - allowList: ["^ENV_VAR_[A-Z]+$"], - }), - }, - { - code: "const getEnv = (key) => import.meta.env[key];", - ...options(), - }, - { - code: "function getEnv(key) { return import.meta.env[key]; }", - ...options(), - }, - { - code: "for (let x of ['ONE', 'TWO', 'THREE']) { console.log(import.meta.env[x]); }", - ...options(), - }, - ], - - invalid: [ - { - code: "let { X } = import.meta.env;", - ...options(), - errors: [{ message: "X is not listed as a dependency in turbo.json" }], - }, - { - code: "const { X, Y, Z } = import.meta.env;", - ...options(), - errors: [ - { message: "X is not listed as a dependency in turbo.json" }, - { message: "Y is not listed as a dependency in turbo.json" }, - { message: "Z is not listed as a dependency in turbo.json" }, - ], - }, - { - code: "const { X, Y: NewName, Z } = import.meta.env;", - ...options(), - errors: [ - { message: "X is not listed as a dependency in turbo.json" }, - { message: "Y is not listed as a dependency in turbo.json" }, - { message: "Z is not listed as a dependency in turbo.json" }, - ], - }, - { - code: "var x = import.meta.env.NOT_THERE;", - ...options(), - errors: [ - { - message: "NOT_THERE is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: "var x = import.meta.env.KEY;", - ...options({ - allowList: ["^ANOTHER_KEY_[A-Z]+$"], - }), - errors: [{ message: "KEY is not listed as a dependency in turbo.json" }], - }, - { - code: ` - var globalOrTask = import.meta.env.TASK_ENV_KEY_NEW || import.meta.env.GLOBAL_ENV_KEY_NEW; - var oneOrTwo = import.meta.env.ENV_VAR_ONE || import.meta.env.ENV_VAR_TWO; - `, - ...options(), - errors: [ - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: "ENV_VAR_ONE is not listed as a dependency in turbo.json", - }, - { - message: "ENV_VAR_TWO is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - () => { return import.meta.env.GLOBAL_ENV_KEY_NEW } - () => { return import.meta.env.TASK_ENV_KEY_NEW } - () => { return import.meta.env.ENV_VAR_NOT_ALLOWED } - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - var foo = process?.env.GLOBAL_ENV_KEY_NEW - var foo = process?.env.TASK_ENV_KEY_NEW - var foo = process?.env.ENV_VAR_NOT_ALLOWED - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - function test1(arg1 = import.meta.env.GLOBAL_ENV_KEY_NEW) {}; - function test2(arg1 = import.meta.env.TASK_ENV_KEY_NEW) {}; - function test3(arg1 = import.meta.env.ENV_VAR_NOT_ALLOWED) {}; - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: ` - (arg1 = import.meta.env.GLOBAL_ENV_KEY_NEW) => {} - (arg1 = import.meta.env.TASK_ENV_KEY_NEW) => {} - (arg1 = import.meta.env.ENV_VAR_NOT_ALLOWED) => {} - `, - ...options(), - errors: [ - { - message: - "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", - }, - { - message: - "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", - }, - ], - }, - ], -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/framework-inference/no-undeclared-env-vars.commonjs.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/framework-inference/no-undeclared-env-vars.commonjs.test.ts deleted file mode 100644 index 2e48a404e8e6b..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/framework-inference/no-undeclared-env-vars.commonjs.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import path from "node:path"; -import { RuleTester } from "eslint"; -import { RULES } from "../../../../lib/constants"; -import rule from "../../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020 }, -}); - -const cwd = path.join( - __dirname, - "../../../../__fixtures__/framework-inference" -); -const nextJsFilename = path.join(cwd, "/apps/nextjs/index.js"); -const viteFilename = path.join(cwd, "/apps/vite/index.js"); -const kitchenSinkFilename = path.join(cwd, "/apps/kitchen-sink/index.js"); -const options = (extra: Record = {}) => ({ - options: [ - { - cwd, - ...extra, - }, - ], -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: `const { NEXT_PUBLIC_ZILTOID } = process.env;`, - ...options(), - filename: nextJsFilename, - }, - { - code: `const { VITE_THINGS } = process.env;`, - ...options(), - filename: viteFilename, - }, - { - code: `const { NEXT_PUBLIC_ZILTOID, GATSBY_THE, NITRO_OMNISCIENT } = process.env;`, - ...options(), - filename: kitchenSinkFilename, - }, - ], - invalid: [ - { - code: `const { NEXT_PUBLIC_ZILTOID } = process.env;`, - ...options(), - filename: viteFilename, - errors: [ - { - message: - "NEXT_PUBLIC_ZILTOID is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: `const { VITE_THINGS } = process.env;`, - ...options(), - filename: nextJsFilename, - errors: [ - { - message: "VITE_THINGS is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: `const { VITE_THINGS } = process.env;`, - ...options(), - filename: kitchenSinkFilename, - errors: [ - { - message: "VITE_THINGS is not listed as a dependency in turbo.json", - }, - ], - }, - ], -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/framework-inference/no-undeclared-env-vars.module.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/framework-inference/no-undeclared-env-vars.module.test.ts deleted file mode 100644 index bd8ab7737b122..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/framework-inference/no-undeclared-env-vars.module.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import path from "node:path"; -import { RuleTester } from "eslint"; -import { RULES } from "../../../../lib/constants"; -import rule from "../../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020, sourceType: "module" }, -}); - -const cwd = path.join( - __dirname, - "../../../../__fixtures__/framework-inference" -); -const nextJsFilename = path.join(cwd, "/apps/nextjs/index.js"); -const viteFilename = path.join(cwd, "/apps/vite/index.js"); -const kitchenSinkFilename = path.join(cwd, "/apps/kitchen-sink/index.js"); -const options = (extra: Record = {}) => ({ - options: [ - { - cwd, - ...extra, - }, - ], -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: `const { NEXT_PUBLIC_ZILTOID } = import.meta.env;`, - ...options(), - filename: nextJsFilename, - }, - { - code: `const { VITE_THINGS } = import.meta.env;`, - ...options(), - filename: viteFilename, - }, - { - code: `const { NEXT_PUBLIC_ZILTOID, GATSBY_THE, NITRO_OMNISCIENT } = import.meta.env;`, - ...options(), - filename: kitchenSinkFilename, - }, - ], - invalid: [ - { - code: `const { NEXT_PUBLIC_ZILTOID } = import.meta.env;`, - ...options(), - filename: viteFilename, - errors: [ - { - message: - "NEXT_PUBLIC_ZILTOID is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: `const { VITE_THINGS } = import.meta.env;`, - ...options(), - filename: nextJsFilename, - errors: [ - { - message: "VITE_THINGS is not listed as a dependency in turbo.json", - }, - ], - }, - { - code: `const { VITE_THINGS } = import.meta.env;`, - ...options(), - filename: kitchenSinkFilename, - errors: [ - { - message: "VITE_THINGS is not listed as a dependency in turbo.json", - }, - ], - }, - ], -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/no-undeclared-env-vars.commonjs.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/no-undeclared-env-vars.commonjs.test.ts deleted file mode 100644 index 81e40b3b79a00..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/no-undeclared-env-vars.commonjs.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { RuleTester } from "eslint"; -import { RULES } from "../../../lib/constants"; -import rule from "../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020 }, -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: ` - const { TZ } = process.env; - `, - options: [{ cwd: "/some/random/path" }], - }, - { - code: ` - const { ENV_1 } = process.env; - `, - options: [{ cwd: "/some/random/path" }], - }, - ], - invalid: [], -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/no-undeclared-env-vars.module.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/no-undeclared-env-vars.module.test.ts deleted file mode 100644 index ee75c05f50d24..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/no-undeclared-env-vars.module.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { RuleTester } from "eslint"; -import { RULES } from "../../../lib/constants"; -import rule from "../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020, sourceType: "module" }, -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: ` - const { TZ } = import.meta.env; - `, - options: [{ cwd: "/some/random/path" }], - }, - { - code: ` - const { ENV_1 } = import.meta.env; - `, - options: [{ cwd: "/some/random/path" }], - }, - ], - invalid: [], -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/workspace-configs/no-undeclared-env-vars.commonjs.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/workspace-configs/no-undeclared-env-vars.commonjs.test.ts deleted file mode 100644 index de6129ae2b92a..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/workspace-configs/no-undeclared-env-vars.commonjs.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -import path from "node:path"; -import { RuleTester } from "eslint"; -import { RULES } from "../../../../lib/constants"; -import rule from "../../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020 }, -}); - -const cwd = path.join(__dirname, "../../../../__fixtures__/workspace-configs"); -const webFilename = path.join(cwd, "/apps/web/index.js"); -const docsFilename = path.join(cwd, "/apps/docs/index.js"); -const options = (extra: Record = {}) => ({ - options: [ - { - cwd, - ...extra, - }, - ], -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: ` - const env2 = process.env['ENV_2']; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const env2 = process.env["ENV_2"]; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { ENV_2 } = process.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { ROOT_DOT_ENV, WEB_DOT_ENV } = process.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { NEXT_PUBLIC_HAHAHAHA } = process.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { ENV_1 } = process.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { CI } = process.env; - `, - ...options(), - filename: webFilename, - }, - ], - invalid: [ - { - code: ` - const env2 = process.env['ENV_3']; - `, - ...options(), - filename: webFilename, - errors: [ - { - message: - "ENV_3 is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - ], - }, - { - code: ` - const env2 = process.env["ENV_3"]; - `, - ...options(), - filename: webFilename, - errors: [ - { - message: - "ENV_3 is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - ], - }, - { - code: ` - const { ENV_2 } = process.env; - `, - ...options(), - filename: docsFilename, - errors: [ - { - message: - "ENV_2 is not listed as a dependency in the root turbo.json or workspace (apps/docs) turbo.json", - }, - ], - }, - { - code: ` - const { NEXT_PUBLIC_HAHAHAHA, NEXT_PUBLIC_EXCLUDE, NEXT_PUBLIC_EXCLUDED } = process.env; - `, - ...options(), - filename: webFilename, - errors: [ - { - message: - "NEXT_PUBLIC_EXCLUDE is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - { - message: - "NEXT_PUBLIC_EXCLUDED is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - ], - }, - ], -}); diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/workspace-configs/no-undeclared-env-vars.module.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/workspace-configs/no-undeclared-env-vars.module.test.ts deleted file mode 100644 index 5ca66e6b4761f..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars/workspace-configs/no-undeclared-env-vars.module.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -import path from "node:path"; -import { RuleTester } from "eslint"; -import { RULES } from "../../../../lib/constants"; -import rule from "../../../../lib/rules/no-undeclared-env-vars"; - -const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 2020, sourceType: "module" }, -}); - -const cwd = path.join(__dirname, "../../../../__fixtures__/workspace-configs"); -const webFilename = path.join(cwd, "/apps/web/index.js"); -const docsFilename = path.join(cwd, "/apps/docs/index.js"); -const options = (extra: Record = {}) => ({ - options: [ - { - cwd, - ...extra, - }, - ], -}); - -ruleTester.run(RULES.noUndeclaredEnvVars, rule, { - valid: [ - { - code: ` - const env2 = import.meta.env['ENV_2']; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const env2 = import.meta.env["ENV_2"]; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { ENV_2 } = import.meta.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { ROOT_DOT_ENV, WEB_DOT_ENV } = import.meta.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { NEXT_PUBLIC_HAHAHAHA } = import.meta.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { ENV_1 } = import.meta.env; - `, - ...options(), - filename: webFilename, - }, - { - code: ` - const { CI } = import.meta.env; - `, - ...options(), - filename: webFilename, - }, - ], - invalid: [ - { - code: ` - const env2 = import.meta.env['ENV_3']; - `, - ...options(), - filename: webFilename, - errors: [ - { - message: - "ENV_3 is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - ], - }, - { - code: ` - const env2 = import.meta.env["ENV_3"]; - `, - ...options(), - filename: webFilename, - errors: [ - { - message: - "ENV_3 is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - ], - }, - { - code: ` - const { ENV_2 } = import.meta.env; - `, - ...options(), - filename: docsFilename, - errors: [ - { - message: - "ENV_2 is not listed as a dependency in the root turbo.json or workspace (apps/docs) turbo.json", - }, - ], - }, - { - code: ` - const { NEXT_PUBLIC_HAHAHAHA, NEXT_PUBLIC_EXCLUDE, NEXT_PUBLIC_EXCLUDED } = import.meta.env; - `, - ...options(), - filename: webFilename, - errors: [ - { - message: - "NEXT_PUBLIC_EXCLUDE is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - { - message: - "NEXT_PUBLIC_EXCLUDED is not listed as a dependency in the root turbo.json or workspace (apps/web) turbo.json", - }, - ], - }, - ], -}); diff --git a/packages/eslint-plugin-turbo/jest.config.js b/packages/eslint-plugin-turbo/jest.config.js new file mode 100644 index 0000000000000..286c1a0613822 --- /dev/null +++ b/packages/eslint-plugin-turbo/jest.config.js @@ -0,0 +1,14 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + roots: [""], + transform: { + "^.+\\.tsx?$": "ts-jest", + }, + testPathIgnorePatterns: ["/__fixtures__/"], + coveragePathIgnorePatterns: ["/__fixtures__/"], + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: ["/node_modules", "/dist"], + preset: "ts-jest", + verbose: process.env.RUNNER_DEBUG === "1", + silent: process.env.RUNNER_DEBUG !== "1", +}; diff --git a/packages/eslint-plugin-turbo/package.json b/packages/eslint-plugin-turbo/package.json index c412587707f76..d6d1951a28bb7 100644 --- a/packages/eslint-plugin-turbo/package.json +++ b/packages/eslint-plugin-turbo/package.json @@ -32,27 +32,27 @@ "lint:prettier": "prettier -c . --cache --ignore-path=../../.prettierignore" }, "dependencies": { - "dotenv": "16.0.3" + "dotenv": "16.4.7" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@turbo/eslint-config": "workspace:*", "@turbo/test-utils": "workspace:*", "@turbo/tsconfig": "workspace:*", "@turbo/types": "workspace:*", "@turbo/utils": "workspace:*", - "@types/eslint": "^8.56.10", - "@types/estree": "^1.0.1", - "@types/node": "^18.17.2", - "jest": "^29.7.0", - "json5": "^2.2.1", - "ts-jest": "^29.2.5", - "tsup": "^6.2.0", - "typescript": "5.5.4" + "@types/eslint": "9.6.1", + "@types/estree": "1.0.6", + "@types/node": "22.13.1", + "jest": "29.7.0", + "json5": "2.2.3", + "ts-jest": "29.2.5", + "tsup": "8.3.6", + "typescript": "5.7.3" }, "peerDependencies": { - "eslint": ">6.6.0", - "turbo": ">2.0.0" + "eslint": ">=9.20.1", + "turbo": ">=2.4.2" }, "license": "MIT" } diff --git a/packages/node-module-trace/package.json b/packages/node-module-trace/package.json new file mode 100644 index 0000000000000..40fe8b81469a3 --- /dev/null +++ b/packages/node-module-trace/package.json @@ -0,0 +1,7 @@ +{ + "name": "@vercel/experimental-nft", + "description": "Node.js module trace", + "dependencies": {}, + "devDependencies": {}, + "alias": "node-file-trace" +} diff --git a/packages/prysk/package.json b/packages/prysk/package.json index c6359014b637e..6298ae522ece0 100644 --- a/packages/prysk/package.json +++ b/packages/prysk/package.json @@ -1,6 +1,7 @@ { - "name": "prysk", - "description": "Wraps the python test runner prysk", - "private": true, - "bin": "index.mjs" + "name": "prysk", + "description": "Wraps the python test runner prysk", + "bin": "index.mjs", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/top-issues/README.md b/packages/top-issues/README.md deleted file mode 100644 index e7bab28c621ca..0000000000000 --- a/packages/top-issues/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# `@turbo/top-issues` - -This is an internal package that is used by a GitHub Actions Workflow to post -top issues in `vercel/turbo` to Slack. - -The code here gets the top issues and writes them to a file. The GitHub Action -workflow will then take that file and post it to Slack with a marketplace -action. diff --git a/packages/top-issues/src/index.mjs b/packages/top-issues/Source/index.mjs similarity index 100% rename from packages/top-issues/src/index.mjs rename to packages/top-issues/Source/index.mjs diff --git a/packages/top-issues/package.json b/packages/top-issues/package.json index 0c68076dd1a45..1a8b45d0de851 100644 --- a/packages/top-issues/package.json +++ b/packages/top-issues/package.json @@ -1,9 +1,9 @@ { - "name": "@turbo-internal/top-issues-gh-action", - "private": true, - "description": "Notify Turbo team about recent, popular issues. This is meant to be run as a GitHub Action.", - "dependencies": { - "@actions/core": "^1.10.1", - "@actions/github": "5.1.1" - } + "name": "@turbo-internal/top-issues-gh-action", + "description": "Notify Turbo team about recent, popular issues. This is meant to be run as a GitHub Action.", + "dependencies": { + "@actions/core": "1.11.1", + "@actions/github": "6.0.0" + }, + "devDependencies": {} } diff --git a/packages/tsconfig/README.md b/packages/tsconfig/README.md deleted file mode 100644 index e33c639d8e5fd..0000000000000 --- a/packages/tsconfig/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/tsconfig` - -Collection of internal tsconfigs shared between [turborepo/packages/](https://github.com/vercel/turborepo/tree/main/packages) diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json index 913e344367cf9..7140d7aa09588 100644 --- a/packages/tsconfig/package.json +++ b/packages/tsconfig/package.json @@ -1,5 +1,5 @@ { - "name": "@turbo/tsconfig", - "version": "0.0.0", - "private": true + "name": "@turbo/tsconfig", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-benchmark/.eslintignore b/packages/turbo-benchmark/.eslintignore deleted file mode 100644 index 908519ac181e6..0000000000000 --- a/packages/turbo-benchmark/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -src/templates/** diff --git a/packages/turbo-benchmark/.eslintrc.js b/packages/turbo-benchmark/.eslintrc.js deleted file mode 100644 index c4d04fe6260e6..0000000000000 --- a/packages/turbo-benchmark/.eslintrc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], - rules: { - "no-console": "off", - }, -}; diff --git a/packages/turbo-benchmark/README.md b/packages/turbo-benchmark/README.md deleted file mode 100644 index 2fe53013c516d..0000000000000 --- a/packages/turbo-benchmark/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Turborepo Benchmarking - -To run benchmarks for turborepo - -1. Follow the [Building Turborepo](../CONTRIBUTING.md#building-turborepo) instructions to install dependencies -2. `cargo build --package turbo --profile release-turborepo` to build turbo -3. From this directory `pnpm run benchmark` diff --git a/packages/turbo-benchmark/src/generate.mjs b/packages/turbo-benchmark/Source/generate.mjs similarity index 100% rename from packages/turbo-benchmark/src/generate.mjs rename to packages/turbo-benchmark/Source/generate.mjs diff --git a/packages/turbo-benchmark/src/helpers.ts b/packages/turbo-benchmark/Source/helpers.ts similarity index 100% rename from packages/turbo-benchmark/src/helpers.ts rename to packages/turbo-benchmark/Source/helpers.ts diff --git a/packages/turbo-benchmark/src/index.ts b/packages/turbo-benchmark/Source/index.ts similarity index 100% rename from packages/turbo-benchmark/src/index.ts rename to packages/turbo-benchmark/Source/index.ts diff --git a/packages/turbo-benchmark/src/templates/src/index.ts b/packages/turbo-benchmark/Source/templates/Source/index.ts similarity index 100% rename from packages/turbo-benchmark/src/templates/src/index.ts rename to packages/turbo-benchmark/Source/templates/Source/index.ts diff --git a/packages/turbo-benchmark/Source/templates/jest.config.js b/packages/turbo-benchmark/Source/templates/jest.config.js new file mode 100644 index 0000000000000..05483066e69d8 --- /dev/null +++ b/packages/turbo-benchmark/Source/templates/jest.config.js @@ -0,0 +1,10 @@ +module.exports = { + roots: ["/src"], + transform: { + "^.+\\.tsx?$": "ts-jest", + }, + // testRegex: '(/__tests__/.*(\\.|/)(test|spec))\\.tsx?$', + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: ["/src/__fixtures__"], + preset: "ts-jest", +}; diff --git a/packages/turbo-benchmark/src/templates/jest.config.ts b/packages/turbo-benchmark/Source/templates/jest.config.ts similarity index 100% rename from packages/turbo-benchmark/src/templates/jest.config.ts rename to packages/turbo-benchmark/Source/templates/jest.config.ts diff --git a/packages/turbo-benchmark/src/templates/tsconfig.json b/packages/turbo-benchmark/Source/templates/tsconfig.json similarity index 100% rename from packages/turbo-benchmark/src/templates/tsconfig.json rename to packages/turbo-benchmark/Source/templates/tsconfig.json diff --git a/packages/turbo-benchmark/src/ttft/build-vega.ts b/packages/turbo-benchmark/Source/ttft/build-vega.ts similarity index 100% rename from packages/turbo-benchmark/src/ttft/build-vega.ts rename to packages/turbo-benchmark/Source/ttft/build-vega.ts diff --git a/packages/turbo-benchmark/src/ttft/index.ts b/packages/turbo-benchmark/Source/ttft/index.ts old mode 100755 new mode 100644 similarity index 100% rename from packages/turbo-benchmark/src/ttft/index.ts rename to packages/turbo-benchmark/Source/ttft/index.ts diff --git a/packages/turbo-benchmark/src/ttft/run.ts b/packages/turbo-benchmark/Source/ttft/run.ts old mode 100755 new mode 100644 similarity index 100% rename from packages/turbo-benchmark/src/ttft/run.ts rename to packages/turbo-benchmark/Source/ttft/run.ts diff --git a/packages/turbo-benchmark/src/ttft/slack.ts b/packages/turbo-benchmark/Source/ttft/slack.ts similarity index 100% rename from packages/turbo-benchmark/src/ttft/slack.ts rename to packages/turbo-benchmark/Source/ttft/slack.ts diff --git a/packages/turbo-benchmark/src/ttft/tinybird.ts b/packages/turbo-benchmark/Source/ttft/tinybird.ts similarity index 100% rename from packages/turbo-benchmark/src/ttft/tinybird.ts rename to packages/turbo-benchmark/Source/ttft/tinybird.ts diff --git a/packages/turbo-benchmark/package.json b/packages/turbo-benchmark/package.json index bd6fc71545296..33bf39cb0327e 100644 --- a/packages/turbo-benchmark/package.json +++ b/packages/turbo-benchmark/package.json @@ -1,48 +1,41 @@ { - "name": "@turbo/benchmark", - "version": "1.0.0", - "scripts": { - "benchmark": "node -r esbuild-register src/index.ts", - "ttft": "node -r esbuild-register src/ttft/index.ts", - "lint": "eslint src", - "lint:prettier": "prettier -c src --cache --ignore-path=../.prettierignore", - "check-types": "tsc --noEmit", - "demo": "pnpm run demo:lage && pnpm run demo:lerna && pnpm run demo:nx && pnpm run demo:turbo", - "demo:lage": "node src/generate.mjs lage", - "demo:lerna": "node src/generate.mjs lerna", - "demo:nx": "node src/generate.mjs nx", - "demo:turbo": "node src/generate.mjs turbo", - "bench": "pnpm run bench:lerna && pnpm run bench:lage && pnpm run bench:nx && pnpm run bench:turbo", - "bench:lerna": "cd ./demo/lerna && node_modules/.bin/lerna run build", - "bench:lage": "echo $PWD && cd ./demo/lage && node_modules/.bin/lage build", - "bench:nx": "cd ./demo/nx && node_modules/.bin/nx run-many --target=build --all", - "bench:turbo": "cd ./demo/turbo && ./turbo run test", - "clean": "rm -rf ./demo" - }, - "dependencies": { - "@vercel/blob": "^0.22.1", - "copy-template-dir": "^1.4.0", - "esbuild": "^0.15.0", - "esbuild-register": "^3.3.2", - "faker": "^5.1.0", - "fs-extra": "^10.0.0", - "ndjson": "^2.0.0", - "ngraph.generators": "^19.3.0", - "node-fetch": "^2.6.8", - "sharp": "^0.33.2", - "shelljs": "^0.8.4", - "vega": "^5.27.0" - }, - "devDependencies": { - "@jest/globals": "29.7.0", - "@turbo/eslint-config": "workspace:*", - "@turbo/tsconfig": "workspace:*", - "@types/fs-extra": "^9.0.13", - "@types/ndjson": "^2.0.2", - "@types/node": "^18.17.4", - "@types/node-fetch": "^2.6.6", - "jest": "^29.7.0", - "ts-jest": "^29.2.5", - "typescript": "5.5.4" - } + "name": "@turbo/benchmark", + "scripts": { + "bench": "pnpm run bench:lerna && pnpm run bench:lage && pnpm run bench:nx && pnpm run bench:turbo", + "bench:lage": "echo $PWD && cd ./demo/lage && node_modules/.bin/lage build", + "bench:lerna": "cd ./demo/lerna && node_modules/.bin/lerna run build", + "bench:nx": "cd ./demo/nx && node_modules/.bin/nx run-many --target=build --all", + "bench:turbo": "cd ./demo/turbo && ./turbo run test", + "benchmark": "node -r esbuild-register src/index.ts", + "check-types": "tsc --noEmit", + "clean": "rm -rf ./demo", + "demo": "pnpm run demo:lage && pnpm run demo:lerna && pnpm run demo:nx && pnpm run demo:turbo", + "demo:lage": "node src/generate.mjs lage", + "demo:lerna": "node src/generate.mjs lerna", + "demo:nx": "node src/generate.mjs nx", + "demo:turbo": "node src/generate.mjs turbo", + "ttft": "node -r esbuild-register src/ttft/index.ts" + }, + "dependencies": { + "@vercel/blob": "0.27.1", + "copy-template-dir": "1.4.0", + "esbuild": "0.25.0", + "esbuild-register": "3.6.0", + "faker": "6.6.6", + "fs-extra": "11.3.0", + "ndjson": "2.0.0", + "ngraph.generators": "20.1.0", + "node-fetch": "3.3.2", + "sharp": "0.33.5", + "shelljs": "0.8.5", + "vega": "5.31.0" + }, + "devDependencies": { + "@turbo/eslint-config": "workspace:*", + "@turbo/tsconfig": "workspace:*", + "@types/fs-extra": "11.0.4", + "@types/ndjson": "2.0.4", + "@types/node": "22.13.1", + "@types/node-fetch": "2.6.12" + } } diff --git a/packages/turbo-benchmark/src/templates/src/__tests__/index.test.ts b/packages/turbo-benchmark/src/templates/src/__tests__/index.test.ts deleted file mode 100644 index 6a91522a3409b..0000000000000 --- a/packages/turbo-benchmark/src/templates/src/__tests__/index.test.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { sum } from "../."; -import { describe, it, expect } from "@jest/globals"; - -describe("Hello", () => { - it("renders without crashing", () => { - expect(sum(1, 2)).toEqual(3); - }); -}); diff --git a/packages/turbo-benchmark/src/templates/src/__tests__/tsconfig.json b/packages/turbo-benchmark/src/templates/src/__tests__/tsconfig.json deleted file mode 100644 index bf65be62f2d5c..0000000000000 --- a/packages/turbo-benchmark/src/templates/src/__tests__/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": [".", "../."] -} diff --git a/packages/turbo-codemod/.eslintrc.js b/packages/turbo-codemod/.eslintrc.js deleted file mode 100644 index 4ca761e2f8eb5..0000000000000 --- a/packages/turbo-codemod/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], -}; diff --git a/packages/turbo-codemod/README.md b/packages/turbo-codemod/README.md deleted file mode 100644 index 5545561f660bc..0000000000000 --- a/packages/turbo-codemod/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Turborepo Codemods - -Turborepo provides Codemod transformations to help upgrade your Turborepo codebase. - -Codemods are transformations that run on your codebase programmatically. This allows for a large amount of changes to be applied without having to manually go through every file. - -## Commands - -### `migrate` - -Updates your Turborepo codebase to the specified version of Turborepo (defaults to the latest), running any required codemods, and installing the new version of Turborepo. - -``` -Usage: @turbo/codemod migrate|update [options] [path] - -Migrate a project to the latest version of Turborepo - -Arguments: - path Directory where the transforms should be applied - -Options: - --from Specify the version to migrate from (default: current version) - --to Specify the version to migrate to (default: latest) - --install Install new version of turbo after migration (default: true) - --force Bypass Git safety checks and forcibly run codemods (default: false) - --dry Dry run (no changes are made to files) (default: false) - --print Print transformed files to your terminal (default: false) - -h, --help display help for command -``` - -### `transform` (default) - -Runs a single codemod on your codebase. This is the default command, and can be omitted. - -``` -Usage: @turbo/codemod transform [options] [transform] [path] - @turbo/codemod [options] [transform] [path] - -Apply a single code transformation to a project - -Arguments: - transform The transformer to run - path Directory where the transforms should be applied - -Options: - --force Bypass Git safety checks and forcibly run codemods (default: false) - --list List all available transforms (default: false) - --dry Dry run (no changes are made to files) (default: false) - --print Print transformed files to your terminal (default: false) - -h, --help display help for command -``` - -## Developing - -To add a new transformer, run `pnpm add-transformer`, or [view the complete guide](./src/transforms/README.md). diff --git a/packages/turbo-codemod/src/cli.ts b/packages/turbo-codemod/Source/cli.ts similarity index 100% rename from packages/turbo-codemod/src/cli.ts rename to packages/turbo-codemod/Source/cli.ts diff --git a/packages/turbo-codemod/src/commands/index.ts b/packages/turbo-codemod/Source/commands/index.ts similarity index 100% rename from packages/turbo-codemod/src/commands/index.ts rename to packages/turbo-codemod/Source/commands/index.ts diff --git a/packages/turbo-codemod/src/commands/migrate/index.ts b/packages/turbo-codemod/Source/commands/migrate/index.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/index.ts rename to packages/turbo-codemod/Source/commands/migrate/index.ts diff --git a/packages/turbo-codemod/src/commands/migrate/steps/getCurrentVersion.ts b/packages/turbo-codemod/Source/commands/migrate/steps/getCurrentVersion.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/steps/getCurrentVersion.ts rename to packages/turbo-codemod/Source/commands/migrate/steps/getCurrentVersion.ts diff --git a/packages/turbo-codemod/src/commands/migrate/steps/getLatestVersion.ts b/packages/turbo-codemod/Source/commands/migrate/steps/getLatestVersion.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/steps/getLatestVersion.ts rename to packages/turbo-codemod/Source/commands/migrate/steps/getLatestVersion.ts diff --git a/packages/turbo-codemod/src/commands/migrate/steps/getTransformsForMigration.ts b/packages/turbo-codemod/Source/commands/migrate/steps/getTransformsForMigration.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/steps/getTransformsForMigration.ts rename to packages/turbo-codemod/Source/commands/migrate/steps/getTransformsForMigration.ts diff --git a/packages/turbo-codemod/src/commands/migrate/steps/getTurboUpgradeCommand.ts b/packages/turbo-codemod/Source/commands/migrate/steps/getTurboUpgradeCommand.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/steps/getTurboUpgradeCommand.ts rename to packages/turbo-codemod/Source/commands/migrate/steps/getTurboUpgradeCommand.ts diff --git a/packages/turbo-codemod/src/commands/migrate/steps/shutdownDaemon.ts b/packages/turbo-codemod/Source/commands/migrate/steps/shutdownDaemon.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/steps/shutdownDaemon.ts rename to packages/turbo-codemod/Source/commands/migrate/steps/shutdownDaemon.ts diff --git a/packages/turbo-codemod/src/commands/migrate/types.ts b/packages/turbo-codemod/Source/commands/migrate/types.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/types.ts rename to packages/turbo-codemod/Source/commands/migrate/types.ts diff --git a/packages/turbo-codemod/src/commands/migrate/utils.ts b/packages/turbo-codemod/Source/commands/migrate/utils.ts similarity index 100% rename from packages/turbo-codemod/src/commands/migrate/utils.ts rename to packages/turbo-codemod/Source/commands/migrate/utils.ts diff --git a/packages/turbo-codemod/src/commands/transform/index.ts b/packages/turbo-codemod/Source/commands/transform/index.ts similarity index 100% rename from packages/turbo-codemod/src/commands/transform/index.ts rename to packages/turbo-codemod/Source/commands/transform/index.ts diff --git a/packages/turbo-codemod/src/commands/transform/types.ts b/packages/turbo-codemod/Source/commands/transform/types.ts similarity index 100% rename from packages/turbo-codemod/src/commands/transform/types.ts rename to packages/turbo-codemod/Source/commands/transform/types.ts diff --git a/packages/turbo-codemod/src/runner/FileTransform.ts b/packages/turbo-codemod/Source/runner/FileTransform.ts similarity index 100% rename from packages/turbo-codemod/src/runner/FileTransform.ts rename to packages/turbo-codemod/Source/runner/FileTransform.ts diff --git a/packages/turbo-codemod/src/runner/Runner.ts b/packages/turbo-codemod/Source/runner/Runner.ts similarity index 100% rename from packages/turbo-codemod/src/runner/Runner.ts rename to packages/turbo-codemod/Source/runner/Runner.ts diff --git a/packages/turbo-codemod/src/runner/index.ts b/packages/turbo-codemod/Source/runner/index.ts similarity index 100% rename from packages/turbo-codemod/src/runner/index.ts rename to packages/turbo-codemod/Source/runner/index.ts diff --git a/packages/turbo-codemod/src/runner/types.ts b/packages/turbo-codemod/Source/runner/types.ts similarity index 100% rename from packages/turbo-codemod/src/runner/types.ts rename to packages/turbo-codemod/Source/runner/types.ts diff --git a/packages/turbo-codemod/src/transforms/add-package-manager.ts b/packages/turbo-codemod/Source/transforms/add-package-manager.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/add-package-manager.ts rename to packages/turbo-codemod/Source/transforms/add-package-manager.ts diff --git a/packages/turbo-codemod/src/transforms/add-package-names.ts b/packages/turbo-codemod/Source/transforms/add-package-names.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/add-package-names.ts rename to packages/turbo-codemod/Source/transforms/add-package-names.ts diff --git a/packages/turbo-codemod/src/transforms/clean-globs.ts b/packages/turbo-codemod/Source/transforms/clean-globs.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/clean-globs.ts rename to packages/turbo-codemod/Source/transforms/clean-globs.ts diff --git a/packages/turbo-codemod/src/transforms/create-turbo-config.ts b/packages/turbo-codemod/Source/transforms/create-turbo-config.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/create-turbo-config.ts rename to packages/turbo-codemod/Source/transforms/create-turbo-config.ts diff --git a/packages/turbo-codemod/src/transforms/migrate-dot-env.ts b/packages/turbo-codemod/Source/transforms/migrate-dot-env.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/migrate-dot-env.ts rename to packages/turbo-codemod/Source/transforms/migrate-dot-env.ts diff --git a/packages/turbo-codemod/src/transforms/migrate-env-var-dependencies.ts b/packages/turbo-codemod/Source/transforms/migrate-env-var-dependencies.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/migrate-env-var-dependencies.ts rename to packages/turbo-codemod/Source/transforms/migrate-env-var-dependencies.ts diff --git a/packages/turbo-codemod/src/transforms/rename-output-mode.ts b/packages/turbo-codemod/Source/transforms/rename-output-mode.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/rename-output-mode.ts rename to packages/turbo-codemod/Source/transforms/rename-output-mode.ts diff --git a/packages/turbo-codemod/src/transforms/rename-pipeline.ts b/packages/turbo-codemod/Source/transforms/rename-pipeline.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/rename-pipeline.ts rename to packages/turbo-codemod/Source/transforms/rename-pipeline.ts diff --git a/packages/turbo-codemod/src/transforms/set-default-outputs.ts b/packages/turbo-codemod/Source/transforms/set-default-outputs.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/set-default-outputs.ts rename to packages/turbo-codemod/Source/transforms/set-default-outputs.ts diff --git a/packages/turbo-codemod/src/transforms/stabilize-env-mode.ts b/packages/turbo-codemod/Source/transforms/stabilize-env-mode.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/stabilize-env-mode.ts rename to packages/turbo-codemod/Source/transforms/stabilize-env-mode.ts diff --git a/packages/turbo-codemod/src/transforms/stabilize-ui.ts b/packages/turbo-codemod/Source/transforms/stabilize-ui.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/stabilize-ui.ts rename to packages/turbo-codemod/Source/transforms/stabilize-ui.ts diff --git a/packages/turbo-codemod/src/transforms/transform-env-literals-to-wildcards.ts b/packages/turbo-codemod/Source/transforms/transform-env-literals-to-wildcards.ts similarity index 100% rename from packages/turbo-codemod/src/transforms/transform-env-literals-to-wildcards.ts rename to packages/turbo-codemod/Source/transforms/transform-env-literals-to-wildcards.ts diff --git a/packages/turbo-codemod/src/types.ts b/packages/turbo-codemod/Source/types.ts similarity index 100% rename from packages/turbo-codemod/src/types.ts rename to packages/turbo-codemod/Source/types.ts diff --git a/packages/turbo-codemod/src/utils/checkGitStatus.ts b/packages/turbo-codemod/Source/utils/checkGitStatus.ts similarity index 100% rename from packages/turbo-codemod/src/utils/checkGitStatus.ts rename to packages/turbo-codemod/Source/utils/checkGitStatus.ts diff --git a/packages/turbo-codemod/src/utils/directoryInfo.ts b/packages/turbo-codemod/Source/utils/directoryInfo.ts similarity index 100% rename from packages/turbo-codemod/src/utils/directoryInfo.ts rename to packages/turbo-codemod/Source/utils/directoryInfo.ts diff --git a/packages/turbo-codemod/src/utils/getTransformerHelpers.ts b/packages/turbo-codemod/Source/utils/getTransformerHelpers.ts similarity index 100% rename from packages/turbo-codemod/src/utils/getTransformerHelpers.ts rename to packages/turbo-codemod/Source/utils/getTransformerHelpers.ts diff --git a/packages/turbo-codemod/src/utils/loadTransformers.ts b/packages/turbo-codemod/Source/utils/loadTransformers.ts similarity index 100% rename from packages/turbo-codemod/src/utils/loadTransformers.ts rename to packages/turbo-codemod/Source/utils/loadTransformers.ts diff --git a/packages/turbo-codemod/src/utils/loadTurboJson.ts b/packages/turbo-codemod/Source/utils/loadTurboJson.ts similarity index 100% rename from packages/turbo-codemod/src/utils/loadTurboJson.ts rename to packages/turbo-codemod/Source/utils/loadTurboJson.ts diff --git a/packages/turbo-codemod/src/utils/logger.ts b/packages/turbo-codemod/Source/utils/logger.ts similarity index 100% rename from packages/turbo-codemod/src/utils/logger.ts rename to packages/turbo-codemod/Source/utils/logger.ts diff --git a/packages/turbo-codemod/src/utils/looksLikeRepo.ts b/packages/turbo-codemod/Source/utils/looksLikeRepo.ts similarity index 100% rename from packages/turbo-codemod/src/utils/looksLikeRepo.ts rename to packages/turbo-codemod/Source/utils/looksLikeRepo.ts diff --git a/packages/turbo-codemod/src/utils/notifyUpdate.ts b/packages/turbo-codemod/Source/utils/notifyUpdate.ts similarity index 100% rename from packages/turbo-codemod/src/utils/notifyUpdate.ts rename to packages/turbo-codemod/Source/utils/notifyUpdate.ts diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/has-package-manager/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/has-package-manager/package.json deleted file mode 100644 index d6edac5a550f5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/has-package-manager/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "has-package-manager", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/no-package-manager/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/no-package-manager/package.json deleted file mode 100644 index 2e28fe4684af3..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/no-package-manager/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "no-package-manager", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/wrong-package-manager/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/wrong-package-manager/package.json deleted file mode 100644 index f58aca2b1a778..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-manager/wrong-package-manager/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "has-package-manager", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "turbo@1.7.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/package.json deleted file mode 100644 index 4da92049f9be5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "root", - "workspaces": [ - "packages/*" - ], - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/packages/ui/package.json deleted file mode 100644 index 0a833e899ae58..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/packages/ui/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "ui", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/packages/utils/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/packages/utils/package.json deleted file mode 100644 index f980397cf1c01..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/correct-names/packages/utils/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "utils", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/package.json deleted file mode 100644 index 4da92049f9be5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "root", - "workspaces": [ - "packages/*" - ], - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/apps/docs/package.json deleted file mode 100644 index 3abadc5cc44c3..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/apps/docs/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "@acme/docs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/apps/web/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/apps/web/package.json deleted file mode 100644 index 3abadc5cc44c3..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/apps/web/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "@acme/docs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/ui/package.json deleted file mode 100644 index fe616c702a22a..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/ui/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "some-pkg", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/utils/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/utils/package.json deleted file mode 100644 index fe616c702a22a..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/duplicate-names/packages/utils/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "some-pkg", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/package.json deleted file mode 100644 index 27bb15f33630d..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "root", - "workspaces": [ - "packages/*", - "!packages/ui" - ], - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "pnpm@8.15.4" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/packages/ui/package.json deleted file mode 100644 index 2e5879a21b308..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/packages/ui/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/packages/utils/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/packages/utils/package.json deleted file mode 100644 index f980397cf1c01..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/packages/utils/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "utils", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/pnpm-workspace.yaml b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/pnpm-workspace.yaml deleted file mode 100644 index bf8462e53767b..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/ignored-packages/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -packages: - - "packages/*" - - "!packages/ui" diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/package.json deleted file mode 100644 index 4da92049f9be5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "root", - "workspaces": [ - "packages/*" - ], - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/packages/ui/package.json deleted file mode 100644 index 2e5879a21b308..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/packages/ui/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/packages/utils/package.json b/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/packages/utils/package.json deleted file mode 100644 index 2e5879a21b308..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/add-package-names/missing-names/packages/utils/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/clean-globs/clean-globs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/clean-globs/clean-globs/package.json deleted file mode 100644 index 0967ef424bce6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/clean-globs/clean-globs/package.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/clean-globs/clean-globs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/clean-globs/clean-globs/turbo.json deleted file mode 100644 index c879014c37587..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/clean-globs/clean-globs/turbo.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "../../../../../../docs/public/schema.json", - "pipeline": { - "case_1": { - "inputs": ["../../app-store/**/**", "**/**/result.json"], - "outputs": ["../../app-store/**/**", "**/**/result.json"] - }, - "case_2": { - "inputs": ["!**/dist", "!**/node_modules"], - "outputs": ["!**/dist", "!**/node_modules"] - }, - "case_3": { - "inputs": [ - "cypress/integration/**.test.ts", - "src/types/generated/**.ts", - "scripts/**.mjs", - "scripts/**.js" - ], - "outputs": [ - "cypress/integration/**.test.ts", - "src/types/generated/**.ts", - "scripts/**.mjs", - "scripts/**.js" - ] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/both-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/both-configs/package.json deleted file mode 100644 index c4606fa004ecc..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/both-configs/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "both-configs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3", - "turbo": { - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "package-only": { - "cache": false, - "persistent": true - }, - "build": { - "outputs": [ - ".next/**", - "!.next/cache/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/both-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/both-configs/turbo.json deleted file mode 100644 index e6eb6522e4709..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/both-configs/turbo.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "turbo-only": { - "cache": false, - "persistent": true - }, - "build": { - "outputs": [".next/**", "!.next/cache/**"] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-package-json-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-package-json-config/package.json deleted file mode 100644 index b965b7d241991..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-package-json-config/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-turbo-json-config", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-package-json-file/a-random-file.txt b/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-package-json-file/a-random-file.txt deleted file mode 100644 index 7488fec2fb491..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-package-json-file/a-random-file.txt +++ /dev/null @@ -1 +0,0 @@ -Nothing exists here diff --git a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-turbo-json-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-turbo-json-config/package.json deleted file mode 100644 index 7754c7d2fd200..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/no-turbo-json-config/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "no-turbo-json-config", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3", - "turbo": { - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build": { - "outputs": [ - ".next/**", - "!.next/cache/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/turbo-json-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/turbo-json-config/package.json deleted file mode 100644 index a48d0ec648e0b..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/turbo-json-config/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "both-configs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/turbo-json-config/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/turbo-json-config/turbo.json deleted file mode 100644 index e6eb6522e4709..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/create-turbo-config/turbo-json-config/turbo.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "turbo-only": { - "cache": false, - "persistent": true - }, - "build": { - "outputs": [".next/**", "!.next/cache/**"] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-deps/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-deps/package.json deleted file mode 100644 index b632eefa7de27..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-deps/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "no-turbo", - "version": "0.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-package/README.md b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-package/README.md deleted file mode 100644 index 64355e7d19a6a..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-package/README.md +++ /dev/null @@ -1 +0,0 @@ -Nothing here diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-turbo/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-turbo/package.json deleted file mode 100644 index 524df502ea0da..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/no-turbo/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "no-turbo", - "version": "0.0.0", - "dependencies": {}, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/normal-workspaces-dev-install/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/normal-workspaces-dev-install/package.json deleted file mode 100644 index f5b2368eb0711..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/normal-workspaces-dev-install/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "normal-workspaces", - "version": "0.0.0", - "workspaces": [ - "apps/*", - "packages/*" - ], - "dependencies": {}, - "devDependencies": { - "turbo": "1.0.0" - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/normal-workspaces/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/normal-workspaces/package.json deleted file mode 100644 index 6344a38d27e8c..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/normal-workspaces/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "normal-workspaces", - "version": "0.0.0", - "workspaces": [ - "apps/*", - "packages/*" - ], - "dependencies": { - "turbo": "1.0.0" - }, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces-dev-install/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces-dev-install/package.json deleted file mode 100644 index 5c12f28a5476e..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces-dev-install/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "pnpm-workspaces", - "version": "0.0.0", - "dependencies": {}, - "devDependencies": { - "turbo": "1.0.0" - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces-dev-install/pnpm-workspace.yaml b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces-dev-install/pnpm-workspace.yaml deleted file mode 100644 index 3ff5faaaf5f13..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces-dev-install/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -packages: - - "apps/*" - - "packages/*" diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces/package.json deleted file mode 100644 index fedeb8d1b6654..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "pnpm-workspaces", - "version": "0.0.0", - "dependencies": { - "turbo": "1.0.0" - }, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces/pnpm-workspace.yaml b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces/pnpm-workspace.yaml deleted file mode 100644 index 3ff5faaaf5f13..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/pnpm-workspaces/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -packages: - - "apps/*" - - "packages/*" diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/single-package-dev-install/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/single-package-dev-install/package.json deleted file mode 100644 index 38bd995f7470d..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/single-package-dev-install/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "single-package-dev-install", - "version": "0.0.0", - "dependencies": {}, - "devDependencies": { - "turbo": "1.0.0" - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/single-package/package.json b/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/single-package/package.json deleted file mode 100644 index 0fd3453677dad..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/get-turbo-upgrade-command/single-package/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "single-package", - "version": "0.0.0", - "dependencies": { - "turbo": "1.0.0" - }, - "devDependencies": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-dot-env/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-dot-env/package.json deleted file mode 100644 index 4e17dc1580d17..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-dot-env/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-dot-env/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-dot-env/turbo.json deleted file mode 100644 index 8626eccbf24e0..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-dot-env/turbo.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build-one": { - "dependsOn": ["build-two"] - }, - "build-two": { - "cache": false - }, - "build-three": { - "persistent": true - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-pipeline/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-pipeline/package.json deleted file mode 100644 index 6e20fc8fea33f..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-pipeline/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-pipeline", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-pipeline/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-pipeline/turbo.json deleted file mode 100644 index 43131abdbb781..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-pipeline/turbo.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - "tasks": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-turbo-json/package.json deleted file mode 100644 index cd983346b8584..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "set-default-outputs-no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/with-dot-env/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/with-dot-env/package.json deleted file mode 100644 index e4220baf4c6b9..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/with-dot-env/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "old-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/with-dot-env/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/with-dot-env/turbo.json deleted file mode 100644 index 1a7fda5aa2c8c..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/with-dot-env/turbo.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDotEnv": [".env"], - "tasks": { - "build-one": { - "dotEnv": ["build-one/.env"] - }, - "build-two": { - "dotEnv": ["build-two/.env"], - "inputs": ["build-two/main.js"] - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/index.js b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/index.js deleted file mode 100644 index 4de53f5ec2caa..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function docs() { - if (process.env.ENV_1 === undefined) { - return "does not exist"; - } - return "exists"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/package.json deleted file mode 100644 index 82f9a44736f00..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "docs", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/turbo.json deleted file mode 100644 index ffd1e39374ab9..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/docs/turbo.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "tasks": { - "build": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/index.js b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/index.js deleted file mode 100644 index bfd3ab817a0de..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function web() { - if (!process.env.ENV_2) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/package.json deleted file mode 100644 index d8a83edbd32a1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "web", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/turbo.json deleted file mode 100644 index b45133c008346..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/apps/web/turbo.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "tasks": { - "build": { - // old - "dotEnv": [".env"], - "inputs": ["src/**/*.ts"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/package.json deleted file mode 100644 index c6616a615d2d5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/index.js b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/index.js deleted file mode 100644 index dee5e80cd6992..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function foo() { - if (!process.env.IS_SERVER) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/package.json deleted file mode 100644 index 7cb7cf17345dc..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "ui", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/turbo.json deleted file mode 100644 index 852b684e6a67e..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/packages/ui/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "tasks": { - "build-three": { - "dotEnv": [".env"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/turbo.json deleted file mode 100644 index 6e047ca1f5bfd..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-dot-env/workspace-configs/turbo.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build-one": { - "dotEnv": ["build-one/.env"] - }, - "build-two": { - "dotEnv": ["build-two/.env"], - "inputs": ["build-two/**/*.ts"] - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/env-dependencies/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/env-dependencies/turbo.json deleted file mode 100644 index bb3e2484b59c1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/env-dependencies/turbo.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - "pipeline": { - "build": { - "outputs": [".next/**", "!.next/cache/**"], - "dependsOn": ["^build", "$PROD_API_KEY"] - }, - "lint": { - "outputs": [], - "dependsOn": ["$IS_CI"] - }, - "test": { - "outputs": [], - "dependsOn": ["$IS_CI", "test"] - }, - "dev": { - "cache": false - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/migrated-env-dependencies/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/migrated-env-dependencies/turbo.json deleted file mode 100644 index 9217af680e020..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/migrated-env-dependencies/turbo.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": [], - "globalEnv": ["NEXT_PUBLIC_API_KEY", "STRIPE_API_KEY"], - "pipeline": { - "build": { - "dependsOn": ["^build"], - "env": ["PROD_API_KEY"], - "outputs": [".next/**", "!.next/cache/**"] - }, - "dev": { - "cache": false - }, - "lint": { - "dependsOn": [], - "env": ["IS_CI"], - "outputs": [] - }, - "test": { - "dependsOn": ["test"], - "env": ["IS_CI"], - "outputs": [] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/no-turbo-json/package.json deleted file mode 100644 index 83443be28012a..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/old-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/old-config/package.json deleted file mode 100644 index 6774d3ce615a4..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/old-config/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "migrate-env-var-dependencies-old-config", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3", - "turbo": { - "pipeline": { - "build-one": { - "outputs": [ - "foo" - ] - }, - "build-two": { - "outputs": [] - }, - "build-three": {} - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/old-config/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/old-config/turbo.json deleted file mode 100644 index b0f615072a2ac..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/old-config/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputs": ["foo"] - }, - "build-two": { - "outputs": [] - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/index.js b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/index.js deleted file mode 100644 index 4de53f5ec2caa..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function docs() { - if (process.env.ENV_1 === undefined) { - return "does not exist"; - } - return "exists"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/package.json deleted file mode 100644 index 82f9a44736f00..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "docs", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/turbo.json deleted file mode 100644 index a3713efab8eec..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/docs/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": { - "env": ["ENV_3"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/index.js b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/index.js deleted file mode 100644 index bfd3ab817a0de..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function web() { - if (!process.env.ENV_2) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/package.json deleted file mode 100644 index d8a83edbd32a1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "web", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/turbo.json deleted file mode 100644 index dd69c3130a3fa..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/apps/web/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": { - // old - "dependsOn": ["build", "$ENV_2"], - // new - "env": ["ENV_1"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/package.json deleted file mode 100644 index c6616a615d2d5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/index.js b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/index.js deleted file mode 100644 index dee5e80cd6992..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function foo() { - if (!process.env.IS_SERVER) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/package.json deleted file mode 100644 index 7cb7cf17345dc..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "ui", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/turbo.json deleted file mode 100644 index 6ce7b3007b67b..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/packages/ui/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": { - "dependsOn": ["$IS_SERVER"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/turbo.json deleted file mode 100644 index 718e4619b41e8..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate-env-var-dependencies/workspace-configs/turbo.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - "pipeline": { - "build": { - "outputs": [".next/**", "!.next/cache/**"], - "dependsOn": ["^build", "$PROD_API_KEY"] - }, - "lint": { - "outputs": [], - "dependsOn": ["$IS_TEST"] - }, - "test": { - "outputs": [], - "dependsOn": ["$IS_CI", "test"] - }, - "dev": { - "cache": false - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate/no-repo/README.md b/packages/turbo-codemod/__tests__/__fixtures__/migrate/no-repo/README.md deleted file mode 100644 index 64355e7d19a6a..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate/no-repo/README.md +++ /dev/null @@ -1 +0,0 @@ -Nothing here diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate/old-turbo/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate/old-turbo/package.json deleted file mode 100644 index 62959b8388a6e..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate/old-turbo/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": { - "turbo": "1.0.0" - }, - "turbo": { - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build": { - "outputs": [ - ".next/**", - "!.next/cache/**" - ] - }, - "lint": { - "outputs": [] - }, - "test": {}, - "dev": { - "cache": false - } - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate/turbo-1/package.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate/turbo-1/package.json deleted file mode 100644 index 24a20e7c3b688..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate/turbo-1/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "turbo-1", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": { - "turbo": "1.7.1" - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/migrate/turbo-1/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/migrate/turbo-1/turbo.json deleted file mode 100644 index 68f85a6513427..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/migrate/turbo-1/turbo.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - // A comment which we allow - "pipeline": { - "build": { - "outputs": [".next/**", "!.next/cache/**"] - }, - "lint": { - "dotEnv": [".env.local"], - "outputs": [] - }, - "test": { - "outputMode": "errors-only" - }, - "dev": { - "cache": false - } - }, - "experimentalUI": true -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/invalid-output-mode/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/invalid-output-mode/package.json deleted file mode 100644 index 6b50aacd6c2a7..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/invalid-output-mode/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "invalid-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/invalid-output-mode/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/invalid-output-mode/turbo.json deleted file mode 100644 index 816e9f6295cfc..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/invalid-output-mode/turbo.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputMode": "errors-only" - }, - "build-two": { - "outputMode": [] - }, - "build-three": {}, - "garbage-in-numeric-0": { - "outputMode": 0 - }, - "garbage-in-numeric": { - "outputMode": 42 - }, - "garbage-in-string": { - "outputMode": "string" - }, - "garbage-in-empty-string": { - "outputMode": "" - }, - "garbage-in-null": { - "outputMode": null - }, - "garbage-in-false": { - "outputMode": false - }, - "garbage-in-true": { - "outputMode": true - }, - "garbage-in-object": { - "outputMode": {} - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-output-mode/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-output-mode/package.json deleted file mode 100644 index 4e17dc1580d17..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-output-mode/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-output-mode/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-output-mode/turbo.json deleted file mode 100644 index f5d57fcc231bb..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-output-mode/turbo.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "dependsOn": ["build-two"] - }, - "build-two": { - "cache": false - }, - "build-three": { - "persistent": true - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-pipeline/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-pipeline/package.json deleted file mode 100644 index 6e20fc8fea33f..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-pipeline/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-pipeline", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-pipeline/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-pipeline/turbo.json deleted file mode 100644 index 0e2d6fd17ed74..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-pipeline/turbo.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - "pipeline": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-turbo-json/package.json deleted file mode 100644 index cd983346b8584..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "set-default-outputs-no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-config/package.json deleted file mode 100644 index 662a519471385..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-config/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "set-default-outputs-old-config", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3", - "turbo": { - "pipeline": { - "build-one": { - "outputMode": "errors-only" - }, - "build-two": { - "outputMode": "none" - }, - "build-three": {} - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-config/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-config/turbo.json deleted file mode 100644 index 1e2d653f41ae0..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-config/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputMode": "errors-only" - }, - "build-two": { - "outputMode": "none" - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-output-mode/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-output-mode/package.json deleted file mode 100644 index e4220baf4c6b9..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-output-mode/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "old-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-output-mode/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-output-mode/turbo.json deleted file mode 100644 index 3338946304cc6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/old-output-mode/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputMode": "hash-only" - }, - "build-two": { - "outputMode": "full" - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/index.js b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/index.js deleted file mode 100644 index 4de53f5ec2caa..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function docs() { - if (process.env.ENV_1 === undefined) { - return "does not exist"; - } - return "exists"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/package.json deleted file mode 100644 index 82f9a44736f00..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "docs", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/turbo.json deleted file mode 100644 index e60cdb750955c..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/docs/turbo.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/index.js b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/index.js deleted file mode 100644 index bfd3ab817a0de..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function web() { - if (!process.env.ENV_2) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/package.json deleted file mode 100644 index d8a83edbd32a1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "web", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/turbo.json deleted file mode 100644 index 9154476a84363..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/apps/web/turbo.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": { - // old - "outputMode": "none" - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/package.json deleted file mode 100644 index c6616a615d2d5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/index.js b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/index.js deleted file mode 100644 index dee5e80cd6992..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function foo() { - if (!process.env.IS_SERVER) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/package.json deleted file mode 100644 index 7cb7cf17345dc..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "ui", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/turbo.json deleted file mode 100644 index caf46e51da937..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/packages/ui/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build-three": { - "outputMode": "new-only" - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/turbo.json deleted file mode 100644 index 252d4a27e035f..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-output-mode/workspace-configs/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputMode": "new-only" - }, - "build-two": { - "outputMode": "none" - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/no-turbo-json/package.json deleted file mode 100644 index cd983346b8584..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "set-default-outputs-no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/important.txt b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/important.txt deleted file mode 100644 index ce013625030ba..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/important.txt +++ /dev/null @@ -1 +0,0 @@ -hello diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/package.json deleted file mode 100644 index 0967ef424bce6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/package.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/turbo.json deleted file mode 100644 index caa7754bb02c9..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/root-only/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": ["important.txt"], - "pipeline": { - "build": { - "outputs": ["dist"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/with-tasks/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/with-tasks/turbo.json deleted file mode 100644 index 3d6dcac06cfac..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/with-tasks/turbo.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build": { - "outputs": ["dist"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/index.js b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/index.js deleted file mode 100644 index 4de53f5ec2caa..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function docs() { - if (process.env.ENV_1 === undefined) { - return "does not exist"; - } - return "exists"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/package.json deleted file mode 100644 index 82f9a44736f00..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "docs", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/turbo.json deleted file mode 100644 index a3713efab8eec..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/docs/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": { - "env": ["ENV_3"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/index.js b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/index.js deleted file mode 100644 index bfd3ab817a0de..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function web() { - if (!process.env.ENV_2) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/package.json deleted file mode 100644 index d8a83edbd32a1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "web", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/turbo.json deleted file mode 100644 index 2adc44b444f16..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/apps/web/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": { - "dependsOn": [] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/package.json deleted file mode 100644 index c6616a615d2d5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/index.js b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/index.js deleted file mode 100644 index dee5e80cd6992..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function foo() { - if (!process.env.IS_SERVER) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/package.json deleted file mode 100644 index 7cb7cf17345dc..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "ui", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/turbo.json deleted file mode 100644 index f82702d1356df..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/packages/ui/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "test": { - "dependsOn": ["build"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/turbo.json deleted file mode 100644 index 6a7d63e0dcb41..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/rename-pipeline/workspace-configs/turbo.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build": { - "outputs": [".next/**", "!.next/cache/**"], - "dependsOn": ["^build"] - }, - "lint": { - "outputs": [] - }, - "test": { - "outputs": [] - }, - "dev": { - "cache": false - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/invalid-outputs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/invalid-outputs/package.json deleted file mode 100644 index 6b50aacd6c2a7..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/invalid-outputs/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "invalid-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/invalid-outputs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/invalid-outputs/turbo.json deleted file mode 100644 index 33c2b93b8738c..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/invalid-outputs/turbo.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputs": ["foo"] - }, - "build-two": { - "outputs": [] - }, - "build-three": {}, - "garbage-in-numeric-0": { - "outputs": 0 - }, - "garbage-in-numeric": { - "outputs": 42 - }, - "garbage-in-string": { - "outputs": "string" - }, - "garbage-in-empty-string": { - "outputs": "" - }, - "garbage-in-null": { - "outputs": null - }, - "garbage-in-false": { - "outputs": false - }, - "garbage-in-true": { - "outputs": true - }, - "garbage-in-object": { - "outputs": {} - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-outputs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-outputs/package.json deleted file mode 100644 index 4e17dc1580d17..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-outputs/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-outputs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-outputs/turbo.json deleted file mode 100644 index f5d57fcc231bb..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-outputs/turbo.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "dependsOn": ["build-two"] - }, - "build-two": { - "cache": false - }, - "build-three": { - "persistent": true - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-pipeline/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-pipeline/package.json deleted file mode 100644 index 6e20fc8fea33f..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-pipeline/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "no-pipeline", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-pipeline/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-pipeline/turbo.json deleted file mode 100644 index 0e2d6fd17ed74..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-pipeline/turbo.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - "pipeline": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-turbo-json/package.json deleted file mode 100644 index cd983346b8584..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "set-default-outputs-no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-config/package.json deleted file mode 100644 index 4c816c2a26535..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-config/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "set-default-outputs-old-config", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3", - "turbo": { - "pipeline": { - "build-one": { - "outputs": [ - "foo" - ] - }, - "build-two": { - "outputs": [] - }, - "build-three": {} - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-config/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-config/turbo.json deleted file mode 100644 index b0f615072a2ac..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-config/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputs": ["foo"] - }, - "build-two": { - "outputs": [] - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-outputs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-outputs/package.json deleted file mode 100644 index e4220baf4c6b9..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-outputs/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "old-outputs", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-outputs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-outputs/turbo.json deleted file mode 100644 index b0f615072a2ac..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/old-outputs/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputs": ["foo"] - }, - "build-two": { - "outputs": [] - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/index.js b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/index.js deleted file mode 100644 index 4de53f5ec2caa..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function docs() { - if (process.env.ENV_1 === undefined) { - return "does not exist"; - } - return "exists"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/package.json deleted file mode 100644 index 82f9a44736f00..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "docs", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/turbo.json deleted file mode 100644 index e60cdb750955c..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/docs/turbo.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/index.js b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/index.js deleted file mode 100644 index bfd3ab817a0de..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function web() { - if (!process.env.ENV_2) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/package.json deleted file mode 100644 index d8a83edbd32a1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "web", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/turbo.json deleted file mode 100644 index b239cbf3d1da2..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/apps/web/turbo.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build": { - // old - "outputs": [] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/package.json deleted file mode 100644 index c6616a615d2d5..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/index.js b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/index.js deleted file mode 100644 index dee5e80cd6992..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function foo() { - if (!process.env.IS_SERVER) { - return "bar"; - } - return "foo"; -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/package.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/package.json deleted file mode 100644 index 7cb7cf17345dc..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "ui", - "version": "1.0.0" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/turbo.json deleted file mode 100644 index fe5111997e17a..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/packages/ui/turbo.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "pipeline": { - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/turbo.json deleted file mode 100644 index b0f615072a2ac..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/set-default-outputs/workspace-configs/turbo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build-one": { - "outputs": ["foo"] - }, - "build-two": { - "outputs": [] - }, - "build-three": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-both/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-both/turbo.json deleted file mode 100644 index aeb3832b3045e..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-both/turbo.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "experimentalGlobalPassThroughEnv": ["EXPERIMENTAL_GLOBAL_PASSTHROUGH"], - "globalPassThroughEnv": ["GLOBAL_PASSTHROUGH"], - "pipeline": { - "build": { - "experimentalPassThroughEnv": ["EXPERIMENTAL_TASK_PASSTHROUGH"], - "passThroughEnv": ["TASK_PASSTHROUGH"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-duplicates/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-duplicates/turbo.json deleted file mode 100644 index ce3114ef210c6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-duplicates/turbo.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "experimentalGlobalPassThroughEnv": [ - "DUPLICATE_GLOBAL", - "DUPLICATE_GLOBAL", - "EXPERIMENTAL_GLOBAL_PASSTHROUGH" - ], - "globalPassThroughEnv": [ - "DUPLICATE_GLOBAL", - "DUPLICATE_GLOBAL", - "GLOBAL_PASSTHROUGH" - ], - "pipeline": { - "build": { - "experimentalPassThroughEnv": [ - "DUPLICATE_TASK", - "DUPLICATE_TASK", - "EXPERIMENTAL_TASK_PASSTHROUGH" - ], - "passThroughEnv": ["DUPLICATE_TASK", "DUPLICATE_TASK", "TASK_PASSTHROUGH"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-empty/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-empty/turbo.json deleted file mode 100644 index cae6810aa7dff..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-empty/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "experimentalGlobalPassThroughEnv": [], - "pipeline": { - "build": { - "experimentalPassThroughEnv": [] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-neither/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-neither/turbo.json deleted file mode 100644 index d4487028869da..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-neither/turbo.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-new/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-new/turbo.json deleted file mode 100644 index 34b660f75d049..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-new/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalPassThroughEnv": ["GLOBAL_PASSTHROUGH"], - "pipeline": { - "build": { - "passThroughEnv": ["TASK_PASSTHROUGH"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-old/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-old/turbo.json deleted file mode 100644 index c24826d6ced6b..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/has-old/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "experimentalGlobalPassThroughEnv": ["GLOBAL_PASSTHROUGH"], - "pipeline": { - "build": { - "experimentalPassThroughEnv": ["TASK_PASSTHROUGH"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/no-turbo-json/package.json deleted file mode 100644 index aa617c22147da..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "stabilize-env-mode-no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/old-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/old-config/package.json deleted file mode 100644 index dee4d36e44406..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/old-config/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "stabilize-env-mode-old-config", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3", - "turbo": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/docs/package.json deleted file mode 100644 index 4652bd790cec0..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/docs/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "stabilize-env-mode-docs" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/docs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/docs/turbo.json deleted file mode 100644 index a394f8ec0d06a..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/docs/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": ["//"], - "pipeline": { - "build": { - "experimentalPassThroughEnv": ["EXPERIMENTAL_DOCS_TASK_PASSTHROUGH"], - "passThroughEnv": ["DOCS_TASK_PASSTHROUGH"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/website/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/website/package.json deleted file mode 100644 index 47efe80369ec1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/website/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "stabilize-env-mode-website" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/website/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/website/turbo.json deleted file mode 100644 index 4af676c7807cf..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/apps/website/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": ["//"], - "pipeline": { - "build": { - "experimentalPassThroughEnv": ["EXPERIMENTAL_WEBSITE_TASK_PASSTHROUGH"], - "passThroughEnv": ["WEBSITE_TASK_PASSTHROUGH"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/package.json deleted file mode 100644 index 60fcf9becdd65..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "private": true, - "workspaces": [ - "apps/*" - ], - "packageManager": "yarn@1.22.19" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/turbo.json deleted file mode 100644 index aeb3832b3045e..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-env-mode/workspace-configs/turbo.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "experimentalGlobalPassThroughEnv": ["EXPERIMENTAL_GLOBAL_PASSTHROUGH"], - "globalPassThroughEnv": ["GLOBAL_PASSTHROUGH"], - "pipeline": { - "build": { - "experimentalPassThroughEnv": ["EXPERIMENTAL_TASK_PASSTHROUGH"], - "passThroughEnv": ["TASK_PASSTHROUGH"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/disabled/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/disabled/package.json deleted file mode 100644 index 0967ef424bce6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/disabled/package.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/disabled/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/disabled/turbo.json deleted file mode 100644 index f0d4e6a0422d0..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/disabled/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build": { - "outputs": ["dist"] - } - }, - "experimentalUI": false -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/enabled/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/enabled/package.json deleted file mode 100644 index 0967ef424bce6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/enabled/package.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/enabled/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/enabled/turbo.json deleted file mode 100644 index 6083eb8b249d8..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/enabled/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build": { - "outputs": ["dist"] - } - }, - "experimentalUI": true -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-config/package.json deleted file mode 100644 index 0967ef424bce6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-config/package.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-config/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-config/turbo.json deleted file mode 100644 index 3d6dcac06cfac..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-config/turbo.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build": { - "outputs": ["dist"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-turbo-json/package.json deleted file mode 100644 index cd983346b8584..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/stabilize-ui/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "set-default-outputs-no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/has-empty/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/has-empty/turbo.json deleted file mode 100644 index 69b8f1e4742e2..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/has-empty/turbo.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalEnv": [], - "globalPassThroughEnv": [], - "pipeline": { - "build": { - "env": [], - "passThroughEnv": [] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/has-nothing/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/has-nothing/turbo.json deleted file mode 100644 index d4487028869da..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/has-nothing/turbo.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "pipeline": { - "build": {} - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/needs-rewriting/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/needs-rewriting/turbo.json deleted file mode 100644 index 29fb6cba4f9af..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/needs-rewriting/turbo.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalEnv": ["NO!", "!!!", "!!!"], - "globalPassThroughEnv": ["DOES", "**BOLD**", "WORK"], - "pipeline": { - "build": { - "env": ["PLAIN", "SMALL_PRINT*"], - "passThroughEnv": ["PASSWORD", "*****"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/no-turbo-json/package.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/no-turbo-json/package.json deleted file mode 100644 index 59f9fd0a90528..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/no-turbo-json/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "transform-env-literals-to-wildcards-no-turbo-json", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/old-config/package.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/old-config/package.json deleted file mode 100644 index 0fb3b2d5f94b7..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/old-config/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "transform-env-literals-to-wildcards-old-config", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": {}, - "packageManager": "npm@1.2.3", - "turbo": {} -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/docs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/docs/package.json deleted file mode 100644 index e90b6ceca5a21..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/docs/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "transform-env-literals-to-wildcards-docs" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/docs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/docs/turbo.json deleted file mode 100644 index 0df4958c90ae6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/docs/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": ["//"], - "pipeline": { - "build": { - "env": ["NO_DOCS_ENV", "!*!*DOCS"], - "passThroughEnv": ["NO_DOCS_PASSTHROUGH_ENV", "!*!*DOCS"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/website/package.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/website/package.json deleted file mode 100644 index e0aad834c7347..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/website/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "transform-env-literals-to-wildcards-website" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/website/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/website/turbo.json deleted file mode 100644 index c89a552697396..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/apps/website/turbo.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": ["//"], - "pipeline": { - "build": { - "env": ["NO_WEBSITE_ENV", "!*!*WEBSITE"], - "passThroughEnv": ["NO_WEBSITE_PASSTHROUGH_ENV", "!*!*WEBSITE"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/package.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/package.json deleted file mode 100644 index 60fcf9becdd65..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "private": true, - "workspaces": [ - "apps/*" - ], - "packageManager": "yarn@1.22.19" -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/turbo.json b/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/turbo.json deleted file mode 100644 index 69dfeba1c2bd1..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform-env-literals-to-wildcards/workspace-configs/turbo.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalEnv": ["!*!*"], - "globalPassThroughEnv": ["!*!*"], - "pipeline": { - "build": { - "env": ["NO_ROOT_ENV", "!*!*ROOT"], - "passThroughEnv": ["NO_ROOT_PASSTHROUGH_ENV", "!*!*ROOT"] - } - } -} diff --git a/packages/turbo-codemod/__tests__/__fixtures__/transform/basic/package.json b/packages/turbo-codemod/__tests__/__fixtures__/transform/basic/package.json deleted file mode 100644 index 651edb65f86f6..0000000000000 --- a/packages/turbo-codemod/__tests__/__fixtures__/transform/basic/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "transform-basic", - "version": "1.0.0", - "dependencies": {}, - "devDependencies": { - "turbo": "1.0.0" - } -} diff --git a/packages/turbo-codemod/__tests__/add-package-manager.test.ts b/packages/turbo-codemod/__tests__/add-package-manager.test.ts deleted file mode 100644 index 374997e222e69..0000000000000 --- a/packages/turbo-codemod/__tests__/add-package-manager.test.ts +++ /dev/null @@ -1,336 +0,0 @@ -import fs from "fs-extra"; -import * as turboWorkspaces from "@turbo/workspaces"; -import * as turboUtils from "@turbo/utils"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { transformer } from "../src/transforms/add-package-manager"; -import type { TransformerResults } from "../src/runner"; -import type { TransformerOptions } from "../src/types"; -import { getWorkspaceDetailsMockReturnValue } from "./test-utils"; - -jest.mock("@turbo/workspaces", () => ({ - __esModule: true, - ...jest.requireActual("@turbo/workspaces"), -})); - -interface TestCase { - name: string; - fixture: string; - existingPackageManagerString: string | undefined; - packageManager: turboUtils.PackageManager; - packageManagerVersion: string; - options: TransformerOptions; - result: TransformerResults; -} - -const TEST_CASES: Array = [ - { - name: "basic", - fixture: "no-package-manager", - existingPackageManagerString: undefined, - packageManager: "npm", - packageManagerVersion: "7.0.0", - options: { force: false, dryRun: false, print: false }, - result: { - changes: { - "package.json": { - action: "modified", - additions: 1, - deletions: 0, - }, - }, - }, - }, - { - name: "dry", - fixture: "no-package-manager", - existingPackageManagerString: undefined, - packageManager: "npm", - packageManagerVersion: "7.0.0", - options: { force: false, dryRun: true, print: false }, - result: { - changes: { - "package.json": { - action: "skipped", - additions: 1, - deletions: 0, - }, - }, - }, - }, - { - name: "print", - fixture: "no-package-manager", - existingPackageManagerString: undefined, - packageManager: "yarn", - packageManagerVersion: "1.2.3", - options: { force: false, dryRun: false, print: true }, - result: { - changes: { - "package.json": { - action: "modified", - additions: 1, - deletions: 0, - }, - }, - }, - }, - { - name: "print & dry", - fixture: "no-package-manager", - existingPackageManagerString: undefined, - packageManager: "pnpm", - packageManagerVersion: "1.2.3", - options: { force: false, dryRun: true, print: true }, - result: { - changes: { - "package.json": { - action: "skipped", - additions: 1, - deletions: 0, - }, - }, - }, - }, - { - name: "basic", - fixture: "has-package-manager", - existingPackageManagerString: "npm@1.2.3", - packageManager: "npm", - packageManagerVersion: "1.2.3", - options: { force: false, dryRun: false, print: false }, - result: { - changes: {}, - }, - }, - { - name: "basic", - fixture: "wrong-package-manager", - existingPackageManagerString: "turbo@1.7.0", - packageManager: "pnpm", - packageManagerVersion: "1.2.3", - options: { force: false, dryRun: false, print: false }, - result: { - changes: {}, - }, - }, -]; - -describe("add-package-manager-2", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "add-package-manager", - }); - - it.each(TEST_CASES)( - "$fixture - $name with $packageManager@$packageManagerVersion using $options", - async ({ - fixture, - existingPackageManagerString, - packageManager, - packageManagerVersion, - options, - result, - }) => { - // load the fixture for the test - const { root, read } = useFixture({ fixture }); - - // mock out workspace and version detection so we're not dependent on our actual repo - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManager === "pnpm" ? packageManagerVersion : undefined, - npm: packageManager === "npm" ? packageManagerVersion : undefined, - yarn: packageManager === "yarn" ? packageManagerVersion : undefined, - bun: packageManager === "bun" ? packageManagerVersion : undefined, - }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - // verify package manager - expect(JSON.parse(read("package.json") || "{}").packageManager).toEqual( - existingPackageManagerString - ); - - // run the transformer - const transformerResult = await transformer({ - root, - options, - }); - - if (existingPackageManagerString === undefined) { - expect(mockGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockGetWorkspaceDetails).toHaveBeenCalled(); - } - - expect(JSON.parse(read("package.json") || "{}").packageManager).toEqual( - options.dryRun - ? undefined - : existingPackageManagerString || - `${packageManager}@${packageManagerVersion}` - ); - - // result should be correct - expect(transformerResult.changes).toMatchObject(result.changes); - - // run the transformer again to ensure nothing changes on a second run - const repeatResult = await transformer({ - root, - options, - }); - expect(repeatResult.fatalError).toBeUndefined(); - expect(repeatResult.changes).toMatchObject({}); - - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - } - ); - - describe("errors", () => { - it("unable to determine workspace manager", async () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-package-manager" }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockRejectedValue(undefined); - - // package manager should not exist - expect( - JSON.parse(read("package.json") || "{}").packageManager - ).toBeUndefined(); - // run the transformer - const result = await transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(mockGetWorkspaceDetails).toHaveBeenCalledTimes(1); - - // result should be correct - expect(result.fatalError?.message).toMatch( - /Unable to determine package manager for .*?/ - ); - - mockGetWorkspaceDetails.mockRestore(); - }); - - it("unable to determine package manager version", async () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-package-manager" }); - - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: undefined, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager: "npm", - }) - ); - - // package manager should not exist - expect( - JSON.parse(read("package.json") || "{}").packageManager - ).toBeUndefined(); - // run the transformer - const result = await transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(mockGetAvailablePackageManagers).toHaveBeenCalledTimes(1); - expect(mockGetWorkspaceDetails).toHaveBeenCalledTimes(1); - - // result should be correct - expect(result.fatalError?.message).toMatch( - /Unable to determine package manager version for .*?/ - ); - - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - }); - - it("unable to write json", async () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-package-manager" }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // mock out workspace and version detection so we're not dependent on our actual repo - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - const mockWriteJsonSync = jest - .spyOn(fs, "writeJsonSync") - .mockImplementation(() => { - throw new Error("could not write file"); - }); - - // package manager should not exist - expect( - JSON.parse(read("package.json") || "{}").packageManager - ).toBeUndefined(); - // run the transformer - const result = await transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // package manager should still not exist (we couldn't write it) - expect( - JSON.parse(read("package.json") || "{}").packageManager - ).toBeUndefined(); - - // result should be correct - expect(result.fatalError?.message).toMatch( - "Encountered an error while transforming files" - ); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "error", - "additions": 1, - "deletions": 0, - "error": [Error: could not write file], - }, - } - `); - - mockWriteJsonSync.mockRestore(); - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - }); - }); -}); diff --git a/packages/turbo-codemod/__tests__/add-package-names.test.ts b/packages/turbo-codemod/__tests__/add-package-names.test.ts deleted file mode 100644 index bf66f60b9978a..0000000000000 --- a/packages/turbo-codemod/__tests__/add-package-names.test.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/add-package-names"; - -describe("add-package-names", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "add-package-names", - }); - - it("missing names", async () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "missing-names", - }); - - // run the transformer - const result = await transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "packages/ui/package.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - "packages/utils/package.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - } - `); - - // validate unique names - const names = new Set(); - - for (const pkg of ["ui", "utils"]) { - const pkgJson = readJson<{ name: string }>( - `packages/${pkg}/package.json` - ); - expect(pkgJson?.name).toBeDefined(); - expect(names.has(pkgJson?.name)).toBe(false); - names.add(pkgJson?.name); - } - }); - - it("duplicate names", async () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "duplicate-names", - }); - - // run the transformer - const result = await transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "packages/utils/package.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - } - `); - - // validate unique names - const names = new Set(); - - for (const pkg of ["ui", "utils"]) { - const pkgJson = readJson<{ name: string }>( - `packages/${pkg}/package.json` - ); - expect(pkgJson?.name).toBeDefined(); - expect(names.has(pkgJson?.name)).toBe(false); - names.add(pkgJson?.name); - } - }); - - it("correct names", async () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "correct-names", - }); - - // run the transformer - const result = await transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(`{}`); - - // validate unique names - const names = new Set(); - - for (const pkg of ["ui", "utils"]) { - const pkgJson = readJson<{ name: string }>( - `packages/${pkg}/package.json` - ); - expect(pkgJson?.name).toBeDefined(); - expect(names.has(pkgJson?.name)).toBe(false); - names.add(pkgJson?.name); - } - }); - - it("ignored packages", async () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "ignored-packages", - }); - - // run the transformer - const result = await transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(`{}`); - - // validate unique names - const names = new Set(); - - const pkg = "utils"; - const pkgJson = readJson<{ name: string }>(`packages/${pkg}/package.json`); - expect(pkgJson?.name).toBeDefined(); - expect(names.has(pkgJson?.name)).toBe(false); - names.add(pkgJson?.name); - - const unchangedPkg = "ui"; - const unchangedPkgJson = readJson<{ name: string }>( - `packages/${unchangedPkg}/package.json` - ); - expect(unchangedPkgJson?.name).toBeUndefined(); - }); -}); diff --git a/packages/turbo-codemod/__tests__/clean-globs.test.ts b/packages/turbo-codemod/__tests__/clean-globs.test.ts deleted file mode 100644 index 63a9622fb4a23..0000000000000 --- a/packages/turbo-codemod/__tests__/clean-globs.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { transformer, fixGlobPattern } from "../src/transforms/clean-globs"; - -describe("clean-globs", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "clean-globs", - }); - - it("basic", () => { - // load the fixture for the test - const { root } = useFixture({ - fixture: "clean-globs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 6, - "deletions": 6, - }, - } - `); - }); - - it("collapses back-to-back doublestars", () => { - const badGlobPatterns = [ - ["../../app-store/**/**", "../../app-store/**"], - ["**/**/result.json", "**/result.json"], - ["**/**/**/**", "**"], - ["**/foo/**/**/bar/**", "**/foo/**/bar/**"], - ["**/foo/**/**/**/bar/**/**", "**/foo/**/bar/**"], - ["**/foo/**/**/**/**/bar/**/**/**", "**/foo/**/bar/**"], - ]; - - // Now let's test the function - badGlobPatterns.forEach(([input, output]) => { - expect(fixGlobPattern(input)).toBe(output); - }); - }); - - it("doesn't update valid globs and prints a message", () => { - // Now let's test the function - expect(fixGlobPattern("a/b/c/*")).toBe("a/b/c/*"); - }); - - it("transforms '**ext' to '**/*ext'", () => { - const badGlobPatterns = [ - ["cypress/integration/**.test.ts", "cypress/integration/**/*.test.ts"], - ["scripts/**.mjs", "scripts/**/*.mjs"], - ["scripts/**.js", "scripts/**/*.js"], - ["src/types/generated/**.ts", "src/types/generated/**/*.ts"], - ["**md", "**/*md"], - ["**txt", "**/*txt"], - ["**html", "**/*html"], - ]; - - // Now let's test the function - badGlobPatterns.forEach(([input, output]) => { - expect(fixGlobPattern(input)).toBe(output); - }); - }); - - it("transforms 'pre**' to pre*/**", () => { - const badGlobPatterns = [ - ["pre**", "pre*/**"], - ["pre**/foo", "pre*/**/foo"], - ["pre**/foo/bar", "pre*/**/foo/bar"], - ["pre**/foo/bar/baz", "pre*/**/foo/bar/baz"], - ["pre**/foo/bar/baz/qux", "pre*/**/foo/bar/baz/qux"], - ]; - - // Now let's test the function - badGlobPatterns.forEach(([input, output]) => { - expect(fixGlobPattern(input)).toBe(output); - }); - }); - - it("should collapse back-to-back doublestars to a single doublestar", () => { - expect(fixGlobPattern("../../app-store/**/**")).toBe("../../app-store/**"); - expect(fixGlobPattern("**/**/result.json")).toBe("**/result.json"); - }); - - it("should change **.ext to **/*.ext", () => { - expect(fixGlobPattern("**.js")).toBe("**/*.js"); - expect(fixGlobPattern("**.json")).toBe("**/*.json"); - expect(fixGlobPattern("**.ext")).toBe("**/*.ext"); - }); - - it("should change prefix** to prefix*/**", () => { - expect(fixGlobPattern("app**")).toBe("app*/**"); - expect(fixGlobPattern("src**")).toBe("src*/**"); - expect(fixGlobPattern("prefix**")).toBe("prefix*/**"); - }); - - it("should collapse back-to-back doublestars and change **.ext to **/*.ext", () => { - expect(fixGlobPattern("../../app-store/**/**/*.js")).toBe( - "../../app-store/**/*.js" - ); - expect(fixGlobPattern("**/**/result.json")).toBe("**/result.json"); - }); - - it("should collapse back-to-back doublestars and change prefix** to prefix*/**", () => { - expect(fixGlobPattern("../../app-store/**/**prefix**")).toBe( - "../../app-store/**/*prefix*/**" - ); - expect(fixGlobPattern("**/**/prefix**")).toBe("**/prefix*/**"); - }); - - it("should not modify valid glob patterns", () => { - expect(fixGlobPattern("src/**/*.js")).toBe("src/**/*.js"); - expect(fixGlobPattern("src/**/test/*.js")).toBe("src/**/test/*.js"); - expect(fixGlobPattern("src/**/test/**/*.js")).toBe("src/**/test/**/*.js"); - expect(fixGlobPattern("src/**/test/**/result.json")).toBe( - "src/**/test/**/result.json" - ); - }); - - it("should handle glob patterns with non-ASCII characters", () => { - expect(fixGlobPattern("src/日本語/**/*.js")).toBe("src/日本語/**/*.js"); - expect(fixGlobPattern("src/中文/**/*.json")).toBe("src/中文/**/*.json"); - expect(fixGlobPattern("src/руÑÑкий/**/*.ts")).toBe("src/руÑÑкий/**/*.ts"); - }); - it("should handle glob patterns with emojis", () => { - expect(fixGlobPattern("src/👋**/*.js")).toBe("src/👋*/**/*.js"); - expect(fixGlobPattern("src/🌎**/*.json")).toBe("src/🌎*/**/*.json"); - expect(fixGlobPattern("src/🚀**/*.ts")).toBe("src/🚀*/**/*.ts"); - }); -}); diff --git a/packages/turbo-codemod/__tests__/create-turbo-config.test.ts b/packages/turbo-codemod/__tests__/create-turbo-config.test.ts deleted file mode 100644 index d7bf60e04fe08..0000000000000 --- a/packages/turbo-codemod/__tests__/create-turbo-config.test.ts +++ /dev/null @@ -1,417 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import fs from "fs-extra"; -import { transformer } from "../src/transforms/create-turbo-config"; - -describe("create-turbo-config", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "create-turbo-config", - }); - - it("package.json config exists but no turbo.json config - basic", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-turbo-json-config" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // get config from package.json for comparison later - const turboConfig = JSON.parse(read("package.json") || "{}").turbo; - expect(turboConfig).toBeDefined(); - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // turbo.json should now exist (and match the package.json config) - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboConfig); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "modified", - "additions": 0, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - } - `); - }); - - it("package.json config exists but no turbo.json config - repeat run", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-turbo-json-config" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // get config from package.json for comparison later - const turboConfig = JSON.parse(read("package.json") || "{}").turbo; - expect(turboConfig).toBeDefined(); - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // turbo.json should now exist (and match the package.json config) - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboConfig); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "modified", - "additions": 0, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - } - `); - - // run the transformer - const repeatResult = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - // result should be correct - expect(repeatResult.fatalError).toBeUndefined(); - expect(repeatResult.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("package.json config exists but no turbo.json config - dry", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-turbo-json-config" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // get config from package.json for comparison later - const turboConfig = JSON.parse(read("package.json") || "{}").turbo; - expect(turboConfig).toBeDefined(); - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // turbo.json still not exist (dry run) - expect(read("turbo.json")).toBeUndefined(); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "skipped", - "additions": 0, - "deletions": 1, - }, - "turbo.json": { - "action": "skipped", - "additions": 1, - "deletions": 0, - }, - } - `); - }); - - it("package.json config exists but no turbo.json config - print", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-turbo-json-config" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // get config from package.json for comparison later - const turboConfig = JSON.parse(read("package.json") || "{}").turbo; - expect(turboConfig).toBeDefined(); - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: true }, - }); - - // turbo.json should now exist (and match the package.json config) - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboConfig); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "modified", - "additions": 0, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - } - `); - }); - - it("package.json config exists but no turbo.json config - dry & print", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-turbo-json-config" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // get config from package.json for comparison later - const turboConfig = JSON.parse(read("package.json") || "{}").turbo; - expect(turboConfig).toBeDefined(); - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: true }, - }); - - // turbo.json still not exist (dry run) - expect(read("turbo.json")).toBeUndefined(); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "skipped", - "additions": 0, - "deletions": 1, - }, - "turbo.json": { - "action": "skipped", - "additions": 1, - "deletions": 0, - }, - } - `); - }); - - it("no package.json config or turbo.json file exists", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-package-json-config" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // get config from package.json for comparison later - const packageJsonConfig = JSON.parse(read("package.json") || "{}"); - const turboConfig = packageJsonConfig.turbo; - expect(turboConfig).toBeUndefined(); - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // turbo.json should still not exist - expect(read("turbo.json")).toBeUndefined(); - - // make sure we didn't change the package.json - expect(JSON.parse(read("package.json") || "{}")).toEqual(packageJsonConfig); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("no package.json file exists", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-package-json-file" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // turbo.json should still not exist - expect(read("turbo.json")).toBeUndefined(); - - // result should be correct - expect(result.fatalError?.message).toMatch( - /No package\.json found at .*?\. Is the path correct\?/ - ); - }); - - it("turbo.json file exists and no package.json config exists", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "turbo-json-config" }); - - // turbo.json should exist - expect(read("turbo.json")).toBeDefined(); - - // no config should exist in package.json - const packageJsonConfig = JSON.parse(read("package.json") || "{}"); - const turboConfig = packageJsonConfig.turbo; - expect(turboConfig).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // turbo.json should still exist - expect(read("turbo.json")).toBeDefined(); - - // make sure we didn't change the package.json - expect(JSON.parse(read("package.json") || "{}")).toEqual(packageJsonConfig); - - // result should be correct - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("turbo.json file exists and package.json config exists", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "both-configs" }); - - // turbo.json should exist - const turboJsonConfig = JSON.parse(read("turbo.json") || "{}"); - expect(turboJsonConfig.pipeline).toBeDefined(); - - // no config should exist in package.json - const packageJsonConfig = JSON.parse(read("package.json") || "{}"); - const turboConfig = JSON.parse(read("package.json") || "{}").turbo; - expect(turboConfig).toBeDefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // make sure we didn't change the package.json - expect(JSON.parse(read("package.json") || "{}")).toEqual(packageJsonConfig); - - // make sure we didn't change the turbo.json - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJsonConfig); - - // result should be correct - expect(result.fatalError?.message).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("errors when unable to write json", () => { - // load the fixture for the test - const { root, read } = useFixture({ fixture: "no-turbo-json-config" }); - - // turbo.json should not exist - expect(read("turbo.json")).toBeUndefined(); - - // get config from package.json for comparison later - const turboConfig = JSON.parse(read("package.json") || "{}").turbo; - expect(turboConfig).toBeDefined(); - - const mockWriteJsonSync = jest - .spyOn(fs, "writeJsonSync") - .mockImplementation(() => { - throw new Error("could not write file"); - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - // turbo.json should still not exist (error writing) - expect(read("turbo.json")).toBeUndefined(); - - // result should be correct - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - "Encountered an error while transforming files" - ); - expect(result.changes).toMatchInlineSnapshot(` - { - "package.json": { - "action": "error", - "additions": 0, - "deletions": 1, - "error": [Error: could not write file], - }, - "turbo.json": { - "action": "error", - "additions": 1, - "deletions": 0, - "error": [Error: could not write file], - }, - } - `); - - mockWriteJsonSync.mockRestore(); - }); -}); diff --git a/packages/turbo-codemod/__tests__/generate-package-name.test.ts b/packages/turbo-codemod/__tests__/generate-package-name.test.ts deleted file mode 100644 index a42d120191181..0000000000000 --- a/packages/turbo-codemod/__tests__/generate-package-name.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, it, expect } from "@jest/globals"; -import { getNewPkgName } from "../src/transforms/add-package-names"; - -describe("getNewPkgName", () => { - it.each([ - { - pkgPath: "/packages/ui/package.json", - pkgName: "old-name", - expected: "ui-old-name", - }, - // scoped - { - pkgPath: "/packages/ui/package.json", - pkgName: "@acme/name", - expected: "@acme/ui-name", - }, - // no name - { - pkgPath: "/packages/ui/package.json", - pkgName: undefined, - expected: "ui", - }, - ])( - "should return a new package name for pkgPath: $pkgPath and pkgName: $pkgName", - ({ pkgPath, pkgName, expected }) => { - const newName = getNewPkgName({ pkgPath, pkgName }); - expect(newName).toBe(expected); - } - ); -}); diff --git a/packages/turbo-codemod/__tests__/get-transforms-for-migration.test.ts b/packages/turbo-codemod/__tests__/get-transforms-for-migration.test.ts deleted file mode 100644 index e1ddf72ecaa38..0000000000000 --- a/packages/turbo-codemod/__tests__/get-transforms-for-migration.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { describe, it, expect } from "@jest/globals"; -import { getTransformsForMigration } from "../src/commands/migrate/steps/getTransformsForMigration"; - -describe("get-transforms-for-migration", () => { - it("ordering", () => { - const results = getTransformsForMigration({ - fromVersion: "1.0.0", - toVersion: "1.10.0", - }); - - expect(results.map((transform) => transform.name)).toEqual([ - "add-package-manager", - "create-turbo-config", - "migrate-env-var-dependencies", - "set-default-outputs", - "stabilize-env-mode", - "transform-env-literals-to-wildcards", - ]); - }); -}); diff --git a/packages/turbo-codemod/__tests__/get-turbo-upgrade-command.test.ts b/packages/turbo-codemod/__tests__/get-turbo-upgrade-command.test.ts deleted file mode 100644 index f3a5b2ee967fe..0000000000000 --- a/packages/turbo-codemod/__tests__/get-turbo-upgrade-command.test.ts +++ /dev/null @@ -1,662 +0,0 @@ -import * as turboWorkspaces from "@turbo/workspaces"; -import * as turboUtils from "@turbo/utils"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { getTurboUpgradeCommand } from "../src/commands/migrate/steps/getTurboUpgradeCommand"; -import * as utils from "../src/commands/migrate/utils"; -import { getWorkspaceDetailsMockReturnValue } from "./test-utils"; - -jest.mock("@turbo/workspaces", () => ({ - __esModule: true, - ...jest.requireActual("@turbo/workspaces"), -})); - -interface TestCase { - version: string; - packageManager: turboUtils.PackageManager; - packageManagerVersion: string; - fixture: string; - expected: string; -} - -const LOCAL_INSTALL_COMMANDS: Array = [ - // npm - workspaces - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "normal-workspaces-dev-install", - expected: "npm install turbo@latest --save-dev", - }, - { - version: "1.6.3", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "normal-workspaces-dev-install", - expected: "npm install turbo@1.6.3 --save-dev", - }, - { - version: "canary", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "normal-workspaces-dev-install", - expected: "npm install turbo@canary --save-dev", - }, - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "normal-workspaces", - expected: "npm install turbo@latest", - }, - // npm - single package - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "single-package-dev-install", - expected: "npm install turbo@latest --save-dev", - }, - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "single-package", - expected: "npm install turbo@latest", - }, - // pnpm - workspaces - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "pnpm-workspaces-dev-install", - expected: "pnpm add turbo@latest --save-dev -w", - }, - { - version: "1.6.3", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "pnpm-workspaces-dev-install", - expected: "pnpm add turbo@1.6.3 --save-dev -w", - }, - { - version: "canary", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "pnpm-workspaces-dev-install", - expected: "pnpm add turbo@canary --save-dev -w", - }, - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "pnpm-workspaces", - expected: "pnpm add turbo@latest -w", - }, - // pnpm - single package - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "single-package-dev-install", - expected: "pnpm add turbo@latest --save-dev", - }, - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "single-package", - expected: "pnpm add turbo@latest", - }, - // yarn 1.x - workspaces - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@latest --dev -W", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "normal-workspaces", - expected: "yarn add turbo@latest -W", - }, - { - version: "1.6.3", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@1.6.3 --dev -W", - }, - { - version: "canary", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@canary --dev -W", - }, - // yarn 1.x - single package - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "single-package-dev-install", - expected: "yarn add turbo@latest --dev", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "single-package", - expected: "yarn add turbo@latest", - }, - // yarn 2.x - workspaces - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@latest --dev", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "normal-workspaces", - expected: "yarn add turbo@latest", - }, - { - version: "1.6.3", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@1.6.3 --dev", - }, - { - version: "canary", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@canary --dev", - }, - // yarn 2.x - single package - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "single-package-dev-install", - expected: "yarn add turbo@latest --dev", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "single-package", - expected: "yarn add turbo@latest", - }, - // yarn 3.x - workspaces - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@latest --dev", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "normal-workspaces", - expected: "yarn add turbo@latest", - }, - { - version: "1.6.3", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@1.6.3 --dev", - }, - { - version: "canary", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn add turbo@canary --dev", - }, - // yarn 3.x - single package - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "single-package-dev-install", - expected: "yarn add turbo@latest --dev", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "single-package", - expected: "yarn add turbo@latest", - }, -]; - -const GLOBAL_INSTALL_COMMANDS: Array = [ - // npm - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "normal-workspaces-dev-install", - expected: "npm install turbo@latest --global", - }, - { - version: "1.6.3", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "normal-workspaces-dev-install", - expected: "npm install turbo@1.6.3 --global", - }, - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "normal-workspaces", - expected: "npm install turbo@latest --global", - }, - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "single-package", - expected: "npm install turbo@latest --global", - }, - { - version: "latest", - packageManager: "npm", - packageManagerVersion: "7.0.0", - fixture: "single-package-dev-install", - expected: "npm install turbo@latest --global", - }, - // pnpm - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "pnpm-workspaces-dev-install", - expected: "pnpm add turbo@latest --global", - }, - { - version: "1.6.3", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "pnpm-workspaces-dev-install", - expected: "pnpm add turbo@1.6.3 --global", - }, - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "pnpm-workspaces", - expected: "pnpm add turbo@latest --global", - }, - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "single-package", - expected: "pnpm add turbo@latest --global", - }, - { - version: "latest", - packageManager: "pnpm", - packageManagerVersion: "7.0.0", - fixture: "single-package-dev-install", - expected: "pnpm add turbo@latest --global", - }, - // yarn 1.x - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "normal-workspaces-dev-install", - expected: "yarn global add turbo@latest", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "normal-workspaces", - expected: "yarn global add turbo@latest", - }, - { - version: "1.6.3", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "normal-workspaces-dev-install", - expected: "yarn global add turbo@1.6.3", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "single-package", - expected: "yarn global add turbo@latest", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "1.22.19", - fixture: "single-package-dev-install", - expected: "yarn global add turbo@latest", - }, - // yarn 2.x - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn global add turbo@latest", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "normal-workspaces", - expected: "yarn global add turbo@latest", - }, - { - version: "1.6.3", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "normal-workspaces-dev-install", - expected: "yarn global add turbo@1.6.3", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "single-package", - expected: "yarn global add turbo@latest", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "2.3.4", - fixture: "single-package-dev-install", - expected: "yarn global add turbo@latest", - }, - // yarn 3.x - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.3", - fixture: "normal-workspaces-dev-install", - expected: "yarn global add turbo@latest", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.3", - fixture: "normal-workspaces", - expected: "yarn global add turbo@latest", - }, - { - version: "1.6.3", - packageManager: "yarn", - packageManagerVersion: "3.3.3", - fixture: "normal-workspaces-dev-install", - expected: "yarn global add turbo@1.6.3", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "single-package", - expected: "yarn global add turbo@latest", - }, - { - version: "latest", - packageManager: "yarn", - packageManagerVersion: "3.3.4", - fixture: "single-package-dev-install", - expected: "yarn global add turbo@latest", - }, -]; - -describe("get-turbo-upgrade-command", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "get-turbo-upgrade-command", - }); - - it.each(LOCAL_INSTALL_COMMANDS)( - "returns correct upgrade command for local install of turbo@$version using $packageManager@$packageManagerVersion (fixture: $fixture)", - async ({ - version, - packageManager, - packageManagerVersion, - fixture, - expected, - }) => { - const { root } = useFixture({ - fixture, - }); - - const mockedExec = jest - .spyOn(utils, "exec") - .mockImplementation((command: string) => { - // fail the check for global turbo - if (command.includes("bin")) { - return undefined; - } - }); - const mockGetPackageManagersBinPaths = jest - .spyOn(turboUtils, "getPackageManagersBinPaths") - .mockResolvedValue({ - pnpm: undefined, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManager === "pnpm" ? packageManagerVersion : undefined, - npm: packageManager === "npm" ? packageManagerVersion : undefined, - yarn: packageManager === "yarn" ? packageManagerVersion : undefined, - bun: packageManager === "bun" ? packageManagerVersion : undefined, - }); - - const project = getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - singlePackage: fixture.includes("single-package"), - }); - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue(project); - - // get the command - const upgradeCommand = await getTurboUpgradeCommand({ - project, - to: version === "latest" ? undefined : version, - }); - - expect(upgradeCommand).toEqual(expected); - - mockedExec.mockRestore(); - mockGetPackageManagersBinPaths.mockRestore(); - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - } - ); - - it.each(GLOBAL_INSTALL_COMMANDS)( - "returns correct upgrade command for global install of turbo@$version using $packageManager@$packageManagerVersion (fixture: $fixture)", - async ({ - version, - packageManager, - packageManagerVersion, - fixture, - expected, - }) => { - const { root } = useFixture({ - fixture, - }); - - const mockedExec = jest - .spyOn(utils, "exec") - .mockImplementation((command: string) => { - if (command === "turbo bin") { - return `/global/${packageManager}/bin/turbo`; - } - return undefined; - }); - const mockGetPackageManagersBinPaths = jest - .spyOn(turboUtils, "getPackageManagersBinPaths") - .mockResolvedValue({ - pnpm: `/global/pnpm/bin`, - npm: `/global/npm/bin`, - yarn: `/global/yarn/bin`, - bun: `/global/bun/bin`, - }); - - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManager === "pnpm" ? packageManagerVersion : undefined, - npm: packageManager === "npm" ? packageManagerVersion : undefined, - yarn: packageManager === "yarn" ? packageManagerVersion : undefined, - bun: packageManager === "bun" ? packageManagerVersion : undefined, - }); - - const project = getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }); - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue(project); - - // get the command - const upgradeCommand = await getTurboUpgradeCommand({ - project, - to: version === "latest" ? undefined : version, - }); - - expect(upgradeCommand).toEqual(expected); - - mockedExec.mockRestore(); - mockGetPackageManagersBinPaths.mockRestore(); - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - } - ); - - describe("errors", () => { - it("fails gracefully if no package.json exists", async () => { - const { root } = useFixture({ - fixture: "no-package", - }); - - const mockedExec = jest - .spyOn(utils, "exec") - .mockImplementation((command: string) => { - // fail the check for the turbo to force local - if (command.includes("bin")) { - return undefined; - } - }); - - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: "8.0.0", - npm: undefined, - yarn: undefined, - bun: undefined, - }); - - const project = getWorkspaceDetailsMockReturnValue({ - root, - packageManager: "pnpm", - }); - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue(project); - - // get the command - const upgradeCommand = await getTurboUpgradeCommand({ - project, - }); - - expect(upgradeCommand).toEqual(undefined); - - mockedExec.mockRestore(); - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - }, 10000); - - it.each([ - { - fixture: "no-package", - name: "fails gracefully if no package.json exists", - }, - { - fixture: "no-turbo", - name: "fails gracefully if turbo cannot be found in package.json", - }, - { - fixture: "no-deps", - name: "fails gracefully if package.json has no deps or devDeps", - }, - ])( - "$name", - async ({ fixture }) => { - const { root } = useFixture({ - fixture, - }); - - const mockedExec = jest - .spyOn(utils, "exec") - .mockImplementation((command: string) => { - // fail the check for the turbo to force local - if (command.includes("bin")) { - return undefined; - } - }); - - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: "8.0.0", - npm: undefined, - yarn: undefined, - bun: undefined, - }); - - const project = getWorkspaceDetailsMockReturnValue({ - root, - packageManager: "pnpm", - }); - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue(project); - - // get the command - const upgradeCommand = await getTurboUpgradeCommand({ - project, - }); - - expect(upgradeCommand).toEqual(undefined); - - mockedExec.mockRestore(); - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - }, - 10000 - ); - }); -}); diff --git a/packages/turbo-codemod/__tests__/migrate-dot-env.test.ts b/packages/turbo-codemod/__tests__/migrate-dot-env.test.ts deleted file mode 100644 index 9f4ec2c8a7843..0000000000000 --- a/packages/turbo-codemod/__tests__/migrate-dot-env.test.ts +++ /dev/null @@ -1,314 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { type Schema } from "@turbo/types"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/migrate-dot-env"; - -describe("migrate-dot-env", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "migrate-dot-env", - }); - it("migrates turbo.json dot-env - basic", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "with-dot-env", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: [".env"], - tasks: { - "build-one": { - inputs: ["$TURBO_DEFAULT$", "build-one/.env"], - }, - "build-two": { - inputs: ["build-two/main.js", "build-two/.env"], - }, - "build-three": {}, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 3, - "deletions": 3, - }, - } - `); - }); - - it("migrates turbo.json dot-env - workspace configs", () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "workspace-configs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(readJson("turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - "build-one": { - inputs: ["$TURBO_DEFAULT$", "build-one/.env"], - }, - "build-two": { - inputs: ["build-two/**/*.ts", "build-two/.env"], - }, - "build-three": {}, - }, - }); - - expect(readJson("apps/docs/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - tasks: { - build: {}, - }, - }); - - expect(readJson("apps/web/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - tasks: { - build: { - inputs: ["src/**/*.ts", ".env"], - }, - }, - }); - - expect(readJson("packages/ui/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - tasks: { - "build-three": { - inputs: ["$TURBO_DEFAULT$", ".env"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "apps/docs/turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - "apps/web/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - "packages/ui/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates turbo.json dot-env - dry", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "with-dot-env", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as Schema; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 3, - "deletions": 3, - }, - } - `); - }); - - it("migrates turbo.json dot-env - print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "with-dot-env", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: true }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: [".env"], - tasks: { - "build-one": { - inputs: ["$TURBO_DEFAULT$", "build-one/.env"], - }, - "build-three": {}, - "build-two": { - inputs: ["build-two/main.js", "build-two/.env"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 3, - "deletions": 3, - }, - } - `); - }); - - it("migrates turbo.json dot-env - dry & print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "with-dot-env", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as Schema; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 3, - "deletions": 3, - }, - } - `); - }); - - it("migrates turbo.json dot-env - config with no pipeline", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-pipeline", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - tasks: {}, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates turbo.json dot-env - config with no dot env", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-dot-env", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - "build-one": { - dependsOn: ["build-two"], - }, - "build-two": { - cache: false, - }, - "build-three": { - persistent: true, - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); -}); diff --git a/packages/turbo-codemod/__tests__/migrate-env-var-dependencies.test.ts b/packages/turbo-codemod/__tests__/migrate-env-var-dependencies.test.ts deleted file mode 100644 index d15031ef7b300..0000000000000 --- a/packages/turbo-codemod/__tests__/migrate-env-var-dependencies.test.ts +++ /dev/null @@ -1,761 +0,0 @@ -import merge from "deepmerge"; -import type { SchemaV1, SchemaV2 } from "@turbo/types"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { - hasLegacyEnvVarDependencies, - migratePipeline, - migrateConfig, - transformer, -} from "../src/transforms/migrate-env-var-dependencies"; - -const getTestTurboConfig = ( - override: SchemaV1 = { pipeline: {} } -): SchemaV1 => { - const config = { - $schema: "./docs/public/schema.json", - globalDependencies: ["$GLOBAL_ENV_KEY"], - pipeline: { - test: { - outputs: ["coverage/**/*"], - dependsOn: ["^build"], - }, - lint: { - outputs: [], - }, - dev: { - cache: false, - }, - build: { - outputs: ["dist/**/*", ".next/**/*", "!.next/cache/**"], - dependsOn: ["^build", "$TASK_ENV_KEY", "$ANOTHER_ENV_KEY"], - }, - }, - }; - - return merge(config, override, { - arrayMerge: (_: unknown, sourceArray: Array) => sourceArray, - }); -}; - -describe("migrate-env-var-dependencies", () => { - describe("hasLegacyEnvVarDependencies - utility", () => { - it("finds env keys in legacy turbo.json - has keys", () => { - const config = getTestTurboConfig(); - const { hasKeys, envVars } = hasLegacyEnvVarDependencies(config); - expect(hasKeys).toEqual(true); - expect(envVars).toMatchInlineSnapshot(` - [ - "$GLOBAL_ENV_KEY", - "$TASK_ENV_KEY", - "$ANOTHER_ENV_KEY", - ] - `); - }); - - it("finds env keys in legacy turbo.json - multiple pipeline keys", () => { - const config = getTestTurboConfig({ - pipeline: { test: { dependsOn: ["$MY_ENV"] } }, - }); - const { hasKeys, envVars } = hasLegacyEnvVarDependencies(config); - expect(hasKeys).toEqual(true); - expect(envVars).toMatchInlineSnapshot(` - [ - "$GLOBAL_ENV_KEY", - "$MY_ENV", - "$TASK_ENV_KEY", - "$ANOTHER_ENV_KEY", - ] - `); - }); - - it("finds env keys in legacy turbo.json - no keys", () => { - // override to exclude keys - const config = getTestTurboConfig({ - globalDependencies: [], - pipeline: { build: { dependsOn: [] } }, - }); - const { hasKeys, envVars } = hasLegacyEnvVarDependencies(config); - expect(hasKeys).toEqual(false); - expect(envVars).toMatchInlineSnapshot(`[]`); - }); - - it("finds env keys in turbo.json - no global", () => { - const { hasKeys, envVars } = hasLegacyEnvVarDependencies({ - pipeline: { build: { dependsOn: ["$cool"] } }, - }); - expect(hasKeys).toEqual(true); - expect(envVars).toMatchInlineSnapshot(` - [ - "$cool", - ] - `); - }); - }); - - describe("migratePipeline - utility", () => { - it("migrates pipeline with env var dependencies", () => { - const config = getTestTurboConfig(); - const { build } = config.pipeline; - const pipeline = migratePipeline(build); - expect(pipeline).toHaveProperty("env"); - expect(pipeline.env).toMatchInlineSnapshot(` - [ - "TASK_ENV_KEY", - "ANOTHER_ENV_KEY", - ] - `); - expect(pipeline.dependsOn).toMatchInlineSnapshot(` - [ - "^build", - ] - `); - }); - - it("migrates pipeline with no env var dependencies", () => { - const config = getTestTurboConfig(); - const { test } = config.pipeline; - const pipeline = migratePipeline(test); - expect(pipeline.env).toBeUndefined(); - expect(pipeline.dependsOn).toMatchInlineSnapshot(` - [ - "^build", - ] - `); - }); - - it("migrates pipeline with existing env key", () => { - const config = getTestTurboConfig({ - pipeline: { test: { env: ["$MY_ENV"], dependsOn: ["^build"] } }, - }); - const { test } = config.pipeline; - const pipeline = migratePipeline(test); - expect(pipeline).toHaveProperty("env"); - expect(pipeline.env).toMatchInlineSnapshot(` - [ - "$MY_ENV", - ] - `); - expect(pipeline.dependsOn).toMatchInlineSnapshot(` - [ - "^build", - ] - `); - }); - - it("migrates pipeline with incomplete env key", () => { - const config = getTestTurboConfig({ - pipeline: { - test: { env: ["$MY_ENV"], dependsOn: ["^build", "$SUPER_COOL"] }, - }, - }); - const { test } = config.pipeline; - const pipeline = migratePipeline(test); - expect(pipeline).toHaveProperty("env"); - expect(pipeline.env).toMatchInlineSnapshot(` - [ - "$MY_ENV", - "SUPER_COOL", - ] - `); - expect(pipeline.dependsOn).toMatchInlineSnapshot(` - [ - "^build", - ] - `); - }); - - it("migrates pipeline with duplicate env keys", () => { - const config = getTestTurboConfig({ - pipeline: { - test: { env: ["$MY_ENV"], dependsOn: ["^build", "$MY_ENV"] }, - }, - }); - const { test } = config.pipeline; - const pipeline = migratePipeline(test); - expect(pipeline).toHaveProperty("env"); - expect(pipeline.env).toMatchInlineSnapshot(` - [ - "$MY_ENV", - "MY_ENV", - ] - `); - expect(pipeline.dependsOn).toMatchInlineSnapshot(` - [ - "^build", - ] - `); - }); - }); - - describe("migrateConfig - utility", () => { - it("migrates config with env var dependencies", () => { - const config = getTestTurboConfig(); - const pipeline = migrateConfig(config); - expect(pipeline).toMatchInlineSnapshot(` - { - "$schema": "./docs/public/schema.json", - "globalEnv": [ - "GLOBAL_ENV_KEY", - ], - "pipeline": { - "build": { - "dependsOn": [ - "^build", - ], - "env": [ - "TASK_ENV_KEY", - "ANOTHER_ENV_KEY", - ], - "outputs": [ - "dist/**/*", - ".next/**/*", - "!.next/cache/**", - ], - }, - "dev": { - "cache": false, - }, - "lint": { - "outputs": [], - }, - "test": { - "dependsOn": [ - "^build", - ], - "outputs": [ - "coverage/**/*", - ], - }, - }, - } - `); - }); - - it("migrates config with no env var dependencies", () => { - const config = getTestTurboConfig({ - globalDependencies: [], - pipeline: { - build: { dependsOn: ["^build"] }, - }, - }); - const pipeline = migrateConfig(config); - expect(pipeline).toMatchInlineSnapshot(` - { - "$schema": "./docs/public/schema.json", - "pipeline": { - "build": { - "dependsOn": [ - "^build", - ], - "outputs": [ - "dist/**/*", - ".next/**/*", - "!.next/cache/**", - ], - }, - "dev": { - "cache": false, - }, - "lint": { - "outputs": [], - }, - "test": { - "dependsOn": [ - "^build", - ], - "outputs": [ - "coverage/**/*", - ], - }, - }, - } - `); - }); - - it("migrates config with inconsistent config", () => { - const config = getTestTurboConfig({ - pipeline: { - test: { env: ["$MY_ENV"], dependsOn: ["^build", "$SUPER_COOL"] }, - }, - }); - const pipeline = migrateConfig(config); - expect(pipeline).toMatchInlineSnapshot(` - { - "$schema": "./docs/public/schema.json", - "globalEnv": [ - "GLOBAL_ENV_KEY", - ], - "pipeline": { - "build": { - "dependsOn": [ - "^build", - ], - "env": [ - "TASK_ENV_KEY", - "ANOTHER_ENV_KEY", - ], - "outputs": [ - "dist/**/*", - ".next/**/*", - "!.next/cache/**", - ], - }, - "dev": { - "cache": false, - }, - "lint": { - "outputs": [], - }, - "test": { - "dependsOn": [ - "^build", - ], - "env": [ - "$MY_ENV", - "SUPER_COOL", - ], - "outputs": [ - "coverage/**/*", - ], - }, - }, - } - `); - }); - - it("migrates config with duplicate env keys", () => { - const config = getTestTurboConfig({ - pipeline: { - test: { env: ["$MY_ENV"], dependsOn: ["^build", "$MY_ENV"] }, - }, - }); - const pipeline = migrateConfig(config); - expect(pipeline).toMatchInlineSnapshot(` - { - "$schema": "./docs/public/schema.json", - "globalEnv": [ - "GLOBAL_ENV_KEY", - ], - "pipeline": { - "build": { - "dependsOn": [ - "^build", - ], - "env": [ - "TASK_ENV_KEY", - "ANOTHER_ENV_KEY", - ], - "outputs": [ - "dist/**/*", - ".next/**/*", - "!.next/cache/**", - ], - }, - "dev": { - "cache": false, - }, - "lint": { - "outputs": [], - }, - "test": { - "dependsOn": [ - "^build", - ], - "env": [ - "$MY_ENV", - "MY_ENV", - ], - "outputs": [ - "coverage/**/*", - ], - }, - }, - } - `); - }); - }); - - describe("transform", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "migrate-env-var-dependencies", - }); - - it("migrates turbo.json env var dependencies - basic", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "env-dependencies", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: [".env"], - globalEnv: ["NEXT_PUBLIC_API_KEY", "STRIPE_API_KEY"], - pipeline: { - build: { - dependsOn: ["^build"], - env: ["PROD_API_KEY"], - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: { - dependsOn: [], - env: ["IS_CI"], - outputs: [], - }, - test: { - dependsOn: ["test"], - env: ["IS_CI"], - outputs: [], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 4, - "deletions": 4, - }, - } - `); - }); - - it("migrates turbo.json env var dependencies - workspace configs", () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "workspace-configs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(readJson("turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: [".env"], - globalEnv: ["NEXT_PUBLIC_API_KEY", "STRIPE_API_KEY"], - pipeline: { - build: { - dependsOn: ["^build"], - env: ["PROD_API_KEY"], - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: { - dependsOn: [], - env: ["IS_TEST"], - outputs: [], - }, - test: { - dependsOn: ["test"], - env: ["IS_CI"], - outputs: [], - }, - }, - }); - - expect(readJson("apps/web/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - build: { - // old - dependsOn: ["build"], - // new - env: ["ENV_1", "ENV_2"], - }, - }, - }); - - expect(readJson("packages/ui/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - build: { - dependsOn: [], - env: ["IS_SERVER"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "apps/web/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - "packages/ui/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 4, - "deletions": 4, - }, - } - `); - }); - - it("migrates turbo.json env var dependencies - repeat run", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "env-dependencies", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: [".env"], - globalEnv: ["NEXT_PUBLIC_API_KEY", "STRIPE_API_KEY"], - pipeline: { - build: { - dependsOn: ["^build"], - env: ["PROD_API_KEY"], - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: { - dependsOn: [], - env: ["IS_CI"], - outputs: [], - }, - test: { - dependsOn: ["test"], - env: ["IS_CI"], - outputs: [], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 4, - "deletions": 4, - }, - } - `); - - // run the transformer - const repeatResult = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(repeatResult.fatalError).toBeUndefined(); - expect(repeatResult.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates turbo.json env var dependencies - dry", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "env-dependencies", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as SchemaV2; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 4, - "deletions": 4, - }, - } - `); - }); - - it("migrates turbo.json env var dependencies - print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "env-dependencies", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: true }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalEnv: ["NEXT_PUBLIC_API_KEY", "STRIPE_API_KEY"], - globalDependencies: [".env"], - pipeline: { - build: { - dependsOn: ["^build"], - env: ["PROD_API_KEY"], - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: { - dependsOn: [], - env: ["IS_CI"], - outputs: [], - }, - test: { - dependsOn: ["test"], - env: ["IS_CI"], - outputs: [], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 4, - "deletions": 4, - }, - } - `); - }); - - it("migrates turbo.json env var dependencies - dry & print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "env-dependencies", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as SchemaV2; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: true }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 4, - "deletions": 4, - }, - } - `); - }); - - it("does not change turbo.json if already migrated", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "migrated-env-dependencies", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as SchemaV2; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); - - it("errors if package.json config exists and has not been migrated", () => { - // load the fixture for the test - const { root } = useFixture({ - fixture: "old-config", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - 'turbo" key detected in package.json. Run `npx @turbo/codemod transform create-turbo-config` first' - ); - }); - }); -}); diff --git a/packages/turbo-codemod/__tests__/migrate.test.ts b/packages/turbo-codemod/__tests__/migrate.test.ts deleted file mode 100644 index 23b7acdd88c51..0000000000000 --- a/packages/turbo-codemod/__tests__/migrate.test.ts +++ /dev/null @@ -1,1018 +0,0 @@ -import childProcess from "node:child_process"; -import * as turboUtils from "@turbo/utils"; -import * as turboWorkspaces from "@turbo/workspaces"; -import { setupTestFixtures, spyExit } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { migrate } from "../src/commands/migrate"; -import * as checkGitStatus from "../src/utils/checkGitStatus"; -import * as getCurrentVersion from "../src/commands/migrate/steps/getCurrentVersion"; -import * as getLatestVersion from "../src/commands/migrate/steps/getLatestVersion"; -import * as getTurboUpgradeCommand from "../src/commands/migrate/steps/getTurboUpgradeCommand"; -import { getWorkspaceDetailsMockReturnValue } from "./test-utils"; - -jest.mock("@turbo/workspaces", () => ({ - __esModule: true, - ...jest.requireActual("@turbo/workspaces"), -})); - -describe("migrate", () => { - const mockExit = spyExit(); - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "migrate", - }); - - it("migrates from 1.0.0 to 1.7.0", async () => { - const { root, readJson } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.0.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.7.0"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue("pnpm install -g turbo@latest"); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.0.0", - }, - name: "no-turbo-json", - packageManager: "pnpm@1.2.3", - version: "1.0.0", - }); - expect(readJson("turbo.json")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - build: { - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: {}, - test: { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("migrates from 1.0.0 to 1.2.0 (dry run)", async () => { - const { root, readJson } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.0.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.2.0"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue("pnpm install -g turbo@latest"); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - const packageJson = readJson("package.json"); - const turboJson = readJson("turbo.json"); - - await migrate(root, { - force: false, - dryRun: true, - print: false, - install: true, - }); - - // make sure nothing changed - expect(readJson("package.json")).toStrictEqual(packageJson); - expect(readJson("turbo.json")).toStrictEqual(turboJson); - - // verify mocks were called - expect(mockedCheckGitStatus).not.toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("next version can be passed as an option", async () => { - const { root, readJson } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.0.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.7.0"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue("pnpm install -g turbo@latest"); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - to: "1.7.0", - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.0.0", - }, - name: "no-turbo-json", - packageManager: "pnpm@1.2.3", - version: "1.0.0", - }); - expect(readJson("turbo.json")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - build: { - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - test: { - outputs: ["dist/**", "build/**"], - }, - lint: {}, - }, - }); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("current version can be passed as an option", async () => { - const { root, readJson } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.7.0"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue("pnpm install -g turbo@latest"); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - from: "1.0.0", - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.0.0", - }, - name: "no-turbo-json", - packageManager: "pnpm@1.2.3", - version: "1.0.0", - }); - expect(readJson("turbo.json")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - build: { - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: {}, - test: { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("exits if the current version is the same as the new version", async () => { - const { root } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.7.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.7.0"); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(0); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("continues when migration doesn't require codemods", async () => { - const { root } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "npm"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.3.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.3.1"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue("npm install turbo@1.3.1"); - const mockedExecSync = jest - .spyOn(childProcess, "execSync") - .mockReturnValue("installed"); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: true, - }); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - expect(mockedExecSync).toHaveBeenNthCalledWith(1, "turbo bin", { - cwd: root, - stdio: "ignore", - }); - expect(mockedExecSync).toHaveBeenNthCalledWith(2, "turbo daemon stop", { - cwd: root, - stdio: "ignore", - }); - expect(mockedExecSync).toHaveBeenNthCalledWith( - 3, - "npm install turbo@1.3.1", - { - cwd: root, - stdio: "pipe", - } - ); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - mockedExecSync.mockRestore(); - }); - - it("installs the correct turbo version", async () => { - const { root, readJson } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.0.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.7.0"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue("pnpm install -g turbo@1.7.0"); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - const mockedExecSync = jest - .spyOn(childProcess, "execSync") - .mockReturnValue("installed"); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: true, - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.0.0", - }, - name: "no-turbo-json", - packageManager: "pnpm@1.2.3", - version: "1.0.0", - }); - expect(readJson("turbo.json")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - build: { - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: {}, - test: { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - expect(mockedExecSync).toHaveBeenCalled(); - expect(mockedExecSync).toHaveBeenNthCalledWith(1, "turbo bin", { - cwd: root, - stdio: "ignore", - }); - expect(mockedExecSync).toHaveBeenNthCalledWith(2, "turbo daemon stop", { - cwd: root, - stdio: "ignore", - }); - expect(mockedExecSync).toHaveBeenNthCalledWith( - 3, - "pnpm install -g turbo@1.7.0", - { - cwd: root, - stdio: "pipe", - } - ); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - mockedExecSync.mockRestore(); - }); - - it("fails gracefully when the correct upgrade command cannot be found", async () => { - const { root, readJson } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.0.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.7.0"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue(undefined); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - const mockedExecSync = jest - .spyOn(childProcess, "execSync") - .mockReturnValue("installed"); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: true, - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.0.0", - }, - name: "no-turbo-json", - packageManager: "pnpm@1.2.3", - version: "1.0.0", - }); - expect(readJson("turbo.json")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - build: { - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: {}, - test: { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - expect(mockedExecSync).toHaveBeenCalledTimes(2); - expect(mockedExecSync).toHaveBeenNthCalledWith(1, "turbo bin", { - cwd: root, - stdio: "ignore", - }); - expect(mockedExecSync).toHaveBeenNthCalledWith(2, "turbo daemon stop", { - cwd: root, - stdio: "ignore", - }); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - mockedExecSync.mockRestore(); - }); - - it("exits if current version is not passed and cannot be inferred", async () => { - const { root } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue(undefined); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("exits if latest version is not passed and cannot be inferred", async () => { - const { root } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "npm"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.5.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue(undefined); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("exits if latest version throws", async () => { - const { root } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "yarn"; - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.5.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockRejectedValue(new Error("failed to fetch version")); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("exits if any transforms encounter an error", async () => { - const { root } = useFixture({ - fixture: "old-turbo", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.0.0"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("1.7.0"); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: true, - print: false, - install: true, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - - // verify mocks were called - expect(mockedCheckGitStatus).not.toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }); - - it("exits if invalid directory is passed", async () => { - useFixture({ - fixture: "old-turbo", - }); - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - - await migrate("~/path/that/does/not/exist", { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - }); - - it("exits if directory with no repo is passed", async () => { - const { root } = useFixture({ - fixture: "no-repo", - }); - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - }); - - it("migrates across majors with all required codemods", async () => { - const { root, readJson } = useFixture({ - fixture: "turbo-1", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockedGetCurrentVersion = jest - .spyOn(getCurrentVersion, "getCurrentVersion") - .mockReturnValue("1.99.99"); - const mockedGetLatestVersion = jest - .spyOn(getLatestVersion, "getLatestVersion") - .mockResolvedValue("2.0.0"); - const mockedGetTurboUpgradeCommand = jest - .spyOn(getTurboUpgradeCommand, "getTurboUpgradeCommand") - .mockResolvedValue("pnpm install -g turbo@latest"); - const mockedGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - const mockedGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await migrate(root, { - force: false, - dryRun: false, - print: false, - install: false, - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.7.1", - }, - name: "turbo-1", - packageManager: "pnpm@1.2.3", - version: "1.0.0", - }); - expect(readJson("turbo.json")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - build: { - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: { - inputs: ["$TURBO_DEFAULT$", ".env.local"], - outputs: [], - }, - test: { - outputLogs: "errors-only", - }, - }, - }); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockedGetCurrentVersion).toHaveBeenCalled(); - expect(mockedGetLatestVersion).toHaveBeenCalled(); - expect(mockedGetTurboUpgradeCommand).toHaveBeenCalled(); - expect(mockedGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockedGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockedGetCurrentVersion.mockRestore(); - mockedGetLatestVersion.mockRestore(); - mockedGetTurboUpgradeCommand.mockRestore(); - mockedGetAvailablePackageManagers.mockRestore(); - mockedGetWorkspaceDetails.mockRestore(); - }, 10000); -}); diff --git a/packages/turbo-codemod/__tests__/rename-output-mode.test.ts b/packages/turbo-codemod/__tests__/rename-output-mode.test.ts deleted file mode 100644 index d54a597b495da..0000000000000 --- a/packages/turbo-codemod/__tests__/rename-output-mode.test.ts +++ /dev/null @@ -1,391 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { type Schema } from "@turbo/types"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/rename-output-mode"; - -describe("rename-output-mode", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "rename-output-mode", - }); - it("migrates turbo.json outputs - basic", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-output-mode", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputLogs: "hash-only", - }, - "build-two": { - outputLogs: "full", - }, - "build-three": {}, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates turbo.json outputs - workspace configs", () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "workspace-configs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(readJson("turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputLogs: "new-only", - }, - "build-two": { - outputLogs: "none", - }, - "build-three": {}, - }, - }); - - expect(readJson("apps/docs/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - build: {}, - }, - }); - - expect(readJson("apps/web/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - build: { - outputLogs: "none", - }, - }, - }); - - expect(readJson("packages/ui/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - "build-three": { - outputLogs: "new-only", - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "apps/docs/turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - "apps/web/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - "packages/ui/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates turbo.json outputs - dry", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-output-mode", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as Schema; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates turbo.json outputs - print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-output-mode", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: true }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputLogs: "hash-only", - }, - "build-three": {}, - "build-two": { - outputLogs: "full", - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates turbo.json outputs - dry & print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-output-mode", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as Schema; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates turbo.json outputs - invalid", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "invalid-output-mode", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputLogs: "errors-only", - }, - "build-two": { - outputLogs: [], - }, - "build-three": {}, - "garbage-in-numeric-0": { - outputLogs: 0, - }, - "garbage-in-numeric": { - outputLogs: 42, - }, - "garbage-in-string": { - outputLogs: "string", - }, - "garbage-in-empty-string": { - outputLogs: "", - }, - "garbage-in-null": { - outputLogs: null, - }, - "garbage-in-false": { - outputLogs: false, - }, - "garbage-in-true": { - outputLogs: true, - }, - "garbage-in-object": { - outputLogs: {}, - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 10, - "deletions": 10, - }, - } - `); - }); - - it("migrates turbo.json outputs - config with no pipeline", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-pipeline", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - pipeline: {}, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates turbo.json outputs - config with no output mode", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-output-mode", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - dependsOn: ["build-two"], - }, - "build-two": { - cache: false, - }, - "build-three": { - persistent: true, - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); - - it("errors if package.json config exists and has not been migrated", () => { - // load the fixture for the test - const { root } = useFixture({ - fixture: "old-config", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - 'turbo" key detected in package.json. Run `npx @turbo/codemod transform create-turbo-config` first' - ); - }); -}); diff --git a/packages/turbo-codemod/__tests__/rename-pipeline.ts b/packages/turbo-codemod/__tests__/rename-pipeline.ts deleted file mode 100644 index 38c197bcf5ff1..0000000000000 --- a/packages/turbo-codemod/__tests__/rename-pipeline.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/rename-pipeline"; - -describe("rename-pipeline", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "rename-pipeline", - }); - - it("migrates turbo.json pipeline - root config only", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "root-only", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: ["important.txt"], - tasks: { - build: { - outputs: ["dist"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - } - `); - }); - - it("migrates turbo.json pipeline - workspace configs", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "workspace-configs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - build: { - dependsOn: ["^build"], - outputs: [".next/**", "!.next/cache/**"], - }, - dev: { - cache: false, - }, - lint: { - outputs: [], - }, - test: { - outputs: [], - }, - }, - }); - - expect(JSON.parse(read("apps/web/turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - tasks: { - build: { - dependsOn: [], - }, - }, - }); - - expect(JSON.parse(read("packages/ui/turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - tasks: { - test: { - dependsOn: ["build"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "apps/docs/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "apps/web/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "packages/ui/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); - - it("does not do anything if there is already a top level tasks key", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "with-tasks", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - build: { - outputs: ["dist"], - }, - }, - }); - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toStrictEqual({}); - }); -}); diff --git a/packages/turbo-codemod/__tests__/set-default-outputs.test.ts b/packages/turbo-codemod/__tests__/set-default-outputs.test.ts deleted file mode 100644 index 60460ec21ea1a..0000000000000 --- a/packages/turbo-codemod/__tests__/set-default-outputs.test.ts +++ /dev/null @@ -1,393 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { type Schema } from "@turbo/types"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/set-default-outputs"; - -describe("set-default-outputs", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "set-default-outputs", - }); - it("migrates turbo.json outputs - basic", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-outputs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputs: ["foo"], - }, - "build-two": {}, - "build-three": { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 1, - }, - } - `); - }); - - it("migrates turbo.json outputs - workspace configs", () => { - // load the fixture for the test - const { root, readJson } = useFixture({ - fixture: "workspace-configs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(readJson("turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputs: ["foo"], - }, - "build-two": {}, - "build-three": { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - expect(readJson("apps/docs/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - build: { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - expect(readJson("apps/web/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - build: {}, - }, - }); - - expect(readJson("packages/ui/turbo.json") || "{}").toStrictEqual({ - $schema: "https://turbo.build/schema.json", - extends: ["//"], - pipeline: { - "build-three": { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "apps/docs/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "apps/web/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 0, - }, - "packages/ui/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 1, - }, - } - `); - }); - - it("migrates turbo.json outputs - dry", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-outputs", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as Schema; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 2, - "deletions": 1, - }, - } - `); - }); - - it("migrates turbo.json outputs - print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-outputs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: true }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputs: ["foo"], - }, - "build-two": {}, - "build-three": { - outputs: ["dist/**", "build/**"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 1, - }, - } - `); - }); - - it("migrates turbo.json outputs - dry & print", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "old-outputs", - }); - - const turboJson = JSON.parse(read("turbo.json") || "{}") as Schema; - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: true, print: false }, - }); - - // make sure it didn't change - expect(JSON.parse(read("turbo.json") || "{}")).toEqual(turboJson); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "skipped", - "additions": 2, - "deletions": 1, - }, - } - `); - }); - - it("migrates turbo.json outputs - invalid", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "invalid-outputs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - outputs: ["foo"], - }, - "build-two": {}, - "build-three": { - outputs: ["dist/**", "build/**"], - }, - "garbage-in-numeric-0": { - outputs: ["dist/**", "build/**"], - }, - "garbage-in-numeric": { - outputs: 42, - }, - "garbage-in-string": { - outputs: "string", - }, - "garbage-in-empty-string": { - outputs: ["dist/**", "build/**"], - }, - "garbage-in-null": { - outputs: ["dist/**", "build/**"], - }, - "garbage-in-false": { - outputs: ["dist/**", "build/**"], - }, - "garbage-in-true": { - outputs: true, - }, - "garbage-in-object": { - outputs: {}, - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 6, - "deletions": 5, - }, - } - `); - }); - - it("migrates turbo.json outputs - config with no pipeline", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-pipeline", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalDependencies: ["$NEXT_PUBLIC_API_KEY", "$STRIPE_API_KEY", ".env"], - pipeline: {}, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates turbo.json outputs - config with no outputs", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-outputs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - "build-one": { - dependsOn: ["build-two"], - outputs: ["dist/**", "build/**"], - }, - "build-two": { - cache: false, - }, - "build-three": { - persistent: true, - outputs: ["dist/**", "build/**"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 0, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); - - it("errors if package.json config exists and has not been migrated", () => { - // load the fixture for the test - const { root } = useFixture({ - fixture: "old-config", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - 'turbo" key detected in package.json. Run `npx @turbo/codemod transform create-turbo-config` first' - ); - }); -}); diff --git a/packages/turbo-codemod/__tests__/stabilize-env-mode.test.ts b/packages/turbo-codemod/__tests__/stabilize-env-mode.test.ts deleted file mode 100644 index d60af37412524..0000000000000 --- a/packages/turbo-codemod/__tests__/stabilize-env-mode.test.ts +++ /dev/null @@ -1,332 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/stabilize-env-mode"; - -describe("stabilize-env-mode", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "stabilize-env-mode", - }); - - it("migrates env-mode has-both", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-both", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalPassThroughEnv: [ - "EXPERIMENTAL_GLOBAL_PASSTHROUGH", - "GLOBAL_PASSTHROUGH", - ], - pipeline: { - build: { - passThroughEnv: ["EXPERIMENTAL_TASK_PASSTHROUGH", "TASK_PASSTHROUGH"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 4, - }, - } - `); - }); - - it("migrates env-mode has-duplicates", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-duplicates", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalPassThroughEnv: [ - "DUPLICATE_GLOBAL", - "EXPERIMENTAL_GLOBAL_PASSTHROUGH", - "GLOBAL_PASSTHROUGH", - ], - pipeline: { - build: { - passThroughEnv: [ - "DUPLICATE_TASK", - "EXPERIMENTAL_TASK_PASSTHROUGH", - "TASK_PASSTHROUGH", - ], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 6, - }, - } - `); - }); - - it("migrates env-mode has-empty", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-empty", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalPassThroughEnv: [], - pipeline: { - build: { - passThroughEnv: [], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates env-mode has-neither", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-neither", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - build: {}, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates env-mode has-new", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-new", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalPassThroughEnv: ["GLOBAL_PASSTHROUGH"], - pipeline: { - build: { - passThroughEnv: ["TASK_PASSTHROUGH"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates env-mode has-old", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-old", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalPassThroughEnv: ["GLOBAL_PASSTHROUGH"], - pipeline: { - build: { - passThroughEnv: ["TASK_PASSTHROUGH"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - } - `); - }); - - it("migrates env-mode workspace-configs", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "workspace-configs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalPassThroughEnv: [ - "EXPERIMENTAL_GLOBAL_PASSTHROUGH", - "GLOBAL_PASSTHROUGH", - ], - pipeline: { - build: { - passThroughEnv: ["EXPERIMENTAL_TASK_PASSTHROUGH", "TASK_PASSTHROUGH"], - }, - }, - }); - - expect(JSON.parse(read("apps/docs/turbo.json") || "{}")).toStrictEqual({ - extends: ["//"], - pipeline: { - build: { - passThroughEnv: [ - "DOCS_TASK_PASSTHROUGH", - "EXPERIMENTAL_DOCS_TASK_PASSTHROUGH", - ], - }, - }, - }); - - expect(JSON.parse(read("apps/website/turbo.json") || "{}")).toStrictEqual({ - extends: ["//"], - pipeline: { - build: { - passThroughEnv: [ - "EXPERIMENTAL_WEBSITE_TASK_PASSTHROUGH", - "WEBSITE_TASK_PASSTHROUGH", - ], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "apps/docs/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - "apps/website/turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 2, - }, - "turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 4, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); - - it("errors if package.json config exists and has not been migrated", () => { - // load the fixture for the test - const { root } = useFixture({ - fixture: "old-config", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - 'turbo" key detected in package.json. Run `npx @turbo/codemod transform create-turbo-config` first' - ); - }); -}); diff --git a/packages/turbo-codemod/__tests__/stabilize-ui.test.ts b/packages/turbo-codemod/__tests__/stabilize-ui.test.ts deleted file mode 100644 index 4973b3cf8813b..0000000000000 --- a/packages/turbo-codemod/__tests__/stabilize-ui.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/stabilize-ui"; - -describe("stabilize-ui", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "stabilize-ui", - }); - - it("adds no config where there was none", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-config", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - build: { - outputs: ["dist"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("removes config if it was already enabled", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "enabled", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - build: { - outputs: ["dist"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 0, - "deletions": 1, - }, - } - `); - }); - - it("renames config if disabled", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "disabled", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - tasks: { - build: { - outputs: ["dist"], - }, - }, - ui: "stream", - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 1, - "deletions": 1, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); -}); diff --git a/packages/turbo-codemod/__tests__/test-utils.ts b/packages/turbo-codemod/__tests__/test-utils.ts deleted file mode 100644 index 0e065d5a1c187..0000000000000 --- a/packages/turbo-codemod/__tests__/test-utils.ts +++ /dev/null @@ -1,45 +0,0 @@ -import path from "node:path"; -import type { PackageManager } from "@turbo/utils"; -import type { Project } from "@turbo/workspaces"; - -export function getWorkspaceDetailsMockReturnValue({ - root, - packageManager = "npm", - singlePackage = false, -}: { - root: string; - packageManager: PackageManager; - singlePackage?: boolean; -}): Project { - return { - name: "mock-project", - packageManager, - paths: { - root, - packageJson: path.join(root, "package.json"), - lockfile: path.join(root, "yarn.lock"), - nodeModules: path.join(root, "node_modules"), - }, - workspaceData: { - globs: singlePackage ? [] : ["packages/*"], - workspaces: singlePackage - ? [] - : [ - { - name: "packages/mock-package", - paths: { - root: path.join(root, "packages/mock-package"), - packageJson: path.join( - root, - "packages/mock-package/package.json" - ), - nodeModules: path.join( - root, - "packages/mock-package/node_modules" - ), - }, - }, - ], - }, - }; -} diff --git a/packages/turbo-codemod/__tests__/transform-env-literals-to-wildcards.test.ts b/packages/turbo-codemod/__tests__/transform-env-literals-to-wildcards.test.ts deleted file mode 100644 index 8e2e2b03b3dda..0000000000000 --- a/packages/turbo-codemod/__tests__/transform-env-literals-to-wildcards.test.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { transformer } from "../src/transforms/transform-env-literals-to-wildcards"; - -describe.only("transform-env-literals-to-wildcards", () => { - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "transform-env-literals-to-wildcards", - }); - - it("migrates wildcards has-empty", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-empty", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalEnv: [], - globalPassThroughEnv: [], - pipeline: { - build: { - env: [], - passThroughEnv: [], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates env-mode has-nothing", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "has-nothing", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - pipeline: { - build: {}, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "unchanged", - "additions": 0, - "deletions": 0, - }, - } - `); - }); - - it("migrates env-mode needs-rewriting", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "needs-rewriting", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalEnv: ["NO!", "\\!!!", "\\!!!"], - globalPassThroughEnv: ["DOES", "\\*\\*BOLD\\*\\*", "WORK"], - pipeline: { - build: { - env: ["PLAIN", "SMALL_PRINT\\*"], - passThroughEnv: ["PASSWORD", "\\*\\*\\*\\*\\*"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "turbo.json": { - "action": "modified", - "additions": 4, - "deletions": 4, - }, - } - `); - }); - - it("migrates env-mode workspace-configs", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "workspace-configs", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(JSON.parse(read("turbo.json") || "{}")).toStrictEqual({ - $schema: "https://turbo.build/schema.json", - globalEnv: ["\\!\\*!\\*"], - globalPassThroughEnv: ["\\!\\*!\\*"], - pipeline: { - build: { - env: ["NO_ROOT_ENV", "\\!\\*!\\*ROOT"], - passThroughEnv: ["NO_ROOT_PASSTHROUGH_ENV", "\\!\\*!\\*ROOT"], - }, - }, - }); - - expect(JSON.parse(read("apps/docs/turbo.json") || "{}")).toStrictEqual({ - extends: ["//"], - pipeline: { - build: { - env: ["NO_DOCS_ENV", "\\!\\*!\\*DOCS"], - passThroughEnv: ["NO_DOCS_PASSTHROUGH_ENV", "\\!\\*!\\*DOCS"], - }, - }, - }); - - expect(JSON.parse(read("apps/website/turbo.json") || "{}")).toStrictEqual({ - extends: ["//"], - pipeline: { - build: { - env: ["NO_WEBSITE_ENV", "\\!\\*!\\*WEBSITE"], - passThroughEnv: ["NO_WEBSITE_PASSTHROUGH_ENV", "\\!\\*!\\*WEBSITE"], - }, - }, - }); - - expect(result.fatalError).toBeUndefined(); - expect(result.changes).toMatchInlineSnapshot(` - { - "apps/docs/turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - "apps/website/turbo.json": { - "action": "modified", - "additions": 2, - "deletions": 2, - }, - "turbo.json": { - "action": "modified", - "additions": 4, - "deletions": 4, - }, - } - `); - }); - - it("errors if no turbo.json can be found", () => { - // load the fixture for the test - const { root, read } = useFixture({ - fixture: "no-turbo-json", - }); - - expect(read("turbo.json")).toBeUndefined(); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(read("turbo.json")).toBeUndefined(); - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - /No turbo\.json found at .*?\. Is the path correct\?/ - ); - }); - - it("errors if package.json config exists and has not been migrated", () => { - // load the fixture for the test - const { root } = useFixture({ - fixture: "old-config", - }); - - // run the transformer - const result = transformer({ - root, - options: { force: false, dryRun: false, print: false }, - }); - - expect(result.fatalError).toBeDefined(); - expect(result.fatalError?.message).toMatch( - 'turbo" key detected in package.json. Run `npx @turbo/codemod transform create-turbo-config` first' - ); - }); -}); diff --git a/packages/turbo-codemod/__tests__/transform.test.ts b/packages/turbo-codemod/__tests__/transform.test.ts deleted file mode 100644 index 3c2c7d8097d51..0000000000000 --- a/packages/turbo-codemod/__tests__/transform.test.ts +++ /dev/null @@ -1,181 +0,0 @@ -import * as turboWorkspaces from "@turbo/workspaces"; -import * as turboUtils from "@turbo/utils"; -import { setupTestFixtures, spyExit } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { transform } from "../src/commands/transform"; -import * as checkGitStatus from "../src/utils/checkGitStatus"; -import type { MigrateCommandArgument } from "../src/commands"; -import { getWorkspaceDetailsMockReturnValue } from "./test-utils"; - -jest.mock("@turbo/workspaces", () => ({ - __esModule: true, - ...jest.requireActual("@turbo/workspaces"), -})); - -describe("transform", () => { - const mockExit = spyExit(); - const { useFixture } = setupTestFixtures({ - directory: __dirname, - test: "transform", - }); - - it("runs the selected transform", async () => { - const { root, readJson } = useFixture({ - fixture: "basic", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await transform("add-package-manager", root as MigrateCommandArgument, { - list: false, - force: false, - dryRun: false, - print: false, - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.0.0", - }, - name: "transform-basic", - packageManager: "pnpm@1.2.3", - version: "1.0.0", - }); - - // verify mocks were called - expect(mockedCheckGitStatus).toHaveBeenCalled(); - expect(mockGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - }); - - it("runs the selected transform - dry & print", async () => { - const { root, readJson } = useFixture({ - fixture: "basic", - }); - - const packageManager = "pnpm"; - const packageManagerVersion = "1.2.3"; - - // setup mocks - const mockedCheckGitStatus = jest - .spyOn(checkGitStatus, "checkGitStatus") - .mockReturnValue(undefined); - const mockGetAvailablePackageManagers = jest - .spyOn(turboUtils, "getAvailablePackageManagers") - .mockResolvedValue({ - pnpm: packageManagerVersion, - npm: undefined, - yarn: undefined, - bun: undefined, - }); - - const mockGetWorkspaceDetails = jest - .spyOn(turboWorkspaces, "getWorkspaceDetails") - .mockResolvedValue( - getWorkspaceDetailsMockReturnValue({ - root, - packageManager, - }) - ); - - await transform("add-package-manager", root, { - list: false, - force: false, - dryRun: true, - print: true, - }); - - expect(readJson("package.json")).toStrictEqual({ - dependencies: {}, - devDependencies: { - turbo: "1.0.0", - }, - name: "transform-basic", - version: "1.0.0", - }); - - // verify mocks were called - expect(mockedCheckGitStatus).not.toHaveBeenCalled(); - expect(mockGetAvailablePackageManagers).toHaveBeenCalled(); - expect(mockGetWorkspaceDetails).toHaveBeenCalled(); - - // restore mocks - mockedCheckGitStatus.mockRestore(); - mockGetAvailablePackageManagers.mockRestore(); - mockGetWorkspaceDetails.mockRestore(); - }); - - it("lists transforms", async () => { - const { root } = useFixture({ - fixture: "basic", - }); - - await transform("add-package-manager", root, { - list: true, - force: false, - dryRun: false, - print: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(0); - }); - - it("exits on invalid transform", async () => { - const { root } = useFixture({ - fixture: "basic", - }); - - await transform("not-a-real-option", root, { - list: false, - force: false, - dryRun: false, - print: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - }); - - it("exits on invalid directory", async () => { - useFixture({ - fixture: "basic", - }); - - await transform("add-package-manager", "~/path/that/does/not/exist", { - list: false, - force: false, - dryRun: false, - print: false, - }); - - expect(mockExit.exit).toHaveBeenCalledWith(1); - }); -}); diff --git a/packages/turbo-codemod/jest.config.js b/packages/turbo-codemod/jest.config.js new file mode 100644 index 0000000000000..e2d0aef7a2614 --- /dev/null +++ b/packages/turbo-codemod/jest.config.js @@ -0,0 +1,30 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: "ts-jest/presets/js-with-ts", + testEnvironment: "node", + transformIgnorePatterns: ["node_modules/*", "packages/turbo-workspaces/*"], + modulePathIgnorePatterns: [ + "/node_modules", + "/dist", + "/__tests__/__fixtures__", + ], + testPathIgnorePatterns: [ + "__tests__/__fixtures__/", + "/__tests__/test-utils.ts", + ], + coveragePathIgnorePatterns: [ + "__tests__/__fixtures__/", + "/__tests__/test-utils.ts", + ], + collectCoverage: true, + coverageThreshold: { + global: { + branches: 85, + functions: 93, + lines: 92, + statements: 92, + }, + }, + verbose: process.env.RUNNER_DEBUG === "1", + silent: process.env.RUNNER_DEBUG !== "1", +}; diff --git a/packages/turbo-codemod/package.json b/packages/turbo-codemod/package.json index a12f796dbedc3..ae5cd41efac18 100644 --- a/packages/turbo-codemod/package.json +++ b/packages/turbo-codemod/package.json @@ -22,23 +22,23 @@ "lint:prettier": "prettier -c . --cache --ignore-path=../../.prettierignore" }, "dependencies": { - "axios": "0.27.2", - "commander": "^9.5.0", - "diff": "^5.1.0", - "find-up": "4.1.0", - "fs-extra": "^10.0.0", - "gradient-string": "^2.0.0", - "inquirer": "^8.2.4", - "inquirer-file-tree-selection-prompt": "^1.0.19", - "json5": "^2.2.3", - "is-git-clean": "^1.1.0", - "ora": "4.1.1", - "picocolors": "1.0.1", - "semver": "^7.3.7", - "update-check": "^1.5.4" + "axios": "1.7.9", + "commander": "13.1.0", + "diff": "7.0.0", + "find-up": "7.0.0", + "fs-extra": "11.3.0", + "gradient-string": "3.0.0", + "inquirer": "12.4.1", + "inquirer-file-tree-selection-prompt": "2.0.5", + "json5": "2.2.3", + "is-git-clean": "1.1.0", + "ora": "8.2.0", + "picocolors": "1.1.1", + "semver": "7.7.1", + "update-check": "1.5.4" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@turbo/eslint-config": "workspace:*", "@turbo/gen": "workspace:*", "@turbo/test-utils": "workspace:*", @@ -46,20 +46,20 @@ "@turbo/types": "workspace:*", "@turbo/utils": "workspace:*", "@turbo/workspaces": "workspace:*", - "@types/diff": "^5.0.2", - "@types/fs-extra": "^9.0.13", - "@types/gradient-string": "^1.1.2", - "@types/inquirer": "^8.2.0", - "@types/node": "^18.17.2", - "@types/semver": "^7.3.9", - "@types/uuid": "^9.0.0", - "deepmerge": "^4.2.2", - "jest": "^29.7.0", - "plop": "^3.1.1", - "semver": "^7.3.5", - "ts-jest": "^29.2.5", - "tsup": "^6.7.0", - "typescript": "5.5.4" + "@types/diff": "7.0.1", + "@types/fs-extra": "11.0.4", + "@types/gradient-string": "1.1.6", + "@types/inquirer": "9.0.7", + "@types/node": "22.13.1", + "@types/semver": "7.5.8", + "@types/uuid": "10.0.0", + "deepmerge": "4.3.1", + "jest": "29.7.0", + "plop": "4.0.1", + "semver": "7.7.1", + "ts-jest": "29.2.5", + "tsup": "8.3.6", + "typescript": "5.7.3" }, "files": [ "dist" diff --git a/packages/turbo-codemod/src/transforms/README.md b/packages/turbo-codemod/src/transforms/README.md deleted file mode 100644 index c5b32ce1494e2..0000000000000 --- a/packages/turbo-codemod/src/transforms/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# `@turbo/codemod` Transformers - -## Adding new transformers - -Add new transformers using the [plopjs](https://github.com/plopjs/plop) template by running: - -```bash -pnpm add-transformer -``` - -New Transformers will be automatically surfaced to the `transform` CLI command and used by the `migrate` CLI command when appropriate. - -## How it works - -Transformers are loaded automatically from the `src/transforms/` directory via the [`loadTransforms`](../utils/loadTransformers.ts) function. - -All new transformers must contain a default export that matches the [`Transformer`](../types.ts) type: - -```ts -export type Transformer = { - name: string; - description: string; - introducedIn: string; - transformer: (args: TransformerArgs) => TransformerResults; -}; -``` - -## Writing a Transform - -Transforms are ran using the [TransformRunner](../runner/Runner.ts). This class is designed to make writing transforms as simple as possible by abstracting away all of the boilerplate that determines what should be logged, saved, or output as a result. - -To use the TransformRunner: - -1. Transform each file in memory (do not write it back to disk `TransformRunner` takes care of this depending on the options passed in by the user), and pass to `TransformRunner.modifyFile` method. -2. If the transform encounters an unrecoverable error, pass it to the `TransformRunner.abortTransform` method. -3. When all files have been modified and passed to `TransformRunner.modifyFile`, call `TransformRunner.finish` method to write the files to disk (when not running in `dry` mode) and log the results. diff --git a/packages/turbo-exe-stub/package.json b/packages/turbo-exe-stub/package.json index 9732b223d47ed..6928e0b9cf098 100644 --- a/packages/turbo-exe-stub/package.json +++ b/packages/turbo-exe-stub/package.json @@ -1,8 +1,9 @@ { - "name": "@turbo/exe-stub", - "description": "Stub for turbo.exe", - "private": true, - "scripts": { - "build": "bash build.sh" - } + "name": "@turbo/exe-stub", + "description": "Stub for turbo.exe", + "scripts": { + "build": "bash build.sh" + }, + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-gen/.eslintrc.js b/packages/turbo-gen/.eslintrc.js deleted file mode 100644 index a437d3f9fea61..0000000000000 --- a/packages/turbo-gen/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], - ignorePatterns: ["node_modules/", "dist/", "src/templates/**/*"], -}; diff --git a/packages/turbo-gen/README.md b/packages/turbo-gen/README.md deleted file mode 100644 index 880844c4e48fc..0000000000000 --- a/packages/turbo-gen/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# `@turbo/gen` - -Types for working with [Turborepo Generators](https://turbo.build/repo/docs/core-concepts/monorepos/code-generation). - -## Usage - -Install: - -```bash -pnpm add @turbo/gen --save-dev -``` - -Use types within your generator `config.ts`: - -```ts filename="turbo/generators/config.ts" -import type { PlopTypes } from "@turbo/gen"; - -export default function generator(plop: PlopTypes.NodePlopAPI): void { - // create a generator - plop.setGenerator("Generator name", { - description: "Generator description", - // gather information from the user - prompts: [ - ... - ], - // perform actions based on the prompts - actions: [ - ... - ], - }); -} -``` - -Learn more about Turborepo Generators in the [docs](https://turbo.build/repo/docs/core-concepts/monorepos/code-generation) - ---- - -For more information about Turborepo, visit [turbo.build](https://turbo.build) and follow us on X ([@turborepo](https://x.com/turborepo))! diff --git a/packages/turbo-gen/src/cli.ts b/packages/turbo-gen/Source/cli.ts similarity index 100% rename from packages/turbo-gen/src/cli.ts rename to packages/turbo-gen/Source/cli.ts diff --git a/packages/turbo-gen/src/commands/index.ts b/packages/turbo-gen/Source/commands/index.ts similarity index 100% rename from packages/turbo-gen/src/commands/index.ts rename to packages/turbo-gen/Source/commands/index.ts diff --git a/packages/turbo-gen/src/commands/raw/index.ts b/packages/turbo-gen/Source/commands/raw/index.ts similarity index 100% rename from packages/turbo-gen/src/commands/raw/index.ts rename to packages/turbo-gen/Source/commands/raw/index.ts diff --git a/packages/turbo-gen/src/commands/run/index.ts b/packages/turbo-gen/Source/commands/run/index.ts similarity index 100% rename from packages/turbo-gen/src/commands/run/index.ts rename to packages/turbo-gen/Source/commands/run/index.ts diff --git a/packages/turbo-gen/src/commands/run/prompts.ts b/packages/turbo-gen/Source/commands/run/prompts.ts similarity index 100% rename from packages/turbo-gen/src/commands/run/prompts.ts rename to packages/turbo-gen/Source/commands/run/prompts.ts diff --git a/packages/turbo-gen/src/commands/workspace/index.ts b/packages/turbo-gen/Source/commands/workspace/index.ts similarity index 100% rename from packages/turbo-gen/src/commands/workspace/index.ts rename to packages/turbo-gen/Source/commands/workspace/index.ts diff --git a/packages/turbo-gen/src/commands/workspace/prompts.ts b/packages/turbo-gen/Source/commands/workspace/prompts.ts similarity index 100% rename from packages/turbo-gen/src/commands/workspace/prompts.ts rename to packages/turbo-gen/Source/commands/workspace/prompts.ts diff --git a/packages/turbo-gen/src/generators/copy.ts b/packages/turbo-gen/Source/generators/copy.ts similarity index 100% rename from packages/turbo-gen/src/generators/copy.ts rename to packages/turbo-gen/Source/generators/copy.ts diff --git a/packages/turbo-gen/src/generators/custom.ts b/packages/turbo-gen/Source/generators/custom.ts similarity index 100% rename from packages/turbo-gen/src/generators/custom.ts rename to packages/turbo-gen/Source/generators/custom.ts diff --git a/packages/turbo-gen/src/generators/empty.ts b/packages/turbo-gen/Source/generators/empty.ts similarity index 100% rename from packages/turbo-gen/src/generators/empty.ts rename to packages/turbo-gen/Source/generators/empty.ts diff --git a/packages/turbo-gen/src/generators/index.ts b/packages/turbo-gen/Source/generators/index.ts similarity index 100% rename from packages/turbo-gen/src/generators/index.ts rename to packages/turbo-gen/Source/generators/index.ts diff --git a/packages/turbo-gen/src/generators/types.ts b/packages/turbo-gen/Source/generators/types.ts similarity index 100% rename from packages/turbo-gen/src/generators/types.ts rename to packages/turbo-gen/Source/generators/types.ts diff --git a/packages/turbo-gen/src/templates/simple-js/config.js b/packages/turbo-gen/Source/templates/simple-js/config.js similarity index 100% rename from packages/turbo-gen/src/templates/simple-js/config.js rename to packages/turbo-gen/Source/templates/simple-js/config.js diff --git a/crates/turborepo-vt100/tests/data/fixtures/decstbm/6.typescript b/packages/turbo-gen/Source/templates/simple-js/package.json similarity index 100% rename from crates/turborepo-vt100/tests/data/fixtures/decstbm/6.typescript rename to packages/turbo-gen/Source/templates/simple-js/package.json diff --git a/packages/turbo-gen/src/templates/simple-js/templates/turborepo-generators.hbs b/packages/turbo-gen/Source/templates/simple-js/templates/turborepo-generators.hbs similarity index 100% rename from packages/turbo-gen/src/templates/simple-js/templates/turborepo-generators.hbs rename to packages/turbo-gen/Source/templates/simple-js/templates/turborepo-generators.hbs diff --git a/packages/turbo-gen/src/templates/simple-ts/config.ts b/packages/turbo-gen/Source/templates/simple-ts/config.ts similarity index 100% rename from packages/turbo-gen/src/templates/simple-ts/config.ts rename to packages/turbo-gen/Source/templates/simple-ts/config.ts diff --git a/crates/turborepo-vt100/tests/data/fixtures/intermediate_control/3.typescript b/packages/turbo-gen/Source/templates/simple-ts/package.json similarity index 100% rename from crates/turborepo-vt100/tests/data/fixtures/intermediate_control/3.typescript rename to packages/turbo-gen/Source/templates/simple-ts/package.json diff --git a/packages/turbo-gen/src/templates/simple-ts/templates/turborepo-generators.hbs b/packages/turbo-gen/Source/templates/simple-ts/templates/turborepo-generators.hbs similarity index 100% rename from packages/turbo-gen/src/templates/simple-ts/templates/turborepo-generators.hbs rename to packages/turbo-gen/Source/templates/simple-ts/templates/turborepo-generators.hbs diff --git a/packages/turbo-gen/src/types.ts b/packages/turbo-gen/Source/types.ts similarity index 100% rename from packages/turbo-gen/src/types.ts rename to packages/turbo-gen/Source/types.ts diff --git a/packages/turbo-gen/src/utils/error.ts b/packages/turbo-gen/Source/utils/error.ts similarity index 100% rename from packages/turbo-gen/src/utils/error.ts rename to packages/turbo-gen/Source/utils/error.ts diff --git a/packages/turbo-gen/src/utils/gatherAddRequirements.ts b/packages/turbo-gen/Source/utils/gatherAddRequirements.ts similarity index 100% rename from packages/turbo-gen/src/utils/gatherAddRequirements.ts rename to packages/turbo-gen/Source/utils/gatherAddRequirements.ts diff --git a/packages/turbo-gen/src/utils/getProject.ts b/packages/turbo-gen/Source/utils/getProject.ts similarity index 100% rename from packages/turbo-gen/src/utils/getProject.ts rename to packages/turbo-gen/Source/utils/getProject.ts diff --git a/packages/turbo-gen/src/utils/getWorkspaceList.ts b/packages/turbo-gen/Source/utils/getWorkspaceList.ts similarity index 100% rename from packages/turbo-gen/src/utils/getWorkspaceList.ts rename to packages/turbo-gen/Source/utils/getWorkspaceList.ts diff --git a/packages/turbo-gen/src/utils/getWorkspaceStructure.ts b/packages/turbo-gen/Source/utils/getWorkspaceStructure.ts similarity index 100% rename from packages/turbo-gen/src/utils/getWorkspaceStructure.ts rename to packages/turbo-gen/Source/utils/getWorkspaceStructure.ts diff --git a/packages/turbo-gen/src/utils/notifyUpdate.ts b/packages/turbo-gen/Source/utils/notifyUpdate.ts similarity index 100% rename from packages/turbo-gen/src/utils/notifyUpdate.ts rename to packages/turbo-gen/Source/utils/notifyUpdate.ts diff --git a/packages/turbo-gen/src/utils/plop.ts b/packages/turbo-gen/Source/utils/plop.ts similarity index 100% rename from packages/turbo-gen/src/utils/plop.ts rename to packages/turbo-gen/Source/utils/plop.ts diff --git a/packages/turbo-gen/src/utils/setupFromTemplate.ts b/packages/turbo-gen/Source/utils/setupFromTemplate.ts similarity index 100% rename from packages/turbo-gen/src/utils/setupFromTemplate.ts rename to packages/turbo-gen/Source/utils/setupFromTemplate.ts diff --git a/packages/turbo-gen/src/utils/workspaceRoots.ts b/packages/turbo-gen/Source/utils/workspaceRoots.ts similarity index 100% rename from packages/turbo-gen/src/utils/workspaceRoots.ts rename to packages/turbo-gen/Source/utils/workspaceRoots.ts diff --git a/packages/turbo-gen/__tests__/raw.test.ts b/packages/turbo-gen/__tests__/raw.test.ts deleted file mode 100644 index 127a03d15bace..0000000000000 --- a/packages/turbo-gen/__tests__/raw.test.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { describe, it, expect, jest } from "@jest/globals"; -import { raw } from "../src/commands/raw"; -import * as run from "../src/commands/run"; -import * as workspace from "../src/commands/workspace"; - -describe("raw", () => { - const testMatrix = [ - // run - { - command: "run", - options: { config: "../config.ts", root: "../" }, - target: "run", - calledWith: { config: "../config.ts", root: "../" }, - }, - { - command: "run", - options: { - generator_name: "thisOne", - config: "../config.ts", - root: "../", - }, - target: "run", - calledWith: { config: "../config.ts", root: "../" }, - }, - { - command: "run", - options: { - generator_name: "thisOne", - config: "../config.ts", - root: "../", - args: ["cool name", "packages/cool-name"], - }, - target: "run", - calledWith: { - config: "../config.ts", - root: "../", - args: ["cool name", "packages/cool-name"], - }, - }, - // workspace - { - command: "workspace", - options: {}, - target: "workspace", - calledWith: { - empty: true, - copy: false, - showAllDependencies: false, - }, - }, - { - command: "workspace", - options: { - copy: "", - }, - target: "workspace", - calledWith: { - empty: false, - copy: true, - showAllDependencies: false, - }, - }, - { - command: "workspace", - options: { - copy: "some-workspace", - show_all_dependencies: false, - }, - target: "workspace", - calledWith: { - copy: "some-workspace", - empty: false, - showAllDependencies: false, - }, - }, - { - command: "workspace", - options: { - type: "package", - name: "cool-name", - copy: true, - show_all_dependencies: true, - }, - target: "workspace", - calledWith: { - type: "package", - name: "cool-name", - copy: true, - empty: false, - showAllDependencies: true, - }, - }, - { - command: "workspace", - options: { - type: "package", - name: "cool-name", - empty: true, - copy: "tailwind-css", - destination: "../../", - show_all_dependencies: true, - example_path: "packages/cool-name", - }, - target: "workspace", - calledWith: { - type: "package", - name: "cool-name", - empty: false, - copy: "tailwind-css", - destination: "../../", - showAllDependencies: true, - examplePath: "packages/cool-name", - }, - }, - // different casing - { - command: "workspace", - options: { - type: "package", - name: "cool-name", - empty: true, - copy: "tailwind-css", - destination: "../../", - "show-all-dependencies": true, - "example-path": "packages/cool-name", - }, - target: "workspace", - calledWith: { - type: "package", - name: "cool-name", - empty: false, - copy: "tailwind-css", - destination: "../../", - showAllDependencies: true, - examplePath: "packages/cool-name", - }, - }, - ]; - it.each(testMatrix)( - "$command and $options calls $target with $calledWith", - async ({ command, options, target, calledWith }) => { - // mock generation functions, we only care if they are called, - // and what they are called with - const mockWorkspace = jest - .spyOn(workspace, "workspace") - .mockResolvedValue(undefined); - - const mockRun = jest.spyOn(run, "run").mockResolvedValue(undefined); - - await raw(command, { json: JSON.stringify(options) }); - - if (target === "run") { - expect(mockRun).toHaveBeenCalledWith( - options.generator_name, - calledWith - ); - expect(mockWorkspace).not.toHaveBeenCalled(); - } else { - expect(mockWorkspace).toHaveBeenCalledWith(calledWith); - expect(mockRun).not.toHaveBeenCalled(); - } - - mockWorkspace.mockRestore(); - mockRun.mockRestore(); - } - ); -}); diff --git a/packages/turbo-gen/__tests__/test-utils.ts b/packages/turbo-gen/__tests__/test-utils.ts deleted file mode 100644 index f594a42c179e2..0000000000000 --- a/packages/turbo-gen/__tests__/test-utils.ts +++ /dev/null @@ -1,34 +0,0 @@ -import path from "node:path"; -import type { PackageManager } from "@turbo/utils"; - -export function getWorkspaceDetailsMockReturnValue({ - root, - packageManager = "npm", -}: { - root: string; - packageManager: PackageManager; -}) { - return { - name: "mock-project", - packageManager, - paths: { - root, - packageJson: path.join(root, "package.json"), - lockfile: path.join(root, "yarn.lock"), - nodeModules: path.join(root, "node_modules"), - }, - workspaceData: { - globs: ["packages/*"], - workspaces: [ - { - name: "packages/mock-package", - paths: { - root: path.join(root, "packages/mock-package"), - packageJson: path.join(root, "packages/mock-package/package.json"), - nodeModules: path.join(root, "packages/mock-package/node_modules"), - }, - }, - ], - }, - }; -} diff --git a/packages/turbo-gen/jest.config.js b/packages/turbo-gen/jest.config.js new file mode 100644 index 0000000000000..9e9d6c5f19aab --- /dev/null +++ b/packages/turbo-gen/jest.config.js @@ -0,0 +1,12 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: "ts-jest/presets/js-with-ts", + testEnvironment: "node", + testPathIgnorePatterns: ["__fixtures__/", "/__tests__/test-utils.ts"], + coveragePathIgnorePatterns: ["__fixtures__/", "/__tests__/test-utils.ts"], + transformIgnorePatterns: ["node_modules/*", "packages/turbo-workspaces/*"], + modulePathIgnorePatterns: ["/node_modules", "/dist"], + collectCoverage: true, + verbose: process.env.RUNNER_DEBUG === "1", + silent: process.env.RUNNER_DEBUG !== "1", +}; diff --git a/packages/turbo-gen/package.json b/packages/turbo-gen/package.json index 8a72561024465..65ffbb4522f33 100644 --- a/packages/turbo-gen/package.json +++ b/packages/turbo-gen/package.json @@ -22,31 +22,31 @@ }, "dependencies": { "@turbo/workspaces": "workspace:*", - "commander": "^10.0.0", - "fs-extra": "^10.1.0", - "inquirer": "^8.2.4", - "minimatch": "^9.0.0", - "node-plop": "^0.26.3", - "picocolors": "1.0.1", - "proxy-agent": "^6.2.2", - "ts-node": "^10.9.2", - "update-check": "^1.5.4", - "validate-npm-package-name": "^5.0.0" + "commander": "13.1.0", + "fs-extra": "11.3.0", + "inquirer": "12.4.1", + "minimatch": "10.0.1", + "node-plop": "0.32.0", + "picocolors": "1.1.1", + "proxy-agent": "6.5.0", + "ts-node": "10.9.2", + "update-check": "1.5.4", + "validate-npm-package-name": "6.0.0" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@turbo/eslint-config": "workspace:*", "@turbo/test-utils": "workspace:*", "@turbo/tsconfig": "workspace:*", "@turbo/utils": "workspace:*", - "@types/fs-extra": "^9.0.13", - "@types/inquirer": "^8.2.5", - "@types/node": "^18.17.2", - "@types/validate-npm-package-name": "^4.0.0", - "jest": "^29.7.0", - "ts-jest": "^29.2.5", - "tsup": "^6.7.0", - "typescript": "5.5.4" + "@types/fs-extra": "11.0.4", + "@types/inquirer": "9.0.7", + "@types/node": "22.13.1", + "@types/validate-npm-package-name": "4.0.2", + "jest": "29.7.0", + "ts-jest": "29.2.5", + "tsup": "8.3.6", + "typescript": "5.7.3" }, "files": [ "dist" diff --git a/packages/turbo-gen/src/templates/simple-js/package.json b/packages/turbo-gen/src/templates/simple-js/package.json deleted file mode 100644 index 5bbefffbabee3..0000000000000 --- a/packages/turbo-gen/src/templates/simple-js/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "commonjs" -} diff --git a/packages/turbo-gen/src/templates/simple-ts/package.json b/packages/turbo-gen/src/templates/simple-ts/package.json deleted file mode 100644 index 5bbefffbabee3..0000000000000 --- a/packages/turbo-gen/src/templates/simple-ts/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "commonjs" -} diff --git a/packages/turbo-ignore/.eslintrc.js b/packages/turbo-ignore/.eslintrc.js deleted file mode 100644 index 1e66e397a97b6..0000000000000 --- a/packages/turbo-ignore/.eslintrc.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], - - overrides: [ - { - files: ["__tests__/**"], - rules: { - "@typescript-eslint/no-confusing-void-expression": "off", - "@typescript-eslint/no-unsafe-return": "off", - }, - }, - ], -}; diff --git a/packages/turbo-ignore/README.md b/packages/turbo-ignore/README.md deleted file mode 100644 index 0ccbde2d7cd01..0000000000000 --- a/packages/turbo-ignore/README.md +++ /dev/null @@ -1,103 +0,0 @@ -# `turbo-ignore` - -To get started, use the following command as your [Ignored Build Step](https://vercel.com/docs/concepts/projects/overview#ignored-build-step): - -```sh -$ npx turbo-ignore -``` - -This uses `turbo` to automatically determine if the current app has new changes that need to be deployed. - -## Usage - -Use `npx turbo-ignore --help` to see list of options: - -```sh -turbo-ignore - -Automatically ignore builds that have no changes - -Usage: - $ npx turbo-ignore [] [flags...] - -If is not provided, it will be inferred from the "name" -field of the "package.json" located at the current working directory. - -Flags: - --fallback= On Vercel, if no previously deployed SHA is available to compare against, - fallback to comparing against the provided ref [default: None]. When not on Vercel, - compare against the provided fallback - --help, -h Show this help message - --version, -v Show the version of this script - ---- - -turbo-ignore will also check for special commit messages to indicate if a build should be skipped or not. - -Skip turbo-ignore check and automatically ignore: - - [skip ci] - - [ci skip] - - [no ci] - - [skip vercel] - - [vercel skip] - - [vercel skip ] - -Skip turbo-ignore check and automatically deploy: - - [vercel deploy] - - [vercel build] - - [vercel deploy ] - - [vercel build ] - -Skip turbo-ignore check and automatically deploy specific workspace and ignore others: - - [vercel only ] -``` - -### Examples - -```sh -npx turbo-ignore -``` - -> Only build if there are changes to the workspace in the current working directory, or any of it's dependencies. On Vercel, compare against the last successful deployment for the current branch. When not on Vercel, compare against the parent commit (`HEAD^`). - ---- - -```sh -npx turbo-ignore docs -``` - -> Only build if there are changes to the `docs` workspace, or any of its dependencies. On Vercel, compare against the last successful deployment for the current branch. When not on Vercel compare against the parent commit (`HEAD^`). - ---- - -```sh -npx turbo-ignore --fallback=HEAD~10 -``` - -> Only build if there are changes to the workspace in the current working directory, or any of it's dependencies. On Vercel, compare against the last successful deployment for the current branch. If this does not exist (first deploy of the branch), compare against the previous 10 commits. When not on Vercel, compare against the parent commit (`HEAD^`) or the fallback provided. - ---- - -```sh -npx turbo-ignore --fallback=HEAD^ -``` - -> Only build if there are changes to the workspace in the current working directory, or any of it's dependencies. On Vercel, compare against the last successful deployment for the current branch. If this does not exist (first deploy of the branch), compare against the parent commit (`HEAD^`). When not on Vercel, compare against the parent commit (`HEAD^`) or the fallback provided. - -## How it Works - -`turbo-ignore` determines if a build should continue by analyzing the package dependency graph of the given workspace. - -The _given workspace_ is determined by reading the "name" field in the "package.json" file located at the current working directory, or by passing in a workspace name as the first argument to `turbo-ignore`. - -Next, it uses `turbo run build --dry` to determine if the given workspace, _or any dependencies of the workspace_, have changed since the previous commit. - -**NOTE:** `turbo` determines dependencies from reading the dependency graph of the given workspace. This means a workspace **must** be listed as a `dependency` (or `devDependency`) in the given workspaces `package.json` for `turbo` to recognize it. - -When deploying on [Vercel](https://vercel.com), `turbo-ignore` can make a more accurate decision by comparing between the current commit, and the last successfully deployed commit for the current branch. - -**NOTE:** By default on Vercel, `turbo-ignore` will always deploy the first commit of a new branch. This behavior can be changed by providing the `ref` to compare against to the `--fallback` flag. See the [Examples](#Examples) section for more details. - ---- - -For more information about Turborepo, visit [turbo.build](https://turbo.build) and follow us on X ([@turborepo](https://x.com/turborepo))! diff --git a/packages/turbo-ignore/src/checkCommit.ts b/packages/turbo-ignore/Source/checkCommit.ts similarity index 100% rename from packages/turbo-ignore/src/checkCommit.ts rename to packages/turbo-ignore/Source/checkCommit.ts diff --git a/packages/turbo-ignore/src/cli.ts b/packages/turbo-ignore/Source/cli.ts old mode 100755 new mode 100644 similarity index 100% rename from packages/turbo-ignore/src/cli.ts rename to packages/turbo-ignore/Source/cli.ts diff --git a/packages/turbo-ignore/src/errors.ts b/packages/turbo-ignore/Source/errors.ts similarity index 100% rename from packages/turbo-ignore/src/errors.ts rename to packages/turbo-ignore/Source/errors.ts diff --git a/packages/turbo-ignore/src/getComparison.ts b/packages/turbo-ignore/Source/getComparison.ts similarity index 100% rename from packages/turbo-ignore/src/getComparison.ts rename to packages/turbo-ignore/Source/getComparison.ts diff --git a/packages/turbo-ignore/src/getTask.ts b/packages/turbo-ignore/Source/getTask.ts similarity index 100% rename from packages/turbo-ignore/src/getTask.ts rename to packages/turbo-ignore/Source/getTask.ts diff --git a/packages/turbo-ignore/src/getTurboVersion.ts b/packages/turbo-ignore/Source/getTurboVersion.ts similarity index 100% rename from packages/turbo-ignore/src/getTurboVersion.ts rename to packages/turbo-ignore/Source/getTurboVersion.ts diff --git a/packages/turbo-ignore/src/getWorkspace.ts b/packages/turbo-ignore/Source/getWorkspace.ts similarity index 100% rename from packages/turbo-ignore/src/getWorkspace.ts rename to packages/turbo-ignore/Source/getWorkspace.ts diff --git a/packages/turbo-ignore/src/ignore.ts b/packages/turbo-ignore/Source/ignore.ts similarity index 100% rename from packages/turbo-ignore/src/ignore.ts rename to packages/turbo-ignore/Source/ignore.ts diff --git a/packages/turbo-ignore/src/logger.ts b/packages/turbo-ignore/Source/logger.ts similarity index 100% rename from packages/turbo-ignore/src/logger.ts rename to packages/turbo-ignore/Source/logger.ts diff --git a/packages/turbo-ignore/src/types.ts b/packages/turbo-ignore/Source/types.ts similarity index 100% rename from packages/turbo-ignore/src/types.ts rename to packages/turbo-ignore/Source/types.ts diff --git a/packages/turbo-ignore/__fixtures__/app/package.json b/packages/turbo-ignore/__fixtures__/app/package.json index 17d7c56314b6d..a6ccfd6af2567 100644 --- a/packages/turbo-ignore/__fixtures__/app/package.json +++ b/packages/turbo-ignore/__fixtures__/app/package.json @@ -1,11 +1,8 @@ { - "name": "test-app", - "private": true, - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "vercel" + "name": "test-app", + "description": "", + "main": "index.js", + "scripts": {}, + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-ignore/__fixtures__/invalid-app/package.json b/packages/turbo-ignore/__fixtures__/invalid-app/package.json index ee2f59bce648e..8b137891791fe 100644 --- a/packages/turbo-ignore/__fixtures__/invalid-app/package.json +++ b/packages/turbo-ignore/__fixtures__/invalid-app/package.json @@ -1,10 +1 @@ -{ - "private": true, - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "vercel" -} + diff --git a/packages/turbo-ignore/__fixtures__/invalid_turbo_json/package.json b/packages/turbo-ignore/__fixtures__/invalid_turbo_json/package.json index 17d7c56314b6d..a6ccfd6af2567 100644 --- a/packages/turbo-ignore/__fixtures__/invalid_turbo_json/package.json +++ b/packages/turbo-ignore/__fixtures__/invalid_turbo_json/package.json @@ -1,11 +1,8 @@ { - "name": "test-app", - "private": true, - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "vercel" + "name": "test-app", + "description": "", + "main": "index.js", + "scripts": {}, + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-ignore/__fixtures__/no_turbo_deps/package.json b/packages/turbo-ignore/__fixtures__/no_turbo_deps/package.json index 17d7c56314b6d..a6ccfd6af2567 100644 --- a/packages/turbo-ignore/__fixtures__/no_turbo_deps/package.json +++ b/packages/turbo-ignore/__fixtures__/no_turbo_deps/package.json @@ -1,11 +1,8 @@ { - "name": "test-app", - "private": true, - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "vercel" + "name": "test-app", + "description": "", + "main": "index.js", + "scripts": {}, + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-ignore/__fixtures__/no_turbo_deps_v1/package.json b/packages/turbo-ignore/__fixtures__/no_turbo_deps_v1/package.json index 17d7c56314b6d..a6ccfd6af2567 100644 --- a/packages/turbo-ignore/__fixtures__/no_turbo_deps_v1/package.json +++ b/packages/turbo-ignore/__fixtures__/no_turbo_deps_v1/package.json @@ -1,11 +1,8 @@ { - "name": "test-app", - "private": true, - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "vercel" + "name": "test-app", + "description": "", + "main": "index.js", + "scripts": {}, + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-ignore/__fixtures__/turbo_in_deps/package.json b/packages/turbo-ignore/__fixtures__/turbo_in_deps/package.json index 5ecef8f856f45..80324b32bfaa7 100644 --- a/packages/turbo-ignore/__fixtures__/turbo_in_deps/package.json +++ b/packages/turbo-ignore/__fixtures__/turbo_in_deps/package.json @@ -1,14 +1,10 @@ { - "name": "test-app", - "private": true, - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "vercel", - "dependencies": { - "turbo": "^99" - } + "name": "test-app", + "description": "", + "main": "index.js", + "scripts": {}, + "dependencies": { + "turbo": "99" + }, + "devDependencies": {} } diff --git a/packages/turbo-ignore/__tests__/checkCommit.test.ts b/packages/turbo-ignore/__tests__/checkCommit.test.ts deleted file mode 100644 index f5e8881e75077..0000000000000 --- a/packages/turbo-ignore/__tests__/checkCommit.test.ts +++ /dev/null @@ -1,283 +0,0 @@ -// eslint-disable-next-line camelcase -- this is a good exception to this rule -import child_process from "node:child_process"; -import { mockEnv } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { checkCommit } from "../src/checkCommit"; - -describe("checkCommit()", () => { - describe("on Vercel", () => { - mockEnv(); - - describe("for all workspaces", () => { - it("results in continue when no special commit messages are found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = "fixing a test"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "continue", - scope: "global", - reason: "No deploy or skip string found in commit message.", - }); - }); - - it("results in conflict when deploy and skip commit messages are found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = - "deploying [vercel deploy] and skipping [vercel skip]"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "conflict", - scope: "global", - reason: - "Conflicting commit messages found: [vercel deploy] and [vercel skip]", - }); - }); - - it("results in deploy when deploy commit message is found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = "deploying [vercel deploy]"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "deploy", - scope: "global", - reason: "Found commit message: [vercel deploy]", - }); - }); - - it("results in skip when skip commit message is found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = "skip deployment [vercel skip]"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "skip", - scope: "global", - reason: "Found commit message: [vercel skip]", - }); - }); - }); - - describe("for specific workspaces", () => { - it("results in continue when no special commit messages are found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = - "fixing a test in test-workspace"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "continue", - scope: "global", - reason: "No deploy or skip string found in commit message.", - }); - }); - - it("results in conflict when deploy and skip commit messages are found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = - "deploying [vercel deploy test-workspace] and skipping [vercel skip test-workspace]"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "conflict", - scope: "workspace", - reason: - "Conflicting commit messages found: [vercel deploy test-workspace] and [vercel skip test-workspace]", - }); - }); - - it("results in deploy when deploy commit message is found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = - "deploying [vercel deploy test-workspace]"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "deploy", - scope: "workspace", - reason: "Found commit message: [vercel deploy test-workspace]", - }); - }); - - it("results in skip when skip commit message is found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = - "skip deployment [vercel skip test-workspace]"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "skip", - scope: "workspace", - reason: "Found commit message: [vercel skip test-workspace]", - }); - }); - - it("results in deploy when deploy only is found", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = - "deploying [vercel only test-workspace]"; - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "deploy", - scope: "workspace", - reason: "Found commit message: [vercel only test-workspace]", - }); - }); - - it("results in skip when deploy not match workspace", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = - "deploying [vercel only test-workspace]"; - expect(checkCommit({ workspace: "test-workspace2" })).toEqual({ - result: "skip", - scope: "workspace", - reason: "Found commit message: [vercel only test-workspace]", - }); - }); - }); - }); - describe("Not on Vercel", () => { - describe("for all workspaces", () => { - it("results in continue when no special commit messages are found", () => { - const commitBody = "fixing a test"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "continue", - scope: "global", - reason: "No deploy or skip string found in commit message.", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in conflict when deploy and skip commit messages are found", () => { - const commitBody = - "deploying [vercel deploy] and skipping [vercel skip]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "conflict", - scope: "global", - reason: - "Conflicting commit messages found: [vercel deploy] and [vercel skip]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in deploy when deploy commit message is found", () => { - const commitBody = "deploying [vercel deploy]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "deploy", - scope: "global", - reason: "Found commit message: [vercel deploy]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in skip when skip commit message is found", () => { - const commitBody = "skip deployment [vercel skip]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "skip", - scope: "global", - reason: "Found commit message: [vercel skip]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - }); - - describe("for specific workspaces", () => { - it("results in continue when no special commit messages are found", () => { - const commitBody = "fixing a test in test-workspace"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "continue", - scope: "global", - reason: "No deploy or skip string found in commit message.", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in conflict when deploy and skip commit messages are found", () => { - const commitBody = - "deploying [vercel deploy test-workspace] and skipping [vercel skip test-workspace]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "conflict", - scope: "workspace", - reason: - "Conflicting commit messages found: [vercel deploy test-workspace] and [vercel skip test-workspace]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in deploy when deploy commit message is found", () => { - const commitBody = "deploying [vercel deploy test-workspace]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "deploy", - scope: "workspace", - reason: "Found commit message: [vercel deploy test-workspace]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in skip when skip commit message is found", () => { - const commitBody = "skip deployment [vercel skip test-workspace]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "skip", - scope: "workspace", - reason: "Found commit message: [vercel skip test-workspace]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in deploy when deploy only is found", () => { - const commitBody = "deploying [vercel only test-workspace]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace" })).toEqual({ - result: "deploy", - scope: "workspace", - reason: "Found commit message: [vercel only test-workspace]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - - it("results in skip when deploy not match workspace", () => { - const commitBody = "deploying [vercel only test-workspace]"; - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((_) => commitBody); - - expect(checkCommit({ workspace: "test-workspace2" })).toEqual({ - result: "skip", - scope: "workspace", - reason: "Found commit message: [vercel only test-workspace]", - }); - expect(mockExecSync).toHaveBeenCalledWith("git show -s --format=%B"); - mockExecSync.mockRestore(); - }); - }); - }); -}); diff --git a/packages/turbo-ignore/__tests__/errors.test.ts b/packages/turbo-ignore/__tests__/errors.test.ts deleted file mode 100644 index da8e3b47ec329..0000000000000 --- a/packages/turbo-ignore/__tests__/errors.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { describe, it, expect } from "@jest/globals"; -import { shouldWarn, NON_FATAL_ERRORS } from "../src/errors"; - -describe("shouldWarn()", () => { - it("it detects errors when packageManager is missing", () => { - const result = shouldWarn({ - err: `run failed: We did not detect an in-use package manager for your project. Please set the "packageManager" property in your root package.json (https://nodejs.org/api/packages.html#packagemanager) or run \`npx @turbo/codemod add-package-manager\` in the root of your monorepo.`, - }); - expect(result.code).toBe("NO_PACKAGE_MANAGER"); - expect(result.level).toBe("warn"); - expect(result.message).toBe(NON_FATAL_ERRORS.NO_PACKAGE_MANAGER.message); - }); - - it("it detects errors when yarn lockfile is missing", () => { - const result = shouldWarn({ - err: `* reading yarn.lock: open /test/../yarn.lock: no such file or directory`, - }); - expect(result.code).toBe("MISSING_LOCKFILE"); - expect(result.level).toBe("warn"); - expect(result.message).toBe(NON_FATAL_ERRORS.MISSING_LOCKFILE.message); - }); - - it("it detects errors when pnpm lockfile is missing", () => { - const result = shouldWarn({ - err: `* reading pnpm-lock.yaml: open /test/../pnpm-lock.yaml: no such file or directory`, - }); - expect(result.code).toBe("MISSING_LOCKFILE"); - expect(result.level).toBe("warn"); - expect(result.message).toBe(NON_FATAL_ERRORS.MISSING_LOCKFILE.message); - }); - - it("it detects errors when npm lockfile is missing", () => { - const result = shouldWarn({ - err: `* reading package-lock.json: open /test/../package-lock.json: no such file or directory`, - }); - expect(result.code).toBe("MISSING_LOCKFILE"); - expect(result.level).toBe("warn"); - expect(result.message).toBe(NON_FATAL_ERRORS.MISSING_LOCKFILE.message); - }); - - it("it returns unknown errors", () => { - const result = shouldWarn({ err: `something bad happened` }); - expect(result.code).toBe("UNKNOWN_ERROR"); - expect(result.level).toBe("error"); - expect(result.message).toBe(`something bad happened`); - }); -}); diff --git a/packages/turbo-ignore/__tests__/getComparison.test.ts b/packages/turbo-ignore/__tests__/getComparison.test.ts deleted file mode 100644 index 7a194353e364f..0000000000000 --- a/packages/turbo-ignore/__tests__/getComparison.test.ts +++ /dev/null @@ -1,202 +0,0 @@ -// eslint-disable-next-line camelcase -- This is a test file -import child_process from "node:child_process"; -import { spyConsole, mockEnv, validateLogs } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { getComparison } from "../src/getComparison"; - -describe("getComparison()", () => { - mockEnv(); - const mockConsole = spyConsole(); - it("uses headRelative comparison when not running Vercel CI", () => { - expect(getComparison({ workspace: "test-workspace" })) - .toMatchInlineSnapshot(` - { - "ref": "HEAD^", - "type": "headRelative", - } - `); - expect(mockConsole.log).toHaveBeenCalledTimes(0); - }); - - it("uses fallback comparison if provided when not running Vercel CI", () => { - expect(getComparison({ workspace: "test-workspace", fallback: "HEAD^2" })) - .toMatchInlineSnapshot(` - { - "ref": "HEAD^2", - "type": "customFallback", - } - `); - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - "Falling back to ref HEAD^2" - ); - }); - - it("returns null when running in Vercel CI with no VERCEL_GIT_PREVIOUS_SHA", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - expect(getComparison({ workspace: "test-workspace" })).toBeNull(); - - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'No previous deployments found for "test-workspace" on branch "my-branch"' - ); - }); - - it("uses custom fallback when running in Vercel CI with no VERCEL_GIT_PREVIOUS_SHA", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - expect(getComparison({ workspace: "test-workspace", fallback: "HEAD^2" })) - .toMatchInlineSnapshot(` - { - "ref": "HEAD^2", - "type": "customFallback", - } - `); - - validateLogs(mockConsole.log, [ - [ - "≫ ", - 'No previous deployments found for "test-workspace" on branch "my-branch"', - ], - ["≫ ", "Falling back to ref HEAD^2"], - ]); - }); - - it("modifies output when running in Vercel CI with no VERCEL_GIT_PREVIOUS_SHA and no VERCEL_GIT_COMMIT_REF", () => { - process.env.VERCEL = "1"; - expect(getComparison({ workspace: "test-workspace", fallback: "HEAD^2" })) - .toMatchInlineSnapshot(` - { - "ref": "HEAD^2", - "type": "customFallback", - } - `); - - validateLogs(mockConsole.log, [ - ["≫ ", 'No previous deployments found for "test-workspace"'], - ["≫ ", "Falling back to ref HEAD^2"], - ]); - }); - - it("uses previousDeploy when running in Vercel CI with VERCEL_GIT_PREVIOUS_SHA", () => { - const mockExec = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "mygitsha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - expect(getComparison({ workspace: "test-workspace" })) - .toMatchInlineSnapshot(` - { - "ref": "mygitsha", - "type": "previousDeploy", - } - `); - - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Found previous deployment ("mygitsha") for "test-workspace" on branch "my-branch"' - ); - - mockExec.mockRestore(); - }); - - it("uses fallback when running in Vercel CI with unreachable VERCEL_GIT_PREVIOUS_SHA", () => { - const mockExec = jest - .spyOn(child_process, "execSync") - .mockImplementation(() => { - throw new Error("fatal: Not a valid object name mygitsha"); - }); - - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "mygitsha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - expect(getComparison({ workspace: "test-workspace", fallback: "HEAD^2" })) - .toMatchInlineSnapshot(` - { - "ref": "HEAD^2", - "type": "customFallback", - } - `); - - validateLogs(mockConsole.log, [ - [ - "≫ ", - 'Previous deployment ("mygitsha") for "test-workspace" on branch "my-branch" is unreachable.', - ], - ["≫ ", "Falling back to ref HEAD^2"], - ]); - - mockExec.mockRestore(); - }); - - it("returns null running in Vercel CI with unreachable VERCEL_GIT_PREVIOUS_SHA and no fallback", () => { - const mockExec = jest - .spyOn(child_process, "execSync") - .mockImplementation(() => { - throw new Error("fatal: Not a valid object name mygitsha"); - }); - - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "mygitsha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - expect(getComparison({ workspace: "test-workspace" })).toBeNull(); - - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Previous deployment ("mygitsha") for "test-workspace" on branch "my-branch" is unreachable.' - ); - - mockExec.mockRestore(); - }); - - it("modifies output when running in Vercel CI with VERCEL_GIT_PREVIOUS_SHA but no VERCEL_GIT_COMMIT_REF", () => { - const mockExec = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "mygitsha"; - expect(getComparison({ workspace: "test-workspace" })) - .toMatchInlineSnapshot(` - { - "ref": "mygitsha", - "type": "previousDeploy", - } - `); - - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Found previous deployment ("mygitsha") for "test-workspace"' - ); - - mockExec.mockRestore(); - }); - - it("modifies output when running in Vercel CI with unreachable VERCEL_GIT_PREVIOUS_SHA and no VERCEL_GIT_COMMIT_REF", () => { - const mockExec = jest - .spyOn(child_process, "execSync") - .mockImplementation(() => { - throw new Error("fatal: Not a valid object name mygitsha"); - }); - - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "mygitsha"; - expect(getComparison({ workspace: "test-workspace" })).toBeNull(); - - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Previous deployment ("mygitsha") for "test-workspace" is unreachable.' - ); - - mockExec.mockRestore(); - }); -}); diff --git a/packages/turbo-ignore/__tests__/getTask.test.ts b/packages/turbo-ignore/__tests__/getTask.test.ts deleted file mode 100644 index 7c23eb3b16576..0000000000000 --- a/packages/turbo-ignore/__tests__/getTask.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { spyConsole } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { getTask } from "../src/getTask"; - -describe("getWorkspace()", () => { - const mockConsole = spyConsole(); - it("getTask defaults to build", () => { - expect(getTask({})).toEqual("build"); - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Using "build" as the task as it was unspecified' - ); - }); - - it("getTask returns a quoted task if user-supplied", () => { - expect( - getTask({ - task: "workspace#task", - }) - ).toEqual(`"workspace#task"`); - - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Using "workspace#task" as the task from the arguments' - ); - }); -}); diff --git a/packages/turbo-ignore/__tests__/getTurboVersion.test.ts b/packages/turbo-ignore/__tests__/getTurboVersion.test.ts deleted file mode 100644 index 0e41c42fd7fd5..0000000000000 --- a/packages/turbo-ignore/__tests__/getTurboVersion.test.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { spyConsole } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { getTurboVersion } from "../src/getTurboVersion"; - -describe("getWorkspace()", () => { - const mockConsole = spyConsole(); - it("getTurboVersion returns turboVersion from arg", () => { - expect( - getTurboVersion( - { - turboVersion: "1.2.3", - }, - "./__fixtures__/app" - ) - ).toEqual("1.2.3"); - - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Using turbo version "1.2.3" from arguments' - ); - }); - - it("getTurboVersion returns version from package.json", () => { - expect(getTurboVersion({}, "./__fixtures__/turbo_in_deps")).toEqual("^99"); - expect(mockConsole.log).toHaveBeenCalledWith( - "≫ ", - 'Inferred turbo version "^99" from "package.json"' - ); - }); - - it("getTurboVersion infers ^2 if tasks in turbo.json", () => { - expect(getTurboVersion({}, "./__fixtures__/no_turbo_deps")).toEqual("^2"); - expect(mockConsole.log).toHaveBeenCalledWith( - "≫ ", - 'Inferred turbo version ^2 based on "tasks" in "turbo.json"' - ); - }); - - it("getTurboVersion infers ^1 if pipeline in turbo.json", () => { - expect(getTurboVersion({}, "./__fixtures__/no_turbo_deps_v1")).toEqual( - "^1" - ); - expect(mockConsole.log).toHaveBeenCalledWith( - "≫ ", - 'Inferred turbo version ^1 based on "pipeline" in "turbo.json"' - ); - }); - - it("getTurboVersion return null if no turbo.json", () => { - expect(getTurboVersion({}, "./__fixtures__/app")).toEqual(null); - expect(mockConsole.error).toHaveBeenCalledWith( - "≫ ", - '"__fixtures__/app/turbo.json" could not be read. turbo-ignore turbo version inference failed' - ); - }); - - it("getTurboVersion return null if no package.json", () => { - expect(getTurboVersion({}, "./__fixtures__/no-app")).toEqual(null); - expect(mockConsole.error).toHaveBeenCalledWith( - "≫ ", - '"__fixtures__/no-app/package.json" could not be read. turbo-ignore turbo version inference failed' - ); - }); - - it("getTurboVersion return null if invalid JSON", () => { - expect(getTurboVersion({}, "./__fixtures__/invalid_turbo_json")).toEqual( - null - ); - }); -}); diff --git a/packages/turbo-ignore/__tests__/getWorkspace.test.ts b/packages/turbo-ignore/__tests__/getWorkspace.test.ts deleted file mode 100644 index 42a4f693a6722..0000000000000 --- a/packages/turbo-ignore/__tests__/getWorkspace.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { spyConsole } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { getWorkspace } from "../src/getWorkspace"; - -describe("getWorkspace()", () => { - const mockConsole = spyConsole(); - it("getWorkspace returns workspace from arg", () => { - expect( - getWorkspace({ - workspace: "test-workspace", - }) - ).toEqual("test-workspace"); - expect(mockConsole.log).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Using "test-workspace" as workspace from arguments' - ); - }); - - it("getWorkspace returns workspace from package.json", () => { - expect( - getWorkspace({ - directory: "./__fixtures__/app", - }) - ).toEqual("test-app"); - expect(mockConsole.log).toHaveBeenCalledWith( - "≫ ", - 'Inferred "test-app" as workspace from "package.json"' - ); - }); - - it("getWorkspace used current directory if not specified", () => { - expect(getWorkspace({})).toEqual("turbo-ignore"); - expect(mockConsole.log).toHaveBeenCalledWith( - "≫ ", - 'Inferred "turbo-ignore" as workspace from "package.json"' - ); - }); - - it("getWorkspace returns null when no arg is provided and package.json is missing name field", () => { - expect( - getWorkspace({ - directory: "./__fixtures__/invalid-app", - }) - ).toEqual(null); - expect(mockConsole.error).toHaveBeenCalledWith( - "≫ ", - '"__fixtures__/invalid-app/package.json" is missing the "name" field (required).' - ); - }); - - it("getWorkspace returns null when no arg is provided and package.json can be found", () => { - expect( - getWorkspace({ - directory: "./__fixtures__/no-app", - }) - ).toEqual(null); - expect(mockConsole.error).toHaveBeenCalledWith( - "≫ ", - '"__fixtures__/no-app/package.json" could not be found. turbo-ignore inferencing failed' - ); - }); -}); diff --git a/packages/turbo-ignore/__tests__/ignore.test.ts b/packages/turbo-ignore/__tests__/ignore.test.ts deleted file mode 100644 index b5fe5f42a9b1b..0000000000000 --- a/packages/turbo-ignore/__tests__/ignore.test.ts +++ /dev/null @@ -1,756 +0,0 @@ -// eslint-disable-next-line camelcase -- This is a test file -import child_process, { - type ChildProcess, - type ExecException, -} from "node:child_process"; -import { - spyConsole, - spyExit, - type SpyExit, - mockEnv, - validateLogs, -} from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { TurboIgnoreTelemetry, TelemetryConfig } from "@turbo/telemetry"; -import { turboIgnore } from "../src/ignore"; - -function expectBuild(mockExit: SpyExit) { - expect(mockExit.exit).toHaveBeenCalledWith(1); -} - -function expectIgnore(mockExit: SpyExit) { - expect(mockExit.exit).toHaveBeenCalledWith(0); -} - -describe("turboIgnore()", () => { - mockEnv(); - const mockExit = spyExit(); - const mockConsole = spyConsole(); - - const telemetry = new TurboIgnoreTelemetry({ - api: "https://example.com", - packageInfo: { - name: "turbo-ignore", - version: "1.0.0", - }, - config: new TelemetryConfig({ - configPath: "test-config-path", - config: { - telemetry_enabled: false, - telemetry_id: "telemetry-test-id", - telemetry_salt: "telemetry-salt", - }, - }), - }); - - it("throws error and allows build when exec fails", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - { message: "error details" } as unknown as ExecException, - "stdout", - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore("test-workspace", { telemetry }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-workspace...[HEAD^]" --dry=json`, - expect.anything(), - expect.anything() - ); - - expect(mockConsole.error).toHaveBeenNthCalledWith( - 1, - "≫ ", - "UNKNOWN_ERROR: error details" - ); - - expectBuild(mockExit); - mockExec.mockRestore(); - }); - - it("throws pretty error and allows build when exec fails", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - { - message: - "run failed: We did not detect an in-use package manager for your project", - } as unknown as ExecException, - "stdout", - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore("test-workspace", {}); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-workspace...[HEAD^]" --dry=json`, - expect.anything(), - expect.anything() - ); - - expect(mockConsole.warn).toHaveBeenNthCalledWith( - 1, - "≫ ", - `turbo-ignore could not complete - no package manager detected, please commit a lockfile, or set "packageManager" in your root "package.json"` - ); - - expectBuild(mockExit); - mockExec.mockRestore(); - }); - - it("throws pretty error and allows build when can't find previous sha", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "too-far-back"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - { - message: - " ERROR run failed: failed to resolve packages to run: commit too-far-back does not exist", - } as unknown as ExecException, - "stdout", - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore("test-workspace", { telemetry }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-workspace...[too-far-back]" --dry=json`, - expect.anything(), - expect.anything() - ); - - expect(mockConsole.warn).toHaveBeenNthCalledWith( - 1, - "≫ ", - `turbo-ignore could not complete - a ref or SHA is invalid. It could have been removed from the branch history via a force push, or this could be a shallow clone with insufficient history` - ); - - expectBuild(mockExit); - mockExecSync.mockRestore(); - mockExec.mockRestore(); - }); - - it("throws pretty error and allows build when fallback fails", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - { - message: - "ERROR run failed: failed to resolve packages to run: commit HEAD^ does not exist", - } as unknown as ExecException, - "stdout", - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore("test-workspace", { fallback: "HEAD^" }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-workspace...[HEAD^]" --dry=json`, - expect.anything(), - expect.anything() - ); - - expect(mockConsole.warn).toHaveBeenNthCalledWith( - 1, - "≫ ", - `turbo-ignore could not complete - parent commit does not exist or is unreachable` - ); - - expectBuild(mockExit); - mockExec.mockRestore(); - }); - - it("skips checks and allows build when no workspace can be found", () => { - turboIgnore(undefined, { directory: "__fixtures__/no-app" }); - expect(mockConsole.error).toHaveBeenNthCalledWith( - 1, - "≫ ", - expect.stringContaining( - " could not be found. turbo-ignore inferencing failed" - ) - ); - - expectBuild(mockExit); - }); - - it("skips checks and allows build when a workspace with no name is found", () => { - turboIgnore(undefined, { directory: "__fixtures__/invalid-app" }); - expect(mockConsole.error).toHaveBeenNthCalledWith( - 1, - "≫ ", - expect.stringContaining(' is missing the "name" field (required).') - ); - expectBuild(mockExit); - }); - - it("skips checks and allows build when no monorepo root can be found", () => { - turboIgnore(undefined, { directory: "/" }); - expectBuild(mockExit); - expect(mockConsole.error).toHaveBeenNthCalledWith( - 1, - "≫ ", - "Monorepo root not found. turbo-ignore inferencing failed" - ); - }); - - it("skips checks and allows build when TURBO_FORCE is set", () => { - process.env.TURBO_FORCE = "true"; - turboIgnore(undefined, { directory: "test-workspace" }); - expect(mockConsole.log).toHaveBeenNthCalledWith( - 2, - "≫ ", - "`TURBO_FORCE` detected" - ); - expectBuild(mockExit); - }); - - it("allows build when no comparison is returned", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = ""; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - turboIgnore("test-app", { directory: "__fixtures__/app" }); - expect(mockConsole.log).toHaveBeenNthCalledWith( - 5, - "≫ ", - 'No previous deployments found for "test-app" on branch "my-branch"' - ); - expectBuild(mockExit); - }); - - it("skips build for `previousDeploy` comparison with no changes", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "last-deployed-sha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages":[],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - turboIgnore(undefined, { directory: "__fixtures__/app" }); - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "build" as the task as it was unspecified'], - [ - "≫ ", - `Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"`, - ], - [ - "≫ ", - 'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`', - ], - ["≫ ", "This project and its dependencies are not affected"], - [expect.stringContaining("â­ Ignoring the change")], - ]); - - expectIgnore(mockExit); - mockExecSync.mockRestore(); - mockExec.mockRestore(); - }); - - it("allows build for `previousDeploy` comparison with changes", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "last-deployed-sha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages":["test-app"],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - turboIgnore(undefined, { - task: "workspace#build", - directory: "__fixtures__/app", - }); - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "workspace#build" as the task from the arguments'], - [ - "≫ ", - 'Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"', - ], - [ - "≫ ", - 'Analyzing results of `npx -y turbo@^2 run "workspace#build" --filter="test-app...[last-deployed-sha]" --dry=json`', - ], - ["≫ ", 'This commit affects "test-app"'], - [expect.stringContaining("✓ Proceeding with deployment")], - ]); - - expectBuild(mockExit); - mockExecSync.mockRestore(); - mockExec.mockRestore(); - }); - - it("allows build for `previousDeploy` comparison with single dependency change", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "last-deployed-sha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages":["test-app", "ui"],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - turboIgnore(undefined, { directory: "__fixtures__/app" }); - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "build" as the task as it was unspecified'], - [ - "≫ ", - 'Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"', - ], - [ - "≫ ", - 'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`', - ], - ["≫ ", 'This commit affects "test-app" and 1 dependency (ui)'], - [expect.stringContaining("✓ Proceeding with deployment")], - ]); - - expectBuild(mockExit); - mockExecSync.mockRestore(); - mockExec.mockRestore(); - }); - - it("allows build for `previousDeploy` comparison with multiple dependency changes", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "last-deployed-sha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages":["test-app", "ui", "tsconfig"],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - turboIgnore(undefined, { directory: "__fixtures__/app" }); - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "build" as the task as it was unspecified'], - [ - "≫ ", - 'Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"', - ], - [ - "≫ ", - 'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`', - ], - [ - "≫ ", - 'This commit affects "test-app" and 2 dependencies (ui, tsconfig)', - ], - [expect.stringContaining("✓ Proceeding with deployment")], - ]); - - expectBuild(mockExit); - mockExecSync.mockRestore(); - mockExec.mockRestore(); - }); - - it("allows build for unavailable `previousDeploy` comparison with fallback", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "last-deployed-sha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockImplementation((cmd: string) => { - if (cmd.includes("git cat-file")) { - throw new Error("fatal: Not a valid object name last-deployed-sha"); - } - return ""; - }); - - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages":["test-app"],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - turboIgnore(undefined, { - task: "workspace#build", - fallback: "HEAD^2", - directory: "__fixtures__/app", - }); - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "workspace#build" as the task from the arguments'], - [ - "≫ ", - 'Previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch" is unreachable.', - ], - ["≫ ", "Falling back to ref HEAD^2"], - [ - "≫ ", - 'Analyzing results of `npx -y turbo@^2 run "workspace#build" --filter="test-app...[HEAD^2]" --dry=json`', - ], - ["≫ ", 'This commit affects "test-app"'], - [expect.stringContaining("✓ Proceeding with deployment")], - ]); - - expectBuild(mockExit); - mockExecSync.mockRestore(); - mockExec.mockRestore(); - }); - - it("throws error and allows build when json cannot be parsed", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback(null, "stdout", "stderr") as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore(undefined, { directory: "__fixtures__/app" }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`, - expect.anything(), - expect.anything() - ); - - expect(mockConsole.error).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Failed to parse JSON output from `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`.' - ); - - expectBuild(mockExit); - mockExec.mockRestore(); - }); - - it("throws error and allows build when stdout is null", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - null as unknown as string, - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore(undefined, { directory: "__fixtures__/app" }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`, - expect.anything(), - expect.anything() - ); - - expect(mockConsole.error).toHaveBeenNthCalledWith( - 1, - "≫ ", - 'Failed to parse JSON output from `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`.' - ); - - expectBuild(mockExit); - mockExec.mockRestore(); - }); - - it("skips when commit message contains a skip string", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = "[vercel skip]"; - - turboIgnore(undefined, { directory: "__fixtures__/app" }); - - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "build" as the task as it was unspecified'], - ["≫ ", "Found commit message: [vercel skip]"], - [expect.stringContaining("â­ Ignoring the change")], - ]); - - expectIgnore(mockExit); - }); - - it("deploys when commit message contains a deploy string", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = "[vercel deploy]"; - - turboIgnore(undefined, { directory: "__fixtures__/app" }); - - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "build" as the task as it was unspecified'], - ["≫ ", "Found commit message: [vercel deploy]"], - [expect.stringContaining("✓ Proceeding with deployment")], - ]); - - expectBuild(mockExit); - }); - - it("runs full turbo-ignore check when commit message contains a conflicting string", () => { - process.env.VERCEL = "1"; - process.env.VERCEL_GIT_COMMIT_MESSAGE = "[vercel deploy] [vercel skip]"; - process.env.VERCEL_GIT_PREVIOUS_SHA = "last-deployed-sha"; - process.env.VERCEL_GIT_COMMIT_REF = "my-branch"; - - const mockExecSync = jest - .spyOn(child_process, "execSync") - .mockReturnValue("commit"); - - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages":[],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore(undefined, { directory: "__fixtures__/app" }); - - validateLogs(mockConsole.log, [ - [ - "≫ ", - "Using Turborepo to determine if this project is affected by the commit...\n", - ], - ["≫ ", 'Inferred "test-app" as workspace from "package.json"'], - ["≫ ", 'Inferred turbo version ^2 based on "tasks" in "turbo.json"'], - ["≫ ", 'Using "build" as the task as it was unspecified'], - [ - "≫ ", - "Conflicting commit messages found: [vercel deploy] and [vercel skip]", - ], - [ - "≫ ", - `Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"`, - ], - [ - "≫ ", - 'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`', - ], - ["≫ ", "This project and its dependencies are not affected"], - [expect.stringContaining("Ignoring the change")], - ]); - - expectIgnore(mockExit); - mockExecSync.mockRestore(); - mockExec.mockRestore(); - }); - - it("passes max buffer to turbo execution", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages": [],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore(undefined, { directory: "__fixtures__/app", maxBuffer: 1024 }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`, - expect.objectContaining({ maxBuffer: 1024 }), - expect.anything() - ); - - mockExec.mockRestore(); - }); - - it("runs with telemetry", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages": [],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore(undefined, { - directory: "__fixtures__/app", - maxBuffer: 1024, - telemetry, - }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`, - expect.objectContaining({ maxBuffer: 1024 }), - expect.anything() - ); - - mockExec.mockRestore(); - }); - - it("allows build if packages is missing", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore(undefined, { - directory: "__fixtures__/app", - }); - - expectBuild(mockExit); - mockExec.mockRestore(); - }); - - it("defaults to latest turbo if no hints for version", () => { - const mockExec = jest - .spyOn(child_process, "exec") - .mockImplementation((command, options, callback) => { - if (callback) { - return callback( - null, - '{"packages": [],"tasks":[]}', - "stderr" - ) as unknown as ChildProcess; - } - return {} as unknown as ChildProcess; - }); - - turboIgnore(undefined, { directory: "__fixtures__/invalid_turbo_json" }); - - expect(mockExec).toHaveBeenCalledWith( - `npx -y turbo run build --filter="test-app...[HEAD^]" --dry=json`, - expect.anything(), - expect.anything() - ); - - mockExec.mockRestore(); - }); -}); diff --git a/packages/turbo-ignore/jest.config.js b/packages/turbo-ignore/jest.config.js new file mode 100644 index 0000000000000..2b8bd07645c8c --- /dev/null +++ b/packages/turbo-ignore/jest.config.js @@ -0,0 +1,20 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: "ts-jest/presets/js-with-ts", + testEnvironment: "node", + testPathIgnorePatterns: ["/__fixtures__/"], + coveragePathIgnorePatterns: ["/__fixtures__/"], + collectCoverage: true, + coverageThreshold: { + global: { + branches: 100, + functions: 100, + lines: 100, + statements: 100, + }, + }, + modulePathIgnorePatterns: ["/node_modules", "/dist"], + transformIgnorePatterns: ["node_modules/*"], + verbose: process.env.RUNNER_DEBUG === "1", + silent: process.env.RUNNER_DEBUG !== "1", +}; diff --git a/packages/turbo-ignore/package.json b/packages/turbo-ignore/package.json index f31b585d7657f..901365909846c 100644 --- a/packages/turbo-ignore/package.json +++ b/packages/turbo-ignore/package.json @@ -26,21 +26,21 @@ "lint:prettier": "prettier -c . --cache --ignore-path=../../.prettierignore" }, "dependencies": { - "json5": "^2.2.3" + "json5": "2.2.3" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "29.7.0", "@turbo/eslint-config": "workspace:*", "@turbo/telemetry": "workspace:*", "@turbo/test-utils": "workspace:*", "@turbo/tsconfig": "workspace:*", "@turbo/types": "workspace:*", "@turbo/utils": "workspace:*", - "@types/node": "^18.17.2", - "commander": "^11.0.0", - "jest": "^29.7.0", - "ts-jest": "^29.2.5", - "tsup": "^5.12.1", - "typescript": "5.5.4" + "@types/node": "22.13.1", + "commander": "13.1.0", + "jest": "29.7.0", + "ts-jest": "29.2.5", + "tsup": "8.3.6", + "typescript": "5.7.3" } } diff --git a/packages/turbo-repository/README.md b/packages/turbo-repository/README.md deleted file mode 100644 index 94fc90378ebfd..0000000000000 --- a/packages/turbo-repository/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# `@turbo/repository` - -This package builds `@turbo/repository`, which in turn packages up some of Turborepo's repository analysis functionality -for use in a javascript context. - -The `rust/` folder contains the wrapper around core Turborepo Rust code, and should limit -itself to basic data transformations to match JS APIs. Any logic updates should preferably land in core Turborepo. - -The `js/` folder contains the meta package to handle importing platform-specific native libraries, as well as the type definitions -for the JS API. - -This package contains scripts to build dev and release versions. `pnpm build && pnpm package` will build and package a dev version of the native library for `darwin-arm64`, or you can pass an additional argument for a specific target. `pnpm build:release` will build a release version of the library - -## Setup - -Install JS dependencies: - -```sh -pnpm install -``` - -## Build - -Build native library and TypeScript wrapper: - -```sh -pnpm build -cargo build -``` - -## Test - -```sh -pnpm test -``` - -## Example Usage - -You can see examples in the `__tests__` directory, or see a simple script in `node scripts/test.mjs`. -Note that this may fall out of date over time, but it's meant to be used during the early iterations. - -## Publishing - -There is now a version bump script in [bump-version.sh](./scripts/bump-version.sh). Passing it the new version will bump the meta package version, as well as the optional dependencies list and native packages. diff --git a/packages/turbo-repository/__tests__/affected-packages.test.ts b/packages/turbo-repository/__tests__/affected-packages.test.ts deleted file mode 100644 index 4cb62e0b50f6b..0000000000000 --- a/packages/turbo-repository/__tests__/affected-packages.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { describe, it } from "node:test"; -import { strict as assert } from "node:assert"; -import * as path from "node:path"; -import { Workspace, Package, PackageManager } from "../js/dist/index.js"; - -type PackageReduced = Pick; - -interface AffectedPackagesTestParams { - description: string; - files: string[]; - changedLockfile?: string | undefined | null; - expected: PackageReduced[]; -} - -describe("affectedPackages", () => { - const tests: AffectedPackagesTestParams[] = [ - { - description: "app change", - files: ["apps/app/file.txt"], - expected: [{ name: "app-a", relativePath: "apps/app" }], - }, - { - description: "lib change", - files: ["packages/ui/a.txt"], - expected: [{ name: "ui", relativePath: "packages/ui" }], - }, - { - description: "global change", - files: ["package.json"], - expected: [ - { name: "app-a", relativePath: "apps/app" }, - { name: "ui", relativePath: "packages/ui" }, - ], - }, - { - description: - "a lockfile change will only affect packages impacted by the change", - files: [], - changedLockfile: `lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: {} - - apps/app: - dependencies: - microdiff: - specifier: ^1.4.0 - version: 1.5.0 - ui: - specifier: workspace:* - version: link:../../packages/ui - - packages/blank: {} - - packages/ui: {} - -packages: - - /microdiff@1.5.0: - resolution: {integrity: sha512-Drq+/THMvDdzRYrK0oxJmOKiC24ayUV8ahrt8l3oRK51PWt6gdtrIGrlIH3pT/lFh1z93FbAcidtsHcWbnRz8Q==} - dev: false -`, - expected: [{ name: "app-a", relativePath: "apps/app" }], - }, - ]; - - for (const { description, files, expected, changedLockfile } of tests) { - it(description, async () => { - const dir = path.resolve(__dirname, "./fixtures/monorepo"); - const workspace = await Workspace.find(dir); - - const reduced: PackageReduced[] = ( - await workspace.affectedPackages(files, changedLockfile) - ).map((pkg) => { - return { - name: pkg.name, - relativePath: pkg.relativePath, - }; - }); - - assert.deepEqual(reduced, expected); - }); - } -}); diff --git a/packages/turbo-repository/__tests__/find-packages.test.ts b/packages/turbo-repository/__tests__/find-packages.test.ts deleted file mode 100644 index 0d9c43ebd91f6..0000000000000 --- a/packages/turbo-repository/__tests__/find-packages.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { describe, it } from "node:test"; -import { strict as assert } from "node:assert"; -import * as path from "node:path"; -import { Workspace, Package } from "../js/dist/index.js"; - -describe("findPackages", () => { - it("enumerates packages", async () => { - const workspace = await Workspace.find("./fixtures/monorepo"); - const packages: Package[] = await workspace.findPackages(); - assert.notEqual(packages.length, 0); - }); - - it("returns a package graph", async () => { - const dir = path.resolve(__dirname, "./fixtures/monorepo"); - const workspace = await Workspace.find(dir); - const packages = await workspace.findPackagesWithGraph(); - - assert.equal(Object.keys(packages).length, 2); - - const pkg1 = packages["apps/app"]; - const pkg2 = packages["packages/ui"]; - - assert.deepEqual(pkg1.dependencies, ["packages/ui"]); - assert.deepEqual(pkg1.dependents, []); - - assert.deepEqual(pkg2.dependencies, []); - assert.deepEqual(pkg2.dependents, ["apps/app"]); - }); -}); diff --git a/packages/turbo-repository/__tests__/fixtures/monorepo/apps/app/package.json b/packages/turbo-repository/__tests__/fixtures/monorepo/apps/app/package.json deleted file mode 100644 index 6b7095cdbdb27..0000000000000 --- a/packages/turbo-repository/__tests__/fixtures/monorepo/apps/app/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "app-a", - "dependencies": { - "microdiff": "^1.4.0", - "ui": "workspace:*" - } -} diff --git a/packages/turbo-repository/__tests__/fixtures/monorepo/package.json b/packages/turbo-repository/__tests__/fixtures/monorepo/package.json deleted file mode 100644 index 409bceb9ac7dd..0000000000000 --- a/packages/turbo-repository/__tests__/fixtures/monorepo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "basic", - "packageManager": "pnpm@8.14.0" -} diff --git a/packages/turbo-repository/__tests__/fixtures/monorepo/packages/blank/package.json b/packages/turbo-repository/__tests__/fixtures/monorepo/packages/blank/package.json deleted file mode 100644 index b0de282a25e06..0000000000000 --- a/packages/turbo-repository/__tests__/fixtures/monorepo/packages/blank/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "//": "missing name field in this package.json" -} diff --git a/packages/turbo-repository/__tests__/fixtures/monorepo/packages/ui/package.json b/packages/turbo-repository/__tests__/fixtures/monorepo/packages/ui/package.json deleted file mode 100644 index 1cd75b539ecc2..0000000000000 --- a/packages/turbo-repository/__tests__/fixtures/monorepo/packages/ui/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "ui" -} diff --git a/packages/turbo-repository/__tests__/fixtures/monorepo/pnpm-lock.yaml b/packages/turbo-repository/__tests__/fixtures/monorepo/pnpm-lock.yaml deleted file mode 100644 index c7d50d6e90e75..0000000000000 --- a/packages/turbo-repository/__tests__/fixtures/monorepo/pnpm-lock.yaml +++ /dev/null @@ -1,28 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: {} - - apps/app: - dependencies: - microdiff: - specifier: ^1.4.0 - version: 1.4.0 - ui: - specifier: workspace:* - version: link:../../packages/ui - - packages/blank: {} - - packages/ui: {} - -packages: - - /microdiff@1.4.0: - resolution: {integrity: sha512-OBKBOa1VBznvLPb/3ljeJaENVe0fO0lnWl77lR4vhPlQD71UpjEoRV5P0KdQkcjbFlBu1Oy2mEUBMU3wxcBAGg==} - dev: false diff --git a/packages/turbo-repository/__tests__/fixtures/monorepo/pnpm-workspace.yaml b/packages/turbo-repository/__tests__/fixtures/monorepo/pnpm-workspace.yaml deleted file mode 100644 index 4839fcf0810d5..0000000000000 --- a/packages/turbo-repository/__tests__/fixtures/monorepo/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -packages: - - apps/** - - packages/** diff --git a/packages/turbo-repository/__tests__/workspace.test.ts b/packages/turbo-repository/__tests__/workspace.test.ts deleted file mode 100644 index f9f351be880d4..0000000000000 --- a/packages/turbo-repository/__tests__/workspace.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { describe, it } from "node:test"; -import { strict as assert } from "node:assert"; -import * as path from "node:path"; -import { Workspace, PackageManager } from "../js/dist/index.js"; - -describe("Workspace", () => { - it("finds a workspace", async () => { - const workspace = await Workspace.find(); - const expectedRoot = path.resolve(__dirname, "../../.."); - assert.equal(workspace.absolutePath, expectedRoot); - }); - - it("finds a package manager", async () => { - const workspace = await Workspace.find(); - const packageManager: PackageManager = workspace.packageManager; - assert.equal(packageManager.name, "pnpm"); - }); -}); diff --git a/packages/turbo-repository/js/README.md b/packages/turbo-repository/js/README.md deleted file mode 100644 index fe449aa156951..0000000000000 --- a/packages/turbo-repository/js/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## Repositories - -Provides JS repository analysis functionality, scoped to the JS ecosystem. - -Note that this is not yet a stable package, and functionality, API, and naming may all change. - -## Development Notes - -1. The `.d.ts` file generated by NAPI is checked in, but not considered the definitive types to publish. We can give better details by adding our own edits on top of it. As a consequence, any PR that edits `index-generated.d.ts` will also need to edit `index.d.ts`. -2. If new exports are added, `index.js` will need to be updated as well. diff --git a/packages/turbo-repository/package.json b/packages/turbo-repository/package.json index ce0a41bc16e43..f5ad04ba18bcf 100644 --- a/packages/turbo-repository/package.json +++ b/packages/turbo-repository/package.json @@ -1,38 +1,30 @@ { - "name": "turborepo-repository", - "version": "0.0.1", - "description": "", - "bugs": "https://github.com/vercel/turborepo/issues", - "homepage": "https://turbo.build/repo", - "scripts": { - "build": "bash scripts/build.sh", - "build:release": "bash scripts/build.sh release", - "package": "node scripts/publish.mjs", - "test": "node --import tsx --test __tests__/*.test.ts" - }, - "keywords": [], - "author": "", - "license": "MIT", - "devDependencies": { - "@napi-rs/cli": "^2.16.3", - "execa": "^8.0.1", - "fs-extra": "^11.1.1", - "prettier": "^3.2.5", - "tsx": "4.19.1" - }, - "main": "dist/index.js", - "napi": { - "name": "@turbo/repository", - "triples": { - "defaults": true, - "additional": [ - "x86_64-apple-darwin", - "aarch64-apple-darwin", - "x86_64-unknown-linux-gnu", - "aarch64-unknown-linux-gnu", - "x86_64-pc-windows-msvc", - "aarch64-pc-windows-msvc" - ] - } - } + "name": "turborepo-repository", + "description": "", + "main": "dist/index.js", + "scripts": { + "build": "bash scripts/build.sh", + "build:release": "bash scripts/build.sh release" + }, + "dependencies": {}, + "devDependencies": { + "@napi-rs/cli": "2.18.4", + "execa": "9.5.2", + "fs-extra": "11.3.0", + "tsx": "4.19.2" + }, + "napi": { + "name": "@turbo/repository", + "triples": { + "additional": [ + "x86_64-apple-darwin", + "aarch64-apple-darwin", + "x86_64-unknown-linux-gnu", + "aarch64-unknown-linux-gnu", + "x86_64-pc-windows-msvc", + "aarch64-pc-windows-msvc" + ], + "defaults": true + } + } } diff --git a/packages/turbo-repository/rust/Cargo.toml b/packages/turbo-repository/rust/Cargo.toml index 6a97de05ced1e..65027bce67274 100644 --- a/packages/turbo-repository/rust/Cargo.toml +++ b/packages/turbo-repository/rust/Cargo.toml @@ -1,14 +1,5 @@ -[package] -name = "turborepo-napi" -version = "0.1.0" -edition = "2021" -license = "MIT" - -[lib] -crate-type = ["cdylib"] - -[lints] -workspace = true +[build-dependencies] +napi-build = "2.0.1" [dependencies] napi = { version = "2.14.0", features = ["tokio_rt"] } @@ -21,10 +12,18 @@ turborepo-repository = { workspace = true } [dev-dependencies] pretty_assertions = { workspace = true } -[build-dependencies] -napi-build = "2.0.1" - [features] -# The napi proc macro expands to include this feature, forward it correct feature -# to avoid the lint warning. noop = ["napi-derive/noop"] + +[lib] +crate-type = ["cdylib"] +path = "Source/lib.rs" + +[lints] +workspace = true + +[package] +edition = "2021" +license-file = "LICENSE" +name = "turborepo-napi" +version = "0.1.0" diff --git a/packages/turbo-repository/rust/README.md b/packages/turbo-repository/rust/README.md deleted file mode 100644 index 2a58ba84c2a81..0000000000000 --- a/packages/turbo-repository/rust/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# `turbo-repository` - -This sub-crate provides repository helpers which are written in Rust and translated to TypeScript with [NAPI-RS](https://napi.rs). - -See the [root `README.md` for instructions](../README.md). diff --git a/packages/turbo-repository/rust/Source/internal.rs b/packages/turbo-repository/rust/Source/internal.rs new file mode 100644 index 0000000000000..02f59fc894bfd --- /dev/null +++ b/packages/turbo-repository/rust/Source/internal.rs @@ -0,0 +1,125 @@ +use napi::Status; +use thiserror::Error; +use turbopath::{AbsoluteSystemPathBuf, PathError}; +use turborepo_repository::{ + inference::{self, RepoMode as WorkspaceType, RepoState as WorkspaceState}, + package_graph::PackageGraphBuilder, + package_json::PackageJson, + package_manager, +}; + +use crate::{Package, PackageManager, Workspace}; + +/// This module is used to isolate code with defined errors +/// from code in lib.rs that needs to have errors coerced to strings / +/// napi::Error for return to javascript. +/// Dividing the source code up this way allows us to be stricter here, and have +/// the strictness relaxed only at the boundary. + +#[derive(Debug, Error)] +pub(crate) enum Error { + #[error("Failed to resolve starting path from {path}: {path_error}")] + StartingPath { path_error:PathError, path:String }, + #[error(transparent)] + Inference(#[from] inference::Error), + #[error("Failed to resolve package manager from {path}: {error}")] + PackageManager { error:String, path:AbsoluteSystemPathBuf }, + #[error("Failed to discover packages from root {workspace_root}: {error}")] + PackageJsons { error:package_manager::Error, workspace_root:AbsoluteSystemPathBuf }, + #[error("Package directory {0} has no parent")] + MissingParent(AbsoluteSystemPathBuf), + #[error("Package graph error: {0}")] + PackageGraph(#[from] turborepo_repository::package_graph::Error), + #[error("package.json error: {0}")] + PackageJson(#[from] turborepo_repository::package_json::Error), +} + +impl From for napi::Error { + fn from(value:Error) -> Self { napi::Error::from_reason(value.to_string()) } +} + +impl Workspace { + pub(crate) async fn find_internal(path:Option) -> Result { + let reference_dir = path + .map(|path| { + AbsoluteSystemPathBuf::from_cwd(&path) + .map_err(|path_error| Error::StartingPath { path:path.clone(), path_error }) + }) + .unwrap_or_else(|| { + AbsoluteSystemPathBuf::cwd() + .map_err(|path_error| Error::StartingPath { path:"".to_string(), path_error }) + })?; + let workspace_state = WorkspaceState::infer(&reference_dir)?; + let is_multi_package = workspace_state.mode == WorkspaceType::MultiPackage; + let package_manager_name = workspace_state + .package_manager + .as_ref() + .map_err(|error| { + Error::PackageManager { error:error.to_string(), path:workspace_state.root.clone() } + })? + .name(); + + let workspace_root = &workspace_state.root; + let root_package_json = PackageJson::load(&workspace_root.join_component("package.json"))?; + let package_graph = PackageGraphBuilder::new(workspace_root, root_package_json) + .with_single_package_mode(!is_multi_package) + .build() + .await?; + + Ok(Self { + absolute_path:workspace_state.root.to_string(), + workspace_state, + is_multi_package, + package_manager:PackageManager { name:package_manager_name.to_string() }, + graph:package_graph, + }) + } + + pub(crate) async fn packages_internal(&self) -> Result, Error> { + // Note: awkward error handling because we memoize the error from package + // manager discovery. That probably isn't the best design. We should + // address it when we decide how we want to handle possibly finding a + // repo root but not finding a package manager. + let package_manager = self.workspace_state.package_manager.as_ref().map_err(|error| { + Error::PackageManager { + error:error.to_string(), + path:self.workspace_state.root.clone(), + } + })?; + + let package_manager = package_manager.clone(); + let workspace_root = self.workspace_state.root.clone(); + + let package_json_paths = + tokio::task::spawn(async move { package_manager.get_package_jsons(&workspace_root) }) + .await + .expect("package enumeration should not crash") + .map_err(|error| { + Error::PackageJsons { error, workspace_root:self.workspace_state.root.clone() } + })?; + + let packages = package_json_paths + .filter_map(|path| { + // Return an error if we fail to load the package.json + let pkg_json = match PackageJson::load(&path) { + Ok(pkg) => pkg, + Err(err) => return Some(Err(err.into())), + }; + + // Skip packages that don't have names + let name = pkg_json.name?; + + // Get the package path and turn it into a package + // Error if we fail to get the package path (parent to + // package_json_path) + path.parent() + .map(|package_path| { + Ok(Package::new(name, &self.workspace_state.root, package_path)) + }) + .or_else(|| Some(Err(Error::MissingParent(path.to_owned())))) + }) + .collect::, Error>>()?; + + Ok(packages) + } +} diff --git a/packages/turbo-repository/rust/src/lib.rs b/packages/turbo-repository/rust/Source/lib.rs similarity index 100% rename from packages/turbo-repository/rust/src/lib.rs rename to packages/turbo-repository/rust/Source/lib.rs diff --git a/packages/turbo-repository/rust/build.rs b/packages/turbo-repository/rust/build.rs index 1265cec440d89..877a9b3538bbe 100644 --- a/packages/turbo-repository/rust/build.rs +++ b/packages/turbo-repository/rust/build.rs @@ -1,15 +1,15 @@ fn main() { - #[cfg(not(target_os = "macos"))] - napi_build::setup(); + #[cfg(not(target_os = "macos"))] + napi_build::setup(); - // This is a workaround for napi always including a GCC specific flag. - #[cfg(target_os = "macos")] - { - println!("cargo:rerun-if-env-changed=DEBUG_GENERATED_CODE"); - println!("cargo:rerun-if-env-changed=TYPE_DEF_TMP_PATH"); - println!("cargo:rerun-if-env-changed=CARGO_CFG_NAPI_RS_CLI_VERSION"); + // This is a workaround for napi always including a GCC specific flag. + #[cfg(target_os = "macos")] + { + println!("cargo:rerun-if-env-changed=DEBUG_GENERATED_CODE"); + println!("cargo:rerun-if-env-changed=TYPE_DEF_TMP_PATH"); + println!("cargo:rerun-if-env-changed=CARGO_CFG_NAPI_RS_CLI_VERSION"); - println!("cargo:rustc-cdylib-link-arg=-undefined"); - println!("cargo:rustc-cdylib-link-arg=dynamic_lookup"); - } + println!("cargo:rustc-cdylib-link-arg=-undefined"); + println!("cargo:rustc-cdylib-link-arg=dynamic_lookup"); + } } diff --git a/packages/turbo-repository/rust/src/internal.rs b/packages/turbo-repository/rust/src/internal.rs deleted file mode 100644 index 2bd5c72d58a3a..0000000000000 --- a/packages/turbo-repository/rust/src/internal.rs +++ /dev/null @@ -1,143 +0,0 @@ -use napi::Status; -use thiserror::Error; -use turbopath::{AbsoluteSystemPathBuf, PathError}; -use turborepo_repository::{ - inference::{self, RepoMode as WorkspaceType, RepoState as WorkspaceState}, - package_graph::PackageGraphBuilder, - package_json::PackageJson, - package_manager, -}; - -use crate::{Package, PackageManager, Workspace}; - -/// This module is used to isolate code with defined errors -/// from code in lib.rs that needs to have errors coerced to strings / -/// napi::Error for return to javascript. -/// Dividing the source code up this way allows us to be stricter here, and have -/// the strictness relaxed only at the boundary. - -#[derive(Debug, Error)] -pub(crate) enum Error { - #[error("Failed to resolve starting path from {path}: {path_error}")] - StartingPath { path_error: PathError, path: String }, - #[error(transparent)] - Inference(#[from] inference::Error), - #[error("Failed to resolve package manager from {path}: {error}")] - PackageManager { - error: String, - path: AbsoluteSystemPathBuf, - }, - #[error("Failed to discover packages from root {workspace_root}: {error}")] - PackageJsons { - error: package_manager::Error, - workspace_root: AbsoluteSystemPathBuf, - }, - #[error("Package directory {0} has no parent")] - MissingParent(AbsoluteSystemPathBuf), - #[error("Package graph error: {0}")] - PackageGraph(#[from] turborepo_repository::package_graph::Error), - #[error("package.json error: {0}")] - PackageJson(#[from] turborepo_repository::package_json::Error), -} - -impl From for napi::Error { - fn from(value: Error) -> Self { - napi::Error::from_reason(value.to_string()) - } -} - -impl Workspace { - pub(crate) async fn find_internal(path: Option) -> Result { - let reference_dir = path - .map(|path| { - AbsoluteSystemPathBuf::from_cwd(&path).map_err(|path_error| Error::StartingPath { - path: path.clone(), - path_error, - }) - }) - .unwrap_or_else(|| { - AbsoluteSystemPathBuf::cwd().map_err(|path_error| Error::StartingPath { - path: "".to_string(), - path_error, - }) - })?; - let workspace_state = WorkspaceState::infer(&reference_dir)?; - let is_multi_package = workspace_state.mode == WorkspaceType::MultiPackage; - let package_manager_name = workspace_state - .package_manager - .as_ref() - .map_err(|error| Error::PackageManager { - error: error.to_string(), - path: workspace_state.root.clone(), - })? - .name(); - - let workspace_root = &workspace_state.root; - let root_package_json = PackageJson::load(&workspace_root.join_component("package.json"))?; - let package_graph = PackageGraphBuilder::new(workspace_root, root_package_json) - .with_single_package_mode(!is_multi_package) - .build() - .await?; - - Ok(Self { - absolute_path: workspace_state.root.to_string(), - workspace_state, - is_multi_package, - package_manager: PackageManager { - name: package_manager_name.to_string(), - }, - graph: package_graph, - }) - } - - pub(crate) async fn packages_internal(&self) -> Result, Error> { - // Note: awkward error handling because we memoize the error from package - // manager discovery. That probably isn't the best design. We should - // address it when we decide how we want to handle possibly finding a - // repo root but not finding a package manager. - let package_manager = self - .workspace_state - .package_manager - .as_ref() - .map_err(|error| Error::PackageManager { - error: error.to_string(), - path: self.workspace_state.root.clone(), - })?; - - let package_manager = package_manager.clone(); - let workspace_root = self.workspace_state.root.clone(); - - let package_json_paths = - tokio::task::spawn(async move { package_manager.get_package_jsons(&workspace_root) }) - .await - .expect("package enumeration should not crash") - .map_err(|error| Error::PackageJsons { - error, - workspace_root: self.workspace_state.root.clone(), - })?; - - let packages = package_json_paths - .filter_map(|path| { - // Return an error if we fail to load the package.json - let pkg_json = match PackageJson::load(&path) { - Ok(pkg) => pkg, - Err(err) => return Some(Err(err.into())), - }; - - // Skip packages that don't have names - let name = pkg_json.name?; - - // Get the package path and turn it into a package - // Error if we fail to get the package path (parent to - // package_json_path) - path.parent() - .map(|package_path| { - Ok(Package::new(name, &self.workspace_state.root, package_path)) - }) - .or_else(|| Some(Err(Error::MissingParent(path.to_owned())))) - }) - .collect::, Error>>()?; - - Ok(packages) - } -} diff --git a/packages/turbo-repository/scripts/build.sh b/packages/turbo-repository/scripts/build.sh index 418e862b67491..d58fedb3648d7 100755 --- a/packages/turbo-repository/scripts/build.sh +++ b/packages/turbo-repository/scripts/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash flags="\ --platform \ diff --git a/packages/turbo-repository/scripts/bump-version.sh b/packages/turbo-repository/scripts/bump-version.sh index a133c0d3dfa5f..0f96eea191f9a 100755 --- a/packages/turbo-repository/scripts/bump-version.sh +++ b/packages/turbo-repository/scripts/bump-version.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/packages/turbo-telemetry/.eslintrc.js b/packages/turbo-telemetry/.eslintrc.js deleted file mode 100644 index a6e3310c0c4f5..0000000000000 --- a/packages/turbo-telemetry/.eslintrc.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], - overrides: [ - { - files: ["src/utils.ts"], - rules: { - "import/no-default-export": "off", - }, - }, - { - files: ["src/**/*.test.ts"], - rules: { - // https://github.com/nodejs/node/issues/51292 - "@typescript-eslint/no-floating-promises": "off", - "@typescript-eslint/no-unsafe-member-access": "off", - "@typescript-eslint/no-unsafe-argument": "off", - }, - }, - ], -}; diff --git a/packages/turbo-telemetry/README.md b/packages/turbo-telemetry/README.md deleted file mode 100644 index 8bd44dc7ac96b..0000000000000 --- a/packages/turbo-telemetry/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# `@turbo/telemetry` - -**NOTE**: -This package is a direct port of the [turbo-telemetry](https://github.com/vercel/turborepo/blob/main/crates/turborepo-telemetry) crate. -Any changes made here should also be made to that crate as well. - -## Overview - -This package provides a way to optionally record anonymous usage data that originates from the turborepo node packages. -This information is used to shape the Turborepo roadmap and prioritize features. You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the [documentation](https://turbo.build/repo/docs/telemetry): - -## Events - -Each package must create a subclass of the main telemetry client and implement specific methods for each telemetry event. All recorded events can be found by browsing the [packages classes](./src/events). - -## Usage - -1. Init the client with your package name and version: - -```ts -import { initTelemetry } from "@turbo/telemetry"; -import pkgJson from "../package.json"; - -const { telemetry } = await initTelemetry({ - name: pkgJson.name, - version: pkgJson.version, -}); -``` - -2. Send events - -```ts -telemetry.myCustomEventName({ - // event properties -}); -``` - -3. Close the client before exiting - -```ts -await telemetry.close(); -``` diff --git a/packages/turbo-telemetry/src/cli.ts b/packages/turbo-telemetry/Source/cli.ts similarity index 100% rename from packages/turbo-telemetry/src/cli.ts rename to packages/turbo-telemetry/Source/cli.ts diff --git a/packages/turbo-telemetry/src/client.ts b/packages/turbo-telemetry/Source/client.ts similarity index 100% rename from packages/turbo-telemetry/src/client.ts rename to packages/turbo-telemetry/Source/client.ts diff --git a/packages/turbo-telemetry/src/config.ts b/packages/turbo-telemetry/Source/config.ts similarity index 100% rename from packages/turbo-telemetry/src/config.ts rename to packages/turbo-telemetry/Source/config.ts diff --git a/packages/turbo-telemetry/src/events/create-turbo.ts b/packages/turbo-telemetry/Source/events/create-turbo.ts similarity index 100% rename from packages/turbo-telemetry/src/events/create-turbo.ts rename to packages/turbo-telemetry/Source/events/create-turbo.ts diff --git a/packages/turbo-telemetry/src/events/turbo-ignore.ts b/packages/turbo-telemetry/Source/events/turbo-ignore.ts similarity index 100% rename from packages/turbo-telemetry/src/events/turbo-ignore.ts rename to packages/turbo-telemetry/Source/events/turbo-ignore.ts diff --git a/packages/turbo-telemetry/src/events/types.ts b/packages/turbo-telemetry/Source/events/types.ts similarity index 100% rename from packages/turbo-telemetry/src/events/types.ts rename to packages/turbo-telemetry/Source/events/types.ts diff --git a/packages/turbo-telemetry/src/index.ts b/packages/turbo-telemetry/Source/index.ts similarity index 100% rename from packages/turbo-telemetry/src/index.ts rename to packages/turbo-telemetry/Source/index.ts diff --git a/packages/turbo-telemetry/src/init.ts b/packages/turbo-telemetry/Source/init.ts similarity index 100% rename from packages/turbo-telemetry/src/init.ts rename to packages/turbo-telemetry/Source/init.ts diff --git a/packages/turbo-telemetry/src/utils.ts b/packages/turbo-telemetry/Source/utils.ts similarity index 100% rename from packages/turbo-telemetry/src/utils.ts rename to packages/turbo-telemetry/Source/utils.ts diff --git a/packages/turbo-telemetry/package.json b/packages/turbo-telemetry/package.json index fecacb3b20c33..c7bceb6cb79ef 100644 --- a/packages/turbo-telemetry/package.json +++ b/packages/turbo-telemetry/package.json @@ -1,47 +1,26 @@ { - "name": "@turbo/telemetry", - "version": "0.0.0", - "private": true, - "description": "", - "homepage": "https://turbo.build/repo", - "keywords": [], - "author": "Vercel", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/vercel/turborepo", - "directory": "packages/turbo-telemetry" - }, - "bugs": { - "url": "https://github.com/vercel/turborepo/issues" - }, - "module": "src/index.ts", - "main": "src/index.ts", - "types": "src/index.ts", - "scripts": { - "test": "node --import tsx --test src/*.test.ts", - "lint": "eslint src/", - "check-types": "tsc --noEmit", - "lint:prettier": "prettier -c . --cache --ignore-path=../../.prettierignore" - }, - "dependencies": { - "ci-info": "^4.0.0", - "got": "^11.8.6", - "picocolors": "1.0.1", - "zod": "^3.22.4" - }, - "devDependencies": { - "@turbo/eslint-config": "workspace:*", - "@turbo/test-utils": "workspace:*", - "@turbo/tsconfig": "workspace:*", - "@turbo/types": "workspace:*", - "@turbo/utils": "workspace:*", - "@types/node": "^20.11.30", - "dirs-next": "0.0.1-canary.1", - "tsx": "4.19.1", - "typescript": "5.5.4" - }, - "peerDependencies": { - "commander": "^11.0.0" - } + "name": "@turbo/telemetry", + "description": "", + "main": "src/index.ts", + "module": "src/index.ts", + "types": "src/index.ts", + "scripts": { + "check-types": "tsc --noEmit" + }, + "dependencies": { + "ci-info": "4.1.0", + "got": "14.4.6", + "picocolors": "1.1.1", + "zod": "3.24.2" + }, + "devDependencies": { + "@turbo/eslint-config": "workspace:*", + "@turbo/test-utils": "workspace:*", + "@turbo/tsconfig": "workspace:*", + "@turbo/types": "workspace:*", + "@turbo/utils": "workspace:*", + "@types/node": "22.13.1", + "dirs-next": "0.0.1-canary.1", + "tsx": "4.19.2" + } } diff --git a/packages/turbo-telemetry/src/client.test.ts b/packages/turbo-telemetry/src/client.test.ts deleted file mode 100644 index 48065274811dd..0000000000000 --- a/packages/turbo-telemetry/src/client.test.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { describe, it, mock, beforeEach } from "node:test"; -import { strict as assert } from "node:assert"; -import got from "got"; -import { TelemetryClient } from "./client"; -import { TelemetryConfig } from "./config"; - -describe("TelemetryClient", () => { - beforeEach(() => { - mock.reset(); - }); - - it("sends request when batch size is reached", (t) => { - const mockPost = mock.fn(); - t.mock.method(got, "post", mockPost); - const config = new TelemetryConfig({ - configPath: "test-config-path", - config: { - telemetry_enabled: true, - telemetry_id: "telemetry-test-id", - telemetry_salt: "telemetry-salt", - }, - }); - - const client = new TelemetryClient({ - api: "https://example.com", - packageInfo: { - name: "create-turbo", - version: "1.0.0", - }, - config, - opts: { - batchSize: 2, - }, - }); - - // add two events to trigger the batch flush - client.trackCommandStatus({ - command: "test-command", - status: "start", - }); - client.trackCommandStatus({ - command: "test-command", - status: "end", - }); - - assert.equal(mockPost.mock.callCount() > 0, true); - - assert.deepEqual( - mockPost.mock.calls[0].arguments[0], - "https://example.com/api/turborepo/v1/events" - ); - - assert.equal(mockPost.mock.calls[0].arguments[1].json.length, 2); - assert.deepEqual( - Object.keys(mockPost.mock.calls[0].arguments[1].json[0].package), - ["id", "key", "value", "package_name", "package_version", "parent_id"] - ); - - assert.equal( - typeof mockPost.mock.calls[0].arguments[1].json[0].package.id, - "string" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.key, - "command:test-command" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.value, - "start" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.package_name, - "create-turbo" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.package_version, - "1.0.0" - ); - - assert.deepEqual( - Object.keys(mockPost.mock.calls[0].arguments[1].json[1].package), - ["id", "key", "value", "package_name", "package_version", "parent_id"] - ); - assert.equal( - typeof mockPost.mock.calls[0].arguments[1].json[1].package.id, - "string" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[1].package.key, - "command:test-command" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[1].package.value, - "end" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[1].package.package_name, - "create-turbo" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[1].package.package_version, - "1.0.0" - ); - - assert.equal( - "x-turbo-session-id" in mockPost.mock.calls[0].arguments[1].headers, - true - ); - assert.equal( - "x-turbo-telemetry-id" in mockPost.mock.calls[0].arguments[1].headers, - true - ); - assert.equal( - /create-turbo 1\.0\.0/.test( - mockPost.mock.calls[0].arguments[1].headers["User-Agent"] - ), - true - ); - - assert.equal(client.hasPendingEvents(), false); - }); - - it("does not send request before batch size is reached", (t) => { - const mockPost = mock.fn(); - t.mock.method(got, "post", mockPost); - - const config = new TelemetryConfig({ - configPath: "test-config-path", - config: { - telemetry_enabled: true, - telemetry_id: "telemetry-test-id", - telemetry_salt: "telemetry-salt", - }, - }); - - const client = new TelemetryClient({ - api: "https://example.com", - packageInfo: { - name: "create-turbo", - version: "1.0.0", - }, - config, - }); - - client.trackCommandStatus({ - command: "test-command", - status: "start", - }); - assert.equal(mockPost.mock.callCount(), 0); - assert.equal(client.hasPendingEvents(), true); - }); - - it("does not send request if telemetry is disabled", (t) => { - const mockPost = mock.fn(); - t.mock.method(got, "post", mockPost); - const config = new TelemetryConfig({ - configPath: "test-config-path", - config: { - telemetry_enabled: false, - telemetry_id: "telemetry-test-id", - telemetry_salt: "telemetry-salt", - }, - }); - - const client = new TelemetryClient({ - api: "https://example.com", - packageInfo: { - name: "create-turbo", - version: "1.0.0", - }, - config, - }); - - client.trackCommandStatus({ - command: "test-command", - status: "start", - }); - assert.equal(mockPost.mock.callCount(), 0); - assert.equal(client.hasPendingEvents(), false); - }); - - it("flushes events when closed even if batch size is not reached", async (t) => { - const mockPost = mock.fn((_url, _opts) => { - // do nothing with either arg - }); - t.mock.method(got, "post", mockPost); - - const config = new TelemetryConfig({ - configPath: "test-config-path", - config: { - telemetry_enabled: true, - telemetry_id: "telemetry-test-id", - telemetry_salt: "telemetry-salt", - }, - }); - - const client = new TelemetryClient({ - api: "https://example.com", - packageInfo: { - name: "create-turbo", - version: "1.0.0", - }, - config, - opts: { - batchSize: 2, - }, - }); - - // add one event - client.trackCommandStatus({ - command: "test-command", - status: "start", - }); - - assert.equal(mockPost.mock.callCount(), 0); - - await client.close(); - - assert.equal(mockPost.mock.callCount(), 1); - assert.equal( - mockPost.mock.calls[0].arguments[0], - "https://example.com/api/turborepo/v1/events" - ); - - assert.equal(mockPost.mock.calls[0].arguments[1].json.length, 1); - assert.deepEqual( - Object.keys(mockPost.mock.calls[0].arguments[1].json[0].package), - ["id", "key", "value", "package_name", "package_version", "parent_id"] - ); - assert.equal( - typeof mockPost.mock.calls[0].arguments[1].json[0].package.id, - "string" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.key, - "command:test-command" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.value, - "start" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.package_name, - "create-turbo" - ); - assert.equal( - mockPost.mock.calls[0].arguments[1].json[0].package.package_version, - "1.0.0" - ); - - assert.equal( - "x-turbo-session-id" in mockPost.mock.calls[0].arguments[1].headers, - true - ); - assert.equal( - "x-turbo-telemetry-id" in mockPost.mock.calls[0].arguments[1].headers, - true - ); - - assert.match( - mockPost.mock.calls[0].arguments[1].headers["User-Agent"], - /create-turbo 1\.0\.0/ - ); - - assert.equal(client.hasPendingEvents(), false); - }); -}); diff --git a/packages/turbo-telemetry/src/config.test.ts b/packages/turbo-telemetry/src/config.test.ts deleted file mode 100644 index e1ad778cb1afa..0000000000000 --- a/packages/turbo-telemetry/src/config.test.ts +++ /dev/null @@ -1,455 +0,0 @@ -import { describe, it, mock, afterEach, beforeEach } from "node:test"; -import { strict as assert } from "node:assert"; -import fs from "node:fs"; -import { TelemetryConfig } from "./config"; -import utils from "./utils"; - -describe("TelemetryConfig", () => { - let telemetryConfig: TelemetryConfig; - - beforeEach(() => { - telemetryConfig = new TelemetryConfig({ - configPath: "/path/to/config.json", - config: { - telemetry_enabled: true, - telemetry_id: "123456", - telemetry_salt: "private-salt", - }, - }); - }); - - afterEach(() => { - mock.reset(); - - delete process.env.DO_NOT_TRACK; - delete process.env.TURBO_TELEMETRY_DISABLED; - delete process.env.TURBO_TELEMETRY_MESSAGE_DISABLED; - delete process.env.TURBO_TELEMETRY_DEBUG; - }); - - describe("fromDefaultConfig", () => { - it("should create TelemetryConfig instance from default config", async (t) => { - const mockConfigPath = "/path/to/defaultConfig.json"; - const mockFileContent = JSON.stringify({ - telemetry_enabled: true, - telemetry_id: "654321", - telemetry_salt: "default-salt", - }); - - const mockDefaultConfigPath = mock.fn(() => mockConfigPath); - const mockReadFileSync = mock.fn(() => mockFileContent); - - t.mock.method(utils, "defaultConfigPath", mockDefaultConfigPath); - t.mock.method(fs, "readFileSync", mockReadFileSync); - - const result = await TelemetryConfig.fromDefaultConfig(); - - assert.equal(mockDefaultConfigPath.mock.calls.length > 0, true); - assert.deepEqual(mockReadFileSync.mock.calls[0].arguments, [ - mockConfigPath, - "utf-8", - ]); - assert.equal(result instanceof TelemetryConfig, true); - assert.equal(result?.id, "654321"); - }); - - it("should generate new config if default config doesn't exist", async (t) => { - const mockConfigPath = "/path/to/defaultConfig.json"; - const mockDefaultConfigPath = mock.fn(() => mockConfigPath); - const mockReadFileSync = mock.fn(() => { - throw new Error("File not found"); - }); - const mockRmSync = mock.fn(); - const mockWriteFileSync = mock.fn(); - - t.mock.method(utils, "defaultConfigPath", mockDefaultConfigPath); - t.mock.method(fs, "readFileSync", mockReadFileSync); - t.mock.method(fs, "rmSync", mockRmSync); - t.mock.method(fs, "writeFileSync", mockWriteFileSync); - - const result = await TelemetryConfig.fromDefaultConfig(); - - assert.equal(mockDefaultConfigPath.mock.calls.length > 0, true); - assert.deepEqual(mockReadFileSync.mock.calls[0].arguments, [ - mockConfigPath, - "utf-8", - ]); - assert.equal(mockRmSync.mock.calls.length, 1); - assert.deepEqual(mockRmSync.mock.calls[0].arguments, [ - mockConfigPath, - { - force: true, - }, - ]); - - assert.equal(mockWriteFileSync.mock.calls.length, 1); - - assert.deepEqual( - mockWriteFileSync.mock.calls[0].arguments[0], - mockConfigPath - ); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- types are wrong? - const parsedSecondArg = JSON.parse( - mockWriteFileSync.mock.calls[0].arguments[1] - ); - assert.deepEqual(parsedSecondArg.telemetry_enabled, true); - assert.deepEqual(typeof parsedSecondArg.telemetry_id, "string"); - assert.deepEqual(typeof parsedSecondArg.telemetry_salt, "string"); - - assert.equal(result instanceof TelemetryConfig, true); - assert.equal(typeof result?.id, "string"); - assert.equal(result?.config.telemetry_enabled, true); - }); - - it("should not throw if default config is missing a key", async (t) => { - const mockConfigPath = "/path/to/defaultConfig.json"; - const id = "654321"; - const mockFileContent = JSON.stringify({ - // missing telemetry_enabled - telemetry_id: id, - telemetry_salt: "default-salt", - }); - const mockRmSync = mock.fn(); - const mockWriteFileSync = mock.fn(); - - const mockDefaultConfigPath = mock.fn(() => mockConfigPath); - const mockReadFileSync = mock.fn(() => mockFileContent); - - t.mock.method(utils, "defaultConfigPath", mockDefaultConfigPath); - t.mock.method(fs, "readFileSync", mockReadFileSync); - t.mock.method(fs, "rmSync", mockRmSync); - t.mock.method(fs, "writeFileSync", mockWriteFileSync); - - const result = await TelemetryConfig.fromDefaultConfig(); - - assert.equal(mockDefaultConfigPath.mock.calls.length, 1); - assert.deepEqual(mockReadFileSync.mock.calls[0].arguments, [ - mockConfigPath, - "utf-8", - ]); - assert.equal(mockRmSync.mock.calls.length, 1); - assert.deepEqual(mockRmSync.mock.calls[0].arguments, [ - mockConfigPath, - { - force: true, - }, - ]); - assert.equal(mockWriteFileSync.mock.calls.length, 1); - assert.deepEqual( - mockWriteFileSync.mock.calls[0].arguments[0], - mockConfigPath - ); - assert.equal( - typeof mockWriteFileSync.mock.calls[0].arguments[1], - "string" - ); - - assert.equal(result instanceof TelemetryConfig, true); - assert.equal(typeof result?.id, "string"); - // this shouldn't match because we threw away the file and made a new one - assert.notEqual(result?.id, id); - assert.equal(result?.config.telemetry_enabled, true); - }); - - it("should not throw if default config has a key of the wrong type", async (t) => { - const mockConfigPath = "/path/to/defaultConfig.json"; - const salt = "default-salt"; - const mockFileContent = JSON.stringify({ - telemetry_enabled: true, - // telemetry_id should be a string - telemetry_id: true, - telemetry_salt: salt, - }); - const mockRmSync = mock.fn(); - const mockWriteFileSync = mock.fn(); - - const mockDefaultConfigPath = mock.fn(() => mockConfigPath); - const mockReadFileSync = mock.fn(() => mockFileContent); - - t.mock.method(utils, "defaultConfigPath", mockDefaultConfigPath); - t.mock.method(fs, "readFileSync", mockReadFileSync); - t.mock.method(fs, "rmSync", mockRmSync); - t.mock.method(fs, "writeFileSync", mockWriteFileSync); - - const result = await TelemetryConfig.fromDefaultConfig(); - - assert.equal(mockDefaultConfigPath.mock.calls.length, 1); - assert.deepEqual(mockReadFileSync.mock.calls[0].arguments, [ - mockConfigPath, - "utf-8", - ]); - assert.equal(mockRmSync.mock.calls.length, 1); - assert.deepEqual(mockRmSync.mock.calls[0].arguments, [ - mockConfigPath, - { - force: true, - }, - ]); - assert.equal(mockWriteFileSync.mock.calls.length, 1); - assert.equal( - mockWriteFileSync.mock.calls[0].arguments[0], - mockConfigPath - ); - assert.equal( - typeof mockWriteFileSync.mock.calls[0].arguments[1], - "string" - ); - assert.equal(result instanceof TelemetryConfig, true); - assert.equal(typeof result?.id, "string"); - // this shouldn't match because we threw away the file and made a new one - assert.notEqual(result?.config.telemetry_salt, salt); - assert.equal(result?.config.telemetry_enabled, true); - }); - }); - - describe("write", () => { - it("should write the config to the file", (t) => { - const mockWriteFileSync = mock.fn(); - t.mock.method(fs, "writeFileSync", mockWriteFileSync); - - const mockJson = JSON.stringify(telemetryConfig.config, null, 2); - telemetryConfig.tryWrite(); - - assert.deepEqual(mockWriteFileSync.mock.calls[0].arguments, [ - "/path/to/config.json", - mockJson, - ]); - }); - - it("should not throw if write fails", (t) => { - const mockWriteFileSync = t.mock.method(fs, "writeFileSync", () => { - throw new Error("Write error"); - }); - - const mockJson = JSON.stringify(telemetryConfig.config, null, 2); - // this shouldn't throw - telemetryConfig.tryWrite(); - assert.deepStrictEqual(mockWriteFileSync.mock.calls[0].arguments, [ - "/path/to/config.json", - mockJson, - ]); - }); - }); - - describe("hasSeenAlert", () => { - it("should return true if telemetry_alerted is defined", () => { - telemetryConfig = new TelemetryConfig({ - configPath: "/path/to/config.json", - config: { - telemetry_enabled: true, - telemetry_id: "123456", - telemetry_salt: "private-salt", - telemetry_alerted: new Date().toISOString(), - }, - }); - - const result = telemetryConfig.hasSeenAlert(); - - assert.equal(result, true); - }); - - it("should return false if telemetry_alerted key exists but is undefined", () => { - telemetryConfig = new TelemetryConfig({ - configPath: "/path/to/config.json", - config: { - telemetry_enabled: true, - telemetry_id: "123456", - telemetry_salt: "private-salt", - telemetry_alerted: undefined, - }, - }); - const result = telemetryConfig.hasSeenAlert(); - - assert.equal(result, false); - }); - - it("should return false if telemetry_alerted is undefined", () => { - const result = telemetryConfig.hasSeenAlert(); - - assert.equal(result, false); - }); - }); - - describe("isEnabled", () => { - const testCases = [ - { envVar: "DO_NOT_TRACK", value: "1", expectedResult: false }, - { envVar: "DO_NOT_TRACK", value: "true", expectedResult: false }, - { envVar: "TURBO_TELEMETRY_DISABLED", value: "1", expectedResult: false }, - { - envVar: "TURBO_TELEMETRY_DISABLED", - value: "true", - expectedResult: false, - }, - { envVar: null, value: null, expectedResult: true }, - ]; - for (const { envVar, value, expectedResult } of testCases) { - it(`should return ${expectedResult} when ${envVar} is set to '${value}'`, () => { - const config = new TelemetryConfig({ - configPath: "/path/to/config.json", - config: { - telemetry_enabled: true, - telemetry_id: "123456", - telemetry_salt: "private-salt", - }, - }); - - if (envVar) { - process.env[envVar] = value; - } - - const result = config.isEnabled(); - assert.equal(result, expectedResult); - }); - } - }); - - describe("isTelemetryWarningEnabled", () => { - it("should return false if TURBO_TELEMETRY_MESSAGE_DISABLED is set to '1'", () => { - process.env.TURBO_TELEMETRY_MESSAGE_DISABLED = "1"; - - const result = telemetryConfig.isTelemetryWarningEnabled(); - - assert.equal(result, false); - }); - - it("should return false if TURBO_TELEMETRY_MESSAGE_DISABLED is set to 'true'", () => { - process.env.TURBO_TELEMETRY_MESSAGE_DISABLED = "true"; - - const result = telemetryConfig.isTelemetryWarningEnabled(); - - assert.equal(result, false); - }); - - it("should return true if TURBO_TELEMETRY_MESSAGE_DISABLED is not set", () => { - const result = telemetryConfig.isTelemetryWarningEnabled(); - - assert.equal(result, true); - }); - }); - - describe("showAlert", () => { - it("should log the telemetry alert if conditions are met", (t) => { - const mockLog = t.mock.method(console, "log"); - telemetryConfig.showAlert(); - assert.equal(mockLog.mock.calls.length, 6); - }); - - it("should not log the telemetry alert if conditions are not met", (t) => { - const mockLog = t.mock.method(console, "log"); - - telemetryConfig = new TelemetryConfig({ - configPath: "/path/to/config.json", - config: { - telemetry_enabled: false, - telemetry_id: "123456", - telemetry_salt: "private-salt", - }, - }); - - telemetryConfig.showAlert(); - - assert.deepEqual(mockLog.mock.calls.length, 0); - }); - }); - - describe("enable", () => { - it("should set telemetry_enabled to true and write the config", (t) => { - const mockWriteFileSync = t.mock.method(fs, "writeFileSync"); - - telemetryConfig.enable(); - assert.equal(telemetryConfig.isEnabled(), true); - assert.equal(mockWriteFileSync.mock.calls.length, 1); - assert.deepStrictEqual(mockWriteFileSync.mock.calls[0].arguments, [ - "/path/to/config.json", - JSON.stringify(telemetryConfig.config, null, 2), - ]); - }); - }); - - describe("disable", () => { - it("should set telemetry_enabled to false and write the config", (t) => { - const mockWriteFileSync = t.mock.method(fs, "writeFileSync"); - telemetryConfig.disable(); - - assert.equal(telemetryConfig.isEnabled(), false); - assert.equal(mockWriteFileSync.mock.calls.length, 1); - assert.deepStrictEqual(mockWriteFileSync.mock.calls[0].arguments, [ - "/path/to/config.json", - JSON.stringify(telemetryConfig.config, null, 2), - ]); - }); - }); - - describe("alertShown", () => { - it("should return true if telemetry_alerted is defined", () => { - telemetryConfig = new TelemetryConfig({ - configPath: "/path/to/config.json", - config: { - telemetry_enabled: true, - telemetry_id: "123456", - telemetry_salt: "private-salt", - telemetry_alerted: new Date().toISOString(), - }, - }); - - const result = telemetryConfig.alertShown(); - - assert.equal(result, true); - }); - - it("should set telemetry_alerted to current date and write the config if telemetry_alerted is undefined", (t) => { - const mockWriteFileSync = mock.fn(); - t.mock.method(fs, "writeFileSync", mockWriteFileSync); - const result = telemetryConfig.alertShown(); - - assert.equal(result, true); - assert.equal(telemetryConfig.hasSeenAlert(), true); - assert.equal(mockWriteFileSync.mock.calls.length, 1); - assert.deepEqual(mockWriteFileSync.mock.calls[0].arguments, [ - "/path/to/config.json", - JSON.stringify(telemetryConfig.config, null, 2), - ]); - }); - }); - - describe("oneWayHash", () => { - it("should call oneWayHashWithSalt with the input and telemetry_salt from the config", (t) => { - const mockOneWayHashWithSalt = mock.fn(() => "hashed-value"); - t.mock.method(utils, "oneWayHashWithSalt", mockOneWayHashWithSalt); - - const result = telemetryConfig.oneWayHash("input-value"); - assert.deepEqual(mockOneWayHashWithSalt.mock.calls[0].arguments, [ - { - input: "input-value", - salt: "private-salt", - }, - ]); - assert.equal(result, "hashed-value"); - }); - }); - - describe("isDebug", () => { - it("should return true if TURBO_TELEMETRY_DEBUG is set to '1'", () => { - process.env.TURBO_TELEMETRY_DEBUG = "1"; - - const result = TelemetryConfig.isDebug(); - - assert.equal(result, true); - }); - - it("should return true if TURBO_TELEMETRY_DEBUG is set to 'true'", () => { - process.env.TURBO_TELEMETRY_DEBUG = "true"; - - const result = TelemetryConfig.isDebug(); - - assert.equal(result, true); - }); - - it("should return false if TURBO_TELEMETRY_DEBUG is not set", () => { - const result = TelemetryConfig.isDebug(); - - assert.equal(result, false); - }); - }); -}); diff --git a/packages/turbo-telemetry/src/utils.test.ts b/packages/turbo-telemetry/src/utils.test.ts deleted file mode 100644 index 81d4861beb842..0000000000000 --- a/packages/turbo-telemetry/src/utils.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { describe, it } from "node:test"; -import { strict as assert } from "node:assert"; -import utils from "./utils"; - -describe("utils", () => { - describe("oneWayHashWithSalt", () => { - it("should return the hashed value with salt", () => { - const input = "a-sensitive-value"; - const salt = "private-salt"; - - const result = utils.oneWayHashWithSalt({ input, salt }); - assert.equal( - result, - "568d39ba8435f9c37e80e01c6bb6e27d7b65b4edf837e44dee662ffc99206eec" - ); - }); - - it("should return consistent length", () => { - const input = "a-sensitive-value"; - const salt = "private-salt"; - - const result1 = utils.oneWayHashWithSalt({ input, salt }); - const result2 = utils.oneWayHashWithSalt({ - input: `${input}-${input}`, - salt, - }); - - assert.equal(result1.length, result2.length); - }); - }); - - describe("defaultConfigPath", () => { - it("supports overriding by env var", async () => { - process.env.TURBO_CONFIG_DIR_PATH = "/tmp"; - const result = await utils.defaultConfigPath(); - assert.equal(result, "/tmp/turborepo/telemetry.json"); - }); - }); -}); diff --git a/packages/turbo-test-utils/.eslintrc.js b/packages/turbo-test-utils/.eslintrc.js deleted file mode 100644 index 4ca761e2f8eb5..0000000000000 --- a/packages/turbo-test-utils/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], -}; diff --git a/packages/turbo-test-utils/README.md b/packages/turbo-test-utils/README.md deleted file mode 100644 index a237ccbad6a29..0000000000000 --- a/packages/turbo-test-utils/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/test-utils` - -Internal package of generic testing utilities shared between [turborepo/packages/](https://github.com/vercel/turborepo/tree/main/packages) diff --git a/packages/turbo-test-utils/src/index.ts b/packages/turbo-test-utils/Source/index.ts similarity index 100% rename from packages/turbo-test-utils/src/index.ts rename to packages/turbo-test-utils/Source/index.ts diff --git a/packages/turbo-test-utils/src/mockEnv.ts b/packages/turbo-test-utils/Source/mockEnv.ts similarity index 100% rename from packages/turbo-test-utils/src/mockEnv.ts rename to packages/turbo-test-utils/Source/mockEnv.ts diff --git a/packages/turbo-test-utils/src/spyConsole.ts b/packages/turbo-test-utils/Source/spyConsole.ts similarity index 100% rename from packages/turbo-test-utils/src/spyConsole.ts rename to packages/turbo-test-utils/Source/spyConsole.ts diff --git a/packages/turbo-test-utils/src/spyExit.ts b/packages/turbo-test-utils/Source/spyExit.ts similarity index 100% rename from packages/turbo-test-utils/src/spyExit.ts rename to packages/turbo-test-utils/Source/spyExit.ts diff --git a/packages/turbo-test-utils/src/useFixtures.ts b/packages/turbo-test-utils/Source/useFixtures.ts similarity index 100% rename from packages/turbo-test-utils/src/useFixtures.ts rename to packages/turbo-test-utils/Source/useFixtures.ts diff --git a/packages/turbo-test-utils/src/validateLogs.ts b/packages/turbo-test-utils/Source/validateLogs.ts similarity index 100% rename from packages/turbo-test-utils/src/validateLogs.ts rename to packages/turbo-test-utils/Source/validateLogs.ts diff --git a/packages/turbo-test-utils/package.json b/packages/turbo-test-utils/package.json index 1c47fd672f639..b4e7d31df9368 100644 --- a/packages/turbo-test-utils/package.json +++ b/packages/turbo-test-utils/package.json @@ -1,41 +1,20 @@ { - "name": "@turbo/test-utils", - "version": "0.0.0", - "private": true, - "description": "", - "homepage": "https://turbo.build/repo", - "keywords": [], - "author": "Vercel", - "main": "src/index.ts", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/vercel/turborepo", - "directory": "packages/turbo-test-utils" - }, - "bugs": { - "url": "https://github.com/vercel/turborepo/issues" - }, - "scripts": { - "lint": "eslint src/", - "check-types": "tsc --noEmit", - "lint:prettier": "prettier -c . --cache --ignore-path=../../.prettier-ignore" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@turbo/eslint-config": "workspace:*", - "@turbo/tsconfig": "workspace:*", - "@types/fs-extra": "^9.0.13", - "@types/js-yaml": "^4.0.5", - "@types/node": "^18.17.2", - "jest": "^29.7.0", - "jest-mock": "^29.7.0", - "ts-jest": "^29.2.5", - "typescript": "5.5.4" - }, - "dependencies": { - "fs-extra": "^11.1.0", - "js-yaml": "^4.1.0", - "json5": "^2.2.3" - } + "name": "@turbo/test-utils", + "description": "", + "main": "src/index.ts", + "scripts": { + "check-types": "tsc --noEmit" + }, + "dependencies": { + "fs-extra": "11.3.0", + "js-yaml": "4.1.0", + "json5": "2.2.3" + }, + "devDependencies": { + "@turbo/eslint-config": "workspace:*", + "@turbo/tsconfig": "workspace:*", + "@types/fs-extra": "11.0.4", + "@types/js-yaml": "4.0.9", + "@types/node": "22.13.1" + } } diff --git a/packages/turbo-tracing-next-plugin/Source/index.ts b/packages/turbo-tracing-next-plugin/Source/index.ts new file mode 100644 index 0000000000000..0b75113b46343 --- /dev/null +++ b/packages/turbo-tracing-next-plugin/Source/index.ts @@ -0,0 +1,27 @@ +import { + NodeModuleTracePlugin, + NodeModuleTracePluginOptions, +} from "@vercel/webpack-nft"; +import type { NextConfig } from "next"; + +export function createNodeFileTrace(options?: NodeModuleTracePluginOptions) { + return function withNodeFileTrace(config: NextConfig = {}) { + const createWebpackConfig = config.webpack; + config.outputFileTracing = false; + config.webpack = (webpackConfig, context) => { + const config = + createWebpackConfig?.(webpackConfig, context) ?? webpackConfig; + if (context.isServer && !context.dev) { + const plugin = new NodeModuleTracePlugin(options); + if (config.plugins) { + config.plugins.push(plugin); + } else { + config.plugins = [plugin]; + } + } + + return config; + }; + return config; + }; +} diff --git a/packages/turbo-tracing-next-plugin/package.json b/packages/turbo-tracing-next-plugin/package.json new file mode 100644 index 0000000000000..b57cdb79366e7 --- /dev/null +++ b/packages/turbo-tracing-next-plugin/package.json @@ -0,0 +1,16 @@ +{ + "name": "@vercel/experimental-nft-next-plugin", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*" + ], + "scripts": {}, + "dependencies": { + "@vercel/webpack-nft": "workspace:*" + }, + "devDependencies": { + "@turbo/eslint-config": "workspace:*", + "next": "15.1.7" + } +} diff --git a/packages/turbo-tracing-next-plugin/tsconfig.json b/packages/turbo-tracing-next-plugin/tsconfig.json new file mode 100644 index 0000000000000..18316acfb61a9 --- /dev/null +++ b/packages/turbo-tracing-next-plugin/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src"], + "references": [ + { + "path": "../webpack-nmt" + } + ] +} diff --git a/packages/turbo-types/.eslintrc.js b/packages/turbo-types/.eslintrc.js deleted file mode 100644 index 4ca761e2f8eb5..0000000000000 --- a/packages/turbo-types/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], -}; diff --git a/packages/turbo-types/.prettierignore b/packages/turbo-types/.prettierignore deleted file mode 100644 index 36a114ebb3b74..0000000000000 --- a/packages/turbo-types/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -schemas diff --git a/packages/turbo-types/README.md b/packages/turbo-types/README.md deleted file mode 100644 index 0f99e6d13898b..0000000000000 --- a/packages/turbo-types/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# `@turbo/types` - -TypeScript types for `turbo.json` - ---- - -For more information about Turborepo, visit [turbo.build/repo](https://turbo.build/repo) and follow us on X ([@turborepo](https://x.com/turborepo))! diff --git a/packages/turbo-types/src/index.ts b/packages/turbo-types/Source/index.ts similarity index 100% rename from packages/turbo-types/src/index.ts rename to packages/turbo-types/Source/index.ts diff --git a/packages/turbo-types/src/json/frameworks.json b/packages/turbo-types/Source/json/frameworks.json similarity index 100% rename from packages/turbo-types/src/json/frameworks.json rename to packages/turbo-types/Source/json/frameworks.json diff --git a/packages/turbo-types/Source/scripts/codegen.js b/packages/turbo-types/Source/scripts/codegen.js new file mode 100644 index 0000000000000..2f0eff6e6d1dc --- /dev/null +++ b/packages/turbo-types/Source/scripts/codegen.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node + +const fs = require("node:fs"); +const path = require("node:path"); +const tsj = require("ts-json-schema-generator"); + +/** @type {import('ts-json-schema-generator/dist/src/Config').Config} */ +const config = { + path: path.join(__dirname, "../index.ts"), + tsconfig: path.join(__dirname, "../../tsconfig.json"), + type: "Schema", + minify: true, +}; + +const outputPath = process.argv[2]; +if (!outputPath) { + throw new Error("Missing output path"); +} +const schema = tsj.createGenerator(config).createSchema(config.type); +fs.writeFile(outputPath, JSON.stringify(schema), (err) => { + if (err) throw err; +}); diff --git a/packages/turbo-types/src/types/config-v1.ts b/packages/turbo-types/Source/types/config-v1.ts similarity index 100% rename from packages/turbo-types/src/types/config-v1.ts rename to packages/turbo-types/Source/types/config-v1.ts diff --git a/packages/turbo-types/src/types/config-v2.ts b/packages/turbo-types/Source/types/config-v2.ts similarity index 100% rename from packages/turbo-types/src/types/config-v2.ts rename to packages/turbo-types/Source/types/config-v2.ts diff --git a/packages/turbo-types/Source/types/config.ts b/packages/turbo-types/Source/types/config.ts new file mode 100644 index 0000000000000..3c8aa1a553414 --- /dev/null +++ b/packages/turbo-types/Source/types/config.ts @@ -0,0 +1,303 @@ +/* This file generates the `schema.json` file. */ +export type Schema = RootSchema | WorkspaceSchema; + +/* Used to support codemods that target turbo 1 */ +export type LegacySchema = LegacyRootSchema | LegacyWorkspaceSchema; + +export type SchemaV1 = RootSchemaV1 | WorkspaceSchemaV1; + +export interface BaseSchema { + /** @defaultValue https://turbo.build/schema.json */ + $schema?: string; + /** + * An object representing the task dependency graph of your project. turbo interprets + * these conventions to schedule, execute, and cache the outputs of tasks in + * your project. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#tasks + * + * @defaultValue `{}` + */ + // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style -- it's more readable to specify a name for the key + tasks: { + /** + * The name of a task that can be executed by turbo. If turbo finds a workspace + * package with a package.json scripts object with a matching key, it will apply the + * pipeline task configuration to that npm script during execution. + */ + [script: string]: Pipeline; + }; +} + +export interface BaseSchemaV1 { + // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style -- it's more readable to specify a name for the key + pipeline: { + [script: string]: Pipeline; + }; +} + +export type LegacyBaseSchema = BaseSchema | BaseSchemaV1; + +export interface WorkspaceSchema extends BaseSchema { + /** + * This key is only available in Workspace Configs + * and cannot be used in your root turbo.json. + * + * Tells turbo to extend your root `turbo.json` + * and overrides with the keys provided + * in your Workspace Configs. + * + * Currently, only the "//" value is allowed. + * + * @defaultValue ["//"] + */ + extends: Array; +} + +export type LegacyWorkspaceSchema = WorkspaceSchema & LegacyBaseSchema; + +export type WorkspaceSchemaV1 = Omit & BaseSchemaV1; + +export interface RootSchema extends BaseSchema { + /** + * A list of globs to include in the set of implicit global hash dependencies. + * + * The contents of these files will be included in the global hashing + * algorithm and affect the hashes of all tasks. + * + * This is useful for busting the cache based on: + * + * - .env files (not in Git) + * + * - any root level file that impacts package tasks + * that are not represented in the traditional dependency graph + * (e.g. a root tsconfig.json, jest.config.js, .eslintrc, etc.) + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#globaldependencies + * + * @defaultValue [] + */ + globalDependencies?: Array; + + /** + * A list of environment variables for implicit global hash dependencies. + * + * The variables included in this list will affect all task hashes. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#globalenv + * + * @defaultValue [] + */ + globalEnv?: Array; + + /** + * An allowlist of environment variables that should be made to all tasks, but + * should not contribute to the task's cache key, e.g. `AWS_SECRET_KEY`. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#globalpassthroughenv + * + * @defaultValue null + */ + globalPassThroughEnv?: null | Array; + + /** + * A priority-ordered (most-significant to least-significant) array of project-anchored + * Unix-style paths to `.env` files to include in the global hash. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#globalDotEnv + * + * @defaultValue null + */ + globalDotEnv?: null | Array; + + /** + * Configuration options that control how turbo interfaces with the remote cache. + * + * Documentation: https://turbo.build/repo/docs/core-concepts/remote-caching + * + * @defaultValue `{}` + */ + remoteCache?: RemoteCache; + + /** + * Enable use of the UI for `turbo`. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#ui + * + * @defaultValue `"tui"` + */ + ui?: UI; +} + +export type LegacyRootSchema = RootSchema & LegacyBaseSchema; + +export type RootSchemaV1 = Omit & BaseSchemaV1; + +export interface Pipeline { + /** + * The list of tasks that this task depends on. + * + * Prefixing an item in dependsOn with a ^ prefix tells turbo that this task depends + * on the package's topological dependencies completing the task first. + * (e.g. "A package's build tasks should only run once all of its workspace dependencies + * have completed their own build commands.") + * + * Items in dependsOn without a ^ prefix express the relationships between tasks within the + * same package (e.g. "A package's test and lint commands depend on its own build being + * completed first.") + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#dependson + * + * @defaultValue [] + */ + dependsOn?: Array; + + /** + * A list of environment variables that this task depends on. + * + * Note: If you are migrating from a turbo version 1.5 or below, + * you may be used to prefixing your variables with a $. + * You no longer need to use the $ prefix. + * (e.g. $GITHUB_TOKEN → GITHUB_TOKEN) + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#env + * + * @defaultValue [] + */ + env?: Array; + + /** + * An allowlist of environment variables that should be made available in this + * task's environment, but should not contribute to the task's cache key, + * e.g. `AWS_SECRET_KEY`. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#passthroughenv + * + * @defaultValue null + */ + passThroughEnv?: null | Array; + + /** + * A priority-ordered (most-significant to least-significant) array of workspace-anchored + * Unix-style paths to `.env` files to include in the task hash. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#dotEnv + * + * @defaultValue null + */ + dotEnv?: null | Array; + + /** + * The set of glob patterns indicating a task's cacheable filesystem outputs. + * + * Turborepo captures task logs for all tasks. This enables us to cache tasks whose runs + * produce no artifacts other than logs (such as linters). Logs are always treated as a + * cacheable artifact and never need to be specified. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#outputs + * + * @defaultValue [] + */ + outputs?: Array; + + /** + * Whether or not to cache the outputs of the task. + * + * Setting cache to false is useful for long-running "watch" or development mode tasks. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#cache + * + * @defaultValue true + */ + cache?: boolean; + + /** + * The set of glob patterns to consider as inputs to this task. + * + * Changes to files covered by these globs will cause a cache miss and + * the task will be rerun. + * + * If a file has been changed that is **not** included in the set of globs, + * it will not cause a cache miss. + * + * If omitted or empty, all files in the package are considered as inputs. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#inputs + * + * @defaultValue [] + */ + inputs?: Array; + + /** + * Output mode for the task. + * + * "full": Displays all output + * + * "hash-only": Show only the hashes of the tasks + * + * "new-only": Only show output from cache misses + * + * "errors-only": Only show output from task failures + * + * "none": Hides all task output + * + * Documentation: https://turbo.build/repo/docs/reference/run#--output-logs-option + * + * @defaultValue full + */ + outputLogs?: OutputMode; + + /** + * Indicates whether the task exits or not. Setting `persistent` to `true` tells + * turbo that this is a long-running task and will ensure that other tasks + * cannot depend on it. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#persistent + * + * @defaultValue false + */ + persistent?: boolean; + + /** + * Mark a task as interactive allowing it to receive input from stdin. + * Interactive tasks must be marked with "cache": false as the input + * they receive from stdin can change the outcome of the task. + * + * Documentation: https://turbo.build/repo/docs/reference/configuration#interactive + */ + interactive?: boolean; +} + +export interface RemoteCache { + /** + * Indicates if signature verification is enabled for requests to the remote cache. When + * `true`, Turborepo will sign every uploaded artifact using the value of the environment + * variable `TURBO_REMOTE_CACHE_SIGNATURE_KEY`. Turborepo will reject any downloaded artifacts + * that have an invalid signature or are missing a signature. + * + * @defaultValue false + */ + signature?: boolean; + + /** + * Indicates if the remote cache is enabled. When `false`, Turborepo will disable + * all remote cache operations, even if the repo has a valid token. If true, remote caching + * is enabled, but still requires the user to login and link their repo to a remote cache. + * Documentation: https://turbo.build/repo/docs/core-concepts/remote-caching + * + * @defaultValue true + */ + enabled?: boolean; +} + +export type OutputMode = + | "full" + | "hash-only" + | "new-only" + | "errors-only" + | "none"; + +export type UI = "tui" | "stream"; + +export type AnchoredUnixPath = string; +export type EnvWildcard = string; diff --git a/packages/turbo-types/src/types/dry.ts b/packages/turbo-types/Source/types/dry.ts similarity index 100% rename from packages/turbo-types/src/types/dry.ts rename to packages/turbo-types/Source/types/dry.ts diff --git a/packages/turbo-types/src/types/frameworks.ts b/packages/turbo-types/Source/types/frameworks.ts similarity index 100% rename from packages/turbo-types/src/types/frameworks.ts rename to packages/turbo-types/Source/types/frameworks.ts diff --git a/packages/turbo-types/package.json b/packages/turbo-types/package.json index 69a85b3c96d58..25aca881007aa 100644 --- a/packages/turbo-types/package.json +++ b/packages/turbo-types/package.json @@ -24,9 +24,9 @@ "devDependencies": { "@turbo/eslint-config": "workspace:*", "@turbo/tsconfig": "workspace:*", - "@types/node": "^20", + "@types/node": "22", "ts-json-schema-generator": "2.3.0", - "tsx": "4.19.1" + "tsx": "4.19.2" }, "files": [ "src", diff --git a/packages/turbo-utils/.eslintrc.js b/packages/turbo-utils/.eslintrc.js deleted file mode 100644 index 4ca761e2f8eb5..0000000000000 --- a/packages/turbo-utils/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@turbo/eslint-config/library"], -}; diff --git a/packages/turbo-utils/README.md b/packages/turbo-utils/README.md deleted file mode 100644 index 3a6f7848bf209..0000000000000 --- a/packages/turbo-utils/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/utils` - -Internal package of generic utilities shared between [turborepo/packages/](https://github.com/vercel/turborepo/tree/main/packages) diff --git a/packages/turbo-utils/src/convertCase.ts b/packages/turbo-utils/Source/convertCase.ts similarity index 100% rename from packages/turbo-utils/src/convertCase.ts rename to packages/turbo-utils/Source/convertCase.ts diff --git a/packages/turbo-utils/src/createProject.ts b/packages/turbo-utils/Source/createProject.ts similarity index 100% rename from packages/turbo-utils/src/createProject.ts rename to packages/turbo-utils/Source/createProject.ts diff --git a/packages/turbo-utils/src/examples.ts b/packages/turbo-utils/Source/examples.ts similarity index 100% rename from packages/turbo-utils/src/examples.ts rename to packages/turbo-utils/Source/examples.ts diff --git a/packages/turbo-utils/src/getTurboConfigs.ts b/packages/turbo-utils/Source/getTurboConfigs.ts similarity index 100% rename from packages/turbo-utils/src/getTurboConfigs.ts rename to packages/turbo-utils/Source/getTurboConfigs.ts diff --git a/packages/turbo-utils/src/getTurboRoot.ts b/packages/turbo-utils/Source/getTurboRoot.ts similarity index 100% rename from packages/turbo-utils/src/getTurboRoot.ts rename to packages/turbo-utils/Source/getTurboRoot.ts diff --git a/packages/turbo-utils/src/index.ts b/packages/turbo-utils/Source/index.ts similarity index 100% rename from packages/turbo-utils/src/index.ts rename to packages/turbo-utils/Source/index.ts diff --git a/packages/turbo-utils/src/isFolderEmpty.ts b/packages/turbo-utils/Source/isFolderEmpty.ts similarity index 100% rename from packages/turbo-utils/src/isFolderEmpty.ts rename to packages/turbo-utils/Source/isFolderEmpty.ts diff --git a/packages/turbo-utils/src/isWriteable.ts b/packages/turbo-utils/Source/isWriteable.ts similarity index 100% rename from packages/turbo-utils/src/isWriteable.ts rename to packages/turbo-utils/Source/isWriteable.ts diff --git a/packages/turbo-utils/src/logger.ts b/packages/turbo-utils/Source/logger.ts similarity index 100% rename from packages/turbo-utils/src/logger.ts rename to packages/turbo-utils/Source/logger.ts diff --git a/packages/turbo-utils/src/managers.ts b/packages/turbo-utils/Source/managers.ts similarity index 100% rename from packages/turbo-utils/src/managers.ts rename to packages/turbo-utils/Source/managers.ts diff --git a/packages/turbo-utils/src/searchUp.ts b/packages/turbo-utils/Source/searchUp.ts similarity index 100% rename from packages/turbo-utils/src/searchUp.ts rename to packages/turbo-utils/Source/searchUp.ts diff --git a/packages/turbo-utils/src/types.ts b/packages/turbo-utils/Source/types.ts similarity index 100% rename from packages/turbo-utils/src/types.ts rename to packages/turbo-utils/Source/types.ts diff --git a/packages/turbo-utils/src/validateDirectory.ts b/packages/turbo-utils/Source/validateDirectory.ts similarity index 100% rename from packages/turbo-utils/src/validateDirectory.ts rename to packages/turbo-utils/Source/validateDirectory.ts diff --git a/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/docs/package.json b/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/docs/package.json index 82f9a44736f00..a95984fb3f175 100644 --- a/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/docs/package.json +++ b/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/docs/package.json @@ -1,4 +1,5 @@ { - "name": "docs", - "version": "1.0.0" + "name": "docs", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/web/package.json b/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/web/package.json index d8a83edbd32a1..6dc872312103a 100644 --- a/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/web/package.json +++ b/packages/turbo-utils/__fixtures__/common/old-workspace-config/apps/web/package.json @@ -1,4 +1,5 @@ { - "name": "web", - "version": "1.0.0" + "name": "web", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/old-workspace-config/package.json b/packages/turbo-utils/__fixtures__/common/old-workspace-config/package.json index 20fc040b0763e..8b137891791fe 100644 --- a/packages/turbo-utils/__fixtures__/common/old-workspace-config/package.json +++ b/packages/turbo-utils/__fixtures__/common/old-workspace-config/package.json @@ -1,16 +1 @@ -{ - "private": true, - "workspaces": { - "packages": [ - "apps/*", - "packages/*" - ] - }, - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} + diff --git a/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/ui/package.json b/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/ui/package.json index 7cb7cf17345dc..d1ba3c544165d 100644 --- a/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/ui/package.json +++ b/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/ui/package.json @@ -1,4 +1,5 @@ { - "name": "ui", - "version": "1.0.0" + "name": "ui", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/utils/package.json b/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/utils/package.json index 39308ba79008b..986415d8ddb08 100644 --- a/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/utils/package.json +++ b/packages/turbo-utils/__fixtures__/common/old-workspace-config/packages/utils/package.json @@ -1,4 +1,5 @@ { - "name": "utils", - "version": "1.0.0" + "name": "utils", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/single-package/package.json b/packages/turbo-utils/__fixtures__/common/single-package/package.json index b2a09270488e6..9670a548d0b47 100644 --- a/packages/turbo-utils/__fixtures__/common/single-package/package.json +++ b/packages/turbo-utils/__fixtures__/common/single-package/package.json @@ -1,3 +1,5 @@ { - "name": "single-package" + "name": "single-package", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/docs/package.json b/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/docs/package.json index 82f9a44736f00..a95984fb3f175 100644 --- a/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/docs/package.json +++ b/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/docs/package.json @@ -1,4 +1,5 @@ { - "name": "docs", - "version": "1.0.0" + "name": "docs", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/web/package.json b/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/web/package.json index d8a83edbd32a1..6dc872312103a 100644 --- a/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/web/package.json +++ b/packages/turbo-utils/__fixtures__/common/workspace-configs/apps/web/package.json @@ -1,4 +1,5 @@ { - "name": "web", - "version": "1.0.0" + "name": "web", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/workspace-configs/package.json b/packages/turbo-utils/__fixtures__/common/workspace-configs/package.json index c6616a615d2d5..8b137891791fe 100644 --- a/packages/turbo-utils/__fixtures__/common/workspace-configs/package.json +++ b/packages/turbo-utils/__fixtures__/common/workspace-configs/package.json @@ -1,14 +1 @@ -{ - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build" - }, - "devDependencies": { - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" -} + diff --git a/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/ui/package.json b/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/ui/package.json index 7cb7cf17345dc..d1ba3c544165d 100644 --- a/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/ui/package.json +++ b/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/ui/package.json @@ -1,4 +1,5 @@ { - "name": "ui", - "version": "1.0.0" + "name": "ui", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/utils/package.json b/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/utils/package.json index 39308ba79008b..986415d8ddb08 100644 --- a/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/utils/package.json +++ b/packages/turbo-utils/__fixtures__/common/workspace-configs/packages/utils/package.json @@ -1,4 +1,5 @@ { - "name": "utils", - "version": "1.0.0" + "name": "utils", + "dependencies": {}, + "devDependencies": {} } diff --git a/packages/turbo-utils/__tests__/convertCase.test.ts b/packages/turbo-utils/__tests__/convertCase.test.ts deleted file mode 100644 index 487714ade5218..0000000000000 --- a/packages/turbo-utils/__tests__/convertCase.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { describe, it, expect } from "@jest/globals"; -import { convertCase, type CaseOptions } from "../src/convertCase"; - -interface TestCase { - input: string; - expected: string; - to: CaseOptions["to"]; -} - -describe("convertCase", () => { - const testCases: Array = [ - { input: "hello_world", expected: "helloWorld", to: "camel" }, - { input: "hello-world", expected: "helloWorld", to: "camel" }, - { input: "helloWorld", expected: "helloWorld", to: "camel" }, - { input: "helloworld", expected: "helloworld", to: "camel" }, - ]; - - it.each(testCases)( - "should convert '$input' to '$to'", - ({ input, expected, to }) => { - expect(convertCase(input, { to })).toBe(expected); - } - ); -}); diff --git a/packages/turbo-utils/__tests__/examples.test.ts b/packages/turbo-utils/__tests__/examples.test.ts deleted file mode 100644 index b607c40d6f05d..0000000000000 --- a/packages/turbo-utils/__tests__/examples.test.ts +++ /dev/null @@ -1,135 +0,0 @@ -import got from "got"; -import * as Got from "got"; -import { describe, it, expect, jest } from "@jest/globals"; -import { isUrlOk, getRepoInfo, hasRepo } from "../src/examples"; - -jest.mock("got", () => ({ - __esModule: true, - ...jest.requireActual("got"), -})); - -describe("examples", () => { - describe("isUrlOk", () => { - it("returns true if url returns 200", async () => { - const mockGot = jest - .spyOn(got, "head") - .mockReturnValue({ statusCode: 200 } as any); - - const url = "https://github.com/vercel/turborepo/"; - const result = await isUrlOk(url); - expect(result).toBe(true); - - expect(mockGot).toHaveBeenCalledWith(url); - mockGot.mockRestore(); - }); - - it("returns false if url returns status != 200", async () => { - const mockGot = jest - .spyOn(got, "head") - .mockReturnValue({ statusCode: 401 } as any); - - const url = "https://not-github.com/vercel/turborepo/"; - const result = await isUrlOk(url); - expect(result).toBe(false); - - expect(mockGot).toHaveBeenCalledWith(url); - mockGot.mockRestore(); - }); - }); - - describe("getRepoInfo", () => { - it.each([ - { - repoUrl: "https://github.com/vercel/turborepo/", - examplePath: undefined, - defaultBranch: "main", - expectBranchLookup: true, - expected: { - username: "vercel", - name: "turborepo", - branch: "main", - filePath: "", - }, - }, - { - repoUrl: - "https://github.com/vercel/turborepo/tree/canary/examples/kitchen-sink", - examplePath: undefined, - defaultBranch: "canary", - expectBranchLookup: false, - expected: { - username: "vercel", - name: "turborepo", - branch: "canary", - filePath: "examples/kitchen-sink", - }, - }, - { - repoUrl: "https://github.com/vercel/turborepo/tree/tek/test-branch/", - examplePath: "examples/basic", - defaultBranch: "canary", - expectBranchLookup: false, - expected: { - username: "vercel", - name: "turborepo", - branch: "tek/test-branch", - filePath: "examples/basic", - }, - }, - ])( - "retrieves repo info for $repoUrl and $examplePath", - async ({ - repoUrl, - examplePath, - defaultBranch, - expectBranchLookup, - expected, - }) => { - const mockGot = jest.spyOn(Got, "default").mockReturnValue({ - body: JSON.stringify({ default_branch: defaultBranch }), - } as any); - - const url = new URL(repoUrl); - const result = await getRepoInfo(url, examplePath); - expect(result).toMatchObject(expected); - - if (result && expectBranchLookup) { - expect(mockGot).toHaveBeenCalledWith( - `https://api.github.com/repos/${result.username}/${result.name}` - ); - } - - mockGot.mockRestore(); - } - ); - }); - - describe("hasRepo", () => { - it.each([ - { - repoInfo: { - username: "vercel", - name: "turbo", - branch: "main", - filePath: "", - }, - expected: true, - expectedUrl: - "https://api.github.com/repos/vercel/turbo/contents/package.json?ref=main", - }, - ])( - "checks repo at $expectedUrl", - async ({ expected, repoInfo, expectedUrl }) => { - const mockGot = jest - .spyOn(got, "head") - .mockReturnValue({ statusCode: 200 } as any); - - const result = await hasRepo(repoInfo); - expect(result).toBe(expected); - - expect(mockGot).toHaveBeenCalledWith(expectedUrl); - mockGot.mockRestore(); - } - ); - }); -}); diff --git a/packages/turbo-utils/__tests__/getTurboConfigs.test.ts b/packages/turbo-utils/__tests__/getTurboConfigs.test.ts deleted file mode 100644 index de4bc8a0d3885..0000000000000 --- a/packages/turbo-utils/__tests__/getTurboConfigs.test.ts +++ /dev/null @@ -1,142 +0,0 @@ -import path from "node:path"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { getTurboConfigs } from "../src/getTurboConfigs"; - -describe("getTurboConfigs", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - test: "common", - }); - - it("supports single-package repos", () => { - const { root } = useFixture({ fixture: `single-package` }); - const configs = getTurboConfigs(root); - expect(configs).toHaveLength(1); - expect(configs[0].isRootConfig).toBe(true); - expect(configs[0].config).toMatchInlineSnapshot(` - { - "$schema": "https://turbo.build/schema.json", - "globalEnv": [ - "UNORDERED", - "CI", - ], - "tasks": { - "build": { - "dependsOn": [ - "^build", - ], - }, - "deploy": { - "dependsOn": [ - "build", - "test", - "lint", - ], - "outputs": [], - }, - "lint": { - "outputs": [], - }, - "test": { - "dependsOn": [ - "build", - ], - "inputs": [ - "src/**/*.tsx", - "src/**/*.ts", - "test/**/*.ts", - "test/**/*.tsx", - ], - "outputs": [], - }, - }, - } - `); - }); - - it("supports repos using workspace configs", () => { - const { root } = useFixture({ fixture: `workspace-configs` }); - const configs = getTurboConfigs(root); - - expect(configs).toHaveLength(3); - expect(configs[0].isRootConfig).toBe(true); - expect(configs[0].config).toMatchInlineSnapshot(` - { - "$schema": "https://turbo.build/schema.json", - "globalEnv": [ - "CI", - ], - "tasks": { - "build": { - "env": [ - "ENV_1", - ], - }, - }, - } - `); - expect(configs[1].isRootConfig).toBe(false); - expect(configs[1].config).toMatchInlineSnapshot(` - { - "$schema": "https://turbo.build/schema.json", - "extends": [ - "//", - ], - "tasks": { - "build": { - "env": [ - "ENV_2", - ], - }, - }, - } - `); - - expect(configs[2].isRootConfig).toBe(false); - expect(configs[2].config).toMatchInlineSnapshot(` - { - "$schema": "https://turbo.build/schema.json", - "extends": [ - "//", - ], - "tasks": { - "build": { - "env": [ - "IS_SERVER", - ], - }, - }, - } - `); - }); - - it("supports repos with old workspace configuration format", () => { - const { root } = useFixture({ fixture: `old-workspace-config` }); - const configs = getTurboConfigs(root); - - expect(configs).toHaveLength(1); - expect(configs[0].isRootConfig).toBe(true); - expect(configs[0].config).toMatchInlineSnapshot(` - { - "$schema": "https://turbo.build/schema.json", - "globalDependencies": [ - "**/.env.*local", - ], - "tasks": { - "build": { - "outputs": [ - ".next/**", - "!.next/cache/**", - ], - }, - "dev": { - "cache": false, - "persistent": true, - }, - "lint": {}, - }, - } - `); - }); -}); diff --git a/packages/turbo-utils/__tests__/getTurboRoot.test.ts b/packages/turbo-utils/__tests__/getTurboRoot.test.ts deleted file mode 100644 index 4ff3d0631b758..0000000000000 --- a/packages/turbo-utils/__tests__/getTurboRoot.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import path from "node:path"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { getTurboRoot } from "../src/getTurboRoot"; - -describe("getTurboConfigs", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - test: "common", - }); - - it.each([[""], ["child"]])( - "finds the root in a non-monorepo (%s)", - (repoPath) => { - const { root } = useFixture({ fixture: `single-package` }); - const turboRoot = getTurboRoot(path.join(root, repoPath)); - expect(turboRoot).toEqual(root); - } - ); - - it.each([ - [""], - ["apps"], - ["apps/docs"], - ["apps/web"], - ["packages"], - ["packages/ui"], - ["not-a-real/path"], - ])("finds the root in a monorepo with workspace configs (%s)", (repoPath) => { - const { root } = useFixture({ fixture: `workspace-configs` }); - const turboRoot = getTurboRoot(path.join(root, repoPath)); - expect(turboRoot).toEqual(root); - }); -}); diff --git a/packages/turbo-utils/__tests__/isFolderEmpty.test.ts b/packages/turbo-utils/__tests__/isFolderEmpty.test.ts deleted file mode 100644 index 80e8a1c3c487d..0000000000000 --- a/packages/turbo-utils/__tests__/isFolderEmpty.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import path from "node:path"; -import fs from "fs-extra"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect } from "@jest/globals"; -import { isFolderEmpty } from "../src/isFolderEmpty"; - -describe("isFolderEmpty", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - options: { - emptyFixture: true, - }, - }); - - it("correctly identifies an empty directory", async () => { - const { root } = useFixture({ fixture: `is-folder-empty` }); - const result = isFolderEmpty(root); - expect(result.isEmpty).toEqual(true); - expect(result.conflicts).toEqual([]); - }); - - it("correctly identifies a directory with non-conflicting files", async () => { - const { root } = useFixture({ fixture: `is-folder-empty` }); - fs.writeFileSync(path.join(root, "LICENSE"), "MIT"); - const result = isFolderEmpty(root); - expect(result.isEmpty).toEqual(true); - expect(result.conflicts).toEqual([]); - }); - - it("correctly identifies a directory non-conflicting files (intelliJ)", async () => { - const { root } = useFixture({ fixture: `is-folder-empty` }); - fs.writeFileSync(path.join(root, "intellij-idea-config.iml"), "{}"); - const result = isFolderEmpty(root); - expect(result.isEmpty).toEqual(true); - expect(result.conflicts).toEqual([]); - }); - - it("correctly identifies a directory conflicting files", async () => { - const { root } = useFixture({ fixture: `is-folder-empty` }); - fs.writeFileSync(path.join(root, "README.md"), "my cool project"); - const result = isFolderEmpty(root); - expect(result.isEmpty).toEqual(false); - expect(result.conflicts).toEqual(["README.md"]); - }); -}); diff --git a/packages/turbo-utils/__tests__/isWritable.test.ts b/packages/turbo-utils/__tests__/isWritable.test.ts deleted file mode 100644 index de0b6d93f8686..0000000000000 --- a/packages/turbo-utils/__tests__/isWritable.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import path from "node:path"; -import fs from "fs-extra"; -import { setupTestFixtures } from "@turbo/test-utils"; -import { describe, it, expect, jest } from "@jest/globals"; -import { isWriteable } from "../src/isWriteable"; - -describe("isWriteable", () => { - const { useFixture } = setupTestFixtures({ - directory: path.join(__dirname, "../"), - options: { emptyFixture: true }, - }); - - it("correctly identifies a writeable directory", async () => { - const { root } = useFixture({ fixture: `is-writeable` }); - const result = await isWriteable(root); - expect(result).toEqual(true); - }); - - it("correctly identifies a non-writeable directory", async () => { - const { root } = useFixture({ fixture: `is-writeable` }); - const result = await isWriteable(path.join(root, "does-not-exist")); - expect(result).toEqual(false); - }); - - it("returns false on unexpected failure", async () => { - const { root } = useFixture({ fixture: `is-writeable` }); - const mockFsAccess = jest - .spyOn(fs, "access") - .mockRejectedValue(new Error("unknown error")); - - const result = await isWriteable(root); - expect(result).toEqual(false); - expect(mockFsAccess).toHaveBeenCalledWith(root, fs.constants.W_OK); - - mockFsAccess.mockRestore(); - }); -}); diff --git a/packages/turbo-utils/jest.config.js b/packages/turbo-utils/jest.config.js new file mode 100644 index 0000000000000..f109e6b44fa1f --- /dev/null +++ b/packages/turbo-utils/jest.config.js @@ -0,0 +1,9 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: "ts-jest/presets/js-with-ts", + testEnvironment: "node", + modulePathIgnorePatterns: ["/node_modules", "/dist"], + transformIgnorePatterns: ["/node_modules/(?!(ansi-regex)/)"], + verbose: process.env.RUNNER_DEBUG === "1", + silent: process.env.RUNNER_DEBUG !== "1", +}; diff --git a/packages/turbo-utils/package.json b/packages/turbo-utils/package.json index a28968d356eb2..e23c6eb0c6401 100644 --- a/packages/turbo-utils/package.json +++ b/packages/turbo-utils/package.json @@ -1,55 +1,35 @@ { - "name": "@turbo/utils", - "version": "0.0.0", - "private": true, - "description": "", - "homepage": "https://turbo.build/repo", - "keywords": [], - "author": "Vercel", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/vercel/turborepo", - "directory": "packages/turbo-utils" - }, - "bugs": { - "url": "https://github.com/vercel/turborepo/issues" - }, - "module": "src/index.ts", - "main": "src/index.ts", - "types": "src/index.ts", - "scripts": { - "test": "jest", - "lint": "eslint src/", - "check-types": "tsc --noEmit", - "lint:prettier": "prettier -c . --cache --ignore-path=../../.prettierignore" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@manypkg/find-root": "^1.1.0", - "@turbo/eslint-config": "workspace:*", - "@turbo/test-utils": "workspace:*", - "@turbo/tsconfig": "workspace:*", - "@turbo/types": "workspace:*", - "@types/async-retry": "^1.4.5", - "@types/fs-extra": "^9.0.13", - "@types/gradient-string": "^1.1.2", - "@types/js-yaml": "^4.0.5", - "@types/node": "^20.5.7", - "@types/tar": "^6.1.4", - "async-retry": "^1.3.3", - "execa": "5.1.1", - "fast-glob": "^3.2.12", - "fs-extra": "^11.1.1", - "got": "^11.8.6", - "gradient-string": "^2.0.0", - "jest": "^29.7.0", - "js-yaml": "^4.1.0", - "json5": "^2.2.3", - "ora": "4.1.1", - "picocolors": "1.0.1", - "tar": "6.1.13", - "ts-jest": "^29.2.5", - "typescript": "5.5.4" - } + "name": "@turbo/utils", + "description": "", + "main": "src/index.ts", + "module": "src/index.ts", + "types": "src/index.ts", + "scripts": { + "check-types": "tsc --noEmit" + }, + "dependencies": {}, + "devDependencies": { + "@manypkg/find-root": "2.2.3", + "@turbo/eslint-config": "workspace:*", + "@turbo/test-utils": "workspace:*", + "@turbo/tsconfig": "workspace:*", + "@turbo/types": "workspace:*", + "@types/async-retry": "1.4.9", + "@types/fs-extra": "11.0.4", + "@types/gradient-string": "1.1.6", + "@types/js-yaml": "4.0.9", + "@types/node": "22.13.1", + "@types/tar": "6.1.13", + "async-retry": "1.3.3", + "execa": "9.5.2", + "fast-glob": "3.3.3", + "fs-extra": "11.3.0", + "got": "14.4.6", + "gradient-string": "3.0.0", + "js-yaml": "4.1.0", + "json5": "2.2.3", + "ora": "8.2.0", + "picocolors": "1.1.1", + "tar": "7.4.3" + } } diff --git a/packages/turbo-vsc/ARCHITECTURE.md b/packages/turbo-vsc/ARCHITECTURE.md deleted file mode 100644 index 428f23e7ae064..0000000000000 --- a/packages/turbo-vsc/ARCHITECTURE.md +++ /dev/null @@ -1,155 +0,0 @@ -# Architecture - -This document attempts to give a high level overview to the extension / LSP, -which APIs it uses to achieve its feature set, and how it is structured. - -## Client - -You're here! The client is the side that runs in VSCode. It is essentially -an entry point into the LSP but there are a few other things it manages -mostly for convenience sake. - -- basic syntax highlighting for the pipeline gradient -- discovery and installation of global / local turbo -- toolbar item to enable / disable the daemon -- some editor commands - - start daemon - - stop daemon - - restart daemon - - run turbo command - - run turbo lint - -Otherwise it simply selects the correct LSP binary and runs it using vscode's -built-in LSP library, and the LSP in turn interacts with the turbo daemon to -get the information it needs to fulfil client requests. - -## Daemon - -The daemon plays a minor role in relaying important metadata about the -workspace itself back to the LSP. The general rule is the LSP can know about -packages, turbo jsons, and how to parse them, but shouldn't need to do any -inference, package manager work, etc etc. Any heavy lifting should be kept -on the daemon. - -## Server - turborepo_lsp - -This is the rust side. It imports some parts from the rest of the turbo -codebase and utilizes the daemon to query data about the repository. When -the LSP is initialized, the client sends a list of open workspaces and the -LSP opens a connection to the (hopefully running) daemon, or starts one. - -> Note that we use the `jsonc_parser` crate rather than turbo's own -> TurboJSON parsing logic for maximum flexibility. we don't care if parts -> of it are malformed, as long as we can parse the parts we need to perform -> the client's request. See the tech debt section for more. - -### Language Server Protocol - -Using the [`tower_lsp`](https://crates.io/crates/tower-lsp) crate makes LSPs -quite easy. It includes a server trait and all the message types required. We -implement the `LanguageServer` trait and the library is responsible for all -IO. All that remains is adding the relevant LSP handlers to support the -features we need, which are broken down below, and hooking it up to the -default communication mechanism: stdio. - -To begin a session, the client sends an `initialize` request. The server must -respond with the capabilities it supports, such that the client knows what -type of questions it can ask. The capacilities we support are covered in the -next sections. - -#### LanguageServer::did_open - textDocument/didOpen - -We need to respond to updates to the turbo.json file live as the user is -writing in them. Watching the FS does not cut it, as we need to give context -to the _state of the buffer_ not the _file_. The LSP has support for this. -By advertising to the client the 'text document sync' capability, the client -knows that it can send us updates about file state. We send this during -initialization and as a result the client pushes events (open and change) when -turbo json files are loaded into the buffer. - -We need to store these locally since later requests will only send the URI of -the resource they are querying. It is up to the LSP to store the current state -which we do through ropes. - -All file changes (opening or changing) trigger `handle_file_update`, which is -detailed in the next part. - -#### LanguageServer::did_change - textDocument/didChange - -Updates are treated the same. Any file changes require flushing new diagnostics -which is done in `handle_file_update`. It is in charge of a few things: - -- fetch a fresh list of packages and workspaces from the daemon (cheap) -- traverse the workspaces and parse the package name + scripts -- parse the turbo json to ensure - - all globs are valid (global and pipeline specific ones) - - all pipeline key names refer to valid tasks - - all dependOn fields are sound - -These are reported back to the client along with their line and column ranges -via the `textDocument/publishDiagnostics` LSP command and displayed on the -document. - -#### LanguageServer::completion - textDocument/completion - -If an IDE requests completion information at a particular position in the -document, this call kicks in. In VSCode, knowing that both the json LSP -and turbo LSP apply, will fire off a request to each and resolve JsonSchema -items, as well as turbo tasks. The logic for turbo is handled here. -To resolve, we get all referenced scripts in any package in the workspace, -as well as all valid `#

    + + +
    +
    +
    +
    + Turborepo +
    +
    + +
    + +
    + +
    +
    + +
    + + Turborepo logo + + + + + + + + + + +
    +
    +
    + +
    + {LINKS.map(({ title, href, description }) => ( + + {description} + + ))} +
    +